ladybird/Ports/ja2/patches/0001-Make-it-build-with-SDL-2-instead-of-1.2.patch

2479 lines
75 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: safarp <safar.pavel@gmail.com>
Date: Mon, 21 Mar 2022 21:51:29 +0100
Subject: [PATCH] Make it build with SDL 2 instead of 1.2
---
Build/Laptop/IMP_Begin_Screen.cc | 2 +-
Build/Laptop/IMP_HomePage.cc | 4 +-
Build/SaveLoadGame.cc | 10 +-
Build/Utils/Quantize.cc | 2 +-
Build/Utils/Text_Input.cc | 23 +-
Makefile | 15 +-
sgp/FileMan.cc | 211 +++++++-----
sgp/FileMan.h | 15 +-
sgp/Input.cc | 243 +++++++++-----
sgp/Input.h | 22 +-
sgp/PCX.cc | 2 +-
sgp/Platform.h | 8 +-
sgp/SGP.cc | 23 +-
sgp/STCI.cc | 2 +-
sgp/SoundMan.cc | 537 ++++++-------------------------
sgp/VSurface.cc | 13 +-
sgp/Video.cc | 282 ++++++----------
sgp/Video.h | 5 +-
18 files changed, 566 insertions(+), 853 deletions(-)
diff --git a/Build/Laptop/IMP_Begin_Screen.cc b/Build/Laptop/IMP_Begin_Screen.cc
index 81db086..63c6bab 100644
--- a/Build/Laptop/IMP_Begin_Screen.cc
+++ b/Build/Laptop/IMP_Begin_Screen.cc
@@ -398,7 +398,7 @@ static void GetPlayerKeyBoardInputForIMPBeginScreen(void)
// handle input events
while( DequeueEvent(&InputEvent) )
{
- if( !HandleTextInput( &InputEvent ) && (InputEvent.usEvent == KEY_DOWN || InputEvent.usEvent == KEY_REPEAT) )
+ if( !HandleTextInput( &InputEvent ) && (InputEvent.usEvent == TEXT_INPUT || InputEvent.usEvent == KEY_DOWN || InputEvent.usEvent == KEY_REPEAT) )
{
switch( InputEvent.usParam )
{
diff --git a/Build/Laptop/IMP_HomePage.cc b/Build/Laptop/IMP_HomePage.cc
index 1512a04..bc0157a 100644
--- a/Build/Laptop/IMP_HomePage.cc
+++ b/Build/Laptop/IMP_HomePage.cc
@@ -230,7 +230,7 @@ static void GetPlayerKeyBoardInputForIMPHomePage(void)
InputAtom InputEvent;
while (DequeueEvent(&InputEvent))
{
- if( !HandleTextInput( &InputEvent ) && (InputEvent.usEvent == KEY_DOWN || InputEvent.usEvent == KEY_REPEAT || InputEvent.usEvent == KEY_UP ) )
+ if( !HandleTextInput( &InputEvent ) && (InputEvent.usEvent == TEXT_INPUT || InputEvent.usEvent == KEY_DOWN || InputEvent.usEvent == KEY_REPEAT || InputEvent.usEvent == KEY_UP ) )
{
switch( InputEvent.usParam )
{
@@ -247,7 +247,7 @@ static void GetPlayerKeyBoardInputForIMPHomePage(void)
case SDLK_ESCAPE: HandleLapTopESCKey(); break;
default:
- if(InputEvent.usEvent == KEY_DOWN || InputEvent.usEvent == KEY_REPEAT )
+ if(InputEvent.usEvent == TEXT_INPUT)
{
HandleTextEvent(&InputEvent);
}
diff --git a/Build/SaveLoadGame.cc b/Build/SaveLoadGame.cc
index dbf14b8..9f48503 100644
--- a/Build/SaveLoadGame.cc
+++ b/Build/SaveLoadGame.cc
@@ -2545,8 +2545,8 @@ static void UpdateMercMercContractInfo(void)
INT8 GetNumberForAutoSave( BOOLEAN fLatestAutoSave )
{
BOOLEAN fFile1Exist, fFile2Exist;
- SGP_FILETIME CreationTime1, LastAccessedTime1, LastWriteTime1;
- SGP_FILETIME CreationTime2, LastAccessedTime2, LastWriteTime2;
+ time_t LastWriteTime1;
+ time_t LastWriteTime2;
fFile1Exist = FALSE;
fFile2Exist = FALSE;
@@ -2559,15 +2559,13 @@ INT8 GetNumberForAutoSave( BOOLEAN fLatestAutoSave )
if( GCM->doesGameResExists( zFileName1 ) )
{
- AutoSGPFile hFile(GCM->openUserPrivateFileForReading(std::string(zFileName1)));
- GetFileManFileTime( hFile, &CreationTime1, &LastAccessedTime1, &LastWriteTime1 );
+ GetFileManFileTime( zFileName1, &LastWriteTime1 );
fFile1Exist = TRUE;
}
if( GCM->doesGameResExists( zFileName2 ) )
{
- AutoSGPFile hFile(GCM->openUserPrivateFileForReading(std::string(zFileName2)));
- GetFileManFileTime( hFile, &CreationTime2, &LastAccessedTime2, &LastWriteTime2 );
+ GetFileManFileTime( zFileName2, &LastWriteTime2 );
fFile2Exist = TRUE;
}
diff --git a/Build/Utils/Quantize.cc b/Build/Utils/Quantize.cc
index 998179a..c036a78 100644
--- a/Build/Utils/Quantize.cc
+++ b/Build/Utils/Quantize.cc
@@ -127,7 +127,7 @@ static size_t GetPaletteColors(const NODE* const pTree, SGPPaletteEntry* const p
dst->r = pTree->nRedSum / pTree->nPixelCount;
dst->g = pTree->nGreenSum / pTree->nPixelCount;
dst->b = pTree->nBlueSum / pTree->nPixelCount;
- dst->unused = 0;
+ dst->a = 0;
}
else
{
diff --git a/Build/Utils/Text_Input.cc b/Build/Utils/Text_Input.cc
index fc64d58..4869ce2 100644
--- a/Build/Utils/Text_Input.cc
+++ b/Build/Utils/Text_Input.cc
@@ -562,10 +562,19 @@ BOOLEAN HandleTextInput(InputAtom const* const a)
// Not in text input mode
if (!gfTextInputMode) return FALSE;
// Unless we are psycho typers, we only want to process these key events.
- if (a->usEvent != KEY_DOWN && a->usEvent != KEY_REPEAT) return FALSE;
+ if (a->usEvent != TEXT_INPUT && a->usEvent != KEY_DOWN && a->usEvent != KEY_REPEAT) return FALSE;
// Currently in a user field, so return unless TAB is pressed.
if (!gfEditingText && a->usParam != SDLK_TAB) return FALSE;
+ if (a->usEvent == TEXT_INPUT) {
+ wchar_t const c = a->Char;
+ /* If the key has no character associated, bail out */
+ AssertMsg(c != L'\0', "TEXT_INPUT event sent null character");
+ DeleteHilitedText();
+ HandleRegularInput(c);
+ return TRUE;
+ }
+
switch (a->usKeyState)
{
case 0:
@@ -642,7 +651,8 @@ BOOLEAN HandleTextInput(InputAtom const* const a)
}
break;
- default: goto enter_character;
+ default:
+ return TRUE;
}
break;
@@ -670,14 +680,9 @@ BOOLEAN HandleTextInput(InputAtom const* const a)
gubCursorPos = 0;
return TRUE;
- default: // Check for typing keys
-enter_character:
- wchar_t const c = a->Char;
- /* If the key has no character associated, bail out */
- if (c == L'\0') return FALSE;
- DeleteHilitedText();
- HandleRegularInput(c);
+ default:
return TRUE;
+
}
case CTRL_DOWN:
diff --git a/Makefile b/Makefile
index 6db811f..53103d3 100644
--- a/Makefile
+++ b/Makefile
@@ -38,12 +38,18 @@ CFLAGS += -DGAME_VERSION=\"$(GAME_VERSION)\"
ifdef LOCAL_SDL_LIB
-CFLAGS_SDL= -I./$(LOCAL_SDL_LIB)/include/SDL -D_GNU_SOURCE=1 -Dmain=SDL_main
-LDFLAGS_SDL=-L./$(LOCAL_SDL_LIB)/lib -lmingw32 -lSDLmain -lSDL -mwindows
+CFLAGS_SDL= -I./$(LOCAL_SDL_LIB)/include/SDL2 -D_GNU_SOURCE=1 -Dmain=SDL_main
+LDFLAGS_SDL=-L./$(LOCAL_SDL_LIB)/lib -lmingw32 -lSDL2main -lSDL2 -mwindows
endif
ifndef LOCAL_SDL_LIB
+# using Serenity SDL2 library
+ifdef SERENITY
+CFLAGS_SDL= -I${SERENITY_BUILD_DIR}/Root/usr/local/include/SDL2 -D_REENTRANT
+LDFLAGS_SDL= -L${SERENITY_BUILD_DIR}/Root/usr/local/lib -lSDL2
+endif
+
# using system SDL library
SDL_CONFIG ?= sdl-config
@@ -156,6 +162,7 @@ CCFLAGS += -Wimplicit-int
CCFLAGS += -Wmissing-prototypes
CXXFLAGS += $(CFLAGS)
+CXXFLAGS += -std=c++11
LDFLAGS += -lm
@@ -723,10 +730,10 @@ build-on-mac:
make "CFLAGS_SDL=$(MACOS_STATIC_CFLAGS_SDL)" "LDFLAGS_SDL=$(MACOS_STATIC_LDFLAGS_SDL)"
build-on-win:
- PATH=/cygdrive/c/MinGW/bin:$$PATH make all USE_MINGW=1 MINGW_PREFIX=/cygdrive/c/MinGW/bin/mingw32 LOCAL_SDL_LIB=_build/lib-SDL-devel-1.2.15-mingw32
+ PATH=/cygdrive/c/MinGW/bin:$$PATH make all USE_MINGW=1 MINGW_PREFIX=/cygdrive/c/MinGW/bin/mingw32 LOCAL_SDL_LIB=_build/lib-SDL2-2.0.4-mingw/i686-w64-mingw32 WITH_LPTHREAD=0
cp /cygdrive/c/MinGW/bin/libstdc++-6.dll .
cp /cygdrive/c/MinGW/bin/libgcc_s_dw2-1.dll .
- cp _build/lib-SDL-devel-1.2.15-mingw32/bin/SDL.dll .
+ cp _build/lib-SDL2-2.0.4-mingw/i686-w64-mingw32/bin/SDL2.dll .
SOURCE_DIR_NAME := ja2-stracciatella_$(VERSION)
build-source-archive:
diff --git a/sgp/FileMan.cc b/sgp/FileMan.cc
index 0b607c2..cdfca08 100644
--- a/sgp/FileMan.cc
+++ b/sgp/FileMan.cc
@@ -9,12 +9,10 @@
#include "LibraryDataBase.h"
#include "MemMan.h"
#include "PODObj.h"
-#include "Logger.h"
#include "boost/filesystem.hpp"
#include "slog/slog.h"
-#define TAG "FileMan"
#if _WIN32
#include <shlobj.h>
@@ -23,6 +21,7 @@
#endif
#include "PlatformIO.h"
+#include "Debug.h"
#if MACOS_USE_RESOURCES_FROM_BUNDLE && defined __APPLE__ && defined __MACH__
#include <CoreFoundation/CFBundle.h>
@@ -30,11 +29,15 @@
#if CASE_SENSITIVE_FS
#include <dirent.h>
+#include <SDL_rwops.h>
#endif
// XXX: remove FileMan class and make it into a namespace
#define LOCAL_CURRENT_DIR "tmp"
+#define SDL_RWOPS_SGP 222
+
+#define DEBUG_TAG_FILEMAN "Fileman"
enum FileOpenFlags
{
@@ -117,18 +120,23 @@ std::string FileMan::findConfigFolderAndSwitchIntoIt()
if (mkdir(configFolderPath.c_str(), 0700) != 0 && errno != EEXIST)
{
- LOG_ERROR("Unable to create directory '%s'\n", configFolderPath.c_str());
+ SLOGE(DEBUG_TAG_FILEMAN, "Unable to create tmp directory '%s'", configFolderPath.c_str());
throw std::runtime_error("Unable to local directory");
}
+ return switchTmpFolder(configFolderPath);
+}
+/** Switch config folder. */
+std::string FileMan::switchTmpFolder(std::string home)
+{
// Create another directory and set is as the current directory for the process
// Temporary files will be created in this directory.
// ----------------------------------------------------------------------------
- std::string tmpPath = FileMan::joinPaths(configFolderPath, LOCAL_CURRENT_DIR);
+ std::string tmpPath = FileMan::joinPaths(home, LOCAL_CURRENT_DIR);
if (mkdir(tmpPath.c_str(), 0700) != 0 && errno != EEXIST)
{
- LOG_ERROR("Unable to create tmp directory '%s'\n", tmpPath.c_str());
+ SLOGE(DEBUG_TAG_FILEMAN, "Unable to create tmp directory '%s'", tmpPath.c_str());
throw std::runtime_error("Unable to create tmp directory");
}
else
@@ -136,7 +144,7 @@ std::string FileMan::findConfigFolderAndSwitchIntoIt()
SetFileManCurrentDirectory(tmpPath.c_str());
}
- return configFolderPath;
+ return home;
}
@@ -237,19 +245,8 @@ void FileClose(SGPFile* f)
MemFree(f);
}
-
-#ifdef JA2TESTVERSION
-# include "Timer_Control.h"
-extern UINT32 uiTotalFileReadTime;
-extern UINT32 uiTotalFileReadCalls;
-#endif
-
void FileRead(SGPFile* const f, void* const pDest, size_t const uiBytesToRead)
{
-#ifdef JA2TESTVERSION
- const UINT32 uiStartTime = GetJA2Clock();
-#endif
-
BOOLEAN ret;
if (f->flags & SGPFILE_REAL)
{
@@ -260,12 +257,6 @@ void FileRead(SGPFile* const f, void* const pDest, size_t const uiBytesToRead)
ret = LoadDataFromLibrary(&f->u.lib, pDest, (UINT32)uiBytesToRead);
}
-#ifdef JA2TESTVERSION
- //Add the time that we spent in this function to the total.
- uiTotalFileReadTime += GetJA2Clock() - uiStartTime;
- uiTotalFileReadCalls++;
-#endif
-
if (!ret) throw std::runtime_error("Reading from file failed");
}
@@ -276,6 +267,80 @@ void FileWrite(SGPFile* const f, void const* const pDest, size_t const uiBytesTo
if (fwrite(pDest, uiBytesToWrite, 1, f->u.file) != 1) throw std::runtime_error("Writing to file failed");
}
+static int64_t SGPSeekRW(SDL_RWops *context, int64_t offset, int whence)
+{
+ SGPFile* sgpFile = (SGPFile*)(context->hidden.unknown.data1);
+ FileSeekMode mode = FILE_SEEK_FROM_CURRENT;
+ switch (whence) {
+ case RW_SEEK_SET:
+ mode = FILE_SEEK_FROM_START;
+ break;
+ case RW_SEEK_END:
+ mode = FILE_SEEK_FROM_END;
+ break;
+ default:
+ break;
+ }
+
+ FileSeek(sgpFile, offset, mode);
+
+ return int64_t(FileGetPos(sgpFile));
+}
+
+static int64_t SGPSizeRW(SDL_RWops *context)
+{
+ SGPFile* sgpFile = (SGPFile*)(context->hidden.unknown.data1);
+
+ return FileGetSize(sgpFile);
+}
+
+static size_t SGPReadRW(SDL_RWops *context, void *ptr, size_t size, size_t maxnum)
+{
+ SGPFile* sgpFile = (SGPFile*)(context->hidden.unknown.data1);
+ UINT32 posBefore = UINT32(FileGetPos(sgpFile));
+
+ FileRead(sgpFile, ptr, size * maxnum);
+
+ UINT32 posAfter = UINT32(FileGetPos(sgpFile));
+
+ return (posAfter - posBefore) / size;
+}
+
+static size_t SGPWriteRW(SDL_RWops *context, const void *ptr, size_t size, size_t num)
+{
+ AssertMsg(false, "SGPWriteRW not supported");
+ return 0;
+}
+
+static int SGPCloseRW(SDL_RWops *context)
+{
+ if(context->type != SDL_RWOPS_SGP)
+ {
+ return SDL_SetError("Wrong kind of SDL_RWops for SGPCloseRW()");
+ }
+ SGPFile* sgpFile = (SGPFile*)(context->hidden.unknown.data1);
+
+ FileClose(sgpFile);
+ SDL_FreeRW(context);
+
+ return 0;
+}
+
+SDL_RWops* FileGetRWOps(SGPFile* const f) {
+ SDL_RWops* rwOps = SDL_AllocRW();
+ if(rwOps == NULL) {
+ return NULL;
+ }
+ rwOps->type = SDL_RWOPS_SGP;
+ rwOps->size = SGPSizeRW;
+ rwOps->seek = SGPSeekRW;
+ rwOps->read = SGPReadRW;
+ rwOps->write= SGPWriteRW;
+ rwOps->close= SGPCloseRW;
+ rwOps->hidden.unknown.data1 = f;
+
+ return rwOps;
+}
void FileSeek(SGPFile* const f, INT32 distance, FileSeekMode const how)
{
@@ -397,63 +462,36 @@ BOOLEAN FileClearAttributes(const std::string &filename)
BOOLEAN FileClearAttributes(const char* const filename)
{
-#if 1 // XXX TODO
- SLOGW(TAG, "ignoring %s(\"%s\")", __func__, filename);
- return FALSE;
- // UNIMPLEMENTED
-#else
- return SetFileAttributes(filename, FILE_ATTRIBUTE_NORMAL);
-#endif
+ using namespace boost::filesystem;
+
+ permissions(filename, ( add_perms | owner_read | owner_write | group_read | group_write ));
+ return true;
}
-BOOLEAN GetFileManFileTime(const SGPFile* f, SGP_FILETIME* const pCreationTime, SGP_FILETIME* const pLastAccessedTime, SGP_FILETIME* const pLastWriteTime)
+BOOLEAN GetFileManFileTime(const char* fileName, time_t* const pLastWriteTime)
{
-#if 1 // XXX TODO
- UNIMPLEMENTED;
- return FALSE;
-#else
- //Initialize the passed in variables
- memset(pCreationTime, 0, sizeof(*pCreationTime));
- memset(pLastAccessedTime, 0, sizeof(*pLastAccessedTime));
- memset(pLastWriteTime, 0, sizeof(*pLastWriteTime));
-
- if (f->flags & SGPFILE_REAL)
+ using namespace boost::filesystem;
+ *pLastWriteTime = last_write_time(fileName);
+ if(*pLastWriteTime == -1)
{
- const HANDLE hRealFile = f->u.file;
-
- //Gets the UTC file time for the 'real' file
- SGP_FILETIME sCreationUtcFileTime;
- SGP_FILETIME sLastAccessedUtcFileTime;
- SGP_FILETIME sLastWriteUtcFileTime;
- GetFileTime(hRealFile, &sCreationUtcFileTime, &sLastAccessedUtcFileTime, &sLastWriteUtcFileTime);
-
- //converts the creation UTC file time to the current time used for the file
- FileTimeToLocalFileTime(&sCreationUtcFileTime, pCreationTime);
-
- //converts the accessed UTC file time to the current time used for the file
- FileTimeToLocalFileTime(&sLastAccessedUtcFileTime, pLastAccessedTime);
-
- //converts the write UTC file time to the current time used for the file
- FileTimeToLocalFileTime(&sLastWriteUtcFileTime, pLastWriteTime);
- return TRUE;
+ return FALSE;
}
- else
- {
- return GetLibraryFileTime(&f->u.lib, pLastWriteTime);
- }
-#endif
+ return TRUE;
}
-INT32 CompareSGPFileTimes(const SGP_FILETIME* const pFirstFileTime, const SGP_FILETIME* const pSecondFileTime)
+INT32 CompareSGPFileTimes(const time_t* const pFirstFileTime, const time_t* const pSecondFileTime)
{
-#if 1 // XXX TODO
- UNIMPLEMENTED;
- return 0;
-#else
- return CompareFileTime(pFirstFileTime, pSecondFileTime);
-#endif
+ if ( *pFirstFileTime < *pSecondFileTime )
+ {
+ return -1;
+ }
+ if ( *pFirstFileTime > *pSecondFileTime )
+ {
+ return 1;
+ }
+ return 0;
}
@@ -462,19 +500,19 @@ FILE* GetRealFileHandleFromFileManFileHandle(const SGPFile* f)
return f->flags & SGPFILE_REAL ? f->u.file : f->u.lib.lib->hLibraryHandle;
}
-UINT32 GetFreeSpaceOnHardDriveWhereGameIsRunningFrom(void)
+uintmax_t GetFreeSpaceOnHardDriveWhereGameIsRunningFrom(void)
{
-#if 1 // XXX TODO
- FIXME
- return 1024 * 1024 * 1024; // XXX TODO return an arbitrary number for now
-#else
- //get the drive letter from the exec dir
- STRING512 zDrive;
- _splitpath(GetExecutableDirectory(), zDrive, NULL, NULL, NULL);
-
- sprintf(zDrive, "%s\\", zDrive);
- return GetFreeSpaceOnHardDrive(zDrive);
-#endif
+ using namespace boost::filesystem;
+ space_info si = space(current_path());
+ if (si.available == -1)
+ {
+ /* something is wrong, tell everyone no space available */
+ return 0;
+ }
+ else
+ {
+ return si.available;
+ }
}
/** Join two path components. */
@@ -562,7 +600,7 @@ bool FileMan::findObjectCaseInsensitive(const char *directory, const char *name,
}
}
- // LOG_INFO("XXXXX Looking for %s/[ %s ] : %s\n", directory, name, result ? "success" : "failure");
+ // SLOGI(DEBUG_TAG_FILEMAN,"Looking for %s/[ %s ] : %s", directory, name, result ? "success" : "failure");
return result;
}
#endif
@@ -820,3 +858,10 @@ bool FileMan::checkFileExistance(const char *folder, const char *fileName)
path /= fileName;
return boost::filesystem::exists(path);
}
+
+void FileMan::moveFile(const char *from, const char *to)
+{
+ boost::filesystem::path fromPath(from);
+ boost::filesystem::path toPath(to);
+ boost::filesystem::rename(fromPath, toPath);
+}
diff --git a/sgp/FileMan.h b/sgp/FileMan.h
index a7f96cb..d4fdf3c 100644
--- a/sgp/FileMan.h
+++ b/sgp/FileMan.h
@@ -10,8 +10,6 @@
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
-#else
-# include <glob.h>
#endif
/* Delete the file at path. Returns true iff deleting the file succeeded or
@@ -21,6 +19,7 @@ void FileDelete(const std::string &path);
void FileRead( SGPFile*, void* pDest, size_t uiBytesToRead);
void FileWrite(SGPFile*, void const* pDest, size_t uiBytesToWrite);
+SDL_RWops* FileGetRWOps(SGPFile* const f);
template<typename T, typename U> static inline void FileWriteArray(SGPFile* const f, T const& n, U const* const data)
{
@@ -51,13 +50,13 @@ BOOLEAN FileClearAttributes(const char* filename);
BOOLEAN FileClearAttributes(const std::string &filename);
-BOOLEAN GetFileManFileTime(const SGPFile* hFile, SGP_FILETIME* pCreationTime, SGP_FILETIME* pLastAccessedTime, SGP_FILETIME* pLastWriteTime);
+BOOLEAN GetFileManFileTime(const char* fileName, time_t* pLastWriteTime);
/* returns
* - -1 if the First file time is less than second file time. (first file is older)
* - 0 First file time is equal to second file time.
* - +1 First file time is greater than second file time (first file is newer). */
-INT32 CompareSGPFileTimes(const SGP_FILETIME* const pFirstFileTime, const SGP_FILETIME* const pSecondFileTime);
+INT32 CompareSGPFileTimes(const time_t* const pFirstFileTime, const time_t* const pSecondFileTime);
/* Pass in the Fileman file handle of an OPEN file and it will return..
* - if its a Real File, the return will be the handle of the REAL file
@@ -65,7 +64,7 @@ INT32 CompareSGPFileTimes(const SGP_FILETIME* const pFirstFileTime, const SGP_FI
FILE* GetRealFileHandleFromFileManFileHandle(const SGPFile* hFile);
//Gets the amount of free space on the hard drive that the main executeablt is runnning from
-UINT32 GetFreeSpaceOnHardDriveWhereGameIsRunningFrom(void);
+uintmax_t GetFreeSpaceOnHardDriveWhereGameIsRunningFrom(void);
/***
* New file manager.
@@ -78,6 +77,9 @@ public:
/** Find config folder and switch into it. */
static std::string findConfigFolderAndSwitchIntoIt();
+ /** Switch config folder into it. */
+ static std::string switchTmpFolder(std::string homeDir);
+
/** Open file for writing.
* If file is missing it will be created.
* If file exists, it's content will be removed. */
@@ -156,6 +158,9 @@ public:
/** Check file existance. */
static bool checkFileExistance(const char *folder, const char *fileName);
+ /** Move a file */
+ static void moveFile(const char *from, const char *to);
+
private:
/** Private constructor to avoid instantiation. */
FileMan() {};
diff --git a/sgp/Input.cc b/sgp/Input.cc
index 3b64602..6d82a14 100644
--- a/sgp/Input.cc
+++ b/sgp/Input.cc
@@ -1,3 +1,5 @@
+#include <bitset>
+#include "UTF8String.h"
#include "Types.h"
#include "Input.h"
#include "MemMan.h"
@@ -7,11 +9,12 @@
#include "Local.h"
#include "UILayout.h"
+#include "slog/slog.h"
-// The gfKeyState table is used to track which of the keys is up or down at any one time. This is used while polling
-// the interface.
-BOOLEAN gfKeyState[SDLK_LAST]; // TRUE = Pressed, FALSE = Not Pressed
+// The gfKeyState table is used to track which of the keys is up or down at any one time. This is used while polling
+// the interface. true = pressed, false = not pressed.
+static std::bitset<2 * SDL_NUM_SCANCODES> gfKeyState;
static BOOLEAN fCursorWasClipped = FALSE;
static SGPRect gCursorClipRect;
@@ -22,9 +25,11 @@ static UINT32 guiSingleClickTimer;
static UINT32 guiLeftButtonRepeatTimer;
static UINT32 guiRightButtonRepeatTimer;
+static UINT32 guiMiddleButtonRepeatTimer;
BOOLEAN gfLeftButtonState; // TRUE = Pressed, FALSE = Not Pressed
BOOLEAN gfRightButtonState; // TRUE = Pressed, FALSE = Not Pressed
+BOOLEAN gfMiddleButtonState;// TRUE = Pressed, FALSE = Not Pressed
UINT16 gusMouseXPos; // X position of the mouse on screen
UINT16 gusMouseYPos; // y position of the mouse on screen
@@ -49,7 +54,7 @@ static void QueueMouseEvent(UINT16 ubInputEvent)
}
-static void QueueKeyEvent(UINT16 ubInputEvent, SDLKey Key, SDLMod Mod, wchar_t Char)
+static void QueueKeyEvent(UINT16 ubInputEvent, SDL_Keycode Key, SDL_Keymod Mod, wchar_t Char)
{
// Can we queue up one more event, if not, the event is lost forever
if (gusQueueCount == lengthof(gEventQueue)) return;
@@ -68,6 +73,16 @@ static void QueueKeyEvent(UINT16 ubInputEvent, SDLKey Key, SDLMod Mod, wchar_t C
gusTailIndex = (gusTailIndex + 1) % lengthof(gEventQueue);
}
+void SetSafeMousePosition(int x, int y) {
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (x > SCREEN_WIDTH) x = SCREEN_WIDTH;
+ if (y > SCREEN_HEIGHT) y = SCREEN_HEIGHT;
+
+ gusMouseXPos = x;
+ gusMouseYPos = y;
+}
+
BOOLEAN DequeueSpecificEvent(InputAtom* Event, UINT32 uiMaskFlags)
{
@@ -103,12 +118,11 @@ BOOLEAN DequeueEvent(InputAtom* Event)
static void UpdateMousePos(const SDL_MouseButtonEvent* BtnEv)
{
- gusMouseXPos = BtnEv->x;
- gusMouseYPos = BtnEv->y;
+ SetSafeMousePosition(BtnEv->x, BtnEv->y);
}
-#if defined WITH_MAEMO
+#if defined(WITH_MAEMO) || defined __APPLE__
static BOOLEAN g_down_right;
#endif
@@ -123,8 +137,13 @@ void MouseButtonDown(const SDL_MouseButtonEvent* BtnEv)
#if defined WITH_MAEMO
/* If the menu button (mapped to F4) is pressed, then treat the event as
* right click */
- const Uint8* const key_state = SDL_GetKeyState(NULL);
- g_down_right = key_state[SDLK_F4];
+ const Uint8* const key_state = SDL_GetKeyboardState(NULL);
+ g_down_right = key_state[SDL_SCANCODE_F4];
+ if (g_down_right) goto right_button;
+#endif
+#if defined(__APPLE__)
+ const Uint8* const key_state = SDL_GetKeyboardState(NULL);
+ g_down_right = key_state[SDL_SCANCODE_LGUI] || key_state[SDL_SCANCODE_RGUI];
if (g_down_right) goto right_button;
#endif
guiLeftButtonRepeatTimer = GetClock() + BUTTON_REPEAT_TIMEOUT;
@@ -134,7 +153,7 @@ void MouseButtonDown(const SDL_MouseButtonEvent* BtnEv)
}
case SDL_BUTTON_RIGHT:
-#if defined WITH_MAEMO
+#if defined(WITH_MAEMO) || defined(__APPLE__)
right_button:
#endif
guiRightButtonRepeatTimer = GetClock() + BUTTON_REPEAT_TIMEOUT;
@@ -142,8 +161,11 @@ right_button:
QueueMouseEvent(RIGHT_BUTTON_DOWN);
break;
- case SDL_BUTTON_WHEELUP: QueueMouseEvent(MOUSE_WHEEL_UP); break;
- case SDL_BUTTON_WHEELDOWN: QueueMouseEvent(MOUSE_WHEEL_DOWN); break;
+ case SDL_BUTTON_MIDDLE:
+ guiMiddleButtonRepeatTimer = GetClock() + BUTTON_REPEAT_TIMEOUT;
+ gfMiddleButtonState = TRUE;
+ QueueMouseEvent(MIDDLE_BUTTON_DOWN);
+ break;
}
}
@@ -155,7 +177,7 @@ void MouseButtonUp(const SDL_MouseButtonEvent* BtnEv)
{
case SDL_BUTTON_LEFT:
{
-#if defined WITH_MAEMO
+#if defined(WITH_MAEMO) || defined(__APPLE__)
if (g_down_right) goto right_button;
#endif
guiLeftButtonRepeatTimer = 0;
@@ -174,21 +196,55 @@ void MouseButtonUp(const SDL_MouseButtonEvent* BtnEv)
}
case SDL_BUTTON_RIGHT:
-#if defined WITH_MAEMO
+#if defined WITH_MAEMO || defined(__APPLE__)
right_button:
#endif
guiRightButtonRepeatTimer = 0;
gfRightButtonState = FALSE;
QueueMouseEvent(RIGHT_BUTTON_UP);
break;
+
+ case SDL_BUTTON_MIDDLE:
+ guiMiddleButtonRepeatTimer = 0;
+ gfMiddleButtonState = FALSE;
+ QueueMouseEvent(MIDDLE_BUTTON_UP);
+ break;
+ }
+}
+
+void MouseWheelScroll(const SDL_MouseWheelEvent* WheelEv)
+{
+ if (WheelEv->y > 0)
+ {
+ QueueMouseEvent(MOUSE_WHEEL_UP);
+ }
+ else
+ {
+ QueueMouseEvent(MOUSE_WHEEL_DOWN);
}
}
-static void KeyChange(SDL_keysym const* const key_sym, bool const pressed)
+// Remap SDL keycodes with bit 30 set to the range 512..1023
+// Necessary to be able to use the keycode as an index for the gfKeyState bitset.
+static SDL_Keycode RemapKeycode(SDL_Keycode const key)
+{
+ return (key & SDLK_SCANCODE_MASK)
+ ? (key & ~SDLK_SCANCODE_MASK) + SDL_NUM_SCANCODES
+ : key;
+}
+
+
+bool _KeyDown(SDL_Keycode const keycode)
+{
+ return gfKeyState[RemapKeycode(keycode)];
+}
+
+
+static void KeyChange(SDL_Keysym const* const key_sym, bool const pressed)
{
- SDLKey key = key_sym->sym;
- SDLMod const mod = key_sym->mod;
+ SDL_Keycode key = key_sym->sym;
+ SDL_Keymod const mod = (SDL_Keymod) key_sym->mod;
bool const num = mod & KMOD_NUM;
switch (key)
{
@@ -197,19 +253,19 @@ static void KeyChange(SDL_keysym const* const key_sym, bool const pressed)
case SDLK_F4: return;
#endif
- case SDLK_KP0: key = num ? SDLK_0 : SDLK_INSERT; break;
- case SDLK_KP1: key = num ? SDLK_1 : SDLK_END; break;
- case SDLK_KP2: key = num ? SDLK_2 : SDLK_DOWN; break;
- case SDLK_KP3: key = num ? SDLK_3 : SDLK_PAGEDOWN; break;
- case SDLK_KP4: key = num ? SDLK_4 : SDLK_LEFT; break;
- case SDLK_KP5:
+ case SDLK_KP_0: key = num ? SDLK_0 : SDLK_INSERT; break;
+ case SDLK_KP_1: key = num ? SDLK_1 : SDLK_END; break;
+ case SDLK_KP_2: key = num ? SDLK_2 : SDLK_DOWN; break;
+ case SDLK_KP_3: key = num ? SDLK_3 : SDLK_PAGEDOWN; break;
+ case SDLK_KP_4: key = num ? SDLK_4 : SDLK_LEFT; break;
+ case SDLK_KP_5:
if (!num) return;
key = SDLK_5;
break;
- case SDLK_KP6: key = num ? SDLK_6 : SDLK_RIGHT; break;
- case SDLK_KP7: key = num ? SDLK_7 : SDLK_HOME; break;
- case SDLK_KP8: key = num ? SDLK_8 : SDLK_UP; break;
- case SDLK_KP9: key = num ? SDLK_9 : SDLK_PAGEUP; break;
+ case SDLK_KP_6: key = num ? SDLK_6 : SDLK_RIGHT; break;
+ case SDLK_KP_7: key = num ? SDLK_7 : SDLK_HOME; break;
+ case SDLK_KP_8: key = num ? SDLK_8 : SDLK_UP; break;
+ case SDLK_KP_9: key = num ? SDLK_9 : SDLK_PAGEUP; break;
case SDLK_KP_PERIOD: key = num ? SDLK_PERIOD : SDLK_DELETE; break;
case SDLK_KP_DIVIDE: key = SDLK_SLASH; break;
case SDLK_KP_MULTIPLY: key = SDLK_ASTERISK; break;
@@ -218,12 +274,12 @@ static void KeyChange(SDL_keysym const* const key_sym, bool const pressed)
case SDLK_KP_ENTER: key = SDLK_RETURN; break;
default:
- if (key >= lengthof(gfKeyState)) return;
+ if ((key & ~SDLK_SCANCODE_MASK) >= SDL_NUM_SCANCODES) return;
break;
}
UINT event_type;
- BOOLEAN& key_state = gfKeyState[key];
+ bool key_state = _KeyDown(key);
if (pressed)
{
event_type = key_state ? KEY_REPEAT : KEY_DOWN;
@@ -233,32 +289,33 @@ static void KeyChange(SDL_keysym const* const key_sym, bool const pressed)
if (!key_state) return;
event_type = KEY_UP;
}
- key_state = pressed;
- QueueKeyEvent(event_type, key, mod, key_sym->unicode);
+ gfKeyState[RemapKeycode(key)] = pressed;
+
+ QueueKeyEvent(event_type, key, mod, '\0');
}
-void KeyDown(const SDL_keysym* KeySym)
+void KeyDown(const SDL_Keysym* KeySym)
{
switch (KeySym->sym)
{
case SDLK_LSHIFT:
case SDLK_RSHIFT:
- _KeyDown(SHIFT) = TRUE;
+ gfKeyState.set(SHIFT);
break;
case SDLK_LCTRL:
case SDLK_RCTRL:
- _KeyDown(CTRL) = TRUE;
+ gfKeyState.set(CTRL);
break;
case SDLK_LALT:
case SDLK_RALT:
- _KeyDown(ALT) = TRUE;
+ gfKeyState.set(ALT);
break;
- case SDLK_PRINT:
- case SDLK_SCROLLOCK:
+ case SDLK_PRINTSCREEN:
+ case SDLK_SCROLLLOCK:
break;
default:
@@ -268,34 +325,35 @@ void KeyDown(const SDL_keysym* KeySym)
}
-void KeyUp(const SDL_keysym* KeySym)
+void KeyUp(const SDL_Keysym* KeySym)
{
switch (KeySym->sym)
{
case SDLK_LSHIFT:
case SDLK_RSHIFT:
- _KeyDown(SHIFT) = FALSE;
+ gfKeyState.reset(SHIFT);
break;
case SDLK_LCTRL:
case SDLK_RCTRL:
- _KeyDown(CTRL) = FALSE;
+ gfKeyState.reset(CTRL);
break;
case SDLK_LALT:
case SDLK_RALT:
- _KeyDown(ALT) = FALSE;
+ gfKeyState.reset(ALT);
break;
- case SDLK_PRINT:
- if (KeySym->mod & KMOD_CTRL) VideoCaptureToggle(); else PrintScreen();
+ case SDLK_PRINTSCREEN:
+ PrintScreen();
break;
- case SDLK_SCROLLOCK:
- SDL_WM_GrabInput
+ case SDLK_SCROLLLOCK:
+ SDL_SetWindowGrab
(
- SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF ?
- SDL_GRAB_ON : SDL_GRAB_OFF
+ GAME_WINDOW,
+ SDL_GetWindowGrab(GAME_WINDOW) == SDL_FALSE ?
+ SDL_TRUE : SDL_FALSE
);
break;
@@ -313,14 +371,28 @@ void KeyUp(const SDL_keysym* KeySym)
}
}
+void TextInput(const SDL_TextInputEvent* TextEv) {
+ try {
+ UTF8String utf8String = UTF8String(TextEv->text);
+ QueueKeyEvent(TEXT_INPUT, SDLK_UNKNOWN, KMOD_NONE, utf8String.getUTF16()[0]);
+ }
+ catch (const InvalidEncodingException&)
+ {
+ // ignore invalid inputs
+ static bool warn = true;
+ if (warn)
+ {
+ SLOGW("SGP", "Received invalid utf-8 character.");
+ warn = false;
+ }
+ }
+}
+
void GetMousePos(SGPPoint* Point)
{
- int x;
- int y;
- SDL_GetMouseState(&x, &y);
- Point->iX = x;
- Point->iY = y;
+ Point->iX = gusMouseXPos;
+ Point->iY = gusMouseYPos;
}
@@ -356,20 +428,6 @@ void FreeMouseCursor(void)
fCursorWasClipped = FALSE;
}
-
-void RestoreCursorClipRect(void)
-{
-#if 1 // XXX TODO0000
- UNIMPLEMENTED
-#else
- if (fCursorWasClipped)
- {
- ClipCursor(&gCursorClipRect);
- }
-#endif
-}
-
-
void GetRestrictedClipCursor(SGPRect* pRectangle)
{
#if 1 // XXX TODO0000
@@ -391,26 +449,27 @@ BOOLEAN IsCursorRestricted(void)
void SimulateMouseMovement( UINT32 uiNewXPos, UINT32 uiNewYPos )
{
- // Wizardry NOTE: This function currently doesn't quite work right for in any Windows resolution other than 640x480.
- // mouse_event() uses your current Windows resolution to calculate the resulting x,y coordinates. So in order to get
- // the right coordinates, you'd have to find out the current Windows resolution through a system call, and then do:
- // uiNewXPos = uiNewXPos * SCREEN_WIDTH / WinScreenResX;
- // uiNewYPos = uiNewYPos * SCREEN_HEIGHT / WinScreenResY;
- //
- // JA2 doesn't have this problem, 'cause they use DirectDraw calls that change the Windows resolution properly.
- //
- // Alex Meduna, Dec. 3, 1997
-
-#if 1
- FIXME
- SDL_WarpMouse(uiNewXPos, uiNewYPos);
-#else
- // Adjust coords based on our resolution
- FLOAT flNewXPos = (FLOAT)uiNewXPos / SCREEN_WIDTH * 65536;
- FLOAT flNewYPos = (FLOAT)uiNewYPos / SCREEN_HEIGHT * 65536;
+ int windowWidth, windowHeight;
+ SDL_GetWindowSize(GAME_WINDOW, &windowWidth, &windowHeight);
- mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, (UINT32)flNewXPos, (UINT32)flNewYPos, 0, 0);
-#endif
+ double windowWidthD = windowWidth;
+ double windowHeightD = windowHeight;
+ double screenWidthD = SCREEN_WIDTH;
+ double screenHeightD = SCREEN_HEIGHT;
+
+ double scaleFactorX = windowWidthD / screenWidthD;
+ double scaleFactorY = windowHeightD / screenHeightD;
+ double scaleFactor = windowWidth > windowHeight ? scaleFactorY : scaleFactorX;
+
+ double scaledWindowWidth = scaleFactor * screenWidthD;
+ double scaledWindowHeight = scaleFactor * screenHeightD;
+
+ double paddingX = (windowWidthD - scaledWindowWidth) / 2.0;
+ double paddingY = (windowHeight - scaledWindowHeight) / 2.0;
+ int windowPositionX = paddingX + (double)uiNewXPos * scaledWindowWidth / screenWidthD;
+ int windowPositionY = paddingY + (double)uiNewYPos * scaledWindowHeight / screenHeightD;
+
+ SDL_WarpMouseInWindow(GAME_WINDOW, windowPositionX, windowPositionY);
}
@@ -465,4 +524,18 @@ static void HandleSingleClicksAndButtonRepeats(void)
{
guiRightButtonRepeatTimer = 0;
}
+
+ // Is there a MIDDLE mouse button repeat
+ if (gfMiddleButtonState)
+ {
+ if ((guiMiddleButtonRepeatTimer > 0)&&(guiMiddleButtonRepeatTimer <= uiTimer))
+ {
+ QueueMouseEvent(MIDDLE_BUTTON_REPEAT);
+ guiMiddleButtonRepeatTimer = uiTimer + BUTTON_REPEAT_TIME;
+ }
+ }
+ else
+ {
+ guiMiddleButtonRepeatTimer = 0;
+ }
}
diff --git a/sgp/Input.h b/sgp/Input.h
index 84d7cd1..0da0517 100644
--- a/sgp/Input.h
+++ b/sgp/Input.h
@@ -8,6 +8,7 @@
#define KEY_DOWN 0x0001
#define KEY_UP 0x0002
#define KEY_REPEAT 0x0004
+#define TEXT_INPUT 0x0006
#define LEFT_BUTTON_DOWN 0x0008
#define LEFT_BUTTON_UP 0x0010
#define LEFT_BUTTON_DBL_CLK 0x0020
@@ -18,7 +19,11 @@
#define MOUSE_POS 0x0400
#define MOUSE_WHEEL_UP 0x0800
#define MOUSE_WHEEL_DOWN 0x1000
-#define MOUSE_EVENTS 0x1FF8
+#define MOUSE_EVENTS 0xFFF8
+
+#define MIDDLE_BUTTON_DOWN 0x2000
+#define MIDDLE_BUTTON_UP 0x4000
+#define MIDDLE_BUTTON_REPEAT 0x8000
#define SHIFT_DOWN 0x01
#define CTRL_DOWN 0x02
@@ -41,9 +46,11 @@ extern BOOLEAN DequeueEvent(InputAtom *Event);
void MouseButtonDown(const SDL_MouseButtonEvent*);
void MouseButtonUp(const SDL_MouseButtonEvent*);
+void MouseWheelScroll(const SDL_MouseWheelEvent*);
-void KeyDown(const SDL_keysym*);
-void KeyUp( const SDL_keysym*);
+void KeyDown(const SDL_Keysym*);
+void KeyUp( const SDL_Keysym*);
+void TextInput( const SDL_TextInputEvent*);
extern void GetMousePos(SGPPoint *Point);
@@ -51,10 +58,10 @@ extern BOOLEAN DequeueSpecificEvent(InputAtom *Event, UINT32 uiMaskFlags );
extern void RestrictMouseToXYXY(UINT16 usX1, UINT16 usY1, UINT16 usX2, UINT16 usY2);
void RestrictMouseCursor(const SGPRect* pRectangle);
+extern void SetSafeMousePosition(int x, int y);
extern void FreeMouseCursor(void);
extern BOOLEAN IsCursorRestricted( void );
extern void GetRestrictedClipCursor( SGPRect *pRectangle );
-extern void RestoreCursorClipRect( void );
void SimulateMouseMovement( UINT32 uiNewXPos, UINT32 uiNewYPos );
@@ -62,16 +69,15 @@ void SimulateMouseMovement( UINT32 uiNewXPos, UINT32 uiNewYPos );
void DequeueAllKeyBoardEvents(void);
-extern BOOLEAN gfKeyState[SDLK_LAST]; // TRUE = Pressed, FALSE = Not Pressed
-
extern UINT16 gusMouseXPos; // X position of the mouse on screen
extern UINT16 gusMouseYPos; // y position of the mouse on screen
extern BOOLEAN gfLeftButtonState; // TRUE = Pressed, FALSE = Not Pressed
extern BOOLEAN gfRightButtonState; // TRUE = Pressed, FALSE = Not Pressed
+extern BOOLEAN gfMiddleButtonState;
-
-#define _KeyDown(a) gfKeyState[(a)]
+bool _KeyDown(SDL_Keycode);
#define _LeftButtonDown gfLeftButtonState
#define _RightButtonDown gfRightButtonState
+#define _MiddleButtonDown gfMiddleButtonState
#endif
diff --git a/sgp/PCX.cc b/sgp/PCX.cc
index cf1719b..bfea6df 100644
--- a/sgp/PCX.cc
+++ b/sgp/PCX.cc
@@ -75,7 +75,7 @@ SGPImage* LoadPCXFileToImage(char const* const filename, UINT16 const contents)
dst[i].r = palette[i * 3 + 0];
dst[i].g = palette[i * 3 + 1];
dst[i].b = palette[i * 3 + 2];
- dst[i].unused = 0;
+ dst[i].a = 0;
}
img->pui16BPPPalette = Create16BPPPalette(dst);
}
diff --git a/sgp/Platform.h b/sgp/Platform.h
index 263f9b1..c232813 100644
--- a/sgp/Platform.h
+++ b/sgp/Platform.h
@@ -43,11 +43,9 @@
#define __func__ __FUNCTION__
#endif
-#if !defined(_WIN32)
- /* Not Visual Studio, not MINGW */
- #define __max(a, b) ((a) > (b) ? (a) : (b))
- #define __min(a, b) ((a) < (b) ? (a) : (b))
-#endif
+/* Not Visual Studio, not MINGW */
+#define __max(a, b) ((a) > (b) ? (a) : (b))
+#define __min(a, b) ((a) < (b) ? (a) : (b))
/**************************************************************
*
diff --git a/sgp/SGP.cc b/sgp/SGP.cc
index 7b9b710..1c43c4c 100644
--- a/sgp/SGP.cc
+++ b/sgp/SGP.cc
@@ -212,28 +212,28 @@ static void MainLoop(int msPerGameCycle)
{
switch (event.type)
{
- case SDL_ACTIVEEVENT:
- if (event.active.state & SDL_APPACTIVE)
- {
- s_doGameCycles = (event.active.gain != 0);
- break;
- }
+ case SDL_APP_WILLENTERBACKGROUND:
+ s_doGameCycles = false;
+ break;
+
+ case SDL_APP_WILLENTERFOREGROUND:
+ s_doGameCycles = true;
break;
case SDL_KEYDOWN: KeyDown(&event.key.keysym); break;
case SDL_KEYUP: KeyUp( &event.key.keysym); break;
+ case SDL_TEXTINPUT: TextInput(&event.text); break;
case SDL_MOUSEBUTTONDOWN: MouseButtonDown(&event.button); break;
case SDL_MOUSEBUTTONUP: MouseButtonUp(&event.button); break;
case SDL_MOUSEMOTION:
- gusMouseXPos = event.motion.x;
- gusMouseYPos = event.motion.y;
+ SetSafeMousePosition(event.motion.x, event.motion.y);
break;
- case SDL_QUIT:
- deinitGameAndExit();
- break;
+ case SDL_MOUSEWHEEL: MouseWheelScroll(&event.wheel); break;
+
+ case SDL_QUIT: deinitGameAndExit(); break;
}
}
else
@@ -358,7 +358,6 @@ try
////////////////////////////////////////////////////////////
SDL_Init(SDL_INIT_VIDEO);
- SDL_EnableUNICODE(SDL_ENABLE);
#ifdef __APPLE__
// Enable 3-button mouse support if the user haven't instructed
diff --git a/sgp/STCI.cc b/sgp/STCI.cc
index c5d958e..bc200f7 100644
--- a/sgp/STCI.cc
+++ b/sgp/STCI.cc
@@ -113,7 +113,7 @@ static SGPImage* STCILoadIndexed(UINT16 const contents, HWFILE const f, STCIHead
palette[i].r = pSTCIPalette[i].ubRed;
palette[i].g = pSTCIPalette[i].ubGreen;
palette[i].b = pSTCIPalette[i].ubBlue;
- palette[i].unused = 0;
+ palette[i].a = 0;
}
img->fFlags |= IMAGE_PALETTE;
diff --git a/sgp/SoundMan.cc b/sgp/SoundMan.cc
index e37d632..aff2980 100644
--- a/sgp/SoundMan.cc
+++ b/sgp/SoundMan.cc
@@ -14,22 +14,18 @@
#include "Timer.h"
#include <SDL.h>
#include <assert.h>
+#include <stdexcept>
#include "ContentManager.h"
#include "GameInstance.h"
+#include "slog/slog.h"
+#define DEBUG_TAG_SOUND "Sound"
+#define DEBUG_TAG_ASSERTS "Asserts"
// Uncomment this to disable the startup of sound hardware
//#define SOUND_DISABLE
-
-#ifdef WITH_SOUND_DEBUG
-# define SNDDBG(fmt, ...) (void)fprintf(stderr, ">>>> SND: " fmt, __VA_ARGS__)
-#else
-# define SNDDBG(fmt, ...) (void)0
-#endif
-
-
/*
* from\to FREE PLAY STOP DEAD
* FREE M
@@ -59,25 +55,17 @@ enum
SAMPLE_ALLOCATED = 1U << 0,
SAMPLE_LOCKED = 1U << 1,
SAMPLE_RANDOM = 1U << 2,
- SAMPLE_STEREO = 1U << 3,
- SAMPLE_16BIT = 1U << 4
+ SAMPLE_STEREO = 1U << 3
};
#define SOUND_MAX_CACHED 128 // number of cache slots
+#define SOUND_MAX_CHANNELS 16 // number of mixer channels
-#ifdef JA2
-# define SOUND_MAX_CHANNELS 16 // number of mixer channels
-#else
-# define SOUND_MAX_CHANNELS 32 // number of mixer channels
-#endif
-
-
-#define SOUND_DEFAULT_MEMORY (16 * 1024 * 1024) // default memory limit
+#define SOUND_DEFAULT_MEMORY (32 * 1024 * 1024) // default memory limit
#define SOUND_DEFAULT_THRESH ( 2 * 1024 * 1024) // size for sample to be double-buffered
#define SOUND_DEFAULT_STREAM (64 * 1024) // double-buffered buffer size
-
// Struct definition for sample slots in the cache
// Holds the regular sample data, as well as the data for the random samples
struct SAMPLETAG
@@ -85,7 +73,6 @@ struct SAMPLETAG
CHAR8 pName[128]; // Path to sample data
UINT32 n_samples;
UINT32 uiFlags; // Status flags
- UINT32 uiSpeed; // Playback frequency
PTR pData; // pointer to sample data memory
UINT32 uiCacheHits;
@@ -121,15 +108,19 @@ struct SOUNDTAG
UINT32 Pan;
};
-
+static size_t GetSampleSize(const SAMPLETAG* const s);
static const UINT32 guiSoundDefaultVolume = MAXVOLUME;
static const UINT32 guiSoundMemoryLimit = SOUND_DEFAULT_MEMORY; // Maximum memory used for sounds
static UINT32 guiSoundMemoryUsed = 0; // Memory currently in use
static const UINT32 guiSoundCacheThreshold = SOUND_DEFAULT_THRESH; // Double-buffered threshold
+static void IncreaseSoundMemoryUsedBySample(SAMPLETAG *sample) { guiSoundMemoryUsed += sample->n_samples * GetSampleSize(sample); }
+static void DecreaseSoundMemoryUsedBySample(SAMPLETAG *sample) { guiSoundMemoryUsed -= sample->n_samples * GetSampleSize(sample); }
static BOOLEAN fSoundSystemInit = FALSE; // Startup called
static BOOLEAN gfEnableStartup = TRUE; // Allow hardware to start up
+SDL_AudioSpec gTargetAudioSpec;
+
// Sample cache list for files loaded
static SAMPLETAG pSampleList[SOUND_MAX_CACHED];
// Sound channel list for output channels
@@ -188,13 +179,7 @@ UINT32 SoundPlay(const char* pFilename, UINT32 volume, UINT32 pan, UINT32 loop,
if (SoundPlayStreamed(pFilename))
{
//Trying to play a sound which is bigger then the 'guiSoundCacheThreshold'
-
- // This line was causing a page fault in the Wiz 8 project, so
- // I changed it to the second line, which works OK. -- DB
-
- //DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("\n*******\nSoundPlay(): ERROR: trying to play %s which is bigger then the 'guiSoundCacheThreshold', use SoundPlayStreamedFile() instead\n", pFilename));
-
- FastDebugMsg(String("SoundPlay: ERROR: Trying to play %s sound is too lardge to load into cache, use SoundPlayStreamedFile() instead\n", pFilename));
+ SLOGE(DEBUG_TAG_SOUND, "Trying to play %s sound is too large to load into cache, use SoundPlayStreamedFile() instead", pFilename));
return SOUND_ERROR;
}
#endif
@@ -211,7 +196,6 @@ UINT32 SoundPlay(const char* pFilename, UINT32 volume, UINT32 pan, UINT32 loop,
static SAMPLETAG* SoundGetEmptySample(void);
static BOOLEAN SoundCleanCache(void);
static SAMPLETAG* SoundGetEmptySample(void);
-static size_t GetSampleSize(const SAMPLETAG* const s);
UINT32 SoundPlayFromBuffer(INT16* pbuffer, UINT32 size, UINT32 volume, UINT32 pan, UINT32 loop, void (*end_callback)(void*), void* data)
{
@@ -223,14 +207,13 @@ UINT32 SoundPlayFromBuffer(INT16* pbuffer, UINT32 size, UINT32 volume, UINT32 pa
SoundCleanCache();
buffertag = SoundGetEmptySample();
}
- sprintf(buffertag->pName, "SmackBuff %p - SampleSize %u", pbuffer, size);
- buffertag->uiSpeed=22050;
+ sprintf(buffertag->pName, "SmackBuff %p - SampleSize %u", pbuffer, size);
buffertag->n_samples = size;
buffertag->pData = pbuffer;
- buffertag->uiFlags = SAMPLE_16BIT | SAMPLE_STEREO | SAMPLE_ALLOCATED;
+ buffertag->uiFlags = SAMPLE_STEREO | SAMPLE_ALLOCATED;
buffertag->uiPanMax = 64;
buffertag->uiMaxInstances = 1;
- guiSoundMemoryUsed += size * GetSampleSize(buffertag);
+ IncreaseSoundMemoryUsedBySample(buffertag);
SOUNDTAG* const channel = SoundGetFreeChannel();
if (channel == NULL) return SOUND_ERROR;
@@ -263,7 +246,7 @@ try
FILE* hRealFileHandle = GetRealFileHandleFromFileManFileHandle(hFile);
if (hRealFileHandle == NULL)
{
- FastDebugMsg(String("\n*******\nSoundPlayStreamedFile(): ERROR: Couldnt get a real file handle for '%s' in SoundPlayStreamedFile()\n", pFilename ) );
+ SLOGE(DEBUG_TAG_SOUND, "SoundPlayStreamedFile(): Couldnt get a real file handle for '%s' in SoundPlayStreamedFile()", pFilename );
return SOUND_ERROR;
}
@@ -285,14 +268,14 @@ try
}
catch (...)
{
- FastDebugMsg(String("\n*******\nSoundPlayStreamedFile(): ERROR: Failed to play '%s'\n", pFilename));
+ SLOGE(DEBUG_TAG_SOUND, "SoundPlayStreamedFile(): Failed to play '%s'", pFilename);
return SOUND_ERROR;
}
UINT32 SoundPlayRandom(const char* pFilename, UINT32 time_min, UINT32 time_max, UINT32 vol_min, UINT32 vol_max, UINT32 pan_min, UINT32 pan_max, UINT32 max_instances)
{
- SNDDBG("RAND \"%s\"\n", pFilename);
+ SLOGD(DEBUG_TAG_SOUND, "playing random Sound: \"%s\"", pFilename);
if (!fSoundSystemInit) return SOUND_ERROR;
@@ -479,7 +462,7 @@ void SoundServiceStreams(void)
SOUNDTAG* Sound = &pSoundList[i];
if (Sound->State == CHANNEL_DEAD)
{
- SNDDBG("DEAD channel %u file \"%s\" (refcount %u)\n", i, Sound->pSample->pName, Sound->pSample->uiInstances);
+ SLOGD(DEBUG_TAG_SOUND, "DEAD channel %u file \"%s\" (refcount %u)", i, Sound->pSample->pName, Sound->pSample->uiInstances);
if (Sound->EOSCallback != NULL) Sound->EOSCallback(Sound->pCallbackData);
assert(Sound->pSample->uiInstances != 0);
Sound->pSample->uiInstances--;
@@ -556,274 +539,37 @@ static SAMPLETAG* SoundGetCached(const char* pFilename)
static size_t GetSampleSize(const SAMPLETAG* const s)
{
- return
- (s->uiFlags & SAMPLE_16BIT ? 2 : 1) *
- (s->uiFlags & SAMPLE_STEREO ? 2 : 1);
-}
-
-
-static BOOLEAN HalfSampleRate(SAMPLETAG* const s)
-{
- SNDDBG("SMPL \"%s\" from %uHz to %uHz\n", s->pName, s->uiSpeed, s->uiSpeed / 2);
-
- UINT32 const n_samples = s->n_samples / 2;
- void* const ndata = malloc(n_samples * GetSampleSize(s));
- if (ndata == NULL) return FALSE;
- void* const odata = s->pData;
- if (s->uiFlags & SAMPLE_16BIT)
- {
- INT16* const dst = (INT16*)ndata;
- const INT16* const src = (const INT16*)odata;
- if (s->uiFlags & SAMPLE_STEREO)
- {
- for (size_t i = 0; i < n_samples; ++i)
- {
- dst[2 * i + 0] = (src[4 * i + 0] + src[4 * i + 2]) / 2;
- dst[2 * i + 1] = (src[4 * i + 1] + src[4 * i + 3]) / 2;
- }
- }
- else
- {
- for (size_t i = 0; i < n_samples; ++i)
- {
- dst[i] = (src[2 * i] + src[2 * i + 1]) / 2;
- }
- }
- }
- else
- {
- UINT8* const dst = (UINT8*)ndata;
- const UINT8* const src = (const UINT8*)odata;
- if (s->uiFlags & SAMPLE_STEREO)
- {
- for (size_t i = 0; i < n_samples; ++i)
- {
- dst[2 * i + 0] = (src[4 * i + 0] + src[4 * i + 2]) / 2;
- dst[2 * i + 1] = (src[4 * i + 1] + src[4 * i + 3]) / 2;
- }
- }
- else
- {
- for (size_t i = 0; i < n_samples; ++i)
- {
- dst[i] = (src[2 * i] + src[2 * i + 1]) / 2;
- }
- }
- }
- s->pData = ndata;
- free(odata);
-
- s->n_samples = n_samples;
- s->uiSpeed /= 2;
- return TRUE;
-}
-
-static BOOLEAN DoubleSampleRate(SAMPLETAG* const s)
-{
- UINT8 bitcount = s->uiFlags & SAMPLE_16BIT ? 16 : 8;
-
- SNDDBG("SMPL \"%s\" %dbit from %uHz to %uHz\n", s->pName, bitcount, s->uiSpeed, s->uiSpeed * 2);
-
- UINT32 const n_samples = s->n_samples * 2;
- void* const ndata = malloc(n_samples * GetSampleSize(s));
- if (ndata == NULL) return FALSE;
- void* const odata = s->pData;
- if (bitcount == 16)
- {
- INT16* const dst = (INT16*)ndata;
- const INT16* const src = (const INT16*)odata;
- if (s->uiFlags & SAMPLE_STEREO)
- {
- for (size_t i = 0; i < s->n_samples; ++i)
- {
- INT16 i1c1 = src[2 * i + 0];
- INT16 i1c2 = src[2 * i + 1];
- INT16 i2c1 = i != s->n_samples-1 ? src[2 * i + 2] : i1c1;
- INT16 i2c2 = i != s->n_samples-1 ? src[2 * i + 3] : i1c2;
-
- dst[4 * i + 0] = i1c1;
- dst[4 * i + 1] = i1c2;
- dst[4 * i + 2] = (i1c1 + i2c1) / 2;
- dst[4 * i + 3] = (i1c2 + i2c2) / 2;
- }
- }
- else
- {
- for (size_t i = 0; i < s->n_samples; ++i)
- {
- INT16 i1 = src[i];
- INT16 i2 = i != s->n_samples-1 ? src[i+1] : i1;
- dst[i*2] = i1;
- dst[i*2+1] = (i1 + i2) / 2;
- }
- }
- }
- else
- {
- UINT8* const dst = (UINT8*)ndata;
- const UINT8* const src = (const UINT8*)odata;
- if (s->uiFlags & SAMPLE_STEREO)
- {
- for (size_t i = 0; i < s->n_samples; ++i)
- {
- UINT8 i1c1 = src[2 * i + 0];
- UINT8 i1c2 = src[2 * i + 1];
- UINT8 i2c1 = i != s->n_samples-1 ? src[2 * i + 2] : i1c1;
- UINT8 i2c2 = i != s->n_samples-1 ? src[2 * i + 3] : i1c2;
-
- dst[4 * i + 0] = i1c1;
- dst[4 * i + 1] = i1c2;
- dst[4 * i + 2] = (i1c1 + i2c1) / 2;
- dst[4 * i + 3] = (i1c2 + i2c2) / 2;
- }
- }
- else
- {
- for (size_t i = 0; i < s->n_samples; ++i)
- {
- UINT8 i1 = src[i];
- UINT8 i2 = i != s->n_samples-1 ? src[i+1] : i1;
- dst[i*2] = i1;
- dst[i*2+1] = (i1 + i2) / 2;
- }
- }
- }
- s->pData = ndata;
- free(odata);
-
- s->n_samples = n_samples;
- s->uiSpeed *= 2;
- return TRUE;
-}
-
-
-#define FOURCC(a, b, c, d) ((UINT8)(d) << 24 | (UINT8)(c) << 16 | (UINT8)(b) << 8 | (UINT8)(a))
-
-
-enum WaveFormatTag
-{
- WAVE_FORMAT_UNKNOWN = 0x0000,
- WAVE_FORMAT_PCM = 0x0001,
- WAVE_FORMAT_DVI_ADPCM = 0x0011
-};
-
-
-static void LoadPCM(SAMPLETAG* const s, HWFILE const file, UINT32 const size)
-{
- SGP::Buffer<UINT8> data(size);
- FileRead(file, data, size);
-
- s->n_samples = size / GetSampleSize(s);
- s->pData = data.Release();
-}
-
-
-static inline int Clamp(int min, int x, int max)
-{
- if (x < min) return min;
- if (x > max) return max;
- return x;
+ return 2u * (s->uiFlags & SAMPLE_STEREO ? 2 : 1);
}
-
-static void LoadDVIADPCM(SAMPLETAG* const s, HWFILE const file, UINT16 const block_align)
-{
- s->uiFlags |= SAMPLE_16BIT;
-
- size_t CountSamples = s->n_samples;
- INT16* const Data = (INT16*)malloc(CountSamples * GetSampleSize(s));
- INT16* D = Data;
-
- for (;;)
- {
- INT16 CurSample_;
- FileRead(file, &CurSample_, sizeof(CurSample_));
-
- UINT8 StepIndex_;
- FileRead(file, &StepIndex_, sizeof(StepIndex_));
-
- FileSeek(file, 1 , FILE_SEEK_FROM_CURRENT); // reserved byte
-
- INT32 CurSample = CurSample_;
- INT32 StepIndex = StepIndex_;
-
- *D++ = CurSample;
- if (--CountSamples == 0)
- {
- s->pData = Data;
- return;
- }
-
- UINT DataCount = block_align / 4;
- while (--DataCount != 0)
- {
- UINT32 DataWord;
- FileRead(file, &DataWord, sizeof(DataWord));
- for (UINT i = 0; i < 8; i++)
- {
- static const INT16 StepTable[] =
- {
- 7, 8, 9, 10, 11, 12, 13, 14,
- 16, 17, 19, 21, 23, 25, 28, 31,
- 34, 37, 41, 45, 50, 55, 60, 66,
- 73, 80, 88, 97, 107, 118, 130, 143,
- 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658,
- 724, 796, 876, 963, 1060, 1166, 1282, 1411,
- 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
- 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
- 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
- 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
- 32767
- };
-
- static const INT8 IndexTable[] =
- {
- -1, -1, -1, -1, 2, 4, 6, 8
- };
-
-#if 1
- INT32 Diff = ((DataWord & 7) * 2 + 1) * StepTable[StepIndex] >> 3;
-#else
- INT32 Diff = 0;
- if (DataWord & 4) Diff += StepTable[StepIndex];
- if (DataWord & 2) Diff += StepTable[StepIndex] >> 1;
- if (DataWord & 1) Diff += StepTable[StepIndex] >> 2;
- Diff += StepTable[StepIndex] >> 3;
-#endif
- if (DataWord & 8) Diff = -Diff;
- CurSample = Clamp(-32768, CurSample + Diff, 32767);
- StepIndex = Clamp(0, StepIndex + IndexTable[DataWord & 7], 88);
- DataWord >>= 4;
-
- *D++ = CurSample;
- if (--CountSamples == 0)
- {
- s->pData = Data;
- return;
- }
- }
- }
- }
-}
-
-
-
-
-
/* Loads a sound file from disk into the cache, allocating memory and a slot
* for storage.
*
* Returns: The sample index if successful, NO_SAMPLE if the file wasn't found
* in the cache. */
static SAMPLETAG* SoundLoadDisk(const char* pFilename)
-try
{
Assert(pFilename != NULL);
- AutoSGPFile hFile(GCM->openGameResForReading(pFilename));
+ if(pFilename[0] == '\0') {
+ SLOGE(DEBUG_TAG_ASSERTS, "SoundLoadDisk Error: pFilename is an empty string.");
+ return NULL;
+ }
- UINT32 uiSize = FileGetSize(hFile);
+ AutoSGPFile hFile;
+
+ try
+ {
+ hFile = GCM->openGameResForReading(pFilename);
+ }
+ catch (const std::runtime_error& err)
+ {
+ SLOGE(DEBUG_TAG_ASSERTS, "SoundLoadDisk Error: %s", err.what());
+ return NULL;
+ }
+
+ // A pessimistic approach as we dont know the decoded size yet
+ UINT32 uiSize = FileGetSize(hFile) * 2;
// if insufficient memory, start unloading old samples until either
// there's nothing left to unload, or we fit
@@ -831,8 +577,8 @@ try
{
if (!SoundCleanCache())
{
- SNDDBG("Not enough memory. Size: %u, Used: %u, Max: %u\n", uiSize, guiSoundMemoryUsed, guiSoundMemoryLimit);
- FastDebugMsg(String("SoundLoadDisk: ERROR: trying to play %s, not enough memory\n", pFilename));
+ SLOGE(DEBUG_TAG_SOUND, "SoundLoadDisk: trying to play %s, not enough memory\nSize: %u, Used: %u, Max: %u",
+ pFilename, uiSize, guiSoundMemoryUsed, guiSoundMemoryLimit);
return NULL;
}
}
@@ -848,107 +594,63 @@ try
// if we still don't have a sample slot
if (s == NULL)
{
- FastDebugMsg(String("SoundLoadDisk: ERROR: Trying to play %s, sound channels are full\n", pFilename));
+ SLOGE(DEBUG_TAG_SOUND, "SoundLoadDisk: Trying to play %s, sound channels are full", pFilename);
return NULL;
}
memset(s, 0, sizeof(*s));
- FileSeek(hFile, 12, FILE_SEEK_FROM_CURRENT);
-
- UINT16 FormatTag = WAVE_FORMAT_UNKNOWN;
- UINT16 BlockAlign = 0;
- for (;;)
- {
- UINT32 Tag;
- UINT32 Size;
-
- FileRead(hFile, &Tag, sizeof(Tag));
- FileRead(hFile, &Size, sizeof(Size));
+ SDL_RWops* rwOps = FileGetRWOps(hFile);
+ SDL_AudioSpec wavSpec;
+ Uint32 wavLength;
+ Uint8 *wavBuffer;
+ SDL_AudioCVT cvt;
- switch (Tag)
- {
- case FOURCC('f', 'm', 't', ' '):
- {
- UINT16 Channels;
- UINT32 Rate;
- UINT16 BitsPerSample;
-
- FileRead(hFile, &FormatTag, sizeof(FormatTag));
- FileRead(hFile, &Channels, sizeof(Channels));
- FileRead(hFile, &Rate, sizeof(Rate));
- FileSeek(hFile, 4 , FILE_SEEK_FROM_CURRENT);
- FileRead(hFile, &BlockAlign, sizeof(BlockAlign));
- FileRead(hFile, &BitsPerSample, sizeof(BitsPerSample));
- SNDDBG("LOAD file \"%s\" format %u channels %u rate %u bits %u to slot %u\n", pFilename, FormatTag, Channels, Rate, BitsPerSample, s - pSampleList);
- switch (FormatTag)
- {
- case WAVE_FORMAT_PCM: break;
+ if (SDL_LoadWAV_RW(rwOps, 0, &wavSpec, &wavBuffer, &wavLength) == NULL) {
+ SLOGE(DEBUG_TAG_SOUND, "Error loading sound file: %s", SDL_GetError());
+ return NULL;
+ }
- case WAVE_FORMAT_DVI_ADPCM:
- FileSeek(hFile, 4 , FILE_SEEK_FROM_CURRENT);
- break;
+ SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, gTargetAudioSpec.format, wavSpec.channels, gTargetAudioSpec.freq);
+ cvt.len = wavLength;
+ cvt.buf = MALLOCN(UINT8, cvt.len * cvt.len_mult);
+ memcpy(cvt.buf, wavBuffer, wavLength);
+ SDL_FreeWAV(wavBuffer);
+ SDL_FreeRW(rwOps);
- default: return NULL;
- }
+ if (cvt.needed) {
+ if (SDL_ConvertAudio(&cvt) != 0) {
+ SLOGE(DEBUG_TAG_SOUND, "Error converting sound file: %s", SDL_GetError());
+ return NULL;
+ };
+ }
- s->uiSpeed = Rate;
- if (Channels != 1) s->uiFlags |= SAMPLE_STEREO;
- if (BitsPerSample == 16) s->uiFlags |= SAMPLE_16BIT;
- break;
- }
+ UINT32 convertedSize = cvt.len * cvt.len_ratio;
- case FOURCC('f', 'a', 'c', 't'):
- {
- UINT32 Samples;
- FileRead(hFile, &Samples, sizeof(Samples));
- s->n_samples = Samples;
- break;
- }
+ strcpy(s->pName, pFilename);
+ s->n_samples = UINT32(convertedSize / (wavSpec.channels * 2));
+ s->uiFlags |= SAMPLE_ALLOCATED;
+ if (wavSpec.channels != 1) {
+ s->uiFlags |= SAMPLE_STEREO;
+ }
- case FOURCC('d', 'a', 't', 'a'):
- {
- switch (FormatTag)
- {
- case WAVE_FORMAT_PCM:
- LoadPCM(s, hFile, Size);
- goto sound_loaded;
+ s->uiInstances = 0;
+ s->pData = MALLOCN(UINT8, convertedSize);
+ memcpy(s->pData, cvt.buf, convertedSize);
- case WAVE_FORMAT_DVI_ADPCM:
- LoadDVIADPCM(s, hFile, BlockAlign);
- goto sound_loaded;
+ free(cvt.buf);
- default: return NULL;
- }
- }
-
- default:
- FileSeek(hFile, Size, FILE_SEEK_FROM_CURRENT);
- break;
- }
- }
+ IncreaseSoundMemoryUsedBySample(s);
-sound_loaded:
- strcpy(s->pName, pFilename);
- if (s->uiSpeed == 44100 && !HalfSampleRate(s))
- {
- free(s->pData);
- return NULL;
- }
- if (s->uiSpeed == 11025 && !DoubleSampleRate(s))
- {
- free(s->pData);
- return NULL;
- }
- guiSoundMemoryUsed += s->n_samples * GetSampleSize(s);
- s->uiFlags |= SAMPLE_ALLOCATED;
- s->uiInstances = 0;
return s;
}
-catch (...) { return 0; }
-static BOOLEAN SoundSampleIsPlaying(const SAMPLETAG* s);
+// Returns TRUE/FALSE that a sample is currently in use for playing a sound.
+static BOOLEAN SoundSampleIsPlaying(const SAMPLETAG* s)
+{
+ return s->uiInstances > 0;
+}
/* Removes the least-used sound from the cache to make room.
@@ -970,7 +672,7 @@ static BOOLEAN SoundCleanCache(void)
if (candidate != NULL)
{
- SNDDBG("FREE sample %u \"%s\" with %u hits\n", candidate - pSampleList, candidate->pName, candidate->uiCacheHits);
+ SLOGD(DEBUG_TAG_SOUND, "freeing sample %u \"%s\" with %u hits", candidate - pSampleList, candidate->pName, candidate->uiCacheHits);
SoundFreeSample(candidate);
return TRUE;
}
@@ -979,13 +681,6 @@ static BOOLEAN SoundCleanCache(void)
}
-// Returns TRUE/FALSE that a sample is currently in use for playing a sound.
-static BOOLEAN SoundSampleIsPlaying(const SAMPLETAG* s)
-{
- return s->uiInstances > 0;
-}
-
-
/* Returns an available sample.
*
* Returns: A free sample or NULL if none are left. */
@@ -1007,8 +702,8 @@ static void SoundFreeSample(SAMPLETAG* s)
assert(s->uiInstances == 0);
- guiSoundMemoryUsed -= s->n_samples * GetSampleSize(s);
- free(s->pData);
+ DecreaseSoundMemoryUsedBySample(s);
+ MemFree(s->pData);
memset(s, 0, sizeof(*s));
}
@@ -1030,6 +725,8 @@ static SOUNDTAG* SoundGetChannelByID(UINT32 uiSoundID)
static void SoundCallback(void* userdata, Uint8* stream, int len)
{
+ SDL_memset(stream, 0, len);
+
UINT16* Stream = (UINT16*)stream;
// XXX TODO proper mixing, mainly clipping
@@ -1058,48 +755,23 @@ static void SoundCallback(void* userdata, Uint8* stream, int len)
mixing:
amount = MIN(samples, s->n_samples - Sound->pos);
- if (s->uiFlags & SAMPLE_16BIT)
+ if (s->uiFlags & SAMPLE_STEREO)
{
- if (s->uiFlags & SAMPLE_STEREO)
+ const INT16* const src = (const INT16*)s->pData + Sound->pos * 2;
+ for (UINT32 i = 0; i < amount; ++i)
{
- const INT16* const src = (const INT16*)s->pData + Sound->pos * 2;
- for (UINT32 i = 0; i < amount; ++i)
- {
- Stream[2 * i + 0] += src[2 * i + 0] * vol_l >> 7;
- Stream[2 * i + 1] += src[2 * i + 1] * vol_r >> 7;
- }
- }
- else
- {
- const INT16* const src = (const INT16*)s->pData + Sound->pos;
- for (UINT32 i = 0; i < amount; i++)
- {
- const INT data = src[i];
- Stream[2 * i + 0] += data * vol_l >> 7;
- Stream[2 * i + 1] += data * vol_r >> 7;
- }
+ Stream[2 * i + 0] += src[2 * i + 0] * vol_l >> 7;
+ Stream[2 * i + 1] += src[2 * i + 1] * vol_r >> 7;
}
}
else
{
- if (s->uiFlags & SAMPLE_STEREO)
- {
- const UINT8* const src = (const UINT8*)s->pData + Sound->pos * 2;
- for (UINT32 i = 0; i < amount; ++i)
- {
- Stream[2 * i + 0] += (src[2 * i + 0] - 128) * vol_l << 1;
- Stream[2 * i + 1] += (src[2 * i + 1] - 128) * vol_r << 1;
- }
- }
- else
+ const INT16* const src = (const INT16*)s->pData + Sound->pos;
+ for (UINT32 i = 0; i < amount; i++)
{
- const UINT8* const src = (const UINT8*)s->pData + Sound->pos;
- for (UINT32 i = 0; i < amount; ++i)
- {
- const INT data = (src[i] - 128) << 1;
- Stream[2 * i + 0] += data * vol_l;
- Stream[2 * i + 1] += data * vol_r;
- }
+ const INT data = src[i];
+ Stream[2 * i + 0] += data * vol_l >> 7;
+ Stream[2 * i + 1] += data * vol_r >> 7;
}
}
@@ -1128,15 +800,14 @@ static BOOLEAN SoundInitHardware(void)
{
SDL_InitSubSystem(SDL_INIT_AUDIO);
- SDL_AudioSpec spec;
- spec.freq = 22050;
- spec.format = AUDIO_S16SYS;
- spec.channels = 2;
- spec.samples = 1024;
- spec.callback = SoundCallback;
- spec.userdata = NULL;
+ gTargetAudioSpec.freq = 44100;
+ gTargetAudioSpec.format = AUDIO_S16SYS;
+ gTargetAudioSpec.channels = 2;
+ gTargetAudioSpec.samples = 1024;
+ gTargetAudioSpec.callback = SoundCallback;
+ gTargetAudioSpec.userdata = NULL;
- if (SDL_OpenAudio(&spec, NULL) != 0) return FALSE;
+ if (SDL_OpenAudio(&gTargetAudioSpec, NULL) != 0) return FALSE;
memset(pSoundList, 0, sizeof(pSoundList));
SDL_PauseAudio(0);
@@ -1174,7 +845,7 @@ static UINT32 SoundGetUniqueID(void);
* Returns: Unique sound ID if successful, SOUND_ERROR if not. */
static UINT32 SoundStartSample(SAMPLETAG* sample, SOUNDTAG* channel, UINT32 volume, UINT32 pan, UINT32 loop, void (*end_callback)(void*), void* data)
{
- SNDDBG("PLAY channel %u sample %u file \"%s\"\n", channel - pSoundList, sample - pSampleList, sample->pName);
+ SLOGD(DEBUG_TAG_SOUND, "playing channel %u sample %u file \"%s\"", channel - pSoundList, sample - pSampleList, sample->pName);
if (!fSoundSystemInit) return SOUND_ERROR;
@@ -1220,7 +891,7 @@ static BOOLEAN SoundStopChannel(SOUNDTAG* channel)
if (channel->pSample == NULL) return FALSE;
- SNDDBG("STOP channel %u\n", channel - pSoundList);
+ SLOGD(DEBUG_TAG_SOUND, "stopping channel channel %u", channel - pSoundList);
channel->State = CHANNEL_STOP;
return TRUE;
}
diff --git a/sgp/VSurface.cc b/sgp/VSurface.cc
index 9147259..4c68143 100644
--- a/sgp/VSurface.cc
+++ b/sgp/VSurface.cc
@@ -28,13 +28,13 @@ SGPVSurface::SGPVSurface(UINT16 const w, UINT16 const h, UINT8 const bpp) :
switch (bpp)
{
case 8:
- s = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp, 0, 0, 0, 0);
+ s = SDL_CreateRGBSurface(0, w, h, bpp, 0, 0, 0, 0);
break;
case 16:
{
- SDL_PixelFormat const* f = SDL_GetVideoSurface()->format;
- s = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp, f->Rmask, f->Gmask, f->Bmask, 0);
+ SDL_PixelFormat const* f = SDL_AllocFormat(SDL_PIXELFORMAT_RGB565);
+ s = SDL_CreateRGBSurface(0, w, h, bpp, f->Rmask, f->Gmask, f->Bmask, f->Amask);
break;
}
@@ -112,7 +112,7 @@ void SGPVSurface::SetTransparency(const COLORVAL colour)
default: abort(); // HACK000E
}
- SDL_SetColorKey(surface_, SDL_SRCCOLORKEY, colour_key);
+ SDL_SetColorKey(surface_, SDL_TRUE, colour_key);
}
@@ -370,9 +370,10 @@ void BltStretchVideoSurface(SGPVSurface* const dst, SGPVSurface const* const src
UINT const dx = src_rect->w;
UINT const dy = src_rect->h;
UINT py = 0;
- if (ssurface->flags & SDL_SRCCOLORKEY)
+ if (ssurface->flags & SDL_TRUE)
{
- const UINT16 key = ssurface->format->colorkey;
+// const UINT16 key = ssurface->format->colorkey;
+ const UINT16 key = 0;
for (UINT iy = 0; iy < height; ++iy)
{
const UINT16* s = os;
diff --git a/sgp/Video.cc b/sgp/Video.cc
index 1c6c217..57fab03 100644
--- a/sgp/Video.cc
+++ b/sgp/Video.cc
@@ -22,13 +22,13 @@
#include <stdarg.h>
#include "UILayout.h"
#include "PlatformIO.h"
-#include "PlatformSDL.h"
#include "Font.h"
#include "Icon.h"
#include "ContentManager.h"
#include "GameInstance.h"
+#include "slog/slog.h"
#define BUFFER_READY 0x00
#define BUFFER_DIRTY 0x02
@@ -44,6 +44,12 @@
#define MAX_NUM_FRAMES 25
+#define RED_MASK 0xF800
+#define GREEN_MASK 0x07E0
+#define BLUE_MASK 0x001F
+#define ALPHA_MASK 0
+
+#define DEBUG_TAG_VIDEO "Video"
static BOOLEAN gfVideoCapture = FALSE;
static UINT32 guiFramePeriod = 1000 / 15;
@@ -80,9 +86,12 @@ static UINT32 guiPrintFrameBufferIndex;
static SDL_Surface* MouseCursor;
static SDL_Surface* FrameBuffer;
-static SDL_Surface* ScreenBuffer;
-static Uint32 g_video_flags = SDL_SWSURFACE | SDL_HWPALETTE;
+static SDL_Renderer* GameRenderer;
+SDL_Window* g_game_window;
+static SDL_Surface* ScreenBuffer;
+static SDL_Texture* ScreenTexture;
+static Uint32 g_window_flags = 0;
static void RecreateBackBuffer();
static void DeletePrimaryVideoSurfaces(void);
@@ -91,48 +100,25 @@ void VideoSetFullScreen(const BOOLEAN enable)
{
if (enable)
{
- g_video_flags |= SDL_FULLSCREEN;
+ g_window_flags |= SDL_WINDOW_FULLSCREEN;
}
else
{
- g_video_flags &= ~SDL_FULLSCREEN;
+ g_window_flags &= ~SDL_WINDOW_FULLSCREEN;
}
}
void VideoToggleFullScreen(void)
{
- SDL_Surface* const scr = ScreenBuffer;
-
- // First try using SDL magic to toggle fullscreen
- if (SDL_WM_ToggleFullScreen(scr))
+ if (SDL_GetWindowFlags(g_game_window) & SDL_WINDOW_FULLSCREEN)
{
- g_video_flags ^= SDL_FULLSCREEN;
- return;
+ SDL_SetWindowFullscreen(g_game_window, 0);
+ }
+ else
+ {
+ SDL_SetWindowFullscreen(g_game_window, SDL_WINDOW_FULLSCREEN);
}
-
- // Fallback to manual toggling
- SDL_PixelFormat const& fmt = *scr->format;
- int const w = scr->w;
- int const h = scr->h;
- Uint8 const bpp = fmt.BitsPerPixel;
-
- SGP::AutoObj<SDL_Surface, SDL_FreeSurface> tmp(SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp, fmt.Rmask, fmt.Gmask, fmt.Bmask, fmt.Amask));
- if (!tmp) return;
-
- SDL_BlitSurface(scr, 0, tmp, 0);
-
- Uint32 const new_vflags = g_video_flags ^ SDL_FULLSCREEN;
- SDL_Surface* const new_scr = SDL_SetVideoMode(w, h, bpp, new_vflags);
- if (!new_scr) return;
-
- g_video_flags = new_vflags;
-
- ScreenBuffer = new_scr;
- RecreateBackBuffer();
-
- SDL_BlitSurface(tmp, 0, new_scr, 0);
- SDL_UpdateRect(new_scr, 0, 0, 0, 0);
}
@@ -141,9 +127,21 @@ static void GetRGBDistribution();
void InitializeVideoManager(void)
{
- DebugMsg(TOPIC_VIDEO, DBG_LEVEL_0, "Initializing the video manager");
+ SLOGD(DEBUG_TAG_VIDEO, "Initializing the video manager");
+ SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
+ SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
+
+ g_window_flags |= SDL_WINDOW_RESIZABLE;
+
+ g_game_window = SDL_CreateWindow(APPLICATION_NAME,
+ SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ SCREEN_WIDTH, SCREEN_HEIGHT,
+ g_window_flags);
+
+ GameRenderer = SDL_CreateRenderer(g_game_window, -1, 0);
+ SDL_RenderSetLogicalSize(GameRenderer, SCREEN_WIDTH, SCREEN_HEIGHT);
- SDL_WM_SetCaption(APPLICATION_NAME, NULL);
SDL_Surface* windowIcon = SDL_CreateRGBSurfaceFrom(
(void*)gWindowIconData.pixel_data,
gWindowIconData.width,
@@ -151,29 +149,56 @@ void InitializeVideoManager(void)
gWindowIconData.bytes_per_pixel*8,
gWindowIconData.bytes_per_pixel*gWindowIconData.width,
0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
- SDL_WM_SetIcon(windowIcon, NULL);
+ SDL_SetWindowIcon(g_game_window, windowIcon);
SDL_FreeSurface(windowIcon);
+
ClippingRect.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
- ScreenBuffer = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, PIXEL_DEPTH, g_video_flags);
- if (!ScreenBuffer) throw std::runtime_error("Failed to set up video mode");
+ ScreenBuffer = SDL_CreateRGBSurface(
+ 0,
+ SCREEN_WIDTH,
+ SCREEN_HEIGHT,
+ PIXEL_DEPTH,
+ RED_MASK,
+ GREEN_MASK,
+ BLUE_MASK,
+ ALPHA_MASK
+ );
+
+ if (ScreenBuffer == NULL) {
+ SLOGE(DEBUG_TAG_VIDEO, "SDL_CreateRGBSurface for ScreenBuffer failed: %s\n", SDL_GetError());
+ }
- Uint32 Rmask = ScreenBuffer->format->Rmask;
- Uint32 Gmask = ScreenBuffer->format->Gmask;
- Uint32 Bmask = ScreenBuffer->format->Bmask;
- Uint32 Amask = ScreenBuffer->format->Amask;
+ ScreenTexture = SDL_CreateTexture(GameRenderer,
+ SDL_PIXELFORMAT_RGB565,
+ SDL_TEXTUREACCESS_STREAMING,
+ SCREEN_WIDTH, SCREEN_HEIGHT);
+
+ if (ScreenTexture == NULL) {
+ SLOGE(DEBUG_TAG_VIDEO, "SDL_CreateTexture for ScreenTexture failed: %s\n", SDL_GetError());
+ }
FrameBuffer = SDL_CreateRGBSurface(
SDL_SWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, PIXEL_DEPTH,
- Rmask, Gmask, Bmask, Amask
+ RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK
);
+ if (FrameBuffer == NULL)
+ {
+ SLOGE(DEBUG_TAG_VIDEO, "SDL_CreateRGBSurface for FrameBuffer failed: %s\n", SDL_GetError());
+ }
+
MouseCursor = SDL_CreateRGBSurface(
- SDL_SWSURFACE, MAX_CURSOR_WIDTH, MAX_CURSOR_HEIGHT, PIXEL_DEPTH,
- Rmask, Gmask, Bmask, Amask
+ 0, MAX_CURSOR_WIDTH, MAX_CURSOR_HEIGHT, PIXEL_DEPTH,
+ RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK
);
- SDL_SetColorKey(MouseCursor, SDL_SRCCOLORKEY, 0);
+ SDL_SetColorKey(MouseCursor, SDL_TRUE, 0);
+
+ if (MouseCursor == NULL)
+ {
+ SLOGE(DEBUG_TAG_VIDEO, "SDL_CreateRGBSurface for MouseCursor failed: %s\n", SDL_GetError());
+ }
SDL_ShowCursor(SDL_DISABLE);
@@ -192,8 +217,7 @@ void InitializeVideoManager(void)
void ShutdownVideoManager(void)
{
- DebugMsg(TOPIC_VIDEO, DBG_LEVEL_0, "Shutting down the video manager");
-
+ SLOGD(DEBUG_TAG_VIDEO, "Shutting down the video manager");
/* Toggle the state of the video manager to indicate to the refresh thread
* that it needs to shut itself down */
@@ -211,32 +235,6 @@ void SuspendVideoManager(void)
guiVideoManagerState = VIDEO_SUSPENDED;
}
-
-BOOLEAN RestoreVideoManager(void)
-{
-#if 1 // XXX TODO
- UNIMPLEMENTED;
- return false;
-#else
- // Make sure the video manager is indeed suspended before moving on
-
- if (guiVideoManagerState == VIDEO_SUSPENDED)
- {
- // Set the video state to VIDEO_ON
-
- guiFrameBufferState = BUFFER_DIRTY;
- gfForceFullScreenRefresh = TRUE;
- guiVideoManagerState = VIDEO_ON;
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-#endif
-}
-
-
void InvalidateRegion(INT32 iLeft, INT32 iTop, INT32 iRight, INT32 iBottom)
{
if (gfForceFullScreenRefresh)
@@ -346,7 +344,7 @@ void InvalidateScreen(void)
static void ScrollJA2Background(INT16 sScrollXIncrement, INT16 sScrollYIncrement)
{
SDL_Surface* Frame = FrameBuffer;
- SDL_Surface* Source = ScreenBuffer; // Primary
+ SDL_Surface* Source = SDL_CreateRGBSurface(0, ScreenBuffer->w, ScreenBuffer->h, PIXEL_DEPTH, RED_MASK, GREEN_MASK, BLUE_MASK, ALPHA_MASK);
SDL_Surface* Dest = ScreenBuffer; // Back
SDL_Rect SrcRect;
SDL_Rect DstRect;
@@ -356,6 +354,8 @@ static void ScrollJA2Background(INT16 sScrollXIncrement, INT16 sScrollYIncrement
const UINT16 usWidth = SCREEN_WIDTH;
const UINT16 usHeight = gsVIEWPORT_WINDOW_END_Y - gsVIEWPORT_WINDOW_START_Y;
+ SDL_BlitSurface(ScreenBuffer, NULL, Source, NULL);
+
if (sScrollXIncrement < 0)
{
SrcRect.x = 0;
@@ -444,14 +444,17 @@ static void ScrollJA2Background(INT16 sScrollXIncrement, INT16 sScrollYIncrement
// BLIT NEW
ExecuteVideoOverlaysToAlternateBuffer(BACKBUFFER);
- SDL_UpdateRect
- (
- Dest,
- gsVIEWPORT_START_X,
- gsVIEWPORT_WINDOW_START_Y,
- gsVIEWPORT_END_X - gsVIEWPORT_START_X,
- gsVIEWPORT_WINDOW_END_Y - gsVIEWPORT_WINDOW_START_Y
- );
+ SDL_Texture* screenTexture = SDL_CreateTextureFromSurface(GameRenderer, ScreenBuffer);
+
+ SDL_Rect r;
+ r.x = gsVIEWPORT_START_X;
+ r.y = gsVIEWPORT_WINDOW_START_Y;
+ r.w = gsVIEWPORT_END_X - gsVIEWPORT_START_X;
+ r.h = gsVIEWPORT_WINDOW_END_Y - gsVIEWPORT_WINDOW_START_Y;
+ SDL_RenderCopy(GameRenderer, screenTexture, &r, &r);
+
+ SDL_FreeSurface(Source);
+ SDL_DestroyTexture(screenTexture);
}
@@ -481,8 +484,8 @@ static void WriteTGAHeader(FILE* const f)
0,
0, 0,
0, 0,
- SCREEN_WIDTH % 256, SCREEN_WIDTH / 256,
- SCREEN_HEIGHT % 256, SCREEN_HEIGHT / 256,
+ (UINT8) (SCREEN_WIDTH % 256), (UINT8) (SCREEN_WIDTH / 256),
+ (UINT8) (SCREEN_HEIGHT % 256), (UINT8) (SCREEN_HEIGHT / 256),
PIXEL_DEPTH,
0
};
@@ -550,29 +553,6 @@ static void TakeScreenshot()
static void SnapshotSmall(void);
-#if EXPENSIVE_SDL_UPDATE_RECT
-static void joinInRectangle(SDL_Rect &result, const SDL_Rect &newRect)
-{
- if((newRect.w != 0) && (newRect.h != 0))
- {
- if((result.w == 0) && (result.h == 0))
- {
- // special case: empty rectangle
- result = newRect;
- }
- else
- {
- int16_t X2 = std::max(result.x + result.w, newRect.x + newRect.w);
- int16_t Y2 = std::max(result.y + result.h, newRect.y + newRect.h);
- result.x = std::min(result.x, newRect.x);
- result.y = std::min(result.y, newRect.y);
- result.w = X2 - result.x;
- result.h = Y2 - result.y;
- }
- }
-}
-#endif
-
void RefreshScreen(void)
{
if (guiVideoManagerState != VIDEO_ON) return;
@@ -660,10 +640,6 @@ void RefreshScreen(void)
gfPrintFrameBuffer = FALSE;
}
-#if EXPENSIVE_SDL_UPDATE_RECT
- SDL_Rect combinedRect = {0, 0, 0, 0};
-#endif
-
SGPPoint MousePos;
GetMousePos(&MousePos);
SDL_Rect src;
@@ -675,56 +651,13 @@ void RefreshScreen(void)
dst.x = MousePos.iX - gsMouseCursorXOffset;
dst.y = MousePos.iY - gsMouseCursorYOffset;
SDL_BlitSurface(MouseCursor, &src, ScreenBuffer, &dst);
-
-#if EXPENSIVE_SDL_UPDATE_RECT
- joinInRectangle(combinedRect, dst);
- joinInRectangle(combinedRect, MouseBackground);
-#else
- SDL_UpdateRects(ScreenBuffer, 1, &dst);
- SDL_UpdateRects(ScreenBuffer, 1, &MouseBackground);
-#endif
-
MouseBackground = dst;
- if (gfForceFullScreenRefresh)
- {
- SDL_UpdateRect(ScreenBuffer, 0, 0, 0, 0);
- }
- else
- {
-#if EXPENSIVE_SDL_UPDATE_RECT
- for(int i = 0; i < guiDirtyRegionCount; i++)
- {
- joinInRectangle(combinedRect, DirtyRegions[i]);
- }
-#else
- SDL_UpdateRects(ScreenBuffer, guiDirtyRegionCount, DirtyRegions);
-#endif
-
- for (UINT32 i = 0; i < guiDirtyRegionExCount; i++)
- {
- SDL_Rect* r = &DirtyRegionsEx[i];
- if (scrolling)
- {
- if (r->y <= gsVIEWPORT_WINDOW_END_Y && r->y + r->h <= gsVIEWPORT_WINDOW_END_Y)
- {
- continue;
- }
- }
-#if EXPENSIVE_SDL_UPDATE_RECT
- joinInRectangle(combinedRect, *r);
-#else
- SDL_UpdateRects(ScreenBuffer, 1, r);
-#endif
- }
- }
+ SDL_UpdateTexture(ScreenTexture, NULL, ScreenBuffer->pixels, ScreenBuffer->pitch);
-#if EXPENSIVE_SDL_UPDATE_RECT
- if((combinedRect.w != 0) && (combinedRect.h != 0))
- {
- SDL_UpdateRects(ScreenBuffer, 1, &combinedRect);
- }
-#endif
+ SDL_RenderClear(GameRenderer);
+ SDL_RenderCopy(GameRenderer, ScreenTexture, NULL, NULL);
+ SDL_RenderPresent(GameRenderer);
gfForceFullScreenRefresh = FALSE;
guiDirtyRegionCount = 0;
@@ -815,33 +748,6 @@ static void SnapshotSmall(void)
if (giNumFrames == MAX_NUM_FRAMES) RefreshMovieCache();
}
-
-void VideoCaptureToggle(void)
-{
-#ifdef JA2TESTVERSION
- gfVideoCapture = !gfVideoCapture;
- if (gfVideoCapture)
- {
- for (INT32 cnt = 0; cnt < MAX_NUM_FRAMES; cnt++)
- {
- gpFrameData[cnt] = MALLOCN(UINT16, SCREEN_WIDTH * SCREEN_HEIGHT);
- }
- guiLastFrame = GetClock();
- }
- else
- {
- RefreshMovieCache();
-
- for (INT32 cnt = 0; cnt < MAX_NUM_FRAMES; cnt++)
- {
- if (gpFrameData[cnt] != NULL) MemFree(gpFrameData[cnt]);
- }
- }
- giNumFrames = 0;
-#endif
-}
-
-
static void RefreshMovieCache(void)
{
static UINT32 uiPicNum = 0;
@@ -935,7 +841,7 @@ void InitializeVideoSurfaceManager(void)
void ShutdownVideoSurfaceManager(void)
{
- DebugMsg(TOPIC_VIDEOSURFACE, DBG_LEVEL_0, "Shutting down the Video Surface manager");
+ SLOGD(DEBUG_TAG_VIDEO, "Shutting down the Video Surface manager");
// Delete primary viedeo surfaces
DeletePrimaryVideoSurfaces();
diff --git a/sgp/Video.h b/sgp/Video.h
index fbb980b..2158ef3 100644
--- a/sgp/Video.h
+++ b/sgp/Video.h
@@ -6,13 +6,14 @@
#define VIDEO_NO_CURSOR 0xFFFF
+#define GAME_WINDOW g_game_window
+extern SDL_Window* g_game_window;
void VideoSetFullScreen(BOOLEAN enable);
void InitializeVideoManager(void);
void ShutdownVideoManager(void);
void SuspendVideoManager(void);
-BOOLEAN RestoreVideoManager(void);
void InvalidateRegion(INT32 iLeft, INT32 iTop, INT32 iRight, INT32 iBottom);
void InvalidateScreen(void);
void GetPrimaryRGBDistributionMasks(UINT32* RedBitMask, UINT32* GreenBitMask, UINT32* BlueBitMask);
@@ -25,8 +26,6 @@ void VideoToggleFullScreen(void);
void SetMouseCursorProperties(INT16 sOffsetX, INT16 sOffsetY, UINT16 usCursorHeight, UINT16 usCursorWidth);
-void VideoCaptureToggle(void);
-
void InvalidateRegionEx(INT32 iLeft, INT32 iTop, INT32 iRight, INT32 iBottom);
void RefreshScreen(void);