From 15f584ecc6aabad8ee7768c7b212482ee368f31d Mon Sep 17 00:00:00 2001
From: mazmazz <mar.marcoz@outlook.com>
Date: Mon, 3 Dec 2018 22:12:13 -0500
Subject: [PATCH] Installer followup

* Check if administrator rights are required
* Add INSTALL INSTRUCTIONS text file to root install folder in case the installer fails
* Add failsafes to uninstaller file deletion: check if name is a folder, and check for illegal chars
* Fixed parentheses breaking the installer by instead making exclamation marks do the breaking. Thanks Windows!
---
 windows-installer/BuildInstaller.bat          |  24 +-
 windows-installer/new-install/staging.bat     | 253 --------------
 windows-installer/new-install/uninstall.bat   | 139 --------
 windows-installer/sfx/config-installer.txt    |   4 +-
 windows-installer/sfx/config-patch.txt        |   2 +-
 .../staging/! SRB2 INSTALL INSTRUCTIONS !.txt |  11 +
 .../staging/new-install/staging.bat           | 315 ++++++++++++++++++
 .../staging/new-install/uninstall.bat         | 186 +++++++++++
 8 files changed, 533 insertions(+), 401 deletions(-)
 delete mode 100644 windows-installer/new-install/staging.bat
 delete mode 100644 windows-installer/new-install/uninstall.bat
 create mode 100644 windows-installer/staging/! SRB2 INSTALL INSTRUCTIONS !.txt
 create mode 100644 windows-installer/staging/new-install/staging.bat
 create mode 100644 windows-installer/staging/new-install/uninstall.bat

diff --git a/windows-installer/BuildInstaller.bat b/windows-installer/BuildInstaller.bat
index 0b8cd9fd2..70843d9ba 100644
--- a/windows-installer/BuildInstaller.bat
+++ b/windows-installer/BuildInstaller.bat
@@ -26,13 +26,16 @@ if ["%SVZIP%"] == [""] (
 
 :: Operate on install archives
 
-type NUL > "%SCRIPTDIR%\new-install\staging.txt"
+type NUL > "%SCRIPTDIR%\staging\new-install\staging.txt"
 
 if exist "%SCRIPTDIR%\Installer.7z" (
 	if ["%SVZIP%"] == [""] (
 		echo.
 	) else (
-		"%SVZIP%" a "%SCRIPTDIR%\Installer.7z" "%SCRIPTDIR%\new-install"
+		cd "%SCRIPTDIR%\staging"
+		"%SVZIP%" a "%SCRIPTDIR%\Installer.7z" "%SCRIPTDIR%\staging\new-install"
+		"%SVZIP%" a "%SCRIPTDIR%\Installer.7z" "%SCRIPTDIR%\staging\! SRB2 INSTALL INSTRUCTIONS !.txt"
+		cd "%SCRIPTDIR%"
 	)
 	copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2.sfx" + "%SCRIPTDIR%\sfx\config-installer.txt" + "%SCRIPTDIR%\Installer.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-Installer.exe"
 )
@@ -41,7 +44,10 @@ if exist "%SCRIPTDIR%\Patch.7z" (
 	if ["%SVZIP%"] == [""] (
 		echo.
 	) else (
-		"%SVZIP%" a "%SCRIPTDIR%\Patch.7z" "%SCRIPTDIR%\new-install\"
+		cd "%SCRIPTDIR%\staging"
+		"%SVZIP%" a "%SCRIPTDIR%\Patch.7z" "%SCRIPTDIR%\staging\new-install\"
+		"%SVZIP%" a "%SCRIPTDIR%\Patch.7z" "%SCRIPTDIR%\staging\! SRB2 INSTALL INSTRUCTIONS !.txt"
+		cd "%SCRIPTDIR%"
 	)
 	copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2.sfx" + "%SCRIPTDIR%\sfx\config-patch.txt" + "%SCRIPTDIR%\Patch.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-Patch.exe"
 )
@@ -50,7 +56,10 @@ if exist "%SCRIPTDIR%\Installer_x64.7z" (
 	if ["%SVZIP%"] == [""] (
 		echo.
 	) else (
-		"%SVZIP%" a "%SCRIPTDIR%\Installer_x64.7z" "%SCRIPTDIR%\new-install\"
+		cd "%SCRIPTDIR%\staging"
+		"%SVZIP%" a "%SCRIPTDIR%\Installer_x64.7z" "%SCRIPTDIR%\staging\new-install\"
+		"%SVZIP%" a "%SCRIPTDIR%\Installer_x64.7z" "%SCRIPTDIR%\staging\! SRB2 INSTALL INSTRUCTIONS !.txt"
+		cd "%SCRIPTDIR%"
 	)
 	copy /y /b "%SCRIPTDIR%\sfx\7zsd_LZMA2_x64.sfx" + "%SCRIPTDIR%\sfx\config-installer.txt" + "%SCRIPTDIR%\Installer_x64.7z" "%SCRIPTDIR%\SRB2-%SRB2VERSIONNAME%-x64-Installer.exe"
 )
@@ -59,9 +68,12 @@ if exist "%SCRIPTDIR%\Patch_x64.7z" (
 	if ["%SVZIP%"] == [""] (
 		echo.
 	) else (
-		"%SVZIP%" a "%SCRIPTDIR%\Patch_x64.7z" "%SCRIPTDIR%\new-install\"
+		cd "%SCRIPTDIR%\staging"
+		"%SVZIP%" a "%SCRIPTDIR%\Patch_x64.7z" "%SCRIPTDIR%\staging\new-install\"
+		"%SVZIP%" a "%SCRIPTDIR%\Patch_x64.7z" "%SCRIPTDIR%\staging\! SRB2 INSTALL INSTRUCTIONS !.txt"
+		cd "%SCRIPTDIR%"
 	)
 	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%\new-install\staging.txt"
+del /f /q "%SCRIPTDIR%\staging\new-install\staging.txt"
diff --git a/windows-installer/new-install/staging.bat b/windows-installer/new-install/staging.bat
deleted file mode 100644
index a0f3e5522..000000000
--- a/windows-installer/new-install/staging.bat
+++ /dev/null
@@ -1,253 +0,0 @@
-@echo off
-
-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
-::
-
-:: For 2.1.21, we are changing the DLL structure
-:: So move everything that's EXE or DLL
-
-set MoveOldExesDlls=1
-
-:: 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%"
-
-:: FAILSAFE: Check if staging.txt exists in the directory
-:: If not, exit, so we don't mess up anything by accident.
-
-if exist "%STAGINGDIR%\staging.txt" (
-	echo.
-) else (
-	exit
-)
-
-:: 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 errorlevel 1 (
-	echo.
-) else (
-	goto SetUserDir
-)
-
-:: Are we in Program Files (x86)?
-echo.%STAGINGDIR% | findstr /C:"%ProgramFiles(X86)%" 1>nul
-if errorlevel 1 (
-	echo.
-) else (
-	goto SetUserDir
-)
-
-:: Are we 32-bit and actually in Program Files?
-echo.%STAGINGDIR% | findstr /C:"%ProgramW6432%" 1>nul
-if errorlevel 1 (
-	echo.
-) else (
-	goto SetUserDir
-)
-
-goto MoveOldInstall
-
-: SetUserDir
-
-:: If the user folder already exists, there's nothing to do
-set "USERDIR=%UserProfile%\SRB2"
-
-:: set USERDIREXISTS=
-:: if exist "%USERDIR%\*" (
-:: 	set USERDIREXISTS=1
-:: )
-
-:: Make the folder!
-mkdir "%USERDIR%"
-
-:: 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 EXEs and DLLs
-:
-
-set OLDINSTALLCHANGED=
-
-if ["%MoveOldExesDlls%"] == ["1"] (
-	goto MoveOldInstallExeDll
-) else (
-	goto MoveOldInstallNewFiles
-)
-
-: MoveOldInstallExeDll
-
-xcopy /y /v "%INSTALLDIR%\*.exe" "%OLDINSTALLDIR%"
-if errorlevel 0 del /f /q "%INSTALLDIR%\*.exe"
-xcopy /y /v "%INSTALLDIR%\*.dll" "%OLDINSTALLDIR%"
-if errorlevel 0 del /f /q "%INSTALLDIR%\*.dll"
-
-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
-
-echo uninstall-list.txt >> "%INSTALLDIR%\uninstall-list.txt"
-echo uninstall-userdir.txt >> "%INSTALLDIR%\uninstall-list.txt"
-echo ! SRB2 Data Folder !.lnk >> "%INSTALLDIR%\uninstall-list.txt"
-
-:: Start moving files
-
-for %%F in ("%STAGINGDIR%\*") DO (
-	if exist "%INSTALLDIR%\%%~nxF" (
-		set OLDINSTALLCHANGED=1
-		move "%INSTALLDIR%\%%~nxF" "%OLDINSTALLDIR%\%%~nxF"
-	)
-	if ["%%~nxF"] == ["staging.bat"] (
-		echo.
-	) else (
-		if ["%%~nxF"] == ["staging.txt"] (
-			echo.
-		) else (
-			move "%STAGINGDIR%\%%~nxF" "%INSTALLDIR%\%%~nxF"
-		)
-	)
-)
-
-: Finished
-
-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/new-install/uninstall.bat b/windows-installer/new-install/uninstall.bat
deleted file mode 100644
index 367e5e5c6..000000000
--- a/windows-installer/new-install/uninstall.bat
+++ /dev/null
@@ -1,139 +0,0 @@
-@echo off
-
-cls
-
-set "INSTALLDIR=%~dp0"
-set "INSTALLDIR=%INSTALLDIR:~0,-1%"
-set /p USERDIR=<"%INSTALLDIR%\uninstall-userdir.txt"
-set "USERDIR=%USERDIR:~0,-1%"
-
-: ProceedPrompt
-
-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 ["%PROCEED%"] == ["1"] (
-	echo.
-) else (
-	exit
-)
-
-: DeleteFiles
-
-for /F "usebackq tokens=*" %%A in ("%INSTALLDIR%\uninstall-list.txt") do (
-	if exist "%INSTALLDIR%\%%A" (
-		if ["%%A"] == ["%~nx0"] (
-			echo.
-		) else (
-			echo Deleting %INSTALLDIR%\%%A
-			del /q /f "%INSTALLDIR%\%%A"
-		)
-	)
-)
-
-: 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 ["%%i"] == ["%~nx0"] (
-		echo.
-	) else (
-		set USERDIRFILLED=1
-		goto InstallFilledCheck
-	)
-)
-
-: InstallFilledCheck
-
-if /I ["%USERDIR%"] == ["%INSTALLDIR%"] (
-	echo.
-) else (
-	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 ["%FINALPROMPT%"] == ["Press Enter key to exit."] (
-	echo.
-) else (
-	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 "
-
diff --git a/windows-installer/sfx/config-installer.txt b/windows-installer/sfx/config-installer.txt
index 5e65786ac..4c83c2b5d 100644
--- a/windows-installer/sfx/config-installer.txt
+++ b/windows-installer/sfx/config-installer.txt
@@ -4,9 +4,9 @@ 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."
+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:"
+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"
diff --git a/windows-installer/sfx/config-patch.txt b/windows-installer/sfx/config-patch.txt
index bc8211037..e78d055ca 100644
--- a/windows-installer/sfx/config-patch.txt
+++ b/windows-installer/sfx/config-patch.txt
@@ -6,7 +6,7 @@ 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:"
+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"
diff --git a/windows-installer/staging/! SRB2 INSTALL INSTRUCTIONS !.txt b/windows-installer/staging/! SRB2 INSTALL INSTRUCTIONS !.txt
new file mode 100644
index 000000000..f367296f5
--- /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/staging.bat b/windows-installer/staging/new-install/staging.bat
new file mode 100644
index 000000000..85568efba
--- /dev/null
+++ b/windows-installer/staging/new-install/staging.bat
@@ -0,0 +1,315 @@
+@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
+::
+
+:: For 2.1.21, we are changing the DLL structure
+:: So move everything that's EXE or DLL
+
+set MoveOldExesDlls=1
+
+:: 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!"
+
+:: FAILSAFE: Check if staging.txt exists in the directory
+:: If not, exit, so we don't mess up anything by accident.
+
+if exist "!STAGINGDIR!\staging.txt" (
+	echo.
+) else (
+	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 errorlevel 1 (
+	echo.
+) else (
+	goto SetUserDir
+)
+
+:: Are we in Program Files (x86)?
+echo.!STAGINGDIR! | findstr /C:"!ProgramFiles(X86)!" 1>nul
+if errorlevel 1 (
+	echo.
+) else (
+	goto SetUserDir
+)
+
+:: Are we 32-bit and actually in Program Files?
+echo.!STAGINGDIR! | findstr /C:"!ProgramW6432!" 1>nul
+if errorlevel 1 (
+	echo.
+) else (
+	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 EXEs and DLLs
+:
+
+set OLDINSTALLCHANGED=
+
+if ["!MoveOldExesDlls!"] == ["1"] (
+	goto MoveOldInstallExeDll
+) else (
+	goto MoveOldInstallNewFiles
+)
+
+: MoveOldInstallExeDll
+
+xcopy /y /v "!INSTALLDIR!\*.exe" "!OLDINSTALLDIR!"
+if errorlevel 0 del /f /q "!INSTALLDIR!\*.exe"
+xcopy /y /v "!INSTALLDIR!\*.dll" "!OLDINSTALLDIR!"
+if errorlevel 0 del /f /q "!INSTALLDIR!\*.dll"
+
+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
+
+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"
+
+:: Start moving files
+
+for %%F in ("!STAGINGDIR!\*") DO (
+	if exist "!INSTALLDIR!\%%~nxF" (
+		set OLDINSTALLCHANGED=1
+		move "!INSTALLDIR!\%%~nxF" "!OLDINSTALLDIR!\%%~nxF"
+	)
+	if ["%%~nxF"] == ["staging.bat"] (
+		echo.
+	) else (
+		if ["%%~nxF"] == ["staging.txt"] (
+			echo.
+		) else (
+			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/staging/new-install/uninstall.bat b/windows-installer/staging/new-install/uninstall.bat
new file mode 100644
index 000000000..a0995eb49
--- /dev/null
+++ b/windows-installer/staging/new-install/uninstall.bat
@@ -0,0 +1,186 @@
+@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
+
+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 ["!PROCEED!"] == ["1"] (
+	echo.
+) else (
+	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.
+::
+set "TESTFILE=!TEMP!\!RANDOM!.txt"
+
+for /F "usebackq tokens=*" %%A in ("!INSTALLDIR!\uninstall-list.txt") do (
+	if exist "!INSTALLDIR!\%%A" (
+		if ["%%A"] == ["%~nx0"] (
+			echo.
+		) else (
+			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 ["%%i"] == ["%~nx0"] (
+		echo.
+	) else (
+		set USERDIRFILLED=1
+		goto InstallFilledCheck
+	)
+)
+
+: InstallFilledCheck
+
+if /I ["!USERDIR!"] == ["!INSTALLDIR!"] (
+	echo.
+) else (
+	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 ["!FINALPROMPT!"] == ["Press Enter key to exit."] (
+	echo.
+) else (
+	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 "