GBA BIOS: Initial HLE timing estimation of UnLz77 functions (fixes #2141)

This commit is contained in:
Vicki Pfau 2022-01-22 17:38:50 -08:00
parent d1bc394ca3
commit 6f4398a3b9
4 changed files with 21 additions and 13 deletions

View File

@ -17,6 +17,7 @@ Emulation fixes:
- GB Video: Draw SGB border pieces that overlap GB graphics (fixes mgba.io/i/1339)
- GBA: Improve timing when not booting from BIOS
- GBA BIOS: Work around IRQ handling hiccup in Mario & Luigi (fixes mgba.io/i/1059)
- GBA BIOS: Initial HLE timing estimation of UnLz77 functions (fixes mgba.io/i/2141)
- GBA DMA: Fix DMA source direction bits being cleared (fixes mgba.io/i/2410)
- GBA I/O: Redo internal key input, enabling edge-based key IRQs
- GBA I/O: Disable open bus behavior on invalid register 06A

View File

@ -536,6 +536,7 @@ void GBASwi16(struct ARMCore* cpu, int immediate) {
case REGION_WORKING_RAM:
case REGION_WORKING_IRAM:
case REGION_VRAM:
useStall = true;
_unLz77(gba, immediate == GBA_SWI_LZ77_UNCOMP_WRAM ? 1 : 2);
break;
}
@ -644,7 +645,8 @@ static void _unLz77(struct GBA* gba, int width) {
struct ARMCore* cpu = gba->cpu;
uint32_t source = cpu->gprs[0];
uint32_t dest = cpu->gprs[1];
int remaining = (cpu->memory.load32(cpu, source, 0) & 0xFFFFFF00) >> 8;
int32_t cycles = 20;
int remaining = (cpu->memory.load32(cpu, source, &cycles) & 0xFFFFFF00) >> 8;
// We assume the signature byte (0x10) is correct
int blockheader = 0; // Some compilers warn if this isn't set, even though it's trivially provably always set
source += 4;
@ -654,14 +656,17 @@ static void _unLz77(struct GBA* gba, int width) {
int byte;
int halfword = 0;
while (remaining > 0) {
cycles += 14;
if (blocksRemaining) {
cycles += 18;
if (blockheader & 0x80) {
// Compressed
int block = cpu->memory.load8(cpu, source + 1, 0) | (cpu->memory.load8(cpu, source, 0) << 8);
int block = cpu->memory.load8(cpu, source + 1, &cycles) | (cpu->memory.load8(cpu, source, &cycles) << 8);
source += 2;
disp = dest - (block & 0x0FFF) - 1;
bytes = (block >> 12) + 3;
while (bytes--) {
cycles += 10;
if (remaining) {
--remaining;
} else {
@ -673,35 +678,36 @@ static void _unLz77(struct GBA* gba, int width) {
}
}
if (width == 2) {
byte = (int16_t) cpu->memory.load16(cpu, disp & ~1, 0);
byte = (int16_t) cpu->memory.load16(cpu, disp & ~1, &cycles);
if (dest & 1) {
byte >>= (disp & 1) * 8;
halfword |= byte << 8;
cpu->memory.store16(cpu, dest ^ 1, halfword, 0);
cpu->memory.store16(cpu, dest ^ 1, halfword, &cycles);
} else {
byte >>= (disp & 1) * 8;
halfword = byte & 0xFF;
}
cycles += 4;
} else {
byte = cpu->memory.load8(cpu, disp, 0);
cpu->memory.store8(cpu, dest, byte, 0);
byte = cpu->memory.load8(cpu, disp, &cycles);
cpu->memory.store8(cpu, dest, byte, &cycles);
}
++disp;
++dest;
}
} else {
// Uncompressed
byte = cpu->memory.load8(cpu, source, 0);
byte = cpu->memory.load8(cpu, source, &cycles);
++source;
if (width == 2) {
if (dest & 1) {
halfword |= byte << 8;
cpu->memory.store16(cpu, dest ^ 1, halfword, 0);
cpu->memory.store16(cpu, dest ^ 1, halfword, &cycles);
} else {
halfword = byte;
}
} else {
cpu->memory.store8(cpu, dest, byte, 0);
cpu->memory.store8(cpu, dest, byte, &cycles);
}
++dest;
--remaining;
@ -709,7 +715,7 @@ static void _unLz77(struct GBA* gba, int width) {
blockheader <<= 1;
--blocksRemaining;
} else {
blockheader = cpu->memory.load8(cpu, source, 0);
blockheader = cpu->memory.load8(cpu, source, &cycles);
++source;
blocksRemaining = 8;
}
@ -717,6 +723,7 @@ static void _unLz77(struct GBA* gba, int width) {
cpu->gprs[0] = source;
cpu->gprs[1] = dest;
cpu->gprs[3] = 0;
gba->biosStall = cycles;
}
DECL_BITFIELD(HuffmanNode, uint8_t);

View File

@ -26,7 +26,7 @@ const uint8_t hleBios[SIZE_BIOS] = {
0x48, 0x03, 0x00, 0x00, 0x48, 0x03, 0x00, 0x00, 0x48, 0x03, 0x00, 0x00,
0x48, 0x03, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00,
0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
0xb0, 0x01, 0x00, 0x00, 0x48, 0x03, 0x00, 0x00, 0x48, 0x03, 0x00, 0x00,
0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,

View File

@ -137,8 +137,6 @@ GetBiosChecksum:
BgAffineSet:
ObjAffineSet:
BitUnPack:
Lz77UnCompWram:
Lz77UnCompVram:
HuffmanUnComp:
RlUnCompWram:
RlUnCompVram:
@ -308,6 +306,8 @@ DivArm:
Sqrt:
ArcTan:
ArcTan2:
Lz77UnCompWram:
Lz77UnCompVram:
StallCall:
subs r11, #4