Add --bsvrecord.

This commit is contained in:
Themaister 2011-11-18 18:03:24 +01:00
parent 81b0e6d0a3
commit c5c60c6f53
4 changed files with 109 additions and 15 deletions

View File

@ -1,6 +1,6 @@
.\" ssnes.1:
.TH "SSNES" "1" "October 2011" "SSNES" "System Manager's Manual: ssnes"
.TH "SSNES" "1" "November 2011" "SSNES" "System Manager's Manual: ssnes"
.SH NAME
@ -101,6 +101,7 @@ When using Sufami, save ram paths will be inferred from the Sufami BIOS path, no
\fB--mouse PORT, -m PORT\fR
Connects a Super Nintendo Mouse into port number PORT of the emulated SNES. Possible values for PORT are 1 and 2.
.TP
\fB--nodevice PORT, -N PORT\fR
Disconnects an input device from port number PORT of the emulated SNES. Possible values for PORT are 1 and 2. This may be needed for some odd games to run properly.
@ -135,6 +136,14 @@ The video input is scaled with point filtering before being encoded at the corre
Play back a movie recorded in the .bsv format (bSNES). Cart ROM and movie file need to correspond.
It also requires to play back with the same libsnes backend that was used for recording.
.TP
\fB--bsvrecord MODE, -R MODE\fR
Start recording a .bsv video immediately after startup.
MODE designates how to handle SRAM.
The format of the second parameter is {no,}load-{no,}save.
These two boolean values tell if SRAM loading and SRAM saving should take place.
Not loading SRAM when recording allows SSNES to avoid including a save state in the .bsv to conserve space.
.TP
\fB--verbose, -v\fR
Activates verbose logging.

View File

@ -271,6 +271,11 @@ struct global
bool bsv_movie_end;
bool bsv_movie_playback;
// Immediate recording.
bool bsv_movie_record_start;
bool bsv_movie_record_sram_start;
bool bsv_movie_record_sram_end;
// Pausing support
bool is_paused;
bool is_oneshot;

11
movie.c
View File

@ -196,6 +196,9 @@ static bool init_record(bsv_movie_t *handle, const char *path)
header[CRC_INDEX] = swap_if_big32(g_extern.cart_crc);
uint32_t state_size = psnes_serialize_size();
if (!g_extern.bsv_movie_record_sram_start)
state_size = 0;
header[STATE_SIZE_INDEX] = swap_if_big32(state_size);
fwrite(header, 4, sizeof(uint32_t), handle->file);
@ -205,8 +208,12 @@ static bool init_record(bsv_movie_t *handle, const char *path)
handle->min_file_pos = sizeof(header) + state_size;
psnes_serialize(handle->state, state_size);
fwrite(handle->state, 1, state_size, handle->file);
if (state_size > 0)
{
psnes_serialize(handle->state, state_size);
fwrite(handle->state, 1, state_size, handle->file);
}
return true;
}

97
ssnes.c
View File

