2014-05-31 08:22:15 +00:00
|
|
|
; bankswitches and runs _UncompressSpriteData
|
2015-08-31 02:38:41 +00:00
|
|
|
; bank is given in a, sprite input stream is pointed to in wSpriteInputPtr
|
2016-06-12 00:24:04 +00:00
|
|
|
UncompressSpriteData::
|
2014-05-31 08:22:15 +00:00
|
|
|
ld b, a
|
|
|
|
ld a, [H_LOADEDROMBANK]
|
|
|
|
push af
|
|
|
|
ld a, b
|
|
|
|
ld [H_LOADEDROMBANK], a
|
2015-07-03 19:37:53 +00:00
|
|
|
ld [MBC1RomBank], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, $a
|
|
|
|
ld [$0], a
|
|
|
|
xor a
|
|
|
|
ld [$4000], a
|
|
|
|
call _UncompressSpriteData
|
|
|
|
pop af
|
|
|
|
ld [H_LOADEDROMBANK], a
|
2015-07-03 19:37:53 +00:00
|
|
|
ld [MBC1RomBank], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ret
|
|
|
|
|
|
|
|
; initializes necessary data to load a sprite and runs UncompressSpriteDataLoop
|
2016-06-12 00:24:04 +00:00
|
|
|
_UncompressSpriteData::
|
2015-08-31 03:15:32 +00:00
|
|
|
ld hl, sSpriteBuffer1
|
2014-05-31 08:22:15 +00:00
|
|
|
ld c, (2*SPRITEBUFFERSIZE) % $100
|
|
|
|
ld b, (2*SPRITEBUFFERSIZE) / $100
|
|
|
|
xor a
|
|
|
|
call FillMemory ; clear sprite buffer 1 and 2
|
|
|
|
ld a, $1
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteInputBitCounter], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, $3
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputBitOffset], a
|
2014-05-31 08:22:15 +00:00
|
|
|
xor a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosX], a
|
|
|
|
ld [wSpriteCurPosY], a
|
|
|
|
ld [wSpriteLoadFlags], a
|
2014-05-31 08:22:15 +00:00
|
|
|
call ReadNextInputByte ; first byte of input determines sprite width (high nybble) and height (low nybble) in tiles (8x8 pixels)
|
|
|
|
ld b, a
|
|
|
|
and $f
|
|
|
|
add a
|
|
|
|
add a
|
|
|
|
add a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteHeight], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, b
|
|
|
|
swap a
|
|
|
|
and $f
|
|
|
|
add a
|
|
|
|
add a
|
|
|
|
add a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteWidth], a
|
2014-05-31 08:22:15 +00:00
|
|
|
call ReadNextInputBit
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteLoadFlags], a ; initialite bit1 to 0 and bit0 to the first input bit
|
2015-08-31 03:15:32 +00:00
|
|
|
; this will load two chunks of data to sSpriteBuffer1 and sSpriteBuffer2
|
2014-05-31 08:22:15 +00:00
|
|
|
; bit 0 decides in which one the first chunk is placed
|
|
|
|
; fall through
|
|
|
|
|
2015-08-31 03:15:32 +00:00
|
|
|
; uncompresses a chunk from the sprite input data stream (pointed to at wd0da) into sSpriteBuffer1 or sSpriteBuffer2
|
2014-05-31 08:22:15 +00:00
|
|
|
; each chunk is a 1bpp sprite. A 2bpp sprite consist of two chunks which are merged afterwards
|
|
|
|
; note that this is an endless loop which is terminated during a call to MoveToNextBufferPosition by manipulating the stack
|
2016-06-12 00:24:04 +00:00
|
|
|
UncompressSpriteDataLoop::
|
2015-08-31 03:15:32 +00:00
|
|
|
ld hl, sSpriteBuffer1
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteLoadFlags]
|
2014-05-31 08:22:15 +00:00
|
|
|
bit 0, a
|
|
|
|
jr z, .useSpriteBuffer1 ; check which buffer to use
|
2015-08-31 03:15:32 +00:00
|
|
|
ld hl, sSpriteBuffer2
|
2014-05-31 08:22:15 +00:00
|
|
|
.useSpriteBuffer1
|
|
|
|
call StoreSpriteOutputPointer
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteLoadFlags]
|
2014-05-31 08:22:15 +00:00
|
|
|
bit 1, a
|
|
|
|
jr z, .startDecompression ; check if last iteration
|
|
|
|
call ReadNextInputBit ; if last chunk, read 1-2 bit unpacking mode
|
|
|
|
and a
|
|
|
|
jr z, .unpackingMode0 ; 0 -> mode 0
|
|
|
|
call ReadNextInputBit ; 1 0 -> mode 1
|
|
|
|
inc a ; 1 1 -> mode 2
|
|
|
|
.unpackingMode0
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteUnpackMode], a
|
2014-05-31 08:22:15 +00:00
|
|
|
.startDecompression
|
|
|
|
call ReadNextInputBit
|
|
|
|
and a
|
|
|
|
jr z, .readRLEncodedZeros ; if first bit is 0, the input starts with zeroes, otherwise with (non-zero) input
|
|
|
|
.readNextInput
|
|
|
|
call ReadNextInputBit
|
|
|
|
ld c, a
|
|
|
|
call ReadNextInputBit
|
|
|
|
sla c
|
|
|
|
or c ; read next two bits into c
|
|
|
|
and a
|
|
|
|
jr z, .readRLEncodedZeros ; 00 -> RLEncoded zeroes following
|
|
|
|
call WriteSpriteBitsToBuffer ; otherwise write input to output and repeat
|
|
|
|
call MoveToNextBufferPosition
|
|
|
|
jr .readNextInput
|
|
|
|
.readRLEncodedZeros
|
|
|
|
ld c, $0 ; number of zeroes it length encoded, the number
|
|
|
|
.countConsecutiveOnesLoop ; of consecutive ones determines the number of bits the number has
|
|
|
|
call ReadNextInputBit
|
|
|
|
and a
|
|
|
|
jr z, .countConsecutiveOnesFinished
|
|
|
|
inc c
|
|
|
|
jr .countConsecutiveOnesLoop
|
|
|
|
.countConsecutiveOnesFinished
|
|
|
|
ld a, c
|
|
|
|
add a
|
|
|
|
ld hl, LengthEncodingOffsetList
|
|
|
|
add l
|
|
|
|
ld l, a
|
|
|
|
jr nc, .noCarry
|
|
|
|
inc h
|
|
|
|
.noCarry
|
|
|
|
ld a, [hli] ; read offset that is added to the number later on
|
|
|
|
ld e, a ; adding an offset of 2^length - 1 makes every integer uniquely
|
|
|
|
ld d, [hl] ; representable in the length encoding and saves bits
|
|
|
|
push de
|
|
|
|
inc c
|
|
|
|
ld e, $0
|
|
|
|
ld d, e
|
|
|
|
.readNumberOfZerosLoop ; reads the next c+1 bits of input
|
|
|
|
call ReadNextInputBit
|
|
|
|
or e
|
|
|
|
ld e, a
|
|
|
|
dec c
|
|
|
|
jr z, .readNumberOfZerosDone
|
|
|
|
sla e
|
|
|
|
rl d
|
|
|
|
jr .readNumberOfZerosLoop
|
|
|
|
.readNumberOfZerosDone
|
|
|
|
pop hl ; add the offset
|
|
|
|
add hl, de
|
|
|
|
ld e, l
|
|
|
|
ld d, h
|
|
|
|
.writeZerosLoop
|
|
|
|
ld b, e
|
|
|
|
xor a ; write 00 to buffer
|
|
|
|
call WriteSpriteBitsToBuffer
|
|
|
|
ld e, b
|
|
|
|
call MoveToNextBufferPosition
|
|
|
|
dec de
|
|
|
|
ld a, d
|
|
|
|
and a
|
|
|
|
jr nz, .continueLoop
|
|
|
|
ld a, e
|
|
|
|
and a
|
|
|
|
.continueLoop
|
|
|
|
jr nz, .writeZerosLoop
|
|
|
|
jr .readNextInput
|
|
|
|
|
|
|
|
; moves output pointer to next position
|
|
|
|
; also cancels the calling function if the all output is done (by removing the return pointer from stack)
|
|
|
|
; and calls postprocessing functions according to the unpack mode
|
2016-06-12 00:24:04 +00:00
|
|
|
MoveToNextBufferPosition::
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteHeight]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld b, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteCurPosY]
|
2014-05-31 08:22:15 +00:00
|
|
|
inc a
|
|
|
|
cp b
|
|
|
|
jr z, .curColumnDone
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosY], a
|
|
|
|
ld a, [wSpriteOutputPtr]
|
2014-05-31 08:22:15 +00:00
|
|
|
inc a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtr], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ret nz
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
inc a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtr+1], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ret
|
|
|
|
.curColumnDone
|
|
|
|
xor a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosY], a
|
|
|
|
ld a, [wSpriteOutputBitOffset]
|
2014-05-31 08:22:15 +00:00
|
|
|
and a
|
|
|
|
jr z, .bitOffsetsDone
|
|
|
|
dec a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputBitOffset], a
|
|
|
|
ld hl, wSpriteOutputPtrCached
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, [hli]
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtr], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, [hl]
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtr+1], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ret
|
|
|
|
.bitOffsetsDone
|
|
|
|
ld a, $3
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputBitOffset], a
|
|
|
|
ld a, [wSpriteCurPosX]
|
2014-05-31 08:22:15 +00:00
|
|
|
add $8
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosX], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld b, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteWidth]
|
2014-05-31 08:22:15 +00:00
|
|
|
cp b
|
|
|
|
jr z, .allColumnsDone
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld h, a
|
|
|
|
inc hl
|
|
|
|
jp StoreSpriteOutputPointer
|
|
|
|
.allColumnsDone
|
|
|
|
pop hl
|
|
|
|
xor a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosX], a
|
|
|
|
ld a, [wSpriteLoadFlags]
|
2014-05-31 08:22:15 +00:00
|
|
|
bit 1, a
|
|
|
|
jr nz, .done ; test if there is one more sprite to go
|
|
|
|
xor $1
|
|
|
|
set 1, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteLoadFlags], a
|
2014-05-31 08:22:15 +00:00
|
|
|
jp UncompressSpriteDataLoop
|
|
|
|
.done
|
|
|
|
jp UnpackSprite
|
|
|
|
|
2015-08-31 02:38:41 +00:00
|
|
|
; writes 2 bits (from a) to the output buffer (pointed to from wSpriteOutputPtr)
|
2016-06-12 00:24:04 +00:00
|
|
|
WriteSpriteBitsToBuffer::
|
2014-05-31 08:22:15 +00:00
|
|
|
ld e, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputBitOffset]
|
2014-05-31 08:22:15 +00:00
|
|
|
and a
|
|
|
|
jr z, .offset0
|
|
|
|
cp $2
|
|
|
|
jr c, .offset1
|
|
|
|
jr z, .offset2
|
|
|
|
rrc e ; offset 3
|
|
|
|
rrc e
|
|
|
|
jr .offset0
|
|
|
|
.offset1
|
|
|
|
sla e
|
|
|
|
sla e
|
|
|
|
jr .offset0
|
|
|
|
.offset2
|
|
|
|
swap e
|
|
|
|
.offset0
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld h, a
|
|
|
|
ld a, [hl]
|
|
|
|
or e
|
|
|
|
ld [hl], a
|
|
|
|
ret
|
|
|
|
|
|
|
|
; reads next bit from input stream and returns it in a
|
2016-06-12 00:24:04 +00:00
|
|
|
ReadNextInputBit::
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteInputBitCounter]
|
2014-05-31 08:22:15 +00:00
|
|
|
dec a
|
|
|
|
jr nz, .curByteHasMoreBitsToRead
|
|
|
|
call ReadNextInputByte
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteInputCurByte], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, $8
|
|
|
|
.curByteHasMoreBitsToRead
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteInputBitCounter], a
|
|
|
|
ld a, [wSpriteInputCurByte]
|
2014-05-31 08:22:15 +00:00
|
|
|
rlca
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteInputCurByte], a
|
2014-05-31 08:22:15 +00:00
|
|
|
and $1
|
|
|
|
ret
|
|
|
|
|
|
|
|
; reads next byte from input stream and returns it in a
|
2016-06-12 00:24:04 +00:00
|
|
|
ReadNextInputByte::
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteInputPtr]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteInputPtr+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld h, a
|
|
|
|
ld a, [hli]
|
|
|
|
ld b, a
|
|
|
|
ld a, l
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteInputPtr], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, h
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteInputPtr+1], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, b
|
|
|
|
ret
|
|
|
|
|
|
|
|
; the nth item is 2^n - 1
|
2016-06-12 00:24:04 +00:00
|
|
|
LengthEncodingOffsetList::
|
2014-05-31 08:22:15 +00:00
|
|
|
dw %0000000000000001
|
|
|
|
dw %0000000000000011
|
|
|
|
dw %0000000000000111
|
|
|
|
dw %0000000000001111
|
|
|
|
dw %0000000000011111
|
|
|
|
dw %0000000000111111
|
|
|
|
dw %0000000001111111
|
|
|
|
dw %0000000011111111
|
|
|
|
dw %0000000111111111
|
|
|
|
dw %0000001111111111
|
|
|
|
dw %0000011111111111
|
|
|
|
dw %0000111111111111
|
|
|
|
dw %0001111111111111
|
|
|
|
dw %0011111111111111
|
|
|
|
dw %0111111111111111
|
|
|
|
dw %1111111111111111
|
|
|
|
|
|
|
|
; unpacks the sprite data depending on the unpack mode
|
2016-06-12 00:24:04 +00:00
|
|
|
UnpackSprite::
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteUnpackMode]
|
2014-05-31 08:22:15 +00:00
|
|
|
cp $2
|
|
|
|
jp z, UnpackSpriteMode2
|
|
|
|
and a
|
|
|
|
jp nz, XorSpriteChunks
|
2015-08-31 03:15:32 +00:00
|
|
|
ld hl, sSpriteBuffer1
|
2014-05-31 08:22:15 +00:00
|
|
|
call SpriteDifferentialDecode
|
2015-08-31 03:15:32 +00:00
|
|
|
ld hl, sSpriteBuffer2
|
2014-05-31 08:22:15 +00:00
|
|
|
; fall through
|
|
|
|
|
|
|
|
; decodes differential encoded sprite data
|
|
|
|
; input bit value 0 preserves the current bit value and input bit value 1 toggles it (starting from initial value 0).
|
2016-06-12 00:24:04 +00:00
|
|
|
SpriteDifferentialDecode::
|
2014-05-31 08:22:15 +00:00
|
|
|
xor a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosX], a
|
|
|
|
ld [wSpriteCurPosY], a
|
2014-05-31 08:22:15 +00:00
|
|
|
call StoreSpriteOutputPointer
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteFlipped]
|
2014-05-31 08:22:15 +00:00
|
|
|
and a
|
|
|
|
jr z, .notFlipped
|
|
|
|
ld hl, DecodeNybble0TableFlipped
|
|
|
|
ld de, DecodeNybble1TableFlipped
|
|
|
|
jr .storeDecodeTablesPointers
|
|
|
|
.notFlipped
|
|
|
|
ld hl, DecodeNybble0Table
|
|
|
|
ld de, DecodeNybble1Table
|
|
|
|
.storeDecodeTablesPointers
|
|
|
|
ld a, l
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteDecodeTable0Ptr], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, h
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteDecodeTable0Ptr+1], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, e
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteDecodeTable1Ptr], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, d
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteDecodeTable1Ptr+1], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld e, $0 ; last decoded nybble, initialized to 0
|
|
|
|
.decodeNextByteLoop
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld h, a
|
|
|
|
ld a, [hl]
|
|
|
|
ld b, a
|
|
|
|
swap a
|
|
|
|
and $f
|
|
|
|
call DifferentialDecodeNybble ; decode high nybble
|
|
|
|
swap a
|
|
|
|
ld d, a
|
|
|
|
ld a, b
|
|
|
|
and $f
|
|
|
|
call DifferentialDecodeNybble ; decode low nybble
|
|
|
|
or d
|
|
|
|
ld b, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld h, a
|
|
|
|
ld a, b
|
|
|
|
ld [hl], a ; write back decoded data
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteHeight]
|
2014-05-31 08:22:15 +00:00
|
|
|
add l ; move on to next column
|
|
|
|
jr nc, .noCarry
|
|
|
|
inc h
|
|
|
|
.noCarry
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtr], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, h
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtr+1], a
|
|
|
|
ld a, [wSpriteCurPosX]
|
2014-05-31 08:22:15 +00:00
|
|
|
add $8
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosX], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld b, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteWidth]
|
2014-05-31 08:22:15 +00:00
|
|
|
cp b
|
|
|
|
jr nz, .decodeNextByteLoop ; test if current row is done
|
|
|
|
xor a
|
|
|
|
ld e, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosX], a
|
|
|
|
ld a, [wSpriteCurPosY] ; move on to next row
|
2014-05-31 08:22:15 +00:00
|
|
|
inc a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosY], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld b, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteHeight]
|
2014-05-31 08:22:15 +00:00
|
|
|
cp b
|
|
|
|
jr z, .done ; test if all rows finished
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtrCached]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtrCached+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld h, a
|
|
|
|
inc hl
|
|
|
|
call StoreSpriteOutputPointer
|
|
|
|
jr .decodeNextByteLoop
|
|
|
|
.done
|
|
|
|
xor a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosY], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ret
|
|
|
|
|
|
|
|
; decodes the nybble stored in a. Last decoded data is assumed to be in e (needed to determine if initial value is 0 or 1)
|
2016-06-12 00:24:04 +00:00
|
|
|
DifferentialDecodeNybble::
|
2014-05-31 08:22:15 +00:00
|
|
|
srl a ; c=a%2, a/=2
|
|
|
|
ld c, $0
|
|
|
|
jr nc, .evenNumber
|
|
|
|
ld c, $1
|
|
|
|
.evenNumber
|
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteFlipped]
|
2014-05-31 08:22:15 +00:00
|
|
|
and a
|
|
|
|
jr z, .notFlipped ; determine if initial value is 0 or one
|
|
|
|
bit 3, e ; if flipped, consider MSB of last data
|
|
|
|
jr .selectLookupTable
|
|
|
|
.notFlipped
|
|
|
|
bit 0, e ; else consider LSB
|
|
|
|
.selectLookupTable
|
|
|
|
ld e, l
|
|
|
|
jr nz, .initialValue1 ; load the appropriate table
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteDecodeTable0Ptr]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteDecodeTable0Ptr+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
jr .tableLookup
|
|
|
|
.initialValue1
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteDecodeTable1Ptr]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteDecodeTable1Ptr+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
.tableLookup
|
|
|
|
ld h, a
|
|
|
|
ld a, e
|
|
|
|
add l
|
|
|
|
ld l, a
|
|
|
|
jr nc, .noCarry
|
|
|
|
inc h
|
|
|
|
.noCarry
|
|
|
|
ld a, [hl]
|
|
|
|
bit 0, c
|
|
|
|
jr nz, .selectLowNybble
|
|
|
|
swap a ; select high nybble
|
|
|
|
.selectLowNybble
|
|
|
|
and $f
|
|
|
|
ld e, a ; update last decoded data
|
|
|
|
ret
|
|
|
|
|
2016-06-12 00:24:04 +00:00
|
|
|
DecodeNybble0Table::
|
2014-05-31 08:22:15 +00:00
|
|
|
dn $0, $1
|
|
|
|
dn $3, $2
|
|
|
|
dn $7, $6
|
|
|
|
dn $4, $5
|
|
|
|
dn $f, $e
|
|
|
|
dn $c, $d
|
|
|
|
dn $8, $9
|
|
|
|
dn $b, $a
|
2016-06-12 00:24:04 +00:00
|
|
|
DecodeNybble1Table::
|
2014-05-31 08:22:15 +00:00
|
|
|
dn $f, $e
|
|
|
|
dn $c, $d
|
|
|
|
dn $8, $9
|
|
|
|
dn $b, $a
|
|
|
|
dn $0, $1
|
|
|
|
dn $3, $2
|
|
|
|
dn $7, $6
|
|
|
|
dn $4, $5
|
2016-06-12 00:24:04 +00:00
|
|
|
DecodeNybble0TableFlipped::
|
2014-05-31 08:22:15 +00:00
|
|
|
dn $0, $8
|
|
|
|
dn $c, $4
|
|
|
|
dn $e, $6
|
|
|
|
dn $2, $a
|
|
|
|
dn $f, $7
|
|
|
|
dn $3, $b
|
|
|
|
dn $1, $9
|
|
|
|
dn $d, $5
|
2016-06-12 00:24:04 +00:00
|
|
|
DecodeNybble1TableFlipped::
|
2014-05-31 08:22:15 +00:00
|
|
|
dn $f, $7
|
|
|
|
dn $3, $b
|
|
|
|
dn $1, $9
|
|
|
|
dn $d, $5
|
|
|
|
dn $0, $8
|
|
|
|
dn $c, $4
|
|
|
|
dn $e, $6
|
|
|
|
dn $2, $a
|
|
|
|
|
|
|
|
; combines the two loaded chunks with xor (the chunk loaded second is the destination). The source chunk is differeintial decoded beforehand.
|
2016-06-12 00:24:04 +00:00
|
|
|
XorSpriteChunks::
|
2014-05-31 08:22:15 +00:00
|
|
|
xor a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosX], a
|
|
|
|
ld [wSpriteCurPosY], a
|
2014-05-31 08:22:15 +00:00
|
|
|
call ResetSpriteBufferPointers
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr] ; points to buffer 1 or 2, depending on flags
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld h, a
|
|
|
|
call SpriteDifferentialDecode ; decode buffer 1 or 2, depending on flags
|
|
|
|
call ResetSpriteBufferPointers
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr] ; source buffer, points to buffer 1 or 2, depending on flags
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtr+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld h, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtrCached] ; destination buffer, points to buffer 2 or 1, depending on flags
|
2014-05-31 08:22:15 +00:00
|
|
|
ld e, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtrCached+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld d, a
|
|
|
|
.xorChunksLoop
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteFlipped]
|
2014-05-31 08:22:15 +00:00
|
|
|
and a
|
|
|
|
jr z, .notFlipped
|
|
|
|
push de
|
|
|
|
ld a, [de]
|
|
|
|
ld b, a
|
|
|
|
swap a
|
|
|
|
and $f
|
|
|
|
call ReverseNybble ; if flipped reverse the nybbles in the destination buffer
|
|
|
|
swap a
|
|
|
|
ld c, a
|
|
|
|
ld a, b
|
|
|
|
and $f
|
|
|
|
call ReverseNybble
|
|
|
|
or c
|
|
|
|
pop de
|
|
|
|
ld [de], a
|
|
|
|
.notFlipped
|
|
|
|
ld a, [hli]
|
|
|
|
ld b, a
|
|
|
|
ld a, [de]
|
|
|
|
xor b
|
|
|
|
ld [de], a
|
|
|
|
inc de
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteCurPosY]
|
2014-05-31 08:22:15 +00:00
|
|
|
inc a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosY], a ; go to next row
|
2014-05-31 08:22:15 +00:00
|
|
|
ld b, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteHeight]
|
2014-05-31 08:22:15 +00:00
|
|
|
cp b
|
|
|
|
jr nz, .xorChunksLoop ; test if column finished
|
|
|
|
xor a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosY], a
|
|
|
|
ld a, [wSpriteCurPosX]
|
2014-05-31 08:22:15 +00:00
|
|
|
add $8
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosX], a ; go to next column
|
2014-05-31 08:22:15 +00:00
|
|
|
ld b, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteWidth]
|
2014-05-31 08:22:15 +00:00
|
|
|
cp b
|
|
|
|
jr nz, .xorChunksLoop ; test if all columns finished
|
|
|
|
xor a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteCurPosX], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ret
|
|
|
|
|
|
|
|
; reverses the bits in the nybble given in register a
|
2016-06-12 00:24:04 +00:00
|
|
|
ReverseNybble::
|
2014-05-31 08:22:15 +00:00
|
|
|
ld de, NybbleReverseTable
|
|
|
|
add e
|
|
|
|
ld e, a
|
|
|
|
jr nc, .asm_283f
|
|
|
|
inc d
|
|
|
|
.asm_283f
|
|
|
|
ld a, [de]
|
|
|
|
ret
|
|
|
|
|
2015-08-31 02:38:41 +00:00
|
|
|
; resets sprite buffer pointers to buffer 1 and 2, depending on wSpriteLoadFlags
|
2016-06-12 00:24:04 +00:00
|
|
|
ResetSpriteBufferPointers::
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteLoadFlags]
|
2014-05-31 08:22:15 +00:00
|
|
|
bit 0, a
|
|
|
|
jr nz, .buffer2Selected
|
2015-08-31 03:15:32 +00:00
|
|
|
ld de, sSpriteBuffer1
|
|
|
|
ld hl, sSpriteBuffer2
|
2014-05-31 08:22:15 +00:00
|
|
|
jr .storeBufferPointers
|
|
|
|
.buffer2Selected
|
2015-08-31 03:15:32 +00:00
|
|
|
ld de, sSpriteBuffer2
|
|
|
|
ld hl, sSpriteBuffer1
|
2014-05-31 08:22:15 +00:00
|
|
|
.storeBufferPointers
|
|
|
|
ld a, l
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtr], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, h
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtr+1], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, e
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtrCached], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, d
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtrCached+1], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ret
|
|
|
|
|
|
|
|
; maps each nybble to its reverse
|
2016-06-12 00:24:04 +00:00
|
|
|
NybbleReverseTable::
|
2014-05-31 08:22:15 +00:00
|
|
|
db $0, $8, $4, $c, $2, $a, $6 ,$e, $1, $9, $5, $d, $3, $b, $7 ,$f
|
|
|
|
|
|
|
|
; combines the two loaded chunks with xor (the chunk loaded second is the destination). Both chunks are differeintial decoded beforehand.
|
2016-06-12 00:24:04 +00:00
|
|
|
UnpackSpriteMode2::
|
2014-05-31 08:22:15 +00:00
|
|
|
call ResetSpriteBufferPointers
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteFlipped]
|
2014-05-31 08:22:15 +00:00
|
|
|
push af
|
|
|
|
xor a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteFlipped], a ; temporarily clear flipped flag for decoding the destination chunk
|
|
|
|
ld a, [wSpriteOutputPtrCached]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld l, a
|
2015-08-31 02:38:41 +00:00
|
|
|
ld a, [wSpriteOutputPtrCached+1]
|
2014-05-31 08:22:15 +00:00
|
|
|
ld h, a
|
|
|
|
call SpriteDifferentialDecode
|
|
|
|
call ResetSpriteBufferPointers
|
|
|
|
pop af
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteFlipped], a
|
2014-05-31 08:22:15 +00:00
|
|
|
jp XorSpriteChunks
|
|
|
|
|
|
|
|
; stores hl into the output pointers
|
2016-06-12 00:24:04 +00:00
|
|
|
StoreSpriteOutputPointer::
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, l
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtr], a
|
|
|
|
ld [wSpriteOutputPtrCached], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ld a, h
|
2015-08-31 02:38:41 +00:00
|
|
|
ld [wSpriteOutputPtr+1], a
|
|
|
|
ld [wSpriteOutputPtrCached+1], a
|
2014-05-31 08:22:15 +00:00
|
|
|
ret
|