Merge branch 'master' into wii-network

Conflicts:
	Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp
	Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp
	Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp
	Source/VSProps/Dolphin.Win32.props
	Source/VSProps/Dolphin.x64.props
This commit is contained in:
Pierre Bourdon
2012-05-16 09:27:37 +02:00
2925 changed files with 69775 additions and 594118 deletions

View File

@@ -210,7 +210,6 @@
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="Src\SConscript" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\Common.vcxproj">

View File

@@ -46,7 +46,6 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Src\SConscript" />
<None Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,29 +0,0 @@
# -*- python -*-
Import('env')
import sys
files = [
'Src/AudioCommon.cpp',
'Src/AudioCommonConfig.cpp',
'Src/Mixer.cpp',
'Src/NullSoundStream.cpp',
'Src/WaveFile.cpp',
]
if sys.platform == 'darwin':
files += ['Src/CoreAudioSoundStream.cpp']
elif sys.platform == 'win32':
files += ['Src/DSoundStream.cpp']
files += ['Src/XAudio2Stream.cpp']
else:
if env['HAVE_ALSA']:
files += ['Src/AlsaSoundStream.cpp']
if env['HAVE_AO']:
files += ['Src/AOSoundStream.cpp']
if env['HAVE_OPENAL']:
files += ['Src/OpenALStream.cpp', 'Src/aldlist.cpp']
if env['HAVE_PULSEAUDIO']:
files += ['Src/PulseAudioStream.cpp']
env['LIBS'] += env.StaticLibrary('audiocommon', files)

View File

@@ -31,7 +31,6 @@ void AudioCommonConfig::Load()
IniFile file;
file.Load(File::GetUserPath(F_DSPCONFIG_IDX));
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
file.Get("Config", "EnableJIT", &m_EnableJIT, true);
file.Get("Config", "DumpAudio", &m_DumpAudio, false);
#if defined __linux__ && HAVE_ALSA
@@ -53,7 +52,6 @@ void AudioCommonConfig::SaveSettings()
IniFile file;
file.Load(File::GetUserPath(F_DSPCONFIG_IDX));
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
file.Set("Config", "EnableJIT", m_EnableJIT);
file.Set("Config", "DumpAudio", m_DumpAudio);
file.Set("Config", "Backend", sBackend);
@@ -67,7 +65,6 @@ void AudioCommonConfig::SaveSettings()
void AudioCommonConfig::Update() {
if (soundStream) {
soundStream->GetMixer()->SetThrottle(SConfig::GetInstance().m_Framelimit == 2);
soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
soundStream->SetVolume(m_Volume);
}
}

View File

@@ -33,7 +33,6 @@
struct AudioCommonConfig
{
bool m_EnableDTKMusic;
bool m_EnableJIT;
bool m_DumpAudio;
int m_Volume;

View File

@@ -136,8 +136,7 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
if (m_AIplaying) {
Premix(samples, numLeft);
if (m_EnableDTKMusic)
AudioInterface::Callback_GetStreaming(samples, numLeft, m_sampleRate);
AudioInterface::Callback_GetStreaming(samples, numLeft, m_sampleRate);
g_wave_writer.AddStereoSamples(samples, numLeft);
}
@@ -147,11 +146,8 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples)
Premix(samples, numSamples);
// Add the DTK Music
if (m_EnableDTKMusic)
{
// Re-sampling is done inside
AudioInterface::Callback_GetStreaming(samples, numSamples, m_sampleRate);
}
// Re-sampling is done inside
AudioInterface::Callback_GetStreaming(samples, numSamples, m_sampleRate);
}

View File

@@ -61,7 +61,6 @@ public:
unsigned int GetSampleRate() {return m_sampleRate;}
void SetThrottle(bool use) { m_throttle = use;}
void SetDTKMusic(bool use) { m_EnableDTKMusic = use;}
// TODO: do we need this
bool IsHLEReady() { return m_HLEready;}
@@ -103,7 +102,6 @@ protected:
bool m_HLEready;
bool m_logAudio;
bool m_EnableDTKMusic;
bool m_throttle;
short m_buffer[MAX_SAMPLES * 2];

View File

@@ -108,27 +108,21 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>.\Src;..\..\..\Externals/CLRun/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile />
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>.\Src;..\..\..\Externals/CLRun/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile />
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>.\Src;..\..\..\Externals/CLRun/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile />
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -137,9 +131,7 @@
<Lib />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>.\Src;..\..\..\Externals/CLRun/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile />
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -148,9 +140,7 @@
<Lib />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>.\Src;..\..\..\Externals/CLRun/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile />
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -159,9 +149,7 @@
<Lib />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
<ClCompile>
<AdditionalIncludeDirectories>.\Src;..\..\..\Externals/CLRun/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile />
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -270,7 +258,6 @@
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="Src\SConscript" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@@ -126,7 +126,6 @@
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="Src\SConscript" />
</ItemGroup>
<ItemGroup>
<Filter Include="Crypto">

View File

@@ -1,60 +0,0 @@
# -*- python -*-
Import('env')
import os
import sys
out_contents =\
'#define SCM_REV_STR "' + env['gitrev'] + '"\n' +\
'#define SCM_DESC_STR "' + env['gitdesc'] + '"\n' +\
'#define SCM_BRANCH_STR "' + env['gitbranch'] + '"\n' +\
'#define SCM_IS_MASTER ' + ('1' if env['gitbranch'] == 'master' else '0') + '\n\n'
Execute(Delete('Src/scmrev.h'))
outfile = open('Src/scmrev.h', 'w')
outfile.write(out_contents)
outfile.close()
files = [
'Src/ABI.cpp',
'Src/BreakPoints.cpp',
'Src/CDUtils.cpp',
'Src/CPUDetect.cpp',
'Src/ColorUtil.cpp',
'Src/ConsoleListener.cpp',
'Src/Crypto/aes_cbc.cpp',
'Src/Crypto/aes_core.cpp',
'Src/Crypto/bn.cpp',
'Src/Crypto/ec.cpp',
'Src/Crypto/md5.cpp',
'Src/Crypto/sha1.cpp',
'Src/FileSearch.cpp',
'Src/FileUtil.cpp',
'Src/Hash.cpp',
'Src/IniFile.cpp',
'Src/LogManager.cpp',
'Src/MathUtil.cpp',
'Src/MemArena.cpp',
'Src/MemoryUtil.cpp',
'Src/Misc.cpp',
'Src/MsgHandler.cpp',
'Src/NandPaths.cpp',
'Src/SDCardUtil.cpp',
'Src/StringUtil.cpp',
'Src/SymbolDB.cpp',
'Src/SysConf.cpp',
'Src/Thread.cpp',
'Src/Thunk.cpp',
'Src/Timer.cpp',
'Src/Version.cpp',
'Src/VideoBackendBase.cpp',
'Src/x64Analyzer.cpp',
'Src/x64Emitter.cpp',
]
if sys.platform == 'win32':
files += ['Src/ExtendedTrace.cpp']
files += ['Src/stdafx.cpp']
env['CPPPATH'] += ['Src']
env['LIBS'] += env.StaticLibrary('common', files)

View File

@@ -7,13 +7,11 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="make_scmrev.h.js">
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cscript /nologo /E:JScript "make_scmrev.h.js"</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Updating scmrev.h</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">dummy</Outputs>
</CustomBuild>
<None Include="make_scmrev.h.js">
</None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="force_rebuild.h" />
<ClInclude Include="Src\scmrev.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
@@ -37,25 +35,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PreBuildEvent>
<Command>
</Command>
<Command>cscript /nologo /E:JScript "make_scmrev.h.js"</Command>
</PreBuildEvent>
<CustomBuild>
<Outputs>
</Outputs>
</CustomBuild>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

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

View File

@@ -78,7 +78,7 @@ public:
// Remove Breakpoint
void Remove(u32 _iAddress);
void Clear() { m_BreakPoints.clear(); };
void Clear();
void DeleteByAddress(u32 _Address);

View File

@@ -103,8 +103,6 @@ private:
//CrtDebugBreak breakAt(614);
#endif // end DEBUG/FAST
#elif defined HAVE_CONFIG_H
#include "config.h" // SCons autoconfiguration defines
#endif
// Windows compatibility

View File

@@ -21,6 +21,7 @@
#ifdef _WIN32
#define SLEEP(x) Sleep(x)
#else
#include <unistd.h>
#define SLEEP(x) usleep(x*1000)
#endif

View File

@@ -121,6 +121,8 @@
#define GC_MEMCARDA "MemoryCardA"
#define GC_MEMCARDB "MemoryCardB"
#define WII_STATE "state.dat"
#define WII_SETTING "setting.txt"
#define GECKO_CODE_HANDLER "codehandler.bin"

View File

@@ -24,7 +24,7 @@
// Increment this every time you change shader generation code.
enum
{
LINEAR_DISKCACHE_VER = 6972
LINEAR_DISKCACHE_VER = 6975
};
// On disk format:

View File

@@ -161,6 +161,7 @@ void LoadDefaultSSEState();
float MathFloatVectorSum(const std::vector<float>&);
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
// Tiny matrix/vector library.

View File

@@ -1,207 +1,207 @@
// 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 "Common.h"
#include "MemoryUtil.h"
#include "StringUtil.h"
#ifdef _WIN32
#include <windows.h>
#include <psapi.h>
#else
#include <errno.h>
#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)
{
// 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 "Common.h"
#include "MemoryUtil.h"
#include "StringUtil.h"
#ifdef _WIN32
#include <windows.h>
#include <psapi.h>
#else
#include <errno.h>
#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)
{
#if defined(_WIN32)
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else
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(__x86_64__) && defined(MAP_32BIT)
| (low ? MAP_32BIT : 0)
#endif
, -1, 0);
#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");
}
#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
return ptr;
}
void* AllocateMemoryPages(size_t size)
{
#ifdef _WIN32
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
#else
void* ptr = mmap(0, size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
#endif
// printf("Mapped memory at %p (size %ld)\n", ptr,
// (unsigned long)size);
if (ptr == NULL)
PanicAlert("Failed to allocate raw memory");
return ptr;
}
void* AllocateAlignedMemory(size_t size,size_t alignment)
{
#ifdef _WIN32
void* ptr = _aligned_malloc(size,alignment);
#else
void* ptr = NULL;
posix_memalign(&ptr, alignment, size);
;
#endif
// printf("Mapped memory at %p (size %ld)\n", ptr,
// (unsigned long)size);
if (ptr == NULL)
PanicAlert("Failed to allocate aligned memory");
return ptr;
}
void FreeMemoryPages(void* ptr, size_t size)
{
if (ptr)
{
#ifdef _WIN32
if (!VirtualFree(ptr, 0, MEM_RELEASE))
PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg());
ptr = NULL; // Is this our responsibility?
#else
munmap(ptr, size);
#endif
}
}
void FreeAlignedMemory(void* ptr)
{
if (ptr)
{
#ifdef _WIN32
_aligned_free(ptr);
#else
free(ptr);
#endif
}
}
void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{
#ifdef _WIN32
DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue))
PanicAlert("WriteProtectMemory failed!\n%s", GetLastErrorMsg());
#else
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ);
#endif
}
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{
#ifdef _WIN32
DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue))
PanicAlert("UnWriteProtectMemory failed!\n%s", GetLastErrorMsg());
#else
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ);
#endif
}
std::string MemUsage()
{
#ifdef _WIN32
#pragma comment(lib, "psapi")
DWORD processID = GetCurrentProcessId();
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
std::string Ret;
// Print information about the memory usage of the process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
if (NULL == hProcess) return "MemUsage Error";
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
CloseHandle(hProcess);
return Ret;
#else
return "";
#endif
}
#else
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(__x86_64__) && defined(MAP_32BIT)
| (low ? MAP_32BIT : 0)
#endif
, -1, 0);
#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");
}
#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
return ptr;
}
void* AllocateMemoryPages(size_t size)
{
#ifdef _WIN32
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
#else
void* ptr = mmap(0, size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
#endif
// printf("Mapped memory at %p (size %ld)\n", ptr,
// (unsigned long)size);
if (ptr == NULL)
PanicAlert("Failed to allocate raw memory");
return ptr;
}
void* AllocateAlignedMemory(size_t size,size_t alignment)
{
#ifdef _WIN32
void* ptr = _aligned_malloc(size,alignment);
#else
void* ptr = NULL;
posix_memalign(&ptr, alignment, size);
;
#endif
// printf("Mapped memory at %p (size %ld)\n", ptr,
// (unsigned long)size);
if (ptr == NULL)
PanicAlert("Failed to allocate aligned memory");
return ptr;
}
void FreeMemoryPages(void* ptr, size_t size)
{
if (ptr)
{
#ifdef _WIN32
if (!VirtualFree(ptr, 0, MEM_RELEASE))
PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg());
ptr = NULL; // Is this our responsibility?
#else
munmap(ptr, size);
#endif
}
}
void FreeAlignedMemory(void* ptr)
{
if (ptr)
{
#ifdef _WIN32
_aligned_free(ptr);
#else
free(ptr);
#endif
}
}
void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{
#ifdef _WIN32
DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue))
PanicAlert("WriteProtectMemory failed!\n%s", GetLastErrorMsg());
#else
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ);
#endif
}
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{
#ifdef _WIN32
DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue))
PanicAlert("UnWriteProtectMemory failed!\n%s", GetLastErrorMsg());
#else
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ);
#endif
}
std::string MemUsage()
{
#ifdef _WIN32
#pragma comment(lib, "psapi")
DWORD processID = GetCurrentProcessId();
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
std::string Ret;
// Print information about the memory usage of the process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
if (NULL == hProcess) return "MemUsage Error";
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
CloseHandle(hProcess);
return Ret;
#else
return "";
#endif
}

View File

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

View File

@@ -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;
@@ -159,6 +160,7 @@ class VideoBackendHardware : public VideoBackend
void Video_GatherPipeBursted();
bool Video_IsPossibleWaitingSetDrawDone();
bool Video_IsHiWatermarkActive();
void Video_AbortFrame();
readFn16 Video_CPRead16();

View File

@@ -576,7 +576,6 @@
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="Src\HW\DSPHLE\UCodes\UCode_Zelda_Obsolete.txt" />
<None Include="Src\SConscript" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Externals\Bochs_disasm\Bochs_disasm.vcxproj">

View File

@@ -1051,7 +1051,6 @@
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="Src\SConscript" />
<None Include="Src\HW\DSPHLE\UCodes\UCode_Zelda_Obsolete.txt">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE\uCodes</Filter>
</None>

View File

@@ -1,215 +0,0 @@
# -*- python -*-
Import('env')
import sys
files = [
'Src/ARDecrypt.cpp',
'Src/ActionReplay.cpp',
'Src/Boot/Boot.cpp',
'Src/Boot/Boot_BS2Emu.cpp',
'Src/Boot/Boot_DOL.cpp',
'Src/Boot/Boot_ELF.cpp',
'Src/Boot/Boot_WiiWAD.cpp',
'Src/Boot/ElfReader.cpp',
'Src/BootManager.cpp',
'Src/ConfigManager.cpp',
'Src/Console.cpp',
'Src/Core.cpp',
'Src/CoreParameter.cpp',
'Src/CoreRerecording.cpp',
'Src/CoreTiming.cpp',
'Src/DSP/DSPAccelerator.cpp',
'Src/DSP/DSPAnalyzer.cpp',
'Src/DSP/DSPCodeUtil.cpp',
'Src/DSP/DSPCore.cpp',
'Src/DSP/DSPEmitter.cpp',
'Src/DSP/DSPHWInterface.cpp',
'Src/DSP/DSPIntCCUtil.cpp',
'Src/DSP/DSPIntExtOps.cpp',
'Src/DSP/DSPInterpreter.cpp',
'Src/DSP/DSPMemoryMap.cpp',
'Src/DSP/DSPStacks.cpp',
'Src/DSP/DSPTables.cpp',
'Src/DSP/DspIntArithmetic.cpp',
'Src/DSP/DspIntBranch.cpp',
'Src/DSP/DspIntLoadStore.cpp',
'Src/DSP/DspIntMisc.cpp',
'Src/DSP/DspIntMultiplier.cpp',
'Src/DSP/Jit/DSPJitArithmetic.cpp',
'Src/DSP/Jit/DSPJitBranch.cpp',
'Src/DSP/Jit/DSPJitCCUtil.cpp',
'Src/DSP/Jit/DSPJitExtOps.cpp',
'Src/DSP/Jit/DSPJitLoadStore.cpp',
'Src/DSP/Jit/DSPJitMisc.cpp',
'Src/DSP/Jit/DSPJitMultiplier.cpp',
'Src/DSP/Jit/DSPJitRegCache.cpp',
'Src/DSP/Jit/DSPJitUtil.cpp',
'Src/DSP/LabelMap.cpp',
'Src/DSP/assemble.cpp',
'Src/DSP/disassemble.cpp',
'Src/DSPEmulator.cpp',
'Src/Debugger/Debugger_SymbolMap.cpp',
'Src/Debugger/Dump.cpp',
'Src/Debugger/PPCDebugInterface.cpp',
'Src/FifoPlayer/FifoAnalyzer.cpp',
'Src/FifoPlayer/FifoDataFile.cpp',
'Src/FifoPlayer/FifoPlaybackAnalyzer.cpp',
'Src/FifoPlayer/FifoPlayer.cpp',
'Src/FifoPlayer/FifoRecordAnalyzer.cpp',
'Src/FifoPlayer/FifoRecorder.cpp',
'Src/GeckoCode.cpp',
'Src/GeckoCodeConfig.cpp',
'Src/HLE/HLE.cpp',
'Src/HLE/HLE_Misc.cpp',
'Src/HLE/HLE_OS.cpp',
'Src/HW/AudioInterface.cpp',
'Src/HW/CPU.cpp',
'Src/HW/DSP.cpp',
'Src/HW/DSPHLE/DSPHLE.cpp',
'Src/HW/DSPHLE/HLEMixer.cpp',
'Src/HW/DSPHLE/MailHandler.cpp',
'Src/HW/DSPHLE/UCodes/UCode_AX.cpp',
'Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp',
'Src/HW/DSPHLE/UCodes/UCode_CARD.cpp',
'Src/HW/DSPHLE/UCodes/UCode_GBA.cpp',
'Src/HW/DSPHLE/UCodes/UCode_InitAudioSystem.cpp',
'Src/HW/DSPHLE/UCodes/UCode_ROM.cpp',
'Src/HW/DSPHLE/UCodes/UCode_Zelda.cpp',
'Src/HW/DSPHLE/UCodes/UCode_Zelda_ADPCM.cpp',
'Src/HW/DSPHLE/UCodes/UCode_Zelda_Synth.cpp',
'Src/HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp',
'Src/HW/DSPHLE/UCodes/UCodes.cpp',
'Src/HW/DSPLLE/DSPDebugInterface.cpp',
'Src/HW/DSPLLE/DSPHost.cpp',
'Src/HW/DSPLLE/DSPLLE.cpp',
#'Src/HW/DSPLLE/DSPLLEGlobals.cpp',
'Src/HW/DSPLLE/DSPLLETools.cpp',
'Src/HW/DSPLLE/DSPSymbols.cpp',
'Src/HW/DVDInterface.cpp',
'Src/HW/EXI.cpp',
'Src/HW/EXI_Channel.cpp',
'Src/HW/EXI_Device.cpp',
'Src/HW/EXI_DeviceAD16.cpp',
'Src/HW/EXI_DeviceAMBaseboard.cpp',
'Src/HW/EXI_DeviceEthernet.cpp',
'Src/HW/EXI_DeviceGecko.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',
'Src/HW/HW.cpp',
'Src/HW/Memmap.cpp',
'Src/HW/MemmapFunctions.cpp',
'Src/HW/MemoryInterface.cpp',
'Src/HW/ProcessorInterface.cpp',
'Src/HW/SI.cpp',
'Src/HW/SI_Device.cpp',
'Src/HW/SI_DeviceAMBaseboard.cpp',
'Src/HW/SI_DeviceGBA.cpp',
'Src/HW/SI_DeviceGCController.cpp',
'Src/HW/Sram.cpp',
'Src/HW/StreamADPCM.cpp',
'Src/HW/SystemTimers.cpp',
'Src/HW/VideoInterface.cpp',
'Src/HW/WII_IOB.cpp',
'Src/HW/WII_IPC.cpp',
'Src/HW/Wiimote.cpp',
'Src/HW/WiimoteEmu/Attachment/Attachment.cpp',
'Src/HW/WiimoteEmu/Attachment/Classic.cpp',
'Src/HW/WiimoteEmu/Attachment/Drums.cpp',
'Src/HW/WiimoteEmu/Attachment/Guitar.cpp',
'Src/HW/WiimoteEmu/Attachment/Nunchuk.cpp',
'Src/HW/WiimoteEmu/Attachment/Turntable.cpp',
'Src/HW/WiimoteEmu/EmuSubroutines.cpp',
'Src/HW/WiimoteEmu/Encryption.cpp',
'Src/HW/WiimoteEmu/Speaker.cpp',
'Src/HW/WiimoteEmu/WiimoteEmu.cpp',
'Src/HW/WiimoteReal/WiimoteReal.cpp',
'Src/IPC_HLE/WII_IPC_HLE.cpp',
'Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp',
'Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp',
'Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp',
'Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp',
'Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp',
'Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp',
'Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp',
'Src/IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp',
'Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp',
'Src/IPC_HLE/WiiMote_HID_Attr.cpp',
'Src/MemTools.cpp',
'Src/Movie.cpp',
'Src/NetPlay.cpp',
'Src/NetPlayClient.cpp',
'Src/NetPlayServer.cpp',
'Src/PatchEngine.cpp',
'Src/PowerPC/Interpreter/Interpreter.cpp',
'Src/PowerPC/Interpreter/Interpreter_Branch.cpp',
'Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp',
'Src/PowerPC/Interpreter/Interpreter_Integer.cpp',
'Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp',
'Src/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp',
'Src/PowerPC/Interpreter/Interpreter_Paired.cpp',
'Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp',
'Src/PowerPC/Interpreter/Interpreter_Tables.cpp',
'Src/PowerPC/Jit64/Jit.cpp',
'Src/PowerPC/Jit64/Jit64_Tables.cpp',
'Src/PowerPC/Jit64/JitAsm.cpp',
'Src/PowerPC/Jit64/JitRegCache.cpp',
'Src/PowerPC/Jit64/Jit_Branch.cpp',
'Src/PowerPC/Jit64/Jit_FloatingPoint.cpp',
'Src/PowerPC/Jit64/Jit_Integer.cpp',
'Src/PowerPC/Jit64/Jit_LoadStore.cpp',
'Src/PowerPC/Jit64/Jit_LoadStoreFloating.cpp',
'Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp',
'Src/PowerPC/Jit64/Jit_Paired.cpp',
'Src/PowerPC/Jit64/Jit_SystemRegisters.cpp',
'Src/PowerPC/Jit64IL/IR.cpp',
'Src/PowerPC/Jit64IL/IR_X86.cpp',
'Src/PowerPC/Jit64IL/JitIL.cpp',
'Src/PowerPC/Jit64IL/JitILAsm.cpp',
'Src/PowerPC/Jit64IL/JitIL_Branch.cpp',
'Src/PowerPC/Jit64IL/JitIL_FloatingPoint.cpp',
'Src/PowerPC/Jit64IL/JitIL_Integer.cpp',
'Src/PowerPC/Jit64IL/JitIL_LoadStore.cpp',
'Src/PowerPC/Jit64IL/JitIL_LoadStoreFloating.cpp',
'Src/PowerPC/Jit64IL/JitIL_LoadStorePaired.cpp',
'Src/PowerPC/Jit64IL/JitIL_Paired.cpp',
'Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp',
'Src/PowerPC/Jit64IL/JitIL_Tables.cpp',
'Src/PowerPC/JitCommon/JitAsmCommon.cpp',
'Src/PowerPC/JitCommon/JitBackpatch.cpp',
'Src/PowerPC/JitCommon/JitBase.cpp',
'Src/PowerPC/JitCommon/JitCache.cpp',
'Src/PowerPC/JitCommon/Jit_Util.cpp',
'Src/PowerPC/LUT_frsqrtex.cpp',
'Src/PowerPC/PPCAnalyst.cpp',
'Src/PowerPC/PPCCache.cpp',
'Src/PowerPC/PPCSymbolDB.cpp',
'Src/PowerPC/PPCTables.cpp',
'Src/PowerPC/PowerPC.cpp',
'Src/PowerPC/Profiler.cpp',
'Src/PowerPC/SignatureDB.cpp',
'Src/State.cpp',
'Src/Tracer.cpp',
'Src/VolumeHandler.cpp',
]
if sys.platform == 'win32':
files += ['Src/HW/BBA-TAP/TAP_Win32.cpp']
files += ['Src/HW/WiimoteReal/IOWin.cpp']
files += ['Src/stdafx.cpp']
elif sys.platform == 'darwin':
files += ['Src/HW/BBA-TAP/TAP_Apple.cpp']
files += ['Src/HW/WiimoteReal/IOdarwin.mm']
elif sys.platform == 'linux2' and env['HAVE_BLUEZ']:
files += ['Src/HW/BBA-TAP/TAP_Unix.cpp']
files += ['Src/HW/WiimoteReal/IODummy.cpp']
else:
files += ['Src/HW/BBA-TAP/TAP_Unix.cpp']
files += ['Src/HW/WiimoteReal/IODummy.cpp']
env['LIBS'] += env.StaticLibrary('core', files)

