mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-27 13:11:46 +03:00
2479 lines
75 KiB
Diff
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);
|