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)