Starting work on disambiguating PCjs the emulator from PCjs the project/website; the emulator will become PCx86

This commit is contained in:
Jeff Parsons 2016-05-16 20:53:57 -07:00
commit 288f28055d
1519 changed files with 16242 additions and 6939 deletions

View file

@ -5,17 +5,17 @@ date: 2015-07-17 11:00:00
category: Windows 95
permalink: /blog/2015/07/17/
machines:
- type: pc
- type: pcx86
id: deskpro386
debugger: true
state: /disks/pc/windows/win95/4.00.950/deskpro386.json
config: /devices/pc/machine/compaq/deskpro386/vga/4096kb/debugger/machine.xml
drives: '[{name:"68Mb Hard Disk",type:4,path:"http://archive.pcjs.org/disks/pc/fixed/68mb/win95.json"}]'
state: /disks/pcx86/windows/win95/4.00.950/deskpro386.json
config: /devices/pcx86/machine/compaq/deskpro386/vga/4096kb/debugger/machine.xml
drives: '[{name:"68Mb Hard Disk",type:4,path:"http://archive.pcjs.org/disks/pcx86/fixed/68mb/win95.json"}]'
autoMount: ''
---
This week (July 14, 2015) was the 20th anniversary of Windows 95 RTM ("Release To Manufacturing"). So I decided to
throw a PCjs party and try running Windows 95 Setup inside a PCjs machine for the first time.
throw a PCjs party and try running Windows 95 Setup inside a PCx86 machine for the first time.
Sadly, it immediately failed:
@ -52,17 +52,17 @@ The failing code:
0E36:0927 07 POP ES
0E36:0928 C3 RET
was easily fixed with a change to [x86cpu.js](/modules/pcjs/lib/x86cpu.js), allowing the IOPL bits to be
was easily fixed with a change to [x86cpu.js](/modules/pcx86/lib/x86cpu.js), allowing the IOPL bits to be
modified in real-mode on an 80386. When I had previously tweaked setPS() to accomodate 80286/80386 discrimination
logic in OS/2 1.0, there was no 80386 support in PCjs at that time, so it was sufficient to *never* allow the
logic in OS/2 1.0, there was no 80386 support in PCx86 at that time, so it was sufficient to *never* allow the
IOPL bits to be altered in real-mode.
The next problem was triggered by Setup's CAB ("Diamond") decompression code, which uses all 32 bits
of the 80386's 32-bit registers. That in itself was not a problem, but by leaving stray bits in the upper halves of
registers like EDX, it exposed a bug in the PCjs I/O instruction handlers, which neglected to mask EDX with 0xFFFF before
registers like EDX, it exposed a bug in the PCx86 I/O instruction handlers, which neglected to mask EDX with 0xFFFF before
performing port lookups, causing mysterious I/O failures that usually manifested themselves as hard disk I/O errors.
Then PCjs crashed in the middle of the decompression of the first CAB file (MINI.CAB). It turned out the stack
Then PCx86 crashed in the middle of the decompression of the first CAB file (MINI.CAB). It turned out the stack
had been improperly adjusted because a "RETF n" instruction mistakenly believed that a stack switch had occurred.
This was, in fact, a left-over condition from a protected-mode stack-switch. That was easily cleared.
@ -75,7 +75,7 @@ fixed by flagging the opcode as genuinely invalid.
> SIDEBAR
> By default, PCjs marks opcodes as invalid *only* if they have been confirmed invalid. PCjs considers the vast
> By default, PCx86 marks opcodes as invalid *only* if they have been confirmed invalid. PCx86 considers the vast
majority of unused/undocumented opcodes to be merely "undefined" until I've seen them in the wild. An instruction will
be marked invalid if I either discover that real hardware treats it as an Invalid Opcode (by throwing the exception)
*or* that real software expects it to. For opcode 0x0F,0xFF, it was the latter.
@ -86,9 +86,9 @@ I consider it a misnomer to refer to any invalid instruction as "undefined".
The other recent Windows 95 oddity I ran into was an instruction with multiple address-override (0x67) prefixes; the
first prefix changed the instruction's addressing mode from 16-bit to 32-bit, and the second prefix changed it back to
16-bit. PCjs should have simply ignored the second prefix.
16-bit. PCx86 should have simply ignored the second prefix.
With all of the above changes in place, PCjs v1.18.4 is able to run Windows 95 Setup a bit farther, but still far from
With all of the above changes in place, PCx86 v1.18.4 is able to run Windows 95 Setup a bit farther, but still far from
completion. If you want to give it a spin yourself, start the machine below (click the "Run" button) and once it has
finished booting, run SETUP from drive B, where the first Windows 95 diskette is already loaded.
@ -103,9 +103,9 @@ diskette.
August 13, 2015 Update
---
PCjs v1.18.8 has made a little more progress running Windows 95 Setup, but CAB decompression still fails almost
PCx86 v1.18.8 has made a little more progress running Windows 95 Setup, but CAB decompression still fails almost
immediately. To monitor DOS calls until the first 36-byte read of PRECOPY1.CAB, try setting the following
breakpoint and then starting the machine, using the PCjs Debugger *input* field next to the **Enter** button:
breakpoint and then starting the machine, using the PCx86 Debugger *input* field next to the **Enter** button:
m dos off
bp 1ED4:16B4 "set fn=ah;dos;if fn!=3f||cx!=24"
@ -132,7 +132,7 @@ second breakpoint can check the value on exit.
Regarding the other Debugger commands shown above, the `dos` command describes the current DOS operation
(alternatively, you could use the `m int on; m dos on` commands to turn on DOS interrupt messages). The `di`
command dumps PCjs BACKTRACK(tm) information, to help you visually confirm which INT 0x21 calls are reading
command dumps PCx86 BACKTRACK(tm) information, to help you visually confirm which INT 0x21 calls are reading
PRECOPY1.CAB. Finally, the `if` command evaluates the given expression, and if the result is non-zero ("true"),
all subsequent commands are executed, up to to any `else` command; otherwise, only commands after the `else`
command will be executed, and if there is no `else` command, execution will stop.
@ -142,17 +142,17 @@ are evaluated using traditional operator precedence (ie, the same as C or JavaSc
parentheses, assignment operators, and unary or ternary operators, are not supported in expressions.
This test machine below has been updated to load WDEB386.EXE prior to starting B:SETUP.EXE, if you prefer using
WDEB386. Make sure the machine is running (ie, click the **Run** button, or use the PCjs Debugger "g" command),
WDEB386. Make sure the machine is running (ie, click the **Run** button, or use the PCx86 Debugger "g" command),
and then click on the Debugger *output* control to give it focus and press CTRL-C to trigger WDEB386.
The Debugger *input* field is used exclusively for PCjs Debugger commands, whereas the *output* textarea combines
all Debugger output *and* WDEB386 COM2 serial port I/O. You can even use the PCjs Debugger to debug
The Debugger *input* field is used exclusively for PCx86 Debugger commands, whereas the *output* textarea combines
all Debugger output *and* WDEB386 COM2 serial port I/O. You can even use the PCx86 Debugger to debug
the WDEB386 debugger; just make sure the appropriate text control has focus before typing a command.
To help reduce confusion, the PCjs Debugger displays a double-character command prefix, to differentiate its commands
To help reduce confusion, the PCx86 Debugger displays a double-character command prefix, to differentiate its commands
from WDEB386's single-character command prompt -- but it's still easy to get confused.
A quick recap of those command prefixes (which you won't see until AFTER you've typed a PCjs command):
A quick recap of those command prefixes (which you won't see until AFTER you've typed a PCx86 command):
* `>>` indicates real-mode
* `##` indicates protected-mode
@ -165,7 +165,7 @@ A quick recap of those command prefixes (which you won't see until AFTER you've
August 21, 2015 Update
---
PCjs v1.19.1 has finally solved a number of nagging bugs. The CAB decompression code itself was running
PCx86 v1.19.1 has finally solved a number of nagging bugs. The CAB decompression code itself was running
fine; it would crash after loading a 32-bit value into EAX *and* a timer interrupt occurred. A path
through the interrupt handler was trashing the upper bits of EAX. The culprit: any of the MOV instructions
that move an immediate value into one of the "high" 8-bit registers (AH, BH, CH, or DH). Those instructions