project-slippi/Ishiiruka/pull/247

removed some unnecessary logic

we used to overwrite where the codehandler looks for the gecko codes... but we don't run the codehandler anymore past initializing the bootloader. Plus given the codehandler was different than in Ishii, this overwrite location was totally wrong anyway.

Co-authored-by: Jas Laferriere <Fizzi36@gmail.com>
This commit is contained in:
Nikhil Narayana 2021-12-03 17:22:47 -08:00
commit d59553ccba
12 changed files with 254 additions and 60 deletions

BIN
Data/Sys/bootloader.gct Normal file

Binary file not shown.

View file

@ -128,6 +128,7 @@
#define WII_SETTING "setting.txt" #define WII_SETTING "setting.txt"
#define GECKO_CODE_HANDLER "codehandler.bin" #define GECKO_CODE_HANDLER "codehandler.bin"
#define GCT_BOOTLOADER "bootloader.gct"
// Subdirs in Sys // Subdirs in Sys
#define GC_SYS_DIR "GC" #define GC_SYS_DIR "GC"

View file

@ -41,6 +41,7 @@ namespace fs = std::filesystem;
#include "Core/Config/SYSCONFSettings.h" #include "Core/Config/SYSCONFSettings.h"
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/FifoPlayer/FifoPlayer.h" #include "Core/FifoPlayer/FifoPlayer.h"
#include "Core/GeckoCode.h"
#include "Core/HLE/HLE.h" #include "Core/HLE/HLE.h"
#include "Core/HW/DVD/DVDInterface.h" #include "Core/HW/DVD/DVDInterface.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h" #include "Core/HW/EXI/EXI_DeviceIPL.h"
@ -537,6 +538,7 @@ bool CBoot::BootUp(std::unique_ptr<BootParameters> boot)
PatchEngine::LoadPatches(); PatchEngine::LoadPatches();
HLE::PatchFixedFunctions(); HLE::PatchFixedFunctions();
Gecko::RunCodeHandler();
return true; return true;
} }

View file

