Mercurial > hg > Members > kono > nitros9-code
view 3rdparty/utils/view/view_gif.a @ 2488:00e35931156e
Updated
author | boisy |
---|---|
date | Wed, 31 Mar 2010 02:58:46 +0000 |
parents | 37fd74e6fad8 |
children |
line wrap: on
line source
* * GIF supervisor and LZW decoding stuff. * ifp1 use os9defs.d endc psect view_gif_a,0,0,0,0,0 * * GIFshowpic * * Display a GIF picture * vsect dp * These are initialized by SetGIF in view_gifset.a giftable: rmb 2 Pointer to 12k decode table gifstack: rmb 2 Pointer to 4k space for reversing codes * These are used by the actual screen output routines in view_gifpix.a gifiheight: rmb 2 Image height gifiwidth: rmb 2 image width gifinterlace: rmb 1 T=Use interlace in displaying picture. * These are all used locally. sheight rmb 2 Screen height (We use the image size instead of these). swidth rmb 2 Screen width domap rmb 1 T= Color map follows *cr rmb 1 Number bits of color resolution pixel rmb 1 Number bits per pixel background rmb 1 Background color screenset rmb 1 T= screen has been set. endsect GIFshowpic: clr screenset lbsr signature Find signature in input stream lbsr screendesc Parse the screen descriptor information tst <domap beq noglobal lbsr colormap Read and parse the colormap and set up the screen. clr <domap noglobal * * Main image processing loop * Searches the input stream for one of the following separator characters, * and acts accordingly: * 0x2c (comma) - GIF image follows * 0x21 (exclamation point) - extension block follows * 0x3b (semicolon) - end of GIF file GIFLoop lbsr I_GetByte lbcs _error cmpa #$3b semicolon marks the end of the file beq GIFend cmpa #$21 bne gif2 lbsr skipextension bra GIFLoop gif2 cmpa #$2c bne GIFLoop bsr gifimage bra GIFLoop GIFend lbsr EndGIF Return extra memory area. rts vsect dp mincode rmb 1 Starting code size lastcode rmb 2 Last code input thiscode rmb 2 the current code endcode rmb 2 Code signifying end of picture clrcode rmb 2 code indicating that we clear the table firstcolor rmb 1 First color of code just processed codesize rmb 1 Current code size in bits *bethy rmb 50 How much I love Beth. (Needs to be MUCH bigger...) endsect * Process a GIF image gifimage pshs a,b,x,y,u * First, handle the image descriptor lbsr GIFgetword offset of pic from left edge of screen lbsr GIFgetword offset of pic from top of screen lbsr GIFgetword image width std gifiwidth lbsr GIFgetword image height std gifiheight lbsr I_GetByte bitmapped option byte tfr a,b sex sta domap top bit: T=local map follows tfr b,a anda #$3 inca sta pixel Bottom 3 bits: bits/pixel less one. lslb sex sta gifinterlace Bit 6: T=Use interlace tst domap Is there a local color map? beq nolocal lbsr colormap Yes, handle it. nolocal * Now, we're down to the actual image. lbsr I_GetByte Get the starting code size. sta mincode cmpa #8 Does code size make sense? bls gifcodeok lbra E$Format No, report a format error. gifcodeok lbsr lzwinit Initialize some machinery lbsr gifoutinit * From here on, U holds the address of the next entry in the decode table. lbsr clrtable Clear table, set endcode and clrcode imageloop lbsr nexttoken Get a code. stx thiscode cmpx endcode Is it an end-of-pic code? beq imageend cmpx clrcode Is it a clear code? bne imagenormal lbsr clrtable If so, reinitialize everything. lbsr nexttoken Get the next token (always a root) stx lastcode lbsr outcode Output it. bra imageloop imagenormal lbsr outcode Output the code, set the initial color var. ldx lastcode lda firstcolor stx ,u++ Add the code to the decode table. sta ,u+ cmpu <codelimit Are we at the point where we change code size? blo addcend lbsr setlimit Yes, do it. addcend ldx thiscode stx lastcode bra imageloop imageend puls a,b,x,y,u,pc * This is an extension block, so skip it. skipextension pshs a,b,x,y lbsr I_GetByte Get function code extensloop bsr getpacket Get packet, size in A. tsta bne extensloop Non-zero, get another. puls a,b,x,y,pc * Get a packet from input into AltBuff, return packet size in A. getpacket pshs b,x,y lbsr I_GetByte tsta beq getpackend pshs a tfr a,b clra leax altbuff,y tfr d,y lbsr I_Read lbcs _error puls a getpackend puls b,x,y,pc * Read and process colormap colormap pshs a,b,x,y,u lda pixel bsr powertwo leax altbuff,y leau alt2buff,y pshs y tfr d,y leay d,y leay d,y Y:=3*D lbsr I_Read Read global color map lbcs _error puls y tst <screenset Is screen already set? bne endcmap Yes, don't process stuff. com screenset No, mark it as set. lbsr GIFcolors Translate colors, and generate color translation table. lbsr setscreen lbsr setbuffer lbsr setpals Set the palettes lda background Translate background color through the translation table leau a,u leau a,u lda a,u lbsr setborder Set the border color. endcmap puls a,b,x,y,u,pc * Take value in A and return 2**A in D (assumes A<15). powertwo pshs a ldd #1 tst ,s powerloop beq powerend lslb rola dec ,s bra powerloop powerend leas 1,s rts * Read and process screen descriptor screendesc pshs a,b bsr GIFgetword std swidth First word is screen width in pixels bsr GIFgetword std sheight Next is screen height in pixels lbsr I_GetByte This is bit-mapped lbcs _error Bit 7: T= global map follows tfr a,b Bits 6:5:4: number bits of "color resolution" - 1 andb #7 Bits 2:1:0: Number of bits per pixel - 1 incb (Determines size of color map) stb pixel tfr a,b sex sta domap Top bit is true if global color map follows lbsr I_GetByte lbcs _error sta background lbsr I_GetByte lbcs _error tsta lbne E$Format puls a,b,pc GIFgetword lbsr I_GetByte lbcs _error tfr a,b lbsr I_GetByte lbcs _error rts * Signature: scan input to find "GIF###", the GIF signature string, * where ### is two digits followed by a lowercase letter, e.g. * '87a' sigsub lbsr I_GetByte lbcs _error rts signature pshs a,b Sig0 bsr sigsub Sig1 cmpa #'G Search for "GIF" bne Sig0 bsr sigsub cmpa #'I bne Sig1 bsr sigsub cmpa #'F bne Sig1 clrb Sig2 bsr sigsub Get two digits cmpa #'0 blo Sig1 cmpa #'9 bhi Sig1 comb bne Sig2 bsr sigsub and one lowercase letter cmpa #'a blo Sig1 cmpa #'z bhi Sig1 puls a,b,pc * *LZW decode subs. * vsect dp codelimit rmb 2 Point at which we must switch code sizes. endsect * Miscellaneous initialization lzwinit pshs a,b,x clr <packsiz clr <numbits puls a,b,x,pc * Initialize the decode table * clrtable pshs a,b,x,y ldx giftable Get start of table lda mincode lbsr powertwo pshs y tfr d,y clra clrb clrloop sta ,x+ Roots have 0 for pointer, themselves for suffix std ,x++ incb leay -1,y bne clrloop puls y stx clrcode leax 3,x stx endcode leax 3,x tfr x,u Set up nextentry pointer in U lda mincode sta codesize Pretend we were doing "mincode". lbsr setlimit Bump to next codesize. puls a,b,x,y,pc vsect dp packptr rmb 2 packsiz rmb 1 endsect * Return next byte from file nextbyte pshs x tst packsiz bne nextbyte1 lbsr getpacket sta packsiz leax altbuff,y stx packptr nextbyte1 dec packsiz ldx packptr lda ,x+ stx packptr puls x,pc vsect dp numbits rmb 1 Number of bits in bit buffer bitbuff rmb 3 Buffer bits from file here codemask rmb 2 Mask off just codesize bits. endsect * Return next token from file nexttoken pshs d ldb numbits First, fill bitbuffer with enough bits to make up codesize bra nexttokst nexttokloop ldx bitbuff Move other 16 bits forward. stx bitbuff+1 bsr nextbyte Get 8 more bits sta bitbuff addb #8 Increase bit count. nexttokst cmpb codesize blo nexttokloop stb numbits cmpb #17 Do we have to deal with three bytes? blo nexttok2 No, 16 or fewer bits, so just deal with two. ldb #20 subb numbits First, we shift until we get to bit #20. clra tfr d,x ldd bitbuff We keep first two bytes in D, leave 3rd one in place. nexttok31 lsra Analysis shows that we are never past bit 19, so we will rorb always have to process this loop at least once. ror bitbuff+2 leax -1,x bne nexttok31 tfr b,a Now, the first bit of the token we want is out of the first ldb bitbuff+2 byte, so we're down to two bytes. lsra rorb Since we start with the least sig bit in bit #20, and we want it lsra in bit #24, we must shift exactly 4 times. rorb lsra rorb lsra rorb bra nexttok10 Now we have our token. nexttok2 cmpb #9 Do we have to deal with two bytes? blo nexttok1 ldb #16 subb numbits clra tfr d,x ldd bitbuff stx -2,s Test X for zero. beq nexttok10 nexttok21 lsra rorb leax -1,x bne nexttok21 bra nexttok10 nexttok1 ldb bitbuff lda #8 suba numbits beq nexttok10 nexttok11 lsrb deca bne nexttok11 nexttok10 anda codemask andb codemask+1 ldx <giftable leax d,x leax d,x leax d,x ldb numbits subb codesize stb numbits puls d,pc outcode pshs a,b,x,y,u ldu <gifstack cmpx 6,s U is on the stack. lbhi E$Format If the code is too large, report a format error beq outcode1 bsr outcsub If it's in the table, process it. bra outcode2 outcode1 ldx lastcode If it's not in the table, then it is the last code bsr outcsub followed by the first color of the last code. lda firstcolor lbsr gifoutpix outcode2 puls a,b,x,y,u,pc outcsub pshs y ldy #0000 outc1 lda 2,x leay 1,y pshu a ldx ,x bne outc1 tfr y,x Put the count in X puls y sta firstcolor Now we know the first color, so store it. outc2 pulu a lbsr gifoutpix leax -1,x bne outc2 rts * Add a code to the table addcode pshs a,b puls a,b,pc setlimit pshs a,b,x lda codesize cmpa #12 bhs setlim1 inca setlim1 sta codesize lbsr powertwo ldx giftable leax d,x leax d,x leax d,x stx codelimit subd #1 std <codemask puls a,b,x,pc endsect