VOGONS


Reply 20 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++

I just tried to run it again with a once-again clean setup(maybe some empty config.sys lines or empty switches).

Now running HDPMI32 and then ENGINE I see the double fault being due to opcode E8 causing a stack fault?

Edit: Trying it again, I see:
1. A segment write fault #GP(0030), writing segment value 0x32, opcode C5(32-bit LDS instruction). The offset for the destination register is 0x02000000. It's executed at 0020:00000024
2. A #GP(0) fault execution LES of DS:1C8A, which causes an access rights type violation(Not present, AR byte is 0x13). At 0020:0010 on the memory operand itself.
3. Same as #2.
4. Same as #2 at 0020:0010.
5. Once again same as #2.
6. And again.
7. And again.
8. And again.
9. And again.
10. And again.
5. Then a #SS(0) at 0020:462D. Which double and then triple faults. This is opcode E8 trying to near CALL offset -14838, so it's trying to call a function at offset C3C.

Filename
debugger_HDPMI32_ENGINE_UniPCemu_20190219_2034.7z
File size
832.33 KiB
Downloads
109 downloads
File comment
HPDMI32 loaded, running ENGINE, filtered segment 20h in protected mode.
File license
Fair use/fair dealing exception

Edit: Oddly enough, That first address faulting isn't the same address I see being read by the instruction, except if there's a SS.BASE!=0 ?
Edit: SS.BASE=109F0. CS.BASE=FF801000 and limit 67D3 at the first fault.
Step 1 is loading 28:7F5, which is valid. That resuls in logical memory address 111E5 for the first operand(the destination ESI). Then for the destination DS, linear address 111E9 and 111EA is used.
Then (as the next, lower, priority), the physical memory access is checked against. That reaches into the TLB entry, with tag 11000D, pointing to physical memory location 110000, so a linear mapping is used for these accesses.
I actually see the pointer 0032:02000000 being read from said location on the stack?
Edit: I see the descriptor being located at logical memory location ff808830, which translates to physical memory location block 00bf4000, so physical memory location 00bf4830. That translates to real memory location 00b94830(subtracting 100000-A0000 for said location between 1-15MB).
So it's addressing just a bit under the actual physical memory installed into the machine.

The descriptor that's at that memory location is (decoded as DWORDS, so little-endian): 11F80067, 00008B01 (or in memory order: 67 00 F8 11 01 8B 00 00 for the entire descriptor).
So it's a code descriptor of some kind.
Edit: It's a non-conforming code segment, readable, accessed, for DPL=0.
Edit: Somehow, the code thinks it's an execute-only code segment it seems? So it's perfectly valid to load into DS, but my code oddly seems to think it's invalid to load, directly after checking the present bit and validating any data segment against system and non-readable code segment?
Edit: Whoops, my bad. It's type is 8B, so it's a busy 80386 TSS? It's trying to load a busy 80386 TSS into DS? Why would it try to do that?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 21 of 591, by keenmaster486

User metadata
Rank l33t
Rank
l33t

Wow. This is some useful information. You know, I may even pass this along to the FreeBasic people for debugging purposes.

This sort of thing happens on real machines as well. If your emulator isn't emulating an FPU, chances are that these errors are the same ones that cause it to fail on a real 386SX.

Maybe I will try compiling it with a different FPU emulator and see if that works.

Is it possible that this is due to the attempted execution of an FPU instruction? Also, I assume all of these faults show up right after you select a level and it begins trying to load.

The first thing that loads is the sound effects files (just basic disk operations), after which it runs the SB initialization code. It doesn't even try to allocate memory for graphics, level data, etc. until it's done with that. Try running it in DOSBox and you can see what I mean.

edit: on some systems it will throw a GPF no matter what. For example, I have a Pentium MMX 166 laptop, and it throws a GPF every time I select a level and it begins trying to load the sound effects. However, I have a desktop Pentium MMX 200 machine, and it always loads perfectly every time on that machine. It's frustrating!

World's foremost 486 enjoyer.

Reply 22 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++
keenmaster486 wrote:
Wow. This is some useful information. You know, I may even pass this along to the FreeBasic people for debugging purposes. […]
Show full quote

Wow. This is some useful information. You know, I may even pass this along to the FreeBasic people for debugging purposes.

This sort of thing happens on real machines as well. If your emulator isn't emulating an FPU, chances are that these errors are the same ones that cause it to fail on a real 386SX.

Maybe I will try compiling it with a different FPU emulator and see if that works.

Is it possible that this is due to the attempted execution of an FPU instruction? Also, I assume all of these faults show up right after you select a level and it begins trying to load.

The first thing that loads is the sound effects files (just basic disk operations), after which it runs the SB initialization code. It doesn't even try to allocate memory for graphics, level data, etc. until it's done with that. Try running it in DOSBox and you can see what I mean.

edit: on some systems it will throw a GPF no matter what. For example, I have a Pentium MMX 166 laptop, and it throws a GPF every time I select a level and it begins trying to load the sound effects. However, I have a desktop Pentium MMX 200 machine, and it always loads perfectly every time on that machine. It's frustrating!

