Skip to content

Commit bf2a05c

Browse files
committed
Fixed the reason why rewinding was crashing the emulator (it was the sound rendering code - specifically, silence rendering)
Added backwards-compatibility for 0x10 version save states (only load, no save) Moved timing to emulate.cpp (was in tlcs900h) State saving is now only done if at least one button is mapped to 'rewind'
1 parent 840d222 commit bf2a05c

5 files changed

Lines changed: 221 additions & 60 deletions

File tree

psp/emulate.cpp

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ static int ScreenX, ScreenY, ScreenW, ScreenH;
5656
static int ClearScreen;
5757
static int Rewinding;
5858
static int frames_until_save;
59+
static u32 TicksPerUpdate;
60+
static u64 LastTick;
61+
static u64 CurrentTick;
62+
static u8 RewindEnabled;
5963

6064
static void AudioCallback(pl_snd_sample* buf,
6165
unsigned int samples,
@@ -96,11 +100,17 @@ void graphics_paint()
96100

97101
/* Blit screen */
98102
sceGuDisable(GU_BLEND);
99-
pspVideoPutImage(Screen,
100-
ScreenX, ScreenY,
101-
ScreenW, ScreenH);
103+
pspVideoPutImage(Screen, ScreenX, ScreenY, ScreenW, ScreenH);
102104
sceGuEnable(GU_BLEND);
103105

106+
/* Wait if needed */
107+
if (psp_options.update_freq)
108+
{
109+
do { sceRtcGetCurrentTick(&CurrentTick); }
110+
while (CurrentTick - LastTick < TicksPerUpdate);
111+
LastTick = CurrentTick;
112+
}
113+
104114
/* Show FPS counter */
105115
if (psp_options.show_fps)
106116
{
@@ -149,8 +159,30 @@ void RunEmulation()
149159
/* Initialize performance counter */
150160
pl_perf_init_counter(&FpsCounter);
151161
ClearScreen = 1;
152-
Rewinding = 0;
153162
frames_until_save = 0;
163+
Rewinding = 0;
164+
165+
/* Determine if at least 1 button is mapped to 'rewind' */
166+
RewindEnabled = 0;
167+
psp_ctrl_mask_to_index_map_t *current_mapping = physical_to_emulated_button_map;
168+
for (; current_mapping->mask; current_mapping++)
169+
{
170+
u32 code = current_map.button_map[current_mapping->index];
171+
if ((code & SPC) && (CODE_MASK(code) == SPC_REWIND))
172+
{
173+
RewindEnabled = 1; /* Rewind button is mapped */
174+
break;
175+
}
176+
}
177+
178+
/* Recompute update frequency */
179+
u32 TicksPerSecond = sceRtcGetTickResolution();
180+
if (psp_options.update_freq)
181+
{
182+
TicksPerUpdate = TicksPerSecond
183+
/ (psp_options.update_freq / (psp_options.frame_skip + 1));
184+
sceRtcGetCurrentTick(&LastTick);
185+
}
154186

155187
/* Resume sound */
156188
pl_snd_resume(0);
@@ -219,6 +251,9 @@ void UpdateInputState()
219251

220252
void HandleStateSaving()
221253
{
254+
if (!RewindEnabled)
255+
return;
256+
222257
/* Rewind/save state */
223258
if (!Rewinding)
224259
{
@@ -239,15 +274,17 @@ static void AudioCallback(pl_snd_sample* buf,
239274
unsigned int samples,
240275
void *userdata)
241276
{
277+
int length_bytes = samples << 1; /* 2 bytes per sample */
278+
242279
if (!Rewinding)
243280
{
244-
int length_bytes = samples << 1; /* 2 bytes per sample */
245281
sound_update((_u16*)buf, length_bytes); //Get sound data
246282
dac_update((_u16*)buf, length_bytes);
247283
}
248284
else /* Render silence */
249-
for (unsigned int i = 0; i < samples; i++)
250-
buf[i].stereo.l = buf[i].stereo.r = 0;
285+
{
286+
memset(buf, 0, length_bytes);
287+
}
251288
}
252289

253290
/* Release emulation resources */

psp/emulate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ typedef struct psp_options_t
3939
uint16_t clock_freq;
4040
uint8_t autofire;
4141
int rewind_save_rate;
42+
uint8_t update_freq;
4243
} psp_options_t;
4344

4445
extern psp_options_t psp_options;

psp/menu.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,7 @@ static void psp_load_options()
10801080
psp_options.frame_skip = pl_ini_get_int(&file, "Video", "Frame Skipping", 0);
10811081
psp_options.clock_freq = pl_ini_get_int(&file, "Video", "PSP Clock Frequency", 333);
10821082
psp_options.show_fps = pl_ini_get_int(&file, "Video", "Show FPS", 0);
1083+
psp_options.update_freq = pl_ini_get_int(&file, "Video", "Update Frequency", HOST_FPS);
10831084
psp_options.rewind_save_rate = pl_ini_get_int(&file, "Enhancements", "Rewind Save Rate", 5);
10841085
pl_ini_get_string(&file, "File", "Game Path", NULL,
10851086
GamePath, sizeof(GamePath));
@@ -1114,6 +1115,8 @@ static int psp_save_options()
11141115
psp_options.frame_skip);
11151116
pl_ini_set_int(&file, "Video", "PSP Clock Frequency",
11161117
psp_options.clock_freq);
1118+
pl_ini_set_int(&file, "Video", "Update Frequency",
1119+
psp_options.update_freq);
11171120
pl_ini_set_int(&file, "Video", "Show FPS",
11181121
psp_options.show_fps);
11191122
pl_ini_set_int(&file, "Menu", "Control Mode",

state.cpp

Lines changed: 156 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// state.cpp: state saving
1010
//
1111
// 01/20/2009 Cleaned up interface, added loading from memory
12-
// Moved signature-related stuff out of RACE_STATE (A.K.)
12+
// Moved signature-related stuff out of race_state (A.K.)
1313
// 09/11/2008 Initial version (Akop Karapetyan)
1414
//
1515
//////////////////////////////////////////////////////////////////////
@@ -27,16 +27,15 @@
2727
#undef PC
2828
#endif
2929

30-
/* sizeof() tends to report a larger size, IIRC */
31-
/* #define RACE_STATE_HEADER_SIZE sizeof(struct RACE_STATE_HEADER) */
32-
#define RACE_STATE_HEADER_SIZE 0x41
33-
struct RACE_STATE_HEADER
30+
#define CURRENT_SAVE_STATE_VERSION 0x11
31+
32+
struct race_state_header
3433
{
35-
u8 state_version; /* State version, currently = 0x10 */
34+
u8 state_version; /* State version */
3635
u8 rom_signature[0x40]; /* Rom signature, for verification */
3736
};
3837

39-
struct RACE_STATE
38+
struct race_state_0x11
4039
{
4140
/* Memory */
4241
u8 ram[0xc000];
@@ -62,27 +61,64 @@ struct RACE_STATE
6261

6362
/* DMA */
6463
u8 ldcRegs[64];
65-
};
64+
};
65+
66+
struct race_state_0x10 /* Older state format */
67+
{
68+
//Save state version
69+
u8 state_version; // = 0x10
70+
71+
//Rom signature
72+
u8 rom_signature[0x40];
73+
74+
//Memory
75+
u8 ram[0xc000];
76+
u8 cpuram[0x08a0];// 0xC000]; 0x38000
77+
78+
//TLCS-900h Registers
79+
u32 pc, sr;
80+
u8 f_dash;
81+
u32 gpr[23];
82+
83+
//Z80 Registers
84+
cz80_struc RACE_cz80_struc;
85+
u32 PC_offset;
86+
s32 Z80_ICount;
87+
88+
//Sound Chips
89+
int sndCycles;
90+
SoundChip toneChip;
91+
SoundChip noiseChip;
92+
93+
//Timers
94+
int timer0, timer1, timer2, timer3;
95+
96+
//DMA
97+
u8 ldcRegs[64];
98+
};
6699

67-
static int state_store(struct RACE_STATE *rs);
68-
static int state_restore(struct RACE_STATE *rs);
100+
typedef struct race_state_0x11 race_state_t;
101+
102+
static int state_store(race_state_t *rs);
103+
static int state_restore(race_state_t *rs);
104+
static int state_restore_0x10(FILE *stream);
69105

70106
int state_store_mem(void *state)
71107
{
72-
return state_store((struct RACE_STATE*)state);
108+
return state_store((race_state_t*)state);
73109
}
74110

75111
int state_restore_mem(void *state)
76112
{
77-
return state_restore((struct RACE_STATE*)state);
113+
return state_restore((race_state_t*)state);
78114
}
79115

80116
int state_get_size()
81117
{
82-
return sizeof(struct RACE_STATE);
118+
return sizeof(race_state_t);
83119
}
84120

85-
static int state_store(struct RACE_STATE *rs)
121+
static int state_store(race_state_t *rs)
86122
{
87123
int i = 0;
88124

@@ -151,7 +187,7 @@ static int state_store(struct RACE_STATE *rs)
151187
return 1;
152188
}
153189

154-
static int state_restore(struct RACE_STATE *rs)
190+
static int state_restore(race_state_t *rs)
155191
{
156192
int i = 0;
157193

@@ -225,20 +261,30 @@ static int state_restore(struct RACE_STATE *rs)
225261
}
226262

227263
int state_restore(FILE *stream)
228-
{
264+
{
265+
/* Note current position (in case of compatibility rewinds */
266+
long read_pos = ftell(stream);
267+
229268
/* Read header */
230-
struct RACE_STATE_HEADER rsh;
231-
if (fread(&rsh, RACE_STATE_HEADER_SIZE, 1, stream) < 1)
269+
struct race_state_header rsh;
270+
if (fread(&rsh, sizeof(rsh), 1, stream) < 1)
232271
return 0;
233272

234-
/* Verify state version & signature */
235-
if (rsh.state_version != 0x10)
236-
return 0;
273+
/* Verify state version */
274+
if (rsh.state_version == 0x10)
275+
{
276+
fseek(stream, read_pos, SEEK_SET); /* Rewind and load old format */
277+
return state_restore_0x10(stream);
278+
}
279+
else if (rsh.state_version != CURRENT_SAVE_STATE_VERSION)
280+
return 0; /* Unsupported version */
281+
282+
/* Verify ROM signature */
237283
if (memcmp(mainrom, rsh.rom_signature, sizeof(rsh.rom_signature)) != 0)
238284
return 0;
239285

240286
/* Read state data */
241-
struct RACE_STATE rs;
287+
race_state_t rs;
242288
if (fread(&rs, sizeof(rs), 1, stream) < 1)
243289
return 0;
244290

@@ -249,17 +295,17 @@ int state_restore(FILE *stream)
249295
int state_store(FILE *stream)
250296
{
251297
/* Set version & ROM signature information */
252-
struct RACE_STATE_HEADER rsh;
253-
rsh.state_version = 0x10;
298+
struct race_state_header rsh;
299+
rsh.state_version = CURRENT_SAVE_STATE_VERSION;
254300
memcpy(rsh.rom_signature, mainrom, sizeof(rsh.rom_signature));
255301

256302
/* Initialize state data */
257-
struct RACE_STATE rs;
303+
race_state_t rs;
258304
if (!state_store(&rs))
259305
return 0;
260306

261307
/* Write to file */
262-
if (fwrite(&rsh, RACE_STATE_HEADER_SIZE, 1, stream) < 1)
308+
if (fwrite(&rsh, sizeof(rsh), 1, stream) < 1)
263309
return 0;
264310
if (fwrite(&rs, sizeof(rs), 1, stream) < 1)
265311
return 0;
@@ -277,7 +323,8 @@ int state_store(char* filename)
277323
fclose(stream);
278324

279325
return status;
280-
}
326+
}
327+
281328
int state_restore(char* filename)
282329
{
283330
FILE *stream;
@@ -290,3 +337,85 @@ int state_restore(char* filename)
290337
return status;
291338
}
292339

340+
static int state_restore_0x10(FILE *stream)
341+
{
342+
struct race_state_0x10 rs;
343+
if (fread(&rs, sizeof(rs), 1, stream) < 1)
344+
return 0;
345+
346+
// Verify state version
347+
if (rs.state_version != 0x10)
348+
return 0;
349+
350+
// Verify ROM signature
351+
if (memcmp(mainrom, rs.rom_signature, sizeof(rs.rom_signature)) != 0)
352+
return 0;
353+
354+
//TLCS-900h Registers
355+
gen_regsPC = rs.pc;
356+
gen_regsSR = rs.sr;
357+
F2 = rs.f_dash;
358+
359+
int i = 0;
360+
gen_regsXWA0 = rs.gpr[i++];
361+
gen_regsXBC0 = rs.gpr[i++];
362+
gen_regsXDE0 = rs.gpr[i++];
363+
gen_regsXHL0 = rs.gpr[i++];
364+
365+
gen_regsXWA1 = rs.gpr[i++];
366+
gen_regsXBC1 = rs.gpr[i++];
367+
gen_regsXDE1 = rs.gpr[i++];
368+
gen_regsXHL1 = rs.gpr[i++];
369+
370+
gen_regsXWA2 = rs.gpr[i++];
371+
gen_regsXBC2 = rs.gpr[i++];
372+
gen_regsXDE2 = rs.gpr[i++];
373+
gen_regsXHL2 = rs.gpr[i++];
374+
375+
gen_regsXWA3 = rs.gpr[i++];
376+
gen_regsXBC3 = rs.gpr[i++];
377+
gen_regsXDE3 = rs.gpr[i++];
378+
gen_regsXHL3 = rs.gpr[i++];
379+
380+
gen_regsXIX = rs.gpr[i++];
381+
gen_regsXIY = rs.gpr[i++];
382+
gen_regsXIZ = rs.gpr[i++];
383+
gen_regsXSP = rs.gpr[i++];
384+
385+
gen_regsSP = rs.gpr[i++];
386+
gen_regsXSSP = rs.gpr[i++];
387+
gen_regsXNSP = rs.gpr[i++];
388+
389+
//Z80 Registers
390+
extern cz80_struc *RACE_cz80_struc;
391+
extern s32 Z80_ICount;
392+
int size_of_z80 =
393+
(u32)(&(RACE_cz80_struc->CycleSup)) - (u32)(&(RACE_cz80_struc->BC));
394+
395+
memcpy(RACE_cz80_struc, &rs.RACE_cz80_struc, size_of_z80);
396+
Z80_ICount = rs.Z80_ICount;
397+
Cz80_Set_PC(RACE_cz80_struc, rs.PC_offset);
398+
399+
//Sound Chips
400+
extern int sndCycles;
401+
sndCycles = rs.sndCycles;
402+
memcpy(&toneChip, &rs.toneChip, sizeof(SoundChip));
403+
memcpy(&noiseChip, &rs.noiseChip, sizeof(SoundChip));
404+
405+
//Timers
406+
timer0 = rs.timer0;
407+
timer1 = rs.timer1;
408+
timer2 = rs.timer2;
409+
timer3 = rs.timer3;
410+
411+
//DMA
412+
memcpy(&ldcRegs, &rs.ldcRegs, sizeof(ldcRegs));
413+
414+
//Memory
415+
memcpy(mainram, rs.ram, sizeof(rs.ram));
416+
memcpy(&mainram[0x20000], rs.cpuram, sizeof(rs.cpuram));
417+
418+
tlcs_reinit();
419+
420+
return 1;
421+
}

0 commit comments

Comments
 (0)