Pate has posted some more great WIP News about his Dos Emulator for DS:
Alpha version 0.01 feedback
Big thanks to everyone of you who tested the 0.01 alpha version and reported the problems you found, either by sending me the full DSx86dbg.log files or by posting on the GBADEV forum thread! The logs showed pretty clearly that DSx86 is still missing too many opcodes for it to support other games besides those I have specifically supported. Sorry about that, I thought it might be able to run some other simple games already. Also, the logs showed that quite many games want to use the graphics mode 0x0D (320x200 16-color EGA mode). I guess this should be the next graphics mode DSx86 will support.
Opcode tester program progress
Pretty soon after I released the 0.01 version, I noticed some serious problems with Leisure Suit Larry 3. After I fixed the missing opcode in 0.01, it still would not recognize any user input, instead it always said "Bad Said Spec" whatever I tried to type. I could not find the problem by debugging the code (and I tried for hours), so I then decided that now would be a good time to finally improve my opcode tester program. Until now the program had only tested for typos in the memory access, so that my opcode handlers don't change the wrong memory location (addressing with [SI] instead of [DI], for example).
I worked on the tester program for two full days, and added pretty complete tests for all arithmetic, logical, and move opcodes. It tests all modrm byte variations that DSx86 supports, and is smart enough to skip the variations I haven't yet coded. It checks for the correct result of the operation, and also for correct CPU flag changes.
When running the improved tester program I found about half a dozen bugs in my opcode handlers, including bugs in "TEST" opcode, which the original tester program had skipped completely, as it doesn't change any memory.
Now I feel much more confident that the new opcodes and modrm byte variations I add will work properly even when I don't currently know of a game that would use them. Thus, I have been adding quite a few new opcodes these past days since the 0.01 release, for example all "INC", "DEC" and "LEA" variations are now fully supported, same as all arithmetic 16-bit operations with immediate values, and most of the "MOV" opcodes as well. Still a lot of work to do with the remaining missing opcodes, but it is much nicer to keep adding them now when I can test the new variations immediately.
Auxiliary Carry and Parity flags
One big difference between the ARM and x86 processors is that ARM does not have the Auxiliary Carry (which works like the normal Carry flag, but for the bottom 4 bits of a byte) nor the Parity flag (which tells whether the least significant byte of the last arithmetic operation has an even number of set bits). I had hoped that games would not use these flags, but now I have noticed them both being used in games.
The AC flag is used in Leisure Suit Larry 3. When drawing data to the screen, LSL3 uses both the Carry flag (for the upper 4 bits) and the AC flag (for the lower 4 bits) to determine whether the new data is in front of or behind whatever is currently on the screen. It uses code like this:
CMP BL,[DI+7FF0]
LAHF
TEST AH,10
That is, it compares the current value in BL with the value in memory, then loads the AH register with the resulting flags, and then tests for the bit in AH that has received the AC flag. A somewhat complex method, but since the x86 instruction set does not contain a conditional jump that would check the AC flag, this is the most straightforward method available.
Since the ARM processor does not have anything similar, I had to code a game-specific special case to handle this. I added some code to the LAHF opcode (which is quite rare) handler, so that it checks whether the next opcode is "TEST AH,10" (which could have no other purpose but to test the AC flag), and if so, it determines if the previous opcode is "CMP BL,[DI+7FF0]", and if so, it performs the compare again, but this time by shifting the values 4 bits left, so the resulting real carry will get the value that the AC flag would get in x86. This new carry is then stored into the AH register bit 0x10, so the following test will give the correct result. This seemed to solve the problem completely for Leisure Suit Larry 3.
Based on a log file I received, The Incredible Machine uses the parity flag. However, on closer examination of the code I believe this is actually a bug in the game. The game has code like this:
1E30:60EB 83F90A cmp cx,000A
1E30:60EE 7C0C jl 60FC ($+c)
1E30:60F0 0BFF or di,di
1E30:60F2 7A02 jpe 60F6 ($+2)
1E30:60F4 AA stosb
1E30:60F5 49 dec cx
1E30:60F6 D1E9 shr cx,1
1E30:60F8 F3AB repe stosw
1E30:60FA D0D1 rcl cl,1
1E30:60FC F3AA repe stosb
The way I interpret that is, that it first check if it has less than 10 bytes to move. If so, it jumps to simply moving them byte-by-byte. If
...
Catherine: Full Body’s English translation for the Vita