Merge branch 'master' into gh-pages
This commit is contained in:
commit
f2582de7b6
9 changed files with 932 additions and 690 deletions
83
_posts/2017-06-15-adventures-in-archiving.md
Normal file
83
_posts/2017-06-15-adventures-in-archiving.md
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
layout: post
|
||||
title: Adventures in Archiving
|
||||
date: 2017-06-15 22:00:00
|
||||
permalink: /blog/2017/06/15/
|
||||
machines:
|
||||
- type: pcx86
|
||||
id: ibm5150
|
||||
config: /devices/pcx86/machine/5150/cga/64kb/machine.xml
|
||||
autoMount:
|
||||
A:
|
||||
path: /disks/pcx86/dos/ibm/1.00/PCDOS100.json
|
||||
B:
|
||||
path: /apps/pcx86/1983/adventmath/ADVENTMATH100.json
|
||||
autoType: 8-10-81\\rb:\\ra:basica castle\\r
|
||||
---
|
||||
|
||||
In October 1983, IBM released a game called "Adventures in Math", which apparently tried to make mathematics as
|
||||
exciting as walking through a dungeon full of locked doors, treasures, spiders, and more. I had never heard of this
|
||||
game, until I was recently browsing the [Internet Archive](https://archive.org/)'s
|
||||
[MS-DOS Showcase](https://archive.org/details/softwarelibrary_msdos_showcase):
|
||||
|
||||
> This collection is a hand-picked set of selections from the MS-DOS Software Library of the Internet Archive.
|
||||
They've been chosen because they represent major parts of the MS-DOS story, because they are particularly impressive,
|
||||
and because they're fun. The intention is to eventually link these games to manuals and other materials as time goes on.
|
||||
|
||||
> Curation was done by Jason Scott, Internet Archive's Software Librarian. He can be reached at jscott@archive.org with
|
||||
suggestion, questions and inquiries.
|
||||
|
||||
For some reason, "Adventures in Math" caught my eye. You can play it on the
|
||||
[Internet Archive](https://archive.org/details/msdos_Adventures_in_Math_1983), or play it below, using PCjs. In
|
||||
fact, I invite you to play it in BOTH places, and let me know what you think.
|
||||
|
||||
A word of warning: this is NOT a great game. I find it interesting only as an example of the challenges we face
|
||||
archiving and emulating old software.
|
||||
|
||||
{% include machine.html id="ibm5150" %}
|
||||
|
||||
Hosting the software on the PCjs website was more tedious than I'd expected, but that wasn't due to technical issues.
|
||||
The biggest challenge was isolating and recreating the original distribution software. You can find all the gory
|
||||
details on the page I created for "[Adventures in Math](/apps/pcx86/1983/adventmath/)".
|
||||
|
||||
In short, although the software is archived inside multiple ZIP archives at the [Internet Archive](https://archive.org/),
|
||||
none of them appeared to contain an un-mingled, un-modified, distribution-only copy of the original software.
|
||||
And discovering that the software was archived inside multiple ZIP archives was a purely accidental discovery, not
|
||||
something one could easily determine using the Internet Archive's own search engine.
|
||||
|
||||
### Emulation Challenges
|
||||
|
||||
There are also some fundamental problems with the Internet Archive's approach to emulation. They load sets of files,
|
||||
along with custom batch files, into tightly coupled machine configurations, with no indication which files were part
|
||||
of the original software distribution, and no hardware details regarding their "mystery" machine configurations.
|
||||
|
||||
And the Internet Archive's overall "emulation experience" is often not very faithful. Their rendering of
|
||||
"Adventures in Math" gives the impression that the game ran *much* faster than it actually ran on a 4.77Mhz IBM PC.
|
||||
While their emulator can be configured operate at different speeds, it's unclear which of their holdings have already
|
||||
been "tuned". As a fallback, they do provide some user controls:
|
||||
|
||||
> "While the program is running, press CTRL-F11 to slow the program down. Pressing CTRL-F11 repeatedly will slow it
|
||||
down further, until the speed is more reasonable. (Pressing CTRL-F12 repeatedly will attempt to speed things up.)"
|
||||
|
||||
but in general, the user has no idea what speed they have currently selected, or what the target speed should be.
|
||||
For users who simply want "to play the game," that may be fine, but an historian would probably prefer to see how the
|
||||
game originally operated and how each screen was painstakingly rendered, to better understand both the original user
|
||||
experience and the challenges that early software developers faced.
|
||||
|
||||
The failure to archive software exactly as it was originally distributed, generally as one or more disk image (IMG)
|
||||
files along with scanned (PDF) copies of the documentation, is the most serious problem we collectively face. I don't
|
||||
blame the Internet Archive, because in most cases, they're simply archiving what someone else archived before them,
|
||||
and those earlier "archivists" often didn't take the time to thoroughly preserve and document everything.
|
||||
|
||||
On the other hand, the Internet Archive could do a better job of cataloging its holdings, recording the provenance of
|
||||
everything they have archived, maintaining a clear separation of original material from subsequent modifications
|
||||
(including any modifications created solely for ease of emulation), providing more control over machine configurations,
|
||||
and enabling the use of third-party emulators -- like PCjs -- which may be able to perform a more faithful rendering
|
||||
of certain software packages.
|
||||
|
||||
In addition, I would hope that anything the Internet Archive "archives" itself (ie, from original distribution media)
|
||||
is duplicated and preserved according to a *much* higher standard than any files, documents, etc, it has simply scraped
|
||||
from the Internet.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*Jun 15, 2017*
|
||||
|
|
@ -11,7 +11,7 @@ machines:
|
|||
path: /disks/pcx86/dos/ibm/1.00/PCDOS100.json
|
||||
B:
|
||||
path: /apps/pcx86/1983/adventmath/ADVENTMATH100.json
|
||||
autoType: 8-10-81\rb:\ra:basica castle\r
|
||||
autoType: 8-10-81\\rb:\\ra:basica castle\\r
|
||||
---
|
||||
|
||||
Adventures in Math (1983)
|
||||
|
|
@ -36,12 +36,12 @@ The contents of their ZIP archive contained:
|
|||
-rwxr-xr-x@ 1 Jeff staff 13 Dec 24 1996 Sn
|
||||
-rwxr-xr-x@ 1 Jeff staff 369 Dec 24 1996 Topten
|
||||
|
||||
It's unfortunate that the archive did not contain a complete dump of the original "Adventures in Math" diskette.
|
||||
It's especially disturbing that all the files in the archive are dated "Dec 24 1996", calling into question which,
|
||||
if any, of these files are authentic.
|
||||
It was unfortunate that the archive did not contain a complete dump of the original "Adventures in Math"
|
||||
diskette, and that all the files in the archive were dated "Dec 24 1996", calling into question the authenticity
|
||||
of the files.
|
||||
|
||||
After digging around a bit more on the Internet Archive, I discovered that
|
||||
[A Large Collection of DOS Collections](https://archive.org/details/large_dos_collection_2013_08) contains:
|
||||
[A Large Collection of DOS Collections](https://archive.org/details/large_dos_collection_2013_08) contained:
|
||||
|
||||
- DOS Collection v0.7/DVD1/Adventures In Math (1983)(Ibm).zip
|
||||
- main torrent/1983/Adventures in Math (1983)(IBM) [Educational].zip
|
||||
|
|
@ -78,10 +78,10 @@ And in the second ZIP file:
|
|||
-rw-r--r--@ 1 Jeff staff 369 Sep 17 1999 Topten
|
||||
-rw-r--r--@ 1 Jeff staff 170 Jan 22 2011 file_id.diz
|
||||
|
||||
I decided to start with the contents of the second ZIP file, since the timestamps of the most of the files
|
||||
I decided to start with the contents of the second ZIP file, since the timestamps of most of the files
|
||||
appeared to be legitimate.
|
||||
|
||||
One strange file common to *all* these archives is **MONOCODE.000**. Dumping that file revealed:
|
||||
One strange file common to *all* the archives was **MONOCODE.000**. Dumping that file revealed:
|
||||
|
||||
00000c60 20 4d 4f 4e 4f 50 4f 4c 59 20 69 73 20 61 20 72 | MONOPOLY is a r|
|
||||
00000c70 65 67 69 73 74 65 72 65 64 20 74 72 61 64 65 6d |egistered tradem|
|
||||
|
|
@ -93,15 +93,14 @@ One strange file common to *all* these archives is **MONOCODE.000**. Dumping th
|
|||
00000cd0 20 44 6f 6e 20 50 68 69 6c 6c 69 70 20 47 69 62 | Don Phillip Gib|
|
||||
00000ce0 73 6f 6e 20 5b e8 96 7d 03 35 2e 31 b8 5d 00 50 |son [..}.5.1.].P|
|
||||
|
||||
So at some point, unrelated ("MONOPOLY") files were mingled with this game. I deleted the file.
|
||||
So at some point, unrelated "MONOPOLY" files were mingled with this game. I deleted **MONOCODE.000**.
|
||||
|
||||
Another unexpected file is **BASICA.EXE** (54277 bytes) from 1999. It seems unlikely that IBM would have distributed
|
||||
Another unexpected file was **BASICA.EXE** (54277 bytes) from 1999. It seems unlikely that IBM would have distributed
|
||||
*any* BASIC binary with this game, because DOS was a prerequisite, and at the time, all versions of DOS included BASIC.
|
||||
IBM's PC-DOS shipped with **BASICA.COM**, and OEM versions of DOS shipped with either **GWBASIC.EXE** or **BASIC.EXE**.
|
||||
IBM's PC-DOS shipped with **BASICA.COM** and OEM versions of DOS shipped with either **GWBASIC.EXE** or **BASIC.EXE**.
|
||||
|
||||
The closest matching binary I'd seen up to this point was **BASICA.EXE** from [COMPAQ DOS 1.12](/disks/pcx86/dos/compaq/1.12/)
|
||||
(54304 bytes). And sure enough, examining the strings contained inside this **BASICA.EXE** revealed that it was a close
|
||||
relative:
|
||||
(54304 bytes). And sure enough, dumping the strings inside this **BASICA.EXE** revealed that it was a close relative:
|
||||
|
||||
The COMPAQ Personal Computer BASIC
|
||||
Version 1.13
|
||||
|
|
@ -109,11 +108,8 @@ relative:
|
|||
|
||||
It's safe to say that IBM would not have distributed a COMPAQ binary; if IBM had distributed any BASIC binary at all,
|
||||
it would have been their own **BASICA.COM**. Of course, the problem with IBM's **BASICA.COM** is that it also requires
|
||||
an IBM PC with ROM BASIC installed, which is why some people would have preferred the COMPAQ version: it has no ROM
|
||||
dependencies.
|
||||
|
||||
Anyway, I've deleted **BASICA.EXE**. The proper thing to do -- and what any purchaser of this game would have to do --
|
||||
is boot a machine with an appropriate version of DOS and use the BASIC binary included with DOS to run this game.
|
||||
an IBM PC with ROM BASIC installed, which is why some people would have preferred the COMPAQ binary: it had no ROM
|
||||
dependencies. Anyway, I deleted **BASICA.EXE**.
|
||||
|
||||
Finally, there was **FILE_ID.DIZ**:
|
||||
|
||||
|
|
@ -147,13 +143,13 @@ and **TOPTEN**:
|
|||
Z[z],55677,LARGE,07-24-81
|
||||
[z],55197,LARGE,07-23-81
|
||||
|
||||
All those files have been deleted as well, leaving 8 files dated "Aug 11 1983". Next, I used the PCjs
|
||||
[DiskDump](/modules/diskdump/) utility to create a disk image from a directory ("archive/disk") containing just
|
||||
All those files were deleted as well, leaving 8 files dated "Aug 11 1983". Next, I used the PCjs
|
||||
[DiskDump](/modules/diskdump/) utility to create a disk image from a directory ("archive/disk") containing
|
||||
those files:
|
||||
|
||||
diskdump --dir=archive/disk --format=json --output=ADVENTMATH100.json --manifest
|
||||
|
||||
The resulting 160Kb disk image contains:
|
||||
Here's a directory listing of the resulting 160Kb disk image:
|
||||
|
||||
Volume in drive A is PCJS ORG
|
||||
Directory of A:\
|
||||
|
|
@ -168,10 +164,10 @@ The resulting 160Kb disk image contains:
|
|||
SN 13 8-11-83 12:00p
|
||||
8 File(s) 108544 bytes free
|
||||
|
||||
And this disk has now been added to the PCjs [IBM PC Disk Library](/disks/pcx86/) as "Adventures in Math (1983)".
|
||||
This disk has now been added to the PCjs [IBM PC Disk Library](/disks/pcx86/) as "Adventures in Math (1983)".
|
||||
|
||||
I originally selected an [IBM PC (Model 5150, 64Kb) with Color Display](/devices/pcx86/machine/5150/cga/64kb/),
|
||||
which boots PC-DOS 2.00 by default. However, in the course of starting the game, it would crash:
|
||||
To run the game, I originally selected an [IBM PC (Model 5150, 64Kb) with Color Display](/devices/pcx86/machine/5150/cga/64kb/),
|
||||
which boots PC-DOS 2.00 by default. However, in the course of starting the game, it crashed:
|
||||
|
||||

|
||||
|
||||
|
|
@ -183,9 +179,28 @@ It appeared to run fine with 256Kb of RAM, but these were IBM's "System Requirem
|
|||
|
||||
> One diskette drive
|
||||
|
||||
so I reconfigured the machine to boot PC-DOS 1.00, which required less RAM than PC-DOS 2.00, and that appeared to be
|
||||
sufficient. Note that the game was released in October 1983, well after the March 1983 release of PC-DOS 2.00, so
|
||||
either it wasn't tested with PC-DOS 2.00 on a 64Kb machine, or the error is a PCjs anomaly.
|
||||
so I reconfigured the machine to boot PC-DOS 1.00, which requires less RAM than PC-DOS 2.00, and that worked.
|
||||
Note that the game was released in October 1983, well after the March 1983 release of PC-DOS 2.00, so it should
|
||||
have been tested with PC-DOS 2.00 on a 64Kb machine, but perhaps it wasn't.
|
||||
|
||||
The machine on this page is configured with the following "autoType" sequence:
|
||||
|
||||
autoType: 8-10-81\\rb:\\ra:basica castle\\r
|
||||
|
||||
which translates to:
|
||||
|
||||
8-10-81 [enter an arbitrary date]
|
||||
b: [switch to drive B:]
|
||||
a:basica castle [run BASICA on drive A: and load CASTLE.BAS on drive B:]
|
||||
|
||||
This is one of the preferred methods of demonstrating software in PCjs: loading unmodified disk images into machines
|
||||
that match the software's system requirements as closely as possible, powering the machine, and then automatically
|
||||
executing a series of commands that an owner of that hardware and software combination would have likely executed.
|
||||
|
||||
The other preferred method is to use a machine state file, which restores the machine to a state where the software is
|
||||
already running. This is the fastest approach, and it is useful when the software has an involved installation
|
||||
process, but it takes more effort to set up. The [VisiCalc (1981)](/apps/pcx86/1981/visicalc/) demo operates this way,
|
||||
but it does so purely for convenience (and because it predates the "autoType" feature).
|
||||
|
||||
References
|
||||
----------
|
||||
|
|
|
|||
|
|
@ -7,12 +7,80 @@ permalink: /disks/pcx86/fixed/10mb/
|
|||
10Mb Hard Drive (Fixed Disk) Images
|
||||
---
|
||||
|
||||
This folder contains the following 10Mb disk images:
|
||||
This folder contains the following 10Mb fixed disk images:
|
||||
|
||||
* Empty formatted disk ([PCDOS200-EMPTY](PCDOS200-EMPTY.json))
|
||||
* PC-DOS 2.00 with Windows 1.01 for CGA ([PCDOS200-WIN101-CGA](pcdos200-win101-cga.xml))
|
||||
* PC-DOS 2.00 with Windows 1.01 for EGA ([PCDOS200-WIN101-EGA](pcdos200-win101-ega.xml))
|
||||
|
||||
These disk images are used by various [Model 5160](/devices/pcx86/machine/5160/) machine configurations.
|
||||
These disk images are used by various IBM PC XT [Model 5160](/devices/pcx86/machine/5160/) machine configurations.
|
||||
|
||||
NOTE: The empty disk is *completely* empty. It was partitioned with the PC-DOS 2.00 **FDISK** utility, allocating
|
||||
the entire disk to a single DOS partition, and then it was formatted with the PC-DOS 2.00 **FORMAT** utility.
|
||||
Neither the **FORMAT** "/S" option nor the **SYS** command were used, so no system files were transferred, leaving
|
||||
the disk completely empty and non-bootable.
|
||||
|
||||
After formatting, PC-DOS 2.00 reports:
|
||||
|
||||
10592256 bytes total disk space
|
||||
10592256 bytes available on disk
|
||||
|
||||
As explained in the [DiskDump source code](/modules/diskdump/lib/diskdump.js), in its description of the 10Mb
|
||||
BPB, a 10Mb "Type 3" PC XT fixed disk contains:
|
||||
|
||||
306 cylinders
|
||||
4 heads
|
||||
17 sectors/track
|
||||
|
||||
for a total of 20808 sectors or 10,653,696 bytes. However, as p.1-179 of the PC XT Technical Reference Manual
|
||||
(April 1983) notes:
|
||||
|
||||
WARNING: The last cylinder on the fixed disk drive is reserved for diagnostic use.
|
||||
Diagnostic write tests will destroy any data on this cylinder.
|
||||
|
||||
And this is confirmed by the PC XT BIOS, p.A-94, in the code for the "GET PARAMETERS (AH = 8)" function:
|
||||
|
||||
C800:03B2 268B07 MOV AX,ES:[BX] ; MAX NUMBER OF CYLINDERS
|
||||
C800:03B5 2D0200 SUB AX,2 ; ADJUST FOR 0-N AND RESERVE LAST TRACK
|
||||
|
||||
By "RESERVE LAST TRACK", they really meant "RESERVE LAST CYLINDER", because 68 (not 17) sectors are reserved at
|
||||
the end of the disk. In addition, the first sector of the disk is reserved for the Master Boot Record (MBR), so there
|
||||
are a total of 69 reserved sectors. (20808 - 69) = 20739 or 0x5103, which is exactly what's stored in the "total
|
||||
sectors" field of the disk's BPB, yielding a total partition size of 10,618,368 bytes.
|
||||
|
||||
However, that 69-sector overhead is not the end of the story. There is also overhead incurred by the FAT file system,
|
||||
which, in this case, consists of:
|
||||
|
||||
- Boot sector (1)
|
||||
- FAT sectors (2 * 8 = 16)
|
||||
- Root directory sectors (32)
|
||||
|
||||
for a total of 49 sectors, leaving (20739 - 49) = 20690 sectors. Moreover, free space is measured in clusters,
|
||||
not sectors, and the partition uses 8 sectors/cluster, leaving room for 2586.25 clusters. Since a fractional cluster
|
||||
is not allowed, another 2 sectors are lost, bringing the total FAT file system overhead to 51 sectors.
|
||||
|
||||
Thus, actual free space is (20739 - 51) * 512, or 10,592,256 bytes, which is exactly what DOS reports as the available
|
||||
space.
|
||||
|
||||
Some sources on the internet (eg, http://www.wikiwand.com/en/Timeline_of_DOS_operating_systems) claim that the (FAT)
|
||||
file system overhead for the XT's 10Mb disk is "50 sectors". As they explain:
|
||||
|
||||
"The fixed disk has 10,618,880 bytes of raw space: 305 cylinders (the equivalent of tracks) × 2 platters
|
||||
× 2 sides or heads per platter × 17 sectors per track = 20,740 sectors × 512 bytes per sector = 10,618,880
|
||||
bytes...."
|
||||
|
||||
and:
|
||||
|
||||
"With DOS the only partition, the combined overhead is 50 sectors leaving 10,592,256 bytes for user data:
|
||||
DOS's FAT is eight sectors (16 sectors for two copies) + 32 sectors for the root directory, room for 512
|
||||
directory entries + 2 sectors (one master and one DOS boot sector) = 50 sectors...."
|
||||
|
||||
However, that's incorrect. First, the disk has 306 cylinders, not 305. Second, there are TWO overhead values:
|
||||
the overhead OUTSIDE the partition (69 sectors) and the overhead INSIDE the partition (51 sectors). They failed
|
||||
to account for the reserved cylinder in the first calculation and the lost fractional cluster in the second
|
||||
calculation, and then they conflated the two values to produce a single (incorrect) result.
|
||||
|
||||
---
|
||||
|
||||
To use one of these disks with another machine configuration, include:
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -530,15 +530,15 @@ DiskDump.aDefaultBPBs = [
|
|||
/*
|
||||
* Here's some useful background information on a 10Mb PC XT fixed disk, partitioned with a single DOS partition.
|
||||
*
|
||||
* The BPB for a 10Mb "type 3" PC XT drive specifies 0x5103 or 20739 for TOTAL_SECS, which is the partition
|
||||
* The BPB for a 10Mb "type 3" PC XT hard disk specifies 0x5103 or 20739 for TOTAL_SECS, which is the partition
|
||||
* size in sectors (10,618,368 bytes), whereas total disk size is 20808 sectors (10,653,696 bytes). The partition
|
||||
* is 69 sectors smaller than the disk because the first sector is reserved for the MBR and 68 sectors (the entire
|
||||
* last cylinder) are reserved for diagnostics, head parking, etc. This cylinder usage is confirmed by FDISK,
|
||||
* which reports that 305 cylinders (not 306) are assigned to the DOS partition.
|
||||
*
|
||||
* That 69-sector overhead is NOT the overhead incurred by the FAT file system. That overhead is the boot sector
|
||||
* That 69-sector overhead is NOT overhead incurred by the FAT file system. The FAT overhead is the boot sector
|
||||
* (1), FAT sectors (2 * 8), and root directory sectors (32), for a total of 49 sectors, leaving 20739 - 49 or
|
||||
* 20690 sectors. However, free space is measured in clusters, not sectors, and the partition uses 8 sectors/cluster,
|
||||
* 20690 sectors. Moreover, free space is measured in clusters, not sectors, and the partition uses 8 sectors/cluster,
|
||||
* leaving room for 2586.25 clusters. Since a fractional cluster is not allowed, another 2 sectors are lost, for
|
||||
* a total of 51 sectors of FAT overhead. So actual free space is (20739 - 51) * 512, or 10,592,256 bytes -- which
|
||||
* is exactly what is reported as the available space on a freshly formatted 10Mb PC XT fixed disk.
|
||||
|
|
@ -562,7 +562,7 @@ DiskDump.aDefaultBPBs = [
|
|||
* and then they conflated the two values to produce a single (incorrect) result.
|
||||
*
|
||||
* Even if one were to assume that the disk had only 305 cylinders, that would only change the partitioning overhead
|
||||
* to 1 sector; the file system overhead would still be 51 sectors.
|
||||
* to 1 sector; the FAT file system overhead would still be 51 sectors.
|
||||
*/
|
||||
[ // define BPB for 10Mb hard drive
|
||||
0xEB, 0xFE, 0x90, // 0x00: JMP instruction, following by 8-byte OEM signature
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ if (NODE) {
|
|||
var Keys = require("../../shared/lib/keys");
|
||||
var State = require("../../shared/lib/state");
|
||||
var PCX86 = require("./defines");
|
||||
var Interrupts = require("./interrupts");
|
||||
var Messages = require("./messages");
|
||||
var ChipSet = require("./chipset");
|
||||
var CPU = require("./cpu");
|
||||
|
|
@ -59,6 +60,8 @@ class Keyboard extends Component {
|
|||
* "US84"
|
||||
* "US101"
|
||||
*
|
||||
* autoType: string of keys to automatically inject when the machine is ready (undefined if none)
|
||||
*
|
||||
* Its main purpose is to receive binding requests for various keyboard events, and to use those events
|
||||
* to simulate the PC's keyboard hardware.
|
||||
*
|
||||
|
|
@ -137,7 +140,14 @@ class Keyboard extends Component {
|
|||
this.msAutoRepeat = 500;
|
||||
this.msNextRepeat = 100;
|
||||
this.msAutoRelease = 50;
|
||||
this.msInjectDelay = 300; // number of milliseconds between injected keystrokes
|
||||
this.msInjectDelay = 150; // number of milliseconds between injected keystrokes
|
||||
|
||||
/*
|
||||
* autoType records the machine's specified autoType sequence, if any. At the appropriate signal(s),
|
||||
* autoType will be copied to autoInject, and injection will commence.
|
||||
*/
|
||||
this.autoInject = null;
|
||||
this.autoType = parmsKbd['autoType'];
|
||||
|
||||
/*
|
||||
* HACK: We set fAllDown to false to ignore all down/up events for keys not explicitly marked as ONDOWN;
|
||||
|
|
@ -351,6 +361,26 @@ class Keyboard extends Component {
|
|||
this.cpu = cpu;
|
||||
this.dbg = dbg;
|
||||
this.chipset = cmp.getMachineComponent("ChipSet");
|
||||
this.autoType = cmp.getMachineParm('autoType') || this.autoType;
|
||||
cpu.addIntNotify(Interrupts.DOS, this.intDOS.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* intDOS()
|
||||
*
|
||||
* Monitors selected DOS interrupts for signals to initialize 'autoType' injection.
|
||||
*
|
||||
* @this {Keyboard}
|
||||
* @param {number} addr
|
||||
* @return {boolean} true to proceed with the INT 0x21 software interrupt, false to skip
|
||||
*/
|
||||
intDOS(addr)
|
||||
{
|
||||
var AH = (this.cpu.regEAX >> 8) & 0xff;
|
||||
if (AH == 0x0A) {
|
||||
this.injectInit();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -726,6 +756,7 @@ class Keyboard extends Component {
|
|||
/*
|
||||
* Make sure the auto-injection buffer is empty (an injection could have been in progress on any reset after the first).
|
||||
*/
|
||||
this.autoInject = null;
|
||||
this.sInjectBuffer = "";
|
||||
}
|
||||
|
||||
|
|
@ -833,6 +864,19 @@ class Keyboard extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* injectInit()
|
||||
*
|
||||
* @this {Keyboard}
|
||||
*/
|
||||
injectInit()
|
||||
{
|
||||
if (!this.autoInject && this.autoType) {
|
||||
this.autoInject = this.autoType;
|
||||
this.injectKeys(this.autoInject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* injectKeys(sKeys, msDelay)
|
||||
*
|
||||
|
|
@ -857,15 +901,41 @@ class Keyboard extends Component {
|
|||
*/
|
||||
injectKeysFromBuffer(msDelay)
|
||||
{
|
||||
if (this.sInjectBuffer.length > 0) {
|
||||
var ch = this.sInjectBuffer.charCodeAt(0);
|
||||
var charCode = 0;
|
||||
while (this.sInjectBuffer.length > 0 && !charCode) {
|
||||
var ch = this.sInjectBuffer.charAt(0);
|
||||
this.sInjectBuffer = this.sInjectBuffer.substr(1);
|
||||
if (ch != '\\') {
|
||||
charCode = ch.charCodeAt(0);
|
||||
} else {
|
||||
ch = this.sInjectBuffer.charAt(0);
|
||||
this.sInjectBuffer = this.sInjectBuffer.substr(1);
|
||||
switch (ch) {
|
||||
case 'n':
|
||||
charCode = 0x0A;
|
||||
break;
|
||||
case 'r':
|
||||
charCode = 0x0D;
|
||||
break;
|
||||
case 't':
|
||||
charCode = 0x09;
|
||||
break;
|
||||
default:
|
||||
if (ch >= '1' && ch <= '9') {
|
||||
msDelay = ch.charCodeAt(0) * 100;
|
||||
break;
|
||||
}
|
||||
charCode = ch.charCodeAt(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (charCode) {
|
||||
/*
|
||||
* I could require all callers to supply CRs instead of LFs, but this is friendlier.
|
||||
*/
|
||||
if (ch == 0x0a) ch = 0x0d;
|
||||
|
||||
this.sInjectBuffer = this.sInjectBuffer.substr(1);
|
||||
this.addActiveKey(ch, true);
|
||||
if (charCode == 0x0A) charCode = 0x0D;
|
||||
this.addActiveKey(charCode, true);
|
||||
}
|
||||
if (this.sInjectBuffer.length > 0) {
|
||||
setTimeout(function(kbd) {
|
||||
|
|
@ -1012,7 +1082,9 @@ class Keyboard extends Component {
|
|||
*/
|
||||
addActiveKey(simCode, fPress)
|
||||
{
|
||||
if (!Keyboard.SIMCODES[simCode]) {
|
||||
var wCode = Keyboard.SIMCODES[simCode] || Keyboard.SIMCODES[simCode += Keys.KEYCODE.ONDOWN];
|
||||
|
||||
if (!wCode) {
|
||||
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
|
||||
this.printMessage("addActiveKey(" + simCode + "," + (fPress? "press" : "down") + "): unrecognized", true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1461,7 +1461,7 @@ class X86CPU extends CPU {
|
|||
/**
|
||||
* addIntNotify(nInt, fn)
|
||||
*
|
||||
* Add an software interrupt notification handler to the CPU's list of such handlers.
|
||||
* Add a software interrupt notification handler to the CPU's list of such handlers.
|
||||
*
|
||||
* TODO: Consider adding removeIntNotify(). Example use case: if the Debugger's intWindowsDebugger() function
|
||||
* detects that an INT 0x41 client is loaded, it would be quite happy to uninstall itself.
|
||||
|
|
|
|||
|
|
@ -905,8 +905,8 @@ class Debugger extends Component
|
|||
* And to avoid conflicts with MACRO-10 syntax, I've replaced the original mod operator ('%') with '^/'.
|
||||
*
|
||||
* The MACRO-10 binary shifting suffix ('B') is a bit more problematic, since a capital B can also appear
|
||||
* inside symbols. So I pre-scan for that suffix and replace all non-symbolic occurrences with an internal
|
||||
* shift operator ('^_').
|
||||
* inside symbols, or inside hex values. So if the default base is NOT 16, then I pre-scan for that suffix
|
||||
* and replace all non-symbolic occurrences with an internal shift operator ('^_').
|
||||
*
|
||||
* Note that Str.parseInt(), which parseValue() relies on, supports both the MACRO-10 base prefix overrides
|
||||
* and the binary shifting suffix ('B'), but since that suffix can also be a bracketed expression, we have to
|
||||
|
|
@ -923,7 +923,9 @@ class Debugger extends Component
|
|||
* that to generate an error; if we converted it to "AB", evaluation might inadvertently succeed.
|
||||
*/
|
||||
var regExp = /({|}|\|\||&&|\||\^!|\^B|\^O|\^D|\^L|\^-|~|\^_|_|&|!=|!|==|>=|>>>|>>|>|<=|<<|<|-|\+|\^\/|\/|\*|,,| )/;
|
||||
if (this.nBase != 16) {
|
||||
sExp = sExp.replace(/(^|[^A-Z0-9$%.])([0-9]+)B/, "$1$2^_").replace(/\s+/g, ' ');
|
||||
}
|
||||
var asValues = sExp.split(regExp);
|
||||
value = this.parseArray(asValues, 0, asValues.length, this.nBase, aUndefined);
|
||||
if (value !== undefined && fPrint) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue