1: Added logging to the AR.

2: Small fix to Fill and Slide and Memory Copy, but Fill And Slide does not actually work...:(.
3: Moved the AR code files into an "ActionReplay" VS Filter (a folder in VS, but not a real one on the FS).

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1216 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
omegadox 2008-11-19 10:49:23 +00:00
parent a006e258ec
commit 33edd6c553
4 changed files with 199 additions and 38 deletions

View File

@ -225,6 +225,7 @@ class LogTypes
WII_IPC_FILEIO, WII_IPC_FILEIO,
WII_IPC_NET, WII_IPC_NET,
WII_IPC_WIIMOTE, WII_IPC_WIIMOTE,
ACTIONREPLAY,
NUMBER_OF_LOGS NUMBER_OF_LOGS
}; };
}; };

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?> <?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="9,00" Version="9.00"
Name="Core" Name="Core"
ProjectGUID="{F0B874CB-4476-4199-9315-8343D05AE684}" ProjectGUID="{F0B874CB-4476-4199-9315-8343D05AE684}"
RootNamespace="Core" RootNamespace="Core"
@ -1204,6 +1204,9 @@
> >
</File> </File>
</Filter> </Filter>
<Filter
Name="ActionReplay"
>
<File <File
RelativePath=".\Src\ActionReplay.cpp" RelativePath=".\Src\ActionReplay.cpp"
> >
@ -1220,6 +1223,7 @@
RelativePath=".\Src\ARDecrypt.h" RelativePath=".\Src\ARDecrypt.h"
> >
</File> </File>
</Filter>
<File <File
RelativePath=".\Src\Console.cpp" RelativePath=".\Src\Console.cpp"
> >

View File

