Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; ==============================================================================
- ; ------------------------------------------------------------------------------
- ; Nemesis decompression routine
- ; ------------------------------------------------------------------------------
- ; Optimized by vladikcomper
- ; Modified for Sonic 2 by MainMemory
- ; ------------------------------------------------------------------------------
- NemDecToRAM:
- movem.l d0-a1/a3-a6,-(sp)
- lea NemDec_WriteAndAdvance(pc),a3
- bra.s NemDec_Main
- ; ------------------------------------------------------------------------------
- NemDec:
- movem.l d0-a1/a3-a6,-(sp)
- lea (VDP_data_port).l,a4 ; load VDP Data Port
- lea NemDec_WriteAndStay(pc),a3
- NemDec_Main:
- lea (Decomp_Buffer).w,a1 ; load Nemesis decompression buffer
- move.w (a0)+,d2 ; get number of patterns
- bpl.s + ; are we in Mode 0?
- lea $A(a3),a3 ; if not, use Mode 1
- +
- lsl.w #3,d2
- movea.w d2,a5
- moveq #7,d3
- moveq #0,d2
- moveq #0,d4
- bsr.w NemDecPrepare
- move.b (a0)+,d5 ; get first byte of compressed data
- asl.w #8,d5 ; shift up by a byte
- move.b (a0)+,d5 ; get second byte of compressed data
- move.w #$10,d6 ; set initial shift value
- bsr.s NemDec2
- movem.l (sp)+,d0-a1/a3-a6
- rts
- ; ---------------------------------------------------------------------------
- ; Part of the Nemesis decompressor, processes the actual compressed data
- ; ---------------------------------------------------------------------------
- NemDec2:
- move.w d6,d7
- subq.w #8,d7 ; get shift value
- move.w d5,d1
- lsr.w d7,d1 ; shift so that high bit of the code is in bit position 7
- cmpi.b #%11111100,d1 ; are the high 6 bits set?
- bcc.s NemDec_InlineData ; if they are, it signifies inline data
- andi.w #$FF,d1
- add.w d1,d1
- sub.b (a1,d1.w),d6 ; ~~ subtract from shift value so that the next code is read next time around
- cmpi.w #9,d6 ; does a new byte need to be read?
- bcc.s + ; if not, branch
- addq.w #8,d6
- asl.w #8,d5
- move.b (a0)+,d5 ; read next byte
- +
- move.b 1(a1,d1.w),d1
- move.w d1,d0
- andi.w #$F,d1 ; get palette index for pixel
- andi.w #$F0,d0
- NemDec_GetRepeatCount:
- lsr.w #4,d0 ; get repeat count
- NemDec_WritePixel:
- lsl.l #4,d4 ; shift up by a nybble
- or.b d1,d4 ; write pixel
- dbf d3,NemDec_WritePixelLoop; ~~
- jmp (a3) ; otherwise, write the row to its destination
- ; ---------------------------------------------------------------------------
- NemDec_WriteIter:
- moveq #0,d4 ; reset row
- moveq #7,d3 ; reset nybble counter
- NemDec_WritePixelLoop:
- dbf d0,NemDec_WritePixel
- bra.s NemDec2
- ; ---------------------------------------------------------------------------
- NemDec_InlineData:
- subq.w #6,d6 ; 6 bits needed to signal inline data
- cmpi.w #9,d6
- bcc.s +
- addq.w #8,d6
- asl.w #8,d5
- move.b (a0)+,d5
- +
- subq.w #7,d6 ; and 7 bits needed for the inline data itself
- move.w d5,d1
- lsr.w d6,d1 ; shift so that low bit of the code is in bit position 0
- move.w d1,d0
- andi.w #$F,d1 ; get palette index for pixel
- andi.w #$70,d0 ; high nybble is repeat count for pixel
- cmpi.w #9,d6
- bcc.s NemDec_GetRepeatCount
- addq.w #8,d6
- asl.w #8,d5
- move.b (a0)+,d5
- bra.s NemDec_GetRepeatCount
- ; ---------------------------------------------------------------------------
- ; Subroutines to output decompressed entry
- ; Selected depending on current decompression mode
- ; ---------------------------------------------------------------------------
- NemDec_WriteAndStay:
- loc_1502:
- move.l d4,(a4) ; write 8-pixel row
- subq.w #1,a5
- move.w a5,d4 ; have all the 8-pixel rows been written?
- bne.s NemDec_WriteIter ; if not, branch
- rts
- ; ---------------------------------------------------------------------------
- NemDec_WriteAndStay_XOR:
- eor.l d4,d2 ; XOR the previous row by the current row
- move.l d2,(a4) ; and write the result
- subq.w #1,a5
- move.w a5,d4
- bne.s NemDec_WriteIter
- rts
- ; ---------------------------------------------------------------------------
- NemDec_WriteAndAdvance:
- move.l d4,(a4)+ ; write 8-pixel row
- subq.w #1,a5
- move.w a5,d4 ; have all the 8-pixel rows been written?
- bne.s NemDec_WriteIter ; if not, branch
- rts
- ; ---------------------------------------------------------------------------
- NemDec_WriteAndAdvance_XOR:
- eor.l d4,d2 ; XOR the previous row by the current row
- move.l d2,(a4)+ ; and write the result
- subq.w #1,a5
- move.w a5,d4
- bne.s NemDec_WriteIter
- rts
- ; ---------------------------------------------------------------------------
- ; Part of the Nemesis decompressor, builds the code table (in RAM)
- ; ---------------------------------------------------------------------------
- NemDecPrepare:
- move.b (a0)+,d0 ; read first byte
- .ChkEnd:
- cmpi.b #$FF,d0 ; has the end of the code table description been reached?
- bne.s .NewPalIndex ; if not, branch
- rts
- ; ---------------------------------------------------------------------------
- .NewPalIndex:
- move.w d0,d7
- .ItemLoop:
- move.b (a0)+,d0 ; read next byte
- bmi.s .ChkEnd ; ~~
- move.b d0,d1
- andi.w #$F,d7 ; get palette index
- andi.w #$70,d1 ; get repeat count for palette index
- or.w d1,d7 ; combine the two
- andi.w #$F,d0 ; get the length of the code in bits
- move.b d0,d1
- lsl.w #8,d1
- or.w d1,d7 ; combine with palette index and repeat count to form code table entry
- moveq #8,d1
- sub.w d0,d1 ; is the code 8 bits long?
- bne.s .ItemShortCode ; if not, a bit of extra processing is needed
- move.b (a0)+,d0 ; get code
- add.w d0,d0 ; each code gets a word-sized entry in the table
- move.w d7,(a1,d0.w) ; store the entry for the code
- bra.s .ItemLoop ; repeat
- ; ---------------------------------------------------------------------------
- .ItemShortCode:
- move.b (a0)+,d0 ; get code
- lsl.w d1,d0 ; shift so that high bit is in bit position 7
- add.w d0,d0 ; get index into code table
- moveq #1,d5
- lsl.w d1,d5
- subq.w #1,d5 ; d5 = 2^d1 - 1
- lea (a1,d0.w),a6 ; ~~
- .ItemShortCodeLoop:
- move.w d7,(a6)+ ; ~~ store entry
- dbf d5,.ItemShortCodeLoop ; repeat for required number of entries
- bra.s .ItemLoop
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement