From a3a948ac1de802a6af5252773b3917a15a1f5f0c Mon Sep 17 00:00:00 2001 From: omegadox Date: Wed, 15 Oct 2008 16:33:22 +0000 Subject: [PATCH] Re-committed code from R874, but fixed the build problem, and made some code cleanup. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@880 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Core.vcproj | 8 + Source/Core/Core/Src/ActionReplay.cpp | 370 ++++++++++++++++++++++++++ Source/Core/Core/Src/ActionReplay.h | 38 +++ Source/Core/Core/Src/PatchEngine.cpp | 340 +---------------------- Source/Core/Core/Src/PatchEngine.h | 27 +- Source/Core/Core/Src/SConscript | 3 +- 6 files changed, 449 insertions(+), 337 deletions(-) create mode 100644 Source/Core/Core/Src/ActionReplay.cpp create mode 100644 Source/Core/Core/Src/ActionReplay.h diff --git a/Source/Core/Core/Core.vcproj b/Source/Core/Core/Core.vcproj index eb770222f4..20fb7b864b 100644 --- a/Source/Core/Core/Core.vcproj +++ b/Source/Core/Core/Core.vcproj @@ -1192,6 +1192,14 @@ > + + + + diff --git a/Source/Core/Core/Src/ActionReplay.cpp b/Source/Core/Core/Src/ActionReplay.cpp new file mode 100644 index 0000000000..f388b2b751 --- /dev/null +++ b/Source/Core/Core/Src/ActionReplay.cpp @@ -0,0 +1,370 @@ +// 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/ + +#include +#include +#include "StringUtil.h" +#include "IniFile.h" +#include "HW/Memmap.h" +#include "ActionReplay.h" + +u32 cmd_addr; +u8 cmd; +u32 addr; +u32 data; +u8 subtype; +u8 w; +u8 type; +u8 z; +std::vector::const_iterator iter; +std::vector arCodes; +ARCode code; + +void LoadActionReplayCodes(IniFile &ini) +{ + std::vector lines; + ARCode currentCode; + arCodes.clear(); + + if (!ini.GetLines("ActionReplay", lines)) return; + + for (std::vector::const_iterator it = lines.begin(); it != lines.end(); ++it) + { + std::string line = *it; + + std::vector pieces; + SplitString(line, " ", pieces); + if (pieces.size() == 2 && pieces[0].size() == 8 && pieces[1].size() == 8) + { + // Smells like a decrypted Action Replay code, great! Decode! + AREntry op; + bool success = TryParseUInt(std::string("0x") + pieces[0], &op.cmd_addr); + success |= TryParseUInt(std::string("0x") + pieces[1], &op.value); + if (!success) + PanicAlert("Invalid AR code line: %s", line.c_str()); + else + currentCode.ops.push_back(op); + } + else + { + SplitString(line, "-", pieces); + if (pieces.size() == 3 && pieces[0].size() == 4 && pieces[1].size() == 4 && pieces[2].size() == 4) + { + // Encrypted AR code + PanicAlert("Dolphin does not yet support encrypted AR codes."); + } + else if (line.size() > 1) + { + // OK, name line. This is the start of a new code. Push the old one, prepare the new one. + if (currentCode.ops.size()) + arCodes.push_back(currentCode); + currentCode.name = "(invalid)"; + currentCode.ops.clear(); + + if (line[0] == '+') + { + // Active code - name line. + line = StripSpaces(line.substr(1)); + currentCode.name = line; + currentCode.active = true; + } + else + { + // Inactive code. + currentCode.name = line; + currentCode.active = false; + } + } + } + } + + // Handle the last code correctly. + if (currentCode.ops.size()) + arCodes.push_back(currentCode); +} + + +// The mechanism is slightly different than what the real AR uses, so there may be compatibility problems. +// For example, some authors have created codes that add features to AR. Hacks for popular ones can be added here, +// but the problem is not generally solvable. +void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) { + code = arcode; + for (iter = code.ops.begin(); iter != code.ops.end(); ++iter) + { + cmd_addr = iter->cmd_addr; + cmd = iter->cmd_addr>>24; + addr = (iter->cmd_addr & 0x01FFFFFF); + data = iter->value; + subtype = ((addr >> 30) & 0x03); + w = (cmd - ((cmd >> 4) << 4)); + type = ((addr >> 27) & 0x07); + z = (cmd >> 4); + + if (addr >= 0x00002000 && addr < 0x00003000) { + PanicAlert("This action replay simulator does not support codes that modify Action Replay itself."); + return; + } + + // End of sequence. Dunno why anybody would use it. + if (iter->cmd_addr == 0) { + // Special command! + if ((data >> 28) == 0x8) { // Fill 'n' slide + PanicAlert("Fill'n'slide command not yet supported."); + ++iter; /* + u32 x = data; + u32 size = (addr >> 25) & 3; + addr &= 0x01FFFFFF;*/ + } + else { + if (data == 0x40000000) + { + // Resume normal execution. Don't need to do anything here. + } + else + { + PanicAlert("This action replay command (%08x %08x) not yet supported.", cmd_addr, data); + } + } + } + + // skip these weird init lines + if (iter == code.ops.begin() && cmd == 1) continue; + + // SubType selector + switch(z) + { + case 0x0: // Ram write (and fill) + { + DoARSubtype_RamWriteAndFill(); continue; + } + case 0x4: // Write to pointer + { + DoARSubtype_WriteToPointer(); continue; + } + case 0x8: // Add code + { + DoARSubtype_AddCode(); continue; + } + case 0xC: // Master Code & Write to CCXXXXXX + { + DoARSubtype_MasterCodeAndWriteToCCXXXXXX(); // TODO: This is not implemented yet + } + default: // non-specific z codes (hacks) + { + DoARSubtype_Other(); + } + } + } +} + +void DoARSubtype_RamWriteAndFill() +{ + if(w < 0x8) // Check the value W in 0xZWXXXXXXX + { + u32 new_addr = (addr | 0x80000000); + switch ((new_addr >> 25) & 0x03) + { + case 0x00: // Byte write + { + u8 repeat = data >> 8; + for (int i = 0; i <= repeat; i++) { + Memory::Write_U8(data & 0xFF, new_addr + i); + } + break; + } + + case 0x01: // Short write + { + u16 repeat = data >> 16; + for (int i = 0; i <= repeat; i++) { + Memory::Write_U16(data & 0xFFFF, new_addr + i * 2); + } + break; + } + + + case 0x02: // Dword write + { + Memory::Write_U32(data, new_addr); + break; + } + default: break; // TODO(Omega): maybe add a PanicAlert here? + } + } +} +void DoARSubtype_WriteToPointer() +{ + if(w < 0x8) + { + u32 new_addr = (addr | 0x80000000); + switch ((new_addr >> 25) & 0x03) + { + case 0x00: // Byte write to pointer + { + u32 ptr = Memory::Read_U32(new_addr); + u8 thebyte = data & 0xFF; + u32 offset = data >> 8; + Memory::Write_U8(thebyte, ptr + offset); + break; + } + + case 0x01: // Short write to pointer + { + u32 ptr = Memory::Read_U32(new_addr); + u16 theshort = data & 0xFFFF; + u32 offset = (data >> 16) << 1; + Memory::Write_U16(theshort, ptr + offset); + break; + } + + + case 0x02: // Dword write to pointer + { + u32 ptr = Memory::Read_U32(new_addr); + Memory::Write_U32(data, ptr); + break; + } + default: PanicAlert("AR Method Error (Write To Pointer): w = %08x, addr = %08x",w,addr); + } + } +} + +void DoARSubtype_AddCode() +{ + if(w < 0x8) + { + u32 new_addr = (addr | 0x81FFFFFF); + switch((new_addr >> 25) & 0x03) + { + case 0x0: // Byte add + { + Memory::Write_U8(Memory::Read_U8(new_addr) + (data & 0xFF), new_addr); break; + } + case 0x1: // Short add + { + Memory::Write_U16(Memory::Read_U16(new_addr) + (data & 0xFFFF), new_addr); break; + } + case 0x2: // DWord add + { + Memory::Write_U32(Memory::Read_U32(new_addr) + data, new_addr); break; + } + case 0x3: // Float add (not working?) + { + union { u32 u; float f;} fu, d; + fu.u = Memory::Read_U32(new_addr); + d.u = data; + fu.f += data; + Memory::Write_U32(fu.u, new_addr); + break; + } + default: break; + } + } +} + +void DoARSubtype_MasterCodeAndWriteToCCXXXXXX() +{ + // code not yet implemented - TODO + + //if(w < 0x8) + //{ + // u32 new_addr = (addr | 0x80000000); + // switch((new_addr >> 25) & 0x03) + // { + // case 0x2: + // { + + // } + // } + //} +} + +void DoARSubtype_Other() +{ + switch (cmd & 0xFE) + { + case 0x90: if (Memory::Read_U32(addr) == data) return; // IF 32 bit equal, exit + case 0x08: // IF 8 bit equal, execute next opcode + case 0x48: // (double) + { + if (Memory::Read_U16(addr) != (data & 0xFFFF)) { + if (++iter == code.ops.end()) return; + if (cmd == 0x48) if (++iter == code.ops.end()) return; + } + break; + } + case 0x0A: // IF 16 bit equal, execute next opcode + case 0x4A: // (double) + { + if (Memory::Read_U16(addr) != (data & 0xFFFF)) { + if (++iter == code.ops.end()) return; + if (cmd == 0x4A) if (++iter == code.ops.end()) return; + } + break; + } + case 0x0C: // IF 32 bit equal, execute next opcode + case 0x4C: // (double) + { + if (Memory::Read_U32(addr) != data) { + if (++iter == code.ops.end()) return; + if (cmd == 0x4C) if (++iter == code.ops.end()) return; + } + break; + } + case 0x10: // IF NOT 8 bit equal, execute next opcode + case 0x50: // (double) + { + if (Memory::Read_U8(addr) == (data & 0xFF)) { + if (++iter == code.ops.end()) return; + if (cmd == 0x50) if (++iter == code.ops.end()) return; + } + break; + } + case 0x12: // IF NOT 16 bit equal, execute next opcode + case 0x52: // (double) + { + if (Memory::Read_U16(addr) == (data & 0xFFFF)) { + if (++iter == code.ops.end()) return; + if (cmd == 0x52) if (++iter == code.ops.end()) return; + } + break; + } + case 0x14: // IF NOT 32 bit equal, execute next opcode + case 0x54: // (double) + { + if (Memory::Read_U32(addr) == data) { + if (++iter == code.ops.end()) return; + if (cmd == 0x54) if (++iter == code.ops.end()) return; + } + break; + } + case 0xC4: // "Master Code" - configure the AR + { + u8 number = data & 0xFF; + if (number == 0) + { + // Normal master code - execute once. + } else { + // PanicAlert("Not supporting multiple master codes."); + } + // u8 numOpsPerFrame = (data >> 8) & 0xFF; + // Blah, we generally ignore master codes. + break; + } + default: PanicAlert("Unknown Action Replay command %02x (%08x %08x)", cmd, iter->cmd_addr, iter->value); break; + } +} \ No newline at end of file diff --git a/Source/Core/Core/Src/ActionReplay.h b/Source/Core/Core/Src/ActionReplay.h new file mode 100644 index 0000000000..f83a8c6f8b --- /dev/null +++ b/Source/Core/Core/Src/ActionReplay.h @@ -0,0 +1,38 @@ +// 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/ + +struct AREntry { + u32 cmd_addr; + u32 value; +}; + +struct ARCode { + std::string name; + std::vector ops; + bool active; +}; + +extern std::vector arCodes; + +void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup); +void LoadActionReplayCodes(IniFile &ini); +void DoARSubtype_RamWriteAndFill(); +void DoARSubtype_WriteToPointer(); +void DoARSubtype_AddCode(); +void DoARSubtype_MasterCodeAndWriteToCCXXXXXX(); +void DoARSubtype_Other(); + diff --git a/Source/Core/Core/Src/PatchEngine.cpp b/Source/Core/Core/Src/PatchEngine.cpp index ea1d2f7fce..df0182f8c1 100644 --- a/Source/Core/Core/Src/PatchEngine.cpp +++ b/Source/Core/Core/Src/PatchEngine.cpp @@ -15,73 +15,29 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include -#include - // PatchEngine - // [Tue Aug 21 2007] [18:30:40] 0x802904b4 in US released // [Tue Aug 21 2007] [18:30:53] 0x80294d54 in EUR Demo version // [Tue Aug 21 2007] [18:31:10] we just patch a blr on it (0x4E800020) // A little present to our dear hacker friends // (A partial Action Replay engine) // And a temporary "solution" to Zelda item glitch... - // [OnLoad] // 0x80020394=dword,0x4e800020 - // #define BLR_OP 0x4e800020 +#include +#include #include "StringUtil.h" #include "PatchEngine.h" #include "IniFile.h" #include "HW/Memmap.h" - - -enum PatchType -{ - PATCH_8BIT, - PATCH_16BIT, - PATCH_32BIT, -}; - -static const char *PatchTypeStrings[] = -{ - "byte", - "word", - "dword", - 0 -}; - - -struct Patch -{ - Patch() {} - Patch(PatchType _t, u32 _addr, u32 _value) : type(_t), address(_addr), value(_value) {} - PatchType type; - u32 address; - u32 value; -}; - -std::vector onLoad; -std::vector onFrame; - -struct AREntry { - u32 cmd_addr; - u32 value; -}; - -struct ARCode { - std::string name; - std::vector ops; - bool active; -}; - -std::vector arCodes; +#include "ActionReplay.h" using namespace Common; -void RunActionReplayCode(const ARCode &code, bool nowIsBootup); +std::vector onLoad; +std::vector onFrame; void LoadPatchSection(const char *section, std::vector &patches, IniFile &ini) { @@ -110,8 +66,6 @@ void LoadPatchSection(const char *section, std::vector &patches, IniFile } } -void LoadActionReplayCodes(IniFile &ini); - void PatchEngine_LoadPatches(const char *gameID) { IniFile ini; @@ -156,291 +110,11 @@ void PatchEngine_ApplyFramePatches() { ApplyPatches(onFrame); } + void PatchEngine_ApplyARPatches() { for (std::vector::const_iterator iter = arCodes.begin(); iter != arCodes.end(); ++iter) { if (iter->active) RunActionReplayCode(*iter, false); } -} - -void LoadActionReplayCodes(IniFile &ini) -{ - std::vector lines; - ARCode currentCode; - arCodes.clear(); - - if (!ini.GetLines("ActionReplay", lines)) - return; - - for (std::vector::const_iterator iter = lines.begin(); iter != lines.end(); ++iter) - { - std::string line = *iter; - - std::vector pieces; - SplitString(line, " ", pieces); - if (pieces.size() == 2 && pieces[0].size() == 8 && pieces[1].size() == 8) - { - // Smells like a decrypted Action Replay code, great! Decode! - AREntry op; - bool success = TryParseUInt(std::string("0x") + pieces[0], &op.cmd_addr); - success |= TryParseUInt(std::string("0x") + pieces[1], &op.value); - if (!success) - PanicAlert("Invalid AR code line: %s", line.c_str()); - else - currentCode.ops.push_back(op); - } - else - { - SplitString(line, "-", pieces); - if (pieces.size() == 3 && pieces[0].size() == 4 && pieces[1].size() == 4 && pieces[2].size() == 5) - { - // Encrypted AR code - PanicAlert("Dolphin does not support encrypted AR codes"); - } - else if (line.size() > 1) - { - // OK, name line. This is the start of a new code. Push the old one, prepare the new one. - if (currentCode.ops.size()) - arCodes.push_back(currentCode); - currentCode.name = "(invalid)"; - currentCode.ops.clear(); - - if (line[0] == '+') - { - // Active code - name line. - line = StripSpaces(line.substr(1)); - currentCode.name = line; - currentCode.active = true; - } - else - { - // Inactive code. - currentCode.name = line; - currentCode.active = false; - } - } - } - } - - // Handle the last code correctly. - if (currentCode.ops.size()) - arCodes.push_back(currentCode); -} - -// The mechanism is slightly different than what the real AR uses, so there may be compatibility problems. -// For example, some authors have created codes that add features to AR. Hacks for popular ones can be added here, -// but the problem is not generally solvable. -void RunActionReplayCode(const ARCode &code, bool nowIsBootup) { - for (std::vector::const_iterator iter = code.ops.begin(); iter != code.ops.end(); ++iter) { - u32 cmd_addr = iter->cmd_addr; - u8 cmd = iter->cmd_addr>>24; - u32 addr = (iter->cmd_addr & 0x01FFFFFF); - u32 data = iter->value; - u8 z = (cmd >> 4); - u8 w = (cmd - ((cmd >> 4) << 4)); - - if (addr >= 0x00002000 && addr < 0x00003000) { - PanicAlert("This action replay simulator does not support codes that modify Action Replay itself."); - return; - } - - // End of sequence. Dunno why anybody would use it. - if (iter->cmd_addr == 0) { - // Special command! - if ((data >> 28) == 0x8) { // Fill 'n' slide - PanicAlert("Fill'n'slide command not yet supported."); - ++iter; /* - u32 x = data; - u32 size = (addr >> 25) & 3; - addr &= 0x01FFFFFF;*/ - } - else { - if (data == 0x40000000) - { - // Resume normal execution. Don't need to do anything here. - } - else - { - PanicAlert("This action replay command (%08x %08x) not yet supported.", cmd_addr, data); - } - } - } - - // skip these weird init lines - if (iter == code.ops.begin() && cmd == 1) continue; - - switch(z) - { - case 0x00: // Ram write (and fill) - { - if(w < 0x8) // Check the value W in 0xZWXXXXXXX - { - u32 new_addr = (addr | 0x80000000); - switch ((new_addr >> 25) & 0x03) - { - case 0x00: // Byte write - { - u8 repeat = data >> 8; - for (int i = 0; i <= repeat; i++) { - Memory::Write_U8(data & 0xFF, new_addr + i); - } - break; - } - - case 0x01: // Short write - { - u16 repeat = data >> 16; - for (int i = 0; i <= repeat; i++) { - Memory::Write_U16(data & 0xFFFF, new_addr + i * 2); - } - break; - } - - - case 0x02: // Dword write - { - Memory::Write_U32(data, new_addr); - break; - } - default: break; // TODO(Omega): maybe add a PanicAlert here? - } - } - continue; - } - case 0x04: // Write to pointer - { - if(w < 0x8) - { - u32 new_addr = (addr | 0x80000000); - switch ((new_addr >> 25) & 0x03) - { - case 0x00: // Byte write to pointer - { - u32 ptr = Memory::Read_U32(new_addr); - u8 thebyte = data & 0xFF; - u32 offset = data >> 8; - Memory::Write_U8(thebyte, ptr + offset); - break; - } - - case 0x01: // Short write to pointer - { - u32 ptr = Memory::Read_U32(new_addr); - u16 theshort = data & 0xFFFF; - u32 offset = (data >> 16) << 1; - Memory::Write_U16(theshort, ptr + offset); - break; - } - - - case 0x02: // Dword write to pointer - { - u32 ptr = Memory::Read_U32(new_addr); - Memory::Write_U32(data, ptr); - break; - } - default: break; // TODO(Omega): maybe add a PanicAlert here? - } - } - continue; - } - default: - { - switch (cmd & 0xFE) - { - case 0x80: // Byte add - Memory::Write_U8(Memory::Read_U8(addr) + (data & 0xFF), addr); - break; - case 0x82: // Short add - Memory::Write_U16(Memory::Read_U16(addr) + (data & 0xFFFF), addr); - break; - case 0x84: // DWord add - Memory::Write_U32(Memory::Read_U32(addr) + data, addr); - break; - case 0x86: // Float add (not working?) - { - union { - u32 u; - float f; - } fu, d; - fu.u = Memory::Read_U32(addr); - d.u = data; - fu.f += data; - Memory::Write_U32(fu.u, addr); - break; - } - case 0x90: if (Memory::Read_U32(addr) == data) return; // IF 32 bit equal, exit - case 0x08: // IF 8 bit equal, execute next opcode - case 0x48: // (double) - { - if (Memory::Read_U16(addr) != (data & 0xFFFF)) { - if (++iter == code.ops.end()) return; - if (cmd == 0x48) if (++iter == code.ops.end()) return; - } - break; - } - case 0x0A: // IF 16 bit equal, execute next opcode - case 0x4A: // (double) - { - if (Memory::Read_U16(addr) != (data & 0xFFFF)) { - if (++iter == code.ops.end()) return; - if (cmd == 0x4A) if (++iter == code.ops.end()) return; - } - break; - } - case 0x0C: // IF 32 bit equal, execute next opcode - case 0x4C: // (double) - { - if (Memory::Read_U32(addr) != data) { - if (++iter == code.ops.end()) return; - if (cmd == 0x4C) if (++iter == code.ops.end()) return; - } - break; - } - case 0x10: // IF NOT 8 bit equal, execute next opcode - case 0x50: // (double) - { - if (Memory::Read_U8(addr) == (data & 0xFF)) { - if (++iter == code.ops.end()) return; - if (cmd == 0x50) if (++iter == code.ops.end()) return; - } - break; - } - case 0x12: // IF NOT 16 bit equal, execute next opcode - case 0x52: // (double) - { - if (Memory::Read_U16(addr) == (data & 0xFFFF)) { - if (++iter == code.ops.end()) return; - if (cmd == 0x52) if (++iter == code.ops.end()) return; - } - break; - } - case 0x14: // IF NOT 32 bit equal, execute next opcode - case 0x54: // (double) - { - if (Memory::Read_U32(addr) == data) { - if (++iter == code.ops.end()) return; - if (cmd == 0x54) if (++iter == code.ops.end()) return; - } - break; - } - case 0xC4: // "Master Code" - configure the AR - { - u8 number = data & 0xFF; - if (number == 0) - { - // Normal master code - execute once. - } else { - // PanicAlert("Not supporting multiple master codes."); - } - // u8 numOpsPerFrame = (data >> 8) & 0xFF; - // Blah, we generally ignore master codes. - break; - } - default: PanicAlert("Unknown Action Replay command %02x (%08x %08x)", cmd, iter->cmd_addr, iter->value); break; - } - } - } - } -} +} \ No newline at end of file diff --git a/Source/Core/Core/Src/PatchEngine.h b/Source/Core/Core/Src/PatchEngine.h index b128e95651..22f80be3db 100644 --- a/Source/Core/Core/Src/PatchEngine.h +++ b/Source/Core/Core/Src/PatchEngine.h @@ -18,9 +18,30 @@ #ifndef _PATCHENGINE_H #define _PATCHENGINE_H -// see comments in patchengine.cpp -// TODO(ector): Actually call these functions somewhere, -// and figure out where to place patch files +enum PatchType +{ + PATCH_8BIT, + PATCH_16BIT, + PATCH_32BIT, +}; + +static const char *PatchTypeStrings[] = +{ + "byte", + "word", + "dword", + 0 +}; + +struct Patch +{ + Patch() {} + Patch(PatchType _t, u32 _addr, u32 _value) : type(_t), address(_addr), value(_value) {} + PatchType type; + u32 address; + u32 value; +}; + void PatchEngine_LoadPatches(const char *gameID); void PatchEngine_ApplyLoadPatches(); void PatchEngine_ApplyFramePatches(); diff --git a/Source/Core/Core/Src/SConscript b/Source/Core/Core/Src/SConscript index 27ac56c9e8..bc4621154a 100644 --- a/Source/Core/Core/Src/SConscript +++ b/Source/Core/Core/Src/SConscript @@ -9,6 +9,7 @@ files = ["Console.cpp", "Host.cpp", "LogManager.cpp", "MemTools.cpp", + "ActionReplay.cpp", "PatchEngine.cpp", "State.cpp", "Tracer.cpp", @@ -25,7 +26,7 @@ files = ["Console.cpp", # "Debugger/GClibloc.cpp", #Outdated "HW/AudioInterface.cpp", "HW/CommandProcessor.cpp", - "HW/CPU.cpp", + "HW/CPU.cpp", "HW/CPUCompare.cpp", "HW/DSP.cpp", "HW/DVDInterface.cpp",