mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-08-26 20:58:28 -05:00
Merge branch 'master' into zcomploc-support
Conflicts: Source/Core/VideoCommon/Src/PixelShaderGen.cpp
This commit is contained in:
@@ -45,7 +45,6 @@
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
@@ -56,7 +55,6 @@
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
|
||||
@@ -6,33 +6,33 @@ set(SRCS Src/AudioCommon.cpp
|
||||
|
||||
set(LIBS "")
|
||||
|
||||
if(ALSA_FOUND)
|
||||
set(SRCS ${SRCS} Src/AlsaSoundStream.cpp)
|
||||
set(LIBS ${LIBS} ${ALSA_LIBRARIES})
|
||||
endif(ALSA_FOUND)
|
||||
|
||||
if(AO_FOUND)
|
||||
set(SRCS ${SRCS} Src/AOSoundStream.cpp)
|
||||
set(LIBS ${LIBS} ${AO_LIBRARIES})
|
||||
endif(AO_FOUND)
|
||||
|
||||
if(OPENAL_FOUND)
|
||||
set(SRCS ${SRCS} Src/OpenALStream.cpp Src/aldlist.cpp)
|
||||
set(LIBS ${LIBS} ${OPENAL_LIBRARY})
|
||||
endif(OPENAL_FOUND)
|
||||
|
||||
if(PULSEAUDIO_FOUND)
|
||||
set(SRCS ${SRCS} Src/PulseAudioStream.cpp)
|
||||
set(LIBS ${LIBS} ${PULSEAUDIO_LIBRARIES})
|
||||
endif(PULSEAUDIO_FOUND)
|
||||
|
||||
if(WIN32)
|
||||
set(SRCS ${SRCS} Src/DSoundStream.cpp)
|
||||
set(SRCS ${SRCS} Src/XAudio2Stream.cpp)
|
||||
endif(WIN32)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(SRCS ${SRCS} Src/CoreAudioSoundStream.cpp)
|
||||
else()
|
||||
if(ALSA_FOUND)
|
||||
set(SRCS ${SRCS} Src/AlsaSoundStream.cpp)
|
||||
set(LIBS ${LIBS} ${ALSA_LIBRARIES})
|
||||
endif(ALSA_FOUND)
|
||||
|
||||
if(AO_FOUND)
|
||||
set(SRCS ${SRCS} Src/AOSoundStream.cpp)
|
||||
set(LIBS ${LIBS} ${AO_LIBRARIES})
|
||||
endif(AO_FOUND)
|
||||
|
||||
if(OPENAL_FOUND)
|
||||
set(SRCS ${SRCS} Src/OpenALStream.cpp Src/aldlist.cpp)
|
||||
set(LIBS ${LIBS} openal)
|
||||
endif(OPENAL_FOUND)
|
||||
|
||||
if(PULSEAUDIO_FOUND)
|
||||
set(SRCS ${SRCS} Src/PulseAudioStream.cpp)
|
||||
set(LIBS ${LIBS} ${PULSEAUDIO_LIBRARIES})
|
||||
endif(PULSEAUDIO_FOUND)
|
||||
|
||||
if(WIN32)
|
||||
set(SRCS ${SRCS} Src/DSoundStream.cpp)
|
||||
set(SRCS ${SRCS} Src/XAudio2Stream.cpp)
|
||||
endif(WIN32)
|
||||
endif()
|
||||
|
||||
add_library(audiocommon STATIC ${SRCS})
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
void AOSound::SoundLoop()
|
||||
{
|
||||
Common::SetCurrentThreadName("Audio thread - ao");
|
||||
|
||||
uint_32 numBytesToRender = 256;
|
||||
ao_initialize();
|
||||
default_driver = ao_default_driver_id();
|
||||
|
||||
@@ -60,6 +60,7 @@ void AlsaSound::SoundLoop()
|
||||
thread_data = 2;
|
||||
return;
|
||||
}
|
||||
Common::SetCurrentThreadName("Audio thread - alsa");
|
||||
while (!thread_data)
|
||||
{
|
||||
m_mixer->Mix(reinterpret_cast<short *>(mix_buffer), frames_to_deliver);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "AudioCommon.h"
|
||||
#include "CommonPaths.h"
|
||||
#include "FileUtil.h"
|
||||
#include "../../Core/Src/ConfigManager.h"
|
||||
|
||||
AudioCommonConfig ac_Config;
|
||||
|
||||
@@ -31,7 +32,6 @@ void AudioCommonConfig::Load()
|
||||
file.Load(File::GetUserPath(F_DSPCONFIG_IDX));
|
||||
|
||||
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
|
||||
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
|
||||
file.Get("Config", "EnableJIT", &m_EnableJIT, true);
|
||||
file.Get("Config", "DumpAudio", &m_DumpAudio, false);
|
||||
#if defined __linux__ && HAVE_ALSA
|
||||
@@ -54,7 +54,6 @@ void AudioCommonConfig::SaveSettings()
|
||||
file.Load(File::GetUserPath(F_DSPCONFIG_IDX));
|
||||
|
||||
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
|
||||
file.Set("Config", "EnableThrottle", m_EnableThrottle);
|
||||
file.Set("Config", "EnableJIT", m_EnableJIT);
|
||||
file.Set("Config", "DumpAudio", m_DumpAudio);
|
||||
file.Set("Config", "Backend", sBackend);
|
||||
@@ -67,7 +66,7 @@ void AudioCommonConfig::SaveSettings()
|
||||
// Update according to the values (stream/mixer)
|
||||
void AudioCommonConfig::Update() {
|
||||
if (soundStream) {
|
||||
soundStream->GetMixer()->SetThrottle(m_EnableThrottle);
|
||||
soundStream->GetMixer()->SetThrottle(SConfig::GetInstance().m_Framelimit == 2);
|
||||
soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
|
||||
soundStream->SetVolume(m_Volume);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
struct AudioCommonConfig
|
||||
{
|
||||
bool m_EnableDTKMusic;
|
||||
bool m_EnableThrottle;
|
||||
bool m_EnableJIT;
|
||||
bool m_DumpAudio;
|
||||
int m_Volume;
|
||||
|
||||
@@ -96,6 +96,8 @@ bool DSound::WriteDataToBuffer(DWORD dwOffset, // Our own write
|
||||
// The audio thread.
|
||||
void DSound::SoundLoop()
|
||||
{
|
||||
Common::SetCurrentThreadName("Audio thread - dsound");
|
||||
|
||||
currentPos = 0;
|
||||
lastPos = 0;
|
||||
dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
|
||||
@@ -130,7 +132,7 @@ bool DSound::Start()
|
||||
|
||||
DWORD num1;
|
||||
short* p1;
|
||||
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
|
||||
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, DSBLOCK_ENTIREBUFFER);
|
||||
memset(p1, 0, num1);
|
||||
dsBuffer->Unlock(p1, num1, 0, 0);
|
||||
thread = std::thread(std::mem_fun(&DSound::SoundLoop), this);
|
||||
|
||||
@@ -121,6 +121,8 @@ void OpenALStream::Clear(bool mute)
|
||||
|
||||
void OpenALStream::SoundLoop()
|
||||
{
|
||||
Common::SetCurrentThreadName("Audio thread - openal");
|
||||
|
||||
ALenum err;
|
||||
u32 ulFrequency = m_mixer->GetSampleRate();
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ void PulseAudio::Update()
|
||||
// Called on audio thread.
|
||||
void PulseAudio::SoundLoop()
|
||||
{
|
||||
Common::SetCurrentThreadName("Audio thread - pulse");
|
||||
|
||||
thread_running = PulseInit();
|
||||
|
||||
while (thread_running)
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
#ifdef _WIN32
|
||||
#include "../../../../Externals/OpenAL/include/al.h"
|
||||
#include "../../../../Externals/OpenAL/include/alc.h"
|
||||
#elif defined(__APPLE__)
|
||||
#include <al.h>
|
||||
#include <alc.h>
|
||||
#else
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
@@ -56,7 +55,6 @@
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
|
||||
@@ -189,7 +189,7 @@ unsigned int XEmitter::ABI_GetAlignedFrameSize(unsigned int frameSize) {
|
||||
#ifdef __GNUC__
|
||||
(frameSize + 15) & -16;
|
||||
#else
|
||||
frameSize;
|
||||
(frameSize + 3) & -4;
|
||||
#endif
|
||||
return alignedSize;
|
||||
}
|
||||
@@ -200,16 +200,15 @@ void XEmitter::ABI_AlignStack(unsigned int frameSize) {
|
||||
// Linux requires the stack to be 16-byte aligned before calls that put SSE
|
||||
// vectors on the stack, but since we do not keep track of which calls do that,
|
||||
// it is effectively every call as well.
|
||||
// Windows binaries compiled with MSVC do not have such a restriction, but I
|
||||
// Windows binaries compiled with MSVC do not have such a restriction*, but I
|
||||
// expect that GCC on Windows acts the same as GCC on Linux in this respect.
|
||||
// It would be nice if someone could verify this.
|
||||
#ifdef __GNUC__
|
||||
// *However, the MSVC optimizing compiler assumes a 4-byte-aligned stack at times.
|
||||
unsigned int fillSize =
|
||||
ABI_GetAlignedFrameSize(frameSize) - (frameSize + 4);
|
||||
if (fillSize != 0) {
|
||||
SUB(32, R(ESP), Imm8(fillSize));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void XEmitter::ABI_RestoreStack(unsigned int frameSize) {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "Common.h"
|
||||
#include "DebugInterface.h"
|
||||
#include "BreakPoints.h"
|
||||
#include "../../Core/Src/PowerPC/JitCommon/JitBase.h"
|
||||
#include <sstream>
|
||||
|
||||
bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
|
||||
@@ -70,7 +71,11 @@ void BreakPoints::AddFromStrings(const TBreakPointsStr& bps)
|
||||
void BreakPoints::Add(const TBreakPoint& bp)
|
||||
{
|
||||
if (!IsAddressBreakPoint(bp.iAddress))
|
||||
{
|
||||
m_BreakPoints.push_back(bp);
|
||||
if (jit)
|
||||
jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void BreakPoints::Add(u32 em_address, bool temp)
|
||||
@@ -83,21 +88,35 @@ void BreakPoints::Add(u32 em_address, bool temp)
|
||||
pt.iAddress = em_address;
|
||||
|
||||
m_BreakPoints.push_back(pt);
|
||||
|
||||
if (jit)
|
||||
jit->GetBlockCache()->InvalidateICache(em_address, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void BreakPoints::Remove(u32 _iAddress)
|
||||
void BreakPoints::Remove(u32 em_address)
|
||||
{
|
||||
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
|
||||
{
|
||||
if (i->iAddress == _iAddress)
|
||||
if (i->iAddress == em_address)
|
||||
{
|
||||
m_BreakPoints.erase(i);
|
||||
if (jit)
|
||||
jit->GetBlockCache()->InvalidateICache(em_address, 4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BreakPoints::Clear()
|
||||
{
|
||||
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
|
||||
{
|
||||
if (jit)
|
||||
jit->GetBlockCache()->InvalidateICache(i->iAddress, 4);
|
||||
m_BreakPoints.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
MemChecks::TMemChecksStr MemChecks::GetStrings() const
|
||||
{
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
|
||||
// Remove Breakpoint
|
||||
void Remove(u32 _iAddress);
|
||||
void Clear() { m_BreakPoints.clear(); };
|
||||
void Clear();
|
||||
|
||||
void DeleteByAddress(u32 _Address);
|
||||
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
//#include <config/i386/cpuid.h>
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#if defined __FreeBSD__
|
||||
#include <sys/types.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#else
|
||||
static inline void do_cpuid(unsigned int *eax, unsigned int *ebx,
|
||||
unsigned int *ecx, unsigned int *edx)
|
||||
{
|
||||
@@ -39,41 +43,42 @@ static inline void do_cpuid(unsigned int *eax, unsigned int *ebx,
|
||||
// Note: EBX is reserved on Mac OS X and in PIC on Linux, so it has to
|
||||
// restored at the end of the asm block.
|
||||
__asm__ (
|
||||
"mov %%rbx,%%rdi;"
|
||||
"cpuid;"
|
||||
"movl %%ebx,%1;"
|
||||
"mov %%rdi,%%rbx;"
|
||||
: "=a" (*eax),
|
||||
"=g" (*ebx),
|
||||
"=S" (*ebx),
|
||||
"=c" (*ecx),
|
||||
"=d" (*edx)
|
||||
: "a" (*eax)
|
||||
: "rdi", "rbx"
|
||||
: "rbx"
|
||||
);
|
||||
#else
|
||||
__asm__(
|
||||
"movl %%ebx,%%edi;"
|
||||
__asm__ (
|
||||
"cpuid;"
|
||||
"movl %%ebx,%1;"
|
||||
"movl %%edi,%%ebx;"
|
||||
"movl %%ebx,%1;"
|
||||
: "=a" (*eax),
|
||||
"=g" (*ebx),
|
||||
"=S" (*ebx),
|
||||
"=c" (*ecx),
|
||||
"=d" (*edx)
|
||||
: "a" (*eax)
|
||||
: "edi", "ebx"
|
||||
: "ebx"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
#endif /* defined __FreeBSD__ */
|
||||
|
||||
static void __cpuid(int info[4], int x)
|
||||
{
|
||||
#if defined __FreeBSD__
|
||||
do_cpuid((unsigned int)x, (unsigned int*)info);
|
||||
#else
|
||||
unsigned int eax = x, ebx = 0, ecx = 0, edx = 0;
|
||||
do_cpuid(&eax, &ebx, &ecx, &edx);
|
||||
info[0] = eax;
|
||||
info[1] = ebx;
|
||||
info[2] = ecx;
|
||||
info[3] = edx;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -154,7 +154,21 @@ public:
|
||||
}
|
||||
(*ptr) += stringLen;
|
||||
}
|
||||
|
||||
|
||||
void Do(std::wstring &x)
|
||||
{
|
||||
int stringLen = sizeof(wchar_t)*((int)x.length() + 1);
|
||||
Do(stringLen);
|
||||
|
||||
switch (mode) {
|
||||
case MODE_READ: x = (wchar_t*)*ptr; break;
|
||||
case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
|
||||
case MODE_MEASURE: break;
|
||||
case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (wchar_t*)*ptr, "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break;
|
||||
}
|
||||
(*ptr) += stringLen;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void DoArray(T *x, int count) {
|
||||
DoVoid((void *)x, sizeof(T) * count);
|
||||
@@ -170,6 +184,17 @@ public:
|
||||
// TODO
|
||||
PanicAlert("Do(linked list<>) does not yet work.");
|
||||
}
|
||||
|
||||
void DoMarker(const char* prevName, u32 arbitraryNumber=0x42)
|
||||
{
|
||||
u32 cookie = arbitraryNumber;
|
||||
Do(cookie);
|
||||
if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber)
|
||||
{
|
||||
PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber);
|
||||
mode = PointerWrap::MODE_MEASURE;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ private:
|
||||
// Since it is always around on windows
|
||||
#define HAVE_WX 1
|
||||
|
||||
#define HAVE_PORTAUDIO 1
|
||||
|
||||
// Debug definitions
|
||||
#if defined(_DEBUG)
|
||||
#include <crtdbg.h>
|
||||
@@ -137,14 +139,18 @@ private:
|
||||
// wxWidgets does not have a true dummy macro for this.
|
||||
#define _trans(a) a
|
||||
|
||||
#if defined __APPLE__ && defined __i386__
|
||||
#define _M_SSE 0x300
|
||||
#elif defined __APPLE__ && defined __x86_64__
|
||||
#define _M_SSE 0x301
|
||||
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
|
||||
#define _M_SSE 0x301
|
||||
#elif _MSC_VER >= 1500 // Visual Studio 2008
|
||||
#define _M_SSE 0x402
|
||||
#if defined __GNUC__
|
||||
# if defined __SSE4_2__
|
||||
# define _M_SSE 0x402
|
||||
# elif defined __SSE4_1__
|
||||
# define _M_SSE 0x401
|
||||
# elif defined __SSSE3__
|
||||
# define _M_SSE 0x301
|
||||
# elif defined __SSE3__
|
||||
# define _M_SSE 0x300
|
||||
# endif
|
||||
#elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008
|
||||
# define _M_SSE 0x402
|
||||
#endif
|
||||
|
||||
// Host communication.
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
template <bool> struct CompileTimeAssert;
|
||||
template<> struct CompileTimeAssert<true> {};
|
||||
|
||||
#define b2(x) ( (x) | ( (x) >> 1) )
|
||||
#define b4(x) ( b2(x) | ( b2(x) >> 2) )
|
||||
#define b8(x) ( b4(x) | ( b4(x) >> 4) )
|
||||
#define b16(x) ( b8(x) | ( b8(x) >> 8) )
|
||||
#define b32(x) (b16(x) | (b16(x) >>16) )
|
||||
#define ROUND_UP_POW2(x) (b32(x - 1) + 1)
|
||||
|
||||
#if defined __GNUC__ && !defined __SSSE3__
|
||||
#include <emmintrin.h>
|
||||
static __inline __m128i __attribute__((__always_inline__))
|
||||
@@ -45,6 +52,8 @@ _mm_shuffle_epi8(__m128i a, __m128i mask)
|
||||
#include <errno.h>
|
||||
#ifdef __linux__
|
||||
#include <byteswap.h>
|
||||
#elif defined __FreeBSD__
|
||||
#include <sys/endian.h>
|
||||
#endif
|
||||
|
||||
// go to debugger mode
|
||||
@@ -137,6 +146,10 @@ inline __attribute__((always_inline)) u32 swap32(u32 _data)
|
||||
{return __builtin_bswap32(_data);}
|
||||
inline __attribute__((always_inline)) u64 swap64(u64 _data)
|
||||
{return __builtin_bswap64(_data);}
|
||||
#elif __FreeBSD__
|
||||
inline u16 swap16(u16 _data) {return bswap16(_data);}
|
||||
inline u32 swap32(u32 _data) {return bswap32(_data);}
|
||||
inline u64 swap64(u64 _data) {return bswap64(_data);}
|
||||
#else
|
||||
// Slow generic implementation.
|
||||
inline u16 swap16(u16 data) {return (data >> 8) | (data << 8);}
|
||||
|
||||
@@ -126,6 +126,8 @@
|
||||
#define WII_USA_SETTING "setting-usa.txt"
|
||||
#define WII_JAP_SETTING "setting-jpn.txt"
|
||||
|
||||
#define GECKO_CODE_HANDLER "codehandler.bin"
|
||||
|
||||
// Subdirs in Sys
|
||||
#define GC_SYS_DIR "GC"
|
||||
#define WII_SYS_DIR "Wii"
|
||||
|
||||
@@ -167,7 +167,7 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
|
||||
const u8 * data = (const u8*)src;
|
||||
const int nblocks = len / 16;
|
||||
u32 Step = (len / 8);
|
||||
if(samples == 0) samples = Step;
|
||||
if(samples == 0) samples = max(Step, 1u);
|
||||
Step = Step / samples;
|
||||
if(Step < 1) Step = 1;
|
||||
|
||||
@@ -245,7 +245,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
|
||||
u32 Step = (len / 8);
|
||||
const u64 *data = (const u64 *)src;
|
||||
const u64 *end = data + Step;
|
||||
if(samples == 0) samples = Step;
|
||||
if(samples == 0) samples = max(Step, 1u);
|
||||
Step = Step / samples;
|
||||
if(Step < 1) Step = 1;
|
||||
while(data < end)
|
||||
@@ -275,7 +275,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
|
||||
u32 Step = (len / 8);
|
||||
const u64 *data = (const u64 *)src;
|
||||
const u64 *end = data + Step;
|
||||
if(samples == 0) samples = Step;
|
||||
if(samples == 0) samples = max(Step, 1u);
|
||||
Step = Step / samples;
|
||||
if(Step < 1) Step = 1;
|
||||
while(data < end)
|
||||
@@ -318,7 +318,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
|
||||
u32 Step = (len/4);
|
||||
const u32 *data = (const u32 *)src;
|
||||
const u32 *end = data + Step;
|
||||
if(samples == 0) samples = Step;
|
||||
if(samples == 0) samples = max(Step, 1u);
|
||||
Step = Step / samples;
|
||||
if(Step < 1) Step = 1;
|
||||
while(data < end)
|
||||
@@ -390,7 +390,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples)
|
||||
u32 out[2];
|
||||
const int nblocks = len / 8;
|
||||
u32 Step = (len / 4);
|
||||
if(samples == 0) samples = Step;
|
||||
if(samples == 0) samples = max(Step, 1u);
|
||||
Step = Step / samples;
|
||||
if(Step < 1) Step = 1;
|
||||
|
||||
@@ -464,7 +464,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
|
||||
u32 Step = (len / 8);
|
||||
const u64 *data = (const u64 *)src;
|
||||
const u64 *end = data + Step;
|
||||
if(samples == 0) samples = Step;
|
||||
if(samples == 0) samples = max(Step, 1u);
|
||||
Step = Step / samples;
|
||||
if(Step < 1) Step = 1;
|
||||
while(data < end)
|
||||
|
||||
@@ -459,7 +459,11 @@ bool IniFile::Save(const char* filename)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::vector<Section>::const_iterator iter = sections.begin(); iter != sections.end(); ++iter)
|
||||
// Currently testing if dolphin community can handle the requirements of C++11 compilation
|
||||
// If you get a compiler error on this line, your compiler is probably old.
|
||||
// Update to g++ 4.4 or a recent version of clang (XCode 4.2 on OS X).
|
||||
// If you don't want to update, complain in a google code issue, the dolphin forums or #dolphin-emu.
|
||||
for (auto iter = sections.begin(); iter != sections.end(); ++iter)
|
||||
{
|
||||
const Section& section = *iter;
|
||||
|
||||
|
||||
@@ -21,12 +21,10 @@
|
||||
#include "Common.h"
|
||||
#include <fstream>
|
||||
|
||||
// Update this to the current SVN revision every time you change shader generation code.
|
||||
// We don't automatically get this from SVN_REV because that would mean regenerating the
|
||||
// shader cache for every revision, graphics-related or not, which is simply annoying.
|
||||
// Increment this every time you change shader generation code.
|
||||
enum
|
||||
{
|
||||
LINEAR_DISKCACHE_VER = 6964
|
||||
LINEAR_DISKCACHE_VER = 6972
|
||||
};
|
||||
|
||||
// On disk format:
|
||||
@@ -73,36 +71,58 @@ public:
|
||||
|
||||
// close any currently opened file
|
||||
Close();
|
||||
m_num_entries = 0;
|
||||
|
||||
// try opening for reading/writing
|
||||
m_file.open(filename, ios_base::in | ios_base::out | ios_base::binary | ios_base::app);
|
||||
m_file.open(filename, ios_base::in | ios_base::out | ios_base::binary);
|
||||
|
||||
m_file.seekg(0, std::ios::end);
|
||||
std::fstream::pos_type end_pos = m_file.tellg();
|
||||
m_file.seekg(0, std::ios::beg);
|
||||
std::fstream::pos_type start_pos = m_file.tellg();
|
||||
std::streamoff file_size = end_pos - start_pos;
|
||||
|
||||
if (m_file.is_open() && ValidateHeader())
|
||||
{
|
||||
// good header, read some key/value pairs
|
||||
u32 num_entries = 0;
|
||||
K key;
|
||||
|
||||
V *value = NULL;
|
||||
u32 value_size;
|
||||
u32 entry_number;
|
||||
|
||||
std::fstream::pos_type last_pos = m_file.tellg();
|
||||
|
||||
while (Read(&value_size))
|
||||
{
|
||||
std::streamoff next_extent = (last_pos - start_pos) + sizeof(value_size) + value_size;
|
||||
if (next_extent > file_size)
|
||||
break;
|
||||
|
||||
delete[] value;
|
||||
value = new V[value_size];
|
||||
|
||||
// read key/value and pass to reader
|
||||
if (Read(&key) && Read(value, value_size))
|
||||
if (Read(&key) &&
|
||||
Read(value, value_size) &&
|
||||
Read(&entry_number) &&
|
||||
entry_number == m_num_entries+1)
|
||||
{
|
||||
reader.Read(key, value, value_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++num_entries;
|
||||
m_num_entries++;
|
||||
last_pos = m_file.tellg();
|
||||
}
|
||||
m_file.seekp(last_pos);
|
||||
m_file.clear();
|
||||
|
||||
delete[] value;
|
||||
return num_entries;
|
||||
return m_num_entries;
|
||||
}
|
||||
|
||||
// failed to open file for reading or bad header
|
||||
@@ -129,10 +149,12 @@ public:
|
||||
// Appends a key-value pair to the store.
|
||||
void Append(const K &key, const V *value, u32 value_size)
|
||||
{
|
||||
// TODO: Should do a check that we don't already have "key"?
|
||||
// TODO: Should do a check that we don't already have "key"? (I think each caller does that already.)
|
||||
Write(&value_size);
|
||||
Write(&key);
|
||||
Write(value, value_size);
|
||||
m_num_entries++;
|
||||
Write(&m_num_entries);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -176,6 +198,7 @@ private:
|
||||
} m_header;
|
||||
|
||||
std::fstream m_file;
|
||||
u32 m_num_entries;
|
||||
};
|
||||
|
||||
#endif // _LINEAR_DISKCACHE
|
||||
|
||||
@@ -85,12 +85,17 @@ LogManager::LogManager()
|
||||
|
||||
m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str());
|
||||
m_consoleLog = new ConsoleListener();
|
||||
m_debuggerLog = new DebuggerLogListener();
|
||||
|
||||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
|
||||
{
|
||||
m_Log[i]->SetEnable(true);
|
||||
m_Log[i]->AddListener(m_fileLog);
|
||||
m_Log[i]->AddListener(m_consoleLog);
|
||||
#ifdef _MSC_VER
|
||||
if (IsDebuggerPresent())
|
||||
m_Log[i]->AddListener(m_debuggerLog);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +105,7 @@ LogManager::~LogManager()
|
||||
{
|
||||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog);
|
||||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog);
|
||||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog);
|
||||
}
|
||||
|
||||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
|
||||
@@ -187,3 +193,10 @@ void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
|
||||
std::lock_guard<std::mutex> lk(m_log_lock);
|
||||
m_logfile << msg << std::flush;
|
||||
}
|
||||
|
||||
void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
|
||||
{
|
||||
#if _MSC_VER
|
||||
::OutputDebugStringA(msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -58,6 +58,12 @@ private:
|
||||
bool m_enable;
|
||||
};
|
||||
|
||||
class DebuggerLogListener : public LogListener
|
||||
{
|
||||
public:
|
||||
void Log(LogTypes::LOG_LEVELS, const char *msg);
|
||||
};
|
||||
|
||||
class LogContainer
|
||||
{
|
||||
public:
|
||||
@@ -97,6 +103,7 @@ private:
|
||||
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
|
||||
FileLogListener *m_fileLog;
|
||||
ConsoleListener *m_consoleLog;
|
||||
DebuggerLogListener *m_debuggerLog;
|
||||
static LogManager *m_logManager; // Singleton. Ugh.
|
||||
|
||||
LogManager();
|
||||
@@ -153,6 +160,11 @@ public:
|
||||
return m_consoleLog;
|
||||
}
|
||||
|
||||
DebuggerLogListener *GetDebuggerListener() const
|
||||
{
|
||||
return m_debuggerLog;
|
||||
}
|
||||
|
||||
static LogManager* GetInstance()
|
||||
{
|
||||
return m_logManager;
|
||||
|
||||
@@ -27,28 +27,65 @@
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
|
||||
#include <unistd.h>
|
||||
#define PAGE_MASK (getpagesize() - 1)
|
||||
#define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK))
|
||||
#endif
|
||||
|
||||
// This is purposely not a full wrapper for virtualalloc/mmap, but it
|
||||
// provides exactly the primitive operations that Dolphin needs.
|
||||
|
||||
void* AllocateExecutableMemory(size_t size, bool low)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
#if defined(_WIN32)
|
||||
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
#else
|
||||
void* ptr = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
static char *map_hint = 0;
|
||||
#if defined(__x86_64__) && !defined(MAP_32BIT)
|
||||
// This OS has no flag to enforce allocation below the 4 GB boundary,
|
||||
// but if we hint that we want a low address it is very likely we will
|
||||
// get one.
|
||||
// An older version of this code used MAP_FIXED, but that has the side
|
||||
// effect of discarding already mapped pages that happen to be in the
|
||||
// requested virtual memory range (such as the emulated RAM, sometimes).
|
||||
if (low && (!map_hint))
|
||||
map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */
|
||||
#endif
|
||||
void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_ANON | MAP_PRIVATE
|
||||
#if defined __linux__ && defined __x86_64__
|
||||
#if defined(__x86_64__) && defined(MAP_32BIT)
|
||||
| (low ? MAP_32BIT : 0)
|
||||
#endif
|
||||
, -1, 0);
|
||||
#endif
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
// printf("Mapped executable memory at %p (size %ld)\n", ptr,
|
||||
// (unsigned long)size);
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
if (ptr == MAP_FAILED)
|
||||
{
|
||||
ptr = NULL;
|
||||
#else
|
||||
if (ptr == NULL)
|
||||
{
|
||||
#endif
|
||||
PanicAlert("Failed to allocate executable memory");
|
||||
#ifdef _M_X64
|
||||
}
|
||||
#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
|
||||
else
|
||||
{
|
||||
if (low)
|
||||
{
|
||||
map_hint += size;
|
||||
map_hint = (char*)round_page(map_hint); /* round up to the next page */
|
||||
// printf("Next map will (hopefully) be at %p\n", map_hint);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_M_X64)
|
||||
if ((u64)ptr >= 0x80000000 && low == true)
|
||||
PanicAlert("Executable memory ended up above 2GB!");
|
||||
#endif
|
||||
|
||||
@@ -86,7 +86,7 @@ bool MsgAlert(bool yes_no, int Style, const char* format, ...)
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
CharArrayFromFormatV(buffer, 2047, str_translator(format).c_str(), args);
|
||||
CharArrayFromFormatV(buffer, sizeof(buffer)-1, str_translator(format).c_str(), args);
|
||||
va_end(args);
|
||||
|
||||
ERROR_LOG(MASTER_LOG, "%s: %s", caption.c_str(), buffer);
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
|
||||
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
|
||||
// GCC 4.4 provides <thread>
|
||||
#ifndef _GLIBCXX_USE_SCHED_YIELD
|
||||
#define _GLIBCXX_USE_SCHED_YIELD
|
||||
#endif
|
||||
#include <thread>
|
||||
#else
|
||||
|
||||
|
||||
@@ -125,15 +125,26 @@ std::string StripQuotes(const std::string& s)
|
||||
bool TryParse(const std::string &str, u32 *const output)
|
||||
{
|
||||
char *endptr = NULL;
|
||||
u32 value = strtoul(str.c_str(), &endptr, 0);
|
||||
|
||||
// Reset errno to a value other than ERANGE
|
||||
errno = 0;
|
||||
|
||||
unsigned long value = strtoul(str.c_str(), &endptr, 0);
|
||||
|
||||
if (!endptr || *endptr)
|
||||
return false;
|
||||
|
||||
if (value == ULONG_MAX && errno == ERANGE)
|
||||
if (errno == ERANGE)
|
||||
return false;
|
||||
|
||||
*output = value;
|
||||
if (ULONG_MAX > UINT_MAX) {
|
||||
// Note: The typecasts avoid GCC warnings when long is 32 bits wide.
|
||||
if (value >= static_cast<unsigned long>(0x100000000ull)
|
||||
&& value <= static_cast<unsigned long>(0xFFFFFFFF00000000ull))
|
||||
return false;
|
||||
}
|
||||
|
||||
*output = static_cast<u32>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -387,7 +387,7 @@ bool SysConf::SaveToFile(const char *filename)
|
||||
}
|
||||
else if (i->type == Type_SmallArray)
|
||||
{
|
||||
const u8 len = i->dataLength;
|
||||
const u8 len = (u8)(i->dataLength);
|
||||
f.WriteArray(&len, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,10 +66,9 @@ struct SSysConfEntry
|
||||
}
|
||||
bool SetArrayData(u8* buffer, u16 bufferSize)
|
||||
{
|
||||
|
||||
if (buffer && bufferSize <= dataLength)
|
||||
if (buffer)
|
||||
{
|
||||
memcpy(data, buffer, bufferSize);
|
||||
memcpy(data, buffer, min<u16>(bufferSize, dataLength));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -72,6 +72,13 @@ public:
|
||||
is_set = false;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(m_mutex);
|
||||
// no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
|
||||
is_set = false;
|
||||
}
|
||||
|
||||
private:
|
||||
class IsSet
|
||||
{
|
||||
|
||||
@@ -30,7 +30,12 @@ const char *scm_rev_str = "Dolphin "
|
||||
#if !SCM_IS_MASTER
|
||||
"[" SCM_BRANCH_STR "] "
|
||||
#endif
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
BUILD_TYPE_STR SCM_DESC_STR "-ICC";
|
||||
#else
|
||||
BUILD_TYPE_STR SCM_DESC_STR;
|
||||
#endif
|
||||
|
||||
#ifdef _M_X64
|
||||
#define NP_ARCH "x64"
|
||||
|
||||
@@ -119,6 +119,7 @@ public:
|
||||
virtual void Video_GatherPipeBursted() = 0;
|
||||
|
||||
virtual bool Video_IsPossibleWaitingSetDrawDone() = 0;
|
||||
virtual bool Video_IsHiWatermarkActive() = 0;
|
||||
virtual void Video_AbortFrame() = 0;
|
||||
|
||||
virtual readFn16 Video_CPRead16() = 0;
|
||||
@@ -140,6 +141,7 @@ class VideoBackendHardware : public VideoBackend
|
||||
{
|
||||
void DoState(PointerWrap &p);
|
||||
void RunLoop(bool enable);
|
||||
bool Initialize(void *&) { InitializeShared(); return true; }
|
||||
|
||||
void EmuStateChange(EMUSTATE_CHANGE);
|
||||
|
||||
@@ -158,6 +160,7 @@ class VideoBackendHardware : public VideoBackend
|
||||
void Video_GatherPipeBursted();
|
||||
|
||||
bool Video_IsPossibleWaitingSetDrawDone();
|
||||
bool Video_IsHiWatermarkActive();
|
||||
void Video_AbortFrame();
|
||||
|
||||
readFn16 Video_CPRead16();
|
||||
@@ -165,6 +168,9 @@ class VideoBackendHardware : public VideoBackend
|
||||
readFn16 Video_PERead16();
|
||||
writeFn16 Video_PEWrite16();
|
||||
writeFn32 Video_PEWrite32();
|
||||
|
||||
protected:
|
||||
void InitializeShared();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -834,6 +834,102 @@ void XEmitter::SHL(int bits, OpArg dest, OpArg shift) {WriteShift(bits, dest, sh
|
||||
void XEmitter::SHR(int bits, OpArg dest, OpArg shift) {WriteShift(bits, dest, shift, 5);}
|
||||
void XEmitter::SAR(int bits, OpArg dest, OpArg shift) {WriteShift(bits, dest, shift, 7);}
|
||||
|
||||
// index can be either imm8 or register, don't use memory destination because it's slow
|
||||
void XEmitter::WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext)
|
||||
{
|
||||
if (dest.IsImm())
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "WriteBitTest - can't test imms");
|
||||
}
|
||||
if ((index.IsImm() && index.GetImmBits() != 8))
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "WriteBitTest - illegal argument");
|
||||
}
|
||||
if (bits == 16) Write8(0x66);
|
||||
if (index.IsImm())
|
||||
{
|
||||
dest.WriteRex(this, bits, bits);
|
||||
Write8(0x0F); Write8(0xBA);
|
||||
dest.WriteRest(this, 1, (X64Reg)ext);
|
||||
Write8((u8)index.offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
X64Reg operand = index.GetSimpleReg();
|
||||
dest.WriteRex(this, bits, bits, operand);
|
||||
Write8(0x0F); Write8(0x83 + 8*ext);
|
||||
dest.WriteRest(this, 1, operand);
|
||||
}
|
||||
}
|
||||
|
||||
void XEmitter::BT(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 4);}
|
||||
void XEmitter::BTS(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 5);}
|
||||
void XEmitter::BTR(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 6);}
|
||||
void XEmitter::BTC(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 7);}
|
||||
|
||||
//shift can be either imm8 or cl
|
||||
void XEmitter::SHRD(int bits, OpArg dest, OpArg src, OpArg shift)
|
||||
{
|
||||
bool writeImm = false;
|
||||
if (dest.IsImm())
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "SHRD - can't use imms as destination");
|
||||
}
|
||||
if (!src.IsSimpleReg())
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "SHRD - must use simple register as source");
|
||||
}
|
||||
if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8))
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "SHRD - illegal shift");
|
||||
}
|
||||
if (bits == 16) Write8(0x66);
|
||||
X64Reg operand = src.GetSimpleReg();
|
||||
dest.WriteRex(this, bits, bits, operand);
|
||||
if (shift.GetImmBits() == 8)
|
||||
{
|
||||
Write8(0x0F); Write8(0xAC);
|
||||
dest.WriteRest(this, 1, operand);
|
||||
Write8((u8)shift.offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
Write8(0x0F); Write8(0xAD);
|
||||
dest.WriteRest(this, 0, operand);
|
||||
}
|
||||
}
|
||||
|
||||
void XEmitter::SHLD(int bits, OpArg dest, OpArg src, OpArg shift)
|
||||
{
|
||||
bool writeImm = false;
|
||||
if (dest.IsImm())
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "SHLD - can't use imms as destination");
|
||||
}
|
||||
if (!src.IsSimpleReg())
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "SHLD - must use simple register as source");
|
||||
}
|
||||
if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8))
|
||||
{
|
||||
_assert_msg_(DYNA_REC, 0, "SHLD - illegal shift");
|
||||
}
|
||||
if (bits == 16) Write8(0x66);
|
||||
X64Reg operand = src.GetSimpleReg();
|
||||
dest.WriteRex(this, bits, bits, operand);
|
||||
if (shift.GetImmBits() == 8)
|
||||
{
|
||||
Write8(0x0F); Write8(0xA4);
|
||||
dest.WriteRest(this, 1, operand);
|
||||
Write8((u8)shift.offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
Write8(0x0F); Write8(0xA5);
|
||||
dest.WriteRest(this, 0, operand);
|
||||
}
|
||||
}
|
||||
|
||||
void OpArg::WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg _operandReg, int bits)
|
||||
{
|
||||
if (bits == 16)
|
||||
|
||||
@@ -249,6 +249,7 @@ private:
|
||||
void WriteMulDivType(int bits, OpArg src, int ext);
|
||||
void WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2);
|
||||
void WriteShift(int bits, OpArg dest, OpArg &shift, int ext);
|
||||
void WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext);
|
||||
void WriteMXCSR(OpArg arg, int ext);
|
||||
void WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0);
|
||||
void WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg &a1, const OpArg &a2);
|
||||
@@ -374,6 +375,16 @@ public:
|
||||
void SHR(int bits, OpArg dest, OpArg shift);
|
||||
void SAR(int bits, OpArg dest, OpArg shift);
|
||||
|
||||
// Bit Test
|
||||
void BT(int bits, OpArg dest, OpArg index);
|
||||
void BTS(int bits, OpArg dest, OpArg index);
|
||||
void BTR(int bits, OpArg dest, OpArg index);
|
||||
void BTC(int bits, OpArg dest, OpArg index);
|
||||
|
||||
// Double-Precision Shift
|
||||
void SHRD(int bits, OpArg dest, OpArg src, OpArg shift);
|
||||
void SHLD(int bits, OpArg dest, OpArg src, OpArg shift);
|
||||
|
||||
// Extend EAX into EDX in various ways
|
||||
void CWD(int bits = 16);
|
||||
inline void CDQ() {CWD(32);}
|
||||
|
||||
@@ -101,6 +101,7 @@ set(SRCS Src/ActionReplay.cpp
|
||||
Src/HW/EXI_DeviceIPL.cpp
|
||||
Src/HW/EXI_DeviceMemoryCard.cpp
|
||||
Src/HW/EXI_DeviceMic.cpp
|
||||
Src/HW/GCMemcard.cpp
|
||||
Src/HW/GCPad.cpp
|
||||
Src/HW/GCPadEmu.cpp
|
||||
Src/HW/GPFifo.cpp
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
@@ -56,7 +55,6 @@
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
@@ -117,7 +115,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -129,7 +127,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -141,7 +139,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -155,7 +153,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -169,7 +167,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -183,7 +181,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@@ -289,6 +287,7 @@
|
||||
<ClCompile Include="Src\HW\EXI_DeviceIPL.cpp" />
|
||||
<ClCompile Include="Src\HW\EXI_DeviceMemoryCard.cpp" />
|
||||
<ClCompile Include="Src\HW\EXI_DeviceMic.cpp" />
|
||||
<ClCompile Include="Src\HW\GCMemcard.cpp" />
|
||||
<ClCompile Include="Src\HW\GCPad.cpp" />
|
||||
<ClCompile Include="Src\HW\GCPadEmu.cpp" />
|
||||
<ClCompile Include="Src\HW\GPFifo.cpp" />
|
||||
@@ -485,6 +484,7 @@
|
||||
<ClInclude Include="Src\HW\EXI_DeviceIPL.h" />
|
||||
<ClInclude Include="Src\HW\EXI_DeviceMemoryCard.h" />
|
||||
<ClInclude Include="Src\HW\EXI_DeviceMic.h" />
|
||||
<ClInclude Include="Src\HW\GCMemcard.h" />
|
||||
<ClInclude Include="Src\HW\GCPad.h" />
|
||||
<ClInclude Include="Src\HW\GCPadEmu.h" />
|
||||
<ClInclude Include="Src\HW\GPFifo.h" />
|
||||
|
||||
@@ -553,6 +553,9 @@
|
||||
<Filter>FifoPlayer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\Movie.cpp" />
|
||||
<ClCompile Include="Src\HW\GCMemcard.cpp">
|
||||
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Src\ConfigManager.h" />
|
||||
@@ -1027,6 +1030,9 @@
|
||||
<Filter>FifoPlayer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Src\Movie.h" />
|
||||
<ClInclude Include="Src\HW\GCMemcard.h">
|
||||
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
@@ -1165,5 +1171,8 @@
|
||||
<Filter Include="FifoPlayer">
|
||||
<UniqueIdentifier>{ca7d56f7-4e84-4d15-9aea-7ae6fa7d6586}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="HW %28Flipper/Hollywood%29\GCMemcard">
|
||||
<UniqueIdentifier>{3e9e6e83-c1bf-45f9-aeff-231f98f60d29}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -97,6 +97,7 @@ files = [
|
||||
'Src/HW/EXI_DeviceIPL.cpp',
|
||||
'Src/HW/EXI_DeviceMemoryCard.cpp',
|
||||
'Src/HW/EXI_DeviceMic.cpp',
|
||||
'Src/HW/GCMemcard.cpp',
|
||||
'Src/HW/GCPad.cpp',
|
||||
'Src/HW/GCPadEmu.cpp',
|
||||
'Src/HW/GPFifo.cpp',
|
||||
|
||||
@@ -195,10 +195,13 @@ bool CBoot::BootUp()
|
||||
|
||||
NOTICE_LOG(BOOT, "Booting %s", _StartupPara.m_strFilename.c_str());
|
||||
|
||||
// HLE jump to loader (homebrew)
|
||||
HLE::Patch(0x80001800, "HBReload");
|
||||
const u8 stubstr[] = { 'S', 'T', 'U', 'B', 'H', 'A', 'X', 'X' };
|
||||
Memory::WriteBigEData(stubstr, 0x80001804, 8);
|
||||
// HLE jump to loader (homebrew). Disabled when Gecko is active as it interferes with the code handler
|
||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
|
||||
{
|
||||
HLE::Patch(0x80001800, "HBReload");
|
||||
const u8 stubstr[] = { 'S', 'T', 'U', 'B', 'H', 'A', 'X', 'X' };
|
||||
Memory::WriteBigEData(stubstr, 0x80001804, 8);
|
||||
}
|
||||
|
||||
g_symbolDB.Clear();
|
||||
VideoInterface::Preset(_StartupPara.bNTSC);
|
||||
|
||||
@@ -66,7 +66,7 @@ bool CBoot::EmulatedBS2_GC()
|
||||
DVDInterface::DVDRead(0x00000000, 0x80000000, 0x20); // write disc info
|
||||
|
||||
Memory::Write_U32(0x0D15EA5E, 0x80000020); // booted from bootrom. 0xE5207C22 = booted from jtag
|
||||
Memory::Write_U32(0x01800000, 0x80000028); // Physical Memory Size (24MB on retail)
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x80000028); // Physical Memory Size (24MB on retail)
|
||||
// TODO determine why some games fail when using a retail id. (Seem to take different EXI paths, see ikaruga for example)
|
||||
Memory::Write_U32(0x10000006, 0x8000002C); // Console type - DevKit (retail ID == 0x00000003) see yagcd 4.2.1.1.2
|
||||
|
||||
@@ -172,7 +172,6 @@ bool CBoot::EmulatedBS2_GC()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CBoot::SetupWiiMemory(unsigned int _CountryCode)
|
||||
{
|
||||
INFO_LOG(BOOT, "Setup Wii Memory...");
|
||||
@@ -238,14 +237,14 @@ bool CBoot::SetupWiiMemory(unsigned int _CountryCode)
|
||||
DVDInterface::DVDRead(0x00000000, 0x00000000, 0x20); // Game Code
|
||||
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
|
||||
Memory::Write_U32(0x00000001, 0x00000024); // Unknown
|
||||
Memory::Write_U32(0x01800000, 0x00000028); // MEM1 size 24MB
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x00000028); // MEM1 size 24MB
|
||||
Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model
|
||||
Memory::Write_U32(0x00000000, 0x00000030); // Init
|
||||
Memory::Write_U32(0x817FEC60, 0x00000034); // Init
|
||||
// 38, 3C should get start, size of FST through apploader
|
||||
Memory::Write_U32(0x38a00040, 0x00000060); // Exception init
|
||||
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
|
||||
Memory::Write_U32(0x01800000, 0x000000f0); // "Simulated memory size" (debug mode?)
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x000000f0); // "Simulated memory size" (debug mode?)
|
||||
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
|
||||
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
|
||||
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
|
||||
|
||||
@@ -223,7 +223,6 @@ void SConfig::SaveSettings()
|
||||
ini.Set("Core", "SelectedLanguage", m_LocalCoreStartupParameter.SelectedLanguage);
|
||||
ini.Set("Core", "MemcardA", m_strMemoryCardA);
|
||||
ini.Set("Core", "MemcardB", m_strMemoryCardB);
|
||||
ini.Set("Core", "ReloadMemcardOnState", b_reloadMCOnState);
|
||||
ini.Set("Core", "SlotA", m_EXIDevice[0]);
|
||||
ini.Set("Core", "SlotB", m_EXIDevice[1]);
|
||||
ini.Set("Core", "SerialPort1", m_EXIDevice[2]);
|
||||
@@ -354,8 +353,7 @@ void SConfig::LoadSettings()
|
||||
ini.Get("Core", "SelectedLanguage", &m_LocalCoreStartupParameter.SelectedLanguage, 0);
|
||||
ini.Get("Core", "MemcardA", &m_strMemoryCardA);
|
||||
ini.Get("Core", "MemcardB", &m_strMemoryCardB);
|
||||
ini.Get("Core", "ReloadMemcardOnState", &b_reloadMCOnState, true);
|
||||
ini.Get("Core", "SlotA", (int*)&m_EXIDevice[0], EXIDEVICE_MEMORYCARD_A);
|
||||
ini.Get("Core", "SlotA", (int*)&m_EXIDevice[0], EXIDEVICE_MEMORYCARD);
|
||||
ini.Get("Core", "SlotB", (int*)&m_EXIDevice[1], EXIDEVICE_NONE);
|
||||
ini.Get("Core", "SerialPort1", (int*)&m_EXIDevice[2], EXIDEVICE_NONE);
|
||||
ini.Get("Core", "BBA_MAC", &m_bba_mac);
|
||||
@@ -366,7 +364,7 @@ void SConfig::LoadSettings()
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
sprintf(sidevicenum, "SIDevice%i", i);
|
||||
ini.Get("Core", sidevicenum, (u32*)&m_SIDevice[i], i==0 ? SI_GC_CONTROLLER:SI_NONE);
|
||||
ini.Get("Core", sidevicenum, (u32*)&m_SIDevice[i], (i == 0) ? SIDEVICE_GC_CONTROLLER : SIDEVICE_NONE);
|
||||
}
|
||||
|
||||
ini.Get("Core", "WiiSDCard", &m_WiiSDCard, false);
|
||||
|
||||
@@ -47,12 +47,8 @@ struct SConfig : NonCopyable
|
||||
|
||||
std::string m_strMemoryCardA;
|
||||
std::string m_strMemoryCardB;
|
||||
// eject and reload the memory card on state
|
||||
// in ZTP and other games if the save file has been deleted from the memory card
|
||||
//this is necessary to save after loading a savestate
|
||||
bool b_reloadMCOnState;
|
||||
TEXIDevices m_EXIDevice[3];
|
||||
TSIDevices m_SIDevice[4];
|
||||
SIDevices m_SIDevice[4];
|
||||
std::string m_bba_mac;
|
||||
|
||||
// interface language
|
||||
|
||||
@@ -101,6 +101,7 @@ std::string g_stateFileName;
|
||||
std::thread g_EmuThread;
|
||||
|
||||
static std::thread g_cpu_thread;
|
||||
static bool g_requestRefreshInfo;
|
||||
|
||||
SCoreStartupParameter g_CoreStartupParameter;
|
||||
|
||||
@@ -261,7 +262,7 @@ void Stop() // - Hammertime!
|
||||
SConfig::GetInstance().m_SYSCONF->Reload();
|
||||
|
||||
INFO_LOG(CONSOLE, "Stop [Main Thread]\t\t---- Shutdown complete ----");
|
||||
Movie::g_InputCounter = 0;
|
||||
Movie::g_currentInputCount = 0;
|
||||
g_bStopping = false;
|
||||
}
|
||||
|
||||
@@ -345,6 +346,8 @@ void EmuThread()
|
||||
DisplayMessage(cpu_info.Summarize(), 8000);
|
||||
DisplayMessage(_CoreParameter.m_strFilename, 3000);
|
||||
|
||||
Movie::Init();
|
||||
|
||||
HW::Init();
|
||||
|
||||
if (!g_video_backend->Initialize(g_pWindowHandle))
|
||||
@@ -537,15 +540,20 @@ void SaveScreenShot()
|
||||
SetState(CORE_RUN);
|
||||
}
|
||||
|
||||
void RequestRefreshInfo()
|
||||
{
|
||||
g_requestRefreshInfo = true;
|
||||
}
|
||||
|
||||
// Apply Frame Limit and Display FPS info
|
||||
// This should only be called from VI
|
||||
void VideoThrottle()
|
||||
{
|
||||
u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 1) ?
|
||||
SConfig::GetInstance().m_Framelimit * 5 : VideoInterface::TargetRefreshRate;
|
||||
u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 2) ?
|
||||
(SConfig::GetInstance().m_Framelimit - 1) * 5 : VideoInterface::TargetRefreshRate;
|
||||
|
||||
// Disable the frame-limiter when the throttle (Tab) key is held down
|
||||
if (SConfig::GetInstance().m_Framelimit && !Host_GetKeyState('\t'))
|
||||
// Disable the frame-limiter when the throttle (Tab) key is held down. Audio throttle: m_Framelimit = 2
|
||||
if (SConfig::GetInstance().m_Framelimit && SConfig::GetInstance().m_Framelimit != 2 && !Host_GetKeyState('\t'))
|
||||
{
|
||||
u32 frametime = ((SConfig::GetInstance().b_UseFPS)? Common::AtomicLoad(DrawnFrame) : DrawnVideo) * 1000 / TargetVPS;
|
||||
|
||||
@@ -561,8 +569,9 @@ void VideoThrottle()
|
||||
|
||||
// Update info per second
|
||||
u32 ElapseTime = (u32)Timer.GetTimeDifference();
|
||||
if ((ElapseTime >= 1000 && DrawnVideo > 0) || Movie::g_bFrameStep)
|
||||
if ((ElapseTime >= 1000 && DrawnVideo > 0) || g_requestRefreshInfo)
|
||||
{
|
||||
g_requestRefreshInfo = false;
|
||||
SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
|
||||
|
||||
u32 FPS = Common::AtomicLoad(DrawnFrame) * 1000 / ElapseTime;
|
||||
@@ -599,8 +608,10 @@ void VideoThrottle()
|
||||
|
||||
#else // Summary information
|
||||
std::string SFPS;
|
||||
if (Movie::IsPlayingInput() || Movie::IsRecordingInput())
|
||||
SFPS = StringFromFormat("VI: %u - Frame: %u - FPS: %u - VPS: %u - SPEED: %u%%", Movie::g_frameCounter, Movie::g_InputCounter, FPS, VPS, Speed);
|
||||
if (Movie::IsPlayingInput())
|
||||
SFPS = StringFromFormat("VI: %u/%u - Frame: %u/%u - FPS: %u - VPS: %u - SPEED: %u%%", (u32)Movie::g_currentFrame, (u32)Movie::g_totalFrames, (u32)Movie::g_currentInputCount, (u32)Movie::g_totalInputCount, FPS, VPS, Speed);
|
||||
else if (Movie::IsRecordingInput())
|
||||
SFPS = StringFromFormat("VI: %u - Frame: %u - FPS: %u - VPS: %u - SPEED: %u%%", (u32)Movie::g_currentFrame, (u32)Movie::g_currentInputCount, FPS, VPS, Speed);
|
||||
else
|
||||
SFPS = StringFromFormat("FPS: %u - VPS: %u - SPEED: %u%%", FPS, VPS, Speed);
|
||||
#endif
|
||||
|
||||
@@ -85,6 +85,7 @@ void StopTrace();
|
||||
|
||||
bool ShouldSkipFrame(int skipped);
|
||||
void VideoThrottle();
|
||||
void RequestRefreshInfo();
|
||||
|
||||
#ifdef RERECORDING
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ void Init()
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
MoveEvents();
|
||||
ClearPendingEvents();
|
||||
UnregisterAllEvents();
|
||||
|
||||
@@ -163,6 +164,7 @@ void DoState(PointerWrap &p)
|
||||
p.Do(fakeDecStartTicks);
|
||||
p.Do(fakeTBStartValue);
|
||||
p.Do(fakeTBStartTicks);
|
||||
p.DoMarker("CoreTimingData");
|
||||
// OK, here we're gonna need to specialize depending on the mode.
|
||||
// Should do something generic to serialize linked lists.
|
||||
switch (p.GetMode()) {
|
||||
@@ -209,6 +211,7 @@ void DoState(PointerWrap &p)
|
||||
break;
|
||||
}
|
||||
}
|
||||
p.DoMarker("CoreTimingEvents");
|
||||
}
|
||||
|
||||
u64 GetTicks()
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
|
||||
@@ -85,14 +85,14 @@ void LoadBPReg(const BPCmd &bp, BPMemory &bpMem)
|
||||
|
||||
void GetTlutLoadData(u32 &tlutAddr, u32 &memAddr, u32 &tlutXferCount, BPMemory &bpMem)
|
||||
{
|
||||
tlutAddr = (bpMem.tlutXferDest & 0x3FF) << 9;
|
||||
tlutXferCount = (bpMem.tlutXferDest & 0x1FFC00) >> 5;
|
||||
tlutAddr = (bpMem.tmem_config.tlut_dest & 0x3FF) << 9;
|
||||
tlutXferCount = (bpMem.tmem_config.tlut_dest & 0x1FFC00) >> 5;
|
||||
|
||||
// TODO - figure out a cleaner way.
|
||||
if (Core::g_CoreStartupParameter.bWii)
|
||||
memAddr = bpmem.tlutXferSrc << 5;
|
||||
memAddr = bpmem.tmem_config.tlut_src << 5;
|
||||
else
|
||||
memAddr = (bpmem.tlutXferSrc & 0xFFFFF) << 5;
|
||||
memAddr = (bpmem.tmem_config.tlut_src & 0xFFFFF) << 5;
|
||||
}
|
||||
|
||||
void LoadCPReg(u32 subCmd, u32 value, CPMemory &cpMem)
|
||||
@@ -232,4 +232,4 @@ void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory &cpMe
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,4 +51,4 @@ namespace FifoAnalyzer
|
||||
void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory &cpMem);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -282,4 +282,4 @@ void FifoDataFile::ReadMemoryUpdates(u64 fileOffset, u32 numUpdates, std::vector
|
||||
file.Seek(srcUpdate.dataOffset, SEEK_SET);
|
||||
file.ReadBytes(dstUpdate.data, srcUpdate.dataSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,4 +109,4 @@ private:
|
||||
std::vector<FifoFrameInfo> m_Frames;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -82,4 +82,4 @@ struct FileMemoryUpdate
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -343,4 +343,4 @@ void FifoPlaybackAnalyzer::StoreWrittenRegion(u32 address, u32 size)
|
||||
|
||||
m_WrittenMemory.push_back(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,4 +61,4 @@ private:
|
||||
FifoAnalyzer::CPMemory m_CpMem;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -118,4 +118,4 @@ private:
|
||||
std::vector<AnalyzedFrameInfo> m_FrameInfo;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -302,4 +302,4 @@ void FifoRecordAnalyzer::WriteTexMapMemory(int texMap, u32 &writtenTexMaps)
|
||||
}
|
||||
|
||||
FifoRecorder::GetInstance().WriteMemory(imageBase, textureSize, MemoryUpdate::TEXTURE_MAP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,4 +53,4 @@ private:
|
||||
FifoAnalyzer::CPMemory m_CpMem;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -77,4 +77,4 @@ private:
|
||||
FifoRecordAnalyzer m_RecordAnalyzer;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
// 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/
|
||||
|
||||
#include "GeckoCode.h"
|
||||
|
||||
#include "Thread.h"
|
||||
@@ -5,6 +19,8 @@
|
||||
#include "ConfigManager.h"
|
||||
|
||||
#include "vector"
|
||||
#include "PowerPC/PowerPC.h"
|
||||
#include "CommonPaths.h"
|
||||
|
||||
namespace Gecko
|
||||
{
|
||||
@@ -40,6 +56,9 @@ static struct
|
||||
// codes execute when counter is 0
|
||||
static int code_execution_counter = 0;
|
||||
|
||||
// Track whether the code handler has been installed
|
||||
static bool code_handler_installed = false;
|
||||
|
||||
// the currently active codes
|
||||
std::vector<GeckoCode> active_codes;
|
||||
|
||||
@@ -93,6 +112,70 @@ void SetActiveCodes(const std::vector<GeckoCode>& gcodes)
|
||||
}
|
||||
|
||||
inserted_asm_codes.clear();
|
||||
|
||||
code_handler_installed = false;
|
||||
}
|
||||
|
||||
bool InstallCodeHandler()
|
||||
{
|
||||
u32 codelist_location = 0x800028B8; // Debugger on location (0x800022A8 = Debugger off, using codehandleronly.bin)
|
||||
std::string data;
|
||||
std::string _rCodeHandlerFilename = File::GetSysDirectory() + GECKO_CODE_HANDLER;
|
||||
if (!File::ReadFileToString(false, _rCodeHandlerFilename.c_str(), data))
|
||||
return false;
|
||||
|
||||
// Install code handler
|
||||
Memory::WriteBigEData((const u8*)data.data(), 0x80001800, data.length());
|
||||
|
||||
// Turn off Pause on start
|
||||
Memory::Write_U32(0, 0x80002774);
|
||||
|
||||
// Write the Game ID into the location expected by WiiRD
|
||||
Memory::WriteBigEData(Memory::GetPointer(0x80000000), 0x80001800, 6);
|
||||
|
||||
// Create GCT in memory
|
||||
Memory::Write_U32(0x00d0c0de, codelist_location);
|
||||
Memory::Write_U32(0x00d0c0de, codelist_location + 4);
|
||||
|
||||
std::lock_guard<std::mutex> lk(active_codes_lock);
|
||||
|
||||
int i = 0;
|
||||
std::vector<GeckoCode>::iterator
|
||||
gcodes_iter = active_codes.begin(),
|
||||
gcodes_end = active_codes.end();
|
||||
for (; gcodes_iter!=gcodes_end; ++gcodes_iter)
|
||||
{
|
||||
if (gcodes_iter->enabled)
|
||||
{
|
||||
current_code = codes_start = &*gcodes_iter->codes.begin();
|
||||
codes_end = &*gcodes_iter->codes.end();
|
||||
for (; current_code < codes_end; ++current_code)
|
||||
{
|
||||
const GeckoCode::Code& code = *current_code;
|
||||
|
||||
// Make sure we have enough memory to hold the code list
|
||||
if ((codelist_location + 24 + i) < 0x80003000)
|
||||
{
|
||||
Memory::Write_U32(code.address, codelist_location + 8 + i);
|
||||
Memory::Write_U32(code.data, codelist_location + 12 + i);
|
||||
i += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Memory::Write_U32(0xff000000, codelist_location + 8 + i);
|
||||
Memory::Write_U32(0x00000000, codelist_location + 12 + i);
|
||||
|
||||
// Turn on codes
|
||||
Memory::Write_U8(1, 0x80001807);
|
||||
|
||||
// Invalidate the icache
|
||||
for (int i = 0; i < data.length(); i += 32)
|
||||
{
|
||||
PowerPC::ppcState.iCache.Invalidate(0x80001800 + i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RunGeckoCode(GeckoCode& gecko_code)
|
||||
@@ -137,7 +220,7 @@ bool RunGeckoCode(GeckoCode& gecko_code)
|
||||
gecko_code.enabled = false;
|
||||
|
||||
PanicAlertT("GeckoCode failed to run (CT%i CST%i) (%s)"
|
||||
"\n(either a bad code or the code type is not yet supported.)"
|
||||
"\n(either a bad code or the code type is not yet supported. Try using the native code handler by placing the codehandler.bin file into the Sys directory and restarting Dolphin.)"
|
||||
, code.type, code.subtype, gecko_code.name.c_str());
|
||||
return false;
|
||||
}
|
||||
@@ -168,6 +251,44 @@ bool RunActiveCodes()
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunCodeHandler()
|
||||
{
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
|
||||
{
|
||||
u8 *gameId = Memory::GetPointer(0x80000000);
|
||||
u8 *wiirdId = Memory::GetPointer(0x80001800);
|
||||
|
||||
if (!code_handler_installed || memcmp(gameId, wiirdId, 6))
|
||||
code_handler_installed = InstallCodeHandler();
|
||||
|
||||
if (code_handler_installed)
|
||||
{
|
||||
if (PC == LR)
|
||||
{
|
||||
u32 oldLR = LR;
|
||||
PowerPC::CoreMode oldMode = PowerPC::GetMode();
|
||||
|
||||
PC = 0x800018A8;
|
||||
LR = 0;
|
||||
|
||||
// Execute the code handler in interpreter mode to track when it exits
|
||||
PowerPC::SetMode(PowerPC::MODE_INTERPRETER);
|
||||
|
||||
while (PC != 0)
|
||||
PowerPC::SingleStep();
|
||||
|
||||
PowerPC::SetMode(oldMode);
|
||||
PC = LR = oldLR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the emulated code handler
|
||||
Gecko::RunActiveCodes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::map<u32, std::vector<u32> >& GetInsertedAsmCodes() {
|
||||
return inserted_asm_codes;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
// 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/
|
||||
|
||||
#ifndef __GECKOCODE_h__
|
||||
#define __GECKOCODE_h__
|
||||
@@ -67,6 +80,7 @@ namespace Gecko
|
||||
|
||||
void SetActiveCodes(const std::vector<GeckoCode>& gcodes);
|
||||
bool RunActiveCodes();
|
||||
void RunCodeHandler();
|
||||
const std::map<u32, std::vector<u32> >& GetInsertedAsmCodes();
|
||||
|
||||
} // namespace Gecko
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
// 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/
|
||||
|
||||
#include "GeckoCodeConfig.h"
|
||||
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
// 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/
|
||||
|
||||
#ifndef __GECKOCODECONFIG_h__
|
||||
#define __GECKOCODECONFIG_h__
|
||||
|
||||
@@ -69,9 +69,10 @@ void GetStringVA(std::string& _rOutBuffer, u32 strReg)
|
||||
char ArgumentBuffer[256];
|
||||
u32 ParameterCounter = 4;
|
||||
u32 FloatingParameterCounter = 1;
|
||||
char* pString = (char*)Memory::GetPointer(GPR(strReg));
|
||||
if (!pString) {
|
||||
//PanicAlert("Invalid GetStringVA call");
|
||||
char *pString = (char*)Memory::GetPointer(GPR(strReg));
|
||||
if (!pString)
|
||||
{
|
||||
ERROR_LOG(OSREPORT, "r%i invalid", strReg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,6 +153,12 @@ void Init()
|
||||
m_Volume.hex = 0;
|
||||
m_SampleCounter = 0;
|
||||
m_InterruptTiming = 0;
|
||||
|
||||
g_LastCPUTime = 0;
|
||||
g_CPUCyclesPerSample = 0xFFFFFFFFFFFULL;
|
||||
|
||||
g_AISSampleRate = 48000;
|
||||
g_AIDSampleRate = 32000;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
|
||||
@@ -115,6 +115,7 @@ void CCPU::EnableStepping(const bool _bStepping)
|
||||
if (_bStepping)
|
||||
{
|
||||
PowerPC::Pause();
|
||||
m_StepEvent.Reset();
|
||||
g_video_backend->EmuStateChange(EMUSTATE_CHANGE_PAUSE);
|
||||
DSP::GetDSPEmulator()->DSP_ClearAudioBuffer(true);
|
||||
}
|
||||
|
||||
@@ -131,7 +131,51 @@ void DSPHLE::SwapUCode(u32 _crc)
|
||||
void DSPHLE::DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(m_InitMixer);
|
||||
GetUCode()->DoState(p);
|
||||
p.Do(m_DSPControl);
|
||||
p.Do(m_dspState);
|
||||
|
||||
int ucode_crc = IUCode::GetCRC(m_pUCode);
|
||||
int ucode_crc_beforeLoad = ucode_crc;
|
||||
int lastucode_crc = IUCode::GetCRC(m_lastUCode);
|
||||
int lastucode_crc_beforeLoad = lastucode_crc;
|
||||
|
||||
p.Do(ucode_crc);
|
||||
p.Do(lastucode_crc);
|
||||
|
||||
// if a different type of ucode was being used when the savestate was created,
|
||||
// we have to reconstruct the old type of ucode so that we have a valid thing to call DoState on.
|
||||
IUCode* ucode = (ucode_crc == ucode_crc_beforeLoad) ? m_pUCode : UCodeFactory( ucode_crc, this, m_bWii);
|
||||
IUCode* lastucode = (lastucode_crc != lastucode_crc_beforeLoad) ? m_lastUCode : UCodeFactory(lastucode_crc, this, m_bWii);
|
||||
|
||||
if (ucode)
|
||||
ucode->DoState(p);
|
||||
if (lastucode)
|
||||
lastucode->DoState(p);
|
||||
|
||||
// if a different type of ucode was being used when the savestate was created,
|
||||
// discard it if we're not loading, otherwise discard the old one and keep the new one.
|
||||
if (ucode != m_pUCode)
|
||||
{
|
||||
if (p.GetMode() != PointerWrap::MODE_READ)
|
||||
delete ucode;
|
||||
else
|
||||
{
|
||||
delete m_pUCode;
|
||||
m_pUCode = ucode;
|
||||
}
|
||||
}
|
||||
if (lastucode != m_lastUCode)
|
||||
{
|
||||
if (p.GetMode() != PointerWrap::MODE_READ)
|
||||
delete lastucode;
|
||||
else
|
||||
{
|
||||
delete m_lastUCode;
|
||||
m_lastUCode = lastucode;
|
||||
}
|
||||
}
|
||||
|
||||
m_MailHandler.DoState(p);
|
||||
}
|
||||
|
||||
// Mailbox fuctions
|
||||
|
||||
@@ -28,9 +28,8 @@
|
||||
#include "UCode_AX_Voice.h"
|
||||
|
||||
CUCode_AX::CUCode_AX(DSPHLE *dsp_hle, u32 l_CRC)
|
||||
: IUCode(dsp_hle)
|
||||
: IUCode(dsp_hle, l_CRC)
|
||||
, m_addressPBs(0xFFFFFFFF)
|
||||
, _CRC(l_CRC)
|
||||
{
|
||||
// we got loaded
|
||||
m_rMailHandler.PushMail(DSP_INIT);
|
||||
@@ -175,7 +174,7 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
|
||||
|
||||
ProcessUpdates(PB);
|
||||
|
||||
if (_CRC != 0x3389a79e)
|
||||
if (m_CRC != 0x3389a79e)
|
||||
VoiceHacks(PB);
|
||||
|
||||
MixAddVoice(PB, templbuffer, temprbuffer, _iSize);
|
||||
@@ -463,11 +462,8 @@ void CUCode_AX::DoState(PointerWrap &p)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m_csMix);
|
||||
|
||||
p.Do(_CRC);
|
||||
p.Do(numPBaddr);
|
||||
p.Do(m_addressPBs);
|
||||
p.Do(PBaddr);
|
||||
p.Do(m_UploadSetupInProgress);
|
||||
|
||||
m_rMailHandler.DoState(p);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ public:
|
||||
u8 numPBaddr;
|
||||
u32 PBaddr[8]; //2 needed for MP2
|
||||
u32 m_addressPBs;
|
||||
u32 _CRC;
|
||||
|
||||
private:
|
||||
enum
|
||||
|
||||
@@ -28,9 +28,8 @@
|
||||
|
||||
|
||||
CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC)
|
||||
: IUCode(dsp_hle)
|
||||
: IUCode(dsp_hle, l_CRC)
|
||||
, m_addressPBs(0xFFFFFFFF)
|
||||
, _CRC(l_CRC)
|
||||
{
|
||||
// we got loaded
|
||||
m_rMailHandler.PushMail(DSP_INIT);
|
||||
@@ -38,7 +37,7 @@ CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC)
|
||||
templbuffer = new int[1024 * 1024];
|
||||
temprbuffer = new int[1024 * 1024];
|
||||
|
||||
wiisportsHack = _CRC == 0xfa450138;
|
||||
wiisportsHack = m_CRC == 0xfa450138;
|
||||
}
|
||||
|
||||
CUCode_AXWii::~CUCode_AXWii()
|
||||
@@ -260,10 +259,7 @@ void CUCode_AXWii::DoState(PointerWrap &p)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m_csMix);
|
||||
|
||||
p.Do(_CRC);
|
||||
p.Do(m_addressPBs);
|
||||
p.Do(wiisportsHack);
|
||||
p.Do(m_UploadSetupInProgress);
|
||||
|
||||
m_rMailHandler.DoState(p);
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#include "../../DSP.h"
|
||||
|
||||
|
||||
CUCode_CARD::CUCode_CARD(DSPHLE *dsp_hle)
|
||||
: IUCode(dsp_hle)
|
||||
CUCode_CARD::CUCode_CARD(DSPHLE *dsp_hle, u32 crc)
|
||||
: IUCode(dsp_hle, crc)
|
||||
{
|
||||
DEBUG_LOG(DSPHLE, "CUCode_CARD - initialized");
|
||||
m_rMailHandler.PushMail(DSP_INIT);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
class CUCode_CARD : public IUCode
|
||||
{
|
||||
public:
|
||||
CUCode_CARD(DSPHLE *dsp_hle);
|
||||
CUCode_CARD(DSPHLE *dsp_hle, u32 crc);
|
||||
virtual ~CUCode_CARD();
|
||||
|
||||
void HandleMail(u32 _uMail);
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
#include "../../DSP.h"
|
||||
|
||||
CUCode_GBA::CUCode_GBA(DSPHLE *dsp_hle)
|
||||
: IUCode(dsp_hle)
|
||||
CUCode_GBA::CUCode_GBA(DSPHLE *dsp_hle, u32 crc)
|
||||
: IUCode(dsp_hle, crc)
|
||||
{
|
||||
m_rMailHandler.PushMail(DSP_INIT);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
struct CUCode_GBA : public IUCode
|
||||
{
|
||||
CUCode_GBA(DSPHLE *dsp_hle);
|
||||
CUCode_GBA(DSPHLE *dsp_hle, u32 crc);
|
||||
virtual ~CUCode_GBA();
|
||||
|
||||
void HandleMail(u32 _uMail);
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
#include "UCodes.h"
|
||||
#include "UCode_InitAudioSystem.h"
|
||||
|
||||
CUCode_InitAudioSystem::CUCode_InitAudioSystem(DSPHLE *dsp_hle)
|
||||
: IUCode(dsp_hle)
|
||||
CUCode_InitAudioSystem::CUCode_InitAudioSystem(DSPHLE *dsp_hle, u32 crc)
|
||||
: IUCode(dsp_hle, crc)
|
||||
{
|
||||
DEBUG_LOG(DSPHLE, "CUCode_InitAudioSystem - initialized");
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
class CUCode_InitAudioSystem : public IUCode
|
||||
{
|
||||
public:
|
||||
CUCode_InitAudioSystem(DSPHLE *dsp_hle);
|
||||
CUCode_InitAudioSystem(DSPHLE *dsp_hle, u32 crc);
|
||||
virtual ~CUCode_InitAudioSystem();
|
||||
|
||||
void HandleMail(u32 _uMail);
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#include "Hash.h"
|
||||
#include "../../Memmap.h"
|
||||
|
||||
CUCode_Rom::CUCode_Rom(DSPHLE *dsp_hle)
|
||||
: IUCode(dsp_hle)
|
||||
CUCode_Rom::CUCode_Rom(DSPHLE *dsp_hle, u32 crc)
|
||||
: IUCode(dsp_hle, crc)
|
||||
, m_CurrentUCode()
|
||||
, m_BootTask_numSteps(0)
|
||||
, m_NextParameter(0)
|
||||
@@ -117,4 +117,10 @@ void CUCode_Rom::BootUCode()
|
||||
m_DSPHLE->SetUCode(ector_crc);
|
||||
}
|
||||
|
||||
void CUCode_Rom::DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(m_CurrentUCode);
|
||||
p.Do(m_BootTask_numSteps);
|
||||
p.Do(m_NextParameter);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,14 @@
|
||||
class CUCode_Rom : public IUCode
|
||||
{
|
||||
public:
|
||||
CUCode_Rom(DSPHLE *dsp_hle);
|
||||
CUCode_Rom(DSPHLE *dsp_hle, u32 _crc);
|
||||
virtual ~CUCode_Rom();
|
||||
|
||||
void HandleMail(u32 _uMail);
|
||||
void Update(int cycles);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
private:
|
||||
struct SUCode
|
||||
{
|
||||
|
||||
@@ -31,8 +31,7 @@
|
||||
|
||||
CUCode_Zelda::CUCode_Zelda(DSPHLE *dsp_hle, u32 _CRC)
|
||||
:
|
||||
IUCode(dsp_hle),
|
||||
m_CRC(_CRC),
|
||||
IUCode(dsp_hle, _CRC),
|
||||
|
||||
m_bSyncInProgress(false),
|
||||
m_MaxVoice(0),
|
||||
@@ -572,8 +571,6 @@ void CUCode_Zelda::DoState(PointerWrap &p)
|
||||
// It's bad if we try to save during Mix()
|
||||
std::lock_guard<std::mutex> lk(m_csMix);
|
||||
|
||||
p.Do(m_CRC);
|
||||
|
||||
p.Do(m_AFCCoefTable);
|
||||
p.Do(m_MiscTable);
|
||||
|
||||
@@ -616,6 +613,4 @@ void CUCode_Zelda::DoState(PointerWrap &p)
|
||||
p.Do(m_PBAddress2);
|
||||
|
||||
p.Do(m_UploadSetupInProgress);
|
||||
|
||||
m_rMailHandler.DoState(p);
|
||||
}
|
||||
|
||||
@@ -212,8 +212,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
u32 m_CRC;
|
||||
|
||||
// These are the only dynamically allocated things allowed in the ucode.
|
||||
s32* m_VoiceBuffer;
|
||||
s16* m_ResampleBuffer;
|
||||
|
||||
@@ -426,18 +426,15 @@ void CUCode_Zelda::RenderVoice_Raw(ZeldaVoicePB &PB, s16 *_Buffer, int _Size)
|
||||
|
||||
PB.Unk36[0] = (u16)(ACC0 >> 16);
|
||||
|
||||
// This subtract does really not make much sense at all.
|
||||
ACC0 -= AX0 << 16;
|
||||
|
||||
if ((s64)ACC0 < 0)
|
||||
{
|
||||
// There's something wrong with this looping code.
|
||||
|
||||
ERROR_LOG(DSPHLE, "Raw loop: ReadAudio size = %04x 34:%04x %08x", PB.Unk36[0], PB.raw[0x34 ^ 1], (int)ACC0);
|
||||
// ERROR_LOG(DSPHLE, "Raw loop: ReadAudio size = %04x 34:%04x %08x", PB.Unk36[0], PB.raw[0x34 ^ 1], (int)ACC0);
|
||||
Decoder21_ReadAudio(PB, PB.Unk36[0], _Buffer);
|
||||
|
||||
ACC0 = _Size << 16;
|
||||
ACC0 -= PB.Unk36[0] << 16;
|
||||
ACC0 = -(s64)ACC0;
|
||||
_Buffer += PB.Unk36[0];
|
||||
|
||||
PB.raw[0x34 ^ 1] = 0;
|
||||
|
||||
|
||||
@@ -32,19 +32,19 @@ IUCode* UCodeFactory(u32 _CRC, DSPHLE *dsp_hle, bool bWii)
|
||||
{
|
||||
case UCODE_ROM:
|
||||
INFO_LOG(DSPHLE, "Switching to ROM ucode");
|
||||
return new CUCode_Rom(dsp_hle);
|
||||
return new CUCode_Rom(dsp_hle, _CRC);
|
||||
|
||||
case UCODE_INIT_AUDIO_SYSTEM:
|
||||
INFO_LOG(DSPHLE, "Switching to INIT ucode");
|
||||
return new CUCode_InitAudioSystem(dsp_hle);
|
||||
return new CUCode_InitAudioSystem(dsp_hle, _CRC);
|
||||
|
||||
case 0x65d6cc6f: // CARD
|
||||
INFO_LOG(DSPHLE, "Switching to CARD ucode");
|
||||
return new CUCode_CARD(dsp_hle);
|
||||
return new CUCode_CARD(dsp_hle, _CRC);
|
||||
|
||||
case 0xdd7e72d5:
|
||||
INFO_LOG(DSPHLE, "Switching to GBA ucode");
|
||||
return new CUCode_GBA(dsp_hle);
|
||||
return new CUCode_GBA(dsp_hle, _CRC);
|
||||
|
||||
case 0x3ad3b7ac: // Naruto3, Paper Mario - The Thousand Year Door
|
||||
case 0x3daf59b9: // Alien Hominid
|
||||
@@ -103,6 +103,9 @@ IUCode* UCodeFactory(u32 _CRC, DSPHLE *dsp_hle, bool bWii)
|
||||
PanicAlert("DSPHLE: Unknown ucode (CRC = %08x) - forcing AX.\n\nTry LLE emulator if this is homebrew.", _CRC);
|
||||
return new CUCode_AX(dsp_hle, _CRC);
|
||||
}
|
||||
|
||||
case UCODE_NULL:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -25,8 +25,9 @@
|
||||
#include "../DSPHLE.h"
|
||||
#include "../../Memmap.h"
|
||||
|
||||
#define UCODE_ROM 0x0000000
|
||||
#define UCODE_INIT_AUDIO_SYSTEM 0x0000001
|
||||
#define UCODE_ROM 0x00000000
|
||||
#define UCODE_INIT_AUDIO_SYSTEM 0x00000001
|
||||
#define UCODE_NULL 0xFFFFFFFF
|
||||
|
||||
class CMailHandler;
|
||||
|
||||
@@ -73,10 +74,11 @@ inline void* HLEMemory_Get_Pointer(u32 _uAddress)
|
||||
class IUCode
|
||||
{
|
||||
public:
|
||||
IUCode(DSPHLE *dsphle)
|
||||
IUCode(DSPHLE *dsphle, u32 _crc)
|
||||
: m_rMailHandler(dsphle->AccessMailHandler())
|
||||
, m_UploadSetupInProgress(false)
|
||||
, m_DSPHLE(dsphle)
|
||||
, m_CRC(_crc)
|
||||
, m_NextUCode()
|
||||
, m_NextUCode_steps(0)
|
||||
, m_NeedsResumeMail(false)
|
||||
@@ -93,6 +95,8 @@ public:
|
||||
|
||||
virtual void DoState(PointerWrap &p) {}
|
||||
|
||||
static u32 GetCRC(IUCode* pUCode) { return pUCode ? pUCode->m_CRC : UCODE_NULL; }
|
||||
|
||||
protected:
|
||||
void PrepareBootUCode(u32 mail);
|
||||
|
||||
@@ -121,6 +125,10 @@ protected:
|
||||
// Need a pointer back to DSPHLE to switch ucodes.
|
||||
DSPHLE *m_DSPHLE;
|
||||
|
||||
// used for reconstruction when loading saves,
|
||||
// and for variations within certain ucodes.
|
||||
u32 m_CRC;
|
||||
|
||||
private:
|
||||
struct SUCode
|
||||
{
|
||||
|
||||
@@ -49,6 +49,9 @@ DSPLLE::DSPLLE() {
|
||||
m_cycle_count = 0;
|
||||
}
|
||||
|
||||
Common::Event dspEvent;
|
||||
Common::Event ppcEvent;
|
||||
|
||||
void DSPLLE::DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(g_dsp.r);
|
||||
@@ -96,7 +99,10 @@ void DSPLLE::dsp_thread(DSPLLE *dsp_lle)
|
||||
Common::AtomicStore(dsp_lle->m_cycle_count, 0);
|
||||
}
|
||||
else
|
||||
Common::YieldCPU();
|
||||
{
|
||||
ppcEvent.Set();
|
||||
dspEvent.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +144,8 @@ void DSPLLE::DSP_StopSoundStream()
|
||||
m_bIsRunning = false;
|
||||
if (m_bDSPThread)
|
||||
{
|
||||
ppcEvent.Set();
|
||||
dspEvent.Set();
|
||||
m_hDSPThread.join();
|
||||
}
|
||||
}
|
||||
@@ -274,9 +282,10 @@ void DSPLLE::DSP_Update(int cycles)
|
||||
else
|
||||
{
|
||||
// Wait for dsp thread to complete its cycle. Note: this logic should be thought through.
|
||||
while (m_cycle_count != 0)
|
||||
;
|
||||
ppcEvent.Wait();
|
||||
Common::AtomicStore(m_cycle_count, dsp_cycles);
|
||||
dspEvent.Set();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -522,7 +522,7 @@ void GenerateDIInterrupt(DI_InterruptType _DVDInterrupt)
|
||||
void ExecuteCommand(UDICR& _DICR)
|
||||
{
|
||||
// _dbg_assert_(DVDINTERFACE, _DICR.RW == 0); // only DVD to Memory
|
||||
int GCAM = ((SConfig::GetInstance().m_SIDevice[0] == SI_AM_BASEBOARD)
|
||||
int GCAM = ((SConfig::GetInstance().m_SIDevice[0] == SIDEVICE_AM_BASEBOARD)
|
||||
&& (SConfig::GetInstance().m_EXIDevice[2] == EXIDEVICE_AM_BASEBOARD))
|
||||
? 1 : 0;
|
||||
|
||||
|
||||
@@ -64,29 +64,31 @@ void Shutdown()
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
// TODO: Complete DoState for each IEXIDevice
|
||||
g_Channels[0]->GetDevice(1)->DoState(p);
|
||||
g_Channels[0]->GetDevice(2)->DoState(p);
|
||||
g_Channels[0]->GetDevice(4)->DoState(p);
|
||||
g_Channels[1]->GetDevice(1)->DoState(p);
|
||||
g_Channels[2]->GetDevice(1)->DoState(p);
|
||||
for (int c = 0; c < NUM_CHANNELS; ++c)
|
||||
g_Channels[c]->DoState(p);
|
||||
}
|
||||
|
||||
void OnAfterLoad()
|
||||
{
|
||||
for (int c = 0; c < NUM_CHANNELS; ++c)
|
||||
g_Channels[c]->OnAfterLoad();
|
||||
}
|
||||
|
||||
void ChangeDeviceCallback(u64 userdata, int cyclesLate)
|
||||
{
|
||||
u8 channel = (u8)(userdata >> 32);
|
||||
u8 device = (u8)(userdata >> 16);
|
||||
u8 slot = (u8)userdata;
|
||||
u8 type = (u8)(userdata >> 16);
|
||||
u8 num = (u8)userdata;
|
||||
|
||||
g_Channels[channel]->AddDevice((TEXIDevices)device, slot);
|
||||
g_Channels[channel]->AddDevice((TEXIDevices)type, num);
|
||||
}
|
||||
|
||||
void ChangeDevice(u8 channel, TEXIDevices device, u8 slot)
|
||||
void ChangeDevice(const u8 channel, const TEXIDevices device_type, const u8 device_num)
|
||||
{
|
||||
// Called from GUI, so we need to make it thread safe.
|
||||
// Let the hardware see no device for .5b cycles
|
||||
CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, ((u64)channel << 32) | ((u64)EXIDEVICE_NONE << 16) | slot);
|
||||
CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDevice, ((u64)channel << 32) | ((u64)device << 16) | slot);
|
||||
CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, ((u64)channel << 32) | ((u64)EXIDEVICE_NONE << 16) | device_num);
|
||||
CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDevice, ((u64)channel << 32) | ((u64)device_type << 16) | device_num);
|
||||
}
|
||||
|
||||
// Unused (?!)
|
||||
|
||||
@@ -28,12 +28,13 @@ namespace ExpansionInterface
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap &p);
|
||||
void OnAfterLoad();
|
||||
|
||||
void Update();
|
||||
void UpdateInterrupts();
|
||||
|
||||
void ChangeDeviceCallback(u64 userdata, int cyclesLate);
|
||||
void ChangeDevice(u8 channel, TEXIDevices device, u8 slot);
|
||||
void ChangeDevice(const u8 channel, const TEXIDevices device_type, const u8 device_num);
|
||||
|
||||
void Read32(u32& _uReturnValue, const u32 _iAddress);
|
||||
void Write32(const u32 _iValue, const u32 _iAddress);
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "EXI_Channel.h"
|
||||
#include "EXI_Device.h"
|
||||
#include "EXI.h"
|
||||
#include "../ConfigManager.h"
|
||||
#include "../Movie.h"
|
||||
|
||||
#define EXI_READ 0
|
||||
#define EXI_WRITE 1
|
||||
@@ -42,7 +44,7 @@ CEXIChannel::CEXIChannel(u32 ChannelId) :
|
||||
m_Status.CHIP_SELECT = 1;
|
||||
|
||||
for (int i = 0; i < NUM_DEVICES; i++)
|
||||
m_pDevices[i] = EXIDevice_Create(EXIDEVICE_NONE);
|
||||
m_pDevices[i] = EXIDevice_Create(EXIDEVICE_NONE, m_ChannelId);
|
||||
}
|
||||
|
||||
CEXIChannel::~CEXIChannel()
|
||||
@@ -59,26 +61,35 @@ void CEXIChannel::RemoveDevices()
|
||||
}
|
||||
}
|
||||
|
||||
void CEXIChannel::AddDevice(const TEXIDevices _device, const unsigned int _iSlot)
|
||||
void CEXIChannel::AddDevice(const TEXIDevices device_type, const int device_num)
|
||||
{
|
||||
_dbg_assert_(EXPANSIONINTERFACE, _iSlot < NUM_DEVICES);
|
||||
IEXIDevice* pNewDevice = EXIDevice_Create(device_type, m_ChannelId);
|
||||
AddDevice(pNewDevice, device_num);
|
||||
}
|
||||
|
||||
void CEXIChannel::AddDevice(IEXIDevice* pDevice, const int device_num, bool notifyPresenceChanged)
|
||||
{
|
||||
_dbg_assert_(EXPANSIONINTERFACE, device_num < NUM_DEVICES);
|
||||
|
||||
// delete the old device
|
||||
if (m_pDevices[_iSlot] != NULL)
|
||||
if (m_pDevices[device_num] != NULL)
|
||||
{
|
||||
delete m_pDevices[_iSlot];
|
||||
m_pDevices[_iSlot] = NULL;
|
||||
delete m_pDevices[device_num];
|
||||
m_pDevices[device_num] = NULL;
|
||||
}
|
||||
|
||||
// create the new one
|
||||
m_pDevices[_iSlot] = EXIDevice_Create(_device);
|
||||
// replace it with the new one
|
||||
m_pDevices[device_num] = pDevice;
|
||||
|
||||
// This means "device presence changed", software has to check
|
||||
// m_Status.EXT to see if it is now present or not
|
||||
if (m_ChannelId != 2)
|
||||
if(notifyPresenceChanged)
|
||||
{
|
||||
m_Status.EXTINT = 1;
|
||||
UpdateInterrupts();
|
||||
// This means "device presence changed", software has to check
|
||||
// m_Status.EXT to see if it is now present or not
|
||||
if (m_ChannelId != 2)
|
||||
{
|
||||
m_Status.EXTINT = 1;
|
||||
UpdateInterrupts();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,9 +118,9 @@ bool CEXIChannel::IsCausingInterrupt()
|
||||
}
|
||||
}
|
||||
|
||||
IEXIDevice* CEXIChannel::GetDevice(u8 _CHIP_SELECT)
|
||||
IEXIDevice* CEXIChannel::GetDevice(const u8 chip_select)
|
||||
{
|
||||
switch(_CHIP_SELECT)
|
||||
switch (chip_select)
|
||||
{
|
||||
case 1: return m_pDevices[0];
|
||||
case 2: return m_pDevices[1];
|
||||
@@ -264,3 +275,43 @@ void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CEXIChannel::DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(m_Status);
|
||||
p.Do(m_DMAMemoryAddress);
|
||||
p.Do(m_DMALength);
|
||||
p.Do(m_Control);
|
||||
p.Do(m_ImmData);
|
||||
|
||||
for (int d = 0; d < NUM_DEVICES; ++d)
|
||||
{
|
||||
IEXIDevice* pDevice = m_pDevices[d];
|
||||
TEXIDevices type = pDevice->m_deviceType;
|
||||
p.Do(type);
|
||||
IEXIDevice* pSaveDevice = (type == pDevice->m_deviceType) ? pDevice : EXIDevice_Create(type, m_ChannelId);
|
||||
pSaveDevice->DoState(p);
|
||||
if(pSaveDevice != pDevice)
|
||||
{
|
||||
// if we had to create a temporary device, discard it if we're not loading.
|
||||
// also, if no movie is active, we'll assume the user wants to keep their current devices
|
||||
// instead of the ones they had when the savestate was created,
|
||||
// unless the device is NONE (since ChangeDevice sets that temporarily).
|
||||
if(p.GetMode() != PointerWrap::MODE_READ)
|
||||
{
|
||||
delete pSaveDevice;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddDevice(pSaveDevice, d, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEXIChannel::OnAfterLoad()
|
||||
{
|
||||
for (int d = 0; d < NUM_DEVICES; ++d)
|
||||
m_pDevices[d]->OnAfterLoad();
|
||||
}
|
||||
|
||||
|
||||
@@ -112,12 +112,13 @@ private:
|
||||
|
||||
public:
|
||||
// get device
|
||||
IEXIDevice* GetDevice(u8 _CHIP_SELECT);
|
||||
IEXIDevice* GetDevice(const u8 _CHIP_SELECT);
|
||||
|
||||
CEXIChannel(u32 ChannelId);
|
||||
~CEXIChannel();
|
||||
|
||||
void AddDevice(const TEXIDevices _device, const unsigned int _iSlot);
|
||||
void AddDevice(const TEXIDevices device_type, const int device_num);
|
||||
void AddDevice(IEXIDevice* pDevice, const int device_num, bool notifyPresenceChanged=true);
|
||||
|
||||
// Remove all devices
|
||||
void RemoveDevices();
|
||||
@@ -128,6 +129,8 @@ public:
|
||||
void Update();
|
||||
bool IsCausingInterrupt();
|
||||
void UpdateInterrupts();
|
||||
void DoState(PointerWrap &p);
|
||||
void OnAfterLoad();
|
||||
|
||||
// This should only be used to transition interrupts from SP1 to Channel 2
|
||||
void SetEXIINT(bool exiint) { m_Status.EXIINT = !!exiint; }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user