Guest User

Untitled

a guest
Dec 15th, 2017
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; ------------------------------------------------------------------------------
  2. ; Nemesis decompression routine
  3. ; ------------------------------------------------------------------------------
  4. ; Optimized by vladikcomper, further optimizations & comments by carljr17
  5. ; ------------------------------------------------------------------------------
  6.  
  7. NemDec_RAM:
  8.  
  9.         ; INPUT:
  10.         ;   a4 -> RAM to output patterns to
  11.  
  12.         movem.l d0-d6/a0-a1/a3-a5,-(sp)     ; 8 + 8*12 = 104
  13.  
  14.         lea     NemDec_WriteRowToRAM(pc),a3 ; 8
  15.  
  16.         bra.s   NemDec_Main                 ; 10
  17.  
  18. ; ------------------------------------------------------------------------------
  19.  
  20. NemDec:
  21.  
  22.         ; a0 -> number of patterns + mode, followed by compressed data
  23.  
  24.         movem.l d0-d6/a0-a1/a3-a5,-(sp)
  25.  
  26.         lea     NemDec_WriteRowToVDP(pc),a3 ;  8 a3  = jump address for pixel row writes
  27.         lea     $C00000,a4                  ; 12 a4 -> [vdp_data_port]
  28. NemDec_Main:
  29.         ; a3  = NemDec_WriteRowToRAM/VDP
  30.         ; a4 -> [$C00000] (vdp_data_port) (or anywhere in RAM)
  31.  
  32.         lea     $FFAA00.w,a1            ;  8 a1 -> [$FFAA00] (Nemesis decompression buffer)
  33.  
  34.         move.w  (a0)+,d3                ;  8 d3 <- #/patterns (MSB set for Mode 1)
  35.         bpl.s   @0                      ; 10/8 d3.15 == 1 ? no, so in Mode 0 (not based on changes between rows)
  36.  
  37.         lea     NemDec_WriteRowToVDP_XOR-NemDec_WriteRowToVDP(a3),a3 ;  8 yes, so in Mode 1 (each row XOR'd with last, only changes recorded)
  38. @0:
  39.         lsl.w   #3,d3                   ; 6 + 2*3 = 12 -.
  40.         subq.w  #1,d3                   ;            4 -' d3 = #/patterns * 8 (= number of rows to plot), minus 1
  41.  
  42.         bsr.w   NemDec4                 ; 18 d0-2/d5/a5 build opcode-to-count/color lookup table
  43.  
  44.         moveq   #0,d2                   ; for use with Mode 1 only (XOR with first row)
  45.         moveq   #1,d4                   ; set stop bit (nybble counter) -- 8 pixels per row
  46.  
  47.         move.b  (a0)+,d5                ; -. get first two bytes of compressed data
  48.         asl.w   #8,d5                   ;  : (can't we replace this with move.w (a0)+,d5 !?)
  49.         move.b  (a0)+,d5                ; -'
  50.  
  51.         moveq   #16,d6                  ; 16 bits ready, set initial shift value
  52.  
  53.         bsr.s   NemDec2                 ; read in from bit stream of opcodes/in-line data, output rows
  54.  
  55.         movem.l (sp)+,d0-d6/a0-a1/a3-a5
  56.  
  57.         rts
  58.  
  59. ; ---------------------------------------------------------------------------
  60. ; Part of the Nemesis decompressor, processes the actual compressed data
  61. ; ---------------------------------------------------------------------------
  62.  
  63. NemDec_WritePixelLoop:
  64.  
  65.         or.b    d1,d4                   ; d4.l = ........ ........ .......! 00001111 etc.
  66. NemDec3:
  67.         dbra    d0,NemDec_WritePixel    ; 10/12 --repeat count == -1 ? no, so plot another pixel
  68. NemDec2:
  69.  
  70.         ; INPUT:
  71.  
  72.         ;   a0 -> stream of bits -- opcodes and/or in-line data
  73.         ;   a1 -> [$FFAA000] (LUT: opcode to palette, repeat count, & opcode width, 512 bytes)
  74.         ;   a3  = NemDec_WriteRowToRAM/VDP/_XOR
  75.         ;   a4 -> [$C00000] (vdp_data_port) (or anywhere in RAM)
  76.  
  77.         ;   d2.l  = previous row of 8 pixels, or 0 if first row; XOR'd with new row (mode 1 only)
  78.         ;   d3.w  = number of patterns * 8 (= number of rows to plot), minus 1
  79.         ;   d4.l  = holds 8 pixel nibbles, initially 1 (used as a stop bit or nybble counter)
  80.         ;   d5.w  = [a0 - 2] (first 16 bits of stream, read left to right)
  81.         ;   d6.b  = #/bits remaining to process, initially 16
  82.  
  83.         ; TRASHES: d0-d1
  84.  
  85.         subq.b  #9,d6                   ;  4 get right shift value to peek ahead at next 9 bits
  86.         move.w  d5,d0                   ;  4    -. left-justify opcode (high bit in bit #8),
  87.         lsr.w   d6,d0                   ;  6+2n -' followed by 1 or more unrelated, unprocessed bits
  88.  
  89.         andi.w  #$01FE,d0               ;  8 isolate 8 bits for lookup: opcode and 1 or more unrelated bits
  90.         sub.b   0(a1,d0.w),d6           ; 14 subtract opcode width, minus 9, from #/bits remaining
  91.         move.b  1(a1,d0.w),d0           ; 14 d0.w <- .......? irrrpppp
  92.         bpl.s   NemDec_NotInline        ; if i == 1, inline: next 7 bits are palette + count (rrrpppp)
  93.  
  94.         cmpi.b  #9,d6                   ; 9 or more bits still available ?
  95.         bcc.s   @0                      ; no,  so not enough room to read next byte
  96.  
  97.         addq.b  #8,d6                   ; 8 new bits, about to be read in below
  98.         asl.w   #8,d5                   ; shift all remaining bits into high byte
  99.         move.b  (a0)+,d5                ; get next 8 bits into low of d5
  100. @0:
  101.         subq.b  #7,d6                   ; 7 bits needed for inline data itself (palette + count)
  102.         move.w  d5,d0
  103.         lsr.w   d6,d0                   ; shift so that low bit rrrpppp is in bit position 0
  104. NemDec_NotInline:
  105.         cmpi.b  #9,d6                   ; 9 or more bits still available ?
  106.         bcc.s   @1                      ; no,  so not enough room for read next byte
  107.  
  108.         addq.b  #8,d6                   ; 8 new bits, about to be read in below
  109.         asl.w   #8,d5                   ; shift all remaining bits into high byte
  110.         move.b  (a0)+,d5                ; get next 8 bits into low of d5
  111. @1:
  112.         move.b  d0,d1                   ; d1.w  = ???????? ?rrrpppp
  113.         andi.b  #$0F,d1                 ;       = ???????? ....pppp (palette index)
  114.         andi.w  #$0070,d0               ; d0.w  = ........ .rrr....
  115.         lsr.w   #4,d0                   ;       = ........ .....rrr (repeat count, minus 1; clear bits 8-15)
  116. NemDec_WritePixel:
  117.         lsl.l   #4,d4                   ; d4.l = ........ ........ .......! 0000....
  118.         bcc.s   NemDec_WritePixelLoop   ; 10/8
  119.  
  120.         or.b    d1,d4                   ; d4.l = 00001111 22223333 44445555 66667777
  121.  
  122.         jmp     (a3)                    ; 8
  123.  
  124. ; ---------------------------------------------------------------------------
  125.  
  126. NemDec_WriteRowToVDP:
  127.  
  128.         move.l  d4,(a4)                 ; write 8-pixel row to VDP control port
  129.  
  130.         moveq   #1,d4                   ;  4 reset 8-pixel row, set stop bit/nybble counter
  131.  
  132.         dbra    d3,NemDec3              ; 10/12 have all 8-pixel rows been written ? if yes, branch
  133.  
  134.         rts
  135.  
  136. NemDec_WriteRowToVDP_XOR:
  137.  
  138.         eor.l   d4,d2                   ; XOR the previous row by the current row
  139.         move.l  d2,(a4)                 ; write new current row to VDP control port
  140.  
  141.         moveq   #1,d4                   ;  4 reset 8-pixel row, set stop bit/nybble counter
  142.  
  143.         dbra    d3,NemDec3              ; 10/12 have all 8-pixel rows been written ? if yes, branch
  144.  
  145.         rts
  146.  
  147. ; ---------------------------------------------------------------------------
  148.  
  149. NemDec_WriteRowToRAM:
  150.  
  151.         move.l  d4,(a4)+                ; write 8-pixel row to RAM, with post-increment
  152.  
  153.         moveq   #1,d4                   ;  4 reset 8-pixel row, set stop bit/nybble counter
  154.  
  155.         dbra    d3,NemDec3              ; 10/12 have all 8-pixel rows been written ? if yes, branch
  156.  
  157.         rts
  158.  
  159. NemDec_WriteRowToRAM_XOR:
  160.  
  161.         eor.l   d4,d2                   ; XOR the previous row by the current row
  162.         move.l  d2,(a4)+                ; write new current row to RAM with post-increment
  163.  
  164.         moveq   #1,d4                   ;  4 reset 8-pixel row, set stop bit/nybble counter
  165.  
  166.         dbra    d3,NemDec3              ; 10/12 have all 8-pixel rows been written ? if yes, branch
  167.  
  168.         rts
  169.  
  170. ; ---------------------------------------------------------------------------
  171. ; Part of the Nemesis decompressor, builds the code table (in RAM)
  172. ; ---------------------------------------------------------------------------
  173.  
  174. NemDec4:
  175.  
  176.         ; INPUT:
  177.  
  178.         ;   a0 -> !...pppp (palette index -- 1st need not have bit #7 set)
  179.         ;         .rrrcccc (repeat count + code length)
  180.         ;         cccccccc (opcode, mysteriously right-justified)
  181.         ;         .rrrcccc (repeat count + code length)
  182.         ;         cccccccc (opcode, mysteriously right-justified)
  183.         ;         ...
  184.         ;         $FF      (end-of-table)
  185.         ;   a1 -> [$FFAA000] (nemesis decompression buffer -- actually 512 byte opcode-to-count/color LUT)
  186.  
  187.         ; TRASHES: d0-2/d5/a5
  188.  
  189.         lea     $01F8(a1),a5            ;  8 point to last four entries of table (used to flag inline data)
  190.         move.l  #$FDFFFDFF,d5           ; 12 set cccc (opcode width) = 6 (minus 9), i (inline) = 1, rrrpppp = don't care
  191.         move.l  d5,(a5)+                ; 12 [$01F8 + 0/2].w <- !!!!cccc irrrpppp
  192.         move.l  d5,(a5)+                ; 12 [$01F8 + 4/6].w <- !!!!cccc irrrpppp
  193.  
  194.         move.b  (a0)+,d0                ;  8 read 1st byte (????pppp or $FF for end-of-table)
  195.  
  196.         bra.s   @ChkEnd                 ; 10 if d0.7 == 1, end of table ($FF) OR new palette index (!???pppp)
  197.  
  198. @ItemLoop:
  199.  
  200.         move.b  d0,d5                   ;  4 d5.w = ???????? .rrrcccc (rrr = repeat count, cccc = opcode width)
  201.         andi.w  #$000F,d2               ;  8 d2.w = ........ ....pppp
  202.         andi.w  #$0070,d0               ;  8 d0.w = ........ .rrr.... (note bits 8-15 cleared for below)
  203.         or.b    d0,d2                   ;  4 d2.w = ........ .rrrpppp
  204.  
  205.         eor.b   d0,d5                   ;  4 d5.w = ???????? ....cccc
  206.  
  207.         moveq   #8,d1                   ;  4 -. d1.b = 8 - code length = shift left count (for left justify)
  208.         sub.b   d5,d1                   ;  4 -' i.e., 12345678 -> 76543210
  209.  
  210.         sub.b   #9,d5                   ;  8 opcode width - 9 needed for NemDec2
  211.         lsl.w   #8,d5                   ; 6 + 2*8 = 24 d5.w = !!!!cccc ........
  212.         or.w    d5,d2                   ;  4 d2.w = !!!!cccc .rrrpppp (table entry)
  213.  
  214.         move.b  (a0)+,d0                ;  8 get actual opcode (mysteriously not shifted into position)
  215.         lsl.b   d1,d0                   ; 6 + 2*d1 d0.b = opcode << ( 8 - opcode width ) (= left justify opcode; but why isn't this just pre-shifted ?)
  216.         add.w   d0,d0                   ;  4 double to index into table of words
  217.  
  218.         moveq   #0,d5                   ;  4 -.
  219.         bset    d1,d5                   ;  6  : d5 = 1 << ( 8 - opcode length ) - 1
  220.         subq.b  #1,d5                   ;  4 -'    = #/times to repeat table entry
  221.  
  222.         lea     (a1,d0.w),a5            ; 12 (versus 4 move.w a1, a5 + 8 add.w d0, a5 = 12)
  223. @ItemShortCodeLoop:
  224.         move.w  d2,(a5)+                ;  8 store entry: !!!!cccc .rrrpppp
  225.         dbra    d5,@ItemShortCodeLoop   ; 10/14 repeat for required number of entries
  226. @ChkNext:
  227.         move.b  (a0)+,d0                ;  8 palette index, repeat count/opcode width, or end-of-table
  228.         bpl.s   @ItemLoop               ; 10/8 if d0.7 == 0, repeat count/opcode width
  229. @ChkEnd:
  230.         move.b  d0,d2                   ;  4 d2.w = ???????? ????pppp (pppp = palette index)
  231.  
  232.         not.b   d0                      ;  4 reached end-of-table ?
  233.         bne.s   @ChkNext                ; 10/8 yes, so return to caller (RTS)
  234.  
  235.         rts                             ; return to caller
Add Comment
Please, Sign In to add comment