Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'new-ax-hle'
GC and Wii games using the AX UCode should now work almost perfectly with DSP
HLE. If you get any issue, make sure the "DSP on dedicated thread" option is
disabled, and try setting framelimit to "Audio".

As a side effect, DSP HLE should not desync anymore (making it usable in
netplay and TAS) with AX games.

Conflicts:
	Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h
	Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp
  • Loading branch information
delroth committed Apr 2, 2013
2 parents d951c4c + 9860137 commit eb06c62
Show file tree
Hide file tree
Showing 17 changed files with 1,104 additions and 1,606 deletions.
3 changes: 1 addition & 2 deletions Source/Core/Core/CMakeLists.txt
Expand Up @@ -69,8 +69,7 @@ set(SRCS Src/ActionReplay.cpp
Src/HW/CPU.cpp
Src/HW/DSP.cpp
Src/HW/DSPHLE/UCodes/UCode_AX.cpp
Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp
Src/HW/DSPHLE/UCodes/UCode_NewAXWii.cpp
Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp
Src/HW/DSPHLE/UCodes/UCode_CARD.cpp
Src/HW/DSPHLE/UCodes/UCode_InitAudioSystem.cpp
Src/HW/DSPHLE/UCodes/UCode_ROM.cpp
Expand Down
8 changes: 2 additions & 6 deletions Source/Core/Core/Core.vcxproj
Expand Up @@ -261,7 +261,6 @@
<ClCompile Include="Src\HW\DSPHLE\UCodes\UCodes.cpp" />
<ClCompile Include="Src\HW\DSPHLE\UCodes\UCode_AX.cpp" />
<ClCompile Include="Src\HW\DSPHLE\UCodes\UCode_AXWii.cpp" />
<ClCompile Include="Src\HW\DSPHLE\UCodes\UCode_NewAXWii.cpp" />
<ClCompile Include="Src\HW\DSPHLE\UCodes\UCode_CARD.cpp" />
<ClCompile Include="Src\HW\DSPHLE\UCodes\UCode_GBA.cpp" />
<ClCompile Include="Src\HW\DSPHLE\UCodes\UCode_InitAudioSystem.cpp" />
Expand Down Expand Up @@ -465,11 +464,8 @@
<ClInclude Include="Src\HW\DSPHLE\MailHandler.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCodes.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AX.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AX_Structs.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AXStructs.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AXWii.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AXWii_Structs.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AXWii_Voice.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_NewAXWii.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AX_Voice.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_CARD.h" />
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_GBA.h" />
Expand Down Expand Up @@ -602,4 +598,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
14 changes: 1 addition & 13 deletions Source/Core/Core/Core.vcxproj.filters
Expand Up @@ -196,9 +196,6 @@
<ClCompile Include="Src\HW\DSPHLE\UCodes\UCode_AXWii.cpp">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</ClCompile>
<ClCompile Include="Src\HW\DSPHLE\UCodes\UCode_NewAXWii.cpp">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</ClCompile>
<ClCompile Include="Src\HW\DSPHLE\UCodes\UCode_CARD.cpp">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</ClCompile>
Expand Down Expand Up @@ -738,21 +735,12 @@
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AX_Voice.h">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</ClInclude>
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AX_Structs.h">
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AXStructs.h">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</ClInclude>
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AXWii.h">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</ClInclude>
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AXWii_Structs.h">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</ClInclude>
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_AXWii_Voice.h">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</ClInclude>
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_NewAXWii.h">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</ClInclude>
<ClInclude Include="Src\HW\DSPHLE\UCodes\UCode_CARD.h">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</ClInclude>
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp
Expand Up @@ -273,7 +273,7 @@ u16 DSPHLE::DSP_WriteControlRegister(unsigned short _Value)
UDSPControl Temp(_Value);
if (!m_InitMixer)
{
if (!Temp.DSPHalt && Temp.DSPInit)
if (!Temp.DSPHalt)
{
InitMixer();
}
Expand Down
109 changes: 88 additions & 21 deletions Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp
Expand Up @@ -17,29 +17,78 @@

#include "UCode_AX.h"
#include "../../DSP.h"
#include "FileUtil.h"
#include "ConfigManager.h"

#define AX_GC
#include "UCode_AX_Voice.h"

CUCode_AX::CUCode_AX(DSPHLE* dsp_hle, u32 crc)
: IUCode(dsp_hle, crc)
, m_work_available(false)
, m_cmdlist_size(0)
, m_axthread(&SpawnAXThread, this)
, m_run_on_thread(SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPThread)
{
WARN_LOG(DSPHLE, "Instantiating CUCode_AX: crc=%08x", crc);
m_rMailHandler.PushMail(DSP_INIT);
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);

LoadResamplingCoefficients();

if (m_run_on_thread)
m_axthread = std::thread(SpawnAXThread, this);
}

CUCode_AX::~CUCode_AX()
{
m_cmdlist_size = (u16)-1; // Special value to signal end
NotifyAXThread();
m_axthread.join();
if (m_run_on_thread)
{
m_cmdlist_size = (u16)-1; // Special value to signal end
NotifyAXThread();
m_axthread.join();
}

m_rMailHandler.Clear();
}

void CUCode_AX::LoadResamplingCoefficients()
{
m_coeffs_available = false;

std::string filenames[] = {
File::GetUserPath(D_GCUSER_IDX) + "dsp_coef.bin",
File::GetSysDirectory() + "/GC/dsp_coef.bin"
};

size_t fidx;
std::string filename;
for (fidx = 0; fidx < sizeof (filenames) / sizeof (filenames[0]); ++fidx)
{
filename = filenames[fidx];
if (!File::Exists(filename))
continue;

if (File::GetSize(filename) != 0x1000)
continue;

break;
}

if (fidx >= sizeof (filenames) / sizeof (filenames[0]))
return;

WARN_LOG(DSPHLE, "Loading polyphase resampling coeffs from %s", filename.c_str());

FILE* fp = fopen(filename.c_str(), "rb");
fread(m_coeffs, 1, 0x1000, fp);
fclose(fp);

for (u32 i = 0; i < 0x800; ++i)
m_coeffs[i] = Common::swap16(m_coeffs[i]);

m_coeffs_available = true;
}

void CUCode_AX::SpawnAXThread(CUCode_AX* self)
{
self->AXThread();
Expand All @@ -61,20 +110,32 @@ void CUCode_AX::AXThread()
m_processing.lock();
HandleCommandList();
m_cmdlist_size = 0;

// Signal end of processing
m_rMailHandler.PushMail(DSP_YIELD);
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
SignalWorkEnd();
m_processing.unlock();
}
}