View File

@@ -19,6 +19,7 @@
#include "Common.h" // Common
#include "StringUtil.h"
#include "FileUtil.h"
#include "MathUtil.h"
#include "../HLE/HLE.h" // Core
#include "../PowerPC/PowerPC.h"
@@ -68,13 +69,13 @@ void CBoot::Load_FST(bool _bIsWii)
u32 fstSize = VolumeHandler::Read32(0x0428) << shift;
u32 maxFstSize = VolumeHandler::Read32(0x042c) << shift;
u32 arenaHigh = 0x817FFFF4 - maxFstSize;
u32 arenaHigh = ROUND_DOWN(0x817FFFFF - maxFstSize, 0x20);
Memory::Write_U32(arenaHigh, 0x00000034);
// load FST
VolumeHandler::ReadToPtr(Memory::GetPointer(arenaHigh), fstOffset, fstSize);
Memory::Write_U32(arenaHigh, 0x00000038);
Memory::Write_U32(maxFstSize, 0x0000003c);
Memory::Write_U32(maxFstSize, 0x0000003c);
}
void CBoot::UpdateDebugger_MapLoaded(const char *_gameID)
@@ -227,7 +228,9 @@ bool CBoot::BootUp()
// setup the map from ISOFile ID
VolumeHandler::SetVolumeName(_StartupPara.m_strFilename);
VideoInterface::SetRegionReg((char)VolumeHandler::GetVolume()->GetUniqueID().at(3));
std::string unique_id = VolumeHandler::GetVolume()->GetUniqueID();
if (unique_id.size() >= 4)
VideoInterface::SetRegionReg(unique_id.at(3));
DVDInterface::SetDiscInside(VolumeHandler::IsValid());

View File

@@ -297,6 +297,7 @@ bool CBoot::SetupWiiMemory(unsigned int _CountryCode)
Memory::Write_U32(0x00000000, 0x000030c4); // EXI
Memory::Write_U32(0x00000000, 0x000030dc); // Time
Memory::Write_U32(0x00000000, 0x000030d8); // Time
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
Memory::Write_U32(0x01800000, 0x00003100); // BAT
Memory::Write_U32(0x01800000, 0x00003104); // BAT
@@ -309,7 +310,7 @@ bool CBoot::SetupWiiMemory(unsigned int _CountryCode)
Memory::Write_U32(0x93ae0000, 0x00003128); // Init - MEM2 high
Memory::Write_U32(0x93ae0000, 0x00003130); // IOS MEM2 low
Memory::Write_U32(0x93b00000, 0x00003134); // IOS MEM2 high
Memory::Write_U32(0x00000011, 0x00003138); // Console type
Memory::Write_U32(0x00000012, 0x00003138); // Console type
// 40 is copied from 88 after running apploader
Memory::Write_U32(0x00090204, 0x00003140); // IOS revision (IOS9, v2.4)
Memory::Write_U32(0x00062507, 0x00003144); // IOS date in USA format (June 25, 2007)

View File

@@ -34,12 +34,35 @@ bool CBoot::IsElfWii(const char *filename)
File::IOFile f(filename, "rb");
f.ReadBytes(mem, (size_t)filesize);
}
ElfReader reader(mem);
// TODO: Find a more reliable way to distinguish.
bool isWii = reader.GetEntryPoint() >= 0x80004000;
delete[] mem;
// Use the same method as the DOL loader uses: search for mfspr from HID4,
// which should only be used in Wii ELFs.
//
// Likely to have some false positives/negatives, patches implementing a
// better heuristic are welcome.
u32 HID4_pattern = 0x7c13fba6;
u32 HID4_mask = 0xfc1fffff;
ElfReader reader(mem);
bool isWii = false;
for (int i = 0; i < reader.GetNumSections(); ++i)
{
if (reader.IsCodeSection(i))
{
for (unsigned int j = 0; j < reader.GetSectionSize(i) / sizeof (u32); ++j)
{
u32 word = Common::swap32(((u32*)reader.GetSectionDataPtr(i))[j]);
if ((word & HID4_mask) == HID4_pattern)
{
isWii = true;
break;
}
}
}
}
delete[] mem;
return isWii;
}

View File

@@ -32,8 +32,57 @@
#include "VolumeCreator.h"
#include "CommonPaths.h"
static u32 state_checksum(u32 *buf, int len)
{
u32 checksum = 0;
len = len>>2;
for(int i=0; i<len; i++)
{
checksum += buf[i];
}
return checksum;
}
typedef struct {
u32 checksum;
u8 flags;
u8 type;
u8 discstate;
u8 returnto;
u32 unknown[6];
} StateFlags;
bool CBoot::Boot_WiiWAD(const char* _pFilename)
{
std::string state_filename(Common::GetTitleDataPath(TITLEID_SYSMENU) + WII_STATE);
if (File::Exists(state_filename))
{
File::IOFile state_file(state_filename, "r+b");
StateFlags state;
state_file.ReadBytes(&state, sizeof(StateFlags));
state.type = 0x03; // TYPE_RETURN
state.checksum = state_checksum((u32*)&state.flags, sizeof(StateFlags)-4);
state_file.Seek(0, SEEK_SET);
state_file.WriteBytes(&state, sizeof(StateFlags));
}
else
{
File::CreateFullPath(state_filename);
File::IOFile state_file(state_filename, "a+b");
StateFlags state;
memset(&state,0,sizeof(StateFlags));
state.type = 0x03; // TYPE_RETURN
state.discstate = 0x01; // DISCSTATE_WII
state.checksum = state_checksum((u32*)&state.flags, sizeof(StateFlags)-4);
state_file.WriteBytes(&state, sizeof(StateFlags));
}
const DiscIO::INANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(_pFilename);
if (!ContentLoader.IsValid())
return false;

View File

@@ -59,7 +59,6 @@ public:
bool LoadInto(u32 vaddr);
bool LoadSymbols();
private:
int GetNumSegments() const { return (int)(header->e_phnum); }
int GetNumSections() const { return (int)(header->e_shnum); }
const u8 *GetPtr(int offset) const { return (u8*)base + offset; }
@@ -73,6 +72,10 @@ private:
else
return 0;
}
bool IsCodeSection(int section) const
{
return sections[section].sh_type == SHT_PROGBITS;
}
const u8 *GetSegmentPtr(int segment)
{
return GetPtr(segments[segment].p_offset);

View File

@@ -74,9 +74,6 @@ bool BootCore(const std::string& _rFilename)
StartUp.bRunCompareServer = false;
StartUp.hInstance = Host_GetInstance();
#if defined(_WIN32) && defined(_M_X64)
StartUp.bUseFastMem = true;
#endif
// If for example the ISO file is bad we return here
if (!StartUp.AutoSetup(SCoreStartupParameter::BOOT_DEFAULT)) return false;

View File

@@ -190,6 +190,7 @@ void SConfig::SaveSettings()
ini.Set("Display", "RenderWindowWidth", m_LocalCoreStartupParameter.iRenderWindowWidth);
ini.Set("Display", "RenderWindowHeight", m_LocalCoreStartupParameter.iRenderWindowHeight);
ini.Set("Display", "RenderWindowAutoSize", m_LocalCoreStartupParameter.bRenderWindowAutoSize);
ini.Set("Display", "KeepWindowOnTop", m_LocalCoreStartupParameter.bKeepWindowOnTop);
ini.Set("Display", "ProgressiveScan", m_LocalCoreStartupParameter.bProgressive);
ini.Set("Display", "DisableScreenSaver", m_LocalCoreStartupParameter.bDisableScreenSaver);
ini.Set("Display", "ForceNTSCJ", m_LocalCoreStartupParameter.bForceNTSCJ);
@@ -319,6 +320,7 @@ void SConfig::LoadSettings()
ini.Get("Display", "RenderWindowWidth", &m_LocalCoreStartupParameter.iRenderWindowWidth, 640);
ini.Get("Display", "RenderWindowHeight", &m_LocalCoreStartupParameter.iRenderWindowHeight, 480);
ini.Get("Display", "RenderWindowAutoSize", &m_LocalCoreStartupParameter.bRenderWindowAutoSize, false);
ini.Get("Display", "KeepWindowOnTop", &m_LocalCoreStartupParameter.bKeepWindowOnTop, false);
ini.Get("Display", "ProgressiveScan", &m_LocalCoreStartupParameter.bProgressive, false);
ini.Get("Display", "DisableScreenSaver", &m_LocalCoreStartupParameter.bDisableScreenSaver, true);
ini.Get("Display", "ForceNTSCJ", &m_LocalCoreStartupParameter.bForceNTSCJ, false);

View File

@@ -129,11 +129,19 @@ void DisplayMessage(const char *message, int time_in_ms)
SCoreStartupParameter& _CoreParameter =
SConfig::GetInstance().m_LocalCoreStartupParameter;
// Actually displaying non-ASCII could cause things to go pear-shaped
for (const char *c = message; *c != '\0'; ++c)
if (*c < ' ')
return;
g_video_backend->Video_AddMessage(message, time_in_ms);
if (_CoreParameter.bRenderToMain &&
SConfig::GetInstance().m_InterfaceStatusbar) {
Host_UpdateStatusBar(message);
} else
SConfig::GetInstance().m_InterfaceStatusbar)
{
Host_UpdateStatusBar(message);
}
else
Host_UpdateTitle(message);
}
@@ -285,8 +293,9 @@ void CpuThread()
if (_CoreParameter.bLockThreads)
Common::SetCurrentThreadAffinity(1); // Force to first core
if (_CoreParameter.bUseFastMem)
#if defined(_WIN32) && defined(_M_X64)
EMM::InstallExceptionHandler(); // Let's run under memory watch
#endif
if (!g_stateFileName.empty())
State::LoadAs(g_stateFileName);

View File

@@ -45,8 +45,7 @@ SCoreStartupParameter::SCoreStartupParameter()
bEnableFPRF(false),
bCPUThread(true), bDSPThread(false), bDSPHLE(true),
bSkipIdle(true), bNTSC(false), bForceNTSCJ(false),
bHLE_BS2(true), bUseFastMem(false),
bLockThreads(false),
bHLE_BS2(true), bLockThreads(false),
bEnableCheats(false),
bMergeBlocks(false),
bRunCompareServer(false), bRunCompareClient(false),
@@ -57,7 +56,7 @@ SCoreStartupParameter::SCoreStartupParameter()
bAutoHideCursor(false), bUsePanicHandlers(true),
iRenderWindowXPos(-1), iRenderWindowYPos(-1),
iRenderWindowWidth(640), iRenderWindowHeight(480),
bRenderWindowAutoSize(false),
bRenderWindowAutoSize(false), bKeepWindowOnTop(false),
bFullscreen(false), bRenderToMain(false),
bProgressive(false), bDisableScreenSaver(false),
iTheme(0),
@@ -127,6 +126,7 @@ bool SCoreStartupParameter::AutoSetup(EBootBS2 _BootBS2)
SplitPath(m_strFilename, NULL, NULL, &Extension);
if (!strcasecmp(Extension.c_str(), ".gcm") ||
!strcasecmp(Extension.c_str(), ".iso") ||
!strcasecmp(Extension.c_str(), ".wbfs") ||
!strcasecmp(Extension.c_str(), ".ciso") ||
!strcasecmp(Extension.c_str(), ".gcz") ||
bootDrive)

View File

@@ -103,7 +103,6 @@ struct SCoreStartupParameter
bool bNTSC;
bool bForceNTSCJ;
bool bHLE_BS2;
bool bUseFastMem;
bool bLockThreads;
bool bEnableCheats;
bool bMergeBlocks;
@@ -133,7 +132,7 @@ struct SCoreStartupParameter
std::string strFullscreenResolution;
int iRenderWindowXPos, iRenderWindowYPos;
int iRenderWindowWidth, iRenderWindowHeight;
bool bRenderWindowAutoSize;
bool bRenderWindowAutoSize, bKeepWindowOnTop;
bool bFullscreen, bRenderToMain;
bool bProgressive, bDisableScreenSaver;

View File

@@ -153,17 +153,17 @@ void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory &cpMe
const VAT &vtxAttr = cpMem.vtxAttr[vatIndex];
// Colors
const int colDesc[2] = {vtxDesc.Color0, vtxDesc.Color1};
const int colComp[2] = {vtxAttr.g0.Color0Comp, vtxAttr.g0.Color1Comp};
const u32 colDesc[2] = {vtxDesc.Color0, vtxDesc.Color1};
const u32 colComp[2] = {vtxAttr.g0.Color0Comp, vtxAttr.g0.Color1Comp};
const int tcElements[8] =
const u32 tcElements[8] =
{
vtxAttr.g0.Tex0CoordElements, vtxAttr.g1.Tex1CoordElements, vtxAttr.g1.Tex2CoordElements,
vtxAttr.g1.Tex3CoordElements, vtxAttr.g1.Tex4CoordElements, vtxAttr.g2.Tex5CoordElements,
vtxAttr.g2.Tex6CoordElements, vtxAttr.g2.Tex7CoordElements
};
const int tcFormat[8] =
const u32 tcFormat[8] =
{
vtxAttr.g0.Tex0CoordFormat, vtxAttr.g1.Tex1CoordFormat, vtxAttr.g1.Tex2CoordFormat,
vtxAttr.g1.Tex3CoordFormat, vtxAttr.g1.Tex4CoordFormat, vtxAttr.g2.Tex5CoordFormat,

View File

@@ -71,10 +71,10 @@ void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile *file, std::vector<Analyze
u32 cmdStart = 0;
u32 nextMemUpdate = 0;
// Debugging
vector<CmdData> prevCmds;
while (cmdStart < frame.fifoDataSize)
{
// Add memory updates that have occured before this point in the frame
@@ -83,9 +83,9 @@ void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile *file, std::vector<Analyze
AddMemoryUpdate(frame.memoryUpdates[nextMemUpdate], analyzed);
++nextMemUpdate;
}
bool wasDrawing = m_DrawingObject;
u32 cmdSize = DecodeCommand(&frame.fifoData[cmdStart]);
#if (LOG_FIFO_CMDS)
@@ -95,7 +95,7 @@ void FifoPlaybackAnalyzer::AnalyzeFrames(FifoDataFile *file, std::vector<Analyze
cmdData.size = cmdSize;
prevCmds.push_back(cmdData);
#endif
// Check for error
if (cmdSize == 0)
{

View File

@@ -94,8 +94,9 @@ bool FifoPlayer::Play()
if (m_EarlyMemoryUpdates && m_CurrentFrame == m_FrameRangeStart)
WriteAllMemoryUpdates();
WriteFrame(m_File->GetFrame(m_CurrentFrame), m_FrameInfo[m_CurrentFrame]);
++m_CurrentFrame;
WriteFrame(m_File->GetFrame(m_CurrentFrame), m_FrameInfo[m_CurrentFrame]);
++m_CurrentFrame;
}
}
}

View File

@@ -44,6 +44,8 @@ public:
u32 GetFrameObjectCount();
u32 GetCurrentFrameNum() { return m_CurrentFrame; }
const AnalyzedFrameInfo& GetAnalyzedFrameInfo(u32 frame) { return m_FrameInfo[frame]; }
// Frame range
u32 GetFrameRangeStart() { return m_FrameRangeStart; }
void SetFrameRangeStart(u32 start);

View File

@@ -253,9 +253,12 @@ bool RunActiveCodes()
void RunCodeHandler()
{
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats && active_codes.size() > 0)
{
if (!code_handler_installed)
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)

View File

@@ -234,8 +234,8 @@ void Write32(const u32 _Value, const u32 _Address)
m_Control.PSTAT = tmpAICtrl.PSTAT;
g_LastCPUTime = CoreTiming::GetTicks();
// Tell Drive Interface to stop streaming
if (!tmpAICtrl.PSTAT) DVDInterface::g_bStream = false;
// Tell Drive Interface to start/stop streaming
DVDInterface::g_bStream = tmpAICtrl.PSTAT;
}
// AI Interrupt
@@ -293,6 +293,11 @@ static void GenerateAudioInterrupt()
UpdateInterrupts();
}
void GenerateAISInterrupt()
{
GenerateAudioInterrupt();
}
void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DACSampleRate)
{
_AISampleRate = g_AISSampleRate;

View File

@@ -43,6 +43,8 @@ void Write32(const u32 _iValue, const u32 _iAddress);
// Get the audio rates (48000 or 32000 only)
unsigned int GetAIDSampleRate();
void GenerateAISInterrupt();
} // namespace
#endif

View File

