Skip to content

Commit

Permalink
Fixed the reason why rewinding was crashing the emulator (it was the …
Browse files Browse the repository at this point in the history
…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'
  • Loading branch information
0xe1f committed Apr 4, 2009
1 parent 840d222 commit bf2a05c
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 60 deletions.
51 changes: 44 additions & 7 deletions psp/emulate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ static int ScreenX, ScreenY, ScreenW, ScreenH;
static int ClearScreen;
static int Rewinding;
static int frames_until_save;
static u32 TicksPerUpdate;
static u64 LastTick;
static u64 CurrentTick;
static u8 RewindEnabled;

static void AudioCallback(pl_snd_sample* buf,
unsigned int samples,
Expand Down Expand Up @@ -96,11 +100,17 @@ void graphics_paint()

/* Blit screen */
sceGuDisable(GU_BLEND);
pspVideoPutImage(Screen,
ScreenX, ScreenY,
ScreenW, ScreenH);
pspVideoPutImage(Screen, ScreenX, ScreenY, ScreenW, ScreenH);
sceGuEnable(GU_BLEND);

/* Wait if needed */
if (psp_options.update_freq)
{
do { sceRtcGetCurrentTick(&CurrentTick); }
while (CurrentTick - LastTick < TicksPerUpdate);
LastTick = CurrentTick;
}

/* Show FPS counter */
if (psp_options.show_fps)
{
Expand Down Expand Up @@ -149,8 +159,30 @@ void RunEmulation()
/* Initialize performance counter */
pl_perf_init_counter(&FpsCounter);
ClearScreen = 1;
Rewinding = 0;
frames_until_save = 0;
Rewinding = 0;

/* Determine if at least 1 button is mapped to 'rewind' */
RewindEnabled = 0;
psp_ctrl_mask_to_index_map_t *current_mapping = physical_to_emulated_button_map;
for (; current_mapping->mask; current_mapping++)
{
u32 code = current_map.button_map[current_mapping->index];
if ((code & SPC) && (CODE_MASK(code) == SPC_REWIND))
{
RewindEnabled = 1; /* Rewind button is mapped */
break;
}
}

/* Recompute update frequency */
u32 TicksPerSecond = sceRtcGetTickResolution();
if (psp_options.update_freq)
{
TicksPerUpdate = TicksPerSecond
/ (psp_options.update_freq / (psp_options.frame_skip + 1));
sceRtcGetCurrentTick(&LastTick);
}

/* Resume sound */
pl_snd_resume(0);
Expand Down Expand Up @@ -219,6 +251,9 @@ void UpdateInputState()

void HandleStateSaving()
{
if (!RewindEnabled)
return;

/* Rewind/save state */
if (!Rewinding)
{
Expand All @@ -239,15 +274,17 @@ static void AudioCallback(pl_snd_sample* buf,
unsigned int samples,
void *userdata)
{
int length_bytes = samples << 1; /* 2 bytes per sample */

if (!Rewinding)
{
int length_bytes = samples << 1; /* 2 bytes per sample */
sound_update((_u16*)buf, length_bytes); //Get sound data
dac_update((_u16*)buf, length_bytes);
}
else /* Render silence */
for (unsigned int i = 0; i < samples; i++)
buf[i].stereo.l = buf[i].stereo.r = 0;
{
memset(buf, 0, length_bytes);
}
}

/* Release emulation resources */
Expand Down
1 change: 1 addition & 0 deletions psp/emulate.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ typedef struct psp_options_t
uint16_t clock_freq;
uint8_t autofire;
int rewind_save_rate;
uint8_t update_freq;
} psp_options_t;

extern psp_options_t psp_options;
Expand Down
3 changes: 3 additions & 0 deletions psp/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,7 @@ static void psp_load_options()
psp_options.frame_skip = pl_ini_get_int(&file, "Video", "Frame Skipping", 0);
psp_options.clock_freq = pl_ini_get_int(&file, "Video", "PSP Clock Frequency", 333);
psp_options.show_fps = pl_ini_get_int(&file, "Video", "Show FPS", 0);
psp_options.update_freq = pl_ini_get_int(&file, "Video", "Update Frequency", HOST_FPS);
psp_options.rewind_save_rate = pl_ini_get_int(&file, "Enhancements", "Rewind Save Rate", 5);
pl_ini_get_string(&file, "File", "Game Path", NULL,
GamePath, sizeof(GamePath));
Expand Down Expand Up @@ -1114,6 +1115,8 @@ static int psp_save_options()
psp_options.frame_skip);
pl_ini_set_int(&file, "Video", "PSP Clock Frequency",
psp_options.clock_freq);
pl_ini_set_int(&file, "Video", "Update Frequency",
psp_options.update_freq);
pl_ini_set_int(&file, "Video", "Show FPS",
psp_options.show_fps);
pl_ini_set_int(&file, "Menu", "Control Mode",
Expand Down
183 changes: 156 additions & 27 deletions state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// state.cpp: state saving
//
// 01/20/2009 Cleaned up interface, added loading from memory
// Moved signature-related stuff out of RACE_STATE (A.K.)
// Moved signature-related stuff out of race_state (A.K.)
// 09/11/2008 Initial version (Akop Karapetyan)
//
//////////////////////////////////////////////////////////////////////
Expand All @@ -27,16 +27,15 @@
#undef PC
#endif

/* sizeof() tends to report a larger size, IIRC */
/* #define RACE_STATE_HEADER_SIZE sizeof(struct RACE_STATE_HEADER) */
#define RACE_STATE_HEADER_SIZE 0x41
struct RACE_STATE_HEADER
#define CURRENT_SAVE_STATE_VERSION 0x11

struct race_state_header
{
u8 state_version; /* State version, currently = 0x10 */
u8 state_version; /* State version */
u8 rom_signature[0x40]; /* Rom signature, for verification */
};

struct RACE_STATE
struct race_state_0x11
{
/* Memory */
u8 ram[0xc000];
Expand All @@ -62,27 +61,64 @@ struct RACE_STATE

/* DMA */
u8 ldcRegs[64];
};
};

struct race_state_0x10 /* Older state format */
{
//Save state version
u8 state_version; // = 0x10

//Rom signature
u8 rom_signature[0x40];

//Memory
u8 ram[0xc000];
u8 cpuram[0x08a0];// 0xC000]; 0x38000

//TLCS-900h Registers
u32 pc, sr;
u8 f_dash;
u32 gpr[23];

//Z80 Registers
cz80_struc RACE_cz80_struc;
u32 PC_offset;
s32 Z80_ICount;

//Sound Chips
int sndCycles;
SoundChip toneChip;
SoundChip noiseChip;

//Timers
int timer0, timer1, timer2, timer3;

//DMA
u8 ldcRegs[64];
};

static int state_store(struct RACE_STATE *rs);
static int state_restore(struct RACE_STATE *rs);
typedef struct race_state_0x11 race_state_t;

static int state_store(race_state_t *rs);
static int state_restore(race_state_t *rs);
static int state_restore_0x10(FILE *stream);

int state_store_mem(void *state)
{
return state_store((struct RACE_STATE*)state);
return state_store((race_state_t*)state);
}

int state_restore_mem(void *state)
{
return state_restore((struct RACE_STATE*)state);
return state_restore((race_state_t*)state);
}

int state_get_size()
{
return sizeof(struct RACE_STATE);
return sizeof(race_state_t);
}

static int state_store(struct RACE_STATE *rs)
static int state_store(race_state_t *rs)
{
int i = 0;

Expand Down Expand Up @@ -151,7 +187,7 @@ static int state_store(struct RACE_STATE *rs)
return 1;
}

static int state_restore(struct RACE_STATE *rs)
static int state_restore(race_state_t *rs)
{
int i = 0;

Expand Down Expand Up @@ -225,20 +261,30 @@ static int state_restore(struct RACE_STATE *rs)
}

int state_restore(FILE *stream)
{
{
/* Note current position (in case of compatibility rewinds */
long read_pos = ftell(stream);

/* Read header */
struct RACE_STATE_HEADER rsh;
if (fread(&rsh, RACE_STATE_HEADER_SIZE, 1, stream) < 1)
struct race_state_header rsh;
if (fread(&rsh, sizeof(rsh), 1, stream) < 1)
return 0;

/* Verify state version & signature */
if (rsh.state_version != 0x10)
return 0;
/* Verify state version */
if (rsh.state_version == 0x10)
{
fseek(stream, read_pos, SEEK_SET); /* Rewind and load old format */
return state_restore_0x10(stream);
}
else if (rsh.state_version != CURRENT_SAVE_STATE_VERSION)
return 0; /* Unsupported version */

/* Verify ROM signature */
if (memcmp(mainrom, rsh.rom_signature, sizeof(rsh.rom_signature)) != 0)
return 0;

/* Read state data */
struct RACE_STATE rs;
race_state_t rs;
if (fread(&rs, sizeof(rs), 1, stream) < 1)
return 0;

Expand All @@ -249,17 +295,17 @@ int state_restore(FILE *stream)
int state_store(FILE *stream)
{
/* Set version & ROM signature information */
struct RACE_STATE_HEADER rsh;
rsh.state_version = 0x10;
struct race_state_header rsh;
rsh.state_version = CURRENT_SAVE_STATE_VERSION;
memcpy(rsh.rom_signature, mainrom, sizeof(rsh.rom_signature));

/* Initialize state data */
struct RACE_STATE rs;
race_state_t rs;
if (!state_store(&rs))
return 0;

/* Write to file */
if (fwrite(&rsh, RACE_STATE_HEADER_SIZE, 1, stream) < 1)
if (fwrite(&rsh, sizeof(rsh), 1, stream) < 1)
return 0;
if (fwrite(&rs, sizeof(rs), 1, stream) < 1)
return 0;
Expand All @@ -277,7 +323,8 @@ int state_store(char* filename)
fclose(stream);

return status;
}
}

int state_restore(char* filename)
{
FILE *stream;
Expand All @@ -290,3 +337,85 @@ int state_restore(char* filename)
return status;
}

static int state_restore_0x10(FILE *stream)
{
struct race_state_0x10 rs;
if (fread(&rs, sizeof(rs), 1, stream) < 1)
return 0;

// Verify state version
if (rs.state_version != 0x10)
return 0;

// Verify ROM signature
if (memcmp(mainrom, rs.rom_signature, sizeof(rs.rom_signature)) != 0)
return 0;

//TLCS-900h Registers
gen_regsPC = rs.pc;
gen_regsSR = rs.sr;
F2 = rs.f_dash;

int i = 0;
gen_regsXWA0 = rs.gpr[i++];
gen_regsXBC0 = rs.gpr[i++];
gen_regsXDE0 = rs.gpr[i++];
gen_regsXHL0 = rs.gpr[i++];

gen_regsXWA1 = rs.gpr[i++];
gen_regsXBC1 = rs.gpr[i++];
gen_regsXDE1 = rs.gpr[i++];
gen_regsXHL1 = rs.gpr[i++];

gen_regsXWA2 = rs.gpr[i++];
gen_regsXBC2 = rs.gpr[i++];
gen_regsXDE2 = rs.gpr[i++];
gen_regsXHL2 = rs.gpr[i++];

gen_regsXWA3 = rs.gpr[i++];
gen_regsXBC3 = rs.gpr[i++];
gen_regsXDE3 = rs.gpr[i++];
gen_regsXHL3 = rs.gpr[i++];

gen_regsXIX = rs.gpr[i++];
gen_regsXIY = rs.gpr[i++];
gen_regsXIZ = rs.gpr[i++];
gen_regsXSP = rs.gpr[i++];

gen_regsSP = rs.gpr[i++];
gen_regsXSSP = rs.gpr[i++];
gen_regsXNSP = rs.gpr[i++];

//Z80 Registers
extern cz80_struc *RACE_cz80_struc;
extern s32 Z80_ICount;
int size_of_z80 =
(u32)(&(RACE_cz80_struc->CycleSup)) - (u32)(&(RACE_cz80_struc->BC));

memcpy(RACE_cz80_struc, &rs.RACE_cz80_struc, size_of_z80);
Z80_ICount = rs.Z80_ICount;
Cz80_Set_PC(RACE_cz80_struc, rs.PC_offset);

//Sound Chips
extern int sndCycles;
sndCycles = rs.sndCycles;
memcpy(&toneChip, &rs.toneChip, sizeof(SoundChip));
memcpy(&noiseChip, &rs.noiseChip, sizeof(SoundChip));

//Timers
timer0 = rs.timer0;
timer1 = rs.timer1;
timer2 = rs.timer2;
timer3 = rs.timer3;

//DMA
memcpy(&ldcRegs, &rs.ldcRegs, sizeof(ldcRegs));

//Memory
memcpy(mainram, rs.ram, sizeof(rs.ram));
memcpy(&mainram[0x20000], rs.cpuram, sizeof(rs.cpuram));

tlcs_reinit();

return 1;
}
Loading

0 comments on commit bf2a05c

Please sign in to comment.