Merge branch 'master' into primitive_restart

Conflicts:
	Source/Core/VideoCommon/Src/VideoConfig.h
	Source/Plugins/Plugin_VideoDX9/Src/main.cpp
	Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
This commit is contained in:
degasus 2013-04-08 15:57:51 +02:00
commit 702198f39b
334 changed files with 21473 additions and 18765 deletions

View file

@ -76,7 +76,7 @@ public:
g_wave_writer.SetSkipSilence(false);
NOTICE_LOG(DSPHLE, "Starting Audio logging");
} else {
WARN_LOG(DSPHLE, "Audio logging already started");
WARN_LOG(DSPHLE, "Audio logging has already been started");
}
}
@ -86,7 +86,7 @@ public:
g_wave_writer.Stop();
NOTICE_LOG(DSPHLE, "Stopping Audio logging");
} else {
WARN_LOG(DSPHLE, "Audio logging already stopped");
WARN_LOG(DSPHLE, "Audio logging has already been stopped");
}
}

View file

@ -73,7 +73,7 @@ bool WaveFileWriter::Start(const char *filename, unsigned int HLESampleRate)
// We are now at offset 44
if (file.Tell() != 44)
PanicAlert("wrong offset: %lld", (long long)file.Tell());
PanicAlert("Wrong offset: %lld", (long long)file.Tell());
return true;
}

View file

@ -66,23 +66,26 @@ _mm_shuffle_epi8(__m128i a, __m128i mask)
#define Crash() {asm ("int $3");}
#endif
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
// GCC 4.8 defines all the rotate functions now
// Small issue with GCC's lrotl/lrotr intrinsics is they are still 32bit while we require 64bit
#ifndef _rotl
inline u32 _rotl(u32 x, int shift) {
shift &= 31;
if (!shift) return x;
return (x << shift) | (x >> (32 - shift));
}
inline u64 _rotl64(u64 x, unsigned int shift){
unsigned int n = shift % 64;
return (x << n) | (x >> (64 - n));
}
inline u32 _rotr(u32 x, int shift) {
shift &= 31;
if (!shift) return x;
return (x >> shift) | (x << (32 - shift));
}
#endif
inline u64 _rotl64(u64 x, unsigned int shift){
unsigned int n = shift % 64;
return (x << n) | (x >> (64 - n));
}
inline u64 _rotr64(u64 x, unsigned int shift){
unsigned int n = shift % 64;

View file

@ -36,15 +36,16 @@ public:
return (0 == m_size);
}
const T& Front() const
T& Front() const
{
return *m_read_ptr->current;
}
void Push(const T& t)
template <typename Arg>
void Push(Arg&& t)
{
// create the element, add it to the queue
m_write_ptr->current = new T(t);
m_write_ptr->current = new T(std::forward<Arg>(t));
// set the next pointer to a new element ptr
// then advance the write pointer
m_write_ptr = m_write_ptr->next = new ElementPtr();
@ -67,7 +68,7 @@ public:
if (Empty())
return false;
t = Front();
t = std::move(Front());
Pop();
return true;

View file

@ -124,7 +124,7 @@ bool Delete(const std::string &filename)
// being there, not the actual delete.
if (!Exists(filename))
{
WARN_LOG(COMMON, "Delete: %s does not exists", filename.c_str());
WARN_LOG(COMMON, "Delete: %s does not exist", filename.c_str());
return true;
}
@ -216,7 +216,7 @@ bool CreateFullPath(const std::string &fullPath)
panicCounter--;
if (panicCounter <= 0)
{
ERROR_LOG(COMMON, "CreateFullPath: directory structure too deep");
ERROR_LOG(COMMON, "CreateFullPath: directory structure is too deep");
return false;
}
position++;
@ -324,7 +324,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
goto bail;
}
}
// close flushs
// close files
fclose(input);
fclose(output);
return true;
@ -669,7 +669,7 @@ std::string GetSysDirectory()
// Returns a string with a Dolphin data dir or file in the user's home
// directory. To be used in "multi-user" mode (that is, installed).
std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
const std::string& GetUserPath(const unsigned int DirIDX, const std::string &newPath)
{
static std::string paths[NUM_PATH_INDICES];
@ -723,11 +723,11 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
if (!newPath.empty())
{
if(DirIDX != D_WIIROOT_IDX)
PanicAlert("trying to change user path other than wii root");
PanicAlert("Trying to change user path other than Wii root");
if (!File::IsDirectory(newPath))
{
WARN_LOG(COMMON, "Invalid path specified %s, wii user path will be set to default", newPath.c_str());
WARN_LOG(COMMON, "Invalid path specified %s, Wii user path will be set to default", newPath.c_str());
paths[D_WIIROOT_IDX] = paths[D_USER_IDX] + WII_USER_DIR;
}
else
@ -742,6 +742,19 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
return paths[DirIDX];
}
std::string GetThemeDir(const std::string& theme_name)
{
std::string dir = File::GetUserPath(D_THEMES_IDX) + theme_name + "/";
#if !defined(_WIN32)
// If theme does not exist in user's dir load from shared directory
if (!File::Exists(dir))
dir = SHARED_USER_DIR THEMES_DIR "/" + theme_name + "/";
#endif
return dir;
}
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
{
return File::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size());

View file

@ -132,7 +132,10 @@ bool SetCurrentDir(const std::string &directory);
// Returns a pointer to a string with a Dolphin data dir in the user's home
// directory. To be used in "multi-user" mode (that is, installed).
std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath="");
const std::string& GetUserPath(const unsigned int DirIDX, const std::string &newPath="");
// probably doesn't belong here
std::string GetThemeDir(const std::string& theme_name);
// Returns the path to where the sys file are
std::string GetSysDirectory();

View file

@ -46,7 +46,7 @@ public:
void Log(LogTypes::LOG_LEVELS, const char *msg);
bool IsValid() { return (m_logfile != NULL); }
bool IsValid() { return (bool)m_logfile; }
bool IsEnabled() const { return m_enable; }
void SetEnable(bool enable) { m_enable = enable; }

View file

@ -5,9 +5,26 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#ifndef __has_include
#define __has_include(s) 0
#endif
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <condition_variable>
#include <condition_variable>
#elif __has_include(<condition_variable>)
// clang and libc++ provide <condition_variable> on OSX. However, the version
// of libc++ bundled with OSX 10.7 and 10.8 is buggy: it uses _ as a variable.
//
// We work around this issue by undefining and redefining _.
#undef _
#include <condition_variable>
#define _(s) wxGetTranslation((s))
#else
// partial std::condition_variable implementation for win32/pthread

View file

@ -5,9 +5,16 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#ifndef __has_include
#define __has_include(s) 0
#endif
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <mutex>
#include <mutex>
#elif __has_include(<mutex>)
// Clang + libc++
#include <mutex>
#else
// partial <mutex> implementation for win32/pthread

View file

@ -5,12 +5,19 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#ifndef __has_include
#define __has_include(s) 0
#endif
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <thread>
#ifndef _GLIBCXX_USE_SCHED_YIELD
#define _GLIBCXX_USE_SCHED_YIELD
#endif
#include <thread>
#elif __has_include(<thread>)
// Clang + libc++
#include <thread>
#else
// partial std::thread implementation for win32/pthread

View file

@ -18,9 +18,9 @@
#ifndef _THREAD_H_
#define _THREAD_H_
#include "StdThread.h"
#include "StdMutex.h"
#include "StdConditionVariable.h"
#include "StdMutex.h"
#include "StdThread.h"
// Don't include common.h here as it will break LogManager
#include "CommonTypes.h"

View file

@ -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

View file

@ -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" />
@ -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" />
@ -602,4 +598,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View file

@ -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>
@ -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>

View file

@ -176,7 +176,7 @@ bool CBoot::Load_BS2(const std::string& _rBootROMFilename)
std::string BootRegion = _rBootROMFilename.substr(_rBootROMFilename.find_last_of(DIR_SEP) - 3, 3);
if (BootRegion != ipl_region)
PanicAlert("%s ipl found in %s directory, the disc may not be recognized", ipl_region.c_str(), BootRegion.c_str());
PanicAlert("%s IPL found in %s directory. The disc may not be recognized", ipl_region.c_str(), BootRegion.c_str());
// Run the descrambler over the encrypted section containing BS1/BS2
CEXIIPL::Descrambler((u8*)data.data()+0x100, 0x1AFE00);

View file

@ -27,7 +27,7 @@
#include "SysConf.h"
// DSP Backend Types
#define BACKEND_NULLSOUND "No audio output"
#define BACKEND_NULLSOUND _trans("No audio output")
#define BACKEND_ALSA "ALSA"
#define BACKEND_AOSOUND "AOSound"
#define BACKEND_COREAUDIO "CoreAudio"

View file

@ -38,12 +38,12 @@ void Console_Submit(const char *cmd)
CASE1("r")
{
Core::StartTrace(false);
INFO_LOG(CONSOLE, "read tracing started.");
INFO_LOG(CONSOLE, "Read tracing started.");
}
CASE1("w")
{
Core::StartTrace(true);
INFO_LOG(CONSOLE, "write tracing started.");
INFO_LOG(CONSOLE, "Write tracing started.");
}
CASE("trans")
{

View file

@ -46,7 +46,7 @@ SCoreStartupParameter::SCoreStartupParameter()
bCPUThread(true), bDSPThread(false), bDSPHLE(true),
bSkipIdle(true), bNTSC(false), bForceNTSCJ(false),
bHLE_BS2(true), bEnableCheats(false),
bMergeBlocks(false),
bMergeBlocks(false), bEnableMemcardSaving(true),
bDPL2Decoder(false), iLatency(14),
bRunCompareServer(false), bRunCompareClient(false),
bMMU(false), bDCBZOFF(false), iTLBHack(0), bVBeam(false),
@ -81,6 +81,7 @@ void SCoreStartupParameter::LoadDefaults()
bSyncGPU = false;
bFastDiscSpeed = false;
bMergeBlocks = false;
bEnableMemcardSaving = true;
SelectedLanguage = 0;
bWii = false;
bDPL2Decoder = false;
@ -326,7 +327,7 @@ bool SCoreStartupParameter::AutoSetup(EBootBS2 _BootBS2)
{
if (!File::Exists(m_strBootROM))
{
WARN_LOG(BOOT, "bootrom file %s not found - using HLE.", m_strBootROM.c_str());
WARN_LOG(BOOT, "Bootrom file %s not found - using HLE.", m_strBootROM.c_str());
bHLE_BS2 = true;
}
}

View file

@ -105,6 +105,7 @@ struct SCoreStartupParameter
bool bHLE_BS2;
bool bEnableCheats;
bool bMergeBlocks;
bool bEnableMemcardSaving;
bool bDPL2Decoder;
int iLatency;

View file

@ -318,11 +318,11 @@ static void gdsp_do_dma()
if (len > 0x4000)
{
ERROR_LOG(DSPLLE, "DMA ERROR pc: %04x ctl: %04x addr: %08x da: %04x size: %04x", g_dsp.pc, ctl, addr, dsp_addr, len);
ERROR_LOG(DSPLLE, "DMA ERROR: PC: %04x, Control: %04x, Address: %08x, DSP Address: %04x, Size: %04x", g_dsp.pc, ctl, addr, dsp_addr, len);
exit(0);
}
#if defined(_DEBUG) || defined(DEBUGFAST)
DEBUG_LOG(DSPLLE, "DMA pc: %04x ctl: %04x addr: %08x da: %04x size: %04x", g_dsp.pc, ctl, addr, dsp_addr, len);
DEBUG_LOG(DSPLLE, "DMA pc: %04x, Control: %04x, Address: %08x, DSP Address: %04x, Size: %04x", g_dsp.pc, ctl, addr, dsp_addr, len);
#endif
switch (ctl & 0x3)
{

View file

@ -52,7 +52,7 @@ u16 dsp_dmem_read(u16 addr)
return g_dsp.dram[addr & DSP_DRAM_MASK];
case 0x1: // 1xxx COEF
DEBUG_LOG(DSPLLE, "%04x : Coef Read @ %04x", g_dsp.pc, addr);
DEBUG_LOG(DSPLLE, "%04x : Coefficient Read @ %04x", g_dsp.pc, addr);
return g_dsp.coef[addr & DSP_COEF_MASK];
case 0xf: // Fxxx HW regs

View file

@ -191,7 +191,7 @@ void Read32(u32& _rReturnValue, const u32 _Address)
break;
default:
ERROR_LOG(AUDIO_INTERFACE, "unknown read 0x%08x", _Address);
ERROR_LOG(AUDIO_INTERFACE, "Unknown read 0x%08x", _Address);
_dbg_assert_msg_(AUDIO_INTERFACE, 0, "AudioInterface - Read from 0x%08x", _Address);
_rReturnValue = 0;
return;
@ -212,13 +212,13 @@ void Write32(const u32 _Value, const u32 _Address)
// Set frequency of streaming audio
if (tmpAICtrl.AISFR != m_Control.AISFR)
{
{
DEBUG_LOG(AUDIO_INTERFACE, "Change AISFR to %s", tmpAICtrl.AISFR ? "48khz":"32khz");
m_Control.AISFR = tmpAICtrl.AISFR;
}
// Set frequency of DMA
if (tmpAICtrl.AIDFR != m_Control.AIDFR)
{
{
DEBUG_LOG(AUDIO_INTERFACE, "Change AIDFR to %s", tmpAICtrl.AIDFR ? "32khz":"48khz");
m_Control.AIDFR = tmpAICtrl.AIDFR;
}
@ -281,7 +281,7 @@ void Write32(const u32 _Value, const u32 _Address)
break;
default:
ERROR_LOG(AUDIO_INTERFACE, "unknown write %08x @ %08x", _Value, _Address);
ERROR_LOG(AUDIO_INTERFACE, "Unknown write %08x @ %08x", _Value, _Address);
_dbg_assert_msg_(AUDIO_INTERFACE,0,"AIS - Write %08x to %08x", _Value, _Address);
break;
}
@ -294,7 +294,7 @@ static void UpdateInterrupts()
}
static void GenerateAudioInterrupt()
{
{
m_Control.AIINT = 1;
UpdateInterrupts();
}
@ -315,7 +315,7 @@ void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DACSampl
unsigned int Callback_GetStreaming(short* _pDestBuffer, unsigned int _numSamples, unsigned int _sampleRate)
{
if (m_Control.PSTAT && !CCPU::IsStepping())
{
{
static int pos = 0;
static short pcm[NGCADPCM::SAMPLES_PER_BLOCK*2];
const int lvolume = m_Volume.left;
@ -443,7 +443,7 @@ static void IncreaseSampleCount(const u32 _iAmount)
{
m_SampleCounter += _iAmount;
if (m_Control.AIINTVLD && (m_SampleCounter >= m_InterruptTiming))
{
{
GenerateAudioInterrupt();
}
}
@ -460,7 +460,7 @@ void Update(u64 userdata, int cyclesLate)
{
const u64 Diff = CoreTiming::GetTicks() - g_LastCPUTime;
if (Diff > g_CPUCyclesPerSample)
{
{
const u32 Samples = static_cast<u32>(Diff / g_CPUCyclesPerSample);
g_LastCPUTime += Samples * g_CPUCyclesPerSample;
IncreaseSampleCount(Samples);

View file

@ -334,7 +334,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
// ARAM
case AR_INFO:
//PanicAlert("read %x %x", g_ARAM_Info.Hex,PowerPC::ppcState.pc);
//PanicAlert("Read %x %x", g_ARAM_Info.Hex,PowerPC::ppcState.pc);
_uReturnValue = g_ARAM_Info.Hex;
break;
@ -647,6 +647,7 @@ void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type, bool _bSet)
{
CoreTiming::ScheduleEvent_Threadsafe(
0, et_GenerateDSPInterrupt, type | (_bSet<<16));
CoreTiming::ForceExceptionCheck(100);
}
// called whenever SystemTimers thinks the dsp deserves a few more cycles
@ -696,8 +697,8 @@ void Do_ARAM_DMA()
g_dspState.DSPControl.DMAState = 1;
CoreTiming::ScheduleEvent_Threadsafe(0, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
// Force an early exception check. Fixes RE2 audio.
if (g_arDMA.Cnt.count == 4096)
// Force an early exception check on large transfers. Fixes RE2 audio.
if (g_arDMA.Cnt.count > 2048 && g_arDMA.Cnt.count <= 10240)
CoreTiming::ForceExceptionCheck(100);
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks

View file

@ -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();
}

View file

@ -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();
@ -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
@ -200,11 +261,9 @@ 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;
// suppress warnings:
(void)samp_val; (void)idx;
break;
}
@ -243,26 +302,25 @@ void CUCode_AX::HandleCommandList()
}
default:
ERROR_LOG(DSPHLE, "Unknown command in AX cmdlist: %04x", cmd);
ERROR_LOG(DSPHLE, "Unknown command in AX command list: %04x", cmd);
end = true;
break;
}
}
}
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;
}
}
@ -405,11 +463,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)
@ -599,6 +661,7 @@ void CUCode_AX::HandleMail(u32 mail)
if (next_is_cmdlist)
{
CopyCmdList(mail, cmdlist_size);
StartWorking();
NotifyAXThread();
}
else if (m_UploadSetupInProgress)
@ -667,6 +730,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)

View file

@ -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
@ -75,7 +75,7 @@ public:
virtual void DoState(PointerWrap& p);
// Needed because StdThread.h std::thread implem does not support member
// pointers.
// pointers. TODO(delroth): obsolete.
static void SpawnAXThread(CUCode_AX* self);
protected:
@ -102,18 +102,31 @@ protected:
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;
std::thread m_axthread;
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);
@ -122,13 +135,21 @@ protected:
// 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);

View file

