VOGONS


Reply 41 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

With the current commit, that's impossible, as it requires a running BIOS that can already boot from a harddisk to run the executables(which need to be stored inside a hard disk image for the emulator to run the .exe files). It's 80486 NOFPU version has always crashed on UniPCemu, not generating any results, on the 80486 emulation. First, those bugs from the latest two commits need to be fixed, in order to boot from the virtual hard disk.

Edit: Thinking about it: I might be able to sniff out the problem by simply enable a full log(no state log, which has changed due to fixed timings in the IDIV instruction, no longer doubling the amount of cycles spent on all CPUs), then running both commits of UniPCemu, generating a full log. Then simply diff the two logs to find the offending instruction, then fix the found problem and check again until no differences are found anymore(or no errors pop up anymore). Both pieces of code are functionally equivalent, except for the INTO instruction, which has been fixed(no longer aborting the interrupt process in the middle of it when the flags' Overflow bit has been cleared due to stack operations handling the interrupt).

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

Reply 42 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

I'm trying to get the sed command to remove the logged timestamp(format: "%02u:%02u:%02u:%02u.%05u: ", without "-marks, as inputted into sprintf). I've currently end up with:
$ sed -e 's/\(\[0-9\]\{2,3\}\):\(\[0-9\]\{2\}\):\(\[0-9\]\{2\}\):\(\[0-9\]\{2\}\).\(\[0-9\]\{5\}\)://g' debugger.log

But it keeps outputting the unmodified lines, with the timestamp still there, instead of removed?

Edit: Managed to get it fixed:
$ sed -e 's/^[0-9]\+:[0-9]\+:[0-9]\+:[0-9]\+\.[0-9]\+: //g' debugger.log

That will remove the timestamps from the log, which can then be compared to the other version of the same log to find errors in CPU execution(replacing -e with -i to actually remove the timestamps).

Edit: Afterwards, no changes are shown? I'm recreating the logs again(using a simple patch of the fixed INTO commands:

extern uint_32 exception_busy; //Exception is busy?
extern byte tempcycles;

OPTINLINE byte CPU8086_internal_INTO()
{
if (exception_busy&0x10) goto busyEX4;
if (FLAG_OF==0) goto finishINTO; //Finish?
exception_busy |= 0x10; //We're busy!
if (CPU_faultraised(EXCEPTION_OVERFLOW)==0) //Fault raised?
{
exception_busy &= ~0x10; //Not busy anymore!
return 1; //Abort handling when needed!
}
busyEX4:
CPU_resetOP(); //Reset instruction to start of instruction!
tempcycles = CPU[activeCPU].cycles_OP; //Save old cycles!
if ((CPU086_int(EXCEPTION_OVERFLOW)==0) && (!(EMULATED_CPU>=CPU_80286))) return 1; //Return to opcode!
exception_busy &= ~0x10; //Not busy anymore!
CPU[activeCPU].cycles_Exception += CPU[activeCPU].cycles_OP; //Our cycles are counted as a hardware interrupt's cycles instead!
CPU[activeCPU].cycles_OP = tempcycles; //Restore cycles!
return 0; //Finished: OK!
finishINTO:
{
if (CPU_apply286cycles()==0) //No 80286+ cycles instead?
{
CPU[activeCPU].cycles_OP += 4; //Timings!
}
}
return 0; //Finished: OK!
}

As well as the IDIV command not supposed to count it's timings double(when checking for IDIV timings).)

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

Reply 43 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

After using VBinDiff to compare the two logs, I've finally found a difference:
F000:E180 (26C70608005FF8)MOVW AX,F85F

Which is supposed to be:
F000:E180 (26C70608005FF8)MOVW [ES:0008],F85F

So one down, maybe some to go?
Edit: Just a disassembler error, but it's a start. Next...

Edit: Next up: the LES instruction!

LES DS,AX instead of LES SI,[DS:0074]. Binary: C4367400.

Edit: Fixed, it was an error in the debugger/disassembler as well.

Edit: Now it gets interesting: both the same instruction (F000:E2FA (26FF1E6700)CALL [ES:0067] on the new version and old version, but different communication ensues around it.

Looking into it some more I've found the final problem(other parts confirmed working, by reversing and redo): the CS value of the 0xFF far CALL instruction wasn't being read, because it used a base index of 2 instead of it's required 0(because IP isn't read before it anymore). This fixes the BIOS and it now continues running correctly. 😁

Edit: Just tried running 8088 MPH... It hangs when starting the bobbing text effect(with the text visible on the screen)... 😖
Edit: Just tried with the old commit as well. The very same thing happens: the entire application(8088 MPH, not the emulator itself) just freezes.
Edit: It seems to be halted in an odd way(with a HLT instruction, never to check for resuming).
Edit: Having fixed that, 8088 MPH continues running.
Edit: It now runs all the way up to the credits, where the SMC crashes as usual(due to cycle inaccuracy). 8088 MPH now reports UniPCemu as even more inaccurate, at a metric cycle count of 1581(6% off)? At the most, three timings have now been changed(dramatically reduced): IDIV(((118-READ cycles) or 112)+6 cycles becoming only 6 cycles added on top of the DIV timings to become more perfect), INTO being fixed and properly firing the interrupt when needed and the GRP3 instructions etc. now properly execute only once(execution phase after fetching data from RAM/CPU for processing, before writing it back to memory)) instead of multiple times waiting for the BIU to get ready to write data back to memory.

