News from Pate concerning his Dos Emulator for DS

AdLib emulation finished for now
Last Monday I added the last missing features of the AdLib emulation, frequency modulation (vibrato) and amplitude modulation. I figured out a way to handle the vibrato without slowing down the code all that much. The sound frequency should change (using the 32kHz sound output frequency) after every 674 samples, but as I fill the buffers 64 samples at a time, I decided to change the frequency after every 640 samples, so I can move the calculations outside of the sample building loop. So the vibrato is slightly faster than it should be, but I don't think that is much of a problem. I did a similar change to the amplitude modulation, it should change the sound volume every 168 samples, but I change it every 192 samples, again to move the calculations outside of the 64-sample loops.

I just need to comment the code better and create a test project that would use my AdLib emulation code and then I could release the sources, in case people are interested in those.

Some compatibility improvements
I have so far tested Adventures of Robin Hood, Silpheed and SimAnt. Adventures of Robin Hood crashed with an sunsupported opcode, and when I debugged it I noticed that it uses only a 32-byte(!) stack! That is so little space that when a timer interrupt happens when the code calls a subroutine (after receiving a keypress) it runs out of stack space. Actually, the stack pointer should wrap to the end of the stack segment (which has unused space in the game launcher program), but my DSx86 stack emulation implementation did not handle this properly and thus crashed. I changed my stack emulation to handle stack pointer wrap-arounds properly, so Adventures of Robin Hood started up fine.

Silpheed progressed pretty far with the single-opcode internal refactoring I had already done, but then it ran into a problem with my string opcodes that still didn't handle writing to graphics memory with a segment address pointing to plain RAM properly. It did draw most of the enemy ships with the plain opcodes, but their removal from the screen was done using string opcodes, so after a while the screen was full of enemy ships. :-) It needed the refactored string opcodes before I could continue with it.

I then tested SimAnt, and noticed that it used the EMS memory in a way that also was incompatible with my segment-based memory access mode handling. It got the wrong data from the EMS memory using my old string opcodes, and thus filled the screen with garbage data instead of the Maxis logo at the start, for example. So, I decided to start working on the string opcode refactoring next.

Internal refactoring
I have now refactored many of the simple opcodes, like all OR operation variants and most of the MOV opcodes. What was interesting when I did this refactoring was that after every build the resulting DSx86.nds file got smaller. This was due to the new memory access handling using more common code for both the normal RAM and graphics opcodes, as only after the effective memory adress is calculated the code will branch to different handlers. Originally I had completely different opcode handlers, depending on where the effective segment poinst to. Thus, the new code has a lot more branches (which makes the code slower), but on the other hand there is much more common code which will help with the cache hit percentage. So perhaps the total slowdown is not quite as drastic. I also have a couple of speedup tricks I can still use, but those I can not do until all of the code is changed to use the new memory access strategy. So, looks like the next version will be quite a bit slower than the current version, but after I have refactored all the opcodes I can make the code slightly faster again.

I am currently working on the string opcode refactoring, and now I am pretty happy with the way the code looks. I am splitting the memory moves, for example, so that they are done in blocks that fit within the same 16K memory page, both for the source and target address, and also possible SI and DI segment wrap is taken into account. So all EMS memory and graphics memory access with the string opcodes should now always handle the correct data, so I can look elsewhere for erractic behaviour in games. I have already coded most of the string opcodes for main RAM and EGA graphics memory, but Mode-X handling is still completely missing. I still have a week before the next release, so I should have enough time to handle those as well.

After I coded the main RAM and EGA string operations, both Silpheed and SimAnt looked to be playable. Silpheed still hangs after intro if Enter is not pressed, and it also hangs when going to the debugger and trying to continue, so there are still some issues. SimAnt I haven't tested any further than by going to the main menu. It uses 640x480 graphics mode so it is a bit awkward to play in any case.

The heat wave continues here in Finland (as it seems to do for most of Europe), so I shall see how much coding I can get done during the next week.