PDA

View Full Version : DS2x86 screen scaling - Dos Emulator for DS



wraggster
November 21st, 2010, 22:29
Pate has posted more WIP News of his Dos emulator for the DS

Since last weekend I have been working on the I/O port handling and other things that already exist in DSx86 but which I had not ported over to DS2x86 yet. When I got DS2x86 running, I wanted to immediately start working on the protected mode stuff, so I left a lot of code commented out. Now I thought is a good time to port this code as well, so that DS2x86 could run most of the same games that DSx86 runs. I got most of the EGA/VGA port addresses done, and then also coded the MCGA graphics support, so that Wing Commander II will progress up to the part where it attempts to play digitized sounds.

After I had coded the straightforward MCGA mode blitting (where only a 256x192 window of the original 320x200 screen is converted to 16-bit color and copied to the DSTwo SDK internal buffers), I thought that this might be a good time to look into improved screen scaling methods. Many users of DSx86 have requested a smoother screen scaling method, but I have not yet added that as it needs going from the 256-color palette mode to 16-bit color mode. Now with DS2x86 I need to use the 16-bit color mode in any case, so this is a suitable test bench for the better scaling method.

The biggest problem with the more advanced screen scaling methods is that they are quite expensive computationally. The direct palette conversion code is reasonably straightforward, it just needs an extra table lookup to convert the palette index to a 16-bit color that can then be written to the output buffer, like this (shown for a single row):

la v0, BG_PALETTE // v0 = address of the palette table
1: lbu t3, 0(t1) // Get a byte (palette index) from VGA VRAM
addu t1, 1 // Increment input index
sll t3, 1 // Palette table has 16-bit values
addu t3, v0 // t3 = pointer to the palette table
lhu t3, 0(t3) // Get the 16-bit color from the palette table
addu t0, 2 // Increment output index
sh t3, -2(t0) // Store the 16-bit color to output table
bne t0, t2, 1b // Loop until one row done


However, even the simplest smooth scaling method, linear interpolation, needs a division and two multiplications per pixel. I am actually not sure how many CPU cycles multiplications and divisions take on the MIPS processor of DSTwo, but I assume they are more expensive than normal additions and subtractions. In any case, I used a calculator and some experimenting, and noticed that what I actually need is a way to smoothly draw 4 output pixels for every 5 input pixels (as 320/256 = 5/4). So, I have only four separate cases, and in fact the two rightmost output pixels are mirror images of the two leftmost pixels, so actually I only have two different cases. I was sure that I can come up with some shortcuts for these two situations, so I began to look into these more closely.

Linearly interpolating over 5 input pixels showed that the first output pixel should have a color of 80% of the first input pixel and 20% of the second input pixel. The second output pixel should have 60% of the second input pixel and 40% of the third input pixel. Mirroring these, the third output pixel should have 40% and 60%, and finally the last output pixel needs 20% and 80% weighting of the colors. To get rid of the divisions, I looked into multipliers that would let me divide the result by a power of two (so that I can use a shift instead of division). The first 80%/20% case is pretty close to 25/32 (78.125%) and 7/32 (21.875%), and the 60%/40% case is close to 5/8 (62.5%) and 3/8 (37.5%). I coded the first version of a linearly interpolating scaling code using simple shifts and additions to handle this pixel weighting, and I thought the result looked satisfactory, especially as the pixel weighting percentages are not quite correct. The code did not seem to cause any noticeable slowdown, even though it is still far from fully optimized. Here below are screen copies of the zoomed and scaled versions of the same Wing Commander II title screen.


Next I plan to start looking into the audio support. The whole audio playing technique in the DSTwo SDK is still completely unclear to me, as I haven't looked into it at all yet. That is the biggest feature still completely unsupported, so it is time to start working on it.

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