diff --git a/bootcore.cpp b/bootcore.cpp index 39d54fa..5e72896 100644 --- a/bootcore.cpp +++ b/bootcore.cpp @@ -11,7 +11,7 @@ #include -extern int arcade_load(const char *xml); +extern int xml_load(const char *xml); int16_t btimeout; char bootcoretype[64]; @@ -206,7 +206,7 @@ void bootcore_init(const char *path) { if (!cfg.bootcore_timeout) { - isMraName(bootcore) ? arcade_load(bootcore) : fpga_load_rbf(bootcore); + isXmlName(bootcore) ? xml_load(bootcore) : fpga_load_rbf(bootcore); } strcpy(cfg.bootcore, strcmp(bootcore, "menu.rbf") ? bootcore : ""); @@ -219,7 +219,7 @@ void bootcore_init(const char *path) { strcpy(auxstr, path); - auxpointer = (!strcmp(cfg.bootcore, "lastexactcore") || isMraName(auxstr)) ? getcoreExactName(auxstr) : getcoreName(auxstr); + auxpointer = (!strcmp(cfg.bootcore, "lastexactcore") || isXmlName(auxstr)) ? getcoreExactName(auxstr) : getcoreName(auxstr); if (auxpointer != NULL) { diff --git a/file_io.cpp b/file_io.cpp index 16bfec0..464b4e1 100644 --- a/file_io.cpp +++ b/file_io.cpp @@ -1890,10 +1890,15 @@ char* flist_GetPrevNext(const char* base_path, const char* file, const char* ext return path + strlen(base_path) + 1; } -bool isMraName(char *path) +int isXmlName(const char *path) { - char *spl = strrchr(path, '.'); - return (spl && !strcmp(spl, ".mra")); + int len = strlen(path); + if (len > 4) + { + if (!strcasecmp(path + len - 4, ".mra")) return 1; + if (!strcasecmp(path + len - 4, ".mgl")) return 2; + } + return 0; } fileTextReader::fileTextReader() diff --git a/file_io.h b/file_io.h index d58c6af..9952c34 100644 --- a/file_io.h +++ b/file_io.h @@ -131,7 +131,7 @@ const char *getRootDir(); const char *getFullPath(const char *name); uint32_t getFileType(const char *name); -bool isMraName(char *path); +int isXmlName(const char *path); // 1 - MRA, 2 - MGL bool FileOpenTextReader(fileTextReader *reader, const char *path); const char* FileReadLine(fileTextReader *reader); diff --git a/input.cpp b/input.cpp index e79c46d..c23288d 100644 --- a/input.cpp +++ b/input.cpp @@ -4708,8 +4708,7 @@ int input_test(int getchar) if (!strncmp(cmd, "fb_cmd", 6)) video_cmd(cmd); else if (!strncmp(cmd, "load_core ", 10)) { - len = strlen(cmd); - if (len > 4 && !strcasecmp(cmd + len - 4, ".mra")) arcade_load(cmd + 10); + if(isXmlName(cmd)) xml_load(cmd + 10); else fpga_load_rbf(cmd + 10); } else if (!strncmp(cmd, "screenshot", 10)) diff --git a/menu.cpp b/menu.cpp index d3a113f..e148d31 100644 --- a/menu.cpp +++ b/menu.cpp @@ -376,7 +376,7 @@ void SelectFile(const char* path, const char* pFileExt, int Options, unsigned ch if(strlen(selPath)) strcat(selPath, "/"); strcat(selPath, get_rbf_name()); } - pFileExt = "RBFMRA"; + pFileExt = "RBFMRAMGL"; home_dir = NULL; } else if (Options & SCANO_TXT) @@ -713,7 +713,7 @@ static void printSysInfo() if (hasbat) { infowrite(n++, ""); - + sprintf(str, "\x1F "); if (bat.capacity == -1) strcat(str, "n/a"); else sprintf(str + strlen(str), "%d%%", bat.capacity); @@ -789,7 +789,7 @@ const char* get_rbf_name_bootcore(char *str) if (!p) return str; char *spl = strrchr(p + 1, '.'); - if (spl && (!strcmp(spl, ".rbf") || !strcmp(spl, ".mra"))) + if (spl && (!strcmp(spl, ".rbf") || !strcmp(spl, ".mra") || !strcmp(spl, ".mgl"))) { *spl = 0; } @@ -1016,10 +1016,34 @@ void HandleUI(void) static int store_name; static int vfilter_type; + static int mgl_done = 0; + static int mgl_active = 0; + static int mgl_submenu = -1; + static char cp_MenuCancel; - // get user control codes - uint32_t c = menu_key_get(); + uint32_t c = 0; + + if (!mgl_done) + { + mgl_struct *mgl = mgl_get(); + if (mgl->valid != 0xF || + is_menu() || is_minimig() || is_st() || is_archie() + || user_io_core_type() == CORE_TYPE_SHARPMZ) mgl_done = 1; + else + { + if (mgl->timer && CheckTimer(mgl->timer)) + { + mgl_active = 1; + mgl_done = 1; + } + } + } + else if(!mgl_active) + { + // get user control codes + c = menu_key_get(); + } int release = 0; if (c & UPSTROKE) release = 1; @@ -1296,7 +1320,7 @@ void HandleUI(void) if (CheckTimer(menu_timer)) menustate = MENU_NONE1; // fall through case MENU_NONE2: - if (menu || (is_menu() && !video_fb_state())) + if (menu || (is_menu() && !video_fb_state()) || mgl_active) { OsdSetSize(16); if(!is_menu() && (get_key_mod() & (LALT | RALT))) //Alt+Menu @@ -1334,7 +1358,8 @@ void HandleUI(void) } menusub = 0; OsdClear(); - OsdEnable(DISABLE_KEYBOARD); + if (mgl_active) OsdDisable(); + else OsdEnable(DISABLE_KEYBOARD); } break; @@ -1665,7 +1690,13 @@ void HandleUI(void) { if (p[0] == 'S') s_entry = selentry; substrcpy(s, p, 2); - int num = (p[1] >= '0' && p[1] <= '9') ? p[1] - '0' : 0; + int idx = 1; + + if (p[idx] == 'S') idx++; + if (p[idx] == 'C') idx++; + + int num = (p[idx] >= '0' && p[idx] <= '9') ? p[idx] - '0' : 0; + if (mgl_active && num == mgl_get()->index && (p[0] == mgl_get()->type)) mgl_submenu = selentry; if (is_x86() && x86_get_image_name(num)) { @@ -1866,6 +1897,9 @@ void HandleUI(void) case MENU_GENERIC_MAIN2: saved_menustate = MENU_GENERIC_MAIN1; + // F/S option not found -> deactivate mgl. + if (mgl_active && mgl_submenu < 0) mgl_active = 0; + if (menu_save_timer && !CheckTimer(menu_save_timer)) { for (int i = 0; i < 16; i++) OsdWrite(m++); @@ -1892,8 +1926,14 @@ void HandleUI(void) page = 0; } } - else if (select || recent || minus || plus) + else if (select || recent || minus || plus || mgl_active) { + if (mgl_active) + { + menusub = mgl_submenu; + select = 1; + } + if ((dip_submenu == menusub || dip2_submenu == menusub) && select) { dipv = (dip_submenu == menusub) ? 0 : 1; @@ -2003,8 +2043,9 @@ void HandleUI(void) } } - if (select) SelectFile(Selected_F[ioctl_index & 15], ext, fs_Options, fs_MenuSelect, fs_MenuCancel); - else if(recent_init(ioctl_index)) menustate = MENU_RECENT1; + if (mgl_active) menustate = MENU_GENERIC_FILE_SELECTED; + else if (select) SelectFile(Selected_F[ioctl_index & 15], ext, fs_Options, fs_MenuSelect, fs_MenuCancel); + else if (recent_init(ioctl_index)) menustate = MENU_RECENT1; } else if (p[0] == 'S' && (select || recent)) { @@ -2052,8 +2093,9 @@ void HandleUI(void) if (is_psx()) fs_Options |= SCANO_NOZIP; - if (select) SelectFile(Selected_tmp, ext, fs_Options, fs_MenuSelect, fs_MenuCancel); - else if(recent_init(ioctl_index + 500)) menustate = MENU_RECENT1; + if (mgl_active) menustate = MENU_GENERIC_IMAGE_SELECTED; + else if (select) SelectFile(Selected_tmp, ext, fs_Options, fs_MenuSelect, fs_MenuCancel); + else if (recent_init(ioctl_index + 500)) menustate = MENU_RECENT1; } else if (select || minus || plus) { @@ -2183,10 +2225,15 @@ void HandleUI(void) case MENU_GENERIC_FILE_SELECTED: { + if (mgl_active) snprintf(selPath, sizeof(selPath), "%s/%s", HomeDir(), mgl_get()->path); + MenuHide(); printf("File selected: %s\n", selPath); memcpy(Selected_F[ioctl_index & 15], selPath, sizeof(Selected_F[ioctl_index & 15])); + if (!mgl_active && selPath[0]) recent_update(SelectedDir, Selected_F[ioctl_index & 15], SelectedLabel, ioctl_index); + mgl_active = 0; + if (store_name) { char str[64]; @@ -2217,14 +2264,14 @@ void HandleUI(void) } if (addon[0] == 'f' && addon[1] == '1') process_addon(addon, idx); - - recent_update(SelectedDir, Selected_F[ioctl_index & 15], SelectedLabel, ioctl_index); } } break; case MENU_GENERIC_IMAGE_SELECTED: { + if (mgl_active) snprintf(selPath, sizeof(selPath), "%s/%s", HomeDir(), mgl_get()->path); + if (store_name) { char str[64]; @@ -2237,6 +2284,8 @@ void HandleUI(void) printf("Image selected: %s\n", selPath); memcpy(Selected_S[(int)ioctl_index], selPath, sizeof(Selected_S[(int)ioctl_index])); + if (!mgl_active) recent_update(SelectedDir, Selected_S[(int)ioctl_index], SelectedLabel, ioctl_index + 500); + mgl_active = 0; char idx = user_io_ext_idx(selPath, fs_pFileExt) << 6 | ioctl_index; if (addon[0] == 'f' && addon[1] != '1') process_addon(addon, idx); @@ -2266,8 +2315,6 @@ void HandleUI(void) } if (addon[0] == 'f' && addon[1] == '1') process_addon(addon, idx); - - recent_update(SelectedDir, Selected_S[(int)ioctl_index], SelectedLabel, ioctl_index + 500); } break; @@ -6400,10 +6447,10 @@ void HandleUI(void) } } - if (!strcasecmp(".mra",&(Selected_tmp[strlen(Selected_tmp) - 4]))) + if (isXmlName(Selected_tmp)) { // find the RBF file from the XML - arcade_load(getFullPath(Selected_tmp)); + xml_load(getFullPath(Selected_tmp)); } else { @@ -6471,7 +6518,7 @@ void HandleUI(void) OsdWrite(14, s, 1, 0, 0, 0); sprintf(str, " Loading..."); OsdWrite(15, str, 1, 0); - isMraName(cfg.bootcore) ? arcade_load(getFullPath(cfg.bootcore)) : fpga_load_rbf(cfg.bootcore); + isXmlName(cfg.bootcore) ? xml_load(getFullPath(cfg.bootcore)) : fpga_load_rbf(cfg.bootcore); } } } diff --git a/support/arcade/mra_loader.cpp b/support/arcade/mra_loader.cpp index f0d5691..fec1dbe 100644 --- a/support/arcade/mra_loader.cpp +++ b/support/arcade/mra_loader.cpp @@ -1097,7 +1097,16 @@ void arcade_check_error() } } -static const char *get_rbf(const char *xml) +static const char *get_rbf_path(const char *rbfname) +{ + static char path[kBigTextSize]; + snprintf(path, sizeof(path), "%s/%s", getRootDir(), rbfname); + char *p = strrchr(path, '/'); + *p = 0; + return path; +} + +static const char *get_rbf(const char *xml, int arcade) { static char rbfname[kBigTextSize]; @@ -1111,9 +1120,23 @@ static const char *get_rbf(const char *xml) /* once we have the rbfname fragment from the MRA xml file * search the arcade folder for the match */ struct dirent *entry; - DIR *dir; + DIR *dir = 0; + + const char *dirname; + const char *filename; + if (arcade) + { + dirname = get_arcade_root(1); + filename = rbfname; + } + else + { + dirname = get_rbf_path(rbfname); + filename = strrchr(rbfname, '/'); + if (filename) filename++; + else filename = rbfname; + } - const char *dirname = get_arcade_root(1); if (!(dir = opendir(dirname))) { printf("%s directory not found\n", dirname); @@ -1130,17 +1153,20 @@ static const char *get_rbf(const char *xml) static char newstring[kBigTextSize]; //printf("entry name: %s\n",entry->d_name); - snprintf(newstring, kBigTextSize, "Arcade-%s", rbfname); - len = strlen(newstring); - if (!strncasecmp(newstring, entry->d_name, len) && (entry->d_name[len] == '.' || entry->d_name[len] == '_')) + if (arcade) { - if (!lastfound[0] || strcmp(lastfound, entry->d_name) < 0) + snprintf(newstring, kBigTextSize, "Arcade-%s", filename); + len = strlen(newstring); + if (!strncasecmp(newstring, entry->d_name, len) && (entry->d_name[len] == '.' || entry->d_name[len] == '_')) { - strcpy(lastfound, entry->d_name); + if (!lastfound[0] || strcmp(lastfound, entry->d_name) < 0) + { + strcpy(lastfound, entry->d_name); + } } } - snprintf(newstring, kBigTextSize, "%s", rbfname); + snprintf(newstring, kBigTextSize, "%s", filename); len = strlen(newstring); if (!strncasecmp(newstring, entry->d_name, len) && (entry->d_name[len] == '.' || entry->d_name[len] == '_')) { @@ -1158,7 +1184,7 @@ static const char *get_rbf(const char *xml) return lastfound[0] ? rbfname : NULL; } -int arcade_load(const char *xml) +int xml_load(const char *xml) { MenuHide(); static char path[kBigTextSize]; @@ -1166,13 +1192,16 @@ int arcade_load(const char *xml) if(xml[0] == '/') strcpy(path, xml); else snprintf(path, sizeof(path), "%s/%s", getRootDir(), xml); - set_arcade_root(path); - printf("arcade_load [%s]\n", path); - const char *rbf = get_rbf(path); + int len = strlen(xml); + int is_arcade = (len > 4) && !strcasecmp(xml + len - 4, ".mra"); + + if (is_arcade) set_arcade_root(path); + printf("xml_load [%s]\n", path); + const char *rbf = get_rbf(path, is_arcade); if (rbf) { - printf("MRA: %s, RBF: %s\n", path, rbf); + printf("XML: %s, RBF: %s\n", path, rbf); fpga_load_rbf(rbf, NULL, path); } else @@ -1182,3 +1211,91 @@ int arcade_load(const char *xml) return 0; } + +static mgl_struct mgl = {}; + +static int scan_mgl(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, const int n, SAX_Data* sd) +{ + (void)sd; + + static int inside_mgl = 0; + switch (evt) + { + case XML_EVENT_START_DOC: + inside_mgl = 0; + break; + + case XML_EVENT_START_NODE: + if (!strcasecmp(node->tag, "mistergamedescription")) inside_mgl = 1; + else if (inside_mgl && !strcasecmp(node->tag, "file")) + { + for (int i = 0; i < node->n_attributes; i++) + { + if (!strcasecmp(node->attributes[i].name, "delay")) + { + mgl.delay = strtoul(node->attributes[i].value, NULL, 0); + mgl.valid |= 0x1; + } + else if (!strcasecmp(node->attributes[i].name, "type")) + { + if (!strcasecmp(node->attributes[i].value, "s")) + { + mgl.type = 'S'; + mgl.valid |= 0x2; + } + else if (!strcasecmp(node->attributes[i].value, "f")) + { + mgl.type = 'F'; + mgl.valid |= 0x2; + } + } + else if (!strcasecmp(node->attributes[i].name, "index")) + { + mgl.index = strtoul(node->attributes[i].value, NULL, 0); + mgl.valid |= 0x4; + } + else if (!strcasecmp(node->attributes[i].name, "path")) + { + snprintf(mgl.path, sizeof(mgl.path), "%s", node->attributes[i].value); + mgl.valid |= 0x8; + } + } + } + break; + + case XML_EVENT_TEXT: + break; + + case XML_EVENT_END_NODE: + if (!strcasecmp(node->tag, "mistergamedescription")) inside_mgl = 0; + break; + + case XML_EVENT_ERROR: + printf("XML parse: %s: ERROR %d\n", text, n); + break; + default: + break; + } + + return true; +} + +mgl_struct* mgl_parse(const char *xml) +{ + memset(&mgl, 0, sizeof(mgl)); + + SAX_Callbacks sax; + SAX_Callbacks_init(&sax); + sax.all_event = scan_mgl; + XMLDoc_parse_file_SAX(xml, &sax, 0); + + printf("MGL %s\n delay=%d\n type=%c\n index=%d\n path=%s\n valid=%X\n\n", xml, mgl.delay, mgl.type, mgl.index, mgl.path, mgl.valid); + + mgl.parsed = 1; + return &mgl; +} + +mgl_struct* mgl_get() +{ + return &mgl; +} diff --git a/support/arcade/mra_loader.h b/support/arcade/mra_loader.h index 609f59d..c2b2691 100644 --- a/support/arcade/mra_loader.h +++ b/support/arcade/mra_loader.h @@ -2,7 +2,7 @@ #define ROMUTILS_H_ int arcade_send_rom(const char *xml); -int arcade_load(const char *xml); +int xml_load(const char *xml); void arcade_check_error(); struct dip_struct @@ -27,6 +27,17 @@ struct sw_struct dip_struct dip[64]; }; +struct mgl_struct +{ + char path[1024]; + int delay; + char type; + int index; + int valid; + int parsed; + uint32_t timer; +}; + sw_struct *arcade_sw(int n); void arcade_sw_send(int n); void arcade_sw_save(int n); @@ -35,4 +46,7 @@ void arcade_override_name(const char *xml); void arcade_nvm_save(); +mgl_struct* mgl_parse(const char *xml); +mgl_struct* mgl_get(); + #endif diff --git a/user_io.cpp b/user_io.cpp index 4a23b4e..b2d0a8f 100644 --- a/user_io.cpp +++ b/user_io.cpp @@ -1084,7 +1084,7 @@ void user_io_init(const char *path, const char *xml) OsdSetSize(8); - if (xml) + if (xml && isXmlName(xml) == 1) { is_arcade_type = 1; arcade_override_name(xml); @@ -1142,6 +1142,7 @@ void user_io_init(const char *path, const char *xml) load_volume(); user_io_send_buttons(1); + if (xml && isXmlName(xml) == 2) mgl_parse(xml); switch (core_type) { @@ -1193,7 +1194,7 @@ void user_io_init(const char *path, const char *xml) } else { - if (xml) + if (xml && isXmlName(xml) == 1) { arcade_send_rom(xml); } @@ -1307,7 +1308,7 @@ void user_io_init(const char *path, const char *xml) // release reset if(!is_minimig() && !is_st()) user_io_status(0, UIO_STATUS_RESET); - if(xml) arcade_check_error(); + if (xml && isXmlName(xml) == 1) arcade_check_error(); break; } @@ -1351,6 +1352,8 @@ void user_io_init(const char *path, const char *xml) if (uartmode < 3 || uartmode > 4) midilink = 0; SetMidiLinkMode(midilink); SetUARTMode(uartmode); + + if (mgl_get()->valid == 0xF) mgl_get()->timer = GetTimer(mgl_get()->delay * 1000); } static int joyswap = 0;