@@ -354,7 +354,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
// AI
case AUDIO_DMA_BLOCKS_LEFT:
_uReturnValue = g_audioDMA.BlocksLeft;
_uReturnValue = g_audioDMA.BlocksLeft > 0 ? g_audioDMA.BlocksLeft - 1 : 0; // AUDIO_DMA_BLOCKS_LEFT is zero based
break;
case AUDIO_DMA_START_LO:
@@ -435,10 +435,10 @@ void Write16(const u16 _Value, const u32 _Address)
if (tmpControl.ARAM) g_dspState.DSPControl.ARAM = 0;
if (tmpControl.DSP) g_dspState.DSPControl.DSP = 0;
// g_ARAM
// g_ARAM (line below should be commented out to emulate the DMA wait time)
g_dspState.DSPControl.DMAState = 0; // keep g_ARAM DMA State zero
// unknown
// unknown
g_dspState.DSPControl.unk3 = tmpControl.unk3;
g_dspState.DSPControl.pad = tmpControl.pad;
if (g_dspState.DSPControl.pad != 0)
@@ -453,13 +453,30 @@ void Write16(const u16 _Value, const u32 _Address)
// ARAM
// DMA back and forth between ARAM and RAM
case AR_INFO:
//PanicAlert("write %x %x", _Value,PowerPC::ppcState.pc);
//PanicAlert("AR_INFO %x PC: %x", _Value, PowerPC::ppcState.pc);
ERROR_LOG(DSPINTERFACE, "AR_INFO %x PC: %x", _Value, PowerPC::ppcState.pc);
g_ARAM_Info.Hex = _Value;
// 0x43
// Monster Hunter Tri, DKCR
// 0x43, 0x63:
// Rebel Strike, Clone Wars, WWE DOR2, Mario Golf
// 0x43, 0x64, 0x63
// Transworld Surf, Smashing Drive, SSBM, Cel Damage
// __OSInitAudioSystem sets to 0x43 -> expects 16bit adressing and mapping to dsp iram?
// __OSCheckSize sets = 0x20 | 3 (keeps upper bits)
// 0x23 -> Zelda standard mode (standard ARAM access ??)
// 0x43 -> Set by Eternal Darkness and SSBB
// 0x43 -> Set by __OSInitAudioSystem
// 0x58 -> Transworld Surf, Cel Damage, SSBM
// 0x60 -> Transworld Surf, Cel Damage, SSBM
// 0x63 -> ARCheckSize Mode (access AR-registers ??) or no exception ??
// 0x64 -> Transworld Surf, Cel Damage, SSBM
// 0x00 -> Switch to external ARAM
// 0x04 -> Switch to internal ARAM
break;
case AR_MODE:
@@ -620,7 +637,7 @@ void GenerateDSPInterrupt(DSPInterruptType type, bool _bSet)
switch (type)
{
case INT_DSP: g_dspState.DSPControl.DSP = _bSet ? 1 : 0; break;
case INT_ARAM: g_dspState.DSPControl.ARAM = _bSet ? 1 : 0; break;
case INT_ARAM: g_dspState.DSPControl.ARAM = _bSet ? 1 : 0; if (_bSet) g_dspState.DSPControl.DMAState = 0; break;
case INT_AID: g_dspState.DSPControl.AID = _bSet ? 1 : 0; break;
}
@@ -672,7 +689,7 @@ void UpdateAudioDMA()
{
// Send silence. Yeah, it's a bit of a waste to sample rate convert
// silence. or hm. Maybe we shouldn't do this :)
// dsp->DSP_SendAIBuffer(0, AudioInterface::GetDSPSampleRate());
//dsp_emulator->DSP_SendAIBuffer(0, AudioInterface::GetAIDSampleRate());
}
}
@@ -682,44 +699,95 @@ void Do_ARAM_DMA()
// seems like a good estimate
CoreTiming::ScheduleEvent_Threadsafe(g_arDMA.Cnt.count >> 1, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
// Uncomment the line below to emulate the DMA wait time.
//g_dspState.DSPControl.DMAState = 1;
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks
if (g_arDMA.Cnt.dir)
{
// ARAM -> MRAM
INFO_LOG(DSPINTERFACE, "DMA %08x bytes from ARAM %08x to MRAM %08x",
g_arDMA.Cnt.count, g_arDMA.ARAddr, g_arDMA.MMAddr);
INFO_LOG(DSPINTERFACE, "DMA %08x bytes from ARAM %08x to MRAM %08x PC: %08x",
g_arDMA.Cnt.count, g_arDMA.ARAddr, g_arDMA.MMAddr, PC);
while (g_arDMA.Cnt.count)
// Outgoing data from ARAM is mirrored every 64MB (verified on real HW)
g_arDMA.ARAddr &= 0x3ffffff;
g_arDMA.MMAddr &= 0x3ffffff;
if (g_arDMA.ARAddr < g_ARAM.size)
{
if (g_arDMA.ARAddr < g_ARAM.size)
while (g_arDMA.Cnt.count)
{
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr], g_arDMA.MMAddr);
if ((g_ARAM_Info.Hex & 0xf) == 3)
{
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask], g_arDMA.MMAddr);
}
else if ((g_ARAM_Info.Hex & 0xf) == 4)
{
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask], g_arDMA.MMAddr);
}
else
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask], g_arDMA.MMAddr);
g_arDMA.MMAddr += 8;
g_arDMA.ARAddr += 8;
g_arDMA.Cnt.count -= 8;
}
}
else
{
// Assuming no external ARAM installed; returns zeroes on out of bounds reads (verified on real HW)
while (g_arDMA.Cnt.count)
{
Memory::Write_U64(0, g_arDMA.MMAddr);
g_arDMA.MMAddr += 8;
g_arDMA.ARAddr += 8;
g_arDMA.Cnt.count -= 8;
}
g_arDMA.Cnt.count -= 8;
}
}
else
{
// MRAM -> ARAM
INFO_LOG(DSPINTERFACE, "DMA %08x bytes from MRAM %08x to ARAM %08x",
g_arDMA.Cnt.count, g_arDMA.MMAddr, g_arDMA.ARAddr);
INFO_LOG(DSPINTERFACE, "DMA %08x bytes from MRAM %08x to ARAM %08x PC: %08x",
g_arDMA.Cnt.count, g_arDMA.MMAddr, g_arDMA.ARAddr, PC);
while (g_arDMA.Cnt.count)
// Incoming data into ARAM is mirrored every 64MB (verified on real HW)
g_arDMA.ARAddr &= 0x3ffffff;
g_arDMA.MMAddr &= 0x3ffffff;
if (g_arDMA.ARAddr < g_ARAM.size)
{
if (g_arDMA.ARAddr < g_ARAM.size)
while (g_arDMA.Cnt.count)
{
*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
if ((g_ARAM_Info.Hex & 0xf) == 3)
{
*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
}
else if ((g_ARAM_Info.Hex & 0xf) == 4)
{
if (g_arDMA.ARAddr < 0x400000)
{
*(u64*)&g_ARAM.ptr[(g_arDMA.ARAddr + 0x400000) & g_ARAM.mask] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
}
*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
}
else
*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
g_arDMA.MMAddr += 8;
g_arDMA.ARAddr += 8;
g_arDMA.Cnt.count -= 8;
}
g_arDMA.Cnt.count -= 8;
}
else
{
// Assuming no external ARAM installed; writes nothing to ARAM when out of bounds (verified on real HW)
g_arDMA.MMAddr += g_arDMA.Cnt.count;
g_arDMA.ARAddr += g_arDMA.Cnt.count;
g_arDMA.Cnt.count = 0;
}
}
}
// (shuffle2) I still don't believe that this hack is actually needed... :(
// Maybe the wii sports ucode is processed incorrectly?
// (LM) It just means that dsp reads via '0xffdd' on WII can end up in EXRAM or main RAM

View File

@@ -24,6 +24,8 @@
#include "Thread.h"
#include "ChunkFile.h"
#include "IniFile.h"
#include "ConfigManager.h"
#include "CPUDetect.h"
#include "DSPLLEGlobals.h" // Local
#include "DSP/DSPInterpreter.h"
@@ -84,6 +86,27 @@ void DSPLLE::dsp_thread(DSPLLE *dsp_lle)
{
Common::SetCurrentThreadName("DSP thread");
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bLockThreads)
{
if (cpu_info.num_cores > 3)
{
// HACK (delroth): there is no way to know where hyperthreads are in
// the current Dolphin version.
bool windows = false;
#ifdef _WIN32
windows = true;
#endif
u8 core_id;
if (windows && cpu_info.num_cores > 4) // Probably HT
core_id = 5; // 3rd non HT core
else
core_id = 3; // 3rd core
Common::SetCurrentThreadAffinity(1 << core_id);
}
}
while (dsp_lle->m_bIsRunning)
{
int cycles = (int)dsp_lle->m_cycle_count;

View File

@@ -28,6 +28,7 @@
#include "Thread.h"
#include "Memmap.h"
#include "../VolumeHandler.h"
#include "AudioInterface.h"
// Disc transfer rate measured in bytes per second
static const u32 DISC_TRANSFER_RATE_GC = 3125 * 1024;
@@ -201,9 +202,11 @@ static UDICR m_DICR;
static UDIIMMBUF m_DIIMMBUF;
static UDICFG m_DICFG;
static u32 AudioStart;
static u32 LoopStart;
static u32 AudioPos;
static u32 AudioLength;
static u32 CurrentStart;
static u32 LoopLength;
static u32 CurrentLength;
u32 g_ErrorCode = 0;
bool g_bDiscInside = false;
@@ -238,12 +241,16 @@ void DoState(PointerWrap &p)
p.Do(m_DIIMMBUF);
p.Do(m_DICFG);
p.Do(AudioStart);
p.Do(LoopStart);
p.Do(AudioPos);
p.Do(AudioLength);
p.Do(LoopLength);
p.Do(g_ErrorCode);
p.Do(g_bDiscInside);
p.Do(g_bStream);
p.Do(CurrentStart);
p.Do(CurrentLength);
}
void TransferComplete(u64 userdata, int cyclesLate)
@@ -266,9 +273,13 @@ void Init()
m_DICFG.Hex = 0;
m_DICFG.CONFIG = 1; // Disable bootrom descrambler
AudioStart = 0;
AudioPos = 0;
AudioLength = 0;
AudioPos = 0;
LoopStart = 0;
LoopLength = 0;
CurrentStart = 0;
CurrentLength = 0;
g_bStream = false;
ejectDisc = CoreTiming::RegisterEvent("EjectDisc", EjectDiscCallback);
insertDisc = CoreTiming::RegisterEvent("InsertDisc", InsertDiscCallback);
@@ -351,33 +362,46 @@ bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength)
bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples)
{
_iNumSamples &= ~31;
if (AudioPos == 0)
{
//MessageBox(0,"DVD: Trying to stream from 0", "bah", 0);
memset(_pDestBuffer, 0, _iNumSamples); // probably __AI_SRC_INIT :P
return false;
}
_iNumSamples &= ~31;
else
{
std::lock_guard<std::mutex> lk(dvdread_section);
VolumeHandler::ReadToPtr(_pDestBuffer, AudioPos, _iNumSamples);
std::lock_guard<std::mutex> lk(dvdread_section);
VolumeHandler::ReadToPtr(_pDestBuffer, AudioPos, _iNumSamples);
}
//
// FIX THIS
//
// loop check
//
AudioPos += _iNumSamples;
if (AudioPos >= AudioStart + AudioLength)
if (g_bStream)
{
g_bStream = false; // Starfox Adventures
AudioPos = AudioStart;
NGCADPCM::InitFilter();
}
AudioPos += _iNumSamples;
//WARN_LOG(DVDINTERFACE,"ReadADPCM");
return true;
if (AudioPos >= CurrentStart + CurrentLength)
{
if (LoopStart == 0)
{
AudioPos = 0;
CurrentStart = 0;
CurrentLength = 0;
}
else
{
AudioPos = LoopStart;
CurrentStart = LoopStart;
CurrentLength = LoopLength;
}
NGCADPCM::InitFilter();
AudioInterface::GenerateAISInterrupt();
}
//WARN_LOG(DVDINTERFACE,"ReadADPCM");
return true;
}
else
return false;
}
void Read32(u32& _uReturnValue, const u32 _iAddress)
@@ -813,28 +837,69 @@ void ExecuteCommand(UDICR& _DICR)
// m_DICMDBUF[2].Hex = Length of the stream
case 0xE1:
{
// ugly hack to catch the disable command
if (m_DICMDBUF[1].Hex != 0)
u32 pos = m_DICMDBUF[1].Hex << 2;
u32 length = m_DICMDBUF[2].Hex;
// Start playing
if (!g_bStream && m_DICMDBUF[0].CMDBYTE1 == 0 && pos != 0 && length != 0)
{
AudioPos = m_DICMDBUF[1].Hex << 2;
AudioStart = AudioPos;
AudioLength = m_DICMDBUF[2].Hex;
NGCADPCM::InitFilter();
AudioPos = pos;
CurrentStart = pos;
CurrentLength = length;
NGCADPCM::InitFilter();
g_bStream = true;
WARN_LOG(DVDINTERFACE, "(Audio) Stream subcmd = %02x offset = %08x length=%08x",
m_DICMDBUF[0].CMDBYTE1, AudioPos, AudioLength);
}
else
WARN_LOG(DVDINTERFACE, "(Audio) Off?");
LoopStart = pos;
LoopLength = length;
g_bStream = (m_DICMDBUF[0].CMDBYTE1 == 0); // This command can start/stop the stream
// Stop stream
if (m_DICMDBUF[0].CMDBYTE1 == 1)
{
AudioPos = 0;
LoopStart = 0;
LoopLength = 0;
CurrentStart = 0;
CurrentLength = 0;
}
WARN_LOG(DVDINTERFACE, "(Audio) Stream subcmd = %08x offset = %08x length=%08x",
m_DICMDBUF[0].Hex, m_DICMDBUF[1].Hex << 2, m_DICMDBUF[2].Hex);
}
break;
// Request Audio Status (Immediate)
case 0xE2:
m_DIIMMBUF.Hex = g_bStream ? 1 : 0;
//WARN_LOG(DVDINTERFACE, "(Audio): Request Audio status %s", g_bStream? "on":"off");
{
switch (m_DICMDBUF[0].CMDBYTE1)
{
case 0x00: // Returns streaming status
m_DIIMMBUF.Hex = (AudioPos == 0) ? 0 : 1;
break;
case 0x01: // Returns the current offset
if (g_bStream)
m_DIIMMBUF.Hex = (AudioPos - CurrentStart) >> 2;
else
m_DIIMMBUF.Hex = 0;
break;
case 0x02: // Returns the start offset
if (g_bStream)
m_DIIMMBUF.Hex = CurrentStart >> 2;
else
m_DIIMMBUF.Hex = 0;
break;
case 0x03: // Returns the total length
if (g_bStream)
m_DIIMMBUF.Hex = CurrentLength;
else
m_DIIMMBUF.Hex = 0;
break;
default:
WARN_LOG(DVDINTERFACE, "(Audio): Subcommand: %02x Request Audio status %s", m_DICMDBUF[0].CMDBYTE1, g_bStream? "on":"off");
break;
}
}
break;
case DVDLowStopMotor:

View File

@@ -109,7 +109,7 @@ CEXIIPL::CEXIIPL() :
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHLE_BS2)
{
// Copy header
memcpy(m_pIPL, m_bNTSC ? iplverNTSC : iplverPAL, sizeof(m_bNTSC ? iplverNTSC : iplverPAL));
memcpy(m_pIPL, m_bNTSC ? iplverNTSC : iplverPAL, m_bNTSC ? sizeof(iplverNTSC) : sizeof(iplverPAL));
// Load fonts
LoadFileToIPL((File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + FONT_SJIS), 0x1aff00);
@@ -197,7 +197,7 @@ void CEXIIPL::TransferByte(u8& _uByte)
// The first 4 bytes must be the address
// If we haven't read it, do it now
if (m_uPosition < 4)
if (m_uPosition <= 3)
{
m_uAddress <<= 8;
m_uAddress |= _uByte;
@@ -207,137 +207,156 @@ void CEXIIPL::TransferByte(u8& _uByte)
// Check if the command is complete
if (m_uPosition == 3)
{
// Get the time ...
// Get the time ...
u32 &rtc = *((u32 *)&m_RTC);
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
*((u32 *)&m_RTC) = Common::swap32(CEXIIPL::GetGCTime() - cWiiBias); // Subtract Wii bias
{
// Subtract Wii bias
rtc = Common::swap32(CEXIIPL::GetGCTime() - cWiiBias);
}
else
*((u32 *)&m_RTC) = Common::swap32(CEXIIPL::GetGCTime());
{
rtc = Common::swap32(CEXIIPL::GetGCTime());
}
#if MAX_LOGLEVEL >= INFO_LEVEL
if ((m_uAddress & 0xF0000000) == 0xb0000000)
// Log the command
std::string device_name;
switch (CommandRegion())
{
INFO_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: WII something");
case REGION_RTC:
device_name = "RTC";
break;
case REGION_SRAM:
device_name = "SRAM";
break;
case REGION_UART:
device_name = "UART";
break;
case REGION_EUART:
case REGION_EUART_UNK:
device_name = "EUART";
break;
case REGION_UART_UNK:
device_name = "UART Other?";
break;
case REGION_BARNACLE:
device_name = "UART Barnacle";
break;
case REGION_WRTC0:
case REGION_WRTC1:
case REGION_WRTC2:
device_name = "Wii RTC flags - not implemented";
break;
default:
if ((m_uAddress >> 6) < ROM_SIZE)
{
device_name = "ROM";
}
else
{
device_name = "illegal address";
_dbg_assert_msg_(EXPANSIONINTERFACE, 0,
"EXI IPL-DEV: %s %08x", device_name.c_str(), m_uAddress);
}
break;
}
else if ((m_uAddress & 0xF0000000) == 0x30000000)
{
// wii stuff perhaps wii SRAM?
INFO_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: WII something (perhaps SRAM?)");
}
else if ((m_uAddress & 0x60000000) == 0)
{
INFO_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: IPL access");
}
else if ((m_uAddress & 0x7FFFFF00) == 0x20000000)
{
INFO_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: RTC access");
}
else if ((m_uAddress & 0x7FFFFF00) == 0x20000100)
{
INFO_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: SRAM access");
}
else if ((m_uAddress & 0x7FFFFF00) == 0x20010000)
{
DEBUG_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: UART");
}
else if ((m_uAddress & 0x7FFFFF00) == 0x20011300)
{
DEBUG_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: UART Barnacle");
}
else if ((m_uAddress & 0x7FFFFF00) == 0x20010300)
{
DEBUG_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: UART Other?");
}
else if (((m_uAddress & 0x7FFFFF00) == 0x21000000) ||
((m_uAddress & 0x7FFFFF00) == 0x21000100) ||
((m_uAddress & 0x7FFFFF00) == 0x21000800))
{
ERROR_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: RTC flags (WII only) - not implemented");
}
else
{
//_dbg_assert_(EXPANSIONINTERFACE, 0);
_dbg_assert_msg_(EXPANSIONINTERFACE, 0, "EXI IPL-DEV: illegal access address %08x", m_uAddress);
ERROR_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: illegal address %08x", m_uAddress);
}
#endif
DEBUG_LOG(EXPANSIONINTERFACE, "%s %s %08x", device_name.c_str(),
IsWriteCommand() ? "write" : "read", m_uAddress);
}
}
else
{
// --- Encrypted ROM ---
// atm we pre-decrypt the whole thing, see CEXIIPL ctor
if ((m_uAddress & 0x60000000) == 0)
// Actually read or write a byte
switch (CommandRegion())
{
if ((m_uAddress & 0x80000000) == 0)
{
u32 position = ((m_uAddress >> 6) & ROM_MASK) + m_uRWOffset;
// Technically we should apply descrambling here, if it's currently enabled.
_uByte = m_pIPL[position];
if ((position >= 0x001AFF00) && (position <= 0x001FF474) && !m_FontsLoaded)
{
PanicAlertT("Error: Trying to access %s fonts but they are not loaded. Games may not show fonts correctly, or crash.",
(position >= 0x001FCF00)?"ANSI":"SJIS");
m_FontsLoaded = true; // Don't be a nag :p
}
}
}
// --- Real Time Clock (RTC) ---
else if ((m_uAddress & 0x7FFFFF00) == 0x20000000)
{
if (m_uAddress & 0x80000000)
case REGION_RTC:
if (IsWriteCommand())
m_RTC[(m_uAddress & 0x03) + m_uRWOffset] = _uByte;
else
_uByte = m_RTC[(m_uAddress & 0x03) + m_uRWOffset];
}
// --- SRAM ---
else if ((m_uAddress & 0x7FFFFF00) == 0x20000100)
{
if (m_uAddress & 0x80000000)
break;
case REGION_SRAM:
if (IsWriteCommand())
g_SRAM.p_SRAM[(m_uAddress & 0x3F) + m_uRWOffset] = _uByte;
else
_uByte = g_SRAM.p_SRAM[(m_uAddress & 0x3F) + m_uRWOffset];
}
// --- UART ---
else if ((m_uAddress & 0x7FFFFF00) == 0x20010000)
{
if (m_uAddress & 0x80000000)
break;
case REGION_UART:
case REGION_EUART:
if (IsWriteCommand())
{
m_szBuffer[m_count++] = _uByte;
if (_uByte != '\0')
m_szBuffer[m_count++] = _uByte;
if ((m_count >= 256) || (_uByte == 0xD))
{
m_szBuffer[m_count] = 0x00;
INFO_LOG(OSREPORT, "%s", m_szBuffer);
NOTICE_LOG(OSREPORT, "%s", m_szBuffer);
memset(m_szBuffer, 0, sizeof(m_szBuffer));
m_count = 0;
}
}
else
_uByte = 0x01; // dunno
}
else if ((m_uAddress & 0x7FFFFF00) == 0x20011300)
{
INFO_LOG(OSREPORT, "UART Barnacle %x", _uByte);
}
else if ((m_uAddress & 0x7FFFFF00) == 0x20010300)
{
INFO_LOG(OSREPORT, "UART? %x", _uByte);
{
// "Queue Length"... return 0 cause we're instant
_uByte = 0;
}
break;
case REGION_EUART_UNK:
// Writes 0xf2 then 0xf3 on EUART init. Just need to return non-zero
// so we can leave the byte untouched.
break;
case REGION_UART_UNK:
DEBUG_LOG(OSREPORT, "UART? %x", _uByte);
_uByte = 0xff;
break;
case REGION_BARNACLE:
DEBUG_LOG(OSREPORT, "UART Barnacle %x", _uByte);
break;
case REGION_WRTC0:
case REGION_WRTC1:
case REGION_WRTC2:
// WII only RTC flags... afaik just the wii menu initialize it
default:
if ((m_uAddress >> 6) < ROM_SIZE)
{
if (!IsWriteCommand())
{
u32 position = ((m_uAddress >> 6) & ROM_MASK) + m_uRWOffset;
// Technically we should descramble here iff descrambling logic is enabled.
// At the moment, we pre-decrypt the whole thing and
// ignore the "enabled" bit - see CEXIIPL::CEXIIPL
_uByte = m_pIPL[position];
if ((position >= 0x001AFF00) && (position <= 0x001FF474) && !m_FontsLoaded)
{
PanicAlertT(
"Error: Trying to access %s fonts but they are not loaded. "
"Games may not show fonts correctly, or crash.",
(position >= 0x001FCF00) ? "ANSI" : "SJIS");
m_FontsLoaded = true; // Don't be a nag :p
}
}
}
else
{
NOTICE_LOG(OSREPORT, "EXI IPL-DEV: %s %x at %08x",
IsWriteCommand() ? "write" : "read", _uByte, m_uAddress);
}
break;
}
else if (((m_uAddress & 0x7FFFFF00) == 0x21000000) ||
((m_uAddress & 0x7FFFFF00) == 0x21000100) ||
((m_uAddress & 0x7FFFFF00) == 0x21000800))
{
// WII only RTC flags... afaik just the wii menu initialize it
// if (m_uAddress & 0x80000000)
// g_SRAM.p_SRAM[(m_uAddress & 0x3F) + m_uRWOffset] = _uByte;
// else
// _uByte = g_SRAM.p_SRAM[(m_uAddress & 0x3F) + m_uRWOffset];
}
m_uRWOffset++;
}
m_uPosition++;
}

View File

@@ -43,6 +43,20 @@ private:
ROM_MASK = (ROM_SIZE - 1)
};
enum
{
REGION_RTC = 0x200000,
REGION_SRAM = 0x200001,
REGION_UART = 0x200100,
REGION_UART_UNK = 0x200103,
REGION_BARNACLE = 0x200113,
REGION_WRTC0 = 0x210000,
REGION_WRTC1 = 0x210001,
REGION_WRTC2 = 0x210008,
REGION_EUART_UNK= 0x300000,
REGION_EUART = 0x300001
};
// Region
bool m_bNTSC;
@@ -63,6 +77,8 @@ private:
bool m_FontsLoaded;
virtual void TransferByte(u8 &_uByte);
bool IsWriteCommand() const { return !!(m_uAddress & (1 << 31)); }
u32 const CommandRegion() const { return (m_uAddress & ~(1 << 31)) >> 8; }
void LoadFileToIPL(std::string filename, u32 offset);
};

View File

@@ -103,7 +103,7 @@ CEXIMemoryCard::CEXIMemoryCard(const int index)
void innerFlush(FlushData* data)
{
File::IOFile pFile(data->filename, "wb");
File::IOFile pFile(data->filename, "r+b");
if (!pFile)
{
std::string dir;

File diff suppressed because it is too large Load Diff

View File

@@ -19,14 +19,15 @@
#define __GCMEMCARD_h__
#include "Common.h"
#include "CommonPaths.h"
#include "Sram.h"
#include "StringUtil.h"
#include "EXI_DeviceIPL.h"
#define BE64(x) (Common::swap64(x))
#define BE32(x) (Common::swap32(x))
#define BE16(x) (Common::swap16(x))
#define ArrayByteSwap(a) (ByteSwap(a, a+sizeof(u8)));
enum
{
SLOT_A = 0,
@@ -54,6 +55,7 @@ enum
DENTRY_STRLEN = 0x20,
DENTRY_SIZE = 0x40,
BLOCK_SIZE = 0x2000,
BAT_SIZE = 0xFFB,
MemCard59Mb = 0x04,
MemCard123Mb = 0x08,
@@ -75,25 +77,28 @@ private:
std::string m_fileName;
u32 maxBlock;
u32 mc_data_size;
u8* mc_data;
u16 m_sizeMb;
struct GCMBlock
{
GCMBlock(){erase();}
void erase() {memset(block, 0xFF, BLOCK_SIZE);}
u8 block[BLOCK_SIZE];
};
std::vector<GCMBlock> mc_data_blocks;
#pragma pack(push,1)
struct Header { //Offset Size Description
// Serial in libogc
u8 serial[12]; //0x0000 12 ?
u64 formatTime; //0x000c 8 time of format (OSTime value)
u8 SramBias[4]; //0x0014 4 sram bias at time of format
u8 SramLang[4]; //0x0018 4 sram language
u32 SramBias; //0x0014 4 sram bias at time of format
u32 SramLang; //0x0018 4 sram language
u8 Unk2[4]; //0x001c 4 ? almost always 0
// end Serial in libogc
u8 deviceID[2]; //0x0020 2 0 if formated in slot A 1 if formated in slot B
u8 SizeMb[2]; //0x0022 2 size of memcard in Mbits
u16 Encoding; //0x0024 2 encoding (ASCII or japanese)
u8 Unused1[468]; //0x0026 468 unused (0xff)
u8 UpdateCounter[2];//0x01fa 2 update Counter (?, probably unused)
u16 UpdateCounter; //0x01fa 2 update Counter (?, probably unused)
u16 Checksum; //0x01fc 2 Additive Checksum
u16 Checksum_Inv; //0x01fe 2 Inverse Checksum
u8 Unused2[7680]; //0x0200 0x1e00 unused (0xff)
@@ -101,7 +106,7 @@ private:
struct DEntry {
u8 Gamecode[4]; //0x00 0x04 Gamecode
u8 Markercode[2]; //0x04 0x02 Makercode
u8 Makercode[2]; //0x04 0x02 Makercode
u8 Unused1; //0x06 0x01 reserved/unused (always 0xff, has no effect)
u8 BIFlags; //0x07 0x01 banner gfx format and icon animation (Image Key)
// bit(s) description
@@ -147,19 +152,25 @@ private:
struct Directory {
DEntry Dir[DIRLEN]; //0x0000 Directory Entries (max 127)
u8 Padding[0x3a];
u8 UpdateCounter[2];//0x1ffa 2 update Counter
u16 UpdateCounter; //0x1ffa 2 update Counter
u16 Checksum; //0x1ffc 2 Additive Checksum
u16 Checksum_Inv; //0x1ffe 2 Inverse Checksum
} dir, dir_backup;
Directory *CurrentDir, *PreviousDir;
struct BlockAlloc {
u16 Checksum; //0x0000 2 Additive Checksum
u16 Checksum_Inv; //0x0002 2 Inverse Checksum
u8 UpdateCounter[2];//0x0004 2 update Counter
u8 FreeBlocks[2]; //0x0006 2 free Blocks
u8 LastAllocated[2];//0x0008 2 last allocated Block
u16 Map[0xFFB]; //0x000a 0x1ff8 Map of allocated Blocks
u16 Checksum; //0x0000 2 Additive Checksum
u16 Checksum_Inv; //0x0002 2 Inverse Checksum
u16 UpdateCounter; //0x0004 2 update Counter
u16 FreeBlocks; //0x0006 2 free Blocks
u16 LastAllocated; //0x0008 2 last allocated Block
u16 Map[BAT_SIZE]; //0x000a 0x1ff8 Map of allocated Blocks
u16 GetNextBlock(u16 Block) const;
u16 NextFreeBlock(u16 StartingBlock=MC_FST_BLOCKS) const;
bool ClearBlocks(u16 StartingBlock, u16 Length);
} bat,bat_backup;
BlockAlloc *CurrentBat, *PreviousBat;
struct GCMC_Header
{
Header *hdr;
@@ -168,92 +179,83 @@ private:
};
#pragma pack(pop)
u32 ImportGciInternal(FILE* gcih, const char *inputFile, std::string outputFile);
u32 ImportGciInternal(FILE* gcih, const char *inputFile, const std::string &outputFile);
static void FormatInternal(GCMC_Header &GCP);
public:
GCMemcard(const char* fileName, bool forceCreation=false, bool sjis=false);
bool IsValid() { return m_valid; }
bool IsAsciiEncoding();
bool IsValid() const { return m_valid; }
bool IsAsciiEncoding() const;
bool Save();
bool Format(bool sjis = false, u16 SizeMb = MemCard2043Mb);
static bool Format(u8 * card_data, bool sjis = false, u16 SizeMb = MemCard2043Mb);
static void calc_checksumsBE(u16 *buf, u32 length, u16 *csum, u16 *inv_csum);
u32 TestChecksums();
u32 TestChecksums() const;
bool FixChecksums();
// get number of file entries in the directory
u8 GetNumFiles();
u8 GetNumFiles() const;
u8 GetFileIndex(u8 fileNumber) const;
// get the free blocks from bat
u16 GetFreeBlocks();
u16 GetFreeBlocks() const;
// If title already on memcard returns index, otherwise returns -1
u8 TitlePresent(DEntry d);
// DEntry functions, all take u8 index < DIRLEN (127)
// Functions that have ascii output take a char *buffer
u8 TitlePresent(DEntry d) const;
// buffer needs to be a char[5] or bigger
bool DEntry_GameCode(u8 index, char *buffer);
// buffer needs to be a char[2] or bigger
bool DEntry_Markercode(u8 index, char *buffer);
// buffer needs to be a char[9] or bigger
bool DEntry_BIFlags(u8 index, char *buffer);
// buffer needs to be a char[32] or bigger
bool DEntry_FileName(u8 index, char *buffer);
u32 DEntry_ModTime(u8 index);
u32 DEntry_ImageOffset(u8 index);
// buffer needs to be a char[17] or bigger
bool DEntry_IconFmt(u8 index, char *buffer);
u16 DEntry_AnimSpeed(u8 index);
// buffer needs to be a char[4] or bigger
bool DEntry_Permissions(u8 index, char *buffer);
u8 DEntry_CopyCounter(u8 index);
bool GCI_FileName(u8 index, std::string &filename) const;
// DEntry functions, all take u8 index < DIRLEN (127)
std::string DEntry_GameCode(u8 index) const;
std::string DEntry_Makercode(u8 index) const;
std::string DEntry_BIFlags(u8 index) const;
std::string DEntry_FileName(u8 index) const;
u32 DEntry_ModTime(u8 index) const;
u32 DEntry_ImageOffset(u8 index) const;
std::string DEntry_IconFmt(u8 index) const;
u16 DEntry_AnimSpeed(u8 index) const;
std::string DEntry_Permissions(u8 index) const;
u8 DEntry_CopyCounter(u8 index) const;
// get first block for file
u16 DEntry_FirstBlock(u8 index);
u16 DEntry_FirstBlock(u8 index) const;
// get file length in blocks
u16 DEntry_BlockCount(u8 index);
u32 DEntry_CommentsAddress(u8 index);
// buffer needs to be a char[32] or bigger
bool DEntry_Comment1(u8 index, char *buffer);
// buffer needs to be a char[32] or bigger
bool DEntry_Comment2(u8 index, char *buffer);
u16 DEntry_BlockCount(u8 index) const;
u32 DEntry_CommentsAddress(u8 index) const;
std::string GetSaveComment1(u8 index) const;
std::string GetSaveComment2(u8 index) const;
// Copies a DEntry from u8 index to DEntry& data
bool DEntry_Copy(u8 index, DEntry& data);
bool GetDEntry(u8 index, DEntry &dest) const;
// assumes there's enough space in buffer
// old determines if function uses old or new method of copying data
// some functions only work with old way, some only work with new way
// TODO: find a function that works for all calls or split into 2 functions
u32 DEntry_GetSaveData(u8 index, u8* buffer, bool old);
u32 GetSaveData(u8 index, std::vector<GCMBlock> &saveBlocks) const;
// adds the file to the directory and copies its contents
// if remove > 0 it will pad bat.map with 0's sizeof remove
u32 ImportFile(DEntry& direntry, u8* contents, int remove);
u32 ImportFile(DEntry& direntry, std::vector<GCMBlock> &saveBlocks);
// delete a file from the directory
u32 RemoveFile(u8 index);
// reads a save from another memcard, and imports the data into this memcard
u32 CopyFrom(GCMemcard& source, u8 index);
u32 CopyFrom(const GCMemcard& source, u8 index);
// reads a .gci/.gcs/.sav file and calls ImportFile or saves out a gci file
u32 ImportGci(const char* inputFile, std::string outputFile);
u32 ImportGci(const char* inputFile,const std::string &outputFile);
// writes a .gci file to disk containing index
u32 ExportGci(u8 index, const char* fileName, std::string* fileName2);
u32 ExportGci(u8 index, const char* fileName, const std::string &directory) const;
// GCI files are untouched, SAV files are byteswapped
// GCS files have the block count set, default is 1 (For export as GCS)
void Gcs_SavConvert(DEntry* tempDEntry, int saveType, int length = BLOCK_SIZE);
static void Gcs_SavConvert(DEntry &tempDEntry, int saveType, int length = BLOCK_SIZE);
// reads the banner image
bool ReadBannerRGBA8(u8 index, u32* buffer);
bool ReadBannerRGBA8(u8 index, u32* buffer) const;
// reads the animation frames
u32 ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays);
u32 ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays) const;
};
#endif

View File

@@ -19,9 +19,9 @@
#include "ChunkFile.h"
#include "ProcessorInterface.h"
#include "Memmap.h"
#include "../PowerPC/PowerPC.h"
#include "VideoBackendBase.h"
#include "../PowerPC/JitCommon/JitBase.h"
#include "../PowerPC/PowerPC.h"
#include "GPFifo.h"
@@ -96,6 +96,15 @@ void STACKALIGN CheckGatherPipe()
// move back the spill bytes
memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount);
// Profile where the FIFO writes are occurring.
if (jit && (jit->js.fifoWriteAddresses.find(PC)) == (jit->js.fifoWriteAddresses.end()))
{
jit->js.fifoWriteAddresses.insert(PC);
// Invalidate the JIT block so that it gets recompiled with the external exception check included.
jit->GetBlockCache()->InvalidateICache(PC, 4);
}
}
}

View File

@@ -427,6 +427,7 @@ void Wiimote::ReadData(const wm_read_data* const rd)
if (address + size > WIIMOTE_EEPROM_SIZE)
{
PanicAlert("ReadData: address + size out of bounds");
delete [] block;
return;
}
// generate a read error

View File

@@ -127,11 +127,6 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes)
bti = [[IOBluetoothDeviceInquiry alloc] init];
[bti setDelegate: sbt];
[bti setInquiryLength: 5];
[bti setSearchCriteria: kBluetoothServiceClassMajorAny
majorDeviceClass: kBluetoothDeviceClassMajorPeripheral
minorDeviceClass: kBluetoothDeviceClassMinorAny
];
[bti setUpdateNewDeviceNames: NO];
if ([bti start] == kIOReturnSuccess)
[bti retain];
@@ -149,6 +144,9 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes)
en = [[bti foundDevices] objectEnumerator];
for (int i = 0; i < found_devices; i++)
{
IOBluetoothDevice *dev = [en nextObject];
if (!IsValidBluetoothName([[dev name] UTF8String]))
continue;
// Find an unused slot
for (int k = 0; k < MAX_WIIMOTES; k++) {
if (wm[k] != NULL ||
@@ -156,7 +154,7 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes)
continue;
wm[k] = new Wiimote(k);
wm[k]->btd = [en nextObject];
wm[k]->btd = dev;
found_wiimotes++;
break;
}
@@ -177,10 +175,6 @@ bool Wiimote::Connect()
if (IsConnected())
return false;
if ([btd remoteNameRequest:nil] == kIOReturnSuccess)
m_motion_plus_inside =
static_cast<bool>([[btd getName] hasSuffix:@"-TR"]);
[btd openL2CAPChannelSync: &cchan
withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt];
[btd openL2CAPChannelSync: &ichan

View File

@@ -50,7 +50,6 @@ Wiimote::Wiimote(const unsigned int _index)
#endif
, leds(0), m_last_data_report(Report((u8 *)NULL, 0))
, m_channel(0), m_connected(false)
, m_motion_plus_inside(false)
{
#if defined(__linux__) && HAVE_BLUEZ
bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}};
@@ -143,16 +142,16 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const
rpt.second = (u8)size;
memcpy(rpt.first, (u8*)data, size);
// Convert output DATA packets to SET_REPORT packets for non-TR
// Wiimotes. Nintendo Wiimotes work without this translation, but 3rd
// Convert output DATA packets to SET_REPORT packets.
// Nintendo Wiimotes work without this translation, but 3rd
// party ones don't.
u8 head = m_motion_plus_inside ? 0xa2 : 0x52;
if (rpt.first[0] == 0xa2)
{
rpt.first[0] = head;
rpt.first[0] = WM_SET_REPORT | WM_BT_OUTPUT;
}
if (rpt.first[0] == head && rpt.first[1] == 0x18 && rpt.second == 23)
if (rpt.first[0] == (WM_SET_REPORT | WM_BT_OUTPUT) &&
rpt.first[1] == 0x18 && rpt.second == 23)
{
m_audio_reports.Push(rpt);
return;
@@ -513,4 +512,19 @@ void StateChange(EMUSTATE_CHANGE newState)
// TODO: disable/enable auto reporting, maybe
}
#define ARRAYSIZE(_arr) (sizeof(_arr)/(sizeof(_arr[0])))
bool IsValidBluetoothName(const char* name) {
static const char* kValidWiiRemoteBluetoothNames[] = {
"Nintendo RVL-CNT-01",
"Nintendo RVL-CNT-01-TR",
"Nintendo RVL-WBC-01",
};
for (size_t i = 0; i < ARRAYSIZE(kValidWiiRemoteBluetoothNames); i++)
if (strcmp(name, kValidWiiRemoteBluetoothNames[i]) == 0)
return true;
return false;
}
}; // end of namespace

View File

@@ -95,7 +95,6 @@ private:
void ThreadFunc();
bool m_connected;
bool m_motion_plus_inside;
std::thread m_wiimote_thread;
Common::FifoQueue<Report> m_read_reports;
Common::FifoQueue<Report> m_write_reports;
@@ -114,6 +113,8 @@ void StateChange(EMUSTATE_CHANGE newState);
int FindWiimotes(Wiimote** wm, int max_wiimotes);
bool IsValidBluetoothName(const char* name);
}; // WiimoteReal
#endif

View File

@@ -32,7 +32,14 @@
#define WM_OUTPUT_CHANNEL 0x11
#define WM_INPUT_CHANNEL 0x13
// The 4 most significant bits of the first byte of an outgoing command must be
// 0x50 if sending on the command channel and 0xA0 if sending on the interrupt
// channel. On Mac we use interrupt channel; on Windows/Linux, command.
#ifndef __APPLE__
#define WM_SET_REPORT 0x50
#else
#define WM_SET_REPORT 0xA0
#endif
// Commands
#define WM_CMD_RUMBLE 0x10

View File

