summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorhrydgard <hrydgard@gmail.com>2008-10-16 22:06:06 +0000
committerhrydgard <hrydgard@gmail.com>2008-10-16 22:06:06 +0000
commit21b0d596e4aa948a2be0ef482e82c4dc7208c436 (patch)
treecb67daeee9849df19686b7cf9e9cd019f6f1e830 /Source
parent3ae2d556ab35c1479f8f874bc8ca28a3b001c681 (diff)
Kill lots of old outdated comments. Some new comments added. Misc style fixes. No effect on emulation.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@894 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/Src/ActionReplay.cpp342
-rw-r--r--Source/Core/Core/Src/ActionReplay.h8
-rw-r--r--Source/Core/Core/Src/Console.cpp19
-rw-r--r--Source/Core/Core/Src/Console.h5
-rw-r--r--Source/Core/Core/Src/Core.h14
-rw-r--r--Source/Core/Core/Src/CoreParameter.h1
-rw-r--r--Source/Core/Core/Src/CoreTiming.cpp7
-rw-r--r--Source/Core/Core/Src/CoreTiming.h12
-rw-r--r--Source/Core/Core/Src/HW/DSP.cpp7
-rw-r--r--Source/Core/Core/Src/HW/Memmap.cpp10
-rw-r--r--Source/Core/Core/Src/LogManager.cpp1
-rw-r--r--Source/Core/Core/Src/LogManager.h4
-rw-r--r--Source/Core/Core/Src/MemTools.cpp4
-rw-r--r--Source/Core/Core/Src/MemTools.h43
-rw-r--r--Source/Core/Core/Src/PatchEngine.cpp18
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp197
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit.h11
-rw-r--r--Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp11
-rw-r--r--Source/Core/Core/Src/PowerPC/PPCTables.cpp2
-rw-r--r--Source/Core/Core/Src/PowerPC/PPCTables.h1
-rw-r--r--Source/Core/Core/Src/PowerPC/PowerPC.cpp436
-rw-r--r--Source/Core/Core/Src/PowerPC/PowerPC.h12
-rw-r--r--Source/Core/Core/Src/State.h2
-rw-r--r--Source/Core/Core/Src/VolumeHandler.cpp3
-rw-r--r--Source/Core/Core/Src/VolumeHandler.h10
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/XFB.cpp2
26 files changed, 553 insertions, 629 deletions
diff --git a/Source/Core/Core/Src/ActionReplay.cpp b/Source/Core/Core/Src/ActionReplay.cpp
index aca8c7f904..f6fff3f47e 100644
--- a/Source/Core/Core/Src/ActionReplay.cpp
+++ b/Source/Core/Core/Src/ActionReplay.cpp
@@ -15,36 +15,60 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+
+// Simple partial Action Replay code system implementation.
+
+// Will never be able to support some AR codes - specifically those that patch the running
+// Action Replay engine itself - yes they do exist!!!
+
+// Action Replay actually is a small virtual machine with a limited number of commands.
+// It probably is Turing complete - but what does that matter when AR codes can write
+// actual PowerPC code.
+
#include <string>
#include <vector>
+
#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;
-std::vector<AREntry>::const_iterator iter;
-std::vector<ARCode> arCodes;
-ARCode code;
+namespace {
+
+// These should be turned into locals in RunActionReplayCode, and passed as parameters to the others.
+static u32 cmd_addr;
+static u8 cmd;
+static u32 addr;
+static u32 data;
+static u8 subtype;
+static u8 w;
+static u8 type;
+static std::vector<AREntry>::const_iterator iter;
+
+static std::vector<ARCode> arCodes;
+static ARCode code;
+
+} // namespace
+
+void DoARSubtype_RamWriteAndFill();
+void DoARSubtype_WriteToPointer();
+void DoARSubtype_AddCode();
+void DoARSubtype_MasterCodeAndWriteToCCXXXXXX();
+void DoARSubtype_Other();
+// Parses the Action Replay section of a game ini file.
void LoadActionReplayCodes(IniFile &ini)
{
std::vector<std::string> lines;
ARCode currentCode;
arCodes.clear();
- if (!ini.GetLines("ActionReplay", lines)) return;
+ if (!ini.GetLines("ActionReplay", lines))
+ return; // no codes found.
for (std::vector<std::string>::const_iterator it = lines.begin(); it != lines.end(); ++it)
{
std::string line = *it;
-
std::vector<std::string> pieces;
SplitString(line, " ", pieces);
if (pieces.size() == 2 && pieces[0].size() == 8 && pieces[1].size() == 8)
@@ -96,6 +120,12 @@ void LoadActionReplayCodes(IniFile &ini)
arCodes.push_back(currentCode);
}
+void ActionReplayRunAllActive()
+{
+ for (std::vector<ARCode>::const_iterator iter = arCodes.begin(); iter != arCodes.end(); ++iter)
+ if (iter->active)
+ RunActionReplayCode(*iter, false);
+}
// 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,
@@ -143,121 +173,114 @@ void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) {
if (iter == code.ops.begin() && cmd == 1) continue;
// SubType selector
- switch(subtype)
+ switch (subtype)
{
- case 0x0: // Ram write (and fill)
- {
- DoARSubtype_RamWriteAndFill(); continue;
- }
- case 0x1: // Write to pointer
- {
- DoARSubtype_WriteToPointer(); continue;
- }
- case 0x2: // Add code
- {
- DoARSubtype_AddCode(); continue;
- }
- case 0x3: // Master Code & Write to CCXXXXXX
- {
- DoARSubtype_MasterCodeAndWriteToCCXXXXXX(); continue;// TODO: This is not implemented yet
- }
- default: // non-specific z codes (hacks)
- {
- DoARSubtype_Other(); continue;
- }
+ case 0x0: // Ram write (and fill)
+ DoARSubtype_RamWriteAndFill();
+ continue;
+ case 0x1: // Write to pointer
+ DoARSubtype_WriteToPointer();
+ continue;
+ case 0x2: // Add code
+ DoARSubtype_AddCode();
+ continue;
+ case 0x3: // Master Code & Write to CCXXXXXX
+ DoARSubtype_MasterCodeAndWriteToCCXXXXXX();
+ continue; // TODO: This is not implemented yet
+ default: // non-specific z codes (hacks)
+ DoARSubtype_Other();
+ continue;
}
}
}
void DoARSubtype_RamWriteAndFill()
{
- if(w < 0x8) // Check the value W in 0xZWXXXXXXX
+ if (w < 0x8) // Check the value W in 0xZWXXXXXXX
{
u32 new_addr = ( (addr & 0x01FFFFFF) | 0x80000000);
switch ((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 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 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?
+ 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)
+ if (w < 0x8)
{
u32 new_addr = ( addr | 0x80000000);
switch ((addr >> 25) & 0x03)
{
- case 0x00: // Byte write to pointer [40]
- {
- u32 ptr = Memory::Read_U32(new_addr);
- u8 thebyte = data & 0xFF;
- u32 offset = data >> 8;
- Memory::Write_U8(thebyte, ptr + offset);
- break;
- }
+ case 0x00: // Byte write to pointer [40]
+ {
+ 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 [42]
- {
- u32 ptr = Memory::Read_U32(new_addr);
- u16 theshort = data & 0xFFFF;
- u32 offset = (data >> 16) << 1;
- Memory::Write_U16(theshort, ptr + offset);
- break;
- }
+ case 0x01: // Short write to pointer [42]
+ {
+ 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 [44]
- {
- Memory::Write_U32(data, Memory::Read_U32(new_addr)); break;
- }
+ case 0x02: // Dword write to pointer [44]
+ Memory::Write_U32(data, Memory::Read_U32(new_addr));
+ break;
- default: PanicAlert("AR Method Error (Write To Pointer): w = %08x, addr = %08x",w,addr);
+ default:
+ PanicAlert("AR Method Error (Write To Pointer): w = %08x, addr = %08x", w, addr);
+ break;
}
}
}
void DoARSubtype_AddCode()
{
- if(w < 0x8)
+ if (w < 0x8)
{
u32 new_addr = ( (addr & 0x01FFFFFF) | 0x81FFFFFF);
- switch((addr >> 25) & 0x03)
+ switch ((addr >> 25) & 0x03)
{
case 0x0: // Byte add
- {
- Memory::Write_U8(Memory::Read_U8(new_addr) + (data & 0xFF), new_addr); break;
- }
+ 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;
- }
+ 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;
- }
+ 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;
@@ -267,7 +290,8 @@ void DoARSubtype_AddCode()
Memory::Write_U32(fu.u, new_addr);
break;
}
- default: break;
+ default:
+ break;
}
}
}
@@ -276,10 +300,10 @@ void DoARSubtype_MasterCodeAndWriteToCCXXXXXX()
{
// code not yet implemented - TODO
- //if(w < 0x8)
+ //if (w < 0x8)
//{
// u32 new_addr = (addr | 0x80000000);
- // switch((new_addr >> 25) & 0x03)
+ // switch ((new_addr >> 25) & 0x03)
// {
// case 0x2:
// {
@@ -291,76 +315,68 @@ void DoARSubtype_MasterCodeAndWriteToCCXXXXXX()
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;
- }
+ switch (cmd & 0xFE)
+ {
+ case 0x90:
+ // Eh, this must be wrong. Should it really fallthrough?
+ 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
index f83a8c6f8b..0747ef7072 100644
--- a/Source/Core/Core/Src/ActionReplay.h
+++ b/Source/Core/Core/Src/ActionReplay.h
@@ -26,13 +26,7 @@ struct ARCode {
bool active;
};
-extern std::vector<ARCode> arCodes;
-
+void ActionReplayRunAllActive();
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/Console.cpp b/Source/Core/Core/Src/Console.cpp
index b2ef092e8d..c9dd42a5e4 100644
--- a/Source/Core/Core/Src/Console.cpp
+++ b/Source/Core/Core/Src/Console.cpp
@@ -14,6 +14,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+
#include <iostream>
#include <cstring>
@@ -22,32 +23,16 @@
#include "HW/Memmap.h"
#include "PowerPC/PPCAnalyst.h"
#include "PowerPC/PPCTables.h"
-#include "Console.h"
#include "CoreTiming.h"
#include "Core.h"
#include "PowerPC/Jit64/JitCache.h"
#include "PowerPC/SymbolDB.h"
#include "PowerPCDisasm.h"
+#include "Console.h"
#define CASE(x) else if (memcmp(cmd, x, 4*sizeof(TCHAR))==0)
#define CASE1(x) if (memcmp(cmd, x, 2*sizeof(TCHAR))==0)
-/*
-static Common::Thread *cons_thread;
-
-THREAD_RETURN ConsoleThreadFunc(void *) {
- printf("Welcome to the console thread!\n\n");
- while (true) {
- std::string command;
- getline(std::cin, command);
- Console_Submit(command.c_str());
- }
-}
-
-void StartConsoleThread() {
- cons_thread = new Common::Thread(ConsoleThreadFunc, 0);
-}*/
-
void Console_Submit(const char *cmd)
{
CASE1("jits")
diff --git a/Source/Core/Core/Src/Console.h b/Source/Core/Core/Src/Console.h
index 7353f50aab..96e1063b4e 100644
--- a/Source/Core/Core/Src/Console.h
+++ b/Source/Core/Core/Src/Console.h
@@ -14,11 +14,14 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+
+
+// Simple debugging console currently residing in the Logging window. Not used much.
+
#ifndef _CONSOLE_H
#define _CONSOLE_H
void Console_Submit(const char *cmd);
-// void StartConsoleThread();
#endif
diff --git a/Source/Core/Core/Src/Core.h b/Source/Core/Core/Src/Core.h
index d4ab0da840..8c3606804c 100644
--- a/Source/Core/Core/Src/Core.h
+++ b/Source/Core/Core/Src/Core.h
@@ -14,6 +14,14 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+
+
+// Core
+
+// The external interface to the emulator core. Plus some extras.
+// This is another part of the emu that needs cleaning - Core.cpp really has
+// too much random junk inside.
+
#ifndef _CORE_H
#define _CORE_H
@@ -36,10 +44,7 @@ namespace Core
bool Init(const SCoreStartupParameter _CoreParameter);
void Stop();
- // Get state
bool SetState(EState _State);
-
- // Get state
EState GetState();
// Save/Load state
@@ -64,8 +69,7 @@ namespace Core
int SyncTrace();
void SetBlockStart(u32 addr);
void StopTrace();
-
-} // end of namespace Core
+} // namespace
#endif
diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h
index ea6f22dbc5..f304e10b7c 100644
--- a/Source/Core/Core/Src/CoreParameter.h
+++ b/Source/Core/Core/Src/CoreParameter.h
@@ -14,6 +14,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+
#ifndef _COREPARAMETER_H
#define _COREPARAMETER_H
diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp
index 7c79751197..e1436f118e 100644
--- a/Source/Core/Core/Src/CoreTiming.cpp
+++ b/Source/Core/Core/Src/CoreTiming.cpp
@@ -293,16 +293,13 @@ void Advance()
externalEventSection.Enter();
while (tsFirst)
{
- //MessageBox(0,"yay",0,0);
Event *next = tsFirst->next;
AddEventToQueue(tsFirst);
tsFirst = next;
}
externalEventSection.Leave();
- // we are out of run, downcount = -3
int cyclesExecuted = slicelength - downcount;
- // sliceLength = downac
globalTimer += cyclesExecuted;
@@ -312,7 +309,6 @@ void Advance()
{
// LOG(GEKKO, "[Scheduler] %s (%lld, %lld) ",
// first->name ? first->name : "?", (u64)globalTimer, (u64)first->time);
-
event_types[first->type].callback(first->userdata, (int)(globalTimer - first->time));
Event *next = first->next;
delete first;
@@ -326,7 +322,6 @@ void Advance()
if (!first)
{
LOG(GEKKO, "WARNING - no events in queue. Setting downcount to 10000");
- // PanicAlert?
downcount += 10000;
}
else
@@ -379,4 +374,4 @@ std::string GetScheduledEventsSummary()
return text;
}
-}; // end of namespace
+} // namespace
diff --git a/Source/Core/Core/Src/CoreTiming.h b/Source/Core/Core/Src/CoreTiming.h
index 09f4ea4f9f..ed98ef4a85 100644
--- a/Source/Core/Core/Src/CoreTiming.h
+++ b/Source/Core/Core/Src/CoreTiming.h
@@ -24,6 +24,13 @@
// To schedule an event, you first have to register its type. This is where you pass in the
// callback. You then schedule events using the type id you get back.
+// See HW/SystemTimers.cpp for the main part of Dolphin's usage of this scheduler.
+
+// The int cyclesLate that the callbacks get is how many cycles late it was.
+// So to schedule a new event on a regular basis:
+// inside callback:
+// ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever")
+
#include "Common.h"
#include <string>
@@ -33,7 +40,6 @@
namespace CoreTiming
{
-
void Init();
void Shutdown();
@@ -43,10 +49,6 @@ u64 GetTicks();
u64 GetIdleTicks();
void DoState(PointerWrap &p);
-// The int that the callbacks get is how many cycles late it was.
-// So to schedule a new event on a regular basis:
-// inside callback:
-// ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever")
// Returns the event_type identifier.
int RegisterEvent(const char *name, TimedCallback callback);
diff --git a/Source/Core/Core/Src/HW/DSP.cpp b/Source/Core/Core/Src/HW/DSP.cpp
index a70f642558..344c04ba00 100644
--- a/Source/Core/Core/Src/HW/DSP.cpp
+++ b/Source/Core/Core/Src/HW/DSP.cpp
@@ -17,10 +17,9 @@
// AID / AUDIO_DMA controls pushing audio out to the SRC and then the speakers.
// The audio DMA pushes audio through a small FIFO 32 bytes at a time, as needed.
-// Since the SRC behind the fifo eats stereo 16-bit data at a sample rate of 32khz,
-// that is, 4 bytes at 32 khz, which is 32 bytes at 4 khz. We should thus schedule an
-// event that runs at 4khz, that eats audio from the fifo, and all the rest will follow.
-// Then we will have homebrew audio.
+// The SRC behind the fifo eats stereo 16-bit data at a sample rate of 32khz,
+// that is, 4 bytes at 32 khz, which is 32 bytes at 4 khz. We thereforce schedule an
+// event that runs at 4khz, that eats audio from the fifo. Thus, we have homebrew audio.
// The AID interrupt is set when the fifo STARTS a transfer. It latches address and count
// into internal registers and starts copying. This means that the interrupt handler can simply
diff --git a/Source/Core/Core/Src/HW/Memmap.cpp b/Source/Core/Core/Src/HW/Memmap.cpp
index f76dc760d5..a2155f0f2e 100644
--- a/Source/Core/Core/Src/HW/Memmap.cpp
+++ b/Source/Core/Core/Src/HW/Memmap.cpp
@@ -156,6 +156,16 @@ void InitHWMemFuncs()
hwRead16 [i] = HW_Default_Read<u16&>;
hwRead32 [i] = HW_Default_Read<u32&>;
hwRead64 [i] = HW_Default_Read<u64&>;
+
+ // To prevent Dolphin from crashing when running Wii executables in Gc mode.
+ hwWriteWii8 [i] = HW_Default_Write<u8>;
+ hwWriteWii16[i] = HW_Default_Write<u16>;
+ hwWriteWii32[i] = HW_Default_Write<u32>;
+ hwWriteWii64[i] = HW_Default_Write<u64>;
+ hwReadWii8 [i] = HW_Default_Read<u8&>;
+ hwReadWii16 [i] = HW_Default_Read<u16&>;
+ hwReadWii32 [i] = HW_Default_Read<u32&>;
+ hwReadWii64 [i] = HW_Default_Read<u64&>;
}
for (int i = 0; i < BLOCKSIZE; i++)
diff --git a/Source/Core/Core/Src/LogManager.cpp b/Source/Core/Core/Src/LogManager.cpp
index 0ccad1e621..1daf0f8a57 100644
--- a/Source/Core/Core/Src/LogManager.cpp
+++ b/Source/Core/Core/Src/LogManager.cpp
@@ -14,6 +14,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+
#include <stdio.h>
#include "Common.h"
diff --git a/Source/Core/Core/Src/LogManager.h b/Source/Core/Core/Src/LogManager.h
index 1fb10be8cd..f36adfe96a 100644
--- a/Source/Core/Core/Src/LogManager.h
+++ b/Source/Core/Core/Src/LogManager.h
@@ -14,6 +14,10 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+
+
+// Dolphin Logging framework. Needs a good ol' spring cleaning methinks.
+
#ifndef _LOGMANAGER_H
#define _LOGMANAGER_H
diff --git a/Source/Core/Core/Src/MemTools.cpp b/Source/Core/Core/Src/MemTools.cpp
index 154db1c499..e5c04982bc 100644
--- a/Source/Core/Core/Src/MemTools.cpp
+++ b/Source/Core/Core/Src/MemTools.cpp
@@ -15,7 +15,9 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-// TODO: create a OS-neutral version of this file and put it in Common.
+
+// TODO: create a working OS-neutral version of this file and put it in Common.
+
#ifdef _WIN32
diff --git a/Source/Core/Core/Src/MemTools.h b/Source/Core/Core/Src/MemTools.h
index c3d847bbcf..93053f56fd 100644
--- a/Source/Core/Core/Src/MemTools.h
+++ b/Source/Core/Core/Src/MemTools.h
@@ -20,52 +20,11 @@
#include "Common.h"
-typedef u32 EAddr;
namespace EMM
{
- enum WR
- {
- Read = 1,
- Write = 2,
- Execute = 4
- };
-
- enum WatchType
- {
- Oneshot,
- Continuous
- };
-
- enum AccessSize
- {
- Access8,
- Access16,
- Access32,
- Access64,
- Access128
- };
-
- typedef int WatchID;
- typedef void (*WatchCallback)(EAddr addr, AccessSize size, WR action, WatchID id);
-
- //Useful to emulate low-used I/O, and caching of memory resources that can change any time
- WatchID AddWatchRegion(EAddr startAddr, EAddr endAddr, WR watchFor, WatchType type, WatchCallback callback, u64 userData);
- void RemoveWatchRegion(WatchID id);
- void ClearWatches();
-
- //Call this on your main emulator thread, with your mainloop in codeToRun
-
+ typedef u32 EAddr;
void InstallExceptionHandler();
}
-u8 ReadHandler8(EAddr address);
-u16 ReadHandler16(EAddr address);
-u32 ReadHandler32(EAddr address);
-u64 ReadHandler64(EAddr address);
-void WriteHandler8(EAddr address, u8 value);
-void WriteHandler16(EAddr address, u16 value);
-void WriteHandler32(EAddr address, u32 value);
-void WriteHandler64(EAddr address, u64 value);
-
#endif
diff --git a/Source/Core/Core/Src/PatchEngine.cpp b/Source/Core/Core/Src/PatchEngine.cpp
index df0182f8c1..cd8e94e4e0 100644
--- a/Source/Core/Core/Src/PatchEngine.cpp
+++ b/Source/Core/Core/Src/PatchEngine.cpp
@@ -16,15 +16,15 @@
// 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)
-// 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 <string>
#include <vector>
@@ -36,9 +36,14 @@
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;
@@ -113,8 +118,5 @@ void PatchEngine_ApplyFramePatches()
void PatchEngine_ApplyARPatches()
{
- for (std::vector<ARCode>::const_iterator iter = arCodes.begin(); iter != arCodes.end(); ++iter) {
- if (iter->active)
- RunActionReplayCode(*iter, false);
- }
+ ActionReplayRunAllActive();
} \ No newline at end of file
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
index a047f8c73e..793c5d9ed8 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
@@ -39,130 +39,77 @@ using namespace Gen;
using namespace PowerPC;
extern int blocksExecuted;
-//X64 Win64 calling convention:
-// Parameters in RCX RDX R8 R9
-// Volatile RAX R10 R11
-// Non volatile (must be saved)
-// RBX RSI RDI R12 R13 R14 R15
-//Register allocation:
+// Dolphin's PowerPC->x86 JIT dynamic recompiler
+// All code by ector (hrydgard)
+// Features:
+// * x86 & x64 support, lots of shared code.
+// * Basic block linking
+// * Fast dispatcher
-//RAX - Generic quicktemp register
-//RBX - point to base of memory map
-//RSI RDI R12 R13 R14 R15 - free for allocation
-//RCX RDX R8 R9 R10 R11 - allocate in emergencies. These need to be flushed before functions are called.
-//RSP - stack pointer, do not generally use, very dangerous
-//RBP - ?
+// Unfeatures:
+// * Does not recompile all instructions. Often falls back to inserting a CALL to the corresponding JIT function.
-//RCX RDX R8 R9 are function parameters. We will only call 1 and 2 param functions from compiled code anyway.
-//Calling out to the interpreter needs only to flush the volatile regs!
+// Various notes below
-//IMPORTANT:
-//Make sure that all generated code and all emulator state sits under the 2GB boundary so that
-//RIP addressing can be used easily. Windows will always allocate static code under the 2GB boundary.
-//Also make sure to use VirtualAlloc and specify EXECUTE permission.
+// Register allocation
+// RAX - Generic quicktemp register
+// RBX - point to base of memory map
+// RSI RDI R12 R13 R14 R15 - free for allocation
+// RCX RDX R8 R9 R10 R11 - allocate in emergencies. These need to be flushed before functions are called.
+// RSP - stack pointer, do not generally use, very dangerous
+// RBP - ?
-//Since RIP stores/loads will not be possible to the high memory area, we will have to use
-//a statically allocated base pointer in a register, and use displacement addressing off of that.
-//A candidate for this is a non vol like R15, since we would not like to have to do a RIP load
-//to restore it all the time.
-//No wait a minute, why not just keep the unprotected mappings below 2GB?
+// IMPORTANT:
+// Make sure that all generated code and all emulator state sits under the 2GB boundary so that
+// RIP addressing can be used easily. Windows will always allocate static code under the 2GB boundary.
+// Also make sure to use VirtualAlloc and specify EXECUTE permission.
-//Another question to be addressed is if it is smart to have a static pointer reg to the base
-//of the PowerPC reg area.
-//Pro: Smaller accesses for GPR (8-bit displacement good enough only for gprs)
-//Con: A taken nonvol register (may not be so bad)
+// Open questions
+// * Should there be any statically allocated registers? r3, r4, r5, r8, r0 come to mind.. maybe sp
+// * Does it make sense to finish off the remaining non-jitted instructions? Seems we are hitting diminishing returns.
+// * Why is the FPU exception handling not working 100%? Several games still get corrupted floating point state.
+// This can even be seen in one homebrew Wii demo - RayTracer.elf
-//Should there be any statically allocated registers? r3, r4, r5, r8, r0 come to mind.. maybe sp
-
-//When calling external functions, only volatile regs need to be saved.
-//This means that they should be allocated last. RAX should probably never
-//be allocated, it should just be a temporary to do non-destructive trinary ops.
-
-//However, for the above to work and be a win, we need to store away the non volatiles before
-//entering "JIT space". However, once we're there, it will be a win.
-//Also, JIT space will need to be surrounded with stack adjusting, since functions will be called.
+// Other considerations
//Many instructions have shorter forms for EAX. However, I believe their performance boost
//will be as small to be negligble, so I haven't dirtied up the code with that. AMD recommends it in their
//optimization manuals, though.
-//IDEA: FPU exception emulation support by having all fpu blocks writeNTA to a spot in memory that
-//is protected if FPU exceptions are enabled. The exception handler would then have to run the
-//interpreter until rfi, at which point control can be returned. Of course all regs need to be
-//flushed before this happens. This method is branch free but does a memory write or read in the fast case.
-// Probably not worthwhile, a test/jz in every fpu block should be enough.
-
-//Block linking is needed. Reserve space at the end of every block for a full 5-byte jmp. Save 16-bit offsets
-//from the starts of each block, marking the exits so that they can be nicely patched at any time.
-
-//Blocks do NOT use call/ret, they only jmp to each other and to the dispatcher when necessary.
+// We support block linking. Reserve space at the exits of every block for a full 5-byte jmp. Save 16-bit offsets
+// from the starts of each block, marking the exits so that they can be nicely patched at any time.
-//All blocks that can be precompiled will be precompiled. Code will be memory protected - any write will mark
-//the region as non-compilable, and all links to the page will be torn out and replaced with dispatcher jmps.
+// * Blocks do NOT use call/ret, they only jmp to each other and to the dispatcher when necessary.
-//Alternatively, icbi instruction SHOULD mark where we can't compile
+// All blocks that can be precompiled will be precompiled. Code will be memory protected - any write will mark
+// the region as non-compilable, and all links to the page will be torn out and replaced with dispatcher jmps.
-//IDEA: All major memory altering events (not singular accesses) should call Gfx::Snoop to let it know that memory chagned.
+// Alternatively, icbi instruction SHOULD mark where we can't compile
-//Seldom-happening events will be handled by adding a decrement of a counter to all blr instructions (which are
-//expensive anyway since we need to return to dispatcher, except when they can be predicted).
-
-//TODO:
-
-// TODO: SERIOUS synchronization problem with the video plugin setting tokens and breakpoints!!!
-// Somewhat fixed by disabling idle skipping when certain interrupts are enabled
-// This is no permantent reliable fix
+// Seldom-happening events will be handled by adding a decrement of a counter to all blr instructions (which are
+// expensive anyway since we need to return to dispatcher, except when they can be predicted).
+// TODO: SERIOUS synchronization problem with the video plugin setting tokens and breakpoints in dual core mode!!!
+// Somewhat fixed by disabling idle skipping when certain interrupts are enabled
+// This is no permantent reliable fix
// TODO: Zeldas go whacko when you hang the gfx thread
-// Plan: 1. Byteswap Dolphin DONE!
-// 2. Fix timing WORKING
-// 3. Lay groundwork for x64 JIT WORKING
-// 4. Get OneTri up to 60fps, and check compatibility from time to time (yea right) ????
-// 5. Add block linking to JIT << NOT SO IMPORTANT
-// 6. Optimize GFX plugin to hell << IMPORTANT
-// 7. Watch Zelda do 20 fps.
-// 8. Watch Zelda TP do 30 fps. DONE :D
+// Idea - Accurate exception handling
+// Compute register state at a certain instruction by running the JIT in "dry mode", and stopping at the right place.
+// Not likely to be done :P
-//Optimizations -
+
+// Optimization Ideas -
/*
- * Assume SP is in main RAM (in Wii mode too?)
+ * Assume SP is in main RAM (in Wii mode too?) - partly done
* Assume all floating point loads and double precision loads+stores are to/from main ram
- (single precision can be used in write gather)
- (this is valid on Wii too when using the VM emulator)
-
+ (single precision can be used in write gather pipe, specialized fast check added)
* AMD only - use movaps instead of movapd when loading ps from memory?
* HLE functions like floorf, sin, memcpy, etc - they can be much faster
- * Optimal sequence to store floats
- * TODO: find optimal sequence to store doubles as floats
-
- cvtpd2ps xmm0, xmm0
- movss xmm0, f
- movss tempspace, xmm0
- mov eax, tempspace
- bswap eax
- mov [edi], eax
-
- I think pshufb does it faster.
-
-BLOCK EXIT DESIGN
-
-TEST whatever
-JZ skip
-MOV NPC, exit1
-JMP dispatcher
-skip:
-MOV NPC, exit2
-JMP dispatcher
-
-This can be patched into (when both exits are known):
-JZ exit2
-JMP exit1
-
-The problem is, we still need to fit the downcount somewhere...
+
Low hanging fruit:
stfd -- guaranteed in memory
cmpl
@@ -186,9 +133,6 @@ cntlzwx
bcctrx
WriteBigEData
-
-detect immediates in stb stw sth
-
TODO
lha
srawx
@@ -196,29 +140,18 @@ addic_rc
addex
subfcx
subfex
-000000000A42BD7F mov ecx,0FCBF41BAh
-000000000A42BD85 call CInterpreter::fmaddx (5BA3A0h)
-000000000A42BD8A mov ecx,0FC8D0132h
-000000000A42BD90 call CInterpreter::fmulx (5BA540h)
-000000000A42BD95 mov ecx,0FC85202Ah
-000000000A42BD9B call CInterpreter::faddx (5BA220h)
-000000000A42BDA0 mov ecx,0FC81113Ah
-000000000A42BDA6 call CInterpreter::fmaddx (5BA3A0h)
-000000000A42C11A call CInterpreter::fnegx (5BA0B0h)
-000000000A42C604 call CInterpreter::frspx (5BA170h)
-000000000A428FDC call CInterpreter::ps_sum0 (5C9730h)
-000000000A428FE1 mov ecx,0FCA02034h
-000000000A428FE7 call CInterpreter::frsqrtex (5BA7C0h)
-000000000A429062 call CInterpreter::ps_muls0 (5C9820h)
-000000000A4290AF call CInterpreter::psq_st (5C9DF0h)
+
+fmaddx
+fmulx
+faddx
+fnegx
+frspx
+frsqrtex
+ps_sum0
*/
-// Accurate exception handling
-// Compute register state at a certain instruction by running the JIT in "dry mode", and stopping at the right place.
-// Not likely to be done :P
-// Evil
namespace CPUCompare
{
extern u32 m_BlockStart;
@@ -232,7 +165,7 @@ namespace Jit64
void Init()
{
- jo.optimizeStack = true;
+ jo.optimizeStack = false;
jo.enableBlocklink = true; // Speed boost, but not 100% safe
#ifdef _M_X64
jo.enableFastMem = Core::GetStartupParameter().bUseFastMem;
@@ -243,6 +176,7 @@ namespace Jit64
jo.fpAccurateFlags = true;
jo.optimizeGatherPipe = true;
jo.interpretFPU = false;
+ jo.fastInterrupts = false;
}
void WriteCallInterpreter(UGeckoInstruction _inst)
@@ -280,6 +214,7 @@ namespace Jit64
static const bool ImHereDebug = false;
static const bool ImHereLog = false;
static std::map<u32, int> been_here;
+
void ImHere()
{
static FILE *f = 0;
@@ -378,9 +313,11 @@ namespace Jit64
const u8 *start = AlignCode4(); //TODO: Test if this or AlignCode16 make a difference from GetCodePtr
b.checkedEntry = start;
b.runCount = 0;
+
+ // Downcount flag check. The last block decremented downcounter, and the flag should still be available.
FixupBranch skip = J_CC(CC_NBE);
MOV(32, M(&PC), Imm32(js.blockStart));
- JMP(Asm::doTiming, true);
+ JMP(Asm::doTiming, true); // downcount hit zero - go doTiming.
SetJumpTarget(skip);
const u8 *normalEntry = GetCodePtr();
@@ -396,6 +333,17 @@ namespace Jit64
SetJumpTarget(b1);
}
+ if (false && jo.fastInterrupts)
+ {
+ // This does NOT yet work.
+ TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF));
+ FixupBranch b1 = J_CC(CC_Z);
+ MOV(32, M(&PC), Imm32(js.blockStart));
+ JMP(Asm::testExceptions, true);
+ SetJumpTarget(b1);
+ }
+
+ // Conditionally add profiling code.
if (Profiler::g_ProfileBlocks) {
ADD(32, M(&b.runCount), Imm8(1));
#ifdef _WIN32
@@ -439,13 +387,12 @@ namespace Jit64
}
// const GekkoOpInfo *info = GetOpInfo();
- // if (js.isLastInstruction)
+
if (jo.interpretFPU && PPCTables::UsesFPU(ops[i].inst))
Default(ops[i].inst);
else
PPCTables::CompileInstruction(ops[i].inst);
- // else
- // Default(ops[i].inst);
+
gpr.SanityCheck();
fpr.SanityCheck();
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32)
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
index e2cb716055..6dbae8b73e 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
@@ -15,9 +15,9 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-// Low hanging fruit:
-// all used in zelda
-// negx
+// ========================
+// See comments in Jit.cpp.
+// ========================
#ifndef _JIT_H
#define _JIT_H
@@ -26,14 +26,10 @@
#include "JitCache.h"
#include "x64Emitter.h"
-
-// =======================================================================================
// Enable or disable JIT off options. All the if() checks in the JIT functions may result in a
// speed drop. However it should barely be noticable as the code is recompiled rarely.
-// --------------
#define JIT_OFF_OPTIONS
-
namespace Jit64
{
struct JitStats
@@ -80,6 +76,7 @@ namespace Jit64
bool enableFastMem;
bool optimizeGatherPipe;
bool interpretFPU;
+ bool fastInterrupts;
};
extern JitState js;
diff --git a/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp
index b9a5705b97..131b82707f 100644
--- a/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp
+++ b/Source/Core/Core/Src/PowerPC/PPCAnalyst.cpp
@@ -30,17 +30,20 @@
// and what functions calls it. That is, we will have an incomplete call graph,
// but only missing indirect branches.
-// The results of this analysis are currently not really used for anything, other than
-// finding function boundaries so that we can find, fingerprint and detect library functions.
+// The results of this analysis is displayed in the code browsing sections at the bottom left
+// of the disassembly window (debugger).
+
+// It is also useful for finding function boundaries so that we can find, fingerprint and detect library functions.
+// We don't do this much currently. Only for the special case Super Monkey Ball.
namespace PPCAnalyst {
using namespace std;
-// VERY ugly. TODO: remove.
PPCAnalyst::CodeOp *codebuffer;
-enum {
+enum
+{
CODEBUFFER_SIZE = 32000,
};
diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp
index 55e4856345..dae64e3e4c 100644
--- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp
+++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp
@@ -41,8 +41,6 @@ struct GekkoOPTemplate
int runCount;
};
-// The eventual goal is to be able to constify as much as possible in this file.
-// Currently, the main obstacle is runCount above.
static GekkoOPInfo *m_infoTable[64];
static GekkoOPInfo *m_infoTable4[1024];
static GekkoOPInfo *m_infoTable19[1024];
diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.h b/Source/Core/Core/Src/PowerPC/PPCTables.h
index 8aecbc2115..15d7b922dc 100644
--- a/Source/Core/Core/Src/PowerPC/PPCTables.h
+++ b/Source/Core/Core/Src/PowerPC/PPCTables.h
@@ -46,7 +46,6 @@ enum
FL_CHECKEXCEPTIONS = (1<<16),
};
-
enum
{
OPTYPE_INVALID ,
diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp
index b9f6dd643c..62a7eae02b 100644
--- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp
+++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp
@@ -37,269 +37,271 @@
namespace PowerPC
{
- // STATE_TO_SAVE
- PowerPCState GC_ALIGNED16(ppcState);
- volatile CPUState state = CPU_STEPPING;
- static CoreMode mode;
+// STATE_TO_SAVE
+PowerPCState GC_ALIGNED16(ppcState);
+volatile CPUState state = CPU_STEPPING;
- void DoState(PointerWrap &p)
+static CoreMode mode;
+
+void DoState(PointerWrap &p)
+{
+ p.Do(ppcState);
+}
+
+void ResetRegisters()
+{
+ for (int i = 0; i < 32; i++)
{
- p.Do(ppcState);
+ ppcState.gpr[i] = 0;
+ riPS0(i) = 0;
+ riPS1(i) = 0;
}
- void ResetRegisters()
- {
- for (int i = 0; i < 32; i++)
- {
- ppcState.gpr[i] = 0;
- riPS0(i) = 0;
- riPS1(i) = 0;
- }
+ memset(ppcState.spr, 0, sizeof(ppcState.spr));
- memset(ppcState.spr, 0, sizeof(ppcState.spr));
+ ppcState.cr = 0;
+ ppcState.fpscr = 0;
+ ppcState.pc = 0;
+ ppcState.npc = 0;
+ ppcState.Exceptions = 0;
- ppcState.cr = 0;
- ppcState.fpscr = 0;
- ppcState.pc = 0;
- ppcState.npc = 0;
- ppcState.Exceptions = 0;
+ TL = 0;
+ TU = 0;
- TL = 0;
- TU = 0;
+ ppcState.msr = 0;
+ rDEC = 0xFFFFFFFF;
+}
- ppcState.msr = 0;
- rDEC = 0xFFFFFFFF;
- }
+void Init()
+{
+ enum {
+ FPU_PREC_24 = 0 << 8,
+ FPU_PREC_53 = 2 << 8,
+ FPU_PREC_64 = 3 << 8,
+ FPU_PREC_MASK = 3 << 8,
+ };
+ #ifdef _M_IX86
+ // sets the floating-point lib to 53-bit
+ // PowerPC has a 53bit floating pipeline only
+ // eg: sscanf is very sensitive
+#ifdef _WIN32
+ _control87(_PC_53, MCW_PC);
+#else
+ unsigned short _mode;
+ asm ("fstcw %0" : : "m" (_mode));
+ _mode = (_mode & ~FPU_PREC_MASK) | FPU_PREC_53;
+ asm ("fldcw %0" : : "m" (_mode));
+#endif
+#else
+ //x64 doesn't need this - fpu is done with SSE
+ //but still - set any useful sse options here
+#endif
- void Init()
- {
- enum {
- FPU_PREC_24 = 0 << 8,
- FPU_PREC_53 = 2 << 8,
- FPU_PREC_64 = 3 << 8,
- FPU_PREC_MASK = 3 << 8,
- };
- #ifdef _M_IX86
- // sets the floating-point lib to 53-bit
- // PowerPC has a 53bit floating pipeline only
- // eg: sscanf is very sensitive
- #ifdef _WIN32
- _control87(_PC_53, MCW_PC);
- #else
- unsigned short _mode;
- asm ("fstcw %0" : : "m" (_mode));
- _mode = (_mode & ~FPU_PREC_MASK) | FPU_PREC_53;
- asm ("fldcw %0" : : "m" (_mode));
- #endif
- #else
- //x64 doesn't need this - fpu is done with SSE
- //but still - set any useful sse options here
- #endif
-
- ResetRegisters();
- PPCTables::InitTables();
-
- // Initialize both execution engines ...
- Interpreter::Init();
- Jit64::Core::Init();
- // ... but start as interpreter by default.
- mode = MODE_INTERPRETER;
- state = CPU_STEPPING;
- }
+ ResetRegisters();
+ PPCTables::InitTables();
- void Shutdown()
- {
- // Shutdown both execution engines. Doesn't matter which one is active.
- Jit64::Core::Shutdown();
- Interpreter::Shutdown();
- }
+ // Initialize both execution engines ...
+ Interpreter::Init();
+ Jit64::Core::Init();
+ // ... but start as interpreter by default.
+ mode = MODE_INTERPRETER;
+ state = CPU_STEPPING;
+}
- void SetMode(CoreMode new_mode)
- {
- if (new_mode == mode)
- return; // We don't need to do anything.
+void Shutdown()
+{
+ // Shutdown both execution engines. Doesn't matter which one is active.
+ Jit64::Core::Shutdown();
+ Interpreter::Shutdown();
+}
- mode = new_mode;
- switch (mode)
- {
- case MODE_INTERPRETER: // Switching from JIT to interpreter
- Jit64::ClearCache(); // Remove all those nasty JIT patches.
- break;
+void SetMode(CoreMode new_mode)
+{
+ if (new_mode == mode)
+ return; // We don't need to do anything.
- case MODE_JIT: // Switching from interpreter to JIT.
- // Don't really need to do much. It'll work, the cache will refill itself.
- break;
- }
+ mode = new_mode;
+ switch (mode)
+ {
+ case MODE_INTERPRETER: // Switching from JIT to interpreter
+ Jit64::ClearCache(); // Remove all those nasty JIT patches.
+ break;
+
+ case MODE_JIT: // Switching from interpreter to JIT.
+ // Don't really need to do much. It'll work, the cache will refill itself.
+ break;
}
+}
- void SingleStep()
+void SingleStep()
+{
+ switch (mode)
{
- switch (mode)
- {
- case MODE_INTERPRETER:
- Interpreter::SingleStep();
- break;
- case MODE_JIT:
- Jit64::Core::SingleStep();
- break;
- }
+ case MODE_INTERPRETER:
+ Interpreter::SingleStep();
+ break;
+ case MODE_JIT:
+ Jit64::Core::SingleStep();
+ break;
}
+}
- void RunLoop()
+void RunLoop()
+{
+ state = CPU_RUNNING;
+ switch (mode)
{
- state = CPU_RUNNING;
- switch (mode)
- {
- case MODE_INTERPRETER:
- Interpreter::Run();
- break;
- case MODE_JIT:
- Jit64::Core::Run();
- break;
- }
- Host_UpdateDisasmDialog();
+ case MODE_INTERPRETER:
+ Interpreter::Run();
+ break;
+ case MODE_JIT:
+ Jit64::Core::Run();
+ break;
}
+ Host_UpdateDisasmDialog();
+}
- void Start()
+void Start()
+{
+ state = Core::g_CoreStartupParameter.bEnableDebugging ? CPU_RUNNINGDEBUG : CPU_RUNNING;
+ if (Core::bReadTrace || Core::bWriteTrace)
{
- state = Core::g_CoreStartupParameter.bEnableDebugging ? CPU_RUNNINGDEBUG : CPU_RUNNING;
- if (Core::bReadTrace || Core::bWriteTrace)
- {
- state = CPU_RUNNING;
- }
- Host_UpdateDisasmDialog();
+ state = CPU_RUNNING;
}
+ Host_UpdateDisasmDialog();
+}
+
+void Pause()
+{
+ state = CPU_STEPPING;
+ Host_UpdateDisasmDialog();
+}
+
+void Stop()
+{
+ state = CPU_POWERDOWN;
+ Host_UpdateDisasmDialog();
+}
- void Pause()
+void CheckExceptions()
+{
+ // This check is unnecessary in JIT mode. However, it probably doesn't really hurt.
+ if (!ppcState.Exceptions)
+ return;
+
+ // TODO(ector):
+ // gcemu uses the mask 0x87C0FFFF instead of 0x0780FF77
+ // Investigate!
+
+ if (ppcState.Exceptions & EXCEPTION_FPU_UNAVAILABLE)
+ {
+ //This happens a lot - Gamecube OS uses deferred FPU context switching
+ SRR0 = PC; // re-execute the instruction
+ SRR1 = MSR & 0x0780FF77;
+ NPC = 0x80000800;
+
+ LOG(GEKKO, "EXCEPTION_FPU_UNAVAILABLE");
+ ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE;
+ SRR1 |= 0x02; //recoverable
+ }
+ else if (ppcState.Exceptions & EXCEPTION_SYSCALL)
+ {
+ SRR0 = NPC; // execute next instruction when we come back from handler
+ SRR1 = MSR & 0x0780FF77;
+ NPC = 0x80000C00;
+
+ LOG(GEKKO, "EXCEPTION_SYSCALL (PC=%08x)",PC);
+ ppcState.Exceptions &= ~EXCEPTION_SYSCALL;
+ SRR1 |= 0x02; //recoverable
+ }
+ else if (ppcState.Exceptions & EXCEPTION_DSI)
{
- state = CPU_STEPPING;
- Host_UpdateDisasmDialog();
+ SRR0 = PC; // re-execute the instruction
+ SRR1 = MSR & 0x0780FF77;
+ NPC = 0x80000300;
+
+ LOG(GEKKO, "EXCEPTION_DSI");
+ ppcState.Exceptions &= ~EXCEPTION_DSI;
+ //SRR1 |= 0x02; //make recoverable ?
}
+ else if (ppcState.Exceptions & EXCEPTION_ISI)
+ {
+ SRR0 = PC;
+ SRR1 = (MSR & 0x0780FF77) | 0x40000000;
+ NPC = 0x80000400;
- void Stop()
+ LOG(GEKKO, "EXCEPTION_ISI");
+ ppcState.Exceptions &= ~EXCEPTION_ISI;
+ //SRR1 |= 0x02; //make recoverable ?
+ }
+ else if (ppcState.Exceptions & EXCEPTION_ALIGNMENT)
{
- state = CPU_POWERDOWN;
- Host_UpdateDisasmDialog();
+ //This never happens ATM
+ SRR0 = NPC;
+ SRR1 = MSR & 0x0780FF77;
+ NPC = 0x80000600;
+
+ LOG(GEKKO, "EXCEPTION_ALIGNMENT");
+ ppcState.Exceptions &= ~EXCEPTION_ALIGNMENT;
+ //SRR1 |= 0x02; //make recoverable ?
}
-
- void CheckExceptions()
+
+ // EXTERNAL INTTERUPT
+ else if (MSR & 0x0008000)
{
- // This check is unnecessary in JIT mode. However, it probably doesn't really hurt.
- if (!ppcState.Exceptions)
- return;
-
- // TODO(ector):
- // gcemu uses the mask 0x87C0FFFF instead of 0x0780FF77
- // Investigate!
-
- if (ppcState.Exceptions & EXCEPTION_FPU_UNAVAILABLE)
- {
- //This happens a lot - Gamecube OS uses deferred FPU context switching
- SRR0 = PC; // re-execute the instruction
- SRR1 = MSR & 0x0780FF77;
- NPC = 0x80000800;
-
- LOG(GEKKO, "EXCEPTION_FPU_UNAVAILABLE");
- ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE;
- SRR1 |= 0x02; //recoverable
- }
- else if (ppcState.Exceptions & EXCEPTION_SYSCALL)
- {
- SRR0 = NPC; // execute next instruction when we come back from handler
- SRR1 = MSR & 0x0780FF77;
- NPC = 0x80000C00;
-
- LOG(GEKKO, "EXCEPTION_SYSCALL (PC=%08x)",PC);
- ppcState.Exceptions &= ~EXCEPTION_SYSCALL;
- SRR1 |= 0x02; //recoverable
- }
- else if (ppcState.Exceptions & EXCEPTION_DSI)
+ if (ppcState.Exceptions & EXCEPTION_EXTERNAL_INT)
{
- SRR0 = PC; // re-execute the instruction
- SRR1 = MSR & 0x0780FF77;
- NPC = 0x80000300;
+ // Pokemon gets this "too early", it hasn't a handler yet
+ ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT; // clear exception
- LOG(GEKKO, "EXCEPTION_DSI");
- ppcState.Exceptions &= ~EXCEPTION_DSI;
- //SRR1 |= 0x02; //make recoverable ?
- }
- else if (ppcState.Exceptions & EXCEPTION_ISI)
- {
- SRR0 = PC;
- SRR1 = (MSR & 0x0780FF77) | 0x40000000;
- NPC = 0x80000400;
+ SRR0 = NPC;
+ NPC = 0x80000500;
+ SRR1 = (MSR & 0x0780FF77);
+
+ LOG(GEKKO, "EXCEPTION_EXTERNAL_INT");
- LOG(GEKKO, "EXCEPTION_ISI");
- ppcState.Exceptions &= ~EXCEPTION_ISI;
- //SRR1 |= 0x02; //make recoverable ?
+ SRR1 |= 0x02; //set it to recoverable
+ _dbg_assert_msg_(GEKKO, (SRR1 & 0x02) != 0, "GEKKO", "EXTERNAL_INT unrecoverable???"); // unrecoverable exception !?!
}
- else if (ppcState.Exceptions & EXCEPTION_ALIGNMENT)
+ else if (ppcState.Exceptions & EXCEPTION_DECREMENTER)
{
- //This never happens ATM
SRR0 = NPC;
- SRR1 = MSR & 0x0780FF77;
- NPC = 0x80000600;
+ SRR1 = MSR & 0x0000FF77;
+ NPC = 0x80000900;
- LOG(GEKKO, "EXCEPTION_ALIGNMENT");
- ppcState.Exceptions &= ~EXCEPTION_ALIGNMENT;
- //SRR1 |= 0x02; //make recoverable ?
+ ppcState.Exceptions &= ~EXCEPTION_DECREMENTER;
+
+ LOG(GEKKO, "EXCEPTION_DECREMENTER");
+ SRR1 |= 0x02; //make recoverable
}
-
- // EXTERNAL INTTERUPT
- else if (MSR & 0x0008000)
+ else
{
- if (ppcState.Exceptions & EXCEPTION_EXTERNAL_INT)
- {
- // Pokemon gets this "too early", it hasn't a handler yet
- ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT; // clear exception
-
- SRR0 = NPC;
- NPC = 0x80000500;
- SRR1 = (MSR & 0x0780FF77);
-
- LOG(GEKKO, "EXCEPTION_EXTERNAL_INT");
-
- SRR1 |= 0x02; //set it to recoverable
- _dbg_assert_msg_(GEKKO, (SRR1 & 0x02) != 0, "GEKKO", "EXTERNAL_INT unrecoverable???"); // unrecoverable exception !?!
- }
- else if (ppcState.Exceptions & EXCEPTION_DECREMENTER)
- {
- SRR0 = NPC;
- SRR1 = MSR & 0x0000FF77;
- NPC = 0x80000900;
-
- ppcState.Exceptions &= ~EXCEPTION_DECREMENTER;
-
- LOG(GEKKO, "EXCEPTION_DECREMENTER");
- SRR1 |= 0x02; //make recoverable
- }
- else
- {
- _dbg_assert_msg_(GEKKO, 0, "Unknown EXT interrupt: Exceptions == %08x", ppcState.Exceptions);
- LOG(GEKKO, "Unknown EXTERNAL INTERRUPT exception: Exceptions == %08x", ppcState.Exceptions);
- }
+ _dbg_assert_msg_(GEKKO, 0, "Unknown EXT interrupt: Exceptions == %08x", ppcState.Exceptions);
+ LOG(GEKKO, "Unknown EXTERNAL INTERRUPT exception: Exceptions == %08x", ppcState.Exceptions);
}
- MSR &= ~0x0008000; // clear EE-bit so interrupts aren't possible anymore
}
+ MSR &= ~0x0008000; // clear EE-bit so interrupts aren't possible anymore
+}
- void OnIdle(u32 _uThreadAddr)
+void OnIdle(u32 _uThreadAddr)
+{
+ u32 nextThread = Memory::Read_U32(_uThreadAddr);
+ //do idle skipping
+ if (nextThread == 0)
{
- u32 nextThread = Memory::Read_U32(_uThreadAddr);
- //do idle skipping
- if (nextThread == 0)
- {
- CoreTiming::Idle();
- }
+ CoreTiming::Idle();
}
- //DualCore OnIdle
- void OnIdleDC(void)
- {
+}
+
+//DualCore OnIdle
+void OnIdleDC(void)
+{
#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32)
- if (g_hEventOnIdle==NULL) PanicAlert("Idle() -> EventOnIdle NULL");
- if (! SetEvent(g_hEventOnIdle) ) { PanicAlert("Idle() -> SetEvent EventOnIdle failed");}
+ if (g_hEventOnIdle==NULL) PanicAlert("Idle() -> EventOnIdle NULL");
+ if (! SetEvent(g_hEventOnIdle) ) { PanicAlert("Idle() -> SetEvent EventOnIdle failed");}
#endif
- CoreTiming::Idle();
- }
+ CoreTiming::Idle();
}
+} // namespace
diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.h b/Source/Core/Core/Src/PowerPC/PowerPC.h
index b97b79ee0c..ab3dbf2605 100644
--- a/Source/Core/Core/Src/PowerPC/PowerPC.h
+++ b/Source/Core/Core/Src/PowerPC/PowerPC.h
@@ -31,6 +31,7 @@ namespace PowerPC
MODE_JIT,
};
+ // This contains the entire state of the emulated PowerPC "Gekko" CPU.
struct GC_ALIGNED64(PowerPCState)
{
u32 mojs[128]; // Try to isolate the regs from other variables in the cache.
@@ -88,7 +89,7 @@ namespace PowerPC
void OnIdleDC(void);
}
-// Special registers
+// Easy register access macros.
#define HID2 ((UReg_HID2&)PowerPC::ppcState.spr[SPR_HID2])
#define DMAU (*(UReg_DMAU*)&PowerPC::ppcState.spr[SPR_DMAU])
#define DMAL (*(UReg_DMAL*)&PowerPC::ppcState.spr[SPR_DMAL])
@@ -115,15 +116,16 @@ namespace PowerPC
#define TL PowerPC::ppcState.spr[SPR_TL]
#define TU PowerPC::ppcState.spr[SPR_TU]
-
#define rPS0(i) (*(double*)(&PowerPC::ppcState.ps[i][0]))
#define rPS1(i) (*(double*)(&PowerPC::ppcState.ps[i][1]))
#define riPS0(i) (*(u64*)(&PowerPC::ppcState.ps[i][0]))
#define riPS1(i) (*(u64*)(&PowerPC::ppcState.ps[i][1]))
-// #define DMAU PowerPC::ppcState.Helper[SPR_DMAU ]
-// #define DMAL PowerPC::ppcState.Helper[SPR_DMAL ]
+
+// Wrappers to make it easier to in the future completely replace the storage of CR and Carry bits
+// to something more x86-friendly. These are not used 100% consistently yet - and if we do this, we
+// need the corresponding stuff on the JIT side too.
inline void SetCRField(int cr_field, int value) {
PowerPC::ppcState.cr = (PowerPC::ppcState.cr & (~(0xF0000000 >> (cr_field * 4)))) | (value << ((7 - cr_field) * 4));
@@ -153,6 +155,4 @@ inline int GetCarry() {
return XER.CA;
}
-
-
#endif
diff --git a/Source/Core/Core/Src/State.h b/Source/Core/Core/Src/State.h
index 2dc5798c95..90d1c17ef0 100644
--- a/Source/Core/Core/Src/State.h
+++ b/Source/Core/Core/Src/State.h
@@ -15,6 +15,8 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+// Emulator state saving support.
+
#ifndef _STATE_H
#define _STATE_H
diff --git a/Source/Core/Core/Src/VolumeHandler.cpp b/Source/Core/Core/Src/VolumeHandler.cpp
index 908048c397..74016568e3 100644
--- a/Source/Core/Core/Src/VolumeHandler.cpp
+++ b/Source/Core/Core/Src/VolumeHandler.cpp
@@ -31,6 +31,7 @@ void SetVolumeName(const std::string& _rFullPath)
{
if (g_pVolume)
{
+ // This code looks scary. Can the try/catch stuff be removed?
try
{
delete g_pVolume;
@@ -91,4 +92,4 @@ bool IsWii()
return false;
}
-}
+} // namespace
diff --git a/Source/Core/Core/Src/VolumeHandler.h b/Source/Core/Core/Src/VolumeHandler.h
index ce64e59ba5..22d398a139 100644
--- a/Source/Core/Core/Src/VolumeHandler.h
+++ b/Source/Core/Core/Src/VolumeHandler.h
@@ -15,6 +15,9 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+// Disc volume handler. It's here because Wii discs can consist of multiple volumes.
+// GC discs are seen as one big volume.
+
#ifndef _VOLUMEHANDLER_H
#define _VOLUMEHANDLER_H
@@ -22,25 +25,20 @@
#include "CommonTypes.h"
#include "Volume.h"
-
namespace VolumeHandler
{
void SetVolumeName(const std::string& _rFullPath);
-
void SetVolumeDirectory(const std::string& _rFullPath, bool _bIsWii);
u32 Read32(u64 _Offset);
-
bool ReadToPtr(u8* ptr, u64 _dwOffset, u64 _dwLength);
bool IsValid();
-
bool IsWii();
DiscIO::IVolume *GetVolume();
-}
+} // namespace
#endif
-
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/XFB.cpp b/Source/Plugins/Plugin_VideoOGL/Src/XFB.cpp
index a8ffceda52..cdb5fb8932 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/XFB.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/XFB.cpp
@@ -28,7 +28,7 @@
enum {
XFB_WIDTH = 640,
- XFB_HEIGHT = 480, //480,
+ XFB_HEIGHT = 480, // 528 is max height.
XFB_BUF_HEIGHT = 538, //480,
// TODO: figure out what to do with PAL
};