From 652a8423d350a83c40c2757e76f3cdf2f2d24962 Mon Sep 17 00:00:00 2001 From: Marcoen Hirschberg Date: Mon, 21 Feb 2022 17:31:51 +0100 Subject: [PATCH] psx: add cheats (#551) * PSX: implement game ID * initialize cheats for PSX --- cheats.cpp | 41 ++++++++++++++++++++++++++- menu.cpp | 1 + support/psx/psx.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++ support/psx/psx.h | 1 + 4 files changed, 110 insertions(+), 1 deletion(-) diff --git a/cheats.cpp b/cheats.cpp index 2671e96..d8b0d85 100644 --- a/cheats.cpp +++ b/cheats.cpp @@ -122,6 +122,36 @@ static int find_in_same_dir(const char *name) return 0; } + +bool cheat_init_psx(mz_zip_archive* _z, const char* rom_path) +{ + // lookup based on file name + const char *rom_name = strrchr(rom_path, '/'); + if (rom_name) + { + sprintf(cheat_zip, "%s/cheats/%s%s", getRootDir(), CoreName, rom_name); + char *p = strrchr(cheat_zip, '.'); + if (p) *p = 0; + strcat(cheat_zip, ".zip"); + printf("Trying cheat file: %s\n", cheat_zip); + + memset(_z, 0, sizeof(mz_zip_archive)); + if (mz_zip_reader_init_file(_z, cheat_zip, 0)) return true; + } + + // lookup based on game ID + const char* game_id = psx_get_game_id(); + if (game_id && game_id[0]) + { + sprintf(cheat_zip, "%s/cheats/%s/%s.zip", getRootDir(), CoreName, psx_get_game_id()); + printf("Trying cheat file: %s\n", cheat_zip); + memset(_z, 0, sizeof(mz_zip_archive)); + if (mz_zip_reader_init_file(_z, cheat_zip, 0)) return true; + } + + return false; +} + void cheats_init(const char *rom_path, uint32_t romcrc) { cheats.clear(); @@ -143,7 +173,16 @@ void cheats_init(const char *rom_path, uint32_t romcrc) } mz_zip_archive _z = {}; - if (!mz_zip_reader_init_file(&_z, cheat_zip, 0)) + + if (is_psx() && !mz_zip_reader_init_file(&_z, cheat_zip, 0)) + { + if (!cheat_init_psx(&_z, rom_path)) + { + printf("no cheat file found\n"); + return; + } + } + else if (!mz_zip_reader_init_file(&_z, cheat_zip, 0)) { memset(&_z, 0, sizeof(_z)); if (!(pcecd_using_cd() || is_megacd()) || !find_in_same_dir(rom_path) || !mz_zip_reader_init_file(&_z, cheat_zip, 0)) diff --git a/menu.cpp b/menu.cpp index e3ab1ce..d3a113f 100644 --- a/menu.cpp +++ b/menu.cpp @@ -2257,6 +2257,7 @@ void HandleUI(void) else if (is_psx() && ioctl_index == 1) { psx_mount_cd(user_io_ext_idx(selPath, fs_pFileExt) << 6 | (menusub + 1), ioctl_index, selPath); + cheats_init(selPath, 0); } else { diff --git a/support/psx/psx.cpp b/support/psx/psx.cpp index 95c32b4..edc23e3 100644 --- a/support/psx/psx.cpp +++ b/support/psx/psx.cpp @@ -4,6 +4,9 @@ #include #include +#include +#include + #include "../../file_io.h" #include "../../user_io.h" #include "../../spi.h" @@ -497,6 +500,69 @@ void psx_read_cd(uint8_t *buffer, int lba, int cnt) } } +#define ROOT_FOLDER_LBA 150 + 22 + +std::vector game_id_prefixes +{ + "SCES", + "SLES", + "SCUS", + "SLUS", + "SCPM", + "SLPM", + "SCPS", + "SLPS", +}; + +const char* psx_get_game_id() +{ + uint8_t buffer[CD_SECTOR_LEN]; + + static char game_id[11]; + memset(game_id, 0, sizeof(game_id)); + + for (int sector = ROOT_FOLDER_LBA; sector < ROOT_FOLDER_LBA + 3; ++sector) + { + psx_read_cd(buffer, sector, 1); + //hexdump(buffer, CD_SECTOR_LEN); + char* start = nullptr; + + for (const auto& prefix : game_id_prefixes) + { + start = (char*)memmem(buffer, CD_SECTOR_LEN, prefix.c_str(), prefix.size()); + if (start) break; + } + + if (!start) continue; + + const size_t start_pos = start - (char*)buffer; + char* end = (char*)memmem(start, CD_SECTOR_LEN - start_pos, ";1", 2); + + if (!end) continue; + + size_t size = end - start; + + // file is usually in CCCC_DDD.DD format, normalize to CCCC-DDDDD + if (size == 11) + { + if (start[4] == '_') start[4] = '-'; + if (start[8] == '.') + { + start[8] = start[9]; + start[9] = start[10]; + --size; + } + } + + const size_t max_length = sizeof(game_id) - 1; + if (size > max_length) size = max_length; + + return (char*)memcpy(game_id, start, size); + } + + return game_id; +} + static void mount_cd(int size, int index) { spi_uio_cmd_cont(UIO_SET_SDINFO); @@ -523,6 +589,8 @@ void psx_mount_cd(int f_index, int s_index, const char *filename) { if (load_cd_image(filename, &toc) && toc.last) { + printf("GAME ID: %s\n", psx_get_game_id()); + int name_len = strlen(filename); if (toc.tracks[0].type) // is first track a data? diff --git a/support/psx/psx.h b/support/psx/psx.h index cff25f4..0045127 100644 --- a/support/psx/psx.h +++ b/support/psx/psx.h @@ -4,5 +4,6 @@ void psx_mount_cd(int f_index, int s_index, const char *filename); void psx_fill_blanksave(uint8_t *buffer, uint32_t lba, int cnt); void psx_read_cd(uint8_t *buffer, int lba, int cnt); +const char* psx_get_game_id(); #endif