This patch adds those missing HLE BIOS functions for sound driver: https://sourceforge.net/p/vbam/bugs/24/
It is utilized by Phantasy Star Collection at intro. I don't know any other games using this BIOS driver, so I just implemented the parts that Phantasy Star Collection uses. This patch is far away from perfect yet. Sound quality is not the same as with original BIOS. Also code is horrible to read, since I just kept translating arm instructions to C without thinking too much. Got it done quickly so if anyone has keen interest on continuing from here. Patch by Juha Laukkanen
This commit is contained in:
parent
1e1b1cc35c
commit
a9aa25a56f
|
@ -2342,6 +2342,28 @@ void CPUSoftwareInterrupt(int comment)
|
|||
else
|
||||
soundResume();
|
||||
break;
|
||||
case 0x1A:
|
||||
BIOS_SndDriverInit();
|
||||
SWITicks = 252000;
|
||||
break;
|
||||
case 0x1B:
|
||||
BIOS_SndDriverMode();
|
||||
SWITicks = 280000;
|
||||
break;
|
||||
case 0x1C:
|
||||
BIOS_SndDriverMain();
|
||||
SWITicks = 11050;//avg
|
||||
break;
|
||||
case 0x1D:
|
||||
BIOS_SndDriverVSync();
|
||||
SWITicks = 44;
|
||||
break;
|
||||
case 0x1E:
|
||||
BIOS_SndChannelClear();
|
||||
break;
|
||||
case 0x28:
|
||||
BIOS_SndDriverVSyncOff();
|
||||
break;
|
||||
case 0x1F:
|
||||
BIOS_MidiKey2Freq();
|
||||
break;
|
||||
|
|
703
src/gba/bios.cpp
703
src/gba/bios.cpp
|
@ -1108,6 +1108,709 @@ void BIOS_Sqrt()
|
|||
#endif
|
||||
}
|
||||
|
||||
#define ADBITS_MASK 0x3FU
|
||||
u32 const base1 = 0x040000C0;
|
||||
u32 const base2 = 0x04000080;
|
||||
|
||||
static bool BIOS_SndDriver_ba4(u32 r0, u32 r4r12) // 0xba4
|
||||
{
|
||||
if (r4r12)
|
||||
{
|
||||
r4r12 = r4r12 & ~0xFE000000;
|
||||
r4r12 += r0;
|
||||
if (!((r0 & 0x0E000000) && (r4r12 & 0x0E000000)))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void BIOS_SndDriver_b4c(u32 r0, u32 r1, u32 r2) // 0xb4c
|
||||
{
|
||||
// @r4
|
||||
u32 r4 = 4 * r2 & 0x7FFFFF;
|
||||
bool ok = BIOS_SndDriver_ba4(r0, r4); // aka b9c
|
||||
|
||||
#if 0
|
||||
int v3; // r4@1
|
||||
int v4; // r0@1
|
||||
int v5; // r1@1
|
||||
int v6; // r2@1
|
||||
char v7; // zf@1
|
||||
signed int v8; // r5@2
|
||||
int v9; // r5@4
|
||||
int v10; // r3@6
|
||||
int v11; // r3@10
|
||||
unsigned int v12; // r4@11
|
||||
unsigned short v13; // r3@13
|
||||
#endif
|
||||
|
||||
// 0b56
|
||||
if ( !ok )
|
||||
{
|
||||
u32 r5 = 0; //v8
|
||||
if ( r2 >= (1<<(27-1)) ) //v6
|
||||
{
|
||||
r5 = r1 + r4;
|
||||
if ( r2 >= (1<<(25-1)) )
|
||||
{
|
||||
u32 r3 = CPUReadMemory(r0);
|
||||
while ( r1 < r5 )
|
||||
{
|
||||
CPUWriteMemory(r1, r3);
|
||||
r1 += 4;
|
||||
}
|
||||
}
|
||||
else // @todo 0b6e
|
||||
{
|
||||
#if 0
|
||||
while ( v5 < v9 )
|
||||
{
|
||||
v11 = *(_DWORD *)v4;
|
||||
v4 += 4;
|
||||
*(_DWORD *)v5 = v11;
|
||||
v5 += 4;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else // @todo 0b78
|
||||
{
|
||||
#if 0
|
||||
v12 = (unsigned int)v3 >> 1;
|
||||
if ( __CFSHR__(v6, 25) )
|
||||
{
|
||||
v13 = *(_WORD *)v4;
|
||||
while ( v8 < (signed int)v12 )
|
||||
{
|
||||
*(_WORD *)(v5 + v8) = v13;
|
||||
v8 += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while ( v8 < (signed int)v12 )
|
||||
{
|
||||
*(_WORD *)(v5 + v8) = *(_WORD *)(v4 + v8);
|
||||
v8 += 2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// 0x0b96
|
||||
}
|
||||
|
||||
static s32 BIOS_SndDriver_3e4(u32 const r0a, u32 const r1a) // 0x3e4
|
||||
{
|
||||
s32 r0 = r1a;
|
||||
s32 r1 = r0a;
|
||||
u32 v5 = r0 & 0x80000000;
|
||||
s32 r12;
|
||||
s32 r2;
|
||||
bool gtr;
|
||||
|
||||
if ( (r1 & 0x80000000 & 0x80000000) != 0 )
|
||||
r1 = -r1;
|
||||
r12 = r0; //v5 ^ (r0 >> 32);
|
||||
if ( r0 < 0 )
|
||||
r0 = -r0;
|
||||
r2 = r1;
|
||||
|
||||
do
|
||||
{
|
||||
gtr = (r2 >= r0 >> 1);
|
||||
if ( r2 <= r0 >> 1 )
|
||||
r2 *= 2;
|
||||
} while ( !gtr );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
v5 += (r0 >= (u32)r2) + v5;
|
||||
if ( r0 >= (u32)r2 )
|
||||
r0 -= r2;
|
||||
if ( r2 == r1 )
|
||||
break;
|
||||
r2 = (u32)r2 >> 1;
|
||||
}
|
||||
|
||||
if ( !(r12 << 1) )
|
||||
return -v5;
|
||||
else
|
||||
return v5;
|
||||
}
|
||||
|
||||
static void BIOS_SndDriverSub1(u32 p1) // 0x170a
|
||||
{
|
||||
u8 local1 = (p1 & 0x000F0000) >> 16; // param is r0
|
||||
u32 const puser1 = CPUReadMemory(0x3007FF0); // 7FC0 + 0x30
|
||||
|
||||
// Store something
|
||||
CPUWriteByte(puser1+8, local1);
|
||||
|
||||
u32 r0 = (0x31e8 + (local1 << 1)) - 0x20;
|
||||
|
||||
// @todo read from bios region
|
||||
if (r0 == 0x31D0)
|
||||
{
|
||||
r0 = 0xE0;
|
||||
}
|
||||
else if (r0 == 0x31E0)
|
||||
{
|
||||
r0 = 0x2C0;
|
||||
}
|
||||
else r0 = CPUReadHalfWord(r0+0x1E);
|
||||
CPUWriteMemory(puser1+0x10, r0);
|
||||
|
||||
u32 r1 = 0x630;
|
||||
u32 const r4 = r0;
|
||||
|
||||
// 0x172c
|
||||
r0 = BIOS_SndDriver_3e4(r0, r1);
|
||||
CPUWriteByte(puser1+0xB, r0);
|
||||
|
||||
u32 x = 0x91d1b * r4;
|
||||
r1 = x + 0x1388;
|
||||
r0 = 0x1388 << 1;
|
||||
r0 = BIOS_SndDriver_3e4(r0, r1);
|
||||
CPUWriteMemory(puser1+0x14, r0);
|
||||
|
||||
r1 = 1 << 24;
|
||||
r0 = BIOS_SndDriver_3e4(r0, r1) + 1;
|
||||
r0 /= 2;
|
||||
CPUWriteMemory(puser1+0x18, r0);
|
||||
|
||||
// 0x1750
|
||||
u32 r4basesnd = 0x4000100;
|
||||
r0 = r4;
|
||||
r1 = 0x44940;
|
||||
CPUWriteHalfWord(r4basesnd+2, 0);
|
||||
r0 = BIOS_SndDriver_3e4(r0, r1);
|
||||
r0 = (1<<16)-r0;
|
||||
CPUWriteHalfWord(r4basesnd+0, r0);
|
||||
|
||||
// sub 0x18c8 is unrolled here
|
||||
r1 = 0x5b << 9;
|
||||
CPUWriteHalfWord(base1+6 , r1);
|
||||
CPUWriteHalfWord(base1+12 , r1);
|
||||
|
||||
// 0x176a, @todo busy loop here
|
||||
r0 = 0x4000000;
|
||||
//do
|
||||
{
|
||||
r1 = CPUReadByte(r0+6);
|
||||
} //while (r1 != 0x9F);
|
||||
|
||||
CPUWriteHalfWord(r4basesnd+2, 0x80);
|
||||
}
|
||||
|
||||
void BIOS_SndDriverInit() // 0x166a
|
||||
{
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("SndDriverInit: WaveData=%08x mk=%08x fp=%08x\n",
|
||||
reg[0].I,
|
||||
reg[1].I,
|
||||
reg[2].I);
|
||||
}
|
||||
#endif
|
||||
|
||||
// 7FC0 + 0x30
|
||||
u32 const puser1 = 0x3007FF0;
|
||||
u32 const user1 = reg[0].I;
|
||||
|
||||
u32 base3 = 0x040000BC;
|
||||
//u32 base4 = 0x03007FF0;
|
||||
|
||||
CPUWriteHalfWord(base1+6 , 0);
|
||||
CPUWriteHalfWord(base1+12, 0);
|
||||
|
||||
CPUWriteHalfWord(base2+4, 0x8F);
|
||||
CPUWriteHalfWord(base2+2, 0xA90E);
|
||||
|
||||
u16 val9 = CPUReadHalfWord(base2+9);
|
||||
CPUWriteHalfWord(base2+9, val9&ADBITS_MASK); // DA?
|
||||
|
||||
CPUWriteMemory(base3+0, (user1 + 0x350)); //0x350, 640int
|
||||
CPUWriteMemory(base1+0, 0x40000A0);
|
||||
CPUWriteMemory(base1+8, 2224); //0x980
|
||||
CPUWriteMemory(base1+12, 0x40000A4);
|
||||
CPUWriteMemory(puser1, user1);
|
||||
|
||||
u32 const r2 = 0x050003EC;
|
||||
u32 const sp = reg[13].I; // 0x03003c98;
|
||||
CPUWriteMemory(sp, 0);
|
||||
BIOS_SndDriver_b4c(sp, user1, r2);
|
||||
|
||||
// 0x16b0
|
||||
CPUWriteByte(user1+0x6, 0x8);
|
||||
CPUWriteByte(user1+0x7, 0xF);
|
||||
CPUWriteMemory(user1+0x38, 0x2425);
|
||||
CPUWriteMemory(user1+0x28, 0x1709);
|
||||
CPUWriteMemory(user1+0x2C, 0x1709);
|
||||
CPUWriteMemory(user1+0x30, 0x1709);
|
||||
CPUWriteMemory(user1+0x3C, 0x1709);
|
||||
CPUWriteMemory(user1+0x34, 0x3738);
|
||||
|
||||
BIOS_SndDriverSub1(0x40000);
|
||||
|
||||
CPUWriteMemory(user1, 0x68736D53); // this ret is common among funcs
|
||||
}
|
||||
|
||||
void BIOS_SndDriverMode() //0x179c
|
||||
{
|
||||
u32 input = reg[0].I;
|
||||
u32 const puser1 = CPUReadMemory(0x3007FF0); // 7FC0 + 0x30
|
||||
u32 user1 = CPUReadMemory(puser1);
|
||||
|
||||
if ( user1 == 0x68736D53 )
|
||||
{
|
||||
CPUWriteMemory(puser1, (++user1)); // this guard is common for funcs, unify
|
||||
|
||||
// reverb values at bits 0...7
|
||||
u8 revb = (input & 0xFF);
|
||||
if ( revb )
|
||||
{
|
||||
revb>>=1; // shift out the 7th enable bit
|
||||
CPUWriteByte(puser1+5, revb);
|
||||
}
|
||||
// direct sound multi channels at bits 8...11
|
||||
u8 chc = (input & 0xF00)>>8;
|
||||
if ( chc > 0 )
|
||||
{
|
||||
CPUWriteByte(puser1+6, chc);
|
||||
u32 puser2 = puser1 + 7 + 0x49;
|
||||
int count=12;
|
||||
while (count--)
|
||||
{
|
||||
CPUWriteByte(puser2, 0);
|
||||
puser2+=0x40;
|
||||
}
|
||||
}
|
||||
// direct sound master volume at bits 12...15
|
||||
u8 chv = (input & 0xF000)>>12;
|
||||
if ( chv > 0 )
|
||||
{
|
||||
CPUWriteByte(puser1+7, chv);
|
||||
}
|
||||
// DA converter bits at bits 20...23
|
||||
u32 dab = (input & 0x00B00000);
|
||||
if ( dab )
|
||||
{
|
||||
dab &= 0x00300000;
|
||||
dab >>= 0xE;
|
||||
u8 adv = CPUReadByte(puser1+9) & ADBITS_MASK; // @todo verify offset
|
||||
dab |= adv;
|
||||
CPUWriteByte(puser1+9, dab);
|
||||
}
|
||||
// Playback frequency at bits 16...19
|
||||
u32 pbf = (input & 0x000F0000);
|
||||
if ( pbf )
|
||||
{
|
||||
// Modifies puser1/user1
|
||||
BIOS_SndDriverVSyncOff();
|
||||
|
||||
// another sub at 180c
|
||||
BIOS_SndDriverSub1(pbf);
|
||||
}
|
||||
CPUWriteMemory(puser1, (--user1));
|
||||
}
|
||||
}
|
||||
|
||||
void BIOS_SndDriverMain() // 0x1dc4 -> 0x08004024 phantasy star
|
||||
{
|
||||
//// Usually addr 0x2010928
|
||||
u32 const puser1 = CPUReadMemory(0x3007FF0); // 7FC0 + 0x30, //@+sp14
|
||||
u32 user1 = CPUReadMemory(puser1);
|
||||
|
||||
if ( user1 != 0x68736D53 )
|
||||
return;
|
||||
|
||||
// main
|
||||
CPUWriteMemory(puser1, (++user1)); // this guard is common for funcs, unify
|
||||
|
||||
int const user2 = CPUReadMemory(puser1 + 0x20);
|
||||
if ( user2 )
|
||||
{
|
||||
int const par1 = CPUReadMemory(puser1 + 0x24);
|
||||
// Call 0x2102 sub_16A8 - -> param r1
|
||||
}
|
||||
|
||||
int const userfunc = CPUReadMemory(puser1 + 0x28);
|
||||
switch (userfunc)
|
||||
{
|
||||
case 0x1709: //phantasy star
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
u32 const v2 = CPUReadMemory(puser1 + 0x10); //r8
|
||||
u8 const user4 = CPUReadByte(puser1+4) - 1;
|
||||
u32 user41 = 0;
|
||||
|
||||
if ( user4 > 0 )
|
||||
{
|
||||
user41 = CPUReadByte(puser1 + 0x0B);
|
||||
user41 -= user4;
|
||||
user41 *= v2;
|
||||
}
|
||||
|
||||
u32 r5;
|
||||
u32 const r5c = puser1 + 0x350 + user41; //r5 @sp+8
|
||||
int user6 = r5c + 0x630; //r6
|
||||
int user5 = CPUReadByte(puser1 + 0x5); //r3
|
||||
|
||||
if ( user5 )
|
||||
{
|
||||
// @todo 0x1e1a
|
||||
}
|
||||
else // 0x1e74
|
||||
{
|
||||
r5 = r5c;
|
||||
int count = v2>>4; //r1...v13
|
||||
if ( !(v2 >> 3) )
|
||||
{
|
||||
CPUWriteMemory(r5, 0);
|
||||
CPUWriteMemory(user6, 0);
|
||||
r5+=4; user6+=4;
|
||||
}
|
||||
if ( !(v2 >> 1) ) //0x1e7c
|
||||
{
|
||||
CPUWriteMemory(r5, 0);
|
||||
CPUWriteMemory(user6, 0);
|
||||
r5+=4; user6+=4;
|
||||
|
||||
CPUWriteMemory(r5, 0);
|
||||
CPUWriteMemory(user6, 0);
|
||||
r5+=4; user6+=4;
|
||||
}
|
||||
do // 0x1e8e
|
||||
{
|
||||
// @todo optimize this memset
|
||||
CPUWriteMemory(r5, 0);
|
||||
CPUWriteMemory(user6, 0);
|
||||
r5+=4; user6+=4;
|
||||
|
||||
CPUWriteMemory(r5, 0);
|
||||
CPUWriteMemory(user6, 0);
|
||||
r5+=4; user6+=4;
|
||||
|
||||
CPUWriteMemory(r5, 0);
|
||||
CPUWriteMemory(user6, 0);
|
||||
r5+=4; user6+=4;
|
||||
|
||||
CPUWriteMemory(r5, 0);
|
||||
CPUWriteMemory(user6, 0);
|
||||
r5+=4; user6+=4;
|
||||
|
||||
count -= 1;
|
||||
} while (count > 0);
|
||||
}
|
||||
|
||||
//0x1ea2
|
||||
u32 r4 = puser1; // apparenty ch ptr?
|
||||
int r9 = CPUReadMemory(r4+0x14);
|
||||
int r12 = CPUReadMemory(r4+0x18);
|
||||
u32 i = CPUReadByte(r4+0x6);
|
||||
|
||||
for (r4+=0x10; i > 0; i-- )
|
||||
{
|
||||
r4+=0x40;
|
||||
/*lbl_0x1eb0:*/
|
||||
u32 r3 = CPUReadMemory(r4+0x24);
|
||||
u8 r6 = CPUReadByte(r4);
|
||||
|
||||
if ( (r6 & 0xC7) == 0 ) // 0x1ebc
|
||||
continue; //goto lbl_20e4;
|
||||
if ( (r6 & 0x80) && ((r6 & 0x40) == 0) ) // 0x1ec4
|
||||
{
|
||||
r6 = 0x3;
|
||||
CPUWriteByte(r4, r6);
|
||||
CPUWriteMemory(r4+0x28, r3+0x10);
|
||||
|
||||
int r0t1 = CPUReadMemory(r3+0xC);
|
||||
CPUWriteMemory(r4+0x18, r0t1);
|
||||
|
||||
r5=0;
|
||||
CPUWriteByte(r4+0x9, 0);
|
||||
CPUWriteMemory(r4+0x1c, 0);
|
||||
|
||||
u8 r2a = CPUReadByte(r3+0x3); // seems to be LABEL_20e4
|
||||
if ((r2a & 0xC0)) // 1ee4
|
||||
{
|
||||
|
||||
}
|
||||
goto lbl_0x1f46;
|
||||
}
|
||||
else
|
||||
{
|
||||
//lbl_0x1eee:
|
||||
r5 = CPUReadByte(r4+0x9); //
|
||||
if ( (r6 & 0x4) != 0) // @todo 0x1ef4
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if ( (r6 & 0x40) != 0) // @todo 0x1f08
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if ( (r6 & 0x03) == 2) // 0x1f2a
|
||||
{
|
||||
u8 mul1 = CPUReadByte(r4+0x5);
|
||||
r5*=mul1;
|
||||
r5>>=8;
|
||||
|
||||
u8 cmp1 = CPUReadByte(r4+0x6);
|
||||
if (r5 <= cmp1)
|
||||
{
|
||||
r5=cmp1;
|
||||
// @todo beq @ 0x1f3a -> ??
|
||||
r6--;
|
||||
CPUWriteByte(r4, r6);
|
||||
}
|
||||
}
|
||||
else if ( (r6 & 0x03) == 3) // 0x1f44
|
||||
{
|
||||
lbl_0x1f46: //@todo check if there is really another path to here
|
||||
u8 add1 = CPUReadByte(r4+0x4);
|
||||
r5+=add1;
|
||||
|
||||
if (r5>=0xff)
|
||||
{
|
||||
r6--;
|
||||
r5=0xff;
|
||||
CPUWriteByte(r4, r6);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
//lbl_0x1f54:
|
||||
CPUWriteByte(r4+0x9, r5);
|
||||
|
||||
u32 user0 = CPUReadByte(puser1+0x7); // @sp+10
|
||||
user0++;
|
||||
user0*=r5;
|
||||
r5=user0>>4;
|
||||
|
||||
user0 = CPUReadByte(r4+0x2);
|
||||
user0*=r5;
|
||||
user0>>=8;
|
||||
CPUWriteByte(r4+0xA, user0);
|
||||
|
||||
user0 = CPUReadByte(r4+0x3);
|
||||
user0*=r5;
|
||||
user0>>=8;
|
||||
CPUWriteByte(r4+0xB, user0);
|
||||
|
||||
user0 = r6&0x10;
|
||||
if ( user0 != 0) // @todo 0x1f76
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
r5 = r5c; // @todo below r5 is used and updated
|
||||
u32 r2 = CPUReadMemory(r4+0x18);
|
||||
r3 = CPUReadMemory(r4+0x28);
|
||||
|
||||
u32 r8 = v2;
|
||||
|
||||
u8 r10 = CPUReadByte(r4+0xA);
|
||||
u8 r11 = CPUReadByte(r4+0xB);
|
||||
u8 r0a = CPUReadByte(r4+0x1);
|
||||
if ((r0a & 8)) //@todo 0x1fa8
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
u32 r7 = CPUReadMemory(r4+0x1c);
|
||||
u32 r14 = CPUReadMemory(r4+0x20);
|
||||
|
||||
lbl_0x2004:// LABEL_52:
|
||||
while ( r7 >= 4 * r9 )
|
||||
{
|
||||
if ( r2 <= 4 )// @todo 0x2008, no phant
|
||||
goto lbl_204c;
|
||||
r2 -= 4;
|
||||
r3 += 4;
|
||||
r7 -= 4 * r9;
|
||||
}
|
||||
if ( r7 >= 2 * r9 )
|
||||
{
|
||||
if ( r2 <= 2 ) // @todo 0x2008, no phant
|
||||
goto lbl_204c;
|
||||
r2 -= 2;
|
||||
r3 += 2;
|
||||
r7 -= 2 * r9;
|
||||
}
|
||||
if ( r7 < r9 )
|
||||
goto lbl_207c;
|
||||
do
|
||||
{
|
||||
lbl_204c: // LABEL_59:
|
||||
--r2;
|
||||
if ( r2 )
|
||||
{
|
||||
++r3;
|
||||
}
|
||||
else
|
||||
{
|
||||
r2 = user0; //0x2054
|
||||
if ( r2 )
|
||||
{
|
||||
r3 = CPUReadMemory(reg[13].I+0xC); // @todo stack pull 0x205c
|
||||
}
|
||||
else
|
||||
{
|
||||
CPUWriteByte(r4, r2);
|
||||
goto lbl_20e4;
|
||||
}
|
||||
}
|
||||
r7 -= r9;
|
||||
} while ( r7 >= r9 );
|
||||
lbl_207c:
|
||||
while ( 1 )
|
||||
{
|
||||
s32 r0a = CPUReadByte(r3);
|
||||
s32 r1a = CPUReadByte(r3+0x1);
|
||||
|
||||
r1a-=r0a;
|
||||
s32 r6a = r1a*(s32)r7;
|
||||
r1a = r6a * r12; // 208c
|
||||
r6a = (r0a + ((s8)(r1a>>23)));
|
||||
|
||||
r1a = r6a * (s32)r11;
|
||||
|
||||
r0a = CPUReadByte(r5 + 0x630);
|
||||
r0a = (r0a + ((s8)(r1a>>8)));
|
||||
CPUWriteByte(r5 + 0x630, r0a);
|
||||
r1a = r6a * (s32)r10;
|
||||
r0a = CPUReadByte(r5);
|
||||
r0a = (r0a + ((s8)(r1a>>8)));
|
||||
CPUWriteByte(r5++, r0a); //ptr inc +1 not +4
|
||||
|
||||
r7+=r14;
|
||||
--r8;
|
||||
if ( !r8 )
|
||||
break;
|
||||
if ( r7 >= r9 )
|
||||
goto lbl_0x2004;
|
||||
}
|
||||
|
||||
CPUWriteMemory(r4+0x1c, r7);
|
||||
//lbl_20cc:
|
||||
CPUWriteMemory(r4+0x18, r2);
|
||||
CPUWriteMemory(r4+0x28, r3);
|
||||
}
|
||||
lbl_20e4:
|
||||
(void)r5;
|
||||
}
|
||||
|
||||
// 0x20EE
|
||||
CPUWriteMemory(puser1, 0x68736D53); // this guard is common for funcs, unify
|
||||
}
|
||||
|
||||
// fully implemented @ 0x210c
|
||||
void BIOS_SndDriverVSync()
|
||||
{
|
||||
u32 const puser1 = CPUReadMemory(0x3007FF0); // @todo some sound area, make it common.
|
||||
u32 const user1 = CPUReadMemory(puser1);
|
||||
|
||||
if ( user1 == 0x68736D53 )
|
||||
{
|
||||
u8 v1 = CPUReadByte(puser1+4);
|
||||
s8 v1i = v1-1;
|
||||
CPUWriteByte(puser1+4, v1i);
|
||||
if ( v1 <= 1 )
|
||||
{
|
||||
u8 v2 = CPUReadByte(puser1+0xB); //11
|
||||
u32 base2 = 0x040000D2;
|
||||
CPUWriteByte(puser1+4, v2);
|
||||
|
||||
CPUWriteHalfWord(base1+0x6 , 0);
|
||||
CPUWriteHalfWord(base2, 0);
|
||||
CPUWriteHalfWord(base1+0x6 , 0xB600);
|
||||
CPUWriteHalfWord(base2, 0xB600); //-18944
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BIOS_SndDriverVSyncOff() // 0x1878
|
||||
{
|
||||
u32 const puser1 = CPUReadMemory(0x3007FF0); // 7FC0 + 0x30
|
||||
u32 user1 = CPUReadMemory(puser1);
|
||||
|
||||
if ( user1 == 0x68736D53 || user1 == 0x68736D54 )
|
||||
{
|
||||
CPUWriteMemory(puser1, (++user1)); // this guard is common for funcs, unify
|
||||
|
||||
CPUWriteHalfWord(base1+0x6 , 0);
|
||||
CPUWriteHalfWord(base1+0x12 , 0);
|
||||
CPUWriteByte(puser1+4, 0);
|
||||
|
||||
u32 r1 = puser1+0x350;
|
||||
u32 r2 = 0x05000318;
|
||||
u32 sp = reg[13].I; //0x03003c94;
|
||||
|
||||
CPUWriteMemory(sp, 0);
|
||||
BIOS_SndDriver_b4c(sp, r1, r2);
|
||||
|
||||
user1 = CPUReadMemory(puser1); // 0x18aa
|
||||
CPUWriteMemory(puser1, (--user1)); // this ret is common among funcs
|
||||
}
|
||||
//0x18b0
|
||||
}
|
||||
|
||||
// This functions is verified but lacks proper register settings before calling user func
|
||||
// it might be that user func modifies or uses those?
|
||||
// r7 should be puser1, r6 should be flags, ....
|
||||
void BIOS_SndChannelClear() //0x1824
|
||||
{
|
||||
u32 const puser1 = CPUReadMemory(0x3007FF0); // 7FC0 + 0x30
|
||||
u32 user1 = CPUReadMemory(puser1);
|
||||
|
||||
if ( user1 == 0x68736D53 )
|
||||
{
|
||||
CPUWriteMemory(puser1, (++user1));
|
||||
u32 puser2 = puser1 + 0x7 + 0x49;
|
||||
|
||||
int count=12;
|
||||
while (count--)
|
||||
{
|
||||
CPUWriteByte(puser2, 0);
|
||||
puser2+=0x40;
|
||||
}
|
||||
|
||||
reg[4].I = CPUReadMemory(puser1 + 0x1c); //r5 -> some user thing
|
||||
if ( reg[4].I != 0 )
|
||||
{
|
||||
reg[3].I = 1; // r4 -> channel counter?
|
||||
int puser4 = puser1 + 0x2c;
|
||||
//reg[0].I = reg[3].I = 1; // r0 & r4 => 1
|
||||
|
||||
while (reg[3].I <= 4)
|
||||
{
|
||||
// @todo does user func modify these?
|
||||
reg[0].I = reg[3].I << 24;
|
||||
reg[0].I >>= 24;
|
||||
|
||||
// Get ptr to user func
|
||||
reg[1].I = CPUReadMemory(puser4);
|
||||
|
||||
// @todo here we jump where r1 points; user func?
|
||||
// @todo might modify r6 also?
|
||||
|
||||
// After call routines
|
||||
reg[3].I += 1; // r4 -> channel counter?
|
||||
reg[4].I += 0x40;// r5 -> some user thing
|
||||
}
|
||||
CPUWriteByte(reg[4].I, 0); // terminating record?
|
||||
}
|
||||
CPUWriteMemory(puser1, 0x68736D53);
|
||||
}
|
||||
}
|
||||
|
||||
void BIOS_MidiKey2Freq()
|
||||
{
|
||||
#ifdef GBA_LOGGING
|
||||
|
|
|
@ -25,5 +25,11 @@ extern void BIOS_SoftReset();
|
|||
extern void BIOS_Sqrt();
|
||||
extern void BIOS_MidiKey2Freq();
|
||||
extern void BIOS_SndDriverJmpTableCopy();
|
||||
extern void BIOS_SndDriverInit();
|
||||
extern void BIOS_SndDriverMode();
|
||||
extern void BIOS_SndDriverMain();
|
||||
extern void BIOS_SndDriverVSync();
|
||||
extern void BIOS_SndDriverVSyncOff();
|
||||
extern void BIOS_SndChannelClear();
|
||||
|
||||
#endif // BIOS_H
|
||||
|
|
Loading…
Reference in New Issue