Skip to content

Commit

Permalink
- Fix conflict with software audio mixing.
Browse files Browse the repository at this point in the history
- Fix issue when a buffer underflow condition occurs in The Legend of Zelda: Majora's Mask.
  • Loading branch information
Extrems committed Jul 6, 2020
1 parent 6cb905a commit 119295b
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
19 changes: 16 additions & 3 deletions cube/patches/alt/emulator.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,30 +361,41 @@ static sample_t (*AXOutBuffer)[160] = OSCachedToUncached(__AXOutBuffer);
static int AXOutFrame = 0;

static uint32_t DSP_EMU[15] = {0};
static int dsp_aimar_count = 0;

static void dsp_read(unsigned index, uint32_t *value)
{
*value = ((uint16_t *)DSP)[index];
switch (index) {
case 24:
case 25:
*value = ((uint16_t *)DSP)[index];
dsp_aimar_count--;
break;
default:
*value = ((uint16_t *)DSP)[index];
}
}

static void dsp_write(unsigned index, uint16_t value)
{
switch (index) {
case 24:
((uint16_t *)DSP_EMU)[index] = value & 0x3FF;
dsp_aimar_count++;
break;
case 25:
((uint16_t *)DSP_EMU)[index] = value & 0xFFE0;
dsp_aimar_count++;
break;
case 27:
((uint16_t *)DSP_EMU)[index] = value;

if (value & 0x8000) {
if ((value & 0x8000) && dsp_aimar_count >= 0) {
void *buffer = OSPhysicalToUncached(DSP_EMU[12]);
int length = (DSP_EMU[13] & 0x7FFF) << 5;
int count = length / sizeof(sample_t);

if (length == sizeof(*AXOutBuffer))
if (length <= sizeof(*AXOutBuffer))
buffer = memcpy(AXOutBuffer[AXOutFrame ^= 1], buffer, length);

if ((AI[0] & 0b0000001) && fifo_size() >= length) {
Expand All @@ -408,6 +419,8 @@ static void dsp_write(unsigned index, uint16_t value)
DSP[12] = DSP_EMU[12];
DSP[13] = DSP_EMU[13];
}

dsp_aimar_count = 0;
break;
default:
DSP[index] = value;
Expand Down
26 changes: 26 additions & 0 deletions cube/swiss/source/patcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,16 @@ u32 _dvdgettransferredsize[] = {
0x4E800020 // blr
};

u32 _aigetdmastartaddr[] = {
0x3C60CC00, // lis r3, 0xCC00
0x38635000, // addi r3, r3, 0x5000
0xA0830030, // lhz r4, 0x0030 (r3)
0xA0030032, // lhz r0, 0x0032 (r3)
0x54030434, // rlwinm r3, r0, 0, 16, 26
0x5083819E, // rlwimi r3, r4, 16, 6, 15
0x4E800020 // blr
};

u32 _gxpeekz_a[] = {
0x546013BA, // clrlslwi r0, r3, 16, 2
0x6400C800, // oris r0, r0, 0xC800
Expand Down Expand Up @@ -949,6 +959,8 @@ int Patch_Hypervisor(u32 *data, u32 length, int dataType)
{ 44, 12, 2, 3, 1, 6, NULL, 0, "AIInitDMAD" },
{ 34, 8, 4, 2, 0, 5, NULL, 0, "AIInitDMA" }
};
FuncPattern AIGetDMAStartAddrSig =
{ 7, 2, 0, 0, 0, 0, NULL, 0, "AIGetDMAStartAddr" };
FuncPattern GXPeekZSigs[3] = {
{ 10, 1, 1, 0, 0, 1, NULL, 0, "GXPeekZ A" },
{ 10, 1, 1, 0, 0, 1, NULL, 0, "GXPeekZ B" }, // SN Systems ProDG
Expand Down Expand Up @@ -1010,6 +1022,8 @@ int Patch_Hypervisor(u32 *data, u32 length, int dataType)
PPCHaltSig.offsetFoundAt = i;
else if (!memcmp(data + i, _dvdgettransferredsize, sizeof(_dvdgettransferredsize)))
DVDGetTransferredSizeSig.offsetFoundAt = i;
else if (!memcmp(data + i, _aigetdmastartaddr, sizeof(_aigetdmastartaddr)))
AIGetDMAStartAddrSig.offsetFoundAt = i;
else if (!memcmp(data + i, _gxpeekz_a, sizeof(_gxpeekz_a)))
GXPeekZSigs[0].offsetFoundAt = i;
else if (!memcmp(data + i, _gxpeekz_b, sizeof(_gxpeekz_b)))
Expand Down Expand Up @@ -4367,6 +4381,18 @@ int Patch_Hypervisor(u32 *data, u32 length, int dataType)
}
}

if ((i = AIGetDMAStartAddrSig.offsetFoundAt)) {
u32 *AIGetDMAStartAddr = Calc_ProperAddress(data, dataType, i * sizeof(u32));

if (AIGetDMAStartAddr) {
if (devices[DEVICE_CUR]->emulate & EMU_AUDIO_STREAMING)
data[i + 0] = 0x3C600C00; // lis r3, 0x0C00

print_gecko("Found:[%s] @ %08X\n", AIGetDMAStartAddrSig.Name, AIGetDMAStartAddr);
patched++;
}
}

for (j = 0; j < sizeof(GXPeekZSigs) / sizeof(FuncPattern); j++)
if (GXPeekZSigs[j].offsetFoundAt) break;

Expand Down

0 comments on commit 119295b

Please sign in to comment.