Arcade cheat support (#969)
Remove dip switch based cheat support which was unused by any core. MRA files can now specify cheat data directly
This commit is contained in:
138
cheats.cpp
138
cheats.cpp
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "hardware.h"
|
||||
#include "file_io.h"
|
||||
#include "str_util.h"
|
||||
#include "user_io.h"
|
||||
#include "fpga_io.h"
|
||||
#include "miniz.h"
|
||||
@@ -32,6 +33,22 @@ struct cheat_rec_t
|
||||
memset(name, 0, sizeof(name));
|
||||
}
|
||||
|
||||
cheat_rec_t(const cheat_rec_t& other)
|
||||
{
|
||||
memcpy(this->name, other.name, sizeof(other.name));
|
||||
this->enabled = other.enabled;
|
||||
this->cheatSize = other.cheatSize;
|
||||
if (other.cheatData)
|
||||
{
|
||||
this->cheatData = new char [this->cheatSize];
|
||||
memcpy(this->cheatData, other.cheatData, this->cheatSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->cheatData = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~cheat_rec_t()
|
||||
{
|
||||
if (this->cheatData)
|
||||
@@ -44,9 +61,13 @@ struct cheat_rec_t
|
||||
typedef std::vector<cheat_rec_t> CheatVector;
|
||||
static CheatVector cheats;
|
||||
|
||||
#define CHEAT_SIZE (128*16) // 128 codes max
|
||||
|
||||
static int iSelectedEntry = 0;
|
||||
static int iFirstEntry = 0;
|
||||
static int loaded = 0;
|
||||
static int cheat_unit_size = 16;
|
||||
static int cheat_max_active = 128;
|
||||
|
||||
struct CheatComp
|
||||
{
|
||||
@@ -170,10 +191,50 @@ bool cheat_init_psx(mz_zip_archive* _z, const char *rom_path)
|
||||
return false;
|
||||
}
|
||||
|
||||
void cheats_init_arcade(int unit_size, int max_active)
|
||||
{
|
||||
cheats.clear();
|
||||
loaded = 0;
|
||||
cheat_unit_size = unit_size > 0 ? unit_size : 16;
|
||||
cheat_max_active = max_active > 0 ? max_active : 128;
|
||||
if ((cheat_max_active * cheat_unit_size) > CHEAT_SIZE)
|
||||
{
|
||||
cheat_max_active = CHEAT_SIZE / cheat_unit_size;
|
||||
}
|
||||
|
||||
cheat_zip[0] = 0;
|
||||
}
|
||||
|
||||
void cheats_add_arcade(const char *name, const char *cheatData, int cheatSize)
|
||||
{
|
||||
cheat_rec_t cheat = {};
|
||||
|
||||
if ((cheatSize % cheat_unit_size) != 0)
|
||||
{
|
||||
printf("Arcade cheat \'%s\' has incorrect length %d -> skipping.\n", name, cheatSize);
|
||||
return;
|
||||
}
|
||||
|
||||
strcpyz(cheat.name, name);
|
||||
cheat.cheatSize = cheatSize;
|
||||
cheat.cheatData = new char [cheatSize];
|
||||
memcpy(cheat.cheatData, cheatData, cheatSize);
|
||||
cheats.push_back(cheat);
|
||||
}
|
||||
|
||||
void cheats_finalize_arcade()
|
||||
{
|
||||
printf("MRA cheats: %d\n", cheats_available());
|
||||
cheats_scan(SCANF_INIT);
|
||||
}
|
||||
|
||||
|
||||
void cheats_init(const char *rom_path, uint32_t romcrc)
|
||||
{
|
||||
cheats.clear();
|
||||
loaded = 0;
|
||||
cheat_unit_size = 16;
|
||||
cheat_max_active = 128;
|
||||
cheat_zip[0] = 0;
|
||||
|
||||
// reset cheats
|
||||
@@ -412,7 +473,6 @@ void cheats_print()
|
||||
}
|
||||
}
|
||||
|
||||
#define CHEAT_SIZE (128*16) // 128 codes max
|
||||
|
||||
static void cheats_send()
|
||||
{
|
||||
@@ -437,7 +497,7 @@ static void cheats_send()
|
||||
}
|
||||
}
|
||||
|
||||
loaded = pos / 16;
|
||||
loaded = pos / cheat_unit_size;
|
||||
printf("Cheat codes: %d\n", loaded);
|
||||
|
||||
if (is_n64())
|
||||
@@ -459,15 +519,7 @@ void cheats_toggle()
|
||||
|
||||
if (cheats[iSelectedEntry].enabled == true)
|
||||
{
|
||||
/* disabled loaded cheat, free data */
|
||||
if (cheats[iSelectedEntry].cheatData)
|
||||
{
|
||||
delete[] cheats[iSelectedEntry].cheatData;
|
||||
cheats[iSelectedEntry].cheatData = NULL;
|
||||
}
|
||||
|
||||
cheats[iSelectedEntry].enabled = false;
|
||||
cheats[iSelectedEntry].cheatSize = 0;
|
||||
changedCheats = true;
|
||||
}
|
||||
else
|
||||
@@ -476,55 +528,57 @@ void cheats_toggle()
|
||||
static char filename[1024];
|
||||
fileTYPE f = {};
|
||||
|
||||
if (cheats[iSelectedEntry].cheatData)
|
||||
/* lazy load cheat data */
|
||||
if (cheats[iSelectedEntry].cheatData == NULL)
|
||||
{
|
||||
printf("Consistency error, memory for cheat already allocated -> cleanup.\n");
|
||||
delete[] cheats[iSelectedEntry].cheatData;
|
||||
cheats[iSelectedEntry].cheatData = NULL;
|
||||
cheats[iSelectedEntry].cheatSize = 0;
|
||||
}
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%s", cheat_zip, cheats[iSelectedEntry].name);
|
||||
if (FileOpen(&f, filename))
|
||||
{
|
||||
int len = f.size;
|
||||
if (!len || (len & 15))
|
||||
snprintf(filename, sizeof(filename), "%s/%s", cheat_zip, cheats[iSelectedEntry].name);
|
||||
if (FileOpen(&f, filename))
|
||||
{
|
||||
printf("Cheat file %s has incorrect length %d -> skipping.\n", filename, len);
|
||||
}
|
||||
else if ((len + cheats_loaded() * 16) <= CHEAT_SIZE)
|
||||
{
|
||||
cheats[iSelectedEntry].cheatData = new char[len];
|
||||
if (cheats[iSelectedEntry].cheatData)
|
||||
int len = f.size;
|
||||
if (!len || (len % cheat_unit_size))
|
||||
{
|
||||
if (FileReadAdv(&f, cheats[iSelectedEntry].cheatData, len) == len)
|
||||
printf("Cheat file %s has incorrect length %d -> skipping.\n", filename, len);
|
||||
}
|
||||
else if (((len / cheat_unit_size) + cheats_loaded()) <= cheat_max_active)
|
||||
{
|
||||
cheats[iSelectedEntry].cheatData = new char[len];
|
||||
if (cheats[iSelectedEntry].cheatData)
|
||||
{
|
||||
cheats[iSelectedEntry].cheatSize = len;
|
||||
cheats[iSelectedEntry].enabled = true;
|
||||
changedCheats = true;
|
||||
if (FileReadAdv(&f, cheats[iSelectedEntry].cheatData, len) == len)
|
||||
{
|
||||
cheats[iSelectedEntry].cheatSize = len;
|
||||
cheats[iSelectedEntry].enabled = true;
|
||||
changedCheats = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Cannot read cheat file %s.\n", filename);
|
||||
delete[] cheats[iSelectedEntry].cheatData;
|
||||
cheats[iSelectedEntry].cheatData = NULL;
|
||||
cheats[iSelectedEntry].cheatSize = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Cannot read cheat file %s.\n", filename);
|
||||
delete[] cheats[iSelectedEntry].cheatData;
|
||||
cheats[iSelectedEntry].cheatData = NULL;
|
||||
cheats[iSelectedEntry].cheatSize = 0;
|
||||
printf("Could not allocate required memory (%d) for cheat file %s.\n", len, filename);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Could not allocate required memory (%d) for cheat file %s.\n", len, filename);
|
||||
printf("No more room in current selection for cheat file %s.\n", filename);
|
||||
}
|
||||
FileClose(&f);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("No more room in current selection for cheat file %s.\n", filename);
|
||||
printf("Cannot open cheat file %s.\n", filename);
|
||||
}
|
||||
FileClose(&f);
|
||||
}
|
||||
else
|
||||
|
||||
if (cheats[iSelectedEntry].cheatData)
|
||||
{
|
||||
printf("Cannot open cheat file %s.\n", filename);
|
||||
cheats[iSelectedEntry].enabled = true;
|
||||
changedCheats = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,4 +591,4 @@ void cheats_toggle()
|
||||
int cheats_loaded()
|
||||
{
|
||||
return loaded;
|
||||
}
|
||||
}
|
||||
|
||||
4
cheats.h
4
cheats.h
@@ -9,4 +9,8 @@ void cheats_print();
|
||||
void cheats_toggle();
|
||||
int cheats_loaded();
|
||||
|
||||
void cheats_init_arcade(int unit_size, int max_active);
|
||||
void cheats_add_arcade(const char *name, const char *cheatData, int cheatSize);
|
||||
void cheats_finalize_arcade();
|
||||
|
||||
#endif
|
||||
|
||||
69
menu.cpp
69
menu.cpp
@@ -975,7 +975,7 @@ void HandleUI(void)
|
||||
static int has_fb_terminal = 0;
|
||||
static unsigned long flash_timer = 0;
|
||||
static int flash_state = 0;
|
||||
static uint32_t dip_submenu, dip2_submenu, dipv;
|
||||
static uint32_t dip_submenu;
|
||||
static int need_reset = 0;
|
||||
static int flat = 0;
|
||||
static int menusub_parent = 0;
|
||||
@@ -1702,7 +1702,6 @@ void HandleUI(void)
|
||||
OsdSetTitle(page ? title : user_io_get_core_name());
|
||||
|
||||
dip_submenu = -1;
|
||||
dip2_submenu = -1;
|
||||
|
||||
int last_space = 0;
|
||||
|
||||
@@ -1725,7 +1724,7 @@ void HandleUI(void)
|
||||
else if (!strcmp(p, "DIP"))
|
||||
{
|
||||
h = page;
|
||||
if (!h && arcade_sw(0)->dip_num)
|
||||
if (!h && arcade_sw()->dip_num)
|
||||
{
|
||||
dip_submenu = selentry;
|
||||
MenuWrite(entry, " DIP Switches \x16", menusub == selentry, 0);
|
||||
@@ -1735,19 +1734,6 @@ void HandleUI(void)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "CHEAT"))
|
||||
{
|
||||
h = page;
|
||||
if (!h && arcade_sw(1)->dip_num)
|
||||
{
|
||||
dip2_submenu = selentry;
|
||||
MenuWrite(entry, " Cheats \x16", menusub == selentry, 0);
|
||||
entry++;
|
||||
selentry++;
|
||||
menumask = (menumask << 1) | 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Hide or Disable flag (small letter - opposite action)
|
||||
@@ -2094,9 +2080,8 @@ void HandleUI(void)
|
||||
select = 1;
|
||||
}
|
||||
|
||||
if ((dip_submenu == menusub || dip2_submenu == menusub) && select)
|
||||
if (dip_submenu == menusub && select)
|
||||
{
|
||||
dipv = (dip_submenu == menusub) ? 0 : 1;
|
||||
menustate = MENU_ARCADE_DIP1;
|
||||
menusub = 0;
|
||||
}
|
||||
@@ -2119,8 +2104,7 @@ void HandleUI(void)
|
||||
d = 0;
|
||||
inpage = !page;
|
||||
|
||||
if (!strcmp(p, "DIP")) h = page || !arcade_sw(0)->dip_num;
|
||||
else if (!strcmp(p, "CHEAT")) h = page || !arcade_sw(1)->dip_num;
|
||||
if (!strcmp(p, "DIP")) h = page || !arcade_sw()->dip_num;
|
||||
else if (strncmp(p, "DEFMRA,", 7))
|
||||
{
|
||||
//Hide or Disable flag
|
||||
@@ -3115,7 +3099,7 @@ void HandleUI(void)
|
||||
case MENU_ARCADE_DIP1:
|
||||
helptext_idx = 0;
|
||||
menumask = 0;
|
||||
OsdSetTitle(dipv ? "Cheats" : "DIP Switches");
|
||||
OsdSetTitle("DIP Switches");
|
||||
menustate = MENU_ARCADE_DIP2;
|
||||
parentstate = MENU_ARCADE_DIP1;
|
||||
|
||||
@@ -3128,7 +3112,7 @@ void HandleUI(void)
|
||||
uint32_t selentry = 0;
|
||||
menumask = 0;
|
||||
|
||||
sw_struct *sw = arcade_sw(dipv);
|
||||
sw_struct *sw = arcade_sw();
|
||||
|
||||
int n = (sw->dip_num < OsdGetSize() - 1) ? (OsdGetSize() - 1 - sw->dip_num) / 2 : 0;
|
||||
for (; entry < n; entry++) MenuWrite(entry);
|
||||
@@ -3169,7 +3153,7 @@ void HandleUI(void)
|
||||
|
||||
for (; entry < OsdGetSize() - 1; entry++) MenuWrite(entry, "", 0, 0);
|
||||
|
||||
MenuWrite(entry, dipv ? STD_BACK : " Reset to apply", menusub == selentry);
|
||||
MenuWrite(entry, " Reset to apply", menusub == selentry);
|
||||
menusub_last = selentry;
|
||||
menumask = (menumask << 1) | 1;
|
||||
|
||||
@@ -3182,30 +3166,22 @@ void HandleUI(void)
|
||||
if (menu || left)
|
||||
{
|
||||
menustate = MENU_GENERIC_MAIN1;
|
||||
menusub = dipv ? dip2_submenu : dip_submenu;
|
||||
arcade_sw_save(0);
|
||||
menusub = dip_submenu;
|
||||
arcade_sw_save();
|
||||
}
|
||||
|
||||
if (select)
|
||||
{
|
||||
if (menusub == menusub_last)
|
||||
{
|
||||
if (!dipv)
|
||||
{
|
||||
arcade_sw_save(dipv);
|
||||
user_io_status_set("[0]", 1);
|
||||
user_io_status_set("[0]", 0);
|
||||
menustate = MENU_NONE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
menusub = dip2_submenu;
|
||||
menustate = MENU_GENERIC_MAIN1;
|
||||
}
|
||||
arcade_sw_save();
|
||||
user_io_status_set("[0]", 1);
|
||||
user_io_status_set("[0]", 0);
|
||||
menustate = MENU_NONE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sw_struct *sw = arcade_sw(dipv);
|
||||
sw_struct *sw = arcade_sw();
|
||||
uint64_t status = sw->dip_cur & sw->dip[menusub].mask;
|
||||
int m = 0;
|
||||
for (int n = 0; n < sw->dip[menusub].num; n++)
|
||||
@@ -3220,7 +3196,7 @@ void HandleUI(void)
|
||||
m = (m + 1) % sw->dip[menusub].num;
|
||||
sw->dip_cur = (sw->dip_cur & ~sw->dip[menusub].mask) | sw->dip[menusub].val[m];
|
||||
menustate = MENU_ARCADE_DIP1;
|
||||
arcade_sw_send(dipv);
|
||||
arcade_sw_send();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -5415,16 +5391,13 @@ void HandleUI(void)
|
||||
printf("Saving config to %s\n", filename);
|
||||
user_io_status_save(filename);
|
||||
menustate = MENU_GENERIC_MAIN1;
|
||||
for (int n = 0; n < 2; n++)
|
||||
if (arcade_sw()->dip_num)
|
||||
{
|
||||
if (arcade_sw(n)->dip_num)
|
||||
{
|
||||
arcade_sw(n)->dip_cur = arcade_sw(n)->dip_def;
|
||||
arcade_sw_send(n);
|
||||
user_io_status_set("[0]", 1);
|
||||
user_io_status_set("[0]", 0);
|
||||
arcade_sw_save(n);
|
||||
}
|
||||
arcade_sw()->dip_cur = arcade_sw()->dip_def;
|
||||
arcade_sw_send();
|
||||
user_io_status_set("[0]", 1);
|
||||
user_io_status_set("[0]", 0);
|
||||
arcade_sw_save();
|
||||
}
|
||||
menustate = MENU_NONE1;
|
||||
menusub = 0;
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "../../fpga_io.h"
|
||||
#include "../../lib/md5/md5.h"
|
||||
#include "../../shmem.h"
|
||||
#include "../../str_util.h"
|
||||
#include "../../cheats.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "mra_loader.h"
|
||||
@@ -25,6 +27,7 @@ struct arc_struct {
|
||||
char partname[kBigTextSize];
|
||||
char romname[kBigTextSize];
|
||||
char error_msg[kBigTextSize];
|
||||
char cheatname[kBigTextSize];
|
||||
int romindex;
|
||||
int offset;
|
||||
int length;
|
||||
@@ -35,6 +38,7 @@ struct arc_struct {
|
||||
int validrom0;
|
||||
int insidesw;
|
||||
int insideinterleave;
|
||||
int insidecheats;
|
||||
int ifrom;
|
||||
int ito;
|
||||
int imap;
|
||||
@@ -51,7 +55,7 @@ static char mame_root[kBigTextSize];
|
||||
|
||||
static bool is_vertical = false;
|
||||
|
||||
static sw_struct switches[2] = {};
|
||||
static sw_struct switches = {};
|
||||
|
||||
static int nvram_idx = 0;
|
||||
static int nvram_size = 0;
|
||||
@@ -76,7 +80,7 @@ void arcade_nvm_save()
|
||||
user_io_set_upload(0);
|
||||
|
||||
FileSave(path, buf, nvram_size);
|
||||
delete(buf);
|
||||
delete [] buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,37 +105,35 @@ static void arcade_nvm_load()
|
||||
user_io_set_download(0);
|
||||
}
|
||||
|
||||
delete(buf);
|
||||
delete [] buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sw_struct *arcade_sw(int n)
|
||||
sw_struct *arcade_sw()
|
||||
{
|
||||
if (n > 1) n = 1;
|
||||
if (n < 0) n = 0;
|
||||
return &switches[n];
|
||||
return &switches;
|
||||
}
|
||||
|
||||
void arcade_sw_send(int n)
|
||||
void arcade_sw_send()
|
||||
{
|
||||
sw_struct *sw = arcade_sw(n);
|
||||
sw_struct *sw = arcade_sw();
|
||||
if (sw->dip_num)
|
||||
{
|
||||
user_io_set_index(254 + n);
|
||||
user_io_set_index(254);
|
||||
user_io_set_download(1);
|
||||
user_io_file_tx_data((uint8_t*)&sw->dip_cur, sizeof(sw->dip_cur));
|
||||
user_io_set_download(0);
|
||||
}
|
||||
}
|
||||
|
||||
void arcade_sw_save(int n)
|
||||
void arcade_sw_save()
|
||||
{
|
||||
sw_struct *sw = arcade_sw(n);
|
||||
sw_struct *sw = arcade_sw();
|
||||
if (sw->dip_num && sw->dip_saved != sw->dip_cur)
|
||||
{
|
||||
static char path[1024];
|
||||
strcpy(path, (n) ? CONFIG_DIR"/cheats/" : CONFIG_DIR"/dips/");
|
||||
strcpy(path, CONFIG_DIR"/dips/");
|
||||
FileCreatePath(path);
|
||||
strcat(path, sw->name);
|
||||
if (FileSave(path, &sw->dip_cur, sizeof(sw->dip_cur)))
|
||||
@@ -141,11 +143,11 @@ void arcade_sw_save(int n)
|
||||
}
|
||||
}
|
||||
|
||||
void arcade_sw_load(int n)
|
||||
void arcade_sw_load()
|
||||
{
|
||||
sw_struct *sw = arcade_sw(n);
|
||||
sw_struct *sw = arcade_sw();
|
||||
static char path[1024];
|
||||
strcpy(path, (n) ? "cheats/" : "dips/");
|
||||
strcpy(path, "dips/");
|
||||
strcat(path, sw->name);
|
||||
FileLoadConfig(path, &sw->dip_cur, sizeof(sw->dip_cur));
|
||||
}
|
||||
@@ -207,7 +209,7 @@ static int rom_checksz(int idx, int chunk)
|
||||
{
|
||||
if ((romlen[idx] + chunk) > romblkl)
|
||||
{
|
||||
if (romlen[idx] + chunk > romblkl + BLKL)
|
||||
if (romlen[idx] + chunk > romblkl + BLKL)
|
||||
romblkl += (chunk + BLKL);
|
||||
else
|
||||
romblkl += BLKL;
|
||||
@@ -432,12 +434,16 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
static char message[32];
|
||||
struct arc_struct *arc_info = (struct arc_struct *)sd->user;
|
||||
|
||||
int cheat_size = 0;
|
||||
int cheat_max = 0;
|
||||
|
||||
switch (evt)
|
||||
{
|
||||
case XML_EVENT_START_DOC:
|
||||
message[0] = 0;
|
||||
arc_info->insiderom = 0;
|
||||
arc_info->insidesw = 0;
|
||||
arc_info->insidecheats = 0;
|
||||
break;
|
||||
|
||||
case XML_EVENT_START_NODE:
|
||||
@@ -447,6 +453,7 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
buffer_destroy(arc_info->data);
|
||||
arc_info->data = buffer_init(kBigTextSize);
|
||||
arc_info->partname[0] = 0;
|
||||
arc_info->cheatname[0] = 0;
|
||||
arc_info->offset = 0;
|
||||
arc_info->length = -1;
|
||||
arc_info->repeat = 1;
|
||||
@@ -472,20 +479,12 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
if (!strcasecmp(node->tag, "switches"))
|
||||
{
|
||||
arc_info->insidesw = 1;
|
||||
switches[0].dip_cur = 0;
|
||||
switches[0].dip_def = 0;
|
||||
switches[0].dip_num = 0;
|
||||
memset(&switches[0].dip, 0, sizeof(switches[0].dip));
|
||||
switches.dip_cur = 0;
|
||||
switches.dip_def = 0;
|
||||
switches.dip_num = 0;
|
||||
memset(&switches.dip, 0, sizeof(switches.dip));
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->tag, "cheats"))
|
||||
{
|
||||
arc_info->insidesw = 2;
|
||||
switches[1].dip_cur = 0;
|
||||
switches[1].dip_def = 0;
|
||||
switches[1].dip_num = 0;
|
||||
memset(&switches[1].dip, 0, sizeof(switches[1].dip));
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->tag, "interleave"))
|
||||
{
|
||||
@@ -602,8 +601,8 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
}
|
||||
else if (arc_info->insidesw)
|
||||
{
|
||||
sw_struct* sw = &switches[arc_info->insidesw - 1];
|
||||
if (!strcasecmp(node->tag, "switches") || !strcasecmp(node->tag, "cheats"))
|
||||
sw_struct* sw = &switches;
|
||||
if (!strcasecmp(node->tag, "switches"))
|
||||
{
|
||||
if (!strcasecmp(node->attributes[i].name, "default"))
|
||||
{
|
||||
@@ -682,6 +681,16 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (arc_info->insidecheats)
|
||||
{
|
||||
if (!strcasecmp(node->tag, "cheat"))
|
||||
{
|
||||
if (!strcasecmp(node->attributes[i].name, "name"))
|
||||
{
|
||||
strcpyz(arc_info->cheatname, node->attributes[i].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strcasecmp(node->attributes[i].name, "index") && !strcasecmp(node->tag, "nvram"))
|
||||
@@ -693,6 +702,18 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
{
|
||||
nvram_size = strtoul(node->attributes[i].value, NULL, 0);
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->tag, "cheats"))
|
||||
{
|
||||
if (!strcasecmp(node->attributes[i].name, "size"))
|
||||
{
|
||||
cheat_size = strtoul(node->attributes[i].value, NULL, 0);
|
||||
}
|
||||
if (!strcasecmp(node->attributes[i].name, "max"))
|
||||
{
|
||||
cheat_max = strtoul(node->attributes[i].value, NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -710,6 +731,12 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
rom_start(arc_info->romindex);
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->tag, "cheats"))
|
||||
{
|
||||
arc_info->insidecheats = 1;
|
||||
cheats_init_arcade(cheat_size, cheat_max);
|
||||
}
|
||||
|
||||
if (arc_info->insiderom && !strcasecmp(node->tag, "interleave"))
|
||||
{
|
||||
int valid = 1;
|
||||
@@ -718,7 +745,7 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
if (arc_info->ito < arc_info->ifrom) valid = 0;
|
||||
|
||||
unitlen = arc_info->ifrom ? arc_info->ito / arc_info->ifrom : 1;
|
||||
if (unitlen < 0 && unitlen>8) valid = 0;
|
||||
if (unitlen < 0 || unitlen>8) valid = 0;
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
@@ -913,7 +940,7 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
|
||||
if (arc_info->insidesw && !strcasecmp(node->tag, "dip"))
|
||||
{
|
||||
sw_struct* sw = &switches[arc_info->insidesw - 1];
|
||||
sw_struct* sw = &switches;
|
||||
|
||||
int n = sw->dip_num;
|
||||
for (int i = 0; i < sw->dip[n].num; i++)
|
||||
@@ -931,6 +958,20 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
arc_info->insidesw = 0;
|
||||
}
|
||||
|
||||
if (arc_info->insidecheats && !strcasecmp(node->tag, "cheat"))
|
||||
{
|
||||
size_t len = 0;
|
||||
unsigned char* binary = hexstr_to_char(arc_info->data->content, &len);
|
||||
cheats_add_arcade(arc_info->cheatname, (char *)binary, len);
|
||||
free(binary);
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->tag, "cheats"))
|
||||
{
|
||||
cheats_finalize_arcade();
|
||||
arc_info->insidecheats = 0;
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->tag, "interleave"))
|
||||
{
|
||||
arc_info->ifrom = 0;
|
||||
@@ -1056,10 +1097,9 @@ int arcade_send_rom(const char *xml)
|
||||
{
|
||||
const char *p = strrchr(xml, '/');
|
||||
p = p ? p + 1 : xml;
|
||||
snprintf(switches[0].name, sizeof(switches[0].name), "%s", p);
|
||||
char *ext = strcasestr(switches[0].name, ".mra");
|
||||
snprintf(switches.name, sizeof(switches.name), "%s", p);
|
||||
char *ext = strcasestr(switches.name, ".mra");
|
||||
if (ext) strcpy(ext, ".dip");
|
||||
memcpy(switches[1].name, switches[0].name, sizeof(switches[1].name));
|
||||
|
||||
snprintf(nvram_name, sizeof(nvram_name), p);
|
||||
ext = strcasestr(nvram_name, ".mra");
|
||||
@@ -1090,13 +1130,10 @@ int arcade_send_rom(const char *xml)
|
||||
}
|
||||
buffer_destroy(arc_info.data);
|
||||
|
||||
for (int n = 0; n < 2; n++)
|
||||
{
|
||||
switches[n].dip_cur = switches[n].dip_def;
|
||||
arcade_sw_load(n);
|
||||
switches[n].dip_saved = switches[n].dip_cur;
|
||||
arcade_sw_send(n);
|
||||
}
|
||||
switches.dip_cur = switches.dip_def;
|
||||
arcade_sw_load();
|
||||
switches.dip_saved = switches.dip_cur;
|
||||
arcade_sw_send();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,10 +55,10 @@ struct mgl_struct
|
||||
int done;
|
||||
};
|
||||
|
||||
sw_struct *arcade_sw(int n);
|
||||
void arcade_sw_send(int n);
|
||||
void arcade_sw_save(int n);
|
||||
void arcade_sw_load(int n);
|
||||
sw_struct *arcade_sw();
|
||||
void arcade_sw_send();
|
||||
void arcade_sw_save();
|
||||
void arcade_sw_load();
|
||||
|
||||
// Read any mra info necessary for ini processing
|
||||
void arcade_pre_parse(const char *xml);
|
||||
|
||||
Reference in New Issue
Block a user