From 2efa6a87a868b1d9301d8a9365b1496a1037aca7 Mon Sep 17 00:00:00 2001 From: misteraddons <51079966+misteraddons@users.noreply.github.com> Date: Wed, 22 Oct 2025 05:54:43 -0600 Subject: [PATCH] Write unique game info to /tmp/GAMENAME (#1045) * Write unique game info to /tmp/GAMENAME * Remove CD product code lookup, and crc32 * Remove product codes /tmp/GAMENAME only uses file path and crc32 * Clean up * Cleanup * Only write CRC32 and or Product Code to /tmp/GAMEID Realizing we already have the file path, this change writes the already calculated CRC32 and or game ID (N64 and PSX only) to /tmp/GAMEID. This ignores boot*.rom and cd_bios*.rom CRC32: XXXXXXXX Product Code: XXXXXXXXXXXX * Clean up * Update neogeo_loader.cpp * Skip GAMEID for all BIOS files * Guard behind log_file_entry ini option and clean up print statements * Add MRA GAMEID support and improve GAMEID writing MRA files use setname as serial * Add MGL handling for /tmp/ STARTPATH, FULLPATH, CURRENTPATH, and FILESELECT * Update mgl /tmp/ file handling --- menu.cpp | 31 +++++++++++++++++++- support/arcade/mra_loader.cpp | 16 ++++++++++- support/n64/n64.cpp | 7 +++++ support/psx/psx.cpp | 6 ++++ user_io.cpp | 54 +++++++++++++++++++++++++++++++++++ user_io.h | 1 + 6 files changed, 113 insertions(+), 2 deletions(-) diff --git a/menu.cpp b/menu.cpp index 554e285..a748665 100644 --- a/menu.cpp +++ b/menu.cpp @@ -2393,6 +2393,15 @@ void HandleUI(void) { if(mgl->item[mgl->current].path[0] == '/') snprintf(selPath, sizeof(selPath), "%s", mgl->item[mgl->current].path); else snprintf(selPath, sizeof(selPath), "%s/%s", HomeDir(), mgl->item[mgl->current].path); + + // Update /tmp/ files to reflect the actual file being loaded by MGL + if (cfg.log_file_entry) + { + const char *fname = strrchr(selPath, '/'); + MakeFile("/tmp/FULLPATH", selPath); + MakeFile("/tmp/CURRENTPATH", fname ? fname + 1 : selPath); + MakeFile("/tmp/FILESELECT", "selected"); + } } MenuHide(); @@ -2457,6 +2466,15 @@ void HandleUI(void) { if (mgl->item[mgl->current].path[0] == '/') snprintf(selPath, sizeof(selPath), "%s", mgl->item[mgl->current].path); else snprintf(selPath, sizeof(selPath), "%s/%s", HomeDir(((is_pce() && !strncasecmp(fs_pFileExt, "CUE", 3)) ? PCECD_DIR : NULL)), mgl->item[mgl->current].path); + + // Update /tmp/ files to reflect the actual image being loaded by MGL + if (cfg.log_file_entry) + { + const char *fname = strrchr(selPath, '/'); + MakeFile("/tmp/FULLPATH", selPath); + MakeFile("/tmp/CURRENTPATH", fname ? fname + 1 : selPath); + MakeFile("/tmp/FILESELECT", "selected"); + } } if (store_name) @@ -5687,7 +5705,18 @@ void HandleUI(void) break; case MENU_MINIMIG_ADFFILE_SELECTED: - if (!mgl->done) snprintf(selPath, sizeof(selPath), "%s/%s", HomeDir(), mgl->item[mgl->current].path); + if (!mgl->done) + { + snprintf(selPath, sizeof(selPath), "%s/%s", HomeDir(), mgl->item[mgl->current].path); + // Update /tmp/ files to reflect the actual file being loaded by MGL + if (cfg.log_file_entry) + { + const char *fname = strrchr(selPath, '/'); + MakeFile("/tmp/FULLPATH", selPath); + MakeFile("/tmp/CURRENTPATH", fname ? fname + 1 : selPath); + MakeFile("/tmp/FILESELECT", "selected"); + } + } memcpy(Selected_F[menusub], selPath, sizeof(Selected_F[menusub])); if (mgl->done) recent_update(SelectedDir, selPath, SelectedLabel, 0); InsertFloppy(&df[menusub], selPath); diff --git a/support/arcade/mra_loader.cpp b/support/arcade/mra_loader.cpp index c106f34..f5b430b 100644 --- a/support/arcade/mra_loader.cpp +++ b/support/arcade/mra_loader.cpp @@ -52,6 +52,7 @@ struct arc_struct { static char arcade_error_msg[kBigTextSize] = {}; static char arcade_root[kBigTextSize]; static char mame_root[kBigTextSize]; +static char arcade_setname[kBigTextSize] = {}; static bool is_vertical = false; @@ -1077,7 +1078,12 @@ static int xml_read_pre_parse(XMLEvent evt, const XMLNode* node, SXML_CHAR* text break; case XML_EVENT_TEXT: - if(insetname) user_io_name_override(text, samedir); + if(insetname) + { + user_io_name_override(text, samedir); + // Capture setname for game ID + snprintf(arcade_setname, sizeof(arcade_setname), "%s", text); + } if(inrotation) { is_vertical = strncasecmp(text, "vertical", 8) == 0; @@ -1137,6 +1143,14 @@ int arcade_send_rom(const char *xml) } buffer_destroy(arc_info.data); + // Write game ID using setname as serial + if (arcade_setname[0]) + { + char mra_path[kBigTextSize]; + snprintf(mra_path, sizeof(mra_path), "%s.mra", arcade_setname); + user_io_write_gameid(mra_path, 0, arcade_setname); + } + switches.dip_cur = switches.dip_def; arcade_sw_load(); switches.dip_saved = switches.dip_cur; diff --git a/support/n64/n64.cpp b/support/n64/n64.cpp index a403f6c..92fe236 100644 --- a/support/n64/n64.cpp +++ b/support/n64/n64.cpp @@ -1685,8 +1685,15 @@ int n64_rom_tx(const char* name, unsigned char idx, uint32_t load_addr, uint32_t } printf("Done loading N64 ROM.\n"); + printf("CRC32: %08X\n", file_crc); FileClose(&f); + // Write game ID if cart_id exists (BIOS check is handled in user_io_write_gameid) + if (cart_id[0]) + { + user_io_write_gameid(name, file_crc, cart_id); + } + bool is_patched = false; if (mem) { diff --git a/support/psx/psx.cpp b/support/psx/psx.cpp index e7e33a0..f9f3c9c 100644 --- a/support/psx/psx.cpp +++ b/support/psx/psx.cpp @@ -699,6 +699,12 @@ void psx_mount_cd(int f_index, int s_index, const char *filename) region = game_info.region; printf("Game ID: %s, region: %s\n", game_id, region_string(region)); + // Write game ID if it's not empty (BIOS check is handled in user_io_write_gameid) + if (game_id && game_id[0] != '\0') + { + user_io_write_gameid(filename, 0, game_id); + } + int name_len = strlen(filename); if (toc.tracks[0].type) // is first track a data? diff --git a/user_io.cpp b/user_io.cpp index 1fd30ea..4022116 100644 --- a/user_io.cpp +++ b/user_io.cpp @@ -1325,6 +1325,9 @@ void user_io_init(const char *path, const char *xml) core_name[0] = 0; disable_osd = 0; + // Clean up old game ID when loading a new core + unlink("/tmp/GAMEID"); + // we need to set the directory to where the XML file (MRA) is // not the RBF. The RBF will be in arcade, which the user shouldn't // browse @@ -2422,6 +2425,55 @@ uint32_t user_io_get_file_crc() return file_crc; } +void user_io_write_gameid(const char *filename, uint32_t crc32_val, const char *serial) +{ + if (!cfg.log_file_entry) return; + + // Extract basename from filename + const char *fname = strrchr(filename, '/'); + if (!fname) fname = filename; + else fname++; + + // Skip BIOS files + if (strncasecmp(fname, "boot", 4) == 0 || strcasestr(fname, "bios")) + { + return; + } + + FILE *f = fopen("/tmp/GAMEID", "w"); + if (!f) + { + printf("Failed to write /tmp/GAMEID\n"); + return; + } + + int wrote_something = 0; + printf("Game ID: %s", fname); + + if (crc32_val) + { + fprintf(f, "CRC32: %08X\n", crc32_val); + printf(" [CRC32: %08X]", crc32_val); + wrote_something = 1; + } + if (serial && serial[0]) + { + fprintf(f, "Serial: %s\n", serial); + printf(" [%s]", serial); + wrote_something = 1; + } + + // Ensure we always write something to the file + if (!wrote_something) + { + fprintf(f, "# No game ID available\n"); + } + + printf("\n"); + fflush(f); + fclose(f); +} + int user_io_use_cheats() { return use_cheats; @@ -2729,6 +2781,8 @@ int user_io_file_tx(const char* name, unsigned char index, char opensave, char m printf("Done.\n"); printf("CRC32: %08X\n", file_crc); + user_io_write_gameid(name, file_crc); + FileClose(&f); if (opensave) diff --git a/user_io.h b/user_io.h index d3ee5cd..3a4e457 100644 --- a/user_io.h +++ b/user_io.h @@ -184,6 +184,7 @@ int user_io_status_save(const char *filename); void user_io_status_reset(); uint32_t user_io_get_file_crc(); +void user_io_write_gameid(const char *filename, uint32_t crc32_val = 0, const char *product_code = NULL); int user_io_file_mount(const char *name, unsigned char index = 0, char pre = 0, int pre_size = 0); void user_io_bufferinvalidate(unsigned char index); char *user_io_make_filepath(const char *path, const char *filename);