@ -51,6 +51,7 @@
#include "VideoCommon/HiresTextures.h" #include "VideoCommon/HiresTextures.h"
#include "DiscIO/Enums.h" #include "DiscIO/Enums.h"
#include "DiscIO/Filesystem.h"
#include "DiscIO/Volume.h" #include "DiscIO/Volume.h"
#include "DiscIO/VolumeWad.h" #include "DiscIO/VolumeWad.h"
@ -959,7 +960,32 @@ bool SConfig::SetPathsAndGameMetadata(const BootParameters& boot)
const std::string region_dir = GetDirectoryForRegion(ToGameCubeRegion(m_region)); const std::string region_dir = GetDirectoryForRegion(ToGameCubeRegion(m_region));
m_strSRAM = File::GetUserPath(F_GCSRAM_IDX); m_strSRAM = File::GetUserPath(F_GCSRAM_IDX);
m_strBootROM = GetBootROMPath(region_dir); m_strBootROM = GetBootROMPath(region_dir);
m_strIsoPath = (boot.parameters.index() == 0) ? std::get<BootParameters::Disc>(boot.parameters).path : ""; m_strIsoPath =
(boot.parameters.index() == 0) ? std::get<BootParameters::Disc>(boot.parameters).path : "";
std::shared_ptr<DiscIO::Volume> volume = DiscIO::CreateVolume(m_strIsoPath);
if (m_game_id == "GALE01" || m_game_id == "GALJ01")
{
m_melee_version = Melee::Version::NTSC;
if (volume->GetLongNames()[DiscIO::Language::English].find("20XX") != std::string::npos)
m_melee_version = Melee::Version::TwentyXX;
else
{
// check for m-ex based build
if (volume->FileExists("MxDt.dat"))
{
m_melee_version = Melee::Version::MEX;
}
}
}
else if (m_game_id == "GTME01")
{
m_melee_version = Melee::Version::UPTM;
}
INFO_LOG_FMT(BOOT, "Melee Version: {}", m_melee_version);
return true; return true;
} }

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <future>
#include <limits> #include <limits>
#include <optional> #include <optional>
#include <set> #include <set>
@ -45,6 +46,18 @@ namespace SerialInterface
enum SIDevices : int; enum SIDevices : int;
} // namespace SerialInterface } // namespace SerialInterface
namespace Melee
{
enum class Version
{
NTSC,
TwentyXX,
UPTM,
MEX,
OTHER,
};
}
struct BootParameters; struct BootParameters;
// DSP Backend Types // DSP Backend Types
@ -67,6 +80,8 @@ enum class GPUDeterminismMode
struct SConfig struct SConfig
{ {
// Melee Version
Melee::Version m_melee_version;
// Wii Devices // Wii Devices
bool m_WiiSDCard; bool m_WiiSDCard;
bool m_WiiKeyboard; bool m_WiiKeyboard;

View file

@ -19,6 +19,8 @@
#include "Core/PowerPC/MMU.h" #include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "VideoCommon/OnScreenDisplay.h"
namespace Gecko namespace Gecko
{ {
static constexpr u32 CODE_SIZE = 8; static constexpr u32 CODE_SIZE = 8;
@ -68,6 +70,8 @@ void SetActiveCodes(const std::vector<GeckoCode>& gcodes)
{ {
std::lock_guard<std::mutex> lk(s_active_codes_lock); std::lock_guard<std::mutex> lk(s_active_codes_lock);
DEBUG_LOG_FMT(ACTIONREPLAY, "Setting up active codes...");
s_active_codes.clear(); s_active_codes.clear();
if (SConfig::GetInstance().bEnableCheats) if (SConfig::GetInstance().bEnableCheats)
{ {
@ -153,32 +157,39 @@ static Installation InstallCodeHandlerLocked()
} }
} }
u32 codelist_base_address; u32 codelist_base_address = INSTALLER_BASE_ADDRESS + static_cast<u32>(data.length()) - CODE_SIZE;
u32 codelist_end_address; u32 codelist_end_address = INSTALLER_END_ADDRESS;
// Let the Gecko codehandler use free space from Melee's tournament mode region
if (SConfig::GetInstance().GetGameID() == "GALE01") // Write a magic value to 'gameid' (codehandleronly does not actually read this).
PowerPC::HostWrite_U32(MAGIC_GAMEID, INSTALLER_BASE_ADDRESS);
// Install the custom bootloader to write gecko codes to the heaps
if (SConfig::GetInstance().m_melee_version == Melee::Version::NTSC ||
SConfig::GetInstance().m_melee_version == Melee::Version::MEX)
{ {
INFO_LOG(ACTIONREPLAY, // Write GCT loader into memory which will eventually load the real GCT into the heap
"Detected GALE01 - using tournament mode region for Gecko codelist"); std::string bootloaderData;
std::string _bootloaderFilename = File::GetSysDirectory() + GCT_BOOTLOADER;
if (!File::ReadFileToString(_bootloaderFilename, bootloaderData))
{
OSD::AddMessage("bootloader.gct not found in Sys folder.", 30000, 0xFFFF0000);
ERROR_LOG_FMT(ACTIONREPLAY, "Could not enable cheats because bootloader.gct was missing.");
return Installation::Failed;
}
// Set codelist base to the tournament mode region if (bootloaderData.length() > codelist_end_address - codelist_base_address)
codelist_base_address = 0x801910E0; {
codelist_end_address = 0x8019AF4C; OSD::AddMessage("Gecko bootloader too large.", 30000, 0xFFFF0000);
ERROR_LOG_FMT(SLIPPI, "Gecko bootloader too large");
return Installation::Failed;
}
// Patch codehandler to use tournament mode region // Install bootloader gct
PowerPC::HostWrite_U32(0x3DE08019, 0x80001904); // lis r15, 0x8019 for (size_t i = 0; i < bootloaderData.length(); ++i)
PowerPC::HostWrite_U32(0x61EF10E0, 0x80001908); // ori r15, r15, 0x10e0 PowerPC::HostWrite_U8(bootloaderData[i], static_cast<u32>(codelist_base_address + i));
} }
else else
{ {
codelist_base_address = INSTALLER_BASE_ADDRESS + static_cast<u32>(data.size()) - CODE_SIZE;
codelist_end_address = INSTALLER_END_ADDRESS;
}
// Write a magic value to 'gameid' (codehandleronly does not actually read this).
// This value will be read back and modified over time by HLE_Misc::GeckoCodeHandlerICacheFlush.
PowerPC::HostWrite_U32(MAGIC_GAMEID, INSTALLER_BASE_ADDRESS);
// Create GCT in memory // Create GCT in memory
PowerPC::HostWrite_U32(0x00d0c0de, codelist_base_address); PowerPC::HostWrite_U32(0x00d0c0de, codelist_base_address);
PowerPC::HostWrite_U32(0x00d0c0de, codelist_base_address + 4); PowerPC::HostWrite_U32(0x00d0c0de, codelist_base_address + 4);
@ -194,6 +205,11 @@ static Installation InstallCodeHandlerLocked()
// If the code is not going to fit in the space we have left then we have to skip it // If the code is not going to fit in the space we have left then we have to skip it
if (next_address + active_code.codes.size() * CODE_SIZE > end_address) if (next_address + active_code.codes.size() * CODE_SIZE > end_address)
{ {
OSD::AddMessage(
fmt::format("Ran out of memory applying gecko codes. Too many codes enabled. "
"Need {} bytes, only {} remain.",
active_code.codes.size() * CODE_SIZE, end_address - next_address),
30000, 0xFFFF0000);
NOTICE_LOG_FMT(ACTIONREPLAY, NOTICE_LOG_FMT(ACTIONREPLAY,
"Too many GeckoCodes! Ran out of storage space in Game RAM. Could " "Too many GeckoCodes! Ran out of storage space in Game RAM. Could "
"not write: \"{}\". Need {} bytes, only {} remain.", "not write: \"{}\". Need {} bytes, only {} remain.",
@ -216,6 +232,9 @@ static Installation InstallCodeHandlerLocked()
// Stop code. Tells the handler that this is the end of the list. // Stop code. Tells the handler that this is the end of the list.
PowerPC::HostWrite_U32(0xF0000000, next_address); PowerPC::HostWrite_U32(0xF0000000, next_address);
PowerPC::HostWrite_U32(0x00000000, next_address + 4); PowerPC::HostWrite_U32(0x00000000, next_address + 4);
}
// Write 0 to trampoline address, not sure why this is necessary
PowerPC::HostWrite_U32(0, HLE_TRAMPOLINE_ADDRESS); PowerPC::HostWrite_U32(0, HLE_TRAMPOLINE_ADDRESS);
// Turn on codes // Turn on codes
@ -226,6 +245,7 @@ static Installation InstallCodeHandlerLocked()
{ {
PowerPC::ppcState.iCache.Invalidate(INSTALLER_BASE_ADDRESS + j); PowerPC::ppcState.iCache.Invalidate(INSTALLER_BASE_ADDRESS + j);
} }
return Installation::Installed; return Installation::Installed;
} }
@ -296,10 +316,75 @@ void RunCodeHandler()
} }
DEBUG_LOG_FMT(ACTIONREPLAY, DEBUG_LOG_FMT(ACTIONREPLAY,
"GeckoCodes: Initiating phantom branch-and-link. " "GeckoCodes: Initiating phantom branch-and-link. "
"PC = {:#010x}, SP = {:#010x}, SFP = {:#010x}", "PC = {:#010x}, SP = {:#010x}, SFP = {:#010x}\n",
PC, SP, SFP); PC, SP, SFP);
LR = HLE_TRAMPOLINE_ADDRESS; LR = HLE_TRAMPOLINE_ADDRESS;
PC = NPC = ENTRY_POINT; PC = NPC = ENTRY_POINT;
} }
u32 GetGctLength()
{
std::lock_guard<std::mutex> lk(s_active_codes_lock);
int i = 0;
for (const GeckoCode& active_code : s_active_codes)
{
if (active_code.enabled)
{
i += 8 * static_cast<int>(active_code.codes.size());
}
}
return i + 0x10; // 0x10 is the fixed size of the header and terminator
}
std::vector<u8> uint32ToVector(u32 num)
{
u8 byte0 = num >> 24;
u8 byte1 = (num & 0xFF0000) >> 16;
u8 byte2 = (num & 0xFF00) >> 8;
u8 byte3 = num & 0xFF;
return std::vector<u8>({byte0, byte1, byte2, byte3});
}
void appendWordToBuffer(std::vector<u8>* buf, u32 word)
{
auto wordVector = uint32ToVector(word);
buf->insert(buf->end(), wordVector.begin(), wordVector.end());
}
std::vector<u8> GenerateGct()
{
std::vector<u8> res;
// Write header
appendWordToBuffer(&res, 0x00d0c0de);
appendWordToBuffer(&res, 0x00d0c0de);
std::lock_guard<std::mutex> lk(s_active_codes_lock);
int i = 0;
// Write codes
for (const GeckoCode& active_code : s_active_codes)
{
if (active_code.enabled)
{
for (const GeckoCode::Code& code : active_code.codes)
{
appendWordToBuffer(&res, code.address);
appendWordToBuffer(&res, code.data);
}
}
}
// Write footer
appendWordToBuffer(&res, 0xff000000);
appendWordToBuffer(&res, 0x00000000);
return res;
}
} // namespace Gecko } // namespace Gecko

View file

@ -66,4 +66,7 @@ void RunCodeHandler();
void Shutdown(); void Shutdown();
void DoState(PointerWrap&); void DoState(PointerWrap&);
u32 GetGctLength();
std::vector<u8> GenerateGct();
} // namespace Gecko } // namespace Gecko

