via http://dsx86.patrickaalto.com/DSblog.html

During the past week I have finally had some time to work on DS2x86, I have spent an hour or two almost every day on it. My goal was to improve the graphics transfer and blitting code so that also the high resolution modes reach at least 30fps screen refresh rate. I managed to reach speeds of over 60fps in Zoom mode in all the standard graphics modes, but in 640x480 scaled mode and in the weird Mode-X resolutions the blitting speed will sadly still not reach 60fps. But in any case all graphics transfer is now faster than what it was in the original DSTwo transfer system. Below is a table showing the current graphics refresh rates in the various resolutions, in both Zoom and Scaled modes.

Mode Zoom Scale Notes
80x25 Text >200 fps >200 fps Varies by the number of changed characters
320x200 CGA 229 fps 229 fps
640x200 CGA 222 fps 229 fps
320x200 EGA 128 fps 128 fps When logical screen width = 320 pixel
320x200 EGA 119 fps 119 fps When logical screen width > 320 pixels
640x200 EGA 156 fps 70 fps
640x350 EGA 156 fps 80 fps In Scale mode 320x175 bytes transferred
640x480 VGA 156 fps 58 fps In Scale mode 320x240 bytes transferred
320x200 MCGA 70 fps 70 fps
360x240 Mode-X 56 fps 56 fps Used in "Settlers"
320x480 Mode-X 58 fps 58 fps Used in "LineWars II", 320x240 bytes transferred


To reach these speeds in the >=350 scanline Scale modes, I had to combine two adjacent scanlines on the MIPS side before sending them as a single scanline. This will cause the graphics quality to suffer (since I don't want to go to 16-bit color mode where I could do some palette averaging, but which would again drop the refresh rate down to around 40 fps). In the Mode-X 320x400 and 320x480 modes this joining of two scanlines is done also in the Zoom mode, to improved the aspect ratio, so those modes will suffer the most. Luckily, those are rather uncommon screen modes, so not many games are affected. In the 640x??? Zoom modes I only transfer the 256x192 pixels of the visible screen area, so those will run much faster than the corresponding Scale modes.

Serious FS and GS segment register bug fixed
While testing various games with the new graphics transfer routines, I noticed a problem in Chaos Engine. It went into the game fine, but then immediately the screen got filled with seemingly random multicolour pixels. I tested the game with the previous 0.23 version, but the problem was present in there as well! So, it was not caused by the new transfer system, but something more serious. I tested also with DS2x86 version 0.22, in which the game worked fine, so the problem was obviously caused by the "major internal rewrite" that I did for version 0.23.

Next I tried to stop the game into the debugger immediately after the problem began to occur, and almost by chance I managed to get inside some graphics drawing routine, where I immediately noticed that the game uses the FS segment register. It is rather uncommon for real-mode games to use the FS and GS segment registers, and since in version 0.23 I had changed the FS and GS registers to be handled differently, this immediately made me suspect the new handling for those segment registers. The FS register had a value 0x03D2, and the graphics code tested whether a byte in that segment was 0xFF. When I looked at the address of that byte, I noticed that it actually seems to point to code and not data! This was very suspicious, so I checked what the FS register value was in DS2x86 version 0.22 when running that code, and there the FS register value was 0x3D2F!

So, now it was just a matter of determining which of my opcode handlers cause the FS segment register to shift 4 bit positions to the right. Pretty soon I found that the problem was in the software interrupt (INT opcode) handler. It was supposed to shift both FS and GS registers 4 bit positions right (to adjust from effective to actual segment register value when calling the interrupt), but due to a copy-paste bug I shifted FS register two times and did not shift the GS register at all! So, whenever a software interrupt was called, both FS and GS registers got invalid values!

Since those registers are rarely used in real mode, and the protected mode handling for those registers was not broken, this only caused problems in a few games, Chaos Engine being one of them. After I fixed that, I tested also Elder Scrolls: Arena, which had also started to misbehave during the same time, dropping back to DOS with a "Memory list blown" error message. This FS and GS segment register fix did seem to fix that game also, so in the next 0.33 version Arena should again be playable.

Future work
I haven't yet had time to recode the SoundBlaster support, so that is what I plan to work on next. I would like to be able to implement all the ADPCM digitized audio modes, and fix the timing and skipping problems in the current system. This will be rather lot of work, so I am not sure if I have time to do all of that during the next week, but we shall see. I would also like to soon have time to work on the game compatibility again, but it looks like that will have to wait for a little while longer. In any case, thanks for your test reports for the previous 0.32 version, I will eventually get around to fixing the problems!