psx - straighten out setting of discs when loading savestates, and avoid doing likely desyncing operations in CDC module when loading savestates and setting the appropriate disc. fixes

This commit is contained in:
zeromus 2015-02-01 04:55:09 +00:00
parent 62d781b960
commit 91c130a07a
7 changed files with 108 additions and 32 deletions
BizHawk.Emulation.Cores/Consoles/Sony/PSX
output/dll
psx/octoshock/psx

View File

@ -524,6 +524,20 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
return new System.Drawing.Size(VirtualWidth, VirtualHeight);
}
void PokeDisc()
{
if (CurrentDiscIndexMounted == 0)
{
currentDiscInterface = null;
OctoshockDll.shock_PokeDisc(psx, IntPtr.Zero);
}
else
{
currentDiscInterface = discInterfaces[CurrentDiscIndexMounted - 1];
OctoshockDll.shock_PokeDisc(psx, currentDiscInterface.OctoshockHandle);
}
}
void FrameAdvance_PrepDiscState()
{
//reminder: if this is the beginning of time, we can begin with the disc ejected or inserted.
@ -834,6 +848,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
Frame = s.ExtraData.Frame;
CurrentTrayOpen = s.ExtraData.CurrentDiscEjected;
CurrentDiscIndexMounted = s.ExtraData.CurrentDiscIndexMounted;
PokeDisc();
}
byte[] savebuff;
@ -899,8 +914,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
Frame = reader.ReadInt32();
CurrentTrayOpen = reader.ReadBoolean();
CurrentDiscIndexMounted = reader.ReadInt32();
//TODO - need a method to sneak the required disc, without having to do a proper eject sequence
PokeDisc();
}
}

View File

@ -211,6 +211,9 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
[DllImport(dd, CallingConvention = cc)]
public static extern int shock_SetDisc(IntPtr psx, IntPtr disc);
[DllImport(dd, CallingConvention = cc)]
public static extern int shock_PokeDisc(IntPtr psx, IntPtr disc);
[DllImport(dd, CallingConvention = cc)]
public static extern int shock_CloseTray(IntPtr psx);

Binary file not shown.

View File

@ -62,6 +62,7 @@ PS_CDC::PS_CDC() : DMABuffer(4096)
{
IsPSXDisc = false;
Cur_disc = NULL;
Open_disc = NULL;
DriveStatus = DS_STOPPED;
PendingCommandPhase = 0;
@ -90,33 +91,58 @@ void PS_CDC::DMForceStop(void)
SectorsRead = 0;
}
void PS_CDC::SetDisc(bool tray_open, ShockDiscRef *disc, const char *disc_id)
void PS_CDC::OpenTray()
{
if(tray_open)
disc = NULL;
//effectively a NOP at t=0
DMForceStop();
Cur_disc = disc;
//zero 31-jan-2015 - psxtech says that what this is used for is actually a 'was open' flag which gets cleared after the status gets polled.
//so lets set it here, and rename it later if we're sure.
DiscChanged = true;
}
void PS_CDC::CloseTray(bool poke)
{
//switch pending (open) disc to current disc
Cur_disc = Open_disc;
Open_disc = NULL;
char disc_id[5];
strncpy(disc_id,(char*)Open_DiscID,4);
Open_DiscID[0] = 0;
//prepare analysis if disc: leave in empty state
IsPSXDisc = false;
memset(DiscID, 0, sizeof(DiscID));
if(!Cur_disc)
//stuff to always happen, even when poking:
if(Cur_disc)
{
DMForceStop();
}
else
{
HeaderBufValid = false;
DiscStartupDelay = (int64)1000 * 33868800 / 1000;
DiscChanged = true;
Cur_disc->ReadTOC((ShockTOC*)&toc,(ShockTOCTrack*)toc.tracks);
//complete analysis
if(disc_id)
{
strncpy((char *)DiscID, disc_id, 4);
IsPSXDisc = true;
}
}
//stuff to happen when not poking (reset CDC state)
if(Cur_disc && !poke)
{
HeaderBufValid = false;
DiscStartupDelay = (int64)1000 * 33868800 / 1000;
}
}
void PS_CDC::SetDisc(ShockDiscRef *disc, const char *disc_id, bool poke)
{
Open_disc = disc;
strncpy((char*)Open_DiscID,disc_id,4);
if(poke)
CloseTray(true);
}
int32 PS_CDC::CalcNextEvent(void)

