VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

I can see that, somehow, Jazz Jackrabbit crashes when configured for Sound Blaster and using a Sound Blaster 2.0 card on UniPCemu(DSP reporting as version "2.o1". DSP Version "2.00" (older UniPCemu builds) before that change don't crash it).

https://bitbucket.org/superfury/unipcemu/src/ … /soundblaster.c

When using said card instead of a 1.x card, it crashes with a stack fault pretty much immediately after starting the DMA for the Sound Blaster audio?

Anyone knows anything about this?
Edit: It's probably a problem with the Sound Blaster 2.0 or it's driver that's causing the stack fault? Since the only thing the hardware changes with the newer version(2.0 vs 1.x) is the new commands and it's version number(2.01 vs 1.05), perhaps the issue has something to do with that?
The last thing I see it do is starting up DMA autoinit 8-bit PCM playback(don't know if it's high speed or not) just before crashing on SB2.0?

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

Reply 1 of 47, by Jo22

User metadata
Rank l33t++
Rank
l33t++

Hi! Not sure if this helpful, but I used to play Jazz Jackrabbit with a Pro AudioSpectrum 16.
As you know, it also incorporates a ThunderBoard chipset, which is roughly SB 1.5 compatible.
Again not sure if this is helpful. Just wanted to note that actual SB 2.0 compatibility is perhaps not needed, even.
At Mobygames, there's a photography of a Jazz game box. it just says "Jazz Jackrabbit supports: Sound Blaster"
https://www.mobygames.com/game/dos/jazz-jackr … CoverId,134302/

"Time, it seems, doesn't flow. For some it's fast, for some it's slow.
In what to one race is no time at all, another race can rise and fall..." - The Minstrel

//My video channel//

Reply 2 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

Well, that very first DMA transaction is weird as well(at least on the SB side, haven't checked the DMA chip yet): the DMA block size(which was set immediately before that) is set to 0, thus only 1 byte(sample) of audio before issuing it's interrupt? Is that supposed to happen normally?

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

Reply 3 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. This is a list of written bytes:
0xE1(Version command). Gives 2.1(firstbyte.secondbyte).
0xD1(Enable speaker).
0xE1(Version command). See first call.
0xD1(Enable speaker).
0x40(Set time constant).
0xAE(Set time constant parameter: 12195Hz)
0x1C(Auto-initialize DMA DAC). This uses a block size of 0(reset default)? Thus 1 sample.
DMA sample: 0x80. Raises an IRQ. Autoinit of SB2.0 resets for 1 sample to render. Starts playback for said sample on the timing that's setup(when the timer ticks again for rendering the buffered sample).

Then I see it raising interrupts for each rendered sample, with them being acnowledged by a read from the DSP's data register.

Edit: Just have been making some little notes about the DREQ bitflags(a simple byte value containing the status of DMA playback to use), which is mainly used for setting and clearing DREQ(It's the SOUNDBLASTER.DREQ variable):

Flag bits(hex bit values(OR'ed together)):
x1=Transfer running
x2=Acnowledged, waiting for playback to happen. Set by SB DMA autoinit and samples left to render when sending a sample to render.
x4=Acnowledged DREQ. Cleared by timing of a sample(both silent and from the rendering buffer). Set by DACK being raised by the DMA controller.
x8=Waiting for IRQ to be acnowledged to resume DMA playback. Set by SB DMA executing autoinit when raising an IRQ. Cleared when acnowledging an raised IRQ that was pending.
x10=Recording flag. Ignored for DMA purposes.

Bit values 1 and x10(only when recording) are set when starting a DMA playback operation.

The DMADisabled flag

The DREQ signal for the DMA controller is raised(set high) when all bits are cleared but bit 0. Bit 4 is ignored for DMA DREQ determination and DMA isn't disabled by the DMADisabled flag(when it's zeroed).

DREQ is fully cleared when DMA finishes, DMA command is given(before completing it), Direct ADC command is given, Set DMA Block Size command is given, Direct DAC command is completed, DMA DAC finishes(without autoinit) it's samples(programmed count or DMA block count), DAC is silenced, DMA ADC finished without autoinit, and finally when the DSP is reset.

DMADisabled is:
- Initialized to zero.
- Set by silencing samples raising an IRQ on completion.
- Cleared when starting a new DMA transfer.
- Set by command D0(Halt DMA operation, 8-bit) when DREQ isn't zero.
- Cleared by command D4(Continue DMA operation, 8-bit) when set.
- Cleared by command 10(Direct DAC).

One interesting thing: when trying to restart jazz.exe when it's crashed with exception 0xC, it complains that it can't find setup.exe? CS is 0x20 when it crashes, with it pointing to a memory location above 1MB? SS is seemingly 16-bit, with the PUSHA(D) instruction crashing on memory location of (E)SP=FFFE? The full ESP value that's being used is 0xFFFFFFFF, but it might only be using the lower 16-bits in 16-bit mode?
Edit: It's a PUSHAD at 0020:132F. CS=Base:101000,limit:ffff. SS=Base:14C50,limit:ffff.EFLAGS=3002.
So it's probably during some interrupt handling this happens(since EFLAGS.IF=0)?

Edit: A full log(common emulator logging format, but with extended information(e.g. memory writes/read etc.)) of segment 20h executing for Jazz Jackrabbit(protected mode): https://www.dropbox.com/s/ng2wvs6a6b9kp0p/deb … 6_SB2.0.7z?dl=0

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

Reply 4 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. Found out some stuff about the memory manager of Jazz Jackrabbit, as it's crashing:
TR(0158) is the current task. TR+8=Current task as a data segment, TR+0x10=TR's LDT. Probably TR+0x18=TR's LDT as a data segment?
Then, I found out that DS:0401 bit 4 seems to be some bit determining 32-bittyness, making the return to the caller or something like that(at 0020:13eb) jump to a 32-bit PUSHAD/POPAD (POPAD in normal POPs and SUB for SP?) or a plain 16-bit POPA instruction?

I see it setting the IOPL on the stack, as well as inspecting the current task and modifying it's SP value using the TR+8 descriptor(the current task's data segment descriptor).
Edit: OK. Strange: I see it setting the SP0 in the task to FFFFh at 0020:00001363.

Hmmm... I then see it matching some descriptor(B3) to some memory value and the interrupt flag being set on the stack(&0x200), then jumping to a place it hadn't been before: 0020:00003e80. So, it's found out the original task(?) is a user-mode task, then takes some special action based on that... Hmmm...
Edit: It then clears bit 2 of byte DS:[403], which it was looking at for something earlier...
Edit: Then checks something for user mode again(417h)?
Edit: Actually, non-user mode is non-CPL0 instead(so CPL of 1,2 or 3 is counted the same). So it's checking against the kernel privilege(CPL 0) itself and goes on based on that.
I now end up at 0020:00003f44.
Edit: Oooohhh.... I see something interesting: The jump based on the difference of the start of the IRQ handler eventually takes a different path: the difference is 0xC(thus jumping to 0020:00000cbc). Since the difference is 0xC, that means 12 bytes are pushed on the stack(EIP(at BP),CS(at BP+4),EFLAGS(at BP+8)) and thus an interrupt/exception from the kernel level, setting ESP from FF8h to FECh(the base address of the interrupt handler's 'parameters'), so it's not an exception handler, but instead a interrupt call to whatever interrupt handler is running?
Edit: It gets to 0020:00003d23 because it's not a 0xD fault handler(it's an kernel privileged interrupt call after all).
Edit: Hmmm... Interrupt 0xD is for MS-DOS the IRQ5 handler, so it's probably an interrupt arriving from the Sound Blaster 2.0?
Edit: Then it checks against interrupt 0x34, which doesn't match, so it jumps to 0020:35D0.
Edit: It loads TSS+68h into AX, so that's a lot after the 80286 TSS's end(0x26BC), then 2 bytes after that to DX(0x417). Perhaps some kind of pointer(417:26BC)?
Edit: It loads 5B into ES at 0020:00003663...
Edit: OK. So it is overwriting at B3:0002 with EFLAGS=0x3202, so running with interrupts(as it should when handling a hardware interrupt, in this case the Sound Blaster IRQ, seeing from the start of the 0x20:xxxx handler).
Edit: I see it copying said block of memory(B3:0002 as CS:IP and EFLAGS=0x3202) over the return address?
Edit: Eventually, there's an IRET to the IRQ handler(?), which pops 26BCh(IP), 0417h(CS), 3000h(EFLAGS), 0ffah(SP), 005bh(SS). So it returns to said PL3 IRQ5 interrupt handler?
It eventually reaches an interrupt handler at 0020:0C7a again?
Edit: ESP is FAA at both the IRET and when returning to the handler at 0020:0C7A, so it's handling a new event or interrupt nested within the old interrupt handler of PL3(probably the one launched the previous IRET)?
Edit: I see ESP keep being the same between IRET and the start of the 0xD handler, while it keeps adding 2 more bytes(error code) ever other interrupt?
Edit: Said exception at segment 417h seems to be the origin of the stack overflow? Seeing as it's calling seems to cause the 2-byte decrement in ESP when the GP fault handler starts, thus pushing an error code for some error to be handled?
Edit: Making a log of segment 417h I see it executing IRET to segment B3 lots of times, with EBP keeps decreasing until it's really low and the kernel thread crashes. So the next step would be segment B3 instead...

Filename
debugger_UniPCemu_JazzJackrabbit_SB2.0_segment417.7z
File size
537.91 KiB
Downloads
47 downloads
File license
Fair use/fair dealing exception

Edit: OK. Segment B3 just seems to execute only one instruction: HLT at 00B3:0002, which causes a #GP fault to kernel mode, causing the stack to behave the way it does(since CPL!=0)?

Filename
debugger_UniPCemu_JazzJackrabbit_SB2.0_segmentB3.7z
File size
31.5 KiB
Downloads
44 downloads
File license
Fair use/fair dealing exception

Edit: Looking more into the B3 segment, I also see a RETF to 008F:0470 mixed in various times?
Edit: And 8F just leads to itself and segment E7 during RETF and B3 during JMP and CALLF.

Filename
debugger_UniPCemu_JazzJackrabbit_SB2.0_segment8F.7z
File size
754.73 KiB
Downloads
60 downloads
File license
Fair use/fair dealing exception

Edit: And E7 only has #NP faults and RETF to 257h, together with more of the same as above(JMPF,CALLF etc.), also segment B7 being returned to:

Filename
debugger_UniPCemu_JazzJackrabbit_SB2.0_E7.7z
File size
4.59 MiB
Downloads
65 downloads
File license
Fair use/fair dealing exception

Edit: Nothing on segment B7 either:

Filename
debugger_UniPCemu_JazzJackrabbit_SB2.0_segmentB7.7z
File size
1.79 MiB
Downloads
47 downloads
File license
Fair use/fair dealing exception

Edit: Starting to think I'm chasing an endless rabbithole...

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

Reply 5 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmm... One thing is interesting: Jazz Jackrabbit's SB2.0's GP fault handler keeps recursively faulting on INTDh handlers? The IRQ from each SB2.0 sample starts interrupt 0xD without parameters, which it adds some information to and returns to user mode with a lowered EBP, effectively allocating a stack frame for handling the interrupt in user mode. Then it IRET's back to user mode.
Eventually, user mode ends up at a HLT instruction, which causes a #GP fault to kernel mode, adding 2 bytes of the error code on top of the CS,EIP,FLAGS pushed on the stack(so it's difference isn't 0xC anymore, but 0xE instead). Then said fault handler moves ESP to EBP and the kernel's SP0 register in it's TSS, causing future fault handlers to fault with their return information(from the HLT instruction) to be stored below that. Said process is somehow never undone, so when it returns, executes user-mode code, it eventually still faults back to the kernel to handle said fault, after which it repeats the saving of the stack, which causes the user-mode HLT to repeatedly bump the stack further down, until the kernel reaches a point of storing it's user-mode registers with pusha which it can't(the stack being filled with infinitely repeated, never unwound stack frames) after which the ugly 0xC fault to the MS-DOS prompt shows itself and terminates the program, corrupting MS-DOS to the corrupted MS-DOS prompt?

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

Reply 6 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm... I see ES:[0002](which is the SP0 field in the TSS), where ES~TR(but a data segment by adding 8 to the selector) being written with a new value, but is that actually being used for the exception that follows for the HLT?
Edit: Hmmm... It loads F98h there(at 10a5f2), while the exception ends up from f8e to f8c?
Edit: It's setting SS0 to BP+44h, which seems to be constant?
Edit: Fault handling seems to be correct itself, but why does it keep decreasing BP infinitely instead of returning SS0 to it's base level(ffch?)?

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

Reply 7 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. So at the instruction where b3:0034 becomes b3:0002, the SS0 starts to lower from ff8 to fb4, where it starts to go down from there onwards?

So, it starts to decrease here:

00:20:12:96.04736: #GP fault(00000000)!
MMU: Reading from real(r): 000a7e58=7a (z)
Reading from RAM(r): 00107e58=7a (z)
Reading from physical memory(r): 00107e58=7a (z)
Reading from paged memory(r): 00107e58=7a (z)
MMU: Reading from real(r): 000a7e59=0c ()
Reading from RAM(r): 00107e59=0c ()
Reading from physical memory(r): 00107e59=0c ()
Reading from paged memory(r): 00107e59=0c ()
MMU: Reading from real(r): 000a7e5a=20 ( )
Reading from RAM(r): 00107e5a=20 ( )
Reading from physical memory(r): 00107e5a=20 ( )
Reading from paged memory(r): 00107e5a=20 ( )
MMU: Reading from real(r): 000a7e5b=00 ( )
Reading from RAM(r): 00107e5b=00 ( )
Reading from physical memory(r): 00107e5b=00 ( )
Reading from paged memory(r): 00107e5b=00 ( )
MMU: Reading from real(r): 000a7e5c=00 ( )
Reading from RAM(r): 00107e5c=00 ( )
Reading from physical memory(r): 00107e5c=00 ( )
Reading from paged memory(r): 00107e5c=00 ( )
MMU: Reading from real(r): 000a7e5d=e6 (æ)
Reading from RAM(r): 00107e5d=e6 (æ)
Reading from physical memory(r): 00107e5d=e6 (æ)
Reading from paged memory(r): 00107e5d=e6 (æ)
MMU: Reading from real(r): 000a7e5e=00 ( )
Reading from RAM(r): 00107e5e=00 ( )
Reading from physical memory(r): 00107e5e=00 ( )
Reading from paged memory(r): 00107e5e=00 ( )
MMU: Reading from real(r): 000a7e5f=00 ( )
Reading from RAM(r): 00107e5f=00 ( )
Reading from physical memory(r): 00107e5f=00 ( )
Reading from paged memory(r): 00107e5f=00 ( )
MMU: Reading from real(r): 00012800=ff (ÿ)
Reading from RAM(r): 00012800=ff (ÿ)
Reading from physical memory(r): 00012800=ff (ÿ)
Reading from paged memory(r): 00012800=ff (ÿ)
MMU: Reading from real(r): 00012801=ff (ÿ)
Reading from RAM(r): 00012801=ff (ÿ)
Reading from physical memory(r): 00012801=ff (ÿ)
Reading from paged memory(r): 00012801=ff (ÿ)
MMU: Reading from real(r): 00012802=00 ( )
Reading from RAM(r): 00012802=00 ( )
Reading from physical memory(r): 00012802=00 ( )
Reading from paged memory(r): 00012802=00 ( )
MMU: Reading from real(r): 00012803=10 ()
Reading from RAM(r): 00012803=10 ()
Reading from physical memory(r): 00012803=10 ()
Reading from paged memory(r): 00012803=10 ()
MMU: Reading from real(r): 00012804=10 ()
Reading from RAM(r): 00012804=10 ()
Reading from physical memory(r): 00012804=10 ()
Reading from paged memory(r): 00012804=10 ()
MMU: Reading from real(r): 00012805=9b (›)
Reading from RAM(r): 00012805=9b (›)
Reading from physical memory(r): 00012805=9b (›)
Reading from paged memory(r): 00012805=9b (›)
MMU: Reading from real(r): 00012806=00 ( )
Reading from RAM(r): 00012806=00 ( )
Reading from physical memory(r): 00012806=00 ( )
Show last 172 lines
Reading from paged memory(r): 00012806=00 ( )
MMU: Reading from real(r): 00012807=00 ( )
Reading from RAM(r): 00012807=00 ( )
Reading from physical memory(r): 00012807=00 ( )
Reading from paged memory(r): 00012807=00 ( )
MMU: Reading from real(r): 000127f8=ff (ÿ)
Reading from RAM(r): 000127f8=ff (ÿ)
Reading from physical memory(r): 000127f8=ff (ÿ)
Reading from paged memory(r): 000127f8=ff (ÿ)
MMU: Reading from real(r): 000127f9=ff (ÿ)
Reading from RAM(r): 000127f9=ff (ÿ)
Reading from physical memory(r): 000127f9=ff (ÿ)
Reading from paged memory(r): 000127f9=ff (ÿ)
MMU: Reading from real(r): 000127fa=50 (P)
Reading from RAM(r): 000127fa=50 (P)
Reading from physical memory(r): 000127fa=50 (P)
Reading from paged memory(r): 000127fa=50 (P)
MMU: Reading from real(r): 000127fb=4c (L)
Reading from RAM(r): 000127fb=4c (L)
Reading from physical memory(r): 000127fb=4c (L)
Reading from paged memory(r): 000127fb=4c (L)
MMU: Reading from real(r): 000127fc=01 ()
Reading from RAM(r): 000127fc=01 ()
Reading from physical memory(r): 000127fc=01 ()
Reading from paged memory(r): 000127fc=01 ()
MMU: Reading from real(r): 000127fd=93 (“)
Reading from RAM(r): 000127fd=93 (“)
Reading from physical memory(r): 000127fd=93 (“)
Reading from paged memory(r): 000127fd=93 (“)
MMU: Reading from real(r): 000127fe=00 ( )
Reading from RAM(r): 000127fe=00 ( )
Reading from physical memory(r): 000127fe=00 ( )
Reading from paged memory(r): 000127fe=00 ( )
MMU: Reading from real(r): 000127ff=00 ( )
Reading from RAM(r): 000127ff=00 ( )
Reading from physical memory(r): 000127ff=00 ( )
Reading from paged memory(r): 000127ff=00 ( )
00b3:00000034 F4 hlt RealRAM(p):000a8624=f4(ô); RAM(p):00108624=f4(ô); Physical(p):00108624=f4(ô); Paged(p):00108624=f4(ô); Normal(p):00000034=f4(ô); RealRAM(p):000a8625=01(); RAM(p):00108625=01(); Physical(p):00108625=01(); Paged(p):00108625=01(); Normal(p):00000035=01(); RealRAM(p):000a8626=31(1); RAM(p):00108626=31(1); Physical(p):00108626=31(1); Paged(p):00108626=31(1); Normal(p):00000036=31(1); RealRAM(p):000a8627=00( ); RAM(p):00108627=00( ); Physical(p):00108627=00( ); Paged(p):00108627=00( ); Normal(p):00000037=00( ); RealRAM(p):000a8628=20( ); RAM(p):00108628=20( ); Physical(p):00108628=20( ); Paged(p):00108628=20( ); Normal(p):00000038=20( ); RealRAM(p):000a8629=00( ); RAM(p):00108629=00( ); Physical(p):00108629=00( ); Paged(p):00108629=00( ); Normal(p):00000039=00( ); RealRAM(p):000a862a=2a(*); RAM(p):0010862a=2a(*); Physical(p):0010862a=2a(*); Paged(p):0010862a=2a(*); Normal(p):0000003a=2a(*); RealRAM(p):000a862b=16(); RAM(p):0010862b=16(); Physical(p):0010862b=16(); Paged(p):0010862b=16(); Normal(p):0000003b=16(); RealRAM(p):000a862c=00( ); RAM(p):0010862c=00( ); Physical(p):0010862c=00( ); Paged(p):0010862c=00( ); Normal(p):0000003c=00( ); RealRAM(p):000a862d=00( ); RAM(p):0010862d=00( ); Physical(p):0010862d=00( ); Paged(p):0010862d=00( ); Normal(p):0000003d=00( ); RealRAM(p):000a862e=f4(ô); RAM(p):0010862e=f4(ô); Physical(p):0010862e=f4(ô); Paged(p):0010862e=f4(ô); Normal(p):0000003e=f4(ô); RealRAM(p):000a862f=02(); RAM(p):0010862f=02(); Physical(p):0010862f=02(); Paged(p):0010862f=02(); Normal(p):0000003f=02(); RealRAM(p):000a8630=00( ); RAM(p):00108630=00( ); Physical(p):00108630=00( ); Paged(p):00108630=00( ); Normal(p):00000040=00( ); RealRAM(p):000a8631=00( ); RAM(p):00108631=00( ); Physical(p):00108631=00( ); Paged(p):00108631=00( ); Normal(p):00000041=00( ); RealRAM(p):000a8632=20( ); RAM(p):00108632=20( ); Physical(p):00108632=20( ); Paged(p):00108632=20( ); Normal(p):00000042=20( ); RealRAM(p):000a8633=00( ); RAM(p):00108633=00( ); Physical(p):00108633=00( ); Paged(p):00108633=00( ); Normal(p):00000043=00( ); RealRAM(r):000aa5f2=f8(ø); RAM(r):0010a5f2=f8(ø); Physical(r):0010a5f2=f8(ø); Paged(r):0010a5f2=f8(ø); Normal(r):00000002=f8(ø); RealRAM(r):000aa5f3=0f(); RAM(r):0010a5f3=0f(); Physical(r):0010a5f3=0f(); Paged(r):0010a5f3=0f(); Normal(r):00000003=0f(); RealRAM(r):000aa5f4=18(); RAM(r):0010a5f4=18(); Physical(r):0010a5f4=18(); Paged(r):0010a5f4=18(); Normal(r):00000004=18(); RealRAM(r):000aa5f5=00( ); RAM(r):0010a5f5=00( ); Physical(r):0010a5f5=00( ); Paged(r):0010a5f5=00( ); Normal(r):00000005=00( ); Normal(w):00000ff6=8f(); Paged(w):00015c46=8f(); Physical(w):00015c46=8f(); RAM(w):00015c46=8f(); RealRAM(w):00015c46=8f(); Normal(w):00000ff7=02(); Paged(w):00015c47=02(); Physical(w):00015c47=02(); RAM(w):00015c47=02(); RealRAM(w):00015c47=02(); Normal(w):00000ff4=6a(j); Paged(w):00015c44=6a(j); Physical(w):00015c44=6a(j); RAM(w):00015c44=6a(j); RealRAM(w):00015c44=6a(j); Normal(w):00000ff5=3e(>); Paged(w):00015c45=3e(>); Physical(w):00015c45=3e(>); RAM(w):00015c45=3e(>); RealRAM(w):00015c45=3e(>); Normal(w):00000ff2=12(); Paged(w):00015c42=12(); Physical(w):00015c42=12(); RAM(w):00015c42=12(); RealRAM(w):00015c42=12(); Normal(w):00000ff3=32(2); Paged(w):00015c43=32(2); Physical(w):00015c43=32(2); RAM(w):00015c43=32(2); RealRAM(w):00015c43=32(2); Normal(w):00000ff0=b3(³); Paged(w):00015c40=b3(³); Physical(w):00015c40=b3(³); RAM(w):00015c40=b3(³); RealRAM(w):00015c40=b3(³); Normal(w):00000ff1=00( ); Paged(w):00015c41=00( ); Physical(w):00015c41=00( ); RAM(w):00015c41=00( ); RealRAM(w):00015c41=00( ); Normal(w):00000fee=34(4); Paged(w):00015c3e=34(4); Physical(w):00015c3e=34(4); RAM(w):00015c3e=34(4); RealRAM(w):00015c3e=34(4); Normal(w):00000fef=00( ); Paged(w):00015c3f=00( ); Physical(w):00015c3f=00( ); RAM(w):00015c3f=00( ); RealRAM(w):00015c3f=00( ); Normal(w):00000fec=00( ); Paged(w):00015c3c=00( ); Physical(w):00015c3c=00( ); RAM(w):00015c3c=00( ); RealRAM(w):00015c3c=00( ); Normal(w):00000fed=00( ); Paged(w):00015c3d=00( ); Physical(w):00015c3d=00( ); RAM(w):00015c3d=00( ); RealRAM(w):00015c3d=00( )
Registers:
EAX: 00000205 EBX: 0000250d ECX: 00b30417 EDX: 000026bc
ESP: 00003e6a EBP: 00003e76 ESI: 00000417 EDI: 00000160
CS: 00b3 DS: 00bf ES: 00b3 FS: 0000 GS: 0000 SS: 028f TR: 0158 LDTR: 0168
EIP: 00000034 EFLAGS: 00003212
CR0: 00000001 CR1: 00000000 CR2: 00000000 CR3: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000000127e003ff IDTR: 000000107df007ff
CS descriptor: 0000FB1085F00FFF
DS descriptor: 0000F309DA3021CF
ES descriptor: 0000FB1085F00FFF
FS descriptor: 00007303B3F0FFFF
GS descriptor: 00007303C1C0FFFF
SS descriptor: 0000F31362C03FFF
TR descriptor: 00008310A5F00BF9
LDTR descriptor: 000082FCFF8007FF
FLAGSINFO: 00000000000000vr0n11odItsz0A0p1c
00:20:12:99.07760: #GP fault(00000000)!
MMU: Reading from real(r): 000a7e58=7a (z)
Reading from RAM(r): 00107e58=7a (z)
Reading from physical memory(r): 00107e58=7a (z)
Reading from paged memory(r): 00107e58=7a (z)
MMU: Reading from real(r): 000a7e59=0c ()
Reading from RAM(r): 00107e59=0c ()
Reading from physical memory(r): 00107e59=0c ()
Reading from paged memory(r): 00107e59=0c ()
MMU: Reading from real(r): 000a7e5a=20 ( )
Reading from RAM(r): 00107e5a=20 ( )
Reading from physical memory(r): 00107e5a=20 ( )
Reading from paged memory(r): 00107e5a=20 ( )
MMU: Reading from real(r): 000a7e5b=00 ( )
Reading from RAM(r): 00107e5b=00 ( )
Reading from physical memory(r): 00107e5b=00 ( )
Reading from paged memory(r): 00107e5b=00 ( )
MMU: Reading from real(r): 000a7e5c=00 ( )
Reading from RAM(r): 00107e5c=00 ( )
Reading from physical memory(r): 00107e5c=00 ( )
Reading from paged memory(r): 00107e5c=00 ( )
MMU: Reading from real(r): 000a7e5d=e6 (æ)
Reading from RAM(r): 00107e5d=e6 (æ)
Reading from physical memory(r): 00107e5d=e6 (æ)
Reading from paged memory(r): 00107e5d=e6 (æ)
MMU: Reading from real(r): 000a7e5e=00 ( )
Reading from RAM(r): 00107e5e=00 ( )
Reading from physical memory(r): 00107e5e=00 ( )
Reading from paged memory(r): 00107e5e=00 ( )
MMU: Reading from real(r): 000a7e5f=00 ( )
Reading from RAM(r): 00107e5f=00 ( )
Reading from physical memory(r): 00107e5f=00 ( )
Reading from paged memory(r): 00107e5f=00 ( )
MMU: Reading from real(r): 00012800=ff (ÿ)
Reading from RAM(r): 00012800=ff (ÿ)
Reading from physical memory(r): 00012800=ff (ÿ)
Reading from paged memory(r): 00012800=ff (ÿ)
MMU: Reading from real(r): 00012801=ff (ÿ)
Reading from RAM(r): 00012801=ff (ÿ)
Reading from physical memory(r): 00012801=ff (ÿ)
Reading from paged memory(r): 00012801=ff (ÿ)
MMU: Reading from real(r): 00012802=00 ( )
Reading from RAM(r): 00012802=00 ( )
Reading from physical memory(r): 00012802=00 ( )
Reading from paged memory(r): 00012802=00 ( )
MMU: Reading from real(r): 00012803=10 ()
Reading from RAM(r): 00012803=10 ()
Reading from physical memory(r): 00012803=10 ()
Reading from paged memory(r): 00012803=10 ()
MMU: Reading from real(r): 00012804=10 ()
Reading from RAM(r): 00012804=10 ()
Reading from physical memory(r): 00012804=10 ()
Reading from paged memory(r): 00012804=10 ()
MMU: Reading from real(r): 00012805=9b (›)
Reading from RAM(r): 00012805=9b (›)
Reading from physical memory(r): 00012805=9b (›)
Reading from paged memory(r): 00012805=9b (›)
MMU: Reading from real(r): 00012806=00 ( )
Reading from RAM(r): 00012806=00 ( )
Reading from physical memory(r): 00012806=00 ( )
Reading from paged memory(r): 00012806=00 ( )
MMU: Reading from real(r): 00012807=00 ( )
Reading from RAM(r): 00012807=00 ( )
Reading from physical memory(r): 00012807=00 ( )
Reading from paged memory(r): 00012807=00 ( )
MMU: Reading from real(r): 000127f8=ff (ÿ)
Reading from RAM(r): 000127f8=ff (ÿ)
Reading from physical memory(r): 000127f8=ff (ÿ)
Reading from paged memory(r): 000127f8=ff (ÿ)
MMU: Reading from real(r): 000127f9=ff (ÿ)
Reading from RAM(r): 000127f9=ff (ÿ)
Reading from physical memory(r): 000127f9=ff (ÿ)
Reading from paged memory(r): 000127f9=ff (ÿ)
MMU: Reading from real(r): 000127fa=50 (P)
Reading from RAM(r): 000127fa=50 (P)
Reading from physical memory(r): 000127fa=50 (P)
Reading from paged memory(r): 000127fa=50 (P)
MMU: Reading from real(r): 000127fb=4c (L)
Reading from RAM(r): 000127fb=4c (L)
Reading from physical memory(r): 000127fb=4c (L)
Reading from paged memory(r): 000127fb=4c (L)
MMU: Reading from real(r): 000127fc=01 ()
Reading from RAM(r): 000127fc=01 ()
Reading from physical memory(r): 000127fc=01 ()
Reading from paged memory(r): 000127fc=01 ()
MMU: Reading from real(r): 000127fd=93 (“)
Reading from RAM(r): 000127fd=93 (“)
Reading from physical memory(r): 000127fd=93 (“)
Reading from paged memory(r): 000127fd=93 (“)
MMU: Reading from real(r): 000127fe=00 ( )
Reading from RAM(r): 000127fe=00 ( )
Reading from physical memory(r): 000127fe=00 ( )
Reading from paged memory(r): 000127fe=00 ( )
MMU: Reading from real(r): 000127ff=00 ( )
Reading from RAM(r): 000127ff=00 ( )
Reading from physical memory(r): 000127ff=00 ( )
Reading from paged memory(r): 000127ff=00 ( )
00b3:00000002 F4 hlt RealRAM(p):000a85f2=f4(ô); RAM(p):001085f2=f4(ô); Physical(p):001085f2=f4(ô); Paged(p):001085f2=f4(ô); Normal(p):00000002=f4(ô); RealRAM(p):000a85f3=02(); RAM(p):001085f3=02(); Physical(p):001085f3=02(); Paged(p):001085f3=02(); Normal(p):00000003=02(); RealRAM(p):000a85f4=00( ); RAM(p):001085f4=00( ); Physical(p):001085f4=00( ); Paged(p):001085f4=00( ); Normal(p):00000004=00( ); RealRAM(p):000a85f5=00( ); RAM(p):001085f5=00( ); Physical(p):001085f5=00( ); Paged(p):001085f5=00( ); Normal(p):00000005=00( ); RealRAM(p):000a85f6=20( ); RAM(p):001085f6=20( ); Physical(p):001085f6=20( ); Paged(p):001085f6=20( ); Normal(p):00000006=20( ); RealRAM(p):000a85f7=00( ); RAM(p):001085f7=00( ); Physical(p):001085f7=00( ); Paged(p):001085f7=00( ); Normal(p):00000007=00( ); RealRAM(p):000a85f8=21(!); RAM(p):001085f8=21(!); Physical(p):001085f8=21(!); Paged(p):001085f8=21(!); Normal(p):00000008=21(!); RealRAM(p):000a85f9=3f(?); RAM(p):001085f9=3f(?); Physical(p):001085f9=3f(?); Paged(p):001085f9=3f(?); Normal(p):00000009=3f(?); RealRAM(p):000a85fa=00( ); RAM(p):001085fa=00( ); Physical(p):001085fa=00( ); Paged(p):001085fa=00( ); Normal(p):0000000a=00( ); RealRAM(p):000a85fb=00( ); RAM(p):001085fb=00( ); Physical(p):001085fb=00( ); Paged(p):001085fb=00( ); Normal(p):0000000b=00( ); RealRAM(p):000a85fc=f4(ô); RAM(p):001085fc=f4(ô); Physical(p):001085fc=f4(ô); Paged(p):001085fc=f4(ô); Normal(p):0000000c=f4(ô); RealRAM(p):000a85fd=02(); RAM(p):001085fd=02(); Physical(p):001085fd=02(); Paged(p):001085fd=02(); Normal(p):0000000d=02(); RealRAM(p):000a85fe=00( ); RAM(p):001085fe=00( ); Physical(p):001085fe=00( ); Paged(p):001085fe=00( ); Normal(p):0000000e=00( ); RealRAM(p):000a85ff=00( ); RAM(p):001085ff=00( ); Physical(p):001085ff=00( ); Paged(p):001085ff=00( ); Normal(p):0000000f=00( ); RealRAM(p):000a8600=20( ); RAM(p):00108600=20( ); Physical(p):00108600=20( ); Paged(p):00108600=20( ); Normal(p):00000010=20( ); RealRAM(p):000a8601=00( ); RAM(p):00108601=00( ); Physical(p):00108601=00( ); Paged(p):00108601=00( ); Normal(p):00000011=00( ); RealRAM(r):000aa5f2=b4(´); RAM(r):0010a5f2=b4(´); Physical(r):0010a5f2=b4(´); Paged(r):0010a5f2=b4(´); Normal(r):00000002=b4(´); RealRAM(r):000aa5f3=0f(); RAM(r):0010a5f3=0f(); Physical(r):0010a5f3=0f(); Paged(r):0010a5f3=0f(); Normal(r):00000003=0f(); RealRAM(r):000aa5f4=18(); RAM(r):0010a5f4=18(); Physical(r):0010a5f4=18(); Paged(r):0010a5f4=18(); Normal(r):00000004=18(); RealRAM(r):000aa5f5=00( ); RAM(r):0010a5f5=00( ); Physical(r):0010a5f5=00( ); Paged(r):0010a5f5=00( ); Normal(r):00000005=00( ); Normal(w):00000fb2=5b([); Paged(w):00015c02=5b([); Physical(w):00015c02=5b([); RAM(w):00015c02=5b([); RealRAM(w):00015c02=5b([); Normal(w):00000fb3=00( ); Paged(w):00015c03=00( ); Physical(w):00015c03=00( ); RAM(w):00015c03=00( ); RealRAM(w):00015c03=00( ); Normal(w):00000fb0=00( ); Paged(w):00015c00=00( ); Physical(w):00015c00=00( ); RAM(w):00015c00=00( ); RealRAM(w):00015c00=00( ); Normal(w):00000fb1=10(); Paged(w):00015c01=10(); Physical(w):00015c01=10(); RAM(w):00015c01=10(); RealRAM(w):00015c01=10(); Normal(w):00000fae=06(); Paged(w):00015bfe=06(); Physical(w):00015bfe=06(); RAM(w):00015bfe=06(); RealRAM(w):00015bfe=06(); Normal(w):00000faf=32(2); Paged(w):00015bff=32(2); Physical(w):00015bff=32(2); RAM(w):00015bff=32(2); RealRAM(w):00015bff=32(2); Normal(w):00000fac=b3(³); Paged(w):00015bfc=b3(³); Physical(w):00015bfc=b3(³); RAM(w):00015bfc=b3(³); RealRAM(w):00015bfc=b3(³); Normal(w):00000fad=00( ); Paged(w):00015bfd=00( ); Physical(w):00015bfd=00( ); RAM(w):00015bfd=00( ); RealRAM(w):00015bfd=00( ); Normal(w):00000faa=02(); Paged(w):00015bfa=02(); Physical(w):00015bfa=02(); RAM(w):00015bfa=02(); RealRAM(w):00015bfa=02(); Normal(w):00000fab=00( ); Paged(w):00015bfb=00( ); Physical(w):00015bfb=00( ); RAM(w):00015bfb=00( ); RealRAM(w):00015bfb=00( ); Normal(w):00000fa8=00( ); Paged(w):00015bf8=00( ); Physical(w):00015bf8=00( ); RAM(w):00015bf8=00( ); RealRAM(w):00015bf8=00( ); Normal(w):00000fa9=00( ); Paged(w):00015bf9=00( ); Physical(w):00015bf9=00( ); RAM(w):00015bf9=00( ); RealRAM(w):00015bf9=00( )
Registers:
EAX: 0000005b EBX: 00000ffa ECX: 000001d7 EDX: 00003df7
ESP: 00001000 EBP: 00000fa0 ESI: 00000fb4 EDI: 00001000
CS: 00b3 DS: 0000 ES: 005b FS: 0000 GS: 0000 SS: 005b TR: 0158 LDTR: 0168
EIP: 00000002 EFLAGS: 00003206
CR0: 00000001 CR1: 00000000 CR2: 00000000 CR3: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000000127e003ff IDTR: 000000107df007ff
CS descriptor: 0000FB1085F00FFF
DS descriptor: 000073126BA0F710
ES descriptor: 0000F31095F00FFF
FS descriptor: 00007303B3F0FFFF
GS descriptor: 00007303C1C0FFFF
SS descriptor: 0000F31095F00FFF
TR descriptor: 00008310A5F00BF9
LDTR descriptor: 000082FCFF8007FF
FLAGSINFO: 00000000000000vr0n11odItsz0a0P1c

Edit: Said block reaching said point is seemingly started at the following IRET(which starts the downwards staircase to a crash):

MMU: Reading from real(r): 000ab460=19 ()
Reading from RAM(r): 0010b460=19 ()
Reading from physical memory(r): 0010b460=19 ()
Reading from paged memory(r): 0010b460=19 ()
MMU: Reading from real(r): 000ab461=1c ()
Reading from RAM(r): 0010b461=1c ()
Reading from physical memory(r): 0010b461=1c ()
Reading from paged memory(r): 0010b461=1c ()
MMU: Reading from real(r): 000ab462=80 (?)
Reading from RAM(r): 0010b462=80 (?)
Reading from physical memory(r): 0010b462=80 (?)
Reading from paged memory(r): 0010b462=80 (?)
MMU: Reading from real(r): 000ab463=4f (O)
Reading from RAM(r): 0010b463=4f (O)
Reading from physical memory(r): 0010b463=4f (O)
Reading from paged memory(r): 0010b463=4f (O)
MMU: Reading from real(r): 000ab464=12 ()
Reading from RAM(r): 0010b464=12 ()
Reading from physical memory(r): 0010b464=12 ()
Reading from paged memory(r): 0010b464=12 ()
MMU: Reading from real(r): 000ab465=fb (?)
Reading from RAM(r): 0010b465=fb (?)
Reading from physical memory(r): 0010b465=fb (?)
Reading from paged memory(r): 0010b465=fb (?)
MMU: Reading from real(r): 000ab466=00 ( )
Reading from RAM(r): 0010b466=00 ( )
Reading from physical memory(r): 0010b466=00 ( )
Reading from paged memory(r): 0010b466=00 ( )
MMU: Reading from real(r): 000ab467=00 ( )
Reading from RAM(r): 0010b467=00 ( )
Reading from physical memory(r): 0010b467=00 ( )
Reading from paged memory(r): 0010b467=00 ( )
MMU: Reading from real(r): 000ab478=ff (?)
Reading from RAM(r): 0010b478=ff (?)
Reading from physical memory(r): 0010b478=ff (?)
Reading from paged memory(r): 0010b478=ff (?)
MMU: Reading from real(r): 000ab479=3f (?)
Reading from RAM(r): 0010b479=3f (?)
Reading from physical memory(r): 0010b479=3f (?)
Reading from paged memory(r): 0010b479=3f (?)
MMU: Reading from real(r): 000ab47a=c0 (?)
Reading from RAM(r): 0010b47a=c0 (?)
Reading from physical memory(r): 0010b47a=c0 (?)
Reading from paged memory(r): 0010b47a=c0 (?)
MMU: Reading from real(r): 000ab47b=62 (b)
Reading from RAM(r): 0010b47b=62 (b)
Reading from physical memory(r): 0010b47b=62 (b)
Reading from paged memory(r): 0010b47b=62 (b)
MMU: Reading from real(r): 000ab47c=13 ()
Reading from RAM(r): 0010b47c=13 ()
Reading from physical memory(r): 0010b47c=13 ()
Reading from paged memory(r): 0010b47c=13 ()
MMU: Reading from real(r): 000ab47d=f3 (?)
Reading from RAM(r): 0010b47d=f3 (?)
Reading from physical memory(r): 0010b47d=f3 (?)
Reading from paged memory(r): 0010b47d=f3 (?)
MMU: Reading from real(r): 000ab47e=00 ( )
Reading from RAM(r): 0010b47e=00 ( )
Reading from physical memory(r): 0010b47e=00 ( )
Reading from paged memory(r): 0010b47e=00 ( )
Show last 24 lines
MMU: Reading from real(r): 000ab47f=00 ( )
Reading from RAM(r): 0010b47f=00 ( )
Reading from physical memory(r): 0010b47f=00 ( )
Reading from paged memory(r): 0010b47f=00 ( )
0020:000013fb CF iret RealRAM(p):000a23fb=cf(?); RAM(p):001023fb=cf(?); Physical(p):001023fb=cf(?); Paged(p):001023fb=cf(?); Normal(p):000013fb=cf(?); RealRAM(p):000a23fc=c8(?); RAM(p):001023fc=c8(?); Physical(p):001023fc=c8(?); Paged(p):001023fc=c8(?); Normal(p):000013fc=c8(?); RealRAM(p):000a23fd=02(); RAM(p):001023fd=02(); Physical(p):001023fd=02(); Paged(p):001023fd=02(); Normal(p):000013fd=02(); RealRAM(p):000a23fe=00( ); RAM(p):001023fe=00( ); Physical(p):001023fe=00( ); Paged(p):001023fe=00( ); Normal(p):000013fe=00( ); RealRAM(p):000a23ff=00( ); RAM(p):001023ff=00( ); Physical(p):001023ff=00( ); Paged(p):001023ff=00( ); Normal(p):000013ff=00( ); RealRAM(p):000a2400=50(P); RAM(p):00102400=50(P); Physical(p):00102400=50(P); Paged(p):00102400=50(P); Normal(p):00001400=50(P); RealRAM(p):000a2401=53(S); RAM(p):00102401=53(S); Physical(p):00102401=53(S); Paged(p):00102401=53(S); Normal(p):00001401=53(S); RealRAM(p):000a2402=52(R); RAM(p):00102402=52(R); Physical(p):00102402=52(R); Paged(p):00102402=52(R); Normal(p):00001402=52(R); RealRAM(p):000a2403=56(V); RAM(p):00102403=56(V); Physical(p):00102403=56(V); Paged(p):00102403=56(V); Normal(p):00001403=56(V); RealRAM(p):000a2404=57(W); RAM(p):00102404=57(W); Physical(p):00102404=57(W); Paged(p):00102404=57(W); Normal(p):00001404=57(W); RealRAM(p):000a2405=06(); RAM(p):00102405=06(); Physical(p):00102405=06(); Paged(p):00102405=06(); Normal(p):00001405=06(); RealRAM(p):000a2406=6a(j); RAM(p):00102406=6a(j); Physical(p):00102406=6a(j); Paged(p):00102406=6a(j); Normal(p):00001406=6a(j); RealRAM(p):000a2407=00( ); RAM(p):00102407=00( ); Physical(p):00102407=00( ); Paged(p):00102407=00( ); Normal(p):00001407=00( ); RealRAM(p):000a2408=6a(j); RAM(p):00102408=6a(j); Physical(p):00102408=6a(j); Paged(p):00102408=6a(j); Normal(p):00001408=6a(j); RealRAM(p):000a2409=02(); RAM(p):00102409=02(); Physical(p):00102409=02(); Paged(p):00102409=02(); Normal(p):00001409=02(); RealRAM(p):000a240a=e8(?); RAM(p):0010240a=e8(?); Physical(p):0010240a=e8(?); Paged(p):0010240a=e8(?); Normal(p):0000140a=e8(?); RealRAM(r):00015c3e=c0(?); RAM(r):00015c3e=c0(?); Physical(r):00015c3e=c0(?); Paged(r):00015c3e=c0(?); Normal(r):00000fee=c0(?); RealRAM(r):00015c3f=01(); RAM(r):00015c3f=01(); Physical(r):00015c3f=01(); Paged(r):00015c3f=01(); Normal(r):00000fef=01(); RealRAM(r):00015c40=77(w); RAM(r):00015c40=77(w); Physical(r):00015c40=77(w); Paged(r):00015c40=77(w); Normal(r):00000ff0=77(w); RealRAM(r):00015c41=02(); RAM(r):00015c41=02(); Physical(r):00015c41=02(); Paged(r):00015c41=02(); Normal(r):00000ff1=02(); RealRAM(r):00015c42=46(F); RAM(r):00015c42=46(F); Physical(r):00015c42=46(F); Paged(r):00015c42=46(F); Normal(r):00000ff2=46(F); RealRAM(r):00015c43=32(2); RAM(r):00015c43=32(2); Physical(r):00015c43=32(2); Paged(r):00015c43=32(2); Normal(r):00000ff3=32(2); RealRAM(r):00015c44=1c(); RAM(r):00015c44=1c(); Physical(r):00015c44=1c(); Paged(r):00015c44=1c(); Normal(r):00000ff4=1c(); RealRAM(r):00015c45=3b(;); RAM(r):00015c45=3b(;); Physical(r):00015c45=3b(;); Paged(r):00015c45=3b(;); Normal(r):00000ff5=3b(;); RealRAM(r):00015c46=8f(?); RAM(r):00015c46=8f(?); Physical(r):00015c46=8f(?); Paged(r):00015c46=8f(?); Normal(r):00000ff6=8f(?); RealRAM(r):00015c47=02(); RAM(r):00015c47=02(); Physical(r):00015c47=02(); Paged(r):00015c47=02(); Normal(r):00000ff7=02()
Registers:
EAX: 00003d00 EBX: 00003b24 ECX: 00000000 EDX: 3aac3c76
ESP: 00000fee EBP: 00003b24 ESI: 00003b3f EDI: 00003c46
CS: 0020 DS: 028f ES: 028f FS: 0000 GS: 0000 SS: 0018 TR: 0158 LDTR: 0168
EIP: 000013fb EFLAGS: 00003006
CR0: 00000001 CR1: 00000000 CR2: 00000000 CR3: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000000127e003ff IDTR: 000000107df007ff
CS descriptor: 00009B101000FFFF
DS descriptor: 0000F31362C03FFF
ES descriptor: 0000F31362C03FFF
FS descriptor: 00007303A410FFFF
GS descriptor: 00007303B1E0FFFF
SS descriptor: 000093014C50FFFF
TR descriptor: 00008310A5F00BF9
LDTR descriptor: 00008210B1F003FF
FLAGSINFO: 00000000000000vr0n11oditsz0a0P1c

Edit: So it all starts with the following instruction:

0020:00000b52 55 push bp	RealRAM(p):000a1b52=55(U); RAM(p):00101b52=55(U); Physical(p):00101b52=55(U); Paged(p):00101b52=55(U); Normal(p):00000b52=55(U); RealRAM(p):000a1b53=8b(?); RAM(p):00101b53=8b(?); Physical(p):00101b53=8b(?); Paged(p):00101b53=8b(?); Normal(p):00000b53=8b(?); RealRAM(p):000a1b54=ec(?); RAM(p):00101b54=ec(?); Physical(p):00101b54=ec(?); Paged(p):00101b54=ec(?); Normal(p):00000b54=ec(?); RealRAM(p):000a1b55=06(); RAM(p):00101b55=06(); Physical(p):00101b55=06(); Paged(p):00101b55=06(); Normal(p):00000b55=06(); RealRAM(p):000a1b56=50(P); RAM(p):00101b56=50(P); Physical(p):00101b56=50(P); Paged(p):00101b56=50(P); Normal(p):00000b56=50(P); RealRAM(p):000a1b57=f7(?); RAM(p):00101b57=f7(?); Physical(p):00101b57=f7(?); Paged(p):00101b57=f7(?); Normal(p):00000b57=f7(?); RealRAM(p):000a1b58=46(F); RAM(p):00101b58=46(F); Physical(p):00101b58=46(F); Paged(p):00101b58=46(F); Normal(p):00000b58=46(F); RealRAM(p):000a1b59=06(); RAM(p):00101b59=06(); Physical(p):00101b59=06(); Paged(p):00101b59=06(); Normal(p):00000b59=06(); RealRAM(p):000a1b5a=02(); RAM(p):00101b5a=02(); Physical(p):00101b5a=02(); Paged(p):00101b5a=02(); Normal(p):00000b5a=02(); RealRAM(p):000a1b5b=00( ); RAM(p):00101b5b=00( ); Physical(p):00101b5b=00( ); Paged(p):00101b5b=00( ); Normal(p):00000b5b=00( ); RealRAM(p):000a1b5c=74(t); RAM(p):00101b5c=74(t); Physical(p):00101b5c=74(t); Paged(p):00101b5c=74(t); Normal(p):00000b5c=74(t); RealRAM(p):000a1b5d=18(); RAM(p):00101b5d=18(); Physical(p):00101b5d=18(); Paged(p):00101b5d=18(); Normal(p):00000b5d=18(); RealRAM(p):000a1b5e=0f(); RAM(p):00101b5e=0f(); Physical(p):00101b5e=0f(); Paged(p):00101b5e=0f(); Normal(p):00000b5e=0f(); RealRAM(p):000a1b5f=00( ); RAM(p):00101b5f=00( ); Physical(p):00101b5f=00( ); Paged(p):00101b5f=00( ); Normal(p):00000b5f=00( ); RealRAM(p):000a1b60=c8(?); RAM(p):00101b60=c8(?); Physical(p):00101b60=c8(?); Paged(p):00101b60=c8(?); Normal(p):00000b60=c8(?); RealRAM(p):000a1b61=05(); RAM(p):00101b61=05(); Physical(p):00101b61=05(); Paged(p):00101b61=05(); Normal(p):00000b61=05(); Paged(w):00015c3c=b0(?); Physical(w):00015c3c=b0(?); RAM(w):00015c3c=b0(?); RealRAM(w):00015c3c=b0(?); Paged(w):00015c3d=3a(:); Physical(w):00015c3d=3a(:); RAM(w):00015c3d=3a(:); RealRAM(w):00015c3d=3a(:)
Registers:
EAX: 00000000 EBX: 0000007a ECX: 00008ff6 EDX: 3aac3c76
ESP: 00000fee EBP: 00003ab0 ESI: 00003b3f EDI: 00003c7f
CS: 0020 DS: 00bf ES: 028f FS: 0000 GS: 0000 SS: 0018 TR: 0158 LDTR: 0168
EIP: 00000b52 EFLAGS: 00003083
CR0: 00000001 CR1: 00000000 CR2: 00000000 CR3: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: 00000000 DR7: 00000000
GDTR: 0000000127e003ff IDTR: 000000107df007ff
CS descriptor: 00009B101000FFFF
DS descriptor: 0000F309DA3021CF
ES descriptor: 0000F31362C03FFF
FS descriptor: 00007303A410FFFF
GS descriptor: 00007303B1E0FFFF
SS descriptor: 000093014C50FFFF
TR descriptor: 00008310A5F00BF9
LDTR descriptor: 00008210B1F003FF
FLAGSINFO: 00000000000000vr0n11oditSz0a0p1C

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

Reply 8 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. Just looked at the instruction flow after that. It sets up a stack frame, then checks BP+6 for bit 1 to be set or not. But at that location(with a normal interrupt) would have FLAGS? That would make no sense at all?
But, what if the interrupt had an error code? Then it WOULD make sense:
Normal interrupt stack:

ff8: IRET stack top! Starts being OOR!
ff6 iret ss
ff4 iret sp
ff2 iret flags=3283
ff0 iret cs
fee iret ip
fec old bp=3ab0 <- bp
fea es
fe8 ax

Exception stack with fault code:

ffa: IRET stack top! Starts being OOR!
ff8 iret ss
ff6 iret sp
ff4 iret flags
ff2 iret cs=3283(checked for bit 1 being set)
ff0 iret ip
fee error code
fec old bp=3ab0 <- bp
fea es
fe8 ax

So now we know that the issue is with some exception handler instead of a normal interrupt! It's the handling at an (probably loading of some segment) at segment 3283 for privilege level 3! Probably one of those #NP fault handlers!
Edit: The current stack top is at ff8(evidenced by the reading of the TSS check of SS0 for the ffffh value), so something's expecting an error code, where there isn't one for some weird reason?
Edit: It's the handler at 0020:0B52.
Edit: It's the interrupt 8h handler?

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

Reply 9 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. The HLT at 00b3:0002 is reached by both the kernel segment and segment 1d7?

Edit: The log of segment 1D7 running:

Filename
debugger_UniPCemu_JazzJackrabbit_SB2.0_segment1D7.7z
File size
49.8 KiB
Downloads
44 downloads
File comment
Segment 1D7 running in UniPCemu running Jazz Jackrabbit
File license
Fair use/fair dealing exception

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

Reply 10 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

Ooooohhhh.... Interesting:
Selecting the "Sound Blaster Clone" option in the settings makes it run without crashing on starting on the Sound Blaster 2.0 configuration?

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

Reply 11 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. Having started up the game on the "Sound Blaster clone" setting instead of plain "Sound Blaster" for the emulated SB 2.0 card, I notice the following weirdness when trying the bonus level from the main menu:
Pressing forward has no visible effect? Backward, left and right on the analog stick work as expected?

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

Reply 12 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm... Just looked at Dosbox-x's sblaster.cpp.

I see that starting the auto-init DMA commands on SB 2.0 don't act any different than their non-auto-init versions: they still start out with the block size of the two parameter bytes? It's just that it's reloading it from the SB 2.0's Set DMA Block size command when that buffer and any buffers after it is processed(all those bytes have been transferred)?

So, Jazz Jackrabbit would send 1c,lo,hi for the DMA transfer to transfer lo+(hi*256) bytes, after which it would start to load the default(since the Set DMA Block size command size isn't received after reset) size instead? And that default size being 0, thus each DMA sample=1 interrupt, but only after said param 16-bit amount of bytes?

Would that be correct behaviour?

Although I see sblaster.cpp reading the 2 bytes in the command buffer while it's parameter table contains 0 parameters for the DMA auto-init commands, thus undefined behaviour?

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

Reply 13 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm... Just taken another look at this:
https://rpix86.patrickaalto.com/rblog.html

So segment 417h is at least containing the Sound Blaster code?

It does send those two parameter bytes to the SB 2.0 and up? Are those just undefined implemented on SB 2.0 only? Or is it a bug only? How does the Set DMA Block size setting affect all this? Does it only affect auto-init after the command 0x1C parameters are sent? Or does 0x1C ignore those parameters, having no DMA block size(still set to 0x0000 at that point in UniPCemu), causing it t0 throw an IRQ each sample?

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

Reply 14 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

Oh! Interesting! I see the sound blaster sending 0x1C, but never the parameters the code from rpix86 executes?

Edit: Hmmm... The first call to 22f5 I see happening, at 0417:000025e8, but it never seems to return?

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

Reply 15 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. It might never be able to return, because I see it what seems to be the IRQ5 handler(for the Sound Blaster) keeping to trigger each sample, which adds 0xAE(the sample rate constant) to ds:[26ba]?

Could it be that it expects the sample rate constant to be expired before triggering the IRQ? So perhaps UniPCemu's time constant isn't correct?

UniPCemu currently converts the constant into a rate, then starts triggering said a rate on the current timing it's using(resetting the timer to a different rate when setting the time constant)...

I've now changed said timer to run at 1MHz, then simply divide it up by the current count(just like the 8254 PIT does) to obtain a basic sample rate, then time the running DMA transfers using that timing when the counter ticks from 1 to 0(reloading happens when writing/reading a DMA sample to/from the DMA controller and when a new transfer is started), starting at 256-[programmed rate].

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

Reply 16 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. Just tried Jazz Jackrabbit with the same IRQ/DMA settings on Dosbox 0.74-3(the most recent one from Dosbox.com). When trying the same settings on the SB 2.0 with the normal Sound Blaster setting, it doesn't crash like UniPCemu does, but it runs without sound.
When trying the same with setting it up for the "Sound Blaster compatible (stereo)"-named setting(same IRQ and DMA settings using manual settings), it runs without issues on Dosbox's SB 2.0, just like UniPCemu does?

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

Reply 17 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

One thing I'm thinking about: how does the DSP busy bit on port work? When is it set or reset?

Also, I notice one thing while selecting the Sound Blaster compatible setting in the setup: the information bar in Jazz Jackrabbit's (with it's HP, timing etc.) seems to be gone? As in, only the gameplay part is still there(so no status etc. is visible)? All I did was play the bonus levels(first, second partly, then returned to the main menu) first.

Edit: Perhaps an ET4000 issue?
Edit: Nope. It's the pure VGA that's being emulated. So a VGA issue somehow? The screen is only partly rendered?

Edit: OK. Comparing to Dosbox for the first level, it doesn't look like it's incorrectly rendered, but it's just more than the display can handle somehow? Like it's cut off just after the first scanline of the status bar?
Edit: OK. The issue was the splitscreen operation, which was determining that the split screen meant that it should render on the other monitor instead of the current one(just affecting VRAM fetches).
Edit: Having fixed that, I notice that the vertical display end register indicates active display is only 199 pixels high? Shouldn't that need to be 200 usually?

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

Reply 18 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. In the normal "Sound Blaster" setting it, upon reaching 0417:2308 after 0417:2307, seems to somehow be executing something which looks like a strange interrupt of some kind?
Edit: It seems to be located at position 68h in the IDT, so it's interrupt Dh, thus a #GP fault or Sound Blaster interrupt?

Edit: Huh? I see it starting to execute a RET (opcode C3) at that location, but while it's starting to wait for it's common POP timing, the instruction aborts(as it should, to handle the common timing before a POP instruction actually starts popping it's data requesting it from the BIU to be read) and starts fetching and executing a new instruction when triggering the next CPU cycle, instead of continuing the executing instruction???

Edit: OK. More weirdness: the debugger was visible(thus the emulation should be halted until pressing the cross/NUM2 key), but the emulation somehow continued executing. That's not something that's supposed to happen, as the emulation shouldn't be running at that point(just the debugger thread) 😖

Edit: Of course, on my second try, I see it triggering an IRQ at 0020:C7A on that location, from a real Sound Blaster IRQ(hardware interrupt 0xD)! The SB timer has counted down from 0xAE(+1) to 0x51 in that time(those few instructions).

Edit: That's probably just bad timing!
Edit: I see it executing, returning to 0x25EB.
Edit: And, immediately on the next instruction interrupt 0x8(IRQ0) happens, after which it crashes once again.
Edit: Hmmmm.... Are interrupts supposed to be enabled while handling said code?
Edit: OK. There might be a possible issue with detecting busy instructions/interrupts/TSS-based multitasking... Although I can't exactly remember why executing instructions state aren't counted as a 'busy execution phase', since the instruction is clearly still running when that's the case.
Edit: Fixed said 'bug' (if that was the whole story) wasn't enough. It's still crashing due to a stack overflow before/at reaching said location, never returning from the function. That's at/directly after it's RETF instruction, because it's handling a PIT interrupt there(IRQ0).

Edit: Just added multiple breakpoint support(up to 5 breakpoints that trigger together(basically OR'ed together in their usage)). So they're handled like they're one condition, and if any one is matched, the breakpoint is active for the current instruction.
Managed to make a log with segment 20h and 417h only. That should at least tell us what's happening to the strange interrupt 8h that's occurring and causing Jazz Jackrabbit to crash?
I think it might have something to do with the strange stack handling of the interrupt handler? I remember that the interrupt handler decreases ESP normally, building saved data of the originating task, but eventually overwrites the top of the stack with new data instead of doing it somewhere lower on the stack(on the EBP bottom of the stack, for instance, which would make more sense(if you're not wanting to generate an infinite loop with the last interrupt returned to))?

I've uploaded that log to dropbox(seeing as it exceeds the 5MB limit of the forum by just a bit(~6MB in this case)): https://www.dropbox.com/s/c4kaic6inasnj7d/deb … 17and20.7z?dl=0

Edit: OK, at 0020:00000cbf it gets interesting. It has determined that it's an interrupt(probably, since the difference of the SS0 and BP was 0xC), so it's starting the interrupt handling here?
ESP is returned to pointing to the original stack frame of the IRQ being triggered at that point(at FEEh).
Edit: OK. At some point, the build stack is skipped back, while a return to the call handler that had (0xD,0x0,IRET frame) as parameters is done from the bottom of the stack(it's returning to the call IP value at 0020:00001383).

ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h <- bp <- sp


Execution at 0020:0cbc=Start of IRQ/interrupt handler
98:63E=BP(fb4).
JMP to fe8 address(=cc6h) is done with this stack at 0020:00001383.
It reaches 0020:00003d09 when returning from this(after a unconditional JMP).
It compares interrupt number(0xD) against 0x75. Then starts adding more to the stack.
ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happens here)
fb2: ax=1ch
fb0: dx=Ah
fae: FEA's contents=Dh
fac: 3d36's return IP=3D39h
faa: bp=fb4h <- bp (end result after stack build for next check of 34h)
fa8: es=160h
fa6: di=Ah
fa4: bx=0 <- sp (end result after stack build for next check of 34h)

OK, it then checks FAEh against 34h, another interrupt check.
ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happens here)
fb2: ax=1ch
fb0: dx=Ah
fae: FEA's contents=Dh
fac: 3d36's return IP=3D39h
faa: bp=fb4h <- bp (end result after stack build for next check of 34h, at 0020:000035a5)
fa8: es=160h
fa6: di=Ah
fa4: bx=0 <- sp (end result after stack build for next check of 34h)

OK, it then checks FAEh against 34h, another interrupt check, at 0020:000035a8.
ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happens here)
fb2: ax=1ch
fb0: dx=Ah
fae: FEA's contents=Dh
fac: 3d36's return IP=3D39h
faa: bp=fb4h <- bp (end result after stack build for next check of 34h, at 0020:000035a5)
fa8: es=160h
fa6: di=Ah
fa4: bx=0 <- sp (end result after stack build for next check of 34h).

It then prepares something for some kind of TSS transfer?

Edit: Apparently, the TSS location 34h and up contains some sort of table with interrupt vectors(the IVT for protected mode? It looks like they're stored like a normal IVT, but with protected mode 16-bit segment:offset instead?).
Handling seems to start at 0020:000035db.

It eventually seems to return to 0020:00003d39.

ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happens here) <- bp (end result after stack build for next check of 34h, at 0020:000035a5)
fb2: ax=1ch
fb0: dx=Ah
fae: FEA's contents=Dh <- sp returned here at 0020:3d39.
fac: 3d36's return IP=3D39h
faa: bp=fb4h
fa8: es=160h
fa6: di=Ah
fa4: bx=0

AX=IP, DX=CS for the retrieved interrupt vector at this point.
It discards FAEh's stack entry and checks the returned DX(=CS for the interrupt vector)?

ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happens here) <- bp (end result after stack build for next check of 34h, at 0020:000035a5)
fb2: ax=1ch
fb0: dx=Ah <- sp when checking DX against 0.
fae: FEA's contents=Dh
fac: 3d36's return IP=3D39h
faa: bp=fb4h
fa8: es=160h
fa6: di=Ah
fa4: bx=0

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

Reply 19 of 47, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. It then loads some data from RAM(B3:0002?), then proceeds to push the interrupted location's FLAGS on the stack, at FB2h.

OK. It then loads some data from RAM(B3:0002?), then proceeds to push the interrupted location's FLAGS on the stack, at FB2h.

ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happens here) <- bp (end result after stack build for next check of 34h, at 0020:000035a5)
fb2: IRET flags=3202h <- sp after pushing FLAGS.
fb0: dx=Ah
fae: FEA's contents=Dh
fac: 3d36's return IP=3D39h
faa: bp=fb4h
fa8: es=160h
fa6: di=Ah
fa4: bx=0

Then BX is added as well(B3), and CX as well(02):

ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happens here) <- bp (end result after stack build for next check of 34h, at 0020:000035a5)
fb2: IRET flags=3202h
fb0: bx=B3h
fae: cx=2h <- sp after pushing CX.
fac: 3d36's return IP=3D39h
faa: bp=fb4h
fa8: es=160h
fa6: di=Ah
fa4: bx=0

Then, a constant 3h, followed by 0h, 1h, dx(417), ax(26bc):

ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happens here) <- bp (end result after stack build for next check of 34h, at 0020:000035a5)
fb2: IRET flags=3202h
fb0: bx=B3h
fae: cx=2h
fac: 3h
faa: 0h
fa8: 1h
fa6: dx=417h
fa4: ax=26BCh <- sp after pushing AX at the end.

This is followed by a call, then enter 0,0:

ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happened here)
fb2: IRET flags=3202h
fb0: bx=B3h
fae: cx=2h
fac: 3h
faa: 0h
fa8: 1h
fa6: dx=417h
fa4: ax=26BCh
fa2: ip=3D64h
fa0: bp=FB4 <- sp <- bp

It then reached 0020:00003636. So far, everything seems sane.

ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happened here)
fb2: IRET flags=3202h
fb0: bx=B3h
fae: cx=2h
fac: 3h
faa: 0h
fa8: 1h
fa6: dx=417h
fa4: ax=26BCh
fa2: ip=3D64h
fa0: bp=FB4 <- bp
f9e: bp=fa0h <- sp

It then prepares for something at 0020:00003660. It sets 98:403 bit 2 to 1. It then pops bp to return to the previous stack frame?

ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happened here)
fb2: IRET flags=3202h
fb0: bx=B3h
fae: cx=2h
fac: 3h
faa: 0h
fa8: 1h
fa6: dx=417h
fa4: ax=26BCh
fa2: ip=3D64h
fa0: bp=FB4<- sp <- bp

It loads CX from BP+C(=3), points DS to the stack, loads SI from BP+Eh(2), AX with that CX(=3), multiplied by 2(=6), compares AX(=6) against DI(=1000h)...
Substracts AX from DI(1000-6=FFA)? So ES:DI now points to 2 bytes above the IRET stack frame of the interrupted procedure?
It moves said address to BX, adds AX(6) to SI(FAE), thus SI=FB4(the previous EBP). It pushes SI...

ff8: sp0 base for the original IRQ0 handler to return to the never returning code
ff6: IRET ss
ff4: IRET sp
ff2: IRET flags
ff0: IRET cs
fee: IRET ip (base frame for IRQ0)
fec: 0h
fea: Dh
fe8: call IP=cc6h
fe6: ???
fe4: ???
fe2: ???
fe0: ???
fde: gs
ffc: fs
fda: ds
fd8: es
fd6: 0h
fd2: eax=1Ch
fce: ecx=0
fca: edx=Ah
fc6: ebx=0
fc2: esp=FD6h
fbe: ebp=3EB4
fba: esi=2127h
fb6: edi=2174h
fb4: [ds:63E]=fb4h (check against 75h happened here)
fb2: IRET flags=3202h
fb0: bx=B3h
fae: cx=2h
fac: 3h
faa: 0h
fa8: 1h
fa6: dx=417h
fa4: ax=26BCh
fa2: ip=3D64h
fa0: bp=FB4 <- bp
f9e: si <- sp

It then substracts AX from SI, returning it to FAEh. It then clears the direction flag and copies from FAE to FFA, just overwriting the IRET IP,CS,EFLAGS with B3:0002, flags=3202h.

So what it's effectively done at this point is replace the IRET information with it's interrupt vector, having what seems to be the original CS:IP of the interrupted procedure(which never regains control) at [FA6]:[FA4].
Edit: OK. This doesn't happen on the kernel's stack, but on the top of the user's stack instead?

Last edited by superfury on 2020-02-16, 17:59. Edited 1 time in total.

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