Save states - more boring groundwork. Far from done.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@263 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2008-08-21 23:28:07 +00:00
parent 28edd4d31b
commit 465ee5fd86
45 changed files with 677 additions and 87 deletions

View File

@ -455,6 +455,14 @@
RelativePath=".\Src\ABI.h" RelativePath=".\Src\ABI.h"
> >
</File> </File>
<File
RelativePath=".\Src\ChunkFile.cpp"
>
</File>
<File
RelativePath=".\Src\ChunkFile.h"
>
</File>
<File <File
RelativePath=".\Src\Common.cpp" RelativePath=".\Src\Common.cpp"
> >

View File

@ -0,0 +1,175 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "ChunkFile.h"
#include <stdio.h>
// Not using file mapping, just bog standard fopen and friends. We trust them to be fast
// enough to not be the bottleneck.
ChunkFile::ChunkFile(const char *filename, ChunkFileMode _mode)
{
mode = _mode;
data = 0;
didFail = false;
f = fopen(filename, mode == MODE_WRITE ? "wb" : "rb");
if (!f) {
didFail = true;
return;
}
fseek(f, 0, SEEK_END);
size = ftell(f);
eof = size;
stack_ptr = 0;
}
ChunkFile::~ChunkFile()
{
if (f)
fclose(f);
}
int ChunkFile::ReadInt()
{
int x;
fread(&x, 4, 1, f);
return x;
}
void ChunkFile::WriteInt(int x)
{
fwrite(&x, 4, 1, f);
}
bool ChunkFile::Do(void *ptr, int size)
{
int sz;
switch (mode) {
case MODE_READ:
sz = ReadInt();
if (sz != size)
return false;
fread(ptr, size, 1, f);
fseek(f, ((size + 3) & ~3) - size, SEEK_CUR);
break;
case MODE_WRITE:
WriteInt(size);
fwrite(ptr, size, 1, f);
fseek(f, ((size + 3) & ~3) - size, SEEK_CUR);
break;
case MODE_VERIFY:
sz = ReadInt();
if (sz != size)
return false;
fseek(f, (size + 3) & ~3, SEEK_CUR);
break;
}
return true;
}
//let's get into the business
bool ChunkFile::Descend(const char *cid)
{
int id = *((int*)cid);
if (mode == MODE_READ)
{
bool found = false;
int startPos = ftell(f);
ChunkInfo temp = stack[stack_ptr];
//save information to restore after the next Ascend
stack[stack_ptr].parentStartLocation = startPos;
stack[stack_ptr].parentEOF = eof;
int firstID = 0;
//let's search through children..
while (ftell(f) < eof)
{
stack[stack_ptr].ID = ReadInt();
if (firstID == 0)
firstID = stack[stack_ptr].ID|1;
stack[stack_ptr].length = ReadInt();
stack[stack_ptr].startLocation = ftell(f);
if (stack[stack_ptr].ID == id)
{
found = true;
break;
}
else
{
fseek(f, stack[stack_ptr].length, SEEK_CUR); //try next block
}
}
//if we found nothing, return false so the caller can skip this
if (!found)
{
stack[stack_ptr] = temp;
fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET);
return false;
}
//descend into it
//pos was set inside the loop above
eof = stack[stack_ptr].startLocation + stack[stack_ptr].length;
stack_ptr++;
return true;
}
else
{
//write a chunk id, and prepare for filling in length later
WriteInt(id);
WriteInt(0); //will be filled in by Ascend
stack[stack_ptr].startLocation = ftell(f);
stack_ptr++;
return true;
}
}
//let's ascend out
void ChunkFile::Ascend()
{
if (mode == MODE_READ)
{
//ascend, and restore information
stack_ptr--;
fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET);
eof = stack[stack_ptr].parentEOF;
}
else
{
stack_ptr--;
//now fill in the written length automatically
int posNow = ftell(f);
fseek(f, stack[stack_ptr].startLocation - 4, SEEK_SET);
WriteInt(posNow - stack[stack_ptr].startLocation);
fseek(f, posNow, SEEK_SET);
}
}
int ChunkFile::GetCurrentChunkSize()
{
if (stack_ptr)
return stack[stack_ptr - 1].length;
else
return 0;
}

View File

@ -0,0 +1,109 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _CHUNKFILE_H
#define _CHUNKFILE_H
// Class to read/write/verify hierarchical binary file formats.
// Grabbed from one of my older projects and modified heavily.
// Works more like a RIFF file than a Google Protocol Buffer, for example.
#include "Common.h"
#include <stdio.h>
#include <map>
#include <vector>
//TO REMEMBER WHEN USING:
//EITHER a chunk contains ONLY data
//OR it contains ONLY other chunks
//otherwise the scheme breaks...
class ChunkFile
{
public:
enum ChunkFileMode
{
MODE_READ,
MODE_WRITE,
MODE_VERIFY,
};
private:
struct ChunkInfo
{
int startLocation;
int parentStartLocation;
int parentEOF;
unsigned int ID;
int length;
};
ChunkInfo stack[8];
int stack_ptr;
char *data;
int size;
int eof;
ChunkFileMode mode;
FILE *f;
bool didFail;
// Used for internal bookkeeping only.
int ReadInt();
void WriteInt(int x);
public:
ChunkFile(const char *filename, ChunkFileMode mode);
~ChunkFile();
// Only pass 4-character IDs.
bool Descend(const char *id);
void Ascend();
//void Do(int &i);
//bool Do(std::string &s);
bool Do(void *ptr, int size);
// Future
// bool DoCompressed(void *ptr, int size)
// Store maps to file. Very useful.
template<class T>
void Do(std::map<u32, T> &x) {
}
// Store vectors.
template<class T>
void Do(std::vector<T> &x) {
}
// Handle everything else
template<class T>
void Do(T &x) {
Do((void *)&x, sizeof(x));
}
int GetCurrentChunkSize();
bool failed() {return didFail;}
};
#endif

