User:Kmeisthax/Findings/2013/4/23/Tilemap compression
< User:Kmeisthax | Findings
A2A and A34 get called to decompress compressed tilemaps from one of two banks into one of two hardware tilemaps.
ROM:00000A2A ; =============== S U B R O U T I N E ======================================= ROM:00000A2A ROM:00000A2A ; Decompress a tilemap into the hardware's FIRST or SECOND tilemap. ROM:00000A2A ; ROM:00000A2A ; Params: ROM:00000A2A ; ROM:00000A2A ; A = What source bank to read from (bank table is at B18) ROM:00000A2A ; ROM:00000A2A ; BC = XY coordinates to write to ROM:00000A2A ; E = Index of compressed tilemap to uncompress (map table is at BANKxx:4000) ROM:00000A2A ROM:00000A2A RunLengthDecompTMap0: ; CODE XREF: Banked_RunLengthDecompTMap0+A�p ROM:00000A2A push af ROM:00000A2B ld hl, $9800 ROM:00000A2E xor a ROM:00000A2F ld [CurrentTilemap], a ROM:00000A32 jr _RLDecomp_Start ROM:00000A34 ; --------------------------------------------------------------------------- ROM:00000A34 ROM:00000A34 RunLengthDecompTMap1: ROM:00000A34 push af ROM:00000A35 ld hl, $9C00 ROM:00000A38 ld a, 1 ROM:00000A3A ld [CurrentTilemap], a ROM:00000A3D ROM:00000A3D _RLDecomp_Start: ; CODE XREF: RunLengthDecompTMap0+8�j ROM:00000A3D pop af ROM:00000A3E push hl ROM:00000A3F push de ROM:00000A40 ld hl, $B18 ROM:00000A43 ld d, 0 ROM:00000A45 ld e, a ROM:00000A46 add hl, de ROM:00000A47 ld a, [hl] ROM:00000A48 rst $10 ROM:00000A49 pop de ROM:00000A4A pop hl ROM:00000A4B push de ROM:00000A4C ld a, b ROM:00000A4D and $1F ROM:00000A4F ld b, a ROM:00000A50 ld a, c ROM:00000A51 and $1F ROM:00000A53 ld c, a ; B &= 0x1F ROM:00000A54 ld d, 0 ROM:00000A56 ld e, c ROM:00000A57 sla e ROM:00000A59 rl d ROM:00000A5B sla e ROM:00000A5D rl d ROM:00000A5F sla e ROM:00000A61 rl d ROM:00000A63 sla e ROM:00000A65 rl d ROM:00000A67 sla e ROM:00000A69 rl d ; DE = (C & 0x1F) * 32 ROM:00000A6B ld c, b ROM:00000A6C ld b, 0 ; BC = (int)B ROM:00000A6E add hl, bc ROM:00000A6F add hl, de ; essentially HL = &tilemap[B][C] ROM:00000A70 pop de ; restore argument DE ROM:00000A71 push hl ROM:00000A72 ld hl, $4000 ROM:00000A75 ld d, 0 ROM:00000A77 sla e ROM:00000A79 rl d ROM:00000A7B add hl, de ROM:00000A7C ldi a, [hl] ROM:00000A7D ld d, [hl] ROM:00000A7E ld e, a ; DE = ptr_table[E] ROM:00000A7F pop hl ROM:00000A80 ld b, h ROM:00000A81 ld c, l ; BC = &tilemap[B][C] ROM:00000A82 ld a, [de] ROM:00000A83 cp $FF ROM:00000A85 ret z ; FF = return ROM:00000A86 and 3 ROM:00000A88 jr z, _copyLinesMode ; if lower 2 bits are 0 ROM:00000A8A jr _rllDecompressMode ; if lower 2 bits are not 0 ROM:00000A8C ; --------------------------------------------------------------------------- ROM:00000A8C ROM:00000A8C _copyLinesMode: ; CODE XREF: RunLengthDecompTMap0+5E�j ROM:00000A8C ; RunLengthDecompTMap0+74�j ... ROM:00000A8C inc de ROM:00000A8D ld a, [de] ROM:00000A8E cp $FF ROM:00000A90 ret z ; FF = return (again) ROM:00000A91 cp $FE ; '¦' ROM:00000A93 jr z, _newLine ; FE = newline ROM:00000A95 call vmempoke ; increment+write A to HL after blanking ROM:00000A98 ld a, [CurrentTilemap] ROM:00000A9B call TileMapLineWrap ; Wrap HL within tilemap A AND within a particular line. ROM:00000A9B ; (Assumes you will increment HL between calls) ROM:00000A9E jr _copyLinesMode ; Loop until FF or FE ROM:00000AA0 ; --------------------------------------------------------------------------- ROM:00000AA0 ROM:00000AA0 _newLine: ; CODE XREF: RunLengthDecompTMap0+69�j ROM:00000AA0 push de ROM:00000AA1 ld de, $20 ; ' ' ROM:00000AA4 ld h, b ROM:00000AA5 ld l, c ROM:00000AA6 add hl, de ROM:00000AA7 ld a, [CurrentTilemap] ROM:00000AAA call TileMapWrap ; Wrap HL within tilemap A. ROM:00000AAA ; ROM:00000AAA ; Clobbers: A (with result H) ROM:00000AAD ld b, h ROM:00000AAE ld c, l ROM:00000AAF pop de ROM:00000AB0 jr _copyLinesMode ROM:00000AB2 ; --------------------------------------------------------------------------- ROM:00000AB2 ROM:00000AB2 _rllDecompressMode: ; CODE XREF: RunLengthDecompTMap0+60�j ROM:00000AB2 ; RunLengthDecompTMap0+AD�j ... ROM:00000AB2 inc de ROM:00000AB3 ld a, [de] ROM:00000AB4 cp $FF ROM:00000AB6 ret z ; FF = return ROM:00000AB7 ld a, [de] ; useless read ROM:00000AB8 and $C0 ; '+' ROM:00000ABA cp $C0 ; '+' ROM:00000ABC jp z, _cmd3 ; Command 3: DecBytes ROM:00000ABC ; ROM:00000ABC ; Write a sequence of up to 65 decreasing bytes, ROM:00000ABC ; starting from the following byte. ROM:00000ABC ; (Lower 6 bits of command are count minus 2.) ROM:00000ABF cp $80 ; 'Ç' ROM:00000AC1 jp z, _cmd2 ; Command 2: IncBytes ROM:00000AC1 ; ROM:00000AC1 ; Write a sequence of up to 65 increasing bytes, ROM:00000AC1 ; starting from the following byte. ROM:00000AC1 ; (Lower 6 bits of command are count minus 2.) ROM:00000AC4 cp $40 ; '@' ROM:00000AC6 jp z, _cmd1 ; Command 1: RepeatBytes ROM:00000AC6 ; ROM:00000AC6 ; Repeat the following byte upto 65 times. ROM:00000AC6 ; (Lower 6 bits of command are count minus 2) ROM:00000AC9 push bc ; Command 0: CopyBytes ROM:00000AC9 ; ROM:00000AC9 ; Copy up to 64 bytes following the command. ROM:00000AC9 ; (Lower bits of command byte are count minus 1) ROM:00000ACA ld a, [de] ROM:00000ACB inc a ROM:00000ACC ld b, a ROM:00000ACD ROM:00000ACD _cmd0loop: ; CODE XREF: RunLengthDecompTMap0+A9�j ROM:00000ACD inc de ROM:00000ACE ld a, [de] ROM:00000ACF call vmempoke ; increment+write A to HL after blanking ROM:00000AD2 dec b ROM:00000AD3 jp nz, _cmd0loop ROM:00000AD6 pop bc ROM:00000AD7 jp _rllDecompressMode ROM:00000ADA ; --------------------------------------------------------------------------- ROM:00000ADA ROM:00000ADA _cmd1: ; CODE XREF: RunLengthDecompTMap0+9C�j ROM:00000ADA push bc ; Command 1: RepeatBytes ROM:00000ADA ; ROM:00000ADA ; Repeat the following byte upto 65 times. ROM:00000ADA ; (Lower 6 bits of command are count minus 2) ROM:00000ADB ld a, [de] ROM:00000ADC and $3F ; '?' ROM:00000ADE add a, 2 ROM:00000AE0 ld b, a ROM:00000AE1 inc de ROM:00000AE2 ld a, [de] ROM:00000AE3 ROM:00000AE3 _cmd1Repeat: ; CODE XREF: RunLengthDecompTMap0+BD�j ROM:00000AE3 call vmempoke ; increment+write A to HL after blanking ROM:00000AE6 dec b ROM:00000AE7 jp nz, _cmd1Repeat ROM:00000AEA pop bc ROM:00000AEB jp _rllDecompressMode ROM:00000AEE ; --------------------------------------------------------------------------- ROM:00000AEE ROM:00000AEE _cmd2: ; CODE XREF: RunLengthDecompTMap0+97�j ROM:00000AEE push bc ; Command 2: IncBytes ROM:00000AEE ; ROM:00000AEE ; Write a sequence of up to 65 increasing bytes, ROM:00000AEE ; starting from the following byte. ROM:00000AEE ; (Lower 6 bits of command are count minus 2.) ROM:00000AEF ld a, [de] ROM:00000AF0 and $3F ; '?' ROM:00000AF2 add a, 2 ROM:00000AF4 ld b, a ROM:00000AF5 inc de ROM:00000AF6 ld a, [de] ROM:00000AF7 ROM:00000AF7 _cmd2RepeatAndIncrement: ; CODE XREF: RunLengthDecompTMap0+D2�j ROM:00000AF7 call vmempoke ; increment+write A to HL after blanking ROM:00000AFA inc a ROM:00000AFB dec b ROM:00000AFC jp nz, _cmd2RepeatAndIncrement ROM:00000AFF pop bc ROM:00000B00 jp _rllDecompressMode ROM:00000B03 ; --------------------------------------------------------------------------- ROM:00000B03 ROM:00000B03 _cmd3: ; CODE XREF: RunLengthDecompTMap0+92�j ROM:00000B03 push bc ; Command 3: DecBytes ROM:00000B03 ; ROM:00000B03 ; Write a sequence of up to 65 decreasing bytes, ROM:00000B03 ; starting from the following byte. ROM:00000B03 ; (Lower 6 bits of command are count minus 2.) ROM:00000B04 ROM:00000B04 loc_B04: ; DATA XREF: ROM:0002E3D0�w ROM:00000B04 ld a, [de] ; (ignore the DATA XREF, IDA can't banks) ROM:00000B05 and $3F ; '?' ROM:00000B07 add a, 2 ROM:00000B09 ld b, a ROM:00000B0A inc de ROM:00000B0B ld a, [de] ROM:00000B0C ROM:00000B0C _cmd3RepeatAndDecrement: ; CODE XREF: RunLengthDecompTMap0+E7�j ROM:00000B0C call vmempoke ; increment+write A to HL after blanking ROM:00000B0F dec a ROM:00000B10 dec b ROM:00000B11 jp nz, _cmd3RepeatAndDecrement ROM:00000B14 pop bc ROM:00000B15 jp _rllDecompressMode ROM:00000B15 ; End of function RunLengthDecompTMap0 ROM:00000B15 ROM:00000B15 ; --------------------------------------------------------------------------- ROM:00000B18 db $3E ; > ; Bank 3E: Compressed tilemaps ROM:00000B19 db $3F ; ? ; Bank 3F: Compressed tile attributes