@@ -69,8 +69,13 @@ TDeviceMap g_DeviceMap;
// STATE_TO_SAVE
typedef std::map<u32, std::string> TFileNameMap;
TFileNameMap g_FileNameMap;
u32 g_LastDeviceID;
#define IPC_MAX_FDS 0x18
#define ES_MAX_COUNT 2
IWII_IPC_HLE_Device* g_FdMap[IPC_MAX_FDS];
bool es_inuse[ES_MAX_COUNT];
IWII_IPC_HLE_Device* es_handles[ES_MAX_COUNT];
typedef std::deque<u32> ipc_msg_queue;
static ipc_msg_queue request_queue; // ppc -> arm
@@ -79,14 +84,28 @@ static ipc_msg_queue reply_queue; // arm -> ppc
void Init()
{
_dbg_assert_msg_(WII_IPC_HLE, g_DeviceMap.empty(), "DeviceMap isnt empty on init");
u32 i;
for (i=0; i<IPC_MAX_FDS; i++)
{
g_FdMap[i] = NULL;
}
u32 i = IPC_FIRST_HARDWARE_ID;
i = 0;
// Build hardware devices
g_DeviceMap[i] = new CWII_IPC_HLE_Device_usb_oh1_57e_305(i, std::string("/dev/usb/oh1/57e/305")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stm_immediate(i, std::string("/dev/stm/immediate")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stm_eventhook(i, std::string("/dev/stm/eventhook")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_fs(i, std::string("/dev/fs")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_es(i, std::string("/dev/es")); i++;
// IOS allows two ES devices at a time<
u32 j;
for (j=0; j<ES_MAX_COUNT; j++)
{
g_DeviceMap[i] = es_handles[j] = new CWII_IPC_HLE_Device_es(i, std::string("/dev/es")); i++;
es_inuse[j] = false;
}
g_DeviceMap[i] = new CWII_IPC_HLE_Device_di(i, std::string("/dev/di")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_kd_request(i, std::string("/dev/net/kd/request")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_kd_time(i, std::string("/dev/net/kd/time")); i++;
@@ -99,13 +118,24 @@ void Init()
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, std::string("/dev/sdio/slot1")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, std::string("/dev/usb/hid")); i++;
g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, std::string("/dev/usb/oh1")); i++;
g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, std::string("_Unimplemented_Device_"));
g_LastDeviceID = IPC_FIRST_FILEIO_ID;
g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, std::string("_Unimplemented_Device_")); i++;
}
void Reset(bool _bHard)
{
u32 i;
for (i=0; i<IPC_MAX_FDS; i++)
{
if (g_FdMap[i] != NULL && !g_FdMap[i]->IsHardware())
{
// close all files and delete their resources
g_FdMap[i]->Close(0, true);
delete g_FdMap[i];
}
g_FdMap[i] = NULL;
}
TDeviceMap::iterator itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
@@ -114,21 +144,17 @@ void Reset(bool _bHard)
// Force close
itr->second->Close(0, true);
// Hardware should not be deleted unless it is a hard reset
if (_bHard || !itr->second->IsHardware())
if (_bHard)
delete itr->second;
}
++itr;
}
// Skip hardware devices if not a hard reset
itr = (_bHard) ? g_DeviceMap.begin() : g_DeviceMap.lower_bound(IPC_FIRST_FILEIO_ID);
// Erase devices
g_DeviceMap.erase(itr, g_DeviceMap.end());
g_FileNameMap.clear();
if (_bHard)
{
g_DeviceMap.erase(g_DeviceMap.begin(), g_DeviceMap.end());
}
request_queue.clear();
reply_queue.clear();
g_LastDeviceID = IPC_FIRST_FILEIO_ID;
}
void Shutdown()
@@ -138,41 +164,53 @@ void Shutdown()
void SetDefaultContentFile(const std::string& _rFilename)
{
CWII_IPC_HLE_Device_es* pDevice =
(CWII_IPC_HLE_Device_es*)AccessDeviceByID(GetDeviceIDByName(std::string("/dev/es")));
if (pDevice)
pDevice->LoadWAD(_rFilename);
TDeviceMap::const_iterator itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
if (itr->second && itr->second->GetDeviceName().find(std::string("/dev/es")) == 0)
{
((CWII_IPC_HLE_Device_es*)itr->second)->LoadWAD(_rFilename);
}
++itr;
}
}
void ES_DIVerify(u8 *_pTMD, u32 _sz)
{
CWII_IPC_HLE_Device_es* pDevice =
(CWII_IPC_HLE_Device_es*)AccessDeviceByID(GetDeviceIDByName(std::string("/dev/es")));
if (pDevice)
pDevice->ES_DIVerify(_pTMD, _sz);
else
ERROR_LOG(WII_IPC_ES, "DIVerify called but /dev/es is not available");
CWII_IPC_HLE_Device_es::ES_DIVerify(_pTMD, _sz);
}
void SDIO_EventNotify()
{
CWII_IPC_HLE_Device_sdio_slot0 *pDevice =
(CWII_IPC_HLE_Device_sdio_slot0*)AccessDeviceByID(GetDeviceIDByName(std::string("/dev/sdio/slot0")));
(CWII_IPC_HLE_Device_sdio_slot0*)GetDeviceByName(std::string("/dev/sdio/slot0"));
if (pDevice)
pDevice->EventNotify();
}
int getFreeDeviceId()
{
u32 i;
for (i=0; i<IPC_MAX_FDS; i++)
{
if (g_FdMap[i] == NULL)
{
return i;
}
}
return -1;
}
int GetDeviceIDByName(const std::string& _rDeviceName)
IWII_IPC_HLE_Device* GetDeviceByName(const std::string& _rDeviceName)
{
TDeviceMap::const_iterator itr = g_DeviceMap.begin();
while(itr != g_DeviceMap.end())
while (itr != g_DeviceMap.end())
{
if (itr->second->GetDeviceName() == _rDeviceName)
return itr->first;
if (itr->second && itr->second->GetDeviceName() == _rDeviceName)
return itr->second;
++itr;
}
return -1;
return NULL;
}
IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID)
@@ -180,17 +218,7 @@ IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID)
if (g_DeviceMap.find(_ID) != g_DeviceMap.end())
return g_DeviceMap[_ID];
return NULL;
}
void DeleteDeviceByID(u32 ID)
{
IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(ID);
if (pDevice)
delete pDevice;
g_DeviceMap.erase(ID);
g_FileNameMap.erase(ID);
return NULL;
}
// This is called from ExecuteCommand() COMMAND_OPEN_DEVICE
@@ -208,60 +236,86 @@ IWII_IPC_HLE_Device* CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName
void DoState(PointerWrap &p)
{
p.Do(g_LastDeviceID);
p.Do(request_queue);
p.Do(reply_queue);
if (p.GetMode() == PointerWrap::MODE_READ)
{
TFileNameMap::const_iterator itr;
// Delete file Handles
itr = g_FileNameMap.begin();
while (itr != g_FileNameMap.end())
{
TDeviceMap::const_iterator devitr = g_DeviceMap.find(itr->first);
if (devitr != g_DeviceMap.end())
TDeviceMap::const_iterator itr;
itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
if (itr->second->IsHardware())
{
if (devitr->second)
delete devitr->second;
g_DeviceMap.erase(itr->first);
itr->second->DoState(p);
}
++itr;
}
// Load file names
p.Do(g_FileNameMap);
// Rebuild file handles
itr = g_FileNameMap.begin();
while (itr != g_FileNameMap.end())
}
if (p.GetMode() == PointerWrap::MODE_READ)
{
u32 i;
for (i=0; i<IPC_MAX_FDS; i++)
{
g_DeviceMap[itr->first] = new CWII_IPC_HLE_Device_FileIO(itr->first, itr->second);
++itr;
u32 exists;
p.Do(exists);
if (exists)
{
u32 isHw;
p.Do(isHw);
if (isHw)
{
u32 hwId;
p.Do(hwId);
g_FdMap[i] = AccessDeviceByID(hwId);
}
else
{
g_FdMap[i] = new CWII_IPC_HLE_Device_FileIO(i, "");
g_FdMap[i]->DoState(p);
}
}
else
{
g_FdMap[i] = NULL;
}
}
for (i=0; i<ES_MAX_COUNT; i++)
{
p.Do(es_inuse[i]);
u32 handleID = es_handles[i]->GetDeviceID();
p.Do(handleID);
es_handles[i] = AccessDeviceByID(handleID);
}
}
else
{
p.Do(g_FileNameMap);
}
p.Do(request_queue);
p.Do(reply_queue);
TDeviceMap::const_iterator itr;
//first, all the real devices
//(because we need fs to be deserialized first)
itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
if (itr->second->IsHardware())
itr->second->DoState(p);
++itr;
}
//then all the files
itr = g_DeviceMap.begin();
while (itr != g_DeviceMap.end())
{
if (!itr->second->IsHardware())
itr->second->DoState(p);
++itr;
u32 i;
for (i=0; i<IPC_MAX_FDS; i++)
{
u32 exists = g_FdMap[i] ? 1 : 0;
p.Do(exists);
if (exists)
{
u32 isHw = g_FdMap[i]->IsHardware() ? 1 : 0;
p.Do(isHw);
if (isHw)
{
u32 hwId = g_FdMap[i]->GetDeviceID();
p.Do(hwId);
}
else
{
g_FdMap[i]->DoState(p);
}
}
}
for (i=0; i<ES_MAX_COUNT; i++)
{
p.Do(es_inuse[i]);
u32 handleID = es_handles[i]->GetDeviceID();
p.Do(handleID);
}
}
}
@@ -270,67 +324,110 @@ void ExecuteCommand(u32 _Address)
bool CmdSuccess = false;
ECommandType Command = static_cast<ECommandType>(Memory::Read_U32(_Address));
int DeviceID = Memory::Read_U32(_Address + 8);
IWII_IPC_HLE_Device* pDevice = AccessDeviceByID(DeviceID);
volatile int DeviceID = Memory::Read_U32(_Address + 8);
INFO_LOG(WII_IPC_HLE, "-->> Execute Command Address: 0x%08x (code: %x, device: %x) ", _Address, Command, DeviceID);
IWII_IPC_HLE_Device* pDevice = (DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? g_FdMap[DeviceID] : NULL;
INFO_LOG(WII_IPC_HLE, "-->> Execute Command Address: 0x%08x (code: %x, device: %x) %p", _Address, Command, DeviceID, pDevice);
switch (Command)
{
case COMMAND_OPEN_DEVICE:
{
// Create a new HLE device. The Mode and DeviceName is given to us but we
// generate a DeviceID to be used for access to this device until it is Closed.
std::string DeviceName;
Memory::GetString(DeviceName, Memory::Read_U32(_Address + 0xC));
{
u32 Mode = Memory::Read_U32(_Address + 0x10);
DeviceID = getFreeDeviceId();
std::string DeviceName;
Memory::GetString(DeviceName, Memory::Read_U32(_Address + 0xC));
u32 Mode = Memory::Read_U32(_Address + 0x10);
DeviceID = GetDeviceIDByName(DeviceName);
// check if a device with this name has been created already
if (DeviceName.find("/dev/") == std::string::npos || DeviceID == -1)
{
if (DeviceName.find("/dev/") == 0)
WARN_LOG(WII_IPC_HLE, "Tried to open %s as %d", DeviceName.c_str(), DeviceID);
if (DeviceID >= 0)
{
if (DeviceName.find("/dev/es") == 0)
{
u32 j;
for (j=0; j<ES_MAX_COUNT; j++)
{
WARN_LOG(WII_IPC_HLE, "Unimplemented device: %s", DeviceName.c_str());
if (!es_inuse[j])
{
es_inuse[j] = true;
g_FdMap[DeviceID] = es_handles[j];
CmdSuccess = es_handles[j]->Open(_Address, Mode);
Memory::Write_U32(DeviceID, _Address+4);
break;
}
}
if (j == ES_MAX_COUNT)
{
Memory::Write_U32(FS_EESEXHAUSTED, _Address + 4);
CmdSuccess = true;
}
pDevice = AccessDeviceByID(GetDeviceIDByName(std::string("_Unimplemented_Device_")));
}
else if (DeviceName.find("/dev/") == 0)
{
pDevice = GetDeviceByName(DeviceName);
if (pDevice)
{
g_FdMap[DeviceID] = pDevice;
CmdSuccess = pDevice->Open(_Address, Mode);
INFO_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
Memory::Write_U32(DeviceID, _Address+4);
}
else
{
// create new file handle
u32 CurrentDeviceID = g_LastDeviceID;
pDevice = CreateFileIO(CurrentDeviceID, DeviceName);
g_DeviceMap[CurrentDeviceID] = pDevice;
g_FileNameMap[CurrentDeviceID] = DeviceName;
g_LastDeviceID++;
CmdSuccess = pDevice->Open(_Address, Mode);
INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), CurrentDeviceID, Mode);
WARN_LOG(WII_IPC_HLE, "Unimplemented device: %s", DeviceName.c_str());
Memory::Write_U32(FS_ENOENT, _Address+4);
CmdSuccess = true;
}
}
else
{
// F|RES: prolly the re-open is just a mode change
pDevice = AccessDeviceByID(DeviceID);
}
else
{
IWII_IPC_HLE_Device* pDevice = CreateFileIO(DeviceID, DeviceName);
CmdSuccess = pDevice->Open(_Address, Mode);
INFO_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
}
}
break;
INFO_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
if (Memory::Read_U32(_Address + 4) == DeviceID)
{
g_FdMap[DeviceID] = pDevice;
}
else
{
delete pDevice;
}
}
}
else
{
Memory::Write_U32(FS_EFDEXHAUSTED, _Address + 4);
CmdSuccess = true;
}
break;
}
case COMMAND_CLOSE_DEVICE:
if (pDevice)
{
if (pDevice)
{
CmdSuccess = pDevice->Close(_Address);
u32 j;
for (j=0; j<ES_MAX_COUNT; j++)
{
if (es_handles[j] == g_FdMap[DeviceID])
{
es_inuse[j] = false;
}
}
g_FdMap[DeviceID] = NULL;
// Don't delete hardware
if (!pDevice->IsHardware())
DeleteDeviceByID(DeviceID);
delete pDevice;
}
else
{
@@ -338,50 +435,67 @@ void ExecuteCommand(u32 _Address)
CmdSuccess = true;
}
break;
}
case COMMAND_READ:
{
if (pDevice)
{
CmdSuccess = pDevice->Read(_Address);
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
CmdSuccess = true;
}
break;
}
case COMMAND_WRITE:
{
if (pDevice)
{
CmdSuccess = pDevice->Write(_Address);
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
CmdSuccess = true;
}
break;
}
case COMMAND_SEEK:
{
if (pDevice)
{
CmdSuccess = pDevice->Seek(_Address);
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
CmdSuccess = true;
}
break;
}
case COMMAND_IOCTL:
{
if (pDevice)
{
CmdSuccess = pDevice->IOCtl(_Address);
}
break;
}
case COMMAND_IOCTLV:
{
if (pDevice)
{
CmdSuccess = pDevice->IOCtlV(_Address);
}
break;
}
default:
{
_dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown IPC Command %i (0x%08x)", Command, _Address);
break;
}
}
// It seems that the original hardware overwrites the command after it has been
@@ -453,9 +567,10 @@ void Update()
void UpdateDevices()
{
// Check if a hardware device must be updated
TDeviceMap::const_iterator itrEnd = g_DeviceMap.lower_bound(IPC_FIRST_FILEIO_ID);
for (TDeviceMap::const_iterator itr = g_DeviceMap.begin(); itr != itrEnd; ++itr) {
if (itr->second->IsOpened() && itr->second->Update()) {
for (TDeviceMap::const_iterator itr = g_DeviceMap.begin(); itr != g_DeviceMap.end(); ++itr)
{
if (itr->second->IsOpened() && itr->second->Update())
{
break;
}
}

View File

@@ -25,9 +25,9 @@ class IWII_IPC_HLE_Device;
namespace WII_IPC_HLE_Interface
{
#define IPC_FIRST_HARDWARE_ID 0 // first IPC device ID
#define IPC_FIRST_FILEIO_ID 33 // first IPC file ID
#define IPC_FIRST_ID 0x00 // first IPC device ID
#define IPC_MAX_FILES 0x10 // first IPC file ID
// Init
void Init();
@@ -46,14 +46,13 @@ void ES_DIVerify(u8 *_pTMD, u32 _sz);
void SDIO_EventNotify();
int GetDeviceIDByName(const std::string& _rDeviceName);
IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID);
void DeleteDeviceByID(u32 _ID);
IWII_IPC_HLE_Device* CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName);
IWII_IPC_HLE_Device* GetDeviceByName(const std::string& _rDeviceName);
IWII_IPC_HLE_Device* AccessDeviceByID(u32 _ID);
int getFreeDeviceId();
// Update
void Update();

View File

@@ -39,7 +39,7 @@ class PointerWrap;
#define FS_ENOENT2 (u32)-106 // File not found
#define FS_ENFILE (u32)-107 // Too many fds open
#define FS_EFBIG (u32)-108 // max block count reached?
#define FS_ENFILE2 (u32)-109 // Too many fds open
#define FS_EFDEXHAUSTED (u32)-109 // Too many fds open
#define FS_ENAMELEN (u32)-110 // pathname is too long
#define FS_EFDOPEN (u32)-111 // FD is already open
#define FS_EIO2 (u32)-114 // returned on ECC error
@@ -47,6 +47,7 @@ class PointerWrap;
#define FS_EDIRDEPTH (u32)-116 // max directory depth exceeded
#define FS_EBUSY2 (u32)-118 // Resource busy
//#define FS_EFATAL (u32)-119 // fatal error not used by IOS as fatal ERROR
#define FS_EESEXHAUSTED (u32)-1016 // Max of 2 ES handles at a time
class IWII_IPC_HLE_Device
{

View File

@@ -428,6 +428,16 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32
break;
case DVDLowAudioBufferConfig:
/*
For more information: http://www.crazynation.org/GC/GC_DD_TECH/GCTech.htm
Upon Power up or reset , 2 commands must be issued for proper use of audio streaming:
DVDReadDiskID A8000040,00000000,00000020
DVDLowAudioBufferConfig E4xx00yy,00000000,00000020
xx=byte 8 [0 or 1] from the disk header retrieved from DVDReadDiskID
yy=0 (if xx=0) or 0xA (if xx=1)
*/
ERROR_LOG(WII_IPC_DVD, "DVDLowAudioBufferConfig");
break;

View File

@@ -28,7 +28,7 @@
static Common::replace_v replacements;
// This is used by several of the FileIO and /dev/fs/ functions
// This is used by several of the FileIO and /dev/fs functions
std::string HLE_IPC_BuildFilename(const char* _pFilename, int _size)
{
std::string path_full = File::GetUserPath(D_WIIROOT_IDX);
@@ -128,7 +128,7 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
// The file must exist before we can open it
// It should be created by ISFS_CreateFile, not here
if(File::Exists(m_Filename))
if (File::Exists(m_Filename))
{
INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s == %08X)", m_Name.c_str(), Modes[_Mode], _Mode);
ReturnValue = m_DeviceID;
@@ -146,28 +146,31 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode)
}
bool CWII_IPC_HLE_Device_FileIO::OpenFile()
{
switch(m_Mode)
switch (m_Mode)
{
case ISFS_OPEN_READ:
{
m_pFileHandle.Open(m_Filename, "rb");
break;
// "r+b" is technically wrong, but OPEN_WRITE should not truncate the file as "wb" does.
}
case ISFS_OPEN_WRITE:
{
m_pFileHandle.Open(m_Filename, "r+b");
break;
}
case ISFS_OPEN_RW:
{
m_pFileHandle.Open(m_Filename, "r+b");
break;
}
default:
{
PanicAlertT("FileIO: Unknown open mode : 0x%02x", m_Mode);
break;
}
}
return m_pFileHandle.IsOpen();
}
@@ -178,21 +181,21 @@ void CWII_IPC_HLE_Device_FileIO::CloseFile()
bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
{
u32 ReturnValue = FS_RESULT_FATAL;
const s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
const s32 Mode = Memory::Read_U32(_CommandAddress + 0x10);
u32 ReturnValue = FS_RESULT_FATAL;
const s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
const s32 Mode = Memory::Read_U32(_CommandAddress + 0x10);
if(OpenFile())
if (OpenFile())
{
ReturnValue = FS_RESULT_FATAL;
const u64 fileSize = m_pFileHandle.GetSize();
const u64 fileSize = m_pFileHandle.GetSize();
INFO_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08llx)", SeekPosition, Mode, m_Name.c_str(), fileSize);
switch(Mode){
switch (Mode){
case 0:
{
if(SeekPosition >=0 && SeekPosition <= fileSize)
if (SeekPosition >=0 && SeekPosition <= fileSize)
{
m_SeekPos = SeekPosition;
ReturnValue = m_SeekPos;
@@ -202,7 +205,7 @@ bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
case 1:
{
s32 wantedPos = SeekPosition+m_SeekPos;
if(wantedPos >=0 && wantedPos <= fileSize)
if (wantedPos >=0 && wantedPos <= fileSize)
{
m_SeekPos = wantedPos;
ReturnValue = m_SeekPos;
@@ -212,7 +215,7 @@ bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
case 2:
{
s32 wantedPos = fileSize+m_SeekPos;
if(wantedPos >=0 && wantedPos <= fileSize)
if (wantedPos >=0 && wantedPos <= fileSize)
{
m_SeekPos = wantedPos;
ReturnValue = m_SeekPos;
@@ -244,7 +247,7 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
const u32 Size = Memory::Read_U32(_CommandAddress + 0x10);
if(OpenFile())
if (OpenFile())
{
if (m_Mode == ISFS_OPEN_WRITE)
{
@@ -284,7 +287,7 @@ bool CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
const u32 Size = Memory::Read_U32(_CommandAddress + 0x10);
if(OpenFile())
if (OpenFile())
{
if (m_Mode == ISFS_OPEN_READ)
{
@@ -318,21 +321,14 @@ bool CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress)
#if defined(_DEBUG) || defined(DEBUGFAST)
DumpCommands(_CommandAddress);
#endif
const u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
const u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
u32 ReturnValue = 0;
//u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
//u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
//u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
//u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
// Return Value
u32 ReturnValue = 0; // no error
switch(Parameter)
switch (Parameter)
{
case ISFS_IOCTL_GETFILESTATS:
{
if(OpenFile())
if (OpenFile())
{
u32 m_FileLength = (u32)m_pFileHandle.GetSize();

View File

@@ -64,6 +64,8 @@
#include <openssl/sha.h>
#include <openssl/objects.h>
std::string CWII_IPC_HLE_Device_es::m_ContentFile;
CWII_IPC_HLE_Device_es::CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName)
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
, m_pContentLoader(NULL)
@@ -276,8 +278,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
m_ContentAccessMap[CFD].m_Position = 0;
m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(m_TitleID).GetContentByIndex(Index);
_dbg_assert_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL);
if (m_ContentAccessMap[CFD].m_pContent == NULL)
CFD = 0xffffffff; //TODO: what is the correct error value here?
@@ -775,21 +776,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
PC = DolLoader.GetEntryPoint() | 0x80000000;
IOSv = ContentLoader.GetIosVersion();
bSuccess = true;
// Reset the connection of all connected wiimotes
// ugly haxx
static CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < 4; i++)
{
if (s_Usb->m_WiiMotes[i].IsConnected())
{
s_Usb->m_WiiMotes[i].Activate(false);
s_Usb->m_WiiMotes[i].Activate(true);
}
else
{
s_Usb->m_WiiMotes[i].Activate(false);
}
}
}
}
}
@@ -802,8 +789,32 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
IOSv = TitleID & 0xffff;
}
if (!bSuccess)
{
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);
}
else
{
std::string tContentFile(m_ContentFile.c_str());
WII_IPC_HLE_Interface::Reset(true);
WII_IPC_HLE_Interface::Init();
static CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < s_Usb->m_WiiMotes.size(); i++)
{
if (s_Usb->m_WiiMotes[i].IsConnected())
{
s_Usb->m_WiiMotes[i].Activate(false);
s_Usb->m_WiiMotes[i].Activate(true);
}
else
{
s_Usb->m_WiiMotes[i].Activate(false);
}
}
WII_IPC_HLE_Interface::SetDefaultContentFile(tContentFile);
}
// Pass the "#002 check"
// Apploader should write the IOS version and revision to 0x3140, and compare it
// to 0x3188 to pass the check, but we don't do it, and i don't know where to read the IOS rev...

View File

@@ -37,7 +37,7 @@ public:
virtual bool Close(u32 _CommandAddress, bool _bForce);
virtual bool IOCtlV(u32 _CommandAddress);
u32 ES_DIVerify(u8 *_pTMD, u32 _sz);
static u32 ES_DIVerify(u8 *_pTMD, u32 _sz);
private:
enum
@@ -135,7 +135,7 @@ private:
u64 m_TitleID;
u32 AccessIdentID;
// This should only be cleared on power reset
std::string m_ContentFile;
static std::string m_ContentFile;
static u8 *keyTable[11];

View File

@@ -304,7 +304,7 @@ bool BeginRecordingInput(int controllers)
g_rerecords = 0;
g_playMode = MODE_RECORDING;
delete tmpInput;
delete [] tmpInput;
tmpInput = new u8[MAX_DTM_LENGTH];
g_currentByte = g_totalBytes = 0;
@@ -627,6 +627,10 @@ void LoadInput(const char *filename)
if (!g_bReadOnly)
{
if (g_rerecords > tmpHeader.numRerecords)
{
tmpHeader.numRerecords = g_rerecords;
}
tmpHeader.numRerecords++;
t_record.Seek(0, SEEK_SET);
t_record.WriteArray(&tmpHeader, 1);
@@ -653,7 +657,7 @@ void LoadInput(const char *filename)
g_totalInputCount = tmpHeader.inputCount;
g_totalBytes = totalSavedBytes;
delete tmpInput;
delete [] tmpInput;
tmpInput = new u8[MAX_DTM_LENGTH];
t_record.ReadArray(tmpInput, (size_t)g_totalBytes);
}
@@ -707,7 +711,7 @@ void LoadInput(const char *filename)
break;
}
}
delete movInput;
delete [] movInput;
}
}
t_record.Close();

View File

@@ -181,7 +181,7 @@ union UGeckoInstruction
u32 : 11;
u32 CRBB : 5;
u32 CRBA : 5;
u32 CRBD : 5;
u32 CRBD : 5;
u32 : 6;
};
@@ -235,9 +235,9 @@ union UGeckoInstruction
};
struct
{
u32 : 17;
u32 FM : 8;
u32 : 7;
u32 : 17;
u32 FM : 8;
u32 : 7;
};
// paired
@@ -247,8 +247,8 @@ union UGeckoInstruction
u32 Ix : 3;
u32 Wx : 1;
u32 : 1;
u32 I : 3;
u32 W : 1;
u32 I : 3;
u32 W : 1;
u32 : 16;
};
@@ -319,7 +319,7 @@ union UReg_XER
u32 Hex;
UReg_XER(u32 _hex) { Hex = _hex; }
UReg_XER() { Hex = 0; }
UReg_XER() { Hex = 0; }
};
// Machine State Register
@@ -351,7 +351,7 @@ union UReg_MSR
u32 Hex;
UReg_MSR(u32 _hex) { Hex = _hex; }
UReg_MSR() { Hex = 0; }
UReg_MSR() { Hex = 0; }
};
// Floating Point Status and Control Register
@@ -487,13 +487,47 @@ union UReg_SPR1
u32 Hex;
struct
{
u32 htaborg : 16;
u32 : 7;
u32 htabmask : 9;
u32 htaborg : 16;
u32 : 7;
u32 htabmask : 9;
};
};
// MMCR0 - Monitor Mode Control Register 0 format
union UReg_MMCR0
{
u32 Hex;
struct
{
u32 PMC2SELECT : 6;
u32 PMC1SELECT : 7;
u32 PMCTRIGGER : 1;
u32 PMCINTCONTROL : 1;
u32 PMC1INTCONTROL : 1;
u32 THRESHOLD : 6;
u32 INTONBITTRANS : 1;
u32 RTCSELECT : 2;
u32 DISCOUNT : 1;
u32 ENINT : 1;
u32 DMR : 1;
u32 DMS : 1;
u32 DU : 1;
u32 DP : 1;
u32 DIS : 1;
};
};
// MMCR1 - Monitor Mode Control Register 1 format
union UReg_MMCR1
{
u32 Hex;
struct
{
u32 : 22;
u32 PMC4SELECT : 5;
u32 PMC3SELECT : 5;
};
};
// Write Pipe Address Register
union UReg_WPAR
@@ -516,7 +550,7 @@ union UReg_DMAU
struct
{
u32 DMA_LEN_U : 5;
u32 MEM_ADDR : 27;
u32 MEM_ADDR : 27;
};
u32 Hex;
@@ -533,7 +567,7 @@ union UReg_DMAL
u32 DMA_T : 1;
u32 DMA_LEN_L : 2;
u32 DMA_LD : 1;
u32 LC_ADDR : 27;
u32 LC_ADDR : 27;
};
u32 Hex;
@@ -545,11 +579,11 @@ union UReg_BAT_Up
{
struct
{
u32 VP : 1;
u32 VS : 1;
u32 VP : 1;
u32 VS : 1;
u32 BL : 11; // Block length (aka block size mask)
u32 : 4;
u32 BEPI : 15;
u32 BEPI : 15;
};
u32 Hex;
@@ -561,8 +595,8 @@ union UReg_BAT_Lo
{
struct
{
u32 PP : 2;
u32 : 1;
u32 PP : 2;
u32 : 1;
u32 WIMG : 4;
u32 : 10;
u32 BRPN : 15; // Physical Block Number
@@ -586,7 +620,7 @@ union UReg_PTE
u64 WIMG : 4;
u64 C : 1;
u64 R : 1;
u64 : 3;
u64 : 3;
u64 RPN : 20;
};
@@ -623,16 +657,16 @@ enum
// Special purpose register indices
enum
{
SPR_XER = 1,
SPR_XER = 1,
SPR_LR = 8,
SPR_CTR = 9,
SPR_DSISR = 18,
SPR_DAR = 19,
SPR_DAR = 19,
SPR_DEC = 22,
SPR_SDR = 25,
SPR_SDR = 25,
SPR_SRR0 = 26,
SPR_SRR1 = 27,
SPR_TL = 268,
SPR_TL = 268,
SPR_TU = 269,
SPR_TL_W = 284,
SPR_TU_W = 285,
@@ -669,7 +703,17 @@ enum
SPR_ECID_U = 924,
SPR_ECID_M = 925,
SPR_ECID_L = 926,
SPR_L2CR = 1017
SPR_L2CR = 1017,
SPR_UMMCR0 = 936,
SPR_MMCR0 = 952,
SPR_PMC1 = 953,
SPR_PMC2 = 954,
SPR_UMMCR1 = 940,
SPR_MMCR1 = 956,
SPR_PMC3 = 957,
SPR_PMC4 = 958,
};
// Exceptions
@@ -679,8 +723,9 @@ enum
#define EXCEPTION_DSI 0x00000008
#define EXCEPTION_ISI 0x00000010
#define EXCEPTION_ALIGNMENT 0x00000020
#define EXCEPTION_FPU_UNAVAILABLE 0x00000040
#define EXCEPTION_FPU_UNAVAILABLE 0x00000040
#define EXCEPTION_PROGRAM 0x00000080
#define EXCEPTION_PERFORMANCE_MONITOR 0x00000100
inline s32 SignExt16(s16 x) {return (s32)(s16)x;}
inline s32 SignExt26(u32 x) {return x & 0x2000000 ? (s32)(x | 0xFC000000) : (s32)(x);}

View File

@@ -42,10 +42,6 @@ using namespace MathUtil;
void UpdateSSEState();
#ifdef _MSC_VER
#pragma float_control(precise, on, push)
#endif
// Extremely rare - actually, never seen.
// Star Wars : Rogue Leader spams that at some point :|
void Interpreter::Helper_UpdateCR1(double _fValue)
@@ -518,8 +514,4 @@ void Interpreter::fsqrtx(UGeckoInstruction _inst)
rPS0(_inst.FD) = sqrt(b);
UpdateFPRF(rPS0(_inst.FD));
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
#ifdef _MSC_VER
#pragma float_control(pop)
#endif
}

View File

@@ -363,28 +363,34 @@ void Interpreter::dcbf(UGeckoInstruction _inst)
{
NPC = PC + 12;
}*/
// Invalidate the icache on dcbf
// Invalidate the jit block cache on dcbf
if (jit)
{
u32 address = Helper_Get_EA_X(_inst);
jit->GetBlockCache()->InvalidateICache(address & ~0x1f);
jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32);
}
}
void Interpreter::dcbi(UGeckoInstruction _inst)
{
// Removes a block from data cache. Since we don't emulate the data cache, we don't need to do anything to the data cache
// However, we invalidate the icache on dcbi
// However, we invalidate the jit block cache on dcbi
if (jit)
{
u32 address = Helper_Get_EA_X(_inst);
jit->GetBlockCache()->InvalidateICache(address & ~0x1f);
jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32);
}
}
void Interpreter::dcbst(UGeckoInstruction _inst)
{
// Cache line flush. Since we don't emulate the data cache, we don't need to do anything.
// Invalidate the jit block cache on dcbst in case new code has been loaded via the data cache
if (jit)
{
u32 address = Helper_Get_EA_X(_inst);
jit->GetBlockCache()->InvalidateICache(address & ~0x1f, 32);
}
}
void Interpreter::dcbt(UGeckoInstruction _inst)

