From bc8e66c202ce9af15aa12718939726eea42b25fd Mon Sep 17 00:00:00 2001 From: rubidium Date: Mon, 31 Aug 2009 22:38:37 +0000 Subject: (svn r17336) -Codechange: move some os specific files into src/os/ --- Makefile.src.in | 6 +- os/win32/installer/build_installers.bat | 4 - os/win32/installer/cdfinder.ini | 26 - os/win32/installer/install.nsi | 546 ------------ os/win32/installer/top.bmp | Bin 25820 -> 0 bytes os/win32/installer/version_win32.txt | 5 - os/win32/installer/version_win64.txt | 5 - os/win32/installer/version_win9x.txt | 5 - os/win32/installer/welcome.bmp | Bin 154544 -> 0 bytes os/windows/installer/build_installers.bat | 4 + os/windows/installer/cdfinder.ini | 26 + os/windows/installer/install.nsi | 546 ++++++++++++ os/windows/installer/top.bmp | Bin 0 -> 25820 bytes os/windows/installer/version_win32.txt | 5 + os/windows/installer/version_win64.txt | 5 + os/windows/installer/version_win9x.txt | 5 + os/windows/installer/welcome.bmp | Bin 0 -> 154544 bytes projects/determineversion.vbs | 4 +- projects/openttd_vs80.vcproj | 10 +- projects/openttd_vs80.vcproj.in | 4 +- projects/openttd_vs90.vcproj | 10 +- projects/openttd_vs90.vcproj.in | 4 +- source.list | 14 +- src/fontcache.cpp | 2 +- src/masm64.rules | 266 ------ src/music/dmusic.cpp | 2 +- src/os/os2/os2.cpp | 243 +++++ src/os/unix/unix.cpp | 314 +++++++ src/os/windows/masm64.rules | 266 ++++++ src/os/windows/ottdres.rc.in | 111 +++ src/os/windows/win32.cpp | 1378 +++++++++++++++++++++++++++++ src/os/windows/win32.h | 55 ++ src/os/windows/win64.asm | 8 + src/os2.cpp | 243 ----- src/ottdres.rc.in | 111 --- src/unix.cpp | 314 ------- src/video/win32_v.cpp | 2 +- src/win32.cpp | 1378 ----------------------------- src/win32.h | 55 -- src/win64.asm | 8 - 40 files changed, 2995 insertions(+), 2995 deletions(-) delete mode 100644 os/win32/installer/build_installers.bat delete mode 100644 os/win32/installer/cdfinder.ini delete mode 100644 os/win32/installer/install.nsi delete mode 100644 os/win32/installer/top.bmp delete mode 100644 os/win32/installer/version_win32.txt delete mode 100644 os/win32/installer/version_win64.txt delete mode 100644 os/win32/installer/version_win9x.txt delete mode 100644 os/win32/installer/welcome.bmp create mode 100644 os/windows/installer/build_installers.bat create mode 100644 os/windows/installer/cdfinder.ini create mode 100644 os/windows/installer/install.nsi create mode 100644 os/windows/installer/top.bmp create mode 100644 os/windows/installer/version_win32.txt create mode 100644 os/windows/installer/version_win64.txt create mode 100644 os/windows/installer/version_win9x.txt create mode 100644 os/windows/installer/welcome.bmp delete mode 100644 src/masm64.rules create mode 100644 src/os/os2/os2.cpp create mode 100644 src/os/unix/unix.cpp create mode 100644 src/os/windows/masm64.rules create mode 100644 src/os/windows/ottdres.rc.in create mode 100644 src/os/windows/win32.cpp create mode 100644 src/os/windows/win32.h create mode 100644 src/os/windows/win64.asm delete mode 100644 src/os2.cpp delete mode 100644 src/ottdres.rc.in delete mode 100644 src/unix.cpp delete mode 100644 src/win32.cpp delete mode 100644 src/win32.h delete mode 100644 src/win64.asm diff --git a/Makefile.src.in b/Makefile.src.in index 739a9aa3b..e0083ce2a 100644 --- a/Makefile.src.in +++ b/Makefile.src.in @@ -278,8 +278,8 @@ $(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp $(SRC_DIR)/rev.cpp: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/rev.cpp.in $(Q)cat $(SRC_DIR)/rev.cpp.in | sed "s@\!\!REVISION\!\!@$(REV_NR)@g;s@!!VERSION!!@$(REV)@g;s@!!MODIFIED!!@$(MODIFIED)@g;s@!!DATE!!@`date +%d.%m.%y`@g" > $(SRC_DIR)/rev.cpp -$(SRC_DIR)/ottdres.rc: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/ottdres.rc.in - $(Q)cat $(SRC_DIR)/ottdres.rc.in | sed "s@\!\!REVISION\!\!@$(REV_NR)@g;s@!!VERSION!!@$(REV)@g;s@!!DATE!!@`date +%d.%m.%y`@g" > $(SRC_DIR)/ottdres.rc +$(SRC_DIR)/os/windows/ottdres.rc: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/os/windows/ottdres.rc.in + $(Q)cat $(SRC_DIR)/os/windows/ottdres.rc.in | sed "s@\!\!REVISION\!\!@$(REV_NR)@g;s@!!VERSION!!@$(REV)@g;s@!!DATE!!@`date +%d.%m.%y`@g" > $(SRC_DIR)/os/windows/ottdres.rc FORCE: @@ -290,7 +290,7 @@ clean: $(Q)rm -f $(DEPS) $(OBJS) $(TTD) $(DEPEND) $(TTD:%=$(BIN_DIR)/%) $(CONFIG_CACHE_COMPILER) $(CONFIG_CACHE_LINKER) $(CONFIG_CACHE_ENDIAN) $(CONFIG_CACHE_SOURCE) $(ENDIAN_TARGETS) mrproper: clean - $(Q)rm -f $(SRC_DIR)/rev.cpp $(SRC_DIR)/ottdres.rc + $(Q)rm -f $(SRC_DIR)/rev.cpp $(SRC_DIR)/os/windows/ottdres.rc %.o: @echo '$(STAGE) No such source-file: $(@:%.o=%).[c|cpp|mm|rc]' diff --git a/os/win32/installer/build_installers.bat b/os/win32/installer/build_installers.bat deleted file mode 100644 index 73a2898da..000000000 --- a/os/win32/installer/build_installers.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -"c:\Program Files\NSIS\makensis.exe" /DVERSION_INCLUDE=version_win9x.txt install.nsi > win9x.log -"c:\Program Files\NSIS\makensis.exe" /DVERSION_INCLUDE=version_win32.txt install.nsi > win32.log -"c:\Program Files\NSIS\makensis.exe" /DVERSION_INCLUDE=version_win64.txt install.nsi > win64.log diff --git a/os/win32/installer/cdfinder.ini b/os/win32/installer/cdfinder.ini deleted file mode 100644 index 45f9602f1..000000000 --- a/os/win32/installer/cdfinder.ini +++ /dev/null @@ -1,26 +0,0 @@ -; Ini file generated by the HM NIS Edit IO designer. -[Settings] -NumFields=3 - -[Field 1] -Type=Groupbox -Text=Transport Tycoon Deluxe Installation location -Left=6 -Right=294 -Top=68 -Bottom=100 - -[Field 2] -Type=DirRequest -Left=10 -Right=290 -Top=80 -Bottom=92 - -[Field 3] -Type=Label -Left=17 -Right=282 -Top=6 -Bottom=64 - diff --git a/os/win32/installer/install.nsi b/os/win32/installer/install.nsi deleted file mode 100644 index 69534505a..000000000 --- a/os/win32/installer/install.nsi +++ /dev/null @@ -1,546 +0,0 @@ -!define APPNAME "OpenTTD" ; Define application name -!define APPVERSION "0.8.0" ; Define application version -!define APPVERSIONINTERNAL "0.8.0.0" ; Define application version in X.X.X.X -!define INSTALLERVERSION 65 ; NEED TO UPDATE THIS FOR EVERY RELEASE!!! -!include ${VERSION_INCLUDE} - -!define APPURLLINK "http://www.openttd.org" -!define APPNAMEANDVERSION "${APPNAME} ${APPVERSION}" - -!define OPENGFX_BASE_VERSION "0.7.0" -!define OPENSFX_BASE_VERSION "0.8.0" - -!define MUI_ICON "..\..\..\media\openttd.ico" -!define MUI_UNICON "..\..\..\media\openttd.ico" -!define MUI_WELCOMEFINISHPAGE_BITMAP "welcome.bmp" -!define MUI_HEADERIMAGE -!define MUI_HEADERIMAGE_BITMAP "top.bmp" - -BrandingText "OpenTTD Installer" -SetCompressor LZMA - -; Version Info -Var AddWinPrePopulate -VIProductVersion "${APPVERSIONINTERNAL}" -VIAddVersionKey "ProductName" "OpenTTD Installer ${APPBITS} bits version ${EXTRA_VERSION}" -VIAddVersionKey "Comments" "Installs ${APPNAMEANDVERSION}" -VIAddVersionKey "CompanyName" "OpenTTD Developers" -VIAddVersionKey "FileDescription" "Installs ${APPNAMEANDVERSION}" -VIAddVersionKey "ProductVersion" "${APPVERSION}" -VIAddVersionKey "InternalName" "InstOpenTTD-${APPARCH}" -VIAddVersionKey "FileVersion" "${APPVERSION}-${APPARCH}" -VIAddVersionKey "LegalCopyright" " " -; Main Install settings -Name "${APPNAMEANDVERSION} ${APPBITS} bits version ${EXTRA_VERSION}" - -; NOTE: Keep trailing backslash! -InstallDirRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Install Folder" -OutFile "openttd-${APPVERSION}-${APPARCH}.exe" -CRCCheck force - -ShowInstDetails show -ShowUninstDetails show - -Var SHORTCUTS -Var CDDRIVE - -; Modern interface settings -!include "MUI.nsh" - -!define MUI_ABORTWARNING -!define MUI_WELCOMEPAGE_TITLE_3LINES -!insertmacro MUI_PAGE_WELCOME - -!define MUI_LICENSEPAGE_RADIOBUTTONS -!insertmacro MUI_DEFAULT MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_ACCEPT "I &accept this agreement" -!insertmacro MUI_DEFAULT MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_DECLINE "I &do not accept this agreement" -!insertmacro MUI_PAGE_LICENSE "..\..\..\COPYING" - -!insertmacro MUI_PAGE_COMPONENTS - -;--------------------------------- -; Custom page for finding TTDLX CD -Page custom SelectCDEnter SelectCDExit ": TTD folder" - -!insertmacro MUI_PAGE_DIRECTORY - -;Start Menu Folder Page Configuration -!define MUI_STARTMENUPAGE_DEFAULTFOLDER $SHORTCUTS -!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKEY_LOCAL_MACHINE" -!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" -!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Shortcut Folder" - -!insertmacro MUI_PAGE_STARTMENU "OpenTTD" $SHORTCUTS - -!insertmacro MUI_PAGE_INSTFILES - -!define MUI_FINISHPAGE_TITLE_3LINES -!define MUI_FINISHPAGE_RUN_TEXT "Run ${APPNAMEANDVERSION} now!" -!define MUI_FINISHPAGE_RUN "$INSTDIR\openttd.exe" -!define MUI_FINISHPAGE_LINK "Visit the OpenTTD site for latest news, FAQs and downloads" -!define MUI_FINISHPAGE_LINK_LOCATION "${APPURLLINK}" -!define MUI_FINISHPAGE_NOREBOOTSUPPORT -!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\readme.txt" -!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED -!define MUI_WELCOMEFINISHPAGE_CUSTOMFUNCTION_INIT DisableBack - -!insertmacro MUI_PAGE_FINISH -!define MUI_PAGE_HEADER_TEXT "Uninstall ${APPNAMEANDVERSION}" -!insertmacro MUI_UNPAGE_CONFIRM -!insertmacro MUI_UNPAGE_INSTFILES - -; Set languages (first is default language) -!insertmacro MUI_LANGUAGE "English" -!insertmacro MUI_RESERVEFILE_LANGDLL - -;-------------------------------------------------------------- -; (Core) OpenTTD install section. Copies all internal game data -Section "!OpenTTD" Section1 - ; Overwrite files by default, but don't complain on failure - SetOverwrite try - - ; Define root variable relative to installer - !define PATH_ROOT "..\..\..\" - - ; Copy language files - SetOutPath "$INSTDIR\lang\" - File ${PATH_ROOT}bin\lang\*.lng - - ; Copy AI files - SetOutPath "$INSTDIR\ai\" - File ${PATH_ROOT}bin\ai\compat_*.nut - - ; Copy data files - SetOutPath "$INSTDIR\data\" - File ${PATH_ROOT}bin\data\*.grf - File ${PATH_ROOT}bin\data\*.obg - File ${PATH_ROOT}bin\data\*.obs - File ${PATH_ROOT}bin\data\opntitle.dat - - ; Copy the scripts - SetOutPath "$INSTDIR\scripts\" - File ${PATH_ROOT}bin\scripts\*.* - - ; Copy the rest of the stuff - SetOutPath "$INSTDIR\" - - ; Copy text files - File ${PATH_ROOT}changelog.txt - File ${PATH_ROOT}COPYING - File ${PATH_ROOT}readme.txt - File ${PATH_ROOT}known-bugs.txt - - ; Copy executable - File /oname=openttd.exe ${BINARY_DIR}\openttd.exe - - - ; Delete old files from the main dir. they are now placed in data/ and lang/ - Delete "$INSTDIR\*.lng" - Delete "$INSTDIR\*.grf" - Delete "$INSTDIR\sample.cat" - Delete "$INSTDIR\ttd.exe" - - - ; Create the Registry Entries - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Comments" "Visit ${APPURLLINK}" - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayIcon" "$INSTDIR\openttd.exe,0" - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayName" "OpenTTD ${APPVERSION}" - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayVersion" "${APPVERSION}" - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "HelpLink" "${APPURLLINK}" - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Install Folder" "$INSTDIR" - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Publisher" "OpenTTD" - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Shortcut Folder" "$SHORTCUTS" - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "UninstallString" "$INSTDIR\uninstall.exe" - WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "URLInfoAbout" "${APPURLLINK}" - ; This key sets the Version DWORD that new installers will check against - WriteRegDWORD HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Version" ${INSTALLERVERSION} - - !insertmacro MUI_STARTMENU_WRITE_BEGIN "OpenTTD" - CreateShortCut "$DESKTOP\OpenTTD.lnk" "$INSTDIR\openttd.exe" - CreateDirectory "$SMPROGRAMS\$SHORTCUTS" - CreateShortCut "$SMPROGRAMS\$SHORTCUTS\OpenTTD.lnk" "$INSTDIR\openttd.exe" - CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Uninstall.lnk" "$INSTDIR\uninstall.exe" - CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Readme.lnk" "$INSTDIR\Readme.txt" - CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Changelog.lnk" "$INSTDIR\Changelog.txt" - CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Known-bugs.lnk" "$INSTDIR\known-bugs.txt" - !insertmacro MUI_STARTMENU_WRITE_END -SectionEnd - -;---------------------------------------------------------------------------------- -; OpenGFX files install section. Downloads OpenGFX and installs it -Section "Download free Graphics" Section3 - SetOverwrite try - - NSISdl::download "http://binaries.openttd.org/installer/opengfx-${OPENGFX_BASE_VERSION}.tar.7z" "$INSTDIR\data\opengfx.tar.7z" - Pop $R0 ;Get the return value - StrCmp $R0 "success" +3 - MessageBox MB_OK "Downloading of OpenGFX failed" - Goto Done - - ; Let's extract the files - SetOutPath "$INSTDIR\data\" - NSIS7z::Extract "$INSTDIR\data\opengfx.tar.7z" - - Delete "$INSTDIR\data\opengfx.tar.7z" - SetOutPath "$INSTDIR\" -Done: - -SectionEnd - -;---------------------------------------------------------------------------------- -; OpenSFX files install section. Downloads OpenSFX and installs it -Section "Download free Sounds" Section4 - SetOverwrite try - - NSISdl::download "http://binaries.openttd.org/installer/opensfx-${OPENSFX_BASE_VERSION}.tar.7z" "$INSTDIR\data\opensfx.tar.7z" - Pop $R0 ;Get the return value - StrCmp $R0 "success" +3 - MessageBox MB_OK "Downloading of OpenSFX failed" - Goto Done - - ; Let's extract the files - SetOutPath "$INSTDIR\data\" - NSIS7z::Extract "$INSTDIR\data\opensfx.tar.7z" - - Delete "$INSTDIR\data\opensfx.tar.7z" - SetOutPath "$INSTDIR\" -Done: - -SectionEnd - -;---------------------------------------------------------------------------------- -; TTDLX files install section. Copies all needed TTDLX files from CD or install dir -Section /o "Copy Game Graphics" Section2 - SetOverwrite try - ; Let's copy the files with size approximation - SetOutPath "$INSTDIR\gm" - CopyFiles "$CDDRIVE\gm\*.gm" "$INSTDIR\gm\" 1028 - SetOutPath "$INSTDIR\data\" - CopyFiles "$CDDRIVE\sample.cat" "$INSTDIR\data\sample.cat" 1566 - ; Copy Windows files - CopyFiles "$CDDRIVE\trg1r.grf" "$INSTDIR\data\trg1r.grf" 2365 - CopyFiles "$CDDRIVE\trgcr.grf" "$INSTDIR\data\trgcr.grf" 260 - CopyFiles "$CDDRIVE\trghr.grf" "$INSTDIR\data\trghr.grf" 400 - CopyFiles "$CDDRIVE\trgir.grf" "$INSTDIR\data\trgir.grf" 334 - CopyFiles "$CDDRIVE\trgtr.grf" "$INSTDIR\data\trgtr.grf" 546 - ; Copy DOS files - CopyFiles "$CDDRIVE\trg1.grf" "$INSTDIR\data\trg1.grf" 2365 - CopyFiles "$CDDRIVE\trgc.grf" "$INSTDIR\data\trgc.grf" 260 - CopyFiles "$CDDRIVE\trgh.grf" "$INSTDIR\data\trgh.grf" 400 - CopyFiles "$CDDRIVE\trgi.grf" "$INSTDIR\data\trgi.grf" 334 - CopyFiles "$CDDRIVE\trgt.grf" "$INSTDIR\data\trgt.grf" 546 - SetOutPath "$INSTDIR\" -SectionEnd - -;------------------------------------------- -; Install the uninstaller (option is hidden) -Section -FinishSection - WriteUninstaller "$INSTDIR\uninstall.exe" -SectionEnd - -; Modern install component descriptions -!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN - !insertmacro MUI_DESCRIPTION_TEXT ${Section1} "OpenTTD is a fully functional clone of Transport Tycoon Deluxe and is very playable. You need at least one of the game graphics and sound sets installed" - !insertmacro MUI_DESCRIPTION_TEXT ${Section3} "Download the free OpenGFX game graphics. This download is about 3 MiB." - !insertmacro MUI_DESCRIPTION_TEXT ${Section4} "Download the free OpenSFX game sounds. This download is about 7 MiB." - !insertmacro MUI_DESCRIPTION_TEXT ${Section2} "Copies the game graphics and sounds from the Transport Tycoon Deluxe CD." -!insertmacro MUI_FUNCTION_DESCRIPTION_END - -;----------------------------------------------- -; Uninstall section, deletes all installed files -Section "Uninstall" - MessageBox MB_YESNO|MB_ICONQUESTION \ - "Remove the save game folders located at $\"$INSTDIR\save?$\"$\n \ - If you choose Yes, your saved games will be deleted." \ - IDYES RemoveSavedGames IDNO NoRemoveSavedGames - RemoveSavedGames: - Delete "$INSTDIR\save\autosave\*" - RMDir "$INSTDIR\save\autosave" - Delete "$INSTDIR\save\*" - RMDir "$INSTDIR\save" - NoRemoveSavedGames: - - MessageBox MB_YESNO|MB_ICONQUESTION \ - "Remove the scenario folders located at $\"$INSTDIR\scenario?$\"$\n \ - If you choose Yes, your scenarios will be deleted." \ - IDYES RemoveScen IDNO NoRemoveScen - RemoveScen: - Delete "$INSTDIR\scenario\heightmap*" - RMDir "$INSTDIR\scenario\heightmap" - Delete "$INSTDIR\scenario\*" - RMDir "$INSTDIR\scenario" - NoRemoveScen: - - ; Remove from registry... - !insertmacro MUI_STARTMENU_GETFOLDER "OpenTTD" $SHORTCUTS - ReadRegStr $SHORTCUTS HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Shortcut Folder" - - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" - - ; Delete self - Delete "$INSTDIR\uninstall.exe" - - ; Delete Shortcuts - Delete "$DESKTOP\OpenTTD.lnk" - Delete "$SMPROGRAMS\$SHORTCUTS\OpenTTD.lnk" - Delete "$SMPROGRAMS\$SHORTCUTS\Uninstall.lnk" - Delete "$SMPROGRAMS\$SHORTCUTS\Readme.lnk" - Delete "$SMPROGRAMS\$SHORTCUTS\Changelog.lnk" - Delete "$SMPROGRAMS\$SHORTCUTS\Known-bugs.lnk" - - ; Clean up OpenTTD dir - Delete "$INSTDIR\changelog.txt" - Delete "$INSTDIR\readme.txt" - Delete "$INSTDIR\known-bugs.txt" - Delete "$INSTDIR\openttd.exe" - Delete "$INSTDIR\COPYING" - Delete "$INSTDIR\INSTALL.LOG" - Delete "$INSTDIR\crash.log" - Delete "$INSTDIR\crash.dmp" - Delete "$INSTDIR\openttd.cfg" - Delete "$INSTDIR\hs.dat" - Delete "$INSTDIR\cached_sprites.*" - Delete "$INSTDIR\save\autosave\network*.tmp" ; temporary network file - - ; AI files - Delete "$INSTDIR\ai\compat_*.nut" - - ; Data files - Delete "$INSTDIR\data\opntitle.dat" - - Delete "$INSTDIR\data\2ccmap.grf" - Delete "$INSTDIR\data\airports.grf" - Delete "$INSTDIR\data\autorail.grf" - Delete "$INSTDIR\data\canalsw.grf" - Delete "$INSTDIR\data\dosdummy.grf" - Delete "$INSTDIR\data\elrailsw.grf" - Delete "$INSTDIR\data\nsignalsw.grf" - Delete "$INSTDIR\data\openttd.grf" - Delete "$INSTDIR\data\roadstops.grf" - Delete "$INSTDIR\data\trkfoundw.grf" - Delete "$INSTDIR\data\openttdd.grf" - Delete "$INSTDIR\data\openttdw.grf" - Delete "$INSTDIR\data\orig_win.obg" - Delete "$INSTDIR\data\orig_dos.obg" - Delete "$INSTDIR\data\orig_dos_de.obg" - Delete "$INSTDIR\data\orig_win.obs" - Delete "$INSTDIR\data\orig_dos.obs" - - Delete "$INSTDIR\data\sample.cat" - ; Windows Data files - Delete "$INSTDIR\data\trg1r.grf" - Delete "$INSTDIR\data\trghr.grf" - Delete "$INSTDIR\data\trgtr.grf" - Delete "$INSTDIR\data\trgcr.grf" - Delete "$INSTDIR\data\trgir.grf" - ; Dos Data files - Delete "$INSTDIR\data\trg1.grf" - Delete "$INSTDIR\data\trgh.grf" - Delete "$INSTDIR\data\trgt.grf" - Delete "$INSTDIR\data\trgc.grf" - Delete "$INSTDIR\data\trgi.grf" - - ; Music - Delete "$INSTDIR\gm\*.gm" - - ; Downloaded OpenGFX/OpenSFX - Delete "$INSTDIR\data\opengfx.tar" - Delete "$INSTDIR\data\opensfx.tar" - - ; Language files - Delete "$INSTDIR\lang\*.lng" - - ; Scripts - Delete "$INSTDIR\scripts\*.*" - - ; Remove remaining directories - RMDir "$SMPROGRAMS\$SHORTCUTS\Extras\" - RMDir "$SMPROGRAMS\$SHORTCUTS" - RMDir "$INSTDIR\gm" - RMDir "$INSTDIR\lang" - RMDir "$INSTDIR\data" - RMDir "$INSTDIR" - -SectionEnd - -;------------------------------------------------------------ -; Custom page function to find the TTDLX CD/install location -Function SelectCDEnter - SectionGetFlags ${Section2} $0 - IntOp $1 $0 & 0x80 ; bit 7 set by upgrade, no need to copy files - IntCmp $1 1 DoneCD ; Upgrade doesn't need copy files - - IntOp $0 $0 & 1 - IntCmp $0 1 NoAbort - Abort -NoAbort: - - GetTempFileName $R0 - !insertmacro MUI_HEADER_TEXT "Locate TTD" "Setup needs the location of Transport Tycoon Deluxe in order to continue." - !insertmacro MUI_INSTALLOPTIONS_EXTRACT_AS "CDFinder.ini" "CDFinder" - - ClearErrors - ; Now, let's populate $CDDRIVE - ReadRegStr $R0 HKLM "SOFTWARE\Fish Technology Group\Transport Tycoon Deluxe" "HDPath" - IfErrors NoTTD - StrCmp $CDDRIVE "" 0 Populated - StrCpy $CDDRIVE $R0 -Populated: - StrCpy $AddWinPrePopulate "Setup has detected your TTD folder. Don't change the folder. Simply press Next." - Goto TruFinish -NoTTD: - StrCpy $AddWinPrePopulate "Setup couldn't find TTD. Please enter the path where the graphics files from TTD are stored and press Next to continue." -TruFinish: - ClearErrors - !insertmacro MUI_INSTALLOPTIONS_WRITE "CDFinder" "Field 2" "State" $CDDRIVE ; TTDLX path - !insertmacro MUI_INSTALLOPTIONS_WRITE "CDFinder" "Field 3" "Text" $AddWinPrePopulate ; Caption -DoneCD: - ; Initialize the dialog *AFTER* we've changed the text otherwise we won't see the changes - !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CDFinder" - !insertmacro MUI_INSTALLOPTIONS_SHOW -FunctionEnd - -;---------------------------------------------------------------- -; Custom page function when 'next' is selected for the TTDLX path -Function SelectCDExit - !insertmacro MUI_INSTALLOPTIONS_READ $CDDRIVE "CDFinder" "Field 2" "State" - ; If trg1r.grf does not exist at the path, retry with DOS version - IfFileExists $CDDRIVE\trg1r.grf "" DosCD - IfFileExists $CDDRIVE\trgir.grf "" NoCD - IfFileExists $CDDRIVE\sample.cat hasCD NoCD -DosCD: - IfFileExists $CDDRIVE\TRG1.GRF "" NoCD - IfFileExists $CDDRIVE\TRGI.GRF "" NoCD - IfFileExists $CDDRIVE\SAMPLE.CAT hasCD NoCD -NoCD: - MessageBox MB_OK "Setup cannot continue without the Transport Tycoon Deluxe Location!" - Abort -hasCD: -FunctionEnd - -;---------------------------------------------------------------------------------- -; Disable the "Back" button on finish page if the installer is run on Win9x systems -Function DisableBack - Call GetWindowsVersion - Pop $R0 - StrCmp $R0 "win9x" 0 WinNT - !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "Settings" "BackEnabled" "0" -WinNT: - ClearErrors -FunctionEnd - -;------------------------------------------------------------------------------- -; Determine windows version, returns "win9x" if Win9x/Me or "winnt" on the stack -Function GetWindowsVersion - ClearErrors - StrCpy $R0 "winnt" - - GetVersion::WindowsPlatformId - Pop $R0 - IntCmp $R0 2 WinNT 0 - StrCpy $R0 "win9x" -WinNT: - ClearErrors - Push $R0 -FunctionEnd - -;------------------------------------------------------------------------------- -; Check whether we're not running an installer for 64 bits on 32 bits and vice versa -Function CheckProcessorArchitecture - GetVersion::WindowsPlatformArchitecture - Pop $R0 - IntCmp $R0 64 Win64 0 - ClearErrors - IntCmp ${APPBITS} 64 0 Done - MessageBox MB_OKCANCEL|MB_ICONSTOP "You want to install the 64 bits OpenTTD on a 32 bits Operating System. This is not going to work. Please download the correct version. Do you really want to continue?" IDOK Done IDCANCEL Abort - GoTo Done -Win64: - ClearErrors - IntCmp ${APPBITS} 64 Done 0 - MessageBox MB_OKCANCEL|MB_ICONINFORMATION "You want to install the 32 bits OpenTTD on a 64 bits Operating System. This is not adviced, but will work with reduced capabilities. We suggest that you download the correct version. Do you really want to continue?" IDOK Done IDCANCEL Abort - GoTo Done -Abort: - Quit -Done: -FunctionEnd - - -;------------------------------------------------------------------------------- -; Check whether we're not running an installer for NT on 9x and vice versa -Function CheckWindowsVersion - Call GetWindowsVersion - Pop $R0 - StrCmp $R0 "win9x" 0 WinNT - ClearErrors - StrCmp ${APPARCH} "win9x" Done 0 - MessageBox MB_OKCANCEL|MB_ICONSTOP "You want to install the Windows 2000, XP and Vista version on Windows 95, 98 or ME. This is will not work. Please download the correct version. Do you really want to continue?" IDOK Done IDCANCEL Abort - GoTo Done -WinNT: - ClearErrors - StrCmp ${APPARCH} "win9x" 0 Done - MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "You want to install the Windows 95, 98 and ME version on Windows 2000, XP or Vista. This is not adviced, but will work with reduced capabilities. We suggest that you download the correct version. Do you really want to continue?" IDOK Done IDCANCEL Abort -Abort: - Quit -Done: -FunctionEnd - -Var OLDVERSION -Var UninstallString - -;----------------------------------------------------------------------------------- -; NSIS Initialize function, determine if we are going to install/upgrade or uninstall -Function .onInit - StrCpy $SHORTCUTS "OpenTTD" - - SectionSetSize ${Section3} 6144 - SectionSetSize ${Section4} 10240 - - SectionSetFlags 0 17 - - ; Starts Setup - let's look for an older version of OpenTTD - ReadRegDWORD $R8 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Version" - - IfErrors ShowWelcomeMessage ShowUpgradeMessage -ShowWelcomeMessage: - ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Version" - ; In the event someone still has OpenTTD 0.1, this will detect that (that installer used a string instead of dword entry) - IfErrors FinishCallback - -ShowUpgradeMessage: - IntCmp ${INSTALLERVERSION} $R8 VersionsAreEqual InstallerIsOlder WelcomeToSetup -WelcomeToSetup: - ; An older version was found. Let's let the user know there's an upgrade that will take place. - ReadRegStr $OLDVERSION HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayVersion" - ; Gets the older version then displays it in a message box - MessageBox MB_OK|MB_ICONINFORMATION \ - "Welcome to ${APPNAMEANDVERSION} Setup.$\n \ - This will allow you to upgrade from version $OLDVERSION." - SectionSetFlags ${Section2} 0x80 ; set bit 7 - SectionSetFlags ${Section3} 0x80 ; set bit 7 - SectionSetFlags ${Section4} 0x80 ; set bit 7 - Goto FinishCallback - -VersionsAreEqual: - ReadRegStr $UninstallString HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "UninstallString" - IfFileExists "$UninstallString" "" FinishCallback - MessageBox MB_YESNO|MB_ICONQUESTION \ - "Setup detected ${APPNAMEANDVERSION} on your system. That's the version this program will install.$\n \ - Are you trying to uninstall it?" \ - IDYES DoUninstall IDNO FinishCallback -DoUninstall: ; You have the same version as this installer. This allows you to uninstall. - Exec "$UninstallString" - Quit - -InstallerIsOlder: - MessageBox MB_OK|MB_ICONSTOP \ - "You have a newer version of ${APPNAME}.$\n \ - Setup will now exit." - Quit - -FinishCallback: - ClearErrors - Call CheckProcessorArchitecture - Call CheckWindowsVersion -FunctionEnd -; eof - diff --git a/os/win32/installer/top.bmp b/os/win32/installer/top.bmp deleted file mode 100644 index 15a170ec1..000000000 Binary files a/os/win32/installer/top.bmp and /dev/null differ diff --git a/os/win32/installer/version_win32.txt b/os/win32/installer/version_win32.txt deleted file mode 100644 index ed7f77e3d..000000000 --- a/os/win32/installer/version_win32.txt +++ /dev/null @@ -1,5 +0,0 @@ -!define APPBITS 32 ; Define number of bits for the architecture -!define EXTRA_VERSION "for Windows 2000, XP and Vista" -!define APPARCH "win32" ; Define the application architecture -!define BINARY_DIR "${PATH_ROOT}objs\win32\Release" -InstallDir "$PROGRAMFILES32\OpenTTD\" diff --git a/os/win32/installer/version_win64.txt b/os/win32/installer/version_win64.txt deleted file mode 100644 index 3c84447b6..000000000 --- a/os/win32/installer/version_win64.txt +++ /dev/null @@ -1,5 +0,0 @@ -!define APPBITS 64 ; Define number of bits for the architecture -!define EXTRA_VERSION "for Windows XP and Vista" -!define APPARCH "win64" ; Define the application architecture -!define BINARY_DIR "${PATH_ROOT}objs\x64\Release" -InstallDir "$PROGRAMFILES64\OpenTTD\" diff --git a/os/win32/installer/version_win9x.txt b/os/win32/installer/version_win9x.txt deleted file mode 100644 index be20888e5..000000000 --- a/os/win32/installer/version_win9x.txt +++ /dev/null @@ -1,5 +0,0 @@ -!define APPBITS 32 ; Define number of bits for the architecture -!define EXTRA_VERSION "for Windows 95, 98 and ME" -!define APPARCH "win9x" ; Define the application architecture -!define BINARY_DIR "${PATH_ROOT}bin" -InstallDir "$PROGRAMFILES32\OpenTTD\" diff --git a/os/win32/installer/welcome.bmp b/os/win32/installer/welcome.bmp deleted file mode 100644 index 8df4fa899..000000000 Binary files a/os/win32/installer/welcome.bmp and /dev/null differ diff --git a/os/windows/installer/build_installers.bat b/os/windows/installer/build_installers.bat new file mode 100644 index 000000000..73a2898da --- /dev/null +++ b/os/windows/installer/build_installers.bat @@ -0,0 +1,4 @@ +@echo off +"c:\Program Files\NSIS\makensis.exe" /DVERSION_INCLUDE=version_win9x.txt install.nsi > win9x.log +"c:\Program Files\NSIS\makensis.exe" /DVERSION_INCLUDE=version_win32.txt install.nsi > win32.log +"c:\Program Files\NSIS\makensis.exe" /DVERSION_INCLUDE=version_win64.txt install.nsi > win64.log diff --git a/os/windows/installer/cdfinder.ini b/os/windows/installer/cdfinder.ini new file mode 100644 index 000000000..45f9602f1 --- /dev/null +++ b/os/windows/installer/cdfinder.ini @@ -0,0 +1,26 @@ +; Ini file generated by the HM NIS Edit IO designer. +[Settings] +NumFields=3 + +[Field 1] +Type=Groupbox +Text=Transport Tycoon Deluxe Installation location +Left=6 +Right=294 +Top=68 +Bottom=100 + +[Field 2] +Type=DirRequest +Left=10 +Right=290 +Top=80 +Bottom=92 + +[Field 3] +Type=Label +Left=17 +Right=282 +Top=6 +Bottom=64 + diff --git a/os/windows/installer/install.nsi b/os/windows/installer/install.nsi new file mode 100644 index 000000000..69534505a --- /dev/null +++ b/os/windows/installer/install.nsi @@ -0,0 +1,546 @@ +!define APPNAME "OpenTTD" ; Define application name +!define APPVERSION "0.8.0" ; Define application version +!define APPVERSIONINTERNAL "0.8.0.0" ; Define application version in X.X.X.X +!define INSTALLERVERSION 65 ; NEED TO UPDATE THIS FOR EVERY RELEASE!!! +!include ${VERSION_INCLUDE} + +!define APPURLLINK "http://www.openttd.org" +!define APPNAMEANDVERSION "${APPNAME} ${APPVERSION}" + +!define OPENGFX_BASE_VERSION "0.7.0" +!define OPENSFX_BASE_VERSION "0.8.0" + +!define MUI_ICON "..\..\..\media\openttd.ico" +!define MUI_UNICON "..\..\..\media\openttd.ico" +!define MUI_WELCOMEFINISHPAGE_BITMAP "welcome.bmp" +!define MUI_HEADERIMAGE +!define MUI_HEADERIMAGE_BITMAP "top.bmp" + +BrandingText "OpenTTD Installer" +SetCompressor LZMA + +; Version Info +Var AddWinPrePopulate +VIProductVersion "${APPVERSIONINTERNAL}" +VIAddVersionKey "ProductName" "OpenTTD Installer ${APPBITS} bits version ${EXTRA_VERSION}" +VIAddVersionKey "Comments" "Installs ${APPNAMEANDVERSION}" +VIAddVersionKey "CompanyName" "OpenTTD Developers" +VIAddVersionKey "FileDescription" "Installs ${APPNAMEANDVERSION}" +VIAddVersionKey "ProductVersion" "${APPVERSION}" +VIAddVersionKey "InternalName" "InstOpenTTD-${APPARCH}" +VIAddVersionKey "FileVersion" "${APPVERSION}-${APPARCH}" +VIAddVersionKey "LegalCopyright" " " +; Main Install settings +Name "${APPNAMEANDVERSION} ${APPBITS} bits version ${EXTRA_VERSION}" + +; NOTE: Keep trailing backslash! +InstallDirRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Install Folder" +OutFile "openttd-${APPVERSION}-${APPARCH}.exe" +CRCCheck force + +ShowInstDetails show +ShowUninstDetails show + +Var SHORTCUTS +Var CDDRIVE + +; Modern interface settings +!include "MUI.nsh" + +!define MUI_ABORTWARNING +!define MUI_WELCOMEPAGE_TITLE_3LINES +!insertmacro MUI_PAGE_WELCOME + +!define MUI_LICENSEPAGE_RADIOBUTTONS +!insertmacro MUI_DEFAULT MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_ACCEPT "I &accept this agreement" +!insertmacro MUI_DEFAULT MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_DECLINE "I &do not accept this agreement" +!insertmacro MUI_PAGE_LICENSE "..\..\..\COPYING" + +!insertmacro MUI_PAGE_COMPONENTS + +;--------------------------------- +; Custom page for finding TTDLX CD +Page custom SelectCDEnter SelectCDExit ": TTD folder" + +!insertmacro MUI_PAGE_DIRECTORY + +;Start Menu Folder Page Configuration +!define MUI_STARTMENUPAGE_DEFAULTFOLDER $SHORTCUTS +!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKEY_LOCAL_MACHINE" +!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" +!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Shortcut Folder" + +!insertmacro MUI_PAGE_STARTMENU "OpenTTD" $SHORTCUTS + +!insertmacro MUI_PAGE_INSTFILES + +!define MUI_FINISHPAGE_TITLE_3LINES +!define MUI_FINISHPAGE_RUN_TEXT "Run ${APPNAMEANDVERSION} now!" +!define MUI_FINISHPAGE_RUN "$INSTDIR\openttd.exe" +!define MUI_FINISHPAGE_LINK "Visit the OpenTTD site for latest news, FAQs and downloads" +!define MUI_FINISHPAGE_LINK_LOCATION "${APPURLLINK}" +!define MUI_FINISHPAGE_NOREBOOTSUPPORT +!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\readme.txt" +!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED +!define MUI_WELCOMEFINISHPAGE_CUSTOMFUNCTION_INIT DisableBack + +!insertmacro MUI_PAGE_FINISH +!define MUI_PAGE_HEADER_TEXT "Uninstall ${APPNAMEANDVERSION}" +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +; Set languages (first is default language) +!insertmacro MUI_LANGUAGE "English" +!insertmacro MUI_RESERVEFILE_LANGDLL + +;-------------------------------------------------------------- +; (Core) OpenTTD install section. Copies all internal game data +Section "!OpenTTD" Section1 + ; Overwrite files by default, but don't complain on failure + SetOverwrite try + + ; Define root variable relative to installer + !define PATH_ROOT "..\..\..\" + + ; Copy language files + SetOutPath "$INSTDIR\lang\" + File ${PATH_ROOT}bin\lang\*.lng + + ; Copy AI files + SetOutPath "$INSTDIR\ai\" + File ${PATH_ROOT}bin\ai\compat_*.nut + + ; Copy data files + SetOutPath "$INSTDIR\data\" + File ${PATH_ROOT}bin\data\*.grf + File ${PATH_ROOT}bin\data\*.obg + File ${PATH_ROOT}bin\data\*.obs + File ${PATH_ROOT}bin\data\opntitle.dat + + ; Copy the scripts + SetOutPath "$INSTDIR\scripts\" + File ${PATH_ROOT}bin\scripts\*.* + + ; Copy the rest of the stuff + SetOutPath "$INSTDIR\" + + ; Copy text files + File ${PATH_ROOT}changelog.txt + File ${PATH_ROOT}COPYING + File ${PATH_ROOT}readme.txt + File ${PATH_ROOT}known-bugs.txt + + ; Copy executable + File /oname=openttd.exe ${BINARY_DIR}\openttd.exe + + + ; Delete old files from the main dir. they are now placed in data/ and lang/ + Delete "$INSTDIR\*.lng" + Delete "$INSTDIR\*.grf" + Delete "$INSTDIR\sample.cat" + Delete "$INSTDIR\ttd.exe" + + + ; Create the Registry Entries + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Comments" "Visit ${APPURLLINK}" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayIcon" "$INSTDIR\openttd.exe,0" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayName" "OpenTTD ${APPVERSION}" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayVersion" "${APPVERSION}" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "HelpLink" "${APPURLLINK}" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Install Folder" "$INSTDIR" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Publisher" "OpenTTD" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Shortcut Folder" "$SHORTCUTS" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "UninstallString" "$INSTDIR\uninstall.exe" + WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "URLInfoAbout" "${APPURLLINK}" + ; This key sets the Version DWORD that new installers will check against + WriteRegDWORD HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Version" ${INSTALLERVERSION} + + !insertmacro MUI_STARTMENU_WRITE_BEGIN "OpenTTD" + CreateShortCut "$DESKTOP\OpenTTD.lnk" "$INSTDIR\openttd.exe" + CreateDirectory "$SMPROGRAMS\$SHORTCUTS" + CreateShortCut "$SMPROGRAMS\$SHORTCUTS\OpenTTD.lnk" "$INSTDIR\openttd.exe" + CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Uninstall.lnk" "$INSTDIR\uninstall.exe" + CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Readme.lnk" "$INSTDIR\Readme.txt" + CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Changelog.lnk" "$INSTDIR\Changelog.txt" + CreateShortCut "$SMPROGRAMS\$SHORTCUTS\Known-bugs.lnk" "$INSTDIR\known-bugs.txt" + !insertmacro MUI_STARTMENU_WRITE_END +SectionEnd + +;---------------------------------------------------------------------------------- +; OpenGFX files install section. Downloads OpenGFX and installs it +Section "Download free Graphics" Section3 + SetOverwrite try + + NSISdl::download "http://binaries.openttd.org/installer/opengfx-${OPENGFX_BASE_VERSION}.tar.7z" "$INSTDIR\data\opengfx.tar.7z" + Pop $R0 ;Get the return value + StrCmp $R0 "success" +3 + MessageBox MB_OK "Downloading of OpenGFX failed" + Goto Done + + ; Let's extract the files + SetOutPath "$INSTDIR\data\" + NSIS7z::Extract "$INSTDIR\data\opengfx.tar.7z" + + Delete "$INSTDIR\data\opengfx.tar.7z" + SetOutPath "$INSTDIR\" +Done: + +SectionEnd + +;---------------------------------------------------------------------------------- +; OpenSFX files install section. Downloads OpenSFX and installs it +Section "Download free Sounds" Section4 + SetOverwrite try + + NSISdl::download "http://binaries.openttd.org/installer/opensfx-${OPENSFX_BASE_VERSION}.tar.7z" "$INSTDIR\data\opensfx.tar.7z" + Pop $R0 ;Get the return value + StrCmp $R0 "success" +3 + MessageBox MB_OK "Downloading of OpenSFX failed" + Goto Done + + ; Let's extract the files + SetOutPath "$INSTDIR\data\" + NSIS7z::Extract "$INSTDIR\data\opensfx.tar.7z" + + Delete "$INSTDIR\data\opensfx.tar.7z" + SetOutPath "$INSTDIR\" +Done: + +SectionEnd + +;---------------------------------------------------------------------------------- +; TTDLX files install section. Copies all needed TTDLX files from CD or install dir +Section /o "Copy Game Graphics" Section2 + SetOverwrite try + ; Let's copy the files with size approximation + SetOutPath "$INSTDIR\gm" + CopyFiles "$CDDRIVE\gm\*.gm" "$INSTDIR\gm\" 1028 + SetOutPath "$INSTDIR\data\" + CopyFiles "$CDDRIVE\sample.cat" "$INSTDIR\data\sample.cat" 1566 + ; Copy Windows files + CopyFiles "$CDDRIVE\trg1r.grf" "$INSTDIR\data\trg1r.grf" 2365 + CopyFiles "$CDDRIVE\trgcr.grf" "$INSTDIR\data\trgcr.grf" 260 + CopyFiles "$CDDRIVE\trghr.grf" "$INSTDIR\data\trghr.grf" 400 + CopyFiles "$CDDRIVE\trgir.grf" "$INSTDIR\data\trgir.grf" 334 + CopyFiles "$CDDRIVE\trgtr.grf" "$INSTDIR\data\trgtr.grf" 546 + ; Copy DOS files + CopyFiles "$CDDRIVE\trg1.grf" "$INSTDIR\data\trg1.grf" 2365 + CopyFiles "$CDDRIVE\trgc.grf" "$INSTDIR\data\trgc.grf" 260 + CopyFiles "$CDDRIVE\trgh.grf" "$INSTDIR\data\trgh.grf" 400 + CopyFiles "$CDDRIVE\trgi.grf" "$INSTDIR\data\trgi.grf" 334 + CopyFiles "$CDDRIVE\trgt.grf" "$INSTDIR\data\trgt.grf" 546 + SetOutPath "$INSTDIR\" +SectionEnd + +;------------------------------------------- +; Install the uninstaller (option is hidden) +Section -FinishSection + WriteUninstaller "$INSTDIR\uninstall.exe" +SectionEnd + +; Modern install component descriptions +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${Section1} "OpenTTD is a fully functional clone of Transport Tycoon Deluxe and is very playable. You need at least one of the game graphics and sound sets installed" + !insertmacro MUI_DESCRIPTION_TEXT ${Section3} "Download the free OpenGFX game graphics. This download is about 3 MiB." + !insertmacro MUI_DESCRIPTION_TEXT ${Section4} "Download the free OpenSFX game sounds. This download is about 7 MiB." + !insertmacro MUI_DESCRIPTION_TEXT ${Section2} "Copies the game graphics and sounds from the Transport Tycoon Deluxe CD." +!insertmacro MUI_FUNCTION_DESCRIPTION_END + +;----------------------------------------------- +; Uninstall section, deletes all installed files +Section "Uninstall" + MessageBox MB_YESNO|MB_ICONQUESTION \ + "Remove the save game folders located at $\"$INSTDIR\save?$\"$\n \ + If you choose Yes, your saved games will be deleted." \ + IDYES RemoveSavedGames IDNO NoRemoveSavedGames + RemoveSavedGames: + Delete "$INSTDIR\save\autosave\*" + RMDir "$INSTDIR\save\autosave" + Delete "$INSTDIR\save\*" + RMDir "$INSTDIR\save" + NoRemoveSavedGames: + + MessageBox MB_YESNO|MB_ICONQUESTION \ + "Remove the scenario folders located at $\"$INSTDIR\scenario?$\"$\n \ + If you choose Yes, your scenarios will be deleted." \ + IDYES RemoveScen IDNO NoRemoveScen + RemoveScen: + Delete "$INSTDIR\scenario\heightmap*" + RMDir "$INSTDIR\scenario\heightmap" + Delete "$INSTDIR\scenario\*" + RMDir "$INSTDIR\scenario" + NoRemoveScen: + + ; Remove from registry... + !insertmacro MUI_STARTMENU_GETFOLDER "OpenTTD" $SHORTCUTS + ReadRegStr $SHORTCUTS HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Shortcut Folder" + + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" + + ; Delete self + Delete "$INSTDIR\uninstall.exe" + + ; Delete Shortcuts + Delete "$DESKTOP\OpenTTD.lnk" + Delete "$SMPROGRAMS\$SHORTCUTS\OpenTTD.lnk" + Delete "$SMPROGRAMS\$SHORTCUTS\Uninstall.lnk" + Delete "$SMPROGRAMS\$SHORTCUTS\Readme.lnk" + Delete "$SMPROGRAMS\$SHORTCUTS\Changelog.lnk" + Delete "$SMPROGRAMS\$SHORTCUTS\Known-bugs.lnk" + + ; Clean up OpenTTD dir + Delete "$INSTDIR\changelog.txt" + Delete "$INSTDIR\readme.txt" + Delete "$INSTDIR\known-bugs.txt" + Delete "$INSTDIR\openttd.exe" + Delete "$INSTDIR\COPYING" + Delete "$INSTDIR\INSTALL.LOG" + Delete "$INSTDIR\crash.log" + Delete "$INSTDIR\crash.dmp" + Delete "$INSTDIR\openttd.cfg" + Delete "$INSTDIR\hs.dat" + Delete "$INSTDIR\cached_sprites.*" + Delete "$INSTDIR\save\autosave\network*.tmp" ; temporary network file + + ; AI files + Delete "$INSTDIR\ai\compat_*.nut" + + ; Data files + Delete "$INSTDIR\data\opntitle.dat" + + Delete "$INSTDIR\data\2ccmap.grf" + Delete "$INSTDIR\data\airports.grf" + Delete "$INSTDIR\data\autorail.grf" + Delete "$INSTDIR\data\canalsw.grf" + Delete "$INSTDIR\data\dosdummy.grf" + Delete "$INSTDIR\data\elrailsw.grf" + Delete "$INSTDIR\data\nsignalsw.grf" + Delete "$INSTDIR\data\openttd.grf" + Delete "$INSTDIR\data\roadstops.grf" + Delete "$INSTDIR\data\trkfoundw.grf" + Delete "$INSTDIR\data\openttdd.grf" + Delete "$INSTDIR\data\openttdw.grf" + Delete "$INSTDIR\data\orig_win.obg" + Delete "$INSTDIR\data\orig_dos.obg" + Delete "$INSTDIR\data\orig_dos_de.obg" + Delete "$INSTDIR\data\orig_win.obs" + Delete "$INSTDIR\data\orig_dos.obs" + + Delete "$INSTDIR\data\sample.cat" + ; Windows Data files + Delete "$INSTDIR\data\trg1r.grf" + Delete "$INSTDIR\data\trghr.grf" + Delete "$INSTDIR\data\trgtr.grf" + Delete "$INSTDIR\data\trgcr.grf" + Delete "$INSTDIR\data\trgir.grf" + ; Dos Data files + Delete "$INSTDIR\data\trg1.grf" + Delete "$INSTDIR\data\trgh.grf" + Delete "$INSTDIR\data\trgt.grf" + Delete "$INSTDIR\data\trgc.grf" + Delete "$INSTDIR\data\trgi.grf" + + ; Music + Delete "$INSTDIR\gm\*.gm" + + ; Downloaded OpenGFX/OpenSFX + Delete "$INSTDIR\data\opengfx.tar" + Delete "$INSTDIR\data\opensfx.tar" + + ; Language files + Delete "$INSTDIR\lang\*.lng" + + ; Scripts + Delete "$INSTDIR\scripts\*.*" + + ; Remove remaining directories + RMDir "$SMPROGRAMS\$SHORTCUTS\Extras\" + RMDir "$SMPROGRAMS\$SHORTCUTS" + RMDir "$INSTDIR\gm" + RMDir "$INSTDIR\lang" + RMDir "$INSTDIR\data" + RMDir "$INSTDIR" + +SectionEnd + +;------------------------------------------------------------ +; Custom page function to find the TTDLX CD/install location +Function SelectCDEnter + SectionGetFlags ${Section2} $0 + IntOp $1 $0 & 0x80 ; bit 7 set by upgrade, no need to copy files + IntCmp $1 1 DoneCD ; Upgrade doesn't need copy files + + IntOp $0 $0 & 1 + IntCmp $0 1 NoAbort + Abort +NoAbort: + + GetTempFileName $R0 + !insertmacro MUI_HEADER_TEXT "Locate TTD" "Setup needs the location of Transport Tycoon Deluxe in order to continue." + !insertmacro MUI_INSTALLOPTIONS_EXTRACT_AS "CDFinder.ini" "CDFinder" + + ClearErrors + ; Now, let's populate $CDDRIVE + ReadRegStr $R0 HKLM "SOFTWARE\Fish Technology Group\Transport Tycoon Deluxe" "HDPath" + IfErrors NoTTD + StrCmp $CDDRIVE "" 0 Populated + StrCpy $CDDRIVE $R0 +Populated: + StrCpy $AddWinPrePopulate "Setup has detected your TTD folder. Don't change the folder. Simply press Next." + Goto TruFinish +NoTTD: + StrCpy $AddWinPrePopulate "Setup couldn't find TTD. Please enter the path where the graphics files from TTD are stored and press Next to continue." +TruFinish: + ClearErrors + !insertmacro MUI_INSTALLOPTIONS_WRITE "CDFinder" "Field 2" "State" $CDDRIVE ; TTDLX path + !insertmacro MUI_INSTALLOPTIONS_WRITE "CDFinder" "Field 3" "Text" $AddWinPrePopulate ; Caption +DoneCD: + ; Initialize the dialog *AFTER* we've changed the text otherwise we won't see the changes + !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "CDFinder" + !insertmacro MUI_INSTALLOPTIONS_SHOW +FunctionEnd + +;---------------------------------------------------------------- +; Custom page function when 'next' is selected for the TTDLX path +Function SelectCDExit + !insertmacro MUI_INSTALLOPTIONS_READ $CDDRIVE "CDFinder" "Field 2" "State" + ; If trg1r.grf does not exist at the path, retry with DOS version + IfFileExists $CDDRIVE\trg1r.grf "" DosCD + IfFileExists $CDDRIVE\trgir.grf "" NoCD + IfFileExists $CDDRIVE\sample.cat hasCD NoCD +DosCD: + IfFileExists $CDDRIVE\TRG1.GRF "" NoCD + IfFileExists $CDDRIVE\TRGI.GRF "" NoCD + IfFileExists $CDDRIVE\SAMPLE.CAT hasCD NoCD +NoCD: + MessageBox MB_OK "Setup cannot continue without the Transport Tycoon Deluxe Location!" + Abort +hasCD: +FunctionEnd + +;---------------------------------------------------------------------------------- +; Disable the "Back" button on finish page if the installer is run on Win9x systems +Function DisableBack + Call GetWindowsVersion + Pop $R0 + StrCmp $R0 "win9x" 0 WinNT + !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "Settings" "BackEnabled" "0" +WinNT: + ClearErrors +FunctionEnd + +;------------------------------------------------------------------------------- +; Determine windows version, returns "win9x" if Win9x/Me or "winnt" on the stack +Function GetWindowsVersion + ClearErrors + StrCpy $R0 "winnt" + + GetVersion::WindowsPlatformId + Pop $R0 + IntCmp $R0 2 WinNT 0 + StrCpy $R0 "win9x" +WinNT: + ClearErrors + Push $R0 +FunctionEnd + +;------------------------------------------------------------------------------- +; Check whether we're not running an installer for 64 bits on 32 bits and vice versa +Function CheckProcessorArchitecture + GetVersion::WindowsPlatformArchitecture + Pop $R0 + IntCmp $R0 64 Win64 0 + ClearErrors + IntCmp ${APPBITS} 64 0 Done + MessageBox MB_OKCANCEL|MB_ICONSTOP "You want to install the 64 bits OpenTTD on a 32 bits Operating System. This is not going to work. Please download the correct version. Do you really want to continue?" IDOK Done IDCANCEL Abort + GoTo Done +Win64: + ClearErrors + IntCmp ${APPBITS} 64 Done 0 + MessageBox MB_OKCANCEL|MB_ICONINFORMATION "You want to install the 32 bits OpenTTD on a 64 bits Operating System. This is not adviced, but will work with reduced capabilities. We suggest that you download the correct version. Do you really want to continue?" IDOK Done IDCANCEL Abort + GoTo Done +Abort: + Quit +Done: +FunctionEnd + + +;------------------------------------------------------------------------------- +; Check whether we're not running an installer for NT on 9x and vice versa +Function CheckWindowsVersion + Call GetWindowsVersion + Pop $R0 + StrCmp $R0 "win9x" 0 WinNT + ClearErrors + StrCmp ${APPARCH} "win9x" Done 0 + MessageBox MB_OKCANCEL|MB_ICONSTOP "You want to install the Windows 2000, XP and Vista version on Windows 95, 98 or ME. This is will not work. Please download the correct version. Do you really want to continue?" IDOK Done IDCANCEL Abort + GoTo Done +WinNT: + ClearErrors + StrCmp ${APPARCH} "win9x" 0 Done + MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "You want to install the Windows 95, 98 and ME version on Windows 2000, XP or Vista. This is not adviced, but will work with reduced capabilities. We suggest that you download the correct version. Do you really want to continue?" IDOK Done IDCANCEL Abort +Abort: + Quit +Done: +FunctionEnd + +Var OLDVERSION +Var UninstallString + +;----------------------------------------------------------------------------------- +; NSIS Initialize function, determine if we are going to install/upgrade or uninstall +Function .onInit + StrCpy $SHORTCUTS "OpenTTD" + + SectionSetSize ${Section3} 6144 + SectionSetSize ${Section4} 10240 + + SectionSetFlags 0 17 + + ; Starts Setup - let's look for an older version of OpenTTD + ReadRegDWORD $R8 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Version" + + IfErrors ShowWelcomeMessage ShowUpgradeMessage +ShowWelcomeMessage: + ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "Version" + ; In the event someone still has OpenTTD 0.1, this will detect that (that installer used a string instead of dword entry) + IfErrors FinishCallback + +ShowUpgradeMessage: + IntCmp ${INSTALLERVERSION} $R8 VersionsAreEqual InstallerIsOlder WelcomeToSetup +WelcomeToSetup: + ; An older version was found. Let's let the user know there's an upgrade that will take place. + ReadRegStr $OLDVERSION HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "DisplayVersion" + ; Gets the older version then displays it in a message box + MessageBox MB_OK|MB_ICONINFORMATION \ + "Welcome to ${APPNAMEANDVERSION} Setup.$\n \ + This will allow you to upgrade from version $OLDVERSION." + SectionSetFlags ${Section2} 0x80 ; set bit 7 + SectionSetFlags ${Section3} 0x80 ; set bit 7 + SectionSetFlags ${Section4} 0x80 ; set bit 7 + Goto FinishCallback + +VersionsAreEqual: + ReadRegStr $UninstallString HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenTTD" "UninstallString" + IfFileExists "$UninstallString" "" FinishCallback + MessageBox MB_YESNO|MB_ICONQUESTION \ + "Setup detected ${APPNAMEANDVERSION} on your system. That's the version this program will install.$\n \ + Are you trying to uninstall it?" \ + IDYES DoUninstall IDNO FinishCallback +DoUninstall: ; You have the same version as this installer. This allows you to uninstall. + Exec "$UninstallString" + Quit + +InstallerIsOlder: + MessageBox MB_OK|MB_ICONSTOP \ + "You have a newer version of ${APPNAME}.$\n \ + Setup will now exit." + Quit + +FinishCallback: + ClearErrors + Call CheckProcessorArchitecture + Call CheckWindowsVersion +FunctionEnd +; eof + diff --git a/os/windows/installer/top.bmp b/os/windows/installer/top.bmp new file mode 100644 index 000000000..15a170ec1 Binary files /dev/null and b/os/windows/installer/top.bmp differ diff --git a/os/windows/installer/version_win32.txt b/os/windows/installer/version_win32.txt new file mode 100644 index 000000000..ed7f77e3d --- /dev/null +++ b/os/windows/installer/version_win32.txt @@ -0,0 +1,5 @@ +!define APPBITS 32 ; Define number of bits for the architecture +!define EXTRA_VERSION "for Windows 2000, XP and Vista" +!define APPARCH "win32" ; Define the application architecture +!define BINARY_DIR "${PATH_ROOT}objs\win32\Release" +InstallDir "$PROGRAMFILES32\OpenTTD\" diff --git a/os/windows/installer/version_win64.txt b/os/windows/installer/version_win64.txt new file mode 100644 index 000000000..3c84447b6 --- /dev/null +++ b/os/windows/installer/version_win64.txt @@ -0,0 +1,5 @@ +!define APPBITS 64 ; Define number of bits for the architecture +!define EXTRA_VERSION "for Windows XP and Vista" +!define APPARCH "win64" ; Define the application architecture +!define BINARY_DIR "${PATH_ROOT}objs\x64\Release" +InstallDir "$PROGRAMFILES64\OpenTTD\" diff --git a/os/windows/installer/version_win9x.txt b/os/windows/installer/version_win9x.txt new file mode 100644 index 000000000..be20888e5 --- /dev/null +++ b/os/windows/installer/version_win9x.txt @@ -0,0 +1,5 @@ +!define APPBITS 32 ; Define number of bits for the architecture +!define EXTRA_VERSION "for Windows 95, 98 and ME" +!define APPARCH "win9x" ; Define the application architecture +!define BINARY_DIR "${PATH_ROOT}bin" +InstallDir "$PROGRAMFILES32\OpenTTD\" diff --git a/os/windows/installer/welcome.bmp b/os/windows/installer/welcome.bmp new file mode 100644 index 000000000..8df4fa899 Binary files /dev/null and b/os/windows/installer/welcome.bmp differ diff --git a/projects/determineversion.vbs b/projects/determineversion.vbs index 7104b833a..1c6f48552 100755 --- a/projects/determineversion.vbs +++ b/projects/determineversion.vbs @@ -44,7 +44,7 @@ Sub UpdateFiles(version) End If UpdateFile modified, revision, version, cur_date, "../src/rev.cpp" - UpdateFile modified, revision, version, cur_date, "../src/ottdres.rc" + UpdateFile modified, revision, version, cur_date, "../src/os/windows/ottdres.rc" End Sub Function ReadRegistryKey(shive, subkey, valuename, architecture) @@ -286,6 +286,6 @@ End Function Dim version version = DetermineSVNVersion -If Not (IsCachedVersion(version) And CheckFile("../src/rev.cpp") And CheckFile("../src/ottdres.rc")) Then +If Not (IsCachedVersion(version) And CheckFile("../src/rev.cpp") And CheckFile("../src/os/windows/ottdres.rc")) Then UpdateFiles version End If diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 9e868d5f6..566353e7b 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -16,7 +16,7 @@ @@ -652,7 +652,7 @@ > @@ -458,7 +458,7 @@ Filter="asm" > @@ -649,7 +649,7 @@ > @@ -455,7 +455,7 @@ Filter="asm" > #include /* SHGetFolderPath */ -#include "win32.h" +#include "os/windows/win32.h" /** * Get the short DOS 8.3 format for paths. diff --git a/src/masm64.rules b/src/masm64.rules deleted file mode 100644 index 62e6e0f8b..000000000 --- a/src/masm64.rules +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/music/dmusic.cpp b/src/music/dmusic.cpp index 5042571ad..988884b8f 100644 --- a/src/music/dmusic.cpp +++ b/src/music/dmusic.cpp @@ -16,7 +16,7 @@ #undef WIN32_LEAN_AND_MEAN // Don't exclude rarely-used stuff from Windows headers #endif #include "../debug.h" -#include "../win32.h" +#include "../os/windows/win32.h" #include "dmusic.h" #include diff --git a/src/os/os2/os2.cpp b/src/os/os2/os2.cpp new file mode 100644 index 000000000..06508b361 --- /dev/null +++ b/src/os/os2/os2.cpp @@ -0,0 +1,243 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file os2.cpp OS2 related OS support. */ + +#include "../../stdafx.h" +#include "../../openttd.h" +#include "../../variables.h" +#include "../../gui.h" +#include "../../fileio_func.h" +#include "../../fios.h" +#include "../../functions.h" +#include "../../core/random_func.hpp" +#include "../../string_func.h" +#include "../../textbuf_gui.h" + +#include "table/strings.h" + +#include +#include +#include +#include +#include +#ifndef __INNOTEK_LIBC__ + #include +#endif + +#define INCL_WIN +#define INCL_WINCLIPBOARD + +#include +#ifndef __INNOTEK_LIBC__ + #include +#endif + +bool FiosIsRoot(const char *file) +{ + return file[3] == '\0'; +} + +void FiosGetDrives() +{ + uint disk, disk2, save, total; + +#ifndef __INNOTEK_LIBC__ + _dos_getdrive(&save); // save original drive +#else + save = _getdrive(); // save original drive + char wd[MAX_PATH]; + getcwd(wd, MAX_PATH); + total = 'z'; +#endif + + /* get an available drive letter */ +#ifndef __INNOTEK_LIBC__ + for (disk = 1;; disk++) { + _dos_setdrive(disk, &total); +#else + for (disk = 'A';; disk++) { + _chdrive(disk); +#endif + if (disk >= total) break; + +#ifndef __INNOTEK_LIBC__ + _dos_getdrive(&disk2); +#else + disk2 = _getdrive(); +#endif + + if (disk == disk2) { + FiosItem *fios = _fios_items.Append(); + fios->type = FIOS_TYPE_DRIVE; + fios->mtime = 0; +#ifndef __INNOTEK_LIBC__ + snprintf(fios->name, lengthof(fios->name), "%c:", 'A' + disk - 1); +#else + snprintf(fios->name, lengthof(fios->name), "%c:", disk); +#endif + strecpy(fios->title, fios->name, lastof(fios->title)); + } + } + + /* Restore the original drive */ +#ifndef __INNOTEK_LIBC__ + _dos_setdrive(save, &total); +#else + chdir(wd); +#endif +} + +bool FiosGetDiskFreeSpace(const char *path, uint64 *tot) +{ +#ifndef __INNOTEK_LIBC__ + struct diskfree_t free; + char drive = path[0] - 'A' + 1; + + if (tot != NULL && _getdiskfree(drive, &free) == 0) { + *tot = free.avail_clusters * free.sectors_per_cluster * free.bytes_per_sector; + return true; + } + + return false; +#else + uint64 free = 0; + +#ifdef HAS_STATVFS + { + struct statvfs s; + + if (statvfs(path, &s) != 0) return false; + free = (uint64)s.f_frsize * s.f_bavail; + } +#endif + if (tot != NULL) *tot = free; + return true; +#endif +} + +bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) +{ + char filename[MAX_PATH]; + + snprintf(filename, lengthof(filename), "%s" PATHSEP "%s", path, ent->d_name); + return stat(filename, sb) == 0; +} + +bool FiosIsHiddenFile(const struct dirent *ent) +{ + return ent->d_name[0] == '.'; +} + +void ShowInfo(const char *str) +{ + HAB hab; + HMQ hmq; + ULONG rc; + + /* init PM env. */ + hmq = WinCreateMsgQueue((hab = WinInitialize(0)), 0); + + /* display the box */ + rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, (const unsigned char *)str, (const unsigned char *)"OpenTTD", 0, MB_OK | MB_MOVEABLE | MB_INFORMATION); + + /* terminate PM env. */ + WinDestroyMsgQueue(hmq); + WinTerminate(hab); +} + +void ShowOSErrorBox(const char *buf, bool system) +{ + HAB hab; + HMQ hmq; + ULONG rc; + + /* init PM env. */ + hmq = WinCreateMsgQueue((hab = WinInitialize(0)), 0); + + /* display the box */ + rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, (const unsigned char *)buf, (const unsigned char *)"OpenTTD", 0, MB_OK | MB_MOVEABLE | MB_ERROR); + + /* terminate PM env. */ + WinDestroyMsgQueue(hmq); + WinTerminate(hab); +} + +int CDECL main(int argc, char *argv[]) +{ + SetRandomSeed(time(NULL)); + + return ttd_main(argc, argv); +} + +/** + * Insert a chunk of text from the clipboard onto the textbuffer. Get TEXT clipboard + * and append this up to the maximum length (either absolute or screenlength). If maxlength + * is zero, we don't care about the screenlength but only about the physical length of the string + * @param tb Textbuf type to be changed + * @return Return true on successful change of Textbuf, or false otherwise + */ +bool InsertTextBufferClipboard(Textbuf *tb) +{ +/* XXX -- Currently no clipboard support implemented with GCC */ +#ifndef __INNOTEK_LIBC__ + HAB hab = 0; + + if (WinOpenClipbrd(hab)) + { + const char *text = (const char*)WinQueryClipbrdData(hab, CF_TEXT); + + if (text != NULL) + { + uint length = 0; + uint width = 0; + const char *i; + + for (i = text; IsValidAsciiChar(*i); i++) + { + uint w; + + if (tb->size + length + 1 > tb->maxsize) break; + + w = GetCharacterWidth(FS_NORMAL, (byte)*i); + if (tb->maxwidth != 0 && width + tb->width + w > tb->maxwidth) break; + + width += w; + length++; + } + + memmove(tb->buf + tb->caretpos + length, tb->buf + tb->caretpos, tb->size - tb->caretpos); + memcpy(tb->buf + tb->caretpos, text, length); + tb->width += width; + tb->caretxoffs += width; + tb->size += length; + tb->caretpos += length; + + WinCloseClipbrd(hab); + return true; + } + + WinCloseClipbrd(hab); + } +#endif + return false; +} + + +void CSleep(int milliseconds) +{ +#ifndef __INNOTEK_LIBC__ + delay(milliseconds); +#else + usleep(milliseconds * 1000); +#endif +} + +const char *FS2OTTD(const char *name) {return name;} +const char *OTTD2FS(const char *name) {return name;} diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp new file mode 100644 index 000000000..bbe916c57 --- /dev/null +++ b/src/os/unix/unix.cpp @@ -0,0 +1,314 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file unix.cpp Implementation of Unix specific file handling. */ + +#include "../../stdafx.h" +#include "../../openttd.h" +#include "../../variables.h" +#include "../../textbuf_gui.h" +#include "../../functions.h" +#include "../../core/random_func.hpp" + +#include "table/strings.h" + +#include +#include +#include +#include +#include + +#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__) + #define HAS_STATVFS +#endif + +#ifdef HAS_STATVFS +#include +#endif + + +#ifdef __MORPHOS__ +#include +ULONG __stack = (1024*1024)*2; // maybe not that much is needed actually ;) + +/* The system supplied definition of SIG_IGN does not match */ +#undef SIG_IGN +#define SIG_IGN (void (*)(int))1 +#endif /* __MORPHOS__ */ + +#ifdef __AMIGA__ +#warning add stack symbol to avoid that user needs to set stack manually (tokai) +// ULONG __stack = +#endif + +#if defined(__APPLE__) + #if defined(WITH_SDL) + /* the mac implementation needs this file included in the same file as main() */ + #include + #endif +#endif + +bool FiosIsRoot(const char *path) +{ +#if !defined(__MORPHOS__) && !defined(__AMIGAOS__) + return path[1] == '\0'; +#else + /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */ + const char *s = strchr(path, ':'); + return s != NULL && s[1] == '\0'; +#endif +} + +void FiosGetDrives() +{ + return; +} + +bool FiosGetDiskFreeSpace(const char *path, uint64 *tot) +{ + uint64 free = 0; + +#ifdef HAS_STATVFS +# ifdef __APPLE__ + /* OSX 10.3 lacks statvfs so don't try to use it even though later versions of OSX has it. */ + if (MacOSVersionIsAtLeast(10, 4, 0)) +# endif + { + struct statvfs s; + + if (statvfs(path, &s) != 0) return false; + free = (uint64)s.f_frsize * s.f_bavail; + } +#endif + if (tot != NULL) *tot = free; + return true; +} + +bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) +{ + char filename[MAX_PATH]; + +#if defined(__MORPHOS__) || defined(__AMIGAOS__) + /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */ + if (FiosIsRoot(path)) { + snprintf(filename, lengthof(filename), "%s:%s", path, ent->d_name); + } else // XXX - only next line! +#else + assert(path[strlen(path) - 1] == PATHSEPCHAR); + if (strlen(path) > 2) assert(path[strlen(path) - 2] != PATHSEPCHAR); +#endif + snprintf(filename, lengthof(filename), "%s%s", path, ent->d_name); + + return stat(filename, sb) == 0; +} + +bool FiosIsHiddenFile(const struct dirent *ent) +{ + return ent->d_name[0] == '.'; +} + +#ifdef WITH_ICONV + +#include +#include +#include "../../debug.h" +#include "../../string_func.h" + +const char *GetCurrentLocale(const char *param); + +#define INTERNALCODE "UTF-8" + +/** Try and try to decipher the current locale from environmental + * variables. MacOSX is hardcoded, other OS's are dynamic. If no suitable + * locale can be found, don't do any conversion "" */ +static const char *GetLocalCode() +{ +#if defined(__APPLE__) + return "UTF-8-MAC"; +#else + /* Strip locale (eg en_US.UTF-8) to only have UTF-8 */ + const char *locale = GetCurrentLocale("LC_CTYPE"); + if (locale != NULL) locale = strchr(locale, '.'); + + return (locale == NULL) ? "" : locale + 1; +#endif +} + +/** FYI: This is not thread-safe. + * convert between locales, which from and which to is set in the calling + * functions OTTD2FS() and FS2OTTD(). You should NOT use this function directly + * NOTE: iconv was added in OSX 10.3. 10.2.x will still have the invalid char + * issues. There aren't any easy fix for this */ +static const char *convert_tofrom_fs(iconv_t convd, const char *name) +{ + static char buf[1024]; + /* Work around buggy iconv implementation where inbuf is wrongly typed as + * non-const. Correct implementation is at + * http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.html */ +#ifdef HAVE_BROKEN_ICONV + char *inbuf = (char*)name; +#else + const char *inbuf = name; +#endif + + char *outbuf = buf; + size_t outlen = sizeof(buf) - 1; + size_t inlen = strlen(name); + + strecpy(outbuf, name, outbuf + outlen); + + iconv(convd, NULL, NULL, NULL, NULL); + if (iconv(convd, &inbuf, &inlen, &outbuf, &outlen) == (size_t)(-1)) { + DEBUG(misc, 0, "[iconv] error converting '%s'. Errno %d", name, errno); + } + + *outbuf = '\0'; + /* FIX: invalid characters will abort conversion, but they shouldn't occur? */ + return buf; +} + +/** Convert from OpenTTD's encoding to that of the local environment + * @param name pointer to a valid string that will be converted + * @return pointer to a new stringbuffer that contains the converted string */ +const char *OTTD2FS(const char *name) +{ + static iconv_t convd = (iconv_t)(-1); + + if (convd == (iconv_t)(-1)) { + const char *env = GetLocalCode(); + convd = iconv_open(env, INTERNALCODE); + if (convd == (iconv_t)(-1)) { + DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", INTERNALCODE, env); + return name; + } + } + + return convert_tofrom_fs(convd, name); +} + +/** Convert to OpenTTD's encoding from that of the local environment + * @param name pointer to a valid string that will be converted + * @return pointer to a new stringbuffer that contains the converted string */ +const char *FS2OTTD(const char *name) +{ + static iconv_t convd = (iconv_t)(-1); + + if (convd == (iconv_t)(-1)) { + const char *env = GetLocalCode(); + convd = iconv_open(INTERNALCODE, env); + if (convd == (iconv_t)(-1)) { + DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", env, INTERNALCODE); + return name; + } + } + + return convert_tofrom_fs(convd, name); +} + +#else +const char *FS2OTTD(const char *name) {return name;} +const char *OTTD2FS(const char *name) {return name;} +#endif /* WITH_ICONV */ + +void ShowInfo(const char *str) +{ + fprintf(stderr, "%s\n", str); +} + +void ShowOSErrorBox(const char *buf, bool system) +{ +#if defined(__APPLE__) + /* this creates an NSAlertPanel with the contents of 'buf' + * this is the native and nicest way to do this on OSX */ + ShowMacDialog( buf, "See readme for more info\nMost likely you are missing files from the original TTD", "Quit" ); +#else + /* All unix systems, except OSX. Only use escape codes on a TTY. */ + if (isatty(fileno(stderr))) { + fprintf(stderr, "\033[1;31mError: %s\033[0;39m\n", buf); + } else { + fprintf(stderr, "Error: %s\n", buf); + } +#endif +} + +#ifdef WITH_COCOA +void cocoaSetupAutoreleasePool(); +void cocoaReleaseAutoreleasePool(); +#endif + +int CDECL main(int argc, char *argv[]) +{ + int ret; + +#ifdef WITH_COCOA + cocoaSetupAutoreleasePool(); + /* This is passed if we are launched by double-clicking */ + if (argc >= 2 && strncmp(argv[1], "-psn", 4) == 0) { + argv[1] = NULL; + argc = 1; + } +#endif + + SetRandomSeed(time(NULL)); + + signal(SIGPIPE, SIG_IGN); + + ret = ttd_main(argc, argv); + +#ifdef WITH_COCOA + cocoaReleaseAutoreleasePool(); +#endif + + return ret; +} + +bool InsertTextBufferClipboard(Textbuf *tb) +{ + return false; +} + + +/* multi os compatible sleep function */ + +#ifdef __AMIGA__ +/* usleep() implementation */ +# include +# include + + extern struct Device *TimerBase = NULL; + extern struct MsgPort *TimerPort = NULL; + extern struct timerequest *TimerRequest = NULL; +#endif /* __AMIGA__ */ + +void CSleep(int milliseconds) +{ + #if defined(PSP) + sceKernelDelayThread(milliseconds * 1000); + #elif defined(__BEOS__) + snooze(milliseconds * 1000); + #elif defined(__AMIGA__) + { + ULONG signals; + ULONG TimerSigBit = 1 << TimerPort->mp_SigBit; + + /* send IORequest */ + TimerRequest->tr_node.io_Command = TR_ADDREQUEST; + TimerRequest->tr_time.tv_secs = (milliseconds * 1000) / 1000000; + TimerRequest->tr_time.tv_micro = (milliseconds * 1000) % 1000000; + SendIO((struct IORequest *)TimerRequest); + + if (!((signals = Wait(TimerSigBit | SIGBREAKF_CTRL_C)) & TimerSigBit) ) { + AbortIO((struct IORequest *)TimerRequest); + } + WaitIO((struct IORequest *)TimerRequest); + } + #else + usleep(milliseconds * 1000); + #endif +} diff --git a/src/os/windows/masm64.rules b/src/os/windows/masm64.rules new file mode 100644 index 000000000..62e6e0f8b --- /dev/null +++ b/src/os/windows/masm64.rules @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/os/windows/ottdres.rc.in b/src/os/windows/ottdres.rc.in new file mode 100644 index 000000000..f0989f5bb --- /dev/null +++ b/src/os/windows/ottdres.rc.in @@ -0,0 +1,111 @@ +//Microsoft Developer Studio generated resource script. +// $Id$ +// +// This file is part of OpenTTD. +// OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. +// OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . +// +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_READONLY_SYMBOLS +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#ifdef MSVC +#include "winres.h" +#else +#define IDC_STATIC (-1) // all static controls +#endif + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral (Default) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +100 ICON DISCARDABLE "../media/openttd.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +100 DIALOG DISCARDABLE 0, 0, 305, 77 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Fatal Application Failure" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "&Close",12,7,58,50,14 +// PUSHBUTTON "&Submit report",14,81,58,68,14,WS_DISABLED + PUSHBUTTON "&Emergency save",13,155,58,68,14 + PUSHBUTTON "",15,243,58,55,14 + EDITTEXT 11,7,79,291,118,ES_MULTILINE | ES_READONLY | WS_VSCROLL | + WS_HSCROLL | NOT WS_TABSTOP + LTEXT "",10,36,7,262,43 + ICON 100,IDC_STATIC,9,9,20,20 +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,8,0,!!REVISION!! + PRODUCTVERSION 0,8,0,!!REVISION!! + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "This program is licensed under the GNU General Public License.\0" + VALUE "CompanyName", "OpenTTD Development Team\0" + VALUE "FileDescription", "OpenTTD\0" + VALUE "FileVersion", "Development !!VERSION!!\0" + VALUE "InternalName", "openttd\0" + VALUE "LegalCopyright", "Copyright \xA9 OpenTTD Developers 2002-2009. All Rights Reserved.\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "openttd.exe\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "OpenTTD\0" + VALUE "ProductVersion", "Development !!VERSION!!\0" + VALUE "SpecialBuild", "-\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // !_MAC + +#endif // Neutral (Default) resources +///////////////////////////////////////////////////////////////////////////// diff --git a/src/os/windows/win32.cpp b/src/os/windows/win32.cpp new file mode 100644 index 000000000..432755fbe --- /dev/null +++ b/src/os/windows/win32.cpp @@ -0,0 +1,1378 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file win32.cpp Implementation of MS Windows system calls */ + +#include "../../stdafx.h" +#include "../../openttd.h" +#include "../../debug.h" +#include "../../saveload/saveload.h" +#include "../../gfx_func.h" +#include "../../textbuf_gui.h" +#include "../../fileio_func.h" +#include "../../fios.h" +#include "../../rev.h" +#include +#include +#include +#include +#include /* SHGetFolderPath */ +#include "../../variables.h" +#include "win32.h" +#include "../../core/alloc_func.hpp" +#include "../../functions.h" +#include "../../core/random_func.hpp" +#include "../../core/bitmath_func.hpp" +#include "../../string_func.h" +#include "../../gamelog.h" +#include +#include +#include +#include +#if defined(_MSC_VER) && !defined(WINCE) + #include + #include "../../strings_func.h" +#endif + +static bool _has_console; + +static bool cursor_visible = true; + +bool MyShowCursor(bool show) +{ + if (cursor_visible == show) return show; + + cursor_visible = show; + ShowCursor(show); + + return !show; +} + +/** Helper function needed by dynamically loading libraries + * XXX: Hurray for MS only having an ANSI GetProcAddress function + * on normal windows and no Wide version except for in Windows Mobile/CE */ +bool LoadLibraryList(Function proc[], const char *dll) +{ + while (*dll != '\0') { + HMODULE lib; + lib = LoadLibrary(MB_TO_WIDE(dll)); + + if (lib == NULL) return false; + for (;;) { + FARPROC p; + + while (*dll++ != '\0') { /* Nothing */ } + if (*dll == '\0') break; +#if defined(WINCE) + p = GetProcAddress(lib, MB_TO_WIDE(dll)); +#else + p = GetProcAddress(lib, dll); +#endif + if (p == NULL) return false; + *proc++ = (Function)p; + } + dll++; + } + return true; +} + +#ifdef _MSC_VER +static const char *_exception_string = NULL; +void SetExceptionString(const char *s, ...) +{ + va_list va; + char buf[512]; + + va_start(va, s); + vsnprintf(buf, lengthof(buf), s, va); + va_end(va); + + _exception_string = strdup(buf); +} +#endif + +void ShowOSErrorBox(const char *buf, bool system) +{ + MyShowCursor(true); + MessageBox(GetActiveWindow(), MB_TO_WIDE(buf), _T("Error!"), MB_ICONSTOP); + +/* if exception tracker is enabled, we crash here to let the exception handler handle it. */ +#if defined(WIN32_EXCEPTION_TRACKER) && !defined(_DEBUG) + if (system) { + _exception_string = buf; + *(byte*)0 = 0; + } +#endif +} + +#if defined(_MSC_VER) && !defined(WINCE) + +static void *_safe_esp; +static char *_crash_msg; +static bool _expanded; +static bool _did_emerg_save; +static int _ident; + +struct DebugFileInfo { + uint32 size; + uint32 crc32; + SYSTEMTIME file_time; +}; + +static uint32 *_crc_table; + +static void MakeCRCTable(uint32 *table) +{ + uint32 crc, poly = 0xEDB88320L; + int i; + int j; + + _crc_table = table; + + for (i = 0; i != 256; i++) { + crc = i; + for (j = 8; j != 0; j--) { + crc = (crc & 1 ? (crc >> 1) ^ poly : crc >> 1); + } + table[i] = crc; + } +} + +static uint32 CalcCRC(byte *data, uint size, uint32 crc) +{ + for (; size > 0; size--) { + crc = ((crc >> 8) & 0x00FFFFFF) ^ _crc_table[(crc ^ *data++) & 0xFF]; + } + return crc; +} + +static void GetFileInfo(DebugFileInfo *dfi, const TCHAR *filename) +{ + HANDLE file; + memset(dfi, 0, sizeof(*dfi)); + + file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); + if (file != INVALID_HANDLE_VALUE) { + byte buffer[1024]; + DWORD numread; + uint32 filesize = 0; + FILETIME write_time; + uint32 crc = (uint32)-1; + + for (;;) { + if (ReadFile(file, buffer, sizeof(buffer), &numread, NULL) == 0 || numread == 0) + break; + filesize += numread; + crc = CalcCRC(buffer, numread, crc); + } + dfi->size = filesize; + dfi->crc32 = crc ^ (uint32)-1; + + if (GetFileTime(file, NULL, NULL, &write_time)) { + FileTimeToSystemTime(&write_time, &dfi->file_time); + } + CloseHandle(file); + } +} + + +static char *PrintModuleInfo(char *output, const char *last, HMODULE mod) +{ + TCHAR buffer[MAX_PATH]; + DebugFileInfo dfi; + + GetModuleFileName(mod, buffer, MAX_PATH); + GetFileInfo(&dfi, buffer); + output += seprintf(output, last, " %-20s handle: %p size: %d crc: %.8X date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n", + WIDE_TO_MB(buffer), + mod, + dfi.size, + dfi.crc32, + dfi.file_time.wYear, + dfi.file_time.wMonth, + dfi.file_time.wDay, + dfi.file_time.wHour, + dfi.file_time.wMinute, + dfi.file_time.wSecond + ); + return output; +} + +static char *PrintModuleList(char *output, const char *last) +{ + BOOL (WINAPI *EnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD); + + if (LoadLibraryList((Function*)&EnumProcessModules, "psapi.dll\0EnumProcessModules\0\0")) { + HMODULE modules[100]; + DWORD needed; + BOOL res; + + HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); + if (proc != NULL) { + res = EnumProcessModules(proc, modules, sizeof(modules), &needed); + CloseHandle(proc); + if (res) { + size_t count = min(needed / sizeof(HMODULE), lengthof(modules)); + + for (size_t i = 0; i != count; i++) output = PrintModuleInfo(output, last, modules[i]); + return output; + } + } + } + output = PrintModuleInfo(output, last, NULL); + return output; +} + +static const TCHAR _crash_desc[] = + _T("A serious fault condition occured in the game. The game will shut down.\n") + _T("Please send the crash information and the crash.dmp file (if any) to the developers.\n") + _T("This will greatly help debugging. The correct place to do this is http://bugs.openttd.org. ") + _T("The information contained in the report is displayed below.\n") + _T("Press \"Emergency save\" to attempt saving the game."); + +static const TCHAR _save_succeeded[] = + _T("Emergency save succeeded.\n") + _T("Be aware that critical parts of the internal game state may have become ") + _T("corrupted. The saved game is not guaranteed to work."); + +static const TCHAR _emergency_crash[] = + _T("A serious fault condition occured in the game. The game will shut down.\n") + _T("As you loaded an emergency savegame no crash information will be generated.\n"); + +static bool EmergencySave() +{ + GamelogStartAction(GLAT_EMERGENCY); + GamelogEmergency(); + GamelogStopAction(); + SaveOrLoad("crash.sav", SL_SAVE, BASE_DIR); + return true; +} + +/* Disable the crash-save submit code as it's not used */ +#if 0 + +struct WinInetProcs { + HINTERNET (WINAPI *InternetOpen)(LPCTSTR, DWORD, LPCTSTR, LPCTSTR, DWORD); + HINTERNET (WINAPI *InternetConnect)(HINTERNET, LPCTSTR, INTERNET_PORT, LPCTSTR, LPCTSTR, DWORD, DWORD, DWORD); + HINTERNET (WINAPI *HttpOpenRequest)(HINTERNET, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR *, DWORD, DWORD); + BOOL (WINAPI *HttpSendRequest)(HINTERNET, LPCTSTR, DWORD, LPVOID, DWORD); + BOOL (WINAPI *InternetCloseHandle)(HINTERNET); + BOOL (WINAPI *HttpQueryInfo)(HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD); +}; + +#define M(x) x "\0" +#if defined(UNICODE) +# define W(x) x "W" +#else +# define W(x) x "A" +#endif +static const char wininet_files[] = + M("wininet.dll") + M(W("InternetOpen")) + M(W("InternetConnect")) + M(W("HttpOpenRequest")) + M(W("HttpSendRequest")) + M("InternetCloseHandle") + M(W("HttpQueryInfo")) + M(""); +#undef W +#undef M + +static WinInetProcs _wininet; + +static const TCHAR *SubmitCrashReport(HWND wnd, void *msg, size_t msglen, const TCHAR *arg) +{ + HINTERNET inet, conn, http; + const TCHAR *err = NULL; + DWORD code, len; + static TCHAR buf[100]; + TCHAR buff[100]; + + if (_wininet.InternetOpen == NULL && !LoadLibraryList((Function*)&_wininet, wininet_files)) return _T("can't load wininet.dll"); + + inet = _wininet.InternetOpen(_T("OTTD"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ); + if (inet == NULL) { err = _T("internetopen failed"); goto error1; } + + conn = _wininet.InternetConnect(inet, _T("www.openttd.org"), INTERNET_DEFAULT_HTTP_PORT, _T(""), _T(""), INTERNET_SERVICE_HTTP, 0, 0); + if (conn == NULL) { err = _T("internetconnect failed"); goto error2; } + + _sntprintf(buff, lengthof(buff), _T("/crash.php?file=%s&ident=%d"), arg, _ident); + + http = _wininet.HttpOpenRequest(conn, _T("POST"), buff, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE , 0); + if (http == NULL) { err = _T("httpopenrequest failed"); goto error3; } + + if (!_wininet.HttpSendRequest(http, _T("Content-type: application/binary"), -1, msg, (DWORD)msglen)) { err = _T("httpsendrequest failed"); goto error4; } + + len = sizeof(code); + if (!_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &code, &len, 0)) { err = _T("httpqueryinfo failed"); goto error4; } + + if (code != 200) { + int l = _sntprintf(buf, lengthof(buf), _T("Server said: %d "), code); + len = sizeof(buf) - l; + _wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_TEXT, buf + l, &len, 0); + err = buf; + } + +error4: + _wininet.InternetCloseHandle(http); +error3: + _wininet.InternetCloseHandle(conn); +error2: + _wininet.InternetCloseHandle(inet); +error1: + return err; +} + +static void SubmitFile(HWND wnd, const TCHAR *file) +{ + HANDLE h; + unsigned long size; + unsigned long read; + void *mem; + + h = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (h == NULL) return; + + size = GetFileSize(h, NULL); + if (size > 500000) goto error1; + + mem = MallocT(size); + if (mem == NULL) goto error1; + + if (!ReadFile(h, mem, size, &read, NULL) || read != size) goto error2; + + SubmitCrashReport(wnd, mem, size, file); + +error2: + free(mem); +error1: + CloseHandle(h); +} + +#endif /* Disabled crash-submit procedures */ + +static const TCHAR * const _expand_texts[] = {_T("S&how report >>"), _T("&Hide report <<") }; + +static void SetWndSize(HWND wnd, int mode) +{ + RECT r, r2; + int offs; + + GetWindowRect(wnd, &r); + + SetDlgItemText(wnd, 15, _expand_texts[mode == 1]); + + if (mode >= 0) { + GetWindowRect(GetDlgItem(wnd, 11), &r2); + offs = r2.bottom - r2.top + 10; + if (!mode) offs = -offs; + SetWindowPos(wnd, HWND_TOPMOST, 0, 0, + r.right - r.left, r.bottom - r.top + offs, SWP_NOMOVE | SWP_NOZORDER); + } else { + SetWindowPos(wnd, HWND_TOPMOST, + (GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left)) / 2, + (GetSystemMetrics(SM_CYSCREEN) - (r.bottom - r.top)) / 2, + 0, 0, SWP_NOSIZE); + } +} + +static bool DoEmergencySave(HWND wnd) +{ + bool b = false; + + EnableWindow(GetDlgItem(wnd, 13), FALSE); + _did_emerg_save = true; + __try { + b = EmergencySave(); + } __except (1) {} + return b; +} + +static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: { +#if defined(UNICODE) + /* We need to put the crash-log in a seperate buffer because the default + * buffer in MB_TO_WIDE is not large enough (512 chars) */ + wchar_t crash_msgW[8096]; +#endif + SetDlgItemText(wnd, 10, _crash_desc); + SetDlgItemText(wnd, 11, MB_TO_WIDE_BUFFER(_crash_msg, crash_msgW, lengthof(crash_msgW))); + SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE); + SetWndSize(wnd, -1); + } return TRUE; + case WM_COMMAND: + switch (wParam) { + case 12: // Close + ExitProcess(0); + case 13: // Emergency save + if (DoEmergencySave(wnd)) { + MessageBox(wnd, _save_succeeded, _T("Save successful"), MB_ICONINFORMATION); + } else { + MessageBox(wnd, _T("Save failed"), _T("Save failed"), MB_ICONINFORMATION); + } + break; +/* Disable the crash-save submit code as it's not used */ +#if 0 + case 14: { // Submit crash report + const TCHAR *s; + + SetCursor(LoadCursor(NULL, IDC_WAIT)); + + s = SubmitCrashReport(wnd, _crash_msg, strlen(_crash_msg), _T("")); + if (s != NULL) { + MessageBox(wnd, s, _T("Error"), MB_ICONSTOP); + break; + } + + /* try to submit emergency savegame */ + if (_did_emerg_save || DoEmergencySave(wnd)) SubmitFile(wnd, _T("crash.sav")); + + /* try to submit the autosaved game */ + if (_opt.autosave) { + TCHAR buf[40]; + _sntprintf(buf, lengthof(buf), _T("autosave%d.sav"), (_autosave_ctr - 1) & 3); + SubmitFile(wnd, buf); + } + EnableWindow(GetDlgItem(wnd, 14), FALSE); + SetCursor(LoadCursor(NULL, IDC_ARROW)); + MessageBox(wnd, _T("Crash report submitted. Thank you."), _T("Crash Report"), MB_ICONINFORMATION); + } break; +#endif /* Disabled crash-submit procedures */ + case 15: // Expand window to show crash-message + _expanded ^= 1; + SetWndSize(wnd, _expanded); + break; + } + return TRUE; + case WM_CLOSE: ExitProcess(0); + } + + return FALSE; +} + +static void Handler2() +{ + ShowCursor(TRUE); + ShowWindow(GetActiveWindow(), FALSE); + DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(100), NULL, CrashDialogFunc); +} + +extern bool CloseConsoleLogIfActive(); + +static HANDLE _file_crash_log; + +static void GamelogPrintCrashLogProc(const char *s) +{ + DWORD num_written; + WriteFile(_file_crash_log, s, (DWORD)strlen(s), &num_written, NULL); + WriteFile(_file_crash_log, "\r\n", (DWORD)strlen("\r\n"), &num_written, NULL); +} + +/** Amount of output for the execption handler. */ +static const int EXCEPTION_OUTPUT_SIZE = 8192; + +static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) +{ + char *output; + static bool had_exception = false; + + if (had_exception) ExitProcess(0); + if (GamelogTestEmergency()) { + MessageBox(NULL, _emergency_crash, _T("Fatal Application Failure"), MB_ICONERROR); + ExitProcess(0); + } + had_exception = true; + + _ident = GetTickCount(); // something pretty unique + + MakeCRCTable(AllocaM(uint32, 256)); + _crash_msg = output = (char*)LocalAlloc(LMEM_FIXED, EXCEPTION_OUTPUT_SIZE); + const char *last = output + EXCEPTION_OUTPUT_SIZE - 1; + + { + SYSTEMTIME time; + GetLocalTime(&time); + output += seprintf(output, last, + "*** OpenTTD Crash Report ***\r\n" + "Date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n" + "Build: %s (%d) built on " __DATE__ " " __TIME__ "\r\n", + time.wYear, + time.wMonth, + time.wDay, + time.wHour, + time.wMinute, + time.wSecond, + _openttd_revision, + _openttd_revision_modified + ); + } + + if (_exception_string) + output += seprintf(output, last, "Reason: %s\r\n", _exception_string); + + output += seprintf(output, last, "Language: %s\r\n", _dynlang.curr_file); + +#ifdef _M_AMD64 + output += seprintf(output, last, "Exception %.8X at %.16IX\r\n" + "Registers:\r\n" + "RAX: %.16llX RBX: %.16llX RCX: %.16llX RDX: %.16llX\r\n" + "RSI: %.16llX RDI: %.16llX RBP: %.16llX RSP: %.16llX\r\n" + "R8: %.16llX R9: %.16llX R10: %.16llX R11: %.16llX\r\n" + "R12: %.16llX R13: %.16llX R14: %.16llX R15: %.16llX\r\n" + "RIP: %.16llX EFLAGS: %.8X\r\n" + "\r\nBytes at CS:RIP:\r\n", + ep->ExceptionRecord->ExceptionCode, + ep->ExceptionRecord->ExceptionAddress, + ep->ContextRecord->Rax, + ep->ContextRecord->Rbx, + ep->ContextRecord->Rcx, + ep->ContextRecord->Rdx, + ep->ContextRecord->Rsi, + ep->ContextRecord->Rdi, + ep->ContextRecord->Rbp, + ep->ContextRecord->Rsp, + ep->ContextRecord->R8, + ep->ContextRecord->R9, + ep->ContextRecord->R10, + ep->ContextRecord->R11, + ep->ContextRecord->R12, + ep->ContextRecord->R13, + ep->ContextRecord->R14, + ep->ContextRecord->R15, + ep->ContextRecord->Rip, + ep->ContextRecord->EFlags + ); +#else + output += seprintf(output, last, "Exception %.8X at %.8p\r\n" + "Registers:\r\n" + " EAX: %.8X EBX: %.8X ECX: %.8X EDX: %.8X\r\n" + " ESI: %.8X EDI: %.8X EBP: %.8X ESP: %.8X\r\n" + " EIP: %.8X EFLAGS: %.8X\r\n" + "\r\nBytes at CS:EIP:\r\n", + ep->ExceptionRecord->ExceptionCode, + ep->ExceptionRecord->ExceptionAddress, + ep->ContextRecord->Eax, + ep->ContextRecord->Ebx, + ep->ContextRecord->Ecx, + ep->ContextRecord->Edx, + ep->ContextRecord->Esi, + ep->ContextRecord->Edi, + ep->ContextRecord->Ebp, + ep->ContextRecord->Esp, + ep->ContextRecord->Eip, + ep->ContextRecord->EFlags + ); +#endif + + { +#ifdef _M_AMD64 + byte *b = (byte*)ep->ContextRecord->Rip; +#else + byte *b = (byte*)ep->ContextRecord->Eip; +#endif + int i; + for (i = 0; i != 24; i++) { + if (IsBadReadPtr(b, 1)) { + output += seprintf(output, last, " ??"); // OCR: WAS: , 0); + } else { + output += seprintf(output, last, " %.2X", *b); + } + b++; + } + output += seprintf(output, last, + "\r\n" + "\r\nStack trace: \r\n" + ); + } + + { + int i, j; +#ifdef _M_AMD64 + uint32 *b = (uint32*)ep->ContextRecord->Rsp; +#else + uint32 *b = (uint32*)ep->ContextRecord->Esp; +#endif + for (j = 0; j != 24; j++) { + for (i = 0; i != 8; i++) { + if (IsBadReadPtr(b, sizeof(uint32))) { + output += seprintf(output, last, " ????????"); // OCR: WAS - , 0); + } else { + output += seprintf(output, last, " %.8X", *b); + } + b++; + } + output += seprintf(output, last, "\r\n"); + } + } + + output += seprintf(output, last, "\r\nModule information:\r\n"); + output = PrintModuleList(output, last); + + { + _OSVERSIONINFOA os; + os.dwOSVersionInfoSize = sizeof(os); + GetVersionExA(&os); + output += seprintf(output, last, "\r\nSystem information:\r\n" + " Windows version %d.%d %d %s\r\n\r\n", + os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber, os.szCSDVersion); + } + + _file_crash_log = CreateFile(_T("crash.log"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + + if (_file_crash_log != INVALID_HANDLE_VALUE) { + DWORD num_written; + WriteFile(_file_crash_log, _crash_msg, output - _crash_msg, &num_written, NULL); + } + +#if !defined(_DEBUG) + HMODULE dbghelp = LoadLibrary(_T("dbghelp.dll")); + if (dbghelp != NULL) { + typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE, + MINIDUMP_TYPE, + CONST PMINIDUMP_EXCEPTION_INFORMATION, + CONST PMINIDUMP_USER_STREAM_INFORMATION, + CONST PMINIDUMP_CALLBACK_INFORMATION); + MiniDumpWriteDump_t funcMiniDumpWriteDump = (MiniDumpWriteDump_t)GetProcAddress(dbghelp, "MiniDumpWriteDump"); + if (funcMiniDumpWriteDump != NULL) { + HANDLE file = CreateFile(_T("crash.dmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + HANDLE proc = GetCurrentProcess(); + DWORD procid = GetCurrentProcessId(); + MINIDUMP_EXCEPTION_INFORMATION mdei; + MINIDUMP_USER_STREAM userstream; + MINIDUMP_USER_STREAM_INFORMATION musi; + char msg[] = "****** Built on " __DATE__ " " __TIME__ ". ******"; + + userstream.Type = LastReservedStream + 1; + userstream.Buffer = msg; + userstream.BufferSize = sizeof(msg); + + musi.UserStreamCount = 1; + musi.UserStreamArray = &userstream; + + mdei.ThreadId = GetCurrentThreadId(); + mdei.ExceptionPointers = ep; + mdei.ClientPointers = false; + + funcMiniDumpWriteDump(proc, procid, file, MiniDumpWithDataSegs, &mdei, &musi, NULL); + } + FreeLibrary(dbghelp); + } +#endif + + if (_file_crash_log != INVALID_HANDLE_VALUE) { + GamelogPrint(&GamelogPrintCrashLogProc); + CloseHandle(_file_crash_log); + } + + /* Close any possible log files */ + CloseConsoleLogIfActive(); + + if (_safe_esp) { +#ifdef _M_AMD64 + ep->ContextRecord->Rip = (DWORD64)Handler2; + ep->ContextRecord->Rsp = (DWORD64)_safe_esp; +#else + ep->ContextRecord->Eip = (DWORD)Handler2; + ep->ContextRecord->Esp = (DWORD)_safe_esp; +#endif + return EXCEPTION_CONTINUE_EXECUTION; + } + + + return EXCEPTION_EXECUTE_HANDLER; +} + +#ifdef _M_AMD64 +extern "C" void *_get_safe_esp(); +#endif + +static void Win32InitializeExceptions() +{ +#ifdef _M_AMD64 + _safe_esp = _get_safe_esp(); +#else + _asm { + mov _safe_esp, esp + } +#endif + + SetUnhandledExceptionFilter(ExceptionHandler); +} +#endif /* _MSC_VER */ + +/* Code below for windows version of opendir/readdir/closedir copied and + * modified from Jan Wassenberg's GPL implementation posted over at + * http://www.gamedev.net/community/forums/topic.asp?topic_id=364584&whichpage=1� */ + +/* suballocator - satisfies most requests with a reusable static instance. + * this avoids hundreds of alloc/free which would fragment the heap. + * To guarantee concurrency, we fall back to malloc if the instance is + * already in use (it's important to avoid suprises since this is such a + * low-level routine). */ +static DIR _global_dir; +static LONG _global_dir_is_in_use = false; + +static inline DIR *dir_calloc() +{ + DIR *d; + + if (InterlockedExchange(&_global_dir_is_in_use, true) == (LONG)true) { + d = CallocT(1); + } else { + d = &_global_dir; + memset(d, 0, sizeof(*d)); + } + return d; +} + +static inline void dir_free(DIR *d) +{ + if (d == &_global_dir) { + _global_dir_is_in_use = (LONG)false; + } else { + free(d); + } +} + +DIR *opendir(const TCHAR *path) +{ + DIR *d; + UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box + DWORD fa = GetFileAttributes(path); + + if ((fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY)) { + d = dir_calloc(); + if (d != NULL) { + TCHAR search_path[MAX_PATH]; + bool slash = path[_tcslen(path) - 1] == '\\'; + + /* build search path for FindFirstFile, try not to append additional slashes + * as it throws Win9x off its groove for root directories */ + _sntprintf(search_path, lengthof(search_path), _T("%s%s*"), path, slash ? _T("") : _T("\\")); + *lastof(search_path) = '\0'; + d->hFind = FindFirstFile(search_path, &d->fd); + + if (d->hFind != INVALID_HANDLE_VALUE || + GetLastError() == ERROR_NO_MORE_FILES) { // the directory is empty + d->ent.dir = d; + d->at_first_entry = true; + } else { + dir_free(d); + d = NULL; + } + } else { + errno = ENOMEM; + } + } else { + /* path not found or not a directory */ + d = NULL; + errno = ENOENT; + } + + SetErrorMode(sem); // restore previous setting + return d; +} + +struct dirent *readdir(DIR *d) +{ + DWORD prev_err = GetLastError(); // avoid polluting last error + + if (d->at_first_entry) { + /* the directory was empty when opened */ + if (d->hFind == INVALID_HANDLE_VALUE) return NULL; + d->at_first_entry = false; + } else if (!FindNextFile(d->hFind, &d->fd)) { // determine cause and bail + if (GetLastError() == ERROR_NO_MORE_FILES) SetLastError(prev_err); + return NULL; + } + + /* This entry has passed all checks; return information about it. + * (note: d_name is a pointer; see struct dirent definition) */ + d->ent.d_name = d->fd.cFileName; + return &d->ent; +} + +int closedir(DIR *d) +{ + FindClose(d->hFind); + dir_free(d); + return 0; +} + +bool FiosIsRoot(const char *file) +{ + return file[3] == '\0'; // C:\... +} + +void FiosGetDrives() +{ +#if defined(WINCE) + /* WinCE only knows one drive: / */ + FiosItem *fios = _fios_items.Append(); + fios->type = FIOS_TYPE_DRIVE; + fios->mtime = 0; + snprintf(fios->name, lengthof(fios->name), PATHSEP ""); + strecpy(fios->title, fios->name, lastof(fios->title)); +#else + TCHAR drives[256]; + const TCHAR *s; + + GetLogicalDriveStrings(lengthof(drives), drives); + for (s = drives; *s != '\0';) { + FiosItem *fios = _fios_items.Append(); + fios->type = FIOS_TYPE_DRIVE; + fios->mtime = 0; + snprintf(fios->name, lengthof(fios->name), "%c:", s[0] & 0xFF); + strecpy(fios->title, fios->name, lastof(fios->title)); + while (*s++ != '\0') { /* Nothing */ } + } +#endif +} + +bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) +{ + /* hectonanoseconds between Windows and POSIX epoch */ + static const int64 posix_epoch_hns = 0x019DB1DED53E8000LL; + const WIN32_FIND_DATA *fd = &ent->dir->fd; + + sb->st_size = ((uint64) fd->nFileSizeHigh << 32) + fd->nFileSizeLow; + /* UTC FILETIME to seconds-since-1970 UTC + * we just have to subtract POSIX epoch and scale down to units of seconds. + * http://www.gamedev.net/community/forums/topic.asp?topic_id=294070&whichpage=1� + * XXX - not entirely correct, since filetimes on FAT aren't UTC but local, + * this won't entirely be correct, but we use the time only for comparsion. */ + sb->st_mtime = (time_t)((*(uint64*)&fd->ftLastWriteTime - posix_epoch_hns) / 1E7); + sb->st_mode = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)? S_IFDIR : S_IFREG; + + return true; +} + +bool FiosIsHiddenFile(const struct dirent *ent) +{ + return (ent->dir->fd.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0; +} + +bool FiosGetDiskFreeSpace(const char *path, uint64 *tot) +{ + UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box + bool retval = false; + TCHAR root[4]; + DWORD spc, bps, nfc, tnc; + + _sntprintf(root, lengthof(root), _T("%c:") _T(PATHSEP), path[0]); + if (tot != NULL && GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) { + *tot = ((spc * bps) * (uint64)nfc); + retval = true; + } + + SetErrorMode(sem); // reset previous setting + return retval; +} + +static int ParseCommandLine(char *line, char **argv, int max_argc) +{ + int n = 0; + + do { + /* skip whitespace */ + while (*line == ' ' || *line == '\t') line++; + + /* end? */ + if (*line == '\0') break; + + /* special handling when quoted */ + if (*line == '"') { + argv[n++] = ++line; + while (*line != '"') { + if (*line == '\0') return n; + line++; + } + } else { + argv[n++] = line; + while (*line != ' ' && *line != '\t') { + if (*line == '\0') return n; + line++; + } + } + *line++ = '\0'; + } while (n != max_argc); + + return n; +} + +void CreateConsole() +{ +#if defined(WINCE) + /* WinCE doesn't support console stuff */ +#else + HANDLE hand; + CONSOLE_SCREEN_BUFFER_INFO coninfo; + + if (_has_console) return; + _has_console = true; + + AllocConsole(); + + hand = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(hand, &coninfo); + coninfo.dwSize.Y = 500; + SetConsoleScreenBufferSize(hand, coninfo.dwSize); + + /* redirect unbuffered STDIN, STDOUT, STDERR to the console */ +#if !defined(__CYGWIN__) + *stdout = *_fdopen( _open_osfhandle((intptr_t)hand, _O_TEXT), "w" ); + *stdin = *_fdopen(_open_osfhandle((intptr_t)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "r" ); + *stderr = *_fdopen(_open_osfhandle((intptr_t)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w" ); +#else + /* open_osfhandle is not in cygwin */ + *stdout = *fdopen(1, "w" ); + *stdin = *fdopen(0, "r" ); + *stderr = *fdopen(2, "w" ); +#endif + + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); +#endif +} + +void ShowInfo(const char *str) +{ + if (_has_console) { + fprintf(stderr, "%s\n", str); + } else { + bool old; +#if defined(UNICODE) + /* We need to put the text in a seperate buffer because the default + * buffer in MB_TO_WIDE might not be large enough (512 chars) */ + wchar_t help_msgW[8192]; +#endif + ReleaseCapture(); + _left_button_clicked = _left_button_down = false; + + old = MyShowCursor(true); + if (MessageBox(GetActiveWindow(), MB_TO_WIDE_BUFFER(str, help_msgW, lengthof(help_msgW)), _T("OpenTTD"), MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL) { + CreateConsole(); + } + MyShowCursor(old); + } +} + +#if defined(WINCE) +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) +#else +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +#endif +{ + int argc; + char *argv[64]; // max 64 command line arguments + char *cmdline; + +#if !defined(UNICODE) + _codepage = GetACP(); // get system codepage as some kind of a default +#endif /* UNICODE */ + +#if defined(UNICODE) + +#if !defined(WINCE) + /* Check if a win9x user started the win32 version */ + if (HasBit(GetVersion(), 31)) usererror("This version of OpenTTD doesn't run on windows 95/98/ME.\nPlease download the win9x binary and try again."); +#endif + + /* For UNICODE we need to convert the commandline to char* _AND_ + * save it because argv[] points into this buffer and thus needs to + * be available between subsequent calls to FS2OTTD() */ + char cmdlinebuf[MAX_PATH]; +#endif /* UNICODE */ + + cmdline = WIDE_TO_MB_BUFFER(GetCommandLine(), cmdlinebuf, lengthof(cmdlinebuf)); + +#if defined(_DEBUG) + CreateConsole(); +#endif + +#if !defined(WINCE) + _set_error_mode(_OUT_TO_MSGBOX); // force assertion output to messagebox +#endif + + /* setup random seed to something quite random */ + SetRandomSeed(GetTickCount()); + + argc = ParseCommandLine(cmdline, argv, lengthof(argv)); + +#if defined(WIN32_EXCEPTION_TRACKER) + Win32InitializeExceptions(); +#endif + +#if defined(WIN32_EXCEPTION_TRACKER_DEBUG) + _try { + LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep); +#endif + ttd_main(argc, argv); + +#if defined(WIN32_EXCEPTION_TRACKER_DEBUG) + } _except (ExceptionHandler(_exception_info())) {} +#endif + + return 0; +} + +#if defined(WINCE) +void GetCurrentDirectoryW(int length, wchar_t *path) +{ + /* Get the name of this module */ + GetModuleFileName(NULL, path, length); + + /* Remove the executable name, this we call CurrentDir */ + wchar_t *pDest = wcsrchr(path, '\\'); + if (pDest != NULL) { + int result = pDest - path + 1; + path[result] = '\0'; + } +} +#endif + +char *getcwd(char *buf, size_t size) +{ +#if defined(WINCE) + TCHAR path[MAX_PATH]; + GetModuleFileName(NULL, path, MAX_PATH); + convert_from_fs(path, buf, size); + /* GetModuleFileName returns dir with file, so remove everything behind latest '\\' */ + char *p = strrchr(buf, '\\'); + if (p != NULL) *p = '\0'; +#elif defined(UNICODE) + TCHAR path[MAX_PATH]; + GetCurrentDirectory(MAX_PATH - 1, path); + convert_from_fs(path, buf, size); +#else + GetCurrentDirectory(size, buf); +#endif + return buf; +} + + +void DetermineBasePaths(const char *exe) +{ + char tmp[MAX_PATH]; + TCHAR path[MAX_PATH]; +#ifdef WITH_PERSONAL_DIR + SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path); + strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp)); + AppendPathSeparator(tmp, MAX_PATH); + ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH); + AppendPathSeparator(tmp, MAX_PATH); + _searchpaths[SP_PERSONAL_DIR] = strdup(tmp); + + SHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path); + strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp)); + AppendPathSeparator(tmp, MAX_PATH); + ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH); + AppendPathSeparator(tmp, MAX_PATH); + _searchpaths[SP_SHARED_DIR] = strdup(tmp); +#else + _searchpaths[SP_PERSONAL_DIR] = NULL; + _searchpaths[SP_SHARED_DIR] = NULL; +#endif + + /* Get the path to working directory of OpenTTD */ + getcwd(tmp, lengthof(tmp)); + AppendPathSeparator(tmp, MAX_PATH); + _searchpaths[SP_WORKING_DIR] = strdup(tmp); + + if (!GetModuleFileName(NULL, path, lengthof(path))) { + DEBUG(misc, 0, "GetModuleFileName failed (%lu)\n", GetLastError()); + _searchpaths[SP_BINARY_DIR] = NULL; + } else { + TCHAR exec_dir[MAX_PATH]; + _tcsncpy(path, MB_TO_WIDE_BUFFER(exe, path, lengthof(path)), lengthof(path)); + if (!GetFullPathName(path, lengthof(exec_dir), exec_dir, NULL)) { + DEBUG(misc, 0, "GetFullPathName failed (%lu)\n", GetLastError()); + _searchpaths[SP_BINARY_DIR] = NULL; + } else { + strecpy(tmp, WIDE_TO_MB_BUFFER(exec_dir, tmp, lengthof(tmp)), lastof(tmp)); + char *s = strrchr(tmp, PATHSEPCHAR); + *(s + 1) = '\0'; + _searchpaths[SP_BINARY_DIR] = strdup(tmp); + } + } + + _searchpaths[SP_INSTALLATION_DIR] = NULL; + _searchpaths[SP_APPLICATION_BUNDLE_DIR] = NULL; +} + +/** + * Insert a chunk of text from the clipboard onto the textbuffer. Get TEXT clipboard + * and append this up to the maximum length (either absolute or screenlength). If maxlength + * is zero, we don't care about the screenlength but only about the physical length of the string + * @param tb Textbuf type to be changed + * @return true on successful change of Textbuf, or false otherwise + */ +bool InsertTextBufferClipboard(Textbuf *tb) +{ + HGLOBAL cbuf; + char utf8_buf[512]; + const char *ptr; + + WChar c; + uint16 width, length; + + if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { + OpenClipboard(NULL); + cbuf = GetClipboardData(CF_UNICODETEXT); + + ptr = (const char*)GlobalLock(cbuf); + const char *ret = convert_from_fs((wchar_t*)ptr, utf8_buf, lengthof(utf8_buf)); + GlobalUnlock(cbuf); + CloseClipboard(); + + if (*ret == '\0') return false; +#if !defined(UNICODE) + } else if (IsClipboardFormatAvailable(CF_TEXT)) { + OpenClipboard(NULL); + cbuf = GetClipboardData(CF_TEXT); + + ptr = (const char*)GlobalLock(cbuf); + strecpy(utf8_buf, FS2OTTD(ptr), lastof(utf8_buf)); + + GlobalUnlock(cbuf); + CloseClipboard(); +#endif /* UNICODE */ + } else { + return false; + } + + width = length = 0; + + for (ptr = utf8_buf; (c = Utf8Consume(&ptr)) != '\0';) { + if (!IsPrintable(c)) break; + + byte len = Utf8CharLen(c); + if (tb->size + length + len > tb->maxsize) break; + + byte charwidth = GetCharacterWidth(FS_NORMAL, c); + if (tb->maxwidth != 0 && width + tb->width + charwidth > tb->maxwidth) break; + + width += charwidth; + length += len; + } + + if (length == 0) return false; + + memmove(tb->buf + tb->caretpos + length, tb->buf + tb->caretpos, tb->size - tb->caretpos); + memcpy(tb->buf + tb->caretpos, utf8_buf, length); + tb->width += width; + tb->caretxoffs += width; + + tb->size += length; + tb->caretpos += length; + assert(tb->size <= tb->maxsize); + tb->buf[tb->size - 1] = '\0'; // terminating zero + + return true; +} + + +void CSleep(int milliseconds) +{ + Sleep(milliseconds); +} + + +/** Utility function to get the current timestamp in milliseconds + * Useful for profiling */ +int64 GetTS() +{ + static double freq; + __int64 value; + if (!freq) { + QueryPerformanceFrequency((LARGE_INTEGER*)&value); + freq = (double)1000000 / value; + } + QueryPerformanceCounter((LARGE_INTEGER*)&value); + return (__int64)(value * freq); +} + + +/** + * Convert to OpenTTD's encoding from that of the local environment. + * When the project is built in UNICODE, the system codepage is irrelevant and + * the input string is wide. In ANSI mode, the string is in the + * local codepage which we'll convert to wide-char, and then to UTF-8. + * OpenTTD internal encoding is UTF8. + * The returned value's contents can only be guaranteed until the next call to + * this function. So if the value is needed for anything else, use convert_from_fs + * @param name pointer to a valid string that will be converted (local, or wide) + * @return pointer to the converted string; if failed string is of zero-length + * @see the current code-page comes from video\win32_v.cpp, event-notification + * WM_INPUTLANGCHANGE */ +const char *FS2OTTD(const TCHAR *name) +{ + static char utf8_buf[512]; +#if defined(UNICODE) + return convert_from_fs(name, utf8_buf, lengthof(utf8_buf)); +#else + char *s = utf8_buf; + + for (; *name != '\0'; name++) { + wchar_t w; + int len = MultiByteToWideChar(_codepage, 0, name, 1, &w, 1); + if (len != 1) { + DEBUG(misc, 0, "[utf8] M2W error converting '%c'. Errno %lu", *name, GetLastError()); + continue; + } + + if (s + Utf8CharLen(w) >= lastof(utf8_buf)) break; + s += Utf8Encode(s, w); + } + + *s = '\0'; + return utf8_buf; +#endif /* UNICODE */ +} + +/** + * Convert from OpenTTD's encoding to that of the local environment. + * When the project is built in UNICODE the system codepage is irrelevant and + * the converted string is wide. In ANSI mode, the UTF8 string is converted + * to multi-byte. + * OpenTTD internal encoding is UTF8. + * The returned value's contents can only be guaranteed until the next call to + * this function. So if the value is needed for anything else, use convert_from_fs + * @param name pointer to a valid string that will be converted (UTF8) + * @return pointer to the converted string; if failed string is of zero-length + * @see the current code-page comes from video\win32_v.cpp, event-notification + * WM_INPUTLANGCHANGE */ +const TCHAR *OTTD2FS(const char *name) +{ + static TCHAR system_buf[512]; +#if defined(UNICODE) + return convert_to_fs(name, system_buf, lengthof(system_buf)); +#else + char *s = system_buf; + + for (WChar c; (c = Utf8Consume(&name)) != '\0';) { + if (s >= lastof(system_buf)) break; + + char mb; + int len = WideCharToMultiByte(_codepage, 0, (wchar_t*)&c, 1, &mb, 1, NULL, NULL); + if (len != 1) { + DEBUG(misc, 0, "[utf8] W2M error converting '0x%X'. Errno %lu", c, GetLastError()); + continue; + } + + *s++ = mb; + } + + *s = '\0'; + return system_buf; +#endif /* UNICODE */ +} + + +/** Convert to OpenTTD's encoding from that of the environment in + * UNICODE. OpenTTD encoding is UTF8, local is wide + * @param name pointer to a valid string that will be converted + * @param utf8_buf pointer to a valid buffer that will receive the converted string + * @param buflen length in characters of the receiving buffer + * @return pointer to utf8_buf. If conversion fails the string is of zero-length */ +char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen) +{ + int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, utf8_buf, (int)buflen, NULL, NULL); + if (len == 0) { + DEBUG(misc, 0, "[utf8] W2M error converting wide-string. Errno %lu", GetLastError()); + utf8_buf[0] = '\0'; + } + + return utf8_buf; +} + + +/** Convert from OpenTTD's encoding to that of the environment in + * UNICODE. OpenTTD encoding is UTF8, local is wide + * @param name pointer to a valid string that will be converted + * @param utf16_buf pointer to a valid wide-char buffer that will receive the + * converted string + * @param buflen length in wide characters of the receiving buffer + * @return pointer to utf16_buf. If conversion fails the string is of zero-length */ +wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen) +{ + int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, utf16_buf, (int)buflen); + if (len == 0) { + DEBUG(misc, 0, "[utf8] M2W error converting '%s'. Errno %lu", name, GetLastError()); + utf16_buf[0] = '\0'; + } + + return utf16_buf; +} + +/** Our very own SHGetFolderPath function for support of windows operating + * systems that don't have this function (eg Win9x, etc.). We try using the + * native function, and if that doesn't exist we will try a more crude approach + * of environment variables and hope for the best */ +HRESULT OTTDSHGetFolderPath(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath) +{ + static HRESULT (WINAPI *SHGetFolderPath)(HWND, int, HANDLE, DWORD, LPTSTR) = NULL; + static bool first_time = true; + + /* We only try to load the library one time; if it fails, it fails */ + if (first_time) { +#if defined(UNICODE) +# define W(x) x "W" +#else +# define W(x) x "A" +#endif + if (!LoadLibraryList((Function*)&SHGetFolderPath, "SHFolder.dll\0" W("SHGetFolderPath") "\0\0")) { + DEBUG(misc, 0, "Unable to load " W("SHGetFolderPath") "from SHFolder.dll"); + } +#undef W + first_time = false; + } + + if (SHGetFolderPath != NULL) return SHGetFolderPath(hwnd, csidl, hToken, dwFlags, pszPath); + + /* SHGetFolderPath doesn't exist, try a more conservative approach, + * eg environment variables. This is only included for legacy modes + * MSDN says: that 'pszPath' is a "Pointer to a null-terminated string of + * length MAX_PATH which will receive the path" so let's assume that + * Windows 95 with Internet Explorer 5.0, Windows 98 with Internet Explorer 5.0, + * Windows 98 Second Edition (SE), Windows NT 4.0 with Internet Explorer 5.0, + * Windows NT 4.0 with Service Pack 4 (SP4) */ + { + DWORD ret; + switch (csidl) { + case CSIDL_FONTS: // Get the system font path, eg %WINDIR%\Fonts + ret = GetEnvironmentVariable(_T("WINDIR"), pszPath, MAX_PATH); + if (ret == 0) break; + _tcsncat(pszPath, _T("\\Fonts"), MAX_PATH); + + return (HRESULT)0; + break; + /* XXX - other types to go here when needed... */ + } + } + + return E_INVALIDARG; +} + +/** Determine the current user's locale. */ +const char *GetCurrentLocale(const char *) +{ + char lang[9], country[9]; + if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, lang, lengthof(lang)) == 0 || + GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, country, lengthof(country)) == 0) { + /* Unable to retrieve the locale. */ + return NULL; + } + /* Format it as 'en_us'. */ + static char retbuf[6] = {lang[0], lang[1], '_', country[0], country[1], 0}; + return retbuf; +} diff --git a/src/os/windows/win32.h b/src/os/windows/win32.h new file mode 100644 index 000000000..19f04d1f2 --- /dev/null +++ b/src/os/windows/win32.h @@ -0,0 +1,55 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file win32.h declarations of functions for MS windows systems */ + +#ifndef WIN32_H +#define WIN32_H + +#include +bool MyShowCursor(bool show); + +typedef void (*Function)(int); +bool LoadLibraryList(Function proc[], const char *dll); + +char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen); +wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen); + +/* Function shortcuts for UTF-8 <> UNICODE conversion. When unicode is not + * defined these macros return the string passed to them, with UNICODE + * they return a pointer to the converted string. The only difference between + * XX_TO_YY and XX_TO_YY_BUFFER is that with the buffer variant you can + * specify where to put the converted string (and how long it can be). Without + * the buffer and internal buffer is used, of max 512 characters */ +#if defined(UNICODE) +# define MB_TO_WIDE(str) OTTD2FS(str) +# define MB_TO_WIDE_BUFFER(str, buffer, buflen) convert_to_fs(str, buffer, buflen) +# define WIDE_TO_MB(str) FS2OTTD(str) +# define WIDE_TO_MB_BUFFER(str, buffer, buflen) convert_from_fs(str, buffer, buflen) +#else +extern uint _codepage; // local code-page in the system @see win32_v.cpp:WM_INPUTLANGCHANGE +# define MB_TO_WIDE(str) (str) +# define MB_TO_WIDE_BUFFER(str, buffer, buflen) (str) +# define WIDE_TO_MB(str) (str) +# define WIDE_TO_MB_BUFFER(str, buffer, buflen) (str) +#endif + +/* Override SHGetFolderPath with our custom implementation */ +#if defined(SHGetFolderPath) +#undef SHGetFolderPath +#endif +#define SHGetFolderPath OTTDSHGetFolderPath + +HRESULT OTTDSHGetFolderPath(HWND, int, HANDLE, DWORD, LPTSTR); + +#if defined(__MINGW32__) +#define SHGFP_TYPE_CURRENT 0 +#endif /* __MINGW32__ */ + +#endif /* WIN32_H */ diff --git a/src/os/windows/win64.asm b/src/os/windows/win64.asm new file mode 100644 index 000000000..d95bc3898 --- /dev/null +++ b/src/os/windows/win64.asm @@ -0,0 +1,8 @@ + .CODE + +PUBLIC _get_safe_esp +_get_safe_esp: + MOV RAX,RSP + RET + + END diff --git a/src/os2.cpp b/src/os2.cpp deleted file mode 100644 index a40a46c84..000000000 --- a/src/os2.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* $Id$ */ - -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file os2.cpp OS2 related OS support. */ - -#include "stdafx.h" -#include "openttd.h" -#include "variables.h" -#include "gui.h" -#include "fileio_func.h" -#include "fios.h" -#include "functions.h" -#include "core/random_func.hpp" -#include "string_func.h" -#include "textbuf_gui.h" - -#include "table/strings.h" - -#include -#include -#include -#include -#include -#ifndef __INNOTEK_LIBC__ - #include -#endif - -#define INCL_WIN -#define INCL_WINCLIPBOARD - -#include -#ifndef __INNOTEK_LIBC__ - #include -#endif - -bool FiosIsRoot(const char *file) -{ - return file[3] == '\0'; -} - -void FiosGetDrives() -{ - uint disk, disk2, save, total; - -#ifndef __INNOTEK_LIBC__ - _dos_getdrive(&save); // save original drive -#else - save = _getdrive(); // save original drive - char wd[MAX_PATH]; - getcwd(wd, MAX_PATH); - total = 'z'; -#endif - - /* get an available drive letter */ -#ifndef __INNOTEK_LIBC__ - for (disk = 1;; disk++) { - _dos_setdrive(disk, &total); -#else - for (disk = 'A';; disk++) { - _chdrive(disk); -#endif - if (disk >= total) break; - -#ifndef __INNOTEK_LIBC__ - _dos_getdrive(&disk2); -#else - disk2 = _getdrive(); -#endif - - if (disk == disk2) { - FiosItem *fios = _fios_items.Append(); - fios->type = FIOS_TYPE_DRIVE; - fios->mtime = 0; -#ifndef __INNOTEK_LIBC__ - snprintf(fios->name, lengthof(fios->name), "%c:", 'A' + disk - 1); -#else - snprintf(fios->name, lengthof(fios->name), "%c:", disk); -#endif - strecpy(fios->title, fios->name, lastof(fios->title)); - } - } - - /* Restore the original drive */ -#ifndef __INNOTEK_LIBC__ - _dos_setdrive(save, &total); -#else - chdir(wd); -#endif -} - -bool FiosGetDiskFreeSpace(const char *path, uint64 *tot) -{ -#ifndef __INNOTEK_LIBC__ - struct diskfree_t free; - char drive = path[0] - 'A' + 1; - - if (tot != NULL && _getdiskfree(drive, &free) == 0) { - *tot = free.avail_clusters * free.sectors_per_cluster * free.bytes_per_sector; - return true; - } - - return false; -#else - uint64 free = 0; - -#ifdef HAS_STATVFS - { - struct statvfs s; - - if (statvfs(path, &s) != 0) return false; - free = (uint64)s.f_frsize * s.f_bavail; - } -#endif - if (tot != NULL) *tot = free; - return true; -#endif -} - -bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) -{ - char filename[MAX_PATH]; - - snprintf(filename, lengthof(filename), "%s" PATHSEP "%s", path, ent->d_name); - return stat(filename, sb) == 0; -} - -bool FiosIsHiddenFile(const struct dirent *ent) -{ - return ent->d_name[0] == '.'; -} - -void ShowInfo(const char *str) -{ - HAB hab; - HMQ hmq; - ULONG rc; - - /* init PM env. */ - hmq = WinCreateMsgQueue((hab = WinInitialize(0)), 0); - - /* display the box */ - rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, (const unsigned char *)str, (const unsigned char *)"OpenTTD", 0, MB_OK | MB_MOVEABLE | MB_INFORMATION); - - /* terminate PM env. */ - WinDestroyMsgQueue(hmq); - WinTerminate(hab); -} - -void ShowOSErrorBox(const char *buf, bool system) -{ - HAB hab; - HMQ hmq; - ULONG rc; - - /* init PM env. */ - hmq = WinCreateMsgQueue((hab = WinInitialize(0)), 0); - - /* display the box */ - rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, (const unsigned char *)buf, (const unsigned char *)"OpenTTD", 0, MB_OK | MB_MOVEABLE | MB_ERROR); - - /* terminate PM env. */ - WinDestroyMsgQueue(hmq); - WinTerminate(hab); -} - -int CDECL main(int argc, char *argv[]) -{ - SetRandomSeed(time(NULL)); - - return ttd_main(argc, argv); -} - -/** - * Insert a chunk of text from the clipboard onto the textbuffer. Get TEXT clipboard - * and append this up to the maximum length (either absolute or screenlength). If maxlength - * is zero, we don't care about the screenlength but only about the physical length of the string - * @param tb Textbuf type to be changed - * @return Return true on successful change of Textbuf, or false otherwise - */ -bool InsertTextBufferClipboard(Textbuf *tb) -{ -/* XXX -- Currently no clipboard support implemented with GCC */ -#ifndef __INNOTEK_LIBC__ - HAB hab = 0; - - if (WinOpenClipbrd(hab)) - { - const char *text = (const char*)WinQueryClipbrdData(hab, CF_TEXT); - - if (text != NULL) - { - uint length = 0; - uint width = 0; - const char *i; - - for (i = text; IsValidAsciiChar(*i); i++) - { - uint w; - - if (tb->size + length + 1 > tb->maxsize) break; - - w = GetCharacterWidth(FS_NORMAL, (byte)*i); - if (tb->maxwidth != 0 && width + tb->width + w > tb->maxwidth) break; - - width += w; - length++; - } - - memmove(tb->buf + tb->caretpos + length, tb->buf + tb->caretpos, tb->size - tb->caretpos); - memcpy(tb->buf + tb->caretpos, text, length); - tb->width += width; - tb->caretxoffs += width; - tb->size += length; - tb->caretpos += length; - - WinCloseClipbrd(hab); - return true; - } - - WinCloseClipbrd(hab); - } -#endif - return false; -} - - -void CSleep(int milliseconds) -{ -#ifndef __INNOTEK_LIBC__ - delay(milliseconds); -#else - usleep(milliseconds * 1000); -#endif -} - -const char *FS2OTTD(const char *name) {return name;} -const char *OTTD2FS(const char *name) {return name;} diff --git a/src/ottdres.rc.in b/src/ottdres.rc.in deleted file mode 100644 index f0989f5bb..000000000 --- a/src/ottdres.rc.in +++ /dev/null @@ -1,111 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// $Id$ -// -// This file is part of OpenTTD. -// OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. -// OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . -// -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#define APSTUDIO_READONLY_SYMBOLS -#define APSTUDIO_HIDDEN_SYMBOLS -#include "windows.h" -#undef APSTUDIO_HIDDEN_SYMBOLS -#ifdef MSVC -#include "winres.h" -#else -#define IDC_STATIC (-1) // all static controls -#endif - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Neutral (Default) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD) -#ifdef _WIN32 -LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -100 ICON DISCARDABLE "../media/openttd.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -100 DIALOG DISCARDABLE 0, 0, 305, 77 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Fatal Application Failure" -FONT 8, "MS Sans Serif" -BEGIN - PUSHBUTTON "&Close",12,7,58,50,14 -// PUSHBUTTON "&Submit report",14,81,58,68,14,WS_DISABLED - PUSHBUTTON "&Emergency save",13,155,58,68,14 - PUSHBUTTON "",15,243,58,55,14 - EDITTEXT 11,7,79,291,118,ES_MULTILINE | ES_READONLY | WS_VSCROLL | - WS_HSCROLL | NOT WS_TABSTOP - LTEXT "",10,36,7,262,43 - ICON 100,IDC_STATIC,9,9,20,20 -END - - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,8,0,!!REVISION!! - PRODUCTVERSION 0,8,0,!!REVISION!! - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "Comments", "This program is licensed under the GNU General Public License.\0" - VALUE "CompanyName", "OpenTTD Development Team\0" - VALUE "FileDescription", "OpenTTD\0" - VALUE "FileVersion", "Development !!VERSION!!\0" - VALUE "InternalName", "openttd\0" - VALUE "LegalCopyright", "Copyright \xA9 OpenTTD Developers 2002-2009. All Rights Reserved.\0" - VALUE "LegalTrademarks", "\0" - VALUE "OriginalFilename", "openttd.exe\0" - VALUE "PrivateBuild", "\0" - VALUE "ProductName", "OpenTTD\0" - VALUE "ProductVersion", "Development !!VERSION!!\0" - VALUE "SpecialBuild", "-\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END - -#endif // !_MAC - -#endif // Neutral (Default) resources -///////////////////////////////////////////////////////////////////////////// diff --git a/src/unix.cpp b/src/unix.cpp deleted file mode 100644 index dc55a3a37..000000000 --- a/src/unix.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/* $Id$ */ - -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file unix.cpp Implementation of Unix specific file handling. */ - -#include "stdafx.h" -#include "openttd.h" -#include "variables.h" -#include "textbuf_gui.h" -#include "functions.h" -#include "core/random_func.hpp" - -#include "table/strings.h" - -#include -#include -#include -#include -#include - -#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__) - #define HAS_STATVFS -#endif - -#ifdef HAS_STATVFS -#include -#endif - - -#ifdef __MORPHOS__ -#include -ULONG __stack = (1024*1024)*2; // maybe not that much is needed actually ;) - -/* The system supplied definition of SIG_IGN does not match */ -#undef SIG_IGN -#define SIG_IGN (void (*)(int))1 -#endif /* __MORPHOS__ */ - -#ifdef __AMIGA__ -#warning add stack symbol to avoid that user needs to set stack manually (tokai) -// ULONG __stack = -#endif - -#if defined(__APPLE__) - #if defined(WITH_SDL) - /* the mac implementation needs this file included in the same file as main() */ - #include - #endif -#endif - -bool FiosIsRoot(const char *path) -{ -#if !defined(__MORPHOS__) && !defined(__AMIGAOS__) - return path[1] == '\0'; -#else - /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */ - const char *s = strchr(path, ':'); - return s != NULL && s[1] == '\0'; -#endif -} - -void FiosGetDrives() -{ - return; -} - -bool FiosGetDiskFreeSpace(const char *path, uint64 *tot) -{ - uint64 free = 0; - -#ifdef HAS_STATVFS -# ifdef __APPLE__ - /* OSX 10.3 lacks statvfs so don't try to use it even though later versions of OSX has it. */ - if (MacOSVersionIsAtLeast(10, 4, 0)) -# endif - { - struct statvfs s; - - if (statvfs(path, &s) != 0) return false; - free = (uint64)s.f_frsize * s.f_bavail; - } -#endif - if (tot != NULL) *tot = free; - return true; -} - -bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) -{ - char filename[MAX_PATH]; - -#if defined(__MORPHOS__) || defined(__AMIGAOS__) - /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */ - if (FiosIsRoot(path)) { - snprintf(filename, lengthof(filename), "%s:%s", path, ent->d_name); - } else // XXX - only next line! -#else - assert(path[strlen(path) - 1] == PATHSEPCHAR); - if (strlen(path) > 2) assert(path[strlen(path) - 2] != PATHSEPCHAR); -#endif - snprintf(filename, lengthof(filename), "%s%s", path, ent->d_name); - - return stat(filename, sb) == 0; -} - -bool FiosIsHiddenFile(const struct dirent *ent) -{ - return ent->d_name[0] == '.'; -} - -#ifdef WITH_ICONV - -#include -#include -#include "debug.h" -#include "string_func.h" - -const char *GetCurrentLocale(const char *param); - -#define INTERNALCODE "UTF-8" - -/** Try and try to decipher the current locale from environmental - * variables. MacOSX is hardcoded, other OS's are dynamic. If no suitable - * locale can be found, don't do any conversion "" */ -static const char *GetLocalCode() -{ -#if defined(__APPLE__) - return "UTF-8-MAC"; -#else - /* Strip locale (eg en_US.UTF-8) to only have UTF-8 */ - const char *locale = GetCurrentLocale("LC_CTYPE"); - if (locale != NULL) locale = strchr(locale, '.'); - - return (locale == NULL) ? "" : locale + 1; -#endif -} - -/** FYI: This is not thread-safe. - * convert between locales, which from and which to is set in the calling - * functions OTTD2FS() and FS2OTTD(). You should NOT use this function directly - * NOTE: iconv was added in OSX 10.3. 10.2.x will still have the invalid char - * issues. There aren't any easy fix for this */ -static const char *convert_tofrom_fs(iconv_t convd, const char *name) -{ - static char buf[1024]; - /* Work around buggy iconv implementation where inbuf is wrongly typed as - * non-const. Correct implementation is at - * http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.html */ -#ifdef HAVE_BROKEN_ICONV - char *inbuf = (char*)name; -#else - const char *inbuf = name; -#endif - - char *outbuf = buf; - size_t outlen = sizeof(buf) - 1; - size_t inlen = strlen(name); - - strecpy(outbuf, name, outbuf + outlen); - - iconv(convd, NULL, NULL, NULL, NULL); - if (iconv(convd, &inbuf, &inlen, &outbuf, &outlen) == (size_t)(-1)) { - DEBUG(misc, 0, "[iconv] error converting '%s'. Errno %d", name, errno); - } - - *outbuf = '\0'; - /* FIX: invalid characters will abort conversion, but they shouldn't occur? */ - return buf; -} - -/** Convert from OpenTTD's encoding to that of the local environment - * @param name pointer to a valid string that will be converted - * @return pointer to a new stringbuffer that contains the converted string */ -const char *OTTD2FS(const char *name) -{ - static iconv_t convd = (iconv_t)(-1); - - if (convd == (iconv_t)(-1)) { - const char *env = GetLocalCode(); - convd = iconv_open(env, INTERNALCODE); - if (convd == (iconv_t)(-1)) { - DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", INTERNALCODE, env); - return name; - } - } - - return convert_tofrom_fs(convd, name); -} - -/** Convert to OpenTTD's encoding from that of the local environment - * @param name pointer to a valid string that will be converted - * @return pointer to a new stringbuffer that contains the converted string */ -const char *FS2OTTD(const char *name) -{ - static iconv_t convd = (iconv_t)(-1); - - if (convd == (iconv_t)(-1)) { - const char *env = GetLocalCode(); - convd = iconv_open(INTERNALCODE, env); - if (convd == (iconv_t)(-1)) { - DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", env, INTERNALCODE); - return name; - } - } - - return convert_tofrom_fs(convd, name); -} - -#else -const char *FS2OTTD(const char *name) {return name;} -const char *OTTD2FS(const char *name) {return name;} -#endif /* WITH_ICONV */ - -void ShowInfo(const char *str) -{ - fprintf(stderr, "%s\n", str); -} - -void ShowOSErrorBox(const char *buf, bool system) -{ -#if defined(__APPLE__) - /* this creates an NSAlertPanel with the contents of 'buf' - * this is the native and nicest way to do this on OSX */ - ShowMacDialog( buf, "See readme for more info\nMost likely you are missing files from the original TTD", "Quit" ); -#else - /* All unix systems, except OSX. Only use escape codes on a TTY. */ - if (isatty(fileno(stderr))) { - fprintf(stderr, "\033[1;31mError: %s\033[0;39m\n", buf); - } else { - fprintf(stderr, "Error: %s\n", buf); - } -#endif -} - -#ifdef WITH_COCOA -void cocoaSetupAutoreleasePool(); -void cocoaReleaseAutoreleasePool(); -#endif - -int CDECL main(int argc, char *argv[]) -{ - int ret; - -#ifdef WITH_COCOA - cocoaSetupAutoreleasePool(); - /* This is passed if we are launched by double-clicking */ - if (argc >= 2 && strncmp(argv[1], "-psn", 4) == 0) { - argv[1] = NULL; - argc = 1; - } -#endif - - SetRandomSeed(time(NULL)); - - signal(SIGPIPE, SIG_IGN); - - ret = ttd_main(argc, argv); - -#ifdef WITH_COCOA - cocoaReleaseAutoreleasePool(); -#endif - - return ret; -} - -bool InsertTextBufferClipboard(Textbuf *tb) -{ - return false; -} - - -/* multi os compatible sleep function */ - -#ifdef __AMIGA__ -/* usleep() implementation */ -# include -# include - - extern struct Device *TimerBase = NULL; - extern struct MsgPort *TimerPort = NULL; - extern struct timerequest *TimerRequest = NULL; -#endif /* __AMIGA__ */ - -void CSleep(int milliseconds) -{ - #if defined(PSP) - sceKernelDelayThread(milliseconds * 1000); - #elif defined(__BEOS__) - snooze(milliseconds * 1000); - #elif defined(__AMIGA__) - { - ULONG signals; - ULONG TimerSigBit = 1 << TimerPort->mp_SigBit; - - /* send IORequest */ - TimerRequest->tr_node.io_Command = TR_ADDREQUEST; - TimerRequest->tr_time.tv_secs = (milliseconds * 1000) / 1000000; - TimerRequest->tr_time.tv_micro = (milliseconds * 1000) % 1000000; - SendIO((struct IORequest *)TimerRequest); - - if (!((signals = Wait(TimerSigBit | SIGBREAKF_CTRL_C)) & TimerSigBit) ) { - AbortIO((struct IORequest *)TimerRequest); - } - WaitIO((struct IORequest *)TimerRequest); - } - #else - usleep(milliseconds * 1000); - #endif -} diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index fffb86770..efa4295ed 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -13,7 +13,7 @@ #include "../openttd.h" #include "../gfx_func.h" #include "../variables.h" -#include "../win32.h" +#include "../os/windows/win32.h" #include "../rev.h" #include "../blitter/factory.hpp" #include "../network/network.h" diff --git a/src/win32.cpp b/src/win32.cpp deleted file mode 100644 index d262abebd..000000000 --- a/src/win32.cpp +++ /dev/null @@ -1,1378 +0,0 @@ -/* $Id$ */ - -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file win32.cpp Implementation of MS Windows system calls */ - -#include "stdafx.h" -#include "openttd.h" -#include "debug.h" -#include "saveload/saveload.h" -#include "gfx_func.h" -#include "textbuf_gui.h" -#include "fileio_func.h" -#include "fios.h" -#include "rev.h" -#include -#include -#include -#include -#include /* SHGetFolderPath */ -#include "variables.h" -#include "win32.h" -#include "core/alloc_func.hpp" -#include "functions.h" -#include "core/random_func.hpp" -#include "core/bitmath_func.hpp" -#include "string_func.h" -#include "gamelog.h" -#include -#include -#include -#include -#if defined(_MSC_VER) && !defined(WINCE) - #include - #include "strings_func.h" -#endif - -static bool _has_console; - -static bool cursor_visible = true; - -bool MyShowCursor(bool show) -{ - if (cursor_visible == show) return show; - - cursor_visible = show; - ShowCursor(show); - - return !show; -} - -/** Helper function needed by dynamically loading libraries - * XXX: Hurray for MS only having an ANSI GetProcAddress function - * on normal windows and no Wide version except for in Windows Mobile/CE */ -bool LoadLibraryList(Function proc[], const char *dll) -{ - while (*dll != '\0') { - HMODULE lib; - lib = LoadLibrary(MB_TO_WIDE(dll)); - - if (lib == NULL) return false; - for (;;) { - FARPROC p; - - while (*dll++ != '\0') { /* Nothing */ } - if (*dll == '\0') break; -#if defined(WINCE) - p = GetProcAddress(lib, MB_TO_WIDE(dll)); -#else - p = GetProcAddress(lib, dll); -#endif - if (p == NULL) return false; - *proc++ = (Function)p; - } - dll++; - } - return true; -} - -#ifdef _MSC_VER -static const char *_exception_string = NULL; -void SetExceptionString(const char *s, ...) -{ - va_list va; - char buf[512]; - - va_start(va, s); - vsnprintf(buf, lengthof(buf), s, va); - va_end(va); - - _exception_string = strdup(buf); -} -#endif - -void ShowOSErrorBox(const char *buf, bool system) -{ - MyShowCursor(true); - MessageBox(GetActiveWindow(), MB_TO_WIDE(buf), _T("Error!"), MB_ICONSTOP); - -/* if exception tracker is enabled, we crash here to let the exception handler handle it. */ -#if defined(WIN32_EXCEPTION_TRACKER) && !defined(_DEBUG) - if (system) { - _exception_string = buf; - *(byte*)0 = 0; - } -#endif -} - -#if defined(_MSC_VER) && !defined(WINCE) - -static void *_safe_esp; -static char *_crash_msg; -static bool _expanded; -static bool _did_emerg_save; -static int _ident; - -struct DebugFileInfo { - uint32 size; - uint32 crc32; - SYSTEMTIME file_time; -}; - -static uint32 *_crc_table; - -static void MakeCRCTable(uint32 *table) -{ - uint32 crc, poly = 0xEDB88320L; - int i; - int j; - - _crc_table = table; - - for (i = 0; i != 256; i++) { - crc = i; - for (j = 8; j != 0; j--) { - crc = (crc & 1 ? (crc >> 1) ^ poly : crc >> 1); - } - table[i] = crc; - } -} - -static uint32 CalcCRC(byte *data, uint size, uint32 crc) -{ - for (; size > 0; size--) { - crc = ((crc >> 8) & 0x00FFFFFF) ^ _crc_table[(crc ^ *data++) & 0xFF]; - } - return crc; -} - -static void GetFileInfo(DebugFileInfo *dfi, const TCHAR *filename) -{ - HANDLE file; - memset(dfi, 0, sizeof(*dfi)); - - file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); - if (file != INVALID_HANDLE_VALUE) { - byte buffer[1024]; - DWORD numread; - uint32 filesize = 0; - FILETIME write_time; - uint32 crc = (uint32)-1; - - for (;;) { - if (ReadFile(file, buffer, sizeof(buffer), &numread, NULL) == 0 || numread == 0) - break; - filesize += numread; - crc = CalcCRC(buffer, numread, crc); - } - dfi->size = filesize; - dfi->crc32 = crc ^ (uint32)-1; - - if (GetFileTime(file, NULL, NULL, &write_time)) { - FileTimeToSystemTime(&write_time, &dfi->file_time); - } - CloseHandle(file); - } -} - - -static char *PrintModuleInfo(char *output, const char *last, HMODULE mod) -{ - TCHAR buffer[MAX_PATH]; - DebugFileInfo dfi; - - GetModuleFileName(mod, buffer, MAX_PATH); - GetFileInfo(&dfi, buffer); - output += seprintf(output, last, " %-20s handle: %p size: %d crc: %.8X date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n", - WIDE_TO_MB(buffer), - mod, - dfi.size, - dfi.crc32, - dfi.file_time.wYear, - dfi.file_time.wMonth, - dfi.file_time.wDay, - dfi.file_time.wHour, - dfi.file_time.wMinute, - dfi.file_time.wSecond - ); - return output; -} - -static char *PrintModuleList(char *output, const char *last) -{ - BOOL (WINAPI *EnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD); - - if (LoadLibraryList((Function*)&EnumProcessModules, "psapi.dll\0EnumProcessModules\0\0")) { - HMODULE modules[100]; - DWORD needed; - BOOL res; - - HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); - if (proc != NULL) { - res = EnumProcessModules(proc, modules, sizeof(modules), &needed); - CloseHandle(proc); - if (res) { - size_t count = min(needed / sizeof(HMODULE), lengthof(modules)); - - for (size_t i = 0; i != count; i++) output = PrintModuleInfo(output, last, modules[i]); - return output; - } - } - } - output = PrintModuleInfo(output, last, NULL); - return output; -} - -static const TCHAR _crash_desc[] = - _T("A serious fault condition occured in the game. The game will shut down.\n") - _T("Please send the crash information and the crash.dmp file (if any) to the developers.\n") - _T("This will greatly help debugging. The correct place to do this is http://bugs.openttd.org. ") - _T("The information contained in the report is displayed below.\n") - _T("Press \"Emergency save\" to attempt saving the game."); - -static const TCHAR _save_succeeded[] = - _T("Emergency save succeeded.\n") - _T("Be aware that critical parts of the internal game state may have become ") - _T("corrupted. The saved game is not guaranteed to work."); - -static const TCHAR _emergency_crash[] = - _T("A serious fault condition occured in the game. The game will shut down.\n") - _T("As you loaded an emergency savegame no crash information will be generated.\n"); - -static bool EmergencySave() -{ - GamelogStartAction(GLAT_EMERGENCY); - GamelogEmergency(); - GamelogStopAction(); - SaveOrLoad("crash.sav", SL_SAVE, BASE_DIR); - return true; -} - -/* Disable the crash-save submit code as it's not used */ -#if 0 - -struct WinInetProcs { - HINTERNET (WINAPI *InternetOpen)(LPCTSTR, DWORD, LPCTSTR, LPCTSTR, DWORD); - HINTERNET (WINAPI *InternetConnect)(HINTERNET, LPCTSTR, INTERNET_PORT, LPCTSTR, LPCTSTR, DWORD, DWORD, DWORD); - HINTERNET (WINAPI *HttpOpenRequest)(HINTERNET, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR *, DWORD, DWORD); - BOOL (WINAPI *HttpSendRequest)(HINTERNET, LPCTSTR, DWORD, LPVOID, DWORD); - BOOL (WINAPI *InternetCloseHandle)(HINTERNET); - BOOL (WINAPI *HttpQueryInfo)(HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD); -}; - -#define M(x) x "\0" -#if defined(UNICODE) -# define W(x) x "W" -#else -# define W(x) x "A" -#endif -static const char wininet_files[] = - M("wininet.dll") - M(W("InternetOpen")) - M(W("InternetConnect")) - M(W("HttpOpenRequest")) - M(W("HttpSendRequest")) - M("InternetCloseHandle") - M(W("HttpQueryInfo")) - M(""); -#undef W -#undef M - -static WinInetProcs _wininet; - -static const TCHAR *SubmitCrashReport(HWND wnd, void *msg, size_t msglen, const TCHAR *arg) -{ - HINTERNET inet, conn, http; - const TCHAR *err = NULL; - DWORD code, len; - static TCHAR buf[100]; - TCHAR buff[100]; - - if (_wininet.InternetOpen == NULL && !LoadLibraryList((Function*)&_wininet, wininet_files)) return _T("can't load wininet.dll"); - - inet = _wininet.InternetOpen(_T("OTTD"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ); - if (inet == NULL) { err = _T("internetopen failed"); goto error1; } - - conn = _wininet.InternetConnect(inet, _T("www.openttd.org"), INTERNET_DEFAULT_HTTP_PORT, _T(""), _T(""), INTERNET_SERVICE_HTTP, 0, 0); - if (conn == NULL) { err = _T("internetconnect failed"); goto error2; } - - _sntprintf(buff, lengthof(buff), _T("/crash.php?file=%s&ident=%d"), arg, _ident); - - http = _wininet.HttpOpenRequest(conn, _T("POST"), buff, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE , 0); - if (http == NULL) { err = _T("httpopenrequest failed"); goto error3; } - - if (!_wininet.HttpSendRequest(http, _T("Content-type: application/binary"), -1, msg, (DWORD)msglen)) { err = _T("httpsendrequest failed"); goto error4; } - - len = sizeof(code); - if (!_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &code, &len, 0)) { err = _T("httpqueryinfo failed"); goto error4; } - - if (code != 200) { - int l = _sntprintf(buf, lengthof(buf), _T("Server said: %d "), code); - len = sizeof(buf) - l; - _wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_TEXT, buf + l, &len, 0); - err = buf; - } - -error4: - _wininet.InternetCloseHandle(http); -error3: - _wininet.InternetCloseHandle(conn); -error2: - _wininet.InternetCloseHandle(inet); -error1: - return err; -} - -static void SubmitFile(HWND wnd, const TCHAR *file) -{ - HANDLE h; - unsigned long size; - unsigned long read; - void *mem; - - h = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (h == NULL) return; - - size = GetFileSize(h, NULL); - if (size > 500000) goto error1; - - mem = MallocT(size); - if (mem == NULL) goto error1; - - if (!ReadFile(h, mem, size, &read, NULL) || read != size) goto error2; - - SubmitCrashReport(wnd, mem, size, file); - -error2: - free(mem); -error1: - CloseHandle(h); -} - -#endif /* Disabled crash-submit procedures */ - -static const TCHAR * const _expand_texts[] = {_T("S&how report >>"), _T("&Hide report <<") }; - -static void SetWndSize(HWND wnd, int mode) -{ - RECT r, r2; - int offs; - - GetWindowRect(wnd, &r); - - SetDlgItemText(wnd, 15, _expand_texts[mode == 1]); - - if (mode >= 0) { - GetWindowRect(GetDlgItem(wnd, 11), &r2); - offs = r2.bottom - r2.top + 10; - if (!mode) offs = -offs; - SetWindowPos(wnd, HWND_TOPMOST, 0, 0, - r.right - r.left, r.bottom - r.top + offs, SWP_NOMOVE | SWP_NOZORDER); - } else { - SetWindowPos(wnd, HWND_TOPMOST, - (GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left)) / 2, - (GetSystemMetrics(SM_CYSCREEN) - (r.bottom - r.top)) / 2, - 0, 0, SWP_NOSIZE); - } -} - -static bool DoEmergencySave(HWND wnd) -{ - bool b = false; - - EnableWindow(GetDlgItem(wnd, 13), FALSE); - _did_emerg_save = true; - __try { - b = EmergencySave(); - } __except (1) {} - return b; -} - -static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_INITDIALOG: { -#if defined(UNICODE) - /* We need to put the crash-log in a seperate buffer because the default - * buffer in MB_TO_WIDE is not large enough (512 chars) */ - wchar_t crash_msgW[8096]; -#endif - SetDlgItemText(wnd, 10, _crash_desc); - SetDlgItemText(wnd, 11, MB_TO_WIDE_BUFFER(_crash_msg, crash_msgW, lengthof(crash_msgW))); - SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE); - SetWndSize(wnd, -1); - } return TRUE; - case WM_COMMAND: - switch (wParam) { - case 12: // Close - ExitProcess(0); - case 13: // Emergency save - if (DoEmergencySave(wnd)) { - MessageBox(wnd, _save_succeeded, _T("Save successful"), MB_ICONINFORMATION); - } else { - MessageBox(wnd, _T("Save failed"), _T("Save failed"), MB_ICONINFORMATION); - } - break; -/* Disable the crash-save submit code as it's not used */ -#if 0 - case 14: { // Submit crash report - const TCHAR *s; - - SetCursor(LoadCursor(NULL, IDC_WAIT)); - - s = SubmitCrashReport(wnd, _crash_msg, strlen(_crash_msg), _T("")); - if (s != NULL) { - MessageBox(wnd, s, _T("Error"), MB_ICONSTOP); - break; - } - - /* try to submit emergency savegame */ - if (_did_emerg_save || DoEmergencySave(wnd)) SubmitFile(wnd, _T("crash.sav")); - - /* try to submit the autosaved game */ - if (_opt.autosave) { - TCHAR buf[40]; - _sntprintf(buf, lengthof(buf), _T("autosave%d.sav"), (_autosave_ctr - 1) & 3); - SubmitFile(wnd, buf); - } - EnableWindow(GetDlgItem(wnd, 14), FALSE); - SetCursor(LoadCursor(NULL, IDC_ARROW)); - MessageBox(wnd, _T("Crash report submitted. Thank you."), _T("Crash Report"), MB_ICONINFORMATION); - } break; -#endif /* Disabled crash-submit procedures */ - case 15: // Expand window to show crash-message - _expanded ^= 1; - SetWndSize(wnd, _expanded); - break; - } - return TRUE; - case WM_CLOSE: ExitProcess(0); - } - - return FALSE; -} - -static void Handler2() -{ - ShowCursor(TRUE); - ShowWindow(GetActiveWindow(), FALSE); - DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(100), NULL, CrashDialogFunc); -} - -extern bool CloseConsoleLogIfActive(); - -static HANDLE _file_crash_log; - -static void GamelogPrintCrashLogProc(const char *s) -{ - DWORD num_written; - WriteFile(_file_crash_log, s, (DWORD)strlen(s), &num_written, NULL); - WriteFile(_file_crash_log, "\r\n", (DWORD)strlen("\r\n"), &num_written, NULL); -} - -/** Amount of output for the execption handler. */ -static const int EXCEPTION_OUTPUT_SIZE = 8192; - -static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) -{ - char *output; - static bool had_exception = false; - - if (had_exception) ExitProcess(0); - if (GamelogTestEmergency()) { - MessageBox(NULL, _emergency_crash, _T("Fatal Application Failure"), MB_ICONERROR); - ExitProcess(0); - } - had_exception = true; - - _ident = GetTickCount(); // something pretty unique - - MakeCRCTable(AllocaM(uint32, 256)); - _crash_msg = output = (char*)LocalAlloc(LMEM_FIXED, EXCEPTION_OUTPUT_SIZE); - const char *last = output + EXCEPTION_OUTPUT_SIZE - 1; - - { - SYSTEMTIME time; - GetLocalTime(&time); - output += seprintf(output, last, - "*** OpenTTD Crash Report ***\r\n" - "Date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n" - "Build: %s (%d) built on " __DATE__ " " __TIME__ "\r\n", - time.wYear, - time.wMonth, - time.wDay, - time.wHour, - time.wMinute, - time.wSecond, - _openttd_revision, - _openttd_revision_modified - ); - } - - if (_exception_string) - output += seprintf(output, last, "Reason: %s\r\n", _exception_string); - - output += seprintf(output, last, "Language: %s\r\n", _dynlang.curr_file); - -#ifdef _M_AMD64 - output += seprintf(output, last, "Exception %.8X at %.16IX\r\n" - "Registers:\r\n" - "RAX: %.16llX RBX: %.16llX RCX: %.16llX RDX: %.16llX\r\n" - "RSI: %.16llX RDI: %.16llX RBP: %.16llX RSP: %.16llX\r\n" - "R8: %.16llX R9: %.16llX R10: %.16llX R11: %.16llX\r\n" - "R12: %.16llX R13: %.16llX R14: %.16llX R15: %.16llX\r\n" - "RIP: %.16llX EFLAGS: %.8X\r\n" - "\r\nBytes at CS:RIP:\r\n", - ep->ExceptionRecord->ExceptionCode, - ep->ExceptionRecord->ExceptionAddress, - ep->ContextRecord->Rax, - ep->ContextRecord->Rbx, - ep->ContextRecord->Rcx, - ep->ContextRecord->Rdx, - ep->ContextRecord->Rsi, - ep->ContextRecord->Rdi, - ep->ContextRecord->Rbp, - ep->ContextRecord->Rsp, - ep->ContextRecord->R8, - ep->ContextRecord->R9, - ep->ContextRecord->R10, - ep->ContextRecord->R11, - ep->ContextRecord->R12, - ep->ContextRecord->R13, - ep->ContextRecord->R14, - ep->ContextRecord->R15, - ep->ContextRecord->Rip, - ep->ContextRecord->EFlags - ); -#else - output += seprintf(output, last, "Exception %.8X at %.8p\r\n" - "Registers:\r\n" - " EAX: %.8X EBX: %.8X ECX: %.8X EDX: %.8X\r\n" - " ESI: %.8X EDI: %.8X EBP: %.8X ESP: %.8X\r\n" - " EIP: %.8X EFLAGS: %.8X\r\n" - "\r\nBytes at CS:EIP:\r\n", - ep->ExceptionRecord->ExceptionCode, - ep->ExceptionRecord->ExceptionAddress, - ep->ContextRecord->Eax, - ep->ContextRecord->Ebx, - ep->ContextRecord->Ecx, - ep->ContextRecord->Edx, - ep->ContextRecord->Esi, - ep->ContextRecord->Edi, - ep->ContextRecord->Ebp, - ep->ContextRecord->Esp, - ep->ContextRecord->Eip, - ep->ContextRecord->EFlags - ); -#endif - - { -#ifdef _M_AMD64 - byte *b = (byte*)ep->ContextRecord->Rip; -#else - byte *b = (byte*)ep->ContextRecord->Eip; -#endif - int i; - for (i = 0; i != 24; i++) { - if (IsBadReadPtr(b, 1)) { - output += seprintf(output, last, " ??"); // OCR: WAS: , 0); - } else { - output += seprintf(output, last, " %.2X", *b); - } - b++; - } - output += seprintf(output, last, - "\r\n" - "\r\nStack trace: \r\n" - ); - } - - { - int i, j; -#ifdef _M_AMD64 - uint32 *b = (uint32*)ep->ContextRecord->Rsp; -#else - uint32 *b = (uint32*)ep->ContextRecord->Esp; -#endif - for (j = 0; j != 24; j++) { - for (i = 0; i != 8; i++) { - if (IsBadReadPtr(b, sizeof(uint32))) { - output += seprintf(output, last, " ????????"); // OCR: WAS - , 0); - } else { - output += seprintf(output, last, " %.8X", *b); - } - b++; - } - output += seprintf(output, last, "\r\n"); - } - } - - output += seprintf(output, last, "\r\nModule information:\r\n"); - output = PrintModuleList(output, last); - - { - _OSVERSIONINFOA os; - os.dwOSVersionInfoSize = sizeof(os); - GetVersionExA(&os); - output += seprintf(output, last, "\r\nSystem information:\r\n" - " Windows version %d.%d %d %s\r\n\r\n", - os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber, os.szCSDVersion); - } - - _file_crash_log = CreateFile(_T("crash.log"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); - - if (_file_crash_log != INVALID_HANDLE_VALUE) { - DWORD num_written; - WriteFile(_file_crash_log, _crash_msg, output - _crash_msg, &num_written, NULL); - } - -#if !defined(_DEBUG) - HMODULE dbghelp = LoadLibrary(_T("dbghelp.dll")); - if (dbghelp != NULL) { - typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE, - MINIDUMP_TYPE, - CONST PMINIDUMP_EXCEPTION_INFORMATION, - CONST PMINIDUMP_USER_STREAM_INFORMATION, - CONST PMINIDUMP_CALLBACK_INFORMATION); - MiniDumpWriteDump_t funcMiniDumpWriteDump = (MiniDumpWriteDump_t)GetProcAddress(dbghelp, "MiniDumpWriteDump"); - if (funcMiniDumpWriteDump != NULL) { - HANDLE file = CreateFile(_T("crash.dmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); - HANDLE proc = GetCurrentProcess(); - DWORD procid = GetCurrentProcessId(); - MINIDUMP_EXCEPTION_INFORMATION mdei; - MINIDUMP_USER_STREAM userstream; - MINIDUMP_USER_STREAM_INFORMATION musi; - char msg[] = "****** Built on " __DATE__ " " __TIME__ ". ******"; - - userstream.Type = LastReservedStream + 1; - userstream.Buffer = msg; - userstream.BufferSize = sizeof(msg); - - musi.UserStreamCount = 1; - musi.UserStreamArray = &userstream; - - mdei.ThreadId = GetCurrentThreadId(); - mdei.ExceptionPointers = ep; - mdei.ClientPointers = false; - - funcMiniDumpWriteDump(proc, procid, file, MiniDumpWithDataSegs, &mdei, &musi, NULL); - } - FreeLibrary(dbghelp); - } -#endif - - if (_file_crash_log != INVALID_HANDLE_VALUE) { - GamelogPrint(&GamelogPrintCrashLogProc); - CloseHandle(_file_crash_log); - } - - /* Close any possible log files */ - CloseConsoleLogIfActive(); - - if (_safe_esp) { -#ifdef _M_AMD64 - ep->ContextRecord->Rip = (DWORD64)Handler2; - ep->ContextRecord->Rsp = (DWORD64)_safe_esp; -#else - ep->ContextRecord->Eip = (DWORD)Handler2; - ep->ContextRecord->Esp = (DWORD)_safe_esp; -#endif - return EXCEPTION_CONTINUE_EXECUTION; - } - - - return EXCEPTION_EXECUTE_HANDLER; -} - -#ifdef _M_AMD64 -extern "C" void *_get_safe_esp(); -#endif - -static void Win32InitializeExceptions() -{ -#ifdef _M_AMD64 - _safe_esp = _get_safe_esp(); -#else - _asm { - mov _safe_esp, esp - } -#endif - - SetUnhandledExceptionFilter(ExceptionHandler); -} -#endif /* _MSC_VER */ - -/* Code below for windows version of opendir/readdir/closedir copied and - * modified from Jan Wassenberg's GPL implementation posted over at - * http://www.gamedev.net/community/forums/topic.asp?topic_id=364584&whichpage=1� */ - -/* suballocator - satisfies most requests with a reusable static instance. - * this avoids hundreds of alloc/free which would fragment the heap. - * To guarantee concurrency, we fall back to malloc if the instance is - * already in use (it's important to avoid suprises since this is such a - * low-level routine). */ -static DIR _global_dir; -static LONG _global_dir_is_in_use = false; - -static inline DIR *dir_calloc() -{ - DIR *d; - - if (InterlockedExchange(&_global_dir_is_in_use, true) == (LONG)true) { - d = CallocT(1); - } else { - d = &_global_dir; - memset(d, 0, sizeof(*d)); - } - return d; -} - -static inline void dir_free(DIR *d) -{ - if (d == &_global_dir) { - _global_dir_is_in_use = (LONG)false; - } else { - free(d); - } -} - -DIR *opendir(const TCHAR *path) -{ - DIR *d; - UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box - DWORD fa = GetFileAttributes(path); - - if ((fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY)) { - d = dir_calloc(); - if (d != NULL) { - TCHAR search_path[MAX_PATH]; - bool slash = path[_tcslen(path) - 1] == '\\'; - - /* build search path for FindFirstFile, try not to append additional slashes - * as it throws Win9x off its groove for root directories */ - _sntprintf(search_path, lengthof(search_path), _T("%s%s*"), path, slash ? _T("") : _T("\\")); - *lastof(search_path) = '\0'; - d->hFind = FindFirstFile(search_path, &d->fd); - - if (d->hFind != INVALID_HANDLE_VALUE || - GetLastError() == ERROR_NO_MORE_FILES) { // the directory is empty - d->ent.dir = d; - d->at_first_entry = true; - } else { - dir_free(d); - d = NULL; - } - } else { - errno = ENOMEM; - } - } else { - /* path not found or not a directory */ - d = NULL; - errno = ENOENT; - } - - SetErrorMode(sem); // restore previous setting - return d; -} - -struct dirent *readdir(DIR *d) -{ - DWORD prev_err = GetLastError(); // avoid polluting last error - - if (d->at_first_entry) { - /* the directory was empty when opened */ - if (d->hFind == INVALID_HANDLE_VALUE) return NULL; - d->at_first_entry = false; - } else if (!FindNextFile(d->hFind, &d->fd)) { // determine cause and bail - if (GetLastError() == ERROR_NO_MORE_FILES) SetLastError(prev_err); - return NULL; - } - - /* This entry has passed all checks; return information about it. - * (note: d_name is a pointer; see struct dirent definition) */ - d->ent.d_name = d->fd.cFileName; - return &d->ent; -} - -int closedir(DIR *d) -{ - FindClose(d->hFind); - dir_free(d); - return 0; -} - -bool FiosIsRoot(const char *file) -{ - return file[3] == '\0'; // C:\... -} - -void FiosGetDrives() -{ -#if defined(WINCE) - /* WinCE only knows one drive: / */ - FiosItem *fios = _fios_items.Append(); - fios->type = FIOS_TYPE_DRIVE; - fios->mtime = 0; - snprintf(fios->name, lengthof(fios->name), PATHSEP ""); - strecpy(fios->title, fios->name, lastof(fios->title)); -#else - TCHAR drives[256]; - const TCHAR *s; - - GetLogicalDriveStrings(lengthof(drives), drives); - for (s = drives; *s != '\0';) { - FiosItem *fios = _fios_items.Append(); - fios->type = FIOS_TYPE_DRIVE; - fios->mtime = 0; - snprintf(fios->name, lengthof(fios->name), "%c:", s[0] & 0xFF); - strecpy(fios->title, fios->name, lastof(fios->title)); - while (*s++ != '\0') { /* Nothing */ } - } -#endif -} - -bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb) -{ - /* hectonanoseconds between Windows and POSIX epoch */ - static const int64 posix_epoch_hns = 0x019DB1DED53E8000LL; - const WIN32_FIND_DATA *fd = &ent->dir->fd; - - sb->st_size = ((uint64) fd->nFileSizeHigh << 32) + fd->nFileSizeLow; - /* UTC FILETIME to seconds-since-1970 UTC - * we just have to subtract POSIX epoch and scale down to units of seconds. - * http://www.gamedev.net/community/forums/topic.asp?topic_id=294070&whichpage=1� - * XXX - not entirely correct, since filetimes on FAT aren't UTC but local, - * this won't entirely be correct, but we use the time only for comparsion. */ - sb->st_mtime = (time_t)((*(uint64*)&fd->ftLastWriteTime - posix_epoch_hns) / 1E7); - sb->st_mode = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)? S_IFDIR : S_IFREG; - - return true; -} - -bool FiosIsHiddenFile(const struct dirent *ent) -{ - return (ent->dir->fd.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0; -} - -bool FiosGetDiskFreeSpace(const char *path, uint64 *tot) -{ - UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box - bool retval = false; - TCHAR root[4]; - DWORD spc, bps, nfc, tnc; - - _sntprintf(root, lengthof(root), _T("%c:") _T(PATHSEP), path[0]); - if (tot != NULL && GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) { - *tot = ((spc * bps) * (uint64)nfc); - retval = true; - } - - SetErrorMode(sem); // reset previous setting - return retval; -} - -static int ParseCommandLine(char *line, char **argv, int max_argc) -{ - int n = 0; - - do { - /* skip whitespace */ - while (*line == ' ' || *line == '\t') line++; - - /* end? */ - if (*line == '\0') break; - - /* special handling when quoted */ - if (*line == '"') { - argv[n++] = ++line; - while (*line != '"') { - if (*line == '\0') return n; - line++; - } - } else { - argv[n++] = line; - while (*line != ' ' && *line != '\t') { - if (*line == '\0') return n; - line++; - } - } - *line++ = '\0'; - } while (n != max_argc); - - return n; -} - -void CreateConsole() -{ -#if defined(WINCE) - /* WinCE doesn't support console stuff */ -#else - HANDLE hand; - CONSOLE_SCREEN_BUFFER_INFO coninfo; - - if (_has_console) return; - _has_console = true; - - AllocConsole(); - - hand = GetStdHandle(STD_OUTPUT_HANDLE); - GetConsoleScreenBufferInfo(hand, &coninfo); - coninfo.dwSize.Y = 500; - SetConsoleScreenBufferSize(hand, coninfo.dwSize); - - /* redirect unbuffered STDIN, STDOUT, STDERR to the console */ -#if !defined(__CYGWIN__) - *stdout = *_fdopen( _open_osfhandle((intptr_t)hand, _O_TEXT), "w" ); - *stdin = *_fdopen(_open_osfhandle((intptr_t)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "r" ); - *stderr = *_fdopen(_open_osfhandle((intptr_t)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w" ); -#else - /* open_osfhandle is not in cygwin */ - *stdout = *fdopen(1, "w" ); - *stdin = *fdopen(0, "r" ); - *stderr = *fdopen(2, "w" ); -#endif - - setvbuf(stdin, NULL, _IONBF, 0); - setvbuf(stdout, NULL, _IONBF, 0); - setvbuf(stderr, NULL, _IONBF, 0); -#endif -} - -void ShowInfo(const char *str) -{ - if (_has_console) { - fprintf(stderr, "%s\n", str); - } else { - bool old; -#if defined(UNICODE) - /* We need to put the text in a seperate buffer because the default - * buffer in MB_TO_WIDE might not be large enough (512 chars) */ - wchar_t help_msgW[8192]; -#endif - ReleaseCapture(); - _left_button_clicked = _left_button_down = false; - - old = MyShowCursor(true); - if (MessageBox(GetActiveWindow(), MB_TO_WIDE_BUFFER(str, help_msgW, lengthof(help_msgW)), _T("OpenTTD"), MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL) { - CreateConsole(); - } - MyShowCursor(old); - } -} - -#if defined(WINCE) -int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) -#else -int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) -#endif -{ - int argc; - char *argv[64]; // max 64 command line arguments - char *cmdline; - -#if !defined(UNICODE) - _codepage = GetACP(); // get system codepage as some kind of a default -#endif /* UNICODE */ - -#if defined(UNICODE) - -#if !defined(WINCE) - /* Check if a win9x user started the win32 version */ - if (HasBit(GetVersion(), 31)) usererror("This version of OpenTTD doesn't run on windows 95/98/ME.\nPlease download the win9x binary and try again."); -#endif - - /* For UNICODE we need to convert the commandline to char* _AND_ - * save it because argv[] points into this buffer and thus needs to - * be available between subsequent calls to FS2OTTD() */ - char cmdlinebuf[MAX_PATH]; -#endif /* UNICODE */ - - cmdline = WIDE_TO_MB_BUFFER(GetCommandLine(), cmdlinebuf, lengthof(cmdlinebuf)); - -#if defined(_DEBUG) - CreateConsole(); -#endif - -#if !defined(WINCE) - _set_error_mode(_OUT_TO_MSGBOX); // force assertion output to messagebox -#endif - - /* setup random seed to something quite random */ - SetRandomSeed(GetTickCount()); - - argc = ParseCommandLine(cmdline, argv, lengthof(argv)); - -#if defined(WIN32_EXCEPTION_TRACKER) - Win32InitializeExceptions(); -#endif - -#if defined(WIN32_EXCEPTION_TRACKER_DEBUG) - _try { - LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep); -#endif - ttd_main(argc, argv); - -#if defined(WIN32_EXCEPTION_TRACKER_DEBUG) - } _except (ExceptionHandler(_exception_info())) {} -#endif - - return 0; -} - -#if defined(WINCE) -void GetCurrentDirectoryW(int length, wchar_t *path) -{ - /* Get the name of this module */ - GetModuleFileName(NULL, path, length); - - /* Remove the executable name, this we call CurrentDir */ - wchar_t *pDest = wcsrchr(path, '\\'); - if (pDest != NULL) { - int result = pDest - path + 1; - path[result] = '\0'; - } -} -#endif - -char *getcwd(char *buf, size_t size) -{ -#if defined(WINCE) - TCHAR path[MAX_PATH]; - GetModuleFileName(NULL, path, MAX_PATH); - convert_from_fs(path, buf, size); - /* GetModuleFileName returns dir with file, so remove everything behind latest '\\' */ - char *p = strrchr(buf, '\\'); - if (p != NULL) *p = '\0'; -#elif defined(UNICODE) - TCHAR path[MAX_PATH]; - GetCurrentDirectory(MAX_PATH - 1, path); - convert_from_fs(path, buf, size); -#else - GetCurrentDirectory(size, buf); -#endif - return buf; -} - - -void DetermineBasePaths(const char *exe) -{ - char tmp[MAX_PATH]; - TCHAR path[MAX_PATH]; -#ifdef WITH_PERSONAL_DIR - SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path); - strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp)); - AppendPathSeparator(tmp, MAX_PATH); - ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH); - AppendPathSeparator(tmp, MAX_PATH); - _searchpaths[SP_PERSONAL_DIR] = strdup(tmp); - - SHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path); - strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp)); - AppendPathSeparator(tmp, MAX_PATH); - ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH); - AppendPathSeparator(tmp, MAX_PATH); - _searchpaths[SP_SHARED_DIR] = strdup(tmp); -#else - _searchpaths[SP_PERSONAL_DIR] = NULL; - _searchpaths[SP_SHARED_DIR] = NULL; -#endif - - /* Get the path to working directory of OpenTTD */ - getcwd(tmp, lengthof(tmp)); - AppendPathSeparator(tmp, MAX_PATH); - _searchpaths[SP_WORKING_DIR] = strdup(tmp); - - if (!GetModuleFileName(NULL, path, lengthof(path))) { - DEBUG(misc, 0, "GetModuleFileName failed (%lu)\n", GetLastError()); - _searchpaths[SP_BINARY_DIR] = NULL; - } else { - TCHAR exec_dir[MAX_PATH]; - _tcsncpy(path, MB_TO_WIDE_BUFFER(exe, path, lengthof(path)), lengthof(path)); - if (!GetFullPathName(path, lengthof(exec_dir), exec_dir, NULL)) { - DEBUG(misc, 0, "GetFullPathName failed (%lu)\n", GetLastError()); - _searchpaths[SP_BINARY_DIR] = NULL; - } else { - strecpy(tmp, WIDE_TO_MB_BUFFER(exec_dir, tmp, lengthof(tmp)), lastof(tmp)); - char *s = strrchr(tmp, PATHSEPCHAR); - *(s + 1) = '\0'; - _searchpaths[SP_BINARY_DIR] = strdup(tmp); - } - } - - _searchpaths[SP_INSTALLATION_DIR] = NULL; - _searchpaths[SP_APPLICATION_BUNDLE_DIR] = NULL; -} - -/** - * Insert a chunk of text from the clipboard onto the textbuffer. Get TEXT clipboard - * and append this up to the maximum length (either absolute or screenlength). If maxlength - * is zero, we don't care about the screenlength but only about the physical length of the string - * @param tb Textbuf type to be changed - * @return true on successful change of Textbuf, or false otherwise - */ -bool InsertTextBufferClipboard(Textbuf *tb) -{ - HGLOBAL cbuf; - char utf8_buf[512]; - const char *ptr; - - WChar c; - uint16 width, length; - - if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { - OpenClipboard(NULL); - cbuf = GetClipboardData(CF_UNICODETEXT); - - ptr = (const char*)GlobalLock(cbuf); - const char *ret = convert_from_fs((wchar_t*)ptr, utf8_buf, lengthof(utf8_buf)); - GlobalUnlock(cbuf); - CloseClipboard(); - - if (*ret == '\0') return false; -#if !defined(UNICODE) - } else if (IsClipboardFormatAvailable(CF_TEXT)) { - OpenClipboard(NULL); - cbuf = GetClipboardData(CF_TEXT); - - ptr = (const char*)GlobalLock(cbuf); - strecpy(utf8_buf, FS2OTTD(ptr), lastof(utf8_buf)); - - GlobalUnlock(cbuf); - CloseClipboard(); -#endif /* UNICODE */ - } else { - return false; - } - - width = length = 0; - - for (ptr = utf8_buf; (c = Utf8Consume(&ptr)) != '\0';) { - if (!IsPrintable(c)) break; - - byte len = Utf8CharLen(c); - if (tb->size + length + len > tb->maxsize) break; - - byte charwidth = GetCharacterWidth(FS_NORMAL, c); - if (tb->maxwidth != 0 && width + tb->width + charwidth > tb->maxwidth) break; - - width += charwidth; - length += len; - } - - if (length == 0) return false; - - memmove(tb->buf + tb->caretpos + length, tb->buf + tb->caretpos, tb->size - tb->caretpos); - memcpy(tb->buf + tb->caretpos, utf8_buf, length); - tb->width += width; - tb->caretxoffs += width; - - tb->size += length; - tb->caretpos += length; - assert(tb->size <= tb->maxsize); - tb->buf[tb->size - 1] = '\0'; // terminating zero - - return true; -} - - -void CSleep(int milliseconds) -{ - Sleep(milliseconds); -} - - -/** Utility function to get the current timestamp in milliseconds - * Useful for profiling */ -int64 GetTS() -{ - static double freq; - __int64 value; - if (!freq) { - QueryPerformanceFrequency((LARGE_INTEGER*)&value); - freq = (double)1000000 / value; - } - QueryPerformanceCounter((LARGE_INTEGER*)&value); - return (__int64)(value * freq); -} - - -/** - * Convert to OpenTTD's encoding from that of the local environment. - * When the project is built in UNICODE, the system codepage is irrelevant and - * the input string is wide. In ANSI mode, the string is in the - * local codepage which we'll convert to wide-char, and then to UTF-8. - * OpenTTD internal encoding is UTF8. - * The returned value's contents can only be guaranteed until the next call to - * this function. So if the value is needed for anything else, use convert_from_fs - * @param name pointer to a valid string that will be converted (local, or wide) - * @return pointer to the converted string; if failed string is of zero-length - * @see the current code-page comes from video\win32_v.cpp, event-notification - * WM_INPUTLANGCHANGE */ -const char *FS2OTTD(const TCHAR *name) -{ - static char utf8_buf[512]; -#if defined(UNICODE) - return convert_from_fs(name, utf8_buf, lengthof(utf8_buf)); -#else - char *s = utf8_buf; - - for (; *name != '\0'; name++) { - wchar_t w; - int len = MultiByteToWideChar(_codepage, 0, name, 1, &w, 1); - if (len != 1) { - DEBUG(misc, 0, "[utf8] M2W error converting '%c'. Errno %lu", *name, GetLastError()); - continue; - } - - if (s + Utf8CharLen(w) >= lastof(utf8_buf)) break; - s += Utf8Encode(s, w); - } - - *s = '\0'; - return utf8_buf; -#endif /* UNICODE */ -} - -/** - * Convert from OpenTTD's encoding to that of the local environment. - * When the project is built in UNICODE the system codepage is irrelevant and - * the converted string is wide. In ANSI mode, the UTF8 string is converted - * to multi-byte. - * OpenTTD internal encoding is UTF8. - * The returned value's contents can only be guaranteed until the next call to - * this function. So if the value is needed for anything else, use convert_from_fs - * @param name pointer to a valid string that will be converted (UTF8) - * @return pointer to the converted string; if failed string is of zero-length - * @see the current code-page comes from video\win32_v.cpp, event-notification - * WM_INPUTLANGCHANGE */ -const TCHAR *OTTD2FS(const char *name) -{ - static TCHAR system_buf[512]; -#if defined(UNICODE) - return convert_to_fs(name, system_buf, lengthof(system_buf)); -#else - char *s = system_buf; - - for (WChar c; (c = Utf8Consume(&name)) != '\0';) { - if (s >= lastof(system_buf)) break; - - char mb; - int len = WideCharToMultiByte(_codepage, 0, (wchar_t*)&c, 1, &mb, 1, NULL, NULL); - if (len != 1) { - DEBUG(misc, 0, "[utf8] W2M error converting '0x%X'. Errno %lu", c, GetLastError()); - continue; - } - - *s++ = mb; - } - - *s = '\0'; - return system_buf; -#endif /* UNICODE */ -} - - -/** Convert to OpenTTD's encoding from that of the environment in - * UNICODE. OpenTTD encoding is UTF8, local is wide - * @param name pointer to a valid string that will be converted - * @param utf8_buf pointer to a valid buffer that will receive the converted string - * @param buflen length in characters of the receiving buffer - * @return pointer to utf8_buf. If conversion fails the string is of zero-length */ -char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen) -{ - int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, utf8_buf, (int)buflen, NULL, NULL); - if (len == 0) { - DEBUG(misc, 0, "[utf8] W2M error converting wide-string. Errno %lu", GetLastError()); - utf8_buf[0] = '\0'; - } - - return utf8_buf; -} - - -/** Convert from OpenTTD's encoding to that of the environment in - * UNICODE. OpenTTD encoding is UTF8, local is wide - * @param name pointer to a valid string that will be converted - * @param utf16_buf pointer to a valid wide-char buffer that will receive the - * converted string - * @param buflen length in wide characters of the receiving buffer - * @return pointer to utf16_buf. If conversion fails the string is of zero-length */ -wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen) -{ - int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, utf16_buf, (int)buflen); - if (len == 0) { - DEBUG(misc, 0, "[utf8] M2W error converting '%s'. Errno %lu", name, GetLastError()); - utf16_buf[0] = '\0'; - } - - return utf16_buf; -} - -/** Our very own SHGetFolderPath function for support of windows operating - * systems that don't have this function (eg Win9x, etc.). We try using the - * native function, and if that doesn't exist we will try a more crude approach - * of environment variables and hope for the best */ -HRESULT OTTDSHGetFolderPath(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath) -{ - static HRESULT (WINAPI *SHGetFolderPath)(HWND, int, HANDLE, DWORD, LPTSTR) = NULL; - static bool first_time = true; - - /* We only try to load the library one time; if it fails, it fails */ - if (first_time) { -#if defined(UNICODE) -# define W(x) x "W" -#else -# define W(x) x "A" -#endif - if (!LoadLibraryList((Function*)&SHGetFolderPath, "SHFolder.dll\0" W("SHGetFolderPath") "\0\0")) { - DEBUG(misc, 0, "Unable to load " W("SHGetFolderPath") "from SHFolder.dll"); - } -#undef W - first_time = false; - } - - if (SHGetFolderPath != NULL) return SHGetFolderPath(hwnd, csidl, hToken, dwFlags, pszPath); - - /* SHGetFolderPath doesn't exist, try a more conservative approach, - * eg environment variables. This is only included for legacy modes - * MSDN says: that 'pszPath' is a "Pointer to a null-terminated string of - * length MAX_PATH which will receive the path" so let's assume that - * Windows 95 with Internet Explorer 5.0, Windows 98 with Internet Explorer 5.0, - * Windows 98 Second Edition (SE), Windows NT 4.0 with Internet Explorer 5.0, - * Windows NT 4.0 with Service Pack 4 (SP4) */ - { - DWORD ret; - switch (csidl) { - case CSIDL_FONTS: // Get the system font path, eg %WINDIR%\Fonts - ret = GetEnvironmentVariable(_T("WINDIR"), pszPath, MAX_PATH); - if (ret == 0) break; - _tcsncat(pszPath, _T("\\Fonts"), MAX_PATH); - - return (HRESULT)0; - break; - /* XXX - other types to go here when needed... */ - } - } - - return E_INVALIDARG; -} - -/** Determine the current user's locale. */ -const char *GetCurrentLocale(const char *) -{ - char lang[9], country[9]; - if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, lang, lengthof(lang)) == 0 || - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, country, lengthof(country)) == 0) { - /* Unable to retrieve the locale. */ - return NULL; - } - /* Format it as 'en_us'. */ - static char retbuf[6] = {lang[0], lang[1], '_', country[0], country[1], 0}; - return retbuf; -} diff --git a/src/win32.h b/src/win32.h deleted file mode 100644 index 19f04d1f2..000000000 --- a/src/win32.h +++ /dev/null @@ -1,55 +0,0 @@ -/* $Id$ */ - -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file win32.h declarations of functions for MS windows systems */ - -#ifndef WIN32_H -#define WIN32_H - -#include -bool MyShowCursor(bool show); - -typedef void (*Function)(int); -bool LoadLibraryList(Function proc[], const char *dll); - -char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen); -wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen); - -/* Function shortcuts for UTF-8 <> UNICODE conversion. When unicode is not - * defined these macros return the string passed to them, with UNICODE - * they return a pointer to the converted string. The only difference between - * XX_TO_YY and XX_TO_YY_BUFFER is that with the buffer variant you can - * specify where to put the converted string (and how long it can be). Without - * the buffer and internal buffer is used, of max 512 characters */ -#if defined(UNICODE) -# define MB_TO_WIDE(str) OTTD2FS(str) -# define MB_TO_WIDE_BUFFER(str, buffer, buflen) convert_to_fs(str, buffer, buflen) -# define WIDE_TO_MB(str) FS2OTTD(str) -# define WIDE_TO_MB_BUFFER(str, buffer, buflen) convert_from_fs(str, buffer, buflen) -#else -extern uint _codepage; // local code-page in the system @see win32_v.cpp:WM_INPUTLANGCHANGE -# define MB_TO_WIDE(str) (str) -# define MB_TO_WIDE_BUFFER(str, buffer, buflen) (str) -# define WIDE_TO_MB(str) (str) -# define WIDE_TO_MB_BUFFER(str, buffer, buflen) (str) -#endif - -/* Override SHGetFolderPath with our custom implementation */ -#if defined(SHGetFolderPath) -#undef SHGetFolderPath -#endif -#define SHGetFolderPath OTTDSHGetFolderPath - -HRESULT OTTDSHGetFolderPath(HWND, int, HANDLE, DWORD, LPTSTR); - -#if defined(__MINGW32__) -#define SHGFP_TYPE_CURRENT 0 -#endif /* __MINGW32__ */ - -#endif /* WIN32_H */ diff --git a/src/win64.asm b/src/win64.asm deleted file mode 100644 index d95bc3898..000000000 --- a/src/win64.asm +++ /dev/null @@ -1,8 +0,0 @@ - .CODE - -PUBLIC _get_safe_esp -_get_safe_esp: - MOV RAX,RSP - RET - - END -- cgit v1.2.3-70-g09d2