After some cross-BIOS and revert commit checking, I've found out that there's only a bug left in the NEC V30(80186) core. So once that's solved, I can start reconverting the now cycle-compatible 8086 core(to start with) to the 80386 core(32-bit extensions of the 16-bit instructions), which is still not cycle accurate(I'll also need to implement the tables for the 80286+ to contain the 80386 timings, but that can be done later, after the 80386 core has the new timed instructions implemented). The 80386 core currently still has the old non-cycle accurate 8086-80286 instruction implementations in it for it's 32-bit versions of those instructions(the 16/8-bit versions are still in the 8086-80286 cores and don't need further adjusting to implement on the 80386, since they don't have modified behaviour on the 80386+.

Edit: Traced it down to the 80186+ opcodes C0&C1(80186+ GRP opcodes).
Edit: Their behaviour was changed with the latest changes. I've fixed the wrong behaviour. Now the BIOS POSTs correctly again.

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

Reply 44 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

Gotten the 8086, 80186 and 80286 cores working now. I've adjusted the 80386 and 80486 timing tables to fix some errors and reconverted the cycle-accurate 8086 code to the 32-bit 80386 instructions(80186+ instructions still need to be converted). So far, the converted 8086 32-bit instructions seem to work(the BIOS POSTs completely). The 32-bit 80186 and 80286 instructions still need to be reconverted to 32-bit. The 80386 and 80486 instructions aren't cycle accurate in any way yet, but can probably be implemented quickly(since they're quite few compared to the base set of the 8086, with only relatively a few instructions added each CPU generation).

Edit: For some reason, Wolfenstein 3D now crashes due to executing at offset 0xFFFF, causing a #GP fault because it's an instruction past the segment limit(64K limit). It isn't even supposed to be able to reach that point, if there's not a problem with the normal execution flow. Probably some point earlier in the program going haywire(jumping to an invalid address or keep linearly executing(like unitialized memory) until reaching that point)?

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

Reply 45 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried Megarace again on the Compaq Deskpro 386 with the latest fixes(the 32-bit instructions being reimplemented and PS/2 mouse changed to Serial mouse). It now has a responsive menu with mouse reponse(no keyboard reponse until inputting the keys for mapping to fire etc.). When trying to map the keys, the first four keys work correctly(left/right/up/down to left/right/speed up/stop), but for some reason trying to map the fire button to space fails. Debugging the PS/2 keyboard itself shows that the buffer is still being emptied by the CPU, as the scancodes are received, even the multibyte scancodes(0xF0 XX key release codes for releasing the space key). But the program refuses to map it to space?

Edit: Found two problems in the keyboard layout, when comparing my code, http://www.quadibloc.com/comp/scan.htm and http://www.computer-engineering.org/ps2keyboa … scancodes3.html (which is the original source I've based my emulator's tables on). Two errors were found:
The 'i' key has a release code of F0, 48 according to http://www.computer-engineering.org/ps2keyboa … scancodes3.html , but according to http://www.quadibloc.com/comp/scan.htm it's F0, 43. The latter seems to be correct, as all those release scan codes contain a full copy in one form or another of the make code?

The scroll lock key has a make code of 5F and a break code of F0, 5F. My emulator had a make code of 7F instead(which is incorrect, according to both sources).

This should fix at least some of the keyboard problems.

I'm wondering about one little thing: what happens to the PS/2 keyboard make/release scancodes buffered when a new command is issued? The buffer is cleared, but what about the buffered scancodes? Are they resent?

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

Reply 46 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried the 80186 testsuite again. The control.bin ROM fails. So there's definitely a problem with some control transfers.
Edit: And by pure accident I find that I still haven't implemented the Resume Flag into the debugger exceptions. Implemented it right away.

I'm wondering about something: does the 80286 mask the low 3 bits of the highest nibble of the FLAGS register to 0 in real mode? What about the 80386 and up? The manuals don't seem to mention this?

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

Reply 47 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

With the current commits of UniPCemu, I notice that the Windows 3.0 setup mouse still responds when reaching the copy phase of disk 5, but the software doesn't respond to key input(emulating 8086 w/ CGA on XT architecture)?

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

Reply 48 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

Somehow, it now gets up to the phase of copying the second font(helvetica), but then entering the path, the keyboard input is 100% unresponsive(should still generate packets though). Same for the MS-DOS 5.0 prompt, but not for the mouse input(which responds fine(serial mouse on COM1).

I'm testing with a 640x480 16-color VGA. CGA installed and ran without problems. So a 80186 problem?
Anyone might know the possible cause? The kernel is at least somewhat working now(GUI runs), but input troubles? A problem in the PS/2 keyboard still?

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

Reply 49 of 142, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

I'm testing with a 640x480 16-color VGA. CGA installed and ran without problems. So a 80186 problem?

What would CGA vs VGA be a 80186 problem? And what does PS/2 have to do with it?

Can you install on a XT machine? If yes then only change one component at a time, like add VGA, or change to AT machine but still with CGA and see which change breaks it.

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 50 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've tested the following cases until now:
- IBM XT 8086/88 with CGA installs and runs Windows 3.0 without problems.
- IBM XT NEC V30(or 386, but don't remember for sure) with VGA running CGA windows that's already installed without problems.
- IBM AT with 80286 with VGA crashes Windows 3.0 in real mode, infinite looping or faulting.
- Compaq Deskpro 386 with 80386 & CGA doesn't POST completely(hangs after memory test as far as I remember).
- Compaq Deskpro 386 with 80386 & VGA has the same problem as the AT 286 & VGA.

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

Reply 51 of 142, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie

Maybe I can help you. CAPE can install and run Win 3.0 on CGA on a typical XT machine (IBM 5150). I will try it on a 286 IBM AT machine with CGA and if it works then we can compare instructions logs and see where things diverge. I do not emulate VGA (yet) but likely your problems are not related to CGA vs VGA.

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 52 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

I think the problem is with the CPU itself, seeing as strange (un)real mode problems occur on 80286+, as well as problems with the Compaq BIOS locking up on CGA. Also, I know that there's problems with add/sub instructions using carry/overflow/adjust flags(I'm currently trying to adopt those based on Bochs, see UniPCemu's latest commit's flags.c). The overflow should be accurate, according to the 80186 testsuite's sub test ROM. The problems with the carry/auxiliary carry(adjust) flags still happen in two of the tested cases with the current commit.

https://bitbucket.org/superfury/unipcemu/src/ … ags.c?at=master

Can you see what's going wrong? I've based it on the Bochs code of it's lazy flags(see the macro called bcbitsa/bcbitss(which indicates a bit has been borrowed/carried for addition(bcbitsa) or substraction(bcbitss)). Can you see what's going wrong? The check sets carry/adjust set to bit 7/15/31(depending on word size being 8/16/32-bits), while adjust/auxiliary is set to bit 3.

#define bcbitsa(v1,v2) (((v1)^(v2))^(((v1)^(dst))&~((v1)^(v2)))^dst)
#define bcbitss(v1,v2) (((v1)^(v2))^(((v1)^(dst))&((v1)^(v2)))^dst)

Overflow is now handled by indexing sign bit into a lookup table:

//Index Bit0=sumsign, Bit1=num2sign(add or sub negated value), Bit2=num1sign(v1)
byte addoverflow[8] = {0,1,0,0,0,0,1,0};
byte suboverflow[8] = {0,0,0,1,1,0,0,0};

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

Reply 53 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

I want to look at Windows 3.0 IRQ1 handler executing. Does anyone know the IRQ1 handler when Windows 3.0's kernel is started? It doesn't seem to use F000:E987 anymore? Not even in real mode, after returning to MS-DOS?

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

Reply 54 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've adjusted the BCD instructions to now have two different versions for 8086 and 186+, but the AAD instruction seems to fail, according to the testsuite(as well as pretty much all shift/rotate instructions?)?

AAD instruction:

OPTINLINE byte CPU8086_internal_AAD(byte data)
{
CPUPROT1
oper2b = REG_AL; //What to add!
oper1b = (REG_AH*data); //AAD base to work on, we're adding to this!
op_add8(); //Add, 8-bit, including flags!
REG_AL = res8; //The result to load!
REG_AH = 0; //AH is cleared!
CPUPROT2
if (CPU_apply286cycles()==0) //No 80286+ cycles instead?
{
CPU[activeCPU].cycles_OP += 60; //Timings!
}
return 0;
}

Shift/rotate instructions:

byte op_grp2_8(byte cnt, byte varshift) {
//word d,
INLINEREGISTER word s, shift, oldCF, msb;
//word backup;
//if (cnt>0x8) return(oper1b); //NEC V20/V30+ limits shift count
s = oper1b;
oldCF = FLAG_CF;
if (EMULATED_CPU >= CPU_NECV30) cnt &= 0x1F; //Clear the upper 3 bits to become a NEC V20/V30+!
switch (thereg) {
case 0: //ROL r/m8
for (shift = 1; shift <= cnt; shift++) {
if (s & 0x80) FLAGW_CF(1); else FLAGW_CF(0);
s = s << 1;
s = s | FLAG_CF;
}
if (cnt==1) FLAGW_OF(((s >> 7) & 1)&FLAG_CF); else FLAGW_OF(0);
break;

case 1: //ROR r/m8
for (shift = 1; shift <= cnt; shift++) {
FLAGW_CF(s & 1);
s = (s >> 1) | (FLAG_CF << 7);
}
if (cnt==1) FLAGW_OF((s >> 7) ^ ((s >> 6) & 1));
break;

case 2: //RCL r/m8
for (shift = 1; shift <= cnt; shift++) {
oldCF = FLAG_CF;
if (s & 0x80) FLAGW_CF(1); else FLAGW_CF(0);
s = s << 1;
s = s | oldCF;
}
if (cnt==1) FLAGW_OF(FLAG_CF ^ ((s >> 7) & 1));
break;

case 3: //RCR r/m8
for (shift = 1; shift <= cnt; shift++) {
oldCF = FLAG_CF;
FLAGW_CF(s & 1);
s = (s >> 1) | (oldCF << 7);
}
if (cnt==1) FLAGW_OF((s >> 7) ^ ((s >> 6) & 1));
break;

case 4: case 6: //SHL r/m8
//FLAGW_AF(0);
for (shift = 1; shift <= cnt; shift++) {
if (s & 0x80) FLAGW_CF(1); else FLAGW_CF(0);
//if (s & 0x8) FLAGW_AF(1); //Auxiliary carry?
s = (s << 1) & 0xFF;
}
if (cnt==1) { if (FLAG_CF==(s>>7)) FLAGW_OF(0); else FLAGW_OF(1); }
flag_szp8((uint8_t)(s&0xFF)); break;

case 5: //SHR r/m8
if (cnt == 1) { if (s&0x80) FLAGW_OF(1); else FLAGW_OF(0); }
//FLAGW_AF(0);
for (shift = 1; shift <= cnt; shift++) {
FLAGW_CF(s & 1);
Show last 150 lines
			//backup = s; //Save backup!
s = s >> 1;
//if (((backup^s)&0x10)) FLAGW_AF(1); //Auxiliary carry?
}
flag_szp8((uint8_t)(s & 0xFF)); break;

case 7: //SAR r/m8
msb = s & 0x80;
//FLAGW_AF(0);
for (shift = 1; shift <= cnt; shift++) {
FLAGW_CF(s & 1);
//backup = s; //Save backup!
s = (s >> 1) | msb;
//if (((backup^s)&0x10)) FLAGW_AF(1); //Auxiliary carry?
}
byte tempSF;
tempSF = FLAG_SF; //Save the SF!
/*flag_szp8((uint8_t)(s & 0xFF));*/
//http://www.electronics.dit.ie/staff/tscarff/8086_instruction_set/8086_instruction_set.html#SAR says only C and O flags!
if (!cnt) //Nothing done?
{
FLAGW_SF(tempSF); //We don't update when nothing's done!
}
else if (cnt==1) //Overflow is cleared on all 1-bit shifts!
{
flag_s8(s); //Affect sign as well!
FLAGW_OF(0); //Cleared!
}
else if (cnt) //Anything shifted at all?
{
flag_s8(s); //Affect sign as well!
}
if ((EMULATED_CPU>=CPU_NECV30) && cnt) //NECV20+ affected?
{
flag_p8(s); //Affect parity as well!
}
break;
}
op_grp2_cycles(cnt, varshift);
return(s & 0xFF);
}

word op_grp2_16(byte cnt, byte varshift) {
//uint32_t d,
INLINEREGISTER uint_32 s, shift, oldCF, msb;
//if (cnt>0x10) return(oper1); //NEC V20/V30+ limits shift count
if (EMULATED_CPU >= CPU_NECV30) cnt &= 0x1F; //Clear the upper 3 bits to become a NEC V20/V30+!
//word backup;
s = oper1;
oldCF = FLAG_CF;
switch (thereg) {
case 0: //ROL r/m16
for (shift = 1; shift <= cnt; shift++) {
if (s & 0x8000) FLAGW_CF(1); else FLAGW_CF(0);
s = s << 1;
s = s | FLAG_CF;
}
if (cnt==1) FLAGW_OF(FLAG_CF ^ ((s >> 15) & 1));
break;

case 1: //ROR r/m16
for (shift = 1; shift <= cnt; shift++) {
FLAGW_CF(s & 1);
s = (s >> 1) | (FLAG_CF << 15);
}
if (cnt==1) FLAGW_OF((s >> 15) ^ ((s >> 14) & 1));
break;

case 2: //RCL r/m16
for (shift = 1; shift <= cnt; shift++) {
oldCF = FLAG_CF;
if (s & 0x8000) FLAGW_CF(1); else FLAGW_CF(0);
s = s << 1;
s = s | oldCF;
//oldCF = ((s&0x8000)>>15)&1; //Save FLAG_CF!
//s = (s<<1)+FLAG_CF;
//FLAG_CF = oldCF;
}
if (cnt==1) FLAGW_OF(FLAG_CF ^ ((s >> 15) & 1));
break;

case 3: //RCR r/m16
for (shift = 1; shift <= cnt; shift++) {
oldCF = FLAG_CF;
FLAGW_CF(s & 1);
s = (s >> 1) | (oldCF << 15);
//oldCF = s&1;
//s = (s<<1)+(FLAG_CF<<16);
//FLAG_CF = oldCF;
}
if (cnt==1) FLAGW_OF((s >> 15) ^ ((s >> 14) & 1));
break;

case 4: case 6: //SHL r/m16
//FLAGW_AF(0);
for (shift = 1; shift <= cnt; shift++) {
if (s & 0x8000) FLAGW_CF(1); else FLAGW_CF(0);
//if (s & 0x8) FLAGW_AF(1); //Auxiliary carry?
s = (s << 1) & 0xFFFF;
}
if (cnt==1) { if (FLAG_CF == (s >> 15)) FLAGW_OF(0); else FLAGW_OF(1); }
flag_szp16(s); break;

case 5: //SHR r/m16
if (cnt==1) { if (s&0x8000) FLAGW_OF(1); else FLAGW_OF(0); }
//FLAGW_AF(0);
for (shift = 1; shift <= cnt; shift++) {
FLAGW_CF(s & 1);
//backup = s; //Save backup!
s = s >> 1;
//if (((backup^s)&0x10)) FLAGW_AF(1); //Auxiliary carry?
}
flag_szp16(s); break;

case 7: //SAR r/m16
msb = s & 0x8000; //Read the MSB!
//FLAGW_AF(0);
for (shift = 1; shift <= cnt; shift++) {
FLAGW_CF(s & 1);
//backup = s; //Save backup!
s = (s >> 1) | msb;
//if (((backup^s)&0x10)) FLAGW_AF(1); //Auxiliary carry?
}
byte tempSF;
tempSF = FLAG_SF; //Save the SF!
/*flag_szp16(s);*/
//http://www.electronics.dit.ie/staff/tscarff/8086_instruction_set/8086_instruction_set.html#SAR says only C and O flags!
if (!cnt) //Nothing done?
{
FLAGW_SF(tempSF); //We don't update when nothing's done!
}
else if (cnt==1) //Overflow is cleared on all 1-bit shifts!
{
flag_s16(s); //Affect sign as well!
FLAGW_OF(0); //Cleared!
}
else if (cnt) //Anything shifted at all?
{
flag_s16(s); //Affect sign as well!
}
if ((EMULATED_CPU>=CPU_NECV30) && cnt) //NECV20+ affected?
{
flag_p16(s); //Affect parity as well!
flag_s16(s); //Affect sign as well!
}
break;
}
op_grp2_cycles(cnt, varshift|4);
return(s & 0xFFFF);
}

32-bit versions are just extended versions of the 16-bit instructions.

Can anyone see what's going wrong?

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

Reply 55 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just modified the PIC to not ignore raising of the IR lines and registering the IRQ as pending while the IMR register's corresponding IR bit is set. That fixes the input on Windows 3.0 it seems? Doesn't the PIC ignore the IR lines being raised when the IMR bit is set? Or does it just mask the incoming line to 0?

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

Reply 56 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried to install Windows 3.0 on the current CPU core. Something goes horribly wrong at the end, creating the program groups(VGA w/ 80188 emulation):

428-Windows3.0SetupCrashing.png
Filename
428-Windows3.0SetupCrashing.png
File size
26.64 KiB
Views
586 views
File comment
Windows 3.0 setup crashing creating the program groups.
File license
Fair use/fair dealing exception

Looking at the current emulation status:
CS:IP is 4900:0004. Previous opcode: 0x28(last executed opcode, not 0x0F opcode). Last opcode(actually current opcode): 0xFF. ModR/M byte is 0xFF. It isn't fetching anymore. The fault raising flag is set(so a fault has been raised).

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

Reply 57 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried starting win.com after that, it starts the loading screen on the Compaq Deskpro 386 with 80486, then directly after finishing the screen drawing, it jumps to a null descriptor, which triple faults the CPU(because the double fault handler is a NULL descriptor as well). Having improved the handling of the protection and errors, it now properly triple faults and resets the CPU when needed.

Now, why is the IDT incorrect? Or the not present GDT entry for jumping(maybe directly after entering protected mode)?

CR0 has value 00000009h loaded(protected mode, task switched).
The GDT is at 0x110000(limit FFEF). The IDT is at 0x120000(limit 0x7FF). The very first jump is loaded from address 0x110110.

The descriptor that's pointed at is a NULL descriptor(containing zeroed RAM only). The fault happens at 1172:09B6.

Can anyone tell me why that RAM is zeroed in the first place?

Next, it tries to run the #NP interrupt handler. That one's located at 0x120058 in linear RAM. That's also zeroed. Thus another #NP exception at descriptor address 0x120040, that is also zeroed RAM. That causes a Double fault exception(interrupt 08h). The interrupt information is loaded from 0x120040. That also contains zeroed RAM. Then, the resulting #NP exception causes a triple fault to occur, rebooting the PC?

Can anyone tell me why there isn't any interrupt handlers, nor any GDT entries at the specified addresses? Is it pointing to the wrong address?

Edit: Monitoring the LGDT/LIDT instructions show that it tries to load in Standard mode(80386 enhanced mode won't run because setup didn't copy the required files, crashing before getting to the point of copying the Standard/enhanced mode files).

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

Reply 58 of 142, by crazyc

User metadata
Rank Member
Rank
Member

You can tell it's in Standard mode by just looking at CR0. In Enhanced mode, paging would be enabled. As for why the IDT is mostly zero, that's probably impossible to tell with the information available. I can tell you that when run in a different emulator, descriptor 0x0008 points to the GDT and 0x0010 points to the IDT.

Reply 59 of 142, by superfury

User metadata
Rank l33t++
Rank
l33t++

Looking at the RAM accesses, the address 0x110110 isn't ever written to RAM when loading Windows 3.0? So the CPU is loading a descriptor from uninitialized RAM(or cleared by the BIOS during POST).

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