@ -161,15 +161,15 @@ struct PBDpopWii
struct PBDpopWM
{
s16 aMain0;
s16 aMain1;
s16 aMain2;
s16 aMain3;
s16 main0;
s16 main1;
s16 main2;
s16 main3;
s16 aAux0;
s16 aAux1;
s16 aAux2;
s16 aAux3;
s16 aux0;
s16 aux1;
s16 aux2;
s16 aux3;
};
struct PBVolumeEnvelope
@ -211,13 +211,13 @@ struct PBSampleRateConverter
u16 ratio_hi; // integer part of sampling ratio
u16 ratio_lo; // fraction part of sampling ratio
u16 cur_addr_frac;
u16 last_samples[4];
s16 last_samples[4];
};
struct PBSampleRateConverterWM
{
u16 currentAddressFrac;
u16 last_samples[4];
u16 cur_addr_frac;
s16 last_samples[4];
};
struct PBADPCMLoopInfo
@ -230,7 +230,7 @@ struct PBADPCMLoopInfo
struct PBLowPassFilter
{
u16 enabled;
u16 yn1;
s16 yn1;
u16 a0;
u16 b0;
};
@ -324,52 +324,6 @@ struct AXPBWii
u16 pad[12]; // align us, captain! (32B)
};
// Seems like nintendo used an early version of AXWii and forgot to remove the update functionality ;p
struct PBUpdatesWiiSports
{
u16 num_updates[3];
u16 data_hi;
u16 data_lo;
};
struct AXPBWiiSports
{
u16 next_pb_hi;
u16 next_pb_lo;
u16 this_pb_hi;
u16 this_pb_lo;
u16 src_type; // Type of sample rate converter (none, 4-tap, linear)
u16 coef_select; // coef for the 4-tap src
u32 mixer_control;
u16 running; // 1=RUN 0=STOP
u16 is_stream; // 1 = stream, 0 = one shot
PBMixerWii mixer;
PBInitialTimeDelay initial_time_delay;
PBUpdatesWiiSports updates;
PBDpopWii dpop;
PBVolumeEnvelope vol_env;
PBAudioAddr audio_addr;
PBADPCMInfo adpcm;
PBSampleRateConverter src;
PBADPCMLoopInfo adpcm_loop_info;
PBLowPassFilter lpf;
PBBiquadFilter biquad;
// WIIMOTE :D
u16 remote;
u16 remote_mixer_control;
PBMixerWM remote_mixer;
PBDpopWM remote_dpop;
PBSampleRateConverterWM remote_src;
PBInfImpulseResponseWM remote_iir;
u16 pad[7]; // align us, captain! (32B)
};
// TODO: All these enums have changed a lot for wii
enum {
AUDIOFORMAT_ADPCM = 0,

View file

@ -21,247 +21,678 @@
#include "Mixer.h"
#include "UCodes.h"
#include "UCode_AXWii_Structs.h"
#include "UCode_AX.h" // for some functions in CUCode_AX
#include "UCode_AXStructs.h"
#include "UCode_AXWii.h"
#include "UCode_AXWii_Voice.h"
#define AX_WII
#include "UCode_AX_Voice.h"
CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC)
: IUCode(dsp_hle, l_CRC)
, m_addressPBs(0xFFFFFFFF)
: CUCode_AX(dsp_hle, l_CRC),
m_last_main_volume(0x8000)
{
// we got loaded
m_rMailHandler.PushMail(DSP_INIT);
for (int i = 0; i < 3; ++i)
m_last_aux_volumes[i] = 0x8000;
WARN_LOG(DSPHLE, "Instantiating CUCode_AXWii");
templbuffer = new int[1024 * 1024];
temprbuffer = new int[1024 * 1024];
wiisportsHack = m_CRC == 0xfa450138;
m_old_axwii = (l_CRC == 0xfa450138);
}
CUCode_AXWii::~CUCode_AXWii()
{
m_rMailHandler.Clear();
delete [] templbuffer;
delete [] temprbuffer;
}
void CUCode_AXWii::HandleMail(u32 _uMail)
void CUCode_AXWii::HandleCommandList()
{
if (m_UploadSetupInProgress)
// Temp variables for addresses computation
u16 addr_hi, addr_lo;
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)
// WARN_LOG(DSPHLE, "%04x", m_cmdlist[i]);
// WARN_LOG(DSPHLE, "-------------");
u32 curr_idx = 0;
bool end = false;
while (!end)
{
PrepareBootUCode(_uMail);
return;
}
else if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST)
{
// We are expected to get a new CmdBlock
DEBUG_LOG(DSPHLE, "GetNextCmdBlock (%ibytes)", (u16)_uMail);
}
else switch(_uMail)
{
case 0xCDD10000: // Action 0 - AX_ResumeTask()
m_rMailHandler.PushMail(DSP_RESUME);
break;
u16 cmd = m_cmdlist[curr_idx++];
case 0xCDD10001: // Action 1 - new ucode upload
DEBUG_LOG(DSPHLE,"DSP IROM - New Ucode!");
// TODO find a better way to protect from HLEMixer?
soundStream->GetMixer()->SetHLEReady(false);
m_UploadSetupInProgress = true;
break;
if (m_old_axwii)
{
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 0xCDD10002: // Action 2 - IROM_Reset(); ( WII: De Blob, Cursed Mountain,...)
DEBUG_LOG(DSPHLE,"DSP IROM - Reset!");
m_DSPHLE->SetUCode(UCODE_ROM);
return;
case CMD_SETUP_OLD:
addr_hi = m_cmdlist[curr_idx++];
addr_lo = m_cmdlist[curr_idx++];
SetupProcessing(HILO_TO_32(addr));
break;
case 0xCDD10003: // Action 3 - AX_GetNextCmdBlock()
break;
case CMD_ADD_TO_LR_OLD:
case CMD_SUB_TO_LR_OLD:
addr_hi = m_cmdlist[curr_idx++];
addr_lo = m_cmdlist[curr_idx++];
AddToLR(HILO_TO_32(addr), cmd == CMD_SUB_TO_LR_OLD);
break;
default:
DEBUG_LOG(DSPHLE, " >>>> u32 MAIL : AXTask Mail (%08x)", _uMail);
AXTask(_uMail);
break;
}
}
case CMD_ADD_SUB_TO_LR_OLD:
addr_hi = m_cmdlist[curr_idx++];
addr_lo = m_cmdlist[curr_idx++];
AddSubToLR(HILO_TO_32(addr));
break;
void CUCode_AXWii::MixAdd(short* _pBuffer, int _iSize)
{
AXPBWii PB;
case CMD_PB_ADDR_OLD:
addr_hi = m_cmdlist[curr_idx++];
addr_lo = m_cmdlist[curr_idx++];
pb_addr = HILO_TO_32(addr);
break;
if (_iSize > 1024 * 1024)
_iSize = 1024 * 1024;
case CMD_PROCESS_OLD:
ProcessPBList(pb_addr);
break;
memset(templbuffer, 0, _iSize * sizeof(int));
memset(temprbuffer, 0, _iSize * sizeof(int));
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;
u32 blockAddr = m_addressPBs;
if (!blockAddr)
return;
case CMD_UPL_AUXA_MIX_LRSC_OLD:
case CMD_UPL_AUXB_MIX_LRSC_OLD:
{
volume = m_cmdlist[curr_idx++];
u32 addresses[6] = {
(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],
(u32)(m_cmdlist[curr_idx + 8] << 16) | m_cmdlist[curr_idx + 9],
(u32)(m_cmdlist[curr_idx + 10] << 16) | m_cmdlist[curr_idx + 11],
};
curr_idx += 12;
UploadAUXMixLRSC(cmd == CMD_UPL_AUXB_MIX_LRSC_OLD, addresses, volume);
break;
}
for (int i = 0; i < NUMBER_OF_PBS; i++)
{
if (!ReadPB(blockAddr, PB))
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;
if (wiisportsHack)
MixAddVoice(*(AXPBWiiSports*)&PB, templbuffer, temprbuffer, _iSize);
case CMD_OUTPUT_OLD:
case CMD_OUTPUT_DPL2_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,
cmd == CMD_OUTPUT_DPL2_OLD);
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
MixAddVoice(PB, templbuffer, temprbuffer, _iSize);
if (!WritePB(blockAddr, PB))
break;
// next PB, or done
blockAddr = (PB.next_pb_hi << 16) | PB.next_pb_lo;
if (!blockAddr)
break;
}
// We write the sound to _pBuffer
if (_pBuffer)
{
for (int i = 0; i < _iSize; i++)
{
// Clamp into 16-bit. Maybe we should add a volume compressor here.
int left = templbuffer[i] + _pBuffer[0];
int right = temprbuffer[i] + _pBuffer[1];
if (left < -32767) left = -32767;
else if (left > 32767) left = 32767;
if (right < -32767) right = -32767;
else if (right > 32767) right = 32767;
*_pBuffer++ = left;
*_pBuffer++ = right;
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:
case CMD_SUB_TO_LR:
addr_hi = m_cmdlist[curr_idx++];
addr_lo = m_cmdlist[curr_idx++];
AddToLR(HILO_TO_32(addr), cmd == CMD_SUB_TO_LR);
break;
case CMD_ADD_SUB_TO_LR:
addr_hi = m_cmdlist[curr_idx++];
addr_lo = m_cmdlist[curr_idx++];
AddSubToLR(HILO_TO_32(addr));
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;
case CMD_UPL_AUXA_MIX_LRSC:
case CMD_UPL_AUXB_MIX_LRSC:
{
volume = m_cmdlist[curr_idx++];
u32 addresses[6] = {
(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],
(u32)(m_cmdlist[curr_idx + 8] << 16) | m_cmdlist[curr_idx + 9],
(u32)(m_cmdlist[curr_idx + 10] << 16) | m_cmdlist[curr_idx + 11],
};
curr_idx += 12;
UploadAUXMixLRSC(cmd == CMD_UPL_AUXB_MIX_LRSC, addresses, volume);
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:
case CMD_OUTPUT_DPL2:
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,
cmd == CMD_OUTPUT_DPL2);
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;
}
}
}
}
void CUCode_AXWii::Update(int cycles)
void CUCode_AXWii::SetupProcessing(u32 init_addr)
{
if (NeedsResumeMail())
// TODO: should be easily factorizable with AX
s16 init_data[60];
for (u32 i = 0; i < 60; ++i)
init_data[i] = HLEMemory_Read_U16(init_addr + 2 * i);
// List of all buffers we have to initialize
struct {
int* ptr;
u32 samples;
} buffers[] = {
{ m_samples_left, 32 },
{ m_samples_right, 32 },
{ m_samples_surround, 32 },
{ m_samples_auxA_left, 32 },
{ m_samples_auxA_right, 32 },
{ m_samples_auxA_surround, 32 },
{ m_samples_auxB_left, 32 },
{ m_samples_auxB_right, 32 },
{ m_samples_auxB_surround, 32 },
{ m_samples_auxC_left, 32 },
{ m_samples_auxC_right, 32 },
{ m_samples_auxC_surround, 32 },
{ m_samples_wm0, 6 },
{ m_samples_aux0, 6 },
{ m_samples_wm1, 6 },
{ m_samples_aux1, 6 },
{ m_samples_wm2, 6 },
{ m_samples_aux2, 6 },
{ m_samples_wm3, 6 },
{ m_samples_aux3, 6 }
};
u32 init_idx = 0;
for (u32 i = 0; i < sizeof (buffers) / sizeof (buffers[0]); ++i)
{
m_rMailHandler.PushMail(DSP_RESUME);
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
}
// check if we have to send something
else if (!m_rMailHandler.IsEmpty())
{
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
s32 init_val = (s32)((init_data[init_idx] << 16) | init_data[init_idx + 1]);
s16 delta = (s16)init_data[init_idx + 2];
init_idx += 3;
if (!init_val)
memset(buffers[i].ptr, 0, 3 * buffers[i].samples * sizeof (int));
else
{
for (u32 j = 0; j < 3 * buffers[i].samples; ++j)
{
buffers[i].ptr[j] = init_val;
init_val += delta;
}
}
}
}
// AX seems to bootup one task only and waits for resume-callbacks
// everytime the DSP has "spare time" it sends a resume-mail to the CPU
// and the __DSPHandler calls a AX-Callback which generates a new AXFrame
bool CUCode_AXWii::AXTask(u32& _uMail)
void CUCode_AXWii::AddToLR(u32 val_addr, bool neg)
{
u32 uAddress = _uMail;
//u32 Addr__AXStudio;
//u32 Addr__AXOutSBuffer;
bool bExecuteList = true;
/*
for (int i=0;i<64;i++) {
NOTICE_LOG(DSPHLE,"%x - %08x",uAddress+(i*4),HLEMemory_Read_U32(uAddress+(i*4)));
}
*/
while (bExecuteList)
int* ptr = (int*)HLEMemory_Get_Pointer(val_addr);
for (int i = 0; i < 32 * 3; ++i)
{
u16 iCommand = HLEMemory_Read_U16(uAddress);
uAddress += 2;
//NOTICE_LOG(DSPHLE,"AXWII - AXLIST CMD %X",iCommand);
int val = (int)Common::swap32(*ptr++);
if (neg)
val = -val;
switch (iCommand)
{
case 0x0000:
//Addr__AXStudio = HLEMemory_Read_U32(uAddress);
uAddress += 4;
break;
m_samples_left[i] += val;
m_samples_right[i] += val;
}
}
case 0x0001:
uAddress += 4;
break;
void CUCode_AXWii::AddSubToLR(u32 val_addr)
{
int* ptr = (int*)HLEMemory_Get_Pointer(val_addr);
for (int i = 0; i < 32 * 3; ++i)
{
int val = (int)Common::swap32(*ptr++);
m_samples_left[i] += val;
}
for (int i = 0; i < 32 * 3; ++i)
{
int val = (int)Common::swap32(*ptr++);
m_samples_right[i] -= val;
}
}
case 0x0003:
uAddress += 4;
break;
AXMixControl CUCode_AXWii::ConvertMixerControl(u32 mixer_control)
{
u32 ret = 0;
case 0x0004:
// PBs are here now
m_addressPBs = HLEMemory_Read_U32(uAddress);
if (soundStream)
soundStream->GetMixer()->SetHLEReady(true);
// soundStream->Update();
uAddress += 4;
break;
if (mixer_control & 0x00000001) ret |= MIX_L;
if (mixer_control & 0x00000002) ret |= MIX_R;
if (mixer_control & 0x00000004) ret |= MIX_L_RAMP | MIX_R_RAMP;
if (mixer_control & 0x00000008) ret |= MIX_S;
if (mixer_control & 0x00000010) ret |= MIX_S_RAMP;
if (mixer_control & 0x00010000) ret |= MIX_AUXA_L;
if (mixer_control & 0x00020000) ret |= MIX_AUXA_R;
if (mixer_control & 0x00040000) ret |= MIX_AUXA_L_RAMP | MIX_AUXA_R_RAMP;
if (mixer_control & 0x00080000) ret |= MIX_AUXA_S;
if (mixer_control & 0x00100000) ret |= MIX_AUXA_S_RAMP;
if (mixer_control & 0x00200000) ret |= MIX_AUXB_L;
if (mixer_control & 0x00400000) ret |= MIX_AUXB_R;
if (mixer_control & 0x00800000) ret |= MIX_AUXB_L_RAMP | MIX_AUXB_R_RAMP;
if (mixer_control & 0x01000000) ret |= MIX_AUXB_S;
if (mixer_control & 0x02000000) ret |= MIX_AUXB_S_RAMP;
if (mixer_control & 0x04000000) ret |= MIX_AUXC_L;
if (mixer_control & 0x08000000) ret |= MIX_AUXC_R;
if (mixer_control & 0x10000000) ret |= MIX_AUXC_L_RAMP | MIX_AUXC_R_RAMP;
if (mixer_control & 0x20000000) ret |= MIX_AUXC_S;
if (mixer_control & 0x40000000) ret |= MIX_AUXC_S_RAMP;
case 0x0005:
if (!wiisportsHack)
uAddress += 10;
break;
return (AXMixControl)ret;
}
case 0x0006:
uAddress += 10;
break;
void CUCode_AXWii::GenerateVolumeRamp(u16* output, u16 vol1, u16 vol2, size_t nvals)
{
float curr = vol1;
for (size_t i = 0; i < nvals; ++i)
{
curr += (vol2 - vol1) / (float)nvals;
output[i] = curr;
}
}
case 0x0007: // AXLIST_SBUFFER
//Addr__AXOutSBuffer = HLEMemory_Read_U32(uAddress);
uAddress += 10;
break;
bool CUCode_AXWii::ExtractUpdatesFields(AXPBWii& pb, u16* num_updates, u16* updates,
u32* updates_addr)
{
u16* pb_mem = (u16*)&pb;
case 0x0008:
uAddress += 26;
break;
if (!m_old_axwii)
return false;
case 0x000a:
uAddress += wiisportsHack ? 4 : 8; // AXLIST_COMPRESSORTABLE
break;
// Copy the num_updates field.
memcpy(num_updates, pb_mem + 41, 6);
case 0x000b:
uAddress += wiisportsHack ? 2 : 10;
break;
// Get the address of the updates data
u16 addr_hi = pb_mem[44];
u16 addr_lo = pb_mem[45];
u32 addr = HILO_TO_32(addr);
u16* ptr = (u16*)HLEMemory_Get_Pointer(addr);
case 0x000c:
uAddress += wiisportsHack ? 8 : 10;
break;
*updates_addr = addr;
case 0x000d:
uAddress += 16;
break;
// 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];
for (u32 i = 0; i < updates_count; ++i)
{
u16 update_off = Common::swap16(ptr[2 * i]);
u16 update_val = Common::swap16(ptr[2 * i + 1]);
case 0x000e:
if (wiisportsHack)
uAddress += 16;
else
bExecuteList = false;
break;
if (update_off > 45)
update_off -= 5;
case 0x000f: // only for Wii Sports uCode
bExecuteList = false;
break;
default:
INFO_LOG(DSPHLE,"DSPHLE - AXwii - AXLIST - Unknown CMD: %x",iCommand);
// unknown command so stop the execution of this TaskList
bExecuteList = false;
break;
}
updates[2 * i] = update_off;
updates[2 * i + 1] = update_val;
}
m_rMailHandler.PushMail(DSP_YIELD); //its here in case there is a CMD fuckup
// Remove the updates data from the PB
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;
while (pb_addr)
{
AXBuffers buffers = {{
m_samples_left,
m_samples_right,
m_samples_surround,
m_samples_auxA_left,
m_samples_auxA_right,
m_samples_auxA_surround,
m_samples_auxB_left,
m_samples_auxB_right,
m_samples_auxB_surround,
m_samples_auxC_left,
m_samples_auxC_right,
m_samples_auxC_surround,
m_samples_wm0,
m_samples_aux0,
m_samples_wm1,
m_samples_aux1,
m_samples_wm2,
m_samples_aux2,
m_samples_wm3,
m_samples_aux3
}};
if (!ReadPB(pb_addr, pb))
break;
u16 num_updates[3];
u16 updates[1024];
u32 updates_addr;
if (ExtractUpdatesFields(pb, num_updates, updates, &updates_addr))
{
for (int curr_ms = 0; curr_ms < 3; ++curr_ms)
{
ApplyUpdatesForMs(curr_ms, (u16*)&pb, num_updates, updates);
ProcessVoice(pb, buffers, 32,
ConvertMixerControl(HILO_TO_32(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)
buffers.ptrs[i] += 32;
}
ReinjectUpdatesFields(pb, num_updates, updates_addr);
}
else
{
ProcessVoice(pb, buffers, 96,
ConvertMixerControl(HILO_TO_32(pb.mixer_control)),
m_coeffs_available ? m_coeffs : NULL);
}
WritePB(pb_addr, pb);
pb_addr = HILO_TO_32(pb.next_pb);
}
}
void CUCode_AXWii::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr, u16 volume)
{
u16 volume_ramp[96];
GenerateVolumeRamp(volume_ramp, m_last_aux_volumes[aux_id], volume, 96);
m_last_aux_volumes[aux_id] = volume;
int* buffers[3] = { 0 };
int* main_buffers[3] = {
m_samples_left,
m_samples_right,
m_samples_surround
};
switch (aux_id)
{
case 0:
buffers[0] = m_samples_auxA_left;
buffers[1] = m_samples_auxA_right;
buffers[2] = m_samples_auxA_surround;
break;
case 1:
buffers[0] = m_samples_auxB_left;
buffers[1] = m_samples_auxB_right;
buffers[2] = m_samples_auxB_surround;
break;
case 2:
buffers[0] = m_samples_auxC_left;
buffers[1] = m_samples_auxC_right;
buffers[2] = m_samples_auxC_surround;
break;
}
// Send the content of AUX buffers to the CPU
if (write_addr)
{
int* ptr = (int*)HLEMemory_Get_Pointer(write_addr);
for (u32 i = 0; i < 3; ++i)
for (u32 j = 0; j < 3 * 32; ++j)
*ptr++ = Common::swap32(buffers[i][j]);
}
// Then read the buffers from the CPU and add to our main buffers.
int* ptr = (int*)HLEMemory_Get_Pointer(read_addr);
for (u32 i = 0; i < 3; ++i)
for (u32 j = 0; j < 3 * 32; ++j)
{
s64 sample = (s64)(s32)Common::swap32(*ptr++);
sample *= volume_ramp[j];
main_buffers[i][j] += (s32)(sample >> 15);
}
}
void CUCode_AXWii::UploadAUXMixLRSC(int aux_id, u32* addresses, u16 volume)
{
int* aux_left = aux_id ? m_samples_auxB_left : m_samples_auxA_left;
int* aux_right = aux_id ? m_samples_auxB_right : m_samples_auxA_right;
int* aux_surround = aux_id ? m_samples_auxB_surround : m_samples_auxA_surround;
int* auxc_buffer = aux_id ? m_samples_auxC_surround : m_samples_auxC_right;
int* upload_ptr = (int*)HLEMemory_Get_Pointer(addresses[0]);
for (u32 i = 0; i < 96; ++i)
*upload_ptr++ = Common::swap32(aux_left[i]);
for (u32 i = 0; i < 96; ++i)
*upload_ptr++ = Common::swap32(aux_right[i]);
for (u32 i = 0; i < 96; ++i)
*upload_ptr++ = Common::swap32(aux_surround[i]);
upload_ptr = (int*)HLEMemory_Get_Pointer(addresses[1]);
for (u32 i = 0; i < 96; ++i)
*upload_ptr++ = Common::swap32(auxc_buffer[i]);
u16 volume_ramp[96];
GenerateVolumeRamp(volume_ramp, m_last_aux_volumes[aux_id], volume, 96);
m_last_aux_volumes[aux_id] = volume;
int* mix_dest[4] = {
m_samples_left,
m_samples_right,
m_samples_surround,
m_samples_auxC_left
};
for (u32 mix_i = 0; mix_i < 4; ++mix_i)
{
int* dl_ptr = (int*)HLEMemory_Get_Pointer(addresses[2 + mix_i]);
for (u32 i = 0; i < 96; ++i)
aux_left[i] = Common::swap32(dl_ptr[i]);
for (u32 i = 0; i < 96; ++i)
{
s64 sample = (s64)(s32)aux_left[i];
sample *= volume_ramp[i];
mix_dest[mix_i][i] += (s32)(sample >> 15);
}
}
}
void CUCode_AXWii::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume,
bool upload_auxc)
{
u16 volume_ramp[96];
GenerateVolumeRamp(volume_ramp, m_last_main_volume, volume, 96);
m_last_main_volume = volume;
int upload_buffer[3 * 32] = { 0 };
for (u32 i = 0; i < 3 * 32; ++i)
upload_buffer[i] = Common::swap32(m_samples_surround[i]);
memcpy(HLEMemory_Get_Pointer(surround_addr), upload_buffer, sizeof (upload_buffer));
if (upload_auxc)
{
surround_addr += sizeof (upload_buffer);
for (u32 i = 0; i < 3 * 32; ++i)
upload_buffer[i] = Common::swap32(m_samples_auxC_left[i]);
memcpy(HLEMemory_Get_Pointer(surround_addr), upload_buffer, sizeof (upload_buffer));
}
short buffer[3 * 32 * 2];
// Clamp internal buffers to 16 bits.
for (u32 i = 0; i < 3 * 32; ++i)
{
int left = m_samples_left[i];
int right = m_samples_right[i];
// Apply global volume. Cast to s64 to avoid overflow.
left = ((s64)left * volume_ramp[i]) >> 15;
right = ((s64)right * volume_ramp[i]) >> 15;
if (left < -32767) left = -32767;
if (left > 32767) left = 32767;
if (right < -32767) right = -32767;
if (right > 32767) right = 32767;
m_samples_left[i] = left;
m_samples_right[i] = right;
}
for (u32 i = 0; i < 3 * 32; ++i)
{
buffer[2 * i] = Common::swap16(m_samples_right[i]);
buffer[2 * i + 1] = Common::swap16(m_samples_left[i]);
}
memcpy(HLEMemory_Get_Pointer(lr_addr), buffer, sizeof (buffer));
// There should be a DSP_SYNC message sent here. However, it looks like not
// sending it does not cause any issue, and sending it actually causes some
// sounds to go at half speed. I have no idea why.
}
void CUCode_AXWii::OutputWMSamples(u32* addresses)
{
int* buffers[] = {
m_samples_wm0,
m_samples_wm1,
m_samples_wm2,
m_samples_wm3
};
for (u32 i = 0; i < 4; ++i)
{
int* in = buffers[i];
u16* out = (u16*)HLEMemory_Get_Pointer(addresses[i]);
for (u32 j = 0; j < 3 * 6; ++j)
{
int sample = in[j];
if (sample < -32767) sample = -32767;
if (sample > 32767) sample = 32767;
out[j] = Common::swap16((u16)sample);
}
}
}
void CUCode_AXWii::DoState(PointerWrap &p)
{
std::lock_guard<std::mutex> lk(m_csMix);
p.Do(m_addressPBs);
p.Do(wiisportsHack);
std::lock_guard<std::mutex> lk(m_processing);
DoStateShared(p);
DoAXState(p);
p.Do(m_samples_auxC_left);
p.Do(m_samples_auxC_right);
p.Do(m_samples_auxC_surround);
p.Do(m_samples_wm0);
p.Do(m_samples_wm1);
p.Do(m_samples_wm2);
p.Do(m_samples_wm3);
p.Do(m_samples_aux0);
p.Do(m_samples_aux1);
p.Do(m_samples_aux2);
p.Do(m_samples_aux3);
p.Do(m_last_main_volume);
p.Do(m_last_aux_volumes);
}

View file

@ -12,44 +12,116 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _UCODE_AXWII
#define _UCODE_AXWII
#ifndef _UCODE_AXWII_H
#define _UCODE_AXWII_H
#include "UCode_AXWii_Structs.h"
#include "UCode_AX.h"
#define NUMBER_OF_PBS 128
class CUCode_AXWii : public IUCode
class CUCode_AXWii : public CUCode_AX
{
public:
CUCode_AXWii(DSPHLE *dsp_hle, u32 _CRC);
virtual ~CUCode_AXWii();
void HandleMail(u32 _uMail);
void MixAdd(short* _pBuffer, int _iSize);
void Update(int cycles);
void DoState(PointerWrap &p);
virtual void DoState(PointerWrap &p);
protected:
// Additional AUX buffers
int m_samples_auxC_left[32 * 3];
int m_samples_auxC_right[32 * 3];
int m_samples_auxC_surround[32 * 3];
// Wiimote buffers
int m_samples_wm0[6 * 3];
int m_samples_aux0[6 * 3];
int m_samples_wm1[6 * 3];
int m_samples_aux1[6 * 3];
int m_samples_wm2[6 * 3];
int m_samples_aux2[6 * 3];
int m_samples_wm3[6 * 3];
int m_samples_aux3[6 * 3];
// Are we implementing an old version of AXWii which still has updates?
bool m_old_axwii;
// Last volume values for MAIN and AUX. Used to generate volume ramps to
// interpolate nicely between old and new volume values.
u16 m_last_main_volume;
u16 m_last_aux_volumes[3];
// 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
// versions of AX.
AXMixControl ConvertMixerControl(u32 mixer_control);
// Generate a volume ramp from vol1 to vol2, interpolating n volume values.
// Uses floating point arithmetic, which isn't exactly what the UCode does,
// but this gives better precision and nicer code.
void GenerateVolumeRamp(u16* output, u16 vol1, u16 vol2, size_t nvals);
virtual void HandleCommandList();
void SetupProcessing(u32 init_addr);
void AddToLR(u32 val_addr, bool neg);
void AddSubToLR(u32 val_addr);
void ProcessPBList(u32 pb_addr);
void MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr, u16 volume);
void UploadAUXMixLRSC(int aux_id, u32* addresses, u16 volume);
void OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume,
bool upload_auxc);
void OutputWMSamples(u32* addresses); // 4 addresses
private:
enum
enum CmdType
{
MAIL_AX_ALIST = 0xBABE0000,
CMD_SETUP = 0x00,
CMD_ADD_TO_LR = 0x01,
CMD_SUB_TO_LR = 0x02,
CMD_ADD_SUB_TO_LR = 0x03,
CMD_PROCESS = 0x04,
CMD_MIX_AUXA = 0x05,
CMD_MIX_AUXB = 0x06,
CMD_MIX_AUXC = 0x07,
CMD_UPL_AUXA_MIX_LRSC = 0x08,
CMD_UPL_AUXB_MIX_LRSC = 0x09,
CMD_UNK_0A = 0x0A,
CMD_OUTPUT = 0x0B,
CMD_OUTPUT_DPL2 = 0x0C,
CMD_WM_OUTPUT = 0x0D,
CMD_END = 0x0E,
};
// PBs
u32 m_addressPBs;
bool wiisportsHack;
int *templbuffer;
int *temprbuffer;
// ax task message handler
bool AXTask(u32& _uMail);
void SendMail(u32 _uMail);
// 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_SUB_TO_LR_OLD = 0x02,
CMD_ADD_SUB_TO_LR_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_UPL_AUXA_MIX_LRSC_OLD = 0x09,
CMD_UPL_AUXB_MIX_LRSC_OLD = 0x0a,
CMD_UNK_0B_OLD = 0x0B,
CMD_OUTPUT_OLD = 0x0C, // no volume!
CMD_OUTPUT_DPL2_OLD = 0x0D,
CMD_WM_OUTPUT_OLD = 0x0E,
CMD_END_OLD = 0x0F
};
};
#endif // _UCODE_AXWII

View file

@ -1,92 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _UCODE_AX_ADPCM_H
#define _UCODE_AX_ADPCM_H
#include "../../DSP.h"
static inline s16 ADPCM_Step(PBADPCMInfo &adpcm, u32& samplePos, u32 newSamplePos, u16 frac)
{
while (samplePos < newSamplePos)
{
if ((samplePos & 15) == 0)
{
adpcm.pred_scale = DSP::ReadARAM((samplePos & ~15) >> 1);
samplePos += 2;
newSamplePos += 2;
}
int scale = 1 << (adpcm.pred_scale & 0xF);
int coef_idx = (adpcm.pred_scale >> 4) & 7;
s32 coef1 = adpcm.coefs[coef_idx * 2 + 0];
s32 coef2 = adpcm.coefs[coef_idx * 2 + 1];
int temp = (samplePos & 1) ?
(DSP::ReadARAM(samplePos >> 1) & 0xF) :
(DSP::ReadARAM(samplePos >> 1) >> 4);
if (temp >= 8)
temp -= 16;
// 0x400 = 0.5 in 11-bit fixed point
int val = (scale * temp) + ((0x400 + coef1 * adpcm.yn1 + coef2 * adpcm.yn2) >> 11);
if (val > 0x7FFF)
val = 0x7FFF;
else if (val < -0x7FFF)
val = -0x7FFF;
adpcm.yn2 = adpcm.yn1;
adpcm.yn1 = val;
samplePos++;
}
return adpcm.yn1;
}
// TODO: WTF is going on here?!?
// Volume control (ramping)
static inline u16 ADPCM_Vol(u16 vol, u16 delta)
{
int x = vol;
if (delta && delta < 0x5000)
x += delta * 20 * 8; // unsure what the right step is
//x += 1 * 20 * 8;
else if (delta && delta > 0x5000)
//x -= (0x10000 - delta); // this is to small, it's often 1
x -= (0x10000 - delta) * 20 * 16; // if this was 20 * 8 the sounds in Fire Emblem and Paper Mario
// did not have time to go to zero before the were closed
//x -= 1 * 20 * 16;
// make lower limits
if (x < 0) x = 0;
//if (pb.mixer_control < 1000 && x < pb.mixer_control) x = pb.mixer_control; // does this make
// any sense?
// make upper limits
//if (mixer_control > 1000 && x > mixer_control) x = mixer_control; // maybe mixer_control also
// has a volume target?
//if (x >= 0x7fff) x = 0x7fff; // this seems a little high
//if (x >= 0x4e20) x = 0x4e20; // add a definitive limit at 20 000
if (x >= 0x8000) x = 0x8000; // clamp to 32768;
return x; // update volume
}
#endif // _UCODE_AX_ADPCM_H

View file

@ -1,365 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _UCODE_AX_STRUCTS_H
#define _UCODE_AX_STRUCTS_H
struct PBMixer
{
u16 left;
u16 left_delta;
u16 right;
u16 right_delta;
u16 unknown3[8];
u16 unknown4[6];
};
struct PBMixerWii
{
// volume mixing values in .15, 0x8000 = ca. 1.0
u16 left;
u16 left_delta;
u16 right;
u16 right_delta;
u16 auxA_left;
u16 auxA_left_delta;
u16 auxA_right;
u16 auxA_right_delta;
u16 auxB_left;
u16 auxB_left_delta;
u16 auxB_right;
u16 auxB_right_delta;
// Note: the following elements usage changes a little in DPL2 mode
// TODO: implement and comment it in the mixer
u16 auxC_left;
u16 auxC_left_delta;
u16 auxC_right;
u16 auxC_right_delta;
u16 surround;
u16 surround_delta;
u16 auxA_surround;
u16 auxA_surround_delta;
u16 auxB_surround;
u16 auxB_surround_delta;
u16 auxC_surround;
u16 auxC_surround_delta;
};
struct PBMixerWM
{
u16 main0;
u16 main0_delta;
u16 aux0;
u16 aux0_delta;
u16 main1;
u16 main1_delta;
u16 aux1;
u16 aux1_delta;
u16 main2;
u16 main2_delta;
u16 aux2;
u16 aux2_delta;
u16 main3;
u16 main3_delta;
u16 aux3;
u16 aux3_delta;
};
struct PBInitialTimeDelay
{
u16 on;
u16 addrMemHigh;
u16 addrMemLow;
u16 offsetLeft;
u16 offsetRight;
u16 targetLeft;
u16 targetRight;
};
// Update data - read these each 1ms subframe and use them!
// It seems that to provide higher time precisions for MIDI events, some games
// use this thing to update the parameter blocks per 1ms sub-block (a block is 5ms).
// Using this data should fix games that are missing MIDI notes.
struct PBUpdates
{
u16 num_updates[5];
u16 data_hi; // These point to main RAM. Not sure about the structure of the data.
u16 data_lo;
};
// The DSP stores the final sample values for each voice after every frame of processing.
// The values are then accumulated for all dropped voices, added to the next frame of audio,
// and ramped down on a per-sample basis to provide a gentle "roll off."
struct PBDpop
{
s16 unknown[9];
};
struct PBDpopWii
{
s16 left;
s16 auxA_left;
s16 auxB_left;
s16 auxC_left;
s16 right;
s16 auxA_right;
s16 auxB_right;
s16 auxC_right;
s16 surround;
s16 auxA_surround;
s16 auxB_surround;
s16 auxC_surround;
};
struct PBDpopWM
{
s16 aMain0;
s16 aMain1;
s16 aMain2;
s16 aMain3;
s16 aAux0;
s16 aAux1;
s16 aAux2;
s16 aAux3;
};
struct PBVolumeEnvelope
{
u16 cur_volume; // volume at start of frame
s16 cur_volume_delta; // signed per sample delta (96 samples per frame)
};
struct PBUnknown2
{
u16 unknown_reserved[3];
};
struct PBAudioAddr
{
u16 looping;
u16 sample_format;
u16 loop_addr_hi; // Start of loop (this will point to a shared "zero" buffer if one-shot mode is active)
u16 loop_addr_lo;
u16 end_addr_hi; // End of sample (and loop), inclusive
u16 end_addr_lo;
u16 cur_addr_hi;
u16 cur_addr_lo;
};
struct PBADPCMInfo
{
s16 coefs[16];
u16 gain;
u16 pred_scale;
s16 yn1;
s16 yn2;
};
struct PBSampleRateConverter
{
// ratio = (f32)ratio * 0x10000;
// valid range is 1/512 to 4.0000
u16 ratio_hi; // integer part of sampling ratio
u16 ratio_lo; // fraction part of sampling ratio
u16 cur_addr_frac;
u16 last_samples[4];
};
struct PBSampleRateConverterWM
{
u16 currentAddressFrac;
u16 last_samples[4];
};
struct PBADPCMLoopInfo
{
u16 pred_scale;
u16 yn1;
u16 yn2;
};
struct AXPB
{
u16 next_pb_hi;
u16 next_pb_lo;
u16 this_pb_hi;
u16 this_pb_lo;
u16 src_type; // Type of sample rate converter (none, ?, linear)
u16 coef_select;
u16 mixer_control;
u16 running; // 1=RUN 0=STOP
u16 is_stream; // 1 = stream, 0 = one shot
PBMixer mixer;
PBInitialTimeDelay initial_time_delay;
PBUpdates updates;
PBDpop dpop;
PBVolumeEnvelope vol_env;
PBUnknown2 unknown3;
PBAudioAddr audio_addr;
PBADPCMInfo adpcm;
PBSampleRateConverter src;
PBADPCMLoopInfo adpcm_loop_info;
u16 unknown_maybe_padding[3];
};
struct PBLowPassFilter
{
u16 enabled;
u16 yn1;
u16 a0;
u16 b0;
};
struct PBBiquadFilter
{
u16 on; // on = 2, off = 0
u16 xn1; // History data
u16 xn2;
u16 yn1;
u16 yn2;
u16 b0; // Filter coefficients
u16 b1;
u16 b2;
u16 a1;
u16 a2;
};
union PBInfImpulseResponseWM
{
PBLowPassFilter lpf;
PBBiquadFilter biquad;
};
struct AXPBWii
{
u16 next_pb_hi;
u16 next_pb_lo;
u16 this_pb_hi;
u16 this_pb_lo;
u16 src_type; // Type of sample rate converter (none, 4-tap, linear)
u16 coef_select; // coef for the 4-tap src
u32 mixer_control;
u16 running; // 1=RUN 0=STOP
u16 is_stream; // 1 = stream, 0 = one shot
PBMixerWii mixer;
PBInitialTimeDelay initial_time_delay;
PBDpopWii dpop;
PBVolumeEnvelope vol_env;
PBAudioAddr audio_addr;
PBADPCMInfo adpcm;
PBSampleRateConverter src;
PBADPCMLoopInfo adpcm_loop_info;
PBLowPassFilter lpf;
PBBiquadFilter biquad;
// WIIMOTE :D
u16 remote;
u16 remote_mixer_control;
PBMixerWM remote_mixer;
PBDpopWM remote_dpop;
PBSampleRateConverterWM remote_src;
PBInfImpulseResponseWM remote_iir;
u16 pad[12]; // align us, captain! (32B)
};
// Seems like nintendo used an early version of AXWii and forgot to remove the update functionality ;p
struct PBUpdatesWiiSports
{
u16 num_updates[3];
u16 data_hi;
u16 data_lo;
};
struct AXPBWiiSports
{
u16 next_pb_hi;
u16 next_pb_lo;
u16 this_pb_hi;
u16 this_pb_lo;
u16 src_type; // Type of sample rate converter (none, 4-tap, linear)
u16 coef_select; // coef for the 4-tap src
u32 mixer_control;
u16 running; // 1=RUN 0=STOP
u16 is_stream; // 1 = stream, 0 = one shot
PBMixerWii mixer;
PBInitialTimeDelay initial_time_delay;
PBUpdatesWiiSports updates;
PBDpopWii dpop;
PBVolumeEnvelope vol_env;
PBAudioAddr audio_addr;
PBADPCMInfo adpcm;
PBSampleRateConverter src;
PBADPCMLoopInfo adpcm_loop_info;
PBLowPassFilter lpf;
PBBiquadFilter biquad;
// WIIMOTE :D
u16 remote;
u16 remote_mixer_control;
PBMixerWM remote_mixer;
PBDpopWM remote_dpop;
PBSampleRateConverterWM remote_src;
PBInfImpulseResponseWM remote_iir;
u16 pad[7]; // align us, captain! (32B)
};
// TODO: All these enums have changed a lot for wii
enum {
AUDIOFORMAT_ADPCM = 0,
AUDIOFORMAT_PCM8 = 0x19,
AUDIOFORMAT_PCM16 = 0xA,
};
enum {
SRCTYPE_LINEAR = 1,
SRCTYPE_NEAREST = 2,
MIXCONTROL_RAMPING = 8,
};
// Both may be used at once
enum {
FILTER_LOWPASS = 1,
FILTER_BIQUAD = 2,
};
#endif // _UCODE_AX_STRUCTS_H

