From f843d68bb65f8a532b365efc5cbdf5be65c5f517 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Mon, 24 Dec 2012 01:15:41 -0500 Subject: Make the GUI accept and save Snes9x's cheat file format. Improve support for saving the values present in ROM/RAM before a cheat is applied. Beautify the cheat selection menu, making it more tabular. --- CATSFC/system/language.msg | 12 ++-- source/cheats2.cpp | 29 ++++---- source/nds/gcheat.c | 6 +- source/nds/gui.c | 171 ++++++++++++--------------------------------- 4 files changed, 71 insertions(+), 147 deletions(-) diff --git a/CATSFC/system/language.msg b/CATSFC/system/language.msg index 549183e..4f003e4 100644 --- a/CATSFC/system/language.msg +++ b/CATSFC/system/language.msg @@ -191,10 +191,10 @@ Enable No game is currently loaded #MSG_CHEAT_MENU_NON_LOAD -Cheat %d (none loaded) + #MSG_CHEAT_MENU_0 -Cheat %d (%s): %%s +-Unused message- #MSG_LOAD_STATE Load saved state @@ -547,10 +547,10 @@ SFC 按键 A %s 没有加载游戏 #MSG_CHEAT_MENU_NON_LOAD -作弊代码 %d (没有加载) +<没有加载> #MSG_CHEAT_MENU_LOADED -作弊代码 %d (%s): %%s +-UNUSED MESSAGE- #MSG_LOAD_STATE 装载即时存档 @@ -910,10 +910,10 @@ Activer Aucun jeu n'est actuellement chargé #MSG_CHEAT_MENU_NON_LOAD -Code de triche %d (aucun chargé) + #MSG_CHEAT_MENU_0 -Code %d (%s): %%s +-Unused message- #MSG_LOAD_STATE Charger diff --git a/source/cheats2.cpp b/source/cheats2.cpp index 8d81d6d..e5a7b0f 100644 --- a/source/cheats2.cpp +++ b/source/cheats2.cpp @@ -171,6 +171,8 @@ void S9xRemoveCheat (uint32 which1) *(ptr + (address & 0xffff)) = Cheat.c [which1].saved_byte; else S9xSetByte (Cheat.c [which1].saved_byte, address); + // Unsave the address for the next call to S9xRemoveCheat. + Cheat.c [which1].saved = FALSE; } } @@ -213,20 +215,24 @@ bool8 S9xLoadCheatFile (const char *filename) Cheat.num_cheats = 0; FILE *fs = fopen (filename, "rb"); - uint8 data [28]; + uint8 data [8 + MAX_SFCCHEAT_NAME]; if (!fs) return (FALSE); - while (fread ((void *) data, 1, 28, fs) == 28) + while (fread ((void *) data, 1, 8 + MAX_SFCCHEAT_NAME, fs) == 8 + MAX_SFCCHEAT_NAME) { + if (data[6] != 254 || data[7] != 252) { + fclose (fs); + return (FALSE); + } Cheat.c [Cheat.num_cheats].enabled = (data [0] & 4) == 0; Cheat.c [Cheat.num_cheats].byte = data [1]; Cheat.c [Cheat.num_cheats].address = data [2] | (data [3] << 8) | (data [4] << 16); Cheat.c [Cheat.num_cheats].saved_byte = data [5]; Cheat.c [Cheat.num_cheats].saved = (data [0] & 8) != 0; - memmove (Cheat.c [Cheat.num_cheats].name, &data [8], 20); - Cheat.c [Cheat.num_cheats++].name [20] = 0; + memcpy (Cheat.c [Cheat.num_cheats].name, &data [8], MAX_SFCCHEAT_NAME - 1); + Cheat.c [Cheat.num_cheats++].name [MAX_SFCCHEAT_NAME - 1] = 0; } fclose (fs); @@ -242,7 +248,7 @@ bool8 S9xSaveCheatFile (const char *filename) } FILE *fs = fopen (filename, "wb"); - uint8 data [28]; + uint8 data [8 + MAX_SFCCHEAT_NAME]; if (!fs) return (FALSE); @@ -250,12 +256,9 @@ bool8 S9xSaveCheatFile (const char *filename) uint32 i; for (i = 0; i < Cheat.num_cheats; i++) { - memset (data, 0, 28); - if (i == 0) - { - data [6] = 254; - data [7] = 252; - } + memset (data, 0, 8 + MAX_SFCCHEAT_NAME); + data [6] = 254; + data [7] = 252; if (!Cheat.c [i].enabled) data [0] |= 4; @@ -268,8 +271,8 @@ bool8 S9xSaveCheatFile (const char *filename) data [4] = (uint8) (Cheat.c [i].address >> 16); data [5] = Cheat.c [i].saved_byte; - memmove (&data [8], Cheat.c [i].name, 19); - if (fwrite (data, 28, 1, fs) != 1) + memcpy (&data [8], Cheat.c [i].name, MAX_SFCCHEAT_NAME - 1); + if (fwrite (data, 8 + MAX_SFCCHEAT_NAME, 1, fs) != 1) { fclose (fs); return (FALSE); diff --git a/source/nds/gcheat.c b/source/nds/gcheat.c index e3d0e8d..d0ada43 100644 --- a/source/nds/gcheat.c +++ b/source/nds/gcheat.c @@ -103,17 +103,17 @@ int NDSSFCLoadCheatFile(const char* filename) ptr++; // Go past the + , or " code[i] = '\0'; if (!S9xGameGenieToRaw (code, &address, &byte)) { - S9xAddCheat (FALSE, TRUE, address, byte); + S9xAddCheat (FALSE, FALSE, address, byte); strncpy (Cheat.c[Cheat.num_cheats - 1].name, description, MAX_SFCCHEAT_NAME); } else if (!S9xProActionReplayToRaw (code, &address, &byte)) { - S9xAddCheat (FALSE, TRUE, address, byte); + S9xAddCheat (FALSE, FALSE, address, byte); strncpy (Cheat.c[Cheat.num_cheats - 1].name, description, MAX_SFCCHEAT_NAME); } else if (!S9xGoldFingerToRaw (code, &address, &sram, &num_bytes, bytes)) { for (c = 0; c < num_bytes; c++) { - S9xAddCheat (FALSE, TRUE, address + c, bytes[c]); + S9xAddCheat (FALSE, FALSE, address + c, bytes[c]); strncpy (Cheat.c[Cheat.num_cheats - 1].name, description, MAX_SFCCHEAT_NAME); } } diff --git a/source/nds/gui.c b/source/nds/gui.c index 1b265b6..a8152c4 100644 --- a/source/nds/gui.c +++ b/source/nds/gui.c @@ -111,7 +111,7 @@ static unsigned int savestate_index; action_function, \ passive_function, \ NULL, \ - &cheat_format_ptr[number], \ + &cheat_data_ptr[number], \ enable_disable_options, \ &(Cheat.c[number].enabled), \ 2, \ @@ -1659,8 +1659,9 @@ u32 menu(u16 *screen) u32 first_load = 0; char tmp_filename[MAX_FILE]; char line_buffer[512]; - char cheat_format_str[MAX_CHEATS_T][41*4]; - char *cheat_format_ptr[MAX_CHEATS_T]; + char cheat_data_str[MAX_CHEATS_T][5]; + // ^ Holds the index inside Cheat, as a number in an ASCIIZ string + char* cheat_data_ptr[MAX_CHEATS_T]; MENU_TYPE *current_menu; MENU_OPTION_TYPE *current_option; @@ -2222,16 +2223,8 @@ u32 menu(u16 *screen) { for(i = 0; i < MAX_CHEATS_T; i++) { - if(i >= Cheat.num_cheats) - { - sprintf(cheat_format_str[i], msg[MSG_CHEAT_MENU_NON_LOAD], i); - } - else - { - sprintf(cheat_format_str[i], msg[MSG_CHEAT_MENU_LOADED], i, Cheat.c[i].name); - } - - cheat_format_ptr[i]= cheat_format_str[i]; + sprintf(cheat_data_str[i], "%d", i); + cheat_data_ptr[i] = &cheat_data_str[i][0]; } reload_cheats_page(); @@ -2239,6 +2232,17 @@ u32 menu(u16 *screen) void cheat_menu_end() { + // Honour current cheat selections. + uint32 i; + for (i = 0; i < Cheat.num_cheats; i++) { + if (Cheat.c[i].enabled) + S9xApplyCheat(i); + else + S9xRemoveCheat(i); + } + // Save current cheat selections to the cheat binary file. + strcpy(line_buffer, (char *) S9xGetFilename (".chb")); + S9xSaveCheatFile (line_buffer); // cheat binary } void dynamic_cheat_key() @@ -2452,102 +2456,13 @@ u32 menu(u16 *screen) void cheat_option_action() { - unsigned int nums; - - nums = (CHEATS_PER_PAGE * menu_cheat_page) + current_option_num -1; - if(gui_action == CURSOR_SELECT && nums < Cheat.num_cheats) - { - unsigned int m; - - // nums = game_config.cheats_flag[(CHEATS_PER_PAGE * menu_cheat_page) + current_option_num -1].item_num; - // REVISIT [Neb] - - if(dynamic_cheat_options) - { - free((void*)dynamic_cheat_options); - dynamic_cheat_options = NULL; - } - - if(dynamic_cheat_menu) - { - free((void*)dynamic_cheat_menu); - dynamic_cheat_menu = NULL; - } - - dynamic_cheat_options = (MENU_OPTION_TYPE*)malloc(sizeof(MENU_OPTION_TYPE)*(nums+1)); - if(dynamic_cheat_options == NULL) return; - - dynamic_cheat_menu = (MENU_TYPE*)malloc(sizeof(MENU_TYPE)); - if(dynamic_cheat_menu == NULL) - { - free((void*)dynamic_cheat_options); - dynamic_cheat_options = NULL; - return; - } - - //menu - dynamic_cheat_menu->init_function = NULL; - dynamic_cheat_menu->passive_function = dynamic_cheat_menu_passive; - dynamic_cheat_menu->key_function = dynamic_cheat_key; - dynamic_cheat_menu->end_function = dynamic_cheat_menu_end; - dynamic_cheat_menu->options = dynamic_cheat_options; - dynamic_cheat_menu->num_options = nums+1; - dynamic_cheat_menu->focus_option = 0; - dynamic_cheat_menu->screen_focus = 0; - //back option - dynamic_cheat_options[0].action_function = NULL; - dynamic_cheat_options[0].passive_function = NULL; - dynamic_cheat_options[0].sub_menu = &cheats_menu; - // dynamic_cheat_options[0].display_string = (char**)(dynamic_cheat_pt + game_config.cheats_flag[(CHEATS_PER_PAGE * menu_cheat_page) + current_option_num -1].name_id); - // REVISIT [Neb] - dynamic_cheat_options[0].options = NULL; - dynamic_cheat_options[0].current_option = NULL; - dynamic_cheat_options[0].num_options = 0; - dynamic_cheat_options[0].help_string = NULL; - dynamic_cheat_options[0].line_number = 0; - dynamic_cheat_options[0].option_type = SUBMENU_TYPE; - - // m = game_config.cheats_flag[(CHEATS_PER_PAGE * menu_cheat_page) + current_option_num -1].item_id; - // REVISIT [Neb] - for(i= 0; i < nums; i++) - { - dynamic_cheat_options[i+1].action_function = dynamic_cheat_action; - dynamic_cheat_options[i+1].passive_function = NULL; - dynamic_cheat_options[i+1].sub_menu = NULL; - // dynamic_cheat_options[i+1].display_string = (char**)(dynamic_cheat_pt + S9xGetCheat_nameid(m, i, g_cheat_cell_num)); - // REVISIT [Neb] - dynamic_cheat_options[i+1].options = NULL; - dynamic_cheat_options[i+1].current_option = NULL; - dynamic_cheat_options[i+1].num_options = 2; - dynamic_cheat_options[i+1].help_string = NULL; - dynamic_cheat_options[i+1].line_number = i+1; - dynamic_cheat_options[i+1].option_type = ACTION_TYPE; - } - - // dynamic_cheat_active = game_config.cheats_flag[(CHEATS_PER_PAGE * menu_cheat_page) + - // current_option_num -1].active & 0x1; - // dynamic_cheat_active |= game_config.cheats_flag[(CHEATS_PER_PAGE * menu_cheat_page) + - // current_option_num -1].sub_active << 16; - // REVISIT [Neb] - - //Initial srollable options - int k; - - draw_hscroll_init(down_screen_addr, 50, 9, 180, COLOR_TRANS, - COLOR_ACTIVE_ITEM, *dynamic_cheat_options[0].display_string); - - if(nums>5) nums = SUBMENU_ROW_NUM; - for(k= 0; k < nums; k++) - { - draw_hscroll_init(down_screen_addr, 23, 40 + k*27, 200, - COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[k+1].display_string); - } - dynamic_cheat_scroll_value= 0; - - choose_menu(dynamic_cheat_menu); - } } +#define CHEAT_NUMBER_X 26 +#define CHEAT_DESC_X 52 +#define CHEAT_DESC_SX 163 +#define CHEAT_ACTIVE_X 225 + void cheat_option_passive() { unsigned short color; @@ -2562,27 +2477,33 @@ u32 menu(u16 *screen) //sprintf("%A") will have problem ? strcpy(tmp_buf, *(display_option->display_string)); - pt = strrchr(tmp_buf, ':'); - if(pt != NULL) - sprintf(pt+1, "%s", *((u32*)(((u32 *)display_option->options)[*(display_option->current_option)]))); + // This is the number of the cheat to display - strcpy(line_buffer, tmp_buf); - pt = strrchr(line_buffer, ')'); - *pt = '\0'; - pt = strchr(line_buffer, '('); + int i = atoi(tmp_buf); - len = BDF_cut_string(pt+1, 0, 2); - if(len > 90) - { - len = BDF_cut_string(pt+1, 90, 1); - *(pt+1+len) = '\0'; - strcat(line_buffer, "..."); - } + sprintf(line_buffer, "%d.", i + 1); + PRINT_STRING_BG(down_screen_addr, line_buffer, color, COLOR_TRANS, CHEAT_NUMBER_X, 40 + display_option-> line_number*27); - pt = strrchr(tmp_buf, ')'); - strcat(line_buffer, pt); + if (i >= Cheat.num_cheats) { + PRINT_STRING_BG(down_screen_addr, msg[MSG_CHEAT_MENU_NON_LOAD], color, COLOR_TRANS, CHEAT_DESC_X, 40 + display_option-> line_number*27); + } + else { + strcpy(line_buffer, Cheat.c[i].name); + len = BDF_cut_string(line_buffer, 0, 2); + if(len > CHEAT_DESC_SX) + { + len = BDF_cut_string(line_buffer, CHEAT_DESC_SX, 1); + line_buffer[len] = '\0'; + strcat(line_buffer, "..."); + } + PRINT_STRING_BG(down_screen_addr, line_buffer, color, COLOR_TRANS, CHEAT_DESC_X, 40 + display_option-> line_number*27); - PRINT_STRING_BG(down_screen_addr, line_buffer, color, COLOR_TRANS, 26, 40 + display_option-> line_number*27); + if (Cheat.c[i].enabled) + strcpy(line_buffer, "+"); + else + strcpy(line_buffer, "-"); + PRINT_STRING_BG(down_screen_addr, line_buffer, color, COLOR_TRANS, CHEAT_ACTIVE_X, 40 + display_option-> line_number*27); + } } void dynamic_cheat_menu_end() @@ -3578,7 +3499,7 @@ u32 menu(u16 *screen) { for(i = 0; i < CHEATS_PER_PAGE; i++) { - cheats_options[i+1].display_string = &cheat_format_ptr[(CHEATS_PER_PAGE * menu_cheat_page) + i]; + cheats_options[i+1].display_string = &cheat_data_ptr[(CHEATS_PER_PAGE * menu_cheat_page) + i]; cheats_options[i+1].current_option = &(Cheat.c[(CHEATS_PER_PAGE * menu_cheat_page) + i].enabled); } } -- cgit v1.2.3