diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 20a962dbe..95d73a355 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -962,6 +962,7 @@ set (PCH_SOURCES blood/src/warp.cpp blood/src/weapon.cpp + common/utility/m_argv.cpp ) if( MSVC ) @@ -1015,6 +1016,7 @@ include_directories( libxmp-lite/include/libxmp-lite libsmackerdec/include thirdparty/include + common/utility ${CMAKE_BINARY_DIR}/libraries/gdtoa ${CMAKE_BINARY_DIR}/libraries/enet @@ -1113,6 +1115,7 @@ install(TARGETS demolition DESTINATION ${INSTALL_PATH} COMPONENT "Game executable") +source_group("Utility" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/utility/.+") source_group("Utility\\Audiolib" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/audiolib/.+") source_group("Utility\\Audiolib Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/audiolib/include/.+") source_group("Utility\\Audiolib Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/audiolib/src/.+") diff --git a/source/blood/src/barf.cpp b/source/blood/src/barf.cpp index 04a8e9eb3..92f3f4850 100644 --- a/source/blood/src/barf.cpp +++ b/source/blood/src/barf.cpp @@ -943,7 +943,6 @@ void sub_11DF0(char *filePath, char flags, int ID) char zDirectory[BMAX_PATH]; char zFilename[BMAX_PATH]; char zType[BMAX_PATH]; - buildvfs_fd handle; SplitPath(filePath, zDirectory, zFilename, zType); diff --git a/source/blood/src/startwin.game.cpp b/source/blood/src/startwin.game.cpp index 7f8519793..679b9fae6 100644 --- a/source/blood/src/startwin.game.cpp +++ b/source/blood/src/startwin.game.cpp @@ -720,7 +720,6 @@ int32_t startwin_run(void) if (done) { gSetup = settings.shared; - glrendmode = (settings.polymer) ? REND_POLYMER : REND_POLYMOST; pINISelected = settings.ini; Bstrcpy(g_modDir, (gNoSetup == 0 && settings.gamedir != NULL) ? settings.gamedir : "/"); } diff --git a/source/build/include/baselayer.h b/source/build/include/baselayer.h index 81de3db0e..a61012e1b 100644 --- a/source/build/include/baselayer.h +++ b/source/build/include/baselayer.h @@ -258,9 +258,6 @@ void wm_setapptitle(const char *name); // baselayer.c int32_t baselayer_init(); -void makeasmwriteable(void); -void maybe_redirect_outputs(void); - #include "print.h" struct GameInterface diff --git a/source/build/include/winbits.h b/source/build/include/winbits.h index e4c8af38a..e21e99516 100644 --- a/source/build/include/winbits.h +++ b/source/build/include/winbits.h @@ -14,11 +14,9 @@ extern int64_t win_timerfreq; extern char silentvideomodeswitch; -extern void win_open(void); extern void win_init(void); extern void win_setvideomode(int32_t c); extern void win_uninit(void); -extern void win_close(void); extern int32_t addsearchpath_ProgramFiles(const char *p); diff --git a/source/build/src/baselayer.cpp b/source/build/src/baselayer.cpp index f33a03eb8..9c45e795e 100644 --- a/source/build/src/baselayer.cpp +++ b/source/build/src/baselayer.cpp @@ -454,25 +454,3 @@ int32_t baselayer_init(void) return 0; } -void maybe_redirect_outputs(void) -{ -#if !(defined __APPLE__ && defined __BIG_ENDIAN__) - char *argp; - - // pipe standard outputs to files - if ((argp = Bgetenv("BUILD_LOGSTDOUT")) == NULL || Bstrcasecmp(argp, "TRUE")) - return; - - FILE *fp = freopen("stdout.txt", "w", stdout); - - if (!fp) - fp = fopen("stdout.txt", "w"); - - if (fp) - { - setvbuf(fp, 0, _IONBF, 0); - *stdout = *fp; - *stderr = *fp; - } -#endif -} diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index a0ac76426..d0644dda3 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -8162,7 +8162,6 @@ int32_t enginePreInit(void) baselayer_init(); initdivtables(); if (initsystem()) Bexit(9); - makeasmwriteable(); #if !defined DEBUG_MAIN_ARRAYS sector = sector_s; @@ -10505,9 +10504,6 @@ int32_t videoSetGameMode(char davidoption, int32_t daupscaledxdim, int32_t daups g_lastpalettesum = 0; if (videoSetMode(daupscaledxdim,daupscaledydim,dabpp,davidoption) < 0) return -1; - // Workaround possible bugs in the GL driver - makeasmwriteable(); - #ifdef USE_OPENGL if (dabpp > 8) rendmode = glrendmode; // GL renderer else rendmode = REND_CLASSIC; diff --git a/source/build/src/sdlayer.cpp b/source/build/src/sdlayer.cpp index a336711d6..183068b7e 100644 --- a/source/build/src/sdlayer.cpp +++ b/source/build/src/sdlayer.cpp @@ -16,6 +16,7 @@ #include "renderlayer.h" #include "sdl_inc.h" #include "softsurface.h" +#include "m_argv.h" #ifdef USE_OPENGL # include "glad/glad.h" @@ -42,6 +43,7 @@ static SDL_version linked; #endif GameInterface* gi; +FArgs* Args; #if !defined STARTUP_SETUP_WINDOW int32_t startwin_open(void) { return 0; } @@ -434,7 +436,7 @@ void ChooseGame() } } -int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) +int WINAPI WinMain(HINSTANCE , HINSTANCE , LPSTR , int ) #else int main(int argc, char *argv[]) #endif @@ -457,31 +459,27 @@ int main(int argc, char *argv[]) auto buildargv = argv; #endif - for (int i = 0; i < buildargc - 1; i++) + Args = new FArgs(buildargc, buildargv); + + auto dir = Args->CheckValue("-maindir"); + if (dir && !chdir(dir)) { - if (!strcmp(buildargv[i], "-maindir")) + FILE* f = fopen("blood.rff", "rb"); + if (f) { - const char* dir = buildargv[i + 1]; - if (!chdir(dir)) + gi = &Blood::Interface; + fclose(f); + } + else + { + f = fopen("redneck.grp", "rb"); + if (f) { - FILE* f = fopen("blood.rff", "rb"); - if (f) - { - gi = &Blood::Interface; - fclose(f); - } - else - { - f = fopen("redneck.grp", "rb"); - if (f) - { - gi = &Redneck::Interface; - fclose(f); - } - else - gi = &Duke::Interface; - } + gi = &Redneck::Interface; + fclose(f); } + else + gi = &Duke::Interface; } } // Hack to be able to choose from the available game frontends until the startup dialogue can be moved out of the frontend code. @@ -507,24 +505,15 @@ int main(int argc, char *argv[]) buildkeytranslationtable(); -#ifndef __ANDROID__ +#ifndef _WIN32 // catching signals is not really helpful on Windows. signal(SIGSEGV, sighandler); signal(SIGILL, sighandler); /* clang -fcatch-undefined-behavior uses an ill. insn */ signal(SIGABRT, sighandler); signal(SIGFPE, sighandler); -#else - SDL_SetEventFilter(sdlayer_mobilefilter, NULL); #endif -#ifdef _WIN32 - UNREFERENCED_PARAMETER(hInst); - UNREFERENCED_PARAMETER(hPrevInst); - UNREFERENCED_PARAMETER(lpCmdLine); - UNREFERENCED_PARAMETER(nCmdShow); - win_open(); - -#elif defined(HAVE_GTK2) +#if defined(HAVE_GTK2) // Pre-initialize SDL video system in order to make sure XInitThreads() is called // before GTK starts talking to X11. uint32_t inited = SDL_WasInit(SDL_INIT_VIDEO); @@ -535,33 +524,13 @@ int main(int argc, char *argv[]) gtkbuild_init(&argc, &argv); #endif - - startwin_open(); - maybe_redirect_outputs(); - -#ifdef _WIN32 - -#ifdef USE_PHYSFS - PHYSFS_init(buildargv[0]); - PHYSFS_setWriteDir(PHYSFS_getBaseDir()); -#endif r = gi->app_main(buildargc, (const char **)buildargv); -#else -#ifdef USE_PHYSFS - int pfsi = PHYSFS_init(argv[0]); - assert(pfsi != 0); - PHYSFS_setWriteDir(PHYSFS_getUserDir()); -#endif - r = app_main(argc, (char const * const *)argv); -#endif startwin_close(); -#ifdef _WIN32 - win_close(); -#elif defined(HAVE_GTK2) +#if defined(HAVE_GTK2) gtkbuild_exit(r); #endif diff --git a/source/build/src/winbits.cpp b/source/build/src/winbits.cpp index db00220f2..83b7cbe9f 100644 --- a/source/build/src/winbits.cpp +++ b/source/build/src/winbits.cpp @@ -16,8 +16,6 @@ char silentvideomodeswitch = 0; static char taskswitching = 1; -static HANDLE instanceflag = NULL; - static OSVERSIONINFOEXA osv; static int32_t togglecomp = 0; @@ -113,14 +111,6 @@ static void ToggleDesktopComposition(BOOL compEnable) typedef void (*dllSetString)(const char*); -// -// win_open(), win_init(), win_setvideomode(), win_uninit(), win_close() -- shared code -// -void win_open(void) -{ - instanceflag = CreateSemaphoreA(NULL, 1,1, WindowClass); -} - void win_init(void) { uint32_t i; @@ -146,11 +136,6 @@ void win_uninit(void) { } -void win_close(void) -{ - if (instanceflag) CloseHandle(instanceflag); -} - diff --git a/source/common/utility/m_argv.cpp b/source/common/utility/m_argv.cpp new file mode 100644 index 000000000..76cc73e43 --- /dev/null +++ b/source/common/utility/m_argv.cpp @@ -0,0 +1,420 @@ +/* +** m_argv.cpp +** Manages command line arguments +** +**--------------------------------------------------------------------------- +** Copyright 1998-2006 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include "m_argv.h" + +//=========================================================================== +// +// FArgs Default Constructor +// +//=========================================================================== + +FArgs::FArgs() +{ +} + +//=========================================================================== +// +// FArgs Copy Constructor +// +//=========================================================================== + +FArgs::FArgs(const FArgs &other) +: Argv(other.Argv) +{ +} + +//=========================================================================== +// +// FArgs Argv Constructor +// +//=========================================================================== + +FArgs::FArgs(int argc, char **argv) +{ + SetArgs(argc, argv); +} + +//=========================================================================== +// +// FArgs String Argv Constructor +// +//=========================================================================== + +FArgs::FArgs(int argc, const std::string *argv) +{ + AppendArgs(argc, argv); +} + + + +//=========================================================================== +// +// FArgs Copy Operator +// +//=========================================================================== + +FArgs &FArgs::operator=(const FArgs &other) +{ + Argv = other.Argv; + return *this; +} + +//=========================================================================== +// +// FArgs :: SetArgs +// +//=========================================================================== + +void FArgs::SetArgs(int argc, char **argv) +{ + Argv.resize(argc); + for (int i = 0; i < argc; ++i) + { + Argv[i] = argv[i]; + } +} + +//=========================================================================== +// +// FArgs :: FlushArgs +// +//=========================================================================== + +void FArgs::FlushArgs() +{ + Argv.clear(); +} + +//=========================================================================== +// +// FArgs :: CheckParm +// +// Checks for the given parameter in the program's command line arguments. +// Returns the argument number (1 to argc-1) or 0 if not present +// +//=========================================================================== + +int FArgs::CheckParm(const char *check, int start) const +{ + for (unsigned i = start; i < Argv.size(); ++i) + { + if (0 == stricmp(check, Argv[i].c_str())) + { + return i; + } + } + return 0; +} + +//=========================================================================== +// +// FArgs :: CheckParmList +// +// Returns the number of arguments after the parameter (if found) and also +// returns a pointer to the first argument. +// +//=========================================================================== + +int FArgs::CheckParmList(const char *check, const std::string **strings, int start) const +{ + unsigned int i, parmat = CheckParm(check, start); + + if (parmat == 0) + { + if (strings != nullptr) + { + *strings = nullptr; + } + return 0; + } + for (i = ++parmat; i < Argv.size(); ++i) + { + if (Argv[i][0] == '-' || Argv[i][1] == '+') + { + break; + } + } + if (strings != nullptr) + { + *strings = &Argv[parmat]; + } + return i - parmat; +} + +//=========================================================================== +// +// FArgs :: CheckValue +// +// Like CheckParm, but it also checks that the parameter has a value after +// it and returns that or nullptr if not present. +// +//=========================================================================== + +const char *FArgs::CheckValue(const char *check) const +{ + int i = CheckParm(check); + + if (i > 0 && i < (int)Argv.size() - 1) + { + i++; + return Argv[i][0] != '+' && Argv[i][0] != '-' ? Argv[i].c_str() : nullptr; + } + else + { + return nullptr; + } +} + +//=========================================================================== +// +// FArgs :: TakeValue +// +// Like CheckValue, except it also removes the parameter and its argument +// (if present) from argv. +// +//=========================================================================== + +std::string FArgs::TakeValue(const char *check) +{ + int i = CheckParm(check); + std::string out; + + if (i > 0 && i < (int)Argv.size()) + { + if (i < (int)Argv.size() - 1 && Argv[i+1][0] != '+' && Argv[i+1][0] != '-') + { + out = Argv[i+1]; + Argv.erase(Argv.begin() + i, Argv.begin() + (i+2)); // Delete the parm and its value. + } + else + { + Argv.erase(Argv.begin() + i); // Just delete the parm, since it has no value. + } + } + return out; +} + +//=========================================================================== +// +// FArgs :: RemoveArg +// +//=========================================================================== + +void FArgs::RemoveArgs(const char *check) +{ + int i = CheckParm(check); + + if (i > 0 && i < (int)Argv.size() - 1) + { + do + { + RemoveArg(i); + } + while (Argv[i][0] != '+' && Argv[i][0] != '-' && i < (int)Argv.size() - 1); + } +} + +//=========================================================================== +// +// FArgs :: GetArg +// +// Gets the argument at a particular position. +// +//=========================================================================== + +const char *FArgs::GetArg(int arg) const +{ + return ((unsigned)arg < Argv.size()) ? Argv[arg].c_str() : nullptr; +} + +//=========================================================================== +// +// FArgs :: GetArgList +// +// Returns a pointer to the std::string at a particular position. +// +//=========================================================================== + +const std::string *FArgs::GetArgList(int arg) const +{ + return ((unsigned)arg < Argv.size()) ? &Argv[arg] : nullptr; +} + +//=========================================================================== +// +// FArgs :: NumArgs +// +//=========================================================================== + +int FArgs::NumArgs() const +{ + return (int)Argv.size(); +} + +//=========================================================================== +// +// FArgs :: AppendArg +// +// Adds another argument to argv. Invalidates any previous results from +// GetArgList(). +// +//=========================================================================== + +void FArgs::AppendArg(std::string arg) +{ + Argv.push_back(arg); +} + +//=========================================================================== +// +// FArgs :: AppendArgs +// +// Adds an array of std::strings to argv. +// +//=========================================================================== + +void FArgs::AppendArgs(int argc, const std::string *argv) +{ + if (argv != nullptr && argc > 0) + { + for (int i = 0; i < argc; ++i) + { + Argv.push_back(argv[i]); + } + } +} + +//=========================================================================== +// +// FArgs :: RemoveArg +// +// Removes a single argument from argv. +// +//=========================================================================== + +void FArgs::RemoveArg(int argindex) +{ + Argv.erase(Argv.begin() + argindex); +} + +//=========================================================================== +// +// FArgs :: CollectFiles +// +// Takes all arguments after any instance of -param and any arguments before +// all switches that end in .extension and combines them into a single +// -switch block at the end of the arguments. If extension is nullptr, then +// every parameter before the first switch is added after this -param. +// +//=========================================================================== + +void FArgs::CollectFiles(const char *param, const char *extension) +{ + std::vector work; + unsigned int i; + size_t extlen = extension == nullptr ? 0 : strlen(extension); + + // Step 1: Find suitable arguments before the first switch. + i = 1; + while (i < Argv.size() && Argv[i][0] != '-' && Argv[i][0] != '+') + { + bool useit; + + if (extlen > 0) + { // Argument's extension must match. + size_t len = Argv[i].length(); + useit = (len >= extlen && stricmp(&Argv[i][len - extlen], extension) == 0); + } + else + { // Anything will do so long as it's before the first switch. + useit = true; + } + if (useit) + { + work.push_back(Argv[i]); + RemoveArg(i); + } + else + { + i++; + } + } + + // Step 2: Find each occurence of -param and add its arguments to work. + while ((i = CheckParm(param, i)) > 0) + { + RemoveArg(i); + while (i < Argv.size() && Argv[i][0] != '-' && Argv[i][0] != '+') + { + work.push_back(Argv[i]); + RemoveArg(i); + } + } + + // Optional: Replace short path names with long path names +#if 0 //def _WIN32 + for (i = 0; i < work.Size(); ++i) + { + work[i] = I_GetLongPathName(work[i]); + } +#endif + + // Step 3: Add work back to Argv, as long as it's non-empty. + if (work.size() > 0) + { + Argv.push_back(param); + AppendArgs(work.size(), &work[0]); + } +} + +//=========================================================================== +// +// FArgs :: GatherFiles +// +// Returns all the arguments after the first instance of -param. If you want +// to combine more than one or get switchless stuff included, you need to +// call CollectFiles first. +// +//=========================================================================== + +FArgs *FArgs::GatherFiles(const char *param) const +{ + const std::string *files; + int filecount; + + filecount = CheckParmList(param, &files); + return new FArgs(filecount, files); +} diff --git a/source/common/utility/m_argv.h b/source/common/utility/m_argv.h new file mode 100644 index 000000000..fe0875818 --- /dev/null +++ b/source/common/utility/m_argv.h @@ -0,0 +1,77 @@ +/* +** m_argv.h +** +**--------------------------------------------------------------------------- +** Copyright 1998-2006 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#ifndef __M_ARGV_H__ +#define __M_ARGV_H__ + +#include +#include + +// +// MISC +// +class FArgs +{ +public: + FArgs(); + FArgs(const FArgs &args); + FArgs(int argc, char **argv); + FArgs(int argc, const std::string *argv); + + FArgs &operator=(const FArgs &other); + + void AppendArg(std::string arg); + void AppendArgs(int argc, const std::string *argv); + void RemoveArg(int argindex); + void RemoveArgs(const char *check); + void SetArgs(int argc, char **argv); + void CollectFiles(const char *param, const char *extension); + FArgs *GatherFiles(const char *param) const; + void SetArg(int argnum, const char *arg); + + int CheckParm(const char *check, int start=1) const; // Returns the position of the given parameter in the arg list (0 if not found). + int CheckParmList(const char *check, const std::string **strings, int start=1) const; + const char *CheckValue(const char *check) const; + const char *GetArg(int arg) const; + const std::string *GetArgList(int arg) const; + std::string TakeValue(const char *check); + int NumArgs() const; + void FlushArgs(); + +private: + std::vector Argv; +}; + +extern FArgs *Args; + +#endif //__M_ARGV_H__ diff --git a/source/duke3d/src/startwin.game.cpp b/source/duke3d/src/startwin.game.cpp index b746ad514..bd8e73088 100644 --- a/source/duke3d/src/startwin.game.cpp +++ b/source/duke3d/src/startwin.game.cpp @@ -713,9 +713,6 @@ int32_t startwin_run(void) if (done) { ud.setup = settings.shared; -#ifdef USE_OPENGL - glrendmode = (settings.polymer) ? REND_POLYMER : REND_POLYMOST; -#endif g_selectedGrp = settings.grp; Bstrcpy(g_modDir, (g_noSetup == 0 && settings.gamedir != NULL) ? settings.gamedir : "/"); }