|
May 1st, 2011, 23:30 Posted By: wraggster
News via http://dsx86.patrickaalto.com/DSblog.html
Happy May 1st! Since releasing the 0.07 version of DS2x86 I have received several new debug log files. For the past week I have been adding the missing opcodes from the logs, and I have now added nearly all of them. The remaining issues in the logs are either due to missing virtual memory support (which is not coming very soon), or the game executing data instead of code. So, instead of adding new opcodes I can now move my focus to making the emulation itself more robust.
On Saturday I improved the exception (BSOD) handling again. I noticed that several games, for example Carmageddon and Destruction Derby crashed within my ASM code, so that the call stack was not sufficient to determine which opcode caused the error. I added some checks to the exception handler to determine if the crash happened inside my ASM code, and if so, made the exception handler return gracefully to the debugger breakpoint exit. Thus, I know the opcode that caused the exception was the opcode immediately before the opcode where the debugger points to. This has the added bonus that the exception info gets written to the dsx86dbg.log, so you don't need to type it down from the blue screen.
After that change, I then debugged both Carmageddon and Destruction Derby further. I noticed that both of them crash because of floating point opcodes not being supported. I don't plan to add floating point opcodes (as the DSTwo architecture does not have a floating point unit), and since I could not get Carmageddon to work on DOSBox (after turning off the floating point support in it as well) either, I decided to ignore Carmageddon. It will not work in DS2x86 in the foreseeable future. This is what the crash log in Carmageddon looks like with the new exception handling: ------------------- [STYLE] --------------------Exception 2 at 801A33F0!TLB miss on load from 08241B60!CPU: PROT, USE32, CPL=0GraphMode=03, EGAMode=00, Chain4=OFFEAX=0029274D EBX=00281E46 ECX=00281E46 EDX=00000004ESP=002C9B6C EBP=00133111 ESI=002C9C70 EDI=020906D8DS=0168 ES=0168 SS=0168 CS=0160 FS=0000 GS=0020NV UP EI PL NZ NA PE NC VM=0 IOPL=00160:1CCF83 3C00 cmp al,00Disassembly of code around the location:0160:1CCF63 E8F0970500 call 00226758 ($+597f0)0160:1CCF68 DB9C24A4010000 fistp [esp+000001A4]0160:1CCF6F 6BBC24A40100000Eimul edi,[esp+000001A4],0E0160:1CCF77 B894272900 mov eax,002927940160:1CCF7C 01C7 add edi,eax0160:1CCF7E 57 push edi0160:1CCF7F 8A06 mov al,[esi]0160:1CCF81 8807 mov [edi],al0160:1CCF83 3C00 cmp al,000160:1CCF85 7410 je 001CCF97 ($+10)Looking at the above log, the crash happens at address 0160:1CCF81F, where the AL register value is being written to memory address in EDI register. The EDI register contains value 0x020906D8, which is above the 16MB of RAM that DS2x86 has available, thus the address is not within the mapped RAM. (In case you are wondering why the crash happens with address 0x08241B60 instead of 0x020906D8, that is because addresses outside the mapped memory area default to Mode-X/EGA RAM handling, where the address is first multiplied by 4 before it is attempted to be used). The value in EDI seems to be calculated by multiplying memory address [ESP+000001A4] contents with 0x0E, and then adding 0x00292794 to that value. However, the content of memory address [ESP+000001A4] is the result of an unsupported floating point operation fistp, so this memory address will contain whatever it did before this unsupported opcode. Thus, multiplying a random value with 14 and then adding something to it can easily point to outside the 16MB RAM area. There is no proper way of fixing this without adding support to floating point opcodes.
However, Destruction Derby seems to work on DOSBox, even tough it attempts to run floating point opcodes there also. Thus, there is something else wrong in DS2x86 with this game. I spent the whole of Saturday debugging this problem, but did not yet find the cause. In the end I got frustrated with that issue, and looked into the Arkania hanging problem. I noticed that it hangs also in DSx86, so this issues seems to be something that is common to both my emulators. I have now deciphered the timer code that causes a neverending loop. The game tries to measure the time it takes to draw a full VGA frame, using the timer. The code first checks that two adjacent measurements do not differ by more than 50 timer ticks (where the timer runs at 1.193.182 Hz, so 50 timer ticks is about 42 microseconds). If the difference is larger, the code loops to try again. Surprisingly, this does not seem to cause big problems in DSx86 nor in DS2x86, the code might need to try a few times but this does not cause a never-ending loop.
The next step in the timer check code is where the problem seems to be. The code gets the timer result, subtracts 1000 from it, divides the result by two, and then checks that the resulting value is larger than 14336. Counting backwards from the test value, it seems the original timer value must be larger than 29672 for the code to accept it. I don't quite understand how that would make sense, as that timer value corresponds to 25ms (or about 40Hz), and for the timer value to be bigger the screen refresh rate would need to be slower! The VGA screen in DSx86 and DS2x86 is refreshed at about 60Hz, so the code never sees slower than 40Hz screen refresh rate and thus hangs. However, in DOSBox the resulting timer value is about 34000 (28ms), which is what Arkania accepts. But that speed corresponds to a 35Hz VGA refresh rate! In DSx86 and DS2x86 the resulting timer value is around 23000 (20ms), which would be around 50Hz. I'll need to look deeper into DOSBox sources and the VGA documentation to make some sense of these values.
Thanks again for the debug logs you have sent, and for the games to test that some of you have attached! I'll look into these during the next week, and hope to release a new version again next weekend.
For more information and downloads, click here!
There are 0 comments - Join In and Discuss Here
|
|