@ -456,6 +456,9 @@ static void print_help(void)
puts("\t-J/--justifiers: Daisy chain two virtual Konami Justifiers into port 2 of the SNES.");
puts("\t-4/--multitap: Connect a multitap to port 2 of the SNES.");
puts("\t-P/--bsvplay: Playback a BSV movie file.");
puts("\t-R/--bsvrecord: Start recording a BSV movie file from the beginning.");
puts("\t\tThis option takes arguments telling how to handle SRAM in the recording session.");
puts("\t\t{no,}load-{no,}save describes if SRAM should be loaded, and if SRAM should be saved.");
#ifdef HAVE_NETPLAY
puts("\t-H/--host: Host netplay as player 1.");
puts("\t-C/--connect: Connect to netplay as player 2.");
@ -602,6 +605,7 @@ static void parse_input(int argc, char *argv[])
{ "sufamiA", 1, NULL, 'Y' },
{ "sufamiB", 1, NULL, 'Z' },
{ "bsvplay", 1, NULL, 'P' },
{ "bsvrecord", 1, NULL, 'R' },
{ "host", 0, NULL, 'H' },
{ "connect", 1, NULL, 'C' },
{ "frames", 1, NULL, 'F' },
@ -634,7 +638,7 @@ static void parse_input(int argc, char *argv[])
#define DYNAMIC_ARG
#endif
char optstring[] = "hs:fvS:m:p4jJg:b:B:Y:Z:P:HC:F:U:DN:X:" DYNAMIC_ARG FFMPEG_RECORD_ARG CONFIG_FILE_ARG;
char optstring[] = "hs:fvS:m:p4jJg:b:B:Y:Z:P:R:HC:F:U:DN:X:" DYNAMIC_ARG FFMPEG_RECORD_ARG CONFIG_FILE_ARG;
for (;;)
{
val = 0;
@ -753,6 +757,38 @@ static void parse_input(int argc, char *argv[])
case 'P':
strlcpy(g_extern.bsv_movie_path, optarg, sizeof(g_extern.bsv_movie_path));
g_extern.bsv_movie_playback = true;
g_extern.bsv_movie_record_start = false;
break;
case 'R':
g_extern.bsv_movie_playback = false;
g_extern.bsv_movie_record_start = true;
if (strcmp(optarg, "noload-nosave") == 0)
{
g_extern.bsv_movie_record_sram_start = false;
g_extern.bsv_movie_record_sram_end = false;
}
else if (strcmp(optarg, "noload-save") == 0)
{
g_extern.bsv_movie_record_sram_start = false;
g_extern.bsv_movie_record_sram_end = true;
}
else if (strcmp(optarg, "load-nosave") == 0)
{
g_extern.bsv_movie_record_sram_start = true;
g_extern.bsv_movie_record_sram_end = false;
}
else if (strcmp(optarg, "load-save") == 0)
{
g_extern.bsv_movie_record_sram_start = true;
g_extern.bsv_movie_record_sram_end = true;
}
else
{
SSNES_ERR("Invalid argument in --bsvrecord!\n");
print_help();
exit(1);
}
break;
case 'H':
@ -1092,6 +1128,25 @@ static void init_movie(void)
g_settings.rewind_granularity = 1;
SSNES_LOG("Starting movie playback!\n");
}
else if (g_extern.bsv_movie_record_start)
{
g_settings.rewind_granularity = 1;
char path[MAXPATHLEN];
if (g_extern.state_slot > 0)
snprintf(path, sizeof(path), "%s%u.bsv", g_extern.bsv_movie_path, g_extern.state_slot);
else
snprintf(path, sizeof(path), "%s.bsv", g_extern.bsv_movie_path);
g_extern.bsv_movie = bsv_movie_init(path, SSNES_MOVIE_RECORD);
msg_queue_clear(g_extern.msg_queue);
msg_queue_push(g_extern.msg_queue, g_extern.bsv_movie ? "Starting movie record!" : "Failed to start movie record!", 1, 180);
if (g_extern.bsv_movie)
SSNES_LOG("Starting movie record!\n");
else
SSNES_ERR("Failed to start movie record!\n");
}
}
static void deinit_movie(void)
@ -1546,9 +1601,9 @@ static void check_movie_record(void)
else
{
g_settings.rewind_granularity = 1;
char path[512];
char path[MAXPATHLEN];
if (g_extern.state_slot > 0)
snprintf(path, sizeof(path), "%s%d.bsv", g_extern.bsv_movie_path, g_extern.state_slot);
snprintf(path, sizeof(path), "%s%u.bsv", g_extern.bsv_movie_path, g_extern.state_slot);
else
snprintf(path, sizeof(path), "%s.bsv", g_extern.bsv_movie_path);
@ -1841,10 +1896,19 @@ int main(int argc, char *argv[])
goto error;
init_msg_queue();
init_movie();
if (!g_extern.bsv_movie)
load_save_files();
if (g_extern.bsv_movie_record_start)
{
if (g_extern.bsv_movie_record_sram_start)
load_save_files();
init_movie();
}
else
{
init_movie();
if (!g_extern.bsv_movie)
load_save_files();
}
#ifdef HAVE_NETPLAY
init_netplay();
@ -1855,9 +1919,12 @@ int main(int argc, char *argv[])
init_rewind();
#ifdef HAVE_NETPLAY
psnes_set_video_refresh(g_extern.netplay ? video_frame_net : video_frame);
psnes_set_audio_sample(g_extern.netplay ? audio_sample_net : audio_sample);
psnes_set_input_state(g_extern.netplay ? input_state_net : input_state);
psnes_set_video_refresh(g_extern.netplay ?
video_frame_net : video_frame);
psnes_set_audio_sample(g_extern.netplay ?
audio_sample_net : audio_sample);
psnes_set_input_state(g_extern.netplay ?
input_state_net : input_state);
#else
psnes_set_video_refresh(video_frame);
psnes_set_audio_sample(audio_sample);
@ -1871,7 +1938,13 @@ int main(int argc, char *argv[])
init_recording();
#endif
if (!g_extern.bsv_movie_playback && !g_extern.netplay_is_client)
bool use_sram_auto = !g_extern.bsv_movie_playback &&
!g_extern.netplay_is_client &&
!g_extern.bsv_movie_record_start;
bool use_sram_end = use_sram_auto || g_extern.bsv_movie_record_sram_end;
if (use_sram_auto)
init_autosave();
#ifdef HAVE_XML
@ -1928,14 +2001,14 @@ int main(int argc, char *argv[])
deinit_netplay();
#endif
if (!g_extern.bsv_movie_playback && !g_extern.netplay_is_client)
if (use_sram_auto)
deinit_autosave();
#ifdef HAVE_FFMPEG
deinit_recording();
#endif
if (!g_extern.bsv_movie_playback && !g_extern.netplay_is_client)
if (use_sram_end)
save_files();
if (!g_extern.netplay)