View file

@ -1,271 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _UCODE_AXWII_VOICE_H
#define _UCODE_AXWII_VOICE_H
#include "UCodes.h"
#include "UCode_AXWii_ADPCM.h"
#include "UCode_AX.h"
#include "Mixer.h"
#include "../../AudioInterface.h"
// MRAM -> ARAM for GC
inline bool ReadPB(u32 addr, AXPB &PB)
{
const u16* PB_in_mram = (const u16*)Memory::GetPointer(addr);
if (PB_in_mram == NULL)
return false;
u16* PB_in_aram = (u16*)&PB;
for (size_t p = 0; p < (sizeof(AXPB) >> 1); p++)
{
PB_in_aram[p] = Common::swap16(PB_in_mram[p]);
}
return true;
}
// MRAM -> ARAM for Wii
inline bool ReadPB(u32 addr, AXPBWii &PB)
{
const u16* PB_in_mram = (const u16*)Memory::GetPointer(addr);
if (PB_in_mram == NULL)
return false;
u16* PB_in_aram = (u16*)&PB;
// preswap the mixer_control
PB.mixer_control = ((u32)PB_in_mram[7] << 16) | ((u32)PB_in_mram[6] >> 16);
for (size_t p = 0; p < (sizeof(AXPBWii) >> 1); p++)
{
PB_in_aram[p] = Common::swap16(PB_in_mram[p]);
}
return true;
}
// ARAM -> MRAM for GC
inline bool WritePB(u32 addr, AXPB &PB)
{
const u16* PB_in_aram = (const u16*)&PB;
u16* PB_in_mram = (u16*)Memory::GetPointer(addr);
if (PB_in_mram == NULL)
return false;
for (size_t p = 0; p < (sizeof(AXPB) >> 1); p++)
{
PB_in_mram[p] = Common::swap16(PB_in_aram[p]);
}
return true;
}
// ARAM -> MRAM for Wii
inline bool WritePB(u32 addr, AXPBWii &PB)
{
const u16* PB_in_aram = (const u16*)&PB;
u16* PB_in_mram = (u16*)Memory::GetPointer(addr);
if (PB_in_mram == NULL)
return false;
// preswap the mixer_control
*(u32*)&PB_in_mram[6] = (PB.mixer_control << 16) | (PB.mixer_control >> 16);
for (size_t p = 0; p < (sizeof(AXPBWii) >> 1); p++)
{
PB_in_mram[p] = Common::swap16(PB_in_aram[p]);
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// TODO: fix handling of gc/wii PB differences
// TODO: generally fix up the mess - looks crazy and kinda wrong
template<class ParamBlockType>
inline void MixAddVoice(ParamBlockType &pb,
int *templbuffer, int *temprbuffer,
int _iSize)
{
if (pb.running)
{
const u32 ratio = (u32)(((pb.src.ratio_hi << 16) + pb.src.ratio_lo)
* /*ratioFactor:*/((float)AudioInterface::GetAIDSampleRate() / (float)soundStream->GetMixer()->GetSampleRate()));
u32 sampleEnd = (pb.audio_addr.end_addr_hi << 16) | pb.audio_addr.end_addr_lo;
u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo;
u32 samplePos = (pb.audio_addr.cur_addr_hi << 16) | pb.audio_addr.cur_addr_lo;
u32 frac = pb.src.cur_addr_frac;
// =======================================================================================
// Handle No-SRC streams - No src streams have pb.src_type == 2 and have pb.src.ratio_hi = 0
// and pb.src.ratio_lo = 0. We handle that by setting the sampling ratio integer to 1. This
// makes samplePos update in the correct way. I'm unsure how we are actually supposed to
// detect that this setting. Updates did not fix this automatically.
// ---------------------------------------------------------------------------------------
// Stream settings
// src_type = 2 (most other games have src_type = 0)
// Affected games:
// Baten Kaitos - Eternal Wings (2003)
// Baten Kaitos - Origins (2006)?
// Soul Calibur 2: The movie music use src_type 2 but it needs no adjustment, perhaps
// the sound format plays in to, Baten use ADPCM, SC2 use PCM16
//if (pb.src_type == 2 && (pb.src.ratio_hi == 0 && pb.src.ratio_lo == 0))
if (pb.running && (pb.src.ratio_hi == 0 && pb.src.ratio_lo == 0))
{
pb.src.ratio_hi = 1;
}
// =======================================================================================
// Games that use looping to play non-looping music streams - SSBM has info in all
// pb.adpcm_loop_info parameters but has pb.audio_addr.looping = 0. If we treat these streams
// like any other looping streams the music works. I'm unsure how we are actually supposed to
// detect that these kinds of blocks should be looping. It seems like pb.mixer_control == 0 may
// identify these types of blocks. Updates did not write any looping values.
if (
(pb.adpcm_loop_info.pred_scale || pb.adpcm_loop_info.yn1 || pb.adpcm_loop_info.yn2)
&& pb.mixer_control == 0 && pb.adpcm_loop_info.pred_scale <= 0x7F
)
{
pb.audio_addr.looping = 1;
}
// Top Spin 3 Wii
if (pb.audio_addr.sample_format > 25)
pb.audio_addr.sample_format = 0;
// =======================================================================================
// Walk through _iSize. _iSize = numSamples. If the game goes slow _iSize will be higher to
// compensate for that. _iSize can be as low as 100 or as high as 2000 some cases.
for (int s = 0; s < _iSize; s++)
{
int sample = 0;
u32 oldFrac = frac;
frac += ratio;
u32 newSamplePos = samplePos + (frac >> 16); //whole number of frac
// =======================================================================================
// Process sample format
switch (pb.audio_addr.sample_format)
{
case AUDIOFORMAT_PCM8:
pb.adpcm.yn2 = ((s8)DSP::ReadARAM(samplePos)) << 8; //current sample
pb.adpcm.yn1 = ((s8)DSP::ReadARAM(samplePos + 1)) << 8; //next sample
if (pb.src_type == SRCTYPE_NEAREST)
sample = pb.adpcm.yn2;
else // linear interpolation
sample = (pb.adpcm.yn1 * (u16)oldFrac + pb.adpcm.yn2 * (u16)(0xFFFF - oldFrac) + pb.adpcm.yn2) >> 16;
samplePos = newSamplePos;
break;
case AUDIOFORMAT_PCM16:
pb.adpcm.yn2 = (s16)(u16)((DSP::ReadARAM(samplePos * 2) << 8) | (DSP::ReadARAM((samplePos * 2 + 1)))); //current sample
pb.adpcm.yn1 = (s16)(u16)((DSP::ReadARAM((samplePos + 1) * 2) << 8) | (DSP::ReadARAM(((samplePos + 1) * 2 + 1)))); //next sample
if (pb.src_type == SRCTYPE_NEAREST)
sample = pb.adpcm.yn2;
else // linear interpolation
sample = (pb.adpcm.yn1 * (u16)oldFrac + pb.adpcm.yn2 * (u16)(0xFFFF - oldFrac) + pb.adpcm.yn2) >> 16;
samplePos = newSamplePos;
break;
case AUDIOFORMAT_ADPCM:
ADPCM_Step(pb.adpcm, samplePos, newSamplePos, frac);
if (pb.src_type == SRCTYPE_NEAREST)
sample = pb.adpcm.yn2;
else // linear interpolation
sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac) + pb.adpcm.yn2) >> 16; //adpcm moves on frac
break;
default:
break;
}
// ===================================================================
// Overall volume control. In addition to this there is also separate volume settings to
// different channels (left, right etc).
frac &= 0xffff;
int vol = pb.vol_env.cur_volume >> 9;
sample = sample * vol >> 8;
if (pb.mixer_control & MIXCONTROL_RAMPING)
{
int x = pb.vol_env.cur_volume;
x += pb.vol_env.cur_volume_delta; // I'm not sure about this, can anybody find a game
// that use this? Or how does it work?
if (x < 0)
x = 0;
if (x >= 0x7fff)
x = 0x7fff;
pb.vol_env.cur_volume = x; // maybe not per sample?? :P
}
int leftmix = pb.mixer.left >> 5;
int rightmix = pb.mixer.right >> 5;
int left = sample * leftmix >> 8;
int right = sample * rightmix >> 8;
// adpcm has to walk from oldSamplePos to samplePos here
templbuffer[s] += left;
temprbuffer[s] += right;
// Control the behavior when we reach the end of the sample
if (samplePos >= sampleEnd)
{
if (pb.audio_addr.looping == 1)
{
if ((samplePos & ~0x1f) == (sampleEnd & ~0x1f) || (pb.audio_addr.sample_format != AUDIOFORMAT_ADPCM))
samplePos = loopPos;
if ((!pb.is_stream) && (pb.audio_addr.sample_format == AUDIOFORMAT_ADPCM))
{
pb.adpcm.yn1 = pb.adpcm_loop_info.yn1;
pb.adpcm.yn2 = pb.adpcm_loop_info.yn2;
pb.adpcm.pred_scale = pb.adpcm_loop_info.pred_scale;
}
}
else
{
pb.running = 0;
samplePos = loopPos;
//samplePos = samplePos - sampleEnd + loopPos;
memset(&pb.dpop, 0, sizeof(pb.dpop));
memset(pb.src.last_samples, 0, 8);
break;
}
}
} // end of the _iSize loop
// Update volume
pb.mixer.left = ADPCM_Vol(pb.mixer.left, pb.mixer.left_delta);
pb.mixer.right = ADPCM_Vol(pb.mixer.right, pb.mixer.right_delta);
pb.src.cur_addr_frac = (u16)frac;
pb.audio_addr.cur_addr_hi = samplePos >> 16;
pb.audio_addr.cur_addr_lo = (u16)samplePos;
} // if (pb.running)
}
#endif

View file

@ -27,13 +27,17 @@
#endif
#include "Common.h"
#include "UCode_AX_Structs.h"
#include "UCode_AXStructs.h"
#include "../../DSP.h"
#include <functional>
#ifdef AX_GC
# define PB_TYPE AXPB
# define MAX_SAMPLES_PER_FRAME 32
#else
# define PB_TYPE AXPBWii
# define MAX_SAMPLES_PER_FRAME 96
#endif
// Put all of that in an anonymous namespace to avoid stupid compilers merging
@ -65,13 +69,22 @@ union AXBuffers
int* auxC_left;
int* auxC_right;
int* auxC_surround;
int* wm_main0;
int* wm_aux0;
int* wm_main1;
int* wm_aux1;
int* wm_main2;
int* wm_aux2;
int* wm_main3;
int* wm_aux3;
#endif
};
#ifdef AX_GC
int* ptrs[9];
#else
int* ptrs[12];
int* ptrs[20];
#endif
};
@ -127,6 +140,7 @@ void DumpPB(const PB_TYPE& pb)
static u32 acc_loop_addr, acc_end_addr;
static u32* acc_cur_addr;
static PB_TYPE* acc_pb;
static bool acc_end_reached;
// Sets up the simulated accelerator.
void AcceleratorSetup(PB_TYPE* pb, u32* cur_addr)
@ -135,6 +149,7 @@ void AcceleratorSetup(PB_TYPE* pb, u32* cur_addr)
acc_loop_addr = HILO_TO_32(pb->audio_addr.loop_addr);
acc_end_addr = HILO_TO_32(pb->audio_addr.end_addr);
acc_cur_addr = cur_addr;
acc_end_reached = false;
}
// Reads a sample from the simulated accelerator. Also handles looping and
@ -144,6 +159,49 @@ u16 AcceleratorGetSample()
{
u16 ret;
// Have we reached the end address?
//
// On real hardware, this would raise an interrupt that is handled by the
// UCode. We simulate what this interrupt does here.
if ((*acc_cur_addr & ~1) == (acc_end_addr & ~1))
{
// loop back to loop_addr.
*acc_cur_addr = acc_loop_addr;
if (acc_pb->audio_addr.looping)
{
// Set the ADPCM infos to continue processing at loop_addr.
//
// For some reason, yn1 and yn2 aren't set if the voice is not of
// stream type. This is what the AX UCode does and I don't really
// know why.
acc_pb->adpcm.pred_scale = acc_pb->adpcm_loop_info.pred_scale;
if (!acc_pb->is_stream)
{
acc_pb->adpcm.yn1 = acc_pb->adpcm_loop_info.yn1;
acc_pb->adpcm.yn2 = acc_pb->adpcm_loop_info.yn2;
}
}
else
{
// Non looping voice reached the end -> running = 0.
acc_pb->running = 0;
#ifdef AX_WII
// One of the few meaningful differences between AXGC and AXWii:
// while AXGC handles non looping voices ending by having 0000
// samples at the loop address, AXWii has the 0000 samples
// internally in DRAM and use an internal pointer to it (loop addr
// does not contain 0000 samples on AXWii!).
acc_end_reached = true;
#endif
}
}
// See above for explanations about acc_end_reached.
if (acc_end_reached)
return 0;
switch (acc_pb->audio_addr.sample_format)
{
case 0x00: // ADPCM
@ -199,104 +257,159 @@ u16 AcceleratorGetSample()
return 0;
}
// Have we reached the end address?
//
// On real hardware, this would raise an interrupt that is handled by the
// UCode. We simulate what this interrupt does here.
if ((*acc_cur_addr & ~1) == (acc_end_addr & ~1))
{
// loop back to loop_addr.
*acc_cur_addr = acc_loop_addr;
if (acc_pb->audio_addr.looping)
{
// Set the ADPCM infos to continue processing at loop_addr.
//
// For some reason, yn1 and yn2 aren't set if the voice is not of
// stream type. This is what the AX UCode does and I don't really
// know why.
acc_pb->adpcm.pred_scale = acc_pb->adpcm_loop_info.pred_scale;
if (!acc_pb->is_stream)
{
acc_pb->adpcm.yn1 = acc_pb->adpcm_loop_info.yn1;
acc_pb->adpcm.yn2 = acc_pb->adpcm_loop_info.yn2;
}
}
else
{
// Non looping voice reached the end -> running = 0.
acc_pb->running = 0;
}
}
return ret;
}
// Read 32 input samples from ARAM, decoding and converting rate if required.
void GetInputSamples(PB_TYPE& pb, s16* samples)
// Reads samples from the input callback, resamples them to <count> samples at
// the wanted sample rate (computed from the ratio, see below).
//
// If srctype is SRCTYPE_POLYPHASE, coefficients need to be provided as well
// (or the srctype will automatically be changed to LINEAR).
//
// Returns the current position after resampling (including fractional part).
//
// The input to output ratio is set in <ratio>, which is a floating point num
// stored as a 32b integer:
// * Upper 16 bits of the ratio are the integer part
// * Lower 16 bits are the decimal part
//
// <curr_pos> is a 32b integer structured in the same way as the ratio: the
// upper 16 bits are the integer part of the current position in the input
// stream, and the lower 16 bits are the decimal part.
//
// We start getting samples not from sample 0, but 0.<curr_pos_frac>. This
// avoids discontinuties in the audio stream, especially with very low ratios
// which interpolate a lot of values between two "real" samples.
u32 ResampleAudio(std::function<s16(u32)> input_callback, s16* output, u32 count,
s16* last_samples, u32 curr_pos, u32 ratio, int srctype,
const s16* coeffs)
{
int read_samples_count = 0;
// TODO(delroth): find out why the polyphase resampling algorithm causes
// audio glitches in Wii games with non integral ratios.
// If DSP DROM coefficients are available, support polyphase resampling.
if (0) // if (coeffs && srctype == SRCTYPE_POLYPHASE)
{
s16 temp[4];
u32 idx = 0;
temp[idx++ & 3] = last_samples[0];
temp[idx++ & 3] = last_samples[1];
temp[idx++ & 3] = last_samples[2];
temp[idx++ & 3] = last_samples[3];
for (u32 i = 0; i < count; ++i)
{
curr_pos += ratio;
while (curr_pos >= 0x10000)
{
temp[idx++ & 3] = input_callback(read_samples_count++);
curr_pos -= 0x10000;
}
u16 curr_pos_frac = ((curr_pos & 0xFFFF) >> 9) << 2;
const s16* c = &coeffs[curr_pos_frac];
s64 t0 = temp[idx++ & 3];
s64 t1 = temp[idx++ & 3];
s64 t2 = temp[idx++ & 3];
s64 t3 = temp[idx++ & 3];
s64 samp = (t0 * c[0] + t1 * c[1] + t2 * c[2] + t3 * c[3]) >> 15;
output[i] = (s16)samp;
}
last_samples[3] = temp[--idx & 3];
last_samples[2] = temp[--idx & 3];
last_samples[1] = temp[--idx & 3];
last_samples[0] = temp[--idx & 3];
}
else if (srctype == SRCTYPE_LINEAR || srctype == SRCTYPE_POLYPHASE)
{
// This is the circular buffer containing samples to use for the
// interpolation. It is initialized with the values from the PB, and it
// will be stored back to the PB at the end.
s16 temp[4];
u32 idx = 0;
temp[idx++ & 3] = last_samples[0];
temp[idx++ & 3] = last_samples[1];
temp[idx++ & 3] = last_samples[2];
temp[idx++ & 3] = last_samples[3];
for (u32 i = 0; i < count; ++i)
{
curr_pos += ratio;
// While our current position is >= 1.0, push new samples to the
// circular buffer.
while (curr_pos >= 0x10000)
{
temp[idx++ & 3] = input_callback(read_samples_count++);
curr_pos -= 0x10000;
}
// Get our current fractional position, used to know how much of
// curr0 and how much of curr1 the output sample should be.
u16 curr_frac = curr_pos & 0xFFFF;
u16 inv_curr_frac = -curr_frac;
// Interpolate! If curr_frac is 0, we can simply take the last
// sample without any multiplying.
s16 sample;
if (curr_frac)
{
s32 s0 = temp[idx++ & 3];
s32 s1 = temp[idx++ & 3];
sample = ((s0 * inv_curr_frac) + (s1 * curr_frac)) >> 16;
idx += 2;
}
else
{
sample = temp[idx++ & 3];
idx += 3;
}
output[i] = sample;
}
// Update the four last_samples values.
last_samples[3] = temp[--idx & 3];
last_samples[2] = temp[--idx & 3];
last_samples[1] = temp[--idx & 3];
last_samples[0] = temp[--idx & 3];
}
else // SRCTYPE_NEAREST
{
// No sample rate conversion here: simply read samples from the
// accelerator to the output buffer.
for (u32 i = 0; i < count; ++i)
output[i] = input_callback(i);
memcpy(last_samples, output + count - 4, 4 * sizeof (u16));
}
return curr_pos;
}
// Read <count> input samples from ARAM, decoding and converting rate
// if required.
void GetInputSamples(PB_TYPE& pb, s16* samples, u16 count, const s16* coeffs)
{
u32 cur_addr = HILO_TO_32(pb.audio_addr.cur_addr);
AcceleratorSetup(&pb, &cur_addr);
// TODO: support polyphase interpolation if coefficients are available.
if (pb.src_type == SRCTYPE_POLYPHASE || pb.src_type == SRCTYPE_LINEAR)
{
// Convert the input to a higher or lower sample rate using a linear
// interpolation algorithm. The input to output ratio is set in
// pb.src.ratio, which is a floating point num stored as a 32b integer:
// * Upper 16 bits of the ratio are the integer part
// * Lower 16 bits are the decimal part
u32 ratio = HILO_TO_32(pb.src.ratio);
// We start getting samples not from sample 0, but 0.<cur_addr_frac>.
// This avoids discontinuties in the audio stream, especially with very
// low ratios which interpolate a lot of values between two "real"
// samples.
u32 curr_pos = pb.src.cur_addr_frac;
// These are the two samples between which we interpolate. The initial
// values are stored in the PB, and we update them when resampling the
// input data.
s16 curr0 = pb.src.last_samples[2];
s16 curr1 = pb.src.last_samples[3];
for (u32 i = 0; i < 32; ++i)
{
// Get our current fractional position, used to know how much of
// curr0 and how much of curr1 the output sample should be.
s32 curr_frac_pos = curr_pos & 0xFFFF;
// Linear interpolation: s1 + (s2 - s1) * pos
s16 sample = curr0 + (s16)(((curr1 - curr0) * (s32)curr_frac_pos) >> 16);
samples[i] = sample;
curr_pos += ratio;
// While our current position is >= 1.0, shift to the next 2
// samples for interpolation.
while ((curr_pos >> 16) != 0)
{
curr0 = curr1;
curr1 = AcceleratorGetSample();
curr_pos -= 0x10000;
}
}
// Update the two last_samples values in the PB as well as the current
// position.
pb.src.last_samples[2] = curr0;
pb.src.last_samples[3] = curr1;
pb.src.cur_addr_frac = curr_pos & 0xFFFF;
}
else // SRCTYPE_NEAREST
{
// No sample rate conversion here: simply read 32 samples from the
// accelerator to the output buffer.
for (u32 i = 0; i < 32; ++i)
samples[i] = AcceleratorGetSample();
memcpy(pb.src.last_samples, samples + 28, 4 * sizeof (u16));
}
if (coeffs)
coeffs += pb.coef_select * 0x200;
u32 curr_pos = ResampleAudio([](u32) { return AcceleratorGetSample(); },
samples, count, pb.src.last_samples,
pb.src.cur_addr_frac, HILO_TO_32(pb.src.ratio),
pb.src_type, coeffs);
pb.src.cur_addr_frac = (curr_pos & 0xFFFF);
// Update current position in the PB.
pb.audio_addr.cur_addr_hi = (u16)(cur_addr >> 16);
@ -304,7 +417,7 @@ void GetInputSamples(PB_TYPE& pb, s16* samples)
}
// Add samples to an output buffer, with optional volume ramping.
void MixAdd(int* out, const s16* input, u16* pvol, s16* dpop, bool ramp)
void MixAdd(int* out, const s16* input, u32 count, u16* pvol, s16* dpop, bool ramp)
{
u16& volume = pvol[0];
u16 volume_delta = pvol[1];
@ -315,7 +428,7 @@ void MixAdd(int* out, const s16* input, u16* pvol, s16* dpop, bool ramp)
if (!ramp)
volume_delta = 0;
for (u32 i = 0; i < 32; ++i)
for (u32 i = 0; i < count; ++i)
{
s64 sample = input[i];
sample *= volume;
@ -328,62 +441,69 @@ void MixAdd(int* out, const s16* input, u16* pvol, s16* dpop, bool ramp)
}
}
// Process 1ms of audio (32 samples) from a PB and mix it to the buffers.
void Process1ms(PB_TYPE& pb, const AXBuffers& buffers, AXMixControl mctrl)
// Execute a low pass filter on the samples using one history value. Returns
// the new history value.
s16 LowPassFilter(s16* samples, u32 count, s16 yn1, u16 a0, u16 b0)
{
for (u32 i = 0; i < count; ++i)
yn1 = samples[i] = (a0 * (s32)samples[i] + b0 * (s32)yn1) >> 15;
return yn1;
}
// Process 1ms of audio (for AX GC) or 3ms of audio (for AX Wii) from a PB and
// mix it to the output buffers.
void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl mctrl, const s16* coeffs)
{
// If the voice is not running, nothing to do.
if (!pb.running)
return;
// Read input samples, performing sample rate conversion if needed.
s16 samples[32];
GetInputSamples(pb, samples);
s16 samples[MAX_SAMPLES_PER_FRAME];
GetInputSamples(pb, samples, count, coeffs);
// Apply a global volume ramp using the volume envelope parameters.
for (u32 i = 0; i < 32; ++i)
for (u32 i = 0; i < count; ++i)
{
s64 sample = 2 * (s16)samples[i] * (s16)pb.vol_env.cur_volume;
samples[i] = (s16)(sample >> 16);
samples[i] = ((s32)samples[i] * pb.vol_env.cur_volume) >> 15;
pb.vol_env.cur_volume += pb.vol_env.cur_volume_delta;
}
// Optionally, execute a low pass filter
if (pb.lpf.enabled)
{
// TODO
}
pb.lpf.yn1 = LowPassFilter(samples, count, pb.lpf.yn1, pb.lpf.a0, pb.lpf.b0);
// Mix LRS, AUXA and AUXB depending on mixer_control
// TODO: Handle DPL2 on AUXB.
if (mctrl & MIX_L)
MixAdd(buffers.left, samples, &pb.mixer.left, &pb.dpop.left, mctrl & MIX_L_RAMP);
MixAdd(buffers.left, samples, count, &pb.mixer.left, &pb.dpop.left, mctrl & MIX_L_RAMP);
if (mctrl & MIX_R)
MixAdd(buffers.right, samples, &pb.mixer.right, &pb.dpop.right, mctrl & MIX_R_RAMP);
MixAdd(buffers.right, samples, count, &pb.mixer.right, &pb.dpop.right, mctrl & MIX_R_RAMP);
if (mctrl & MIX_S)
MixAdd(buffers.surround, samples, &pb.mixer.surround, &pb.dpop.surround, mctrl & MIX_S_RAMP);
MixAdd(buffers.surround, samples, count, &pb.mixer.surround, &pb.dpop.surround, mctrl & MIX_S_RAMP);
if (mctrl & MIX_AUXA_L)
MixAdd(buffers.auxA_left, samples, &pb.mixer.auxA_left, &pb.dpop.auxA_left, mctrl & MIX_AUXA_L_RAMP);
MixAdd(buffers.auxA_left, samples, count, &pb.mixer.auxA_left, &pb.dpop.auxA_left, mctrl & MIX_AUXA_L_RAMP);
if (mctrl & MIX_AUXA_R)
MixAdd(buffers.auxA_right, samples, &pb.mixer.auxA_right, &pb.dpop.auxA_right, mctrl & MIX_AUXA_R_RAMP);
MixAdd(buffers.auxA_right, samples, count, &pb.mixer.auxA_right, &pb.dpop.auxA_right, mctrl & MIX_AUXA_R_RAMP);
if (mctrl & MIX_AUXA_S)
MixAdd(buffers.auxA_surround, samples, &pb.mixer.auxA_surround, &pb.dpop.auxA_surround, mctrl & MIX_AUXA_S_RAMP);
MixAdd(buffers.auxA_surround, samples, count, &pb.mixer.auxA_surround, &pb.dpop.auxA_surround, mctrl & MIX_AUXA_S_RAMP);
if (mctrl & MIX_AUXB_L)
MixAdd(buffers.auxB_left, samples, &pb.mixer.auxB_left, &pb.dpop.auxB_left, mctrl & MIX_AUXB_L_RAMP);
MixAdd(buffers.auxB_left, samples, count, &pb.mixer.auxB_left, &pb.dpop.auxB_left, mctrl & MIX_AUXB_L_RAMP);
if (mctrl & MIX_AUXB_R)
MixAdd(buffers.auxB_right, samples, &pb.mixer.auxB_right, &pb.dpop.auxB_right, mctrl & MIX_AUXB_R_RAMP);
MixAdd(buffers.auxB_right, samples, count, &pb.mixer.auxB_right, &pb.dpop.auxB_right, mctrl & MIX_AUXB_R_RAMP);
if (mctrl & MIX_AUXB_S)
MixAdd(buffers.auxB_surround, samples, &pb.mixer.auxB_surround, &pb.dpop.auxB_surround, mctrl & MIX_AUXB_S_RAMP);
MixAdd(buffers.auxB_surround, samples, count, &pb.mixer.auxB_surround, &pb.dpop.auxB_surround, mctrl & MIX_AUXB_S_RAMP);
#ifdef AX_WII
if (mctrl & MIX_AUXC_L)
MixAdd(buffers.auxC_left, samples, &pb.mixer.auxC_left, &pb.dpop.auxC_left, mctrl & MIX_AUXC_L_RAMP);
MixAdd(buffers.auxC_left, samples, count, &pb.mixer.auxC_left, &pb.dpop.auxC_left, mctrl & MIX_AUXC_L_RAMP);
if (mctrl & MIX_AUXC_R)
MixAdd(buffers.auxC_right, samples, &pb.mixer.auxC_right, &pb.dpop.auxC_right, mctrl & MIX_AUXC_R_RAMP);
MixAdd(buffers.auxC_right, samples, count, &pb.mixer.auxC_right, &pb.dpop.auxC_right, mctrl & MIX_AUXC_R_RAMP);
if (mctrl & MIX_AUXC_S)
MixAdd(buffers.auxC_surround, samples, &pb.mixer.auxC_surround, &pb.dpop.auxC_surround, mctrl & MIX_AUXC_S_RAMP);
MixAdd(buffers.auxC_surround, samples, count, &pb.mixer.auxC_surround, &pb.dpop.auxC_surround, mctrl & MIX_AUXC_S_RAMP);
#endif
// Optionally, phase shift left or right channel to simulate 3D sound.
@ -391,6 +511,47 @@ void Process1ms(PB_TYPE& pb, const AXBuffers& buffers, AXMixControl mctrl)
{
// TODO
}
#ifdef AX_WII
// Wiimote mixing.
if (pb.remote)
{
// Old AXWii versions process ms per ms.
u16 wm_count = count == 96 ? 18 : 6;
// Interpolate at most 18 samples from the 96 samples we read before.
s16 wm_samples[18];
// We use ratio 0x55555 == (5 * 65536 + 21845) / 65536 == 5.3333 which
// is the nearest we can get to 96/18
u32 curr_pos = ResampleAudio([&samples](u32 i) { return samples[i]; },
wm_samples, wm_count, pb.remote_src.last_samples,
pb.remote_src.cur_addr_frac, 0x55555,
SRCTYPE_POLYPHASE, coeffs);
pb.remote_src.cur_addr_frac = curr_pos & 0xFFFF;
// Mix to main[0-3] and aux[0-3]
#define WMCHAN_MIX_ON(n) ((pb.remote_mixer_control >> (2 * n)) & 3)
#define WMCHAN_MIX_RAMP(n) ((pb.remote_mixer_control >> (2 * n)) & 2)
if (WMCHAN_MIX_ON(0))
MixAdd(buffers.wm_main0, wm_samples, wm_count, &pb.remote_mixer.main0, &pb.remote_dpop.main0, WMCHAN_MIX_RAMP(0));
if (WMCHAN_MIX_ON(1))
MixAdd(buffers.wm_aux0, wm_samples, wm_count, &pb.remote_mixer.aux0, &pb.remote_dpop.aux0, WMCHAN_MIX_RAMP(1));
if (WMCHAN_MIX_ON(2))
MixAdd(buffers.wm_main1, wm_samples, wm_count, &pb.remote_mixer.main1, &pb.remote_dpop.main1, WMCHAN_MIX_RAMP(2));
if (WMCHAN_MIX_ON(3))
MixAdd(buffers.wm_aux1, wm_samples, wm_count, &pb.remote_mixer.aux1, &pb.remote_dpop.aux1, WMCHAN_MIX_RAMP(3));
if (WMCHAN_MIX_ON(4))
MixAdd(buffers.wm_main2, wm_samples, wm_count, &pb.remote_mixer.main2, &pb.remote_dpop.main2, WMCHAN_MIX_RAMP(4));
if (WMCHAN_MIX_ON(5))
MixAdd(buffers.wm_aux2, wm_samples, wm_count, &pb.remote_mixer.aux2, &pb.remote_dpop.aux2, WMCHAN_MIX_RAMP(5));
if (WMCHAN_MIX_ON(6))
MixAdd(buffers.wm_main3, wm_samples, wm_count, &pb.remote_mixer.main3, &pb.remote_dpop.main3, WMCHAN_MIX_RAMP(6));
if (WMCHAN_MIX_ON(7))
MixAdd(buffers.wm_aux3, wm_samples, wm_count, &pb.remote_mixer.aux3, &pb.remote_dpop.aux3, WMCHAN_MIX_RAMP(7));
}
#endif
}
} // namespace

