So what this means is that now you can make fully standalone Win32/Win64 executables out of CLI based MS-DOS applications.
D:\tcc>msdos\binary\i486_x64\msdos.exe tcc -Iinclude -Llib hi.c
Turbo C++ Version 3.00 Copyright (c) 1992 Borland International
Turbo Link Version 5.0 Copyright (c) 1992 Borland International
Available memory 4215648
D:\tcc>c:msdos\binary\i486_x64\msdos.exe -c hi.exe
‘new_exec_file.exe’ is successfully created
Isn’t that great?
I’ve had one issue with Turbo C++ 3.00 and that is the embedded executable will run out of memory while linking, but invoking it by calling msdos.exe let’s it run fine. If you compile and link separately it’ll run just fine.
While I’m waiting for my real PC-9821 to arrive, I’ve been playing with various software. One fun thing was the old DJGPP, as the version 1.x had a customized version of go32 to support the PC-98 hardware. This is cool, but I’d love to perhaps start down the road of porting something to the PC-98. There is no VGA adapter, and the I/O is mapped differently so naturally this is why they are only loosely compatible. So while I was looking for any kind of source code using DJGPP, I found the FCE: Family Computer Emulator (NES). It includes source code, which is great but it builds against DJGPP 2.x What makes it more interesting is that it has DPMI hooks in place, unlike the old DJGPP 1.x’s DOS extender which is DPMI incompatible. So how do you magically get a DPMI environment for MS-DOS? Well one way is to run it under Windows 3.0 or higher. And certainly with MS-DOS 3.30 that is an option. However lurking in the disk images of MS-DOS 5.00A was a fun program DPMI.EXE . Well now that is interesting!
Using a generic config.sys I have 600kb of low RAM available, and 7MB of extended RAM.
As you can see this is pretty much the 386 enhanced portion of Windows 3.0! So you get all of the DPMI services offered by Windows as part of the OS.
As you can see, with DPMI running I have access to EMS, and XMS memory now available. Additionally with paging you can even over commit memory.
My only question, is why was DPMI not an added in feature of the English versions of MS-DOS? Granted there was a LOT of OEM bundling with new machines so you were forced to purchase a copy of Windows along with MS-DOS on all new computers, regardless of what you were going to do with them, and this would have been a bit more interesting.
This kind of environment was extensively documented in the “Unauthorized Windows 95“, by Andrew Schulman that showed how DOSX.EXE could chain load Win386 + command.com achieving the same thing. The DPMI environment from MS-DOS 5.00A is dated 11/11/1992, I wonder if he knew about this going into the Windows 95 book. It’s been too long since I’ve read it to remember, but I don’t recall any details about Japanese PC-98 releases of MS-DOS. There was also a ‘MSDPMI’ environment created for the beta versions of Microsoft C 7.0, but I’ve been unable to find one to verify. MSC 7.0 was released in 1992, so it fits in the same timeframe, but the shipping products used QEMM’s DPMI server instead.
Binaries are built and tested mostly under Windows Vista Business (SP2)
Source RPMS needed for building Linux to DJGPP cross-compiler
Binary RPMs for both i686 and x86_64 are available. I built these binary RPMs
in CentOS 6.7 chroot under Fedora 23. Binaries are statically linked with GMP-6.1.0
MPFR-3.1.4 and MPC-1.0.3 to avoid unnecessary dependencies and increase
compatibility with other Linux distributions. For example they are expected
to work without problems in other reasonably recent Linux distributions
(like Fedora, RHEL-6 and newer, etc)
gcc610s2.zip is no more provided as patching GCC using DJGPP tools
has not been tested and even attempted by me for a long time.
DJGPP source file gcc610s.zip is a side product of building
gcc-6.1.0 Linux to DJGPP cross-compiler RPM packages. See source
RPM for patches applied to original FSF version of GCC-6.1.0.
You can find the same contents in the file
While I was looking for System16 stuff, I found the first version of MAME to include the UAE 68000 core starting in release MAME 28, although System16 emulation itself didn’t appear until MAME 33b3, but not playable until MAME 33b4.
So what does it mean? Well at the time the UAE core was the way to go. However from looking at the MAME source, the UAE core that they were using from System16 was already generated, while UAE still included the build68k program to parse the tables, and generate the 68000. Instead they were editing the outputted C. UAE wasn’t GPL until version 0.7(something), 0.7.6 for sure, so I don’t know why they weren’t using it from the source.
Eventually starting in MAME 35b2, the core was replaced with MUSASHI , so Among their reasons for dumping the early UAE CPU core was this laundry list:
New 68000 C core. For testing purposes, this is also being used in the DOS
version instead of the asm core. [Karl Stenerud]
1. Faster. This code is, barring ram fetch time, almost twice as fast as the
existing C core in MAME. I’ve done extensive speed profiling on both
engines. The only problem now is the slow memory access in MAME due to
bankswitching et al.
2. Emulation more correct. I found many bugs in the MAME engine (and many,
many more in mine for that matter) when I pitted them head-to-head.
I have run random instructions from each opcode class at least 10 million
times, comparing the resultant CPU states, and have left it running random
instructions for 1 billion iterations. In every case, I have adhered to
the specs defined in M68000PM/AD REV. 1.
3. Disassembler is correct. The current M68000 disassembler in mame has a
tendency to disassemble instructions that have an invalid EA mode.
4. Cycle counting is 99.9% correct. The only instructions which don’t have
correct cycle counts are divs, divu, muls, mulu, and they’re not worth
counting correctly. (I’m not about to waste emulation time counting 0-1 and
5. > 32 bit friendly. I’ve taken care to ensure maximum portability without
sacrificing speed. The result is conditional compiling dependant on your
architecture. I’ve also implemented and tested a compatible solution for
architectures that lack 8, 16, or 32 bit signed storage types.
6. The code is carefully laid out to be readable.
Also in MAME 35b4 added in was emulation of the NEC uPD7759 chip for speech, fleshing out the System16 emulation.
To compile these ancient versions, and inbetween I was using my Candadian cross DJGPP GCC 4.12 Win32 cross compiler. For Allegro I’ve always found it builds far easier using GCC 184.108.40.206, a vintage compiler from back in the day I could just run in DOSBox.
Obviously with today’s machines, these ancient versions of MAME run fine on DOSBox! It’s really amazing in the scope of emulators running emulators.
A long long time ago, back when I got a Pentium 100 the wonderful world of emulation was really starting to be possible with such a high powered CPU. First was the simple Game Boy emulators, then a Commodore 64 emulator, the incredible Amiga Emulator, the beginnings of SIMH (back when it was only a PDP-11 emulator), and then I found the SEGA emulator, System 16.
It was really cool being able to play 16bit arcade games on the desktop, although rather slowly. From there everyone knows the rise of MAME. But while looking around for a small 68000 C compiler, I came across the source code to an older version of System 16, 0.53 on archive.org. Naturally it’s for MS-DOS, as was everything back in the day. Also slightly interesting is the 68000 emulation, written by Bernd Schmitd of UAE fame. So for the heck of it, I set about getting Thierry Lescot’s System 16 building again. I’ve never used allegro before, so it was a bit of a fight to get a version of it to actually build. It turns out that I should have been building version 2.11 with tools of that era (why on earth was I using GCC 4, and binutils 2.18?) and instead stick with GCC 220.127.116.11 and some much older binutils. And in no time I had build the library, and it’s examples. With that done, I was able to re-build System 16 with GCC 4.1.2 and get a binary!
Back in the day, I actually did have an Altered Beast arcade board. Sadly it died in a move, someone near and dear just saw the PCB as “garbage” and tossed it. Sigh, but I did have ROM dumps, as I did a refresh of it forever ago. Anyways I still have the ROM files, so I guess that is nice.
Anyways I fired up the emulator and got what is known as the “jail bar” effect, which is from a bad ROM.
The System 16 splits it’s memory into a program space, a sprite memory bank, a tile memory bank, and RAM for stack and things like the palette. As you can see the program is certainly running, and the sprites are good. I did some poking around a bit later, and noticed that due to a logic bug, the texture ROMs are actually never loaded!
So a quick patch, and now we get Altered Beast up and running!
Well, now isn’t that great!
Not that I would imagine anyone would really care, I mean MAME is a thing, and even from the readme:
Altered Beast : No sound emulation
So it’s pretty quiet. Additionally the source is pretty restrictive:
These sources can’t be used for commercial purpose, any new version of the
emulator done with these sources must specify my name somewhere on the screen
et docs and I must be informed about any new release of the emulator.
The casino computer virus is a malicious virus that upon running the infected file, copies the File Allocation Tables (FATs) to random-access memory (RAM), then deletes the FAT from the hard disk. It challenges the user to a game of Jackpot of which they have 5 credits to play with, hence the name. No matter if they win or lose, the computer shuts down, thereby making them have to reinstall their DOS.
The following is a guest post / wrap-up of the Q2DOS adventure by [HCI]Mara’akate.
In the last update sezero and I([HCI]Mara’akate) tied up most loose ends with regards to Q2DOS. Specifically: adding in DXE support for mods and cleaning up some code from the early efforts. During this time, a forum user by the name of ggorts (strogg spelled backwards!) mentioned the possibility of using an old Mesa version with 3DFX support in DOS. I worked on separating the ref_soft from being statically linked into a DXE form and sezero cleaned up any potential problems there.
I mentioned the possibility of attempting the Mesa port to sezero and he thought it was probably a wasted effort and thought making a ref_glide depending only on glide3x.dxe would be a better way to go with less overhead. I started some initial work on it but quickly abandoned this side-project as I have no real glide (or even OpenGL) knowledge and didn’t have enough time on my hands to play around with it.
Around this time, we also separated the GameSpy browser code into a separate DXE for potential legal issues. The GameSpy code was publicly released, but never officially GPL’d. Using this method, other port authors could link against a gamespy.dll to add in the browser capabilities that connect to my GameSpy master server emulator (see QDOS branch for source code to that particular project).
Ggorts also came up with some code for us to be able to finally use the banked modes and Mode-X 320×240. Though 320×240 Mode-X seems to have some issues with certain emulator configurations, for the most part it works OK. This also helped us to get some ASM rendering code in from Q1 and help clean up the original mess that was the SVGA driver; a lot of unused code from Q1 was removed and sezero found a clever way to send the video modes list between the game binary and renderer DXE.
In any event, one night I figured I’d take a stab at trying to get Mesa working in Q2DOS. Checking out the Mesa3d FTP and researching the various changelogs it appears as if Mesa 5 series was the last true effort with Mesa 6.4.x series being the last maintained version with 3DFX specific code. I got everything to compile but ran into hard-lock issues no matter what I attempted. During this time, ggorts found out some various small, but now obvious issues. Including increasing the stack size to 1MB and he hard-coded the ref_gl to only work in 640×480. It took a lot of pleading but eventually he released his source with a static compile for Voodoo 1 cards only as he was testing this on emulators like DOSBox with glide support and PCem dev branch.
I worked on cleaning up the source and he produced some glide3x libraries for me for Voodoo 2 and Voodoo 5 as these were the only cards I personally owned. Imagine my surprise as I first loaded it up and it actually worked! And it was smooth with no rendering issues!
At this point, sezero became involved and worked very hard to clean up the Mesa compile issues, including various scary warnings and helped to update us to the final glide3x commit pushed to the development branch and Mesa v6.4.3 which was an unreleased maintenance update for Mesa v6.4.2.
It was a long journey to get the code all working together just right, and a big thanks goes out to the early Mesa crew including Brian Paul, Daniel Borca, and “KoolSmoky” and the mysterious ggorts fellow who pushed hard for this feature.
To recap, Q2DOS from the last time we talked now has:
3DFX Rendering with Mesa v6.4.3 for all Voodoo cards.
Separated renderer so it is no longer statically linked.
GameSpy is now a DXE.
WAV streaming, which is practically free as opposed to the OGG format.
We are about at the end of our Q2DOS journey. A few odds and ends with Mesa and Voodoo 5 SLI issues remain (though nothing too show stopping) and there’s a small wishlist of some unnecessary features but it’s come a long way from the initial null driver effort!
I have to say it is simply incredible to see how Q2DOS went from a very primitive ‘wow it works’ port to a full featured port. Simply amazing!
Since the last update we got some help in a few fields that have really fleshed out this ‘experimental’ port into a full fledged port. First RayerR helped us with the fun of getting us onto the latest deployment of DJGPP, 2.05 (rc1). It’s always nice to be in the latest available release. Next in a passing comment, Ruslan Starodubov had mentioned that he had gotten a much older build of our QDOS to support the Intel HDA sound chipset via the MPXPlay sound library. I wrote to the author of MPXPlay, Pádár Attila asking for us to distribute his source in our project, and he granted permission.
So at this point things were looking good. The only ‘feature’ that modern OS’s really held over us was the ability to dynamically load and unload game modules on the fly. I had tried to use DLM, but it stripped the DPMI functionality out of the MS-DOS Extender making the port really useless. I tried to build the newer DXE3 support but had no luck. I suspect now my native tool chain was interfering with the build process. But Maraakate managed to get it to not only build, but to run!
Adding in DX3 support was relatively painless. I first looked at DJGPP’s FAQ and downloaded the example code. In the example code there was small helper functions to make unions and check the symbols. If they didn’t exist a printf was spit out to alert you about it. To resolve the issue you simply just add DXE_EXPORT to the other list of missing exports.
Compiling the game code was easy, again referring to the example I saw that basically they compiled it the same, but at link time you use DX3GEN and -U flag to ignore unresolved symbols.
The biggest head scratcher was the Sys_GetGameAPI failing to find GetGameAPI from the DX3. After some piddling around I noticed that it listed GetGameAPI as _GetGameAPI inside the DX3 itself. I added the underscore and it worked!
Other things that were relatively to easy to import was R1Q2’s HTTP downloading code. Compiling CURL was kind of tricky because of the linking order, but thankfully neozeed figured it out quickly.
All of Yamagi’s Quake 2 updated game DLLs were all diff’d by hand using BeyondCompare to make sure I didn’t clash using some newer functions that weren’t available in DJGPP. I also merged their Zaero code with their baseq2 code by comparing Zaeros code to the Quake 2 SDK, marking every thing that was changed. The result is a really stable Zaero game code. If you haven’t played Zaero check it out. I think it’s a lot better than Rogue, but Xatrix is probably my favourite (even over stock Q2).
Other cool things I’m glad to get into the code was the GameSpy Browser. It took me quite a bit of work to get it where it is, but it’s really nice to just be able to ping to a master server (a custom GameSpy emulator I wrote specifically for Q2DOS. Source is not finalized yet, but will be available soon for those curious), pick a server and go! All in DOS!
So here we are at the end of the journey. Or at least safe enough for a 1.0 release.
To recap, we have:
* SVGA (LFB modes only)
* SoundBlaster and Gravis UltraSound Family
* CD-ROM music
* OGG music
* Networking (You need a packet driver)
* Loading/unloading game DLLs in DX3 format.
* Intel HDA support -hda
* Mouse wheel support with -mwheel
Well it mostly works now. But did we ever have the biggest fun with the sound and SVGA.
So [HCI]Mara’akate integrated all the Q1 sound code, got it to compile, but nothing not a peep from the sound card. While I was busy trashing the video code, he spent way too much time on the audio, and then for the heck of it I thought I’d look at the code, although I’m really stabbing in the dark when it comes to audio. Imagine my surprise when I compiled the code, and ran it and got the sound blasting at full volume! It turns out that I had my audio set to ‘high quality’ in the client, while he had his set to ‘low quality’. What it does is govern the frequency between 11Khz and 22Khz. And if you get this wrong you get *NO* audio. OOPS. At least it was one of those feeling vindicated moments that his efforts for sound really did work.
Now with audio, it was my time to hurry up and get the video going. I had basic VGA working so I figured I didn’t want to spend a lot of time on this, so I was going to go with the VESA 2.0 linear frame buffer. Well this once more again proved to be a bit more involved as the only way I really have to test is emulation via DOSBox and Qemu. And naturally both of them worked fine, but when [HCI]Mara’akate ran it on his real DOS Box (with GUS of course) it crashed wonderfully.
Now I had taken the VESA init code from Quake 1 to build a table of what 8bit modes are supported, and used the VESA code to switch, along with drawing to the buffer with a simple memcpy. And we got nothing but crashes.
After looking more around, I found that you had to add 0x4000 to the VESA mode you want if you wanted to access it’s LFB. Did that work? No still crashed.
Later in the adventure we noticed to get proper access you had enable ‘near pointer acess’ with a call to :
So naturally I would disable it when I’m done, making the call look like this:
WRONG. Oh so WRONG. Well OK technically it did work, but if sound is enabled (and why wouldn’t it be?) it would immediately crash with an error in the DMA code. We ended up wasting over a day trying to figure this one out until I just said screw it, let’s never dsiable the nearpointer, leave it unprotected. Naturally that actually worked. The hint is in map_in_conventional_memory, where __djgpp_nearptr_enable(); is called, but of course there is no calls to __djgpp_nearptr_disable(); I’ve thought about going back through the source to ‘clean’ it up to make it lock and unlock memory as needed, but this is 2015 not 1997 so good enough is well, good enough.
So now with VESA and Sound, I thought this would be a great time to tackle the dynamic loading of gamex86. We will have to re-compile whatever gamex86 DLLs are out there as of course DOS is DOS. The HX DOS guy Japheth seems to have died, as his site and all the info on that extender seems to have mostly vanished. I have an old copy, but I never could make it call DOS stuff if you had WIN32 stuff going on. And if he’s really dead it’s too late to ask him.
Ages ago I remembered this DLL support for DJGPP called DLM, so I thought I’d give that a try. I was able to take our ‘null’ version of Quake II, and get it to where it can load and unload the gamex86.dlm at will. So I figured this was going to be an easy win, right?
Wrong again. Once I started to put in the MS-DOS specific code I got this fun crash:
DLM -> Exiting due to signal SIGSEGV at
0x0014f59d SYM: _dos_lockmem+0x9 DLM: q2.exe [0xf5000]
possibly because of undefined reference to symbol ‘___djgpp_base_address’
So apparently it doesn’t export (or import) djgpp stuff like the base address calculations so we can’t do direct memory access, which means no video and no sound. Ouch. I’ll have to hit the lists to see about support. I don’t like the DXE’s because they cannot be unloaded, so that isn’t much good. And of course things like the JVM inside of gamex86.dll is right out as JAVA inside of MS-DOS? in 64MB of RAM? Dream on.
So for now, the gamex86.dll is statically linked into the executable. You are restricted to vanilla gameplay for now.
As an added bonus, I used Rufus 2.2, to setup a bootable MS-DOS USB stick, slapped everything onto there, and booted up on my Xeon, and it works!
Now as a super bonus, [HCI]Mara’akate went above and beyond by adding in a bunch of fixes, and updates from 3.24 and varous stuff from Knightmare. And then the best part is integrating libogg, so it can now play the ogg sound track! Really, just place the ogg files in the baseq2\music directory and away you go!