mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
Support the old AXWii version used in games like Wii Sports or Excite Truck
This commit is contained in:
parent
276c457bed
commit
60b43eb8d3
@ -50,8 +50,10 @@ void CUCode_AXWii::HandleCommandList()
|
||||
u16 addr2_hi, addr2_lo;
|
||||
u16 volume;
|
||||
|
||||
u32 pb_addr = 0;
|
||||
|
||||
// WARN_LOG(DSPHLE, "Command list:");
|
||||
// for (u32 i = 0; m_cmdlist[i] != CMD_END; ++i)
|
||||
// for (u32 i = 0; m_cmdlist[i] != CMD_END_OLD; ++i)
|
||||
// WARN_LOG(DSPHLE, "%04x", m_cmdlist[i]);
|
||||
// WARN_LOG(DSPHLE, "-------------");
|
||||
|
||||
@ -61,78 +63,160 @@ void CUCode_AXWii::HandleCommandList()
|
||||
{
|
||||
u16 cmd = m_cmdlist[curr_idx++];
|
||||
|
||||
switch (cmd)
|
||||
if (m_old_axwii)
|
||||
{
|
||||
// Some of these commands are unknown, or unused in this AX HLE.
|
||||
// We still need to skip their arguments using "curr_idx += N".
|
||||
|
||||
case CMD_SETUP:
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
SetupProcessing(HILO_TO_32(addr));
|
||||
break;
|
||||
|
||||
case CMD_ADD_TO_LR:
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
AddToLR(HILO_TO_32(addr));
|
||||
break;
|
||||
|
||||
case CMD_UNK_02: curr_idx += 2; break;
|
||||
case CMD_UNK_03: curr_idx += 2; break;
|
||||
|
||||
case CMD_PROCESS:
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
ProcessPBList(HILO_TO_32(addr));
|
||||
break;
|
||||
|
||||
case CMD_MIX_AUXA:
|
||||
case CMD_MIX_AUXB:
|
||||
case CMD_MIX_AUXC:
|
||||
volume = m_cmdlist[curr_idx++];
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
addr2_hi = m_cmdlist[curr_idx++];
|
||||
addr2_lo = m_cmdlist[curr_idx++];
|
||||
MixAUXSamples(cmd - CMD_MIX_AUXA, HILO_TO_32(addr), HILO_TO_32(addr2), volume);
|
||||
break;
|
||||
|
||||
// These two go together and manipulate some AUX buffers.
|
||||
case CMD_UNK_08: curr_idx += 13; break;
|
||||
case CMD_UNK_09: curr_idx += 13; break;
|
||||
|
||||
// TODO(delroth): figure this one out, it's used by almost every
|
||||
// game I've tested so far.
|
||||
case CMD_UNK_0A: curr_idx += 4; break;
|
||||
|
||||
case CMD_OUTPUT:
|
||||
volume = m_cmdlist[curr_idx++];
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
addr2_hi = m_cmdlist[curr_idx++];
|
||||
addr2_lo = m_cmdlist[curr_idx++];
|
||||
OutputSamples(HILO_TO_32(addr2), HILO_TO_32(addr), volume);
|
||||
break;
|
||||
|
||||
case CMD_UNK_0C: curr_idx += 5; break;
|
||||
|
||||
case CMD_WM_OUTPUT:
|
||||
switch (cmd)
|
||||
{
|
||||
u32 addresses[4] = {
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
};
|
||||
curr_idx += 8;
|
||||
OutputWMSamples(addresses);
|
||||
break;
|
||||
}
|
||||
// Some of these commands are unknown, or unused in this AX HLE.
|
||||
// We still need to skip their arguments using "curr_idx += N".
|
||||
|
||||
case CMD_END:
|
||||
end = true;
|
||||
break;
|
||||
case CMD_SETUP_OLD:
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
SetupProcessing(HILO_TO_32(addr));
|
||||
break;
|
||||
|
||||
case CMD_ADD_TO_LR_OLD:
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
AddToLR(HILO_TO_32(addr));
|
||||
break;
|
||||
|
||||
case CMD_UNK_02_OLD: curr_idx += 2; break;
|
||||
case CMD_UNK_03_OLD: curr_idx += 2; break;
|
||||
|
||||
case CMD_PB_ADDR_OLD:
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
pb_addr = HILO_TO_32(addr);
|
||||
break;
|
||||
|
||||
case CMD_PROCESS_OLD:
|
||||
ProcessPBList(pb_addr);
|
||||
break;
|
||||
|
||||
case CMD_MIX_AUXA_OLD:
|
||||
case CMD_MIX_AUXB_OLD:
|
||||
case CMD_MIX_AUXC_OLD:
|
||||
volume = m_cmdlist[curr_idx++];
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
addr2_hi = m_cmdlist[curr_idx++];
|
||||
addr2_lo = m_cmdlist[curr_idx++];
|
||||
MixAUXSamples(cmd - CMD_MIX_AUXA_OLD, HILO_TO_32(addr), HILO_TO_32(addr2), volume);
|
||||
break;
|
||||
|
||||
// These two go together and manipulate some AUX buffers.
|
||||
case CMD_UNK_09_OLD: curr_idx += 13; break;
|
||||
case CMD_UNK_0A_OLD: curr_idx += 13; break;
|
||||
|
||||
// TODO(delroth): figure this one out, it's used by almost every
|
||||
// game I've tested so far.
|
||||
case CMD_UNK_0B_OLD: curr_idx += 4; break;
|
||||
|
||||
case CMD_OUTPUT_OLD:
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
addr2_hi = m_cmdlist[curr_idx++];
|
||||
addr2_lo = m_cmdlist[curr_idx++];
|
||||
OutputSamples(HILO_TO_32(addr2), HILO_TO_32(addr), 0x8000);
|
||||
break;
|
||||
|
||||
case CMD_UNK_0D_OLD: curr_idx += 5; break;
|
||||
|
||||
case CMD_WM_OUTPUT_OLD:
|
||||
{
|
||||
u32 addresses[4] = {
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
};
|
||||
curr_idx += 8;
|
||||
OutputWMSamples(addresses);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_END_OLD:
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
// Some of these commands are unknown, or unused in this AX HLE.
|
||||
// We still need to skip their arguments using "curr_idx += N".
|
||||
|
||||
case CMD_SETUP:
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
SetupProcessing(HILO_TO_32(addr));
|
||||
break;
|
||||
|
||||
case CMD_ADD_TO_LR:
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
AddToLR(HILO_TO_32(addr));
|
||||
break;
|
||||
|
||||
case CMD_UNK_02: curr_idx += 2; break;
|
||||
case CMD_UNK_03: curr_idx += 2; break;
|
||||
|
||||
case CMD_PROCESS:
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
ProcessPBList(HILO_TO_32(addr));
|
||||
break;
|
||||
|
||||
case CMD_MIX_AUXA:
|
||||
case CMD_MIX_AUXB:
|
||||
case CMD_MIX_AUXC:
|
||||
volume = m_cmdlist[curr_idx++];
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
addr2_hi = m_cmdlist[curr_idx++];
|
||||
addr2_lo = m_cmdlist[curr_idx++];
|
||||
MixAUXSamples(cmd - CMD_MIX_AUXA, HILO_TO_32(addr), HILO_TO_32(addr2), volume);
|
||||
break;
|
||||
|
||||
// These two go together and manipulate some AUX buffers.
|
||||
case CMD_UNK_08: curr_idx += 13; break;
|
||||
case CMD_UNK_09: curr_idx += 13; break;
|
||||
|
||||
// TODO(delroth): figure this one out, it's used by almost every
|
||||
// game I've tested so far.
|
||||
case CMD_UNK_0A: curr_idx += 4; break;
|
||||
|
||||
case CMD_OUTPUT:
|
||||
volume = m_cmdlist[curr_idx++];
|
||||
addr_hi = m_cmdlist[curr_idx++];
|
||||
addr_lo = m_cmdlist[curr_idx++];
|
||||
addr2_hi = m_cmdlist[curr_idx++];
|
||||
addr2_lo = m_cmdlist[curr_idx++];
|
||||
OutputSamples(HILO_TO_32(addr2), HILO_TO_32(addr), volume);
|
||||
break;
|
||||
|
||||
case CMD_UNK_0C: curr_idx += 5; break;
|
||||
|
||||
case CMD_WM_OUTPUT:
|
||||
{
|
||||
u32 addresses[4] = {
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
};
|
||||
curr_idx += 8;
|
||||
OutputWMSamples(addresses);
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_END:
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -244,7 +328,8 @@ void CUCode_AXWii::GenerateVolumeRamp(u16* output, u16 vol1, u16 vol2, size_t nv
|
||||
}
|
||||
}
|
||||
|
||||
bool CUCode_AXWii::ExtractUpdatesFields(AXPBWii& pb, u16* num_updates, u16* updates)
|
||||
bool CUCode_AXWii::ExtractUpdatesFields(AXPBWii& pb, u16* num_updates, u16* updates,
|
||||
u32* updates_addr)
|
||||
{
|
||||
u16* pb_mem = (u16*)&pb;
|
||||
|
||||
@ -260,6 +345,8 @@ bool CUCode_AXWii::ExtractUpdatesFields(AXPBWii& pb, u16* num_updates, u16* upda
|
||||
u32 addr = HILO_TO_32(addr);
|
||||
u16* ptr = (u16*)HLEMemory_Get_Pointer(addr);
|
||||
|
||||
*updates_addr = addr;
|
||||
|
||||
// Copy the updates data and change the offset to match a PB without
|
||||
// updates data.
|
||||
u32 updates_count = num_updates[0] + num_updates[1] + num_updates[2];
|
||||
@ -276,11 +363,26 @@ bool CUCode_AXWii::ExtractUpdatesFields(AXPBWii& pb, u16* num_updates, u16* upda
|
||||
}
|
||||
|
||||
// Remove the updates data from the PB
|
||||
memmove(pb_mem + 41, pb_mem + 45, sizeof (pb) - 2 * 45);
|
||||
memmove(pb_mem + 41, pb_mem + 46, sizeof (pb) - 2 * 46);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CUCode_AXWii::ReinjectUpdatesFields(AXPBWii& pb, u16* num_updates, u32 updates_addr)
|
||||
{
|
||||
u16* pb_mem = (u16*)&pb;
|
||||
|
||||
// Make some space
|
||||
memmove(pb_mem + 46, pb_mem + 41, sizeof (pb) - 2 * 46);
|
||||
|
||||
// Reinsert previous values
|
||||
pb_mem[41] = num_updates[0];
|
||||
pb_mem[42] = num_updates[1];
|
||||
pb_mem[43] = num_updates[2];
|
||||
pb_mem[44] = updates_addr >> 16;
|
||||
pb_mem[45] = updates_addr & 0xFFFF;
|
||||
}
|
||||
|
||||
void CUCode_AXWii::ProcessPBList(u32 pb_addr)
|
||||
{
|
||||
AXPBWii pb;
|
||||
@ -315,7 +417,8 @@ void CUCode_AXWii::ProcessPBList(u32 pb_addr)
|
||||
|
||||
u16 num_updates[3];
|
||||
u16 updates[1024];
|
||||
if (ExtractUpdatesFields(pb, num_updates, updates))
|
||||
u32 updates_addr;
|
||||
if (ExtractUpdatesFields(pb, num_updates, updates, &updates_addr))
|
||||
{
|
||||
for (int curr_ms = 0; curr_ms < 3; ++curr_ms)
|
||||
{
|
||||
@ -328,6 +431,7 @@ void CUCode_AXWii::ProcessPBList(u32 pb_addr)
|
||||
for (u32 i = 0; i < sizeof (buffers.ptrs) / sizeof (buffers.ptrs[0]); ++i)
|
||||
buffers.ptrs[i] += 32;
|
||||
}
|
||||
ReinjectUpdatesFields(pb, num_updates, updates_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -52,8 +52,11 @@ protected:
|
||||
u16 m_last_main_volume;
|
||||
u16 m_last_aux_volumes[3];
|
||||
|
||||
// If needed, extract the updates related fields from a PB.
|
||||
bool ExtractUpdatesFields(AXPBWii& pb, u16* num_updates, u16* updates);
|
||||
// If needed, extract the updates related fields from a PB. We need to
|
||||
// reinject them afterwards so that the correct PB typs is written to RAM.
|
||||
bool ExtractUpdatesFields(AXPBWii& pb, u16* num_updates, u16* updates,
|
||||
u32* updates_addr);
|
||||
void ReinjectUpdatesFields(AXPBWii& pb, u16* num_updates, u32 updates_addr);
|
||||
|
||||
// Convert a mixer_control bitfield to our internal representation for that
|
||||
// value. Required because that bitfield has a different meaning in some
|
||||
@ -91,7 +94,30 @@ private:
|
||||
CMD_OUTPUT = 0x0B,
|
||||
CMD_UNK_0C = 0x0C,
|
||||
CMD_WM_OUTPUT = 0x0D,
|
||||
CMD_END = 0x0E
|
||||
CMD_END = 0x0E,
|
||||
};
|
||||
|
||||
// A lot of these are similar to the new version, but there is an offset in
|
||||
// the command ids due to the PB_ADDR command (which was removed from the
|
||||
// new AXWii).
|
||||
enum CmdTypeOld
|
||||
{
|
||||
CMD_SETUP_OLD = 0x00,
|
||||
CMD_ADD_TO_LR_OLD = 0x01,
|
||||
CMD_UNK_02_OLD = 0x02,
|
||||
CMD_UNK_03_OLD = 0x03,
|
||||
CMD_PB_ADDR_OLD = 0x04,
|
||||
CMD_PROCESS_OLD = 0x05,
|
||||
CMD_MIX_AUXA_OLD = 0x06,
|
||||
CMD_MIX_AUXB_OLD = 0x07,
|
||||
CMD_MIX_AUXC_OLD = 0x08,
|
||||
CMD_UNK_09_OLD = 0x09,
|
||||
CMD_UNK_0A_OLD = 0x0A,
|
||||
CMD_UNK_0B_OLD = 0x0B,
|
||||
CMD_OUTPUT_OLD = 0x0C, // no volume!
|
||||
CMD_UNK_0D_OLD = 0x0D,
|
||||
CMD_WM_OUTPUT_OLD = 0x0E,
|
||||
CMD_END_OLD = 0x0F
|
||||
};
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user