View file

@ -48,11 +48,11 @@ void CUCode_CARD::HandleMail(u32 _uMail)
{
if (_uMail == 0xFF000000) // unlock card
{
// m_Mails.push(0x00000001); // ACK (actualy anything != 0)
// m_Mails.push(0x00000001); // ACK (actually anything != 0)
}
else
{
DEBUG_LOG(DSPHLE, "CUCode_CARD - unknown cmd: %x", _uMail);
DEBUG_LOG(DSPHLE, "CUCode_CARD - unknown command: %x", _uMail);
}
m_rMailHandler.PushMail(DSP_DONE);

View file

@ -122,8 +122,8 @@ void CUCode_GBA::HandleMail(u32 _uMail)
*(u32*)HLEMemory_Get_Pointer(sec_params.dest_addr+4) = Common::swap32((x22 << 16) | x23);
// Done!
DEBUG_LOG(DSPHLE, "\n%08x -> key %08x len %08x dest_addr %08x unk1 %08x unk2 %08x"
" 22 %04x 23 %04x",
DEBUG_LOG(DSPHLE, "\n%08x -> key: %08x, len: %08x, dest_addr: %08x, unk1: %08x, unk2: %08x"
" 22: %04x, 23: %04x",
mramaddr,
*(u32*)sec_params.key, sec_params.length, sec_params.dest_addr,
*(u32*)sec_params.unk1, *(u32*)sec_params.unk2,
@ -143,12 +143,12 @@ void CUCode_GBA::HandleMail(u32 _uMail)
m_DSPHLE->SetUCode(UCODE_ROM);
break;
default:
DEBUG_LOG(DSPHLE, "CUCode_GBA - unknown 0xcdd1 cmd: %08x", _uMail);
DEBUG_LOG(DSPHLE, "CUCode_GBA - unknown 0xcdd1 command: %08x", _uMail);
break;
}
}
else
{
DEBUG_LOG(DSPHLE, "CUCode_GBA - unknown cmd: %08x", _uMail);
DEBUG_LOG(DSPHLE, "CUCode_GBA - unknown command: %08x", _uMail);
}
}

View file

@ -1,383 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "StringUtil.h"
#include "../MailHandler.h"
#include "Mixer.h"
#include "UCodes.h"
#include "UCode_AX_Structs.h"
#include "UCode_NewAXWii.h"
#define AX_WII
#include "UCode_AX_Voice.h"
CUCode_NewAXWii::CUCode_NewAXWii(DSPHLE *dsp_hle, u32 l_CRC)
: CUCode_AX(dsp_hle, l_CRC)
{
WARN_LOG(DSPHLE, "Instantiating CUCode_NewAXWii");
}
CUCode_NewAXWii::~CUCode_NewAXWii()
{
}
void CUCode_NewAXWii::HandleCommandList()
{
// Temp variables for addresses computation
u16 addr_hi, addr_lo;
u16 addr2_hi, addr2_lo;
u16 volume;
// WARN_LOG(DSPHLE, "Command list:");
// for (u32 i = 0; m_cmdlist[i] != CMD_END; ++i)
// WARN_LOG(DSPHLE, "%04x", m_cmdlist[i]);
// WARN_LOG(DSPHLE, "-------------");
u32 curr_idx = 0;
bool end = false;
while (!end)
{
u16 cmd = m_cmdlist[curr_idx++];
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_UNK_01: curr_idx += 2; 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;
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;
}
}
}
void CUCode_NewAXWii::SetupProcessing(u32 init_addr)
{
// TODO: should be easily factorizable with AX
s16 init_data[60];
for (u32 i = 0; i < 60; ++i)
init_data[i] = HLEMemory_Read_U16(init_addr + 2 * i);
// List of all buffers we have to initialize
struct {
int* ptr;
u32 samples;
} buffers[] = {
{ m_samples_left, 32 },
{ m_samples_right, 32 },
{ m_samples_surround, 32 },
{ m_samples_auxA_left, 32 },
{ m_samples_auxA_right, 32 },
{ m_samples_auxA_surround, 32 },
{ m_samples_auxB_left, 32 },
{ m_samples_auxB_right, 32 },
{ m_samples_auxB_surround, 32 },
{ m_samples_auxC_left, 32 },
{ m_samples_auxC_right, 32 },
{ m_samples_auxC_surround, 32 },
{ m_samples_wm0, 6 },
{ m_samples_aux0, 6 },
{ m_samples_wm1, 6 },
{ m_samples_aux1, 6 },
{ m_samples_wm2, 6 },
{ m_samples_aux2, 6 },
{ m_samples_wm3, 6 },
{ m_samples_aux3, 6 }
};
u32 init_idx = 0;
for (u32 i = 0; i < sizeof (buffers) / sizeof (buffers[0]); ++i)
{
s32 init_val = (s32)((init_data[init_idx] << 16) | init_data[init_idx + 1]);
s16 delta = (s16)init_data[init_idx + 2];
init_idx += 3;
if (!init_val)
memset(buffers[i].ptr, 0, 3 * buffers[i].samples * sizeof (int));
else
{
for (u32 j = 0; j < 3 * buffers[i].samples; ++j)
{
buffers[i].ptr[j] = init_val;
init_val += delta;
}
}
}
}
AXMixControl CUCode_NewAXWii::ConvertMixerControl(u32 mixer_control)
{
u32 ret = 0;
if (mixer_control & 0x00000001) ret |= MIX_L;
if (mixer_control & 0x00000002) ret |= MIX_R;
if (mixer_control & 0x00000004) ret |= MIX_L_RAMP | MIX_R_RAMP;
if (mixer_control & 0x00000008) ret |= MIX_S;
if (mixer_control & 0x00000010) ret |= MIX_S_RAMP;
if (mixer_control & 0x00010000) ret |= MIX_AUXA_L;
if (mixer_control & 0x00020000) ret |= MIX_AUXA_R;
if (mixer_control & 0x00040000) ret |= MIX_AUXA_L_RAMP | MIX_AUXA_R_RAMP;
if (mixer_control & 0x00080000) ret |= MIX_AUXA_S;
if (mixer_control & 0x00100000) ret |= MIX_AUXA_S_RAMP;
if (mixer_control & 0x00200000) ret |= MIX_AUXB_L;
if (mixer_control & 0x00400000) ret |= MIX_AUXB_R;
if (mixer_control & 0x00800000) ret |= MIX_AUXB_L_RAMP | MIX_AUXB_R_RAMP;
if (mixer_control & 0x01000000) ret |= MIX_AUXB_S;
if (mixer_control & 0x02000000) ret |= MIX_AUXB_S_RAMP;
if (mixer_control & 0x04000000) ret |= MIX_AUXC_L;
if (mixer_control & 0x08000000) ret |= MIX_AUXC_R;
if (mixer_control & 0x10000000) ret |= MIX_AUXC_L_RAMP | MIX_AUXC_R_RAMP;
if (mixer_control & 0x20000000) ret |= MIX_AUXC_S;
if (mixer_control & 0x40000000) ret |= MIX_AUXC_S_RAMP;
return (AXMixControl)ret;
}
void CUCode_NewAXWii::ProcessPBList(u32 pb_addr)
{
const u32 spms = 32;
AXPBWii pb;
while (pb_addr)
{
AXBuffers buffers = {{
m_samples_left,
m_samples_right,
m_samples_surround,
m_samples_auxA_left,
m_samples_auxA_right,
m_samples_auxA_surround,
m_samples_auxB_left,
m_samples_auxB_right,
m_samples_auxB_surround,
m_samples_auxC_left,
m_samples_auxC_right,
m_samples_auxC_surround
}};
if (!ReadPB(pb_addr, pb))
break;
for (int curr_ms = 0; curr_ms < 3; ++curr_ms)
{
Process1ms(pb, buffers, ConvertMixerControl(HILO_TO_32(pb.mixer_control)));
// Forward the buffers
for (u32 i = 0; i < sizeof (buffers.ptrs) / sizeof (buffers.ptrs[0]); ++i)
buffers.ptrs[i] += spms;
}
WritePB(pb_addr, pb);
pb_addr = HILO_TO_32(pb.next_pb);
}
}
void CUCode_NewAXWii::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr, u16 volume)
{
int* buffers[3] = { 0 };
int* main_buffers[3] = {
m_samples_left,
m_samples_right,
m_samples_surround
};
switch (aux_id)
{
case 0:
buffers[0] = m_samples_auxA_left;
buffers[1] = m_samples_auxA_right;
buffers[2] = m_samples_auxA_surround;
break;
case 1:
buffers[0] = m_samples_auxB_left;
buffers[1] = m_samples_auxB_right;
buffers[2] = m_samples_auxB_surround;
break;
case 2:
buffers[0] = m_samples_auxC_left;
buffers[1] = m_samples_auxC_right;
buffers[2] = m_samples_auxC_surround;
break;
}
// Send the content of AUX buffers to the CPU
if (write_addr)
{
int* ptr = (int*)HLEMemory_Get_Pointer(write_addr);
for (u32 i = 0; i < 3; ++i)
for (u32 j = 0; j < 3 * 32; ++j)
*ptr++ = Common::swap32(buffers[i][j]);
}
// Then read the buffers from the CPU and add to our main buffers.
int* ptr = (int*)HLEMemory_Get_Pointer(read_addr);
for (u32 i = 0; i < 3; ++i)
for (u32 j = 0; j < 3 * 32; ++j)
{
s64 new_val = main_buffers[i][j] + Common::swap32(*ptr++);
main_buffers[i][j] = (new_val * volume) >> 15;
}
}
void CUCode_NewAXWii::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume)
{
int surround_buffer[3 * 32] = { 0 };
for (u32 i = 0; i < 3 * 32; ++i)
surround_buffer[i] = Common::swap32(m_samples_surround[i]);
memcpy(HLEMemory_Get_Pointer(surround_addr), surround_buffer, sizeof (surround_buffer));
short buffer[3 * 32 * 2];
// Clamp internal buffers to 16 bits.
for (u32 i = 0; i < 3 * 32; ++i)
{
int left = m_samples_left[i];
int right = m_samples_right[i];
// Apply global volume. Cast to s64 to avoid overflow.
left = ((s64)left * volume) >> 15;
right = ((s64)right * volume) >> 15;
if (left < -32767) left = -32767;
if (left > 32767) left = 32767;
if (right < -32767) right = -32767;
if (right > 32767) right = 32767;
m_samples_left[i] = left;
m_samples_right[i] = right;
}
for (u32 i = 0; i < 3 * 32; ++i)
{
buffer[2 * i] = Common::swap16(m_samples_left[i]);
buffer[2 * i + 1] = Common::swap16(m_samples_right[i]);
}
memcpy(HLEMemory_Get_Pointer(lr_addr), buffer, sizeof (buffer));
}
void CUCode_NewAXWii::OutputWMSamples(u32* addresses)
{
int* buffers[] = {
m_samples_wm0,
m_samples_wm1,
m_samples_wm2,
m_samples_wm3
};
for (u32 i = 0; i < 4; ++i)
{
int* in = buffers[i];
u16* out = (u16*)HLEMemory_Get_Pointer(addresses[i]);
for (u32 j = 0; j < 3 * 6; ++j)
{
int sample = in[j];
if (sample < -32767) sample = -32767;
if (sample > 32767) sample = 32767;
out[j] = Common::swap16((u16)sample);
}
}
}
void CUCode_NewAXWii::DoState(PointerWrap &p)
{
std::lock_guard<std::mutex> lk(m_processing);
DoStateShared(p);
DoAXState(p);
p.Do(m_samples_auxC_left);
p.Do(m_samples_auxC_right);
p.Do(m_samples_auxC_surround);
p.Do(m_samples_wm0);
p.Do(m_samples_wm1);
p.Do(m_samples_wm2);
p.Do(m_samples_wm3);
p.Do(m_samples_aux0);
p.Do(m_samples_aux1);
p.Do(m_samples_aux2);
p.Do(m_samples_aux3);
}

View file

@ -1,80 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _UCODE_NEWAXWII_H
#define _UCODE_NEWAXWII_H
#include "UCode_AX.h"
class CUCode_NewAXWii : public CUCode_AX
{
public:
CUCode_NewAXWii(DSPHLE *dsp_hle, u32 _CRC);
virtual ~CUCode_NewAXWii();
virtual void DoState(PointerWrap &p);
protected:
int m_samples_auxC_left[32 * 3];
int m_samples_auxC_right[32 * 3];
int m_samples_auxC_surround[32 * 3];
// Wiimote buffers
int m_samples_wm0[6 * 3];
int m_samples_aux0[6 * 3];
int m_samples_wm1[6 * 3];
int m_samples_aux1[6 * 3];
int m_samples_wm2[6 * 3];
int m_samples_aux2[6 * 3];
int m_samples_wm3[6 * 3];
int m_samples_aux3[6 * 3];
// Convert a mixer_control bitfield to our internal representation for that
// value. Required because that bitfield has a different meaning in some
// versions of AX.
AXMixControl ConvertMixerControl(u32 mixer_control);
virtual void HandleCommandList();
void SetupProcessing(u32 init_addr);
void ProcessPBList(u32 pb_addr);
void MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr, u16 volume);
void OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume);
void OutputWMSamples(u32* addresses); // 4 addresses
private:
enum CmdType
{
CMD_SETUP = 0x00,
CMD_UNK_01 = 0x01,
CMD_UNK_02 = 0x02,
CMD_UNK_03 = 0x03,
CMD_PROCESS = 0x04,
CMD_MIX_AUXA = 0x05,
CMD_MIX_AUXB = 0x06,
CMD_MIX_AUXC = 0x07,
CMD_UNK_08 = 0x08,
CMD_UNK_09 = 0x09,
CMD_UNK_0A = 0x0A,
CMD_OUTPUT = 0x0B,
CMD_UNK_0C = 0x0C,
CMD_WM_OUTPUT = 0x0D,
CMD_END = 0x0E
};
};
#endif // _UCODE_AXWII

View file

@ -112,7 +112,7 @@ u8 *CUCode_Zelda::GetARAMPointer(u32 address)
void CUCode_Zelda::Update(int cycles)
{
if (!IsLightVersion())
if (!IsLightVersion())
{
if (m_rMailHandler.GetNextMail() == DSP_FRAME_END)
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
@ -445,7 +445,7 @@ void CUCode_Zelda::ExecuteList()
Sync = CmdMail >> 16;
DEBUG_LOG(DSPHLE, "==============================================================================");
DEBUG_LOG(DSPHLE, "Zelda UCode - execute dlist (cmd: 0x%04x : sync: 0x%04x)", Command, Sync);
DEBUG_LOG(DSPHLE, "Zelda UCode - execute dlist (command: 0x%04x : sync: 0x%04x)", Command, Sync);
switch (Command)
{
@ -545,7 +545,7 @@ void CUCode_Zelda::ExecuteList()
// default ... zelda ww jumps to 0x0043
default:
PanicAlert("Zelda UCode - unknown cmd: %x (size %i)", Command, m_numSteps);
PanicAlert("Zelda UCode - unknown command: %x (size %i)", Command, m_numSteps);
break;
}

View file

@ -218,7 +218,6 @@ private:
s32* m_LeftBuffer;
s32* m_RightBuffer;
// If you add variables, remember to keep DoState() and the constructor up to date.
s16 m_AFCCoefTable[32];

View file

@ -19,7 +19,6 @@
#include "UCode_AX.h"
#include "UCode_AXWii.h"
#include "UCode_NewAXWii.h"
#include "UCode_Zelda.h"
#include "UCode_ROM.h"
#include "UCode_CARD.h"
@ -27,12 +26,6 @@
#include "UCode_GBA.h"
#include "Hash.h"
#if 0
# define AXWII CUCode_NewAXWii
#else
# define AXWII CUCode_AXWii
#endif
IUCode* UCodeFactory(u32 _CRC, DSPHLE *dsp_hle, bool bWii)
{
switch (_CRC)
@ -97,13 +90,13 @@ IUCode* UCodeFactory(u32 _CRC, DSPHLE *dsp_hle, bool bWii)
case 0x4cc52064: // Bleach: Versus Crusade
case 0xd9c4bf34: // WiiMenu
INFO_LOG(DSPHLE, "CRC %08x: Wii - AXWii chosen", _CRC);
return new AXWII(dsp_hle, _CRC);
return new CUCode_AXWii(dsp_hle, _CRC);
default:
if (bWii)
{
PanicAlert("DSPHLE: Unknown ucode (CRC = %08x) - forcing AXWii.\n\nTry LLE emulator if this is homebrew.", _CRC);
return new AXWII(dsp_hle, _CRC);
return new CUCode_AXWii(dsp_hle, _CRC);
}
else
{

View file

@ -270,7 +270,7 @@ void DSPLLE::DSP_WriteMailBoxHigh(bool _CPUMailbox, u16 _uHighMail)
}
else
{
ERROR_LOG(DSPLLE, "CPU cant write to DSP mailbox");
ERROR_LOG(DSPLLE, "CPU can't write to DSP mailbox");
}
}
@ -282,7 +282,7 @@ void DSPLLE::DSP_WriteMailBoxLow(bool _CPUMailbox, u16 _uLowMail)
}
else
{
ERROR_LOG(DSPLLE, "CPU cant write to DSP mailbox");
ERROR_LOG(DSPLLE, "CPU can't write to DSP mailbox");
}
}

View file

@ -43,7 +43,7 @@ bool DumpDSPCode(const u8 *code_be, int size_in_bytes, u32 crc)
}
else
{
PanicAlert("Cant open file (%s) to dump UCode!!", binFile);
PanicAlert("Can't open file (%s) to dump UCode!!", binFile);
return false;
}

View file

@ -269,7 +269,7 @@ void AutoDisassembly(u16 start_addr, u16 end_addr)
break;
}
//NOTICE_LOG(DSPLLE, "added %04x %i %s", addr, line_counter, buf.c_str());
//NOTICE_LOG(DSPLLE, "Added %04x %i %s", addr, line_counter, buf.c_str());
lines.push_back(buf);
line_counter++;
}

View file

@ -671,7 +671,7 @@ void ExecuteCommand(UDICR& _DICR)
// Here is the actual Disk Reading
if (!DVDRead(iDVDOffset, m_DIMAR.Address, m_DILENGTH.Length))
{
PanicAlertT("Cant read from DVD_Plugin - DVD-Interface: Fatal Error");
PanicAlertT("Can't read from DVD_Plugin - DVD-Interface: Fatal Error");
}
}
break;
@ -681,7 +681,7 @@ void ExecuteCommand(UDICR& _DICR)
_dbg_assert_(DVDINTERFACE, m_DICMDBUF[2].Hex == m_DILENGTH.Length);
_dbg_assert_(DVDINTERFACE, m_DILENGTH.Length == 0x20);
if (!DVDRead(m_DICMDBUF[1].Hex, m_DIMAR.Address, m_DILENGTH.Length))
PanicAlertT("Cant read from DVD_Plugin - DVD-Interface: Fatal Error");
PanicAlertT("Can't read from DVD_Plugin - DVD-Interface: Fatal Error");
WARN_LOG(DVDINTERFACE, "Read DiscID %08x", Memory::Read_U32(m_DIMAR.Address));
break;
@ -712,7 +712,7 @@ void ExecuteCommand(UDICR& _DICR)
/*
if (iDVDOffset == 0x84800000)
{
ERROR_LOG(DVDINTERFACE, "firmware upload");
ERROR_LOG(DVDINTERFACE, "Firmware upload");
}
else*/
if ((offset < 0) || ((offset + len) > 0x40) || len > 0x40)

View file