void CUCode_AX::SignalWorkEnd()
{
// Signal end of processing
m_rMailHandler.PushMail(DSP_YIELD);
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
}

void CUCode_AX::NotifyAXThread()
{
std::unique_lock<std::mutex> lk(m_cmdlist_mutex);
m_cmdlist_cv.notify_one();
}

void CUCode_AX::StartWorking()
{
if (m_run_on_thread)
NotifyAXThread();
else
m_work_available = true;
}

void CUCode_AX::HandleCommandList()
{
// Temp variables for addresses computation
Expand Down Expand Up @@ -200,11 +261,7 @@ void CUCode_AX::HandleCommandList()
u16 idx = m_cmdlist[curr_idx++];
addr_hi = m_cmdlist[curr_idx++];
addr_lo = m_cmdlist[curr_idx++];

// TODO
(void)samp_val;
(void)idx;

break;
}

Expand Down Expand Up @@ -250,19 +307,18 @@ void CUCode_AX::HandleCommandList()
}
}

static void ApplyUpdatesForMs(AXPB& pb, int curr_ms)
void CUCode_AX::ApplyUpdatesForMs(int curr_ms, u16* pb, u16* num_updates, u16* updates)
{
u32 start_idx = 0;
for (int i = 0; i < curr_ms; ++i)
start_idx += pb.updates.num_updates[i];
start_idx += num_updates[i];

u32 update_addr = HILO_TO_32(pb.updates.data);
for (u32 i = start_idx; i < start_idx + pb.updates.num_updates[curr_ms]; ++i)
for (u32 i = start_idx; i < start_idx + num_updates[curr_ms]; ++i)
{
u16 update_off = HLEMemory_Read_U16(update_addr + 4 * i);
u16 update_val = HLEMemory_Read_U16(update_addr + 4 * i + 2);
u16 update_off = Common::swap16(updates[2 * i]);
u16 update_val = Common::swap16(updates[2 * i + 1]);

((u16*)&pb)[update_off] = update_val;
pb[update_off] = update_val;
}
}

