diff --git a/changelog.txt b/changelog.txt index e791a58f..fc014dec 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,4 @@ +16-may-2010 - ugetab - Added player 3 and 4 to autohold notification window. Made FCEU_DispMessage able to display to different screen locations to do it. Made sure to update SDL with the change. Hope SDL still compiles ok. 15-may-2010 - ugetab - Win32 - Added option for palette selection as color for LUA colors. Included an LUA script to display all choices with the value used to pick displayed color. 14-may-2010 - adelikat - Win32 - Replay dialog, when selecting a movie in a relative path (.\movies for example), the recent movies list stores an absolute path instead. 14-may-2010 - adelikat - Win32 - When recording a movie, add it to recent movies diff --git a/src/boards/mmc1.cpp b/src/boards/mmc1.cpp index d62b03fc..97b7a941 100644 --- a/src/boards/mmc1.cpp +++ b/src/boards/mmc1.cpp @@ -139,7 +139,7 @@ static uint64 lreset; static DECLFW(MMC1_write) { int n=(A>>13)-4; - //FCEU_DispMessage("%016x",timestampbase+timestamp); + //FCEU_DispMessage("%016x",0,timestampbase+timestamp); // FCEU_printf("$%04x:$%02x, $%04x\n",A,V,X.PC); //DumpMem("out",0xe000,0xffff); diff --git a/src/cheat.cpp b/src/cheat.cpp index 5e89e30d..b0cdb1d2 100644 --- a/src/cheat.cpp +++ b/src/cheat.cpp @@ -128,7 +128,7 @@ void RebuildSubCheats(void) if(GetReadHandler(c->addr)==SubCheatsRead) { /* Prevent a catastrophe by this check. */ - //FCEU_DispMessage("oops"); + //FCEU_DispMessage("oops",0); } else { @@ -144,7 +144,7 @@ void RebuildSubCheats(void) } FrozenAddressCount = numsubcheats; //Update the frozen address list UpdateFrozenList(); - //FCEUI_DispMessage("Active Cheats: %d", FrozenAddresses.size()/*FrozenAddressCount*/); //Debug + //FCEUI_DispMessage("Active Cheats: %d",0, FrozenAddresses.size()/*FrozenAddressCount*/); //Debug } void FCEU_PowerCheats() @@ -214,8 +214,8 @@ void FCEU_LoadGameCheats(FILE *override) if(!fp) return; } - FCEU_DispMessage("Cheats file loaded."); //Tells user a cheats file was loaded. - FCEU_printf("Cheats file loaded.\n"); //Sends message to message log. + FCEU_DispMessage("Cheats file loaded.",0); //Tells user a cheats file was loaded. + FCEU_printf("Cheats file loaded.\n",0); //Sends message to message log. while(fgets(linebuf,2048,fp)>0) { char *tbuf=linebuf; @@ -948,5 +948,5 @@ void UpdateFrozenList(void) FrozenAddresses.push_back(SubCheats[x].addr); //FCEU_printf("Address %d: %d \n",x,FrozenAddresses[x]); //Debug } - //FCEUI_DispMessage("FrozenCount: %d",FrozenAddressCount);//Debug + //FCEUI_DispMessage("FrozenCount: %d",0,FrozenAddressCount);//Debug } \ No newline at end of file diff --git a/src/drawing.cpp b/src/drawing.cpp index c0296ed5..2da03cd7 100644 --- a/src/drawing.cpp +++ b/src/drawing.cpp @@ -135,7 +135,11 @@ void DrawMessage(bool beforeMovie) uint8 *t; guiMessage.howlong--; - t=XBuf+FCEU_TextScanlineOffsetFromBottom(20)+1; + + if (guiMessage.linesFromBottom) + t=XBuf+FCEU_TextScanlineOffsetFromBottom(guiMessage.linesFromBottom)+1; + else + t=XBuf+FCEU_TextScanlineOffsetFromBottom(20)+1; /* FCEU palette: diff --git a/src/driver.h b/src/driver.h index 5edd33eb..4fe6af38 100644 --- a/src/driver.h +++ b/src/driver.h @@ -178,7 +178,7 @@ void FCEUD_LuaRunFrom(void); int32 FCEUI_GetDesiredFPS(void); void FCEUI_SaveSnapshot(void); -void FCEU_DispMessage(char *format, ...); +void FCEU_DispMessage(char *format, int disppos, ...); #define FCEUI_DispMessage FCEU_DispMessage int FCEUI_DecodePAR(const char *code, int *a, int *v, int *c, int *type); diff --git a/src/drivers/sdl/input.cpp b/src/drivers/sdl/input.cpp index b652ca4c..8878e0a5 100644 --- a/src/drivers/sdl/input.cpp +++ b/src/drivers/sdl/input.cpp @@ -1,1819 +1,1819 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#include "main.h" -#include "dface.h" -#include "input.h" -#include "config.h" - - -#include "sdl-video.h" -#include "sdl.h" - -#include "../common/cheat.h" -#include "../../movie.h" -#include "../../fceu.h" -#include "../../driver.h" -#include "../../utils/xstring.h" -#ifdef _S9XLUA_H -#include "../../fceulua.h" -#endif - -#ifdef _GTK_LITE -#include -#endif - - -/** GLOBALS **/ -int NoWaiting=1; -extern Config *g_config; -extern bool bindSavestate, frameAdvanceLagSkip, lagCounterDisplay; - - -/* UsrInputType[] is user-specified. InputType[] is current - (game loading can override user settings) -*/ -static int UsrInputType[NUM_INPUT_DEVICES]; -static int InputType[NUM_INPUT_DEVICES]; -static int cspec = 0; - -extern int gametype; - -/** - * Necessary for proper GUI functioning (configuring when a game isn't loaded). - */ -void -InputUserActiveFix() -{ - int x; - for(x = 0; x < 3; x++) { - InputType[x] = UsrInputType[x]; - } -} - -/** - * Parse game information and configure the input devices accordingly. - */ -void -ParseGIInput(FCEUGI *gi) -{ - gametype=gi->type; - - InputType[0] = UsrInputType[0]; - InputType[1] = UsrInputType[1]; - InputType[2] = UsrInputType[2]; - - if(gi->input[0]>=0) { - InputType[0] = gi->input[0]; - } - if(gi->input[1]>=0) { - InputType[1] = gi->input[1]; - } - if(gi->inputfc>=0) { - InputType[2] = gi->inputfc; - } - cspec = gi->cspecial; -} - - -static uint8 QuizKingData = 0; -static uint8 HyperShotData = 0; -static uint32 MahjongData = 0; -static uint32 FTrainerData = 0; -static uint8 TopRiderData = 0; -static uint8 BWorldData[1+13+1]; - -static void UpdateFKB(void); -static void UpdateGamepad(void); -static void UpdateQuizKing(void); -static void UpdateHyperShot(void); -static void UpdateMahjong(void); -static void UpdateFTrainer(void); -static void UpdateTopRider(void); - -static uint32 JSreturn=0; - -/** - * Configure cheat devices (game genie, etc.). Restarts the keyboard - * and video subsystems. - */ -static void -DoCheatSeq() -{ - SilenceSound(1); - KillVideo(); - - DoConsoleCheatConfig(); - InitVideo(GameInfo); - SilenceSound(0); -} - -#include "keyscan.h" -static uint8 *g_keyState = 0; -static int DIPS = 0; - -static uint8 keyonce[MKK_COUNT]; -#define KEY(__a) g_keyState[MKK(__a)] - -static int -_keyonly(int a) -{ - // check for valid key - if(a > SDLK_LAST+1 || a < 0) - return(0); - #if SDL_VERSION_ATLEAST(1, 3, 0) - if(g_keyState[SDL_GetScancodeFromKey((SDLKey)a)]) - #else - if(g_keyState[a]) - #endif - { - - if(!keyonce[a]) { - keyonce[a] = 1; - return(1); - } - } else { - keyonce[a] = 0; - } - return(0); -} - -#define keyonly(__a) _keyonly(MKK(__a)) - -static int g_fkbEnabled = 0; - -// this function loads the sdl hotkeys from the config file into the -// global scope. this elimates the need for accessing the config file - -int Hotkeys[HK_MAX] = {0}; - -// on every cycle of keyboardinput() -void setHotKeys() -{ - std::string prefix = "SDL.Hotkeys."; - for(int i=0; igetOption(prefix + HotkeyStrings[i], &Hotkeys[i]); - } - return; -} - -/*** - * 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) -{ - if (FCEUI_EmulationPaused() == 0) - FCEUI_ToggleEmulationPause(); - std::string fname = ""; - -#ifdef WIN32 - OPENFILENAME ofn; // common dialog box structure - char szFile[260]; // buffer for file name - HWND hwnd; // owner window - HANDLE hf; // file handle - - // Initialize OPENFILENAME - memset(&ofn,0,sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hwnd; - ofn.lpstrFile = szFile; - // 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); - ofn.lpstrFilter = "All\0*.*\0"; - ofn.nFilterIndex = 1; - ofn.lpstrFileTitle = NULL; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = NULL; - ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - - // Display the Open dialog box. - fname = GetOpenFileName(&ofn); - -#endif -#ifdef _GTK_LITE - int fullscreen = 0; - g_config->getOption("SDL.Fullscreen", &fullscreen); - if(fullscreen) - ToggleFS(); - - GtkWidget* fileChooser; - - GtkFileFilter* filterX; - GtkFileFilter* filterAll; - - filterX = gtk_file_filter_new(); - gtk_file_filter_add_pattern(filterX, filter); - gtk_file_filter_set_name(filterX, filter); - - - filterAll = gtk_file_filter_new(); - gtk_file_filter_add_pattern(filterAll, "*"); - gtk_file_filter_set_name(filterAll, "All Files"); - - 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); - 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); - - // 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)); - - // flush gtk events - while(gtk_events_pending()) - gtk_main_iteration_do(TRUE); - - if (response == GTK_RESPONSE_ACCEPT) - fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); - - gtk_widget_destroy (fileChooser); - - while(gtk_events_pending()) - gtk_main_iteration_do(TRUE); -#endif - FCEUI_ToggleEmulationPause(); - return fname; -} - -/** - * This function opens a text entry dialog and returns the user's input - */ -std::string GetUserText(const char* title) -{ -#ifdef _GTK_LITE - - GtkWidget* d; - GtkWidget* entry; - - d = gtk_dialog_new_with_buttons(title, NULL, GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_OK); - - entry = gtk_entry_new(); - - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(d)->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); - - 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; - std::string input; - while((c = fgetc(fpipe))) - { - if (c == EOF || c == '\n') - break; - input += c; - } - pclose(fpipe);*/ - gtk_widget_destroy(d); - - - while(gtk_events_pending()) - gtk_main_iteration_do(TRUE); - - FCEUI_ToggleEmulationPause(); // unpause emulation - return input; - -#endif - return ""; -} - - -/** -* Lets the user start a new .fm2 movie file -**/ -void FCEUD_MovieRecordTo() -{ - std::string fname = GetFilename("Save FM2 movie for recording", true, "FM2 movies|*.fm2"); - if (!fname.size()) - return; // no filename selected, quit the whole thing - std::wstring author = mbstowcs(GetUserText("Author name")); // the author can be empty, so no need to check here - - FCEUI_SaveMovie(fname.c_str(), MOVIE_FLAG_FROM_POWERON, author); -} - - -/** -* Lets the user save a savestate to a specific file -**/ -void FCEUD_SaveStateAs() -{ - std::string fname = GetFilename("Save savestate as...", true, "Savestates|*.fc0"); - if (!fname.size()) - return; // no filename selected, quit the whole thing - - FCEUI_SaveState(fname.c_str()); -} - -/** -* Lets the user load a savestate from a specific file -*/ -void FCEUD_LoadStateFrom() -{ - std::string fname = GetFilename("Load savestate from...", false, "Savestates|*.fc?"); - if (!fname.size()) - return; // no filename selected, quit the whole thing - - FCEUI_LoadState(fname.c_str()); -} - -/** - * Parse keyboard commands and execute accordingly. - */ -static void -KeyboardCommands() -{ - int is_shift, is_alt; - SDLMod mod; - - char* movie_fname = ""; - // get the keyboard input - #if SDL_VERSION_ATLEAST(1, 3, 0) - g_keyState = SDL_GetKeyboardState(NULL); - #else - g_keyState = SDL_GetKeyState(NULL); - #endif - - // check if the family keyboard is enabled - if(InputType[2] == SIFC_FKB) { - if(keyonly(SCROLLLOCK)) { - g_fkbEnabled ^= 1; - FCEUI_DispMessage("Family Keyboard %sabled.", - g_fkbEnabled ? "en" : "dis"); - } - SDL_WM_GrabInput(g_fkbEnabled ? SDL_GRAB_ON : SDL_GRAB_OFF); - if(g_fkbEnabled) { - return; - } - } - - mod = SDL_GetModState(); - if(mod & (KMOD_LSHIFT|KMOD_RSHIFT)) - is_shift = 1; - else - is_shift = 0; - if(mod & (KMOD_LALT| KMOD_RALT)) - is_alt = 1; - else - is_alt = 0; - - - if(_keyonly(Hotkeys[HK_TOGGLE_BG])) { - if(is_shift) { - FCEUI_SetRenderPlanes(true, false); - } else { - FCEUI_SetRenderPlanes(true, true); - } - } - - // Alt-Enter to toggle full-screen - if(keyonly(ENTER) && is_alt) { - ToggleFS(); - } - - - - // Toggle Movie auto-backup - if(keyonly(M) && is_shift) { - autoMovieBackup ^= 1; - FCEUI_DispMessage("Automatic movie backup %sabled.", - autoMovieBackup ? "en" : "dis"); - } - - // Start recording an FM2 movie on Alt+R - if(keyonly(R) && is_alt) { - FCEUD_MovieRecordTo(); - } - - // Save a state from a file - if(keyonly(S) && is_alt) { - FCEUD_SaveStateAs(); - } - - // Load a state from a file - if(keyonly(L) && is_alt) { - FCEUD_LoadStateFrom(); - } - - // Famicom disk-system games - if(gametype==GIT_FDS) - { - if(_keyonly(Hotkeys[HK_FDS_SELECT])) { - FCEUI_FDSSelect(); - } - if(_keyonly(Hotkeys[HK_FDS_EJECT])) { - FCEUI_FDSInsert(); - } - } - - if(_keyonly(Hotkeys[HK_SCREENSHOT])) { - FCEUI_SaveSnapshot(); - } - - // if not NES Sound Format - if(gametype != GIT_NSF) { - if(_keyonly(Hotkeys[HK_CHEAT_MENU])) { - DoCheatSeq(); - } - - // f5 (default) save key, hold shift to save movie - if(_keyonly(Hotkeys[HK_SAVE_STATE])) { - if(is_shift) { - movie_fname = 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""); - } else { - FCEUI_SaveState(NULL); - } - } - - // f7 to load state, Shift-f7 to load movie - if(_keyonly(Hotkeys[HK_LOAD_STATE])) { - if(is_shift) { - FCEUI_StopMovie(); - std::string fname; - fname = GetFilename("Open FM2 movie for playback...", false, "FM2 movies|*.fm2"); - if(fname != "") - { - if(fname.find(".fm2") != std::string::npos) - { - FCEUI_printf("Playing back movie located at %s\n", fname.c_str()); - FCEUI_LoadMovie(fname.c_str(), false, false, false); - } - else - { - FCEUI_printf("Only FM2 movies are supported.\n"); - } - } - } else { - FCEUI_LoadState(NULL); - } - } - } - - - if(_keyonly(Hotkeys[HK_DECREASE_SPEED])) { - DecreaseEmulationSpeed(); - } - - if(_keyonly(Hotkeys[HK_INCREASE_SPEED])) { - IncreaseEmulationSpeed(); - } - - if(_keyonly(Hotkeys[HK_TOGGLE_FRAME_DISPLAY])) { - FCEUI_MovieToggleFrameDisplay(); - } - - if(_keyonly(Hotkeys[HK_TOGGLE_INPUT_DISPLAY])) { - FCEUI_ToggleInputDisplay(); - extern int input_display; - g_config->setOption("SDL.InputDisplay", input_display); - } - - if(_keyonly(Hotkeys[HK_MOVIE_TOGGLE_RW])) { - FCEUI_SetMovieToggleReadOnly(!FCEUI_GetMovieToggleReadOnly()); - } - - #ifdef CREATE_AVI - if(_keyonly(Hotkeys[HK_MUTE_CAPTURE])) { - extern int mutecapture; - mutecapture ^= 1; - } - #endif - - if(_keyonly(Hotkeys[HK_PAUSE])) { - FCEUI_ToggleEmulationPause(); - } - - // Toggle throttling - NoWaiting &= ~1; - if(g_keyState[Hotkeys[HK_TURBO]]) { - NoWaiting |= 1; - } - - static bool frameAdvancing = false; - if(g_keyState[Hotkeys[HK_FRAME_ADVANCE]]) - { - if(frameAdvancing == false) - { - FCEUI_FrameAdvance(); - frameAdvancing = true; - } - } - else - { - if(frameAdvancing) - { - FCEUI_FrameAdvanceEnd(); - frameAdvancing = false; - } - } - - if(_keyonly(Hotkeys[HK_RESET])) { - FCEUI_ResetNES(); - } - //if(_keyonly(Hotkeys[HK_POWER])) { - // FCEUI_PowerNES(); - //} - - if(_keyonly(Hotkeys[HK_QUIT])) { - CloseGame(); - } - #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()); - } - #endif - - for(int i=0; i<10; i++) - if(_keyonly(Hotkeys[HK_SELECT_STATE_0 + i])) - FCEUI_SelectState(i, 1); - - if(_keyonly(Hotkeys[HK_BIND_STATE])) { - bindSavestate ^= 1; - FCEUI_DispMessage("Savestate binding to movie %sabled.", - bindSavestate ? "en" : "dis"); - } - - if(_keyonly(Hotkeys[HK_FA_LAG_SKIP])) { - frameAdvanceLagSkip ^= 1; - FCEUI_DispMessage("Skipping lag in Frame Advance %sabled.", - frameAdvanceLagSkip ? "en" : "dis"); - } - - if(_keyonly(Hotkeys[HK_LAG_COUNTER_DISPLAY])) { - lagCounterDisplay ^= 1; - } - - if (_keyonly(Hotkeys[HK_TOGGLE_SUBTITLE])) { - extern int movieSubtitles; - movieSubtitles ^= 1; - FCEUI_DispMessage("Movie subtitles o%s.", - movieSubtitles ? "n" : "ff"); - } - - // VS Unisystem games - if(gametype == GIT_VSUNI) { - // insert coin - if(_keyonly(Hotkeys[HK_VS_INSERT_COIN])) FCEUI_VSUniCoin(); - - // toggle dipswitch display - if(_keyonly(Hotkeys[HK_VS_TOGGLE_DIPSWITCH])) { - DIPS^=1; - FCEUI_VSUniToggleDIPView(); - } - if(!(DIPS&1)) goto DIPSless; - - // toggle the various dipswitches - if(keyonly(1)) FCEUI_VSUniToggleDIP(0); - if(keyonly(2)) FCEUI_VSUniToggleDIP(1); - if(keyonly(3)) FCEUI_VSUniToggleDIP(2); - if(keyonly(4)) FCEUI_VSUniToggleDIP(3); - if(keyonly(5)) FCEUI_VSUniToggleDIP(4); - if(keyonly(6)) FCEUI_VSUniToggleDIP(5); - if(keyonly(7)) FCEUI_VSUniToggleDIP(6); - if(keyonly(8)) FCEUI_VSUniToggleDIP(7); - } else { - static uint8 bbuf[32]; - static int bbuft; - static int barcoder = 0; - - if(keyonly(H)) FCEUI_NTSCSELHUE(); - if(keyonly(T)) FCEUI_NTSCSELTINT(); - - if (_keyonly(Hotkeys[HK_DECREASE_SPEED])) - FCEUI_NTSCDEC(); - if (_keyonly(Hotkeys[HK_INCREASE_SPEED])) - FCEUI_NTSCINC(); - - if((InputType[2] == SIFC_BWORLD) || (cspec == SIS_DATACH)) { - if(keyonly(F8)) { - barcoder ^= 1; - if(!barcoder) { - if(InputType[2] == SIFC_BWORLD) { - strcpy((char *)&BWorldData[1], (char *)bbuf); - BWorldData[0] = 1; - } else { - FCEUI_DatachSet(bbuf); - } - FCEUI_DispMessage("Barcode Entered"); - } else { - bbuft = 0; - FCEUI_DispMessage("Enter Barcode"); - } - } - } else { - barcoder = 0; - } - -#define SSM(x) \ -do { \ - if(barcoder) { \ - if(bbuft < 13) { \ - bbuf[bbuft++] = '0' + x; \ - bbuf[bbuft] = 0; \ - } \ - FCEUI_DispMessage("Barcode: %s", bbuf); \ - } \ -} while(0) - - DIPSless: - if(keyonly(0)) SSM(0); - if(keyonly(1)) SSM(1); - if(keyonly(2)) SSM(2); - if(keyonly(3)) SSM(3); - if(keyonly(4)) SSM(4); - if(keyonly(5)) SSM(5); - if(keyonly(6)) SSM(6); - if(keyonly(7)) SSM(7); - if(keyonly(8)) SSM(8); - if(keyonly(9)) SSM(9); -#undef SSM - } -} - -/** - * Return the state of the mouse buttons. Input 'd' is an array of 3 - * integers that store . - */ -void // removed static for a call in lua-engine.cpp -GetMouseData(uint32 (&d)[3]) -{ - int x,y; - uint32 t; - - // Don't get input when a movie is playing back - if(FCEUMOV_Mode(MOVIEMODE_PLAY)) - return; - - // retrieve the state of the mouse from SDL - t = SDL_GetMouseState(&x, &y); - - d[2] = 0; - if(t & SDL_BUTTON(1)) { - d[2] |= 0x1; - } - if(t & SDL_BUTTON(3)) { - d[2] |= 0x2; - } - - // get the mouse position from the SDL video driver - t = PtoV(x, y); - d[0] = t & 0xFFFF; - d[1] = (t >> 16) & 0xFFFF; -} - -/** - * Handles outstanding SDL events. - */ -static void -UpdatePhysicalInput() -{ - SDL_Event event; - - // loop, handling all pending events - while(SDL_PollEvent(&event)) { - switch(event.type) { - case SDL_QUIT: - CloseGame(); - puts("Quit"); - break; - default: - // do nothing - break; - } - } - //SDL_PumpEvents(); -} - - -static int bcpv,bcpj; - -/** - * Begin configuring the buttons by placing the video and joystick - * subsystems into a well-known state. Button configuration really - * needs to be cleaned up after the new config system is in place. - */ -int -ButtonConfigBegin() -{ - SDL_Surface *screen; - - // XXX soules - why are we doing this right before KillVideo()? - SDL_QuitSubSystem(SDL_INIT_VIDEO); - - // shut down the video and joystick subsystems - bcpv=KillVideo(); - bcpj=KillJoysticks(); - - // reactivate the video subsystem - if(!SDL_WasInit(SDL_INIT_VIDEO)) { - if(SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) { - FCEUD_Message(SDL_GetError()); - return(0); - } - } - - // set the screen and notify the user of button configuration - screen = SDL_SetVideoMode(420, 200, 8, 0); - SDL_WM_SetCaption("Button Config",0); - - // XXX soules - why did we shut this down? - // initialize the joystick subsystem - InitJoysticks(); - - return(1); -} - -/** - * Finish configuring the buttons by reverting the video and joystick - * subsystems to their previous state. Button configuration really - * needs to be cleaned up after the new config system is in place. - */ -void -ButtonConfigEnd() -{ - extern FCEUGI *GameInfo; - - // shutdown the joystick and video subsystems - KillJoysticks(); - SDL_QuitSubSystem(SDL_INIT_VIDEO); - - // re-initialize joystick and video subsystems if they were active before - if(!bcpv) { - InitVideo(GameInfo); - } - if(!bcpj) { - InitJoysticks(); - } -} - -/** - * Tests to see if a specified button is currently pressed. - */ -static int -DTestButton(ButtConfig *bc) -{ - int x; - - for(x = 0; x < bc->NumC; x++) { - if(bc->ButtType[x] == BUTTC_KEYBOARD) { - #if SDL_VERSION_ATLEAST(1,3,0) - if(g_keyState[SDL_GetScancodeFromKey((SDLKey)bc->ButtonNum[x])]) { - #else - if(g_keyState[bc->ButtonNum[x]]) { - #endif - return(1); - } - } else if(bc->ButtType[x] == BUTTC_JOYSTICK) { - if(DTestButtonJoy(bc)) { - return(1); - } - } - } - return(0); -} - - - - -#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1} -#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2} -#define MKZ() {{0},{0},{0},0} -#define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} - -ButtConfig GamePadConfig[4][10]={ - /* Gamepad 1 */ - { MK(KP3), MK(KP2), MK(SLASH), MK(ENTER), - MK(W), MK(Z), MK(A), MK(S), MKZ(), MKZ() }, - - /* Gamepad 2 */ - GPZ(), - - /* Gamepad 3 */ - GPZ(), - - /* Gamepad 4 */ - GPZ() -}; - -/** - * Update the status of the gamepad input devices. - */ -static void -UpdateGamepad(void) -{ - // don't update during movie playback - if(FCEUMOV_Mode(MOVIEMODE_PLAY)) { - return; - } - - static int rapid=0; - uint32 JS=0; - int x; - int wg; - - rapid ^= 1; - - // go through each of the four game pads - for(wg = 0; wg < 4; wg++) { - // the 4 directional buttons, start, select, a, b - for(x = 0; x < 8; x++) { - if(DTestButton(&GamePadConfig[wg][x])) { - JS |= (1 << x) << (wg << 3); - } - } - - // rapid-fire a, rapid-fire b - if(rapid) { - for(x = 0; x < 2; x++) { - if(DTestButton(&GamePadConfig[wg][8+x])) { - JS |= (1 << x) << (wg << 3); - } - } - } - } - - // for(x=0;x<32;x+=8) /* Now, test to see if anything weird(up+down at same time) - // is happening, and correct */ - // { - // if((JS & (0xC0<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) { - bc->ButtType[wb] = BUTTC_JOYSTICK; - bc->DeviceNum[wb] = event.jhat.which; - bc->ButtonNum[wb] = (0x2000 | ((event.jhat.hat & 0x1F) << 8) | - event.jhat.value); - 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; - } - } 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); - } - } - break; - } - } - - return(0); -} - -/** - * This function takes in button inputs until either it sees two of - * the same button presses in a row or gets four inputs and then saves - * the total number of button presses. Each of the keys pressed is - * used as input for the specified button, thus allowing up to four - * possible settings for each input button. - */ -void -ConfigButton(char *text, - ButtConfig *bc) -{ - uint8 buf[256]; - int wc; - - for(wc = 0; wc < MAXBUTTCONFIG; wc++) { - sprintf((char *)buf, "%s (%d)", text, wc + 1); - 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]) { - break; - } - } - bc->NumC = wc; -} - -/** - * Update the button configuration for a specified device. - */ -extern Config *g_config; - -void -ConfigDevice(int which, - int arg) -{ - char buf[256]; - int x; - std::string prefix; - char *str[10]={"A","B","SELECT","START","UP","DOWN","LEFT","RIGHT","Rapid A","Rapid B"}; - - // XXX soules - set the configuration options so that later calls - // don't override these. This is a temp hack until I - // can clean up this file. - - 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]); - - 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]); - - 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]); - - 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; - - 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]); - } - - 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(); -} - - -/** - * Update the button configuration for a device, specified by a text string. - */ -void -InputCfg(const std::string &text) -{ - if(text.find("gamepad") != std::string::npos) { - int device = (text[strlen("gamepad")] - '1'); - if(device<0 || device>3) { - FCEUD_PrintError("Invalid gamepad device specified; must be one of gamepad1 through gamepad4"); - exit(-1); - } - ConfigDevice(FCFGD_GAMEPAD, device); - } else if(text.find("powerpad") != std::string::npos) { - int device = (text[strlen("powerpad")] - '1'); - if(device<0 || device>1) { - FCEUD_PrintError("Invalid powerpad device specified; must be powerpad1 or powerpad2"); - exit(-1); - } - ConfigDevice(FCFGD_POWERPAD, device); - } else if(text.find("hypershot") != std::string::npos) { - ConfigDevice(FCFGD_HYPERSHOT, 0); - } else if(text.find("quizking") != std::string::npos) { - ConfigDevice(FCFGD_QUIZKING, 0); - } -} - - -/** - * Hack to map the new configuration onto the existing button - * configuration management. Will probably want to change this in the - * future - soules. - */ -void -UpdateInput(Config *config) -{ - char buf[64]; - std::string device, prefix; - - for(unsigned int i = 0; i < 3; i++) { - snprintf(buf, 64, "SDL.Input.%d", i); - config->getOption(buf, &device); - - if(device == "None") { - UsrInputType[i] = SI_NONE; - } else if(device.find("GamePad") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_GAMEPAD : (int)SIFC_NONE; - } else if(device.find("PowerPad.0") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_POWERPADA : (int)SIFC_NONE; - } else if(device.find("PowerPad.1") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_POWERPADB : (int)SIFC_NONE; - } else if(device.find("QuizKing") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_QUIZKING; - } else if(device.find("HyperShot") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_HYPERSHOT; - } else if(device.find("Mahjong") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_MAHJONG; - } else if(device.find("TopRider") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_TOPRIDER; - } else if(device.find("FTrainer") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_FTRAINERA; - } else if(device.find("FamilyKeyBoard") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_FKB; - } else if(device.find("OekaKids") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_OEKAKIDS; - } else if(device.find("Arkanoid") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_ARKANOID : (int)SIFC_ARKANOID; - } else if(device.find("Shadow") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_SHADOW; - } else if(device.find("Zapper") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_ZAPPER : (int)SIFC_NONE; - } else if(device.find("BWorld") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_BWORLD; - } else if(device.find("4Player") != std::string::npos) { - UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_4PLAYER; - } else { - // Unknown device - UsrInputType[i] = SI_NONE; - } - } - - // update each of the devices' configuration structure - // XXX soules - this is temporary until this file is cleaned up to - // simplify the interface between configuration and - // structure data. This will likely include the - // removal of multiple input buttons for a single - // input device key. - int type, devnum, button; - - // gamepad 0 - 3 - for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) { - char buf[64]; - snprintf(buf, 20, "SDL.Input.GamePad.%d.", i); - prefix = buf; - - config->getOption(prefix + "DeviceType", &device); - if(device.find("Keyboard") != std::string::npos) { - type = BUTTC_KEYBOARD; - } else if(device.find("Joystick") != std::string::npos) { - type = BUTTC_JOYSTICK; - } else { - type = 0; - } - - config->getOption(prefix + "DeviceNum", &devnum); - for(unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) { - config->getOption(prefix + GamePadNames[j], &button); - - GamePadConfig[i][j].ButtType[0] = type; - GamePadConfig[i][j].DeviceNum[0] = devnum; - GamePadConfig[i][j].ButtonNum[0] = button; - GamePadConfig[i][j].NumC = 1; - } - } - - // PowerPad 0 - 1 - for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) { - char buf[64]; - snprintf(buf, 20, "SDL.Input.PowerPad.%d.", i); - prefix = buf; - - config->getOption(prefix + "DeviceType", &device); - if(device.find("Keyboard") != std::string::npos) { - type = BUTTC_KEYBOARD; - } else if(device.find("Joystick") != std::string::npos) { - type = BUTTC_JOYSTICK; - } else { - type = 0; - } - - config->getOption(prefix + "DeviceNum", &devnum); - for(unsigned int j = 0; j < POWERPAD_NUM_BUTTONS; j++) { - config->getOption(prefix + PowerPadNames[j], &button); - - powerpadsc[i][j].ButtType[0] = type; - powerpadsc[i][j].DeviceNum[0] = devnum; - powerpadsc[i][j].ButtonNum[0] = button; - powerpadsc[i][j].NumC = 1; - } - } - - // QuizKing - prefix = "SDL.Input.QuizKing."; - config->getOption(prefix + "DeviceType", &device); - if(device.find("Keyboard") != std::string::npos) { - type = BUTTC_KEYBOARD; - } else if(device.find("Joystick") != std::string::npos) { - type = BUTTC_JOYSTICK; - } else { - type = 0; - } - config->getOption(prefix + "DeviceNum", &devnum); - for(unsigned int j = 0; j < QUIZKING_NUM_BUTTONS; j++) { - config->getOption(prefix + QuizKingNames[j], &button); - - QuizKingButtons[j].ButtType[0] = type; - QuizKingButtons[j].DeviceNum[0] = devnum; - QuizKingButtons[j].ButtonNum[0] = button; - QuizKingButtons[j].NumC = 1; - } - - // HyperShot - prefix = "SDL.Input.HyperShot."; - config->getOption(prefix + "DeviceType", &device); - if(device.find("Keyboard") != std::string::npos) { - type = BUTTC_KEYBOARD; - } else if(device.find("Joystick") != std::string::npos) { - type = BUTTC_JOYSTICK; - } else { - type = 0; - } - config->getOption(prefix + "DeviceNum", &devnum); - for(unsigned int j = 0; j < HYPERSHOT_NUM_BUTTONS; j++) { - config->getOption(prefix + HyperShotNames[j], &button); - - HyperShotButtons[j].ButtType[0] = type; - HyperShotButtons[j].DeviceNum[0] = devnum; - HyperShotButtons[j].ButtonNum[0] = button; - HyperShotButtons[j].NumC = 1; - } - - // Mahjong - prefix = "SDL.Input.Mahjong."; - config->getOption(prefix + "DeviceType", &device); - if(device.find("Keyboard") != std::string::npos) { - type = BUTTC_KEYBOARD; - } else if(device.find("Joystick") != std::string::npos) { - type = BUTTC_JOYSTICK; - } else { - type = 0; - } - config->getOption(prefix + "DeviceNum", &devnum); - for(unsigned int j = 0; j < MAHJONG_NUM_BUTTONS; j++) { - config->getOption(prefix + MahjongNames[j], &button); - - MahjongButtons[j].ButtType[0] = type; - MahjongButtons[j].DeviceNum[0] = devnum; - MahjongButtons[j].ButtonNum[0] = button; - MahjongButtons[j].NumC = 1; - } - - // TopRider - prefix = "SDL.Input.TopRider."; - config->getOption(prefix + "DeviceType", &device); - if(device.find("Keyboard") != std::string::npos) { - type = BUTTC_KEYBOARD; - } else if(device.find("Joystick") != std::string::npos) { - type = BUTTC_JOYSTICK; - } else { - type = 0; - } - config->getOption(prefix + "DeviceNum", &devnum); - for(unsigned int j = 0; j < TOPRIDER_NUM_BUTTONS; j++) { - config->getOption(prefix + TopRiderNames[j], &button); - - TopRiderButtons[j].ButtType[0] = type; - TopRiderButtons[j].DeviceNum[0] = devnum; - TopRiderButtons[j].ButtonNum[0] = button; - TopRiderButtons[j].NumC = 1; - } - - // FTrainer - prefix = "SDL.Input.FTrainer."; - config->getOption(prefix + "DeviceType", &device); - if(device.find("Keyboard") != std::string::npos) { - type = BUTTC_KEYBOARD; - } else if(device.find("Joystick") != std::string::npos) { - type = BUTTC_JOYSTICK; - } else { - type = 0; - } - config->getOption(prefix + "DeviceNum", &devnum); - for(unsigned int j = 0; j < FTRAINER_NUM_BUTTONS; j++) { - config->getOption(prefix + FTrainerNames[j], &button); - - FTrainerButtons[j].ButtType[0] = type; - FTrainerButtons[j].DeviceNum[0] = devnum; - FTrainerButtons[j].ButtonNum[0] = button; - FTrainerButtons[j].NumC = 1; - } - - // FamilyKeyBoard - prefix = "SDL.Input.FamilyKeyBoard."; - config->getOption(prefix + "DeviceType", &device); - if(device.find("Keyboard") != std::string::npos) { - type = BUTTC_KEYBOARD; - } else if(device.find("Joystick") != std::string::npos) { - type = BUTTC_JOYSTICK; - } else { - type = 0; - } - config->getOption(prefix + "DeviceNum", &devnum); - for(unsigned int j = 0; j < FAMILYKEYBOARD_NUM_BUTTONS; j++) { - config->getOption(prefix + FamilyKeyBoardNames[j], &button); - - fkbmap[j].ButtType[0] = type; - fkbmap[j].DeviceNum[0] = devnum; - fkbmap[j].ButtonNum[0] = button; - fkbmap[j].NumC = 1; - } -} -// Definitions from main.h: -// GamePad defaults -const char *GamePadNames[GAMEPAD_NUM_BUTTONS] = - {"A", "B", "Select", "Start", - "Up", "Down", "Left", "Right", "TurboA", "TurboB"}; -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 } }; - -// PowerPad defaults -const char *PowerPadNames[POWERPAD_NUM_BUTTONS] = - {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B"}; -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 } }; - -// QuizKing defaults -const char *QuizKingNames[QUIZKING_NUM_BUTTONS] = - { "0", "1", "2", "3", "4", "5" }; -const char *DefaultQuizKingDevice = "Keyboard"; -const int DefaultQuizKing[QUIZKING_NUM_BUTTONS] = - { SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y }; - -// HyperShot defaults -const char *HyperShotNames[HYPERSHOT_NUM_BUTTONS] = - { "0", "1", "2", "3" }; -const char *DefaultHyperShotDevice = "Keyboard"; -const int DefaultHyperShot[HYPERSHOT_NUM_BUTTONS] = - { SDLK_q, SDLK_w, SDLK_e, SDLK_r }; - -// Mahjong defaults -const char *MahjongNames[MAHJONG_NUM_BUTTONS] = - { "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_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 }; - -// TopRider defaults -const char *TopRiderNames[TOPRIDER_NUM_BUTTONS] = - { "0", "1", "2", "3", "4", "5", "6", "7" }; -const char *DefaultTopRiderDevice = "Keyboard"; -const int DefaultTopRider[TOPRIDER_NUM_BUTTONS] = - { SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y, SDLK_u, SDLK_i }; - -// FTrainer defaults -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_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", - "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", - "MINUS", "EQUAL", "BACKSLASH", "BACKSPACE", - "ESCAPE", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", - "P", "GRAVE", "BRACKET_LEFT", "ENTER", - "LEFTCONTROL", "A", "S", "D", "F", "G", "H", "J", "K", - "L", "SEMICOLON", "APOSTROPHE", "BRACKET_RIGHT", "INSERT", - "LEFTSHIFT", "Z", "X", "C", "V", "B", "N", "M", "COMMA", - "PERIOD", "SLASH", "RIGHTALT", "RIGHTSHIFT", "LEFTALT", "SPACE", - "DELETE", "END", "PAGEDOWN", - "CURSORUP", "CURSORLEFT", "CURSORRIGHT", "CURSORDOWN" }; -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_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, - SDLK_ESCAPE, SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y, SDLK_u, - SDLK_i, SDLK_o, SDLK_p, SDLK_BACKQUOTE, SDLK_LEFTBRACKET, SDLK_RETURN, - SDLK_LCTRL, SDLK_a, SDLK_s, SDLK_d, SDLK_f, SDLK_g, SDLK_h, SDLK_j, - SDLK_k, SDLK_l, SDLK_SEMICOLON, SDLK_QUOTE, SDLK_RIGHTBRACKET, - SDLK_INSERT, SDLK_LSHIFT, SDLK_z, SDLK_x, SDLK_c, SDLK_v, SDLK_b, - SDLK_n, SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH, SDLK_RALT, - SDLK_RSHIFT, SDLK_LALT, SDLK_SPACE, SDLK_DELETE, SDLK_END, SDLK_PAGEDOWN, - SDLK_UP, SDLK_LEFT, SDLK_RIGHT, SDLK_DOWN }; - +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "main.h" +#include "dface.h" +#include "input.h" +#include "config.h" + + +#include "sdl-video.h" +#include "sdl.h" + +#include "../common/cheat.h" +#include "../../movie.h" +#include "../../fceu.h" +#include "../../driver.h" +#include "../../utils/xstring.h" +#ifdef _S9XLUA_H +#include "../../fceulua.h" +#endif + +#ifdef _GTK_LITE +#include +#endif + + +/** GLOBALS **/ +int NoWaiting=1; +extern Config *g_config; +extern bool bindSavestate, frameAdvanceLagSkip, lagCounterDisplay; + + +/* UsrInputType[] is user-specified. InputType[] is current + (game loading can override user settings) +*/ +static int UsrInputType[NUM_INPUT_DEVICES]; +static int InputType[NUM_INPUT_DEVICES]; +static int cspec = 0; + +extern int gametype; + +/** + * Necessary for proper GUI functioning (configuring when a game isn't loaded). + */ +void +InputUserActiveFix() +{ + int x; + for(x = 0; x < 3; x++) { + InputType[x] = UsrInputType[x]; + } +} + +/** + * Parse game information and configure the input devices accordingly. + */ +void +ParseGIInput(FCEUGI *gi) +{ + gametype=gi->type; + + InputType[0] = UsrInputType[0]; + InputType[1] = UsrInputType[1]; + InputType[2] = UsrInputType[2]; + + if(gi->input[0]>=0) { + InputType[0] = gi->input[0]; + } + if(gi->input[1]>=0) { + InputType[1] = gi->input[1]; + } + if(gi->inputfc>=0) { + InputType[2] = gi->inputfc; + } + cspec = gi->cspecial; +} + + +static uint8 QuizKingData = 0; +static uint8 HyperShotData = 0; +static uint32 MahjongData = 0; +static uint32 FTrainerData = 0; +static uint8 TopRiderData = 0; +static uint8 BWorldData[1+13+1]; + +static void UpdateFKB(void); +static void UpdateGamepad(void); +static void UpdateQuizKing(void); +static void UpdateHyperShot(void); +static void UpdateMahjong(void); +static void UpdateFTrainer(void); +static void UpdateTopRider(void); + +static uint32 JSreturn=0; + +/** + * Configure cheat devices (game genie, etc.). Restarts the keyboard + * and video subsystems. + */ +static void +DoCheatSeq() +{ + SilenceSound(1); + KillVideo(); + + DoConsoleCheatConfig(); + InitVideo(GameInfo); + SilenceSound(0); +} + +#include "keyscan.h" +static uint8 *g_keyState = 0; +static int DIPS = 0; + +static uint8 keyonce[MKK_COUNT]; +#define KEY(__a) g_keyState[MKK(__a)] + +static int +_keyonly(int a) +{ + // check for valid key + if(a > SDLK_LAST+1 || a < 0) + return(0); + #if SDL_VERSION_ATLEAST(1, 3, 0) + if(g_keyState[SDL_GetScancodeFromKey((SDLKey)a)]) + #else + if(g_keyState[a]) + #endif + { + + if(!keyonce[a]) { + keyonce[a] = 1; + return(1); + } + } else { + keyonce[a] = 0; + } + return(0); +} + +#define keyonly(__a) _keyonly(MKK(__a)) + +static int g_fkbEnabled = 0; + +// this function loads the sdl hotkeys from the config file into the +// global scope. this elimates the need for accessing the config file + +int Hotkeys[HK_MAX] = {0}; + +// on every cycle of keyboardinput() +void setHotKeys() +{ + std::string prefix = "SDL.Hotkeys."; + for(int i=0; igetOption(prefix + HotkeyStrings[i], &Hotkeys[i]); + } + return; +} + +/*** + * 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) +{ + if (FCEUI_EmulationPaused() == 0) + FCEUI_ToggleEmulationPause(); + std::string fname = ""; + +#ifdef WIN32 + OPENFILENAME ofn; // common dialog box structure + char szFile[260]; // buffer for file name + HWND hwnd; // owner window + HANDLE hf; // file handle + + // Initialize OPENFILENAME + memset(&ofn,0,sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwnd; + ofn.lpstrFile = szFile; + // 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); + ofn.lpstrFilter = "All\0*.*\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + + // Display the Open dialog box. + fname = GetOpenFileName(&ofn); + +#endif +#ifdef _GTK_LITE + int fullscreen = 0; + g_config->getOption("SDL.Fullscreen", &fullscreen); + if(fullscreen) + ToggleFS(); + + GtkWidget* fileChooser; + + GtkFileFilter* filterX; + GtkFileFilter* filterAll; + + filterX = gtk_file_filter_new(); + gtk_file_filter_add_pattern(filterX, filter); + gtk_file_filter_set_name(filterX, filter); + + + filterAll = gtk_file_filter_new(); + gtk_file_filter_add_pattern(filterAll, "*"); + gtk_file_filter_set_name(filterAll, "All Files"); + + 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); + 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); + + // 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)); + + // flush gtk events + while(gtk_events_pending()) + gtk_main_iteration_do(TRUE); + + if (response == GTK_RESPONSE_ACCEPT) + fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fileChooser)); + + gtk_widget_destroy (fileChooser); + + while(gtk_events_pending()) + gtk_main_iteration_do(TRUE); +#endif + FCEUI_ToggleEmulationPause(); + return fname; +} + +/** + * This function opens a text entry dialog and returns the user's input + */ +std::string GetUserText(const char* title) +{ +#ifdef _GTK_LITE + + GtkWidget* d; + GtkWidget* entry; + + d = gtk_dialog_new_with_buttons(title, NULL, GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_OK); + + entry = gtk_entry_new(); + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(d)->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); + + 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; + std::string input; + while((c = fgetc(fpipe))) + { + if (c == EOF || c == '\n') + break; + input += c; + } + pclose(fpipe);*/ + gtk_widget_destroy(d); + + + while(gtk_events_pending()) + gtk_main_iteration_do(TRUE); + + FCEUI_ToggleEmulationPause(); // unpause emulation + return input; + +#endif + return ""; +} + + +/** +* Lets the user start a new .fm2 movie file +**/ +void FCEUD_MovieRecordTo() +{ + std::string fname = GetFilename("Save FM2 movie for recording", true, "FM2 movies|*.fm2"); + if (!fname.size()) + return; // no filename selected, quit the whole thing + std::wstring author = mbstowcs(GetUserText("Author name")); // the author can be empty, so no need to check here + + FCEUI_SaveMovie(fname.c_str(), MOVIE_FLAG_FROM_POWERON, author); +} + + +/** +* Lets the user save a savestate to a specific file +**/ +void FCEUD_SaveStateAs() +{ + std::string fname = GetFilename("Save savestate as...", true, "Savestates|*.fc0"); + if (!fname.size()) + return; // no filename selected, quit the whole thing + + FCEUI_SaveState(fname.c_str()); +} + +/** +* Lets the user load a savestate from a specific file +*/ +void FCEUD_LoadStateFrom() +{ + std::string fname = GetFilename("Load savestate from...", false, "Savestates|*.fc?"); + if (!fname.size()) + return; // no filename selected, quit the whole thing + + FCEUI_LoadState(fname.c_str()); +} + +/** + * Parse keyboard commands and execute accordingly. + */ +static void +KeyboardCommands() +{ + int is_shift, is_alt; + SDLMod mod; + + char* movie_fname = ""; + // get the keyboard input + #if SDL_VERSION_ATLEAST(1, 3, 0) + g_keyState = SDL_GetKeyboardState(NULL); + #else + g_keyState = SDL_GetKeyState(NULL); + #endif + + // check if the family keyboard is enabled + if(InputType[2] == SIFC_FKB) { + if(keyonly(SCROLLLOCK)) { + g_fkbEnabled ^= 1; + FCEUI_DispMessage("Family Keyboard %sabled.",0, + g_fkbEnabled ? "en" : "dis"); + } + SDL_WM_GrabInput(g_fkbEnabled ? SDL_GRAB_ON : SDL_GRAB_OFF); + if(g_fkbEnabled) { + return; + } + } + + mod = SDL_GetModState(); + if(mod & (KMOD_LSHIFT|KMOD_RSHIFT)) + is_shift = 1; + else + is_shift = 0; + if(mod & (KMOD_LALT| KMOD_RALT)) + is_alt = 1; + else + is_alt = 0; + + + if(_keyonly(Hotkeys[HK_TOGGLE_BG])) { + if(is_shift) { + FCEUI_SetRenderPlanes(true, false); + } else { + FCEUI_SetRenderPlanes(true, true); + } + } + + // Alt-Enter to toggle full-screen + if(keyonly(ENTER) && is_alt) { + ToggleFS(); + } + + + + // Toggle Movie auto-backup + if(keyonly(M) && is_shift) { + autoMovieBackup ^= 1; + FCEUI_DispMessage("Automatic movie backup %sabled.",0, + autoMovieBackup ? "en" : "dis"); + } + + // Start recording an FM2 movie on Alt+R + if(keyonly(R) && is_alt) { + FCEUD_MovieRecordTo(); + } + + // Save a state from a file + if(keyonly(S) && is_alt) { + FCEUD_SaveStateAs(); + } + + // Load a state from a file + if(keyonly(L) && is_alt) { + FCEUD_LoadStateFrom(); + } + + // Famicom disk-system games + if(gametype==GIT_FDS) + { + if(_keyonly(Hotkeys[HK_FDS_SELECT])) { + FCEUI_FDSSelect(); + } + if(_keyonly(Hotkeys[HK_FDS_EJECT])) { + FCEUI_FDSInsert(); + } + } + + if(_keyonly(Hotkeys[HK_SCREENSHOT])) { + FCEUI_SaveSnapshot(); + } + + // if not NES Sound Format + if(gametype != GIT_NSF) { + if(_keyonly(Hotkeys[HK_CHEAT_MENU])) { + DoCheatSeq(); + } + + // f5 (default) save key, hold shift to save movie + if(_keyonly(Hotkeys[HK_SAVE_STATE])) { + if(is_shift) { + movie_fname = 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""); + } else { + FCEUI_SaveState(NULL); + } + } + + // f7 to load state, Shift-f7 to load movie + if(_keyonly(Hotkeys[HK_LOAD_STATE])) { + if(is_shift) { + FCEUI_StopMovie(); + std::string fname; + fname = GetFilename("Open FM2 movie for playback...", false, "FM2 movies|*.fm2"); + if(fname != "") + { + if(fname.find(".fm2") != std::string::npos) + { + FCEUI_printf("Playing back movie located at %s\n", fname.c_str()); + FCEUI_LoadMovie(fname.c_str(), false, false, false); + } + else + { + FCEUI_printf("Only FM2 movies are supported.\n"); + } + } + } else { + FCEUI_LoadState(NULL); + } + } + } + + + if(_keyonly(Hotkeys[HK_DECREASE_SPEED])) { + DecreaseEmulationSpeed(); + } + + if(_keyonly(Hotkeys[HK_INCREASE_SPEED])) { + IncreaseEmulationSpeed(); + } + + if(_keyonly(Hotkeys[HK_TOGGLE_FRAME_DISPLAY])) { + FCEUI_MovieToggleFrameDisplay(); + } + + if(_keyonly(Hotkeys[HK_TOGGLE_INPUT_DISPLAY])) { + FCEUI_ToggleInputDisplay(); + extern int input_display; + g_config->setOption("SDL.InputDisplay", input_display); + } + + if(_keyonly(Hotkeys[HK_MOVIE_TOGGLE_RW])) { + FCEUI_SetMovieToggleReadOnly(!FCEUI_GetMovieToggleReadOnly()); + } + + #ifdef CREATE_AVI + if(_keyonly(Hotkeys[HK_MUTE_CAPTURE])) { + extern int mutecapture; + mutecapture ^= 1; + } + #endif + + if(_keyonly(Hotkeys[HK_PAUSE])) { + FCEUI_ToggleEmulationPause(); + } + + // Toggle throttling + NoWaiting &= ~1; + if(g_keyState[Hotkeys[HK_TURBO]]) { + NoWaiting |= 1; + } + + static bool frameAdvancing = false; + if(g_keyState[Hotkeys[HK_FRAME_ADVANCE]]) + { + if(frameAdvancing == false) + { + FCEUI_FrameAdvance(); + frameAdvancing = true; + } + } + else + { + if(frameAdvancing) + { + FCEUI_FrameAdvanceEnd(); + frameAdvancing = false; + } + } + + if(_keyonly(Hotkeys[HK_RESET])) { + FCEUI_ResetNES(); + } + //if(_keyonly(Hotkeys[HK_POWER])) { + // FCEUI_PowerNES(); + //} + + if(_keyonly(Hotkeys[HK_QUIT])) { + CloseGame(); + } + #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()); + } + #endif + + for(int i=0; i<10; i++) + if(_keyonly(Hotkeys[HK_SELECT_STATE_0 + i])) + FCEUI_SelectState(i, 1); + + if(_keyonly(Hotkeys[HK_BIND_STATE])) { + bindSavestate ^= 1; + FCEUI_DispMessage("Savestate binding to movie %sabled.",0, + bindSavestate ? "en" : "dis"); + } + + if(_keyonly(Hotkeys[HK_FA_LAG_SKIP])) { + frameAdvanceLagSkip ^= 1; + FCEUI_DispMessage("Skipping lag in Frame Advance %sabled.",0, + frameAdvanceLagSkip ? "en" : "dis"); + } + + if(_keyonly(Hotkeys[HK_LAG_COUNTER_DISPLAY])) { + lagCounterDisplay ^= 1; + } + + if (_keyonly(Hotkeys[HK_TOGGLE_SUBTITLE])) { + extern int movieSubtitles; + movieSubtitles ^= 1; + FCEUI_DispMessage("Movie subtitles o%s.",0, + movieSubtitles ? "n" : "ff"); + } + + // VS Unisystem games + if(gametype == GIT_VSUNI) { + // insert coin + if(_keyonly(Hotkeys[HK_VS_INSERT_COIN])) FCEUI_VSUniCoin(); + + // toggle dipswitch display + if(_keyonly(Hotkeys[HK_VS_TOGGLE_DIPSWITCH])) { + DIPS^=1; + FCEUI_VSUniToggleDIPView(); + } + if(!(DIPS&1)) goto DIPSless; + + // toggle the various dipswitches + if(keyonly(1)) FCEUI_VSUniToggleDIP(0); + if(keyonly(2)) FCEUI_VSUniToggleDIP(1); + if(keyonly(3)) FCEUI_VSUniToggleDIP(2); + if(keyonly(4)) FCEUI_VSUniToggleDIP(3); + if(keyonly(5)) FCEUI_VSUniToggleDIP(4); + if(keyonly(6)) FCEUI_VSUniToggleDIP(5); + if(keyonly(7)) FCEUI_VSUniToggleDIP(6); + if(keyonly(8)) FCEUI_VSUniToggleDIP(7); + } else { + static uint8 bbuf[32]; + static int bbuft; + static int barcoder = 0; + + if(keyonly(H)) FCEUI_NTSCSELHUE(); + if(keyonly(T)) FCEUI_NTSCSELTINT(); + + if (_keyonly(Hotkeys[HK_DECREASE_SPEED])) + FCEUI_NTSCDEC(); + if (_keyonly(Hotkeys[HK_INCREASE_SPEED])) + FCEUI_NTSCINC(); + + if((InputType[2] == SIFC_BWORLD) || (cspec == SIS_DATACH)) { + if(keyonly(F8)) { + barcoder ^= 1; + if(!barcoder) { + if(InputType[2] == SIFC_BWORLD) { + strcpy((char *)&BWorldData[1], (char *)bbuf); + BWorldData[0] = 1; + } else { + FCEUI_DatachSet(bbuf); + } + FCEUI_DispMessage("Barcode Entered",0); + } else { + bbuft = 0; + FCEUI_DispMessage("Enter Barcode",0); + } + } + } else { + barcoder = 0; + } + +#define SSM(x) \ +do { \ + if(barcoder) { \ + if(bbuft < 13) { \ + bbuf[bbuft++] = '0' + x; \ + bbuf[bbuft] = 0; \ + } \ + FCEUI_DispMessage("Barcode: %s",0, bbuf); \ + } \ +} while(0) + + DIPSless: + if(keyonly(0)) SSM(0); + if(keyonly(1)) SSM(1); + if(keyonly(2)) SSM(2); + if(keyonly(3)) SSM(3); + if(keyonly(4)) SSM(4); + if(keyonly(5)) SSM(5); + if(keyonly(6)) SSM(6); + if(keyonly(7)) SSM(7); + if(keyonly(8)) SSM(8); + if(keyonly(9)) SSM(9); +#undef SSM + } +} + +/** + * Return the state of the mouse buttons. Input 'd' is an array of 3 + * integers that store . + */ +void // removed static for a call in lua-engine.cpp +GetMouseData(uint32 (&d)[3]) +{ + int x,y; + uint32 t; + + // Don't get input when a movie is playing back + if(FCEUMOV_Mode(MOVIEMODE_PLAY)) + return; + + // retrieve the state of the mouse from SDL + t = SDL_GetMouseState(&x, &y); + + d[2] = 0; + if(t & SDL_BUTTON(1)) { + d[2] |= 0x1; + } + if(t & SDL_BUTTON(3)) { + d[2] |= 0x2; + } + + // get the mouse position from the SDL video driver + t = PtoV(x, y); + d[0] = t & 0xFFFF; + d[1] = (t >> 16) & 0xFFFF; +} + +/** + * Handles outstanding SDL events. + */ +static void +UpdatePhysicalInput() +{ + SDL_Event event; + + // loop, handling all pending events + while(SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_QUIT: + CloseGame(); + puts("Quit"); + break; + default: + // do nothing + break; + } + } + //SDL_PumpEvents(); +} + + +static int bcpv,bcpj; + +/** + * Begin configuring the buttons by placing the video and joystick + * subsystems into a well-known state. Button configuration really + * needs to be cleaned up after the new config system is in place. + */ +int +ButtonConfigBegin() +{ + SDL_Surface *screen; + + // XXX soules - why are we doing this right before KillVideo()? + SDL_QuitSubSystem(SDL_INIT_VIDEO); + + // shut down the video and joystick subsystems + bcpv=KillVideo(); + bcpj=KillJoysticks(); + + // reactivate the video subsystem + if(!SDL_WasInit(SDL_INIT_VIDEO)) { + if(SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) { + FCEUD_Message(SDL_GetError()); + return(0); + } + } + + // set the screen and notify the user of button configuration + screen = SDL_SetVideoMode(420, 200, 8, 0); + SDL_WM_SetCaption("Button Config",0); + + // XXX soules - why did we shut this down? + // initialize the joystick subsystem + InitJoysticks(); + + return(1); +} + +/** + * Finish configuring the buttons by reverting the video and joystick + * subsystems to their previous state. Button configuration really + * needs to be cleaned up after the new config system is in place. + */ +void +ButtonConfigEnd() +{ + extern FCEUGI *GameInfo; + + // shutdown the joystick and video subsystems + KillJoysticks(); + SDL_QuitSubSystem(SDL_INIT_VIDEO); + + // re-initialize joystick and video subsystems if they were active before + if(!bcpv) { + InitVideo(GameInfo); + } + if(!bcpj) { + InitJoysticks(); + } +} + +/** + * Tests to see if a specified button is currently pressed. + */ +static int +DTestButton(ButtConfig *bc) +{ + int x; + + for(x = 0; x < bc->NumC; x++) { + if(bc->ButtType[x] == BUTTC_KEYBOARD) { + #if SDL_VERSION_ATLEAST(1,3,0) + if(g_keyState[SDL_GetScancodeFromKey((SDLKey)bc->ButtonNum[x])]) { + #else + if(g_keyState[bc->ButtonNum[x]]) { + #endif + return(1); + } + } else if(bc->ButtType[x] == BUTTC_JOYSTICK) { + if(DTestButtonJoy(bc)) { + return(1); + } + } + } + return(0); +} + + + + +#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1} +#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2} +#define MKZ() {{0},{0},{0},0} +#define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} + +ButtConfig GamePadConfig[4][10]={ + /* Gamepad 1 */ + { MK(KP3), MK(KP2), MK(SLASH), MK(ENTER), + MK(W), MK(Z), MK(A), MK(S), MKZ(), MKZ() }, + + /* Gamepad 2 */ + GPZ(), + + /* Gamepad 3 */ + GPZ(), + + /* Gamepad 4 */ + GPZ() +}; + +/** + * Update the status of the gamepad input devices. + */ +static void +UpdateGamepad(void) +{ + // don't update during movie playback + if(FCEUMOV_Mode(MOVIEMODE_PLAY)) { + return; + } + + static int rapid=0; + uint32 JS=0; + int x; + int wg; + + rapid ^= 1; + + // go through each of the four game pads + for(wg = 0; wg < 4; wg++) { + // the 4 directional buttons, start, select, a, b + for(x = 0; x < 8; x++) { + if(DTestButton(&GamePadConfig[wg][x])) { + JS |= (1 << x) << (wg << 3); + } + } + + // rapid-fire a, rapid-fire b + if(rapid) { + for(x = 0; x < 2; x++) { + if(DTestButton(&GamePadConfig[wg][8+x])) { + JS |= (1 << x) << (wg << 3); + } + } + } + } + + // for(x=0;x<32;x+=8) /* Now, test to see if anything weird(up+down at same time) + // is happening, and correct */ + // { + // if((JS & (0xC0<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) { + bc->ButtType[wb] = BUTTC_JOYSTICK; + bc->DeviceNum[wb] = event.jhat.which; + bc->ButtonNum[wb] = (0x2000 | ((event.jhat.hat & 0x1F) << 8) | + event.jhat.value); + 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; + } + } 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); + } + } + break; + } + } + + return(0); +} + +/** + * This function takes in button inputs until either it sees two of + * the same button presses in a row or gets four inputs and then saves + * the total number of button presses. Each of the keys pressed is + * used as input for the specified button, thus allowing up to four + * possible settings for each input button. + */ +void +ConfigButton(char *text, + ButtConfig *bc) +{ + uint8 buf[256]; + int wc; + + for(wc = 0; wc < MAXBUTTCONFIG; wc++) { + sprintf((char *)buf, "%s (%d)", text, wc + 1); + 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]) { + break; + } + } + bc->NumC = wc; +} + +/** + * Update the button configuration for a specified device. + */ +extern Config *g_config; + +void +ConfigDevice(int which, + int arg) +{ + char buf[256]; + int x; + std::string prefix; + char *str[10]={"A","B","SELECT","START","UP","DOWN","LEFT","RIGHT","Rapid A","Rapid B"}; + + // XXX soules - set the configuration options so that later calls + // don't override these. This is a temp hack until I + // can clean up this file. + + 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]); + + 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]); + + 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]); + + 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; + + 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]); + } + + 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(); +} + + +/** + * Update the button configuration for a device, specified by a text string. + */ +void +InputCfg(const std::string &text) +{ + if(text.find("gamepad") != std::string::npos) { + int device = (text[strlen("gamepad")] - '1'); + if(device<0 || device>3) { + FCEUD_PrintError("Invalid gamepad device specified; must be one of gamepad1 through gamepad4"); + exit(-1); + } + ConfigDevice(FCFGD_GAMEPAD, device); + } else if(text.find("powerpad") != std::string::npos) { + int device = (text[strlen("powerpad")] - '1'); + if(device<0 || device>1) { + FCEUD_PrintError("Invalid powerpad device specified; must be powerpad1 or powerpad2"); + exit(-1); + } + ConfigDevice(FCFGD_POWERPAD, device); + } else if(text.find("hypershot") != std::string::npos) { + ConfigDevice(FCFGD_HYPERSHOT, 0); + } else if(text.find("quizking") != std::string::npos) { + ConfigDevice(FCFGD_QUIZKING, 0); + } +} + + +/** + * Hack to map the new configuration onto the existing button + * configuration management. Will probably want to change this in the + * future - soules. + */ +void +UpdateInput(Config *config) +{ + char buf[64]; + std::string device, prefix; + + for(unsigned int i = 0; i < 3; i++) { + snprintf(buf, 64, "SDL.Input.%d", i); + config->getOption(buf, &device); + + if(device == "None") { + UsrInputType[i] = SI_NONE; + } else if(device.find("GamePad") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_GAMEPAD : (int)SIFC_NONE; + } else if(device.find("PowerPad.0") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_POWERPADA : (int)SIFC_NONE; + } else if(device.find("PowerPad.1") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_POWERPADB : (int)SIFC_NONE; + } else if(device.find("QuizKing") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_QUIZKING; + } else if(device.find("HyperShot") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_HYPERSHOT; + } else if(device.find("Mahjong") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_MAHJONG; + } else if(device.find("TopRider") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_TOPRIDER; + } else if(device.find("FTrainer") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_FTRAINERA; + } else if(device.find("FamilyKeyBoard") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_FKB; + } else if(device.find("OekaKids") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_OEKAKIDS; + } else if(device.find("Arkanoid") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_ARKANOID : (int)SIFC_ARKANOID; + } else if(device.find("Shadow") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_SHADOW; + } else if(device.find("Zapper") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_ZAPPER : (int)SIFC_NONE; + } else if(device.find("BWorld") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_BWORLD; + } else if(device.find("4Player") != std::string::npos) { + UsrInputType[i] = (i < 2) ? (int)SI_NONE : (int)SIFC_4PLAYER; + } else { + // Unknown device + UsrInputType[i] = SI_NONE; + } + } + + // update each of the devices' configuration structure + // XXX soules - this is temporary until this file is cleaned up to + // simplify the interface between configuration and + // structure data. This will likely include the + // removal of multiple input buttons for a single + // input device key. + int type, devnum, button; + + // gamepad 0 - 3 + for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) { + char buf[64]; + snprintf(buf, 20, "SDL.Input.GamePad.%d.", i); + prefix = buf; + + config->getOption(prefix + "DeviceType", &device); + if(device.find("Keyboard") != std::string::npos) { + type = BUTTC_KEYBOARD; + } else if(device.find("Joystick") != std::string::npos) { + type = BUTTC_JOYSTICK; + } else { + type = 0; + } + + config->getOption(prefix + "DeviceNum", &devnum); + for(unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) { + config->getOption(prefix + GamePadNames[j], &button); + + GamePadConfig[i][j].ButtType[0] = type; + GamePadConfig[i][j].DeviceNum[0] = devnum; + GamePadConfig[i][j].ButtonNum[0] = button; + GamePadConfig[i][j].NumC = 1; + } + } + + // PowerPad 0 - 1 + for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) { + char buf[64]; + snprintf(buf, 20, "SDL.Input.PowerPad.%d.", i); + prefix = buf; + + config->getOption(prefix + "DeviceType", &device); + if(device.find("Keyboard") != std::string::npos) { + type = BUTTC_KEYBOARD; + } else if(device.find("Joystick") != std::string::npos) { + type = BUTTC_JOYSTICK; + } else { + type = 0; + } + + config->getOption(prefix + "DeviceNum", &devnum); + for(unsigned int j = 0; j < POWERPAD_NUM_BUTTONS; j++) { + config->getOption(prefix + PowerPadNames[j], &button); + + powerpadsc[i][j].ButtType[0] = type; + powerpadsc[i][j].DeviceNum[0] = devnum; + powerpadsc[i][j].ButtonNum[0] = button; + powerpadsc[i][j].NumC = 1; + } + } + + // QuizKing + prefix = "SDL.Input.QuizKing."; + config->getOption(prefix + "DeviceType", &device); + if(device.find("Keyboard") != std::string::npos) { + type = BUTTC_KEYBOARD; + } else if(device.find("Joystick") != std::string::npos) { + type = BUTTC_JOYSTICK; + } else { + type = 0; + } + config->getOption(prefix + "DeviceNum", &devnum); + for(unsigned int j = 0; j < QUIZKING_NUM_BUTTONS; j++) { + config->getOption(prefix + QuizKingNames[j], &button); + + QuizKingButtons[j].ButtType[0] = type; + QuizKingButtons[j].DeviceNum[0] = devnum; + QuizKingButtons[j].ButtonNum[0] = button; + QuizKingButtons[j].NumC = 1; + } + + // HyperShot + prefix = "SDL.Input.HyperShot."; + config->getOption(prefix + "DeviceType", &device); + if(device.find("Keyboard") != std::string::npos) { + type = BUTTC_KEYBOARD; + } else if(device.find("Joystick") != std::string::npos) { + type = BUTTC_JOYSTICK; + } else { + type = 0; + } + config->getOption(prefix + "DeviceNum", &devnum); + for(unsigned int j = 0; j < HYPERSHOT_NUM_BUTTONS; j++) { + config->getOption(prefix + HyperShotNames[j], &button); + + HyperShotButtons[j].ButtType[0] = type; + HyperShotButtons[j].DeviceNum[0] = devnum; + HyperShotButtons[j].ButtonNum[0] = button; + HyperShotButtons[j].NumC = 1; + } + + // Mahjong + prefix = "SDL.Input.Mahjong."; + config->getOption(prefix + "DeviceType", &device); + if(device.find("Keyboard") != std::string::npos) { + type = BUTTC_KEYBOARD; + } else if(device.find("Joystick") != std::string::npos) { + type = BUTTC_JOYSTICK; + } else { + type = 0; + } + config->getOption(prefix + "DeviceNum", &devnum); + for(unsigned int j = 0; j < MAHJONG_NUM_BUTTONS; j++) { + config->getOption(prefix + MahjongNames[j], &button); + + MahjongButtons[j].ButtType[0] = type; + MahjongButtons[j].DeviceNum[0] = devnum; + MahjongButtons[j].ButtonNum[0] = button; + MahjongButtons[j].NumC = 1; + } + + // TopRider + prefix = "SDL.Input.TopRider."; + config->getOption(prefix + "DeviceType", &device); + if(device.find("Keyboard") != std::string::npos) { + type = BUTTC_KEYBOARD; + } else if(device.find("Joystick") != std::string::npos) { + type = BUTTC_JOYSTICK; + } else { + type = 0; + } + config->getOption(prefix + "DeviceNum", &devnum); + for(unsigned int j = 0; j < TOPRIDER_NUM_BUTTONS; j++) { + config->getOption(prefix + TopRiderNames[j], &button); + + TopRiderButtons[j].ButtType[0] = type; + TopRiderButtons[j].DeviceNum[0] = devnum; + TopRiderButtons[j].ButtonNum[0] = button; + TopRiderButtons[j].NumC = 1; + } + + // FTrainer + prefix = "SDL.Input.FTrainer."; + config->getOption(prefix + "DeviceType", &device); + if(device.find("Keyboard") != std::string::npos) { + type = BUTTC_KEYBOARD; + } else if(device.find("Joystick") != std::string::npos) { + type = BUTTC_JOYSTICK; + } else { + type = 0; + } + config->getOption(prefix + "DeviceNum", &devnum); + for(unsigned int j = 0; j < FTRAINER_NUM_BUTTONS; j++) { + config->getOption(prefix + FTrainerNames[j], &button); + + FTrainerButtons[j].ButtType[0] = type; + FTrainerButtons[j].DeviceNum[0] = devnum; + FTrainerButtons[j].ButtonNum[0] = button; + FTrainerButtons[j].NumC = 1; + } + + // FamilyKeyBoard + prefix = "SDL.Input.FamilyKeyBoard."; + config->getOption(prefix + "DeviceType", &device); + if(device.find("Keyboard") != std::string::npos) { + type = BUTTC_KEYBOARD; + } else if(device.find("Joystick") != std::string::npos) { + type = BUTTC_JOYSTICK; + } else { + type = 0; + } + config->getOption(prefix + "DeviceNum", &devnum); + for(unsigned int j = 0; j < FAMILYKEYBOARD_NUM_BUTTONS; j++) { + config->getOption(prefix + FamilyKeyBoardNames[j], &button); + + fkbmap[j].ButtType[0] = type; + fkbmap[j].DeviceNum[0] = devnum; + fkbmap[j].ButtonNum[0] = button; + fkbmap[j].NumC = 1; + } +} +// Definitions from main.h: +// GamePad defaults +const char *GamePadNames[GAMEPAD_NUM_BUTTONS] = + {"A", "B", "Select", "Start", + "Up", "Down", "Left", "Right", "TurboA", "TurboB"}; +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 } }; + +// PowerPad defaults +const char *PowerPadNames[POWERPAD_NUM_BUTTONS] = + {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B"}; +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 } }; + +// QuizKing defaults +const char *QuizKingNames[QUIZKING_NUM_BUTTONS] = + { "0", "1", "2", "3", "4", "5" }; +const char *DefaultQuizKingDevice = "Keyboard"; +const int DefaultQuizKing[QUIZKING_NUM_BUTTONS] = + { SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y }; + +// HyperShot defaults +const char *HyperShotNames[HYPERSHOT_NUM_BUTTONS] = + { "0", "1", "2", "3" }; +const char *DefaultHyperShotDevice = "Keyboard"; +const int DefaultHyperShot[HYPERSHOT_NUM_BUTTONS] = + { SDLK_q, SDLK_w, SDLK_e, SDLK_r }; + +// Mahjong defaults +const char *MahjongNames[MAHJONG_NUM_BUTTONS] = + { "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_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 }; + +// TopRider defaults +const char *TopRiderNames[TOPRIDER_NUM_BUTTONS] = + { "0", "1", "2", "3", "4", "5", "6", "7" }; +const char *DefaultTopRiderDevice = "Keyboard"; +const int DefaultTopRider[TOPRIDER_NUM_BUTTONS] = + { SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y, SDLK_u, SDLK_i }; + +// FTrainer defaults +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_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", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", + "MINUS", "EQUAL", "BACKSLASH", "BACKSPACE", + "ESCAPE", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", + "P", "GRAVE", "BRACKET_LEFT", "ENTER", + "LEFTCONTROL", "A", "S", "D", "F", "G", "H", "J", "K", + "L", "SEMICOLON", "APOSTROPHE", "BRACKET_RIGHT", "INSERT", + "LEFTSHIFT", "Z", "X", "C", "V", "B", "N", "M", "COMMA", + "PERIOD", "SLASH", "RIGHTALT", "RIGHTSHIFT", "LEFTALT", "SPACE", + "DELETE", "END", "PAGEDOWN", + "CURSORUP", "CURSORLEFT", "CURSORRIGHT", "CURSORDOWN" }; +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_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, + SDLK_ESCAPE, SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y, SDLK_u, + SDLK_i, SDLK_o, SDLK_p, SDLK_BACKQUOTE, SDLK_LEFTBRACKET, SDLK_RETURN, + SDLK_LCTRL, SDLK_a, SDLK_s, SDLK_d, SDLK_f, SDLK_g, SDLK_h, SDLK_j, + SDLK_k, SDLK_l, SDLK_SEMICOLON, SDLK_QUOTE, SDLK_RIGHTBRACKET, + SDLK_INSERT, SDLK_LSHIFT, SDLK_z, SDLK_x, SDLK_c, SDLK_v, SDLK_b, + SDLK_n, SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH, SDLK_RALT, + SDLK_RSHIFT, SDLK_LALT, SDLK_SPACE, SDLK_DELETE, SDLK_END, SDLK_PAGEDOWN, + SDLK_UP, SDLK_LEFT, SDLK_RIGHT, SDLK_DOWN }; + diff --git a/src/drivers/sdl/sdl-sound.cpp b/src/drivers/sdl/sdl-sound.cpp index 8dd71a86..55537743 100644 --- a/src/drivers/sdl/sdl-sound.cpp +++ b/src/drivers/sdl/sdl-sound.cpp @@ -246,7 +246,7 @@ FCEUD_SoundVolumeAdjust(int n) FCEUI_SetSoundVolume(soundvolume); g_config->setOption("SDL.SoundVolume", soundvolume); - FCEU_DispMessage("Sound volume %d.", soundvolume); + FCEU_DispMessage("Sound volume %d.",0, soundvolume); } /** @@ -261,10 +261,10 @@ FCEUD_SoundToggle(void) s_mute = 0; FCEUI_SetSoundVolume(soundvolume); - FCEU_DispMessage("Sound mute off."); + FCEU_DispMessage("Sound mute off.",0); } else { s_mute = 1; FCEUI_SetSoundVolume(0); - FCEU_DispMessage("Sound mute on."); + FCEU_DispMessage("Sound mute on.",0); } } diff --git a/src/drivers/sdl/sdl-throttle.cpp b/src/drivers/sdl/sdl-throttle.cpp index 90913753..cb2b8e2d 100644 --- a/src/drivers/sdl/sdl-throttle.cpp +++ b/src/drivers/sdl/sdl-throttle.cpp @@ -98,7 +98,7 @@ void IncreaseEmulationSpeed(void) RefreshThrottleFPS(); - FCEU_DispMessage("emulation speed %.1f%%", g_fpsScale*100.0); + FCEU_DispMessage("emulation speed %.1f%%",0, g_fpsScale*100.0); } /** @@ -112,7 +112,7 @@ void DecreaseEmulationSpeed(void) RefreshThrottleFPS(); - FCEU_DispMessage("emulation speed %.1f%%", g_fpsScale*100.0); + FCEU_DispMessage("emulation speed %.1f%%",0, g_fpsScale*100.0); } /** @@ -146,5 +146,5 @@ FCEUD_SetEmulationSpeed(int cmd) RefreshThrottleFPS(); - FCEU_DispMessage("emulation speed %.1f%%", g_fpsScale*100.0); + FCEU_DispMessage("emulation speed %.1f%%",0, g_fpsScale*100.0); } diff --git a/src/drivers/sdl/sdl.cpp b/src/drivers/sdl/sdl.cpp index 491b03c4..62bb4569 100644 --- a/src/drivers/sdl/sdl.cpp +++ b/src/drivers/sdl/sdl.cpp @@ -853,7 +853,7 @@ void FCEUD_PrintError(const char *errormsg) // dummy functions -#define DUMMY(__f) void __f(void) {printf("%s\n", #__f); FCEU_DispMessage("Not implemented.");} +#define DUMMY(__f) void __f(void) {printf("%s\n", #__f); FCEU_DispMessage("Not implemented.",0);} DUMMY(FCEUD_HideMenuToggle) DUMMY(FCEUD_MovieReplayFrom) DUMMY(FCEUD_ToggleStatusIcon) diff --git a/src/drivers/sdl/unix-netplay.cpp b/src/drivers/sdl/unix-netplay.cpp index 156c3b5b..32e6d409 100644 --- a/src/drivers/sdl/unix-netplay.cpp +++ b/src/drivers/sdl/unix-netplay.cpp @@ -117,7 +117,7 @@ FCEUD_NetworkConnect(void) if(TSocket < 0) { char* s = "Error creating stream socket."; puts(s); - FCEU_DispMessage(s); + FCEU_DispMessage(s,0); FCEUD_NetworkClose(); return 0; } @@ -146,7 +146,7 @@ FCEUD_NetworkConnect(void) phostentb = gethostbyname(server.c_str()); if(!phostentb) { puts("Error getting host network information."); - FCEU_DispMessage("Error getting host info"); + FCEU_DispMessage("Error getting host info",0); close(TSocket); FCEUD_NetworkClose(); return(0); @@ -159,7 +159,7 @@ FCEUD_NetworkConnect(void) error = connect(TSocket, (struct sockaddr *)&sockin, sizeof(sockin)); if(error < 0) { puts("Error connecting to remote host."); - FCEU_DispMessage("Error connecting to server"); + FCEU_DispMessage("Error connecting to server",0); close(TSocket); FCEUD_NetworkClose(); return 0; @@ -228,7 +228,7 @@ FCEUD_NetworkConnect(void) netdivisor = buf[0]; puts("*** Connection established."); - FCEU_DispMessage("Connection established."); + FCEU_DispMessage("Connection established.",0); FCEUDnetplay = 1; FCEUI_NetplayStart(localPlayers, netdivisor); diff --git a/src/drivers/win/aviout.cpp b/src/drivers/win/aviout.cpp index 83ddab25..1c6c9c71 100644 --- a/src/drivers/win/aviout.cpp +++ b/src/drivers/win/aviout.cpp @@ -359,7 +359,7 @@ int FCEUI_AviBegin(const char* fname) // Don't display at file splits if(!avi_segnum) - FCEU_DispMessage("AVI recording started."); + FCEU_DispMessage("AVI recording started.",0); strncpy(saved_cur_avi_fnameandext,fname,MAX_PATH); strncpy(saved_avi_fname,fname,MAX_PATH); @@ -423,7 +423,7 @@ void FCEUI_AviEnd() // Don't display if we're just starting another segment if(avi_file->tBytes <= 2097152000) - FCEU_DispMessage("AVI recording ended."); + FCEU_DispMessage("AVI recording ended.",0); avi_destroy(&avi_file); } diff --git a/src/drivers/win/input.cpp b/src/drivers/win/input.cpp index a3306cf6..66e0afe3 100644 --- a/src/drivers/win/input.cpp +++ b/src/drivers/win/input.cpp @@ -295,19 +295,26 @@ void UpdateGamepad() } } - char inputstr [64]; + char inputstr [45]; { uint32 c = JSAutoHeld; - sprintf(inputstr, "%c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c", + sprintf(inputstr, "1%c%c%c%c%c%c%c%c 2%c%c%c%c%c%c%c%c\n 3%c%c%c%c%c%c%c%c 4%c%c%c%c%c%c%c%c", (c&0x40)?'<':' ', (c&0x10)?'^':' ', (c&0x80)?'>':' ', (c&0x20)?'v':' ', (c&0x01)?'A':' ', (c&0x02)?'B':' ', (c&0x08)?'S':' ', (c&0x04)?'s':' ', (c&0x4000)?'<':' ', (c&0x1000)?'^':' ', (c&0x8000)?'>':' ', (c&0x2000)?'v':' ', (c&0x0100)?'A':' ', (c&0x0200)?'B':' ', (c&0x0800)?'S':' ', (c&0x0400)?'s':' ', - (c&0x40000)?'A':' '); - if(!(c&0xff00)) - inputstr[8] = '\0'; + (c&0x400000)?'<':' ', (c&0x100000)?'^':' ', (c&0x800000)?'>':' ', (c&0x200000)?'v':' ', + (c&0x010000)?'A':' ', (c&0x020000)?'B':' ', (c&0x080000)?'S':' ', (c&0x040000)?'s':' ', + (c&0x40000000)?'<':' ', (c&0x10000000)?'^':' ', (c&0x80000000)?'>':' ', (c&0x20000000)?'v':' ', + (c&0x01000000)?'A':' ', (c&0x02000000)?'B':' ', (c&0x08000000)?'S':' ', (c&0x04000000)?'s':' '); + if(!(c&0xffffff00)) + inputstr[9] = '\0'; + if(!(c&0xffff0000)) + inputstr[19] = '\0'; + if(!(c&0xff000000)) + inputstr[30] = '\0'; } - FCEU_DispMessage("Held: %s", inputstr); + FCEU_DispMessage("Held: %s", 40, inputstr); } else { @@ -317,7 +324,7 @@ void UpdateGamepad() if(autoHoldReset) { - FCEU_DispMessage("Held: "); + FCEU_DispMessage("Held: ",0); JSAutoHeld = 0; JSAutoHeldAffected = 0; autoHoldRefire = 0; @@ -1604,7 +1611,7 @@ void FCEUI_UseInputPreset(int preset) case 1: memcpy(GamePadConfig, GamePadPreset2, sizeof(GamePadPreset2)); break; case 2: memcpy(GamePadConfig, GamePadPreset3, sizeof(GamePadPreset3)); break; } - FCEU_DispMessage("Using input preset %d.",preset+1); + FCEU_DispMessage("Using input preset %d.",0,preset+1); } static void PresetExport(int preset) diff --git a/src/drivers/win/movieoptions.cpp b/src/drivers/win/movieoptions.cpp index 61cfd72c..6c5300b4 100644 --- a/src/drivers/win/movieoptions.cpp +++ b/src/drivers/win/movieoptions.cpp @@ -84,8 +84,8 @@ BOOL CALLBACK MovieOptionsCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM l case IDC_MOVIE_DISPLAYSUBTITLES: movieSubtitles ^= 1; - if (movieSubtitles) FCEU_DispMessage("Movie subtitles on"); - else FCEU_DispMessage("Movie subtitles off"); + if (movieSubtitles) FCEU_DispMessage("Movie subtitles on",0); + else FCEU_DispMessage("Movie subtitles off",0); break; case IDC_MOVIE_SUBTITLESINAVI: diff --git a/src/drivers/win/sound.cpp b/src/drivers/win/sound.cpp index ba6a5f91..61e115c8 100644 --- a/src/drivers/win/sound.cpp +++ b/src/drivers/win/sound.cpp @@ -812,12 +812,12 @@ void FCEUD_SoundToggle(void) if(mute) { mute = false; - FCEU_DispMessage("Sound unmuted"); + FCEU_DispMessage("Sound unmuted",0); } else { mute = true; - FCEU_DispMessage("Sound muted"); + FCEU_DispMessage("Sound muted",0); } } @@ -831,5 +831,5 @@ void FCEUD_SoundVolumeAdjust(int n) } mute = false; FCEUI_SetSoundVolume(soundvolume); - FCEU_DispMessage("Sound volume %d.", soundvolume); + FCEU_DispMessage("Sound volume %d.",0, soundvolume); } diff --git a/src/drivers/win/throttle.cpp b/src/drivers/win/throttle.cpp index 0557166e..bcae561d 100644 --- a/src/drivers/win/throttle.cpp +++ b/src/drivers/win/throttle.cpp @@ -148,5 +148,5 @@ void FCEUD_SetEmulationSpeed(int cmd) RefreshThrottleFPS(); - FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8); + FCEU_DispMessage("emulation speed %d%%",0,(fps_scale*100)>>8); } diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 02d11812..90e7243b 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -2154,7 +2154,7 @@ adelikat: Outsourced this to a remappable hotkey if(wParam==VK_SCROLL) { cidisabled^=1; - FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis"); + FCEUI_DispMessage("Family Keyboard %sabled.",0,cidisabled?"en":"dis"); } if(cidisabled) break; // Hopefully this won't break DInput... @@ -2164,7 +2164,7 @@ adelikat: Outsourced this to a remappable hotkey if(wParam==VK_SCROLL) { cidisabled^=1; - FCEUI_DispMessage("Subor Keyboard %sabled.",cidisabled?"en":"dis"); + FCEUI_DispMessage("Subor Keyboard %sabled.",0,cidisabled?"en":"dis"); } if(cidisabled) break; diff --git a/src/fceu.h b/src/fceu.h index 4a97430d..7e347a73 100644 --- a/src/fceu.h +++ b/src/fceu.h @@ -112,7 +112,7 @@ bool CheckFileExists(const char* filename); //Receives a filename (fullpath) and void FCEU_PrintError(char *format, ...); void FCEU_printf(char *format, ...); -void FCEU_DispMessage(char *format, ...); +void FCEU_DispMessage(char *format, int disppos, ...); void FCEU_DispMessageOnMovie(char *format, ...); void SetNESDeemph(uint8 d, int force); diff --git a/src/fds.cpp b/src/fds.cpp index e3d40f78..9f3f861e 100644 --- a/src/fds.cpp +++ b/src/fds.cpp @@ -157,17 +157,17 @@ void FCEU_FDSInsert(void) if(TotalSides==0) { - FCEU_DispMessage("Not FDS; can't eject disk."); + FCEU_DispMessage("Not FDS; can't eject disk.",0); return; } if(InDisk==255) { - FCEU_DispMessage("Disk %d Side %s Inserted",SelectDisk>>1,(SelectDisk&1)?"B":"A"); + FCEU_DispMessage("Disk %d Side %s Inserted",0,SelectDisk>>1,(SelectDisk&1)?"B":"A"); InDisk=SelectDisk; } else { - FCEU_DispMessage("Disk %d Side %s Ejected",SelectDisk>>1,(SelectDisk&1)?"B":"A"); + FCEU_DispMessage("Disk %d Side %s Ejected",0,SelectDisk>>1,(SelectDisk&1)?"B":"A"); InDisk=255; } } @@ -186,16 +186,16 @@ void FCEU_FDSSelect(void) if(TotalSides==0) { - FCEU_DispMessage("Not FDS; can't select disk."); + FCEU_DispMessage("Not FDS; can't select disk.",0); return; } if(InDisk!=255) { - FCEU_DispMessage("Eject disk before selecting."); + FCEU_DispMessage("Eject disk before selecting.",0); return; } SelectDisk=((SelectDisk+1)%TotalSides)&3; - FCEU_DispMessage("Disk %d Side %c Selected",SelectDisk>>1,(SelectDisk&1)?'B':'A'); + FCEU_DispMessage("Disk %d Side %c Selected",0,SelectDisk>>1,(SelectDisk&1)?'B':'A'); } static void FDSFix(int a) diff --git a/src/filter.cpp b/src/filter.cpp index 2a0ebf84..35d6e183 100644 --- a/src/filter.cpp +++ b/src/filter.cpp @@ -56,7 +56,7 @@ void SexyFilter(int32 *in, int32 *out, int32 count) mul2=(24<<16)/FSettings.SndRate; vmul=(FSettings.SoundVolume<<16)*3/4/100; - //FCEU_DispMessage("SoundVolume %d, vmul %d",FSettings.SoundVolume,vmul); + //FCEU_DispMessage("SoundVolume %d, vmul %d",0,FSettings.SoundVolume,vmul); if(FSettings.soundq) vmul/=4; else vmul*=2; /* TODO: Increase volume in low quality sound rendering code itself */ diff --git a/src/input.cpp b/src/input.cpp index aa761b30..0e15fabc 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -799,7 +799,7 @@ void FCEUI_HandleEmuCommands(TestCommandState* testfn) static void CommandUnImpl(void) { - FCEU_DispMessage("command '%s' unimplemented.", FCEUI_CommandTable[i].name); + FCEU_DispMessage("command '%s' unimplemented.",0, FCEUI_CommandTable[i].name); } static void CommandToggleDip(void) @@ -1043,8 +1043,8 @@ static void CloseRom(void) static void MovieSubtitleToggle(void) { movieSubtitles ^= 1; - if (movieSubtitles) FCEU_DispMessage("Movie subtitles on"); - else FCEU_DispMessage("Movie subtitles off"); + if (movieSubtitles) FCEU_DispMessage("Movie subtitles on",0); + else FCEU_DispMessage("Movie subtitles off",0); } static void UndoRedoSavestate(void) diff --git a/src/lua-engine.cpp b/src/lua-engine.cpp index 45790c87..e04f86c6 100644 --- a/src/lua-engine.cpp +++ b/src/lua-engine.cpp @@ -408,7 +408,7 @@ static int emu_unpause(lua_State *L) { static int emu_message(lua_State *L) { const char *msg = luaL_checkstring(L,1); - FCEU_DispMessage("%s", msg); + FCEU_DispMessage("%s",0, msg); return 0; @@ -4814,7 +4814,7 @@ void FCEU_LuaFrameBoundary() { } else { FCEU_LuaOnStop(); - FCEU_DispMessage("Script died of natural causes.\n"); + FCEU_DispMessage("Script died of natural causes.\n",0); } // Past here, the nes actually runs, so any Lua code is called mid-frame. We must @@ -4981,7 +4981,7 @@ int FCEU_LoadLuaCode(const char *filename, const char *arg) { void FCEU_ReloadLuaCode() { if (!luaScriptName) - FCEU_DispMessage("There's no script to reload."); + FCEU_DispMessage("There's no script to reload.",0); else FCEU_LoadLuaCode(luaScriptName); } diff --git a/src/movie.cpp b/src/movie.cpp index 0277b7b5..b9caff35 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -764,7 +764,7 @@ static void StopPlayback() /// Stop movie recording static void StopRecording() { - FCEU_DispMessage("Movie recording stopped."); + FCEU_DispMessage("Movie recording stopped.",0); movieMode = MOVIEMODE_INACTIVE; @@ -854,13 +854,13 @@ void FCEUMOV_EnterTasEdit() currMovieData.TryDumpIncremental(); - FCEU_DispMessage("Tasedit engaged"); + FCEU_DispMessage("Tasedit engaged",0); } void FCEUMOV_ExitTasEdit() { movieMode = MOVIEMODE_INACTIVE; - FCEU_DispMessage("Tasedit disengaged"); + FCEU_DispMessage("Tasedit disengaged",0); currMovieData = MovieData(); } @@ -964,15 +964,15 @@ bool FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _paus currRerecordCount = currMovieData.rerecordCount; if(movie_readonly) - FCEU_DispMessage("Replay started Read-Only."); + FCEU_DispMessage("Replay started Read-Only.",0); else - FCEU_DispMessage("Replay started Read+Write."); + FCEU_DispMessage("Replay started Read+Write.",0); } #ifdef CREATE_AVI if(LoggingEnabled) { - FCEU_DispMessage("Video recording enabled.\n"); + FCEU_DispMessage("Video recording enabled.\n",0); LoggingEnabled = 2; } #endif @@ -1040,7 +1040,7 @@ void FCEUI_SaveMovie(const char *fname, EMOVIE_FLAG flags, std::wstring author) movie_readonly = false; currRerecordCount = 0; - FCEU_DispMessage("Movie recording started."); + FCEU_DispMessage("Movie recording started.",0); } static int _currCommand = 0; @@ -1049,7 +1049,7 @@ static int _currCommand = 0; // Stop movie playback without closing the movie. static void FinishPlayback() { - FCEU_DispMessage("Movie finished playing."); + FCEU_DispMessage("Movie finished playing.",0); movieMode = MOVIEMODE_FINISHED; } @@ -1122,7 +1122,7 @@ void FCEUMOV_AddInputState() if(FCEUMOV_ShouldPause() && FCEUI_EmulationPaused()==0) { FCEUI_ToggleEmulationPause(); - FCEU_DispMessage("Paused at specified movie frame"); + FCEU_DispMessage("Paused at specified movie frame",0); } } @@ -1435,20 +1435,20 @@ void FCEUI_SetMovieToggleReadOnly(bool which) if (!movie_readonly) //If not already set { movie_readonly = true; - FCEU_DispMessage("Movie is now Read-Only."); + FCEU_DispMessage("Movie is now Read-Only.",0); } else //Else restate message - FCEU_DispMessage("Movie is Read-Only."); + FCEU_DispMessage("Movie is Read-Only.",0); } else //If set to read+write { if (movie_readonly) //If not already set { movie_readonly = false; - FCEU_DispMessage("Movie is now Read+Write."); + FCEU_DispMessage("Movie is now Read+Write.",0); } else //Else restate message - FCEU_DispMessage("Movie is Read+Write."); + FCEU_DispMessage("Movie is Read+Write.",0); } } void FCEUI_MovieToggleReadOnly() @@ -1467,7 +1467,7 @@ void FCEUI_MovieToggleReadOnly() else if (movieMode == MOVIEMODE_FINISHED) strcat(message, " (finished)"); - FCEU_DispMessage(message); + FCEU_DispMessage(message,0); movie_readonly = !movie_readonly; } @@ -1481,7 +1481,7 @@ void FCEUI_MoviePlayFromBeginning(void) currFrameCounter=0; movieMode = MOVIEMODE_PLAY; - FCEU_DispMessage("Movie is now Read-Only. Playing from beginning."); + FCEU_DispMessage("Movie is now Read-Only. Playing from beginning.",0); } } @@ -1561,6 +1561,7 @@ void FCEU_DisplaySubtitles(char *format, ...) subtitleMessage.howlong = 300; subtitleMessage.isMovieMessage = subtitlesOnAVI; + subtitleMessage.linesFromBottom = 0; } void FCEUI_CreateMovieFile(std::string fn) @@ -1622,9 +1623,9 @@ void FCEUI_MakeBackupMovie(bool dispMessage) if (dispMessage) //If we should inform the user { if (overflow) - FCEUI_DispMessage("Backup overflow, overwriting %s",backupFn.c_str()); //Inform user of overflow + FCEUI_DispMessage("Backup overflow, overwriting %s",0,backupFn.c_str()); //Inform user of overflow else - FCEUI_DispMessage("%s created",backupFn.c_str()); //Inform user of backup filename + FCEUI_DispMessage("%s created",0,backupFn.c_str()); //Inform user of backup filename } } diff --git a/src/netplay.cpp b/src/netplay.cpp index e39744d7..102870f8 100644 --- a/src/netplay.cpp +++ b/src/netplay.cpp @@ -50,7 +50,7 @@ static int netdcount; static void NetError(void) { - FCEU_DispMessage("Network error/connection lost!"); + FCEU_DispMessage("Network error/connection lost!",0); FCEUD_NetworkClose(); } @@ -310,7 +310,7 @@ void NetplayUpdate(uint8 *joyp) if(FCEUSS_LoadFP(fp,SSLOADPARAM_BACKUP)) { fclose(fp); - FCEU_DispMessage("Remote state loaded."); + FCEU_DispMessage("Remote state loaded.",0); } else FCEUD_PrintError("File error. (K)ill, (M)aim, (D)estroy?"); } break;*/ diff --git a/src/oldmovie.cpp b/src/oldmovie.cpp index 1b415b56..345af2da 100644 --- a/src/oldmovie.cpp +++ b/src/oldmovie.cpp @@ -350,7 +350,7 @@ uint16 metadata_ucs2[]; // ucs-2, ick! sizeof(metadata) = offset_to_savesta // framets=0; // nextts=0; // nextd = -1; -// FCEU_DispMessage("Movie playback started."); +// FCEU_DispMessage("Movie playback started.",0); //} // //static int FCEUI_MovieGetInfo_v1(const char* fname, MOVIE_INFO* info) diff --git a/src/ppu.cpp b/src/ppu.cpp index c53fd758..5ef969d7 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -2002,7 +2002,7 @@ int FCEUPPU_Loop(int skip) } deempcnt[x]=0; } - //FCEU_DispMessage("%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x %d",deempcnt[0],deempcnt[1],deempcnt[2],deempcnt[3],deempcnt[4],deempcnt[5],deempcnt[6],deempcnt[7],maxref); + //FCEU_DispMessage("%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x %d",0,deempcnt[0],deempcnt[1],deempcnt[2],deempcnt[3],deempcnt[4],deempcnt[5],deempcnt[6],deempcnt[7],maxref); //memset(deempcnt,0,sizeof(deempcnt)); SetNESDeemph(maxref,0); } diff --git a/src/state.cpp b/src/state.cpp index 1acf3236..81f10a93 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -448,7 +448,7 @@ void FCEUSS_Save(const char *fname) if(geniestage==1) { - FCEU_DispMessage("Cannot save FCS in GG screen."); + FCEU_DispMessage("Cannot save FCS in GG screen.",0); return; } @@ -477,7 +477,7 @@ void FCEUSS_Save(const char *fname) if(st == NULL) { - FCEU_DispMessage("State %d save error.",CurrentState); + FCEU_DispMessage("State %d save error.",0,CurrentState); return; } @@ -517,7 +517,7 @@ void FCEUSS_Save(const char *fname) if(!fname) { SaveStateStatus[CurrentState]=1; - FCEU_DispMessage("State %d saved.",CurrentState); + FCEU_DispMessage("State %d saved.",0,CurrentState); } redoSS = false; //we have a new savestate so redo is not possible } @@ -709,7 +709,7 @@ bool FCEUSS_Load(const char *fname) if(geniestage==1) { - FCEU_DispMessage("Cannot load FCS in GG screen."); + FCEU_DispMessage("Cannot load FCS in GG screen.",0); return false; } if(fname) @@ -726,7 +726,7 @@ bool FCEUSS_Load(const char *fname) if(st == NULL) { - FCEU_DispMessage("State %d load error.",CurrentState); + FCEU_DispMessage("State %d load error.",0,CurrentState); SaveStateStatus[CurrentState]=0; return false; } @@ -740,11 +740,11 @@ bool FCEUSS_Load(const char *fname) { char szFilename[260]={0}; splitpath(fname, 0, 0, szFilename, 0); - FCEU_DispMessage("State %s loaded.",szFilename); + FCEU_DispMessage("State %s loaded.",0,szFilename); } else { - FCEU_DispMessage("State %d loaded.",CurrentState); + FCEU_DispMessage("State %d loaded.",0,CurrentState); SaveStateStatus[CurrentState]=1; } delete st; @@ -787,7 +787,7 @@ bool FCEUSS_Load(const char *fname) { SaveStateStatus[CurrentState]=1; } - FCEU_DispMessage("Error(s) reading state %d!",CurrentState); + FCEU_DispMessage("Error(s) reading state %d!",0,CurrentState); delete st; return 0; } @@ -875,7 +875,7 @@ int FCEUI_SelectState(int w, int show) if(show) { StateShow=180; - FCEU_DispMessage("-select state-"); + FCEU_DispMessage("-select state-",0); } return oldstate; } @@ -984,14 +984,14 @@ void SwapSaveState() if (!lastSavestateMade) { - FCEUI_DispMessage("Can't Undo"); + FCEUI_DispMessage("Can't Undo",0); FCEUI_printf("Undo savestate was attempted but unsuccessful because there was not a recently used savestate.\n"); return; //If there is no last savestate, can't undo } string backup = GenerateBackupSaveStateFn(lastSavestateMade); //Get filename of backup state if (!CheckFileExists(backup.c_str())) { - FCEUI_DispMessage("Can't Undo"); + FCEUI_DispMessage("Can't Undo",0); FCEUI_printf("Undo savestate was attempted but unsuccessful because there was not a backup of the last used savestate.\n"); return; //If no backup, can't undo } @@ -1012,8 +1012,8 @@ void SwapSaveState() else //This was an undo function so next will be redo, so flag it redoSS = true; - FCEUI_DispMessage("%s restored",backup.c_str()); - FCEUI_printf("%s restored\n",backup.c_str()); + FCEUI_DispMessage("%s restored",0,backup.c_str()); + FCEUI_printf("%s restored\n",0,backup.c_str()); } //------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -1081,7 +1081,7 @@ void LoadBackup() undoLS = false; //Flag that LoadBackup cannot be run again } else - FCEUI_DispMessage("Error: Could not load %s",filename.c_str()); + FCEUI_DispMessage("Error: Could not load %s",0,filename.c_str()); } void RedoLoadState() diff --git a/src/video.cpp b/src/video.cpp index 4b8145a4..c5b38531 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -188,9 +188,9 @@ static void ReallySnap(void) { int x=SaveSnapshot(); if(!x) - FCEU_DispMessage("Error saving screen snapshot."); + FCEU_DispMessage("Error saving screen snapshot.",0); else - FCEU_DispMessage("Screen snapshot %d saved.",x-1); + FCEU_DispMessage("Screen snapshot %d saved.",0,x-1); } void FCEU_PutImage(void) @@ -281,7 +281,7 @@ void FCEU_PutImage(void) if (!oldInputDisplay) ci = FCEUMOV_Mode(MOVIEMODE_PLAY) ? 0:GetGamepadPressedImmediate() >> (controller * 8); else ci = 0; - if (!oldInputDisplay && !FCEUMOV_Mode(MOVIEMODE_PLAY)) held >>= (controller * 8); + if (!oldInputDisplay && !FCEUMOV_Mode(MOVIEMODE_PLAY)) held = (held >> 8); else held = 0; #else // Put other port info here @@ -382,7 +382,7 @@ void FCEU_PutImage(void) //Down if (held&32) { //If auto-hold if (!(ci&32) ) color = ahold; - else + else color = (c&32) ? on : off; //If the button is pressed down (immediate) that negates auto hold, however it is only off if the previous frame the button wasn't pressed! } else { @@ -444,21 +444,25 @@ void FCEU_DispMessageOnMovie(char *format, ...) guiMessage.howlong = 180; guiMessage.isMovieMessage = true; + guiMessage.linesFromBottom = 0; + if (FCEUI_AviIsRecording() && FCEUI_AviDisableMovieMessages()) guiMessage.howlong = 0; } -void FCEU_DispMessage(char *format, ...) +void FCEU_DispMessage(char *format, int disppos=0, ...) { va_list ap; - va_start(ap,format); + va_start(ap,disppos); vsnprintf(guiMessage.errmsg,sizeof(guiMessage.errmsg),format,ap); va_end(ap); guiMessage.howlong = 180; guiMessage.isMovieMessage = false; - + + guiMessage.linesFromBottom = disppos; + //adelikat: Pretty sure this code fails, Movie playback stopped is done with FCEU_DispMessageOnMovie() #ifdef CREATE_AVI if(LoggingEnabled == 2) @@ -476,6 +480,7 @@ void FCEU_ResetMessages() { guiMessage.howlong = 0; guiMessage.isMovieMessage = false; + guiMessage.linesFromBottom = 0; } diff --git a/src/video.h b/src/video.h index c97b620f..d7a33b4b 100644 --- a/src/video.h +++ b/src/video.h @@ -17,6 +17,9 @@ extern struct GUIMESSAGE //indicates that the movie should be drawn even on top of movies bool isMovieMessage; + //in case of multiple lines, allow one to move the message + int linesFromBottom; + } guiMessage; extern GUIMESSAGE subtitleMessage;