mirror of https://github.com/mgba-emu/mgba.git
GBA BIOS: Implement BitUnPack
This commit is contained in:
parent
e5a9f8a030
commit
8fd14f40c0
1
CHANGES
1
CHANGES
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue