SDL1 to SDL2 internal changes

This commit is contained in:
SpinDizzy 2020-04-19 08:34:58 +00:00
parent 14e2a50212
commit 4f347ff3f1
12 changed files with 466 additions and 416 deletions

View file

@ -1,3 +1,9 @@
#
# TODO: MacOS port is probably broken. Someone with MacOS needs to figure out
# how to compile with SDL2.
#
## ##
## Supermodel ## Supermodel
## A Sega Model 3 Arcade Emulator. ## A Sega Model 3 Arcade Emulator.
@ -51,7 +57,7 @@ LD = gcc
# #
SDL_CFLAGS = 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 # OSX-specific

View file

@ -50,15 +50,15 @@ LD = gcc
# SDL # SDL
# #
SDL_CFLAGS = `sdl-config --cflags` SDL2_CFLAGS = `sdl2-config --cflags`
SDL_LIBS = `sdl-config --libs` SDL2_LIBS = `sdl2-config --libs`
# #
# UNIX-specific # UNIX-specific
# #
PLATFORM_CFLAGS = $(SDL_CFLAGS) PLATFORM_CFLAGS = $(SDL2_CFLAGS)
PLATFORM_LDFLAGS = $(SDL_LIBS) -lGL -lGLU -lz -lm -lstdc++ PLATFORM_LDFLAGS = $(SDL2_LIBS) -lGL -lGLU -lz -lm -lstdc++
############################################################################### ###############################################################################

View file

@ -33,7 +33,7 @@
# Configuration # Configuration
# #
# Edit as necessary. Some users may need to edit the "Platform 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 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 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
SDL_LIB_DIR = C:/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/lib 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 # Toolchain
@ -74,25 +74,20 @@ ifeq ($(strip $(MSYSTEM)),)
endif endif
# #
# SDL # SDL2
# #
# SDL2_LIBS = -lmingw32 -lSDL2main -lSDL2 -luser32 -lgdi32 -lwinmm -limm32 -lversion -lsetupapi
# (At least for SDL) The linked libs order is fundamental for a successful compiling! SDL2_CFLAGS =
# 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
# #
# MinGW/Windows-specific # MinGW/Windows-specific
# #
PLATFORM_INCLUDE_DIR = $(SDL_INCLUDE_DIR) PLATFORM_INCLUDE_DIR = $(SDL2_INCLUDE_DIR)
PLATFORM_LIB_DIR = $(SDL_LIB_DIR) PLATFORM_LIB_DIR = $(SDL2_LIB_DIR)
PLATFORM_LIBS = -ldinput8 -lglu32 -lole32 -loleaut32 -lopengl32 -lwbemuuid -lws2_32 -lz PLATFORM_LIBS = -ldinput8 -lglu32 -lole32 -loleaut32 -lopengl32 -lwbemuuid -lws2_32 -lz
PLATFORM_CFLAGS = $(SDL_CFLAGS) -DSUPERMODEL_WIN32 $(addprefix -I,$(sort $(PLATFORM_INCLUDE_DIR))) PLATFORM_CFLAGS = $(SDL2_CFLAGS) -DSUPERMODEL_WIN32 $(addprefix -I,$(sort $(PLATFORM_INCLUDE_DIR)))
PLATFORM_LDFLAGS = -static -L$(sort $(PLATFORM_LIB_DIR)) $(SDL_LIBS) $(PLATFORM_LIBS) PLATFORM_LDFLAGS = -static -L$(sort $(PLATFORM_LIB_DIR)) $(SDL2_LIBS) $(PLATFORM_LIBS)
############################################################################### ###############################################################################

View file