View File

@ -2,6 +2,7 @@ Import('env')
files = ["ABI.cpp", files = ["ABI.cpp",
"Common.cpp", "Common.cpp",
"ChunkFile.cpp",
"CPUDetect.cpp", "CPUDetect.cpp",
"DynamicLibrary.cpp", "DynamicLibrary.cpp",
"Hash.cpp", "Hash.cpp",

View File

@ -1174,6 +1174,14 @@
RelativePath=".\Src\SConscript" RelativePath=".\Src\SConscript"
> >
</File> </File>
<File
RelativePath=".\Src\State.cpp"
>
</File>
<File
RelativePath=".\Src\State.h"
>
</File>
<File <File
RelativePath=".\Src\stdafx.cpp" RelativePath=".\Src\stdafx.cpp"
> >

View File

@ -61,7 +61,7 @@ int RegisterEvent(const char *name, TimedCallback callback)
type.name = name; type.name = name;
type.callback = callback; type.callback = callback;
event_types.push_back(type); event_types.push_back(type);
return event_types.size() - 1; return (int)event_types.size() - 1;
} }
void UnregisterAllEvents() void UnregisterAllEvents()
@ -71,6 +71,18 @@ void UnregisterAllEvents()
event_types.clear(); event_types.clear();
} }
void DoState(ChunkFile &f)
{
externalEventSection.Enter();
f.Descend("TIME");
f.Do(downcount);
f.Do(slicelength);
f.Do(maxSliceLength);
f.Do(globalTimer);
f.Do(idledCycles);
f.Ascend();
externalEventSection.Leave();
}
u64 GetTicks() u64 GetTicks()
{ {

View File

@ -25,6 +25,7 @@
// callback. You then schedule events using the type id you get back. // callback. You then schedule events using the type id you get back.
#include "Common.h" #include "Common.h"
#include "ChunkFile.h"
namespace CoreTiming namespace CoreTiming
{ {
@ -34,6 +35,7 @@ typedef void (*TimedCallback)(u64 userdata, int cyclesLate);
u64 GetTicks(); u64 GetTicks();
u64 GetIdleTicks(); u64 GetIdleTicks();
void DoState(ChunkFile &f);
// The int that the callbacks get is how many cycles late it was. // The int that the callbacks get is how many cycles late it was.
// So to schedule a new event on a regular basis: // So to schedule a new event on a regular basis:
// inside callback: // inside callback:

View File

@ -87,18 +87,29 @@ struct SAudioRegister
u32 m_InterruptTiming; u32 m_InterruptTiming;
}; };
SAudioRegister g_AudioRegister; // STATE_TO_SAVE
static SAudioRegister g_AudioRegister;
static u64 g_LastCPUTime = 0;
static int g_SampleRate = 32000;
static int g_DSPSampleRate = 32000;
static u64 g_CPUCyclesPerSample = 0xFFFFFFFFFFFULL;
void DoState(ChunkFile &f)
{
f.Descend("AI ");
f.Do(g_AudioRegister);
f.Do(g_LastCPUTime);
f.Do(g_SampleRate);
f.Do(g_DSPSampleRate);
f.Do(g_CPUCyclesPerSample);
f.Ascend();
}
void GenerateAudioInterrupt(); void GenerateAudioInterrupt();
void UpdateInterrupts(); void UpdateInterrupts();
void IncreaseSampleCount(const u32 _uAmount); void IncreaseSampleCount(const u32 _uAmount);
void ReadStreamBlock(short* _pPCM); void ReadStreamBlock(short* _pPCM);
static u64 g_LastCPUTime = 0;
static int g_SampleRate = 32000;
static int g_DSPSampleRate = 32000;
static u64 g_CPUCyclesPerSample = 0xFFFFFFFFFFFULL;
void Init() void Init()
{ {
g_AudioRegister.m_SampleCounter = 0; g_AudioRegister.m_SampleCounter = 0;

View File

@ -20,32 +20,28 @@
#ifndef _AUDIOINTERFACE_H #ifndef _AUDIOINTERFACE_H
#define _AUDIOINTERFACE_H #define _AUDIOINTERFACE_H
class ChunkFile;
namespace AudioInterface namespace AudioInterface
{ {
// Init
void Init(); void Init();
// Shutdown
void Shutdown(); void Shutdown();
void DoState(ChunkFile &f);
// Update
void Update(); void Update();
// Calls by DSP plugin // Calls by DSP plugin
unsigned __int32 Callback_GetStreaming(short* _pDestBuffer, unsigned __int32 _numSamples); unsigned __int32 Callback_GetStreaming(short* _pDestBuffer, unsigned __int32 _numSamples);
// Read32
void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress); void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress);
// Write32
void HWCALL Write32(const u32 _iValue, const u32 _iAddress); void HWCALL Write32(const u32 _iValue, const u32 _iAddress);
// Get the Audio Rate (48000 or 32000) // Get the audio rates (48000 or 32000 only)
u32 GetAISampleRate(); u32 GetAISampleRate();
u32 GetDSPSampleRate(); u32 GetDSPSampleRate();
} // end of namespace AudioInterface } // namespace
#endif #endif

View File

@ -105,6 +105,20 @@ u16 m_tokenReg;
CPFifo fifo; //This one is shared between gfx thread and emulator thread CPFifo fifo; //This one is shared between gfx thread and emulator thread
void DoState(ChunkFile &f)
{
f.Descend("CP ");
f.Do(m_CPStatusReg);
f.Do(m_CPCtrlReg);
f.Do(m_CPClearReg);
f.Do(m_bboxleft);
f.Do(m_bboxtop);
f.Do(m_bboxright);
f.Do(m_bboxbottom);
f.Do(m_tokenReg);
f.Do(fifo);
f.Ascend();
}
// function // function
void UpdateFifoRegister(); void UpdateFifoRegister();

View File

@ -18,6 +18,9 @@
#ifndef _COMMANDPROCESSOR_H #ifndef _COMMANDPROCESSOR_H
#define _COMMANDPROCESSOR_H #define _COMMANDPROCESSOR_H
#include "Common.h"
class ChunkFile;
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#endif #endif
@ -79,6 +82,7 @@ extern CPFifo fifo;
// Init // Init
void Init(); void Init();
void Shutdown(); void Shutdown();
void DoState(ChunkFile &f);
// Read // Read
void HWCALL Read16(u16& _rReturnValue, const u32 _Address); void HWCALL Read16(u16& _rReturnValue, const u32 _Address);

View File

@ -175,6 +175,19 @@ u16 g_AR_MODE = 0x43; // 0x23 -> Zelda standard mode (standard ARAM access ??)
// 0x43 -> written by OSAudioInit at the UCode upload (upload UCode) // 0x43 -> written by OSAudioInit at the UCode upload (upload UCode)
// 0x63 -> ARCheckSize Mode (access AR-registers ??) or no exception ?? // 0x63 -> ARCheckSize Mode (access AR-registers ??) or no exception ??
void DoState(ChunkFile &f)
{
f.Descend("DSP ");
f.Do(g_ARAM, ARAM_SIZE);
f.Do(g_dspState);
f.Do(g_audioDMA);
f.Do(g_arDMA);
f.Do(g_AR_READY_FLAG);
f.Do(g_AR_MODE);
f.Ascend();
}
void UpdateInterrupts(); void UpdateInterrupts();
void Update_ARAM_DMA(); void Update_ARAM_DMA();
void WriteARAM(u8 _iValue, u32 _iAddress); void WriteARAM(u8 _iValue, u32 _iAddress);

View File

@ -19,6 +19,7 @@
#define _DSPINTERFACE_H #define _DSPINTERFACE_H
#include "Common.h" #include "Common.h"
class ChunkFile;
namespace DSP namespace DSP
{ {
@ -32,6 +33,8 @@ enum DSPInterruptType
void Init(); void Init();
void Shutdown(); void Shutdown();
void DoState(ChunkFile &f);
void GenerateDSPInterrupt(DSPInterruptType _DSPInterruptType, bool _bSet = true); void GenerateDSPInterrupt(DSPInterruptType _DSPInterruptType, bool _bSet = true);
void GenerateDSPInterruptFromPlugin(DSPInterruptType _DSPInterruptType, bool _bSet = true); void GenerateDSPInterruptFromPlugin(DSPInterruptType _DSPInterruptType, bool _bSet = true);

View File

@ -15,6 +15,9 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "ChunkFile.h"
#include "StreamADPCM.H" #include "StreamADPCM.H"
#include "DVDInterface.h" #include "DVDInterface.h"
@ -44,7 +47,7 @@ namespace DVDInterface
20993: 00000000 DVD (zzz_80146e44 ??, 0x80146fcc) : DVD(r): 0xcc006018 20993: 00000000 DVD (zzz_80146e44 ??, 0x80146fcc) : DVD(r): 0xcc006018
After this, Cubivore infinitely calls DVDGetDriveStatus, which does not even After this, Cubivore infinitely calls DVDGetDriveStatus, which does not even
bother to check any DVD regs bother to check any DVD regs. Waiting for interrupt?
*/ */
// internal hardware addresses // internal hardware addresses
@ -69,7 +72,7 @@ enum DVDInterruptType
INT_DEINT = 0, INT_DEINT = 0,
INT_TCINT = 1, INT_TCINT = 1,
INT_BRKINT = 2, INT_BRKINT = 2,
INT_CVRINT INT_CVRINT = 3,
}; };
// DI Status Register // DI Status Register
@ -78,14 +81,14 @@ union UDISR
u32 Hex; u32 Hex;
struct struct
{ {
unsigned BREAK : 1; // Stop the Device + Interrupt unsigned BREAK : 1; // Stop the Device + Interrupt
unsigned DEINITMASK : 1; // Access Device Error Int Mask unsigned DEINITMASK : 1; // Access Device Error Int Mask
unsigned DEINT : 1; // Access Device Error Int unsigned DEINT : 1; // Access Device Error Int
unsigned TCINTMASK : 1; // Transfer Complete Int Mask unsigned TCINTMASK : 1; // Transfer Complete Int Mask
unsigned TCINT : 1; // Transfer Complete Int unsigned TCINT : 1; // Transfer Complete Int
unsigned BRKINTMASK : 1; unsigned BRKINTMASK : 1;
unsigned BRKINT : 1; // w 1: clear brkint unsigned BRKINT : 1; // w 1: clear brkint
unsigned : 25; unsigned : 25;
}; };
UDISR() {Hex = 0;} UDISR() {Hex = 0;}
UDISR(u32 _hex) {Hex = _hex;} UDISR(u32 _hex) {Hex = _hex;}
@ -97,10 +100,10 @@ union UDICVR
u32 Hex; u32 Hex;
struct struct
{ {
unsigned CVR : 1; // 0: Cover closed 1: Cover open unsigned CVR : 1; // 0: Cover closed 1: Cover open
unsigned CVRINTMASK : 1; // 1: Interrupt enabled; unsigned CVRINTMASK : 1; // 1: Interrupt enabled;
unsigned CVRINT : 1; // 1: Interrupt clear unsigned CVRINT : 1; // 1: Interrupt clear
unsigned : 29; unsigned : 29;
}; };
UDICVR() {Hex = 0;} UDICVR() {Hex = 0;}
UDICVR(u32 _hex) {Hex = _hex;} UDICVR(u32 _hex) {Hex = _hex;}
@ -170,11 +173,19 @@ struct DVDMemStruct
u32 AudioLength; u32 AudioLength;
}; };
// STATE_TO_SAVE
DVDMemStruct dvdMem; DVDMemStruct dvdMem;
u32 g_ErrorCode = 0x00;
bool g_bDiscInside = true;
// helper void DoState(ChunkFile &f)
u32 g_ErrorCode = 0x00; {
bool g_bDiscInside = true; f.Descend("DI ");
f.Do(dvdMem);
f.Do(g_ErrorCode);
f.Do(g_bDiscInside);
f.Ascend();
}
void UpdateInterrupts(); void UpdateInterrupts();
void GenerateDVDInterrupt(DVDInterruptType _DVDInterrupt); void GenerateDVDInterrupt(DVDInterruptType _DVDInterrupt);

View File

@ -19,13 +19,14 @@
#define _DVDINTERFACE_H #define _DVDINTERFACE_H
#include "Common.h" #include "Common.h"
class ChunkFile;
namespace DVDInterface namespace DVDInterface
{ {
// Init
void Init(); void Init();
void Shutdown(); void Shutdown();
void DoState(ChunkFile &f);
void SetDiscInside(bool _DiscInside); void SetDiscInside(bool _DiscInside);

View File

@ -15,6 +15,9 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "ChunkFile.h"
#include "PeripheralInterface.h" #include "PeripheralInterface.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
@ -50,6 +53,13 @@ void Shutdown()
g_Channels = 0; g_Channels = 0;
} }
void DoState(ChunkFile &f)
{
f.Descend("EXI ");
// TODO: descend all the devices recursively.
f.Ascend();
}
void Update() void Update()
{ {
g_Channels[0].Update(); g_Channels[0].Update();

View File

@ -18,12 +18,15 @@
#define _EXIINTERFACE_H #define _EXIINTERFACE_H
#include "Common.h" #include "Common.h"
class ChunkFile;
namespace ExpansionInterface namespace ExpansionInterface
{ {
void Init(); void Init();
void Shutdown(); void Shutdown();
void DoState(ChunkFile &f);
void Update(); void Update();
void UpdateInterrupts(); void UpdateInterrupts();

View File

@ -289,7 +289,7 @@ void CEXIMemoryCard::TransferByte(u8 &byte)
break; break;
case cmdSetInterrupt: case cmdSetInterrupt:
if (m_uPosition==1) if (m_uPosition == 1)
{ {
interruptSwitch = byte; interruptSwitch = byte;
} }

View File

@ -15,13 +15,15 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "GPFifo.h" #include "Common.h"
#include "ChunkFile.h"
#include "PeripheralInterface.h" #include "PeripheralInterface.h"
#include "CommandProcessor.h" #include "CommandProcessor.h"
#include "Memmap.h" #include "Memmap.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
#include "GPFifo.h"
namespace GPFifo namespace GPFifo
{ {
@ -42,6 +44,14 @@ u8 GC_ALIGNED32(m_gatherPipe[GATHER_PIPE_SIZE*16]); //more room, for the fastmod
// pipe counter // pipe counter
u32 m_gatherPipeCount = 0; u32 m_gatherPipeCount = 0;
void DoState(ChunkFile &f)
{
f.Descend("FIFO");
f.Do(m_gatherPipe);
f.Do(m_gatherPipeCount);
f.Ascend();
}
void Init() void Init()
{ {
ResetGatherPipe(); ResetGatherPipe();

View File

@ -19,6 +19,7 @@
#define _GPFIFO_H #define _GPFIFO_H
#include "Common.h" #include "Common.h"
class ChunkFile;
namespace GPFifo namespace GPFifo
{ {
@ -35,6 +36,7 @@ extern u32 m_gatherPipeCount;
// Init // Init
void Init(); void Init();
void DoState(ChunkFile &f);
// ResetGatherPipe // ResetGatherPipe
void ResetGatherPipe(); void ResetGatherPipe();

View File

@ -37,6 +37,7 @@
#include "../CoreTiming.h" #include "../CoreTiming.h"
#include "SystemTimers.h" #include "SystemTimers.h"
#include "../IPC_HLE/WII_IPC_HLE.h" #include "../IPC_HLE/WII_IPC_HLE.h"
#include "../State.h"
#define CURVERSION 0x0001 #define CURVERSION 0x0001
@ -45,7 +46,10 @@ namespace HW
void Init() void Init()
{ {
Thunk_Init(); // not really hw, but this way we know it's inited first :P Thunk_Init(); // not really hw, but this way we know it's inited first :P
State_Init();
// Init the whole Hardware // Init the whole Hardware
AudioInterface::Init();
PixelEngine::Init(); PixelEngine::Init();
CommandProcessor::Init(); CommandProcessor::Init();
VideoInterface::Init(); VideoInterface::Init();
@ -72,11 +76,32 @@ namespace HW
DSP::Shutdown(); DSP::Shutdown();
Memory::Shutdown(); Memory::Shutdown();
SerialInterface::Shutdown(); SerialInterface::Shutdown();
AudioInterface::Shutdown();
WII_IPC_HLE_Interface::Shutdown(); WII_IPC_HLE_Interface::Shutdown();
WII_IPCInterface::Shutdown(); WII_IPCInterface::Shutdown();
State_Shutdown();
Thunk_Shutdown(); Thunk_Shutdown();
CoreTiming::UnregisterAllEvents(); CoreTiming::UnregisterAllEvents();
} }
void DoState(ChunkFile &f)
{
f.Descend("HWst");
PixelEngine::DoState(f);
CommandProcessor::DoState(f);
VideoInterface::DoState(f);
SerialInterface::DoState(f);
CPeripheralInterface::DoState(f);
DSP::DoState(f);
DVDInterface::DoState(f);
GPFifo::DoState(f);
ExpansionInterface::DoState(f);
AudioInterface::DoState(f);
CoreTiming::DoState(f);
WII_IPCInterface::DoState(f);
f.Ascend();
}
} }

View File

@ -19,15 +19,13 @@
#define _HW_H #define _HW_H
#include "Common.h" #include "Common.h"
#include "ChunkFile.h"
namespace HW namespace HW
{ {
void Init(); void Init();
void Shutdown(); void Shutdown();
/* void DoState(ChunkFile &f);
void LoadState(const char* _szFilename);
void SaveState(const char* _szFilename);
*/
} }
#endif #endif

View File

@ -21,6 +21,8 @@
#include "Common.h" #include "Common.h"
class ChunkFile;
typedef void (HWCALL *writeFn8 )(const u8, const u32); typedef void (HWCALL *writeFn8 )(const u8, const u32);
typedef void (HWCALL *writeFn16)(const u16,const u32); typedef void (HWCALL *writeFn16)(const u16,const u32);
typedef void (HWCALL *writeFn32)(const u32,const u32); typedef void (HWCALL *writeFn32)(const u32,const u32);
@ -63,6 +65,8 @@ namespace Memory
bool IsInitialized(); bool IsInitialized();
bool Init(); bool Init();
bool Shutdown(); bool Shutdown();
void DoState(ChunkFile &f);
void Clear(); void Clear();
bool AreMemoryBreakpointsActivated(); bool AreMemoryBreakpointsActivated();

View File

@ -15,6 +15,9 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "ChunkFile.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
#include "MemoryInterface.h" #include "MemoryInterface.h"
@ -47,6 +50,13 @@ struct MIMemStruct
// STATE_TO_SAVE // STATE_TO_SAVE
static MIMemStruct miMem; static MIMemStruct miMem;
void DoState(ChunkFile &f)
{
f.Descend("MI ");
f.Do(miMem);
f.Ascend();
}
void Read16(u16& _uReturnValue, const u32 _iAddress) void Read16(u16& _uReturnValue, const u32 _iAddress)
{ {
//0x30 -> 0x5a : gp memory metrics //0x30 -> 0x5a : gp memory metrics

View File

@ -17,8 +17,13 @@
#ifndef _MEMORYINTERFACE_H #ifndef _MEMORYINTERFACE_H
#define _MEMORYINTERFACE_H #define _MEMORYINTERFACE_H
#include "Common.h"
class ChunkFile;
namespace MemoryInterface namespace MemoryInterface
{ {
void DoState(ChunkFile &f);
void HWCALL Read16(u16& _uReturnValue, const u32 _iAddress); void HWCALL Read16(u16& _uReturnValue, const u32 _iAddress);
void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress); void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress);
void HWCALL Write32(const u32 _iValue, const u32 _iAddress); void HWCALL Write32(const u32 _iValue, const u32 _iAddress);

View File

@ -16,6 +16,8 @@
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <stdio.h> #include <stdio.h>
#include "Common.h"
#include "ChunkFile.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
#include "../HW/CPU.h" #include "../HW/CPU.h"
@ -31,6 +33,17 @@ u32 CPeripheralInterface::Fifo_CPUBase;
u32 CPeripheralInterface::Fifo_CPUEnd; u32 CPeripheralInterface::Fifo_CPUEnd;
u32 CPeripheralInterface::Fifo_CPUWritePointer; u32 CPeripheralInterface::Fifo_CPUWritePointer;
void CPeripheralInterface::DoState(ChunkFile &f)
{
f.Descend("PI ");
f.Do(m_InterruptMask);
f.Do(m_InterruptCause);
f.Do(Fifo_CPUBase);
f.Do(Fifo_CPUEnd);
f.Do(Fifo_CPUWritePointer);
f.Ascend();
}
void CPeripheralInterface::Init() void CPeripheralInterface::Init()
{ {
m_InterruptMask = 0; m_InterruptMask = 0;

View File

@ -19,6 +19,8 @@
#define _PERIPHERALINTERFACE_H #define _PERIPHERALINTERFACE_H
#include "Common.h" #include "Common.h"
class ChunkFile;
// //
// PERIPHERALINTERFACE // PERIPHERALINTERFACE
// Handles communication with cpu services like the write gatherer used for fifos, and interrupts // Handles communication with cpu services like the write gatherer used for fifos, and interrupts
@ -96,6 +98,7 @@ public:
static u32 Fifo_CPUWritePointer; static u32 Fifo_CPUWritePointer;
static void Init(); static void Init();
static void DoState(ChunkFile &f);
static void SetInterrupt(InterruptCause _causemask, bool _bSet=true); static void SetInterrupt(InterruptCause _causemask, bool _bSet=true);

View File

@ -15,6 +15,9 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "ChunkFile.h"
#include "PixelEngine.h" #include "PixelEngine.h"
#include "../CoreTiming.h" #include "../CoreTiming.h"
@ -60,6 +63,16 @@ static bool g_bSignalFinishInterrupt;
int et_SetTokenOnMainThread; int et_SetTokenOnMainThread;
int et_SetFinishOnMainThread; int et_SetFinishOnMainThread;
void DoState(ChunkFile &f)
{
f.Descend("PE ");
f.Do(g_ctrlReg);
f.Do(g_token);
f.Do(g_bSignalTokenInterrupt);
f.Do(g_bSignalFinishInterrupt);
f.Ascend();
}
void UpdateInterrupts(); void UpdateInterrupts();
void SetToken_OnMainThread(u64 userdata, int cyclesLate); void SetToken_OnMainThread(u64 userdata, int cyclesLate);

View File

@ -18,10 +18,12 @@
#define _PIXELENGINE_H #define _PIXELENGINE_H
#include "Common.h" #include "Common.h"
class ChunkFile;
namespace PixelEngine namespace PixelEngine
{ {
void Init(); void Init();
void DoState(ChunkFile &f);
// Read // Read
void HWCALL Read16(u16& _uReturnValue, const u32 _iAddress); void HWCALL Read16(u16& _uReturnValue, const u32 _iAddress);

View File

@ -17,6 +17,9 @@
#include <string.h> #include <string.h>
#include "Common.h"
#include "ChunkFile.h"
#include "SerialInterface.h" #include "SerialInterface.h"
#include "SerialInterface_Devices.h" #include "SerialInterface_Devices.h"
@ -215,6 +218,18 @@ static USIStatusReg g_StatusReg;
static USIEXIClockCount g_EXIClockCount; static USIEXIClockCount g_EXIClockCount;
static u8 g_SIBuffer[128]; static u8 g_SIBuffer[128];
void DoState(ChunkFile &f)
{
f.Descend("SI ");
f.Do(g_Channel);
f.Do(g_Poll);
f.Do(g_ComCSR);
f.Do(g_StatusReg);
f.Do(g_EXIClockCount);
f.Do(g_SIBuffer);
f.Ascend();
}
static void GenerateSIInterrupt(SIInterruptType _SIInterrupt); static void GenerateSIInterrupt(SIInterruptType _SIInterrupt);
void RunSIBuffer(); void RunSIBuffer();
void UpdateInterrupts(); void UpdateInterrupts();
@ -228,10 +243,10 @@ void Init()
g_Channel[i].m_InLo.Hex = 0; g_Channel[i].m_InLo.Hex = 0;
} }
unsigned int AttachedPasMask = PluginPAD::PAD_GetAttachedPads(); unsigned int AttachedPadMask = PluginPAD::PAD_GetAttachedPads();
for (int i=0; i<4; i++) for (int i = 0; i < 4; i++)
{ {
if (AttachedPasMask & (1 << i)) if (AttachedPadMask & (1 << i))
g_Channel[i].m_pDevice = new CSIDevice_GCController(i); g_Channel[i].m_pDevice = new CSIDevice_GCController(i);
else else
g_Channel[i].m_pDevice = new CSIDevice_Dummy(i); g_Channel[i].m_pDevice = new CSIDevice_Dummy(i);
@ -246,7 +261,7 @@ void Init()
void Shutdown() void Shutdown()
{ {
for (int i=0; i<NUMBER_OF_CHANNELS; i++) for (int i = 0; i < NUMBER_OF_CHANNELS; i++)
{ {
delete g_Channel[i].m_pDevice; delete g_Channel[i].m_pDevice;
g_Channel[i].m_pDevice = NULL; g_Channel[i].m_pDevice = NULL;

View File

@ -19,22 +19,18 @@
#define _SERIALINTERFACE_H #define _SERIALINTERFACE_H
#include "Common.h" #include "Common.h"
class ChunkFile;
namespace SerialInterface namespace SerialInterface
{ {
// Init
void Init(); void Init();
// Shutdown
void Shutdown(); void Shutdown();
void DoState(ChunkFile &f);
void UpdateDevices(); void UpdateDevices();
// Read32
void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress); void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress);
// Write32
void HWCALL Write32(const u32 _iValue, const u32 _iAddress); void HWCALL Write32(const u32 _iValue, const u32 _iAddress);
}; // end of namespace SerialInterface }; // end of namespace SerialInterface

View File

@ -19,6 +19,7 @@
#define _SERIALINTERFACE_DEVICES_H #define _SERIALINTERFACE_DEVICES_H
#include "Common.h" #include "Common.h"
class ChunkFile;
class ISIDevice class ISIDevice
{ {

View File

@ -12,6 +12,7 @@
#define _STREAMADPCM_H #define _STREAMADPCM_H
#include "Common.h" #include "Common.h"
class ChunkFile;
#define ONE_BLOCK_SIZE 32 #define ONE_BLOCK_SIZE 32
#define SAMPLES_PER_BLOCK 28 #define SAMPLES_PER_BLOCK 28

View File

@ -7,7 +7,9 @@
#include "StreamADPCM.H" #include "StreamADPCM.H"
float NGCADPCM::iir1[STEREO], NGCADPCM::iir2[STEREO]; // STATE_TO_SAVE
float NGCADPCM::iir1[STEREO],
NGCADPCM::iir2[STEREO];
void NGCADPCM::InitFilter() void NGCADPCM::InitFilter()
{ {

View File

@ -15,6 +15,9 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "ChunkFile.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
#include "PeripheralInterface.h" #include "PeripheralInterface.h"
@ -83,30 +86,44 @@ union UVIInterruptRegister
}; };
// STATE_TO_SAVE // STATE_TO_SAVE
UVIDisplayControlRegister m_VIDisplayControlRegister; static UVIDisplayControlRegister m_VIDisplayControlRegister;
// Framebuffers // Framebuffers
u32 m_FrameBuffer1; // normal framebuffer address static u32 m_FrameBuffer1; // normal framebuffer address
u32 m_FrameBuffer2; // framebuffer for 3d buffer address static u32 m_FrameBuffer2; // framebuffer for 3d buffer address
// VI Interrupt Registers // VI Interrupt Registers
UVIInterruptRegister m_VIInterruptRegister[4]; static UVIInterruptRegister m_VIInterruptRegister[4];
u8 m_UVIUnknownRegs[0x1000]; u8 m_UVIUnknownRegs[0x1000];
u16 HorizontalBeamPos = 0; static u16 HorizontalBeamPos = 0;
u16 VerticalBeamPos = 0; static u16 VerticalBeamPos = 0;
u32 TicksPerFrame = 0; static u32 TicksPerFrame = 0;
u32 LineCount = 0; static u32 LineCount = 0;
u64 LastTime = 0; static u64 LastTime = 0;
void DoState(ChunkFile &f)
{
f.Descend("VI ");
f.Do(m_VIDisplayControlRegister);
f.Do(m_FrameBuffer1);
f.Do(m_FrameBuffer2);
f.Do(m_VIInterruptRegister);
f.Do(m_UVIUnknownRegs, 0x1000);
f.Do(HorizontalBeamPos);
f.Do(VerticalBeamPos);
f.Do(TicksPerFrame);
f.Do(LineCount);
f.Do(LastTime);
f.Ascend();
}
void Init() void Init()
{ {
for (int i=0; i<4; i++) for (int i = 0; i < 4; i++)
{
m_VIInterruptRegister[i].Hex = 0x00; m_VIInterruptRegister[i].Hex = 0x00;
}
m_VIDisplayControlRegister.Hex = 0x0000; m_VIDisplayControlRegister.Hex = 0x0000;
m_VIDisplayControlRegister.ENB = 0; m_VIDisplayControlRegister.ENB = 0;

View File

@ -18,6 +18,7 @@
#define _VIDEOINTERFACE_H #define _VIDEOINTERFACE_H
#include "Common.h" #include "Common.h"
class ChunkFile;
namespace VideoInterface namespace VideoInterface
{ {
@ -29,20 +30,18 @@ namespace VideoInterface
INT_REG_3, INT_REG_3,
}; };
// Init
void Init(); void Init();
void DoState(ChunkFile &f);
// Read
void HWCALL Read16(u16& _uReturnValue, const u32 _uAddress); void HWCALL Read16(u16& _uReturnValue, const u32 _uAddress);
void HWCALL Read32(u32& _uReturnValue, const u32 _uAddress); void HWCALL Read32(u32& _uReturnValue, const u32 _uAddress);
// Write
void HWCALL Write16(const u16 _uValue, const u32 _uAddress); void HWCALL Write16(const u16 _uValue, const u32 _uAddress);
void HWCALL Write32(const u32 _uValue, const u32 _uAddress); void HWCALL Write32(const u32 _uValue, const u32 _uAddress);
void GenerateVIInterrupt(VIInterruptType _VIInterrupt); void GenerateVIInterrupt(VIInterruptType _VIInterrupt);
// returns a pointer to the framebuffer // returns a pointer to the current visible framebuffer
u8* GetFrameBufferPointer(); u8* GetFrameBufferPointer();
// pre init // pre init
@ -51,7 +50,6 @@ namespace VideoInterface
// VI Unknown Regs // VI Unknown Regs
extern u8 m_UVIUnknownRegs[0x1000]; extern u8 m_UVIUnknownRegs[0x1000];
// ?????? // ??????
void Update(); void Update();
@ -59,7 +57,6 @@ namespace VideoInterface
// UpdateInterrupts: check if we have to generate a new VI Interrupt // UpdateInterrupts: check if we have to generate a new VI Interrupt
void UpdateInterrupts(); void UpdateInterrupts();
// ?????? // ??????
void UpdateTiming(); void UpdateTiming();
}; };

View File

@ -16,6 +16,7 @@
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
#include "ChunkFile.h"
#include "WII_IOB.h" #include "WII_IOB.h"
namespace WII_IOBridge namespace WII_IOBridge

View File

@ -17,16 +17,16 @@
#ifndef _WII_IOBRIDGE_H_ #ifndef _WII_IOBRIDGE_H_
#define _WII_IOBRIDGE_H_ #define _WII_IOBRIDGE_H_
#include "Common.h"
class ChunkFile;
namespace WII_IOBridge namespace WII_IOBridge
{ {
// Init
void Init(); void Init();
// Shutdown
void Shutdown(); void Shutdown();
void DoState(ChunkFile &f);
// Update
void Update(); void Update();
void HWCALL Read8(u8& _rReturnValue, const u32 _Address); void HWCALL Read8(u8& _rReturnValue, const u32 _Address);

View File

@ -18,13 +18,14 @@
#include <map> #include <map>
#include "Common.h" #include "Common.h"
#include "WII_IPC.h" #include "ChunkFile.h"
#include "CPU.h" #include "CPU.h"
#include "Memmap.h" #include "Memmap.h"
#include "PeripheralInterface.h" #include "PeripheralInterface.h"
#include "../IPC_HLE/WII_IPC_HLE.h" #include "../IPC_HLE/WII_IPC_HLE.h"
#include "WII_IPC.h"
namespace WII_IPCInterface namespace WII_IPCInterface
{ {
@ -92,6 +93,17 @@ u32 g_Address = 0;
u32 g_Reply = 0; u32 g_Reply = 0;
u32 g_SensorBarPower = 0; u32 g_SensorBarPower = 0;
void DoState(ChunkFile &f)
{
f.Descend("WIPC");
f.Do(g_IPC_Status);
f.Do(g_IPC_Config);
f.Do(g_IPC_Control);
f.Do(g_Address);
f.Do(g_Reply);
f.Do(g_SensorBarPower);
f.Ascend();
}
void UpdateInterrupts(); void UpdateInterrupts();

View File

@ -17,18 +17,17 @@
#ifndef _WII_IPC_H_ #ifndef _WII_IPC_H_
#define _WII_IPC_H_ #define _WII_IPC_H_
#include "Common.h"
class ChunkFile;
namespace WII_IPCInterface namespace WII_IPCInterface
{ {
// Init
void Init(); void Init();
// Shutdown
void Shutdown(); void Shutdown();
void DoState(ChunkFile &f);
// Update
void Update(); void Update();
bool IsReady(); bool IsReady();
void GenerateReply(u32 _AnswerAddress); void GenerateReply(u32 _AnswerAddress);
void GenerateAck(u32 _AnswerAddress); void GenerateAck(u32 _AnswerAddress);

View File

@ -15,6 +15,9 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "ChunkFile.h"
#include "../HW/Memmap.h" #include "../HW/Memmap.h"
#include "../HW/CPU.h" #include "../HW/CPU.h"
#include "../Core.h" #include "../Core.h"
@ -29,10 +32,19 @@
namespace PowerPC namespace PowerPC
{ {
// STATE_TO_SAVE
PowerPCState GC_ALIGNED16(ppcState); PowerPCState GC_ALIGNED16(ppcState);
volatile CPUState state = CPU_STEPPING;
ICPUCore* m_pCore = NULL; ICPUCore* m_pCore = NULL;
volatile CPUState state = CPU_STEPPING; void DoState(ChunkFile &f)
{
f.Descend("PPC ");
f.Do(ppcState);
f.Do(state);
f.Ascend();
}
void ResetRegisters() void ResetRegisters()
{ {

View File

@ -29,6 +29,8 @@
#include "Gekko.h" #include "Gekko.h"
#include "ICPUCore.h" #include "ICPUCore.h"
class ChunkFile;
namespace PowerPC namespace PowerPC
{ {
enum ECoreType enum ECoreType
@ -85,6 +87,8 @@ namespace PowerPC
void Init(); void Init();
void Shutdown(); void Shutdown();
void DoState(ChunkFile &f);
void SetCore(ECoreType _coreType); void SetCore(ECoreType _coreType);
ICPUCore& GetCore(); ICPUCore& GetCore();

View File

@ -4,11 +4,12 @@ files = ["Console.cpp",
"Core.cpp", "Core.cpp",
"CoreTiming.cpp", "CoreTiming.cpp",
"CoreParameter.cpp", "CoreParameter.cpp",
"LogManager.cpp",
"PatchEngine.cpp",
"MemTools.cpp",
"Tracer.cpp",
"Host.cpp", "Host.cpp",
"LogManager.cpp",
"MemTools.cpp",
"PatchEngine.cpp",
"State.cpp",
"Tracer.cpp",
"VolumeHandler.cpp", "VolumeHandler.cpp",
"Boot/Boot.cpp", "Boot/Boot.cpp",
"Boot/Boot_DOL.cpp", "Boot/Boot_DOL.cpp",

View File

@ -0,0 +1,54 @@
#include "Common.h"
#include "State.h"
#include "CoreTiming.h"
#include "HW/HW.h"
#include "PowerPC/PowerPC.h"
static int ev_Save;
static int ev_Load;
static std::string cur_filename;
void DoState(ChunkFile &f)
{
f.Descend("DOLP");
PowerPC::DoState(f);
HW::DoState(f);
f.Ascend();
}
void SaveStateCallback(u64 userdata, int cyclesLate)
{
ChunkFile f(cur_filename.c_str(), ChunkFile::MODE_WRITE);
DoState(f);
}
void LoadStateCallback(u64 userdata, int cyclesLate)
{
ChunkFile f(cur_filename.c_str(), ChunkFile::MODE_READ);
DoState(f);
}
void State_Init()
{
ev_Load = CoreTiming::RegisterEvent("LoadState", &LoadStateCallback);
ev_Save = CoreTiming::RegisterEvent("SaveState", &SaveStateCallback);
}
void State_Shutdown()
{
// nothing to do, here for consistency.
}
void SaveState(const char *filename)
{
cur_filename = filename;
CoreTiming::ScheduleEvent_Threadsafe(0, ev_Save);
}
void LoadState(const char *filename)
{
cur_filename = filename;
CoreTiming::ScheduleEvent_Threadsafe(0, ev_Load);
}

View File

@ -0,0 +1,12 @@
#ifndef _STATE_H
#define _STATE_H
// None of these happen instantly - they get scheduled as an event.
void State_Init();
void State_Shutdown();
void State_Save();
void State_Load();
#endif