Added speed hack engine (way to make block take more cycles). Added example speed hack for Metroid Prime 2 PAL. (Speedhacking is only useful on games with really stupid idle loops, like the Metroids).

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1271 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2008-11-23 12:59:10 +00:00
parent e2345ba340
commit f87c709aa9
6 changed files with 84 additions and 29 deletions

View File

@ -0,0 +1,14 @@
# G2MP01 - Metroid Prime 2 Echoes
[Core]
#Values set here will override the main dolphin settings.
[Speedhacks]
# Patch OSYieldThread to take more time - MP2's idle loop is really stupid.
0x80375c68=200
[EmuState]
#The Emulation State. 1 is worst, 5 is best, 0 is not set.
EmulationStateId = 2
[OnLoad]
#Add memory patches to be loaded once on boot here.
[OnFrame]
#Add memory patches to be applied every frame here.
[ActionReplay]

View File

@ -51,21 +51,22 @@ Section::Section(const Section& other)
lines = other.lines; lines = other.lines;
} }
const Section* IniFile::GetSection(const char* sectionName) const
{
for (std::vector<Section>::const_iterator iter = sections.begin(); iter != sections.end(); ++iter)
if (!strcmp(iter->name.c_str(), sectionName))
return (&(*iter));
return 0;
}
Section* IniFile::GetSection(const char* sectionName) Section* IniFile::GetSection(const char* sectionName)
{ {
for (std::vector<Section>::iterator iter = sections.begin(); iter != sections.end(); ++iter) for (std::vector<Section>::iterator iter = sections.begin(); iter != sections.end(); ++iter)
{
if (!strcmp(iter->name.c_str(), sectionName)) if (!strcmp(iter->name.c_str(), sectionName))
{ return (&(*iter));
return(&(*iter)); return 0;
}
}
return(0);
} }
Section* IniFile::GetOrCreateSection(const char* sectionName) Section* IniFile::GetOrCreateSection(const char* sectionName)
{ {
Section* section = GetSection(sectionName); Section* section = GetSection(sectionName);
@ -102,7 +103,7 @@ bool IniFile::DeleteSection(const char* sectionName)
} }
void IniFile::ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) void IniFile::ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) const
{ {
// allow many types of commenting // allow many types of commenting
// These MUST be signed! Do not change to size_t // These MUST be signed! Do not change to size_t
@ -390,9 +391,9 @@ bool IniFile::Save(const char* filename)
} }
bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys) bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys) const
{ {
Section* section = GetSection(sectionName); const Section* section = GetSection(sectionName);
if (!section) if (!section)
{ {
@ -412,9 +413,9 @@ bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys)
} }
bool IniFile::GetLines(const char* sectionName, std::vector<std::string>& lines) bool IniFile::GetLines(const char* sectionName, std::vector<std::string>& lines) const
{ {
Section* section = GetSection(sectionName); const Section* section = GetSection(sectionName);
if (!section) if (!section)
return false; return false;

View File

@ -64,20 +64,21 @@ public:
bool Get(const char* sectionName, const char* key, bool* value, bool defaultValue = false); bool Get(const char* sectionName, const char* key, bool* value, bool defaultValue = false);
bool Get(const char* sectionName, const char* key, std::vector<std::string>& values); bool Get(const char* sectionName, const char* key, std::vector<std::string>& values);
bool GetKeys(const char* sectionName, std::vector<std::string>& keys); bool GetKeys(const char* sectionName, std::vector<std::string>& keys) const;
bool GetLines(const char* sectionName, std::vector<std::string>& lines); bool GetLines(const char* sectionName, std::vector<std::string>& lines) const;
bool DeleteKey(const char* sectionName, const char* key); bool DeleteKey(const char* sectionName, const char* key);
bool DeleteSection(const char* sectionName); bool DeleteSection(const char* sectionName);
void SortSections(); void SortSections();
void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut); void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) const;
std::string* GetLine(Section* section, const char* key, std::string* valueOut, std::string* commentOut); std::string* GetLine(Section* section, const char* key, std::string* valueOut, std::string* commentOut);
private: private:
std::vector<Section>sections; std::vector<Section>sections;
const Section* GetSection(const char* section) const;
Section* GetSection(const char* section); Section* GetSection(const char* section);
Section* GetOrCreateSection(const char* section); Section* GetOrCreateSection(const char* section);
std::string* GetLine(const char* section, const char* key); std::string* GetLine(const char* section, const char* key);

View File

@ -28,6 +28,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
#include "StringUtil.h" #include "StringUtil.h"
#include "PatchEngine.h" #include "PatchEngine.h"
#include "IniFile.h" #include "IniFile.h"
@ -41,10 +42,9 @@ namespace
std::vector<Patch> onLoad; std::vector<Patch> onLoad;
std::vector<Patch> onFrame; std::vector<Patch> onFrame;
std::map<u32, int> speedHacks;
} // namespace static void LoadPatchSection(const char *section, std::vector<Patch> &patches, IniFile &ini)
void LoadPatchSection(const char *section, std::vector<Patch> &patches, IniFile &ini)
{ {
std::vector<std::string> keys; std::vector<std::string> keys;
ini.GetKeys(section, keys); ini.GetKeys(section, keys);
@ -59,18 +59,54 @@ void LoadPatchSection(const char *section, std::vector<Patch> &patches, IniFile
std::string val(value); std::string val(value);
std::vector<std::string> items; std::vector<std::string> items;
SplitString(val, ":", items); SplitString(val, ":", items);
Patch p; if (items.size() >= 2) {
bool success = true; Patch p;
success = success && TryParseUInt(std::string(key.c_str()), &p.address); bool success = true;
success = success && TryParseUInt(items[1], &p.value); success = success && TryParseUInt(std::string(key.c_str()), &p.address);
p.type = (PatchType)ChooseStringFrom(items[0].c_str(), PatchTypeStrings); success = success && TryParseUInt(items[1], &p.value);
success = success && (p.type != (PatchType)-1); p.type = (PatchType)ChooseStringFrom(items[0].c_str(), PatchTypeStrings);
if (success) success = success && (p.type != (PatchType)-1);
patches.push_back(p); if (success)
patches.push_back(p);
}
} }
} }
} }
static void LoadSpeedhacks(const char *section, std::map<u32, int> &hacks, IniFile &ini) {
std::vector<std::string> keys;
ini.GetKeys(section, keys);
for (std::vector<std::string>::const_iterator iter = keys.begin(); iter != keys.end(); ++iter)
{
std::string key = *iter;
std::string value;
ini.Get(section, key.c_str(), &value, "BOGUS");
if (value != "BOGUS")
{
u32 address;
u32 cycles;
bool success = true;
success = success && TryParseUInt(std::string(key.c_str()), &address);
success = success && TryParseUInt(value, &cycles);
if (success) {
speedHacks[address] = (int)cycles;
}
}
}
}
} // namespace
int PatchEngine_GetSpeedhackCycles(u32 addr)
{
std::map<u32, int>::const_iterator iter = speedHacks.find(addr);
if (iter == speedHacks.end())
return 0;
else
return iter->second;
}
void PatchEngine_LoadPatches(const char *gameID) void PatchEngine_LoadPatches(const char *gameID)
{ {
IniFile ini; IniFile ini;
@ -79,6 +115,7 @@ void PatchEngine_LoadPatches(const char *gameID)
LoadPatchSection("OnLoad", onLoad, ini); LoadPatchSection("OnLoad", onLoad, ini);
LoadPatchSection("OnFrame", onFrame, ini); LoadPatchSection("OnFrame", onFrame, ini);
LoadActionReplayCodes(ini, false); LoadActionReplayCodes(ini, false);
LoadSpeedhacks("Speedhacks", speedHacks, ini);
} }
} }