View file

@ -20,11 +20,13 @@
#include "Core/Core.h" #include "Core/Core.h"
#include "Core/CoreTiming.h" #include "Core/CoreTiming.h"
#include "Core/Debugger/Debugger_SymbolMap.h" #include "Core/Debugger/Debugger_SymbolMap.h"
#include "Core/GeckoCode.h"
#include "Core/HW/EXI/EXI_DeviceSlippi.h" #include "Core/HW/EXI/EXI_DeviceSlippi.h"
#include "Core/HW/Memmap.h" #include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h" #include "Core/HW/SystemTimers.h"
#include "Core/Host.h" #include "Core/Host.h"
#include "Core/NetPlayClient.h" #include "Core/NetPlayClient.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/Slippi/SlippiPlayback.h" #include "Core/Slippi/SlippiPlayback.h"
#include "Core/Slippi/SlippiReplayComm.h" #include "Core/Slippi/SlippiReplayComm.h"
#include "Core/State.h" #include "Core/State.h"
@ -2316,6 +2318,32 @@ void CEXISlippi::prepareFileLoad(u8* payload)
m_read_queue.insert(m_read_queue.end(), buf.begin(), buf.end()); m_read_queue.insert(m_read_queue.end(), buf.begin(), buf.end());
} }
void CEXISlippi::prepareGctLength()
{
m_read_queue.clear();
u32 size = Gecko::GetGctLength();
INFO_LOG(SLIPPI, "Getting gct size: %d", size);
// Write size to output
appendWordToBuffer(&m_read_queue, size);
}
void CEXISlippi::prepareGctLoad(u8* payload)
{
m_read_queue.clear();
auto gct = Gecko::GenerateGct();
// This is the address where the codes will be written to
auto address = Common::swap32(&payload[0]);
INFO_LOG(SLIPPI, "Preparing to write gecko codes at: 0x%X", address);
m_read_queue.insert(m_read_queue.end(), gct.begin(), gct.end());
}
void CEXISlippi::handleChatMessage(u8* payload) void CEXISlippi::handleChatMessage(u8* payload)
{ {
int messageId = payload[0]; int messageId = payload[0];
@ -2618,6 +2646,12 @@ void CEXISlippi::DMAWrite(u32 _uAddr, u32 _uSize)
case CMD_REPORT_GAME: case CMD_REPORT_GAME:
handleReportGame(&memPtr[bufLoc + 1]); handleReportGame(&memPtr[bufLoc + 1]);
break; break;
case CMD_GCT_LENGTH:
prepareGctLength();
break;
case CMD_GCT_LOAD:
prepareGctLoad(&memPtr[bufLoc + 1]);
break;
default: default:
writeToFileAsync(&memPtr[bufLoc], payloadLen + 1, ""); writeToFileAsync(&memPtr[bufLoc], payloadLen + 1, "");
SlippiSpectateServer::getInstance().write(&memPtr[bufLoc], payloadLen + 1); SlippiSpectateServer::getInstance().write(&memPtr[bufLoc], payloadLen + 1);

View file

@ -10,6 +10,7 @@
#include "Common/File.h" #include "Common/File.h"
#include "Common/FileUtil.h" #include "Common/FileUtil.h"
#include "Core/Slippi/SlippiGameFileLoader.h" #include "Core/Slippi/SlippiGameFileLoader.h"
#include "Core/Slippi/SlippiGameReporter.h"
#include "Core/Slippi/SlippiMatchmaking.h" #include "Core/Slippi/SlippiMatchmaking.h"
#include "Core/Slippi/SlippiNetplay.h" #include "Core/Slippi/SlippiNetplay.h"
#include "Core/Slippi/SlippiPlayback.h" #include "Core/Slippi/SlippiPlayback.h"
@ -17,7 +18,6 @@
#include "Core/Slippi/SlippiSavestate.h" #include "Core/Slippi/SlippiSavestate.h"
#include "Core/Slippi/SlippiSpectate.h" #include "Core/Slippi/SlippiSpectate.h"
#include "Core/Slippi/SlippiUser.h" #include "Core/Slippi/SlippiUser.h"
#include "Core/Slippi/SlippiGameReporter.h"
#include "EXI_Device.h" #include "EXI_Device.h"
#define ROLLBACK_MAX_FRAMES 7 #define ROLLBACK_MAX_FRAMES 7
@ -79,6 +79,8 @@ private:
CMD_LOG_MESSAGE = 0xD0, CMD_LOG_MESSAGE = 0xD0,
CMD_FILE_LENGTH = 0xD1, CMD_FILE_LENGTH = 0xD1,
CMD_FILE_LOAD = 0xD2, CMD_FILE_LOAD = 0xD2,
CMD_GCT_LENGTH = 0xD3,
CMD_GCT_LOAD = 0xD4,
}; };
enum enum
@ -124,6 +126,8 @@ private:
{CMD_LOG_MESSAGE, 0xFFFF}, // Variable size... will only work if by itself {CMD_LOG_MESSAGE, 0xFFFF}, // Variable size... will only work if by itself
{CMD_FILE_LENGTH, 0x40}, {CMD_FILE_LENGTH, 0x40},
{CMD_FILE_LOAD, 0x40}, {CMD_FILE_LOAD, 0x40},
{CMD_GCT_LENGTH, 0x0},
{CMD_GCT_LOAD, 0x4},
}; };
struct WriteMessage struct WriteMessage
@ -189,6 +193,8 @@ private:
void logMessageFromGame(u8* payload); void logMessageFromGame(u8* payload);
void prepareFileLength(u8* payload); void prepareFileLength(u8* payload);
void prepareFileLoad(u8* payload); void prepareFileLoad(u8* payload);
void prepareGctLength();
void prepareGctLoad(u8* payload);
int getCharColor(u8 charId, u8 teamId); int getCharColor(u8 charId, u8 teamId);
void FileWriteThread(void); void FileWriteThread(void);

