#endif
pl_rearmed_cbs.gpu_peops.iUseDither = 1;
pl_rearmed_cbs.gpu_peops.dwActFixes = GPU_PEOPS_OLD_FRAME_SKIP;
- spu_config.iUseFixedUpdates = 1;
SaveFuncs.open = save_open;
SaveFuncs.read = save_read;
}
int mdecFreeze(void *f, int Mode) {
- u8 *base = (u8 *)&psxM[0x100000];
+ u8 *base = (u8 *)psxM;
u32 v;
gzfreeze(&mdec.reg0, sizeof(mdec.reg0));
gzfreeze(&mdec.reg1, sizeof(mdec.reg1));
- // old code used to save raw pointers..
v = (u8 *)mdec.rl - base;
gzfreeze(&v, sizeof(v));
- mdec.rl = (u16 *)(base + (v & 0xffffe));
+ mdec.rl = (u16 *)(base + (v & 0x1ffffe));
v = (u8 *)mdec.rl_end - base;
gzfreeze(&v, sizeof(v));
- mdec.rl_end = (u16 *)(base + (v & 0xffffe));
+ mdec.rl_end = (u16 *)(base + (v & 0x1ffffe));
v = 0;
if (mdec.block_buffer_pos)
- v = mdec.block_buffer_pos - base;
+ v = mdec.block_buffer_pos - mdec.block_buffer;
gzfreeze(&v, sizeof(v));
mdec.block_buffer_pos = 0;
- if (v)
- mdec.block_buffer_pos = base + (v & 0xfffff);
+ if (v && v < sizeof(mdec.block_buffer))
+ mdec.block_buffer_pos = mdec.block_buffer;
gzfreeze(&mdec.block_buffer, sizeof(mdec.block_buffer));
gzfreeze(&mdec.pending_dma1, sizeof(mdec.pending_dma1));
//psxCpu->Reset();
if (Config.HLE)
- psxBiosCheckExe(tmpHead.h.t_addr, tmpHead.h.t_size);
+ psxBiosCheckExe(tmpHead.h.t_addr, tmpHead.h.t_size, 0);
return 0;
}
padFreeze(f, 0);
if (Config.HLE)
- psxBiosCheckExe(biosBranchCheckOld, 0x60);
+ psxBiosCheckExe(biosBranchCheckOld, 0x60, 1);
result = 0;
cleanup:
#include "../psxcommon.h"
+extern int stop;
+
union psxCP0Regs_;
u32 schedule_timeslice(void);
void gen_interupt(union psxCP0Regs_ *cp0);
hleExcPadCard1, hleExcPadCard2,
};
-void psxBiosCheckExe(u32 t_addr, u32 t_size)
+void psxBiosCheckExe(u32 t_addr, u32 t_size, int loading_state)
{
// lw $v0, 0x10($sp)
// nop
if ((SWAP32(r32[i + j]) >> 16) != 0x3c04) // lui
continue;
- SysPrintf("HLE vsync @%08x\n", start + i * 4);
+ if (!loading_state)
+ SysPrintf("HLE vsync @%08x\n", start + i * 4);
psxRegs.biosBranchCheck = (t_addr & 0xa01ffffc) + i * 4;
}
}
void psxBiosFreeze(int Mode);
void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 sp);
void psxBiosSetupBootState(void);
-void psxBiosCheckExe(u32 t_addr, u32 t_size);
+void psxBiosCheckExe(u32 t_addr, u32 t_size, int loading_state);
void psxBiosCheckBranch(void);
extern void (*biosA0[256])();
s32 psxRcntFreeze( void *f, s32 Mode )
{
u32 spuSyncCount = 0;
- u32 count;
s32 i;
gzfreeze( &rcnts, sizeof(Rcnt) * CounterQuantity );
if (Mode == 0)
{
- // don't trust things from a savestate
rcnts[3].rate = 1;
- for( i = 0; i < CounterQuantity; ++i )
- {
+ for( i = 0; i < CounterQuantity - 1; ++i )
_psxRcntWmode( i, rcnts[i].mode );
- count = (psxRegs.cycle - rcnts[i].cycleStart) / rcnts[i].rate;
- _psxRcntWcount( i, count );
- }
scheduleRcntBase();
psxRcntSet();
}
void (CALLBACK *cddavCallback)(short, short);\r
void (CALLBACK *scheduleCallback)(unsigned int);\r
\r
- xa_decode_t * xapGlobal;\r
+ const xa_decode_t * xapGlobal;\r
unsigned int * XAFeed;\r
unsigned int * XAPlay;\r
unsigned int * XAStart;\r
unsigned short decode_pos;\r
uint32_t pSpuIrq;\r
uint32_t spuAddr;\r
- uint32_t dummy1;\r
- uint32_t dummy2;\r
- uint32_t dummy3;\r
+ uint32_t rvb_cur;\r
+ uint16_t xa_left;\r
+ uint16_t cdda_left;\r
+ uint32_t cycles_played;\r
\r
SPUCHAN_orig s_chan[MAXCHAN]; \r
\r
\r
////////////////////////////////////////////////////////////////////////\r
\r
-void LoadStateV5(SPUFreeze_t * pF); // newest version\r
-void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles); // unknown format\r
+static SPUOSSFreeze_t * LoadStateV5(SPUFreeze_t * pF, uint32_t cycles);\r
+static void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles); // unknown format\r
\r
// we want to retain compatibility between versions,\r
// so use original channel struct\r
long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,\r
uint32_t cycles)\r
{\r
- int i;SPUOSSFreeze_t * pFO;\r
+ SPUOSSFreeze_t * pFO = NULL;\r
+ int i;\r
\r
if(!pF) return 0; // first check\r
\r
- do_samples(cycles, 1);\r
-\r
if(ulFreezeMode) // info or save?\r
{//--------------------------------------------------//\r
+ int xa_left = 0, cdda_left = 0;\r
+ do_samples(cycles, 1);\r
+\r
if(ulFreezeMode==1) \r
memset(pF,0,sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t));\r
\r
\r
if(spu.xapGlobal && spu.XAPlay!=spu.XAFeed) // some xa\r
{\r
- pF->xaS=*spu.xapGlobal;\r
+ xa_left = spu.XAFeed - spu.XAPlay;\r
+ if (xa_left < 0)\r
+ xa_left = spu.XAEnd - spu.XAPlay + spu.XAFeed - spu.XAStart;\r
+ pF->xaS = *spu.xapGlobal;\r
+ }\r
+ else if (spu.CDDAPlay != spu.CDDAFeed)\r
+ {\r
+ // abuse the xa struct to store leftover cdda samples\r
+ unsigned int *p = spu.CDDAPlay;\r
+ cdda_left = spu.CDDAFeed - spu.CDDAPlay;\r
+ if (cdda_left < 0)\r
+ cdda_left = spu.CDDAEnd - spu.CDDAPlay + spu.CDDAFeed - spu.CDDAStart;\r
+ if (cdda_left > sizeof(pF->xaS.pcm) / 4)\r
+ cdda_left = sizeof(pF->xaS.pcm) / 4;\r
+ if (p + cdda_left <= spu.CDDAEnd)\r
+ memcpy(pF->xaS.pcm, p, cdda_left * 4);\r
+ else {\r
+ memcpy(pF->xaS.pcm, p, (spu.CDDAEnd - p) * 4);\r
+ memcpy((char *)pF->xaS.pcm + (spu.CDDAEnd - p) * 4, spu.CDDAStart,\r
+ (cdda_left - (spu.CDDAEnd - p)) * 4);\r
+ }\r
+ pF->xaS.nsamples = 0;\r
}\r
- else \r
- memset(&pF->xaS,0,sizeof(xa_decode_t)); // or clean xa\r
+ else\r
+ memset(&pF->xaS,0,sizeof(xa_decode_t)); // or clean xa\r
\r
pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff\r
\r
pFO->spuAddr=spu.spuAddr;\r
if(pFO->spuAddr==0) pFO->spuAddr=0xbaadf00d;\r
pFO->decode_pos = spu.decode_pos;\r
+ pFO->rvb_cur = spu.rvb->CurrAddr;\r
+ pFO->xa_left = xa_left;\r
+ pFO->cdda_left = cdda_left;\r
+ pFO->cycles_played = spu.cycles_played;\r
\r
for(i=0;i<MAXCHAN;i++)\r
{\r
memcpy(spu.regArea,pF->cSPUPort,0x200);\r
spu.bMemDirty = 1;\r
\r
- if(pF->xaS.nsamples<=4032) // start xa again\r
- SPUplayADPCMchannel(&pF->xaS, spu.cycles_played, 0);\r
-\r
- spu.xapGlobal=0;\r
-\r
- if(!strcmp(pF->szSPUName,"PBOSS") && pF->ulFreezeVersion==5)\r
- LoadStateV5(pF);\r
+ if (!strcmp(pF->szSPUName,"PBOSS") && pF->ulFreezeVersion==5)\r
+ pFO = LoadStateV5(pF, cycles);\r
else LoadStateUnknown(pF, cycles);\r
\r
+ spu.XAPlay = spu.XAFeed = spu.XAStart;\r
+ spu.CDDAPlay = spu.CDDAFeed = spu.CDDAStart;\r
+ if (pFO && pFO->xa_left && pF->xaS.nsamples) { // start xa again\r
+ FeedXA(&pF->xaS);\r
+ spu.XAPlay = spu.XAFeed - pFO->xa_left;\r
+ if (spu.XAPlay < spu.XAStart)\r
+ spu.XAPlay = spu.XAStart;\r
+ }\r
+ else if (pFO && pFO->cdda_left) { // start cdda again\r
+ FeedCDDA((void *)pF->xaS.pcm, pFO->cdda_left * 4);\r
+ }\r
+\r
// repair some globals\r
for(i=0;i<=62;i+=2)\r
load_register(H_Reverb+i, cycles);\r
for(i=0;i<MAXCHAN;i++) spu.SB[i * SB_SIZE + 28]=0;\r
\r
ClearWorkingState();\r
- spu.cycles_played = cycles;\r
\r
if (spu.spuCtrl & CTRL_IRQ)\r
schedule_next_irq();\r
\r
////////////////////////////////////////////////////////////////////////\r
\r
-void LoadStateV5(SPUFreeze_t * pF)\r
+static SPUOSSFreeze_t * LoadStateV5(SPUFreeze_t * pF, uint32_t cycles)\r
{\r
int i;SPUOSSFreeze_t * pFO;\r
\r
else spu.spuAddr = pFO->spuAddr & 0x7fffe;\r
}\r
spu.decode_pos = pFO->decode_pos & 0x1ff;\r
+ spu.rvb->CurrAddr = pFO->rvb_cur;\r
+ spu.cycles_played = pFO->cycles_played ? pFO->cycles_played : cycles;\r
\r
spu.dwNewChannel=0;\r
spu.dwChannelsAudible=0;\r
spu.s_chan[i].pCurr+=(uintptr_t)spu.spuMemC;\r
spu.s_chan[i].pLoop+=(uintptr_t)spu.spuMemC;\r
}\r
+ return pFO;\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
\r
-void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles)\r
+static void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles)\r
{\r
int i;\r
\r
spu.dwChannelsAudible=0;\r
spu.dwChannelDead=0;\r
spu.pSpuIrq=spu.spuMemC;\r
+ spu.cycles_played = cycles;\r
\r
for(i=0;i<0xc0;i++)\r
{\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
+// vim:shiftwidth=1:expandtab\r
void CALLBACK SPUasync(unsigned int cycle, unsigned int flags)
{
- do_samples(cycle, spu_config.iUseFixedUpdates);
+ do_samples(cycle, 0);
if (spu.spuCtrl & CTRL_IRQ)
schedule_next_irq();
do_samples(cycle, 1); // catch up to prevent source underflows later
FeedXA(xap); // call main XA feeder
+ spu.xapGlobal = xap; // store info for save states
}
// CDDA AUDIO
if (is_start)
do_samples(cycle, 1); // catch up to prevent source underflows later
- return FeedCDDA((unsigned char *)pcm, nbytes);
+ FeedCDDA((unsigned char *)pcm, nbytes);
+ return 0;
}
// to be called after state load
spu.XAFeed = spu.XAStart;
spu.CDDAStart = malloc(CDDA_BUFFER_SIZE); // alloc cdda buffer
- spu.CDDAEnd = spu.CDDAStart + 16384;
+ spu.CDDAEnd = spu.CDDAStart + CDDA_BUFFER_SIZE / sizeof(uint32_t);
spu.CDDAPlay = spu.CDDAStart;
spu.CDDAFeed = spu.CDDAStart;
void ClearWorkingState(void);\r
void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap, unsigned int cycle, int is_start);\r
int CALLBACK SPUplayCDDAchannel(short *pcm, int bytes, unsigned int cycle, int is_start);\r
+void FeedXA(const xa_decode_t *xap);\r
+void FeedCDDA(unsigned char *pcm, int nBytes);\r
\r
#endif /* __P_SPU_H__ */\r
int iUseInterpolation;
int iTempo;
int iUseThread;
- int iUseFixedUpdates; // output fixed number of samples/frame
// status
int iThreadAvail;
// FEED XA
////////////////////////////////////////////////////////////////////////
-INLINE void FeedXA(xa_decode_t *xap)
+void FeedXA(const xa_decode_t *xap)
{
int sinc,spos,i,iSize,iPlace,vl,vr;
if(!spu.bSPUIsOpen) return;
- spu.xapGlobal = xap; // store info for save states
spu.XARepeat = 3; // set up repeat
#if 0//def XA_HACK
// FEED CDDA
////////////////////////////////////////////////////////////////////////
-INLINE int FeedCDDA(unsigned char *pcm, int nBytes)
+void FeedCDDA(unsigned char *pcm, int nBytes)
{
int space;
space=(spu.CDDAPlay-spu.CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1);
if(space<nBytes)
- return 0x7761; // rearmed_wait
+ return;
while(nBytes>0)
{
nBytes-=space;
pcm+=space;
}
-
- return 0x676f; // rearmed_go
}
#endif