psx - savestates
This commit is contained in:
parent
b16497ad24
commit
2cd1ef1c63
|
@ -21,7 +21,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
isPorted: true,
|
||||
isReleased: false
|
||||
)]
|
||||
public unsafe class Octoshock : IEmulator, IVideoProvider, ISyncSoundProvider, IMemoryDomains, ISaveRam, IDriveLight
|
||||
public unsafe class Octoshock : IEmulator, IVideoProvider, ISyncSoundProvider, IMemoryDomains, ISaveRam, IStatable, IDriveLight
|
||||
{
|
||||
public string SystemId { get { return "PSX"; } }
|
||||
|
||||
|
@ -213,7 +213,6 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
OctoshockDll.shock_Create(out psx, region, pFirmware);
|
||||
|
||||
SetMemoryDomains();
|
||||
StudySaveBufferSize();
|
||||
|
||||
//these should track values in octoshock gpu.cpp FillVideoParams
|
||||
//if (discInfo.region == OctoshockDll.eRegion.EU)
|
||||
|
@ -248,6 +247,10 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
OctoshockDll.shock_MountEXE(psx, pExeBuffer, exe.Length);
|
||||
}
|
||||
OctoshockDll.shock_Peripheral_Connect(psx, 0x01, OctoshockDll.ePeripheralType.DualShock);
|
||||
|
||||
//do this after framebuffers and peripherals and whatever crap are setup. kind of lame, but thats how it is for now
|
||||
StudySaveBufferSize();
|
||||
|
||||
OctoshockDll.shock_PowerOn(psx);
|
||||
}
|
||||
|
||||
|
@ -503,7 +506,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
var transaction = new OctoshockDll.ShockStateTransaction()
|
||||
{
|
||||
transaction = OctoshockDll.eShockStateTransaction.TextLoad,
|
||||
ff = s.GetFunctionPointersSave()
|
||||
ff = s.GetFunctionPointersLoad()
|
||||
};
|
||||
|
||||
int result = OctoshockDll.shock_StateTransaction(psx, ref transaction);
|
||||
|
|
Binary file not shown.
|
@ -53,6 +53,7 @@
|
|||
<ClInclude Include="..\cdrom\CDUtility.h" />
|
||||
<ClInclude Include="..\cdrom\dvdisaster.h" />
|
||||
<ClInclude Include="..\cdrom\lec.h" />
|
||||
<ClInclude Include="..\cdrom\SimpleFIFO.h" />
|
||||
<ClInclude Include="..\emuware\emuware.h" />
|
||||
<ClInclude Include="..\emuware\EW_state.h" />
|
||||
<ClInclude Include="..\emuware\msvc\inttypes.h" />
|
||||
|
|
|
@ -226,6 +226,9 @@
|
|||
<ClInclude Include="..\emuware\EW_state.h">
|
||||
<Filter>emuware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\cdrom\SimpleFIFO.h">
|
||||
<Filter>cdrom</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\psx\gpu_command_table.inc">
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#include "../mednafen.h"
|
||||
#include "SimpleFIFO.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -29,9 +29,10 @@ class SimpleFIFO
|
|||
|
||||
INLINE void SaveStatePostLoad(void)
|
||||
{
|
||||
read_pos %= data.size();
|
||||
write_pos %= data.size();
|
||||
in_count %= (data.size() + 1);
|
||||
//I think this is crap about file format (buffer size) change recovery. screw it.
|
||||
//read_pos %= data.size();
|
||||
//write_pos %= data.size();
|
||||
//in_count %= (data.size() + 1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -134,6 +135,20 @@ class SimpleFIFO
|
|||
uint32 read_pos; // Read position
|
||||
uint32 write_pos; // Write position
|
||||
uint32 in_count; // Number of units in the FIFO
|
||||
|
||||
template<bool isReader> void SyncState(EW::NewState *ns)
|
||||
{
|
||||
//I dont like this class...
|
||||
|
||||
PSS(&data[0], data.capacity());
|
||||
NSS(read_pos);
|
||||
NSS(write_pos);
|
||||
NSS(in_count);
|
||||
|
||||
|
||||
SaveStatePostLoad();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "EW_state.h"
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace EW {
|
||||
|
||||
|
@ -56,13 +58,37 @@ void NewStateExternalFunctions::Load(void *ptr, size_t size, const char *name)
|
|||
{
|
||||
Load_(ptr, size, name);
|
||||
}
|
||||
void NewStateExternalFunctions::EnterSection(const char *name)
|
||||
|
||||
void NewStateExternalFunctions::EnterSection(const char *name, ...)
|
||||
{
|
||||
EnterSection_(name);
|
||||
//analysis: multiple passes to generate string not ideal, but there arent many sections.. so it should be OK. improvement would be special vararg overload
|
||||
va_list ap;
|
||||
va_start(ap,name);
|
||||
char easybuf[32];
|
||||
int size = vsnprintf(easybuf,0,name,ap);
|
||||
char *ptr = easybuf;
|
||||
if(size>31)
|
||||
ptr = (char*)malloc(size+1);
|
||||
vsprintf(ptr,name,ap);
|
||||
EnterSection_(ptr);
|
||||
if(ptr != easybuf)
|
||||
free(ptr);
|
||||
va_end(ap);
|
||||
}
|
||||
void NewStateExternalFunctions::ExitSection(const char *name)
|
||||
void NewStateExternalFunctions::ExitSection(const char *name, ...)
|
||||
{
|
||||
ExitSection_(name);
|
||||
va_list ap;
|
||||
va_start(ap,name);
|
||||
char easybuf[32];
|
||||
int size = vsnprintf(easybuf,0,name,ap);
|
||||
char *ptr = easybuf;
|
||||
if(size>31)
|
||||
ptr = (char*)malloc(size+1);
|
||||
vsprintf(ptr,name,ap);
|
||||
ExitSection_(ptr);
|
||||
if(ptr != easybuf)
|
||||
free(ptr);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ namespace EW
|
|||
public:
|
||||
virtual void Save(const void *ptr, size_t size, const char *name) = 0;
|
||||
virtual void Load(void *ptr, size_t size, const char *name) = 0;
|
||||
virtual void EnterSection(const char *name) { }
|
||||
virtual void ExitSection(const char *name) { }
|
||||
virtual void EnterSection(const char *name, ...) { }
|
||||
virtual void ExitSection(const char *name, ...) { }
|
||||
};
|
||||
|
||||
class NewStateDummy : public NewState
|
||||
|
@ -62,8 +62,8 @@ namespace EW
|
|||
NewStateExternalFunctions(const FPtrs *ff);
|
||||
virtual void Save(const void *ptr, size_t size, const char *name);
|
||||
virtual void Load(void *ptr, size_t size, const char *name);
|
||||
virtual void EnterSection(const char *name);
|
||||
virtual void ExitSection(const char *name);
|
||||
virtual void EnterSection(const char *name, ...);
|
||||
virtual void ExitSection(const char *name, ...);
|
||||
};
|
||||
|
||||
// defines and explicitly instantiates
|
||||
|
|
|
@ -215,99 +215,83 @@ void PS_CDC::Power(void)
|
|||
lastts = 0;
|
||||
}
|
||||
|
||||
int PS_CDC::StateAction(StateMem *sm, int load, int data_only)
|
||||
SYNCFUNC(PS_CDC)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(DiscChanged),
|
||||
SFVAR(DiscStartupDelay),
|
||||
NSS(DiscChanged);
|
||||
NSS(DiscStartupDelay);
|
||||
|
||||
SFARRAY16(&AudioBuffer.Samples[0][0], sizeof(AudioBuffer.Samples) / sizeof(AudioBuffer.Samples[0][0])),
|
||||
SFVAR(AudioBuffer.Size),
|
||||
SFVAR(AudioBuffer.Freq),
|
||||
SFVAR(AudioBuffer.ReadPos),
|
||||
NSS(AudioBuffer);
|
||||
|
||||
SFARRAY(&Pending_DecodeVolume[0][0], 2 * 2),
|
||||
SFARRAY(&DecodeVolume[0][0], 2 * 2),
|
||||
NSS(Pending_DecodeVolume);
|
||||
NSS(DecodeVolume);
|
||||
|
||||
SFARRAY16(&ADPCM_ResampBuf[0][0], sizeof(ADPCM_ResampBuf) / sizeof(ADPCM_ResampBuf[0][0])),
|
||||
SFVAR(ADPCM_ResampCurPhase),
|
||||
SFVAR(ADPCM_ResampCurPos),
|
||||
NSS(ADPCM_ResampBuf);
|
||||
NSS(ADPCM_ResampCurPhase);
|
||||
NSS(ADPCM_ResampCurPos);
|
||||
|
||||
NSS(RegSelector);
|
||||
NSS(ArgsBuf);
|
||||
NSS(ArgsWP);
|
||||
NSS(ArgsRP);
|
||||
|
||||
NSS(ArgsReceiveLatch);
|
||||
NSS(ArgsReceiveBuf);
|
||||
NSS(ArgsReceiveIn);
|
||||
|
||||
NSS(ResultsBuffer);
|
||||
NSS(ResultsIn);
|
||||
NSS(ResultsWP);
|
||||
NSS(ResultsRP);
|
||||
|
||||
SSS(DMABuffer);
|
||||
|
||||
NSS(SB);
|
||||
NSS(SB_In);
|
||||
|
||||
NSS(SectorPipe);
|
||||
NSS(SectorPipe_Pos);
|
||||
NSS(SectorPipe_In);
|
||||
|
||||
NSS(SubQBuf);
|
||||
NSS(SubQBuf_Safe);
|
||||
|
||||
NSS(SubQChecksumOK);
|
||||
|
||||
NSS(HeaderBufValid);
|
||||
NSS(HeaderBuf);
|
||||
|
||||
NSS(IRQBuffer);
|
||||
NSS(IRQOutTestMask);
|
||||
NSS(CDCReadyReceiveCounter);
|
||||
|
||||
|
||||
NSS(FilterFile);
|
||||
NSS(FilterChan);
|
||||
|
||||
SFVAR(RegSelector),
|
||||
SFARRAY(ArgsBuf, 16),
|
||||
SFVAR(ArgsWP),
|
||||
SFVAR(ArgsRP),
|
||||
NSS(PendingCommand);
|
||||
NSS(PendingCommandPhase);
|
||||
NSS(PendingCommandCounter);
|
||||
|
||||
SFVAR(ArgsReceiveLatch),
|
||||
SFARRAY(ArgsReceiveBuf, 32),
|
||||
SFVAR(ArgsReceiveIn),
|
||||
NSS(SPUCounter);
|
||||
|
||||
SFARRAY(ResultsBuffer, 16),
|
||||
SFVAR(ResultsIn),
|
||||
SFVAR(ResultsWP),
|
||||
SFVAR(ResultsRP),
|
||||
NSS(Mode);
|
||||
NSS(DriveStatus);
|
||||
NSS(StatusAfterSeek);
|
||||
NSS(Forward);
|
||||
NSS(Backward);
|
||||
NSS(Muted);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
SFARRAY(&DMABuffer.data[0], DMABuffer.data.size()),
|
||||
SFVAR(DMABuffer.read_pos),
|
||||
SFVAR(DMABuffer.write_pos),
|
||||
SFVAR(DMABuffer.in_count),
|
||||
//
|
||||
//
|
||||
//
|
||||
NSS(PlayTrackMatch);
|
||||
|
||||
SFARRAY(SB, sizeof(SB) / sizeof(SB[0])),
|
||||
SFVAR(SB_In),
|
||||
NSS(PSRCounter);
|
||||
|
||||
SFARRAY(&SectorPipe[0][0], sizeof(SectorPipe) / sizeof(SectorPipe[0][0])),
|
||||
SFVAR(SectorPipe_Pos),
|
||||
SFVAR(SectorPipe_In),
|
||||
NSS(CurSector);
|
||||
|
||||
SFARRAY(SubQBuf, sizeof(SubQBuf) / sizeof(SubQBuf[0])),
|
||||
SFARRAY(SubQBuf_Safe, sizeof(SubQBuf_Safe) / sizeof(SubQBuf_Safe[0])),
|
||||
NSS(AsyncIRQPending);
|
||||
NSS(AsyncResultsPending);
|
||||
NSS(AsyncResultsPendingCount);
|
||||
|
||||
SFVAR(SubQChecksumOK),
|
||||
|
||||
SFVAR(HeaderBufValid),
|
||||
SFARRAY(HeaderBuf, sizeof(HeaderBuf) / sizeof(HeaderBuf[0])),
|
||||
|
||||
SFVAR(IRQBuffer),
|
||||
SFVAR(IRQOutTestMask),
|
||||
SFVAR(CDCReadyReceiveCounter),
|
||||
|
||||
|
||||
SFVAR(FilterFile),
|
||||
SFVAR(FilterChan),
|
||||
|
||||
SFVAR(PendingCommand),
|
||||
SFVAR(PendingCommandPhase),
|
||||
SFVAR(PendingCommandCounter),
|
||||
|
||||
SFVAR(SPUCounter),
|
||||
|
||||
SFVAR(Mode),
|
||||
SFVAR(DriveStatus),
|
||||
SFVAR(StatusAfterSeek),
|
||||
SFVAR(Forward),
|
||||
SFVAR(Backward),
|
||||
SFVAR(Muted),
|
||||
|
||||
SFVAR(PlayTrackMatch),
|
||||
|
||||
SFVAR(PSRCounter),
|
||||
|
||||
SFVAR(CurSector),
|
||||
|
||||
SFVAR(AsyncIRQPending),
|
||||
SFARRAY(AsyncResultsPending, sizeof(AsyncResultsPending) / sizeof(AsyncResultsPending[0])),
|
||||
SFVAR(AsyncResultsPendingCount),
|
||||
|
||||
SFVAR(SeekTarget),
|
||||
NSS(SeekTarget);
|
||||
|
||||
// FIXME: Save TOC stuff?
|
||||
#if 0
|
||||
|
@ -316,27 +300,17 @@ int PS_CDC::StateAction(StateMem *sm, int load, int data_only)
|
|||
uint8 DiscID[4];
|
||||
#endif
|
||||
|
||||
SFVAR(CommandLoc),
|
||||
SFVAR(CommandLoc_Dirty),
|
||||
SFARRAY16(&xa_previous[0][0], sizeof(xa_previous) / sizeof(xa_previous[0][0])),
|
||||
NSS(CommandLoc);
|
||||
NSS(CommandLoc_Dirty);
|
||||
NSS(xa_previous);
|
||||
|
||||
SFVAR(xa_cur_set),
|
||||
SFVAR(xa_cur_file),
|
||||
SFVAR(xa_cur_chan),
|
||||
NSS(xa_cur_set);
|
||||
NSS(xa_cur_file);
|
||||
NSS(xa_cur_chan);
|
||||
|
||||
SFVAR(ReportLastF),
|
||||
NSS(ReportLastF);
|
||||
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "CDC");
|
||||
|
||||
if(load)
|
||||
{
|
||||
DMABuffer.SaveStatePostLoad();
|
||||
SectorPipe_Pos %= SectorPipe_Count;
|
||||
}
|
||||
return(ret);
|
||||
//(%= crap about file format recovery in case SectorPipe_Pos changes)
|
||||
}
|
||||
|
||||
void PS_CDC::ResetTS(void)
|
||||
|
|
|
@ -25,6 +25,8 @@ class PS_CDC
|
|||
PS_CDC();
|
||||
~PS_CDC();
|
||||
|
||||
template<bool isReader>void SyncState(EW::NewState *ns);
|
||||
|
||||
void SetDisc(bool tray_open, ShockDiscRef *disc, const char disc_id[4]);
|
||||
|
||||
void Power(void);
|
||||
|
|
|
@ -951,4 +951,39 @@ void PS_CPU::CheckBreakpoints(void (*callback)(bool write, uint32_t address, uns
|
|||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
SYNCFUNC(PS_CPU)
|
||||
{
|
||||
NSS(GPR);
|
||||
NSS(LO);
|
||||
NSS(HI);
|
||||
NSS(BACKED_PC);
|
||||
NSS(BACKED_new_PC);
|
||||
NSS(BACKED_new_PC_mask);
|
||||
|
||||
NSS(IPCache);
|
||||
NSS(Halted);
|
||||
|
||||
NSS(BACKED_LDWhich);
|
||||
NSS(BACKED_LDValue);
|
||||
NSS(LDAbsorb);
|
||||
|
||||
NSS(next_event_ts);
|
||||
NSS(gte_ts_done);
|
||||
NSS(muldiv_ts_done);
|
||||
|
||||
NSS(BIU);
|
||||
NSS(ICache_Bulk);
|
||||
|
||||
NSS(CP0.Regs);
|
||||
|
||||
NSS(ReadAbsorb);
|
||||
NSS(ReadAbsorbDummy);
|
||||
NSS(ReadAbsorbWhich);
|
||||
NSS(ReadFudge);
|
||||
|
||||
NSS(ScratchRAM.data8);
|
||||
|
||||
} //SYNCFUNC(CPU)
|
||||
|
||||
} //namespace MDFN_IEN_PSX
|
||||
|
|
|
@ -52,6 +52,8 @@ class PS_CPU
|
|||
PS_CPU();
|
||||
~PS_CPU();
|
||||
|
||||
template<bool isReader>void SyncState(EW::NewState *ns);
|
||||
|
||||
// FAST_MAP_* enums are in BYTES(8-bit), not in 32-bit units("words" in MIPS context), but the sizes
|
||||
// will always be multiples of 4.
|
||||
enum { FAST_MAP_SHIFT = 16 };
|
||||
|
|
|
@ -777,44 +777,14 @@ uint32 DMA_Read(const pscpu_timestamp_t timestamp, uint32 A)
|
|||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
int DMA_StateAction(StateMem *sm, int load, int data_only)
|
||||
void DMA_SyncState(bool isReader, EW::NewState *ns)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(DMACycleCounter),
|
||||
SFVAR(DMAControl),
|
||||
SFVAR(DMAIntControl),
|
||||
SFVAR(DMAIntStatus),
|
||||
SFVAR(IRQOut),
|
||||
|
||||
#define SFDMACH(n) SFVARN(DMACH[n].BaseAddr, #n "BaseAddr"), \
|
||||
SFVARN(DMACH[n].BlockControl, #n "BlockControl"), \
|
||||
SFVARN(DMACH[n].ChanControl, #n "ChanControl"), \
|
||||
SFVARN(DMACH[n].CurAddr, #n "CurAddr"), \
|
||||
SFVARN(DMACH[n].WordCounter, #n "WordCounter"), \
|
||||
SFVARN(DMACH[n].ClockCounter, #n "ClockCounter")
|
||||
|
||||
SFDMACH(0),
|
||||
SFDMACH(1),
|
||||
SFDMACH(2),
|
||||
SFDMACH(3),
|
||||
SFDMACH(4),
|
||||
SFDMACH(5),
|
||||
SFDMACH(6),
|
||||
|
||||
#undef SFDMACH
|
||||
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "DMA");
|
||||
|
||||
if(load)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return(ret);
|
||||
NSS(DMACycleCounter);
|
||||
NSS(DMAControl);
|
||||
NSS(DMAIntControl);
|
||||
NSS(DMAIntStatus);
|
||||
NSS(IRQOut);
|
||||
NSS(DMACH);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -141,9 +141,10 @@ FrontIO::FrontIO()
|
|||
MCPorts[i] = new InputDevice();
|
||||
}
|
||||
|
||||
//always add one memory device for now
|
||||
//always add one memory device for now
|
||||
delete MCPorts[0];
|
||||
MCPorts[0] = Device_Memcard_Create();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FrontIO::~FrontIO()
|
||||
|
@ -625,6 +626,68 @@ uint64 FrontIO::GetMemcardDirtyCount(unsigned int which)
|
|||
return(MCPorts[which]->GetNVDirtyCount());
|
||||
}
|
||||
|
||||
//TODO - ok, savestating varying input devices. this is tricky.
|
||||
//its like... what happens when the hardware unfreezes with different input attached?
|
||||
//thats some kind of instantaneous change event which shouldnt/cant be properly emulated or likely even implemented
|
||||
//so in that respect it's very much like (if not identical to) CDs.
|
||||
//heres a discussion question. what are we doing here? savestating the CONSOLE or savestating the ENTIRE SYSTEM?
|
||||
//well, what's being emulated?
|
||||
//I dont know. lets save it for later.
|
||||
//You know, this is one reason mednafen had a distinction between ports and devices.
|
||||
//But I had to get rid of it, I just had to. At least they need to be organized into a pool differently somehow.
|
||||
|
||||
//Anyway, think about this: We cant just savestate the entire system. The game will be depending on the input devices being in a certain state.
|
||||
//If theyre in any other state, literally, any other state, then the game will fail.
|
||||
//Therefore the entire system needs saving together and mismatches MUST NOT BE PERMITTED.
|
||||
|
||||
SYNCFUNC(FrontIO)
|
||||
{
|
||||
NSS(ClockDivider);
|
||||
|
||||
NSS(ReceivePending);
|
||||
NSS(TransmitPending);
|
||||
|
||||
NSS(ReceiveInProgress);
|
||||
NSS(TransmitInProgress);
|
||||
|
||||
NSS(ReceiveBufferAvail);
|
||||
|
||||
NSS(ReceiveBuffer);
|
||||
NSS(TransmitBuffer);
|
||||
|
||||
NSS(ReceiveBitCounter);
|
||||
NSS(TransmitBitCounter);
|
||||
|
||||
NSS(Mode);
|
||||
NSS(Control);
|
||||
NSS(Baudrate);
|
||||
|
||||
NSS(istatus);
|
||||
|
||||
// FIXME: Step mode save states.
|
||||
NSS(irq10_pulse_ts);
|
||||
NSS(dsr_pulse_delay);
|
||||
NSS(dsr_active_until_ts);
|
||||
|
||||
//state actions for ports and such
|
||||
for(int i=0;i<2;i++)
|
||||
{
|
||||
ns->EnterSection("PORT%d",i);
|
||||
Ports[i]->SyncState(isReader,ns);
|
||||
ns->ExitSection("PORT%d",i);
|
||||
ns->EnterSection("MCPORT%d",i);
|
||||
MCPorts[i]->SyncState(isReader,ns);
|
||||
ns->ExitSection("MCPORT%d",i);
|
||||
}
|
||||
|
||||
//more of this crap....
|
||||
if(isReader)
|
||||
{
|
||||
IRQ_Assert(IRQ_SIO, istatus);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int FrontIO::StateAction(StateMem* sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
|
|
|
@ -15,6 +15,8 @@ class InputDevice
|
|||
|
||||
virtual void Power(void);
|
||||
virtual void UpdateInput(const void *data);
|
||||
|
||||
virtual void SyncState(bool isReader, EW::NewState *ns) {}
|
||||
virtual int StateAction(StateMem* sm, int load, int data_only, const char* section_name);
|
||||
|
||||
virtual bool RequireNoFrameskip(void);
|
||||
|
@ -61,6 +63,8 @@ class FrontIO
|
|||
FrontIO();
|
||||
~FrontIO();
|
||||
|
||||
template<bool isReader>void SyncState(EW::NewState *ns);
|
||||
|
||||
void Power(void);
|
||||
void Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V);
|
||||
uint32 Read(pscpu_timestamp_t timestamp, uint32 A);
|
||||
|
|
|
@ -1573,119 +1573,105 @@ void PS_GPU::StartFrame(EmulateSpecStruct *espec_arg)
|
|||
}
|
||||
}
|
||||
|
||||
int PS_GPU::StateAction(StateMem *sm, int load, int data_only)
|
||||
SYNCFUNC(PS_GPU)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY16(&GPURAM[0][0], sizeof(GPURAM) / sizeof(GPURAM[0][0])),
|
||||
NSS(GPURAM);
|
||||
|
||||
SFVAR(DMAControl),
|
||||
NSS(DMAControl);
|
||||
|
||||
SFVAR(ClipX0),
|
||||
SFVAR(ClipY0),
|
||||
SFVAR(ClipX1),
|
||||
SFVAR(ClipY1),
|
||||
NSS(ClipX0);
|
||||
NSS(ClipY0);
|
||||
NSS(ClipX1);
|
||||
NSS(ClipY1);
|
||||
|
||||
SFVAR(OffsX),
|
||||
SFVAR(OffsY),
|
||||
NSS(OffsX);
|
||||
NSS(OffsY);
|
||||
|
||||
SFVAR(dtd),
|
||||
SFVAR(dfe),
|
||||
NSS(dtd);
|
||||
NSS(dfe);
|
||||
|
||||
SFVAR(MaskSetOR),
|
||||
SFVAR(MaskEvalAND),
|
||||
NSS(MaskSetOR);
|
||||
NSS(MaskEvalAND);
|
||||
|
||||
SFVAR(tww),
|
||||
SFVAR(twh),
|
||||
SFVAR(twx),
|
||||
SFVAR(twy),
|
||||
NSS(tww);
|
||||
NSS(twh);
|
||||
NSS(twx);
|
||||
NSS(twy);
|
||||
|
||||
SFVAR(TexPageX),
|
||||
SFVAR(TexPageY),
|
||||
NSS(TexPageX);
|
||||
NSS(TexPageY);
|
||||
|
||||
SFVAR(SpriteFlip),
|
||||
NSS(SpriteFlip);
|
||||
|
||||
SFVAR(abr),
|
||||
SFVAR(TexMode),
|
||||
NSS(abr);
|
||||
NSS(TexMode);
|
||||
|
||||
SFARRAY32(&BlitterFIFO.data[0], BlitterFIFO.data.size()),
|
||||
SFVAR(BlitterFIFO.read_pos),
|
||||
SFVAR(BlitterFIFO.write_pos),
|
||||
SFVAR(BlitterFIFO.in_count),
|
||||
SSS(BlitterFIFO);
|
||||
|
||||
SFVAR(DataReadBuffer),
|
||||
NSS(DataReadBuffer);
|
||||
|
||||
SFVAR(IRQPending),
|
||||
NSS(IRQPending);
|
||||
|
||||
SFVAR(InCmd),
|
||||
SFVAR(InCmd_CC),
|
||||
NSS(InCmd);
|
||||
NSS(InCmd_CC);
|
||||
|
||||
#define TVHELPER(n) SFVAR(n.x), SFVAR(n.y), SFVAR(n.u), SFVAR(n.v), SFVAR(n.r), SFVAR(n.g), SFVAR(n.b)
|
||||
TVHELPER(InQuad_F3Vertices[0]),
|
||||
TVHELPER(InQuad_F3Vertices[1]),
|
||||
TVHELPER(InQuad_F3Vertices[2]),
|
||||
#undef TVHELPER
|
||||
SFVAR(InQuad_clut),
|
||||
NSS(InQuad_F3Vertices);
|
||||
|
||||
SFVAR(InPLine_PrevPoint.x),
|
||||
SFVAR(InPLine_PrevPoint.y),
|
||||
SFVAR(InPLine_PrevPoint.r),
|
||||
SFVAR(InPLine_PrevPoint.g),
|
||||
SFVAR(InPLine_PrevPoint.b),
|
||||
NSS(InQuad_clut);
|
||||
|
||||
SFVAR(FBRW_X),
|
||||
SFVAR(FBRW_Y),
|
||||
SFVAR(FBRW_W),
|
||||
SFVAR(FBRW_H),
|
||||
SFVAR(FBRW_CurY),
|
||||
SFVAR(FBRW_CurX),
|
||||
NSS(InPLine_PrevPoint);
|
||||
|
||||
SFVAR(DisplayMode),
|
||||
SFVAR(DisplayOff),
|
||||
SFVAR(DisplayFB_XStart),
|
||||
SFVAR(DisplayFB_YStart),
|
||||
NSS(FBRW_X);
|
||||
NSS(FBRW_Y);
|
||||
NSS(FBRW_W);
|
||||
NSS(FBRW_H);
|
||||
NSS(FBRW_CurY);
|
||||
NSS(FBRW_CurX);
|
||||
|
||||
SFVAR(HorizStart),
|
||||
SFVAR(HorizEnd),
|
||||
NSS(DisplayMode);
|
||||
NSS(DisplayOff);
|
||||
NSS(DisplayFB_XStart);
|
||||
NSS(DisplayFB_YStart);
|
||||
|
||||
SFVAR(VertStart),
|
||||
SFVAR(VertEnd),
|
||||
NSS(HorizStart);
|
||||
NSS(HorizEnd);
|
||||
|
||||
SFVAR(DisplayFB_CurYOffset),
|
||||
SFVAR(DisplayFB_CurLineYReadout),
|
||||
NSS(VertStart);
|
||||
NSS(VertEnd);
|
||||
|
||||
SFVAR(InVBlank),
|
||||
NSS(DisplayFB_CurYOffset);
|
||||
NSS(DisplayFB_CurLineYReadout);
|
||||
|
||||
SFVAR(LinesPerField),
|
||||
SFVAR(scanline),
|
||||
SFVAR(field),
|
||||
SFVAR(field_ram_readout),
|
||||
SFVAR(PhaseChange),
|
||||
NSS(InVBlank);
|
||||
|
||||
SFVAR(DotClockCounter),
|
||||
NSS(LinesPerField);
|
||||
NSS(scanline);
|
||||
NSS(field);
|
||||
NSS(field_ram_readout);
|
||||
NSS(PhaseChange);
|
||||
|
||||
SFVAR(GPUClockCounter),
|
||||
SFVAR(LineClockCounter),
|
||||
SFVAR(LinePhase),
|
||||
NSS(DotClockCounter);
|
||||
|
||||
SFVAR(DrawTimeAvail),
|
||||
NSS(GPUClockCounter);
|
||||
NSS(LineClockCounter);
|
||||
NSS(LinePhase);
|
||||
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "GPU");
|
||||
NSS(DrawTimeAvail);
|
||||
|
||||
if(load)
|
||||
{
|
||||
RecalcTexWindowLUT();
|
||||
BlitterFIFO.SaveStatePostLoad();
|
||||
if(isReader)
|
||||
{
|
||||
//cached luts; safe not to sync
|
||||
RecalcTexWindowLUT();
|
||||
|
||||
HorizStart &= 0xFFF;
|
||||
HorizEnd &= 0xFFF;
|
||||
//what the hell is this? I dont like it at all.
|
||||
HorizStart &= 0xFFF;
|
||||
HorizEnd &= 0xFFF;
|
||||
|
||||
IRQ_Assert(IRQ_GPU, IRQPending);
|
||||
}
|
||||
//this is kind of typical stuff, BUT: a cursory inspection reveals nothing. the IRQ and CPU modules should be handling it OK
|
||||
//LOOK HERE FOR BUGS
|
||||
IRQ_Assert(IRQ_GPU, IRQPending);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ class PS_GPU
|
|||
PS_GPU(bool pal_clock_and_tv, int sls, int sle) MDFN_COLD;
|
||||
~PS_GPU() MDFN_COLD;
|
||||
|
||||
template<bool isReader>void SyncState(EW::NewState *ns);
|
||||
|
||||
void FillVideoParams(MDFNGI* gi) MDFN_COLD;
|
||||
|
||||
void Power(void) MDFN_COLD;
|
||||
|
|
|
@ -233,63 +233,11 @@ void GTE_Power(void)
|
|||
Reg23 = 0;
|
||||
}
|
||||
|
||||
// TODO: Don't save redundant state, regarding CR cache variables
|
||||
int GTE_StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFARRAY32(CR, 32),
|
||||
SFVAR(FLAGS),
|
||||
|
||||
SFARRAY16(&Matrices.Raw16[0][0], 4 * 10),
|
||||
return 1;
|
||||
|
||||
SFARRAY32(&CRVectors.All[0][0], 4 * 4),
|
||||
|
||||
SFVAR(OFX),
|
||||
SFVAR(OFY),
|
||||
SFVAR(H),
|
||||
SFVAR(DQA),
|
||||
SFVAR(DQB),
|
||||
|
||||
SFVAR(ZSF3),
|
||||
SFVAR(ZSF4),
|
||||
SFARRAY16(&Vectors[0][0], 3 * 4),
|
||||
|
||||
SFARRAY(RGB.Raw8, 4),
|
||||
SFVAR(OTZ),
|
||||
SFARRAY16(IR, 4),
|
||||
|
||||
SFVAR(XY_FIFO[0].X),
|
||||
SFVAR(XY_FIFO[0].Y),
|
||||
SFVAR(XY_FIFO[1].X),
|
||||
SFVAR(XY_FIFO[1].Y),
|
||||
SFVAR(XY_FIFO[2].X),
|
||||
SFVAR(XY_FIFO[2].Y),
|
||||
SFVAR(XY_FIFO[3].X),
|
||||
SFVAR(XY_FIFO[3].Y),
|
||||
|
||||
SFARRAY16(Z_FIFO, 4),
|
||||
|
||||
SFARRAY(RGB_FIFO[0].Raw8, 4),
|
||||
SFARRAY(RGB_FIFO[1].Raw8, 4),
|
||||
SFARRAY(RGB_FIFO[2].Raw8, 4),
|
||||
|
||||
SFARRAY32(MAC, 4),
|
||||
|
||||
SFVAR(LZCS),
|
||||
SFVAR(LZCR),
|
||||
SFVAR(Reg23),
|
||||
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "GTE");
|
||||
|
||||
if(load)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1731,6 +1679,43 @@ int32 GTE_Instruction(uint32 instr)
|
|||
return(ret - 1);
|
||||
}
|
||||
|
||||
void GTE_SyncState(bool isReader, EW::NewState *ns)
|
||||
{
|
||||
NSS(CR);
|
||||
NSS(FLAGS);
|
||||
|
||||
NSS(Matrices);
|
||||
|
||||
NSS(CRVectors);
|
||||
|
||||
NSS(OFX);
|
||||
NSS(OFY);
|
||||
NSS(H);
|
||||
NSS(DQA);
|
||||
NSS(DQB);
|
||||
|
||||
NSS(ZSF3);
|
||||
NSS(ZSF4);
|
||||
NSS(Vectors);
|
||||
|
||||
NSS(RGB);
|
||||
NSS(OTZ);
|
||||
NSS(IR);
|
||||
|
||||
NSS(XY_FIFO);
|
||||
|
||||
NSS(Z_FIFO);
|
||||
|
||||
NSS(RGB_FIFO);
|
||||
|
||||
NSS(MAC);
|
||||
|
||||
NSS(LZCS);
|
||||
NSS(LZCR);
|
||||
NSS(Reg23);
|
||||
}
|
||||
|
||||
#ifndef PSXDEV_GTE_TESTING
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ class InputDevice_DualShock : public InputDevice
|
|||
virtual ~InputDevice_DualShock();
|
||||
|
||||
virtual void Power(void);
|
||||
virtual int StateAction(StateMem* sm, int load, int data_only, const char* section_name);
|
||||
virtual void SyncState(bool isReader, EW::NewState *ns);
|
||||
|
||||
virtual void Update(const pscpu_timestamp_t timestamp);
|
||||
virtual void ResetTS(void);
|
||||
|
@ -232,56 +232,40 @@ void InputDevice_DualShock::Power(void)
|
|||
prev_ana_button_state = false;
|
||||
}
|
||||
|
||||
int InputDevice_DualShock::StateAction(StateMem* sm, int load, int data_only, const char* section_name)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
void InputDevice_DualShock::SyncState(bool isReader, EW::NewState *ns)
|
||||
{
|
||||
SFVAR(cur_ana_button_state),
|
||||
SFVAR(prev_ana_button_state),
|
||||
SFVAR(combo_anatoggle_counter),
|
||||
NSS(cur_ana_button_state);
|
||||
NSS(prev_ana_button_state);
|
||||
NSS(combo_anatoggle_counter);
|
||||
|
||||
SFVAR(da_rumble_compat),
|
||||
NSS(da_rumble_compat);
|
||||
|
||||
SFVAR(analog_mode),
|
||||
SFVAR(analog_mode_locked),
|
||||
NSS(analog_mode);
|
||||
NSS(analog_mode_locked);
|
||||
|
||||
SFVAR(mad_munchkins),
|
||||
SFARRAY(rumble_magic, sizeof(rumble_magic)),
|
||||
NSS(mad_munchkins);
|
||||
NSS(rumble_magic);
|
||||
|
||||
SFARRAY(rumble_param, sizeof(rumble_param)),
|
||||
NSS(rumble_param);
|
||||
|
||||
SFVAR(dtr),
|
||||
NSS(dtr);
|
||||
|
||||
SFARRAY(buttons, sizeof(buttons)),
|
||||
SFARRAY(&axes[0][0], sizeof(axes)),
|
||||
NSS(buttons);
|
||||
NSS(axes);
|
||||
|
||||
SFVAR(command_phase),
|
||||
SFVAR(bitpos),
|
||||
SFVAR(receive_buffer),
|
||||
NSS(command_phase);
|
||||
NSS(bitpos);
|
||||
NSS(receive_buffer);
|
||||
|
||||
SFVAR(command),
|
||||
NSS(command);
|
||||
|
||||
SFARRAY(transmit_buffer, sizeof(transmit_buffer)),
|
||||
SFVAR(transmit_pos),
|
||||
SFVAR(transmit_count),
|
||||
NSS(transmit_buffer);
|
||||
NSS(transmit_pos);
|
||||
NSS(transmit_count);
|
||||
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name);
|
||||
|
||||
if(load)
|
||||
{
|
||||
if((transmit_pos + transmit_count) > sizeof(transmit_buffer))
|
||||
{
|
||||
transmit_pos = 0;
|
||||
transmit_count = 0;
|
||||
}
|
||||
//THERES MORE BUFFER SIZE SANITY CHECKS HERE. DONT LIKE THAT STUFF
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
void InputDevice_DualShock::UpdateInput(const void *data)
|
||||
{
|
||||
uint8 *d8 = (uint8 *)data;
|
||||
|
|
|
@ -41,7 +41,7 @@ class InputDevice_Memcard : public InputDevice
|
|||
|
||||
virtual void Power(void);
|
||||
virtual int StateAction(StateMem* sm, int load, int data_only, const char* section_name);
|
||||
|
||||
virtual void SyncState(bool isReader, EW::NewState *ns);
|
||||
//
|
||||
//
|
||||
//
|
||||
|
@ -162,6 +162,38 @@ void InputDevice_Memcard::Power(void)
|
|||
presence_new = true;
|
||||
}
|
||||
|
||||
void InputDevice_Memcard::SyncState(bool isReader, EW::NewState *ns)
|
||||
{
|
||||
NSS(presence_new);
|
||||
|
||||
NSS(rw_buffer);
|
||||
NSS(write_xor);
|
||||
|
||||
NSS(dtr);
|
||||
NSS(command_phase);
|
||||
NSS(bitpos);
|
||||
NSS(receive_buffer);
|
||||
|
||||
NSS(command);
|
||||
NSS(addr);
|
||||
NSS(calced_xor);
|
||||
|
||||
NSS(transmit_buffer);
|
||||
NSS(transmit_count);
|
||||
|
||||
NSS(data_used);
|
||||
|
||||
//(now there was logic to avoid savestating cards that had never been used. only needed if we have a pool of cards)
|
||||
//(also it called Format() but I dont see how that makes sense at all and anyway I'm ignoring it)
|
||||
|
||||
//now for the BIG QUESTION, regarding clobber's lament.
|
||||
//we need to dump the contents of the card along with the register state. its necessary for safety.
|
||||
//HOWEVER - we clear the dirty flag. that way, a user wont accidentally `clobber` his savestates when loading a state.
|
||||
//instead, the state will only be dirtied when the game actually modifies the contents
|
||||
NSS(card_data);
|
||||
dirty_count = 0;
|
||||
}
|
||||
|
||||
int InputDevice_Memcard::StateAction(StateMem* sm, int load, int data_only, const char* section_name)
|
||||
{
|
||||
// Don't save dirty_count.
|
||||
|
|
|
@ -58,6 +58,19 @@ int IRQ_StateAction(StateMem *sm, int load, int data_only)
|
|||
}
|
||||
|
||||
|
||||
void IRQ_SyncState(bool isReader, EW::NewState *ns)
|
||||
{
|
||||
NSS(Asserted);
|
||||
NSS(Mask);
|
||||
NSS(Status);
|
||||
|
||||
//as usual, not sure why this is necessary
|
||||
if(isReader)
|
||||
{
|
||||
Recalc();
|
||||
}
|
||||
}
|
||||
|
||||
void IRQ_Assert(int which, bool status)
|
||||
{
|
||||
uint32 old_Asserted = Asserted;
|
||||
|
|
|
@ -164,64 +164,50 @@ void MDEC_Power(void)
|
|||
RAMOffsetWWS = 0;
|
||||
}
|
||||
|
||||
int MDEC_StateAction(StateMem *sm, int load, int data_only)
|
||||
template<bool isReader> void MDEC_SyncState(EW::NewState *ns)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(ClockCounter),
|
||||
SFVAR(MDRPhase),
|
||||
NSS(ClockCounter);
|
||||
NSS(MDRPhase);
|
||||
|
||||
#define SFFIFO32(fifoobj) SFARRAY32(&fifoobj.data[0], fifoobj.data.size()), \
|
||||
SFVAR(fifoobj.read_pos), \
|
||||
SFVAR(fifoobj.write_pos), \
|
||||
SFVAR(fifoobj.in_count)
|
||||
SSS(InFIFO);
|
||||
SSS(OutFIFO);
|
||||
|
||||
SFFIFO32(InFIFO),
|
||||
SFFIFO32(OutFIFO),
|
||||
#undef SFFIFO
|
||||
NSS(block_y);
|
||||
NSS(block_cb);
|
||||
NSS(block_cr);
|
||||
|
||||
SFARRAY(&block_y[0][0], sizeof(block_y) / sizeof(block_y[0][0])),
|
||||
SFARRAY(&block_cb[0][0], sizeof(block_cb) / sizeof(block_cb[0][0])),
|
||||
SFARRAY(&block_cr[0][0], sizeof(block_cr) / sizeof(block_cr[0][0])),
|
||||
NSS(Control);
|
||||
NSS(Command);
|
||||
NSS(InCommand);
|
||||
|
||||
SFVAR(Control),
|
||||
SFVAR(Command),
|
||||
SFVAR(InCommand),
|
||||
NSS(QMatrix);
|
||||
NSS(QMIndex);
|
||||
|
||||
SFARRAY(&QMatrix[0][0], sizeof(QMatrix) / sizeof(QMatrix[0][0])),
|
||||
SFVAR(QMIndex),
|
||||
NSS(IDCTMatrix);
|
||||
NSS(IDCTMIndex);
|
||||
|
||||
SFARRAY16(&IDCTMatrix[0], sizeof(IDCTMatrix) / sizeof(IDCTMatrix[0])),
|
||||
SFVAR(IDCTMIndex),
|
||||
NSS(QScale);
|
||||
|
||||
SFVAR(QScale),
|
||||
NSS(Coeff);
|
||||
NSS(CoeffIndex);
|
||||
NSS(DecodeWB);
|
||||
|
||||
SFARRAY16(&Coeff[0], sizeof(Coeff) / sizeof(Coeff[0])),
|
||||
SFVAR(CoeffIndex),
|
||||
SFVAR(DecodeWB),
|
||||
NSS(PixelBuffer);
|
||||
NSS(PixelBufferReadOffset);
|
||||
NSS(PixelBufferCount32);
|
||||
|
||||
SFARRAY32(&PixelBuffer.pix32[0], sizeof(PixelBuffer.pix32) / sizeof(PixelBuffer.pix32[0])),
|
||||
SFVAR(PixelBufferReadOffset),
|
||||
SFVAR(PixelBufferCount32),
|
||||
NSS(InCounter);
|
||||
|
||||
SFVAR(InCounter),
|
||||
NSS(RAMOffsetY);
|
||||
NSS(RAMOffsetCounter);
|
||||
NSS(RAMOffsetWWS);
|
||||
|
||||
SFVAR(RAMOffsetY),
|
||||
SFVAR(RAMOffsetCounter),
|
||||
SFVAR(RAMOffsetWWS),
|
||||
}
|
||||
|
||||
SFEND
|
||||
};
|
||||
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "MDEC");
|
||||
|
||||
if(load)
|
||||
{
|
||||
InFIFO.SaveStatePostLoad();
|
||||
OutFIFO.SaveStatePostLoad();
|
||||
}
|
||||
|
||||
return(ret);
|
||||
void MDEC_SyncState(bool isReader, EW::NewState *ns)
|
||||
{
|
||||
if(isReader) MDEC_SyncState<true>(ns);
|
||||
else MDEC_SyncState<false>(ns);
|
||||
}
|
||||
|
||||
static INLINE int8 Mask9ClampS8(int32 v)
|
||||
|
|
|
@ -1116,6 +1116,7 @@ struct {
|
|||
|
||||
case eShockMemcardTransaction_Write:
|
||||
FIO->MCPorts[portnum]->WriteNV((uint8*)transaction->buffer128k,0,128*1024);
|
||||
FIO->MCPorts[portnum]->ResetNVDirtyCount();
|
||||
return SHOCK_OK;
|
||||
|
||||
case eShockMemcardTransaction_Read:
|
||||
|
@ -1825,62 +1826,6 @@ static void CloseGame(void)
|
|||
Cleanup();
|
||||
}
|
||||
|
||||
static int StateAction(StateMem *sm, int load, int data_only)
|
||||
{
|
||||
|
||||
//SFORMAT StateRegs[] =
|
||||
//{
|
||||
// NSS(CD_TrayOpen);
|
||||
// PSS(MainRAM.data8, 2*1024*1024);
|
||||
// NSS(SysControl.Regs, 9);
|
||||
|
||||
// //SFVAR(PSX_PRNG.lcgo),
|
||||
// //SFVAR(PSX_PRNG.x),
|
||||
// //SFVAR(PSX_PRNG.y),
|
||||
// //SFVAR(PSX_PRNG.z),
|
||||
// //SFVAR(PSX_PRNG.c),
|
||||
|
||||
// SFEND
|
||||
//};
|
||||
|
||||
//int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "MAIN");
|
||||
|
||||
//// Call SetDisc() BEFORE we load CDC state, since SetDisc() has emulation side effects. We might want to clean this up in the future.
|
||||
//if(load)
|
||||
//{
|
||||
// if(CD_SelectedDisc >= (int)cdifs->size())
|
||||
// CD_SelectedDisc = -1;
|
||||
|
||||
////DAW????????????
|
||||
//// CDC->SetDisc(CD_TrayOpen, (CD_SelectedDisc >= 0 && !CD_TrayOpen) ? (*cdifs)[CD_SelectedDisc] : NULL,
|
||||
////(CD_SelectedDisc >= 0 && !CD_TrayOpen) ? cdifs_scex_ids[CD_SelectedDisc] : NULL);
|
||||
//}
|
||||
|
||||
//// TODO: Remember to increment dirty count in memory card state loading routine.
|
||||
|
||||
//ret &= CPU->StateAction(sm, load, data_only);
|
||||
//ret &= DMA_StateAction(sm, load, data_only);
|
||||
//ret &= TIMER_StateAction(sm, load, data_only);
|
||||
//ret &= SIO_StateAction(sm, load, data_only);
|
||||
|
||||
//ret &= CDC->StateAction(sm, load, data_only);
|
||||
//ret &= MDEC_StateAction(sm, load, data_only);
|
||||
//ret &= GPU->StateAction(sm, load, data_only);
|
||||
//ret &= SPU->StateAction(sm, load, data_only);
|
||||
|
||||
//ret &= FIO->StateAction(sm, load, data_only);
|
||||
|
||||
//ret &= IRQ_StateAction(sm, load, data_only); // Do it last.
|
||||
|
||||
//if(load)
|
||||
//{
|
||||
// ForceEventUpdates(0); // FIXME to work with debugger step mode.
|
||||
//}
|
||||
|
||||
//return(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void CDInsertEject(void)
|
||||
{
|
||||
CD_TrayOpen = !CD_TrayOpen;
|
||||
|
@ -1922,6 +1867,10 @@ EW_EXPORT s32 shock_SetDisc(void* psx, ShockDiscRef* disc)
|
|||
s32 ret = shock_AnalyzeDisc(disc,&info);
|
||||
if(ret != SHOCK_OK) return ret;
|
||||
|
||||
//heres a comment from some old savestating code. something to keep in mind (maybe or maybe not a surprise depending on your point of view)
|
||||
//"Call SetDisc() BEFORE we load CDC state, since SetDisc() has emulation side effects. We might want to clean this up in the future."
|
||||
//I'm not really sure I like how SetDisc works, so I'm glad this was brought to our attention
|
||||
|
||||
s_CurrDiscInfo = info;
|
||||
s_CurrDisc = disc;
|
||||
CDC->SetDisc(true,s_CurrDisc,s_CurrDiscInfo.id);
|
||||
|
@ -2419,62 +2368,79 @@ public:
|
|||
template<bool isReader>void SyncState(EW::NewState *ns);
|
||||
} s_PSX;
|
||||
|
||||
//--OLD SAVESTATE--
|
||||
//SFORMAT StateRegs[] =
|
||||
//{
|
||||
// NSS(CD_TrayOpen);
|
||||
// PSS(MainRAM.data8, 2*1024*1024);
|
||||
// NSS(SysControl.Regs, 9);
|
||||
|
||||
// //SFVAR(PSX_PRNG.lcgo),
|
||||
// //SFVAR(PSX_PRNG.x),
|
||||
// //SFVAR(PSX_PRNG.y),
|
||||
// //SFVAR(PSX_PRNG.z),
|
||||
// //SFVAR(PSX_PRNG.c),
|
||||
|
||||
// SFEND
|
||||
//};
|
||||
|
||||
//int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "MAIN");
|
||||
|
||||
//// Call SetDisc() BEFORE we load CDC state, since SetDisc() has emulation side effects. We might want to clean this up in the future.
|
||||
//if(load)
|
||||
//{
|
||||
// if(CD_SelectedDisc >= (int)cdifs->size())
|
||||
// CD_SelectedDisc = -1;
|
||||
|
||||
////DAW????????????
|
||||
//// CDC->SetDisc(CD_TrayOpen, (CD_SelectedDisc >= 0 && !CD_TrayOpen) ? (*cdifs)[CD_SelectedDisc] : NULL,
|
||||
////(CD_SelectedDisc >= 0 && !CD_TrayOpen) ? cdifs_scex_ids[CD_SelectedDisc] : NULL);
|
||||
//}
|
||||
|
||||
//// TODO: Remember to increment dirty count in memory card state loading routine.
|
||||
|
||||
//ret &= CPU->StateAction(sm, load, data_only);
|
||||
//ret &= DMA_StateAction(sm, load, data_only);
|
||||
//ret &= TIMER_StateAction(sm, load, data_only);
|
||||
//ret &= SIO_StateAction(sm, load, data_only);
|
||||
|
||||
//ret &= CDC->StateAction(sm, load, data_only);
|
||||
//ret &= MDEC_StateAction(sm, load, data_only);
|
||||
//ret &= GPU->StateAction(sm, load, data_only);
|
||||
//ret &= SPU->StateAction(sm, load, data_only);
|
||||
|
||||
//ret &= FIO->StateAction(sm, load, data_only);
|
||||
|
||||
//ret &= IRQ_StateAction(sm, load, data_only); // Do it last.
|
||||
|
||||
//if(load)
|
||||
//{
|
||||
// ForceEventUpdates(0); // FIXME to work with debugger step mode.
|
||||
//}
|
||||
|
||||
namespace MDFN_IEN_PSX {
|
||||
void DMA_SyncState(bool isReader, EW::NewState *ns);
|
||||
void GTE_SyncState(bool isReader, EW::NewState *ns);
|
||||
void TIMER_SyncState(bool isReader, EW::NewState *ns);
|
||||
void SIO_SyncState(bool isReader, EW::NewState *ns);
|
||||
void MDEC_SyncState(bool isReader, EW::NewState *ns);
|
||||
void IRQ_SyncState(bool isReader, EW::NewState *ns);
|
||||
}
|
||||
|
||||
SYNCFUNC(PSX)
|
||||
{
|
||||
NSS(CD_TrayOpen);
|
||||
PSS(MainRAM.data8, 2*1024*1024);
|
||||
NSS(SysControl.Regs); //9 regs.. does the array work?
|
||||
NSS(SysControl.Regs);
|
||||
NSS(PSX_PRNG.lcgo);
|
||||
NSS(PSX_PRNG.x);
|
||||
NSS(PSX_PRNG.y);
|
||||
NSS(PSX_PRNG.z);
|
||||
NSS(PSX_PRNG.c);
|
||||
|
||||
//note: mednafen used to save the current disc index. that's kind of nice, I guess, if you accept that responsibility in the core.
|
||||
//but we're not doing things that way.
|
||||
//I think instead maybe we should generate a hash of the inserted disc and save that, and then check if theres a mismatch between the disc at the time of the savestate and the current disc
|
||||
//but we'll do that in the frontend for now
|
||||
|
||||
//old:
|
||||
// "TODO: Remember to increment dirty count in memory card state loading routine."
|
||||
//not sure what this means or whether I like it
|
||||
|
||||
//I've kept the ordering of these sections the same, in case its important for some unknown reason.. for now.
|
||||
|
||||
TSS(CPU);
|
||||
|
||||
ns->EnterSection("GTE");
|
||||
GTE_SyncState(isReader,ns);
|
||||
ns->ExitSection("GTE");
|
||||
|
||||
ns->EnterSection("DMA");
|
||||
DMA_SyncState(isReader,ns);
|
||||
ns->ExitSection("DMA");
|
||||
|
||||
ns->EnterSection("TIMER");
|
||||
TIMER_SyncState(isReader,ns);
|
||||
ns->ExitSection("TIMER");
|
||||
|
||||
ns->EnterSection("SIO");
|
||||
SIO_SyncState(isReader,ns);
|
||||
ns->ExitSection("SIO");
|
||||
|
||||
TSS(CDC);
|
||||
|
||||
ns->EnterSection("MDEC");
|
||||
MDEC_SyncState(isReader,ns);
|
||||
ns->ExitSection("MDEC");
|
||||
|
||||
TSS(GPU); //did some special logic for the CPU, ordering may matter, but probably not
|
||||
|
||||
TSS(SPU);
|
||||
TSS(FIO); //TODO - DUALSHOCK, MC
|
||||
|
||||
|
||||
//"Do it last." the comments say. And all this other nonsense about IRQs in the other state syncing functions. weird.....
|
||||
//ret &= IRQ_StateAction(sm, load, data_only); //
|
||||
|
||||
ns->EnterSection("IRQ");
|
||||
IRQ_SyncState(isReader,ns);
|
||||
ns->ExitSection("IRQ");
|
||||
|
||||
//zero: this is probably OK
|
||||
if(isReader)
|
||||
{
|
||||
ForceEventUpdates(0); // FIXME to work with debugger step mode.
|
||||
}
|
||||
}
|
||||
|
||||
EW_EXPORT s32 shock_StateTransaction(void *psx, ShockStateTransaction* transaction)
|
||||
|
@ -2518,5 +2484,8 @@ EW_EXPORT s32 shock_StateTransaction(void *psx, ShockStateTransaction* transacti
|
|||
return SHOCK_OK;
|
||||
}
|
||||
return SHOCK_ERROR;
|
||||
|
||||
default:
|
||||
return SHOCK_ERROR;
|
||||
}
|
||||
}
|
|
@ -316,6 +316,9 @@ EW_EXPORT s32 shock_SetDisc(void* psx, ShockDiscRef* disc);
|
|||
EW_EXPORT s32 shock_CloseTray(void* psx);
|
||||
|
||||
//Steps emulation by the specified interval
|
||||
//TODO - think about something. After loadstating, the device input state is probably nonsense.
|
||||
//Normally we'd set the input before frame advancing. But every frontend might not do that, and we might not be stepping by one frame.
|
||||
//What to do about this?
|
||||
EW_EXPORT s32 shock_Step(void* psx, eShockStep step);
|
||||
|
||||
//Fetches the framebuffer. Can retrieve parameters (set the job ptr to NULL) or fill the provided job ptr with the framebuffer (make sure its big enough).
|
||||
|
|
|
@ -103,26 +103,14 @@ void SIO_Write(pscpu_timestamp_t timestamp, uint32 A, uint32 V)
|
|||
}
|
||||
}
|
||||
|
||||
int SIO_StateAction(StateMem *sm, int load, int data_only)
|
||||
|
||||
void SIO_SyncState(bool isReader, EW::NewState *ns)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
SFVAR(Status),
|
||||
SFVAR(Mode),
|
||||
SFVAR(Control),
|
||||
SFVAR(BaudRate),
|
||||
SFVAR(DataBuffer),
|
||||
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "SIO");
|
||||
|
||||
if(load)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return(ret);
|
||||
NSS(Status);
|
||||
NSS(Mode);
|
||||
NSS(Control);
|
||||
NSS(BaudRate);
|
||||
NSS(DataBuffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1160,147 +1160,61 @@ int32 PS_SPU::EndFrame(int16 *SoundBuf)
|
|||
}
|
||||
}
|
||||
|
||||
int PS_SPU::StateAction(StateMem *sm, int load, int data_only)
|
||||
SYNCFUNC(PS_SPU)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
#define SFSWEEP(r) SFVAR((r).Control), \
|
||||
SFVAR((r).Current), \
|
||||
SFVAR((r).Divider)
|
||||
NSS(Voices);
|
||||
|
||||
#define SFVOICE(n) SFARRAY16(&Voices[n].DecodeBuffer[0], sizeof(Voices[n].DecodeBuffer) / sizeof(Voices[n].DecodeBuffer[0])), \
|
||||
SFVAR(Voices[n].DecodeM2), \
|
||||
SFVAR(Voices[n].DecodeM1), \
|
||||
SFVAR(Voices[n].DecodePlayDelay), \
|
||||
SFVAR(Voices[n].DecodeWritePos), \
|
||||
SFVAR(Voices[n].DecodeReadPos), \
|
||||
SFVAR(Voices[n].DecodeAvail), \
|
||||
SFVAR(Voices[n].DecodeShift), \
|
||||
SFVAR(Voices[n].DecodeWeight), \
|
||||
SFVAR(Voices[n].DecodeFlags), \
|
||||
SFVAR(Voices[n].IgnoreSampLA), \
|
||||
\
|
||||
SFSWEEP(Voices[n].Sweep[0]), \
|
||||
SFSWEEP(Voices[n].Sweep[1]), \
|
||||
\
|
||||
SFVAR(Voices[n].Pitch), \
|
||||
SFVAR(Voices[n].CurPhase), \
|
||||
\
|
||||
SFVAR(Voices[n].StartAddr), \
|
||||
SFVAR(Voices[n].CurAddr), \
|
||||
SFVAR(Voices[n].ADSRControl), \
|
||||
SFVAR(Voices[n].LoopAddr), \
|
||||
SFVAR(Voices[n].PreLRSample), \
|
||||
\
|
||||
SFVAR(Voices[n].ADSR.EnvLevel), \
|
||||
SFVAR(Voices[n].ADSR.Divider), \
|
||||
SFVAR(Voices[n].ADSR.Phase), \
|
||||
\
|
||||
SFVAR(Voices[n].ADSR.AttackExp), \
|
||||
SFVAR(Voices[n].ADSR.SustainExp), \
|
||||
SFVAR(Voices[n].ADSR.SustainDec), \
|
||||
SFVAR(Voices[n].ADSR.ReleaseExp), \
|
||||
\
|
||||
SFVAR(Voices[n].ADSR.AttackRate), \
|
||||
SFVAR(Voices[n].ADSR.DecayRate), \
|
||||
SFVAR(Voices[n].ADSR.SustainRate), \
|
||||
SFVAR(Voices[n].ADSR.ReleaseRate), \
|
||||
\
|
||||
SFVAR(Voices[n].ADSR.SustainLevel)
|
||||
NSS(NoiseCounter);
|
||||
NSS(LFSR);
|
||||
|
||||
SFVOICE(0),
|
||||
SFVOICE(1),
|
||||
SFVOICE(2),
|
||||
SFVOICE(3),
|
||||
SFVOICE(4),
|
||||
SFVOICE(5),
|
||||
SFVOICE(6),
|
||||
SFVOICE(7),
|
||||
SFVOICE(8),
|
||||
SFVOICE(9),
|
||||
SFVOICE(10),
|
||||
SFVOICE(11),
|
||||
SFVOICE(12),
|
||||
SFVOICE(13),
|
||||
SFVOICE(14),
|
||||
SFVOICE(15),
|
||||
SFVOICE(16),
|
||||
SFVOICE(17),
|
||||
SFVOICE(18),
|
||||
SFVOICE(19),
|
||||
SFVOICE(20),
|
||||
SFVOICE(21),
|
||||
SFVOICE(22),
|
||||
SFVOICE(23),
|
||||
#undef SFVOICE
|
||||
NSS(FM_Mode);
|
||||
NSS(Noise_Mode);
|
||||
NSS(Reverb_Mode);
|
||||
|
||||
SFVAR(NoiseCounter),
|
||||
SFVAR(LFSR),
|
||||
NSS(ReverbWA);
|
||||
|
||||
SFVAR(FM_Mode),
|
||||
SFVAR(Noise_Mode),
|
||||
SFVAR(Reverb_Mode),
|
||||
NSS(GlobalSweep);
|
||||
|
||||
SFVAR(ReverbWA),
|
||||
NSS(ReverbVol);
|
||||
|
||||
SFSWEEP(GlobalSweep[0]),
|
||||
SFSWEEP(GlobalSweep[1]),
|
||||
|
||||
SFARRAY32(ReverbVol, sizeof(ReverbVol) / sizeof(ReverbVol[0])),
|
||||
|
||||
SFARRAY32(CDVol, sizeof(CDVol) / sizeof(CDVol[0])),
|
||||
SFARRAY32(ExternVol, sizeof(ExternVol) / sizeof(ExternVol[0])),
|
||||
NSS(CDVol);
|
||||
NSS(ExternVol);
|
||||
|
||||
SFVAR(IRQAddr),
|
||||
NSS(IRQAddr);
|
||||
|
||||
SFVAR(RWAddr),
|
||||
NSS(RWAddr);
|
||||
|
||||
SFVAR(SPUControl),
|
||||
NSS(SPUControl);
|
||||
|
||||
SFVAR(VoiceOn),
|
||||
SFVAR(VoiceOff),
|
||||
NSS(VoiceOn);
|
||||
NSS(VoiceOff);
|
||||
|
||||
SFVAR(BlockEnd),
|
||||
NSS(BlockEnd);
|
||||
|
||||
SFVAR(CWA),
|
||||
NSS(CWA);
|
||||
|
||||
SFARRAY16(Regs, sizeof(Regs) / sizeof(Regs[0])),
|
||||
SFARRAY16(AuxRegs, sizeof(AuxRegs) / sizeof(AuxRegs[0])),
|
||||
NSS(Regs);
|
||||
NSS(AuxRegs);
|
||||
|
||||
SFARRAY16(&RDSB[0][0], sizeof(RDSB) / sizeof(RDSB[0][0])),
|
||||
SFVAR(RDSB_WP),
|
||||
NSS(RDSB);
|
||||
NSS(RDSB_WP);
|
||||
|
||||
SFARRAY16(&RUSB[0][0], sizeof(RUSB) / sizeof(RUSB[0][0])),
|
||||
SFVAR(RUSB_WP),
|
||||
NSS(RUSB);
|
||||
NSS(RUSB_WP);
|
||||
|
||||
SFVAR(ReverbCur),
|
||||
SFVAR(IRQAsserted),
|
||||
NSS(ReverbCur);
|
||||
NSS(IRQAsserted);
|
||||
|
||||
SFVAR(clock_divider),
|
||||
NSS(clock_divider);
|
||||
|
||||
SFARRAY16(SPURAM, 524288 / sizeof(uint16)),
|
||||
SFEND
|
||||
};
|
||||
#undef SFSWEEP
|
||||
int ret = 1;
|
||||
NSS(SPURAM);
|
||||
|
||||
ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, "SPU");
|
||||
|
||||
if(load)
|
||||
{
|
||||
for(unsigned i = 0; i < 24; i++)
|
||||
{
|
||||
Voices[i].DecodeReadPos &= 0x1F;
|
||||
Voices[i].DecodeWritePos &= 0x1F;
|
||||
}
|
||||
|
||||
RDSB_WP &= 0x3F;
|
||||
RUSB_WP &= 0x3F;
|
||||
|
||||
IRQ_Assert(IRQ_SPU, IRQAsserted);
|
||||
}
|
||||
|
||||
return(ret);
|
||||
//if(isReader)
|
||||
//{
|
||||
//there was more weird crap here about controlling the range of variables. just sanity checks, I guess? to prevent crashes? no thanks, id rather have crashes alert me to nondeterminisms.
|
||||
//and another thing like this, which I think makes no sense. I really need to test these.
|
||||
IRQ_Assert(IRQ_SPU, IRQAsserted);
|
||||
//}
|
||||
}
|
||||
|
||||
uint16 PS_SPU::PeekSPURAM(uint32 address)
|
||||
|
|
|
@ -99,6 +99,8 @@ class PS_SPU
|
|||
PS_SPU();
|
||||
~PS_SPU();
|
||||
|
||||
template<bool isReader>void SyncState(EW::NewState *ns);
|
||||
|
||||
int StateAction(StateMem *sm, int load, int data_only);
|
||||
|
||||
void Power(void);
|
||||
|
|
|
@ -446,34 +446,11 @@ void TIMER_Power(void)
|
|||
memset(Timers, 0, sizeof(Timers));
|
||||
}
|
||||
|
||||
int TIMER_StateAction(StateMem *sm, int load, int data_only)
|
||||
void TIMER_SyncState(bool isReader, EW::NewState *ns)
|
||||
{
|
||||
SFORMAT StateRegs[] =
|
||||
{
|
||||
#define SFTIMER(n) SFVARN(Timers[n].Mode, #n "Mode"), \
|
||||
SFVARN(Timers[n].Counter, #n "Counter"), \
|
||||
SFVARN(Timers[n].Target, #n "Target"), \
|
||||
SFVARN(Timers[n].Div8Counter, #n "Div8Counter"), \
|
||||
SFVARN(Timers[n].IRQDone, #n "IRQDone"), \
|
||||
SFVARN(Timers[n].DoZeCounting, #n "DoZeCounting")
|
||||
SFTIMER(0),
|
||||
SFTIMER(1),
|
||||
SFTIMER(2),
|
||||
#undef SFTIMER
|
||||
|
||||
SFVAR(vblank),
|
||||
SFVAR(hretrace),
|
||||
|
||||
SFEND
|
||||
};
|
||||
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "TIMER");
|
||||
|
||||
if(load)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return(ret);
|
||||
NSS(Timers);
|
||||
NSS(vblank);
|
||||
NSS(hretrace);
|
||||
}
|
||||
|
||||
uint32 TIMER_GetRegister(unsigned int which, char *special, const uint32 special_len)
|
||||
|
|
Loading…
Reference in New Issue