View File

@ -26,7 +26,9 @@ class PS_CDC
template<bool isReader>void SyncState(EW::NewState *ns);
void SetDisc(bool tray_open, ShockDiscRef *disc, const char disc_id[4]);
void OpenTray();
void SetDisc(ShockDiscRef *disc, const char disc_id[4], bool poke);
void CloseTray(bool poke);
void Power(void);
void ResetTS(void);
@ -47,6 +49,10 @@ class PS_CDC
private:
CDIF *Cur_CDIF;
ShockDiscRef* Cur_disc;
ShockDiscRef* Open_disc; //the disc that's in the tray, while the tray is open. pending, kind of. used because Cur_disc != NULL is used as a tray-closed marker in the CDC code
uint8 Open_DiscID[4]; //same thing
bool DiscChanged;
int32 DiscStartupDelay;

View File

@ -1285,8 +1285,7 @@ EW_EXPORT s32 shock_Create(void** psx, s32 region, void* firmware512k)
s_ShockState.power = false;
s_ShockState.eject = false;
//set tray closed with no disc
CDC->SetDisc(false,NULL,"");
//do we need to do anything particualr with the CDC disc/tray state? survey says... no.
return SHOCK_OK;
}
@ -1896,15 +1895,41 @@ EW_EXPORT s32 shock_SetDisc(void* psx, ShockDiscRef* disc)
if(ret != SHOCK_OK) return ret;
}
s_CurrDiscInfo = info;
s_CurrDisc = disc;
CDC->SetDisc(s_CurrDisc,s_CurrDiscInfo.id, false);
return SHOCK_OK;
}
EW_EXPORT s32 shock_PokeDisc(void* psx, ShockDiscRef* disc)
{
//TODO HACKS! DONT COPY/PASTE SO MUCH! REFACTOR DISC ID STUFF!
//let's talk about why this function is needed. well, let's paste an old comment on the subject:
//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
//TODO - non-psx disc is legal here. should pass null ID to CDC setdisc
//analyze disc so we dont have to annoyingly manage it from client
//TODO - so junky
ShockDiscInfo info;
strcpy(info.id,"\0\0\0\0");
info.region = REGION_NONE;
if(disc != NULL)
{
s32 ret = shock_AnalyzeDisc(disc,&info);
if(ret != SHOCK_OK) return ret;
}
s_CurrDiscInfo = info;
s_CurrDisc = disc;
//set the disc to the CDC, but since its necessarily open to insert, this is false
CDC->SetDisc(true,s_CurrDisc,s_CurrDiscInfo.id);
CDC->SetDisc(s_CurrDisc,s_CurrDiscInfo.id,true);
return SHOCK_OK;
}
@ -1913,7 +1938,7 @@ EW_EXPORT s32 shock_OpenTray(void* psx)
{
if(s_ShockState.eject) return SHOCK_NOCANDO;
s_ShockState.eject = true;
CDC->SetDisc(true,s_CurrDisc,s_CurrDiscInfo.id);
CDC->OpenTray();
return SHOCK_OK;
}
@ -1921,7 +1946,7 @@ EW_EXPORT s32 shock_CloseTray(void* psx)
{
if(!s_ShockState.eject) return SHOCK_NOCANDO;
s_ShockState.eject = false;
CDC->SetDisc(false,s_CurrDisc,s_CurrDiscInfo.id);
CDC->CloseTray(false);
return SHOCK_OK;
}
@ -2106,7 +2131,6 @@ static s32 AnalyzeDiscEx(ShockDiscRef* disc, ShockDiscInfo* info)
uint8 buf[2048];
uint8 fbuf[2048 + 1];
unsigned ipos, opos;
int i;
//clear it out in case of error
info->region = REGION_NONE;

View File

@ -343,6 +343,9 @@ EW_EXPORT s32 shock_OpenTray(void* psx);
//Sets the disc in the tray. Returns SHOCK_NOCANDO if it's closed. You can pass NULL to remove a disc from the tray
EW_EXPORT s32 shock_SetDisc(void* psx, ShockDiscRef* disc);
//POKES the disc in the tray, for use after loading a state. Does not affect any of the internal emulation parameters
EW_EXPORT s32 shock_PokeDisc(void* psx, ShockDiscRef* disc);
//Closes the disc tray. Returns SHOCK_NOCANDO if already closed.
EW_EXPORT s32 shock_CloseTray(void* psx);