View File

@@ -41,6 +41,10 @@
#include "JitAsm.h"
#include "JitRegCache.h"
#include "Jit64_Tables.h"
#include "HW/ProcessorInterface.h"
#if defined(_DEBUG) || defined(DEBUGFAST)
#include "PowerPCDisasm.h"
#endif
using namespace Gen;
using namespace PowerPC;
@@ -187,12 +191,7 @@ void Jit64::Init()
else
jo.enableBlocklink = !Core::g_CoreStartupParameter.bMMU;
}
#ifdef _M_X64
jo.enableFastMem = Core::g_CoreStartupParameter.bUseFastMem;
#else
jo.enableFastMem = false;
#endif
jo.assumeFPLoadFromMem = Core::g_CoreStartupParameter.bUseFastMem;
jo.fpAccurateFcmp = true; // Fallback to Interpreter
jo.optimizeGatherPipe = true;
jo.fastInterrupts = false;
@@ -296,6 +295,10 @@ void Jit64::Cleanup()
{
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
ABI_CallFunction((void *)&GPFifo::CheckGatherPipe);
// SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time.
if (MMCR0.Hex || MMCR1.Hex)
ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst);
}
void Jit64::WriteExit(u32 destination, int exit_num)
@@ -334,16 +337,31 @@ void Jit64::WriteExitDestInEAX()
void Jit64::WriteRfiExitDestInEAX()
{
MOV(32, M(&PC), R(EAX));
MOV(32, M(&NPC), R(EAX));
Cleanup();
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
JMP(asm_routines.testExceptions, true);
JMP(asm_routines.dispatcher, true);
}
void Jit64::WriteExceptionExit()
{
Cleanup();
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
JMP(asm_routines.testExceptions, true);
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
void Jit64::WriteExternalExceptionExit()
{
Cleanup();
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExternalExceptions));
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
void STACKALIGN Jit64::Run()
@@ -412,15 +430,18 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
// Comment out the following to disable breakpoints (speed-up)
blockSize = 1;
broken_block = true;
Trace();
if (!Profiler::g_ProfileBlocks)
{
if (GetState() == CPU_STEPPING)
blockSize = 1;
Trace();
}
}
if (em_address == 0)
{
Core::SetState(Core::CORE_PAUSE);
PanicAlert("ERROR: Compiling at 0. LR=%08x CTR=%08x", LR, CTR);
// Memory exception occurred during instruction fetch
memory_exception = true;
}
if (Core::g_CoreStartupParameter.bMMU && (em_address & JIT_ICACHE_VMEM_BIT))
@@ -433,12 +454,15 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
}
int size = 0;
js.firstFPInstructionFound = false;
js.isLastInstruction = false;
js.blockStart = em_address;
js.fifoBytesThisBlock = 0;
js.curBlock = b;
js.block_flags = 0;
js.cancel = false;
jit->js.numLoadStoreInst = 0;
jit->js.numFloatingPointInst = 0;
// Analyze the block, collect all instructions it is made of (including inlining,
// if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
@@ -470,16 +494,6 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (ImHereDebug)
ABI_CallFunction((void *)&ImHere); //Used to get a trace of the last few blocks before a crash, sometimes VERY useful
if (js.fpa.any)
{
// This block uses FPU - needs to add FP exception bailout
TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); //Test FP enabled bit
FixupBranch b1 = J_CC(CC_NZ);
MOV(32, M(&PC), Imm32(js.blockStart));
JMP(asm_routines.fpException, true);
SetJumpTarget(b1);
}
// Conditionally add profiling code.
if (Profiler::g_ProfileBlocks) {
ADD(32, M(&b->runCount), Imm8(1));
@@ -555,18 +569,62 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (!ops[i].skip)
{
if (js.memcheck && (opinfo->flags & FL_USE_FPU))
if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound)
{
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
//This instruction uses FPU - needs to add FP exception bailout
TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); // Test FP enabled bit
FixupBranch b1 = J_CC(CC_NZ);
FixupBranch b1 = J_CC(CC_NZ, true);
// If a FPU exception occurs, the exception handler will read
// from PC. Update PC with the latest value in case that happens.
MOV(32, M(&PC), Imm32(ops[i].address));
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
JMP(asm_routines.fpException, true);
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
WriteExceptionExit();
SetJumpTarget(b1);
js.firstFPInstructionFound = true;
}
// Add an external exception check if the instruction writes to the FIFO.
if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end())
{
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
FixupBranch clearInt = J_CC(CC_NZ, true);
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
FixupBranch noExtException = J_CC(CC_Z, true);
TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000));
FixupBranch noExtIntEnable = J_CC(CC_Z, true);
TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH));
FixupBranch noCPInt = J_CC(CC_Z, true);
MOV(32, M(&PC), Imm32(ops[i].address));
WriteExternalExceptionExit();
SetJumpTarget(noCPInt);
SetJumpTarget(noExtIntEnable);
SetJumpTarget(noExtException);
SetJumpTarget(clearInt);
}
if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
MOV(32, M(&PC), Imm32(ops[i].address));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z);
WriteExit(ops[i].address, 0);
SetJumpTarget(noBreakpoint);
}
Jit64Tables::CompileInstruction(ops[i]);
@@ -578,7 +636,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
fpr.Flush(FLUSH_ALL);
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI));
FixupBranch noMemException = J_CC(CC_Z);
FixupBranch noMemException = J_CC(CC_Z, true);
// If a memory exception occurs, the exception handler will read
// from PC. Update PC with the latest value in case that happens.
@@ -586,6 +644,12 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
WriteExceptionExit();
SetJumpTarget(noMemException);
}
if (opinfo->flags & FL_LOADSTORE)
++jit->js.numLoadStoreInst;
if (opinfo->flags & FL_USE_FPU)
++jit->js.numFloatingPointInst;
}
#if defined(_DEBUG) || defined(DEBUGFAST)
@@ -596,7 +660,6 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
NOTICE_LOG(DYNA_REC, "Unflushed reg: %s", ppcInst);
}
#endif
if (js.skipnext) {
js.skipnext = false;
i++; // Skip next instruction
@@ -610,6 +673,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
{
// Address of instruction could not be translated
MOV(32, M(&NPC), Imm32(js.compilerPC));
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI));
// Remove the invalid instruction from the icache, forcing a recompile

View File

@@ -65,32 +65,6 @@
class Jit64 : public JitBase
{
private:
struct JitState
{
u32 compilerPC;
u32 next_compilerPC;
u32 blockStart;
bool cancel;
bool skipnext;
UGeckoInstruction next_inst; // for easy peephole opt.
int blockSize;
int instructionNumber;
int downcountAmount;
int block_flags;
bool isLastInstruction;
bool memcheck;
int fifoBytesThisBlock;
PPCAnalyst::BlockStats st;
PPCAnalyst::BlockRegStats gpa;
PPCAnalyst::BlockRegStats fpa;
PPCAnalyst::CodeOp *op;
JitBlock *curBlock;
};
GPRRegCache gpr;
FPURegCache fpr;
@@ -103,8 +77,6 @@ public:
Jit64() : code_buffer(32000) {}
~Jit64() {}
JitState js;
void Init();
void Shutdown();
@@ -143,6 +115,7 @@ public:
void WriteExit(u32 destination, int exit_num);
void WriteExitDestInEAX();
void WriteExceptionExit();
void WriteExternalExceptionExit();
void WriteRfiExitDestInEAX();
void WriteCallInterpreter(UGeckoInstruction _inst);
void Cleanup();

View File

@@ -210,7 +210,7 @@ static GekkoOPTemplate table31[] =
{824, &Jit64::srawix}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{24, &Jit64::slwx}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{54, &Jit64::DoNothing}, //"dcbst", OPTYPE_DCACHE, 0, 4}},
{54, &Jit64::Default}, //"dcbst", OPTYPE_DCACHE, 0, 4}},
{86, &Jit64::Default}, //"dcbf", OPTYPE_DCACHE, 0, 4}},
{246, &Jit64::DoNothing}, //"dcbtst", OPTYPE_DCACHE, 0, 1}},
{278, &Jit64::DoNothing}, //"dcbt", OPTYPE_DCACHE, 0, 1}},

View File

@@ -70,7 +70,7 @@ void Jit64AsmRoutineManager::Generate()
MOV(64, R(R15), Imm64((u64)jit->GetBlockCache()->GetCodePointers())); //It's below 2GB so 32 bits are good enough
#endif
const u8 *outerLoop = GetCodePtr();
outerLoop = GetCodePtr();
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
FixupBranch skipToRealDispatch = J(); //skip the sync and compare first time
@@ -81,12 +81,15 @@ void Jit64AsmRoutineManager::Generate()
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(PowerPC::CPU_STEPPING));
FixupBranch notStepping = J_CC(CC_Z);
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z);
ABI_PopAllCalleeSavedRegsAndAdjustStack();
RET();
SetJumpTarget(noBreakpoint);
SetJumpTarget(notStepping);
}
SetJumpTarget(skipToRealDispatch);
@@ -191,27 +194,17 @@ void Jit64AsmRoutineManager::Generate()
#endif
JMP(dispatcherNoCheck); // no point in special casing this
//FP blocks test for FPU available, jump here if false
fpException = AlignCode4();
LOCK();
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
MOV(32, R(EAX), M(&NPC));
MOV(32, M(&PC), R(EAX));
JMP(dispatcher, true);
SetJumpTarget(bail);
doTiming = GetCodePtr();
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
testExceptions = GetCodePtr();
testExternalExceptions = GetCodePtr();
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT | EXCEPTION_PERFORMANCE_MONITOR | EXCEPTION_DECREMENTER));
FixupBranch noExtException = J_CC(CC_Z);
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
MOV(32, R(EAX), M(&NPC));
MOV(32, M(&PC), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExternalExceptions));
SetJumpTarget(noExtException);
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
J_CC(CC_Z, outerLoop, true);

View File

