mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 15:49:25 +01:00
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:
parent
e2345ba340
commit
f87c709aa9
14
Data/User/GameConfig/G2MP01.ini
Normal file
14
Data/User/GameConfig/G2MP01.ini
Normal 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]
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user