From fac82c2ca11dd9326f58ef0e2d110927e73c7c10 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 6 Jan 2015 23:07:59 -0800 Subject: [PATCH] GBA BIOS: Implement Diff8bitUnFilterWram and Diff16bitUnFilter --- CHANGES | 1 + src/gba/gba-bios.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/CHANGES b/CHANGES index 1397b8f68..74bb16aa2 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,7 @@ Features: - Support for games using the tilt sensor - Remappable shortcuts for keyboard and gamepad - Rewinding of emulation + - Implemented BIOS routines Diff8bitUnFilterWram, and Diff16bitUnFilter Bugfixes: - Qt: Fix issue with set frame sizes being the wrong height - Qt: Fix emulator crashing when full screen if a game is not running diff --git a/src/gba/gba-bios.c b/src/gba/gba-bios.c index ee7b95533..5227123a4 100644 --- a/src/gba/gba-bios.c +++ b/src/gba/gba-bios.c @@ -15,6 +15,7 @@ const uint32_t GBA_DS_BIOS_CHECKSUM = 0xBAAE1880; static void _unLz77(struct GBA* gba, uint32_t source, uint32_t dest, int width); static void _unHuffman(struct GBA* gba, uint32_t source, uint32_t dest); static void _unRl(struct GBA* gba, uint32_t source, uint32_t dest, int width); +static void _unFilter(struct GBA* gba, uint32_t source, uint32_t dest, int inwidth, int outwidth); static void _RegisterRamReset(struct GBA* gba) { uint32_t registers = gba->cpu->gprs[0]; @@ -212,6 +213,22 @@ void GBASwi16(struct ARMCore* cpu, int immediate) { break; } break; + case 0x16: + case 0x17: + case 0x18: + if (cpu->gprs[0] < BASE_WORKING_RAM) { + GBALog(gba, GBA_LOG_GAME_ERROR, "Bad UnFilter source"); + } + switch (cpu->gprs[1] >> BASE_OFFSET) { + default: + GBALog(gba, GBA_LOG_GAME_ERROR, "Bad UnFilter destination"); + case REGION_WORKING_RAM: + case REGION_WORKING_IRAM: + case REGION_VRAM: + _unFilter(gba, cpu->gprs[0], cpu->gprs[1], immediate == 0x18 ? 2 : 1, immediate == 0x16 ? 1 : 2); + break; + } + break; case 0x1F: _MidiKey2Freq(gba); break; @@ -438,3 +455,36 @@ static void _unRl(struct GBA* gba, uint32_t source, uint32_t dest, int width) { } } } + +static void _unFilter(struct GBA* gba, uint32_t source, uint32_t dest, int inwidth, int outwidth) { + struct ARMCore* cpu = gba->cpu; + source = source & 0xFFFFFFFC; + uint32_t header = cpu->memory.load32(cpu, source, 0); + int remaining = header >> 8; + // We assume the signature nybble (0x8) is correct + uint16_t halfword = 0; + uint16_t old = 0; + source += 4; + while (remaining > 0) { + if (inwidth == 1) { + halfword = cpu->memory.loadU8(cpu, source, 0); + } else { + halfword = cpu->memory.loadU16(cpu, source, 0); + } + halfword += old; + if (outwidth > inwidth) { + GBALog(gba, GBA_LOG_STUB, "Unimplemented Diff8bitUnFilterVram"); + } else { + if (outwidth == 1) { + halfword &= 0xFF; + cpu->memory.store8(cpu, dest, halfword, 0); + } else { + cpu->memory.store16(cpu, dest, halfword, 0); + } + old = halfword; + dest += outwidth; + } + source += inwidth; + --remaining; + } +}