mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-19 20:41:16 +01:00
47dfc9ad38
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1134 8ced0084-cf51-0410-be5f-012b33b47a6e
123 lines
3.3 KiB
C++
123 lines
3.3 KiB
C++
// Copyright (C) 2003-2008 Dolphin Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official SVN repository and contact information can be found at
|
|
// http://code.google.com/p/dolphin-emu/
|
|
|
|
// PatchEngine
|
|
// Supports simple memory patches, and has a partial Action Replay implementation
|
|
// in ActionReplay.cpp/h.
|
|
|
|
// Zelda item hang fixes:
|
|
// [Tue Aug 21 2007] [18:30:40] <Knuckles-> 0x802904b4 in US released
|
|
// [Tue Aug 21 2007] [18:30:53] <Knuckles-> 0x80294d54 in EUR Demo version
|
|
// [Tue Aug 21 2007] [18:31:10] <Knuckles-> we just patch a blr on it (0x4E800020)
|
|
// [OnLoad]
|
|
// 0x80020394=dword,0x4e800020
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include "StringUtil.h"
|
|
#include "PatchEngine.h"
|
|
#include "IniFile.h"
|
|
#include "HW/Memmap.h"
|
|
#include "ActionReplay.h"
|
|
|
|
using namespace Common;
|
|
|
|
namespace
|
|
{
|
|
|
|
std::vector<Patch> onLoad;
|
|
std::vector<Patch> onFrame;
|
|
|
|
} // namespace
|
|
|
|
void LoadPatchSection(const char *section, std::vector<Patch> &patches, 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")
|
|
{
|
|
std::string val(value);
|
|
std::vector<std::string> items;
|
|
SplitString(val, ":", items);
|
|
Patch p;
|
|
bool success = true;
|
|
success = success && TryParseUInt(std::string(key.c_str()), &p.address);
|
|
success = success && TryParseUInt(items[1], &p.value);
|
|
p.type = (PatchType)ChooseStringFrom(items[0].c_str(), PatchTypeStrings);
|
|
success = success && (p.type != (PatchType)-1);
|
|
if (success)
|
|
patches.push_back(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PatchEngine_LoadPatches(const char *gameID)
|
|
{
|
|
IniFile ini;
|
|
std::string filename = std::string(FULL_GAMECONFIG_DIR) + gameID + ".ini";
|
|
if (ini.Load(filename.c_str())) {
|
|
LoadPatchSection("OnLoad", onLoad, ini);
|
|
LoadPatchSection("OnFrame", onFrame, ini);
|
|
LoadActionReplayCodes(ini, false);
|
|
}
|
|
}
|
|
|
|
void ApplyPatches(const std::vector<Patch> &patches)
|
|
{
|
|
for (std::vector<Patch>::const_iterator iter = patches.begin(); iter != patches.end(); ++iter)
|
|
{
|
|
u32 addr = iter->address;
|
|
u32 value = iter->value;
|
|
switch (iter->type)
|
|
{
|
|
case PATCH_8BIT:
|
|
Memory::Write_U8((u8)value, addr);
|
|
break;
|
|
case PATCH_16BIT:
|
|
Memory::Write_U16((u16)value, addr);
|
|
break;
|
|
case PATCH_32BIT:
|
|
Memory::Write_U32(value, addr);
|
|
break;
|
|
default:
|
|
//unknown patchtype
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PatchEngine_ApplyLoadPatches()
|
|
{
|
|
ApplyPatches(onLoad);
|
|
}
|
|
|
|
void PatchEngine_ApplyFramePatches()
|
|
{
|
|
ApplyPatches(onFrame);
|
|
}
|
|
|
|
void PatchEngine_ApplyARPatches()
|
|
{
|
|
ActionReplayRunAllActive();
|
|
}
|