@@ -266,7 +266,7 @@ void Jit64::reg_imm(UGeckoInstruction inst)
case 15:
if (a == 0) { // lis
// Merge with next instruction if loading a 32-bits immediate value (lis + addi, lis + ori)
if (!js.isLastInstruction) {
if (!js.isLastInstruction && !Core::g_CoreStartupParameter.bEnableDebugging) {
if ((js.next_inst.OPCD == 14) && (js.next_inst.RD == d) && (js.next_inst.RA == d)) { // addi
gpr.SetImmediate32(d, ((u32)inst.SIMM_16 << 16) + (u32)(s32)js.next_inst.SIMM_16);
js.downcountAmount++;

View File

@@ -151,7 +151,7 @@ void Jit64::lXXx(UGeckoInstruction inst)
// ! we must continue executing of the loop after exception handling, maybe there is still 0 in r0
//MOV(32, M(&PowerPC::ppcState.pc), Imm32(js.compilerPC));
JMP(asm_routines.testExceptions, true);
WriteExceptionExit();
SetJumpTarget(noIdle);
@@ -352,8 +352,8 @@ void Jit64::stX(UGeckoInstruction inst)
}
/* // TODO - figure out why Beyond Good and Evil hates this
#ifdef _M_X64
if (accessSize == 32 && !update && jo.enableFastMem)
#if defined(_WIN32) && defined(_M_X64)
if (accessSize == 32 && !update)
{
// Fast and daring - requires 64-bit
MOV(32, R(EAX), gpr.R(s));
@@ -405,10 +405,13 @@ void Jit64::stXx(UGeckoInstruction inst)
gpr.Lock(a, b, s);
gpr.FlushLockX(ECX, EDX);
if (inst.SUBOP10 & 32) {
if (inst.SUBOP10 & 32)
{
MEMCHECK_START
gpr.BindToRegister(a, true, true);
ADD(32, gpr.R(a), gpr.R(b));
MOV(32, R(EDX), gpr.R(a));
MEMCHECK_END
} else {
MOV(32, R(EDX), gpr.R(a));
ADD(32, R(EDX), gpr.R(b));
@@ -425,12 +428,6 @@ void Jit64::stXx(UGeckoInstruction inst)
MOV(32, R(ECX), gpr.R(s));
SafeWriteRegToReg(ECX, EDX, accessSize, 0);
//MEMCHECK_START
// TODO: Insert rA update code here
//MEMCHECK_END
gpr.UnlockAll();
gpr.UnlockAllX();
}
@@ -438,6 +435,9 @@ void Jit64::stXx(UGeckoInstruction inst)
// A few games use these heavily in video codecs.
void Jit64::lmw(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(LoadStore)
#ifdef _M_X64
gpr.FlushLockX(ECX);
MOV(32, R(EAX), Imm32((u32)(s32)inst.SIMM_16));
@@ -458,6 +458,9 @@ void Jit64::lmw(UGeckoInstruction inst)
void Jit64::stmw(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(LoadStore)
#ifdef _M_X64
gpr.FlushLockX(ECX);
MOV(32, R(EAX), Imm32((u32)(s32)inst.SIMM_16));

View File

@@ -62,14 +62,11 @@ void Jit64::lfs(UGeckoInstruction inst)
return;
}
s32 offset = (s32)(s16)inst.SIMM_16;
if (jo.assumeFPLoadFromMem)
{
UnsafeLoadToEAX(gpr.R(a), 32, offset, false);
}
else
{
SafeLoadToEAX(gpr.R(a), 32, offset, false);
}
#if defined(_WIN32) && defined(_M_X64)
UnsafeLoadToEAX(gpr.R(a), 32, offset, false);
#else
SafeLoadToEAX(gpr.R(a), 32, offset, false);
#endif
MEMCHECK_START
@@ -219,7 +216,7 @@ void Jit64::stfd(UGeckoInstruction inst)
MOVD_xmm(R(EAX), XMM0);
UnsafeWriteRegToReg(EAX, ABI_PARAM1, 32, 0);
}
FixupBranch exit = J();
FixupBranch exit = J(true);
SetJumpTarget(safe);
// Safe but slow routine
@@ -240,7 +237,14 @@ void Jit64::stfd(UGeckoInstruction inst)
fpr.UnlockAll();
}
// In Release on 32bit build,
// this seemed to cause a problem with PokePark2
// at start after talking to first pokemon,
// you run and smash a box, then he goes on about
// following him and then you cant do anything.
// I have enabled interpreter for this function
// in the mean time.
// Parlane
void Jit64::stfs(UGeckoInstruction inst)
{
INSTRUCTION_START

View File

@@ -93,6 +93,10 @@ void Jit64::mfspr(UGeckoInstruction inst)
case SPR_DEC:
case SPR_TL:
case SPR_TU:
case SPR_PMC1:
case SPR_PMC2:
case SPR_PMC3:
case SPR_PMC4:
Default(inst);
return;
default:
@@ -119,6 +123,7 @@ void Jit64::mtmsr(UGeckoInstruction inst)
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
WriteExit(js.compilerPC + 4, 0);
js.firstFPInstructionFound = false;
}
void Jit64::mfmsr(UGeckoInstruction inst)

View File

@@ -1212,7 +1212,7 @@ void IRBuilder::simplifyCommutative(unsigned Opcode, InstLoc& Op1, InstLoc& Op2)
}
bool IRBuilder::maskedValueIsZero(InstLoc Op1, InstLoc Op2) const {
return (~ComputeKnownZeroBits(Op1) & ~ComputeKnownZeroBits(Op1)) == 0;
return (~ComputeKnownZeroBits(Op1) & ~ComputeKnownZeroBits(Op2)) == 0;
}
// Returns I' if I == (0 - I')
@@ -1260,16 +1260,17 @@ static const std::string opcodeNames[] = {
"FResult_End", "StorePaired", "StoreSingle", "StoreDouble", "StoreFReg",
"FDCmpCR", "CInt16", "CInt32", "SystemCall", "RFIExit",
"InterpreterBranch", "IdleBranch", "ShortIdleLoop",
"FPExceptionCheckStart", "FPExceptionCheckEnd", "ISIException", "Tramp",
"BlockStart", "BlockEnd", "Int3",
"FPExceptionCheckStart", "FPExceptionCheckEnd", "ISIException", "ExtExceptionCheck",
"Tramp", "BlockStart", "BlockEnd", "Int3",
};
static const unsigned alwaysUsedList[] = {
InterpreterFallback, StoreGReg, StoreCR, StoreLink, StoreCTR, StoreMSR,
StoreGQR, StoreSRR, StoreCarry, StoreFPRF, Load8, Load16, Load32, Store8,
Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR,
BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop,
SystemCall, InterpreterBranch, RFIExit, FPExceptionCheckStart,
FPExceptionCheckEnd, ISIException, Int3, Tramp, Nop
SystemCall, InterpreterBranch, RFIExit, FPExceptionCheck,
DSIExceptionCheck, ISIException, ExtExceptionCheck, BreakPointCheck,
Int3, Tramp, Nop
};
static const unsigned extra8RegList[] = {
LoadGReg, LoadCR, LoadGQR, LoadFReg, LoadFRegDENToZero,

View File

@@ -165,10 +165,10 @@ enum Opcode {
ShortIdleLoop, // Idle loop seen in homebrew like wii mahjong,
// just a branch
// used for MMU, at least until someone
// used for exception checking, at least until someone
// has a better idea of integrating it
FPExceptionCheckStart, FPExceptionCheckEnd,
ISIException,
FPExceptionCheck, DSIExceptionCheck,
ISIException, ExtExceptionCheck, BreakPointCheck,
// "Opcode" representing a register too far away to
// reference directly; this is a size optimization
Tramp,
@@ -402,15 +402,21 @@ public:
InstLoc EmitSystemCall(InstLoc pc) {
return FoldUOp(SystemCall, pc);
}
InstLoc EmitFPExceptionCheckStart(InstLoc pc) {
return EmitUOp(FPExceptionCheckStart, pc);
InstLoc EmitFPExceptionCheck(InstLoc pc) {
return EmitUOp(FPExceptionCheck, pc);
}
InstLoc EmitFPExceptionCheckEnd(InstLoc pc) {
return EmitUOp(FPExceptionCheckEnd, pc);
InstLoc EmitDSIExceptionCheck(InstLoc pc) {
return EmitUOp(DSIExceptionCheck, pc);
}
InstLoc EmitISIException(InstLoc dest) {
return EmitUOp(ISIException, dest);
}
InstLoc EmitExtExceptionCheck(InstLoc pc) {
return EmitUOp(ExtExceptionCheck, pc);
}
InstLoc EmitBreakPointCheck(InstLoc pc) {
return EmitUOp(BreakPointCheck, pc);
}
InstLoc EmitRFIExit() {
return FoldZeroOp(RFIExit, 0);
}

View File

@@ -50,6 +50,7 @@ The register allocation is linear scan allocation.
#include "../../../../Common/Src/CPUDetect.h"
#include "MathUtil.h"
#include "../../Core.h"
#include "HW/ProcessorInterface.h"
static ThunkManager thunks;
@@ -758,9 +759,11 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
case RFIExit:
case InterpreterBranch:
case ShortIdleLoop:
case FPExceptionCheckStart:
case FPExceptionCheckEnd:
case FPExceptionCheck:
case DSIExceptionCheck:
case ISIException:
case ExtExceptionCheck:
case BreakPointCheck:
case Int3:
case Tramp:
// No liveness effects
@@ -1385,7 +1388,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
Jit->MOV(32, R(ECX), regLocForInst(RI, getOp2(I)));
RI.Jit->UnsafeWriteRegToReg(EAX, ECX, 32, 0);
}
FixupBranch exit = Jit->J();
FixupBranch exit = Jit->J(true);
Jit->SetJumpTarget(safe);
// Safe but slow routine
OpArg value = fregLocForInst(RI, getOp1(I));
@@ -1866,7 +1869,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
Jit->WriteRfiExitDestInOpArg(R(EAX));
break;
}
case FPExceptionCheckStart: {
case FPExceptionCheck: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
//This instruction uses FPU - needs to add FP exception bailout
Jit->TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); // Test FP enabled bit
@@ -1880,7 +1883,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
Jit->SetJumpTarget(b1);
break;
}
case FPExceptionCheckEnd: {
case DSIExceptionCheck: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI));
FixupBranch noMemException = Jit->J_CC(CC_Z);
@@ -1920,6 +1923,38 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
Jit->WriteExceptionExit();
break;
}
case ExtExceptionCheck: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
FixupBranch clearInt = Jit->J_CC(CC_NZ);
Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
FixupBranch noExtException = Jit->J_CC(CC_Z);
Jit->TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000));
FixupBranch noExtIntEnable = Jit->J_CC(CC_Z);
Jit->TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH));
FixupBranch noCPInt = Jit->J_CC(CC_Z);
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->WriteExceptionExit();
Jit->SetJumpTarget(noCPInt);
Jit->SetJumpTarget(noExtIntEnable);
Jit->SetJumpTarget(noExtException);
Jit->SetJumpTarget(clearInt);
break;
}
case BreakPointCheck: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
Jit->TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = Jit->J_CC(CC_Z);
Jit->WriteExit(InstLoc, 0);
Jit->SetJumpTarget(noBreakpoint);
break;
}
case Int3: {
Jit->INT3();
break;

View File

@@ -276,12 +276,6 @@ void JitIL::Init()
jo.enableBlocklink = !Core::g_CoreStartupParameter.bMMU;
}
#ifdef _M_X64
jo.enableFastMem = false;
#else
jo.enableFastMem = false;
#endif
jo.assumeFPLoadFromMem = Core::g_CoreStartupParameter.bUseFastMem;
jo.fpAccurateFcmp = false;
jo.optimizeGatherPipe = true;
jo.fastInterrupts = false;
@@ -396,6 +390,10 @@ void JitIL::Cleanup()
{
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
ABI_CallFunction((void *)&GPFifo::CheckGatherPipe);
// SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time.
if (MMCR0.Hex || MMCR1.Hex)
ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst);
}
void JitIL::WriteExit(u32 destination, int exit_num)
@@ -524,12 +522,19 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
// Comment out the following to disable breakpoints (speed-up)
blockSize = 1;
Trace();
if (!Profiler::g_ProfileBlocks)
{
if (GetState() == CPU_STEPPING)
blockSize = 1;
Trace();
}
}
if (em_address == 0)
PanicAlert("ERROR : Trying to compile at 0. LR=%08x", LR);
{
// Memory exception occurred during instruction fetch
memory_exception = true;
}
if (Core::g_CoreStartupParameter.bMMU && (em_address & JIT_ICACHE_VMEM_BIT))
{
@@ -546,6 +551,8 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
js.fifoBytesThisBlock = 0;
js.curBlock = b;
js.cancel = false;
jit->js.numLoadStoreInst = 0;
jit->js.numFloatingPointInst = 0;
// Analyze the block, collect all instructions it is made of (including inlining,
// if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
@@ -646,15 +653,31 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
{
if (js.memcheck && (opinfo->flags & FL_USE_FPU))
{
ibuild.EmitFPExceptionCheckStart(ibuild.EmitIntConst(ops[i].address));
ibuild.EmitFPExceptionCheck(ibuild.EmitIntConst(ops[i].address));
}
if (jit->js.fifoWriteAddresses.find(js.compilerPC) != jit->js.fifoWriteAddresses.end())
{
ibuild.EmitExtExceptionCheck(ibuild.EmitIntConst(ops[i].address));
}
if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{
ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address));
}
JitILTables::CompileInstruction(ops[i]);
if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
{
ibuild.EmitFPExceptionCheckEnd(ibuild.EmitIntConst(ops[i].address));
ibuild.EmitDSIExceptionCheck(ibuild.EmitIntConst(ops[i].address));
}
if (opinfo->flags & FL_LOADSTORE)
++jit->js.numLoadStoreInst;
if (opinfo->flags & FL_USE_FPU)
++jit->js.numFloatingPointInst;
}
}

View File

@@ -83,12 +83,15 @@ void JitILAsmRoutineManager::Generate()
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(PowerPC::CPU_STEPPING));
FixupBranch notStepping = J_CC(CC_Z);
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z);
ABI_PopAllCalleeSavedRegsAndAdjustStack();
RET();
SetJumpTarget(noBreakpoint);
SetJumpTarget(notStepping);
}
SetJumpTarget(skipToRealDispatch);
@@ -208,14 +211,14 @@ void JitILAsmRoutineManager::Generate()
doTiming = GetCodePtr();
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
testExceptions = GetCodePtr();
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
MOV(32, R(EAX), M(&NPC));
MOV(32, M(&PC), R(EAX));
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
J_CC(CC_Z, outerLoop, true);
//Landing pad for drec space

View File

@@ -493,6 +493,9 @@ void JitIL::srawx(UGeckoInstruction inst)
test = ibuild.EmitOr(val, mask2);
test = ibuild.EmitICmpUgt(test, mask);
ibuild.EmitStoreCarry(test);
if (inst.Rc)
ComputeRC(ibuild, val);
}
void JitIL::srawix(UGeckoInstruction inst)

View File

@@ -212,7 +212,7 @@ static GekkoOPTemplate table31[] =
{824, &JitIL::srawix}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{24, &JitIL::slwx}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{54, &JitIL::DoNothing}, //"dcbst", OPTYPE_DCACHE, 0, 4}},
{54, &JitIL::Default}, //"dcbst", OPTYPE_DCACHE, 0, 4}},
{86, &JitIL::Default}, //"dcbf", OPTYPE_DCACHE, 0, 4}},
{246, &JitIL::DoNothing}, //"dcbtst", OPTYPE_DCACHE, 0, 1}},
{278, &JitIL::DoNothing}, //"dcbt", OPTYPE_DCACHE, 0, 1}},

View File

@@ -40,12 +40,14 @@ public:
const u8 *enterCode;
const u8 *outerLoop;
const u8 *dispatcher;
const u8 *dispatcherNoCheck;
const u8 *dispatcherPcInEAX;
const u8 *fpException;
const u8 *testExceptions;
const u8 *testExternalExceptions;
const u8 *dispatchPcInEAX;
const u8 *doTiming;

View File

@@ -13,6 +13,8 @@
// If not, see http://www.gnu.org/licenses/
#include "JitBase.h"
#include "PowerPCDisasm.h"
#include "disasm.h"
JitBase *jit;

View File

@@ -28,8 +28,7 @@
#include "JitBackpatch.h" // for EmuCodeBlock
#include "JitAsmCommon.h"
#include "PowerPCDisasm.h"
#include "disasm.h"
#include <set>
#define JIT_OPCODE 0
@@ -42,10 +41,8 @@ protected:
struct JitOptions
{
bool optimizeStack;
bool assumeFPLoadFromMem;
bool enableBlocklink;
bool fpAccurateFcmp;
bool enableFastMem;
bool optimizeGatherPipe;
bool fastInterrupts;
bool accurateSinglePrecision;
@@ -60,11 +57,16 @@ protected:
int blockSize;
int instructionNumber;
int downcountAmount;
u32 numLoadStoreInst;
u32 numFloatingPointInst;
bool firstFPInstructionFound;
bool isLastInstruction;
bool forceUnsafeLoad;
bool memcheck;
bool skipnext;
bool broken_block;
int block_flags;
int fifoBytesThisBlock;
@@ -75,6 +77,8 @@ protected:
u8* rewriteStart;
JitBlock *curBlock;
std::set<u32> fifoWriteAddresses;
};
public:

View File

@@ -208,7 +208,11 @@ bool JitBlock::ContainsAddress(u32 em_address)
JitBlock &b = blocks[block_num];
b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress);
Memory::Write_Opcode_JIT(b.originalAddress, (JIT_OPCODE << 26) | block_num);
block_map[std::make_pair(b.originalAddress + 4 * b.originalSize - 1, b.originalAddress)] = block_num;
// Convert the logical address to a physical address for the block map
u32 pAddr = b.originalAddress & 0x1FFFFFFF;
block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num;
if (block_link)
{
for (int i = 0; i < 2; i++)
@@ -353,6 +357,24 @@ bool JitBlock::ContainsAddress(u32 em_address)
}
}
void JitBlockCache::UnlinkBlock(int i)
{
JitBlock &b = blocks[i];
std::map<u32, int>::iterator iter;
pair<multimap<u32, int>::iterator, multimap<u32, int>::iterator> ppp;
ppp = links_to.equal_range(b.originalAddress);
if (ppp.first == ppp.second)
return;
for (multimap<u32, int>::iterator iter2 = ppp.first; iter2 != ppp.second; ++iter2) {
JitBlock &sourceBlock = blocks[iter2->second];
for (int e = 0; e < 2; e++)
{
if (sourceBlock.exitAddress[e] == b.originalAddress)
sourceBlock.linkStatus[e] = false;
}
}
}
void JitBlockCache::DestroyBlock(int block_num, bool invalidate)
{
if (block_num < 0 || block_num >= num_blocks)
@@ -375,7 +397,9 @@ bool JitBlock::ContainsAddress(u32 em_address)
Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress);
#endif
// We don't unlink blocks, we just send anyone who tries to run them back to the dispatcher.
UnlinkBlock(block_num);
// Send anyone who tries to run this block back to the dispatcher.
// Not entirely ideal, but .. pretty good.
// Spurious entrances from previously linked blocks can only come through checkedEntry
XEmitter emit((u8 *)b.checkedEntry);
@@ -389,16 +413,38 @@ bool JitBlock::ContainsAddress(u32 em_address)
*/
}
void JitBlockCache::InvalidateICache(u32 address)
void JitBlockCache::InvalidateICache(u32 address, const u32 length)
{
address &= ~0x1f;
// Convert the logical address to a physical address for the block map
u32 pAddr = address & 0x1FFFFFFF;
// destroy JIT blocks
// !! this works correctly under assumption that any two overlapping blocks end at the same address
std::map<pair<u32,u32>, u32>::iterator it1 = block_map.lower_bound(std::make_pair(address, 0)), it2 = it1, it;
while (it2 != block_map.end() && it2->first.second < address + 0x20)
std::map<pair<u32,u32>, u32>::iterator it1 = block_map.lower_bound(std::make_pair(pAddr, 0)), it2 = it1, it;
while (it2 != block_map.end() && it2->first.second < pAddr + length)
{
DestroyBlock(it2->second, true);
#ifdef JIT_UNLIMITED_ICACHE
JitBlock &b = blocks[it2->second];
if (b.originalFirstOpcode != Memory::ReadUnchecked_U32(b.originalAddress))
{
if (b.originalAddress & JIT_ICACHE_VMEM_BIT)
{
u32 cacheaddr = b.originalAddress & JIT_ICACHE_MASK;
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, 4);
}
else if (b.originalAddress & JIT_ICACHE_EXRAM_BIT)
{
u32 cacheaddr = b.originalAddress & JIT_ICACHEEX_MASK;
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 4);
}
else
{
u32 cacheaddr = b.originalAddress & JIT_ICACHE_MASK;
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, 4);
}
#endif
DestroyBlock(it2->second, true);
}
it2++;
}
if (it1 != it2)
@@ -418,17 +464,17 @@ bool JitBlock::ContainsAddress(u32 em_address)
if (address & JIT_ICACHE_VMEM_BIT)
{
u32 cacheaddr = address & JIT_ICACHE_MASK;
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, length);
}
else if (address & JIT_ICACHE_EXRAM_BIT)
{
u32 cacheaddr = address & JIT_ICACHEEX_MASK;
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, length);
}
else
{
u32 cacheaddr = address & JIT_ICACHE_MASK;
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
memset(iCache + cacheaddr, JIT_ICACHE_INVALID_BYTE, length);
}
#endif
}

View File

@@ -87,6 +87,7 @@ class JitBlockCache
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
void LinkBlockExits(int i);
void LinkBlock(int i);
void UnlinkBlock(int i);
public:
JitBlockCache() :
@@ -129,7 +130,7 @@ public:
CompiledCode GetCompiledCodeFromBlock(int block_num);
// DOES NOT WORK CORRECTLY WITH INLINING
void InvalidateICache(u32 em_address);
void InvalidateICache(u32 address, const u32 length);
void DestroyBlock(int block_num, bool invalidate);
// Not currently used

View File

