From bb27c041ea6464dd4e332e43d04b6dfdf834167f Mon Sep 17 00:00:00 2001 From: mcfarlandjb Date: Sun, 16 Feb 2014 04:49:53 +0000 Subject: [PATCH] Added basic SDL2 GameController API support. SDL2 rendering added. For some reason windowed mode totally sucks, at least on my Ubuntu 12.04 machine. But fullscreen runs just fine. Updated main SConstruct to allow overriding LIBRARY_PATH and INCLUDE_PATH for non-standard SDL2 installation paths --- branches/sdl2/SConstruct | 5 +- branches/sdl2/src/drivers/sdl/SConscript | 1 + branches/sdl2/src/drivers/sdl/config.cpp | 59 +- branches/sdl2/src/drivers/sdl/dface.h | 2 + branches/sdl2/src/drivers/sdl/input.cpp | 937 +++++++++--------- branches/sdl2/src/drivers/sdl/input.h | 2 + .../sdl2/src/drivers/sdl/sdl-gamectrl.cpp | 125 +++ branches/sdl2/src/drivers/sdl/sdl-sound.cpp | 21 +- branches/sdl2/src/drivers/sdl/sdl-video.cpp | 558 ++++++++--- branches/sdl2/src/drivers/sdl/sdl.cpp | 5 + 10 files changed, 1099 insertions(+), 616 deletions(-) create mode 100644 branches/sdl2/src/drivers/sdl/sdl-gamectrl.cpp diff --git a/branches/sdl2/SConstruct b/branches/sdl2/SConstruct index 5d9f0bb4..59e1b7ae 100644 --- a/branches/sdl2/SConstruct +++ b/branches/sdl2/SConstruct @@ -66,7 +66,10 @@ if os.environ.has_key('PKG_CONFIG_PATH'): env['ENV']['PKG_CONFIG_PATH'] = os.environ['PKG_CONFIG_PATH'] if os.environ.has_key('PKG_CONFIG_LIBDIR'): env['ENV']['PKG_CONFIG_LIBDIR'] = os.environ['PKG_CONFIG_LIBDIR'] - +if os.environ.has_key('LIBRARY_PATH'): + env['ENV']['LIBRARY_PATH'] = os.environ['LIBRARY_PATH'] +if os.environ.has_key('INCLUDE_PATH'): + env['ENV']['INCLUDE_PATH'] = os.environ['INCLUDE_PATH'] print "platform: ", env['PLATFORM'] diff --git a/branches/sdl2/src/drivers/sdl/SConscript b/branches/sdl2/src/drivers/sdl/SConscript index 23e11b95..2f370d08 100644 --- a/branches/sdl2/src/drivers/sdl/SConscript +++ b/branches/sdl2/src/drivers/sdl/SConscript @@ -11,6 +11,7 @@ source_list = Split( config.cpp sdl.cpp sdl-joystick.cpp + sdl-gamectrl.cpp sdl-sound.cpp sdl-throttle.cpp sdl-video.cpp diff --git a/branches/sdl2/src/drivers/sdl/config.cpp b/branches/sdl2/src/drivers/sdl/config.cpp index 0dbb2a92..ace336ac 100644 --- a/branches/sdl2/src/drivers/sdl/config.cpp +++ b/branches/sdl2/src/drivers/sdl/config.cpp @@ -62,7 +62,7 @@ LoadCPalette(const std::string &file) static void CreateDirs(const std::string &dir) { - char *subs[8]={"fcs","snaps","gameinfo","sav","cheats","movies","cfg.d"}; + char *subs[8]= {"fcs","snaps","gameinfo","sav","cheats","movies","cfg.d"}; std::string subdir; int x; @@ -139,7 +139,7 @@ InitConfig() config->addOption("soundrecord", "SDL.Sound.RecordFile", ""); config->addOption("soundbufsize", "SDL.Sound.BufSize", 128); config->addOption("lowpass", "SDL.Sound.LowPass", 0); - + config->addOption('g', "gamegenie", "SDL.GameGenie", 0); config->addOption("pal", "SDL.PAL", 0); config->addOption("frameskip", "SDL.Frameskip", 0); @@ -191,7 +191,7 @@ InitConfig() config->addOption('k', "netkey", "SDL.NetworkGameKey", ""); config->addOption("port", "SDL.NetworkPort", 4046); config->addOption("players", "SDL.NetworkPlayers", 1); - + // input configuration options config->addOption("input1", "SDL.Input.0", "GamePad.0"); config->addOption("input2", "SDL.Input.1", "GamePad.1"); @@ -200,50 +200,50 @@ InitConfig() // allow for input configuration config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg); - + // display input config->addOption("inputdisplay", "SDL.InputDisplay", 0); // enable / disable opposite directionals (left + right or up + down simultaneously) config->addOption("opposite-directionals", "SDL.Input.EnableOppositeDirectionals", 1); - + // pause movie playback at frame x config->addOption("pauseframe", "SDL.PauseFrame", 0); config->addOption("recordhud", "SDL.RecordHUD", 1); config->addOption("moviemsg", "SDL.MovieMsg", 1); - + // overwrite the config file? config->addOption("no-config", "SDL.NoConfig", 0); config->addOption("autoresume", "SDL.AutoResume", 0); - + // video playback config->addOption("playmov", "SDL.Movie", ""); config->addOption("subtitles", "SDL.SubtitleDisplay", 1); - + config->addOption("fourscore", "SDL.FourScore", 0); config->addOption("nofscursor", "SDL.NoFullscreenCursor", 1); - - #ifdef _S9XLUA_H + +#ifdef _S9XLUA_H // load lua script config->addOption("loadlua", "SDL.LuaScript", ""); - #endif - - #ifdef CREATE_AVI +#endif + +#ifdef CREATE_AVI config->addOption("videolog", "SDL.VideoLog", ""); config->addOption("mute", "SDL.MuteCapture", 0); - #endif - - // auto load/save on gameload/close +#endif + + // auto load/save on gameload/close config->addOption("loadstate", "SDL.AutoLoadState", INVALID_STATE); config->addOption("savestate", "SDL.AutoSaveState", INVALID_STATE); - //TODO implement this - config->addOption("periodicsaves", "SDL.PeriodicSaves", 0); + //TODO implement this + config->addOption("periodicsaves", "SDL.PeriodicSaves", 0); - - #ifdef _GTK + +#ifdef _GTK char* home_dir = getenv("HOME"); // prefixed with _ because they are internal (not cli options) config->addOption("_lastopenfile", "SDL.LastOpenFile", home_dir); @@ -251,19 +251,19 @@ InitConfig() config->addOption("_lastopennsf", "SDL.LastOpenNSF", home_dir); config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", home_dir); config->addOption("_lastloadlua", "SDL.LastLoadLua", home_dir); - #endif - +#endif + // fcm -> fm2 conversion config->addOption("fcmconvert", "SDL.FCMConvert", ""); - + // fm2 -> srt conversion config->addOption("ripsubs", "SDL.RipSubs", ""); - + // enable new PPU core config->addOption("newppu", "SDL.NewPPU", 0); - // quit when a+b+select+start is pressed - config->addOption("4buttonexit", "SDL.ABStartSelectExit", 0); + // quit when a+b+select+start is pressed + config->addOption("4buttonexit", "SDL.ABStartSelectExit", 0); // GamePad 0 - 3 for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) { @@ -277,7 +277,7 @@ InitConfig() config->addOption(prefix + GamePadNames[j], DefaultGamePad[i][j]); } } - + // PowerPad 0 - 1 for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) { char buf[64]; @@ -337,7 +337,7 @@ InitConfig() config->addOption(prefix + "DeviceNum", 0); for(unsigned int j = 0; j < FAMILYKEYBOARD_NUM_BUTTONS; j++) { config->addOption(prefix + FamilyKeyBoardNames[j], - DefaultFamilyKeyBoard[j]); + DefaultFamilyKeyBoard[j]); } // for FAMICOM microphone in pad 2 pad 1 didn't have it @@ -377,7 +377,8 @@ InitConfig() SDLK_0, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6, SDLK_7, SDLK_8, SDLK_9, SDLK_PAGEUP, // select state next - SDLK_PAGEDOWN}; // select state prev + SDLK_PAGEDOWN + }; // select state prev prefix = "SDL.Hotkeys."; for(int i=0; i < HK_MAX; i++) diff --git a/branches/sdl2/src/drivers/sdl/dface.h b/branches/sdl2/src/drivers/sdl/dface.h index f753f3ca..ea326f30 100644 --- a/branches/sdl2/src/drivers/sdl/dface.h +++ b/branches/sdl2/src/drivers/sdl/dface.h @@ -18,6 +18,8 @@ void SilenceSound(int s); /* DOS and SDL */ int InitJoysticks(void); int KillJoysticks(void); +int InitGameControllers(void); +int KillGameControllers(void); uint32 *GetJSOr(void); int InitVideo(FCEUGI *gi); diff --git a/branches/sdl2/src/drivers/sdl/input.cpp b/branches/sdl2/src/drivers/sdl/input.cpp index c371b2fe..b1061dfe 100644 --- a/branches/sdl2/src/drivers/sdl/input.cpp +++ b/branches/sdl2/src/drivers/sdl/input.cpp @@ -159,7 +159,7 @@ _keyonly (int a) keyonce[a] = 1; return 1; } - } + } else { keyonce[a] = 0; } @@ -222,8 +222,8 @@ TogglePause () return; } -/*** - * This function opens a file chooser dialog and returns the filename the +/*** + * This function opens a file chooser dialog and returns the filename the * user selected. * */ std::string GetFilename (const char *title, bool save, const char *filter) @@ -243,7 +243,7 @@ std::string GetFilename (const char *title, bool save, const char *filter) ofn.lStructSize = sizeof (ofn); ofn.hwndOwner = hwnd; ofn.lpstrFile = szFile; - // Set lpstrFile[0] to '\0' so that GetOpenFileName does not + // Set lpstrFile[0] to '\0' so that GetOpenFileName does not // use the contents of szFile to initialize itself. ofn.lpstrFile[0] = '\0'; ofn.nMaxFile = sizeof (szFile); @@ -254,7 +254,7 @@ std::string GetFilename (const char *title, bool save, const char *filter) ofn.lpstrInitialDir = NULL; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - // Display the Open dialog box. + // Display the Open dialog box. fname = GetOpenFileName (&ofn); #endif @@ -280,20 +280,20 @@ std::string GetFilename (const char *title, bool save, const char *filter) if (save) fileChooser = gtk_file_chooser_dialog_new ("Save as", NULL, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE_AS, - GTK_RESPONSE_ACCEPT, NULL); + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE_AS, + GTK_RESPONSE_ACCEPT, NULL); else fileChooser = gtk_file_chooser_dialog_new ("Open", NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, - GTK_RESPONSE_ACCEPT, NULL); + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, + GTK_RESPONSE_ACCEPT, NULL); - // TODO: make file filters case insensitive + // TODO: make file filters case insensitive //gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fileChooser), filterX); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll); int response = gtk_dialog_run (GTK_DIALOG (fileChooser)); @@ -320,49 +320,49 @@ std::string GetFilename (const char *title, bool save, const char *filter) std::string GetUserText (const char *title) { #ifdef _GTK -/* prg318 - 10/13/11 - this is broken in recent build and causes - * segfaults/very weird behavior i'd rather remove it for now than it cause - * accidental segfaults - * TODO fix it -*/ + /* prg318 - 10/13/11 - this is broken in recent build and causes + * segfaults/very weird behavior i'd rather remove it for now than it cause + * accidental segfaults + * TODO fix it + */ #if 0 GtkWidget* d; GtkWidget* entry; - - d = gtk_dialog_new_with_buttons(title, NULL, GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_OK); - + + d = gtk_dialog_new_with_buttons(title, NULL, GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_OK); + entry = gtk_entry_new(); GtkWidget* vbox = gtk_dialog_get_content_area(GTK_DIALOG(d)); - + gtk_container_add(GTK_CONTAINER(vbox), entry); - + gtk_widget_show_all(d); - + gtk_dialog_run(GTK_DIALOG(d)); - + // flush gtk events while(gtk_events_pending()) - gtk_main_iteration_do(TRUE); + gtk_main_iteration_do(TRUE); + + std::string input = gtk_entry_get_text(GTK_ENTRY(entry)); + + if (FCEUI_EmulationPaused() == 0) + FCEUI_ToggleEmulationPause(); // pause emulation + + int fullscreen = 0; + g_config->getOption("SDL.Fullscreen", &fullscreen); + if(fullscreen) + ToggleFS(); // disable fullscreen emulation - std::string input = gtk_entry_get_text(GTK_ENTRY(entry)); - - if (FCEUI_EmulationPaused() == 0) - FCEUI_ToggleEmulationPause(); // pause emulation - - int fullscreen = 0; - g_config->getOption("SDL.Fullscreen", &fullscreen); - if(fullscreen) - ToggleFS(); // disable fullscreen emulation - FILE *fpipe; std::string command = "zenity --entry --title=\""; command.append(title); command.append("\" --text=\""); command.append(title); command.append(":\""); - + if (!(fpipe = (FILE*)popen(command.c_str(),"r"))) // If fpipe is NULL FCEUD_PrintError("Pipe error on opening zenity"); int c; @@ -373,18 +373,18 @@ std::string GetUserText (const char *title) break; input += c; } - pclose(fpipe); - gtk_widget_destroy(d); + pclose(fpipe); + gtk_widget_destroy(d); - while(gtk_events_pending()) - gtk_main_iteration_do(TRUE); + while(gtk_events_pending()) + gtk_main_iteration_do(TRUE); - FCEUI_ToggleEmulationPause(); // unpause emulation - return input; + FCEUI_ToggleEmulationPause(); // unpause emulation + return input; #endif // #if 0 #endif - return ""; + return ""; } @@ -429,7 +429,7 @@ void FCEUD_LoadStateFrom () /** * Hook for transformer board */ -unsigned int *GetKeyboard(void) +unsigned int *GetKeyboard(void) { int size = 256; #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -464,11 +464,11 @@ static void KeyboardCommands () #else if (keyonly (SCROLLLOCK)) #endif - { - g_fkbEnabled ^= 1; - FCEUI_DispMessage ("Family Keyboard %sabled.", 0, - g_fkbEnabled ? "en" : "dis"); - } + { + g_fkbEnabled ^= 1; + FCEUI_DispMessage ("Family Keyboard %sabled.", 0, + g_fkbEnabled ? "en" : "dis"); + } #if SDL_VERSION_ATLEAST(2, 0, 0) // TODO - SDL2 #else @@ -482,26 +482,26 @@ static void KeyboardCommands () #if SDL_VERSION_ATLEAST(2, 0, 0) if (g_keyState[SDL_GetScancodeFromKey (SDLK_LSHIFT)] - || g_keyState[SDL_GetScancodeFromKey (SDLK_RSHIFT)]) + || g_keyState[SDL_GetScancodeFromKey (SDLK_RSHIFT)]) #else if (g_keyState[SDLK_LSHIFT] || g_keyState[SDLK_RSHIFT]) #endif - is_shift = 1; - else - is_shift = 0; + is_shift = 1; + else + is_shift = 0; #if SDL_VERSION_ATLEAST(2, 0, 0) if (g_keyState[SDL_GetScancodeFromKey (SDLK_LALT)] - || g_keyState[SDL_GetScancodeFromKey (SDLK_RALT)]) + || g_keyState[SDL_GetScancodeFromKey (SDLK_RALT)]) #else if (g_keyState[SDLK_LALT] || g_keyState[SDLK_RALT]) #endif { is_alt = 1; #if !SDL_VERSION_ATLEAST(2, 0, 0) - // workaround for GDK->SDL in GTK problems where ALT release is never - // getting sent - // I know this is sort of an ugly hack to fix this, but the bug is - // rather annoying + // workaround for GDK->SDL in GTK problems where ALT release is never + // getting sent + // I know this is sort of an ugly hack to fix this, but the bug is + // rather annoying // prg318 10/23/11 int fullscreen; g_config->getOption ("SDL.Fullscreen", &fullscreen); @@ -541,7 +541,7 @@ static void KeyboardCommands () { autoMovieBackup ^= 1; FCEUI_DispMessage ("Automatic movie backup %sabled.", 0, - autoMovieBackup ? "en" : "dis"); + autoMovieBackup ? "en" : "dis"); } // Start recording an FM2 movie on Alt+R @@ -562,7 +562,7 @@ static void KeyboardCommands () FCEUD_LoadStateFrom (); } - // Famicom disk-system games + // Famicom disk-system games if (gametype == GIT_FDS) { if (_keyonly (Hotkeys[HK_FDS_SELECT])) @@ -594,7 +594,7 @@ static void KeyboardCommands () if (is_shift) { movie_fname = - const_cast (FCEU_MakeFName (FCEUMKF_MOVIE, 0, 0).c_str ()); + const_cast (FCEU_MakeFName (FCEUMKF_MOVIE, 0, 0).c_str ()); FCEUI_printf ("Recording movie to %s\n", movie_fname); FCEUI_SaveMovie (movie_fname, MOVIE_FLAG_NONE, L""); } @@ -612,21 +612,21 @@ static void KeyboardCommands () FCEUI_StopMovie (); std::string fname; fname = - GetFilename ("Open FM2 movie for playback...", false, - "FM2 movies|*.fm2"); + GetFilename ("Open FM2 movie for playback...", false, + "FM2 movies|*.fm2"); if (fname != "") { if (fname.find (".fm2") != std::string::npos - || fname.find (".fm3") != std::string::npos) + || fname.find (".fm3") != std::string::npos) { FCEUI_printf ("Playing back movie located at %s\n", - fname.c_str ()); + fname.c_str ()); FCEUI_LoadMovie (fname.c_str (), false, false); } else { FCEUI_printf - ("Only .fm2 and .fm3 movies are supported.\n"); + ("Only .fm2 and .fm3 movies are supported.\n"); } } } @@ -675,7 +675,7 @@ static void KeyboardCommands () if (_keyonly (Hotkeys[HK_PAUSE])) { - //FCEUI_ToggleEmulationPause(); + //FCEUI_ToggleEmulationPause(); // use the wrapper function instead of the fceui function directly // so we can handle cursor grabbage TogglePause (); @@ -729,13 +729,13 @@ static void KeyboardCommands () } else #ifdef _S9XLUA_H - if (_keyonly (Hotkeys[HK_LOAD_LUA])) - { - std::string fname; - fname = GetFilename ("Open LUA script...", false, "Lua scripts|*.lua"); - if (fname != "") - FCEU_LoadLuaCode (fname.c_str ()); - } + if (_keyonly (Hotkeys[HK_LOAD_LUA])) + { + std::string fname; + fname = GetFilename ("Open LUA script...", false, "Lua scripts|*.lua"); + if (fname != "") + FCEU_LoadLuaCode (fname.c_str ()); + } #endif for (int i = 0; i < 10; i++) @@ -761,14 +761,14 @@ static void KeyboardCommands () { bindSavestate ^= 1; FCEUI_DispMessage ("Savestate binding to movie %sabled.", 0, - bindSavestate ? "en" : "dis"); + bindSavestate ? "en" : "dis"); } if (_keyonly (Hotkeys[HK_FA_LAG_SKIP])) { frameAdvanceLagSkip ^= 1; FCEUI_DispMessage ("Skipping lag in Frame Advance %sabled.", 0, - frameAdvanceLagSkip ? "en" : "dis"); + frameAdvanceLagSkip ? "en" : "dis"); } if (_keyonly (Hotkeys[HK_LAG_COUNTER_DISPLAY])) @@ -781,7 +781,7 @@ static void KeyboardCommands () extern int movieSubtitles; movieSubtitles ^= 1; FCEUI_DispMessage ("Movie subtitles o%s.", 0, - movieSubtitles ? "n" : "ff"); + movieSubtitles ? "n" : "ff"); } // VS Unisystem games @@ -801,7 +801,7 @@ static void KeyboardCommands () goto DIPSless; // toggle the various dipswitches - for(int i=1; i<=8;i++) + for(int i=1; i<=8; i++) { if(keyonly(i)) FCEUI_VSUniToggleDIP(i-1); @@ -864,8 +864,8 @@ do { \ } \ } while(0) - DIPSless: - for(int i=0; i<10;i++) +DIPSless: + for(int i=0; i<10; i++) { if (keyonly (i)) SSM (i); @@ -920,7 +920,7 @@ GetMouseData (uint32 (&d)[3]) t = PtoV (x, y); d[0] = t & 0xFFFF; d[1] = (t >> 16) & 0xFFFF; - // debug print + // debug print // printf("mouse %d %d %d\n", d[0], d[1], d[2]); } @@ -937,22 +937,22 @@ UpdatePhysicalInput () { switch (event.type) { - case SDL_QUIT: - CloseGame (); - puts ("Quit"); - break; - case SDL_FCEU_HOTKEY_EVENT: - switch (event.user.code) - { - case HK_PAUSE: - TogglePause (); - break; - default: - FCEU_printf ("Warning: unknown hotkey event %d\n", - event.user.code); - } - default: + case SDL_QUIT: + CloseGame (); + puts ("Quit"); + break; + case SDL_FCEU_HOTKEY_EVENT: + switch (event.user.code) + { + case HK_PAUSE: + TogglePause (); break; + default: + FCEU_printf ("Warning: unknown hotkey event %d\n", + event.user.code); + } + default: + break; } } //SDL_PumpEvents(); @@ -1007,11 +1007,11 @@ int ButtonConfigBegin () char SDL_windowhack[128]; if (gtk_widget_get_window (evbox)) sprintf (SDL_windowhack, "SDL_WINDOWID=%u", - (unsigned int) GDK_WINDOW_XID (gtk_widget_get_window (evbox))); + (unsigned int) GDK_WINDOW_XID (gtk_widget_get_window (evbox))); #if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL2 + // TODO - SDL2 #else - SDL_putenv (SDL_windowhack); + SDL_putenv (SDL_windowhack); #endif } #endif @@ -1048,7 +1048,7 @@ ButtonConfigEnd () { // shutdown the joystick and video subsystems KillJoysticks (); - //SDL_QuitSubSystem(SDL_INIT_VIDEO); + //SDL_QuitSubSystem(SDL_INIT_VIDEO); // re-initialize joystick and video subsystems if they were active before /*if(!bcpv) { @@ -1089,8 +1089,17 @@ DTestButton (ButtConfig * bc) return 1; } } - } - return 0; +#if SDL_VERSION_ATLEAST(2, 0, 0) + else if( bc->ButtType[x] == BUTTC_GAMECONTROLLER ) + { + if( DTestButtonGC(bc) ) + { + return 1; + } + } +#endif + } + return 0; } @@ -1099,15 +1108,32 @@ DTestButton (ButtConfig * bc) #define MKZ() {{0},{0},{0},0} #define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} +#define MGC(x) {{BUTTC_GAMECONTROLLER}, {0}, {x},1} +#define MGZ() {{0},{0},{0},SDL_CONTROLLER_BUTTON_INVALID} + ButtConfig GamePadConfig[4][10] = { #if SDL_VERSION_ATLEAST(2, 0, 0) -/* Gamepad 1 */ - {MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER), - MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()}, + /* Gamepad 1 */ + { + // 'B' button -- using 'x' as 'B' works out well for XBox controller for + // which SDL2 buttons seem to be named. This is 'square' on PS3. + MGC (SDL_CONTROLLER_BUTTON_A), + // 'A' button 360 'A' button, PS3 'X' button. + MGC (SDL_CONTROLLER_BUTTON_X), + MGC (SDL_CONTROLLER_BUTTON_BACK), // Select = SDL "BACK" at least for PS3. + MGC (SDL_CONTROLLER_BUTTON_START), // START seem to be fairly universal. + MGC (SDL_CONTROLLER_BUTTON_DPAD_UP), + MGC (SDL_CONTROLLER_BUTTON_DPAD_DOWN), + MGC (SDL_CONTROLLER_BUTTON_DPAD_LEFT), + MGC (SDL_CONTROLLER_BUTTON_DPAD_RIGHT), + MGZ (), + MGZ () + }, #else /* Gamepad 1 */ - {MK (KP3), MK (KP2), MK (SLASH), MK (ENTER), - MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()}, + { MK (KP3), MK (KP2), MK (SLASH), MK (ENTER), + MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ () + }, #endif /* Gamepad 2 */ @@ -1130,7 +1156,7 @@ UpdateGamepad(void) if (FCEUMOV_Mode (MOVIEMODE_PLAY)) { return; - } + } static int rapid = 0; uint32 JS = 0; @@ -1155,32 +1181,32 @@ UpdateGamepad(void) if(opposite_dirs == 0) { // test for left+right and up+down - if(x == 4){ + if(x == 4) { up = true; - } - if((x == 5) && (up == true)){ + } + if((x == 5) && (up == true)) { continue; - } - if(x == 6){ + } + if(x == 6) { left = true; - } - if((x == 7) && (left == true)){ + } + if((x == 7) && (left == true)) { continue; - } + } } JS |= (1 << x) << (wg << 3); } } - int four_button_exit; - g_config->getOption("SDL.ABStartSelectExit", &four_button_exit); - // if a+b+start+select is pressed, exit - if (four_button_exit && JS == 15) { - FCEUI_printf("all buttons pressed, exiting\n"); - CloseGame(); - FCEUI_Kill(); - exit(0); - } + int four_button_exit; + g_config->getOption("SDL.ABStartSelectExit", &four_button_exit); + // if a+b+start+select is pressed, exit + if (four_button_exit && JS == 15) { + FCEUI_printf("all buttons pressed, exiting\n"); + CloseGame(); + FCEUI_Kill(); + exit(0); + } // rapid-fire a, rapid-fire b if (rapid) @@ -1210,12 +1236,14 @@ static ButtConfig powerpadsc[2][12] = { MK (O), MK (P), MK (BRACKET_LEFT), MK (BRACKET_RIGHT), MK (K), MK (L), MK (SEMICOLON), MK (APOSTROPHE), - MK (M), MK (COMMA), MK (PERIOD), MK (SLASH)}, + MK (M), MK (COMMA), MK (PERIOD), MK (SLASH) + }, { MK (O), MK (P), MK (BRACKET_LEFT), MK (BRACKET_RIGHT), MK (K), MK (L), MK (SEMICOLON), MK (APOSTROPHE), - MK (M), MK (COMMA), MK (PERIOD), MK (SLASH)} + MK (M), MK (COMMA), MK (PERIOD), MK (SLASH) + } }; static uint32 powerpadbuf[2] = { 0, 0 }; @@ -1267,55 +1295,55 @@ void FCEUD_UpdateInput () { switch (CurInputType[x]) { - case SI_GAMEPAD: - t |= 1; - break; - case SI_ARKANOID: - t |= 2; - break; - case SI_ZAPPER: - t |= 2; - break; - case SI_POWERPADA: - case SI_POWERPADB: - powerpadbuf[x] = UpdatePPadData (x); - break; + case SI_GAMEPAD: + t |= 1; + break; + case SI_ARKANOID: + t |= 2; + break; + case SI_ZAPPER: + t |= 2; + break; + case SI_POWERPADA: + case SI_POWERPADB: + powerpadbuf[x] = UpdatePPadData (x); + break; } } switch (CurInputType[2]) { - case SIFC_ARKANOID: - t |= 2; - break; - case SIFC_SHADOW: - t |= 2; - break; - case SIFC_FKB: - if (g_fkbEnabled) - { - UpdateFKB (); - } - break; - case SIFC_HYPERSHOT: - UpdateHyperShot (); - break; - case SIFC_MAHJONG: - UpdateMahjong (); - break; - case SIFC_QUIZKING: - UpdateQuizKing (); - break; - case SIFC_FTRAINERB: - case SIFC_FTRAINERA: - UpdateFTrainer (); - break; - case SIFC_TOPRIDER: - UpdateTopRider (); - break; - case SIFC_OEKAKIDS: - t |= 2; - break; + case SIFC_ARKANOID: + t |= 2; + break; + case SIFC_SHADOW: + t |= 2; + break; + case SIFC_FKB: + if (g_fkbEnabled) + { + UpdateFKB (); + } + break; + case SIFC_HYPERSHOT: + UpdateHyperShot (); + break; + case SIFC_MAHJONG: + UpdateMahjong (); + break; + case SIFC_QUIZKING: + UpdateQuizKing (); + break; + case SIFC_FTRAINERB: + case SIFC_FTRAINERA: + UpdateFTrainer (); + break; + case SIFC_TOPRIDER: + UpdateTopRider (); + break; + case SIFC_OEKAKIDS: + t |= 2; + break; } if (t & 1) @@ -1330,18 +1358,18 @@ void FCEUD_UpdateInput () } void FCEUD_SetInput (bool fourscore, bool microphone, ESI port0, ESI port1, - ESIFC fcexp) + ESIFC fcexp) { eoptions &= ~EO_FOURSCORE; if (fourscore) - { // Four Score emulation, only support gamepads, nothing else + { // Four Score emulation, only support gamepads, nothing else eoptions |= EO_FOURSCORE; CurInputType[0] = SI_GAMEPAD; // Controllers 1 and 3 CurInputType[1] = SI_GAMEPAD; // Controllers 2 and 4 CurInputType[2] = SIFC_NONE; // No extension } else - { + { // no Four Core emulation, check the config/movie file for controller types CurInputType[0] = port0; CurInputType[1] = port1; @@ -1371,22 +1399,22 @@ void InitInputInterface () switch (CurInputType[x]) { - case SI_POWERPADA: - case SI_POWERPADB: - InputDPtr = &powerpadbuf[x]; - break; - case SI_GAMEPAD: - InputDPtr = &JSreturn; - break; - case SI_ARKANOID: - InputDPtr = MouseData; - t |= 1; - break; - case SI_ZAPPER: - InputDPtr = MouseData; - t |= 1; - attrib = 1; - break; + case SI_POWERPADA: + case SI_POWERPADB: + InputDPtr = &powerpadbuf[x]; + break; + case SI_GAMEPAD: + InputDPtr = &JSreturn; + break; + case SI_ARKANOID: + InputDPtr = MouseData; + t |= 1; + break; + case SI_ZAPPER: + InputDPtr = MouseData; + t |= 1; + attrib = 1; + break; } FCEUI_SetInput (x, (ESI) CurInputType[x], InputDPtr, attrib); } @@ -1395,42 +1423,42 @@ void InitInputInterface () InputDPtr = 0; switch (CurInputType[2]) { - case SIFC_SHADOW: - InputDPtr = MouseData; - t |= 1; - attrib = 1; - break; - case SIFC_OEKAKIDS: - InputDPtr = MouseData; - t |= 1; - attrib = 1; - break; - case SIFC_ARKANOID: - InputDPtr = MouseData; - t |= 1; - break; - case SIFC_FKB: - InputDPtr = fkbkeys; - break; - case SIFC_HYPERSHOT: - InputDPtr = &HyperShotData; - break; - case SIFC_MAHJONG: - InputDPtr = &MahjongData; - break; - case SIFC_QUIZKING: - InputDPtr = &QuizKingData; - break; - case SIFC_TOPRIDER: - InputDPtr = &TopRiderData; - break; - case SIFC_BWORLD: - InputDPtr = BWorldData; - break; - case SIFC_FTRAINERA: - case SIFC_FTRAINERB: - InputDPtr = &FTrainerData; - break; + case SIFC_SHADOW: + InputDPtr = MouseData; + t |= 1; + attrib = 1; + break; + case SIFC_OEKAKIDS: + InputDPtr = MouseData; + t |= 1; + attrib = 1; + break; + case SIFC_ARKANOID: + InputDPtr = MouseData; + t |= 1; + break; + case SIFC_FKB: + InputDPtr = fkbkeys; + break; + case SIFC_HYPERSHOT: + InputDPtr = &HyperShotData; + break; + case SIFC_MAHJONG: + InputDPtr = &MahjongData; + break; + case SIFC_QUIZKING: + InputDPtr = &QuizKingData; + break; + case SIFC_TOPRIDER: + InputDPtr = &TopRiderData; + break; + case SIFC_BWORLD: + InputDPtr = BWorldData; + break; + case SIFC_FTRAINERA: + case SIFC_FTRAINERB: + InputDPtr = &FTrainerData; + break; } FCEUI_SetInputFC ((ESIFC) CurInputType[2], InputDPtr, attrib); @@ -1482,7 +1510,7 @@ static ButtConfig HyperShotButtons[4] = { /** * Update the status of the HyperShot input device. */ - static void +static void UpdateHyperShot () { int x; @@ -1506,7 +1534,7 @@ static ButtConfig MahjongButtons[21] = { /** * Update the status of for the Mahjong input device. */ - static void +static void UpdateMahjong () { int x; @@ -1528,7 +1556,7 @@ static ButtConfig QuizKingButtons[6] = { /** * Update the status of the QuizKing input device. */ - static void +static void UpdateQuizKing () { int x; @@ -1551,7 +1579,7 @@ static ButtConfig TopRiderButtons[8] = { /** * Update the status of the TopRider input device. */ - static void +static void UpdateTopRider () { int x; @@ -1575,7 +1603,7 @@ static ButtConfig FTrainerButtons[12] = { /** * Update the status of the FTrainer input device. */ - static void +static void UpdateFTrainer () { int x; @@ -1591,7 +1619,7 @@ UpdateFTrainer () } /** - * Get the display name of the key or joystick button mapped to a specific + * Get the display name of the key or joystick button mapped to a specific * NES gamepad button. * @param bc the NES gamepad's button config * @param which the index of the button @@ -1602,53 +1630,53 @@ const char * ButtonName (const ButtConfig * bc, int which) switch (bc->ButtType[which]) { - case BUTTC_KEYBOARD: + case BUTTC_KEYBOARD: #if SDL_VERSION_ATLEAST(2,0,0) - return SDL_GetKeyName (bc->ButtonNum[which]); + return SDL_GetKeyName (bc->ButtonNum[which]); #else - return SDL_GetKeyName ((SDLKey) bc->ButtonNum[which]); + return SDL_GetKeyName ((SDLKey) bc->ButtonNum[which]); #endif - case BUTTC_JOYSTICK: - int joyNum, inputNum; - const char *inputType, *inputDirection; + case BUTTC_JOYSTICK: + int joyNum, inputNum; + const char *inputType, *inputDirection; - joyNum = bc->DeviceNum[which]; + joyNum = bc->DeviceNum[which]; - if (bc->ButtonNum[which] & 0x8000) - { - inputType = "Axis"; - inputNum = bc->ButtonNum[which] & 0x3FFF; - inputDirection = bc->ButtonNum[which] & 0x4000 ? "-" : "+"; - } - else if (bc->ButtonNum[which] & 0x2000) - { - int inputValue; - char direction[128] = ""; + if (bc->ButtonNum[which] & 0x8000) + { + inputType = "Axis"; + inputNum = bc->ButtonNum[which] & 0x3FFF; + inputDirection = bc->ButtonNum[which] & 0x4000 ? "-" : "+"; + } + else if (bc->ButtonNum[which] & 0x2000) + { + int inputValue; + char direction[128] = ""; - inputType = "Hat"; - inputNum = (bc->ButtonNum[which] >> 8) & 0x1F; - inputValue = bc->ButtonNum[which] & 0xF; + inputType = "Hat"; + inputNum = (bc->ButtonNum[which] >> 8) & 0x1F; + inputValue = bc->ButtonNum[which] & 0xF; - if (inputValue & SDL_HAT_UP) - strncat (direction, "Up ", sizeof (direction)); - if (inputValue & SDL_HAT_DOWN) - strncat (direction, "Down ", sizeof (direction)); - if (inputValue & SDL_HAT_LEFT) - strncat (direction, "Left ", sizeof (direction)); - if (inputValue & SDL_HAT_RIGHT) - strncat (direction, "Right ", sizeof (direction)); + if (inputValue & SDL_HAT_UP) + strncat (direction, "Up ", sizeof (direction)); + if (inputValue & SDL_HAT_DOWN) + strncat (direction, "Down ", sizeof (direction)); + if (inputValue & SDL_HAT_LEFT) + strncat (direction, "Left ", sizeof (direction)); + if (inputValue & SDL_HAT_RIGHT) + strncat (direction, "Right ", sizeof (direction)); - if (direction[0]) - inputDirection = direction; - else - inputDirection = "Center"; - } + if (direction[0]) + inputDirection = direction; else - { - inputType = "Button"; - inputNum = bc->ButtonNum[which]; - inputDirection = ""; - } + inputDirection = "Center"; + } + else + { + inputType = "Button"; + inputNum = bc->ButtonNum[which]; + inputDirection = ""; + } } return name; @@ -1696,58 +1724,58 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb) done++; switch (event.type) { - case SDL_KEYDOWN: - bc->ButtType[wb] = BUTTC_KEYBOARD; - bc->DeviceNum[wb] = 0; - bc->ButtonNum[wb] = event.key.keysym.sym; - return (1); - case SDL_JOYBUTTONDOWN: + case SDL_KEYDOWN: + bc->ButtType[wb] = BUTTC_KEYBOARD; + bc->DeviceNum[wb] = 0; + bc->ButtonNum[wb] = event.key.keysym.sym; + return (1); + case SDL_JOYBUTTONDOWN: + bc->ButtType[wb] = BUTTC_JOYSTICK; + bc->DeviceNum[wb] = event.jbutton.which; + bc->ButtonNum[wb] = event.jbutton.button; + return (1); + case SDL_JOYHATMOTION: + if (event.jhat.value == SDL_HAT_CENTERED) + done--; + else + { bc->ButtType[wb] = BUTTC_JOYSTICK; - bc->DeviceNum[wb] = event.jbutton.which; - bc->ButtonNum[wb] = event.jbutton.button; + bc->DeviceNum[wb] = event.jhat.which; + bc->ButtonNum[wb] = + (0x2000 | ((event.jhat.hat & 0x1F) << 8) | event. + jhat.value); return (1); - case SDL_JOYHATMOTION: - if (event.jhat.value == SDL_HAT_CENTERED) - done--; - else + } + break; + case SDL_JOYAXISMOTION: + if (LastAx[event.jaxis.which][event.jaxis.axis] == 0x100000) + { + if (abs (event.jaxis.value) < 1000) + { + LastAx[event.jaxis.which][event.jaxis.axis] = + event.jaxis.value; + } + done--; + } + else + { + if (abs + (LastAx[event.jaxis.which][event.jaxis.axis] - + event.jaxis.value) >= 8192) { bc->ButtType[wb] = BUTTC_JOYSTICK; - bc->DeviceNum[wb] = event.jhat.which; - bc->ButtonNum[wb] = - (0x2000 | ((event.jhat.hat & 0x1F) << 8) | event. - jhat.value); + bc->DeviceNum[wb] = event.jaxis.which; + bc->ButtonNum[wb] = (0x8000 | event.jaxis.axis | + ((event.jaxis.value < 0) + ? 0x4000 : 0)); return (1); } - break; - case SDL_JOYAXISMOTION: - if (LastAx[event.jaxis.which][event.jaxis.axis] == 0x100000) - { - if (abs (event.jaxis.value) < 1000) - { - LastAx[event.jaxis.which][event.jaxis.axis] = - event.jaxis.value; - } - done--; - } else - { - if (abs - (LastAx[event.jaxis.which][event.jaxis.axis] - - event.jaxis.value) >= 8192) - { - bc->ButtType[wb] = BUTTC_JOYSTICK; - bc->DeviceNum[wb] = event.jaxis.which; - bc->ButtonNum[wb] = (0x8000 | event.jaxis.axis | - ((event.jaxis.value < 0) - ? 0x4000 : 0)); - return (1); - } - else - done--; - } - break; - default: - done--; + done--; + } + break; + default: + done--; } } if (done) @@ -1764,7 +1792,7 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb) * used as input for the specified button, thus allowing up to four * possible settings for each input button. */ - void +void ConfigButton (char *text, ButtConfig * bc) { uint8 buf[256]; @@ -1776,9 +1804,9 @@ ConfigButton (char *text, ButtConfig * bc) DWaitButton (buf, bc, wc); if (wc && - bc->ButtType[wc] == bc->ButtType[wc - 1] && - bc->DeviceNum[wc] == bc->DeviceNum[wc - 1] && - bc->ButtonNum[wc] == bc->ButtonNum[wc - 1]) + bc->ButtType[wc] == bc->ButtType[wc - 1] && + bc->DeviceNum[wc] == bc->DeviceNum[wc - 1] && + bc->ButtonNum[wc] == bc->ButtonNum[wc - 1]) { break; } @@ -1797,7 +1825,7 @@ void ConfigDevice (int which, int arg) int x; std::string prefix; char *str[10] = - { "A", "B", "SELECT", "START", "UP", "DOWN", "LEFT", "RIGHT", "Rapid A", + { "A", "B", "SELECT", "START", "UP", "DOWN", "LEFT", "RIGHT", "Rapid A", "Rapid B" }; @@ -1808,114 +1836,114 @@ void ConfigDevice (int which, int arg) ButtonConfigBegin (); switch (which) { - case FCFGD_QUIZKING: - prefix = "SDL.Input.QuizKing."; - for (x = 0; x < 6; x++) - { - sprintf (buf, "Quiz King Buzzer #%d", x + 1); - ConfigButton (buf, &QuizKingButtons[x]); + case FCFGD_QUIZKING: + prefix = "SDL.Input.QuizKing."; + for (x = 0; x < 6; x++) + { + sprintf (buf, "Quiz King Buzzer #%d", x + 1); + ConfigButton (buf, &QuizKingButtons[x]); - g_config->setOption (prefix + QuizKingNames[x], - QuizKingButtons[x].ButtonNum[0]); - } + g_config->setOption (prefix + QuizKingNames[x], + QuizKingButtons[x].ButtonNum[0]); + } - if (QuizKingButtons[0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (QuizKingButtons[0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - QuizKingButtons[0].DeviceNum[0]); - break; - case FCFGD_HYPERSHOT: - prefix = "SDL.Input.HyperShot."; - for (x = 0; x < 4; x++) - { - sprintf (buf, "Hyper Shot %d: %s", - ((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN"); - ConfigButton (buf, &HyperShotButtons[x]); + if (QuizKingButtons[0].ButtType[0] == BUTTC_KEYBOARD) + { + g_config->setOption (prefix + "DeviceType", "Keyboard"); + } + else if (QuizKingButtons[0].ButtType[0] == BUTTC_JOYSTICK) + { + g_config->setOption (prefix + "DeviceType", "Joystick"); + } + else + { + g_config->setOption (prefix + "DeviceType", "Unknown"); + } + g_config->setOption (prefix + "DeviceNum", + QuizKingButtons[0].DeviceNum[0]); + break; + case FCFGD_HYPERSHOT: + prefix = "SDL.Input.HyperShot."; + for (x = 0; x < 4; x++) + { + sprintf (buf, "Hyper Shot %d: %s", + ((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN"); + ConfigButton (buf, &HyperShotButtons[x]); - g_config->setOption (prefix + HyperShotNames[x], - HyperShotButtons[x].ButtonNum[0]); - } + g_config->setOption (prefix + HyperShotNames[x], + HyperShotButtons[x].ButtonNum[0]); + } - if (HyperShotButtons[0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (HyperShotButtons[0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - HyperShotButtons[0].DeviceNum[0]); - break; - case FCFGD_POWERPAD: - snprintf (buf, 256, "SDL.Input.PowerPad.%d", (arg & 1)); - prefix = buf; - for (x = 0; x < 12; x++) - { - sprintf (buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11); - ConfigButton (buf, &powerpadsc[arg & 1][x]); + if (HyperShotButtons[0].ButtType[0] == BUTTC_KEYBOARD) + { + g_config->setOption (prefix + "DeviceType", "Keyboard"); + } + else if (HyperShotButtons[0].ButtType[0] == BUTTC_JOYSTICK) + { + g_config->setOption (prefix + "DeviceType", "Joystick"); + } + else + { + g_config->setOption (prefix + "DeviceType", "Unknown"); + } + g_config->setOption (prefix + "DeviceNum", + HyperShotButtons[0].DeviceNum[0]); + break; + case FCFGD_POWERPAD: + snprintf (buf, 256, "SDL.Input.PowerPad.%d", (arg & 1)); + prefix = buf; + for (x = 0; x < 12; x++) + { + sprintf (buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11); + ConfigButton (buf, &powerpadsc[arg & 1][x]); - g_config->setOption (prefix + PowerPadNames[x], - powerpadsc[arg & 1][x].ButtonNum[0]); - } + g_config->setOption (prefix + PowerPadNames[x], + powerpadsc[arg & 1][x].ButtonNum[0]); + } - if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - powerpadsc[arg & 1][0].DeviceNum[0]); - break; + if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_KEYBOARD) + { + g_config->setOption (prefix + "DeviceType", "Keyboard"); + } + else if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_JOYSTICK) + { + g_config->setOption (prefix + "DeviceType", "Joystick"); + } + else + { + g_config->setOption (prefix + "DeviceType", "Unknown"); + } + g_config->setOption (prefix + "DeviceNum", + powerpadsc[arg & 1][0].DeviceNum[0]); + break; - case FCFGD_GAMEPAD: - snprintf (buf, 256, "SDL.Input.GamePad.%d", arg); - prefix = buf; - for (x = 0; x < 10; x++) - { - sprintf (buf, "GamePad #%d: %s", arg + 1, str[x]); - ConfigButton (buf, &GamePadConfig[arg][x]); + case FCFGD_GAMEPAD: + snprintf (buf, 256, "SDL.Input.GamePad.%d", arg); + prefix = buf; + for (x = 0; x < 10; x++) + { + sprintf (buf, "GamePad #%d: %s", arg + 1, str[x]); + ConfigButton (buf, &GamePadConfig[arg][x]); - g_config->setOption (prefix + GamePadNames[x], - GamePadConfig[arg][x].ButtonNum[0]); - } + g_config->setOption (prefix + GamePadNames[x], + GamePadConfig[arg][x].ButtonNum[0]); + } - if (GamePadConfig[arg][0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (GamePadConfig[arg][0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - GamePadConfig[arg][0].DeviceNum[0]); - break; + if (GamePadConfig[arg][0].ButtType[0] == BUTTC_KEYBOARD) + { + g_config->setOption (prefix + "DeviceType", "Keyboard"); + } + else if (GamePadConfig[arg][0].ButtType[0] == BUTTC_JOYSTICK) + { + g_config->setOption (prefix + "DeviceType", "Joystick"); + } + else + { + g_config->setOption (prefix + "DeviceType", "Unknown"); + } + g_config->setOption (prefix + "DeviceNum", + GamePadConfig[arg][0].DeviceNum[0]); + break; } ButtonConfigEnd (); @@ -1942,7 +1970,7 @@ void InputCfg (const std::string & text) if (device < 0 || device > 3) { FCEUD_PrintError - ("Invalid gamepad device specified; must be one of gamepad1 through gamepad4"); + ("Invalid gamepad device specified; must be one of gamepad1 through gamepad4"); exit (-1); } ConfigDevice (FCFGD_GAMEPAD, device); @@ -1953,7 +1981,7 @@ void InputCfg (const std::string & text) if (device < 0 || device > 1) { FCEUD_PrintError - ("Invalid powerpad device specified; must be powerpad1 or powerpad2"); + ("Invalid powerpad device specified; must be powerpad1 or powerpad2"); exit (-1); } ConfigDevice (FCFGD_POWERPAD, device); @@ -1978,7 +2006,7 @@ void InputCfg (const std::string & text) * configuration management. Will probably want to change this in the * future - soules. */ - void +void UpdateInput (Config * config) { char buf[64]; @@ -2084,6 +2112,10 @@ UpdateInput (Config * config) { type = BUTTC_JOYSTICK; } + else if (device.find ("GameController") != std::string::npos) + { + type = BUTTC_GAMECONTROLLER; + } else { type = 0; @@ -2294,17 +2326,39 @@ UpdateInput (Config * config) // Definitions from main.h: // GamePad defaults const char *GamePadNames[GAMEPAD_NUM_BUTTONS] = { "A", "B", "Select", "Start", - "Up", "Down", "Left", "Right", "TurboA", "TurboB" + "Up", "Down", "Left", "Right", "TurboA", "TurboB" + }; +#if SDL_VERSION_ATLEAST(2, 0, 0) +const char *DefaultGamePadDevice[GAMEPAD_NUM_DEVICES] = +{ "GameController", "None", "None", "None" }; +const int DefaultGamePad[GAMEPAD_NUM_DEVICES][GAMEPAD_NUM_BUTTONS] = +{ { SDL_CONTROLLER_BUTTON_A, + SDL_CONTROLLER_BUTTON_X, + SDL_CONTROLLER_BUTTON_BACK, + SDL_CONTROLLER_BUTTON_START, + SDL_CONTROLLER_BUTTON_DPAD_UP, + SDL_CONTROLLER_BUTTON_DPAD_DOWN, + SDL_CONTROLLER_BUTTON_DPAD_LEFT, + SDL_CONTROLLER_BUTTON_DPAD_RIGHT, + SDL_CONTROLLER_BUTTON_INVALID, + SDL_CONTROLLER_BUTTON_INVALID + }, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; +#else const char *DefaultGamePadDevice[GAMEPAD_NUM_DEVICES] = { "Keyboard", "None", "None", "None" }; const int DefaultGamePad[GAMEPAD_NUM_DEVICES][GAMEPAD_NUM_BUTTONS] = -{ {SDLK_F, SDLK_D, SDLK_S, SDLK_RETURN, - SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, 0, 0}, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +{ { SDLK_F, SDLK_D, SDLK_S, SDLK_RETURN, + SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, 0, 0 + }, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; +#endif // PowerPad defaults const char *PowerPadNames[POWERPAD_NUM_BUTTONS] = @@ -2312,10 +2366,11 @@ const char *PowerPadNames[POWERPAD_NUM_BUTTONS] = const char *DefaultPowerPadDevice[POWERPAD_NUM_DEVICES] = { "Keyboard", "None" }; const int DefaultPowerPad[POWERPAD_NUM_DEVICES][POWERPAD_NUM_BUTTONS] = -{ {SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET, - SDLK_k, SDLK_l, SDLK_SEMICOLON, SDLK_QUOTE, - SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH}, -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +{ { SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET, + SDLK_k, SDLK_l, SDLK_SEMICOLON, SDLK_QUOTE, + SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH + }, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; // QuizKing defaults @@ -2334,14 +2389,14 @@ const int DefaultHyperShot[HYPERSHOT_NUM_BUTTONS] = // Mahjong defaults const char *MahjongNames[MAHJONG_NUM_BUTTONS] = -{ "00", "01", "02", "03", "04", "05", "06", "07", +{ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20" }; const char *DefaultMahjongDevice = "Keyboard"; const int DefaultMahjong[MAHJONG_NUM_BUTTONS] = -{ SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_a, SDLK_s, SDLK_d, +{ SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_a, SDLK_s, SDLK_d, SDLK_f, SDLK_g, SDLK_h, SDLK_j, SDLK_k, SDLK_l, SDLK_z, SDLK_x, SDLK_c, SDLK_v, SDLK_b, SDLK_n, SDLK_m }; @@ -2358,14 +2413,14 @@ const char *FTrainerNames[FTRAINER_NUM_BUTTONS] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B" }; const char *DefaultFTrainerDevice = "Keyboard"; const int DefaultFTrainer[FTRAINER_NUM_BUTTONS] = -{ SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET, +{ SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET, SDLK_k, SDLK_l, SDLK_SEMICOLON, SDLK_QUOTE, SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH }; // FamilyKeyBoard defaults const char *FamilyKeyBoardNames[FAMILYKEYBOARD_NUM_BUTTONS] = -{ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", +{ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "MINUS", "EQUAL", "BACKSLASH", "BACKSPACE", "ESCAPE", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", @@ -2380,7 +2435,7 @@ const char *FamilyKeyBoardNames[FAMILYKEYBOARD_NUM_BUTTONS] = const char *DefaultFamilyKeyBoardDevice = "Keyboard"; const int DefaultFamilyKeyBoard[FAMILYKEYBOARD_NUM_BUTTONS] = -{ SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F8, +{ SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F8, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6, SDLK_7, SDLK_8, SDLK_9, SDLK_0, SDLK_MINUS, SDLK_EQUALS, SDLK_BACKSLASH, SDLK_BACKSPACE, diff --git a/branches/sdl2/src/drivers/sdl/input.h b/branches/sdl2/src/drivers/sdl/input.h index bd3d4994..7f391e88 100644 --- a/branches/sdl2/src/drivers/sdl/input.h +++ b/branches/sdl2/src/drivers/sdl/input.h @@ -27,6 +27,7 @@ int DWaitButton(const uint8 *text, ButtConfig *bc, int wb); #define BUTTC_KEYBOARD 0x00 #define BUTTC_JOYSTICK 0x01 #define BUTTC_MOUSE 0x02 +#define BUTTC_GAMECONTROLLER 0x03 #define FCFGD_GAMEPAD 1 #define FCFGD_POWERPAD 2 @@ -48,6 +49,7 @@ void IncreaseEmulationSpeed(void); void DecreaseEmulationSpeed(void); int DTestButtonJoy(ButtConfig *bc); +int DTestButtonGC(ButtConfig *bc); void FCEUD_UpdateInput(void); diff --git a/branches/sdl2/src/drivers/sdl/sdl-gamectrl.cpp b/branches/sdl2/src/drivers/sdl/sdl-gamectrl.cpp new file mode 100644 index 00000000..df9650a3 --- /dev/null +++ b/branches/sdl2/src/drivers/sdl/sdl-gamectrl.cpp @@ -0,0 +1,125 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2002 Paul Kuliniewicz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/// \file +/// \brief Handles GameController input using the SDL. This is an SDL2-only feature + +#include "sdl.h" + +/* This entire file is SDL2 only. GameController API is new as of SDL2 */ +#if SDL_VERSION_ATLEAST(2, 0, 0) + +#include +#include +#include +#include + +#define MAX_GAMECONTROLLERS 32 +static SDL_GameController *s_GameCtrls[MAX_GAMECONTROLLERS] = {NULL}; + +static int s_gcinited = 0; + + +/** + * Tests if the given button is active on the joystick. + */ +int +DTestButtonGC(ButtConfig *bc) +{ + int x; + //printf("DTestButtonGC\n"); + SDL_GameController *gc; + + for(x = 0; x < bc->NumC; x++) + { + gc = s_GameCtrls[bc->DeviceNum[x]]; + if( SDL_GameControllerGetButton(gc, (SDL_GameControllerButton) bc->ButtonNum[x]) ) + { + //printf("GC %d btn '%s'=down\n", bc->DeviceNum[x], + // SDL_GameControllerGetStringForButton( (SDL_GameControllerButton) bc->ButtonNum[x])); + return 1; + } + } + return 0; +} + +/** + * Shutdown the SDL joystick subsystem. + */ +int +KillGameControllers() +{ + int n; /* joystick index */ + + if(!s_gcinited) { + return -1; + } + + for(n = 0; n < MAX_GAMECONTROLLERS; n++) { + if (s_GameCtrls[n]) { + SDL_GameControllerClose(s_GameCtrls[n]); + } + s_GameCtrls[n]=0; + } + SDL_QuitSubSystem(MAX_GAMECONTROLLERS); + return 0; +} + +/** + * Initialize the SDL Game-Controller subsystem. + */ +int +InitGameControllers() +{ + int n; /* joystick index */ + int total; + + + SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); + + // Game Controller API wraps joystick API, so the number of joysticks is also + // the number of game controllers. For some reason SDL2 decided to leave + // this as one API + total = SDL_NumJoysticks(); + if(total>MAX_GAMECONTROLLERS) { + total = MAX_GAMECONTROLLERS; + } + + for(n = 0; n < total; n++) { + // Detect if a JoyStick is a game-controller, and if so, open it. + if( SDL_IsGameController(n) ) { + s_GameCtrls[n] = SDL_GameControllerOpen(n); + if( ! s_GameCtrls[n] ) { + printf("Could not open gamecontroller %d: %s.\n", + n - 1, SDL_GetError()); + } + else { + printf("Opening Game Controller %d, name=%s\n", n, SDL_GameControllerName(s_GameCtrls[n])); + } + } + } + + s_gcinited = 1; + return 1; +} + +#endif //#if SDL_VERSION_ATLEAST(2, 0, 0) + diff --git a/branches/sdl2/src/drivers/sdl/sdl-sound.cpp b/branches/sdl2/src/drivers/sdl/sdl-sound.cpp index 55ef7679..35424b96 100644 --- a/branches/sdl2/src/drivers/sdl/sdl-sound.cpp +++ b/branches/sdl2/src/drivers/sdl/sdl-sound.cpp @@ -46,9 +46,12 @@ static int s_mute = 0; */ static void fillaudio(void *udata, - uint8 *stream, - int len) + uint8 *stream, + int len) { +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_memset(stream, 0, len); +#endif int16 *tmps = (int16*)stream; len >>= 1; while(len) { @@ -117,7 +120,7 @@ InitSound() // For safety, set a bare minimum: if (s_BufferSize < spec.samples * 2) - s_BufferSize = spec.samples * 2; + s_BufferSize = spec.samples * 2; s_Buffer = (int *)FCEU_dmalloc(sizeof(int) * s_BufferSize); if (!s_Buffer) @@ -129,7 +132,7 @@ InitSound() puts(SDL_GetError()); KillSound(); return 0; - } + } SDL_PauseAudio(0); FCEUI_SetSoundVolume(soundvolume); @@ -173,7 +176,7 @@ WriteSound(int32 *buf, if (EmulationPaused == 0) while(Count) { - while(s_BufferIn == s_BufferSize) + while(s_BufferIn == s_BufferSize) { SDL_Delay(1); } @@ -181,11 +184,11 @@ WriteSound(int32 *buf, s_Buffer[s_BufferWrite] = *buf; Count--; s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize; - + SDL_LockAudio(); s_BufferIn++; SDL_UnlockAudio(); - + buf++; } } @@ -195,8 +198,8 @@ WriteSound(int32 *buf, */ void SilenceSound(int n) -{ - SDL_PauseAudio(n); +{ + SDL_PauseAudio(n); } /** diff --git a/branches/sdl2/src/drivers/sdl/sdl-video.cpp b/branches/sdl2/src/drivers/sdl/sdl-video.cpp index 88aacd3f..158a33b1 100644 --- a/branches/sdl2/src/drivers/sdl/sdl-video.cpp +++ b/branches/sdl2/src/drivers/sdl/sdl-video.cpp @@ -52,11 +52,19 @@ // GLOBALS extern Config *g_config; +#if SDL_VERSION_ATLEAST(2, 0, 0) +static SDL_Window * s_window; +static SDL_Renderer * s_renderer; +extern SDL_Surface * s_screen; // TODO - where else is this accessed? +static SDL_Texture * s_texture; +static SDL_Surface * s_IconSurface = NULL; +#else // STATIC GLOBALS extern SDL_Surface *s_screen; static SDL_Surface *s_BlitBuf; // Buffer when using hardware-accelerated blits. static SDL_Surface *s_IconSurface = NULL; +#endif static int s_curbpp; static int s_srendline, s_erendline; @@ -71,8 +79,11 @@ static int s_eefx; static int s_clipSides; static int s_fullscreen; static int noframe; +#if SDL_VERSION_ATLEAST(2, 0, 0) +#else static int s_nativeWidth = -1; static int s_nativeHeight = -1; +#endif #define NWIDTH (256 - (s_clipSides ? 16 : 0)) #define NOFFSET (s_clipSides ? 8 : 0) @@ -91,7 +102,8 @@ bool FCEUD_ShouldDrawInputAids() { return s_fullscreen!=0; } - + +#if SDL_VERSION_ATLEAST(2, 0, 0) int KillVideo() { @@ -104,7 +116,51 @@ KillVideo() // return failure if the video system was not initialized if(s_inited == 0) return -1; - + + // shut down the system that converts from 8 to 16/32 bpp + if(s_curbpp > 8) + KillBlitToHigh(); + + // Tear down SDL2 resources in reverse order from init + if(s_texture) { + SDL_DestroyTexture(s_texture); + s_texture = 0; + } + + if(s_screen) { + SDL_FreeSurface(s_screen); + s_screen=0; + } + + if(s_renderer) { + SDL_DestroyRenderer(s_renderer); + } + + if( s_window ) { + SDL_DestroyWindow(s_window); + s_window=0; + } + + // shut down the SDL video sub-system + SDL_QuitSubSystem(SDL_INIT_VIDEO); + + s_inited = 0; + return 0; +} +#else // SDL < 2.0 +int +KillVideo() +{ + // if the IconSurface has been initialized, destroy it + if(s_IconSurface) { + SDL_FreeSurface(s_IconSurface); + s_IconSurface=0; + } + + // return failure if the video system was not initialized + if(s_inited == 0) + return -1; + // if the rest of the system has been initialized, shut it down #ifdef OPENGL // check for OpenGL and shut it down @@ -122,6 +178,7 @@ KillVideo() s_inited = 0; return 0; } +#endif // SDL2 check // this variable contains information about the special scaling filters @@ -154,6 +211,142 @@ int InitVideo(FCEUGI *gi) // This is a big TODO. Stubbing this off into its own function, // as the SDL surface routines have changed drastically in SDL2 // TODO - SDL2 + const char * window_name; + int error, flags = 0; + int doublebuf, xstretch, ystretch, xres, yres, show_fps; + uint32_t Amask, Rmask, Gmask, Bmask; + int bpp; + + FCEUI_printf("Initializing video (SDL2.x) ..."); + + // load the relevant configuration variables + g_config->getOption("SDL.Fullscreen", &s_fullscreen); + g_config->getOption("SDL.DoubleBuffering", &doublebuf); +#ifdef OPENGL + g_config->getOption("SDL.OpenGL", &s_useOpenGL); +#endif + g_config->getOption("SDL.SpecialFilter", &s_sponge); + g_config->getOption("SDL.XStretch", &xstretch); + g_config->getOption("SDL.YStretch", &ystretch); + g_config->getOption("SDL.LastXRes", &xres); + g_config->getOption("SDL.LastYRes", &yres); + g_config->getOption("SDL.ClipSides", &s_clipSides); + g_config->getOption("SDL.NoFrame", &noframe); + g_config->getOption("SDL.ShowFPS", &show_fps); + + // check the starting, ending, and total scan lines + FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline); + s_tlines = s_erendline - s_srendline + 1; + +#if OPENGL + if( !s_useOpenGL || s_sponge ) + { + FCEUD_PrintError("SDL2 Does not support non-OpenGL rendering or special filters\n"); + KillVideo(); + return -1; + } +#endif + + // initialize the SDL video subsystem if it is not already active + if(!SDL_WasInit(SDL_INIT_VIDEO)) { + error = SDL_InitSubSystem(SDL_INIT_VIDEO); + if(error) { + FCEUD_PrintError(SDL_GetError()); + return -1; + } + } + s_inited = 1; + + // For simplicity, hard-code this to 32bpp for now... + s_curbpp = 32; + + // If game is running, set window name accordingly + if( gi ) + { + window_name = (const char *) gi->name; + } + else + { + window_name = "FCE Ultra"; + } + + s_exs = 1.0; + s_eys = 1.0; + if(s_fullscreen) { + s_window = SDL_CreateWindow( window_name, + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + 0, 0, // Res not specified in full-screen mode + SDL_WINDOW_FULLSCREEN_DESKTOP); + } else { + s_window = SDL_CreateWindow( window_name, + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + xres, yres, + 0); + } + + // This stuff all applies regardless of full-screen vs windowed mode. + s_renderer = SDL_CreateRenderer(s_window, -1, 0); + + // Set logical rendering size & specify scaling mode. All rendering is + // now done to the renderer rather than directly to the screen surface. + // The renderer takes care of any scaling necessary. + // + // NOTE: setting scale quality to "nearest" will result in a blown-up but + // pixelated while "linear" will tend to blur everything. + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); + SDL_RenderSetLogicalSize(s_renderer, xres, yres); + + + // + // Create the texture that will ultimately be rendered. + // s_screen is used to build up an image, then the texture will be updated + // all at once when it's ready + s_texture = SDL_CreateTexture(s_renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, + xres, yres); + // + // Create a surface to draw pixels onto + // + SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ARGB8888, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + s_screen = SDL_CreateRGBSurface(0, xres, yres, bpp, + Rmask, Gmask, Bmask, Amask); + + if( !s_screen ) + { + FCEUD_PrintError(SDL_GetError()); + return -1; + } + + // + // Setup Icon surface + // +#ifdef LSB_FIRST + s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, + 32, 32, 24, 32 * 3, + 0xFF, 0xFF00, 0xFF0000, 0x00); +#else + s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, + 32, 32, 24, 32 * 3, + 0xFF0000, 0xFF00, 0xFF, 0x00); +#endif + + SDL_SetWindowIcon(s_window, s_IconSurface); + + s_paletterefresh = 1; // Force palette refresh + + // always init blit to high since bpp forced to 32 for now. + InitBlitToHigh(s_curbpp >> 3, + s_screen->format->Rmask, + s_screen->format->Gmask, + s_screen->format->Bmask, + 0, //s_eefx, Hard-code SFX off + 0, //s_sponge, Hard-code special filters off. + 0); + + return 0; } #else /** @@ -191,7 +384,7 @@ InitVideo(FCEUGI *gi) // check if we should auto-set x/y resolution - // check for OpenGL and set the global flags + // check for OpenGL and set the global flags #if OPENGL if(s_useOpenGL && !s_sponge) { flags = SDL_OPENGL; @@ -216,7 +409,7 @@ InitVideo(FCEUGI *gi) if(vinf->hw_available) { flags |= SDL_HWSURFACE; } - + // get the monitor's current resolution if we do not already have it if(s_nativeWidth < 0) { s_nativeWidth = vinf->current_w; @@ -227,7 +420,7 @@ InitVideo(FCEUGI *gi) // check to see if we are showing FPS FCEUI_SetShowFPS(show_fps); - + // check if we are rendering fullscreen if(s_fullscreen) { int no_cursor; @@ -238,7 +431,7 @@ InitVideo(FCEUGI *gi) else { SDL_ShowCursor(1); } - + if(noframe) { flags |= SDL_NOFRAME; } @@ -251,7 +444,7 @@ InitVideo(FCEUGI *gi) if(s_useOpenGL) { FCEU_printf("Initializing with OpenGL (Disable with '--opengl 0').\n"); if(doublebuf) { - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); } } else #endif @@ -270,21 +463,21 @@ InitVideo(FCEUGI *gi) double native_ratio = ((double)NWIDTH) / s_tlines; double screen_ratio = ((double)xres) / yres; int keep_ratio; - + g_config->getOption("SDL.KeepRatio", &keep_ratio); - + // Try to choose resolution if (screen_ratio < native_ratio) { // The screen is narrower than the original. Maximizing width will not clip auto_xscale = auto_yscale = GetXScale(xres); - if (keep_ratio) + if (keep_ratio) auto_yscale = GetYScale(yres); } else { auto_yscale = auto_xscale = GetYScale(yres); - if (keep_ratio) + if (keep_ratio) auto_xscale = GetXScale(xres); } s_exs = auto_xscale; @@ -304,7 +497,7 @@ InitVideo(FCEUGI *gi) } else { desbpp = 0; } - + // -Video Modes Tag- if(s_sponge) { if(s_sponge == 4 || s_sponge == 5) { @@ -337,8 +530,8 @@ InitVideo(FCEUGI *gi) #ifdef OPENGL s_screen = SDL_SetVideoMode(s_useOpenGL ? s_nativeWidth : xres, - s_useOpenGL ? s_nativeHeight : yres, - desbpp, flags); + s_useOpenGL ? s_nativeHeight : yres, + desbpp, flags); #else s_screen = SDL_SetVideoMode(xres, yres, desbpp, flags); #endif @@ -354,7 +547,7 @@ InitVideo(FCEUGI *gi) g_config->getOption("SDL.XScale", &s_exs); g_config->getOption("SDL.YScale", &s_eys); g_config->getOption("SDL.SpecialFX", &s_eefx); - + // -Video Modes Tag- if(s_sponge) { if(s_sponge >= 4) { @@ -392,11 +585,11 @@ InitVideo(FCEUGI *gi) { while (gtk_events_pending()) gtk_main_iteration_do(FALSE); - + char SDL_windowhack[128]; sprintf(SDL_windowhack, "SDL_WINDOWID=%u", (unsigned int)GDK_WINDOW_XID(gtk_widget_get_window(evbox))); SDL_putenv(SDL_windowhack); - + // init SDL video if (SDL_WasInit(SDL_INIT_VIDEO)) SDL_QuitSubSystem(SDL_INIT_VIDEO); @@ -407,10 +600,10 @@ InitVideo(FCEUGI *gi) } } #endif - + s_screen = SDL_SetVideoMode((int)(NWIDTH * s_exs), - (int)(s_tlines * s_eys), - desbpp, flags); + (int)(s_tlines * s_eys), + desbpp, flags); if(!s_screen) { FCEUD_PrintError(SDL_GetError()); return -1; @@ -422,9 +615,9 @@ InitVideo(FCEUGI *gi) GtkRequisition req; gtk_widget_size_request(GTK_WIDGET(MainWindow), &req); gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height); - } + } #endif - } + } s_curbpp = s_screen->format->BitsPerPixel; if(!s_screen) { FCEUD_PrintError(SDL_GetError()); @@ -434,17 +627,17 @@ InitVideo(FCEUGI *gi) #if 0 // XXX soules - this would be creating a surface on the video - // card, but was commented out for some reason... - s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240, - s_screen->format->BitsPerPixel, - s_screen->format->Rmask, - s_screen->format->Gmask, - s_screen->format->Bmask, 0); + // card, but was commented out for some reason... + s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240, + s_screen->format->BitsPerPixel, + s_screen->format->Rmask, + s_screen->format->Gmask, + s_screen->format->Bmask, 0); #endif FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n", - s_screen->w, s_screen->h, s_screen->format->BitsPerPixel, - s_fullscreen ? "full screen" : ""); + s_screen->w, s_screen->h, s_screen->format->BitsPerPixel, + s_fullscreen ? "full screen" : ""); if(s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) { FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", s_curbpp); @@ -465,34 +658,34 @@ InitVideo(FCEUGI *gi) // create the surface for displaying graphical messages #ifdef LSB_FIRST s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, - 32, 32, 24, 32 * 3, - 0xFF, 0xFF00, 0xFF0000, 0x00); + 32, 32, 24, 32 * 3, + 0xFF, 0xFF00, 0xFF0000, 0x00); #else s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, - 32, 32, 24, 32 * 3, - 0xFF0000, 0xFF00, 0xFF, 0x00); + 32, 32, 24, 32 * 3, + 0xFF0000, 0xFF00, 0xFF, 0x00); #endif SDL_WM_SetIcon(s_IconSurface,0); s_paletterefresh = 1; // XXX soules - can't SDL do this for us? - // if using more than 8bpp, initialize the conversion routines + // if using more than 8bpp, initialize the conversion routines if(s_curbpp > 8) { - InitBlitToHigh(s_curbpp >> 3, - s_screen->format->Rmask, - s_screen->format->Gmask, - s_screen->format->Bmask, - s_eefx, s_sponge, 0); + InitBlitToHigh(s_curbpp >> 3, + s_screen->format->Rmask, + s_screen->format->Gmask, + s_screen->format->Bmask, + s_eefx, s_sponge, 0); #ifdef OPENGL - if(s_useOpenGL) + if(s_useOpenGL) { int openGLip; g_config->getOption("SDL.OpenGLip", &openGLip); if(!InitOpenGL(NOFFSET, 256 - (s_clipSides ? 8 : 0), - s_srendline, s_erendline + 1, - s_exs, s_eys, s_eefx, - openGLip, xstretch, ystretch, s_screen)) + s_srendline, s_erendline + 1, + s_exs, s_eys, s_eefx, + openGLip, xstretch, ystretch, s_screen)) { FCEUD_PrintError("Error initializing OpenGL."); KillVideo(); @@ -505,12 +698,37 @@ InitVideo(FCEUGI *gi) } #endif +#if SDL_VERSION_ATLEAST(2, 0, 0) +void ToggleFS() +{ + // pause while we we are making the switch + bool paused = FCEUI_EmulationPaused(); + + if(!paused) + FCEUI_ToggleEmulationPause(); + + g_config->getOption("SDL.Fullscreen", &s_fullscreen); + s_fullscreen = !s_fullscreen; + g_config->setOption("SDL.Fullscreen", s_fullscreen); + + // shut down the current video system + // KillVideo(); - No longer needed for SDL2, I think? + + // flip the fullscreen flag + SDL_SetWindowFullscreen(s_window, + s_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0 ); + + // if we paused to make the switch; unpause + if(!paused) + FCEUI_ToggleEmulationPause(); +} +#else /** * Toggles the full-screen display. */ void ToggleFS() { - // pause while we we are making the switch + // pause while we we are making the switch bool paused = FCEUI_EmulationPaused(); if(!paused) FCEUI_ToggleEmulationPause(); @@ -526,7 +744,7 @@ void ToggleFS() if(noGui == 0) { if(!fullscreen) - showGui(0); + showGui(0); else showGui(1); } @@ -542,6 +760,7 @@ void ToggleFS() if(!paused) FCEUI_ToggleEmulationPause(); } +#endif static SDL_Color s_psdl[256]; @@ -566,46 +785,102 @@ FCEUD_SetPalette(uint8 index, */ void FCEUD_GetPalette(uint8 index, - uint8 *r, - uint8 *g, - uint8 *b) + uint8 *r, + uint8 *g, + uint8 *b) { *r = s_psdl[index].r; *g = s_psdl[index].g; *b = s_psdl[index].b; } -/** +/** * Pushes the palette structure into the underlying video subsystem. */ static void RedoPalette() { +#if SDL_VERSION_ATLEAST(2, 0, 0) + SetPaletteBlitToHigh((uint8*)s_psdl); +#else #ifdef OPENGL if(s_useOpenGL) SetOpenGLPalette((uint8*)s_psdl); - else + else #endif { if(s_curbpp > 8) { SetPaletteBlitToHigh((uint8*)s_psdl); } else { -#if SDL_VERSION_ATLEAST(2, 0, 0) - //TODO - SDL2 -#else + SDL_SetPalette(s_screen, SDL_PHYSPAL, s_psdl, 0, 256); -#endif } } +#endif } // XXX soules - console lock/unlock unimplemented? ///Currently unimplemented. -void LockConsole(){} +void LockConsole() {} ///Currently unimplemented. -void UnlockConsole(){} +void UnlockConsole() {} +#if SDL_VERSION_ATLEAST(2, 0, 0) +void +BlitScreen(uint8 *XBuf) +{ + SDL_Surface * TmpScreen = s_screen; + uint8 *dest; + int xo = 0, yo = 0; + + if(!s_screen) { + return; + } + + // refresh the palette if required + if(s_paletterefresh) { + RedoPalette(); + s_paletterefresh = 0; + } + + // XXX soules - not entirely sure why this is being done yet + XBuf += s_srendline * 256; + + // lock the display, if necessary + if(SDL_MUSTLOCK(TmpScreen)) { + if(SDL_LockSurface(TmpScreen) < 0) { + return; + } + } + + dest = (uint8*)TmpScreen->pixels; + +#if 0 + if(s_fullscreen) { + xo = (int)(((TmpScreen->w - NWIDTH * s_exs)) / 2); + dest += xo * (s_curbpp >> 3); + if(TmpScreen->h > (s_tlines * s_eys)) { + yo = (int)((TmpScreen->h - s_tlines * s_eys) / 2); + dest += yo * TmpScreen->pitch; + } + } +#endif + + Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, + TmpScreen->pitch, (int)s_exs, (int)s_eys); + + if(SDL_MUSTLOCK(TmpScreen)) { + SDL_UnlockSurface(TmpScreen); + } + + SDL_UpdateTexture(s_texture, NULL, s_screen->pixels, s_screen->pitch); + SDL_RenderClear(s_renderer); + SDL_RenderCopy(s_renderer, s_texture, NULL, NULL); + SDL_RenderPresent(s_renderer); +} + +#else // SDL1.x /** * Pushes the given buffer of bits to the screen. */ @@ -666,19 +941,19 @@ BlitScreen(uint8 *XBuf) if(s_curbpp > 8) { if(s_BlitBuf) { Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, 1, 1); + TmpScreen->pitch, 1, 1); } else { Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, (int)s_exs, (int)s_eys); + TmpScreen->pitch, (int)s_exs, (int)s_eys); } } else { if(s_BlitBuf) { Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, 1, 1, 0, s_sponge); + TmpScreen->pitch, 1, 1, 0, s_sponge); } else { Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, (int)s_exs, (int)s_eys, - s_eefx, s_sponge); + TmpScreen->pitch, (int)s_exs, (int)s_eys, + s_eefx, s_sponge); } } @@ -687,7 +962,7 @@ BlitScreen(uint8 *XBuf) SDL_UnlockSurface(TmpScreen); } - // if we have a hardware video buffer, do a fast video->video copy + // if we have a hardware video buffer, do a fast video->video copy if(s_BlitBuf) { SDL_Rect srect; SDL_Rect drect; @@ -705,97 +980,108 @@ BlitScreen(uint8 *XBuf) SDL_BlitSurface(s_BlitBuf, &srect, s_screen, &drect); } - // ensure that the display is updated -#if SDL_VERSION_ATLEAST(2, 0, 0) - //TODO - SDL2 -#else + // ensure that the display is updated SDL_UpdateRect(s_screen, xo, yo, - (Uint32)(NWIDTH * s_exs), (Uint32)(s_tlines * s_eys)); -#endif + (Uint32)(NWIDTH * s_exs), (Uint32)(s_tlines * s_eys)); #ifdef CREATE_AVI #if 0 /* PAL INTO NTSC HACK */ - { int fps = FCEUI_GetDesiredFPS(); - if(FCEUI_GetDesiredFPS() == 838977920) fps = 1008307711; - NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); - if(FCEUI_GetDesiredFPS() == 838977920) - { - static unsigned dup=0; - if(++dup==5) { dup=0; - NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); } - } } + { int fps = FCEUI_GetDesiredFPS(); + if(FCEUI_GetDesiredFPS() == 838977920) fps = 1008307711; + NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); + if(FCEUI_GetDesiredFPS() == 838977920) + { + static unsigned dup=0; + if(++dup==5) { + dup=0; + NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); + } + } + } #else - { int fps = FCEUI_GetDesiredFPS(); - static unsigned char* result = NULL; - static unsigned resultsize = 0; - int width = NWIDTH, height = s_tlines; - if(!result || resultsize != width*height*3*2) - { - if(result) free(result); - result = (unsigned char*) FCEU_dmalloc(resultsize = width*height*3*2); - } - switch(s_curbpp) - { - #if 0 - case 24: case 32: case 15: case 16: - /* Convert to I420 if possible, because our I420 conversion is optimized - * and it'll produce less network traffic, hence faster throughput than - * anything else. And H.264 eats only I420, so it'd be converted sooner - * or later anyway if we didn't do it. Win-win situation. - */ - switch(s_curbpp) - { - case 32: Convert32To_I420Frame(s_screen->pixels, &result[0], width*height, width); break; - case 24: Convert24To_I420Frame(s_screen->pixels, &result[0], width*height, width); break; - case 15: Convert15To_I420Frame(s_screen->pixels, &result[0], width*height, width); break; - case 16: Convert16To_I420Frame(s_screen->pixels, &result[0], width*height, width); break; - } - NESVideoLoggingVideo(&result[0], width,height, fps, 12); - break; - #endif - default: - NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); - } - } + { int fps = FCEUI_GetDesiredFPS(); + static unsigned char* result = NULL; + static unsigned resultsize = 0; + int width = NWIDTH, height = s_tlines; + if(!result || resultsize != width*height*3*2) + { + if(result) free(result); + result = (unsigned char*) FCEU_dmalloc(resultsize = width*height*3*2); + } + switch(s_curbpp) + { +#if 0 + case 24: + case 32: + case 15: + case 16: + /* Convert to I420 if possible, because our I420 conversion is optimized + * and it'll produce less network traffic, hence faster throughput than + * anything else. And H.264 eats only I420, so it'd be converted sooner + * or later anyway if we didn't do it. Win-win situation. + */ + switch(s_curbpp) + { + case 32: + Convert32To_I420Frame(s_screen->pixels, &result[0], width*height, width); + break; + case 24: + Convert24To_I420Frame(s_screen->pixels, &result[0], width*height, width); + break; + case 15: + Convert15To_I420Frame(s_screen->pixels, &result[0], width*height, width); + break; + case 16: + Convert16To_I420Frame(s_screen->pixels, &result[0], width*height, width); + break; + } + NESVideoLoggingVideo(&result[0], width,height, fps, 12); + break; +#endif + default: + NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); + } + } #endif #if REALTIME_LOGGING - { - static struct timeval last_time; - static int first_time=1; - extern long soundrate; - - struct timeval cur_time; - gettimeofday(&cur_time, NULL); - - double timediff = - (cur_time.tv_sec *1e6 + cur_time.tv_usec - - (last_time.tv_sec *1e6 + last_time.tv_usec)) / 1e6; - - int nframes = timediff * 60 - 1; - if(first_time) - first_time = 0; - else while(nframes > 0) - { - static const unsigned char Buf[800*4] = {0}; - NESVideoLoggingVideo(screen->pixels, 256,tlines, FCEUI_GetDesiredFPS(), s_curbpp); - NESVideoLoggingAudio(Buf, soundrate,16,1, soundrate/60.0); - --nframes; - } - memcpy(&last_time, &cur_time, sizeof(last_time)); - } + { + static struct timeval last_time; + static int first_time=1; + extern long soundrate; + + struct timeval cur_time; + gettimeofday(&cur_time, NULL); + + double timediff = + (cur_time.tv_sec *1e6 + cur_time.tv_usec + - (last_time.tv_sec *1e6 + last_time.tv_usec)) / 1e6; + + int nframes = timediff * 60 - 1; + if(first_time) + first_time = 0; + else while(nframes > 0) + { + static const unsigned char Buf[800*4] = {0}; + NESVideoLoggingVideo(screen->pixels, 256,tlines, FCEUI_GetDesiredFPS(), s_curbpp); + NESVideoLoggingAudio(Buf, soundrate,16,1, soundrate/60.0); + --nframes; + } + memcpy(&last_time, &cur_time, sizeof(last_time)); + } #endif #endif #if SDL_VERSION_ATLEAST(2, 0, 0) // TODO #else - // have to flip the displayed buffer in the case of double buffering + // have to flip the displayed buffer in the case of double buffering if(s_screen->flags & SDL_DOUBLEBUF) { SDL_Flip(s_screen); } #endif } +#endif // SDL_VERSION_ATLEAST(2, 0, 0) for BlitScreen /** * Converts an x-y coordinate in the window manager into an x-y @@ -803,7 +1089,7 @@ BlitScreen(uint8 *XBuf) */ uint32 PtoV(uint16 x, - uint16 y) + uint16 y) { y = (uint16)((double)y / s_eys); x = (uint16)((double)x / s_exs); diff --git a/branches/sdl2/src/drivers/sdl/sdl.cpp b/branches/sdl2/src/drivers/sdl/sdl.cpp index d23e5a64..47d44665 100644 --- a/branches/sdl2/src/drivers/sdl/sdl.cpp +++ b/branches/sdl2/src/drivers/sdl/sdl.cpp @@ -310,6 +310,9 @@ DriverInitialize(FCEUGI *gi) if(InitJoysticks()) inited|=2; + if(InitGameControllers()) + inited|=8; + int fourscore=0; g_config->getOption("SDL.FourScore", &fourscore); eoptions &= ~EO_FOURSCORE; @@ -329,6 +332,8 @@ DriverKill() if (!noconfig) g_config->save(); + if(inited&8) + KillGameControllers(); if(inited&2) KillJoysticks(); if(inited&4)