Expand Down Expand Up @@ -405,11 +461,15 @@ void CUCode_AX::ProcessPBList(u32 pb_addr)
if (!ReadPB(pb_addr, pb))
break;

u32 updates_addr = HILO_TO_32(pb.updates.data);
u16* updates = (u16*)HLEMemory_Get_Pointer(updates_addr);

for (int curr_ms = 0; curr_ms < 5; ++curr_ms)
{
ApplyUpdatesForMs(pb, curr_ms);
ApplyUpdatesForMs(curr_ms, (u16*)&pb, pb.updates.num_updates, updates);

Process1ms(pb, buffers, ConvertMixerControl(pb.mixer_control));
ProcessVoice(pb, buffers, spms, ConvertMixerControl(pb.mixer_control),
m_coeffs_available ? m_coeffs : NULL);

// Forward the buffers
for (u32 i = 0; i < sizeof (buffers.ptrs) / sizeof (buffers.ptrs[0]); ++i)
Expand Down Expand Up @@ -599,6 +659,7 @@ void CUCode_AX::HandleMail(u32 mail)
if (next_is_cmdlist)
{
CopyCmdList(mail, cmdlist_size);
StartWorking();
NotifyAXThread();
}
else if (m_UploadSetupInProgress)
Expand Down Expand Up @@ -667,6 +728,12 @@ void CUCode_AX::Update(int cycles)
m_rMailHandler.PushMail(DSP_RESUME);
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
}
else if (m_work_available)
{
HandleCommandList();
m_cmdlist_size = 0;
SignalWorkEnd();
}
}

void CUCode_AX::DoAXState(PointerWrap& p)
Expand Down
25 changes: 23 additions & 2 deletions Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h
Expand Up @@ -27,7 +27,7 @@
#define _UCODE_AX_H

#include "UCodes.h"
#include "UCode_AX_Structs.h"
#include "UCode_AXStructs.h"

// We can't directly use the mixer_control field from the PB because it does
// not mean the same in all AX versions. The AX UCode converts the
Expand Down Expand Up @@ -102,18 +102,31 @@ class CUCode_AX : public IUCode
int m_samples_auxB_right[32 * 5];
int m_samples_auxB_surround[32 * 5];

// This flag is set if there is anything to process.
bool m_work_available;

// Volatile because it's set by HandleMail and accessed in
// HandleCommandList, which are running in two different threads.
volatile u16 m_cmdlist[512];
volatile u32 m_cmdlist_size;

bool m_run_on_thread;

// Sync objects
std::mutex m_processing;
std::condition_variable m_cmdlist_cv;
std::mutex m_cmdlist_mutex;

std::thread m_axthread;

// Table of coefficients for polyphase sample rate conversion.
// The coefficients aren't always available (they are part of the DSP DROM)
// so we also need to know if they are valid or not.
bool m_coeffs_available;
s16 m_coeffs[0x800];

void LoadResamplingCoefficients();

// Copy a command list from memory to our temp buffer
void CopyCmdList(u32 addr, u16 size);

Expand All @@ -122,13 +135,21 @@ class CUCode_AX : public IUCode
// versions of AX.
AXMixControl ConvertMixerControl(u32 mixer_control);

// Send a notification to the AX thread to tell him a new cmdlist addr is
// Apply updates to a PB. Generic, used in AX GC and AX Wii.
void ApplyUpdatesForMs(int curr_ms, u16* pb, u16* num_updates, u16* updates);

// Signal that we should start handling a command list. Dispatches to the
// AX thread if using a thread, else just sets a boolean flag.
void StartWorking();

// Send a notification to the AX thread to tell it a new cmdlist addr is
// available for processing.
void NotifyAXThread();

void AXThread();

virtual void HandleCommandList();
void SignalWorkEnd();

void SetupProcessing(u32 init_addr);
void DownloadAndMixWithVolume(u32 addr, u16 vol_main, u16 vol_auxa, u16 vol_auxb);
Expand Down

0 comments on commit eb06c62

Please sign in to comment.