@@ -118,16 +118,18 @@ void EmuCodeBlock::UnsafeLoadToEAX(const Gen::OpArg & opAddress, int accessSize,
void EmuCodeBlock::SafeLoadToEAX(const Gen::OpArg & opAddress, int accessSize, s32 offset, bool signExtend)
{
#if defined(_WIN32) && defined(_M_X64)
#ifdef ENABLE_MEM_CHECK
if (Core::g_CoreStartupParameter.bUseFastMem && (accessSize == 32) && !Core::g_CoreStartupParameter.bMMU && !Core::g_CoreStartupParameter.bEnableDebugging)
if (accessSize == 32 && !Core::g_CoreStartupParameter.bMMU && !Core::g_CoreStartupParameter.bEnableDebugging)
#else
if (Core::g_CoreStartupParameter.bUseFastMem && (accessSize == 32) && !Core::g_CoreStartupParameter.bMMU)
if (accessSize == 32 && !Core::g_CoreStartupParameter.bMMU)
#endif
{
// BackPatch only supports 32-bits accesses
UnsafeLoadToEAX(opAddress, accessSize, offset, signExtend);
}
else
#endif
{
u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS;
if (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.iTLBHack)
@@ -252,7 +254,7 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce
TEST(32, R(reg_addr), Imm32(mem_mask));
FixupBranch fast = J_CC(CC_Z);
MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
switch (accessSize)
{
case 32: ABI_CallFunctionRR(thunks.ProtectFunction(swap ? ((void *)&Memory::Write_U32) : ((void *)&Memory::Write_U32_Swap), 2), reg_value, reg_addr); break;
@@ -288,6 +290,7 @@ void EmuCodeBlock::SafeWriteFloatToReg(X64Reg xmm_value, X64Reg reg_addr)
MOVSS(M(&float_buffer), xmm_value);
MOV(32, R(EAX), M(&float_buffer));
BSWAP(32, EAX);
MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
ABI_CallFunctionRR(thunks.ProtectFunction(((void *)&Memory::Write_U32), 2), EAX, reg_addr);
FixupBranch arg2 = J();
SetJumpTarget(argh);

View File

@@ -299,7 +299,7 @@ u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa,
merged_addresses[0] = address;
size_of_merged_addresses = 1;
memset(st, 0, sizeof(st));
memset(st, 0, sizeof(*st));
// Disabled the following optimization in preference of FAST_ICACHE
//UGeckoInstruction previnst = Memory::Read_Opcode_JIT_LC(address - 4);
@@ -559,7 +559,7 @@ u32 Flatten(u32 address, int *realsize, BlockStats *st, BlockRegStats *gpa,
}
else
{
// Memory exception occurred
// ISI exception or other critical memory exception occurred (game over)
break;
}
}

View File

@@ -110,7 +110,7 @@ namespace PowerPC
#endif
valid[set] = 0;
if (jit)
jit->GetBlockCache()->InvalidateICache(addr);
jit->GetBlockCache()->InvalidateICache(addr & ~0x1f, 32);
}
u32 InstructionCache::ReadInstruction(u32 addr)

View File

@@ -289,6 +289,65 @@ void Stop()
Host_UpdateDisasmDialog();
}
void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst)
{
switch (MMCR0.PMC1SELECT)
{
case 0: // No change
break;
case 1: // Processor cycles
PowerPC::ppcState.spr[SPR_PMC1] += cycles;
break;
default:
break;
}
switch (MMCR0.PMC2SELECT)
{
case 0: // No change
break;
case 1: // Processor cycles
PowerPC::ppcState.spr[SPR_PMC2] += cycles;
break;
case 11: // Number of loads and stores completed
PowerPC::ppcState.spr[SPR_PMC2] += num_load_stores;
break;
default:
break;
}
switch (MMCR1.PMC3SELECT)
{
case 0: // No change
break;
case 1: // Processor cycles
PowerPC::ppcState.spr[SPR_PMC3] += cycles;
break;
case 11: // Number of FPU instructions completed
PowerPC::ppcState.spr[SPR_PMC3] += num_fp_inst;
break;
default:
break;
}
switch (MMCR1.PMC4SELECT)
{
case 0: // No change
break;
case 1: // Processor cycles
PowerPC::ppcState.spr[SPR_PMC4] += cycles;
break;
default:
break;
}
if ((MMCR0.PMC1INTCONTROL && (PowerPC::ppcState.spr[SPR_PMC1] & 0x80000000) != 0) ||
(MMCR0.PMCINTCONTROL && (PowerPC::ppcState.spr[SPR_PMC2] & 0x80000000) != 0) ||
(MMCR0.PMCINTCONTROL && (PowerPC::ppcState.spr[SPR_PMC3] & 0x80000000) != 0) ||
(MMCR0.PMCINTCONTROL && (PowerPC::ppcState.spr[SPR_PMC4] & 0x80000000) != 0))
PowerPC::ppcState.Exceptions |= EXCEPTION_PERFORMANCE_MONITOR;
}
void CheckExceptions()
{
// Make sure we are checking against the latest EXI status. This is required
@@ -298,9 +357,6 @@ void CheckExceptions()
// Read volatile data once
u32 exceptions = ppcState.Exceptions;
if (!exceptions)
return;
// Example procedure:
// set SRR0 to either PC or NPC
//SRR0 = NPC;
@@ -311,7 +367,7 @@ void CheckExceptions()
// clear MSR as specified
//MSR &= ~0x04EF36; // 0x04FF36 also clears ME (only for machine check exception)
// set to exception type entry point
//NPC = 0x80000x00;
//NPC = 0x00000x00;
if (exceptions & EXCEPTION_ISI)
{
@@ -320,7 +376,7 @@ void CheckExceptions()
SRR1 = (MSR & 0x87C0FFFF) | (1 << 30);
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
NPC = 0x80000400;
PC = NPC = 0x00000400;
INFO_LOG(POWERPC, "EXCEPTION_ISI");
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_ISI);
@@ -332,7 +388,7 @@ void CheckExceptions()
SRR1 = (MSR & 0x87C0FFFF) | 0x20000;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
NPC = 0x80000700;
PC = NPC = 0x00000700;
INFO_LOG(POWERPC, "EXCEPTION_PROGRAM");
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_PROGRAM);
@@ -343,7 +399,7 @@ void CheckExceptions()
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
NPC = 0x80000C00;
PC = NPC = 0x00000C00;
INFO_LOG(POWERPC, "EXCEPTION_SYSCALL (PC=%08x)", PC);
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_SYSCALL);
@@ -355,7 +411,7 @@ void CheckExceptions()
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
NPC = 0x80000800;
PC = NPC = 0x00000800;
INFO_LOG(POWERPC, "EXCEPTION_FPU_UNAVAILABLE");
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_FPU_UNAVAILABLE);
@@ -366,7 +422,7 @@ void CheckExceptions()
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
NPC = 0x80000300;
PC = NPC = 0x00000300;
//DSISR and DAR regs are changed in GenerateDSIException()
INFO_LOG(POWERPC, "EXCEPTION_DSI");
@@ -380,7 +436,7 @@ void CheckExceptions()
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
NPC = 0x80000600;
PC = NPC = 0x00000600;
//TODO crazy amount of DSISR options to check out
@@ -398,20 +454,78 @@ void CheckExceptions()
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
NPC = 0x80000500;
PC = NPC = 0x00000500;
INFO_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_EXTERNAL_INT);
_dbg_assert_msg_(POWERPC, (SRR1 & 0x02) != 0, "EXTERNAL_INT unrecoverable???");
}
else if (exceptions & EXCEPTION_PERFORMANCE_MONITOR)
{
SRR0 = NPC;
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
PC = NPC = 0x00000F00;
INFO_LOG(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_PERFORMANCE_MONITOR);
}
else if (exceptions & EXCEPTION_DECREMENTER)
{
SRR0 = NPC;
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
NPC = 0x80000900;
PC = NPC = 0x00000900;
INFO_LOG(POWERPC, "EXCEPTION_DECREMENTER");
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_DECREMENTER);
}
}
}
void CheckExternalExceptions()
{
// Read volatile data once
u32 exceptions = ppcState.Exceptions;
// EXTERNAL INTERRUPT
if (MSR & 0x0008000) //hacky...the exception shouldn't be generated if EE isn't set...
{
if (exceptions & EXCEPTION_EXTERNAL_INT)
{
// Pokemon gets this "too early", it hasn't a handler yet
SRR0 = NPC;
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
PC = NPC = 0x00000500;
INFO_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_EXTERNAL_INT);
_dbg_assert_msg_(POWERPC, (SRR1 & 0x02) != 0, "EXTERNAL_INT unrecoverable???");
}
else if (exceptions & EXCEPTION_PERFORMANCE_MONITOR)
{
SRR0 = NPC;
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
PC = NPC = 0x00000F00;
INFO_LOG(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_PERFORMANCE_MONITOR);
}
else if (exceptions & EXCEPTION_DECREMENTER)
{
SRR0 = NPC;
SRR1 = MSR & 0x87C0FFFF;
MSR |= (MSR >> 16) & 1;
MSR &= ~0x04EF36;
PC = NPC = 0x00000900;
INFO_LOG(POWERPC, "EXCEPTION_DECREMENTER");
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_DECREMENTER);

View File

@@ -102,6 +102,7 @@ void SetMode(CoreMode _coreType);
void SingleStep();
void CheckExceptions();
void CheckExternalExceptions();
void CheckBreakPoints();
void RunLoop();
void Start();
@@ -116,12 +117,16 @@ void ExpandCR();
void OnIdle(u32 _uThreadAddr);
void OnIdleIL();
void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst);
// Easy register access macros.
#define HID0 ((UReg_HID0&)PowerPC::ppcState.spr[SPR_HID0])
#define HID2 ((UReg_HID2&)PowerPC::ppcState.spr[SPR_HID2])
#define HID4 ((UReg_HID4&)PowerPC::ppcState.spr[SPR_HID4])
#define DMAU (*(UReg_DMAU*)&PowerPC::ppcState.spr[SPR_DMAU])
#define DMAL (*(UReg_DMAL*)&PowerPC::ppcState.spr[SPR_DMAL])
#define MMCR0 ((UReg_MMCR0&)PowerPC::ppcState.spr[SPR_MMCR0])
#define MMCR1 ((UReg_MMCR1&)PowerPC::ppcState.spr[SPR_MMCR1])
#define PC PowerPC::ppcState.pc
#define NPC PowerPC::ppcState.npc
#define FPSCR ((UReg_FPSCR&)PowerPC::ppcState.fpscr)

View File

@@ -56,18 +56,21 @@ void WriteProfileResults(const char *filename)
for (int i = 0; i < jit->GetBlockCache()->GetNumBlocks(); i++)
{
const JitBlock *block = jit->GetBlockCache()->GetBlock(i);
// Rough heuristic. Mem instructions should cost more.
u64 cost = block->originalSize * (block->runCount / 4);
if (block && !block->invalid)
{
// Rough heuristic. Mem instructions should cost more.
u64 cost = block->originalSize * (block->runCount / 4);
#ifdef _WIN32
u64 timecost = block->ticCounter;
u64 timecost = block->ticCounter;
#endif
// Todo: tweak.
if (block->runCount >= 1)
stats.push_back(BlockStat(i, cost));
cost_sum += cost;
// Todo: tweak.
if (block->runCount >= 1)
stats.push_back(BlockStat(i, cost));
cost_sum += cost;
#ifdef _WIN32
timecost_sum += timecost;
timecost_sum += timecost;
#endif
}
}
sort(stats.begin(), stats.end());
@@ -77,18 +80,18 @@ void WriteProfileResults(const char *filename)
PanicAlert("failed to open %s", filename);
return;
}
fprintf(f.GetHandle(), "origAddr\tblkName\tcost\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n");
fprintf(f.GetHandle(), "origAddr\tblkName\tcost\trunCount\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n");
for (unsigned int i = 0; i < stats.size(); i++)
{
const JitBlock *block = jit->GetBlockCache()->GetBlock(stats[i].blockNum);
if (block)
if (block && !block->invalid)
{
std::string name = g_symbolDB.GetDescription(block->originalAddress);
double percent = 100.0 * (double)stats[i].cost / (double)cost_sum;
#ifdef _WIN32
double timePercent = 100.0 * (double)block->ticCounter / (double)timecost_sum;
fprintf(f.GetHandle(), "%08x\t%s\t%llu\t%llu\t%.2lf\t%llf\t%lf\t%i\n",
block->originalAddress, name.c_str(), stats[i].cost,
fprintf(f.GetHandle(), "%08x\t%s\t%llu\t%llu\t%llu\t%.2lf\t%llf\t%lf\t%i\n",
block->originalAddress, name.c_str(), stats[i].cost, block->runCount,
block->ticCounter, percent, timePercent,
(double)block->ticCounter*1000.0/(double)countsPerSec, block->codeSize);
#else

View File

@@ -3,6 +3,7 @@ set(SRCS Src/BannerLoader.cpp
Src/BannerLoaderWii.cpp
Src/Blob.cpp
Src/CISOBlob.cpp
Src/WbfsBlob.cpp
Src/CompressedBlob.cpp
Src/DiscScrubber.cpp
Src/DriveBlob.cpp

View File

@@ -175,6 +175,7 @@
<ClInclude Include="Src\BannerLoaderWii.h" />
<ClInclude Include="Src\Blob.h" />
<ClInclude Include="Src\CISOBlob.h" />
<ClInclude Include="Src\WbfsBlob.h" />
<ClInclude Include="Src\CompressedBlob.h" />
<ClInclude Include="Src\DiscScrubber.h" />
<ClInclude Include="Src\DriveBlob.h" />
@@ -199,6 +200,7 @@
<ClCompile Include="Src\BannerLoaderWii.cpp" />
<ClCompile Include="Src\Blob.cpp" />
<ClCompile Include="Src\CISOBlob.cpp" />
<ClCompile Include="Src\WbfsBlob.cpp" />
<ClCompile Include="Src\CompressedBlob.cpp" />
<ClCompile Include="Src\DiscScrubber.cpp" />
<ClCompile Include="Src\DriveBlob.cpp" />
@@ -226,7 +228,6 @@
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
<None Include="Src\SConscript" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@@ -8,6 +8,9 @@
<ClCompile Include="Src\CISOBlob.cpp">
<Filter>Volume\Blob</Filter>
</ClCompile>
<ClCompile Include="Src\WbfsBlob.cpp">
<Filter>Volume\Blob</Filter>
</ClCompile>
<ClCompile Include="Src\CompressedBlob.cpp">
<Filter>Volume\Blob</Filter>
</ClCompile>
@@ -71,6 +74,9 @@
<ClInclude Include="Src\CISOBlob.h">
<Filter>Volume\Blob</Filter>
</ClInclude>
<ClInclude Include="Src\WbfsBlob.h">
<Filter>Volume\Blob</Filter>
</ClInclude>
<ClInclude Include="Src\Blob.h">
<Filter>Volume\Blob</Filter>
</ClInclude>
@@ -133,7 +139,6 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Src\SConscript" />
<None Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,29 +0,0 @@
# -*- python -*-
Import('env')
files = [
'Src/BannerLoader.cpp',
'Src/BannerLoaderGC.cpp',
'Src/BannerLoaderWii.cpp',
'Src/Blob.cpp',
'Src/CISOBlob.cpp',
'Src/CompressedBlob.cpp',
'Src/DiscScrubber.cpp',
'Src/DriveBlob.cpp',
'Src/FileBlob.cpp',
'Src/FileHandlerARC.cpp',
'Src/FileMonitor.cpp',
'Src/FileSystemGCWii.cpp',
'Src/Filesystem.cpp',
'Src/NANDContentLoader.cpp',
'Src/VolumeCommon.cpp',
'Src/VolumeCreator.cpp',
'Src/VolumeDirectory.cpp',
'Src/VolumeGC.cpp',
'Src/VolumeWad.cpp',
'Src/VolumeWiiCrypted.cpp',
'Src/WiiWad.cpp',
]
env['LIBS'] += env.StaticLibrary('discio', files)

View File

@@ -23,6 +23,7 @@
#include "FileBlob.h"
#include "CISOBlob.h"
#include "DriveBlob.h"
#include "WbfsBlob.h"
namespace DiscIO
{
@@ -128,6 +129,9 @@ IBlobReader* CreateBlobReader(const char* filename)
if (!File::Exists(filename))
return 0;
if (IsWbfsBlob(filename))
return WbfsFileReader::Create(filename);
if (IsCompressedBlob(filename))
return CompressedBlobReader::Create(filename);

View File

@@ -462,7 +462,7 @@ void cUIDsys::AddTitle(u64 _TitleID)
File::CreateFullPath(uidSys);
File::IOFile pFile(uidSys, "ab");
if (pFile.WriteArray(&Element, 1))
if (!pFile.WriteArray(&Element, 1))
ERROR_LOG(DISCIO, "fwrite failed");
}

View File

@@ -38,9 +38,11 @@ public:
virtual std::string GetUniqueID() const = 0;
virtual std::string GetMakerID() const = 0;
virtual std::string GetName() const = 0;
virtual bool GetWName(std::vector<std::wstring>& _rwNames) const {return false;};
virtual bool GetWName(std::vector<std::wstring>& _rwNames) const { return false; }
virtual u32 GetFSTSize() const = 0;
virtual std::string GetApploaderDate() const = 0;
virtual bool SupportsIntegrityCheck() const { return false; }
virtual bool CheckIntegrity() const { return false; }
enum ECountry
{

View File

@@ -16,6 +16,7 @@
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "MathUtil.h"
#include "CommonPaths.h"
#include "VolumeDirectory.h"
#include "FileBlob.h"
@@ -23,17 +24,6 @@
namespace DiscIO
{
static const u8 ENTRY_SIZE = 0x0c;
static const u8 FILE_ENTRY = 0;
static const u8 DIRECTORY_ENTRY = 1;
static const u64 DISKHEADER_ADDRESS = 0;
static const u64 DISKHEADERINFO_ADDRESS = 0x440;
static const u64 APPLOADER_ADDRESS = 0x2440;
static const u32 MAX_NAME_LENGTH = 0x3df;
// relocatable
static u64 FST_ADDRESS = 0x440;
static u64 DOL_ADDRESS = 0;
CVolumeDirectory::CVolumeDirectory(const std::string& _rDirectory, bool _bIsWii,
const std::string& _rApploader, const std::string& _rDOL)
: m_totalNameSize(0)
@@ -44,6 +34,8 @@ CVolumeDirectory::CVolumeDirectory(const std::string& _rDirectory, bool _bIsWii,
, m_apploader(NULL)
, m_DOLSize(0)
, m_DOL(NULL)
, FST_ADDRESS(0)
, DOL_ADDRESS(0)
{
m_rootDirectory = ExtractDirectoryName(_rDirectory);
@@ -321,7 +313,7 @@ bool CVolumeDirectory::SetApploader(const std::string& _rApploader)
copy(data.begin(), data.end(), m_apploader);
// 32byte aligned (plus 0x20 padding)
DOL_ADDRESS = (APPLOADER_ADDRESS + m_apploaderSize + 0x20 + 31) & ~31ULL;
DOL_ADDRESS = ROUND_UP(APPLOADER_ADDRESS + m_apploaderSize + 0x20, 0x20ull);
return true;
}
else
@@ -347,7 +339,7 @@ void CVolumeDirectory::SetDOL(const std::string& _rDOL)
Write32((u32)(DOL_ADDRESS >> m_addressShift), 0x0420, m_diskHeader);
// 32byte aligned (plus 0x20 padding)
FST_ADDRESS = (DOL_ADDRESS + m_DOLSize + 0x20 + 31) & ~31ULL;
FST_ADDRESS = ROUND_UP(DOL_ADDRESS + m_DOLSize + 0x20, 0x20ull);
}
}
@@ -367,8 +359,12 @@ void CVolumeDirectory::BuildFST()
m_fstSize = m_fstNameOffset + m_totalNameSize;
m_FSTData = new u8[(u32)m_fstSize];
// if FST hasn't been assigned (ie no apploader/dol setup), set to default
if (FST_ADDRESS == 0)
FST_ADDRESS = APPLOADER_ADDRESS + 0x2000;
// 4 byte aligned start of data on disk
m_dataStartAddress = (FST_ADDRESS + m_fstSize + 3) & ~3;
m_dataStartAddress = ROUND_UP(FST_ADDRESS + m_fstSize, 0x8000ull);
u64 curDataAddress = m_dataStartAddress;
u32 fstOffset = 0; // offset within FST data
@@ -389,8 +385,8 @@ void CVolumeDirectory::BuildFST()
// write FST size and location
_dbg_assert_(DVDINTERFACE, m_diskHeader);
Write32((u32)(FST_ADDRESS >> m_addressShift), 0x0424, m_diskHeader);
Write32((u32)m_fstSize, 0x0428, m_diskHeader);
Write32((u32)m_fstSize, 0x042c, m_diskHeader);
Write32((u32)(m_fstSize >> m_addressShift), 0x0428, m_diskHeader);
Write32((u32)(m_fstSize >> m_addressShift), 0x042c, m_diskHeader);
}
void CVolumeDirectory::WriteToBuffer(u64 _SrcStartAddress, u64 _SrcLength, u8* _Src,
@@ -490,7 +486,7 @@ void CVolumeDirectory::WriteEntry(const File::FSTEntry& entry, u32& fstOffset, u
m_virtualDisk.insert(make_pair(dataOffset, entry.physicalName));
// 4 byte aligned
dataOffset = (dataOffset + entry.size + 3) & ~3ULL;
dataOffset = ROUND_UP(dataOffset + entry.size, 0x8000ull);
}
}

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