Implement LZ77 decompression

This commit is contained in:
Jeffrey Pfau 2013-04-20 02:52:10 -07:00
parent cf9a7224a3
commit e83936152d
1 changed files with 47 additions and 0 deletions

View File

@ -3,6 +3,8 @@
#include "gba.h"
#include "gba-memory.h"
static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest);
static void _CpuSet(struct GBA* gba) {
uint32_t source = gba->cpu.gprs[0];
uint32_t dest = gba->cpu.gprs[1];
@ -78,6 +80,12 @@ void GBASwi16(struct ARMBoard* board, int immediate) {
case 0xC:
_FastCpuSet(gba);
break;
case 0x11:
_unLz77(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->memory.wram)[(gba->cpu.gprs[1] & (SIZE_WORKING_RAM - 1))]);
break;
case 0x12:
_unLz77(&gba->memory, gba->cpu.gprs[0], &((uint8_t*) gba->video.renderer->vram)[(gba->cpu.gprs[1] & (SIZE_VRAM - 1))]);
break;
default:
GBALog(GBA_LOG_STUB, "Stub software interrupt: %02x", immediate);
}
@ -86,3 +94,42 @@ void GBASwi16(struct ARMBoard* board, int immediate) {
void GBASwi32(struct ARMBoard* board, int immediate) {
GBASwi32(board, immediate >> 16);
}
static void _unLz77(struct GBAMemory* memory, uint32_t source, uint8_t* dest) {
int remaining = (GBALoad32(&memory->d, source) & 0xFFFFFF00) >> 8;
// We assume the signature byte (0x10) is correct
int blockheader;
uint32_t sPointer = source + 4;
uint8_t* dPointer = dest;
int blocksRemaining = 0;
int block;
uint8_t* disp;
int bytes;
while (remaining > 0) {
if (blocksRemaining) {
if (blockheader & 0x80) {
// Compressed
block = GBALoadU8(&memory->d, sPointer) | (GBALoadU8(&memory->d, sPointer + 1) << 8);
sPointer += 2;
disp = dPointer - (((block & 0x000F) << 8) | ((block & 0xFF00) >> 8)) - 1;
bytes = ((block & 0x00F0) >> 4) + 3;
while (bytes-- && remaining) {
--remaining;
*dPointer = *disp;
++disp;
++dPointer;
}
} else {
// Uncompressed
*dPointer = GBALoadU8(&memory->d, sPointer++);
++dPointer;
--remaining;
}
blockheader <<= 1;
--blocksRemaining;
} else {
blockheader = GBALoadU8(&memory->d, sPointer++);
blocksRemaining = 8;
}
}
}