return;
}
- gpu = malloc(sizeof(*gpu));
+ gpu = malloc(sizeof(*gpu) + 1024*512*2);
if (gpu == NULL) {
gzclose(f);
return;
}
- ret = gzread(f, gpu, sizeof(*gpu));
+ ret = gzread(f, gpu, sizeof(*gpu) + 1024*512*2);
gzclose(f);
- if (ret != sizeof(*gpu)) {
+ if (ret != sizeof(*gpu) + 1024*512*2) {
fprintf(stderr, "gzread failed\n");
goto out;
}
{
int w = min(g_menuscreen_w, 1024);
int h = min(g_menuscreen_h, 512);
- u16 *d = g_menuscreen_ptr;
- u16 *s = (u16 *)gpuf->psxVRam + y * 1024 + x;
+ u16 *s, *d = g_menuscreen_ptr;
+ uint16_t *vram = NULL;
char buff[64];
int ty = 1;
gpuf->ulFreezeVersion = 1;
if (GPU_freeze != NULL)
- GPU_freeze(1, gpuf);
+ GPU_freeze(1, gpuf, &vram);
+ s = vram + y * 1024 + x;
for (; h > 0; h--, d += g_menuscreen_w, s += 1024)
bgr555_to_rgb565(d, s, w);
extern void GPUreadDataMem(uint32_t *, int);
extern long GPUdmaChain(uint32_t *, uint32_t, uint32_t *, int32_t *);
extern void GPUupdateLace(void);
-extern long GPUfreeze(uint32_t, void *);
+extern long GPUfreeze(uint32_t, void *, uint16_t **);
extern void GPUvBlank(int, int);
extern void GPUgetScreenInfo(int *y, int *base_hres);
extern void GPUrearmedCallbacks(const struct rearmed_cbs *cbs);
short pcm[16384];
} xa_decode_t;
-typedef struct {
- char PluginName[8];
- unsigned int PluginVersion;
- unsigned int Size;
-} SPUFreezeHdr_t;
-
typedef struct SPUFreeze {
char PluginName[8];
unsigned int PluginVersion;
unsigned int Size;
unsigned char SPUPorts[0x200];
- unsigned char SPURam[0x80000];
- xa_decode_t xa;
+ //unsigned char SPURam[0x80000]; // handled separately
+ //xa_decode_t xa;
} SPUFreeze_t;
+#define SPUFREEZE_F2_MAX_SIZE 0xc000
+
/* NET PlugIn v2 */
/* Added by linuzappz@pcsx.net */
uint32_t ulFreezeVersion;
uint32_t ulStatus;
uint32_t ulControl[256];
- unsigned char psxVRam[1024*512*2];
+ unsigned char psxVRam[0]; // 1024*512*2 // saved separately
} GPUFreeze_t;
#define PSXGPU_LCF (1u<<31)
int SaveState(const char *file) {
struct misc_save_data *misc = (void *)(psxRegs.ptrs.psxH + 0xf000);
struct origin_info oi = { 0, };
- GPUFreeze_t *gpufP = NULL;
- SPUFreezeHdr_t spufH;
- SPUFreeze_t *spufP = NULL;
- u8 buf[EX_SCREENPIC_SIZE];
- int result = -1;
- int Size;
+ union {
+ // save stack space
+ u8 buf[EX_SCREENPIC_SIZE];
+ GPUFreeze_t gpu_hdr;
+ struct {
+ SPUFreeze_t spu_hdr;
+ u8 spu_part2[SPUFREEZE_F2_MAX_SIZE];
+ };
+ } u;
+ unsigned short *spuram = NULL;
+ uint16_t *vram = NULL;
void *f;
assert(!psxRegs.branching);
snprintf(oi.build_info, sizeof(oi.build_info), "%s", get_build_info());
// this was space for ScreenPic
- assert(sizeof(buf) >= EX_SCREENPIC_SIZE);
assert(sizeof(oi) - 3 <= EX_SCREENPIC_SIZE);
- memset(buf, 0, sizeof(buf));
- memcpy(buf + 3, &oi, sizeof(oi));
- SaveFuncs.write(f, buf, EX_SCREENPIC_SIZE);
+ memset(u.buf, 0, sizeof(u.buf));
+ memcpy(u.buf + 3, &oi, sizeof(oi));
+ SaveFuncs.write(f, u.buf, sizeof(u.buf));
if (Config.HLE)
psxBiosFreeze(1);
SaveFuncs.write(f, &psxRegs, offsetof(psxRegisters, gteBusyCycle));
// gpu
- gpufP = (GPUFreeze_t *)malloc(sizeof(GPUFreeze_t));
- if (gpufP == NULL) goto cleanup;
- gpufP->ulFreezeVersion = 1;
- memset(gpufP->ulControl, 0, sizeof(gpufP->ulControl));
- GPU_freeze(1, gpufP);
- SaveFuncs.write(f, gpufP, sizeof(GPUFreeze_t));
- free(gpufP); gpufP = NULL;
+ u.gpu_hdr.ulFreezeVersion = 1;
+ u.gpu_hdr.ulStatus = 0;
+ memset(u.gpu_hdr.ulControl, 0, sizeof(u.gpu_hdr.ulControl));
+ GPU_freeze(1, &u.gpu_hdr, &vram);
+ SaveFuncs.write(f, &u.gpu_hdr, sizeof(u.gpu_hdr));
+ SaveFuncs.write(f, vram, 1024*512*2);
// spu
- SPU_freeze(2, (SPUFreeze_t *)&spufH, psxRegs.cycle);
- Size = spufH.Size; SaveFuncs.write(f, &Size, 4);
- spufP = (SPUFreeze_t *) malloc(Size);
- if (spufP == NULL) goto cleanup;
- SPU_freeze(1, spufP, psxRegs.cycle);
- SaveFuncs.write(f, spufP, Size);
- free(spufP); spufP = NULL;
+ SPU_freeze(1, &u.spu_hdr, &spuram, u.spu_part2, psxRegs.cycle);
+ assert(u.spu_hdr.Size > sizeof(u.spu_hdr) + 512*1024);
+ assert(u.spu_hdr.Size <= sizeof(u.spu_hdr) + 512*1024 + sizeof(u.spu_part2));
+ assert(spuram);
+ SaveFuncs.write(f, &u.spu_hdr.Size, 4); // redundant, for compat
+ SaveFuncs.write(f, &u.spu_hdr, sizeof(u.spu_hdr));
+ SaveFuncs.write(f, spuram, 512*1024);
+ SaveFuncs.write(f, &u.spu_part2, u.spu_hdr.Size - sizeof(u.spu_hdr) - 512*1024);
sioFreeze(f, 1);
cdrFreeze(f, 1);
ndrc_freeze(f, 1);
padFreeze(f, 1);
- result = 0;
-cleanup:
memset(misc, 0, sizeof(*misc));
SaveFuncs.close(f);
- return result;
+ return 0;
}
int LoadState(const char *file) {
struct misc_save_data *misc = (void *)(psxRegs.ptrs.psxH + 0xf000);
u32 biosBranchCheckOld = psxRegs.biosBranchCheck;
- void *f;
- GPUFreeze_t *gpufP = NULL;
- SPUFreeze_t *spufP = NULL;
+ union {
+ // save stack space
+ GPUFreeze_t gpu_hdr;
+ struct {
+ SPUFreeze_t spu_hdr;
+ u8 spu_part2[SPUFREEZE_F2_MAX_SIZE];
+ };
+ } u;
+ unsigned short *spuram = NULL;
+ uint16_t *vram = NULL;
boolean hle, oldhle;
int Size;
char header[32];
u32 version;
int result = -1;
+ void *f;
f = SaveFuncs.open(file, "rb");
if (f == NULL) return -1;
psxBiosFreeze(0);
// gpu
- gpufP = (GPUFreeze_t *)malloc(sizeof(GPUFreeze_t));
- if (gpufP == NULL) goto cleanup;
- SaveFuncs.read(f, gpufP, sizeof(GPUFreeze_t));
- GPU_freeze(0, gpufP);
- free(gpufP);
+ SaveFuncs.read(f, &u.gpu_hdr, sizeof(u.gpu_hdr));
+ GPU_freeze(0, &u.gpu_hdr, &vram);
+ assert(vram);
+ SaveFuncs.read(f, vram, 1024*512*2);
gpuSyncPluginSR();
// spu
SaveFuncs.read(f, &Size, 4);
- spufP = (SPUFreeze_t *)malloc(Size);
- if (spufP == NULL) goto cleanup;
- SaveFuncs.read(f, spufP, Size);
- SPU_freeze(0, spufP, psxRegs.cycle);
- free(spufP);
+ if (sizeof(u.spu_hdr) + 512*1024 < Size &&
+ (uint32_t)Size <= sizeof(u.spu_hdr) + 512*1024u + sizeof(u.spu_part2))
+ {
+ SPU_freeze(0, NULL, &spuram, NULL, psxRegs.cycle);
+ assert(spuram);
+ SaveFuncs.read(f, &u.spu_hdr, sizeof(u.spu_hdr));
+ SaveFuncs.read(f, spuram, 512*1024);
+ SaveFuncs.read(f, &u.spu_part2, Size - sizeof(u.spu_hdr) - 512*1024);
+ SPU_freeze(0, &u.spu_hdr, &spuram, u.spu_part2, psxRegs.cycle);
+ }
+ else
+ {
+ SysPrintf("broken spu save size %d, attempting to skip\n", Size);
+ SaveFuncs.seek(f, Size, SEEK_CUR);
+ }
sioFreeze(f, 0);
cdrFreeze(f, 0);
typedef void (CALLBACK* GPUreadDataMem)(uint32_t *, int);\r
typedef long (CALLBACK* GPUdmaChain)(uint32_t *, uint32_t, uint32_t *, int32_t *);\r
typedef void (CALLBACK* GPUupdateLace)(void);\r
-typedef long (CALLBACK* GPUfreeze)(uint32_t, GPUFreeze_t *);\r
+typedef long (CALLBACK* GPUfreeze)(uint32_t, GPUFreeze_t *, uint16_t **);\r
typedef void (CALLBACK* GPUvBlank)(int, int);\r
typedef void (CALLBACK* GPUgetScreenInfo)(int *, int *);\r
\r
typedef void (CALLBACK* SPUplayADPCMchannel)(xa_decode_t *, unsigned int, int);\r
typedef void (CALLBACK* SPUregisterCallback)(void (CALLBACK *callback)(int));\r
typedef void (CALLBACK* SPUregisterScheduleCb)(void (CALLBACK *callback)(unsigned int cycles_after));\r
-typedef long (CALLBACK* SPUfreeze)(unsigned int, struct SPUFreeze *, unsigned int);\r
+typedef long (CALLBACK* SPUfreeze)(int ulFreezeMode, SPUFreeze_t * pF,\r
+ unsigned short **ram, void * pF2, unsigned int cycles);\r
typedef void (CALLBACK* SPUasync)(unsigned int, unsigned int);\r
typedef int (CALLBACK* SPUplayCDDAchannel)(short *, int, unsigned int, int);\r
typedef void (CALLBACK* SPUsetCDvol)(unsigned char, unsigned char, unsigned char, unsigned char, unsigned int);\r
\r
typedef struct\r
{\r
+ xa_decode_t xa;\r
+\r
unsigned short spuIrq;\r
unsigned short decode_pos;\r
uint32_t pSpuIrq;\r
\r
////////////////////////////////////////////////////////////////////////\r
\r
-static SPUOSSFreeze_t * LoadStateV5(SPUFreeze_t * pF, uint32_t cycles);\r
-static void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles); // unknown format\r
+static void LoadStateV5(SPUOSSFreeze_t * pFO, uint32_t cycles);\r
+static void LoadStateUnknown(uint32_t cycles); // unknown format\r
\r
#define SB_FORMAT_MAGIC 0x73626201\r
\r
// SPUFREEZE: called by main emu on savestate load/save\r
////////////////////////////////////////////////////////////////////////\r
\r
-long DoFreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,\r
- unsigned int cycles)\r
+long DoFreeze(int ulFreezeMode, struct SPUFreeze * pF, unsigned short **ram,\r
+ void * pF2, unsigned int cycles)\r
{\r
SPUOSSFreeze_t * pFO = NULL;\r
sample_buf_rvb *sb_rvb = &spu.sb_rvb;\r
+ unsigned int ossOffset = sizeof(SPUFreeze_t) + 512*1024; // when combined\r
int i, j;\r
\r
- if(!pF) return 0; // first check\r
+ assert(sizeof(SPUOSSFreeze_t) <= SPUFREEZE_F2_MAX_SIZE);\r
+ if (ram)\r
+ *ram = spu.spuMem;\r
+ if (!pF || !pF2) return 0; // first check\r
+ pFO = pF2;\r
\r
#if P_HAVE_PTHREAD || defined(WANT_THREAD_CODE)\r
sb_rvb = (sample_buf_rvb *)&spu.sb_thread[MAXCHAN];\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
+ if (ulFreezeMode == 1)\r
+ memset(pF, 0, sizeof(*pF));\r
\r
strcpy(pF->PluginName, "PBOSS");\r
pF->PluginVersion = 5;\r
- pF->Size = sizeof(SPUFreeze_t)+sizeof(SPUOSSFreeze_t);\r
+ pF->Size = ossOffset + sizeof(SPUOSSFreeze_t);\r
\r
if(ulFreezeMode==2) return 1; // info mode? ok, bye\r
// save mode:\r
regAreaGet(H_SPUctrl) = spu.spuCtrl;\r
regAreaGet(H_SPUstat) = spu.spuStat;\r
- memcpy(pF->SPURam, spu.spuMem, 0x80000); // copy common infos\r
memcpy(pF->SPUPorts, spu.regArea, 0x200);\r
\r
if(spu.xapGlobal && spu.XAPlay!=spu.XAFeed) // some xa\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->xa = *spu.xapGlobal;\r
+ pFO->xa = *spu.xapGlobal;\r
}\r
else if (spu.CDDAPlay != spu.CDDAFeed)\r
{\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->xa.pcm) / 4)\r
- cdda_left = sizeof(pF->xa.pcm) / 4;\r
+ if (cdda_left > sizeof(pFO->xa.pcm) / 4)\r
+ cdda_left = sizeof(pFO->xa.pcm) / 4;\r
if (p + cdda_left <= spu.CDDAEnd)\r
- memcpy(pF->xa.pcm, p, cdda_left * 4);\r
+ memcpy(pFO->xa.pcm, p, cdda_left * 4);\r
else {\r
- memcpy(pF->xa.pcm, p, (spu.CDDAEnd - p) * 4);\r
- memcpy((char *)pF->xa.pcm + (spu.CDDAEnd - p) * 4, spu.CDDAStart,\r
+ memcpy(pFO->xa.pcm, p, (spu.CDDAEnd - p) * 4);\r
+ memcpy((char *)pFO->xa.pcm + (spu.CDDAEnd - p) * 4, spu.CDDAStart,\r
(cdda_left - (spu.CDDAEnd - p)) * 4);\r
}\r
- pF->xa.nsamples = 0;\r
+ pFO->xa.nsamples = 0;\r
}\r
else\r
- memset(&pF->xa, 0, sizeof(xa_decode_t)); // or clean xa\r
-\r
- pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff\r
+ memset(&pFO->xa, 0, sizeof(xa_decode_t)); // or clean xa\r
\r
pFO->spuIrq = spu.regArea[(H_SPUirqAddr - 0x0c00) / 2];\r
if(spu.pSpuIrq) pFO->pSpuIrq = spu.pSpuIrq - spu.spuMemC;\r
\r
if(ulFreezeMode!=0) return 0; // bad mode? bye\r
\r
- memcpy(spu.spuMem, pF->SPURam, 0x80000); // get ram\r
memcpy(spu.regArea, pF->SPUPorts, 0x200);\r
spu.bMemDirty = 1;\r
spu.spuCtrl = regAreaGet(H_SPUctrl);\r
spu.spuStat = regAreaGet(H_SPUstat);\r
\r
if (!strcmp(pF->PluginName, "PBOSS") && pF->PluginVersion == 5)\r
- pFO = LoadStateV5(pF, cycles);\r
- else LoadStateUnknown(pF, cycles);\r
+ LoadStateV5(pFO, cycles);\r
+ else {\r
+ LoadStateUnknown(cycles);\r
+ pFO = NULL;\r
+ }\r
\r
spu.XAPlay = spu.XAFeed = spu.XAStart;\r
spu.CDDAPlay = spu.CDDAFeed = spu.CDDAStart;\r
spu.cdClearSamples = 512;\r
- if (pFO && pFO->xa_left && pF->xa.nsamples) { // start xa again\r
- FeedXA(&pF->xa);\r
+ if (pFO && pFO->xa_left && pFO->xa.nsamples) { // start xa again\r
+ FeedXA(&pFO->xa);\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->xa.pcm, pFO->cdda_left * 4);\r
+ FeedCDDA((void *)pFO->xa.pcm, pFO->cdda_left * 4);\r
}\r
\r
// not in old savestates\r
spu.XALastVal = 0;\r
spu.last_keyon_cycles = cycles - 16*786u;\r
spu.interpolation = -1;\r
- if (pFO && pF->Size >= sizeof(*pF) + offsetof(SPUOSSFreeze_t, rvb_sb)) {\r
+ if (pFO && pF->Size >= ossOffset + offsetof(SPUOSSFreeze_t, rvb_sb)) {\r
spu.cycles_dma_end = pFO->cycles_dma_end;\r
spu.decode_dirty_ch = pFO->decode_dirty_ch;\r
spu.dwNoiseVal = pFO->dwNoiseVal;\r
spu.XALastVal = pFO->XALastVal;\r
spu.last_keyon_cycles = pFO->last_keyon_cycles;\r
}\r
- if (pFO && pF->Size >= sizeof(*pF) + sizeof(*pFO)) {\r
+ if (pFO && pF->Size >= ossOffset + sizeof(*pFO)) {\r
for (i = 0; i < 2; i++)\r
for (j = 0; j < 2; j++)\r
memcpy(&sb_rvb->sample[i][j*4], pFO->rvb_sb[i], 4 * sizeof(sb_rvb->sample[i][0]));\r
\r
////////////////////////////////////////////////////////////////////////\r
\r
-static SPUOSSFreeze_t * LoadStateV5(SPUFreeze_t * pF, uint32_t cycles)\r
+static void LoadStateV5(SPUOSSFreeze_t * pFO, uint32_t cycles)\r
{\r
- int i;SPUOSSFreeze_t * pFO;\r
-\r
- pFO=(SPUOSSFreeze_t *)(pF+1);\r
+ int i;\r
\r
spu.pSpuIrq = spu.spuMemC + ((spu.regArea[(H_SPUirqAddr - 0x0c00) / 2] << 3) & ~0xf);\r
\r
spu.s_chan[i].pCurr+=(uintptr_t)spu.spuMemC;\r
spu.s_chan[i].pLoop+=(uintptr_t)spu.spuMemC;\r
}\r
-\r
- return pFO;\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
\r
-static void LoadStateUnknown(SPUFreeze_t * pF, uint32_t cycles)\r
+static void LoadStateUnknown(uint32_t cycles)\r
{\r
int i;\r
\r
#endif
-long CALLBACK SPUfreeze(unsigned int ulFreezeMode, struct SPUFreeze * pF,
- unsigned int cycles)
+long CALLBACK SPUfreeze(int ulFreezeMode, SPUFreeze_t * pF, unsigned short **ram,
+ void * pF2, unsigned int cycles)
{
if (worker != NULL)
sync_worker_thread(1);
- return DoFreeze(ulFreezeMode, pF, cycles);
+ return DoFreeze(ulFreezeMode, pF, ram, pF2, cycles);
}
// SPUINIT: this func will be called first by the main emu
unsigned short CALLBACK SPUreadRegister(unsigned long, unsigned int);\r
void CALLBACK SPUregisterCallback(void (*cb)(int));\r
void CALLBACK SPUregisterScheduleCb(void (*cb)(unsigned int));\r
-long CALLBACK SPUfreeze(unsigned int, struct SPUFreeze *, unsigned int);\r
+long CALLBACK SPUfreeze(int ulFreezeMode, struct SPUFreeze * pF, unsigned short **ram,\r
+ void * pF2, unsigned int cycles);\r
void CALLBACK SPUasync(unsigned int, unsigned int);\r
\r
void CALLBACK SPUreadDMAMem(unsigned short * pusPSXMem,int iSize,unsigned int cycles);\r
\r
// internal\r
void ClearWorkingState(void);\r
-long DoFreeze(unsigned int, struct SPUFreeze *, unsigned int);\r
+long DoFreeze(int ulFreezeMode, struct SPUFreeze * pF, unsigned short **ram,\r
+ void * pF2, unsigned int cycles);\r
\r
#endif /* __P_SPU_H__ */\r
return ret;
}
-long GPUfreeze(uint32_t type, GPUFreeze_t *freeze)
+long GPUfreeze(uint32_t type, GPUFreeze_t *freeze, uint16_t **vram_ptr)
{
int i;
}
sync_renderer(&gpu);
- memcpy(freeze->psxVRam, gpu.vram, 1024 * 512 * 2);
memcpy(freeze->ulControl, gpu.regs, sizeof(gpu.regs));
memcpy(freeze->ulControl + 0xe0, gpu.ex_regs, sizeof(gpu.ex_regs));
freeze->ulStatus = gpu.status;
break;
case 0: // load
sync_renderer(&gpu);
- memcpy(gpu.vram, freeze->psxVRam, 1024 * 512 * 2);
//memcpy(gpu.regs, freeze->ulControl, sizeof(gpu.regs));
memcpy(gpu.ex_regs, freeze->ulControl + 0xe0, sizeof(gpu.ex_regs));
gpu.status = freeze->ulStatus;
break;
}
+ *vram_ptr = gpu.vram;
return 1;
}
uint32_t GPUreadData(void);
uint32_t GPUreadStatus(void);
void GPUwriteStatus(uint32_t data);
-long GPUfreeze(uint32_t type, struct GPUFreeze *freeze);
+long GPUfreeze(uint32_t type, struct GPUFreeze *freeze, uint16_t **vram_ptr);
void GPUupdateLace(void);
long GPUopen(unsigned long *disp, char *cap, char *cfg);
long GPUclose(void);
////////////////////////////////////////////////////////////////////////\r
-long CALLBACK SPUfreeze(unsigned long ulFreezeMode,SPUFreeze_t * pF,unsigned int cycles)
+long DoFreeze(int ulFreezeMode, SPUFreeze_t * pF, unsigned short **ram,
+ void * pF2, unsigned int cycles)
{
int i;
+ if (ram)
+ *ram = spuMem;
if(!pF) return 0;
if(ulFreezeMode)
if(ulFreezeMode==2) return 1;
- memcpy(pF->SPURam, spuMem, 0x80000);
memcpy(pF->SPUPorts, regArea, 0x200);
- // dummy:
- memset(&pF->xa, 0, sizeof(xa_decode_t));
return 1;
}
if(ulFreezeMode!=0) return 0;
- memcpy(spuMem, pF->SPURam, 0x80000);
memcpy(regArea, pF->SPUPorts, 0x200);
for(i=0;i<0x100;i++)