1; ************************************************** 2; SMSlib - C programming library for the SMS/GG 3; ( part of devkitSMS - github.com/sverx/devkitSMS ) 4; ************************************************** 5 6INCLUDE "SMSlib_private.inc" 7 8SECTION bss_clib 9SECTION bss_SMSlib 10 11__SMSlib_PSGaidenDecompBufferAddr: 12 defw 0 13 14SECTION code_clib 15SECTION code_SMSlib 16 17PUBLIC asm_SMSlib_loadPSGaidencompressedTiles 18 19asm_SMSlib_loadPSGaidencompressedTiles: 20 21 ; Phantasy Star Gaiden Tile Decoder 22 ; taken from http://www.smspower.org/Development/PhantasyStarGaidenTileDecoder 23 24 ; void SMS_loadPSGaidencompressedTiles (void *src, unsigned int tilefrom) 25 ; 26 ; enter : de = void *src 27 ; hl = unsigned int tilefrom 28 ; 29 ; uses : af, bc, de, hl, ix, iy 30 31 add hl,hl 32 add hl,hl 33 add hl,hl 34 add hl,hl 35 add hl,hl 36 37 set 6,h 38 INCLUDE "SMS_CRT0_RST08.inc" 39 40 ld hl,-32 41 add hl,sp 42 ld sp,hl 43 44 ld (__SMSlib_PSGaidenDecompBufferAddr),hl 45 46 ex de,hl 47 48 ld c,(hl) ; bc = number of tiles 49 inc hl 50 ld b,(hl) 51 inc hl 52 53 push hl ; ld ix,hl 54 pop ix 55 56_DecompressTile: 57 push bc ; save number of tiles 58 ld b,4 ; count 4 bitplanes 59 ld de,(__SMSlib_PSGaidenDecompBufferAddr) ; write to de 60 ld c,(ix) ; c = encoding information for 4 bitplanes 61 inc ix 62 63_DecompressBitplane: 64 rlc c ; %0x = all bits either 0 or 1 65 jr nc,_AllTheSame 66 rlc c ; %11 = raw data 67 jr c,_RawData 68 69_Compressed: 70 ld a,(ix) ; get method byte 71 inc ix 72 73 ex de,hl ; get bitplane, if it is referring to one 74 ld d,a 75 and 0x03 76 add a,a ; calculate address of that bitplane 77 add a,a ; = buffer + bitplane * 8 78 add a,a 79 ld e,a 80 ld a,d ; get method byte back 81 ld d,0x00 82 ld iy,(__SMSlib_PSGaidenDecompBufferAddr) 83 add iy,de ; now iy points to the referred to bitplane 84 ex de,hl 85 86 ; now check the method byte 87 cp 0x03 ; %000000pp 88 jr c,_DuplicateBitplane 89 cp 0x10 90 jr c,_CommonValue 91 cp 0x13 ; %000100pp 92 jr c,_DuplicateBitplaneInvert 93 cp 0x20 94 jr c,_CommonValue 95 cp 0x23 ; %001000pp 96 jr c,_DuplicateBitplanePartial 97 cp 0x40 98 jr c,_CommonValue 99 cp 0x43 ; %010000pp 100 jr c,_DuplicateBitplanePartialInvert 101 ; fall through 102 103_CommonValue: 104 ld h,a ; h = bitmask 105 ld l,(ix) ; l = common value 106 inc ix 107 jr _OutputCommonValue 108 109_RawData: 110 ld h,0x00 ; empty bitmask; no common value 111 jr _OutputCommonValue 112 113_AllTheSame: 114 rlc c ; get next bit into carry 115 sbc a,a ; will make $00 if carry = 0, $ff if it is 1 116 ld l,a ; that is the common value 117 ld h,0xff ; full bitmask 118 ; fall through 119 120_OutputCommonValue: 121 push bc 122 ld b,8 ; loop counter 123_loop1: 124 ld a,l ; get common value 125 rlc h ; get bit out of bitmask 126 jr c,_skip1 ; if 1, use the common value 127 ld a,(ix) ; else get it from (ix++) 128 inc ix 129_skip1: 130 ld (de),a ; write to dest 131 inc de 132 djnz _loop1 ; loop over 8 bytes 133 pop bc 134 jr _BitplaneDone 135 136_DuplicateBitplane: 137 ld hl,0xff00 ; full copy bitmask, empty inversion bitmask 138 jr _OutputDuplicate 139 140_DuplicateBitplaneInvert: 141 ld hl,0xffff ; full copy bitmask, full inversion bitmask 142 jr _OutputDuplicate 143 144_DuplicateBitplanePartial: 145 ld h,(ix) ; get copy bitmask 146 ld l,0x00 ; empty inversion bitmask 147 inc ix 148 jr _OutputDuplicate 149 150_DuplicateBitplanePartialInvert: 151 ld h,(ix) ; get copy bitmask 152 ld l,0xff ; full inversion bitmask 153 inc ix 154 ; fall through 155 156_OutputDuplicate: 157 push bc 158 ld b,8 ; loop counter 159_loop2: 160 ld a,(iy) ; read byte to copy 161 inc iy 162 xor l ; apply inversion mask 163 rlc h ; get bit out of bitmask 164 jr c,_skip2 ; if 1, use the copied value 165 ld a,(ix) ; else get it from (ix++) 166 inc ix 167_skip2: 168 ld (de),a ; write to dest 169 inc de 170 djnz _loop2 ; loop over 8 bytes 171 pop bc 172 ; fall through 173 174_BitplaneDone: 175 dec b ; decrement bitplane counter 176 jp nz,_DecompressBitplane ; loop if not zero 177 178_OutputTileToVRAM: 179 ld de,8 ; we are interleaving every 8th byte 180 ld c,e ; counter for the interleaving run 181 ld hl,(__SMSlib_PSGaidenDecompBufferAddr) ; point at data to write 182 183_outLoop: 184 ld b,4 ; there are 4 bytes to interleave 185 push hl 186_inLoop: 187 ld a,(hl) ; read byte 188 out (VDPDataPort),a ; write to vram 189 add hl,de ; skip 8 bytes 190 djnz _inLoop 191 pop hl 192 inc hl ; next interleaving run 193 dec c 194 jr nz,_outLoop 195 196 pop bc 197 dec bc ; next tile 198 ld a,b 199 or c 200 jp nz,_DecompressTile 201 202 ld hl,32 203 add hl,sp 204 ld sp,hl 205 206 ret 207