From 2fa4495e723e97decf2db9c4c11a5f0156bf81de Mon Sep 17 00:00:00 2001 From: lemon-sherbet Date: Fri, 5 Feb 2021 09:45:38 +0100 Subject: [PATCH 1/2] Add m64 movie playback (from reset only) --- si/controller.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/si/controller.c b/si/controller.c index d62330620..746de9eae 100644 --- a/si/controller.c +++ b/si/controller.c @@ -146,7 +146,38 @@ int pif_perform_command(struct si_controller *si, if (likely(bus->vi->window)) { cen64_mutex_lock(&bus->vi->window->event_mutex); + + static FILE* m64 = NULL; + static bool give_up_m64 = false; + if (m64 || (!m64 && !give_up_m64)) { + if (!m64) { + m64 = fopen("cont.m64", "rb"); + if (m64) { + uint8_t header[0x400]; + int n = fread(header, 1, sizeof header, m64); + if (n == sizeof header) { + printf("Playing back m64:\n"); + printf(" ROM name: %.32s (crc %X, region %X)\n", + header+0xC4, + *(uint32_t*)(header+0xE4), + *(uint16_t*)(header+0xE8)); + printf(" Author: %.222s\n", header+0x222); + printf(" Description: %.256s\n", header+0x300); + } else { + printf("Bad m64!\n"); + fclose(m64), m64 = NULL; + give_up_m64 = true; + } + } else { + give_up_m64 = true; + } + } + + if (m64) fread(si->input, 1, 4, m64); + } + memcpy(recv_buf, si->input, sizeof(si->input)); + cen64_mutex_unlock(&bus->vi->window->event_mutex); } From 0297c9ffd5573ac427c35fb06ee1c5f350848ef0 Mon Sep 17 00:00:00 2001 From: lemon-sherbet Date: Fri, 5 Feb 2021 11:14:31 +0100 Subject: [PATCH 2/2] (m64 playback) Add proper command line interface. --- cen64.c | 28 +++++++++++++++++++++++++++- device/device.c | 10 +++++++--- device/device.h | 2 +- device/options.c | 12 ++++++++++++ device/options.h | 2 ++ si/controller.c | 38 +++++++++++--------------------------- si/controller.h | 5 ++++- 7 files changed, 64 insertions(+), 33 deletions(-) diff --git a/cen64.c b/cen64.c index 0aa7ec355..a3cef30e3 100644 --- a/cen64.c +++ b/cen64.c @@ -53,6 +53,8 @@ int cen64_main(int argc, const char **argv) { struct save_file flashram; struct is_viewer is, *is_in = NULL; + FILE* m64_fp = NULL; + if (!cart_db_is_well_formed()) { printf("Internal cart detection database is not well-formed.\n"); return EXIT_FAILURE; @@ -180,6 +182,30 @@ int cen64_main(int argc, const char **argv) { } } + if (options.m64_path) { + m64_fp = fopen(options.m64_path, "rb"); + if (m64_fp != NULL) { + // http://tasvideos.org/EmulatorResources/Mupen/M64.html + uint8_t header[0x400]; + size_t n = fread(header, 1, sizeof header, m64_fp); + if (n == sizeof header && memcmp(header, "M64\x1A", 4) == 0) { + printf("Playing back m64:\n"); + printf(" ROM name: %.32s (crc %X, region %X)\n", + header+0xC4, + *(uint32_t*)(header+0xE4), + *(uint16_t*)(header+0xE8)); + printf(" Author: %.222s\n", header+0x222); + printf(" Description: %.256s\n", header+0x300); + } else { + fclose(m64_fp); + printf("Invalid Mupen64 movie file '%s'.\n", options.m64_path); + return EXIT_FAILURE; + } + } else { + printf("Failed to open Mupen64 movie file '%s'.\n", options.m64_path); + return EXIT_FAILURE; + } + } // Allocate memory for and create the device. @@ -193,7 +219,7 @@ int cen64_main(int argc, const char **argv) { if (device_create(device, &ddipl, dd_variant, &ddrom, &pifrom, &cart, &eeprom, &sram, - &flashram, is_in, controller, + &flashram, is_in, controller, m64_fp, options.no_audio, options.no_video, options.enable_profiling) == NULL) { printf("Failed to create a device.\n"); status = EXIT_FAILURE; diff --git a/device/device.c b/device/device.c index cd5a046c6..4f2289609 100644 --- a/device/device.c +++ b/device/device.c @@ -44,7 +44,7 @@ struct cen64_device *device_create(struct cen64_device *device, const struct rom_file *pifrom, const struct rom_file *cart, const struct save_file *eeprom, const struct save_file *sram, const struct save_file *flashram, struct is_viewer *is, - const struct controller *controller, + const struct controller *controller, FILE* m64_fp, bool no_audio, bool no_video, bool profiling) { // Allocate memory for VR4300 @@ -99,7 +99,7 @@ struct cen64_device *device_create(struct cen64_device *device, // Initialize the SI. if (si_init(&device->si, &device->bus, pifrom->ptr, cart->ptr, dd_variant, eeprom->ptr, eeprom->size, - controller)) { + controller, m64_fp)) { debug("create_device: Failed to initialize the SI.\n"); return NULL; } @@ -160,6 +160,10 @@ void device_destroy(struct cen64_device *device, const char *cart_path) { fclose(f); } + + if (device->si.m64_fp != NULL) { + fclose(device->si.m64_fp); + } } // Called when we should (probably?) leave simulation. @@ -351,4 +355,4 @@ int device_debug_spin(struct cen64_device *device) { cen64_cold void device_connect_debugger(struct cen64_device *device, void* break_handler_data, vr4300_debug_break_handler break_handler) { vr4300_connect_debugger(device->vr4300, break_handler_data, break_handler); -} \ No newline at end of file +} diff --git a/device/device.h b/device/device.h index 81709c25a..dd63b3f8e 100644 --- a/device/device.h +++ b/device/device.h @@ -61,7 +61,7 @@ cen64_cold struct cen64_device *device_create(struct cen64_device *device, const struct rom_file *pifrom, const struct rom_file *cart, const struct save_file *eeprom, const struct save_file *sram, const struct save_file *flashram, struct is_viewer *is, - const struct controller *controller, + const struct controller *controller, FILE* m64_fp, bool no_audio, bool no_video, bool profiling); cen64_cold void device_exit(struct bus_controller *bus); diff --git a/device/options.c b/device/options.c index 65265061d..014aaa003 100644 --- a/device/options.c +++ b/device/options.c @@ -26,6 +26,7 @@ const struct cen64_options default_cen64_options = { NULL, // flashram_path 0, // is_viewer_present NULL, // controller + NULL, // m64_path #ifdef _WIN32 false, // console #endif @@ -153,6 +154,15 @@ int parse_options(struct cen64_options *options, int argc, const char *argv[]) { options->controller[num] = opt; } + else if (!strcmp(argv[i], "-m64")) { + if ((i + 1) >= (argc - 1)) { + printf("-m64 requires a path to the movie file.\n\n"); + return 1; + } + + options->m64_path = argv[++i]; + } + // TODO: Handle this better. else break; @@ -282,6 +292,8 @@ void print_command_line_usage(const char *invokation_string) { " -sram : Path to SRAM save.\n" " -flash : Path to FlashRAM save.\n" " For mempak see controller options.\n" + "Mupen64 movie playback options:\n" + " -m64 : Path to m64 movie file.\n" ,invokation_string ); diff --git a/device/options.h b/device/options.h index c8d38b9aa..aca8b8836 100644 --- a/device/options.h +++ b/device/options.h @@ -27,6 +27,8 @@ struct cen64_options { struct controller *controller; + const char* m64_path; + #ifdef _WIN32 bool console; #endif diff --git a/si/controller.c b/si/controller.c index 746de9eae..f6b9a9660 100644 --- a/si/controller.c +++ b/si/controller.c @@ -44,7 +44,8 @@ int si_init(struct si_controller *si, struct bus_controller *bus, const uint8_t *pif_rom, const uint8_t *cart_rom, const struct dd_variant *dd_variant, uint8_t *eeprom, size_t eeprom_size, - const struct controller *controller) { + const struct controller *controller, + FILE* m64_fp) { uint32_t cic_seed; si->bus = bus; @@ -83,6 +84,9 @@ int si_init(struct si_controller *si, struct bus_controller *bus, // controllers memcpy(si->controller, controller, sizeof(struct controller) * 4); + // Mupen64 movie file + si->m64_fp = m64_fp; + return 0; } @@ -147,33 +151,13 @@ int pif_perform_command(struct si_controller *si, if (likely(bus->vi->window)) { cen64_mutex_lock(&bus->vi->window->event_mutex); - static FILE* m64 = NULL; - static bool give_up_m64 = false; - if (m64 || (!m64 && !give_up_m64)) { - if (!m64) { - m64 = fopen("cont.m64", "rb"); - if (m64) { - uint8_t header[0x400]; - int n = fread(header, 1, sizeof header, m64); - if (n == sizeof header) { - printf("Playing back m64:\n"); - printf(" ROM name: %.32s (crc %X, region %X)\n", - header+0xC4, - *(uint32_t*)(header+0xE4), - *(uint16_t*)(header+0xE8)); - printf(" Author: %.222s\n", header+0x222); - printf(" Description: %.256s\n", header+0x300); - } else { - printf("Bad m64!\n"); - fclose(m64), m64 = NULL; - give_up_m64 = true; - } - } else { - give_up_m64 = true; - } + if (si->m64_fp != NULL) { + fread(si->input, 1, 4, si->m64_fp); + if (feof(si->m64_fp) || ferror(si->m64_fp)) { + fclose(si->m64_fp); + si->m64_fp = NULL; + printf("Movie playback finished.\n"); } - - if (m64) fread(si->input, 1, 4, m64); } memcpy(recv_buf, si->input, sizeof(si->input)); diff --git a/si/controller.h b/si/controller.h index 2e8a4ff4b..229ae9807 100644 --- a/si/controller.h +++ b/si/controller.h @@ -41,13 +41,16 @@ struct si_controller { uint8_t input[4]; struct eeprom eeprom; struct controller controller[4]; + + FILE* m64_fp; // Mupen64 movie file }; cen64_cold int si_init(struct si_controller *si, struct bus_controller *bus, const uint8_t *pif_rom, const uint8_t *cart_rom, const struct dd_variant *dd_variant, uint8_t *eeprom, size_t eeprom_size, - const struct controller *controller); + const struct controller *controller, + FILE* m64_fp); int read_pif_rom_and_ram(void *opaque, uint32_t address, uint32_t *word); int write_pif_rom_and_ram(void *opaque, uint32_t address, uint32_t word, uint32_t dqm);