mirror of https://github.com/mgba-emu/mgba.git
Implement LZ77 decompression
This commit is contained in:
parent
cf9a7224a3
commit
e83936152d
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue