diff --git a/CMakeLists.txt b/CMakeLists.txt index eb91866f..c85f2374 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,10 +98,10 @@ add_subdirectory(assets) ## config.h generation set(GIT_EXECUTABLE "git" CACHE FILEPATH "Path to git binary") include(GitUtilities) -git_describe(SRB2_GIT_DESCRIBE "${CMAKE_SOURCE_DIR}") +git_latest_commit(SRB2_COMP_COMMIT "${CMAKE_SOURCE_DIR}") git_current_branch(SRB2_GIT_BRANCH "${CMAKE_SOURCE_DIR}") set(SRB2_COMP_BRANCH "${SRB2_GIT_BRANCH}") -set(SRB2_COMP_REVISION "${SRB2_GIT_DESCRIBE}") +set(SRB2_COMP_REVISION "${SRB2_COMP_COMMIT}") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/src/config.h) ##### PACKAGE CONFIGURATION ##### diff --git a/bin/Resources/i686/exchndl.dll b/bin/Resources/i686/exchndl.dll deleted file mode 100644 index d836a676..00000000 Binary files a/bin/Resources/i686/exchndl.dll and /dev/null differ diff --git a/cmake/Modules/GitUtilities.cmake b/cmake/Modules/GitUtilities.cmake index 683cf9b6..d29e6b50 100644 --- a/cmake/Modules/GitUtilities.cmake +++ b/cmake/Modules/GitUtilities.cmake @@ -27,5 +27,17 @@ function(git_current_branch variable path) OUTPUT_STRIP_TRAILING_WHITESPACE ) + set(${variable} "${output}" PARENT_SCOPE) +endfunction() + +function(git_latest_commit variable path) + execute_process(COMMAND ${GIT_EXECUTABLE} "rev-parse" "--short" "HEAD" + WORKING_DIRECTORY "${path}" + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(${variable} "${output}" PARENT_SCOPE) endfunction() \ No newline at end of file diff --git a/libs/DLL-README.txt b/libs/DLL-README.txt new file mode 100644 index 00000000..058ec068 --- /dev/null +++ b/libs/DLL-README.txt @@ -0,0 +1,43 @@ +# SRB2 - Which DLLs do I need to bundle? + +Updated 12/4/2018 (v2.1.21) + +Here are the required DLLs, per build. For each architecture, copy all the binaries from these folders: + +* libs\dll-binaries\[i686/x86_64] +* libs\SDL2\[i686/x86_64]...\bin +* libs\SDL2_mixer\[i686/x86_64]...\bin + +and don't forget to build r_opengl.dll for srb2dd. + +## srb2win, 32-bit + +* libs\dll-binaries\i686\exchndl.dll +* libs\dll-binaries\i686\libgme.dll +* libs\dll-binaries\i686\mgwhelp.dll (depend for exchndl.dll) +* libs\SDL2\i686-w64-mingw32\bin\SDL2.dll +* libs\SDL2_mixer\i686-w64-mingw32\bin\*.dll (get everything) + +## srb2win, 64-bit + +* libs\dll-binaries\x86_64\exchndl.dll +* libs\dll-binaries\x86_64\libgme.dll +* libs\dll-binaries\x86_64\mgwhelp.dll (depend for exchndl.dll) +* libs\SDL2\x86_64-w64-mingw32\bin\SDL2.dll +* libs\SDL2_mixer\x86_64-w64-mingw32\bin\*.dll (get everything) + +## srb2dd, 32-bit + +* libs\dll-binaries\i686\exchndl.dll +* libs\dll-binaries\i686\fmodex.dll +* libs\dll-binaries\i686\libgme.dll +* libs\dll-binaries\i686\mgwhelp.dll (depend for exchndl.dll) +* r_opengl.dll (build this from make) + +## srb2dd, 64-bit + +* libs\dll-binaries\x86_64\exchndl.dll +* libs\dll-binaries\x86_64\fmodex.dll +* libs\dll-binaries\x86_64\libgme.dll +* libs\dll-binaries\x86_64\mgwhelp.dll (depend for exchndl.dll) +* r_opengl.dll (build this from make) diff --git a/bin/Resources/i686/fmod.dll b/libs/dll-binaries/i686/Old/fmod.dll similarity index 100% rename from bin/Resources/i686/fmod.dll rename to libs/dll-binaries/i686/Old/fmod.dll diff --git a/bin/Resources/i686/fmodexL.dll b/libs/dll-binaries/i686/Old/fmodexL.dll similarity index 100% rename from bin/Resources/i686/fmodexL.dll rename to libs/dll-binaries/i686/Old/fmodexL.dll diff --git a/bin/Resources/i686/libgcc_s_dw2-1.dll b/libs/dll-binaries/i686/Old/libgcc_s_dw2-1.dll similarity index 100% rename from bin/Resources/i686/libgcc_s_dw2-1.dll rename to libs/dll-binaries/i686/Old/libgcc_s_dw2-1.dll diff --git a/bin/Resources/i686/libintl-8.dll b/libs/dll-binaries/i686/Old/libintl-8.dll similarity index 100% rename from bin/Resources/i686/libintl-8.dll rename to libs/dll-binaries/i686/Old/libintl-8.dll diff --git a/libs/dll-binaries/i686/exchndl.dll b/libs/dll-binaries/i686/exchndl.dll new file mode 100644 index 00000000..d6beb764 Binary files /dev/null and b/libs/dll-binaries/i686/exchndl.dll differ diff --git a/bin/Resources/i686/fmodex.dll b/libs/dll-binaries/i686/fmodex.dll similarity index 100% rename from bin/Resources/i686/fmodex.dll rename to libs/dll-binaries/i686/fmodex.dll diff --git a/bin/Resources/i686/libgme.dll b/libs/dll-binaries/i686/libgme.dll similarity index 100% rename from bin/Resources/i686/libgme.dll rename to libs/dll-binaries/i686/libgme.dll diff --git a/libs/dll-binaries/i686/mgwhelp.dll b/libs/dll-binaries/i686/mgwhelp.dll new file mode 100644 index 00000000..3cf97424 Binary files /dev/null and b/libs/dll-binaries/i686/mgwhelp.dll differ diff --git a/bin/Resources/x86_64/fmod64.dll b/libs/dll-binaries/x86_64/Old/fmod64.dll similarity index 100% rename from bin/Resources/x86_64/fmod64.dll rename to libs/dll-binaries/x86_64/Old/fmod64.dll diff --git a/bin/Resources/x86_64/fmodexL64.dll b/libs/dll-binaries/x86_64/Old/fmodexL64.dll similarity index 100% rename from bin/Resources/x86_64/fmodexL64.dll rename to libs/dll-binaries/x86_64/Old/fmodexL64.dll diff --git a/libs/dll-binaries/x86_64/exchndl.dll b/libs/dll-binaries/x86_64/exchndl.dll new file mode 100644 index 00000000..747d7a3d Binary files /dev/null and b/libs/dll-binaries/x86_64/exchndl.dll differ diff --git a/bin/Resources/x86_64/fmodex64.dll b/libs/dll-binaries/x86_64/fmodex64.dll similarity index 100% rename from bin/Resources/x86_64/fmodex64.dll rename to libs/dll-binaries/x86_64/fmodex64.dll diff --git a/bin/Resources/x86_64/libgme.dll b/libs/dll-binaries/x86_64/libgme.dll similarity index 100% rename from bin/Resources/x86_64/libgme.dll rename to libs/dll-binaries/x86_64/libgme.dll diff --git a/libs/dll-binaries/x86_64/mgwhelp.dll b/libs/dll-binaries/x86_64/mgwhelp.dll new file mode 100644 index 00000000..4e30e140 Binary files /dev/null and b/libs/dll-binaries/x86_64/mgwhelp.dll differ diff --git a/src/Makefile.cfg b/src/Makefile.cfg index 20219168..cdd4c3c7 100644 --- a/src/Makefile.cfg +++ b/src/Makefile.cfg @@ -20,7 +20,7 @@ GCC64=1 endif ifdef GCC64 -GCC64=1 +GCC63=1 endif ifdef GCC63 diff --git a/src/config.h.in b/src/config.h.in index 5f06ec45..7452ec80 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -21,8 +21,6 @@ #define SRB2_COMP_REVISION "${SRB2_COMP_REVISION}" #define SRB2_COMP_BRANCH "${SRB2_COMP_BRANCH}" -#define SRB2_GIT_DESCRIBE "${SRB2_GIT_DESCRIBE}" -#define SRB2_GIT_BRANCH "${SRB2_GIT_BRANCH}" #define CMAKE_ASSETS_DIR "${CMAKE_SOURCE_DIR}/assets" diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 739d3009..fe717c8d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -240,7 +240,7 @@ INT32 cv_debug; consvar_t cv_usemouse = {"use_mouse", "On", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_usemouse2 = {"use_mouse2", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse2, 0, NULL, NULL, 0, 0, NULL}; -#if defined (DC) || defined (_XBOX) || defined (WMINPUT) || defined (_WII) //joystick 1 and 2 +#if defined (DC) || defined (_XBOX) || defined (WMINPUT) || defined (_WII) || defined(HAVE_SDL) || defined(_WIN32) //joystick 1 and 2 consvar_t cv_usejoystick = {"use_joystick", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_usejoystick2 = {"use_joystick2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, diff --git a/src/m_anigif.c b/src/m_anigif.c index 84509921..4e68819b 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -492,8 +492,8 @@ static void GIF_framewrite(void) // screen regions are handled in GIF_lzw { - int d1 = (int)((100.0/NEWTICRATE)*(gif_frames+1)); - int d2 = (int)((100.0/NEWTICRATE)*(gif_frames)); + int d1 = (int)((100.0f/NEWTICRATE)*(gif_frames+1)); + int d2 = (int)((100.0f/NEWTICRATE)*(gif_frames)); UINT16 delay = d1-d2; INT32 startline; diff --git a/src/m_menu.c b/src/m_menu.c index 0ca5aaf6..3d759be3 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -54,6 +54,8 @@ #include "st_stuff.h" #include "i_sound.h" +#include "i_joy.h" // for joystick menu controls + // Condition Sets #include "m_cond.h" @@ -160,7 +162,7 @@ typedef enum levellist_mode_t levellistmode = LLM_CREATESERVER; UINT8 maplistoption = 0; -static char joystickInfo[8][25]; +static char joystickInfo[8][29]; #ifndef NONET static UINT32 serverlistpage; #endif @@ -2074,6 +2076,7 @@ boolean M_Responder(event_t *ev) INT32 ch = -1; // INT32 i; static tic_t joywait = 0, mousewait = 0; + static INT32 pjoyx = 0, pjoyy = 0; static INT32 pmousex = 0, pmousey = 0; static INT32 lastx = 0, lasty = 0; void (*routine)(INT32 choice); // for some casting problem @@ -2128,26 +2131,45 @@ boolean M_Responder(event_t *ev) } else if (ev->type == ev_joystick && ev->data1 == 0 && joywait < I_GetTime()) { - if (ev->data3 == -1) + const INT32 jdeadzone = JOYAXISRANGE/4; + if (ev->data3 != INT32_MAX) { - ch = KEY_UPARROW; - joywait = I_GetTime() + NEWTICRATE/7; - } - else if (ev->data3 == 1) - { - ch = KEY_DOWNARROW; - joywait = I_GetTime() + NEWTICRATE/7; + if (Joystick.bGamepadStyle || abs(ev->data3) > jdeadzone) + { + if (ev->data3 < 0 && pjoyy >= 0) + { + ch = KEY_UPARROW; + joywait = I_GetTime() + NEWTICRATE/7; + } + else if (ev->data3 > 0 && pjoyy <= 0) + { + ch = KEY_DOWNARROW; + joywait = I_GetTime() + NEWTICRATE/7; + } + pjoyy = ev->data3; + } + else + pjoyy = 0; } - if (ev->data2 == -1) + if (ev->data2 != INT32_MAX) { - ch = KEY_LEFTARROW; - joywait = I_GetTime() + NEWTICRATE/17; - } - else if (ev->data2 == 1) - { - ch = KEY_RIGHTARROW; - joywait = I_GetTime() + NEWTICRATE/17; + if (Joystick.bGamepadStyle || abs(ev->data2) > jdeadzone) + { + if (ev->data2 < 0 && pjoyx >= 0) + { + ch = KEY_LEFTARROW; + joywait = I_GetTime() + NEWTICRATE/17; + } + else if (ev->data2 > 0 && pjoyx <= 0) + { + ch = KEY_RIGHTARROW; + joywait = I_GetTime() + NEWTICRATE/17; + } + pjoyx = ev->data2; + } + else + pjoyx = 0; } } else if (ev->type == ev_mouse && mousewait < I_GetTime()) @@ -6726,35 +6748,32 @@ static void M_DrawJoystick(void) M_DrawGenericMenu(); - for (i = 0;i < 8; i++) + for (i = 0;i < 7; i++) { - M_DrawSaveLoadBorder(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i); + M_DrawTextBox(OP_JoystickSetDef.x-8, OP_JoystickSetDef.y+LINEHEIGHT*i-12, 28, 1); + //M_DrawSaveLoadBorder(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i); if ((setupcontrols_secondaryplayer && (i == cv_usejoystick2.value)) || (!setupcontrols_secondaryplayer && (i == cv_usejoystick.value))) - V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i,V_GREENMAP,joystickInfo[i]); + V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,V_GREENMAP,joystickInfo[i]); else - V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i,0,joystickInfo[i]); + V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,0,joystickInfo[i]); } } static void M_SetupJoystickMenu(INT32 choice) { INT32 i = 0; - const char *joyname = "None"; const char *joyNA = "Unavailable"; INT32 n = I_NumJoys(); (void)choice; - strcpy(joystickInfo[i], joyname); + strcpy(joystickInfo[i], "None"); for (i = 1; i < 8; i++) { - if (i <= n && (joyname = I_GetJoyName(i)) != NULL) - { - strncpy(joystickInfo[i], joyname, 24); - joystickInfo[i][24] = '\0'; - } + if (i <= n && (I_GetJoyName(i)) != NULL) + strncpy(joystickInfo[i], I_GetJoyName(i), 28); else strcpy(joystickInfo[i], joyNA); } diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 2b35ce8b..50c3018a 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -894,8 +894,8 @@ void I_GetJoystickEvents(void) UINT64 joyhats = 0; #if 0 UINT64 joybuttons = 0; -#endif Sint16 axisx, axisy; +#endif if (!joystick_started) return; @@ -963,6 +963,7 @@ void I_GetJoystickEvents(void) } } +#if 0 // send joystick axis positions event.type = ev_joystick; @@ -1013,6 +1014,7 @@ void I_GetJoystickEvents(void) } D_PostEvent(&event); } +#endif } /** \brief Open joystick handle @@ -1176,8 +1178,8 @@ void I_GetJoystick2Events(void) UINT64 joyhats = 0; #if 0 INT64 joybuttons = 0; -#endif INT32 axisx, axisy; +#endif if (!joystick2_started) return; @@ -1247,6 +1249,7 @@ void I_GetJoystick2Events(void) } } +#if 0 // send joystick axis positions event.type = ev_joystick2; @@ -1297,7 +1300,7 @@ void I_GetJoystick2Events(void) } D_PostEvent(&event); } - +#endif } /** \brief Open joystick handle @@ -1453,18 +1456,28 @@ INT32 I_NumJoys(void) return numjoy; } +static char joyname[255]; // MAX_PATH; joystick name is straight from the driver + const char *I_GetJoyName(INT32 joyindex) { - const char *joyname = "NA"; + const char *tempname = NULL; joyindex--; //SDL's Joystick System starts at 0, not 1 if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1) - joyname = SDL_JoystickNameForIndex(joyindex); + { + tempname = SDL_JoystickNameForIndex(joyindex); + if (tempname) + strncpy(joyname, tempname, 255); + } SDL_QuitSubSystem(SDL_INIT_JOYSTICK); } else - joyname = SDL_JoystickNameForIndex(joyindex); + { + tempname = SDL_JoystickNameForIndex(joyindex); + if (tempname) + strncpy(joyname, tempname, 255); + } return joyname; } diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 3cc29dbb..2c199c2d 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -767,6 +767,33 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt) D_PostEvent(&event); } +#if 0 +static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt) +{ + event_t event; + SDL_JoystickID joyid[2]; + + // Determine the Joystick IDs for each current open joystick + joyid[0] = SDL_JoystickInstanceID(JoyInfo.dev); + joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev); + + if (evt.hat >= JOYHATS) + return; // ignore hats with too high an index + + if (evt.which == joyid[0]) + { + event.data1 = KEY_HAT1 + (evt.hat*4); + } + else if (evt.which == joyid[1]) + { + event.data1 = KEY_2HAT1 + (evt.hat*4); + } + else return; + + // NOTE: UNFINISHED +} +#endif + static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type) { event_t event; @@ -804,6 +831,8 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type) if (event.type != ev_console) D_PostEvent(&event); } + + void I_GetEvent(void) { SDL_Event evt; @@ -844,6 +873,11 @@ void I_GetEvent(void) case SDL_JOYAXISMOTION: Impl_HandleJoystickAxisEvent(evt.jaxis); break; +#if 0 + case SDL_JOYHATMOTION: + Impl_HandleJoystickHatEvent(evt.jhat) + break; +#endif case SDL_JOYBUTTONUP: case SDL_JOYBUTTONDOWN: Impl_HandleJoystickButtonEvent(evt.jbutton, evt.type); diff --git a/src/sdl/macosx/Srb2mac.icns b/src/sdl/macosx/Srb2mac.icns index 4baedc1c..96cb8a36 100644 Binary files a/src/sdl/macosx/Srb2mac.icns and b/src/sdl/macosx/Srb2mac.icns differ diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index a3c42199..3f9b09f1 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -50,8 +50,8 @@ #ifdef HAVE_LIBGME #include "gme/gme.h" -#define GME_TREBLE 5.0 -#define GME_BASS 1.0 +#define GME_TREBLE 5.0f +#define GME_BASS 1.0f #ifdef HAVE_ZLIB #ifndef _MSC_VER diff --git a/src/sdl12/i_system.c b/src/sdl12/i_system.c index 8729e592..10fbc50e 100644 --- a/src/sdl12/i_system.c +++ b/src/sdl12/i_system.c @@ -1575,18 +1575,28 @@ INT32 I_NumJoys(void) return numjoy; } +static char joyname[255]; // MAX_PATH; joystick name is straight from the driver + const char *I_GetJoyName(INT32 joyindex) { - const char *joyname = "NA"; + const char *tempname = NULL; joyindex--; //SDL's Joystick System starts at 0, not 1 if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) { if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1) - joyname = SDL_JoystickName(joyindex); + { + tempname = SDL_JoystickNameForIndex(joyindex); + if (tempname) + strncpy(joyname, tempname, 255); + } SDL_QuitSubSystem(SDL_INIT_JOYSTICK); } else - joyname = SDL_JoystickName(joyindex); + { + tempname = SDL_JoystickNameForIndex(joyindex); + if (tempname) + strncpy(joyname, tempname, 255); + } return joyname; } diff --git a/src/sdl12/macosx/Srb2mac.icns b/src/sdl12/macosx/Srb2mac.icns index 4baedc1c..96cb8a36 100644 Binary files a/src/sdl12/macosx/Srb2mac.icns and b/src/sdl12/macosx/Srb2mac.icns differ diff --git a/windows-installer/! MAKE SURE FILES ARE IN new-install ARCHIVE FOLDER !.txt b/windows-installer/! MAKE SURE FILES ARE IN new-install ARCHIVE FOLDER !.txt new file mode 100644 index 00000000..e69de29b diff --git a/windows-installer/.gitignore b/windows-installer/.gitignore new file mode 100644 index 00000000..40ca3713 --- /dev/null +++ b/windows-installer/.gitignore @@ -0,0 +1,10 @@ +* +*.* +!staging +!sfx +!uninstaller +!! MAKE SURE FILES ARE IN new-install ARCHIVE FOLDER !.txt +!BuildInstaller.bat +!README.txt +!VersionFileName.txt +!.gitignore diff --git a/windows-installer/BuildInstaller.bat b/windows-installer/BuildInstaller.bat new file mode 100644 index 00000000..cc6ff74b --- /dev/null +++ b/windows-installer/BuildInstaller.bat @@ -0,0 +1,76 @@ +@echo off + +set "SCRIPTDIR=%~dp0" +set "SCRIPTDIR=%SCRIPTDIR:~0,-1%" + +IF [%SRB2VERSIONNAME%] == [] set /p SRB2VERSIONNAME=<"%SCRIPTDIR%\VersionFileName.txt" + +:: Find 7z + +set SVZIP= + +if NOT [%1] == [] ( + echo.%~1 | findstr /C:"7z" 1>nul + if NOT errorlevel 1 ( + if exist "%~1" set "SVZIP=%~1" + ) +) + +if ["%SVZIP%"] == [""] ( + if exist "%ProgramFiles(x86)%\7-Zip\7z.exe" set "SVZIP=%ProgramFiles(x86)%\7-Zip\7z.exe" + if exist "%ProgramFiles%\7-Zip\7z.exe" set "SVZIP=%ProgramFiles%\7-Zip\7z.exe" + if exist "%ProgramW6432%\7-Zip\7z.exe" set "SVZIP=%ProgramW6432%\7-Zip\7z.exe" +) + +:: Is it in PATH? + +if ["%SVZIP%"] == [""] ( + "7z.exe" --help > NUL 2> NUL + if NOT errorlevel 1 ( + set "SVZIP=7z.exe" + ) +) + +:: Create the uninstaller + +if NOT ["%SVZIP%"] == [""] ( + del /f /q "%SCRIPTDIR%\Uninstaller.7z" 2> NUL + "%SVZIP%" a -t7z "%SCRIPTDIR%\Uninstaller.7z" "%SCRIPTDIR%\uninstaller\*" -m5=LZMA2 + copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2.sfx" + "%SCRIPTDIR%\sfx\config-uninstaller.txt" + "%SCRIPTDIR%\Uninstaller.7z" "%SCRIPTDIR%\staging\new-install\uninstall.exe" + del /f /q "%SCRIPTDIR%\uninstaller.7z" +) + +:: Operate on install archives + +type NUL > "%SCRIPTDIR%\staging\new-install\staging.txt" + +if exist "%SCRIPTDIR%\Installer.7z" ( + if NOT ["%SVZIP%"] == [""] ( + "%SVZIP%" a "%SCRIPTDIR%\Installer.7z" "%SCRIPTDIR%\staging\*" + ) + copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2.sfx" + "%SCRIPTDIR%\sfx\config-installer.txt" + "%SCRIPTDIR%\Installer.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-Installer.exe" +) + +if exist "%SCRIPTDIR%\Patch.7z" ( + if NOT ["%SVZIP%"] == [""] ( + "%SVZIP%" a "%SCRIPTDIR%\Patch.7z" "%SCRIPTDIR%\staging\*" + ) + copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2.sfx" + "%SCRIPTDIR%\sfx\config-patch.txt" + "%SCRIPTDIR%\Patch.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-Patch.exe" +) + +if exist "%SCRIPTDIR%\Installer_x64.7z" ( + if NOT ["%SVZIP%"] == [""] ( + "%SVZIP%" a "%SCRIPTDIR%\Installer_x64.7z" "%SCRIPTDIR%\staging\*" + ) + copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2_x64.sfx" + "%SCRIPTDIR%\sfx\config-installer.txt" + "%SCRIPTDIR%\Installer_x64.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-x64-Installer.exe" +) + +if exist "%SCRIPTDIR%\Patch_x64.7z" ( + if NOT ["%SVZIP%"] == [""] ( + "%SVZIP%" a "%SCRIPTDIR%\Patch_x64.7z" "%SCRIPTDIR%\staging\*" + ) + copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2_x64.sfx" + "%SCRIPTDIR%\sfx\config-patch.txt" + "%SCRIPTDIR%\Patch_x64.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-x64-Patch.exe" +) + +del /f /q "%SCRIPTDIR%\staging\new-install\staging.txt" +del /f /q "%SCRIPTDIR%\staging\new-install\uninstall.exe" diff --git a/windows-installer/README.txt b/windows-installer/README.txt new file mode 100644 index 00000000..67995f33 --- /dev/null +++ b/windows-installer/README.txt @@ -0,0 +1,48 @@ +Windows Install Builder +for SRB2 + +This installer is much like the 7-Zip self-extracting archive, except +this allows for scripting the post-install step. + +This also allows for some light customization, including dialog messages +and program shortcuts. + +The included install scripts manage the game data location depending on the +install location -- if installed in Program Files or AppData\Local, the +game data location is set to %UserProfile%\SRB2. + +Program shortcuts are also added, as well as an uninstaller that +will remove the icons and also selectively uninstall the core game files. +The uninstaller gives you the option to preserve your game data and mods. + +How to Use +---------- + +1. Zip up the install contents in 7z format. + * ALL FILES MUST BE IN THE `new-install/` ARCHIVE SUBFOLDER, OR THE + POST-INSTALL SCRIPT WILL NOT WORK! + * Make sure you are using the LZMA2 algorithm, which is 7-Zip's default. + +2. Copy the 7z archive to this folder using the following names: + * Installer.7z - 32-bit full installer + * Patch.7z - 32-bit patch + * Installer_x64.7z - 64-bit full installer + * Patch_x64.7z - 64-bit patch + +3. Set the text in VersionFilename.txt to the version identifier for the + installer's filename. + * e.g., v2121 for v2.1.21, from "SRB2-v2121-Installer.exe" + * Also look through sfx/config-installer.txt and sfx/config-patch.txt + and update the version strings. Templating is TODO. + +4. Run BuildInstaller.bat [7z.exe install path] + * First argument is the path to 7z.exe. If this is not specified, the + script will try to look for it in C:\Program Files [(x86)] + * This script will automatically add the install scripts to each + installer. + +Credit +------ + +OlegScherbakov/7zSFX +https://github.com/OlegScherbakov/7zSFX diff --git a/windows-installer/VersionFileName.txt b/windows-installer/VersionFileName.txt new file mode 100644 index 00000000..559abffe --- /dev/null +++ b/windows-installer/VersionFileName.txt @@ -0,0 +1 @@ +v2121 \ No newline at end of file diff --git a/windows-installer/sfx/7zsd_LZMA2.sfx b/windows-installer/sfx/7zsd_LZMA2.sfx new file mode 100644 index 00000000..c4ba9c58 Binary files /dev/null and b/windows-installer/sfx/7zsd_LZMA2.sfx differ diff --git a/windows-installer/sfx/7zsd_LZMA2_x64.sfx b/windows-installer/sfx/7zsd_LZMA2_x64.sfx new file mode 100644 index 00000000..758e4c2d Binary files /dev/null and b/windows-installer/sfx/7zsd_LZMA2_x64.sfx differ diff --git a/windows-installer/sfx/config-installer.txt b/windows-installer/sfx/config-installer.txt new file mode 100644 index 00000000..bdbddea5 --- /dev/null +++ b/windows-installer/sfx/config-installer.txt @@ -0,0 +1,24 @@ +;!@Install@!UTF-8! + +GUIFlags="8+32+64+4096" +GUIMode="1" + +Title="Sonic Robo Blast 2 v2.1.21" +BeginPrompt="Sonic Robo Blast 2 v2.1.21\nFull Installer\n\nSelect a folder to install SRB2 in.\n\nIf you install in \"AppData\\Local\" or \"Program Files\", your game data will be saved to:\n%UserProfile%\\SRB2\n\nOtherwise, your game data will be in the installation folder.\n\nShortcuts will be created in your Start Menu." + +ExtractPathText="Installation folder: (no exclamation points, please!)" +InstallPath="%LocalAppData%\\SRB2" +ExtractTitle="Installing..." +ExtractDialogText="Installing SRB2 v2.1.21...\n\nCheck out our modding community!\nWe make levels, characters, and much more!\n\nVisit http://www.srb2.org/mods" + +Shortcut="Pu,{%%T\\srb2win.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2},{%%T\\},{%%T\\srb2win.exe},{0}" +Shortcut="Pu,{%%T\\srb2win.exe},{-win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (Windowed)},{%%T\\},{%%T\\srb2win.exe},{0}" +Shortcut="Pu,{%%T\\srb2win.exe},{-opengl},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (OpenGL)},{%%T\\},{%%T\\srb2win.exe},{0}" +Shortcut="Pu,{%%T\\srb2win.exe},{-opengl -win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (OpenGL, Windowed)},{%%T\\},{%%T\\srb2win.exe},{0}" +Shortcut="Pu,{%%T\\srb2dd.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (DirectDraw)},{%%T\\},{%%T\\srb2dd.exe},{0}" +Shortcut="Pu,{%%T\\srb2dd.exe},{-win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (DirectDraw, Windowed)},{%%T\\},{%%T\\srb2dd.exe},{0}" +Shortcut="Pu,{%%T\\uninstall.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{Uninstall SRB2},{%%T\\},{shell32.dll},{31}" + +RunProgram="nowait:\"%%T\\new-install\\staging.bat\"" + +;!@InstallEnd@! diff --git a/windows-installer/sfx/config-patch.txt b/windows-installer/sfx/config-patch.txt new file mode 100644 index 00000000..bde6135d --- /dev/null +++ b/windows-installer/sfx/config-patch.txt @@ -0,0 +1,24 @@ +;!@Install@!UTF-8! + +GUIFlags="8+32+64+4096" +GUIMode="1" + +Title="Sonic Robo Blast 2 v2.1.21" +BeginPrompt="Sonic Robo Blast 2 v2.1.21\nPatch Installer\n\nYou must have at least v2.1.15 to use this patch.\n\nSelect your current SRB2 folder.\n\nShortcuts will be created in your Start Menu." + +ExtractPathText="Current SRB2 folder: (no exclamation points, please!)" +InstallPath="%LocalAppData%\\SRB2" +ExtractTitle="Installing..." +ExtractDialogText="Installing SRB2 v2.1.21...\n\nCheck out our modding community!\nWe make levels, characters, and much more!\n\nVisit http://www.srb2.org/mods" + +Shortcut="Pu,{%%T\\srb2win.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2},{%%T\\},{%%T\\srb2win.exe},{0}" +Shortcut="Pu,{%%T\\srb2win.exe},{-win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (Windowed)},{%%T\\},{%%T\\srb2win.exe},{0}" +Shortcut="Pu,{%%T\\srb2win.exe},{-opengl},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (OpenGL)},{%%T\\},{%%T\\srb2win.exe},{0}" +Shortcut="Pu,{%%T\\srb2win.exe},{-opengl -win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (OpenGL, Windowed)},{%%T\\},{%%T\\srb2win.exe},{0}" +Shortcut="Pu,{%%T\\srb2dd.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (DirectDraw)},{%%T\\},{%%T\\srb2dd.exe},{0}" +Shortcut="Pu,{%%T\\srb2dd.exe},{-win},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{SRB2 (DirectDraw, Windowed)},{%%T\\},{%%T\\srb2dd.exe},{0}" +Shortcut="Pu,{%%T\\uninstall.exe},{},{Sonic Robo Blast 2},{Sonic Robo Blast 2 (SRB2), a 3D Sonic the Hedgehog fangame.},{Uninstall SRB2},{%%T\\},{shell32.dll},{31}" + +RunProgram="nowait:\"%%T\\new-install\\staging.bat\"" + +;!@InstallEnd@! diff --git a/windows-installer/sfx/config-uninstaller.txt b/windows-installer/sfx/config-uninstaller.txt new file mode 100644 index 00000000..f3de9e26 --- /dev/null +++ b/windows-installer/sfx/config-uninstaller.txt @@ -0,0 +1,13 @@ +;!@Install@!UTF-8! + +GUIFlags="1+2+8" +GUIMode="2" + +Title="Uninstall SRB2" +BeginPrompt="Are you sure you want to uninstall Sonic Robo Blast 2?\n\nYour game data and mods will be preserved, as well as\nany extra files in your install folder." + +InstallPath="%%S" + +RunProgram="nowait:\"%%S\\uninstall.bat\" /y" + +;!@InstallEnd@! diff --git a/windows-installer/staging/! SRB2 INSTALL INSTRUCTIONS !.txt b/windows-installer/staging/! SRB2 INSTALL INSTRUCTIONS !.txt new file mode 100644 index 00000000..f367296f --- /dev/null +++ b/windows-installer/staging/! SRB2 INSTALL INSTRUCTIONS !.txt @@ -0,0 +1,11 @@ +SRB2 Install Instructions + +1. Move every file from the "new-install" folder to this main install folder. + +2. DELETE "staging.bat" and "staging.txt"! These can mess up your installation if run by accident! + +3. Optionally, create a folder in your user profile named "SRB2". This is where your game data and addons may live. For example, + + C:\Users\[User]\SRB2 + +4. Run the game! Double-click srb2win.exe -- or see if you have Start Menu icons under "Sonic Robo Blast 2". \ No newline at end of file diff --git a/windows-installer/staging/new-install/old-install-list.txt b/windows-installer/staging/new-install/old-install-list.txt new file mode 100644 index 00000000..6f33660a --- /dev/null +++ b/windows-installer/staging/new-install/old-install-list.txt @@ -0,0 +1,15 @@ +exchndl.dll +fmodex.dll +libFLAC-8.dll +libgme.dll +libintl-8.dll +libmikmod-2.dll +libogg-0.dll +libvorbis-0.dll +libvorbisfile-3.dll +r_opengl.dll +SDL2.dll +SDL2_mixer.dll +smpeg2.dll +srb2dd.exe +srb2win.exe \ No newline at end of file diff --git a/windows-installer/staging/new-install/staging.bat b/windows-installer/staging/new-install/staging.bat new file mode 100644 index 00000000..2c3c9491 --- /dev/null +++ b/windows-installer/staging/new-install/staging.bat @@ -0,0 +1,363 @@ +@echo off + +setlocal enabledelayedexpansion + +cls + +:: SRB2 Install Staging +:: +:: This accomplishes the following tasks: +:: +:: 1. Creates a user profile folder if SRB2 is installed in AppData or Program Files, and config.cfg is not already in the install folder +:: +:: 2. Moves old installation files into old-install +:: +:: 3. Moves new installaton files into install folder +:: + +:: Get Parent folder (the SRB2 install folder) +:: +:: https://wiert.me/2011/08/30/batch-file-to-get-parent-directory-not-the-directory-of-the-batch-file-but-the-parent-of-that-directory/ + +set "STAGINGDIR=%~dp0" +:: strip trailing backslash +set "STAGINGDIR=!STAGINGDIR:~0,-1!" +:: ~dp only works for batch file parameters and loop indexes +for %%d in ("!STAGINGDIR!") do set "INSTALLDIR=%%~dpd" +set "INSTALLDIR=!INSTALLDIR:~0,-1!" + +:: Find 7z + +set SVZIP= +if ["%SVZIP%"] == [""] ( + if exist "!ProgramFiles(x86)!\7-Zip\7z.exe" set "SVZIP=!ProgramFiles(x86)!\7-Zip\7z.exe" + if exist "!ProgramFiles!\7-Zip\7z.exe" set "SVZIP=!ProgramFiles!\7-Zip\7z.exe" + if exist "!ProgramW6432!\7-Zip\7z.exe" set "SVZIP=!ProgramW6432!\7-Zip\7z.exe" +) + +:: Is it in PATH? + +if ["%SVZIP%"] == [""] ( + "7z.exe" --help > NUL 2> NUL + if NOT errorlevel 1 ( + set "SVZIP=7z.exe" + ) +) + +:: FAILSAFE: Check if staging.txt exists in the directory +:: If not, exit, so we don't mess up anything by accident. + +if NOT exist "!STAGINGDIR!\staging.txt" ( + exit +) + +: CheckPermissionsInstall + +:: Write a dummy file and check for an error. If error, we need administrator rights + +:: NOTE: We should never have to deal with this because the main installer should +:: already have the rights. + +mkdir "!INSTALLDIR!\install-dummy" + +:: TODO elevate automatically +if errorlevel 1 ( + echo Finish installing SRB2 with these steps: + echo. + echo 1. Go to your SRB2 install folder + echo. + echo !INSTALLDIR! + echo. + echo 2. Copy all files from the "new-install" subfolder into the main folder + echo and DELETE staging.bat and staging.txt!!! + echo. + echo 3. Optionally, create a folder in your user profile named "SRB2". + echo This is where your game data and addons may live. + echo To create the folder, go here: + echo. + echo !USERPROFILE! + echo. + echo If anything fails, you may delete the files and try to run the installer + echo again with Administrator Rights: Right-click on the icon and click + echo "Run as administrator." + echo. + "!SystemRoot!\explorer.exe" "!INSTALLDIR!" + set /p ADMINFINAL="Press Enter key to exit. " + + exit +) else ( + rmdir /s /q "!INSTALLDIR!\install-dummy" + goto CheckUserDir +) + +: CheckUserDir + +:: Check if we need to create !userprofile!\SRB2 + +set "USERDIR=!INSTALLDIR!" + +:: Is config.cfg in our install dir? +if exist "!INSTALLDIR!\config.cfg" goto MoveOldInstall + +:: Are we in AppData? +echo.!STAGINGDIR! | findstr /C:"!LocalAppData!" 1>nul +if errorlevel 1 ( + echo. +) else ( + goto SetUserDir +) + +: Are we in Program Files? +echo.!STAGINGDIR! | findstr /C:"!ProgramFiles!" 1>nul +if NOT errorlevel 1 ( + goto SetUserDir +) + +:: Are we in Program Files (x86)? +echo.!STAGINGDIR! | findstr /C:"!ProgramFiles(X86)!" 1>nul +if NOT errorlevel 1 ( + goto SetUserDir +) + +:: Are we 32-bit and actually in Program Files? +echo.!STAGINGDIR! | findstr /C:"!ProgramW6432!" 1>nul +if NOT errorlevel 1 ( + goto SetUserDir +) + +goto MoveOldInstall + +: SetUserDir +: CheckPermissionsUserDir + +set "USERDIR=!UserProfile!\SRB2" + +:: Check for permissions and create the folder +if exist "!USERDIR!\*" ( + mkdir "!USERDIR!\install-dummy" + + if errorlevel 1 ( + echo User profile folder exists, but we won't operate on it. + echo. + goto MoveOldInstall + ) else ( + rmdir /s /q "!USERDIR!\install-dummy" + ) +) else ( + mkdir "!USERDIR!" + + if errorlevel 1 ( + echo Could not create user profile folder + echo Defaulting to install dir: "!INSTALLDIR!" + echo. + set "USERDIR=!INSTALLDIR!" + goto MoveOldInstall + ) +) + +:: Now copy READMEs +:: echo f answers xcopy's prompt as to whether the destination is a file or a folder +echo f | xcopy /y "!STAGINGDIR!\README.txt" "!USERDIR!\README.txt" +echo f | xcopy /y "!STAGINGDIR!\LICENSE.txt" "!USERDIR!\LICENSE.txt" +echo f | xcopy /y "!STAGINGDIR!\LICENSE-3RD-PARTY.txt" "!USERDIR!\LICENSE-3RD-PARTY.txt" +echo Your game data and mods folder is: > "!USERDIR!\^! Data and Mods Go Here ^!.txt" +echo. >> "!USERDIR!\^! Data and Mods Go Here ^!.txt" +echo !USERDIR! >> "!USERDIR!\^! Data and Mods Go Here ^!.txt" +echo. >> "!USERDIR!\^! Data and Mods Go Here ^!.txt" +echo Your install folder is: >> "!USERDIR!\^! Data and Mods Go Here ^!.txt" +echo. >> "!USERDIR!\^! Data and Mods Go Here ^!.txt" +echo !INSTALLDIR! >> "!USERDIR!\^! Data and Mods Go Here ^!.txt" +echo. >> "!USERDIR!\^! Data and Mods Go Here ^!.txt" +echo To run SRB2, go to: >> "!USERDIR!\^! Data and Mods Go Here ^!.txt" +echo. >> "!USERDIR!\^! Data and Mods Go Here ^!.txt" +echo Start Menu ^> Programs ^> Sonic Robo Blast 2 >> "!USERDIR!\^! Data and Mods Go Here ^!.txt" + +:: Copy path to install folder + +set "SCRIPT=!TEMP!\!RANDOM!-!RANDOM!-!RANDOM!-!RANDOM!.vbs" +echo Set oWS = WScript.CreateObject("WScript.Shell") >> "!SCRIPT!" +echo sLinkFile = "!USERDIR!\^! SRB2 Install Folder ^!.lnk" >> "!SCRIPT!" +echo Set oLink = oWS.CreateShortcut(sLinkFile) >> "!SCRIPT!" +echo oLink.TargetPath = "!INSTALLDIR!" >> "!SCRIPT!" +echo oLink.WorkingDirectory = "!INSTALLDIR!" >> "!SCRIPT!" +echo oLink.Arguments = "" >> "!SCRIPT!" +echo oLink.IconLocation = "!INSTALLDIR!\srb2win.exe,0" >> "!SCRIPT!" +echo oLink.Save >> "!SCRIPT!" +cscript /nologo "!SCRIPT!" +del "!SCRIPT!" + +:: Also do it the other way around + +set "SCRIPT=!TEMP!\!RANDOM!-!RANDOM!-!RANDOM!-!RANDOM!.vbs" +echo Set oWS = WScript.CreateObject("WScript.Shell") >> "!SCRIPT!" +echo sLinkFile = "!INSTALLDIR!\^! SRB2 Data Folder ^!.lnk" >> "!SCRIPT!" +echo Set oLink = oWS.CreateShortcut(sLinkFile) >> "!SCRIPT!" +echo oLink.TargetPath = "!USERDIR!" >> "!SCRIPT!" +echo oLink.WorkingDirectory = "!USERDIR!" >> "!SCRIPT!" +echo oLink.Arguments = "" >> "!SCRIPT!" +echo oLink.IconLocation = "!INSTALLDIR!\srb2win.exe,0" >> "!SCRIPT!" +echo oLink.Save >> "!SCRIPT!" +cscript /nologo "!SCRIPT!" +del "!SCRIPT!" + +: MoveOldInstall + +if exist "!INSTALLDIR!\old-install\*" ( + set "OLDINSTALLDIR=!INSTALLDIR!\old-install-!RANDOM!" +) else ( + set "OLDINSTALLDIR=!INSTALLDIR!\old-install" +) + +mkdir "!OLDINSTALLDIR!" + +:: +:: Move all old install files +:: We support a list of explicit files to copy to old-install +:: And later, we also loop through our staging files, look for the pre-existing copy in +:: install root, then copy that also to old-install +:: + +:: Extract the uninstall-list.txt and uninstall-userdir.txt files from uninstaller.exe +:: if it exists + +if exist "!INSTALLDIR!\uninstall.exe" ( + if NOT ["!SVZIP!"] == [""] ( + "!SVZIP!" x "!INSTALLDIR!\uninstall.exe" "uninstall-list.txt" -o"!INSTALLDIR!" + "!SVZIP!" x "!INSTALLDIR!\uninstall.exe" "uninstall-userdir.txt" -o"!INSTALLDIR!" + ) +) + +set OLDINSTALLCHANGED= + +if exist "!STAGINGDIR!\old-install-list.txt" ( + goto MoveOldInstallOldFiles +) else ( + goto MoveOldInstallNewFiles +) + +: MoveOldInstallOldFiles + +set "TESTFILE=!TEMP!\!RANDOM!.txt" + +:: Do our failsafes before copying the file in the list +:: See uninstall.bat for details +for /F "usebackq tokens=*" %%A in ("!STAGINGDIR!\old-install-list.txt") do ( + if exist "!INSTALLDIR!\%%A" ( + if NOT ["%%A"] == [""] ( + if NOT ["%%A"] == ["%~nx0"] ( + echo %%A> "!TESTFILE!" + findstr /r ".*[<>:\"\"/\\|?*%%].*" "!TESTFILE!" >nul + if !errorlevel! equ 0 ( + echo %%A has invalid characters, skipping... + ) else ( + if exist "!INSTALLDIR!\%%A\*" ( + echo %%A is a folder, skipping... + ) else ( + echo Moving !INSTALLDIR!\%%A to "old-install" folder + echo f | xcopy /y /v "!INSTALLDIR!\%%A" "!OLDINSTALLDIR!\%%A" + if errorlevel 0 del /f /q "!INSTALLDIR!\%%A" + ) + ) + ) + ) + ) +) + +del /q /f "!STAGINGDIR!\old-install-list.txt" + +for %%F in ("!OLDINSTALLDIR!\*") DO ( + set OLDINSTALLCHANGED=1 + goto MoveOldInstallNewFiles +) + +: MoveOldInstallNewFiles + +:: Save a list of standard files +:: So the uninstall script will know what to remove +:: Append to any existing file, in case we are a patch + +dir /b /a-d "!STAGINGDIR!" >> "!INSTALLDIR!\uninstall-list.txt" + +:: Overwrite the last known gamedata folder + +echo !USERDIR! > "!INSTALLDIR!\uninstall-userdir.txt" + +:: Add the install-generated to the uninstall list +:: NO FOLLOWING SPACES AFTER THE FILENAME!!! + +echo uninstall.bat>> "!INSTALLDIR!\uninstall-list.txt" +echo uninstall-list.txt>> "!INSTALLDIR!\uninstall-list.txt" +echo uninstall-userdir.txt>> "!INSTALLDIR!\uninstall-list.txt" +:: *ahem* Prints as ^! SRB2 Data Folder ^!.lnk +:: We need to escape the exclamations (^^!) and the carets themselves (^^^^) +echo ^^^^^^! SRB2 Data Folder ^^^^^^!.lnk>> "!INSTALLDIR!\uninstall-list.txt" + +:: Add the uninstall list files to the uninstall EXE + +if NOT ["!SVZIP!"] == [""] ( + if exist "!INSTALLDIR!\new-install\uninstall.exe" ( + "!SVZIP!" a "!INSTALLDIR!\new-install\uninstall.exe" "!INSTALLDIR!\uninstall-list.txt" -sdel + "!SVZIP!" a "!INSTALLDIR!\new-install\uninstall.exe" "!INSTALLDIR!\uninstall-userdir.txt" -sdel + ) +) + +:: Start moving files + +for %%F in ("!STAGINGDIR!\*") DO ( + if exist "!INSTALLDIR!\%%~nxF" ( + set OLDINSTALLCHANGED=1 + move "!INSTALLDIR!\%%~nxF" "!OLDINSTALLDIR!\%%~nxF" + ) + if NOT ["%%~nxF"] == ["staging.bat"] ( + if NOT ["%%~nxF"] == ["staging.txt"] ( + move "!STAGINGDIR!\%%~nxF" "!INSTALLDIR!\%%~nxF" + ) + ) +) + +: Finished + +del /q /f "!INSTALLDIR!\^! SRB2 INSTALL INSTRUCTIONS ^!.txt" + +set MSGEXE= +if exist "!SystemRoot!\System32\msg.exe" ( + set MSGEXE=!SystemRoot!\System32\msg.exe +) else ( + if exist "!SystemRoot!\Sysnative\msg.exe" ( + set MSGEXE=!SystemRoot!\Sysnative\msg.exe + ) +) + +if ["!OLDINSTALLCHANGED!"] == ["1"] ( + "!systemroot!\explorer.exe" /select, "!OLDINSTALLDIR!" + echo Finished^^! Some of your old installation files were moved to the "old-install" folder. > !TEMP!\srb2msgprompt.txt + echo. >> !TEMP!\srb2msgprompt.txt + echo If you no longer need these files, you may delete the folder safely. >> !TEMP!\srb2msgprompt.txt + echo. >> !TEMP!\srb2msgprompt.txt + echo To run SRB2, go to: Start Menu ^> Programs ^> Sonic Robo Blast 2. >> !TEMP!\srb2msgprompt.txt + !MSGEXE! "!username!" < !TEMP!\srb2msgprompt.txt + del !TEMP!\srb2msgprompt.txt +) else ( + if /I ["!USERDIR!"] == ["!INSTALLDIR!"] ( + "!systemroot!\explorer.exe" "!INSTALLDIR!" + echo Finished^^! > !TEMP!\srb2msgprompt.txt + echo. >> !TEMP!\srb2msgprompt.txt + echo To run SRB2, go to: Start Menu ^> Programs ^> Sonic Robo Blast 2. >> !TEMP!\srb2msgprompt.txt + !MSGEXE! "!username!" < !TEMP!\srb2msgprompt.txt + del !TEMP!\srb2msgprompt.txt + ) else ( + "!systemroot!\explorer.exe" "!USERDIR!" + echo Finished^^! You may find your game data in this folder: > !TEMP!\srb2msgprompt.txt + echo. >> !TEMP!\srb2msgprompt.txt + echo !USERDIR! >> !TEMP!\srb2msgprompt.txt + echo. >> !TEMP!\srb2msgprompt.txt + echo To run SRB2, go to: Start Menu ^> Programs ^> Sonic Robo Blast 2. >> !TEMP!\srb2msgprompt.txt + !MSGEXE! "!username!" < !TEMP!\srb2msgprompt.txt + del !TEMP!\srb2msgprompt.txt + ) +) + +: Attempt to remove OLDINSTALLDIR, in case it's empty +rmdir /q "!OLDINSTALLDIR!" +cd \ +start "" /b "cmd" /s /c " del /f /q "%STAGINGDIR%\*"&rmdir /s /q "%STAGINGDIR%"&exit /b " diff --git a/windows-installer/uninstaller/uninstall.bat b/windows-installer/uninstaller/uninstall.bat new file mode 100644 index 00000000..ed7c3339 --- /dev/null +++ b/windows-installer/uninstaller/uninstall.bat @@ -0,0 +1,183 @@ +@echo off + +setlocal enabledelayedexpansion + +cls + +set "INSTALLDIR=%~dp0" +set "INSTALLDIR=!INSTALLDIR:~0,-1!" +set /p USERDIR=<"!INSTALLDIR!\uninstall-userdir.txt" +set "USERDIR=!USERDIR:~0,-1!" + +: ProceedPrompt + +if ["%1"] == ["/y"] ( + set "PROCEED=1" +) else ( + set PROCEED= + set /p PROCEED="Are you sure you want to uninstall SRB2? [yes/no] " + + if /I ["!PROCEED:~0,1!"] == ["n"] exit + if /I ["!PROCEED!"] == ["y"] ( + echo Type Yes or No + echo. + goto ProceedPrompt + ) else ( + if /I ["!PROCEED!"] == ["yes"] ( + set PROCEED=1 + ) else ( + echo. + goto ProceedPrompt + ) + ) +) + +:: Failsafe, in case we Ctrl+C and decline "Terminate batch file?" + +if NOT ["!PROCEED!"] == ["1"] ( + exit +) + +: CheckPermissions + +:: Write a dummy file and check for an error. If error, we need administrator rights + +mkdir "!INSTALLDIR!\uninstall-dummy" + +:: TODO elevate automatically +if errorlevel 1 ( + echo We need Administrator Rights to uninstall SRB2. + echo. + echo Try running this uninstaller by right-clicking on the icon + echo and click "Run as administrator" + echo. + set /p ADMINFINAL="Press Enter key to exit. " + exit +) else ( + rmdir /s /q "!INSTALLDIR!\uninstall-dummy" + goto DeleteFiles +) + +: DeleteFiles + +:: Our deletion list is a list of filenames, no paths, in the current folder +:: +:: We apply the following failsafes: +:: 1. Is filename the script itself? +:: 2. Does filename have illegal characters? https://stackoverflow.com/a/33625339/241046 +:: 3. Is filename a directory? +:: +:: TODO hack this to support .\file.txt relative paths +:: Can %%A be substring'd to get only the filename and extension? +:: If so, print that to the temp file instead of the whole line +:: And possibly do the folder check before the invalid char check. +:: ALSO: Don't honor upward relative paths! (..\) +:: +set "TESTFILE=!TEMP!\!RANDOM!.txt" + +for /F "usebackq tokens=*" %%A in ("!INSTALLDIR!\uninstall-list.txt") do ( + if exist "!INSTALLDIR!\%%A" ( + if NOT ["%%A"] == [""] ( + if NOT ["%%A"] == ["%~nx0"] ( + echo %%A> "!TESTFILE!" + findstr /r ".*[<>:\"\"/\\|?*%%].*" "!TESTFILE!" >nul + if !errorlevel! equ 0 ( + echo %%A has invalid characters, skipping... + ) else ( + if exist "!INSTALLDIR!\%%A\*" ( + echo %%A is a folder, skipping... + ) else ( + echo Deleting !INSTALLDIR!\%%A + del /q /f "!INSTALLDIR!\%%A" + ) + ) + ) + ) + ) +) + +del /q /f "!TESTFILE!" + +: AllDone + +:: Delete the program icons +echo Deleting your program icons... +echo. + +cd \ +rmdir /s /q "!AppData!\Microsoft\Windows\Start Menu\Programs\Sonic Robo Blast 2" + +:: Check if our install folder is non-empty + +set USERDIRFILLED= +set INSTALLDIRFILLED= +for /F %%i in ('dir /b /a "!USERDIR!\*"') do ( + if NOT ["%%i"] == ["%~nx0"] ( + set USERDIRFILLED=1 + goto InstallFilledCheck + ) +) + +: InstallFilledCheck + +if /I NOT ["!USERDIR!"] == ["!INSTALLDIR!"] ( + for /F %%i in ('dir /b /a "!INSTALLDIR!\*"') do ( + if ["%%i"] == ["%~nx0"] ( + echo. + ) else ( + set INSTALLDIRFILLED=1 + goto Final + ) + ) +) + +: Final + +echo All done^^! Visit http://www.srb2.org if you want to play SRB2 again^^! +echo. + +set "FINALPROMPT=Press Enter key to exit." +if ["!USERDIRFILLED!"] == ["1"] ( + echo We left your game data and mods alone, so you may delete those manually. + echo. + echo !USERDIR! + echo. + set "FINALPROMPT=Do you want to view your data? [yes/no]" +) + +if ["!INSTALLDIRFILLED!"] == ["1"] ( + echo We left some extra files alone in your install folder. + echo. + echo !INSTALLDIR! + echo. + set "FINALPROMPT=Do you want to view your data? [yes/no]" +) + +set FINALRESPONSE= +set /p FINALRESPONSE="!FINALPROMPT! " + +if NOT ["!FINALPROMPT!"] == ["Press Enter key to exit."] ( + if /I ["!FINALRESPONSE:~0,1!"] == ["y"] ( + if ["!USERDIRFILLED!"] == ["1"] ( + "!SystemRoot!\explorer.exe" "!USERDIR!" + ) + if ["!INSTALLDIRFILLED!"] == ["1"] ( + "!SystemRoot!\explorer.exe" "!INSTALLDIR!" + ) + ) else ( + if ["!FINALRESPONSE!"] == [""] ( + if ["!USERDIRFILLED!"] == ["1"] ( + "!SystemRoot!\explorer.exe" "!USERDIR!" + ) + if ["!INSTALLDIRFILLED!"] == ["1"] ( + "!SystemRoot!\explorer.exe" "!INSTALLDIR!" + ) + ) + ) +) + +: DeferredDelete + +:: Now let's delete our installation folder! +cd \ +start "" /b "cmd" /s /c " del /q /f "%INSTALLDIR%\uninstall.bat"&timeout /t 2 > NUL&rmdir "%INSTALLDIR%"&exit /b "