Advertisement
Guest User

An Optimized Nemesis decompressor for 68k (S2 version)

a guest
Feb 28th, 2015
439
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; ==============================================================================
  2. ; ------------------------------------------------------------------------------
  3. ; Nemesis decompression routine
  4. ; ------------------------------------------------------------------------------
  5. ; Optimized by vladikcomper
  6. ; Modified for Sonic 2 by MainMemory
  7. ; ------------------------------------------------------------------------------
  8.  
  9. NemDecToRAM:
  10.     movem.l d0-a1/a3-a6,-(sp)
  11.     lea NemDec_WriteAndAdvance(pc),a3
  12.     bra.s   NemDec_Main
  13.  
  14. ; ------------------------------------------------------------------------------
  15. NemDec:
  16.     movem.l d0-a1/a3-a6,-(sp)
  17.     lea (VDP_data_port).l,a4        ; load VDP Data Port    
  18.     lea NemDec_WriteAndStay(pc),a3
  19.  
  20. NemDec_Main:
  21.     lea (Decomp_Buffer).w,a1        ; load Nemesis decompression buffer
  22.     move.w  (a0)+,d2        ; get number of patterns
  23.     bpl.s   +           ; are we in Mode 0?
  24.     lea $A(a3),a3       ; if not, use Mode 1
  25. +
  26.     lsl.w   #3,d2
  27.     movea.w d2,a5
  28.     moveq   #7,d3
  29.     moveq   #0,d2
  30.     moveq   #0,d4
  31.     bsr.w   NemDecPrepare
  32.     move.b  (a0)+,d5        ; get first byte of compressed data
  33.     asl.w   #8,d5           ; shift up by a byte
  34.     move.b  (a0)+,d5        ; get second byte of compressed data
  35.     move.w  #$10,d6         ; set initial shift value
  36.     bsr.s   NemDec2
  37.     movem.l (sp)+,d0-a1/a3-a6
  38.     rts
  39.  
  40. ; ---------------------------------------------------------------------------
  41. ; Part of the Nemesis decompressor, processes the actual compressed data
  42. ; ---------------------------------------------------------------------------
  43.  
  44. NemDec2:
  45.     move.w  d6,d7
  46.     subq.w  #8,d7           ; get shift value
  47.     move.w  d5,d1
  48.     lsr.w   d7,d1           ; shift so that high bit of the code is in bit position 7
  49.     cmpi.b  #%11111100,d1       ; are the high 6 bits set?
  50.     bcc.s   NemDec_InlineData   ; if they are, it signifies inline data
  51.     andi.w  #$FF,d1
  52.     add.w   d1,d1
  53.     sub.b   (a1,d1.w),d6        ; ~~ subtract from shift value so that the next code is read next time around
  54.     cmpi.w  #9,d6           ; does a new byte need to be read?
  55.     bcc.s   +           ; if not, branch
  56.     addq.w  #8,d6
  57.     asl.w   #8,d5
  58.     move.b  (a0)+,d5        ; read next byte
  59. +
  60.     move.b  1(a1,d1.w),d1
  61.     move.w  d1,d0
  62.     andi.w  #$F,d1          ; get palette index for pixel
  63.     andi.w  #$F0,d0
  64.  
  65. NemDec_GetRepeatCount:
  66.     lsr.w   #4,d0           ; get repeat count
  67.  
  68. NemDec_WritePixel:
  69.     lsl.l   #4,d4           ; shift up by a nybble
  70.     or.b    d1,d4           ; write pixel
  71.     dbf d3,NemDec_WritePixelLoop; ~~
  72.     jmp (a3)            ; otherwise, write the row to its destination
  73. ; ---------------------------------------------------------------------------
  74.  
  75. NemDec_WriteIter:
  76.     moveq   #0,d4           ; reset row
  77.     moveq   #7,d3           ; reset nybble counter
  78.  
  79. NemDec_WritePixelLoop:
  80.     dbf d0,NemDec_WritePixel
  81.     bra.s   NemDec2
  82. ; ---------------------------------------------------------------------------
  83.  
  84. NemDec_InlineData:
  85.     subq.w  #6,d6           ; 6 bits needed to signal inline data
  86.     cmpi.w  #9,d6
  87.     bcc.s   +
  88.     addq.w  #8,d6
  89.     asl.w   #8,d5
  90.     move.b  (a0)+,d5
  91. +
  92.     subq.w  #7,d6           ; and 7 bits needed for the inline data itself
  93.     move.w  d5,d1
  94.     lsr.w   d6,d1           ; shift so that low bit of the code is in bit position 0
  95.     move.w  d1,d0
  96.     andi.w  #$F,d1          ; get palette index for pixel
  97.     andi.w  #$70,d0         ; high nybble is repeat count for pixel
  98.     cmpi.w  #9,d6
  99.     bcc.s   NemDec_GetRepeatCount
  100.     addq.w  #8,d6
  101.     asl.w   #8,d5
  102.     move.b  (a0)+,d5
  103.     bra.s   NemDec_GetRepeatCount
  104.  
  105. ; ---------------------------------------------------------------------------
  106. ; Subroutines to output decompressed entry
  107. ; Selected depending on current decompression mode
  108. ; ---------------------------------------------------------------------------
  109.  
  110. NemDec_WriteAndStay:
  111. loc_1502:
  112.     move.l  d4,(a4)         ; write 8-pixel row
  113.     subq.w  #1,a5
  114.     move.w  a5,d4           ; have all the 8-pixel rows been written?
  115.     bne.s   NemDec_WriteIter            ; if not, branch
  116.     rts
  117. ; ---------------------------------------------------------------------------
  118.  
  119. NemDec_WriteAndStay_XOR:
  120.     eor.l   d4,d2           ; XOR the previous row by the current row
  121.     move.l  d2,(a4)         ; and write the result
  122.     subq.w  #1,a5
  123.     move.w  a5,d4
  124.     bne.s   NemDec_WriteIter
  125.     rts
  126. ; ---------------------------------------------------------------------------
  127.  
  128. NemDec_WriteAndAdvance:
  129.     move.l  d4,(a4)+        ; write 8-pixel row
  130.     subq.w  #1,a5
  131.     move.w  a5,d4           ; have all the 8-pixel rows been written?
  132.     bne.s   NemDec_WriteIter            ; if not, branch
  133.     rts
  134. ; ---------------------------------------------------------------------------
  135.  
  136. NemDec_WriteAndAdvance_XOR:
  137.     eor.l   d4,d2           ; XOR the previous row by the current row
  138.     move.l  d2,(a4)+        ; and write the result
  139.     subq.w  #1,a5
  140.     move.w  a5,d4
  141.     bne.s   NemDec_WriteIter
  142.     rts
  143.  
  144. ; ---------------------------------------------------------------------------
  145. ; Part of the Nemesis decompressor, builds the code table (in RAM)
  146. ; ---------------------------------------------------------------------------
  147.  
  148. NemDecPrepare:
  149.     move.b  (a0)+,d0        ; read first byte
  150.  
  151. .ChkEnd:
  152.     cmpi.b  #$FF,d0         ; has the end of the code table description been reached?
  153.     bne.s   .NewPalIndex        ; if not, branch
  154.     rts
  155. ; ---------------------------------------------------------------------------
  156.  
  157. .NewPalIndex:
  158.     move.w  d0,d7
  159.  
  160. .ItemLoop:
  161.     move.b  (a0)+,d0        ; read next byte
  162.     bmi.s   .ChkEnd         ; ~~
  163.     move.b  d0,d1
  164.     andi.w  #$F,d7          ; get palette index
  165.     andi.w  #$70,d1         ; get repeat count for palette index
  166.     or.w    d1,d7           ; combine the two
  167.     andi.w  #$F,d0          ; get the length of the code in bits
  168.     move.b  d0,d1
  169.     lsl.w   #8,d1
  170.     or.w    d1,d7           ; combine with palette index and repeat count to form code table entry
  171.     moveq   #8,d1
  172.     sub.w   d0,d1           ; is the code 8 bits long?
  173.     bne.s   .ItemShortCode      ; if not, a bit of extra processing is needed
  174.     move.b  (a0)+,d0        ; get code
  175.     add.w   d0,d0           ; each code gets a word-sized entry in the table
  176.     move.w  d7,(a1,d0.w)        ; store the entry for the code
  177.     bra.s   .ItemLoop       ; repeat
  178. ; ---------------------------------------------------------------------------
  179.  
  180. .ItemShortCode:
  181.     move.b  (a0)+,d0        ; get code
  182.     lsl.w   d1,d0           ; shift so that high bit is in bit position 7
  183.     add.w   d0,d0           ; get index into code table
  184.     moveq   #1,d5
  185.     lsl.w   d1,d5
  186.     subq.w  #1,d5           ; d5 = 2^d1 - 1
  187.     lea (a1,d0.w),a6        ; ~~
  188.  
  189. .ItemShortCodeLoop:
  190.     move.w  d7,(a6)+        ; ~~ store entry
  191.     dbf d5,.ItemShortCodeLoop   ; repeat for required number of entries
  192.     bra.s   .ItemLoop
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement