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) - GB Video: Draw SGB border pieces that overlap GB graphics (fixes mgba.io/i/1339)
- GBA: Improve timing when not booting from BIOS - 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: 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 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: Redo internal key input, enabling edge-based key IRQs
- GBA I/O: Disable open bus behavior on invalid register 06A - 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_RAM:
case REGION_WORKING_IRAM: case REGION_WORKING_IRAM:
case REGION_VRAM: case REGION_VRAM:
useStall = true;
_unLz77(gba, immediate == GBA_SWI_LZ77_UNCOMP_WRAM ? 1 : 2); _unLz77(gba, immediate == GBA_SWI_LZ77_UNCOMP_WRAM ? 1 : 2);
break; break;
} }
@ -644,7 +645,8 @@ static void _unLz77(struct GBA* gba, int width) {
struct ARMCore* cpu = gba->cpu; struct ARMCore* cpu = gba->cpu;
uint32_t source = cpu->gprs[0]; uint32_t source = cpu->gprs[0];
uint32_t dest = cpu->gprs[1]; 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 // 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 int blockheader = 0; // Some compilers warn if this isn't set, even though it's trivially provably always set
source += 4; source += 4;
@ -654,14 +656,17 @@ static void _unLz77(struct GBA* gba, int width) {
int byte; int byte;
int halfword = 0; int halfword = 0;
while (remaining > 0) { while (remaining > 0) {
cycles += 14;
if (blocksRemaining) { if (blocksRemaining) {
cycles += 18;
if (blockheader & 0x80) { if (blockheader & 0x80) {
// Compressed // 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; source += 2;
disp = dest - (block & 0x0FFF) - 1; disp = dest - (block & 0x0FFF) - 1;
bytes = (block >> 12) + 3; bytes = (block >> 12) + 3;
while (bytes--) { while (bytes--) {
cycles += 10;
if (remaining) { if (remaining) {
--remaining; --remaining;
} else { } else {
@ -673,35 +678,36 @@ static void _unLz77(struct GBA* gba, int width) {
} }
} }
if (width == 2) { 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) { if (dest & 1) {
byte >>= (disp & 1) * 8; byte >>= (disp & 1) * 8;
halfword |= byte << 8; halfword |= byte << 8;
cpu->memory.store16(cpu, dest ^ 1, halfword, 0); cpu->memory.store16(cpu, dest ^ 1, halfword, &cycles);
} else { } else {
byte >>= (disp & 1) * 8; byte >>= (disp & 1) * 8;
halfword = byte & 0xFF; halfword = byte & 0xFF;
} }
cycles += 4;
} else { } else {
byte = cpu->memory.load8(cpu, disp, 0); byte = cpu->memory.load8(cpu, disp, &cycles);
cpu->memory.store8(cpu, dest, byte, 0); cpu->memory.store8(cpu, dest, byte, &cycles);
} }
++disp; ++disp;
++dest; ++dest;
} }
} else { } else {
// Uncompressed // Uncompressed
byte = cpu->memory.load8(cpu, source, 0); byte = cpu->memory.load8(cpu, source, &cycles);
++source; ++source;
if (width == 2) { if (width == 2) {
if (dest & 1) { if (dest & 1) {
halfword |= byte << 8; halfword |= byte << 8;
cpu->memory.store16(cpu, dest ^ 1, halfword, 0); cpu->memory.store16(cpu, dest ^ 1, halfword, &cycles);
} else { } else {
halfword = byte; halfword = byte;
} }
} else { } else {
cpu->memory.store8(cpu, dest, byte, 0); cpu->memory.store8(cpu, dest, byte, &cycles);
} }
++dest; ++dest;
--remaining; --remaining;
@ -709,7 +715,7 @@ static void _unLz77(struct GBA* gba, int width) {
blockheader <<= 1; blockheader <<= 1;
--blocksRemaining; --blocksRemaining;
} else { } else {
blockheader = cpu->memory.load8(cpu, source, 0); blockheader = cpu->memory.load8(cpu, source, &cycles);
++source; ++source;
blocksRemaining = 8; blocksRemaining = 8;
} }
@ -717,6 +723,7 @@ static void _unLz77(struct GBA* gba, int width) {
cpu->gprs[0] = source; cpu->gprs[0] = source;
cpu->gprs[1] = dest; cpu->gprs[1] = dest;
cpu->gprs[3] = 0; cpu->gprs[3] = 0;
gba->biosStall = cycles;
} }
DECL_BITFIELD(HuffmanNode, uint8_t); 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, 0x48, 0x03, 0x00, 0x00, 0x48, 0x03, 0x00, 0x00,
0x48, 0x03, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0xa8, 0x02, 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, 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, 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: BgAffineSet:
ObjAffineSet: ObjAffineSet:
BitUnPack: BitUnPack:
Lz77UnCompWram:
Lz77UnCompVram:
HuffmanUnComp: HuffmanUnComp:
RlUnCompWram: RlUnCompWram:
RlUnCompVram: RlUnCompVram:
@ -308,6 +306,8 @@ DivArm:
Sqrt: Sqrt:
ArcTan: ArcTan:
ArcTan2: ArcTan2:
Lz77UnCompWram:
Lz77UnCompVram:
StallCall: StallCall:
subs r11, #4 subs r11, #4