@ -28,18 +28,20 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "Common.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "HW/Memmap.h" #include "HW/Memmap.h"
#include "ActionReplay.h" #include "ActionReplay.h"
#include "Core.h" #include "Core.h"
#include "ARDecrypt.h" #include "ARDecrypt.h"
#include "LogManager.h"
namespace namespace
{ {
static std::vector<AREntry>::const_iterator iter; static std::vector<AREntry>::const_iterator iter;
static std::vector<ARCode> arCodes; static std::vector<ARCode> arCodes;
static ARCode code; static ARCode code;
static bool b_RanOnce = false;
} // namespace } // namespace
@ -48,8 +50,9 @@ bool DoARSubtype_WriteToPointer(u8 w, u32 addr, u32 data);
bool DoARSubtype_AddCode(u8 w, u32 addr, u32 data); bool DoARSubtype_AddCode(u8 w, u32 addr, u32 data);
bool DoARSubtype_MasterCodeAndWriteToCCXXXXXX(); bool DoARSubtype_MasterCodeAndWriteToCCXXXXXX();
bool DoARSubtype_Other(u8 cmd, u32 addr, u32 data); bool DoARSubtype_Other(u8 cmd, u32 addr, u32 data);
bool DoARZeroCode_FillAndSlide(u32 addr_last, u32 addr, u32 data, bool doFillNSlide); bool DoARZeroCode_FillAndSlide(u32 addr_last, u32 addr, u32 data);
bool DoARZeroCode_MemoryCopy(u32 val_last, u32 addr, u32 data); bool DoARZeroCode_MemoryCopy(u32 val_last, u32 addr, u32 data);
void LogInfo(const char *format, ...);
// Parses the Action Replay section of a game ini file. // Parses the Action Replay section of a game ini file.
void LoadActionReplayCodes(IniFile &ini, bool bForGUI) void LoadActionReplayCodes(IniFile &ini, bool bForGUI)
@ -140,9 +143,13 @@ void ActionReplayRunAllActive()
{ {
if (Core::GetStartupParameter().bEnableCheats) { if (Core::GetStartupParameter().bEnableCheats) {
for (std::vector<ARCode>::iterator iter = arCodes.begin(); iter != arCodes.end(); ++iter) for (std::vector<ARCode>::iterator iter = arCodes.begin(); iter != arCodes.end(); ++iter)
if (iter->active) if (iter->active) {
if(!RunActionReplayCode(*iter)) if(!RunActionReplayCode(*iter))
iter->active = false; iter->active = false;
LogInfo("\n");
}
if(!b_RanOnce)
b_RanOnce = true;
} }
} }
@ -166,8 +173,12 @@ bool RunActionReplayCode(const ARCode &arcode) {
code = arcode; code = arcode;
LogInfo("Code Name: %s", code.name.c_str());
LogInfo("Num code lines: %i", code.ops.size());
for (iter = code.ops.begin(); iter != code.ops.end(); ++iter) for (iter = code.ops.begin(); iter != code.ops.end(); ++iter)
{ {
LogInfo("====Do Code====");
cmd = iter->cmd_addr >> 24; // AR command cmd = iter->cmd_addr >> 24; // AR command
addr = iter->cmd_addr; // AR command with address offset addr = iter->cmd_addr; // AR command with address offset
data = iter->value; data = iter->value;
@ -176,15 +187,29 @@ bool RunActionReplayCode(const ARCode &arcode) {
type = ((addr >> 27) & 0x07); type = ((addr >> 27) & 0x07);
zcode = ((data >> 29) & 0x07); zcode = ((data >> 29) & 0x07);
LogInfo("################");
LogInfo("Command: %08x", cmd);
LogInfo("Address: %08x", addr);
LogInfo("Data: %08x", data);
LogInfo("SubType: %08x", subtype);
LogInfo("W: %08x", w);
LogInfo("ZCode: %08x", zcode);
LogInfo("Type: %08x", type);
LogInfo("################");
// Do Fill & Slide // Do Fill & Slide
if (doFillNSlide) { if (doFillNSlide) {
if (!DoARZeroCode_FillAndSlide(addr_last, addr, data, doFillNSlide)) doFillNSlide = false;
LogInfo("Doing Fill And Slide");
if (!DoARZeroCode_FillAndSlide(addr_last, addr, data))
return false; return false;
continue; continue;
} }
// Memory Copy // Memory Copy
if (doMemoryCopy) { if (doMemoryCopy) {
doMemoryCopy = false;
LogInfo("Doing Memory Copy");
if (!DoARZeroCode_MemoryCopy(val_last, addr, data)) if (!DoARZeroCode_MemoryCopy(val_last, addr, data))
return false; return false;
continue; continue;
@ -192,6 +217,7 @@ bool RunActionReplayCode(const ARCode &arcode) {
// ActionReplay program self modification codes // ActionReplay program self modification codes
if (addr >= 0x00002000 && addr < 0x00003000) { if (addr >= 0x00002000 && addr < 0x00003000) {
LogInfo("This action replay simulator does not support codes that modify Action Replay itself.");
PanicAlert("This action replay simulator does not support codes that modify Action Replay itself."); PanicAlert("This action replay simulator does not support codes that modify Action Replay itself.");
return false; return false;
} }
@ -202,54 +228,68 @@ bool RunActionReplayCode(const ARCode &arcode) {
// Zero codes // Zero codes
if (addr == 0x0) // Check if the code is a zero code if (addr == 0x0) // Check if the code is a zero code
{ {
LogInfo("This is a zcode");
switch(zcode) switch(zcode)
{ {
case 0x00: // END OF CODES case 0x00: // END OF CODES
LogInfo("ZCode: End Of Codes");
return true; return true;
case 0x02: // Normal execution of codes case 0x02: // Normal execution of codes
// Todo: Set register 1BB4 to 0 // Todo: Set register 1BB4 to 0
LogInfo("ZCode: Normal execution of codes, set register 1BB4 to 0 (zcode not supported)");
break; break;
case 0x03: // Executes all codes in the same row case 0x03: // Executes all codes in the same row
// Todo: Set register 1BB4 to 1 // Todo: Set register 1BB4 to 1
LogInfo("ZCode: Executes all codes in the same row, Set register 1BB4 to 1 (zcode not supported)");
PanicAlert("Zero 3 code not supported"); PanicAlert("Zero 3 code not supported");
return false; return false;
case 0x04: // Fill & Slide or Memory Copy case 0x04: // Fill & Slide or Memory Copy
if (((addr >> 25) & 0x03) == 0x3) { if (((addr >> 25) & 0x03) == 0x3) {
LogInfo("ZCode: Memory Copy");
doMemoryCopy = true; doMemoryCopy = true;
addr_last = addr; addr_last = addr;
val_last = data; val_last = data;
} }
else { else
{
LogInfo("ZCode: Fill And Slide");
doFillNSlide = true; doFillNSlide = true;
addr_last = addr; addr_last = addr;
} }
continue; continue;
default: default:
LogInfo("ZCode: Unknown");
PanicAlert("Zero code unknown to dolphin: %08x",zcode); PanicAlert("Zero code unknown to dolphin: %08x",zcode);
return false; return false;
} }
} }
// Normal codes // Normal codes
LogInfo("Is a normal code");
switch (subtype) switch (subtype)
{ {
case 0x0: // Ram write (and fill) case 0x0: // Ram write (and fill)
LogInfo("NCode: Ram Write And Fill");
if (!DoARSubtype_RamWriteAndFill(w, addr, data)) if (!DoARSubtype_RamWriteAndFill(w, addr, data))
return false; return false;
continue; continue;
case 0x1: // Write to pointer case 0x1: // Write to pointer
LogInfo("NCode: Write To Pointer");
if (!DoARSubtype_WriteToPointer(w, addr, data)) if (!DoARSubtype_WriteToPointer(w, addr, data))
return false; return false;
continue; continue;
case 0x2: // Add code case 0x2: // Add code
LogInfo("NCode: Add Code");
if (!DoARSubtype_AddCode(w, addr, data)) if (!DoARSubtype_AddCode(w, addr, data))
return false; return false;
continue; continue;
case 0x3: // Master Code & Write to CCXXXXXX case 0x3: // Master Code & Write to CCXXXXXX
LogInfo("NCode: Master Code And Write to CCXXXXXX (ncode not supported)");
if (!DoARSubtype_MasterCodeAndWriteToCCXXXXXX()) if (!DoARSubtype_MasterCodeAndWriteToCCXXXXXX())
return false; return false;
continue; continue;
default: // non-specific z codes (hacks) default: // non-specific z codes (hacks)
LogInfo("NCode: other AR hacks");
if (!DoARSubtype_Other(cmd, addr, data)) if (!DoARSubtype_Other(cmd, addr, data))
return false; return false;
continue; continue;
@ -264,29 +304,46 @@ bool DoARSubtype_RamWriteAndFill(u8 w, u32 addr, u32 data)
{ {
u32 new_addr = ((addr & 0x7FFFFF) | 0x80000000); // real GC address u32 new_addr = ((addr & 0x7FFFFF) | 0x80000000); // real GC address
u8 size = ((addr >> 25) & 0x03); u8 size = ((addr >> 25) & 0x03);
LogInfo("Gamecube Address: %08x", new_addr);
LogInfo("Size: %08x", size);
switch (size) switch (size)
{ {
case 0x00: // Byte write case 0x00: // Byte write
{ {
LogInfo("Byte Write");
LogInfo("--------");
u8 repeat = data >> 8; u8 repeat = data >> 8;
for (int i = 0; i <= repeat; i++) { for (int i = 0; i <= repeat; i++) {
Memory::Write_U8(data & 0xFF, new_addr + i); Memory::Write_U8(data & 0xFF, new_addr + i);
LogInfo("Wrote %08x to address %08x", data & 0xFF, new_addr + i);
} }
LogInfo("--------");
break; break;
} }
case 0x01: // Short write case 0x01: // Short write
{ {
LogInfo("Short Write");
LogInfo("--------");
u16 repeat = data >> 16; u16 repeat = data >> 16;
for (int i = 0; i <= repeat; i++) for (int i = 0; i <= repeat; i++) {
Memory::Write_U16(data & 0xFFFF, new_addr + i * 2); Memory::Write_U16(data & 0xFFFF, new_addr + i * 2);
LogInfo("Wrote %08x to address %08x", data & 0xFFFF, new_addr + i * 2);
}
LogInfo("--------");
break; break;
} }
case 0x03: //some codes use 03, but its just the same as 02... case 0x03: //some codes use 03, but its just the same as 02...
LogInfo("The odd size 3 code (we just decided to write a U32 for this)");
case 0x02: // Dword write case 0x02: // Dword write
LogInfo("Dword Write");
LogInfo("--------");
Memory::Write_U32(data, new_addr); Memory::Write_U32(data, new_addr);
LogInfo("Wrote %08x to address %08x", data, new_addr);
LogInfo("--------");
break; break;
default: default:
LogInfo("Bad Size");
PanicAlert("Action Replay Error: Invalid size (%08x : address = %08x) in Ram Write And Fill (%s)", size, addr, code.name.c_str()); PanicAlert("Action Replay Error: Invalid size (%08x : address = %08x) in Ram Write And Fill (%s)", size, addr, code.name.c_str());
return false; return false;
} }
@ -301,31 +358,52 @@ bool DoARSubtype_WriteToPointer(u8 w, u32 addr, u32 data)
{ {
u32 new_addr = ((addr & 0x7FFFFF) | 0x80000000); u32 new_addr = ((addr & 0x7FFFFF) | 0x80000000);
u8 size = ((addr >> 25) & 0x03); u8 size = ((addr >> 25) & 0x03);
LogInfo("Gamecube Address: %08x", new_addr);
LogInfo("Size: %08x", size);
switch (size) switch (size)
{ {
case 0x00: // Byte write to pointer [40] case 0x00: // Byte write to pointer [40]
{ {
LogInfo("Write byte to pointer");
LogInfo("--------");
u32 ptr = Memory::Read_U32(new_addr); u32 ptr = Memory::Read_U32(new_addr);
u8 thebyte = data & 0xFF; u8 thebyte = data & 0xFF;
u32 offset = data >> 8; u32 offset = data >> 8;
LogInfo("Pointer: %08x", ptr);
LogInfo("Byte: %08x", thebyte);
LogInfo("Offset: %08x", offset);
Memory::Write_U8(thebyte, ptr + offset); Memory::Write_U8(thebyte, ptr + offset);
LogInfo("Wrote %08x to address %08x", thebyte, ptr + offset);
LogInfo("--------");
break; break;
} }
case 0x01: // Short write to pointer [42] case 0x01: // Short write to pointer [42]
{ {
LogInfo("Write short to pointer");
LogInfo("--------");
u32 ptr = Memory::Read_U32(new_addr); u32 ptr = Memory::Read_U32(new_addr);
u16 theshort = data & 0xFFFF; u16 theshort = data & 0xFFFF;
u32 offset = (data >> 16) << 1; u32 offset = (data >> 16) << 1;
LogInfo("Pointer: %08x", ptr);
LogInfo("Byte: %08x", theshort);
LogInfo("Offset: %08x", offset);
Memory::Write_U16(theshort, ptr + offset); Memory::Write_U16(theshort, ptr + offset);
LogInfo("Wrote %08x to address %08x", theshort, ptr + offset);
LogInfo("--------");
break; break;
} }
case 0x02: // Dword write to pointer [44] case 0x02: // Dword write to pointer [44]
LogInfo("Write dword to pointer");
LogInfo("--------");
Memory::Write_U32(data, Memory::Read_U32(new_addr)); Memory::Write_U32(data, Memory::Read_U32(new_addr));
LogInfo("Wrote %08x to address %08x", data, Memory::Read_U32(new_addr));
LogInfo("--------");
break; break;
default: default:
LogInfo("Bad Size");
PanicAlert("Action Replay Error: Invalid size (%08x : address = %08x) in Write To Pointer (%s)", size, addr, code.name.c_str()); PanicAlert("Action Replay Error: Invalid size (%08x : address = %08x) in Write To Pointer (%s)", size, addr, code.name.c_str());
return false; return false;
} }
@ -340,27 +418,46 @@ bool DoARSubtype_AddCode(u8 w, u32 addr, u32 data)
{ {
u32 new_addr = (addr & 0x81FFFFFF); u32 new_addr = (addr & 0x81FFFFFF);
u8 size = ((addr >> 25) & 0x03); u8 size = ((addr >> 25) & 0x03);
LogInfo("Gamecube Address: %08x", new_addr);
LogInfo("Size: %08x", size);
switch (size) switch (size)
{ {
case 0x0: // Byte add case 0x0: // Byte add
LogInfo("Byte Add");
LogInfo("--------");
Memory::Write_U8(Memory::Read_U8(new_addr) + (data & 0xFF), new_addr); Memory::Write_U8(Memory::Read_U8(new_addr) + (data & 0xFF), new_addr);
LogInfo("Wrote %08x to address %08x", Memory::Read_U8(new_addr) + (data & 0xFF), new_addr);
LogInfo("--------");
break; break;
case 0x1: // Short add case 0x1: // Short add
LogInfo("Short Add");
LogInfo("--------");
Memory::Write_U16(Memory::Read_U16(new_addr) + (data & 0xFFFF), new_addr); Memory::Write_U16(Memory::Read_U16(new_addr) + (data & 0xFFFF), new_addr);
LogInfo("Wrote %08x to address %08x", Memory::Read_U16(new_addr) + (data & 0xFFFF), new_addr);
LogInfo("--------");
break; break;
case 0x2: // DWord add case 0x2: // DWord add
LogInfo("Dword Add");
LogInfo("--------");
Memory::Write_U32(Memory::Read_U32(new_addr) + data, new_addr); Memory::Write_U32(Memory::Read_U32(new_addr) + data, new_addr);
LogInfo("Wrote %08x to address %08x", Memory::Read_U32(new_addr) + data, new_addr);
LogInfo("--------");
break; break;
case 0x3: // Float add (not working?) case 0x3: // Float add (not working?)
{ {
LogInfo("Float Add");
LogInfo("--------");
union { u32 u; float f;} fu, d; union { u32 u; float f;} fu, d;
fu.u = Memory::Read_U32(new_addr); fu.u = Memory::Read_U32(new_addr);
d.u = data; d.u = data;
fu.f += data; fu.f += data;
Memory::Write_U32(fu.u, new_addr); Memory::Write_U32(fu.u, new_addr);
LogInfo("Wrote %08x to address %08x", fu.u, new_addr);
LogInfo("--------");
break; break;
} }
default: default:
LogInfo("Bad Size");
PanicAlert("Action Replay Error: Invalid size(%08x : address = %08x) in Add Code (%s)", size, addr, code.name.c_str()); PanicAlert("Action Replay Error: Invalid size(%08x : address = %08x) in Add Code (%s)", size, addr, code.name.c_str());
return false; return false;
} }
@ -379,6 +476,8 @@ bool DoARSubtype_MasterCodeAndWriteToCCXXXXXX()
// TODO(Omega): I think this needs cleanup, there might be a better way to code this part // TODO(Omega): I think this needs cleanup, there might be a better way to code this part
bool DoARSubtype_Other(u8 cmd, u32 addr, u32 data) bool DoARSubtype_Other(u8 cmd, u32 addr, u32 data)
{ {
LogInfo("Case: %08x", cmd & 0xFE);
LogInfo("Sorry not logging for now ... too much of a mess here ...");
switch (cmd & 0xFE) switch (cmd & 0xFE)
{ {
case 0x90: case 0x90:
@ -446,7 +545,7 @@ bool DoARSubtype_Other(u8 cmd, u32 addr, u32 data)
return true; return true;
} }
bool DoARZeroCode_FillAndSlide(u32 addr_last, u32 addr, u32 data, bool doFillNSlide) // This needs more testing bool DoARZeroCode_FillAndSlide(u32 addr_last, u32 addr, u32 data) // This needs more testing
{ {
u32 new_addr = (addr_last & 0x81FFFFFF); u32 new_addr = (addr_last & 0x81FFFFFF);
u8 size = ((new_addr >> 25) & 0x03); u8 size = ((new_addr >> 25) & 0x03);
@ -455,9 +554,12 @@ bool DoARZeroCode_FillAndSlide(u32 addr_last, u32 addr, u32 data, bool doFillNSl
int val_incr; int val_incr;
u8 write_num = ((data & 0x78000) >> 16); // Z2 u8 write_num = ((data & 0x78000) >> 16); // Z2
u32 curr_addr = new_addr; u32 curr_addr = new_addr;
LogInfo("Current Gamecube Address: %08x", new_addr);
LogInfo("Size: %08x", size);
LogInfo("Write Num: %08x", write_num);
if (write_num < 1) { if (write_num < 1) {
doFillNSlide = false; LogInfo("Write Num is less than 1, exiting Fill and Slide call...");
return true; return true;
} }
@ -470,46 +572,73 @@ bool DoARZeroCode_FillAndSlide(u32 addr_last, u32 addr, u32 data, bool doFillNSl
val_incr = (int)(data & 0x7F); // 000000Z1 val_incr = (int)(data & 0x7F); // 000000Z1
} }
LogInfo("Address Increment: %08x", addr_incr);
LogInfo("Value Increment: %08x", val_incr);
// Correct? // Correct?
if (val_incr < 0) if (val_incr < 0)
{ {
curr_addr = new_addr + (addr_incr * write_num); curr_addr = new_addr + (addr_incr * write_num);
LogInfo("Value increment is less than 0, we need to go to the last address");
LogInfo("Current GCN Address Update: %08x", curr_addr);
} }
switch(size) switch(size)
{ {
case 0x0: // Byte case 0x0: // Byte
LogInfo("Byte Write");
LogInfo("--------");
for (int i=0; i < write_num; i++) { for (int i=0; i < write_num; i++) {
u8 repeat = val >> 8; u8 repeat = val >> 8;
for(int j=0; j < repeat; j++) { for(int j=0; j < repeat; j++) {
Memory::Write_U8(val & 0xFF, new_addr + j); Memory::Write_U8(val & 0xFF, new_addr + j);
} LogInfo("Write %08x to address %08x", val & 0xFF, new_addr + j);
val += val_incr; val += val_incr;
curr_addr += addr_incr; curr_addr += addr_incr;
} break; LogInfo("Value Update: %08x", val);
LogInfo("Current GCN Address Update: %08x", curr_addr);
}
}
LogInfo("--------");
break;
case 0x1: // Halfword case 0x1: // Halfword
addr_incr >>= 1; addr_incr >>= 1;
LogInfo ("Address increment shifted right by 1: %08x", addr_incr);
LogInfo("Short Write");
LogInfo("--------");
for (int i=0; i < write_num; i++) { for (int i=0; i < write_num; i++) {
u8 repeat = val >> 16; u8 repeat = val >> 16;
for(int j=0; j < repeat; j++) { for(int j=0; j < repeat; j++) {
Memory::Write_U16(val & 0xFFFF, new_addr + j * 2); Memory::Write_U16(val & 0xFFFF, new_addr + j * 2);
} LogInfo("Write %08x to address %08x", val & 0xFFFF, new_addr + j * 2);
val += val_incr; val += val_incr;
curr_addr += addr_incr; curr_addr += addr_incr;
} break; LogInfo("Value Update: %08x", val);
LogInfo("Current GCN Address Update: %08x", curr_addr);
}
}
LogInfo("--------");
break;
case 0x2: // Word case 0x2: // Word
addr_incr >>= 2; addr_incr >>= 2;
LogInfo ("Address increment shifted right by 2: %08x", addr_incr);
LogInfo("Word Write");
LogInfo("--------");
for (int i=0; i < write_num; i++) { for (int i=0; i < write_num; i++) {
Memory::Write_U32(val, new_addr); Memory::Write_U32(val, new_addr);
LogInfo("Write %08x to address %08x", val, new_addr);
val += val_incr; val += val_incr;
curr_addr += addr_incr; curr_addr += addr_incr;
} break; LogInfo("Value Update: %08x", val);
LogInfo("Current GCN Address Update: %08x", curr_addr);
}
LogInfo("--------");
break;
default: default:
LogInfo("Bad Size");
PanicAlert("Action Replay Error: Invalid size (%08x : address = %08x) in Fill and Slide (%s)", size, new_addr, code.name.c_str()); PanicAlert("Action Replay Error: Invalid size (%08x : address = %08x) in Fill and Slide (%s)", size, new_addr, code.name.c_str());
doFillNSlide = false;
return false; return false;
} }
doFillNSlide = false;
return true; return true;
} }
@ -518,25 +647,51 @@ bool DoARZeroCode_MemoryCopy(u32 val_last, u32 addr, u32 data) // Has not been t
u32 addr_dest = (val_last | 0x06000000); u32 addr_dest = (val_last | 0x06000000);
u32 addr_src = ((addr & 0x7FFFFF) | 0x80000000); u32 addr_src = ((addr & 0x7FFFFF) | 0x80000000);
u8 num_bytes = (data & 0x7FFF); u8 num_bytes = (data & 0x7FFF);
LogInfo("Dest Address: %08x", addr_dest);
LogInfo("Src Address: %08x", addr_src);
LogInfo("Size: %08x", num_bytes);
if ((data & ~0x7FFF) == 0x0000) if ((data & ~0x7FFF) == 0x0000)
{ {
if((data >> 24) != 0x0) if((data >> 24) != 0x0)
{ // Memory Copy With Pointers Support { // Memory Copy With Pointers Support
for(int i = 0; i < 138; i++) LogInfo("Memory Copy With Pointers Support");
LogInfo("--------");
for (int i = 0; i < 138; i++) {
Memory::Write_U8(Memory::Read_U8(addr_src + i), addr_dest + i); Memory::Write_U8(Memory::Read_U8(addr_src + i), addr_dest + i);
LogInfo("Wrote %08x to address %08x", Memory::Read_U8(addr_src + i), addr_dest + i);
}
LogInfo("--------");
} }
else else
{ // Memory Copy Without Pointer Support { // Memory Copy Without Pointer Support
for (int i=0; i < num_bytes; i++) LogInfo("Memory Copy Without Pointers Support");
LogInfo("--------");
for (int i=0; i < num_bytes; i++) {
Memory::Write_U32(Memory::Read_U32(addr_src + i), addr_dest + i); Memory::Write_U32(Memory::Read_U32(addr_src + i), addr_dest + i);
LogInfo("Wrote %08x to address %08x", Memory::Read_U32(addr_src + i), addr_dest + i);
}
LogInfo("--------");
return true; return true;
} }
} }
else else
{ {
LogInfo("Bad Value");
PanicAlert("Action Replay Error: Invalid value (&08x) in Memory Copy (%s)", (data & ~0x7FFF), code.name.c_str()); PanicAlert("Action Replay Error: Invalid value (&08x) in Memory Copy (%s)", (data & ~0x7FFF), code.name.c_str());
return false; return false;
} }
return true; return true;
} }
void LogInfo(const char *format, ...)
{
if(!b_RanOnce && IsLoggingActivated()) {
char* temp = (char*)alloca(strlen(format)+512);
va_list args;
va_start(args, format);
CharArrayFromFormatV(temp, 512, format, args);
va_end(args);
LogManager::Log(LogTypes::ACTIONREPLAY, temp);
}
}

View File

@ -139,6 +139,7 @@ void LogManager::Init()
m_Log[LogTypes::WII_IPC_FILEIO + i*100] = new CDebugger_Log("WII_IPC_FILEIO", "WII IPC FILEIO", i); m_Log[LogTypes::WII_IPC_FILEIO + i*100] = new CDebugger_Log("WII_IPC_FILEIO", "WII IPC FILEIO", i);
m_Log[LogTypes::WII_IPC_NET + i*100] = new CDebugger_Log("WII_IPC_NET", "WII IPC NET", i); m_Log[LogTypes::WII_IPC_NET + i*100] = new CDebugger_Log("WII_IPC_NET", "WII IPC NET", i);
m_Log[LogTypes::WII_IPC_WIIMOTE + i*100] = new CDebugger_Log("WII_IPC_WIIMOTE", "WII IPC WIIMOTE", i); m_Log[LogTypes::WII_IPC_WIIMOTE + i*100] = new CDebugger_Log("WII_IPC_WIIMOTE", "WII IPC WIIMOTE", i);
m_Log[LogTypes::ACTIONREPLAY + i*100] = new CDebugger_Log("ActionReplay", "ActionReplay", i);
m_nextMessages[i] = 0; // initiate to zero m_nextMessages[i] = 0; // initiate to zero
} }