Forum:Please port to older Windows versions

From NetHackWiki
Jump to navigation Jump to search


Hi, could someone please port the newly released vanilla NetHack 3.6.0 to older Windows versions such as Windows XP, and have it also work on older CPUs (my CPU is an AMD Sempron 2800+ which doesn't support the SSE2 instruction set)? If you use the GNU GCC compiler for Windows (I recommend MinGW instead of Cygwin, and in particular recommend the MinGW distribution called TDM-GCC and suggest the 32-bit version), well that will produce executables that work as far back as Windows 98 and Windows NT 4.0 on CPUs as far back as the 386, while still being perfectly compatible with the newest 64-bit Windows 10. The best IDE for C/C++ on either Windows or Linux (not Mac OS X though sorry) is Code::Blocks and its Windows version integrates very well with TDM-GCC. In fact Code::Blocks provides builds that have TDM-GCC bundled with it (if you use an older version of Code::Blocks with a newer version of TDM-GCC you'll have problems). Right now other than the nightly builds there is also a release candidate out right now for the latest Code::Blocks which should work fine with the latest TDM-GCC (the last stable Code::Blocks from 2013 obviously doesn't work with the latest TDM-GCC from 2015). I'd suggest the latest Code::Blocks 15.12 Release Candidate 1 (WITHOUT bundled MinGW) as the IDE, used with the latest TDM-GCC 32-bit bundle 5.1.0-3 distribution of MinGW-GCC as the compiler. That oughta be able to compile NetHack 3.6.0 or anything else written in C or C++, even stuff using the latest language features like C11 or C++14, and compile it so it works even on really old computers.

Anyway someone please compile and build a NetHack 3.6.0 port for older 32-bit Windows versions, for people who aren't using Windows 7 yet. With the above instructions you ought to be able to build NetHack 3.6.0 to run on any Windows version as far back as Windows 98 (maybe even 95?) or Windows NT 4.0 on any CPU as far back as a 386. That'll be fine not just for me with my early-2005 32-bit AMD CPU running Windows XP, but people on computers from back in the 1990s still running Windows 9x if there are still any of those around (I've seen stuff online from Windows 98 enthusiasts who apparently still exist and still use Windows 98 even today in 2015, so if you think I am out of date using Windows XP just think about the Windows 98 enthusiast community, or for that matter, the people who still use DOS).

Porting NetHack to all sorts of platforms has always been a big part of its history so not even having a version that works on 32-bit Windows XP is kinda ridiculous. Anyway I think it's likely plenty of NetHack developers or developers of various NetHack variants might read this and have the programming skills to pull it off (there might be some compiler warnings and/or errors and only folks like you who know the NetHack code inside and out would have an easy time of getting things to work). I'm more of a C++ developer than a vanilla C developer and I have a tough time with memory management in vanilla C plus I don't know the NetHack source code and it takes awhile to get up to speed on a project so I figured someone else might be better suited to getting this compiled correctly than me. Anyway thanks for reading this everyone, I hope one of ya manages to port this to older versions of 32-bit Windows. Oh, and for the people who program variants... it'd also be nice if you compiled your variants to work on older versions of Windows and work with older CPUs, and didn't use Microsoft's compilers, instead using the trusty MinGW-GCC compilers, specifically the handy TDM-GCC distribution which is all-in-one and works quite well.

Oh and hopefully NetHack 3.6.0 doesn't use any APIs that require Windows 7 or later or Vista or later such as DirectX 11. If so that would make things tougher as the last version of DirectX supported by Windows XP (as well as Windows 98, ME, and 2000) is DirectX 9.0c. That's just one example of a new API in the Windows NT 6.x kernel that might possibly be used in NetHack 3.6.0 and prevent it from being compatible with Windows XP or even older versions. Hopefully NetHack 3.6.0 uses as few new APIs as possible... it's still written in vanilla C, I think, and it's written to be cross-platform, so I don't expect they would use too many new APIs from Windows.

--Yetisyny (talk) 11:17, 15 December 2015 (UTC)

Open source developers, as a rule, are more easily persuaded by neat ideas and some code than by just neat ideas. You furthermore have something very important to such an effort that I don't -- access to a box running the targeted version of Windows. I have nothing functional that runs Windows XP.
I don't know if NetHack uses anything much other than the bare-bones Win32 API. It certainly doesn't use any version of DirectX.
The fix for W343-3 is to call a Unicode API instead of the ANSI one. When I composed the patch, I still had Windows 98 handy, and put in a check for Windows 9x to avoid calling that Unicode API on Windows 9x. The check is present in NetHack 3.6.0: search sys/winnt/nttty.c for the variable name has_unicode. I conclude that the DevTeam has not intentionally broken compatibility with older versions of Windows.
Perhaps the binary distribution will work just fine. Or you might try compiling from source, and posting any errors here.--Ray Chason (talk) 01:50, 16 December 2015 (UTC)
Aha, I've tested it on another Windows XP computer with a more modern CPU and found out the REAL source of this problem. Actually the incompatibility wasn't the operating system at all. It works perfectly fine on Windows XP computers if their CPUs support the SSE2 instruction set. The reason it wasn't working was that the computer I usually use not only runs Windows XP but has a 32-bit AMD Sempron 2800+ CPU (equivalent to an AMD Athlon XP 2800+ and supposedly equivalent to a Pentium 4 2.8 GHz, except for the fact that Pentium 4's support the SSE2 instruction set and Athlon XPs and 32-bit Semprons don't).
Microsoft Visual C and Visual C++ prior to the 2012 version (i.e. the 2010 version and earlier) by default target the IA32/Pentium Pro/i686 CPU architecture. See here for architecture targeting in Microsoft Visual C and C++ 2010, the last version whose default CPU target was IA32/Pentium Pro/i686. Microsoft Visual C and C++ in the 2012 and later versions (including the 2013 version that it seems NetHack 3.6.0 is compiled with) by default target the SSE2/Pentium IV/pentium4 architecture (and AMD chips didn't support all of the instruction sets of this architecture until AMD64 chips came out, with SSE2 introduced at the same time as 64-bit instructions to the AMD product line, meaning no 32-bit AMD chip supports SSE2, and AMD began its transition from 32-bit to 64-bit in late 2003 and finished it in early 2005). See here for architecture targeting in Microsoft Visual C and C++ 2013 version, which is the version that the DevTeam used to compile NetHack 3.6.0.
So what is necessary is to use the "/arch:IA32" option as specified here for the Microsoft Visual C 2013 project... and to NOT specify any architecture to target for the Microsoft Visual C 2010 project since if you do specify one it will require newer CPUs and Visual C 2010 didn't have "/arch:IA32" as an option since it was the default prior to the 2012 version.
The easiest, safest way to do it is through the GUI of Microsoft Visual Studio 2013 and is explained here. Specifically, to do it from the IDE of Microsoft Visual Studio 2013, open the Property Pages dialog box for the project, select the Configuration Properties, C/C++ folder, select the Code Generation property page, and modify the Enable Enhanced Instruction Set property so that it is set to IA32, and do that with every single one of the Visual C 2013 project files in /win/win32/vs2013.
A more difficult method that can be done through any text editor can be done by modifying the .vcxproj files in the /win/win32/vs2013 directory and making sure that every time there is a <ClCompile> for a 32-bit build (not 64-bit), inside that there is an <AdditionalOptions> that has "/arch:IA32" as one of the options prior to the "%" at the end of the list of additional options. So for example, under a <ClCompile>, if you find an <AdditionalOptions> such as "<AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>", you would change it to "<AdditionalOptions>/arch:IA32 /FS %(AdditionalOptions)</AdditionalOptions>", by adding in "/arch:IA32 " right after <AdditionalOptions>. And if you find a <ClCompile> that doesn't have an <AdditionalOptions> element inside it, you'd put in a line that says "<AdditionalOptions>/arch:IA32 %(AdditionalOptions)</AdditionalOptions>". There are also <AdditionalOptions> sections inside <Link> sections but in those you shouldn't add the "/arch:IA32"... it only goes in the <ClCompile> sections. And this is only for the Visual C 2013 project files in /win/win32/vs2013, not the Visual C 2010 project files in /win/win32/vs2010. The Visual C 2010 project files in /win/win32/vs2010 are fine the way they are already and don't need modifications. For an example of a .vcxproj file that has the correct "/arch:IA32" option in all the right places, this code from another open-source project's .vcxproj file has it done correctly in the way it is done in Visual Studio 2012, 2013, and 2015.
Anyway this is what is needed to fix the incompatibility with older CPUs (such as ALL 32-bit AMD chips ever made, along with pre-Pentium IV Intel chips). It just requires those simple changes to the Visual C 2013 project files, either through the IDE of Microsoft Visual Studio 2013 or by making the edits I specified above to the .vcxproj files in the /win/win32/vs2013 directory of NetHack 3.6.0's source code. Doing this using the IDE of Microsoft Visual Studio 2013 is probably safer than doing it by hand-editing the .vcxproj files in a text editor so I'd recommend that method as the preferred one out of the 2 I described. The only advantage of hand-editing the .vcxproj files is that it doesn't require Microsoft Visual Studio 2013 and can be done simply by using a text editor, although you have to be a lot more careful with that method not to mess anything else up in those files.
In some good news, there isn't any operating system incompatibility AT ALL with the latest NetHack 3.6.0 and Windows XP or Windows Vista. It is a CPU incompatibility, not an operating system incompatibility, according to some testing I have done on various computers. The current NetHack 3.6.0 binaries work perfectly fine on any computer with Windows XP or later, as long as the computer has an Intel or AMD CPU that supports the SSE2 instruction set. And if the fix I propose here is adopted, the SSE2 instruction set won't be required anymore and all that'll be required is Windows XP or later. By the way, the SSE2 instruction set didn't become a system requirement for Windows itself until Windows 8.1. All versions of Windows up through the original 8.0 do not require SSE2. So making it a requirement for NetHack is not a good idea. Anyway, the ACTUAL system requirements for the current binaries aren't Windows 7 or later, they're Windows XP or later plus a CPU that supports the SSE2 instruction set.
Well I'd like to submit this as a bugfix to the official NetHack DevTeam. I think with this amount of information they can take care of the rest of it themselves, and then it won't require SSE2 anymore and will work on ANY computer with Windows XP or later.
As far as compiling a build that would work on even older versions of Windows that are pre-XP, I think that's obviously a lower priority than getting this incompatibility problem fixed, since reducing the CPU requirement from SSE2 to just 32-bit x86 doesn't require anyone to switch compilers, it just means fixing the .vcxproj files to have the right options for the compiler, which is pretty simple to do from the IDE of Microsoft Visual Studio 2013.
Sorry about initially getting the cause of the incompatibility wrong in my first post... there's no operating system incompatibility with Windows XP at all, it's a CPU incompatibility with CPUs that don't support the SSE2 instruction set. I was mostly misled into thinking it was an OS incompatibility because I was going by what the NetHack website said about system requirements, rather than actually testing it out on different computers to find out for real what the actual requirements are, something I've done since then.
--Yetisyny (talk) 12:34, 16 December 2015 (UTC)
I have just submitted a bug report to the DevTeam using the Contact page at nethack dot org containing a summary of the above information about the SSE2 incompatibility and the fact that it actually is compatible with XP and Vista (and submitting it under my real name rather than an online alias). The ID number for my message is '#H4097', in case anyone here is a member of the DevTeam and wants to know which message was submitted by the me posting here as Yetisyny, so that you can tell I am the same person.
--Yetisyny (talk) 05:13, 17 December 2015 (UTC)
I got a response from the DevTeam. They only list Windows 7 and later because they only list the platforms they are absolutely sure their binaries will run on. They will look into this SSE2 thing and they've said they might implement it by the time they do their next release (i.e. the next one after 3.6.0) but will not do it for 3.6.0, and in the meantime, they said that people who want to compile builds for older CPUs can do it themselves (like I did). They said they don't have anyone in their DevTeam who has a suitable non-SSE2 machine for testing on so they aren't entirely sure what they will do but they thanked me for my detailed bug report. I think it's likely they'll fix it in the next official release but not entirely guaranteed, they didn't make any promises but I'm hopeful, given the fact that they fixed almost all known bugs from 3.4.3 when 3.6.0 was released, which means they have a pretty good track record of fixing bugs, although of course nothing is guaranteed.
--Yetisyny (talk) 17:16, 19 December 2015 (UTC)

More news: I compiled NetHack 3.6.0 for 32-bit or 64-bit Windows using TDM-GCC 5.1.0 and compilation options to optimize for minimal file size (options like -Os and -s, with GCC, and using the strip command afterwards) and further reduced file size using the free open-source UPX software, and packaged it in a 7z archive (use the free open-source program 7-zip to unpack it, 7z archives have better compression than zip, rar, etc.). It should work on anything as far back as Windows 98 or Windows NT 4.0 and it might possibly work on Windows 95, and its only CPU requirement should be a 386 or later. The download link is here: https://www.sendspace.com/file/23ir4k. That is a temporary download link that lasts for 30 days (from December 16, 2015 to either January 14 or 15, 2015). My specific build options were "cflags = -mms-bitfields -fomit-frame-pointer -Os -mtune=generic -m32" and "lflags = -fomit-frame-pointer -Os -mtune=generic -m32" which I changed in Makefile.gcc, then after building I used the "strip -s" command to strip unnecessary info from the files and then I used UPX 3.91w with the "--best --ultra-brute --compress-icons=0" options to compress the files afterwards, then I used 7-zip 15.12 for the compression with the highest maximum settings... and for the non-executable files I used the ones from the Windows download so that the line-endings would be correct for the Windows platform (the line-endings for the non-executable files that come with the source code all have UNIX-style line endings which don't show up correctly in Windows Notepad).

Anyway the download link is https://www.sendspace.com/file/23ir4k and there you can get a version that works fine in older versions of 32-bit or 64-bit Windows and older CPUs, going back to Windows NT 4.0, Windows 98, and 386 CPUs, and it's compressed to take up as little disk space as possible.

The downside to the small size is it doesn't have any debugging information in the files, this is more aimed at end users than people who run things in symbolic debuggers, since people who know how to use symbolic debuggers also know how to compile their own binaries. If you don't trust my binary for whatever reason just follow my instructions from the last paragraph and build your own using the NetHack 3.6.0 source code (follow what it says in the README, including running the /sys/winnt/nhsetup.bat batch file, then modify the Makefile.gcc file in the /src directory with the cflags and lflags I list above, then run the MinGW make command exactly how it says in the instructions in /sys/winnt/Install.nt, then copy over the files that don't have .exe or .dll extensions from the Windows binary distribution of 3.6.0 from nethack.org into your /binary directory (but don't overwrite the .exe or .dll files!), then run "strip -s" on all your .dll and .exe files, then run UPX 3.91w with the options from that previous paragraph on all the .dll and .exe files, then pack it up into a .7z or .zip or .rar or whatever archive format you prefer, if ya want to do this yourself.

And if you want to be able to use a debugger just leave out the steps about changing the cflags and lflags in Makefile.gcc, using "strip -s", and using UPX, don't do ANY of those 3 extra steps, just follow the directions in the source code EXACTLY (other than the extra step of copying the non-.dll and non-.exe files from the Windows binary distribution into your /binary directory so that the line-endings are correct, that step is still necessary). Your executable files will be 10 times as big, but they'll have all the debugging information you need. Kinda pointless if you ask me since I don't use symbolic debuggers and file size bloat kinda bugs me, but whatever floats your boat. Anyway it turns out an IDE (integrated development environment) isn't even needed, all you need to compile and build this is TDM-GCC from http://tdm-gcc.tdragon.net/. Oh and if for some reason you want to make a 64-bit build you should get the 64-bit version of TDM-GCC, it can make those, but I made a 32-bit build since it works on both 32-bit and 64-bit versions of Windows and there isn't really any advantage to making a 64-bit build other than a very minor performance improvement, at the cost of losing compatibility with all 32-bit editions of Windows. If you want a 64-bit version of it compiled, don't ask me, because I don't have any systems with 64-bit Windows on them so I wouldn't be able to test any 64-bit builds I cross-compiled to see if they actually work.

The build I uploaded to https://www.sendspace.com/file/23ir4k does work, on any 32-bit or 64-bit Windows except possibly it might have problems on Windows 95, only because TDM-GCC 5.1.0 which I compiled it with apparently might not produce executables compatible with Windows 95. Since that download link will expire and disappear after 30 days, in mid-January, automatically, I'd suggest that if anyone really wants my build they download it and then upload it to some other website... I don't really know the best place to host executables, I use that sendspace site because it's easy but the 30-day limit is kind of an annoyance.

--Yetisyny (talk) 15:26, 16 December 2015 (UTC)