diff --git a/Source/Core/Core/ActionReplay.cpp b/Source/Core/Core/ActionReplay.cpp index 4047332ba785..657fa7c987c5 100644 --- a/Source/Core/Core/ActionReplay.cpp +++ b/Source/Core/Core/ActionReplay.cpp @@ -99,17 +99,6 @@ struct ARAddr operator u32() const { return address; } }; -void LogInfo(const char *format, ...); -bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data); -bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data); -bool Subtype_AddCode(const ARAddr& addr, const u32 data); -bool Subtype_MasterCodeAndWriteToCCXXXXXX(const ARAddr& addr, const u32 data); -bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const u32 data); -bool ZeroCode_MemoryCopy(const u32 val_last, const ARAddr& addr, const u32 data); -bool NormalCode(const ARAddr& addr, const u32 data); -bool ConditionalCode(const ARAddr& addr, const u32 data, int* const pSkipCount); -bool CompareValues(const u32 val1, const u32 val2, const int type); - // ---------------------- // AR Remote Functions void LoadCodes(const IniFile& globalIni, const IniFile& localIni, bool forceLoad) @@ -227,7 +216,7 @@ void LoadCodes(std::vector &_arCodes, IniFile &globalIni, IniFile& local } -void LogInfo(const char *format, ...) +static void LogInfo(const char *format, ...) { if (!b_RanOnce) { @@ -250,183 +239,6 @@ void LogInfo(const char *format, ...) } } - -void RunAllActive() -{ - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats) - { - for (auto& activeCode : activeCodes) - { - if (activeCode.active) - { - activeCode.active = RunCode(activeCode); - LogInfo("\n"); - } - } - - b_RanOnce = true; - } -} - -bool RunCode(const ARCode &arcode) -{ - // The mechanism is different than what the real AR uses, so there may be compatibility problems. - - bool doFillNSlide = false; - bool doMemoryCopy = false; - - // used for conditional codes - int skip_count = 0; - - u32 val_last = 0; - - current_code = &arcode; - - LogInfo("Code Name: %s", arcode.name.c_str()); - LogInfo("Number of codes: %i", arcode.ops.size()); - - for (const AREntry& entry : arcode.ops) - { - const ARAddr& addr = *(ARAddr*)&entry.cmd_addr; - const u32 data = entry.value; - - // after a conditional code, skip lines if needed - if (skip_count) - { - if (skip_count > 0) // skip x lines - { - LogInfo("Line skipped"); - --skip_count; - } - else if (-CONDTIONAL_ALL_LINES == skip_count) - { - // skip all lines - LogInfo("All Lines skipped"); - return true; // don't need to iterate through the rest of the ops - } - else if (-CONDTIONAL_ALL_LINES_UNTIL == skip_count) - { - // skip until a "00000000 40000000" line is reached - LogInfo("Line skipped"); - if (addr == 0 && 0x40000000 == data) // check for an endif line - skip_count = 0; - } - - continue; - } - - LogInfo("--- Running Code: %08x %08x ---", addr.address, data); - //LogInfo("Command: %08x", cmd); - - // Do Fill & Slide - if (doFillNSlide) - { - doFillNSlide = false; - LogInfo("Doing Fill And Slide"); - if (false == ZeroCode_FillAndSlide(val_last, addr, data)) - return false; - continue; - } - - // Memory Copy - if (doMemoryCopy) - { - doMemoryCopy = false; - LogInfo("Doing Memory Copy"); - if (false == ZeroCode_MemoryCopy(val_last, addr, data)) - return false; - continue; - } - - // ActionReplay program self modification codes - if (addr >= 0x00002000 && addr < 0x00003000) - { - LogInfo("This action replay simulator does not support codes that modify Action Replay itself."); - PanicAlertT("This action replay simulator does not support codes that modify Action Replay itself."); - return false; - } - - // skip these weird init lines - // TODO: Where are the "weird init lines"? - //if (iter == code.ops.begin() && cmd == 1) - //continue; - - // Zero codes - if (0x0 == addr) // Check if the code is a zero code - { - const u8 zcode = (data >> 29); - - LogInfo("Doing Zero Code %08x", zcode); - - switch (zcode) - { - case ZCODE_END: // END OF CODES - LogInfo("ZCode: End Of Codes"); - return true; - break; - - // TODO: the "00000000 40000000"(end if) codes fall into this case, I don't think that is correct - case ZCODE_NORM: // Normal execution of codes - // Todo: Set register 1BB4 to 0 - LogInfo("ZCode: Normal execution of codes, set register 1BB4 to 0 (zcode not supported)"); - break; - - case ZCODE_ROW: // Executes all codes in the same row - // Todo: Set register 1BB4 to 1 - LogInfo("ZCode: Executes all codes in the same row, Set register 1BB4 to 1 (zcode not supported)"); - PanicAlertT("Zero 3 code not supported"); - return false; - break; - - case ZCODE_04: // Fill & Slide or Memory Copy - if (0x3 == ((data >> 25) & 0x03)) - { - LogInfo("ZCode: Memory Copy"); - doMemoryCopy = true; - val_last = data; - } - else - { - LogInfo("ZCode: Fill And Slide"); - doFillNSlide = true; - val_last = data; - } - break; - - default: - LogInfo("ZCode: Unknown"); - PanicAlertT("Zero code unknown to dolphin: %08x", zcode); - return false; - break; - } - - // done handling zero codes - continue; - } - - // Normal codes - LogInfo("Doing Normal Code %08x", addr.type); - LogInfo("Subtype: %08x", addr.subtype); - - switch (addr.type) - { - case 0x00: - if (false == NormalCode(addr, data)) - return false; - break; - - default: - LogInfo("This Normal Code is a Conditional Code"); - if (false == ConditionalCode(addr, data, &skip_count)) - return false; - break; - } - } - - b_RanOnce = true; - - return true; -} size_t GetCodeListSize() { return arCodes.size(); @@ -486,7 +298,7 @@ bool IsSelfLogging() // ---------------------- // Code Functions -bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data) +static bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data) { const u32 new_addr = addr.GCAddress(); @@ -543,7 +355,7 @@ bool Subtype_RamWriteAndFill(const ARAddr& addr, const u32 data) return true; } -bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data) +static bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data) { const u32 new_addr = addr.GCAddress(); const u32 ptr = Memory::Read_U32(new_addr); @@ -602,7 +414,7 @@ bool Subtype_WriteToPointer(const ARAddr& addr, const u32 data) return true; } -bool Subtype_AddCode(const ARAddr& addr, const u32 data) +static bool Subtype_AddCode(const ARAddr& addr, const u32 data) { // Used to increment/decrement a value in memory const u32 new_addr = addr.GCAddress(); @@ -662,7 +474,7 @@ bool Subtype_AddCode(const ARAddr& addr, const u32 data) return true; } -bool Subtype_MasterCodeAndWriteToCCXXXXXX(const ARAddr& addr, const u32 data) +static bool Subtype_MasterCodeAndWriteToCCXXXXXX(const ARAddr& addr, const u32 data) { // code not yet implemented - TODO // u32 new_addr = (addr & 0x01FFFFFF) | 0x80000000; @@ -674,7 +486,7 @@ bool Subtype_MasterCodeAndWriteToCCXXXXXX(const ARAddr& addr, const u32 data) return false; } -bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const u32 data) // This needs more testing +static bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const u32 data) // This needs more testing { const u32 new_addr = ((ARAddr*)&val_last)->GCAddress(); const u8 size = ((ARAddr*)&val_last)->size; @@ -749,7 +561,7 @@ bool ZeroCode_FillAndSlide(const u32 val_last, const ARAddr& addr, const u32 dat } // Looks like this is new?? - untested -bool ZeroCode_MemoryCopy(const u32 val_last, const ARAddr& addr, const u32 data) +static bool ZeroCode_MemoryCopy(const u32 val_last, const ARAddr& addr, const u32 data) { const u32 addr_dest = val_last | 0x06000000; const u32 addr_src = addr.GCAddress(); @@ -795,7 +607,7 @@ bool ZeroCode_MemoryCopy(const u32 val_last, const ARAddr& addr, const u32 data) return true; } -bool NormalCode(const ARAddr& addr, const u32 data) +static bool NormalCode(const ARAddr& addr, const u32 data) { switch (addr.subtype) { @@ -833,7 +645,53 @@ bool NormalCode(const ARAddr& addr, const u32 data) return true; } -bool ConditionalCode(const ARAddr& addr, const u32 data, int* const pSkipCount) +static bool CompareValues(const u32 val1, const u32 val2, const int type) +{ + switch (type) + { + case CONDTIONAL_EQUAL: + LogInfo("Type 1: If Equal"); + return (val1 == val2); + break; + + case CONDTIONAL_NOT_EQUAL: + LogInfo("Type 2: If Not Equal"); + return (val1 != val2); + break; + + case CONDTIONAL_LESS_THAN_SIGNED: + LogInfo("Type 3: If Less Than (Signed)"); + return ((int)val1 < (int)val2); + break; + + case CONDTIONAL_GREATER_THAN_SIGNED: + LogInfo("Type 4: If Greater Than (Signed)"); + return ((int)val1 >(int)val2); + break; + + case CONDTIONAL_LESS_THAN_UNSIGNED: + LogInfo("Type 5: If Less Than (Unsigned)"); + return (val1 < val2); + break; + + case CONDTIONAL_GREATER_THAN_UNSIGNED: + LogInfo("Type 6: If Greater Than (Unsigned)"); + return (val1 > val2); + break; + + case CONDTIONAL_AND: + LogInfo("Type 7: If And"); + return !!(val1 & val2); // bitwise AND + break; + + default: LogInfo("Unknown Compare type"); + PanicAlertT("Action Replay: Invalid Normal Code Type %08x (%s)", type, current_code->name.c_str()); + return false; + break; + } +} + +static bool ConditionalCode(const ARAddr& addr, const u32 data, int* const pSkipCount) { const u32 new_addr = addr.GCAddress(); @@ -892,50 +750,182 @@ bool ConditionalCode(const ARAddr& addr, const u32 data, int* const pSkipCount) return true; } -bool CompareValues(const u32 val1, const u32 val2, const int type) + +void RunAllActive() { - switch (type) + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats) { - case CONDTIONAL_EQUAL: - LogInfo("Type 1: If Equal"); - return (val1 == val2); - break; + for (auto& activeCode : activeCodes) + { + if (activeCode.active) + { + activeCode.active = RunCode(activeCode); + LogInfo("\n"); + } + } - case CONDTIONAL_NOT_EQUAL: - LogInfo("Type 2: If Not Equal"); - return (val1 != val2); - break; + b_RanOnce = true; + } +} - case CONDTIONAL_LESS_THAN_SIGNED: - LogInfo("Type 3: If Less Than (Signed)"); - return ((int)val1 < (int)val2); - break; +bool RunCode(const ARCode &arcode) +{ + // The mechanism is different than what the real AR uses, so there may be compatibility problems. - case CONDTIONAL_GREATER_THAN_SIGNED: - LogInfo("Type 4: If Greater Than (Signed)"); - return ((int)val1 > (int)val2); - break; + bool doFillNSlide = false; + bool doMemoryCopy = false; - case CONDTIONAL_LESS_THAN_UNSIGNED: - LogInfo("Type 5: If Less Than (Unsigned)"); - return (val1 < val2); - break; + // used for conditional codes + int skip_count = 0; - case CONDTIONAL_GREATER_THAN_UNSIGNED: - LogInfo("Type 6: If Greater Than (Unsigned)"); - return (val1 > val2); - break; + u32 val_last = 0; - case CONDTIONAL_AND: - LogInfo("Type 7: If And"); - return !!(val1 & val2); // bitwise AND - break; + current_code = &arcode; - default: LogInfo("Unknown Compare type"); - PanicAlertT("Action Replay: Invalid Normal Code Type %08x (%s)", type, current_code->name.c_str()); - return false; - break; + LogInfo("Code Name: %s", arcode.name.c_str()); + LogInfo("Number of codes: %i", arcode.ops.size()); + + for (const AREntry& entry : arcode.ops) + { + const ARAddr& addr = *(ARAddr*)&entry.cmd_addr; + const u32 data = entry.value; + + // after a conditional code, skip lines if needed + if (skip_count) + { + if (skip_count > 0) // skip x lines + { + LogInfo("Line skipped"); + --skip_count; + } + else if (-CONDTIONAL_ALL_LINES == skip_count) + { + // skip all lines + LogInfo("All Lines skipped"); + return true; // don't need to iterate through the rest of the ops + } + else if (-CONDTIONAL_ALL_LINES_UNTIL == skip_count) + { + // skip until a "00000000 40000000" line is reached + LogInfo("Line skipped"); + if (addr == 0 && 0x40000000 == data) // check for an endif line + skip_count = 0; + } + + continue; + } + + LogInfo("--- Running Code: %08x %08x ---", addr.address, data); + //LogInfo("Command: %08x", cmd); + + // Do Fill & Slide + if (doFillNSlide) + { + doFillNSlide = false; + LogInfo("Doing Fill And Slide"); + if (false == ZeroCode_FillAndSlide(val_last, addr, data)) + return false; + continue; + } + + // Memory Copy + if (doMemoryCopy) + { + doMemoryCopy = false; + LogInfo("Doing Memory Copy"); + if (false == ZeroCode_MemoryCopy(val_last, addr, data)) + return false; + continue; + } + + // ActionReplay program self modification codes + if (addr >= 0x00002000 && addr < 0x00003000) + { + LogInfo("This action replay simulator does not support codes that modify Action Replay itself."); + PanicAlertT("This action replay simulator does not support codes that modify Action Replay itself."); + return false; + } + + // skip these weird init lines + // TODO: Where are the "weird init lines"? + //if (iter == code.ops.begin() && cmd == 1) + //continue; + + // Zero codes + if (0x0 == addr) // Check if the code is a zero code + { + const u8 zcode = (data >> 29); + + LogInfo("Doing Zero Code %08x", zcode); + + switch (zcode) + { + case ZCODE_END: // END OF CODES + LogInfo("ZCode: End Of Codes"); + return true; + break; + + // TODO: the "00000000 40000000"(end if) codes fall into this case, I don't think that is correct + case ZCODE_NORM: // Normal execution of codes + // Todo: Set register 1BB4 to 0 + LogInfo("ZCode: Normal execution of codes, set register 1BB4 to 0 (zcode not supported)"); + break; + + case ZCODE_ROW: // Executes all codes in the same row + // Todo: Set register 1BB4 to 1 + LogInfo("ZCode: Executes all codes in the same row, Set register 1BB4 to 1 (zcode not supported)"); + PanicAlertT("Zero 3 code not supported"); + return false; + break; + + case ZCODE_04: // Fill & Slide or Memory Copy + if (0x3 == ((data >> 25) & 0x03)) + { + LogInfo("ZCode: Memory Copy"); + doMemoryCopy = true; + val_last = data; + } + else + { + LogInfo("ZCode: Fill And Slide"); + doFillNSlide = true; + val_last = data; + } + break; + + default: + LogInfo("ZCode: Unknown"); + PanicAlertT("Zero code unknown to dolphin: %08x", zcode); + return false; + break; + } + + // done handling zero codes + continue; + } + + // Normal codes + LogInfo("Doing Normal Code %08x", addr.type); + LogInfo("Subtype: %08x", addr.subtype); + + switch (addr.type) + { + case 0x00: + if (false == NormalCode(addr, data)) + return false; + break; + + default: + LogInfo("This Normal Code is a Conditional Code"); + if (false == ConditionalCode(addr, data, &skip_count)) + return false; + break; + } } + + b_RanOnce = true; + + return true; } } // namespace ActionReplay