Nope. Those faults I meantioned happen right after having loaded HDPMI32, then typing engine at the command prompt and pressing carriage return. When your application starts(nothing is done on the screen yet, not even a newline of MS-DOS is visible yet), all those faults happen right one after another(as I'm debugging those with Visual Studio debugging my emulator itself to see what is causing said faults).

In the end, it all seems to start with that #GP(30) fault, which incorrectly tries to load 0x32(a busy TSS) into DS, which is forbidden according to the hardware specs(any x86 manual I know of), as TSSes are only allowed to be loaded into the TR register(same with the LDT and LDTR), or (in the case of an TSS) an alternative using JMP/CALL 'loading' it into CS(either directly or through a task gate) to trigger a task switch(instead of a direct descriptor loading of the TSS descriptor into the CS descriptor cache)).

Now the question is: why is it trying to load a TSS descriptor into the DS register, as said operation is 100% invalid and SHOULD trigger a #GP exception according to the documentation. Perhaps the problem is somewhere before that load? Perhaps the value on the stack is incorrectly set up? LDS assumes the stack in this case to first have pushed the offset, then the segment. But segment:offset pairs usually aren't used for TSS descriptors(unless you have a data segment descriptor somewhere for pointing to the same memory location and size)? They cannot usually be used together. The only actual being in the x86 CPU that can access the full segment:offset pair and dereference it is the CPU itself while performing stuff like task switching, stack switching etc., which is out of control of any program(it's just a part of the CPU's operation. There isn't any program in existence afaik that is capable of using the TR segment directly(as there aren't any TR-segment prefixes after all).

Edit: Trying to load your program from the command prompt without having loaded the DPMI driver(empty config.sys in effect, so MS-DOS 6.22 without any drivers) results in the program throwing a double fault immediately, dumping the fault information and returning back to the MS-DOS prompt.

Edit: Interestingly enough, tracing up the log for the location of said real memory address, I end up at the following instructions:

0020:000012b0 66 26 8B 47 08 mov ax,word es:[edi+08]	RealRAM(p):00b9a2cd=0f(); RAM(p):00bfa2cd=0f(); Physical(p):00bfa2cd=0f(); Paged(p):ff8022cd=0f(); Normal(p):000012cd=0f(); RealRAM(p):00b9a2ce=82(?); RAM(p):00bfa2ce=82(?); Physical(p):00bfa2ce=82(?); Paged(p):ff8022ce=82(?); Normal(p):000012ce=82(?); RealRAM(p):00b9a2cf=05(); RAM(p):00bfa2cf=05(); Physical(p):00bfa2cf=05(); Paged(p):ff8022cf=05(); Normal(p):000012cf=05(); RealRAM(r):0001446a=02(); RAM(r):0001446a=02(); Physical(r):0001446a=02(); Paged(r):0001446a=02(); RealRAM(r):0001446b=72(r); RAM(r):0001446b=72(r); Physical(r):0001446b=72(r); Paged(r):0001446b=72(r)
Registers:
EAX: 00000213 EBX: 0000008f ECX: 0004ffff EDX: 00004000
ESP: 000007cc EBP: 000007cc ESI: 00000090 EDI: 00014462
CS: 0020 DS: 0028 ES: 004b FS: 0000 GS: 0000 SS: 0028 TR: 0030 LDTR: 0038
EIP: 000012b0 EFLAGS: 00003016
CR0: e0000031 CR1: 00000000 CR2: 00000000 CR3: 00bff000
CR4: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000ff80880007ff IDTR: 0000ff80900007ff
FLAGSINFO: 0000000000i00avr0n11oditsz0A0P1c
0020:000012b5 66 25 FE 03 and ax,03fe RealRAM(p):00b9a2d0=01(); RAM(p):00bfa2d0=01(); Physical(p):00bfa2d0=01(); Paged(p):ff8022d0=01(); Normal(p):000012d0=01(); RealRAM(p):00b9a2d1=00( ); RAM(p):00bfa2d1=00( ); Physical(p):00bfa2d1=00( ); Paged(p):ff8022d1=00( ); Normal(p):000012d1=00( ); RealRAM(p):00b9a2d2=00( ); RAM(p):00bfa2d2=00( ); Physical(p):00bfa2d2=00( ); Paged(p):ff8022d2=00( ); Normal(p):000012d2=00( ); RealRAM(p):00b9a2d3=66(f); RAM(p):00bfa2d3=66(f); Physical(p):00bfa2d3=66(f); Paged(p):ff8022d3=66(f); Normal(p):000012d3=66(f); RealRAM(p):00b9a2d4=89(?); RAM(p):00bfa2d4=89(?); Physical(p):00bfa2d4=89(?); Paged(p):ff8022d4=89(?); Normal(p):000012d4=89(?)
Registers:
EAX: 00007202 EBX: 0000008f ECX: 0004ffff EDX: 00004000
ESP: 000007cc EBP: 000007cc ESI: 00000090 EDI: 00014462
CS: 0020 DS: 0028 ES: 004b FS: 0000 GS: 0000 SS: 0028 TR: 0030 LDTR: 0038
EIP: 000012b5 EFLAGS: 00003016
CR0: e0000031 CR1: 00000000 CR2: 00000000 CR3: 00bff000
CR4: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000ff80880007ff IDTR: 0000ff80900007ff
FLAGSINFO: 0000000000i00avr0n11oditsz0A0P1c
0020:000012b9 80 CC 30 or ah,30 RealRAM(p):00b9a2d5=5d(]); RAM(p):00bfa2d5=5d(]); Physical(p):00bfa2d5=5d(]); Paged(p):ff8022d5=5d(]); Normal(p):000012d5=5d(]); RealRAM(p):00b9a2d6=28((); RAM(p):00bfa2d6=28((); Physical(p):00bfa2d6=28((); Paged(p):ff8022d6=28((); Normal(p):000012d6=28((); RealRAM(p):00b9a2d7=67(g); RAM(p):00bfa2d7=67(g); Physical(p):00bfa2d7=67(g); Paged(p):ff8022d7=67(g); Normal(p):000012d7=67(g); RealRAM(p):00b9a2d8=66(f); RAM(p):00bfa2d8=66(f); Physical(p):00bfa2d8=66(f); Paged(p):ff8022d8=66(f); Normal(p):000012d8=66(f)
Registers:
EAX: 00000202 EBX: 0000008f ECX: 0004ffff EDX: 00004000
ESP: 000007cc EBP: 000007cc ESI: 00000090 EDI: 00014462
CS: 0020 DS: 0028 ES: 004b FS: 0000 GS: 0000 SS: 0028 TR: 0030 LDTR: 0038
EIP: 000012b9 EFLAGS: 00003002
CR0: e0000031 CR1: 00000000 CR2: 00000000 CR3: 00bff000
CR4: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000ff80880007ff IDTR: 0000ff80900007ff
FLAGSINFO: 0000000000i00avr0n11oditsz0a0p1c
RealRAM(p):00b9a2d9=8b(?); RAM(p):00bfa2d9=8b(?); Physical(p):00bfa2d9=8b(?); Paged(p):ff8022d9=8b(?); Normal(p):000012d9=8b(?); RealRAM(p):00b9a2da=1e(); RAM(p):00bfa2da=1e(); Physical(p):00bfa2da=1e(); Paged(p):ff8022da=1e(); Normal(p):000012da=1e(); RealRAM(p):00b9a2db=2a(*); RAM(p):00bfa2db=2a(*); Physical(p):00bfa2db=2a(*); Paged(p):ff8022db=2a(*); Normal(p):000012db=2a(*)
0020:000012bc 89 45 2C mov dword ss:[ebp+2c],eax Paged(w):000111e8=02(); Physical(w):000111e8=02(); RAM(w):000111e8=02(); RealRAM(w):000111e8=02(); Paged(w):000111e9=32(2); Physical(w):000111e9=32(2); RAM(w):000111e9=32(2); RealRAM(w):000111e9=32(2); Paged(w):000111ea=00( ); Physical(w):000111ea=00( ); RAM(w):000111ea=00( ); RealRAM(w):000111ea=00( ); Paged(w):000111eb=00( ); Physical(w):000111eb=00( ); RAM(w):000111eb=00( ); RealRAM(w):000111eb=00( )
Registers:
EAX: 00003202 EBX: 0000008f ECX: 0004ffff EDX: 00004000
ESP: 000007cc EBP: 000007cc ESI: 00000090 EDI: 00014462
CS: 0020 DS: 0028 ES: 004b FS: 0000 GS: 0000 SS: 0028 TR: 0030 LDTR: 0038
EIP: 000012bc EFLAGS: 00003002
CR0: e0000031 CR1: 00000000 CR2: 00000000 CR3: 00bff000
CR4: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000ff80880007ff IDTR: 0000ff80900007ff
FLAGSINFO: 0000000000i00avr0n11oditsz0a0p1c

That final instruction seems to write a value to it's second byte on the stack(at ss:[EBP+2D]) which is the first byte retrieved by the faulting LDS instruction for the DS segment selector. This does really sound like some kind of stack misallignment somehow? Look at the ESP and EBP values: both are DWORD-aligned.

Interestingly, the faulting ESP address is unaligned(due to ESP being unaligned) and the EBP as well as the ModR/M displacement are both DWORD-aligned.

So, that means that there's probably some instruction that applies to the stack that is somehow aligning the stack to a word-alignment, while a DWORD-alignment is required for the instruction to proceed?

Edit: Yes, there we go, I've found the offending instruction:

	RealRAM(r):00b9fffb=00( ); RAM(r):00bffffb=00( ); Physical(r):00bffffb=00( ); RealRAM(r):00b9fffa=bf(?); RAM(r):00bffffa=bf(?); Physical(r):00bffffa=bf(?); RealRAM(r):00b9fff9=d4(?); RAM(r):00bffff9=d4(?); Physical(r):00bffff9=d4(?); RealRAM(r):00b9fff8=67(g); RAM(r):00bffff8=67(g); Physical(r):00bffff8=67(g); RealRAM(r):00b9d007=00( ); RAM(r):00bfd007=00( ); Physical(r):00bfd007=00( ); RealRAM(r):00b9d006=bf(?); RAM(r):00bfd006=bf(?); Physical(r):00bfd006=bf(?); RealRAM(r):00b9d005=b4(?); RAM(r):00bfd005=b4(?); Physical(r):00bfd005=b4(?); RealRAM(r):00b9d004=65(e); RAM(r):00bfd004=65(e); Physical(r):00bfd004=65(e); RealRAM(p):00b9bc68=c3(?); RAM(p):00bfbc68=c3(?); Physical(p):00bfbc68=c3(?); Paged(p):ff801c68=c3(?); Normal(p):00000c68=c3(?); RealRAM(p):00b9bc69=8d(?); RAM(p):00bfbc69=8d(?); Physical(p):00bfbc69=8d(?); Paged(p):ff801c69=8d(?); Normal(p):00000c69=8d(?); RealRAM(p):00b9bc6a=40(@); RAM(p):00bfbc6a=40(@); Physical(p):00bfbc6a=40(@); Paged(p):ff801c6a=40(@); Normal(p):00000c6a=40(@); RealRAM(p):00b9bc6b=00( ); RAM(p):00bfbc6b=00( ); Physical(p):00bfbc6b=00( ); Paged(p):ff801c6b=00( ); Normal(p):00000c6b=00( ); RealRAM(p):00b9bc6c=9c(?); RAM(p):00bfbc6c=9c(?); Physical(p):00bfbc6c=9c(?); Paged(p):ff801c6c=9c(?); Normal(p):00000c6c=9c(?); RealRAM(p):00b9bc6d=50(P); RAM(p):00bfbc6d=50(P); Physical(p):00bfbc6d=50(P); Paged(p):ff801c6d=50(P); Normal(p):00000c6d=50(P); RealRAM(p):00b9bc6e=1e(); RAM(p):00bfbc6e=1e(); Physical(p):00bfbc6e=1e(); Paged(p):ff801c6e=1e(); Normal(p):00000c6e=1e(); RealRAM(p):00b9bc6f=6a(j); RAM(p):00bfbc6f=6a(j); Physical(p):00bfbc6f=6a(j); Paged(p):ff801c6f=6a(j); Normal(p):00000c6f=6a(j); RealRAM(p):00b9bc70=4b(K); RAM(p):00bfbc70=4b(K); Physical(p):00bfbc70=4b(K); Paged(p):ff801c70=4b(K); Normal(p):00000c70=4b(K); RealRAM(p):00b9bc71=1f(); RAM(p):00bfbc71=1f(); Physical(p):00bfbc71=1f(); Paged(p):ff801c71=1f(); Normal(p):00000c71=1f(); RealRAM(p):00b9bc72=a0(?); RAM(p):00bfbc72=a0(?); Physical(p):00bfbc72=a0(?); Paged(p):ff801c72=a0(?); Normal(p):00000c72=a0(?); RealRAM(p):00b9bc73=17(); RAM(p):00bfbc73=17(); Physical(p):00bfbc73=17(); Paged(p):ff801c73=17(); Normal(p):00000c73=17(); RealRAM(p):00b9bc74=04(); RAM(p):00bfbc74=04(); Physical(p):00bfbc74=04(); Paged(p):ff801c74=04(); Normal(p):00000c74=04(); RealRAM(p):00b9bc75=00( ); RAM(p):00bfbc75=00( ); Physical(p):00bfbc75=00( ); Paged(p):ff801c75=00( ); Normal(p):00000c75=00( ); RealRAM(p):00b9bc76=00( ); RAM(p):00bfbc76=00( ); Physical(p):00bfbc76=00( ); Paged(p):ff801c76=00( ); Normal(p):00000c76=00( ); RealRAM(p):00b9bc77=24($); RAM(p):00bfbc77=24($); Physical(p):00bfbc77=24($); Paged(p):ff801c77=24($); Normal(p):00000c77=24($); RealRAM(p):00b9bc78=0c(); RAM(p):00bfbc78=0c(); Physical(p):00bfbc78=0c(); Paged(p):ff801c78=0c(); Normal(p):00000c78=0c(); RealRAM(p):00b9bc79=3c(<); RAM(p):00bfbc79=3c(<); Physical(p):00bfbc79=3c(<); Paged(p):ff801c79=3c(<); Normal(p):00000c79=3c(<); RealRAM(p):00b9bc7a=0c(); RAM(p):00bfbc7a=0c(); Physical(p):00bfbc7a=0c(); Paged(p):ff801c7a=0c(); Normal(p):00000c7a=0c(); RealRAM(p):00b9bc7b=75(u); RAM(p):00bfbc7b=75(u); Physical(p):00bfbc7b=75(u); Paged(p):ff801c7b=75(u); Normal(p):00000c7b=75(u); RealRAM(p):00b9bc7c=06(); RAM(p):00bfbc7c=06(); Physical(p):00bfbc7c=06(); Paged(p):ff801c7c=06(); Normal(p):00000c7c=06(); RealRAM(p):00b9bc7d=e4(?); RAM(p):00bfbc7d=e4(?); Physical(p):00bfbc7d=e4(?); Paged(p):ff801c7d=e4(?); Normal(p):00000c7d=e4(?); RealRAM(p):00b9bc7e=60(`); RAM(p):00bfbc7e=60(`); Physical(p):00bfbc7e=60(`); Paged(p):ff801c7e=60(`); Normal(p):00000c7e=60(`); RealRAM(p):00b9bc7f=3c(<); RAM(p):00bfbc7f=3c(<); Physical(p):00bfbc7f=3c(<); Paged(p):ff801c7f=3c(<); Normal(p):00000c7f=3c(<); RealRAM(p):00b9bc80=53(S); RAM(p):00bfbc80=53(S); Physical(p):00bfbc80=53(S); Paged(p):ff801c80=53(S); Normal(p):00000c80=53(S); RealRAM(p):00b9bc81=74(t); RAM(p):00bfbc81=74(t); Physical(p):00bfbc81=74(t); Paged(p):ff801c81=74(t); Normal(p):00000c81=74(t); RealRAM(p):00b9bc82=04(); RAM(p):00bfbc82=04(); Physical(p):00bfbc82=04(); Paged(p):ff801c82=04(); Normal(p):00000c82=04(); RealRAM(p):00b9bc83=1f(); RAM(p):00bfbc83=1f(); Physical(p):00bfbc83=1f(); Paged(p):ff801c83=1f(); Normal(p):00000c83=1f(); RealRAM(p):00b9bc84=58(X); RAM(p):00bfbc84=58(X); Physical(p):00bfbc84=58(X); Paged(p):ff801c84=58(X); Normal(p):00000c84=58(X); RealRAM(p):00b9bc85=9d(?); RAM(p):00bfbc85=9d(?); Physical(p):00bfbc85=9d(?); Paged(p):ff801c85=9d(?); Normal(p):00000c85=9d(?); RealRAM(p):00b9bc86=c3(?); RAM(p):00bfbc86=c3(?); Physical(p):00bfbc86=c3(?); Paged(p):ff801c86=c3(?); Normal(p):00000c86=c3(?); RealRAM(p):00b9bc87=67(g); RAM(p):00bfbc87=67(g); Physical(p):00bfbc87=67(g); Paged(p):ff801c87=67(g); Normal(p):00000c87=67(g)
0020:00000c68 C3 retd RealRAM(r):000111a8=21(!); RAM(r):000111a8=21(!); Physical(r):000111a8=21(!); Paged(r):000111a8=21(!); RealRAM(r):000111a9=00( ); RAM(r):000111a9=00( ); Physical(r):000111a9=00( ); Paged(r):000111a9=00( ); RealRAM(r):000111aa=00( ); RAM(r):000111aa=00( ); Physical(r):000111aa=00( ); Paged(r):000111aa=00( ); RealRAM(r):000111ab=00( ); RAM(r):000111ab=00( ); Physical(r):000111ab=00( ); Paged(r):000111ab=00( ); RealRAM(p):00b9b021=44(D); RAM(p):00bfb021=44(D); Physical(p):00bfb021=44(D); Paged(p):ff801021=44(D); Normal(p):00000021=44(D); RealRAM(p):00b9b022=24($); RAM(p):00bfb022=24($); Physical(p):00bfb022=24($); Paged(p):ff801022=24($); Normal(p):00000022=24($); RealRAM(p):00b9b023=18(); RAM(p):00bfb023=18(); Physical(p):00bfb023=18(); Paged(p):ff801023=18(); Normal(p):00000023=18(); RealRAM(p):00b9b024=c5(?); RAM(p):00bfb024=c5(?); Physical(p):00bfb024=c5(?); Paged(p):ff801024=c5(?); Normal(p):00000024=c5(?); RealRAM(p):00b9b025=74(t); RAM(p):00bfb025=74(t); Physical(p):00bfb025=74(t); Paged(p):ff801025=74(t); Normal(p):00000025=74(t); RealRAM(p):00b9b026=24($); RAM(p):00bfb026=24($); Physical(p):00bfb026=24($); Paged(p):ff801026=24($); Normal(p):00000026=24($); RealRAM(p):00b9b027=38(8); RAM(p):00bfb027=38(8); Physical(p):00bfb027=38(8); Paged(p):ff801027=38(8); Normal(p):00000027=38(8); RealRAM(p):00b9b028=8c(?); RAM(p):00bfb028=8c(?); Physical(p):00bfb028=8c(?); Paged(p):ff801028=8c(?); Normal(p):00000028=8c(?); RealRAM(p):00b9b029=d8(?); RAM(p):00bfb029=d8(?); Physical(p):00bfb029=d8(?); Paged(p):ff801029=d8(?); Normal(p):00000029=d8(?); RealRAM(p):00b9b02a=66(f); RAM(p):00bfb02a=66(f); Physical(p):00bfb02a=66(f); Paged(p):ff80102a=66(f); Normal(p):0000002a=66(f); RealRAM(p):00b9b02b=3d(=); RAM(p):00bfb02b=3d(=); Physical(p):00bfb02b=3d(=); Paged(p):ff80102b=3d(=); Normal(p):0000002b=3d(=); RealRAM(p):00b9b02c=87(?); RAM(p):00bfb02c=87(?); Physical(p):00bfb02c=87(?); Paged(p):ff80102c=87(?); Normal(p):0000002c=87(?); RealRAM(p):00b9b02d=00( ); RAM(p):00bfb02d=00( ); Physical(p):00bfb02d=00( ); Paged(p):ff80102d=00( ); Normal(p):0000002d=00( ); RealRAM(p):00b9b02e=75(u); RAM(p):00bfb02e=75(u); Physical(p):00bfb02e=75(u); Paged(p):ff80102e=75(u); Normal(p):0000002e=75(u); RealRAM(p):00b9b02f=0e(); RAM(p):00bfb02f=0e(); Physical(p):00bfb02f=0e(); Paged(p):ff80102f=0e(); Normal(p):0000002f=0e(); RealRAM(p):00b9b030=66(f); RAM(p):00bfb030=66(f); Physical(p):00bfb030=66(f); Paged(p):ff801030=66(f); Normal(p):00000030=66(f); RealRAM(p):00b9b031=81(?); RAM(p):00bfb031=81(?); Physical(p):00bfb031=81(?); Paged(p):ff801031=81(?); Normal(p):00000031=81(?); RealRAM(p):00b9b032=fe(?); RAM(p):00bfb032=fe(?); Physical(p):00bfb032=fe(?); Paged(p):ff801032=fe(?); Normal(p):00000032=fe(?); RealRAM(p):00b9b033=ec(?); RAM(p):00bfb033=ec(?); Physical(p):00bfb033=ec(?); Paged(p):ff801033=ec(?); Normal(p):00000033=ec(?); RealRAM(p):00b9b034=0f(); RAM(p):00bfb034=0f(); Physical(p):00bfb034=0f(); Paged(p):ff801034=0f(); Normal(p):00000034=0f(); RealRAM(p):00b9b035=75(u); RAM(p):00bfb035=75(u); Physical(p):00bfb035=75(u); Paged(p):ff801035=75(u); Normal(p):00000035=75(u); RealRAM(p):00b9b036=07(); RAM(p):00bfb036=07(); Physical(p):00bfb036=07(); Paged(p):ff801036=07(); Normal(p):00000036=07(); RealRAM(p):00b9b037=67(g); RAM(p):00bfb037=67(g); Physical(p):00bfb037=67(g); Paged(p):ff801037=67(g); Normal(p):00000037=67(g); RealRAM(p):00b9b038=36(6); RAM(p):00bfb038=36(6); Physical(p):00bfb038=36(6); Paged(p):ff801038=36(6); Normal(p):00000038=36(6); RealRAM(p):00b9b039=c6(?); RAM(p):00bfb039=c6(?); Physical(p):00bfb039=c6(?); Paged(p):ff801039=c6(?); Normal(p):00000039=c6(?); RealRAM(p):00b9b03a=06(); RAM(p):00bfb03a=06(); Physical(p):00bfb03a=06(); Paged(p):ff80103a=06(); Normal(p):0000003a=06(); RealRAM(p):00b9b03b=d6(?); RAM(p):00bfb03b=d6(?); Physical(p):00bfb03b=d6(?); Paged(p):ff80103b=d6(?); Normal(p):0000003b=d6(?); RealRAM(p):00b9b03c=11(); RAM(p):00bfb03c=11(); Physical(p):00bfb03c=11(); Paged(p):ff80103c=11(); Normal(p):0000003c=11(); RealRAM(p):00b9b03d=00( ); RAM(p):00bfb03d=00( ); Physical(p):00bfb03d=00( ); Paged(p):ff80103d=00( ); Normal(p):0000003d=00( ); RealRAM(p):00b9b03e=8b(?); RAM(p):00bfb03e=8b(?); Physical(p):00bfb03e=8b(?); Paged(p):ff80103e=8b(?); Normal(p):0000003e=8b(?); RealRAM(p):00b9b03f=3e(>); RAM(p):00bfb03f=3e(>); Physical(p):00bfb03f=3e(>); Paged(p):ff80103f=3e(>); Normal(p):0000003f=3e(>); RealRAM(p):00b9b040=8b(?); RAM(p):00bfb040=8b(?); Physical(p):00bfb040=8b(?); Paged(p):ff801040=8b(?); Normal(p):00000040=8b(?)
Registers:
EAX: 00002fa0 EBX: 00000080 ECX: 0004ffff EDX: 00000000
ESP: 000007b8 EBP: 000007cc ESI: 00000090 EDI: 00014462
CS: 0020 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 0028 TR: 0030 LDTR: 0038
EIP: 00000c68 EFLAGS: 00003046
CR0: e0000031 CR1: 00000000 CR2: 00000000 CR3: 00bff000
CR4: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000ff80880007ff IDTR: 0000ff80900007ff
FLAGSINFO: 0000000000i00avr0n11oditsZ0a0P1c
0020:00000021 44 inc esp
Registers:
EAX: 00002fa0 EBX: 00000080 ECX: 0004ffff EDX: 00000000
ESP: 000007bc EBP: 000007cc ESI: 00000090 EDI: 00014462
CS: 0020 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 0028 TR: 0030 LDTR: 0038
EIP: 00000021 EFLAGS: 00003046
CR0: e0000031 CR1: 00000000 CR2: 00000000 CR3: 00bff000
CR4: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000ff80880007ff IDTR: 0000ff80900007ff
FLAGSINFO: 0000000000i00avr0n11oditsZ0a0P1c
0020:00000022 24 18 and al,18 RealRAM(p):00b9b041=5e(^); RAM(p):00bfb041=5e(^); Physical(p):00bfb041=5e(^); Paged(p):ff801041=5e(^); Normal(p):00000041=5e(^)
Registers:
EAX: 00002fa0 EBX: 00000080 ECX: 0004ffff EDX: 00000000
ESP: 000007bd EBP: 000007cc ESI: 00000090 EDI: 00014462
CS: 0020 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 0028 TR: 0030 LDTR: 0038
EIP: 00000022 EFLAGS: 00003006
CR0: e0000031 CR1: 00000000 CR2: 00000000 CR3: 00bff000
CR4: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000ff80880007ff IDTR: 0000ff80900007ff
FLAGSINFO: 0000000000i00avr0n11oditsz0a0P1c

The instruction right before the faulting instruction. See that inc esp instruction? Because ESP is incremented by 1, the pointer to the data is being messed up, so it's also 1 ahead, thus the invalid pointer? If said pointer wasn't already incorrect enough or incorrect to begin with?

Edit: Interestingly enough, searching the location pointed to by ESP during the inc esp instruction, searching upwards, shows a "6A 21 PUSH 21" instruction, according to disassembly?

0020:000039ec 6A 21 push 21	Paged(w):000111a8=21(!); Physical(w):000111a8=21(!); RAM(w):000111a8=21(!); RealRAM(w):000111a8=21(!); Paged(w):000111a9=00( ); Physical(w):000111a9=00( ); RAM(w):000111a9=00( ); RealRAM(w):000111a9=00( ); Paged(w):000111aa=00( ); Physical(w):000111aa=00( ); RAM(w):000111aa=00( ); RealRAM(w):000111aa=00( ); Paged(w):000111ab=00( ); Physical(w):000111ab=00( ); RAM(w):000111ab=00( ); RealRAM(w):000111ab=00( )
Registers:
EAX: 00002fa0 EBX: 000000a7 ECX: 0004ffff EDX: 00000000
ESP: 000007bc EBP: 000007cc ESI: 00000090 EDI: 00014462
CS: 0020 DS: 0000 ES: 0000 FS: 0000 GS: 0000 SS: 0028 TR: 0030 LDTR: 0038
EIP: 000039ec EFLAGS: 00003046
CR0: e0000031 CR1: 00000000 CR2: 00000000 CR3: 00bff000
CR4: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000ff80880007ff IDTR: 0000ff80900007ff
FLAGSINFO: 0000000000i00avr0n11oditsZ0a0P1c

Both before said instruction, as well as after said instruction, is a CALLD instruction(32-bit near CALL). Is said PUSH working correctly? Afaik said instruction is supposed to push a 32-bit value on the stack and descrease ESP by 2 or 4(depending on the operand size, which in this case is 32-bit) before that?

Edit: Even more interesingly: what do I see immediately after the push to the same address is a CALL to our C3C address that's providing the triple fault(although at a different address of course)!

Last edited by superfury on 2019-02-20, 17:58. Edited 1 time in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 23 of 591, by keenmaster486

User metadata
Rank l33t
Rank
l33t

Try the following binaries (fyi, they should still work with the game files you have. If you get loading errors I'll send you the updated files):

The original (compiler switches: "-arch 386 -l wmemu -t 2048" - architecture: 386, load library wmemu (FPU emulator), stack size 2048 KB):

Filename
ENGINE.EXE
File size
274.5 KiB
Downloads
127 downloads
File license
Fair use/fair dealing exception

Compiler switches "-arch 386 -l wmemu" (default stack size of 1024 KB)

Filename
ENGINE1.EXE
File size
311.5 KiB
Downloads
123 downloads
File license
Fair use/fair dealing exception

Compiler switches "-arch 386" (no FPU emulator, perhaps try running with emu87):

Filename
ENGINE2.EXE
File size
274.5 KiB
Downloads
124 downloads
File license
Fair use/fair dealing exception

No compiler switches (default architecture target of 486, no FPU emulator, default stack size of 1024 KB):

Filename
ENGINE3.EXE
File size
274.5 KiB
Downloads
131 downloads
File license
Fair use/fair dealing exception

I just noticed that the only one with a greater binary size is ENGINE1.EXE. Perhaps the -t 2048 switch was interfering somehow with the inclusion of the FPU emulator.

Edit: just noticed your edits to post above. I'm not well versed in assembly but the stack problem thing is intriguing. Perhaps that has something to do with it.

World's foremost 486 enjoyer.

Reply 24 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++

I'll try your four versions, although without FPU emulation it will crash 100% sure(since no FPU is emulated at all).

Also note the EIP=C3C CALL immediately after the location that the INC ESP is working on. That seems to somehow be a hint towards what might be going on!

Edit: So far, ENGINE has the same problem.
Edit: Same with ENGINE1.
Edit: ENGINE2&3: Can't find any EMU87 when googling. So I can't test those, except without FPU?

Edit: Just ran CWSDPMI and then ENGINE. This reports a Double fault, but no Double fault is thrown by the emulator?

1048-Engine-CWSDPMI-DoubleFault.jpg
Filename
1048-Engine-CWSDPMI-DoubleFault.jpg
File size
79.5 KiB
Views
2583 views
File comment
CWSDPMI then ENGINE = 'Double Fault'?
File license
Fair use/fair dealing exception
Last edited by superfury on 2019-02-20, 18:19. Edited 1 time in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 26 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++

Do I just add said EMU387.ZIP to the folder? Or do I need to extract those files inside the folder?
Edit: Already found the answer inside the documentation inside the ZIP folder.

But the program doesn't crash on any FPU opcodes yet? The cause of this is way before that it seems?
Edit: Added FPU emulator anyways. Same result with ENGINE2(no Coprocessor opcodes thrown faults yet).
Edit: And the same result again with ENGINE3.

Last edited by superfury on 2019-02-20, 18:37. Edited 1 time in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 27 of 591, by keenmaster486

User metadata
Rank l33t
Rank
l33t

Testing on PCem reveals that none of my binaries now work on the 486DX2/66 emulation. Whaaat? They worked a few weeks ago when I was testing this! I didn't change anything that would cause that, at least not that I know of - other than using the new version of the FreeBasic compiler.

Testing on PCem 386SX shows that ENGINE1.EXE is the only one that actually starts to load, but selecting a level throws a page fault on the sound effects loading code, also strange because all that code does is basic file I/O.

Edit: The first thing the engine does when you run it is allocate memory for various pointers which will later be used to point to graphics pages, plus some memory for various things such as sound and music data, stored in arrays. Perhaps that is what is tripping it up. There is also a timer routine that modifies the DOS timer to have enough resolution to time the framerate.

World's foremost 486 enjoyer.

Reply 28 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++

Perhaps there's a problem with the HDPMI32 executable I'm trying to run it with?

Edit: Running no extender before starting it, I see a lot of page faults(which didn't appear when using the HDPMI32 loader) for address 0x400000, but the first time it ends up at a Double Fault. And the second time I run it I get a FPU overrun?

1049-Running Engine1 twice - FPU overrun.jpg
Filename
1049-Running Engine1 twice - FPU overrun.jpg
File size
77.86 KiB
Views
2575 views
File comment
Running ENGINE1 twice.
File license
Fair use/fair dealing exception

Edit: Even better, after said 'FPU overrun', the keyboard is completely unresponsive?
Edit: All I see are page faults?

Last edited by superfury on 2019-02-20, 18:48. Edited 1 time in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 29 of 591, by keenmaster486

User metadata
Rank l33t
Rank
l33t

ENGINE1 has the FPU emulator, so you *shouldn't* need to load EMU87 before that one.

Edit: I've tried HDPMI32 and CWSDPMI both, and haven't been able to get the engine to behave any differently with either one of them.

World's foremost 486 enjoyer.

Reply 30 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++

interestingly, I see it page faulting on the range of 4XXXXX to around 51XXXX, starting with an address ending in 600(400600?) if I remember correctly.

I see that range being page faulted each time I run the ENGINE1 executable(without any other drivers added, no HDPMI32 nor CWSDPMI).

1050-Engine1 failing. No drivers or loaders.jpg
Filename
1050-Engine1 failing. No drivers or loaders.jpg
File size
101.73 KiB
Views
2572 views
File comment
Without any drivers loaded.
File license
Fair use/fair dealing exception

Edit: It's 401800. Up to and including address 461000 in 0x1000 increments(from 401800 to 402000, then increments of 1000).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 31 of 591, by keenmaster486

User metadata
Rank l33t
Rank
l33t

Having tested in 86Box I can confirm that in that emulator, it (the default exe) loads and runs correctly on a 386DX/40 and a 486DX2/66. Very slow on the 386 though, but that's a different issue. Normal speed on the DX2/66. On a 486SX/33, it gets to the level select screen, and throws a page fault after I select a level.

World's foremost 486 enjoyer.

Reply 32 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++
keenmaster486 wrote:

Having tested in 86Box I can confirm that in that emulator, it (the default exe) loads and runs correctly on a 386DX/40 and a 486DX2/66. Very slow on the 386 though, but that's a different issue. Normal speed on the DX2/66. On a 486SX/33, it gets to the level select screen, and throws a page fault after I select a level.

By "the default exe", do you mean the latest build exe that you sent a few posts back(the one from the drive), or the ENGINE.EXE from your list of ENGINE-ENGINE3.EXE?
Edit: That drive version only throws Page faults, and itself crashes with a 'Double fault' (even though no Double fault is thrown by the emulator. Perhaps an INT 08h, like a timer interrupt?).

Edit: Yes, that's the problem: the reported 'Double Fault' at EIP=315/318 is actually just a timer interrupt(IRQ0) being thrown incorrectly! Why hasn't it rerouted said interrupt or disabled interrupts?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 33 of 591, by keenmaster486

User metadata
Rank l33t
Rank
l33t

"Default" as in either the exe from the drive, or the first one I posted in the list - both were compiled with the same compiler flags.

The timer code I'm using utilizes IRQ8 - but I do happen to know that fbgfx (the FreeBasic graphics library) does install an IRQ0 timer. I just don't know what it is used for.

My timer code was not written by me, it's the code here: https://www.freebasic.net/forum/viewtopic.php?t=18260

World's foremost 486 enjoyer.

Reply 34 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++

Well, the problem in this case is that the PIC isn't reprogrammed correctly it seems, as it receives either an IRQ0 or IRQ8 from interrupt vector 08h, which is the double fault interrupt. When it receives that, it misdiagnoses that to be a double fault?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 35 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just now trying to run Descent. I see it at least page faulting some times, as well as reporting something it calls Virtual memory?

Said memory addresses are just past the 1GB virtual memory(at address 1XXXXXXXh)? At least during the intro?
Edit: I also see it task switching during Page Faults(using hardware task switching)?
Edit: I also see that the LDTR is loaded with a non-NULL value, so that's active as well.
And the CS descriptor is a 4GB flat one. So it's a full-blown 32-bit application, that's at least running until the main menu loading? 😁

Edit: Also nice, it's also using the processor's feature of emulating the FPU(using the EM bit in CR0)! 😁
Edit: Those EM triggers are at least for opcode 9B(FWAIT).
Edit: There was a problem with the CR0 EM bit triggering faults for FWAIT instructions instead of ESC instructions. Having fixed this, I now see it continuing to load data(Big DESCENT text in red over a rocky background with "LOADING DATA..." (unquoted) at the bottom of the screen)...
Edit: After a while loading, it reaches a pilot selection screen. 😁
Edit: So far progressed to some kind of storytelling...
Edit: Pressed ESC to skip it...
Edit: Prepare for descent...
Edit: The level is running properly.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 36 of 591, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie

That's a bit weird, I'm very familiar with Descent's source code and it doesn't use floating point math - all the 3D stuff is completely fixed-point/integer based. If there's any FPU ops they must be in the audio driver (the HMI stuff) or VR drivers since they were 3rd party and not included with the source.

Reply 37 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried Wing Commander: Privateer once again with the latest bugfixes. It now at least shows a globe(the start of the cutscene), but seems unresponsive after that(or very, very slow)?

I only have HIMEM.SYS loaded(From MS-DOS 6.22).

Edit: Also just tried Dark Seed(which I've seen a bit of somewhere). It seems to run fine, except the cutscenes at the beginning(until the main game starts), where it's only displaying a black screen?

Edit: Interestingly, during Privateer's cutscene, the interrupt flag is NEVER enabled? So perhaps that's part of the problem?
Edit: It's in V86 mode, with the Interrupt flag disabled?
Edit: POPFD properly handles the Interrupt flag in those cases(either modifying it or not modifiying it at all during privilege being denied). But perhaps IRETD is causing a problem there?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 38 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmmm.... What happens when an IRETD is executed from protected mode, with EFLAGS.VM on the stack being set and CPL not being 0? The 80386 documentation says it's a normal protected-mode IRET(D) in that case, handling a return back to protected mode. But what happens with the VM flag in the EFLAGS register in that case? Is it set anyways? Or is it ignored(unmodified by thr IRET instruction) for said bit only, like POPFD does?

https://www.felixcloutier.com/x86/iret:iretd looks like it's saying it's actually ignored during the POPFD part of IRETD?
Edit: I've changed the IRETD instruction to ignore the VM flag if it's set when CPL isn't 0. Essentially the same is done as with IOPL, but it's not depending on any CPL, just always applied when not returning to V86 from CPL 0(and of course in protected mode, not returning to a different task or from V86 mode).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 39 of 591, by superfury

User metadata
Rank l33t++
Rank
l33t++

One strange thing that I notice when running various games(currently optimizing CPU emulation) is that the framerate is very low? Even though the full framerate should be 25 to 30FPS(e.g. for Descent 6FPS(6 frames/second rendered by the VGA) at 18%, so 6/0.18=33FPS inside the CPU, but the framerate looks more like 3 seconds/frame, so 0.3FPS in realtime(which translates to (1/3)/0.18=1.8FPS from the perspective of the emulated CPU.

Perhaps it's using the CMOS clock(100 realtime Hz) as a timing source(the only component that isn't in sync with the rest of the system(except timing updates themselves))? Or even worse, the Sound Blaster realtime recording clock(which runs at a realtime rate of 44.1kHz, translating realtime samples to the emulated clock)?

The demo playback percentage of the first demo of Descent seems to change every 6 seconds(so every 2 frames that are rendered, while each a new frame is rendered every 3 seconds).

The CPU itself is running at 3MIPS (using the IPS clocking mode).
Edit: The problem doesn't seem to be CMOS-related, seeing as putting it in cycle-accurate mode doesn't change said behaviour.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io