mirror of https://github.com/mgba-emu/mgba.git
GBA BIOS: Initial HLE timing estimation of UnLz77 functions (fixes #2141)
This commit is contained in:
parent
d1bc394ca3
commit
6f4398a3b9
1
CHANGES
1
CHANGES
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue