2023-07-31 03:29:43 +03:00
; includes
!include MUI2.nsh
2023-07-31 15:42:48 +03:00
!include nsDialogs.nsh
2023-07-31 03:29:43 +03:00
!include WinMessages.nsh
; settings
Name " Geode "
2023-08-01 21:57:01 +03:00
OutFile " geode-installer-win.exe "
2023-07-31 03:29:43 +03:00
Unicode true
2023-07-31 15:58:50 +03:00
InstallDir " $PROGRAMFILES32 \Steam\steamapps\common\Geometry Dash\ " ; set default path to the most common one
2023-07-31 14:23:33 +03:00
XPStyle on
2024-02-18 21:20:24 -03:00
RequestExecutionLevel user
2023-07-31 19:44:32 +03:00
ManifestSupportedOS Win7
2024-06-23 10:42:18 -04:00
SetCompressor /SOLID lzma
SetCompressorDictSize 64
SetDatablockOptimize ON
2023-07-31 03:29:43 +03:00
; ui settings
!define MUI_ABORTWARNING
!define MUI_LANGDLL_ALLLANGUAGES
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_UNFINISHPAGE_NOAUTOCLOSE
2023-07-31 14:48:50 +03:00
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
2023-07-31 16:58:09 +03:00
!define MUI_ICON Graphics\ logo_inst.ico
!define MUI_UNICON Graphics\ logo_uninst.ico
!define MUI_WELCOMEFINISHPAGE_BITMAP Graphics\ banner.bmp
!define MUI_UNWELCOMEFINISHPAGE_BITMAP Graphics\ banner.bmp
2023-07-31 03:29:43 +03:00
; pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE " ..\..\LICENSE.txt "
2023-08-25 21:02:38 +03:00
!define MUI_COMPONENTSPAGE_NODESC
!insertmacro MUI_PAGE_COMPONENTS
2023-07-31 15:42:48 +03:00
!define MUI_PAGE_CUSTOMFUNCTION_SHOW DirectoryPageShow
2023-07-31 03:29:43 +03:00
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
; languages
2023-07-31 16:58:09 +03:00
!macro GEODE_LANGUAGE NSFID
!insertmacro MUI_LANGUAGE ${NSFID}
!insertmacro LANGFILE_INCLUDE " Language Files\${NSFID}Extra.nsh "
!macroend
; TODO: add the commented out languages (other available languages are listed here: https://nsis.sourceforge.io/Examples/Modern%20UI/MultiLanguage.nsi)
!insertmacro GEODE_LANGUAGE " English "
2024-04-11 19:32:59 +02:00
!insertmacro GEODE_LANGUAGE " French "
2023-08-01 00:08:24 +02:00
!insertmacro GEODE_LANGUAGE " Spanish "
!insertmacro GEODE_LANGUAGE " SpanishInternational "
2024-04-11 13:21:58 -04:00
!insertmacro GEODE_LANGUAGE " Swedish "
2024-04-08 17:27:30 +03:00
!insertmacro GEODE_LANGUAGE " Greek "
2023-07-31 17:47:38 +03:00
!insertmacro GEODE_LANGUAGE " Finnish "
2024-06-25 16:45:51 +02:00
!insertmacro GEODE_LANGUAGE " Polish "
2023-07-31 16:58:09 +03:00
!insertmacro GEODE_LANGUAGE " Russian "
2023-07-31 17:39:47 -03:00
!insertmacro GEODE_LANGUAGE " PortugueseBR "
2024-04-11 20:20:24 +03:00
!insertmacro GEODE_LANGUAGE " Ukrainian "
2023-08-01 00:34:56 +02:00
!insertmacro GEODE_LANGUAGE " Czech "
2024-01-20 20:36:27 +03:00
!insertmacro GEODE_LANGUAGE " Turkish "
2024-02-10 17:13:42 +03:00
!insertmacro GEODE_LANGUAGE " Japanese "
2024-04-11 13:21:58 -04:00
!insertmacro GEODE_LANGUAGE " SimpChinese "
!insertmacro GEODE_LANGUAGE " TradChinese "
2024-06-25 23:47:11 +09:00
!insertmacro GEODE_LANGUAGE " Korean "
2023-07-31 03:29:43 +03:00
!insertmacro MUI_RESERVEFILE_LANGDLL
; random shit
; https://nsis.sourceforge.io/StrReplace
!define StrRep " !insertmacro StrRep "
!macro StrRep output string old new
Push ` ${string} `
Push ` ${old} `
Push ` ${new} `
!ifdef __UNINSTALL__
Call un.StrRep
!else
Call StrRep
!endif
Pop ${output}
!macroend
!macro Func_StrRep un
Function ${un} StrRep
Exch $R2 ;new
Exch 1
Exch $R1 ;old
Exch 2
Exch $R0 ;string
Push $R3
Push $R4
Push $R5
Push $R6
Push $R7
Push $R8
Push $R9
StrCpy $R3 0
StrLen $R4 $R1
StrLen $R6 $R0
StrLen $R9 $R2
loop :
StrCpy $R5 $R0 $R4 $R3
StrCmp $R5 $R1 found
StrCmp $R3 $R6 done
IntOp $R3 $R3 + 1 ;move offset by 1 to check the next character
Goto loop
found :
StrCpy $R5 $R0 $R3
IntOp $R8 $R3 + $R4
StrCpy $R7 $R0 " " $R8
StrCpy $R0 $R5 $R2 $R7
StrLen $R6 $R0
IntOp $R3 $R3 + $R9 ;move offset by length of the replacement string
Goto loop
done :
Pop $R9
Pop $R8
Pop $R7
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Push $R0
Push $R1
Pop $R0
Pop $R1
Pop $R0
Pop $R2
Exch $R1
FunctionEnd
!macroend
!insertmacro Func_StrRep " "
;!insertmacro Func_StrRep "un."
; https://nsis.sourceforge.io/Remove_leading_and_trailing_whitespaces_from_a_string
Function Trim
Exch $R1 ; Original string
Push $R2
Loop :
StrCpy $R2 " $R1 " 1
StrCmp " $R2 " " " TrimLeft
StrCmp " $R2 " " $\r " TrimLeft
StrCmp " $R2 " " $\n " TrimLeft
StrCmp " $R2 " " $\t " TrimLeft
Goto Loop2
TrimLeft :
StrCpy $R1 " $R1 " " " 1
Goto Loop
Loop2 :
StrCpy $R2 " $R1 " 1 - 1
StrCmp " $R2 " " " TrimRight
StrCmp " $R2 " " $\r " TrimRight
StrCmp " $R2 " " $\n " TrimRight
StrCmp " $R2 " " $\t " TrimRight
Goto Done
TrimRight :
StrCpy $R1 " $R1 " - 1
Goto Loop2
Done :
Pop $R2
Exch $R1
FunctionEnd
!define Trim " !insertmacro Trim "
!macro Trim ResultVar String
Push " ${String} "
Call Trim
Pop " ${ResultVar} "
!macroend
; https://nsis.sourceforge.io/Split_strings
!macro GET_STRING_TOKEN INPUT PART
Push $R0
Push $R1
Push $R2
StrCpy $R0 - 1
IntOp $R1 ${PART} * 2
IntOp $R1 $R1 - 1
findStart_loop_${PART} :
IntOp $R0 $R0 + 1
StrCpy $R2 ${INPUT} 1 $R0
StrCmp $R2 " " error_${PART}
StrCmp $R2 '"' 0 findStart_loop_${PART}
IntOp $R1 $R1 - 1
IntCmp $R1 0 0 0 findStart_loop_${PART}
IntOp $R1 $R0 + 1
findEnd_loop_${PART} :
IntOp $R0 $R0 + 1
StrCpy $R2 ${INPUT} 1 $R0
StrCmp $R2 " " error_${PART}
StrCmp $R2 '"' 0 findEnd_loop_${PART}
IntOp $R0 $R0 - $R1
StrCpy $R0 ${INPUT} $R0 $R1
Goto done_${PART}
error_${PART} :
StrCpy $R0 error
done_${PART} :
Pop $R2
Pop $R1
Exch $R0
!macroend
2023-08-25 20:05:58 +03:00
; https://nsis.sourceforge.io/StrStr
Function un.StrStr
Exch $R0
Exch
Exch $R1
Push $R2
Push $R3
Push $R4
Push $R5
StrLen $R2 $R0
StrLen $R3 $R1
StrCpy $R4 0
loop :
StrCpy $R5 $R1 $R2 $R4
StrCmp $R5 $R0 done
IntCmp $R4 $R3 done 0 done
IntOp $R4 $R4 + 1
Goto loop
done :
StrCpy $R0 $R1 ` ` $R4
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
; https://nsis.sourceforge.io/Get_command_line_parameters
Function un.GetParameters
Push $R0
Push $R1
Push $R2
Push $R3
StrCpy $R2 1
StrLen $R3 $CMDLINE
StrCpy $R0 $CMDLINE $R2
StrCmp $R0 '"' 0 + 3
StrCpy $R1 '"'
Goto loop
StrCpy $R1 " "
loop :
IntOp $R2 $R2 + 1
StrCpy $R0 $CMDLINE 1 $R2
StrCmp $R0 $R1 get
StrCmp $R2 $R3 get
Goto loop
get :
IntOp $R2 $R2 + 1
StrCpy $R0 $CMDLINE 1 $R2
StrCmp $R0 " " get
StrCpy $R0 $CMDLINE " " $R2
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
; https://nsis.sourceforge.io/Get_command_line_parameter_by_name
Function un.GetParameterValue
Exch $R0
Exch
Exch $R1
Push $R2
Push $R3
Push $R4
Push $R5
Strlen $R2 $R1 + 2
Call un.GetParameters
Pop $R3
StrCpy $R5 '"'
Push $R3
Push '"/$R1='
Call un.StrStr
Pop $R4
StrCpy $R4 $R4 " " 1
StrCmp $R4 " " " " next
StrCpy $R5 ' '
Push $R3
Push '/$R1='
Call un.StrStr
Pop $R4
next :
StrCmp $R4 " " check_for_switch
StrCpy $R0 $R4 " " $R2
Push $R0
Push $R5
Call un.StrStr
Pop $R4
StrCmp $R4 " " done
StrLen $R4 $R4
StrCpy $R0 $R0 - $R4
goto done
check_for_switch :
Push $R3
Push '/$R1'
Call un.StrStr
Pop $R4
StrCmp $R4 " " done
StrCpy $R0 " "
done :
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
2023-07-31 03:29:43 +03:00
; actual code
2023-08-01 21:57:01 +03:00
!define BINDIR ..\ ..\ bin\ nightly
2023-07-31 03:29:43 +03:00
2023-07-31 14:03:48 +03:00
; installer
2023-07-31 15:42:48 +03:00
Var geode.DirectoryPage.ErrorText
2023-07-31 03:29:43 +03:00
Var GamePath
Function FindGamePath
Push $0
Push $1
Push $2
Push $3
Push $4
# get steam path
ReadRegStr $0 HKCU " Software\Valve\Steam " " SteamPath "
IfErrors gamePathError
${StrRep} $0 $0 " / " " \ "
# read library folders
FileOpen $1 " $0 \steamapps\libraryfolders.vdf " r
IfErrors gamePathError
vdfReadLine :
ClearErrors
FileRead $1 $2
IfErrors vdfDone
${Trim} $2 $2
!insertmacro GET_STRING_TOKEN $2 1
Pop $4
StrCmp $4 " path " 0 vdfCheckAppId
!insertmacro GET_STRING_TOKEN $2 2
Pop $3 # save current library path into $3
vdfCheckAppId :
SetErrors
StrCmp $4 " 322170 " 0 vdfReadLine
ClearErrors # gd found in current library
vdfDone :
IfErrors gamePathError
FileClose $1
IfErrors gamePathError
${StrRep} $0 $3 " \\ " " \ "
StrCpy $GamePath " $0 \steamapps\common\Geometry Dash "
# make sure game path is correct
IfFileExists " $GamePath \*.exe " + 2 0
gamePathError :
SetErrors
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
2023-07-31 15:42:48 +03:00
Function DirectoryPageShow
2023-07-31 16:58:09 +03:00
System :: Call 'USER32::CreateWindowEx(i${__NSD_Label_EXSTYLE}, t"${__NSD_Label_CLASS}", t"", i${__NSD_Label_STYLE}, i0, i70, i400, i40, p$mui.DirectoryPage, p0, p0, p0)p.s'
2023-07-31 15:42:48 +03:00
Pop $geode .DirectoryPage.ErrorText
ShowWindow $geode .DirectoryPage.ErrorText 0
SendMessage $mui .DirectoryPage ${WM_GETFONT} 0 0 $0
SendMessage $geode .DirectoryPage.ErrorText ${WM_SETFONT} $0 1
SetCtlColors $geode .DirectoryPage.ErrorText ff0000 transparent
; place the label at the top
System :: Call 'USER32::SetWindowPos(p$geode.DirectoryPage.ErrorText, p0, i0, i0, i0, i0, i3)i'
Pop $0
FunctionEnd
2023-07-31 03:29:43 +03:00
Function .onVerifyInstDir
LockWindow on
; check if there's any exe and libcocos2d.dll (GeometryDash.exe won't work because of GDPSes)
IfFileExists $INSTDIR \ * .exe 0 noGameNoLife
2023-07-31 17:15:40 +03:00
IfFileExists $INSTDIR \ libcocos2d.dll 0 noGameNoLife
2023-07-31 03:29:43 +03:00
2024-07-06 00:52:11 +02:00
; check if we're on 64-bit gd (checks for some of the DLLs introduced in 2.206)
IfFileExists $INSTDIR \ libpng16.dll 0 versionIssueImo
IfFileExists $INSTDIR \ pthreadVC3.dll 0 versionIssueImo
IfFileExists $INSTDIR \ libcrypto- 3- x64.dll 0 versionIssueImo
2023-07-31 17:15:40 +03:00
; check if geode is already installed
IfFileExists $INSTDIR \ Geode.dll valid
2023-07-31 03:29:43 +03:00
2023-07-31 17:15:40 +03:00
; check mod loaders/mod menus
2024-01-20 19:58:36 +03:00
IfFileExists $INSTDIR \ hackpro.dll other_hackpro
2024-06-02 09:36:33 +02:00
IfFileExists $INSTDIR \ XInput1_4.dll other_xinput
2023-07-31 03:29:43 +03:00
2023-07-31 17:15:40 +03:00
; all checks passed
valid :
ShowWindow $geode .DirectoryPage.ErrorText 0
2023-07-31 03:29:43 +03:00
LockWindow off
Return
noGameNoLife :
2023-07-31 16:58:09 +03:00
SendMessage $geode .DirectoryPage.ErrorText ${WM_SETTEXT} " " " STR:$(GEODE_TEXT_GD_MISSING) "
2023-07-31 17:15:40 +03:00
Goto error
2024-07-06 00:52:11 +02:00
versionIssueImo :
SendMessage $geode .DirectoryPage.ErrorText ${WM_SETTEXT} " " " STR:$(GEODE_TEXT_GD_OLD) "
Goto error
2024-01-20 19:58:36 +03:00
other_hackpro :
StrCpy $0 " hackpro.dll "
Goto other
2024-06-02 09:36:33 +02:00
other_xinput :
StrCpy $0 " XInput1_4.dll "
2024-01-20 19:58:36 +03:00
Goto other
2023-07-31 17:15:40 +03:00
other :
2024-01-20 20:10:57 +03:00
${StrRep} $0 $ ( GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED) " the dll trademark " $0
2024-01-20 19:58:36 +03:00
SendMessage $geode .DirectoryPage.ErrorText ${WM_SETTEXT} " " " STR:$0 "
2024-06-23 18:17:21 -03:00
SetCtlColors $geode .DirectoryPage.ErrorText e25402 transparent
LockWindow off
Return
2023-07-31 17:15:40 +03:00
error :
2023-07-31 15:42:48 +03:00
ShowWindow $geode .DirectoryPage.ErrorText 1
2024-06-23 18:17:21 -03:00
SetCtlColors $geode .DirectoryPage.ErrorText ff0000 transparent
2023-07-31 03:29:43 +03:00
LockWindow off
Abort
Return
FunctionEnd
2023-07-31 14:34:11 +03:00
2023-08-25 21:02:38 +03:00
SectionGroup " Geode "
Section " Loader " LOADER_SECTION
SetOutPath $INSTDIR
File ${BINDIR} \ Geode.dll
File ${BINDIR} \ Geode.pdb
File ${BINDIR} \ GeodeUpdater.exe
2024-06-02 09:36:33 +02:00
File ${BINDIR} \ XInput1_4.dll
2023-08-25 21:02:38 +03:00
2024-06-23 22:05:50 +02:00
RMdir /r $INSTDIR \ geode\ update
2024-06-23 22:07:03 +02:00
RMdir /r $INSTDIR \ geode\ index
Delete " $INSTDIR \xinput9_1_0.dll "
Delete " $INSTDIR \xinput9_1_0.lib "
Delete " $INSTDIR \xinput9_1_0.pdb "
2024-06-23 22:05:50 +02:00
2024-06-23 18:17:21 -03:00
Delete " $INSTDIR \hackpro.dll "
2024-06-24 12:29:55 +02:00
Delete " $INSTDIR \msvcp140.dll "
Delete " $INSTDIR \msvcp140d.dll "
2024-06-24 14:33:34 +02:00
Delete " $INSTDIR \vcruntime140.dll "
Delete " $INSTDIR \vcruntime140d.dll "
2024-06-24 12:29:55 +02:00
2023-08-25 21:02:38 +03:00
WriteUninstaller " GeodeUninstaller.exe "
SectionEnd
Section " Resources "
CreateDirectory $INSTDIR \ geode\ resources\ geode.loader
SetOutPath $INSTDIR \ geode\ resources\ geode.loader
File /r ${BINDIR} \ resources\ *
SectionEnd
SectionGroupEnd
2023-08-01 21:57:01 +03:00
; download vc redist in compile-time
!execute " pwsh -nol -noni -nop dl-vcr.ps1 "
2023-07-31 14:34:11 +03:00
Section " Visual Studio Runtime "
SetOutPath $INSTDIR
2024-06-08 17:11:28 -03:00
File VC_redist.x64.exe
ExecWait " $INSTDIR \VC_redist.x64.exe /install /quiet /norestart "
Delete " $INSTDIR \VC_redist.x64.exe "
2023-07-31 14:34:11 +03:00
SectionEnd
2024-01-20 19:28:53 +03:00
Section " steam_appid.txt "
SetOutPath $INSTDIR
FileOpen $0 " $INSTDIR \steam_appid.txt " w
FileWrite $0 " 322170 "
FileClose $0
SectionEnd
2023-08-25 21:02:38 +03:00
Function .onInit
!insertmacro MUI_LANGDLL_DISPLAY
2023-08-03 01:54:26 +03:00
2023-08-25 21:02:38 +03:00
IntOp $0 ${SF_SELECTED} | ${SF_RO}
SectionSetFlags ${LOADER_SECTION} $0
2023-07-31 17:47:38 +03:00
2023-08-25 21:02:38 +03:00
Call FindGamePath
IfErrors 0 + 3
StrCpy $GamePath " "
Return
StrCpy $INSTDIR " $GamePath \ "
FunctionEnd
2023-07-31 03:29:43 +03:00
2023-07-31 14:03:48 +03:00
; uninstaller
Function un.onInit
!insertmacro MUI_UNGETLANGUAGE
; verify uninst dir
; check if there's any exe and libcocos2d.dll (GeometryDash.exe won't work because of GDPSes)
IfFileExists $INSTDIR \ * .exe 0 invalid
IfFileExists $INSTDIR \ libcocos2d.dll 0 invalid
2024-06-02 09:36:33 +02:00
; check if xinput and geode exist
IfFileExists $INSTDIR \ XInput1_4.dll 0 invalid
2023-07-31 14:03:48 +03:00
IfFileExists $INSTDIR \ Geode.dll 0 invalid
Return
invalid :
2023-07-31 16:58:09 +03:00
MessageBox MB_ICONSTOP | MB_OK $ ( GEODE_UNTEXT_GEODE_MISSING)
2023-07-31 14:03:48 +03:00
Abort
FunctionEnd
2023-07-31 03:29:43 +03:00
Section " Uninstall "
2023-08-25 20:05:58 +03:00
DeleteRegKey /ifempty HKCU " Software\Geode "
2023-09-11 16:36:35 +03:00
Delete $INSTDIR \ GeodeUninstaller.exe
2023-07-31 03:29:43 +03:00
Delete $INSTDIR \ Geode.dll
Delete $INSTDIR \ Geode.pdb
2023-09-11 16:36:35 +03:00
Delete $INSTDIR \ Geode.lib
2023-07-31 03:29:43 +03:00
Delete $INSTDIR \ GeodeUpdater.exe
2024-06-02 09:36:33 +02:00
Delete $INSTDIR \ XInput1_4.dll
2023-08-25 20:05:58 +03:00
# default value of DATA is an empty string
# if DATA is empty, keep user data
# otherwise, delete the entire geode and DATA\geode\mods dirs
# the reason we're deleting DATA\geode\mods instead of just passing
# that dir directly to DATA is so that in case someone (either accidentally or maliciously)
# passes the wrong directory, the uninstaller doesn't just blindly clear it
# it will also check for the presence of CCGameManager.dat and CCLocalLevels.dat in DATA
Push " DATA "
Push " "
Call un.GetParameterValue
Pop $0
StrCmp $0 " " keep_data remove_data
keep_data :
# keep configs, mods, logs and crash logs
RMdir /r $INSTDIR \ geode\ index
RMdir /r $INSTDIR \ geode\ resources
RMdir /r $INSTDIR \ geode\ temp
RMdir /r $INSTDIR \ geode\ unzipped
RMdir /r $INSTDIR \ geode\ update
Return
remove_data :
RMdir /r $INSTDIR \ geode
IfFileExists $0 \ CCGameManager.dat 0 invalid
IfFileExists $0 \ CCLocalLevels.dat 0 invalid
RMdir /r $0 \ geode\ mods ; delete DATA\geode\mods
RMdir $0 \ geode ; then delete DATA\geode non-recursively, assuming mods is the only directory in DATA\geode
Return
invalid :
# this message doesnt rly need translatable as
# its only supposed to be used internally by geode itself
MessageBox MB_ICONSTOP | MB_OK " The path passed to DATA is not a valid Geometry Dash data folder! "
Abort
2023-07-31 03:29:43 +03:00
SectionEnd