Add new game config system.

This commit is contained in:
Jean-Philip Desjardins 2025-01-13 18:15:07 -05:00
parent b35ef5663b
commit 8f73d94401
9 changed files with 130 additions and 1 deletions

5
GameConfig.xml Normal file
View file

@ -0,0 +1,5 @@
<GameConfigs>
<GameConfig Executable="SLUS_204.71;1" Title="Rygar - The Legendary Adventure">
<BlockFpRoundingMode Address="0x00147D88" Mode="NEAREST" />
</GameConfig>
</GameConfigs>

View file

@ -1,8 +1,27 @@
#include "EeBasicBlock.h"
#include "offsetof_def.h"
void CEeBasicBlock::SetFpRoundingMode(Jitter::CJitter::ROUNDINGMODE fpRoundingMode)
{
m_fpRoundingMode = fpRoundingMode;
}
void CEeBasicBlock::CompileProlog(CMipsJitter* jitter)
{
if(m_fpRoundingMode != DEFAULT_FP_ROUNDING_MODE)
{
jitter->FP_SetRoundingMode(m_fpRoundingMode);
}
CBasicBlock::CompileProlog(jitter);
}
void CEeBasicBlock::CompileEpilog(CMipsJitter* jitter, bool loopsOnItself)
{
if(m_fpRoundingMode != DEFAULT_FP_ROUNDING_MODE)
{
jitter->FP_SetRoundingMode(DEFAULT_FP_ROUNDING_MODE);
}
if(IsIdleLoopBlock())
{
jitter->PushCst(MIPS_EXCEPTION_IDLE);

View file

@ -7,9 +7,15 @@ class CEeBasicBlock : public CBasicBlock
public:
using CBasicBlock::CBasicBlock;
void SetFpRoundingMode(Jitter::CJitter::ROUNDINGMODE);
protected:
void CompileProlog(CMipsJitter*) override;
void CompileEpilog(CMipsJitter*, bool) override;
private:
bool IsIdleLoopBlock() const;
static constexpr auto DEFAULT_FP_ROUNDING_MODE = Jitter::CJitter::ROUND_TRUNCATE;
Jitter::CJitter::ROUNDINGMODE m_fpRoundingMode = DEFAULT_FP_ROUNDING_MODE;
};

View file

@ -40,6 +40,11 @@ CEeExecutor::CEeExecutor(CMIPS& context, uint8* ram)
m_pageSize = framework_getpagesize();
}
void CEeExecutor::SetBlockFpRoundingModes(BlockFpRoundingModes blockFpRoundingMode)
{
m_blockFpRoundingModes = std::move(blockFpRoundingMode);
}
void CEeExecutor::AddExceptionHandler()
{
assert(g_eeExecutor == nullptr);
@ -111,6 +116,7 @@ void CEeExecutor::Reset()
{
SetMemoryProtected(m_ram, PS2::EE_RAM_SIZE, false);
m_cachedBlocks.clear();
m_blockFpRoundingModes.clear();
CGenericMipsExecutor::Reset();
}
@ -170,6 +176,13 @@ BasicBlockPtr CEeExecutor::BlockFactory(CMIPS& context, uint32 start, uint32 end
}
auto result = std::make_shared<CEeBasicBlock>(context, start, end, m_blockCategory);
if(auto blockFpRoundingModeIterator = m_blockFpRoundingModes.find(start);
blockFpRoundingModeIterator != std::end(m_blockFpRoundingModes))
{
result->SetFpRoundingMode(blockFpRoundingModeIterator->second);
}
result->Compile();
if(!hasBreakpoint)
{

View file

@ -1,6 +1,7 @@
#pragma once
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>
#elif defined(__APPLE__)
#include <mach/mach.h>
@ -14,9 +15,13 @@
class CEeExecutor : public CGenericMipsExecutor<BlockLookupTwoWay>
{
public:
using BlockFpRoundingModes = std::map<uint32, Jitter::CJitter::ROUNDINGMODE>;
CEeExecutor(CMIPS&, uint8*);
virtual ~CEeExecutor() = default;
void SetBlockFpRoundingModes(BlockFpRoundingModes);
void AddExceptionHandler();
void RemoveExceptionHandler();
@ -32,6 +37,8 @@ private:
typedef std::map<CachedBlockKey, BasicBlockPtr> CachedBlockMap;
CachedBlockMap m_cachedBlocks;
BlockFpRoundingModes m_blockFpRoundingModes;
uint8* m_ram = nullptr;
size_t m_pageSize = 0;

View file

@ -22,6 +22,7 @@
#include "Timer.h"
#include "SIF.h"
#include "EEAssembler.h"
#include "EeExecutor.h"
#include "PathUtils.h"
#include "xml/Node.h"
#include "xml/Parser.h"
@ -61,6 +62,8 @@
#define SEMA_ID_BASE 0
#define PATCHESFILENAME "patches.xml"
#define GAMECONFIG_FILENAME "GameConfig.xml"
#define LOG_NAME ("ps2os")
#define SYSCALL_CUSTOM_RESCHEDULE 0x666
@ -435,6 +438,7 @@ void CPS2OS::LoadELF(Framework::CStream* stream, const char* executablePath, con
LoadExecutableInternal();
ApplyPatches();
ApplyGameConfig();
OnExecutableChange();
@ -631,6 +635,78 @@ void CPS2OS::ApplyPatches()
}
}
void CPS2OS::ApplyGameConfig()
{
std::unique_ptr<Framework::Xml::CNode> document;
try
{
#ifdef __ANDROID__
Framework::Android::CAssetStream inputStream(GAMECONFIG_FILENAME);
#else
auto gameConfigPath = Framework::PathUtils::GetAppResourcesPath() / GAMECONFIG_FILENAME;
Framework::CStdStream inputStream(Framework::CreateInputStdStream(gameConfigPath.native()));
#endif
document = Framework::Xml::CParser::ParseDocument(inputStream);
if(!document) return;
}
catch(const std::exception& exception)
{
CLog::GetInstance().Warn(LOG_NAME, "Failed to open game config file: %s.\r\n", exception.what());
return;
}
auto gameConfigsNode = document->Select("GameConfigs");
if(!gameConfigsNode)
{
return;
}
CEeExecutor::BlockFpRoundingModes blockFpRoundingModes;
for(Framework::Xml::CFilteringNodeIterator itNode(gameConfigsNode, "GameConfig");
!itNode.IsEnd(); itNode++)
{
auto gameConfigNode = (*itNode);
const char* executable = gameConfigNode->GetAttribute("Executable");
if(!executable) continue;
if(strcmp(executable, GetExecutableName())) continue;
//Found the right executable, apply config
for(Framework::Xml::CFilteringNodeIterator itNode(gameConfigNode, "BlockFpRoundingMode");
!itNode.IsEnd(); itNode++)
{
auto node = (*itNode);
const char* addressString = node->GetAttribute("Address");
const char* modeString = node->GetAttribute("Mode");
if(!addressString) continue;
if(!modeString) continue;
uint32 address = 0;
auto roundingMode = Jitter::CJitter::ROUND_NEAREST;
if(sscanf(addressString, "%x", &address) == 0) continue;
if(!strcmp(modeString, "NEAREST"))
{
roundingMode = Jitter::CJitter::ROUND_NEAREST;
}
else
{
continue;
}
blockFpRoundingModes.insert(std::make_pair(address, roundingMode));
}
static_cast<CEeExecutor*>(m_ee.m_executor.get())->SetBlockFpRoundingModes(std::move(blockFpRoundingModes));
break;
}
}
void CPS2OS::AssembleCustomSyscallHandler()
{
CMIPSAssembler assembler((uint32*)&m_bios[0x100]);

View file

@ -343,6 +343,7 @@ private:
void UnloadExecutable();
void ApplyPatches();
void ApplyGameConfig();
void DisassembleSysCall(uint8);
std::string GetSysCallDescription(uint8);

2
deps/CodeGen vendored

@ -1 +1 @@
Subproject commit 8ce047963531f0255ad0d5db09d4a2fd616d985d
Subproject commit e113b462ca78b5f6ba8d0294e39936f9561211e7

View file

@ -82,6 +82,7 @@ Section "Play! (required)"
File /oname=styles\qwindowsvistastyle.dll "${BINARY_INPUT_PATH}\styles\qwindowsvistastyle.dll"
File /oname=imageformats\qjpeg.dll "${BINARY_INPUT_PATH}\imageformats\qjpeg.dll"
File "..\Patches.xml"
File "..\GameConfig.xml"
File "..\states.db"
SetOutPath $INSTDIR\arcadedefs
@ -135,6 +136,7 @@ Section "Uninstall"
Delete $INSTDIR\styles\qwindowsvistastyle.dll
Delete $INSTDIR\imageformats\qjpeg.dll
Delete $INSTDIR\Patches.xml
Delete $INSTDIR\GameConfig.xml
Delete $INSTDIR\states.db
Delete $INSTDIR\arcadedefs\*
Delete $INSTDIR\uninstall.exe