@ -180,13 +180,13 @@ void CEXIChannel::Read32(u32& _uReturnValue, const u32 _iRegister)
_uReturnValue = 0xDEADBEEF;
}
DEBUG_LOG(EXPANSIONINTERFACE, "(r32) 0x%08x channel: %i reg: %s",
DEBUG_LOG(EXPANSIONINTERFACE, "(r32) 0x%08x channel: %i register: %s",
_uReturnValue, m_ChannelId, Debug_GetRegisterName(_iRegister));
}
void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister)
{
DEBUG_LOG(EXPANSIONINTERFACE, "(w32) 0x%08x channel: %i reg: %s",
DEBUG_LOG(EXPANSIONINTERFACE, "(w32) 0x%08x channel: %i register: %s",
_iValue, m_ChannelId, Debug_GetRegisterName(_iRegister));
switch (_iRegister)
@ -222,17 +222,17 @@ void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister)
break;
case EXI_DMAADDR:
INFO_LOG(EXPANSIONINTERFACE, "Wrote DMAAddr, chan %i", m_ChannelId);
INFO_LOG(EXPANSIONINTERFACE, "Wrote DMAAddr, channel %i", m_ChannelId);
m_DMAMemoryAddress = _iValue;
break;
case EXI_DMALENGTH:
INFO_LOG(EXPANSIONINTERFACE, "Wrote DMALength, chan %i", m_ChannelId);
INFO_LOG(EXPANSIONINTERFACE, "Wrote DMALength, channel %i", m_ChannelId);
m_DMALength = _iValue;
break;
case EXI_DMACONTROL:
INFO_LOG(EXPANSIONINTERFACE, "Wrote DMAControl, chan %i", m_ChannelId);
INFO_LOG(EXPANSIONINTERFACE, "Wrote DMAControl, channel %i", m_ChannelId);
m_Control.Hex = _iValue;
if (m_Control.TSTART)
@ -274,7 +274,7 @@ void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister)
break;
case EXI_IMMDATA:
INFO_LOG(EXPANSIONINTERFACE, "Wrote IMMData, chan %i", m_ChannelId);
INFO_LOG(EXPANSIONINTERFACE, "Wrote IMMData, channel %i", m_ChannelId);
m_ImmData = _iValue;
break;
}

View file

@ -111,7 +111,7 @@ void CEXIAMBaseboard::TransferByte(u8& _byte)
_byte = m_have_irq ? 0xFF : 0;
break;
default:
_dbg_assert_msg_(SP1, 0, "Unknown AM-BB cmd");
_dbg_assert_msg_(SP1, 0, "Unknown AM-BB command");
break;
}
}

View file

@ -113,7 +113,7 @@ CEXIETHERNET::CEXIETHERNET()
memcpy(&mBbaMem[BBA_NAFR_PAR0], mac_addr, 6);
}
// hax .. fully established 100BASE-T link
// HACK: .. fully established 100BASE-T link
mBbaMem[BBA_NWAYS] = NWAYS_LS100 | NWAYS_LPNWAY | NWAYS_100TXF | NWAYS_ANCLPT;
#if defined(_WIN32)
@ -175,7 +175,7 @@ void CEXIETHERNET::ImmWrite(u32 data, u32 size)
if (transfer.address == BBA_IOB && transfer.region == transfer.MX)
{
ERROR_LOG(SP1, "Usage of BBA_IOB indicates that the rx packet descriptor has been corrupted, killing dolphin...");
ERROR_LOG(SP1, "Usage of BBA_IOB indicates that the rx packet descriptor has been corrupted. Killing Dolphin...");
exit(0);
}
@ -248,7 +248,7 @@ u32 CEXIETHERNET::ImmRead(u32 size)
void CEXIETHERNET::DMAWrite(u32 addr, u32 size)
{
DEBUG_LOG(SP1, "dma w: %08x %x", addr, size);
DEBUG_LOG(SP1, "DMA write: %08x %x", addr, size);
if (transfer.region == transfer.MX &&
transfer.direction == transfer.WRITE &&
@ -258,7 +258,7 @@ void CEXIETHERNET::DMAWrite(u32 addr, u32 size)
}
else
{
ERROR_LOG(SP1, "dma w in %s %s mode - not implemented",
ERROR_LOG(SP1, "DMA write in %s %s mode - not implemented",
transfer.region == transfer.EXI ? "exi" : "mx",
transfer.direction == transfer.READ ? "read" : "write");
}
@ -266,7 +266,7 @@ void CEXIETHERNET::DMAWrite(u32 addr, u32 size)
void CEXIETHERNET::DMARead(u32 addr, u32 size)
{
DEBUG_LOG(SP1, "dma r: %08x %x", addr, size);
DEBUG_LOG(SP1, "DMA read: %08x %x", addr, size);
memcpy(Memory::GetPointer(addr), &mBbaMem[transfer.address], size);
@ -382,7 +382,7 @@ void CEXIETHERNET::MXCommandHandler(u32 data, u32 size)
case BBA_NCRA:
if (data & NCRA_RESET)
{
DEBUG_LOG(SP1, "software reset");
DEBUG_LOG(SP1, "Software reset");
//MXSoftReset();
Activate();
}
@ -400,16 +400,16 @@ void CEXIETHERNET::MXCommandHandler(u32 data, u32 size)
// Only start transfer if there isn't one currently running
if (!(mBbaMem[BBA_NCRA] & (NCRA_ST0 | NCRA_ST1)))
{
// Technically transfer dma status is kept in TXDMA - not implemented
// Technically transfer DMA status is kept in TXDMA - not implemented
if (data & NCRA_ST0)
{
WARN_LOG(SP1, "start tx - local dma");
WARN_LOG(SP1, "start tx - local DMA");
SendFromPacketBuffer();
}
else if (data & NCRA_ST1)
{
DEBUG_LOG(SP1, "start tx - direct fifo");
DEBUG_LOG(SP1, "start tx - direct FIFO");
SendFromDirectFIFO();
// Kind of a hack: send completes instantly, so we don't
// actually write the "send in status" bit to the register
@ -451,7 +451,7 @@ void CEXIETHERNET::DirectFIFOWrite(u8 *data, u32 size)
memcpy(tx_fifo + *tx_fifo_count, data, size);
*tx_fifo_count += size;
// TODO not sure this mask is correct.
// TODO: not sure this mask is correct.
// However, BBA_TXFIFOCNT should never get even close to this amount,
// so it shouldn't matter
*tx_fifo_count &= (1 << 12) - 1;
@ -464,7 +464,7 @@ void CEXIETHERNET::SendFromDirectFIFO()
void CEXIETHERNET::SendFromPacketBuffer()
{
ERROR_LOG(SP1, "tx packet buffer not implemented");
ERROR_LOG(SP1, "tx packet buffer not implemented.");
}
void CEXIETHERNET::SendComplete()
@ -484,7 +484,7 @@ void CEXIETHERNET::SendComplete()
inline u8 CEXIETHERNET::HashIndex(u8 *dest_eth_addr)
{
// Calculate crc
// Calculate CRC
u32 crc = 0xffffffff;
for (size_t byte_num = 0; byte_num < 6; ++byte_num)
@ -601,7 +601,7 @@ bool CEXIETHERNET::RecvHandlePacket()
if (AUTORCVR)
discard bad packet
else
inc MPC instad of recving packets
inc MPC instead of receiving packets
*/
status |= DESC_FO | DESC_BF;
mBbaMem[BBA_IR] |= mBbaMem[BBA_IMR] & INT_RBF;

View file

@ -222,7 +222,7 @@ void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize)
}
default:
ERROR_LOG(EXPANSIONINTERFACE, "Uknown USBGecko command %x", _uData);
ERROR_LOG(EXPANSIONINTERFACE, "Unknown USBGecko command %x", _uData);
break;
}
}

View file

@ -40,7 +40,7 @@
void CEXIMemoryCard::FlushCallback(u64 userdata, int cyclesLate)
{
// note that userdata is forbidden to be a pointer, due to the implemenation of EventDoState
// note that userdata is forbidden to be a pointer, due to the implementation of EventDoState
int card_index = (int)userdata;
CEXIMemoryCard* pThis = (CEXIMemoryCard*)ExpansionInterface::FindDevice(EXIDEVICE_MEMORYCARD, card_index);
if (pThis)
@ -86,7 +86,7 @@ CEXIMemoryCard::CEXIMemoryCard(const int index)
//0x00000510 16Mb "bigben" card
//card_id = 0xc243;
card_id = 0xc221; // It's a nintendo brand memcard
card_id = 0xc221; // It's a Nintendo brand memcard
File::IOFile pFile(m_strFilename, "rb");
if (pFile)
@ -110,7 +110,7 @@ CEXIMemoryCard::CEXIMemoryCard(const int index)
memory_card_content = new u8[memory_card_size];
GCMemcard::Format(memory_card_content, m_strFilename.find(".JAP.raw") != std::string::npos, nintendo_card_id);
memset(memory_card_content+MC_HDR_SIZE, 0xFF, memory_card_size-MC_HDR_SIZE);
WARN_LOG(EXPANSIONINTERFACE, "No memory card found. Will create new.");
WARN_LOG(EXPANSIONINTERFACE, "No memory card found. Will create a new one.");
}
SetCardFlashID(memory_card_content, card_index);
}
@ -130,7 +130,9 @@ void innerFlush(FlushData* data)
if (!pFile) // Note - pFile changed inside above if
{
PanicAlertT("Could not write memory card file %s.\n\n"
"Are you running Dolphin from a CD/DVD, or is the save file maybe write protected?", data->filename.c_str());
"Are you running Dolphin from a CD/DVD, or is the save file maybe write protected?\n\n"
"Are you receiving this after moving the emulator directory?\nIf so, then you may "
"need to re-specify your memory card location in the options.", data->filename.c_str());
return;
}
@ -148,6 +150,9 @@ void CEXIMemoryCard::Flush(bool exiting)
if(!m_bDirty)
return;
if (!Core::g_CoreStartupParameter.bEnableMemcardSaving)
return;
if (flushThread.joinable())
{
flushThread.join();
@ -337,11 +342,11 @@ void CEXIMemoryCard::TransferByte(u8 &byte)
{
case cmdNintendoID:
//
// nintendo card:
// Nintendo card:
// 00 | 80 00 00 00 10 00 00 00
// "bigben" card:
// 00 | ff 00 00 05 10 00 00 00 00 00 00 00 00 00 00
// we do it the nintendo way.
// we do it the Nintendo way.
if (m_uPosition == 1)
byte = 0x80; // dummy cycle
else

View file

@ -89,9 +89,11 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
}
// __________________________________________________________________________________________________
// Function: PAD_Rumble
// Function: Rumble
// Purpose: Pad rumble!
// input: PAD number, Command type (Stop=0, Rumble=1, Stop Hard=2) and strength of Rumble
// input: _numPad - Which pad to rumble.
// _uType - Command type (Stop=0, Rumble=1, Stop Hard=2).
// _uStrength - Strength of the Rumble
// output: none
//
void Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
@ -116,8 +118,9 @@ void Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
// __________________________________________________________________________________________________
// Function: Motor
// Purpose: For devices with constant Force feedback
// input: Type - 06 = Motor On, 04 = Motor Off
// Strength - 00 = Left Strong, 127 = Left Weak, 128 = Right Weak, 255 = Right Strong
// input: _numPAD - The pad to operate on
// _uType - 06 = Motor On, 04 = Motor Off
// _uStrength - 00 = Left Strong, 127 = Left Weak, 128 = Right Weak, 255 = Right Strong
// output: none
//
void Motor(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)

View file

@ -124,28 +124,28 @@ void Read32(u32& _uReturnValue, const u32 _iAddress)
return;
case PI_FIFO_BASE:
DEBUG_LOG(PROCESSORINTERFACE, "read cpu fifo base, value = %08x", Fifo_CPUBase);
DEBUG_LOG(PROCESSORINTERFACE, "Read CPU FIFO base, value = %08x", Fifo_CPUBase);
_uReturnValue = Fifo_CPUBase;
return;
case PI_FIFO_END:
DEBUG_LOG(PROCESSORINTERFACE, "read cpu fifo end, value = %08x", Fifo_CPUEnd);
DEBUG_LOG(PROCESSORINTERFACE, "Read CPU FIFO end, value = %08x", Fifo_CPUEnd);
_uReturnValue = Fifo_CPUEnd;
return;
case PI_FIFO_WPTR:
DEBUG_LOG(PROCESSORINTERFACE, "read writepointer, value = %08x", Fifo_CPUWritePointer);
DEBUG_LOG(PROCESSORINTERFACE, "Read writepointer, value = %08x", Fifo_CPUWritePointer);
_uReturnValue = Fifo_CPUWritePointer; //really writes in 32-byte chunks
// Monk's gcube does some crazy align trickery here.
return;
case PI_RESET_CODE:
INFO_LOG(PROCESSORINTERFACE, "read reset code, 0x%08x", m_ResetCode);
INFO_LOG(PROCESSORINTERFACE, "Read reset code, 0x%08x", m_ResetCode);
_uReturnValue = m_ResetCode;
return;
case PI_FLIPPER_REV:
INFO_LOG(PROCESSORINTERFACE, "read flipper rev, 0x%08x", m_FlipperRev);
INFO_LOG(PROCESSORINTERFACE, "Read flipper rev, 0x%08x", m_FlipperRev);
_uReturnValue = m_FlipperRev;
return;
@ -202,7 +202,7 @@ void Write32(const u32 _uValue, const u32 _iAddress)
break;
case PI_FLIPPER_UNK:
DEBUG_LOG(PROCESSORINTERFACE, "write %08x to unknown PI reg %08x", _uValue, _iAddress);
DEBUG_LOG(PROCESSORINTERFACE, "Write %08x to unknown PI register %08x", _uValue, _iAddress);
break;
default:

View file

@ -143,7 +143,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
{
case 0x10:
{
DEBUG_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 10, %02x (READ STATUS&SWITCHES)", ptr(1));
DEBUG_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 10, %02x (READ STATUS&SWITCHES)", ptr(1));
SPADStatus PadStatus;
memset(&PadStatus, 0 ,sizeof(PadStatus));
Pad::GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
@ -161,13 +161,13 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
break;
}
case 0x12:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 12, %02x %02x", ptr(1), ptr(2));
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 12, %02x %02x", ptr(1), ptr(2));
res[resp++] = 0x12;
res[resp++] = 0x00;
break;
case 0x11:
{
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 11, %02x (READ SERIAL NR)", ptr(1));
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 11, %02x (READ SERIAL NR)", ptr(1));
char string[] = "AADE-01A14964511";
res[resp++] = 0x11;
res[resp++] = 0x10;
@ -183,7 +183,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
res[resp++] = 0x29; // FIRM VERSION
break;
case 0x16:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 16, %02x (READ FPGA VERSION)", ptr(1));
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 16, %02x (READ FPGA VERSION)", ptr(1));
res[resp++] = 0x16;
res[resp++] = 0x02;
res[resp++] = 0x07;
@ -196,7 +196,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
break;
case 0x1f:
{
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 1f, %02x %02x %02x %02x %02x (REGION)", ptr(1), ptr(2), ptr(3), ptr(4), ptr(5));
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 1f, %02x %02x %02x %02x %02x (REGION)", ptr(1), ptr(2), ptr(3), ptr(4), ptr(5));
unsigned char string[] =
"\x00\x00\x30\x00"
//"\x01\xfe\x00\x00" // JAPAN
@ -211,14 +211,14 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
break;
}
case 0x31:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 31 (UNKNOWN)");
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 31 (UNKNOWN)");
res[resp++] = 0x31;
res[resp++] = 0x02;
res[resp++] = 0x00;
res[resp++] = 0x00;
break;
case 0x32:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 32 (UNKNOWN)");
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 32 (UNKNOWN)");
res[resp++] = 0x32;
res[resp++] = 0x02;
res[resp++] = 0x00;
@ -241,7 +241,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
case 0x4e:
case 0x4f:
{
DEBUG_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD %02x, %02x %02x %02x %02x %02x %02x %02x (JVS IO)",
DEBUG_LOG(AMBASEBOARDDEBUG, "GC-AM: Command %02x, %02x %02x %02x %02x %02x %02x %02x (JVS IO)",
ptr(0), ptr(1), ptr(2), ptr(3), ptr(4), ptr(5), ptr(6), ptr(7));
int pptr = 2;
JVSIOMessage msg;
@ -262,7 +262,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
{
int cmd = *jvs_io++;
DEBUG_LOG(AMBASEBOARDDEBUG, "JVS IO, node=%d, cmd=%02x", node, cmd);
DEBUG_LOG(AMBASEBOARDDEBUG, "JVS IO, node=%d, command=%02x", node, cmd);
switch (cmd)
{
@ -391,10 +391,10 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
break;
}
case 0x60:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 60, %02x %02x %02x", ptr(1), ptr(2), ptr(3));
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 60, %02x %02x %02x", ptr(1), ptr(2), ptr(3));
break;
default:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD %02x (unknown) %02x %02x %02x %02x %02x", ptr(0), ptr(1), ptr(2), ptr(3), ptr(4), ptr(5));
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command %02x (unknown) %02x %02x %02x %02x %02x", ptr(0), ptr(1), ptr(2), ptr(3), ptr(4), ptr(5));
break;
}
p += ptr(1) + 2;
@ -414,7 +414,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
log += sprintf(log, "%02x ", ptr(i));
}
ptr(0x7f) = ~csum;
DEBUG_LOG(AMBASEBOARDDEBUG, "command send back: %s", logptr);
DEBUG_LOG(AMBASEBOARDDEBUG, "Command send back: %s", logptr);
#undef ptr
@ -438,7 +438,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
// DEFAULT
default:
{
ERROR_LOG(SERIALINTERFACE, "unknown SI command (0x%x)", command);
ERROR_LOG(SERIALINTERFACE, "Unknown SI command (0x%x)", command);
PanicAlert("SI: Unknown command");
iPosition = _iLength;
}
@ -460,6 +460,6 @@ bool CSIDevice_AMBaseboard::GetData(u32& _Hi, u32& _Low)
void CSIDevice_AMBaseboard::SendCommand(u32 _Cmd, u8 _Poll)
{
ERROR_LOG(SERIALINTERFACE, "unknown direct command (0x%x)", _Cmd);
ERROR_LOG(SERIALINTERFACE, "Unknown direct command (0x%x)", _Cmd);
PanicAlert("SI: (GCAM) Unknown direct command");
}

View file

@ -107,7 +107,7 @@ void GBASockServer::Transfer(char* si_buffer)
else
client.Send(current_data, 1);
DEBUG_LOG(SERIALINTERFACE, "> cmd %02x %02x%02x%02x%02x",
DEBUG_LOG(SERIALINTERFACE, "> command %02x %02x%02x%02x%02x",
(u8)current_data[0], (u8)current_data[1], (u8)current_data[2],
(u8)current_data[3], (u8)current_data[4]);

View file

@ -108,7 +108,7 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
// DEFAULT
default:
{
ERROR_LOG(SERIALINTERFACE, "unknown SI command (0x%x)", command);
ERROR_LOG(SERIALINTERFACE, "Unknown SI command (0x%x)", command);
PanicAlert("SI: Unknown command (0x%x)", command);
}
break;
@ -275,7 +275,7 @@ void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll)
default:
{
ERROR_LOG(SERIALINTERFACE, "unknown direct command (0x%x)", _Cmd);
ERROR_LOG(SERIALINTERFACE, "Unknown direct command (0x%x)", _Cmd);
PanicAlert("SI: Unknown direct command");
}
break;

View file

@ -99,7 +99,7 @@ int CSIDevice_GCSteeringWheel::RunBuffer(u8* _pBuffer, int _iLength)
// DEFAULT
default:
{
ERROR_LOG(SERIALINTERFACE, "unknown SI command (0x%x)", command);
ERROR_LOG(SERIALINTERFACE, "Unknown SI command (0x%x)", command);
}
break;
}
@ -297,7 +297,7 @@ void CSIDevice_GCSteeringWheel::SendCommand(u32 _Cmd, u8 _Poll)
default:
{
ERROR_LOG(SERIALINTERFACE, "unknown direct command (0x%x)", _Cmd);
ERROR_LOG(SERIALINTERFACE, "Unknown direct command (0x%x)", _Cmd);
}
break;
}

View file

@ -243,29 +243,29 @@ void PreInit()
void Init()
{
const int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.bVBeam ? 2 : 1;
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
{
if (!DSP::GetDSPEmulator()->IsLLE())
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
// AyuanX: TO BE TWEAKED
// Now the 1500 is a pure assumption
// We need to figure out the real frequency though
// FYI, WII_IPC_HLE_Interface::Update is also called in WII_IPCInterface::Write32
const int freq = 1500;
const int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.
bVBeam ? 2 : 1;
IPC_HLE_PERIOD = GetTicksPerSecond() / (freq * fields);
}
else
{
if (!DSP::GetDSPEmulator()->IsLLE())
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.005f);
}
if (DSP::GetDSPEmulator()->IsLLE())
DSP_PERIOD = 12000; // TO BE TWEAKED
{
DSP_PERIOD = 12600; // TO BE TWEAKED
}
else
{
// AX HLE uses 3ms (Wii) or 5ms (GC) timing period
int ms_to_process = SConfig::GetInstance().m_LocalCoreStartupParameter.bWii ? 3 : 5;
DSP_PERIOD = (int)(GetTicksPerSecond() / 1000) * ms_to_process / fields;
}
// System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA
AUDIO_DMA_PERIOD = CPU_CORE_CLOCK / (AudioInterface::GetAIDSampleRate() * 4 / 32);

View file

@ -407,11 +407,11 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
case VI_UNK_AA_REG_HI:
_uReturnValue = (m_UnkAARegister & 0xffff0000) >> 16;
WARN_LOG(VIDEOINTERFACE, "(r16) unknown AA reg, not sure what it does :)");
WARN_LOG(VIDEOINTERFACE, "(r16) unknown AA register, not sure what it does :)");
break;
case VI_UNK_AA_REG_LO:
_uReturnValue = m_UnkAARegister & 0x0000ffff;
WARN_LOG(VIDEOINTERFACE, "(r16) unknown AA reg, not sure what it does :)");
WARN_LOG(VIDEOINTERFACE, "(r16) unknown AA register, not sure what it does :)");
break;
case VI_CLOCK:
@ -434,7 +434,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
break;
default:
ERROR_LOG(VIDEOINTERFACE, "(r16) unk reg %x", _iAddress & 0xfff);
ERROR_LOG(VIDEOINTERFACE, "(r16) unknown reg %x", _iAddress & 0xfff);
_uReturnValue = 0x0;
break;
}
@ -659,11 +659,11 @@ void Write16(const u16 _iValue, const u32 _iAddress)
case VI_UNK_AA_REG_HI:
m_UnkAARegister = (m_UnkAARegister & 0x0000ffff) | (u32)(_iValue << 16);
WARN_LOG(VIDEOINTERFACE, "(w16) to unknown AA reg, not sure what it does :)");
WARN_LOG(VIDEOINTERFACE, "(w16) to unknown AA register, not sure what it does :)");
break;
case VI_UNK_AA_REG_LO:
m_UnkAARegister = (m_UnkAARegister & 0xffff0000) | _iValue;
WARN_LOG(VIDEOINTERFACE, "(w16) to unknown AA reg, not sure what it does :)");
WARN_LOG(VIDEOINTERFACE, "(w16) to unknown AA register, not sure what it does :)");
break;
case VI_CLOCK:
@ -686,7 +686,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
break;
default:
ERROR_LOG(VIDEOINTERFACE, "(w16) %04x to unk reg %x", _iValue, _iAddress & 0xfff);
ERROR_LOG(VIDEOINTERFACE, "(w16) %04x to unknown register %x", _iValue, _iAddress & 0xfff);
break;
}
}
@ -812,7 +812,7 @@ static void BeginField(FieldType field)
static const char* const fieldTypeNames[] = { "Progressive", "Upper", "Lower" };
DEBUG_LOG(VIDEOINTERFACE, "(VI->BeginField): addr: %.08X | FieldSteps %u | FbSteps %u | ACV %u | Field %s",
DEBUG_LOG(VIDEOINTERFACE, "(VI->BeginField): Address: %.08X | FieldSteps %u | FbSteps %u | ACV %u | Field %s",
xfbAddr, m_HorizontalStepping.FieldSteps, m_HorizontalStepping.FbSteps, m_VerticalTimingRegister.ACV,
fieldTypeNames[field]
);

View file

@ -194,7 +194,7 @@ void Write32(const u32 _Value, const u32 _Address)
_Value, ctrl.ppc(), ctrl.Y1, ctrl.Y2, ctrl.X1);
if (ctrl.X1)
{
INFO_LOG(WII_IPC, "new pointer available: %08x", ppc_msg);
INFO_LOG(WII_IPC, "New pointer available: %08x", ppc_msg);
// Let the HLE handle the request on it's own time
WII_IPC_HLE_Interface::EnqRequest(ppc_msg);
}

View file

@ -55,11 +55,16 @@ void Initialize(void* const hwnd)
}
// __________________________________________________________________________________________________
// Function: Wiimote_Output
// Function: ControlChannel
// Purpose: An L2CAP packet is passed from the Core to the Wiimote,
// on the HID CONTROL channel.
// input: Da pakket.
// output: none
//
// Inputs: _number [Description needed]
// _channelID [Description needed]
// _pData [Description needed]
// _Size [Description needed]
//
// Output: none
//
void ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
{
@ -71,11 +76,16 @@ void ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
}
// __________________________________________________________________________________________________
// Function: Wiimote_InterruptChannel
// Function: InterruptChannel
// Purpose: An L2CAP packet is passed from the Core to the Wiimote,
// on the HID INTERRUPT channel.
// input: Da pakket.
// output: none
//
// Inputs: _number [Description needed]
// _channelID [Description needed]
// _pData [Description needed]
// _Size [Description needed]
//
// Output: none
//
void InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
{
@ -86,9 +96,9 @@ void InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size
}
// __________________________________________________________________________________________________
// Function: Wiimote_Update
// Purpose: This function is called periodically by the Core.
// input: none
// Function: Update
// Purpose: This function is called periodically by the Core. // TODO: Explain why.
// input: _number: [Description needed]
// output: none
//
void Update(int _number)
@ -113,10 +123,10 @@ void Update(int _number)
}
// __________________________________________________________________________________________________
// Function: PAD_GetAttachedPads
// Function: GetAttached
// Purpose: Get mask of attached pads (eg: controller 1 & 4 -> 0x9)
// input: none
// output: number of pads
// input: none
// output: The number of attached pads
//
unsigned int GetAttached()
{
@ -130,8 +140,8 @@ unsigned int GetAttached()
// ___________________________________________________________________________
// Function: DoState
// Purpose: Saves/load state
// input/output: ptr
// input: mode
// input/output: ptr: [Description Needed]
// input: mode [Description needed]
//
void DoState(u8 **ptr, PointerWrap::Mode mode)
{
@ -145,7 +155,7 @@ void DoState(u8 **ptr, PointerWrap::Mode mode)
// ___________________________________________________________________________
// Function: EmuStateChange
// Purpose: Notifies the plugin of a change in emulation state
// input: newState
// input: newState - The new state for the Wiimote to change to.
// output: none
//
void EmuStateChange(EMUSTATE_CHANGE newState)

View file

@ -360,7 +360,7 @@ void Wiimote::WriteData(const wm_write_data* const wd)
/* TODO?
if (region_ptr == &m_reg_speaker)
{
ERROR_LOG(WIIMOTE, "Write to speaker reg %x %s", address,
ERROR_LOG(WIIMOTE, "Write to speaker register %x %s", address,
ArrayToString(wd->data, wd->size, 100, false).c_str());
}
*/
@ -511,7 +511,7 @@ void Wiimote::ReadData(const wm_read_data* const rd)
break;
default :
PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x)!", size, rd->space);
PanicAlert("WmReadData: unimplemented parameters (size: %i, address: 0x%x)!", size, rd->space);
break;
}

