SHOW:
|
|
- or go back to the newest paste.
| 1 | ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| | |
| 2 | ; --------------------------------------------------------------------------- | |
| 3 | ; Adds a Kosinski Moduled archive to the module queue | |
| 4 | ; Inputs: | |
| 5 | ; a1 = address of the archive | |
| 6 | ; d2 = destination in VRAM | |
| 7 | ; --------------------------------------------------------------------------- | |
| 8 | Queue_Kos_Module: | |
| 9 | lea (Kos_module_queue).w,a2 | |
| 10 | tst.l (a2) ; is the first slot free? | |
| 11 | beq.s Process_Kos_Module_Queue_Init ; if it is, branch | |
| 12 | ||
| 13 | .findFreeSlot: | |
| 14 | addq.w #6,a2 ; otherwise, check next slot | |
| 15 | tst.l (a2) | |
| 16 | bne.s .findFreeSlot | |
| 17 | ||
| 18 | move.l a1,(a2)+ ; store source address | |
| 19 | move.w d2,(a2)+ ; store destination VRAM address | |
| 20 | rts | |
| 21 | ; End of function Queue_Kos_Module | |
| 22 | ; =========================================================================== | |
| 23 | ||
| 24 | ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| | |
| 25 | ; --------------------------------------------------------------------------- | |
| 26 | ; Initializes processing of the first module on the queue | |
| 27 | ; --------------------------------------------------------------------------- | |
| 28 | Process_Kos_Module_Queue_Init: | |
| 29 | move.w (a1)+,d3 ; get uncompressed size | |
| 30 | cmpi.w #$A000,d3 | |
| 31 | bne.s .gotsize | |
| 32 | move.w #$8000,d3 ; $A000 means $8000 for some reason | |
| 33 | ||
| 34 | .gotsize: | |
| 35 | lsr.w #1,d3 | |
| 36 | move.w d3,d0 | |
| 37 | rol.w #5,d0 | |
| 38 | andi.w #$1F,d0 ; get number of complete modules | |
| 39 | move.b d0,(Kos_modules_left).w | |
| 40 | andi.w #$7FF,d3 ; get size of last module in words | |
| 41 | bne.s .gotleftover ; branch if it's non-zero | |
| 42 | subq.b #1,(Kos_modules_left).w ; otherwise decrement the number of modules | |
| 43 | move.w #$800,d3 ; and take the size of the last module to be $800 words | |
| 44 | ||
| 45 | .gotleftover: | |
| 46 | move.w d3,(Kos_last_module_size).w | |
| 47 | move.w d2,(Kos_module_destination).w | |
| 48 | move.l a1,(Kos_module_queue).w | |
| 49 | addq.b #1,(Kos_modules_left).w ; store total number of modules | |
| 50 | rts | |
| 51 | ; End of function Process_Kos_Module_Queue_Init | |
| 52 | ; =========================================================================== | |
| 53 | ||
| 54 | ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| | |
| 55 | ; --------------------------------------------------------------------------- | |
| 56 | ; Processes the first module on the queue | |
| 57 | ; --------------------------------------------------------------------------- | |
| 58 | Process_Kos_Module_Queue: | |
| 59 | tst.b (Kos_modules_left).w | |
| 60 | bne.s .modulesLeft | |
| 61 | ||
| 62 | .done: | |
| 63 | rts | |
| 64 | ; --------------------------------------------------------------------------- | |
| 65 | .modulesLeft: | |
| 66 | bmi.s .decompressionStarted | |
| 67 | cmpi.w #4,(Kos_decomp_queue_count).w | |
| 68 | bcc.s .done ; branch if the Kosinski decompression queue is full | |
| 69 | movea.l (Kos_module_queue).w,a1 | |
| 70 | lea (Kos_decomp_buffer).w,a2 | |
| 71 | bsr.w Queue_Kos ; add current module to decompression queue | |
| 72 | ori.b #$80,(Kos_modules_left).w ; and set bit to signify decompression in progress | |
| 73 | rts | |
| 74 | ; --------------------------------------------------------------------------- | |
| 75 | .decompressionStarted: | |
| 76 | tst.w (Kos_decomp_queue_count).w | |
| 77 | bne.s .done ; branch if the decompression isn't complete | |
| 78 | ||
| 79 | ; otherwise, DMA the decompressed data to VRAM | |
| 80 | andi.b #$7F,(Kos_modules_left).w | |
| 81 | move.w #$800,d3 | |
| 82 | subq.b #1,(Kos_modules_left).w | |
| 83 | bne.s .skip ; branch if it isn't the last module | |
| 84 | move.w (Kos_last_module_size).w,d3 | |
| 85 | ||
| 86 | .skip: | |
| 87 | move.w (Kos_module_destination).w,d2 | |
| 88 | move.w d2,d0 | |
| 89 | add.w d3,d0 | |
| 90 | add.w d3,d0 | |
| 91 | move.w d0,(Kos_module_destination).w ; set new destination | |
| 92 | move.l (Kos_module_queue).w,d0 | |
| 93 | move.l (Kos_decomp_queue).w,d1 | |
| 94 | sub.l d1,d0 | |
| 95 | andi.l #$F,d0 | |
| 96 | add.l d0,d1 ; round to the nearest $10 boundary | |
| 97 | move.l d1,(Kos_module_queue).w ; and set new source | |
| 98 | move.l #Kos_decomp_buffer,d1 | |
| 99 | jsr (QueueDMATransfer).w | |
| 100 | tst.b (Kos_modules_left).w | |
| 101 | bne.s .exit ; return if this wasn't the last module | |
| 102 | lea (Kos_module_queue).w,a0 | |
| 103 | lea (Kos_module_queue+6).w,a1 | |
| 104 | move.l (a1)+,(a0)+ ; otherwise, shift all entries up | |
| 105 | move.w (a1)+,(a0)+ | |
| 106 | move.l (a1)+,(a0)+ | |
| 107 | move.w (a1)+,(a0)+ | |
| 108 | move.l (a1)+,(a0)+ | |
| 109 | move.w (a1)+,(a0)+ | |
| 110 | moveq #0,d0 | |
| 111 | move.l d0,(a0)+ ; and mark the last slot as free | |
| 112 | move.w d0,(a0)+ | |
| 113 | move.l (Kos_module_queue).w,d0 | |
| 114 | beq.s .exit ; return if the queue is now empty | |
| 115 | movea.l d0,a1 | |
| 116 | move.w (Kos_module_destination).w,d2 | |
| 117 | bra.w Process_Kos_Module_Queue_Init | |
| 118 | ||
| 119 | .exit: | |
| 120 | rts | |
| 121 | ; End of function Process_Kos_Module_Queue | |
| 122 | ; =========================================================================== | |
| 123 | ||
| 124 | ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| | |
| 125 | ; --------------------------------------------------------------------------- | |
| 126 | ; Adds Kosinski-compressed data to the decompression queue | |
| 127 | ; Inputs: | |
| 128 | ; a1 = compressed data address | |
| 129 | ; a2 = decompression destination in RAM | |
| 130 | ; --------------------------------------------------------------------------- | |
| 131 | Queue_Kos: | |
| 132 | move.w (Kos_decomp_queue_count).w,d0 | |
| 133 | lsl.w #3,d0 | |
| 134 | lea (Kos_decomp_queue).w,a3 | |
| 135 | move.l a1,(a3,d0.w) ; store source | |
| 136 | move.l a2,4(a3,d0.w) ; store destination | |
| 137 | addq.w #1,(Kos_decomp_queue_count).w | |
| 138 | rts | |
| 139 | ; End of function Queue_Kos | |
| 140 | ; =========================================================================== | |
| 141 | ||
| 142 | ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| | |
| 143 | ; --------------------------------------------------------------------------- | |
| 144 | ; Checks if V-int occured in the middle of Kosinski queue processing | |
| 145 | ; and stores the location from which processing is to resume if it did | |
| 146 | ; --------------------------------------------------------------------------- | |
| 147 | Set_Kos_Bookmark: | |
| 148 | tst.w (Kos_decomp_queue_count).w | |
| 149 | bpl.s .done ; branch if a decompression wasn't in progress | |
| 150 | move.l $42(sp),d0 ; check address V-int is supposed to rte to | |
| 151 | cmpi.l #Process_Kos_Queue.Main,d0 | |
| 152 | bcs.s .done | |
| 153 | cmpi.l #Process_Kos_Queue.Done,d0 | |
| 154 | bcc.s .done | |
| 155 | move.l $42(sp),(Kos_decomp_bookmark).w | |
| 156 | move.l #Backup_Kos_Registers,$42(sp) ; force V-int to rte here instead if needed | |
| 157 | ||
| 158 | .done: | |
| 159 | rts | |
| 160 | ; End of function Set_Kos_Bookmark | |
| 161 | ; =========================================================================== | |
| 162 | ||
| 163 | ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| | |
| 164 | ; --------------------------------------------------------------------------- | |
| 165 | ; Processes the first entry in the Kosinski decompression queue | |
| 166 | ; --------------------------------------------------------------------------- | |
| 167 | Process_Kos_Queue: | |
| 168 | tst.w (Kos_decomp_queue_count).w | |
| 169 | beq.w .Done | |
| 170 | bmi.w Restore_Kos_Bookmark ; branch if a decompression was interrupted by V-int | |
| 171 | ||
| 172 | .Main: | |
| 173 | ori.w #$8000,(Kos_decomp_queue_count).w ; set sign bit to signify decompression in progress | |
| 174 | movea.l (Kos_decomp_queue).w,a0 | |
| 175 | movea.l (Kos_decomp_destination).w,a1 | |
| 176 | ||
| 177 | ; what follows is identical to the normal Kosinski decompressor | |
| 178 | moveq #(1<<_Kos_LoopUnroll)-1,d7 | |
| 179 | if _Kos_UseLUT==1 | |
| 180 | moveq #0,d0 | |
| 181 | moveq #0,d1 | |
| 182 | lea KosDec_ByteMap(pc),a4 ; Load LUT pointer. | |
| 183 | endif | |
| 184 | move.b (a0)+,d0 ; Get desc field low-byte. | |
| 185 | move.b (a0)+,d1 ; Get desc field hi-byte. | |
| 186 | if _Kos_UseLUT==1 | |
| 187 | move.b (a4,d0.w),d0 ; Invert bit order... | |
| 188 | move.b (a4,d1.w),d1 ; ... for both bytes. | |
| 189 | endif | |
| 190 | moveq #7,d2 ; Set repeat count to 8. | |
| 191 | - | moveq #-1,d3 ; d3 will be desc field switcher. |
| 191 | + | moveq #0,d3 ; d3 will be desc field switcher. |
| 192 | - | clr.w d3 ; Low word is zero. |
| 192 | + | |
| 193 | ; --------------------------------------------------------------------------- | |
| 194 | .FetchCodeLoop: | |
| 195 | ; Code 1 (Uncompressed byte). | |
| 196 | _Kos_RunBitStream | |
| 197 | move.b (a0)+,(a1)+ | |
| 198 | ||
| 199 | .FetchNewCode: | |
| 200 | _Kos_ReadBit | |
| 201 | bcs.s .FetchCodeLoop ; If code = 1, branch. | |
| 202 | ||
| 203 | ; Codes 00 and 01. | |
| 204 | moveq #-1,d5 | |
| 205 | lea (a1),a5 | |
| 206 | _Kos_RunBitStream | |
| 207 | if _Kos_ExtremeUnrolling==1 | |
| 208 | _Kos_ReadBit | |
| 209 | bcs.w .Code_01 | |
| 210 | ||
| 211 | ; Code 00 (Dictionary ref. short). | |
| 212 | _Kos_RunBitStream | |
| 213 | _Kos_ReadBit | |
| 214 | bcs.s .Copy45 | |
| 215 | _Kos_RunBitStream | |
| 216 | _Kos_ReadBit | |
| 217 | bcs.s .Copy3 | |
| 218 | _Kos_RunBitStream | |
| 219 | move.b (a0)+,d5 ; d5 = displacement. | |
| 220 | adda.w d5,a5 | |
| 221 | move.b (a5)+,(a1)+ | |
| 222 | move.b (a5)+,(a1)+ | |
| 223 | bra.s .FetchNewCode | |
| 224 | ; --------------------------------------------------------------------------- | |
| 225 | .Copy3: | |
| 226 | _Kos_RunBitStream | |
| 227 | move.b (a0)+,d5 ; d5 = displacement. | |
| 228 | adda.w d5,a5 | |
| 229 | move.b (a5)+,(a1)+ | |
| 230 | move.b (a5)+,(a1)+ | |
| 231 | move.b (a5)+,(a1)+ | |
| 232 | bra.w .FetchNewCode | |
| 233 | ; --------------------------------------------------------------------------- | |
| 234 | .Copy45: | |
| 235 | _Kos_RunBitStream | |
| 236 | _Kos_ReadBit | |
| 237 | bcs.s .Copy5 | |
| 238 | _Kos_RunBitStream | |
| 239 | move.b (a0)+,d5 ; d5 = displacement. | |
| 240 | adda.w d5,a5 | |
| 241 | move.b (a5)+,(a1)+ | |
| 242 | move.b (a5)+,(a1)+ | |
| 243 | move.b (a5)+,(a1)+ | |
| 244 | move.b (a5)+,(a1)+ | |
| 245 | bra.w .FetchNewCode | |
| 246 | ; --------------------------------------------------------------------------- | |
| 247 | .Copy5: | |
| 248 | _Kos_RunBitStream | |
| 249 | move.b (a0)+,d5 ; d5 = displacement. | |
| 250 | adda.w d5,a5 | |
| 251 | move.b (a5)+,(a1)+ | |
| 252 | move.b (a5)+,(a1)+ | |
| 253 | move.b (a5)+,(a1)+ | |
| 254 | move.b (a5)+,(a1)+ | |
| 255 | move.b (a5)+,(a1)+ | |
| 256 | bra.w .FetchNewCode | |
| 257 | ; --------------------------------------------------------------------------- | |
| 258 | else | |
| 259 | moveq #0,d4 ; d4 will contain copy count. | |
| 260 | _Kos_ReadBit | |
| 261 | bcs.s .Code_01 | |
| 262 | ||
| 263 | ; Code 00 (Dictionary ref. short). | |
| 264 | _Kos_RunBitStream | |
| 265 | _Kos_ReadBit | |
| 266 | addx.w d4,d4 | |
| 267 | _Kos_RunBitStream | |
| 268 | _Kos_ReadBit | |
| 269 | addx.w d4,d4 | |
| 270 | _Kos_RunBitStream | |
| 271 | move.b (a0)+,d5 ; d5 = displacement. | |
| 272 | ||
| 273 | .StreamCopy: | |
| 274 | adda.w d5,a5 | |
| 275 | move.b (a5)+,(a1)+ ; Do 1 extra copy (to compensate +1 to copy counter). | |
| 276 | ||
| 277 | .copy: | |
| 278 | move.b (a5)+,(a1)+ | |
| 279 | dbra d4,.copy | |
| 280 | bra.w .FetchNewCode | |
| 281 | endif | |
| 282 | ; --------------------------------------------------------------------------- | |
| 283 | .Code_01: | |
| 284 | moveq #0,d4 ; d4 will contain copy count. | |
| 285 | ; Code 01 (Dictionary ref. long / special). | |
| 286 | _Kos_RunBitStream | |
| 287 | move.b (a0)+,d6 ; d6 = %LLLLLLLL. | |
| 288 | move.b (a0)+,d4 ; d4 = %HHHHHCCC. | |
| 289 | move.b d4,d5 ; d5 = %11111111 HHHHHCCC. | |
| 290 | lsl.w #5,d5 ; d5 = %111HHHHH CCC00000. | |
| 291 | move.b d6,d5 ; d5 = %111HHHHH LLLLLLLL. | |
| 292 | if _Kos_LoopUnroll==3 | |
| 293 | and.w d7,d4 ; d4 = %00000CCC. | |
| 294 | else | |
| 295 | andi.w #7,d4 | |
| 296 | endif | |
| 297 | bne.s .StreamCopy ; if CCC=0, branch. | |
| 298 | ||
| 299 | ; special mode (extended counter) | |
| 300 | move.b (a0)+,d4 ; Read cnt | |
| 301 | beq.s .Quit ; If cnt=0, quit decompression. | |
| 302 | subq.b #1,d4 | |
| 303 | beq.w .FetchNewCode ; If cnt=1, fetch a new code. | |
| 304 | ||
| 305 | adda.w d5,a5 | |
| 306 | move.b (a5)+,(a1)+ ; Do 1 extra copy (to compensate +1 to copy counter). | |
| 307 | move.w d4,d6 | |
| 308 | not.w d6 | |
| 309 | and.w d7,d6 | |
| 310 | add.w d6,d6 | |
| 311 | lsr.w #_Kos_LoopUnroll,d4 | |
| 312 | jmp .largecopy(pc,d6.w) | |
| 313 | ; --------------------------------------------------------------------------- | |
| 314 | .largecopy: | |
| 315 | rept (1<<_Kos_LoopUnroll) | |
| 316 | move.b (a5)+,(a1)+ | |
| 317 | endm | |
| 318 | dbra d4,.largecopy | |
| 319 | bra.w .FetchNewCode | |
| 320 | ; --------------------------------------------------------------------------- | |
| 321 | if _Kos_ExtremeUnrolling==1 | |
| 322 | .StreamCopy: | |
| 323 | adda.w d5,a5 | |
| 324 | move.b (a5)+,(a1)+ ; Do 1 extra copy (to compensate +1 to copy counter). | |
| 325 | if _Kos_LoopUnroll==3 | |
| 326 | eor.w d7,d4 | |
| 327 | else | |
| 328 | eori.w #7,d4 | |
| 329 | endif | |
| 330 | add.w d4,d4 | |
| 331 | jmp .mediumcopy(pc,d4.w) | |
| 332 | ; --------------------------------------------------------------------------- | |
| 333 | .mediumcopy: | |
| 334 | rept 8 | |
| 335 | move.b (a5)+,(a1)+ | |
| 336 | endm | |
| 337 | bra.w .FetchNewCode | |
| 338 | endif | |
| 339 | ; --------------------------------------------------------------------------- | |
| 340 | .Quit: | |
| 341 | move.l a0,(Kos_decomp_queue).w | |
| 342 | move.l a1,(Kos_decomp_destination).w | |
| 343 | andi.w #$7FFF,(Kos_decomp_queue_count).w ; clear decompression in progress bit | |
| 344 | subq.w #1,(Kos_decomp_queue_count).w | |
| 345 | beq.s .Done ; branch if there aren't any entries remaining in the queue | |
| 346 | lea (Kos_decomp_queue).w,a0 | |
| 347 | lea (Kos_decomp_queue+8).w,a1 ; otherwise, shift all entries up | |
| 348 | move.l (a1)+,(a0)+ | |
| 349 | move.l (a1)+,(a0)+ | |
| 350 | move.l (a1)+,(a0)+ | |
| 351 | move.l (a1)+,(a0)+ | |
| 352 | move.l (a1)+,(a0)+ | |
| 353 | move.l (a1)+,(a0)+ | |
| 354 | ||
| 355 | .Done: | |
| 356 | rts | |
| 357 | ; --------------------------------------------------------------------------- | |
| 358 | Restore_Kos_Bookmark: | |
| 359 | movem.w (Kos_decomp_stored_registers).w,d0-d6 | |
| 360 | movem.l (Kos_decomp_stored_registers+2*7).w,a0-a1/a5 | |
| 361 | move.l (Kos_decomp_bookmark).w,-(sp) | |
| 362 | move.w (Kos_decomp_stored_SR).w,-(sp) | |
| 363 | moveq #(1<<_Kos_LoopUnroll)-1,d7 | |
| 364 | lea KosDec_ByteMap(pc),a4 ; Load LUT pointer. | |
| 365 | rte | |
| 366 | ; End of function Process_Kos_Queue | |
| 367 | ; =========================================================================== | |
| 368 | Backup_Kos_Registers: | |
| 369 | move sr,(Kos_decomp_stored_SR).w | |
| 370 | movem.w d0-d6,(Kos_decomp_stored_registers).w | |
| 371 | movem.l a0-a1/a5,(Kos_decomp_stored_registers+2*7).w | |
| 372 | rts | |
| 373 | ; =========================================================================== |