[bios] Fix lz77 and add BIOS_SndDriverVsyncOn
The lz77 uncompresssion software BIOS implementation was exiting early when uncompressing data, if the overall length was larger than advertised in the function parameter. However, real GBA BIOS does read further than the advertised length, so we do here too. This fixes Advance Wars title screen. This also adds a SoundDriverVSyncOn implementation, silencing an error for some Shrek games, though they still cannot properly boot with an emulated BIOS. Fixes #789
This commit is contained in:
parent
4c8b54de89
commit
e26f807355
|
@ -2083,8 +2083,8 @@ void CPUSoftwareInterrupt(int comment)
|
||||||
case 0x02:
|
case 0x02:
|
||||||
#ifdef GBA_LOGGING
|
#ifdef GBA_LOGGING
|
||||||
if (systemVerbose & VERBOSE_SWI) {
|
if (systemVerbose & VERBOSE_SWI) {
|
||||||
/*log("Halt: (VCOUNT = %2d)\n",
|
log("Halt: (VCOUNT = %2d)\n",
|
||||||
VCOUNT);*/
|
VCOUNT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
holdState = true;
|
holdState = true;
|
||||||
|
@ -2094,8 +2094,8 @@ void CPUSoftwareInterrupt(int comment)
|
||||||
case 0x03:
|
case 0x03:
|
||||||
#ifdef GBA_LOGGING
|
#ifdef GBA_LOGGING
|
||||||
if (systemVerbose & VERBOSE_SWI) {
|
if (systemVerbose & VERBOSE_SWI) {
|
||||||
/*log("Stop: (VCOUNT = %2d)\n",
|
log("Stop: (VCOUNT = %2d)\n",
|
||||||
VCOUNT);*/
|
VCOUNT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
holdState = true;
|
holdState = true;
|
||||||
|
@ -2271,11 +2271,14 @@ void CPUSoftwareInterrupt(int comment)
|
||||||
case 0x1E:
|
case 0x1E:
|
||||||
BIOS_SndChannelClear();
|
BIOS_SndChannelClear();
|
||||||
break;
|
break;
|
||||||
|
case 0x1F:
|
||||||
|
BIOS_MidiKey2Freq();
|
||||||
|
break;
|
||||||
case 0x28:
|
case 0x28:
|
||||||
BIOS_SndDriverVSyncOff();
|
BIOS_SndDriverVSyncOff();
|
||||||
break;
|
break;
|
||||||
case 0x1F:
|
case 0x29:
|
||||||
BIOS_MidiKey2Freq();
|
BIOS_SndDriverVSyncOn();
|
||||||
break;
|
break;
|
||||||
case 0xE0:
|
case 0xE0:
|
||||||
case 0xE1:
|
case 0xE1:
|
||||||
|
|
126
src/gba/bios.cpp
126
src/gba/bios.cpp
|
@ -688,34 +688,18 @@ void BIOS_LZ77UnCompVram()
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
uint8_t d = CPUReadByte(source++);
|
uint8_t d = CPUReadByte(source++);
|
||||||
|
|
||||||
if (d) {
|
for (int i = 0; i < 8; i++) {
|
||||||
for (int i = 0; i < 8; i++) {
|
if (d & 0x80) {
|
||||||
if (d & 0x80) {
|
uint16_t data = CPUReadByte(source++) << 8;
|
||||||
uint16_t data = CPUReadByte(source++) << 8;
|
data |= CPUReadByte(source++);
|
||||||
data |= CPUReadByte(source++);
|
int length = (data >> 12) + 3;
|
||||||
int length = (data >> 12) + 3;
|
int offset = (data & 0x0FFF);
|
||||||
int offset = (data & 0x0FFF);
|
uint32_t windowOffset = dest + byteCount - offset - 1;
|
||||||
uint32_t windowOffset = dest + byteCount - offset - 1;
|
for (int i2 = 0; i2 < length; i2++) {
|
||||||
for (int i2 = 0; i2 < length; i2++) {
|
writeValue |= (CPUReadByte(windowOffset++) << byteShift);
|
||||||
writeValue |= (CPUReadByte(windowOffset++) << byteShift);
|
|
||||||
byteShift += 8;
|
|
||||||
byteCount++;
|
|
||||||
|
|
||||||
if (byteCount == 2) {
|
|
||||||
CPUWriteHalfWord(dest, DowncastU16(writeValue));
|
|
||||||
dest += 2;
|
|
||||||
byteCount = 0;
|
|
||||||
byteShift = 0;
|
|
||||||
writeValue = 0;
|
|
||||||
}
|
|
||||||
len--;
|
|
||||||
if (len == 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
writeValue |= (CPUReadByte(source++) << byteShift);
|
|
||||||
byteShift += 8;
|
byteShift += 8;
|
||||||
byteCount++;
|
byteCount++;
|
||||||
|
|
||||||
if (byteCount == 2) {
|
if (byteCount == 2) {
|
||||||
CPUWriteHalfWord(dest, DowncastU16(writeValue));
|
CPUWriteHalfWord(dest, DowncastU16(writeValue));
|
||||||
dest += 2;
|
dest += 2;
|
||||||
|
@ -724,29 +708,34 @@ void BIOS_LZ77UnCompVram()
|
||||||
writeValue = 0;
|
writeValue = 0;
|
||||||
}
|
}
|
||||||
len--;
|
len--;
|
||||||
if (len == 0)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
d <<= 1;
|
} else {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
writeValue |= (CPUReadByte(source++) << byteShift);
|
writeValue |= (CPUReadByte(source++) << byteShift);
|
||||||
byteShift += 8;
|
byteShift += 8;
|
||||||
byteCount++;
|
byteCount++;
|
||||||
if (byteCount == 2) {
|
if (byteCount == 2) {
|
||||||
CPUWriteHalfWord(dest, DowncastU16(writeValue));
|
CPUWriteHalfWord(dest, DowncastU16(writeValue));
|
||||||
dest += 2;
|
dest += 2;
|
||||||
byteShift = 0;
|
|
||||||
byteCount = 0;
|
byteCount = 0;
|
||||||
|
byteShift = 0;
|
||||||
writeValue = 0;
|
writeValue = 0;
|
||||||
}
|
}
|
||||||
len--;
|
len--;
|
||||||
if (len == 0)
|
}
|
||||||
return;
|
|
||||||
|
d <<= 1;
|
||||||
|
|
||||||
|
if (len <= 0) {
|
||||||
|
// This can happen if the parameter was incorrectly set. Real
|
||||||
|
// hardware does a buffer overflow so we do it here too.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reg[0].I = source;
|
||||||
|
reg[1].I = dest;
|
||||||
|
reg[3].I = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BIOS_LZ77UnCompWram()
|
void BIOS_LZ77UnCompWram()
|
||||||
|
@ -772,37 +761,35 @@ void BIOS_LZ77UnCompWram()
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
uint8_t d = CPUReadByte(source++);
|
uint8_t d = CPUReadByte(source++);
|
||||||
|
|
||||||
if (d) {
|
for (int i = 0; i < 8; i++) {
|
||||||
for (int i = 0; i < 8; i++) {
|
if (d & 0x80) {
|
||||||
if (d & 0x80) {
|
uint16_t data = CPUReadByte(source++) << 8;
|
||||||
uint16_t data = CPUReadByte(source++) << 8;
|
data |= CPUReadByte(source++);
|
||||||
data |= CPUReadByte(source++);
|
int length = (data >> 12) + 3;
|
||||||
int length = (data >> 12) + 3;
|
int offset = (data & 0x0FFF);
|
||||||
int offset = (data & 0x0FFF);
|
uint32_t windowOffset = dest - offset - 1;
|
||||||
uint32_t windowOffset = dest - offset - 1;
|
for (int i2 = 0; i2 < length; i2++) {
|
||||||
for (int i2 = 0; i2 < length; i2++) {
|
CPUWriteByte(dest++, CPUReadByte(windowOffset++));
|
||||||
CPUWriteByte(dest++, CPUReadByte(windowOffset++));
|
|
||||||
len--;
|
|
||||||
if (len == 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CPUWriteByte(dest++, CPUReadByte(source++));
|
|
||||||
len--;
|
len--;
|
||||||
if (len == 0)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
d <<= 1;
|
} else {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
CPUWriteByte(dest++, CPUReadByte(source++));
|
CPUWriteByte(dest++, CPUReadByte(source++));
|
||||||
len--;
|
len--;
|
||||||
if (len == 0)
|
}
|
||||||
return;
|
|
||||||
|
d <<= 1;
|
||||||
|
|
||||||
|
if (len <= 0) {
|
||||||
|
// This can happen if the parameter was incorrectly set. Real
|
||||||
|
// hardware does a buffer overflow so we do it here too.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reg[0].I = source;
|
||||||
|
reg[1].I = dest;
|
||||||
|
reg[3].I = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BIOS_ObjAffineSet()
|
void BIOS_ObjAffineSet()
|
||||||
|
@ -1695,6 +1682,13 @@ void BIOS_SndDriverVSync()
|
||||||
|
|
||||||
void BIOS_SndDriverVSyncOff() // 0x1878
|
void BIOS_SndDriverVSyncOff() // 0x1878
|
||||||
{
|
{
|
||||||
|
#ifdef GBA_LOGGING
|
||||||
|
if (systemVerbose & VERBOSE_SWI) {
|
||||||
|
log("SndDriverVSyncOff: (VCOUNT = %2d)\n",
|
||||||
|
VCOUNT);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t const puser1 = CPUReadMemory(0x3007FF0); // 7FC0 + 0x30
|
uint32_t const puser1 = CPUReadMemory(0x3007FF0); // 7FC0 + 0x30
|
||||||
uint32_t user1 = CPUReadMemory(puser1);
|
uint32_t user1 = CPUReadMemory(puser1);
|
||||||
|
|
||||||
|
@ -1718,6 +1712,20 @@ void BIOS_SndDriverVSyncOff() // 0x1878
|
||||||
//0x18b0
|
//0x18b0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BIOS_SndDriverVSyncOn()
|
||||||
|
{
|
||||||
|
#ifdef GBA_LOGGING
|
||||||
|
if (systemVerbose & VERBOSE_SWI) {
|
||||||
|
log("SndDriverVSyncOn: (VCOUNT = %2d)\n",
|
||||||
|
VCOUNT);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const uint16_t r1 = 0x8600; // 91 << 9
|
||||||
|
CPUWriteHalfWord(base1 + 0x6, r1);
|
||||||
|
CPUWriteHalfWord(base1 + 0x12, r1);
|
||||||
|
}
|
||||||
|
|
||||||
// This functions is verified but lacks proper register settings before calling user func
|
// This functions is verified but lacks proper register settings before calling user func
|
||||||
// it might be that user func modifies or uses those?
|
// it might be that user func modifies or uses those?
|
||||||
// r7 should be puser1, r6 should be flags, ....
|
// r7 should be puser1, r6 should be flags, ....
|
||||||
|
|
|
@ -30,6 +30,7 @@ extern void BIOS_SndDriverMode();
|
||||||
extern void BIOS_SndDriverMain();
|
extern void BIOS_SndDriverMain();
|
||||||
extern void BIOS_SndDriverVSync();
|
extern void BIOS_SndDriverVSync();
|
||||||
extern void BIOS_SndDriverVSyncOff();
|
extern void BIOS_SndDriverVSyncOff();
|
||||||
|
extern void BIOS_SndDriverVSyncOn();
|
||||||
extern void BIOS_SndChannelClear();
|
extern void BIOS_SndChannelClear();
|
||||||
|
|
||||||
#endif // BIOS_H
|
#endif // BIOS_H
|
||||||
|
|
Loading…
Reference in New Issue