Want more features on Pastebin? Sign Up, it's FREE!
Guest

An Optimized Nemesis decompressor for 68k (S2 version)

By: a guest on Feb 28th, 2015  |  syntax: Motorola 68000 HiSoft Dev  |  size: 6.06 KB  |  views: 246  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print  |  QR code  |  clone
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  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
clone this paste RAW Paste Data