From f7ddc3a2b618d2889f16cba366f4bdfe02207c63 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sat, 11 May 2013 18:22:23 -0700 Subject: [PATCH] Implement RLUnCompWram/RLUnCompVram --- src/gba/gba-bios.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/gba/gba-bios.c b/src/gba/gba-bios.c index 84f89ab76..51b186e82 100644 --- a/src/gba/gba-bios.c +++ b/src/gba/gba-bios.c @@ -8,6 +8,7 @@ #include static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest); +static void _unRl(struct GBAMemory* memory, uint32_t source, uint8_t* dest); static void _RegisterRamReset(struct GBA* gba) { uint32_t registers = gba->cpu.gprs[0]; @@ -233,6 +234,23 @@ void GBASwi16(struct ARMBoard* board, int immediate) { break; } break; + case 0x14: + case 0x15: + switch (gba->cpu.gprs[1] >> BASE_OFFSET) { + case REGION_WORKING_RAM: + _unRl(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 1))]); + break; + case REGION_WORKING_IRAM: + _unRl(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->memory.iwram)[(gba->cpu.gprs[1] & (SIZE_WORKING_IRAM - 1))]); + break; + case REGION_VRAM: + _unRl(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & 0x0001FFFF)]); + break; + default: + GBALog(GBA_LOG_WARN, "Bad RL destination"); + break; + } + break; case 0x1F: _MidiKey2Freq(gba); break; @@ -283,3 +301,40 @@ static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest) { } } } + +static void _unRl(struct GBAMemory* memory, uint32_t source, uint8_t* dest) { + source = source & 0xFFFFFFFC; + int remaining = (GBALoad32(&memory->d, source, 0) & 0xFFFFFF00) >> 8; + int padding = (4 - remaining) & 0x3; + // We assume the signature byte (0x30) is correct + int blockheader; + int block; + uint32_t sPointer = source + 4; + uint8_t* dPointer = dest; + while (remaining > 0) { + blockheader = GBALoadU8(&memory->d, sPointer++, 0); + if (blockheader & 0x80) { + // Compressed + blockheader &= 0x7F; + blockheader += 3; + block = GBALoadU8(&memory->d, sPointer++, 0); + while (blockheader-- && remaining) { + --remaining; + *dPointer = block; + ++dPointer; + } + } else { + // Uncompressed + blockheader++; + while (blockheader-- && remaining) { + --remaining; + *dPointer = GBALoadU8(&memory->d, sPointer++, 0); + ++dPointer; + } + } + } + while (padding--) { + *dPointer = 0; + ++dPointer; + } +}