diff --git a/builds/genesis_plus_gx_libretro.dll b/builds/genesis_plus_gx_libretro.dll index ae66c7d..b5ebad8 100644 Binary files a/builds/genesis_plus_gx_libretro.dll and b/builds/genesis_plus_gx_libretro.dll differ diff --git a/builds/genplus_cube.dol b/builds/genplus_cube.dol index 86a3b2a..7a86415 100644 Binary files a/builds/genplus_cube.dol and b/builds/genplus_cube.dol differ diff --git a/builds/genplus_wii.dol b/builds/genplus_wii.dol index 88023e4..ecfb22d 100644 Binary files a/builds/genplus_wii.dol and b/builds/genplus_wii.dol differ diff --git a/core/cart_hw/areplay.c b/core/cart_hw/areplay.c index c27f8d8..73b16a4 100644 --- a/core/cart_hw/areplay.c +++ b/core/cart_hw/areplay.c @@ -2,7 +2,7 @@ * Genesis Plus * Action Replay / Pro Action Replay emulation * - * Copyright (C) 2009-2011 Eke-Eke (Genesis Plus GX) + * Copyright (C) 2009-2014 Eke-Eke (Genesis Plus GX) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: @@ -60,7 +60,6 @@ static void ar_write_ram_8(uint32 address, uint32 data); void areplay_init(void) { int size; - FILE *f; memset(&action_replay,0,sizeof(action_replay)); @@ -69,38 +68,33 @@ void areplay_init(void) action_replay.rom = cart.rom + 0x810000; action_replay.ram = cart.rom + 0x830000; - /* Open Action Replay ROM */ - f = fopen(AR_ROM,"rb"); - if (f == NULL) return; - - /* ROM size */ - fseek(f, 0, SEEK_END); - size = ftell(f); - fseek(f, 0, SEEK_SET); + /* try to load Action Replay ROM file */ + size = load_archive(AR_ROM, action_replay.rom, 0x20000, NULL); /* detect Action Replay board type */ switch (size) { case 0x8000: { - /* normal Action Replay (32K) */ - action_replay.enabled = TYPE_AR; - - /* internal registers mapped at $010000-$01ffff */ - m68k.memory_map[0x01].write16 = ar_write_regs; - break; + if (!memcmp(action_replay.rom + 0x120, "ACTION REPLAY ", 16)) + { + /* normal Action Replay (32K) */ + action_replay.enabled = TYPE_AR; + + /* internal registers mapped at $010000-$01ffff */ + m68k.memory_map[0x01].write16 = ar_write_regs; + break; + } } case 0x10000: case 0x20000: { - /* read Stack Pointer */ - uint8 sp[4]; - fread(&sp, 4, 1, f); - fseek(f, 0, SEEK_SET); + /* Read stack pointer MSB */ + uint8 sp = READ_BYTE(action_replay.rom, 0x01); /* Detect board version */ - if (sp[1] == 0x42) + if ((sp == 0x42) && !memcmp(action_replay.rom + 0x120, "ACTION REPLAY 2 ", 16)) { /* PRO Action Replay 1 (64/128K) */ action_replay.enabled = TYPE_PRO1; @@ -108,7 +102,7 @@ void areplay_init(void) /* internal registers mapped at $010000-$01ffff */ m68k.memory_map[0x01].write16 = ar_write_regs; } - else if (sp[1] == 0x60) + else if ((sp == 0x60) && !memcmp(action_replay.rom + 0x3c6, "ACTION REPLAY II", 16)) { /* PRO Action Replay 2 (64K) */ action_replay.enabled = TYPE_PRO2; @@ -120,11 +114,11 @@ void areplay_init(void) /* internal RAM (64k), mapped at $420000-$42ffff or $600000-$60ffff */ if (action_replay.enabled) { - m68k.memory_map[sp[1]].base = action_replay.ram; - m68k.memory_map[sp[1]].read8 = NULL; - m68k.memory_map[sp[1]].read16 = NULL; - m68k.memory_map[sp[1]].write8 = ar_write_ram_8; - m68k.memory_map[sp[1]].write16 = NULL; + m68k.memory_map[sp].base = action_replay.ram; + m68k.memory_map[sp].read8 = NULL; + m68k.memory_map[sp].read16 = NULL; + m68k.memory_map[sp].write8 = ar_write_ram_8; + m68k.memory_map[sp].write16 = NULL; } break; } @@ -135,16 +129,10 @@ void areplay_init(void) } } +#ifdef LSB_FIRST if (action_replay.enabled) { - /* Load ROM */ - int i = 0; - for (i=0; i 0x810000) return; ggenie.rom = cart.rom + 0x810000; - /* Open Game Genie ROM file */ - f = fopen(GG_ROM,"rb"); - if (f == NULL) return; - - /* Load ROM */ - for (i=0; i<0x8000; i+=0x1000) + /* Try to load Game Genie ROM file */ + if (load_archive(GG_ROM, ggenie.rom, 0x8000, NULL) > 0) { - fread(ggenie.rom + i, 0x1000, 1, f); - } - - /* Close ROM file */ - fclose(f); - #ifdef LSB_FIRST - for (i=0; i<0x8000; i+=2) - { - /* Byteswap ROM */ - uint8 temp = ggenie.rom[i]; - ggenie.rom[i] = ggenie.rom[i+1]; - ggenie.rom[i+1] = temp; - } + int i; + for (i=0; i<0x8000; i+=2) + { + /* Byteswap ROM */ + uint8 temp = ggenie.rom[i]; + ggenie.rom[i] = ggenie.rom[i+1]; + ggenie.rom[i+1] = temp; + } #endif - /* $0000-$7fff mirrored into $8000-$ffff */ - memcpy(ggenie.rom + 0x8000, ggenie.rom, 0x8000); + /* $0000-$7fff mirrored into $8000-$ffff */ + memcpy(ggenie.rom + 0x8000, ggenie.rom, 0x8000); - /* set flag */ - ggenie.enabled = 1; + /* Game Genie hardware is enabled */ + ggenie.enabled = 1; + } } void ggenie_shutdown(void) diff --git a/core/cart_hw/ggenie.h b/core/cart_hw/ggenie.h index 524c751..a67f007 100644 --- a/core/cart_hw/ggenie.h +++ b/core/cart_hw/ggenie.h @@ -2,7 +2,7 @@ * Genesis Plus * Game Genie Hardware emulation * - * Copyright (C) 2009-2011 Eke-Eke (Genesis Plus GX) + * Copyright (C) 2009-2014 Eke-Eke (Genesis Plus GX) * * Based on documentation from Charles McDonald * (http://cgfm2.emuviews.com/txt/genie.txt) diff --git a/core/cart_hw/md_cart.c b/core/cart_hw/md_cart.c index 2456954..8ba47f7 100644 --- a/core/cart_hw/md_cart.c +++ b/core/cart_hw/md_cart.c @@ -463,54 +463,45 @@ void md_cart_init(void) case TYPE_SK: { - FILE *f; - /* store S&K ROM above cartridge ROM (and before backup memory) */ if (cart.romsize > 0x600000) break; - /* load Sonic & Knuckles ROM (2 MB) */ - f = fopen(SK_ROM,"rb"); - if (!f) break; - for (i=0; i<0x200000; i+=0x1000) + /* try to load Sonic & Knuckles ROM file (2 MB) */ + if (load_archive(SK_ROM, cart.rom + 0x600000, 0x200000, NULL) == 0x200000) { - fread(cart.rom + 0x600000 + i, 0x1000, 1, f); - } - fclose(f); + /* check ROM header */ + if (!memcmp(cart.rom + 0x600000 + 0x120, "SONIC & KNUCKLES",16)) + { + /* try to load Sonic 2 & Knuckles UPMEM ROM (256 KB) */ + if (load_archive(SK_UPMEM, cart.rom + 0x900000, 0x40000, NULL) == 0x40000) + { + /* $000000-$1FFFFF is mapped to S&K ROM */ + for (i=0x00; i<0x20; i++) + { + m68k.memory_map[i].base = cart.rom + 0x600000 + (i << 16); + } - /* load Sonic 2 UPMEM ROM (256 KB) */ - f = fopen(SK_UPMEM,"rb"); - if (!f) break; - for (i=0; i<0x40000; i+=0x1000) - { - fread(cart.rom + 0x900000 + i, 0x1000, 1, f); - } - fclose(f); - #ifdef LSB_FIRST - for (i=0; i<0x200000; i+=2) - { - /* Byteswap ROM */ - uint8 temp = cart.rom[i + 0x600000]; - cart.rom[i + 0x600000] = cart.rom[i + 0x600000 + 1]; - cart.rom[i + 0x600000 + 1] = temp; - } - - for (i=0; i<0x40000; i+=2) - { - /* Byteswap ROM */ - uint8 temp = cart.rom[i + 0x900000]; - cart.rom[i + 0x900000] = cart.rom[i + 0x900000 + 1]; - cart.rom[i + 0x900000 + 1] = temp; - } + for (i=0; i<0x200000; i+=2) + { + /* Byteswap ROM */ + uint8 temp = cart.rom[i + 0x600000]; + cart.rom[i + 0x600000] = cart.rom[i + 0x600000 + 1]; + cart.rom[i + 0x600000 + 1] = temp; + } + + for (i=0; i<0x40000; i+=2) + { + /* Byteswap ROM */ + uint8 temp = cart.rom[i + 0x900000]; + cart.rom[i + 0x900000] = cart.rom[i + 0x900000 + 1]; + cart.rom[i + 0x900000 + 1] = temp; + } #endif - - /* $000000-$1FFFFF is mapped to S&K ROM */ - for (i=0x00; i<0x20; i++) - { - m68k.memory_map[i].base = cart.rom + 0x600000 + (i << 16); + cart.special |= HW_LOCK_ON; + } + } } - - cart.special |= HW_LOCK_ON; break; } diff --git a/core/loadrom.c b/core/loadrom.c index 09e6db2..309352f 100644 --- a/core/loadrom.c +++ b/core/loadrom.c @@ -453,7 +453,7 @@ int load_bios(void) if (cart.romsize <= 0x400000) { /* load Game Gear BOOTROM file */ - size = load_archive(GG_BIOS, cart.rom + 0x400000, 0x100000, 0); + size = load_archive(GG_BIOS, cart.rom + 0x400000, 0x400000, 0); if (size > 0) { diff --git a/gx/config.c b/gx/config.c index 2c6b9f2..47e9119 100644 --- a/gx/config.c +++ b/gx/config.c @@ -41,6 +41,8 @@ #include "gui.h" #include "file_load.h" +t_config config; + static int config_load(void) { /* open configuration file */ @@ -239,9 +241,23 @@ void config_default(void) sprintf (config.lastdir[4][TYPE_DVD], "dvd:%s/roms/", DEFAULT_PATH); #endif + /* system ROM paths */ + sprintf (config.sys_rom[0], "%s/bios/bios_CD_U.bin", DEFAULT_PATH); + sprintf (config.sys_rom[1], "%s/bios/bios_CD_E.bin", DEFAULT_PATH); + sprintf (config.sys_rom[2], "%s/bios/bios_CD_J.bin", DEFAULT_PATH); + sprintf (config.sys_rom[3], "%s/bios/bios_MD.bin", DEFAULT_PATH); + sprintf (config.sys_rom[4], "%s/bios/bios_U.sms", DEFAULT_PATH); + sprintf (config.sys_rom[5], "%s/bios/bios_E.sms", DEFAULT_PATH); + sprintf (config.sys_rom[6], "%s/bios/bios_J.sms", DEFAULT_PATH); + sprintf (config.sys_rom[7], "%s/bios/bios.gg", DEFAULT_PATH); + sprintf (config.sys_rom[8], "%s/lock-on/ggenie.bin", DEFAULT_PATH); + sprintf (config.sys_rom[9], "%s/lock-on/areplay.bin", DEFAULT_PATH); + sprintf (config.sys_rom[10], "%s/lock-on/sk.bin", DEFAULT_PATH); + sprintf (config.sys_rom[11], "%s/lock-on/sk2chip.bin", DEFAULT_PATH); + /* try to restore user config */ int loaded = config_load(); - + #ifndef HW_RVL /* check if component cable was detected */ if (VIDEO_HaveComponentCable()) diff --git a/gx/config.h b/gx/config.h index 30b6be4..5bfd530 100644 --- a/gx/config.h +++ b/gx/config.h @@ -119,11 +119,10 @@ typedef struct float ntsc_artifacts; float ntsc_fringing; float ntsc_bleed; + char sys_rom[12][256]; } t_config; -/* Global data */ -t_config config; - +extern t_config config; extern void config_save(void); extern void config_default(void); diff --git a/gx/fileio/file_load.c b/gx/fileio/file_load.c index a12b602..dc1fde1 100644 --- a/gx/fileio/file_load.c +++ b/gx/fileio/file_load.c @@ -1,7 +1,7 @@ /* * file_load.c * - * ROM File loading support + * File loading support * * Copyright Eke-Eke (2008-2014) * @@ -238,12 +238,6 @@ int UpdateDirectory(bool go_up, char *dirname) /* go up to parent directory */ if (go_up) { - /* special case */ - if (deviceType == TYPE_RECENT) return 0; - - /* check if we already are at root directory */ - if (!strcmp(rootdir[deviceType], (const char *)fileDir)) return 0; - int size=0; char temp[MAXPATHLEN]; @@ -253,14 +247,20 @@ int UpdateDirectory(bool go_up, char *dirname) while (test != NULL) { size = strlen(test); - strncpy(dirname,test,size); - dirname[size] = 0; + if (dirname) + { + strncpy(dirname,test,size); + dirname[size] = 0; + } test = strtok(NULL,"/"); } + /* check if we already are at root directory */ + size = strlen(fileDir) - size - 1; + if (!size) return 0; + /* remove last folder from path */ - size = strlen(fileDir) - size; - fileDir[size - 1] = 0; + fileDir[size] = 0; } else { @@ -501,8 +501,30 @@ int OpenDirectory(int device, int type) } } - /* parse last directory */ - fileDir = config.lastdir[type][device]; + /* System ROM selection */ + if (type >= FILETYPE_MAX) + { + /* allocate temporary directory */ + fileDir = malloc(MAXPATHLEN); + if (!fileDir) + { + GUI_WaitPrompt("Error","Unable to allocate memory !"); + return 0; + } + + /* extract System ROM directory */ + strcpy(fileDir, config.sys_rom[type-FILETYPE_MAX]); + int i = strlen(fileDir) - 1; + while (fileDir[i] != '/') + i--; + fileDir[i+1] = 0; + } + else + { + /* parse last ROM type directory on selected device */ + fileDir = config.lastdir[type][device]; + } + max = ParseDirectory(); if (max <= 0) { @@ -527,13 +549,24 @@ int OpenDirectory(int device, int type) /* check if device or file type has changed */ if ((device != deviceType) || (type != fileType)) { - /* reset current types */ + /* reset device type */ deviceType = device; - fileType = type; - /* reset File selector */ - ClearSelector(max); + /* make sure we are not selecting System ROM file */ + if (type < FILETYPE_MAX) + { + /* reset file type */ + fileType = type; + + /* reset File selector */ + ClearSelector(max); + } } - return 1; + return max; } + +char *GetCurrentDirectory(void) +{ + return fileDir; +} \ No newline at end of file diff --git a/gx/fileio/file_load.h b/gx/fileio/file_load.h index 3495204..acbb176 100644 --- a/gx/fileio/file_load.h +++ b/gx/fileio/file_load.h @@ -1,7 +1,7 @@ /* * file_load.c * - * ROM File loading support + * File loading support * * Copyright Eke-Eke (2008-2014) * @@ -62,6 +62,8 @@ typedef enum FILETYPE_MAX }FILETYPES; + +extern char *GetCurrentDirectory(void); extern int OpenDirectory(int device, int type); extern int UpdateDirectory(bool go_up, char *filename); extern int ParseDirectory(void); diff --git a/gx/fileio/fileio.c b/gx/fileio/fileio.c index 4d97eb0..dddd128 100644 --- a/gx/fileio/fileio.c +++ b/gx/fileio/fileio.c @@ -4,7 +4,7 @@ * Load a normal file, or ZIP/GZ archive into ROM buffer. * Returns loaded ROM size (zero if an error occured). * - * Copyright Eke-Eke (2007-2013), based on original work from Softdev (2006) + * Copyright Eke-Eke (2007-2014), based on original work from Softdev (2006) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: @@ -87,26 +87,54 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize, char *exten { int size = 0; char in[CHUNKSIZE]; - char msg[64] = "Unable to open file"; + char msg[64]; + char type[16]; /* Open file */ FILE *fd = fopen(filename, "rb"); - /* Master System & Game Gear BIOS are optional files */ - if (!strcmp(filename,MS_BIOS_US) || !strcmp(filename,MS_BIOS_EU) || !strcmp(filename,MS_BIOS_JP) || !strcmp(filename,GG_BIOS)) + /* Autodetect needed System ROM files */ + if (filename == CD_BIOS_US) { - /* disable all messages */ + sprintf(type,"CD BIOS (USA)"); + } + else if (filename == CD_BIOS_EU) + { + sprintf(type,"CD BIOS (PAL)"); + } + else if (filename == CD_BIOS_JP) + { + sprintf(type,"CD BIOS (JAP)"); + } + else if (filename == AR_ROM) + { + sprintf(type,"Action Replay"); + } + else if (filename == GG_ROM) + { + sprintf(type,"Game Genie"); + } + else if (filename == SK_ROM) + { + sprintf(type,"S&K (2MB ROM)"); + } + else if (filename == SK_UPMEM) + { + sprintf(type,"S2&K (256K ROM)"); + } + else if ((filename == MS_BIOS_US) || (filename == MS_BIOS_EU) || (filename == MS_BIOS_JP) || (filename == GG_BIOS) || (filename == MD_BIOS)) + { + /* Mega Drive / Genesis, Master System & Game Gear BIOS are optional so we disable error messages */ SILENT = 1; } - - /* Mega CD BIOS are required files */ - if (!strcmp(filename,CD_BIOS_US) || !strcmp(filename,CD_BIOS_EU) || !strcmp(filename,CD_BIOS_JP)) + else { - sprintf(msg,"Unable to open %s", filename + 14); + sprintf(type,"file"); } if (!fd) { + sprintf(msg,"Unable to open %s", type); GUI_WaitPrompt("Error", msg); SILENT = 0; return 0; @@ -128,13 +156,17 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize, char *exten size = FLIP32(pkzip->uncompressedSize); /* Check ROM size */ - if (size > maxsize) + if (size > MAXROMSIZE) { fclose(fd); GUI_WaitPrompt("Error","File is too large"); SILENT = 0; return 0; } + else if (size > maxsize) + { + size = maxsize; + } sprintf (msg, "Unzipping %d bytes ...", size); GUI_MsgBoxUpdate("Information",msg); @@ -148,25 +180,23 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize, char *exten zs.avail_in = 0; zs.next_in = Z_NULL; int res = inflateInit2(&zs, -MAX_WBITS); - if (res != Z_OK) { fclose(fd); - GUI_WaitPrompt("Error","Unable to unzip file"); + sprintf(msg,"Unable to unzip %s", type); + GUI_WaitPrompt("Error",msg); SILENT = 0; return 0; } /* Compressed filename offset */ int offset = sizeof (PKZIPHEADER) + FLIP16(pkzip->filenameLength); - if (extension) { memcpy(extension, &in[offset - 3], 3); extension[3] = 0; } - /* Initial Zip buffer offset */ offset += FLIP16(pkzip->extraDataLength); zs.next_in = (Bytef *)&in[offset]; @@ -174,6 +204,9 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize, char *exten /* Initial Zip remaining chunk size */ zs.avail_in = CHUNKSIZE - offset; + /* Initialize output size */ + size = 0; + /* Start unzipping file */ do { @@ -188,26 +221,34 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize, char *exten { inflateEnd(&zs); fclose(fd); - GUI_WaitPrompt("Error","Unable to unzip file"); + sprintf(msg,"Unable to unzip %s", type); + GUI_WaitPrompt("Error",msg); SILENT = 0; return 0; } offset = CHUNKSIZE - zs.avail_out; + + if ((size + offset) > maxsize) + { + offset = maxsize - size; + } + if (offset) { memcpy(buffer, out, offset); buffer += offset; + size += offset; } } - while (zs.avail_out == 0); + while ((zs.avail_out == 0) && (size < maxsize)); /* Read next chunk of zipped data */ fread(in, CHUNKSIZE, 1, fd); zs.next_in = (Bytef *)&in[0]; zs.avail_in = CHUNKSIZE; } - while (res != Z_STREAM_END); + while ((res != Z_STREAM_END) && (size < maxsize)); inflateEnd (&zs); } else @@ -217,14 +258,18 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize, char *exten size = ftell(fd); fseek(fd, 0, SEEK_SET); - /* size limit */ - if(size > maxsize) + /* Check ROM size */ + if (size > MAXROMSIZE) { fclose(fd); GUI_WaitPrompt("Error","File is too large"); SILENT = 0; return 0; } + else if (size > maxsize) + { + size = maxsize; + } sprintf((char *)msg,"Loading %d bytes ...", size); GUI_MsgBoxUpdate("Information", (char *)msg); diff --git a/gx/fileio/fileio.h b/gx/fileio/fileio.h index 4e1c6c6..756791d 100644 --- a/gx/fileio/fileio.h +++ b/gx/fileio/fileio.h @@ -4,7 +4,7 @@ * Load a normal file, or ZIP/GZ archive into ROM buffer. * Returns loaded ROM size (zero if an error occured). * - * Copyright Eke-Eke (2007-2013), based on original work from Softdev (2006) + * Copyright Eke-Eke (2007-2014), based on original work from Softdev (2006) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: diff --git a/gx/gui/cheats.c b/gx/gui/cheats.c index 8c31d46..86342fc 100644 --- a/gx/gui/cheats.c +++ b/gx/gui/cheats.c @@ -1,7 +1,7 @@ /* - * cheats.c + * cheats.c * - * Cheats menu + * Genesis Plus GX Cheats menu * * Copyright Eke-Eke (2010-2014) * @@ -82,6 +82,12 @@ static u8 cheatIndexes[MAX_CHEATS]; static void cheatmenu_cb(void); +static gui_image star; +static gui_image bar_over; +static gui_image key_switch; +static gui_image key_enable; +static gui_image key_delete; + /*****************************************************************************/ /* GUI Buttons data */ /*****************************************************************************/ @@ -649,14 +655,8 @@ static void cheatmenu_cb(void) { int i; int yoffset = 108; - gui_image bar_over; - gui_image star; char temp[MAX_DESC_LENGTH]; - /* Initialize textures */ - bar_over.texture = gxTextureOpenPNG(Overlay_bar_png,0); - star.texture = gxTextureOpenPNG(Star_full_png,0); - /* Draw browser array */ gxDrawRectangle(15, 108, 358, 26, 127, (GXColor)BG_COLOR_1); gxDrawRectangle(15, 134, 358, 26, 127, (GXColor)BG_COLOR_2); @@ -761,15 +761,10 @@ static void cheatmenu_cb(void) } } - gxTextureClose(&bar_over.texture); - gxTextureClose(&star.texture); - /* Extra helpers */ if (maxcheats && !(menu_cheats.bg_images[6].state & IMAGE_VISIBLE)) { /* switch between cheat code & description preview */ - gui_image key_switch; - key_switch.texture = gxTextureOpenPNG(Key_DPAD_png,0); #ifdef HW_RVL gxDrawTexture(key_switch.texture,268,424,24,24,255); FONT_write(type ? "View\nCode":"View\nText",16,300,436,640,(GXColor)WHITE); @@ -777,30 +772,21 @@ static void cheatmenu_cb(void) gxDrawTexture(key_switch.texture,272,424,24,24,255); FONT_write(type ? "View\nCode":"View\nText",16,304,436,640,(GXColor)WHITE); #endif - gxTextureClose(&key_switch.texture); /* delete & enable cheats */ if ((offset + selection) < maxcheats) { - gui_image key_enable; - gui_image key_delete; #ifdef HW_RVL - key_enable.texture = gxTextureOpenPNG(Key_Plus_wii_png,0); - key_delete.texture = gxTextureOpenPNG(Key_Minus_wii_png,0); gxDrawTexture(key_enable.texture,152,424,24,24,255); gxDrawTexture(key_delete.texture,372,424,24,24,255); FONT_write(cheatlist[offset + selection].enable ? "Disable\nCheat":"Enable\nCheat",16,184,436,640,(GXColor)WHITE); FONT_write("Delete\nCheat",16,404,436,640,(GXColor)WHITE); #else - key_enable.texture = gxTextureOpenPNG(Key_L_gcn_png,0); - key_delete.texture = gxTextureOpenPNG(Key_R_gcn_png,0); gxDrawTexture(key_enable.texture,136,426,44,20,255); gxDrawTexture(key_delete.texture,368,426,44,20,255); FONT_write(cheatlist[offset + selection].enable ? "Disable\nCheat":"Enable\nCheat",16,188,436,640,(GXColor)WHITE); FONT_write("Delete\nCheat",16,420,436,640,(GXColor)WHITE); #endif - gxTextureClose(&key_enable.texture); - gxTextureClose(&key_delete.texture); } } } @@ -836,6 +822,18 @@ void CheatMenu(void) { bg_cheats[1].state &= ~IMAGE_VISIBLE; } + + /* additional textures */ + star.texture = gxTextureOpenPNG(Star_full_png,0); + bar_over.texture = gxTextureOpenPNG(Overlay_bar_png,0); + key_switch.texture = gxTextureOpenPNG(Key_DPAD_png,0); +#ifdef HW_RVL + key_enable.texture = gxTextureOpenPNG(Key_Plus_wii_png,0); + key_delete.texture = gxTextureOpenPNG(Key_Minus_wii_png,0); +#else + key_enable.texture = gxTextureOpenPNG(Key_L_gcn_png,0); + key_delete.texture = gxTextureOpenPNG(Key_R_gcn_png,0); +#endif /* selected item */ m->selected = selection; @@ -843,7 +841,6 @@ void CheatMenu(void) /* slide-in menu */ GUI_InitMenu(m); GUI_DrawMenuFX(m,30,0); - m->cb = cheatmenu_cb; /* lock background elements */ m->bg_images[2].state &= ~IMAGE_SLIDE_TOP; @@ -868,24 +865,55 @@ void CheatMenu(void) /* check if browsing cheats list */ if (!(m->bg_images[6].state & IMAGE_VISIBLE)) { - /* restore cheats list offset */ + /* restore scrolling list settings */ m->offset = offset; m->max_items = (maxcheats < MAX_CHEATS) ? (maxcheats + 1) : MAX_CHEATS; m->max_buttons = 10; m->helpers[1] = NULL; + + /* check if arrow button is high-lighted */ + if (m->selected >= 30) + { + /* adjust selected button index */ + m->selected -= 20; + } } +#ifdef HW_RVL + if (Shutdown) + { + /* close additional textures */ + gxTextureClose(&star.texture); + gxTextureClose(&bar_over.texture); + gxTextureClose(&key_switch.texture); + gxTextureClose(&key_enable.texture); + gxTextureClose(&key_delete.texture); + + /* restore default GUI settings */ + m->max_items = m->max_buttons = 30; + m->helpers[1] = &action_select; + } +#endif + /* update menu */ update = GUI_UpdateMenu(m); /* check if browsing cheats list */ if (!(m->bg_images[6].state & IMAGE_VISIBLE)) { - /* update selected cheat */ - if ((m->selected < 10) && (selection != m->selected)) + if (m->selected < 10) { - selection = m->selected; - string_offset = 0; + /* update selected cheat */ + if (selection != m->selected) + { + selection = m->selected; + string_offset = 0; + } + } + else + { + /* arrow button is selected */ + m->selected += 20; } /* save cheats list offset */ @@ -990,13 +1018,15 @@ void CheatMenu(void) } /* show digit buttons */ - for (i=10; i<30; i++) m->buttons[i].state |= BUTTON_VISIBLE; + for (i=10; i<30; i++) + m->buttons[i].state |= BUTTON_VISIBLE; /* show right window */ m->bg_images[6].state |= IMAGE_VISIBLE; /* disable left buttons */ - for (i=0; i<10; i++) m->buttons[i].state &= ~BUTTON_ACTIVE; + for (i=0; i<10; i++) + m->buttons[i].state &= ~BUTTON_ACTIVE; /* disable arrow buttons */ m->arrows[0]->state &= ~BUTTON_ACTIVE; @@ -1037,7 +1067,8 @@ void CheatMenu(void) str[digit_cnt] = '*'; /* update scroll value if necessary */ - if (string_offset > 0) string_offset--; + if (string_offset > 0) + string_offset--; } break; } @@ -1124,14 +1155,17 @@ void CheatMenu(void) case 29: /* Validate entry */ { - /* check if entry is valid */ + /* finalize cheat description */ if (type && ((offset + selection) != maxcheats)) { str[digit_cnt] = 0; update = -1; } + + /* finalize cheat code edition */ else if (max && (digit_cnt > max)) { + /* check if cheat code is valid */ if (decode_cheat(cheatlist[offset + selection].code, offset + selection)) { /* new cheat ? */ @@ -1161,10 +1195,12 @@ void CheatMenu(void) default: /* Add Character */ { /* force code separator if none has been set yet */ - if ((max == 0) && (digit_cnt == 6)) break; + if ((max == 0) && (digit_cnt == 6)) + break; /* force 8-bit Game Genie code last separator */ - if (((system_hw & SYSTEM_PBC) != SYSTEM_MD) && (max == 10) && (digit_cnt == 7)) break; + if (((system_hw & SYSTEM_PBC) != SYSTEM_MD) && (max == 10) && (digit_cnt == 7)) + break; /* add character */ if ((digit_cnt <= max) || (max == 0)) @@ -1176,7 +1212,9 @@ void CheatMenu(void) str[digit_cnt] = '*'; str[digit_cnt+1] = 0; } - if (string_offset > 0) string_offset ++; + + if (string_offset > 0) + string_offset ++; } break; } @@ -1184,6 +1222,7 @@ void CheatMenu(void) } else if (update < 0) { + /* cancel */ if (m->bg_images[6].state & IMAGE_VISIBLE) { /* Restore old entry */ @@ -1192,6 +1231,7 @@ void CheatMenu(void) } else { + /* check other buttons pressed while browsing cheats list */ if (maxcheats && !(m->bg_images[6].state & IMAGE_VISIBLE)) { if ((m_input.keys & PAD_BUTTON_LEFT) || (m_input.keys & PAD_BUTTON_RIGHT)) @@ -1202,15 +1242,14 @@ void CheatMenu(void) /* reset scrolling */ string_offset = 0; } - - if ((offset + selection) < maxcheats) + else if ((offset + selection) < maxcheats) { - /* Special inputs */ + /* Delete selected cheat code*/ if (m_input.keys & PAD_TRIGGER_R) { if (GUI_WaitConfirm("Warning","Delete Cheat Entry ?")) { - /* sort cheat list */ + /* shift cheat list up to selected entry */ for (i = offset + selection + 1; i < maxcheats; i++) { strcpy(cheatlist[i-1].text,cheatlist[i].text); @@ -1227,11 +1266,20 @@ void CheatMenu(void) cheatlist[maxcheats-1].data = 0; cheatlist[maxcheats-1].enable = 0; - /* disable last button */ - if ((maxcheats - offset) < 10) + /* adjust scrolling list */ + if (maxcheats < 10) { - m->buttons[maxcheats - offset].state &= ~BUTTON_ACTIVE; - m->buttons[maxcheats - offset - 1].shift[1] = 0; + /* disable next button */ + m->buttons[maxcheats].state &= ~BUTTON_ACTIVE; + m->buttons[maxcheats-1].shift[1] = 0; + } + else + { + /* scroll down cheat list if there is less than 10 visible entries */ + if ((maxcheats < (offset + 10)) && (maxcheats < MAX_CHEATS)) + { + offset--; + } } /* decrease cheat count */ @@ -1243,7 +1291,7 @@ void CheatMenu(void) } else if (m_input.keys & PAD_TRIGGER_L) { - /* cheat ON/OFF */ + /* Enable/Disable selected cheat code */ cheatlist[offset + selection].enable ^= 1; } } @@ -1258,28 +1306,29 @@ void CheatMenu(void) GUI_DrawMenuFX(m,20,1); /* hide digit buttons */ - for (i=10; i<30; i++) m->buttons[i].state &= ~BUTTON_VISIBLE; + for (i=10; i<30; i++) + m->buttons[i].state &= ~BUTTON_VISIBLE; /* hide right window */ m->bg_images[6].state &= ~IMAGE_VISIBLE; - /* update left buttons */ + /* enable left buttons */ for (i=0; i<10; i++) { - if ((offset + i) < maxcheats) + if (i < maxcheats) { - m->buttons[i].state |= BUTTON_ACTIVE; - m->buttons[i].shift[1] = 1; + menu_cheats.buttons[i].state |= BUTTON_ACTIVE; + menu_cheats.buttons[i].shift[1] = 1; } - else if ((offset + i) == maxcheats) + else if (i == maxcheats) { - m->buttons[i].state |= BUTTON_ACTIVE; - m->buttons[i].shift[1] = 0; + menu_cheats.buttons[i].state |= BUTTON_ACTIVE; + menu_cheats.buttons[i].shift[1] = 0; } else { - m->buttons[i].state &= ~BUTTON_ACTIVE; - m->buttons[i].shift[1] = 0; + menu_cheats.buttons[i].state &= ~BUTTON_ACTIVE; + menu_cheats.buttons[i].shift[1] = 0; } } @@ -1326,11 +1375,17 @@ void CheatMenu(void) m->bg_images[2].state |= IMAGE_SLIDE_TOP; m->bg_images[3].state |= IMAGE_SLIDE_BOTTOM; m->bg_images[4].state |= IMAGE_SLIDE_TOP; - + /* leave menu */ - m->cb = NULL; - GUI_DeleteMenu(m); GUI_DrawMenuFX(m,30,1); + GUI_DeleteMenu(m); + + /* close additional textures */ + gxTextureClose(&star.texture); + gxTextureClose(&bar_over.texture); + gxTextureClose(&key_switch.texture); + gxTextureClose(&key_enable.texture); + gxTextureClose(&key_delete.texture); } @@ -1365,8 +1420,10 @@ void CheatLoad(void) while (fgets(temp, 256, f) && (maxcheats < MAX_CHEATS) && (cnt < MAX_CHEATS)) { /* remove CR & EOL chars */ - if ((temp[strlen(temp) - 2] == 0x0d) || (temp[strlen(temp) - 2] == 0x0a)) temp[strlen(temp) - 2] = 0; - else temp[strlen(temp) - 1] = 0; + if ((temp[strlen(temp) - 2] == 0x0d) || (temp[strlen(temp) - 2] == 0x0a)) + temp[strlen(temp) - 2] = 0; + else + temp[strlen(temp) - 1] = 0; /* check cheat validty */ len = decode_cheat(temp, maxcheats); @@ -1379,7 +1436,8 @@ void CheatLoad(void) len++; /* jump TAB and SPACE characters */ - while ((temp[len] == 0x20) || (temp[len] == 0x09)) len++; + while ((temp[len] == 0x20) || (temp[len] == 0x09)) + len++; /* copy cheat description */ strncpy(cheatlist[maxcheats].text, &temp[len], MAX_DESC_LENGTH - 1); @@ -1401,7 +1459,8 @@ void CheatLoad(void) } /* by default, disable cheats that were not flagged */ - while (cnt < maxcheats) cheatlist[cnt++].enable = 0; + while (cnt < maxcheats) + cheatlist[cnt++].enable = 0; /* close file */ fclose(f); diff --git a/gx/gui/cheats.h b/gx/gui/cheats.h index 5a6f216..99c9101 100644 --- a/gx/gui/cheats.h +++ b/gx/gui/cheats.h @@ -1,7 +1,7 @@ /* - * cheats.c + * cheats.c * - * Cheats menu + * Genesis Plus GX Cheats menu * * Copyright Eke-Eke (2010-2014) * diff --git a/gx/gui/filesel.c b/gx/gui/filesel.c index d91d35f..56feab8 100644 --- a/gx/gui/filesel.c +++ b/gx/gui/filesel.c @@ -1,7 +1,7 @@ /* - * filesel.c + * filesel.c * - * ROM File Browser + * File Browser * * Copyright Eke-Eke (2009-2014) * @@ -97,7 +97,7 @@ static gui_item action_cancel = static gui_item action_select = { - NULL,Key_A_png,"","Load ROM file",602,422,28,28 + NULL,Key_A_png,"","Load file",602,422,28,28 }; /*****************************************************************************/ @@ -139,6 +139,9 @@ static const char *Cart_dir[FILETYPE_MAX] = "sg" }; +static gui_image dir_icon; +static gui_image bar_over; + /*****************************************************************************/ /* GUI Descriptor */ /*****************************************************************************/ @@ -162,22 +165,6 @@ static void selector_cb(void) char text[MAXPATHLEN]; int yoffset = 108; - /* Initialize directory icon */ - gui_image dir_icon; - dir_icon.texture = gxTextureOpenPNG(Browser_dir_png,0); - dir_icon.w = dir_icon.texture->width; - dir_icon.h = dir_icon.texture->height; - dir_icon.x = 26; - dir_icon.y = (26 - dir_icon.h)/2; - - /* Initialize selection bar */ - gui_image bar_over; - bar_over.texture = gxTextureOpenPNG(Overlay_bar_png,0); - bar_over.w = bar_over.texture->width; - bar_over.h = bar_over.texture->height; - bar_over.x = 16; - bar_over.y = (26 - bar_over.h)/2; - /* Draw browser array */ gxDrawRectangle(15, 108, 358, 26, 127, (GXColor)BG_COLOR_1); gxDrawRectangle(15, 134, 358, 26, 127, (GXColor)BG_COLOR_2); @@ -250,9 +237,6 @@ static void selector_cb(void) yoffset += 26; } - - gxTextureClose(&bar_over.texture); - gxTextureClose(&dir_icon.texture); } @@ -272,6 +256,10 @@ int FileSelector(int type) FILE *snap; gui_menu *m = &menu_selector; + int offset_ = -1; + int selection_ = -1; + int maxfiles_ = -1; + #ifdef HW_RVL int x,y; gui_butn *button; @@ -294,15 +282,172 @@ int FileSelector(int type) bg_filesel[9+i].state &= ~IMAGE_VISIBLE; } - /* Select cartridge type */ + /* System ROM selection */ + if (type >= FILETYPE_MAX) + { + /* Save current ROM browser */ + offset_ = offset; + maxfiles_ = maxfiles; + selection_ = selection; + + /* Initialize ROM browser */ + maxfiles = ParseDirectory(); + selection = offset = 0; + while (selection < maxfiles) + { + if (strstr(config.sys_rom[type-FILETYPE_MAX], filelist[selection].filename)) + { + offset = selection; + while ((offset > (maxfiles - 10)) && (offset > 0)) + { + offset--; + } + break; + } + selection++; + } + + /* By default, select first file in directory if ROM is not found */ + if (selection >= maxfiles) + { + selection = 0; + } + + /* Set menu title and cartridge label type */ + switch (type - FILETYPE_MAX) + { + case 0: + { + strcpy(m->title,"Sega CD (USA) BIOS Selection"); + type = FILETYPE_MD; + break; + } + + case 1: + { + strcpy(m->title,"Mega CD (PAL) BIOS Selection"); + type = FILETYPE_MD; + break; + } + + case 2: + { + strcpy(m->title,"Mega CD (JAP) BIOS Selection"); + type = FILETYPE_MD; + break; + } + + case 3: + { + strcpy(m->title,"Mega Drive/Genesis BootROM Selection"); + type = FILETYPE_MD; + break; + } + + case 4: + { + strcpy(m->title,"Master System (USA) BootROM Selection"); + type = FILETYPE_MS; + break; + } + + case 5: + { + strcpy(m->title,"Master System (PAL) BootROM Selection"); + type = FILETYPE_MS; + break; + } + + case 6: + { + strcpy(m->title,"Master System (JAP) BootROM Selection"); + type = FILETYPE_MS; + break; + } + + case 7: + { + strcpy(m->title,"Game Gear BootROM Selection"); + type = FILETYPE_GG; + break; + } + + case 8: + { + strcpy(m->title,"Game Genie ROM Selection"); + type = FILETYPE_MD; + break; + } + + case 9: + { + strcpy(m->title,"Action Replay (Pro) ROM Selection"); + type = FILETYPE_MD; + break; + } + + case 10: + { + strcpy(m->title,"Sonic & Knuckles ROM Selection"); + type = FILETYPE_MD; + break; + } + + case 11: + { + strcpy(m->title,"Sonic 2 & Knuckles ROM Selection"); + type = FILETYPE_MD; + break; + } + } + } + else + { + /* reset menu title */ + strcpy(m->title, "Game Selection"); + } + + /* Set default helper for Back button */ + strcpy(m->helpers[0]->comment, "Exit"); + + /* Check if we are not browsing recent file list */ if (type >= 0) { - /* Select cartridge type */ bg_filesel[9 + type].data = Cart_png[type]; bg_filesel[9 + type].state |= IMAGE_VISIBLE; + + /* Get current directory */ + char *dir = GetCurrentDirectory(); + + /* Get current directory name length */ + int size = strlen(dir); + + /* Check if we are not in Root directory */ + if (size > 1) + { + if (dir[size - 2] != ':') + { + /* Update helper for Back button */ + strcpy(m->helpers[0]->comment, "Previous Directory"); + } + } + + /* Initialize directory icon */ + dir_icon.texture = gxTextureOpenPNG(Browser_dir_png,0); + dir_icon.w = dir_icon.texture->width; + dir_icon.h = dir_icon.texture->height; + dir_icon.x = 26; + dir_icon.y = (26 - dir_icon.h)/2; } + /* Initialize selection bar */ + bar_over.texture = gxTextureOpenPNG(Overlay_bar_png,0); + bar_over.w = bar_over.texture->width; + bar_over.h = bar_over.texture->height; + bar_over.x = 16; + bar_over.y = (26 - bar_over.h)/2; + /* Initialize Menu */ GUI_InitMenu(m); string_offset = 0; @@ -340,11 +485,11 @@ int FileSelector(int type) /* show selected cartridge label */ bg_filesel[9 + type].state |= IMAGE_VISIBLE; - - /* default screenshot file path */ - sprintf(fname,"%s/snaps/%s/%s", DEFAULT_PATH, Cart_dir[type], filelist[selection].filename); } + /* default screenshot file path */ + sprintf(fname,"%s/snaps/%s/%s", DEFAULT_PATH, Cart_dir[type], filelist[selection].filename); + /* restore recent type flag */ type = -1; } @@ -376,7 +521,7 @@ int FileSelector(int type) } } - /* update helper */ + /* update Action button helper */ if (m->selected != -1) { /* out of focus */ @@ -390,15 +535,26 @@ int FileSelector(int type) else { /* this is a ROM file */ - strcpy(action_select.comment,"Load File"); + if (offset_ != -1) + { + /* System ROM browser */ + strcpy(action_select.comment,"Select File"); + } + else + { + /* Normal ROM browser */ + strcpy(action_select.comment,"Load File"); + } } - + /* Draw menu*/ GUI_DrawMenu(m); #ifdef HW_RVL if (Shutdown) { + gxTextureClose(&bar_over.texture); + gxTextureClose(&dir_icon.texture); gxTextureClose(&w_pointer); GUI_DeleteMenu(m); GUI_FadeOut(); @@ -465,10 +621,10 @@ int FileSelector(int type) if (p & PAD_BUTTON_DOWN) { selection++; - if (selection == maxfiles) + if (selection >= maxfiles) selection = offset = 0; - if ((selection - offset) >= 10) - offset += 10; + else if (selection >= (offset + 10)) + offset++; } /* highlight previous item */ @@ -479,11 +635,10 @@ int FileSelector(int type) { selection = maxfiles - 1; offset = maxfiles - 10; + if (offset < 0) offset = 0; } - if (selection < offset) - offset -= 10; - if (offset < 0) - offset = 0; + else if (selection < offset) + offset --; } /* go back one page */ @@ -494,10 +649,12 @@ int FileSelector(int type) selection -= 10; if (selection < 0) { + /* first page */ selection = offset = 0; } else if (selection < offset) { + /* previous page */ offset -= 10; if (offset < 0) offset = 0; } @@ -516,7 +673,7 @@ int FileSelector(int type) selection = maxfiles - 1; offset = maxfiles - 10; } - else if (selection >= (offset + 10)) + else if (selection >= (offset + 10)) { /* next page */ offset += 10; @@ -528,8 +685,19 @@ int FileSelector(int type) /* quit */ else if (p & PAD_TRIGGER_Z) { + /* System ROM selection */ + if (offset_ != -1) + { + /* restore current ROM browser */ + offset = offset_; + maxfiles = maxfiles_; + selection = selection_; + } + + gxTextureClose(&bar_over.texture); + gxTextureClose(&dir_icon.texture); GUI_DeleteMenu(m); - return 0; + return -1; } /* previous directory */ @@ -537,12 +705,40 @@ int FileSelector(int type) { string_offset = 0; + /* recent ROM list */ + if (type < 0) + { + /* exit */ + gxTextureClose(&bar_over.texture); + gxTextureClose(&dir_icon.texture); + GUI_DeleteMenu(m); + return -1; + } + /* update browser directory (and get current folder)*/ if (UpdateDirectory(1, prev_folder)) { /* get directory entries */ maxfiles = ParseDirectory(); + /* Get current directory */ + char *dir = GetCurrentDirectory(); + + /* current directory name length */ + int size = strlen(dir); + + /* Adjust helper for back button */ + if ((size > 1) && (dir[size - 2] != ':')) + { + /* Back button goes up one directory */ + strcpy(m->helpers[0]->comment, "Previous Directory"); + } + else + { + /* Back button exits from root directory */ + strcpy(m->helpers[0]->comment, "Exit"); + } + /* clear selection by default */ selection = offset = 0; old = -1; @@ -564,9 +760,20 @@ int FileSelector(int type) } else { - /* exit */ + /* System ROM selection */ + if (offset_ != -1) + { + /* restore current ROM browser */ + offset = offset_; + maxfiles = maxfiles_; + selection = selection_; + } + + /* Exit */ + gxTextureClose(&bar_over.texture); + gxTextureClose(&dir_icon.texture); GUI_DeleteMenu(m); - return 0; + return -1; } } @@ -591,14 +798,30 @@ int FileSelector(int type) old = -1; } else - { - /* load ROM file from device */ - int ret = LoadFile(selection); + { + int ret; + + /* System ROM selection */ + if (offset_ != -1) + { + /* return ROM file index */ + ret = selection; + + /* restore current ROM browser */ + offset = offset_; + maxfiles = maxfiles_; + selection = selection_; + } + else + { + /* load ROM file from device then return ROM size (zero if an error occured) */ + ret = LoadFile(selection); + } /* exit menu */ + gxTextureClose(&bar_over.texture); + gxTextureClose(&dir_icon.texture); GUI_DeleteMenu(m); - - /* return ROM size (or zero if an error occured) */ return ret; } } diff --git a/gx/gui/filesel.h b/gx/gui/filesel.h index cda5c6e..66b7c8e 100644 --- a/gx/gui/filesel.h +++ b/gx/gui/filesel.h @@ -1,7 +1,7 @@ /* - * filesel.c + * filesel.c * - * ROM File Browser + * File Browser * * Copyright Eke-Eke (2009-2014) * diff --git a/gx/gui/menu.c b/gx/gui/menu.c index a380fb8..315886c 100644 --- a/gx/gui/menu.c +++ b/gx/gui/menu.c @@ -355,8 +355,25 @@ static gui_item items_audio[13] = {NULL,NULL,"High Freq: 20000 Hz", "Adjust EQ Highest Frequency", 56,132,276,48} }; +/* System ROM paths */ +static gui_item items_rompaths[12] = +{ + {NULL,NULL,"CD BIOS (USA): NOT FOUND", "Select Sega CD (USA) BIOS", 56,132,276,48}, + {NULL,NULL,"CD BIOS (PAL): NOT FOUND", "Select Mega CD (PAL) BIOS", 56,132,276,48}, + {NULL,NULL,"CD BIOS (JAP): NOT FOUND", "Select Mega CD (JAP) BIOS", 56,132,276,48}, + {NULL,NULL,"MD BIOS (TMSS): NOT FOUND", "Select Mega Drive / Genesis BootROM", 56,132,276,48}, + {NULL,NULL,"MS BIOS (USA): NOT FOUND", "Select Master System (USA) BootROM", 56,132,276,48}, + {NULL,NULL,"MS BIOS (PAL): NOT FOUND", "Select Master System (PAL) BootROM", 56,132,276,48}, + {NULL,NULL,"MS BIOS (JAP): NOT FOUND", "Select Master System (JAP) BootROM", 56,132,276,48}, + {NULL,NULL,"Game Gear BIOS: NOT FOUND", "Select Game Gear BootROM", 56,132,276,48}, + {NULL,NULL,"Game Genie: NOT FOUND", "Select Game Genie ROM", 56,132,276,48}, + {NULL,NULL,"Action Replay: NOT FOUND", "Select Action Replay (Pro) ROM", 56,132,276,48}, + {NULL,NULL,"S&K (2MB ROM): NOT FOUND", "Select Sonic & Knuckle main ROM", 56,132,276,48}, + {NULL,NULL,"S2&K (256K ROM): NOT FOUND","Select Sonic 2 & Knuckle upmem ROM", 56,132,276,48}, +}; + /* System options */ -static gui_item items_system[10] = +static gui_item items_system[11] = { {NULL,NULL,"Console Hardware: AUTO", "Select system hardware model", 56,132,276,48}, {NULL,NULL,"Console Region: AUTO", "Select system region", 56,132,276,48}, @@ -367,6 +384,7 @@ static gui_item items_system[10] = {NULL,NULL,"68k Address Error: ON", "Enable/disable 68k address error exceptions", 56,132,276,48}, {NULL,NULL,"Lock-on: OFF", "Select Lock-On cartridge type", 56,132,276,48}, {NULL,NULL,"Cartridge Swap: OFF", "Enable/disable cartridge hot swap", 56,132,276,48}, + {NULL,NULL,"BIOS & Lock-On ROM paths","Configure BIOS & Lock-On ROM paths", 56,132,276,48}, {NULL,NULL,"SVP Cycles: 1500", "Adjust SVP chip emulation speed", 56,132,276,48} }; @@ -378,7 +396,7 @@ static gui_item items_video[16] = #endif { {NULL,NULL,"Display: PROGRESSIVE", "Select video mode", 56,132,276,48}, - {NULL,NULL,"TV mode: 50/60Hz", "Select video refresh rate", 56,132,276,48}, + {NULL,NULL,"TV mode: 50/60HZ", "Select video refresh rate", 56,132,276,48}, {NULL,NULL,"VSYNC: AUTO", "Enable/disable sync with Video Hardware", 56,132,276,48}, {NULL,NULL,"GX Bilinear Filter: OFF", "Enable/disable texture hardware filtering", 56,132,276,48}, {NULL,NULL,"GX Deflickering Filter: OFF","Enable/disable GX hardware filtering", 56,132,276,48}, @@ -582,6 +600,20 @@ static gui_menu menu_options = NULL }; +/* System ROM Path submenu */ +static gui_menu menu_rompaths = +{ + "System ROM Paths", + 0,0, + 12,4,6,0, + items_rompaths, + buttons_list, + bg_list, + {&action_cancel, &action_select}, + {&arrow_up,&arrow_down}, + NULL +}; + /* System Options menu */ static gui_menu menu_system = { @@ -1107,6 +1139,98 @@ static void soundmenu () GUI_DeleteMenu(m); } +/**************************************************************************** + * System ROM paths menu + * + ****************************************************************************/ + +static void rompathmenu () +{ + FILE *f; + int i, ret; + gui_menu *m = &menu_rompaths; + gui_item *items = m->items; + + for (i=0; i<12; i++) + { + f = fopen(config.sys_rom[i],"rb"); + if (f) + { + strcpy(strstr(items[i].text,":") + 2, "FOUND"); + fclose(f); + } + else + { + strcpy(strstr(items[i].text,":") + 2, "NOT FOUND"); + } + } + + GUI_InitMenu(m); + + while (1) + { + ret = GUI_RunMenu(m); + + switch (ret) + { + case -1: + { + GUI_DeleteMenu(m); + return; + } + + default: + { + /* Initialize System ROM browser */ + if (OpenDirectory(config.l_device, ret + FILETYPE_MAX)) + { + /* Open System ROM browser */ + GUI_DeleteMenu(m); + i = FileSelector(ret + FILETYPE_MAX); + + /* Get current System ROM path */ + char *dir = GetCurrentDirectory(); + + /* System ROM selected ? */ + if (i >= 0) + { + /* full System ROM pathname */ + sprintf(config.sys_rom[ret],"%s%s",dir,filelist[i].filename); + + /* mark System ROM as found */ + strcpy(strstr(items[ret].text,":") + 2, "FOUND"); + + /* Genesis BOOT ROM special case */ + if (config.sys_rom[ret] == MD_BIOS) + { + /* Genesis BOOT ROM must be reloaded */ + if (load_archive(MD_BIOS, boot_rom, 0x800, NULL) > 0) + { + /* check if BOOT ROM header is valid */ + if (!memcmp((char *)(boot_rom + 0x120),"GENESIS OS", 10)) + { + /* mark Genesis BIOS as loaded */ + system_bios |= SYSTEM_MD; + } + else + { + /* mark Genesis BIOS as unloaded */ + system_bios &= ~SYSTEM_MD; + } + } + } + } + + free(dir); + GUI_InitMenu(m); + } + } + } + } + + GUI_DeleteMenu(m); +} + /**************************************************************************** * System Settings menu * @@ -1149,9 +1273,9 @@ static void systemmenu () else if (config.region_detect == 1) sprintf (items[1].text, "Console Region: USA"); else if (config.region_detect == 2) - sprintf (items[1].text, "Console Region: EUROPE"); + sprintf (items[1].text, "Console Region: PAL"); else if (config.region_detect == 3) - sprintf (items[1].text, "Console Region: JAPAN"); + sprintf (items[1].text, "Console Region: JAP"); if (config.vdp_mode == 0) sprintf (items[2].text, "VDP Mode: AUTO"); @@ -1184,12 +1308,12 @@ static void systemmenu () if (svp) { - sprintf (items[9].text, "SVP Cycles: %d", SVP_cycles); - m->max_items = 10; + sprintf (items[10].text, "SVP Cycles: %d", SVP_cycles); + m->max_items = 11; } else { - m->max_items = 9; + m->max_items = 10; } GUI_InitMenu(m); @@ -1308,9 +1432,9 @@ static void systemmenu () else if (config.region_detect == 1) sprintf (items[1].text, "Console Region: USA"); else if (config.region_detect == 2) - sprintf (items[1].text, "Console Region: EUR"); + sprintf (items[1].text, "Console Region: PAL"); else if (config.region_detect == 3) - sprintf (items[1].text, "Console Region: JAPAN"); + sprintf (items[1].text, "Console Region: JAP"); /* force system reinitialization + region BIOS */ reinit = 2; @@ -1431,10 +1555,18 @@ static void systemmenu () break; } - case 9: /*** SVP cycles per line ***/ + case 9: /*** System ROM paths ***/ + { + GUI_DeleteMenu(m); + rompathmenu(); + GUI_InitMenu(m); + break; + } + + case 10: /*** SVP cycles per line ***/ { GUI_OptionBox(m,0,"SVP Cycles",(void *)&SVP_cycles,1,1,1500,1); - sprintf (items[9].text, "SVP Cycles: %d", SVP_cycles); + sprintf (items[10].text, "SVP Cycles: %d", SVP_cycles); break; } @@ -2930,11 +3062,12 @@ static void optionmenu(void) * ****************************************************************************/ static t_slot slots[5]; +static gx_texture *star; + static void savemenu_cb(void) { int i; char msg[16]; - gx_texture *star = gxTextureOpenPNG(Star_full_png,0); if (sram.on) { @@ -2974,7 +3107,6 @@ static void savemenu_cb(void) if (i == config.s_default) gxDrawTexture(star,22,buttons_saves[i].y+(buttons_saves[i].h-star->height)/2,star->width,star->height,255); } - gxTextureClose(&star); } static int savemenu(void) @@ -2986,6 +3118,7 @@ static int savemenu(void) gui_menu *m = &menu_saves; FILE *snap; + star = gxTextureOpenPNG(Star_full_png,0); GUI_InitMenu(m); GUI_DrawMenuFX(m,30,0); @@ -3249,6 +3382,7 @@ static int savemenu(void) m->bg_images[5].state |= IMAGE_SLIDE_TOP; GUI_DrawMenuFX(m,30,1); GUI_DeleteMenu(m); + gxTextureClose(&star); return ret; } @@ -3294,7 +3428,7 @@ static int loadgamemenu () if (ret) { GUI_DeleteMenu(m); - if (FileSelector(filetype)) + if (FileSelector(filetype) > 0) { /* directly jump to game */ return 1; @@ -3540,9 +3674,12 @@ static void mainmenu_cb(void) int status = areplay_get_status(); /* Action Replay Switch current status */ - if (status == AR_SWITCH_TRAINER) strcpy(temp,"TM"); - else if (status == AR_SWITCH_ON) strcpy(temp,"ON"); - else strcpy(temp,"OFF"); + if (status == AR_SWITCH_TRAINER) + strcpy(temp,"TM"); + else if (status == AR_SWITCH_ON) + strcpy(temp,"ON"); + else + strcpy(temp,"OFF"); /* Display informations */ if (m->selected == 6) diff --git a/gx/gx_input.c b/gx/gx_input.c index 50b400b..552160b 100644 --- a/gx/gx_input.c +++ b/gx/gx_input.c @@ -50,12 +50,12 @@ #define ANALOG_SENSITIVITY 30 /* Delay before held keys triggering */ -/* higher is the value, less responsive is the key update */ +/* higher is the value, longer must the key remain held */ #define HELD_DELAY 30 /* Direction & selection update speed when a key is being held */ -/* lower is the value, faster is the key update */ -#define HELD_SPEED 4 +/* lower is the value, faster is the key update (min value = 1) */ +#define HELD_SPEED 2 /* Configurable keys */ diff --git a/gx/main.c b/gx/main.c index 886ba5c..e768324 100644 --- a/gx/main.c +++ b/gx/main.c @@ -110,16 +110,11 @@ static void init_machine(void) /* mark all BIOS as unloaded */ system_bios = 0; - /* Genesis BOOT ROM support (2KB max) */ + /* try to load Genesis BOOT ROM (2KB max) */ memset(boot_rom, 0xFF, 0x800); - FILE *fp = fopen(MD_BIOS, "rb"); - if (fp != NULL) + if (load_archive(MD_BIOS, boot_rom, 0x800, NULL) > 0) { - /* read BOOT ROM */ - fread(boot_rom, 1, 0x800, fp); - fclose(fp); - - /* check BOOT ROM */ + /* check if BOOT ROM header is valid */ if (!memcmp((char *)(boot_rom + 0x120),"GENESIS OS", 10)) { /* mark Genesis BIOS as loaded */ diff --git a/gx/osd.h b/gx/osd.h index debc99a..5bd9bf8 100644 --- a/gx/osd.h +++ b/gx/osd.h @@ -37,18 +37,19 @@ /*************************************************/ /* required by Genesis Plus GX core */ /*************************************************/ -#define GG_ROM "/genplus/lock-on/ggenie.bin" -#define AR_ROM "/genplus/lock-on/areplay.bin" -#define SK_ROM "/genplus/lock-on/sk.bin" -#define SK_UPMEM "/genplus/lock-on/sk2chip.bin" -#define MS_BIOS_US "/genplus/bios/bios_U.sms" -#define MS_BIOS_EU "/genplus/bios/bios_E.sms" -#define MS_BIOS_JP "/genplus/bios/bios_J.sms" -#define GG_BIOS "/genplus/bios/bios.gg" -#define MD_BIOS "/genplus/bios/bios_MD.bin" -#define CD_BIOS_US "/genplus/bios/bios_CD_U.bin" -#define CD_BIOS_EU "/genplus/bios/bios_CD_E.bin" -#define CD_BIOS_JP "/genplus/bios/bios_CD_J.bin" +#define CD_BIOS_US config.sys_rom[0] +#define CD_BIOS_EU config.sys_rom[1] +#define CD_BIOS_JP config.sys_rom[2] +#define MD_BIOS config.sys_rom[3] +#define MS_BIOS_US config.sys_rom[4] +#define MS_BIOS_EU config.sys_rom[5] +#define MS_BIOS_JP config.sys_rom[6] +#define GG_BIOS config.sys_rom[7] +#define GG_ROM config.sys_rom[8] +#define AR_ROM config.sys_rom[9] +#define SK_ROM config.sys_rom[10] +#define SK_UPMEM config.sys_rom[11] + #define CD_BRAM_US "/genplus/saves/cd/scd_U.brm" #define CD_BRAM_EU "/genplus/saves/cd/scd_E.brm" #define CD_BRAM_JP "/genplus/saves/cd/scd_J.brm" diff --git a/libretro/libretro.c b/libretro/libretro.c index 8668399..6119c46 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -222,7 +222,10 @@ void osd_input_update(void) case DEVICE_MOUSE: { input.analog[i][0] = input_state_cb(player, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X); - input.analog[i][1] = -input_state_cb(player, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y); + if (config.invert_mouse) + input.analog[i][1] = input_state_cb(player, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y); + else + input.analog[i][1] = -input_state_cb(player, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y); if (input.analog[i][0] < -255) input.analog[i][0] = -255; @@ -251,6 +254,13 @@ void osd_input_update(void) input.analog[i][0] = ((input_state_cb(player, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) + 0x7fff) * bitmap.viewport.w) / 0xfffe; input.analog[i][1] = ((input_state_cb(player, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) + 0x7fff) * bitmap.viewport.h) / 0xfffe; + if (config.gun_cursor) + { + uint16_t *ptr = (uint16_t *)bitmap.data + ((bitmap.viewport.y + input.analog[i][1]) * bitmap.width) + input.analog[i][0] + bitmap.viewport.x; + ptr[-3*bitmap.width] = ptr[-bitmap.width] = ptr[bitmap.width] = ptr[3*bitmap.width] = ptr[-3] = ptr[-1] = ptr[1] = ptr[3] = (i & 1) ? 0xf800 : 0x001f; + ptr[-2*bitmap.width] = ptr[0] = ptr[2*bitmap.width] = ptr[-2] = ptr[2] = 0xffff; + } + if (input_state_cb(player, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_TRIGGER)) temp |= INPUT_A; if (input_state_cb(player, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_TURBO)) @@ -875,6 +885,24 @@ static void check_variables(void) update_viewports = true; } + var.key = "gun_cursor"; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); + { + if (strcmp(var.value, "off") == 0) + config.gun_cursor = 0; + else + config.gun_cursor = 1; + } + + var.key = "invert_mouse"; + environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var); + { + if (strcmp(var.value, "off") == 0) + config.invert_mouse = 0; + else + config.invert_mouse = 1; + } + if (reinit) { audio_init(44100, snd.frame_rate); @@ -913,6 +941,8 @@ void retro_set_environment(retro_environment_t cb) { "overscan", "Borders; disabled|top/bottom|left/right|full" }, { "gg_extra", "Game Gear extended screen; disabled|enabled" }, { "render", "Interlaced mode 2 output; single field|double field" }, + { "gun_cursor", "Show Lightgun crosshair; no|yes" }, + { "invert_mouse", "Invert Mouse Y-axis; no|yes" }, { NULL, NULL }, }; diff --git a/libretro/osd.h b/libretro/osd.h index acb5f40..e22c446 100644 --- a/libretro/osd.h +++ b/libretro/osd.h @@ -64,6 +64,8 @@ struct uint8 gg_extra; uint8 render; t_input_config input[MAX_INPUTS]; + uint8 invert_mouse; + uint8 gun_cursor; } config; extern char GG_ROM[256];