@ -2250,23 +2250,23 @@ bool CModel3::StartThreads(void)
// Create PPC main board thread, if multi-threading GPU // Create PPC main board thread, if multi-threading GPU
if (m_gpuMultiThreaded) if (m_gpuMultiThreaded)
{ {
ppcBrdThread = CThread::CreateThread(StartMainBoardThread, this); ppcBrdThread = CThread::CreateThread("MainBoard", StartMainBoardThread, this);
if (ppcBrdThread == NULL) if (ppcBrdThread == NULL)
goto ThreadError; goto ThreadError;
} }
// Create sound board thread (sync'd or unsync'd) // Create sound board thread (sync'd or unsync'd)
if (syncSndBrdThread) if (syncSndBrdThread)
sndBrdThread = CThread::CreateThread(StartSoundBoardThreadSyncd, this); sndBrdThread = CThread::CreateThread("SoundBoardSync", StartSoundBoardThreadSyncd, this);
else else
sndBrdThread = CThread::CreateThread(StartSoundBoardThread, this); sndBrdThread = CThread::CreateThread("SoundBoardNoSync", StartSoundBoardThread, this);
if (sndBrdThread == NULL) if (sndBrdThread == NULL)
goto ThreadError; goto ThreadError;
// Create drive board thread, if drive board is attached // Create drive board thread, if drive board is attached
if (DriveBoard.IsAttached()) if (DriveBoard.IsAttached())
{ {
drvBrdThread = CThread::CreateThread(StartDriveBoardThread, this); drvBrdThread = CThread::CreateThread("DriveBoard", StartDriveBoardThread, this);
if (drvBrdThread == NULL) if (drvBrdThread == NULL)
goto ThreadError; goto ThreadError;
} }
@ -3237,7 +3237,7 @@ CModel3::CModel3(const Util::Config::Node &config)
} }
// Dumps a memory region to a file for debugging purposes // 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) static void Dump(const char *file, uint8_t *buf, size_t size, bool reverse32, bool reverse16)
{ {
FILE *fp = fopen(file, "wb"); 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 else
printf("unable to dump %s\n", file); printf("unable to dump %s\n", file);
} }
*/ #endif
CModel3::~CModel3(void) CModel3::~CModel3(void)
{ {

View file

@ -217,6 +217,7 @@ static void MixChannels(unsigned numSamples, INT16 *leftBuffer, INT16 *rightBuff
#endif // NUM_CHANNELS #endif // NUM_CHANNELS
} }
/*
static void LogAudioInfo(SDL_AudioSpec *fmt) static void LogAudioInfo(SDL_AudioSpec *fmt)
{ {
InfoLog("Audio device information:"); InfoLog("Audio device information:");
@ -225,6 +226,7 @@ static void LogAudioInfo(SDL_AudioSpec *fmt)
InfoLog("Sample Format: %d", fmt->format); InfoLog("Sample Format: %d", fmt->format);
InfoLog(""); InfoLog("");
} }
*/
bool OpenAudio() bool OpenAudio()
{ {
@ -241,18 +243,9 @@ bool OpenAudio()
fmt.samples = playSamples; fmt.samples = playSamples;
fmt.callback = PlayCallback; fmt.callback = PlayCallback;
// Try opening SDL audio output with that specification // Force SDL to use the format we requested; it will convert if necessary
SDL_AudioSpec obtained; if (SDL_OpenAudio(&fmt, nullptr) < 0)
if (SDL_OpenAudio(&fmt, &obtained) < 0)
return ErrorLog("Unable to open 44.1KHz 2-channel audio with SDL: %s\n", SDL_GetError()); 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 // Create audio buffer
audioBufferSize = SAMPLE_RATE * BYTES_PER_SAMPLE * latency / MAX_LATENCY; audioBufferSize = SAMPLE_RATE * BYTES_PER_SAMPLE * latency / MAX_LATENCY;

View file

@ -92,6 +92,8 @@ static Util::Config::Node s_runtime_config("Global");
Display Management Display Management
******************************************************************************/ ******************************************************************************/
static SDL_Window *s_window = nullptr;
/* /*
* Position and size of rectangular region within OpenGL display to render to. * Position and size of rectangular region within OpenGL display to render to.
* Unlike the config tree, these end up containing the actual resolution (and * 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) static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *xResPtr, unsigned *yResPtr, unsigned *totalXResPtr, unsigned *totalYResPtr, bool keepAspectRatio)
{ {
// What resolution did we actually get? // What resolution did we actually get?
const SDL_VideoInfo *VideoInfo = SDL_GetVideoInfo(); int actualWidth;
*totalXResPtr = VideoInfo->current_w; int actualHeight;
*totalYResPtr = VideoInfo->current_h; 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 // If required, fix the aspect ratio of the resolution that the user passed to match Model 3 ratio
float xRes = float(*xResPtr); float xRes = float(*xResPtr);
@ -126,10 +130,10 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *
*yOffsetPtr = (*yResPtr - (unsigned) yRes)/2; *yOffsetPtr = (*yResPtr - (unsigned) yRes)/2;
// If the desired resolution is smaller than what we got, re-center again // If the desired resolution is smaller than what we got, re-center again
if (int(*xResPtr) < VideoInfo->current_w) if (int(*xResPtr) < actualWidth)
*xOffsetPtr += (VideoInfo->current_w - *xResPtr)/2; *xOffsetPtr += (actualWidth - *xResPtr)/2;
if (int(*yResPtr) < VideoInfo->current_h) if (int(*yResPtr) < actualHeight)
*yOffsetPtr += (VideoInfo->current_h - *yResPtr)/2; *yOffsetPtr += (actualHeight - *yResPtr)/2;
// OpenGL initialization // OpenGL initialization
glViewport(0,0,*xResPtr,*yResPtr); glViewport(0,0,*xResPtr,*yResPtr);
@ -143,7 +147,7 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
SDL_GL_SwapBuffers(); SDL_GL_SwapWindow(s_window);
} }
// Write back resolution parameters // Write back resolution parameters
@ -159,7 +163,8 @@ static bool SetGLGeometry(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *
{ {
glScissor(0, correction, *totalXResPtr, *totalYResPtr - (correction * 2)); glScissor(0, correction, *totalXResPtr, *totalYResPtr - (correction * 2));
} }
else { else
{
glScissor(*xOffsetPtr + correction, *yOffsetPtr + correction, *xResPtr - (correction * 2), *yResPtr - (correction * 2)); glScissor(*xOffsetPtr + correction, *yOffsetPtr + correction, *xResPtr - (correction * 2), *yResPtr - (correction * 2));
} }
return OKAY; 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 * NOTE: keepAspectRatio should always be true. It has not yet been tested with
* the wide screen hack. * 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; 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 // 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()); return ErrorLog("Unable to initialize SDL video subsystem: %s\n", SDL_GetError());
// Important GL attributes // Important GL attributes
@ -193,18 +206,32 @@ static bool CreateGLScreen(const std::string &caption, unsigned *xOffsetPtr, uns
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,8); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
// Set vsync
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, s_runtime_config["VSync"].ValueAsDefault<bool>(false) ? 1 : 0);
// Set video mode // 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()); ErrorLog("Unable to create an OpenGL display: %s\n", SDL_GetError());
return FAIL; return FAIL;
} }
// Create window caption if (focusWindow)
SDL_WM_SetCaption(caption.c_str(),NULL); {
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<bool>(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 // Initialize GLEW, allowing us to use features beyond OpenGL 1.2
err = glewInit(); 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); 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) static bool ResizeGLScreen(unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *xResPtr, unsigned *yResPtr, unsigned *totalXResPtr, unsigned *totalYResPtr, bool keepAspectRatio, bool fullScreen)
{ {
// Set video mode // Set full screen mode
if (SDL_SetVideoMode(*xResPtr,*yResPtr,0,SDL_OPENGL|(fullScreen?SDL_FULLSCREEN|SDL_HWSURFACE:0)) == NULL) 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; return FAIL;
} }
@ -240,7 +276,7 @@ static void PrintGLInfo(bool createScreen, bool infoLog, bool printExtensions)
unsigned xOffset, yOffset, xRes=496, yRes=384, totalXRes, totalYRes; unsigned xOffset, yOffset, xRes=496, yRes=384, totalXRes, totalYRes;
if (createScreen) 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"); ErrorLog("Unable to query OpenGL.\n");
return; return;
@ -771,7 +807,7 @@ void EndFrameVideo()
UpdateCrosshairs(currentInputs, videoInputs, s_runtime_config["Crosshairs"].ValueAs<unsigned>()); UpdateCrosshairs(currentInputs, videoInputs, s_runtime_config["Crosshairs"].ValueAs<unsigned>());
// Swap the buffers // Swap the buffers
SDL_GL_SwapBuffers(); SDL_GL_SwapWindow(s_window);
} }
static void SuperSleep(UINT32 time) static void SuperSleep(UINT32 time)
@ -814,15 +850,16 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In
// Load NVRAM // Load NVRAM
LoadNVRAM(Model3); LoadNVRAM(Model3);
// Start up SDL and open a GL window // Set the video mode
char baseTitleStr[128]; char baseTitleStr[128];
char titleStr[128]; char titleStr[128];
totalXRes = xRes = s_runtime_config["XResolution"].ValueAs<unsigned>(); totalXRes = xRes = s_runtime_config["XResolution"].ValueAs<unsigned>();
totalYRes = yRes = s_runtime_config["YResolution"].ValueAs<unsigned>(); totalYRes = yRes = s_runtime_config["YResolution"].ValueAs<unsigned>();
sprintf(baseTitleStr, "Supermodel - %s", game.title.c_str()); sprintf(baseTitleStr, "Supermodel - %s", game.title.c_str());
SDL_SetWindowTitle(s_window, baseTitleStr);
bool stretch = s_runtime_config["Stretch"].ValueAs<bool>(); bool stretch = s_runtime_config["Stretch"].ValueAs<bool>();
bool fullscreen = s_runtime_config["FullScreen"].ValueAs<bool>(); bool fullscreen = s_runtime_config["FullScreen"].ValueAs<bool>();
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; return 1;
// Info log GL information // Info log GL information
@ -965,13 +1002,13 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In
Model3->PauseThreads(); Model3->PauseThreads();
SetAudioEnabled(false); SetAudioEnabled(false);
sprintf(titleStr, "%s (Paused)", baseTitleStr); sprintf(titleStr, "%s (Paused)", baseTitleStr);
SDL_WM_SetCaption(titleStr,NULL); SDL_SetWindowTitle(s_window, titleStr);
} }
else else
{ {
Model3->ResumeThreads(); Model3->ResumeThreads();
SetAudioEnabled(true); SetAudioEnabled(true);
SDL_WM_SetCaption(baseTitleStr,NULL); SDL_SetWindowTitle(s_window, baseTitleStr);
} }
// Send paused value as output // Send paused value as output
@ -1156,14 +1193,13 @@ int Supermodel(const Game &game, ROMSet *rom_set, IEmulator *Model3, CInputs *In
// Frame rate and limiting // Frame rate and limiting
unsigned currentFPSTicks = SDL_GetTicks(); unsigned currentFPSTicks = SDL_GetTicks();
unsigned currentTicks = currentFPSTicks;
if (s_runtime_config["ShowFrameRate"].ValueAs<bool>()) if (s_runtime_config["ShowFrameRate"].ValueAs<bool>())
{ {
++fpsFramesElapsed; ++fpsFramesElapsed;
if((currentFPSTicks-prevFPSTicks) >= 1000) // update FPS every 1 second (each tick is 1 ms) 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)" : ""); 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 prevFPSTicks = currentFPSTicks; // reset tick count
fpsFramesElapsed = 0; // reset frame 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 the user wants to configure the inputs, do that now
if (configure) 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 // 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 // game was specified, otherwise the game's node) in the file config, which
// will be written back to disk // will be written back to disk
@ -1250,16 +1293,6 @@ static bool ConfigureInputs(CInputs *Inputs, Util::Config::Node *fileConfig, Uti
fileConfigRoot = &fileConfig->Add(game.name); 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 // Configure the inputs
if (Inputs->ConfigureInputs(game, xOffset, yOffset, xRes, yRes)) if (Inputs->ConfigureInputs(game, xOffset, yOffset, xRes, yRes))
{ {
@ -1672,6 +1705,7 @@ int main(int argc, char **argv)
} }
if (cmd_line.print_gl_info) if (cmd_line.print_gl_info)
{ {
// We must exit after this because CreateGLScreen() is used
PrintGLInfo(true, false, false); PrintGLInfo(true, false, false);
return 0; 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 Util::Config::MergeINISections(&s_runtime_config, config4, cmd_line.config); // apply command line overrides once more
} }
LogConfig(s_runtime_config); LogConfig(s_runtime_config);
std::string selectedInputSystem = s_runtime_config["InputSystem"].ValueAs<std::string>();
// Initialize SDL (individual subsystems get initialized later) // Initialize SDL (individual subsystems get initialized later)
if (SDL_Init(0) != 0) if (SDL_Init(0) != 0)
@ -1723,33 +1758,42 @@ int main(int argc, char **argv)
return 1; return 1;
} }
// Create Model 3 emulator // Begin initializing various subsystems...
#ifdef DEBUG
IEmulator *Model3 = s_gfxStatePath.empty() ? static_cast<IEmulator *>(new CModel3(s_runtime_config)) : static_cast<IEmulator *>(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;
int exitCode = 0; int exitCode = 0;
IEmulator *Model3 = nullptr;
CInputSystem *InputSystem = nullptr;
CInputs *Inputs = nullptr;
COutputs *Outputs = nullptr;
#ifdef SUPERMODEL_DEBUGGER #ifdef SUPERMODEL_DEBUGGER
Debugger::CSupermodelDebugger *Debugger = NULL; Debugger::CSupermodelDebugger *Debugger = NULL;
#endif // SUPERMODEL_DEBUGGER #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<IEmulator *>(new CModel3(s_runtime_config)) : static_cast<IEmulator *>(new CModel3GraphicsState(s_runtime_config, s_gfxStatePath));
#else
Model3 = new CModel3(s_runtime_config);
#endif
// Create input system // Create input system
std::string selectedInputSystem = s_runtime_config["InputSystem"].ValueAs<std::string>();
if (selectedInputSystem == "sdl") if (selectedInputSystem == "sdl")
InputSystem = new CSDLInputSystem(); InputSystem = new CSDLInputSystem();
#ifdef SUPERMODEL_WIN32 #ifdef SUPERMODEL_WIN32
else if (selectedInputSystem == "dinput") 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") 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") 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 #endif // SUPERMODEL_WIN32
else else
{ {
@ -1836,6 +1880,7 @@ Exit:
delete InputSystem; delete InputSystem;
if (Outputs != NULL) if (Outputs != NULL)
delete Outputs; delete Outputs;
DestroyGLScreen();
SDL_Quit(); SDL_Quit();
if (exitCode) if (exitCode)

View file

@ -23,6 +23,10 @@
* SDLInputSystem.cpp * SDLInputSystem.cpp
* *
* Implementation of SDL input system. * Implementation of SDL input system.
*
* TODO:
* -----
* - Implement multiple keyboard and mouse support.
*/ */
#include "SDLInputSystem.h" #include "SDLInputSystem.h"
@ -34,157 +38,137 @@ using namespace std;
SDLKeyMapStruct CSDLInputSystem::s_keyMap[] = SDLKeyMapStruct CSDLInputSystem::s_keyMap[] =
{ {
// General keys // General keys
{ "BACKSPACE", SDLK_BACKSPACE }, { "BACKSPACE", SDL_SCANCODE_BACKSPACE },
{ "TAB", SDLK_TAB }, { "TAB", SDL_SCANCODE_TAB },
{ "CLEAR", SDLK_CLEAR }, { "CLEAR", SDL_SCANCODE_CLEAR },
{ "RETURN", SDLK_RETURN }, { "RETURN", SDL_SCANCODE_RETURN },
{ "PAUSE", SDLK_PAUSE }, { "PAUSE", SDL_SCANCODE_PAUSE },
{ "ESCAPE", SDLK_ESCAPE }, { "ESCAPE", SDL_SCANCODE_ESCAPE },
{ "SPACE", SDLK_SPACE }, { "SPACE", SDL_SCANCODE_SPACE },
{ "EXCLAIM", SDLK_EXCLAIM }, { "QUOTE", SDL_SCANCODE_APOSTROPHE },
{ "DBLQUOTE", SDLK_QUOTEDBL }, { "LEFTPAREN", SDL_SCANCODE_KP_LEFTPAREN },
{ "HASH", SDLK_HASH }, { "RIGHTPAREN", SDL_SCANCODE_KP_RIGHTPAREN },
{ "DOLLAR", SDLK_DOLLAR }, { "COMMA", SDL_SCANCODE_COMMA },
{ "AMPERSAND", SDLK_AMPERSAND }, { "MINUS", SDL_SCANCODE_MINUS },
{ "QUOTE", SDLK_QUOTE }, { "PERIOD", SDL_SCANCODE_PERIOD },
{ "LEFTPAREN", SDLK_LEFTPAREN }, { "SLASH", SDL_SCANCODE_SLASH },
{ "RIGHTPAREN", SDLK_RIGHTPAREN }, { "0", SDL_SCANCODE_0 },
{ "ASTERISK", SDLK_ASTERISK }, { "1", SDL_SCANCODE_1 },
{ "PLUS", SDLK_PLUS }, { "2", SDL_SCANCODE_2 },
{ "COMMA", SDLK_COMMA }, { "3", SDL_SCANCODE_3 },
{ "MINUS", SDLK_MINUS }, { "4", SDL_SCANCODE_4 },
{ "PERIOD", SDLK_PERIOD }, { "5", SDL_SCANCODE_5 },
{ "SLASH", SDLK_SLASH }, { "6", SDL_SCANCODE_6 },
{ "0", SDLK_0 }, { "7", SDL_SCANCODE_7 },
{ "1", SDLK_1 }, { "8", SDL_SCANCODE_8 },
{ "2", SDLK_2 }, { "9", SDL_SCANCODE_9 },
{ "3", SDLK_3 }, { "SEMICOLON", SDL_SCANCODE_SEMICOLON },
{ "4", SDLK_4 }, { "EQUALS", SDL_SCANCODE_EQUALS },
{ "5", SDLK_5 }, { "LEFTBRACKET", SDL_SCANCODE_LEFTBRACKET },
{ "6", SDLK_6 }, { "BACKSLASH", SDL_SCANCODE_BACKSLASH },
{ "7", SDLK_7 }, { "RIGHTBRACKET", SDL_SCANCODE_RIGHTBRACKET },
{ "8", SDLK_8 }, { "BACKQUOTE", SDL_SCANCODE_GRAVE },
{ "9", SDLK_9 }, { "A", SDL_SCANCODE_A },
{ "COLON", SDLK_COLON }, { "B", SDL_SCANCODE_B },
{ "SEMICOLON", SDLK_SEMICOLON }, { "C", SDL_SCANCODE_C },
{ "LESS", SDLK_LESS }, { "D", SDL_SCANCODE_D },
{ "EQUALS", SDLK_EQUALS }, { "E", SDL_SCANCODE_E },
{ "GREATER", SDLK_GREATER }, { "F", SDL_SCANCODE_F },
{ "QUESTION", SDLK_QUESTION }, { "G", SDL_SCANCODE_G },
{ "AT", SDLK_AT }, { "H", SDL_SCANCODE_H },
{ "LEFTBRACKET", SDLK_LEFTBRACKET }, { "I", SDL_SCANCODE_I },
{ "BACKSLASH", SDLK_BACKSLASH }, { "J", SDL_SCANCODE_J },
{ "RIGHTBRACKET", SDLK_RIGHTBRACKET }, { "K", SDL_SCANCODE_K },
{ "CARET", SDLK_CARET }, { "L", SDL_SCANCODE_L },
{ "UNDERSCORE", SDLK_UNDERSCORE }, { "M", SDL_SCANCODE_M },
{ "BACKQUOTE", SDLK_BACKQUOTE }, { "N", SDL_SCANCODE_N },
{ "A", SDLK_a }, { "O", SDL_SCANCODE_O },
{ "B", SDLK_b }, { "P", SDL_SCANCODE_P },
{ "C", SDLK_c }, { "Q", SDL_SCANCODE_Q },
{ "D", SDLK_d }, { "R", SDL_SCANCODE_R },
{ "E", SDLK_e }, { "S", SDL_SCANCODE_S },
{ "F", SDLK_f }, { "T", SDL_SCANCODE_T },
{ "G", SDLK_g }, { "U", SDL_SCANCODE_U },
{ "H", SDLK_h }, { "V", SDL_SCANCODE_V },
{ "I", SDLK_i }, { "W", SDL_SCANCODE_W },
{ "J", SDLK_j }, { "X", SDL_SCANCODE_X },
{ "K", SDLK_k }, { "Y", SDL_SCANCODE_Y },
{ "L", SDLK_l }, { "Z", SDL_SCANCODE_Z },
{ "M", SDLK_m }, { "DEL", SDL_SCANCODE_DELETE },
{ "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 // Keypad
{ "KEYPAD0", SDLK_KP0 }, { "KEYPAD0", SDL_SCANCODE_KP_0 },
{ "KEYPAD1", SDLK_KP1 }, { "KEYPAD1", SDL_SCANCODE_KP_1 },
{ "KEYPAD2", SDLK_KP2 }, { "KEYPAD2", SDL_SCANCODE_KP_2 },
{ "KEYPAD3", SDLK_KP3 }, { "KEYPAD3", SDL_SCANCODE_KP_3 },
{ "KEYPAD4", SDLK_KP4 }, { "KEYPAD4", SDL_SCANCODE_KP_4 },
{ "KEYPAD5", SDLK_KP5 }, { "KEYPAD5", SDL_SCANCODE_KP_5 },
{ "KEYPAD6", SDLK_KP6 }, { "KEYPAD6", SDL_SCANCODE_KP_6 },
{ "KEYPAD7", SDLK_KP7 }, { "KEYPAD7", SDL_SCANCODE_KP_7 },
{ "KEYPAD8", SDLK_KP8 }, { "KEYPAD8", SDL_SCANCODE_KP_8 },
{ "KEYPAD9", SDLK_KP9 }, { "KEYPAD9", SDL_SCANCODE_KP_9 },
{ "KEYPADPERIOD", SDLK_KP_PERIOD }, { "KEYPADPERIOD", SDL_SCANCODE_KP_PERIOD },
{ "KEYPADDIVIDE", SDLK_KP_DIVIDE }, { "KEYPADDIVIDE", SDL_SCANCODE_KP_DIVIDE },
{ "KEYPADMULTIPLY", SDLK_KP_MULTIPLY }, { "KEYPADMULTIPLY", SDL_SCANCODE_KP_MULTIPLY },
{ "KEYPADMINUS", SDLK_KP_MINUS }, { "KEYPADMINUS", SDL_SCANCODE_KP_MINUS },
{ "KEYPADPLUS", SDLK_KP_PLUS }, { "KEYPADPLUS", SDL_SCANCODE_KP_PLUS },
{ "KEYPADENTER", SDLK_KP_ENTER }, { "KEYPADENTER", SDL_SCANCODE_KP_ENTER },
{ "KEYPADEQUALS", SDLK_KP_EQUALS }, { "KEYPADEQUALS", SDL_SCANCODE_KP_EQUALS },
// Arrows + Home/End Pad // Arrows + Home/End Pad
{ "UP", SDLK_UP }, { "UP", SDL_SCANCODE_UP },
{ "DOWN", SDLK_DOWN }, { "DOWN", SDL_SCANCODE_DOWN },
{ "RIGHT", SDLK_RIGHT }, { "RIGHT", SDL_SCANCODE_RIGHT },
{ "LEFT", SDLK_LEFT }, { "LEFT", SDL_SCANCODE_LEFT },
{ "INSERT", SDLK_INSERT }, { "INSERT", SDL_SCANCODE_INSERT },
{ "HOME", SDLK_HOME }, { "HOME", SDL_SCANCODE_HOME },
{ "END", SDLK_END }, { "END", SDL_SCANCODE_END },
{ "PGUP", SDLK_PAGEUP }, { "PGUP", SDL_SCANCODE_PAGEUP },
{ "PGDN", SDLK_PAGEDOWN }, { "PGDN", SDL_SCANCODE_PAGEDOWN },
// Function Key // Function Key
{ "F1", SDLK_F1 }, { "F1", SDL_SCANCODE_F1 },
{ "F2", SDLK_F2 }, { "F2", SDL_SCANCODE_F2 },
{ "F3", SDLK_F3 }, { "F3", SDL_SCANCODE_F3 },
{ "F4", SDLK_F4 }, { "F4", SDL_SCANCODE_F4 },
{ "F5", SDLK_F5 }, { "F5", SDL_SCANCODE_F5 },
{ "F6", SDLK_F6 }, { "F6", SDL_SCANCODE_F6 },
{ "F7", SDLK_F7 }, { "F7", SDL_SCANCODE_F7 },
{ "F8", SDLK_F8 }, { "F8", SDL_SCANCODE_F8 },
{ "F9", SDLK_F9 }, { "F9", SDL_SCANCODE_F9 },
{ "F10", SDLK_F10 }, { "F10", SDL_SCANCODE_F10 },
{ "F11", SDLK_F11 }, { "F11", SDL_SCANCODE_F11 },
{ "F12", SDLK_F12 }, { "F12", SDL_SCANCODE_F12 },
{ "F13", SDLK_F13 }, { "F13", SDL_SCANCODE_F13 },
{ "F14", SDLK_F14 }, { "F14", SDL_SCANCODE_F14 },
{ "F15", SDLK_F15 }, { "F15", SDL_SCANCODE_F15 },
// Modifier Keys // Modifier Keys
// Removed Numlock, Capslock and Scrollock as don't seem to be handled well by SDL // Removed Numlock, Capslock and Scrollock as don't seem to be handled well by SDL
//{ "NUMLOCK", SDLK_NUMLOCK }, //{ "NUMLOCK", SDLK_NUMLOCK },
//{ "CAPSLOCK", SDLK_CAPSLOCK }, //{ "CAPSLOCK", SDL_SCANCODE_CAPSLOCK },
//{ "SCROLLLOCK", SDLK_SCROLLOCK }, //{ "SCROLLLOCK", SDLK_SCROLLOCK },
{ "RIGHTSHIFT", SDLK_RSHIFT }, { "RIGHTSHIFT", SDL_SCANCODE_RSHIFT },
{ "LEFTSHIFT", SDLK_LSHIFT }, { "LEFTSHIFT", SDL_SCANCODE_LSHIFT },
{ "RIGHTCTRL", SDLK_RCTRL }, { "RIGHTCTRL", SDL_SCANCODE_RCTRL },
{ "LEFTCTRL", SDLK_LCTRL }, { "LEFTCTRL", SDL_SCANCODE_LCTRL },
{ "RIGHTALT", SDLK_RALT }, { "RIGHTALT", SDL_SCANCODE_RALT },
{ "LEFTALT", SDLK_LALT }, { "LEFTALT", SDL_SCANCODE_LALT },
{ "RIGHTMETA", SDLK_RMETA }, { "RIGHTMETA", SDL_SCANCODE_RGUI },
{ "LEFTMETA", SDLK_LMETA }, { "LEFTMETA", SDL_SCANCODE_LGUI },
{ "RIGHTWINDOWS", SDLK_RSUPER }, { "ALTGR", SDL_SCANCODE_MODE },
{ "LEFTWINDOWS", SDLK_LSUPER },
{ "ALTGR", SDLK_MODE },
{ "COMPOSE", SDLK_COMPOSE },
// Other // Other
{ "HELP", SDLK_HELP }, { "HELP", SDL_SCANCODE_HELP },
{ "PRINT", SDLK_PRINT }, { "SYSREQ", SDL_SCANCODE_SYSREQ },
{ "SYSREQ", SDLK_SYSREQ }, { "MENU", SDL_SCANCODE_MENU },
{ "BREAK", SDLK_BREAK }, { "POWER", SDL_SCANCODE_POWER },
{ "MENU", SDLK_MENU }, { "UNDO", SDL_SCANCODE_UNDO }
{ "POWER", SDLK_POWER },
{ "EURO", SDLK_EURO },
{ "UNDO", SDLK_UNDO }
}; };
CSDLInputSystem::CSDLInputSystem() CSDLInputSystem::CSDLInputSystem()
: CInputSystem("SDL"), : CInputSystem("SDL"),
m_keyState(NULL), m_keyState(nullptr),
m_mouseX(0), m_mouseX(0),
m_mouseY(0), m_mouseY(0),
m_mouseZ(0), m_mouseZ(0),
@ -205,7 +189,7 @@ void CSDLInputSystem::OpenJoysticks()
for (int joyNum = 0; joyNum < numJoys; joyNum++) for (int joyNum = 0; joyNum < numJoys; joyNum++)
{ {
SDL_Joystick *joystick = SDL_JoystickOpen(joyNum); SDL_Joystick *joystick = SDL_JoystickOpen(joyNum);
if (joystick == NULL) if (joystick == nullptr)
{ {
ErrorLog("Unable to open joystick device %d with SDL - skipping joystick.\n", joyNum + 1); ErrorLog("Unable to open joystick device %d with SDL - skipping joystick.\n", joyNum + 1);
continue; continue;
@ -213,7 +197,7 @@ void CSDLInputSystem::OpenJoysticks()
// Gather joystick details (name, num POVs & buttons and which axes are available) // Gather joystick details (name, num POVs & buttons and which axes are available)
JoyDetails joyDetails; JoyDetails joyDetails;
const char *pName = SDL_JoystickName(joyNum); const char *pName = SDL_JoystickName(joystick);
strncpy(joyDetails.name, pName, MAX_NAME_LENGTH); strncpy(joyDetails.name, pName, MAX_NAME_LENGTH);
joyDetails.name[MAX_NAME_LENGTH] = '\0'; joyDetails.name[MAX_NAME_LENGTH] = '\0';
joyDetails.numAxes = SDL_JoystickNumAxes(joystick); joyDetails.numAxes = SDL_JoystickNumAxes(joystick);
@ -275,14 +259,14 @@ int CSDLInputSystem::GetKeyIndex(const char *keyName)
const char *CSDLInputSystem::GetKeyName(int keyIndex) const char *CSDLInputSystem::GetKeyName(int keyIndex)
{ {
if (keyIndex < 0 || keyIndex >= NUM_SDL_KEYS) if (keyIndex < 0 || keyIndex >= NUM_SDL_KEYS)
return NULL; return nullptr;
return s_keyMap[keyIndex].keyName; return s_keyMap[keyIndex].keyName;
} }
bool CSDLInputSystem::IsKeyPressed(int kbdNum, int keyIndex) bool CSDLInputSystem::IsKeyPressed(int kbdNum, int keyIndex)
{ {
// Get SDL key for given index and check if currently pressed // Get SDL key for given index and check if currently pressed
SDLKey sdlKey = s_keyMap[keyIndex].sdlKey; SDL_Keycode sdlKey = s_keyMap[keyIndex].sdlKey;
return !!m_keyState[sdlKey]; return !!m_keyState[sdlKey];
} }
@ -374,14 +358,14 @@ int CSDLInputSystem::GetNumJoysticks()
const KeyDetails *CSDLInputSystem::GetKeyDetails(int kbdNum) const KeyDetails *CSDLInputSystem::GetKeyDetails(int kbdNum)
{ {
// Return NULL as SDL 1.2 cannot handle multiple keyboards // Return nullptr as SDL 1.2 cannot handle multiple keyboards
return NULL; return nullptr;
} }
const MouseDetails *CSDLInputSystem::GetMouseDetails(int mseNum) const MouseDetails *CSDLInputSystem::GetMouseDetails(int mseNum)
{ {
// Return NULL as SDL 1.2 cannot handle multiple mice // Return nullptr as SDL 1.2 cannot handle multiple mice
return NULL; return nullptr;
} }
const JoyDetails *CSDLInputSystem::GetJoyDetails(int joyNum) const JoyDetails *CSDLInputSystem::GetJoyDetails(int joyNum)
@ -398,27 +382,29 @@ bool CSDLInputSystem::Poll()
SDL_Event e; SDL_Event e;
while (SDL_PollEvent(&e)) while (SDL_PollEvent(&e))
{ {
if (e.type == SDL_QUIT) switch (e.type)
return false;
else if (e.type == SDL_MOUSEBUTTONDOWN)
{ {
// Mouse wheel movements are not returned by SDL_GetMouseState below, so they are handled here instead default:
// The mouse absolute Z-axis value and mouse wheel direction value are updated appropriately break;
if (e.button.button == SDL_BUTTON_WHEELUP) case SDL_QUIT:
return false;
case SDL_MOUSEWHEEL:
if (e.button.y > 0)
{ {
m_mouseZ += 5; m_mouseZ += 5;
m_mouseWheelDir = 1; m_mouseWheelDir = 1;
} }
else if (e.button.button == SDL_BUTTON_WHEELDOWN) else if (e.button.y < 0)
{ {
m_mouseZ -= 5; m_mouseZ -= 5;
m_mouseWheelDir = -1; m_mouseWheelDir = -1;
} }
break;
} }
} }
// Get key state from SDL // Get key state from SDL
m_keyState = SDL_GetKeyState(NULL); m_keyState = SDL_GetKeyboardState(nullptr);
// Get mouse state from SDL (except mouse wheel which was handled earlier) // Get mouse state from SDL (except mouse wheel which was handled earlier)
m_mouseButtons = SDL_GetMouseState(&m_mouseX, &m_mouseY); m_mouseButtons = SDL_GetMouseState(&m_mouseX, &m_mouseY);

View file

@ -46,7 +46,7 @@ using namespace std;
struct SDLKeyMapStruct struct SDLKeyMapStruct
{ {
const char *keyName; const char *keyName;
SDLKey sdlKey; SDL_Scancode sdlKey;
}; };
/* /*
@ -65,7 +65,7 @@ private:
vector<JoyDetails> m_joyDetails; vector<JoyDetails> m_joyDetails;
// Current key state obtained from SDL // Current key state obtained from SDL
Uint8 *m_keyState; const Uint8 *m_keyState;
// Current mouse state obtained from SDL // Current mouse state obtained from SDL
int m_mouseX; int m_mouseX;

View file

@ -45,12 +45,12 @@ UINT32 CThread::GetTicks()
return SDL_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) if (impl == NULL)
return NULL; return NULL;
return new CThread(impl); return new CThread(name, impl);
} }
CSemaphore *CThread::CreateSemaphore(UINT32 initVal) CSemaphore *CThread::CreateSemaphore(UINT32 initVal)
@ -82,14 +82,26 @@ const char *CThread::GetLastError()
return SDL_GetError(); 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() 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() UINT32 CThread::GetId()
@ -97,13 +109,6 @@ UINT32 CThread::GetId()
return SDL_GetThreadID((SDL_Thread*)m_impl); 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 CThread::Wait()
{ {
int status; int status;

View file

@ -28,6 +28,8 @@
#ifndef INCLUDED_THREADS_H #ifndef INCLUDED_THREADS_H
#define INCLUDED_THREADS_H #define INCLUDED_THREADS_H
#include <string>
class CSemaphore; class CSemaphore;
class CMutex; class CMutex;
class CCondVar; class CCondVar;
@ -42,9 +44,10 @@ typedef int (*ThreadStart)(void *startParam);
class CThread class CThread
{ {
private: private:
const std::string m_name;
void *m_impl; void *m_impl;
CThread(void *impl); CThread(const std::string &name, void *impl);
public: public:
/* /*
@ -66,7 +69,7 @@ public:
* *
* Creates a new thread with the given ThreadStart callback and start parameter. The thread starts running immediately. * 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 * CreateSemaphore
@ -101,6 +104,13 @@ public:
*/ */
~CThread(); ~CThread();
/*
* GetName
*
* Returns the name of this thread.
*/
const std::string &GetName() const;
/* /*
* GetId * GetId
* *
@ -108,13 +118,6 @@ public:
*/ */
UINT32 GetId(); UINT32 GetId();
/*
* Kill
*
* Kills this thread.
*/
void Kill();
/* /*
* Wait * Wait
* *

View file

@ -428,11 +428,11 @@ const char *CDirectInputSystem::ConstructName(bool useRawInput, bool useXInput)
return (useXInput ? "Xinput" : "DirectInput"); 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)), CInputSystem(ConstructName(useRawInput, useXInput)),
m_config(config), m_config(config),
m_useRawInput(useRawInput), m_useXInput(useXInput), m_enableFFeedback(true), 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_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) m_xiGetCapabilitiesPtr(NULL), m_xiGetStatePtr(NULL), m_xiSetStatePtr(NULL), m_di8(NULL), m_di8Keyboard(NULL), m_di8Mouse(NULL)
{ {
@ -2051,8 +2051,10 @@ bool CDirectInputSystem::Poll()
// If not, then get Window handle of SDL window // If not, then get Window handle of SDL window
SDL_SysWMinfo info; SDL_SysWMinfo info;
SDL_VERSION(&info.version); SDL_VERSION(&info.version);
if (SDL_GetWMInfo(&info)) if (SDL_GetWindowWMInfo(m_window, &info))
m_hwnd = info.window; {
m_hwnd = info.info.win.window;
}
// Tell SDL to pass on all Windows events // Tell SDL to pass on all Windows events
// Removed - see below // 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 // Poll keyboards, mice and joysticks
PollKeyboardsAndMice(); PollKeyboardsAndMice();
PollJoysticks(); PollJoysticks();

View file

@ -33,10 +33,13 @@
#include "Inputs/InputSource.h" #include "Inputs/InputSource.h"
#include "Inputs/InputSystem.h" #include "Inputs/InputSystem.h"
#include <SDL.h>
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <dinput.h> #include <dinput.h>
#include <XInput.h> #include <XInput.h>
#include <functional>
#include <vector> #include <vector>
using namespace std; using namespace std;
@ -125,6 +128,7 @@ private:
bool m_initializedCOM; bool m_initializedCOM;
bool m_activated; bool m_activated;
SDL_Window *m_window = nullptr;
// Function pointers for RawInput API // Function pointers for RawInput API
GetRawInputDeviceListPtr m_getRIDevListPtr; GetRawInputDeviceListPtr m_getRIDevListPtr;
@ -234,7 +238,7 @@ public:
* to the same shared axis and so cannot be distinguished when pressed together. * 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). * 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(); ~CDirectInputSystem();