GBA BIOS: Implement BitUnPack

This commit is contained in:
Jeffrey Pfau 2016-11-07 13:51:53 -08:00
parent e5a9f8a030
commit 8fd14f40c0
2 changed files with 78 additions and 0 deletions

View File

@ -30,6 +30,7 @@ Bugfixes:
- Qt: Fix Qt Multimedia audio driver on big endian
- GBA: Fix IRQs firing after already being cleared
- All: Fix fullscreen config option being ignored
- GBA BIOS: Implement BitUnPack
Misc:
- SDL: Remove scancode key input
- GBA Video: Clean up unused timers

View File

@ -20,6 +20,7 @@ static void _unLz77(struct GBA* gba, int width);
static void _unHuffman(struct GBA* gba);
static void _unRl(struct GBA* gba, int width);
static void _unFilter(struct GBA* gba, int inwidth, int outwidth);
static void _unBitPack(struct GBA* gba);
static void _SoftReset(struct GBA* gba) {
struct ARMCore* cpu = gba->cpu;
@ -385,6 +386,22 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
case 0xF:
_ObjAffineSet(gba);
break;
case 0x10:
if (cpu->gprs[0] < BASE_WORKING_RAM) {
mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack source");
break;
}
switch (cpu->gprs[1] >> BASE_OFFSET) {
default:
mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack destination");
// Fall through
case REGION_WORKING_RAM:
case REGION_WORKING_IRAM:
case REGION_VRAM:
_unBitPack(gba);
break;
}
break;
case 0x11:
case 0x12:
if (cpu->gprs[0] < BASE_WORKING_RAM) {
@ -736,3 +753,63 @@ static void _unFilter(struct GBA* gba, int inwidth, int outwidth) {
cpu->gprs[0] = source;
cpu->gprs[1] = dest;
}
static void _unBitPack(struct GBA* gba) {
struct ARMCore* cpu = gba->cpu;
uint32_t source = cpu->gprs[0];
uint32_t dest = cpu->gprs[1];
uint32_t info = cpu->gprs[2];
unsigned sourceLen = cpu->memory.load16(cpu, info, 0);
unsigned sourceWidth = cpu->memory.load8(cpu, info + 2, 0);
unsigned destWidth = cpu->memory.load8(cpu, info + 3, 0);
switch (sourceWidth) {
case 1:
case 2:
case 4:
case 8:
break;
default:
mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack source width: %u", sourceWidth);
return;
}
switch (destWidth) {
case 1:
case 2:
case 4:
case 8:
case 16:
case 32:
break;
default:
mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack destination width: %u", destWidth);
return;
}
uint32_t bias = cpu->memory.load32(cpu, info + 4, 0);
uint8_t in = 0;
uint32_t out = 0;
int bitsRemaining = 0;
int bitsEaten = 0;
while (sourceLen > 0) {
if (!bitsRemaining) {
in = cpu->memory.load8(cpu, source, 0);
bitsRemaining = 8;
++source;
--sourceLen;
}
unsigned scaled = in & ((1 << sourceWidth) - 1);
in >>= sourceWidth;
if (scaled || bias & 0x80000000) {
scaled += bias & 0x7FFFFFFF;
scaled &= (1 << destWidth) - 1;
}
bitsRemaining -= sourceWidth;
out |= scaled << bitsEaten;
bitsEaten += destWidth;
if (bitsEaten == 32) {
cpu->memory.store32(cpu, dest, out, 0);
bitsEaten = 0;
out = 0;
dest += 4;
}
}
}