View File

@ -46,4 +46,6 @@ void PatchEngine_LoadPatches(const char *gameID);
void PatchEngine_ApplyLoadPatches(); void PatchEngine_ApplyLoadPatches();
void PatchEngine_ApplyFramePatches(); void PatchEngine_ApplyFramePatches();
void PatchEngine_ApplyARPatches(); void PatchEngine_ApplyARPatches();
int PatchEngine_GetSpeedhackCycles(u32 addr);
#endif //_PATCHENGINE_H #endif //_PATCHENGINE_H

View File

@ -23,6 +23,7 @@
#include "Thunk.h" #include "Thunk.h"
#include "../../HLE/HLE.h" #include "../../HLE/HLE.h"
#include "../../Core.h" #include "../../Core.h"
#include "../../PatchEngine.h"
#include "../../CoreTiming.h" #include "../../CoreTiming.h"
#include "../PowerPC.h" #include "../PowerPC.h"
#include "../Profiler.h" #include "../Profiler.h"
@ -371,7 +372,7 @@ namespace Jit64
gpr.Start(js.gpa); gpr.Start(js.gpa);
fpr.Start(js.fpa); fpr.Start(js.fpa);
js.downcountAmount = js.st.numCycles; js.downcountAmount = js.st.numCycles + PatchEngine_GetSpeedhackCycles(emaddress);
js.blockSize = size; js.blockSize = size;
// Translate instructions // Translate instructions
for (int i = 0; i < (int)size; i++) for (int i = 0; i < (int)size; i++)
@ -396,7 +397,6 @@ namespace Jit64
} }
// const GekkoOpInfo *info = GetOpInfo(); // const GekkoOpInfo *info = GetOpInfo();
if (jo.interpretFPU && PPCTables::UsesFPU(ops[i].inst)) if (jo.interpretFPU && PPCTables::UsesFPU(ops[i].inst))
Default(ops[i].inst); Default(ops[i].inst);
else else