View file

@ -77,7 +77,7 @@ CoreTiming::EventType* et_AudioDMA;
CoreTiming::EventType* et_DSP; CoreTiming::EventType* et_DSP;
CoreTiming::EventType* et_IPC_HLE; CoreTiming::EventType* et_IPC_HLE;
// PatchEngine updates every 1/60th of a second by default // PatchEngine updates every 1/60th of a second by default
CoreTiming::EventType* et_PatchEngine; // CoreTiming::EventType* et_PatchEngine;
CoreTiming::EventType* et_Throttle; CoreTiming::EventType* et_Throttle;
u32 s_cpu_core_clock = 486000000u; // 486 mhz (its not 485, stop bugging me!) u32 s_cpu_core_clock = 486000000u; // 486 mhz (its not 485, stop bugging me!)
@ -163,7 +163,7 @@ void PatchEngineCallback(u64 userdata, s64 cycles_late)
cycles_pruned += next_schedule; cycles_pruned += next_schedule;
} }
CoreTiming::ScheduleEvent(next_schedule, et_PatchEngine, cycles_pruned); // CoreTiming::ScheduleEvent(next_schedule, et_PatchEngine, cycles_pruned);
} }
void ThrottleCallback(u64 last_time, s64 cyclesLate) void ThrottleCallback(u64 last_time, s64 cyclesLate)
@ -326,7 +326,7 @@ void Init()
et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback); et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback);
et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback); et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback);
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback); et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback); // et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
et_Throttle = CoreTiming::RegisterEvent("Throttle", ThrottleCallback); et_Throttle = CoreTiming::RegisterEvent("Throttle", ThrottleCallback);
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerHalfLine(), et_VI); CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerHalfLine(), et_VI);
@ -334,7 +334,7 @@ void Init()
CoreTiming::ScheduleEvent(s_audio_dma_period, et_AudioDMA); CoreTiming::ScheduleEvent(s_audio_dma_period, et_AudioDMA);
CoreTiming::ScheduleEvent(0, et_Throttle, Common::Timer::GetTimeUs()); CoreTiming::ScheduleEvent(0, et_Throttle, Common::Timer::GetTimeUs());
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerField(), et_PatchEngine); // CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerField(), et_PatchEngine);
if (SConfig::GetInstance().bWii) if (SConfig::GetInstance().bWii)
CoreTiming::ScheduleEvent(s_ipc_hle_period, et_IPC_HLE); CoreTiming::ScheduleEvent(s_ipc_hle_period, et_IPC_HLE);

