This weekend was spent mostly tracking down bugs, and fixing them. I started rewriting the string opcodes on Monday and continued that on Tuesday. I get only an hour or so of free time to work on DSx86 during workdays, and being tired after eight hours at the office I usually don't get much done, so this was slow progress. On Wednesday the new string code started to mostly work, so I decided to test whether Wing Commander 2 still works in DSx86.
The last time I ran WC2 in DSx86 was almost two months ago, before I started working on the technology demo with the bundled LineWars II. Back then I had gotten frustrated with the bug that hang the game after a while in space flight, and decided to forget about WC2 for a while. I have done lot of fixes to the emulator since then, so I thought now might be a good time to test it again.
On Saturday I then returned to working on AlleyCat. I had a weird problem with it, where the building windows in the background kept vanishing every now and then. There were other strange things happening as well, but that was the most consistent obviously wrong behaviour.
I used my new memory watch code and made it watch the window location in the graphics memory, and found out that it was a REP MOVSB operation within the CGA memory that overwrote the windows. It took me some more digging to find out why this happens, but finally I noticed that occasionally the emulator code called the CLD (direction bit clear = increment indixes) REP MOVSB code, even though the direction bit was set in the flags. It didn't do this all the time, only occasionally, and never when I traced thru the code in the debugger. After some head scratching it finally occcurred to me that this might happen when an interrupt handler has cleared the direction flag between the setting of the flag using the STD opcode, and the actual REP MOVSB opcode. But I did have a code in the IRET opcode that was supposed to handle this situation!
Well, turned out that the IRET handler first set the new the direction flag and then called the CLD or STD opcode, which in turn first checked whether the new direction flag differs from the existing one before they did anything. The flag did not differ since I had just set it in the IRET handler!
This was a pretty serious bug that might have caused havoc in every game, so it was very good luck that AlleyCat used REP MOVSB with the direction flag set on the graphics screen, which made the problem easy to notice.
On Sunday I then did various minor fixes, like the hardware cursor emulation I mentioned in the previous post. I also tried to run the old CGA version of Elite on DSx86, but that immediately printed "Packed data corrupt" message, and quit to DOS, and also corrupted the memory control blocks while doing it, so 4DOS also exited (and rebooted).
After some debugging I found that the internal unpacker uses the segment
ffset addresses a bit strangely, the offset is always in the range of 0xFFF0..0xFFFF, and the segment is adjusted so that it points to the correct location. Works fine as long as you are using a DOS version that consumes at least the first 64KB of RAM. However, with 4DOS swapping to EMS in DSx86, DOS takes less than 8KB of the low RAM, and the segment address wraps down to 0xFFFF and below. I suppose a real PC might wrap the physical RAM address back to low memory with addresses like 0xFFFE:0xFFF0, but in any case that is NOT a proper way to code software!
Anyways, I will not fix this in DSx86, instead there is an easy workaround for this problem: Start another 4DOS shell but tell it not to swap, so it takes 200KB of RAM, and then launch Elite from within this shell. This will work fine, but currently Elite runs only up to the program protection screen, where it needs a DOS Buffered Input call that I haven't yet coded. Oh, and the screen is in 40x25 text mode, which I also added. This is a nice mode as all the text (except the last line) fits without scrolling or scaling.
Instead of continuing with Elite, I decided to download some other old DOS games to test. The first in line is Solar Winds 1, which I am currently working on. Anyways, here above are some pictures (from AlleyCat in the actual game, the Elite protection screen, and 4DOS "memory" command result), to make this long post a bit less boring, hopefully.