mirror of
https://github.com/project-slippi/Ishiiruka.git
synced 2025-10-06 00:12:42 +02:00
Merge latest master changes
This commit is contained in:
@@ -13,7 +13,7 @@ foreach(LLVM_CONFIG_NAME ${LLVM_CONFIG_EXECUTABLES})
|
||||
if (LLVM_CONFIG_EXE)
|
||||
execute_process(COMMAND ${LLVM_CONFIG_EXE} --version OUTPUT_VARIABLE LLVM_PACKAGE_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
if (${LLVM_PACKAGE_VERSION} VERSION_GREATER "3.3")
|
||||
if (LLVM_PACKAGE_VERSION VERSION_GREATER "3.3")
|
||||
execute_process(COMMAND ${LLVM_CONFIG_EXE} --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIRS
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
execute_process(COMMAND ${LLVM_CONFIG_EXE} --ldflags OUTPUT_VARIABLE LLVM_LDFLAGS
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include "Core/PowerPC/Profiler.h"
|
||||
#include "Core/State.h"
|
||||
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "DiscIO/VolumeCreator.h"
|
||||
|
||||
@@ -226,15 +227,14 @@ static int GetCountry(std::string filename)
|
||||
|
||||
if (pVolume != nullptr)
|
||||
{
|
||||
DiscIO::IVolume::ECountry country = pVolume->GetCountry();
|
||||
int country = static_cast<int>(pVolume->GetCountry());
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Country Code: %i", country);
|
||||
|
||||
return country;
|
||||
}
|
||||
|
||||
// Return UNKNOWN
|
||||
return 13;
|
||||
return static_cast<int>(DiscIO::Country::COUNTRY_UNKNOWN);
|
||||
}
|
||||
|
||||
static int GetPlatform(std::string filename)
|
||||
@@ -245,13 +245,13 @@ static int GetPlatform(std::string filename)
|
||||
{
|
||||
switch (pVolume->GetVolumeType())
|
||||
{
|
||||
case DiscIO::IVolume::GAMECUBE_DISC:
|
||||
case DiscIO::Platform::GAMECUBE_DISC:
|
||||
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Volume is a GameCube disc.");
|
||||
return 0;
|
||||
case DiscIO::IVolume::WII_DISC:
|
||||
case DiscIO::Platform::WII_DISC:
|
||||
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Volume is a Wii disc.");
|
||||
return 1;
|
||||
case DiscIO::IVolume::WII_WAD:
|
||||
case DiscIO::Platform::WII_WAD:
|
||||
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Volume is a Wii WAD.");
|
||||
return 2;
|
||||
}
|
||||
@@ -269,13 +269,13 @@ static std::string GetTitle(std::string filename)
|
||||
|
||||
if (pVolume != nullptr)
|
||||
{
|
||||
std::map<DiscIO::IVolume::ELanguage, std::string> titles = pVolume->GetLongNames();
|
||||
std::map<DiscIO::Language, std::string> titles = pVolume->GetLongNames();
|
||||
if (titles.empty())
|
||||
titles = pVolume->GetShortNames();
|
||||
|
||||
/*
|
||||
bool is_wii_title = pVolume->GetVolumeType() != DiscIO::IVolume::GAMECUBE_DISC;
|
||||
DiscIO::IVolume::ELanguage language = SConfig::GetInstance().GetCurrentLanguage(is_wii_title);
|
||||
bool is_wii_title = pVolume->GetVolumeType() != DiscIO::Platform::GAMECUBE_DISC;
|
||||
DiscIO::Language language = SConfig::GetInstance().GetCurrentLanguage(is_wii_title);
|
||||
|
||||
auto it = titles.find(language);
|
||||
if (it != end)
|
||||
@@ -284,8 +284,8 @@ static std::string GetTitle(std::string filename)
|
||||
auto end = titles.end();
|
||||
|
||||
// English tends to be a good fallback when the requested language isn't available
|
||||
// if (language != DiscIO::IVolume::ELanguage::LANGUAGE_ENGLISH) {
|
||||
auto it = titles.find(DiscIO::IVolume::ELanguage::LANGUAGE_ENGLISH);
|
||||
// if (language != DiscIO::Language::LANGUAGE_ENGLISH) {
|
||||
auto it = titles.find(DiscIO::Language::LANGUAGE_ENGLISH);
|
||||
if (it != end)
|
||||
return it->second;
|
||||
//}
|
||||
@@ -312,11 +312,11 @@ static std::string GetDescription(std::string filename)
|
||||
|
||||
if (volume != nullptr)
|
||||
{
|
||||
std::map<DiscIO::IVolume::ELanguage, std::string> descriptions = volume->GetDescriptions();
|
||||
std::map<DiscIO::Language, std::string> descriptions = volume->GetDescriptions();
|
||||
|
||||
/*
|
||||
bool is_wii_title = pVolume->GetVolumeType() != DiscIO::IVolume::GAMECUBE_DISC;
|
||||
DiscIO::IVolume::ELanguage language = SConfig::GetInstance().GetCurrentLanguage(is_wii_title);
|
||||
bool is_wii_title = pVolume->GetVolumeType() != DiscIO::Platform::GAMECUBE_DISC;
|
||||
DiscIO::Language language = SConfig::GetInstance().GetCurrentLanguage(is_wii_title);
|
||||
|
||||
auto it = descriptions.find(language);
|
||||
if (it != end)
|
||||
@@ -325,8 +325,8 @@ static std::string GetDescription(std::string filename)
|
||||
auto end = descriptions.end();
|
||||
|
||||
// English tends to be a good fallback when the requested language isn't available
|
||||
// if (language != DiscIO::IVolume::ELanguage::LANGUAGE_ENGLISH) {
|
||||
auto it = descriptions.find(DiscIO::IVolume::ELanguage::LANGUAGE_ENGLISH);
|
||||
// if (language != DiscIO::Language::LANGUAGE_ENGLISH) {
|
||||
auto it = descriptions.find(DiscIO::Language::LANGUAGE_ENGLISH);
|
||||
if (it != end)
|
||||
return it->second;
|
||||
//}
|
||||
|
@@ -26,7 +26,10 @@
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\VSProps\Base.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<CScript Condition="'$(ProgramFiles(x86))' != ''">%windir%\System32\cscript</CScript>
|
||||
<CScript Condition="'$(ProgramFiles(x86))' == ''">%windir%\Sysnative\cscript</CScript>
|
||||
</PropertyGroup>
|
||||
<!--
|
||||
OutDir is always created, which is annoying for SCMRevGen as it doesn't really have an outdir.
|
||||
Here it's redirected to some other place to hide the annoyance.
|
||||
@@ -36,7 +39,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<PreBuildEvent>
|
||||
<Command>"%windir%\Sysnative\cscript" /nologo /E:JScript "make_scmrev.h.js"</Command>
|
||||
<Command>"$(CScript)" /nologo /E:JScript "make_scmrev.h.js"</Command>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
@@ -17,15 +17,15 @@
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <iconv.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && !defined(ANDROID)
|
||||
@@ -237,8 +237,7 @@ bool TryParse(const std::string& str, u32* const output)
|
||||
return false;
|
||||
|
||||
#if ULONG_MAX > UINT_MAX
|
||||
if (value >= 0x100000000ull &&
|
||||
value <= 0xFFFFFFFF00000000ull)
|
||||
if (value >= 0x100000000ull && value <= 0xFFFFFFFF00000000ull)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
@@ -248,9 +247,11 @@ bool TryParse(const std::string& str, u32* const output)
|
||||
|
||||
bool TryParse(const std::string& str, bool* const output)
|
||||
{
|
||||
if ("1" == str || !strcasecmp("true", str.c_str()))
|
||||
float value;
|
||||
const bool is_valid_float = TryParse(str, &value);
|
||||
if ((is_valid_float && value == 1) || !strcasecmp("true", str.c_str()))
|
||||
*output = true;
|
||||
else if ("0" == str || !strcasecmp("false", str.c_str()))
|
||||
else if ((is_valid_float && value == 0) || !strcasecmp("false", str.c_str()))
|
||||
*output = false;
|
||||
else
|
||||
return false;
|
||||
@@ -270,7 +271,8 @@ std::string StringFromBool(bool value)
|
||||
return value ? "True" : "False";
|
||||
}
|
||||
|
||||
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension)
|
||||
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename,
|
||||
std::string* _pExtension)
|
||||
{
|
||||
if (full_path.empty())
|
||||
return false;
|
||||
@@ -302,7 +304,8 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
|
||||
return true;
|
||||
}
|
||||
|
||||
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename)
|
||||
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path,
|
||||
const std::string& _Filename)
|
||||
{
|
||||
_CompleteFilename = _Path;
|
||||
|
||||
@@ -357,12 +360,15 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
|
||||
|
||||
std::string UTF16ToUTF8(const std::wstring& input)
|
||||
{
|
||||
auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), (int)input.size(), nullptr, 0, nullptr, nullptr);
|
||||
auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), (int)input.size(), nullptr, 0,
|
||||
nullptr, nullptr);
|
||||
|
||||
std::string output;
|
||||
output.resize(size);
|
||||
|
||||
if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), (int)input.size(), &output[0], (int)output.size(), nullptr, nullptr))
|
||||
if (size == 0 ||
|
||||
size != WideCharToMultiByte(CP_UTF8, 0, input.data(), (int)input.size(), &output[0],
|
||||
(int)output.size(), nullptr, nullptr))
|
||||
{
|
||||
output.clear();
|
||||
}
|
||||
@@ -377,7 +383,9 @@ std::wstring CPToUTF16(u32 code_page, const std::string& input)
|
||||
std::wstring output;
|
||||
output.resize(size);
|
||||
|
||||
if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), (int)input.size(), &output[0], (int)output.size()))
|
||||
if (size == 0 ||
|
||||
size != MultiByteToWideChar(code_page, 0, input.data(), (int)input.size(), &output[0],
|
||||
(int)output.size()))
|
||||
{
|
||||
output.clear();
|
||||
}
|
||||
@@ -427,8 +435,8 @@ std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
|
||||
|
||||
while (src_bytes != 0)
|
||||
{
|
||||
size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
|
||||
&dst_buffer, &dst_bytes);
|
||||
size_t const iconv_result =
|
||||
iconv(conv_desc, (char**)(&src_buffer), &src_bytes, &dst_buffer, &dst_bytes);
|
||||
|
||||
if ((size_t)-1 == iconv_result)
|
||||
{
|
||||
@@ -460,14 +468,14 @@ std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
|
||||
|
||||
std::string CP1252ToUTF8(const std::string& input)
|
||||
{
|
||||
//return CodeToUTF8("CP1252//TRANSLIT", input);
|
||||
//return CodeToUTF8("CP1252//IGNORE", input);
|
||||
// return CodeToUTF8("CP1252//TRANSLIT", input);
|
||||
// return CodeToUTF8("CP1252//IGNORE", input);
|
||||
return CodeToUTF8("CP1252", input);
|
||||
}
|
||||
|
||||
std::string SHIFTJISToUTF8(const std::string& input)
|
||||
{
|
||||
//return CodeToUTF8("CP932", input);
|
||||
// return CodeToUTF8("CP932", input);
|
||||
return CodeToUTF8("SJIS", input);
|
||||
}
|
||||
|
||||
|
@@ -355,7 +355,7 @@ static bool getbitstring(u32 *ctrl, u32 *out, u8 len)
|
||||
static bool batchdecrypt(u32 *codes, u16 size)
|
||||
{
|
||||
u32 tmp, *ptr = codes;
|
||||
u32 tmparray[4] = {0}, tmparray2[8] = {0};
|
||||
u32 tmparray[4] = { 0 }, tmparray2[8] = { 0 };
|
||||
|
||||
// Not required
|
||||
//if (size & 1) return 0;
|
||||
|
@@ -82,7 +82,7 @@ enum
|
||||
static std::mutex s_lock;
|
||||
static std::vector<ARCode> s_active_codes;
|
||||
static std::vector<std::string> s_internal_log;
|
||||
static std::atomic<bool> s_use_internal_log{false};
|
||||
static std::atomic<bool> s_use_internal_log{ false };
|
||||
// pointer to the code currently being run, (used by log messages that include the code name)
|
||||
static const ARCode* s_current_code = nullptr;
|
||||
static bool s_disable_logging = false;
|
||||
@@ -101,7 +101,7 @@ struct ARAddr
|
||||
};
|
||||
};
|
||||
|
||||
ARAddr(const u32 addr): address(addr)
|
||||
ARAddr(const u32 addr) : address(addr)
|
||||
{}
|
||||
u32 GCAddress() const
|
||||
{
|
||||
@@ -167,7 +167,7 @@ std::vector<ARCode> LoadCodes(const IniFile& global_ini, const IniFile& local_in
|
||||
}
|
||||
}
|
||||
|
||||
const IniFile* inis[2] = {&global_ini, &local_ini};
|
||||
const IniFile* inis[2] = { &global_ini, &local_ini };
|
||||
for (const IniFile* ini : inis)
|
||||
{
|
||||
std::vector<std::string> lines;
|
||||
|
@@ -17,7 +17,7 @@ struct AREntry
|
||||
{
|
||||
AREntry()
|
||||
{}
|
||||
AREntry(u32 _addr, u32 _value): cmd_addr(_addr), value(_value)
|
||||
AREntry(u32 _addr, u32 _value) : cmd_addr(_addr), value(_value)
|
||||
{}
|
||||
u32 cmd_addr;
|
||||
u32 value;
|
||||
|
@@ -12,12 +12,10 @@
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/Boot/Boot_DOL.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/Debugger/Debugger_SymbolMap.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HW/DVDInterface.h"
|
||||
@@ -25,13 +23,17 @@
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/HW/ProcessorInterface.h"
|
||||
#include "Core/HW/VideoInterface.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/PowerPC/PPCAnalyst.h"
|
||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/PowerPC/SignatureDB.h"
|
||||
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/NANDContentLoader.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "DiscIO/VolumeCreator.h"
|
||||
|
||||
bool CBoot::DVDRead(u64 dvd_offset, u32 output_address, u32 length, bool decrypt)
|
||||
@@ -51,7 +53,7 @@ void CBoot::Load_FST(bool _bIsWii)
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
|
||||
// copy first 20 bytes of disc to start of Mem 1
|
||||
DVDRead(/*offset*/0, /*address*/0, /*length*/0x20, false);
|
||||
DVDRead(/*offset*/ 0, /*address*/ 0, /*length*/ 0x20, false);
|
||||
|
||||
// copy of game id
|
||||
Memory::Write_U32(Memory::Read_U32(0x0000), 0x3180);
|
||||
@@ -82,8 +84,7 @@ void CBoot::UpdateDebugger_MapLoaded()
|
||||
Host_NotifyMapLoaded();
|
||||
}
|
||||
|
||||
bool CBoot::FindMapFile(std::string* existing_map_file,
|
||||
std::string* writable_map_file,
|
||||
bool CBoot::FindMapFile(std::string* existing_map_file, std::string* writable_map_file,
|
||||
std::string* title_id)
|
||||
{
|
||||
std::string title_id_str;
|
||||
@@ -99,8 +100,7 @@ bool CBoot::FindMapFile(std::string* existing_map_file,
|
||||
if (Loader.IsValid())
|
||||
{
|
||||
u64 TitleID = Loader.GetTitleID();
|
||||
title_id_str = StringFromFormat("%08X_%08X",
|
||||
(u32)(TitleID >> 32) & 0xFFFFFFFF,
|
||||
title_id_str = StringFromFormat("%08X_%08X", (u32)(TitleID >> 32) & 0xFFFFFFFF,
|
||||
(u32)TitleID & 0xFFFFFFFF);
|
||||
}
|
||||
break;
|
||||
@@ -130,7 +130,8 @@ bool CBoot::FindMapFile(std::string* existing_map_file,
|
||||
*title_id = title_id_str;
|
||||
|
||||
bool found = false;
|
||||
static const std::string maps_directories[] = {
|
||||
static const std::string maps_directories[] =
|
||||
{
|
||||
File::GetUserPath(D_MAPS_IDX),
|
||||
File::GetSysDirectory() + MAPS_DIR DIR_SEP
|
||||
};
|
||||
@@ -167,14 +168,18 @@ bool CBoot::LoadMapFromFilename()
|
||||
bool CBoot::Load_BS2(const std::string& _rBootROMFilename)
|
||||
{
|
||||
// CRC32
|
||||
const u32 USA_v1_0 = 0x6D740AE7; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385344#pid385344
|
||||
const u32 USA_v1_1 = 0xD5E6FEEA; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385334#pid385334
|
||||
const u32 USA_v1_2 = 0x86573808; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385399#pid385399
|
||||
const u32 BRA_v1_0 = 0x667D0B64; // GameCubes sold in Brazil have this IPL. Same as USA v1.2 but localized
|
||||
const u32 JAP_v1_0 = 0x6DAC1F2A; // Redump
|
||||
const u32 JAP_v1_1 = 0xD235E3F9; // https://bugs.dolphin-emu.org/issues/8936
|
||||
const u32 PAL_v1_0 = 0x4F319F43; // Redump
|
||||
const u32 PAL_v1_2 = 0xAD1B7F16; // Redump
|
||||
const u32 USA_v1_0 =
|
||||
0x6D740AE7; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385344#pid385344
|
||||
const u32 USA_v1_1 =
|
||||
0xD5E6FEEA; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385334#pid385334
|
||||
const u32 USA_v1_2 =
|
||||
0x86573808; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385399#pid385399
|
||||
const u32 BRA_v1_0 =
|
||||
0x667D0B64; // GameCubes sold in Brazil have this IPL. Same as USA v1.2 but localized
|
||||
const u32 JAP_v1_0 = 0x6DAC1F2A; // Redump
|
||||
const u32 JAP_v1_1 = 0xD235E3F9; // https://bugs.dolphin-emu.org/issues/8936
|
||||
const u32 PAL_v1_0 = 0x4F319F43; // Redump
|
||||
const u32 PAL_v1_2 = 0xAD1B7F16; // Redump
|
||||
|
||||
// Load the whole ROM dump
|
||||
std::string data;
|
||||
@@ -239,7 +244,6 @@ bool CBoot::Load_BS2(const std::string& _rBootROMFilename)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Third boot step after BootManager and Core. See Call schedule in BootManager.cpp
|
||||
bool CBoot::BootUp()
|
||||
{
|
||||
@@ -264,7 +268,7 @@ bool CBoot::BootUp()
|
||||
|
||||
const DiscIO::IVolume& pVolume = DVDInterface::GetVolume();
|
||||
|
||||
if ((pVolume.GetVolumeType() == DiscIO::IVolume::WII_DISC) != _StartupPara.bWii)
|
||||
if ((pVolume.GetVolumeType() == DiscIO::Platform::WII_DISC) != _StartupPara.bWii)
|
||||
{
|
||||
PanicAlertT("Warning - starting ISO in wrong console mode!");
|
||||
}
|
||||
@@ -279,7 +283,7 @@ bool CBoot::BootUp()
|
||||
WII_IPC_HLE_Interface::ES_DIVerify(tmd_buffer);
|
||||
}
|
||||
|
||||
_StartupPara.bWii = pVolume.GetVolumeType() == DiscIO::IVolume::WII_DISC;
|
||||
_StartupPara.bWii = pVolume.GetVolumeType() == DiscIO::Platform::WII_DISC;
|
||||
|
||||
// HLE BS2 or not
|
||||
if (_StartupPara.bHLE_BS2)
|
||||
@@ -338,7 +342,8 @@ bool CBoot::BootUp()
|
||||
{
|
||||
BS2Success = EmulatedBS2(dolWii);
|
||||
}
|
||||
else if ((!DVDInterface::VolumeIsValid() || DVDInterface::GetVolume().GetVolumeType() != DiscIO::IVolume::WII_DISC) &&
|
||||
else if ((!DVDInterface::VolumeIsValid() ||
|
||||
DVDInterface::GetVolume().GetVolumeType() != DiscIO::Platform::WII_DISC) &&
|
||||
!_StartupPara.m_strDefaultISO.empty())
|
||||
{
|
||||
DVDInterface::SetVolumeName(_StartupPara.m_strDefaultISO);
|
||||
@@ -348,7 +353,8 @@ bool CBoot::BootUp()
|
||||
if (!_StartupPara.m_strDVDRoot.empty())
|
||||
{
|
||||
NOTICE_LOG(BOOT, "Setting DVDRoot %s", _StartupPara.m_strDVDRoot.c_str());
|
||||
DVDInterface::SetVolumeDirectory(_StartupPara.m_strDVDRoot, dolWii, _StartupPara.m_strApploader, _StartupPara.m_strFilename);
|
||||
DVDInterface::SetVolumeDirectory(_StartupPara.m_strDVDRoot, dolWii,
|
||||
_StartupPara.m_strApploader, _StartupPara.m_strFilename);
|
||||
BS2Success = EmulatedBS2(dolWii);
|
||||
}
|
||||
|
||||
@@ -408,7 +414,7 @@ bool CBoot::BootUp()
|
||||
|
||||
// Poor man's bootup
|
||||
if (_StartupPara.bWii)
|
||||
SetupWiiMemory(DiscIO::IVolume::COUNTRY_UNKNOWN);
|
||||
SetupWiiMemory(DiscIO::Country::COUNTRY_UNKNOWN);
|
||||
else
|
||||
EmulatedBS2_GC(true);
|
||||
|
||||
@@ -437,7 +443,6 @@ bool CBoot::BootUp()
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
break;
|
||||
|
||||
|
||||
// Bootstrap 2 (AKA: Initial Program Loader, "BIOS")
|
||||
case SConfig::BOOT_BS2:
|
||||
{
|
||||
@@ -465,7 +470,8 @@ bool CBoot::BootUp()
|
||||
}
|
||||
}
|
||||
|
||||
// HLE jump to loader (homebrew). Disabled when Gecko is active as it interferes with the code handler
|
||||
// HLE jump to loader (homebrew). Disabled when Gecko is active as it interferes with the code
|
||||
// handler
|
||||
if (!SConfig::GetInstance().bEnableCheats)
|
||||
{
|
||||
HLE::Patch(0x80001800, "HBReload");
|
||||
|
@@ -7,7 +7,10 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
#include "DiscIO/Volume.h"
|
||||
namespace DiscIO
|
||||
{
|
||||
enum class Country;
|
||||
}
|
||||
|
||||
struct CountrySetting
|
||||
{
|
||||
@@ -20,7 +23,6 @@ struct CountrySetting
|
||||
class CBoot
|
||||
{
|
||||
public:
|
||||
|
||||
static bool BootUp();
|
||||
static bool IsElfWii(const std::string& filename);
|
||||
|
||||
@@ -36,8 +38,7 @@ public:
|
||||
// If title_id is not nullptr, it is set to the title id
|
||||
//
|
||||
// Returns true if a map file exists, false if none could be found.
|
||||
static bool FindMapFile(std::string* existing_map_file,
|
||||
std::string* writable_map_file,
|
||||
static bool FindMapFile(std::string* existing_map_file, std::string* writable_map_file,
|
||||
std::string* title_id = nullptr);
|
||||
|
||||
private:
|
||||
@@ -56,5 +57,5 @@ private:
|
||||
static bool Load_BS2(const std::string& _rBootROMFilename);
|
||||
static void Load_FST(bool _bIsWii);
|
||||
|
||||
static bool SetupWiiMemory(DiscIO::IVolume::ECountry country);
|
||||
static bool SetupWiiMemory(DiscIO::Country country);
|
||||
};
|
||||
|
@@ -8,18 +8,21 @@
|
||||
#include "Common/NandPaths.h"
|
||||
#include "Common/SettingsHandler.h"
|
||||
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/MemTools.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HW/CPU.h"
|
||||
#include "Core/HW/DVDInterface.h"
|
||||
#include "Core/HW/EXI_DeviceIPL.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/MemTools.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
|
||||
void CBoot::RunFunction(u32 _iAddr)
|
||||
{
|
||||
PC = _iAddr;
|
||||
@@ -56,30 +59,37 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
||||
|
||||
// It's possible to boot DOL and ELF files without a disc inserted
|
||||
if (DVDInterface::VolumeIsValid())
|
||||
DVDRead(/*offset*/0x00000000, /*address*/0x00000000, 0x20, false); // write disc info
|
||||
DVDRead(/*offset*/ 0x00000000, /*address*/ 0x00000000, 0x20, false); // write disc info
|
||||
|
||||
PowerPC::HostWrite_U32(0x0D15EA5E, 0x80000020); // Booted from bootrom. 0xE5207C22 = booted from jtag
|
||||
PowerPC::HostWrite_U32(Memory::REALRAM_SIZE, 0x80000028); // Physical Memory Size (24MB on retail)
|
||||
// TODO determine why some games fail when using a retail ID. (Seem to take different EXI paths, see Ikaruga for example)
|
||||
PowerPC::HostWrite_U32(0x10000006, 0x8000002C); // Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2
|
||||
PowerPC::HostWrite_U32(0x0D15EA5E,
|
||||
0x80000020); // Booted from bootrom. 0xE5207C22 = booted from jtag
|
||||
PowerPC::HostWrite_U32(Memory::REALRAM_SIZE,
|
||||
0x80000028); // Physical Memory Size (24MB on retail)
|
||||
// TODO determine why some games fail when using a retail ID. (Seem to take different EXI paths,
|
||||
// see Ikaruga for example)
|
||||
PowerPC::HostWrite_U32(
|
||||
0x10000006,
|
||||
0x8000002C); // Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2
|
||||
|
||||
PowerPC::HostWrite_U32(SConfig::GetInstance().bNTSC
|
||||
? 0 : 1, 0x800000CC); // Fake the VI Init of the IPL (YAGCD 4.2.1.4)
|
||||
PowerPC::HostWrite_U32(SConfig::GetInstance().bNTSC ? 0 : 1,
|
||||
0x800000CC); // Fake the VI Init of the IPL (YAGCD 4.2.1.4)
|
||||
|
||||
PowerPC::HostWrite_U32(0x01000000, 0x800000d0); // ARAM Size. 16MB main + 4/16/32MB external (retail consoles have no external ARAM)
|
||||
PowerPC::HostWrite_U32(0x01000000, 0x800000d0); // ARAM Size. 16MB main + 4/16/32MB external
|
||||
// (retail consoles have no external ARAM)
|
||||
|
||||
PowerPC::HostWrite_U32(0x09a7ec80, 0x800000F8); // Bus Clock Speed
|
||||
PowerPC::HostWrite_U32(0x1cf7c580, 0x800000FC); // CPU Clock Speed
|
||||
PowerPC::HostWrite_U32(0x09a7ec80, 0x800000F8); // Bus Clock Speed
|
||||
PowerPC::HostWrite_U32(0x1cf7c580, 0x800000FC); // CPU Clock Speed
|
||||
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000300); // Write default DFI Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000300); // Write default DFI Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
||||
|
||||
PowerPC::HostWrite_U64((u64)CEXIIPL::GetGCTime() * (u64)40500000, 0x800030D8); // Preset time base ticks
|
||||
// HIO checks this
|
||||
//PowerPC::HostWrite_U16(0x8200, 0x000030e6); // Console type
|
||||
PowerPC::HostWrite_U64((u64)CEXIIPL::GetGCTime() * (u64)40500000,
|
||||
0x800030D8); // Preset time base ticks
|
||||
// HIO checks this
|
||||
// PowerPC::HostWrite_U16(0x8200, 0x000030e6); // Console type
|
||||
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
|
||||
if (!DVDInterface::VolumeIsValid())
|
||||
return false;
|
||||
@@ -89,8 +99,7 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
const u32 apploader_offset = 0x2440;
|
||||
u32 apploader_entry, apploader_size, apploader_trailer;
|
||||
if (skipAppLoader ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, false) ||
|
||||
if (skipAppLoader || !volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, false) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, false) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x18, &apploader_trailer, false) ||
|
||||
apploader_entry == (u32)-1 || apploader_size + apploader_trailer == (u32)-1)
|
||||
@@ -104,8 +113,10 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
||||
if (SConfig::GetInstance().bNTSC)
|
||||
{
|
||||
PowerPC::ppcState.gpr[1] = 0x81566550; // StackPointer, used to be set to 0x816ffff0
|
||||
PowerPC::ppcState.gpr[2] = 0x81465cc0; // Global pointer to Small Data Area 2 Base (haven't seen anything use it...meh)
|
||||
PowerPC::ppcState.gpr[13] = 0x81465320; // Global pointer to Small Data Area Base (Luigi's Mansion's apploader uses it)
|
||||
PowerPC::ppcState.gpr[2] = 0x81465cc0; // Global pointer to Small Data Area 2 Base (haven't
|
||||
// seen anything use it...meh)
|
||||
PowerPC::ppcState.gpr[13] =
|
||||
0x81465320; // Global pointer to Small Data Area Base (Luigi's Mansion's apploader uses it)
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -148,11 +159,11 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
||||
u32 iLength = PowerPC::Read_U32(0x81300008);
|
||||
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c);
|
||||
|
||||
INFO_LOG(MASTER_LOG, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength);
|
||||
INFO_LOG(MASTER_LOG, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset,
|
||||
iRamAddress, iLength);
|
||||
DVDRead(iDVDOffset, iRamAddress, iLength, false);
|
||||
|
||||
}
|
||||
while (PowerPC::ppcState.gpr[3] != 0x00);
|
||||
} while (PowerPC::ppcState.gpr[3] != 0x00);
|
||||
|
||||
// iAppLoaderClose
|
||||
DEBUG_LOG(MASTER_LOG, "call iAppLoaderClose");
|
||||
@@ -170,31 +181,33 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoot::SetupWiiMemory(DiscIO::IVolume::ECountry country)
|
||||
bool CBoot::SetupWiiMemory(DiscIO::Country country)
|
||||
{
|
||||
static const CountrySetting SETTING_EUROPE = {"EUR", "PAL", "EU", "LE"};
|
||||
static const CountrySetting SETTING_USA = {"USA", "NTSC", "US", "LU"};
|
||||
static const CountrySetting SETTING_JAPAN = {"JPN", "NTSC", "JP", "LJ"};
|
||||
static const CountrySetting SETTING_KOREA = {"KOR", "NTSC", "KR", "LKH"};
|
||||
static const std::map<DiscIO::IVolume::ECountry, const CountrySetting> country_settings = {
|
||||
{DiscIO::IVolume::COUNTRY_EUROPE, SETTING_EUROPE},
|
||||
{DiscIO::IVolume::COUNTRY_USA, SETTING_USA},
|
||||
{DiscIO::IVolume::COUNTRY_JAPAN, SETTING_JAPAN},
|
||||
{DiscIO::IVolume::COUNTRY_KOREA, SETTING_KOREA},
|
||||
//TODO: Determine if Taiwan have their own specific settings.
|
||||
// Also determine if there are other specific settings
|
||||
// for other countries.
|
||||
{DiscIO::IVolume::COUNTRY_TAIWAN, SETTING_JAPAN}
|
||||
};
|
||||
static const CountrySetting SETTING_EUROPE = { "EUR", "PAL", "EU", "LE" };
|
||||
static const CountrySetting SETTING_USA = { "USA", "NTSC", "US", "LU" };
|
||||
static const CountrySetting SETTING_JAPAN = { "JPN", "NTSC", "JP", "LJ" };
|
||||
static const CountrySetting SETTING_KOREA = { "KOR", "NTSC", "KR", "LKH" };
|
||||
static const std::map<DiscIO::Country, const CountrySetting> country_settings = {
|
||||
{DiscIO::Country::COUNTRY_EUROPE, SETTING_EUROPE},
|
||||
{DiscIO::Country::COUNTRY_USA, SETTING_USA},
|
||||
{DiscIO::Country::COUNTRY_JAPAN, SETTING_JAPAN},
|
||||
{DiscIO::Country::COUNTRY_KOREA, SETTING_KOREA},
|
||||
// TODO: Determine if Taiwan have their own specific settings.
|
||||
// Also determine if there are other specific settings
|
||||
// for other countries.
|
||||
{DiscIO::Country::COUNTRY_TAIWAN, SETTING_JAPAN} };
|
||||
auto entryPos = country_settings.find(country);
|
||||
const CountrySetting& country_setting =
|
||||
(entryPos != country_settings.end()) ?
|
||||
entryPos->second :
|
||||
(SConfig::GetInstance().bNTSC ? SETTING_USA : SETTING_EUROPE); // default to USA or EUR depending on game's video mode
|
||||
(SConfig::GetInstance().bNTSC ?
|
||||
SETTING_USA :
|
||||
SETTING_EUROPE); // default to USA or EUR depending on game's video mode
|
||||
|
||||
SettingsHandler gen;
|
||||
std::string serno;
|
||||
std::string settings_Filename(Common::GetTitleDataPath(TITLEID_SYSMENU, Common::FROM_SESSION_ROOT) + WII_SETTING);
|
||||
std::string settings_Filename(
|
||||
Common::GetTitleDataPath(TITLEID_SYSMENU, Common::FROM_SESSION_ROOT) + WII_SETTING);
|
||||
if (File::Exists(settings_Filename))
|
||||
{
|
||||
File::IOFile settingsFileHandle(settings_Filename, "rb");
|
||||
@@ -257,51 +270,51 @@ bool CBoot::SetupWiiMemory(DiscIO::IVolume::ECountry country)
|
||||
|
||||
// When booting a WAD or the system menu, there will probably not be a disc inserted
|
||||
if (DVDInterface::VolumeIsValid())
|
||||
DVDRead(0x00000000, 0x00000000, 0x20, false); // Game Code
|
||||
DVDRead(0x00000000, 0x00000000, 0x20, false); // Game Code
|
||||
|
||||
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
|
||||
Memory::Write_U32(0x00000001, 0x00000024); // Unknown
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x00000028); // MEM1 size 24MB
|
||||
Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model
|
||||
Memory::Write_U32(0x00000000, 0x00000030); // Init
|
||||
Memory::Write_U32(0x817FEC60, 0x00000034); // Init
|
||||
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
|
||||
Memory::Write_U32(0x00000001, 0x00000024); // Unknown
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x00000028); // MEM1 size 24MB
|
||||
Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model
|
||||
Memory::Write_U32(0x00000000, 0x00000030); // Init
|
||||
Memory::Write_U32(0x817FEC60, 0x00000034); // Init
|
||||
// 38, 3C should get start, size of FST through apploader
|
||||
Memory::Write_U32(0x38a00040, 0x00000060); // Exception init
|
||||
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x000000f0); // "Simulated memory size" (debug mode?)
|
||||
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
|
||||
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
|
||||
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
|
||||
Memory::Write_U16(0x0000, 0x000030e6); // Console type
|
||||
Memory::Write_U32(0x00000000, 0x000030c0); // EXI
|
||||
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
|
||||
Memory::Write_U32(0x00000000, 0x0000310c); // Init
|
||||
Memory::Write_U32(0x8179d500, 0x00003110); // Init
|
||||
Memory::Write_U32(0x04000000, 0x00003118); // Unknown
|
||||
Memory::Write_U32(0x04000000, 0x0000311c); // BAT
|
||||
Memory::Write_U32(0x93400000, 0x00003120); // BAT
|
||||
Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low
|
||||
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(0x00000012, 0x00003138); // Console type
|
||||
Memory::Write_U32(0x38a00040, 0x00000060); // Exception init
|
||||
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x000000f0); // "Simulated memory size" (debug mode?)
|
||||
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
|
||||
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
|
||||
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
|
||||
Memory::Write_U16(0x0000, 0x000030e6); // Console type
|
||||
Memory::Write_U32(0x00000000, 0x000030c0); // EXI
|
||||
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
|
||||
Memory::Write_U32(0x00000000, 0x0000310c); // Init
|
||||
Memory::Write_U32(0x8179d500, 0x00003110); // Init
|
||||
Memory::Write_U32(0x04000000, 0x00003118); // Unknown
|
||||
Memory::Write_U32(0x04000000, 0x0000311c); // BAT
|
||||
Memory::Write_U32(0x93400000, 0x00003120); // BAT
|
||||
Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low
|
||||
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(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)
|
||||
Memory::Write_U16(0x0113, 0x0000315e); // Apploader
|
||||
Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code
|
||||
Memory::Write_U32(0x00000000, 0x00003160); // Init semaphore (sysmenu waits for this to clear)
|
||||
Memory::Write_U32(0x00090204, 0x00003188); // Expected IOS revision
|
||||
Memory::Write_U32(0x00090204, 0x00003140); // IOS revision (IOS9, v2.4)
|
||||
Memory::Write_U32(0x00062507, 0x00003144); // IOS date in USA format (June 25, 2007)
|
||||
Memory::Write_U16(0x0113, 0x0000315e); // Apploader
|
||||
Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code
|
||||
Memory::Write_U32(0x00000000, 0x00003160); // Init semaphore (sysmenu waits for this to clear)
|
||||
Memory::Write_U32(0x00090204, 0x00003188); // Expected IOS revision
|
||||
|
||||
Memory::Write_U8(0x80, 0x0000315c); // OSInit
|
||||
Memory::Write_U16(0x0000, 0x000030e0); // PADInit
|
||||
Memory::Write_U32(0x80000000, 0x00003184); // GameID Address
|
||||
Memory::Write_U8(0x80, 0x0000315c); // OSInit
|
||||
Memory::Write_U16(0x0000, 0x000030e0); // PADInit
|
||||
Memory::Write_U32(0x80000000, 0x00003184); // GameID Address
|
||||
|
||||
// Fake the VI Init of the IPL
|
||||
Memory::Write_U32(SConfig::GetInstance().bNTSC ? 0 : 1, 0x000000CC);
|
||||
@@ -323,7 +336,7 @@ bool CBoot::EmulatedBS2_Wii()
|
||||
INFO_LOG(BOOT, "Faking Wii BS2...");
|
||||
|
||||
// Setup Wii memory
|
||||
DiscIO::IVolume::ECountry country_code = DiscIO::IVolume::COUNTRY_UNKNOWN;
|
||||
DiscIO::Country country_code = DiscIO::Country::COUNTRY_UNKNOWN;
|
||||
if (DVDInterface::VolumeIsValid())
|
||||
country_code = DVDInterface::GetVolume().GetCountry();
|
||||
if (SetupWiiMemory(country_code) == false)
|
||||
@@ -331,7 +344,8 @@ bool CBoot::EmulatedBS2_Wii()
|
||||
|
||||
// Execute the apploader
|
||||
bool apploaderRan = false;
|
||||
if (DVDInterface::VolumeIsValid() && DVDInterface::GetVolume().GetVolumeType() == DiscIO::IVolume::WII_DISC)
|
||||
if (DVDInterface::VolumeIsValid() &&
|
||||
DVDInterface::GetVolume().GetVolumeType() == DiscIO::Platform::WII_DISC)
|
||||
{
|
||||
// This is some kind of consistency check that is compared to the 0x00
|
||||
// values as the game boots. This location keeps the 4 byte ID for as long
|
||||
@@ -358,15 +372,15 @@ bool CBoot::EmulatedBS2_Wii()
|
||||
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
|
||||
|
||||
Memory::Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi
|
||||
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
|
||||
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
|
||||
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
|
||||
|
||||
const u32 apploader_offset = 0x2440; // 0x1c40;
|
||||
const u32 apploader_offset = 0x2440; // 0x1c40;
|
||||
|
||||
// Load Apploader to Memory
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
@@ -380,7 +394,7 @@ bool CBoot::EmulatedBS2_Wii()
|
||||
}
|
||||
DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size, true);
|
||||
|
||||
//call iAppLoaderEntry
|
||||
// call iAppLoaderEntry
|
||||
DEBUG_LOG(BOOT, "Call iAppLoaderEntry");
|
||||
|
||||
u32 iAppLoaderFuncAddr = 0x80004000;
|
||||
@@ -415,10 +429,10 @@ bool CBoot::EmulatedBS2_Wii()
|
||||
u32 iLength = PowerPC::Read_U32(0x81300008);
|
||||
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c) << 2;
|
||||
|
||||
INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength);
|
||||
INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset,
|
||||
iRamAddress, iLength);
|
||||
DVDRead(iDVDOffset, iRamAddress, iLength, true);
|
||||
}
|
||||
while (PowerPC::ppcState.gpr[3] != 0x00);
|
||||
} while (PowerPC::ppcState.gpr[3] != 0x00);
|
||||
|
||||
// iAppLoaderClose
|
||||
DEBUG_LOG(BOOT, "Run iAppLoaderClose");
|
||||
|
@@ -31,7 +31,8 @@ CDolLoader::CDolLoader(const std::string& filename)
|
||||
}
|
||||
|
||||
CDolLoader::~CDolLoader()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
bool CDolLoader::Initialize(const std::vector<u8>& buffer)
|
||||
{
|
||||
@@ -101,10 +102,12 @@ void CDolLoader::Load() const
|
||||
// load all text (code) sections
|
||||
for (size_t i = 0; i < m_text_sections.size(); ++i)
|
||||
if (!m_text_sections[i].empty())
|
||||
Memory::CopyToEmu(m_dolheader.textAddress[i], m_text_sections[i].data(), m_text_sections[i].size());
|
||||
Memory::CopyToEmu(m_dolheader.textAddress[i], m_text_sections[i].data(),
|
||||
m_text_sections[i].size());
|
||||
|
||||
// load all data sections
|
||||
for (size_t i = 0; i < m_data_sections.size(); ++i)
|
||||
if (!m_data_sections[i].empty())
|
||||
Memory::CopyToEmu(m_dolheader.dataAddress[i], m_data_sections[i].data(), m_data_sections[i].size());
|
||||
Memory::CopyToEmu(m_dolheader.dataAddress[i], m_data_sections[i].data(),
|
||||
m_data_sections[i].size());
|
||||
}
|
||||
|
@@ -16,19 +16,9 @@ public:
|
||||
CDolLoader(const std::vector<u8>& buffer);
|
||||
~CDolLoader();
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_is_valid;
|
||||
}
|
||||
bool IsWii() const
|
||||
{
|
||||
return m_is_wii;
|
||||
}
|
||||
u32 GetEntryPoint() const
|
||||
{
|
||||
return m_dolheader.entryPoint;
|
||||
}
|
||||
|
||||
bool IsValid() const { return m_is_valid; }
|
||||
bool IsWii() const { return m_is_wii; }
|
||||
u32 GetEntryPoint() const { return m_dolheader.entryPoint; }
|
||||
// Load into emulated memory
|
||||
void Load() const;
|
||||
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/Boot/ElfReader.h"
|
||||
@@ -13,7 +14,7 @@
|
||||
bool CBoot::IsElfWii(const std::string& filename)
|
||||
{
|
||||
/* We already check if filename existed before we called this function, so
|
||||
there is no need for another check, just read the file right away */
|
||||
there is no need for another check, just read the file right away */
|
||||
|
||||
size_t filesize = File::GetSize(filename);
|
||||
auto elf = std::make_unique<u8[]>(filesize);
|
||||
@@ -50,7 +51,6 @@ bool CBoot::IsElfWii(const std::string& filename)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CBoot::Boot_ELF(const std::string& filename)
|
||||
{
|
||||
// Read ELF from file
|
||||
|
@@ -9,23 +9,24 @@
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/NandPaths.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/Boot/Boot_DOL.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/HW/VideoInterface.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/NANDContentLoader.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "DiscIO/VolumeCreator.h"
|
||||
#include "DiscIO/WiiWad.h"
|
||||
|
||||
static u32 state_checksum(u32 *buf, int len)
|
||||
static u32 state_checksum(u32* buf, int len)
|
||||
{
|
||||
u32 checksum = 0;
|
||||
len = len >> 2;
|
||||
@@ -50,7 +51,8 @@ struct StateFlags
|
||||
|
||||
bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
|
||||
{
|
||||
std::string state_filename(Common::GetTitleDataPath(TITLEID_SYSMENU, Common::FROM_SESSION_ROOT) + WII_STATE);
|
||||
std::string state_filename(Common::GetTitleDataPath(TITLEID_SYSMENU, Common::FROM_SESSION_ROOT) +
|
||||
WII_STATE);
|
||||
|
||||
if (File::Exists(state_filename))
|
||||
{
|
||||
@@ -58,7 +60,7 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
|
||||
StateFlags state;
|
||||
state_file.ReadBytes(&state, sizeof(StateFlags));
|
||||
|
||||
state.type = 0x03; // TYPE_RETURN
|
||||
state.type = 0x03; // TYPE_RETURN
|
||||
state.checksum = state_checksum((u32*)&state.flags, sizeof(StateFlags) - 4);
|
||||
|
||||
state_file.Seek(0, SEEK_SET);
|
||||
@@ -70,13 +72,14 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
|
||||
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.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::CNANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(_pFilename);
|
||||
const DiscIO::CNANDContentLoader& ContentLoader =
|
||||
DiscIO::CNANDContentManager::Access().GetNANDLoader(_pFilename);
|
||||
if (!ContentLoader.IsValid())
|
||||
return false;
|
||||
|
||||
@@ -90,12 +93,13 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
|
||||
if (!SetupWiiMemory(ContentLoader.GetCountry()))
|
||||
return false;
|
||||
// this sets a bit that is used to detect NTSC-J
|
||||
if (ContentLoader.GetCountry() == DiscIO::IVolume::COUNTRY_JAPAN)
|
||||
if (ContentLoader.GetCountry() == DiscIO::Country::COUNTRY_JAPAN)
|
||||
{
|
||||
VideoInterface::SetRegionReg('J');
|
||||
}
|
||||
// DOL
|
||||
const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex());
|
||||
const DiscIO::SNANDContent* pContent =
|
||||
ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex());
|
||||
if (pContent == nullptr)
|
||||
return false;
|
||||
|
||||
@@ -125,4 +129,3 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -13,16 +13,16 @@
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||
|
||||
static void bswap(u32 &w)
|
||||
static void bswap(u32& w)
|
||||
{
|
||||
w = Common::swap32(w);
|
||||
}
|
||||
static void bswap(u16 &w)
|
||||
static void bswap(u16& w)
|
||||
{
|
||||
w = Common::swap16(w);
|
||||
}
|
||||
|
||||
static void byteswapHeader(Elf32_Ehdr &ELF_H)
|
||||
static void byteswapHeader(Elf32_Ehdr& ELF_H)
|
||||
{
|
||||
bswap(ELF_H.e_type);
|
||||
bswap(ELF_H.e_machine);
|
||||
@@ -39,7 +39,7 @@ static void byteswapHeader(Elf32_Ehdr &ELF_H)
|
||||
bswap(ELF_H.e_flags);
|
||||
}
|
||||
|
||||
static void byteswapSegment(Elf32_Phdr &sec)
|
||||
static void byteswapSegment(Elf32_Phdr& sec)
|
||||
{
|
||||
bswap(sec.p_align);
|
||||
bswap(sec.p_filesz);
|
||||
@@ -51,7 +51,7 @@ static void byteswapSegment(Elf32_Phdr &sec)
|
||||
bswap(sec.p_type);
|
||||
}
|
||||
|
||||
static void byteswapSection(Elf32_Shdr &sec)
|
||||
static void byteswapSection(Elf32_Shdr& sec)
|
||||
{
|
||||
bswap(sec.sh_addr);
|
||||
bswap(sec.sh_addralign);
|
||||
@@ -65,15 +65,15 @@ static void byteswapSection(Elf32_Shdr &sec)
|
||||
bswap(sec.sh_type);
|
||||
}
|
||||
|
||||
ElfReader::ElfReader(void *ptr)
|
||||
ElfReader::ElfReader(void* ptr)
|
||||
{
|
||||
base = (char*)ptr;
|
||||
base32 = (u32*)ptr;
|
||||
header = (Elf32_Ehdr*)ptr;
|
||||
byteswapHeader(*header);
|
||||
|
||||
segments = (Elf32_Phdr *)(base + header->e_phoff);
|
||||
sections = (Elf32_Shdr *)(base + header->e_shoff);
|
||||
segments = (Elf32_Phdr*)(base + header->e_phoff);
|
||||
sections = (Elf32_Shdr*)(base + header->e_shoff);
|
||||
|
||||
for (int i = 0; i < GetNumSegments(); i++)
|
||||
{
|
||||
@@ -122,8 +122,8 @@ bool ElfReader::LoadIntoMemory()
|
||||
{
|
||||
Elf32_Phdr* p = segments + i;
|
||||
|
||||
INFO_LOG(MASTER_LOG, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ",
|
||||
p->p_type, p->p_vaddr, p->p_filesz, p->p_memsz);
|
||||
INFO_LOG(MASTER_LOG, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr,
|
||||
p->p_filesz, p->p_memsz);
|
||||
|
||||
if (p->p_type == PT_LOAD)
|
||||
{
|
||||
@@ -134,7 +134,7 @@ bool ElfReader::LoadIntoMemory()
|
||||
|
||||
Memory::CopyToEmu(writeAddr, src, srcSize);
|
||||
if (srcSize < dstSize)
|
||||
Memory::Memset(writeAddr + srcSize, 0, dstSize - srcSize); //zero out bss
|
||||
Memory::Memset(writeAddr + srcSize, 0, dstSize - srcSize); // zero out bss
|
||||
|
||||
INFO_LOG(MASTER_LOG, "Loadable Segment Copied to %08x, size %08x", writeAddr, p->p_memsz);
|
||||
}
|
||||
@@ -144,7 +144,7 @@ bool ElfReader::LoadIntoMemory()
|
||||
return true;
|
||||
}
|
||||
|
||||
SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const
|
||||
SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const
|
||||
{
|
||||
for (int i = firstSection; i < header->e_shnum; i++)
|
||||
{
|
||||
@@ -163,10 +163,10 @@ bool ElfReader::LoadSymbols()
|
||||
if (sec != -1)
|
||||
{
|
||||
int stringSection = sections[sec].sh_link;
|
||||
const char* stringBase = (const char *)GetSectionDataPtr(stringSection);
|
||||
const char* stringBase = (const char*)GetSectionDataPtr(stringSection);
|
||||
|
||||
//We have a symbol table!
|
||||
Elf32_Sym* symtab = (Elf32_Sym *)(GetSectionDataPtr(sec));
|
||||
// We have a symbol table!
|
||||
Elf32_Sym* symtab = (Elf32_Sym*)(GetSectionDataPtr(sec));
|
||||
int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
|
||||
for (int sym = 0; sym < numSymbols; sym++)
|
||||
{
|
||||
@@ -186,9 +186,11 @@ bool ElfReader::LoadSymbols()
|
||||
switch (type)
|
||||
{
|
||||
case STT_OBJECT:
|
||||
symtype = Symbol::SYMBOL_DATA; break;
|
||||
symtype = Symbol::SYMBOL_DATA;
|
||||
break;
|
||||
case STT_FUNC:
|
||||
symtype = Symbol::SYMBOL_FUNCTION; break;
|
||||
symtype = Symbol::SYMBOL_FUNCTION;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
@@ -26,54 +26,27 @@ private:
|
||||
Elf32_Phdr* segments;
|
||||
Elf32_Shdr* sections;
|
||||
|
||||
u32 *sectionAddrs;
|
||||
u32* sectionAddrs;
|
||||
bool bRelocate;
|
||||
u32 entryPoint;
|
||||
|
||||
public:
|
||||
ElfReader(void* ptr);
|
||||
~ElfReader()
|
||||
{}
|
||||
|
||||
u32 Read32(int off) const
|
||||
{
|
||||
return base32[off >> 2];
|
||||
}
|
||||
|
||||
~ElfReader() {}
|
||||
u32 Read32(int off) const { return base32[off >> 2]; }
|
||||
// Quick accessors
|
||||
ElfType GetType() const
|
||||
{
|
||||
return (ElfType)(header->e_type);
|
||||
}
|
||||
ElfMachine GetMachine() const
|
||||
{
|
||||
return (ElfMachine)(header->e_machine);
|
||||
}
|
||||
u32 GetEntryPoint() const
|
||||
{
|
||||
return entryPoint;
|
||||
}
|
||||
u32 GetFlags() const
|
||||
{
|
||||
return (u32)(header->e_flags);
|
||||
}
|
||||
ElfType GetType() const { return (ElfType)(header->e_type); }
|
||||
ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); }
|
||||
u32 GetEntryPoint() const { return entryPoint; }
|
||||
u32 GetFlags() const { return (u32)(header->e_flags); }
|
||||
bool LoadIntoMemory();
|
||||
bool LoadSymbols();
|
||||
|
||||
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;
|
||||
}
|
||||
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; }
|
||||
const char* GetSectionName(int section) const;
|
||||
const u8 *GetSectionDataPtr(int section) const
|
||||
const u8* GetSectionDataPtr(int section) const
|
||||
{
|
||||
if (section < 0 || section >= header->e_shnum)
|
||||
return nullptr;
|
||||
@@ -82,26 +55,11 @@ public:
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
bool IsCodeSection(int section) const
|
||||
{
|
||||
return sections[section].sh_type == SHT_PROGBITS;
|
||||
}
|
||||
const u8* GetSegmentPtr(int segment)
|
||||
{
|
||||
return GetPtr(segments[segment].p_offset);
|
||||
}
|
||||
u32 GetSectionAddr(SectionID section) const
|
||||
{
|
||||
return sectionAddrs[section];
|
||||
}
|
||||
int GetSectionSize(SectionID section) const
|
||||
{
|
||||
return sections[section].sh_size;
|
||||
}
|
||||
SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found
|
||||
bool IsCodeSection(int section) const { return sections[section].sh_type == SHT_PROGBITS; }
|
||||
const u8* GetSegmentPtr(int segment) { return GetPtr(segments[segment].p_offset); }
|
||||
u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; }
|
||||
int GetSectionSize(SectionID section) const { return sections[section].sh_size; }
|
||||
SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found
|
||||
|
||||
bool DidRelocate() const
|
||||
{
|
||||
return bRelocate;
|
||||
}
|
||||
bool DidRelocate() const { return bRelocate; }
|
||||
};
|
||||
|
@@ -34,62 +34,60 @@ enum ElfMachine
|
||||
};
|
||||
|
||||
// File version
|
||||
#define EV_NONE 0
|
||||
#define EV_NONE 0
|
||||
#define EV_CURRENT 1
|
||||
|
||||
// Identification index
|
||||
#define EI_MAG0 0
|
||||
#define EI_MAG1 1
|
||||
#define EI_MAG2 2
|
||||
#define EI_MAG3 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define EI_MAG0 0
|
||||
#define EI_MAG1 1
|
||||
#define EI_MAG2 2
|
||||
#define EI_MAG3 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define EI_VERSION 6
|
||||
#define EI_PAD 7
|
||||
#define EI_PAD 7
|
||||
#define EI_NIDENT 16
|
||||
|
||||
// Magic number
|
||||
#define ELFMAG0 0x7F
|
||||
#define ELFMAG1 'E'
|
||||
#define ELFMAG2 'L'
|
||||
#define ELFMAG3 'F'
|
||||
#define ELFMAG1 'E'
|
||||
#define ELFMAG2 'L'
|
||||
#define ELFMAG3 'F'
|
||||
|
||||
// File class
|
||||
#define ELFCLASSNONE 0
|
||||
#define ELFCLASS32 1
|
||||
#define ELFCLASS64 2
|
||||
#define ELFCLASS32 1
|
||||
#define ELFCLASS64 2
|
||||
|
||||
// Encoding
|
||||
#define ELFDATANONE 0
|
||||
#define ELFDATA2LSB 1
|
||||
#define ELFDATA2MSB 2
|
||||
|
||||
|
||||
|
||||
// Sections constants
|
||||
|
||||
// Section indexes
|
||||
#define SHN_UNDEF 0
|
||||
#define SHN_UNDEF 0
|
||||
#define SHN_LORESERVE 0xFF00
|
||||
#define SHN_LOPROC 0xFF00
|
||||
#define SHN_HIPROC 0xFF1F
|
||||
#define SHN_ABS 0xFFF1
|
||||
#define SHN_COMMON 0xFFF2
|
||||
#define SHN_LOPROC 0xFF00
|
||||
#define SHN_HIPROC 0xFF1F
|
||||
#define SHN_ABS 0xFFF1
|
||||
#define SHN_COMMON 0xFFF2
|
||||
#define SHN_HIRESERVE 0xFFFF
|
||||
|
||||
// Section types
|
||||
#define SHT_NULL 0
|
||||
#define SHT_PROGBITS 1
|
||||
#define SHT_SYMTAB 2
|
||||
#define SHT_STRTAB 3
|
||||
#define SHT_RELA 4
|
||||
#define SHT_HASH 5
|
||||
#define SHT_DYNAMIC 6
|
||||
#define SHT_NOTE 7
|
||||
#define SHT_NOBITS 8
|
||||
#define SHT_REL 9
|
||||
#define SHT_SHLIB 10
|
||||
#define SHT_DYNSYM 11
|
||||
#define SHT_NULL 0
|
||||
#define SHT_PROGBITS 1
|
||||
#define SHT_SYMTAB 2
|
||||
#define SHT_STRTAB 3
|
||||
#define SHT_RELA 4
|
||||
#define SHT_HASH 5
|
||||
#define SHT_DYNAMIC 6
|
||||
#define SHT_NOTE 7
|
||||
#define SHT_NOBITS 8
|
||||
#define SHT_REL 9
|
||||
#define SHT_SHLIB 10
|
||||
#define SHT_DYNSYM 11
|
||||
#define SHT_LOPROC 0x70000000
|
||||
#define SHT_HIPROC 0x7FFFFFFF
|
||||
#define SHT_LOUSER 0x80000000
|
||||
@@ -98,7 +96,6 @@ enum ElfMachine
|
||||
// Custom section types
|
||||
#define SHT_PSPREL 0x700000a0
|
||||
|
||||
|
||||
// Section flags
|
||||
enum ElfSectionFlags
|
||||
{
|
||||
@@ -109,47 +106,47 @@ enum ElfSectionFlags
|
||||
};
|
||||
|
||||
// Symbol binding
|
||||
#define STB_LOCAL 0
|
||||
#define STB_GLOBAL 1
|
||||
#define STB_WEAK 2
|
||||
#define STB_LOCAL 0
|
||||
#define STB_GLOBAL 1
|
||||
#define STB_WEAK 2
|
||||
#define STB_LOPROC 13
|
||||
#define STB_HIPROC 15
|
||||
|
||||
// Symbol types
|
||||
#define STT_NOTYPE 0
|
||||
#define STT_OBJECT 1
|
||||
#define STT_FUNC 2
|
||||
#define STT_SECTION 3
|
||||
#define STT_FILE 4
|
||||
#define STT_LOPROC 13
|
||||
#define STT_HIPROC 15
|
||||
#define STT_NOTYPE 0
|
||||
#define STT_OBJECT 1
|
||||
#define STT_FUNC 2
|
||||
#define STT_SECTION 3
|
||||
#define STT_FILE 4
|
||||
#define STT_LOPROC 13
|
||||
#define STT_HIPROC 15
|
||||
|
||||
// Undefined name
|
||||
#define STN_UNDEF 0
|
||||
|
||||
// Relocation types
|
||||
#define R_386_NONE 0
|
||||
#define R_386_32 1
|
||||
#define R_386_PC32 2
|
||||
#define R_386_GOT32 3
|
||||
#define R_386_PLT32 4
|
||||
#define R_386_COPY 5
|
||||
#define R_386_GLOB_DAT 6
|
||||
#define R_386_JMP_SLOT 7
|
||||
#define R_386_RELATIVE 8
|
||||
#define R_386_GOTOFF 9
|
||||
#define R_386_GOTPC 10
|
||||
#define R_386_NONE 0
|
||||
#define R_386_32 1
|
||||
#define R_386_PC32 2
|
||||
#define R_386_GOT32 3
|
||||
#define R_386_PLT32 4
|
||||
#define R_386_COPY 5
|
||||
#define R_386_GLOB_DAT 6
|
||||
#define R_386_JMP_SLOT 7
|
||||
#define R_386_RELATIVE 8
|
||||
#define R_386_GOTOFF 9
|
||||
#define R_386_GOTPC 10
|
||||
|
||||
// Segment types
|
||||
#define PT_NULL 0
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define PT_NOTE 4
|
||||
#define PT_SHLIB 5
|
||||
#define PT_PHDR 6
|
||||
#define PT_LOPROC 0x70000000
|
||||
#define PT_HIPROC 0x7FFFFFFF
|
||||
#define PT_NULL 0
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define PT_NOTE 4
|
||||
#define PT_SHLIB 5
|
||||
#define PT_PHDR 6
|
||||
#define PT_LOPROC 0x70000000
|
||||
#define PT_HIPROC 0x7FFFFFFF
|
||||
|
||||
// Segment flags
|
||||
#define PF_X 1
|
||||
@@ -157,50 +154,50 @@ enum ElfSectionFlags
|
||||
#define PF_R 4
|
||||
|
||||
// Dynamic Array Tags
|
||||
#define DT_NULL 0
|
||||
#define DT_NEEDED 1
|
||||
#define DT_PLTRELSZ 2
|
||||
#define DT_PLTGOT 3
|
||||
#define DT_HASH 4
|
||||
#define DT_STRTAB 5
|
||||
#define DT_SYMTAB 6
|
||||
#define DT_RELA 7
|
||||
#define DT_RELASZ 8
|
||||
#define DT_RELAENT 9
|
||||
#define DT_STRSZ 10
|
||||
#define DT_SYMENT 11
|
||||
#define DT_INIT 12
|
||||
#define DT_FINI 13
|
||||
#define DT_SONAME 14
|
||||
#define DT_RPATH 15
|
||||
#define DT_SYMBOLIC 16
|
||||
#define DT_REL 17
|
||||
#define DT_RELSZ 18
|
||||
#define DT_RELENT 19
|
||||
#define DT_PLTREL 20
|
||||
#define DT_DEBUG 21
|
||||
#define DT_TEXTREL 22
|
||||
#define DT_JMPREL 23
|
||||
#define DT_LOPROC 0x70000000
|
||||
#define DT_HIPROC 0x7FFFFFFF
|
||||
#define DT_NULL 0
|
||||
#define DT_NEEDED 1
|
||||
#define DT_PLTRELSZ 2
|
||||
#define DT_PLTGOT 3
|
||||
#define DT_HASH 4
|
||||
#define DT_STRTAB 5
|
||||
#define DT_SYMTAB 6
|
||||
#define DT_RELA 7
|
||||
#define DT_RELASZ 8
|
||||
#define DT_RELAENT 9
|
||||
#define DT_STRSZ 10
|
||||
#define DT_SYMENT 11
|
||||
#define DT_INIT 12
|
||||
#define DT_FINI 13
|
||||
#define DT_SONAME 14
|
||||
#define DT_RPATH 15
|
||||
#define DT_SYMBOLIC 16
|
||||
#define DT_REL 17
|
||||
#define DT_RELSZ 18
|
||||
#define DT_RELENT 19
|
||||
#define DT_PLTREL 20
|
||||
#define DT_DEBUG 21
|
||||
#define DT_TEXTREL 22
|
||||
#define DT_JMPREL 23
|
||||
#define DT_LOPROC 0x70000000
|
||||
#define DT_HIPROC 0x7FFFFFFF
|
||||
|
||||
// ELF file header
|
||||
struct Elf32_Ehdr
|
||||
{
|
||||
u8 e_ident[EI_NIDENT];
|
||||
u16 e_type;
|
||||
u16 e_machine;
|
||||
u32 e_version;
|
||||
u32 e_entry;
|
||||
u32 e_phoff;
|
||||
u32 e_shoff;
|
||||
u32 e_flags;
|
||||
u16 e_ehsize;
|
||||
u16 e_phentsize;
|
||||
u16 e_phnum;
|
||||
u16 e_shentsize;
|
||||
u16 e_shnum;
|
||||
u16 e_shstrndx;
|
||||
u8 e_ident[EI_NIDENT];
|
||||
u16 e_type;
|
||||
u16 e_machine;
|
||||
u32 e_version;
|
||||
u32 e_entry;
|
||||
u32 e_phoff;
|
||||
u32 e_shoff;
|
||||
u32 e_flags;
|
||||
u16 e_ehsize;
|
||||
u16 e_phentsize;
|
||||
u16 e_phnum;
|
||||
u16 e_shentsize;
|
||||
u16 e_shnum;
|
||||
u16 e_shstrndx;
|
||||
};
|
||||
|
||||
// Section header
|
||||
@@ -237,14 +234,14 @@ struct Elf32_Sym
|
||||
u32 st_name;
|
||||
u32 st_value;
|
||||
u32 st_size;
|
||||
u8 st_info;
|
||||
u8 st_other;
|
||||
u8 st_info;
|
||||
u8 st_other;
|
||||
u16 st_shndx;
|
||||
};
|
||||
|
||||
#define ELF32_ST_BIND(i) ((i)>>4)
|
||||
#define ELF32_ST_TYPE(i) ((i)&0xf)
|
||||
#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
|
||||
#define ELF32_ST_BIND(i) ((i) >> 4)
|
||||
#define ELF32_ST_TYPE(i) ((i)&0xf)
|
||||
#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t)&0xf))
|
||||
|
||||
// Relocation entries
|
||||
struct Elf32_Rel
|
||||
@@ -260,16 +257,14 @@ struct Elf32_Rela
|
||||
s32 r_addend;
|
||||
};
|
||||
|
||||
#define ELF32_R_SYM(i) ((i)>>8)
|
||||
#define ELF32_R_SYM(i) ((i) >> 8)
|
||||
#define ELF32_R_TYPE(i) ((u8)(i))
|
||||
#define ELF32_R_INFO(s,t) (((s)<<8 )+(u8)(t))
|
||||
|
||||
#define ELF32_R_INFO(s, t) (((s) << 8) + (u8)(t))
|
||||
|
||||
struct Elf32_Dyn
|
||||
{
|
||||
s32 d_tag;
|
||||
union
|
||||
{
|
||||
union {
|
||||
u32 d_val;
|
||||
u32 d_ptr;
|
||||
} d_un;
|
||||
|
@@ -11,52 +11,41 @@
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h" // for bWii
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/Boot/Boot_DOL.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h" // for bWii
|
||||
#include "Core/FifoPlayer/FifoDataFile.h"
|
||||
#include "Core/HW/SI.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/NANDContentLoader.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "DiscIO/VolumeCreator.h"
|
||||
|
||||
SConfig* SConfig::m_Instance;
|
||||
|
||||
SConfig::SConfig()
|
||||
: bEnableDebugging(false), bAutomaticStart(false), bBootToPause(false),
|
||||
bJITNoBlockCache(false), bJITNoBlockLinking(false),
|
||||
bJITOff(false),
|
||||
bJITLoadStoreOff(false), bJITLoadStorelXzOff(false),
|
||||
bJITLoadStorelwzOff(false), bJITLoadStorelbzxOff(false),
|
||||
bJITLoadStoreFloatingOff(false), bJITLoadStorePairedOff(false),
|
||||
bJITFloatingPointOff(false), bJITIntegerOff(false),
|
||||
bJITPairedOff(false), bJITSystemRegistersOff(false),
|
||||
bJITBranchOff(false),
|
||||
bJITILTimeProfiling(false), bJITILOutputIR(false),
|
||||
bFPRF(false), bAccurateNaNs(false), iTimingVariance(40),
|
||||
bCPUThread(true), bDSPThread(false), bDSPHLE(true),
|
||||
: bEnableDebugging(false), bAutomaticStart(false), bBootToPause(false), bJITNoBlockCache(false),
|
||||
bJITNoBlockLinking(false), bJITOff(false), bJITLoadStoreOff(false),
|
||||
bJITLoadStorelXzOff(false), bJITLoadStorelwzOff(false), bJITLoadStorelbzxOff(false),
|
||||
bJITLoadStoreFloatingOff(false), bJITLoadStorePairedOff(false), bJITFloatingPointOff(false),
|
||||
bJITIntegerOff(false), bJITPairedOff(false), bJITSystemRegistersOff(false),
|
||||
bJITBranchOff(false), bJITILTimeProfiling(false), bJITILOutputIR(false), bFPRF(false),
|
||||
bAccurateNaNs(false), iTimingVariance(40), bCPUThread(true), bDSPThread(false), bDSPHLE(true),
|
||||
bSkipIdle(true), bSyncGPUOnSkipIdleHack(true), bNTSC(false), bForceNTSCJ(false),
|
||||
bHLE_BS2(true), bEnableCheats(false),
|
||||
bEnableMemcardSdWriting(true),
|
||||
bDPL2Decoder(false), bTimeStretching(false), bRSHACK(false), bWiiSpeakSupport(false), iLatency(14),
|
||||
bRunCompareServer(false), bRunCompareClient(false),
|
||||
bMMU(false), bDCBZOFF(false),
|
||||
iBBDumpPort(0), bDoubleVideoRate(false),
|
||||
bFastDiscSpeed(false), bSyncGPU(false),
|
||||
SelectedLanguage(0), bOverrideGCLanguage(false), bWii(false),
|
||||
bConfirmStop(false), bHideCursor(false),
|
||||
bHLE_BS2(true), bEnableCheats(false), bEnableMemcardSdWriting(true), bDPL2Decoder(false),
|
||||
iLatency(14), bRunCompareServer(false), bRunCompareClient(false), bMMU(false),
|
||||
bDCBZOFF(false), iBBDumpPort(0), bFastDiscSpeed(false), bSyncGPU(false), SelectedLanguage(0),
|
||||
bOverrideGCLanguage(false), bWii(false), bConfirmStop(false), bHideCursor(false),
|
||||
bTimeStretching(false), bRSHACK(false), bWiiSpeakSupport(false),
|
||||
bAutoHideCursor(false), bUsePanicHandlers(true), bOnScreenDisplayMessages(true),
|
||||
iRenderWindowXPos(-1), iRenderWindowYPos(-1),
|
||||
iRenderWindowWidth(640), iRenderWindowHeight(480),
|
||||
bRenderWindowAutoSize(false), bKeepWindowOnTop(false),
|
||||
bFullscreen(false), bRenderToMain(false),
|
||||
bProgressive(false), bPAL60(false),
|
||||
bDisableScreenSaver(false),
|
||||
iPosX(100), iPosY(100), iWidth(800), iHeight(600),
|
||||
m_analytics_enabled(false), m_analytics_permission_asked(false),
|
||||
bLoopFifoReplay(true)
|
||||
iRenderWindowXPos(-1), iRenderWindowYPos(-1), iRenderWindowWidth(640),
|
||||
iRenderWindowHeight(480), bRenderWindowAutoSize(false), bKeepWindowOnTop(false),
|
||||
bFullscreen(false), bRenderToMain(false), bProgressive(false), bPAL60(false),
|
||||
bDisableScreenSaver(false), iPosX(100), iPosY(100), iWidth(800), iHeight(600),
|
||||
m_analytics_enabled(false), m_analytics_permission_asked(false), bLoopFifoReplay(true)
|
||||
{
|
||||
LoadDefaults();
|
||||
// Make sure we have log manager
|
||||
@@ -80,12 +69,11 @@ SConfig::~SConfig()
|
||||
delete m_SYSCONF;
|
||||
}
|
||||
|
||||
|
||||
void SConfig::SaveSettings()
|
||||
{
|
||||
NOTICE_LOG(BOOT, "Saving settings to %s", File::GetUserPath(F_DOLPHINCONFIG_IDX).c_str());
|
||||
IniFile ini;
|
||||
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); // load first to not kill unknown stuff
|
||||
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); // load first to not kill unknown stuff
|
||||
|
||||
SaveGeneralSettings(ini);
|
||||
SaveInterfaceSettings(ini);
|
||||
@@ -164,8 +152,8 @@ void SConfig::SaveInterfaceSettings(IniFile& ini)
|
||||
interface->Set("OnScreenDisplayMessages", bOnScreenDisplayMessages);
|
||||
interface->Set("HideCursor", bHideCursor);
|
||||
interface->Set("AutoHideCursor", bAutoHideCursor);
|
||||
interface->Set("MainWindowPosX", (iPosX == -32000) ? 0 : iPosX); // TODO - HAX
|
||||
interface->Set("MainWindowPosY", (iPosY == -32000) ? 0 : iPosY); // TODO - HAX
|
||||
interface->Set("MainWindowPosX", (iPosX == -32000) ? 0 : iPosX); // TODO - HAX
|
||||
interface->Set("MainWindowPosY", (iPosY == -32000) ? 0 : iPosY); // TODO - HAX
|
||||
interface->Set("MainWindowWidth", iWidth);
|
||||
interface->Set("MainWindowHeight", iHeight);
|
||||
interface->Set("Language", m_InterfaceLanguage);
|
||||
@@ -415,6 +403,8 @@ void SConfig::LoadGeneralSettings(IniFile& ini)
|
||||
|
||||
general->Get("NANDRootPath", &m_NANDPath);
|
||||
File::SetUserPath(D_WIIROOT_IDX, m_NANDPath);
|
||||
general->Get("DumpPath", &m_DumpPath);
|
||||
CreateDumpPath(m_DumpPath);
|
||||
general->Get("WirelessMac", &m_WirelessMac);
|
||||
}
|
||||
|
||||
@@ -542,7 +532,8 @@ void SConfig::LoadCoreSettings(IniFile& ini)
|
||||
core->Get("OutputIR", &bJITILOutputIR, false);
|
||||
for (int i = 0; i < MAX_SI_CHANNELS; ++i)
|
||||
{
|
||||
core->Get(StringFromFormat("SIDevice%i", i), (u32*)&m_SIDevice[i], (i == 0) ? SIDEVICE_GC_CONTROLLER : SIDEVICE_NONE);
|
||||
core->Get(StringFromFormat("SIDevice%i", i), (u32*)&m_SIDevice[i],
|
||||
(i == 0) ? SIDEVICE_GC_CONTROLLER : SIDEVICE_NONE);
|
||||
core->Get(StringFromFormat("AdapterRumble%i", i), &m_AdapterRumble[i], true);
|
||||
core->Get(StringFromFormat("SimulateKonga%i", i), &m_AdapterKonga[i], false);
|
||||
}
|
||||
@@ -679,7 +670,7 @@ void SConfig::LoadDefaults()
|
||||
|
||||
bLoopFifoReplay = true;
|
||||
|
||||
bJITOff = false; // debugger only settings
|
||||
bJITOff = false; // debugger only settings
|
||||
bJITLoadStoreOff = false;
|
||||
bJITLoadStoreFloatingOff = false;
|
||||
bJITLoadStorePairedOff = false;
|
||||
@@ -693,31 +684,32 @@ void SConfig::LoadDefaults()
|
||||
m_strUniqueID = "00000000";
|
||||
m_revision = 0;
|
||||
}
|
||||
static const char* GetRegionOfCountry(DiscIO::IVolume::ECountry country)
|
||||
|
||||
static const char* GetRegionOfCountry(DiscIO::Country country)
|
||||
{
|
||||
switch (country)
|
||||
{
|
||||
case DiscIO::IVolume::COUNTRY_USA:
|
||||
case DiscIO::Country::COUNTRY_USA:
|
||||
return USA_DIR;
|
||||
|
||||
case DiscIO::IVolume::COUNTRY_TAIWAN:
|
||||
case DiscIO::IVolume::COUNTRY_KOREA:
|
||||
case DiscIO::Country::COUNTRY_TAIWAN:
|
||||
case DiscIO::Country::COUNTRY_KOREA:
|
||||
// TODO: Should these have their own Region Dir?
|
||||
case DiscIO::IVolume::COUNTRY_JAPAN:
|
||||
case DiscIO::Country::COUNTRY_JAPAN:
|
||||
return JAP_DIR;
|
||||
|
||||
case DiscIO::IVolume::COUNTRY_AUSTRALIA:
|
||||
case DiscIO::IVolume::COUNTRY_EUROPE:
|
||||
case DiscIO::IVolume::COUNTRY_FRANCE:
|
||||
case DiscIO::IVolume::COUNTRY_GERMANY:
|
||||
case DiscIO::IVolume::COUNTRY_ITALY:
|
||||
case DiscIO::IVolume::COUNTRY_NETHERLANDS:
|
||||
case DiscIO::IVolume::COUNTRY_RUSSIA:
|
||||
case DiscIO::IVolume::COUNTRY_SPAIN:
|
||||
case DiscIO::IVolume::COUNTRY_WORLD:
|
||||
case DiscIO::Country::COUNTRY_AUSTRALIA:
|
||||
case DiscIO::Country::COUNTRY_EUROPE:
|
||||
case DiscIO::Country::COUNTRY_FRANCE:
|
||||
case DiscIO::Country::COUNTRY_GERMANY:
|
||||
case DiscIO::Country::COUNTRY_ITALY:
|
||||
case DiscIO::Country::COUNTRY_NETHERLANDS:
|
||||
case DiscIO::Country::COUNTRY_RUSSIA:
|
||||
case DiscIO::Country::COUNTRY_SPAIN:
|
||||
case DiscIO::Country::COUNTRY_WORLD:
|
||||
return EUR_DIR;
|
||||
|
||||
case DiscIO::IVolume::COUNTRY_UNKNOWN:
|
||||
case DiscIO::Country::COUNTRY_UNKNOWN:
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@@ -742,12 +734,9 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
|
||||
|
||||
std::string Extension;
|
||||
SplitPath(m_strFilename, nullptr, nullptr, &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)
|
||||
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)
|
||||
{
|
||||
m_BootType = BOOT_ISO;
|
||||
std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(m_strFilename));
|
||||
@@ -757,7 +746,8 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
|
||||
PanicAlertT("Could not read \"%s\". "
|
||||
"There is no disc in the drive, or it is not a GC/Wii backup. "
|
||||
"Please note that original GameCube and Wii discs cannot be read "
|
||||
"by most PC DVD drives.", m_strFilename.c_str());
|
||||
"by most PC DVD drives.",
|
||||
m_strFilename.c_str());
|
||||
else
|
||||
PanicAlertT("\"%s\" is an invalid GCM/ISO file, or is not a GC/Wii ISO.",
|
||||
m_strFilename.c_str());
|
||||
@@ -768,7 +758,7 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
|
||||
m_revision = pVolume->GetRevision();
|
||||
|
||||
// Check if we have a Wii disc
|
||||
bWii = pVolume->GetVolumeType() == DiscIO::IVolume::WII_DISC;
|
||||
bWii = pVolume->GetVolumeType() == DiscIO::Platform::WII_DISC;
|
||||
|
||||
const char* retrieved_region_dir = GetRegionOfCountry(pVolume->GetCountry());
|
||||
if (!retrieved_region_dir)
|
||||
@@ -786,8 +776,10 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
|
||||
{
|
||||
bWii = CBoot::IsElfWii(m_strFilename);
|
||||
// TODO: Right now GC homebrew boots in NTSC and Wii homebrew in PAL.
|
||||
// This is intentional so that Wii homebrew can boot in both 50Hz and 60Hz, without forcing all GC homebrew to 50Hz.
|
||||
// In the future, it probably makes sense to add a Region setting for homebrew somewhere in the emulator config.
|
||||
// This is intentional so that Wii homebrew can boot in both 50Hz and 60Hz, without forcing
|
||||
// all GC homebrew to 50Hz.
|
||||
// In the future, it probably makes sense to add a Region setting for homebrew somewhere in
|
||||
// the emulator config.
|
||||
bNTSC = bWii ? false : true;
|
||||
set_region_dir = bNTSC ? USA_DIR : EUR_DIR;
|
||||
m_BootType = BOOT_ELF;
|
||||
@@ -818,15 +810,16 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
|
||||
else if (DiscIO::CNANDContentManager::Access().GetNANDLoader(m_strFilename).IsValid())
|
||||
{
|
||||
std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(m_strFilename));
|
||||
const DiscIO::CNANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_strFilename);
|
||||
const DiscIO::CNANDContentLoader& ContentLoader =
|
||||
DiscIO::CNANDContentManager::Access().GetNANDLoader(m_strFilename);
|
||||
|
||||
if (ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex()) == nullptr)
|
||||
{
|
||||
//WAD is valid yet cannot be booted. Install instead.
|
||||
// WAD is valid yet cannot be booted. Install instead.
|
||||
u64 installed = DiscIO::CNANDContentManager::Access().Install_WiiWAD(m_strFilename);
|
||||
if (installed)
|
||||
SuccessAlertT("The WAD has been installed successfully");
|
||||
return false; //do not boot
|
||||
return false; // do not boot
|
||||
}
|
||||
|
||||
const char* retrieved_region_dir = GetRegionOfCountry(ContentLoader.GetCountry());
|
||||
@@ -850,7 +843,8 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
|
||||
}
|
||||
|
||||
// Use the TitleIDhex for name and/or unique ID if launching from nand folder
|
||||
// or if it is not ascii characters (specifically sysmenu could potentially apply to other things)
|
||||
// or if it is not ascii characters (specifically sysmenu could potentially apply to other
|
||||
// things)
|
||||
std::string titleidstr = StringFromFormat("%016" PRIx64, ContentLoader.GetTitleID());
|
||||
|
||||
if (m_strName.empty())
|
||||
@@ -899,7 +893,8 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
|
||||
{
|
||||
m_strBootROM = File::GetUserPath(D_GCUSER_IDX) + DIR_SEP + set_region_dir + DIR_SEP GC_IPL;
|
||||
if (!File::Exists(m_strBootROM))
|
||||
m_strBootROM = File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + set_region_dir + DIR_SEP GC_IPL;
|
||||
m_strBootROM =
|
||||
File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + set_region_dir + DIR_SEP GC_IPL;
|
||||
|
||||
if (!File::Exists(m_strBootROM))
|
||||
{
|
||||
@@ -917,7 +912,8 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
|
||||
return true;
|
||||
}
|
||||
|
||||
void SConfig::CheckMemcardPath(std::string& memcardPath, const std::string& gameRegion, bool isSlotA)
|
||||
void SConfig::CheckMemcardPath(std::string& memcardPath, const std::string& gameRegion,
|
||||
bool isSlotA)
|
||||
{
|
||||
std::string ext("." + gameRegion + ".raw");
|
||||
if (memcardPath.empty())
|
||||
@@ -953,7 +949,7 @@ void SConfig::CheckMemcardPath(std::string& memcardPath, const std::string& game
|
||||
PanicAlertT("Copy failed");
|
||||
}
|
||||
}
|
||||
memcardPath = filename; // Always correct the path!
|
||||
memcardPath = filename; // Always correct the path!
|
||||
}
|
||||
else if (region.compare(gameRegion) != 0)
|
||||
{
|
||||
@@ -964,17 +960,19 @@ void SConfig::CheckMemcardPath(std::string& memcardPath, const std::string& game
|
||||
}
|
||||
}
|
||||
|
||||
DiscIO::IVolume::ELanguage SConfig::GetCurrentLanguage(bool wii) const
|
||||
DiscIO::Language SConfig::GetCurrentLanguage(bool wii) const
|
||||
{
|
||||
DiscIO::IVolume::ELanguage language;
|
||||
int language_value;
|
||||
if (wii)
|
||||
language = (DiscIO::IVolume::ELanguage)SConfig::GetInstance().m_SYSCONF->GetData<u8>("IPL.LNG");
|
||||
language_value = SConfig::GetInstance().m_SYSCONF->GetData<u8>("IPL.LNG");
|
||||
else
|
||||
language = (DiscIO::IVolume::ELanguage)(SConfig::GetInstance().SelectedLanguage + 1);
|
||||
language_value = SConfig::GetInstance().SelectedLanguage + 1;
|
||||
DiscIO::Language language = static_cast<DiscIO::Language>(language_value);
|
||||
|
||||
// Get rid of invalid values (probably doesn't matter, but might as well do it)
|
||||
if (language > DiscIO::IVolume::ELanguage::LANGUAGE_UNKNOWN || language < 0)
|
||||
language = DiscIO::IVolume::ELanguage::LANGUAGE_UNKNOWN;
|
||||
if (language > DiscIO::Language::LANGUAGE_UNKNOWN ||
|
||||
language < DiscIO::Language::LANGUAGE_JAPANESE)
|
||||
language = DiscIO::Language::LANGUAGE_UNKNOWN;
|
||||
return language;
|
||||
}
|
||||
|
||||
|
@@ -12,7 +12,11 @@
|
||||
#include "Common/SysConf.h"
|
||||
#include "Core/HW/EXI_Device.h"
|
||||
#include "Core/HW/SI_Device.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
enum class Language;
|
||||
}
|
||||
|
||||
// DSP Backend Types
|
||||
#define BACKEND_NULLSOUND _trans("No audio output")
|
||||
@@ -34,7 +38,7 @@ enum GPUDeterminismMode
|
||||
GPU_DETERMINISM_FAKE_COMPLETION,
|
||||
};
|
||||
|
||||
struct SConfig: NonCopyable
|
||||
struct SConfig : NonCopyable
|
||||
{
|
||||
// Wii Devices
|
||||
bool m_WiiSDCard;
|
||||
@@ -80,7 +84,7 @@ struct SConfig: NonCopyable
|
||||
bool bFPRF;
|
||||
bool bAccurateNaNs;
|
||||
|
||||
int iTimingVariance; // in milli secounds
|
||||
int iTimingVariance; // in milli secounds
|
||||
bool bCPUThread;
|
||||
bool bDSPThread;
|
||||
bool bDSPHLE;
|
||||
@@ -180,12 +184,9 @@ struct SConfig: NonCopyable
|
||||
|
||||
void LoadDefaults();
|
||||
bool AutoSetup(EBootBS2 _BootBS2);
|
||||
const std::string &GetUniqueID() const
|
||||
{
|
||||
return m_strUniqueID;
|
||||
}
|
||||
const std::string& GetUniqueID() const { return m_strUniqueID; }
|
||||
void CheckMemcardPath(std::string& memcardPath, const std::string& gameRegion, bool isSlotA);
|
||||
DiscIO::IVolume::ELanguage GetCurrentLanguage(bool wii) const;
|
||||
DiscIO::Language GetCurrentLanguage(bool wii) const;
|
||||
|
||||
IniFile LoadDefaultGameIni() const;
|
||||
IniFile LoadLocalGameIni() const;
|
||||
@@ -290,11 +291,7 @@ struct SConfig: NonCopyable
|
||||
void LoadSettings();
|
||||
|
||||
// Return the permanent and somewhat globally used instance of this struct
|
||||
static SConfig& GetInstance()
|
||||
{
|
||||
return(*m_Instance);
|
||||
}
|
||||
|
||||
static SConfig& GetInstance() { return (*m_Instance); }
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
|
@@ -15,15 +15,15 @@
|
||||
|
||||
#include "AudioCommon/AudioCommon.h"
|
||||
|
||||
#include "Common/CPUDetect.h"
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/CPUDetect.h"
|
||||
#include "Common/Logging/LogManager.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/Thread.h"
|
||||
#include "Common/Timer.h"
|
||||
#include "Common/Logging/LogManager.h"
|
||||
|
||||
#include "Core/Analytics.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
@@ -35,11 +35,6 @@
|
||||
#ifdef USE_MEMORYWATCHER
|
||||
#include "Core/MemoryWatcher.h"
|
||||
#endif
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/NetPlayClient.h"
|
||||
#include "Core/NetPlayProto.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/State.h"
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/FifoPlayer/FifoPlayer.h"
|
||||
#include "Core/HW/AudioInterface.h"
|
||||
@@ -58,35 +53,35 @@
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
|
||||
#include "Core/IPC_HLE/WII_Socket.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/NetPlayClient.h"
|
||||
#include "Core/NetPlayProto.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/PowerPC/JitInterface.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/State.h"
|
||||
|
||||
#ifdef USE_GDBSTUB
|
||||
#include "Core/PowerPC/GDBStub.h"
|
||||
#endif
|
||||
|
||||
#include "DiscIO/FileMonitor.h"
|
||||
#include "InputCommon/GCAdapter.h"
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/GCAdapter.h"
|
||||
#include "VideoCommon/Fifo.h"
|
||||
#include "VideoCommon/OnScreenDisplay.h"
|
||||
#include "VideoCommon/RenderBase.h"
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
|
||||
// This can mostly be removed when we move to VS2015
|
||||
// to use the thread_local keyword
|
||||
#ifdef _MSC_VER
|
||||
#define ThreadLocalStorage __declspec(thread)
|
||||
#elif defined __ANDROID__ || defined __APPLE__
|
||||
// This will most likely have to stay, to support android
|
||||
// Android and OSX haven't implemented the keyword yet.
|
||||
#if defined __ANDROID__ || defined __APPLE__
|
||||
#include <pthread.h>
|
||||
#else // Everything besides VS and Android
|
||||
#define ThreadLocalStorage __thread
|
||||
#else // Everything besides OSX and Android
|
||||
#define ThreadLocalStorage thread_local
|
||||
#endif
|
||||
|
||||
namespace Core
|
||||
{
|
||||
|
||||
// TODO: ugly, remove
|
||||
bool g_aspect_wide;
|
||||
|
||||
@@ -106,7 +101,7 @@ void EmuThread();
|
||||
static bool s_is_stopping = false;
|
||||
static bool s_hardware_initialized = false;
|
||||
static bool s_is_started = false;
|
||||
static std::atomic<bool> s_is_booting{false};
|
||||
static std::atomic<bool> s_is_booting{ false };
|
||||
static void* s_window_handle = nullptr;
|
||||
static std::string s_state_filename;
|
||||
static std::thread s_emu_thread;
|
||||
@@ -122,7 +117,7 @@ struct HostJob
|
||||
std::function<void()> job;
|
||||
bool run_after_stop;
|
||||
};
|
||||
static std::mutex s_host_jobs_lock;
|
||||
static std::mutex s_host_jobs_lock;
|
||||
static std::queue<HostJob> s_host_jobs_queue;
|
||||
|
||||
#ifdef ThreadLocalStorage
|
||||
@@ -166,8 +161,8 @@ void FrameUpdateOnCPUThread()
|
||||
// Formatted stop message
|
||||
std::string StopMessage(bool main_thread, const std::string& message)
|
||||
{
|
||||
return StringFromFormat("Stop [%s %i]\t%s\t%s",
|
||||
main_thread ? "Main Thread" : "Video Thread", Common::CurrentThreadId(), MemUsage().c_str(), message.c_str());
|
||||
return StringFromFormat("Stop [%s %i]\t%s\t%s", main_thread ? "Main Thread" : "Video Thread",
|
||||
Common::CurrentThreadId(), MemUsage().c_str(), message.c_str());
|
||||
}
|
||||
|
||||
void DisplayMessage(const std::string& message, int time_in_ms)
|
||||
@@ -249,19 +244,17 @@ bool Init()
|
||||
|
||||
Core::UpdateWantDeterminism(/*initial*/ true);
|
||||
|
||||
INFO_LOG(OSREPORT, "Starting core = %s mode",
|
||||
_CoreParameter.bWii ? "Wii" : "GameCube");
|
||||
INFO_LOG(OSREPORT, "CPU Thread separate = %s",
|
||||
_CoreParameter.bCPUThread ? "Yes" : "No");
|
||||
INFO_LOG(OSREPORT, "Starting core = %s mode", _CoreParameter.bWii ? "Wii" : "GameCube");
|
||||
INFO_LOG(OSREPORT, "CPU Thread separate = %s", _CoreParameter.bCPUThread ? "Yes" : "No");
|
||||
|
||||
Host_UpdateMainFrame(); // Disable any menus or buttons at boot
|
||||
Host_UpdateMainFrame(); // Disable any menus or buttons at boot
|
||||
|
||||
g_aspect_wide = _CoreParameter.bWii;
|
||||
if (g_aspect_wide)
|
||||
{
|
||||
IniFile gameIni = _CoreParameter.LoadGameIni();
|
||||
gameIni.GetOrCreateSection("Wii")->Get("Widescreen", &g_aspect_wide,
|
||||
!!SConfig::GetInstance().m_SYSCONF->GetData<u8>("IPL.AR"));
|
||||
gameIni.GetOrCreateSection("Wii")->Get(
|
||||
"Widescreen", &g_aspect_wide, !!SConfig::GetInstance().m_SYSCONF->GetData<u8>("IPL.AR"));
|
||||
}
|
||||
|
||||
s_window_handle = Host_GetRenderHandle();
|
||||
@@ -338,8 +331,7 @@ void UndeclareAsCPUThread()
|
||||
// For the CPU Thread only.
|
||||
static void CPUSetInitialExecutionState()
|
||||
{
|
||||
QueueHostJob([]
|
||||
{
|
||||
QueueHostJob([] {
|
||||
SetState(SConfig::GetInstance().bBootToPause ? CORE_PAUSE : CORE_RUN);
|
||||
Host_UpdateMainFrame();
|
||||
});
|
||||
@@ -367,15 +359,14 @@ static void CpuThread()
|
||||
DolphinAnalytics::Instance()->ReportGameStart();
|
||||
|
||||
if (_CoreParameter.bFastmem)
|
||||
EMM::InstallExceptionHandler(); // Let's run under memory watch
|
||||
EMM::InstallExceptionHandler(); // Let's run under memory watch
|
||||
|
||||
if (!s_state_filename.empty())
|
||||
{
|
||||
// Needs to PauseAndLock the Core
|
||||
// NOTE: EmuThread should have left us in CPU_STEPPING so nothing will happen
|
||||
// until after the job is serviced.
|
||||
QueueHostJob([]
|
||||
{
|
||||
QueueHostJob([] {
|
||||
// Recheck in case Movie cleared it since.
|
||||
if (!s_state_filename.empty())
|
||||
State::LoadAs(s_state_filename);
|
||||
@@ -496,7 +487,7 @@ void EmuThread()
|
||||
|
||||
HW::Init();
|
||||
|
||||
if (!g_video_backend->Initialize(s_window_handle))
|
||||
if (!video_backend->Initialize(s_window_handle))
|
||||
{
|
||||
s_is_booting.store(false);
|
||||
PanicAlert("Failed to initialize video backend!");
|
||||
@@ -539,7 +530,9 @@ void EmuThread()
|
||||
if (core_parameter.bWii)
|
||||
{
|
||||
if (init_controllers)
|
||||
Wiimote::Initialize(s_window_handle, !s_state_filename.empty());
|
||||
Wiimote::Initialize(s_window_handle, !s_state_filename.empty() ?
|
||||
Wiimote::InitializeMode::DO_WAIT_FOR_WIIMOTES :
|
||||
Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
|
||||
else
|
||||
Wiimote::LoadConfig();
|
||||
|
||||
@@ -547,7 +540,6 @@ void EmuThread()
|
||||
for (unsigned int i = 0; i != MAX_BBMOTES; ++i)
|
||||
if (g_wiimote_sources[i])
|
||||
GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(true);
|
||||
|
||||
}
|
||||
|
||||
AudioCommon::InitSoundStream(s_window_handle);
|
||||
@@ -571,8 +563,8 @@ void EmuThread()
|
||||
UndeclareAsCPUThread();
|
||||
|
||||
// Setup our core, but can't use dynarec if we are compare server
|
||||
if (core_parameter.iCPUCore != PowerPC::CORE_INTERPRETER
|
||||
&& (!core_parameter.bRunCompareServer || core_parameter.bRunCompareClient))
|
||||
if (core_parameter.iCPUCore != PowerPC::CORE_INTERPRETER &&
|
||||
(!core_parameter.bRunCompareServer || core_parameter.bRunCompareClient))
|
||||
{
|
||||
PowerPC::SetMode(PowerPC::MODE_JIT);
|
||||
}
|
||||
@@ -610,7 +602,7 @@ void EmuThread()
|
||||
// We have now exited the Video Loop
|
||||
INFO_LOG(CONSOLE, "%s", StopMessage(false, "Video Loop Ended").c_str());
|
||||
}
|
||||
else // SingleCore mode
|
||||
else // SingleCore mode
|
||||
{
|
||||
// The spawned CPU Thread also does the graphics.
|
||||
// The EmuThread is thus an idle thread, which sleeps while
|
||||
@@ -752,7 +744,7 @@ static std::string GenerateScreenshotName()
|
||||
{
|
||||
std::string path = GenerateScreenshotFolderPath();
|
||||
|
||||
//append gameId, path only contains the folder here.
|
||||
// append gameId, path only contains the folder here.
|
||||
path += SConfig::GetInstance().GetUniqueID();
|
||||
|
||||
std::string name;
|
||||
@@ -820,7 +812,8 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock)
|
||||
// audio has to come after CPU, because CPU thread can wait for audio thread (m_throttle).
|
||||
DSP::GetDSPEmulator()->PauseAndLock(do_lock, false);
|
||||
|
||||
// video has to come after CPU, because CPU thread can wait for video thread (s_efbAccessRequested).
|
||||
// video has to come after CPU, because CPU thread can wait for video thread
|
||||
// (s_efbAccessRequested).
|
||||
Fifo::PauseAndLock(do_lock, false);
|
||||
|
||||
#if defined(__LIBUSB__) || defined(_WIN32)
|
||||
@@ -907,25 +900,32 @@ void UpdateTitle()
|
||||
|
||||
float FPS = (float)(s_drawn_frame.load() * 1000.0 / ElapseTime);
|
||||
float VPS = (float)(s_drawn_video.load() * 1000.0 / ElapseTime);
|
||||
float Speed = (float)(s_drawn_video.load() * (100 * 1000.0) / (VideoInterface::GetTargetRefreshRate() * ElapseTime));
|
||||
float Speed = (float)(s_drawn_video.load() * (100 * 1000.0) /
|
||||
(VideoInterface::GetTargetRefreshRate() * ElapseTime));
|
||||
|
||||
// Settings are shown the same for both extended and summary info
|
||||
std::string SSettings = StringFromFormat("%s %s | %s | %s", PowerPC::GetCPUName(), _CoreParameter.bCPUThread ? "DC" : "SC",
|
||||
std::string SSettings = StringFromFormat(
|
||||
"%s %s | %s | %s", PowerPC::GetCPUName(), _CoreParameter.bCPUThread ? "DC" : "SC",
|
||||
g_video_backend->GetDisplayName().c_str(), _CoreParameter.bDSPHLE ? "HLE" : "LLE");
|
||||
|
||||
std::string SFPS;
|
||||
|
||||
if (Movie::IsPlayingInput())
|
||||
SFPS = StringFromFormat("VI: %u/%u - Input: %u/%u - FPS: %.0f - VPS: %.0f - %.0f%%", (u32)Movie::g_currentFrame, (u32)Movie::g_totalFrames, (u32)Movie::g_currentInputCount, (u32)Movie::g_totalInputCount, FPS, VPS, Speed);
|
||||
SFPS = StringFromFormat("Input: %u/%u - VI: %u - FPS: %.0f - VPS: %.0f - %.0f%%",
|
||||
(u32)Movie::g_currentInputCount, (u32)Movie::g_totalInputCount,
|
||||
(u32)Movie::g_currentFrame, FPS, VPS, Speed);
|
||||
else if (Movie::IsRecordingInput())
|
||||
SFPS = StringFromFormat("VI: %u - Input: %u - FPS: %.0f - VPS: %.0f - %.0f%%", (u32)Movie::g_currentFrame, (u32)Movie::g_currentInputCount, FPS, VPS, Speed);
|
||||
SFPS = StringFromFormat("Input: %u - VI: %u - FPS: %.0f - VPS: %.0f - %.0f%%",
|
||||
(u32)Movie::g_currentInputCount, (u32)Movie::g_currentFrame, FPS, VPS,
|
||||
Speed);
|
||||
else
|
||||
{
|
||||
SFPS = StringFromFormat("FPS: %.0f - VPS: %.0f - %.0f%%", FPS, VPS, Speed);
|
||||
if (SConfig::GetInstance().m_InterfaceExtendedFPSInfo)
|
||||
{
|
||||
// Use extended or summary information. The summary information does not print the ticks data,
|
||||
// that's more of a debugging interest, it can always be optional of course if someone is interested.
|
||||
// that's more of a debugging interest, it can always be optional of course if someone is
|
||||
// interested.
|
||||
static u64 ticks = 0;
|
||||
static u64 idleTicks = 0;
|
||||
u64 newTicks = CoreTiming::GetTicks();
|
||||
@@ -937,16 +937,14 @@ void UpdateTitle()
|
||||
ticks = newTicks;
|
||||
idleTicks = newIdleTicks;
|
||||
|
||||
float TicksPercentage = (float)diff / (float)(SystemTimers::GetTicksPerSecond() / 1000000) * 100;
|
||||
float TicksPercentage =
|
||||
(float)diff / (float)(SystemTimers::GetTicksPerSecond() / 1000000) * 100;
|
||||
|
||||
SFPS += StringFromFormat(" | CPU: %s%i MHz [Real: %i + IdleSkip: %i] / %i MHz (%s%3.0f%%)",
|
||||
_CoreParameter.bSkipIdle ? "~" : "",
|
||||
(int)(diff),
|
||||
(int)(diff - idleDiff),
|
||||
(int)(idleDiff),
|
||||
SystemTimers::GetTicksPerSecond() / 1000000,
|
||||
_CoreParameter.bSkipIdle ? "~" : "",
|
||||
TicksPercentage);
|
||||
SFPS +=
|
||||
StringFromFormat(" | CPU: %s%i MHz [Real: %i + IdleSkip: %i] / %i MHz (%s%3.0f%%)",
|
||||
_CoreParameter.bSkipIdle ? "~" : "", (int)(diff), (int)(diff - idleDiff),
|
||||
(int)(idleDiff), SystemTimers::GetTicksPerSecond() / 1000000,
|
||||
_CoreParameter.bSkipIdle ? "~" : "", TicksPercentage);
|
||||
}
|
||||
}
|
||||
// This is our final "frame counter" string
|
||||
@@ -979,10 +977,7 @@ void UpdateWantDeterminism(bool initial)
|
||||
// For now, this value is not itself configurable. Instead, individual
|
||||
// settings that depend on it, such as GPU determinism mode. should have
|
||||
// override options for testing,
|
||||
bool new_want_determinism =
|
||||
Movie::IsPlayingInput() ||
|
||||
Movie::IsRecordingInput() ||
|
||||
NetPlay::IsNetPlayRunning();
|
||||
bool new_want_determinism = Movie::IsMovieActive() || NetPlay::IsNetPlayRunning();
|
||||
if (new_want_determinism != g_want_determinism || initial)
|
||||
{
|
||||
WARN_LOG(COMMON, "Want determinism <- %s", new_want_determinism ? "true" : "false");
|
||||
@@ -992,7 +987,8 @@ void UpdateWantDeterminism(bool initial)
|
||||
g_want_determinism = new_want_determinism;
|
||||
WiiSockMan::GetInstance().UpdateWantDeterminism(new_want_determinism);
|
||||
Fifo::UpdateWantDeterminism(new_want_determinism);
|
||||
// We need to clear the cache because some parts of the JIT depend on want_determinism, e.g. use of FMA.
|
||||
// We need to clear the cache because some parts of the JIT depend on want_determinism, e.g. use
|
||||
// of FMA.
|
||||
JitInterface::ClearCache();
|
||||
Common::InitializeWiiRoot(g_want_determinism);
|
||||
|
||||
@@ -1009,7 +1005,7 @@ void QueueHostJob(std::function<void()> job, bool run_during_stop)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_host_jobs_lock);
|
||||
send_message = s_host_jobs_queue.empty();
|
||||
s_host_jobs_queue.emplace(HostJob{std::move(job), run_during_stop});
|
||||
s_host_jobs_queue.emplace(HostJob{ std::move(job), run_during_stop });
|
||||
}
|
||||
// If the the queue was empty then kick the Host to come and get this job.
|
||||
if (send_message)
|
||||
@@ -1041,4 +1037,4 @@ void HostDispatchJobs()
|
||||
}
|
||||
}
|
||||
|
||||
} // Core
|
||||
} // Core
|
||||
|
@@ -27,31 +27,31 @@ const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
|
||||
{
|
||||
// From AX:
|
||||
{ 0x26fc, // LRS $30, @DMBH
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
{ 0x27fc, // LRS $31, @DMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
{ 0x26fe, // LRS $30, @CMBH
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
{ 0x27fe, // LRS $31, @CMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
{ 0x26fc, // LRS $AC0.M, @DMBH
|
||||
0x02a0, 0x8000, // ANDF $AC0.M, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x????
|
||||
0, 0 },
|
||||
0x02a0, 0x8000, // ANDF $AC0.M, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x????
|
||||
0, 0 },
|
||||
{ 0x27fc, // LRS $AC1.M, @DMBH
|
||||
0x03a0, 0x8000, // ANDF $AC1.M, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x????
|
||||
0, 0 },
|
||||
// From Zelda:
|
||||
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
|
||||
0x03a0, 0x8000, // ANDF $AC1.M, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x????
|
||||
0, 0 },
|
||||
// From Zelda:
|
||||
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
|
||||
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x05cf
|
||||
0 },
|
||||
|
@@ -45,7 +45,7 @@ static const char *err_string[] =
|
||||
"Number out of range"
|
||||
};
|
||||
|
||||
DSPAssembler::DSPAssembler(const AssemblerSettings &settings):
|
||||
DSPAssembler::DSPAssembler(const AssemblerSettings &settings) :
|
||||
gdg_buffer(nullptr),
|
||||
m_cur_addr(0),
|
||||
m_cur_pass(0),
|
||||
@@ -763,7 +763,7 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass)
|
||||
m_cur_pass = pass;
|
||||
|
||||
#define LINEBUF_SIZE 1024
|
||||
char line[LINEBUF_SIZE] = {0};
|
||||
char line[LINEBUF_SIZE] = { 0 };
|
||||
while (!failed && !fsrc.fail() && !fsrc.eof())
|
||||
{
|
||||
int opcode_size = 0;
|
||||
@@ -775,8 +775,8 @@ bool DSPAssembler::AssembleFile(const char *fname, int pass)
|
||||
//printf("A: %s\n", line);
|
||||
code_line++;
|
||||
|
||||
param_t params[10] = {{0, P_NONE, nullptr}};
|
||||
param_t params_ext[10] = {{0, P_NONE, nullptr}};
|
||||
param_t params[10] = { {0, P_NONE, nullptr} };
|
||||
param_t params_ext[10] = { {0, P_NONE, nullptr} };
|
||||
|
||||
bool upper = true;
|
||||
for (int i = 0; i < LINEBUF_SIZE; i++)
|
||||
|
@@ -42,7 +42,7 @@ public:
|
||||
// default implementation used by the DSP emulator.
|
||||
//
|
||||
// Can also be inherited from if you want to only override part of the methods.
|
||||
class DefaultDSPCaptureLogger: public DSPCaptureLogger
|
||||
class DefaultDSPCaptureLogger : public DSPCaptureLogger
|
||||
{
|
||||
public:
|
||||
void LogIFXRead(u16 address, u16 read_value) override
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
|
||||
// A capture logger implementation that logs to PCAP files in a custom
|
||||
// packet-based format.
|
||||
class PCAPDSPCaptureLogger final: public DSPCaptureLogger, NonCopyable
|
||||
class PCAPDSPCaptureLogger final : public DSPCaptureLogger, NonCopyable
|
||||
{
|
||||
public:
|
||||
// Automatically creates a writeable file (truncate existing file).
|
||||
|
@@ -40,7 +40,7 @@ static bool VerifyRoms()
|
||||
u32 hash_drom; // dsp_coef.bin
|
||||
};
|
||||
|
||||
static const std::array<DspRomHashes, 4> known_roms = {{
|
||||
static const std::array<DspRomHashes, 4> known_roms = { {
|
||||
// Official Nintendo ROM
|
||||
{ 0x66f334fe, 0xf3b93527 },
|
||||
|
||||
@@ -53,7 +53,7 @@ static bool VerifyRoms()
|
||||
|
||||
// above with improved resampling coefficients
|
||||
{ 0xd9907f71, 0xdb6880c1 }
|
||||
}};
|
||||
} };
|
||||
|
||||
u32 hash_irom = HashAdler32((u8*)g_dsp.irom, DSP_IROM_BYTE_SIZE);
|
||||
u32 hash_drom = HashAdler32((u8*)g_dsp.coef, DSP_COEF_BYTE_SIZE);
|
||||
|
@@ -14,46 +14,46 @@
|
||||
#include "Core/DSP/DSPCaptureLogger.h"
|
||||
#include "Core/DSP/DSPEmitter.h"
|
||||
|
||||
enum: u32
|
||||
enum : u32
|
||||
{
|
||||
DSP_IRAM_BYTE_SIZE = 0x2000,
|
||||
DSP_IRAM_SIZE = 0x1000,
|
||||
DSP_IRAM_MASK = 0x0fff
|
||||
};
|
||||
|
||||
enum: u32
|
||||
enum : u32
|
||||
{
|
||||
DSP_IROM_BYTE_SIZE = 0x2000,
|
||||
DSP_IROM_SIZE = 0x1000,
|
||||
DSP_IROM_MASK = 0x0fff
|
||||
};
|
||||
|
||||
enum: u32
|
||||
enum : u32
|
||||
{
|
||||
DSP_DRAM_BYTE_SIZE = 0x2000,
|
||||
DSP_DRAM_SIZE = 0x1000,
|
||||
DSP_DRAM_MASK = 0x0fff
|
||||
};
|
||||
|
||||
enum: u32
|
||||
enum : u32
|
||||
{
|
||||
DSP_COEF_BYTE_SIZE = 0x1000,
|
||||
DSP_COEF_SIZE = 0x800,
|
||||
DSP_COEF_MASK = 0x7ff
|
||||
};
|
||||
|
||||
enum: u16
|
||||
enum : u16
|
||||
{
|
||||
DSP_RESET_VECTOR = 0x8000
|
||||
};
|
||||
|
||||
enum: u8
|
||||
enum : u8
|
||||
{
|
||||
DSP_STACK_DEPTH = 0x20,
|
||||
DSP_STACK_MASK = 0x1f
|
||||
};
|
||||
|
||||
enum: u32
|
||||
enum : u32
|
||||
{
|
||||
DSP_CR_IMEM = 2,
|
||||
DSP_CR_DMEM = 0,
|
||||
@@ -62,7 +62,7 @@ enum: u32
|
||||
};
|
||||
|
||||
// Register table taken from libasnd
|
||||
enum: int
|
||||
enum : int
|
||||
{
|
||||
// Address registers
|
||||
DSP_REG_AR0 = 0x00,
|
||||
@@ -116,7 +116,7 @@ enum: int
|
||||
};
|
||||
|
||||
// Hardware registers address
|
||||
enum: u32
|
||||
enum : u32
|
||||
{
|
||||
DSP_COEF_A1_0 = 0xa0,
|
||||
|
||||
@@ -152,7 +152,7 @@ enum: u32
|
||||
};
|
||||
|
||||
// Stacks
|
||||
enum: int
|
||||
enum : int
|
||||
{
|
||||
DSP_STACK_C,
|
||||
DSP_STACK_D
|
||||
@@ -160,7 +160,7 @@ enum: int
|
||||
|
||||
// cr (Not g_dsp.r[CR]) bits
|
||||
// See HW/DSP.cpp.
|
||||
enum: u32
|
||||
enum : u32
|
||||
{
|
||||
CR_EXTERNAL_INT = 0x0002,
|
||||
CR_HALT = 0x0004,
|
||||
@@ -168,7 +168,7 @@ enum: u32
|
||||
};
|
||||
|
||||
// SR bits
|
||||
enum: u16
|
||||
enum : u16
|
||||
{
|
||||
SR_CARRY = 0x0001,
|
||||
SR_OVERFLOW = 0x0002,
|
||||
@@ -192,7 +192,7 @@ enum: u16
|
||||
};
|
||||
|
||||
// Exception vectors
|
||||
enum: int
|
||||
enum : int
|
||||
{
|
||||
EXP_STOVF = 1, // 0x0002 stack under/over flow
|
||||
EXP_2 = 2, // 0x0004
|
||||
|
@@ -189,7 +189,7 @@ bool DSPDisassembler::DisassembleOpcode(const u16 *binbuf, int base_addr, int pa
|
||||
break;
|
||||
}
|
||||
}
|
||||
const DSPOPCTemplate fake_op = {"CW", 0x0000, 0x0000, nop, nullptr, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, false, false, false, false, false};
|
||||
const DSPOPCTemplate fake_op = { "CW", 0x0000, 0x0000, nop, nullptr, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, false, false, false, false, false };
|
||||
if (!opc)
|
||||
opc = &fake_op;
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
DSPEmitter::DSPEmitter(): gpr(*this), storeIndex(-1), storeIndex2(-1)
|
||||
DSPEmitter::DSPEmitter() : gpr(*this), storeIndex(-1), storeIndex2(-1)
|
||||
{
|
||||
m_compiledCode = nullptr;
|
||||
|
||||
|
@@ -18,7 +18,7 @@
|
||||
typedef u32(*DSPCompiledCode)();
|
||||
typedef const u8 *Block;
|
||||
|
||||
class DSPEmitter: public Gen::X64CodeBlock
|
||||
class DSPEmitter : public Gen::X64CodeBlock
|
||||
{
|
||||
public:
|
||||
DSPEmitter();
|
||||
|
@@ -292,7 +292,7 @@ const DSPOPCTemplate opcodes[] =
|
||||
};
|
||||
|
||||
const DSPOPCTemplate cw =
|
||||
{"CW", 0x0000, 0x0000, nop, nullptr, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, false, false, false, false, false};
|
||||
{ "CW", 0x0000, 0x0000, nop, nullptr, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, false, false, false, false, false };
|
||||
|
||||
// extended opcodes
|
||||
|
||||
|
@@ -12,9 +12,9 @@ using namespace Gen;
|
||||
|
||||
// Ordered in order of prefered use.
|
||||
// Not all of these are actually available
|
||||
const std::array<X64Reg, 15> DSPJitRegCache::m_allocation_order = {{
|
||||
const std::array<X64Reg, 15> DSPJitRegCache::m_allocation_order = { {
|
||||
R8, R9, R10, R11, R12, R13, R14, R15, RSI, RDI, RBX, RCX, RDX, RAX, RBP
|
||||
}};
|
||||
} };
|
||||
|
||||
static void* GetRegisterPointer(size_t reg)
|
||||
{
|
||||
@@ -233,8 +233,7 @@ void DSPJitRegCache::FlushRegs(DSPJitRegCache &cache, bool emit)
|
||||
movcnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (movcnt != 0);
|
||||
} while (movcnt != 0);
|
||||
|
||||
// free all host regs that are not used for the same guest reg
|
||||
for (size_t i = 0; i < regs.size(); i++)
|
||||
|
@@ -49,9 +49,9 @@ public:
|
||||
//this does not modify the final state of gpr
|
||||
<code using gpr>
|
||||
FixupBranch b = JCC();
|
||||
DSPJitRegCache c = gpr;
|
||||
<code using c>
|
||||
gpr.FlushRegs(c);
|
||||
DSPJitRegCache c = gpr;
|
||||
<code using c>
|
||||
gpr.FlushRegs(c);
|
||||
SetBranchTarget(b);
|
||||
<code using gpr>
|
||||
|
||||
@@ -59,12 +59,12 @@ public:
|
||||
<code using gpr>
|
||||
DSPJitRegCache c = gpr;
|
||||
FixupBranch b1 = JCC();
|
||||
<code using gpr>
|
||||
gpr.FlushRegs(c);
|
||||
FixupBranch b2 = JMP();
|
||||
<code using gpr>
|
||||
gpr.FlushRegs(c);
|
||||
FixupBranch b2 = JMP();
|
||||
SetBranchTarget(b1);
|
||||
<code using gpr>
|
||||
gpr.FlushRegs(c);
|
||||
<code using gpr>
|
||||
gpr.FlushRegs(c);
|
||||
SetBranchTarget(b2);
|
||||
<code using gpr>
|
||||
|
||||
@@ -73,21 +73,21 @@ public:
|
||||
<code using gpr>
|
||||
DSPJitRegCache c = gpr;
|
||||
FixupBranch b1 = JCC();
|
||||
<code using c>
|
||||
FixupBranch b2 = JMP();
|
||||
<code using c>
|
||||
FixupBranch b2 = JMP();
|
||||
SetBranchTarget(b1);
|
||||
<code using gpr>
|
||||
gpr.FlushRegs(c);
|
||||
<code using gpr>
|
||||
gpr.FlushRegs(c);
|
||||
SetBranchTarget(b2);
|
||||
<code using gpr>
|
||||
|
||||
//this does not modify the final state of gpr
|
||||
<code using gpr>
|
||||
u8* b = GetCodePtr();
|
||||
DSPJitRegCache c = gpr;
|
||||
<code using gpr>
|
||||
gpr.FlushRegs(c);
|
||||
JCC(b);
|
||||
DSPJitRegCache c = gpr;
|
||||
<code using gpr>
|
||||
gpr.FlushRegs(c);
|
||||
JCC(b);
|
||||
<code using gpr>
|
||||
|
||||
this all is not needed when gpr would not be used at all in the
|
||||
@@ -144,7 +144,7 @@ private:
|
||||
int last_use_ctr;
|
||||
int parentReg;
|
||||
int shift; // Current shift if parentReg == DSP_REG_NONE
|
||||
// otherwise the shift this part can be found at
|
||||
// otherwise the shift this part can be found at
|
||||
Gen::X64Reg host_reg;
|
||||
|
||||
// TODO:
|
||||
|
@@ -21,7 +21,7 @@ class LabelMap
|
||||
{
|
||||
struct label_t
|
||||
{
|
||||
label_t(const std::string &lbl, s32 address, LabelType ltype): name(lbl), addr(address), type(ltype)
|
||||
label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype)
|
||||
{}
|
||||
std::string name;
|
||||
s32 addr;
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "Core/Debugger/Dump.h"
|
||||
|
||||
CDump::CDump(const std::string& filename):
|
||||
CDump::CDump(const std::string& filename) :
|
||||
m_pData(nullptr)
|
||||
{
|
||||
File::IOFile pStream(filename, "rb");
|
||||
|
@@ -109,4 +109,4 @@ struct Rela_Header
|
||||
signed int addend;
|
||||
};
|
||||
|
||||
const char ELFID[4] = {0x7F, 'E', 'L', 'F'};
|
||||
const char ELFID[4] = { 0x7F, 'E', 'L', 'F' };
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
//wrapper between disasm control and Dolphin debugger
|
||||
|
||||
class PPCDebugInterface final: public DebugInterface
|
||||
class PPCDebugInterface final : public DebugInterface
|
||||
{
|
||||
public:
|
||||
PPCDebugInterface()
|
||||
|
@@ -199,18 +199,24 @@ void CalculateVertexElementSizes(int sizes[], int vatIndex, const CPMemory& cpMe
|
||||
const VAT& vtxAttr = cpMem.vtxAttr[vatIndex];
|
||||
|
||||
// Colors
|
||||
const u64 colDesc[2] = {vtxDesc.Color0, vtxDesc.Color1};
|
||||
const u32 colComp[2] = {vtxAttr.g0.Color0Comp, vtxAttr.g0.Color1Comp};
|
||||
const u64 colDesc[2] = { vtxDesc.Color0, vtxDesc.Color1 };
|
||||
const u32 colComp[2] = { vtxAttr.g0.Color0Comp, vtxAttr.g0.Color1Comp };
|
||||
|
||||
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 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 u32 tcFormat[8] = {vtxAttr.g0.Tex0CoordFormat, vtxAttr.g1.Tex1CoordFormat,
|
||||
vtxAttr.g1.Tex2CoordFormat, vtxAttr.g1.Tex3CoordFormat,
|
||||
vtxAttr.g1.Tex4CoordFormat, vtxAttr.g2.Tex5CoordFormat,
|
||||
vtxAttr.g2.Tex6CoordFormat, vtxAttr.g2.Tex7CoordFormat};
|
||||
const u32 tcFormat[8] =
|
||||
{
|
||||
vtxAttr.g0.Tex0CoordFormat, vtxAttr.g1.Tex1CoordFormat,
|
||||
vtxAttr.g1.Tex2CoordFormat, vtxAttr.g1.Tex3CoordFormat,
|
||||
vtxAttr.g1.Tex4CoordFormat, vtxAttr.g2.Tex5CoordFormat,
|
||||
vtxAttr.g2.Tex6CoordFormat, vtxAttr.g2.Tex7CoordFormat
|
||||
};
|
||||
|
||||
// Add position and texture matrix indices
|
||||
u64 vtxDescHex = cpMem.vtxDesc.Hex;
|
||||
|
@@ -12,11 +12,13 @@
|
||||
|
||||
using namespace FifoFileStruct;
|
||||
|
||||
FifoDataFile::FifoDataFile(): m_Flags(0)
|
||||
{}
|
||||
FifoDataFile::FifoDataFile() : m_Flags(0)
|
||||
{
|
||||
}
|
||||
|
||||
FifoDataFile::~FifoDataFile()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
bool FifoDataFile::HasBrokenEFBCopies() const
|
||||
{
|
||||
|
@@ -60,31 +60,13 @@ public:
|
||||
bool GetIsWii() const;
|
||||
bool HasBrokenEFBCopies() const;
|
||||
|
||||
u32* GetBPMem()
|
||||
{
|
||||
return m_BPMem;
|
||||
}
|
||||
u32* GetCPMem()
|
||||
{
|
||||
return m_CPMem;
|
||||
}
|
||||
u32* GetXFMem()
|
||||
{
|
||||
return m_XFMem;
|
||||
}
|
||||
u32* GetXFRegs()
|
||||
{
|
||||
return m_XFRegs;
|
||||
}
|
||||
u32* GetBPMem() { return m_BPMem; }
|
||||
u32* GetCPMem() { return m_CPMem; }
|
||||
u32* GetXFMem() { return m_XFMem; }
|
||||
u32* GetXFRegs() { return m_XFRegs; }
|
||||
void AddFrame(const FifoFrameInfo& frameInfo);
|
||||
const FifoFrameInfo& GetFrame(u32 frame) const
|
||||
{
|
||||
return m_Frames[frame];
|
||||
}
|
||||
u32 GetFrameCount() const
|
||||
{
|
||||
return static_cast<u32>(m_Frames.size());
|
||||
}
|
||||
const FifoFrameInfo& GetFrame(u32 frame) const { return m_Frames[frame]; }
|
||||
u32 GetFrameCount() const { return static_cast<u32>(m_Frames.size()); }
|
||||
bool Save(const std::string& filename);
|
||||
|
||||
static std::unique_ptr<FifoDataFile> Load(const std::string& filename, bool flagsOnly);
|
||||
|
@@ -17,8 +17,7 @@ enum
|
||||
|
||||
#pragma pack(push, 4)
|
||||
|
||||
union FileHeader
|
||||
{
|
||||
union FileHeader {
|
||||
struct
|
||||
{
|
||||
u32 fileId;
|
||||
@@ -39,8 +38,7 @@ union FileHeader
|
||||
u32 rawData[32];
|
||||
};
|
||||
|
||||
union FileFrameInfo
|
||||
{
|
||||
union FileFrameInfo {
|
||||
struct
|
||||
{
|
||||
u64 fifoDataOffset;
|
||||
|
@@ -28,7 +28,8 @@
|
||||
bool IsPlayingBackFifologWithBrokenEFBCopies = false;
|
||||
|
||||
FifoPlayer::~FifoPlayer()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
bool FifoPlayer::Open(const std::string& filename)
|
||||
{
|
||||
@@ -61,62 +62,54 @@ void FifoPlayer::Close()
|
||||
class FifoPlayer::CPUCore final : public CPUCoreBase
|
||||
{
|
||||
public:
|
||||
explicit CPUCore(FifoPlayer* parent): m_parent(parent)
|
||||
{}
|
||||
CPUCore(const CPUCore&) = delete;
|
||||
~CPUCore()
|
||||
{}
|
||||
CPUCore& operator=(const CPUCore&) = delete;
|
||||
explicit CPUCore(FifoPlayer* parent) : m_parent(parent) {}
|
||||
CPUCore(const CPUCore&) = delete;
|
||||
~CPUCore() {}
|
||||
CPUCore& operator=(const CPUCore&) = delete;
|
||||
|
||||
void Init() override
|
||||
{
|
||||
IsPlayingBackFifologWithBrokenEFBCopies = m_parent->m_File->HasBrokenEFBCopies();
|
||||
void Init() override
|
||||
{
|
||||
IsPlayingBackFifologWithBrokenEFBCopies = m_parent->m_File->HasBrokenEFBCopies();
|
||||
|
||||
m_parent->m_CurrentFrame = m_parent->m_FrameRangeStart;
|
||||
m_parent->LoadMemory();
|
||||
}
|
||||
m_parent->m_CurrentFrame = m_parent->m_FrameRangeStart;
|
||||
m_parent->LoadMemory();
|
||||
}
|
||||
|
||||
void Shutdown() override
|
||||
{
|
||||
IsPlayingBackFifologWithBrokenEFBCopies = false;
|
||||
}
|
||||
void ClearCache() override
|
||||
{
|
||||
// Nothing to clear.
|
||||
}
|
||||
void Shutdown() override { IsPlayingBackFifologWithBrokenEFBCopies = false; }
|
||||
void ClearCache() override
|
||||
{
|
||||
// Nothing to clear.
|
||||
}
|
||||
|
||||
void SingleStep() override
|
||||
{
|
||||
// NOTE: AdvanceFrame() will get stuck forever in Dual Core because the FIFO
|
||||
// is disabled by CPU::EnableStepping(true) so the frame never gets displayed.
|
||||
PanicAlertT("Cannot SingleStep the FIFO. Use Frame Advance instead.");
|
||||
}
|
||||
void SingleStep() override
|
||||
{
|
||||
// NOTE: AdvanceFrame() will get stuck forever in Dual Core because the FIFO
|
||||
// is disabled by CPU::EnableStepping(true) so the frame never gets displayed.
|
||||
PanicAlertT("Cannot SingleStep the FIFO. Use Frame Advance instead.");
|
||||
}
|
||||
|
||||
const char* GetName() override
|
||||
{
|
||||
return "FifoPlayer";
|
||||
}
|
||||
void Run() override
|
||||
{
|
||||
while (CPU::GetState() == CPU::CPU_RUNNING)
|
||||
{
|
||||
switch (m_parent->AdvanceFrame())
|
||||
{
|
||||
case CPU::CPU_POWERDOWN:
|
||||
CPU::Break();
|
||||
Host_Message(WM_USER_STOP);
|
||||
break;
|
||||
const char* GetName() override { return "FifoPlayer"; }
|
||||
void Run() override
|
||||
{
|
||||
while (CPU::GetState() == CPU::CPU_RUNNING)
|
||||
{
|
||||
switch (m_parent->AdvanceFrame())
|
||||
{
|
||||
case CPU::CPU_POWERDOWN:
|
||||
CPU::Break();
|
||||
Host_Message(WM_USER_STOP);
|
||||
break;
|
||||
|
||||
case CPU::CPU_STEPPING:
|
||||
CPU::Break();
|
||||
Host_UpdateMainFrame();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
case CPU::CPU_STEPPING:
|
||||
CPU::Break();
|
||||
Host_UpdateMainFrame();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
FifoPlayer* m_parent;
|
||||
FifoPlayer* m_parent;
|
||||
};
|
||||
|
||||
int FifoPlayer::AdvanceFrame()
|
||||
|
@@ -65,64 +65,28 @@ public:
|
||||
// PowerPC state.
|
||||
std::unique_ptr<CPUCoreBase> GetCPUCore();
|
||||
|
||||
FifoDataFile* GetFile()
|
||||
{
|
||||
return m_File.get();
|
||||
}
|
||||
FifoDataFile* GetFile() { return m_File.get(); }
|
||||
u32 GetFrameObjectCount();
|
||||
u32 GetCurrentFrameNum() const
|
||||
{
|
||||
return m_CurrentFrame;
|
||||
}
|
||||
const AnalyzedFrameInfo& GetAnalyzedFrameInfo(u32 frame) const
|
||||
{
|
||||
return m_FrameInfo[frame];
|
||||
}
|
||||
u32 GetCurrentFrameNum() const { return m_CurrentFrame; }
|
||||
const AnalyzedFrameInfo& GetAnalyzedFrameInfo(u32 frame) const { return m_FrameInfo[frame]; }
|
||||
// Frame range
|
||||
u32 GetFrameRangeStart() const
|
||||
{
|
||||
return m_FrameRangeStart;
|
||||
}
|
||||
u32 GetFrameRangeStart() const { return m_FrameRangeStart; }
|
||||
void SetFrameRangeStart(u32 start);
|
||||
|
||||
u32 GetFrameRangeEnd() const
|
||||
{
|
||||
return m_FrameRangeEnd;
|
||||
}
|
||||
u32 GetFrameRangeEnd() const { return m_FrameRangeEnd; }
|
||||
void SetFrameRangeEnd(u32 end);
|
||||
|
||||
// Object range
|
||||
u32 GetObjectRangeStart() const
|
||||
{
|
||||
return m_ObjectRangeStart;
|
||||
}
|
||||
void SetObjectRangeStart(u32 start)
|
||||
{
|
||||
m_ObjectRangeStart = start;
|
||||
}
|
||||
u32 GetObjectRangeEnd() const
|
||||
{
|
||||
return m_ObjectRangeEnd;
|
||||
}
|
||||
void SetObjectRangeEnd(u32 end)
|
||||
{
|
||||
m_ObjectRangeEnd = end;
|
||||
}
|
||||
u32 GetObjectRangeStart() const { return m_ObjectRangeStart; }
|
||||
void SetObjectRangeStart(u32 start) { m_ObjectRangeStart = start; }
|
||||
u32 GetObjectRangeEnd() const { return m_ObjectRangeEnd; }
|
||||
void SetObjectRangeEnd(u32 end) { m_ObjectRangeEnd = end; }
|
||||
// If enabled then all memory updates happen at once before the first frame
|
||||
// Default is disabled
|
||||
void SetEarlyMemoryUpdates(bool enabled)
|
||||
{
|
||||
m_EarlyMemoryUpdates = enabled;
|
||||
}
|
||||
void SetEarlyMemoryUpdates(bool enabled) { m_EarlyMemoryUpdates = enabled; }
|
||||
// Callbacks
|
||||
void SetFileLoadedCallback(CallbackFunc callback)
|
||||
{
|
||||
m_FileLoadedCb = callback;
|
||||
}
|
||||
void SetFrameWrittenCallback(CallbackFunc callback)
|
||||
{
|
||||
m_FrameWrittenCb = callback;
|
||||
}
|
||||
void SetFileLoadedCallback(CallbackFunc callback) { m_FileLoadedCb = callback; }
|
||||
void SetFrameWrittenCallback(CallbackFunc callback) { m_FrameWrittenCb = callback; }
|
||||
static FifoPlayer& GetInstance();
|
||||
|
||||
private:
|
||||
|
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include "Core/FifoPlayer/FifoRecordAnalyzer.h"
|
||||
|
||||
|
@@ -21,7 +21,8 @@ FifoRecorder::FifoRecorder()
|
||||
m_RecordFramesRemaining(0), m_FinishedCb(nullptr), m_File(nullptr), m_SkipNextData(true),
|
||||
m_SkipFutureData(true), m_FrameEnded(false), m_Ram(Memory::RAM_SIZE),
|
||||
m_ExRam(Memory::EXRAM_SIZE)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
FifoRecorder::~FifoRecorder()
|
||||
{
|
||||
|
@@ -19,10 +19,7 @@ public:
|
||||
void StartRecording(s32 numFrames, CallbackFunc finishedCb);
|
||||
void StopRecording();
|
||||
|
||||
FifoDataFile* GetRecordedFile()
|
||||
{
|
||||
return m_File;
|
||||
}
|
||||
FifoDataFile* GetRecordedFile() { return m_File; }
|
||||
// Called from video thread
|
||||
|
||||
// Must write one full GP command at a time
|
||||
@@ -42,10 +39,7 @@ public:
|
||||
void SetVideoMemory(u32* bpMem, u32* cpMem, u32* xfMem, u32* xfRegs, u32 xfRegsSize);
|
||||
|
||||
// Checked once per frame prior to callng EndFrame()
|
||||
bool IsRecording() const
|
||||
{
|
||||
return m_IsRecording;
|
||||
}
|
||||
bool IsRecording() const { return m_IsRecording; }
|
||||
static FifoRecorder& GetInstance();
|
||||
|
||||
private:
|
||||
|
@@ -16,7 +16,7 @@ class GeckoCode
|
||||
{
|
||||
public:
|
||||
|
||||
GeckoCode(): enabled(false)
|
||||
GeckoCode() : enabled(false)
|
||||
{}
|
||||
|
||||
struct Code
|
||||
|
@@ -15,7 +15,7 @@ namespace Gecko
|
||||
|
||||
void LoadCodes(const IniFile& globalIni, const IniFile& localIni, std::vector<GeckoCode>& gcodes)
|
||||
{
|
||||
const IniFile* inis[2] = {&globalIni, &localIni};
|
||||
const IniFile* inis[2] = { &globalIni, &localIni };
|
||||
|
||||
for (const IniFile* ini : inis)
|
||||
{
|
||||
|
@@ -17,24 +17,24 @@ Output at "48KHz" is actually 48043Hz.
|
||||
Sample counter counts streaming stereo samples after upsampling.
|
||||
[DAC] causes [AI I/F] to read from RAM at rate selected by AIDFR.
|
||||
Each [SRC] will upsample a 32KHz source, or pass through the 48KHz
|
||||
source. The [Mixer]/[DAC] only operate at 48KHz.
|
||||
source. The [Mixer]/[DAC] only operate at 48KHz.
|
||||
|
||||
AIS == disc streaming == DTK(Disk Track Player) == streaming audio, etc.
|
||||
|
||||
Supposedly, the retail hardware only supports 48KHz streaming from
|
||||
[Drive I/F]. However it's more likely that the hardware supports
|
||||
32KHz streaming, and the upsampling is transparent to the user.
|
||||
TODO check if anything tries to stream at 32KHz.
|
||||
[Drive I/F]. However it's more likely that the hardware supports
|
||||
32KHz streaming, and the upsampling is transparent to the user.
|
||||
TODO check if anything tries to stream at 32KHz.
|
||||
|
||||
The [Drive I/F] actually supports simultaneous requests for audio and
|
||||
normal data. For this reason, we can't really get rid of the crit section.
|
||||
normal data. For this reason, we can't really get rid of the crit section.
|
||||
|
||||
IMPORTANT:
|
||||
This file mainly deals with the [Drive I/F], however [AIDFR] controls
|
||||
the rate at which the audio data is DMA'd from RAM into the [AI FIFO]
|
||||
(and the speed at which the FIFO is read by its SRC). Everything else
|
||||
relating to AID happens in DSP.cpp. It's kinda just bad hardware design.
|
||||
TODO maybe the files should be merged?
|
||||
the rate at which the audio data is DMA'd from RAM into the [AI FIFO]
|
||||
(and the speed at which the FIFO is read by its SRC). Everything else
|
||||
relating to AID happens in DSP.cpp. It's kinda just bad hardware design.
|
||||
TODO maybe the files should be merged?
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
@@ -70,16 +70,9 @@ enum
|
||||
};
|
||||
|
||||
// AI Control Register
|
||||
union AICR
|
||||
{
|
||||
AICR()
|
||||
{
|
||||
hex = 0;
|
||||
}
|
||||
AICR(u32 _hex)
|
||||
{
|
||||
hex = _hex;
|
||||
}
|
||||
union AICR {
|
||||
AICR() { hex = 0; }
|
||||
AICR(u32 _hex) { hex = _hex; }
|
||||
struct
|
||||
{
|
||||
u32 PSTAT : 1; // sample counter/playback enable
|
||||
@@ -87,8 +80,8 @@ union AICR
|
||||
u32 AIINTMSK : 1; // 0=interrupt masked 1=interrupt enabled
|
||||
u32 AIINT : 1; // audio interrupt status
|
||||
u32 AIINTVLD : 1; // This bit controls whether AIINT is affected by the Interrupt Timing
|
||||
// register
|
||||
// matching the sample counter. Once set, AIINT will hold its last value
|
||||
// register
|
||||
// matching the sample counter. Once set, AIINT will hold its last value
|
||||
u32 SCRESET : 1; // write to reset counter
|
||||
u32 AIDFR : 1; // AID Frequency (0=48khz 1=32khz)
|
||||
u32 : 25;
|
||||
@@ -97,12 +90,8 @@ union AICR
|
||||
};
|
||||
|
||||
// AI Volume Register
|
||||
union AIVR
|
||||
{
|
||||
AIVR()
|
||||
{
|
||||
hex = 0;
|
||||
}
|
||||
union AIVR {
|
||||
AIVR() { hex = 0; }
|
||||
struct
|
||||
{
|
||||
u32 left : 8;
|
||||
@@ -162,14 +151,14 @@ void Init()
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
{
|
||||
mmio->Register(
|
||||
base | AI_CONTROL_REGISTER, MMIO::DirectRead<u32>(&m_Control.hex),
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
||||
AICR tmpAICtrl(val);
|
||||
|
||||
if (m_Control.AIINTMSK != tmpAICtrl.AIINTMSK)
|
||||
@@ -234,20 +223,17 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
}));
|
||||
|
||||
mmio->Register(base | AI_VOLUME_REGISTER, MMIO::DirectRead<u32>(&m_Volume.hex),
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
||||
m_Volume.hex = val;
|
||||
g_sound_stream->GetMixer()->SetStreamingVolume(m_Volume.left, m_Volume.right);
|
||||
}));
|
||||
|
||||
mmio->Register(base | AI_SAMPLE_COUNTER, MMIO::ComplexRead<u32>([](u32)
|
||||
{
|
||||
mmio->Register(base | AI_SAMPLE_COUNTER, MMIO::ComplexRead<u32>([](u32) {
|
||||
return m_SampleCounter +
|
||||
static_cast<u32>((CoreTiming::GetTicks() - g_LastCPUTime) /
|
||||
g_CPUCyclesPerSample);
|
||||
}),
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
||||
m_SampleCounter = val;
|
||||
g_LastCPUTime = CoreTiming::GetTicks();
|
||||
CoreTiming::RemoveEvent(et_AI);
|
||||
@@ -255,8 +241,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
}));
|
||||
|
||||
mmio->Register(base | AI_INTERRUPT_TIMING, MMIO::DirectRead<u32>(&m_InterruptTiming),
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
||||
DEBUG_LOG(AUDIO_INTERFACE, "AI_INTERRUPT_TIMING=%08x@%08x", val,
|
||||
PowerPC::ppcState.pc);
|
||||
m_InterruptTiming = val;
|
||||
|
@@ -74,10 +74,7 @@ void Run()
|
||||
std::unique_lock<std::mutex> state_lock(s_state_change_lock);
|
||||
while (s_state != CPU_POWERDOWN)
|
||||
{
|
||||
s_state_cpu_cvar.wait(state_lock, []
|
||||
{
|
||||
return !s_state_paused_and_locked;
|
||||
});
|
||||
s_state_cpu_cvar.wait(state_lock, [] { return !s_state_paused_and_locked; });
|
||||
|
||||
switch (s_state)
|
||||
{
|
||||
@@ -113,10 +110,7 @@ void Run()
|
||||
case CPU_STEPPING:
|
||||
// Wait for step command.
|
||||
s_state_cpu_cvar.wait(state_lock,
|
||||
[]
|
||||
{
|
||||
return s_state_cpu_step_instruction || s_state != CPU_STEPPING;
|
||||
});
|
||||
[] { return s_state_cpu_step_instruction || s_state != CPU_STEPPING; });
|
||||
if (s_state != CPU_STEPPING)
|
||||
{
|
||||
// Signal event if the mode changes.
|
||||
@@ -167,10 +161,7 @@ void Stop()
|
||||
s_state_cpu_cvar.notify_one();
|
||||
// FIXME: MsgHandler can cause this to deadlock the GUI Thread. Remove the timeout.
|
||||
bool success = s_state_cpu_idle_cvar.wait_for(state_lock, std::chrono::seconds(5),
|
||||
[]
|
||||
{
|
||||
return !s_state_cpu_thread_active;
|
||||
});
|
||||
[] { return !s_state_cpu_thread_active; });
|
||||
if (!success)
|
||||
ERROR_LOG(POWERPC, "CPU Thread failed to acknowledge CPU_POWERDOWN. It may be deadlocked.");
|
||||
RunAdjacentSystems(false);
|
||||
@@ -193,7 +184,8 @@ const volatile State* GetStatePtr()
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void StepOpcode(Common::Event* event)
|
||||
{
|
||||
@@ -236,10 +228,7 @@ void EnableStepping(bool stepping)
|
||||
// Wait for the CPU Thread to leave the run loop
|
||||
// FIXME: MsgHandler can cause this to deadlock the GUI Thread. Remove the timeout.
|
||||
bool success = s_state_cpu_idle_cvar.wait_for(state_lock, std::chrono::seconds(5),
|
||||
[]
|
||||
{
|
||||
return !s_state_cpu_thread_active;
|
||||
});
|
||||
[] { return !s_state_cpu_thread_active; });
|
||||
if (!success)
|
||||
ERROR_LOG(POWERPC, "Abandoned waiting for CPU Thread! The Core may be deadlocked.");
|
||||
|
||||
@@ -288,10 +277,7 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock, bool control_adjacent)
|
||||
|
||||
// FIXME: MsgHandler can cause this to deadlock the GUI Thread. Remove the timeout.
|
||||
bool success = s_state_cpu_idle_cvar.wait_for(state_lock, std::chrono::seconds(10),
|
||||
[]
|
||||
{
|
||||
return !s_state_cpu_thread_active;
|
||||
});
|
||||
[] { return !s_state_cpu_thread_active; });
|
||||
if (!success)
|
||||
NOTICE_LOG(
|
||||
POWERPC,
|
||||
|
@@ -65,8 +65,7 @@ enum
|
||||
};
|
||||
|
||||
// UARAMCount
|
||||
union UARAMCount
|
||||
{
|
||||
union UARAMCount {
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -76,8 +75,7 @@ union UARAMCount
|
||||
};
|
||||
|
||||
// Blocks are 32 bytes.
|
||||
union UAudioDMAControl
|
||||
{
|
||||
union UAudioDMAControl {
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -85,8 +83,7 @@ union UAudioDMAControl
|
||||
u16 Enable : 1;
|
||||
};
|
||||
|
||||
UAudioDMAControl(u16 _Hex = 0): Hex(_Hex)
|
||||
{}
|
||||
UAudioDMAControl(u16 _Hex = 0) : Hex(_Hex) {}
|
||||
};
|
||||
|
||||
// AudioDMA
|
||||
@@ -99,7 +96,8 @@ struct AudioDMA
|
||||
|
||||
AudioDMA()
|
||||
: current_source_address(0), remaining_blocks_count(0), SourceAddress(0), AudioDMAControl(0)
|
||||
{}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// ARAM_DMA
|
||||
@@ -144,8 +142,7 @@ static u32 last_aram_dma_count;
|
||||
static bool instant_dma;
|
||||
UDSPControl g_dspState;
|
||||
|
||||
union ARAM_Info
|
||||
{
|
||||
union ARAM_Info {
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -290,17 +287,17 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
u16* ptr;
|
||||
bool align_writes_on_32_bytes;
|
||||
} directly_mapped_vars[] = {
|
||||
{AR_INFO, &g_ARAM_Info.Hex},
|
||||
{AR_MODE, &g_AR_MODE},
|
||||
{AR_REFRESH, &g_AR_REFRESH},
|
||||
{AR_DMA_MMADDR_H, MMIO::Utils::HighPart(&g_arDMA.MMAddr)},
|
||||
{AR_DMA_MMADDR_L, MMIO::Utils::LowPart(&g_arDMA.MMAddr), true},
|
||||
{AR_DMA_ARADDR_H, MMIO::Utils::HighPart(&g_arDMA.ARAddr)},
|
||||
{AR_DMA_ARADDR_L, MMIO::Utils::LowPart(&g_arDMA.ARAddr), true},
|
||||
{AR_DMA_CNT_H, MMIO::Utils::HighPart(&g_arDMA.Cnt.Hex)},
|
||||
// AR_DMA_CNT_L triggers DMA
|
||||
{AUDIO_DMA_START_HI, MMIO::Utils::HighPart(&g_audioDMA.SourceAddress)},
|
||||
{AUDIO_DMA_START_LO, MMIO::Utils::LowPart(&g_audioDMA.SourceAddress)},
|
||||
{AR_INFO, &g_ARAM_Info.Hex},
|
||||
{AR_MODE, &g_AR_MODE},
|
||||
{AR_REFRESH, &g_AR_REFRESH},
|
||||
{AR_DMA_MMADDR_H, MMIO::Utils::HighPart(&g_arDMA.MMAddr)},
|
||||
{AR_DMA_MMADDR_L, MMIO::Utils::LowPart(&g_arDMA.MMAddr), true},
|
||||
{AR_DMA_ARADDR_H, MMIO::Utils::HighPart(&g_arDMA.ARAddr)},
|
||||
{AR_DMA_ARADDR_L, MMIO::Utils::LowPart(&g_arDMA.ARAddr), true},
|
||||
{AR_DMA_CNT_H, MMIO::Utils::HighPart(&g_arDMA.Cnt.Hex)},
|
||||
// AR_DMA_CNT_L triggers DMA
|
||||
{AUDIO_DMA_START_HI, MMIO::Utils::HighPart(&g_audioDMA.SourceAddress)},
|
||||
{AUDIO_DMA_START_LO, MMIO::Utils::LowPart(&g_audioDMA.SourceAddress)},
|
||||
};
|
||||
for (auto& mapped_var : directly_mapped_vars)
|
||||
{
|
||||
@@ -311,8 +308,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
|
||||
// DSP mail MMIOs call DSP emulator functions to get results or write data.
|
||||
mmio->Register(
|
||||
base | DSP_MAIL_TO_DSP_HI, MMIO::ComplexRead<u16>([](u32)
|
||||
{
|
||||
base | DSP_MAIL_TO_DSP_HI, MMIO::ComplexRead<u16>([](u32) {
|
||||
if (dsp_slice > DSP_MAIL_SLICE && dsp_is_lle)
|
||||
{
|
||||
dsp_emulator->DSP_Update(DSP_MAIL_SLICE);
|
||||
@@ -320,22 +316,12 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
}
|
||||
return dsp_emulator->DSP_ReadMailBoxHigh(true);
|
||||
}),
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val)
|
||||
{
|
||||
dsp_emulator->DSP_WriteMailBoxHigh(true, val);
|
||||
}));
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val) { dsp_emulator->DSP_WriteMailBoxHigh(true, val); }));
|
||||
mmio->Register(
|
||||
base | DSP_MAIL_TO_DSP_LO,
|
||||
MMIO::ComplexRead<u16>([](u32)
|
||||
{
|
||||
return dsp_emulator->DSP_ReadMailBoxLow(true);
|
||||
}),
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val)
|
||||
{
|
||||
dsp_emulator->DSP_WriteMailBoxLow(true, val);
|
||||
}));
|
||||
mmio->Register(base | DSP_MAIL_FROM_DSP_HI, MMIO::ComplexRead<u16>([](u32)
|
||||
{
|
||||
MMIO::ComplexRead<u16>([](u32) { return dsp_emulator->DSP_ReadMailBoxLow(true); }),
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val) { dsp_emulator->DSP_WriteMailBoxLow(true, val); }));
|
||||
mmio->Register(base | DSP_MAIL_FROM_DSP_HI, MMIO::ComplexRead<u16>([](u32) {
|
||||
if (dsp_slice > DSP_MAIL_SLICE && dsp_is_lle)
|
||||
{
|
||||
dsp_emulator->DSP_Update(DSP_MAIL_SLICE);
|
||||
@@ -344,20 +330,17 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
return dsp_emulator->DSP_ReadMailBoxHigh(false);
|
||||
}),
|
||||
MMIO::InvalidWrite<u16>());
|
||||
mmio->Register(base | DSP_MAIL_FROM_DSP_LO, MMIO::ComplexRead<u16>([](u32)
|
||||
{
|
||||
mmio->Register(base | DSP_MAIL_FROM_DSP_LO, MMIO::ComplexRead<u16>([](u32) {
|
||||
return dsp_emulator->DSP_ReadMailBoxLow(false);
|
||||
}),
|
||||
MMIO::InvalidWrite<u16>());
|
||||
|
||||
mmio->Register(
|
||||
base | DSP_CONTROL, MMIO::ComplexRead<u16>([](u32)
|
||||
{
|
||||
base | DSP_CONTROL, MMIO::ComplexRead<u16>([](u32) {
|
||||
return (g_dspState.Hex & ~DSP_CONTROL_MASK) |
|
||||
(dsp_emulator->DSP_ReadControlRegister() & DSP_CONTROL_MASK);
|
||||
}),
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val) {
|
||||
UDSPControl tmpControl;
|
||||
tmpControl.Hex = (val & ~DSP_CONTROL_MASK) |
|
||||
(dsp_emulator->DSP_WriteControlRegister(val) & DSP_CONTROL_MASK);
|
||||
@@ -404,8 +387,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
|
||||
// ARAM MMIO controlling the DMA start.
|
||||
mmio->Register(base | AR_DMA_CNT_L, MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&g_arDMA.Cnt.Hex)),
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val) {
|
||||
g_arDMA.Cnt.Hex = (g_arDMA.Cnt.Hex & 0xFFFF0000) | (val & ~31);
|
||||
Do_ARAM_DMA();
|
||||
}));
|
||||
@@ -413,8 +395,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
// Audio DMA MMIO controlling the DMA start.
|
||||
mmio->Register(
|
||||
base | AUDIO_DMA_CONTROL_LEN, MMIO::DirectRead<u16>(&g_audioDMA.AudioDMAControl.Hex),
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u16>([](u32, u16 val) {
|
||||
bool already_enabled = g_audioDMA.AudioDMAControl.Enable;
|
||||
g_audioDMA.AudioDMAControl.Hex = val;
|
||||
|
||||
@@ -443,8 +424,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
// Audio DMA blocks remaining is invalid to write to, and requires logic on
|
||||
// the read side.
|
||||
mmio->Register(
|
||||
base | AUDIO_DMA_BLOCKS_LEFT, MMIO::ComplexRead<u16>([](u32)
|
||||
{
|
||||
base | AUDIO_DMA_BLOCKS_LEFT, MMIO::ComplexRead<u16>([](u32) {
|
||||
// remaining_blocks_count is zero-based. DreamMix World Fighters will hang if it never
|
||||
// reaches zero.
|
||||
return (g_audioDMA.remaining_blocks_count > 0 ? g_audioDMA.remaining_blocks_count - 1 : 0);
|
||||
@@ -508,7 +488,7 @@ void UpdateDSPSlice(int cycles)
|
||||
// This happens at 4 khz, since 32 bytes at 4khz = 4 bytes at 32 khz (16bit stereo pcm)
|
||||
void UpdateAudioDMA()
|
||||
{
|
||||
static short zero_samples[8 * 2] = {0};
|
||||
static short zero_samples[8 * 2] = { 0 };
|
||||
if (g_audioDMA.AudioDMAControl.Enable)
|
||||
{
|
||||
// Read audio at g_audioDMA.current_source_address in RAM and push onto an
|
||||
|
@@ -31,8 +31,7 @@ enum
|
||||
|
||||
// UDSPControl
|
||||
#define DSP_CONTROL_MASK 0x0C07
|
||||
union UDSPControl
|
||||
{
|
||||
union UDSPControl {
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -51,13 +50,12 @@ union UDSPControl
|
||||
u16 DSP_mask : 1;
|
||||
// Other ???
|
||||
u16 DMAState : 1; // DSPGetDMAStatus() uses this flag. __ARWaitForDMA() uses it too...maybe
|
||||
// it's just general DMA flag
|
||||
// it's just general DMA flag
|
||||
u16 DSPInitCode : 1; // Indicator that the DSP was initialized?
|
||||
u16 DSPInit : 1; // DSPInit() writes to this flag
|
||||
u16 pad : 4;
|
||||
};
|
||||
UDSPControl(u16 _Hex = 0): Hex(_Hex)
|
||||
{}
|
||||
UDSPControl(u16 _Hex = 0) : Hex(_Hex) {}
|
||||
};
|
||||
|
||||
extern UDSPControl g_dspState;
|
||||
|
@@ -13,7 +13,8 @@
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
|
||||
DSPHLE::DSPHLE()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
bool DSPHLE::Initialize(bool bWii, bool bDSPThread)
|
||||
{
|
||||
@@ -33,7 +34,8 @@ bool DSPHLE::Initialize(bool bWii, bool bDSPThread)
|
||||
}
|
||||
|
||||
void DSPHLE::DSP_StopSoundStream()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void DSPHLE::Shutdown()
|
||||
{
|
||||
@@ -242,4 +244,5 @@ u16 DSPHLE::DSP_ReadControlRegister()
|
||||
}
|
||||
|
||||
void DSPHLE::PauseAndLock(bool doLock, bool unpauseOnUnlock)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
@@ -12,17 +12,14 @@
|
||||
class PointerWrap;
|
||||
class UCodeInterface;
|
||||
|
||||
class DSPHLE: public DSPEmulator
|
||||
class DSPHLE : public DSPEmulator
|
||||
{
|
||||
public:
|
||||
DSPHLE();
|
||||
|
||||
bool Initialize(bool bWii, bool bDSPThread) override;
|
||||
void Shutdown() override;
|
||||
bool IsLLE() override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool IsLLE() override { return false; }
|
||||
void DoState(PointerWrap& p) override;
|
||||
void PauseAndLock(bool doLock, bool unpauseOnUnlock = true) override;
|
||||
|
||||
@@ -36,10 +33,7 @@ public:
|
||||
void DSP_StopSoundStream() override;
|
||||
u32 DSP_UpdateRate() override;
|
||||
|
||||
CMailHandler& AccessMailHandler()
|
||||
{
|
||||
return m_MailHandler;
|
||||
}
|
||||
CMailHandler& AccessMailHandler() { return m_MailHandler; }
|
||||
// Formerly DSPHandler
|
||||
UCodeInterface* GetUCode();
|
||||
void SetUCode(u32 _crc);
|
||||
@@ -63,10 +57,7 @@ private:
|
||||
DSPMailbox = 0x00000000;
|
||||
}
|
||||
|
||||
DSPState()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
DSPState() { Reset(); }
|
||||
};
|
||||
DSPState m_dspState;
|
||||
|
||||
|
@@ -10,7 +10,8 @@
|
||||
#include "Core/HW/DSP.h"
|
||||
|
||||
CMailHandler::CMailHandler()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
CMailHandler::~CMailHandler()
|
||||
{
|
||||
|
@@ -16,7 +16,7 @@
|
||||
#define AX_GC
|
||||
#include "Core/HW/DSPHLE/UCodes/AXVoice.h"
|
||||
|
||||
AXUCode::AXUCode(DSPHLE* dsphle, u32 crc): UCodeInterface(dsphle, crc), m_cmdlist_size(0)
|
||||
AXUCode::AXUCode(DSPHLE* dsphle, u32 crc) : UCodeInterface(dsphle, crc), m_cmdlist_size(0)
|
||||
{
|
||||
WARN_LOG(DSPHLE, "Instantiating AXUCode: crc=%08x", crc);
|
||||
m_mail_handler.PushMail(DSP_INIT);
|
||||
@@ -34,8 +34,8 @@ void AXUCode::LoadResamplingCoefficients()
|
||||
{
|
||||
m_coeffs_available = false;
|
||||
|
||||
std::string filenames[] = {File::GetUserPath(D_GCUSER_IDX) + "dsp_coef.bin",
|
||||
File::GetSysDirectory() + "/GC/dsp_coef.bin"};
|
||||
std::string filenames[] = { File::GetUserPath(D_GCUSER_IDX) + "dsp_coef.bin",
|
||||
File::GetSysDirectory() + "/GC/dsp_coef.bin" };
|
||||
|
||||
size_t fidx;
|
||||
std::string filename;
|
||||
@@ -348,9 +348,12 @@ void AXUCode::SetupProcessing(u32 init_addr)
|
||||
init_data[i] = HLEMemory_Read_U16(init_addr + 2 * i);
|
||||
|
||||
// List of all buffers we have to initialize
|
||||
int* buffers[] = {m_samples_left, m_samples_right, m_samples_surround,
|
||||
m_samples_auxA_left, m_samples_auxA_right, m_samples_auxA_surround,
|
||||
m_samples_auxB_left, m_samples_auxB_right, m_samples_auxB_surround};
|
||||
int* buffers[] =
|
||||
{
|
||||
m_samples_left, m_samples_right, m_samples_surround,
|
||||
m_samples_auxA_left, m_samples_auxA_right, m_samples_auxA_surround,
|
||||
m_samples_auxB_left, m_samples_auxB_right, m_samples_auxB_surround
|
||||
};
|
||||
|
||||
u32 init_idx = 0;
|
||||
for (auto& buffer : buffers)
|
||||
@@ -377,11 +380,11 @@ void AXUCode::SetupProcessing(u32 init_addr)
|
||||
|
||||
void AXUCode::DownloadAndMixWithVolume(u32 addr, u16 vol_main, u16 vol_auxa, u16 vol_auxb)
|
||||
{
|
||||
int* buffers_main[3] = {m_samples_left, m_samples_right, m_samples_surround};
|
||||
int* buffers_auxa[3] = {m_samples_auxA_left, m_samples_auxA_right, m_samples_auxA_surround};
|
||||
int* buffers_auxb[3] = {m_samples_auxB_left, m_samples_auxB_right, m_samples_auxB_surround};
|
||||
int** buffers[3] = {buffers_main, buffers_auxa, buffers_auxb};
|
||||
u16 volumes[3] = {vol_main, vol_auxa, vol_auxb};
|
||||
int* buffers_main[3] = { m_samples_left, m_samples_right, m_samples_surround };
|
||||
int* buffers_auxa[3] = { m_samples_auxA_left, m_samples_auxA_right, m_samples_auxA_surround };
|
||||
int* buffers_auxb[3] = { m_samples_auxB_left, m_samples_auxB_right, m_samples_auxB_surround };
|
||||
int** buffers[3] = { buffers_main, buffers_auxa, buffers_auxb };
|
||||
u16 volumes[3] = { vol_main, vol_auxa, vol_auxb };
|
||||
|
||||
for (u32 i = 0; i < 3; ++i)
|
||||
{
|
||||
@@ -410,9 +413,12 @@ void AXUCode::ProcessPBList(u32 pb_addr)
|
||||
|
||||
while (pb_addr)
|
||||
{
|
||||
AXBuffers buffers = {{m_samples_left, m_samples_right, m_samples_surround, m_samples_auxA_left,
|
||||
m_samples_auxA_right, m_samples_auxA_surround, m_samples_auxB_left,
|
||||
m_samples_auxB_right, m_samples_auxB_surround}};
|
||||
AXBuffers buffers = {
|
||||
{
|
||||
m_samples_left, m_samples_right, m_samples_surround, m_samples_auxA_left,
|
||||
m_samples_auxA_right, m_samples_auxA_surround, m_samples_auxB_left,
|
||||
m_samples_auxB_right, m_samples_auxB_surround}
|
||||
};
|
||||
|
||||
ReadPB(pb_addr, pb);
|
||||
|
||||
@@ -438,7 +444,7 @@ void AXUCode::ProcessPBList(u32 pb_addr)
|
||||
|
||||
void AXUCode::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr)
|
||||
{
|
||||
int* buffers[3] = {nullptr};
|
||||
int* buffers[3] = { nullptr };
|
||||
|
||||
switch (aux_id)
|
||||
{
|
||||
@@ -565,7 +571,7 @@ void AXUCode::SendAUXAndMix(u32 main_auxa_up, u32 auxb_s_up, u32 main_l_dl, u32
|
||||
u32 auxb_l_dl, u32 auxb_r_dl)
|
||||
{
|
||||
// Buffers to upload first
|
||||
int* up_buffers[] = {m_samples_auxA_left, m_samples_auxA_right, m_samples_auxA_surround};
|
||||
int* up_buffers[] = { m_samples_auxA_left, m_samples_auxA_right, m_samples_auxA_surround };
|
||||
|
||||
// Upload AUXA LRS
|
||||
int* ptr = (int*)HLEMemory_Get_Pointer(main_auxa_up);
|
||||
@@ -579,8 +585,8 @@ void AXUCode::SendAUXAndMix(u32 main_auxa_up, u32 auxb_s_up, u32 main_l_dl, u32
|
||||
*ptr++ = Common::swap32(sample);
|
||||
|
||||
// Download buffers and addresses
|
||||
int* dl_buffers[] = {m_samples_left, m_samples_right, m_samples_auxB_left, m_samples_auxB_right};
|
||||
u32 dl_addrs[] = {main_l_dl, main_r_dl, auxb_l_dl, auxb_r_dl};
|
||||
int* dl_buffers[] = { m_samples_left, m_samples_right, m_samples_auxB_left, m_samples_auxB_right };
|
||||
u32 dl_addrs[] = { main_l_dl, main_r_dl, auxb_l_dl, auxb_r_dl };
|
||||
|
||||
// Download and mix
|
||||
for (size_t i = 0; i < ArraySize(dl_buffers); ++i)
|
||||
|
@@ -49,7 +49,7 @@ enum AXMixControl
|
||||
MIX_AUXC_S_RAMP = 0x800000
|
||||
};
|
||||
|
||||
class AXUCode: public UCodeInterface
|
||||
class AXUCode : public UCodeInterface
|
||||
{
|
||||
public:
|
||||
AXUCode(DSPHLE* dsphle, u32 crc);
|
||||
|
@@ -176,7 +176,7 @@ struct PBAudioAddr
|
||||
u16 looping;
|
||||
u16 sample_format;
|
||||
u16 loop_addr_hi; // Start of loop (this will point to a shared "zero" buffer if one-shot mode is
|
||||
// active)
|
||||
// active)
|
||||
u16 loop_addr_lo;
|
||||
u16 end_addr_hi; // End of sample (and loop), inclusive
|
||||
u16 end_addr_lo;
|
||||
@@ -267,8 +267,7 @@ struct PBBiquadFilter
|
||||
u16 a2;
|
||||
};
|
||||
|
||||
union PBInfImpulseResponseWM
|
||||
{
|
||||
union PBInfImpulseResponseWM {
|
||||
PBLowPassFilter lpf;
|
||||
PBBiquadFilter biquad;
|
||||
};
|
||||
@@ -308,7 +307,7 @@ struct AXPBWii
|
||||
PBSampleRateConverterWM remote_src;
|
||||
PBInfImpulseResponseWM remote_iir;
|
||||
|
||||
u16 pad[12]; // align us, captain! (32B)
|
||||
u16 padding[12]; // align us, captain! (32B)
|
||||
};
|
||||
|
||||
// TODO: All these enums have changed a lot for Wii
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/HW/DSP.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/AX.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/AXStructs.h"
|
||||
@@ -37,8 +38,7 @@ namespace
|
||||
#define HILO_TO_32(name) ((name##_hi << 16) | name##_lo)
|
||||
|
||||
// Used to pass a large amount of buffers to the mixing function.
|
||||
union AXBuffers
|
||||
{
|
||||
union AXBuffers {
|
||||
struct
|
||||
{
|
||||
int* left;
|
||||
@@ -225,10 +225,28 @@ u16 AcceleratorGetSample()
|
||||
// stream type. This is what the AX UCode does and I don't really
|
||||
// know why.
|
||||
acc_pb->adpcm.pred_scale = acc_pb->adpcm_loop_info.pred_scale;
|
||||
if (!acc_pb->is_stream)
|
||||
if (SConfig::GetInstance().bRSHACK)
|
||||
{
|
||||
acc_pb->adpcm.yn1 = acc_pb->adpcm_loop_info.yn1;
|
||||
acc_pb->adpcm.yn2 = acc_pb->adpcm_loop_info.yn2;
|
||||
if (acc_pb->is_stream)
|
||||
{
|
||||
// HORRIBLE HACK: this behavior changed between versions at some point; needs some sort
|
||||
// of branch. delroth says anyone who submits this code as a serious PR will be banned
|
||||
// from Dolphin.
|
||||
// needed for RS2
|
||||
acc_pb->lpf.enabled += 1;
|
||||
// needed for RS3
|
||||
acc_pb->padding[0] += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!acc_pb->is_stream)
|
||||
{
|
||||
acc_pb->adpcm.yn1 = acc_pb->adpcm_loop_info.yn1;
|
||||
acc_pb->adpcm.yn2 = acc_pb->adpcm_loop_info.yn2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -395,10 +413,7 @@ void GetInputSamples(PB_TYPE& pb, s16* samples, u16 count, const s16* coeffs)
|
||||
if (coeffs)
|
||||
coeffs += pb.coef_select * 0x200;
|
||||
u32 curr_pos =
|
||||
ResampleAudio([](u32)
|
||||
{
|
||||
return AcceleratorGetSample();
|
||||
}, samples, count, pb.src.last_samples,
|
||||
ResampleAudio([](u32) { return AcceleratorGetSample(); }, samples, count, pb.src.last_samples,
|
||||
pb.src.cur_addr_frac, HILO_TO_32(pb.src.ratio), pb.src_type, coeffs);
|
||||
pb.src.cur_addr_frac = (curr_pos & 0xFFFF);
|
||||
|
||||
@@ -537,10 +552,7 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl
|
||||
|
||||
// We use ratio 0x55555 == (5 * 65536 + 21845) / 65536 == 5.3333 which
|
||||
// is the nearest we can get to 96/18
|
||||
u32 curr_pos = ResampleAudio([&samples](u32 i)
|
||||
{
|
||||
return samples[i];
|
||||
}, wm_samples, wm_count,
|
||||
u32 curr_pos = ResampleAudio([&samples](u32 i) { return samples[i]; }, wm_samples, wm_count,
|
||||
pb.remote_src.last_samples, pb.remote_src.cur_addr_frac, 0x55555,
|
||||
SRCTYPE_POLYPHASE, coeffs);
|
||||
pb.remote_src.cur_addr_frac = curr_pos & 0xFFFF;
|
||||
|
@@ -15,7 +15,7 @@
|
||||
#include "Core/HW/DSPHLE/UCodes/AXVoice.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||
|
||||
AXWiiUCode::AXWiiUCode(DSPHLE* dsphle, u32 crc): AXUCode(dsphle, crc), m_last_main_volume(0x8000)
|
||||
AXWiiUCode::AXWiiUCode(DSPHLE* dsphle, u32 crc) : AXUCode(dsphle, crc), m_last_main_volume(0x8000)
|
||||
{
|
||||
for (u16& volume : m_last_aux_volumes)
|
||||
volume = 0x8000;
|
||||
@@ -26,7 +26,8 @@ AXWiiUCode::AXWiiUCode(DSPHLE* dsphle, u32 crc): AXUCode(dsphle, crc), m_last_ma
|
||||
}
|
||||
|
||||
AXWiiUCode::~AXWiiUCode()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void AXWiiUCode::HandleCommandList()
|
||||
{
|
||||
@@ -100,12 +101,12 @@ void AXWiiUCode::HandleCommandList()
|
||||
{
|
||||
volume = m_cmdlist[curr_idx++];
|
||||
u32 addresses[6] = {
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
(u32)(m_cmdlist[curr_idx + 8] << 16) | m_cmdlist[curr_idx + 9],
|
||||
(u32)(m_cmdlist[curr_idx + 10] << 16) | m_cmdlist[curr_idx + 11],
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
(u32)(m_cmdlist[curr_idx + 8] << 16) | m_cmdlist[curr_idx + 9],
|
||||
(u32)(m_cmdlist[curr_idx + 10] << 16) | m_cmdlist[curr_idx + 11],
|
||||
};
|
||||
curr_idx += 12;
|
||||
UploadAUXMixLRSC(cmd == CMD_UPL_AUXB_MIX_LRSC_OLD, addresses, volume);
|
||||
@@ -130,10 +131,10 @@ void AXWiiUCode::HandleCommandList()
|
||||
case CMD_WM_OUTPUT_OLD:
|
||||
{
|
||||
u32 addresses[4] = {
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
};
|
||||
curr_idx += 8;
|
||||
OutputWMSamples(addresses);
|
||||
@@ -193,12 +194,12 @@ void AXWiiUCode::HandleCommandList()
|
||||
{
|
||||
volume = m_cmdlist[curr_idx++];
|
||||
u32 addresses[6] = {
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
(u32)(m_cmdlist[curr_idx + 8] << 16) | m_cmdlist[curr_idx + 9],
|
||||
(u32)(m_cmdlist[curr_idx + 10] << 16) | m_cmdlist[curr_idx + 11],
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
(u32)(m_cmdlist[curr_idx + 8] << 16) | m_cmdlist[curr_idx + 9],
|
||||
(u32)(m_cmdlist[curr_idx + 10] << 16) | m_cmdlist[curr_idx + 11],
|
||||
};
|
||||
curr_idx += 12;
|
||||
UploadAUXMixLRSC(cmd == CMD_UPL_AUXB_MIX_LRSC, addresses, volume);
|
||||
@@ -224,10 +225,10 @@ void AXWiiUCode::HandleCommandList()
|
||||
case CMD_WM_OUTPUT:
|
||||
{
|
||||
u32 addresses[4] = {
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
(u32)(m_cmdlist[curr_idx + 0] << 16) | m_cmdlist[curr_idx + 1],
|
||||
(u32)(m_cmdlist[curr_idx + 2] << 16) | m_cmdlist[curr_idx + 3],
|
||||
(u32)(m_cmdlist[curr_idx + 4] << 16) | m_cmdlist[curr_idx + 5],
|
||||
(u32)(m_cmdlist[curr_idx + 6] << 16) | m_cmdlist[curr_idx + 7],
|
||||
};
|
||||
curr_idx += 8;
|
||||
OutputWMSamples(addresses);
|
||||
@@ -256,14 +257,14 @@ void AXWiiUCode::SetupProcessing(u32 init_addr)
|
||||
int* ptr;
|
||||
u32 samples;
|
||||
} buffers[] = {
|
||||
{m_samples_left, 32}, {m_samples_right, 32}, {m_samples_surround, 32},
|
||||
{m_samples_auxA_left, 32}, {m_samples_auxA_right, 32}, {m_samples_auxA_surround, 32},
|
||||
{m_samples_auxB_left, 32}, {m_samples_auxB_right, 32}, {m_samples_auxB_surround, 32},
|
||||
{m_samples_auxC_left, 32}, {m_samples_auxC_right, 32}, {m_samples_auxC_surround, 32},
|
||||
{m_samples_left, 32}, {m_samples_right, 32}, {m_samples_surround, 32},
|
||||
{m_samples_auxA_left, 32}, {m_samples_auxA_right, 32}, {m_samples_auxA_surround, 32},
|
||||
{m_samples_auxB_left, 32}, {m_samples_auxB_right, 32}, {m_samples_auxB_surround, 32},
|
||||
{m_samples_auxC_left, 32}, {m_samples_auxC_right, 32}, {m_samples_auxC_surround, 32},
|
||||
|
||||
{m_samples_wm0, 6}, {m_samples_aux0, 6}, {m_samples_wm1, 6},
|
||||
{m_samples_aux1, 6}, {m_samples_wm2, 6}, {m_samples_aux2, 6},
|
||||
{m_samples_wm3, 6}, {m_samples_aux3, 6}};
|
||||
{m_samples_wm0, 6}, {m_samples_aux0, 6}, {m_samples_wm1, 6},
|
||||
{m_samples_aux1, 6}, {m_samples_wm2, 6}, {m_samples_aux2, 6},
|
||||
{m_samples_wm3, 6}, {m_samples_aux3, 6} };
|
||||
|
||||
u32 init_idx = 0;
|
||||
for (auto& buffer : buffers)
|
||||
@@ -436,13 +437,18 @@ void AXWiiUCode::ProcessPBList(u32 pb_addr)
|
||||
|
||||
while (pb_addr)
|
||||
{
|
||||
AXBuffers buffers = {{m_samples_left, m_samples_right, m_samples_surround,
|
||||
m_samples_auxA_left, m_samples_auxA_right, m_samples_auxA_surround,
|
||||
m_samples_auxB_left, m_samples_auxB_right, m_samples_auxB_surround,
|
||||
m_samples_auxC_left, m_samples_auxC_right, m_samples_auxC_surround,
|
||||
m_samples_wm0, m_samples_aux0, m_samples_wm1,
|
||||
m_samples_aux1, m_samples_wm2, m_samples_aux2,
|
||||
m_samples_wm3, m_samples_aux3}};
|
||||
AXBuffers buffers =
|
||||
{
|
||||
{
|
||||
m_samples_left, m_samples_right, m_samples_surround,
|
||||
m_samples_auxA_left, m_samples_auxA_right, m_samples_auxA_surround,
|
||||
m_samples_auxB_left, m_samples_auxB_right, m_samples_auxB_surround,
|
||||
m_samples_auxC_left, m_samples_auxC_right, m_samples_auxC_surround,
|
||||
m_samples_wm0, m_samples_aux0, m_samples_wm1,
|
||||
m_samples_aux1, m_samples_wm2, m_samples_aux2,
|
||||
m_samples_wm3, m_samples_aux3
|
||||
}
|
||||
};
|
||||
|
||||
ReadPB(pb_addr, pb);
|
||||
|
||||
@@ -480,8 +486,8 @@ void AXWiiUCode::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr, u16 vo
|
||||
GenerateVolumeRamp(volume_ramp, m_last_aux_volumes[aux_id], volume, ArraySize(volume_ramp));
|
||||
m_last_aux_volumes[aux_id] = volume;
|
||||
|
||||
int* buffers[3] = {nullptr};
|
||||
int* main_buffers[3] = {m_samples_left, m_samples_right, m_samples_surround};
|
||||
int* buffers[3] = { nullptr };
|
||||
int* main_buffers[3] = { m_samples_left, m_samples_right, m_samples_surround };
|
||||
|
||||
switch (aux_id)
|
||||
{
|
||||
@@ -547,7 +553,7 @@ void AXWiiUCode::UploadAUXMixLRSC(int aux_id, u32* addresses, u16 volume)
|
||||
GenerateVolumeRamp(volume_ramp, m_last_aux_volumes[aux_id], volume, 96);
|
||||
m_last_aux_volumes[aux_id] = volume;
|
||||
|
||||
int* mix_dest[4] = {m_samples_left, m_samples_right, m_samples_surround, m_samples_auxC_left};
|
||||
int* mix_dest[4] = { m_samples_left, m_samples_right, m_samples_surround, m_samples_auxC_left };
|
||||
for (u32 mix_i = 0; mix_i < 4; ++mix_i)
|
||||
{
|
||||
int* dl_ptr = (int*)HLEMemory_Get_Pointer(addresses[2 + mix_i]);
|
||||
@@ -569,7 +575,7 @@ void AXWiiUCode::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume, bool
|
||||
GenerateVolumeRamp(volume_ramp, m_last_main_volume, volume, ArraySize(volume_ramp));
|
||||
m_last_main_volume = volume;
|
||||
|
||||
int upload_buffer[3 * 32] = {0};
|
||||
int upload_buffer[3 * 32] = { 0 };
|
||||
|
||||
for (u32 i = 0; i < 3 * 32; ++i)
|
||||
upload_buffer[i] = Common::swap32(m_samples_surround[i]);
|
||||
@@ -614,7 +620,7 @@ void AXWiiUCode::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume, bool
|
||||
|
||||
void AXWiiUCode::OutputWMSamples(u32* addresses)
|
||||
{
|
||||
int* buffers[] = {m_samples_wm0, m_samples_wm1, m_samples_wm2, m_samples_wm3};
|
||||
int* buffers[] = { m_samples_wm0, m_samples_wm1, m_samples_wm2, m_samples_wm3 };
|
||||
|
||||
for (u32 i = 0; i < 4; ++i)
|
||||
{
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
struct AXPBWii;
|
||||
|
||||
class AXWiiUCode: public AXUCode
|
||||
class AXWiiUCode : public AXUCode
|
||||
{
|
||||
public:
|
||||
AXWiiUCode(DSPHLE* dsphle, u32 crc);
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#include "Core/HW/DSPHLE/DSPHLE.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||
|
||||
CARDUCode::CARDUCode(DSPHLE* dsphle, u32 crc): UCodeInterface(dsphle, crc)
|
||||
CARDUCode::CARDUCode(DSPHLE* dsphle, u32 crc) : UCodeInterface(dsphle, crc)
|
||||
{
|
||||
DEBUG_LOG(DSPHLE, "CARDUCode - initialized");
|
||||
m_mail_handler.PushMail(DSP_INIT);
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||
|
||||
class CARDUCode: public UCodeInterface
|
||||
class CARDUCode : public UCodeInterface
|
||||
{
|
||||
public:
|
||||
CARDUCode(DSPHLE* dsphle, u32 crc);
|
||||
|
@@ -82,7 +82,7 @@ void ProcessGBACrypto(u32 address)
|
||||
*(u32*)sec_params.unk1, *(u32*)sec_params.unk2, x22, x23);
|
||||
}
|
||||
|
||||
GBAUCode::GBAUCode(DSPHLE* dsphle, u32 crc): UCodeInterface(dsphle, crc)
|
||||
GBAUCode::GBAUCode(DSPHLE* dsphle, u32 crc) : UCodeInterface(dsphle, crc)
|
||||
{
|
||||
m_mail_handler.PushMail(DSP_INIT);
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@
|
||||
// written back to RAM at the dest address provided in the crypto parameters.
|
||||
void ProcessGBACrypto(u32 address);
|
||||
|
||||
struct GBAUCode: public UCodeInterface
|
||||
struct GBAUCode : public UCodeInterface
|
||||
{
|
||||
GBAUCode(DSPHLE* dsphle, u32 crc);
|
||||
virtual ~GBAUCode();
|
||||
|
@@ -7,20 +7,24 @@
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||
|
||||
INITUCode::INITUCode(DSPHLE* dsphle, u32 crc): UCodeInterface(dsphle, crc)
|
||||
INITUCode::INITUCode(DSPHLE* dsphle, u32 crc) : UCodeInterface(dsphle, crc)
|
||||
{
|
||||
DEBUG_LOG(DSPHLE, "INITUCode - initialized");
|
||||
m_mail_handler.PushMail(0x80544348);
|
||||
}
|
||||
|
||||
INITUCode::~INITUCode()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void INITUCode::Init()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void INITUCode::Update()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void INITUCode::HandleMail(u32 mail)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||
|
||||
class INITUCode: public UCodeInterface
|
||||
class INITUCode : public UCodeInterface
|
||||
{
|
||||
public:
|
||||
INITUCode(DSPHLE* dsphle, u32 crc);
|
||||
|
@@ -27,10 +27,12 @@ ROMUCode::ROMUCode(DSPHLE* dsphle, u32 crc)
|
||||
}
|
||||
|
||||
ROMUCode::~ROMUCode()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void ROMUCode::Update()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void ROMUCode::HandleMail(u32 mail)
|
||||
{
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||
|
||||
class ROMUCode: public UCodeInterface
|
||||
class ROMUCode : public UCodeInterface
|
||||
{
|
||||
public:
|
||||
ROMUCode(DSPHLE* dsphle, u32 crc);
|
||||
|
@@ -47,13 +47,13 @@ UCodeInterface* UCodeFactory(u32 crc, DSPHLE* dsphle, bool wii)
|
||||
case 0x3ad3b7ac: // Naruto 3, Paper Mario - The Thousand Year Door
|
||||
case 0x3daf59b9: // Alien Hominid
|
||||
case 0x4e8a8b21: // spdemo, Crazy Taxi, 18 Wheeler, Disney, Monkeyball 1/2, Cubivore, Nintendo
|
||||
// Puzzle Collection, Wario,
|
||||
// Puzzle Collection, Wario,
|
||||
// Capcom vs. SNK 2, Naruto 2, Lost Kingdoms, Star Fox, Mario Party 4, Mortal Kombat,
|
||||
// Smugglers Run Warzone, Smash Brothers, Sonic Mega Collection, ZooCube
|
||||
// nddemo, Star Fox
|
||||
case 0x07f88145: // bustamove, Ikaruga, F-Zero GX, Robotech Battle Cry, Star Soldier, Soul
|
||||
// Calibur 2,
|
||||
// Zelda:OOT, Tony Hawk, Viewtiful Joe
|
||||
// Calibur 2,
|
||||
// Zelda:OOT, Tony Hawk, Viewtiful Joe
|
||||
case 0xe2136399: // Billy Hatcher, Dragon Ball Z, Mario Party 5, TMNT, 1080° Avalanche
|
||||
case 0x3389a79e: // MP1/MP2 Wii (Metroid Prime Trilogy)
|
||||
INFO_LOG(DSPHLE, "CRC %08x: AX ucode chosen", crc);
|
||||
|
@@ -69,21 +69,15 @@ public:
|
||||
: m_mail_handler(dsphle->AccessMailHandler()), m_upload_setup_in_progress(false),
|
||||
m_dsphle(dsphle), m_crc(crc), m_next_ucode(), m_next_ucode_steps(0),
|
||||
m_needs_resume_mail(false)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~UCodeInterface()
|
||||
{}
|
||||
virtual ~UCodeInterface() {}
|
||||
virtual void HandleMail(u32 mail) = 0;
|
||||
virtual void Update() = 0;
|
||||
|
||||
virtual void DoState(PointerWrap& p)
|
||||
{
|
||||
DoStateShared(p);
|
||||
}
|
||||
static u32 GetCRC(UCodeInterface* ucode)
|
||||
{
|
||||
return ucode ? ucode->m_crc : UCODE_NULL;
|
||||
}
|
||||
virtual void DoState(PointerWrap& p) { DoStateShared(p); }
|
||||
static u32 GetCRC(UCodeInterface* ucode) { return ucode ? ucode->m_crc : UCODE_NULL; }
|
||||
protected:
|
||||
void PrepareBootUCode(u32 mail);
|
||||
|
||||
|
@@ -69,7 +69,7 @@ enum ZeldaUCodeFlag
|
||||
static const std::map<u32, u32> UCODE_FLAGS = {
|
||||
// GameCube IPL/BIOS, NTSC.
|
||||
{0x24B22038, LIGHT_PROTOCOL | FOUR_MIXING_DESTS | TINY_VPB | VOLUME_EXPLICIT_STEP | NO_CMD_0D |
|
||||
WEIRD_CMD_0C},
|
||||
WEIRD_CMD_0C},
|
||||
// GameCube IPL/BIOS, PAL.
|
||||
{0x6BA3B3EA, LIGHT_PROTOCOL | FOUR_MIXING_DESTS | NO_CMD_0D | WEIRD_CMD_0C},
|
||||
// Pikmin 1 GC NTSC.
|
||||
@@ -109,7 +109,7 @@ static const std::map<u32, u32> UCODE_FLAGS = {
|
||||
// * The Legend of Zelda: Twilight Princess / Wii (type ????, CRC ????)
|
||||
};
|
||||
|
||||
ZeldaUCode::ZeldaUCode(DSPHLE* dsphle, u32 crc): UCodeInterface(dsphle, crc)
|
||||
ZeldaUCode::ZeldaUCode(DSPHLE* dsphle, u32 crc) : UCodeInterface(dsphle, crc)
|
||||
{
|
||||
auto it = UCODE_FLAGS.find(crc);
|
||||
if (it == UCODE_FLAGS.end())
|
||||
@@ -694,14 +694,8 @@ struct ZeldaAudioRenderer::VPB
|
||||
// (left/right) and Y (front/back) coordinates of the sound. 0x00 is all
|
||||
// right/back, 0x7F is all left/front. Format is 0XXXXXXX0YYYYYYY.
|
||||
u16 dolby_voice_position;
|
||||
u8 GetDolbyVoiceX() const
|
||||
{
|
||||
return (dolby_voice_position >> 8) & 0x7F;
|
||||
}
|
||||
u8 GetDolbyVoiceY() const
|
||||
{
|
||||
return dolby_voice_position & 0x7F;
|
||||
}
|
||||
u8 GetDolbyVoiceX() const { return (dolby_voice_position >> 8) & 0x7F; }
|
||||
u8 GetDolbyVoiceY() const { return dolby_voice_position & 0x7F; }
|
||||
// How much reverbation to apply to the Dolby mixed voice. 0 is none,
|
||||
// 0x7FFF is the maximum value.
|
||||
s16 dolby_reverb_factor;
|
||||
@@ -774,14 +768,8 @@ struct ZeldaAudioRenderer::VPB
|
||||
// requires the two latest sample values to be able to decode future
|
||||
// samples.
|
||||
s16 afc_remaining_samples[0x10];
|
||||
s16* AFCYN2()
|
||||
{
|
||||
return &afc_remaining_samples[0xE];
|
||||
}
|
||||
s16* AFCYN1()
|
||||
{
|
||||
return &afc_remaining_samples[0xF];
|
||||
}
|
||||
s16* AFCYN2() { return &afc_remaining_samples[0xE]; }
|
||||
s16* AFCYN1() { return &afc_remaining_samples[0xF]; }
|
||||
u16 unk_68_80[0x80 - 0x68];
|
||||
|
||||
enum SamplesSourceType
|
||||
@@ -1003,11 +991,11 @@ void ZeldaAudioRenderer::ApplyReverb(bool post_rendering)
|
||||
|
||||
// Each of the 4 RPBs maps to one of these buffers.
|
||||
MixingBuffer* reverb_buffers[4] = {
|
||||
&m_buf_unk0_reverb, &m_buf_unk1_reverb, &m_buf_front_left_reverb, &m_buf_front_right_reverb,
|
||||
&m_buf_unk0_reverb, &m_buf_unk1_reverb, &m_buf_front_left_reverb, &m_buf_front_right_reverb,
|
||||
};
|
||||
std::array<s16, 8>* last8_samples_buffers[4] = {
|
||||
&m_buf_unk0_reverb_last8, &m_buf_unk1_reverb_last8, &m_buf_front_left_reverb_last8,
|
||||
&m_buf_front_right_reverb_last8,
|
||||
&m_buf_unk0_reverb_last8, &m_buf_unk1_reverb_last8, &m_buf_front_left_reverb_last8,
|
||||
&m_buf_front_right_reverb_last8,
|
||||
};
|
||||
|
||||
u16* rpb_base_ptr = (u16*)HLEMemory_Get_Pointer(m_reverb_pb_base_addr);
|
||||
@@ -1041,8 +1029,7 @@ void ZeldaAudioRenderer::ApplyReverb(bool post_rendering)
|
||||
for (u16 i = 0; i < 8; ++i)
|
||||
(*last8_samples_buffers[rpb_idx])[i] = buffer[0x50 + i];
|
||||
|
||||
auto ApplyFilter = [&]()
|
||||
{
|
||||
auto ApplyFilter = [&]() {
|
||||
// Filter the buffer using provided coefficients.
|
||||
for (u16 i = 0; i < 0x50; ++i)
|
||||
{
|
||||
@@ -1163,10 +1150,10 @@ void ZeldaAudioRenderer::AddVoice(u16 voice_id)
|
||||
// Compute volume for each quadrant.
|
||||
u16 shift_factor = (m_flags & MAKE_DOLBY_LOUDER) ? 15 : 16;
|
||||
s16 quadrant_volumes[4] = {
|
||||
(s16)((left_volume * front_volume) >> shift_factor),
|
||||
(s16)((left_volume * back_volume) >> shift_factor),
|
||||
(s16)((right_volume * front_volume) >> shift_factor),
|
||||
(s16)((right_volume * back_volume) >> shift_factor),
|
||||
(s16)((left_volume * front_volume) >> shift_factor),
|
||||
(s16)((left_volume * back_volume) >> shift_factor),
|
||||
(s16)((right_volume * front_volume) >> shift_factor),
|
||||
(s16)((right_volume * back_volume) >> shift_factor),
|
||||
};
|
||||
|
||||
// Compute the volume delta for each sample to match the difference
|
||||
@@ -1196,15 +1183,15 @@ void ZeldaAudioRenderer::AddVoice(u16 voice_id)
|
||||
s16 volume;
|
||||
s16 volume_delta;
|
||||
} buffers[8] = {
|
||||
{&m_buf_front_left, quadrant_volumes[0], volume_deltas[0]},
|
||||
{&m_buf_back_left, quadrant_volumes[1], volume_deltas[1]},
|
||||
{&m_buf_front_right, quadrant_volumes[2], volume_deltas[2]},
|
||||
{&m_buf_back_right, quadrant_volumes[3], volume_deltas[3]},
|
||||
{&m_buf_front_left, quadrant_volumes[0], volume_deltas[0]},
|
||||
{&m_buf_back_left, quadrant_volumes[1], volume_deltas[1]},
|
||||
{&m_buf_front_right, quadrant_volumes[2], volume_deltas[2]},
|
||||
{&m_buf_back_right, quadrant_volumes[3], volume_deltas[3]},
|
||||
|
||||
{&m_buf_front_left_reverb, reverb_volumes[0], reverb_volume_deltas[0]},
|
||||
{&m_buf_back_left_reverb, reverb_volumes[1], reverb_volume_deltas[1]},
|
||||
{&m_buf_front_right_reverb, reverb_volumes[2], reverb_volume_deltas[2]},
|
||||
{&m_buf_back_right_reverb, reverb_volumes[3], reverb_volume_deltas[3]},
|
||||
{&m_buf_front_left_reverb, reverb_volumes[0], reverb_volume_deltas[0]},
|
||||
{&m_buf_back_left_reverb, reverb_volumes[1], reverb_volume_deltas[1]},
|
||||
{&m_buf_front_right_reverb, reverb_volumes[2], reverb_volume_deltas[2]},
|
||||
{&m_buf_back_right_reverb, reverb_volumes[3], reverb_volume_deltas[3]},
|
||||
};
|
||||
for (const auto& buffer : buffers)
|
||||
{
|
||||
@@ -1400,9 +1387,9 @@ void ZeldaAudioRenderer::LoadInputSamples(MixingBuffer* buffer, VPB* vpb)
|
||||
bool variable_step;
|
||||
};
|
||||
std::map<u16, PatternInfo> samples_source_to_pattern = {
|
||||
{VPB::SRC_CONST_PATTERN_0, {0, false}}, {VPB::SRC_CONST_PATTERN_0_VARIABLE_STEP, {0, true}},
|
||||
{VPB::SRC_CONST_PATTERN_1, {1, false}}, {VPB::SRC_CONST_PATTERN_2, {2, false}},
|
||||
{VPB::SRC_CONST_PATTERN_3, {3, false}},
|
||||
{VPB::SRC_CONST_PATTERN_0, {0, false}}, {VPB::SRC_CONST_PATTERN_0_VARIABLE_STEP, {0, true}},
|
||||
{VPB::SRC_CONST_PATTERN_1, {1, false}}, {VPB::SRC_CONST_PATTERN_2, {2, false}},
|
||||
{VPB::SRC_CONST_PATTERN_3, {3, false}},
|
||||
};
|
||||
auto& pattern_info = samples_source_to_pattern[vpb->samples_source_type];
|
||||
u16 pattern_offset = pattern_info.idx * PATTERN_SIZE;
|
||||
|
@@ -15,50 +15,17 @@ public:
|
||||
void AddVoice(u16 voice_id);
|
||||
void FinalizeFrame();
|
||||
|
||||
void SetFlags(u32 flags)
|
||||
{
|
||||
m_flags = flags;
|
||||
}
|
||||
void SetSineTable(std::array<s16, 0x80>&& sine_table)
|
||||
{
|
||||
m_sine_table = sine_table;
|
||||
}
|
||||
void SetConstPatterns(std::array<s16, 0x100>&& patterns)
|
||||
{
|
||||
m_const_patterns = patterns;
|
||||
}
|
||||
void SetResamplingCoeffs(std::array<s16, 0x100>&& coeffs)
|
||||
{
|
||||
m_resampling_coeffs = coeffs;
|
||||
}
|
||||
void SetAfcCoeffs(std::array<s16, 0x20>&& coeffs)
|
||||
{
|
||||
m_afc_coeffs = coeffs;
|
||||
}
|
||||
void SetVPBBaseAddress(u32 addr)
|
||||
{
|
||||
m_vpb_base_addr = addr;
|
||||
}
|
||||
void SetReverbPBBaseAddress(u32 addr)
|
||||
{
|
||||
m_reverb_pb_base_addr = addr;
|
||||
}
|
||||
void SetOutputVolume(u16 volume)
|
||||
{
|
||||
m_output_volume = volume;
|
||||
}
|
||||
void SetOutputLeftBufferAddr(u32 addr)
|
||||
{
|
||||
m_output_lbuf_addr = addr;
|
||||
}
|
||||
void SetOutputRightBufferAddr(u32 addr)
|
||||
{
|
||||
m_output_rbuf_addr = addr;
|
||||
}
|
||||
void SetARAMBaseAddr(u32 addr)
|
||||
{
|
||||
m_aram_base_addr = addr;
|
||||
}
|
||||
void SetFlags(u32 flags) { m_flags = flags; }
|
||||
void SetSineTable(std::array<s16, 0x80>&& sine_table) { m_sine_table = sine_table; }
|
||||
void SetConstPatterns(std::array<s16, 0x100>&& patterns) { m_const_patterns = patterns; }
|
||||
void SetResamplingCoeffs(std::array<s16, 0x100>&& coeffs) { m_resampling_coeffs = coeffs; }
|
||||
void SetAfcCoeffs(std::array<s16, 0x20>&& coeffs) { m_afc_coeffs = coeffs; }
|
||||
void SetVPBBaseAddress(u32 addr) { m_vpb_base_addr = addr; }
|
||||
void SetReverbPBBaseAddress(u32 addr) { m_reverb_pb_base_addr = addr; }
|
||||
void SetOutputVolume(u16 volume) { m_output_volume = volume; }
|
||||
void SetOutputLeftBufferAddr(u32 addr) { m_output_lbuf_addr = addr; }
|
||||
void SetOutputRightBufferAddr(u32 addr) { m_output_rbuf_addr = addr; }
|
||||
void SetARAMBaseAddr(u32 addr) { m_aram_base_addr = addr; }
|
||||
void DoState(PointerWrap& p);
|
||||
|
||||
private:
|
||||
@@ -215,7 +182,7 @@ private:
|
||||
u32 m_reverb_pb_base_addr = 0;
|
||||
};
|
||||
|
||||
class ZeldaUCode: public UCodeInterface
|
||||
class ZeldaUCode : public UCodeInterface
|
||||
{
|
||||
public:
|
||||
ZeldaUCode(DSPHLE* dsphle, u32 crc);
|
||||
@@ -242,7 +209,7 @@ private:
|
||||
// of the original DSP implementation is rewritten in an asynchronous/coro
|
||||
// + state machine style. It is less readable, but the best we can do given
|
||||
// our constraints.
|
||||
enum class MailState: u32
|
||||
enum class MailState : u32
|
||||
{
|
||||
WAITING,
|
||||
RENDERING,
|
||||
@@ -307,7 +274,7 @@ private:
|
||||
void RunPendingCommands();
|
||||
|
||||
// Sends the two mails from DSP to CPU to ack the command execution.
|
||||
enum class CommandAck: u32
|
||||
enum class CommandAck : u32
|
||||
{
|
||||
STANDARD,
|
||||
DONE_RENDERING,
|
||||
|
@@ -148,12 +148,12 @@ void DSPDebugInterface::InsertBLR(unsigned int address, unsigned int value)
|
||||
int DSPDebugInterface::GetColor(unsigned int address)
|
||||
{
|
||||
static const int colors[6] = {
|
||||
0xd0FFFF, // light cyan
|
||||
0xFFd0d0, // light red
|
||||
0xd8d8FF, // light blue
|
||||
0xFFd0FF, // light purple
|
||||
0xd0FFd0, // light green
|
||||
0xFFFFd0, // light yellow
|
||||
0xd0FFFF, // light cyan
|
||||
0xFFd0d0, // light red
|
||||
0xd8d8FF, // light blue
|
||||
0xFFd0FF, // light purple
|
||||
0xd0FFd0, // light green
|
||||
0xFFFFd0, // light yellow
|
||||
};
|
||||
|
||||
// Scan backwards so we don't miss it. Hm, actually, let's not - it looks pretty good.
|
||||
@@ -194,4 +194,5 @@ void DSPDebugInterface::SetPC(unsigned int address)
|
||||
}
|
||||
|
||||
void DSPDebugInterface::RunToBreakpoint()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
@@ -9,17 +9,13 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/DebugInterface.h"
|
||||
|
||||
class DSPDebugInterface final: public DebugInterface
|
||||
class DSPDebugInterface final : public DebugInterface
|
||||
{
|
||||
public:
|
||||
DSPDebugInterface()
|
||||
{}
|
||||
DSPDebugInterface() {}
|
||||
std::string Disassemble(unsigned int address) override;
|
||||
void GetRawMemoryString(int memory, unsigned int address, char* dest, int max_size) override;
|
||||
int GetInstructionSize(int instruction) override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int GetInstructionSize(int instruction) override { return 1; }
|
||||
bool IsAlive() override;
|
||||
bool IsBreakpoint(unsigned int address) override;
|
||||
void SetBreakpoint(unsigned int address) override;
|
||||
@@ -33,8 +29,7 @@ public:
|
||||
unsigned int ReadInstruction(unsigned int address) override;
|
||||
unsigned int GetPC() override;
|
||||
void SetPC(unsigned int address) override;
|
||||
void Step() override
|
||||
{}
|
||||
void Step() override {}
|
||||
void RunToBreakpoint() override;
|
||||
void InsertBLR(unsigned int address, unsigned int value) override;
|
||||
int GetColor(unsigned int address) override;
|
||||
|
@@ -31,7 +31,8 @@
|
||||
DSPLLE::DSPLLE()
|
||||
: m_hDSPThread(), m_csDSPThreadActive(), m_bWii(false), m_bDSPThread(false),
|
||||
m_bIsRunning(false), m_cycle_count(0)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
static Common::Event dspEvent;
|
||||
static Common::Event ppcEvent;
|
||||
@@ -165,11 +166,9 @@ bool DSPLLE::Initialize(bool bWii, bool bDSPThread)
|
||||
return false;
|
||||
|
||||
// needs to be after DSPCore_Init for the dspjit ptr
|
||||
if (NetPlay::IsNetPlayRunning() || Movie::IsMovieActive() || Core::g_want_determinism ||
|
||||
!g_dsp_jit)
|
||||
{
|
||||
if (Core::g_want_determinism || !g_dsp_jit)
|
||||
bDSPThread = false;
|
||||
}
|
||||
|
||||
m_bWii = bWii;
|
||||
m_bDSPThread = bDSPThread;
|
||||
|
||||
@@ -290,27 +289,26 @@ void DSPLLE::DSP_Update(int cycles)
|
||||
return;
|
||||
// Sound stream update job has been handled by AudioDMA routine, which is more efficient
|
||||
/*
|
||||
// This gets called VERY OFTEN. The soundstream update might be expensive so only do it 200
|
||||
times per second or something.
|
||||
int cycles_between_ss_update;
|
||||
// This gets called VERY OFTEN. The soundstream update might be expensive so only do it 200
|
||||
times per second or something.
|
||||
int cycles_between_ss_update;
|
||||
|
||||
if (g_dspInitialize.bWii)
|
||||
cycles_between_ss_update = 121500000 / 200;
|
||||
else
|
||||
cycles_between_ss_update = 81000000 / 200;
|
||||
if (g_dspInitialize.bWii)
|
||||
cycles_between_ss_update = 121500000 / 200;
|
||||
else
|
||||
cycles_between_ss_update = 81000000 / 200;
|
||||
|
||||
m_cycle_count += cycles;
|
||||
if (m_cycle_count > cycles_between_ss_update)
|
||||
{
|
||||
while (m_cycle_count > cycles_between_ss_update)
|
||||
m_cycle_count -= cycles_between_ss_update;
|
||||
soundStream->Update();
|
||||
}
|
||||
m_cycle_count += cycles;
|
||||
if (m_cycle_count > cycles_between_ss_update)
|
||||
{
|
||||
while (m_cycle_count > cycles_between_ss_update)
|
||||
m_cycle_count -= cycles_between_ss_update;
|
||||
soundStream->Update();
|
||||
}
|
||||
*/
|
||||
if (m_bDSPThread)
|
||||
{
|
||||
if (requestDisableThread || NetPlay::IsNetPlayRunning() || Movie::IsMovieActive() ||
|
||||
Core::g_want_determinism)
|
||||
if (requestDisableThread || Core::g_want_determinism)
|
||||
{
|
||||
DSP_StopSoundStream();
|
||||
m_bDSPThread = false;
|
||||
|
@@ -13,17 +13,14 @@
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
class DSPLLE: public DSPEmulator
|
||||
class DSPLLE : public DSPEmulator
|
||||
{
|
||||
public:
|
||||
DSPLLE();
|
||||
|
||||
bool Initialize(bool bWii, bool bDSPThread) override;
|
||||
void Shutdown() override;
|
||||
bool IsLLE() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool IsLLE() override { return true; }
|
||||
void DoState(PointerWrap& p) override;
|
||||
void PauseAndLock(bool doLock, bool unpauseOnUnlock = true) override;
|
||||
|
||||
|
@@ -11,13 +11,11 @@
|
||||
|
||||
namespace DSPSymbols
|
||||
{
|
||||
class DSPSymbolDB: public SymbolDB
|
||||
class DSPSymbolDB : public SymbolDB
|
||||
{
|
||||
public:
|
||||
DSPSymbolDB()
|
||||
{}
|
||||
~DSPSymbolDB()
|
||||
{}
|
||||
DSPSymbolDB() {}
|
||||
~DSPSymbolDB() {}
|
||||
Symbol* GetSymbolFromAddr(u32 addr) override;
|
||||
};
|
||||
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_DI.h"
|
||||
#include "Core/Movie.h"
|
||||
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "DiscIO/VolumeCreator.h"
|
||||
|
||||
@@ -107,8 +108,7 @@ enum
|
||||
};
|
||||
|
||||
// DI Status Register
|
||||
union UDISR
|
||||
{
|
||||
union UDISR {
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -121,19 +121,12 @@ union UDISR
|
||||
u32 BRKINT : 1; // w 1: clear brkint
|
||||
u32 : 25;
|
||||
};
|
||||
UDISR()
|
||||
{
|
||||
Hex = 0;
|
||||
}
|
||||
UDISR(u32 _hex)
|
||||
{
|
||||
Hex = _hex;
|
||||
}
|
||||
UDISR() { Hex = 0; }
|
||||
UDISR(u32 _hex) { Hex = _hex; }
|
||||
};
|
||||
|
||||
// DI Cover Register
|
||||
union UDICVR
|
||||
{
|
||||
union UDICVR {
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -142,18 +135,11 @@ union UDICVR
|
||||
u32 CVRINT : 1; // r 1: Interrupt requested w 1: Interrupt clear
|
||||
u32 : 29;
|
||||
};
|
||||
UDICVR()
|
||||
{
|
||||
Hex = 0;
|
||||
}
|
||||
UDICVR(u32 _hex)
|
||||
{
|
||||
Hex = _hex;
|
||||
}
|
||||
UDICVR() { Hex = 0; }
|
||||
UDICVR(u32 _hex) { Hex = _hex; }
|
||||
};
|
||||
|
||||
union UDICMDBUF
|
||||
{
|
||||
union UDICMDBUF {
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -165,8 +151,7 @@ union UDICMDBUF
|
||||
};
|
||||
|
||||
// DI DMA Address Register
|
||||
union UDIMAR
|
||||
{
|
||||
union UDIMAR {
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -181,8 +166,7 @@ union UDIMAR
|
||||
};
|
||||
|
||||
// DI DMA Address Length Register
|
||||
union UDILENGTH
|
||||
{
|
||||
union UDILENGTH {
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -197,8 +181,7 @@ union UDILENGTH
|
||||
};
|
||||
|
||||
// DI DMA Control Register
|
||||
union UDICR
|
||||
{
|
||||
union UDICR {
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -209,8 +192,7 @@ union UDICR
|
||||
};
|
||||
};
|
||||
|
||||
union UDIIMMBUF
|
||||
{
|
||||
union UDIIMMBUF {
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -222,22 +204,15 @@ union UDIIMMBUF
|
||||
};
|
||||
|
||||
// DI Config Register
|
||||
union UDICFG
|
||||
{
|
||||
union UDICFG {
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
u32 CONFIG : 8;
|
||||
u32 : 24;
|
||||
};
|
||||
UDICFG()
|
||||
{
|
||||
Hex = 0;
|
||||
}
|
||||
UDICFG(u32 _hex)
|
||||
{
|
||||
Hex = _hex;
|
||||
}
|
||||
UDICFG() { Hex = 0; }
|
||||
UDICFG(u32 _hex) { Hex = _hex; }
|
||||
};
|
||||
|
||||
static std::unique_ptr<DiscIO::IVolume> s_inserted_volume;
|
||||
@@ -357,8 +332,7 @@ static u32 ProcessDTKSamples(short* tempPCM, u32 num_samples)
|
||||
s_audio_position += sizeof(tempADPCM);
|
||||
StreamADPCM::DecodeBlock(tempPCM + samples_processed * 2, tempADPCM);
|
||||
samples_processed += StreamADPCM::SAMPLES_PER_BLOCK;
|
||||
}
|
||||
while (samples_processed < num_samples);
|
||||
} while (samples_processed < num_samples);
|
||||
for (unsigned i = 0; i < samples_processed * 2; ++i)
|
||||
{
|
||||
// TODO: Fix the mixer so it can accept non-byte-swapped samples.
|
||||
@@ -502,10 +476,20 @@ static void InsertDiscCallback(u64 userdata, s64 cyclesLate)
|
||||
delete _FileName;
|
||||
}
|
||||
|
||||
void ChangeDisc(const std::string& newFileName)
|
||||
// Can only be called by the host thread
|
||||
void ChangeDiscAsHost(const std::string& newFileName)
|
||||
{
|
||||
// WARNING: Can only run on Host Thread
|
||||
bool was_unpaused = Core::PauseAndLock(true);
|
||||
|
||||
// The host thread is now temporarily the CPU thread
|
||||
ChangeDiscAsCPU(newFileName);
|
||||
|
||||
Core::PauseAndLock(false, was_unpaused);
|
||||
}
|
||||
|
||||
// Can only be called by the CPU thread
|
||||
void ChangeDiscAsCPU(const std::string& newFileName)
|
||||
{
|
||||
std::string* _FileName = new std::string(newFileName);
|
||||
CoreTiming::ScheduleEvent(0, s_eject_disc);
|
||||
CoreTiming::ScheduleEvent(500000000, s_insert_disc, (u64)_FileName);
|
||||
@@ -522,7 +506,6 @@ void ChangeDisc(const std::string& newFileName)
|
||||
}
|
||||
Movie::g_discChange = fileName.substr(sizeofpath);
|
||||
}
|
||||
Core::PauseAndLock(false, was_unpaused);
|
||||
}
|
||||
|
||||
void SetLidOpen(bool open)
|
||||
@@ -541,8 +524,7 @@ bool ChangePartition(u64 offset)
|
||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
{
|
||||
mmio->Register(base | DI_STATUS_REGISTER, MMIO::DirectRead<u32>(&s_DISR.Hex),
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
||||
UDISR tmpStatusReg(val);
|
||||
|
||||
s_DISR.DEINITMASK = tmpStatusReg.DEINITMASK;
|
||||
@@ -568,8 +550,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
}));
|
||||
|
||||
mmio->Register(base | DI_COVER_REGISTER, MMIO::DirectRead<u32>(&s_DICVR.Hex),
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
||||
UDICVR tmpCoverReg(val);
|
||||
|
||||
s_DICVR.CVRINTMASK = tmpCoverReg.CVRINTMASK;
|
||||
@@ -594,8 +575,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
mmio->Register(base | DI_DMA_LENGTH_REGISTER, MMIO::DirectRead<u32>(&s_DILENGTH.Hex),
|
||||
MMIO::DirectWrite<u32>(&s_DILENGTH.Hex, ~0x1F));
|
||||
mmio->Register(base | DI_DMA_CONTROL_REGISTER, MMIO::DirectRead<u32>(&s_DICR.Hex),
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
||||
s_DICR.Hex = val & 7;
|
||||
if (s_DICR.TSTART)
|
||||
{
|
||||
@@ -970,7 +950,7 @@ void ExecuteCommand(u32 command_0, u32 command_1, u32 command_2, u32 output_addr
|
||||
/*
|
||||
if (iDVDOffset == 0x84800000)
|
||||
{
|
||||
ERROR_LOG(DVDINTERFACE, "Firmware upload");
|
||||
ERROR_LOG(DVDINTERFACE, "Firmware upload");
|
||||
}
|
||||
else*/
|
||||
if ((offset < 0) || ((offset + len) > 0x40) || len > 0x40)
|
||||
@@ -1441,7 +1421,7 @@ s64 CalculateRawDiscReadTime(u64 offset, s64 length)
|
||||
// Note that the speed at a track (in bytes per second) is the same as
|
||||
// the radius of that track because of the length unit used.
|
||||
double speed;
|
||||
if (s_inserted_volume->GetVolumeType() == DiscIO::IVolume::WII_DISC)
|
||||
if (s_inserted_volume->GetVolumeType() == DiscIO::Platform::WII_DISC)
|
||||
{
|
||||
speed = std::sqrt(((average_offset - WII_DISC_LOCATION_1_OFFSET) / WII_BYTES_PER_AREA_UNIT +
|
||||
WII_DISC_AREA_UP_TO_LOCATION_1) /
|
||||
|
@@ -84,7 +84,7 @@ enum DICommand
|
||||
DVDLowAudioBufferConfig = 0xe4
|
||||
};
|
||||
|
||||
enum DIInterruptType: int
|
||||
enum DIInterruptType : int
|
||||
{
|
||||
INT_DEINT = 0,
|
||||
INT_TCINT = 1,
|
||||
@@ -108,7 +108,8 @@ bool VolumeIsValid();
|
||||
// Disc detection and swapping
|
||||
void SetDiscInside(bool _DiscInside);
|
||||
bool IsDiscInside();
|
||||
void ChangeDisc(const std::string& fileName); // [NOT THREADSAFE] Host only
|
||||
void ChangeDiscAsHost(const std::string& path); // Can only be called by the host thread
|
||||
void ChangeDiscAsCPU(const std::string& path); // Can only be called by the CPU thread
|
||||
|
||||
// DVD Access Functions
|
||||
bool ChangePartition(u64 offset);
|
||||
|
@@ -9,7 +9,7 @@
|
||||
class CEXIChannel;
|
||||
class IEXIDevice;
|
||||
class PointerWrap;
|
||||
enum TEXIDevices: int;
|
||||
enum TEXIDevices : int;
|
||||
namespace MMIO
|
||||
{
|
||||
class Mapping;
|
||||
|
@@ -44,8 +44,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
// Warning: the base is not aligned on a page boundary here. We can't use |
|
||||
// to select a register address, instead we need to use +.
|
||||
|
||||
mmio->Register(base + EXI_STATUS, MMIO::ComplexRead<u32>([this](u32)
|
||||
{
|
||||
mmio->Register(base + EXI_STATUS, MMIO::ComplexRead<u32>([this](u32) {
|
||||
// check if external device is present
|
||||
// pretty sure it is memcard only, not entirely sure
|
||||
if (m_ChannelId == 2)
|
||||
@@ -59,8 +58,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
|
||||
return m_Status.Hex;
|
||||
}),
|
||||
MMIO::ComplexWrite<u32>([this](u32, u32 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u32>([this](u32, u32 val) {
|
||||
UEXI_STATUS newStatus(val);
|
||||
|
||||
m_Status.EXIINTMASK = newStatus.EXIINTMASK;
|
||||
@@ -97,8 +95,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
mmio->Register(base + EXI_DMALENGTH, MMIO::DirectRead<u32>(&m_DMALength),
|
||||
MMIO::DirectWrite<u32>(&m_DMALength));
|
||||
mmio->Register(base + EXI_DMACONTROL, MMIO::DirectRead<u32>(&m_Control.Hex),
|
||||
MMIO::ComplexWrite<u32>([this](u32, u32 val)
|
||||
{
|
||||
MMIO::ComplexWrite<u32>([this](u32, u32 val) {
|
||||
m_Control.Hex = val;
|
||||
|
||||
if (m_Control.TSTART)
|
||||
|
@@ -9,7 +9,7 @@
|
||||
|
||||
class IEXIDevice;
|
||||
class PointerWrap;
|
||||
enum TEXIDevices: int;
|
||||
enum TEXIDevices : int;
|
||||
namespace MMIO
|
||||
{
|
||||
class Mapping;
|
||||
@@ -28,8 +28,7 @@ private:
|
||||
};
|
||||
|
||||
// EXI Status Register - "Channel Parameter Register"
|
||||
union UEXI_STATUS
|
||||
{
|
||||
union UEXI_STATUS {
|
||||
u32 Hex;
|
||||
// DO NOT obey the warning and give this struct a name. Things will fail.
|
||||
struct
|
||||
@@ -50,19 +49,12 @@ private:
|
||||
u32 ROMDIS : 1; // ROM Disable
|
||||
u32 : 18;
|
||||
};
|
||||
UEXI_STATUS()
|
||||
{
|
||||
Hex = 0;
|
||||
}
|
||||
UEXI_STATUS(u32 _hex)
|
||||
{
|
||||
Hex = _hex;
|
||||
}
|
||||
UEXI_STATUS() { Hex = 0; }
|
||||
UEXI_STATUS(u32 _hex) { Hex = _hex; }
|
||||
};
|
||||
|
||||
// EXI Control Register
|
||||
union UEXI_CONTROL
|
||||
{
|
||||
union UEXI_CONTROL {
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
@@ -116,8 +108,5 @@ public:
|
||||
void PauseAndLock(bool doLock, bool unpauseOnUnlock);
|
||||
|
||||
// This should only be used to transition interrupts from SP1 to Channel 2
|
||||
void SetEXIINT(bool exiint)
|
||||
{
|
||||
m_Status.EXIINT = !!exiint;
|
||||
}
|
||||
void SetEXIINT(bool exiint) { m_Status.EXIINT = !!exiint; }
|
||||
};
|
||||
|
@@ -67,17 +67,14 @@ void IEXIDevice::DMARead(u32 _uAddr, u32 _uSize)
|
||||
// Just a dummy that logs reads and writes
|
||||
// to be used for EXI devices we haven't emulated
|
||||
// DOES NOT FUNCTION AS "NO DEVICE INSERTED" -> Appears as unknown device
|
||||
class CEXIDummy: public IEXIDevice
|
||||
class CEXIDummy : public IEXIDevice
|
||||
{
|
||||
std::string m_strName;
|
||||
|
||||
void TransferByte(u8& _byte) override
|
||||
{}
|
||||
void TransferByte(u8& _byte) override {}
|
||||
public:
|
||||
CEXIDummy(const std::string& _strName): m_strName(_strName)
|
||||
{}
|
||||
virtual ~CEXIDummy()
|
||||
{}
|
||||
CEXIDummy(const std::string& _strName) : m_strName(_strName) {}
|
||||
virtual ~CEXIDummy() {}
|
||||
void ImmWrite(u32 data, u32 size) override
|
||||
{
|
||||
INFO_LOG(EXPANSIONINTERFACE, "EXI DUMMY %s ImmWrite: %08x", m_strName.c_str(), data);
|
||||
@@ -97,10 +94,7 @@ public:
|
||||
INFO_LOG(EXPANSIONINTERFACE, "EXI DUMMY %s DMARead: %08x bytes, from device to %08x",
|
||||
m_strName.c_str(), size, addr);
|
||||
}
|
||||
bool IsPresent() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool IsPresent() const override { return true; }
|
||||
};
|
||||
|
||||
// F A C T O R Y
|
||||
|
@@ -9,7 +9,7 @@
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
enum TEXIDevices: int
|
||||
enum TEXIDevices : int
|
||||
{
|
||||
EXIDEVICE_DUMMY,
|
||||
EXIDEVICE_MEMORYCARD,
|
||||
@@ -20,53 +20,38 @@ enum TEXIDevices: int
|
||||
EXIDEVICE_AM_BASEBOARD,
|
||||
EXIDEVICE_GECKO,
|
||||
EXIDEVICE_MEMORYCARDFOLDER, // Only used when creating a device by EXIDevice_Create
|
||||
// Converted to EXIDEVICE_MEMORYCARD internally
|
||||
EXIDEVICE_AGP,
|
||||
EXIDEVICE_NONE = (u8)-1
|
||||
// Converted to EXIDEVICE_MEMORYCARD internally
|
||||
EXIDEVICE_AGP,
|
||||
EXIDEVICE_NONE = (u8)-1
|
||||
};
|
||||
|
||||
class IEXIDevice
|
||||
{
|
||||
private:
|
||||
// Byte transfer function for this device
|
||||
virtual void TransferByte(u8&)
|
||||
{}
|
||||
virtual void TransferByte(u8&) {}
|
||||
public:
|
||||
// Immediate copy functions
|
||||
virtual void ImmWrite(u32 _uData, u32 _uSize);
|
||||
virtual u32 ImmRead(u32 _uSize);
|
||||
virtual void ImmReadWrite(u32& /*_uData*/, u32 /*_uSize*/)
|
||||
{}
|
||||
virtual void ImmReadWrite(u32& /*_uData*/, u32 /*_uSize*/) {}
|
||||
// DMA copy functions
|
||||
virtual void DMAWrite(u32 _uAddr, u32 _uSize);
|
||||
virtual void DMARead(u32 _uAddr, u32 _uSize);
|
||||
|
||||
virtual bool UseDelayedTransferCompletion() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool IsPresent() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual void SetCS(int)
|
||||
{}
|
||||
virtual void DoState(PointerWrap&)
|
||||
{}
|
||||
virtual void PauseAndLock(bool doLock, bool unpauseOnUnlock = true)
|
||||
{}
|
||||
virtual bool UseDelayedTransferCompletion() const { return false; }
|
||||
virtual bool IsPresent() const { return false; }
|
||||
virtual void SetCS(int) {}
|
||||
virtual void DoState(PointerWrap&) {}
|
||||
virtual void PauseAndLock(bool doLock, bool unpauseOnUnlock = true) {}
|
||||
virtual IEXIDevice* FindDevice(TEXIDevices device_type, int customIndex = -1)
|
||||
{
|
||||
return (device_type == m_deviceType) ? this : nullptr;
|
||||
}
|
||||
|
||||
// Is generating interrupt ?
|
||||
virtual bool IsInterruptSet()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual ~IEXIDevice()
|
||||
{}
|
||||
virtual bool IsInterruptSet() { return false; }
|
||||
virtual ~IEXIDevice() {}
|
||||
// for savestates. storing it here seemed cleaner than requiring each implementation to report its
|
||||
// type.
|
||||
// I know this class is set up like an interface, but no code requires it to be strictly such.
|
||||
|
@@ -7,7 +7,7 @@
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
CEXIAD16::CEXIAD16(): m_uPosition(0), m_uCommand(0)
|
||||
CEXIAD16::CEXIAD16() : m_uPosition(0), m_uCommand(0)
|
||||
{
|
||||
m_uAD16Register.U32 = 0x00;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
class CEXIAD16: public IEXIDevice
|
||||
class CEXIAD16 : public IEXIDevice
|
||||
{
|
||||
public:
|
||||
CEXIAD16();
|
||||
@@ -24,8 +24,7 @@ private:
|
||||
read = 0xa2
|
||||
};
|
||||
|
||||
union UAD16Reg
|
||||
{
|
||||
union UAD16Reg {
|
||||
u32 U32;
|
||||
u32 U8[4];
|
||||
};
|
||||
|
@@ -218,7 +218,7 @@ u32 CEXIAgp::ImmRead(u32 _uSize)
|
||||
}
|
||||
break;
|
||||
case 0xAE040000: // read 1 byte from 16 bit address
|
||||
// ToDo: Flash special handling
|
||||
// ToDo: Flash special handling
|
||||
if (m_eeprom_size == 0)
|
||||
RomVal1 = 0xFF;
|
||||
else
|
||||
@@ -228,7 +228,7 @@ u32 CEXIAgp::ImmRead(u32 _uSize)
|
||||
m_current_cmd = 0;
|
||||
break;
|
||||
case 0xAE0B0000: // read 1 bit from DMA with 6 or 14 bit address
|
||||
// Change to byte access instead of endian file access?
|
||||
// Change to byte access instead of endian file access?
|
||||
RomVal1 = EE_READ_FALSE;
|
||||
if ((m_eeprom_size != 0) && (m_eeprom_pos >= EE_IGNORE_BITS) &&
|
||||
((((u64*)m_eeprom.data())[(m_eeprom_cmd >> 1) & m_eeprom_add_mask]) >>
|
||||
@@ -271,7 +271,7 @@ void CEXIAgp::ImmWrite(u32 _uData, u32 _uSize)
|
||||
{
|
||||
case 0xAE020000: // set up 24 bit address for read 2 bytes
|
||||
case 0xAE030000: // set up 24 bit address for read (0x10000 byte group)
|
||||
// 25 bit address shifted one bit right = 24 bits
|
||||
// 25 bit address shifted one bit right = 24 bits
|
||||
m_rw_offset = ((_uData & 0xFFFFFF00) >> (8 - 1));
|
||||
m_return_pos = 0;
|
||||
HashCmd = (_uData & 0xFF000000) >> 24;
|
||||
@@ -282,7 +282,7 @@ void CEXIAgp::ImmWrite(u32 _uData, u32 _uSize)
|
||||
CRC8(&HashCmd, 1);
|
||||
break;
|
||||
case 0xAE040000: // set up 16 bit address for read 1 byte
|
||||
// ToDo: Flash special handling
|
||||
// ToDo: Flash special handling
|
||||
m_eeprom_pos = ((_uData & 0xFFFF0000) >> 0x10) & m_eeprom_mask;
|
||||
HashCmd = (_uData & 0xFF000000) >> 24;
|
||||
CRC8(&HashCmd, 1);
|
||||
@@ -290,7 +290,7 @@ void CEXIAgp::ImmWrite(u32 _uData, u32 _uSize)
|
||||
CRC8(&HashCmd, 1);
|
||||
break;
|
||||
case 0xAE070000: // write 1 byte from 16 bit address
|
||||
// ToDo: Flash special handling
|
||||
// ToDo: Flash special handling
|
||||
m_eeprom_pos = ((_uData & 0xFFFF0000) >> 0x10) & m_eeprom_mask;
|
||||
if (m_eeprom_size != 0)
|
||||
((m_eeprom.data()))[(m_eeprom_pos)] = (_uData & 0x0000FF00) >> 0x8;
|
||||
@@ -341,7 +341,7 @@ void CEXIAgp::ImmWrite(u32 _uData, u32 _uSize)
|
||||
case 0xAE010000:
|
||||
case 0xAE090000: // start DMA
|
||||
m_eeprom_write_status = false; // ToDo: Verify with hardware which commands disable EEPROM CS
|
||||
// Fall-through intentional
|
||||
// Fall-through intentional
|
||||
case 0xAE0A0000: // end DMA
|
||||
m_eeprom_pos = 0;
|
||||
// Fall-through intentional
|
||||
|
@@ -11,15 +11,12 @@
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
class CEXIAgp: public IEXIDevice
|
||||
class CEXIAgp : public IEXIDevice
|
||||
{
|
||||
public:
|
||||
CEXIAgp(const int index);
|
||||
virtual ~CEXIAgp() override;
|
||||
bool IsPresent() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool IsPresent() const override { return true; }
|
||||
void ImmWrite(u32 _uData, u32 _uSize) override;
|
||||
u32 ImmRead(u32 _uSize) override;
|
||||
void DoState(PointerWrap& p) override;
|
||||
|
@@ -8,8 +8,9 @@
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Core/HW/EXI_DeviceAMBaseboard.h"
|
||||
|
||||
CEXIAMBaseboard::CEXIAMBaseboard(): m_position(0), m_have_irq(false)
|
||||
{}
|
||||
CEXIAMBaseboard::CEXIAMBaseboard() : m_position(0), m_have_irq(false)
|
||||
{
|
||||
}
|
||||
|
||||
void CEXIAMBaseboard::SetCS(int cs)
|
||||
{
|
||||
@@ -27,25 +28,25 @@ void CEXIAMBaseboard::TransferByte(u8& _byte)
|
||||
{
|
||||
/*
|
||||
ID:
|
||||
00 00 xx xx xx xx
|
||||
xx xx 06 04 10 00
|
||||
00 00 xx xx xx xx
|
||||
xx xx 06 04 10 00
|
||||
CMD:
|
||||
01 00 00 b3 xx
|
||||
xx xx xx xx 04
|
||||
01 00 00 b3 xx
|
||||
xx xx xx xx 04
|
||||
exi_lanctl_write:
|
||||
ff 02 01 63 xx
|
||||
xx xx xx xx 04
|
||||
ff 02 01 63 xx
|
||||
xx xx xx xx 04
|
||||
exi_imr_read:
|
||||
86 00 00 f5 xx xx xx
|
||||
xx xx xx xx 04 rr rr
|
||||
86 00 00 f5 xx xx xx
|
||||
xx xx xx xx 04 rr rr
|
||||
exi_imr_write:
|
||||
87 80 5c 17 xx
|
||||
xx xx xx xx 04
|
||||
87 80 5c 17 xx
|
||||
xx xx xx xx 04
|
||||
|
||||
exi_isr_read:
|
||||
82 .. .. .. xx xx xx
|
||||
xx xx xx xx 04 rr rr
|
||||
3 byte command, 1 byte checksum
|
||||
82 .. .. .. xx xx xx
|
||||
xx xx xx xx 04 rr rr
|
||||
3 byte command, 1 byte checksum
|
||||
*/
|
||||
DEBUG_LOG(SP1, "AM-BB > %02x", _byte);
|
||||
if (m_position < 4)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
class CEXIAMBaseboard: public IEXIDevice
|
||||
class CEXIAMBaseboard : public IEXIDevice
|
||||
{
|
||||
public:
|
||||
CEXIAMBaseboard();
|
||||
|
@@ -30,7 +30,7 @@ CEXIETHERNET::CEXIETHERNET()
|
||||
// Parse MAC address from config, and generate a new one if it doesn't
|
||||
// exist or can't be parsed.
|
||||
std::string& mac_addr_setting = SConfig::GetInstance().m_bba_mac;
|
||||
u8 mac_addr[MAC_ADDRESS_SIZE] = {0};
|
||||
u8 mac_addr[MAC_ADDRESS_SIZE] = { 0 };
|
||||
|
||||
if (!StringToMacAddress(mac_addr_setting, mac_addr))
|
||||
{
|
||||
@@ -436,7 +436,7 @@ inline u8 CEXIETHERNET::HashIndex(u8* dest_eth_addr)
|
||||
|
||||
inline bool CEXIETHERNET::RecvMACFilter()
|
||||
{
|
||||
static u8 const broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
static u8 const broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
// Accept all destination addrs?
|
||||
if (mBbaMem[BBA_NCRB] & NCRB_PR)
|
||||
@@ -522,13 +522,13 @@ bool CEXIETHERNET::RecvHandlePacket()
|
||||
/*
|
||||
halt copy
|
||||
if (cur_packet_size >= PAGE_SIZE)
|
||||
desc.status |= FO | BF
|
||||
desc.status |= FO | BF
|
||||
if (RBFIM)
|
||||
raise RBFI
|
||||
raise RBFI
|
||||
if (AUTORCVR)
|
||||
discard bad packet
|
||||
discard bad packet
|
||||
else
|
||||
inc MPC instead of receiving packets
|
||||
inc MPC instead of receiving packets
|
||||
*/
|
||||
status |= DESC_FO | DESC_BF;
|
||||
mBbaMem[BBA_IR] |= mBbaMem[BBA_IMR] & INT_RBF;
|
||||
|
@@ -194,7 +194,7 @@ enum RecvStatus
|
||||
|
||||
#define BBA_RECV_SIZE 0x800
|
||||
|
||||
class CEXIETHERNET: public IEXIDevice
|
||||
class CEXIETHERNET : public IEXIDevice
|
||||
{
|
||||
public:
|
||||
CEXIETHERNET();
|
||||
@@ -291,10 +291,7 @@ public:
|
||||
return ((u16)mBbaMem[index + 1] << 8) | mBbaMem[index];
|
||||
}
|
||||
|
||||
inline u8* ptr_from_page_ptr(int const index) const
|
||||
{
|
||||
return &mBbaMem[page_ptr(index) << 8];
|
||||
}
|
||||
inline u8* ptr_from_page_ptr(int const index) const { return &mBbaMem[page_ptr(index) << 8]; }
|
||||
bool IsMXCommand(u32 const data);
|
||||
bool IsWriteCommand(u32 const data);
|
||||
const char* GetRegisterName() const;
|
||||
|
@@ -25,7 +25,7 @@ std::atomic<bool> GeckoSockServer::server_running;
|
||||
std::mutex GeckoSockServer::connection_lock;
|
||||
std::queue<std::unique_ptr<sf::TcpSocket>> GeckoSockServer::waiting_socks;
|
||||
|
||||
GeckoSockServer::GeckoSockServer(): client_running(false)
|
||||
GeckoSockServer::GeckoSockServer() : client_running(false)
|
||||
{
|
||||
if (!connectionThread.joinable())
|
||||
connectionThread = std::thread(GeckoConnectionWaiter);
|
||||
|
@@ -45,15 +45,11 @@ private:
|
||||
static std::queue<std::unique_ptr<sf::TcpSocket>> waiting_socks;
|
||||
};
|
||||
|
||||
class CEXIGecko: public IEXIDevice, private GeckoSockServer
|
||||
class CEXIGecko : public IEXIDevice, private GeckoSockServer
|
||||
{
|
||||
public:
|
||||
CEXIGecko()
|
||||
{}
|
||||
bool IsPresent() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
CEXIGecko() {}
|
||||
bool IsPresent() const override { return true; }
|
||||
void ImmReadWrite(u32& _uData, u32 _uSize) override;
|
||||
|
||||
private:
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
@@ -12,6 +13,7 @@
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Common/Timer.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/HW/EXI_DeviceIPL.h"
|
||||
#include "Core/HW/Sram.h"
|
||||
@@ -83,7 +85,7 @@ void CEXIIPL::Descrambler(u8* data, u32 size)
|
||||
}
|
||||
}
|
||||
|
||||
CEXIIPL::CEXIIPL(): m_uPosition(0), m_uAddress(0), m_uRWOffset(0), m_FontsLoaded(false)
|
||||
CEXIIPL::CEXIIPL() : m_uPosition(0), m_uAddress(0), m_uRWOffset(0), m_FontsLoaded(false)
|
||||
{
|
||||
// Determine region
|
||||
m_bNTSC = SConfig::GetInstance().bNTSC;
|
||||
@@ -421,6 +423,7 @@ u32 CEXIIPL::GetGCTime()
|
||||
}
|
||||
else
|
||||
{
|
||||
_assert_(!Core::g_want_determinism);
|
||||
ltime = Common::Timer::GetLocalTimeSinceJan1970();
|
||||
}
|
||||
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
class CEXIIPL: public IEXIDevice
|
||||
class CEXIIPL : public IEXIDevice
|
||||
{
|
||||
public:
|
||||
CEXIIPL();
|
||||
@@ -67,14 +67,8 @@ private:
|
||||
void UpdateRTC();
|
||||
|
||||
void TransferByte(u8& _uByte) override;
|
||||
bool IsWriteCommand() const
|
||||
{
|
||||
return !!(m_uAddress & (1 << 31));
|
||||
}
|
||||
u32 CommandRegion() const
|
||||
{
|
||||
return (m_uAddress & ~(1 << 31)) >> 8;
|
||||
}
|
||||
bool IsWriteCommand() const { return !!(m_uAddress & (1 << 31)); }
|
||||
u32 CommandRegion() const { return (m_uAddress & ~(1 << 31)) >> 8; }
|
||||
void LoadFileToIPL(const std::string& filename, u32 offset);
|
||||
void LoadFontFile(const std::string& filename, u32 offset);
|
||||
std::string FindIPLDump(const std::string& path_prefix);
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "Core/HW/Sram.h"
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DiscIO/NANDContentLoader.h"
|
||||
|
||||
#define MC_STATUS_BUSY 0x80
|
||||
@@ -60,29 +61,23 @@ void CEXIMemoryCard::EventCompleteFindInstance(u64 userdata,
|
||||
|
||||
void CEXIMemoryCard::CmdDoneCallback(u64 userdata, s64 cyclesLate)
|
||||
{
|
||||
EventCompleteFindInstance(userdata, [](CEXIMemoryCard* instance)
|
||||
{
|
||||
instance->CmdDone();
|
||||
});
|
||||
EventCompleteFindInstance(userdata, [](CEXIMemoryCard* instance) { instance->CmdDone(); });
|
||||
}
|
||||
|
||||
void CEXIMemoryCard::TransferCompleteCallback(u64 userdata, s64 cyclesLate)
|
||||
{
|
||||
EventCompleteFindInstance(userdata,
|
||||
[](CEXIMemoryCard* instance)
|
||||
{
|
||||
instance->TransferComplete();
|
||||
});
|
||||
[](CEXIMemoryCard* instance) { instance->TransferComplete(); });
|
||||
}
|
||||
|
||||
CEXIMemoryCard::CEXIMemoryCard(const int index, bool gciFolder): card_index(index)
|
||||
CEXIMemoryCard::CEXIMemoryCard(const int index, bool gciFolder) : card_index(index)
|
||||
{
|
||||
struct
|
||||
{
|
||||
const char* done;
|
||||
const char* transfer_complete;
|
||||
} const event_names[] = {
|
||||
{"memcardDoneA", "memcardTransferCompleteA"}, {"memcardDoneB", "memcardTransferCompleteB"},
|
||||
{"memcardDoneA", "memcardTransferCompleteA"}, {"memcardDoneB", "memcardTransferCompleteB"},
|
||||
};
|
||||
|
||||
if ((size_t)index >= ArraySize(event_names))
|
||||
@@ -134,14 +129,14 @@ CEXIMemoryCard::CEXIMemoryCard(const int index, bool gciFolder): card_index(inde
|
||||
}
|
||||
|
||||
memory_card_size = memorycard->GetCardId() * SIZE_TO_Mb;
|
||||
u8 header[20] = {0};
|
||||
u8 header[20] = { 0 };
|
||||
memorycard->Read(0, static_cast<s32>(ArraySize(header)), header);
|
||||
SetCardFlashID(header, card_index);
|
||||
}
|
||||
|
||||
void CEXIMemoryCard::SetupGciFolder(u16 sizeMb)
|
||||
{
|
||||
DiscIO::IVolume::ECountry country_code = DiscIO::IVolume::COUNTRY_UNKNOWN;
|
||||
DiscIO::Country country_code = DiscIO::Country::COUNTRY_UNKNOWN;
|
||||
auto strUniqueID = SConfig::GetInstance().m_strUniqueID;
|
||||
|
||||
u32 CurrentGameId = 0;
|
||||
@@ -164,14 +159,14 @@ void CEXIMemoryCard::SetupGciFolder(u16 sizeMb)
|
||||
std::string strDirectoryName = File::GetUserPath(D_GCUSER_IDX);
|
||||
switch (country_code)
|
||||
{
|
||||
case DiscIO::IVolume::COUNTRY_JAPAN:
|
||||
case DiscIO::Country::COUNTRY_JAPAN:
|
||||
ascii = false;
|
||||
strDirectoryName += JAP_DIR DIR_SEP;
|
||||
break;
|
||||
case DiscIO::IVolume::COUNTRY_USA:
|
||||
case DiscIO::Country::COUNTRY_USA:
|
||||
strDirectoryName += USA_DIR DIR_SEP;
|
||||
break;
|
||||
case DiscIO::IVolume::COUNTRY_UNKNOWN:
|
||||
case DiscIO::Country::COUNTRY_UNKNOWN:
|
||||
{
|
||||
// The current game's region is not passed down to the EXI device level.
|
||||
// Usually, we can retrieve the region from SConfig::GetInstance().m_strUniqueId.
|
||||
@@ -191,20 +186,20 @@ void CEXIMemoryCard::SetupGciFolder(u16 sizeMb)
|
||||
std::string region = memcardFilename.substr(memcardFilename.size() - 7, 3);
|
||||
if (region == JAP_DIR)
|
||||
{
|
||||
country_code = DiscIO::IVolume::COUNTRY_JAPAN;
|
||||
country_code = DiscIO::Country::COUNTRY_JAPAN;
|
||||
ascii = false;
|
||||
strDirectoryName += JAP_DIR DIR_SEP;
|
||||
break;
|
||||
}
|
||||
else if (region == USA_DIR)
|
||||
{
|
||||
country_code = DiscIO::IVolume::COUNTRY_USA;
|
||||
country_code = DiscIO::Country::COUNTRY_USA;
|
||||
strDirectoryName += USA_DIR DIR_SEP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
country_code = DiscIO::IVolume::COUNTRY_EUROPE;
|
||||
country_code = DiscIO::Country::COUNTRY_EUROPE;
|
||||
strDirectoryName += EUR_DIR DIR_SEP;
|
||||
}
|
||||
strDirectoryName += StringFromFormat("Card %c", 'A' + card_index);
|
||||
|
@@ -12,7 +12,7 @@
|
||||
class MemoryCardBase;
|
||||
class PointerWrap;
|
||||
|
||||
class CEXIMemoryCard: public IEXIDevice
|
||||
class CEXIMemoryCard : public IEXIDevice
|
||||
{
|
||||
public:
|
||||
CEXIMemoryCard(const int index, bool gciFolder);
|
||||
|
@@ -137,9 +137,9 @@ void CEXIMic::StreamReadOne()
|
||||
// cmdGetBuffer, which is when we actually read data from a buffer filled
|
||||
// in the background by Pa_Callback.
|
||||
|
||||
u8 const CEXIMic::exi_id[] = {0, 0x0a, 0, 0, 0};
|
||||
u8 const CEXIMic::exi_id[] = { 0, 0x0a, 0, 0, 0 };
|
||||
|
||||
CEXIMic::CEXIMic(int index): slot(index)
|
||||
CEXIMic::CEXIMic(int index) : slot(index)
|
||||
{
|
||||
m_position = 0;
|
||||
command = 0;
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
#if HAVE_PORTAUDIO
|
||||
|
||||
class CEXIMic: public IEXIDevice
|
||||
class CEXIMic : public IEXIDevice
|
||||
{
|
||||
public:
|
||||
CEXIMic(const int index);
|
||||
@@ -38,8 +38,7 @@ private:
|
||||
|
||||
u32 m_position;
|
||||
int command;
|
||||
union UStatus
|
||||
{
|
||||
union UStatus {
|
||||
u16 U16;
|
||||
u8 U8[2];
|
||||
struct
|
||||
@@ -100,11 +99,10 @@ protected:
|
||||
|
||||
#else // HAVE_PORTAUDIO
|
||||
|
||||
class CEXIMic: public IEXIDevice
|
||||
class CEXIMic : public IEXIDevice
|
||||
{
|
||||
public:
|
||||
CEXIMic(const int)
|
||||
{}
|
||||
CEXIMic(const int) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -6,45 +6,45 @@
|
||||
#include "Common/Common.h"
|
||||
#include "InputCommon/KeyboardStatus.h"
|
||||
|
||||
static const u16 keys0_bitmasks[] = {KEYMASK_HOME, KEYMASK_END, KEYMASK_PGUP, KEYMASK_PGDN,
|
||||
KEYMASK_SCROLLLOCK, KEYMASK_A, KEYMASK_B, KEYMASK_C,
|
||||
KEYMASK_D, KEYMASK_E, KEYMASK_F, KEYMASK_G,
|
||||
KEYMASK_H, KEYMASK_I, KEYMASK_J, KEYMASK_K};
|
||||
static const u16 keys0_bitmasks[] = { KEYMASK_HOME, KEYMASK_END, KEYMASK_PGUP, KEYMASK_PGDN,
|
||||
KEYMASK_SCROLLLOCK, KEYMASK_A, KEYMASK_B, KEYMASK_C,
|
||||
KEYMASK_D, KEYMASK_E, KEYMASK_F, KEYMASK_G,
|
||||
KEYMASK_H, KEYMASK_I, KEYMASK_J, KEYMASK_K };
|
||||
static const u16 keys1_bitmasks[] = {
|
||||
KEYMASK_L, KEYMASK_M, KEYMASK_N, KEYMASK_O, KEYMASK_P, KEYMASK_Q, KEYMASK_R, KEYMASK_S,
|
||||
KEYMASK_T, KEYMASK_U, KEYMASK_V, KEYMASK_W, KEYMASK_X, KEYMASK_Y, KEYMASK_Z, KEYMASK_1};
|
||||
KEYMASK_L, KEYMASK_M, KEYMASK_N, KEYMASK_O, KEYMASK_P, KEYMASK_Q, KEYMASK_R, KEYMASK_S,
|
||||
KEYMASK_T, KEYMASK_U, KEYMASK_V, KEYMASK_W, KEYMASK_X, KEYMASK_Y, KEYMASK_Z, KEYMASK_1 };
|
||||
static const u16 keys2_bitmasks[] = {
|
||||
KEYMASK_2, KEYMASK_3, KEYMASK_4, KEYMASK_5,
|
||||
KEYMASK_6, KEYMASK_7, KEYMASK_8, KEYMASK_9,
|
||||
KEYMASK_0, KEYMASK_MINUS, KEYMASK_PLUS, KEYMASK_PRINTSCR,
|
||||
KEYMASK_BRACE_OPEN, KEYMASK_BRACE_CLOSE, KEYMASK_COLON, KEYMASK_QUOTE};
|
||||
KEYMASK_2, KEYMASK_3, KEYMASK_4, KEYMASK_5,
|
||||
KEYMASK_6, KEYMASK_7, KEYMASK_8, KEYMASK_9,
|
||||
KEYMASK_0, KEYMASK_MINUS, KEYMASK_PLUS, KEYMASK_PRINTSCR,
|
||||
KEYMASK_BRACE_OPEN, KEYMASK_BRACE_CLOSE, KEYMASK_COLON, KEYMASK_QUOTE };
|
||||
static const u16 keys3_bitmasks[] = {
|
||||
KEYMASK_HASH, KEYMASK_COMMA, KEYMASK_PERIOD, KEYMASK_QUESTIONMARK, KEYMASK_INTERNATIONAL1,
|
||||
KEYMASK_F1, KEYMASK_F2, KEYMASK_F3, KEYMASK_F4, KEYMASK_F5,
|
||||
KEYMASK_F6, KEYMASK_F7, KEYMASK_F8, KEYMASK_F9, KEYMASK_F10,
|
||||
KEYMASK_F11};
|
||||
KEYMASK_HASH, KEYMASK_COMMA, KEYMASK_PERIOD, KEYMASK_QUESTIONMARK, KEYMASK_INTERNATIONAL1,
|
||||
KEYMASK_F1, KEYMASK_F2, KEYMASK_F3, KEYMASK_F4, KEYMASK_F5,
|
||||
KEYMASK_F6, KEYMASK_F7, KEYMASK_F8, KEYMASK_F9, KEYMASK_F10,
|
||||
KEYMASK_F11 };
|
||||
static const u16 keys4_bitmasks[] = {
|
||||
KEYMASK_F12, KEYMASK_ESC, KEYMASK_INSERT, KEYMASK_DELETE,
|
||||
KEYMASK_TILDE, KEYMASK_BACKSPACE, KEYMASK_TAB, KEYMASK_CAPSLOCK,
|
||||
KEYMASK_LEFTSHIFT, KEYMASK_RIGHTSHIFT, KEYMASK_LEFTCONTROL, KEYMASK_RIGHTALT,
|
||||
KEYMASK_LEFTWINDOWS, KEYMASK_SPACE, KEYMASK_RIGHTWINDOWS, KEYMASK_MENU};
|
||||
static const u16 keys5_bitmasks[] = {KEYMASK_LEFTARROW, KEYMASK_DOWNARROW, KEYMASK_UPARROW,
|
||||
KEYMASK_RIGHTARROW, KEYMASK_ENTER};
|
||||
KEYMASK_F12, KEYMASK_ESC, KEYMASK_INSERT, KEYMASK_DELETE,
|
||||
KEYMASK_TILDE, KEYMASK_BACKSPACE, KEYMASK_TAB, KEYMASK_CAPSLOCK,
|
||||
KEYMASK_LEFTSHIFT, KEYMASK_RIGHTSHIFT, KEYMASK_LEFTCONTROL, KEYMASK_RIGHTALT,
|
||||
KEYMASK_LEFTWINDOWS, KEYMASK_SPACE, KEYMASK_RIGHTWINDOWS, KEYMASK_MENU };
|
||||
static const u16 keys5_bitmasks[] = { KEYMASK_LEFTARROW, KEYMASK_DOWNARROW, KEYMASK_UPARROW,
|
||||
KEYMASK_RIGHTARROW, KEYMASK_ENTER };
|
||||
|
||||
static const char* const named_keys0[] = {"HOME", "END", "PGUP", "PGDN", "SCR LK", "A", "B", "C",
|
||||
"D", "E", "F", "G", "H", "I", "J", "K"};
|
||||
static const char* const named_keys1[] = {"L", "M", "N", "O", "P", "Q", "R", "S",
|
||||
"T", "U", "V", "W", "X", "Y", "Z", "1"};
|
||||
static const char* const named_keys2[] = {"2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"0", "-", "`", "PRT SC", "'", "[", "EQUALS", "*"};
|
||||
static const char* const named_keys3[] = {"]", ",", ".", "/", "\\", "F1", "F2", "F3",
|
||||
"F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11"};
|
||||
static const char* const named_keys0[] = { "HOME", "END", "PGUP", "PGDN", "SCR LK", "A", "B", "C",
|
||||
"D", "E", "F", "G", "H", "I", "J", "K" };
|
||||
static const char* const named_keys1[] = { "L", "M", "N", "O", "P", "Q", "R", "S",
|
||||
"T", "U", "V", "W", "X", "Y", "Z", "1" };
|
||||
static const char* const named_keys2[] = { "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"0", "-", "`", "PRT SC", "'", "[", "EQUALS", "*" };
|
||||
static const char* const named_keys3[] = { "]", ",", ".", "/", "\\", "F1", "F2", "F3",
|
||||
"F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11" };
|
||||
static const char* const named_keys4[] = {
|
||||
"F12", "ESC", "INSERT", "DELETE", ";", "BACKSPACE", "TAB", "CAPS LOCK",
|
||||
"L SHIFT", "R SHIFT", "L CTRL", "R ALT", "L WIN", "SPACE", "R WIN", "MENU"};
|
||||
static const char* const named_keys5[] = {"LEFT", "DOWN", "UP", "RIGHT", "ENTER"};
|
||||
"F12", "ESC", "INSERT", "DELETE", ";", "BACKSPACE", "TAB", "CAPS LOCK",
|
||||
"L SHIFT", "R SHIFT", "L CTRL", "R ALT", "L WIN", "SPACE", "R WIN", "MENU" };
|
||||
static const char* const named_keys5[] = { "LEFT", "DOWN", "UP", "RIGHT", "ENTER" };
|
||||
|
||||
GCKeyboard::GCKeyboard(const unsigned int index): m_index(index)
|
||||
GCKeyboard::GCKeyboard(const unsigned int index) : m_index(index)
|
||||
{
|
||||
// buttons
|
||||
groups.emplace_back(m_keys0x = new Buttons(_trans("Keys")));
|
||||
@@ -73,9 +73,10 @@ GCKeyboard::GCKeyboard(const unsigned int index): m_index(index)
|
||||
|
||||
// options
|
||||
groups.emplace_back(m_options = new ControlGroup(_trans("Options")));
|
||||
m_options->settings.emplace_back(
|
||||
new ControlGroup::BackgroundInputSetting(_trans("Background Input")));
|
||||
m_options->settings.emplace_back(new ControlGroup::IterateUI(_trans("Iterative Input")));
|
||||
m_options->boolean_settings.emplace_back(
|
||||
std::make_unique<ControlGroup::BackgroundInputSetting>(_trans("Background Input")));
|
||||
m_options->boolean_settings.emplace_back(std::make_unique<ControlGroup::BooleanSetting>(
|
||||
_trans("Iterative Input"), false, ControlGroup::SettingType::VIRTUAL));
|
||||
}
|
||||
|
||||
std::string GCKeyboard::GetName() const
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user