From 4f347ff3f1dda3bd53bd09a5e2c469c181a231be Mon Sep 17 00:00:00 2001 From: SpinDizzy Date: Sun, 19 Apr 2020 08:34:58 +0000 Subject: [PATCH] SDL1 to SDL2 internal changes --- Makefiles/Makefile.OSX | 8 +- Makefiles/Makefile.UNIX | 8 +- Makefiles/Makefile.Win32 | 27 +- Src/Model3/Model3.cpp | 12 +- Src/OSD/SDL/Audio.cpp | 15 +- Src/OSD/SDL/Main.cpp | 161 +++++--- Src/OSD/SDL/SDLInputSystem.cpp | 566 +++++++++++++------------- Src/OSD/SDL/SDLInputSystem.h | 4 +- Src/OSD/SDL/Thread.cpp | 29 +- Src/OSD/Thread.h | 23 +- Src/OSD/Windows/DirectInputSystem.cpp | 23 +- Src/OSD/Windows/DirectInputSystem.h | 6 +- 12 files changed, 466 insertions(+), 416 deletions(-) diff --git a/Makefiles/Makefile.OSX b/Makefiles/Makefile.OSX index e229bd8..55a3207 100644 --- a/Makefiles/Makefile.OSX +++ b/Makefiles/Makefile.OSX @@ -1,3 +1,9 @@ +# +# TODO: MacOS port is probably broken. Someone with MacOS needs to figure out +# how to compile with SDL2. +# + + ## ## Supermodel ## A Sega Model 3 Arcade Emulator. @@ -51,7 +57,7 @@ LD = gcc # SDL_CFLAGS = -SDL_LIBS = -framework SDL -framework AGL -framework OpenGL -framework GLUT -framework Cocoa +SDL_LIBS = -framework SDL2 -framework AGL -framework OpenGL -framework GLUT -framework Cocoa # # OSX-specific diff --git a/Makefiles/Makefile.UNIX b/Makefiles/Makefile.UNIX index 9b3af4d..6781dc2 100644 --- a/Makefiles/Makefile.UNIX +++ b/Makefiles/Makefile.UNIX @@ -50,15 +50,15 @@ LD = gcc # SDL # -SDL_CFLAGS = `sdl-config --cflags` -SDL_LIBS = `sdl-config --libs` +SDL2_CFLAGS = `sdl2-config --cflags` +SDL2_LIBS = `sdl2-config --libs` # # UNIX-specific # -PLATFORM_CFLAGS = $(SDL_CFLAGS) -PLATFORM_LDFLAGS = $(SDL_LIBS) -lGL -lGLU -lz -lm -lstdc++ +PLATFORM_CFLAGS = $(SDL2_CFLAGS) +PLATFORM_LDFLAGS = $(SDL2_LIBS) -lGL -lGLU -lz -lm -lstdc++ ############################################################################### diff --git a/Makefiles/Makefile.Win32 b/Makefiles/Makefile.Win32 index cef74e1..9ac7cc1 100644 --- a/Makefiles/Makefile.Win32 +++ b/Makefiles/Makefile.Win32 @@ -33,7 +33,7 @@ # Configuration # # Edit as necessary. Some users may need to edit the "Platform Configuration" -# section as well, namely SDL_LIBS and PLATFORM_LIBS. +# section as well, namely SDL2_LIBS and PLATFORM_LIBS. ############################################################################### # @@ -42,10 +42,10 @@ BITS = 64 # -# Path to SDL +# Path to SDL2 # -SDL_INCLUDE_DIR = C:/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/include/SDL -SDL_LIB_DIR = C:/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/lib +SDL2_INCLUDE_DIR = c:/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/SDL2 +SDL2_LIB_DIR = c:/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/lib # # Toolchain @@ -74,25 +74,20 @@ ifeq ($(strip $(MSYSTEM)),) endif # -# SDL +# SDL2 # -# -# (At least for SDL) The linked libs order is fundamental for a successful compiling! -# https://stackoverflow.com/questions/24596596/sdl-doesnt-compile-in-native-enviroment -# http://www.cplusplus.com/forum/beginner/110753/ -# -SDL_LIBS = -lmingw32 -static-libgcc -static-libstdc++ -lSDLmain -lSDL -lm -luser32 -lgdi32 -lwinmm -ldxguid -SDL_CFLAGS = -D_GNU_SOURCE=1 -Dmain=SDL_main +SDL2_LIBS = -lmingw32 -lSDL2main -lSDL2 -luser32 -lgdi32 -lwinmm -limm32 -lversion -lsetupapi +SDL2_CFLAGS = # # MinGW/Windows-specific # -PLATFORM_INCLUDE_DIR = $(SDL_INCLUDE_DIR) -PLATFORM_LIB_DIR = $(SDL_LIB_DIR) +PLATFORM_INCLUDE_DIR = $(SDL2_INCLUDE_DIR) +PLATFORM_LIB_DIR = $(SDL2_LIB_DIR) PLATFORM_LIBS = -ldinput8 -lglu32 -lole32 -loleaut32 -lopengl32 -lwbemuuid -lws2_32 -lz -PLATFORM_CFLAGS = $(SDL_CFLAGS) -DSUPERMODEL_WIN32 $(addprefix -I,$(sort $(PLATFORM_INCLUDE_DIR))) -PLATFORM_LDFLAGS = -static -L$(sort $(PLATFORM_LIB_DIR)) $(SDL_LIBS) $(PLATFORM_LIBS) +PLATFORM_CFLAGS = $(SDL2_CFLAGS) -DSUPERMODEL_WIN32 $(addprefix -I,$(sort $(PLATFORM_INCLUDE_DIR))) +PLATFORM_LDFLAGS = -static -L$(sort $(PLATFORM_LIB_DIR)) $(SDL2_LIBS) $(PLATFORM_LIBS) ############################################################################### diff --git a/Src/Model3/Model3.cpp b/Src/Model3/Model3.cpp index a6e4f1e..6a76f62 100644 --- a/Src/Model3/Model3.cpp +++ b/Src/Model3/Model3.cpp @@ -2250,23 +2250,23 @@ bool CModel3::StartThreads(void) // Create PPC main board thread, if multi-threading GPU if (m_gpuMultiThreaded) { - ppcBrdThread = CThread::CreateThread(StartMainBoardThread, this); + ppcBrdThread = CThread::CreateThread("MainBoard", StartMainBoardThread, this); if (ppcBrdThread == NULL) goto ThreadError; } // Create sound board thread (sync'd or unsync'd) if (syncSndBrdThread) - sndBrdThread = CThread::CreateThread(StartSoundBoardThreadSyncd, this); + sndBrdThread = CThread::CreateThread("SoundBoardSync", StartSoundBoardThreadSyncd, this); else - sndBrdThread = CThread::CreateThread(StartSoundBoardThread, this); + sndBrdThread = CThread::CreateThread("SoundBoardNoSync", StartSoundBoardThread, this); if (sndBrdThread == NULL) goto ThreadError; // Create drive board thread, if drive board is attached if (DriveBoard.IsAttached()) { - drvBrdThread = CThread::CreateThread(StartDriveBoardThread, this); + drvBrdThread = CThread::CreateThread("DriveBoard", StartDriveBoardThread, this); if (drvBrdThread == NULL) goto ThreadError; } @@ -3237,7 +3237,7 @@ CModel3::CModel3(const Util::Config::Node &config) } // Dumps a memory region to a file for debugging purposes -/* +#if 0 static void Dump(const char *file, uint8_t *buf, size_t size, bool reverse32, bool reverse16) { FILE *fp = fopen(file, "wb"); @@ -3254,7 +3254,7 @@ static void Dump(const char *file, uint8_t *buf, size_t size, bool reverse32, bo else printf("unable to dump %s\n", file); } -*/ +#endif CModel3::~CModel3(void) { diff --git a/Src/OSD/SDL/Audio.cpp b/Src/OSD/SDL/Audio.cpp index d97dbfc..e37d603 100755 --- a/Src/OSD/SDL/Audio.cpp +++ b/Src/OSD/SDL/Audio.cpp @@ -217,6 +217,7 @@ static void MixChannels(unsigned numSamples, INT16 *leftBuffer, INT16 *rightBuff #endif // NUM_CHANNELS } +/* static void LogAudioInfo(SDL_AudioSpec *fmt) { InfoLog("Audio device information:"); @@ -225,6 +226,7 @@ static void LogAudioInfo(SDL_AudioSpec *fmt) InfoLog("Sample Format: %d", fmt->format); InfoLog(""); } +*/ bool OpenAudio() { @@ -241,18 +243,9 @@ bool OpenAudio() fmt.samples = playSamples; fmt.callback = PlayCallback; - // Try opening SDL audio output with that specification - SDL_AudioSpec obtained; - if (SDL_OpenAudio(&fmt, &obtained) < 0) + // Force SDL to use the format we requested; it will convert if necessary + if (SDL_OpenAudio(&fmt, nullptr) < 0) return ErrorLog("Unable to open 44.1KHz 2-channel audio with SDL: %s\n", SDL_GetError()); - LogAudioInfo(&obtained); - - // Check if obtained format is what we really requested - if ((obtained.freq!=fmt.freq) || (obtained.channels!=fmt.channels) || (obtained.format!=fmt.format)) - ErrorLog("Incompatible audio settings (44.1KHz, 16-bit required). Check drivers!\n"); - - // Check what buffer sample size was actually obtained, and use that - playSamples = obtained.samples; // Create audio buffer audioBufferSize = SAMPLE_RATE * BYTES_PER_SAMPLE * latency / MAX_LATENCY; diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index c098587..c91818c 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -92,6 +92,8 @@ static Util::Config::Node s_runtime_config("Global"); Display Management ******************************************************************************/ +static SDL_Window *s_window = nullptr; + /* * Position and size of rectangular region within OpenGL display to render to. * Unlike the config tree, these end up containing the actual resolution (and @@ -105,9 +107,11 @@ static unsigned totalXRes, totalYRes; // total resolution (the whole GL viewpo static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *xResPtr, unsigned *yResPtr, unsigned *totalXResPtr, unsigned *totalYResPtr, bool keepAspectRatio) { // What resolution did we actually get? - const SDL_VideoInfo *VideoInfo = SDL_GetVideoInfo(); - *totalXResPtr = VideoInfo->current_w; - *totalYResPtr = VideoInfo->current_h; + int actualWidth; + int actualHeight; + SDL_GetWindowSize(s_window, &actualWidth, &actualHeight); + *totalXResPtr = actualWidth; + *totalYResPtr = actualHeight; // If required, fix the aspect ratio of the resolution that the user passed to match Model 3 ratio float xRes = float(*xResPtr); @@ -126,10 +130,10 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned * *yOffsetPtr = (*yResPtr - (unsigned) yRes)/2; // If the desired resolution is smaller than what we got, re-center again - if (int(*xResPtr) < VideoInfo->current_w) - *xOffsetPtr += (VideoInfo->current_w - *xResPtr)/2; - if (int(*yResPtr) < VideoInfo->current_h) - *yOffsetPtr += (VideoInfo->current_h - *yResPtr)/2; + if (int(*xResPtr) < actualWidth) + *xOffsetPtr += (actualWidth - *xResPtr)/2; + if (int(*yResPtr) < actualHeight) + *yOffsetPtr += (actualHeight - *yResPtr)/2; // OpenGL initialization glViewport(0,0,*xResPtr,*yResPtr); @@ -143,7 +147,7 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned * for (int i = 0; i < 2; i++) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - SDL_GL_SwapBuffers(); + SDL_GL_SwapWindow(s_window); } // Write back resolution parameters @@ -159,7 +163,8 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned * { glScissor(0, correction, *totalXResPtr, *totalYResPtr - (correction * 2)); } - else { + else + { glScissor(*xOffsetPtr + correction, *yOffsetPtr + correction, *xResPtr - (correction * 2), *yResPtr - (correction * 2)); } return OKAY; @@ -177,12 +182,20 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned * * NOTE: keepAspectRatio should always be true. It has not yet been tested with * the wide screen hack. */ -static bool CreateGLScreen(const std::string &caption, unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *xResPtr, unsigned *yResPtr, unsigned *totalXResPtr, unsigned *totalYResPtr, bool keepAspectRatio, bool fullScreen) +static bool CreateGLScreen(const std::string &caption, bool focusWindow, unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *xResPtr, unsigned *yResPtr, unsigned *totalXResPtr, unsigned *totalYResPtr, bool keepAspectRatio, bool fullScreen) { GLenum err; + // Call only once per program session (this is because of issues with + // DirectInput when the window is destroyed and a new one created). Use + // ResizeGLScreen() to change resolutions instead. + if (s_window != nullptr) + { + return ErrorLog("Internal error: CreateGLScreen() called more than once"); + } + // Initialize video subsystem - if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) + if (SDL_Init(SDL_INIT_VIDEO) != 0) return ErrorLog("Unable to initialize SDL video subsystem: %s\n", SDL_GetError()); // Important GL attributes @@ -192,19 +205,33 @@ static bool CreateGLScreen(const std::string &caption, unsigned *xOffsetPtr, uns SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,8); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); - - // Set vsync - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, s_runtime_config["VSync"].ValueAsDefault(false) ? 1 : 0); - + // Set video mode - if (SDL_SetVideoMode(*xResPtr,*yResPtr,0,SDL_OPENGL|(fullScreen?SDL_FULLSCREEN|SDL_HWSURFACE:0)) == NULL) + s_window = SDL_CreateWindow(caption.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, *xResPtr, *yResPtr, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | (fullScreen ? SDL_WINDOW_FULLSCREEN : 0)); + if (nullptr == s_window) { ErrorLog("Unable to create an OpenGL display: %s\n", SDL_GetError()); return FAIL; } - - // Create window caption - SDL_WM_SetCaption(caption.c_str(),NULL); + + if (focusWindow) + { + SDL_RaiseWindow(s_window); + } + + // Create OpenGL context + SDL_GLContext context = SDL_GL_CreateContext(s_window); + if (nullptr == context) + { + ErrorLog("Unable to create OpenGL context: %s\n", SDL_GetError()); + return FAIL; + } + + // Set vsync + SDL_GL_SetSwapInterval(s_runtime_config["VSync"].ValueAsDefault(false) ? 1 : 0); + + // Set the context as the current window context + SDL_GL_MakeCurrent(s_window, context); // Initialize GLEW, allowing us to use features beyond OpenGL 1.2 err = glewInit(); @@ -217,12 +244,21 @@ static bool CreateGLScreen(const std::string &caption, unsigned *xOffsetPtr, uns return SetGLGeometry(xOffsetPtr, yOffsetPtr, xResPtr, yResPtr, totalXResPtr, totalYResPtr, keepAspectRatio); } +static void DestroyGLScreen() +{ + if (s_window != nullptr) + { + SDL_GL_DeleteContext(SDL_GL_GetCurrentContext()); + SDL_DestroyWindow(s_window); + } +} + static bool ResizeGLScreen(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *xResPtr, unsigned *yResPtr, unsigned *totalXResPtr, unsigned *totalYResPtr, bool keepAspectRatio, bool fullScreen) { - // Set video mode - if (SDL_SetVideoMode(*xResPtr,*yResPtr,0,SDL_OPENGL|(fullScreen?SDL_FULLSCREEN|SDL_HWSURFACE:0)) == NULL) + // Set full screen mode + if (SDL_SetWindowFullscreen(s_window, fullScreen ? SDL_WINDOW_FULLSCREEN : 0) < 0) { - ErrorLog("Unable to create an OpenGL display: %s\n", SDL_GetError()); + ErrorLog("Unable to enter %s mode: %s\n", fullScreen ? "fullscreen" : "windowed", SDL_GetError()); return FAIL; } @@ -240,7 +276,7 @@ static void PrintGLInfo(bool createScreen, bool infoLog, bool printExtensions) unsigned xOffset, yOffset, xRes=496, yRes=384, totalXRes, totalYRes; if (createScreen) { - if (OKAY != CreateGLScreen("Supermodel - Querying OpenGL Information...", &xOffset, &yOffset, &xRes, &yRes, &totalXRes, &totalYRes, false, false)) + if (OKAY != CreateGLScreen("Supermodel - Querying OpenGL Information...", false, &xOffset, &yOffset, &xRes, &yRes, &totalXRes, &totalYRes, false, false)) { ErrorLog("Unable to query OpenGL.\n"); return; @@ -771,7 +807,7 @@ void EndFrameVideo() UpdateCrosshairs(currentInputs, videoInputs, s_runtime_config["Crosshairs"].ValueAs()); // Swap the buffers - SDL_GL_SwapBuffers(); + SDL_GL_SwapWindow(s_window); } static void SuperSleep(UINT32 time) @@ -814,15 +850,16 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In // Load NVRAM LoadNVRAM(Model3); - // Start up SDL and open a GL window + // Set the video mode char baseTitleStr[128]; char titleStr[128]; totalXRes = xRes = s_runtime_config["XResolution"].ValueAs(); totalYRes = yRes = s_runtime_config["YResolution"].ValueAs(); sprintf(baseTitleStr, "Supermodel - %s", game.title.c_str()); + SDL_SetWindowTitle(s_window, baseTitleStr); bool stretch = s_runtime_config["Stretch"].ValueAs(); bool fullscreen = s_runtime_config["FullScreen"].ValueAs(); - if (OKAY != CreateGLScreen(baseTitleStr, &xOffset, &yOffset ,&xRes, &yRes, &totalXRes, &totalYRes, !stretch, fullscreen)) + if (OKAY != ResizeGLScreen(&xOffset, &yOffset ,&xRes, &yRes, &totalXRes, &totalYRes, !stretch, fullscreen)) return 1; // Info log GL information @@ -965,13 +1002,13 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In Model3->PauseThreads(); SetAudioEnabled(false); sprintf(titleStr, "%s (Paused)", baseTitleStr); - SDL_WM_SetCaption(titleStr,NULL); + SDL_SetWindowTitle(s_window, titleStr); } else { Model3->ResumeThreads(); SetAudioEnabled(true); - SDL_WM_SetCaption(baseTitleStr,NULL); + SDL_SetWindowTitle(s_window, baseTitleStr); } // Send paused value as output @@ -999,7 +1036,7 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In // Recreate renderers and attach to the emulator Render2D = new CRender2D(s_runtime_config); - Render3D = s_runtime_config["New3DEngine"].ValueAs() ? ((IRender3D *) new New3D::CNew3D(s_runtime_config, Model3->GetGame().name)) : ((IRender3D *) new Legacy3D::CLegacy3D(s_runtime_config)); + Render3D = s_runtime_config["New3DEngine"].ValueAs() ? ((IRender3D *) new New3D::CNew3D(s_runtime_config, Model3->GetGame().name)) : ((IRender3D *) new Legacy3D::CLegacy3D(s_runtime_config)); if (OKAY != Render2D->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes)) goto QuitError; if (OKAY != Render3D->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes)) @@ -1156,14 +1193,13 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In // Frame rate and limiting unsigned currentFPSTicks = SDL_GetTicks(); - unsigned currentTicks = currentFPSTicks; if (s_runtime_config["ShowFrameRate"].ValueAs()) { ++fpsFramesElapsed; if((currentFPSTicks-prevFPSTicks) >= 1000) // update FPS every 1 second (each tick is 1 ms) { sprintf(titleStr, "%s - %1.1f FPS%s", baseTitleStr, (float)fpsFramesElapsed/((float)(currentFPSTicks-prevFPSTicks)/1000.0f), paused ? " (Paused)" : ""); - SDL_WM_SetCaption(titleStr,NULL); + SDL_SetWindowTitle(s_window, titleStr); prevFPSTicks = currentFPSTicks; // reset tick count fpsFramesElapsed = 0; // reset frame count } @@ -1241,6 +1277,13 @@ static bool ConfigureInputs(CInputs *Inputs, Util::Config::Node *fileConfig, Uti // If the user wants to configure the inputs, do that now if (configure) { + std::string title("Supermodel - "); + if (game.name.empty()) + title.append("Configuring Default Inputs..."); + else + title.append(Util::Format() << "Configuring Inputs for: " << game.title); + SDL_SetWindowTitle(s_window, title.c_str()); + // Extract the relevant INI section (which will be the global section if no // game was specified, otherwise the game's node) in the file config, which // will be written back to disk @@ -1249,17 +1292,7 @@ static bool ConfigureInputs(CInputs *Inputs, Util::Config::Node *fileConfig, Uti { fileConfigRoot = &fileConfig->Add(game.name); } - - // Open an SDL window - unsigned xOffset, yOffset, xRes=496, yRes=384; - std::string title("Supermodel - "); - if (game.name.empty()) - title.append("Configuring Default Inputs..."); - else - title.append(Util::Format() << "Configuring Inputs for: " << game.title); - if (OKAY != CreateGLScreen(title, &xOffset, &yOffset, &xRes, &yRes, &totalXRes, &totalYRes, false, false)) - return (bool) ErrorLog("Unable to start SDL to configure inputs.\n"); - + // Configure the inputs if (Inputs->ConfigureInputs(game, xOffset, yOffset, xRes, yRes)) { @@ -1672,6 +1705,7 @@ int main(int argc, char **argv) } if (cmd_line.print_gl_info) { + // We must exit after this because CreateGLScreen() is used PrintGLInfo(true, false, false); return 0; } @@ -1715,6 +1749,7 @@ int main(int argc, char **argv) Util::Config::MergeINISections(&s_runtime_config, config4, cmd_line.config); // apply command line overrides once more } LogConfig(s_runtime_config); + std::string selectedInputSystem = s_runtime_config["InputSystem"].ValueAs(); // Initialize SDL (individual subsystems get initialized later) if (SDL_Init(0) != 0) @@ -1722,34 +1757,43 @@ int main(int argc, char **argv) ErrorLog("Unable to initialize SDL: %s\n", SDL_GetError()); return 1; } - - // Create Model 3 emulator -#ifdef DEBUG - IEmulator *Model3 = s_gfxStatePath.empty() ? static_cast(new CModel3(s_runtime_config)) : static_cast(new CModel3GraphicsState(s_runtime_config, s_gfxStatePath)); -#else - IEmulator *Model3 = new CModel3(s_runtime_config); -#endif - - // Create input system (default is SDL) and debugger - CInputSystem *InputSystem = NULL; - CInputs *Inputs = NULL; - COutputs *Outputs = NULL; + + // Begin initializing various subsystems... int exitCode = 0; + IEmulator *Model3 = nullptr; + CInputSystem *InputSystem = nullptr; + CInputs *Inputs = nullptr; + COutputs *Outputs = nullptr; #ifdef SUPERMODEL_DEBUGGER Debugger::CSupermodelDebugger *Debugger = NULL; #endif // SUPERMODEL_DEBUGGER + + // Create a window + xRes = 496; + yRes = 384; + if (OKAY != CreateGLScreen("Supermodel", false, &xOffset, &yOffset, &xRes, &yRes, &totalXRes, &totalYRes, false, false)) + { + exitCode = 1; + goto Exit; + } + + // Create Model 3 emulator +#ifdef DEBUG + Model3 = s_gfxStatePath.empty() ? static_cast(new CModel3(s_runtime_config)) : static_cast(new CModel3GraphicsState(s_runtime_config, s_gfxStatePath)); +#else + Model3 = new CModel3(s_runtime_config); +#endif // Create input system - std::string selectedInputSystem = s_runtime_config["InputSystem"].ValueAs(); if (selectedInputSystem == "sdl") InputSystem = new CSDLInputSystem(); #ifdef SUPERMODEL_WIN32 else if (selectedInputSystem == "dinput") - InputSystem = new CDirectInputSystem(s_runtime_config, false, false); + InputSystem = new CDirectInputSystem(s_runtime_config, s_window, false, false); else if (selectedInputSystem == "xinput") - InputSystem = new CDirectInputSystem(s_runtime_config, false, true); + InputSystem = new CDirectInputSystem(s_runtime_config, s_window, false, true); else if (selectedInputSystem == "rawinput") - InputSystem = new CDirectInputSystem(s_runtime_config, true, false); + InputSystem = new CDirectInputSystem(s_runtime_config, s_window, true, false); #endif // SUPERMODEL_WIN32 else { @@ -1836,6 +1880,7 @@ Exit: delete InputSystem; if (Outputs != NULL) delete Outputs; + DestroyGLScreen(); SDL_Quit(); if (exitCode) diff --git a/Src/OSD/SDL/SDLInputSystem.cpp b/Src/OSD/SDL/SDLInputSystem.cpp index 2f6eaea..6b80b09 100644 --- a/Src/OSD/SDL/SDLInputSystem.cpp +++ b/Src/OSD/SDL/SDLInputSystem.cpp @@ -6,7 +6,7 @@ ** This file is part of Supermodel. ** ** Supermodel 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 + ** the terms of the GNU General Public License as published by the Free ** Software Foundation, either version 3 of the License, or (at your option) ** any later version. ** @@ -18,11 +18,15 @@ ** You should have received a copy of the GNU General Public License along ** with Supermodel. If not, see . **/ - + /* * SDLInputSystem.cpp - * + * * Implementation of SDL input system. + * + * TODO: + * ----- + * - Implement multiple keyboard and mouse support. */ #include "SDLInputSystem.h" @@ -33,402 +37,384 @@ using namespace std; SDLKeyMapStruct CSDLInputSystem::s_keyMap[] = { - // General keys - { "BACKSPACE", SDLK_BACKSPACE }, - { "TAB", SDLK_TAB }, - { "CLEAR", SDLK_CLEAR }, - { "RETURN", SDLK_RETURN }, - { "PAUSE", SDLK_PAUSE }, - { "ESCAPE", SDLK_ESCAPE }, - { "SPACE", SDLK_SPACE }, - { "EXCLAIM", SDLK_EXCLAIM }, - { "DBLQUOTE", SDLK_QUOTEDBL }, - { "HASH", SDLK_HASH }, - { "DOLLAR", SDLK_DOLLAR }, - { "AMPERSAND", SDLK_AMPERSAND }, - { "QUOTE", SDLK_QUOTE }, - { "LEFTPAREN", SDLK_LEFTPAREN }, - { "RIGHTPAREN", SDLK_RIGHTPAREN }, - { "ASTERISK", SDLK_ASTERISK }, - { "PLUS", SDLK_PLUS }, - { "COMMA", SDLK_COMMA }, - { "MINUS", SDLK_MINUS }, - { "PERIOD", SDLK_PERIOD }, - { "SLASH", SDLK_SLASH }, - { "0", SDLK_0 }, - { "1", SDLK_1 }, - { "2", SDLK_2 }, - { "3", SDLK_3 }, - { "4", SDLK_4 }, - { "5", SDLK_5 }, - { "6", SDLK_6 }, - { "7", SDLK_7 }, - { "8", SDLK_8 }, - { "9", SDLK_9 }, - { "COLON", SDLK_COLON }, - { "SEMICOLON", SDLK_SEMICOLON }, - { "LESS", SDLK_LESS }, - { "EQUALS", SDLK_EQUALS }, - { "GREATER", SDLK_GREATER }, - { "QUESTION", SDLK_QUESTION }, - { "AT", SDLK_AT }, - { "LEFTBRACKET", SDLK_LEFTBRACKET }, - { "BACKSLASH", SDLK_BACKSLASH }, - { "RIGHTBRACKET", SDLK_RIGHTBRACKET }, - { "CARET", SDLK_CARET }, - { "UNDERSCORE", SDLK_UNDERSCORE }, - { "BACKQUOTE", SDLK_BACKQUOTE }, - { "A", SDLK_a }, - { "B", SDLK_b }, - { "C", SDLK_c }, - { "D", SDLK_d }, - { "E", SDLK_e }, - { "F", SDLK_f }, - { "G", SDLK_g }, - { "H", SDLK_h }, - { "I", SDLK_i }, - { "J", SDLK_j }, - { "K", SDLK_k }, - { "L", SDLK_l }, - { "M", SDLK_m }, - { "N", SDLK_n }, - { "O", SDLK_o }, - { "P", SDLK_p }, - { "Q", SDLK_q }, - { "R", SDLK_r }, - { "S", SDLK_s }, - { "T", SDLK_t }, - { "U", SDLK_u }, - { "V", SDLK_v }, - { "W", SDLK_w }, - { "X", SDLK_x }, - { "Y", SDLK_y }, - { "Z", SDLK_z }, - { "DEL", SDLK_DELETE }, - - // Keypad - { "KEYPAD0", SDLK_KP0 }, - { "KEYPAD1", SDLK_KP1 }, - { "KEYPAD2", SDLK_KP2 }, - { "KEYPAD3", SDLK_KP3 }, - { "KEYPAD4", SDLK_KP4 }, - { "KEYPAD5", SDLK_KP5 }, - { "KEYPAD6", SDLK_KP6 }, - { "KEYPAD7", SDLK_KP7 }, - { "KEYPAD8", SDLK_KP8 }, - { "KEYPAD9", SDLK_KP9 }, - { "KEYPADPERIOD", SDLK_KP_PERIOD }, - { "KEYPADDIVIDE", SDLK_KP_DIVIDE }, - { "KEYPADMULTIPLY", SDLK_KP_MULTIPLY }, - { "KEYPADMINUS", SDLK_KP_MINUS }, - { "KEYPADPLUS", SDLK_KP_PLUS }, - { "KEYPADENTER", SDLK_KP_ENTER }, - { "KEYPADEQUALS", SDLK_KP_EQUALS }, - - // Arrows + Home/End Pad - { "UP", SDLK_UP }, - { "DOWN", SDLK_DOWN }, - { "RIGHT", SDLK_RIGHT }, - { "LEFT", SDLK_LEFT }, - { "INSERT", SDLK_INSERT }, - { "HOME", SDLK_HOME }, - { "END", SDLK_END }, - { "PGUP", SDLK_PAGEUP }, - { "PGDN", SDLK_PAGEDOWN }, + // General keys + { "BACKSPACE", SDL_SCANCODE_BACKSPACE }, + { "TAB", SDL_SCANCODE_TAB }, + { "CLEAR", SDL_SCANCODE_CLEAR }, + { "RETURN", SDL_SCANCODE_RETURN }, + { "PAUSE", SDL_SCANCODE_PAUSE }, + { "ESCAPE", SDL_SCANCODE_ESCAPE }, + { "SPACE", SDL_SCANCODE_SPACE }, + { "QUOTE", SDL_SCANCODE_APOSTROPHE }, + { "LEFTPAREN", SDL_SCANCODE_KP_LEFTPAREN }, + { "RIGHTPAREN", SDL_SCANCODE_KP_RIGHTPAREN }, + { "COMMA", SDL_SCANCODE_COMMA }, + { "MINUS", SDL_SCANCODE_MINUS }, + { "PERIOD", SDL_SCANCODE_PERIOD }, + { "SLASH", SDL_SCANCODE_SLASH }, + { "0", SDL_SCANCODE_0 }, + { "1", SDL_SCANCODE_1 }, + { "2", SDL_SCANCODE_2 }, + { "3", SDL_SCANCODE_3 }, + { "4", SDL_SCANCODE_4 }, + { "5", SDL_SCANCODE_5 }, + { "6", SDL_SCANCODE_6 }, + { "7", SDL_SCANCODE_7 }, + { "8", SDL_SCANCODE_8 }, + { "9", SDL_SCANCODE_9 }, + { "SEMICOLON", SDL_SCANCODE_SEMICOLON }, + { "EQUALS", SDL_SCANCODE_EQUALS }, + { "LEFTBRACKET", SDL_SCANCODE_LEFTBRACKET }, + { "BACKSLASH", SDL_SCANCODE_BACKSLASH }, + { "RIGHTBRACKET", SDL_SCANCODE_RIGHTBRACKET }, + { "BACKQUOTE", SDL_SCANCODE_GRAVE }, + { "A", SDL_SCANCODE_A }, + { "B", SDL_SCANCODE_B }, + { "C", SDL_SCANCODE_C }, + { "D", SDL_SCANCODE_D }, + { "E", SDL_SCANCODE_E }, + { "F", SDL_SCANCODE_F }, + { "G", SDL_SCANCODE_G }, + { "H", SDL_SCANCODE_H }, + { "I", SDL_SCANCODE_I }, + { "J", SDL_SCANCODE_J }, + { "K", SDL_SCANCODE_K }, + { "L", SDL_SCANCODE_L }, + { "M", SDL_SCANCODE_M }, + { "N", SDL_SCANCODE_N }, + { "O", SDL_SCANCODE_O }, + { "P", SDL_SCANCODE_P }, + { "Q", SDL_SCANCODE_Q }, + { "R", SDL_SCANCODE_R }, + { "S", SDL_SCANCODE_S }, + { "T", SDL_SCANCODE_T }, + { "U", SDL_SCANCODE_U }, + { "V", SDL_SCANCODE_V }, + { "W", SDL_SCANCODE_W }, + { "X", SDL_SCANCODE_X }, + { "Y", SDL_SCANCODE_Y }, + { "Z", SDL_SCANCODE_Z }, + { "DEL", SDL_SCANCODE_DELETE }, - // Function Key - { "F1", SDLK_F1 }, - { "F2", SDLK_F2 }, - { "F3", SDLK_F3 }, - { "F4", SDLK_F4 }, - { "F5", SDLK_F5 }, - { "F6", SDLK_F6 }, - { "F7", SDLK_F7 }, - { "F8", SDLK_F8 }, - { "F9", SDLK_F9 }, - { "F10", SDLK_F10 }, - { "F11", SDLK_F11 }, - { "F12", SDLK_F12 }, - { "F13", SDLK_F13 }, - { "F14", SDLK_F14 }, - { "F15", SDLK_F15 }, - - // Modifier Keys - // Removed Numlock, Capslock and Scrollock as don't seem to be handled well by SDL - //{ "NUMLOCK", SDLK_NUMLOCK }, - //{ "CAPSLOCK", SDLK_CAPSLOCK }, - //{ "SCROLLLOCK", SDLK_SCROLLOCK }, - { "RIGHTSHIFT", SDLK_RSHIFT }, - { "LEFTSHIFT", SDLK_LSHIFT }, - { "RIGHTCTRL", SDLK_RCTRL }, - { "LEFTCTRL", SDLK_LCTRL }, - { "RIGHTALT", SDLK_RALT }, - { "LEFTALT", SDLK_LALT }, - { "RIGHTMETA", SDLK_RMETA }, - { "LEFTMETA", SDLK_LMETA }, - { "RIGHTWINDOWS", SDLK_RSUPER }, - { "LEFTWINDOWS", SDLK_LSUPER }, - { "ALTGR", SDLK_MODE }, - { "COMPOSE", SDLK_COMPOSE }, - - // Other - { "HELP", SDLK_HELP }, - { "PRINT", SDLK_PRINT }, - { "SYSREQ", SDLK_SYSREQ }, - { "BREAK", SDLK_BREAK }, - { "MENU", SDLK_MENU }, - { "POWER", SDLK_POWER }, - { "EURO", SDLK_EURO }, - { "UNDO", SDLK_UNDO } + // Keypad + { "KEYPAD0", SDL_SCANCODE_KP_0 }, + { "KEYPAD1", SDL_SCANCODE_KP_1 }, + { "KEYPAD2", SDL_SCANCODE_KP_2 }, + { "KEYPAD3", SDL_SCANCODE_KP_3 }, + { "KEYPAD4", SDL_SCANCODE_KP_4 }, + { "KEYPAD5", SDL_SCANCODE_KP_5 }, + { "KEYPAD6", SDL_SCANCODE_KP_6 }, + { "KEYPAD7", SDL_SCANCODE_KP_7 }, + { "KEYPAD8", SDL_SCANCODE_KP_8 }, + { "KEYPAD9", SDL_SCANCODE_KP_9 }, + { "KEYPADPERIOD", SDL_SCANCODE_KP_PERIOD }, + { "KEYPADDIVIDE", SDL_SCANCODE_KP_DIVIDE }, + { "KEYPADMULTIPLY", SDL_SCANCODE_KP_MULTIPLY }, + { "KEYPADMINUS", SDL_SCANCODE_KP_MINUS }, + { "KEYPADPLUS", SDL_SCANCODE_KP_PLUS }, + { "KEYPADENTER", SDL_SCANCODE_KP_ENTER }, + { "KEYPADEQUALS", SDL_SCANCODE_KP_EQUALS }, + + // Arrows + Home/End Pad + { "UP", SDL_SCANCODE_UP }, + { "DOWN", SDL_SCANCODE_DOWN }, + { "RIGHT", SDL_SCANCODE_RIGHT }, + { "LEFT", SDL_SCANCODE_LEFT }, + { "INSERT", SDL_SCANCODE_INSERT }, + { "HOME", SDL_SCANCODE_HOME }, + { "END", SDL_SCANCODE_END }, + { "PGUP", SDL_SCANCODE_PAGEUP }, + { "PGDN", SDL_SCANCODE_PAGEDOWN }, + + // Function Key + { "F1", SDL_SCANCODE_F1 }, + { "F2", SDL_SCANCODE_F2 }, + { "F3", SDL_SCANCODE_F3 }, + { "F4", SDL_SCANCODE_F4 }, + { "F5", SDL_SCANCODE_F5 }, + { "F6", SDL_SCANCODE_F6 }, + { "F7", SDL_SCANCODE_F7 }, + { "F8", SDL_SCANCODE_F8 }, + { "F9", SDL_SCANCODE_F9 }, + { "F10", SDL_SCANCODE_F10 }, + { "F11", SDL_SCANCODE_F11 }, + { "F12", SDL_SCANCODE_F12 }, + { "F13", SDL_SCANCODE_F13 }, + { "F14", SDL_SCANCODE_F14 }, + { "F15", SDL_SCANCODE_F15 }, + + // Modifier Keys + // Removed Numlock, Capslock and Scrollock as don't seem to be handled well by SDL + //{ "NUMLOCK", SDLK_NUMLOCK }, + //{ "CAPSLOCK", SDL_SCANCODE_CAPSLOCK }, + //{ "SCROLLLOCK", SDLK_SCROLLOCK }, + { "RIGHTSHIFT", SDL_SCANCODE_RSHIFT }, + { "LEFTSHIFT", SDL_SCANCODE_LSHIFT }, + { "RIGHTCTRL", SDL_SCANCODE_RCTRL }, + { "LEFTCTRL", SDL_SCANCODE_LCTRL }, + { "RIGHTALT", SDL_SCANCODE_RALT }, + { "LEFTALT", SDL_SCANCODE_LALT }, + { "RIGHTMETA", SDL_SCANCODE_RGUI }, + { "LEFTMETA", SDL_SCANCODE_LGUI }, + { "ALTGR", SDL_SCANCODE_MODE }, + + // Other + { "HELP", SDL_SCANCODE_HELP }, + { "SYSREQ", SDL_SCANCODE_SYSREQ }, + { "MENU", SDL_SCANCODE_MENU }, + { "POWER", SDL_SCANCODE_POWER }, + { "UNDO", SDL_SCANCODE_UNDO } }; -CSDLInputSystem::CSDLInputSystem() +CSDLInputSystem::CSDLInputSystem() : CInputSystem("SDL"), - m_keyState(NULL), + m_keyState(nullptr), m_mouseX(0), m_mouseY(0), m_mouseZ(0), m_mouseButtons(0) { - // + // } CSDLInputSystem::~CSDLInputSystem() { - CloseJoysticks(); + CloseJoysticks(); } void CSDLInputSystem::OpenJoysticks() { - // Open all available joysticks - int numJoys = SDL_NumJoysticks(); - for (int joyNum = 0; joyNum < numJoys; joyNum++) - { - SDL_Joystick *joystick = SDL_JoystickOpen(joyNum); - if (joystick == NULL) - { - ErrorLog("Unable to open joystick device %d with SDL - skipping joystick.\n", joyNum + 1); - continue; - } - - // Gather joystick details (name, num POVs & buttons and which axes are available) - JoyDetails joyDetails; - const char *pName = SDL_JoystickName(joyNum); - strncpy(joyDetails.name, pName, MAX_NAME_LENGTH); - joyDetails.name[MAX_NAME_LENGTH] = '\0'; - joyDetails.numAxes = SDL_JoystickNumAxes(joystick); - for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++) - { - joyDetails.hasAxis[axisNum] = joyDetails.numAxes > axisNum; - joyDetails.axisHasFF[axisNum] = false; // SDL 1.2 does not support force feedback - char *axisName = joyDetails.axisName[axisNum]; - strcpy(axisName, CInputSystem::GetDefaultAxisName(axisNum)); // SDL 1.2 does not support axis names - } - joyDetails.numPOVs = SDL_JoystickNumHats(joystick); - joyDetails.numButtons = SDL_JoystickNumButtons(joystick); - joyDetails.hasFFeedback = false; // SDL 1.2 does not support force feedback - - m_joysticks.push_back(joystick); - m_joyDetails.push_back(joyDetails); - } + // Open all available joysticks + int numJoys = SDL_NumJoysticks(); + for (int joyNum = 0; joyNum < numJoys; joyNum++) + { + SDL_Joystick *joystick = SDL_JoystickOpen(joyNum); + if (joystick == nullptr) + { + ErrorLog("Unable to open joystick device %d with SDL - skipping joystick.\n", joyNum + 1); + continue; + } + + // Gather joystick details (name, num POVs & buttons and which axes are available) + JoyDetails joyDetails; + const char *pName = SDL_JoystickName(joystick); + strncpy(joyDetails.name, pName, MAX_NAME_LENGTH); + joyDetails.name[MAX_NAME_LENGTH] = '\0'; + joyDetails.numAxes = SDL_JoystickNumAxes(joystick); + for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++) + { + joyDetails.hasAxis[axisNum] = joyDetails.numAxes > axisNum; + joyDetails.axisHasFF[axisNum] = false; // SDL 1.2 does not support force feedback + char *axisName = joyDetails.axisName[axisNum]; + strcpy(axisName, CInputSystem::GetDefaultAxisName(axisNum)); // SDL 1.2 does not support axis names + } + joyDetails.numPOVs = SDL_JoystickNumHats(joystick); + joyDetails.numButtons = SDL_JoystickNumButtons(joystick); + joyDetails.hasFFeedback = false; // SDL 1.2 does not support force feedback + + m_joysticks.push_back(joystick); + m_joyDetails.push_back(joyDetails); + } } void CSDLInputSystem::CloseJoysticks() { - // Close all previously opened joysticks - for (size_t i = 0; i < m_joysticks.size(); i++) - { - SDL_Joystick *joystick = m_joysticks[i]; - SDL_JoystickClose(joystick); - } + // Close all previously opened joysticks + for (size_t i = 0; i < m_joysticks.size(); i++) + { + SDL_Joystick *joystick = m_joysticks[i]; + SDL_JoystickClose(joystick); + } - m_joysticks.clear(); - m_joyDetails.clear(); + m_joysticks.clear(); + m_joyDetails.clear(); } bool CSDLInputSystem::InitializeSystem() { - // Make sure joystick subsystem is initialized and joystick events are enabled - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0) - { - ErrorLog("Unable to initialize SDL joystick subsystem (%s).\n", SDL_GetError()); + // Make sure joystick subsystem is initialized and joystick events are enabled + if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != 0) + { + ErrorLog("Unable to initialize SDL joystick subsystem (%s).\n", SDL_GetError()); - return false; - } - SDL_JoystickEventState(SDL_ENABLE); + return false; + } + SDL_JoystickEventState(SDL_ENABLE); - // Open attached joysticks - OpenJoysticks(); - return true; + // Open attached joysticks + OpenJoysticks(); + return true; } int CSDLInputSystem::GetKeyIndex(const char *keyName) { - for (int i = 0; i < NUM_SDL_KEYS; i++) - { - if (stricmp(keyName, s_keyMap[i].keyName) == 0) - return i; - } - return -1; + for (int i = 0; i < NUM_SDL_KEYS; i++) + { + if (stricmp(keyName, s_keyMap[i].keyName) == 0) + return i; + } + return -1; } const char *CSDLInputSystem::GetKeyName(int keyIndex) { - if (keyIndex < 0 || keyIndex >= NUM_SDL_KEYS) - return NULL; - return s_keyMap[keyIndex].keyName; + if (keyIndex < 0 || keyIndex >= NUM_SDL_KEYS) + return nullptr; + return s_keyMap[keyIndex].keyName; } bool CSDLInputSystem::IsKeyPressed(int kbdNum, int keyIndex) { - // Get SDL key for given index and check if currently pressed - SDLKey sdlKey = s_keyMap[keyIndex].sdlKey; - return !!m_keyState[sdlKey]; + // Get SDL key for given index and check if currently pressed + SDL_Keycode sdlKey = s_keyMap[keyIndex].sdlKey; + return !!m_keyState[sdlKey]; } int CSDLInputSystem::GetMouseAxisValue(int mseNum, int axisNum) { - // Return value for given mouse axis - switch (axisNum) - { - case AXIS_X: return m_mouseX; - case AXIS_Y: return m_mouseY; - case AXIS_Z: return m_mouseZ; - default: return 0; - } + // Return value for given mouse axis + switch (axisNum) + { + case AXIS_X: return m_mouseX; + case AXIS_Y: return m_mouseY; + case AXIS_Z: return m_mouseZ; + default: return 0; + } } int CSDLInputSystem::GetMouseWheelDir(int mseNum) { - // Return wheel value - return m_mouseWheelDir; + // Return wheel value + return m_mouseWheelDir; } bool CSDLInputSystem::IsMouseButPressed(int mseNum, int butNum) { - // Return value for given mouse button - switch (butNum) - { - case 0: return !!(m_mouseButtons & SDL_BUTTON_LMASK); - case 1: return !!(m_mouseButtons & SDL_BUTTON_MMASK); - case 2: return !!(m_mouseButtons & SDL_BUTTON_RMASK); - case 3: return !!(m_mouseButtons & SDL_BUTTON_X1MASK); - case 4: return !!(m_mouseButtons & SDL_BUTTON_X2MASK); - default: return false; - } + // Return value for given mouse button + switch (butNum) + { + case 0: return !!(m_mouseButtons & SDL_BUTTON_LMASK); + case 1: return !!(m_mouseButtons & SDL_BUTTON_MMASK); + case 2: return !!(m_mouseButtons & SDL_BUTTON_RMASK); + case 3: return !!(m_mouseButtons & SDL_BUTTON_X1MASK); + case 4: return !!(m_mouseButtons & SDL_BUTTON_X2MASK); + default: return false; + } } int CSDLInputSystem::GetJoyAxisValue(int joyNum, int axisNum) { - // Get raw joystick axis value for given joystick from SDL (values range from -32768 to 32767) - SDL_Joystick *joystick = m_joysticks[joyNum]; - return SDL_JoystickGetAxis(joystick, axisNum); + // Get raw joystick axis value for given joystick from SDL (values range from -32768 to 32767) + SDL_Joystick *joystick = m_joysticks[joyNum]; + return SDL_JoystickGetAxis(joystick, axisNum); } bool CSDLInputSystem::IsJoyPOVInDir(int joyNum, int povNum, int povDir) { - // Get current joystick POV-hat value for given joystick and POV number from SDL and check if pointing in required direction - SDL_Joystick *joystick = m_joysticks[joyNum]; - int hatVal = SDL_JoystickGetHat(joystick, povNum); - switch (povDir) - { - case POV_UP: return !!(hatVal & SDL_HAT_UP); - case POV_DOWN: return !!(hatVal & SDL_HAT_DOWN); - case POV_LEFT: return !!(hatVal & SDL_HAT_LEFT); - case POV_RIGHT: return !!(hatVal & SDL_HAT_RIGHT); - default: return false; - } - return false; + // Get current joystick POV-hat value for given joystick and POV number from SDL and check if pointing in required direction + SDL_Joystick *joystick = m_joysticks[joyNum]; + int hatVal = SDL_JoystickGetHat(joystick, povNum); + switch (povDir) + { + case POV_UP: return !!(hatVal & SDL_HAT_UP); + case POV_DOWN: return !!(hatVal & SDL_HAT_DOWN); + case POV_LEFT: return !!(hatVal & SDL_HAT_LEFT); + case POV_RIGHT: return !!(hatVal & SDL_HAT_RIGHT); + default: return false; + } + return false; } bool CSDLInputSystem::IsJoyButPressed(int joyNum, int butNum) { - // Get current joystick button state for given joystick and button number from SDL - SDL_Joystick *joystick = m_joysticks[joyNum]; - return !!SDL_JoystickGetButton(joystick, butNum); + // Get current joystick button state for given joystick and button number from SDL + SDL_Joystick *joystick = m_joysticks[joyNum]; + return !!SDL_JoystickGetButton(joystick, butNum); } bool CSDLInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd) { - // SDL 1.2 does not support force feedback - return false; + // SDL 1.2 does not support force feedback + return false; } int CSDLInputSystem::GetNumKeyboards() { - // Return ANY_KEYBOARD as SDL 1.2 cannot handle multiple keyboards - return ANY_KEYBOARD; + // Return ANY_KEYBOARD as SDL 1.2 cannot handle multiple keyboards + return ANY_KEYBOARD; } - + int CSDLInputSystem::GetNumMice() { - // Return ANY_MOUSE as SDL 1.2 cannot handle multiple mice - return ANY_MOUSE; + // Return ANY_MOUSE as SDL 1.2 cannot handle multiple mice + return ANY_MOUSE; } - + int CSDLInputSystem::GetNumJoysticks() { - // Return number of joysticks found - return (int)m_joysticks.size(); + // Return number of joysticks found + return (int)m_joysticks.size(); } const KeyDetails *CSDLInputSystem::GetKeyDetails(int kbdNum) { - // Return NULL as SDL 1.2 cannot handle multiple keyboards - return NULL; + // Return nullptr as SDL 1.2 cannot handle multiple keyboards + return nullptr; } const MouseDetails *CSDLInputSystem::GetMouseDetails(int mseNum) { - // Return NULL as SDL 1.2 cannot handle multiple mice - return NULL; + // Return nullptr as SDL 1.2 cannot handle multiple mice + return nullptr; } const JoyDetails *CSDLInputSystem::GetJoyDetails(int joyNum) { - return &m_joyDetails[joyNum]; + return &m_joyDetails[joyNum]; } bool CSDLInputSystem::Poll() { - // Reset mouse wheel direction - m_mouseWheelDir = 0; + // Reset mouse wheel direction + m_mouseWheelDir = 0; - // Poll for event from SDL - SDL_Event e; - while (SDL_PollEvent(&e)) - { - if (e.type == SDL_QUIT) - return false; - else if (e.type == SDL_MOUSEBUTTONDOWN) + // Poll for event from SDL + SDL_Event e; + while (SDL_PollEvent(&e)) + { + switch (e.type) { - // Mouse wheel movements are not returned by SDL_GetMouseState below, so they are handled here instead - // The mouse absolute Z-axis value and mouse wheel direction value are updated appropriately - if (e.button.button == SDL_BUTTON_WHEELUP) + default: + break; + case SDL_QUIT: + return false; + case SDL_MOUSEWHEEL: + if (e.button.y > 0) { m_mouseZ += 5; m_mouseWheelDir = 1; } - else if (e.button.button == SDL_BUTTON_WHEELDOWN) + else if (e.button.y < 0) { m_mouseZ -= 5; m_mouseWheelDir = -1; } + break; } - } + } - // Get key state from SDL - m_keyState = SDL_GetKeyState(NULL); + // Get key state from SDL + m_keyState = SDL_GetKeyboardState(nullptr); - // Get mouse state from SDL (except mouse wheel which was handled earlier) - m_mouseButtons = SDL_GetMouseState(&m_mouseX, &m_mouseY); + // Get mouse state from SDL (except mouse wheel which was handled earlier) + m_mouseButtons = SDL_GetMouseState(&m_mouseX, &m_mouseY); - // Update joystick state (not required as called implicitly by SDL_PollEvent above) - //SDL_JoystickUpdate(); - return true; + // Update joystick state (not required as called implicitly by SDL_PollEvent above) + //SDL_JoystickUpdate(); + return true; } void CSDLInputSystem::SetMouseVisibility(bool visible) { - SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE); -} + SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE); +} diff --git a/Src/OSD/SDL/SDLInputSystem.h b/Src/OSD/SDL/SDLInputSystem.h index 2e15030..c853d9c 100644 --- a/Src/OSD/SDL/SDLInputSystem.h +++ b/Src/OSD/SDL/SDLInputSystem.h @@ -46,7 +46,7 @@ using namespace std; struct SDLKeyMapStruct { const char *keyName; - SDLKey sdlKey; + SDL_Scancode sdlKey; }; /* @@ -65,7 +65,7 @@ private: vector m_joyDetails; // Current key state obtained from SDL - Uint8 *m_keyState; + const Uint8 *m_keyState; // Current mouse state obtained from SDL int m_mouseX; diff --git a/Src/OSD/SDL/Thread.cpp b/Src/OSD/SDL/Thread.cpp index 5a61f20..99b09f2 100755 --- a/Src/OSD/SDL/Thread.cpp +++ b/Src/OSD/SDL/Thread.cpp @@ -45,12 +45,12 @@ UINT32 CThread::GetTicks() return SDL_GetTicks(); } -CThread *CThread::CreateThread(ThreadStart start, void *startParam) +CThread *CThread::CreateThread(const std::string &name, ThreadStart start, void *startParam) { - SDL_Thread *impl = SDL_CreateThread(start, startParam); + SDL_Thread *impl = SDL_CreateThread(start, name.c_str(), startParam); if (impl == NULL) return NULL; - return new CThread(impl); + return new CThread(name, impl); } CSemaphore *CThread::CreateSemaphore(UINT32 initVal) @@ -82,14 +82,26 @@ const char *CThread::GetLastError() return SDL_GetError(); } -CThread::CThread(void *impl) : m_impl(impl) +CThread::CThread(const std::string &name, void *impl) + : m_name(name), + m_impl(impl) + { // } CThread::~CThread() { - Kill(); + // User should have called Wait() before thread object is destroyed + if (nullptr != m_impl) + { + ErrorLog("Runaway thread error. A thread was not properly halted: %s\n", GetName()); + } +} + +const std::string &CThread::GetName() const +{ + return m_name; } UINT32 CThread::GetId() @@ -97,13 +109,6 @@ UINT32 CThread::GetId() return SDL_GetThreadID((SDL_Thread*)m_impl); } -void CThread::Kill() -{ - if (m_impl != NULL) - SDL_KillThread((SDL_Thread*)m_impl); - m_impl = NULL; -} - int CThread::Wait() { int status; diff --git a/Src/OSD/Thread.h b/Src/OSD/Thread.h index d3ca28c..cf49546 100755 --- a/Src/OSD/Thread.h +++ b/Src/OSD/Thread.h @@ -28,6 +28,8 @@ #ifndef INCLUDED_THREADS_H #define INCLUDED_THREADS_H +#include + class CSemaphore; class CMutex; class CCondVar; @@ -42,9 +44,10 @@ typedef int (*ThreadStart)(void *startParam); class CThread { private: + const std::string m_name; void *m_impl; - CThread(void *impl); + CThread(const std::string &name, void *impl); public: /* @@ -62,11 +65,11 @@ public: static UINT32 GetTicks(); /* - * CreateThread + * CreateThread * * Creates a new thread with the given ThreadStart callback and start parameter. The thread starts running immediately. */ - static CThread *CreateThread(ThreadStart start, void *startParam); + static CThread *CreateThread(const std::string &name, ThreadStart start, void *startParam); /* * CreateSemaphore @@ -101,6 +104,13 @@ public: */ ~CThread(); + /* + * GetName + * + * Returns the name of this thread. + */ + const std::string &GetName() const; + /* * GetId * @@ -108,13 +118,6 @@ public: */ UINT32 GetId(); - /* - * Kill - * - * Kills this thread. - */ - void Kill(); - /* * Wait * diff --git a/Src/OSD/Windows/DirectInputSystem.cpp b/Src/OSD/Windows/DirectInputSystem.cpp index d6a32eb..84860d8 100644 --- a/Src/OSD/Windows/DirectInputSystem.cpp +++ b/Src/OSD/Windows/DirectInputSystem.cpp @@ -428,11 +428,11 @@ const char *CDirectInputSystem::ConstructName(bool useRawInput, bool useXInput) return (useXInput ? "Xinput" : "DirectInput"); } -CDirectInputSystem::CDirectInputSystem(const Util::Config::Node &config, bool useRawInput, bool useXInput) : +CDirectInputSystem::CDirectInputSystem(const Util::Config::Node &config, SDL_Window *window, bool useRawInput, bool useXInput) : CInputSystem(ConstructName(useRawInput, useXInput)), m_config(config), m_useRawInput(useRawInput), m_useXInput(useXInput), m_enableFFeedback(true), - m_initializedCOM(false), m_activated(false), m_hwnd(NULL), m_screenW(0), m_screenH(0), + m_initializedCOM(false), m_activated(false), m_window(window), m_hwnd(NULL), m_screenW(0), m_screenH(0), m_getRIDevListPtr(NULL), m_getRIDevInfoPtr(NULL), m_regRIDevsPtr(NULL), m_getRIDataPtr(NULL), m_xiGetCapabilitiesPtr(NULL), m_xiGetStatePtr(NULL), m_xiSetStatePtr(NULL), m_di8(NULL), m_di8Keyboard(NULL), m_di8Mouse(NULL) { @@ -2050,9 +2050,11 @@ bool CDirectInputSystem::Poll() { // If not, then get Window handle of SDL window SDL_SysWMinfo info; - SDL_VERSION(&info.version); - if (SDL_GetWMInfo(&info)) - m_hwnd = info.window; + SDL_VERSION(&info.version); + if (SDL_GetWindowWMInfo(m_window, &info)) + { + m_hwnd = info.info.win.window; + } // Tell SDL to pass on all Windows events // Removed - see below @@ -2102,6 +2104,17 @@ bool CDirectInputSystem::Poll() } } + // SDL2: I'm not sure how the SDL1.x code was detecting quit events but in + // SDL2, it seems that we want to explicitly run SDL_PollEvent() after we + // have peeked at the message queue ourselves (above). + // Wait or poll for event from SDL + SDL_Event e; + while (SDL_PollEvent(&e)) + { + if (e.type == SDL_QUIT) + return false; + } + // Poll keyboards, mice and joysticks PollKeyboardsAndMice(); PollJoysticks(); diff --git a/Src/OSD/Windows/DirectInputSystem.h b/Src/OSD/Windows/DirectInputSystem.h index 2b03976..4bee0a8 100644 --- a/Src/OSD/Windows/DirectInputSystem.h +++ b/Src/OSD/Windows/DirectInputSystem.h @@ -33,10 +33,13 @@ #include "Inputs/InputSource.h" #include "Inputs/InputSystem.h" +#include + #define WIN32_LEAN_AND_MEAN #include #include #include +#include #include using namespace std; @@ -125,6 +128,7 @@ private: bool m_initializedCOM; bool m_activated; + SDL_Window *m_window = nullptr; // Function pointers for RawInput API GetRawInputDeviceListPtr m_getRIDevListPtr; @@ -234,7 +238,7 @@ public: * to the same shared axis and so cannot be distinguished when pressed together. * If enableFFeedback is true then force feedback is enabled (for those joysticks which are force feedback capable). */ - CDirectInputSystem(const Util::Config::Node &config, bool useRawInput, bool useXInput); + CDirectInputSystem(const Util::Config::Node &config, SDL_Window *window, bool useRawInput, bool useXInput); ~CDirectInputSystem();