From 4d4ca3fef10ba155c19e83b7ec6a2cc77656344c Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Sat, 28 Mar 2020 10:02:35 +0100 Subject: [PATCH 01/29] Create save sub-directories --- ctp2_code/gs/fileio/CivPaths.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ctp2_code/gs/fileio/CivPaths.cpp b/ctp2_code/gs/fileio/CivPaths.cpp index baf595efa..3cfd3b051 100644 --- a/ctp2_code/gs/fileio/CivPaths.cpp +++ b/ctp2_code/gs/fileio/CivPaths.cpp @@ -215,17 +215,17 @@ void CivPaths::CreateSaveFolders(const MBCHAR *path) c3files_CreateDirectory(path); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveGamePath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveQueuePath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveMPPath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveSCENPath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveMapPath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveClipsPath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); } void CivPaths::InitCDPath(void) From 737864fa31c7e33f08fcd08f3f069f825813c79d Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Sat, 28 Mar 2020 09:33:29 +0100 Subject: [PATCH 02/29] allow non-complete paths in _fullname (linux) --- ctp2_code/os/nowin32/nowin32.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/ctp2_code/os/nowin32/nowin32.cpp b/ctp2_code/os/nowin32/nowin32.cpp index 582469c1a..d5dd70dfd 100644 --- a/ctp2_code/os/nowin32/nowin32.cpp +++ b/ctp2_code/os/nowin32/nowin32.cpp @@ -45,7 +45,8 @@ char* _fullpath(char* absolute, const char* relative, size_t bufsize) else { #ifdef __USE_GNU - char *abs = canonicalize_file_name(CI_FixName(relative)); + const char *fixedName = CI_FixName(relative); + char *abs = canonicalize_file_name(fixedName); if(abs) { strncpy(dest, abs, size - 1); @@ -54,7 +55,29 @@ char* _fullpath(char* absolute, const char* relative, size_t bufsize) } else { - return NULL; + // NOTE: canonicalize_file_name will return NULL if last element does not exist + // as this method should not return NULL in that case we test dirname on existence + char *fixedNameDuplicate = strdup(fixedName); + abs = canonicalize_file_name(dirname(fixedNameDuplicate)); + free(fixedNameDuplicate); + if (abs) + { + strncpy(dest, abs, size - 1); + dest[size - 1] = '\0'; + free(abs); + + // add basename + int spaceLeft = size - strlen(dest); + Assert(spaceLeft >= 0); + strncat(dest, FILE_SEP, spaceLeft); + fixedNameDuplicate = strdup(fixedName); + strncat(dest, basename(fixedNameDuplicate), spaceLeft - strlen(FILE_SEP)); + free(fixedNameDuplicate); + } + else + { + return NULL; + } } #elif defined(BSD) || defined(__USE_BSD) char rlpath[PATH_MAX] = {0}; From 67a3f3c958a73d6fec9367ab50a0f9820cd4cb5f Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Sat, 28 Mar 2020 16:19:18 +0100 Subject: [PATCH 03/29] Fix incorrect assertion --- ctp2_code/ui/aui_common/aui_resource.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ctp2_code/ui/aui_common/aui_resource.h b/ctp2_code/ui/aui_common/aui_resource.h index dfea98d85..b4c1067d3 100644 --- a/ctp2_code/ui/aui_common/aui_resource.h +++ b/ctp2_code/ui/aui_common/aui_resource.h @@ -162,8 +162,8 @@ aui_Resource::aui_Resource() template aui_Resource::~aui_Resource() { - Assert(!m_resourceList); -// diabled because SetPointSize needed in linux debug version before m_surfaceList is populated Assert((m_resourceList->L() == 0)); + // disabled because SetPointSize needed in linux debug version before m_surfaceList is populated + // Assert(!m_resourceList || (m_resourceList->L() == 0)); delete m_resourceList; m_resourceList = NULL; From 1fb807386cfe47364d86e70db61635c489f82e12 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Fri, 17 Apr 2020 13:24:12 +0200 Subject: [PATCH 04/29] Fixes a division by zero Player without any units would cause a division by zero. --- ctp2_code/ui/aui_ctp2/SelItem.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/ctp2_code/ui/aui_ctp2/SelItem.cpp b/ctp2_code/ui/aui_ctp2/SelItem.cpp index 847efea7f..32553120a 100644 --- a/ctp2_code/ui/aui_ctp2/SelItem.cpp +++ b/ctp2_code/ui/aui_ctp2/SelItem.cpp @@ -29,15 +29,15 @@ // correct stop player is set. // - #01 Standardization of city selection and focus handling // (L. Hirth 6/2004) -// - Entrenching units are treated like Entrenched units. (Oct 16th 2005 Martin Gühmann) -// - Added select city instead of army option. (Oct 16th 2005 Martin Gühmann) +// - Entrenching units are treated like Entrenched units. (Oct 16th 2005 Martin Gühmann) +// - Added select city instead of army option. (Oct 16th 2005 Martin Gühmann) // - Added option to avoid an end turn if there are cities with empty build -// queues. (Oct. 22nd 2005 Martin Gühmann) Doesn't really work. +// queues. (Oct. 22nd 2005 Martin Gühmann) Doesn't really work. // - Added option to allow end turn if the game runs in the background, -// useful for automatic AI testing. (Oct. 22nd 2005 Martin Gühmann) -// - Added debug pathing for the city astar. (17-Jan-2008 Martin Gühmann) +// useful for automatic AI testing. (Oct. 22nd 2005 Martin Gühmann) +// - Added debug pathing for the city astar. (17-Jan-2008 Martin Gühmann) // - If the keyboard is used for moving the map is only centered if the auto -// center option is active. (23-Feb-2008 Martin Gühmann) +// center option is active. (23-Feb-2008 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -255,7 +255,7 @@ SelectedItem::SelectedItem(CivArchive &archive) SetPlayerOnScreen(m_current_player); - //Added by Martin Gühmann + //Added by Martin Gühmann //To make sure that save games saved with other players than //player one can be continued without using the cheat editor. NewTurnCount::SetStopPlayer(m_current_player); @@ -662,6 +662,9 @@ void SelectedItem::NextUnmovedUnit(bool isFirst, bool manualNextUnit) double SelectedItem::UnitsDoneRatio(){ Player *p = g_player[GetVisiblePlayer()]; sint32 numUnits= p->m_all_armies->Num(); + if (numUnits == 0) { + return 1.0; + } sint32 unitsDone= numUnits; for(sint32 u = numUnits - 1; u >= 0; u--){ @@ -676,6 +679,9 @@ double SelectedItem::UnitsDoneRatio(){ double SelectedItem::UnitsBusyRatio(){ Player *p = g_player[GetVisiblePlayer()]; sint32 numUnits= p->m_all_armies->Num(); + if (numUnits == 0) { + return 0.0; + } sint32 unitsDone= numUnits; for(sint32 u = numUnits - 1; u >= 0; u--){ From b539d99fe1f3415953a3e37badf13b76d070601b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matin=20G=C3=BChmann?= Date: Sun, 19 Apr 2020 00:08:16 +0100 Subject: [PATCH 05/29] Build the Linux ctp2 executable in executable directory ctp2_code/ctp/ as the Windows executables --- ctp2_code/Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ctp2_code/Makefile.am b/ctp2_code/Makefile.am index 27469209e..049c5decc 100644 --- a/ctp2_code/Makefile.am +++ b/ctp2_code/Makefile.am @@ -10,7 +10,7 @@ SUBDIRS = \ libs \ sound -bin_PROGRAMS = ctp2 +bin_PROGRAMS = ctp/ctp2 # This hack shortens include path list, # but prohibits using a separate build dir #ctp2_code=.. @@ -38,7 +38,7 @@ CTP2_ANET_INC=-I$(ctp2_code)/libs/anet/h include $(ctp2_code)/os/autoconf/Makefile.common -ctp2_LDADD = \ +ctp_ctp2_LDADD = \ gfx/gfx_utils/libgfxgfx_utils.la \ gfx/layers/libgfxlayers.la \ gfx/spritesys/libgfxspritesys.la \ @@ -57,10 +57,10 @@ ctp2_LDADD = \ $(CTP2_LIBOSNOWIN32_LDADD) \ $(CTP2_LIBTTF_LDADD) -ctp2_LDFLAGS = \ +ctp_ctp2_LDFLAGS = \ $(CTP2_LDFLAGS) -ctp2_SOURCES = \ +ctp_ctp2_SOURCES = \ ctp/ctp2_utils/appstrings.cpp \ ctp/ctp2_utils/c3cmdline.cpp \ ctp/ctp2_utils/c3cpu.cpp \ From ba4ca3af0792b9a9e5f8e60b4570a9d82505d96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matin=20G=C3=BChmann?= Date: Sun, 19 Apr 2020 03:18:59 +0100 Subject: [PATCH 06/29] Create ctp2linux.map after building the executable ctp2 for Linux debug builds --- GNUmakefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GNUmakefile.am b/GNUmakefile.am index 94073a0b3..2c51e443f 100644 --- a/GNUmakefile.am +++ b/GNUmakefile.am @@ -13,6 +13,9 @@ bootstrap bootstrap-anet doc local playtest: $(top_srcdir)/Makefile .PHONY: purge bootstrap doc local playtest if DEBUG +all-local: + nm --demangle --defined-only --numeric-sort $(top_srcdir)/ctp2_code/ctp/ctp2 > $(top_srcdir)/ctp2_code/ctp/ctp2linux.map + install-data-hook: nm --demangle --defined-only --numeric-sort $(DESTDIR)$(bindir)/ctp2 > $(DESTDIR)$(bindir)/ctp2linux.map endif From 2e59831a740a3997e22a1ec77daf2d7ecf9948f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matin=20G=C3=BChmann?= Date: Mon, 20 Apr 2020 01:44:43 +0100 Subject: [PATCH 07/29] Remove ctp2linux.map when cleaning or uninstalling Do this even in non-debug configuration, since it could have been created before in debug configuration. --- GNUmakefile.am | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/GNUmakefile.am b/GNUmakefile.am index 2c51e443f..5ccbb127e 100644 --- a/GNUmakefile.am +++ b/GNUmakefile.am @@ -19,3 +19,9 @@ all-local: install-data-hook: nm --demangle --defined-only --numeric-sort $(DESTDIR)$(bindir)/ctp2 > $(DESTDIR)$(bindir)/ctp2linux.map endif + +clean-local: + rm -f $(top_srcdir)/ctp2_code/ctp/ctp2linux.map + +uninstall-local: + rm -f $(DESTDIR)$(bindir)/ctp2linux.map From 84847c64fc92c1ed6caad7a2018d6591019fd7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matin=20G=C3=BChmann?= Date: Mon, 20 Apr 2020 01:49:42 +0100 Subject: [PATCH 08/29] Mention in README.md that you also have to install flex I had to install this too on my laptop, probably my desktop had it already. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d8ece5434..e58e6574a 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ You will probably need GCC 5.x or later to build. The code doesn't seem to build You will need SDL 1.2, SDL_Mixer, SDL_Image and the GTK 2.0 libraries. You will also need `byacc` -On debian and friends, use `sudo apt install libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev byacc gtk2.0-dev` to install them all. +On debian and friends, use `sudo apt install libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev byacc gtk2.0-dev flex` to install them all. The build itself is pretty classing and straight forward: From 08ab5e7a58948dbc8085f1a0d5009d862f8ce2d5 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Tue, 31 Mar 2020 22:28:37 +0200 Subject: [PATCH 09/29] Compile with SDL2 by skipping non-compliant code Three defines have been introduced to skip non-compliant code: SKIP_SDL2_EVENT_ISSUES, SKIP_SDL2_SCREEN_ISSUES, and SKIP_SDL2_CDROM_ISSUES. All three are active. --- configure.ac | 5 +++- ctp2_code/ctp/civ3_main.cpp | 34 ++++++++++++++---------- ctp2_code/ctp/civapp.cpp | 5 ++-- ctp2_code/ctp/ctp2_utils/c3cmdline.cpp | 4 +++ ctp2_code/ctp/ctp2_utils/c3files.cpp | 12 +++++++++ ctp2_code/ctp/ctp2_utils/tracklen.cpp | 13 +++++++++ ctp2_code/ctp/debugtools/log.cpp | 2 +- ctp2_code/ctp/display.cpp | 8 +++++- ctp2_code/net/io/net_thread.cpp | 2 +- ctp2_code/net/io/net_thread.h | 4 +-- ctp2_code/os/autoconf/Makefile.common | 2 +- ctp2_code/os/nowin32/nowin32.cpp | 2 +- ctp2_code/sound/civsound.cpp | 2 +- ctp2_code/sound/civsound.h | 2 +- ctp2_code/sound/soundmanager.cpp | 20 ++++++++++++++ ctp2_code/sound/soundmanager.h | 6 +++-- ctp2_code/ui/aui_common/aui_image.cpp | 2 ++ ctp2_code/ui/aui_common/aui_listbox.cpp | 2 +- ctp2_code/ui/aui_common/aui_mouse.cpp | 7 +++-- ctp2_code/ui/aui_common/aui_mouse.h | 4 +-- ctp2_code/ui/aui_common/aui_movie.cpp | 8 +++--- ctp2_code/ui/aui_common/aui_music.cpp | 4 +++ ctp2_code/ui/aui_common/aui_music.h | 6 ++++- ctp2_code/ui/aui_common/aui_surface.h | 4 +-- ctp2_code/ui/aui_common/aui_ui.cpp | 2 ++ ctp2_code/ui/aui_ctp2/c3imageformats.cpp | 4 +-- ctp2_code/ui/aui_sdl/aui_sdl.cpp | 2 ++ ctp2_code/ui/aui_sdl/aui_sdl.h | 2 +- ctp2_code/ui/aui_sdl/aui_sdlblitter.cpp | 4 +-- ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp | 6 +++-- ctp2_code/ui/aui_sdl/aui_sdlkeyboard.h | 2 +- ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp | 6 ++--- ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp | 7 +++-- ctp2_code/ui/aui_sdl/aui_sdlui.cpp | 2 ++ ctp2_code/ui/interface/chatbox.cpp | 2 +- ctp2_code/ui/netshell/netfunc.cpp | 8 +++--- ctp2_code/ui/netshell/netfunc.h | 4 +-- 37 files changed, 150 insertions(+), 61 deletions(-) diff --git a/configure.ac b/configure.ac index 29752693f..0e401afc3 100644 --- a/configure.ac +++ b/configure.ac @@ -54,11 +54,14 @@ dnl AC_PROG_LIBTOOL AM_PATH_DIRECTX AM_PATH_DXMEDIA -AM_PATH_SDL +AM_PATH_SDL2 AM_PATH_SDL_FFMPEG AC_PATH_X AC_PATH_XTRA AC_DEFINE(USE_SDL,1,[Use the SDL-library]) +AC_DEFINE(SKIP_SDL2_CDROM_ISSUES,1,[Skip SDL2 CD-rom code]) +AC_DEFINE(SKIP_SDL2_SCREEN_ISSUES,1,[Skip SDL2 screen code]) +AC_DEFINE(SKIP_SDL2_EVENT_ISSUES,1,[Skip SDL2 event code]) AC_WORDS_BIGENDIAN AC_OS_DEFINES diff --git a/ctp2_code/ctp/civ3_main.cpp b/ctp2_code/ctp/civ3_main.cpp index bf1e898ea..86af7dc70 100644 --- a/ctp2_code/ctp/civ3_main.cpp +++ b/ctp2_code/ctp/civ3_main.cpp @@ -169,8 +169,8 @@ #include #endif #if defined(USE_SDL) -#include -#include +#include +#include #include "aui_sdlkeyboard.h" #endif #ifdef HAVE_X11 @@ -1168,6 +1168,7 @@ void ParseCommandLine(PSTR szCmdLine) g_runSpriteEditor = (NULL != strstr(szCmdLine, "runspriteeditor")); #if defined(__AUI_USE_SDL__) + #if !defined(SKIP_SDL2_SCREEN_ISSUES) if (strstr(szCmdLine, "fullscreen")) g_SDL_flags = g_SDL_flags|SDL_FULLSCREEN; if (strstr(szCmdLine, "hwsurface")) @@ -1175,6 +1176,7 @@ void ParseCommandLine(PSTR szCmdLine) else g_SDL_flags = g_SDL_flags|SDL_SWSURFACE; if (strstr(szCmdLine, "openglblit")) g_SDL_flags = g_SDL_flags|SDL_OPENGLBLIT; + #endif // SKIP_SDL2_SCREEN_ISSUES #endif g_eventLog = (NULL != strstr(szCmdLine, "eventlog")); @@ -1705,8 +1707,12 @@ int WINAPI CivMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, break; } +#if !defined(SKIP_SDL2_EVENT_ISSUES) int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, ~(SDL_EVENTMASK(SDL_MOUSEMOTION) | SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN) | SDL_EVENTMASK(SDL_MOUSEBUTTONUP))); +#else // SKIP_SDL2_EVENT_ISSUES + int n = 0; +#endif // SKIP_SDL2_EVENT_ISSUES if (0 > n) { fprintf(stderr, "%s L%d: SDL_PeepEvents: Still events stored! Error?: %s\n", __FILE__, __LINE__, SDL_GetError()); @@ -1819,8 +1825,8 @@ int SDLMessageHandler(const SDL_Event &event) // TODO: Determine what the 'swallowNextChar' variable // is for, and, if necessary, implement appropriate // code in the SDL sections to perform the same function. - SDLKey key = event.key.keysym.sym; - SDLMod mod = event.key.keysym.mod; + SDL_Keycode key = event.key.keysym.sym; + Uint16 mod = event.key.keysym.mod; WPARAM wp = '\0'; switch (key) { #define SDLKCONV(sdl_name, char) \ @@ -1891,16 +1897,16 @@ int SDLMessageHandler(const SDL_Event &event) //SDLKCONVSHIFT(SDLK_F13, '' + 128, '\0'); //SDLKCONVSHIFT(SDLK_F14, '' + 128, '\0'); //SDLKCONVSHIFT(SDLK_F15, '' + 128, '\0'); - SDLKCONV(SDLK_KP0, '0'); - SDLKCONV(SDLK_KP1, '1'); - SDLKCONV(SDLK_KP2, '2'); - SDLKCONV(SDLK_KP3, '3'); - SDLKCONV(SDLK_KP4, '4'); - SDLKCONV(SDLK_KP5, '5'); - SDLKCONV(SDLK_KP6, '6'); - SDLKCONV(SDLK_KP7, '7'); - SDLKCONV(SDLK_KP8, '8'); - SDLKCONV(SDLK_KP9, '9'); + SDLKCONV(SDLK_KP_0, '0'); + SDLKCONV(SDLK_KP_1, '1'); + SDLKCONV(SDLK_KP_2, '2'); + SDLKCONV(SDLK_KP_3, '3'); + SDLKCONV(SDLK_KP_4, '4'); + SDLKCONV(SDLK_KP_5, '5'); + SDLKCONV(SDLK_KP_6, '6'); + SDLKCONV(SDLK_KP_7, '7'); + SDLKCONV(SDLK_KP_8, '8'); + SDLKCONV(SDLK_KP_9, '9'); SDLKCONV(SDLK_KP_PERIOD, '.'); SDLKCONV(SDLK_KP_DIVIDE, '/'); SDLKCONV(SDLK_KP_MULTIPLY, '*'); diff --git a/ctp2_code/ctp/civapp.cpp b/ctp2_code/ctp/civapp.cpp index d89e9ef0d..c823a4ef5 100644 --- a/ctp2_code/ctp/civapp.cpp +++ b/ctp2_code/ctp/civapp.cpp @@ -1250,7 +1250,7 @@ sint32 CivApp::InitializeApp(HINSTANCE hInstance, int iCmdShow) CoInitialize(NULL); #endif #ifdef __AUI_USE_SDL__ - Uint32 flags = (SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD) & ~SDL_INIT_AUDIO; //why no audio? + Uint32 flags = (SDL_INIT_EVERYTHING | SDL_INIT_EVENTS) & ~SDL_INIT_AUDIO; //why no audio? #if defined(_DEBUG) || defined(DEBUG) flags |= SDL_INIT_NOPARACHUTE; #endif// _DEBUG || DEBUG @@ -2365,8 +2365,7 @@ sint32 CivApp::ProcessUI(const uint32 target_milliseconds, uint32 &used_millisec #ifdef __AUI_USE_SDL__ // Because of the way keyboard events are handled in SDL, we // need to escape this loop if there are any SDL_KeyEvents pending - if (SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, - SDL_EVENTMASK(SDL_KEYUP) | SDL_EVENTMASK(SDL_KEYDOWN))) { + if (SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYUP)) { break; } #endif diff --git a/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp b/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp index f4d8dd475..1c6aad928 100644 --- a/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp +++ b/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp @@ -5853,9 +5853,13 @@ void FastRoundCommand::Execute(sint32 argc, char **argv) #if __AUI_USE_SDL__ while (1) { + #if !defined(SKIP_SDL2_EVENT_ISSUES) int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, ~(SDL_EVENTMASK(SDL_MOUSEMOTION) | SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN) | SDL_EVENTMASK(SDL_MOUSEBUTTONUP))); + #else // SKIP_SDL2_EVENT_ISSUES + int n = 0; + #endif // SKIP_SDL2_EVENT_ISSUES if (0 > n) { fprintf(stderr, "[FastRoundCommand::Execute] PeepEvents failed: %s\n", SDL_GetError()); diff --git a/ctp2_code/ctp/ctp2_utils/c3files.cpp b/ctp2_code/ctp/ctp2_utils/c3files.cpp index d041e5a9b..c4689a15c 100644 --- a/ctp2_code/ctp/ctp2_utils/c3files.cpp +++ b/ctp2_code/ctp/ctp2_utils/c3files.cpp @@ -580,7 +580,11 @@ bool c3files_HasLegalCD() void c3files_InitializeCD(void) { #if defined(__linux__) +#if !defined(SKIP_SDL2_CDROM_ISSUES) int rc = SDL_Init(SDL_INIT_CDROM); +#else // SKIP_SDL2_CDROM_ISSUES + int rc = 1; +#endif // SKIP_SDL2_CDROM_ISSUES if(0 != rc) { fprintf(stderr, "Could not initialize CDROM:\n%s\n", SDL_GetError()); @@ -828,7 +832,11 @@ void c3files_GetCDDrives(void) } } #else +#if !defined(SKIP_SDL2_CDROM_ISSUES) int CDCnt = SDL_CDNumDrives(); +#else // SKIP_SDL2_CDROM_ISSUES + int CDCnt = 0; +#endif // SKIP_SDL2_CDROM_ISSUES Assert(CDCnt >= 0); if (CDCnt < 0) { @@ -886,6 +894,9 @@ MBCHAR * c3files_GetVolumeName(DriveIdType id) return NULL; #elif defined(LINUX) +#if defined(SKIP_SDL2_CDROM_ISSUES) + return NULL; +#else // SKIP_SDL2_CDROM_ISSUES /// \todo Add code to determine beginsector of iso_primary_sector /// On a German ctp2 cd, it starts on sector 16 (byte 16 << 11 = 0x8000) const MBCHAR *cd_dev = SDL_CDName(id); @@ -946,6 +957,7 @@ MBCHAR * c3files_GetVolumeName(DriveIdType id) VolumeName[i+1] = '\0'; return VolumeName; +#endif // SKIP_SDL2_CDROM_ISSUES #endif } diff --git a/ctp2_code/ctp/ctp2_utils/tracklen.cpp b/ctp2_code/ctp/ctp2_utils/tracklen.cpp index 34c242530..66e49daf2 100644 --- a/ctp2_code/ctp/ctp2_utils/tracklen.cpp +++ b/ctp2_code/ctp/ctp2_utils/tracklen.cpp @@ -43,7 +43,9 @@ #include #endif #if defined(USE_SDL) +#if !defined(SKIP_SDL2_CDROM_ISSUES) #include +#endif // SKIP_SDL2_CDROM_ISSUES #endif #include "cheatkey.h" @@ -108,6 +110,7 @@ void tracklen_cryptBinary(char *data, size_t len) data[ index ] ^= p[ index % 400 ]; } +#if !defined(SKIP_SDL2_CDROM_ISSUES) #ifdef USE_SDL static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, SDL_CD *cdrom ) #else @@ -204,12 +207,17 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w return 0; } +#endif // SKIP_SDL2_CDROM_ISSUES + #if defined(USE_SDL) int tracklen_GetTrackLengths(DWORD *trackLenBuf, int iDrive) #else int tracklen_GetTrackLengths(DWORD *trackLenBuf, char whichDrive) #endif { +#if defined(SKIP_SDL2_CDROM_ISSUES) + return __LINE__; +#else // SKIP_SDL2_CDROM_ISSUES #if defined(USE_SDL) const char *driveName = SDL_CDName(iDrive); if (!driveName) @@ -264,10 +272,14 @@ int tracklen_GetTrackLengths(DWORD *trackLenBuf, char whichDrive) tracklen_DPRINT((tracklen_buf, "GetTrackLengths: Returning %d\n", iRet )); return iRet; +#endif // SKIP_SDL2_CDROM_ISSUES } static int tracklen_CheckTrackLengths2( DWORD *trackLenBuf) { +#if defined(SKIP_SDL2_CDROM_ISSUES) + return __LINE__; +#else // SKIP_SDL2_CDROM_ISSUES if( !trackLenBuf ) return __LINE__; @@ -351,6 +363,7 @@ static int tracklen_CheckTrackLengths2( DWORD *trackLenBuf) tracklen_DPRINT((tracklen_buf, "CheckTrackLengths2: failure!\n")); return __LINE__; +#endif // SKIP_SDL2_CDROM_ISSUES } DWORD *tracklen_LoadEncryptedKey( DWORD *trackLenBuf, const char *szFile ) diff --git a/ctp2_code/ctp/debugtools/log.cpp b/ctp2_code/ctp/debugtools/log.cpp index e7d4d9e2e..3b3c9c45f 100644 --- a/ctp2_code/ctp/debugtools/log.cpp +++ b/ctp2_code/ctp/debugtools/log.cpp @@ -19,7 +19,7 @@ #endif #ifdef USE_SDL -#include +#include #endif #ifdef __linux__ diff --git a/ctp2_code/ctp/display.cpp b/ctp2_code/ctp/display.cpp index e6077d651..c4c982658 100644 --- a/ctp2_code/ctp/display.cpp +++ b/ctp2_code/ctp/display.cpp @@ -9,7 +9,7 @@ #ifdef __AUI_USE_DIRECTX__ #include #elif defined(__AUI_USE_SDL__) -#include +#include #endif PointerList *g_displayModes = NULL; @@ -140,7 +140,11 @@ void display_EnumerateDisplayModes(void) #else SDL_PixelFormat fmt = { 0 }; fmt.BitsPerPixel = 16; +#if !defined(SKIP_SDL2_SCREEN_ISSUES) SDL_Rect **modes = SDL_ListModes(/*&fmt*/NULL, SDL_FULLSCREEN); +#else // SKIP_SDL2_SCREEN_ISSUES + SDL_Rect **modes = 0; +#endif // SKIP_SDL2_SCREEN_ISSUES g_displayModes = new PointerList; @@ -149,6 +153,7 @@ void display_EnumerateDisplayModes(void) } else if ((SDL_Rect **) -1 == modes) { // Fallback if SDL reports us to support anything, // we'll pick 800 x 600 and 1024 x 768 +#if !defined(SKIP_SDL2_SCREEN_ISSUES) const SDL_VideoInfo *info = SDL_GetVideoInfo(); if (0 == info) { return; @@ -172,6 +177,7 @@ void display_EnumerateDisplayModes(void) mode->width = 1024; mode->height = 768; g_displayModes->AddTail(mode); +#endif // SKIP_SDL2_SCREEN_ISSUES } else { for (int i = 0; modes[i]; i++) { // We might get modes multiple times for each bpp diff --git a/ctp2_code/net/io/net_thread.cpp b/ctp2_code/net/io/net_thread.cpp index f1ee9f123..22f2229f5 100644 --- a/ctp2_code/net/io/net_thread.cpp +++ b/ctp2_code/net/io/net_thread.cpp @@ -203,7 +203,7 @@ NET_ERR NetThread::Init(NetIOResponse *response) NetIO::Init(response); #ifdef USE_SDL - if ((m_thread = SDL_CreateThread(NetThread_StartThread, this)) == NULL) { + if ((m_thread = SDL_CreateThread(NetThread_StartThread, "Net-start-thread", this)) == NULL) { #elif defined(WIN32) if((m_threadHandle = CreateThread(NULL, 0, diff --git a/ctp2_code/net/io/net_thread.h b/ctp2_code/net/io/net_thread.h index eac59c5fc..21a832057 100644 --- a/ctp2_code/net/io/net_thread.h +++ b/ctp2_code/net/io/net_thread.h @@ -10,8 +10,8 @@ #include "pointerlist.h" #include "net_anet.h" #ifdef USE_SDL -#include -#include +#include +#include #endif #define k_MAX_NETWORK_PLAYERS 32 diff --git a/ctp2_code/os/autoconf/Makefile.common b/ctp2_code/os/autoconf/Makefile.common index 91eb7f2fd..aa6a5d272 100644 --- a/ctp2_code/os/autoconf/Makefile.common +++ b/ctp2_code/os/autoconf/Makefile.common @@ -6,7 +6,7 @@ CTP2_LDFLAGS = \ $(DIRECTX_LDFLAGS) \ $(DXMEDIA_LDFLAGS) \ $(SDL_LDFLAGS) \ - -ltiff -lz -lSDL -lSDL_image -lSDL_mixer $(SDL_FFMPEG_LDFLAGS) -ldl -lpthread \ + -ltiff -lz -lSDL2 -lSDL2_image -lSDL2_mixer $(SDL_FFMPEG_LDFLAGS) -ldl -lpthread \ $(X_PRE_LIBS) \ $(X_LIBS) -lX11 \ $(GTK_LIBS) -ldl diff --git a/ctp2_code/os/nowin32/nowin32.cpp b/ctp2_code/os/nowin32/nowin32.cpp index d5dd70dfd..7a9235b1e 100644 --- a/ctp2_code/os/nowin32/nowin32.cpp +++ b/ctp2_code/os/nowin32/nowin32.cpp @@ -16,7 +16,7 @@ #endif #include #include -#include +#include #include "windows.h" diff --git a/ctp2_code/sound/civsound.cpp b/ctp2_code/sound/civsound.cpp index 1f49363ff..773238789 100644 --- a/ctp2_code/sound/civsound.cpp +++ b/ctp2_code/sound/civsound.cpp @@ -43,7 +43,7 @@ #include "prjfile.h" #if defined(USE_SDL) -#include +#include #endif extern ProjectFile *g_SoundPF; diff --git a/ctp2_code/sound/civsound.h b/ctp2_code/sound/civsound.h index 7c13bb042..c50d65acb 100644 --- a/ctp2_code/sound/civsound.h +++ b/ctp2_code/sound/civsound.h @@ -49,7 +49,7 @@ #endif #if defined(USE_SDL) -#include +#include #else #include "mss.h" #endif diff --git a/ctp2_code/sound/soundmanager.cpp b/ctp2_code/sound/soundmanager.cpp index fe1b89e7d..40d8d3a4d 100755 --- a/ctp2_code/sound/soundmanager.cpp +++ b/ctp2_code/sound/soundmanager.cpp @@ -94,7 +94,9 @@ SoundManager::SoundManager() #if !defined(USE_SDL) m_redbook (0), #else +#if !defined(SKIP_SDL2_CDROM_ISSUES) m_cdrom (0), +#endif // SKIP_SDL2_CDROM_ISSUES m_useOggTracks (false), m_oggTrack (0), m_SDLInitFlags (SDL_INIT_NOPARACHUTE), @@ -219,6 +221,7 @@ void SoundManager::InitRedbook() printf("Detected Ogg Music track, using that instead of CD Audio\n"); } } +#if !defined(SKIP_SDL2_CDROM_ISSUES) if (!m_cdrom && !m_useOggTracks) { int errcode = SDL_Init(SDL_INIT_CDROM | m_SDLInitFlags); @@ -257,6 +260,7 @@ void SoundManager::InitRedbook() CDstatus status = SDL_CDStatus(m_cdrom); } } +#endif // SKIP_SLD2_CDROM_ISSUES #else // !USE_SDL if (!m_redbook) { @@ -272,10 +276,12 @@ void SoundManager::CleanupRedbook() Mix_FreeMusic(m_oggTrack); m_oggTrack = NULL; } +#if !defined(SKIP_SDL2_CDROM_ISSUES) if (m_cdrom) { SDL_CDClose(m_cdrom); m_cdrom = 0; } +#endif // SKIP_SDL2_CDROM_ISSUES #else if (m_redbook) { AIL_redbook_stop(m_redbook); @@ -291,6 +297,7 @@ void SoundManager::ProcessRedbook() if (!m_musicEnabled) return; +#if!defined(SKIP_SDL2_CDROM_ISSUES) if (GetTickCount() > m_timeToCheckCD) { #if defined(USE_SDL) CDstatus status; @@ -347,6 +354,7 @@ void SoundManager::ProcessRedbook() m_timeToCheckCD = GetTickCount() + k_CHECK_CD_PERIOD; } +#endif // SKIP_SDL2_CDROM_ISSUES } void SoundManager::Process(const uint32 &target_milliseconds, @@ -680,9 +688,11 @@ SoundManager::SetVolume(const SOUNDTYPE &type, const uint32 &volume) Mix_VolumeMusic(scaledVolume); } } +#if !defined(SKIP_SDL2_CDROM_ISSUES) if (m_cdrom) { // TODO: found nothing in reference } +#endif // SKIP_SDL2_CDROM_ISSUES #endif break; } @@ -945,6 +955,7 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) return; } +#if !defined(SKIP_SDL2_CDROM_ISSUES) if (!m_cdrom) { return; } @@ -956,6 +967,9 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) } sint32 const numTracks = m_cdrom->numtracks; +#else // SKIP_SDL2_CDROM_ISSUES + sint32 const numTracks = 0; +#endif // SKIP_SDL2_CDROM_ISSUES #else if (!m_redbook) { return; @@ -985,7 +999,9 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) m_curTrack = trackNum; #if defined(USE_SDL) +#if !defined(SKIP_SDL2_CDROM_ISSUES) SDL_CDPlayTracks(m_cdrom, trackNum, 0, 1, 0); +#endif // SKIP_SDL2_CDROM_ISSUES #else U32 start; U32 end; @@ -1016,7 +1032,9 @@ void SoundManager::TerminateMusic(void) // } if (!m_redbook) return; #else +#if !defined(SKIP_SDL2_CDROM_ISSUES) if (!m_cdrom) return; +#endif // SKIP_SDL2_CDROM_ISSUES #endif m_stopRedbookTemporarily = TRUE; @@ -1026,11 +1044,13 @@ void SoundManager::TerminateMusic(void) AIL_redbook_stop(m_redbook); } #else +#if !defined(SKIP_SDL2_CDROM_ISSUES) CDstatus status = SDL_CDStatus(m_cdrom); if (CD_PLAYING == status) { SDL_CDStop(m_cdrom); } +#endif // SKIP_SDL2_CDROM_ISSUES #endif } diff --git a/ctp2_code/sound/soundmanager.h b/ctp2_code/sound/soundmanager.h index 4c2462676..47ddf9a15 100644 --- a/ctp2_code/sound/soundmanager.h +++ b/ctp2_code/sound/soundmanager.h @@ -44,8 +44,8 @@ #include "gamesounds.h" #if defined(USE_SDL) -#include -#include +#include +#include #endif template class PointerList; @@ -163,7 +163,9 @@ class SoundManager { #if !defined(USE_SDL) HREDBOOK m_redbook; #else + #if !defined(SKIP_SDL2_CDROM_ISSUES) SDL_CD *m_cdrom; + #endif // SKIP_SDL2_CDROM_ISSUES BOOL m_useOggTracks; Uint32 m_SDLInitFlags; Mix_Music *m_oggTrack; diff --git a/ctp2_code/ui/aui_common/aui_image.cpp b/ctp2_code/ui/aui_common/aui_image.cpp index 9f3e3ed96..9e2f6e452 100644 --- a/ctp2_code/ui/aui_common/aui_image.cpp +++ b/ctp2_code/ui/aui_common/aui_image.cpp @@ -324,7 +324,9 @@ AUI_ERRCODE aui_BmpImageFormat::Load(MBCHAR const * filename, aui_Image *image ) if (bmp->format->Gmask >> bmp->format->Gshift == 0x1F) fprintf(stderr, "%s L%d: 555 image!\n", __FILE__, __LINE__); if (NULL == surf) { +#if !defined(SKIP_SDL2_SCREEN_ISSUES) surf = SDL_DisplayFormat(bmp); +#endif // SKIP_SDL2_SCREEN_ISSUES } SDL_FreeSurface(bmp); if (NULL == surf) diff --git a/ctp2_code/ui/aui_common/aui_listbox.cpp b/ctp2_code/ui/aui_common/aui_listbox.cpp index 8ccecd8f5..2c92ec78e 100644 --- a/ctp2_code/ui/aui_common/aui_listbox.cpp +++ b/ctp2_code/ui/aui_common/aui_listbox.cpp @@ -52,7 +52,7 @@ #include "ldl_file.hpp" #ifdef USE_SDL -#include +#include #endif aui_DragDropWindow *aui_ListBox::m_dragDropWindow = NULL; diff --git a/ctp2_code/ui/aui_common/aui_mouse.cpp b/ctp2_code/ui/aui_common/aui_mouse.cpp index e54403c9a..4ca9458e3 100644 --- a/ctp2_code/ui/aui_common/aui_mouse.cpp +++ b/ctp2_code/ui/aui_common/aui_mouse.cpp @@ -404,7 +404,7 @@ AUI_ERRCODE aui_Mouse::Start( void ) m_thread = CreateThread( NULL, 0, MouseThreadProc, (LPVOID)this, 0, &m_threadId ); #elif defined(__AUI_USE_SDL__) - m_thread = SDL_CreateThread(MouseThreadProc, this); + m_thread = SDL_CreateThread(MouseThreadProc, "Mouse-thread", this); #endif m_curCursor = m_cursors + m_firstIndex; @@ -484,7 +484,10 @@ AUI_ERRCODE aui_Mouse::End( void ) else TerminateThread( m_thread, 1 ); #elif defined(__AUI_USE_SDL__) - SDL_KillThread(m_thread); + g_mouseShouldTerminateThread = TRUE; + + int status = 0; + SDL_WaitThread(m_thread, &status); #endif Erase(); diff --git a/ctp2_code/ui/aui_common/aui_mouse.h b/ctp2_code/ui/aui_common/aui_mouse.h index 4b82d5cc2..af9e89466 100644 --- a/ctp2_code/ui/aui_common/aui_mouse.h +++ b/ctp2_code/ui/aui_common/aui_mouse.h @@ -36,8 +36,8 @@ #include "tech_wllist.h" #ifdef USE_SDL -#include -#include +#include +#include #endif class aui_Cursor; diff --git a/ctp2_code/ui/aui_common/aui_movie.cpp b/ctp2_code/ui/aui_common/aui_movie.cpp index e5889169d..1d9bb840c 100644 --- a/ctp2_code/ui/aui_common/aui_movie.cpp +++ b/ctp2_code/ui/aui_common/aui_movie.cpp @@ -24,7 +24,7 @@ // // Modifications from the original Activision code: // -// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin G�hmann) // //---------------------------------------------------------------------------- @@ -37,13 +37,13 @@ #include "aui_movie.h" #ifdef __AUI_USE_SDL__ -#include +#include #ifdef USE_SDL_FFMPEG #include SDL_ffmpegFile* film; #endif -#include -#include +#include +#include #include "soundmanager.h" // g_soundManager #include "aui_sdlsurface.h" diff --git a/ctp2_code/ui/aui_common/aui_music.cpp b/ctp2_code/ui/aui_common/aui_music.cpp index c061aea9b..6bc6c1b18 100644 --- a/ctp2_code/ui/aui_common/aui_music.cpp +++ b/ctp2_code/ui/aui_common/aui_music.cpp @@ -62,7 +62,9 @@ aui_Redbook::aui_Redbook() : #ifdef __AUI_USE_DIRECTX__ m_cd_device_id(-1), #elif defined(__AUI_USE_SDL__) +#if !defined(SKIP_SDL2_CDROM_ISSUES) m_cd_device_id(0), +#endif // SKIP_SDL2_CDROM_ISSUES #endif m_cd_drive_num(0), m_cd_drive_index(0), @@ -77,7 +79,9 @@ aui_Redbook::~aui_Redbook() #ifdef __AUI_USE_DIRECTX__ m_cd_device_id = -1; #elif defined(__AUI_USE_SDL__) +#if !defined(SKIP_SDL2_CDROM_ISSUES) m_cd_device_id = 0; +#endif // SKIP_SDL2_CDROM_ISSUES #endif m_cd_drive_num = 0; m_cd_drive_index = 0; diff --git a/ctp2_code/ui/aui_common/aui_music.h b/ctp2_code/ui/aui_common/aui_music.h index 96cc128d5..890c70757 100644 --- a/ctp2_code/ui/aui_common/aui_music.h +++ b/ctp2_code/ui/aui_common/aui_music.h @@ -3,8 +3,10 @@ #include "aui_base.h" #ifdef USE_SDL -#include +#include +#if !defined(SKIP_SDL2_CDROM_ISSUES) #include +#endif // SKIP_SDL2_CDROM_ISSUES #endif enum AUI_MUSIC_CODE @@ -98,7 +100,9 @@ class aui_Redbook : public aui_Music #ifdef __AUI_USE_DIRECTX__ sint32 m_cd_device_id; #elif defined(__AUI_USE_SDL__) +#if !defined(SKIP_SDL2_CDROM_ISSUES) SDL_CD*m_cd_device_id; +#endif // SKIP_SDL2_CDROM_ISSUES #endif int m_cd_drive_num; sint32 m_cd_drive_index; diff --git a/ctp2_code/ui/aui_common/aui_surface.h b/ctp2_code/ui/aui_common/aui_surface.h index 6d7ce9f27..574d215f0 100644 --- a/ctp2_code/ui/aui_common/aui_surface.h +++ b/ctp2_code/ui/aui_common/aui_surface.h @@ -36,8 +36,8 @@ #include "aui_base.h" #ifdef USE_SDL -#include -#include +#include +#include #endif enum AUI_SURFACE_PIXELFORMAT diff --git a/ctp2_code/ui/aui_common/aui_ui.cpp b/ctp2_code/ui/aui_common/aui_ui.cpp index 46823048b..2bdafa6c0 100644 --- a/ctp2_code/ui/aui_common/aui_ui.cpp +++ b/ctp2_code/ui/aui_common/aui_ui.cpp @@ -1105,6 +1105,7 @@ AUI_ERRCODE aui_UI::Draw( void ) } #ifdef __AUI_USE_SDL__ // refresh screen +#if !defined(SKIP_SDL2_SCREEN_ISSUES) SDL_Surface * screen = SDL_GetVideoSurface(); /*if(m_dirtyRectInfoList->L()) { ListPos position = m_dirtyRectInfoList->GetHeadPosition(); @@ -1124,6 +1125,7 @@ AUI_ERRCODE aui_UI::Draw( void ) } }*/ SDL_Flip(screen); +#endif // SKIP_SDL2_SCREEN_ISSUES #endif errcode = m_mouse->Resume(); Assert( errcode == AUI_ERRCODE_OK ); diff --git a/ctp2_code/ui/aui_ctp2/c3imageformats.cpp b/ctp2_code/ui/aui_ctp2/c3imageformats.cpp index f51cc9d51..4d2c64e26 100644 --- a/ctp2_code/ui/aui_ctp2/c3imageformats.cpp +++ b/ctp2_code/ui/aui_ctp2/c3imageformats.cpp @@ -42,8 +42,8 @@ #endif #if defined(__AUI_USE_SDL__) -#include -#include +#include +#include #include "aui_sdlsurface.h" #endif diff --git a/ctp2_code/ui/aui_sdl/aui_sdl.cpp b/ctp2_code/ui/aui_sdl/aui_sdl.cpp index f5e2ad497..8b5142e00 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdl.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdl.cpp @@ -26,6 +26,7 @@ AUI_ERRCODE aui_SDL::InitCommon(BOOL useExclusiveMode) */ SDL_ShowCursor(SDL_DISABLE); +#if !defined(SKIP_SDL2_EVENT_ISSUES) // enable only a handfull of events SDL_EventState(SDL_IGNORE, SDL_ALLEVENTS); SDL_EventState(SDL_ENABLE, SDL_MOUSEEVENTMASK); @@ -33,6 +34,7 @@ AUI_ERRCODE aui_SDL::InitCommon(BOOL useExclusiveMode) SDL_EventState(SDL_ENABLE, SDL_QUITMASK); SDL_EnableUNICODE(1); +#endif // SKIP_SDL2_EVENT_ISSUES return AUI_ERRCODE_OK; } diff --git a/ctp2_code/ui/aui_sdl/aui_sdl.h b/ctp2_code/ui/aui_sdl/aui_sdl.h index f2173c354..812a25eb4 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdl.h +++ b/ctp2_code/ui/aui_sdl/aui_sdl.h @@ -9,7 +9,7 @@ #if defined(__AUI_USE_SDL__) -#include +#include class aui_SDL { diff --git a/ctp2_code/ui/aui_sdl/aui_sdlblitter.cpp b/ctp2_code/ui/aui_sdl/aui_sdlblitter.cpp index 09ce1be74..94a3901b2 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlblitter.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlblitter.cpp @@ -4,8 +4,8 @@ #include "aui_sdlsurface.h" #include "aui_sdlblitter.h" -#include -#include +#include +#include #ifndef DD_OK #define DD_OK 0 diff --git a/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp b/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp index 9629202cf..03053ba20 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp @@ -3,7 +3,7 @@ #if defined(__AUI_USE_SDL__) -#include +#include #include "aui_sdlkeyboard.h" #include "aui_ui.h" #include "c3ui.h" @@ -149,7 +149,7 @@ void aui_SDLKeyboard::convertSDLKeyboardEvent(SDL_KeyboardEvent &sdlevent, (sdlevent.state & SDL_PRESSED) ? TRUE : FALSE, sdlevent.keysym.sym, (sdlevent.keysym.sym>' ' && sdlevent.keysym.sym<127)?sdlevent.keysym.sym:' ');*/ } -uint32 aui_SDLKeyboard::convertSDLKey(SDL_keysym keysym) +uint32 aui_SDLKeyboard::convertSDLKey(SDL_Keysym keysym) { switch (keysym.sym) { case SDLK_ESCAPE: @@ -169,9 +169,11 @@ uint32 aui_SDLKeyboard::convertSDLKey(SDL_keysym keysym) case SDLK_RIGHT: return AUI_KEYBOARD_KEY_RIGHTARROW; } +#if !defined(SKIP_SDL2_EVENT_ISSUES) if ((keysym.unicode & 0xFF80) == 0) { return (keysym.unicode & 0x7F); } +#endif // SKIP_SDL2_EVENT_ISSUES return AUI_KEYBOARD_KEY_INVALID; } diff --git a/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.h b/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.h index 6b7235161..65508ec3a 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.h @@ -28,7 +28,7 @@ class aui_SDLKeyboard : public aui_Keyboard, public aui_SDLInput { AUI_ERRCODE createSDLKeyboard(); void convertSDLKeyboardEvent(SDL_KeyboardEvent &sdlevent, aui_KeyboardEvent &auievent); - uint32 convertSDLKey(SDL_keysym keysym); + uint32 convertSDLKey(SDL_Keysym keysym); public: virtual AUI_ERRCODE Acquire(); diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp index 6145567b9..467aa0da5 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp @@ -63,9 +63,7 @@ aui_SDLMouse::GetInput(void) SDL_Event od[10]; // check for one of the mouse events int numElements = - SDL_PeepEvents(od, 10, SDL_GETEVENT, - SDL_EVENTMASK(SDL_MOUSEMOTION) | SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN) | - SDL_EVENTMASK(SDL_MOUSEBUTTONUP)); + SDL_PeepEvents(od, 10, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEBUTTONUP); if (0 > numElements) { fprintf(stderr, "Mouse PeepEvents failed: %s\n", SDL_GetError()); return AUI_ERRCODE_GETDEVICEDATAFAILED; @@ -87,6 +85,7 @@ aui_SDLMouse::GetInput(void) break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: +#if !defined(SKIP_SDL2_EVENT_ISSUES) if (od[ev].button.button == SDL_BUTTON_WHEELUP){ HandleMouseWheel((sint16)1); break; @@ -102,6 +101,7 @@ aui_SDLMouse::GetInput(void) } else if (od[ev].button.button == SDL_BUTTON_RIGHT) { m_data.rbutton = od[ev].button.state == SDL_PRESSED; } +#endif // SKIP_SDL2_EVENT_ISSUES break; default: printf("event not handeled: %d\n", od[ev].type); diff --git a/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp b/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp index 6bf130d82..b17691efc 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp @@ -6,7 +6,7 @@ #include "aui_ui.h" #include "aui_uniqueid.h" #include "aui_sdlsurface.h" -#include +#include uint32 aui_SDLSurface::m_SDLSurfaceClassId = aui_UniqueId(); @@ -36,6 +36,7 @@ aui_SDLSurface::aui_SDLSurface( Assert( AUI_SUCCESS(*retval) ); if ( !AUI_SUCCESS(*retval) ) return; +#if !defined(SKIP_SDL2_SCREEN_ISSUES) SDL_PixelFormat* fmt = SDL_GetVideoSurface()->format; if ( !(m_lpdds = lpdds) ) { @@ -67,7 +68,7 @@ aui_SDLSurface::aui_SDLSurface( m_pixelFormat = AUI_SURFACE_PIXELFORMAT_555; //fprintf(stderr, "%s L%d: AUI_SURFACE_PIXELFORMAT_555\n", __FILE__, __LINE__); } - +#endif // SKIP_SDL2_SCREEN_ISSUES m_pitch = m_lpdds->pitch; m_size = m_pitch * m_height; @@ -96,12 +97,14 @@ aui_SDLSurface::~aui_SDLSurface() uint32 aui_SDLSurface::SetChromaKey( uint32 color ) { +#if !defined(SKIP_SDL2_SCREEN_ISSUES) int hr = SDL_SetColorKey(m_lpdds, SDL_SRCCOLORKEY, /*SDL_MapRGB(m_lpdds->format, color>>16, (color>>8)&0xff, color&0xff)*/color); //|SDL_RLEACCEL ? //hr == 0 if succeded! //fprintf(stderr, "%s L%d: SDL_SRCCOLORKEY set to %#X\n", __FILE__, __LINE__, color); if ( hr == 0 ) return aui_Surface::SetChromaKey( color ); //sets aui_Surface.m_chromaKey and returns last value! +#endif //return AUI_ERRCODE_OK; //this is not sensible, should retrun last color key!?! //fprintf(stderr, "%s L%d: SDL_SRCCOLORKEY setting failed!\n", __FILE__, __LINE__); diff --git a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp index f1ec1deee..8e2dd4efe 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp @@ -135,10 +135,12 @@ AUI_ERRCODE aui_SDLUI::CreateNativeScreen( BOOL useExclusiveMode ) assert( AUI_SUCCESS(errcode) ); if ( !AUI_SUCCESS(errcode) ) return errcode; +#if !defined(SKIP_SDL2_SCREEN_ISSUES) m_lpdds = SDL_SetVideoMode(m_width, m_height, m_bpp, g_SDL_flags); // mod by lynx |SDL_FULLSCREEN); if (!m_lpdds) { c3errors_FatalDialog("aui_SDLUI", SDL_GetError()); } +#endif // SKIP_SDL2_SCREEN_ISSUES m_primary = new aui_SDLSurface( &errcode, diff --git a/ctp2_code/ui/interface/chatbox.cpp b/ctp2_code/ui/interface/chatbox.cpp index a9d3255d6..04fecfaf2 100644 --- a/ctp2_code/ui/interface/chatbox.cpp +++ b/ctp2_code/ui/interface/chatbox.cpp @@ -73,7 +73,7 @@ #if defined(__AUI_USE_SDL__) -#include "SDL.h" +#include "SDL2/SDL.h" #include "civ3_main.h" #endif diff --git a/ctp2_code/ui/netshell/netfunc.cpp b/ctp2_code/ui/netshell/netfunc.cpp index 1878a0349..e88e27839 100644 --- a/ctp2_code/ui/netshell/netfunc.cpp +++ b/ctp2_code/ui/netshell/netfunc.cpp @@ -47,8 +47,8 @@ #endif #ifdef USE_SDL -#include -#include +#include +#include #endif #ifdef WIN32 @@ -2460,7 +2460,7 @@ NETFunc::STATUS NETFunc::SetTransport(Transport *t) { } cancelDial = 0; #ifdef USE_SDL - threadHandle = SDL_CreateThread(ConnectThread, (void *)transport); + threadHandle = SDL_CreateThread(ConnectThread, "Connect-thread", (void *)transport); #else threadHandle = CreateThread(0, 0, ConnectThread, (void *)transport, 0, &threadId); #endif @@ -2903,7 +2903,7 @@ NETFunc::STATUS NETFunc::Connect(dp_t *d, PlayerStats *stats, bool h) { return ERR; #ifdef USE_SDL - threadHandle = SDL_CreateThread(ReConnectThread, (void *) &reconnected); + threadHandle = SDL_CreateThread(ReConnectThread, "Reconnect-thread", (void *) &reconnected); #else threadHandle = CreateThread(0, 0, ReConnectThread, (void *)&reconnected, 0, &threadId); #endif diff --git a/ctp2_code/ui/netshell/netfunc.h b/ctp2_code/ui/netshell/netfunc.h index d8bbac8d6..bded23b50 100644 --- a/ctp2_code/ui/netshell/netfunc.h +++ b/ctp2_code/ui/netshell/netfunc.h @@ -51,8 +51,8 @@ #include #ifdef USE_SDL -#include -#include +#include +#include #endif #if defined(WIN32) From 87fb05cf57f317fb0eee1b11e6b61d20babb64c7 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Sat, 4 Apr 2020 17:12:58 +0200 Subject: [PATCH 10/29] Use SDL2 to render (fix SKIP_SDL2_SCREEN_ISSUES) The minimum amount of changes have been implemented to get the rendering working. SDL2 functionality is not used optimally and most likely can the performance be improved. --- configure.ac | 2 +- ctp2_code/ctp/civ3_main.cpp | 24 +++---- ctp2_code/ctp/debugtools/debugmemory.cpp | 15 ++++- ctp2_code/ctp/debugtools/debugmemory.h | 17 ++++- ctp2_code/ctp/display.cpp | 83 +++++++----------------- ctp2_code/ui/aui_common/aui_image.cpp | 12 ++-- ctp2_code/ui/aui_common/aui_surface.cpp | 20 ++++-- ctp2_code/ui/aui_common/aui_surface.h | 4 +- ctp2_code/ui/aui_common/aui_ui.cpp | 23 +------ ctp2_code/ui/aui_common/aui_ui.h | 4 ++ ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp | 55 +++++++++------- ctp2_code/ui/aui_sdl/aui_sdlsurface.h | 5 ++ ctp2_code/ui/aui_sdl/aui_sdlui.cpp | 59 +++++++++-------- ctp2_code/ui/aui_sdl/aui_sdlui.h | 6 +- 14 files changed, 171 insertions(+), 158 deletions(-) diff --git a/configure.ac b/configure.ac index 0e401afc3..a5fa972f4 100644 --- a/configure.ac +++ b/configure.ac @@ -60,8 +60,8 @@ AC_PATH_X AC_PATH_XTRA AC_DEFINE(USE_SDL,1,[Use the SDL-library]) AC_DEFINE(SKIP_SDL2_CDROM_ISSUES,1,[Skip SDL2 CD-rom code]) -AC_DEFINE(SKIP_SDL2_SCREEN_ISSUES,1,[Skip SDL2 screen code]) AC_DEFINE(SKIP_SDL2_EVENT_ISSUES,1,[Skip SDL2 event code]) +AC_DEFINE(SKIP_SDL2_DEBUG_MEMORY_ISSUE,1,[Skip SDL2 screen code]) AC_WORDS_BIGENDIAN AC_OS_DEFINES diff --git a/ctp2_code/ctp/civ3_main.cpp b/ctp2_code/ctp/civ3_main.cpp index 86af7dc70..ed82fb9dc 100644 --- a/ctp2_code/ctp/civ3_main.cpp +++ b/ctp2_code/ctp/civ3_main.cpp @@ -276,11 +276,7 @@ BOOL g_runInBackground = FALSE; BOOL g_runSpriteEditor = FALSE; BOOL g_eventLog = FALSE; -#if 0 -uint32 g_SDL_flags = SDL_DOUBLEBUF | SDL_HWSURFACE; -#else -uint32 g_SDL_flags = 0; //See ctp2_code/ui/aui_common/aui_ui.cpp //SEB Pandora -#endif +uint32 g_SDL_flags = 0; BOOL g_use_profile_process = FALSE; @@ -1168,15 +1164,15 @@ void ParseCommandLine(PSTR szCmdLine) g_runSpriteEditor = (NULL != strstr(szCmdLine, "runspriteeditor")); #if defined(__AUI_USE_SDL__) - #if !defined(SKIP_SDL2_SCREEN_ISSUES) - if (strstr(szCmdLine, "fullscreen")) - g_SDL_flags = g_SDL_flags|SDL_FULLSCREEN; - if (strstr(szCmdLine, "hwsurface")) - g_SDL_flags = g_SDL_flags|SDL_HWSURFACE; - else g_SDL_flags = g_SDL_flags|SDL_SWSURFACE; - if (strstr(szCmdLine, "openglblit")) - g_SDL_flags = g_SDL_flags|SDL_OPENGLBLIT; - #endif // SKIP_SDL2_SCREEN_ISSUES + if (strstr(szCmdLine, "fullscreen")) { + g_SDL_flags = g_SDL_flags | SDL_WINDOW_FULLSCREEN; + } + if (strstr(szCmdLine, "hwsurface")) { + printf("SDL2 does not support hwsurface option"); + } + if (strstr(szCmdLine, "openglblit")) { + printf("SDL2 uses OpenGL automatically"); + } #endif g_eventLog = (NULL != strstr(szCmdLine, "eventlog")); diff --git a/ctp2_code/ctp/debugtools/debugmemory.cpp b/ctp2_code/ctp/debugtools/debugmemory.cpp index a599aa2ea..6adbe0ad3 100644 --- a/ctp2_code/ctp/debugtools/debugmemory.cpp +++ b/ctp2_code/ctp/debugtools/debugmemory.cpp @@ -58,6 +58,17 @@ #define fopen(a, b) ci_fopen(a, b) #endif +#if defined(SKIP_SDL2_DEBUG_MEMORY_ISSUE) + +void DebugMemory_LeaksShow (int turn_count) {} +void DebugMemory_LeaksClear(void) {} +size_t DebugMemory_GetTotalFromEXE(void) { return 0; } +size_t DebugMemory_GetTotalFromDLL(void) { return 0; } +void DebugMemory_Open (void) {} +void DebugMemory_Close (void) {} + +#else + struct DebugMemory; struct MemoryHeapDescriptor; struct AllocHeader; @@ -1351,4 +1362,6 @@ void operator delete (void *mem) #endif // MEMORY_LOGGED -#endif // _DEBUG +#endif // SKIP_SDL2_DEBUG_MEMORY_ISSUE + +#endif // _DEBUG \ No newline at end of file diff --git a/ctp2_code/ctp/debugtools/debugmemory.h b/ctp2_code/ctp/debugtools/debugmemory.h index f2ebc20ff..0942514c3 100644 --- a/ctp2_code/ctp/debugtools/debugmemory.h +++ b/ctp2_code/ctp/debugtools/debugmemory.h @@ -47,6 +47,17 @@ extern "C" { #endif +#if defined(SKIP_SDL2_DEBUG_MEMORY_ISSUE) + +void DebugMemory_LeaksShow (int turn_count); +void DebugMemory_LeaksClear(void); +size_t DebugMemory_GetTotalFromEXE(void); +size_t DebugMemory_GetTotalFromDLL(void); +void DebugMemory_Open (void); +void DebugMemory_Close (void); + +#else + #ifndef _DEBUG_MEMORY #define MEMORY_FAST #else @@ -142,10 +153,12 @@ void DebugMemoryHeap_GuardedClose (const char *file, int line, MemoryHeap h #endif +#endif // SKIP_SDL2_DEBUG_MEMORY_ISSUE + #ifdef __cplusplus } #endif -#endif // __DEBUGMEMORY_H - #endif // _DEBUG + +#endif // __DEBUGMEMORY_H diff --git a/ctp2_code/ctp/display.cpp b/ctp2_code/ctp/display.cpp index c4c982658..10b389d2a 100644 --- a/ctp2_code/ctp/display.cpp +++ b/ctp2_code/ctp/display.cpp @@ -29,8 +29,6 @@ extern sint32 g_ScreenHeight; extern BOOL g_exclusiveMode; extern BOOL g_createDirectDrawOnSecondary; -extern BOOL g_SDL_flags; - #include "profileDB.h" extern ProfileDB *g_theProfileDB; @@ -138,62 +136,32 @@ void display_EnumerateDisplayModes(void) g_displayModes = new PointerList; #else - SDL_PixelFormat fmt = { 0 }; - fmt.BitsPerPixel = 16; -#if !defined(SKIP_SDL2_SCREEN_ISSUES) - SDL_Rect **modes = SDL_ListModes(/*&fmt*/NULL, SDL_FULLSCREEN); -#else // SKIP_SDL2_SCREEN_ISSUES - SDL_Rect **modes = 0; -#endif // SKIP_SDL2_SCREEN_ISSUES - g_displayModes = new PointerList; - if (0 == modes) { - return; - } else if ((SDL_Rect **) -1 == modes) { - // Fallback if SDL reports us to support anything, - // we'll pick 800 x 600 and 1024 x 768 -#if !defined(SKIP_SDL2_SCREEN_ISSUES) - const SDL_VideoInfo *info = SDL_GetVideoInfo(); - if (0 == info) { - return; - } - if (0 == info->vfmt) { - return; - } - if (16 < info->vfmt->BitsPerPixel) { - return; - } - CTPDisplayMode *mode; - mode = new CTPDisplayMode; - if (!mode) - return; - mode->width = 800; - mode->height = 600; - g_displayModes->AddTail(mode); - mode = new CTPDisplayMode; - if (!mode) - return; - mode->width = 1024; - mode->height = 768; - g_displayModes->AddTail(mode); -#endif // SKIP_SDL2_SCREEN_ISSUES - } else { - for (int i = 0; modes[i]; i++) { - // We might get modes multiple times for each bpp - // supported. Thus, check if we got it already. - if (!display_IsLegalResolution(modes[i]->w, - modes[i]->h) - && (modes[i]->h>=600)) { - CTPDisplayMode *mode = new CTPDisplayMode; - if (!mode) - return; - mode->width = modes[i]->w; - mode->height = modes[i]->h; - g_displayModes->AddTail(mode); - } - } - } + static const int PRIMARY_DISPLAY = 0; + int numberOfDisplayModes = SDL_GetNumDisplayModes(PRIMARY_DISPLAY); + if (numberOfDisplayModes < 1) { + c3errors_FatalDialog("CivApp", "Unable to find display-modes:\n%s\n", SDL_GetError()); + return; + } + + SDL_DisplayMode displayMode; + for (int i = 0; i < numberOfDisplayModes; i++) { + const int rc = SDL_GetDisplayMode(PRIMARY_DISPLAY, i, &displayMode); + if (rc < 0) { + c3errors_FatalDialog("CivApp", "Unable to get display-mode:\n%s\n", SDL_GetError()); + return; + } + if (!display_IsLegalResolution(displayMode.w, displayMode.h) && (displayMode.h >= 600)) { + CTPDisplayMode *mode = new CTPDisplayMode; + if (!mode) { + return; + } + mode->width = displayMode.w; + mode->height = displayMode.h; + g_displayModes->AddTail(mode); + } + } #endif #ifdef __AUI_USE_DIRECTX__ @@ -326,9 +294,6 @@ int display_Initialize(HINSTANCE hInstance, int iCmdShow) #endif display_EnumerateDisplayModes(); - - - BOOL foundRes = FALSE; if (g_theProfileDB->IsTryWindowsResolution()) { diff --git a/ctp2_code/ui/aui_common/aui_image.cpp b/ctp2_code/ui/aui_common/aui_image.cpp index 9e2f6e452..98eb255da 100644 --- a/ctp2_code/ui/aui_common/aui_image.cpp +++ b/ctp2_code/ui/aui_common/aui_image.cpp @@ -37,6 +37,10 @@ #include "aui_pixel.h" #include "aui_ui.h" +#if defined(__AUI_USE_SDL__) + #include +#endif + aui_Image::aui_Image( AUI_ERRCODE *retval, const MBCHAR * filename ) @@ -324,10 +328,10 @@ AUI_ERRCODE aui_BmpImageFormat::Load(MBCHAR const * filename, aui_Image *image ) if (bmp->format->Gmask >> bmp->format->Gshift == 0x1F) fprintf(stderr, "%s L%d: 555 image!\n", __FILE__, __LINE__); if (NULL == surf) { -#if !defined(SKIP_SDL2_SCREEN_ISSUES) - surf = SDL_DisplayFormat(bmp); -#endif // SKIP_SDL2_SCREEN_ISSUES - } + SDL_PixelFormat *format = SDL_AllocFormat(aui_SDLSurface::TransformSurfacePixelFormatToSDL(g_ui->PixelFormat())); + surf = SDL_ConvertSurface(bmp, format, 0); + SDL_FreeFormat(format); + } SDL_FreeSurface(bmp); if (NULL == surf) return AUI_ERRCODE_LOADFAILED; diff --git a/ctp2_code/ui/aui_common/aui_surface.cpp b/ctp2_code/ui/aui_common/aui_surface.cpp index 1c00b5b69..b3d4bd836 100644 --- a/ctp2_code/ui/aui_common/aui_surface.cpp +++ b/ctp2_code/ui/aui_common/aui_surface.cpp @@ -25,7 +25,7 @@ // Modifications from the original Activision code: // // - Corrected a reported memory leak. -// - Added back buffering capability. (1-Jan-2010 Martin G�hmann) +// - Added back buffering capability. (1-Jan-2010 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -109,6 +109,21 @@ aui_Surface::aui_Surface( } } +AUI_SURFACE_PIXELFORMAT aui_Surface::TransformBppToSurfacePixelFormat(int bpp) +{ + switch (bpp) { + case 8: + return AUI_SURFACE_PIXELFORMAT_332; + case 16: + return g_is565Format ? AUI_SURFACE_PIXELFORMAT_565 : AUI_SURFACE_PIXELFORMAT_555; + case 24: + case 32: + return AUI_SURFACE_PIXELFORMAT_888; + default: + return AUI_SURFACE_PIXELFORMAT_UNKNOWN; + } +} + AUI_ERRCODE aui_Surface::InitCommon( sint32 width, sint32 height, sint32 bpp, BOOL isPrimary ) { m_pixelFormat = AUI_SURFACE_PIXELFORMAT_UNKNOWN, @@ -145,9 +160,6 @@ AUI_ERRCODE aui_Surface::InitCommon( sint32 width, sint32 height, sint32 bpp, BO #endif } - - - if ( bpp == 16 ) if (g_is565Format) { m_pixelFormat = AUI_SURFACE_PIXELFORMAT_565; diff --git a/ctp2_code/ui/aui_common/aui_surface.h b/ctp2_code/ui/aui_common/aui_surface.h index 574d215f0..35cd71d51 100644 --- a/ctp2_code/ui/aui_common/aui_surface.h +++ b/ctp2_code/ui/aui_common/aui_surface.h @@ -24,7 +24,7 @@ // Modifications from the original Activision code: // // - Corrected a reported memory leak. -// - Added back buffering capability. (1-Jan-2010 Martin Gühmann) +// - Added back buffering capability. (1-Jan-2010 Martin G�hmann) // //---------------------------------------------------------------------------- #if defined(HAVE_PRAGMA_ONCE) @@ -88,6 +88,8 @@ class aui_Surface : public aui_Base AUI_ERRCODE InitCommon( sint32 width, sint32 height, sint32 bpp, BOOL isPrimary ); public: + static AUI_SURFACE_PIXELFORMAT TransformBppToSurfacePixelFormat(int bpp); + virtual BOOL IsThisA( uint32 classId ) { return classId == m_surfaceClassId; diff --git a/ctp2_code/ui/aui_common/aui_ui.cpp b/ctp2_code/ui/aui_common/aui_ui.cpp index 2bdafa6c0..d539ea7a8 100644 --- a/ctp2_code/ui/aui_common/aui_ui.cpp +++ b/ctp2_code/ui/aui_common/aui_ui.cpp @@ -1104,28 +1104,7 @@ AUI_ERRCODE aui_UI::Draw( void ) ShowSelectedRegion( m_editRegion ); } #ifdef __AUI_USE_SDL__ - // refresh screen -#if !defined(SKIP_SDL2_SCREEN_ISSUES) - SDL_Surface * screen = SDL_GetVideoSurface(); - /*if(m_dirtyRectInfoList->L()) { - ListPos position = m_dirtyRectInfoList->GetHeadPosition(); - for ( sint32 i = m_dirtyRectInfoList->L(); i; i-- ) { - DirtyRectInfo *dri = m_dirtyRectInfoList->GetNext( position ); - sint32 dX = dri->rect.left + dri->window->X(); - sint32 dY = dri->rect.top + dri->window->Y(); - sint32 dW = dri->rect.right - dri->rect.left; - sint32 dH = dri->rect.bottom - dri->rect.top; - if(dX<0) dX = 0; if(dX>=screen->w) dX = screen->w-1; - if(dY<0) dY = 0; if(dY>=screen->h) dY = screen->h-1; - if(dX+dW>screen->w) dW = screen->w-dX; - if(dY+dH>screen->h) dH = screen->h-dY; - if(dW>0 && dH>0) { - SDL_UpdateRect(screen, dX, dY, dW, dH); - } - } - }*/ - SDL_Flip(screen); -#endif // SKIP_SDL2_SCREEN_ISSUES + SDLDrawScreen(); #endif errcode = m_mouse->Resume(); Assert( errcode == AUI_ERRCODE_OK ); diff --git a/ctp2_code/ui/aui_common/aui_ui.h b/ctp2_code/ui/aui_common/aui_ui.h index e2bfbd9e5..44b31e10c 100644 --- a/ctp2_code/ui/aui_common/aui_ui.h +++ b/ctp2_code/ui/aui_common/aui_ui.h @@ -410,6 +410,10 @@ class aui_UI : public aui_Region virtual AUI_ERRCODE ClipAndConsolidate( void ); +#ifdef __AUI_USE_SDL__ + virtual AUI_ERRCODE SDLDrawScreen( void ) {} +#endif + AUI_ERRCODE InsertDirtyRectInfo( RECT *rect, aui_Window *window ); void FlushDirtyRectInfoList( void ); diff --git a/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp b/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp index b17691efc..51954f120 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp @@ -36,11 +36,9 @@ aui_SDLSurface::aui_SDLSurface( Assert( AUI_SUCCESS(*retval) ); if ( !AUI_SUCCESS(*retval) ) return; -#if !defined(SKIP_SDL2_SCREEN_ISSUES) - SDL_PixelFormat* fmt = SDL_GetVideoSurface()->format; if ( !(m_lpdds = lpdds) ) { - m_lpdds = (isPrimary)?SDL_GetVideoSurface():SDL_CreateRGBSurface(0, width, height, fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask); + m_lpdds = CreateSDLSurface(width, height, bpp); if ( m_lpdds == NULL ) { *retval = AUI_ERRCODE_MEMALLOCFAILED; @@ -49,26 +47,14 @@ aui_SDLSurface::aui_SDLSurface( m_allocated = TRUE; // clear it with black if (SDL_FillRect(m_lpdds, NULL, 0) < 0) { - fprintf(stderr, "aui_Surface: Failed to erase new surface: %s\n", - SDL_GetError()); + fprintf(stderr, "aui_Surface: Failed to erase new surface: %s\n", SDL_GetError()); } } - else - { + else { m_allocated = takeOwnership; - } + } - //just checking (fmt->Gmask >> fmt->Gshift == 0x3F) should be enough - //but save is save... - if ((fmt->Rmask >> fmt->Rshift == 0x1F) && (fmt->Gmask >> fmt->Gshift == 0x3F) && (fmt->Bmask >> fmt->Bshift == 0x1F)) { - m_pixelFormat = AUI_SURFACE_PIXELFORMAT_565; - //fprintf(stderr, "%s L%d: AUI_SURFACE_PIXELFORMAT_565\n", __FILE__, __LINE__); - } - if ((fmt->Rmask >> fmt->Rshift == 0x1F) && (fmt->Gmask >> fmt->Gshift == 0x1F) && (fmt->Bmask >> fmt->Bshift == 0x1F)) { - m_pixelFormat = AUI_SURFACE_PIXELFORMAT_555; - //fprintf(stderr, "%s L%d: AUI_SURFACE_PIXELFORMAT_555\n", __FILE__, __LINE__); - } -#endif // SKIP_SDL2_SCREEN_ISSUES + m_buffer = (uint8*) m_lpdds->pixels; m_pitch = m_lpdds->pitch; m_size = m_pitch * m_height; @@ -95,16 +81,41 @@ aui_SDLSurface::~aui_SDLSurface() SDL_DestroyMutex(m_bltMutex); } +uint32 aui_SDLSurface::TransformSurfacePixelFormatToSDL(const AUI_SURFACE_PIXELFORMAT pixelFormat) { + switch (pixelFormat) { + case AUI_SURFACE_PIXELFORMAT_332: + return SDL_PIXELFORMAT_RGB332; + case AUI_SURFACE_PIXELFORMAT_565: + return SDL_PIXELFORMAT_RGB565; + case AUI_SURFACE_PIXELFORMAT_555: + return SDL_PIXELFORMAT_RGB555; + case AUI_SURFACE_PIXELFORMAT_888: + return SDL_PIXELFORMAT_RGB888; + default: + return SDL_PIXELFORMAT_UNKNOWN; + } +} + +SDL_Surface* aui_SDLSurface::CreateSDLSurface(const int width, const int height, const int bpp) +{ + const AUI_SURFACE_PIXELFORMAT pixelFormat = TransformBppToSurfacePixelFormat(bpp); + + int sdlBpp; + uint32 rmask; + uint32 gmask; + uint32 bmask; + uint32 amask; + SDL_PixelFormatEnumToMasks(TransformSurfacePixelFormatToSDL(pixelFormat), &sdlBpp, &rmask, &gmask, &bmask, &amask); + return SDL_CreateRGBSurface(0, width, height, sdlBpp, rmask, gmask, bmask, amask); +} uint32 aui_SDLSurface::SetChromaKey( uint32 color ) { -#if !defined(SKIP_SDL2_SCREEN_ISSUES) - int hr = SDL_SetColorKey(m_lpdds, SDL_SRCCOLORKEY, /*SDL_MapRGB(m_lpdds->format, color>>16, (color>>8)&0xff, color&0xff)*/color); //|SDL_RLEACCEL ? + int hr = SDL_SetColorKey(m_lpdds, SDL_TRUE, /*SDL_MapRGB(m_lpdds->format, color>>16, (color>>8)&0xff, color&0xff)*/color); //|SDL_RLEACCEL ? //hr == 0 if succeded! //fprintf(stderr, "%s L%d: SDL_SRCCOLORKEY set to %#X\n", __FILE__, __LINE__, color); if ( hr == 0 ) return aui_Surface::SetChromaKey( color ); //sets aui_Surface.m_chromaKey and returns last value! -#endif //return AUI_ERRCODE_OK; //this is not sensible, should retrun last color key!?! //fprintf(stderr, "%s L%d: SDL_SRCCOLORKEY setting failed!\n", __FILE__, __LINE__); diff --git a/ctp2_code/ui/aui_sdl/aui_sdlsurface.h b/ctp2_code/ui/aui_sdl/aui_sdlsurface.h index 4a7b49d7d..1bf3eeb1e 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlsurface.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlsurface.h @@ -30,6 +30,8 @@ class aui_SDLSurface : public aui_Surface, public aui_SDL { AUI_ERRCODE InitCommon( void ); public: + static uint32 TransformSurfacePixelFormatToSDL(const AUI_SURFACE_PIXELFORMAT pixelFormat); + virtual BOOL IsThisA( uint32 classId ) { return ((classId == m_SDLSurfaceClassId) || aui_Surface::IsThisA( classId ) @@ -56,6 +58,9 @@ class aui_SDLSurface : public aui_Surface, public aui_SDL { protected: SDL_Surface* m_lpdds; + +private: + SDL_Surface* CreateSDLSurface(const int width, const int height, const int bpp); }; typedef aui_SDLSurface aui_NativeSurface; diff --git a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp index 8e2dd4efe..aa4a9ed8c 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp @@ -53,7 +53,8 @@ extern sint32 g_ScreenWidth; extern sint32 g_ScreenHeight; extern DisplayDevice g_displayDevice; -extern BOOL g_SDL_flags; +extern uint32 g_SDL_flags; //See ctp2_code/ctp/civ3_main.cpp +extern sint32 g_is565Format; aui_SDLUI::aui_SDLUI ( @@ -68,7 +69,9 @@ aui_SDLUI::aui_SDLUI ) : aui_UI (), aui_SDL (), - m_X11Display (0) + m_X11Display (0), + m_SDLRenderer (0), + m_SDLTexture (0) { *retval = aui_Region::InitCommon( 0, 0, 0, width, height ); @@ -122,7 +125,6 @@ AUI_ERRCODE aui_SDLUI::DestroyNativeScreen(void) { delete m_primary; m_primary = NULL; - m_lpdds = NULL; } return AUI_ERRCODE_OK; @@ -135,32 +137,29 @@ AUI_ERRCODE aui_SDLUI::CreateNativeScreen( BOOL useExclusiveMode ) assert( AUI_SUCCESS(errcode) ); if ( !AUI_SUCCESS(errcode) ) return errcode; -#if !defined(SKIP_SDL2_SCREEN_ISSUES) - m_lpdds = SDL_SetVideoMode(m_width, m_height, m_bpp, g_SDL_flags); // mod by lynx |SDL_FULLSCREEN); - if (!m_lpdds) { - c3errors_FatalDialog("aui_SDLUI", SDL_GetError()); + m_pixelFormat = aui_Surface::TransformBppToSurfacePixelFormat(m_bpp); + SDL_Window *sdlWindow = SDL_CreateWindow("Call To Power 2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + m_width, m_height, g_SDL_flags); + if (!sdlWindow) { + c3errors_FatalDialog("aui_SDLUI", "SDL window creation failed:\n%s\n", SDL_GetError()); } -#endif // SKIP_SDL2_SCREEN_ISSUES - - m_primary = new aui_SDLSurface( - &errcode, - m_width, - m_height, - m_bpp, - m_lpdds, - TRUE ); + m_SDLRenderer = SDL_CreateRenderer(sdlWindow, -1, 0); + if (!m_SDLRenderer) { + c3errors_FatalDialog("aui_SDLUI", "SDL renderer creation failed:\n%s\n", SDL_GetError()); + } + m_SDLTexture = SDL_CreateTexture(m_SDLRenderer, aui_SDLSurface::TransformSurfacePixelFormatToSDL(m_pixelFormat), + SDL_TEXTUREACCESS_STREAMING, m_width, m_height); + if (!m_SDLTexture) { + c3errors_FatalDialog("aui_SDLUI", "SDL texture creation failed:\n%s\n", SDL_GetError()); + } + + m_primary = new aui_SDLSurface(&errcode, m_width, m_height, m_bpp, NULL, TRUE); Assert( AUI_NEWOK(m_primary,errcode) ); assert( AUI_NEWOK(m_primary,errcode) ); if ( !AUI_NEWOK(m_primary,errcode) ) return AUI_ERRCODE_MEMALLOCFAILED; if(!m_secondary) { - m_secondary = new aui_SDLSurface( - &errcode, - m_width, - m_height, - m_bpp, - NULL, - FALSE ); + m_secondary = new aui_SDLSurface(&errcode, m_width, m_height, m_bpp, NULL, FALSE); Assert( AUI_NEWOK(m_primary,errcode) ); assert( AUI_NEWOK(m_primary,errcode) ); if ( !AUI_NEWOK(m_primary,errcode) ) return AUI_ERRCODE_MEMALLOCFAILED; @@ -181,10 +180,6 @@ aui_SDLUI::getDisplay() aui_SDLUI::~aui_SDLUI( void ) { - if ( m_lpdds ) { - // m_lpdds is deleted by SDL_Quit() - m_lpdds = NULL; - } #ifdef HAVE_X11 if (m_X11Display) { XCloseDisplay(m_X11Display); @@ -335,4 +330,14 @@ AUI_ERRCODE aui_SDLUI::AltTabIn( void ) return FlushDirtyList(); } +AUI_ERRCODE aui_SDLUI::SDLDrawScreen( void ) { + Assert(m_primary); + Assert(m_SDLTexture); + Assert(m_SDLRenderer); + SDL_UpdateTexture(m_SDLTexture, NULL, m_primary->Buffer(), m_primary->Pitch()); + SDL_RenderClear(m_SDLRenderer); + SDL_RenderCopy(m_SDLRenderer, m_SDLTexture, NULL, NULL); + SDL_RenderPresent(m_SDLRenderer); +} + #endif // __AUI_USE_SDL__ diff --git a/ctp2_code/ui/aui_sdl/aui_sdlui.h b/ctp2_code/ui/aui_sdl/aui_sdlui.h index 210c17dbc..df2f14397 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlui.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlui.h @@ -77,10 +77,14 @@ class aui_SDLUI : public aui_UI, public aui_SDL #endif protected: + virtual AUI_ERRCODE SDLDrawScreen( void ); + #if defined(HAVE_X11) Display * m_X11Display; #endif - SDL_Surface *m_lpdds; + SDL_Surface *m_SDLSurface; + SDL_Renderer *m_SDLRenderer; + SDL_Texture *m_SDLTexture; }; typedef aui_SDLUI aui_NativeUI; From 1b5e448c0f734f73df745b7c0590fda241c49b76 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Sun, 5 Apr 2020 14:35:55 +0200 Subject: [PATCH 11/29] Fix crash for -Og &archive was optimized away which caused a segmentation fault (dereference NULL-pointer) --- ctp2_code/ctp/civapp.cpp | 32 +++--- ctp2_code/ctp/civapp.h | 4 +- ctp2_code/gs/fileio/GameFile.cpp | 22 ++-- ctp2_code/gs/utility/gameinit.cpp | 146 +++++++++++++-------------- ctp2_code/gs/utility/gameinit.h | 2 +- ctp2_code/robot/utility/RoboInit.h | 2 +- ctp2_code/robot/utility/roboinit.cpp | 2 +- 7 files changed, 105 insertions(+), 105 deletions(-) diff --git a/ctp2_code/ctp/civapp.cpp b/ctp2_code/ctp/civapp.cpp index c823a4ef5..db93999ab 100644 --- a/ctp2_code/ctp/civapp.cpp +++ b/ctp2_code/ctp/civapp.cpp @@ -1636,7 +1636,7 @@ sint32 CivApp::InitializeGameUI(void) return 0; } -sint32 CivApp::InitializeGame(CivArchive &archive) +sint32 CivApp::InitializeGame(CivArchive *archive) { ProgressWindow::BeginProgress( g_theProgressWindow, @@ -1721,9 +1721,9 @@ sint32 CivApp::InitializeGame(CivArchive &archive) g_theProgressWindow->StartCountingTo( 610 ); - if(g_isScenario && (&archive != NULL && + if(g_isScenario && archive && (g_startInfoType != STARTINFOTYPE_NONE || - g_saveFileVersion < gamefile_CurrentVersion()))) { + g_saveFileVersion < gamefile_CurrentVersion())) { for(sint32 i = 0; i < k_MAX_PLAYERS; i++) { if(g_player[i]) { @@ -1784,7 +1784,7 @@ sint32 CivApp::InitializeGame(CivArchive &archive) GraphicsOptions::Initialize(); SPLASH_STRING("Initializing Tile Engine..."); - tile_Initialize(&archive != NULL); + tile_Initialize(archive != NULL); g_theProgressWindow->StartCountingTo( 660 ); @@ -1814,7 +1814,7 @@ sint32 CivApp::InitializeGame(CivArchive &archive) if(!g_network.IsActive() && !g_network.IsNetworkLaunch()) { - if ((&archive == NULL) || // launch button + if ((archive == NULL) || // launch button ((g_startInfoType != STARTINFOTYPE_NONE) && g_isScenario) // scenario start ) { @@ -1829,7 +1829,7 @@ sint32 CivApp::InitializeGame(CivArchive &archive) g_theProgressWindow->StartCountingTo( 720 ); if(!g_network.IsActive()) { - if (NULL == &archive || + if (NULL == archive || (g_saveFileVersion >= 42 && (g_isScenario && g_startInfoType != STARTINFOTYPE_NOLOCS))) { @@ -1844,7 +1844,7 @@ sint32 CivApp::InitializeGame(CivArchive &archive) g_theProgressWindow->StartCountingTo( 740 ); - if(g_turn->IsEmail() && NULL != &archive) { + if(g_turn->IsEmail() && archive) { g_selected_item->KeyboardSelectFirstUnit(); if(g_selected_item->GetState() != SELECT_TYPE_LOCAL_ARMY && (g_player[g_selected_item->GetVisiblePlayer()]->m_all_cities->Num() > 0)) { @@ -1867,14 +1867,14 @@ sint32 CivApp::InitializeGame(CivArchive &archive) g_theProgressWindow->StartCountingTo( 760 ); - if ((&archive) && g_turn->IsHotSeat()) + if (archive && g_turn->IsHotSeat()) { // Indicate the resuming player when loading a saved hotseat game g_turn->SendNextPlayerMessage(); } else if (g_selected_item) { - if (!&archive) + if (!archive) { g_selected_item->Refresh(); } @@ -2009,7 +2009,7 @@ sint32 InitializeSpriteEditorUI(void) return 0; } -sint32 CivApp::InitializeSpriteEditor(CivArchive &archive) +sint32 CivApp::InitializeSpriteEditor(CivArchive *archive) { ProgressWindow::BeginProgress( g_theProgressWindow, @@ -2063,7 +2063,7 @@ sint32 CivApp::InitializeSpriteEditor(CivArchive &archive) g_theProgressWindow->StartCountingTo( 720 ); - if ( (&archive != NULL) + if (archive && (g_startInfoType != STARTINFOTYPE_NONE || g_saveFileVersion < gamefile_CurrentVersion() ) @@ -2088,7 +2088,7 @@ sint32 CivApp::InitializeSpriteEditor(CivArchive &archive) g_theProgressWindow->StartCountingTo( 750 ); SPLASH_STRING("Initializing Tile Engine..."); - tile_Initialize(&archive != NULL); + tile_Initialize(archive != NULL); g_theProgressWindow->StartCountingTo( 760 ); @@ -2109,7 +2109,7 @@ sint32 CivApp::InitializeSpriteEditor(CivArchive &archive) g_turn->BeginNewTurn(FALSE); if(!g_network.IsActive()) { - if (NULL == &archive || + if (NULL == archive || (g_saveFileVersion >= 42 && (g_isScenario && g_startInfoType != STARTINFOTYPE_NOLOCS))) { @@ -2124,7 +2124,7 @@ sint32 CivApp::InitializeSpriteEditor(CivArchive &archive) g_theProgressWindow->StartCountingTo( 800 ); - if(g_turn->IsEmail() && NULL != &archive) { + if(g_turn->IsEmail() && archive) { g_selected_item->KeyboardSelectFirstUnit(); if(g_selected_item->GetState() != SELECT_TYPE_LOCAL_ARMY && (g_player[g_selected_item->GetVisiblePlayer()]->m_all_cities->Num() > 0)) { @@ -2585,12 +2585,12 @@ sint32 CivApp::Process(void) sint32 CivApp::StartGame(void) { - return InitializeGame((*(CivArchive *)(NULL))); + return InitializeGame(NULL); } sint32 CivApp::StartSpriteEditor(void) { - return InitializeSpriteEditor((*(CivArchive *)(NULL))); + return InitializeSpriteEditor(NULL); } sint32 CivApp::EndGame(void) diff --git a/ctp2_code/ctp/civapp.h b/ctp2_code/ctp/civapp.h index f8ca0b3ca..4284b4657 100644 --- a/ctp2_code/ctp/civapp.h +++ b/ctp2_code/ctp/civapp.h @@ -85,7 +85,7 @@ class CivApp sint32 InitializeApp(HINSTANCE hInstance, int iCmdShow); bool InitializeAppDB(void); sint32 InitializeAppDB(CivArchive &archive); - sint32 InitializeGame(CivArchive &archive); + sint32 InitializeGame(CivArchive *archive); bool IsGameLoaded(void) const { @@ -138,7 +138,7 @@ class CivApp void CleanupGameUI(void); void InitializeAppUI(void); sint32 InitializeGameUI(void); - sint32 InitializeSpriteEditor(CivArchive &archive); + sint32 InitializeSpriteEditor(CivArchive *archive); void PostLoadSaveGameMapAction(MBCHAR const *); sint32 ProcessAI(); sint32 ProcessNet(const uint32 target_milliseconds, uint32 &used_milliseconds); diff --git a/ctp2_code/gs/fileio/GameFile.cpp b/ctp2_code/gs/fileio/GameFile.cpp index 322e2740c..2c1baecb4 100644 --- a/ctp2_code/gs/fileio/GameFile.cpp +++ b/ctp2_code/gs/fileio/GameFile.cpp @@ -28,17 +28,17 @@ // - Readded Activision patch new magic number 66. // - Fixed autosave directory name for scenarios to match normal directory. // - Fixed the scenario savegame bug (but not for autosave, that still needs to be done) -// - Replaced old civilisation database by new one. (Aug 20th 2005 Martin Gühmann) -// - Made progress bar more fluently. (Aug 22nd 2005 Martin Gühmann) -// - Removed old sprite state databases. (Aug 29th 2005 Martin Gühmann) -// - Removed old difficulty database. (April 29th 2006 Martin Gühmann) -// - Removed old pollution database. (July 15th 2006 Martin Gühmann) -// - Removed old gobal warming database. (July 15th 2006 Martin Gühmann) -// - Removed old concept database. (31-Mar-2007 Martin Gühmann) -// - Removed old const database. (5-Aug-2007 Martin Gühmann) -// - Replaced CIV_INDEX by sint32. (2-Jan-2008 Martin Gühmann) +// - Replaced old civilisation database by new one. (Aug 20th 2005 Martin G�hmann) +// - Made progress bar more fluently. (Aug 22nd 2005 Martin G�hmann) +// - Removed old sprite state databases. (Aug 29th 2005 Martin G�hmann) +// - Removed old difficulty database. (April 29th 2006 Martin G�hmann) +// - Removed old pollution database. (July 15th 2006 Martin G�hmann) +// - Removed old gobal warming database. (July 15th 2006 Martin G�hmann) +// - Removed old concept database. (31-Mar-2007 Martin G�hmann) +// - Removed old const database. (5-Aug-2007 Martin G�hmann) +// - Replaced CIV_INDEX by sint32. (2-Jan-2008 Martin G�hmann) // - Make the Linux version loading and producing Windows compatible -// savegames. (16-Jan-2019 Martin Gühmann) +// savegames. (16-Jan-2019 Martin G�hmann) // //---------------------------------------------------------------------------- @@ -845,7 +845,7 @@ uint32 GameFile::Restore(const MBCHAR *filepath) g_theProgressWindow->StartCountingTo( 1080 ); - g_civApp->InitializeGame(archive); + g_civApp->InitializeGame(&archive); g_theProgressWindow->StartCountingTo( 1090 ); diff --git a/ctp2_code/gs/utility/gameinit.cpp b/ctp2_code/gs/utility/gameinit.cpp index 44d4e90b1..15e7533ed 100644 --- a/ctp2_code/gs/utility/gameinit.cpp +++ b/ctp2_code/gs/utility/gameinit.cpp @@ -29,22 +29,22 @@ // Modifications from the original Activision code: // // - Added player selection for new single player game and scenarios of -// all types, by Martin Gühmann. +// all types, by Martin G�hmann. // - Fixed scenarios that allow players other than player 1 to be played, -// by Martin Gühmann +// by Martin G�hmann // - Added multiplayer to single player game conversion for testing. // - Prevent assigning the same civilisation index twice, while keeping the // human player selection. // - TradePool is fixed on reload if the number of goods in the // savegame differs from the number of goods in the database. -// - June 4th 2005 Martin Gühmann +// - June 4th 2005 Martin G�hmann // - Allowed for nPlayers to be 2 or 3 - JJB 2005/06/28 // - Removed auto-tutorial on low difficulty - JJB 2005/06/28 -// - Removed refferences to the civilisation database. (Aug 20th 2005 Martin Gühmann) -// - Removed unused SpriteStateDB refferences. (Aug 28th 2005 Martin Gühmann) -// - Reused obsolate concept icon database slot for new map icon database. (3-Mar-2007 Martin Gühmann) -// - Removed old concept database. (31-Mar-2007 Martin Gühmann) -// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) +// - Removed refferences to the civilisation database. (Aug 20th 2005 Martin G�hmann) +// - Removed unused SpriteStateDB refferences. (Aug 28th 2005 Martin G�hmann) +// - Reused obsolate concept icon database slot for new map icon database. (3-Mar-2007 Martin G�hmann) +// - Removed old concept database. (31-Mar-2007 Martin G�hmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin G�hmann) // //---------------------------------------------------------------------------- @@ -1443,7 +1443,7 @@ sint32 gameinit_GetCivForSlot(sint32 slot) } -sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) +sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive *archive) { g_debugWindow->SetDebugMask(k_DBG_AI); @@ -1470,8 +1470,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) // Removed the auto-tutorial on low difficulty, since it causes // more problems than it solves - JJB - if (&archive) { - g_rand = new RandomGenerator(archive); + if (archive) { + g_rand = new RandomGenerator(*archive); } else { #ifdef _DEBUG FILE * fin = fopen ("logs" FILE_SEP "dbgseed.txt", "r"); @@ -1512,8 +1512,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) - if(&archive) { - g_theGameSettings = new GameSettings(archive); + if(archive) { + g_theGameSettings = new GameSettings(*archive); } else { g_theGameSettings = new GameSettings(); } @@ -1523,8 +1523,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) bool loadEverything = !g_isScenario || (g_startInfoType == STARTINFOTYPE_NOLOCS); - if (&archive) { - g_theWorld = new World(archive) ; + if (archive) { + g_theWorld = new World(*archive) ; if( (g_isScenario && g_startInfoType != STARTINFOTYPE_NOLOCS)) { @@ -1579,8 +1579,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) Assert(g_theWorld); - if (&archive && loadEverything){ - g_turn = new TurnCount(archive); + if (archive && loadEverything){ + g_turn = new TurnCount(*archive); } else { g_turn = new TurnCount(); if(g_network.IsActive() || g_network.IsNetworkLaunch()) { @@ -1591,8 +1591,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) } } - if (&archive && loadEverything){ - g_selected_item = new SelectedItem(archive); + if (archive && loadEverything){ + g_selected_item = new SelectedItem(*archive); }else { g_selected_item = new SelectedItem(nPlayers); } @@ -1614,23 +1614,23 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) sint16(g_theWorld->GetYHeight()), g_theWorld->IsYwrap()); - if (&archive && loadEverything) - g_theUnitPool = new UnitPool(archive); + if (archive && loadEverything) + g_theUnitPool = new UnitPool(*archive); else g_theUnitPool = new UnitPool(); Assert(g_theUnitPool); - if(&archive && loadEverything) - g_theArmyPool = new ArmyPool(archive); + if(archive && loadEverything) + g_theArmyPool = new ArmyPool(*archive); else g_theArmyPool = new ArmyPool(); Assert(g_theArmyPool); - if(&archive && loadEverything) + if(archive && loadEverything) g_theUnitPool->RebuildQuadTree(); - if(&archive && loadEverything) { - g_theTradePool = new TradePool(archive); + if(archive && loadEverything) { + g_theTradePool = new TradePool(*archive); if(g_numGoods != g_theResourceDB->NumRecords()){ sint32 i; @@ -1648,9 +1648,9 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) g_theTradePool = new TradePool(); // 55 is probably the last save game version for CTP1 - if (&archive && loadEverything && (g_saveFileVersion < 55)) + if (archive && loadEverything && (g_saveFileVersion < 55)) { - g_theTradeOfferPool = new TradeOfferPool(archive); + g_theTradeOfferPool = new TradeOfferPool(*archive); } else { @@ -1658,15 +1658,15 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) } Assert(g_theTradeOfferPool); - if (&archive && loadEverything) - g_thePollution = new Pollution(archive); + if (archive && loadEverything) + g_thePollution = new Pollution(*archive); else g_thePollution = new Pollution(); Assert(g_thePollution); - if (&archive && loadEverything && (g_saveFileVersion < 55)) + if (archive && loadEverything && (g_saveFileVersion < 55)) { - g_theTopTen = new TopTen(archive); + g_theTopTen = new TopTen(*archive); } else { @@ -1676,10 +1676,10 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) SPLASH_STRING("Initializing SLIC Engine..."); - if (&archive) + if (archive) { delete g_slicEngine; - g_slicEngine = new SlicEngine(archive); + g_slicEngine = new SlicEngine(*archive); g_slicEngine->PostSerialize(); } else @@ -1715,15 +1715,15 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) SPLASH_STRING("Initializing Object Pools..."); - if(&archive && loadEverything) - g_theTerrainImprovementPool = new TerrainImprovementPool(archive); + if(archive && loadEverything) + g_theTerrainImprovementPool = new TerrainImprovementPool(*archive); else g_theTerrainImprovementPool = new TerrainImprovementPool(); Assert(g_theTerrainImprovementPool) ; - if (&archive && loadEverything && (g_saveFileVersion < 55)) + if (archive && loadEverything && (g_saveFileVersion < 55)) { - g_theDiplomaticRequestPool = new DiplomaticRequestPool(archive) ; + g_theDiplomaticRequestPool = new DiplomaticRequestPool(*archive) ; } else { @@ -1731,15 +1731,15 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) } Assert(g_theDiplomaticRequestPool) ; - if (&archive && loadEverything) - g_theCivilisationPool = new CivilisationPool(archive) ; + if (archive && loadEverything) + g_theCivilisationPool = new CivilisationPool(*archive) ; else g_theCivilisationPool = new CivilisationPool() ; Assert(g_theCivilisationPool) ; - if (&archive && loadEverything && (g_saveFileVersion < 55)) + if (archive && loadEverything && (g_saveFileVersion < 55)) { - g_theAgreementPool = new AgreementPool(archive) ; + g_theAgreementPool = new AgreementPool(*archive) ; } else { @@ -1748,8 +1748,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) Assert(g_theAgreementPool) ; delete g_theMessagePool; - if (&archive && loadEverything) - g_theMessagePool = new MessagePool(archive) ; + if (archive && loadEverything) + g_theMessagePool = new MessagePool(*archive) ; else g_theMessagePool = new MessagePool() ; Assert(g_theMessagePool) ; @@ -1758,68 +1758,68 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) g_theCriticalMessagesPrefs = new CriticalMessagesPrefs() ; Assert(g_theCriticalMessagesPrefs) ; - if(&archive && loadEverything) - g_theInstallationPool = new InstallationPool(archive); + if(archive && loadEverything) + g_theInstallationPool = new InstallationPool(*archive); else g_theInstallationPool = new InstallationPool(); Assert(g_theInstallationPool) ; g_theInstallationPool->RebuildQuadTree(); - if (&archive && loadEverything && (g_saveFileVersion < 55)) + if (archive && loadEverything && (g_saveFileVersion < 55)) { sint32 wormholeExists; - archive >> wormholeExists; - g_wormhole = (wormholeExists) ? new Wormhole(archive) : NULL; + *archive >> wormholeExists; + g_wormhole = (wormholeExists) ? new Wormhole(*archive) : NULL; } else { g_wormhole = NULL; } - if(&archive && loadEverything) { - g_theWonderTracker = new WonderTracker(archive); + if(archive && loadEverything) { + g_theWonderTracker = new WonderTracker(*archive); } else { g_theWonderTracker = new WonderTracker(); } - if(&archive && loadEverything && (g_saveFileVersion < 55)) + if(archive && loadEverything && (g_saveFileVersion < 55)) { - g_theAchievementTracker = new AchievementTracker(archive); + g_theAchievementTracker = new AchievementTracker(*archive); } else { g_theAchievementTracker = new AchievementTracker(); } - if (&archive) + if (archive) { delete g_exclusions; - g_exclusions = new Exclusions(archive); + g_exclusions = new Exclusions(*archive); } else { // Exclusions not used } - if(&archive && loadEverything) { - g_featTracker = new FeatTracker(archive); + if(archive && loadEverything) { + g_featTracker = new FeatTracker(*archive); } else { g_featTracker = new FeatTracker; } - if(&archive && loadEverything && (g_saveFileVersion < 55)) + if(archive && loadEverything && (g_saveFileVersion < 55)) { - g_theTradeBids = new TradeBids(archive); + g_theTradeBids = new TradeBids(*archive); } else { g_theTradeBids = new TradeBids; } - if(&archive && loadEverything) + if(archive && loadEverything) { - g_eventTracker = new EventTracker(archive); + g_eventTracker = new EventTracker(*archive); } else { @@ -1838,24 +1838,24 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) sint32 numPlayersLoaded = 0; sint32 i, j; - if (&archive) + if (archive) { for (i = 0; i < k_MAX_PLAYERS; i++) { - archive >> playerAlive; + *archive >> playerAlive; if (playerAlive) { - g_player[i] = new Player(archive); + g_player[i] = new Player(*archive); numPlayersLoaded++; } } sint32 num; - archive >> num; + *archive >> num; for (i = 0; i < num; i++) { - g_deadPlayer->AddTail(new Player(archive)); + g_deadPlayer->AddTail(new Player(*archive)); } if (g_isScenario && g_startInfoType != STARTINFOTYPE_NOLOCS) @@ -1969,7 +1969,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) case STARTINFOTYPE_CIVSFIXED: case STARTINFOTYPE_POSITIONSFIXED: -// Added by Martin Gühmann +// Added by Martin G�hmann // No difference between STARTINFOTYPE_CIVSFIXED and STARTINFOTYPE_POSITIONSFIXED { Assert(numPlayersLoaded == 0); @@ -2151,13 +2151,13 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) roboinit_Initalize(archive); CtpAi::Cleanup(); - if (&archive && loadEverything) + if (archive && loadEverything) { g_theWorld->SetAllMoveCost(); g_theWorld->A_star_heuristic->Update(); SPLASH_STRING("Load AI data elements..."); - CtpAi::Load(archive); + CtpAi::Load(*archive); createRobotInterface = false; if(!g_theProfileDB->IsAIOn()) { @@ -2210,7 +2210,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) g_theTradeOfferPool->ReRegisterOffers(); - if (!(&archive)) + if (!archive) { sint32 numPlaced = 0; #ifdef _DEBUG @@ -2277,7 +2277,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) g_director->AddCopyVision(); } - if(&archive) + if(archive) { SPLASH_STRING("Set all move costs..."); g_theWorld->SetAllMoveCost(); @@ -2382,7 +2382,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) } SPLASH_STRING("Reset vision..."); - if(&archive && loadEverything) { + if(archive && loadEverything) { for(i = 0; i < k_MAX_PLAYERS; i++) { if(g_player[i]) { g_player[i]->ResetVision(); @@ -2430,7 +2430,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) g_scenarioUsePlayerNumber = 0; } - if (!(&archive) || g_isScenario) + if (!archive || g_isScenario) { if (g_startHotseatGame || g_startEmailGame) { diff --git a/ctp2_code/gs/utility/gameinit.h b/ctp2_code/gs/utility/gameinit.h index 76fe70038..e5d35c82b 100644 --- a/ctp2_code/gs/utility/gameinit.h +++ b/ctp2_code/gs/utility/gameinit.h @@ -13,7 +13,7 @@ struct HotseatPlayerSetup; #include "MapPoint.h" // MapPoint sint32 gameinit_InitializeGameFiles(void); -sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive); +sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive *archive); void gameinit_CleanupMessages(void); void gameinit_Cleanup(void); sint32 gameinit_ResetForNetwork(); diff --git a/ctp2_code/robot/utility/RoboInit.h b/ctp2_code/robot/utility/RoboInit.h index e2e2613fc..f2d8fe98d 100644 --- a/ctp2_code/robot/utility/RoboInit.h +++ b/ctp2_code/robot/utility/RoboInit.h @@ -6,7 +6,7 @@ #include "civarchive.h" -extern void roboinit_Initalize(CivArchive &a); +extern void roboinit_Initalize(CivArchive *a); extern void roboinit_Cleanup(); #endif diff --git a/ctp2_code/robot/utility/roboinit.cpp b/ctp2_code/robot/utility/roboinit.cpp index 8c95ac036..c5044e6ea 100644 --- a/ctp2_code/robot/utility/roboinit.cpp +++ b/ctp2_code/robot/utility/roboinit.cpp @@ -38,7 +38,7 @@ UnitAstar * g_theUnitAstar = NULL; -void roboinit_Initalize(CivArchive &a) +void roboinit_Initalize(CivArchive *a) { Astar_Init(); From d21cc9f7869163f52414670185b53094af96cc17 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Sun, 5 Apr 2020 14:41:14 +0200 Subject: [PATCH 12/29] Use SDL2 for event-handling (fix SKIP_SDL2_EVENT_ISSUES) --- configure.ac | 3 +- ctp2_code/ctp/civ3_main.cpp | 27 ++++++------ ctp2_code/ctp/ctp2_utils/c3cmdline.cpp | 54 ++++++++++++------------ ctp2_code/gs/fileio/GameFile.cpp | 20 ++++----- ctp2_code/gs/utility/gameinit.cpp | 18 ++++---- ctp2_code/ui/aui_common/aui_movie.cpp | 2 +- ctp2_code/ui/aui_common/aui_surface.h | 2 +- ctp2_code/ui/aui_sdl/aui_sdl.cpp | 35 +++++++++++---- ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp | 8 +--- ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp | 22 +++++----- 10 files changed, 102 insertions(+), 89 deletions(-) diff --git a/configure.ac b/configure.ac index a5fa972f4..d2a00a04c 100644 --- a/configure.ac +++ b/configure.ac @@ -60,8 +60,7 @@ AC_PATH_X AC_PATH_XTRA AC_DEFINE(USE_SDL,1,[Use the SDL-library]) AC_DEFINE(SKIP_SDL2_CDROM_ISSUES,1,[Skip SDL2 CD-rom code]) -AC_DEFINE(SKIP_SDL2_EVENT_ISSUES,1,[Skip SDL2 event code]) -AC_DEFINE(SKIP_SDL2_DEBUG_MEMORY_ISSUE,1,[Skip SDL2 screen code]) +AC_DEFINE(SKIP_SDL2_DEBUG_MEMORY_ISSUE,1,[Skip SDL2 debug memory code]) AC_WORDS_BIGENDIAN AC_OS_DEFINES diff --git a/ctp2_code/ctp/civ3_main.cpp b/ctp2_code/ctp/civ3_main.cpp index ed82fb9dc..5f2707c7f 100644 --- a/ctp2_code/ctp/civ3_main.cpp +++ b/ctp2_code/ctp/civ3_main.cpp @@ -1703,26 +1703,29 @@ int WINAPI CivMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, break; } -#if !defined(SKIP_SDL2_EVENT_ISSUES) - int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, - ~(SDL_EVENTMASK(SDL_MOUSEMOTION) | SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN) | SDL_EVENTMASK(SDL_MOUSEBUTTONUP))); -#else // SKIP_SDL2_EVENT_ISSUES - int n = 0; -#endif // SKIP_SDL2_EVENT_ISSUES + int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_MOUSEMOTION-1); if (0 > n) { - fprintf(stderr, "%s L%d: SDL_PeepEvents: Still events stored! Error?: %s\n", __FILE__, __LINE__, SDL_GetError()); - + fprintf(stderr, "%s L%d: SDL_PeepEvents: Still events stored! Error?: %s\n", __FILE__, __LINE__, SDL_GetError()); break; } if (0 == n) { - // other events are handled in other threads - // or no more events - break; + n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEWHEEL+1, SDL_LASTEVENT); + if (0 > n) { + fprintf(stderr, "%s L%d: SDL_PeepEvents: Still events stored! Error?: %s\n", __FILE__, __LINE__, SDL_GetError()); + break; + } + + if (0 == n) { + // other events are handled in other threads + // or no more events + break; + } } - if (SDL_QUIT == event.type) + if (SDL_QUIT == event.type) { gDone = TRUE; + } // If a keyboard event then we must reenqueue it so that aui_sdlkeyboard has a chance to look at it if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) diff --git a/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp b/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp index 1c6aad928..b5b26e4d1 100644 --- a/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp +++ b/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp @@ -34,8 +34,8 @@ // // - Removed non-standard include file . // - Standardised min/max usage. -// - Replaced old civilisation database by new one. (Aug 20th 2005 Martin Gühmann) -// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) +// - Replaced old civilisation database by new one. (Aug 20th 2005 Martin Gühmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -5853,48 +5853,48 @@ void FastRoundCommand::Execute(sint32 argc, char **argv) #if __AUI_USE_SDL__ while (1) { - #if !defined(SKIP_SDL2_EVENT_ISSUES) - int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, - ~(SDL_EVENTMASK(SDL_MOUSEMOTION) | SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN) | - SDL_EVENTMASK(SDL_MOUSEBUTTONUP))); - #else // SKIP_SDL2_EVENT_ISSUES - int n = 0; - #endif // SKIP_SDL2_EVENT_ISSUES + int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_MOUSEMOTION - 1); if (0 > n) { - fprintf(stderr, "[FastRoundCommand::Execute] PeepEvents failed: %s\n", - SDL_GetError()); + fprintf(stderr, "[FastRoundCommand::Execute] PeepEvents failed:\n%s\n", SDL_GetError()); break; } if (0 == n) { - // other events are handled in other threads - // or no more events - break; + n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEWHEEL + 1, SDL_LASTEVENT); + if (0 > n) { + fprintf(stderr, "[FastRoundCommand::Execute] PeepEvents failed:\n%s\n", SDL_GetError()); + break; + } + if (0 == n) { + // other events are handled in other threads + // or no more events + break; + } + } + if (SDL_QUIT == event.type) { + gDone = TRUE; + } + if (SDL_KEYDOWN == event.type) + { + SDL_KeyboardEvent key = event.key; + if (SDLK_ESCAPE == key.keysym.sym) + i = n; } - if (SDL_QUIT == event.type) + } #else while (PeekMessage(&msg, gHwnd, 0, 0, PM_REMOVE) && !g_letUIProcess) { - if (msg.message == WM_QUIT) -#endif + if (msg.message == WM_QUIT) { gDone = TRUE; -#ifndef __AUI_USE_SDL__ + } TranslateMessage(&msg); if (msg.message == WM_CHAR) { if ((MBCHAR)msg.wParam == 0x1B) i = n; } - DispatchMessage(&msg); -#else - if (SDL_KEYDOWN == event.type) - { - SDL_KeyboardEvent key = event.key; - if (SDLK_ESCAPE == key.keysym.sym) - i = n; - } -#endif } +#endif g_letUIProcess = FALSE; } while ((g_selected_item->GetCurPlayer() != g_selected_item->GetVisiblePlayer()) && diff --git a/ctp2_code/gs/fileio/GameFile.cpp b/ctp2_code/gs/fileio/GameFile.cpp index 2c1baecb4..e2f30c1f6 100644 --- a/ctp2_code/gs/fileio/GameFile.cpp +++ b/ctp2_code/gs/fileio/GameFile.cpp @@ -28,17 +28,17 @@ // - Readded Activision patch new magic number 66. // - Fixed autosave directory name for scenarios to match normal directory. // - Fixed the scenario savegame bug (but not for autosave, that still needs to be done) -// - Replaced old civilisation database by new one. (Aug 20th 2005 Martin G�hmann) -// - Made progress bar more fluently. (Aug 22nd 2005 Martin G�hmann) -// - Removed old sprite state databases. (Aug 29th 2005 Martin G�hmann) -// - Removed old difficulty database. (April 29th 2006 Martin G�hmann) -// - Removed old pollution database. (July 15th 2006 Martin G�hmann) -// - Removed old gobal warming database. (July 15th 2006 Martin G�hmann) -// - Removed old concept database. (31-Mar-2007 Martin G�hmann) -// - Removed old const database. (5-Aug-2007 Martin G�hmann) -// - Replaced CIV_INDEX by sint32. (2-Jan-2008 Martin G�hmann) +// - Replaced old civilisation database by new one. (Aug 20th 2005 Martin Gühmann) +// - Made progress bar more fluently. (Aug 22nd 2005 Martin Gühmann) +// - Removed old sprite state databases. (Aug 29th 2005 Martin Gühmann) +// - Removed old difficulty database. (April 29th 2006 Martin Gühmann) +// - Removed old pollution database. (July 15th 2006 Martin Gühmann) +// - Removed old gobal warming database. (July 15th 2006 Martin Gühmann) +// - Removed old concept database. (31-Mar-2007 Martin Gühmann) +// - Removed old const database. (5-Aug-2007 Martin Gühmann) +// - Replaced CIV_INDEX by sint32. (2-Jan-2008 Martin Gühmann) // - Make the Linux version loading and producing Windows compatible -// savegames. (16-Jan-2019 Martin G�hmann) +// savegames. (16-Jan-2019 Martin Gühmann) // //---------------------------------------------------------------------------- diff --git a/ctp2_code/gs/utility/gameinit.cpp b/ctp2_code/gs/utility/gameinit.cpp index 15e7533ed..8c77c5e5a 100644 --- a/ctp2_code/gs/utility/gameinit.cpp +++ b/ctp2_code/gs/utility/gameinit.cpp @@ -29,22 +29,22 @@ // Modifications from the original Activision code: // // - Added player selection for new single player game and scenarios of -// all types, by Martin G�hmann. +// all types, by Martin Gühmann. // - Fixed scenarios that allow players other than player 1 to be played, -// by Martin G�hmann +// by Martin Gühmann // - Added multiplayer to single player game conversion for testing. // - Prevent assigning the same civilisation index twice, while keeping the // human player selection. // - TradePool is fixed on reload if the number of goods in the // savegame differs from the number of goods in the database. -// - June 4th 2005 Martin G�hmann +// - June 4th 2005 Martin Gühmann // - Allowed for nPlayers to be 2 or 3 - JJB 2005/06/28 // - Removed auto-tutorial on low difficulty - JJB 2005/06/28 -// - Removed refferences to the civilisation database. (Aug 20th 2005 Martin G�hmann) -// - Removed unused SpriteStateDB refferences. (Aug 28th 2005 Martin G�hmann) -// - Reused obsolate concept icon database slot for new map icon database. (3-Mar-2007 Martin G�hmann) -// - Removed old concept database. (31-Mar-2007 Martin G�hmann) -// - Replaced old const database by new one. (5-Aug-2007 Martin G�hmann) +// - Removed refferences to the civilisation database. (Aug 20th 2005 Martin Gühmann) +// - Removed unused SpriteStateDB refferences. (Aug 28th 2005 Martin Gühmann) +// - Reused obsolate concept icon database slot for new map icon database. (3-Mar-2007 Martin Gühmann) +// - Removed old concept database. (31-Mar-2007 Martin Gühmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -1969,7 +1969,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive *archive) case STARTINFOTYPE_CIVSFIXED: case STARTINFOTYPE_POSITIONSFIXED: -// Added by Martin G�hmann +// Added by Martin Gühmann // No difference between STARTINFOTYPE_CIVSFIXED and STARTINFOTYPE_POSITIONSFIXED { Assert(numPlayersLoaded == 0); diff --git a/ctp2_code/ui/aui_common/aui_movie.cpp b/ctp2_code/ui/aui_common/aui_movie.cpp index 1d9bb840c..92f536b50 100644 --- a/ctp2_code/ui/aui_common/aui_movie.cpp +++ b/ctp2_code/ui/aui_common/aui_movie.cpp @@ -24,7 +24,7 @@ // // Modifications from the original Activision code: // -// - Initialized local variables. (Sep 9th 2005 Martin G�hmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) // //---------------------------------------------------------------------------- diff --git a/ctp2_code/ui/aui_common/aui_surface.h b/ctp2_code/ui/aui_common/aui_surface.h index 35cd71d51..04c352a82 100644 --- a/ctp2_code/ui/aui_common/aui_surface.h +++ b/ctp2_code/ui/aui_common/aui_surface.h @@ -24,7 +24,7 @@ // Modifications from the original Activision code: // // - Corrected a reported memory leak. -// - Added back buffering capability. (1-Jan-2010 Martin G�hmann) +// - Added back buffering capability. (1-Jan-2010 Martin Gühmann) // //---------------------------------------------------------------------------- #if defined(HAVE_PRAGMA_ONCE) diff --git a/ctp2_code/ui/aui_sdl/aui_sdl.cpp b/ctp2_code/ui/aui_sdl/aui_sdl.cpp index 8b5142e00..1dfc3c578 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdl.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdl.cpp @@ -11,6 +11,31 @@ SDL_Surface *aui_SDL::m_lpdd = 0; uint32 aui_SDL::m_SDLClassId = aui_UniqueId(); sint32 aui_SDL::m_SDLRefCount = 0; +// SKIP_SDL2_EVENT_ISSUES: TODO: handle SDL2 new keyboard-events especially for unicode characters: +// SDL_TEXTEDITING, /**< Keyboard text editing (composition) */ +// SDL_TEXTINPUT, /**< Keyboard text input */ +// SDL_KEYMAPCHANGED /**< Keymap changed due to a system event such as an +// input language or keyboard layout change. +// */ + +int FilterEvents(void* userData, SDL_Event *event) { + switch(event->type) { + // Quit event + case SDL_QUIT: + // Keyboard events + case SDL_KEYDOWN: + case SDL_KEYUP: + // Mouse events + case SDL_MOUSEMOTION: + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEWHEEL: + return 1; + default: + return 0; + } +} + AUI_ERRCODE aui_SDL::InitCommon(BOOL useExclusiveMode) { m_exclusiveMode = useExclusiveMode; @@ -26,15 +51,7 @@ AUI_ERRCODE aui_SDL::InitCommon(BOOL useExclusiveMode) */ SDL_ShowCursor(SDL_DISABLE); -#if !defined(SKIP_SDL2_EVENT_ISSUES) - // enable only a handfull of events - SDL_EventState(SDL_IGNORE, SDL_ALLEVENTS); - SDL_EventState(SDL_ENABLE, SDL_MOUSEEVENTMASK); - SDL_EventState(SDL_ENABLE, SDL_KEYDOWNMASK); - SDL_EventState(SDL_ENABLE, SDL_QUITMASK); - - SDL_EnableUNICODE(1); -#endif // SKIP_SDL2_EVENT_ISSUES + SDL_SetEventFilter(FilterEvents, NULL); return AUI_ERRCODE_OK; } diff --git a/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp b/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp index 03053ba20..b6f0ad482 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp @@ -168,13 +168,9 @@ uint32 aui_SDLKeyboard::convertSDLKey(SDL_Keysym keysym) return AUI_KEYBOARD_KEY_LEFTARROW; case SDLK_RIGHT: return AUI_KEYBOARD_KEY_RIGHTARROW; + default: + return AUI_KEYBOARD_KEY_INVALID; } -#if !defined(SKIP_SDL2_EVENT_ISSUES) - if ((keysym.unicode & 0xFF80) == 0) { - return (keysym.unicode & 0x7F); - } -#endif // SKIP_SDL2_EVENT_ISSUES - return AUI_KEYBOARD_KEY_INVALID; } AUI_ERRCODE aui_SDLKeyboard::Acquire() diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp index 467aa0da5..65cd4fb8d 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp @@ -12,6 +12,8 @@ #include "civapp.h" extern CivApp *g_civApp; +// SKIP_SDL2_EVENT_ISSUES: TODO: scrolling with mouse (screen sides) is too fast to be useful + aui_SDLMouse::aui_SDLMouse( AUI_ERRCODE *retval, const MBCHAR *ldlBlock, @@ -62,8 +64,7 @@ aui_SDLMouse::GetInput(void) SDL_Event od[10]; // check for one of the mouse events - int numElements = - SDL_PeepEvents(od, 10, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEBUTTONUP); + int numElements = SDL_PeepEvents(od, 10, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEWHEEL); if (0 > numElements) { fprintf(stderr, "Mouse PeepEvents failed: %s\n", SDL_GetError()); return AUI_ERRCODE_GETDEVICEDATAFAILED; @@ -85,15 +86,6 @@ aui_SDLMouse::GetInput(void) break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: -#if !defined(SKIP_SDL2_EVENT_ISSUES) - if (od[ev].button.button == SDL_BUTTON_WHEELUP){ - HandleMouseWheel((sint16)1); - break; - } - else if (od[ev].button.button == SDL_BUTTON_WHEELDOWN){ - HandleMouseWheel((sint16)-1); - break; - } m_data.position.x = od[ev].button.x; m_data.position.y = od[ev].button.y; if (od[ev].button.button == SDL_BUTTON_LEFT) { @@ -101,8 +93,14 @@ aui_SDLMouse::GetInput(void) } else if (od[ev].button.button == SDL_BUTTON_RIGHT) { m_data.rbutton = od[ev].button.state == SDL_PRESSED; } -#endif // SKIP_SDL2_EVENT_ISSUES break; + case SDL_MOUSEWHEEL: + if (od[ev].wheel.y > 0) { + HandleMouseWheel((sint16)1); + } else if (od[ev].wheel.y < 0) { + HandleMouseWheel((sint16)-1); + } + break; default: printf("event not handeled: %d\n", od[ev].type); break; From 54b760d071ffc6b84e6a9cdf691d361369c3df45 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Tue, 7 Apr 2020 00:19:41 +0200 Subject: [PATCH 13/29] Updated travis and docker to build with SDL2 --- .travis.yml | 7 ++++--- Dockerfile | 39 +++++---------------------------------- 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1a5ca2e1a..f400bbb41 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,9 +6,10 @@ addons: sources: - ubuntu-toolchain-r-test packages: - - libsdl1.2-dev - - libsdl-mixer1.2-dev - - libsdl-image1.2-dev + - libsdl2-dev + - libsdl2-mixer-dev + - libsdl2-image-dev + - libtiff-dev - byacc - gtk+-2.0-dev - gcc-5 diff --git a/Dockerfile b/Dockerfile index f6584cedd..b3ade54f8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ RUN useradd -m $USERNAME && \ FROM system as builder RUN apt-get update && apt-get install -y --no-install-recommends \ - libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev byacc libgtk2.0-dev gcc-5 g++-5 \ + libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libtiff-dev byacc libgtk2.0-dev gcc-5 g++-5 \ automake libtool unzip flex git ca-certificates ### set default compilers @@ -29,31 +29,6 @@ RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 100 && \ c++ --version && \ cpp --version -### build ffmpeg -RUN git clone --depth 1 -b v0.5.2 http://github.com/FFmpeg/FFmpeg/ && \ - cd FFmpeg && \ - ./configure \ - --prefix=/usr/local/ \ - --disable-ffmpeg \ - --disable-ffplay \ - --disable-ffserver && \ - make -j"$(nproc)" && \ - make install - -### ffmpeg built - -### build SDL_ffmpeg -RUN git clone -b v0.9.0 http://github.com/lynxabraxas/SDL_ffmpeg && \ - cd /SDL_ffmpeg/trunk/ && \ - sed -i 's/CFLAGS=-I$INCDIR/CFLAGS="$CFLAGS -I$INCDIR"/' configure && \ - sed -i 's/LDFLAGS=-L$LIBDIR/LDFLAGS="$LDFLAGS -L$LIBDIR"/' configure && \ - LDFLAGS="-lm" \ - ./configure --prefix=/usr/local/ --static=yes && \ - make && \ - make install - -### SDL_ffmpeg built - ENV LD_LIBRARY_PATH "${LD_LIBRARY_PATH}:/usr/local/lib" ## ctp2CD/ copy not done in builder stage such that stages before are compatible with travis docker build @@ -67,12 +42,10 @@ ARG BTYP RUN cd /ctp2 \ && ./autogen.sh \ - && CPPFLAGS="-I/usr/local/include/SDL/" \ - CC=/usr/bin/gcc-5 \ + && CC=/usr/bin/gcc-5 \ CXX=/usr/bin/g++-5 \ CFLAGS="$CFLAGS -w $( [ "${BTYP##*debug*}" ] && echo -O3 || echo -g -rdynamic ) -fuse-ld=gold" \ CXXFLAGS="$CXXFLAGS -fpermissive -w $( [ "${BTYP##*debug*}" ] && echo -O3 || echo -g -rdynamic ) -fuse-ld=gold" \ - LDFLAGS="$LDFLAGS -L/usr/local/lib" \ ./configure --prefix=/opt/ctp2 --bindir=/opt/ctp2/ctp2_program/ctp --enable-silent-rules $( [ "${BTYP##*debug*}" ] || echo --enable-debug ) \ && make -j"$(nproc)" \ && make -j"$(nproc)" install \ @@ -89,18 +62,16 @@ FROM system as install ARG BTYP RUN apt-get update && apt-get install -y --no-install-recommends \ - libsdl1.2debian libsdl-mixer1.2 libsdl-image1.2 libgtk2.0-0 && \ + libsdl2-2.0 libsdl2-mixer-2.0 libsdl2-image-2.0 libgtk2.0-0 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* -## copy libs first since they are less likely to change -COPY --from=builder /usr/local/lib /usr/local/lib -ENV LD_LIBRARY_PATH "${LD_LIBRARY_PATH}:/usr/local/lib" - ## ctp2CD/ copy done in install stage such that stages before are compatible with travis docker build, results in one additional layer in the final DI (incr. DI download size) COPY ctp2CD/ /opt/ctp2/ ## ctp2/ copy has to be after ctp2CD/ to overwrite with newer versions from civctp2 COPY --from=builder /opt/ctp2/ /opt/ctp2/ +## Disable English layout files +RUN mv /opt/ctp2/ctp2_data/english/uidata/layouts /opt/ctp2/ctp2_data/english/uidata/layouts.org USER $USERNAME From 8f07684335006044b72888e1f9ae11eb93fc90c5 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Wed, 8 Apr 2020 00:17:32 +0200 Subject: [PATCH 14/29] Use bionic (18.04) on Travis to remove the _IO_cookie_io_functions_t error Update gtk 2.0 library reference. --- .travis.yml | 4 +- ctp2_code/ctp/c3.h | 2 +- ctp2_code/ctp/civapp.cpp | 42 ++++++++++----------- ctp2_code/ui/interface/IntroMovieWin.cpp | 2 +- ctp2_code/ui/interface/IntroMovieWindow.cpp | 2 +- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index f400bbb41..806074d13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: cpp sudo: true -dist: trusty +dist: bionic addons: apt: sources: @@ -11,7 +11,7 @@ addons: - libsdl2-image-dev - libtiff-dev - byacc - - gtk+-2.0-dev + - libgtk2.0-dev - gcc-5 - g++-5 diff --git a/ctp2_code/ctp/c3.h b/ctp2_code/ctp/c3.h index 114d2afea..44746b644 100644 --- a/ctp2_code/ctp/c3.h +++ b/ctp2_code/ctp/c3.h @@ -43,7 +43,7 @@ // - Moved DirectX API-Version to use into "ctp2_config.h" // - Added struct for automatic debug tool initialization and // cleanup so that it is the first respective the last thing -// that is done in the program. (Oct 3rd 2005 Martin Gühmann) +// that is done in the program. (Oct 3rd 2005 Martin Gühmann) // //---------------------------------------------------------------------------- diff --git a/ctp2_code/ctp/civapp.cpp b/ctp2_code/ctp/civapp.cpp index db93999ab..6637cf2e6 100644 --- a/ctp2_code/ctp/civapp.cpp +++ b/ctp2_code/ctp/civapp.cpp @@ -39,9 +39,9 @@ // - Keep the user's leader name when the data is consistent. // - Skip begin turn handling when loading from a file. // - Fixed a repetitive memory leak in the Great Libary caused by -// scenario loading, by Martin G?hmann. +// scenario loading, by Martin Gühmann. // - Removed some redundant code, because it is already done -// somewhere else, by Martin G?hmann. +// somewhere else, by Martin Gühmann. // //---------------------------------------------------------------------------- // @@ -65,32 +65,32 @@ // - Used the new ColorSet option to select civilisation colors. // - Memory leak repaired: clean up the turn counter override information. // - Hot seat handling improved. -// - Static member of StatusBar is now deleted correctly, by Martin G?hmann. +// - Static member of StatusBar is now deleted correctly, by Martin Gühmann. // - Cleaned up music screen. // - The civilisation index from the profile is now reset if it is too high. -// This prevents the game from crashing. - April 12th 2005 Martin G?hmann +// This prevents the game from crashing. - April 12th 2005 Martin Gühmann // - Added crash prevention during game loading. // - Added another civilisation index check. // - Option added to include multiple data directories. // - Added Slic segment cleanup. -// - Replaced old civilisation database by new one. (Aug 22nd 2005 Martin G?hmann) -// - Made progress bar more fluently. (Aug 22nd 2005 Martin G?hmann) -// - Removed the old endgame and installation databases. (Aug 29th 2005 Martin G?hmann) +// - Replaced old civilisation database by new one. (Aug 22nd 2005 Martin Gühmann) +// - Made progress bar more fluently. (Aug 22nd 2005 Martin Gühmann) +// - Removed the old endgame and installation databases. (Aug 29th 2005 Martin Gühmann) // - Removed old sprite state databases, removed olf good's icon -// database (unused), replaced old risk database by new one. (Aug 29th 2005 Martin G?hmann) -// - The right color set is now selected afterwards the ProfileDB is available. (Aug 29th 2005 Martin G?hmann) -// - Added cleanup of gaia controller and info window. (Sep 13th 2005 Martin G?hmann) -// - Added ArmyData and Network cleanup. (Sep 25th 2005 Martin G?hmann) -// - Added graphicsresscreen_Cleanup. (Sep 25th 2005 Martin G?hmann) -// - Replaced old difficulty database by new one. (April 29th 2006 Martin G?hmann) -// - Replaced old pollution database by new one. (July 15th 2006 Martin G?hmann) -// - Replaced old global warming database by new one. (July 15th 2006 Martin G?hmann) -// - Added new map icon database. (3-Mar-2007 Martin G?hmann) -// - Replaced old map database by new one. (27-Mar-2007 Martin G?hmann) -// - Replaced old concept database by new one. (31-Mar-2007 Martin G?hmann) -// - Replaced old const database by new one. (5-Aug-2007 Martin G?hmann) -// - Fixed PBEM BeginTurn event execution. (27-Oct-2007 Martin G?hmann) -// - Games can now be saved if the visible player is a robot. (30-Jan-2008 Martin G?hmann) +// database (unused), replaced old risk database by new one. (Aug 29th 2005 Martin Gühmann) +// - The right color set is now selected afterwards the ProfileDB is available. (Aug 29th 2005 Martin Gühmann) +// - Added cleanup of gaia controller and info window. (Sep 13th 2005 Martin Gühmann) +// - Added ArmyData and Network cleanup. (Sep 25th 2005 Martin Gühmann) +// - Added graphicsresscreen_Cleanup. (Sep 25th 2005 Martin Gühmann) +// - Replaced old difficulty database by new one. (April 29th 2006 Martin Gühmann) +// - Replaced old pollution database by new one. (July 15th 2006 Martin Gühmann) +// - Replaced old global warming database by new one. (July 15th 2006 Martin Gühmann) +// - Added new map icon database. (3-Mar-2007 Martin Gühmann) +// - Replaced old map database by new one. (27-Mar-2007 Martin Gühmann) +// - Replaced old concept database by new one. (31-Mar-2007 Martin Gühmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) +// - Fixed PBEM BeginTurn event execution. (27-Oct-2007 Martin Gühmann) +// - Games can now be saved if the visible player is a robot. (30-Jan-2008 Martin Gühmann) // //---------------------------------------------------------------------------- diff --git a/ctp2_code/ui/interface/IntroMovieWin.cpp b/ctp2_code/ui/interface/IntroMovieWin.cpp index 08963aebd..0adf5c0f5 100644 --- a/ctp2_code/ui/interface/IntroMovieWin.cpp +++ b/ctp2_code/ui/interface/IntroMovieWin.cpp @@ -24,7 +24,7 @@ // // Modifications from the original Activision code: // -// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) // //---------------------------------------------------------------------------- diff --git a/ctp2_code/ui/interface/IntroMovieWindow.cpp b/ctp2_code/ui/interface/IntroMovieWindow.cpp index f91a2361f..116fa752a 100644 --- a/ctp2_code/ui/interface/IntroMovieWindow.cpp +++ b/ctp2_code/ui/interface/IntroMovieWindow.cpp @@ -24,7 +24,7 @@ // // Modifications from the original Activision code: // -// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) // //---------------------------------------------------------------------------- From 80965a59f2e43bcf8f7da5d30c185ceff53d4f97 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Mon, 13 Apr 2020 15:48:32 +0200 Subject: [PATCH 15/29] Play movies using the installed ffmpeg libraries. The movie player is a stripped version of ffplay version 3.4 (with some small modifications of version 4.2). The movie can be paused with 'p' and stopped with 'esc', 'space' or a left-mouse-button click. --- .travis.yml | 3 + Dockerfile | 8 +- ctp2_code/Makefile.am | 2 + ctp2_code/ctp/civ3_main.cpp | 26 +- ctp2_code/os/autoconf/sdl_ffmpeg.m4 | 8 +- ctp2_code/sound/soundmanager.cpp | 12 +- ctp2_code/sound/soundmanager.h | 1 - ctp2_code/ui/aui_common/aui_movie.cpp | 363 +-- ctp2_code/ui/aui_common/aui_movie.h | 15 +- ctp2_code/ui/aui_common/auitypes.h | 1 + ctp2_code/ui/aui_directx/aui_directui.cpp | 7 +- ctp2_code/ui/aui_directx/aui_directui.h | 1 + ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp | 2214 ++++++++++++++++++ ctp2_code/ui/aui_sdl/aui_sdlmovie.h | 56 + ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp | 68 + ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h | 45 + ctp2_code/ui/aui_sdl/aui_sdlsurface.h | 1 + ctp2_code/ui/aui_sdl/aui_sdlui.cpp | 35 +- ctp2_code/ui/aui_sdl/aui_sdlui.h | 2 + 19 files changed, 2472 insertions(+), 396 deletions(-) create mode 100644 ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp create mode 100644 ctp2_code/ui/aui_sdl/aui_sdlmovie.h create mode 100644 ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp create mode 100644 ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h diff --git a/.travis.yml b/.travis.yml index 806074d13..cf457f0f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,9 @@ addons: - libsdl2-mixer-dev - libsdl2-image-dev - libtiff-dev + - libavcodec-dev + - libavformat-dev + - libswscale-dev - byacc - libgtk2.0-dev - gcc-5 diff --git a/Dockerfile b/Dockerfile index b3ade54f8..1580ebd21 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,8 +16,8 @@ RUN useradd -m $USERNAME && \ FROM system as builder RUN apt-get update && apt-get install -y --no-install-recommends \ - libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libtiff-dev byacc libgtk2.0-dev gcc-5 g++-5 \ - automake libtool unzip flex git ca-certificates + libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libtiff-dev libavcodec-dev libavformat-dev libswscale-dev \ + byacc libgtk2.0-dev gcc-5 g++-5 automake libtool unzip flex git ca-certificates ### set default compilers RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 100 && \ @@ -62,7 +62,7 @@ FROM system as install ARG BTYP RUN apt-get update && apt-get install -y --no-install-recommends \ - libsdl2-2.0 libsdl2-mixer-2.0 libsdl2-image-2.0 libgtk2.0-0 && \ + libsdl2-2.0 libsdl2-mixer-2.0 libsdl2-image-2.0 ffmpeg libgtk2.0-0 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -70,8 +70,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY ctp2CD/ /opt/ctp2/ ## ctp2/ copy has to be after ctp2CD/ to overwrite with newer versions from civctp2 COPY --from=builder /opt/ctp2/ /opt/ctp2/ -## Disable English layout files -RUN mv /opt/ctp2/ctp2_data/english/uidata/layouts /opt/ctp2/ctp2_data/english/uidata/layouts.org USER $USERNAME diff --git a/ctp2_code/Makefile.am b/ctp2_code/Makefile.am index 049c5decc..841dfa0dc 100644 --- a/ctp2_code/Makefile.am +++ b/ctp2_code/Makefile.am @@ -235,6 +235,8 @@ ctp_ctp2_SOURCES = \ ui/aui_sdl/aui_sdljoystick.cpp \ ui/aui_sdl/aui_sdlkeyboard.cpp \ ui/aui_sdl/aui_sdlmouse.cpp \ + ui/aui_sdl/aui_sdlmovie.cpp \ + ui/aui_sdl/aui_sdlmoviemanager.cpp \ ui/aui_sdl/aui_sdlsound.cpp \ ui/aui_sdl/aui_sdlsurface.cpp \ ui/aui_sdl/aui_sdlui.cpp \ diff --git a/ctp2_code/ctp/civ3_main.cpp b/ctp2_code/ctp/civ3_main.cpp index 5f2707c7f..7f051af73 100644 --- a/ctp2_code/ctp/civ3_main.cpp +++ b/ctp2_code/ctp/civ3_main.cpp @@ -45,17 +45,17 @@ // - Merged GNU and MSVC code (DoFinalCleanup, CivMain). // - Option added to include multiple data directories. // - Display the main thread function name in the debugger. -// - Removed references to CivilisationDB. (Aug 20th 2005 Martin G?hmann) -// - Removed references to old SpriteStateDBs. (Aug 29th 2005 Martin G?hmann) -// - Initialized local variables. (Sep 9th 2005 Martin G?hmann) -// - Removed unused local variables. (Sep 9th 2005 Martin G?hmann) -// - Removed some unreachable code. (Sep 9th 2005 Martin G?hmann) +// - Removed references to CivilisationDB. (Aug 20th 2005 Martin Gühmann) +// - Removed references to old SpriteStateDBs. (Aug 29th 2005 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) +// - Removed unused local variables. (Sep 9th 2005 Martin Gühmann) +// - Removed some unreachable code. (Sep 9th 2005 Martin Gühmann) // - Moved debug tools handling to c3.h, so that the leak reporter doesn't -// report leaks that aren't leaks. (Oct 3rd 2005 Matzin G?hmann) +// report leaks that aren't leaks. (Oct 3rd 2005 Matzin Gühmann) // - Added version to crash.txt -// - USE_LOGGING now works in a final version. (30-Jun-2008 Martin G?hmann) +// - USE_LOGGING now works in a final version. (30-Jun-2008 Martin Gühmann) // - The log files are now only opened and closed once, this speeds up -// debugging significantly. (09-Aug-2008 Martin G?hmann) +// debugging significantly. (09-Aug-2008 Martin Gühmann) // //---------------------------------------------------------------------------- // @@ -72,7 +72,6 @@ #include "ancientwindows.h" #include "appstrings.h" #include "aui.h" -#include "aui_directmoviemanager.h" #include "aui_Factory.h" #include "aui_ldl.h" #include "background.h" @@ -557,12 +556,7 @@ int ui_Initialize(void) g_c3ui->RegisterObject(aui_Factory::new_Keyboard(auiErr)); SPLASH_STRING("Creating Movie manager..."); -#if defined(__AUI_USE_SDL__) - //SDL movie manager is in aui_movie.cpp - g_c3ui->RegisterObject(new aui_MovieManager()); -#else - g_c3ui->RegisterObject(new aui_DirectMovieManager()); -#endif + g_c3ui->RegisterObject(g_c3ui->CreateMovieManager()); SPLASH_STRING("Starting Mouse..."); auiErr = g_c3ui->TheMouse()->Start(); @@ -1165,7 +1159,7 @@ void ParseCommandLine(PSTR szCmdLine) #if defined(__AUI_USE_SDL__) if (strstr(szCmdLine, "fullscreen")) { - g_SDL_flags = g_SDL_flags | SDL_WINDOW_FULLSCREEN; + g_SDL_flags = g_SDL_flags | SDL_WINDOW_FULLSCREEN_DESKTOP; } if (strstr(szCmdLine, "hwsurface")) { printf("SDL2 does not support hwsurface option"); diff --git a/ctp2_code/os/autoconf/sdl_ffmpeg.m4 b/ctp2_code/os/autoconf/sdl_ffmpeg.m4 index 3a71a5eef..5491a0394 100644 --- a/ctp2_code/os/autoconf/sdl_ffmpeg.m4 +++ b/ctp2_code/os/autoconf/sdl_ffmpeg.m4 @@ -3,9 +3,11 @@ dnl $Id$ dnl AC_DEFUN([AM_PATH_SDL_FFMPEG],[ - AC_CHECK_HEADER([SDL/SDL_ffmpeg.h],[ac_found_header=yes],[ac_found_header=no]) - if test x$ac_found_header = xyes; then - SDL_FFMPEG_LDFLAGS="-lSDL_ffmpeg -lavcodec" + AC_CHECK_HEADER([libavcodec/avcodec.h],[av_codec_found_header=yes],[av_codec_found_header=no]) + AC_CHECK_HEADER([libavformat/avformat.h],[av_format_found_header=yes],[av_format_found_header=no]) + AC_CHECK_HEADER([libswscale/swscale.h],[sw_scale_found_header=yes],[sw_scale_found_header=no]) + if test "x$av_codec_found_header" = xyes -a "x$av_format_found_header" = xyes -a "x$sw_scale_found_header" = xyes; then + SDL_FFMPEG_LDFLAGS="-lavutil -lavformat -lavcodec -lswscale -lswresample" AC_DEFINE(USE_SDL_FFMPEG,1,[Enable SDL_ffmpeg library]) else SDL_FFMPEG_LDFLAGS="" diff --git a/ctp2_code/sound/soundmanager.cpp b/ctp2_code/sound/soundmanager.cpp index 40d8d3a4d..89d517cac 100755 --- a/ctp2_code/sound/soundmanager.cpp +++ b/ctp2_code/sound/soundmanager.cpp @@ -99,7 +99,6 @@ SoundManager::SoundManager() #endif // SKIP_SDL2_CDROM_ISSUES m_useOggTracks (false), m_oggTrack (0), - m_SDLInitFlags (SDL_INIT_NOPARACHUTE), #endif m_timeToCheckCD (0), m_numTracks (0), @@ -119,11 +118,6 @@ SoundManager::SoundManager() m_musicVolume = static_cast(g_theProfileDB->GetMusicVolume()); } -#if defined(USE_SDL) && defined(_DEBUG) - // Do not remove this or debugging won't work... :( - m_SDLInitFlags |= SDL_INIT_NOPARACHUTE; -#endif - m_sfxSounds = new PointerList; m_voiceSounds = new PointerList; m_soundWalker = new PointerList::Walker; @@ -159,7 +153,7 @@ void SoundManager::InitSoundDriver() int output_rate = 22050; // 22khz @ 16 Bit stereo Uint16 output_format = AUDIO_S16SYS; int output_channels = 2; - int errcode = SDL_Init(SDL_INIT_AUDIO | m_SDLInitFlags); + int errcode = SDL_InitSubSystem(SDL_INIT_AUDIO); if (errcode < 0) { @@ -204,7 +198,7 @@ void SoundManager::CleanupSoundDriver() Mix_CloseAudio(); } - // SDL_Quit() -> civ_main.cpp:AtExitProc() + SDL_QuitSubSystem(SDL_INIT_AUDIO); #else // !USE_SDL AIL_quick_shutdown(); #endif // USE_SDL @@ -223,7 +217,7 @@ void SoundManager::InitRedbook() } #if !defined(SKIP_SDL2_CDROM_ISSUES) if (!m_cdrom && !m_useOggTracks) { - int errcode = SDL_Init(SDL_INIT_CDROM | m_SDLInitFlags); + int errcode = SDL_Init(SDL_INIT_CDROM); Assert(0 == errcode); if (errcode < 0) { diff --git a/ctp2_code/sound/soundmanager.h b/ctp2_code/sound/soundmanager.h index 47ddf9a15..716fccdd5 100644 --- a/ctp2_code/sound/soundmanager.h +++ b/ctp2_code/sound/soundmanager.h @@ -167,7 +167,6 @@ class SoundManager { SDL_CD *m_cdrom; #endif // SKIP_SDL2_CDROM_ISSUES BOOL m_useOggTracks; - Uint32 m_SDLInitFlags; Mix_Music *m_oggTrack; #endif uint32 m_timeToCheckCD; diff --git a/ctp2_code/ui/aui_common/aui_movie.cpp b/ctp2_code/ui/aui_common/aui_movie.cpp index 92f536b50..95a9e94da 100644 --- a/ctp2_code/ui/aui_common/aui_movie.cpp +++ b/ctp2_code/ui/aui_common/aui_movie.cpp @@ -36,25 +36,13 @@ #include "aui_movie.h" -#ifdef __AUI_USE_SDL__ -#include -#ifdef USE_SDL_FFMPEG -#include -SDL_ffmpegFile* film; -#endif -#include -#include -#include "soundmanager.h" // g_soundManager -#include "aui_sdlsurface.h" - -Mix_Chunk achunk; - -int m_moviechannel; -#endif - WNDPROC aui_Movie::m_windowProc = NULL; aui_Movie *aui_Movie::m_onScreenMovie = NULL; +aui_Movie::aui_Movie() : aui_Base() { + InitCommon(); +} + aui_Movie::aui_Movie( AUI_ERRCODE *retval, const MBCHAR * filename ) @@ -65,8 +53,7 @@ aui_Movie::aui_Movie( Assert( AUI_SUCCESS(*retval) ); } -AUI_ERRCODE aui_Movie::InitCommon( const MBCHAR * filename ) -{ +void aui_Movie::InitCommon() { m_format = NULL; m_surface = NULL; m_isOpen = FALSE; @@ -89,6 +76,11 @@ AUI_ERRCODE aui_Movie::InitCommon( const MBCHAR * filename ) m_getFrame = NULL; #endif m_curFrame = 0; +} + +AUI_ERRCODE aui_Movie::InitCommon( const MBCHAR * filename ) +{ + InitCommon(); AUI_ERRCODE errcode = SetFilename( filename ); Assert( AUI_SUCCESS(errcode) ); @@ -219,139 +211,6 @@ uint32 aui_Movie::SetTimePerFrame( uint32 timePerFrame ) return prevTimePerFrame; } -#ifdef USE_SDL_FFMPEG -/* -void reload_audio(int channel) -{ - SDL_ffmpegAudioFrame *aframe; - - if(channel == m_moviechannel) - { - if(film) - { - while(!aframe) - aframe= SDL_ffmpegGetAudioFrame(film); - //if(aframe){ - - //while(!aframe->size) - // aframe= SDL_ffmpegGetAudioFrame(file); - achunk.alen= aframe->size; - //achunk.abuf= aframe->buffer; //should we copy the data here??? - if(achunk.abuf) //or use realloc??? - free(achunk.abuf); - achunk.abuf= new uint8_t[achunk.alen]; - memcpy(achunk.abuf, aframe->buffer, achunk.alen); - achunk.allocated= 1; //abuf should not be freed if it belongs to aframe - achunk.volume= MIX_MAX_VOLUME; - - m_moviechannel= Mix_PlayChannel(channel, &achunk , 0); - if(m_moviechannel < 0) - fprintf(stderr, "%s L%d: Error initializing SDL_mixer: %s\n", __FILE__, __LINE__, Mix_GetError()); - //else - // Mix_ChannelFinished(reload_audio); - SDL_ffmpegReleaseAudio(film, aframe, achunk.alen); - } - } - else - fprintf(stderr, "%s L%d: Not a movie audio channel!\n", __FILE__, __LINE__); - - return; -} -*/ - -/* sdl_ffmpeg <= 0.7.1 -void audioCallback(void *udata, Uint8 *stream, int len) -{ - // unpack our void pointer - SDL_ffmpegFile *file = (SDL_ffmpegFile*)udata; - - int bytesUsed; - int offset = 0; - SDL_ffmpegAudioFrame *frame = SDL_ffmpegGetAudioFrame(file); - if(!frame) return; - - while(len > 0) - { - // check if we need a new frame - if(!frame->size) - { - frame = SDL_ffmpegGetAudioFrame(file); - if(!frame) return; - } - - if(frame->size <= len) - { - // this frame is smaller or equal to the amount of data needed. - bytesUsed = frame->size; - } - else - { - // this frame has more data than needed - bytesUsed = len; - } - - // copy the correct amount of data - memcpy(stream+offset, frame->buffer, bytesUsed); - // adjust the needed length accordingly - len -= bytesUsed; - offset += bytesUsed; - - SDL_ffmpegReleaseAudio(file, frame, bytesUsed); - } - - return; -} -*/ -/* sdl_ffmpeg > 0.7.1*/ -void audioCallback(void *udata, Uint8 *stream, int len) -{ - - // unpack our void pointer - SDL_ffmpegFile *file = (SDL_ffmpegFile*)udata; - - int bytesUsed; - - SDL_ffmpegAudioFrame *frame; - - while(len > 0) - { - // try to get a new frame - frame = SDL_ffmpegGetAudioFrame(file); - - // we could not receive a new frame, break from loop - if(!frame) break; - - if(frame->size <= len) - { - // this frame is smaller or equal to the amount of data needed. - bytesUsed = frame->size; - } - else - { - // this frame has more data than needed - bytesUsed = len; - } - - // copy the correct amount of data - memcpy(stream, frame->buffer, bytesUsed); - - // adjust the needed length accordingly - len -= bytesUsed; - - // adjust stream offset - stream += bytesUsed; - - // adjust size of frame to prevent reusing the same data - frame->size -= bytesUsed; - - // adjust buffer of frame for the same reason - frame->buffer += bytesUsed; - } - - return; -} -#endif - AUI_ERRCODE aui_Movie::Open( uint32 flags, aui_Surface *surface, @@ -422,32 +281,6 @@ AUI_ERRCODE aui_Movie::Open( m_rect.right = m_rect.left + m_aviStreamInfo.rcFrame.right; m_rect.bottom = m_rect.top + m_aviStreamInfo.rcFrame.bottom; -#elif defined(USE_SDL_FFMPEG) //replaces a aui_sdlmovie::Open( - - //stop game sound - g_soundManager->ReleaseSoundDriver(); // If the CD is mounted, the music keeps playing ... - - //code from SDL_ffmpeg example: - film= SDL_ffmpegOpen(m_filename); - if (film) - { - SDL_ffmpegSelectVideoStream(film, 0); - SDL_ffmpegSelectAudioStream(film, 0); - - int w, h; - // we get the size from our active video stream - if(SDL_ffmpegGetVideoSize(film, &w, &h)) - fprintf(stderr, "%s L%d: Could not determin movie size!\n", __FILE__, __LINE__); - else - { - m_rect.right = m_rect.left + w; - m_rect.bottom = m_rect.top + h; - } - } - else - { - fprintf(stderr, "%s L%d: Could not open %s!\n", __FILE__, __LINE__, m_filename); - } #endif m_isOpen = TRUE; //even if open failed, loops otherwise m_isPlaying = FALSE; @@ -482,13 +315,6 @@ AUI_ERRCODE aui_Movie::Close( void ) AVIFileRelease( m_aviFile ); m_aviFile = NULL; } -#elif defined(USE_SDL_FFMPEG) - if(film) - { - Mix_HookMusic(NULL,NULL); //switch on the general callback function (sound and music) - SDL_ffmpegStopDecoding(film); - SDL_ffmpegFree(film); - } #endif m_isOpen = FALSE; @@ -511,62 +337,6 @@ AUI_ERRCODE aui_Movie::Play( void ) 1000 ); Assert( err == 0 ); if ( err ) return AUI_ERRCODE_HACK; - -#elif defined(USE_SDL_FFMPEG) - /* - //mplayer "movie manager" - SDL_SysWMinfo info; - char cmd[1024]; - cmd[0]=0; - - SDL_VERSION(&info.version); // this is important! - if (SDL_GetWMInfo(&info)) - snprintf(cmd, sizeof(cmd), "mplayer -vo xv -wid 0x%lx /media/cdrom/Setup/data/Max/ctp2_data/default/videos/%s", info.info.x11.window, m_filename); - else - snprintf(cmd, sizeof(cmd), "mplayer -vo sdl /media/cdrom/Setup/data/Max/ctp2_data/default/videos/%s", m_filename); - fprintf(stderr, "%s L%d: Trying to execute: %s!\n", __FILE__, __LINE__, cmd); - fprintf(stderr, "%s L%d: The path to the movies is hard coded! Solve it! ;)\n", __FILE__, __LINE__); - g_soundManager->ReleaseSoundDriver(); - system(cmd); - g_soundManager->ReacquireSoundDriver();//no function with SDL, see soundmanager.cpp - */ - - // we start our decode thread, this always tries to buffer in some frames - // so we can enjoy smooth playback - if(film) - { - Mix_HookMusic(audioCallback, film); - - // if(Mix_OpenAudio(48000, AUDIO_S16SYS, 2, 512)==-1) - // fprintf(stderr, "%s L%d: Mix_OpenAudio: %s\n", __FILE__, __LINE__, Mix_GetError()); - - SDL_ffmpegStartDecoding(film); //returns always 0! - //SDL_ffmpegPause(film, 0);//unpause film sdl_ffmpeg <= 0.7.1 - SDL_ffmpegPlay(film, 1);//unpause film sdl_ffmpeg > 0.7.1 - //start audio here or in process or open??? -/* - SDL_ffmpegAudioFrame *aframe; - - while(!aframe) - aframe= SDL_ffmpegGetAudioFrame(film); - //if(aframe){ - - //while(!aframe->size) - // aframe= SDL_ffmpegGetAudioFrame(file); - achunk.alen= aframe->size; - //achunk.abuf= aframe->buffer; //should we copy the data here??? - achunk.abuf= new uint8_t[achunk.alen]; - memcpy(achunk.abuf, aframe->buffer, achunk.alen); - achunk.allocated= 1; //abuf should not be freed if it belongs to aframe - Mix_VolumeChunk(&achunk, MIX_MAX_VOLUME); - m_moviechannel= Mix_PlayChannel(-1, &achunk , 0); - if(m_moviechannel < 0) - fprintf(stderr, "%s L%d: Error initializing SDL_mixer: %s\n", __FILE__, __LINE__, Mix_GetError()); - else - Mix_ChannelFinished(reload_audio); - SDL_ffmpegReleaseAudio(film, aframe, achunk.alen); -*/ - } #endif if ( m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN ) @@ -581,6 +351,7 @@ AUI_ERRCODE aui_Movie::Play( void ) AUI_ERRCODE aui_Movie::PlayOnScreenMovie( void ) { +#ifdef __AUI_USE_DIRECTX__ aui_Mouse *mouse = g_ui->TheMouse(); sint32 numEvents; static aui_MouseEvent mouseEvents[ k_MOUSE_MAXINPUT ]; @@ -597,7 +368,6 @@ AUI_ERRCODE aui_Movie::PlayOnScreenMovie( void ) mouse->Hide(); } -#ifdef __AUI_USE_DIRECTX__ MSG msg; m_windowProc = (WNDPROC)GetWindowLong( g_ui->TheHWND(), GWL_WNDPROC ); SetWindowLong( g_ui->TheHWND(), GWL_WNDPROC, (LONG)OnScreenMovieWindowProc ); @@ -636,21 +406,12 @@ AUI_ERRCODE aui_Movie::PlayOnScreenMovie( void ) SetWindowLong( g_ui->TheHWND(), GWL_WNDPROC, (LONG)m_windowProc ); m_windowProc = NULL; -#else - fprintf(stderr, "%s L%d: SDL mouse code is missing here!\n", __FILE__, __LINE__); - //m_onScreenMovie = this; - - while(!m_isFinished && m_isPlaying) - { - Process(); - } - //m_onScreenMovie = NULL; -#endif if (mouse) mouse->Show(); g_ui->AddDirtyRect( &m_rect ); // Does this set the rect that needs to be repainted later on? +#endif return Stop(); } @@ -663,16 +424,6 @@ AUI_ERRCODE aui_Movie::Stop( void ) uint32 err = AVIStreamEndStreaming(m_aviStream); Assert(err == 0); if(err) return AUI_ERRCODE_HACK; -#elif defined(USE_SDL_FFMPEG) - fprintf(stderr, "%s L%d: Stopping movie!\n", __FILE__, __LINE__); - if(film) - { - //SDL_ffmpegPause(film, 1);//pause film film sdl_ffmpeg <= 0.7.1 - SDL_ffmpegPlay(film, 0);//pause film sdl_ffmpeg > 0.7.1 - //SDL_ffmpegStopDecoding(film); - } - - g_soundManager->ReacquireSoundDriver(); //no function with SDL, see soundmanager.cpp #endif } @@ -686,11 +437,6 @@ AUI_ERRCODE aui_Movie::Pause(void) { if (m_isPlaying && !m_isPaused) { -#ifdef USE_SDL_FFMPEG - if(film) - //SDL_ffmpegPause(film, 1);//pause film sdl_ffmpeg <= 0.7.1 - SDL_ffmpegPlay(film, 0);//pause film sdl_ffmpeg > 0.7.1 -#endif m_isPaused = TRUE; } @@ -701,11 +447,6 @@ AUI_ERRCODE aui_Movie::Resume(void) { if (m_isPlaying && m_isPaused) { -#ifdef USE_SDL_FFMPEG - if(film) - //SDL_ffmpegPause(film, 0);//unpause film sdl_ffmpeg <= 0.7.1 - SDL_ffmpegPlay(film, 1);//unpause film sdl_ffmpeg > 0.7.1 -#endif m_isPaused = FALSE; } @@ -785,86 +526,6 @@ AUI_ERRCODE aui_Movie::Process( void ) retval = AUI_ERRCODE_HANDLED; } } -#elif defined(USE_SDL_FFMPEG) - - //from SDL_ffmpeg example: - if(m_isPlaying && !m_isPaused) - { - if(film) - { - aui_Surface *surface = (m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN) ? - g_ui->Secondary() : - m_surface; - - int s; - SDL_ffmpegStream *str; - -/* - // print some info on detected stream to output - for(s = 0; sAStreams; s++) - { - str = SDL_ffmpegGetAudioStream(film, s); - - printf("Info on audiostream #%i:\n", s); - printf("\tChannels: %i\n", str->channels); - if(strlen(str->language)) printf("\tLanguage: %s\n", str->language); - printf("\tSampleRate: %i\n", str->sampleRate); - } - - - for(s = 0; sVStreams; s++) - { - str = SDL_ffmpegGetVideoStream(film, s); - - printf("Info on videostream #%i:\n", s); - if(strlen(str->language)) printf("\tLanguage: %s\n", str->language); - printf("\tFrame: %ix%i\n", str->width, str->height); - printf("\tFrameRate: %.2ffps\n", 1.0 / (str->frameRate[0] / str->frameRate[1])); - } -*/ - - SDL_ffmpegVideoFrame* frame = 0; - - SDL_Rect sdl_rect = {m_rect.left, m_rect.top, m_rect.right - m_rect.left, m_rect.bottom - m_rect.top}; - aui_SDLSurface* sdl_surf = static_cast(surface); - - int64_t duration = SDL_ffmpegGetDuration(film); - - //if(!m_isFinished) {//don't wait until frame is ready to be shown - while(!frame && !m_isFinished) - { //wait until there is a frame to be shown - frame = SDL_ffmpegGetVideoFrame(film); - SDL_Delay(5); //too much for 25 fps but here we have only 15 fps - - if(frame) - { - //fprintf(stderr, "%s L%d: Got frame!\n", __FILE__, __LINE__); - - // we got a frame, so we better show this one - SDL_BlitSurface(frame->buffer, 0, sdl_surf->DDS(), &sdl_rect); - - // After releasing this frame, you can no longer use it. - // you should call this function every time you get a frame! - //not in sdl_ffmpeg > 0.7.1!!! - //SDL_ffmpegReleaseVideo(film, frame); - - // we flip the double buffered screen so we might actually see something - SDL_Flip(sdl_surf->DDS()); - } - m_isFinished = SDL_ffmpegGetPosition(film) >= duration; - //m_isFinished= film->playing; - } - - if(m_isFinished) - { - //fprintf(stderr, "%s L%d: Done displaying movie!\n", __FILE__, __LINE__); - m_isPlaying = FALSE; - } - } - else - m_isFinished = TRUE; -} - retval = AUI_ERRCODE_HANDLED; #endif return retval; diff --git a/ctp2_code/ui/aui_common/aui_movie.h b/ctp2_code/ui/aui_common/aui_movie.h index 409ca586a..e5ccea91d 100644 --- a/ctp2_code/ui/aui_common/aui_movie.h +++ b/ctp2_code/ui/aui_common/aui_movie.h @@ -56,19 +56,20 @@ class aui_MovieFormat : public aui_FileFormat class aui_Movie : public aui_Base { public: - + aui_Movie( void ); aui_Movie( AUI_ERRCODE *retval, const MBCHAR * filename = NULL ); virtual ~aui_Movie(); protected: + void InitCommon( void ); AUI_ERRCODE InitCommon( const MBCHAR * filename ); public: - AUI_ERRCODE Load( void ); - AUI_ERRCODE Unload( void ); + virtual AUI_ERRCODE Load( void ); + virtual AUI_ERRCODE Unload( void ); AUI_ERRCODE SetFilename( const MBCHAR * filename ); const MBCHAR *GetFilename( void ) const { return m_filename; } @@ -106,10 +107,10 @@ class aui_Movie : public aui_Base virtual AUI_ERRCODE Process( void ); - BOOL IsOpen( void ) const { return m_isOpen; } - BOOL IsPlaying( void ) const { return m_isPlaying; } - BOOL IsFinished( void ) const { return m_isFinished; } - BOOL IsPaused( void ) const { return m_isPaused; } + virtual BOOL IsOpen( void ) const { return m_isOpen; } + virtual BOOL IsPlaying( void ) const { return m_isPlaying; } + virtual BOOL IsFinished( void ) const { return m_isFinished; } + virtual BOOL IsPaused( void ) const { return m_isPaused; } static WNDPROC m_windowProc; static aui_Movie *m_onScreenMovie; diff --git a/ctp2_code/ui/aui_common/auitypes.h b/ctp2_code/ui/aui_common/auitypes.h index 7d909e7ce..d40317bb1 100644 --- a/ctp2_code/ui/aui_common/auitypes.h +++ b/ctp2_code/ui/aui_common/auitypes.h @@ -80,6 +80,7 @@ enum AUI_ERRCODE AUI_ERRCODE_SETPROPERTYFAILED, AUI_ERRCODE_SETFORMATFAILED, //#endif + AUI_ERRCODE_MOVIEFAILED, AUI_ERRCODE_MAX }; diff --git a/ctp2_code/ui/aui_directx/aui_directui.cpp b/ctp2_code/ui/aui_directx/aui_directui.cpp index e39107f8a..f79ac0c3a 100644 --- a/ctp2_code/ui/aui_directx/aui_directui.cpp +++ b/ctp2_code/ui/aui_directx/aui_directui.cpp @@ -28,7 +28,7 @@ // // - Prevented crashes // - Added graphics DirectX built in double buffering and extended it -// to manual tripple buffering. (1-Jan-2010 Martin Gühmann) +// to manual tripple buffering. (1-Jan-2010 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -43,6 +43,7 @@ #include "aui_joystick.h" #include "aui_directsurface.h" #include "aui_directmouse.h" +#include "aui_directmoviemanager.h" #include "aui_directui.h" @@ -387,4 +388,8 @@ AUI_ERRCODE aui_DirectUI::AltTabIn( void ) return FlushDirtyList(); } +aui_MovieManager* aui_DirectUI::CreateMovieManager( void ) { + return new aui_DirectMovieManager(); +} + #endif // __AUI_USE_DIRECTX__ diff --git a/ctp2_code/ui/aui_directx/aui_directui.h b/ctp2_code/ui/aui_directx/aui_directui.h index c2049ddac..58ca63903 100644 --- a/ctp2_code/ui/aui_directx/aui_directui.h +++ b/ctp2_code/ui/aui_directx/aui_directui.h @@ -79,6 +79,7 @@ class aui_DirectUI : public aui_UI, public aui_DirectX void SetWidth(sint32 width) { m_width = width; } void SetHeight(sint32 height) { m_height = height; } + aui_MovieManager* CreateMovieManager( void ); protected: LPDIRECTDRAWSURFACE m_lpdds; LPDIRECTDRAWSURFACE m_back; diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp new file mode 100644 index 000000000..104417271 --- /dev/null +++ b/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp @@ -0,0 +1,2214 @@ +// +// The implementation of aui_SDLMovie is a stripped version of ffplay.c. +// ffplay.c is part of ffmpeg (https://github.com/FFmpeg/FFmpeg). +// The version used is 3.4 with some version 4.2 modifications. +// + +#include "c3.h" +#include "aui_sdlmovie.h" + +#if defined(__AUI_USE_SDL__) + +#if defined(USE_SDL_FFMPEG) + +extern "C" { + #include + #include + #include + #include "libswscale/swscale.h" +} +#include +#include "profileDB.h" + +#undef MOVIE_RESIZABLE_WINDOW + +#define MAX_QUEUE_SIZE (15 * 1024 * 1024) +#define MIN_FRAMES 25 +#define EXTERNAL_CLOCK_MIN_FRAMES 2 +#define EXTERNAL_CLOCK_MAX_FRAMES 10 + +/* Minimum SDL audio buffer size, in samples. */ +#define SDL_AUDIO_MIN_BUFFER_SIZE 512 +/* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */ +#define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30 + +/* no AV sync correction is done if below the minimum AV sync threshold */ +#define AV_SYNC_THRESHOLD_MIN 0.04 +/* AV sync correction is done if above the maximum AV sync threshold */ +#define AV_SYNC_THRESHOLD_MAX 0.1 +/* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */ +#define AV_SYNC_FRAMEDUP_THRESHOLD 0.1 +/* no AV correction is done if too big error */ +#define AV_NOSYNC_THRESHOLD 10.0 + +/* maximum audio speed change to get correct sync */ +#define SAMPLE_CORRECTION_PERCENT_MAX 10 + +/* external clock speed adjustment constants for realtime sources based on buffer fullness */ +#define EXTERNAL_CLOCK_SPEED_MIN 0.900 +#define EXTERNAL_CLOCK_SPEED_MAX 1.010 +#define EXTERNAL_CLOCK_SPEED_STEP 0.001 + +/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */ +#define AUDIO_DIFF_AVG_NB 20 + +/* polls for possible required screen refresh at least this often, should be less than 1/fps */ +#define REFRESH_RATE 0.01 + +#define CURSOR_HIDE_DELAY 1000000 + +static unsigned sws_flags = SWS_BICUBIC; + +typedef struct MyAVPacketList { + AVPacket pkt; + struct MyAVPacketList *next; + int serial; +} MyAVPacketList; + +typedef struct PacketQueue { + MyAVPacketList *first_pkt, *last_pkt; + int nb_packets; + int size; + int64_t duration; + int abort_request; + int serial; + SDL_mutex *mutex; + SDL_cond *cond; +} PacketQueue; + +#define VIDEO_PICTURE_QUEUE_SIZE 3 +#define SUBPICTURE_QUEUE_SIZE 16 +#define SAMPLE_QUEUE_SIZE 9 +#define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE)) + +typedef struct AudioParams { + int freq; + int channels; + int64_t channel_layout; + enum AVSampleFormat fmt; + int frame_size; + int bytes_per_sec; +} AudioParams; + +typedef struct Clock { + double pts; /* clock base */ + double pts_drift; /* clock base minus time at which we updated the clock */ + double last_updated; + double speed; + int serial; /* clock is based on a packet with this serial */ + int paused; + int *queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */ +} Clock; + +/* Common struct for handling all types of decoded data and allocated render buffers. */ +typedef struct Frame { + AVFrame *frame; + int serial; + double pts; /* presentation timestamp for the frame */ + double duration; /* estimated duration of the frame */ + int64_t pos; /* byte position of the frame in the input file */ + int width; + int height; + int format; + AVRational sar; + int uploaded; + int flip_v; +} Frame; + +typedef struct FrameQueue { + Frame queue[FRAME_QUEUE_SIZE]; + int rindex; + int windex; + int size; + int max_size; + int keep_last; + int rindex_shown; + SDL_mutex *mutex; + SDL_cond *cond; + PacketQueue *pktq; +} FrameQueue; + +enum { + AV_SYNC_AUDIO_MASTER, /* default choice */ + AV_SYNC_VIDEO_MASTER, + AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */ +}; + +typedef struct Decoder { + AVPacket pkt; + PacketQueue *queue; + AVCodecContext *avctx; + int pkt_serial; + int finished; + int packet_pending; + SDL_cond *empty_queue_cond; + int64_t start_pts; + AVRational start_pts_tb; + int64_t next_pts; + AVRational next_pts_tb; + SDL_Thread *decoder_tid; +} Decoder; + +typedef struct VideoState { + SDL_Thread *read_tid; + int abort_request; + int force_refresh; + int paused; + int last_paused; + int queue_attachments_req; + int read_pause_return; + AVFormatContext *ic; + int realtime; + + Clock audclk; + Clock vidclk; + Clock extclk; + + FrameQueue pictq; + FrameQueue sampq; + + Decoder auddec; + Decoder viddec; + + int audio_stream; + + int av_sync_type; + + double audio_clock; + int audio_clock_serial; + double audio_diff_cum; /* used for AV difference average computation */ + double audio_diff_avg_coef; + double audio_diff_threshold; + int audio_diff_avg_count; + AVStream *audio_st; + PacketQueue audioq; + int audio_hw_buf_size; + uint8_t *audio_buf; + uint8_t *audio_buf1; + unsigned int audio_buf_size; /* in bytes */ + unsigned int audio_buf1_size; + int audio_buf_index; /* in bytes */ + int audio_write_buf_size; + int audio_volume; + int muted; + struct AudioParams audio_src; + struct AudioParams audio_tgt; + struct SwrContext *swr_ctx; + int frame_drops_early; + int frame_drops_late; + + SDL_Texture *vis_texture; + SDL_Texture *vid_texture; + + double frame_timer; + double frame_last_filter_delay; + int video_stream; + AVStream *video_st; + PacketQueue videoq; + double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity + struct SwsContext *img_convert_ctx; + struct SwsContext *sub_convert_ctx; + int eof; + + char *filename; + int width, height, xleft, ytop; + int step; + + SDL_cond *continue_read_thread; +} VideoState; + +/* options specified by the user */ +static int default_width = 640; +static int default_height = 480; +static int screen_width = 0; +static int screen_height = 0; +static int av_sync_type = AV_SYNC_AUDIO_MASTER; +static int autoexit = 0; +static int infinite_buffer = -1; +static int64_t cursor_last_shown; +static int cursor_hidden = 0; + +/* current context */ +static int is_full_screen; + +static AVPacket flush_pkt; + +#if defined(MOVIE_RESIZABLE_WINDOW) + static SDL_Window *window = NULL; +#endif // MOVIE_RESIZABLE_WINDOW +static SDL_Renderer *renderer = NULL; +static SDL_AudioDeviceID audio_dev; + +static const struct TextureFormatEntry { + enum AVPixelFormat format; + int texture_fmt; +} sdl_texture_format_map[] = { + { AV_PIX_FMT_RGB8, SDL_PIXELFORMAT_RGB332 }, + { AV_PIX_FMT_RGB444, SDL_PIXELFORMAT_RGB444 }, + { AV_PIX_FMT_RGB555, SDL_PIXELFORMAT_RGB555 }, + { AV_PIX_FMT_BGR555, SDL_PIXELFORMAT_BGR555 }, + { AV_PIX_FMT_RGB565, SDL_PIXELFORMAT_RGB565 }, + { AV_PIX_FMT_BGR565, SDL_PIXELFORMAT_BGR565 }, + { AV_PIX_FMT_RGB24, SDL_PIXELFORMAT_RGB24 }, + { AV_PIX_FMT_BGR24, SDL_PIXELFORMAT_BGR24 }, + { AV_PIX_FMT_0RGB32, SDL_PIXELFORMAT_RGB888 }, + { AV_PIX_FMT_0BGR32, SDL_PIXELFORMAT_BGR888 }, + { AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 }, + { AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 }, + { AV_PIX_FMT_RGB32, SDL_PIXELFORMAT_ARGB8888 }, + { AV_PIX_FMT_RGB32_1, SDL_PIXELFORMAT_RGBA8888 }, + { AV_PIX_FMT_BGR32, SDL_PIXELFORMAT_ABGR8888 }, + { AV_PIX_FMT_BGR32_1, SDL_PIXELFORMAT_BGRA8888 }, + { AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV }, + { AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2 }, + { AV_PIX_FMT_UYVY422, SDL_PIXELFORMAT_UYVY }, + { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_UNKNOWN }, +}; + +static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt) +{ + MyAVPacketList *pkt1; + + if (q->abort_request) + return -1; + + pkt1 = (MyAVPacketList*) av_malloc(sizeof(MyAVPacketList)); + if (!pkt1) + return -1; + pkt1->pkt = *pkt; + pkt1->next = NULL; + if (pkt == &flush_pkt) + q->serial++; + pkt1->serial = q->serial; + + if (!q->last_pkt) + q->first_pkt = pkt1; + else + q->last_pkt->next = pkt1; + q->last_pkt = pkt1; + q->nb_packets++; + q->size += pkt1->pkt.size + sizeof(*pkt1); + q->duration += pkt1->pkt.duration; + /* XXX: should duplicate packet data in DV case */ + SDL_CondSignal(q->cond); + return 0; +} + +static int packet_queue_put(PacketQueue *q, AVPacket *pkt) +{ + int ret; + + SDL_LockMutex(q->mutex); + ret = packet_queue_put_private(q, pkt); + SDL_UnlockMutex(q->mutex); + + if (pkt != &flush_pkt && ret < 0) + av_packet_unref(pkt); + + return ret; +} + +static int packet_queue_put_nullpacket(PacketQueue *q, int stream_index) +{ + AVPacket pkt1, *pkt = &pkt1; + av_init_packet(pkt); + pkt->data = NULL; + pkt->size = 0; + pkt->stream_index = stream_index; + return packet_queue_put(q, pkt); +} + +/* packet queue handling */ +static int packet_queue_init(PacketQueue *q) +{ + memset(q, 0, sizeof(PacketQueue)); + q->mutex = SDL_CreateMutex(); + if (!q->mutex) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + q->cond = SDL_CreateCond(); + if (!q->cond) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + q->abort_request = 1; + return 0; +} + +static void packet_queue_flush(PacketQueue *q) +{ + MyAVPacketList *pkt, *pkt1; + + SDL_LockMutex(q->mutex); + for (pkt = q->first_pkt; pkt; pkt = pkt1) { + pkt1 = pkt->next; + av_packet_unref(&pkt->pkt); + av_freep(&pkt); + } + q->last_pkt = NULL; + q->first_pkt = NULL; + q->nb_packets = 0; + q->size = 0; + q->duration = 0; + SDL_UnlockMutex(q->mutex); +} + +static void packet_queue_destroy(PacketQueue *q) +{ + packet_queue_flush(q); + SDL_DestroyMutex(q->mutex); + SDL_DestroyCond(q->cond); +} + +static void packet_queue_abort(PacketQueue *q) +{ + SDL_LockMutex(q->mutex); + + q->abort_request = 1; + + SDL_CondSignal(q->cond); + + SDL_UnlockMutex(q->mutex); +} + +static void packet_queue_start(PacketQueue *q) +{ + SDL_LockMutex(q->mutex); + q->abort_request = 0; + packet_queue_put_private(q, &flush_pkt); + SDL_UnlockMutex(q->mutex); +} + +/* return < 0 if aborted, 0 if no packet and > 0 if packet. */ +static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial) +{ + MyAVPacketList *pkt1; + int ret; + + SDL_LockMutex(q->mutex); + + for (;;) { + if (q->abort_request) { + ret = -1; + break; + } + + pkt1 = q->first_pkt; + if (pkt1) { + q->first_pkt = pkt1->next; + if (!q->first_pkt) + q->last_pkt = NULL; + q->nb_packets--; + q->size -= pkt1->pkt.size + sizeof(*pkt1); + q->duration -= pkt1->pkt.duration; + *pkt = pkt1->pkt; + if (serial) + *serial = pkt1->serial; + av_free(pkt1); + ret = 1; + break; + } else if (!block) { + ret = 0; + break; + } else { + SDL_CondWait(q->cond, q->mutex); + } + } + SDL_UnlockMutex(q->mutex); + return ret; +} + +static void decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) { + memset(d, 0, sizeof(Decoder)); + d->avctx = avctx; + d->queue = queue; + d->empty_queue_cond = empty_queue_cond; + d->start_pts = AV_NOPTS_VALUE; + d->pkt_serial = -1; +} + +static int decoder_decode_frame(Decoder *d, AVFrame *frame) { + int ret = AVERROR(EAGAIN); + + for (;;) { + AVPacket pkt; + + if (d->queue->serial == d->pkt_serial) { + do { + if (d->queue->abort_request) + return -1; + + switch (d->avctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + ret = avcodec_receive_frame(d->avctx, frame); + if (ret >= 0) { + frame->pts = frame->best_effort_timestamp; + } + break; + case AVMEDIA_TYPE_AUDIO: + ret = avcodec_receive_frame(d->avctx, frame); + if (ret >= 0) { + AVRational tb = (AVRational){1, frame->sample_rate}; + if (frame->pts != AV_NOPTS_VALUE) + frame->pts = av_rescale_q(frame->pts, av_codec_get_pkt_timebase(d->avctx), tb); + else if (d->next_pts != AV_NOPTS_VALUE) + frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb); + if (frame->pts != AV_NOPTS_VALUE) { + d->next_pts = frame->pts + frame->nb_samples; + d->next_pts_tb = tb; + } + } + break; + } + if (ret == AVERROR_EOF) { + d->finished = d->pkt_serial; + avcodec_flush_buffers(d->avctx); + return 0; + } + if (ret >= 0) + return 1; + } while (ret != AVERROR(EAGAIN)); + } + + do { + if (d->queue->nb_packets == 0) + SDL_CondSignal(d->empty_queue_cond); + if (d->packet_pending) { + av_packet_move_ref(&pkt, &d->pkt); + d->packet_pending = 0; + } else { + if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0) + return -1; + } + // Added from ffmpeg 4 + if (d->queue->serial == d->pkt_serial) + break; + av_packet_unref(&pkt); + } while (1); + + if (pkt.data == flush_pkt.data) { + avcodec_flush_buffers(d->avctx); + d->finished = 0; + d->next_pts = d->start_pts; + d->next_pts_tb = d->start_pts_tb; + } else { + if (avcodec_send_packet(d->avctx, &pkt) == AVERROR(EAGAIN)) { + av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n"); + d->packet_pending = 1; + av_packet_move_ref(&d->pkt, &pkt); + } + av_packet_unref(&pkt); + } + } +} + +static void decoder_destroy(Decoder *d) { + av_packet_unref(&d->pkt); + avcodec_free_context(&d->avctx); +} + +static void frame_queue_unref_item(Frame *vp) +{ + av_frame_unref(vp->frame); +} + +static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last) +{ + int i; + memset(f, 0, sizeof(FrameQueue)); + if (!(f->mutex = SDL_CreateMutex())) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + if (!(f->cond = SDL_CreateCond())) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + f->pktq = pktq; + f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE); + f->keep_last = !!keep_last; + for (i = 0; i < f->max_size; i++) + if (!(f->queue[i].frame = av_frame_alloc())) + return AVERROR(ENOMEM); + return 0; +} + +static void frame_queue_destroy(FrameQueue *f) +{ + int i; + for (i = 0; i < f->max_size; i++) { + Frame *vp = &f->queue[i]; + frame_queue_unref_item(vp); + av_frame_free(&vp->frame); + } + SDL_DestroyMutex(f->mutex); + SDL_DestroyCond(f->cond); +} + +static void frame_queue_signal(FrameQueue *f) +{ + SDL_LockMutex(f->mutex); + SDL_CondSignal(f->cond); + SDL_UnlockMutex(f->mutex); +} + +static Frame *frame_queue_peek(FrameQueue *f) +{ + return &f->queue[(f->rindex + f->rindex_shown) % f->max_size]; +} + +static Frame *frame_queue_peek_next(FrameQueue *f) +{ + return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size]; +} + +static Frame *frame_queue_peek_last(FrameQueue *f) +{ + return &f->queue[f->rindex]; +} + +static Frame *frame_queue_peek_writable(FrameQueue *f) +{ + /* wait until we have space to put a new frame */ + SDL_LockMutex(f->mutex); + while (f->size >= f->max_size && + !f->pktq->abort_request) { + SDL_CondWait(f->cond, f->mutex); + } + SDL_UnlockMutex(f->mutex); + + if (f->pktq->abort_request) + return NULL; + + return &f->queue[f->windex]; +} + +static Frame *frame_queue_peek_readable(FrameQueue *f) +{ + /* wait until we have a readable a new frame */ + SDL_LockMutex(f->mutex); + while (f->size - f->rindex_shown <= 0 && + !f->pktq->abort_request) { + SDL_CondWait(f->cond, f->mutex); + } + SDL_UnlockMutex(f->mutex); + + if (f->pktq->abort_request) + return NULL; + + return &f->queue[(f->rindex + f->rindex_shown) % f->max_size]; +} + +static void frame_queue_push(FrameQueue *f) +{ + if (++f->windex == f->max_size) + f->windex = 0; + SDL_LockMutex(f->mutex); + f->size++; + SDL_CondSignal(f->cond); + SDL_UnlockMutex(f->mutex); +} + +static void frame_queue_next(FrameQueue *f) +{ + if (f->keep_last && !f->rindex_shown) { + f->rindex_shown = 1; + return; + } + frame_queue_unref_item(&f->queue[f->rindex]); + if (++f->rindex == f->max_size) + f->rindex = 0; + SDL_LockMutex(f->mutex); + f->size--; + SDL_CondSignal(f->cond); + SDL_UnlockMutex(f->mutex); +} + +/* return the number of undisplayed frames in the queue */ +static int frame_queue_nb_remaining(FrameQueue *f) +{ + return f->size - f->rindex_shown; +} + +static void decoder_abort(Decoder *d, FrameQueue *fq) +{ + packet_queue_abort(d->queue); + frame_queue_signal(fq); + SDL_WaitThread(d->decoder_tid, NULL); + d->decoder_tid = NULL; + packet_queue_flush(d->queue); +} + +static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture) +{ + Uint32 format; + int access, w, h; + // test on texture added from ffmpeg 4 + if (!*texture || SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) { + void *pixels; + int pitch; + if (*texture) + SDL_DestroyTexture(*texture); + if (!(*texture = SDL_CreateTexture(renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height))) + return -1; + if (SDL_SetTextureBlendMode(*texture, blendmode) < 0) + return -1; + if (init_texture) { + if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0) + return -1; + memset(pixels, 0, pitch * new_height); + SDL_UnlockTexture(*texture); + } + av_log(NULL, AV_LOG_VERBOSE, "Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format)); + } + return 0; +} + +static void calculate_display_rect(SDL_Rect *rect, + int scr_xleft, int scr_ytop, int scr_width, int scr_height, + int pic_width, int pic_height, AVRational pic_sar) +{ + float aspect_ratio; + int width, height, x, y; + + if (pic_sar.num == 0) + aspect_ratio = 0; + else + aspect_ratio = av_q2d(pic_sar); + + if (aspect_ratio <= 0.0) + aspect_ratio = 1.0; + aspect_ratio *= (float) pic_width / (float) pic_height; + + /* XXX: we suppose the screen has a 1.0 pixel ratio */ + height = scr_height; + width = lrint(height * aspect_ratio) & ~1; + if (width > scr_width) { + width = scr_width; + height = lrint(width / aspect_ratio) & ~1; + } + x = (scr_width - width) / 2; + y = (scr_height - height) / 2; + rect->x = scr_xleft + x; + rect->y = scr_ytop + y; + rect->w = FFMAX(width, 1); + rect->h = FFMAX(height, 1); +} + +static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_BlendMode *sdl_blendmode) +{ + int i; + *sdl_blendmode = SDL_BLENDMODE_NONE; + *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN; + if (format == AV_PIX_FMT_RGB32 || + format == AV_PIX_FMT_RGB32_1 || + format == AV_PIX_FMT_BGR32 || + format == AV_PIX_FMT_BGR32_1) + *sdl_blendmode = SDL_BLENDMODE_BLEND; + for (i = 0; i < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; i++) { + if (format == sdl_texture_format_map[i].format) { + *sdl_pix_fmt = sdl_texture_format_map[i].texture_fmt; + return; + } + } +} + +static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsContext **img_convert_ctx) { + int ret = 0; + Uint32 sdl_pix_fmt; + SDL_BlendMode sdl_blendmode; + get_sdl_pix_fmt_and_blendmode(frame->format, &sdl_pix_fmt, &sdl_blendmode); + if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0) + return -1; + switch (sdl_pix_fmt) { + case SDL_PIXELFORMAT_UNKNOWN: + *img_convert_ctx = sws_getCachedContext(*img_convert_ctx, + frame->width, frame->height, (AVPixelFormat) frame->format, frame->width, frame->height, + AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL); + if (*img_convert_ctx != NULL) { + uint8_t *pixels[4]; + int pitch[4]; + if (!SDL_LockTexture(*tex, NULL, (void **)pixels, pitch)) { + sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize, + 0, frame->height, pixels, pitch); + SDL_UnlockTexture(*tex); + } + } else { + av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n"); + ret = -1; + } + break; + case SDL_PIXELFORMAT_IYUV: + if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) { + ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0], frame->linesize[0], + frame->data[1], frame->linesize[1], + frame->data[2], frame->linesize[2]); + } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) { + ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0], + frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1], + frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); + } else { + av_log(NULL, AV_LOG_ERROR, "Mixed negative and positive linesizes are not supported.\n"); + return -1; + } + break; + default: + if (frame->linesize[0] < 0) { + ret = SDL_UpdateTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); + } else { + ret = SDL_UpdateTexture(*tex, NULL, frame->data[0], frame->linesize[0]); + } + break; + } + return ret; +} + +static void set_sdl_yuv_conversion_mode(AVFrame *frame) +{ +#if SDL_VERSION_ATLEAST(2,0,8) + SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC; + if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) { + if (frame->color_range == AVCOL_RANGE_JPEG) + mode = SDL_YUV_CONVERSION_JPEG; + else if (frame->colorspace == AVCOL_SPC_BT709) + mode = SDL_YUV_CONVERSION_BT709; + else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M || frame->colorspace == AVCOL_SPC_SMPTE240M) + mode = SDL_YUV_CONVERSION_BT601; + } + SDL_SetYUVConversionMode(mode); +#endif +} + +static void video_image_display(VideoState *is) +{ + Frame *vp; + SDL_Rect rect; + + vp = frame_queue_peek_last(&is->pictq); + + calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar); + + if (!vp->uploaded) { + if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0) + return; + vp->uploaded = 1; + vp->flip_v = vp->frame->linesize[0] < 0; + } + + // copied from ffmpeg 4 + set_sdl_yuv_conversion_mode(vp->frame); + SDL_RenderCopyEx(renderer, is->vid_texture, NULL, &rect, 0, NULL, (SDL_RendererFlip) (vp->flip_v ? SDL_FLIP_VERTICAL : 0)); + // copied from ffmpeg 4 + set_sdl_yuv_conversion_mode(NULL); +} + +static void stream_component_close(VideoState *is, int stream_index) +{ + AVFormatContext *ic = is->ic; + AVCodecParameters *codecpar; + + if (stream_index < 0 || stream_index >= ic->nb_streams) + return; + codecpar = ic->streams[stream_index]->codecpar; + + switch (codecpar->codec_type) { + case AVMEDIA_TYPE_AUDIO: + decoder_abort(&is->auddec, &is->sampq); + SDL_CloseAudioDevice(audio_dev); + decoder_destroy(&is->auddec); + swr_free(&is->swr_ctx); + av_freep(&is->audio_buf1); + is->audio_buf1_size = 0; + is->audio_buf = NULL; + break; + case AVMEDIA_TYPE_VIDEO: + decoder_abort(&is->viddec, &is->pictq); + decoder_destroy(&is->viddec); + break; + default: + break; + } + + ic->streams[stream_index]->discard = AVDISCARD_ALL; + switch (codecpar->codec_type) { + case AVMEDIA_TYPE_AUDIO: + is->audio_st = NULL; + is->audio_stream = -1; + break; + case AVMEDIA_TYPE_VIDEO: + is->video_st = NULL; + is->video_stream = -1; + break; + default: + break; + } +} + +static void stream_close(VideoState *is) +{ + /* XXX: use a special url_shutdown call to abort parse cleanly */ + is->abort_request = 1; + SDL_WaitThread(is->read_tid, NULL); + + /* close each stream */ + if (is->audio_stream >= 0) + stream_component_close(is, is->audio_stream); + if (is->video_stream >= 0) + stream_component_close(is, is->video_stream); + avformat_close_input(&is->ic); + + packet_queue_destroy(&is->videoq); + packet_queue_destroy(&is->audioq); + + /* free all pictures */ + frame_queue_destroy(&is->pictq); + frame_queue_destroy(&is->sampq); + SDL_DestroyCond(is->continue_read_thread); + sws_freeContext(is->img_convert_ctx); + sws_freeContext(is->sub_convert_ctx); + av_free(is->filename); + if (is->vis_texture) + SDL_DestroyTexture(is->vis_texture); + if (is->vid_texture) + SDL_DestroyTexture(is->vid_texture); + av_free(is); +} + +static void set_default_window_size(int width, int height, AVRational sar) +{ + SDL_Rect rect; + int max_width = screen_width ? screen_width : INT_MAX; + int max_height = screen_height ? screen_height : INT_MAX; + if (max_width == INT_MAX && max_height == INT_MAX) + max_height = height; + calculate_display_rect(&rect, 0, 0, max_width, max_height, width, height, sar); + default_width = rect.w; + default_height = rect.h; +} + +static int video_open(VideoState *is) +{ + int w,h; + + w = screen_width ? screen_width : default_width; + h = screen_height ? screen_height : default_height; + +#if defined(MOVIE_RESIZABLE_WINDOW) + SDL_SetWindowSize(window, w, h); + SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + if (is_full_screen) + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); + SDL_ShowWindow(window); +#endif + + is->width = w; + is->height = h; + + return 0; +} + +/* display the current picture, if any */ +static void video_display(VideoState *is) +{ + if (!is->width) + video_open(is); + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + if (is->video_st) + video_image_display(is); + SDL_RenderPresent(renderer); +} + +static double get_clock(Clock *c) +{ + if (*c->queue_serial != c->serial) + return NAN; + if (c->paused) { + return c->pts; + } else { + double time = av_gettime_relative() / 1000000.0; + return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed); + } +} + +static void set_clock_at(Clock *c, double pts, int serial, double time) +{ + c->pts = pts; + c->last_updated = time; + c->pts_drift = c->pts - time; + c->serial = serial; +} + +static void set_clock(Clock *c, double pts, int serial) +{ + double time = av_gettime_relative() / 1000000.0; + set_clock_at(c, pts, serial, time); +} + +static void set_clock_speed(Clock *c, double speed) +{ + set_clock(c, get_clock(c), c->serial); + c->speed = speed; +} + +static void init_clock(Clock *c, int *queue_serial) +{ + c->speed = 1.0; + c->paused = 0; + c->queue_serial = queue_serial; + set_clock(c, NAN, -1); +} + +static void sync_clock_to_slave(Clock *c, Clock *slave) +{ + double clock = get_clock(c); + double slave_clock = get_clock(slave); + if (!isnan(slave_clock) && (isnan(clock) || fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD)) + set_clock(c, slave_clock, slave->serial); +} + +static int get_master_sync_type(VideoState *is) { + if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) { + if (is->video_st) + return AV_SYNC_VIDEO_MASTER; + else + return AV_SYNC_AUDIO_MASTER; + } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) { + if (is->audio_st) + return AV_SYNC_AUDIO_MASTER; + else + return AV_SYNC_EXTERNAL_CLOCK; + } else { + return AV_SYNC_EXTERNAL_CLOCK; + } +} + +/* get the current master clock value */ +static double get_master_clock(VideoState *is) +{ + double val; + + switch (get_master_sync_type(is)) { + case AV_SYNC_VIDEO_MASTER: + val = get_clock(&is->vidclk); + break; + case AV_SYNC_AUDIO_MASTER: + val = get_clock(&is->audclk); + break; + default: + val = get_clock(&is->extclk); + break; + } + return val; +} + +static void check_external_clock_speed(VideoState *is) { + if (is->video_stream >= 0 && is->videoq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES || + is->audio_stream >= 0 && is->audioq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES) { + set_clock_speed(&is->extclk, FFMAX(EXTERNAL_CLOCK_SPEED_MIN, is->extclk.speed - EXTERNAL_CLOCK_SPEED_STEP)); + } else if ((is->video_stream < 0 || is->videoq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES) && + (is->audio_stream < 0 || is->audioq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES)) { + set_clock_speed(&is->extclk, FFMIN(EXTERNAL_CLOCK_SPEED_MAX, is->extclk.speed + EXTERNAL_CLOCK_SPEED_STEP)); + } else { + double speed = is->extclk.speed; + if (speed != 1.0) + set_clock_speed(&is->extclk, speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed)); + } +} + +/* pause or resume the video */ +static void stream_toggle_pause(VideoState *is) +{ + if (is->paused) { + is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated; + if (is->read_pause_return != AVERROR(ENOSYS)) { + is->vidclk.paused = 0; + } + set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial); + } + set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial); + is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused; +} + +static void toggle_pause(VideoState *is) +{ + stream_toggle_pause(is); + is->step = 0; +} + +static void step_to_next_frame(VideoState *is) +{ + /* if the stream is paused unpause it, then step */ + if (is->paused) + stream_toggle_pause(is); + is->step = 1; +} + +static double compute_target_delay(double delay, VideoState *is) +{ + double sync_threshold, diff = 0; + + /* update delay to follow master synchronisation source */ + if (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) { + /* if video is slave, we try to correct big delays by + duplicating or deleting a frame */ + diff = get_clock(&is->vidclk) - get_master_clock(is); + + /* skip or repeat frame. We take into account the + delay to compute the threshold. I still don't know + if it is the best guess */ + sync_threshold = FFMAX(AV_SYNC_THRESHOLD_MIN, FFMIN(AV_SYNC_THRESHOLD_MAX, delay)); + if (!isnan(diff) && fabs(diff) < is->max_frame_duration) { + if (diff <= -sync_threshold) + delay = FFMAX(0, delay + diff); + else if (diff >= sync_threshold && delay > AV_SYNC_FRAMEDUP_THRESHOLD) + delay = delay + diff; + else if (diff >= sync_threshold) + delay = 2 * delay; + } + } + + av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f A-V=%f\n", + delay, -diff); + + return delay; +} + +static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) { + if (vp->serial == nextvp->serial) { + double duration = nextvp->pts - vp->pts; + if (isnan(duration) || duration <= 0 || duration > is->max_frame_duration) + return vp->duration; + else + return duration; + } else { + return 0.0; + } +} + +static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial) { + /* update current video pts */ + set_clock(&is->vidclk, pts, serial); + sync_clock_to_slave(&is->extclk, &is->vidclk); +} + +/* called to display each frame */ +static void video_refresh(void *opaque, double *remaining_time) +{ + VideoState *is = (VideoState*) opaque; + double time; + + Frame *sp, *sp2; + + if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime) + check_external_clock_speed(is); + + if (is->video_st) { + retry: + if (frame_queue_nb_remaining(&is->pictq) == 0) { + // nothing to do, no picture to display in the queue + } else { + double last_duration, duration, delay; + Frame *vp, *lastvp; + + /* dequeue the picture */ + lastvp = frame_queue_peek_last(&is->pictq); + vp = frame_queue_peek(&is->pictq); + + if (vp->serial != is->videoq.serial) { + frame_queue_next(&is->pictq); + goto retry; + } + + if (lastvp->serial != vp->serial) + is->frame_timer = av_gettime_relative() / 1000000.0; + + if (is->paused) + goto display; + + /* compute nominal last_duration */ + last_duration = vp_duration(is, lastvp, vp); + delay = compute_target_delay(last_duration, is); + + time= av_gettime_relative()/1000000.0; + if (time < is->frame_timer + delay) { + *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time); + goto display; + } + + is->frame_timer += delay; + if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX) + is->frame_timer = time; + + SDL_LockMutex(is->pictq.mutex); + if (!isnan(vp->pts)) + update_video_pts(is, vp->pts, vp->pos, vp->serial); + SDL_UnlockMutex(is->pictq.mutex); + + if (frame_queue_nb_remaining(&is->pictq) > 1) { + Frame *nextvp = frame_queue_peek_next(&is->pictq); + duration = vp_duration(is, vp, nextvp); + if(!is->step && (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) && time > is->frame_timer + duration){ + is->frame_drops_late++; + frame_queue_next(&is->pictq); + goto retry; + } + } + + frame_queue_next(&is->pictq); + is->force_refresh = 1; + + if (is->step && !is->paused) + stream_toggle_pause(is); + } + display: + /* display picture */ + if (is->force_refresh && is->pictq.rindex_shown) + video_display(is); + } + is->force_refresh = 0; +} + +static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial) +{ + Frame *vp; + +#if defined(DEBUG_SYNC) + printf("frame_type=%c pts=%0.3f\n", + av_get_picture_type_char(src_frame->pict_type), pts); +#endif + + if (!(vp = frame_queue_peek_writable(&is->pictq))) + return -1; + + vp->sar = src_frame->sample_aspect_ratio; + vp->uploaded = 0; + + vp->width = src_frame->width; + vp->height = src_frame->height; + vp->format = src_frame->format; + + vp->pts = pts; + vp->duration = duration; + vp->pos = pos; + vp->serial = serial; + + set_default_window_size(vp->width, vp->height, vp->sar); + + av_frame_move_ref(vp->frame, src_frame); + frame_queue_push(&is->pictq); + return 0; +} + +static int get_video_frame(VideoState *is, AVFrame *frame) +{ + int got_picture; + + if ((got_picture = decoder_decode_frame(&is->viddec, frame)) < 0) + return -1; + + if (got_picture) { + double dpts = NAN; + + if (frame->pts != AV_NOPTS_VALUE) + dpts = av_q2d(is->video_st->time_base) * frame->pts; + + frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame); + + if (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) { + if (frame->pts != AV_NOPTS_VALUE) { + double diff = dpts - get_master_clock(is); + if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD && + diff - is->frame_last_filter_delay < 0 && + is->viddec.pkt_serial == is->vidclk.serial && + is->videoq.nb_packets) { + is->frame_drops_early++; + av_frame_unref(frame); + got_picture = 0; + } + } + } + } + + return got_picture; +} + +static int audio_thread(void *arg) +{ + VideoState *is = (VideoState*) arg; + AVFrame *frame = av_frame_alloc(); + Frame *af; + int got_frame = 0; + AVRational tb; + int ret = 0; + + if (!frame) + return AVERROR(ENOMEM); + + do { + if ((got_frame = decoder_decode_frame(&is->auddec, frame)) < 0) + goto the_end; + + if (got_frame) { + tb = (AVRational){1, frame->sample_rate}; + + if (!(af = frame_queue_peek_writable(&is->sampq))) + goto the_end; + + af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb); + af->pos = frame->pkt_pos; + af->serial = is->auddec.pkt_serial; + af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate}); + + av_frame_move_ref(af->frame, frame); + frame_queue_push(&is->sampq); + } + } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF); +the_end: + av_frame_free(&frame); + return ret; +} + +static int decoder_start(Decoder *d, int (*fn)(void *), const char *thread_name, void* arg) +{ + packet_queue_start(d->queue); + d->decoder_tid = SDL_CreateThread(fn, thread_name, arg); + if (!d->decoder_tid) { + av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + return 0; +} + +static int video_thread(void *arg) +{ + VideoState *is = (VideoState*) arg; + AVFrame *frame = av_frame_alloc(); + double pts; + double duration; + int ret; + AVRational tb = is->video_st->time_base; + AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL); + + if (!frame) { + return AVERROR(ENOMEM); + } + + for (;;) { + ret = get_video_frame(is, frame); + if (ret < 0) + goto the_end; + if (!ret) + continue; + + duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0); + pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb); + ret = queue_picture(is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial); + av_frame_unref(frame); + + if (ret < 0) + goto the_end; + } + the_end: + av_frame_free(&frame); + return 0; +} + +/* ad-turn the wanted number of samples to get better sync if sync_type is video + * or external master clock */ +static int synchronize_audio(VideoState *is, int nb_samples) +{ + int wanted_nb_samples = nb_samples; + + /* if not master, then we try to remove or add samples to correct the clock */ + if (get_master_sync_type(is) != AV_SYNC_AUDIO_MASTER) { + double diff, avg_diff; + int min_nb_samples, max_nb_samples; + + diff = get_clock(&is->audclk) - get_master_clock(is); + + if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) { + is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum; + if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) { + /* not enough measures to have a correct estimate */ + is->audio_diff_avg_count++; + } else { + /* estimate the A-V difference */ + avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef); + + if (fabs(avg_diff) >= is->audio_diff_threshold) { + wanted_nb_samples = nb_samples + (int)(diff * is->audio_src.freq); + min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100)); + max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100)); + wanted_nb_samples = av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples); + } + av_log(NULL, AV_LOG_TRACE, "diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\n", + diff, avg_diff, wanted_nb_samples - nb_samples, + is->audio_clock, is->audio_diff_threshold); + } + } else { + /* too big difference : may be initial PTS errors, so + reset A-V filter */ + is->audio_diff_avg_count = 0; + is->audio_diff_cum = 0; + } + } + + return wanted_nb_samples; +} + +/** + * Decode one audio frame and return its uncompressed size. + * + * The processed audio frame is decoded, converted if required, and + * stored in is->audio_buf, with size in bytes given by the return + * value. + */ +static int audio_decode_frame(VideoState *is) +{ + int data_size, resampled_data_size; + int64_t dec_channel_layout; + av_unused double audio_clock0; + int wanted_nb_samples; + Frame *af; + + if (is->paused) + return -1; + + do { + if (!(af = frame_queue_peek_readable(&is->sampq))) + return -1; + frame_queue_next(&is->sampq); + } while (af->serial != is->audioq.serial); + + data_size = av_samples_get_buffer_size(NULL, af->frame->channels, + af->frame->nb_samples, + (AVSampleFormat) af->frame->format, 1); + + dec_channel_layout = + (af->frame->channel_layout && af->frame->channels == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ? + af->frame->channel_layout : av_get_default_channel_layout(af->frame->channels); + wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples); + + if (af->frame->format != is->audio_src.fmt || + dec_channel_layout != is->audio_src.channel_layout || + af->frame->sample_rate != is->audio_src.freq || + (wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) { + swr_free(&is->swr_ctx); + is->swr_ctx = swr_alloc_set_opts(NULL, + is->audio_tgt.channel_layout, is->audio_tgt.fmt, is->audio_tgt.freq, + dec_channel_layout, (AVSampleFormat) af->frame->format, af->frame->sample_rate, + 0, NULL); + if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) { + av_log(NULL, AV_LOG_ERROR, + "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n", + af->frame->sample_rate, av_get_sample_fmt_name((AVSampleFormat) af->frame->format), af->frame->channels, + is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels); + swr_free(&is->swr_ctx); + return -1; + } + is->audio_src.channel_layout = dec_channel_layout; + is->audio_src.channels = af->frame->channels; + is->audio_src.freq = af->frame->sample_rate; + is->audio_src.fmt = (AVSampleFormat) af->frame->format; + } + + if (is->swr_ctx) { + const uint8_t **in = (const uint8_t **)af->frame->extended_data; + uint8_t **out = &is->audio_buf1; + int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256; + int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0); + int len2; + if (out_size < 0) { + av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n"); + return -1; + } + if (wanted_nb_samples != af->frame->nb_samples) { + if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate, + wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) { + av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n"); + return -1; + } + } + av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size); + if (!is->audio_buf1) + return AVERROR(ENOMEM); + len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples); + if (len2 < 0) { + av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n"); + return -1; + } + if (len2 == out_count) { + av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n"); + if (swr_init(is->swr_ctx) < 0) + swr_free(&is->swr_ctx); + } + is->audio_buf = is->audio_buf1; + resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt); + } else { + is->audio_buf = af->frame->data[0]; + resampled_data_size = data_size; + } + + audio_clock0 = is->audio_clock; + /* update the audio clock with the pts */ + if (!isnan(af->pts)) + is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate; + else + is->audio_clock = NAN; + is->audio_clock_serial = af->serial; +#ifdef DEBUG + { + static double last_clock; + printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n", + is->audio_clock - last_clock, + is->audio_clock, audio_clock0); + last_clock = is->audio_clock; + } +#endif + return resampled_data_size; +} + +/* prepare a new audio buffer */ +static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) +{ + VideoState *is = (VideoState*) opaque; + int audio_size, len1; + + int64_t audio_callback_time = av_gettime_relative(); + + while (len > 0) { + if (is->audio_buf_index >= is->audio_buf_size) { + audio_size = audio_decode_frame(is); + if (audio_size < 0) { + /* if error, just output silence */ + is->audio_buf = NULL; + is->audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE / is->audio_tgt.frame_size * is->audio_tgt.frame_size; + } else { + is->audio_buf_size = audio_size; + } + is->audio_buf_index = 0; + } + len1 = is->audio_buf_size - is->audio_buf_index; + if (len1 > len) + len1 = len; + if (!is->muted && is->audio_buf && is->audio_volume == SDL_MIX_MAXVOLUME) + memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1); + else { + memset(stream, 0, len1); + if (!is->muted && is->audio_buf) + SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume); + } + len -= len1; + stream += len1; + is->audio_buf_index += len1; + } + is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index; + /* Let's assume the audio driver that is used by SDL has two periods. */ + if (!isnan(is->audio_clock)) { + set_clock_at(&is->audclk, is->audio_clock - (double)(2 * is->audio_hw_buf_size + is->audio_write_buf_size) / is->audio_tgt.bytes_per_sec, is->audio_clock_serial, audio_callback_time / 1000000.0); + sync_clock_to_slave(&is->extclk, &is->audclk); + } +} + +static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb_channels, int wanted_sample_rate, struct AudioParams *audio_hw_params) +{ + SDL_AudioSpec wanted_spec, spec; + const char *env; + static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6}; + static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000}; + int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1; + + env = SDL_getenv("SDL_AUDIO_CHANNELS"); + if (env) { + wanted_nb_channels = atoi(env); + wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels); + } + if (!wanted_channel_layout || wanted_nb_channels != av_get_channel_layout_nb_channels(wanted_channel_layout)) { + wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels); + wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX; + } + wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout); + wanted_spec.channels = wanted_nb_channels; + wanted_spec.freq = wanted_sample_rate; + if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) { + av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n"); + return -1; + } + while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq) + next_sample_rate_idx--; + wanted_spec.format = AUDIO_S16SYS; + wanted_spec.silence = 0; + wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC)); + wanted_spec.callback = sdl_audio_callback; + wanted_spec.userdata = opaque; + while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) { + av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n", + wanted_spec.channels, wanted_spec.freq, SDL_GetError()); + wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)]; + if (!wanted_spec.channels) { + wanted_spec.freq = next_sample_rates[next_sample_rate_idx--]; + wanted_spec.channels = wanted_nb_channels; + if (!wanted_spec.freq) { + av_log(NULL, AV_LOG_ERROR, + "No more combinations to try, audio open failed\n"); + return -1; + } + } + wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels); + } + if (spec.format != AUDIO_S16SYS) { + av_log(NULL, AV_LOG_ERROR, + "SDL advised audio format %d is not supported!\n", spec.format); + return -1; + } + if (spec.channels != wanted_spec.channels) { + wanted_channel_layout = av_get_default_channel_layout(spec.channels); + if (!wanted_channel_layout) { + av_log(NULL, AV_LOG_ERROR, + "SDL advised channel count %d is not supported!\n", spec.channels); + return -1; + } + } + + audio_hw_params->fmt = AV_SAMPLE_FMT_S16; + audio_hw_params->freq = spec.freq; + audio_hw_params->channel_layout = wanted_channel_layout; + audio_hw_params->channels = spec.channels; + audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->channels, 1, audio_hw_params->fmt, 1); + audio_hw_params->bytes_per_sec = av_samples_get_buffer_size(NULL, audio_hw_params->channels, audio_hw_params->freq, audio_hw_params->fmt, 1); + if (audio_hw_params->bytes_per_sec <= 0 || audio_hw_params->frame_size <= 0) { + av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n"); + return -1; + } + return spec.size; +} + +/* open a given stream. Return 0 if OK */ +static int stream_component_open(VideoState *is, int stream_index) +{ + AVFormatContext *ic = is->ic; + AVCodecContext *avctx; + AVCodec *codec; + AVDictionary *opts = NULL; + AVDictionaryEntry *t = NULL; + int sample_rate, nb_channels; + int64_t channel_layout; + int ret = 0; + + if (stream_index < 0 || stream_index >= ic->nb_streams) + return -1; + + avctx = avcodec_alloc_context3(NULL); + if (!avctx) + return AVERROR(ENOMEM); + + ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar); + if (ret < 0) + goto fail; + av_codec_set_pkt_timebase(avctx, ic->streams[stream_index]->time_base); + + codec = avcodec_find_decoder(avctx->codec_id); + + if (!codec) { + av_log(NULL, AV_LOG_WARNING, + "No codec could be found with id %d\n", avctx->codec_id); + ret = AVERROR(EINVAL); + goto fail; + } + + avctx->codec_id = codec->id; +#if FF_API_EMU_EDGE + if(codec->capabilities & AV_CODEC_CAP_DR1) + avctx->flags |= CODEC_FLAG_EMU_EDGE; +#endif + + if ((ret = avcodec_open2(avctx, codec, NULL)) < 0) { + goto fail; + } + + is->eof = 0; + ic->streams[stream_index]->discard = AVDISCARD_DEFAULT; + switch (avctx->codec_type) { + case AVMEDIA_TYPE_AUDIO: + sample_rate = avctx->sample_rate; + nb_channels = avctx->channels; + channel_layout = avctx->channel_layout; + + /* prepare audio output */ + if ((ret = audio_open(is, channel_layout, nb_channels, sample_rate, &is->audio_tgt)) < 0) + goto fail; + is->audio_hw_buf_size = ret; + is->audio_src = is->audio_tgt; + is->audio_buf_size = 0; + is->audio_buf_index = 0; + + /* init averaging filter */ + is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB); + is->audio_diff_avg_count = 0; + /* since we do not have a precise anough audio FIFO fullness, + we correct audio sync only if larger than this threshold */ + is->audio_diff_threshold = (double)(is->audio_hw_buf_size) / is->audio_tgt.bytes_per_sec; + + is->audio_stream = stream_index; + is->audio_st = ic->streams[stream_index]; + + decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread); + if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) && !is->ic->iformat->read_seek) { + is->auddec.start_pts = is->audio_st->start_time; + is->auddec.start_pts_tb = is->audio_st->time_base; + } + if ((ret = decoder_start(&is->auddec, audio_thread, "audio_decoder", is)) < 0) + goto out; + SDL_PauseAudioDevice(audio_dev, 0); + break; + case AVMEDIA_TYPE_VIDEO: + is->video_stream = stream_index; + is->video_st = ic->streams[stream_index]; + + decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread); + if ((ret = decoder_start(&is->viddec, video_thread, "video_decoder", is)) < 0) + goto out; + is->queue_attachments_req = 1; + break; + default: + break; + } + goto out; + +fail: + avcodec_free_context(&avctx); +out: + av_dict_free(&opts); + + return ret; +} + +static int decode_interrupt_cb(void *ctx) +{ + VideoState *is = (VideoState*) ctx; + return is->abort_request; +} + +static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue) { + return stream_id < 0 || + queue->abort_request || + (st->disposition & AV_DISPOSITION_ATTACHED_PIC) || + queue->nb_packets > MIN_FRAMES && (!queue->duration || av_q2d(st->time_base) * queue->duration > 1.0); +} + +static int is_realtime(AVFormatContext *s) +{ + if( !strcmp(s->iformat->name, "rtp") + || !strcmp(s->iformat->name, "rtsp") + || !strcmp(s->iformat->name, "sdp") + ) + return 1; + + if(s->pb && ( !strncmp(s->filename, "rtp:", 4) + || !strncmp(s->filename, "udp:", 4) + ) + ) + return 1; + return 0; +} + +void print_error(const char *filename, int err) +{ + char errbuf[128]; + const char *errbuf_ptr = errbuf; + + if (av_strerror(err, errbuf, sizeof(errbuf)) < 0) + errbuf_ptr = strerror(AVUNERROR(err)); + av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr); +} + +/* this thread gets the stream from the disk or the network */ +static int read_thread(void *arg) +{ + VideoState *is = (VideoState*)arg; + AVFormatContext *ic = NULL; + int err, i, ret; + int st_index[AVMEDIA_TYPE_NB]; + AVPacket pkt1, *pkt = &pkt1; + int64_t stream_start_time; + AVDictionaryEntry *t; + SDL_mutex *wait_mutex = SDL_CreateMutex(); + int scan_all_pmts_set = 0; + int64_t pkt_ts; + + if (!wait_mutex) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); + ret = AVERROR(ENOMEM); + goto fail; + } + + memset(st_index, -1, sizeof(st_index)); + is->video_stream = -1; + is->audio_stream = -1; + is->eof = 0; + + ic = avformat_alloc_context(); + if (!ic) { + av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + ic->interrupt_callback.callback = decode_interrupt_cb; + ic->interrupt_callback.opaque = is; + + err = avformat_open_input(&ic, is->filename, NULL, NULL); + if (err < 0) { + print_error(is->filename, err); + ret = -1; + goto fail; + } + is->ic = ic; + + av_format_inject_global_side_data(ic); + + if (ic->pb) + ic->pb->eof_reached = 0; + + is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0; + + is->realtime = is_realtime(ic); + + st_index[AVMEDIA_TYPE_VIDEO] = + av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, + st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0); + st_index[AVMEDIA_TYPE_AUDIO] = + av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, + st_index[AVMEDIA_TYPE_AUDIO], + st_index[AVMEDIA_TYPE_VIDEO], + NULL, 0); + if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) { + AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]]; + AVCodecParameters *codecpar = st->codecpar; + AVRational sar = av_guess_sample_aspect_ratio(ic, st, NULL); + if (codecpar->width) + set_default_window_size(codecpar->width, codecpar->height, sar); + } + + /* open the streams */ + if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) { + stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]); + } + + ret = -1; + if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) { + ret = stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]); + } + + if (is->video_stream < 0 && is->audio_stream < 0) { + av_log(NULL, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n", + is->filename); + ret = -1; + goto fail; + } + + if (infinite_buffer < 0 && is->realtime) + infinite_buffer = 1; + + for (;;) { + if (is->abort_request) + break; + if (is->paused != is->last_paused) { + is->last_paused = is->paused; + if (is->paused) + is->read_pause_return = av_read_pause(ic); + else + av_read_play(ic); + } + if (is->queue_attachments_req) { + if (is->video_st && is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC) { + AVPacket copy = { 0 }; + if ((ret = av_packet_ref(©, &is->video_st->attached_pic)) < 0) + goto fail; + packet_queue_put(&is->videoq, ©); + packet_queue_put_nullpacket(&is->videoq, is->video_stream); + } + is->queue_attachments_req = 0; + } + + /* if the queue are full, no need to read more */ + if (infinite_buffer<1 && + (is->audioq.size + is->videoq.size > MAX_QUEUE_SIZE + || (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq) && + stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq)))) { + /* wait 10 ms */ + SDL_LockMutex(wait_mutex); + SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10); + SDL_UnlockMutex(wait_mutex); + continue; + } + if (!is->paused && + (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) && + (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) { + if (autoexit) { + ret = AVERROR_EOF; + goto fail; + } + } + ret = av_read_frame(ic, pkt); + if (ret < 0) { + if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) { + if (is->video_stream >= 0) + packet_queue_put_nullpacket(&is->videoq, is->video_stream); + if (is->audio_stream >= 0) + packet_queue_put_nullpacket(&is->audioq, is->audio_stream); + is->eof = 1; + } + if (ic->pb && ic->pb->error) + break; + SDL_LockMutex(wait_mutex); + SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10); + SDL_UnlockMutex(wait_mutex); + continue; + } else { + is->eof = 0; + } + /* check if packet is in play range specified by user, then queue, otherwise discard */ + stream_start_time = ic->streams[pkt->stream_index]->start_time; + pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts; + if (pkt->stream_index == is->audio_stream) { + packet_queue_put(&is->audioq, pkt); + } else if (pkt->stream_index == is->video_stream + && !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) { + packet_queue_put(&is->videoq, pkt); + } else { + av_packet_unref(pkt); + } + } + + ret = 0; +fail: + if (ic && !is->ic) + avformat_close_input(&ic); + + if (ret != 0) { + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); + } + SDL_DestroyMutex(wait_mutex); + return 0; +} + +static VideoState *stream_open(const char *filename, int startup_volume) +{ + VideoState *is; + + is = (VideoState *) av_mallocz(sizeof(VideoState)); + if (!is) + return NULL; + is->filename = av_strdup(filename); + if (!is->filename) + goto fail; + is->ytop = 0; + is->xleft = 0; + + /* start video display */ + if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0) + goto fail; + if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0) + goto fail; + + if (packet_queue_init(&is->videoq) < 0 || + packet_queue_init(&is->audioq) < 0) + goto fail; + + if (!(is->continue_read_thread = SDL_CreateCond())) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError()); + goto fail; + } + + init_clock(&is->vidclk, &is->videoq.serial); + init_clock(&is->audclk, &is->audioq.serial); + init_clock(&is->extclk, &is->extclk.serial); + is->audio_clock_serial = -1; + if (startup_volume < 0) + av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume); + if (startup_volume > 100) + av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume); + startup_volume = av_clip(startup_volume, 0, 100); + startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME); + is->audio_volume = startup_volume; + is->muted = 0; + is->av_sync_type = av_sync_type; + return is; +fail: + stream_close(is); + return NULL; + +} + +static void toggle_full_screen(VideoState *is) +{ +#if defined(MOVIE_RESIZABLE_WINDOW) + is_full_screen = !is_full_screen; + SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); +#endif +} + +static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) { + double remaining_time = 0.0; + SDL_PumpEvents(); + while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) { + if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) { + SDL_ShowCursor(0); + cursor_hidden = 1; + } + if (remaining_time > 0.0) + av_usleep((int64_t)(remaining_time * 1000000.0)); + remaining_time = REFRESH_RATE; + if (!is->paused || is->force_refresh) + video_refresh(is, &remaining_time); + SDL_PumpEvents(); + } +} + +#else // USE_SDL_FFMPEG + +struct VideoState { +}; + +#endif // USE_SDL_FFMPEG + +aui_SDLMovie::aui_SDLMovie(AUI_ERRCODE *retval, const MBCHAR * filename) : + aui_Movie(), + m_videoState(NULL), + m_renderer(NULL), + m_windowWidth(0), + m_windowHeight(0), + m_logicalWidth(0), + m_logicalHeight(0), + m_cursorSurface(NULL), + m_cursor(NULL) +{ + strncpy(m_filename, filename, sizeof(m_filename)); + m_filename[MAX_PATH] = '\0'; + *retval = AUI_ERRCODE_OK; +} + +aui_SDLMovie::~aui_SDLMovie() { + Assert(!m_videoState); + m_renderer = NULL; +} + +void aui_SDLMovie::SetContext(SDL_Renderer *renderer, const int windowWidth, const int windowHeight, + SDL_Surface* cursorSurface) { + Assert(renderer); + m_renderer = renderer; + m_windowWidth = windowWidth; + m_windowHeight = windowHeight; + m_cursorSurface = cursorSurface; +} + +AUI_ERRCODE aui_SDLMovie::Load() { + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMovie::Unload() { + return Close(); +} + +AUI_ERRCODE aui_SDLMovie::Open(uint32 flags, aui_Surface *surface, RECT *rect) { + +#if defined(USE_SDL_FFMPEG) + if (!m_renderer) { + return AUI_ERRCODE_MOVIEFAILED; + } + + av_init_packet(&flush_pkt); + flush_pkt.data = (uint8_t *)&flush_pkt; + + static SDL_RendererInfo renderer_info = {0}; + SDL_GetRendererInfo(m_renderer, &renderer_info); + if (!renderer_info.num_texture_formats) { + av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError()); + Close(); + return AUI_ERRCODE_MOVIEFAILED; + } + + if (m_cursorSurface) { + m_cursor = SDL_CreateColorCursor(m_cursorSurface, 0, 0); + if (m_cursor) { + SDL_SetCursor(m_cursor); + } + } + + renderer = m_renderer; + screen_width = m_windowWidth; + screen_height = m_windowHeight; + SDL_RenderGetLogicalSize(renderer, &m_logicalWidth, &m_logicalHeight); + SDL_RenderSetLogicalSize(renderer, m_windowWidth, m_windowHeight); + autoexit = !(flags & k_AUI_MOVIE_PLAYFLAG_PLAYANDHOLD); + + // Adjust volume range ctp2 [0..10] -> ffmpeg [0..100] + m_videoState = stream_open(m_filename, g_theProfileDB->GetSFXVolume() * 10); + return m_videoState ? AUI_ERRCODE_OK : AUI_ERRCODE_MOVIEFAILED; +#else // USE_SDL_FFMPEG + return AUI_ERRCODE_OK; +#endif // USE_SDL_FFMPEG +} + +AUI_ERRCODE aui_SDLMovie::Close() { + +#if defined(USE_SDL_FFMPEG) + // Reset cursor + if (m_cursor) { + SDL_SetCursor(NULL); + SDL_FreeCursor(m_cursor); + m_cursor = NULL; + } + SDL_ShowCursor(SDL_DISABLE); + if (m_videoState) { + Stop(); + stream_close(m_videoState); + m_videoState = NULL; + } + renderer = NULL; + SDL_RenderSetLogicalSize(m_renderer, m_logicalWidth, m_logicalHeight); + m_isFinished = TRUE; +#endif // USE_SDL_FFMPEG + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMovie::Play() { + +#if defined(USE_SDL_FFMPEG) + if (m_videoState) { + m_videoState->read_tid = SDL_CreateThread(read_thread, "read_thread", m_videoState); + if (!m_videoState->read_tid) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError()); + Stop(); + return AUI_ERRCODE_MOVIEFAILED; + } + } +#endif // USE_SDL_FFMPEG + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMovie::Stop() { + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMovie::Pause() { + +#if defined(USE_SDL_FFMPEG) + if (m_videoState && !m_videoState->paused) { + toggle_pause(m_videoState); + } +#endif // USE_SDL_FFMPEG + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMovie::Resume() { + +#if defined(USE_SDL_FFMPEG) + if (m_videoState && m_videoState->paused) { + toggle_pause(m_videoState); + } +#endif // USE_SDL_FFMPEG +} + +AUI_ERRCODE aui_SDLMovie::Process() { + +#if defined(USE_SDL_FFMPEG) + if (m_videoState) { + /* handle an event sent by the GUI */ + SDL_Event event; + + BOOL done = FALSE; + while (!done) { + double x; + refresh_loop_wait_event(m_videoState, &event); + switch (event.type) { + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_SPACE + || event.key.keysym.sym == SDLK_q) { + done = TRUE; + break; + } + // If we don't yet have a window, skip all key events, because read_thread might still be initializing... + if (!m_videoState->width) + continue; + switch (event.key.keysym.sym) { + #if defined(MOVIE_RESIZABLE_WINDOW) + case SDLK_f: + toggle_full_screen(m_videoState); + m_videoState->force_refresh = 1; + break; + #endif + case SDLK_p: + toggle_pause(m_videoState); + break; + default: + break; + } + break; + case SDL_MOUSEMOTION: + if (cursor_hidden) { + SDL_ShowCursor(1); + cursor_hidden = 0; + } else { + if (event.motion.type & SDL_BUTTON_LMASK != 0) { + done = TRUE; + } + } + cursor_last_shown = av_gettime_relative(); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + done = TRUE; + break; + case SDL_WINDOWEVENT: + switch (event.window.event) { + case SDL_WINDOWEVENT_RESIZED: + screen_width = m_videoState->width = event.window.data1; + screen_height = m_videoState->height = event.window.data2; + if (m_videoState->vis_texture) { + SDL_DestroyTexture(m_videoState->vis_texture); + m_videoState->vis_texture = NULL; + } + case SDL_WINDOWEVENT_EXPOSED: + m_videoState->force_refresh = 1; + } + break; + case SDL_QUIT: + done = TRUE; + break; + default: + break; + } + } + Close(); + } +#endif // USE_SDL_FFMPEG +} + +BOOL aui_SDLMovie::IsOpen() const { + return m_videoState != NULL; +} + +BOOL aui_SDLMovie::IsPlaying() const { +#if defined(USE_SDL_FFMPEG) + return m_videoState && m_videoState->read_tid != NULL; +#else // USE_SDL_FFMPEG + return FALSE; +#endif // USE_SDL_FFMPEG +} + +BOOL aui_SDLMovie::IsPaused() const { + +#if defined(USE_SDL_FFMPEG) + return m_videoState && m_videoState->paused; +#else // USE_SDL_FFMPEG + return FALSE; +#endif // USE_SDL_FFMPEG +} + +#endif // defined(__AUI_USE_SDL__) diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmovie.h b/ctp2_code/ui/aui_sdl/aui_sdlmovie.h new file mode 100644 index 000000000..7a109249c --- /dev/null +++ b/ctp2_code/ui/aui_sdl/aui_sdlmovie.h @@ -0,0 +1,56 @@ +#ifdef HAVE_PRAGMA_ONCE +#pragma once +#endif + +#ifndef __aui_sdl__aui_sdlmovie_h__ +#define __aui_sdl__aui_sdlmovie_h__ 1 + +#include "ctp2_config.h" +#include "aui_movie.h" + +#if defined(__AUI_USE_SDL__) + +class VideoState; +class SDL_Renderer; +class SDL_Surface; +class SDL_Cursor; +class aui_SDLMovie : public aui_Movie { +public: + aui_SDLMovie(AUI_ERRCODE *retval, const MBCHAR * filename = NULL); + virtual ~aui_SDLMovie(); + + void SetContext(SDL_Renderer *renderer, const int windowWidth, const int windowHeight, SDL_Surface *cursorSurface); + + virtual AUI_ERRCODE Load(); + virtual AUI_ERRCODE Unload(); + + virtual AUI_ERRCODE Open(uint32 flags = 0, aui_Surface *surface = NULL, RECT *rect = NULL); + virtual AUI_ERRCODE Close(); + + virtual AUI_ERRCODE Play(); + virtual AUI_ERRCODE Stop(); + + virtual AUI_ERRCODE Pause(); + virtual AUI_ERRCODE Resume(); + + virtual AUI_ERRCODE Process(); + + virtual BOOL IsOpen() const; + virtual BOOL IsPlaying() const; + virtual BOOL IsPaused() const; + +private: + VideoState *m_videoState; + + SDL_Renderer *m_renderer; + int m_windowWidth; + int m_windowHeight; + int m_logicalWidth; + int m_logicalHeight; + SDL_Surface *m_cursorSurface; + SDL_Cursor *m_cursor; +}; + +#endif // defined(__AUI_USE_SDL__) + +#endif diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp new file mode 100644 index 000000000..8c06a3cba --- /dev/null +++ b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp @@ -0,0 +1,68 @@ +#include "c3.h" +#include "aui_sdlmoviemanager.h" + +#if defined(__AUI_USE_SDL__) + +#include "aui_sdlmovie.h" + +#if defined(USE_SDL_FFMPEG) +#include +extern "C" { + #include +} + +static int lockmgr(void **mtx, enum AVLockOp op) +{ + switch(op) { + case AV_LOCK_CREATE: + *mtx = SDL_CreateMutex(); + if(!*mtx) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); + return 1; + } + return 0; + case AV_LOCK_OBTAIN: + return !!SDL_LockMutex((SDL_mutex*) *mtx); + case AV_LOCK_RELEASE: + return !!SDL_UnlockMutex((SDL_mutex*) *mtx); + case AV_LOCK_DESTROY: + SDL_DestroyMutex((SDL_mutex*) *mtx); + return 0; + } + return 1; +} +#endif // USE_SDL_FFMPEG + +aui_SDLMovieManager::aui_SDLMovieManager(SDL_Renderer *renderer, const int windowWidth, const int windowHeight, + SDL_Surface *mouseSurface) : + aui_MovieManager(false), + m_renderer(renderer), + m_windowWidth(windowWidth), + m_windowHeight(windowHeight), + m_mouseSurface(mouseSurface) +{ + Assert(m_renderer); + m_movieResource = new aui_Resource(); + +#if defined(USE_SDL_FFMPEG) + av_register_all(); + if (av_lockmgr_register(lockmgr)) { + av_log(NULL, AV_LOG_FATAL, "Could not initialize lock manager!\n"); + } +#endif // USE_SDL_FFMPEG +} + +aui_SDLMovieManager::~aui_SDLMovieManager() { + delete m_movieResource; +#if defined(USE_SDL_FFMPEG) + av_lockmgr_register(NULL); +#endif // USE_SDL_FFMPEG +} + +aui_Movie* aui_SDLMovieManager::Load(const MBCHAR *filename, C3DIR dir) { + aui_SDLMovie *movie = m_movieResource->Load(filename, dir); + movie->SetContext(m_renderer, m_windowWidth, m_windowHeight, m_mouseSurface); + return movie; +} + +#endif // defined(__AUI_USE_SDL__) \ No newline at end of file diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h new file mode 100644 index 000000000..0bed0aad7 --- /dev/null +++ b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h @@ -0,0 +1,45 @@ +#ifdef HAVE_PRAGMA_ONCE +#pragma once +#endif + +#ifndef __aui_sdl__aui_sdlmoviemanager_h__ +#define __aui_sdl__aui_sdlmoviemanager_h__ 1 + +#include "ctp2_config.h" +#include "aui_moviemanager.h" + +#if defined(__AUI_USE_SDL__) + +#include "aui_sdlmovie.h" +#include + +class aui_SDLMovieManager : public aui_MovieManager { +public: + aui_SDLMovieManager(SDL_Renderer *sdlRenderer, const int windowWidth, const int windowHeight, + SDL_Surface *mouseSurface); + virtual ~aui_SDLMovieManager(); + + virtual aui_Movie *Load(const MBCHAR *filename, C3DIR dir = C3DIR_DIRECT); + + virtual AUI_ERRCODE Unload( aui_Movie *movie ) + { return m_movieResource->Unload((aui_SDLMovie*)movie); } + virtual AUI_ERRCODE Unload( const MBCHAR *movie ) + { return m_movieResource->Unload(movie); } + + virtual AUI_ERRCODE AddSearchPath(const MBCHAR *path) + { return m_movieResource->AddSearchPath(path); } + virtual AUI_ERRCODE RemoveSearchPath(const MBCHAR *path) + { return m_movieResource->RemoveSearchPath(path); } + +private: + aui_Resource *m_movieResource; + + SDL_Renderer *m_renderer; + int m_windowWidth; + int m_windowHeight; + SDL_Surface *m_mouseSurface; +}; + +#endif // defined(__AUI_USE_SDL__) + +#endif diff --git a/ctp2_code/ui/aui_sdl/aui_sdlsurface.h b/ctp2_code/ui/aui_sdl/aui_sdlsurface.h index 1bf3eeb1e..0081c1ca3 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlsurface.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlsurface.h @@ -56,6 +56,7 @@ class aui_SDLSurface : public aui_Surface, public aui_SDL { SDL_mutex* m_bltMutex; + SDL_Surface* GetSDLSurface() { return m_lpdds; } protected: SDL_Surface* m_lpdds; diff --git a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp index aa4a9ed8c..35073da81 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp @@ -38,6 +38,7 @@ #include "aui_joystick.h" #include "aui_sdlsurface.h" #include "aui_sdlmouse.h" +#include "aui_sdlmoviemanager.h" #include "aui_sdlui.h" @@ -70,6 +71,7 @@ aui_SDLUI::aui_SDLUI : aui_UI (), aui_SDL (), m_X11Display (0), + m_SDLWindow (0), m_SDLRenderer (0), m_SDLTexture (0) { @@ -138,15 +140,17 @@ AUI_ERRCODE aui_SDLUI::CreateNativeScreen( BOOL useExclusiveMode ) if ( !AUI_SUCCESS(errcode) ) return errcode; m_pixelFormat = aui_Surface::TransformBppToSurfacePixelFormat(m_bpp); - SDL_Window *sdlWindow = SDL_CreateWindow("Call To Power 2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + m_SDLWindow = SDL_CreateWindow("Call To Power 2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_width, m_height, g_SDL_flags); - if (!sdlWindow) { + if (!m_SDLWindow) { c3errors_FatalDialog("aui_SDLUI", "SDL window creation failed:\n%s\n", SDL_GetError()); } - m_SDLRenderer = SDL_CreateRenderer(sdlWindow, -1, 0); + m_SDLRenderer = SDL_CreateRenderer(m_SDLWindow, -1, 0); if (!m_SDLRenderer) { c3errors_FatalDialog("aui_SDLUI", "SDL renderer creation failed:\n%s\n", SDL_GetError()); } + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + SDL_RenderSetLogicalSize(m_SDLRenderer, m_width, m_height); m_SDLTexture = SDL_CreateTexture(m_SDLRenderer, aui_SDLSurface::TransformSurfacePixelFormatToSDL(m_pixelFormat), SDL_TEXTUREACCESS_STREAMING, m_width, m_height); if (!m_SDLTexture) { @@ -186,6 +190,18 @@ aui_SDLUI::~aui_SDLUI( void ) m_X11Display = 0; } #endif + if (m_SDLTexture) { + SDL_DestroyTexture(m_SDLTexture); + m_SDLTexture = NULL; + } + if (m_SDLRenderer) { + SDL_DestroyRenderer(m_SDLRenderer); + m_SDLRenderer = NULL; + } + if (m_SDLWindow) { + SDL_DestroyWindow(m_SDLWindow); + m_SDLWindow = NULL; + } } AUI_ERRCODE aui_SDLUI::TearDownMouse(void) @@ -330,6 +346,19 @@ AUI_ERRCODE aui_SDLUI::AltTabIn( void ) return FlushDirtyList(); } +aui_MovieManager* aui_SDLUI::CreateMovieManager( void ) { + Assert(m_SDLWindow); + Assert(m_SDLRenderer); + int windowWidth; + int windowHeight; + SDL_GetWindowSize(m_SDLWindow, &windowWidth, &windowHeight); + + aui_Surface *cursorSurface = m_mouse->GetCurrentCursor()->TheSurface(); + aui_SDLSurface *sdlCursorSurface = dynamic_cast(cursorSurface); + return new aui_SDLMovieManager(m_SDLRenderer, windowWidth, windowHeight, + sdlCursorSurface ? sdlCursorSurface->GetSDLSurface() : NULL); +} + AUI_ERRCODE aui_SDLUI::SDLDrawScreen( void ) { Assert(m_primary); Assert(m_SDLTexture); diff --git a/ctp2_code/ui/aui_sdl/aui_sdlui.h b/ctp2_code/ui/aui_sdl/aui_sdlui.h index df2f14397..876fd8ab1 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlui.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlui.h @@ -76,12 +76,14 @@ class aui_SDLUI : public aui_UI, public aui_SDL Display *getDisplay(); #endif + aui_MovieManager* CreateMovieManager( void ); protected: virtual AUI_ERRCODE SDLDrawScreen( void ); #if defined(HAVE_X11) Display * m_X11Display; #endif + SDL_Window *m_SDLWindow; SDL_Surface *m_SDLSurface; SDL_Renderer *m_SDLRenderer; SDL_Texture *m_SDLTexture; From af084f2498662befe6ba86c4929876aa2db46897 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Thu, 16 Apr 2020 23:30:57 +0200 Subject: [PATCH 16/29] Use SDL2 cursor to render cursor. --- ctp2_code/ui/aui_common/aui_mouse.cpp | 9 +- ctp2_code/ui/aui_common/aui_mouse.h | 15 +- ctp2_code/ui/aui_sdl/aui_sdl.cpp | 1 - ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp | 186 ++++++++++++++++++- ctp2_code/ui/aui_sdl/aui_sdlmouse.h | 16 ++ ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp | 23 +-- ctp2_code/ui/aui_sdl/aui_sdlmovie.h | 4 +- ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp | 10 +- ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h | 4 +- ctp2_code/ui/aui_sdl/aui_sdlui.cpp | 6 +- 10 files changed, 225 insertions(+), 49 deletions(-) diff --git a/ctp2_code/ui/aui_common/aui_mouse.cpp b/ctp2_code/ui/aui_common/aui_mouse.cpp index 4ca9458e3..fc90207b4 100644 --- a/ctp2_code/ui/aui_common/aui_mouse.cpp +++ b/ctp2_code/ui/aui_common/aui_mouse.cpp @@ -243,6 +243,7 @@ AUI_ERRCODE aui_Mouse::InitCommonLdl( const MBCHAR *ldlBlock ) m_animDelayList.AddTail( blk->GetInt( k_MOUSE_LDL_ANIMDELAY ) ); } } + ActivateCursor(*m_curCursor); return AUI_ERRCODE_OK; } @@ -357,6 +358,7 @@ void aui_Mouse::SetCurrentCursor( sint32 index ) if ( index < m_firstIndex || index > m_lastIndex ) return; m_curCursor = m_cursors + index; + ActivateCursor(*m_curCursor); } sint32 aui_Mouse::GetCurrentCursorIndex(void) @@ -408,6 +410,7 @@ AUI_ERRCODE aui_Mouse::Start( void ) #endif m_curCursor = m_cursors + m_firstIndex; + ActivateCursor(*m_curCursor); if ( m_thread ) { @@ -889,8 +892,10 @@ AUI_ERRCODE aui_Mouse::HandleAnim( void ) if ( m_lastIndex >= m_firstIndex ) { - if(m_curCursor < m_cursors + m_firstIndex) + if(m_curCursor < m_cursors + m_firstIndex) { m_curCursor = m_cursors + m_firstIndex; + ActivateCursor(*m_curCursor); + } uint32 now = GetTickCount(); if ( now - m_time > m_animDelay ) @@ -898,7 +903,7 @@ AUI_ERRCODE aui_Mouse::HandleAnim( void ) if ( m_curCursor++ >= m_cursors + m_lastIndex ) m_curCursor = m_cursors + m_firstIndex; - + ActivateCursor(*m_curCursor); m_time = now; return AUI_ERRCODE_HANDLED; diff --git a/ctp2_code/ui/aui_common/aui_mouse.h b/ctp2_code/ui/aui_common/aui_mouse.h index af9e89466..3bf97aa63 100644 --- a/ctp2_code/ui/aui_common/aui_mouse.h +++ b/ctp2_code/ui/aui_common/aui_mouse.h @@ -24,7 +24,7 @@ // Modifications from the original Activision code: // // - Increased k_MOUSE_MAXNUMCURSORS to allow some additional cursors. -// - April 30th 2005 Martin Gühmann +// - April 30th 2005 Martin Gühmann // //---------------------------------------------------------------------------- @@ -178,12 +178,12 @@ class aui_Mouse : public aui_Base, public virtual aui_Input AUI_ERRCODE HandleAnim( void ); - AUI_ERRCODE BltWindowToPrimary( aui_Window *window ); - AUI_ERRCODE BltDirtyRectInfoToPrimary( void ); - AUI_ERRCODE BltBackgroundColorToPrimary( + virtual AUI_ERRCODE BltWindowToPrimary( aui_Window *window ); + virtual AUI_ERRCODE BltDirtyRectInfoToPrimary( void ); + virtual AUI_ERRCODE BltBackgroundColorToPrimary( COLORREF color, aui_DirtyList *colorAreas ); - AUI_ERRCODE BltBackgroundImageToPrimary( + virtual AUI_ERRCODE BltBackgroundImageToPrimary( aui_Image *image, RECT *imageRect, aui_DirtyList *imageAreas ); @@ -194,8 +194,8 @@ class aui_Mouse : public aui_Base, public virtual aui_Input LPCRITICAL_SECTION LPCS( void ) const { return m_lpcs; } #endif - AUI_ERRCODE CreatePrivateBuffers( void ); - void DestroyPrivateBuffers( void ); + virtual AUI_ERRCODE CreatePrivateBuffers( void ); + virtual void DestroyPrivateBuffers( void ); uint32 GetFlags(void) { return m_flags;} void SetFlags(uint32 flags) { m_flags = flags; } @@ -207,6 +207,7 @@ class aui_Mouse : public aui_Base, public virtual aui_Input #else static LPCRITICAL_SECTION m_lpcs; #endif + virtual void ActivateCursor(aui_Cursor *cursor) {} virtual AUI_ERRCODE Erase( void ); diff --git a/ctp2_code/ui/aui_sdl/aui_sdl.cpp b/ctp2_code/ui/aui_sdl/aui_sdl.cpp index 1dfc3c578..fe679e28b 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdl.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdl.cpp @@ -49,7 +49,6 @@ AUI_ERRCODE aui_SDL::InitCommon(BOOL useExclusiveMode) return AUI_ERRCODE_CREATEFAILED; } */ - SDL_ShowCursor(SDL_DISABLE); SDL_SetEventFilter(FilterEvents, NULL); diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp index 65cd4fb8d..e2f797ccd 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp @@ -3,6 +3,7 @@ #ifdef __AUI_USE_SDL__ +#include "aui_ui.h" #include "aui_sdlmouse.h" #include "ctp2_listbox.h" @@ -10,6 +11,10 @@ #include "aui_ranger.h" #include "civapp.h" +#include "aui_sdlsurface.h" + +#include "profileDB.h" + extern CivApp *g_civApp; // SKIP_SDL2_EVENT_ISSUES: TODO: scrolling with mouse (screen sides) is too fast to be useful @@ -21,7 +26,8 @@ aui_SDLMouse::aui_SDLMouse( : aui_Input(), aui_Mouse(retval, ldlBlock), - aui_SDLInput(retval, useExclusiveMode) + aui_SDLInput(retval, useExclusiveMode), + m_currentCursor(NULL) { Assert(AUI_SUCCESS(*retval)); if (!AUI_SUCCESS(*retval)) return; @@ -29,6 +35,7 @@ aui_SDLMouse::aui_SDLMouse( aui_SDLMouse::~aui_SDLMouse() { + End(); } void HandleMouseWheel(sint16 delta) @@ -102,7 +109,7 @@ aui_SDLMouse::GetInput(void) } break; default: - printf("event not handeled: %d\n", od[ev].type); + printf("event not handled: %d\n", od[ev].type); break; } ev++; @@ -110,4 +117,179 @@ aui_SDLMouse::GetInput(void) return AUI_ERRCODE_OK; } +void aui_SDLMouse::ActivateCursor(aui_Cursor *cursor) +{ + if (cursor != m_currentCursor) { + aui_Surface *cursorSurface = cursor->TheSurface(); + aui_SDLSurface *sdlCursorSurface = dynamic_cast(cursorSurface); + if (sdlCursorSurface != NULL) { + POINT hotspot; + cursor->GetHotspot(hotspot); + SDL_Cursor *sdlCursor = SDL_CreateColorCursor(sdlCursorSurface->GetSDLSurface(), hotspot.x, hotspot.y); + if (sdlCursor != NULL) { + SDL_Cursor *currentSDLCursor = SDL_GetCursor(); + SDL_SetCursor(sdlCursor); + if (currentSDLCursor) { + SDL_FreeCursor(currentSDLCursor); + } + m_currentCursor = cursor; + } + } + } +} + +AUI_ERRCODE aui_SDLMouse::BltWindowToPrimary(aui_Window *window) +{ + AUI_ERRCODE retcode = AUI_ERRCODE_OK; + + sint32 windowX = window->X(); + sint32 windowY = window->Y(); + aui_Surface *windowSurface = window->TheSurface(); + aui_DirtyList *windowDirtyList = window->GetDirtyList(); + + ListPos position = windowDirtyList->GetHeadPosition(); + for (sint32 j = windowDirtyList->L(); j; j--) + { + RECT *windowDirtyRect = windowDirtyList->GetNext(position); + + RECT screenDirtyRect = *windowDirtyRect; + OffsetRect(&screenDirtyRect, windowX, windowY); + + AUI_ERRCODE errcode = g_ui->BltToSecondary( + screenDirtyRect.left, + screenDirtyRect.top, + windowSurface, + windowDirtyRect, + k_AUI_BLITTER_FLAG_COPY ); + Assert( errcode == AUI_ERRCODE_OK ); + if ( errcode != AUI_ERRCODE_OK ) + { + retcode = AUI_ERRCODE_BLTFAILED; + break; + } + } + + return retcode; +} + +AUI_ERRCODE aui_SDLMouse::BltDirtyRectInfoToPrimary() +{ + AUI_ERRCODE retcode = AUI_ERRCODE_OK; + AUI_ERRCODE errcode; + + if (g_civApp->IsInBackground()) return AUI_ERRCODE_OK; + + tech_WLList *driList = g_ui->GetDirtyRectInfoList(); + + uint32 blitFlags; + LPVOID primaryBuf = NULL; + + if (g_theProfileDB && g_theProfileDB->IsUseDirectXBlitter()) + { + blitFlags = k_AUI_BLITTER_FLAG_COPY; + } + else + { + blitFlags = k_AUI_BLITTER_FLAG_COPY | k_AUI_BLITTER_FLAG_FAST; + errcode = g_ui->Secondary()->Lock(NULL, &primaryBuf, 0); + Assert( errcode == AUI_ERRCODE_OK ); + } + + ListPos position = driList->GetHeadPosition(); + for (sint32 j = driList->L(); j; j--) + { + aui_UI::DirtyRectInfo *dri = driList->GetNext(position); + + aui_Window *window = dri->window; + + sint32 windowX = window->X(); + sint32 windowY = window->Y(); + aui_Surface *windowSurface = window->TheSurface(); + + if (!windowSurface) continue; + + if (g_civApp->IsInBackground()) continue; + + RECT *windowDirtyRect = &dri->rect; + + RECT screenDirtyRect = *windowDirtyRect; + OffsetRect(&screenDirtyRect, windowX, windowY); + + if (!g_civApp->IsInBackground()) // Actual Drawing + { + errcode = g_ui->BltToSecondary( + screenDirtyRect.left, + screenDirtyRect.top, + windowSurface, + windowDirtyRect, + blitFlags); + Assert(errcode == AUI_ERRCODE_OK); + if (errcode != AUI_ERRCODE_OK) + { + retcode = AUI_ERRCODE_BLTFAILED; + break; + } + } + } + + errcode = g_ui->BltSecondaryToPrimary(blitFlags); + Assert(errcode == AUI_ERRCODE_OK); + if (errcode != AUI_ERRCODE_OK) + { + retcode = AUI_ERRCODE_BLTFAILED; + } + + if (!g_theProfileDB || !g_theProfileDB->IsUseDirectXBlitter()) + { + errcode = g_ui->Secondary()->Unlock( primaryBuf ); + Assert( errcode == AUI_ERRCODE_OK ); + } + + return retcode; +} + +AUI_ERRCODE aui_SDLMouse::BltBackgroundColorToPrimary(COLORREF color, aui_DirtyList *colorAreas) +{ + if (g_civApp->IsInBackground()) return AUI_ERRCODE_OK; + + ListPos position = colorAreas->GetHeadPosition(); + for (sint32 j = colorAreas->L(); j; j--) + { + RECT *screenDirtyRect = colorAreas->GetNext(position); + AUI_ERRCODE errcode = g_ui->ColorBltToSecondary(screenDirtyRect, color,0); + Assert(errcode == AUI_ERRCODE_OK); + if (errcode != AUI_ERRCODE_OK) + { + return AUI_ERRCODE_BLTFAILED; + } + } + + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMouse::BltBackgroundImageToPrimary(aui_Image *image, RECT *imageRect, aui_DirtyList *imageAreas) +{ + if (g_civApp->IsInBackground()) return AUI_ERRCODE_OK; + + ListPos position = imageAreas->GetHeadPosition(); + for ( sint32 j = imageAreas->L(); j; j-- ) + { + RECT *screenDirtyRect = imageAreas->GetNext(position); + AUI_ERRCODE errcode = g_ui->BltToSecondary( + screenDirtyRect->left, + screenDirtyRect->top, + image->TheSurface(), + screenDirtyRect, + k_AUI_BLITTER_FLAG_COPY); + + Assert(errcode == AUI_ERRCODE_OK); + if (errcode != AUI_ERRCODE_OK) + { + return AUI_ERRCODE_BLTFAILED; + } + } + + return AUI_ERRCODE_OK; +} + #endif diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmouse.h b/ctp2_code/ui/aui_sdl/aui_sdlmouse.h index 77d83c36b..ab9e9271f 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmouse.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlmouse.h @@ -19,9 +19,25 @@ class aui_SDLMouse : public aui_Mouse, public aui_SDLInput BOOL useExclusiveMode = FALSE); virtual ~aui_SDLMouse(); + virtual AUI_ERRCODE BltWindowToPrimary(aui_Window *window); + virtual AUI_ERRCODE BltDirtyRectInfoToPrimary(); + virtual AUI_ERRCODE BltBackgroundColorToPrimary(COLORREF color, aui_DirtyList *colorAreas); + virtual AUI_ERRCODE BltBackgroundImageToPrimary(aui_Image *image, RECT *imageRect, aui_DirtyList *imageAreas); + protected: aui_SDLMouse(); + + virtual void ActivateCursor(aui_Cursor *cursor); + + virtual AUI_ERRCODE Erase() { return AUI_ERRCODE_OK; } virtual AUI_ERRCODE GetInput(); + virtual AUI_ERRCODE ReactToInput() {} + + virtual AUI_ERRCODE CreatePrivateBuffers() { return AUI_ERRCODE_OK; } + virtual void DestroyPrivateBuffers() {} + +private: + aui_Cursor *m_currentCursor; }; typedef aui_SDLMouse aui_NativeMouse; diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp index 104417271..1fe4a028c 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp @@ -1984,9 +1984,7 @@ aui_SDLMovie::aui_SDLMovie(AUI_ERRCODE *retval, const MBCHAR * filename) : m_windowWidth(0), m_windowHeight(0), m_logicalWidth(0), - m_logicalHeight(0), - m_cursorSurface(NULL), - m_cursor(NULL) + m_logicalHeight(0) { strncpy(m_filename, filename, sizeof(m_filename)); m_filename[MAX_PATH] = '\0'; @@ -1998,13 +1996,11 @@ aui_SDLMovie::~aui_SDLMovie() { m_renderer = NULL; } -void aui_SDLMovie::SetContext(SDL_Renderer *renderer, const int windowWidth, const int windowHeight, - SDL_Surface* cursorSurface) { +void aui_SDLMovie::SetContext(SDL_Renderer *renderer, const int windowWidth, const int windowHeight) { Assert(renderer); m_renderer = renderer; m_windowWidth = windowWidth; m_windowHeight = windowHeight; - m_cursorSurface = cursorSurface; } AUI_ERRCODE aui_SDLMovie::Load() { @@ -2033,13 +2029,6 @@ AUI_ERRCODE aui_SDLMovie::Open(uint32 flags, aui_Surface *surface, RECT *rect) { return AUI_ERRCODE_MOVIEFAILED; } - if (m_cursorSurface) { - m_cursor = SDL_CreateColorCursor(m_cursorSurface, 0, 0); - if (m_cursor) { - SDL_SetCursor(m_cursor); - } - } - renderer = m_renderer; screen_width = m_windowWidth; screen_height = m_windowHeight; @@ -2058,13 +2047,7 @@ AUI_ERRCODE aui_SDLMovie::Open(uint32 flags, aui_Surface *surface, RECT *rect) { AUI_ERRCODE aui_SDLMovie::Close() { #if defined(USE_SDL_FFMPEG) - // Reset cursor - if (m_cursor) { - SDL_SetCursor(NULL); - SDL_FreeCursor(m_cursor); - m_cursor = NULL; - } - SDL_ShowCursor(SDL_DISABLE); + SDL_ShowCursor(SDL_ENABLE); if (m_videoState) { Stop(); stream_close(m_videoState); diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmovie.h b/ctp2_code/ui/aui_sdl/aui_sdlmovie.h index 7a109249c..9979c0e86 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmovie.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlmovie.h @@ -19,7 +19,7 @@ class aui_SDLMovie : public aui_Movie { aui_SDLMovie(AUI_ERRCODE *retval, const MBCHAR * filename = NULL); virtual ~aui_SDLMovie(); - void SetContext(SDL_Renderer *renderer, const int windowWidth, const int windowHeight, SDL_Surface *cursorSurface); + void SetContext(SDL_Renderer *renderer, const int windowWidth, const int windowHeight); virtual AUI_ERRCODE Load(); virtual AUI_ERRCODE Unload(); @@ -47,8 +47,6 @@ class aui_SDLMovie : public aui_Movie { int m_windowHeight; int m_logicalWidth; int m_logicalHeight; - SDL_Surface *m_cursorSurface; - SDL_Cursor *m_cursor; }; #endif // defined(__AUI_USE_SDL__) diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp index 8c06a3cba..68d0e6d90 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp @@ -33,13 +33,11 @@ static int lockmgr(void **mtx, enum AVLockOp op) } #endif // USE_SDL_FFMPEG -aui_SDLMovieManager::aui_SDLMovieManager(SDL_Renderer *renderer, const int windowWidth, const int windowHeight, - SDL_Surface *mouseSurface) : +aui_SDLMovieManager::aui_SDLMovieManager(SDL_Renderer *renderer, const int windowWidth, const int windowHeight) : aui_MovieManager(false), m_renderer(renderer), m_windowWidth(windowWidth), - m_windowHeight(windowHeight), - m_mouseSurface(mouseSurface) + m_windowHeight(windowHeight) { Assert(m_renderer); m_movieResource = new aui_Resource(); @@ -61,8 +59,8 @@ aui_SDLMovieManager::~aui_SDLMovieManager() { aui_Movie* aui_SDLMovieManager::Load(const MBCHAR *filename, C3DIR dir) { aui_SDLMovie *movie = m_movieResource->Load(filename, dir); - movie->SetContext(m_renderer, m_windowWidth, m_windowHeight, m_mouseSurface); + movie->SetContext(m_renderer, m_windowWidth, m_windowHeight); return movie; } -#endif // defined(__AUI_USE_SDL__) \ No newline at end of file +#endif // defined(__AUI_USE_SDL__) diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h index 0bed0aad7..d435f8bcc 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h @@ -15,8 +15,7 @@ class aui_SDLMovieManager : public aui_MovieManager { public: - aui_SDLMovieManager(SDL_Renderer *sdlRenderer, const int windowWidth, const int windowHeight, - SDL_Surface *mouseSurface); + aui_SDLMovieManager(SDL_Renderer *sdlRenderer, const int windowWidth, const int windowHeight); virtual ~aui_SDLMovieManager(); virtual aui_Movie *Load(const MBCHAR *filename, C3DIR dir = C3DIR_DIRECT); @@ -37,7 +36,6 @@ class aui_SDLMovieManager : public aui_MovieManager { SDL_Renderer *m_renderer; int m_windowWidth; int m_windowHeight; - SDL_Surface *m_mouseSurface; }; #endif // defined(__AUI_USE_SDL__) diff --git a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp index 35073da81..8a801f44f 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp @@ -352,11 +352,7 @@ aui_MovieManager* aui_SDLUI::CreateMovieManager( void ) { int windowWidth; int windowHeight; SDL_GetWindowSize(m_SDLWindow, &windowWidth, &windowHeight); - - aui_Surface *cursorSurface = m_mouse->GetCurrentCursor()->TheSurface(); - aui_SDLSurface *sdlCursorSurface = dynamic_cast(cursorSurface); - return new aui_SDLMovieManager(m_SDLRenderer, windowWidth, windowHeight, - sdlCursorSurface ? sdlCursorSurface->GetSDLSurface() : NULL); + return new aui_SDLMovieManager(m_SDLRenderer, windowWidth, windowHeight); } AUI_ERRCODE aui_SDLUI::SDLDrawScreen( void ) { From 587d7b0b866f2d436cf1ef9a9279c5b3b35eb514 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Thu, 16 Apr 2020 23:38:07 +0200 Subject: [PATCH 17/29] Only install those ffmpeg packages that are needed --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1580ebd21..cab6afcdf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -62,7 +62,7 @@ FROM system as install ARG BTYP RUN apt-get update && apt-get install -y --no-install-recommends \ - libsdl2-2.0 libsdl2-mixer-2.0 libsdl2-image-2.0 ffmpeg libgtk2.0-0 && \ + libsdl2-2.0 libsdl2-mixer-2.0 libsdl2-image-2.0 libavcodec57 libavformat57 libswscale4 libgtk2.0-0 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* From 39ec5e209dd5c6a3cf0d32530bc1808bbf05d4e8 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Fri, 17 Apr 2020 10:30:53 +0200 Subject: [PATCH 18/29] Limit number of scroll actions per second As the drawing with SDL2 is faster than before the number of scroll actions are not limited any more by the time to draw. Therefor another way of limiting the number of scroll actions has been introduced. --- ctp2_code/ctp/civ3_main.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ctp2_code/ctp/civ3_main.cpp b/ctp2_code/ctp/civ3_main.cpp index 7f051af73..b6af30371 100644 --- a/ctp2_code/ctp/civ3_main.cpp +++ b/ctp2_code/ctp/civ3_main.cpp @@ -236,7 +236,7 @@ sint32 g_modalWindow = 0; BOOL g_helpMode = TRUE; static uint32 s_scrollcurtick =0; -static uint32 s_scrolllasttick=0; +static uint32 s_lastscrolltick=0; static sint32 s_scrolltime =k_SMOOTH_START_TIME; static uint32 s_accelTickStart = 0; @@ -650,7 +650,6 @@ bool ui_CheckForScroll(void) g_tiledMap->SetScrolling(false); - s_scrolllasttick = s_scrollcurtick; s_scrollcurtick = GetTickCount(); if (!g_c3ui->TheMouse()) @@ -669,6 +668,9 @@ bool ui_CheckForScroll(void) // const int k_MAX_SMOOTH_SCROLL = 64; const int k_TICKS_PER_ACCELERATION = 50; + /* Limit the number of scroll actions per second. */ + const int k_NUMBER_OF_SCROLL_ACTIONS = 20; + const int k_TICKS_PER_SCROLL = 1000 / k_NUMBER_OF_SCROLL_ACTIONS; sint32 deltaX = 0, deltaY = 0; @@ -821,9 +823,12 @@ bool ui_CheckForScroll(void) if (g_smoothScroll) g_tiledMap->ScrollMapSmooth(smoothX, smoothY); - else - g_tiledMap->ScrollMap(deltaX, deltaY); - + else { + if ((s_scrollcurtick - s_lastscrolltick) > k_TICKS_PER_SCROLL) { + s_lastscrolltick = GetTickCount(); + g_tiledMap->ScrollMap(deltaX, deltaY); + } + } } else { From 1015f8ad4723d1dc74d22cb5d97c9562d5e1109d Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Sat, 18 Apr 2020 11:15:43 +0200 Subject: [PATCH 19/29] Remove CD-rom support for Linux As SDL2 does not support CD-rom support any more it has been removed. --- configure.ac | 1 - ctp2_code/ctp/civapp.cpp | 2 + ctp2_code/ctp/ctp2_utils/c3files.cpp | 319 +---------------- ctp2_code/ctp/ctp2_utils/c3files.h | 23 +- ctp2_code/ctp/ctp2_utils/tracklen.cpp | 166 +-------- ctp2_code/ctp/ctp2_utils/tracklen.h | 15 +- ctp2_code/gs/fileio/CivPaths.cpp | 36 +- ctp2_code/gs/fileio/CivPaths.h | 5 +- ctp2_code/sound/soundmanager.cpp | 338 +++++++------------ ctp2_code/sound/soundmanager.h | 17 +- ctp2_code/ui/aui_common/aui_music.cpp | 59 +--- ctp2_code/ui/aui_common/aui_music.h | 16 +- ctp2_code/ui/interface/initialplayscreen.cpp | 7 +- ctp2_code/ui/interface/loadsavescreen.cpp | 18 +- ctp2_code/ui/interface/spnewgamescreen.cpp | 10 +- ctp2_code/ui/netshell/allinonewindow.cpp | 15 +- 16 files changed, 214 insertions(+), 833 deletions(-) diff --git a/configure.ac b/configure.ac index d2a00a04c..c8b7aa879 100644 --- a/configure.ac +++ b/configure.ac @@ -59,7 +59,6 @@ AM_PATH_SDL_FFMPEG AC_PATH_X AC_PATH_XTRA AC_DEFINE(USE_SDL,1,[Use the SDL-library]) -AC_DEFINE(SKIP_SDL2_CDROM_ISSUES,1,[Skip SDL2 CD-rom code]) AC_DEFINE(SKIP_SDL2_DEBUG_MEMORY_ISSUE,1,[Skip SDL2 debug memory code]) AC_WORDS_BIGENDIAN diff --git a/ctp2_code/ctp/civapp.cpp b/ctp2_code/ctp/civapp.cpp index 6637cf2e6..ab0b9b02f 100644 --- a/ctp2_code/ctp/civapp.cpp +++ b/ctp2_code/ctp/civapp.cpp @@ -1274,8 +1274,10 @@ sint32 CivApp::InitializeApp(HINSTANCE hInstance, int iCmdShow) g_logCrashes = g_theProfileDB->GetEnableLogs(); InitDataIncludePath(); +#if !defined(USE_SDL) c3files_InitializeCD(); g_civPaths->InitCDPath(); +#endif // USE_SDL GreatLibrary::Initialize_Great_Library_Data(); display_Initialize(hInstance, iCmdShow); diff --git a/ctp2_code/ctp/ctp2_utils/c3files.cpp b/ctp2_code/ctp/ctp2_utils/c3files.cpp index c4689a15c..8cad75dbe 100644 --- a/ctp2_code/ctp/ctp2_utils/c3files.cpp +++ b/ctp2_code/ctp/ctp2_utils/c3files.cpp @@ -44,8 +44,9 @@ #include "pointerlist.h" #include "profileDB.h" #include "soundmanager.h" +#if !defined(USE_SDL) #include "tracklen.h" - +#endif // USE_SDL #ifdef HAVE_STRING_H #include #endif @@ -81,26 +82,19 @@ extern C3UI * g_c3ui; +#if !defined(USE_SDL) + namespace { -#ifdef _WIN32 // #ifndef USE_SDL DriveIdType const DRIVE_FIRST = 'A'; DriveIdType const DRIVE_LAST = 'Z'; DriveIdType const DRIVE_UNDETERMINED = '\0'; size_t const DRIVE_COUNT = 1 + (DRIVE_LAST - DRIVE_FIRST); -#else - DriveIdType const DRIVE_FIRST = 0; - DriveIdType DRIVE_LAST = -1; - DriveIdType const DRIVE_UNDETERMINED = -1; - size_t DRIVE_COUNT = 0; -#endif size_t const VOLUME_NAME_SIZE = 32; bool g_hasCD = false; -#ifdef _WIN32 // #ifndef USE_SDL bool IsCD[DRIVE_COUNT]; -#endif MBCHAR VolumeName[VOLUME_NAME_SIZE]; DriveIdType WhichCD = DRIVE_UNDETERMINED; @@ -111,6 +105,8 @@ namespace #define k_CTP_CD_VOLUME_NAME "CTP2" +#endif // USE_SDL + FILE* c3files_fopen(C3DIR dirID, MBCHAR const * s1, MBCHAR const * s2, bool checkScenario) { MBCHAR s[_MAX_PATH]; @@ -516,6 +512,8 @@ const MBCHAR *c3files_GetCTPHomeDir() return NULL; } +#if !defined(USE_SDL) + bool c3files_HasLegalCD() { bool success = false; @@ -536,7 +534,6 @@ bool c3files_HasLegalCD() if (!success) { -#if defined(WIN32) int const rval = MessageBox (g_c3ui ? g_c3ui->TheHWND() : NULL, appstrings_GetString(APPSTR_INSERTCDROM), @@ -550,17 +547,9 @@ bool c3files_HasLegalCD() if (IDCANCEL == rval) { -#else - c3errors_ErrorDialog(appstrings_GetString(APPSTR_CDROM), - appstrings_GetString(APPSTR_NEEDCDROM) - ); -#endif - // Do not annoy the user with more messages after cancelling exit(-1); -#if defined(WIN32) } -#endif if (g_c3ui) { @@ -579,18 +568,6 @@ bool c3files_HasLegalCD() void c3files_InitializeCD(void) { -#if defined(__linux__) -#if !defined(SKIP_SDL2_CDROM_ISSUES) - int rc = SDL_Init(SDL_INIT_CDROM); -#else // SKIP_SDL2_CDROM_ISSUES - int rc = 1; -#endif // SKIP_SDL2_CDROM_ISSUES - if(0 != rc) - { - fprintf(stderr, "Could not initialize CDROM:\n%s\n", SDL_GetError()); - return; - } -#endif c3files_GetCDDrives(); (void) c3files_FindCDByName(k_CTP_CD_VOLUME_NAME); } @@ -605,194 +582,6 @@ DriveIdType c3files_GetCtpCdId(void) return WhichCD; } -const MBCHAR *c3files_GetCDDriveMount(MBCHAR *buf, size_t size, - DriveIdType cdIndex) -{ - if(buf == NULL) - return NULL; - - MBCHAR *cdDriveName = c3files_GetVolumeName(cdIndex); - - if(cdDriveName == NULL) - return NULL; - -#if defined(WIN32) - if(strlen(cdDriveName) >= size) - return NULL; - - strcpy(buf, cdDriveName); - return buf; -#elif defined(LINUX) - MBCHAR tempPath[_MAX_PATH] = {0}; - const size_t mntInfoCnt = 2; - // Do not change order of mntInfo - const MBCHAR *mntInfo[mntInfoCnt] = {_PATH_MOUNTED, _PATH_MNTTAB }; - const size_t mntOptsCnt = 23; - int lerrno = errno; - typedef struct - { - const char *name; - unsigned long flag; - bool clear; - } mount_opt_t; - const mount_opt_t mntOpts[mntOptsCnt] = { - { MNTOPT_RO, MS_RDONLY, false }, - { MNTOPT_RW, MS_RDONLY, true }, - { MNTOPT_NOSUID, MS_NOSUID, false }, - { MNTOPT_SUID, MS_NOSUID, true }, - { "nodev", MS_NODEV, false }, - { "dev", MS_NODEV, true }, - { "noexec", MS_NOEXEC, false }, - { "exec", MS_NOEXEC, true }, - { "sync", MS_SYNCHRONOUS, false }, - { "async", MS_SYNCHRONOUS, true }, - { "remount", MS_REMOUNT, false }, - { "lock", MS_MANDLOCK, false }, - { "nolock", MS_MANDLOCK, true }, - { "dirsync", MS_DIRSYNC, false }, - { "noatime", MS_NOATIME, false }, - { "atime", MS_NOATIME, true }, - { "nodiratime", MS_NODIRATIME, false },/// \todo: check string - { "bind", MS_BIND, false }, -// { MS_MOVE }, // for /bin/mount -// { MS_REC }, - { "verbose", MS_VERBOSE, false }, - { "acl", MS_POSIXACL, false }, - { "noacl", MS_POSIXACL, true }, -// { MS_ACTIVE }, - { "nouser", MS_NOUSER, false }, - { "user", MS_NOUSER, true } - }; - - BOOL cdrLink = FALSE; - MBCHAR devlink[_MAX_PATH] = {0}; - char *fulllink = NULL; - struct stat st = {0}; - - if(lstat(cdDriveName, &st) == -1) - { - for(sint32 i = 0; i < strlen(cdDriveName); ++i) - { - cdDriveName[i] = tolower(cdDriveName[i]); - } - - if(lstat(cdDriveName, &st) == -1) - { - return NULL; - } - } - - if(S_ISLNK(st.st_mode)) - { - int len = readlink(cdDriveName, devlink, _MAX_PATH); - if((len > 0) && (len < _MAX_PATH)) - { - - cdrLink = TRUE; - devlink[len] = '\0'; - strcpy(tempPath, cdDriveName); - char *dn = dirname(tempPath); - if(dn) - strcpy(tempPath, dn); - - strcat(tempPath, FILE_SEP); - strcat(tempPath, devlink); - fulllink = _fullpath(NULL, tempPath, 0); - } - } - - for(size_t u = 0; u < mntInfoCnt; u++) - { - FILE *mounts = setmntent(mntInfo[u], "r"); - - if(mounts) - { - struct mntent *mntent; - while(mntent = getmntent(mounts)) - { - if((mntent->mnt_fsname == NULL) || - (mntent->mnt_dir == NULL) || - (mntent->mnt_type == NULL)) - continue; - - if(strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0) - if(mntent->mnt_type == MNTTYPE_IGNORE) - continue; - - if( strcasestr(mntent->mnt_dir, cdDriveName) != NULL - || strcasecmp(cdDriveName, mntent->mnt_fsname) == 0 - || (cdrLink && (!strcasecmp(devlink, mntent->mnt_fsname))) - || ((fulllink != NULL) && (!strcasecmp(fulllink, mntent->mnt_fsname))) - ) - { - const MBCHAR *ret = NULL; - // Mounted? - if(u == 0) - { - strncpy(buf, mntent->mnt_dir, size); - ret = buf; - // Not mounted fstab entry - } - else if(u == 1) - { - unsigned long flags = MS_MGC_VAL; - if(hasmntopt(mntent, "defaults")) - { - flags |= (MS_NOUSER); - } - for(size_t f = 0; f < mntOptsCnt; f++) - { - if(hasmntopt(mntent, mntOpts[f].name)) - if(mntOpts[f].clear) - flags &= ~mntOpts[f].flag; - else - flags |= mntOpts[f].flag; - } - errno = 0; - int rc = mount(mntent->mnt_fsname, - mntent->mnt_dir, - mntent->mnt_type, - flags, 0); - lerrno = errno; //preserve errno value of mount over other library calls! - if(0 == rc) - { - strncpy(buf, mntent->mnt_dir, size); - ret = buf; - } - else - { - fprintf(stderr, "%s L%d: CD mount error occured: ", __FILE__, __LINE__); - perror(strerror(lerrno)); - } - } - - endmntent(mounts); - if(fulllink) - { - free(fulllink); - fulllink = 0; - } - - return ret; - } - } - endmntent(mounts); - } - } - if(fulllink) - { - free(fulllink); - fulllink = 0; - } - - return NULL; -#else -/* Seriously? A game mounting a filesystem? */ -strlcpy(buf, cdDriveName, size); -return buf; -#endif -} - namespace { @@ -813,7 +602,6 @@ namespace //---------------------------------------------------------------------------- void c3files_GetCDDrives(void) { -#if defined(WIN32) // #ifndef USE_SDL MBCHAR drivepath[4]; // letter + : + dir seperator + zero strcpy(drivepath, " :" FILE_SEP); @@ -831,23 +619,6 @@ void c3files_GetCDDrives(void) IsCD[i] = false; } } -#else -#if !defined(SKIP_SDL2_CDROM_ISSUES) - int CDCnt = SDL_CDNumDrives(); -#else // SKIP_SDL2_CDROM_ISSUES - int CDCnt = 0; -#endif // SKIP_SDL2_CDROM_ISSUES - Assert(CDCnt >= 0); - if (CDCnt < 0) - { - DRIVE_COUNT = 0; - } - else - { - DRIVE_COUNT = CDCnt; - } - DRIVE_LAST = DRIVE_COUNT - 1; -#endif } //---------------------------------------------------------------------------- @@ -867,7 +638,6 @@ void c3files_GetCDDrives(void) //---------------------------------------------------------------------------- MBCHAR * c3files_GetVolumeName(DriveIdType id) { -#if defined(WIN32) MBCHAR drivepath[4]; // letter + : + dir seperator + zero strcpy(drivepath, " :" FILE_SEP); drivepath[0] = id; @@ -892,73 +662,6 @@ MBCHAR * c3files_GetVolumeName(DriveIdType id) } return NULL; - -#elif defined(LINUX) -#if defined(SKIP_SDL2_CDROM_ISSUES) - return NULL; -#else // SKIP_SDL2_CDROM_ISSUES - /// \todo Add code to determine beginsector of iso_primary_sector - /// On a German ctp2 cd, it starts on sector 16 (byte 16 << 11 = 0x8000) - const MBCHAR *cd_dev = SDL_CDName(id); - FILE *cd = fopen(cd_dev, "rb"); - int lerrno = errno; - if (cd == NULL) - { - fprintf(stderr, "%s\n", strerror(lerrno)); - return NULL; - } - - int rc = fseek(cd, 0x8000, SEEK_SET); - lerrno = errno; - if (rc != 0) - { - fprintf(stderr, "%s\n", strerror(lerrno)); - fclose(cd); - return NULL; - } - - struct iso_primary_descriptor ipd; - memset(&ipd, 0, sizeof(ipd)); - size_t s = fread(&ipd, 1, sizeof(ipd), cd); - lerrno = errno; - if (s != sizeof(ipd)) - { - fprintf(stderr, "Failed reading %d bytes: %s\n", sizeof(ipd), - strerror(lerrno)); - fclose(cd); - return NULL; - } - unsigned int i = 0; - s = std::min(sizeof(ipd.volume_id), sizeof(VolumeName)); - assert(i < s); - - while (i < s) - { - if ('\0' == ipd.volume_id[i]) - { - VolumeName[i] = '\0'; - return VolumeName; - } - if ((!isalnum(ipd.volume_id[i])) && (!isspace(ipd.volume_id[i]))) - { - return NULL; - } - VolumeName[i] = ipd.volume_id[i]; - i++; - } - i--; - - // Win32 Compat: GetVolumeInformation does not return ending spaces - while ((i > 0) && isspace(VolumeName[i])) - { - i--; - } - if (isspace(VolumeName[i+1])) - VolumeName[i+1] = '\0'; - - return VolumeName; -#endif // SKIP_SDL2_CDROM_ISSUES -#endif } //---------------------------------------------------------------------------- @@ -986,10 +689,8 @@ bool c3files_FindCDByName(MBCHAR const * name) for (DriveIdType i = DRIVE_FIRST; (i <= DRIVE_LAST) && !g_hasCD; ++i) { -#if defined(WIN32) // #ifndef USE_SDL if (IsCD[static_cast(i - DRIVE_FIRST)]) { -#endif MBCHAR const * cdName = c3files_GetVolumeName(i); if (cdName) @@ -1003,12 +704,12 @@ bool c3files_FindCDByName(MBCHAR const * name) g_hasCD = true; } } -#if defined(WIN32) // #ifndef USE_SDL } -#endif } return g_hasCD || !g_theProfileDB->IsRequireCD(); } } // local namespace + +#endif // USE_SDL diff --git a/ctp2_code/ctp/ctp2_utils/c3files.h b/ctp2_code/ctp/ctp2_utils/c3files.h index f21a07e1c..18bf24863 100644 --- a/ctp2_code/ctp/ctp2_utils/c3files.h +++ b/ctp2_code/ctp/ctp2_utils/c3files.h @@ -25,7 +25,7 @@ // // Modifications from the original Activision code: // -// - c3files_fopen can now ignore scenario paths. (9-Apr-2007 Martin Gühmann) +// - c3files_fopen can now ignore scenario paths. (9-Apr-2007 Martin G�hmann) // //---------------------------------------------------------------------------- @@ -84,8 +84,6 @@ enum C3SAVEDIR { // WIN32_FIND_DATA is native type typedef MBCHAR DriveIdType; -// TODO: remove when all references have been removed -#define c3files_GetCTPCDDriveLetter c3files_GetCtpCdId #else @@ -153,22 +151,11 @@ bool c3files_getfilelist_ex(C3SAVEDIR dirID, MBCHAR *ext, PointerList -#if defined(WIN32) #include "windows.h" #include "mbstring.h" #include "mmsystem.h" -#elif defined(LINUX) -#include -#include -#include -#include -#endif + #if defined(HAVE_UNISTD_H) #include #endif -#if defined(USE_SDL) -#if !defined(SKIP_SDL2_CDROM_ISSUES) -#include -#endif // SKIP_SDL2_CDROM_ISSUES -#endif #include "cheatkey.h" #include "tracklen.h" @@ -86,11 +77,9 @@ char *tracklen_cryptAscii(char *s) static void DMCIError(int error) { -#ifdef WIN32 char szScratch[ MAX_PATH ]; mciGetErrorString( error, szScratch, MAX_PATH ); tracklen_DPRINT((tracklen_buf, "last MCI error = %s\n", szScratch )); -#endif } #else @@ -110,23 +99,13 @@ void tracklen_cryptBinary(char *data, size_t len) data[ index ] ^= p[ index % 400 ]; } -#if !defined(SKIP_SDL2_CDROM_ISSUES) -#ifdef USE_SDL -static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, SDL_CD *cdrom ) -#else static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int wDeviceID ) -#endif { -#if defined(WIN32) && !defined(USE_SDL) MCI_STATUS_PARMS msp; MCI_SET_PARMS mp; long totalLen_ms = 0; -#else - uint64 totalLen_ms = 0; -#endif DWORD i; -#if defined(WIN32) && !defined(USE_SDL) memset(&mp, 0, sizeof(mp)); mp.dwTimeFormat = MCI_FORMAT_MILLISECONDS; if (mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&mp)) @@ -145,15 +124,6 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w return __LINE__; } trackLenBuf[0] = msp.dwReturn; -#elif defined(USE_SDL) - if (!cdrom) - return __LINE__; - if (!CD_INDRIVE(SDL_CDStatus(cdrom))) - { - return __LINE__; - } - trackLenBuf[0] = cdrom->numtracks; -#endif tracklen_DPRINT((tracklen_buf, "GetTrackLengths: %d tracks\n", trackLenBuf[0])); if (trackLenBuf[0] > tracklen_MAXTRACKS) { tracklen_DPRINT((tracklen_buf, "GetTrackLengths: too many tracks\n")); @@ -161,7 +131,6 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w } for (i = 1; i <= trackLenBuf[0]; i++) { -#if defined(WIN32) && !defined(USE_SDL) memset(&msp, 0, sizeof(msp)); msp.dwItem = MCI_STATUS_LENGTH; msp.dwTrack = i; @@ -173,18 +142,8 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w continue; } trackLenBuf[i] = msp.dwReturn; -#elif defined(USE_SDL) - uint64 ui = cdrom->track[i - 1].length * 1000 / CD_FPS; - // FIXME: This may not be reusable - // ALL tracks on CTP2 CD are one ms shorter due to rounding - trackLenBuf[i] = ++ui; - totalLen_ms += cdrom->track[i - 1].length * 1000; -#endif tracklen_DPRINT((tracklen_buf, "GetTrackLengths: track %d len %d\n", i, trackLenBuf[i])); } -#if defined(USE_SDL) - totalLen_ms = totalLen_ms / CD_FPS + 1; -#elif defined(WIN32) msp.dwItem = MCI_STATUS_LENGTH; if(mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&msp)) { @@ -193,7 +152,6 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w return __LINE__; } totalLen_ms = msp.dwReturn; -#endif tracklen_DPRINT((tracklen_buf, "GetTrackLengths: got disc len %d\n", totalLen_ms )); if (totalLen_ms < ((74 * 60 + 30) * 1000)) { @@ -207,35 +165,16 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w return 0; } -#endif // SKIP_SDL2_CDROM_ISSUES -#if defined(USE_SDL) -int tracklen_GetTrackLengths(DWORD *trackLenBuf, int iDrive) -#else int tracklen_GetTrackLengths(DWORD *trackLenBuf, char whichDrive) -#endif { -#if defined(SKIP_SDL2_CDROM_ISSUES) - return __LINE__; -#else // SKIP_SDL2_CDROM_ISSUES -#if defined(USE_SDL) - const char *driveName = SDL_CDName(iDrive); - if (!driveName) - return __LINE__; -#endif -#if defined(WIN32) -#if defined(USE_SDL) - char whichDrive = driveName[0]; -#endif MCI_OPEN_PARMS mop; char szDrive[16]; -#endif #ifdef tracklen_LOGGING if (!tracklen_fp) tracklen_fp = fopen(tracklen_LOGFILE, "w"); #endif -#if defined(WIN32) && !defined(USE_SDL) memset(&mop, 0, sizeof(mop)); mop.lpstrDeviceType = (LPCSTR)(MCI_DEVTYPE_CD_AUDIO); mop.lpstrAlias = NULL; @@ -248,76 +187,42 @@ int tracklen_GetTrackLengths(DWORD *trackLenBuf, char whichDrive) int iRet = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_ELEMENT | MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE, (DWORD_PTR)&mop); if (iRet) -#elif defined(USE_SDL) - SDL_CD *cdrom = SDL_CDOpen(iDrive); - if (cdrom == NULL) -#endif { tracklen_DPRINT((tracklen_buf, "GetTrackLengths: failed to open cdrom device.\n" )); -#ifndef USE_SDL DMCIError( iRet ); -#endif return __LINE__; } tracklen_DPRINT((tracklen_buf, "GetTrackLengths: Opened cdrom device\n" )); -#ifdef USE_SDL - int iRet = tracklen_GetTrackLengthsViaHandle( trackLenBuf, cdrom ); - SDL_CDClose(cdrom); -#else iRet = tracklen_GetTrackLengthsViaHandle( trackLenBuf, mop.wDeviceID); mciSendCommand( mop.wDeviceID, MCI_CLOSE, 0, NULL ); -#endif tracklen_DPRINT((tracklen_buf, "GetTrackLengths: Returning %d\n", iRet )); return iRet; -#endif // SKIP_SDL2_CDROM_ISSUES } static int tracklen_CheckTrackLengths2( DWORD *trackLenBuf) { -#if defined(SKIP_SDL2_CDROM_ISSUES) - return __LINE__; -#else // SKIP_SDL2_CDROM_ISSUES if( !trackLenBuf ) return __LINE__; tracklen_DPRINT((tracklen_buf, "CheckTrackLengths2: begin\n" )); int i = 0; -#if defined(WIN32) && !defined(USE_SDL) HWND hCD; for (i = 0; (hCD=FindWindow( "SJE_CdPlayerClass",NULL)) && i < 100; i++) { tracklen_DPRINT((tracklen_buf, "CheckTrackLengths2: Shutting down CD player\n" )); SendMessage( hCD, WM_CLOSE, 0, 0 ); } -#endif int iDrive; -#if defined(USE_SDL) - for (iDrive = 0; iDrive < SDL_CDNumDrives(); iDrive++) { -#else for (iDrive = 0; iDrive < 26; iDrive++) { -#endif -#if defined(USE_SDL) - const char *driveName = SDL_CDName(iDrive); - if (!driveName) - continue; -#endif -#if defined(WIN32) char szDrive[ MAX_PATH ]; int iDriveType; -#if defined(USE_SDL) - if (driveName) - szDrive[0] = driveName[0]; - else - szDrive[0] = ' '; -#else szDrive[0] = static_cast(iDrive + 'A'); -#endif szDrive[1] = ':'; szDrive[2] = '\\'; szDrive[3] = 0; @@ -327,13 +232,8 @@ static int tracklen_CheckTrackLengths2( DWORD *trackLenBuf) continue; } tracklen_DPRINT((tracklen_buf, "CheckTrackLengths2: device %s is cd.\n", szDrive )); -#endif DWORD newbuf[tracklen_MAXTRACKS]; -#if defined(USE_SDL) - int iRet = tracklen_GetTrackLengths(newbuf, iDrive); -#else int iRet = tracklen_GetTrackLengths(newbuf, szDrive[0]); -#endif if (iRet) { tracklen_DPRINT((tracklen_buf, "CheckTrackLengths2: drive %s fails check %d\n", szDrive, iRet )); @@ -363,7 +263,6 @@ static int tracklen_CheckTrackLengths2( DWORD *trackLenBuf) tracklen_DPRINT((tracklen_buf, "CheckTrackLengths2: failure!\n")); return __LINE__; -#endif // SKIP_SDL2_CDROM_ISSUES } DWORD *tracklen_LoadEncryptedKey( DWORD *trackLenBuf, const char *szFile ) @@ -371,28 +270,7 @@ DWORD *tracklen_LoadEncryptedKey( DWORD *trackLenBuf, const char *szFile ) char szTemp[MAX_PATH] = {0}; if( !strchr(szFile, ':' ) && strncmp( szFile, FILE_SEP FILE_SEP, 2 ) ) { -#if defined(WIN32) GetModuleFileName( NULL, szTemp, MAX_PATH ); -#elif defined(HAVE_UNISTD_H) && defined(LINUX) - char szLink[MAX_PATH] = { 0 }; - struct stat st = { 0 }; - pid_t pid = getpid(); - if (pid < 0) - return NULL; - - snprintf(szLink, sizeof(szLink) - 1, "/proc/%ld/exe", pid); - int rc = lstat(szLink, &st); - if (rc == -1) - return NULL; - - if (!S_ISLNK(st.st_mode)) - return NULL; - - int size = readlink(szLink, szTemp, sizeof(szTemp)); - if ((size < 0) || (static_cast(size) > sizeof(szTemp))) - return NULL; - szTemp[size] = 0; -#endif char *pos = (char*)strrchr(szTemp, FILE_SEPC); if (pos) { *pos = '\0'; @@ -405,52 +283,22 @@ DWORD *tracklen_LoadEncryptedKey( DWORD *trackLenBuf, const char *szFile ) else strcpy( szTemp, szFile ); -#ifdef WIN32 HANDLE hFile = CreateFile( szTemp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { -#else - FILE *f = fopen(szTemp, "r"); - - if (!f) - { - strcpy( szTemp, szFile ); - f = fopen(szTemp, "r"); - } - - if (!f) { -#endif tracklen_DPRINT((tracklen_buf, "tracklen_LoadEncryptedKey: can't open %s\n", szTemp)); return NULL; } -#ifdef WIN32 DWORD dwSize = GetFileSize( hFile, NULL ); -#else - struct stat st = { 0 }; - size_t dwSize = 0; - if (stat(szTemp, &st) == 0) { - dwSize = st.st_size; - } -#endif if ((dwSize < 4) || (dwSize % 4)) { tracklen_DPRINT((tracklen_buf, "tracklen_LoadEncryptedKey: %s bad size\n", szTemp)); -#ifdef WIN32 CloseHandle( hFile ); -#else - fclose(f); -#endif return NULL; } -#ifdef WIN32 DWORD ignore; ReadFile( hFile, trackLenBuf, dwSize, &ignore, NULL ); CloseHandle( hFile ); -#else - size_t ignore; - ignore = fread(trackLenBuf, 1, dwSize, f); - fclose(f); -#endif if( ignore < dwSize ) { tracklen_DPRINT((tracklen_buf, "tracklen_LoadEncryptedKey: file %s bad size 2\n", szTemp)); return NULL; @@ -541,13 +389,10 @@ BYTE tracklen_CheckTrackLengths( char *szVersionInfoBuffer ) #define AUTORUN_DEFAULT 0x95 #define AUTORUN_DISABLE 0xff -#if defined(WIN32) static ULONG s_oldAutoRunValue = AUTORUN_UNKNOWN; -#endif void tracklen_AutoPlay_Disable() { -#if defined(WIN32) int res; HKEY hkey; @@ -566,12 +411,10 @@ void tracklen_AutoPlay_Disable() RegFlushKey(hkey); RegCloseKey(hkey); } -#endif } void tracklen_AutoPlay_Restore() { -#if defined(WIN32) int res; HKEY hkey = NULL; @@ -585,5 +428,6 @@ void tracklen_AutoPlay_Restore() RegFlushKey(hkey); RegCloseKey(hkey); } -#endif } + +#endif // USE_SDL diff --git a/ctp2_code/ctp/ctp2_utils/tracklen.h b/ctp2_code/ctp/ctp2_utils/tracklen.h index dfdf57335..6fa499d69 100644 --- a/ctp2_code/ctp/ctp2_utils/tracklen.h +++ b/ctp2_code/ctp/ctp2_utils/tracklen.h @@ -27,14 +27,13 @@ #ifdef HAVE_PRAGMA_ONCE #pragma once #endif + #ifndef tracklen_h #define tracklen_h -#if defined(WIN32) +#if !defined(USE_SDL) + #include -#else -#include "windows.h" -#endif #ifdef __cplusplus extern "C" { @@ -62,11 +61,7 @@ char *tracklen_cryptAscii(char *s); void tracklen_cryptBinary(char *data, size_t len); DWORD *tracklen_LoadEncryptedKey( DWORD *trackLenBuf, const char *szFile ); -#if defined(WIN32) int tracklen_GetTrackLengths(DWORD *trackLenBuf, char whichDrive); -#else -int tracklen_GetTrackLengths(DWORD *trackLenBuf, int iDrive); -#endif char *GetVersionInfo( DWORD *trackLenBuffer ); BYTE tracklen_CheckTrackLengths( char *szVersionInfoBuffer = NULL ); void tracklen_AutoPlay_Disable(); @@ -76,4 +71,6 @@ void tracklen_AutoPlay_Restore(); } #endif -#endif +#endif // USE_SDL + +#endif // tracklen_h diff --git a/ctp2_code/gs/fileio/CivPaths.cpp b/ctp2_code/gs/fileio/CivPaths.cpp index 3cfd3b051..34f728224 100644 --- a/ctp2_code/gs/fileio/CivPaths.cpp +++ b/ctp2_code/gs/fileio/CivPaths.cpp @@ -84,7 +84,9 @@ void CivPaths_CleanupCivPaths() CivPaths::CivPaths(AUI_ERRCODE &errcode) : m_hdPath (new MBCHAR[_MAX_PATH]), +#if !defined(USE_SDL) m_cdPath (new MBCHAR[_MAX_PATH]), +#endif m_defaultPath (new MBCHAR[_MAX_PATH]), m_localizedPath (new MBCHAR[_MAX_PATH]), m_dataPath (new MBCHAR[_MAX_PATH]), @@ -132,7 +134,12 @@ CivPaths::CivPaths(AUI_ERRCODE &errcode) } fscanf(fin, "%s", m_hdPath); +#if defined(USE_SDL) + MBCHAR dummy[_MAX_PATH]; + fscanf(fin, "%s", dummy); +#else // USE_SDL fscanf(fin, "%s", m_cdPath); +#endif // USE_SDL fscanf(fin, "%s", m_defaultPath); fscanf(fin, "%s", m_localizedPath); fscanf(fin, "%s", m_dataPath); @@ -146,7 +153,9 @@ CivPaths::CivPaths(AUI_ERRCODE &errcode) fscanf(fin, "%s", m_saveClipsPath); ReplaceFileSeperator(m_hdPath); +#if !defined(USE_SDL) ReplaceFileSeperator(m_cdPath); +#endif // USE_SDL ReplaceFileSeperator(m_defaultPath); ReplaceFileSeperator(m_localizedPath); ReplaceFileSeperator(m_dataPath); @@ -189,7 +198,9 @@ CivPaths::~CivPaths() delete [] m_curScenarioPath; delete [] m_curScenarioPackPath; delete [] m_hdPath; +#if !defined(USE_SDL) delete [] m_cdPath; +#endif // USE_SDL delete [] m_defaultPath; delete [] m_localizedPath; delete [] m_dataPath; @@ -228,6 +239,7 @@ void CivPaths::CreateSaveFolders(const MBCHAR *path) c3files_CreateDirectory(subFolderPath); } +#if !defined(USE_SDL) void CivPaths::InitCDPath(void) { MBCHAR tempPath[_MAX_PATH] = {0}; @@ -236,27 +248,10 @@ void CivPaths::InitCDPath(void) if(ctpcd < 0) return; -#if defined(LINUX) - const MBCHAR *mount = c3files_GetCDDriveMount(tempPath, _MAX_PATH, ctpcd); - if(NULL == mount) - return; - - if(!m_cdPath[0]) - { - strcpy(tempPath, m_cdPath); - return; - } - - if(FILE_SEPC == m_cdPath[0]) - return; - - strcat(tempPath, FILE_SEP); - strcat(tempPath, m_cdPath); -#else // WIN32 sprintf(tempPath, "%c:%s%s", ctpcd, FILE_SEP, m_cdPath); -#endif strcpy(m_cdPath, tempPath); } +#endif // USE_SDL MBCHAR *CivPaths::MakeSavePath(MBCHAR *fullPath, MBCHAR *s1, MBCHAR *s2, MBCHAR *s3) { @@ -500,6 +495,7 @@ MBCHAR *CivPaths::FindFile(C3DIR dir, const MBCHAR *filename, MBCHAR *path, return path; } +#if !defined(USE_SDL) // The CD will only have the original content if (checkLocalizedPath && MakeAssetPath(fullPath, m_cdPath, m_dataPath, m_localizedPath, m_assetPaths[dir], filename)) { @@ -512,6 +508,7 @@ MBCHAR *CivPaths::FindFile(C3DIR dir, const MBCHAR *filename, MBCHAR *path, strcpy(path, fullPath); return path; } +#endif // !USE_SDL if (check_prjfile && ((dir == C3DIR_PATTERNS) || @@ -633,6 +630,7 @@ bool CivPaths::FindPath(C3DIR dir, int num, MBCHAR * path) sprintf(tempPath, "%s%s%s%s%s%s%s", m_hdPath, FILE_SEP, m_dataPath, FILE_SEP, m_defaultPath, FILE_SEP, m_assetPaths[dir]); break; +#if !defined(USE_SDL) case 6: if (m_cdPath && m_cdPath[0]) { @@ -647,7 +645,7 @@ bool CivPaths::FindPath(C3DIR dir, int num, MBCHAR * path) m_dataPath, FILE_SEP, m_defaultPath, FILE_SEP, m_assetPaths[dir]); } break; - +#endif // USE_SDL default: return false; } // switch diff --git a/ctp2_code/gs/fileio/CivPaths.h b/ctp2_code/gs/fileio/CivPaths.h index 0844e4557..18f3f2ed2 100644 --- a/ctp2_code/gs/fileio/CivPaths.h +++ b/ctp2_code/gs/fileio/CivPaths.h @@ -43,8 +43,9 @@ class CivPaths { private: MBCHAR *m_hdPath; +#if !defined(USE_SDL) MBCHAR *m_cdPath; - +#endif // USE_SDL MBCHAR *m_defaultPath; MBCHAR *m_localizedPath; @@ -76,7 +77,9 @@ class CivPaths { void CreateSaveFolders(const MBCHAR *path); +#if !defined(USE_SDL) void InitCDPath(void); +#endif MBCHAR *GetSavePath(C3SAVEDIR dir, MBCHAR *path); diff --git a/ctp2_code/sound/soundmanager.cpp b/ctp2_code/sound/soundmanager.cpp index 89d517cac..e1445eda5 100755 --- a/ctp2_code/sound/soundmanager.cpp +++ b/ctp2_code/sound/soundmanager.cpp @@ -34,7 +34,7 @@ // - #pragmas commented out // - Includes fixed for case sensitive filesystems // - Added sdl sound and cdrom support -// - Initialized local variables. (Sep 9th 2005 Martin G�hmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -59,12 +59,12 @@ SoundManager *g_soundManager = NULL; namespace { - uint32 const k_CHECK_CD_PERIOD = 4000; // [ms] + uint32 const k_CHECK_MUSIC_PERIOD = 4000; // [ms] uint32 const SLIDER_FULL = 10; #if !defined(USE_SDL) S32 s_masterVolume; -#endif +#endif // USE_SDL sint32 s_startTrack = 1; // skip CD data track } @@ -82,34 +82,31 @@ void SoundManager::Cleanup() SoundManager::SoundManager() : - m_sfxSounds (NULL), - m_voiceSounds (NULL), - m_soundWalker (NULL), - m_sfxVolume (SLIDER_FULL), - m_musicVolume (SLIDER_FULL), - m_voiceVolume (SLIDER_FULL), - m_oldRedbookVolume (0), - m_noSound (false), - m_usePlaySound (false), -#if !defined(USE_SDL) - m_redbook (0), -#else -#if !defined(SKIP_SDL2_CDROM_ISSUES) - m_cdrom (0), -#endif // SKIP_SDL2_CDROM_ISSUES - m_useOggTracks (false), - m_oggTrack (0), -#endif - m_timeToCheckCD (0), - m_numTracks (0), - m_curTrack (0), - m_lastTrack (0), - m_musicEnabled (false), - m_style (MUSICSTYLE_PLAYLIST), - m_playListPosition (0), - m_userTrack (0), - m_autoRepeat (true), - m_stopRedbookTemporarily (false) + m_sfxSounds (NULL), + m_voiceSounds (NULL), + m_soundWalker (NULL), + m_sfxVolume (SLIDER_FULL), + m_musicVolume (SLIDER_FULL), + m_voiceVolume (SLIDER_FULL), + m_oldRedbookVolume (0), + m_noSound (false), + m_usePlaySound (false), +#if defined(USE_SDL) + m_useOggTracks (false), + m_oggTrack (0), +#else // USE_SDL + m_redbook (0), +#endif // USE_SDL + m_timeToCheckMusic (0), + m_numTracks (0), + m_curTrack (0), + m_lastTrack (0), + m_musicEnabled (false), + m_style (MUSICSTYLE_PLAYLIST), + m_playListPosition (0), + m_userTrack (0), + m_autoRepeat (true), + m_stopRedbookTemporarily (false) { if (g_theProfileDB) { @@ -169,16 +166,15 @@ void SoundManager::InitSoundDriver() } m_noSound = (errcode < 0); -#else // !USE_SDL +#else // USE_SDL S32 use_digital = 1; S32 use_MIDI = 0; S32 output_rate = 22050; // 22khz @ 16 Bit stereo S32 output_bits = 16; S32 output_channels = 2; - m_noSound = !AIL_quick_startup - (use_digital, use_MIDI, output_rate, output_bits, output_channels); -#endif // defined(USE_SDL) + m_noSound = !AIL_quick_startup(use_digital, use_MIDI, output_rate, output_bits, output_channels); +#endif // USE_SDL InitRedbook(); @@ -199,7 +195,7 @@ void SoundManager::CleanupSoundDriver() } SDL_QuitSubSystem(SDL_INIT_AUDIO); -#else // !USE_SDL +#else // USE_SDL AIL_quick_shutdown(); #endif // USE_SDL } @@ -212,50 +208,10 @@ void SoundManager::InitRedbook() if( !m_useOggTracks) { if(CI_FileExists("music/Track02.ogg")) { m_useOggTracks = true; - printf("Detected Ogg Music track, using that instead of CD Audio\n"); + printf("Detected Ogg Music track\n"); } } -#if !defined(SKIP_SDL2_CDROM_ISSUES) - if (!m_cdrom && !m_useOggTracks) { - int errcode = SDL_Init(SDL_INIT_CDROM); - - Assert(0 == errcode); - if (errcode < 0) { - return; - } - - int numDrives = SDL_CDNumDrives(); - Assert(numDrives >= 0); - - int drive = -1; - int i = 0; - // Hack: We don't have the num of the SDL drive stored, - // so we search for the drive with the drive letter stored - MBCHAR driveLetter = toupper(c3files_GetCtpCdId()); - while ((i < numDrives) && (-1 == drive)) { - const char *cd_name = SDL_CDName(i); - if (cd_name) { - if (toupper(cd_name[0]) == driveLetter) { - drive = i; - } - } - i++; - } - - // No drive match?! - if (drive < 0) { - return; - } - m_cdrom = SDL_CDOpen(drive); - Assert(m_cdrom != 0); - // No control structur? - if (m_cdrom) - { - CDstatus status = SDL_CDStatus(m_cdrom); - } - } -#endif // SKIP_SLD2_CDROM_ISSUES -#else // !USE_SDL +#else // USE_SDL if (!m_redbook) { m_redbook = AIL_redbook_open_drive(c3files_GetCtpCdId()); @@ -270,19 +226,13 @@ void SoundManager::CleanupRedbook() Mix_FreeMusic(m_oggTrack); m_oggTrack = NULL; } -#if !defined(SKIP_SDL2_CDROM_ISSUES) - if (m_cdrom) { - SDL_CDClose(m_cdrom); - m_cdrom = 0; - } -#endif // SKIP_SDL2_CDROM_ISSUES -#else +#else // USE_SDL if (m_redbook) { AIL_redbook_stop(m_redbook); AIL_redbook_close(m_redbook); m_redbook = NULL; } -#endif +#endif // USE_SDL } void SoundManager::ProcessRedbook() @@ -291,52 +241,28 @@ void SoundManager::ProcessRedbook() if (!m_musicEnabled) return; -#if!defined(SKIP_SDL2_CDROM_ISSUES) - if (GetTickCount() > m_timeToCheckCD) { + if (GetTickCount() > m_timeToCheckMusic) { + #if defined(USE_SDL) - CDstatus status; if(m_useOggTracks) { if(!Mix_PlayingMusic()) { if (m_curTrack != -1) - PickNextTrack(); + PickNextTrack(); - if (m_curTrack != -1 && !m_stopRedbookTemporarily) - StartMusic(m_curTrack); + if (m_curTrack != -1 && !m_stopRedbookTemporarily) + StartMusic(m_curTrack); } } - if (m_cdrom) { - status = SDL_CDStatus(m_cdrom); -#else +#else // USE_SDL U32 status; if (m_redbook) { status = AIL_redbook_status(m_redbook); -#endif switch (status) { -#if !defined(USE_SDL) case REDBOOK_ERROR: -#else - case CD_TRAYEMPTY: - break; - case CD_ERROR: -#endif - break; -#if !defined(USE_SDL) case REDBOOK_PLAYING: -#else - case CD_PLAYING: -#endif - break; -#if !defined(USE_SDL) case REDBOOK_PAUSED: -#else - case CD_PAUSED: -#endif break; -#if !defined(USE_SDL) case REDBOOK_STOPPED: -#else - case CD_STOPPED: -#endif if (m_curTrack != -1) PickNextTrack(); @@ -345,10 +271,9 @@ void SoundManager::ProcessRedbook() break; } } - - m_timeToCheckCD = GetTickCount() + k_CHECK_CD_PERIOD; +#endif // USE_SDL + m_timeToCheckMusic = GetTickCount() + k_CHECK_MUSIC_PERIOD; } -#endif // SKIP_SDL2_CDROM_ISSUES } void SoundManager::Process(const uint32 &target_milliseconds, @@ -371,11 +296,11 @@ void SoundManager::Process(const uint32 &target_milliseconds, if (!sound) continue; if (sound->IsPlaying()) { -#if !defined(USE_SDL) +#if defined(USE_SDL) + if (!Mix_Playing(sound->GetChannel())) { +#else // USE_SDL if (AIL_quick_status(sound->GetHAudio()) == QSTAT_DONE) { -#else - if (!Mix_Playing(sound->GetChannel())) { -#endif +#endif // USE_SDL m_soundWalker->Remove(); delete sound; @@ -395,12 +320,12 @@ void SoundManager::Process(const uint32 &target_milliseconds, if (!sound) continue; if (sound->IsPlaying()) { -#if !defined(USE_SDL) +#if defined(USE_SDL) + if ((-1 == sound->GetChannel()) || + (!Mix_Playing(sound->GetChannel()))) { +#else // USE_SDL if (AIL_quick_status(sound->GetHAudio()) == QSTAT_DONE) { -#else - if ((-1 == sound->GetChannel()) || - (!Mix_Playing(sound->GetChannel()))) { -#endif +#endif // USE_SDL m_soundWalker->Remove(); delete sound; } else { @@ -488,12 +413,12 @@ SoundManager::AddSound(const SOUNDTYPE &type, } else { -#if !defined(USE_SDL) +#if defined(USE_SDL) + int channel = Mix_PlayChannel(-1, sound->GetAudio(), 0); + sound->SetChannel(channel); +#else // USE_SDL AIL_quick_play(sound->GetHAudio(), 1); -#else - int channel = Mix_PlayChannel(-1, sound->GetAudio(), 0); - sound->SetChannel(channel); -#endif +#endif // USE_SDL sound->SetIsPlaying(TRUE); } } @@ -534,12 +459,12 @@ SoundManager::AddLoopingSound(const SOUNDTYPE &type, break; } -#if !defined(USE_SDL) +#if defined(USE_SDL) + int channel = Mix_PlayChannel(-1, sound->GetAudio(), -1); + sound->SetChannel(channel); +#else // USE_SDL AIL_quick_play(sound->GetHAudio(), 0); -#else - int channel = Mix_PlayChannel(-1, sound->GetAudio(), -1); - sound->SetChannel(channel); -#endif +#endif // USE_SDL sound->SetIsLooping(TRUE); sound->SetIsPlaying(TRUE); @@ -553,14 +478,14 @@ SoundManager::TerminateLoopingSound(const SOUNDTYPE &type, if (!existingSound) return; -#if !defined(USE_SDL) - AIL_quick_halt(existingSound->GetHAudio()); +#if defined(USE_SDL) + int channel = existingSound->GetChannel(); + if (channel >= 0) { + Mix_HaltChannel(channel); + } + existingSound->SetChannel(-1); #else - int channel = existingSound->GetChannel(); - if (channel >= 0) { - Mix_HaltChannel(channel); - } - existingSound->SetChannel(-1); + AIL_quick_halt(existingSound->GetHAudio()); #endif } @@ -583,15 +508,15 @@ SoundManager::TerminateAllLoopingSounds(const SOUNDTYPE &type) while (node) { sound = node->GetObj(); if (sound && sound->IsLooping()) { -#if !defined(USE_SDL) +#if defined(USE_SDL) + int channel = sound->GetChannel(); + if (channel >= 0) { + Mix_HaltChannel(channel); + } + sound->SetChannel(-1); +#else // USE_SDL AIL_quick_halt(sound->GetHAudio()); -#else - int channel = sound->GetChannel(); - if (channel >= 0) { - Mix_HaltChannel(channel); - } - sound->SetChannel(-1); -#endif +#endif // USE_SDL } node = node->GetNext(); } @@ -616,14 +541,14 @@ SoundManager::TerminateSounds(const SOUNDTYPE &type) while (node) { sound = node->GetObj(); if (sound) { -#if !defined(USE_SDL) - AIL_quick_halt(sound->GetHAudio()); -#else - int channel = sound->GetChannel(); +#if defined(USE_SDL) + int channel = sound->GetChannel(); if (channel >= 0) { Mix_HaltChannel(channel); } -#endif +#else // USE_SDL + AIL_quick_halt(sound->GetHAudio()); +#endif // USE_SDL } node = node->GetNext(); } @@ -669,11 +594,8 @@ SoundManager::SetVolume(const SOUNDTYPE &type, const uint32 &volume) break; case SOUNDTYPE_MUSIC: m_musicVolume = volume; -#if !defined(USE_SDL) - if (m_redbook) - AIL_redbook_set_volume(m_redbook, (sint32)((double)volume * 12.7)); -#else - if (m_useOggTracks) { +#if defined(USE_SDL) + if (m_useOggTracks) { // Assume max volume is 10... sint32 scaledVolume = (sint32)((double)volume * 12.7); if (scaledVolume > MIX_MAX_VOLUME) { @@ -682,12 +604,10 @@ SoundManager::SetVolume(const SOUNDTYPE &type, const uint32 &volume) Mix_VolumeMusic(scaledVolume); } } -#if !defined(SKIP_SDL2_CDROM_ISSUES) - if (m_cdrom) { - // TODO: found nothing in reference - } -#endif // SKIP_SDL2_CDROM_ISSUES -#endif +#else // USE_SDL + if (m_redbook) + AIL_redbook_set_volume(m_redbook, (sint32)((double)volume * 12.7)); +#endif // USE_SDL break; } } @@ -872,14 +792,14 @@ SoundManager::SetPosition(const SOUNDTYPE &type, #if defined(USE_SDL) Mix_Chunk * myChunk = sound->GetAudio(); // Why set the volume again? -#else +#else // USE_SDL sint32 panValue = 64; HAUDIO hAudio = sound->GetHAudio(); if (hAudio) { AIL_quick_set_volume(hAudio, volume, panValue); } -#endif +#endif // USE_SDL } node = node->GetNext(); @@ -901,11 +821,11 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) { m_stopRedbookTemporarily = FALSE; -#if !defined(USE_SDL) - if (!g_theProfileDB->IsUseRedbookAudio() || !c3files_HasCD()) return; -#else if (!g_theProfileDB->IsUseRedbookAudio()) return; - if (!(c3files_HasCD() || m_useOggTracks)) return; +#if defined(USE_SDL) + if (!m_useOggTracks) return; +#else + if (!c3files_HasCD()) return; #endif if (m_noSound) return; @@ -947,23 +867,7 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) else printf("Error, music track %s not found\n", buf); - return; } -#if !defined(SKIP_SDL2_CDROM_ISSUES) - if (!m_cdrom) { - return; - } - - CDstatus status = SDL_CDStatus(m_cdrom); - - if ((CD_ERROR == status) || (!CD_INDRIVE(status))) { - return; - } - - sint32 const numTracks = m_cdrom->numtracks; -#else // SKIP_SDL2_CDROM_ISSUES - sint32 const numTracks = 0; -#endif // SKIP_SDL2_CDROM_ISSUES #else if (!m_redbook) { return; @@ -980,8 +884,6 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) } sint32 const numTracks = AIL_redbook_tracks(m_redbook); -#endif - if (numTracks <= s_startTrack) return; m_numTracks = numTracks; @@ -992,11 +894,6 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) m_curTrack = trackNum; -#if defined(USE_SDL) -#if !defined(SKIP_SDL2_CDROM_ISSUES) - SDL_CDPlayTracks(m_cdrom, trackNum, 0, 1, 0); -#endif // SKIP_SDL2_CDROM_ISSUES -#else U32 start; U32 end; AIL_redbook_track_info(m_redbook, trackNum, &start, &end); @@ -1005,30 +902,29 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) TerminateAllSounds(); AIL_redbook_play(m_redbook, start, end); -#endif +#endif // USE_SDL } void SoundManager::TerminateMusic(void) { - if (!g_theProfileDB->IsUseRedbookAudio() || !c3files_HasCD()) return; + if (!g_theProfileDB->IsUseRedbookAudio()) return; +#if !defined(USE_SDL) + if (!c3files_HasCD()) return; +#endif if (m_noSound) return; if (m_usePlaySound) return; -#if !defined(USE_SDL) // Does not compile and why the hell is this here? -// if (m_useOggTracks) { -// Mix_StopMUS(); -// if(m_oggTrack) { -// Mix_FreeMusic(m_oggTrack); -// m_oggTrack = NULL; -// } -// } - if (!m_redbook) return; +#if defined(USE_SDL) + if (m_useOggTracks) { + if(m_oggTrack) { + Mix_FreeMusic(m_oggTrack); + m_oggTrack = NULL; + } + } #else -#if !defined(SKIP_SDL2_CDROM_ISSUES) - if (!m_cdrom) return; -#endif // SKIP_SDL2_CDROM_ISSUES + if (!m_redbook) return; #endif m_stopRedbookTemporarily = TRUE; @@ -1037,14 +933,6 @@ void SoundManager::TerminateMusic(void) if (AIL_redbook_track(m_redbook)) { AIL_redbook_stop(m_redbook); } -#else -#if !defined(SKIP_SDL2_CDROM_ISSUES) - CDstatus status = SDL_CDStatus(m_cdrom); - - if (CD_PLAYING == status) { - SDL_CDStop(m_cdrom); - } -#endif // SKIP_SDL2_CDROM_ISSUES #endif } @@ -1108,11 +996,11 @@ void SoundManager::PlayManagedSound(const MBCHAR *fullFilename, const bool &bNoW #if !defined(USE_SDL) PlaySound(fullFilename, NULL, (SND_ASYNC | SND_FILENAME | (bNoWait ? SND_NOWAIT : 0))); -#else - std::cerr << "SoundManager::StupidPlaySound(" +#else // USE_SDL + std::cerr << "SoundManager::PlayManagedSound(" << fullFilename << ") called." << std::endl; -#endif +#endif // USE_SDL } void SoundManager::ReleaseSoundDriver() @@ -1133,7 +1021,7 @@ void SoundManager::ReleaseSoundDriver() S32 err = AIL_digital_handle_release(dig); Assert(err); -#endif +#endif // USE_SDL } void SoundManager::ReacquireSoundDriver() @@ -1151,5 +1039,5 @@ void SoundManager::ReacquireSoundDriver() Assert(err); AIL_set_digital_master_volume(dig, s_masterVolume); -#endif +#endif // USE_SDL } diff --git a/ctp2_code/sound/soundmanager.h b/ctp2_code/sound/soundmanager.h index 716fccdd5..9d16705f1 100644 --- a/ctp2_code/sound/soundmanager.h +++ b/ctp2_code/sound/soundmanager.h @@ -141,10 +141,6 @@ class SoundManager { void ReleaseSoundDriver(); void ReacquireSoundDriver(); -#if defined(USE_SDL) - void SDL_ChannelCompleteCB(int channel); -#endif - private: PointerList *m_sfxSounds; PointerList *m_voiceSounds; @@ -160,16 +156,13 @@ class SoundManager { BOOL m_noSound; BOOL m_usePlaySound; -#if !defined(USE_SDL) - HREDBOOK m_redbook; -#else - #if !defined(SKIP_SDL2_CDROM_ISSUES) - SDL_CD *m_cdrom; - #endif // SKIP_SDL2_CDROM_ISSUES +#if defined(USE_SDL) BOOL m_useOggTracks; Mix_Music *m_oggTrack; -#endif - uint32 m_timeToCheckCD; +#else // USE_SDL + HREDBOOK m_redbook; +#endif // USE_SDL + uint32 m_timeToCheckMusic; sint32 m_numTracks; sint32 m_curTrack; sint32 m_lastTrack; diff --git a/ctp2_code/ui/aui_common/aui_music.cpp b/ctp2_code/ui/aui_common/aui_music.cpp index 6bc6c1b18..024ab17e0 100644 --- a/ctp2_code/ui/aui_common/aui_music.cpp +++ b/ctp2_code/ui/aui_common/aui_music.cpp @@ -38,7 +38,6 @@ m_ctrack(-1), m_volume(0xff), m_pause(FALSE) { - return; } aui_Music::~aui_Music() @@ -58,14 +57,10 @@ aui_Music::SetVolume( uint8 volume ) return AUI_MUSIC_ERRCODE_OK; } +#if !defined(USE_SDL) + aui_Redbook::aui_Redbook() : -#ifdef __AUI_USE_DIRECTX__ m_cd_device_id(-1), -#elif defined(__AUI_USE_SDL__) -#if !defined(SKIP_SDL2_CDROM_ISSUES) -m_cd_device_id(0), -#endif // SKIP_SDL2_CDROM_ISSUES -#endif m_cd_drive_num(0), m_cd_drive_index(0), m_cd_ok(FALSE), @@ -76,13 +71,7 @@ m_aux_cdrom_id(-1) aui_Redbook::~aui_Redbook() { -#ifdef __AUI_USE_DIRECTX__ m_cd_device_id = -1; -#elif defined(__AUI_USE_SDL__) -#if !defined(SKIP_SDL2_CDROM_ISSUES) - m_cd_device_id = 0; -#endif // SKIP_SDL2_CDROM_ISSUES -#endif m_cd_drive_num = 0; m_cd_drive_index = 0; m_aux_cdrom_id = -1; @@ -92,7 +81,6 @@ aui_Redbook::~aui_Redbook() AUI_MUSIC_ERRCODE aui_Redbook::Init() { -#ifdef __AUI_USE_DIRECTX__ MCIERROR returnVal; MCI_OPEN_PARMS mciOpenParms; MCI_SET_PARMS mciSetParms; @@ -150,7 +138,6 @@ aui_Redbook::Init() } m_ntracks = mciStatusParms.dwReturn; -#endif m_first_track = 1; m_last_track = m_ntracks; @@ -163,57 +150,40 @@ aui_Redbook::Init() AUI_MUSIC_ERRCODE aui_Redbook::Close() { -#ifdef __AUI_USE_DIRECTX__ Stop(); return CDDone(); -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::Pause() { -#ifdef __AUI_USE_DIRECTX__ MCI_GENERIC_PARMS mciPauseParms; sint32 mci_retval = mciSendCommand( m_cd_device_id, MCI_PAUSE, 0, (DWORD)&mciPauseParms ); return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::Resume() { -#ifdef __AUI_USE_DIRECTX__ MCI_GENERIC_PARMS mciResumeParms; sint32 mci_retval = mciSendCommand( m_cd_device_id, MCI_RESUME, 0, (DWORD)&mciResumeParms ); return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::Stop() { -#ifdef __AUI_USE_DIRECTX__ MCI_GENERIC_PARMS mciStopParms; sint32 mci_retval = mciSendCommand( m_cd_device_id, MCI_STOP, 0, (DWORD)&mciStopParms ); return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::Play( sint32 itrack ) { -#ifdef __AUI_USE_DIRECTX__ if( (itrack < m_first_track) || (itrack > m_last_track) ) return AUI_MUSIC_ERRCODE_INVALID_TRACKNUMBER; @@ -226,29 +196,21 @@ aui_Redbook::Play( sint32 itrack ) m_ctrack = itrack; return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::Play() { -#ifdef __AUI_USE_DIRECTX__ MCI_PLAY_PARMS mciPlayParms; sint32 mci_retval = mciSendCommand(m_cd_device_id, MCI_PLAY, 0, (DWORD)&mciPlayParms); return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::SetVolume( uint8 volume ) { -#ifdef __AUI_USE_DIRECTX__ m_volume = volume; if (m_aux_cdrom_id == -1) @@ -261,16 +223,12 @@ aui_Redbook::SetVolume( uint8 volume ) sint32 mci_retval = auxSetVolume(m_aux_cdrom_id, CDvolume); return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } sint32 aui_Redbook::CDInitVolume() { int CDRomID = -1; -#ifdef __AUI_USE_DIRECTX__ int HowManyAuxDevices = auxGetNumDevs(); if (HowManyAuxDevices > 0) @@ -315,7 +273,6 @@ aui_Redbook::CDInitVolume() } } } -#endif return( CDRomID ); } @@ -323,7 +280,6 @@ aui_Redbook::CDInitVolume() AUI_MUSIC_ERRCODE aui_Redbook::GetCDIndex() { -#ifdef __AUI_USE_DIRECTX__ LPSTR driveMap = (LPSTR) calloc(105, sizeof(char)); GetLogicalDriveStrings(105, driveMap); @@ -346,7 +302,6 @@ aui_Redbook::GetCDIndex() m_cd_drive_index = 0; free(driveMap); -#endif return AUI_MUSIC_ERRCODE_OK; } @@ -354,23 +309,18 @@ aui_Redbook::GetCDIndex() AUI_MUSIC_ERRCODE aui_Redbook::CDDone() { -#ifdef __AUI_USE_DIRECTX__ MCI_GENERIC_PARMS mciCloseParms; sint32 mci_retval = mciSendCommand( m_cd_device_id, MCI_CLOSE, 0, (DWORD)(&mciCloseParms) ); m_cd_device_id = -1; return mci_retval? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_CODE aui_Redbook::Status() { -#ifdef __AUI_USE_DIRECTX__ if (m_cd_ok) { MCI_STATUS_PARMS mciStatusParms; @@ -406,7 +356,6 @@ aui_Redbook::Status() } return AUI_MUSIC_CODE_UNKNOWN; -#else - return AUI_MUSIC_CODE_EMPTY; -#endif } + +#endif // USE_SDL diff --git a/ctp2_code/ui/aui_common/aui_music.h b/ctp2_code/ui/aui_common/aui_music.h index 890c70757..ad35e209c 100644 --- a/ctp2_code/ui/aui_common/aui_music.h +++ b/ctp2_code/ui/aui_common/aui_music.h @@ -2,12 +2,6 @@ #define __AUI_MUSIC_H__ #include "aui_base.h" -#ifdef USE_SDL -#include -#if !defined(SKIP_SDL2_CDROM_ISSUES) -#include -#endif // SKIP_SDL2_CDROM_ISSUES -#endif enum AUI_MUSIC_CODE { @@ -72,6 +66,8 @@ class aui_Music : public aui_Base }; +#if !defined(USE_SDL) + class aui_Redbook : public aui_Music { public: @@ -97,13 +93,7 @@ class aui_Redbook : public aui_Music protected: -#ifdef __AUI_USE_DIRECTX__ sint32 m_cd_device_id; -#elif defined(__AUI_USE_SDL__) -#if !defined(SKIP_SDL2_CDROM_ISSUES) - SDL_CD*m_cd_device_id; -#endif // SKIP_SDL2_CDROM_ISSUES -#endif int m_cd_drive_num; sint32 m_cd_drive_index; BOOL m_cd_ok; @@ -111,4 +101,6 @@ class aui_Redbook : public aui_Music }; +#endif // USE_SDL + #endif diff --git a/ctp2_code/ui/interface/initialplayscreen.cpp b/ctp2_code/ui/interface/initialplayscreen.cpp index 8a805cc68..62ea07ff4 100644 --- a/ctp2_code/ui/interface/initialplayscreen.cpp +++ b/ctp2_code/ui/interface/initialplayscreen.cpp @@ -304,7 +304,12 @@ void initialplayscreen_tutorialPress(aui_Control *control, uint32 action, uint32 { if ( action != (uint32)AUI_BUTTON_ACTION_EXECUTE ) return; - if (c3files_HasLegalCD()) { +#if defined(USE_SDL) + bool legalGame = true; +#else // USE_SDL + bool legalGame = c3files_HasLegalCD(); +#endif // USE_SDL + if (legalGame) { if(initialplayscreen_removeMyWindow(action)) { g_theProfileDB->SetTutorialAdvice(TRUE); g_civApp->PostStartGameAction(); diff --git a/ctp2_code/ui/interface/loadsavescreen.cpp b/ctp2_code/ui/interface/loadsavescreen.cpp index 8d4799a65..407263d31 100644 --- a/ctp2_code/ui/interface/loadsavescreen.cpp +++ b/ctp2_code/ui/interface/loadsavescreen.cpp @@ -26,15 +26,15 @@ // // - Repaired memory leaks. // - Updated tribe index check. -// - Replaced the old civilisation database by a new one. (Aug 21st 2005 Martin Gühmann) -// - Standardized code (May 21st 2006 Martin Gühmann) +// - Replaced the old civilisation database by a new one. (Aug 21st 2005 Martin G�hmann) +// - Standardized code (May 21st 2006 Martin G�hmann) // //---------------------------------------------------------------------------- // // Remarks // // - This is the only file with some Activision comments left. -// - Fixed scenarios so that the from the civ choser selected civ is used. (2-Jan-2008 Martin Gühmann) +// - Fixed scenarios so that the from the civ choser selected civ is used. (2-Jan-2008 Martin G�hmann) // //---------------------------------------------------------------------------- @@ -642,7 +642,10 @@ void loadsavescreen_LoadGame(void) Assert(gameInfo); if (!gameInfo) return; + +#if !defined(USE_SDL) if (!c3files_HasLegalCD()) return; +#endif // USE_SDL if (SaveInfo * saveInfo = g_loadsaveWindow->GetSaveInfo()) { @@ -797,7 +800,12 @@ void loadsavescreen_LoadMPGame(void) } // SAM042099 check for a valid CD-ROM before allowing a game to be loaded - if ((!g_netfunc || g_netfunc->IsHost()) && !c3files_HasLegalCD()) +#if defined(USE_SDL) + bool legalGame = true; +#else // USE_SDL + bool legalGame = c3files_HasLegalCD(); +#endif // USE_SDL + if ((!g_netfunc || g_netfunc->IsHost()) && !legalGame) return; GameInfo * gameInfo = g_loadsaveWindow->GetGameInfo(); @@ -896,8 +904,10 @@ void loadsavescreen_SaveMPGame(void) void loadsavescreen_LoadSCENGame(void) { +#if !defined(USE_SDL) // SAM042099 check for a valid CD-ROM before allowing a game to be loaded if (!c3files_HasLegalCD()) return; +#endif // USE_SDL GameInfo *gameInfo = g_loadsaveWindow->GetGameInfo(); diff --git a/ctp2_code/ui/interface/spnewgamescreen.cpp b/ctp2_code/ui/interface/spnewgamescreen.cpp index 9015eed43..0937857dc 100644 --- a/ctp2_code/ui/interface/spnewgamescreen.cpp +++ b/ctp2_code/ui/interface/spnewgamescreen.cpp @@ -252,7 +252,12 @@ spnewgamescreen_startPress(aui_Control *control, uint32 action, uint32 data, voi { if ( action == uint32(AUI_BUTTON_ACTION_EXECUTE) ) { - if (c3files_HasLegalCD()) +#if defined(USE_SDL) + bool legalGame = true; +#else // USE_SDL + bool legalGame = c3files_HasLegalCD(); +#endif // USE_SDL + if (legalGame) { MBCHAR fieldText[k_MAX_NAME_LEN]; g_spNewGameWindow->m_spName->GetFieldText(fieldText, k_MAX_NAME_LEN); @@ -397,8 +402,11 @@ void spnewgamescreen_scenarioExitCallback(aui_Control *control, uint32 action, u ); if (c3files_PathIsValid(tempPath)) { + +#if !defined(USE_SDL) if(!c3files_HasLegalCD()) exit(0); +#endif // USE_SDL SaveInfo *saveInfo = new SaveInfo; diff --git a/ctp2_code/ui/netshell/allinonewindow.cpp b/ctp2_code/ui/netshell/allinonewindow.cpp index 34aa01d5e..49a3e06e5 100644 --- a/ctp2_code/ui/netshell/allinonewindow.cpp +++ b/ctp2_code/ui/netshell/allinonewindow.cpp @@ -28,11 +28,11 @@ // Modifications from the original Activision code: // // - Memory leak repaired. -// - Replaced old civilisation database by new one. (Aug 21st 2005 Martin Gühmann) +// - Replaced old civilisation database by new one. (Aug 21st 2005 Martin G�hmann) // - The ages in the summary are now displayed correctly. -// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) -// - Standardized code. (May 29th 2006 Martin Gühmann) -// - Replaced old civ selection button bank by list box. (2-Jan-2008 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin G�hmann) +// - Standardized code. (May 29th 2006 Martin G�hmann) +// - Replaced old civ selection button bank by list box. (2-Jan-2008 Martin G�hmann) // //---------------------------------------------------------------------------- @@ -3585,7 +3585,12 @@ void AllinoneWindow::OKButtonAction::Execute( if ( g_playersetup.IsReadyToLaunch() ) return; - if (g_netfunc->IsHost() && !c3files_HasLegalCD() ) +#if defined(USE_SDL) + bool legalGame = true; +#else // USE_SDL + bool legalGame = c3files_HasLegalCD(); +#endif // USE_SDL + if (g_netfunc->IsHost() && !legalGame ) { static ns_String donthavecd( "strings.system.donthavecd" ); g_netfunc->PushChatMessage( donthavecd.GetString() ); From 8f238475ae364e5183bc9b018b11d31cc3f94c51 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Sun, 19 Apr 2020 14:51:38 +0200 Subject: [PATCH 20/29] Render movie in window (movie-wonder) --- ctp2_code/ui/aui_common/aui_moviebutton.cpp | 5 + ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp | 127 ++++++++++++------- ctp2_code/ui/aui_sdl/aui_sdlmovie.h | 7 +- ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp | 7 +- ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h | 4 +- ctp2_code/ui/aui_sdl/aui_sdlui.cpp | 3 +- 6 files changed, 98 insertions(+), 55 deletions(-) diff --git a/ctp2_code/ui/aui_common/aui_moviebutton.cpp b/ctp2_code/ui/aui_common/aui_moviebutton.cpp index d00e31cea..6cf267244 100644 --- a/ctp2_code/ui/aui_common/aui_moviebutton.cpp +++ b/ctp2_code/ui/aui_common/aui_moviebutton.cpp @@ -172,6 +172,11 @@ AUI_ERRCODE aui_MovieButton::Idle( void ) if (m_ActionFunc) m_ActionFunc((aui_Control *)this, AUI_BUTTON_ACTION_EXECUTE, 0, NULL); } +#if defined(USE_SDL) + else { + m_window->AddDirtyRect( m_x, m_y, m_x + m_width, m_y + m_height ); + } +#endif // USE_SDL } } diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp index 1fe4a028c..330af2961 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp @@ -19,8 +19,7 @@ extern "C" { } #include #include "profileDB.h" - -#undef MOVIE_RESIZABLE_WINDOW +#include "aui_sdlsurface.h" #define MAX_QUEUE_SIZE (15 * 1024 * 1024) #define MIN_FRAMES 25 @@ -197,7 +196,6 @@ typedef struct VideoState { int frame_drops_early; int frame_drops_late; - SDL_Texture *vis_texture; SDL_Texture *vid_texture; double frame_timer; @@ -233,10 +231,8 @@ static int is_full_screen; static AVPacket flush_pkt; -#if defined(MOVIE_RESIZABLE_WINDOW) - static SDL_Window *window = NULL; -#endif // MOVIE_RESIZABLE_WINDOW static SDL_Renderer *renderer = NULL; +static SDL_Texture *background = NULL; static SDL_AudioDeviceID audio_dev; static const struct TextureFormatEntry { @@ -868,8 +864,6 @@ static void stream_close(VideoState *is) sws_freeContext(is->img_convert_ctx); sws_freeContext(is->sub_convert_ctx); av_free(is->filename); - if (is->vis_texture) - SDL_DestroyTexture(is->vis_texture); if (is->vid_texture) SDL_DestroyTexture(is->vid_texture); av_free(is); @@ -894,14 +888,6 @@ static int video_open(VideoState *is) w = screen_width ? screen_width : default_width; h = screen_height ? screen_height : default_height; -#if defined(MOVIE_RESIZABLE_WINDOW) - SDL_SetWindowSize(window, w, h); - SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); - if (is_full_screen) - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); - SDL_ShowWindow(window); -#endif - is->width = w; is->height = h; @@ -916,6 +902,9 @@ static void video_display(VideoState *is) SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); + if (!is_full_screen) { + SDL_RenderCopy(renderer, background, NULL, NULL); + } if (is->video_st) video_image_display(is); SDL_RenderPresent(renderer); @@ -1945,14 +1934,6 @@ static VideoState *stream_open(const char *filename, int startup_volume) } -static void toggle_full_screen(VideoState *is) -{ -#if defined(MOVIE_RESIZABLE_WINDOW) - is_full_screen = !is_full_screen; - SDL_SetWindowFullscreen(window, is_full_screen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); -#endif -} - static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) { double remaining_time = 0.0; SDL_PumpEvents(); @@ -1981,6 +1962,7 @@ aui_SDLMovie::aui_SDLMovie(AUI_ERRCODE *retval, const MBCHAR * filename) : aui_Movie(), m_videoState(NULL), m_renderer(NULL), + m_background(NULL), m_windowWidth(0), m_windowHeight(0), m_logicalWidth(0), @@ -1994,11 +1976,15 @@ aui_SDLMovie::aui_SDLMovie(AUI_ERRCODE *retval, const MBCHAR * filename) : aui_SDLMovie::~aui_SDLMovie() { Assert(!m_videoState); m_renderer = NULL; + m_background = NULL; } -void aui_SDLMovie::SetContext(SDL_Renderer *renderer, const int windowWidth, const int windowHeight) { +void aui_SDLMovie::SetContext(SDL_Renderer *renderer, SDL_Texture *background, const int windowWidth, + const int windowHeight) { Assert(renderer); + Assert(background); m_renderer = renderer; + m_background = background; m_windowWidth = windowWidth; m_windowHeight = windowHeight; } @@ -2014,13 +2000,10 @@ AUI_ERRCODE aui_SDLMovie::Unload() { AUI_ERRCODE aui_SDLMovie::Open(uint32 flags, aui_Surface *surface, RECT *rect) { #if defined(USE_SDL_FFMPEG) - if (!m_renderer) { + if (!m_renderer || (!(flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN) && !m_background)) { return AUI_ERRCODE_MOVIEFAILED; } - av_init_packet(&flush_pkt); - flush_pkt.data = (uint8_t *)&flush_pkt; - static SDL_RendererInfo renderer_info = {0}; SDL_GetRendererInfo(m_renderer, &renderer_info); if (!renderer_info.num_texture_formats) { @@ -2029,15 +2012,31 @@ AUI_ERRCODE aui_SDLMovie::Open(uint32 flags, aui_Surface *surface, RECT *rect) { return AUI_ERRCODE_MOVIEFAILED; } + m_flags = flags; renderer = m_renderer; - screen_width = m_windowWidth; - screen_height = m_windowHeight; + + av_init_packet(&flush_pkt); + flush_pkt.data = (uint8_t *)&flush_pkt; + + is_full_screen = m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN; SDL_RenderGetLogicalSize(renderer, &m_logicalWidth, &m_logicalHeight); - SDL_RenderSetLogicalSize(renderer, m_windowWidth, m_windowHeight); - autoexit = !(flags & k_AUI_MOVIE_PLAYFLAG_PLAYANDHOLD); + if (is_full_screen) { + screen_width = m_windowWidth; + screen_height = m_windowHeight; + SDL_RenderSetLogicalSize(renderer, m_windowWidth, m_windowHeight); + } else { + screen_width = rect->right - rect->left; + screen_height = rect->bottom - rect->top; + background = m_background; + } + autoexit = 1; // Adjust volume range ctp2 [0..10] -> ffmpeg [0..100] m_videoState = stream_open(m_filename, g_theProfileDB->GetSFXVolume() * 10); + if (m_videoState && !(m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN)) { + m_videoState->xleft = rect->left; + m_videoState->ytop = rect->top; + } return m_videoState ? AUI_ERRCODE_OK : AUI_ERRCODE_MOVIEFAILED; #else // USE_SDL_FFMPEG return AUI_ERRCODE_OK; @@ -2050,11 +2049,19 @@ AUI_ERRCODE aui_SDLMovie::Close() { SDL_ShowCursor(SDL_ENABLE); if (m_videoState) { Stop(); + if (m_flags & k_AUI_MOVIE_PLAYFLAG_PLAYANDHOLD) { + GrabLastFrame(); + } stream_close(m_videoState); m_videoState = NULL; } + + if (m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN) { + SDL_RenderSetLogicalSize(m_renderer, m_logicalWidth, m_logicalHeight); + } renderer = NULL; - SDL_RenderSetLogicalSize(m_renderer, m_logicalWidth, m_logicalHeight); + background = NULL; + m_flags = 0; m_isFinished = TRUE; #endif // USE_SDL_FFMPEG return AUI_ERRCODE_OK; @@ -2107,7 +2114,6 @@ AUI_ERRCODE aui_SDLMovie::Process() { BOOL done = FALSE; while (!done) { - double x; refresh_loop_wait_event(m_videoState, &event); switch (event.type) { case SDL_KEYDOWN: @@ -2120,12 +2126,6 @@ AUI_ERRCODE aui_SDLMovie::Process() { if (!m_videoState->width) continue; switch (event.key.keysym.sym) { - #if defined(MOVIE_RESIZABLE_WINDOW) - case SDLK_f: - toggle_full_screen(m_videoState); - m_videoState->force_refresh = 1; - break; - #endif case SDLK_p: toggle_pause(m_videoState); break; @@ -2138,7 +2138,7 @@ AUI_ERRCODE aui_SDLMovie::Process() { SDL_ShowCursor(1); cursor_hidden = 0; } else { - if (event.motion.type & SDL_BUTTON_LMASK != 0) { + if ((event.motion.type & SDL_BUTTON_LMASK != 0) && (m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN)) { done = TRUE; } } @@ -2146,17 +2146,14 @@ AUI_ERRCODE aui_SDLMovie::Process() { break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: - done = TRUE; + if (m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN) + done = TRUE; break; case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: screen_width = m_videoState->width = event.window.data1; screen_height = m_videoState->height = event.window.data2; - if (m_videoState->vis_texture) { - SDL_DestroyTexture(m_videoState->vis_texture); - m_videoState->vis_texture = NULL; - } case SDL_WINDOWEVENT_EXPOSED: m_videoState->force_refresh = 1; } @@ -2174,12 +2171,12 @@ AUI_ERRCODE aui_SDLMovie::Process() { } BOOL aui_SDLMovie::IsOpen() const { - return m_videoState != NULL; + return m_videoState != NULL || m_isFinished; } BOOL aui_SDLMovie::IsPlaying() const { #if defined(USE_SDL_FFMPEG) - return m_videoState && m_videoState->read_tid != NULL; + return m_videoState && m_videoState->read_tid; #else // USE_SDL_FFMPEG return FALSE; #endif // USE_SDL_FFMPEG @@ -2194,4 +2191,36 @@ BOOL aui_SDLMovie::IsPaused() const { #endif // USE_SDL_FFMPEG } +void aui_SDLMovie::GrabLastFrame() { + aui_SDLSurface *sdlSurface = dynamic_cast(GetDestSurface()); + if (sdlSurface) { + // Undo logical size if needed; to grab unscaled pixels + if (m_windowWidth != m_logicalWidth) { + SDL_RenderSetLogicalSize(m_renderer, m_windowWidth, m_windowHeight); + } + + SDL_Surface *surface = sdlSurface->GetSDLSurface(); + SDL_Texture *backgroundTexture = SDL_CreateTextureFromSurface(m_renderer, surface); + if (backgroundTexture) { + SDL_RenderClear(m_renderer); + + SDL_Rect surfaceRect = { 0, 0, surface->w, surface->h }; + SDL_RenderCopy(m_renderer, backgroundTexture, NULL, &surfaceRect); + + RECT *destRect = GetDestRect(); + SDL_Rect sdlSrcRect = {0, 0, destRect->right - destRect->left, destRect->bottom - destRect->top }; + SDL_Rect sdlDestRect = { destRect->left, destRect->top, sdlSrcRect.w, sdlSrcRect.h }; + SDL_RenderCopy(m_renderer, m_videoState->vid_texture, &sdlSrcRect, &sdlDestRect); + SDL_RenderReadPixels(m_renderer, &surfaceRect, surface->format->format, surface->pixels, surface->pitch); + + SDL_RenderClear(m_renderer); + SDL_DestroyTexture(backgroundTexture); + } + + // Reset logical size if needed + if (m_windowWidth != m_logicalWidth) { + SDL_RenderSetLogicalSize(m_renderer, m_logicalWidth, m_logicalHeight); + } + } +} #endif // defined(__AUI_USE_SDL__) diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmovie.h b/ctp2_code/ui/aui_sdl/aui_sdlmovie.h index 9979c0e86..5cfd6f01d 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmovie.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlmovie.h @@ -12,14 +12,14 @@ class VideoState; class SDL_Renderer; +class SDL_Texture; class SDL_Surface; -class SDL_Cursor; class aui_SDLMovie : public aui_Movie { public: aui_SDLMovie(AUI_ERRCODE *retval, const MBCHAR * filename = NULL); virtual ~aui_SDLMovie(); - void SetContext(SDL_Renderer *renderer, const int windowWidth, const int windowHeight); + void SetContext(SDL_Renderer *renderer, SDL_Texture *background, const int windowWidth, const int windowHeight); virtual AUI_ERRCODE Load(); virtual AUI_ERRCODE Unload(); @@ -40,9 +40,12 @@ class aui_SDLMovie : public aui_Movie { virtual BOOL IsPaused() const; private: + void GrabLastFrame(); + VideoState *m_videoState; SDL_Renderer *m_renderer; + SDL_Texture *m_background; int m_windowWidth; int m_windowHeight; int m_logicalWidth; diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp index 68d0e6d90..ef0d041d1 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp @@ -33,13 +33,16 @@ static int lockmgr(void **mtx, enum AVLockOp op) } #endif // USE_SDL_FFMPEG -aui_SDLMovieManager::aui_SDLMovieManager(SDL_Renderer *renderer, const int windowWidth, const int windowHeight) : +aui_SDLMovieManager::aui_SDLMovieManager(SDL_Renderer *renderer, SDL_Texture *background, const int windowWidth, + const int windowHeight) : aui_MovieManager(false), m_renderer(renderer), + m_background(background), m_windowWidth(windowWidth), m_windowHeight(windowHeight) { Assert(m_renderer); + Assert(m_background); m_movieResource = new aui_Resource(); #if defined(USE_SDL_FFMPEG) @@ -59,7 +62,7 @@ aui_SDLMovieManager::~aui_SDLMovieManager() { aui_Movie* aui_SDLMovieManager::Load(const MBCHAR *filename, C3DIR dir) { aui_SDLMovie *movie = m_movieResource->Load(filename, dir); - movie->SetContext(m_renderer, m_windowWidth, m_windowHeight); + movie->SetContext(m_renderer, m_background, m_windowWidth, m_windowHeight); return movie; } diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h index d435f8bcc..bd4cea65f 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h @@ -15,7 +15,8 @@ class aui_SDLMovieManager : public aui_MovieManager { public: - aui_SDLMovieManager(SDL_Renderer *sdlRenderer, const int windowWidth, const int windowHeight); + aui_SDLMovieManager(SDL_Renderer *sdlRenderer, SDL_Texture *background, const int windowWidth, + const int windowHeight); virtual ~aui_SDLMovieManager(); virtual aui_Movie *Load(const MBCHAR *filename, C3DIR dir = C3DIR_DIRECT); @@ -34,6 +35,7 @@ class aui_SDLMovieManager : public aui_MovieManager { aui_Resource *m_movieResource; SDL_Renderer *m_renderer; + SDL_Texture *m_background; int m_windowWidth; int m_windowHeight; }; diff --git a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp index 8a801f44f..9003ad2d8 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp @@ -349,10 +349,11 @@ AUI_ERRCODE aui_SDLUI::AltTabIn( void ) aui_MovieManager* aui_SDLUI::CreateMovieManager( void ) { Assert(m_SDLWindow); Assert(m_SDLRenderer); + Assert(m_SDLTexture); int windowWidth; int windowHeight; SDL_GetWindowSize(m_SDLWindow, &windowWidth, &windowHeight); - return new aui_SDLMovieManager(m_SDLRenderer, windowWidth, windowHeight); + return new aui_SDLMovieManager(m_SDLRenderer, m_SDLTexture, windowWidth, windowHeight); } AUI_ERRCODE aui_SDLUI::SDLDrawScreen( void ) { From 834003e234e3ed8929d5f9e56d94e268b0c5337c Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Wed, 22 Apr 2020 00:11:38 +0200 Subject: [PATCH 21/29] Handle mouse-events in main thread SDL2 strongly recommend to only call SDL_PumpEvents from the main-thread. Previously mouse-events were handled in a separate thread. This functionality has been moved to the main-thread. --- ctp2_code/ctp/civ3_main.cpp | 8 +- ctp2_code/ui/aui_common/aui_mouse.cpp | 169 +++++++----------- ctp2_code/ui/aui_common/aui_mouse.h | 65 +++---- ctp2_code/ui/aui_sdl/aui_sdl.cpp | 30 ++-- ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp | 154 ++++++++++------ ctp2_code/ui/aui_sdl/aui_sdlmouse.h | 14 +- ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp | 115 ++++++------ ctp2_code/ui/aui_sdl/aui_sdlmovie.h | 4 + ctp2_code/ui/aui_sdl/aui_sdlui.h | 5 +- ctp2_code/ui/interface/controlpanelwindow.cpp | 20 ++- .../default/uidata/layouts/wondermovie.ldl | 8 +- 11 files changed, 286 insertions(+), 306 deletions(-) diff --git a/ctp2_code/ctp/civ3_main.cpp b/ctp2_code/ctp/civ3_main.cpp index b6af30371..f357ce0cb 100644 --- a/ctp2_code/ctp/civ3_main.cpp +++ b/ctp2_code/ctp/civ3_main.cpp @@ -770,11 +770,7 @@ bool ui_CheckForScroll(void) isMouseScrolling = true; } - if(scrolled) { - if (isMouseScrolling) - g_cursorManager->SetCursor(scrollCursor); - if(!scrolled_last_time) { scroll_start = GetTickCount(); } @@ -800,6 +796,8 @@ bool ui_CheckForScroll(void) lastdeltaX = deltaX; lastdeltaY = deltaY; + if (isMouseScrolling) + g_cursorManager->SetCursor(scrollCursor); g_tiledMap->SetScrolling(true); uint32 accellTickDelta = s_scrollcurtick - s_accelTickStart; @@ -1033,8 +1031,6 @@ void AtExitProc(void) Mix_CloseAudio(); # endif -g_mouseShouldTerminateThread = TRUE; - // Destroy the mutex used for the secondary keyboard event queue #ifdef __AUI_USE_SDL__ SDL_DestroyMutex(g_secondaryKeyboardEventQueueMutex); diff --git a/ctp2_code/ui/aui_common/aui_mouse.cpp b/ctp2_code/ui/aui_common/aui_mouse.cpp index fc90207b4..54784e320 100644 --- a/ctp2_code/ui/aui_common/aui_mouse.cpp +++ b/ctp2_code/ui/aui_common/aui_mouse.cpp @@ -55,34 +55,15 @@ #include "ldl_data.hpp" #include "ldl_file.hpp" -sint32 aui_Mouse::m_mouseRefCount = 0; #ifdef __AUI_USE_DIRECTX__ +sint32 aui_Mouse::m_mouseRefCount = 0; LPCRITICAL_SECTION aui_Mouse::m_lpcs = NULL; -#elif defined(__AUI_USE_SDL__) -SDL_mutex *aui_Mouse::m_lpcs = NULL; -#endif - -#ifdef __AUI_USE_SDL__ -#define k_AUI_MOUSE_THREAD_SLEEP_TIME 10000 -#else #define k_AUI_MOUSE_THREAD_SLEEP_TIME 10 -#endif +#endif // __AUI_USE_DIRECTX__ #include "civapp.h" extern CivApp *g_civApp; -#ifdef LINUX -#include // usleep -#endif - -#ifdef __AUI_USE_SDL__ -BOOL g_mouseShouldTerminateThread = FALSE; -sint32 g_oldX = 0; -sint32 g_oldY = 0; -sint32 g_oldW = 0; -sint32 g_oldH = 0; -#endif - aui_Mouse::aui_Mouse ( AUI_ERRCODE * retval, @@ -110,13 +91,16 @@ AUI_ERRCODE aui_Mouse::InitCommon( void ) } else { m_sensitivity = 1.0; } - m_privateMix = NULL; - m_pickup = NULL; - m_prevPickup = NULL; m_suspendCount = 0; m_showCount = 0; m_reset = TRUE; -#ifndef __AUI_USE_SDL__ + m_flags = 0; + +#ifdef __AUI_USE_DIRECTX__ + m_privateMix = NULL; + m_pickup = NULL; + m_prevPickup = NULL; + m_thread = NULL; m_threadId = 0; m_threadEvent = NULL; @@ -124,41 +108,27 @@ AUI_ERRCODE aui_Mouse::InitCommon( void ) m_suspendEvent = NULL; m_resumeEvent = NULL; m_replyEvent = NULL; -#endif - m_flags = 0; +#endif // __AUI_USE_DIRECTX__ memset( m_cursors, 0, sizeof( m_cursors ) ); memset( &m_data, 0, sizeof( m_data ) ); memset( m_inputs, 0, sizeof( m_inputs ) ); SetClip( NULL ); + #ifdef __AUI_USE_DIRECTX__ GetCursorPos( &m_data.position ); -#elif defined(__AUI_USE_SDL__) - int x = 0, y = 0; - Uint8 state = SDL_GetMouseState(&x, &y); - m_data.position.x = x; - m_data.position.y = y; - g_oldX = g_oldY = g_oldW = g_oldH = 0; -#endif if ( !m_mouseRefCount++ ) { -#ifdef __AUI_USE_DIRECTX__ m_lpcs = new CRITICAL_SECTION; -#elif defined(__AUI_USE_SDL__) - m_lpcs = SDL_CreateMutex(); -#endif Assert( m_lpcs != NULL ); -#ifdef __AUI_USE_DIRECTX__ if ( m_lpcs ) InitializeCriticalSection( m_lpcs ); else -#elif defined(__AUI_USE_SDL__) - if (!m_lpcs) -#endif return AUI_ERRCODE_MEMALLOCFAILED; } +#endif // __AUI_USE_DIRECTX__ return AUI_ERRCODE_OK; } @@ -279,25 +249,22 @@ aui_Mouse::~aui_Mouse() memset( m_cursors, 0, sizeof( m_cursors ) ); } - DestroyPrivateBuffers(); - m_animIndexList.DeleteAll(); m_animDelayList.DeleteAll(); +#ifdef __AUI_USE_DIRECTX__ + DestroyPrivateBuffers(); + if ( !--m_mouseRefCount ) { if ( m_lpcs ) { -#ifdef __AUI_USE_SDL__ - SDL_DestroyMutex(m_lpcs); -#elif defined(__AUI_USE_DIRECTX__) - DeleteCriticalSection( m_lpcs ); delete m_lpcs; -#endif m_lpcs = NULL; } } +#endif // __AUI_USE_DIRECTX__ } void aui_Mouse::SetClip( sint32 left, sint32 top, sint32 right, sint32 bottom ) @@ -379,6 +346,9 @@ void aui_Mouse::SetAnimDelay( uint32 animDelay ) void aui_Mouse::SetAnimIndexes( sint32 firstIndex, sint32 lastIndex ) { + if (firstIndex == m_firstIndex && lastIndex == m_lastIndex) + return; + Assert( firstIndex >= 0 ); if ( firstIndex < 0 ) return; Assert( lastIndex >= 0 ); @@ -388,6 +358,7 @@ void aui_Mouse::SetAnimIndexes( sint32 firstIndex, sint32 lastIndex ) m_firstIndex = firstIndex; m_lastIndex = lastIndex; + SetCurrentCursor(m_firstIndex); } void aui_Mouse::SetAnim( sint32 anim ) @@ -400,21 +371,15 @@ void aui_Mouse::SetAnim( sint32 anim ) AUI_ERRCODE aui_Mouse::Start( void ) { - CreatePrivateBuffers(); - -#ifdef __AUI_USE_DIRECTX__ - m_thread = - CreateThread( NULL, 0, MouseThreadProc, (LPVOID)this, 0, &m_threadId ); -#elif defined(__AUI_USE_SDL__) - m_thread = SDL_CreateThread(MouseThreadProc, "Mouse-thread", this); -#endif - m_curCursor = m_cursors + m_firstIndex; ActivateCursor(*m_curCursor); +#ifdef __AUI_USE_DIRECTX__ + CreatePrivateBuffers(); + + m_thread = CreateThread( NULL, 0, MouseThreadProc, (LPVOID)this, 0, &m_threadId ); if ( m_thread ) { -#ifdef __AUI_USE_DIRECTX__ SetThreadPriority( m_thread, THREAD_PRIORITY_NORMAL ); m_threadEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); @@ -422,14 +387,16 @@ AUI_ERRCODE aui_Mouse::Start( void ) m_suspendEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); m_resumeEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); m_replyEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); -#endif Acquire(); } +#endif // __AUI_USE_DIRECTX__ return AUI_ERRCODE_OK; } +#ifdef __AUI_USE_DIRECTX__ + AUI_ERRCODE aui_Mouse::CreatePrivateBuffers( void ) { AUI_ERRCODE errcode = AUI_ERRCODE_OK; @@ -463,13 +430,15 @@ void aui_Mouse::DestroyPrivateBuffers( void ) m_prevPickup = NULL; } +#endif // __AUI_USE_DIRECTX__ + AUI_ERRCODE aui_Mouse::End( void ) { +#ifdef __AUI_USE_DIRECTX__ Unacquire(); if ( m_thread ) { -#ifdef __AUI_USE_DIRECTX__ if ( m_threadEvent && m_terminateEvent ) { SetEvent( m_terminateEvent ); @@ -486,16 +455,9 @@ AUI_ERRCODE aui_Mouse::End( void ) } else TerminateThread( m_thread, 1 ); -#elif defined(__AUI_USE_SDL__) - g_mouseShouldTerminateThread = TRUE; - - int status = 0; - SDL_WaitThread(m_thread, &status); -#endif Erase(); -#ifdef __AUI_USE_DIRECTX__ if ( m_suspendEvent ) { CloseHandle( m_suspendEvent ); @@ -517,20 +479,19 @@ AUI_ERRCODE aui_Mouse::End( void ) CloseHandle( m_thread ); m_threadId = 0; -#endif - m_thread = NULL; } -#ifdef __AUI_USE_DIRECTX__ SetCursorPos( m_data.position.x, m_data.position.y ); -#endif +#endif // __AUI_USE_DIRECTX__ return AUI_ERRCODE_OK; } AUI_ERRCODE aui_Mouse::Suspend( BOOL eraseCursor ) { +#ifdef __AUI_USE_DIRECTX__ if ( !m_thread ) return AUI_ERRCODE_NOTHREAD; +#endif // __AUI_USE_DIRECTX__ if ( m_suspendCount ) { @@ -568,12 +529,12 @@ AUI_ERRCODE aui_Mouse::Suspend( BOOL eraseCursor ) AUI_ERRCODE aui_Mouse::Resume( void ) { - +#ifdef __AUI_USE_DIRECTX__ if ( !m_thread ) return AUI_ERRCODE_NOTHREAD; +#endif // __AUI_USE_DIRECTX__ if ( m_suspendCount == 0 ) return AUI_ERRCODE_OK; - if ( m_suspendCount > 1 ) { m_suspendCount--; @@ -602,9 +563,11 @@ AUI_ERRCODE aui_Mouse::Resume( void ) #endif } +#ifdef __AUI_USE_DIRECTX__ + inline BOOL aui_Mouse::ShouldTerminateThread( void ) { -#ifdef __AUI_USE_DIRECTX__ + if ( WaitForSingleObject( m_threadEvent, 0 ) == WAIT_OBJECT_0 ) { ResetEvent( m_threadEvent ); @@ -626,27 +589,16 @@ inline BOOL aui_Mouse::ShouldTerminateThread( void ) } } return FALSE; - -#elif defined(__AUI_USE_SDL__) - return g_mouseShouldTerminateThread; -#endif } -#ifdef __AUI_USE_SDL__ -int MouseThreadProc(void *param) -#elif defined(__AUI_USE_DIRECTX__) DWORD WINAPI MouseThreadProc( LPVOID param ) -#endif { aui_Mouse *mouse = (aui_Mouse *)param; while ( !mouse->ShouldTerminateThread() ) { -#ifdef WIN32 Sleep(k_AUI_MOUSE_THREAD_SLEEP_TIME); -#elif defined(LINUX) - usleep(k_AUI_MOUSE_THREAD_SLEEP_TIME); -#endif + // For that something is wrong with the mouse delay // std::this_thread::sleep_for(std::chrono::milliseconds(k_AUI_MOUSE_THREAD_SLEEP_TIME)); @@ -659,6 +611,8 @@ DWORD WINAPI MouseThreadProc( LPVOID param ) return 0; } +#endif // __AUI_USE_DIRECTX__ + AUI_ERRCODE aui_Mouse::SetPosition( sint32 x, sint32 y ) { if ( x < m_clip.left ) x = m_clip.left; @@ -711,6 +665,7 @@ AUI_ERRCODE aui_Mouse::SetHotspot( sint32 x, sint32 y, sint32 index ) AUI_ERRCODE aui_Mouse::ReactToInput( void ) { +#ifdef __AUI_USE_DIRECTX__ if ( IsHidden() || ((*m_curCursor) == NULL)) return AUI_ERRCODE_OK; POINT hotspot; @@ -883,6 +838,7 @@ AUI_ERRCODE aui_Mouse::ReactToInput( void ) CopyRect( &prevRect, &rect ); CopyRect( &prevUnclippedMixRect, &unclippedMixRect ); +#endif // __AUI_USE_DIRECTX__ return AUI_ERRCODE_OK; } @@ -916,6 +872,8 @@ AUI_ERRCODE aui_Mouse::HandleAnim( void ) AUI_ERRCODE aui_Mouse::BltWindowToPrimary( aui_Window *window ) { AUI_ERRCODE retcode = AUI_ERRCODE_OK; + +#ifdef __AUI_USE_DIRECTX__ AUI_ERRCODE errcode; sint32 windowX = window->X(); @@ -998,12 +956,7 @@ AUI_ERRCODE aui_Mouse::BltWindowToPrimary( aui_Window *window ) &screenDirtyRect, RGB(255,255,255), 0 ); -#ifdef WIN32 Sleep( 20 ); -#elif defined(LINUX) - struct timespec t = { 0, 20000000L }; - nanosleep(&t, NULL); -#endif fclose(f); } #endif @@ -1035,6 +988,7 @@ AUI_ERRCODE aui_Mouse::BltWindowToPrimary( aui_Window *window ) break; } } +#endif // __AUI_USE_DIRECTX__ return retcode; } @@ -1042,6 +996,8 @@ AUI_ERRCODE aui_Mouse::BltWindowToPrimary( aui_Window *window ) AUI_ERRCODE aui_Mouse::BltDirtyRectInfoToPrimary( void ) { AUI_ERRCODE retcode = AUI_ERRCODE_OK; + +#ifdef __AUI_USE_DIRECTX__ AUI_ERRCODE errcode; if (g_civApp->IsInBackground()) return retcode; @@ -1147,12 +1103,7 @@ AUI_ERRCODE aui_Mouse::BltDirtyRectInfoToPrimary( void ) &screenDirtyRect, RGB(255,255,255), 0 ); -#ifdef WIN32 Sleep( 20 ); -#elif defined(LINUX) - struct timespec t = { 0, 20000000L }; - nanosleep(&t, NULL); -#endif } #endif @@ -1200,6 +1151,7 @@ AUI_ERRCODE aui_Mouse::BltDirtyRectInfoToPrimary( void ) errcode = g_ui->Secondary()->Unlock( primaryBuf ); Assert( errcode == AUI_ERRCODE_OK ); } +#endif // __AUI_USE_DIRECTX__ return retcode; } @@ -1209,6 +1161,8 @@ AUI_ERRCODE aui_Mouse::BltBackgroundColorToPrimary( aui_DirtyList *colorAreas ) { AUI_ERRCODE retcode = AUI_ERRCODE_OK; + +#ifdef __AUI_USE_DIRECTX__ AUI_ERRCODE errcode; if (g_civApp->IsInBackground()) return retcode; @@ -1319,6 +1273,7 @@ AUI_ERRCODE aui_Mouse::BltBackgroundColorToPrimary( } } } +#endif // __AUI_USE_DIRECTX__ return retcode; } @@ -1329,6 +1284,8 @@ AUI_ERRCODE aui_Mouse::BltBackgroundImageToPrimary( aui_DirtyList *imageAreas ) { AUI_ERRCODE retcode = AUI_ERRCODE_OK; + +#ifdef __AUI_USE_DIRECTX__ AUI_ERRCODE errcode; if (g_civApp->IsInBackground()) return retcode; @@ -1453,10 +1410,13 @@ AUI_ERRCODE aui_Mouse::BltBackgroundImageToPrimary( } } } +#endif // __AUI_USE_DIRECTX__ return retcode; } +#ifdef __AUI_USE_DIRECTX__ + AUI_ERRCODE aui_Mouse::Erase( void ) { AUI_ERRCODE errcode; @@ -1493,16 +1453,18 @@ AUI_ERRCODE aui_Mouse::Erase( void ) return AUI_ERRCODE_OK; } + +#endif // __AUI_USE_DIRECTX__ + sint32 aui_Mouse::ManipulateInputs( aui_MouseEvent *data, BOOL add ) { sint32 numManipulated = 0; - static sint32 index = 0; #ifdef __AUI_USE_DIRECTX__ + + static sint32 index = 0; + EnterCriticalSection( m_lpcs ); -#elif defined(__AUI_USE_SDL__) - SDL_mutexP(m_lpcs); -#endif if ( add ) { @@ -1542,11 +1504,8 @@ sint32 aui_Mouse::ManipulateInputs( aui_MouseEvent *data, BOOL add ) index = 0; } -#ifdef __AUI_USE_DIRECTX__ LeaveCriticalSection( m_lpcs ); -#elif defined(__AUI_USE_SDL__) - SDL_mutexV(m_lpcs); -#endif +#endif // __AUI_USE_DIRECTX__ return numManipulated; } diff --git a/ctp2_code/ui/aui_common/aui_mouse.h b/ctp2_code/ui/aui_common/aui_mouse.h index 3bf97aa63..6325a26a9 100644 --- a/ctp2_code/ui/aui_common/aui_mouse.h +++ b/ctp2_code/ui/aui_common/aui_mouse.h @@ -35,11 +35,6 @@ #include "aui_input.h" #include "tech_wllist.h" -#ifdef USE_SDL -#include -#include -#endif - class aui_Cursor; class aui_Surface; class aui_Window; @@ -47,12 +42,6 @@ class aui_Image; class aui_DirtyList; class ldl_datablock; -#ifdef USE_SDL -// HACK: Use this global variable to halt mouse event handling -// thread on game exit -extern BOOL g_mouseShouldTerminateThread; -#endif - #define k_MOUSE_LDL_NUMCURSORS "numcursors" #define k_MOUSE_LDL_ANIM "anim" #define k_MOUSE_LDL_CURSOR "cursor" @@ -166,17 +155,15 @@ class aui_Mouse : public aui_Base, public virtual aui_Input if ( firstIndex ) *firstIndex = m_firstIndex; if ( lastIndex ) * lastIndex = m_lastIndex; } - void SetAnimIndexes( sint32 firstIndex, sint32 lastIndex ); + virtual void SetAnimIndexes( sint32 firstIndex, sint32 lastIndex ); void SetAnim( sint32 anim ); virtual AUI_ERRCODE ReactToInput( void ); - BOOL ShouldTerminateThread( void ); + virtual sint32 ManipulateInputs( aui_MouseEvent *data, BOOL add ); - sint32 ManipulateInputs( aui_MouseEvent *data, BOOL add ); - - AUI_ERRCODE HandleAnim( void ); + virtual AUI_ERRCODE HandleAnim( void ); virtual AUI_ERRCODE BltWindowToPrimary( aui_Window *window ); virtual AUI_ERRCODE BltDirtyRectInfoToPrimary( void ); @@ -188,36 +175,21 @@ class aui_Mouse : public aui_Base, public virtual aui_Input RECT *imageRect, aui_DirtyList *imageAreas ); -#ifdef __AUI_USE_SDL__ - SDL_mutex *LPCS(void) const { return m_lpcs; } -#else +#if defined(__AUI_USE_DIRECTX__) LPCRITICAL_SECTION LPCS( void ) const { return m_lpcs; } -#endif - - virtual AUI_ERRCODE CreatePrivateBuffers( void ); - virtual void DestroyPrivateBuffers( void ); +#endif // __AUI_USE_DIRECTX__ uint32 GetFlags(void) { return m_flags;} void SetFlags(uint32 flags) { m_flags = flags; } protected: static sint32 m_mouseRefCount; -#ifdef __AUI_USE_SDL__ - static SDL_mutex* m_lpcs; -#else - static LPCRITICAL_SECTION m_lpcs; -#endif virtual void ActivateCursor(aui_Cursor *cursor) {} - virtual AUI_ERRCODE Erase( void ); - aui_MouseEvent m_data; double m_sensitivity; aui_MouseEvent m_inputs[ k_MOUSE_MAXINPUT ]; - aui_Surface *m_privateMix; - aui_Surface *m_pickup; - aui_Surface *m_prevPickup; RECT m_clip; aui_Cursor *m_cursors[ k_MOUSE_MAXNUMCURSORS ]; @@ -233,10 +205,20 @@ class aui_Mouse : public aui_Base, public virtual aui_Input sint32 m_suspendCount; sint32 m_showCount; BOOL m_reset; + uint32 m_flags; + +#if defined(__AUI_USE_DIRECTX__) + AUI_ERRCODE CreatePrivateBuffers( void ); + void DestroyPrivateBuffers( void ); + AUI_ERRCODE Erase( void ); + + BOOL ShouldTerminateThread( void ); + + aui_Surface *m_privateMix; + aui_Surface *m_pickup; + aui_Surface *m_prevPickup; -#ifdef __AUI_USE_SDL__ - SDL_Thread *m_thread; -#elif defined(__AUI_USE_DIRECTX__) + static LPCRITICAL_SECTION m_lpcs; HANDLE m_thread; DWORD m_threadId; HANDLE m_threadEvent; @@ -244,16 +226,11 @@ class aui_Mouse : public aui_Base, public virtual aui_Input HANDLE m_suspendEvent; HANDLE m_resumeEvent; HANDLE m_replyEvent; -#endif - - uint32 m_flags; +#endif // __AUI_USE_DIRECTX__ }; - -#ifdef __AUI_USE_SDL__ -int MouseThreadProc(void *param); -#else +#if defined(__AUI_USE_DIRECTX__) DWORD WINAPI MouseThreadProc( LPVOID lpVoid ); -#endif +#endif // __AUI_USE_DIRECTX__ #endif diff --git a/ctp2_code/ui/aui_sdl/aui_sdl.cpp b/ctp2_code/ui/aui_sdl/aui_sdl.cpp index fe679e28b..59efd343e 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdl.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdl.cpp @@ -19,21 +19,21 @@ sint32 aui_SDL::m_SDLRefCount = 0; // */ int FilterEvents(void* userData, SDL_Event *event) { - switch(event->type) { - // Quit event - case SDL_QUIT: - // Keyboard events - case SDL_KEYDOWN: - case SDL_KEYUP: - // Mouse events - case SDL_MOUSEMOTION: - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - case SDL_MOUSEWHEEL: - return 1; - default: - return 0; - } + switch(event->type) { + // Quit event + case SDL_QUIT: + // Keyboard events + case SDL_KEYDOWN: + case SDL_KEYUP: + // Mouse events + case SDL_MOUSEMOTION: + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEWHEEL: + return 1; + default: + return 0; + } } AUI_ERRCODE aui_SDL::InitCommon(BOOL useExclusiveMode) diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp index e2f797ccd..42724fb05 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp @@ -17,7 +17,11 @@ extern CivApp *g_civApp; -// SKIP_SDL2_EVENT_ISSUES: TODO: scrolling with mouse (screen sides) is too fast to be useful +uint32 HandleMouseAnimation(uint32 interval, void *param) { + aui_SDLMouse *mouse = (aui_SDLMouse*) param; + mouse->HandleAnim(); + return interval; +} aui_SDLMouse::aui_SDLMouse( AUI_ERRCODE *retval, @@ -27,14 +31,24 @@ aui_SDLMouse::aui_SDLMouse( aui_Input(), aui_Mouse(retval, ldlBlock), aui_SDLInput(retval, useExclusiveMode), - m_currentCursor(NULL) + m_currentCursor(NULL), + m_animationTimer(0) { Assert(AUI_SUCCESS(*retval)); if (!AUI_SUCCESS(*retval)) return; + + int x = 0, y = 0; + SDL_GetMouseState(&x, &y); + m_data.position.x = x; + m_data.position.y = y; } aui_SDLMouse::~aui_SDLMouse() { + if (m_animationTimer) { + SDL_RemoveTimer(m_animationTimer); + m_animationTimer = 0; + } End(); } @@ -62,59 +76,89 @@ void HandleMouseWheel(sint16 delta) fprintf(stderr, "%s L%d: Mouse wheel for SDL not handled!\n", __FILE__, __LINE__); } -AUI_ERRCODE -aui_SDLMouse::GetInput(void) -{ - m_data.time = SDL_GetTicks(); - bool haveMoves = false; - SDL_PumpEvents(); - - SDL_Event od[10]; - // check for one of the mouse events - int numElements = SDL_PeepEvents(od, 10, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEWHEEL); - if (0 > numElements) { - fprintf(stderr, "Mouse PeepEvents failed: %s\n", SDL_GetError()); - return AUI_ERRCODE_GETDEVICEDATAFAILED; - } - if (0 == numElements) { - if(haveMoves) - return AUI_ERRCODE_OK; - else - return AUI_ERRCODE_NOINPUT; - } - sint32 ev = 0; - while(ev < numElements) { - switch (od[ev].type) { - case SDL_MOUSEMOTION: - m_data.position.x = od[ev].motion.x; - m_data.position.y = od[ev].motion.y; - m_data.lbutton = !!(od[ev].motion.state & SDL_BUTTON_LMASK); - m_data.rbutton = !!(od[ev].motion.state & SDL_BUTTON_RMASK); - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - m_data.position.x = od[ev].button.x; - m_data.position.y = od[ev].button.y; - if (od[ev].button.button == SDL_BUTTON_LEFT) { - m_data.lbutton = od[ev].button.state == SDL_PRESSED; - } else if (od[ev].button.button == SDL_BUTTON_RIGHT) { - m_data.rbutton = od[ev].button.state == SDL_PRESSED; - } - break; - case SDL_MOUSEWHEEL: - if (od[ev].wheel.y > 0) { - HandleMouseWheel((sint16)1); - } else if (od[ev].wheel.y < 0) { - HandleMouseWheel((sint16)-1); - } - break; - default: - printf("event not handled: %d\n", od[ev].type); - break; - } - ev++; - } - return AUI_ERRCODE_OK; +AUI_ERRCODE aui_SDLMouse::HandleAnim() { + assert(m_lastIndex > m_firstIndex); + assert(m_curCursor >= m_cursors + m_firstIndex); + + if (m_curCursor++ >= m_cursors + m_lastIndex) { + m_curCursor = m_cursors + m_firstIndex; + } + ActivateCursor(*m_curCursor); + return AUI_ERRCODE_HANDLED; +} + +sint32 aui_SDLMouse::ManipulateInputs(aui_MouseEvent *data, BOOL add) { + assert(!add); + + SDL_PumpEvents(); + + SDL_Event sdlEvents[k_MOUSE_MAXINPUT]; + // check for mouse events + int numberSDLEvents = SDL_PeepEvents(sdlEvents, k_MOUSE_MAXINPUT, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEWHEEL); + if (0 > numberSDLEvents) { + fprintf(stderr, "Mouse PeepEvents failed: %s\n", SDL_GetError()); + return 0; + } + + int numberEvents = 0; + for (int i = 0; i < numberSDLEvents; i++) { + aui_MouseEvent *event = data + numberEvents; + switch (sdlEvents[i].type) { + case SDL_MOUSEMOTION: { + SDL_MouseMotionEvent *motionEvent = &(sdlEvents[i].motion); + event->time = motionEvent->timestamp; + event->position.x = motionEvent->x; + event->position.y = motionEvent->y; + event->lbutton = ((motionEvent->state & SDL_BUTTON_LMASK) != 0); + event->rbutton = ((motionEvent->state & SDL_BUTTON_RMASK) != 0); + numberEvents++; + break; + } + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: { + SDL_MouseButtonEvent *buttonEvent = &(sdlEvents[i].button); + event->time = buttonEvent->timestamp; + event->position.x = buttonEvent->x; + event->position.y = buttonEvent->y; + if (buttonEvent->button == SDL_BUTTON_LEFT) { + event->lbutton = (buttonEvent->state == SDL_PRESSED); + } else if (buttonEvent->button == SDL_BUTTON_RIGHT) { + event->rbutton = (buttonEvent->state == SDL_PRESSED); + } + numberEvents++; + break; + } + case SDL_MOUSEWHEEL: { + if (sdlEvents[i].wheel.y > 0) { + HandleMouseWheel((sint16) 1); + } else if (sdlEvents[i].wheel.y < 0) { + HandleMouseWheel((sint16) -1); + } + break; + } + default: + printf("event not handled: %d\n", sdlEvents[i].type); + break; + } + } + if (numberEvents) { + m_data = data[numberEvents - 1]; + } + return numberEvents; +} + +void aui_SDLMouse::SetAnimIndexes(sint32 firstIndex, sint32 lastIndex) { + if (firstIndex == m_firstIndex && lastIndex == m_lastIndex) + return; + + if (m_animationTimer) { + SDL_RemoveTimer(m_animationTimer); + m_animationTimer = 0; + } + aui_Mouse::SetAnimIndexes(firstIndex, lastIndex); + if (firstIndex != lastIndex) { + m_animationTimer = SDL_AddTimer(m_animDelay, HandleMouseAnimation, this); + } } void aui_SDLMouse::ActivateCursor(aui_Cursor *cursor) diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmouse.h b/ctp2_code/ui/aui_sdl/aui_sdlmouse.h index ab9e9271f..b5039bd3e 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmouse.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlmouse.h @@ -15,10 +15,12 @@ class aui_SDLMouse : public aui_Mouse, public aui_SDLInput { public: - aui_SDLMouse(AUI_ERRCODE *retval, const MBCHAR *ldlBlock, - BOOL useExclusiveMode = FALSE); + aui_SDLMouse(AUI_ERRCODE *retval, const MBCHAR *ldlBlock, BOOL useExclusiveMode = FALSE); virtual ~aui_SDLMouse(); + virtual AUI_ERRCODE HandleAnim(); + virtual void SetAnimIndexes(sint32 firstIndex, sint32 lastIndex); + virtual AUI_ERRCODE BltWindowToPrimary(aui_Window *window); virtual AUI_ERRCODE BltDirtyRectInfoToPrimary(); virtual AUI_ERRCODE BltBackgroundColorToPrimary(COLORREF color, aui_DirtyList *colorAreas); @@ -29,15 +31,13 @@ class aui_SDLMouse : public aui_Mouse, public aui_SDLInput virtual void ActivateCursor(aui_Cursor *cursor); - virtual AUI_ERRCODE Erase() { return AUI_ERRCODE_OK; } - virtual AUI_ERRCODE GetInput(); + virtual AUI_ERRCODE GetInput() {} virtual AUI_ERRCODE ReactToInput() {} - - virtual AUI_ERRCODE CreatePrivateBuffers() { return AUI_ERRCODE_OK; } - virtual void DestroyPrivateBuffers() {} + virtual sint32 ManipulateInputs(aui_MouseEvent *data, BOOL add); private: aui_Cursor *m_currentCursor; + SDL_TimerID m_animationTimer; }; typedef aui_SDLMouse aui_NativeMouse; diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp index 330af2961..8d56e1068 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp @@ -221,7 +221,6 @@ static int default_height = 480; static int screen_width = 0; static int screen_height = 0; static int av_sync_type = AV_SYNC_AUDIO_MASTER; -static int autoexit = 0; static int infinite_buffer = -1; static int64_t cursor_last_shown; static int cursor_hidden = 0; @@ -1836,10 +1835,8 @@ static int read_thread(void *arg) if (!is->paused && (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) && (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) { - if (autoexit) { - ret = AVERROR_EOF; - goto fail; - } + ret = AVERROR_EOF; + goto fail; } ret = av_read_frame(ic, pkt); if (ret < 0) { @@ -1938,7 +1935,7 @@ static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) { double remaining_time = 0.0; SDL_PumpEvents(); while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) { - if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) { + if (is_full_screen && !cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) { SDL_ShowCursor(0); cursor_hidden = 1; } @@ -2029,7 +2026,6 @@ AUI_ERRCODE aui_SDLMovie::Open(uint32 flags, aui_Surface *surface, RECT *rect) { screen_height = rect->bottom - rect->top; background = m_background; } - autoexit = 1; // Adjust volume range ctp2 [0..10] -> ffmpeg [0..100] m_videoState = stream_open(m_filename, g_theProfileDB->GetSFXVolume() * 10); @@ -2112,58 +2108,10 @@ AUI_ERRCODE aui_SDLMovie::Process() { /* handle an event sent by the GUI */ SDL_Event event; - BOOL done = FALSE; - while (!done) { + bool movieFinished = false; + while (!movieFinished) { refresh_loop_wait_event(m_videoState, &event); - switch (event.type) { - case SDL_KEYDOWN: - if (event.key.keysym.sym == SDLK_ESCAPE || event.key.keysym.sym == SDLK_SPACE - || event.key.keysym.sym == SDLK_q) { - done = TRUE; - break; - } - // If we don't yet have a window, skip all key events, because read_thread might still be initializing... - if (!m_videoState->width) - continue; - switch (event.key.keysym.sym) { - case SDLK_p: - toggle_pause(m_videoState); - break; - default: - break; - } - break; - case SDL_MOUSEMOTION: - if (cursor_hidden) { - SDL_ShowCursor(1); - cursor_hidden = 0; - } else { - if ((event.motion.type & SDL_BUTTON_LMASK != 0) && (m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN)) { - done = TRUE; - } - } - cursor_last_shown = av_gettime_relative(); - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - if (m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN) - done = TRUE; - break; - case SDL_WINDOWEVENT: - switch (event.window.event) { - case SDL_WINDOWEVENT_RESIZED: - screen_width = m_videoState->width = event.window.data1; - screen_height = m_videoState->height = event.window.data2; - case SDL_WINDOWEVENT_EXPOSED: - m_videoState->force_refresh = 1; - } - break; - case SDL_QUIT: - done = TRUE; - break; - default: - break; - } + movieFinished = HandleMovieEvent(event); } Close(); } @@ -2191,6 +2139,57 @@ BOOL aui_SDLMovie::IsPaused() const { #endif // USE_SDL_FFMPEG } +bool aui_SDLMovie::HandleMovieEvent(SDL_Event &event) { + bool movieFinished = false; + + switch (event.type) { + case SDL_QUIT: + movieFinished = true; + break; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_ESCAPE: + case SDLK_SPACE: + case SDLK_q: + movieFinished = true; + break; + case SDLK_p: + toggle_pause(m_videoState); + break; + default: + break; + } + break; + case SDL_MOUSEMOTION: + if (cursor_hidden) { + SDL_ShowCursor(1); + cursor_hidden = 0; + } else { + if ((event.motion.type & SDL_BUTTON_LMASK != 0) && + (is_full_screen || InsideMovieArea(event.button.x, event.button.y))) { + movieFinished = true; + } + } + cursor_last_shown = av_gettime_relative(); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + if (is_full_screen || InsideMovieArea(event.button.x, event.button.y)) { + movieFinished = true; + } + break; + default: + break; + } + return movieFinished; +} + + +bool aui_SDLMovie::InsideMovieArea(int x, int y) { + return (x > m_videoState->xleft && x < (m_videoState->xleft + m_videoState->width) + && y > m_videoState->ytop && y < (m_videoState->ytop + m_videoState->height)); +} + void aui_SDLMovie::GrabLastFrame() { aui_SDLSurface *sdlSurface = dynamic_cast(GetDestSurface()); if (sdlSurface) { diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmovie.h b/ctp2_code/ui/aui_sdl/aui_sdlmovie.h index 5cfd6f01d..5f2d0ca97 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmovie.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlmovie.h @@ -10,6 +10,8 @@ #if defined(__AUI_USE_SDL__) +#include + class VideoState; class SDL_Renderer; class SDL_Texture; @@ -40,6 +42,8 @@ class aui_SDLMovie : public aui_Movie { virtual BOOL IsPaused() const; private: + bool HandleMovieEvent(SDL_Event &event); + bool InsideMovieArea(int x, int y); void GrabLastFrame(); VideoState *m_videoState; diff --git a/ctp2_code/ui/aui_sdl/aui_sdlui.h b/ctp2_code/ui/aui_sdl/aui_sdlui.h index 876fd8ab1..a465d7531 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlui.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlui.h @@ -83,10 +83,9 @@ class aui_SDLUI : public aui_UI, public aui_SDL #if defined(HAVE_X11) Display * m_X11Display; #endif - SDL_Window *m_SDLWindow; - SDL_Surface *m_SDLSurface; + SDL_Window *m_SDLWindow; SDL_Renderer *m_SDLRenderer; - SDL_Texture *m_SDLTexture; + SDL_Texture *m_SDLTexture; }; typedef aui_SDLUI aui_NativeUI; diff --git a/ctp2_code/ui/interface/controlpanelwindow.cpp b/ctp2_code/ui/interface/controlpanelwindow.cpp index 1e0392cc9..9dfb4fac0 100644 --- a/ctp2_code/ui/interface/controlpanelwindow.cpp +++ b/ctp2_code/ui/interface/controlpanelwindow.cpp @@ -32,22 +32,22 @@ // play. // - Start the great library with the current research project of the player. // - Added option to add new messages at the top. -// - Fixed crossed Sword bug. - Oct. 14th 2004 Martin Gühmann +// - Fixed crossed Sword bug. - Oct. 14th 2004 Martin Gühmann // - Fixed the crossed sword bug that was caused by the previous bug fix, -// cossed swords even if the city is hidden. - Oct. 15th 2004 Martin Gühmann +// cossed swords even if the city is hidden. - Oct. 15th 2004 Martin Gühmann // - Added unit display name. // - Relaxed Assert for invisible buttons with mods. // - Prevented crashes with mods. -// - Added special attack window. (Aug 15th 2005 Martin Gühmann) +// - Added special attack window. (Aug 15th 2005 Martin Gühmann) // - Removed unused methods: FillBank, ClearButtons and AddButton. -// (Aug 16th 2005 Martin Gühmann) +// (Aug 16th 2005 Martin Gühmann) // - Restored Fifth Tileimp Button Bank by E 2-27-2007 // - TODO fix obsolete tileimp defect // - TODO add buttons for orders button bank // - TODO create scroll bar like CityStyles in Scenario Editor for // Orders and tileimprovements so they are not limited -// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) -// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) // //---------------------------------------------------------------------------- // @@ -58,8 +58,8 @@ // CityPanelRebuild - notice the strange immediate return) are never called, // and some variables (e.g. m_mainDropDown) are not NULL-initialised in the // constructor. Maybe this is some leftover of the CTP1 code? -// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) -// - Standatized code (May 21st 2006 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) +// - Standatized code (May 21st 2006 Martin Gühmann) // - None of the unit or order stuff is used here? see UnitControlPanel.cpp // //---------------------------------------------------------------------------- @@ -2952,7 +2952,9 @@ void ControlPanelWindow::Idle() if (m_targetingMode) TargetingMode(); else - g_cursorManager->SetCursor(CURSORINDEX_DEFAULT); + // prevent resetting of scroll-cursor + if (!g_tiledMap->IsScrolling()) + g_cursorManager->SetCursor(CURSORINDEX_DEFAULT); } void ControlPanelWindow::Move( sint32 x, sint32 y ) diff --git a/ctp2_data/default/uidata/layouts/wondermovie.ldl b/ctp2_data/default/uidata/layouts/wondermovie.ldl index 28f1fe1e5..923fca7c9 100644 --- a/ctp2_data/default/uidata/layouts/wondermovie.ldl +++ b/ctp2_data/default/uidata/layouts/wondermovie.ldl @@ -9,7 +9,7 @@ WonderMovieWindow { string xanchor "center" string yanchor "center" int widthpix 338 - int heightpix 357 + int heightpix 360 string pattern "uptg20e.tga" MovieButton { @@ -39,7 +39,7 @@ WonderMovieWindow { int xpix 0 int ypix 48 int widthpix 9 - int heightpix 292 + int heightpix 295 string pattern "upba6701.tga" } @@ -47,13 +47,13 @@ WonderMovieWindow { int xpix 329 int ypix 48 int widthpix 9 - int heightpix 292 + int heightpix 295 string pattern "upba6702.tga" } BottomBorder { int xpix 0 - int ypix 340 + int ypix 343 int widthpix 338 int heightpix 17 From ee85d1637ee795e5115f65cde71ee7b9fef27ee5 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Fri, 24 Apr 2020 11:00:35 +0200 Subject: [PATCH 22/29] Create virtual mouse-events to force a redraw Previously virtual mouse-events were created to force redraw of windows. The SDL2 implementation only created real mouse-events which means that in some cases the redraw was not done. Solved by re-introducing the virtual mouse-events. --- ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp | 15 ++++++++++++++- ctp2_code/ui/aui_sdl/aui_sdlmouse.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp index 42724fb05..9d09b1a01 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp @@ -32,7 +32,8 @@ aui_SDLMouse::aui_SDLMouse( aui_Mouse(retval, ldlBlock), aui_SDLInput(retval, useExclusiveMode), m_currentCursor(NULL), - m_animationTimer(0) + m_animationTimer(0), + m_lastFrameTick(0) { Assert(AUI_SUCCESS(*retval)); if (!AUI_SUCCESS(*retval)) return; @@ -141,8 +142,20 @@ sint32 aui_SDLMouse::ManipulateInputs(aui_MouseEvent *data, BOOL add) { break; } } + + uint32 currentFrameTick = SDL_GetTicks(); if (numberEvents) { + m_lastFrameTick = currentFrameTick; m_data = data[numberEvents - 1]; + } else { + // generate at least a single event every x ticks to force a redraw + const int FRAMES_PER_SECOND = 60; + const int TICKS_PER_FRAME = 1000 / FRAMES_PER_SECOND; + if (currentFrameTick > m_lastFrameTick + TICKS_PER_FRAME) { + m_lastFrameTick = currentFrameTick; + data[0] = m_data; + numberEvents = 1; + } } return numberEvents; } diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmouse.h b/ctp2_code/ui/aui_sdl/aui_sdlmouse.h index b5039bd3e..bbb99754d 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmouse.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlmouse.h @@ -38,6 +38,7 @@ class aui_SDLMouse : public aui_Mouse, public aui_SDLInput private: aui_Cursor *m_currentCursor; SDL_TimerID m_animationTimer; + uint32 m_lastFrameTick; }; typedef aui_SDLMouse aui_NativeMouse; From 9254fcb3ee949ce794348f2fe7cff94ec0f53bd1 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Fri, 24 Apr 2020 17:41:44 +0200 Subject: [PATCH 23/29] Allocate (debug-)memory on 8-byte boundaries 64-bit machines need their pointers to be 8-byte aligned (address should be dividable by 8) --- configure.ac | 1 - ctp2_code/ctp/debugtools/debugmemory.cpp | 17 ++--------------- ctp2_code/ctp/debugtools/debugmemory.h | 13 ------------- 3 files changed, 2 insertions(+), 29 deletions(-) diff --git a/configure.ac b/configure.ac index c8b7aa879..29c3876cb 100644 --- a/configure.ac +++ b/configure.ac @@ -59,7 +59,6 @@ AM_PATH_SDL_FFMPEG AC_PATH_X AC_PATH_XTRA AC_DEFINE(USE_SDL,1,[Use the SDL-library]) -AC_DEFINE(SKIP_SDL2_DEBUG_MEMORY_ISSUE,1,[Skip SDL2 debug memory code]) AC_WORDS_BIGENDIAN AC_OS_DEFINES diff --git a/ctp2_code/ctp/debugtools/debugmemory.cpp b/ctp2_code/ctp/debugtools/debugmemory.cpp index 6adbe0ad3..2b16385cf 100644 --- a/ctp2_code/ctp/debugtools/debugmemory.cpp +++ b/ctp2_code/ctp/debugtools/debugmemory.cpp @@ -58,17 +58,6 @@ #define fopen(a, b) ci_fopen(a, b) #endif -#if defined(SKIP_SDL2_DEBUG_MEMORY_ISSUE) - -void DebugMemory_LeaksShow (int turn_count) {} -void DebugMemory_LeaksClear(void) {} -size_t DebugMemory_GetTotalFromEXE(void) { return 0; } -size_t DebugMemory_GetTotalFromDLL(void) { return 0; } -void DebugMemory_Open (void) {} -void DebugMemory_Close (void) {} - -#else - struct DebugMemory; struct MemoryHeapDescriptor; struct AllocHeader; @@ -446,8 +435,8 @@ const unsigned char FILL_BYTE_FREE = 0x67; const unsigned char FILL_BYTE_MARKER = 0x68; const unsigned char FILL_BYTE_REALLOC = 0x69; -const unsigned char DATA_GUARD_SIZE = 4; -const unsigned char HEADER_GUARD_SIZE = 4; +const unsigned char DATA_GUARD_SIZE = 8; +const unsigned char HEADER_GUARD_SIZE = 8; const int CALL_STACK_SIZE = 60; @@ -1362,6 +1351,4 @@ void operator delete (void *mem) #endif // MEMORY_LOGGED -#endif // SKIP_SDL2_DEBUG_MEMORY_ISSUE - #endif // _DEBUG \ No newline at end of file diff --git a/ctp2_code/ctp/debugtools/debugmemory.h b/ctp2_code/ctp/debugtools/debugmemory.h index 0942514c3..8a6c4f053 100644 --- a/ctp2_code/ctp/debugtools/debugmemory.h +++ b/ctp2_code/ctp/debugtools/debugmemory.h @@ -47,17 +47,6 @@ extern "C" { #endif -#if defined(SKIP_SDL2_DEBUG_MEMORY_ISSUE) - -void DebugMemory_LeaksShow (int turn_count); -void DebugMemory_LeaksClear(void); -size_t DebugMemory_GetTotalFromEXE(void); -size_t DebugMemory_GetTotalFromDLL(void); -void DebugMemory_Open (void); -void DebugMemory_Close (void); - -#else - #ifndef _DEBUG_MEMORY #define MEMORY_FAST #else @@ -153,8 +142,6 @@ void DebugMemoryHeap_GuardedClose (const char *file, int line, MemoryHeap h #endif -#endif // SKIP_SDL2_DEBUG_MEMORY_ISSUE - #ifdef __cplusplus } #endif From 75f0ea2fe4e92dc8637a337bcd4e6fadf0588263 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Fri, 24 Apr 2020 21:45:33 +0200 Subject: [PATCH 24/29] Minimize latency of UI sound effects Chunksize in combination with the frequency determine the latency of a sound effect. It was 8192 / 22005 * 1000 ms ~370 ms. Chunksize has been decreased to 256 was gives a latency of ~10 ms. --- ctp2_code/sound/soundmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctp2_code/sound/soundmanager.cpp b/ctp2_code/sound/soundmanager.cpp index e1445eda5..588b87719 100755 --- a/ctp2_code/sound/soundmanager.cpp +++ b/ctp2_code/sound/soundmanager.cpp @@ -158,7 +158,7 @@ void SoundManager::InitSoundDriver() } else { - errcode = Mix_OpenAudio(output_rate, output_format, output_channels, 8192); + errcode = Mix_OpenAudio(output_rate, output_format, output_channels, 256); if (errcode < 0) { // char *err = SDL_GetError(); cerr << "Opening mixer failed:" << err << endl; From e12f866e9d83600378e3f6816e812817fb8d060e Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Sat, 25 Apr 2020 21:07:42 +0200 Subject: [PATCH 25/29] Update readme to include instructions how to build with SDL2 --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e58e6574a..59446b25b 100644 --- a/README.md +++ b/README.md @@ -18,15 +18,17 @@ Note that the game files are not included in this repo, you can get them from th ![screenshot](screenshot.png "screenshot of CTP2 running on Linux") -This version should support CD Audio music, and also supports Ripped CD Audio compressed as ogg (like found in the GoG version). The Audio tracks should be named `Track02.ogg` to `Track11.ogg` and be in the `ctp2_program/ctp/music` folder. +The Windows version supports CD Audio music, and the Linux version supports Ripped CD Audio compressed as ogg (like found in the GoG version). The Audio tracks should be named `Track02.ogg` to `Track11.ogg` and be in the `ctp2_program/ctp/music` folder. + +As the Linux version does not support direct play from CD-rom, you need to rip the assets-files from the CD and put them on your disk. ## Building on Linux You will probably need GCC 5.x or later to build. The code doesn't seem to build on GCC 4.8. -You will need SDL 1.2, SDL_Mixer, SDL_Image and the GTK 2.0 libraries. +You will need SDL 2.0, SDL_Mixer 2.0, SDL_Image 2.0 and the GTK 2.0 libraries. To be able to play movies you also need ffmpeg libraries (some). You will also need `byacc` -On debian and friends, use `sudo apt install libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev byacc gtk2.0-dev flex` to install them all. +On debian and friends, use `sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libtiff-dev libavcodec-dev libavformat-dev libswscale-dev byacc gtk2.0-dev flex` to install them all. The build itself is pretty classing and straight forward: From 44885f579717453b0703a5115749705fc099bb09 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Thu, 30 Apr 2020 18:02:57 +0200 Subject: [PATCH 26/29] Use SDL2 to show message-box GTK message-box implementation has been replaced by an SDL2 implementation. As the GTK library was only used for message-box it has been removed from the project. --- .travis.yml | 1 - Dockerfile | 4 +- README.md | 4 +- configure.ac | 9 -- ctp2_code/ctp/civ3_main.cpp | 10 -- ctp2_code/meson.build | 6 +- ctp2_code/os/autoconf/Makefile.common | 4 +- ctp2_code/os/nowin32/nowin32.cpp | 190 +++++++++++++++----------- 8 files changed, 117 insertions(+), 111 deletions(-) diff --git a/.travis.yml b/.travis.yml index cf457f0f7..e5d9e6afc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,6 @@ addons: - libavformat-dev - libswscale-dev - byacc - - libgtk2.0-dev - gcc-5 - g++-5 diff --git a/Dockerfile b/Dockerfile index cab6afcdf..751192159 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ FROM system as builder RUN apt-get update && apt-get install -y --no-install-recommends \ libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libtiff-dev libavcodec-dev libavformat-dev libswscale-dev \ - byacc libgtk2.0-dev gcc-5 g++-5 automake libtool unzip flex git ca-certificates + byacc gcc-5 g++-5 automake libtool unzip flex git ca-certificates ### set default compilers RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 100 && \ @@ -62,7 +62,7 @@ FROM system as install ARG BTYP RUN apt-get update && apt-get install -y --no-install-recommends \ - libsdl2-2.0 libsdl2-mixer-2.0 libsdl2-image-2.0 libavcodec57 libavformat57 libswscale4 libgtk2.0-0 && \ + libsdl2-2.0 libsdl2-mixer-2.0 libsdl2-image-2.0 libavcodec57 libavformat57 libswscale4 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* diff --git a/README.md b/README.md index 59446b25b..7b755c881 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ As the Linux version does not support direct play from CD-rom, you need to rip t You will probably need GCC 5.x or later to build. The code doesn't seem to build on GCC 4.8. -You will need SDL 2.0, SDL_Mixer 2.0, SDL_Image 2.0 and the GTK 2.0 libraries. To be able to play movies you also need ffmpeg libraries (some). +You will need SDL 2.0, SDL_Mixer 2.0, SDL_Image 2.0. To be able to play movies you also need ffmpeg libraries (some). You will also need `byacc` -On debian and friends, use `sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libtiff-dev libavcodec-dev libavformat-dev libswscale-dev byacc gtk2.0-dev flex` to install them all. +On debian and friends, use `sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libtiff-dev libavcodec-dev libavformat-dev libswscale-dev byacc flex` to install them all. The build itself is pretty classing and straight forward: diff --git a/configure.ac b/configure.ac index 29c3876cb..8766e2602 100644 --- a/configure.ac +++ b/configure.ac @@ -64,15 +64,6 @@ AC_WORDS_BIGENDIAN AC_OS_DEFINES AC_OS_PATHNAMES -if test "x$ac_OpSystem" != "xWIN32" -then - PKG_CHECK_MODULES(GTK, gtk+-2.0) - AC_DEFINE(USE_GTK,1,[Use gtk+ for native dialogs]) - AC_SUBST(USE_GTK) - AC_SUBST(GTK_CFLAGS) - AC_SUBST(GTK_LIBS) -fi - AC_CHECK_HEADERS(limits.h sys/param.h) case $host in *-cygwin*) diff --git a/ctp2_code/ctp/civ3_main.cpp b/ctp2_code/ctp/civ3_main.cpp index f357ce0cb..e63e85597 100644 --- a/ctp2_code/ctp/civ3_main.cpp +++ b/ctp2_code/ctp/civ3_main.cpp @@ -175,9 +175,6 @@ #ifdef HAVE_X11 #include #endif -#ifdef USE_GTK -#include -#endif #if defined(_DEBUG) #include "debug.h" // Os::SetThreadName @@ -1568,16 +1565,9 @@ int WINAPI CivMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, } } #endif -#ifdef USE_GTK - gtk_init(&iCmdShow, &pSzCmdLine); -#endif appstrings_Initialize(); -#ifdef USE_GTK -// gtk_set_locale(); - gtk_init(&iCmdShow, &pSzCmdLine); -#endif std::setlocale(LC_COLLATE, appstrings_GetString(APPSTR_LOCALE)); std::setlocale(LC_NUMERIC, "C"); diff --git a/ctp2_code/meson.build b/ctp2_code/meson.build index 1de9cea84..3811d5b0c 100644 --- a/ctp2_code/meson.build +++ b/ctp2_code/meson.build @@ -39,16 +39,12 @@ if not win32 tiff = dependency('libtiff-4') zlib = dependency('zlib') - gtk = dependency('gtk+-3.0') - conf.set('USE_GTK', 1) - x11 = dependency('x11', required: false) if x11.found() conf.set('HAVE_X11', 1, description : 'System with X11 present') endif - main_dependencies += [tiff, zlib, gtk, sdl, x11] + main_dependencies += [tiff, zlib, sdl, x11] - main_dependencies += declare_dependency( sources : 'os/nowin32/nowin32.cpp', dependencies : gtk ) incdir += include_directories('os/nowin32') conf.set_quoted('FILE_SEP', '/') diff --git a/ctp2_code/os/autoconf/Makefile.common b/ctp2_code/os/autoconf/Makefile.common index aa6a5d272..3c205c6e8 100644 --- a/ctp2_code/os/autoconf/Makefile.common +++ b/ctp2_code/os/autoconf/Makefile.common @@ -8,12 +8,10 @@ CTP2_LDFLAGS = \ $(SDL_LDFLAGS) \ -ltiff -lz -lSDL2 -lSDL2_image -lSDL2_mixer $(SDL_FFMPEG_LDFLAGS) -ldl -lpthread \ $(X_PRE_LIBS) \ - $(X_LIBS) -lX11 \ - $(GTK_LIBS) -ldl + $(X_LIBS) -lX11 -ldl CTP2_CFLAGS=\ $(SDL_CFLAGS) \ - $(GTK_CFLAGS) \ $(X_CFLAGS) CTP2_CXXFLAGS=\ diff --git a/ctp2_code/os/nowin32/nowin32.cpp b/ctp2_code/os/nowin32/nowin32.cpp index 7a9235b1e..e709be3ce 100644 --- a/ctp2_code/os/nowin32/nowin32.cpp +++ b/ctp2_code/os/nowin32/nowin32.cpp @@ -20,8 +20,8 @@ #include "windows.h" -#ifdef USE_GTK -#include +#ifdef USE_SDL + #include "SDL2/SDL.h" #endif // @ToDo: _fullpath is the version of ptitSeb's branch, check whether there @@ -141,89 +141,121 @@ uint32 GetTickCount() return SDL_GetTicks(); } -namespace { - int mbRetVal = 0; -} - sint32 MessageBox(HWND parent, const CHAR* msg, const CHAR* title, sint32 flags) { fprintf(stderr, "Messagebox(%s): %s\n", (title ? title : "null"), (msg ? msg : "null")); -#ifdef USE_GTK - GtkWidget *dialog = gtk_message_dialog_new - ( - NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_NONE, - msg - ); - gtk_window_set_title(GTK_WINDOW(dialog), title); - - if (flags & MB_OK) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_OK, IDOK, - NULL); - } - else if(flags & MB_OKCANCEL) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_OK, IDOK, - GTK_STOCK_CANCEL, IDCANCEL, - NULL); - } - else if(flags & MB_ABORTRETRYIGNORE) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - "_Abort", IDABORT, - "_Retry", IDRETRY, - "_Ignore", IDIGNORE, - NULL); - } - else if(flags & MB_YESNOCANCEL) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_YES, IDYES, - GTK_STOCK_NO, IDNO, - GTK_STOCK_CANCEL, IDCANCEL, - NULL); - } - else if(flags & MB_YESNO) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_YES, IDYES, - GTK_STOCK_NO, IDNO, - NULL); - } - else if(flags & MB_RETRYCANCEL) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - "_Retry", IDRETRY, - GTK_STOCK_CANCEL, IDCANCEL, - NULL); - } - else if(flags & MB_CANCELTRYCONTINUE) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_CANCEL, IDCANCEL, - "_Try", IDTRYAGAIN, - "_Continue", IDCONTINUE, - NULL); - } - else - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_OK, IDOK, - NULL); +#ifdef USE_SDL + SDL_MessageBoxData data; + + const SDL_MessageBoxColorScheme colorScheme = { + { + // background + { 0xDE, 0xD2, 0xB4 }, + // text + { 0x32, 0x31, 0x32 }, + // button border + { 0x02, 0x02, 0x02 }, + // button background + { 0xE6, 0xDa, 0xC5 }, + // button text + { 0x02, 0x02, 0x02 } + } + }; + + const int MAXIMUM_NUMBER_OF_BUTTONS = 3; + SDL_MessageBoxButtonData buttonData[MAXIMUM_NUMBER_OF_BUTTONS]; + memset(buttonData, 0, sizeof(SDL_MessageBoxButtonData)*MAXIMUM_NUMBER_OF_BUTTONS); + // filter button + switch (flags & 7) { + case MB_OK: + case MB_OKCANCEL: + data.numbuttons = 1; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDOK; + buttonData[0].text = "OK"; + if (flags == MB_OKCANCEL) { + data.numbuttons = 2; + buttonData[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[1].buttonid = IDCANCEL; + buttonData[1].text = "Cancel"; + } + break; + + case MB_ABORTRETRYIGNORE: + data.numbuttons = 3; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDABORT; + buttonData[0].text = "Abort"; + buttonData[1].flags = 0; + buttonData[1].buttonid = IDRETRY; + buttonData[1].text = "Retry"; + buttonData[2].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[2].buttonid = IDIGNORE; + buttonData[2].text = "Ignore"; + break; + + case MB_YESNO: + case MB_YESNOCANCEL: + data.numbuttons = 2; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDYES; + buttonData[0].text = "Yes"; + buttonData[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[1].buttonid = IDNO; + buttonData[1].text = "No"; + if (flags == MB_YESNOCANCEL) { + data.numbuttons = 3; + buttonData[1].flags = 0; + buttonData[2].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[2].buttonid = IDCANCEL; + buttonData[2].text = "Cancel"; + } + break; + + case MB_RETRYCANCEL: + data.numbuttons = 2; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDRETRY; + buttonData[0].text = "Retry"; + buttonData[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[1].buttonid = IDCANCEL; + buttonData[1].text = "Cancel"; + break; + + case MB_CANCELTRYCONTINUE: + data.numbuttons = 3; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDCONTINUE; + buttonData[0].text = "Continue"; + buttonData[1].flags = 0; + buttonData[1].buttonid = IDTRYAGAIN; + buttonData[1].text = "Try"; + buttonData[2].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[2].buttonid = IDCANCEL; + buttonData[2].text = "Cancel"; + break; + + default: + data.numbuttons = 1; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDOK; + buttonData[0].text = "OK"; + break; } - sint32 result = gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - - while(g_main_iteration(FALSE)) - gtk_main_quit(); + data.buttons = buttonData; + data.flags = SDL_MESSAGEBOX_ERROR; + data.title = title ? title : "null"; + data.message = msg; + data.colorScheme = &colorScheme; + data.window = NULL; - return result; + int selectedButton = IDFAIL; + SDL_ShowMessageBox(&data, &selectedButton); + if (selectedButton == -1) { + selectedButton = buttonData[0].buttonid; + } + return selectedButton; #else return IDFAIL; #endif From a2db90c27e6b2dd2929b92b15e3ffe7c1e1aa646 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Fri, 1 May 2020 11:04:27 +0200 Subject: [PATCH 27/29] Will skip assert-dialogs when requested from the command-line --- ctp2_code/ctp/ctp2_utils/c3debug.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ctp2_code/ctp/ctp2_utils/c3debug.cpp b/ctp2_code/ctp/ctp2_utils/c3debug.cpp index f8bcc16da..d27d1056b 100644 --- a/ctp2_code/ctp/ctp2_utils/c3debug.cpp +++ b/ctp2_code/ctp/ctp2_utils/c3debug.cpp @@ -49,6 +49,7 @@ #include "netconsole.h" #include "c3files.h" +extern BOOL g_noAssertDialogs; uint32 g_debug_mask = k_DBG_NONE; static int g_useMask; @@ -317,7 +318,8 @@ void c3debug_Assert(char const *s, char const * file, int line) MBCHAR str[1024]; sprintf(str, "Assertion (%s) Failed in File:%s, Line:%ld\n", s, file, line); fprintf(stderr, str); - sint32 result = MessageBox(NULL, str, "Assert", MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION); + sint32 result = g_noAssertDialogs ? IDIGNORE + : MessageBox(NULL, str, "Assert", MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION); if(result == IDRETRY) { From accc08a9b911975fd453bcbb7b72abce8b61a6b8 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Sat, 2 May 2020 09:36:16 +0200 Subject: [PATCH 28/29] Use SDL_WaitEventTimeout to throttle main-loop (FIXME) --- ctp2_code/ctp/civ3_main.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/ctp2_code/ctp/civ3_main.cpp b/ctp2_code/ctp/civ3_main.cpp index e63e85597..ceb95b2bb 100644 --- a/ctp2_code/ctp/civ3_main.cpp +++ b/ctp2_code/ctp/civ3_main.cpp @@ -1674,18 +1674,26 @@ int WINAPI CivMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, for (gDone = FALSE; !gDone; ) { + uint32 frameStartTick = GetTickCount(); g_civApp->Process(); - //fprintf(stderr, "%s L%d: g_civApp->Process() done!\n", __FILE__, __LINE__); + //fprintf(stderr, "%s L%d: g_civApp->Process() done!\n", __FILE__, __LINE__); #ifdef __AUI_USE_SDL__ SDL_Event event; while (!g_letUIProcess) { // There are breaks, too ;) - // Throttle the loop a bit to prevent 100% CPU usage in idle state. - // FIXME: implement blocking loop with SDL_WaitEvent(). - if (!SDL_PollEvent(NULL)) { - SDL_Delay(30); - break; + + static const int FRAMES_PER_SECOND = 30; + static const int TICKS_PER_FRAME = 1000 / FRAMES_PER_SECOND; + const int frameTicksLeft = frameStartTick + TICKS_PER_FRAME - GetTickCount(); + if (frameTicksLeft > 0) { + if (!SDL_WaitEventTimeout(NULL, frameTicksLeft)) { + break; + } + } else { + if (!SDL_PollEvent(NULL)) { + break; + } } int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_MOUSEMOTION-1); From d2d03dbe0a1be8a9dce421d4e1e5c49816b91d24 Mon Sep 17 00:00:00 2001 From: William Deurwaarder Date: Fri, 8 May 2020 09:07:53 +0200 Subject: [PATCH 29/29] Fix Windows compile issue (ShouldTerminateThread has to be public) --- ctp2_code/ui/aui_common/aui_mouse.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ctp2_code/ui/aui_common/aui_mouse.h b/ctp2_code/ui/aui_common/aui_mouse.h index 6325a26a9..1921a4870 100644 --- a/ctp2_code/ui/aui_common/aui_mouse.h +++ b/ctp2_code/ui/aui_common/aui_mouse.h @@ -177,6 +177,8 @@ class aui_Mouse : public aui_Base, public virtual aui_Input #if defined(__AUI_USE_DIRECTX__) LPCRITICAL_SECTION LPCS( void ) const { return m_lpcs; } + + BOOL ShouldTerminateThread( void ); #endif // __AUI_USE_DIRECTX__ uint32 GetFlags(void) { return m_flags;} @@ -212,8 +214,6 @@ class aui_Mouse : public aui_Base, public virtual aui_Input void DestroyPrivateBuffers( void ); AUI_ERRCODE Erase( void ); - BOOL ShouldTerminateThread( void ); - aui_Surface *m_privateMix; aui_Surface *m_pickup; aui_Surface *m_prevPickup;