PDA

View Full Version : DS2x86 screen scaling revisited, audio work



wraggster
November 28th, 2010, 21:44
More news from Pate of his work on the Dos emulator for the DS:

After posting my previous blog post, I got an email from Grégori Macário Harbs, who said that he is interested in screen scaling and interpolation algorithms, and has some ideas to share. He suggested a more efficient division of the pixel weights when interpolating over 5 input pixels to produce 4 output pixels. He had even gone so far as to provide an example of how the WC2 title screen would look with different interpolation methods, and he also provided some source examples. Many thanks for the tips Grégori!

Using the ideas that he provided, I was able to make the DS2x86 interpolation algorithm much faster, and also improve the quality. The new algorithm converts the first 4 input pixels with 75%/25%, 50%/50% and 25%/75% weighting to 3 output pixels, and the fifth input pixel is directly output as the fourth output pixel. Since the 25%, 50% and 75% values can be given as 1/4, 2/4 and 3/4, they are much simpler and faster to calculate than my original 80%, 60%, 40% and 20% weights.

Some other ideas that I learned from him for future use is the possibility to precalculate the weighted palette values beforehand, which would be especially useful when interpolating the 16-color modes, and the fact that bilinear interpolation of the Mode-X 320x240 screen is actually 5/4 interpolation on both axis. Neither of these I have implemented yet, but I am looking forward to when I have time to implement and experiment with these. Here below are the screen copies from my original interpolation algorithm (on the left) and the new improved algorithm (on the right). I think the new image looks noticeably sharper with fewer artifacts.


Audio work
By the end of last week I had gotten the new screen interpolation working, so I finally looked into DSTwo SDK audio support. I studied the example provided with the SDK, and then began to look into ways to implement that in DS2x86. Compared to the audio features of Nintendo DS itself, the audio support of the DSTwo SDK is very limited. It only supports one 16-bit stereo audio channel, which can run at 11025, 22050 or 44100 Hz. In DSx86 I had allocated one separate 8-bit audio channel to the SoundBlaster digital audio, one PSG audio channel to the PC speaker sounds, one 8-bit audio channel to the Covox or SB Direct DAC audio, and 9 separate 16-bit audio channels for the AdLib emulation. Packing all of these to the single stereo channel will be quite a challenge.

In DSx86 I coded the audio support so that it will be as close to the x86 method as possible. The game running in the main emulator will send the audio command bytes to an I/O port, which then get sent to the ARM7 side using the FIFO mechanism. The code running on ARM7 then interpreted these bytes (like it was the actual SoundBlaster card) and performed the proper operations. Now in DS2x86 I have to use the same CPU for both running the main emulation and handling the audio emulation.

I decided to start with the simple case of trying to get the SB digital audio channel working. I still used Wing Commander II as the test bench, as it plays speech during the game intro. In DSx86 I could run the separate audio channel at whatever frequency the x86 game requested, but now I needed to select one of the supported frequencies. I decided to go with the 22050 speed, as I thought that going to the full 44100 Hz will slow the emulation down unnecessarily. Since the input audio is 8-bit and I need to convert it on-the-fly to 16-bit and use interpolation to adjust the playing frequency, the quality will be pretty poor in any case, so 44100 Hz will certainly be overkill.

The SDK example had no timing features, it just used a spin loop to check when the audio buffer is free to handle the next block of the WAV file. It was not quite clear to me how the audio buffer interaction works, and whether handling the buffer filling in a timer interrupt (like in my screen handling) will work, so I spent quite some time experimenting with different methods of filling and swapping the buffers, with different buffer sizes. I need to have a timer interrupt running at 60Hz, so that I can use it to handle screen refresh and vertical retrace signalling to the x86 game (many of which sync to the screen retrace signal). I wanted to use this same interrupt for the audio buffer filling, mainly so that the screen contents sending and audio sending from the MIPS side to the ARM side do not conflict with each other. There are some difficulties syncing this 60Hz timer with the buffer filling, as there are three different buffer sizes that need to be taken into account. The ds2 audio buffer size needs to be divisible by 128, the number of samples played during each 60Hz period is 22050/60 = 367.5, and the third size is the DMA buffer length that the x86 game (in this case Wing Commander II) uses. In WC2 the buffer is 4000 bytes (not 4096 bytes), and the frequency it uses is 10752 Hz, so that each 4000-byte x86 DMA transfer will actually generate 8203 output samples.

The current status of my audio tests is that the SB digitized audio works in WC2, but the sound has some cracks and pops. I don't handle the continuing with the next DMA transfer after the previous has finished (and left a buffer only partially filled) properly yet, so I believe that is the cause for the cracks. However, the audio buffer filling happens inside a timer interrupt (which is not recommended in the SDK documentation), same as my screen update, and the game does not see anything wrong with the SB DMA IRQs and such, so I think I will get this working fine. I am currently using a 512-sample buffer (as the buffer obviously needs to have more than one 60Hz interval's worth of samples), but I will test whether different buffer sizes will improve things. Too long a buffer will cause a lag to the audio, so that is not helpful either.

In any case, still a lot to do on the audio front, but the big step forward was that I now understand the DSTwo SDK audio buffering method and can focus on working with it to implement the audio support in DS2x86.

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