From 3307989c04369e3060c2267cd365b4995887f308 Mon Sep 17 00:00:00 2001 From: dborth Date: Sat, 28 Mar 2009 17:23:08 +0000 Subject: [PATCH] preliminary new GUI implementation --- source/ngc/button_mapping.c | 93 +- source/ngc/button_mapping.h | 10 +- source/ngc/common.h | 5 + source/ngc/dvd.cpp | 133 +- source/ngc/dvd.h | 4 +- source/ngc/fceuconfig.cpp | 42 +- source/ngc/fceuconfig.h | 6 +- source/ngc/fceugx.cpp | 170 +- source/ngc/fceugx.h | 25 +- source/ngc/fceuload.cpp | 102 +- source/ngc/fceuload.h | 3 +- source/ngc/fceuram.cpp | 108 +- source/ngc/fceuram.h | 8 +- source/ngc/fceustate.cpp | 190 +- source/ngc/fceustate.h | 8 +- source/ngc/filebrowser.cpp | 523 ++-- source/ngc/filebrowser.h | 18 +- source/ngc/filelist.h | 3 +- source/ngc/fileop.cpp | 266 +- source/ngc/fileop.h | 11 +- source/ngc/gcaudio.cpp | 51 +- source/ngc/gcaudio.h | 4 +- source/ngc/gcunzip.cpp | 33 +- source/ngc/gcvideo.cpp | 331 ++- source/ngc/gcvideo.h | 31 +- source/ngc/gui/gui.h | 22 +- source/ngc/gui/gui_button.cpp | 3 +- source/ngc/gui/gui_element.cpp | 3 +- source/ngc/gui/gui_filebrowser.cpp | 3 +- source/ngc/gui/gui_image.cpp | 3 +- source/ngc/gui/gui_imagedata.cpp | 3 +- source/ngc/gui/gui_keyboard.cpp | 3 +- source/ngc/gui/gui_optionbrowser.cpp | 3 +- source/ngc/gui/gui_savebrowser.cpp | 9 +- source/ngc/gui/gui_sound.cpp | 3 +- source/ngc/gui/gui_text.cpp | 5 +- source/ngc/gui/gui_trigger.cpp | 3 +- source/ngc/gui/gui_window.cpp | 3 +- source/ngc/http.cpp | 2 +- source/ngc/memcardop.cpp | 465 ++-- source/ngc/memcardop.h | 10 +- source/ngc/menu.cpp | 3800 +++++++++++++++++++++----- source/ngc/menu.h | 33 +- source/ngc/networkop.cpp | 14 +- source/ngc/pad.cpp | 252 +- source/ngc/pad.h | 55 +- source/ngc/preferences.cpp | 121 +- source/unzip/miniunz.cpp | 2 +- 48 files changed, 4905 insertions(+), 2093 deletions(-) diff --git a/source/ngc/button_mapping.c b/source/ngc/button_mapping.c index 2e0bf7d..4c9376f 100644 --- a/source/ngc/button_mapping.c +++ b/source/ngc/button_mapping.c @@ -2,8 +2,8 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 * michniewski August 2008 + * Tantric 2008-2009 * * button_mapping.c * @@ -27,6 +27,50 @@ ***/ CtrlrMap ctrlr_def[4] = { +// Gamecube controller btn def +{ + CTRLR_GCPAD, + 13, + { + {PAD_BUTTON_DOWN, "DOWN"}, + {PAD_BUTTON_UP, "UP"}, + {PAD_BUTTON_LEFT, "LEFT"}, + {PAD_BUTTON_RIGHT, "RIGHT"}, + {PAD_BUTTON_A, "A"}, + {PAD_BUTTON_B, "B"}, + {PAD_BUTTON_X, "X"}, + {PAD_BUTTON_Y, "Y"}, + {PAD_BUTTON_MENU, "START"}, + {PAD_BUTTON_START, "START"}, + {PAD_TRIGGER_L, "L"}, + {PAD_TRIGGER_R, "R"}, + {PAD_TRIGGER_Z, "Z"}, + {0, ""}, + {0, ""} + } +}, +// Wiimote btn def +{ + CTRLR_WIIMOTE, + 11, + { + {WPAD_BUTTON_DOWN, "DOWN"}, + {WPAD_BUTTON_UP, "UP"}, + {WPAD_BUTTON_LEFT, "LEFT"}, + {WPAD_BUTTON_RIGHT, "RIGHT"}, + {WPAD_BUTTON_A, "A"}, + {WPAD_BUTTON_B, "B"}, + {WPAD_BUTTON_1, "1"}, + {WPAD_BUTTON_2, "2"}, + {WPAD_BUTTON_PLUS, "PLUS"}, + {WPAD_BUTTON_MINUS, "MINUS"}, + {WPAD_BUTTON_HOME, "HOME"}, + {0, ""}, + {0, ""}, + {0, ""}, + {0, ""} + } +}, // Nunchuk btn def { CTRLR_NUNCHUK, @@ -70,50 +114,5 @@ CtrlrMap ctrlr_def[4] = { {WPAD_CLASSIC_BUTTON_ZL, "ZL"}, {WPAD_CLASSIC_BUTTON_ZR, "ZR"} } -}, -// Gamecube controller btn def -{ - CTRLR_GCPAD, - 13, - { - {PAD_BUTTON_DOWN, "DOWN"}, - {PAD_BUTTON_UP, "UP"}, - {PAD_BUTTON_LEFT, "LEFT"}, - {PAD_BUTTON_RIGHT, "RIGHT"}, - {PAD_BUTTON_A, "A"}, - {PAD_BUTTON_B, "B"}, - {PAD_BUTTON_X, "X"}, - {PAD_BUTTON_Y, "Y"}, - {PAD_BUTTON_MENU, "START"}, - {PAD_BUTTON_START, "START"}, - {PAD_TRIGGER_L, "L TRIG"}, - {PAD_TRIGGER_R, "R TRIG"}, - {PAD_TRIGGER_Z, "Z"}, - {0, ""}, - {0, ""} - } -}, -// Wiimote btn def -{ - CTRLR_WIIMOTE, - 11, - { - {WPAD_BUTTON_DOWN, "DOWN"}, - {WPAD_BUTTON_UP, "UP"}, - {WPAD_BUTTON_LEFT, "LEFT"}, - {WPAD_BUTTON_RIGHT, "RIGHT"}, - {WPAD_BUTTON_A, "A"}, - {WPAD_BUTTON_B, "B"}, - {WPAD_BUTTON_1, "1"}, - {WPAD_BUTTON_2, "2"}, - {WPAD_BUTTON_PLUS, "PLUS"}, - {WPAD_BUTTON_MINUS, "MINUS"}, - {WPAD_BUTTON_HOME, "HOME"}, - {0, ""}, - {0, ""}, - {0, ""}, - {0, ""} - } - } +} }; - diff --git a/source/ngc/button_mapping.h b/source/ngc/button_mapping.h index 3b5d67f..f37a6a1 100644 --- a/source/ngc/button_mapping.h +++ b/source/ngc/button_mapping.h @@ -2,8 +2,8 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 * michniewski August 2008 + * Tantric 2008-2009 * * button_mapping.h * @@ -15,13 +15,15 @@ enum { CTRLR_NONE = -1, - CTRLR_NUNCHUK, - CTRLR_CLASSIC, CTRLR_GCPAD, CTRLR_WIIMOTE, - CTRLR_SNES = 7 // give some other value for the snes padmap + CTRLR_NUNCHUK, + CTRLR_CLASSIC }; +const char ctrlrName[4][20] = +{ "GameCube Controller", "Wiimote", "Nunchuk + Wiimote", "Classic Controller" }; + typedef struct _btn_map { u32 btn; // button 'id' char* name; // button name diff --git a/source/ngc/common.h b/source/ngc/common.h index e27ab49..180ae3d 100644 --- a/source/ngc/common.h +++ b/source/ngc/common.h @@ -11,6 +11,11 @@ #include "driver.h" +extern "C" { +extern void ResetNES(void); +extern void PowerNES(void); +} + /* Message logging(non-netplay messages, usually) for all. */ extern int NoWaiting; extern FCEUGI *GI; diff --git a/source/ngc/dvd.cpp b/source/ngc/dvd.cpp index 4b7a97e..145a604 100644 --- a/source/ngc/dvd.cpp +++ b/source/ngc/dvd.cpp @@ -2,9 +2,11 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * softdev July 2006 + * svpe & crunchy2 June 2007 + * Tantric 2008-2009 * - * dvd.c + * dvd.cpp * * DVD loading routines ****************************************************************************/ @@ -22,9 +24,11 @@ extern "C" { } #endif -#include "menudraw.h" -#include "gcunzip.h" #include "fceugx.h" +#include "menu.h" +#include "gcunzip.h" +#include "filebrowser.h" +#include "fileop.h" #define MAXDVDFILES 2000 @@ -141,7 +145,6 @@ static int dvd_buffered_read(void *dst, u32 len, u64 offset) * This function relies on dvddir (file offset) being prepopulated! * returns: 1 - ok ; 0 - error ***************************************************************************/ - int dvd_safe_read(void *dst_v, u32 len, u64 fileoffset) { u64 offset = dvddir + fileoffset; @@ -318,35 +321,40 @@ getpvd () * * Tests if a ISO9660 DVD is inserted and available, and mounts it ***************************************************************************/ - bool MountDVD(bool silent) { - if (!getpvd()) + bool res = false; + + if (getpvd()) + { + return true; + } + else { ShowAction("Loading DVD..."); #ifdef HW_DOL DVD_Mount(); // mount the DVD unit again - #elif HW_RVL + #else u32 val; DI_GetCoverRegister(&val); if(val & 0x1) // True if no disc inside, use (val & 0x2) for true if disc inside. { if(!silent) - WaitPrompt("No disc inserted!"); + ErrorPrompt("No disc inserted!"); + CancelAction(); return false; } DI_Mount(); - while(DI_GetStatus() & DVD_INIT); + while(DI_GetStatus() & DVD_INIT) usleep(20000); #endif - if (!getpvd()) - { - if(!silent) - WaitPrompt ("Invalid DVD."); - return false; - } + if (getpvd()) + res = true; + else if(!silent) + ErrorPrompt("Invalid DVD."); } - return true; + CancelAction(); + return res; } /**************************************************************************** @@ -355,7 +363,6 @@ bool MountDVD(bool silent) * Support function to return the next file entry, if any * Declared static to avoid accidental external entry. ***************************************************************************/ - static int getentry (int entrycount, unsigned char dvdbuffer[]) { @@ -445,7 +452,7 @@ getentry (int entrycount, unsigned char dvdbuffer[]) if(!newBrowserList) // failed to allocate required memory { ResetBrowser(); - WaitPrompt("Out of memory: too many files!"); + ErrorPrompt("Out of memory: too many files!"); return 0; } else @@ -455,8 +462,16 @@ getentry (int entrycount, unsigned char dvdbuffer[]) memset(&(browserList[entrycount]), 0, sizeof(BROWSERENTRY)); // clear the new entry strncpy (browserList[entrycount].filename, fname, MAXJOLIET); - StripExt(tmpname, fname); // hide file extension - strncpy (browserList[entrycount].displayname, tmpname, MAXDISPLAY); + + if(strcmp(fname,"..") == 0) + { + sprintf(browserList[entrycount].displayname, "Up One Level"); + } + else + { + StripExt(tmpname, fname); // hide file extension + strncpy (browserList[entrycount].displayname, tmpname, MAXDISPLAY); + } memcpy (&offset32, &dvdbuffer[diroffset + EXTENT], 4); @@ -483,7 +498,7 @@ getentry (int entrycount, unsigned char dvdbuffer[]) * It relies on dvddir and dvddirlength being pre-populated by a call to * getpvd, a previous parse or a menu selection. * - * The return value is number of files collected, or 0 on failure. + * The return value is number of files collected, or -1 on failure. ***************************************************************************/ int ParseDVDdirectory () @@ -506,7 +521,7 @@ ParseDVDdirectory () while (len < pdlength) { if (dvd_read (&dvdbuffer, 2048, pdoffset) == 0) - return 0; + return -1; diroffset = 0; @@ -523,6 +538,7 @@ ParseDVDdirectory () // Sort the file list qsort(browserList, filecount, sizeof(BROWSERENTRY), FileSortCallback); + browser.numEntries = filecount; return filecount; } @@ -530,7 +546,6 @@ ParseDVDdirectory () * SetDVDdirectory * Set the current DVD file offset ***************************************************************************/ - void SetDVDdirectory(u64 dir, int length) { dvddir = dir; @@ -579,12 +594,18 @@ static bool SwitchDVDFolderR(char * dir, int maxDepth) if(dirindex >= 0) { - dvddir = browserList[dirindex].offset; - dvddirlength = browserList[dirindex].length; browser.selIndex = dirindex; if(browserList[dirindex].isdir) // only parse directories - browser.numEntries = ParseDVDdirectory(); + { + UpdateDirName(METHOD_DVD); + ParseDVDdirectory(); + } + else + { + dvddir = browserList[dirindex].offset; + dvddirlength = browserList[dirindex].length; + } if(lastdir) return true; @@ -597,8 +618,8 @@ static bool SwitchDVDFolderR(char * dir, int maxDepth) bool SwitchDVDFolder(char origdir[]) { // make a copy of origdir so we don't mess with original - char dir[200]; - strcpy(dir, origdir); + char dir[1024]; + strncpy(dir, origdir, 1024); char * dirptr = dir; @@ -612,6 +633,7 @@ bool SwitchDVDFolder(char origdir[]) // start searching at root of DVD dvddir = dvdrootdir; dvddirlength = dvdrootlength; + browser.dir[0] = 0; ParseDVDdirectory(); return SwitchDVDFolderR(dirptr, 0); @@ -622,10 +644,10 @@ bool SwitchDVDFolder(char origdir[]) * This function will load a file from DVD * It assumes dvddir and dvddirlength are prepopulated ***************************************************************************/ - int LoadDVDFileOffset (unsigned char *buffer, int length) { + int result = 0; int offset; int blocks; int i; @@ -643,17 +665,19 @@ LoadDVDFileOffset (unsigned char *buffer, int length) { ret = dvd_read (buffer, length, discoffset); if(ret <= 0) // read failure - return 0; + goto done; + else + result = length; } else // load whole file { ret = dvd_read (readbuffer, 2048, discoffset); if(ret <= 0) // read failure - return 0; + goto done; if (IsZipFile (readbuffer)) { - return UnZipBuffer (buffer, METHOD_DVD); // unzip from dvd + result = UnZipBuffer (buffer, METHOD_DVD); // unzip from dvd } else { @@ -661,7 +685,7 @@ LoadDVDFileOffset (unsigned char *buffer, int length) { ret = dvd_read (readbuffer, 2048, discoffset); if(ret <= 0) // read failure - return 0; + goto done; memcpy (buffer + offset, readbuffer, 2048); offset += 2048; discoffset += 2048; @@ -674,12 +698,15 @@ LoadDVDFileOffset (unsigned char *buffer, int length) i = dvddirlength % 2048; ret = dvd_read (readbuffer, 2048, discoffset); if(ret <= 0) // read failure - return 0; + goto done; memcpy (buffer + offset, readbuffer, i); } + result = dvddirlength; } } - return dvddirlength; +done: + CancelAction(); + return result; } /**************************************************************************** @@ -688,20 +715,30 @@ LoadDVDFileOffset (unsigned char *buffer, int length) * It will attempt to find the offset of the file, and if successful it * will populate dvddir and dvddirlength, and load the file ***************************************************************************/ - int LoadDVDFile(char * buffer, char *filepath, int datasize, bool silent) { + int ret = 0; + + // retain original browser information + char origDir[MAXPATHLEN]; + memset(origDir, 0, MAXPATHLEN); + strncpy(origDir, browser.dir, MAXPATHLEN); + int origSelIndex = browser.selIndex; + int origPageIndex = browser.selIndex; + if(SwitchDVDFolder(filepath)) - { - return LoadDVDFileOffset ((unsigned char *)buffer, datasize); - } - else - { - if(!silent) - WaitPrompt("Error loading file!"); - return 0; - } + ret = LoadDVDFileOffset ((unsigned char *)buffer, datasize); + else if(!silent) + ErrorPrompt("Error loading file!"); + + // restore browser information + memset(browser.dir, 0, MAXPATHLEN); + strncpy(browser.dir, origDir, MAXPATHLEN); + browser.selIndex = origSelIndex; + browser.pageIndex = origPageIndex; + + return ret; } /**************************************************************************** @@ -768,8 +805,8 @@ int dvd_driveid() dvd[6] = 0x20; dvd[7] = 3; - while( dvd[7] & 1 ) - ; + while( dvd[7] & 1 ); + DCFlushRange((void *)0x80000000, 32); return (int)inquiry[2]; diff --git a/source/ngc/dvd.h b/source/ngc/dvd.h index 6175947..79675e0 100644 --- a/source/ngc/dvd.h +++ b/source/ngc/dvd.h @@ -2,7 +2,9 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * softdev July 2006 + * svpe & crunchy2 June 2007 + * Tantric 2008-2009 * * dvd.h * diff --git a/source/ngc/fceuconfig.cpp b/source/ngc/fceuconfig.cpp index eac80c8..23c5c03 100644 --- a/source/ngc/fceuconfig.cpp +++ b/source/ngc/fceuconfig.cpp @@ -2,9 +2,9 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * - * fceuconfig.c + * fceuconfig.cpp * * Configuration parameters ****************************************************************************/ @@ -20,6 +20,31 @@ struct SGCSettings GCSettings; +/**************************************************************************** + * FixInvalidSettings + * + * Attempts to correct at least some invalid settings - the ones that + * might cause crashes + ***************************************************************************/ +void FixInvalidSettings() +{ + if(!(GCSettings.ZoomLevel > 0.5 && GCSettings.ZoomLevel < 1.5)) + GCSettings.ZoomLevel = 1.0; + if(!(GCSettings.xshift > -50 && GCSettings.xshift < 50)) + GCSettings.xshift = 0; + if(!(GCSettings.yshift > -50 && GCSettings.yshift < 50)) + GCSettings.yshift = 0; + if(!(GCSettings.MusicVolume >= 0 && GCSettings.MusicVolume <= 100)) + GCSettings.MusicVolume = 40; + if(!(GCSettings.SFXVolume >= 0 && GCSettings.SFXVolume <= 100)) + GCSettings.SFXVolume = 40; +} + +/**************************************************************************** + * DefaultSettings + * + * Sets all the defaults! + ***************************************************************************/ void DefaultSettings () { @@ -27,18 +52,21 @@ DefaultSettings () GCSettings.currpal = 0; GCSettings.timing = 0; // 0 - NTSC, 1 - PAL - GCSettings.FourScore = 0; - GCSettings.zapper = 0; + GCSettings.Controller = CTRL_PAD2; // NES pad, Four Score, Zapper GCSettings.crosshair = 1; - GCSettings.Zoom = 0; // zooming default off GCSettings.ZoomLevel = 1.0; // zoom amount GCSettings.render = 2; // Unfiltered GCSettings.widescreen = 0; // no aspect ratio correction GCSettings.hideoverscan = 2; // hide both horizontal and vertical - GCSettings.xshift = 0; // video shift - GCSettings.yshift = 0; + GCSettings.xshift = 0; // horizontal video shift + GCSettings.yshift = 0; // vertical video shift + + GCSettings.WiimoteOrientation = 0; + GCSettings.ExitAction = 0; + GCSettings.MusicVolume = 40; + GCSettings.SFXVolume = 40; GCSettings.LoadMethod = METHOD_AUTO; // Auto, SD, DVD, USB, Network (SMB) GCSettings.SaveMethod = METHOD_AUTO; // Auto, SD, Memory Card Slot A, Memory Card Slot B, USB, Network (SMB) diff --git a/source/ngc/fceuconfig.h b/source/ngc/fceuconfig.h index b46e174..7707bf6 100644 --- a/source/ngc/fceuconfig.h +++ b/source/ngc/fceuconfig.h @@ -2,7 +2,7 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * * fceuconfig.h * @@ -10,9 +10,9 @@ ****************************************************************************/ #ifndef _FCEUCONFIG_H_ - #define _FCEUCONFIG_H_ -void DefaultSettings (); +void FixInvalidSettings(); +void DefaultSettings(); #endif diff --git a/source/ngc/fceugx.cpp b/source/ngc/fceugx.cpp index 2789737..24a6231 100644 --- a/source/ngc/fceugx.cpp +++ b/source/ngc/fceugx.cpp @@ -2,9 +2,9 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * - * fceugx.c + * fceugx.cpp * * This file controls overall program flow. Most things start and end here! ****************************************************************************/ @@ -25,14 +25,16 @@ #include "fceustate.h" #include "fceuram.h" #include "common.h" -#include "menudraw.h" #include "menu.h" #include "preferences.h" #include "fileop.h" +#include "filebrowser.h" #include "networkop.h" #include "gcaudio.h" #include "gcvideo.h" #include "pad.h" +#include "filelist.h" +#include "gui/gui.h" #ifdef HW_RVL extern "C" { @@ -40,6 +42,8 @@ extern "C" { } #endif +#include "FreeTypeGX.h" + extern "C" { #include "types.h" extern int cleanSFMDATA(); @@ -53,21 +57,26 @@ unsigned char * nesrom = NULL; int ConfigRequested = 0; int ShutdownRequested = 0; int ResetRequested = 0; +int ExitRequested = 0; char appPath[1024]; +FreeTypeGX *fontSystem; uint8 *xbsave=NULL; int frameskip = 0; -extern bool romLoaded; - /**************************************************************************** * Shutdown / Reboot / Exit ***************************************************************************/ static void ExitCleanup() { +#ifdef HW_RVL + ShutoffRumble(); +#endif + ShutdownAudio(); + StopGX(); + LWP_SuspendThread (devicethread); UnmountAllFAT(); - CloseShare(); #ifdef HW_RVL DI_Close(); @@ -80,27 +89,32 @@ static void ExitCleanup() void (*PSOReload) () = (void (*)()) 0x80001800; #endif -void Reboot() +void ExitApp() { ExitCleanup(); -#ifdef HW_RVL - SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); -#else - #define SOFTRESET_ADR ((volatile u32*)0xCC003024) - *SOFTRESET_ADR = 0x00000000; -#endif -} -void ExitToLoader() -{ - ExitCleanup(); - // Exit to Loader - #ifdef HW_RVL - exit(0); - #else // gamecube - if (psoid[0] == PSOSDLOADID) - PSOReload (); - #endif + if(GCSettings.ExitAction == 0) // Exit to Loader + { + #ifdef HW_RVL + exit(0); + #else + if (psoid[0] == PSOSDLOADID) + PSOReload (); + #endif + } + else if(GCSettings.ExitAction == 1) // Exit to Menu + { + #ifdef HW_RVL + SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); + #else + #define SOFTRESET_ADR ((volatile u32*)0xCC003024) + *SOFTRESET_ADR = 0x00000000; + #endif + } + else // Shutdown Wii + { + SYS_ResetSystem(SYS_POWEROFF, 0, 0); + } } #ifdef HW_RVL @@ -182,7 +196,6 @@ int main(int argc, char *argv[]) #endif #ifdef HW_RVL - DI_Close(); DI_Init(); // first #endif @@ -194,13 +207,13 @@ int main(int argc, char *argv[]) WPAD_Init(); #endif - InitGCVideo (); + InitGCVideo (); // Initialise video ResetVideo_Menu (); // change to menu video mode #ifdef HW_RVL // read wiimote accelerometer and IR data WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR); - WPAD_SetVRes(WPAD_CHAN_ALL,640,480); + WPAD_SetVRes(WPAD_CHAN_ALL, screenwidth, screenheight); // Wii Power/Reset buttons WPAD_SetPowerButtonCallback((WPADShutdownCallback)ShutdownCB); @@ -208,71 +221,61 @@ int main(int argc, char *argv[]) SYS_SetResetCallback(ResetCB); #endif - // Initialise FreeType - if (FT_Init ()) - { - printf ("Cannot initialise font subsystem!\n"); - while (1); - } - - InitialiseAudio(); - - // Initialize libFAT for SD and USB - MountAllFAT(); - // Initialize DVD subsystem (GameCube only) #ifdef HW_DOL DVD_Init (); #endif - // allocate memory to store rom - nesrom = (unsigned char *)memalign(32,1024*1024*3); // 3 MB should be plenty - - /*** Minimal Emulation Loop ***/ - if ( !FCEUI_Initialize() ) - { - WaitPrompt("Unable to initialize FCE Ultra\n"); - ExitToLoader(); - } - - FCEUI_SetGameGenie(0); // 0 - OFF, 1 - ON - - memset(FDSBIOS, 0, sizeof(FDSBIOS)); // clear FDS BIOS memory - cleanSFMDATA(); // clear state data - - // Set defaults - DefaultSettings(); - // store path app was loaded from sprintf(appPath, "fceugx"); if(argc > 0 && argv[0] != NULL) CreateAppPath(argv[0]); - int selectedMenu = -1; + MountAllFAT(); // Initialize libFAT for SD and USB - // Load preferences - if(!LoadPrefs()) - { - WaitPrompt("Preferences reset - check settings!"); - selectedMenu = 1; // change to preferences menu - } + // Audio + InitialiseAudio(); + + // Initialize font system + fontSystem = new FreeTypeGX(); + fontSystem->loadFont(font_ttf, font_ttf_size, 0); + fontSystem->setCompatibilityMode(FTGX_COMPATIBILITY_DEFAULT_TEVOP_GX_PASSCLR | FTGX_COMPATIBILITY_DEFAULT_VTXDESC_GX_NONE); + + InitGUIThreads(); + + DefaultSettings(); // Set defaults + + // allocate memory to store rom + nesrom = (unsigned char *)memalign(32,1024*1024*3); // 3 MB should be plenty + + /*** Minimal Emulation Loop ***/ + if (!FCEUI_Initialize()) + ExitApp(); + + FCEUI_SetGameGenie(0); // 0 - OFF, 1 - ON + + memset(FDSBIOS, 0, sizeof(FDSBIOS)); // clear FDS BIOS memory + cleanSFMDATA(); // clear state data FCEUI_SetSoundQuality(1); // 0 - low, 1 - high, 2 - high (alt.) FCEUI_SetVidSystem(GCSettings.timing); // causes a small 'pop' in the audio while (1) // main loop { - #ifdef HW_RVL - if(ShutdownRequested) - ShutdownWii(); - #endif - - // go back to checking if devices were inserted/removed + // go back to checking if devices were inserted/removed // since we're entering the menu LWP_ResumeThread (devicethread); - MainMenu(selectedMenu); - selectedMenu = 2; // return to game menu from now on + ConfigRequested = 1; + SwitchAudioMode(1); + + if(!romLoaded) + MainMenu(MENU_GAMESELECTION); + else + MainMenu(MENU_GAME); + + ConfigRequested = 0; + SwitchAudioMode(0); // stop checking if devices were removed/inserted // since we're starting emulation again @@ -308,32 +311,15 @@ int main(int argc, char *argv[]) PowerNES(); // reset game ResetRequested = 0; } - if(ConfigRequested) { + TakeScreenshot(); ResetVideo_Menu(); - if (GCSettings.AutoSave == 1) - { - SaveRAM(GCSettings.SaveMethod, SILENT); - } - else if (GCSettings.AutoSave == 2) - { - SaveState(GCSettings.SaveMethod, SILENT); - } - else if(GCSettings.AutoSave == 3) - { - SaveRAM(GCSettings.SaveMethod, SILENT); - SaveState(GCSettings.SaveMethod, SILENT); - } - - // save zoom level - SavePrefs(SILENT); - ConfigRequested = 0; break; // leave emulation loop } - } - } + } // emulation loop + } // main loop } /**************************************************************************** diff --git a/source/ngc/fceugx.h b/source/ngc/fceugx.h index 7be9bbf..f0aaca8 100644 --- a/source/ngc/fceugx.h +++ b/source/ngc/fceugx.h @@ -40,6 +40,18 @@ enum { FILE_PREF }; +enum +{ + CTRL_PAD, + CTRL_ZAPPER, + CTRL_PAD2, + CTRL_PAD4, + CTRL_LENGTH +}; + +const char ctrlName[6][20] = +{ "NES Controller", "NES Zapper", "NES Controllers (2)", "NES Controllers (4)" }; + struct SGCSettings{ int AutoLoad; int AutoSave; @@ -54,7 +66,6 @@ struct SGCSettings{ char smbpwd[20]; char smbshare[20]; - int Zoom; // 0 - off, 1 - on float ZoomLevel; // zoom amount int VerifySaves; int render; // 0 - original, 1 - filtered, 2 - unfiltered @@ -62,21 +73,23 @@ struct SGCSettings{ int hideoverscan; int currpal; int timing; - int FourScore; - int zapper; + int Controller; int crosshair; int xshift; // video output shift int yshift; + int WiimoteOrientation; + int ExitAction; + int MusicVolume; + int SFXVolume; }; -void ExitToLoader(); -void Reboot(); +void ExitApp(); void ShutdownWii(); extern struct SGCSettings GCSettings; extern int ConfigRequested; extern int ShutdownRequested; +extern int ExitRequested; extern char appPath[]; extern int frameskip; -extern unsigned char * nesrom; #endif diff --git a/source/ngc/fceuload.cpp b/source/ngc/fceuload.cpp index a408c4e..c022bb2 100644 --- a/source/ngc/fceuload.cpp +++ b/source/ngc/fceuload.cpp @@ -2,7 +2,7 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * * fceload.c * @@ -37,9 +37,9 @@ extern uint8 FDSBIOS[8192]; #include "gcaudio.h" #include "common.h" #include "pad.h" -#include "menudraw.h" +#include "menu.h" #include "fileop.h" -#include "filesel.h" +#include "filebrowser.h" bool romLoaded = false; @@ -76,88 +76,88 @@ static void MakeFCEUFile(char * membuffer, int length) int GCMemROM(int method, int size) { - ResetGameLoaded(); + ResetGameLoaded(); - /*** Allocate and clear GameInfo ***/ + /*** Allocate and clear GameInfo ***/ - FCEUGameInfo = (FCEUGI *)memalign(32,sizeof(FCEUGI)); - memset(FCEUGameInfo, 0, sizeof(FCEUGI)); + FCEUGameInfo = (FCEUGI *) memalign(32, sizeof(FCEUGI)); + memset(FCEUGameInfo, 0, sizeof(FCEUGI)); - /*** Set some default values ***/ - FCEUGameInfo->soundchan = 1; - FCEUGameInfo->soundrate = SAMPLERATE; - FCEUGameInfo->name=0; - FCEUGameInfo->type=GIT_CART; - FCEUGameInfo->vidsys=GIV_USER; - FCEUGameInfo->input[0]=FCEUGameInfo->input[1]=-1; - FCEUGameInfo->inputfc=-1; - FCEUGameInfo->cspecial=0; + /*** Set some default values ***/ + FCEUGameInfo->soundchan = 1; + FCEUGameInfo->soundrate = SAMPLERATE; + FCEUGameInfo->name = 0; + FCEUGameInfo->type = GIT_CART; + FCEUGameInfo->vidsys = GIV_USER; + FCEUGameInfo->input[0] = FCEUGameInfo->input[1] = -1; + FCEUGameInfo->inputfc = -1; + FCEUGameInfo->cspecial = 0; - /*** Set internal sound information ***/ - FCEUI_Sound(SAMPLERATE); - FCEUI_SetSoundVolume(100); // 0-100 - FCEUI_SetLowPass(0); + /*** Set internal sound information ***/ + FCEUI_Sound(SAMPLERATE); + FCEUI_SetSoundVolume(100); // 0-100 + FCEUI_SetLowPass(0); - InitialisePads(); + InitialisePads(); - MakeFCEUFile((char *)nesrom, size); + MakeFCEUFile((char *) nesrom, size); - nesGameType = 0; + nesGameType = 0; - if(iNESLoad(NULL, fceufp)) + if (iNESLoad(NULL, fceufp)) nesGameType = 1; - else if(UNIFLoad(NULL,fceufp)) + else if (UNIFLoad(NULL, fceufp)) nesGameType = 2; - else if(NSFLoad(fceufp)) + else if (NSFLoad(fceufp)) nesGameType = 3; else { // read FDS BIOS into FDSBIOS - should be 8192 bytes - if(FDSBIOS[1] == 0) + if (FDSBIOS[1] == 0) { int biosSize = 0; - char * tmpbuffer = (char *)memalign(32,64 * 1024); + char * tmpbuffer = (char *) memalign(32, 64 * 1024); char filepath[1024]; - if(MakeFilePath(filepath, FILE_FDSBIOS, method)) + if (MakeFilePath(filepath, FILE_FDSBIOS, method)) { - biosSize = LoadFile (tmpbuffer, filepath, 0, method, SILENT); + biosSize = LoadFile(tmpbuffer, filepath, 0, method, SILENT); } - if(biosSize == 8192) + if (biosSize == 8192) { memcpy(FDSBIOS, tmpbuffer, 8192); } else { - if(biosSize > 0) - WaitPrompt("FDS BIOS file is invalid!"); + if (biosSize > 0) + ErrorPrompt("FDS BIOS file is invalid!"); return 0; // BIOS not loaded, do not load game } free(tmpbuffer); } // load game - if(FDSLoad(NULL,fceufp)) + if (FDSLoad(NULL, fceufp)) nesGameType = 4; } - if (nesGameType > 0) - { - FCEU_ResetVidSys(); - PowerNES(); - FCEU_ResetPalette(); - FCEU_ResetMessages(); // Save state, status messages, etc. - SetSoundVariables(); - ResetAudio(); - romLoaded = true; - return 1; - } - else - { - WaitPrompt("Invalid game file!"); - romLoaded = false; - return 0; - } + if (nesGameType > 0) + { + FCEU_ResetVidSys(); + PowerNES(); + FCEU_ResetPalette(); + FCEU_ResetMessages(); // Save state, status messages, etc. + SetSoundVariables(); + ResetAudio(); + romLoaded = true; + return 1; + } + else + { + ErrorPrompt("Invalid game file!"); + romLoaded = false; + return 0; + } } diff --git a/source/ngc/fceuload.h b/source/ngc/fceuload.h index 6b44b80..fc24981 100644 --- a/source/ngc/fceuload.h +++ b/source/ngc/fceuload.h @@ -2,7 +2,7 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * * fceuload.h * @@ -10,3 +10,4 @@ ****************************************************************************/ int GCMemROM(int method, int size); +extern bool romLoaded; diff --git a/source/ngc/fceuram.cpp b/source/ngc/fceuram.cpp index aa1accd..8f7f4ae 100644 --- a/source/ngc/fceuram.cpp +++ b/source/ngc/fceuram.cpp @@ -2,9 +2,9 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * - * fceustate.c + * fceustate.cpp * * Memory Based Load/Save RAM Manager * @@ -20,10 +20,9 @@ #include #include -#include "images/saveicon.h" #include "fceugx.h" -#include "menudraw.h" -#include "filesel.h" +#include "menu.h" +#include "filebrowser.h" #include "memcardop.h" #include "fileop.h" @@ -42,34 +41,9 @@ extern CartInfo UNIFCart; static u32 NGCFCEU_GameSave(CartInfo *LocalHWInfo, int operation, int method) { u32 offset = 0; - char comment[2][32]; - memset(comment, 0, 64); if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0]) { - // add save icon and comments for Memory Card saves - if(operation == 0 && - (method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)) - { - // Copy in save icon - memcpy(savebuffer, saveicon, sizeof(saveicon)); - offset += sizeof(saveicon); - - // And the comments - sprintf (comment[0], "%s RAM", APPNAME); - strncpy (comment[1],romFilename,31); // we only have 32 chars to work with! - comment[1][31] = 0; - memcpy(savebuffer+offset, comment, 64); - offset += 64; - } - // skip save icon and comments for Memory Card saves - else if(operation == 1 && - (method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)) - { - offset += sizeof(saveicon); - offset += 64; // sizeof prefscomment - } - int x; for(x=0;x<4;x++) @@ -87,28 +61,25 @@ static u32 NGCFCEU_GameSave(CartInfo *LocalHWInfo, int operation, int method) return offset; } -bool SaveRAM (int method, bool silent) +bool SaveRAM (char * filepath, int method, bool silent) { bool retval = false; - char filepath[1024]; int datasize = 0; int offset = 0; if(nesGameType == 4) { if(!silent) - WaitPrompt("Saving is not available for FDS games!"); + InfoPrompt("RAM saving is not available for FDS games!"); return false; } if(method == METHOD_AUTO) method = autoSaveMethod(silent); - if (!MakeFilePath(filepath, FILE_RAM, method)) + if(method == METHOD_AUTO) return false; - ShowAction ("Saving..."); - AllocSaveBuffer (); // save game save to savebuffer @@ -119,45 +90,65 @@ bool SaveRAM (int method, bool silent) if (datasize) { + if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) + { + // Set the comments + char comments[2][32]; + memset(comments, 0, 64); + sprintf (comments[0], "%s RAM", APPNAME); + snprintf (comments[1], 32, romFilename); + SetMCSaveComments(comments); + } + offset = SaveFile(filepath, datasize, method, silent); if (offset > 0) { - if ( !silent ) - WaitPrompt("Save successful"); + if (!silent) + InfoPrompt("Save successful"); retval = true; } } else { - if ( !silent ) - WaitPrompt("No data to save!"); + if (!silent) + InfoPrompt("No data to save!"); } FreeSaveBuffer (); return retval; } -bool LoadRAM (int method, bool silent) +bool +SaveRAMAuto (int method, bool silent) { + if(method == METHOD_AUTO) + method = autoSaveMethod(silent); + + if(method == METHOD_AUTO) + return false; + char filepath[1024]; + + if(!MakeFilePath(filepath, FILE_RAM, method, romFilename, 0)) + return false; + + return SaveRAM(filepath, method, silent); +} + +bool LoadRAM (char * filepath, int method, bool silent) +{ int offset = 0; bool retval = false; - if(nesGameType == 4) - { - if(!silent) - WaitPrompt("Saving is not available for FDS games!"); + if(nesGameType == 4) // RAM saves don't exist for FDS games return false; - } if(method == METHOD_AUTO) method = autoSaveMethod(silent); // we use 'Save' because we need R/W - if (!MakeFilePath(filepath, FILE_RAM, method)) + if(method == METHOD_AUTO) return false; - ShowAction ("Loading..."); - AllocSaveBuffer (); offset = LoadFile(filepath, method, silent); @@ -176,8 +167,25 @@ bool LoadRAM (int method, bool silent) { // if we reached here, nothing was done! if(!silent) - WaitPrompt ("Save file not found"); + InfoPrompt ("Save file not found"); } FreeSaveBuffer (); return retval; } + +bool +LoadRAMAuto (int method, bool silent) +{ + if(method == METHOD_AUTO) + method = autoSaveMethod(silent); + + if(method == METHOD_AUTO) + return false; + + char filepath[1024]; + + if(!MakeFilePath(filepath, FILE_RAM, method, romFilename, 0)) + return false; + + return LoadRAM(filepath, method, silent); +} diff --git a/source/ngc/fceuram.h b/source/ngc/fceuram.h index af44dc1..dafad30 100644 --- a/source/ngc/fceuram.h +++ b/source/ngc/fceuram.h @@ -2,12 +2,14 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * * fceuram.h * * Memory Based Load/Save RAM Manager ****************************************************************************/ -bool SaveRAM (int method, bool silent); -bool LoadRAM (int method, bool silent); +bool SaveRAM (char * filepath, int method, bool silent); +bool SaveRAMAuto (int method, bool silent); +bool LoadRAM (char * filepath, int method, bool silent); +bool LoadRAMAuto (int method, bool silent); diff --git a/source/ngc/fceustate.cpp b/source/ngc/fceustate.cpp index 8e82a84..6fb21d5 100644 --- a/source/ngc/fceustate.cpp +++ b/source/ngc/fceustate.cpp @@ -2,9 +2,9 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * - * fceustate.c + * fceustate.cpp * * Memory Based Load/Save State Manager * @@ -21,10 +21,9 @@ #include "state.h" #include "x6502.h" -#include "images/saveicon.h" #include "fceugx.h" -#include "menudraw.h" -#include "filesel.h" +#include "menu.h" +#include "filebrowser.h" #include "memcardop.h" #include "fileop.h" @@ -57,33 +56,33 @@ static int sboffset; // Used as a basic fileptr /*** Open a file ***/ static void memopen() { - sboffset = 0; + sboffset = 0; } /*** Write to the file ***/ static void memfwrite(void *buffer, int len) { - if ((sboffset + len) > SAVEBUFFERSIZE) - WaitPrompt("Buffer Exceeded"); + if ((sboffset + len) > SAVEBUFFERSIZE) + ErrorPrompt("Buffer Exceeded"); - if (len > 0) - { - memcpy(&savebuffer[sboffset], buffer, len); - sboffset += len; - } + if (len > 0) + { + memcpy(&savebuffer[sboffset], buffer, len); + sboffset += len; + } } /*** Read from a file ***/ static void memfread(void *buffer, int len) { - if ( (sboffset + len) > SAVEBUFFERSIZE) - WaitPrompt("Buffer exceeded"); + if ((sboffset + len) > SAVEBUFFERSIZE) + ErrorPrompt("Buffer exceeded"); - if (len > 0) - { - memcpy(buffer, &savebuffer[sboffset], len); - sboffset += len; - } + if (len > 0) + { + memcpy(buffer, &savebuffer[sboffset], len); + sboffset += len; + } } /**************************************************************************** @@ -124,14 +123,14 @@ static int GCReadChunk(int chunkid, SFORMAT *sf) } else { - WaitPrompt("Bad chunk link"); + ErrorPrompt("Bad chunk link"); return 0; } } else { sprintf(info, "No Sync %s %s", chunk, sf->desc); - WaitPrompt(info); + ErrorPrompt(info); return 0; } sf++; @@ -155,13 +154,6 @@ static int GCFCEUSS_Load(int method) { memopen(); // reset file pointer - // skip save icon and comments for Memory Card saves - if (method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) - { - sboffset += sizeof(saveicon); - sboffset += 64; // sizeof prefscomment - } - sboffset += 16; // skip FCEU header // Now read the chunks back @@ -201,47 +193,48 @@ static int GCFCEUSS_Load(int method) ****************************************************************************/ static int GCSaveChunk(int chunkid, SFORMAT *sf) { - int chnkstart; - int csize = 0; - int chsize = 0; - char chunk[] = "CHNK"; + int chnkstart; + int csize = 0; + int chsize = 0; + char chunk[] = "CHNK"; - /*** Add chunk marker ***/ - memfwrite(&chunk, 4); - memfwrite(&chunkid, 4); - chnkstart = sboffset; /*** Save ptr ***/ - sboffset += 4; /*** Space for length ***/ - csize += 12; + /*** Add chunk marker ***/ + memfwrite(&chunk, 4); + memfwrite(&chunkid, 4); + chnkstart = sboffset; /*** Save ptr ***/ + sboffset += 4; /*** Space for length ***/ + csize += 12; - /*** Now run through this structure ***/ - while (sf->v) { - /*** Check that there is a decription ***/ - if ( sf->desc == NULL) - break; + /*** Now run through this structure ***/ + while (sf->v) + { + /*** Check that there is a decription ***/ + if (sf->desc == NULL) + break; - /*** Write out the description ***/ - memfwrite( sf->desc, 4); + /*** Write out the description ***/ + memfwrite(sf->desc, 4); - /*** Write the length of this chunk ***/ - chsize = ( sf->s & (~RLSB) ); - memfwrite( &chsize, 4); + /*** Write the length of this chunk ***/ + chsize = (sf->s & (~RLSB)); + memfwrite(&chsize, 4); - if ( chsize > 0 ) - { - /*** Write the actual data ***/ - memfwrite( sf->v, chsize ); - } + if (chsize > 0) + { + /*** Write the actual data ***/ + memfwrite(sf->v, chsize); + } - csize += 8; - csize += chsize; + csize += 8; + csize += chsize; - sf++; - } + sf++; + } - /*** Update CHNK length ***/ - memcpy(&savebuffer[chnkstart], &csize, 4); + /*** Update CHNK length ***/ + memcpy(&savebuffer[chnkstart], &csize, 4); - return csize; + return csize; } /**************************************************************************** @@ -265,21 +258,6 @@ static int GCFCEUSS_Save(int method) memopen(); // Reset Memory File - // add save icon and comments for Memory Card saves - if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) - { - // Copy in save icon - memfwrite((void *)&saveicon, sizeof(saveicon)); - totalsize += sizeof(saveicon); - - // And the comments - sprintf (comment[0], "%s State", APPNAME); - strncpy (comment[1],romFilename,31); // we only have 32 chars to work with! - comment[1][31] = 0; - memfwrite(&comment[0], 64); - totalsize += 64; - } - // Add version ID int mcversion = 0x981211; memcpy(&header[8], &mcversion, 4); @@ -313,33 +291,40 @@ static int GCFCEUSS_Save(int method) return totalsize; } -bool SaveState (int method, bool silent) +bool SaveState (char * filepath, int method, bool silent) { bool retval = false; - char filepath[1024]; int datasize; int offset = 0; if(method == METHOD_AUTO) method = autoSaveMethod(silent); - if (!MakeFilePath(filepath, FILE_STATE, method)) + if(method == METHOD_AUTO) return false; - ShowAction ("Saving..."); - AllocSaveBuffer (); datasize = GCFCEUSS_Save(method); if (datasize) { + if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) + { + // Set the comments + char comments[2][32]; + memset(comments, 0, 64); + sprintf (comments[0], "%s State", APPNAME); + snprintf (comments[1], 32, romFilename); + SetMCSaveComments(comments); + } + offset = SaveFile(filepath, datasize, method, silent); if (offset > 0) { if ( !silent ) - WaitPrompt("Save successful"); + InfoPrompt("Save successful"); retval = true; } } @@ -347,20 +332,34 @@ bool SaveState (int method, bool silent) return retval; } -bool LoadState (int method, bool silent) +bool +SaveStateAuto (int method, bool silent) { + if(method == METHOD_AUTO) + method = autoSaveMethod(silent); + + if(method == METHOD_AUTO) + return false; + char filepath[1024]; + + if(!MakeFilePath(filepath, FILE_STATE, method, romFilename, 0)) + return false; + + return SaveState(filepath, method, silent); +} + +bool LoadState (char * filepath, int method, bool silent) +{ int offset = 0; bool retval = false; if(method == METHOD_AUTO) method = autoSaveMethod(silent); // we use 'Save' because we need R/W - if (!MakeFilePath(filepath, FILE_STATE, method)) + if(method == METHOD_AUTO) return false; - ShowAction ("Loading..."); - AllocSaveBuffer (); offset = LoadFile(filepath, method, silent); @@ -374,8 +373,25 @@ bool LoadState (int method, bool silent) { // if we reached here, nothing was done! if(!silent) - WaitPrompt ("State file not found"); + ErrorPrompt ("State file not found"); } FreeSaveBuffer (); return retval; } + +bool +LoadStateAuto (int method, bool silent) +{ + if(method == METHOD_AUTO) + method = autoSaveMethod(silent); + + if(method == METHOD_AUTO) + return false; + + char filepath[1024]; + + if(!MakeFilePath(filepath, FILE_STATE, method, romFilename, 0)) + return false; + + return LoadState(filepath, method, silent); +} diff --git a/source/ngc/fceustate.h b/source/ngc/fceustate.h index 9470255..9165f45 100644 --- a/source/ngc/fceustate.h +++ b/source/ngc/fceustate.h @@ -2,12 +2,14 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * * fceustate.h * * Memory Based Load/Save State Manager ****************************************************************************/ -bool SaveState (int method, bool silent); -bool LoadState (int method, bool silent); +bool SaveState (char * filepath, int method, bool silent); +bool SaveStateAuto (int method, bool silent); +bool LoadState (char * filepath, int method, bool silent); +bool LoadStateAuto (int method, bool silent); diff --git a/source/ngc/filebrowser.cpp b/source/ngc/filebrowser.cpp index 4b1b045..ecdf550 100644 --- a/source/ngc/filebrowser.cpp +++ b/source/ngc/filebrowser.cpp @@ -2,9 +2,9 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * - * filesel.c + * filebrowser.cpp * * Generic file routines - reading, writing, browsing ****************************************************************************/ @@ -22,14 +22,16 @@ #include "common.h" #include "fceugx.h" #include "dvd.h" -#include "menudraw.h" -#include "filesel.h" +#include "menu.h" +#include "filebrowser.h" #include "networkop.h" #include "fileop.h" #include "memcardop.h" #include "pad.h" #include "fceuload.h" #include "gcunzip.h" +#include "fceuram.h" +#include "fceustate.h" BROWSERINFO browser; BROWSERENTRY * browserList = NULL; // list of files/folders in browser @@ -50,7 +52,7 @@ int autoLoadMethod() { ShowAction ("Attempting to determine load method..."); - int method = 0; + int method = METHOD_AUTO; if(ChangeInterface(METHOD_SD, SILENT)) method = METHOD_SD; @@ -61,10 +63,11 @@ int autoLoadMethod() else if(ChangeInterface(METHOD_SMB, SILENT)) method = METHOD_SMB; else - WaitPrompt("Unable to auto-determine load method!"); + ErrorPrompt("Unable to auto-determine load method!"); if(GCSettings.LoadMethod == METHOD_AUTO) GCSettings.LoadMethod = method; // save method found for later use + CancelAction(); return method; } @@ -78,23 +81,25 @@ int autoSaveMethod(bool silent) if(!silent) ShowAction ("Attempting to determine save method..."); - int method = 0; + int method = METHOD_AUTO; if(ChangeInterface(METHOD_SD, SILENT)) method = METHOD_SD; else if(ChangeInterface(METHOD_USB, SILENT)) method = METHOD_USB; - else if(TestCard(CARD_SLOTA, SILENT)) + else if(ChangeInterface(METHOD_MC_SLOTA, SILENT)) method = METHOD_MC_SLOTA; - else if(TestCard(CARD_SLOTB, SILENT)) + else if(ChangeInterface(METHOD_MC_SLOTB, SILENT)) method = METHOD_MC_SLOTB; else if(ChangeInterface(METHOD_SMB, SILENT)) method = METHOD_SMB; else if(!silent) - WaitPrompt("Unable to auto-determine save method!"); + ErrorPrompt("Unable to auto-determine save method!"); if(GCSettings.SaveMethod == METHOD_AUTO) GCSettings.SaveMethod = method; // save method found for later use + + CancelAction(); return method; } @@ -104,7 +109,9 @@ int autoSaveMethod(bool silent) ***************************************************************************/ void ResetBrowser() { - browser.selIndex = browser.pageIndex = 0; + browser.numEntries = 0; + browser.selIndex = 0; + browser.pageIndex = 0; // Clear any existing values if(browserList != NULL) @@ -166,16 +173,17 @@ int UpdateDirName(int method) } else { - WaitPrompt("Directory name is too long!"); + ErrorPrompt("Directory name is too long!"); return -1; } } } -bool MakeFilePath(char filepath[], int type, int method) +bool MakeFilePath(char filepath[], int type, int method, char * filename, int filenum) { char file[512]; char folder[1024]; + char ext[4]; char temppath[MAXPATHLEN]; if(type == FILE_ROM) @@ -183,7 +191,7 @@ bool MakeFilePath(char filepath[], int type, int method) // Check path length if ((strlen(browser.dir)+1+strlen(browserList[browser.selIndex].filename)) >= MAXPATHLEN) { - WaitPrompt("Maximum filepath length reached!"); + ErrorPrompt("Maximum filepath length reached!"); filepath[0] = 0; return false; } @@ -197,13 +205,33 @@ bool MakeFilePath(char filepath[], int type, int method) switch(type) { case FILE_RAM: - sprintf(folder, GCSettings.SaveFolder); - sprintf(file, "%s.sav", romFilename); - break; case FILE_STATE: sprintf(folder, GCSettings.SaveFolder); - sprintf(file, "%s.fcs", romFilename); + + if(type == FILE_RAM) sprintf(ext, "sav"); + else sprintf(ext, "fcs"); + + if(filenum >= 0) + { + if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) + { + filename[26] = 0; // truncate filename + sprintf(file, "%s%i.%s", filename, filenum, ext); + } + else + { + if(filenum == 0) + sprintf(file, "%s Auto.%s", filename, ext); + else + sprintf(file, "%s %i.%s", filename, filenum, ext); + } + } + else + { + sprintf(file, "%s", filename); + } break; + case FILE_FDSBIOS: sprintf(folder, GCSettings.LoadFolder); sprintf(file, "disksys.rom"); @@ -225,7 +253,7 @@ bool MakeFilePath(char filepath[], int type, int method) break; } } - strcpy(filepath, temppath); + strncpy(filepath, temppath, MAXPATHLEN); return true; } @@ -271,7 +299,7 @@ bool IsValidROM(int method) if(browserList[browser.selIndex].length < (1024*8) || browserList[browser.selIndex].length > (1024*1024*3)) { - WaitPrompt("Invalid file size!"); + ErrorPrompt("Invalid file size!"); return false; } @@ -310,7 +338,7 @@ bool IsValidROM(int method) } } } - WaitPrompt("Unknown file type!"); + ErrorPrompt("Unknown file type!"); return false; } @@ -319,7 +347,6 @@ bool IsValidROM(int method) * * Checks if the specified file is a 7z ***************************************************************************/ - bool IsSz() { if (strlen(browserList[browser.selIndex].filename) > 4) @@ -337,352 +364,178 @@ bool IsSz() * StripExt * * Strips an extension from a filename -****************************************************************************/ - + ***************************************************************************/ void StripExt(char* returnstring, char * inputstring) { char* loc_dot; - strcpy (returnstring, inputstring); + strncpy (returnstring, inputstring, 255); + + if(inputstring == NULL || strlen(inputstring) < 4) + return; + loc_dot = strrchr(returnstring,'.'); if (loc_dot != NULL) - *loc_dot = '\0'; // strip file extension + *loc_dot = 0; // strip file extension } /**************************************************************************** - * FileSelector + * BrowserLoadSz * - * Let user select a file from the listing -****************************************************************************/ -int FileSelector (int method) + * Opens the selected 7z file, and parses a listing of the files within + ***************************************************************************/ +int BrowserLoadSz(int method) { - u32 p = 0; - u32 wp = 0; - u32 ph = 0; - u32 wh = 0; - signed char gc_ay = 0; - signed char gc_sx = 0; - signed char wm_ay = 0; - signed char wm_sx = 0; + char filepath[MAXPATHLEN]; + memset(filepath, 0, MAXPATHLEN); - int haverom = 0; - int redraw = 1; - int selectit = 0; + // we'll store the 7z filepath for extraction later + if(!MakeFilePath(szpath, FILE_ROM, method)) + return 0; - int scroll_delay = 0; - bool move_selection = 0; - #define SCROLL_INITIAL_DELAY 15 - #define SCROLL_LOOP_DELAY 2 + // add device to filepath + sprintf(filepath, "%s%s", rootdir, szpath); + memcpy(szpath, filepath, MAXPATHLEN); - while (haverom == 0) - { - if (redraw) - ShowFiles (browserList, browser.numEntries, browser.pageIndex, browser.selIndex); - redraw = 0; + int szfiles = SzParse(szpath, method); + if(szfiles) + { + browser.numEntries = szfiles; + inSz = true; + } + else + ErrorPrompt("Error opening archive!"); - VIDEO_WaitVSync(); // slow things down a bit so we don't overread the pads + return szfiles; +} - gc_ay = PAD_StickY (0); - gc_sx = PAD_SubStickX (0); +/**************************************************************************** + * BrowserLoadFile + * + * Loads the selected ROM + ***************************************************************************/ +int BrowserLoadFile(int method) +{ + char filepath[1024]; + int filesize = 0; + romLoaded = false; - p = PAD_ButtonsDown (0); - ph = PAD_ButtonsHeld (0); -#ifdef HW_RVL - wm_ay = WPAD_StickY (0, 0); - wm_sx = WPAD_StickX (0, 1); + // check that this is a valid ROM + if(!IsValidROM(method)) + goto done; - wp = WPAD_ButtonsDown (0); - wh = WPAD_ButtonsHeld (0); -#endif + // store the filename (w/o ext) - used for ram/state naming + StripExt(romFilename, browserList[browser.selIndex].filename); - /*** Check for exit combo ***/ - if ( (gc_sx < -70) || (wm_sx < -70) || (wp & WPAD_BUTTON_HOME) || (wp & WPAD_CLASSIC_BUTTON_HOME) ) - return 0; + if(!inSz) + { + if(!MakeFilePath(filepath, FILE_ROM, method)) + goto done; - /*** Check buttons, perform actions ***/ - if ( (p & PAD_BUTTON_A) || selectit || (wp & (WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A)) ) + filesize = LoadFile ((char *)nesrom, filepath, browserList[browser.selIndex].length, method, NOTSILENT); + } + else + { + switch (method) { - if ( selectit ) - selectit = 0; - - if (browserList[browser.selIndex].isdir) // This is directory - { - /* update current directory and set new entry list if directory has changed */ - - int status; - - if(inSz && browser.selIndex == 0) // inside a 7z, requesting to leave - { - if(method == METHOD_DVD) - SetDVDdirectory(browserList[0].offset, browserList[0].length); - inSz = false; - status = 1; - SzClose(); - } - else - { - status = UpdateDirName(method); - } - - if (status == 1) // ok, open directory - { - switch (method) - { - case METHOD_DVD: - browser.numEntries = ParseDVDdirectory(); - break; - - default: - browser.numEntries = ParseDirectory(); - break; - } - - if (!browser.numEntries) - { - WaitPrompt ("Error reading directory!"); - haverom = 1; // quit menu - } - } - else if (status == -1) // directory name too long - { - return 0; // quit menu - } - } - else // this is a file - { - // 7z file - let's open it up to select a file inside - if(IsSz()) - { - // we'll store the 7z filepath for extraction later - if(!MakeFilePath(szpath, FILE_ROM, method)) - return 0; - - // add device to filepath - char fullpath[1024]; - sprintf(fullpath, "%s%s", rootdir, szpath); - strcpy(szpath, fullpath); - - int szfiles = SzParse(szpath, method); - if(szfiles) - { - browser.numEntries = szfiles; - inSz = true; - } - else - WaitPrompt("Error opening archive!"); - } - else - { - // check that this is a valid ROM - if(!IsValidROM(method)) - return 0; - - // store the filename (w/o ext) - used for state saving - StripExt(romFilename, browserList[browser.selIndex].filename); - - ShowAction ("Loading..."); - - int size = 0; - - if(!inSz) - { - char filepath[1024]; - - if(!MakeFilePath(filepath, FILE_ROM, method)) - return 0; - - size = LoadFile((char *)nesrom, filepath, browserList[browser.selIndex].length, method, NOTSILENT); - } - else - { - switch (method) - { - case METHOD_DVD: - size = SzExtractFile(browserList[browser.selIndex].offset, nesrom); - break; - default: - size = LoadSzFile(szpath, nesrom); - break; - } - } - - inSz = false; - - if (size > 0) - { - if(GCMemROM(method, size) > 0) - return 1; - else - return 0; - } - else - { - WaitPrompt("Error loading ROM!"); - return 0; - } - } - } - redraw = 1; - } // End of A - if ((p & PAD_BUTTON_B) - || (wp & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B))) - { - while ((PAD_ButtonsDown(0) & PAD_BUTTON_B) -#ifdef HW_RVL - || (WPAD_ButtonsDown(0) & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)) -#endif - ) - VIDEO_WaitVSync(); - if (strcmp(browserList[0].filename, "..") == 0) - { - browser.selIndex = 0; - selectit = 1; - } - else if (strcmp(browserList[1].filename, "..") == 0) - { - browser.selIndex = selectit = 1; - } - else - { - return 0; - } - } // End of B - if (((p | ph) & PAD_BUTTON_DOWN) || ((wp | wh) & (WPAD_BUTTON_DOWN - | WPAD_CLASSIC_BUTTON_DOWN)) || (gc_ay < -PADCAL) || (wm_ay - < -PADCAL)) - { - if ((p & PAD_BUTTON_DOWN) || (wp & (WPAD_BUTTON_DOWN - | WPAD_CLASSIC_BUTTON_DOWN))) - { /*** Button just pressed ***/ - scroll_delay = SCROLL_INITIAL_DELAY; // reset scroll delay. - move_selection = 1; //continue (move selection) - } - else if (scroll_delay == 0) - { /*** Button is held ***/ - scroll_delay = SCROLL_LOOP_DELAY; - move_selection = 1; //continue (move selection) - } - else - { - scroll_delay--; // wait - } - - if (move_selection) - { - browser.selIndex++; - if (browser.selIndex == browser.numEntries) - browser.selIndex = browser.pageIndex = 0; - if ((browser.selIndex - browser.pageIndex) >= PAGESIZE) - browser.pageIndex += PAGESIZE; - redraw = 1; - move_selection = 0; - } - } // End of down - if (((p | ph) & PAD_BUTTON_UP) || ((wp | wh) & (WPAD_BUTTON_UP - | WPAD_CLASSIC_BUTTON_UP)) || (gc_ay > PADCAL) || (wm_ay - > PADCAL)) - { - if ((p & PAD_BUTTON_UP) || (wp & (WPAD_BUTTON_UP - | WPAD_CLASSIC_BUTTON_UP))) - { /*** Button just pressed***/ - scroll_delay = SCROLL_INITIAL_DELAY; // reset scroll delay. - move_selection = 1; //continue (move selection) - } - else if (scroll_delay == 0) - { /*** Button is held ***/ - scroll_delay = SCROLL_LOOP_DELAY; - move_selection = 1; //continue (move selection) - } - else - { - scroll_delay--; // wait - } - - if (move_selection) - { - browser.selIndex--; - if (browser.selIndex < 0) - { - browser.selIndex = browser.numEntries - 1; - browser.pageIndex = browser.selIndex - PAGESIZE + 1; - } - if (browser.selIndex < browser.pageIndex) - browser.pageIndex -= PAGESIZE; - if (browser.pageIndex < 0) - browser.pageIndex = 0; - redraw = 1; - move_selection = 0; - } - } // End of Up - if ((p & PAD_BUTTON_LEFT) || (wp & (WPAD_BUTTON_LEFT - | WPAD_CLASSIC_BUTTON_LEFT))) - { - /*** Go back a page ***/ - browser.selIndex -= PAGESIZE; - if (browser.selIndex < 0) - { - browser.selIndex = browser.numEntries - 1; - browser.pageIndex = browser.selIndex - PAGESIZE + 1; - } - if (browser.selIndex < browser.pageIndex) - browser.pageIndex -= PAGESIZE; - if (browser.pageIndex < 0) - browser.pageIndex = 0; - redraw = 1; - } - if ((p & PAD_BUTTON_RIGHT) || (wp & (WPAD_BUTTON_RIGHT - | WPAD_CLASSIC_BUTTON_RIGHT))) - { - /*** Go forward a page ***/ - browser.selIndex += PAGESIZE; - if (browser.selIndex > browser.numEntries - 1) - browser.selIndex = browser.pageIndex = 0; - if ((browser.selIndex - browser.pageIndex) >= PAGESIZE) - browser.pageIndex += PAGESIZE; - redraw = 1; + case METHOD_DVD: + filesize = SzExtractFile(browserList[browser.selIndex].offset, nesrom); + break; + default: + filesize = LoadSzFile(szpath, nesrom); + break; } } - return 0; + inSz = false; + + if (filesize <= 0) + { + ErrorPrompt("Error loading ROM!"); + } + else + { + if(GCMemROM(method, filesize) > 0) + { + romLoaded = true; + + // load RAM or state + if (GCSettings.AutoLoad == 1) + LoadRAMAuto(GCSettings.SaveMethod, SILENT); + else if (GCSettings.AutoLoad == 2) + LoadStateAuto(GCSettings.SaveMethod, SILENT); + + ResetNES(); + ResetBrowser(); + } + } +done: + CancelAction(); + return romLoaded; +} + +/**************************************************************************** + * BrowserChangeFolder + * + * Update current directory and set new entry list if directory has changed + ***************************************************************************/ +int BrowserChangeFolder(int method) +{ + if(inSz && browser.selIndex == 0) // inside a 7z, requesting to leave + { + if(method == METHOD_DVD) + SetDVDdirectory(browserList[0].offset, browserList[0].length); + + inSz = false; + SzClose(); + } + + if(!UpdateDirName(method)) + return -1; + + switch (method) + { + case METHOD_DVD: + ParseDVDdirectory(); + break; + + default: + ParseDirectory(method); + break; + } + + if (!browser.numEntries) + { + ErrorPrompt("Error reading directory!"); + } + + return browser.numEntries; } /**************************************************************************** * OpenROM - * Opens device specified by method, displays a list of ROMS + * Displays a list of ROMS on load device ***************************************************************************/ - int -OpenROM (int method) +OpenGameList () { + int method = GCSettings.LoadMethod; + if(method == METHOD_AUTO) method = autoLoadMethod(); - if(ChangeInterface(method, NOTSILENT)) + // change current dir to roms directory + switch(method) { - // change current dir to roms directory - switch(method) - { - case METHOD_DVD: - browser.dir[0] = 0; - browser.numEntries = ParseDVDdirectory(); // Parse root directory - SwitchDVDFolder(GCSettings.LoadFolder); // switch to ROM folder - break; - default: - sprintf(browser.dir, "/%s", GCSettings.LoadFolder); - browser.numEntries = ParseDirectory(); // Parse root directory - break; - } - - if (browser.numEntries > 0) - { - // Select an entry - return FileSelector (method); - } - else - { - // no entries found - WaitPrompt ("No Files Found!"); - return 0; - } + case METHOD_DVD: + browser.dir[0] = 0; + if(MountDVD(NOTSILENT)) + if(ParseDVDdirectory()) // Parse root directory + SwitchDVDFolder(GCSettings.LoadFolder); // switch to ROM folder + break; + default: + sprintf(browser.dir, "/%s", GCSettings.LoadFolder); + ParseDirectory(method); // Parse root directory + break; } - return 0; + return browser.numEntries; } diff --git a/source/ngc/filebrowser.h b/source/ngc/filebrowser.h index 790b7f7..1e776f4 100644 --- a/source/ngc/filebrowser.h +++ b/source/ngc/filebrowser.h @@ -2,15 +2,15 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * - * filesel.h + * filebrowser.h * * Generic file routines - reading, writing, browsing ****************************************************************************/ -#ifndef _NGCFILESEL_ -#define _NGCFILESEL_ +#ifndef _FILEBROWSER_H_ +#define _FILEBROWSER_H_ #include @@ -29,6 +29,7 @@ typedef struct { u64 offset; // DVD offset unsigned int length; // file length + time_t mtime; // file modified time char isdir; // 0 - file, 1 - directory char filename[MAXJOLIET + 1]; // full filename char displayname[MAXDISPLAY + 1]; // name for browser display @@ -41,12 +42,17 @@ extern char rootdir[10]; extern char romFilename[]; extern int nesGameType; -bool MakeFilePath(char filepath[], int type, int method); -int OpenROM (int method); +bool MakeFilePath(char filepath[], int type, int method, char * filename = NULL, int filenum = -1); +int UpdateDirName(int method); +int OpenGameList(); int autoLoadMethod(); int autoSaveMethod(bool silent); int FileSortCallback(const void *f1, const void *f2); void StripExt(char* returnstring, char * inputstring); +bool IsSz(); void ResetBrowser(); +int BrowserLoadSz(int method); +int BrowserChangeFolder(int method); +int BrowserLoadFile(int method); #endif diff --git a/source/ngc/filelist.h b/source/ngc/filelist.h index 9e19c76..351416a 100644 --- a/source/ngc/filelist.h +++ b/source/ngc/filelist.h @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric January 2009 * diff --git a/source/ngc/fileop.cpp b/source/ngc/fileop.cpp index 3304387..dac0b48 100644 --- a/source/ngc/fileop.cpp +++ b/source/ngc/fileop.cpp @@ -2,9 +2,9 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * - * fileop.c + * fileop.cpp * * File operations ****************************************************************************/ @@ -29,8 +29,8 @@ #include "memcardop.h" #include "networkop.h" #include "gcunzip.h" -#include "menudraw.h" -#include "filesel.h" +#include "menu.h" +#include "filebrowser.h" unsigned char * savebuffer = NULL; FILE * file; // file pointer - the only one we should ever use! @@ -48,7 +48,7 @@ bool isMounted[9] = { false, false, false, false, false, false, false, false, fa /**************************************************************************** * deviceThreading ***************************************************************************/ -lwp_t devicethread; +lwp_t devicethread = LWP_THREAD_NULL; /**************************************************************************** * devicecallback @@ -114,7 +114,7 @@ devicecallback (void *arg) void InitDeviceThread() { - LWP_CreateThread (&devicethread, devicecallback, NULL, NULL, 0, 80); + LWP_CreateThread (&devicethread, devicecallback, NULL, NULL, 0, 40); } /**************************************************************************** @@ -179,6 +179,7 @@ bool MountFAT(int method) unmountRequired[method] = false; fatUnmount(rootdir); disc->shutdown(); + isMounted[method] = false; } if(!isMounted[method]) { @@ -225,7 +226,7 @@ bool ChangeInterface(int method, bool silent) mounted = MountFAT(METHOD_SD_SLOTB); // try SD Gecko on slot B #endif if(!mounted && !silent) // no SD device found - WaitPrompt ("SD card not found!"); + ErrorPrompt("SD card not found!"); } else if(method == METHOD_USB) { @@ -233,19 +234,31 @@ bool ChangeInterface(int method, bool silent) mounted = MountFAT(method); if(!mounted && !silent) - WaitPrompt ("USB drive not found!"); + ErrorPrompt("USB drive not found!"); #endif } else if(method == METHOD_DVD) { - sprintf(rootdir, "/"); + rootdir[0] = 0; mounted = MountDVD(silent); } +#ifdef HW_RVL else if(method == METHOD_SMB) { sprintf(rootdir, "smb:/"); mounted = ConnectShare(silent); } +#endif + else if(method == METHOD_MC_SLOTA) + { + rootdir[0] = 0; + mounted = TestMC(CARD_SLOTA, silent); + } + else if(method == METHOD_MC_SLOTB) + { + rootdir[0] = 0; + mounted = TestMC(CARD_SLOTB, silent); + } return mounted; } @@ -254,39 +267,49 @@ bool ChangeInterface(int method, bool silent) * Browse subdirectories **************************************************************************/ int -ParseDirectory() +ParseDirectory(int method) { - DIR_ITER *dir; + DIR_ITER *dir = NULL; char fulldir[MAXPATHLEN]; char filename[MAXPATHLEN]; char tmpname[MAXPATHLEN]; struct stat filestat; char msg[128]; + int retry = 1; + bool mounted = false; // reset browser ResetBrowser(); - // add device to path - sprintf(fulldir, "%s%s", rootdir, browser.dir); + ShowAction("Loading..."); // open the directory - dir = diropen(fulldir); + while(dir == NULL && retry == 1) + { + mounted = ChangeInterface(method, NOTSILENT); + sprintf(fulldir, "%s%s", rootdir, browser.dir); // add device to path + if(mounted) dir = diropen(fulldir); + if(dir == NULL) + { + unmountRequired[method] = true; + sprintf(msg, "Error opening %s", fulldir); + retry = ErrorPromptRetry(msg); + } + } + // if we can't open the dir, try opening the root dir if (dir == NULL) { - sprintf(msg, "Error opening %s", fulldir); - WaitPrompt(msg); - - // if we can't open the dir, open root dir - sprintf(browser.dir,"/"); - - dir = diropen(rootdir); - - if (dir == NULL) + if(ChangeInterface(method, SILENT)) { - sprintf(msg, "Error opening %s", rootdir); - WaitPrompt(msg); - return 0; + sprintf(browser.dir,"/"); + dir = diropen(rootdir); + if (dir == NULL) + { + sprintf(msg, "Error opening %s", rootdir); + ErrorPrompt(msg); + return -1; + } } } @@ -302,8 +325,8 @@ ParseDirectory() if(!newBrowserList) // failed to allocate required memory { ResetBrowser(); - WaitPrompt("Out of memory: too many files!"); - entryNum = 0; + ErrorPrompt("Out of memory: too many files!"); + entryNum = -1; break; } else @@ -313,9 +336,19 @@ ParseDirectory() memset(&(browserList[entryNum]), 0, sizeof(BROWSERENTRY)); // clear the new entry strncpy(browserList[entryNum].filename, filename, MAXJOLIET); - StripExt(tmpname, filename); // hide file extension - strncpy(browserList[entryNum].displayname, tmpname, MAXDISPLAY); // crop name for display + + if(strcmp(filename,"..") == 0) + { + sprintf(browserList[entryNum].displayname, "Up One Level"); + } + else + { + StripExt(tmpname, filename); // hide file extension + strncpy(browserList[entryNum].displayname, tmpname, MAXDISPLAY); // crop name for display + } + browserList[entryNum].length = filestat.st_size; + browserList[entryNum].mtime = filestat.st_mtime; browserList[entryNum].isdir = (filestat.st_mode & _IFDIR) == 0 ? 0 : 1; // flag this as a dir entryNum++; @@ -328,6 +361,9 @@ ParseDirectory() // Sort the file list qsort(browserList, entryNum, sizeof(BROWSERENTRY), FileSortCallback); + CancelAction(); + + browser.numEntries = entryNum; return entryNum; } @@ -338,8 +374,8 @@ ParseDirectory() void AllocSaveBuffer () { - if (savebuffer != NULL) - free(savebuffer); + while(savebuffer != NULL) // save buffer is in use + usleep(50); // wait for it to be free savebuffer = (unsigned char *) memalign(32, SAVEBUFFERSIZE); memset (savebuffer, 0, SAVEBUFFERSIZE); @@ -380,7 +416,7 @@ LoadSzFile(char * filepath, unsigned char * rbuffer) } else { - WaitPrompt("Error opening file"); + ErrorPrompt("Error opening file"); } // go back to checking if devices were inserted/removed @@ -398,9 +434,8 @@ LoadFile (char * rbuffer, char *filepath, u32 length, int method, bool silent) char zipbuffer[2048]; u32 size = 0; u32 readsize = 0; - - if(!ChangeInterface(method, NOTSILENT)) - return 0; + char fullpath[MAXPATHLEN]; + int retry = 1; switch(method) { @@ -419,69 +454,84 @@ LoadFile (char * rbuffer, char *filepath, u32 length, int method, bool silent) // since we're loading a file LWP_SuspendThread (devicethread); - // add device to filepath - char fullpath[1024]; - sprintf(fullpath, "%s%s", rootdir, filepath); - - file = fopen (fullpath, "rb"); - - if (file > 0) + // open the file + while(!size && retry == 1) { - if(length > 0 && length <= 2048) // do a partial read (eg: to check file header) + if(ChangeInterface(method, silent)) { - size = fread (rbuffer, 1, length, file); - } - else // load whole file - { - readsize = fread (zipbuffer, 1, 2048, file); + sprintf(fullpath, "%s%s", rootdir, filepath); // add device to filepath + file = fopen (fullpath, "rb"); - if(readsize > 0) + if(file > 0) { - if (IsZipFile (zipbuffer)) + if(length > 0 && length <= 2048) // do a partial read (eg: to check file header) { - size = UnZipBuffer ((unsigned char *)rbuffer, method); // unzip + size = fread (rbuffer, 1, length, file); } - else + else // load whole file { - struct stat fileinfo; - fstat(file->_file, &fileinfo); - size = fileinfo.st_size; + readsize = fread (zipbuffer, 1, 2048, file); - memcpy (rbuffer, zipbuffer, readsize); // copy what we already read - - u32 offset = readsize; - while(offset < size) + if(readsize > 0) { - ShowProgress ("Loading...", offset, size); - readsize = fread (rbuffer + offset, 1, (1024*512), file); // read in 512K chunks + if (IsZipFile (zipbuffer)) + { + size = UnZipBuffer ((unsigned char *)rbuffer, method); // unzip + } + else + { + struct stat fileinfo; + fstat(file->_file, &fileinfo); + size = fileinfo.st_size; - if(readsize <= 0 || readsize > (1024*512)) - break; // read failure + memcpy (rbuffer, zipbuffer, readsize); // copy what we already read - if(readsize > 0) - offset += readsize; + u32 offset = readsize; + u32 nextread = 0; + while(offset < size) + { + if(size - offset > 1024*512) nextread = 1024*512; + else nextread = size-offset; + ShowProgress ("Loading...", offset, size); + readsize = fread (rbuffer + offset, 1, nextread, file); // read in next chunk + + if(readsize <= 0 || readsize > nextread) + break; // read failure + + if(readsize > 0) + offset += readsize; + } + CancelAction(); + + if(offset != size) // # bytes read doesn't match # expected + size = 0; + } } - - if(offset != size) // # bytes read doesn't match # expected - size = 0; } + fclose (file); + } + } + if(!size) + { + if(!silent) + { + unmountRequired[method] = true; + retry = ErrorPromptRetry("Error loading file!"); + } + else + { + retry = 0; } } - fclose (file); - } - if(!size && !silent) - { - unmountRequired[method] = true; - WaitPrompt("Error loading file!"); } // go back to checking if devices were inserted/removed LWP_ResumeThread (devicethread); - + CancelAction(); return size; } -u32 LoadFile(char filepath[], int method, bool silent) +u32 LoadFile(char * filepath, int method, bool silent) { return LoadFile((char *)savebuffer, filepath, 0, method, silent); } @@ -493,53 +543,59 @@ u32 LoadFile(char filepath[], int method, bool silent) u32 SaveFile (char * buffer, char *filepath, u32 datasize, int method, bool silent) { + char fullpath[MAXPATHLEN]; u32 written = 0; + int retry = 1; - if(!ChangeInterface(method, NOTSILENT)) + if(datasize == 0) return 0; - switch(method) + ShowAction("Saving..."); + + if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) { - case METHOD_MC_SLOTA: + if(method == METHOD_MC_SLOTA) return SaveMCFile (buffer, CARD_SLOTA, filepath, datasize, silent); - break; - case METHOD_MC_SLOTB: + else return SaveMCFile (buffer, CARD_SLOTB, filepath, datasize, silent); - break; } - if (datasize) - { - // stop checking if devices were removed/inserted - // since we're saving a file - LWP_SuspendThread (devicethread); + // stop checking if devices were removed/inserted + // since we're saving a file + LWP_SuspendThread (devicethread); - // add device to filepath - char fullpath[1024]; - sprintf(fullpath, "%s%s", rootdir, filepath); - - // open file for writing - file = fopen (fullpath, "wb"); - - if (file > 0) + while(!written && retry == 1) + { + if(ChangeInterface(method, silent)) { - written = fwrite (savebuffer, 1, datasize, file); - fclose (file); - } + sprintf(fullpath, "%s%s", rootdir, filepath); // add device to filepath + file = fopen (fullpath, "wb"); - if(!written && !silent) + if (file > 0) + { + written = fwrite (savebuffer, 1, datasize, file); + if(written < datasize) written = 0; + fclose (file); + } + } + if(!written) { unmountRequired[method] = true; - WaitPrompt ("Error saving file!"); + if(!silent) + retry = ErrorPromptRetry("Error saving file!"); + else + retry = 0; } + } - // go back to checking if devices were inserted/removed - LWP_ResumeThread (devicethread); - } + // go back to checking if devices were inserted/removed + LWP_ResumeThread (devicethread); + + CancelAction(); return written; } -u32 SaveFile(char filepath[], u32 datasize, int method, bool silent) +u32 SaveFile(char * filepath, u32 datasize, int method, bool silent) { return SaveFile((char *)savebuffer, filepath, datasize, method, silent); } diff --git a/source/ngc/fileop.h b/source/ngc/fileop.h index 41c7ab6..e900080 100644 --- a/source/ngc/fileop.h +++ b/source/ngc/fileop.h @@ -2,15 +2,16 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * - * fatop.h + * fileop.h * * File operations ****************************************************************************/ #ifndef _FILEOP_H_ #define _FILEOP_H_ + #include #include #include @@ -24,14 +25,14 @@ void InitDeviceThread(); void MountAllFAT(); void UnmountAllFAT(); bool ChangeInterface(int method, bool silent); -int ParseDirectory(); +int ParseDirectory(int method); void AllocSaveBuffer(); void FreeSaveBuffer(); u32 LoadFile(char * rbuffer, char *filepath, u32 length, int method, bool silent); -u32 LoadFile(char filepath[], int method, bool silent); +u32 LoadFile(char * filepath, int method, bool silent); u32 LoadSzFile(char * filepath, unsigned char * rbuffer); u32 SaveFile(char * buffer, char *filepath, u32 datasize, int method, bool silent); -u32 SaveFile(char filepath[], u32 datasize, int method, bool silent); +u32 SaveFile(char * filepath, u32 datasize, int method, bool silent); extern unsigned char * savebuffer; extern FILE * file; diff --git a/source/ngc/gcaudio.cpp b/source/ngc/gcaudio.cpp index 20daa33..065908a 100644 --- a/source/ngc/gcaudio.cpp +++ b/source/ngc/gcaudio.cpp @@ -2,16 +2,17 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * eke-eke October 2008 * - * gcaudio.c + * gcaudio.cpp * * Audio driver ****************************************************************************/ #include #include +#include #define SAMPLERATE 48000 @@ -83,8 +84,6 @@ static void AudioSwitchBuffers() void InitialiseAudio() { AUDIO_Init(NULL); // Start audio subsystem - AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ); - AUDIO_RegisterDMACallback( AudioSwitchBuffers ); memset(soundbuffer, 0, 3840*2); memset(mixbuffer, 0, 16000); } @@ -112,6 +111,50 @@ void ResetAudio() mixhead = mixtail = 0; } +/**************************************************************************** + * SwitchAudioMode + * + * Switches between menu sound and emulator sound + ***************************************************************************/ +void +SwitchAudioMode(int mode) +{ + if(mode == 0) // emulator + { + #ifndef NO_SOUND + ASND_Pause(1); + ASND_End(); + #endif + AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ); + AUDIO_RegisterDMACallback(AudioSwitchBuffers); + } + else // menu + { + AUDIO_StopDMA(); + AUDIO_RegisterDMACallback(NULL); + #ifndef NO_SOUND + ASND_Init(); + ASND_Pause(0); + #endif + } +} + +/**************************************************************************** + * ShutdownAudio + * + * Shuts down audio subsystem. Useful to avoid unpleasant sounds if a + * crash occurs during shutdown. + ***************************************************************************/ +void ShutdownAudio() +{ + #ifndef NO_SOUND + ASND_Pause(1); + ASND_End(); + #endif + AUDIO_StopDMA(); + AUDIO_RegisterDMACallback(NULL); +} + /**************************************************************************** * PlaySound * diff --git a/source/ngc/gcaudio.h b/source/ngc/gcaudio.h index 5e3bdbd..cfc4c49 100644 --- a/source/ngc/gcaudio.h +++ b/source/ngc/gcaudio.h @@ -2,7 +2,7 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * eke-eke October 2008 * * gcaudio.h @@ -14,3 +14,5 @@ void InitialiseAudio(); void StopAudio(); void ResetAudio(); void PlaySound( int *Buffer, int samples ); +void SwitchAudioMode(int mode); +void ShutdownAudio(); diff --git a/source/ngc/gcunzip.cpp b/source/ngc/gcunzip.cpp index 64b63fe..52dcecd 100644 --- a/source/ngc/gcunzip.cpp +++ b/source/ngc/gcunzip.cpp @@ -23,8 +23,11 @@ extern "C" { #include "fceugx.h" #include "dvd.h" +#include "networkop.h" #include "fileop.h" -#include "menudraw.h" +#include "filebrowser.h" +#include "gcvideo.h" +#include "menu.h" #include "gcunzip.h" #define ZIPCHUNK 2048 @@ -145,7 +148,7 @@ UnZipBuffer (unsigned char *outbuffer, int method) res = inflateInit2 (&zs, -MAX_WBITS); if (res != Z_OK) - return 0; + goto done; /*** Set ZipChunk for first pass ***/ zipoffset = @@ -169,8 +172,7 @@ UnZipBuffer (unsigned char *outbuffer, int method) if (res == Z_MEM_ERROR) { - inflateEnd (&zs); - return 0; + goto done; } have = ZIPCHUNK - zs.avail_out; @@ -198,23 +200,20 @@ UnZipBuffer (unsigned char *outbuffer, int method) break; } if(sizeread <= 0) - break; // read failure + goto done; // read failure ShowProgress ("Loading...", bufferoffset, pkzip.uncompressedSize); } while (res != Z_STREAM_END); +done: inflateEnd (&zs); + CancelAction(); if (res == Z_STREAM_END) - { - if (pkzip.uncompressedSize == (u32) bufferoffset) - return bufferoffset; - else - return pkzip.uncompressedSize; - } - - return 0; + return pkzip.uncompressedSize; + else + return 0; } /**************************************************************************** @@ -247,7 +246,7 @@ GetFirstZipFilename (int method) } else { - WaitPrompt("Error - Invalid ZIP file!"); + ErrorPrompt("Error - Invalid ZIP file!"); } } @@ -317,7 +316,7 @@ Is7ZipFile (char *buffer) // display an error message static void SzDisplayError(SZ_RESULT res) { - WaitPrompt(szerrormsg[(res - 1)]); + ErrorPrompt(szerrormsg[(res - 1)]); } // function used by the 7zip SDK to read data from SD/USB/DVD/SMB @@ -472,7 +471,7 @@ int SzParse(char * filepath, int method) if(!newBrowserList) // failed to allocate required memory { ResetBrowser(); - WaitPrompt("Out of memory: too many files!"); + ErrorPrompt("Out of memory: too many files!"); nbfiles = 0; break; } @@ -553,6 +552,8 @@ int SzExtractFile(int i, unsigned char *buffer) // close 7Zip archive and free memory SzClose(); + CancelAction(); + // check for errors if(SzRes != SZ_OK) { diff --git a/source/ngc/gcvideo.cpp b/source/ngc/gcvideo.cpp index ff345d6..0ee3020 100644 --- a/source/ngc/gcvideo.cpp +++ b/source/ngc/gcvideo.cpp @@ -2,9 +2,9 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * - * gcvideo.c + * gcvideo.cpp * * Video rendering ****************************************************************************/ @@ -16,12 +16,13 @@ #include #include #include +#include #include "driver.h" #include "gcvideo.h" #include "fceugx.h" -#include "menudraw.h" -#include "images/nesback.h" +#include "menu.h" +#include "pad.h" extern "C" { extern void FCEU_ResetPalette(void); @@ -37,6 +38,7 @@ static GXRModeObj *vmode; // Graphics Mode Object unsigned int *xfb[2]; // Framebuffers int whichfb = 0; // Frame buffer toggle int screenheight; +int screenwidth; bool progressive = FALSE; /*** 3D GX ***/ @@ -47,6 +49,7 @@ static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN(32); static u32 copynow = GX_FALSE; static GXTexObj texobj; static Mtx view; +static Mtx GXmodelView2D; /*** Texture memory ***/ static unsigned char texturemem[TEX_WIDTH * TEX_HEIGHT * 2] ATTRIBUTE_ALIGN (32); @@ -54,6 +57,9 @@ static unsigned char texturemem[TEX_WIDTH * TEX_HEIGHT * 2] ATTRIBUTE_ALIGN (32) static int updateScaling = 1; static int vmode_60hz = 0; +u8 * gameScreenTex = NULL; // a GX texture screen capture of the game +u8 * gameScreenTex2 = NULL; // a GX texture screen capture of the game (copy) + #define HASPECT 256 #define VASPECT 240 @@ -244,7 +250,6 @@ vbgetback (void *arg) } return NULL; - } /**************************************************************************** @@ -272,7 +277,6 @@ InitVideoThread () static void copy_to_xfb (u32 arg) { - if (copynow == GX_TRUE) { GX_CopyDisp (xfb[whichfb], GX_TRUE); @@ -368,13 +372,11 @@ draw_square (Mtx v) /**************************************************************************** * StartGX * - * This function initialises the GX. + * This function initialises GX and sets it up for use ***************************************************************************/ static void StartGX () { - Mtx44 p; - GXColor background = { 0, 0, 0, 0xff }; /*** Clear out FIFO area ***/ @@ -384,27 +386,22 @@ StartGX () GX_Init (&gp_fifo, DEFAULT_FIFO_SIZE); GX_SetCopyClear (background, 0x00ffffff); - - GX_SetViewport (0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1); - GX_SetDispCopyYScale ((f32) vmode->xfbHeight / (f32) vmode->efbHeight); - GX_SetScissor (0, 0, vmode->fbWidth, vmode->efbHeight); - - GX_SetDispCopySrc (0, 0, vmode->fbWidth, vmode->efbHeight); - GX_SetDispCopyDst (vmode->fbWidth, vmode->xfbHeight); - GX_SetCopyFilter (vmode->aa, vmode->sample_pattern, GX_TRUE, vmode->vfilter); - - GX_SetFieldMode (vmode->field_rendering, ((vmode->viHeight == 2 * vmode->xfbHeight) ? GX_ENABLE : GX_DISABLE)); - - GX_SetPixelFmt (GX_PF_RGB8_Z24, GX_ZC_LINEAR); - GX_SetCullMode (GX_CULL_NONE); GX_SetDispCopyGamma (GX_GM_1_0); - GX_SetZMode (GX_TRUE, GX_LEQUAL, GX_TRUE); - GX_SetColorUpdate (GX_TRUE); + GX_SetCullMode (GX_CULL_NONE); +} - guOrtho(p, vmode->efbHeight/2, -(vmode->efbHeight/2), -(vmode->fbWidth/2), vmode->fbWidth/2, 10, 1000); // matrix, t, b, l, r, n, f - GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC); +/**************************************************************************** + * StopGX + * + * Stops GX (when exiting) + ***************************************************************************/ +void StopGX() +{ + GX_AbortFrame(); + GX_Flush(); - GX_CopyDisp (xfb[whichfb], GX_TRUE); // reset xfb + VIDEO_SetBlack(TRUE); + VIDEO_Flush(); } /**************************************************************************** @@ -457,10 +454,28 @@ UpdateScaling() static void UpdatePadsCB () { -#ifdef HW_RVL + #ifdef HW_RVL WPAD_ScanPads(); -#endif + #endif PAD_ScanPads(); + + for(int i=3; i >= 0; i--) + { + #ifdef HW_RVL + memcpy(&userInput[i].wpad, WPAD_Data(i), sizeof(WPADData)); + #endif + + userInput[i].chan = i; + userInput[i].pad.btns_d = PAD_ButtonsDown(i); + userInput[i].pad.btns_u = PAD_ButtonsUp(i); + userInput[i].pad.btns_h = PAD_ButtonsHeld(i); + userInput[i].pad.stickX = PAD_StickX(i); + userInput[i].pad.stickY = PAD_StickY(i); + userInput[i].pad.substickX = PAD_SubStickX(i); + userInput[i].pad.substickY = PAD_SubStickY(i); + userInput[i].pad.triggerL = PAD_TriggerL(i); + userInput[i].pad.triggerR = PAD_TriggerR(i); + } } /**************************************************************************** @@ -523,8 +538,8 @@ InitGCVideo () // configure VI VIDEO_Configure (vmode); - // always 480 lines screenheight = vmode->xfbHeight; + screenwidth = vmode->fbWidth; // Allocate the video buffers xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode)); @@ -549,12 +564,10 @@ InitGCVideo () VIDEO_WaitVSync (); copynow = GX_FALSE; + StartGX (); - draw_init (); - InitVideoThread (); - // Finally, the video is up and ready for use :) } @@ -625,11 +638,17 @@ ResetVideo_Emu () GX_SetViewport (0, 0, rmode->fbWidth, rmode->efbHeight, 0, 1); GX_SetDispCopyYScale ((f32) rmode->xfbHeight / (f32) rmode->efbHeight); GX_SetScissor (0, 0, rmode->fbWidth, rmode->efbHeight); + GX_SetDispCopySrc (0, 0, rmode->fbWidth, rmode->efbHeight); GX_SetDispCopyDst (rmode->fbWidth, rmode->xfbHeight); GX_SetCopyFilter (rmode->aa, rmode->sample_pattern, (GCSettings.render == 1) ? GX_TRUE : GX_FALSE, rmode->vfilter); // deflickering filter only for filtered mode + GX_SetFieldMode (rmode->field_rendering, ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE)); GX_SetPixelFmt (GX_PF_RGB8_Z24, GX_ZC_LINEAR); + + GX_SetZMode (GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetColorUpdate (GX_TRUE); + guOrtho(p, rmode->efbHeight/2, -(rmode->efbHeight/2), -(rmode->fbWidth/2), rmode->fbWidth/2, 10, 1000); // matrix, t, b, l, r, n, f GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC); @@ -644,41 +663,6 @@ ResetVideo_Emu () updateScaling = 5; } -/**************************************************************************** - * ResetVideo_Menu - * - * Reset the video/rendering mode for the menu -****************************************************************************/ -void -ResetVideo_Menu () -{ - Mtx44 p; - - VIDEO_Configure (vmode); - VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK); - VIDEO_Flush(); - VIDEO_WaitVSync(); - if (vmode->viTVMode & VI_NON_INTERLACE) - VIDEO_WaitVSync(); - else - while (VIDEO_GetNextField()) - VIDEO_WaitVSync(); - - GX_SetViewport (0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1); - GX_SetDispCopyYScale ((f32) vmode->xfbHeight / (f32) vmode->efbHeight); - GX_SetScissor (0, 0, vmode->fbWidth, vmode->efbHeight); - - GX_SetDispCopySrc (0, 0, vmode->fbWidth, vmode->efbHeight); - GX_SetDispCopyDst (vmode->fbWidth, vmode->xfbHeight); - GX_SetCopyFilter (vmode->aa, vmode->sample_pattern, GX_TRUE, vmode->vfilter); - - GX_SetFieldMode (vmode->field_rendering, ((vmode->viHeight == 2 * vmode->xfbHeight) ? GX_ENABLE : GX_DISABLE)); - GX_SetPixelFmt (GX_PF_RGB8_Z24, GX_ZC_LINEAR); - - guOrtho(p, vmode->efbHeight/2, -(vmode->efbHeight/2), -(vmode->fbWidth/2), vmode->fbWidth/2, 10, 1000); // matrix, t, b, l, r, n, f - GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC); -} - /**************************************************************************** * RenderFrame * @@ -798,22 +782,211 @@ zoom_reset () updateScaling = 5; // update video } -void -clearscreen () +/**************************************************************************** + * TakeScreenshot + * + * Copies the current screen into a GX texture + ***************************************************************************/ +void TakeScreenshot() { - int colour = COLOR_BLACK; - whichfb ^= 1; - VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], colour); - memcpy (xfb[whichfb], &bg, 1280 * 480); + int texSize = vmode->fbWidth * vmode->efbHeight * 4; + + if(gameScreenTex) free(gameScreenTex); + gameScreenTex = (u8 *)memalign(32, texSize); + if(gameScreenTex == NULL) return; + GX_SetTexCopySrc(0, 0, vmode->fbWidth, vmode->efbHeight); + GX_SetTexCopyDst(vmode->fbWidth, vmode->efbHeight, GX_TF_RGBA8, GX_FALSE); + GX_CopyTex(gameScreenTex, GX_FALSE); + GX_PixModeSync(); + DCFlushRange(gameScreenTex, texSize); + + #ifdef HW_RVL + if(gameScreenTex2) free(gameScreenTex2); + gameScreenTex2 = (u8 *)memalign(32, texSize); + if(gameScreenTex2 == NULL) return; + GX_CopyTex(gameScreenTex2, GX_FALSE); + GX_PixModeSync(); + DCFlushRange(gameScreenTex2, texSize); + #endif } +/**************************************************************************** + * ResetVideo_Menu + * + * Reset the video/rendering mode for the menu +****************************************************************************/ void -showscreen () +ResetVideo_Menu () { - copynow = GX_FALSE; - VIDEO_SetNextFramebuffer (xfb[whichfb]); - VIDEO_Flush (); - VIDEO_WaitVSync (); + Mtx44 p; + f32 yscale; + u32 xfbHeight; + + VIDEO_Configure (vmode); + VIDEO_Flush(); + VIDEO_WaitVSync(); + if (vmode->viTVMode & VI_NON_INTERLACE) + VIDEO_WaitVSync(); + else + while (VIDEO_GetNextField()) + VIDEO_WaitVSync(); + + // clears the bg to color and clears the z buffer + GXColor background = {0, 0, 0, 255}; + GX_SetCopyClear (background, 0x00ffffff); + + yscale = GX_GetYScaleFactor(vmode->efbHeight,vmode->xfbHeight); + xfbHeight = GX_SetDispCopyYScale(yscale); + GX_SetScissor(0,0,vmode->fbWidth,vmode->efbHeight); + GX_SetDispCopySrc(0,0,vmode->fbWidth,vmode->efbHeight); + GX_SetDispCopyDst(vmode->fbWidth,xfbHeight); + GX_SetCopyFilter(vmode->aa,vmode->sample_pattern,GX_TRUE,vmode->vfilter); + GX_SetFieldMode(vmode->field_rendering,((vmode->viHeight==2*vmode->xfbHeight)?GX_ENABLE:GX_DISABLE)); + + if (vmode->aa) + GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); + else + GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + + // setup the vertex descriptor + // tells the flipper to expect direct data + GX_ClearVtxDesc(); + GX_InvVtxCache (); + GX_InvalidateTexAll(); + + GX_SetVtxDesc(GX_VA_TEX0, GX_NONE); + GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); + GX_SetVtxDesc (GX_VA_CLR0, GX_DIRECT); + + GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + GX_SetZMode (GX_FALSE, GX_LEQUAL, GX_TRUE); + + GX_SetNumChans(1); + GX_SetNumTexGens(1); + GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + + guMtxIdentity(GXmodelView2D); + guMtxTransApply (GXmodelView2D, GXmodelView2D, 0.0F, 0.0F, -50.0F); + GX_LoadPosMtxImm(GXmodelView2D,GX_PNMTX0); + + guOrtho(p,0,479,0,639,0,300); + GX_LoadProjectionMtx(p, GX_ORTHOGRAPHIC); + + GX_SetViewport(0,0,vmode->fbWidth,vmode->efbHeight,0,1); + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); + GX_SetAlphaUpdate(GX_TRUE); +} + +/**************************************************************************** + * Menu_Render + * + * Renders everything current sent to GX, and flushes video + ***************************************************************************/ +void Menu_Render() +{ + GX_DrawDone (); + + whichfb ^= 1; // flip framebuffer + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetColorUpdate(GX_TRUE); + GX_CopyDisp(xfb[whichfb],GX_TRUE); + VIDEO_SetNextFramebuffer(xfb[whichfb]); + VIDEO_Flush(); + VIDEO_WaitVSync(); +} + +/**************************************************************************** + * Menu_DrawImg + * + * Draws the specified image on screen using GX + ***************************************************************************/ +void Menu_DrawImg(f32 xpos, f32 ypos, u16 width, u16 height, u8 data[], + f32 degrees, f32 scaleX, f32 scaleY, u8 alpha) +{ + if(data == NULL) + return; + + GXTexObj texObj; + + GX_InitTexObj(&texObj, data, width,height, GX_TF_RGBA8,GX_CLAMP, GX_CLAMP,GX_FALSE); + GX_LoadTexObj(&texObj, GX_TEXMAP0); + GX_InvalidateTexAll(); + + GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE); + GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); + + Mtx m,m1,m2, mv; + width *=.5; + height*=.5; + guMtxIdentity (m1); + guMtxScaleApply(m1,m1,scaleX,scaleY,1.0); + Vector axis = (Vector) {0 , 0, 1 }; + guMtxRotAxisDeg (m2, &axis, degrees); + guMtxConcat(m2,m1,m); + + guMtxTransApply(m,m, xpos+width,ypos+height,0); + guMtxConcat (GXmodelView2D, m, mv); + GX_LoadPosMtxImm (mv, GX_PNMTX0); + + GX_Begin(GX_QUADS, GX_VTXFMT0,4); + GX_Position3f32(-width, -height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(0, 0); + + GX_Position3f32(width, -height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(1, 0); + + GX_Position3f32(width, height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(1, 1); + + GX_Position3f32(-width, height, 0); + GX_Color4u8(0xFF,0xFF,0xFF,alpha); + GX_TexCoord2f32(0, 1); + GX_End(); + GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0); + + GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); + GX_SetVtxDesc (GX_VA_TEX0, GX_NONE); +} + +/**************************************************************************** + * Menu_DrawRectangle + * + * Draws a rectangle at the specified coordinates using GX + ***************************************************************************/ +void Menu_DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color, u8 filled) +{ + u8 fmt; + long n; + int i; + f32 x2 = x+width; + f32 y2 = y+height; + Vector v[] = {{x,y,0.0f}, {x2,y,0.0f}, {x2,y2,0.0f}, {x,y2,0.0f}, {x,y,0.0f}}; + + if(!filled) + { + fmt = GX_LINESTRIP; + n = 5; + } + else + { + fmt = GX_TRIANGLEFAN; + n = 4; + } + + GX_Begin(fmt, GX_VTXFMT0, n); + for(i=0; i #include #include "pngu/pngu.h" -#include "FreeTypeGX.h" -#include "snes9xGX.h" -#include "video.h" -#include "input.h" -#include "filelist.h" -#include "fileop.h" -#include "menu.h" -#include "oggplayer.h" + +#include "../FreeTypeGX.h" +#include "../fceugx.h" +#include "../gcvideo.h" +#include "../pad.h" +#include "../filelist.h" +#include "../fileop.h" +#include "../menu.h" +#include "../oggplayer.h" #define SCROLL_INITIAL_DELAY 20 #define SCROLL_LOOP_DELAY 3 @@ -78,6 +80,8 @@ enum #define EFFECT_SCALE 128 #define EFFECT_COLOR_TRANSITION 256 +extern FreeTypeGX *fontSystem; + class GuiSound { public: diff --git a/source/ngc/gui/gui_button.cpp b/source/ngc/gui/gui_button.cpp index 45fcf45..85a5f5e 100644 --- a/source/ngc/gui/gui_button.cpp +++ b/source/ngc/gui/gui_button.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * diff --git a/source/ngc/gui/gui_element.cpp b/source/ngc/gui/gui_element.cpp index 1a507be..8734d44 100644 --- a/source/ngc/gui/gui_element.cpp +++ b/source/ngc/gui/gui_element.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * diff --git a/source/ngc/gui/gui_filebrowser.cpp b/source/ngc/gui/gui_filebrowser.cpp index 7fc3c3b..1e99cb6 100644 --- a/source/ngc/gui/gui_filebrowser.cpp +++ b/source/ngc/gui/gui_filebrowser.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * diff --git a/source/ngc/gui/gui_image.cpp b/source/ngc/gui/gui_image.cpp index 17ab67d..89f3023 100644 --- a/source/ngc/gui/gui_image.cpp +++ b/source/ngc/gui/gui_image.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * diff --git a/source/ngc/gui/gui_imagedata.cpp b/source/ngc/gui/gui_imagedata.cpp index f8b34ae..535711d 100644 --- a/source/ngc/gui/gui_imagedata.cpp +++ b/source/ngc/gui/gui_imagedata.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * diff --git a/source/ngc/gui/gui_keyboard.cpp b/source/ngc/gui/gui_keyboard.cpp index ecdc7be..b670063 100644 --- a/source/ngc/gui/gui_keyboard.cpp +++ b/source/ngc/gui/gui_keyboard.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * diff --git a/source/ngc/gui/gui_optionbrowser.cpp b/source/ngc/gui/gui_optionbrowser.cpp index e31747e..331fa31 100644 --- a/source/ngc/gui/gui_optionbrowser.cpp +++ b/source/ngc/gui/gui_optionbrowser.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * diff --git a/source/ngc/gui/gui_savebrowser.cpp b/source/ngc/gui/gui_savebrowser.cpp index 0ee7b3d..887c623 100644 --- a/source/ngc/gui/gui_savebrowser.cpp +++ b/source/ngc/gui/gui_savebrowser.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * @@ -354,10 +355,10 @@ void GuiSaveBrowser::Update(GuiTrigger * t) saveDate[i]->SetText(saves->date[listOffset+i]); saveTime[i]->SetText(saves->time[listOffset+i]); - if(saves->type[listOffset+i] == FILE_SRAM) - sprintf(savetext, "SRAM"); + if(saves->type[listOffset+i] == FILE_RAM) + sprintf(savetext, "RAM"); else - sprintf(savetext, "Snapshot"); + sprintf(savetext, "State"); len = strlen(saves->filename[listOffset+i]); if(len > 10 && diff --git a/source/ngc/gui/gui_sound.cpp b/source/ngc/gui/gui_sound.cpp index 140f7fb..b3580ae 100644 --- a/source/ngc/gui/gui_sound.cpp +++ b/source/ngc/gui/gui_sound.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * diff --git a/source/ngc/gui/gui_text.cpp b/source/ngc/gui/gui_text.cpp index 88414c5..5a7231c 100644 --- a/source/ngc/gui/gui_text.cpp +++ b/source/ngc/gui/gui_text.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * @@ -9,8 +10,6 @@ ***************************************************************************/ #include "gui.h" -#include "snes9xGX.h" -#include "filelist.h" static int currentSize = 0; static int presetSize = 0; diff --git a/source/ngc/gui/gui_trigger.cpp b/source/ngc/gui/gui_trigger.cpp index 648c50d..e1277cc 100644 --- a/source/ngc/gui/gui_trigger.cpp +++ b/source/ngc/gui/gui_trigger.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * diff --git a/source/ngc/gui/gui_window.cpp b/source/ngc/gui/gui_window.cpp index 64d16d0..a625d66 100644 --- a/source/ngc/gui/gui_window.cpp +++ b/source/ngc/gui/gui_window.cpp @@ -1,5 +1,6 @@ /**************************************************************************** - * Snes9x 1.51 Nintendo Wii/Gamecube Port + * FCE Ultra 0.98.12 + * Nintendo Wii/Gamecube Port * * Tantric February 2009 * diff --git a/source/ngc/http.cpp b/source/ngc/http.cpp index e563485..29a3851 100644 --- a/source/ngc/http.cpp +++ b/source/ngc/http.cpp @@ -23,7 +23,7 @@ #include #include -#include "menudraw.h" +#include "menu.h" #include "http.h" static s32 tcp_socket(void) diff --git a/source/ngc/memcardop.cpp b/source/ngc/memcardop.cpp index 8994cb1..fd21c13 100644 --- a/source/ngc/memcardop.cpp +++ b/source/ngc/memcardop.cpp @@ -15,104 +15,136 @@ #include #include #include +#include -#include "common.h" -#include "menudraw.h" #include "fceugx.h" +#include "common.h" +#include "gcvideo.h" #include "menu.h" -#include "memcardop.h" +#include "preferences.h" +#include "filebrowser.h" #include "fileop.h" -#include "filesel.h" +#include "dvd.h" +#include "images/saveicon.h" + +static u8 * SysArea = NULL; +static char savecomments[2][32]; /**************************************************************************** - * CardFileExists - * - * Wrapper to search through the files on the card. - * Returns TRUE if found. - ***************************************************************************/ -static int -CardFileExists (char *filename, int slot) -{ - card_dir CardDir; - int CardError; - - CardError = CARD_FindFirst (slot, &CardDir, TRUE); - while (CardError != CARD_ERROR_NOFILE) - { - CardError = CARD_FindNext (&CardDir); - - if (strcmp ((char *) CardDir.filename, filename) == 0) - return 1; - } - - return 0; -} - -/**************************************************************************** - * MountCard + * MountMC * * Mounts the memory card in the given slot. * Returns the result of the last attempted CARD_Mount command. ***************************************************************************/ -static int MountCard(int cslot, bool silent, u8 * SysArea) +static int MountMC(int slot, bool silent) { int ret = -1; int tries = 0; + // Initialize Card System + SysArea = (u8 *)memalign(32, CARD_WORKAREA); + memset (SysArea, 0, CARD_WORKAREA); + CARD_Init ("FCEU", "00"); + // Mount the card - while ( tries < 10 && ret != 0) + while(tries < 10 && ret != 0) { - EXI_ProbeReset (); - ret = CARD_Mount (cslot, &SysArea, NULL); - VIDEO_WaitVSync (); + EXI_ProbeReset(); + ret = CARD_Mount (slot, SysArea, NULL); + VIDEO_WaitVSync(); tries++; } + + if(ret != 0 && !silent) + { + if (slot == CARD_SLOTA) + ErrorPrompt("Unable to mount Slot A Memory Card!"); + else + ErrorPrompt("Unable to mount Slot B Memory Card!"); + } return ret; } /**************************************************************************** - * TestCard + * TestMC * * Checks to see if a card is in the card slot specified ***************************************************************************/ -bool TestCard(int slot, bool silent) +bool TestMC(int slot, bool silent) { // Memory Cards do not work in Wii mode - disable #ifdef HW_RVL return false; #endif - /*** Initialize Card System ***/ - u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN (32); - memset (SysArea, 0, CARD_WORKAREA); - CARD_Init ("FCEU", "00"); + bool ret = false; - /*** Try to mount the card ***/ - if (MountCard(slot, silent, (u8 *)SysArea) == 0) + // Try to mount the card + if (MountMC(slot, silent) == 0) { // Mount successful! - if(!silent) - { - if (slot == CARD_SLOTA) - WaitPrompt("Mounted Slot A Memory Card!"); - else - WaitPrompt("Mounted Slot B Memory Card!"); - } CARD_Unmount (slot); - return true; + ret = true; } - else - { - if(!silent) - { - if (slot == CARD_SLOTA) - WaitPrompt("Unable to Mount Slot A Memory Card!"); - else - WaitPrompt("Unable to Mount Slot B Memory Card!"); - } + free(SysArea); + return ret; +} - return false; +/**************************************************************************** + * ParseMCDirectory + * + * Parses a list of all files on the specified memory card + ***************************************************************************/ +int +ParseMCDirectory (int slot) +{ + card_dir CardDir; + int CardError; + int entryNum = 0; + char tmpname[MAXPATHLEN]; + + // Try to mount the card + CardError = MountMC(slot, NOTSILENT); + + if (CardError == 0) + { + CardError = CARD_FindFirst (slot, &CardDir, TRUE); + while (CardError != CARD_ERROR_NOFILE) + { + BROWSERENTRY * newBrowserList = (BROWSERENTRY *)realloc(browserList, (entryNum+1) * sizeof(BROWSERENTRY)); + + if(!newBrowserList) // failed to allocate required memory + { + ResetBrowser(); + ErrorPrompt("Out of memory: too many files!"); + entryNum = -1; + break; + } + else + { + browserList = newBrowserList; + } + memset(&(browserList[entryNum]), 0, sizeof(BROWSERENTRY)); // clear the new entry + + strncpy(browserList[entryNum].filename, (char *)CardDir.filename, MAXJOLIET); + StripExt(tmpname, (char *)CardDir.filename); // hide file extension + strncpy(browserList[entryNum].displayname, tmpname, MAXDISPLAY); // crop name for display + browserList[entryNum].length = CardDir.filelen; + + entryNum++; + + CardError = CARD_FindNext (&CardDir); + } + CARD_Unmount(slot); } + + // Sort the file list + qsort(browserList, entryNum, sizeof(BROWSERENTRY), FileSortCallback); + + CancelAction(); + + browser.numEntries = entryNum; + return entryNum; } /**************************************************************************** @@ -122,37 +154,27 @@ static int VerifyMCFile (char *buf, int slot, char *filename, int datasize) { card_file CardFile; - unsigned char verifbuffer[65536] ATTRIBUTE_ALIGN (32); + unsigned char verifybuffer[65536] ATTRIBUTE_ALIGN (32); int CardError; unsigned int blocks; unsigned int SectorSize; - char msg[80]; - int bytesleft = 0; - int bytesread = 0; + int bytesleft = 0; + int bytesread = 0; - /*** Initialize Card System ***/ - u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN (32); - memset (SysArea, 0, CARD_WORKAREA); - CARD_Init ("FCEU", "00"); + memset (verifybuffer, 0, 65536); - /*** Try to mount the card ***/ - CardError = MountCard(slot, NOTSILENT, (u8 *)SysArea); + // Get Sector Size + CARD_GetSectorSize (slot, &SectorSize); - if (CardError == 0) + memset (&CardFile, 0, sizeof (CardFile)); + CardError = CARD_Open (slot, filename, &CardFile); + + if(CardError) + { + ErrorPrompt("Unable to open file!"); + } + else { - /*** Get Sector Size ***/ - CARD_GetSectorSize (slot, &SectorSize); - - if (!CardFileExists (filename, slot)) - { - CARD_Unmount (slot); - WaitPrompt("Unable to open file for verify!"); - return 0; - } - - memset (&CardFile, 0, sizeof (CardFile)); - CardError = CARD_Open (slot, filename, &CardFile); - blocks = CardFile.len; if (blocks < SectorSize) @@ -161,41 +183,29 @@ VerifyMCFile (char *buf, int slot, char *filename, int datasize) if (blocks % SectorSize) blocks += SectorSize; - if (blocks > (unsigned int)datasize) - blocks = datasize; + if (blocks > (unsigned int)datasize) + blocks = datasize; - memset (verifbuffer, 0, 65536); bytesleft = blocks; bytesread = 0; while (bytesleft > 0) { - CARD_Read (&CardFile, verifbuffer, SectorSize, bytesread); - if ( memcmp (buf + bytesread, verifbuffer, (unsigned int)bytesleft < SectorSize ? bytesleft : SectorSize) ) - { - CARD_Close (&CardFile); - CARD_Unmount (slot); - WaitPrompt("File did not verify!"); - return 0; - } + CardError = CARD_Read (&CardFile, verifybuffer, SectorSize, bytesread); + if (CardError || memcmp (buf + bytesread, verifybuffer, (unsigned int)bytesleft < SectorSize ? bytesleft : SectorSize) ) + { + bytesread = 0; + ErrorPrompt("File integrity could not be verified!"); + break; + } bytesleft -= SectorSize; bytesread += SectorSize; - - sprintf (msg, "Verified %d of %d bytes", bytesread, blocks); - ShowProgress (msg, bytesread, blocks); + ShowProgress ("Verifying...", bytesread, blocks); } CARD_Close (&CardFile); - CARD_Unmount (slot); - - return 1; + CancelAction(); } - else - if (slot == CARD_SLOTA) - WaitPrompt("Unable to Mount Slot A Memory Card!"); - else - WaitPrompt("Unable to Mount Slot B Memory Card!"); - - return 0; + return bytesread; } /**************************************************************************** @@ -209,59 +219,63 @@ LoadMCFile (char *buf, int slot, char *filename, bool silent) int CardError; unsigned int blocks; unsigned int SectorSize; - int bytesleft = 0; - int bytesread = 0; + int bytesleft = 0; + int bytesread = 0; - /*** Initialize Card System ***/ - u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN (32); - memset (SysArea, 0, CARD_WORKAREA); - CARD_Init ("FCEU", "00"); - - /*** Try to mount the card ***/ - CardError = MountCard(slot, NOTSILENT, (u8 *)SysArea); + // Try to mount the card + CardError = MountMC(slot, NOTSILENT); if (CardError == 0) { - /*** Get Sector Size ***/ + // Get Sector Size CARD_GetSectorSize (slot, &SectorSize); - if (!CardFileExists (filename, slot)) - { - if (!silent) - WaitPrompt("Unable to open file"); - return 0; - } - memset (&CardFile, 0, sizeof (CardFile)); CardError = CARD_Open (slot, filename, &CardFile); - blocks = CardFile.len; - - if (blocks < SectorSize) - blocks = SectorSize; - - if (blocks % SectorSize) - blocks += SectorSize; - - memset (buf, 0, 0x22000); - - bytesleft = blocks; - bytesread = 0; - while (bytesleft > 0) + if(CardError) { - CARD_Read (&CardFile, buf + bytesread, SectorSize, bytesread); - bytesleft -= SectorSize; - bytesread += SectorSize; + if(!silent) + ErrorPrompt("Unable to open file!"); } - CARD_Close (&CardFile); - CARD_Unmount (slot); - } - else - if (slot == CARD_SLOTA) - WaitPrompt("Unable to Mount Slot A Memory Card!"); else - WaitPrompt("Unable to Mount Slot B Memory Card!"); + { + blocks = CardFile.len; + if (blocks < SectorSize) + blocks = SectorSize; + + if (blocks % SectorSize) + blocks += SectorSize; + + bytesleft = blocks; + bytesread = 0; + while (bytesleft > 0) + { + CardError = CARD_Read (&CardFile, buf + bytesread, SectorSize, bytesread); + + if(CardError) + { + ErrorPrompt("Error loading file!"); + bytesread = 0; + break; + } + + bytesleft -= SectorSize; + bytesread += SectorSize; + ShowProgress ("Loading...", bytesread, blocks); + } + CARD_Close (&CardFile); + CancelAction(); + } + CARD_Unmount(slot); + } + + // discard save icon and comments + memmove(buf, buf+sizeof(saveicon)+64, bytesread); + bytesread -= (sizeof(saveicon)+64); + + free(SysArea); return bytesread; } @@ -277,99 +291,59 @@ SaveMCFile (char *buf, int slot, char *filename, int datasize, bool silent) int CardError; unsigned int blocks; unsigned int SectorSize; - char msg[80]; + int byteswritten = 0; + int bytesleft = 0; if(datasize <= 0) return 0; - /*** Initialize Card System ***/ - u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN (32); - memset (SysArea, 0, CARD_WORKAREA); - CARD_Init ("FCEU", "00"); + // add save icon and comments + memmove(buf+sizeof(saveicon)+64, buf, datasize); + memcpy(buf, saveicon, sizeof(saveicon)); + memcpy(buf+sizeof(saveicon), savecomments, 64); + datasize += (sizeof(saveicon)+64); - /*** Try to mount the card ***/ - CardError = MountCard(slot, NOTSILENT, (u8 *)SysArea); + // Try to mount the card + CardError = MountMC(slot, NOTSILENT); if (CardError == 0) { - /*** Get Sector Size ***/ + // Get Sector Size CARD_GetSectorSize (slot, &SectorSize); - /*** Calculate number of blocks required ***/ + // Calculate number of blocks required blocks = (datasize / SectorSize) * SectorSize; if (datasize % SectorSize) blocks += SectorSize; - /*** Does this file exist ? ***/ - if (CardFileExists (filename, slot)) + // Delete existing file (if present) + memset(&CardStatus, 0, sizeof(card_stat)); + CardError = CARD_Open (slot, filename, &CardFile); + + if(CardError == 0) { - /*** Try to open the file ***/ - CardError = CARD_Open (slot, filename, &CardFile); + CARD_Close (&CardFile); + CardError = CARD_Delete(slot, filename); if (CardError) { - CARD_Unmount (slot); - WaitPrompt("Unable to open card file!"); - return 0; - } - - if ( (s32)blocks > CardFile.len ) /*** new data is longer ***/ - { - CARD_Close (&CardFile); - - /*** Try to create temp file to check available space ***/ - CardError = CARD_Create (slot, "TEMPFILESNES9XGX201", blocks, &CardFile); - if (CardError) - { - CARD_Unmount (slot); - WaitPrompt("Not enough space to update file!"); - return 0; - } - - /*** Delete the temporary file ***/ - CARD_Close (&CardFile); - CardError = CARD_Delete(slot, "TEMPFILESNES9XGX201"); - if (CardError) - { - CARD_Unmount (slot); - WaitPrompt("Unable to delete temporary file!"); - return 0; - } - - /*** Delete the existing shorter file ***/ - CardError = CARD_Delete(slot, filename); - if (CardError) - { - CARD_Unmount (slot); - WaitPrompt("Unable to delete existing file!"); - return 0; - } - - /*** Create new, longer file ***/ - CardError = CARD_Create (slot, filename, blocks, &CardFile); - if (CardError) - { - CARD_Unmount (slot); - WaitPrompt("Unable to create updated card file!"); - return 0; - } - } - } - else /*** no file existed, create new one ***/ - { - /*** Create new file ***/ - CardError = CARD_Create (slot, filename, blocks, &CardFile); - if (CardError) - { - CARD_Unmount (slot); - if ( CardError == CARD_ERROR_INSSPACE ) - WaitPrompt("Not enough space to create file!"); - else - WaitPrompt("Unable to create card file!"); - return 0; + ErrorPrompt("Unable to delete existing file!"); + goto done; } } - /*** Now, have an open file handle, ready to send out the data ***/ + // Create new file + memset(&CardStatus, 0, sizeof(card_stat)); + CardError = CARD_Create (slot, filename, blocks, &CardFile); + if (CardError) + { + if (CardError == CARD_ERROR_INSSPACE) + ErrorPrompt("Insufficient space to create file!"); + else + ErrorPrompt("Unable to create card file!"); + goto done; + } + + // Now, have an open file handle, ready to send out the data CARD_GetStatus (slot, CardFile.filenum, &CardStatus); CardStatus.icon_addr = 0x0; CardStatus.icon_fmt = 2; @@ -377,40 +351,43 @@ SaveMCFile (char *buf, int slot, char *filename, int datasize, bool silent) CardStatus.comment_addr = 2048; CARD_SetStatus (slot, CardFile.filenum, &CardStatus); - int byteswritten = 0; - int bytesleft = blocks; + bytesleft = blocks; + while (bytesleft > 0) { CardError = - CARD_Write (&CardFile, buf + byteswritten, - SectorSize, byteswritten); + CARD_Write (&CardFile, buf + byteswritten, SectorSize, byteswritten); + + if(CardError) + { + ErrorPrompt("Error writing file!"); + byteswritten = 0; + break; + } + bytesleft -= SectorSize; byteswritten += SectorSize; - sprintf (msg, "Wrote %d of %d bytes", byteswritten, blocks); - ShowProgress (msg, byteswritten, blocks); + ShowProgress ("Saving...", byteswritten, blocks); } - CARD_Close (&CardFile); - CARD_Unmount (slot); + CancelAction(); - if ( GCSettings.VerifySaves ) + if (byteswritten > 0 && GCSettings.VerifySaves) { - /*** Verify the written file, but only up to the length we wrote - because the file could be longer due to past writes ***/ - if ( VerifyMCFile (buf, slot, filename, byteswritten) ) - return byteswritten; - else - return 0; + // Verify the written file + if (!VerifyMCFile (buf, slot, filename, byteswritten) ) + byteswritten = 0; } - else - return byteswritten; +done: + CARD_Unmount (slot); } - else - if (slot == CARD_SLOTA) - WaitPrompt("Unable to Mount Slot A Memory Card!"); - else - WaitPrompt("Unable to Mount Slot B Memory Card!"); - return 0; + free(SysArea); + return byteswritten; +} + +void SetMCSaveComments(char comments[2][32]) +{ + memcpy(savecomments, comments, 64); } diff --git a/source/ngc/memcardop.h b/source/ngc/memcardop.h index 78a3a46..5ce8fed 100644 --- a/source/ngc/memcardop.h +++ b/source/ngc/memcardop.h @@ -2,18 +2,20 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * * memcardop.h * * Memory Card routines ****************************************************************************/ -#ifndef _MEMCARDOP_H_ -#define _MEMCARDOP_H_ +#ifndef _MEMCARDOP_ +#define _MEMCARDOP_ +int ParseMCDirectory (int slot); int LoadMCFile (char *buf, int slot, char *filename, bool silent); int SaveMCFile (char *buf, int slot, char *filename, int datasize, bool silent); -bool TestCard(int slot, bool silent); +bool TestMC(int slot, bool silent); +void SetMCSaveComments(char comments[2][32]); #endif diff --git a/source/ngc/menu.cpp b/source/ngc/menu.cpp index c90d823..f3969eb 100644 --- a/source/ngc/menu.cpp +++ b/source/ngc/menu.cpp @@ -2,7 +2,7 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * * menu.c * @@ -24,109 +24,2692 @@ #include "fceugx.h" #include "fceuconfig.h" #include "pad.h" -#include "button_mapping.h" -#include "filesel.h" +#include "gcvideo.h" +#include "filebrowser.h" #include "gcunzip.h" #include "networkop.h" #include "memcardop.h" #include "fileop.h" #include "dvd.h" -#include "menudraw.h" -#include "fceustate.h" -#include "gcvideo.h" -#include "preferences.h" #include "fceuram.h" +#include "fceustate.h" +#include "preferences.h" +#include "button_mapping.h" +#include "filelist.h" +#include "gui/gui.h" +#include "menu.h" #include "fceuload.h" -extern "C" { -extern void ResetNES(void); -extern void PowerNES(void); -} +#ifdef HW_RVL +static GuiImageData * pointer[4]; +#endif -extern int menu; -extern bool romLoaded; +static GuiButton * btnLogo = NULL; +static GuiImage * gameScreenImg = NULL; +static GuiImage * bgImg = NULL; +static GuiImage * bgTopImg = NULL; +static GuiImage * bgBottomImg = NULL; +static GuiSound * bgMusic = NULL; +static GuiWindow * mainWindow = NULL; +static GuiText * settingText = NULL; +static int lastMenu = MENU_NONE; +static int mapMenuCtrl = 0; +static int mapMenuCtrlNES = 0; -/**************************************************************************** - * Load Manager - ****************************************************************************/ +static lwp_t guithread = LWP_THREAD_NULL; +static bool guiHalt = true; +static lwp_t progressthread = LWP_THREAD_NULL; +static int showProgress = 0; -int -LoadManager () -{ - int loadROM = OpenROM(GCSettings.LoadMethod); - - if ( loadROM == 1 ) // if ROM was loaded - { - // load the RAM - if (GCSettings.AutoLoad == 1) - LoadRAM(GCSettings.SaveMethod, SILENT); - else if (GCSettings.AutoLoad == 2) - LoadState(GCSettings.SaveMethod, SILENT); - - ResetNES(); - } - return loadROM; -} - -/**************************************************************************** - * Video Options Menu - ****************************************************************************/ +static char progressTitle[100]; +static char progressMsg[200]; +static int progressDone = 0; +static int progressTotal = 0; static void -VideoOptions () +ResumeGui() { - int videomenuCount = 7; - char videomenu[][50] = { + guiHalt = false; + LWP_ResumeThread (guithread); +} - "Video Rendering", - "Video Scaling", - "Video Cropping", - "Palette", - "Enable Zooming", - "Timing", - "Back to Preferences Menu" +static void +HaltGui() +{ + guiHalt = true; + // wait for thread to finish + while(!LWP_ThreadIsSuspended(guithread)) + usleep(50); +} + +/**************************************************************************** + * WindowPrompt + ***************************************************************************/ + +int +WindowPrompt(const char *title, const char *msg, const char *btn1Label, const char *btn2Label) +{ + int choice = -1; + + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt(title, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + msgTxt.SetPosition(0,-20); + msgTxt.SetMaxWidth(430); + + GuiText btn1Txt(btn1Label, 24, (GXColor){0, 0, 0, 255}); + GuiImage btn1Img(&btnOutline); + GuiImage btn1ImgOver(&btnOutlineOver); + GuiButton btn1(btnOutline.GetWidth(), btnOutline.GetHeight()); + + if(btn2Label) + { + btn1.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + btn1.SetPosition(20, -25); + } + else + { + btn1.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + btn1.SetPosition(0, -25); + } + + btn1.SetLabel(&btn1Txt); + btn1.SetImage(&btn1Img); + btn1.SetImageOver(&btn1ImgOver); + btn1.SetSoundOver(&btnSoundOver); + btn1.SetTrigger(&trigA); + btn1.SetState(STATE_SELECTED); + btn1.SetEffectGrow(); + + GuiText btn2Txt(btn2Label, 24, (GXColor){0, 0, 0, 255}); + GuiImage btn2Img(&btnOutline); + GuiImage btn2ImgOver(&btnOutlineOver); + GuiButton btn2(btnOutline.GetWidth(), btnOutline.GetHeight()); + btn2.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btn2.SetPosition(-20, -25); + btn2.SetLabel(&btn2Txt); + btn2.SetImage(&btn2Img); + btn2.SetImageOver(&btn2ImgOver); + btn2.SetSoundOver(&btnSoundOver); + btn2.SetTrigger(&trigA); + btn2.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + promptWindow.Append(&btn1); + + if(btn2Label) + promptWindow.Append(&btn2); + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + CancelAction(); + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + while(choice == -1) + { + VIDEO_WaitVSync(); + + if(btn1.GetState() == STATE_CLICKED) + choice = 1; + else if(btn2.GetState() == STATE_CLICKED) + choice = 0; + } + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while(promptWindow.GetEffect() > 0) usleep(50); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return choice; +} + +/**************************************************************************** + * UpdateGUI + ***************************************************************************/ + +/*static u32 arena1mem = 0; +static u32 arena2mem = 0; +static char mem[150] = { 0 }; +static GuiText * memTxt = NULL;*/ + +static void * +UpdateGUI (void *arg) +{ + while(1) + { + if(guiHalt) + { + LWP_SuspendThread(guithread); + } + else + { + /*arena1mem = (u32)SYS_GetArena1Hi() - (u32)SYS_GetArena1Lo(); + #ifdef HW_RVL + arena2mem = (u32)SYS_GetArena2Hi() - (u32)SYS_GetArena2Lo(); + #endif + sprintf(mem, "A1: %u / A2: %u", arena1mem, arena2mem); + if(memTxt) memTxt->SetText(mem);*/ + + mainWindow->Draw(); + + #ifdef HW_RVL + for(int i=3; i >= 0; i--) // so that player 1's cursor appears on top! + { + if(userInput[i].wpad.ir.valid) + Menu_DrawImg(userInput[i].wpad.ir.x-48, userInput[i].wpad.ir.y-48, + 96, 96, pointer[i]->GetImage(), userInput[i].wpad.ir.angle, 1, 1, 255); + DoRumble(i); + } + #endif + + Menu_Render(); + + for(int i=0; i < 4; i++) + mainWindow->Update(&userInput[i]); + + #ifdef HW_RVL + if(updateFound) + { + updateFound = WindowPrompt( + "Update Available", + "An update is available!", + "Update now", + "Update later"); + if(updateFound) + if(DownloadUpdate()) + ExitRequested = 1; + } + #endif + + if(ExitRequested || ShutdownRequested) + { + for(int a = 0; a < 255; a += 15) + { + mainWindow->Draw(); + Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0, 0, 0, a},1); + Menu_Render(); + } + + if(ExitRequested) + ExitApp(); + #ifdef HW_RVL + else if(ShutdownRequested) + ShutdownWii(); + #endif + } + } + } + return NULL; +} + +/**************************************************************************** + * ProgressWindow + ***************************************************************************/ + +static void +ProgressWindow(char *title, char *msg) +{ + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiImageData progressbarOutline(progressbar_outline_png); + GuiImage progressbarOutlineImg(&progressbarOutline); + progressbarOutlineImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarOutlineImg.SetPosition(25, 40); + + GuiImageData progressbarEmpty(progressbar_empty_png); + GuiImage progressbarEmptyImg(&progressbarEmpty); + progressbarEmptyImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarEmptyImg.SetPosition(25, 40); + progressbarEmptyImg.SetTile(100); + + GuiImageData progressbar(progressbar_png); + GuiImage progressbarImg(&progressbar); + progressbarImg.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + progressbarImg.SetPosition(25, 40); + + GuiImageData throbber(throbber_png); + GuiImage throbberImg(&throbber); + throbberImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + throbberImg.SetPosition(0, 40); + + GuiText titleTxt(title, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + msgTxt.SetPosition(0,80); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + + if(showProgress == 1) + { + promptWindow.Append(&progressbarEmptyImg); + promptWindow.Append(&progressbarImg); + promptWindow.Append(&progressbarOutlineImg); + } + else + { + promptWindow.Append(&throbberImg); + } + + usleep(400000); // wait to see if progress flag changes soon + if(!showProgress) + return; + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + float angle = 0; + u32 count = 0; + + while(showProgress) + { + VIDEO_WaitVSync(); + + if(showProgress == 1) + { + progressbarImg.SetTile(100*progressDone/progressTotal); + } + else if(showProgress == 2) + { + if(count % 5 == 0) + { + angle+=45; + if(angle >= 360) + angle = 0; + throbberImg.SetAngle(angle); + } + count++; + } + } + + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); +} + +static void * ProgressThread (void *arg) +{ + while(1) + { + if(!showProgress) + LWP_SuspendThread (progressthread); + + ProgressWindow(progressTitle, progressMsg); + } + return NULL; +} + +/**************************************************************************** + * InitGUIThread + ***************************************************************************/ + +void +InitGUIThreads() +{ + LWP_CreateThread (&guithread, UpdateGUI, NULL, NULL, 0, 70); + LWP_CreateThread (&progressthread, ProgressThread, NULL, NULL, 0, 40); +} + +/**************************************************************************** + * Progress Bar + * + * Show the user what's happening + ***************************************************************************/ + +void +CancelAction() +{ + showProgress = 0; + + // wait for thread to finish + while(!LWP_ThreadIsSuspended(progressthread)) + usleep(50); +} + +void +ShowProgress (const char *msg, int done, int total) +{ + if(total < (256*1024)) + return; + else if(done > total) // this shouldn't happen + done = total; + + if(done/total > 0.99) + done = total; + + if(showProgress != 1) + CancelAction(); // wait for previous progress window to finish + + strncpy(progressMsg, msg, 200); + sprintf(progressTitle, "Please Wait"); + showProgress = 1; + progressTotal = total; + progressDone = done; + LWP_ResumeThread (progressthread); +} + +void +ShowAction (const char *msg) +{ + if(showProgress != 2) + CancelAction(); // wait for previous progress window to finish + + strncpy(progressMsg, msg, 200); + sprintf(progressTitle, "Please Wait"); + showProgress = 2; + progressDone = 0; + progressTotal = 0; + LWP_ResumeThread (progressthread); +} + +void ErrorPrompt(const char *msg) +{ + WindowPrompt("Error", msg, "OK", NULL); +} + +int ErrorPromptRetry(const char *msg) +{ + return WindowPrompt("Error", msg, "Retry", "Cancel"); +} + +void InfoPrompt(const char *msg) +{ + WindowPrompt("Information", msg, "OK", NULL); +} + +void AutoSave() +{ + if (GCSettings.AutoSave == 1) + { + SaveRAMAuto(GCSettings.SaveMethod, SILENT); + } + else if (GCSettings.AutoSave == 2) + { + if (WindowPrompt("Save", "Save State?", "Save", "Don't Save") ) + SaveStateAuto(GCSettings.SaveMethod, NOTSILENT); + } + else if (GCSettings.AutoSave == 3) + { + if (WindowPrompt("Save", "Save RAM and State?", "Save", "Don't Save") ) + { + SaveRAMAuto(GCSettings.SaveMethod, NOTSILENT); + SaveStateAuto(GCSettings.SaveMethod, NOTSILENT); + } + } +} + +static void OnScreenKeyboard(char * var) +{ + int save = -1; + + GuiKeyboard keyboard(var); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiText okBtnTxt("OK", 24, (GXColor){0, 0, 0, 255}); + GuiImage okBtnImg(&btnOutline); + GuiImage okBtnImgOver(&btnOutlineOver); + GuiButton okBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + + okBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + okBtn.SetPosition(25, -25); + + okBtn.SetLabel(&okBtnTxt); + okBtn.SetImage(&okBtnImg); + okBtn.SetImageOver(&okBtnImgOver); + okBtn.SetSoundOver(&btnSoundOver); + okBtn.SetTrigger(&trigA); + okBtn.SetEffectGrow(); + + GuiText cancelBtnTxt("Cancel", 24, (GXColor){0, 0, 0, 255}); + GuiImage cancelBtnImg(&btnOutline); + GuiImage cancelBtnImgOver(&btnOutlineOver); + GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + cancelBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + cancelBtn.SetPosition(-25, -25); + cancelBtn.SetLabel(&cancelBtnTxt); + cancelBtn.SetImage(&cancelBtnImg); + cancelBtn.SetImageOver(&cancelBtnImgOver); + cancelBtn.SetSoundOver(&btnSoundOver); + cancelBtn.SetTrigger(&trigA); + cancelBtn.SetEffectGrow(); + + keyboard.Append(&okBtn); + keyboard.Append(&cancelBtn); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&keyboard); + mainWindow->ChangeFocus(&keyboard); + ResumeGui(); + + while(save == -1) + { + VIDEO_WaitVSync(); + + if(okBtn.GetState() == STATE_CLICKED) + save = 1; + else if(cancelBtn.GetState() == STATE_CLICKED) + save = 0; + } + + if(save) + { + strncpy(var, keyboard.kbtextstr, 100); + var[100] = 0; + } + + HaltGui(); + mainWindow->Remove(&keyboard); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); +} + +static int +SettingWindow(const char * title, GuiWindow * w) +{ + int save = -1; + + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt(title, 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + + GuiText okBtnTxt("OK", 24, (GXColor){0, 0, 0, 255}); + GuiImage okBtnImg(&btnOutline); + GuiImage okBtnImgOver(&btnOutlineOver); + GuiButton okBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + + okBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + okBtn.SetPosition(20, -25); + + okBtn.SetLabel(&okBtnTxt); + okBtn.SetImage(&okBtnImg); + okBtn.SetImageOver(&okBtnImgOver); + okBtn.SetSoundOver(&btnSoundOver); + okBtn.SetTrigger(&trigA); + okBtn.SetEffectGrow(); + + GuiText cancelBtnTxt("Cancel", 24, (GXColor){0, 0, 0, 255}); + GuiImage cancelBtnImg(&btnOutline); + GuiImage cancelBtnImgOver(&btnOutlineOver); + GuiButton cancelBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + cancelBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + cancelBtn.SetPosition(-20, -25); + cancelBtn.SetLabel(&cancelBtnTxt); + cancelBtn.SetImage(&cancelBtnImg); + cancelBtn.SetImageOver(&cancelBtnImgOver); + cancelBtn.SetSoundOver(&btnSoundOver); + cancelBtn.SetTrigger(&trigA); + cancelBtn.SetEffectGrow(); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&okBtn); + promptWindow.Append(&cancelBtn); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->Append(w); + mainWindow->ChangeFocus(w); + ResumeGui(); + + while(save == -1) + { + VIDEO_WaitVSync(); + + if(okBtn.GetState() == STATE_CLICKED) + save = 1; + else if(cancelBtn.GetState() == STATE_CLICKED) + save = 0; + } + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->Remove(w); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + return save; +} + +/**************************************************************************** + * WindowCredits + * Display credits, legal copyright and licence + * + * THIS MUST NOT BE REMOVED OR DISABLED IN ANY DERIVATIVE WORK + ***************************************************************************/ + +static void WindowCredits(void * ptr) +{ + if(btnLogo->GetState() != STATE_CLICKED) + return; + + btnLogo->ResetState(); + + bool exit = false; + int i = 0; + int y = 20; + + GuiWindow creditsWindow(screenwidth,screenheight); + GuiWindow creditsWindowBox(580,448); + creditsWindowBox.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + GuiImageData creditsBox(credits_box_png); + GuiImage creditsBoxImg(&creditsBox); + creditsBoxImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + creditsWindowBox.Append(&creditsBoxImg); + + int numEntries = 23; + GuiText * txt[numEntries]; + + txt[i] = new GuiText("Credits", 30, (GXColor){0, 0, 0, 255}); + txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); i++; y+=32; + + txt[i] = new GuiText("Official Site: http://code.google.com/p/fceugc/", 20, (GXColor){0, 0, 0, 255}); + txt[i]->SetAlignment(ALIGN_CENTRE, ALIGN_TOP); txt[i]->SetPosition(0,y); i++; y+=40; + + txt[i]->SetPresets(22, (GXColor){0, 0, 0, 255}, 0, + FTGX_JUSTIFY_LEFT | FTGX_ALIGN_TOP, ALIGN_LEFT, ALIGN_TOP); + + txt[i] = new GuiText("Coding & menu design"); + txt[i]->SetPosition(50,y); i++; + txt[i] = new GuiText("Tantric"); + txt[i]->SetPosition(320,y); i++; y+=24; + txt[i] = new GuiText("Menu artwork"); + txt[i]->SetPosition(50,y); i++; + txt[i] = new GuiText("the3seashells"); + txt[i]->SetPosition(320,y); i++; y+=24; + txt[i] = new GuiText("Menu sound"); + txt[i]->SetPosition(50,y); i++; + txt[i] = new GuiText("Peter de Man"); + txt[i]->SetPosition(320,y); i++; y+=48; + + txt[i] = new GuiText("FCE Ultra GX GameCube"); + txt[i]->SetPosition(50,y); i++; + txt[i] = new GuiText("SoftDev, askot,"); + txt[i]->SetPosition(320,y); i++; y+=24; + txt[i] = new GuiText("dsbomb, others"); + txt[i]->SetPosition(320,y); i++; y+=24; + txt[i] = new GuiText("FCE Ultra"); + txt[i]->SetPosition(50,y); i++; + txt[i] = new GuiText("Xodnizel"); + txt[i]->SetPosition(320,y); i++; y+=24; + txt[i] = new GuiText("Original FCE"); + txt[i]->SetPosition(50,y); i++; + txt[i] = new GuiText("BERO"); + txt[i]->SetPosition(320,y); i++; y+=24; + + txt[i] = new GuiText("libogc / devkitPPC"); + txt[i]->SetPosition(50,y); i++; + txt[i] = new GuiText("shagkur & wintermute"); + txt[i]->SetPosition(320,y); i++; y+=24; + txt[i] = new GuiText("FreeTypeGX"); + txt[i]->SetPosition(50,y); i++; + txt[i] = new GuiText("Armin Tamzarian"); + txt[i]->SetPosition(320,y); i++; y+=48; + + txt[i]->SetPresets(18, (GXColor){0, 0, 0, 255}, 0, + FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP, ALIGN_CENTRE, ALIGN_TOP); + + txt[i] = new GuiText("This software is open source and may be copied,"); + txt[i]->SetPosition(0,y); i++; y+=20; + txt[i] = new GuiText("distributed, or modified under the terms of the"); + txt[i]->SetPosition(0,y); i++; y+=20; + txt[i] = new GuiText("GNU General Public License (GPL) Version 2."); + txt[i]->SetPosition(0,y); i++; y+=20; + + for(i=0; i < numEntries; i++) + creditsWindowBox.Append(txt[i]); + + creditsWindow.Append(&creditsWindowBox); + + while(!exit) + { + if(gameScreenImg) + gameScreenImg->Draw(); + else + bgImg->Draw(); + + bgBottomImg->Draw(); + bgTopImg->Draw(); + creditsWindow.Draw(); + + for(i=3; i >= 0; i--) + { + #ifdef HW_RVL + if(userInput[i].wpad.ir.valid) + Menu_DrawImg(userInput[i].wpad.ir.x-48, userInput[i].wpad.ir.y-48, + 96, 96, pointer[i]->GetImage(), userInput[i].wpad.ir.angle, 1, 1, 255); + DoRumble(i); + #endif + } + + Menu_Render(); + + for(i=0; i < 4; i++) + { + if(userInput[i].wpad.btns_d || userInput[i].pad.btns_d) + exit = true; + } + } + + // clear buttons pressed + for(i=0; i < 4; i++) + { + userInput[i].wpad.btns_d = 0; + userInput[i].pad.btns_d = 0; + } + + for(i=0; i < numEntries; i++) + delete txt[i]; +} + +/**************************************************************************** + * MenuGameSelection + ***************************************************************************/ + +static int MenuGameSelection() +{ + #ifdef HW_RVL + ShutoffRumble(); + #endif + + // populate initial directory listing + if(OpenGameList() <= 0) + { + int choice = WindowPrompt( + "Error", + "Games directory is inaccessible on selected load device.", + "Retry", + "Check Settings"); + + if(choice) + return MENU_GAMESELECTION; + else + return MENU_SETTINGS_FILE; + } + + int menu = MENU_NONE; + + GuiText titleTxt("Choose Game", 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData iconHome(icon_home_png); + GuiImageData iconSettings(icon_settings_png); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText settingsBtnTxt("Settings", 24, (GXColor){0, 0, 0, 255}); + GuiImage settingsBtnIcon(&iconSettings); + settingsBtnIcon.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + settingsBtnIcon.SetPosition(20,0); + GuiImage settingsBtnImg(&btnOutline); + GuiImage settingsBtnImgOver(&btnOutlineOver); + GuiButton settingsBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + settingsBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + settingsBtn.SetPosition(100, -35); + settingsBtn.SetLabel(&settingsBtnTxt); + settingsBtn.SetIcon(&settingsBtnIcon); + settingsBtn.SetImage(&settingsBtnImg); + settingsBtn.SetImageOver(&settingsBtnImgOver); + settingsBtn.SetSoundOver(&btnSoundOver); + settingsBtn.SetTrigger(&trigA); + settingsBtn.SetEffectGrow(); + + GuiText exitBtnTxt("Exit", 24, (GXColor){0, 0, 0, 255}); + GuiImage exitBtnIcon(&iconHome); + exitBtnIcon.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + exitBtnIcon.SetPosition(20,0); + GuiImage exitBtnImg(&btnOutline); + GuiImage exitBtnImgOver(&btnOutlineOver); + GuiButton exitBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + exitBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + exitBtn.SetPosition(-100, -35); + exitBtn.SetLabel(&exitBtnTxt); + exitBtn.SetIcon(&exitBtnIcon); + exitBtn.SetImage(&exitBtnImg); + exitBtn.SetImageOver(&exitBtnImgOver); + exitBtn.SetSoundOver(&btnSoundOver); + exitBtn.SetTrigger(&trigA); + exitBtn.SetTrigger(&trigHome); + exitBtn.SetEffectGrow(); + + GuiWindow buttonWindow(screenwidth, screenheight); + buttonWindow.Append(&settingsBtn); + buttonWindow.Append(&exitBtn); + + GuiFileBrowser gameBrowser(424, 248); + gameBrowser.SetPosition(50, 108); + + HaltGui(); + btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + btnLogo->SetPosition(-30, 30); + mainWindow->Append(&titleTxt); + mainWindow->Append(&gameBrowser); + mainWindow->Append(&buttonWindow); + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync(); + + // update gameWindow based on arrow buttons + // set MENU_EXIT if A button pressed on a game + for(int i=0; iGetState() == STATE_CLICKED) + { + gameBrowser.gameList[i]->ResetState(); + // check corresponding browser entry + if(browserList[browser.selIndex].isdir || IsSz()) + { + bool res; + + if(IsSz()) + res = BrowserLoadSz(GCSettings.LoadMethod); + else + res = BrowserChangeFolder(GCSettings.LoadMethod); + + if(res) + { + gameBrowser.ResetState(); + gameBrowser.gameList[0]->SetState(STATE_SELECTED); + gameBrowser.TriggerUpdate(); + } + else + { + menu = MENU_GAMESELECTION; + break; + } + } + else + { + #ifdef HW_RVL + ShutoffRumble(); + #endif + mainWindow->SetState(STATE_DISABLED); + if(BrowserLoadFile(GCSettings.LoadMethod)) + menu = MENU_EXIT; + mainWindow->SetState(STATE_DEFAULT); + } + } + } + + if(settingsBtn.GetState() == STATE_CLICKED) + menu = MENU_SETTINGS; + else if(exitBtn.GetState() == STATE_CLICKED) + ExitRequested = 1; + } + HaltGui(); + mainWindow->Remove(&titleTxt); + mainWindow->Remove(&buttonWindow); + mainWindow->Remove(&gameBrowser); + return menu; +} + +static void ControllerWindowUpdate(void * ptr, int dir) +{ + GuiButton * b = (GuiButton *)ptr; + if(b->GetState() == STATE_CLICKED) + { + GCSettings.Controller += dir; + + if(GCSettings.Controller == CTRL_PAD) // skip + GCSettings.Controller += dir; + + if(GCSettings.Controller > CTRL_LENGTH-1) + GCSettings.Controller = 0; + else if(GCSettings.Controller < 0) + GCSettings.Controller = CTRL_LENGTH-1; + + settingText->SetText(ctrlName[GCSettings.Controller]); + b->ResetState(); + } +} + +static void ControllerWindowLeftClick(void * ptr) { ControllerWindowUpdate(ptr, -1); } +static void ControllerWindowRightClick(void * ptr) { ControllerWindowUpdate(ptr, +1); } + +static void ControllerWindow() +{ + GuiWindow * w = new GuiWindow(250,250); + w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiTrigger trigLeft; + trigLeft.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); + + GuiTrigger trigRight; + trigRight.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); + + GuiImageData arrowLeft(button_arrow_left_png); + GuiImage arrowLeftImg(&arrowLeft); + GuiImageData arrowLeftOver(button_arrow_left_over_png); + GuiImage arrowLeftOverImg(&arrowLeftOver); + GuiButton arrowLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight()); + arrowLeftBtn.SetImage(&arrowLeftImg); + arrowLeftBtn.SetImageOver(&arrowLeftOverImg); + arrowLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + arrowLeftBtn.SetTrigger(0, &trigA); + arrowLeftBtn.SetTrigger(1, &trigLeft); + arrowLeftBtn.SetSelectable(false); + arrowLeftBtn.SetUpdateCallback(ControllerWindowLeftClick); + + GuiImageData arrowRight(button_arrow_right_png); + GuiImage arrowRightImg(&arrowRight); + GuiImageData arrowRightOver(button_arrow_right_over_png); + GuiImage arrowRightOverImg(&arrowRightOver); + GuiButton arrowRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight()); + arrowRightBtn.SetImage(&arrowRightImg); + arrowRightBtn.SetImageOver(&arrowRightOverImg); + arrowRightBtn.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE); + arrowRightBtn.SetTrigger(0, &trigA); + arrowRightBtn.SetTrigger(1, &trigRight); + arrowRightBtn.SetSelectable(false); + arrowRightBtn.SetUpdateCallback(ControllerWindowRightClick); + + settingText = new GuiText(ctrlName[GCSettings.Controller], 24, (GXColor){0, 0, 0, 255}); + + int currentController = GCSettings.Controller; + + w->Append(&arrowLeftBtn); + w->Append(&arrowRightBtn); + w->Append(settingText); + + if(!SettingWindow("Controller",w)) + GCSettings.Controller = currentController; // undo changes + + delete(w); + delete(settingText); +} + +/**************************************************************************** + * MenuGame + ***************************************************************************/ + +static int MenuGame() +{ + int menu = MENU_NONE; + + GuiText titleTxt((char *)romFilename, 24, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnCloseOutline(button_close_png); + GuiImageData btnCloseOutlineOver(button_close_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + GuiImageData battery(battery_png); + GuiImageData batteryRed(battery_red_png); + GuiImageData batteryBar(battery_bar_png); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText saveBtnTxt("Save", 24, (GXColor){0, 0, 0, 255}); + GuiImage saveBtnImg(&btnLargeOutline); + GuiImage saveBtnImgOver(&btnLargeOutlineOver); + GuiButton saveBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + saveBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + saveBtn.SetPosition(50, 120); + saveBtn.SetLabel(&saveBtnTxt); + saveBtn.SetImage(&saveBtnImg); + saveBtn.SetImageOver(&saveBtnImgOver); + saveBtn.SetSoundOver(&btnSoundOver); + saveBtn.SetTrigger(&trigA); + saveBtn.SetEffectGrow(); + + GuiText loadBtnTxt("Load", 24, (GXColor){0, 0, 0, 255}); + GuiImage loadBtnImg(&btnLargeOutline); + GuiImage loadBtnImgOver(&btnLargeOutlineOver); + GuiButton loadBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + loadBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + loadBtn.SetPosition(0, 120); + loadBtn.SetLabel(&loadBtnTxt); + loadBtn.SetImage(&loadBtnImg); + loadBtn.SetImageOver(&loadBtnImgOver); + loadBtn.SetSoundOver(&btnSoundOver); + loadBtn.SetTrigger(&trigA); + loadBtn.SetEffectGrow(); + + GuiText resetBtnTxt("Reset", 24, (GXColor){0, 0, 0, 255}); + GuiImage resetBtnImg(&btnLargeOutline); + GuiImage resetBtnImgOver(&btnLargeOutlineOver); + GuiButton resetBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + resetBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + resetBtn.SetPosition(-50, 120); + resetBtn.SetLabel(&resetBtnTxt); + resetBtn.SetImage(&resetBtnImg); + resetBtn.SetImageOver(&resetBtnImgOver); + resetBtn.SetSoundOver(&btnSoundOver); + resetBtn.SetTrigger(&trigA); + resetBtn.SetEffectGrow(); + + GuiText controllerBtnTxt("Controller", 24, (GXColor){0, 0, 0, 255}); + GuiImage controllerBtnImg(&btnLargeOutline); + GuiImage controllerBtnImgOver(&btnLargeOutlineOver); + GuiButton controllerBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + controllerBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + controllerBtn.SetPosition(-125, 250); + controllerBtn.SetLabel(&controllerBtnTxt); + controllerBtn.SetImage(&controllerBtnImg); + controllerBtn.SetImageOver(&controllerBtnImgOver); + controllerBtn.SetSoundOver(&btnSoundOver); + controllerBtn.SetTrigger(&trigA); + controllerBtn.SetEffectGrow(); + + /*GuiText cheatsBtnTxt("Cheats", 24, (GXColor){0, 0, 0, 255}); + GuiImage cheatsBtnImg(&btnLargeOutline); + GuiImage cheatsBtnImgOver(&btnLargeOutlineOver); + GuiButton cheatsBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + cheatsBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + cheatsBtn.SetPosition(125, 250); + cheatsBtn.SetLabel(&cheatsBtnTxt); + cheatsBtn.SetImage(&cheatsBtnImg); + cheatsBtn.SetImageOver(&cheatsBtnImgOver); + cheatsBtn.SetSoundOver(&btnSoundOver); + cheatsBtn.SetTrigger(&trigA); + cheatsBtn.SetEffectGrow();*/ + + GuiText mainmenuBtnTxt("Main Menu", 24, (GXColor){0, 0, 0, 255}); + GuiImage mainmenuBtnImg(&btnOutline); + GuiImage mainmenuBtnImgOver(&btnOutlineOver); + GuiButton mainmenuBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + mainmenuBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + mainmenuBtn.SetPosition(0, -35); + mainmenuBtn.SetLabel(&mainmenuBtnTxt); + mainmenuBtn.SetImage(&mainmenuBtnImg); + mainmenuBtn.SetImageOver(&mainmenuBtnImgOver); + mainmenuBtn.SetSoundOver(&btnSoundOver); + mainmenuBtn.SetTrigger(&trigA); + mainmenuBtn.SetEffectGrow(); + + GuiText closeBtnTxt("Close", 22, (GXColor){0, 0, 0, 255}); + GuiImage closeBtnImg(&btnCloseOutline); + GuiImage closeBtnImgOver(&btnCloseOutlineOver); + GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + closeBtn.SetPosition(-30, 35); + closeBtn.SetLabel(&closeBtnTxt); + closeBtn.SetImage(&closeBtnImg); + closeBtn.SetImageOver(&closeBtnImgOver); + closeBtn.SetSoundOver(&btnSoundOver); + closeBtn.SetTrigger(&trigA); + closeBtn.SetTrigger(&trigHome); + closeBtn.SetEffectGrow(); + + #ifdef HW_RVL + int i = 0; + char txt[3]; + GuiText * batteryTxt[4]; + GuiImage * batteryImg[4]; + GuiImage * batteryBarImg[4]; + GuiButton * batteryBtn[4]; + + for(i=0; i < 4; i++) + { + if(i == 0) + sprintf(txt, "P %d", i+1); + else + sprintf(txt, "P%d", i+1); + + batteryTxt[i] = new GuiText(txt, 22, (GXColor){255, 255, 255, 255}); + batteryTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i] = new GuiImage(&battery); + batteryImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryImg[i]->SetPosition(30, 0); + batteryBarImg[i] = new GuiImage(&batteryBar); + batteryBarImg[i]->SetTile(0); + batteryBarImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + batteryBarImg[i]->SetPosition(34, 0); + + batteryBtn[i] = new GuiButton(70, 20); + batteryBtn[i]->SetLabel(batteryTxt[i]); + batteryBtn[i]->SetImage(batteryImg[i]); + batteryBtn[i]->SetIcon(batteryBarImg[i]); + batteryBtn[i]->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + batteryBtn[i]->SetRumble(false); + batteryBtn[i]->SetAlpha(150); + } + + batteryBtn[0]->SetPosition(45, -65); + batteryBtn[1]->SetPosition(135, -65); + batteryBtn[2]->SetPosition(45, -40); + batteryBtn[3]->SetPosition(135, -40); + #endif + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&saveBtn); + w.Append(&loadBtn); + w.Append(&resetBtn); + w.Append(&controllerBtn); + //w.Append(&cheatsBtn); + + #ifdef HW_RVL + w.Append(batteryBtn[0]); + w.Append(batteryBtn[1]); + w.Append(batteryBtn[2]); + w.Append(batteryBtn[3]); + #endif + + w.Append(&mainmenuBtn); + w.Append(&closeBtn); + + btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + btnLogo->SetPosition(-30, -40); + mainWindow->Append(&w); + + if(lastMenu == MENU_NONE) + { + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 35); + mainmenuBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + #ifdef HW_RVL + batteryBtn[0]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + batteryBtn[1]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + batteryBtn[2]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + batteryBtn[3]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_IN, 35); + #endif + + saveBtn.SetEffect(EFFECT_FADE, 15); + loadBtn.SetEffect(EFFECT_FADE, 15); + resetBtn.SetEffect(EFFECT_FADE, 15); + controllerBtn.SetEffect(EFFECT_FADE, 15); + //cheatsBtn.SetEffect(EFFECT_FADE, 15); + + AutoSave(); + } + + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync(); + + #ifdef HW_RVL + int level; + for(i=0; i < 4; i++) + { + if(WPAD_Probe(i, NULL) == WPAD_ERR_NONE) // controller connected + { + level = (userInput[i].wpad.battery_level / 100.0) * 4; + batteryBarImg[i]->SetTile(level); + + if(level == 0) + batteryImg[i]->SetImage(&batteryRed); + else + batteryImg[i]->SetImage(&battery); + + batteryBtn[i]->SetAlpha(255); + } + else // controller not connected + { + batteryBarImg[i]->SetTile(0); + batteryImg[i]->SetImage(&battery); + batteryBtn[i]->SetAlpha(150); + } + } + #endif + + if(saveBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME_SAVE; + } + else if(loadBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME_LOAD; + } + else if(resetBtn.GetState() == STATE_CLICKED) + { + PowerNES(); + menu = MENU_EXIT; + } + else if(controllerBtn.GetState() == STATE_CLICKED) + { + ControllerWindow(); + } + /*else if(cheatsBtn.GetState() == STATE_CLICKED) + { + cheatsBtn.ResetState(); + if(Cheat.num_cheats > 0) + menu = MENU_GAME_CHEATS; + else + InfoPrompt("Cheats file not found!"); + }*/ + else if(mainmenuBtn.GetState() == STATE_CLICKED) + { + if(gameScreenImg) + { + mainWindow->Remove(gameScreenImg); + delete gameScreenImg; + gameScreenImg = NULL; + } + if(gameScreenTex) + { + free(gameScreenTex); + gameScreenTex = NULL; + } + bgImg->SetVisible(true); + #ifndef NO_SOUND + bgMusic->Play(); // startup music + #endif + menu = MENU_GAMESELECTION; + } + else if(closeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_EXIT; + + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 35); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 35); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 35); + mainmenuBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + #ifdef HW_RVL + batteryBtn[0]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + batteryBtn[1]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + batteryBtn[2]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + batteryBtn[3]->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + #endif + + saveBtn.SetEffect(EFFECT_FADE, -15); + loadBtn.SetEffect(EFFECT_FADE, -15); + resetBtn.SetEffect(EFFECT_FADE, -15); + controllerBtn.SetEffect(EFFECT_FADE, -15); + //cheatsBtn.SetEffect(EFFECT_FADE, -15); + + usleep(150000); // wait for effects to finish + } + } + + HaltGui(); + + #ifdef HW_RVL + for(i=0; i < 4; i++) + { + delete batteryTxt[i]; + delete batteryImg[i]; + delete batteryBarImg[i]; + delete batteryBtn[i]; + } + #endif + + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * MenuGameSaves + ***************************************************************************/ + +static int MenuGameSaves(int action) +{ + int menu = MENU_NONE; + int ret; + int i, len, len2; + int j = 0; + SaveList saves; + char filepath[1024]; + int method = GCSettings.SaveMethod; + + if(method == METHOD_AUTO) + autoSaveMethod(NOTSILENT); + + if(!ChangeInterface(method, NOTSILENT)) + return MENU_GAME; + + GuiText titleTxt(NULL, 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + if(action == 0) + titleTxt.SetText("Load Game"); + else + titleTxt.SetText("Save Game"); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnCloseOutline(button_close_png); + GuiImageData btnCloseOutlineOver(button_close_over_png); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText backBtnTxt("Go Back", 24, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetTrigger(&trigA); + backBtn.SetEffectGrow(); + + GuiText closeBtnTxt("Close", 22, (GXColor){0, 0, 0, 255}); + GuiImage closeBtnImg(&btnCloseOutline); + GuiImage closeBtnImgOver(&btnCloseOutlineOver); + GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + closeBtn.SetPosition(-30, 35); + closeBtn.SetLabel(&closeBtnTxt); + closeBtn.SetImage(&closeBtnImg); + closeBtn.SetImageOver(&closeBtnImgOver); + closeBtn.SetSoundOver(&btnSoundOver); + closeBtn.SetTrigger(&trigA); + closeBtn.SetTrigger(&trigHome); + closeBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + w.Append(&closeBtn); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + memset(&saves, 0, sizeof(saves)); + + if(method == METHOD_MC_SLOTA) + { + ParseMCDirectory(CARD_SLOTA); + } + else if(method == METHOD_MC_SLOTB) + { + ParseMCDirectory(CARD_SLOTB); + } + else + { + strncpy(browser.dir, GCSettings.SaveFolder, 200); + ParseDirectory(GCSettings.SaveMethod); + } + + for(i=0; i < browser.numEntries; i++) + { + len = strlen(romFilename); + len2 = strlen(browserList[i].filename); + + if(len > 26 && (method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)) + len = 26; // memory card filenames are a maximum of 32 chars + + // find matching files + if(len2 > 5 && strncmp(browserList[i].filename, romFilename, len) == 0) + { + if(strncmp(&browserList[i].filename[len2-4], ".sav", 4) == 0) + saves.type[j] = FILE_RAM; + else if(strncmp(&browserList[i].filename[len2-4], ".fcs", 4) == 0) + saves.type[j] = FILE_STATE; + else + saves.type[j] = -1; + + if(saves.type[j] != -1) + { + int n = -1; + char tmp[256]; + strncpy(tmp, browserList[i].filename, 255); + tmp[len2-4] = 0; + + if(len2 - len == 7) + n = atoi(&tmp[len2-5]); + else if(len2 - len == 6) + n = atoi(&tmp[len2-6]); + + if(n > 0 && n < MAX_SAVES) + saves.files[saves.type[j]][n] = 1; + + strncpy(saves.filename[j], browserList[i].filename, 255); + + if(method != METHOD_MC_SLOTA && method != METHOD_MC_SLOTB) + { + if(saves.type[j] == FILE_STATE) + { + char scrfile[1024]; + sprintf(scrfile, "%s/%s.png", GCSettings.SaveFolder, tmp); + + AllocSaveBuffer(); + if(LoadFile(scrfile, GCSettings.SaveMethod, SILENT)) + saves.previewImg[j] = new GuiImageData(savebuffer); + FreeSaveBuffer(); + } + struct tm * timeinfo = localtime(&browserList[j].mtime); + strftime(saves.date[j], 20, "%a %b %d", timeinfo); + strftime(saves.time[j], 10, "%I:%M %p", timeinfo); + } + j++; + } + } + } + + saves.length = j; + + if(saves.length == 0 && action == 0) + { + InfoPrompt("No game saves found."); + menu = MENU_GAME; + } + + GuiSaveBrowser saveBrowser(552, 248, &saves, action); + saveBrowser.SetPosition(0, 108); + saveBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + mainWindow->Append(&saveBrowser); + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync (); + + ret = saveBrowser.GetClickedSave(); + + // load or save game + if(ret >= 0) + { + int result = 0; + + if(action == 0) // load + { + MakeFilePath(filepath, saves.type[ret], method, saves.filename[ret]); + switch(saves.type[ret]) + { + case FILE_RAM: + result = LoadRAM(filepath, GCSettings.SaveMethod, NOTSILENT); + break; + case FILE_STATE: + result = LoadState(filepath, GCSettings.SaveMethod, NOTSILENT); + break; + } + if(result) + menu = MENU_EXIT; + } + else // save + { + if(ret == 0) // new SRAM + { + for(i=1; i < 100; i++) + if(saves.files[FILE_RAM][i] == 0) + break; + + if(i < 100) + { + MakeFilePath(filepath, FILE_RAM, method, romFilename, i); + SaveRAM(filepath, GCSettings.SaveMethod, NOTSILENT); + menu = MENU_GAME_SAVE; + } + } + else if(ret == 1) // new Snapshot + { + for(i=1; i < 100; i++) + if(saves.files[FILE_STATE][i] == 0) + break; + + if(i < 100) + { + MakeFilePath(filepath, FILE_STATE, method, romFilename, i); + SaveState(filepath, GCSettings.SaveMethod, NOTSILENT); + menu = MENU_GAME_SAVE; + } + } + else // overwrite SRAM/Snapshot + { + MakeFilePath(filepath, saves.type[ret-2], method, saves.filename[ret-2]); + switch(saves.type[ret-2]) + { + case FILE_RAM: + SaveRAM(filepath, GCSettings.SaveMethod, NOTSILENT); + break; + case FILE_STATE: + SaveState(filepath, GCSettings.SaveMethod, NOTSILENT); + break; + } + menu = MENU_GAME_SAVE; + } + } + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME; + } + else if(closeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_EXIT; + + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 35); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 35); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 35); + backBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + + w.SetEffect(EFFECT_FADE, -15); + + usleep(150000); // wait for effects to finish + } + } + + HaltGui(); + + for(i=0; i < saves.length; i++) + if(saves.previewImg[i]) + delete saves.previewImg[i]; + + mainWindow->Remove(&saveBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; +} + +/**************************************************************************** + * MenuGameCheats + ***************************************************************************/ +/* +static int MenuGameCheats() +{ + int menu = MENU_NONE; + int ret; + u16 i = 0; + OptionList options; + + for(i=0; i < Cheat.num_cheats; i++) + sprintf (options.name[i], "%s", Cheat.c[i].name); + + options.length = i; + + GuiText titleTxt("Cheats", 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnCloseOutline(button_close_png); + GuiImageData btnCloseOutlineOver(button_close_over_png); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + + GuiText backBtnTxt("Go Back", 24, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetTrigger(&trigA); + backBtn.SetEffectGrow(); + + GuiText closeBtnTxt("Close", 22, (GXColor){0, 0, 0, 255}); + GuiImage closeBtnImg(&btnCloseOutline); + GuiImage closeBtnImgOver(&btnCloseOutlineOver); + GuiButton closeBtn(btnCloseOutline.GetWidth(), btnCloseOutline.GetHeight()); + closeBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + closeBtn.SetPosition(-30, 35); + closeBtn.SetLabel(&closeBtnTxt); + closeBtn.SetImage(&closeBtnImg); + closeBtn.SetImageOver(&closeBtnImgOver); + closeBtn.SetSoundOver(&btnSoundOver); + closeBtn.SetTrigger(&trigA); + closeBtn.SetTrigger(&trigHome); + closeBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + w.Append(&closeBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync (); + + for(i=0; i < Cheat.num_cheats; i++) + sprintf (options.value[i], "%s", Cheat.c[i].enabled == true ? "On" : "Off"); + + ret = optionBrowser.GetClickedOption(); + + if(Cheat.c[ret].enabled) + S9xDisableCheat(ret); + else + S9xEnableCheat(ret); + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAME; + } + else if(closeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_EXIT; + + bgTopImg->SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 35); + closeBtn.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 35); + titleTxt.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 35); + backBtn.SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + bgBottomImg->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + btnLogo->SetEffect(EFFECT_SLIDE_BOTTOM | EFFECT_SLIDE_OUT, 35); + + w.SetEffect(EFFECT_FADE, -15); + + usleep(150000); // wait for effects to finish + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; +} +*/ +/**************************************************************************** + * MenuSettings + ***************************************************************************/ + +static int MenuSettings() +{ + int menu = MENU_NONE; + + GuiText titleTxt("Settings", 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiText mappingBtnTxt("Button Mappings", 24, (GXColor){0, 0, 0, 255}); + mappingBtnTxt.SetMaxWidth(btnLargeOutline.GetWidth()-30); + GuiImage mappingBtnImg(&btnLargeOutline); + GuiImage mappingBtnImgOver(&btnLargeOutlineOver); + GuiButton mappingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + mappingBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + mappingBtn.SetPosition(50, 120); + mappingBtn.SetLabel(&mappingBtnTxt); + mappingBtn.SetImage(&mappingBtnImg); + mappingBtn.SetImageOver(&mappingBtnImgOver); + mappingBtn.SetSoundOver(&btnSoundOver); + mappingBtn.SetTrigger(&trigA); + mappingBtn.SetEffectGrow(); + + GuiText videoBtnTxt("Video", 24, (GXColor){0, 0, 0, 255}); + videoBtnTxt.SetMaxWidth(btnLargeOutline.GetWidth()-30); + GuiImage videoBtnImg(&btnLargeOutline); + GuiImage videoBtnImgOver(&btnLargeOutlineOver); + GuiButton videoBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + videoBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + videoBtn.SetPosition(0, 120); + videoBtn.SetLabel(&videoBtnTxt); + videoBtn.SetImage(&videoBtnImg); + videoBtn.SetImageOver(&videoBtnImgOver); + videoBtn.SetSoundOver(&btnSoundOver); + videoBtn.SetTrigger(&trigA); + videoBtn.SetEffectGrow(); + + GuiText savingBtnTxt1("Saving", 24, (GXColor){0, 0, 0, 255}); + GuiText savingBtnTxt2("&", 18, (GXColor){0, 0, 0, 255}); + GuiText savingBtnTxt3("Loading", 24, (GXColor){0, 0, 0, 255}); + savingBtnTxt1.SetPosition(0, -20); + savingBtnTxt3.SetPosition(0, +20); + GuiImage savingBtnImg(&btnLargeOutline); + GuiImage savingBtnImgOver(&btnLargeOutlineOver); + GuiButton savingBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + savingBtn.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + savingBtn.SetPosition(-50, 120); + savingBtn.SetLabel(&savingBtnTxt1, 0); + savingBtn.SetLabel(&savingBtnTxt2, 1); + savingBtn.SetLabel(&savingBtnTxt3, 2); + savingBtn.SetImage(&savingBtnImg); + savingBtn.SetImageOver(&savingBtnImgOver); + savingBtn.SetSoundOver(&btnSoundOver); + savingBtn.SetTrigger(&trigA); + savingBtn.SetEffectGrow(); + + GuiText menuBtnTxt("Menu", 24, (GXColor){0, 0, 0, 255}); + menuBtnTxt.SetMaxWidth(btnLargeOutline.GetWidth()-30); + GuiImage menuBtnImg(&btnLargeOutline); + GuiImage menuBtnImgOver(&btnLargeOutlineOver); + GuiButton menuBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + menuBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + menuBtn.SetPosition(-125, 250); + menuBtn.SetLabel(&menuBtnTxt); + menuBtn.SetImage(&menuBtnImg); + menuBtn.SetImageOver(&menuBtnImgOver); + menuBtn.SetSoundOver(&btnSoundOver); + menuBtn.SetTrigger(&trigA); + menuBtn.SetEffectGrow(); + + GuiText networkBtnTxt("Network", 24, (GXColor){0, 0, 0, 255}); + networkBtnTxt.SetMaxWidth(btnLargeOutline.GetWidth()-30); + GuiImage networkBtnImg(&btnLargeOutline); + GuiImage networkBtnImgOver(&btnLargeOutlineOver); + GuiButton networkBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + networkBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + networkBtn.SetPosition(125, 250); + networkBtn.SetLabel(&networkBtnTxt); + networkBtn.SetImage(&networkBtnImg); + networkBtn.SetImageOver(&networkBtnImgOver); + networkBtn.SetSoundOver(&btnSoundOver); + networkBtn.SetTrigger(&trigA); + networkBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 24, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetTrigger(&trigA); + backBtn.SetEffectGrow(); + + GuiText resetBtnTxt("Reset Settings", 24, (GXColor){0, 0, 0, 255}); + GuiImage resetBtnImg(&btnOutline); + GuiImage resetBtnImgOver(&btnOutlineOver); + GuiButton resetBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + resetBtn.SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); + resetBtn.SetPosition(-100, -35); + resetBtn.SetLabel(&resetBtnTxt); + resetBtn.SetImage(&resetBtnImg); + resetBtn.SetImageOver(&resetBtnImgOver); + resetBtn.SetSoundOver(&btnSoundOver); + resetBtn.SetTrigger(&trigA); + resetBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&mappingBtn); + w.Append(&videoBtn); + w.Append(&savingBtn); + w.Append(&menuBtn); + +#ifdef HW_RVL + w.Append(&networkBtn); +#endif + + w.Append(&backBtn); + w.Append(&resetBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync (); + + if(mappingBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MAPPINGS; + } + else if(videoBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_VIDEO; + } + else if(savingBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_FILE; + } + else if(menuBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MENU; + } + else if(networkBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_NETWORK; + } + else if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_GAMESELECTION; + } + else if(resetBtn.GetState() == STATE_CLICKED) + { + resetBtn.ResetState(); + + int choice = WindowPrompt( + "Reset Settings", + "Are you sure that you want to reset your settings?", + "Yes", + "No"); + + if(choice == 1) + DefaultSettings(); + } + } + + if(menu == MENU_GAMESELECTION) + SavePrefs(NOTSILENT); + + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * MenuSettingsMappings + ***************************************************************************/ + +static int MenuSettingsMappings() +{ + int menu = MENU_NONE; + + GuiText titleTxt("Settings - Button Mappings", 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiText nesBtnTxt("NES Controller", 24, (GXColor){0, 0, 0, 255}); + nesBtnTxt.SetMaxWidth(btnLargeOutline.GetWidth()-30); + GuiImage nesBtnImg(&btnLargeOutline); + GuiImage nesBtnImgOver(&btnLargeOutlineOver); + GuiButton nesBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + nesBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + nesBtn.SetPosition(-125, 120); + nesBtn.SetLabel(&nesBtnTxt); + nesBtn.SetImage(&nesBtnImg); + nesBtn.SetImageOver(&nesBtnImgOver); + nesBtn.SetSoundOver(&btnSoundOver); + nesBtn.SetTrigger(&trigA); + nesBtn.SetEffectGrow(); + + GuiText zapperBtnTxt("Zapper", 24, (GXColor){0, 0, 0, 255}); + zapperBtnTxt.SetMaxWidth(btnLargeOutline.GetWidth()-30); + GuiImage zapperBtnImg(&btnLargeOutline); + GuiImage zapperBtnImgOver(&btnLargeOutlineOver); + GuiButton zapperBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + zapperBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + zapperBtn.SetPosition(125, 120); + zapperBtn.SetLabel(&zapperBtnTxt); + zapperBtn.SetImage(&zapperBtnImg); + zapperBtn.SetImageOver(&zapperBtnImgOver); + zapperBtn.SetSoundOver(&btnSoundOver); + zapperBtn.SetTrigger(&trigA); + zapperBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 24, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetTrigger(&trigA); + backBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&nesBtn); + w.Append(&zapperBtn); + + w.Append(&backBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync (); + + if(nesBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MAPPINGS_CTRL; + mapMenuCtrlNES = CTRL_PAD; + } + else if(zapperBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MAPPINGS_CTRL; + mapMenuCtrlNES = CTRL_ZAPPER; + } + else if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +static int MenuSettingsMappingsController() +{ + int menu = MENU_NONE; + char menuTitle[100]; + char menuSubtitle[100]; + + sprintf(menuTitle, "Settings - Button Mappings"); + GuiText titleTxt(menuTitle, 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,30); + + sprintf(menuSubtitle, "%s", ctrlName[mapMenuCtrlNES]); + GuiText subtitleTxt(menuSubtitle, 22, (GXColor){255, 255, 255, 255}); + subtitleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + subtitleTxt.SetPosition(50,60); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiImageData btnLargeOutline(button_large_png); + GuiImageData btnLargeOutlineOver(button_large_over_png); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiText gamecubeBtnTxt("GameCube Controller", 24, (GXColor){0, 0, 0, 255}); + gamecubeBtnTxt.SetMaxWidth(btnLargeOutline.GetWidth()-30); + GuiImage gamecubeBtnImg(&btnLargeOutline); + GuiImage gamecubeBtnImgOver(&btnLargeOutlineOver); + GuiButton gamecubeBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + gamecubeBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + gamecubeBtn.SetPosition(-125, 120); + gamecubeBtn.SetLabel(&gamecubeBtnTxt); + gamecubeBtn.SetImage(&gamecubeBtnImg); + gamecubeBtn.SetImageOver(&gamecubeBtnImgOver); + gamecubeBtn.SetSoundOver(&btnSoundOver); + gamecubeBtn.SetTrigger(&trigA); + gamecubeBtn.SetEffectGrow(); + + GuiText wiimoteBtnTxt("Wiimote", 24, (GXColor){0, 0, 0, 255}); + GuiImage wiimoteBtnImg(&btnLargeOutline); + GuiImage wiimoteBtnImgOver(&btnLargeOutlineOver); + GuiButton wiimoteBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + wiimoteBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + wiimoteBtn.SetPosition(125, 120); + wiimoteBtn.SetLabel(&wiimoteBtnTxt); + wiimoteBtn.SetImage(&wiimoteBtnImg); + wiimoteBtn.SetImageOver(&wiimoteBtnImgOver); + wiimoteBtn.SetSoundOver(&btnSoundOver); + wiimoteBtn.SetTrigger(&trigA); + wiimoteBtn.SetEffectGrow(); + + GuiText classicBtnTxt("Classic Controller", 24, (GXColor){0, 0, 0, 255}); + classicBtnTxt.SetMaxWidth(btnLargeOutline.GetWidth()-30); + GuiImage classicBtnImg(&btnLargeOutline); + GuiImage classicBtnImgOver(&btnLargeOutlineOver); + GuiButton classicBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + classicBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + classicBtn.SetPosition(-125, 250); + classicBtn.SetLabel(&classicBtnTxt); + classicBtn.SetImage(&classicBtnImg); + classicBtn.SetImageOver(&classicBtnImgOver); + classicBtn.SetSoundOver(&btnSoundOver); + classicBtn.SetTrigger(&trigA); + classicBtn.SetEffectGrow(); + + GuiText nunchukBtnTxt("Wiimote Nunchuk", 24, (GXColor){0, 0, 0, 255}); + nunchukBtnTxt.SetMaxWidth(btnLargeOutline.GetWidth()-30); + GuiImage nunchukBtnImg(&btnLargeOutline); + GuiImage nunchukBtnImgOver(&btnLargeOutlineOver); + GuiButton nunchukBtn(btnLargeOutline.GetWidth(), btnLargeOutline.GetHeight()); + nunchukBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + nunchukBtn.SetPosition(125, 250); + nunchukBtn.SetLabel(&nunchukBtnTxt); + nunchukBtn.SetImage(&nunchukBtnImg); + nunchukBtn.SetImageOver(&nunchukBtnImgOver); + nunchukBtn.SetSoundOver(&btnSoundOver); + nunchukBtn.SetTrigger(&trigA); + nunchukBtn.SetEffectGrow(); + + GuiText backBtnTxt("Go Back", 24, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetTrigger(&trigA); + backBtn.SetEffectGrow(); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&titleTxt); + w.Append(&subtitleTxt); + + w.Append(&gamecubeBtn); +#ifdef HW_RVL + w.Append(&wiimoteBtn); + + if(mapMenuCtrlNES == CTRL_PAD) + { + w.Append(&nunchukBtn); + w.Append(&classicBtn); + } +#endif + w.Append(&backBtn); + + mainWindow->Append(&w); + + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync (); + + if(wiimoteBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_WIIMOTE; + } + else if(nunchukBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_NUNCHUK; + } + else if(classicBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_CLASSIC; + } + else if(gamecubeBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MAPPINGS_MAP; + mapMenuCtrl = CTRLR_GCPAD; + } + else if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MAPPINGS; + } + } + HaltGui(); + mainWindow->Remove(&w); + return menu; +} + +/**************************************************************************** + * ButtonMappingWindow + ***************************************************************************/ + +static u32 +ButtonMappingWindow() +{ + GuiWindow promptWindow(448,288); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiImageData dialogBox(dialogue_box_png); + GuiImage dialogBoxImg(&dialogBox); + + GuiText titleTxt("Button Mapping", 26, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,14); + + char msg[200]; + + switch(mapMenuCtrl) + { + case CTRLR_GCPAD: + #ifdef HW_RVL + sprintf(msg, "Press any button on the GameCube Controller now. Press Home or the C-Stick in any direction to cancel."); + #else + sprintf(msg, "Press any button on the GameCube Controller now. Press the C-Stick in any direction to cancel."); + #endif + break; + case CTRLR_WIIMOTE: + sprintf(msg, "Press any button on the Wiimote now. Press Home to cancel."); + break; + case CTRLR_CLASSIC: + sprintf(msg, "Press any button on the Classic Controller now. Press Home to cancel."); + break; + case CTRLR_NUNCHUK: + sprintf(msg, "Press any button on the Wiimote or Nunchuk now. Press Home to cancel."); + break; + } + + GuiText msgTxt(msg, 26, (GXColor){0, 0, 0, 255}); + msgTxt.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + msgTxt.SetPosition(0,-20); + msgTxt.SetMaxWidth(430); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&titleTxt); + promptWindow.Append(&msgTxt); + + HaltGui(); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + u32 pressed = 0; + + while(pressed == 0) + { + VIDEO_WaitVSync(); + + if(mapMenuCtrl == CTRLR_GCPAD) + { + pressed = userInput[0].pad.btns_d; + + + if(userInput[0].pad.substickX < -70 || + userInput[0].pad.substickX > 70 || + userInput[0].pad.substickY < -70 || + userInput[0].pad.substickY > 70) + pressed = WPAD_BUTTON_HOME; + + if(userInput[0].wpad.btns_d == WPAD_BUTTON_HOME) + pressed = WPAD_BUTTON_HOME; + } + else + { + pressed = userInput[0].wpad.btns_d; + + // always allow Home button to be pressed to cancel + if(pressed != WPAD_BUTTON_HOME) + { + switch(mapMenuCtrl) + { + case CTRLR_WIIMOTE: + if(pressed > 0x1000) + pressed = 0; // not a valid input + break; + + case CTRLR_CLASSIC: + if(userInput[0].wpad.exp.type != WPAD_EXP_CLASSIC) + pressed = 0; // not a valid input + else if(pressed <= 0x1000) + pressed = 0; // not a valid input + break; + + case CTRLR_NUNCHUK: + if(userInput[0].wpad.exp.type != WPAD_EXP_NUNCHUK) + pressed = 0; // not a valid input + break; + } + } + } + } + + if(pressed == WPAD_BUTTON_HOME + || pressed == WPAD_CLASSIC_BUTTON_HOME) + pressed = 0; + + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); + + return pressed; +} + +static int MenuSettingsMappingsMap() +{ + int menu = MENU_NONE; + int ret,i,j; + OptionList options; + + char menuTitle[100]; + char menuSubtitle[100]; + sprintf(menuTitle, "Settings - Button Mappings"); + + GuiText titleTxt(menuTitle, 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,30); + + sprintf(menuSubtitle, "%s - %s", ctrlName[mapMenuCtrlNES], ctrlrName[mapMenuCtrl]); + GuiText subtitleTxt(menuSubtitle, 22, (GXColor){255, 255, 255, 255}); + subtitleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + subtitleTxt.SetPosition(50,60); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiText backBtnTxt("Go Back", 24, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetTrigger(&trigA); + backBtn.SetEffectGrow(); + + i=0; + + switch(mapMenuCtrlNES) + { + case CTRL_PAD: + sprintf(options.name[i++], "B"); + sprintf(options.name[i++], "A"); + sprintf(options.name[i++], "B (Rapid)"); + sprintf(options.name[i++], "A (Rapid)"); + sprintf(options.name[i++], "Select"); + sprintf(options.name[i++], "Start"); + sprintf(options.name[i++], "Up"); + sprintf(options.name[i++], "Down"); + sprintf(options.name[i++], "Left"); + sprintf(options.name[i++], "Right"); + sprintf(options.name[i++], "Insert Coin / Switch Disk"); + options.length = i; + break; + case CTRL_ZAPPER: + sprintf(options.name[i++], "Fire"); + sprintf(options.name[i++], "Insert Coin"); + options.length = i; + break; }; - int ret = 0; - int quit = 0; - int oldmenu = menu; - menu = 0; - while (quit == 0) + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser.SetCol2Position(180); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + mainWindow->Append(&subtitleTxt); + ResumeGui(); + + while(menu == MENU_NONE) { + VIDEO_WaitVSync (); + + for(i=0; i < options.length; i++) + { + options.value[i][0] = 0; + + for(j=0; j < ctrlr_def[mapMenuCtrl].num_btns; j++) + { + if(btnmap[mapMenuCtrlNES][mapMenuCtrl][i] == + ctrlr_def[mapMenuCtrl].map[j].btn) + { + sprintf(options.value[i], ctrlr_def[mapMenuCtrl].map[j].name); + break; + } + } + } + + ret = optionBrowser.GetClickedOption(); + + if(ret >= 0) + { + u32 pressed = ButtonMappingWindow(); // get a button selection from user + + if (pressed > 0) + btnmap[mapMenuCtrlNES][mapMenuCtrl][ret] = pressed; // update mapping + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS_MAPPINGS_CTRL; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + mainWindow->Remove(&subtitleTxt); + return menu; +} + +/**************************************************************************** + * MenuSettingsVideo + ***************************************************************************/ + +static void ScreenZoomWindowUpdate(void * ptr, float amount) +{ + GuiButton * b = (GuiButton *)ptr; + if(b->GetState() == STATE_CLICKED) + { + GCSettings.ZoomLevel += amount; + + char zoom[10]; + sprintf(zoom, "%.2f%%", GCSettings.ZoomLevel*100); + settingText->SetText(zoom); + b->ResetState(); + } +} + +static void ScreenZoomWindowLeftClick(void * ptr) { ScreenZoomWindowUpdate(ptr, -0.01); } +static void ScreenZoomWindowRightClick(void * ptr) { ScreenZoomWindowUpdate(ptr, +0.01); } + +static void ScreenZoomWindow() +{ + GuiWindow * w = new GuiWindow(250,250); + w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiTrigger trigLeft; + trigLeft.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); + + GuiTrigger trigRight; + trigRight.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); + + GuiImageData arrowLeft(button_arrow_left_png); + GuiImage arrowLeftImg(&arrowLeft); + GuiImageData arrowLeftOver(button_arrow_left_over_png); + GuiImage arrowLeftOverImg(&arrowLeftOver); + GuiButton arrowLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight()); + arrowLeftBtn.SetImage(&arrowLeftImg); + arrowLeftBtn.SetImageOver(&arrowLeftOverImg); + arrowLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + arrowLeftBtn.SetTrigger(0, &trigA); + arrowLeftBtn.SetTrigger(1, &trigLeft); + arrowLeftBtn.SetSelectable(false); + arrowLeftBtn.SetUpdateCallback(ScreenZoomWindowLeftClick); + + GuiImageData arrowRight(button_arrow_right_png); + GuiImage arrowRightImg(&arrowRight); + GuiImageData arrowRightOver(button_arrow_right_over_png); + GuiImage arrowRightOverImg(&arrowRightOver); + GuiButton arrowRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight()); + arrowRightBtn.SetImage(&arrowRightImg); + arrowRightBtn.SetImageOver(&arrowRightOverImg); + arrowRightBtn.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE); + arrowRightBtn.SetTrigger(0, &trigA); + arrowRightBtn.SetTrigger(1, &trigRight); + arrowRightBtn.SetSelectable(false); + arrowRightBtn.SetUpdateCallback(ScreenZoomWindowRightClick); + + settingText = new GuiText(NULL, 22, (GXColor){0, 0, 0, 255}); + char zoom[10]; + sprintf(zoom, "%.2f%%", GCSettings.ZoomLevel*100); + settingText->SetText(zoom); + + float currentZoom = GCSettings.ZoomLevel; + + w->Append(&arrowLeftBtn); + w->Append(&arrowRightBtn); + w->Append(settingText); + + if(!SettingWindow("Screen Zoom",w)) + GCSettings.ZoomLevel = currentZoom; // undo changes + + delete(w); + delete(settingText); +} + +static void ScreenPositionWindowUpdate(void * ptr, int x, int y) +{ + GuiButton * b = (GuiButton *)ptr; + if(b->GetState() == STATE_CLICKED) + { + GCSettings.xshift += x; + GCSettings.yshift += y; + + char shift[10]; + sprintf(shift, "%i, %i", GCSettings.xshift, GCSettings.yshift); + settingText->SetText(shift); + b->ResetState(); + } +} + +static void ScreenPositionWindowLeftClick(void * ptr) { ScreenPositionWindowUpdate(ptr, -1, 0); } +static void ScreenPositionWindowRightClick(void * ptr) { ScreenPositionWindowUpdate(ptr, +1, 0); } +static void ScreenPositionWindowUpClick(void * ptr) { ScreenPositionWindowUpdate(ptr, 0, -1); } +static void ScreenPositionWindowDownClick(void * ptr) { ScreenPositionWindowUpdate(ptr, 0, +1); } + +static void ScreenPositionWindow() +{ + GuiWindow * w = new GuiWindow(150,150); + w->SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + w->SetPosition(0, -10); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiTrigger trigLeft; + trigLeft.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); + + GuiTrigger trigRight; + trigRight.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); + + GuiTrigger trigUp; + trigUp.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP, PAD_BUTTON_UP); + + GuiTrigger trigDown; + trigDown.SetButtonOnlyInFocusTrigger(-1, WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN, PAD_BUTTON_DOWN); + + GuiImageData arrowLeft(button_arrow_left_png); + GuiImage arrowLeftImg(&arrowLeft); + GuiImageData arrowLeftOver(button_arrow_left_over_png); + GuiImage arrowLeftOverImg(&arrowLeftOver); + GuiButton arrowLeftBtn(arrowLeft.GetWidth(), arrowLeft.GetHeight()); + arrowLeftBtn.SetImage(&arrowLeftImg); + arrowLeftBtn.SetImageOver(&arrowLeftOverImg); + arrowLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + arrowLeftBtn.SetTrigger(0, &trigA); + arrowLeftBtn.SetTrigger(1, &trigLeft); + arrowLeftBtn.SetSelectable(false); + arrowLeftBtn.SetUpdateCallback(ScreenPositionWindowLeftClick); + + GuiImageData arrowRight(button_arrow_right_png); + GuiImage arrowRightImg(&arrowRight); + GuiImageData arrowRightOver(button_arrow_right_over_png); + GuiImage arrowRightOverImg(&arrowRightOver); + GuiButton arrowRightBtn(arrowRight.GetWidth(), arrowRight.GetHeight()); + arrowRightBtn.SetImage(&arrowRightImg); + arrowRightBtn.SetImageOver(&arrowRightOverImg); + arrowRightBtn.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE); + arrowRightBtn.SetTrigger(0, &trigA); + arrowRightBtn.SetTrigger(1, &trigRight); + arrowRightBtn.SetSelectable(false); + arrowRightBtn.SetUpdateCallback(ScreenPositionWindowRightClick); + + GuiImageData arrowUp(button_arrow_up_png); + GuiImage arrowUpImg(&arrowUp); + GuiImageData arrowUpOver(button_arrow_up_over_png); + GuiImage arrowUpOverImg(&arrowUpOver); + GuiButton arrowUpBtn(arrowUp.GetWidth(), arrowUp.GetHeight()); + arrowUpBtn.SetImage(&arrowUpImg); + arrowUpBtn.SetImageOver(&arrowUpOverImg); + arrowUpBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + arrowUpBtn.SetTrigger(0, &trigA); + arrowUpBtn.SetTrigger(1, &trigUp); + arrowUpBtn.SetSelectable(false); + arrowUpBtn.SetUpdateCallback(ScreenPositionWindowUpClick); + + GuiImageData arrowDown(button_arrow_down_png); + GuiImage arrowDownImg(&arrowDown); + GuiImageData arrowDownOver(button_arrow_down_over_png); + GuiImage arrowDownOverImg(&arrowDownOver); + GuiButton arrowDownBtn(arrowDown.GetWidth(), arrowDown.GetHeight()); + arrowDownBtn.SetImage(&arrowDownImg); + arrowDownBtn.SetImageOver(&arrowDownOverImg); + arrowDownBtn.SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM); + arrowDownBtn.SetTrigger(0, &trigA); + arrowDownBtn.SetTrigger(1, &trigDown); + arrowDownBtn.SetSelectable(false); + arrowDownBtn.SetUpdateCallback(ScreenPositionWindowDownClick); + + GuiImageData screenPosition(screen_position_png); + GuiImage screenPositionImg(&screenPosition); + screenPositionImg.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + + settingText = new GuiText(NULL, 22, (GXColor){0, 0, 0, 255}); + char shift[10]; + sprintf(shift, "%i, %i", GCSettings.xshift, GCSettings.yshift); + settingText->SetText(shift); + + int currentX = GCSettings.xshift; + int currentY = GCSettings.yshift; + + w->Append(&arrowLeftBtn); + w->Append(&arrowRightBtn); + w->Append(&arrowUpBtn); + w->Append(&arrowDownBtn); + w->Append(&screenPositionImg); + w->Append(settingText); + + if(!SettingWindow("Screen Position",w)) + { + GCSettings.xshift = currentX; // undo changes + GCSettings.yshift = currentY; + } + + delete(w); + delete(settingText); +} + +static int MenuSettingsVideo() +{ + int menu = MENU_NONE; + int ret; + int i = 0; + OptionList options; + + sprintf(options.name[i++], "Rendering"); + sprintf(options.name[i++], "Scaling"); + sprintf(options.name[i++], "Cropping"); + sprintf(options.name[i++], "Palette"); + sprintf(options.name[i++], "Timing"); + sprintf(options.name[i++], "Screen Zoom"); + sprintf(options.name[i++], "Screen Position"); + options.length = i; + + GuiText titleTxt("Settings - Video", 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiText backBtnTxt("Go Back", 24, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetTrigger(&trigA); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync (); + // don't allow original render mode if progressive video mode detected if (GCSettings.render==0 && progressive) GCSettings.render++; if (GCSettings.render == 0) - sprintf (videomenu[0], "Video Rendering Original"); - if (GCSettings.render == 1) - sprintf (videomenu[0], "Video Rendering Filtered"); - if (GCSettings.render == 2) - sprintf (videomenu[0], "Video Rendering Unfiltered"); + sprintf (options.value[0], "Original"); + else if (GCSettings.render == 1) + sprintf (options.value[0], "Filtered"); + else if (GCSettings.render == 2) + sprintf (options.value[0], "Unfiltered"); - sprintf (videomenu[1], "Video Scaling %s", - GCSettings.widescreen == true ? "16:9 Correction" : "Default"); + if(GCSettings.widescreen) + sprintf (options.value[1], "16:9 Correction"); + else + sprintf (options.value[1], "Default"); - if (GCSettings.hideoverscan == 0) - sprintf (videomenu[2], "Video Cropping Off"); - if (GCSettings.hideoverscan == 1) - sprintf (videomenu[2], "Video Cropping Vertical"); - if (GCSettings.hideoverscan == 2) - sprintf (videomenu[2], "Video Cropping Horizontal"); - if (GCSettings.hideoverscan == 3) - sprintf (videomenu[2], "Video Cropping Both"); + switch(GCSettings.hideoverscan) + { + case 0: sprintf (options.value[2], "Video Cropping Off"); break; + case 1: sprintf (options.value[2], "Video Cropping Vertical"); break; + case 2: sprintf (options.value[2], "Video Cropping Horizontal"); break; + case 3: sprintf (options.value[2], "Video Cropping Both"); break; + } - sprintf (videomenu[3], "Palette - %s", + sprintf (options.value[3], "%s", GCSettings.currpal ? palettes[GCSettings.currpal-1].name : "Default"); - sprintf (videomenu[4], "Enable Zooming %s", - GCSettings.Zoom == true ? " ON" : "OFF"); + sprintf (options.value[4], "%s", GCSettings.timing == true ? " PAL" : "NTSC"); + sprintf (options.value[5], "%.2f%%", GCSettings.ZoomLevel*100); + sprintf (options.value[6], "%d, %d", GCSettings.xshift, GCSettings.yshift); - sprintf (videomenu[5], "Timing - %s", - GCSettings.timing == true ? " PAL" : "NTSC"); - - ret = RunMenu (videomenu, videomenuCount, "Video Options", 20, -1); + ret = optionBrowser.GetClickedOption(); switch (ret) { @@ -134,8 +2717,6 @@ VideoOptions () GCSettings.render++; if (GCSettings.render > 2) GCSettings.render = 0; - // reset zoom - zoom_reset (); break; case 1: @@ -153,58 +2734,100 @@ VideoOptions () GCSettings.currpal = 0; break; - case 4: - GCSettings.Zoom ^= 1; - break; - - case 5: // timing + case 4: // timing GCSettings.timing ^= 1; FCEUI_SetVidSystem(GCSettings.timing); // causes a small 'pop' in the audio break; - case -1: // Button B - case 6: - quit = 1; + case 5: + ScreenZoomWindow(); break; + case 6: + ScreenPositionWindow(); + break; + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; } } - menu = oldmenu; + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; } /**************************************************************************** - * File Options Menu - ****************************************************************************/ + * MenuSettingsFile + ***************************************************************************/ -static void -FileOptions() +static int MenuSettingsFile() { - int filemenuCount = 8; - char filemenu[][50] = { + int menu = MENU_NONE; + int ret; + int i = 0; + OptionList options; + sprintf(options.name[i++], "Load Method"); + sprintf(options.name[i++], "Load Folder"); + sprintf(options.name[i++], "Save Method"); + sprintf(options.name[i++], "Save Folder"); + sprintf(options.name[i++], "Auto Load"); + sprintf(options.name[i++], "Auto Save"); + sprintf(options.name[i++], "Verify MC Saves"); + options.length = i; - "Load Method", - "Load Folder", - "Save Method", - "Save Folder", + GuiText titleTxt("Settings - Saving & Loading", 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); - "Auto Load", - "Auto Save", - "Verify MC Saves", + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); - "Back to Preferences Menu" - }; + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); - int ret = 0; - int quit = 0; - int oldmenu = menu; - menu = 0; - while (quit == 0) + GuiText backBtnTxt("Go Back", 24, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetTrigger(&trigA); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + optionBrowser.SetCol2Position(180); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) { + VIDEO_WaitVSync (); + // some load/save methods are not implemented - here's where we skip them // they need to be skipped in the order they were enumerated in snes9xGX.h // no USB ports on GameCube - #ifndef HW_RVL + #ifdef HW_DOL if(GCSettings.LoadMethod == METHOD_USB) GCSettings.LoadMethod++; if(GCSettings.SaveMethod == METHOD_USB) @@ -216,7 +2839,7 @@ FileOptions() GCSettings.SaveMethod++; // disable SMB in GC mode (stalls out) - #ifndef HW_RVL + #ifdef HW_DOL if(GCSettings.LoadMethod == METHOD_SMB) GCSettings.LoadMethod++; if(GCSettings.SaveMethod == METHOD_SMB) @@ -229,10 +2852,7 @@ FileOptions() GCSettings.SaveMethod++; if(GCSettings.SaveMethod == METHOD_MC_SLOTB) GCSettings.SaveMethod++; - filemenu[6][0] = '\0'; - #else - sprintf (filemenu[6], "Verify MC Saves %s", - GCSettings.VerifySaves == true ? " ON" : "OFF"); + options.name[6][0] = 0; #endif // correct load/save methods out of bounds @@ -241,37 +2861,35 @@ FileOptions() if(GCSettings.SaveMethod > 6) GCSettings.SaveMethod = 0; - if (GCSettings.LoadMethod == METHOD_AUTO) sprintf (filemenu[0],"Load Method AUTO"); - else if (GCSettings.LoadMethod == METHOD_SD) sprintf (filemenu[0],"Load Method SD"); - else if (GCSettings.LoadMethod == METHOD_USB) sprintf (filemenu[0],"Load Method USB"); - else if (GCSettings.LoadMethod == METHOD_DVD) sprintf (filemenu[0],"Load Method DVD"); - else if (GCSettings.LoadMethod == METHOD_SMB) sprintf (filemenu[0],"Load Method Network"); + if (GCSettings.LoadMethod == METHOD_AUTO) sprintf (options.value[0],"Auto"); + else if (GCSettings.LoadMethod == METHOD_SD) sprintf (options.value[0],"SD"); + else if (GCSettings.LoadMethod == METHOD_USB) sprintf (options.value[0],"USB"); + else if (GCSettings.LoadMethod == METHOD_DVD) sprintf (options.value[0],"DVD"); + else if (GCSettings.LoadMethod == METHOD_SMB) sprintf (options.value[0],"Network"); - sprintf (filemenu[1], "Load Folder %s", GCSettings.LoadFolder); + sprintf (options.value[1], "%s", GCSettings.LoadFolder); - if (GCSettings.SaveMethod == METHOD_AUTO) sprintf (filemenu[2],"Save Method AUTO"); - else if (GCSettings.SaveMethod == METHOD_SD) sprintf (filemenu[2],"Save Method SD"); - else if (GCSettings.SaveMethod == METHOD_USB) sprintf (filemenu[2],"Save Method USB"); - else if (GCSettings.SaveMethod == METHOD_SMB) sprintf (filemenu[2],"Save Method Network"); - else if (GCSettings.SaveMethod == METHOD_MC_SLOTA) sprintf (filemenu[2],"Save Method MC Slot A"); - else if (GCSettings.SaveMethod == METHOD_MC_SLOTB) sprintf (filemenu[2],"Save Method MC Slot B"); + if (GCSettings.SaveMethod == METHOD_AUTO) sprintf (options.value[2],"Auto"); + else if (GCSettings.SaveMethod == METHOD_SD) sprintf (options.value[2],"SD"); + else if (GCSettings.SaveMethod == METHOD_USB) sprintf (options.value[2],"USB"); + else if (GCSettings.SaveMethod == METHOD_SMB) sprintf (options.value[2],"Network"); + else if (GCSettings.SaveMethod == METHOD_MC_SLOTA) sprintf (options.value[2],"MC Slot A"); + else if (GCSettings.SaveMethod == METHOD_MC_SLOTB) sprintf (options.value[2],"MC Slot B"); - sprintf (filemenu[3], "Save Folder %s", GCSettings.SaveFolder); + sprintf (options.value[3], "%s", GCSettings.SaveFolder); - // disable changing load/save directories for now - filemenu[1][0] = '\0'; - filemenu[3][0] = '\0'; + if (GCSettings.AutoLoad == 0) sprintf (options.value[4],"Off"); + else if (GCSettings.AutoLoad == 1) sprintf (options.value[4],"SRAM"); + else if (GCSettings.AutoLoad == 2) sprintf (options.value[4],"Snapshot"); - if (GCSettings.AutoLoad == 0) sprintf (filemenu[4],"Auto Load OFF"); - else if (GCSettings.AutoLoad == 1) sprintf (filemenu[4],"Auto Load RAM"); - else if (GCSettings.AutoLoad == 2) sprintf (filemenu[4],"Auto Load STATE"); + if (GCSettings.AutoSave == 0) sprintf (options.value[5],"Off"); + else if (GCSettings.AutoSave == 1) sprintf (options.value[5],"SRAM"); + else if (GCSettings.AutoSave == 2) sprintf (options.value[5],"Snapshot"); + else if (GCSettings.AutoSave == 3) sprintf (options.value[5],"Both"); - if (GCSettings.AutoSave == 0) sprintf (filemenu[5],"Auto Save OFF"); - else if (GCSettings.AutoSave == 1) sprintf (filemenu[5],"Auto Save RAM"); - else if (GCSettings.AutoSave == 2) sprintf (filemenu[5],"Auto Save STATE"); - else if (GCSettings.AutoSave == 3) sprintf (filemenu[5],"Auto Save BOTH"); + sprintf (options.value[6], "%s", GCSettings.VerifySaves == true ? "On" : "Off"); - ret = RunMenu (filemenu, filemenuCount, "Save/Load Options", 20, -1); + ret = optionBrowser.GetClickedOption(); switch (ret) { @@ -280,6 +2898,7 @@ FileOptions() break; case 1: + OnScreenKeyboard(GCSettings.LoadFolder); break; case 2: @@ -287,6 +2906,7 @@ FileOptions() break; case 3: + OnScreenKeyboard(GCSettings.SaveFolder); break; case 4: @@ -304,590 +2924,424 @@ FileOptions() case 6: GCSettings.VerifySaves ^= 1; break; + } - case -1: // Button B - case 7: - quit = 1; - break; - + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; } } - menu = oldmenu; + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; } /**************************************************************************** - * Game Options Menu - ****************************************************************************/ + * MenuSettingsMenu + ***************************************************************************/ -static int -GameMenu () +static int MenuSettingsMenu() { - int gamemenuCount = 9; - char gamemenu[][50] = { - "Return to Game", - "Reset Game", - "ROM Information", - "Load RAM", "Save RAM", - "Load State", "Save State", - "Reset Zoom", - "Back to Main Menu" - }; + int menu = MENU_NONE; + int ret; + int i = 0; + OptionList options; - int ret, retval = 0; - int quit = 0; - int oldmenu = menu; - menu = 0; + sprintf(options.name[i++], "Exit Action"); + sprintf(options.name[i++], "Wiimote Orientation"); + sprintf(options.name[i++], "Music Volume"); + sprintf(options.name[i++], "Sound Effects Volume"); + options.length = i; - while (quit == 0) + GuiText titleTxt("Settings - Menu", 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiText backBtnTxt("Go Back", 24, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetTrigger(&trigA); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) { - if(nesGameType == 4) // FDS game - { - // disable RAM saving/loading - gamemenu[3][0] = '\0'; - gamemenu[4][0] = '\0'; + VIDEO_WaitVSync (); - // disable ROM Information - gamemenu[2][0] = '\0'; - } - - // disable RAM/STATE saving/loading if AUTO is on - if (GCSettings.AutoLoad == 1) // Auto Load RAM - gamemenu[3][0] = '\0'; - else if (GCSettings.AutoLoad == 2) // Auto Load STATE - gamemenu[5][0] = '\0'; - - if (GCSettings.AutoSave == 1) // Auto Save RAM - gamemenu[4][0] = '\0'; - else if (GCSettings.AutoSave == 2) // Auto Save STATE - gamemenu[6][0] = '\0'; - else if (GCSettings.AutoSave == 3) // Auto Save BOTH - { - gamemenu[4][0] = '\0'; - gamemenu[6][0] = '\0'; - } - - // disable Reset Zoom if Zooming is off - if(!GCSettings.Zoom) - gamemenu[7][0] = '\0'; - - ret = RunMenu (gamemenu, gamemenuCount, "Game Menu", 20, -1); - - switch (ret) - { - case 0: // Return to Game - quit = retval = 1; - break; - - case 1: // Reset Game - PowerNES(); - quit = retval = 1; - break; - - case 2: // ROM Information - RomInfo(); - WaitButtonA (); - break; - - case 3: // Load RAM - quit = retval = LoadRAM(GCSettings.SaveMethod, NOTSILENT); - break; - - case 4: // Save RAM - SaveRAM(GCSettings.SaveMethod, NOTSILENT); - break; - - case 5: // Load State - quit = retval = LoadState(GCSettings.SaveMethod, NOTSILENT); - break; - - case 6: // Save State - SaveState(GCSettings.SaveMethod, NOTSILENT); - break; - - case 7: - zoom_reset (); - quit = retval = 1; - break; - - case -1: // Button B - case 8: // Return to previous menu - retval = 0; - quit = 1; - break; - } - } - - menu = oldmenu; - - return retval; -} - -/**************************************************************************** - * Controller Configuration - * - * Snes9x 1.50 uses a cmd system to work out which button has been pressed. - * Here, I simply move the designated value to the gcpadmaps array, which saves - * on updating the cmd sequences. - ****************************************************************************/ -static u32 -GetInput (u16 ctrlr_type) -{ - //u32 exp_type; - u32 pressed; - pressed=0; - s8 gc_px = 0; - - while( PAD_ButtonsHeld(0) -#ifdef HW_RVL - | WPAD_ButtonsHeld(0) -#endif - ) VIDEO_WaitVSync(); // button 'debounce' - - while (pressed == 0) - { - VIDEO_WaitVSync(); - // get input based on controller type - if (ctrlr_type == CTRLR_GCPAD) - { - pressed = PAD_ButtonsHeld (0); - gc_px = PAD_SubStickX (0); - } -#ifdef HW_RVL + #ifdef HW_RVL + if (GCSettings.ExitAction == 1) + sprintf (options.value[0], "Return to Wii Menu"); + else if (GCSettings.ExitAction == 2) + sprintf (options.value[0], "Power off Wii"); else - { - // if ( WPAD_Probe( 0, &exp_type) == 0) // check wiimote and expansion status (first if wiimote is connected & no errors) - // { - pressed = WPAD_ButtonsHeld (0); + sprintf (options.value[0], "Return to Loader"); - // if (ctrlr_type != CTRLR_WIIMOTE && exp_type != ctrlr_type+1) // if we need input from an expansion, and its not connected... - // pressed = 0; - // } - } -#endif - /*** check for exit sequence (c-stick left OR home button) ***/ - if ( (gc_px < -70) || (pressed & WPAD_BUTTON_HOME) || (pressed & WPAD_CLASSIC_BUTTON_HOME) ) - return 0; - } // end while - while( pressed == (PAD_ButtonsHeld(0) -#ifdef HW_RVL - | WPAD_ButtonsHeld(0) -#endif - ) ) VIDEO_WaitVSync(); + if (GCSettings.WiimoteOrientation == 0) + sprintf (options.value[1], "Vertical"); + else if (GCSettings.WiimoteOrientation == 1) + sprintf (options.value[1], "Horizontal"); + #else // GameCube + if(GCSettings.ExitAction > 1) + GCSettings.ExitAction = 0; + if (GCSettings.ExitAction == 0) + sprintf (options.value[0], "Return to Loader"); + else + sprintf (options.value[0], "Reboot"); - return pressed; -} // end GetInput() + options.name[1][0] = 0; // Wiimote + options.name[2][0] = 0; // Music + options.name[3][0] = 0; // Sound Effects + #endif -static u32 -GetButtonMap(u16 ctrlr_type, char* btn_name) -{ - int cfg_text_count = 7; - char cfg_text[][50] = { - "Remapping ", - "Press Any Button", - "on the", - " ", // identify controller - " ", - "Press C-Left or", - "Home to exit" - }; + if(GCSettings.MusicVolume > 0) + sprintf(options.value[2], "%d%%", GCSettings.MusicVolume); + else + sprintf(options.value[2], "Mute"); - u32 pressed, previous; - char temp[50] = ""; - uint k; - pressed = 0; previous = 1; + if(GCSettings.SFXVolume > 0) + sprintf(options.value[3], "%d%%", GCSettings.SFXVolume); + else + sprintf(options.value[3], "Mute"); - switch (ctrlr_type) { - case CTRLR_NUNCHUK: - strncpy (cfg_text[3], "NUNCHUK", 7); - break; - case CTRLR_CLASSIC: - strncpy (cfg_text[3], "CLASSIC", 7); - break; - case CTRLR_GCPAD: - strncpy (cfg_text[3], "GC PAD", 7); - break; - case CTRLR_WIIMOTE: - strncpy (cfg_text[3], "WIIMOTE", 7); - break; - }; - - /*** note which button we are remapping ***/ - sprintf (temp, "Remapping "); - for (k=0; k<9-strlen(btn_name); k++) strcat(temp, " "); // add whitespace padding to align text - strncat (temp, btn_name, 9); // nes button we are remapping - strncpy (cfg_text[0], temp, 19); // copy this all back to the text we wish to display - - DrawMenu(&cfg_text[0], NULL, cfg_text_count, 1, 20, -1); // display text - -// while (previous != pressed && pressed == 0); // get two consecutive button presses (which are the same) -// { -// previous = pressed; -// VIDEO_WaitVSync(); // slow things down a bit so we don't overread the pads - pressed = GetInput(ctrlr_type); -// } - return pressed; -} // end getButtonMap() - -static void -ConfigureButtons (u16 ctrlr_type) -{ - int cfg_btns_count = 12; - char cfg_btns_menu[][50] = { - "B - ", - "A - ", - "RAPID B - ", - "RAPID A - ", - "SELECT - ", - "START - ", - "UP - ", - "DOWN - ", - "LEFT - ", - "RIGHT - ", - "SPECIAL - ", - "Return to previous" - }; - - int quit = 0; - int ret = 0; - int oldmenu = menu; - menu = 0; - char menu_title[50]; - u32 pressed; - - unsigned int* currentpadmap = 0; - char temp[50] = ""; - int i, j; - uint k; - - /*** Update Menu Title (based on controller we're configuring) ***/ - switch (ctrlr_type) { - case CTRLR_NUNCHUK: - sprintf(menu_title, "NES - NUNCHUK"); - currentpadmap = ncpadmap; - break; - case CTRLR_CLASSIC: - sprintf(menu_title, "NES - CLASSIC"); - currentpadmap = ccpadmap; - break; - case CTRLR_GCPAD: - sprintf(menu_title, "NES - GC PAD"); - currentpadmap = gcpadmap; - break; - case CTRLR_WIIMOTE: - sprintf(menu_title, "NES - WIIMOTE"); - currentpadmap = wmpadmap; - break; - }; - - while (quit == 0) - { - /*** Update Menu with Current ButtonMap ***/ - for (i=0; i 2) + GCSettings.ExitAction = 0; + break; case 1: + GCSettings.WiimoteOrientation ^= 1; + break; case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - /*** Change button map ***/ - // wait for input - memset (temp, 0, sizeof(temp)); - strncpy(temp, cfg_btns_menu[ret], 6); // get the name of the snes button we're changing - pressed = GetButtonMap(ctrlr_type, temp); // get a button selection from user - // FIX: check if input is valid for this controller - if (pressed != 0) // check if a the button was configured, or if the user exited. - currentpadmap[ret] = pressed; // update mapping + GCSettings.MusicVolume += 10; + if(GCSettings.MusicVolume > 100) + GCSettings.MusicVolume = 0; + bgMusic->SetVolume(GCSettings.MusicVolume); break; - - case -1: /*** Button B ***/ - case 11: - /*** Return ***/ - quit = 1; + case 3: + GCSettings.SFXVolume += 10; + if(GCSettings.SFXVolume > 100) + GCSettings.SFXVolume = 0; break; } - } - menu = oldmenu; -} // end configurebuttons() -static void -ConfigureControllers () -{ - int ctlrmenucount = 8; - char ctlrmenu[][50] = { - "Four Score", - "Zapper", - "Zapper Crosshair", - "Nunchuk", - "Classic Controller", - "Wiimote", - "Gamecube Pad", - "Back to Preferences Menu" - }; - - int quit = 0; - int ret = 0; - int oldmenu = menu; - menu = 0; - - // disable unavailable controller options if in GC mode - #ifndef HW_RVL - ctlrmenu[3][0] = 0; - ctlrmenu[4][0] = 0; - ctlrmenu[5][0] = 0; - #endif - - while (quit == 0) - { - sprintf (ctlrmenu[0], "Four Score - %s", - GCSettings.FourScore == true ? " ON" : "OFF"); - - if (GCSettings.zapper == 0) sprintf (ctlrmenu[1],"Zapper - Disabled"); - else if (GCSettings.zapper == 1) sprintf (ctlrmenu[1],"Zapper - Port 1"); - else if (GCSettings.zapper == 2) sprintf (ctlrmenu[1],"Zapper - Port 2"); - - sprintf (ctlrmenu[2], "Zapper Crosshair - %s", - GCSettings.crosshair == true ? " ON" : "OFF"); - - /*** Controller Config Menu ***/ - ret = RunMenu (ctlrmenu, ctlrmenucount, "Configure Controllers", 20, -1); - - switch (ret) + if(backBtn.GetState() == STATE_CLICKED) { - case 0: // four score - GCSettings.FourScore ^= 1; - ToggleFourScore(GCSettings.FourScore, romLoaded); - break; - - case 1: // zapper - GCSettings.zapper -= 1; // we do this so Port 2 is first option shown - if(GCSettings.zapper < 0) - GCSettings.zapper = 2; - ToggleZapper(GCSettings.zapper, romLoaded); - break; - - case 2: // zapper crosshair - GCSettings.crosshair ^= 1; - break; - - case 3: - /*** Configure Nunchuk ***/ - ConfigureButtons (CTRLR_NUNCHUK); - break; - - case 4: - /*** Configure Classic ***/ - ConfigureButtons (CTRLR_CLASSIC); - break; - - case 5: - /*** Configure Wiimote ***/ - ConfigureButtons (CTRLR_WIIMOTE); - break; - - case 6: - /*** Configure GC Pad ***/ - ConfigureButtons (CTRLR_GCPAD); - break; - - case -1: /*** Button B ***/ - case 7: - /*** Return ***/ - quit = 1; - break; + menu = MENU_SETTINGS; } } - - menu = oldmenu; + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); + return menu; } /**************************************************************************** - * Preferences Menu + * MenuSettingsNetwork + ***************************************************************************/ + +static int MenuSettingsNetwork() +{ + int menu = MENU_NONE; +#ifdef HW_RVL + int ret; + int i = 0; + OptionList options; + sprintf(options.name[i++], "SMB Share IP"); + sprintf(options.name[i++], "SMB Share Name"); + sprintf(options.name[i++], "SMB Share Username"); + sprintf(options.name[i++], "SMB Share Password"); + options.length = i; + + GuiText titleTxt("Settings - Network", 28, (GXColor){255, 255, 255, 255}); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(50,50); + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM); + GuiImageData btnOutline(button_png); + GuiImageData btnOutlineOver(button_over_png); + + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiText backBtnTxt("Go Back", 24, (GXColor){0, 0, 0, 255}); + GuiImage backBtnImg(&btnOutline); + GuiImage backBtnImgOver(&btnOutlineOver); + GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight()); + backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + backBtn.SetPosition(100, -35); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetImage(&backBtnImg); + backBtn.SetImageOver(&backBtnImgOver); + backBtn.SetSoundOver(&btnSoundOver); + backBtn.SetTrigger(&trigA); + backBtn.SetEffectGrow(); + + GuiOptionBrowser optionBrowser(552, 248, &options); + optionBrowser.SetPosition(0, 108); + optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + + HaltGui(); + GuiWindow w(screenwidth, screenheight); + w.Append(&backBtn); + mainWindow->Append(&optionBrowser); + mainWindow->Append(&w); + mainWindow->Append(&titleTxt); + ResumeGui(); + + while(menu == MENU_NONE) + { + VIDEO_WaitVSync (); + + strncpy (options.value[0], GCSettings.smbip, 15); + strncpy (options.value[1], GCSettings.smbshare, 19); + strncpy (options.value[2], GCSettings.smbuser, 19); + strncpy (options.value[3], GCSettings.smbpwd, 19); + + ret = optionBrowser.GetClickedOption(); + + switch (ret) + { + case 0: + OnScreenKeyboard(GCSettings.smbip); + break; + + case 1: + OnScreenKeyboard(GCSettings.smbshare); + break; + + case 2: + OnScreenKeyboard(GCSettings.smbuser); + break; + + case 3: + OnScreenKeyboard(GCSettings.smbpwd); + break; + } + + if(backBtn.GetState() == STATE_CLICKED) + { + menu = MENU_SETTINGS; + } + } + HaltGui(); + mainWindow->Remove(&optionBrowser); + mainWindow->Remove(&w); + mainWindow->Remove(&titleTxt); +#endif + return menu; +} + +/**************************************************************************** + * MainMenu ***************************************************************************/ void -PreferencesMenu () +MainMenu (int menu) { - int prefmenuCount = 5; - char prefmenu[][50] = { - "Controllers", - "Video", - "Saving / Loading", - "Reset Preferences", - "Back to Main Menu" - }; - - int ret = 0; - int quit = 0; - int oldmenu = menu; - menu = 0; - while (quit == 0) - { - ret = RunMenu (prefmenu, prefmenuCount, "Preferences", 20, -1); - - switch (ret) - { - case 0: - ConfigureControllers (); - break; - - case 1: - VideoOptions (); - break; - - case 2: - FileOptions (); - break; - - case 3: - DefaultSettings (); - WaitPrompt("Preferences Reset"); - break; - - case -1: /*** Button B ***/ - case 4: - SavePrefs(SILENT); - quit = 1; - break; - - } - } - menu = oldmenu; -} - -/**************************************************************************** - * Main Menu - ****************************************************************************/ - -void -MainMenu (int selectedMenu) -{ - int menucount = 7; - char menuitems[][50] = { - "Choose Game", - "Preferences", - "Game Menu", - "Credits", - "DVD Motor Off", - "Reset System", - "Return to Loader" - }; - - int quit = 0; - int ret; + int currentMenu = menu; + lastMenu = MENU_NONE; #ifdef HW_RVL - // don't show dvd motor off on the wii - menuitems[4][0] = 0; - // rename reset/exit items - sprintf (menuitems[5], "Return to Wii Menu"); - sprintf (menuitems[6], "Return to Homebrew Channel"); + pointer[0] = new GuiImageData(player1_point_png); + pointer[1] = new GuiImageData(player2_point_png); + pointer[2] = new GuiImageData(player3_point_png); + pointer[3] = new GuiImageData(player4_point_png); #endif - VIDEO_WaitVSync (); + mainWindow = new GuiWindow(screenwidth, screenheight); - while (quit == 0) + bgImg = new GuiImage(screenwidth, screenheight, (GXColor){175, 200, 215, 255}); + bgImg->ColorStripe(10); + mainWindow->Append(bgImg); + + if(gameScreenTex) { - // disable game-specific menu items if a ROM isn't loaded - if(!romLoaded) - menuitems[2][0] = '\0'; - else - sprintf (menuitems[2], "Game Menu"); - - if(selectedMenu >= 0) - { - ret = selectedMenu; - selectedMenu = -1; // default back to main menu - } - else - { - ret = RunMenu (menuitems, menucount, "Main Menu", 20, -1); - } - - switch (ret) - { - case 0: - // Load ROM Menu - quit = LoadManager (); - break; - - case 1: - // Preferences - PreferencesMenu (); - break; - - case 2: - // Game Options - quit = GameMenu (); - break; - - case 3: - // Credits - Credits (); - WaitButtonA (); - break; - - case 4: - // turn the dvd motor off (GC only) - #ifdef HW_DOL - dvd_motor_off (); - #endif - break; - case 5: - // Reset the Gamecube/Wii - Reboot(); - break; - - case 6: - ExitToLoader(); - break; - - case -1: // Button B - // Return to Game - if(romLoaded) - quit = 1; - break; - } + gameScreenImg = new GuiImage(gameScreenTex, screenwidth, screenheight); + gameScreenImg->SetAlpha(192); + //gameScreenImg->SetStripe(100); + gameScreenImg->ColorStripe(30); + mainWindow->Append(gameScreenImg); + bgImg->SetVisible(false); } - // Wait for buttons to be released - int count = 0; // how long we've been waiting for the user to release the button - while(count < 50 && ( - PAD_ButtonsHeld(0) - #ifdef HW_RVL - || WPAD_ButtonsHeld(0) - #endif - )) + GuiTrigger trigA; + if(GCSettings.WiimoteOrientation) + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + else + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + + GuiImageData bgTop(bg_top_png); + bgTopImg = new GuiImage(&bgTop); + GuiImageData bgBottom(bg_bottom_png); + bgBottomImg = new GuiImage(&bgBottom); + bgBottomImg->SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM); + GuiImageData logo(logo_png); + GuiImage logoImg(&logo); + GuiImageData logoOver(logo_over_png); + GuiImage logoImgOver(&logoOver); + GuiText logoTxt(APPVERSION, 18, (GXColor){255, 255, 255, 255}); + logoTxt.SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + btnLogo = new GuiButton(logoImg.GetWidth(), logoImg.GetHeight()); + btnLogo->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); + btnLogo->SetPosition(-30, 30); + btnLogo->SetImage(&logoImg); + btnLogo->SetImageOver(&logoImgOver); + btnLogo->SetLabel(&logoTxt); + btnLogo->SetTrigger(&trigA); + btnLogo->SetUpdateCallback(WindowCredits); + + mainWindow->Append(bgTopImg); + mainWindow->Append(bgBottomImg); + mainWindow->Append(btnLogo); + + /*// memory usage - for debugging + memTxt = new GuiText(NULL, 18, (GXColor){255, 255, 255, 255}); + memTxt->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + memTxt->SetPosition(20, 20); + mainWindow->Append(memTxt);*/ + + if(currentMenu == MENU_GAMESELECTION) + ResumeGui(); + + // Load preferences + if(!LoadPrefs()) + SavePrefs(SILENT); + + #ifndef NO_SOUND + bgMusic = new GuiSound(bg_music_ogg, bg_music_ogg_size, SOUND_OGG); + bgMusic->SetVolume(GCSettings.MusicVolume); + if(currentMenu == MENU_GAMESELECTION) bgMusic->Play(); // startup music + #endif + + while(currentMenu != MENU_EXIT || !romLoaded) { - VIDEO_WaitVSync(); - count++; + switch (currentMenu) + { + case MENU_GAMESELECTION: + currentMenu = MenuGameSelection(); + break; + case MENU_GAME: + currentMenu = MenuGame(); + break; + case MENU_GAME_LOAD: + currentMenu = MenuGameSaves(0); + break; + case MENU_GAME_SAVE: + currentMenu = MenuGameSaves(1); + break; + /*case MENU_GAME_CHEATS: + currentMenu = MenuGameCheats(); + break;*/ + case MENU_SETTINGS: + currentMenu = MenuSettings(); + break; + case MENU_SETTINGS_MAPPINGS: + currentMenu = MenuSettingsMappings(); + break; + case MENU_SETTINGS_MAPPINGS_CTRL: + currentMenu = MenuSettingsMappingsController(); + break; + case MENU_SETTINGS_MAPPINGS_MAP: + currentMenu = MenuSettingsMappingsMap(); + break; + case MENU_SETTINGS_VIDEO: + currentMenu = MenuSettingsVideo(); + break; + case MENU_SETTINGS_FILE: + currentMenu = MenuSettingsFile(); + break; + case MENU_SETTINGS_MENU: + currentMenu = MenuSettingsMenu(); + break; + case MENU_SETTINGS_NETWORK: + currentMenu = MenuSettingsNetwork(); + break; + default: // unrecognized menu + currentMenu = MenuGameSelection(); + break; + } + lastMenu = currentMenu; + } + + #ifdef HW_RVL + ShutoffRumble(); + #endif + + CancelAction(); + HaltGui(); + + #ifndef NO_SOUND + bgMusic->Stop(); + delete bgMusic; + #endif + + //delete memTxt; + delete btnLogo; + delete bgImg; + delete bgTopImg; + delete bgBottomImg; + delete mainWindow; + + #ifdef HW_RVL + delete pointer[0]; + delete pointer[1]; + delete pointer[2]; + delete pointer[3]; + #endif + + mainWindow = NULL; + + if(gameScreenImg) + { + delete gameScreenImg; + gameScreenImg = NULL; + } + if(gameScreenTex) + { + free(gameScreenTex); + gameScreenTex = NULL; + } + if(gameScreenTex2) + { + free(gameScreenTex2); + gameScreenTex2 = NULL; } } diff --git a/source/ngc/menu.h b/source/ngc/menu.h index ac532e0..3f6bb43 100644 --- a/source/ngc/menu.h +++ b/source/ngc/menu.h @@ -2,7 +2,7 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * * menu.h * @@ -10,9 +10,36 @@ ****************************************************************************/ #ifndef _NGCMENU_ - #define _NGCMENU_ -void MainMenu (int selectedMenu); +#include + +void InitGUIThreads(); +void MainMenu (int menuitem); +void ErrorPrompt(const char * msg); +int ErrorPromptRetry(const char * msg); +void InfoPrompt(const char * msg); +void ShowAction (const char *msg); +void CancelAction(); +void ShowProgress (const char *msg, int done, int total); + +enum +{ + MENU_EXIT = -1, + MENU_NONE, + MENU_SETTINGS, + MENU_SETTINGS_MAPPINGS, + MENU_SETTINGS_MAPPINGS_CTRL, + MENU_SETTINGS_MAPPINGS_MAP, + MENU_SETTINGS_VIDEO, + MENU_SETTINGS_FILE, + MENU_SETTINGS_MENU, + MENU_SETTINGS_NETWORK, + MENU_GAMESELECTION, + MENU_GAME, + MENU_GAME_SAVE, + MENU_GAME_LOAD, + MENU_GAME_CHEATS +}; #endif diff --git a/source/ngc/networkop.cpp b/source/ngc/networkop.cpp index 9a7c71b..a0bca0e 100644 --- a/source/ngc/networkop.cpp +++ b/source/ngc/networkop.cpp @@ -18,7 +18,7 @@ #include "miniunz.h" #include "fceugx.h" -#include "menudraw.h" +#include "menu.h" #include "fileop.h" #include "http.h" @@ -146,12 +146,12 @@ bool DownloadUpdate() if(unzipResult) { result = true; - WaitPrompt("Update successful!"); + InfoPrompt("Update successful!"); } else { result = false; - WaitPrompt("Update failed!"); + InfoPrompt("Update failed!"); } updateFound = false; // updating is finished (successful or not!) @@ -193,7 +193,7 @@ void InitializeNetwork(bool silent) { char msg[150]; sprintf(msg, "Unable to initialize network (Error #: %i)", initResult); - WaitPrompt(msg); + ErrorPrompt(msg); } } } @@ -201,7 +201,7 @@ void InitializeNetwork(bool silent) void CloseShare() { if(networkShareInit) - smbClose(); + smbClose("smb"); networkShareInit = false; networkInit = false; // trigger a network reinit } @@ -242,7 +242,7 @@ ConnectShare (bool silent) sprintf(msg, "Share IP is blank."); sprintf(msg2, "Invalid network settings - %s", msg); - WaitPrompt(msg2); + ErrorPrompt(msg2); } return false; } @@ -268,7 +268,7 @@ ConnectShare (bool silent) } if(!networkShareInit && !silent) - WaitPrompt ("Failed to connect to network share."); + ErrorPrompt ("Failed to connect to network share."); } return networkShareInit; diff --git a/source/ngc/pad.cpp b/source/ngc/pad.cpp index 725445b..41a0579 100644 --- a/source/ngc/pad.cpp +++ b/source/ngc/pad.cpp @@ -10,7 +10,6 @@ ****************************************************************************/ #include -#include #include #include "fceugx.h" @@ -18,7 +17,10 @@ #include "gcaudio.h" #include "menu.h" #include "gcvideo.h" -#include "filesel.h" +#include "filebrowser.h" +#include "button_mapping.h" +#include "gui/gui.h" +#include "fceuload.h" extern "C" { #include "driver.h" @@ -27,7 +29,12 @@ extern "C" { extern INPUTC *FCEU_InitZapper(int w); } -extern bool romLoaded; +int rumbleRequest[4] = {0,0,0,0}; +GuiTrigger userInput[4]; + +#ifdef HW_RVL +static int rumbleCount[4] = {0,0,0,0}; +#endif static uint32 JSReturn = 0; void *InputDPR; @@ -35,11 +42,9 @@ void *InputDPR; static INPUTC *zapperdata[2]; static unsigned int myzappers[2][3]; -unsigned int nespadmap[11]; // Original NES controller buttons -unsigned int gcpadmap[11]; // Gamecube controller Padmap -unsigned int wmpadmap[11]; // Wiimote Padmap -unsigned int ccpadmap[11]; // Classic Controller Padmap -unsigned int ncpadmap[11]; // Nunchuk + wiimote Padmap +u32 nespadmap[11]; // Original NES controller buttons +u32 zapperpadmap[11]; // Original NES Zapper controller buttons +u32 btnmap[2][4][12]; // button mapping void ResetControls() { @@ -62,101 +67,151 @@ void ResetControls() /*** Gamecube controller Padmap ***/ i=0; - gcpadmap[i++] = PAD_BUTTON_B; - gcpadmap[i++] = PAD_BUTTON_A; - gcpadmap[i++] = PAD_BUTTON_Y; - gcpadmap[i++] = PAD_BUTTON_X; - gcpadmap[i++] = PAD_TRIGGER_Z; - gcpadmap[i++] = PAD_BUTTON_START; - gcpadmap[i++] = PAD_BUTTON_UP; - gcpadmap[i++] = PAD_BUTTON_DOWN; - gcpadmap[i++] = PAD_BUTTON_LEFT; - gcpadmap[i++] = PAD_BUTTON_RIGHT; - gcpadmap[i++] = PAD_TRIGGER_L; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_B; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_A; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_Y; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_X; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_TRIGGER_Z; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_START; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_UP; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_DOWN; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_LEFT; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_BUTTON_RIGHT; + btnmap[CTRL_PAD][CTRLR_GCPAD][i++] = PAD_TRIGGER_L; /*** Wiimote Padmap ***/ i=0; - wmpadmap[i++] = WPAD_BUTTON_1; - wmpadmap[i++] = WPAD_BUTTON_2; - wmpadmap[i++] = 0; - wmpadmap[i++] = 0; - wmpadmap[i++] = WPAD_BUTTON_MINUS; - wmpadmap[i++] = WPAD_BUTTON_PLUS; - wmpadmap[i++] = WPAD_BUTTON_RIGHT; - wmpadmap[i++] = WPAD_BUTTON_LEFT; - wmpadmap[i++] = WPAD_BUTTON_UP; - wmpadmap[i++] = WPAD_BUTTON_DOWN; - wmpadmap[i++] = WPAD_BUTTON_A; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_1; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_2; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = 0; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = 0; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_MINUS; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_PLUS; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_RIGHT; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_LEFT; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_UP; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_DOWN; + btnmap[CTRL_PAD][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_A; /*** Classic Controller Padmap ***/ i=0; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_Y; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_B; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_X; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_A; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_MINUS; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_PLUS; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_UP; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_DOWN; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_LEFT; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_RIGHT; - ccpadmap[i++] = WPAD_CLASSIC_BUTTON_FULL_L; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_Y; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_B; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_X; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_A; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_MINUS; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_PLUS; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_UP; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_DOWN; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_LEFT; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_RIGHT; + btnmap[CTRL_PAD][CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_FULL_L; /*** Nunchuk + wiimote Padmap ***/ i=0; - ncpadmap[i++] = WPAD_NUNCHUK_BUTTON_C; - ncpadmap[i++] = WPAD_NUNCHUK_BUTTON_Z; - ncpadmap[i++] = 0; - ncpadmap[i++] = 0; - ncpadmap[i++] = WPAD_BUTTON_MINUS; - ncpadmap[i++] = WPAD_BUTTON_PLUS; - ncpadmap[i++] = WPAD_BUTTON_UP; - ncpadmap[i++] = WPAD_BUTTON_DOWN; - ncpadmap[i++] = WPAD_BUTTON_LEFT; - ncpadmap[i++] = WPAD_BUTTON_RIGHT; - ncpadmap[i++] = WPAD_BUTTON_A; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_NUNCHUK_BUTTON_C; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_NUNCHUK_BUTTON_Z; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = 0; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = 0; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_MINUS; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_PLUS; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_UP; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_DOWN; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_LEFT; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_RIGHT; + btnmap[CTRL_PAD][CTRLR_NUNCHUK][i++] = WPAD_BUTTON_A; + + /*** Zapper : GC controller button mapping ***/ + i=0; + btnmap[CTRL_ZAPPER][CTRLR_GCPAD][i++] = PAD_BUTTON_A; // shoot + btnmap[CTRL_ZAPPER][CTRLR_GCPAD][i++] = PAD_BUTTON_B; // insert coin + + /*** Zapper : wiimote button mapping ***/ + i=0; + btnmap[CTRL_ZAPPER][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_B; // shoot + btnmap[CTRL_ZAPPER][CTRLR_WIIMOTE][i++] = WPAD_BUTTON_A; // insert coin +} + +/**************************************************************************** + * SetControllers + ***************************************************************************/ +void SetControllers() +{ + if(!romLoaded) + return; + + if(GCSettings.Controller == CTRL_PAD4) + FCEUI_DisableFourScore(false); + else + FCEUI_DisableFourScore(true); + + // set defaults + zapperdata[0]=NULL; + zapperdata[1]=NULL; + myzappers[0][0]=myzappers[1][0]=128; + myzappers[0][1]=myzappers[1][1]=120; + myzappers[0][2]=myzappers[1][2]=0; + + // Default ports back to gamepad + FCEUI_SetInput(0, SI_GAMEPAD, InputDPR, 0); + FCEUI_SetInput(1, SI_GAMEPAD, InputDPR, 0); + + if(GCSettings.Controller == CTRL_ZAPPER) + { + // enable Zapper + int z = 1; + zapperdata[z] = FCEU_InitZapper(z); + FCEUI_SetInput(z, SI_ZAPPER, myzappers[z], 1); + } } /**************************************************************************** * Initialise Pads - ****************************************************************************/ + ***************************************************************************/ void InitialisePads() { InputDPR = &JSReturn; FCEUI_SetInput(0, SI_GAMEPAD, InputDPR, 0); FCEUI_SetInput(1, SI_GAMEPAD, InputDPR, 0); - - ToggleFourScore(GCSettings.FourScore, true); - ToggleZapper(GCSettings.zapper, true); + SetControllers(); } -void ToggleFourScore(int set, bool loaded) -{ - if(loaded) - FCEUI_DisableFourScore(set); -} +#ifdef HW_RVL -void ToggleZapper(int set, bool loaded) +/**************************************************************************** + * ShutoffRumble + ***************************************************************************/ + +void ShutoffRumble() { - if(loaded) + for(int i=0;i<4;i++) { - // set defaults - zapperdata[0]=NULL; - zapperdata[1]=NULL; - myzappers[0][0]=myzappers[1][0]=128; - myzappers[0][1]=myzappers[1][1]=120; - myzappers[0][2]=myzappers[1][2]=0; + WPAD_Rumble(i, 0); + rumbleCount[i] = 0; + } +} - // Default ports back to gamepad - FCEUI_SetInput(0, SI_GAMEPAD, InputDPR, 0); - FCEUI_SetInput(1, SI_GAMEPAD, InputDPR, 0); +/**************************************************************************** + * DoRumble + ***************************************************************************/ - if(set) - { - // enable Zapper - zapperdata[set-1] = FCEU_InitZapper(set-1); - FCEUI_SetInput(set-1, SI_ZAPPER, myzappers[set-1], 1); - } +void DoRumble(int i) +{ + if(rumbleRequest[i] && rumbleCount[i] < 3) + { + WPAD_Rumble(i, 1); // rumble on + rumbleCount[i]++; + } + else if(rumbleRequest[i]) + { + rumbleCount[i] = 12; + rumbleRequest[i] = 0; + } + else + { + if(rumbleCount[i]) + rumbleCount[i]--; + WPAD_Rumble(i, 0); // rumble off } } @@ -243,6 +298,7 @@ s8 WPAD_StickY(u8 chan, u8 right) return (s8)(val * 128.0f); } +#endif // hold zapper cursor positions static int pos_x = 0; @@ -413,16 +469,16 @@ static unsigned char DecodeJoy( unsigned short pad ) int i; for (i = 0; i < MAXJP; i++) { - if ( (jp & gcpadmap[i]) // gamecube controller + if ( (jp & btnmap[CTRL_PAD][CTRLR_GCPAD][i]) // gamecube controller #ifdef HW_RVL - || ( (exp_type == WPAD_EXP_NONE) && (wp & wmpadmap[i]) ) // wiimote - || ( (exp_type == WPAD_EXP_CLASSIC) && (wp & ccpadmap[i]) ) // classic controller - || ( (exp_type == WPAD_EXP_NUNCHUK) && (wp & ncpadmap[i]) ) // nunchuk + wiimote + || ( (exp_type == WPAD_EXP_NONE) && (wp & btnmap[CTRL_PAD][CTRLR_WIIMOTE][i]) ) // wiimote + || ( (exp_type == WPAD_EXP_CLASSIC) && (wp & btnmap[CTRL_PAD][CTRLR_CLASSIC][i]) ) // classic controller + || ( (exp_type == WPAD_EXP_NUNCHUK) && (wp & btnmap[CTRL_PAD][CTRLR_NUNCHUK][i]) ) // nunchuk + wiimote #endif ) { // if zapper is on, ignore all buttons except START and SELECT - if(!GCSettings.zapper || nespadmap[i] == JOY_START || nespadmap[i] == JOY_SELECT) + if(GCSettings.Controller != CTRL_ZAPPER || nespadmap[i] == JOY_START || nespadmap[i] == JOY_SELECT) { if(nespadmap[i] == RAPID_A) { @@ -471,18 +527,16 @@ static unsigned char DecodeJoy( unsigned short pad ) } // zapper enabled - if(GCSettings.zapper) + if(GCSettings.Controller == CTRL_ZAPPER) { - int z = GCSettings.zapper-1; // NES port # (0 or 1) + int z = 1; // NES port # (0 or 1) myzappers[z][2] = 0; // reset trigger to not pressed // is trigger pressed? - if ( (jp & PAD_BUTTON_A) // gamecube controller + if ( (jp & btnmap[CTRL_ZAPPER][CTRLR_GCPAD][0]) // gamecube controller #ifdef HW_RVL - || (wp & WPAD_BUTTON_A) // wiimote - || (wp & WPAD_BUTTON_B) - || (wp & WPAD_CLASSIC_BUTTON_A) // classic controller + || ( (exp_type == WPAD_EXP_NONE) && (wp & btnmap[CTRL_ZAPPER][CTRLR_WIIMOTE][0]) ) // wiimote #endif ) { @@ -491,9 +545,9 @@ static unsigned char DecodeJoy( unsigned short pad ) } // VS zapper games - if ( (jp & PAD_BUTTON_B) // gamecube controller + if ( (jp & btnmap[CTRL_ZAPPER][CTRLR_GCPAD][1]) // gamecube controller #ifdef HW_RVL - || (wp & WPAD_BUTTON_1) // wiimote + || ( (exp_type == WPAD_EXP_NONE) && (wp & btnmap[CTRL_ZAPPER][CTRLR_WIIMOTE][1]) ) // wiimote #endif ) { @@ -519,13 +573,11 @@ void GetJoy() short i; s8 gc_px = PAD_SubStickX (0); - s8 gc_py = PAD_SubStickY (0); u32 jp = PAD_ButtonsHeld (0); // gamecube controller button info #ifdef HW_RVL s8 wm_sx = WPAD_StickX (0,1); - s8 wm_sy = WPAD_StickY (0,1); - u32 wm_pb = WPAD_ButtonsHeld (0); // wiimote / expansion button info + u32 wm_pb = WPAD_ButtonsDown (0); // wiimote / expansion button info #endif // Turbo mode @@ -544,17 +596,6 @@ void GetJoy() frameskip = 0; } - // Check for video zoom - if (GCSettings.Zoom) - { - if (gc_py < -36 || gc_py > 36) - zoom ((float) gc_py / -36); - #ifdef HW_RVL - if (wm_sy < -36 || wm_sy > 36) - zoom ((float) wm_sy / -36); - #endif - } - // request to go back to menu if ((gc_px < -70) || ((jp & PAD_BUTTON_START) && (jp & PAD_BUTTON_A) && @@ -565,7 +606,6 @@ void GetJoy() #endif ) { - StopAudio(); ConfigRequested = 1; } else diff --git a/source/ngc/pad.h b/source/ngc/pad.h index d19c679..ce3b00b 100644 --- a/source/ngc/pad.h +++ b/source/ngc/pad.h @@ -13,6 +13,7 @@ #define _PAD_H_ #include +#include #define PI 3.14159265f #define PADCAL 50 @@ -20,20 +21,58 @@ #define RAPID_A 256 #define RAPID_B 512 -extern unsigned int gcpadmap[]; -extern unsigned int wmpadmap[]; -extern unsigned int ccpadmap[]; -extern unsigned int ncpadmap[]; +enum +{ + TRIGGER_SIMPLE, + TRIGGER_BUTTON_ONLY, + TRIGGER_BUTTON_ONLY_IN_FOCUS +}; + +typedef struct _paddata { + u16 btns_d; + u16 btns_u; + u16 btns_h; + s8 stickX; + s8 stickY; + s8 substickX; + s8 substickY; + u8 triggerL; + u8 triggerR; +} PADData; + +class GuiTrigger +{ + public: + GuiTrigger(); + ~GuiTrigger(); + void SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + void SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + void SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + s8 WPAD_Stick(u8 right, int axis); + bool Left(); + bool Right(); + bool Up(); + bool Down(); + + u8 type; + s32 chan; + WPADData wpad; + PADData pad; +}; + +extern GuiTrigger userInput[4]; +extern int rumbleRequest[4]; +extern u32 btnmap[2][4][12]; void ResetControls(); +void ShutoffRumble(); +void DoRumble(int i); s8 WPAD_StickX(u8 chan,u8 right); s8 WPAD_StickY(u8 chan, u8 right); void InitialisePads(); void GetJoy(); -void ToggleFourScore(int set, bool loaded); -void ToggleZapper(int set, bool loaded); +void ToggleFourScore(int set); +void ToggleZapper(int set); void DrawCursor(); #endif - - \ No newline at end of file diff --git a/source/ngc/preferences.cpp b/source/ngc/preferences.cpp index 7ff0301..d5571a2 100644 --- a/source/ngc/preferences.cpp +++ b/source/ngc/preferences.cpp @@ -2,9 +2,9 @@ * FCE Ultra 0.98.12 * Nintendo Wii/Gamecube Port * - * Tantric September 2008 + * Tantric 2008-2009 * - * preferences.c + * preferences.cpp * * Preferences save/load preferences utilities ****************************************************************************/ @@ -15,8 +15,10 @@ #include #include -#include "images/saveicon.h" -#include "menudraw.h" +#include "fceuconfig.h" +#include "button_mapping.h" +#include "filebrowser.h" +#include "menu.h" #include "memcardop.h" #include "fileop.h" #include "fceugx.h" @@ -108,25 +110,6 @@ static const char * XMLSaveCallback(mxml_node_t *node, int where) static int preparePrefsData (int method) { - int offset = 0; - - // add save icon and comments for Memory Card saves - if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) - { - offset = sizeof (saveicon); - - // Copy in save icon - memcpy (savebuffer, saveicon, offset); - - // And the comments - char prefscomment[2][32]; - memset(prefscomment, 0, 64); - sprintf (prefscomment[0], "%s Prefs", APPNAME); - sprintf (prefscomment[1], "Preferences"); - memcpy (savebuffer + offset, prefscomment, 64); - offset += 64; - } - xml = mxmlNewXML("1.0"); mxmlSetWrapMargin(0); // disable line wrapping @@ -152,11 +135,10 @@ preparePrefsData (int method) createXMLSetting("smbuser", "Share Username", GCSettings.smbuser); createXMLSetting("smbpwd", "Share Password", GCSettings.smbpwd); - createXMLSection("Emulation", "Emulation Settings"); + createXMLSection("Video", "Video Settings"); createXMLSetting("currpal", "Palette", toStr(GCSettings.currpal)); createXMLSetting("timing", "Timing", toStr(GCSettings.timing)); - createXMLSetting("Zoom", "Zoom On/Off", toStr(GCSettings.Zoom)); createXMLSetting("ZoomLevel", "Zoom Level", FtoStr(GCSettings.ZoomLevel)); createXMLSetting("render", "Video Filtering", toStr(GCSettings.render)); createXMLSetting("widescreen", "Aspect Ratio Correction", toStr(GCSettings.widescreen)); @@ -164,15 +146,24 @@ preparePrefsData (int method) createXMLSetting("xshift", "Horizontal Video Shift", toStr(GCSettings.xshift)); createXMLSetting("yshift", "Vertical Video Shift", toStr(GCSettings.yshift)); + createXMLSection("Menu", "Menu Settings"); + + createXMLSetting("WiimoteOrientation", "Wiimote Orientation", toStr(GCSettings.WiimoteOrientation)); + createXMLSetting("ExitAction", "Exit Action", toStr(GCSettings.ExitAction)); + createXMLSetting("MusicVolume", "Music Volume", toStr(GCSettings.MusicVolume)); + createXMLSetting("SFXVolume", "Sound Effects Volume", toStr(GCSettings.SFXVolume)); + createXMLSection("Controller", "Controller Settings"); - createXMLSetting("FourScore", "Four Score", toStr(GCSettings.FourScore)); - createXMLSetting("zapper", "Zapper", toStr(GCSettings.zapper)); + createXMLSetting("Controller", "Controller", toStr(GCSettings.Controller)); createXMLSetting("crosshair", "Zapper Crosshair", toStr(GCSettings.crosshair)); - createXMLController(gcpadmap, "gcpadmap", "GameCube Pad"); - createXMLController(wmpadmap, "wmpadmap", "Wiimote"); - createXMLController(ccpadmap, "ccpadmap", "Classic Controller"); - createXMLController(ncpadmap, "ncpadmap", "Nunchuk"); + + createXMLController(btnmap[CTRL_PAD][CTRLR_GCPAD], "btnmap_pad_gcpad", "NES Pad - GameCube Controller"); + createXMLController(btnmap[CTRL_PAD][CTRLR_WIIMOTE], "btnmap_pad_wiimote", "NES Pad - Wiimote"); + createXMLController(btnmap[CTRL_PAD][CTRLR_CLASSIC], "btnmap_pad_classic", "NES Pad - Classic Controller"); + createXMLController(btnmap[CTRL_PAD][CTRLR_NUNCHUK], "btnmap_pad_nunchuk", "NES Pad - Nunchuk + Wiimote"); + createXMLController(btnmap[CTRL_ZAPPER][CTRLR_GCPAD], "btnmap_zapper_gcpad", "Zapper - GameCube Controller"); + createXMLController(btnmap[CTRL_ZAPPER][CTRLR_WIIMOTE], "btnmap_zapper_wiimote", "Zapper - Wiimote"); int datasize = mxmlSaveString(xml, (char *)savebuffer, SAVEBUFFERSIZE, XMLSaveCallback); @@ -216,7 +207,6 @@ static void loadXMLSetting(float * var, const char * name) } static void loadXMLController(unsigned int controller[], const char * name) - { item = mxmlFindElement(xml, xml, "controller", "name", name, MXML_DESCEND); @@ -241,16 +231,8 @@ static bool decodePrefsData (int method) { bool result = false; - int offset = 0; - // skip save icon and comments for Memory Card saves - if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) - { - offset = sizeof (saveicon); - offset += 64; // sizeof prefscomment - } - - xml = mxmlLoadString(NULL, (char *)savebuffer+offset, MXML_TEXT_CALLBACK); + xml = mxmlLoadString(NULL, (char *)savebuffer, MXML_TEXT_CALLBACK); if(xml) { @@ -305,11 +287,10 @@ decodePrefsData (int method) loadXMLSetting(GCSettings.smbuser, "smbuser", sizeof(GCSettings.smbuser)); loadXMLSetting(GCSettings.smbpwd, "smbpwd", sizeof(GCSettings.smbpwd)); - // Emulation Settings + // Video Settings loadXMLSetting(&GCSettings.currpal, "currpal"); loadXMLSetting(&GCSettings.timing, "timing"); - loadXMLSetting(&GCSettings.Zoom, "Zoom"); loadXMLSetting(&GCSettings.ZoomLevel, "ZoomLevel"); loadXMLSetting(&GCSettings.render, "render"); loadXMLSetting(&GCSettings.widescreen, "widescreen"); @@ -317,15 +298,23 @@ decodePrefsData (int method) loadXMLSetting(&GCSettings.xshift, "xshift"); loadXMLSetting(&GCSettings.yshift, "yshift"); + // Menu Settings + + loadXMLSetting(&GCSettings.WiimoteOrientation, "WiimoteOrientation"); + loadXMLSetting(&GCSettings.ExitAction, "ExitAction"); + loadXMLSetting(&GCSettings.MusicVolume, "MusicVolume"); + loadXMLSetting(&GCSettings.SFXVolume, "SFXVolume"); + // Controller Settings - loadXMLSetting(&GCSettings.FourScore, "FSDisable"); - loadXMLSetting(&GCSettings.zapper, "zapper"); + loadXMLSetting(&GCSettings.Controller, "Controller"); loadXMLSetting(&GCSettings.crosshair, "crosshair"); - loadXMLController(gcpadmap, "gcpadmap"); - loadXMLController(wmpadmap, "wmpadmap"); - loadXMLController(ccpadmap, "ccpadmap"); - loadXMLController(ncpadmap, "ncpadmap"); + loadXMLController(btnmap[CTRL_PAD][CTRLR_GCPAD], "btnmap_pad_gcpad"); + loadXMLController(btnmap[CTRL_PAD][CTRLR_WIIMOTE], "btnmap_pad_wiimote"); + loadXMLController(btnmap[CTRL_PAD][CTRLR_CLASSIC], "btnmap_pad_classic"); + loadXMLController(btnmap[CTRL_PAD][CTRLR_NUNCHUK], "btnmap_pad_nunchuk"); + loadXMLController(btnmap[CTRL_ZAPPER][CTRLR_GCPAD], "btnmap_zapper_gcpad"); + loadXMLController(btnmap[CTRL_ZAPPER][CTRLR_WIIMOTE], "btnmap_zapper_wiimote"); } mxmlDelete(xml); } @@ -347,23 +336,40 @@ SavePrefs (bool silent) // is the method preferences will be loaded from by default int method = autoSaveMethod(silent); + if(method == METHOD_AUTO) + return false; + if(!MakeFilePath(filepath, FILE_PREF, method)) return false; if (!silent) ShowAction ("Saving preferences..."); + FixInvalidSettings(); + AllocSaveBuffer (); datasize = preparePrefsData (method); + if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) + { + // Set the comments + char prefscomment[2][32]; + memset(prefscomment, 0, 64); + sprintf (prefscomment[0], "%s Prefs", APPNAME); + sprintf (prefscomment[1], "Preferences"); + SetMCSaveComments(prefscomment); + } + offset = SaveFile(filepath, datasize, method, silent); FreeSaveBuffer (); + CancelAction(); + if (offset > 0) { if (!silent) - WaitPrompt ("Preferences saved"); + InfoPrompt ("Preferences saved"); return true; } return false; @@ -398,20 +404,29 @@ LoadPrefsFromMethod (int method) * Load Preferences * Checks sources consecutively until we find a preference file ***************************************************************************/ +static bool prefLoaded = false; + bool LoadPrefs() { - ShowAction ("Loading preferences..."); + if(prefLoaded) // already attempted loading + return true; + bool prefFound = false; if(ChangeInterface(METHOD_SD, SILENT)) prefFound = LoadPrefsFromMethod(METHOD_SD); if(!prefFound && ChangeInterface(METHOD_USB, SILENT)) prefFound = LoadPrefsFromMethod(METHOD_USB); - if(!prefFound && TestCard(CARD_SLOTA, SILENT)) + if(!prefFound && TestMC(CARD_SLOTA, SILENT)) prefFound = LoadPrefsFromMethod(METHOD_MC_SLOTA); - if(!prefFound && TestCard(CARD_SLOTB, SILENT)) + if(!prefFound && TestMC(CARD_SLOTB, SILENT)) prefFound = LoadPrefsFromMethod(METHOD_MC_SLOTB); if(!prefFound && ChangeInterface(METHOD_SMB, SILENT)) prefFound = LoadPrefsFromMethod(METHOD_SMB); + prefLoaded = true; // attempted to load preferences + + if(prefFound) + FixInvalidSettings(); + return prefFound; } diff --git a/source/unzip/miniunz.cpp b/source/unzip/miniunz.cpp index 45e967c..ce30180 100644 --- a/source/unzip/miniunz.cpp +++ b/source/unzip/miniunz.cpp @@ -16,7 +16,7 @@ #include #include "unzip.h" -#include "menudraw.h" +#include "menu.h" #define CASESENSITIVITY (0) #define WRITEBUFFERSIZE (1024*256)