View file

@ -707,10 +707,10 @@ void Wiimote::Update()
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
if (g_wiimotes[m_index])
{
Report rpt = g_wiimotes[m_index]->ProcessReadQueue();
const u8 *real_data = rpt.first;
if (real_data)
const Report& rpt = g_wiimotes[m_index]->ProcessReadQueue();
if (!rpt.empty())
{
const u8 *real_data = rpt.data();
switch (real_data[1])
{
// use data reports
@ -770,13 +770,9 @@ void Wiimote::Update()
// copy over report from real-wiimote
if (-1 == rptf_size)
{
memcpy(data, real_data, rpt.second);
rptf_size = rpt.second;
std::copy(rpt.begin(), rpt.end(), data);
rptf_size = rpt.size();
}
if (real_data != g_wiimotes[m_index]->\
m_last_data_report.first)
delete[] real_data;
}
}
}

View file

@ -300,7 +300,7 @@ bool Wiimote::Connect()
TCHAR name[128] = {};
HidD_GetProductString(dev_handle, name, 128);
//ERROR_LOG(WIIMOTE, "product string: %s", TStrToUTF8(name).c_str());
//ERROR_LOG(WIIMOTE, "Product string: %s", TStrToUTF8(name).c_str());
if (!IsValidBluetoothName(TStrToUTF8(name)))
{
@ -333,7 +333,7 @@ bool Wiimote::Connect()
/*
if (!SetThreadPriority(m_wiimote_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL))
{
ERROR_LOG(WIIMOTE, "Failed to set wiimote thread priority");
ERROR_LOG(WIIMOTE, "Failed to set Wiimote thread priority");
}
*/
#ifdef SHARE_WRITE_WIIMOTES
@ -370,73 +370,55 @@ bool Wiimote::IsConnected() const
// zero = error
int Wiimote::IORead(u8* buf)
{
// used below for a warning
*buf = 0;
// Add data report indicator byte (here, 0xa1)
buf[0] = 0xa1;
// Used below for a warning
buf[1] = 0;
DWORD bytes;
DWORD bytes = 0;
ResetEvent(hid_overlap_read.hEvent);
if (!ReadFile(dev_handle, buf, MAX_PAYLOAD - 1, &bytes, &hid_overlap_read))
if (!ReadFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap_read))
{
auto const err = GetLastError();
auto const read_err = GetLastError();
if (ERROR_IO_PENDING == err)
if (ERROR_IO_PENDING == read_err)
{
auto const r = WaitForSingleObject(hid_overlap_read.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
if (WAIT_TIMEOUT == r)
auto const wait_result = WaitForSingleObject(hid_overlap_read.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
if (WAIT_TIMEOUT == wait_result)
{
// Timeout - cancel and continue
if (*buf)
WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem (timeout is %i ms).",
CancelIo(dev_handle);
}
else if (WAIT_FAILED == wait_result)
{
WARN_LOG(WIIMOTE, "A wait error occurred on reading from Wiimote %i.", index + 1);
CancelIo(dev_handle);
}
if (!GetOverlappedResult(dev_handle, &hid_overlap_read, &bytes, TRUE))
{
auto const overlapped_err = GetLastError();
if (ERROR_OPERATION_ABORTED == overlapped_err)
{
if (buf[1] != 0)
WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem (timeout is %i ms).",
WIIMOTE_DEFAULT_TIMEOUT);
CancelIo(dev_handle);
bytes = -1;
}
else if (WAIT_FAILED == r)
{
WARN_LOG(WIIMOTE, "A wait error occured on reading from wiimote %i.", index + 1);
bytes = 0;
}
else if (WAIT_OBJECT_0 == r)
{
if (!GetOverlappedResult(dev_handle, &hid_overlap_read, &bytes, TRUE))
{
WARN_LOG(WIIMOTE, "GetOverlappedResult failed on wiimote %i.", index + 1);
bytes = 0;
return -1;
}
WARN_LOG(WIIMOTE, "GetOverlappedResult error %d on Wiimote %i.", overlapped_err, index + 1);
return 0;
}
else
{
bytes = 0;
}
}
else if (ERROR_HANDLE_EOF == err)
{
// Remote disconnect
bytes = 0;
}
else if (ERROR_DEVICE_NOT_CONNECTED == err)
{
// Remote disconnect
bytes = 0;
}
else
{
bytes = 0;
WARN_LOG(WIIMOTE, "ReadFile error %d on Wiimote %i.", read_err, index + 1);
return 0;
}
}
if (bytes > 0)
{
// Move the data over one, so we can add back in data report indicator byte (here, 0xa1)
std::copy_n(buf, MAX_PAYLOAD - 1, buf + 1);
buf[0] = 0xa1;
// TODO: is this really needed?
bytes = MAX_PAYLOAD;
}
return bytes;
return bytes + 1;
}
int Wiimote::IOWrite(const u8* buf, int len)
@ -468,7 +450,7 @@ int Wiimote::IOWrite(const u8* buf, int len)
if (err == 121)
{
// Semaphore timeout
NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to wiimote");
NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to the Wiimote");
}
else
{
@ -553,8 +535,8 @@ void ProcessWiimotes(bool new_scan, T& callback)
HBLUETOOTH_DEVICE_FIND hFindDevice = Bth_BluetoothFindFirstDevice(&srch, &btdi);
while (hFindDevice)
{
// btdi.szName is sometimes missings it's content - it's a bt feature..
DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ",
// btdi.szName is sometimes missing it's content - it's a bt feature..
DEBUG_LOG(WIIMOTE, "Authenticated %i connected %i remembered %i ",
btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered);
if (IsValidBluetoothName(UTF16ToUTF8(btdi.szName)))
@ -597,7 +579,7 @@ bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO& radio_info, BLUETO
{
auto const& wm_addr = btdi.Address.rgBytes;
NOTICE_LOG(WIIMOTE, "Found wiimote (%02x:%02x:%02x:%02x:%02x:%02x). Enabling HID service.",
NOTICE_LOG(WIIMOTE, "Found Wiimote (%02x:%02x:%02x:%02x:%02x:%02x). Enabling HID service.",
wm_addr[0], wm_addr[1], wm_addr[2], wm_addr[3], wm_addr[4], wm_addr[5]);
#if defined(AUTHENTICATE_WIIMOTES)
@ -647,7 +629,7 @@ bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{
// Make Windows forget about device so it will re-find it if visible.
// This is also required to detect a disconnect for some reason..
NOTICE_LOG(WIIMOTE, "Removing remembered wiimote.");
NOTICE_LOG(WIIMOTE, "Removing remembered Wiimote.");
Bth_BluetoothRemoveDevice(&btdi.Address);
return true;
}

View file

@ -57,7 +57,7 @@ Wiimote::Wiimote()
#elif defined(_WIN32)
, dev_handle(0), stack(MSBT_STACK_UNKNOWN)
#endif
, m_last_data_report(Report((u8 *)NULL, 0))
, m_last_input_report()
, m_channel(0), m_run_thread(false)
{
#if defined(__linux__) && HAVE_BLUEZ
@ -73,11 +73,7 @@ Wiimote::~Wiimote()
Disconnect();
ClearReadQueue();
// clear write queue
Report rpt;
while (m_write_reports.Pop(rpt))
delete[] rpt.first;
m_write_reports.Clear();
}
// to be called from CPU thread
@ -85,17 +81,18 @@ void Wiimote::QueueReport(u8 rpt_id, const void* _data, unsigned int size)
{
auto const data = static_cast<const u8*>(_data);
Report rpt;
rpt.second = size + 2;
rpt.first = new u8[rpt.second];
rpt.first[0] = WM_SET_REPORT | WM_BT_OUTPUT;
rpt.first[1] = rpt_id;
std::copy(data, data + size, rpt.first + 2);
m_write_reports.Push(rpt);
Report rpt(size + 2);
rpt[0] = WM_SET_REPORT | WM_BT_OUTPUT;
rpt[1] = rpt_id;
std::copy_n(data, size, rpt.begin() + 2);
m_write_reports.Push(std::move(rpt));
}
void Wiimote::DisableDataReporting()
{
m_last_input_report.clear();
// This probably accomplishes nothing.
wm_report_mode rpt = {};
rpt.mode = WM_REPORT_CORE;
rpt.all_the_time = 0;
@ -107,15 +104,10 @@ void Wiimote::DisableDataReporting()
void Wiimote::ClearReadQueue()
{
Report rpt;
if (m_last_data_report.first)
{
delete[] m_last_data_report.first;
m_last_data_report.first = NULL;
}
// The "Clear" function isn't thread-safe :/
while (m_read_reports.Pop(rpt))
delete[] rpt.first;
{}
}
void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size)
@ -148,65 +140,58 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const
}
auto const data = static_cast<const u8*>(_data);
Report rpt;
rpt.first = new u8[size];
rpt.second = (u8)size;
std::copy(data, data + size, rpt.first);
Report rpt(data, data + size);
// Convert output DATA packets to SET_REPORT packets.
// Nintendo Wiimotes work without this translation, but 3rd
// party ones don't.
if (rpt.first[0] == 0xa2)
if (rpt[0] == 0xa2)
{
rpt.first[0] = WM_SET_REPORT | WM_BT_OUTPUT;
rpt[0] = WM_SET_REPORT | WM_BT_OUTPUT;
}
// Disallow games from turning off all of the LEDs.
// It makes wiimote connection status confusing.
if (rpt.first[1] == WM_LEDS)
// It makes Wiimote connection status confusing.
if (rpt[1] == WM_LEDS)
{
auto& leds_rpt = *reinterpret_cast<wm_leds*>(&rpt.first[2]);
auto& leds_rpt = *reinterpret_cast<wm_leds*>(&rpt[2]);
if (0 == leds_rpt.leds)
{
// Turn on ALL of the LEDs.
leds_rpt.leds = 0xf;
}
}
else if (rpt.first[1] == WM_WRITE_SPEAKER_DATA
else if (rpt[1] == WM_WRITE_SPEAKER_DATA
&& !SConfig::GetInstance().m_WiimoteEnableSpeaker)
{
// Translate speaker data reports into rumble reports.
rpt.first[1] = WM_CMD_RUMBLE;
rpt[1] = WM_RUMBLE;
// Keep only the rumble bit.
rpt.first[2] &= 0x1;
rpt.second = 3;
rpt[2] &= 0x1;
rpt.resize(3);
}
m_write_reports.Push(rpt);
m_write_reports.Push(std::move(rpt));
}
bool Wiimote::Read()
{
Report rpt;
rpt.first = new unsigned char[MAX_PAYLOAD];
rpt.second = IORead(rpt.first);
Report rpt(MAX_PAYLOAD);
auto const result = IORead(rpt.data());
if (0 == rpt.second)
if (result > 0 && m_channel > 0)
{
WARN_LOG(WIIMOTE, "Wiimote::IORead failed. Disconnecting wiimote %d.", index + 1);
// Add it to queue
rpt.resize(result);
m_read_reports.Push(std::move(rpt));
return true;
}
else if (0 == result)
{
WARN_LOG(WIIMOTE, "Wiimote::IORead failed. Disconnecting Wiimote %d.", index + 1);
Disconnect();
}
if (rpt.second > 0 && m_channel > 0)
{
// Add it to queue
m_read_reports.Push(rpt);
return true;
}
delete[] rpt.first;
return false;
}
@ -216,16 +201,15 @@ bool Wiimote::Write()
{
Report const& rpt = m_write_reports.Front();
bool const is_speaker_data = rpt.first[1] == WM_WRITE_SPEAKER_DATA;
bool const is_speaker_data = rpt[1] == WM_WRITE_SPEAKER_DATA;
if (!is_speaker_data || m_last_audio_report.GetTimeDifference() > 5)
{
IOWrite(rpt.first, rpt.second);
IOWrite(rpt.data(), rpt.size());
if (is_speaker_data)
m_last_audio_report.Update();
delete[] rpt.first;
m_write_reports.Pop();
return true;
}
@ -234,23 +218,35 @@ bool Wiimote::Write()
return false;
}
bool IsDataReport(const Report& rpt)
{
return rpt.size() >= 2 && rpt[1] >= WM_REPORT_CORE;
}
// Returns the next report that should be sent
Report Wiimote::ProcessReadQueue()
const Report& Wiimote::ProcessReadQueue()
{
// Pop through the queued reports
Report rpt = m_last_data_report;
while (m_read_reports.Pop(rpt))
while (m_read_reports.Pop(m_last_input_report))
{
if (rpt.first[1] >= WM_REPORT_CORE)
// A data report
m_last_data_report = rpt;
else
// Some other kind of report
return rpt;
if (!IsDataReport(m_last_input_report))
{
// A non-data report, use it.
return m_last_input_report;
// Forget the last data report as it may be of the wrong type
// or contain outdated button data
// or it's not supposed to be sent at this time
// It's just easier to be correct this way and it's probably not horrible.
}
}
// The queue was empty, or there were only data reports
return rpt;
// If the last report wasn't a data report it's irrelevant.
if (!IsDataReport(m_last_input_report))
m_last_input_report.clear();
// If it was a data report, we repeat that until something else comes in.
return m_last_input_report;
}
void Wiimote::Update()
@ -262,16 +258,12 @@ void Wiimote::Update()
}
// Pop through the queued reports
Report const rpt = ProcessReadQueue();
const Report& rpt = ProcessReadQueue();
// Send the report
if (rpt.first != NULL && m_channel > 0)
if (!rpt.empty() && m_channel > 0)
Core::Callback_WiimoteInterruptChannel(index, m_channel,
rpt.first, rpt.second);
// Delete the data if it isn't also the last data rpt
if (rpt != m_last_data_report)
delete[] rpt.first;
rpt.data(), rpt.size());
}
bool Wiimote::Prepare(int _index)
@ -279,13 +271,13 @@ bool Wiimote::Prepare(int _index)
index = _index;
// core buttons, no continuous reporting
u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_REPORT_TYPE, 0, 0x30};
u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REPORT_MODE, 0, WM_REPORT_CORE};
// Set the active LEDs and turn on rumble.
u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_LED, u8(WIIMOTE_LED_1 << index | 0x1)};
u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << index | 0x1)};
// Turn off rumble
u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_RUMBLE, 0};
u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_RUMBLE, 0};
// Request status report
u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0};
@ -308,12 +300,12 @@ void Wiimote::EmuStop()
DisableDataReporting();
NOTICE_LOG(WIIMOTE, "Stopping wiimote data reporting");
NOTICE_LOG(WIIMOTE, "Stopping Wiimote data reporting.");
}
unsigned int CalculateWantedWiimotes()
{
// Figure out how many real wiimotes are required
// Figure out how many real Wiimotes are required
unsigned int wanted_wiimotes = 0;
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] && !g_wiimotes[i])
@ -329,7 +321,7 @@ void WiimoteScanner::WantWiimotes(bool do_want)
void WiimoteScanner::StartScanning()
{
if (!m_run_thread && IsReady())
if (!m_run_thread)
{
m_run_thread = true;
m_scan_thread = std::thread(std::mem_fun(&WiimoteScanner::ThreadFunc), this);
@ -358,13 +350,13 @@ void WiimoteScanner::ThreadFunc()
{
Common::SetCurrentThreadName("Wiimote Scanning Thread");
NOTICE_LOG(WIIMOTE, "Wiimote scanning has started");
NOTICE_LOG(WIIMOTE, "Wiimote scanning has started.");
while (m_run_thread)
{
std::vector<Wiimote*> found_wiimotes;
//NOTICE_LOG(WIIMOTE, "in loop");
//NOTICE_LOG(WIIMOTE, "In loop");
if (m_want_wiimotes)
found_wiimotes = FindWiimotes();
@ -374,7 +366,7 @@ void WiimoteScanner::ThreadFunc()
Update();
}
//NOTICE_LOG(WIIMOTE, "after update");
//NOTICE_LOG(WIIMOTE, "After update");
// TODO: this is a fairly lame place for this
CheckForDisconnectedWiimotes();
@ -385,7 +377,7 @@ void WiimoteScanner::ThreadFunc()
Common::SleepCurrentThread(500);
}
NOTICE_LOG(WIIMOTE, "Wiimote scanning has stopped");
NOTICE_LOG(WIIMOTE, "Wiimote scanning has stopped.");
}
void Wiimote::StartThread()
@ -485,7 +477,7 @@ void ChangeWiimoteSource(unsigned int index, int source)
DoneWithWiimote(index);
}
// reconnect to emu
// reconnect to the emulator
Host_ConnectWiimote(index, false);
if (WIIMOTE_SRC_EMU & source)
Host_ConnectWiimote(index, true);
@ -502,7 +494,7 @@ void TryToConnectWiimote(Wiimote* wm)
{
if (wm->Connect() && wm->Prepare(i))
{
NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", i + 1);
NOTICE_LOG(WIIMOTE, "Connected to Wiimote %i.", i + 1);
std::swap(g_wiimotes[i], wm);
g_wiimotes[i]->StartThread();
@ -528,7 +520,7 @@ void DoneWithWiimote(int index)
{
g_wiimotes[index]->StopThread();
// First see if we can use this real wiimote in another slot.
// First see if we can use this real Wiimote in another slot.
for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
{
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
@ -546,7 +538,7 @@ void DoneWithWiimote(int index)
}
}
// else, just disconnect the wiimote
// else, just disconnect the Wiimote
HandleWiimoteDisconnect(index);
}
@ -563,7 +555,7 @@ void HandleWiimoteDisconnect(int index)
if (wm)
{
delete wm;
NOTICE_LOG(WIIMOTE, "Disconnected wiimote %i.", index + 1);
NOTICE_LOG(WIIMOTE, "Disconnected Wiimote %i.", index + 1);
}
}
@ -583,7 +575,7 @@ void Refresh()
if (0 != CalculateWantedWiimotes())
{
// Don't hang dolphin when searching
// Don't hang Dolphin when searching
lk.unlock();
found_wiimotes = g_wiimote_scanner.FindWiimotes();
lk.lock();
@ -591,7 +583,7 @@ void Refresh()
CheckForDisconnectedWiimotes();
// Brief rumble for already connected wiimotes.
// Brief rumble for already connected Wiimotes.
for (int i = 0; i != MAX_WIIMOTES; ++i)
{
if (g_wiimotes[i])
@ -633,7 +625,7 @@ void Update(int _WiimoteNumber)
if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->Update();
// Wiimote::Update() may remove the wiimote if it was disconnected.
// Wiimote::Update() may remove the Wiimote if it was disconnected.
if (!g_wiimotes[_WiimoteNumber])
{
Host_ConnectWiimote(_WiimoteNumber, false);

View file

@ -33,8 +33,7 @@
#include "../../InputCommon/Src/InputConfig.h"
// Pointer to data, and size of data
typedef std::pair<u8*,u8> Report;
typedef std::vector<u8> Report;
namespace WiimoteReal
{
@ -50,7 +49,7 @@ public:
void InterruptChannel(const u16 channel, const void* const data, const u32 size);
void Update();
Report ProcessReadQueue();
const Report& ProcessReadQueue();
bool Read();
bool Write();
@ -99,7 +98,7 @@ public:
#endif
protected:
Report m_last_data_report;
Report m_last_input_report;
u16 m_channel;
private:

View file

@ -41,20 +41,6 @@
#define WM_SET_REPORT 0xA0
#endif
// TODO: duplicated in WiimoteHid.h
// Commands
#define WM_CMD_RUMBLE 0x10
#define WM_CMD_LED 0x11
#define WM_CMD_REPORT_TYPE 0x12
#define WM_CMD_IR 0x13
#define WM_CMD_SPEAKER_ENABLE 0x14
#define WM_CMD_CTRL_STATUS 0x15
#define WM_CMD_WRITE_DATA 0x16
#define WM_CMD_READ_DATA 0x17
#define WM_CMD_SPEAKER_DATA 0x18
#define WM_CMD_SPEAKER_MUTE 0x19
#define WM_CMD_IR_2 0x1A
#define WM_BT_INPUT 0x01
#define WM_BT_OUTPUT 0x02
@ -73,12 +59,12 @@
#ifdef _WIN32
// Available bluetooth stacks for Windows.
typedef enum win_bt_stack_t
enum win_bt_stack_t
{
MSBT_STACK_UNKNOWN,
MSBT_STACK_MS,
MSBT_STACK_BLUESOLEIL
} win_bt_stack_t;
};
#endif
#endif // WIIMOTE_COMM_H

View file

@ -523,7 +523,7 @@ void ExecuteCommand(u32 _Address)
if (CmdSuccess)
{
// Ensure replies happen in order, fairly ugly
// Without this, tons of games fail now that DI commads have different reply delays
// Without this, tons of games fail now that DI commands have different reply delays
int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0;
const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks();

View file

@ -223,7 +223,7 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
}
else
{
INFO_LOG(WII_IPC_DVD, "DVDLowRead: file unkw - (DVDAddr: 0x%llx, Size: 0x%x)",
INFO_LOG(WII_IPC_DVD, "DVDLowRead: file unknown - (DVDAddr: 0x%llx, Size: 0x%x)",
DVDAddress, Size);
}
}
@ -360,7 +360,7 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
}
else
{
INFO_LOG(WII_IPC_DVD, "DVDLowSeek: file unkw - (DVDAddr: 0x%llx)",
INFO_LOG(WII_IPC_DVD, "DVDLowSeek: file unknown - (DVDAddr: 0x%llx)",
DVDAddress);
}
}
@ -446,15 +446,15 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
// but it seems we don't need to implement anything
case 0x95:
case 0x96:
WARN_LOG(WII_IPC_DVD, "unimplemented cmd 0x%08x (Buffer 0x%08x, 0x%x)",
WARN_LOG(WII_IPC_DVD, "Unimplemented command 0x%08x (Buffer 0x%08x, 0x%x)",
Command, _BufferOut, _BufferOutSize);
break;
default:
ERROR_LOG(WII_IPC_DVD, "unknown cmd 0x%08x (Buffer 0x%08x, 0x%x)",
ERROR_LOG(WII_IPC_DVD, "Unknown command 0x%08x (Buffer 0x%08x, 0x%x)",
Command, _BufferOut, _BufferOutSize);
PanicAlertT("unknown cmd 0x%08x", Command);
PanicAlertT("Unknown command 0x%08x", Command);
break;
}
@ -497,7 +497,7 @@ int CWII_IPC_HLE_Device_di::GetCmdDelay(u32 _CommandAddress)
// case DVDLowReset:
// case DVDLowClosePartition:
default:
// ranom numbers here!
// random numbers here!
// More than ~1/2000th of a second hangs DKCR with DSP HLE, maybe.
return SystemTimers::GetTicksPerSecond() / 15000;
break;

View file

@ -186,7 +186,7 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
{
if (m_Mode == ISFS_OPEN_WRITE)
{
WARN_LOG(WII_IPC_FILEIO, "FileIO: Attempted to read 0x%x bytes to 0x%08x on write-only file %s", Size, Address, m_Name.c_str());
WARN_LOG(WII_IPC_FILEIO, "FileIO: Attempted to read 0x%x bytes to 0x%08x on a write-only file %s", Size, Address, m_Name.c_str());
}
else
{
@ -225,7 +225,7 @@ bool CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
{
if (m_Mode == ISFS_OPEN_READ)
{
WARN_LOG(WII_IPC_FILEIO, "FileIO: Attempted to write 0x%x bytes from 0x%08x to read-only file %s", Size, Address, m_Name.c_str());
WARN_LOG(WII_IPC_FILEIO, "FileIO: Attempted to write 0x%x bytes from 0x%08x to a read-only file %s", Size, Address, m_Name.c_str());
}
else
{

View file

@ -112,7 +112,7 @@ bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode)
Memory::Write_U32(GetDeviceID(), _CommandAddress+4);
if (m_Active)
INFO_LOG(WII_IPC_ES, "Device was ReOpened");
INFO_LOG(WII_IPC_ES, "Device was re-opened.");
m_Active = true;
return true;
}
@ -314,7 +314,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
}
}
INFO_LOG(WII_IPC_ES, "IOCTL_ES_READCONTENT: CFD %x, Addr 0x%x, Size %i -> stream pos %i (Index %i)", CFD, Addr, Size, rContent.m_Position, rContent.m_pContent->m_Index);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_READCONTENT: CFD %x, Address 0x%x, Size %i -> stream pos %i (Index %i)", CFD, Addr, Size, rContent.m_Position, rContent.m_pContent->m_Index);
Memory::Write_U32(Size, _CommandAddress + 0x4);
return true;
@ -365,7 +365,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
break;
}
INFO_LOG(WII_IPC_ES, "IOCTL_ES_SEEKCONTENT: CFD %x, Addr 0x%x, Mode %i -> Pos %i", CFD, Addr, Mode, rContent.m_Position);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_SEEKCONTENT: CFD %x, Address 0x%x, Mode %i -> Pos %i", CFD, Addr, Mode, rContent.m_Position);
Memory::Write_U32(rContent.m_Position, _CommandAddress + 0x4);
return true;
@ -575,7 +575,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
const DiscIO::INANDContentLoader& Loader = AccessContentDevice(TitleID);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x buffersize: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTMDVIEWCNT: title: %08x/%08x buffer size: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
if (Loader.IsValid())
{
@ -682,7 +682,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
const DiscIO::INANDContentLoader& Loader = AccessContentDevice(TitleID);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x buffersize: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETSTOREDTMD: title: %08x/%08x buffer size: %i", (u32)(TitleID >> 32), (u32)TitleID, MaxCount);
if (Loader.IsValid() && Buffer.NumberPayloadBuffer)
{
@ -777,14 +777,14 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
{
//TODO: fixme
// The following is obviously a hack
// Lie to mem about loading a different ios
// Lie to mem about loading a different IOS
// someone with an affected game should test
IOSv = TitleID & 0xffff;
}
if (!bSuccess && IOSv >= 30 && IOSv != 0xffff)
{
PanicAlertT("IOCTL_ES_LAUNCH: Game tried to reload ios or a title that is not available in your nand dump\n"
"TitleID %016llx.\n Dolphin will likely hang now", TitleID);
PanicAlertT("IOCTL_ES_LAUNCH: Game tried to reload an IOS or a title that is not available in your NAND dump\n"
"TitleID %016llx.\n Dolphin will likely hang now.", TitleID);
}
else
{
@ -835,8 +835,8 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
case IOCTL_ES_CHECKKOREAREGION: //note by DacoTaco : name is unknown, i just tried to name it SOMETHING
//IOS70 has this to let system menu 4.2 check if the console is region changed. it returns -1017
//if the IOS didn't find the korean keys and 0 if it does. 0 leads to a error 003
WARN_LOG(WII_IPC_ES,"IOCTL_ES_CHECKKOREAREGION: Title Checked for korean Keys");
//if the IOS didn't find the Korean keys and 0 if it does. 0 leads to a error 003
WARN_LOG(WII_IPC_ES,"IOCTL_ES_CHECKKOREAREGION: Title checked for Korean keys.");
Memory::Write_U32(ES_PARAMTER_SIZE_OR_ALIGNMENT , _CommandAddress + 0x4);
return true;
@ -952,7 +952,7 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(u8* _pTMD, u32 _sz)
{
File::IOFile _pTMDFile(tmdPath, "wb");
if (!_pTMDFile.WriteBytes(_pTMD, _sz))
ERROR_LOG(WII_IPC_ES, "DIVerify failed to write disc tmd to nand");
ERROR_LOG(WII_IPC_ES, "DIVerify failed to write disc TMD to NAND.");
}
DiscIO::cUIDsys::AccessInstance().AddTitle(tmdTitleID);
return 0;

View file

@ -136,7 +136,7 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
if ((CommandBuffer.InBuffer.size() == 1) && (CommandBuffer.PayloadBuffer.size() == 1))
{
size_t numFile = FileSearch.GetFileNames().size();
INFO_LOG(WII_IPC_FILEIO, "\t%lu Files found", (unsigned long)numFile);
INFO_LOG(WII_IPC_FILEIO, "\t%lu files found", (unsigned long)numFile);
Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[0].m_Address);
}
@ -227,7 +227,7 @@ bool CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
fsBlocks = 0;
iNodes = 0;
ReturnValue = FS_RESULT_OK;
WARN_LOG(WII_IPC_FILEIO, "FS: fsBlock failed, cannot find directoy: %s", path.c_str());
WARN_LOG(WII_IPC_FILEIO, "FS: fsBlock failed, cannot find directory: %s", path.c_str());
}
Memory::Write_U32(fsBlocks, CommandBuffer.PayloadBuffer[0].m_Address);

View file

@ -158,7 +158,7 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
break;
case IOCTL_SENDCMD:
INFO_LOG(WII_IPC_SD, "IOCTL_SENDCMD %x ipc:%08x",
INFO_LOG(WII_IPC_SD, "IOCTL_SENDCMD %x IPC:%08x",
Memory::Read_U32(BufferIn), _CommandAddress);
ReturnValue = ExecuteCommand(BufferIn, BufferInSize, 0, 0, BufferOut, BufferOutSize);
break;
@ -242,7 +242,7 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(u32 _CommandAddress)
break;
default:
ERROR_LOG(WII_IPC_SD, "unknown SD IOCtlV command 0x%08x", CommandBuffer.Parameter);
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtlV command 0x%08x", CommandBuffer.Parameter);
break;
}
@ -376,7 +376,7 @@ u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInS
{
Memory::Write_U8((u8)buffer[i], req.addr++);
}
DEBUG_LOG(WII_IPC_SD, "outbuffer size %i got %i", _rwBufferSize, i);
DEBUG_LOG(WII_IPC_SD, "Outbuffer size %i got %i", _rwBufferSize, i);
}
else
{

View file

@ -178,7 +178,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::Close(u32 _CommandAddress, bool _bForc
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtl(u32 _CommandAddress)
{
//ERROR_LOG(WII_IPC_WIIMOTE, "passing ioctl to ioctlv");
//ERROR_LOG(WII_IPC_WIIMOTE, "Passing ioctl to ioctlv");
return IOCtlV(_CommandAddress); //hack
}
@ -422,7 +422,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
else
{
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI endpoint not currently valid, "
"queueing(%lu)...", (unsigned long)m_EventQueue.size());
"queuing(%lu)...", (unsigned long)m_EventQueue.size());
m_EventQueue.push_back(_event);
}
}
@ -431,7 +431,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
{
bool packet_transferred = false;
// check hci queue
// check HCI queue
if (!m_EventQueue.empty() && m_HCIEndpoint.IsValid())
{
// an endpoint has become available, and we have a stored response.
@ -450,7 +450,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
packet_transferred = true;
}
// check acl queue
// check ACL queue
if (!m_acl_pool.IsEmpty() && m_ACLEndpoint.IsValid() && m_EventQueue.empty())
{
m_acl_pool.WriteToEndpoint(m_ACLEndpoint);
@ -517,7 +517,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::Store(const u8* data, const u
}
_dbg_assert_msg_(WII_IPC_WIIMOTE,
size < m_acl_pkt_size, "acl packet too large for pool");
size < m_acl_pkt_size, "ACL packet too large for pool");
m_queue.push_back(Packet());
auto& packet = m_queue.back();
@ -602,7 +602,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventInquiryResponse()
pResponse->page_scan_mode = 0;
pResponse->clock_offset = 0x3818;
INFO_LOG(WII_IPC_WIIMOTE, "Event: Send Fake Inquriy of one controller");
INFO_LOG(WII_IPC_WIIMOTE, "Event: Send Fake Inquiry of one controller");
INFO_LOG(WII_IPC_WIIMOTE, " bd: %02x:%02x:%02x:%02x:%02x:%02x",
pResponse->bdaddr.b[0], pResponse->bdaddr.b[1], pResponse->bdaddr.b[2],
pResponse->bdaddr.b[3], pResponse->bdaddr.b[4], pResponse->bdaddr.b[5]);
@ -1778,7 +1778,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadBufferSize(u8* _Input)
hci_read_buffer_size_rp Reply;
Reply.status = 0x00;
Reply.max_acl_size = m_acl_pkt_size;
// Due to how the widcomm stack which nintendo uses is coded, we must never
// Due to how the widcomm stack which Nintendo uses is coded, we must never
// let the stack think the controller is buffering more than 10 data packets
// - it will cause a u8 underflow and royally screw things up.
Reply.num_acl_pkts = m_acl_pkts_num;
@ -1823,7 +1823,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandVendorSpecific_FC4F(u8* _Input,
Reply.status = 0x00;
INFO_LOG(WII_IPC_WIIMOTE, "Command: CommandVendorSpecific_FC4F: (callstack WUDiRemovePatch)");
INFO_LOG(WII_IPC_WIIMOTE, "input (size 0x%x):", _Size);
INFO_LOG(WII_IPC_WIIMOTE, "Input (size 0x%x):", _Size);
Dolphin_Debugger::PrintDataBuffer(LogTypes::WII_IPC_WIIMOTE, _Input, _Size, "Data: ");
@ -1836,7 +1836,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandVendorSpecific_FC4C(u8* _Input,
Reply.status = 0x00;
INFO_LOG(WII_IPC_WIIMOTE, "Command: CommandVendorSpecific_FC4C:");
INFO_LOG(WII_IPC_WIIMOTE, "input (size 0x%x):", _Size);
INFO_LOG(WII_IPC_WIIMOTE, "Input (size 0x%x):", _Size);
Dolphin_Debugger::PrintDataBuffer(LogTypes::WII_IPC_WIIMOTE, _Input, _Size, "Data: ");
SendEventCommandComplete(0xFC4C, &Reply, sizeof(hci_status_rp));
@ -1862,9 +1862,9 @@ CWII_IPC_HLE_WiiMote* CWII_IPC_HLE_Device_usb_oh1_57e_305::AccessWiiMote(const b
return &m_WiiMotes[i];
}
ERROR_LOG(WII_IPC_WIIMOTE,"Cant find WiiMote by bd: %02x:%02x:%02x:%02x:%02x:%02x",
ERROR_LOG(WII_IPC_WIIMOTE,"Can't find WiiMote by bd: %02x:%02x:%02x:%02x:%02x:%02x",
_rAddr.b[0], _rAddr.b[1], _rAddr.b[2], _rAddr.b[3], _rAddr.b[4], _rAddr.b[5]);
PanicAlertT("Cant find WiiMote by bd: %02x:%02x:%02x:%02x:%02x:%02x",
PanicAlertT("Can't find WiiMote by bd: %02x:%02x:%02x:%02x:%02x:%02x",
_rAddr.b[0], _rAddr.b[1], _rAddr.b[2], _rAddr.b[3], _rAddr.b[4], _rAddr.b[5]);
return NULL;
}
@ -1877,8 +1877,8 @@ CWII_IPC_HLE_WiiMote* CWII_IPC_HLE_Device_usb_oh1_57e_305::AccessWiiMote(u16 _Co
return &m_WiiMotes[i];
}
ERROR_LOG(WII_IPC_WIIMOTE, "Cant find WiiMote by connection handle %02x", _ConnectionHandle);
PanicAlertT("Cant find WiiMote by connection handle %02x", _ConnectionHandle);
ERROR_LOG(WII_IPC_WIIMOTE, "Can't find WiiMote by connection handle %02x", _ConnectionHandle);
PanicAlertT("Can't find WiiMote by connection handle %02x", _ConnectionHandle);
return NULL;
}

View file

@ -227,7 +227,7 @@ u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
0x55, // Multiply
0x57, // Add
0x00, // Separator
0x56, // Substract
0x56, // Subtract
0x63, // Decimal
0x54, // Divide
// F1 -> F12

View file

@ -309,7 +309,7 @@ void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size)
break;
default:
ERROR_LOG(WII_IPC_WIIMOTE, "channel 0x04%x has unknown PSM %x", pHeader->dcid, rChannel.PSM);
ERROR_LOG(WII_IPC_WIIMOTE, "Channel 0x04%x has unknown PSM %x", pHeader->dcid, rChannel.PSM);
break;
}
}
@ -751,8 +751,8 @@ void CWII_IPC_HLE_WiiMote::SDPSendServiceAttributeResponse(u16 cid, u16 Transact
{
if (ServiceHandle != 0x10000)
{
ERROR_LOG(WII_IPC_WIIMOTE, "unknown service handle %x" , ServiceHandle);
PanicAlert("unknown service handle %x" , ServiceHandle);
ERROR_LOG(WII_IPC_WIIMOTE, "Unknown service handle %x" , ServiceHandle);
PanicAlert("Unknown service handle %x" , ServiceHandle);
}

View file

@ -271,6 +271,16 @@ bool NetPlay::StopGame()
return true;
}
void NetPlay::SetMemcardWriteEnabled(bool enabled)
{
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (m_is_running)
{
Core::g_CoreStartupParameter.bEnableMemcardSaving = enabled;
}
}
// called from ---CPU--- thread
u8 NetPlay::GetPadNum(u8 numPAD)
{

View file

@ -111,6 +111,7 @@ public:
virtual bool StartGame(const std::string &path);
virtual bool StopGame();
virtual void SetMemcardWriteEnabled(bool enabled);
//void PushPadStates(unsigned int count);
u8 GetPadNum(u8 numPAD);

View file

@ -52,7 +52,7 @@ void NetPlayServer::ThreadFunc()
// update pings every so many seconds
if ((m_ping_timer.GetTimeElapsed() > (10 * 1000)) || m_update_pings)
{
//PanicAlertT("sending pings");
//PanicAlertT("Sending pings");
m_ping_key = Common::Timer::GetTimeMs();
@ -487,7 +487,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
if (m_ping_key == ping_key)
{
//PanicAlertT("good pong");
//PanicAlertT("Good pong");
player.ping = ping;
}
m_dialog->Update();

View file

@ -306,7 +306,7 @@ void Interpreter::unknown_instruction(UGeckoInstruction _inst)
DisassembleGekko(Memory::ReadUnchecked_U32(last_pc), last_pc, disasm, 256);
NOTICE_LOG(POWERPC, "Last PC = %08x : %s", last_pc, disasm);
Dolphin_Debugger::PrintCallstack();
_dbg_assert_msg_(POWERPC, 0, "\nIntCPU: Unknown instr %08x at PC = %08x last_PC = %08x LR = %08x\n", _inst.hex, PC, last_pc, LR);
_dbg_assert_msg_(POWERPC, 0, "\nIntCPU: Unknown instruction %08x at PC = %08x last_PC = %08x LR = %08x\n", _inst.hex, PC, last_pc, LR);
}
}

View file

@ -679,7 +679,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
{
char ppcInst[256];
DisassembleGekko(ops[i].inst.hex, em_address, ppcInst, 256);
NOTICE_LOG(DYNA_REC, "Unflushed reg: %s", ppcInst);
NOTICE_LOG(DYNA_REC, "Unflushed register: %s", ppcInst);
}
#endif
if (js.skipnext) {

View file

@ -388,7 +388,7 @@ void RegCache::Flush(FlushMode mode)
{
if (locks[i])
{
PanicAlert("Somebody forgot to unlock PPC reg %i.", i);
PanicAlert("Someone forgot to unlock PPC reg %i.", i);
}
if (regs[i].away)
{

View file

@ -125,7 +125,7 @@ const u8 *TrampolineCache::GetWriteTrampoline(const InstructionInfo &info)
// It's a write. Yay. Remember that we don't have to be super efficient since it's "just" a
// hardware access - we can take shortcuts.
//if (emAddress == 0xCC008000)
// PanicAlert("caught a fifo write");
// PanicAlert("Caught a FIFO write");
CMP(32, R(addrReg), Imm32(0xCC008000));
FixupBranch skip_fast = J_CC(CC_NE, false);
MOV(32, R(ABI_PARAM1), R((X64Reg)dataReg));
@ -215,7 +215,7 @@ const u8 *Jitx86Base::BackPatch(u8 *codePtr, int accessType, u32 emAddress, void
emitter.CALL((void *)trampoline);
emitter.NOP((int)info.instructionSize - 3);
if (info.instructionSize < 3)
PanicAlert("instruction too small");
PanicAlert("Instruction too small");
// We entered here with a BSWAP-ed EAX. We'll have to swap it back.
ctx->Rax = Common::swap32((u32)ctx->Rax);
return codePtr - 2;

View file

@ -159,7 +159,7 @@ namespace JitInterface
File::IOFile f(filename, "w");
if (!f)
{
PanicAlert("failed to open %s", filename);
PanicAlert("Failed to open %s", filename);
return;
}
fprintf(f.GetHandle(), "origAddr\tblkName\tcost\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n");

View file

@ -290,7 +290,7 @@ u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa,
int capacity_of_merged_addresses, int& size_of_merged_addresses)
{
if (capacity_of_merged_addresses < FUNCTION_FOLLOWING_THRESHOLD) {
PanicAlert("capacity of merged_addresses is too small!");
PanicAlert("Capacity of merged_addresses is too small!");
}
std::fill_n(merged_addresses, capacity_of_merged_addresses, 0);
merged_addresses[0] = address;
@ -697,7 +697,7 @@ void FindFunctions(u32 startAddr, u32 endAddr, PPCSymbolDB *func_db)
{
if (iter->second.address == 4)
{
WARN_LOG(OSHLE, "weird function");
WARN_LOG(OSHLE, "Weird function");
continue;
}
AnalyzeFunction2(&(iter->second));

View file

@ -93,7 +93,7 @@ bool SetupScrub(const char* filename, int block_size)
if (CLUSTER_SIZE % m_BlockSize != 0)
{
ERROR_LOG(DISCIO, "block size %i is not a factor of 0x8000, scrubbing not possible", m_BlockSize);
ERROR_LOG(DISCIO, "Block size %i is not a factor of 0x8000, scrubbing not possible", m_BlockSize);
return false;
}
@ -106,7 +106,7 @@ bool SetupScrub(const char* filename, int block_size)
// Warn if not DVD5 or DVD9 size
if (numClusters != 0x23048 && numClusters != 0x46090)
WARN_LOG(DISCIO, "%s is not a standard sized wii disc! (%x blocks)", filename, numClusters);
WARN_LOG(DISCIO, "%s is not a standard sized Wii disc! (%x blocks)", filename, numClusters);
// Table of free blocks
m_FreeTable = new u8[numClusters];

View file

@ -57,6 +57,8 @@
<string>${OSX_MIN_VERSION}</string>
<key>LSRequiresCarbon</key>
<true/>
<key>NSHighResolutionCapable</key>
<true/>
<key>CSResourcesFileMapped</key>
<true/>
</dict>

View file

@ -170,8 +170,12 @@ void CARCodeAddEdit::UpdateTextCtrl(ActionReplay::ARCode arCode)
EditCheatCode->Clear();
if (arCode.name != "")
{
for (u32 i = 0; i < arCode.ops.size(); i++)
EditCheatCode->AppendText(wxString::Format(wxT("%08X %08X\n"), arCode.ops.at(i).cmd_addr, arCode.ops.at(i).value));
}
else
{
EditCheatCode->SetValue(_("Insert Encrypted or Decrypted code here..."));
}
}

View file

@ -298,10 +298,11 @@ void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& WXUNUSED (e
sprintf(numcodes, "Number of Codes: %lu", (unsigned long)code.ops.size());
m_Label_NumCodes->SetLabel(StrToWxStr(numcodes));
m_ListBox_CodesList->Clear();
for (size_t j = 0; j < code.ops.size(); j++)
{
char text2[CHAR_MAX];
char* ops = text2;
char* ops = text2;
sprintf(ops, "%08x %08x", code.ops[j].cmd_addr, code.ops[j].value);
m_ListBox_CodesList->Append(StrToWxStr(ops));
}
@ -332,7 +333,7 @@ void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev)
// Apply Gecko Code changes
Gecko::SetActiveCodes(m_geckocode_panel->GetCodes());
// save gameini, with changed gecko codes
// Save gameini, with changed gecko codes
if (m_gameini_path.size())
{
Gecko::SaveCodes(m_gameini, m_geckocode_panel->GetCodes());
@ -409,7 +410,7 @@ void CheatSearchTab::FilterCheatSearchResults(wxCommandEvent&)
filtered_results.reserve(search_results.size());
// determine the selected filter
// Determine the selected filter
// 1 : equal
// 2 : greater-than
// 4 : less-than

View file

@ -18,6 +18,7 @@
#include <string> // System
#include <vector>
#include <algorithm>
#include <functional>
#include <wx/spinbutt.h>
#include "Common.h"
@ -43,14 +44,6 @@
#include "Main.h"
#include "VideoBackendBase.h"
#if defined(__APPLE__)
#include <tr1/functional>
using std::tr1::function;
#else
#include <functional>
using std::function;
#endif
#define TEXT_BOX(page, text) new wxStaticText(page, wxID_ANY, text, wxDefaultPosition, wxDefaultSize)
struct CPUCore
@ -59,12 +52,12 @@ struct CPUCore
const char *name;
};
const CPUCore CPUCores[] = {
{0, "Interpreter (VERY slow)"},
{0, wxTRANSLATE("Interpreter (VERY slow)")},
#ifdef _M_ARM
{3, "Arm JIT (experimental)"},
{3, wxTRANSLATE("Arm JIT (experimental)")},
#else
{1, "JIT Recompiler (recommended)"},
{2, "JITIL experimental recompiler"},
{1, wxTRANSLATE("JIT Recompiler (recommended)")},
{2, wxTRANSLATE("JITIL experimental recompiler")},
#endif
};
@ -268,7 +261,7 @@ void CConfigMain::InitializeGUILists()
// Emulator Engine
for (unsigned int a = 0; a < (sizeof(CPUCores) / sizeof(CPUCore)); ++a)
arrayStringFor_CPUEngine.Add(_(CPUCores[a].name));
arrayStringFor_CPUEngine.Add(wxGetTranslation(CPUCores[a].name));
// DSP Engine
arrayStringFor_DSPEngine.Add(_("DSP HLE emulation (fast)"));
@ -515,7 +508,7 @@ void CConfigMain::InitializeGUITooltips()
InterfaceLang->SetToolTip(_("Change the language of the user interface.\nRequires restart."));
// Audio tooltips
DSPThread->SetToolTip(_("Run DSP LLE on a dedicated thread (not recommended)."));
DSPThread->SetToolTip(_("Run DSP HLE and LLE on a dedicated thread (not recommended: might cause audio glitches with HLE and freezes with LLE)."));
BackendSelection->SetToolTip(_("Changing this will have no effect while the emulator is running!"));
// Gamecube - Devices
@ -624,16 +617,17 @@ void CConfigMain::CreateGUIControls()
SplitPath(filename, NULL, &name, &ext);
name += ext;
if (-1 == theme_selection->FindString(name))
theme_selection->Append(name);
auto const wxname = StrToWxStr(name);
if (-1 == theme_selection->FindString(wxname))
theme_selection->Append(wxname);
});
theme_selection->SetStringSelection(SConfig::GetInstance().m_LocalCoreStartupParameter.theme_name);
theme_selection->SetStringSelection(StrToWxStr(SConfig::GetInstance().m_LocalCoreStartupParameter.theme_name));
// std::function = avoid error on msvc
theme_selection->Bind(wxEVT_COMMAND_CHOICE_SELECTED, function<void(wxEvent&)>([theme_selection](wxEvent&)
theme_selection->Bind(wxEVT_COMMAND_CHOICE_SELECTED, std::function<void(wxEvent&)>([theme_selection](wxEvent&)
{
SConfig::GetInstance().m_LocalCoreStartupParameter.theme_name = theme_selection->GetStringSelection();
SConfig::GetInstance().m_LocalCoreStartupParameter.theme_name = WxStrToStr(theme_selection->GetStringSelection());
main_frame->InitBitmaps();
main_frame->UpdateGameList();
}));
@ -657,7 +651,7 @@ void CConfigMain::CreateGUIControls()
// Audio page
DSPEngine = new wxRadioBox(AudioPage, ID_DSPENGINE, _("DSP Emulator Engine"),
wxDefaultPosition, wxDefaultSize, arrayStringFor_DSPEngine, 0, wxRA_SPECIFY_ROWS);
DSPThread = new wxCheckBox(AudioPage, ID_DSPTHREAD, _("DSP LLE on Thread"));
DSPThread = new wxCheckBox(AudioPage, ID_DSPTHREAD, _("DSP on Dedicated Thread"));
DumpAudio = new wxCheckBox(AudioPage, ID_DUMP_AUDIO, _("Dump Audio"),
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
DPL2Decoder = new wxCheckBox(AudioPage, ID_DPL2DECODER, _("Dolby Pro Logic II decoder"));
@ -976,7 +970,9 @@ void CConfigMain::AudioSettingsChanged(wxCommandEvent& event)
VolumeSlider->Enable(SupportsVolumeChanges(WxStrToStr(BackendSelection->GetStringSelection())));
Latency->Enable(WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_OPENAL);
DPL2Decoder->Enable(WxStrToStr(BackendSelection->GetStringSelection()) == BACKEND_OPENAL);
SConfig::GetInstance().sBackend = WxStrToStr(BackendSelection->GetStringSelection());
// Don't save the translated BACKEND_NULLSOUND string
SConfig::GetInstance().sBackend = BackendSelection->GetSelection() ?
WxStrToStr(BackendSelection->GetStringSelection()) : BACKEND_NULLSOUND;
AudioCommon::UpdateSoundStream();
break;
@ -997,8 +993,8 @@ void CConfigMain::AddAudioBackends()
for (std::vector<std::string>::const_iterator iter = backends.begin();
iter != backends.end(); ++iter)
{
BackendSelection->Append(StrToWxStr(*iter));
int num = BackendSelection->\
BackendSelection->Append(wxGetTranslation(StrToWxStr(*iter)));
int num = BackendSelection->
FindString(StrToWxStr(SConfig::GetInstance().sBackend));
BackendSelection->SetSelection(num);
}
@ -1239,7 +1235,9 @@ void CConfigMain::AddRemoveISOPaths(wxCommandEvent& event)
if (dialog.ShowModal() == wxID_OK)
{
if (ISOPaths->FindString(dialog.GetPath()) != -1)
{
wxMessageBox(_("The chosen directory is already in the list"), _("Error"), wxOK);
}
else
{
bRefreshList = true;

View file

@ -47,10 +47,12 @@ void BreakPointDlg::OnOK(wxCommandEvent& event)
{
PowerPC::breakpoints.Add(Address);
Parent->NotifyUpdate();
Close();
Close();
}
else
{
PanicAlert("The address %s is invalid.", WxStrToStr(AddressString).c_str());
}
event.Skip();
}

View file

@ -40,10 +40,10 @@ void CBreakPointView::Update()
InsertColumn(0, wxT("Active"));
InsertColumn(1, wxT("Type"));
InsertColumn(2, wxT("Function"));
InsertColumn(3, wxT("Address"));
InsertColumn(4, wxT("Flags"));
InsertColumn(3, wxT("Address"));
InsertColumn(4, wxT("Flags"));
char szBuffer[64];
char szBuffer[64];
const BreakPoints::TBreakPoints& rBreakPoints = PowerPC::breakpoints.GetBreakPoints();
for (size_t i = 0; i < rBreakPoints.size(); i++)
{
@ -63,11 +63,11 @@ void CBreakPointView::Update()
SetItem(Item, 2, temp);
}
sprintf(szBuffer, "%08x", rBP.iAddress);
temp = StrToWxStr(szBuffer);
sprintf(szBuffer, "%08x", rBP.iAddress);
temp = StrToWxStr(szBuffer);
SetItem(Item, 3, temp);
SetItemData(Item, rBP.iAddress);
SetItemData(Item, rBP.iAddress);
}
}
@ -108,12 +108,12 @@ void CBreakPointView::Update()
void CBreakPointView::DeleteCurrentSelection()
{
int Item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (Item >= 0)
{
u32 Address = (u32)GetItemData(Item);
PowerPC::breakpoints.Remove(Address);
PowerPC::memchecks.Remove(Address);
int Item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
if (Item >= 0)
{
u32 Address = (u32)GetItemData(Item);
PowerPC::breakpoints.Remove(Address);
PowerPC::memchecks.Remove(Address);
Update();
}
}
}

View file

@ -62,20 +62,20 @@ END_EVENT_TABLE()
CCodeView::CCodeView(DebugInterface* debuginterface, SymbolDB *symboldb,
wxWindow* parent, wxWindowID Id)
: wxControl(parent, Id),
debugger(debuginterface),
debugger(debuginterface),
symbol_db(symboldb),
plain(false),
curAddress(debuginterface->getPC()),
align(debuginterface->getInstructionSize(0)),
rowHeight(13),
selection(0),
oldSelection(0),
selectionChanged(false),
selecting(false),
hasFocus(false),
showHex(false),
lx(-1),
ly(-1)
rowHeight(13),
selection(0),
oldSelection(0),
selectionChanged(false),
selecting(false),
hasFocus(false),
showHex(false),
lx(-1),
ly(-1)
{
}
@ -104,7 +104,9 @@ void CCodeView::OnMouseDown(wxMouseEvent& event)
Refresh();
}
else
{
ToggleBreakpoint(YToAddress(y));
}
event.Skip(true);
}
@ -133,7 +135,9 @@ void CCodeView::OnMouseMove(wxMouseEvent& event)
Refresh();
}
else
{
OnMouseDown(event);
}
}
event.Skip(true);
@ -176,14 +180,17 @@ u32 CCodeView::AddrToBranch(u32 addr)
void CCodeView::InsertBlrNop(int Blr)
{
// Check if this address has been modified
int find = -1;
int find = -1;
for(u32 i = 0; i < BlrList.size(); i++)
{
if(BlrList.at(i).Address == selection)
{ find = i; break; }
{
find = i;
break;
}
}
// Save the old value
// Save the old value
if (find >= 0)
{
debugger->writeExtraMemory(0, BlrList.at(find).OldValue, selection);
@ -196,11 +203,11 @@ void CCodeView::InsertBlrNop(int Blr)
Temp.OldValue = debugger->readMemory(selection);
BlrList.push_back(Temp);
if (Blr == 0)
debugger->insertBLR(selection, 0x4e800020);
debugger->insertBLR(selection, 0x4e800020);
else
debugger->insertBLR(selection, 0x60000000);
debugger->insertBLR(selection, 0x60000000);
}
Refresh();
Refresh();
}
void CCodeView::OnPopupMenu(wxCommandEvent& event)
@ -211,14 +218,14 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
switch (event.GetId())
{
case IDM_GOTOINMEMVIEW:
// CMemoryDlg::Goto(selection);
break;
case IDM_GOTOINMEMVIEW:
// CMemoryDlg::Goto(selection);
break;
#if wxUSE_CLIPBOARD
case IDM_COPYADDRESS:
wxTheClipboard->SetData(new wxTextDataObject(wxString::Format(_T("%08x"), selection)));
break;
case IDM_COPYADDRESS:
wxTheClipboard->SetData(new wxTextDataObject(wxString::Format(_T("%08x"), selection)));
break;
case IDM_COPYCODE:
{
@ -228,13 +235,13 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
}
break;
case IDM_COPYHEX:
{
char temp[24];
sprintf(temp, "%08x", debugger->readInstruction(selection));
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
}
break;
case IDM_COPYHEX:
{
char temp[24];
sprintf(temp, "%08x", debugger->readInstruction(selection));
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
}
break;
case IDM_COPYFUNCTION:
@ -259,11 +266,11 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
break;
#endif
case IDM_RUNTOHERE:
debugger->setBreakpoint(selection);
debugger->runToBreakpoint();
Refresh();
break;
case IDM_RUNTOHERE:
debugger->setBreakpoint(selection);
debugger->runToBreakpoint();
Refresh();
break;
// Insert blr or restore old value
case IDM_INSERTBLR:
@ -275,9 +282,9 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
Refresh();
break;
case IDM_JITRESULTS:
case IDM_JITRESULTS:
debugger->showJitResults(selection);
break;
break;
case IDM_FOLLOWBRANCH:
{
@ -366,7 +373,7 @@ void CCodeView::OnPaint(wxPaintEvent& event)
dc.GetTextExtent(_T("0WJyq"),&w,&h);
if (h > rowHeight)
rowHeight = h;
rowHeight = h;
dc.GetTextExtent(_T("W"),&w,&h);
int charWidth = w;
@ -507,7 +514,8 @@ void CCodeView::OnPaint(wxPaintEvent& event)
strcpy(desc, debugger->getDescription(address).c_str());
}
if (!plain) {
if (!plain)
{
dc.SetTextForeground(_T("#0000FF")); // blue
//char temp[256];
@ -535,11 +543,11 @@ void CCodeView::OnPaint(wxPaintEvent& event)
for (int i = 0; i < numBranches; i++)
{
int x = 17 + 49 * charWidth + (branches[i].srcAddr % 9) * 8;
_MoveTo(x-2, branches[i].src);
int x = 17 + 49 * charWidth + (branches[i].srcAddr % 9) * 8;
_MoveTo(x-2, branches[i].src);
if (branches[i].dst < rc.height + 400 && branches[i].dst > -400)
{
{
_LineTo(dc, x+2, branches[i].src);
_LineTo(dc, x+2, branches[i].dst);
_LineTo(dc, x-4, branches[i].dst);
@ -547,7 +555,7 @@ void CCodeView::OnPaint(wxPaintEvent& event)
_MoveTo(x, branches[i].dst - 4);
_LineTo(dc, x-4, branches[i].dst);
_LineTo(dc, x+1, branches[i].dst+5);
}
}
//else
//{
// This can be re-enabled when there is a scrollbar or

View file

@ -138,16 +138,16 @@ void CCodeWindow::OnHostMessage(wxCommandEvent& event)
{
switch (event.GetId())
{
case IDM_NOTIFYMAPLOADED:
NotifyMapLoaded();
case IDM_NOTIFYMAPLOADED:
NotifyMapLoaded();
if (m_BreakpointWindow) m_BreakpointWindow->NotifyUpdate();
break;
break;
case IDM_UPDATEDISASMDIALOG:
Update();
case IDM_UPDATEDISASMDIALOG:
Update();
if (codeview) codeview->Center(PC);
if (m_RegisterWindow) m_RegisterWindow->NotifyUpdate();
break;
if (m_RegisterWindow) m_RegisterWindow->NotifyUpdate();
break;
case IDM_UPDATEBREAKPOINTS:
Update();
@ -161,31 +161,31 @@ void CCodeWindow::OnCodeStep(wxCommandEvent& event)
{
switch (event.GetId())
{
case IDM_STEP:
case IDM_STEP:
SingleStep();
break;
break;
case IDM_STEPOVER:
case IDM_STEPOVER:
StepOver();
break;
break;
case IDM_TOGGLE_BREAKPOINT:
ToggleBreakpoint();
break;
case IDM_SKIP:
PC += 4;
Update();
break;
case IDM_SKIP:
PC += 4;
Update();
break;
case IDM_SETPC:
PC = codeview->GetSelection();
Update();
break;
case IDM_SETPC:
PC = codeview->GetSelection();
Update();
break;
case IDM_GOTOPC:
JumpToAddress(PC);
break;
case IDM_GOTOPC:
JumpToAddress(PC);
break;
}
UpdateButtonStates();
@ -227,7 +227,7 @@ void CCodeWindow::OnCallstackListChange(wxCommandEvent& event)
{
int index = callstack->GetSelection();
if (index >= 0)
{
{
u32 address = (u32)(u64)(callstack->GetClientData(index));
if (address)
JumpToAddress(address);
@ -238,7 +238,7 @@ void CCodeWindow::OnCallersListChange(wxCommandEvent& event)
{
int index = callers->GetSelection();
if (index >= 0)
{
{
u32 address = (u32)(u64)(callers->GetClientData(index));
if (address)
JumpToAddress(address);
@ -249,7 +249,7 @@ void CCodeWindow::OnCallsListChange(wxCommandEvent& event)
{
int index = calls->GetSelection();
if (index >= 0)
{
{
u32 address = (u32)(u64)(calls->GetClientData(index));
if (address)
JumpToAddress(address);
@ -283,7 +283,9 @@ void CCodeWindow::StepOver()
Update();
}
else
{
SingleStep();
}
UpdateButtonStates();
// Update all toolbars in the aui manager
@ -307,12 +309,13 @@ void CCodeWindow::UpdateLists()
Symbol *symbol = g_symbolDB.GetSymbolFromAddr(addr);
if (!symbol)
return;
for (int i = 0; i < (int)symbol->callers.size(); i++)
{
u32 caller_addr = symbol->callers[i].callAddress;
Symbol *caller_symbol = g_symbolDB.GetSymbolFromAddr(caller_addr);
if (caller_symbol)
{
{
int idx = callers->Append(StrToWxStr(StringFromFormat
("< %s (%08x)", caller_symbol->name.c_str(), caller_addr).c_str()));
callers->SetClientData(idx, (void*)(u64)caller_addr);
@ -325,7 +328,7 @@ void CCodeWindow::UpdateLists()
u32 call_addr = symbol->calls[i].function;
Symbol *call_symbol = g_symbolDB.GetSymbolFromAddr(call_addr);
if (call_symbol)
{
{
int idx = calls->Append(StrToWxStr(StringFromFormat
("> %s (%08x)", call_symbol->name.c_str(), call_addr).c_str()));
calls->SetClientData(idx, (void*)(u64)call_addr);
@ -354,8 +357,7 @@ void CCodeWindow::UpdateCallstack()
}
// Create CPU Mode menus
void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParameter,
wxMenuBar *pMenuBar)
void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParameter, wxMenuBar *pMenuBar)
{
// CPU Mode
wxMenu* pCoreMenu = new wxMenu;
@ -386,7 +388,7 @@ void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParam
_("Turn off all JIT functions, but still use the JIT core from Jit.cpp"),
wxITEM_CHECK);
pCoreMenu->Append(IDM_JITLSOFF, _("&JIT LoadStore off"),
wxEmptyString, wxITEM_CHECK);
wxEmptyString, wxITEM_CHECK);
pCoreMenu->Append(IDM_JITLSLBZXOFF, _(" &JIT LoadStore lbzx off"),
wxEmptyString, wxITEM_CHECK);
pCoreMenu->Append(IDM_JITLSLXZOFF, _(" &JIT LoadStore lXz off"),
@ -394,17 +396,17 @@ void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParam
pCoreMenu->Append(IDM_JITLSLWZOFF, _("&JIT LoadStore lwz off"),
wxEmptyString, wxITEM_CHECK);
pCoreMenu->Append(IDM_JITLSFOFF, _("&JIT LoadStore Floating off"),
wxEmptyString, wxITEM_CHECK);
wxEmptyString, wxITEM_CHECK);
pCoreMenu->Append(IDM_JITLSPOFF, _("&JIT LoadStore Paired off"),
wxEmptyString, wxITEM_CHECK);
wxEmptyString, wxITEM_CHECK);
pCoreMenu->Append(IDM_JITFPOFF, _("&JIT FloatingPoint off"),
wxEmptyString, wxITEM_CHECK);
wxEmptyString, wxITEM_CHECK);
pCoreMenu->Append(IDM_JITIOFF, _("&JIT Integer off"),
wxEmptyString, wxITEM_CHECK);
wxEmptyString, wxITEM_CHECK);
pCoreMenu->Append(IDM_JITPOFF, _("&JIT Paired off"),
wxEmptyString, wxITEM_CHECK);
wxEmptyString, wxITEM_CHECK);
pCoreMenu->Append(IDM_JITSROFF, _("&JIT SystemRegisters off"),
wxEmptyString, wxITEM_CHECK);
wxEmptyString, wxITEM_CHECK);
pMenuBar->Append(pCoreMenu, _("&JIT"));
@ -448,46 +450,46 @@ void CCodeWindow::OnCPUMode(wxCommandEvent& event)
{
case IDM_INTERPRETER:
PowerPC::SetMode(UseInterpreter() ? PowerPC::MODE_INTERPRETER : PowerPC::MODE_JIT);
break;
break;
case IDM_BOOTTOPAUSE:
bBootToPause = !bBootToPause;
return;
return;
case IDM_AUTOMATICSTART:
bAutomaticStart = !bAutomaticStart;
return;
return;
case IDM_JITOFF:
Core::g_CoreStartupParameter.bJITOff = event.IsChecked();
break;
break;
case IDM_JITLSOFF:
Core::g_CoreStartupParameter.bJITLoadStoreOff = event.IsChecked();
break;
break;
case IDM_JITLSLXZOFF:
Core::g_CoreStartupParameter.bJITLoadStorelXzOff = event.IsChecked();
break;
break;
case IDM_JITLSLWZOFF:
Core::g_CoreStartupParameter.bJITLoadStorelwzOff = event.IsChecked();
break;
break;
case IDM_JITLSLBZXOFF:
Core::g_CoreStartupParameter.bJITLoadStorelbzxOff = event.IsChecked();
break;
break;
case IDM_JITLSFOFF:
Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff = event.IsChecked();
break;
break;
case IDM_JITLSPOFF:
Core::g_CoreStartupParameter.bJITLoadStorePairedOff = event.IsChecked();
break;
break;
case IDM_JITFPOFF:
Core::g_CoreStartupParameter.bJITFloatingPointOff = event.IsChecked();
break;
break;
case IDM_JITIOFF:
Core::g_CoreStartupParameter.bJITIntegerOff = event.IsChecked();
break;
break;
case IDM_JITPOFF:
Core::g_CoreStartupParameter.bJITPairedOff = event.IsChecked();
break;
break;
case IDM_JITSROFF:
Core::g_CoreStartupParameter.bJITSystemRegistersOff = event.IsChecked();
break;
break;
}
// Clear the JIT cache to enable these changes
@ -503,22 +505,22 @@ void CCodeWindow::OnJitMenu(wxCommandEvent& event)
{
case IDM_LOGINSTRUCTIONS:
PPCTables::LogCompiledInstructions();
break;
break;
case IDM_CLEARCODECACHE:
JitInterface::ClearCache();
break;
break;
case IDM_SEARCHINSTRUCTION:
{
wxString str;
str = wxGetTextFromUser(_T(""), wxT("Op?"), wxEmptyString, this);
for (u32 addr = 0x80000000; addr < 0x80100000; addr += 4)
{
{
const char *name = PPCTables::GetInstructionName(Memory::ReadUnchecked_U32(addr));
auto const wx_name = WxStrToStr(str);
if (name && (wx_name == name))
{
{
NOTICE_LOG(POWERPC, "Found %s at %08x", wx_name.c_str(), addr);
}
}
@ -575,10 +577,10 @@ void CCodeWindow::PopulateToolbar(wxAuiToolBar* toolBar)
toolBar->SetToolBitmapSize(wxSize(w, h));
toolBar->AddTool(IDM_STEP, _("Step"), m_Bitmaps[Toolbar_Step]);
toolBar->AddTool(IDM_STEPOVER, _("Step Over"), m_Bitmaps[Toolbar_StepOver]);
toolBar->AddTool(IDM_STEPOVER, _("Step Over"), m_Bitmaps[Toolbar_StepOver]);
toolBar->AddTool(IDM_SKIP, _("Skip"), m_Bitmaps[Toolbar_Skip]);
toolBar->AddSeparator();
toolBar->AddTool(IDM_GOTOPC, _("Show PC"), m_Bitmaps[Toolbar_GotoPC]);
toolBar->AddTool(IDM_GOTOPC, _("Show PC"), m_Bitmaps[Toolbar_GotoPC]);
toolBar->AddTool(IDM_SETPC, _("Set PC"), m_Bitmaps[Toolbar_SetPC]);
toolBar->AddSeparator();
toolBar->AddControl(new wxTextCtrl(toolBar, IDM_ADDRBOX, _T("")));

View file

@ -36,13 +36,13 @@ BEGIN_EVENT_TABLE(DSPDebuggerLLE, wxPanel)
EVT_CLOSE(DSPDebuggerLLE::OnClose)
EVT_MENU_RANGE(ID_RUNTOOL, ID_SHOWPCTOOL, DSPDebuggerLLE::OnChangeState)
EVT_TEXT_ENTER(ID_ADDRBOX, DSPDebuggerLLE::OnAddrBoxChange)
EVT_LISTBOX(ID_SYMBOLLIST, DSPDebuggerLLE::OnSymbolListChange)
EVT_LISTBOX(ID_SYMBOLLIST, DSPDebuggerLLE::OnSymbolListChange)
END_EVENT_TABLE()
DSPDebuggerLLE::DSPDebuggerLLE(wxWindow* parent, wxWindowID id)
: wxPanel(parent, id, wxDefaultPosition, wxDefaultSize,
wxTAB_TRAVERSAL, _("DSP LLE Debugger"))
wxTAB_TRAVERSAL, _("DSP LLE Debugger"))
, m_CachedStepCounter(-1)
{
m_DebuggerFrame = this;
@ -184,14 +184,14 @@ void DSPDebuggerLLE::FocusOnPC()
void DSPDebuggerLLE::UpdateState()
{
if (DSPCore_GetState() == DSPCORE_RUNNING)
{
{
m_Toolbar->SetToolLabel(ID_RUNTOOL, wxT("Pause"));
m_Toolbar->SetToolBitmap(ID_RUNTOOL,
wxArtProvider::GetBitmap(wxART_TICK_MARK, wxART_OTHER, wxSize(10,10)));
m_Toolbar->EnableTool(ID_STEPTOOL, false);
}
else
{
else
{
m_Toolbar->SetToolLabel(ID_RUNTOOL, wxT("Run"));
m_Toolbar->SetToolBitmap(ID_RUNTOOL,
wxArtProvider::GetBitmap(wxART_GO_FORWARD, wxART_OTHER, wxSize(10,10)));

View file

@ -79,9 +79,10 @@ void GFXDebuggerPanel::SaveSettings() const
// TODO: make this work when we close the entire program too, currently on total close we get
// weird values, perhaps because of some conflict with the rendering window
// TODO: get the screen resolution and make limits from that
if (GetPosition().x < 1000 && GetPosition().y < 1000
&& GetSize().GetWidth() < 1000
&& GetSize().GetWidth() < 1000
&& GetSize().GetHeight() < 1000)
{
file.Set("VideoWindow", "x", GetPosition().x);

View file

@ -59,15 +59,15 @@ BEGIN_EVENT_TABLE(CJitWindow, wxPanel)
END_EVENT_TABLE()
CJitWindow::CJitWindow(wxWindow* parent, wxWindowID id, const wxPoint& pos,
const wxSize& size, long style, const wxString& name)
const wxSize& size, long style, const wxString& name)
: wxPanel(parent, id, pos, size, style, name)
{
wxBoxSizer* sizerBig = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* sizerSplit = new wxBoxSizer(wxHORIZONTAL);
sizerSplit->Add(ppc_box = new wxTextCtrl(this, IDM_PPC_BOX, _T("(ppc)"),
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE), 1, wxEXPAND);
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE), 1, wxEXPAND);
sizerSplit->Add(x86_box = new wxTextCtrl(this, IDM_X86_BOX, _T("(x86)"),
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE), 1, wxEXPAND);
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE), 1, wxEXPAND);
sizerBig->Add(block_list = new JitBlockList(this, IDM_BLOCKLIST,
wxDefaultPosition, wxSize(100, 140),
wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING),
@ -107,21 +107,26 @@ void CJitWindow::Compare(u32 em_address)
int block_num = jit->GetBlockCache()->GetBlockNumberFromStartAddress(em_address);
if (block_num < 0)
{
for (int i = 0; i < 500; i++) {
for (int i = 0; i < 500; i++)
{
block_num = jit->GetBlockCache()->GetBlockNumberFromStartAddress(em_address - 4 * i);
if (block_num >= 0)
break;
}
if (block_num >= 0) {
if (block_num >= 0)
{
JitBlock *block = jit->GetBlockCache()->GetBlock(block_num);
if (!(block->originalAddress <= em_address &&
block->originalSize + block->originalAddress >= em_address))
block->originalSize + block->originalAddress >= em_address))
block_num = -1;
}
// Do not merge this "if" with the above - block_num changes inside it.
if (block_num < 0) {
if (block_num < 0)
{
ppc_box->SetValue(StrToWxStr(StringFromFormat("(non-code address: %08x)",
em_address)));
em_address)));
x86_box->SetValue(StrToWxStr(StringFromFormat("(no translation)")));
delete[] xDis;
return;
@ -186,12 +191,14 @@ void CJitWindow::Compare(u32 em_address)
sptr += sprintf(sptr, "%i estimated cycles\n", st.numCycles);
sptr += sprintf(sptr, "Num instr: PPC: %i x86: %i (blowup: %i%%)\n",
size, num_x86_instructions, 100 * (num_x86_instructions / size - 1));
size, num_x86_instructions, 100 * (num_x86_instructions / size - 1));
sptr += sprintf(sptr, "Num bytes: PPC: %i x86: %i (blowup: %i%%)\n",
size * 4, block->codeSize, 100 * (block->codeSize / (4 * size) - 1));
size * 4, block->codeSize, 100 * (block->codeSize / (4 * size) - 1));
ppc_box->SetValue(StrToWxStr((char*)xDis));
} else {
}
else
{
ppc_box->SetValue(StrToWxStr(StringFromFormat(
"(non-code address: %08x)", em_address)));
x86_box->SetValue("---");
@ -209,9 +216,9 @@ void CJitWindow::OnHostMessage(wxCommandEvent& event)
{
switch (event.GetId())
{
case IDM_NOTIFYMAPLOADED:
//NotifyMapLoaded();
break;
case IDM_NOTIFYMAPLOADED:
//NotifyMapLoaded();
break;
}
}
@ -229,7 +236,7 @@ enum {
};
JitBlockList::JitBlockList(wxWindow* parent, const wxWindowID id,
const wxPoint& pos, const wxSize& size, long style)
const wxPoint& pos, const wxSize& size, long style)
: wxListCtrl(parent, id, pos, size, style) // | wxLC_VIRTUAL)
{
Init();

View file

@ -90,7 +90,7 @@ void CMemoryView::OnMouseDownL(wxMouseEvent& event)
}
else
{
debugger->toggleMemCheck(YToAddress(y));
debugger->toggleMemCheck(YToAddress(y));
Refresh();
Host_UpdateBreakPointView();
@ -143,17 +143,17 @@ void CMemoryView::OnPopupMenu(wxCommandEvent& event)
switch (event.GetId())
{
#if wxUSE_CLIPBOARD
case IDM_COPYADDRESS:
case IDM_COPYADDRESS:
wxTheClipboard->SetData(new wxTextDataObject(wxString::Format(_T("%08x"), selection)));
break;
break;
case IDM_COPYHEX:
{
char temp[24];
sprintf(temp, "%08x", debugger->readExtraMemory(memory, selection));
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
}
break;
case IDM_COPYHEX:
{
char temp[24];
sprintf(temp, "%08x", debugger->readExtraMemory(memory, selection));
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
}
break;
#endif
case IDM_TOGGLEMEMORY:
@ -197,7 +197,7 @@ void CMemoryView::OnMouseDownR(wxMouseEvent& event)
viewAsSubMenu->Append(IDM_VIEWASFP, StrToWxStr("FP value"));
viewAsSubMenu->Append(IDM_VIEWASASCII, StrToWxStr("ASCII"));
viewAsSubMenu->Append(IDM_VIEWASHEX, StrToWxStr("Hex"));
menu->AppendSubMenu(viewAsSubMenu, StrToWxStr("View As:"));
menu->AppendSubMenu(viewAsSubMenu, StrToWxStr("View As:"));
PopupMenu(menu);
}
@ -212,10 +212,10 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
wxCoord w,h;
dc.GetTextExtent(_T("0WJyq"),&w,&h,NULL,NULL,&hFont);
if (h > rowHeight)
rowHeight = h;
rowHeight = h;
dc.GetTextExtent(_T("0WJyq"),&w,&h,NULL,NULL,&DebuggerFont);
if (h > rowHeight)
rowHeight = h;
rowHeight = h;
if (viewAsType==VIEWAS_HEX)
dc.SetFont(hFont);
@ -359,7 +359,9 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
curAddress += 32;
}
else
{
sprintf(dis, "INVALID VIEWAS TYPE");
}
char desc[256] = "";
if (viewAsType != VIEWAS_HEX)

View file

@ -341,13 +341,13 @@ void CMemoryWindow::onSearch(wxCommandEvent& event)
newsize = rawData.size();
if (pad)
{
{
tmpstr = new char[newsize + 2];
memset(tmpstr, 0, newsize + 2);
tmpstr[0] = '0';
}
else
{
else
{
tmpstr = new char[newsize + 1];
memset(tmpstr, 0, newsize + 1);
}
@ -368,7 +368,9 @@ void CMemoryWindow::onSearch(wxCommandEvent& event)
i += 1;
}
delete[] tmpstr;
} else {
}
else
{
//Looking for an ascii string
size = rawData.size();
Dest.resize(size+1);

View file

@ -31,8 +31,10 @@ static const char *special_reg_names[] = {
"PC", "LR", "CTR", "CR", "FPSCR", "MSR", "SRR0", "SRR1", "Exceptions", "Int Mask", "Int Cause",
};
static u32 GetSpecialRegValue(int reg) {
switch (reg) {
static u32 GetSpecialRegValue(int reg)
{
switch (reg)
{
case 0: return PowerPC::ppcState.pc;
case 1: return PowerPC::ppcState.spr[SPR_LR];
case 2: return PowerPC::ppcState.spr[SPR_CTR];
@ -50,8 +52,10 @@ static u32 GetSpecialRegValue(int reg) {
wxString CRegTable::GetValue(int row, int col)
{
if (row < 32) {
switch (col) {
if (row < 32)
{
switch (col)
{
case 0: return StrToWxStr(GetGPRName(row));
case 1: return wxString::Format(wxT("%08x"), GPR(row));
case 2: return StrToWxStr(GetFPRName(row));
@ -59,20 +63,26 @@ wxString CRegTable::GetValue(int row, int col)
case 4: return wxString::Format(wxT("%016llx"), riPS1(row));
default: return wxEmptyString;
}
} else {
if (row - 32 < NUM_SPECIALS) {
switch (col) {
}
else
{
if (row - 32 < NUM_SPECIALS)
{
switch (col)
{
case 0: return StrToWxStr(special_reg_names[row - 32]);
case 1: return wxString::Format(wxT("%08x"), GetSpecialRegValue(row - 32));
default: return wxEmptyString;
}
}
}
}
return wxEmptyString;
return wxEmptyString;
}
static void SetSpecialRegValue(int reg, u32 value) {
switch (reg) {
static void SetSpecialRegValue(int reg, u32 value)
{
switch (reg)
{
case 0: PowerPC::ppcState.pc = value; break;
case 1: PowerPC::ppcState.spr[SPR_LR] = value; break;
case 2: PowerPC::ppcState.spr[SPR_CTR] = value; break;
@ -94,15 +104,19 @@ void CRegTable::SetValue(int row, int col, const wxString& strNewVal)
u32 newVal = 0;
if (TryParse(WxStrToStr(strNewVal), &newVal))
{
if (row < 32) {
if (row < 32)
{
if (col == 1)
GPR(row) = newVal;
else if (col == 3)
riPS0(row) = newVal;
else if (col == 4)
riPS1(row) = newVal;
} else {
if ((row - 32 < NUM_SPECIALS) && (col == 1)) {
}
else
{
if ((row - 32 < NUM_SPECIALS) && (col == 1))
{
SetSpecialRegValue(row - 32, newVal);
}
}
@ -135,7 +149,8 @@ wxGridCellAttr *CRegTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKind)
attr->SetBackgroundColour(wxColour(wxT("#FFFFFF"))); //wxWHITE
attr->SetFont(DebuggerFont);
switch (col) {
switch (col)
{
case 1:
attr->SetAlignment(wxALIGN_CENTER, wxALIGN_CENTER);
break;
@ -149,11 +164,13 @@ wxGridCellAttr *CRegTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKind)
}
bool red = false;
switch (col) {
switch (col)
{
case 1: red = row < 32 ? m_CachedRegHasChanged[row] : m_CachedSpecialRegHasChanged[row-32]; break;
case 3:
case 4: red = row < 32 ? m_CachedFRegHasChanged[row][col-3] : false; break;
}
attr->SetTextColour(red ? wxColor(wxT("#FF0000")) : wxColor(wxT("#000000")));
attr->IncRef();
return attr;

View file

@ -28,8 +28,8 @@ END_EVENT_TABLE()
CRegisterWindow::CRegisterWindow(wxWindow* parent, wxWindowID id,
const wxPoint& position, const wxSize& size,
long style, const wxString& name)
const wxPoint& position, const wxSize& size,
long style, const wxString& name)
: wxPanel(parent, id, position, size, style, name)
, m_GPRGridView(NULL)
{

View file

@ -387,18 +387,23 @@ void FifoPlayerDlg::OnCheckEarlyMemoryUpdates(wxCommandEvent& event)
void FifoPlayerDlg::OnSaveFile(wxCommandEvent& WXUNUSED(event))
{
// Pointer to the file data that was created as a result of recording.
FifoDataFile *file = FifoRecorder::GetInstance().GetRecordedFile();
if (file)
{
{
// Bring up a save file dialog. The location the user chooses will be assigned to this variable.
wxString path = wxSaveFileSelector(_("Dolphin FIFO"), wxT("dff"), wxEmptyString, this);
// Has a valid file path
if (!path.empty())
{
// Attempt to save the file to the path the user chose
wxBeginBusyCursor();
bool result = file->Save(WxStrToStr(path).c_str());
wxEndBusyCursor();
// Wasn't able to save the file, shit's whack, yo.
if (!result)
PanicAlert("Error saving file");
}
@ -409,14 +414,21 @@ void FifoPlayerDlg::OnRecordStop(wxCommandEvent& WXUNUSED(event))
{
FifoRecorder& recorder = FifoRecorder::GetInstance();
// Recorder is still recording
if (recorder.IsRecording())
{
// Then stop recording
recorder.StopRecording();
// and disable the button to stop recording
m_RecordStop->Disable();
}
else
else // Recorder is actually about to start recording
{
// So start recording
recorder.StartRecording(m_FramesToRecord, RecordingFinished);
// and change the button label accordingly.
m_RecordStop->SetLabel(_("Stop"));
}
}
@ -839,10 +851,12 @@ void FifoPlayerDlg::UpdateAnalyzerGui()
if ((int)m_framesList->GetCount() != num_frames)
{
m_framesList->Clear();
for (int i = 0; i < num_frames; ++i)
{
m_framesList->Append(wxString::Format(wxT("Frame %i"), i));
}
wxCommandEvent ev = wxCommandEvent(wxEVT_COMMAND_LISTBOX_SELECTED);
ev.SetInt(-1);
OnFrameListSelectionChanged(ev);

Some files were not shown because too many files have changed in this diff Show more