View file

@ -85,6 +85,26 @@ std::map<Language, std::string> Volume::ReadWiiNames(const std::vector<char16_t>
return names; return names;
} }
bool Volume::FileExists(std::string file_name)
{
std::vector<DiscIO::Partition> partitions = this->GetPartitions();
if (partitions.empty())
partitions.emplace_back(PARTITION_NONE);
for (const auto& partition : partitions)
{
const DiscIO::FileInfo& root_dir = this->GetFileSystem(partition)->GetRoot();
for (const auto& file_info : root_dir)
{
if (file_info.GetName() == file_name)
{
return true;
}
}
}
return false;
}
static std::unique_ptr<VolumeDisc> CreateDisc(std::unique_ptr<BlobReader>& reader) static std::unique_ptr<VolumeDisc> CreateDisc(std::unique_ptr<BlobReader>& reader)
{ {
// Check for Wii // Check for Wii

View file

@ -152,6 +152,8 @@ public:
// The way the hash is calculated may change with updates to Dolphin. // The way the hash is calculated may change with updates to Dolphin.
virtual std::array<u8, 20> GetSyncHash() const = 0; virtual std::array<u8, 20> GetSyncHash() const = 0;
bool FileExists(std::string file_name);
protected: protected:
template <u32 N> template <u32 N>
std::string DecodeString(const char (&data)[N]) const std::string DecodeString(const char (&data)[N]) const