Final preparations for open source roll-out
This commit is contained in:
parent
e96f0eecd9
commit
60669365f9
40 changed files with 2814 additions and 2639 deletions
53
README.md
53
README.md
|
|
@ -2,8 +2,8 @@ The Original IBM PC in Your Browser
|
||||||
---
|
---
|
||||||
|
|
||||||
Welcome to [pcjs.org](http://www.pcjs.org/) and [PCjs](/docs/about/pcjs/), the first IBM PC simulation to run in your
|
Welcome to [pcjs.org](http://www.pcjs.org/) and [PCjs](/docs/about/pcjs/), the first IBM PC simulation to run in your
|
||||||
web browser without any plugins. It was added to the [JavaScript Machines](/docs/about/) project in Fall 2012.
|
web browser without any plugins. It was added to the [JavaScript Machines](/docs/about/) project in Fall 2012, and is
|
||||||
The project now includes:
|
now part of the [PCjs Project](https://github.com/jeffpar/pcjs) on [GitHub](https://github.com/). The project now includes:
|
||||||
|
|
||||||
* [PCjs](/docs/about/pcjs/), a simulation of the original IBM PC (circa 1981)
|
* [PCjs](/docs/about/pcjs/), a simulation of the original IBM PC (circa 1981)
|
||||||
* [C1Pjs](/docs/c1pjs/), a simulation of the OSI Challenger 1P (circa 1978)
|
* [C1Pjs](/docs/c1pjs/), a simulation of the OSI Challenger 1P (circa 1978)
|
||||||
|
|
@ -60,14 +60,21 @@ copy of the [PCjs web server](http://www.pcjs.org/) and run PCjs simulations:
|
||||||
|
|
||||||
+ A simple Node-based web server ([server.js](server.js))
|
+ A simple Node-based web server ([server.js](server.js))
|
||||||
+ Custom Node modules used by the web server ([HTMLOut](my_modules/htmlout/), [MarkOut](my_modules/markout/), [DiskDump](my_modules/diskdump/), [FileDump](my_modules/filedump/))
|
+ Custom Node modules used by the web server ([HTMLOut](my_modules/htmlout/), [MarkOut](my_modules/markout/), [DiskDump](my_modules/diskdump/), [FileDump](my_modules/filedump/))
|
||||||
+ An assortment of IBM PC and C1P machine XML files (in [/apps](apps/), [/devices](devices/) and elsewhere)
|
+ An assortment of IBM PC and C1P machine XML files (in [/apps](apps/), [/configs](configs/), [/disks](disks/) and elsewhere)
|
||||||
+ The [PCjs](my_modules/pcjs-client/lib/) and [C1Pjs](my_modules/c1pjs-client/lib/) client applications, both "compiled" and uncompiled
|
+ The [PCjs](my_modules/pcjs-client/lib/) and [C1Pjs](my_modules/c1pjs-client/lib/) client applications, both "compiled" and uncompiled
|
||||||
+ A smattering of [PCjs](docs/pcjs/) and [C1Pjs](docs/c1pjs/) documentation, along with [blog posts](blog/), related [publications](pubs/) and more
|
+ A smattering of [PCjs](docs/pcjs/) and [C1Pjs](docs/c1pjs/) documentation, along with [blog posts](blog/), related [publications](pubs/) and more
|
||||||
|
|
||||||
|
Aside from the [PCjs](my_modules/pcjs-client/lib/) and [C1Pjs](my_modules/c1pjs-client/lib/) applications,
|
||||||
|
[DiskDump](my_modules/diskdump/) is another important module. Originally created to dump existing disk images as JSON,
|
||||||
|
**DiskDump** has evolved into a full-featured disk image generator, capable of creating PC-compatible diskette *and*
|
||||||
|
hard disk images from either lists *or* directories of files (including all subdirectories), and supports both
|
||||||
|
command-line and web interfaces.
|
||||||
|
|
||||||
The PCjs web server is *not* required to run most PCjs simulations. Any web server (Node, Apache, Nginx, etc)
|
The PCjs web server is *not* required to run most PCjs simulations. Any web server (Node, Apache, Nginx, etc)
|
||||||
that can serve the necessary JavaScript files to your browser will work. However, instructions for doing
|
that can serve the necessary JavaScript files to your browser will work. However, instructions for doing
|
||||||
that are beyond the scope of this "Quick Start" document. And while it is possible to create simulations that
|
that are beyond the scope of this document (see future document). The PCjs web server does provide disk and file
|
||||||
require access to PCjs web server APIs, none of the simulations in the repository should require API access.
|
APIs that simulations can take advantage of, but none of the simulations currently checked into the repository
|
||||||
|
should require API access.
|
||||||
|
|
||||||
### Installing PCjs
|
### Installing PCjs
|
||||||
|
|
||||||
|
|
@ -242,23 +249,24 @@ A complete list of command-line options can be found in [server.js](server.js).
|
||||||
|
|
||||||
### Client Components
|
### Client Components
|
||||||
|
|
||||||
A special parameter ("gort") can be appended to the URL to request uncompiled client source files, making PCjs and
|
A special command parameter ("gort") can be appended to the URL to request uncompiled client source files, making PCjs
|
||||||
C1Pjs much easier to debug, albeit much slower:
|
and C1Pjs much easier to debug, albeit much slower:
|
||||||
|
|
||||||
http://localhost:8088/?gort=debug
|
http://localhost:8088/?gort=debug
|
||||||
|
|
||||||
The "gort=debug" command is unnecessary if the server is started with `--debug`; the server always serves uncompiled
|
The "gort=debug" command is unnecessary if the server is started with `--debug`; the server always serves uncompiled
|
||||||
files when running in "debug mode".
|
files when running in debug mode.
|
||||||
|
|
||||||
Conversely, if the server is running "debug mode" but you want to test a compiled version of PCjs, use:
|
Conversely, if the server is running debug mode but you want to test a compiled version of PCjs, use:
|
||||||
|
|
||||||
http://localhost:8088/?gort=release
|
http://localhost:8088/?gort=release
|
||||||
|
|
||||||
and the server will serve compiled JavaScript files, regardless whether the server is running in "debug mode" or
|
and the server will serve compiled JavaScript files, regardless whether the server is running in debug mode or
|
||||||
"release mode".
|
release mode.
|
||||||
|
|
||||||
Another useful gort command is "gort=nodebug", which is like "debug" but also sets the client-side **DEBUG** variable
|
Another useful gort command is "gort=nodebug", which is like "gort=debug" but also sets the client-side **DEBUG**
|
||||||
to *false*, disabling all debug-only runtime checks in the client and allowing the simulation to run much faster:
|
variable to *false*, disabling all debug-only runtime checks in the client and allowing the simulation to run much
|
||||||
|
faster:
|
||||||
|
|
||||||
http://localhost:8088/?gort=nodebug
|
http://localhost:8088/?gort=nodebug
|
||||||
|
|
||||||
|
|
@ -285,7 +293,9 @@ To start developing features for a new version of PCjs, here are the recommended
|
||||||
3. Make changes
|
3. Make changes
|
||||||
4. Run "grunt" to build new versions of the apps (eg, "/versions/pcjs/1.xx.yy/pc.js")
|
4. Run "grunt" to build new versions of the apps (eg, "/versions/pcjs/1.xx.yy/pc.js")
|
||||||
|
|
||||||
However, you may want to skip step #2 until you're ready to start testing the new version. Depending on the nature
|
You might also want to check out the blog post on [PCjs Coding Conventions](/blog/2014/09/30/).
|
||||||
|
|
||||||
|
You may also want to skip step #2 until you're ready to start testing the new version. Depending on the nature
|
||||||
of your changes, it may be better to manually edit the version number in only a few machine XML files for testing,
|
of your changes, it may be better to manually edit the version number in only a few machine XML files for testing,
|
||||||
leaving the rest of the XML files pointing to the previous version. Run "grunt promote" when the new version is much
|
leaving the rest of the XML files pointing to the previous version. Run "grunt promote" when the new version is much
|
||||||
closer to being released.
|
closer to being released.
|
||||||
|
|
@ -309,9 +319,22 @@ manually or with the Grunt "clean" task:
|
||||||
|
|
||||||
<!--END:EXCLUDE-->
|
<!--END:EXCLUDE-->
|
||||||
|
|
||||||
|
License
|
||||||
|
---
|
||||||
|
The [PCjs Project](https://github.com/jeffpar/pcjs) is now an open source project on [GitHub](http://github.com/).
|
||||||
|
All published portions are free for redistribution and/or modification under the terms of the
|
||||||
|
[GNU General Public License](/LICENSE) as published by the Free Software Foundation, either version 3 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
You are required to include the appropriate copyright notice (e.g., `PCjs v1.15.4 © 2012-2014 by @jeffpar`)
|
||||||
|
in every source code file of every copy or modified version of this work, and to display that copyright notice
|
||||||
|
on every screen that loads or runs any version of this software.
|
||||||
|
|
||||||
|
See [LICENSE](/LICENSE) for details.
|
||||||
|
|
||||||
More Information
|
More Information
|
||||||
---
|
---
|
||||||
Learn more about the [JavaScript Machines](/docs/about/) project and [PCjs](/docs/about/pcjs/). To
|
Learn more about the [JavaScript Machines](/docs/about/) Project and [PCjs](/docs/about/pcjs/). To
|
||||||
create your own PCjs machines, see the [Documentation](/docs/pcjs/) for details.
|
create your own PCjs machines, see the [Documentation](/docs/pcjs/) for details.
|
||||||
|
|
||||||
If you have questions or run into any problems, you're welcome to [tweet](http://twitter.com/jeffpar) or
|
If you have questions or run into any problems, you're welcome to [tweet](http://twitter.com/jeffpar) or
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
PCjs Coding Conventions
|
PCjs Coding Conventions
|
||||||
---
|
---
|
||||||
|
|
||||||
Some ramblings about the JavaScript coding conventions used for PCjs. This is not an attempt to convince anyone of
|
Here are a few highlights of the (evolving) JavaScript coding conventions used in PCjs.
|
||||||
anything, just an explanation of why things are the way they are.
|
|
||||||
|
|
||||||
### Tabs vs. Spaces
|
### Tabs vs. Spaces
|
||||||
|
|
||||||
|
|
@ -79,6 +78,33 @@ uses the "long form." But again, since the Closure Compiler already does a good
|
||||||
necessary to use the "long form", which is why you'll see newer code using more conventional Object notation to
|
necessary to use the "long form", which is why you'll see newer code using more conventional Object notation to
|
||||||
define class constants.
|
define class constants.
|
||||||
|
|
||||||
|
### DEBUG vs. RELEASE
|
||||||
|
|
||||||
|
While we're talking about constants, it's important to be aware of constants that are not scoped to
|
||||||
|
any particular component.
|
||||||
|
|
||||||
|
In [/my_modules/shared/lib/defines.js](/my_modules/shared/lib/defines.js), **DEBUG** is set to **TRUE**,
|
||||||
|
enabling all debug-only code by default. It is also declared as a *@define* so that the Closure Compiler can
|
||||||
|
override it, setting it to **FALSE** and disabling debug-only code.
|
||||||
|
|
||||||
|
To ensure that debug-only code is not simply *disabled* but also *removed*, the code should be wrapped with:
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
[code to be removed by the Closure Compiler]
|
||||||
|
}
|
||||||
|
|
||||||
|
In many cases, the compiler is able to completely remove calls to debug-only class methods; eg:
|
||||||
|
|
||||||
|
Component.assert(off >= 0 && off < this.cb);
|
||||||
|
|
||||||
|
However, calls to debug-only instance methods seem to be more problematic, so all such calls are wrapped; eg:
|
||||||
|
|
||||||
|
if (DEBUG) this.log('load("' + sFileURL + '")');
|
||||||
|
|
||||||
|
There are a number of other important shared constants in [/my_modules/shared/lib/defines.js](/my_modules/shared/lib/defines.js)
|
||||||
|
and PCjs-specific constants in [/my_modules/pcjs-client/lib/defines.js](/my_modules/pcjs-client/lib/defines.js); refer
|
||||||
|
to those files for more information.
|
||||||
|
|
||||||
### Braces and Parentheses
|
### Braces and Parentheses
|
||||||
|
|
||||||
Most opening braces appear at the end of the line containing the associated "if", "while", "for", "switch",
|
Most opening braces appear at the end of the line containing the associated "if", "while", "for", "switch",
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
About JavaScript Machines
|
About JavaScript Machines
|
||||||
---
|
---
|
||||||
|
|
||||||
The JavaScript Machines (**JSMachines**) project is a collection of computer simulations written in JavaScript,
|
The JavaScript Machines Project (originally at [jsmachines.net](http://jsmachines.net/)) is a collection of computer
|
||||||
maintained on [GitHub](http://github.com/), and hosted at [pcjs.org](http://www.pcjs.org/) (formerly
|
simulations written in JavaScript. It has now been released on [GitHub](https://github.com/) as the
|
||||||
[jsmachines.net](http://jsmachines.net/)).
|
[PCjs Project](https://github.com/jeffpar/pcjs), a copy of which is hosted here at [pcjs.org](http://www.pcjs.org/).
|
||||||
|
|
||||||
The goals of the project are to create fast, full-featured simulations of classic computer
|
The goals of the project are to create fast, full-featured simulations of classic computer
|
||||||
hardware, help people understand how these early machines worked, make it easy to experiment with different machine
|
hardware, help people understand how these early machines worked, make it easy to experiment with different machine
|
||||||
|
|
@ -18,7 +18,7 @@ capabilities can be found in the [Documentation](/docs/).
|
||||||
|
|
||||||
### Emulating the Challenger 1P
|
### Emulating the Challenger 1P
|
||||||
|
|
||||||
The first **JSMachines** application was [C1Pjs](/docs/c1pjs/), a simulation of the
|
The first **JSMachines** simulation was [C1Pjs](/docs/c1pjs/), a simulation of the
|
||||||
Challenger 1P, which was a 6502-based microcomputer introduced by Ohio Scientific in 1978.
|
Challenger 1P, which was a 6502-based microcomputer introduced by Ohio Scientific in 1978.
|
||||||
|
|
||||||
C1Pjs v1.0 was released in July 2012, first on ecpsim.org and cpusim.org, then on [jsmachines.net](http://jsmachines.net/c1pjs),
|
C1Pjs v1.0 was released in July 2012, first on ecpsim.org and cpusim.org, then on [jsmachines.net](http://jsmachines.net/c1pjs),
|
||||||
|
|
@ -30,16 +30,17 @@ at [osiweb.org](http://osiweb.org/).
|
||||||
|
|
||||||
### Emulating the IBM PC
|
### Emulating the IBM PC
|
||||||
|
|
||||||
The next **JSMachines** application was [PCjs](/docs/about/pcjs/), which simulates the original IBM PC and IBM PC XT.
|
The next **JSMachines** simulation was [PCjs](/docs/about/pcjs/), which simulates the original IBM PC, IBM PC XT,
|
||||||
|
and IBM PC AT.
|
||||||
|
|
||||||
[PCjs](/docs/about/pcjs/) emulates the Intel 8088 CPU, as well as IBM Monochrome Display Adapter (MDA) and
|
[PCjs](/docs/about/pcjs/) emulates the Intel 8088 and 80286 CPUs, as well as IBM Monochrome Display Adapter (MDA),
|
||||||
Color Display Adapter (CGA) video cards, along with assorted motherboard and expansion bus components. It also
|
Color Graphics Adapter (CGA), and Enhanced Graphics Adapter (EGA) video cards, along with assorted motherboard and
|
||||||
includes an optional debugger and a user-configurable control panel.
|
expansion bus components. It also includes an optional Debugger and a user-configurable Control Panel.
|
||||||
|
|
||||||
PCjs v1.0 was released on [jsmachines.net](http://jsmachines.net/) in late 2012, and the **JSMachines** project,
|
PCjs v1.0 was released on [jsmachines.net](http://jsmachines.net/) in late 2012, and the **JSMachines** project,
|
||||||
with its second full-featured machine emulation, was launched.
|
with its second full-featured machine emulation, was launched.
|
||||||
|
|
||||||
See the PCjs [History](/docs/about/pcjs/) for information about more recent releases.
|
Read [About PCjs](/docs/about/pcjs/) to learn more about its history, features, and upcoming improvements.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -61,22 +62,20 @@ including extensions to the link syntax that make it easy to embed C1Pjs and PCj
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### License
|
License
|
||||||
|
---
|
||||||
The **JSMachines** project is maintained on [GitHub](http://github.com/) (public release date TBD). The portions
|
The [PCjs Project](https://github.com/jeffpar/pcjs) is now an open source project on [GitHub](http://github.com/).
|
||||||
of the project that have been published here are free for redistribution and/or modification under the terms
|
All published portions are free for redistribution and/or modification under the terms of the
|
||||||
of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
|
[GNU General Public License](/LICENSE) as published by the Free Software Foundation, either version 3 of the License,
|
||||||
or (at your option) any later version.
|
or (at your option) any later version.
|
||||||
|
|
||||||
You are required to include the appropriate copyright notice (e.g., `PCjs v1.15.3 © 2012-2014 by @jeffpar`)
|
You are required to include the appropriate copyright notice (e.g., `PCjs v1.15.4 © 2012-2014 by @jeffpar`)
|
||||||
in every source code file of every copy or modified version of this work, and to display that copyright notice
|
in every source code file of every copy or modified version of this work, and to display that copyright notice
|
||||||
on every screen that loads or runs any version of this software.
|
on every screen that loads or runs any version of this software.
|
||||||
|
|
||||||
See [LICENSE](/LICENSE) for details.
|
See [LICENSE](/LICENSE) for details.
|
||||||
|
|
||||||
|
More Information
|
||||||
---
|
---
|
||||||
|
|
||||||
### More Information
|
|
||||||
|
|
||||||
If you have questions or run into any problems, you're welcome to [tweet](http://twitter.com/jeffpar) or
|
If you have questions or run into any problems, you're welcome to [tweet](http://twitter.com/jeffpar) or
|
||||||
[email](mailto:Jeff@pcjs.org).
|
[email](mailto:Jeff@pcjs.org).
|
||||||
|
|
@ -2,7 +2,8 @@ About PCjs
|
||||||
---
|
---
|
||||||
|
|
||||||
PCjs is a IBM PC and PC XT simulator written entirely in JavaScript. It's designed to load and run extremely
|
PCjs is a IBM PC and PC XT simulator written entirely in JavaScript. It's designed to load and run extremely
|
||||||
fast, it works well in all modern web browsers (both desktop and mobile), and it's easy to customize.
|
fast, it works well in all modern web browsers (both desktop and mobile), and it's easy to customize. It is part of
|
||||||
|
the [PCjs Project](https://github.com/jeffpar/pcjs), an open source project on [GitHub](http://github.com/).
|
||||||
|
|
||||||
Check out the [Demos](/#demos) on the home page, and all the other PCjs [Application](/apps/pc/), [Boot Disk](/disks/pc/)
|
Check out the [Demos](/#demos) on the home page, and all the other PCjs [Application](/apps/pc/), [Boot Disk](/disks/pc/)
|
||||||
and [Machine](/configs/pc/machines/) demos, including an IBM PC XT "[Server Array](/configs/pc/machines/5160/cga/256kb/array/)"
|
and [Machine](/configs/pc/machines/) demos, including an IBM PC XT "[Server Array](/configs/pc/machines/5160/cga/256kb/array/)"
|
||||||
|
|
@ -36,18 +37,19 @@ Chrome or Firefox for other platforms.
|
||||||
|
|
||||||
### Future
|
### Future
|
||||||
|
|
||||||
More hardware suport is targeted for version 1.20.0, including:
|
More hardware support is targeted for version 1.15, including:
|
||||||
|
|
||||||
+ Complete EGA emulation
|
+ Complete EGA emulation
|
||||||
+ 80286 CPU emulation
|
+ 80286 CPU emulation
|
||||||
+ PC AT hardware emulation
|
+ PC AT hardware emulation
|
||||||
|
|
||||||
Limited EGA emulation is currently available as of version 1.14.0.
|
Limited EGA emulation is currently available as of version 1.14.
|
||||||
|
|
||||||
### History
|
### History
|
||||||
|
|
||||||
+ v1.14.0 introduced limited EGA emulation, as discussed on our [Blog](/blog/2014/07/30/).
|
+ v1.15 introduced PC AT (Model 5170) emulation, as discussed on our [Blog](/blog/2014/09/13/).
|
||||||
+ v1.13.0 introduced manifest files that describe software packages that can be used with PCjs.
|
+ v1.14 introduced limited EGA emulation, as discussed on our [Blog](/blog/2014/07/30/).
|
||||||
|
+ v1.13 introduced manifest files that describe software packages that can be used with PCjs.
|
||||||
More information on software manifests is available [here](/apps/).
|
More information on software manifests is available [here](/apps/).
|
||||||
+ v1.12.1 coincided with the first release of the new PCjs web server running on [Node.js](http://nodejs.org).
|
+ v1.12.1 coincided with the first release of the new PCjs web server running on [Node.js](http://nodejs.org).
|
||||||
The new server includes ROM and disk image conversion APIs, as well as a [Markdown](http://daringfireball.net/projects/markdown/syntax)
|
The new server includes ROM and disk image conversion APIs, as well as a [Markdown](http://daringfireball.net/projects/markdown/syntax)
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
|
@ -270,6 +270,29 @@ C1PComputer.init = function()
|
||||||
|
|
||||||
var component;
|
var component;
|
||||||
var modules = {};
|
var modules = {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let's see if the Control Panel is installed (NOTE: its ID must be "panel", and only one per machine is supported);
|
||||||
|
* the Panel needs our setPower() notifications, and this relieves us from having an explicit <module> entry for type="panel".
|
||||||
|
*/
|
||||||
|
var panel = Component.getComponentByID('panel', parmsComputer['id']);
|
||||||
|
if (panel) {
|
||||||
|
modules['panel'] = [panel];
|
||||||
|
/*
|
||||||
|
* Iterate through all the other components and update their print methods if the Control Panel has provided overrides.
|
||||||
|
*/
|
||||||
|
if (panel.controlPrint) {
|
||||||
|
var aComponents = Component.getComponents(parmsComputer['id']);
|
||||||
|
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
|
||||||
|
component = aComponents[iComponent];
|
||||||
|
if (component == panel) continue;
|
||||||
|
component.notice = panel.notice;
|
||||||
|
component.println = panel.println;
|
||||||
|
component.controlPrint = panel.controlPrint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var abMemory;
|
var abMemory;
|
||||||
var addrStart = 0, addrEnd = 0;
|
var addrStart = 0, addrEnd = 0;
|
||||||
|
|
||||||
|
|
@ -326,15 +349,6 @@ C1PComputer.init = function()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Let's see if the Control Panel is installed (NOTE: its ID must be "panel", and only one per machine is supported);
|
|
||||||
* the Panel needs our setPower() notifications, and this relieves us from having an explicit <module> entry for type="panel".
|
|
||||||
*/
|
|
||||||
component = Component.getComponentByID('panel', parmsComputer['id']);
|
|
||||||
if (component) {
|
|
||||||
modules['panel'] = [component];
|
|
||||||
}
|
|
||||||
|
|
||||||
var computer = new C1PComputer(parmsComputer, modules);
|
var computer = new C1PComputer(parmsComputer, modules);
|
||||||
/*
|
/*
|
||||||
* We may eventually add a "Power" button, but for now, all we have is a "Reset" button
|
* We may eventually add a "Power" button, but for now, all we have is a "Reset" button
|
||||||
|
|
|
||||||
|
|
@ -809,7 +809,7 @@ C1PDiskController.prototype.loadDisk = function(sDiskName, sDiskData, nErrorCode
|
||||||
* to its trackNum index, but just in case that wasn't intended, we're going to mention it.
|
* to its trackNum index, but just in case that wasn't intended, we're going to mention it.
|
||||||
*/
|
*/
|
||||||
if (iTrackNum != iTrack) {
|
if (iTrackNum != iTrack) {
|
||||||
this.warning("track " + iTrackNum + " out of order (expected " + iTrack + ")");
|
Component.warning("track " + iTrackNum + " out of order (expected " + iTrack + ")");
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* For each track, we start with an empty trackData array and "push" (ie, append) all the
|
* For each track, we start with an empty trackData array and "push" (ie, append) all the
|
||||||
|
|
|
||||||
|
|
@ -56,19 +56,19 @@ Component.subclass(Component, C1PPanel);
|
||||||
* component that doesn't recognize the specified binding should simply ignore it.
|
* component that doesn't recognize the specified binding should simply ignore it.
|
||||||
*
|
*
|
||||||
* @this {C1PPanel}
|
* @this {C1PPanel}
|
||||||
* @param {string|null} c is the class of the HTML control (eg, "input", "output")
|
* @param {string|null} sHTMLClass is the class of the HTML control (eg, "input", "output")
|
||||||
* @param {string|null} t is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea")
|
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
|
||||||
* @param {string} s is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "reset")
|
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "reset")
|
||||||
* @param {Object} e is the HTML control DOM object (eg, HTMLButtonElement)
|
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
|
||||||
* @return {boolean} true if binding was successful, false if unrecognized binding request
|
* @return {boolean} true if binding was successful, false if unrecognized binding request
|
||||||
*/
|
*/
|
||||||
C1PPanel.prototype.setBinding = function(c, t, s, e)
|
C1PPanel.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, control)
|
||||||
{
|
{
|
||||||
if (this.cmp && this.cmp.setBinding(c, t, s, e)) return true;
|
if (this.cmp && this.cmp.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
||||||
if (this.cpu && this.cpu.setBinding(c, t, s, e)) return true;
|
if (this.cpu && this.cpu.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
||||||
if (this.kbd && this.kbd.setBinding(c, t, s, e)) return true;
|
if (this.kbd && this.kbd.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
||||||
if (DEBUGGER && this.dbg && this.dbg.setBinding(c, t, s, e)) return true;
|
if (DEBUGGER && this.dbg && this.dbg.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
||||||
return Component.prototype.setBinding.call(this, c, t, s, e);
|
return Component.prototype.setBinding.call(this, sHTMLClass, sHTMLType, sBinding, control);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -732,6 +732,7 @@ DiskDump.readFile = function(sPath, sEncoding, done)
|
||||||
/**
|
/**
|
||||||
* isExcluded(sName)
|
* isExcluded(sName)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {string} sName is the basename of a file under consideration
|
* @param {string} sName is the basename of a file under consideration
|
||||||
* @return {boolean} is true if the file should be excluded, false if not
|
* @return {boolean} is true if the file should be excluded, false if not
|
||||||
*/
|
*/
|
||||||
|
|
@ -752,6 +753,7 @@ DiskDump.prototype.isExcluded = function(sName)
|
||||||
* object creation from any I/O that the object may perform, to ensure that a callback can never
|
* object creation from any I/O that the object may perform, to ensure that a callback can never
|
||||||
* be called before the caller has actually received the newly created object.
|
* be called before the caller has actually received the newly created object.
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {function(Error)} done
|
* @param {function(Error)} done
|
||||||
*/
|
*/
|
||||||
DiskDump.prototype.loadFile = function(done)
|
DiskDump.prototype.loadFile = function(done)
|
||||||
|
|
@ -774,6 +776,7 @@ DiskDump.prototype.loadFile = function(done)
|
||||||
*
|
*
|
||||||
* Records the loaded disk data buffer
|
* Records the loaded disk data buffer
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Error} err
|
* @param {Error} err
|
||||||
* @param {Buffer|string} buf
|
* @param {Buffer|string} buf
|
||||||
* @param {function(Error)} done
|
* @param {function(Error)} done
|
||||||
|
|
@ -818,6 +821,7 @@ DiskDump.prototype.setData = function(err, buf, done)
|
||||||
/**
|
/**
|
||||||
* dumpLine(nIndent, sLine, sComment)
|
* dumpLine(nIndent, sLine, sComment)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {number} [nIndent] is the relative number of characters to indent the given line (0 if none)
|
* @param {number} [nIndent] is the relative number of characters to indent the given line (0 if none)
|
||||||
* @param {string} [sLine] is the given line
|
* @param {string} [sLine] is the given line
|
||||||
* @param {string} [sComment] is an optional comment to append to the line, if comment output is enabled
|
* @param {string} [sComment] is an optional comment to append to the line, if comment output is enabled
|
||||||
|
|
@ -840,6 +844,7 @@ DiskDump.prototype.dumpLine = function(nIndent, sLine, sComment)
|
||||||
/**
|
/**
|
||||||
* dumpProp(sKey, value, fLast)
|
* dumpProp(sKey, value, fLast)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {string} sKey
|
* @param {string} sKey
|
||||||
* @param {number|string|null} value
|
* @param {number|string|null} value
|
||||||
* @param {boolean} [fLast]
|
* @param {boolean} [fLast]
|
||||||
|
|
@ -857,6 +862,7 @@ DiskDump.prototype.dumpProp = function(sKey, value, fLast)
|
||||||
/**
|
/**
|
||||||
* dumpBuffer(sKey, buf, len, cbItem, offData)
|
* dumpBuffer(sKey, buf, len, cbItem, offData)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {string|null} sKey is name of buffer data element
|
* @param {string|null} sKey is name of buffer data element
|
||||||
* @param {Buffer} buf is a Buffer containing the bytes to dump
|
* @param {Buffer} buf is a Buffer containing the bytes to dump
|
||||||
* @param {number} len is the number of bytes to dump
|
* @param {number} len is the number of bytes to dump
|
||||||
|
|
@ -908,6 +914,7 @@ DiskDump.prototype.dumpBuffer = function(sKey, buf, len, cbItem, offData)
|
||||||
*
|
*
|
||||||
* Dumps track data for an OSI disk track
|
* Dumps track data for an OSI disk track
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {string} sTrackSig
|
* @param {string} sTrackSig
|
||||||
* @param {number} nTrackNum
|
* @param {number} nTrackNum
|
||||||
* @param {number} nTrackType
|
* @param {number} nTrackType
|
||||||
|
|
@ -932,6 +939,7 @@ DiskDump.prototype.dumpTrackOSI = function(sTrackSig, nTrackNum, nTrackType, nTr
|
||||||
*
|
*
|
||||||
* Dumps sector data for an OSI disk sector
|
* Dumps sector data for an OSI disk sector
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {number|null} nSectorSig
|
* @param {number|null} nSectorSig
|
||||||
* @param {number} nSectorNum
|
* @param {number} nSectorNum
|
||||||
* @param {number} nSectorPages
|
* @param {number} nSectorPages
|
||||||
|
|
@ -968,6 +976,7 @@ DiskDump.prototype.dumpSectorOSI = function(nSectorSig, nSectorNum, nSectorPages
|
||||||
* NOTE: The C1Pjs Simulator doesn't support this feature (yet), which is why
|
* NOTE: The C1Pjs Simulator doesn't support this feature (yet), which is why
|
||||||
* trimSector() isn't used when dumping OSI disk images.
|
* trimSector() isn't used when dumping OSI disk images.
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Buffer} buf
|
* @param {Buffer} buf
|
||||||
* @param {number} len
|
* @param {number} len
|
||||||
* @return {Array} containing [dwPattern, cbBuffer]
|
* @return {Array} containing [dwPattern, cbBuffer]
|
||||||
|
|
@ -1019,6 +1028,7 @@ DiskDump.ATTR_ARCHIVE = 0x20;
|
||||||
/**
|
/**
|
||||||
* validateTime(dateTime)
|
* validateTime(dateTime)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Date} dateTime
|
* @param {Date} dateTime
|
||||||
* @return {boolean} true if date/time modified, false if not
|
* @return {boolean} true if date/time modified, false if not
|
||||||
*/
|
*/
|
||||||
|
|
@ -1062,6 +1072,7 @@ DiskDump.prototype.validateTime = function(dateTime)
|
||||||
/**
|
/**
|
||||||
* buildData(cb)
|
* buildData(cb)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {number} cb
|
* @param {number} cb
|
||||||
* @param {Array.<number>} [abInit]
|
* @param {Array.<number>} [abInit]
|
||||||
* @return {Array.<number>} of bytes zero-initialized
|
* @return {Array.<number>} of bytes zero-initialized
|
||||||
|
|
@ -1078,6 +1089,7 @@ DiskDump.prototype.buildData = function(cb, abInit)
|
||||||
/**
|
/**
|
||||||
* copyData(ab)
|
* copyData(ab)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {number} offDisk
|
* @param {number} offDisk
|
||||||
* @param {Array.<number>} ab
|
* @param {Array.<number>} ab
|
||||||
* @return {number} number of bytes written
|
* @return {number} number of bytes written
|
||||||
|
|
@ -1092,6 +1104,7 @@ DiskDump.prototype.copyData = function(offDisk, ab)
|
||||||
/**
|
/**
|
||||||
* addManifestInfo(fileInfo)
|
* addManifestInfo(fileInfo)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Object} fileInfo
|
* @param {Object} fileInfo
|
||||||
*/
|
*/
|
||||||
DiskDump.prototype.addManifestInfo = function(fileInfo)
|
DiskDump.prototype.addManifestInfo = function(fileInfo)
|
||||||
|
|
@ -1105,6 +1118,7 @@ DiskDump.prototype.addManifestInfo = function(fileInfo)
|
||||||
* Returns an array (aFiles) via the done() callback, where each entry is a fileInfo object.
|
* Returns an array (aFiles) via the done() callback, where each entry is a fileInfo object.
|
||||||
* If fileInfo refers to a subdirectory, then FILE_SIZE is -1 and FILE_DATA entry is another aFiles array.
|
* If fileInfo refers to a subdirectory, then FILE_SIZE is -1 and FILE_DATA entry is another aFiles array.
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {string} sDir is a fully-qualified directory name
|
* @param {string} sDir is a fully-qualified directory name
|
||||||
* @param {boolean} [fRoot] should be true for the first directory read
|
* @param {boolean} [fRoot] should be true for the first directory read
|
||||||
* @param {function(Error,Array)} done
|
* @param {function(Error,Array)} done
|
||||||
|
|
@ -1234,6 +1248,7 @@ DiskDump.prototype.readDir = function(sDir, fRoot, done)
|
||||||
* NOTE: sPath begins fully-qualified (see this.sDiskPath), but if any of the intermediate entries contains paths,
|
* NOTE: sPath begins fully-qualified (see this.sDiskPath), but if any of the intermediate entries contains paths,
|
||||||
* it's our responsibility to join them with sServerRoot.
|
* it's our responsibility to join them with sServerRoot.
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {string} sPath contains series of semi-colon-separated files (local or remote)
|
* @param {string} sPath contains series of semi-colon-separated files (local or remote)
|
||||||
* @param {function(Error,Array)} done
|
* @param {function(Error,Array)} done
|
||||||
*/
|
*/
|
||||||
|
|
@ -1356,6 +1371,7 @@ DiskDump.prototype.readPath = function(sPath, done)
|
||||||
/**
|
/**
|
||||||
* buildName(sFile)
|
* buildName(sFile)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {string} sFile is the basename of a file
|
* @param {string} sFile is the basename of a file
|
||||||
* @return {string} containing a corresponding FAT-compatible filename
|
* @return {string} containing a corresponding FAT-compatible filename
|
||||||
*/
|
*/
|
||||||
|
|
@ -1391,6 +1407,7 @@ DiskDump.prototype.buildName = function(sFile)
|
||||||
* NOTE: When fileInfo is returned, there will be no FILE_PATH property, which means
|
* NOTE: When fileInfo is returned, there will be no FILE_PATH property, which means
|
||||||
* don't go looking for a corresponding entry in the host file system, because there isn't one.
|
* don't go looking for a corresponding entry in the host file system, because there isn't one.
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {string} [sDir]
|
* @param {string} [sDir]
|
||||||
* @return {Object|null} fileInfo (or null if no suitable volume label)
|
* @return {Object|null} fileInfo (or null if no suitable volume label)
|
||||||
*/
|
*/
|
||||||
|
|
@ -1433,6 +1450,7 @@ DiskDump.prototype.buildVolLabel = function(sDir)
|
||||||
/**
|
/**
|
||||||
* buildFAT(abFAT, aFiles, iCluster, cbCluster)
|
* buildFAT(abFAT, aFiles, iCluster, cbCluster)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Array.<number>} abFAT
|
* @param {Array.<number>} abFAT
|
||||||
* @param {Array} aFiles
|
* @param {Array} aFiles
|
||||||
* @param {number} iCluster
|
* @param {number} iCluster
|
||||||
|
|
@ -1476,6 +1494,7 @@ DiskDump.prototype.buildFAT = function(abFAT, aFiles, iCluster, cbCluster)
|
||||||
/**
|
/**
|
||||||
* buildFATEntry(abFat, iFat, v)
|
* buildFATEntry(abFat, iFat, v)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Array.<number>} abFAT
|
* @param {Array.<number>} abFAT
|
||||||
* @param {number} iFAT
|
* @param {number} iFAT
|
||||||
* @param {number} v
|
* @param {number} v
|
||||||
|
|
@ -1501,6 +1520,7 @@ DiskDump.prototype.buildFATEntry = function(abFAT, iFAT, v)
|
||||||
/**
|
/**
|
||||||
* buildDir(abDir, aFiles, dateMod, iCluster, iParentCluster)
|
* buildDir(abDir, aFiles, dateMod, iCluster, iParentCluster)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Array.<number>} abDir
|
* @param {Array.<number>} abDir
|
||||||
* @param {Array} aFiles
|
* @param {Array} aFiles
|
||||||
* @param {Date} [dateMod]
|
* @param {Date} [dateMod]
|
||||||
|
|
@ -1537,6 +1557,7 @@ DiskDump.prototype.buildDir = function(abDir, aFiles, dateMod, iCluster, iParent
|
||||||
*
|
*
|
||||||
* TODO: Create constants that define the various directory entry fields, including the overall size (32 bytes).
|
* TODO: Create constants that define the various directory entry fields, including the overall size (32 bytes).
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Array.<number>} ab contains the bytes of a directory
|
* @param {Array.<number>} ab contains the bytes of a directory
|
||||||
* @param {number} off is the offset within ab to build the next directory entry
|
* @param {number} off is the offset within ab to build the next directory entry
|
||||||
* @param {string} sFile is the file name
|
* @param {string} sFile is the file name
|
||||||
|
|
@ -1621,6 +1642,7 @@ DiskDump.prototype.buildDirEntry = function(ab, off, sFile, cbFile, bAttr, dateM
|
||||||
/**
|
/**
|
||||||
* buildClusters(aFiles, offDisk, cbCluster, iParentCluster, done)
|
* buildClusters(aFiles, offDisk, cbCluster, iParentCluster, done)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Array} aFiles
|
* @param {Array} aFiles
|
||||||
* @param {number} offDisk
|
* @param {number} offDisk
|
||||||
* @param {number} cbCluster
|
* @param {number} cbCluster
|
||||||
|
|
@ -1706,6 +1728,7 @@ DiskDump.prototype.buildClusters = function(aFiles, offDisk, cbCluster, iParentC
|
||||||
/**
|
/**
|
||||||
* buildImage()
|
* buildImage()
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {boolean} fDir
|
* @param {boolean} fDir
|
||||||
* @param {function(Error)} done
|
* @param {function(Error)} done
|
||||||
*/
|
*/
|
||||||
|
|
@ -1740,6 +1763,7 @@ DiskDump.prototype.buildImage = function(fDir, done)
|
||||||
* calculated total data and found a BPB we think will accommodate it. So, the code below
|
* calculated total data and found a BPB we think will accommodate it. So, the code below
|
||||||
* will still have to be prepared for running out of disk space. This is just a good estimate.
|
* will still have to be prepared for running out of disk space. This is just a good estimate.
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Array} aFiles
|
* @param {Array} aFiles
|
||||||
* @return {number} of bytes required for all files, including all subdirectories
|
* @return {number} of bytes required for all files, including all subdirectories
|
||||||
*/
|
*/
|
||||||
|
|
@ -1765,6 +1789,7 @@ DiskDump.prototype.calcFileSizes = function(aFiles)
|
||||||
/**
|
/**
|
||||||
* buildMBR(cHeads, cSectorsPerTrack, cbSector, cTotalSectors)
|
* buildMBR(cHeads, cSectorsPerTrack, cbSector, cTotalSectors)
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {number} cHeads
|
* @param {number} cHeads
|
||||||
* @param {number} cSectorsPerTrack
|
* @param {number} cSectorsPerTrack
|
||||||
* @param {number} cbSector
|
* @param {number} cbSector
|
||||||
|
|
@ -1835,6 +1860,7 @@ DiskDump.prototype.buildMBR = function(cHeads, cSectorsPerTrack, cbSector, cTota
|
||||||
* Note, however, that even if this function returns true, you won't receive the buffer until
|
* Note, however, that even if this function returns true, you won't receive the buffer until
|
||||||
* all the writes to have it have finished.
|
* all the writes to have it have finished.
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @param {Array} aFiles
|
* @param {Array} aFiles
|
||||||
* @param {function(Error)} done
|
* @param {function(Error)} done
|
||||||
* @return {boolean} true if disk allocation successful, false if not
|
* @return {boolean} true if disk allocation successful, false if not
|
||||||
|
|
@ -1996,6 +2022,7 @@ DiskDump.prototype.buildImageFromFiles = function(aFiles, done)
|
||||||
*
|
*
|
||||||
* Converts the disk image data to JSON.
|
* Converts the disk image data to JSON.
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @return {string|null} containing a JSON representation of the disk image, or null if unrecognized/malformed
|
* @return {string|null} containing a JSON representation of the disk image, or null if unrecognized/malformed
|
||||||
*/
|
*/
|
||||||
DiskDump.prototype.convertToJSON = function()
|
DiskDump.prototype.convertToJSON = function()
|
||||||
|
|
@ -2288,6 +2315,7 @@ DiskDump.prototype.convertToJSON = function()
|
||||||
* each containing an array of tracks. It's largely just a matter of reversing the meaning of the two outermost array
|
* each containing an array of tracks. It's largely just a matter of reversing the meaning of the two outermost array
|
||||||
* elements, here and in the C1Pjs disk module.
|
* elements, here and in the C1Pjs disk module.
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @return {string|null} containing a JSON representation of the disk image, or null if unrecognized/malformed
|
* @return {string|null} containing a JSON representation of the disk image, or null if unrecognized/malformed
|
||||||
*/
|
*/
|
||||||
DiskDump.prototype.convertOSIDiskToJSON = function()
|
DiskDump.prototype.convertOSIDiskToJSON = function()
|
||||||
|
|
@ -2406,6 +2434,7 @@ DiskDump.prototype.convertOSIDiskToJSON = function()
|
||||||
* TODO: Consider creating a caching mechanism for these requests (ie, stash a limited number of these
|
* TODO: Consider creating a caching mechanism for these requests (ie, stash a limited number of these
|
||||||
* disk images under /tmp, using a name based on a hash of the source path).
|
* disk images under /tmp, using a name based on a hash of the source path).
|
||||||
*
|
*
|
||||||
|
* @this {DiskDump}
|
||||||
* @return {Buffer|null} containing the disk image's raw data, or null if no data available (or parse error)
|
* @return {Buffer|null} containing the disk image's raw data, or null if no data available (or parse error)
|
||||||
*/
|
*/
|
||||||
DiskDump.prototype.convertToIMG = function()
|
DiskDump.prototype.convertToIMG = function()
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,7 @@ FileDump.validateFormat = function(sFormat)
|
||||||
* object creation from any I/O that the object may perform, to ensure that a callback can never
|
* object creation from any I/O that the object may perform, to ensure that a callback can never
|
||||||
* be called before the caller has actually received the newly created object.
|
* be called before the caller has actually received the newly created object.
|
||||||
*
|
*
|
||||||
|
* @this {FileDump}
|
||||||
* @param {string} sFile
|
* @param {string} sFile
|
||||||
* @param {number} iStart
|
* @param {number} iStart
|
||||||
* @param {number} nSkip
|
* @param {number} nSkip
|
||||||
|
|
@ -273,6 +274,7 @@ FileDump.prototype.loadFile = function(sFile, iStart, nSkip, done)
|
||||||
*
|
*
|
||||||
* Records the given file data in the FileDump's buffer
|
* Records the given file data in the FileDump's buffer
|
||||||
*
|
*
|
||||||
|
* @this {FileDump}
|
||||||
* @param {Buffer} buf
|
* @param {Buffer} buf
|
||||||
* @param {number} iStart
|
* @param {number} iStart
|
||||||
* @param {number} nSkip
|
* @param {number} nSkip
|
||||||
|
|
@ -299,6 +301,7 @@ FileDump.prototype.setData = function(buf, iStart, nSkip)
|
||||||
/**
|
/**
|
||||||
* dumpLine(nIndent, sLine, sComment)
|
* dumpLine(nIndent, sLine, sComment)
|
||||||
*
|
*
|
||||||
|
* @this {FileDump}
|
||||||
* @param {number} [nIndent] is the relative number of characters to indent the given line (0 if none)
|
* @param {number} [nIndent] is the relative number of characters to indent the given line (0 if none)
|
||||||
* @param {string} [sLine] is the given line
|
* @param {string} [sLine] is the given line
|
||||||
* @param {string} [sComment] is an optional comment to append to the line, if comment output is enabled
|
* @param {string} [sComment] is an optional comment to append to the line, if comment output is enabled
|
||||||
|
|
@ -322,6 +325,7 @@ FileDump.prototype.dumpLine = function(nIndent, sLine, sComment)
|
||||||
/**
|
/**
|
||||||
* dumpBuffer(sKey, buf, len, cbItem, offData)
|
* dumpBuffer(sKey, buf, len, cbItem, offData)
|
||||||
*
|
*
|
||||||
|
* @this {FileDump}
|
||||||
* @param {string|null} sKey is name of buffer data element
|
* @param {string|null} sKey is name of buffer data element
|
||||||
* @param {Buffer} buf is a Buffer containing the bytes to dump
|
* @param {Buffer} buf is a Buffer containing the bytes to dump
|
||||||
* @param {number} len is the number of bytes to dump
|
* @param {number} len is the number of bytes to dump
|
||||||
|
|
@ -385,6 +389,7 @@ FileDump.prototype.dumpBuffer = function(sKey, buf, len, cbItem, offData)
|
||||||
*
|
*
|
||||||
* NOTE: Since ".map" files are an internal construct, I support only local map files (for now)
|
* NOTE: Since ".map" files are an internal construct, I support only local map files (for now)
|
||||||
*
|
*
|
||||||
|
* @this {FileDump}
|
||||||
* @param {string} sFilePath
|
* @param {string} sFilePath
|
||||||
* @param {function(Error,string)} done
|
* @param {function(Error,string)} done
|
||||||
*/
|
*/
|
||||||
|
|
@ -564,6 +569,8 @@ FileDump.prototype.loadMap = function(sFilePath, done)
|
||||||
* buildJSON()
|
* buildJSON()
|
||||||
*
|
*
|
||||||
* Common code between the API helper (convertToJSON()) and the command-line helper (convertToFile()).
|
* Common code between the API helper (convertToJSON()) and the command-line helper (convertToFile()).
|
||||||
|
*
|
||||||
|
* @this {FileDump}
|
||||||
*/
|
*/
|
||||||
FileDump.prototype.buildJSON = function()
|
FileDump.prototype.buildJSON = function()
|
||||||
{
|
{
|
||||||
|
|
@ -586,6 +593,7 @@ FileDump.prototype.buildJSON = function()
|
||||||
*
|
*
|
||||||
* Converts the data buffer to JSON.
|
* Converts the data buffer to JSON.
|
||||||
*
|
*
|
||||||
|
* @this {FileDump}
|
||||||
* @param {function(Error,string)} done
|
* @param {function(Error,string)} done
|
||||||
*/
|
*/
|
||||||
FileDump.prototype.convertToJSON = function(done)
|
FileDump.prototype.convertToJSON = function(done)
|
||||||
|
|
@ -599,6 +607,7 @@ FileDump.prototype.convertToJSON = function(done)
|
||||||
*
|
*
|
||||||
* Converts the data buffer to JSON, as appropriate.
|
* Converts the data buffer to JSON, as appropriate.
|
||||||
*
|
*
|
||||||
|
* @this {FileDump}
|
||||||
* @param {string} sOutputFile
|
* @param {string} sOutputFile
|
||||||
* @param {boolean} fOverwrite
|
* @param {boolean} fOverwrite
|
||||||
*/
|
*/
|
||||||
|
|
@ -622,6 +631,7 @@ FileDump.prototype.convertToFile = function(sOutputFile, fOverwrite)
|
||||||
/**
|
/**
|
||||||
* outputFile(sOutputFile, fOverwrite)
|
* outputFile(sOutputFile, fOverwrite)
|
||||||
*
|
*
|
||||||
|
* @this {FileDump}
|
||||||
* @param {string} sOutputFile
|
* @param {string} sOutputFile
|
||||||
* @param {boolean} fOverwrite
|
* @param {boolean} fOverwrite
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,10 @@ var fConsole = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fServerDebug controls server-related debug features; it is false by default and can be enabled using the
|
* fServerDebug controls server-related debug features; it is false by default and can be enabled using the
|
||||||
* setOptions() 'debug' property (or from the command-line interface using "--debug").
|
* setOptions() 'debug' property (or from the server's command-line interface using "--debug").
|
||||||
|
*
|
||||||
|
* This used to be named fDebug, which was fine, but it has been renamed to make the distinction between the
|
||||||
|
* server's debug state (fServerDebug) and the debug state of HTMLOut instances (this.fDebug) clearer.
|
||||||
*/
|
*/
|
||||||
var fServerDebug = false;
|
var fServerDebug = false;
|
||||||
|
|
||||||
|
|
@ -475,7 +478,7 @@ HTMLOut.filter = function(req, res, next)
|
||||||
* and adding an Etag, unless we ALSO change the req.method from "GET" to something else.
|
* and adding an Etag, unless we ALSO change the req.method from "GET" to something else.
|
||||||
* Supposedly, we could also use app.disable('etag'), but I'm not sure that would prevent
|
* Supposedly, we could also use app.disable('etag'), but I'm not sure that would prevent
|
||||||
* Express from changing the status code, and I'm tired of testing work-arounds for this
|
* Express from changing the status code, and I'm tired of testing work-arounds for this
|
||||||
* irritating behavior in Safari.
|
* irritating behavior.
|
||||||
*/
|
*/
|
||||||
req.method = "NONE";
|
req.method = "NONE";
|
||||||
res.set("Content-Type", "application/xml");
|
res.set("Content-Type", "application/xml");
|
||||||
|
|
@ -487,6 +490,10 @@ HTMLOut.filter = function(req, res, next)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (asNonDirectories.indexOf(sBaseName) >= 0) {
|
||||||
|
res.set("Content-Type", "text/plain");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Next, check for API requests (eg, "/api/v1/dump?disk=/disks/pc/dos/ibm/2.00/PCDOS200-DISK1.json&format=img")
|
* Next, check for API requests (eg, "/api/v1/dump?disk=/disks/pc/dos/ibm/2.00/PCDOS200-DISK1.json&format=img")
|
||||||
*
|
*
|
||||||
|
|
@ -681,6 +688,7 @@ HTMLOut.setRoot = function(sRoot)
|
||||||
/**
|
/**
|
||||||
* loadFile()
|
* loadFile()
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sFile
|
* @param {string} sFile
|
||||||
* @param {boolean} fTemplate
|
* @param {boolean} fTemplate
|
||||||
*/
|
*/
|
||||||
|
|
@ -700,6 +708,7 @@ HTMLOut.prototype.loadFile = function(sFile, fTemplate)
|
||||||
*
|
*
|
||||||
* Records the given HTML template and immediately parses it.
|
* Records the given HTML template and immediately parses it.
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {Error} err
|
* @param {Error} err
|
||||||
* @param {string} sData
|
* @param {string} sData
|
||||||
* @param {string} sFile
|
* @param {string} sFile
|
||||||
|
|
@ -741,6 +750,7 @@ HTMLOut.prototype.setData = function(err, sData, sFile, fTemplate)
|
||||||
/**
|
/**
|
||||||
* findTokens()
|
* findTokens()
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {RegExp} reTokens
|
* @param {RegExp} reTokens
|
||||||
*/
|
*/
|
||||||
HTMLOut.prototype.findTokens = function(reTokens)
|
HTMLOut.prototype.findTokens = function(reTokens)
|
||||||
|
|
@ -794,6 +804,8 @@ HTMLOut.prototype.findTokens = function(reTokens)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* replaceTokens()
|
* replaceTokens()
|
||||||
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
*/
|
*/
|
||||||
HTMLOut.prototype.replaceTokens = function()
|
HTMLOut.prototype.replaceTokens = function()
|
||||||
{
|
{
|
||||||
|
|
@ -866,6 +878,7 @@ HTMLOut.prototype.replaceTokens = function()
|
||||||
*
|
*
|
||||||
* aParms[0], if present, is used as the preferred title for the home page
|
* aParms[0], if present, is used as the preferred title for the home page
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -880,6 +893,7 @@ HTMLOut.prototype.getTitle = function(sToken, sIndent, aParms)
|
||||||
*
|
*
|
||||||
* Returns the current version in "package.json".
|
* Returns the current version in "package.json".
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -902,6 +916,7 @@ HTMLOut.prototype.getVersion = function(sToken, sIndent, aParms)
|
||||||
/**
|
/**
|
||||||
* getPath(sToken, sIndent, aParms)
|
* getPath(sToken, sIndent, aParms)
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -914,6 +929,7 @@ HTMLOut.prototype.getPath = function(sToken, sIndent, aParms)
|
||||||
/**
|
/**
|
||||||
* getPCPath(sToken, sIndent, aParms)
|
* getPCPath(sToken, sIndent, aParms)
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -941,6 +957,7 @@ HTMLOut.prototype.getPCPath = function(sToken, sIndent, aParms)
|
||||||
* <a href="/apps/">[apps]</a>
|
* <a href="/apps/">[apps]</a>
|
||||||
* </li>
|
* </li>
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -962,8 +979,8 @@ HTMLOut.prototype.getDirList = function(sToken, sIndent, aParms)
|
||||||
asFiles.push("..");
|
asFiles.push("..");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For sorting purposes, I want all folders ending in "kb" and beginning with one or two
|
* For sorting purposes, I want all folders ending in "kb" and beginning with one to three
|
||||||
* digits to sort as if they all began with THREE digits (ie, with leading zeros as needed).
|
* digits to sort as if they all began with FOUR digits (ie, with leading zeros as needed).
|
||||||
* But I don't want to change the folder names that are ultimately displayed. So instead,
|
* But I don't want to change the folder names that are ultimately displayed. So instead,
|
||||||
* I pad those names with slashes, since a leading slash will sort much like a leading zero
|
* I pad those names with slashes, since a leading slash will sort much like a leading zero
|
||||||
* without being a valid filename character, meaning we can trim away those leading slashes
|
* without being a valid filename character, meaning we can trim away those leading slashes
|
||||||
|
|
@ -1002,7 +1019,7 @@ HTMLOut.prototype.getDirList = function(sToken, sIndent, aParms)
|
||||||
if (asFilesNonListed.indexOf(sBaseName) >= 0) continue;
|
if (asFilesNonListed.indexOf(sBaseName) >= 0) continue;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Even when the server's in Debug mode, there are some files it makes no sense to list....
|
* Even when the server's in Debug mode, there are some files it makes no sense to list.
|
||||||
*/
|
*/
|
||||||
if (sBaseName == "index.html") continue;
|
if (sBaseName == "index.html") continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1073,6 +1090,7 @@ HTMLOut.prototype.getDirList = function(sToken, sIndent, aParms)
|
||||||
*
|
*
|
||||||
* Return the current year.
|
* Return the current year.
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -1087,6 +1105,7 @@ HTMLOut.prototype.getYear = function(sToken, sIndent, aParms)
|
||||||
*
|
*
|
||||||
* If we're in the "blog" folder, then enumerate all available blog entries and create a rendering of blog excerpts.
|
* If we're in the "blog" folder, then enumerate all available blog entries and create a rendering of blog excerpts.
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -1189,7 +1208,7 @@ HTMLOut.prototype.getBlog = function(sToken, sIndent, aParms)
|
||||||
for (var i = 0; i < aExcerpts.length; i++) {
|
for (var i = 0; i < aExcerpts.length; i++) {
|
||||||
sExcerpts += aExcerpts[i].excerpt + "\n\n";
|
sExcerpts += aExcerpts[i].excerpt + "\n\n";
|
||||||
}
|
}
|
||||||
var mExcerpts = new MarkOut(sExcerpts, sIndent, obj.req, aParms, obj.fDebug, fServerDebug);
|
var mExcerpts = new MarkOut(sExcerpts, sIndent, obj.req, aParms, obj.fDebug);
|
||||||
obj.aTokens[sToken] = mExcerpts.convertMD(" ").trim();
|
obj.aTokens[sToken] = mExcerpts.convertMD(" ").trim();
|
||||||
obj.replaceTokens();
|
obj.replaceTokens();
|
||||||
}
|
}
|
||||||
|
|
@ -1223,6 +1242,7 @@ HTMLOut.prototype.getBlog = function(sToken, sIndent, aParms)
|
||||||
* with a specific machine XML file, which would have had the potential to bypass getReadMe() altogether, so
|
* with a specific machine XML file, which would have had the potential to bypass getReadMe() altogether, so
|
||||||
* getMachineXML() may now call getReadMe() -- which must NOT call getMachineXML() back whenever that happens.
|
* getMachineXML() may now call getReadMe() -- which must NOT call getMachineXML() back whenever that happens.
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -1240,6 +1260,7 @@ HTMLOut.prototype.getDefault = function(sToken, sIndent, aParms)
|
||||||
*
|
*
|
||||||
* If the HTML file specified by aParms[0] exists, insert its contents into the current HTML document.
|
* If the HTML file specified by aParms[0] exists, insert its contents into the current HTML document.
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -1280,6 +1301,7 @@ HTMLOut.prototype.getHTMLFile = function(sToken, sIndent, aParms)
|
||||||
*
|
*
|
||||||
* If "machine.xml" exists in the current directory, open it and determine if embedding it makes sense.
|
* If "machine.xml" exists in the current directory, open it and determine if embedding it makes sense.
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>|null} [aParms]
|
* @param {Array.<string>|null} [aParms]
|
||||||
|
|
@ -1343,7 +1365,7 @@ HTMLOut.prototype.getMachineXML = function(sToken, sIndent, aParms, sXMLFile, sS
|
||||||
sMachineDef += (sStateFile? ":" + sStateFile : "");
|
sMachineDef += (sStateFile? ":" + sStateFile : "");
|
||||||
|
|
||||||
s = '[Embedded ' + sMachineClass + '](' + sXMLFile + ' "' + sMachineDef + '")';
|
s = '[Embedded ' + sMachineClass + '](' + sXMLFile + ' "' + sMachineDef + '")';
|
||||||
var m = new MarkOut(s, sIndent, obj.req, null, obj.fDebug, fServerDebug);
|
var m = new MarkOut(s, sIndent, obj.req, null, obj.fDebug);
|
||||||
s = m.convertMD(" ").trim();
|
s = m.convertMD(" ").trim();
|
||||||
|
|
||||||
obj.processMachines(m.getMachines(), function doneProcessXMLMachines() {
|
obj.processMachines(m.getMachines(), function doneProcessXMLMachines() {
|
||||||
|
|
@ -1388,6 +1410,7 @@ HTMLOut.prototype.getMachineXML = function(sToken, sIndent, aParms, sXMLFile, sS
|
||||||
*
|
*
|
||||||
* If "manifest.xml" exists in the current directory, open it and embed it.
|
* If "manifest.xml" exists in the current directory, open it and embed it.
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -1575,6 +1598,7 @@ HTMLOut.prototype.getManifestXML = function(sToken, sIndent, aParms)
|
||||||
*
|
*
|
||||||
* If a "README.md" exists in the current directory, open it, convert it, and prepare for replacement.
|
* If a "README.md" exists in the current directory, open it, convert it, and prepare for replacement.
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -1607,7 +1631,7 @@ HTMLOut.prototype.getReadMe = function(sToken, sIndent, aParms, sPrevious)
|
||||||
obj.getMachineXML(sToken, sIndent); // we don't pass along aParms, because those are for Markdown files only
|
obj.getMachineXML(sToken, sIndent); // we don't pass along aParms, because those are for Markdown files only
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var m = new MarkOut(s, sIndent, obj.req, aParms, obj.fDebug, fServerDebug);
|
var m = new MarkOut(s, sIndent, obj.req, aParms, obj.fDebug);
|
||||||
s = m.convertMD(" ").trim();
|
s = m.convertMD(" ").trim();
|
||||||
/*
|
/*
|
||||||
* If the Markdown document begins with a heading, stuff that into the <title> tag;
|
* If the Markdown document begins with a heading, stuff that into the <title> tag;
|
||||||
|
|
@ -1644,6 +1668,7 @@ HTMLOut.prototype.getReadMe = function(sToken, sIndent, aParms, sPrevious)
|
||||||
/**
|
/**
|
||||||
* getSocketScripts(sToken, sIndent, aParms)
|
* getSocketScripts(sToken, sIndent, aParms)
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sToken
|
* @param {string} sToken
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @param {Array.<string>} [aParms]
|
* @param {Array.<string>} [aParms]
|
||||||
|
|
@ -1658,6 +1683,7 @@ HTMLOut.prototype.getSocketScripts = function(sToken, sIndent, aParms)
|
||||||
*
|
*
|
||||||
* Generate a random string of words, purely for entertainment purposes (eg, something in honor of "ADVENT").
|
* Generate a random string of words, purely for entertainment purposes (eg, something in honor of "ADVENT").
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
|
|
@ -1699,9 +1725,9 @@ HTMLOut.prototype.getRandomString = function(sIndent)
|
||||||
*
|
*
|
||||||
* Additional properties can include:
|
* Additional properties can include:
|
||||||
*
|
*
|
||||||
* 'compiled' (eg, true or false); if not defined, then we choose a value based on any Gort command,
|
* 'compiled' (eg, true or false); if not defined, we choose a value based on the module's fDebug setting
|
||||||
* or failing that, the internal fServerDebug setting
|
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {Array} aMachines is an array of objects containing information about each machine on the current page
|
* @param {Array} aMachines is an array of objects containing information about each machine on the current page
|
||||||
* @param {function()} done
|
* @param {function()} done
|
||||||
*/
|
*/
|
||||||
|
|
@ -1785,6 +1811,7 @@ HTMLOut.prototype.processMachines = function(aMachines, done)
|
||||||
/**
|
/**
|
||||||
* addFilesToHTML(asFiles)
|
* addFilesToHTML(asFiles)
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {Array.<string>} asFiles is a list of CSS and/or JS files to include in the HTML
|
* @param {Array.<string>} asFiles is a list of CSS and/or JS files to include in the HTML
|
||||||
* @param {string} [sScriptEmbed] is an optional script to embed in the <body> (after any JS files listed above)
|
* @param {string} [sScriptEmbed] is an optional script to embed in the <body> (after any JS files listed above)
|
||||||
*/
|
*/
|
||||||
|
|
@ -1842,6 +1869,7 @@ HTMLOut.prototype.addFilesToHTML = function(asFiles, sScriptEmbed)
|
||||||
/**
|
/**
|
||||||
* genOnClick(sURL)
|
* genOnClick(sURL)
|
||||||
*
|
*
|
||||||
|
* @this {HTMLOut}
|
||||||
* @param {string} sURL
|
* @param {string} sURL
|
||||||
* @param {string} [sFormat] (default is DumpAPI.FORMAT.IMG)
|
* @param {string} [sFormat] (default is DumpAPI.FORMAT.IMG)
|
||||||
* @return {string}
|
* @return {string}
|
||||||
|
|
|
||||||
|
|
@ -93,10 +93,9 @@ var sDefaultFile = "./README.md";
|
||||||
* @param {string|null} [sIndent] sets the overall indentation of the document
|
* @param {string|null} [sIndent] sets the overall indentation of the document
|
||||||
* @param {Object} [req] is the web server's (ie, Express) request object, if any
|
* @param {Object} [req] is the web server's (ie, Express) request object, if any
|
||||||
* @param {Array.<string>|null} [aParms] is an array of overrides to use (see below)
|
* @param {Array.<string>|null} [aParms] is an array of overrides to use (see below)
|
||||||
* @param {boolean} [fDebug] turns on debugging features (eg, debug comments)
|
* @param {boolean} [fDebug] turns on debugging features (eg, debug comments, special URL encodings, etc)
|
||||||
* @param {boolean} [fServerDebug] turns on server debug features (eg, special URL encoding rules)
|
|
||||||
*/
|
*/
|
||||||
function MarkOut(sMD, sIndent, req, aParms, fDebug, fServerDebug)
|
function MarkOut(sMD, sIndent, req, aParms, fDebug)
|
||||||
{
|
{
|
||||||
this.sMD = sMD;
|
this.sMD = sMD;
|
||||||
this.sIndent = (sIndent || "");
|
this.sIndent = (sIndent || "");
|
||||||
|
|
@ -109,7 +108,6 @@ function MarkOut(sMD, sIndent, req, aParms, fDebug, fServerDebug)
|
||||||
this.sClassImageLabel = this.sClassImage + "-label";
|
this.sClassImageLabel = this.sClassImage + "-label";
|
||||||
}
|
}
|
||||||
this.fDebug = fDebug;
|
this.fDebug = fDebug;
|
||||||
this.fServerDebug = fServerDebug;
|
|
||||||
this.sHTML = null;
|
this.sHTML = null;
|
||||||
this.aIDs = []; // this keeps tracks of auto-generated ID attributes for page elements, to insure uniqueness
|
this.aIDs = []; // this keeps tracks of auto-generated ID attributes for page elements, to insure uniqueness
|
||||||
this.aMachines = []; // this keeps tracks of embedded machines on the page
|
this.aMachines = []; // this keeps tracks of embedded machines on the page
|
||||||
|
|
@ -242,6 +240,7 @@ MarkOut.setOptions = function(options)
|
||||||
* and make sure all the pre-requisites are in place (eg, CSS file and scripts in the HTML document's
|
* and make sure all the pre-requisites are in place (eg, CSS file and scripts in the HTML document's
|
||||||
* header).
|
* header).
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {Object} infoMachine
|
* @param {Object} infoMachine
|
||||||
*/
|
*/
|
||||||
MarkOut.prototype.addMachine = function(infoMachine)
|
MarkOut.prototype.addMachine = function(infoMachine)
|
||||||
|
|
@ -252,6 +251,7 @@ MarkOut.prototype.addMachine = function(infoMachine)
|
||||||
/**
|
/**
|
||||||
* getMachines()
|
* getMachines()
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @return {Array} of objects containing information about each machine defined by the document
|
* @return {Array} of objects containing information about each machine defined by the document
|
||||||
*/
|
*/
|
||||||
MarkOut.prototype.getMachines = function()
|
MarkOut.prototype.getMachines = function()
|
||||||
|
|
@ -267,6 +267,7 @@ MarkOut.prototype.getMachines = function()
|
||||||
* the result. Furthermore, if the generated ID is not unique (among the set of ALL generated IDs),
|
* the result. Furthermore, if the generated ID is not unique (among the set of ALL generated IDs),
|
||||||
* then no ID is produced.
|
* then no ID is produced.
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} sText
|
* @param {string} sText
|
||||||
* @returns {string|null} converts the given text to a unique ID (or null if resulting ID was not unique)
|
* @returns {string|null} converts the given text to a unique ID (or null if resulting ID was not unique)
|
||||||
*/
|
*/
|
||||||
|
|
@ -301,6 +302,7 @@ MarkOut.aHTMLEntities = {
|
||||||
/**
|
/**
|
||||||
* convertMD()
|
* convertMD()
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} [sIndent] sets the indentation of HTML elements within the document
|
* @param {string} [sIndent] sets the indentation of HTML elements within the document
|
||||||
*/
|
*/
|
||||||
MarkOut.prototype.convertMD = function(sIndent)
|
MarkOut.prototype.convertMD = function(sIndent)
|
||||||
|
|
@ -414,6 +416,7 @@ MarkOut.prototype.convertMD = function(sIndent)
|
||||||
* If your text may contain some block markers (ie, double-linefeeds), or headers (either "Atx-style"
|
* If your text may contain some block markers (ie, double-linefeeds), or headers (either "Atx-style"
|
||||||
* or "Setext-style) that require the insertion of double-linefeed block markers, then call this function.
|
* or "Setext-style) that require the insertion of double-linefeed block markers, then call this function.
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} sMD
|
* @param {string} sMD
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
*/
|
*/
|
||||||
|
|
@ -478,6 +481,7 @@ MarkOut.prototype.convertMDBlocks = function(sMD, sIndent)
|
||||||
/**
|
/**
|
||||||
* convertMDBlock(sBlock, sIndent)
|
* convertMDBlock(sBlock, sIndent)
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} sBlock
|
* @param {string} sBlock
|
||||||
* @param {string} [sIndent]
|
* @param {string} [sIndent]
|
||||||
*/
|
*/
|
||||||
|
|
@ -623,6 +627,7 @@ MarkOut.prototype.convertMDBlock = function(sBlock, sIndent)
|
||||||
* Markdown apparently treats equivalently), I automatically use a list style that omits bullets.
|
* Markdown apparently treats equivalently), I automatically use a list style that omits bullets.
|
||||||
* So, if you REALLY want bullets, use "-" or "+".
|
* So, if you REALLY want bullets, use "-" or "+".
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} sBlock
|
* @param {string} sBlock
|
||||||
* @param {string} sIndent
|
* @param {string} sIndent
|
||||||
* @return {string}
|
* @return {string}
|
||||||
|
|
@ -688,6 +693,7 @@ MarkOut.prototype.convertMDList = function(sBlock, sIndent)
|
||||||
* galleries, which are nothing more than paragraphs containing a series of image links), so this
|
* galleries, which are nothing more than paragraphs containing a series of image links), so this
|
||||||
* code is disabled for now.
|
* code is disabled for now.
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} s
|
* @param {string} s
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
|
|
@ -720,6 +726,7 @@ MarkOut.prototype.convertMDLines = function(s)
|
||||||
*
|
*
|
||||||
* TODO: Consider adding support for "reference"-style Markdown links.
|
* TODO: Consider adding support for "reference"-style Markdown links.
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} sBlock
|
* @param {string} sBlock
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
|
|
@ -748,7 +755,7 @@ MarkOut.prototype.convertMDLinks = function(sBlock)
|
||||||
sType = "id"; // using the "name" attribute is deprecated as well
|
sType = "id"; // using the "name" attribute is deprecated as well
|
||||||
sURL = sURL.substr(1);
|
sURL = sURL.substr(1);
|
||||||
} else {
|
} else {
|
||||||
sURL = net.encodeURL(sURL, this.req, this.fServerDebug);
|
sURL = net.encodeURL(sURL, this.req, this.fDebug);
|
||||||
}
|
}
|
||||||
sBlock = str.replaceAll(aMatch[0], '<' + sTag + ' ' + sType + '="' + sURL + '"' + sTitle + '>' + sText + '</' + sTag + '>', sBlock);
|
sBlock = str.replaceAll(aMatch[0], '<' + sTag + ' ' + sType + '="' + sURL + '"' + sTitle + '>' + sText + '</' + sTag + '>', sBlock);
|
||||||
}
|
}
|
||||||
|
|
@ -758,6 +765,7 @@ MarkOut.prototype.convertMDLinks = function(sBlock)
|
||||||
/**
|
/**
|
||||||
* convertMDImageLinks(sBlock)
|
* convertMDImageLinks(sBlock)
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} sBlock
|
* @param {string} sBlock
|
||||||
* @param {string} sIndent
|
* @param {string} sIndent
|
||||||
* @return {string}
|
* @return {string}
|
||||||
|
|
@ -778,7 +786,7 @@ MarkOut.prototype.convertMDImageLinks = function(sBlock, sIndent)
|
||||||
var sBlockOrig = sBlock;
|
var sBlockOrig = sBlock;
|
||||||
var re = /!\[(.*?)\]\((.*?)(?:\s*"(.*?)"\)|\))/g;
|
var re = /!\[(.*?)\]\((.*?)(?:\s*"(.*?)"\)|\))/g;
|
||||||
while ((aMatch = re.exec(sBlockOrig))) {
|
while ((aMatch = re.exec(sBlockOrig))) {
|
||||||
var sImage = '<img src="' + net.encodeURL(aMatch[2], this.req, this.fServerDebug) + '" alt="' + aMatch[1] + '"';
|
var sImage = '<img src="' + net.encodeURL(aMatch[2], this.req, this.fDebug) + '" alt="' + aMatch[1] + '"';
|
||||||
if (aMatch[3]) {
|
if (aMatch[3]) {
|
||||||
/*
|
/*
|
||||||
* The format of the special "link:" syntax is:
|
* The format of the special "link:" syntax is:
|
||||||
|
|
@ -814,10 +822,10 @@ MarkOut.prototype.convertMDImageLinks = function(sBlock, sIndent)
|
||||||
* The assumption here is that if we have "static" thumbs, then we should also have full "static"
|
* The assumption here is that if we have "static" thumbs, then we should also have full "static"
|
||||||
* copies as well.
|
* copies as well.
|
||||||
*/
|
*/
|
||||||
if (aMatch[2].indexOf("static/") >= 0 && sURL.indexOf("://") > 0 && (this.fServerDebug || net.hasParm(net.REVEAL_COMMAND, net.REVEAL_PDFS, this.req))) {
|
if (aMatch[2].indexOf("static/") >= 0 && sURL.indexOf("://") > 0 && (this.fDebug || net.hasParm(net.REVEAL_COMMAND, net.REVEAL_PDFS, this.req))) {
|
||||||
sURL = aMatch[2].replace("/thumbs/", "/").replace(" 1.jpeg", ".pdf").replace(".jpg", ".pdf");
|
sURL = aMatch[2].replace("/thumbs/", "/").replace(" 1.jpeg", ".pdf").replace(".jpg", ".pdf");
|
||||||
}
|
}
|
||||||
sURL = net.encodeURL(sURL, this.req, this.fServerDebug);
|
sURL = net.encodeURL(sURL, this.req, this.fDebug);
|
||||||
if (asParts[iPart] == "nogallery") {
|
if (asParts[iPart] == "nogallery") {
|
||||||
fNoGallery = true;
|
fNoGallery = true;
|
||||||
iPart++;
|
iPart++;
|
||||||
|
|
@ -862,6 +870,7 @@ MarkOut.prototype.convertMDImageLinks = function(sBlock, sIndent)
|
||||||
/**
|
/**
|
||||||
* convertMDMachineLinks(sBlock)
|
* convertMDMachineLinks(sBlock)
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} sBlock
|
* @param {string} sBlock
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
|
|
@ -992,6 +1001,7 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock)
|
||||||
* Also, for reasons noted in the code below, we don't support emphasis in the middle
|
* Also, for reasons noted in the code below, we don't support emphasis in the middle
|
||||||
* of words.
|
* of words.
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} sBlock
|
* @param {string} sBlock
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
|
|
@ -1031,6 +1041,7 @@ MarkOut.prototype.convertMDEmphasis = function(sBlock)
|
||||||
/**
|
/**
|
||||||
* addIndent(sIndent)
|
* addIndent(sIndent)
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string|undefined} sIndent
|
* @param {string|undefined} sIndent
|
||||||
* @return {string} previous indent
|
* @return {string} previous indent
|
||||||
*/
|
*/
|
||||||
|
|
@ -1044,6 +1055,7 @@ MarkOut.prototype.addIndent = function(sIndent)
|
||||||
/**
|
/**
|
||||||
* subIndent(sIndent)
|
* subIndent(sIndent)
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string|undefined} sIndent
|
* @param {string|undefined} sIndent
|
||||||
*/
|
*/
|
||||||
MarkOut.prototype.subIndent = function(sIndent)
|
MarkOut.prototype.subIndent = function(sIndent)
|
||||||
|
|
@ -1064,6 +1076,7 @@ MarkOut.prototype.subIndent = function(sIndent)
|
||||||
* This is used purely (at the moment) for debugging purposes, so that we can clearly see
|
* This is used purely (at the moment) for debugging purposes, so that we can clearly see
|
||||||
* what our simplistic Markdown parser is parsing at each stage.
|
* what our simplistic Markdown parser is parsing at each stage.
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} sLabel
|
* @param {string} sLabel
|
||||||
* @param {string} sText
|
* @param {string} sText
|
||||||
* @return {string}
|
* @return {string}
|
||||||
|
|
@ -1080,6 +1093,7 @@ MarkOut.prototype.encodeComment = function(sLabel, sText)
|
||||||
* This is used purely (at the moment) for debugging purposes, so that we can clearly see
|
* This is used purely (at the moment) for debugging purposes, so that we can clearly see
|
||||||
* what our simplistic Markdown parser is parsing at each stage.
|
* what our simplistic Markdown parser is parsing at each stage.
|
||||||
*
|
*
|
||||||
|
* @this {MarkOut}
|
||||||
* @param {string} sText
|
* @param {string} sText
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -480,7 +480,7 @@ Bus.prototype.restoreMemory = function(a)
|
||||||
* configuration since it was last saved (the most likely explanation) or there's some internal
|
* configuration since it was last saved (the most likely explanation) or there's some internal
|
||||||
* inconsistency (eg, the block size is wrong).
|
* inconsistency (eg, the block size is wrong).
|
||||||
*/
|
*/
|
||||||
this.error("Unable to restore memory block " + iBlock);
|
Component.error("Unable to restore memory block " + iBlock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -554,7 +554,7 @@ Bus.prototype.addPortInputNotify = function(start, end, component, fn)
|
||||||
if (fn !== undefined) {
|
if (fn !== undefined) {
|
||||||
for (var port = start; port <= end; port++) {
|
for (var port = start; port <= end; port++) {
|
||||||
if (this.aPortInputNotify[port] !== undefined) {
|
if (this.aPortInputNotify[port] !== undefined) {
|
||||||
this.warning("Input port " + str.toHexWord(port) + " registered by " + this.aPortInputNotify[port][0].id + ", ignoring " + component.id);
|
Component.warning("Input port " + str.toHexWord(port) + " registered by " + this.aPortInputNotify[port][0].id + ", ignoring " + component.id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this.aPortInputNotify[port] = [component, fn, false, false];
|
this.aPortInputNotify[port] = [component, fn, false, false];
|
||||||
|
|
@ -674,7 +674,7 @@ Bus.prototype.addPortOutputNotify = function(start, end, component, fn)
|
||||||
if (fn !== undefined) {
|
if (fn !== undefined) {
|
||||||
for (var port = start; port <= end; port++) {
|
for (var port = start; port <= end; port++) {
|
||||||
if (this.aPortOutputNotify[port] !== undefined) {
|
if (this.aPortOutputNotify[port] !== undefined) {
|
||||||
this.warning("Output port " + str.toHexWord(port) + " registered by " + this.aPortOutputNotify[port][0].id + ", ignoring " + component.id);
|
Component.warning("Output port " + str.toHexWord(port) + " registered by " + this.aPortOutputNotify[port][0].id + ", ignoring " + component.id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this.aPortOutputNotify[port] = [component, fn, false, false];
|
this.aPortOutputNotify[port] = [component, fn, false, false];
|
||||||
|
|
@ -764,7 +764,7 @@ Bus.prototype.removePortOutputNotify = function(start, end, component, fn)
|
||||||
*/
|
*/
|
||||||
Bus.prototype.reportError = function(op, addr, size)
|
Bus.prototype.reportError = function(op, addr, size)
|
||||||
{
|
{
|
||||||
this.error("Memory block error (" + op + "," + str.toHex(addr) + "," + str.toHex(size) + ")");
|
Component.error("Memory block error (" + op + "," + str.toHex(addr) + "," + str.toHex(size) + ")");
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -157,12 +157,6 @@ function ChipSet(parmsChipSet)
|
||||||
* and (on the MODEL_5160) whether or not a coprocessor is installed. If no SW1 settings are provided,
|
* and (on the MODEL_5160) whether or not a coprocessor is installed. If no SW1 settings are provided,
|
||||||
* we look for individual 'fdrives' and 'monitor' settings and build a default SW1 value.
|
* we look for individual 'fdrives' and 'monitor' settings and build a default SW1 value.
|
||||||
*
|
*
|
||||||
* TODO: Get rid of reliance on SW1 for MODEL_5170 and later; omitting it now results in a BIOS warning:
|
|
||||||
*
|
|
||||||
* ' 162-System Options Not Set-(Run SETUP)'
|
|
||||||
*
|
|
||||||
* ' (RESUME = "F1" KEY)'
|
|
||||||
*
|
|
||||||
* The defaults below select max memory, monochrome monitor (EGA monitor for MODEL_5170), and two floppies.
|
* The defaults below select max memory, monochrome monitor (EGA monitor for MODEL_5170), and two floppies.
|
||||||
* Don't get too excited about "max memory" either: on a MODEL_5150, the max was 64Kb, and on a MODEL_5160,
|
* Don't get too excited about "max memory" either: on a MODEL_5150, the max was 64Kb, and on a MODEL_5160,
|
||||||
* the max was 256Kb. However, the RAM component is free to install as much base memory as it likes,
|
* the max was 256Kb. However, the RAM component is free to install as much base memory as it likes,
|
||||||
|
|
@ -2566,14 +2560,14 @@ ChipSet.prototype.updateDMA = function(channel)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* inPICL(iPIC, addrFrom)
|
* inPICLo(iPIC, addrFrom)
|
||||||
*
|
*
|
||||||
* @this {ChipSet}
|
* @this {ChipSet}
|
||||||
* @param {number} iPIC
|
* @param {number} iPIC
|
||||||
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
||||||
* @return {number} simulated port value
|
* @return {number} simulated port value
|
||||||
*/
|
*/
|
||||||
ChipSet.prototype.inPICL = function(iPIC, addrFrom)
|
ChipSet.prototype.inPICLo = function(iPIC, addrFrom)
|
||||||
{
|
{
|
||||||
var b = 0;
|
var b = 0;
|
||||||
var pic = this.aPICs[iPIC];
|
var pic = this.aPICs[iPIC];
|
||||||
|
|
@ -2595,14 +2589,14 @@ ChipSet.prototype.inPICL = function(iPIC, addrFrom)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* outPICL(iPIC, bOut, addrFrom)
|
* outPICLo(iPIC, bOut, addrFrom)
|
||||||
*
|
*
|
||||||
* @this {ChipSet}
|
* @this {ChipSet}
|
||||||
* @param {number} iPIC
|
* @param {number} iPIC
|
||||||
* @param {number} bOut
|
* @param {number} bOut
|
||||||
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
||||||
*/
|
*/
|
||||||
ChipSet.prototype.outPICL = function(iPIC, bOut, addrFrom)
|
ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
|
||||||
{
|
{
|
||||||
var pic = this.aPICs[iPIC];
|
var pic = this.aPICs[iPIC];
|
||||||
this.messagePort(pic.port, bOut, addrFrom, "PIC" + iPIC, ChipSet.MESSAGE_PIC);
|
this.messagePort(pic.port, bOut, addrFrom, "PIC" + iPIC, ChipSet.MESSAGE_PIC);
|
||||||
|
|
@ -2613,7 +2607,7 @@ ChipSet.prototype.outPICL = function(iPIC, bOut, addrFrom)
|
||||||
pic.nICW = 0;
|
pic.nICW = 0;
|
||||||
pic.aICW[pic.nICW++] = bOut;
|
pic.aICW[pic.nICW++] = bOut;
|
||||||
/*
|
/*
|
||||||
* I used to do the rest of this initialization in outPICH(), once all the ICW commands had been received,
|
* I used to do the rest of this initialization in outPICHi(), once all the ICW commands had been received,
|
||||||
* but a closer reading of the 8259A spec indicates that that should happen now, on receipt on ICW1.
|
* but a closer reading of the 8259A spec indicates that that should happen now, on receipt on ICW1.
|
||||||
*
|
*
|
||||||
* Also, on p.10 of that spec, it says "The Interrupt Mask Register is cleared". I originally took that to
|
* Also, on p.10 of that spec, it says "The Interrupt Mask Register is cleared". I originally took that to
|
||||||
|
|
@ -2711,7 +2705,7 @@ ChipSet.prototype.outPICL = function(iPIC, bOut, addrFrom)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* This must be an OCW3 request. If it's a "Read Register" command (PIC_LO.OCW3_READ_CMD), inPICL() will take care it.
|
* This must be an OCW3 request. If it's a "Read Register" command (PIC_LO.OCW3_READ_CMD), inPICLo() will take care it.
|
||||||
*
|
*
|
||||||
* TODO: If OCW3 specified a "Poll" command (PIC_LO.OCW3_POLL_CMD) or a "Special Mask Mode" command (PIC_LO.OCW3_SMM_CMD),
|
* TODO: If OCW3 specified a "Poll" command (PIC_LO.OCW3_POLL_CMD) or a "Special Mask Mode" command (PIC_LO.OCW3_SMM_CMD),
|
||||||
* that's unfortunate, because I don't support them yet.
|
* that's unfortunate, because I don't support them yet.
|
||||||
|
|
@ -2724,14 +2718,14 @@ ChipSet.prototype.outPICL = function(iPIC, bOut, addrFrom)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* inPICH(iPIC, addrFrom)
|
* inPICHi(iPIC, addrFrom)
|
||||||
*
|
*
|
||||||
* @this {ChipSet}
|
* @this {ChipSet}
|
||||||
* @param {number} iPIC
|
* @param {number} iPIC
|
||||||
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
||||||
* @return {number} simulated port value
|
* @return {number} simulated port value
|
||||||
*/
|
*/
|
||||||
ChipSet.prototype.inPICH = function(iPIC, addrFrom)
|
ChipSet.prototype.inPICHi = function(iPIC, addrFrom)
|
||||||
{
|
{
|
||||||
var pic = this.aPICs[iPIC];
|
var pic = this.aPICs[iPIC];
|
||||||
var b = pic.bIMR;
|
var b = pic.bIMR;
|
||||||
|
|
@ -2740,14 +2734,14 @@ ChipSet.prototype.inPICH = function(iPIC, addrFrom)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* outPICH(iPIC, bOut, addrFrom)
|
* outPICHi(iPIC, bOut, addrFrom)
|
||||||
*
|
*
|
||||||
* @this {ChipSet}
|
* @this {ChipSet}
|
||||||
* @param {number} iPIC
|
* @param {number} iPIC
|
||||||
* @param {number} bOut
|
* @param {number} bOut
|
||||||
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
||||||
*/
|
*/
|
||||||
ChipSet.prototype.outPICH = function(iPIC, bOut, addrFrom)
|
ChipSet.prototype.outPICHi = function(iPIC, bOut, addrFrom)
|
||||||
{
|
{
|
||||||
var pic = this.aPICs[iPIC];
|
var pic = this.aPICs[iPIC];
|
||||||
this.messagePort(pic.port+1, bOut, addrFrom, "PIC" + iPIC, ChipSet.MESSAGE_PIC);
|
this.messagePort(pic.port+1, bOut, addrFrom, "PIC" + iPIC, ChipSet.MESSAGE_PIC);
|
||||||
|
|
@ -4230,8 +4224,8 @@ ChipSet.aPortInput = {
|
||||||
0x06: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelAddr(ChipSet.DMA0.INDEX, 3, port, addrFrom); },
|
0x06: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelAddr(ChipSet.DMA0.INDEX, 3, port, addrFrom); },
|
||||||
0x07: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelCount(ChipSet.DMA0.INDEX, 3, port, addrFrom); },
|
0x07: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelCount(ChipSet.DMA0.INDEX, 3, port, addrFrom); },
|
||||||
0x08: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAStatus(ChipSet.DMA0.INDEX, port, addrFrom); },
|
0x08: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAStatus(ChipSet.DMA0.INDEX, port, addrFrom); },
|
||||||
0x20: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICL(ChipSet.PIC0.INDEX, addrFrom); },
|
0x20: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICLo(ChipSet.PIC0.INDEX, addrFrom); },
|
||||||
0x21: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICH(ChipSet.PIC0.INDEX, addrFrom); },
|
0x21: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICHi(ChipSet.PIC0.INDEX, addrFrom); },
|
||||||
0x40: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER0.INDEX, addrFrom); },
|
0x40: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER0.INDEX, addrFrom); },
|
||||||
0x41: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER1.INDEX, addrFrom); },
|
0x41: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER1.INDEX, addrFrom); },
|
||||||
0x42: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER2.INDEX, addrFrom); },
|
0x42: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER2.INDEX, addrFrom); },
|
||||||
|
|
@ -4267,8 +4261,8 @@ ChipSet.aPortInput5170 = {
|
||||||
0x8D: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageSpare(5, port, addrFrom); },
|
0x8D: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageSpare(5, port, addrFrom); },
|
||||||
0x8E: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageSpare(6, port, addrFrom); },
|
0x8E: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageSpare(6, port, addrFrom); },
|
||||||
0x8F: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageReg(ChipSet.DMA1.INDEX, 0, port, addrFrom); },
|
0x8F: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageReg(ChipSet.DMA1.INDEX, 0, port, addrFrom); },
|
||||||
0xA0: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICL(ChipSet.PIC1.INDEX, addrFrom); },
|
0xA0: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICLo(ChipSet.PIC1.INDEX, addrFrom); },
|
||||||
0xA1: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICH(ChipSet.PIC1.INDEX, addrFrom); },
|
0xA1: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICHi(ChipSet.PIC1.INDEX, addrFrom); },
|
||||||
0xC0: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelAddr(ChipSet.DMA1.INDEX, 0, port, addrFrom); },
|
0xC0: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelAddr(ChipSet.DMA1.INDEX, 0, port, addrFrom); },
|
||||||
0xC2: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelCount(ChipSet.DMA1.INDEX, 0, port, addrFrom); },
|
0xC2: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelCount(ChipSet.DMA1.INDEX, 0, port, addrFrom); },
|
||||||
0xC4: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelAddr(ChipSet.DMA1.INDEX, 1, port, addrFrom); },
|
0xC4: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelAddr(ChipSet.DMA1.INDEX, 1, port, addrFrom); },
|
||||||
|
|
@ -4298,8 +4292,8 @@ ChipSet.aPortOutput = {
|
||||||
0x0B: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAMode(ChipSet.DMA0.INDEX, port, bOut, addrFrom); },
|
0x0B: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAMode(ChipSet.DMA0.INDEX, port, bOut, addrFrom); },
|
||||||
0x0C: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAIndex(ChipSet.DMA0.INDEX, port, bOut, addrFrom); },
|
0x0C: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAIndex(ChipSet.DMA0.INDEX, port, bOut, addrFrom); },
|
||||||
0x0D: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAClear(ChipSet.DMA0.INDEX, port, bOut, addrFrom); },
|
0x0D: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAClear(ChipSet.DMA0.INDEX, port, bOut, addrFrom); },
|
||||||
0x20: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICL(ChipSet.PIC0.INDEX, bOut, addrFrom); },
|
0x20: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICLo(ChipSet.PIC0.INDEX, bOut, addrFrom); },
|
||||||
0x21: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICH(ChipSet.PIC0.INDEX, bOut, addrFrom); },
|
0x21: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICHi(ChipSet.PIC0.INDEX, bOut, addrFrom); },
|
||||||
0x40: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER0.INDEX, bOut, addrFrom); },
|
0x40: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER0.INDEX, bOut, addrFrom); },
|
||||||
0x41: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER1.INDEX, bOut, addrFrom); },
|
0x41: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER1.INDEX, bOut, addrFrom); },
|
||||||
0x42: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER2.INDEX, bOut, addrFrom); },
|
0x42: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER2.INDEX, bOut, addrFrom); },
|
||||||
|
|
@ -4336,8 +4330,8 @@ ChipSet.aPortOutput5170 = {
|
||||||
0x8D: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageSpare(5, port, bOut, addrFrom); },
|
0x8D: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageSpare(5, port, bOut, addrFrom); },
|
||||||
0x8E: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageSpare(6, port, bOut, addrFrom); },
|
0x8E: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageSpare(6, port, bOut, addrFrom); },
|
||||||
0x8F: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageReg(ChipSet.DMA1.INDEX, 0, port, bOut, addrFrom); },
|
0x8F: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageReg(ChipSet.DMA1.INDEX, 0, port, bOut, addrFrom); },
|
||||||
0xA0: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICL(ChipSet.PIC1.INDEX, bOut, addrFrom); },
|
0xA0: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICLo(ChipSet.PIC1.INDEX, bOut, addrFrom); },
|
||||||
0xA1: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICH(ChipSet.PIC1.INDEX, bOut, addrFrom); },
|
0xA1: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICHi(ChipSet.PIC1.INDEX, bOut, addrFrom); },
|
||||||
0xC0: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAChannelAddr(ChipSet.DMA1.INDEX, 0, port, bOut, addrFrom); },
|
0xC0: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAChannelAddr(ChipSet.DMA1.INDEX, 0, port, bOut, addrFrom); },
|
||||||
0xC2: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAChannelCount(ChipSet.DMA1.INDEX, 0, port, bOut, addrFrom); },
|
0xC2: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAChannelCount(ChipSet.DMA1.INDEX, 0, port, bOut, addrFrom); },
|
||||||
0xC4: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAChannelAddr(ChipSet.DMA1.INDEX, 1, port, bOut, addrFrom); },
|
0xC4: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAChannelAddr(ChipSet.DMA1.INDEX, 1, port, bOut, addrFrom); },
|
||||||
|
|
|
||||||
|
|
@ -139,15 +139,15 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
|
||||||
this.sUserID = this.queryUserID();
|
this.sUserID = this.queryUserID();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the appropriate CPU (and the Debugger, if any)
|
* Find the appropriate CPU (and Debugger and Control Panel, if any)
|
||||||
*/
|
*/
|
||||||
this.cpu = Component.getComponentByType("CPU", this.id);
|
this.cpu = Component.getComponentByType("CPU", this.id);
|
||||||
if (!this.cpu) {
|
if (!this.cpu) {
|
||||||
Component.error("Unable to find CPU component");
|
Component.error("Unable to find CPU component");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dbg = Component.getComponentByType("Debugger", this.id);
|
this.dbg = Component.getComponentByType("Debugger", this.id);
|
||||||
|
this.panel = Component.getComponentByType("Panel", this.id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the Bus component
|
* Initialize the Bus component
|
||||||
|
|
@ -160,6 +160,20 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
|
||||||
var aComponents = Component.getComponents(this.id);
|
var aComponents = Component.getComponents(this.id);
|
||||||
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
|
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
|
||||||
var component = aComponents[iComponent];
|
var component = aComponents[iComponent];
|
||||||
|
/*
|
||||||
|
* I can think of many "cleaner" ways for the Control Panel component to pass its
|
||||||
|
* notice(), println(), etc, overrides on to all the other components, but it's just
|
||||||
|
* too darn convenient to slam those overrides into the components directly.
|
||||||
|
*
|
||||||
|
* Adding more initBus() parameters was another option, but that function is already
|
||||||
|
* looking a bit unwieldy, and Control Panel functionality is a little far afield
|
||||||
|
* from Bus initialization.
|
||||||
|
*/
|
||||||
|
if (this.panel && this.panel.controlPrint) {
|
||||||
|
component.notice = this.panel.notice;
|
||||||
|
component.println = this.panel.println;
|
||||||
|
component.controlPrint = this.panel.controlPrint;
|
||||||
|
}
|
||||||
if (component.initBus) component.initBus(this, this.bus, this.cpu, this.dbg);
|
if (component.initBus) component.initBus(this, this.bus, this.cpu, this.dbg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -557,7 +571,7 @@ Computer.prototype.powerRestore = function(component, stateComputer, fRepower, f
|
||||||
*/
|
*/
|
||||||
if (!component.powerUp(data, fRepower)) {
|
if (!component.powerUp(data, fRepower)) {
|
||||||
if (data) {
|
if (data) {
|
||||||
this.error("Unable to restore state for " + component.type);
|
Component.error("Unable to restore state for " + component.type);
|
||||||
/*
|
/*
|
||||||
* If this is a resume error for a machine that also has a predefined state
|
* If this is a resume error for a machine that also has a predefined state
|
||||||
* AND we're not restoring from that state, then throw away the current state,
|
* AND we're not restoring from that state, then throw away the current state,
|
||||||
|
|
@ -1179,6 +1193,7 @@ Computer.init = function()
|
||||||
|
|
||||||
var eComputer = aeComputers[iComputer];
|
var eComputer = aeComputers[iComputer];
|
||||||
var parmsComputer = Component.getComponentParms(eComputer);
|
var parmsComputer = Component.getComponentParms(eComputer);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We set fSuspended in the Computer constructor because we want to "power up" the
|
* We set fSuspended in the Computer constructor because we want to "power up" the
|
||||||
* computer ourselves, after any/all bindings are in place.
|
* computer ourselves, after any/all bindings are in place.
|
||||||
|
|
|
||||||
|
|
@ -254,11 +254,15 @@ CPU.prototype.powerUp = function(data, fRepower)
|
||||||
this.dbg.init();
|
this.dbg.init();
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* TODO: Once we get rid of those nasty Component method overrides, this test will have to be revised as well
|
* The Computer (this.cmp) knows if there's a Control Panel (this.cmp.panel), and the Control Panel
|
||||||
|
* knows if there's a "print" control (this.cmp.panel.controlPrint), and if there IS a "print" control
|
||||||
|
* but no debugger, the machine is probably misconfigured (most likely, the page simply neglected to
|
||||||
|
* load the Debugger component).
|
||||||
|
*
|
||||||
|
* However, we don't actually need to check all that; it's always safe use println(), regardless whether
|
||||||
|
* a Control Panel with a "print" control is present or not.
|
||||||
*/
|
*/
|
||||||
if (Component.controlPrint) {
|
this.println("No debugger detected");
|
||||||
this.warning("No debugger detected");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.fPowered = true;
|
this.fPowered = true;
|
||||||
|
|
|
||||||
|
|
@ -1562,7 +1562,7 @@ if (DEBUGGER) {
|
||||||
*/
|
*/
|
||||||
if (fUpdateCPU !== false) this.cpu.updateCPU();
|
if (fUpdateCPU !== false) this.cpu.updateCPU();
|
||||||
|
|
||||||
this.updateStatus(fRegs, false);
|
this.updateStatus(fRegs || false, false);
|
||||||
return (this.nCycles > 0);
|
return (this.nCycles > 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2846,8 +2846,8 @@ if (DEBUGGER) {
|
||||||
value = this.cpu.segSS.sel;
|
value = this.cpu.segSS.sel;
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
* I used to alias "PC" to "IP", until I discovered that early (perhaps even ALL?) versions of DEBUG
|
* I used to alias "PC" to "IP", until I discovered that early (perhaps even ALL?) versions of DEBUG.COM
|
||||||
* treat "PC" as an alias for the 16-bit flags register. TODO: Add support for "PC" that matches DEBUG.
|
* treat "PC" as an alias for the 16-bit flags register. TODO: Add support for "PC".
|
||||||
*/
|
*/
|
||||||
case "IP":
|
case "IP":
|
||||||
value = this.cpu.regIP;
|
value = this.cpu.regIP;
|
||||||
|
|
@ -3283,9 +3283,10 @@ if (DEBUGGER) {
|
||||||
*/
|
*/
|
||||||
Debugger.prototype.doClear = function(sCmd)
|
Debugger.prototype.doClear = function(sCmd)
|
||||||
{
|
{
|
||||||
if (Component.controlPrint) {
|
/*
|
||||||
Component.controlPrint.value = "";
|
* TODO: There should be a clear() component method that the Control Panel overrides to perform this function.
|
||||||
}
|
*/
|
||||||
|
if (this.controlPrint) this.controlPrint.value = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -4275,7 +4276,7 @@ if (DEBUGGER) {
|
||||||
/*
|
/*
|
||||||
* Limiting the amount of disassembled code to 256 bytes in non-DEBUG builds is partly to
|
* Limiting the amount of disassembled code to 256 bytes in non-DEBUG builds is partly to
|
||||||
* prevent the user from wedging the browser by dumping too many lines, but also a recognition
|
* prevent the user from wedging the browser by dumping too many lines, but also a recognition
|
||||||
* that, in non-DEBUG builds, Component.println() keeps print output buffer truncated to 8Kb anyway.
|
* that, in non-DEBUG builds, this.println() keeps print output buffer truncated to 8Kb anyway.
|
||||||
*/
|
*/
|
||||||
this.println("range too large");
|
this.println("range too large");
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -613,10 +613,10 @@ Disk.prototype.onLoadDisk = function(sDiskFile, sDiskData, nErrorCode, sDiskPath
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aDiskData.length) {
|
if (!aDiskData.length) {
|
||||||
this.error("Empty disk image: " + this.sDiskName);
|
Component.error("Empty disk image: " + this.sDiskName);
|
||||||
}
|
}
|
||||||
else if (aDiskData.length == 1) {
|
else if (aDiskData.length == 1) {
|
||||||
this.error(aDiskData[0]);
|
Component.error(aDiskData[0]);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* aDiskData is an array of cylinders, each of which is an array of heads, each of which
|
* aDiskData is an array of cylinders, each of which is an array of heads, each of which
|
||||||
|
|
@ -731,7 +731,7 @@ Disk.prototype.onLoadDisk = function(sDiskFile, sDiskData, nErrorCode, sDiskPath
|
||||||
disk = this;
|
disk = this;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error("Disk image error: " + e.message);
|
Component.error("Disk image error: " + e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.fnNotify) {
|
if (this.fnNotify) {
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ function FDC(parmsFDC) {
|
||||||
*/
|
*/
|
||||||
this.pAutoMount = eval("(" + parmsFDC['autoMount'] + ")");
|
this.pAutoMount = eval("(" + parmsFDC['autoMount'] + ")");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error("FDC auto-mount error: " + e.message + " (" + parmsFDC['autoMount'] + ")");
|
Component.error("FDC auto-mount error: " + e.message + " (" + parmsFDC['autoMount'] + ")");
|
||||||
this.pAutoMount = null;
|
this.pAutoMount = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -395,7 +395,7 @@ FDC.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, control)
|
||||||
try {
|
try {
|
||||||
dataValue = eval("({" + sValue + "})");
|
dataValue = eval("({" + sValue + "})");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
fdc.error("FDC option error: " + (e.message || e));
|
Component.error("FDC option error: " + (e.message || e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sDesc = dataValue['desc'];
|
var sDesc = dataValue['desc'];
|
||||||
|
|
@ -745,6 +745,10 @@ FDC.prototype.saveController = function()
|
||||||
/**
|
/**
|
||||||
* initDrive(drive, iDrive, data)
|
* initDrive(drive, iDrive, data)
|
||||||
*
|
*
|
||||||
|
* TODO: Consider a separate Drive class that both FDC and HDC can use, since there's a lot of commonality
|
||||||
|
* between the drive objects created by both controllers. This will clean up overall drive management and allow
|
||||||
|
* us to factor out some common Drive methods (eg, advanceSector()).
|
||||||
|
*
|
||||||
* @this {FDC}
|
* @this {FDC}
|
||||||
* @param {Object} drive
|
* @param {Object} drive
|
||||||
* @param {number} iDrive
|
* @param {number} iDrive
|
||||||
|
|
@ -1933,8 +1937,7 @@ FDC.prototype.doFormat = function(drive)
|
||||||
* NOTE: Since the FDC isn't aware of the extent of the transfer, all readByte() can do is return bytes
|
* NOTE: Since the FDC isn't aware of the extent of the transfer, all readByte() can do is return bytes
|
||||||
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
||||||
*
|
*
|
||||||
* TODO: Research the requirements, if any, for multi-track I/O and determine what if anything needs to be
|
* TODO: Research the requirements, if any, for multi-track I/O and determine what else needs to be done.
|
||||||
* done. At the very least, if it must be supported, there would need to be some head-incrementing somewhere.
|
|
||||||
*
|
*
|
||||||
* @this {FDC}
|
* @this {FDC}
|
||||||
* @param {Object} drive
|
* @param {Object} drive
|
||||||
|
|
@ -1958,7 +1961,11 @@ FDC.prototype.readByte = function(drive, done)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
drive.ibSector = 0;
|
drive.ibSector = 0;
|
||||||
drive.bSector++;
|
/*
|
||||||
|
* We "pre-advance" bSector et al now, instead of waiting to advance it right before the seek().
|
||||||
|
* This allows the initial call to readByte() to perform a seek without triggering an unwanted advance.
|
||||||
|
*/
|
||||||
|
this.advanceSector(drive);
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
done(b, false);
|
done(b, false);
|
||||||
|
|
@ -1981,8 +1988,7 @@ FDC.prototype.readByte = function(drive, done)
|
||||||
* NOTE: Since the FDC isn't aware of the extent of the transfer, all writeByte() can do is accept bytes
|
* NOTE: Since the FDC isn't aware of the extent of the transfer, all writeByte() can do is accept bytes
|
||||||
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
||||||
*
|
*
|
||||||
* TODO: Research the requirements, if any, for multi-track I/O and determine what if anything needs to be
|
* TODO: Research the requirements, if any, for multi-track I/O and determine what else needs to be done.
|
||||||
* done. At the very least, if it must be supported, there would need to be some head-incrementing somewhere.
|
|
||||||
*
|
*
|
||||||
* @this {FDC}
|
* @this {FDC}
|
||||||
* @param {Object} drive
|
* @param {Object} drive
|
||||||
|
|
@ -2010,11 +2016,40 @@ FDC.prototype.writeByte = function(drive, b)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
drive.ibSector = 0;
|
drive.ibSector = 0;
|
||||||
drive.bSector++;
|
/*
|
||||||
|
* We "pre-advance" bSector et al now, instead of waiting to advance it right before the seek().
|
||||||
|
* This allows the initial call to writeByte() to perform a seek without triggering an unwanted advance.
|
||||||
|
*/
|
||||||
|
this.advanceSector(drive);
|
||||||
} while (true);
|
} while (true);
|
||||||
return b;
|
return b;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* advanceSector(drive)
|
||||||
|
*
|
||||||
|
* This increments the sector number; when the sector number reaches drive.nSectors on the current track, we
|
||||||
|
* increment drive.bHead and reset drive.bSector, and when drive.bHead reaches drive.nHeads, we reset drive.bHead
|
||||||
|
* and increment drive.bCylinder.
|
||||||
|
*
|
||||||
|
* @this {FDC}
|
||||||
|
* @param {Object} drive
|
||||||
|
*/
|
||||||
|
FDC.prototype.advanceSector = function(drive)
|
||||||
|
{
|
||||||
|
Component.assert(drive.bCylinder < drive.nCylinders);
|
||||||
|
drive.bSector++;
|
||||||
|
var bSectorStart = 1;
|
||||||
|
if (drive.bSector >= drive.nSectors + bSectorStart) {
|
||||||
|
drive.bSector = bSectorStart;
|
||||||
|
drive.bHead++;
|
||||||
|
if (drive.bHead >= drive.nHeads) {
|
||||||
|
drive.bHead = 0;
|
||||||
|
drive.bCylinder++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* writeFormat(drive, b)
|
* writeFormat(drive, b)
|
||||||
*
|
*
|
||||||
|
|
@ -2085,7 +2120,7 @@ FDC.prototype.intBIOSDiskette = function(addr)
|
||||||
var DL = this.cpu.regDX & 0xff;
|
var DL = this.cpu.regDX & 0xff;
|
||||||
var DH = this.cpu.regDX >> 8;
|
var DH = this.cpu.regDX >> 8;
|
||||||
if (this.dbg && this.dbg.messageEnabled(this.dbg.MESSAGE_FDC) && DL < 0x80) {
|
if (this.dbg && this.dbg.messageEnabled(this.dbg.MESSAGE_FDC) && DL < 0x80) {
|
||||||
this.dbg.message("FDC.intBIOS(AH=" + str.toHexByte(AH) + ",D=" + str.toHexByte(DL) + ",C=" + str.toHexByte(CH) + ",H=" + str.toHexByte(DH) + ",S=" + str.toHexByte(CL) + ",N=" + str.toHexByte(AL) + ") at " + str.toHexAddr(addr - this.cpu.segCS.base, this.cpu.segCS.sel));
|
this.dbg.message("\nFDC.intBIOS(AH=" + str.toHexByte(AH) + ",D=" + str.toHexByte(DL) + ",C=" + str.toHexByte(CH) + ",H=" + str.toHexByte(DH) + ",S=" + str.toHexByte(CL) + ",N=" + str.toHexByte(AL) + ") at " + str.toHexAddr(addr - this.cpu.segCS.base, this.cpu.segCS.sel));
|
||||||
// this.cpu.haltCPU();
|
// this.cpu.haltCPU();
|
||||||
this.cpu.addInterruptReturn(addr, function(fdc, nCycles) {
|
this.cpu.addInterruptReturn(addr, function(fdc, nCycles) {
|
||||||
return function onBIOSDisketteReturn(nLevel) {
|
return function onBIOSDisketteReturn(nLevel) {
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ function HDC(parmsHDC) {
|
||||||
* any disk image "path" properties to process) will take care of the rest.
|
* any disk image "path" properties to process) will take care of the rest.
|
||||||
*/
|
*/
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error("HDC drive configuration error: " + e.message + " (" + parmsHDC['drives'] + ")");
|
Component.error("HDC drive configuration error: " + e.message + " (" + parmsHDC['drives'] + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -779,6 +779,10 @@ HDC.prototype.saveController = function()
|
||||||
/**
|
/**
|
||||||
* initDrive(iDrive, drive, driveConfig, data, fReset)
|
* initDrive(iDrive, drive, driveConfig, data, fReset)
|
||||||
*
|
*
|
||||||
|
* TODO: Consider a separate Drive class that both FDC and HDC can use, since there's a lot of commonality
|
||||||
|
* between the drive objects created by both controllers. This will clean up overall drive management and allow
|
||||||
|
* us to factor out some common Drive methods (eg, advanceSector()).
|
||||||
|
*
|
||||||
* @this {HDC}
|
* @this {HDC}
|
||||||
* @param {number} iDrive
|
* @param {number} iDrive
|
||||||
* @param {Object} drive
|
* @param {Object} drive
|
||||||
|
|
@ -2436,19 +2440,20 @@ HDC.prototype.writeByte = function(drive, b)
|
||||||
* numbers (bSectorBias is 1). Thus, the correct "reset" value for bSector is (1 - bSectorBias), and the correct
|
* numbers (bSectorBias is 1). Thus, the correct "reset" value for bSector is (1 - bSectorBias), and the correct
|
||||||
* limit for bSector is (nSectors + bSectorStart).
|
* limit for bSector is (nSectors + bSectorStart).
|
||||||
*
|
*
|
||||||
|
* @this {HDC}
|
||||||
* @param {Object} drive
|
* @param {Object} drive
|
||||||
*/
|
*/
|
||||||
HDC.prototype.advanceSector = function(drive)
|
HDC.prototype.advanceSector = function(drive)
|
||||||
{
|
{
|
||||||
|
Component.assert(drive.wCylinder < drive.nCylinders);
|
||||||
drive.bSector++;
|
drive.bSector++;
|
||||||
var bSectorStart = (1 - drive.bSectorBias);
|
var bSectorStart = (1 - drive.bSectorBias);
|
||||||
if (drive.bSector >= drive.nSectors + bSectorStart) {
|
if (drive.bSector >= drive.nSectors + bSectorStart) {
|
||||||
drive.bSector = bSectorStart;
|
drive.bSector = bSectorStart;
|
||||||
drive.bHeads++;
|
drive.bHead++;
|
||||||
if (drive.bHeads >= drive.nHeads) {
|
if (drive.bHead >= drive.nHeads) {
|
||||||
drive.bHeads = 0;
|
drive.bHead = 0;
|
||||||
drive.wCylinder++;
|
drive.wCylinder++;
|
||||||
Component.assert(drive.wCylinder < drive.nCylinders);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,8 @@ if (typeof module !== 'undefined') {
|
||||||
* supported in theory, but in practice, they're not.
|
* supported in theory, but in practice, they're not.
|
||||||
*
|
*
|
||||||
* NOTE: Since Memory blocks are low-level objects that have no UI requirements, they do not
|
* NOTE: Since Memory blocks are low-level objects that have no UI requirements, they do not
|
||||||
* inherit from the Component class; so, if you want to use print(), for example, you must
|
* inherit from the Component class; so, if you want to use println(), for example, you must
|
||||||
* rely on class methods like Component.println() rather than object methods like this.println().
|
* use the methods in the Debugger class.
|
||||||
*
|
*
|
||||||
* Because Memory blocks now allow us to have a "sparse" address space, we could choose to
|
* Because Memory blocks now allow us to have a "sparse" address space, we could choose to
|
||||||
* take the memory hit of allocating 4K arrays per block, where each element stores only one byte,
|
* take the memory hit of allocating 4K arrays per block, where each element stores only one byte,
|
||||||
|
|
@ -160,10 +160,6 @@ Memory.prototype = {
|
||||||
* @return {number}
|
* @return {number}
|
||||||
*/
|
*/
|
||||||
readNone: function(off) {
|
readNone: function(off) {
|
||||||
/*
|
|
||||||
* This can happen so frequently that the browser can't come up for air, so it's best to do this only under special circumstances...
|
|
||||||
*/
|
|
||||||
// if (DEBUG) Component.println("readNone(" + str.toHexWord(this.addr + off) + ")");
|
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
|
@ -174,10 +170,6 @@ Memory.prototype = {
|
||||||
* @param {number} v (could be either a byte or word value, since we use the same handler for both kinds of accesses)
|
* @param {number} v (could be either a byte or word value, since we use the same handler for both kinds of accesses)
|
||||||
*/
|
*/
|
||||||
writeNone: function(off, v) {
|
writeNone: function(off, v) {
|
||||||
/*
|
|
||||||
* This can happen so frequently that the browser can't come up for air, so it's best to do this only under special circumstances...
|
|
||||||
*/
|
|
||||||
// if (DEBUG) Component.println("writeNone(" + str.toHexWord(this.addr + off) + "): " + str.toHexWord(v));
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* readByteTArray(off)
|
* readByteTArray(off)
|
||||||
|
|
@ -537,13 +529,13 @@ Memory.prototype = {
|
||||||
if (this.cReadBreakpoints++ === 0) {
|
if (this.cReadBreakpoints++ === 0) {
|
||||||
this.setReadAccess(Memory.afnVerify);
|
this.setReadAccess(Memory.afnVerify);
|
||||||
}
|
}
|
||||||
if (DEBUG) Component.println("read breakpoint added to memory block " + str.toHex(this.addr));
|
if (DEBUG) this.dbg.println("read breakpoint added to memory block " + str.toHex(this.addr));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (this.cWriteBreakpoints++ === 0) {
|
if (this.cWriteBreakpoints++ === 0) {
|
||||||
this.setWriteAccess(Memory.afnVerify);
|
this.setWriteAccess(Memory.afnVerify);
|
||||||
}
|
}
|
||||||
if (DEBUG) Component.println("write breakpoint added to memory block " + str.toHex(this.addr));
|
if (DEBUG) this.dbg.println("write breakpoint added to memory block " + str.toHex(this.addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -559,14 +551,14 @@ Memory.prototype = {
|
||||||
if (!fWrite) {
|
if (!fWrite) {
|
||||||
if (--this.cReadBreakpoints === 0) {
|
if (--this.cReadBreakpoints === 0) {
|
||||||
this.resetReadAccess();
|
this.resetReadAccess();
|
||||||
if (DEBUG) Component.println("all read breakpoints removed from memory block " + str.toHex(this.addr));
|
if (DEBUG) this.dbg.println("all read breakpoints removed from memory block " + str.toHex(this.addr));
|
||||||
}
|
}
|
||||||
Component.assert(this.cReadBreakpoints >= 0);
|
Component.assert(this.cReadBreakpoints >= 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (--this.cWriteBreakpoints === 0) {
|
if (--this.cWriteBreakpoints === 0) {
|
||||||
this.resetWriteAccess();
|
this.resetWriteAccess();
|
||||||
if (DEBUG) Component.println("all write breakpoints removed from memory block " + str.toHex(this.addr));
|
if (DEBUG) this.dbg.println("all write breakpoints removed from memory block " + str.toHex(this.addr));
|
||||||
}
|
}
|
||||||
Component.assert(this.cWriteBreakpoints >= 0);
|
Component.assert(this.cWriteBreakpoints >= 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ Mouse.prototype.powerUp = function(data, fRepower) {
|
||||||
var componentScreen = this.cmp.getComponentByType("Video");
|
var componentScreen = this.cmp.getComponentByType("Video");
|
||||||
if (componentScreen) this.canvasScreen = componentScreen.getCanvas();
|
if (componentScreen) this.canvasScreen = componentScreen.getCanvas();
|
||||||
} else {
|
} else {
|
||||||
this.warning(this.id + ": " + this.sAdapterType + " " + this.idAdapter + " unavailable");
|
Component.warning(this.id + ": " + this.sAdapterType + " " + this.idAdapter + " unavailable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.fActive) {
|
if (this.fActive) {
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,8 @@ Component.subclass(Component, Panel);
|
||||||
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
|
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
|
||||||
* @return {boolean} true if binding was successful, false if unrecognized binding request
|
* @return {boolean} true if binding was successful, false if unrecognized binding request
|
||||||
*/
|
*/
|
||||||
Panel.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, control) {
|
Panel.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, control)
|
||||||
|
{
|
||||||
if (this.cmp && this.cmp.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
if (this.cmp && this.cmp.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
||||||
if (this.cpu && this.cpu.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
if (this.cpu && this.cpu.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
||||||
if (this.kbd && this.kbd.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
if (this.kbd && this.kbd.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
||||||
|
|
@ -84,7 +85,8 @@ Panel.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, control)
|
||||||
* @param {X86CPU} cpu
|
* @param {X86CPU} cpu
|
||||||
* @param {Debugger} dbg
|
* @param {Debugger} dbg
|
||||||
*/
|
*/
|
||||||
Panel.prototype.initBus = function(cmp, bus, cpu, dbg) {
|
Panel.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||||
|
{
|
||||||
this.cmp = cmp;
|
this.cmp = cmp;
|
||||||
this.cpu = cpu;
|
this.cpu = cpu;
|
||||||
this.dbg = dbg;
|
this.dbg = dbg;
|
||||||
|
|
@ -99,7 +101,8 @@ Panel.prototype.initBus = function(cmp, bus, cpu, dbg) {
|
||||||
* @param {boolean} [fRepower]
|
* @param {boolean} [fRepower]
|
||||||
* @return {boolean} true if successful, false if failure
|
* @return {boolean} true if successful, false if failure
|
||||||
*/
|
*/
|
||||||
Panel.prototype.powerUp = function(data, fRepower) {
|
Panel.prototype.powerUp = function(data, fRepower)
|
||||||
|
{
|
||||||
if (!fRepower) {
|
if (!fRepower) {
|
||||||
Panel.init();
|
Panel.init();
|
||||||
}
|
}
|
||||||
|
|
@ -113,7 +116,8 @@ Panel.prototype.powerUp = function(data, fRepower) {
|
||||||
* @param {boolean} fSave
|
* @param {boolean} fSave
|
||||||
* @return {Object|boolean}
|
* @return {Object|boolean}
|
||||||
*/
|
*/
|
||||||
Panel.prototype.powerDown = function(fSave) {
|
Panel.prototype.powerDown = function(fSave)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ RAM.prototype.reset = function() {
|
||||||
}
|
}
|
||||||
if (this.chipset) this.chipset.addCMOSMemory(this.addrRAM, this.sizeRAM);
|
if (this.chipset) this.chipset.addCMOSMemory(this.addrRAM, this.sizeRAM);
|
||||||
} else {
|
} else {
|
||||||
this.error("No RAM allocated");
|
Component.error("No RAM allocated");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -221,11 +221,11 @@ ROM.prototype.onLoadROM = function(sROMFile, sROMData, nErrorCode)
|
||||||
this.aSymbols = rom['symbols'];
|
this.aSymbols = rom['symbols'];
|
||||||
|
|
||||||
if (!this.abROM.length) {
|
if (!this.abROM.length) {
|
||||||
this.error("Empty ROM: " + sROMFile);
|
Component.error("Empty ROM: " + sROMFile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (this.abROM.length == 1) {
|
else if (this.abROM.length == 1) {
|
||||||
this.error(this.abROM[0]);
|
Component.error(this.abROM[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -2478,11 +2478,11 @@ Video.prototype.onLoadSetFonts = function(sFontFile, sFontData, nErrorCode)
|
||||||
var abFontData = eval("(" + sFontData + ")");
|
var abFontData = eval("(" + sFontData + ")");
|
||||||
|
|
||||||
if (!abFontData.length) {
|
if (!abFontData.length) {
|
||||||
this.error("Empty font ROM image: " + sFontFile);
|
Component.error("Empty font ROM image: " + sFontFile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (abFontData.length == 1) {
|
else if (abFontData.length == 1) {
|
||||||
this.error(abFontData[0]);
|
Component.error(abFontData[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -122,21 +122,20 @@ function X86CPU(parmsCPU) {
|
||||||
* "INT 0x00" generated by a divide-by-zero or any other kind of interrupt (nor any interrupt simulated
|
* "INT 0x00" generated by a divide-by-zero or any other kind of interrupt (nor any interrupt simulated
|
||||||
* with "PUSHF/CALLF").
|
* with "PUSHF/CALLF").
|
||||||
*
|
*
|
||||||
* aInterruptReturn is a stack of return address notifications set up by software interrupt notification
|
* aInterruptReturn is a hash of return address notifications set up by software interrupt notification
|
||||||
* functions that want to receive return notifications. A software interrupt function must call
|
* functions that want to receive return notifications. A software interrupt function must call
|
||||||
* cpu.addInterruptReturn(fn).
|
* cpu.addInterruptReturn(fn).
|
||||||
*
|
*
|
||||||
* WARNING: There's no specific mechanism in place to insure that software interrupt return notifications
|
* WARNING: There's no mechanism in place to insure that software interrupt return notifications don't
|
||||||
* don't get "orphaned" and stack up if an interrupt handler bypasses the normal return path (INT 0x24 is
|
* get "orphaned" if an interrupt handler bypasses the normal return path (INT 0x24 is one example of an
|
||||||
* one example of an "evil" software interrupt). So use this feature sparingly, avoid "evil" software
|
* "evil" software interrupt).
|
||||||
* interrupts, and/or add a mechanism to detect and clean up orphans.
|
|
||||||
*/
|
*/
|
||||||
this.aInterruptNotify = [];
|
this.aInterruptNotify = [];
|
||||||
this.aInterruptReturn = [];
|
this.aInterruptReturn = [];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since aReturnNotify is a "sparse array", this global count gives the CPU a quick way of knowing whether
|
* Since aReturnNotify is a "sparse array", this global count gives the CPU a quick way of knowing whether
|
||||||
* or not RETF or IRET instructions need to bother checking the array.
|
* or not RETF or IRET instructions need to bother calling checkInterruptReturn().
|
||||||
*/
|
*/
|
||||||
this.cInterruptReturn = 0;
|
this.cInterruptReturn = 0;
|
||||||
|
|
||||||
|
|
@ -931,27 +930,27 @@ X86CPU.prototype.checkInterruptNotify = function(nInt)
|
||||||
X86CPU.prototype.addInterruptReturn = function(addr, fn)
|
X86CPU.prototype.addInterruptReturn = function(addr, fn)
|
||||||
{
|
{
|
||||||
if (fn !== undefined) {
|
if (fn !== undefined) {
|
||||||
if (this.aInterruptReturn[addr] === undefined)
|
if (this.aInterruptReturn[addr] == null) {
|
||||||
this.aInterruptReturn[addr] = [];
|
|
||||||
this.aInterruptReturn[addr].push(fn);
|
|
||||||
this.cInterruptReturn++;
|
this.cInterruptReturn++;
|
||||||
}
|
}
|
||||||
|
this.aInterruptReturn[addr] = fn;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* checkInterruptReturn(addr)
|
* checkInterruptReturn(addr)
|
||||||
*
|
*
|
||||||
|
* It is expected (though not required) that callers will check cInterruptReturn and avoid calling
|
||||||
|
* this function if the count is zero.
|
||||||
|
*
|
||||||
* @this {X86CPU}
|
* @this {X86CPU}
|
||||||
* @param {number} addr is a physical (non-segmented) address
|
* @param {number} addr is a physical (non-segmented) address
|
||||||
*/
|
*/
|
||||||
X86CPU.prototype.checkInterruptReturn = function(addr)
|
X86CPU.prototype.checkInterruptReturn = function(addr)
|
||||||
{
|
{
|
||||||
var aNotify = this.aInterruptReturn[addr];
|
var fn = this.aInterruptReturn[addr];
|
||||||
if (aNotify !== undefined) {
|
if (fn != null) {
|
||||||
while (aNotify.length > 0) {
|
|
||||||
var fn = aNotify.pop();
|
|
||||||
fn(--this.cInterruptReturn);
|
fn(--this.cInterruptReturn);
|
||||||
}
|
|
||||||
delete this.aInterruptReturn[addr];
|
delete this.aInterruptReturn[addr];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2329,8 +2329,8 @@ var X86OpXX = {
|
||||||
}
|
}
|
||||||
if (nReps--) {
|
if (nReps--) {
|
||||||
/*
|
/*
|
||||||
* NOTE: Storing a word imposes another 4-cycle penalty on the 8088, so consider that if you think the
|
* NOTE: Storing a word imposes another 4-cycle penalty on the 8088, so consider that
|
||||||
* cycle times here are too high.
|
* if you think the cycle times here are too high.
|
||||||
*/
|
*/
|
||||||
this.setSOWord(this.segES, this.regDI, this.regAX);
|
this.setSOWord(this.segES, this.regDI, this.regAX);
|
||||||
this.regDI = (this.regDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & 0xffff;
|
this.regDI = (this.regDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & 0xffff;
|
||||||
|
|
|
||||||
|
|
@ -118,8 +118,8 @@ X86Seg.loadProt = function loadProt(sel, fSuppress)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: This is only the first of many steps toward accurately counting cycles in protected mode;
|
* TODO: This is only the first of many steps toward accurately counting cycles in protected mode;
|
||||||
* I simply noticed that "POP segreg" takes 5 cycles in real mode and 20 in protected mode, so I'm
|
* I simply noted that "POP segreg" takes 5 cycles in real mode and 20 in protected mode, so I'm
|
||||||
* starting with a 15-cycle penalty. Obviously the penalty will be much greater when the load fails.
|
* starting with a 15-cycle difference. Obviously the difference will be much greater when the load fails.
|
||||||
*/
|
*/
|
||||||
this.cpu.nStepCycles -= 15;
|
this.cpu.nStepCycles -= 15;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ global *Buffer* object, as indicated by:
|
||||||
/* global Buffer: false */
|
/* global Buffer: false */
|
||||||
|
|
||||||
And [weblib.js](weblib.js) is appropriate only for client modules, because it contains code that relies on the
|
And [weblib.js](weblib.js) is appropriate only for client modules, because it contains code that relies on the
|
||||||
brower's global *window* object, as indicated by:
|
browser's global *window* object, as indicated by:
|
||||||
|
|
||||||
/* global window: true */
|
/* global window: true */
|
||||||
|
|
||||||
|
|
@ -25,4 +25,4 @@ when running within Node, allowing any other code to test the existence of *wind
|
||||||
|
|
||||||
instead of:
|
instead of:
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {...}
|
if (typeof window !== "undefined") {...}
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ function Component(type, parms, constructor)
|
||||||
*
|
*
|
||||||
if (this.initStep) this.initStep(parms);
|
if (this.initStep) this.initStep(parms);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
this.fnReady = null;
|
this.fnReady = null;
|
||||||
this.fReady = false;
|
this.fReady = false;
|
||||||
this.fBusy = this.fBusyCancel = false;
|
this.fBusy = this.fBusyCancel = false;
|
||||||
|
|
@ -244,12 +245,14 @@ Component.add = function(component)
|
||||||
Component.log = function(s, type)
|
Component.log = function(s, type)
|
||||||
{
|
{
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
var msElapsed, sMsg = (type? (type + ": ") : "") + (s || "");
|
if (s) {
|
||||||
|
var msElapsed, sMsg = (type? (type + ": ") : "") + s;
|
||||||
if (Component.msStart === undefined) {
|
if (Component.msStart === undefined) {
|
||||||
Component.msStart = usr.getTime();
|
Component.msStart = usr.getTime();
|
||||||
}
|
}
|
||||||
msElapsed = usr.getTime() - Component.msStart;
|
msElapsed = usr.getTime() - Component.msStart;
|
||||||
console.log(sMsg? (msElapsed + "ms: " + sMsg.replace(/\n/g, " ")) : "");
|
console.log(msElapsed + "ms: " + sMsg.replace(/\n/g, " "));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -266,13 +269,10 @@ Component.assert = function(f, s)
|
||||||
{
|
{
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
if (!f) {
|
if (!f) {
|
||||||
if (!s) {
|
|
||||||
/*
|
/*
|
||||||
* TODO: An accompanying source file/line number/function call would be nice, if there was a browser-independent way....
|
* TODO: An accompanying source file/line number/function call would be nice, if there was a browser-independent way....
|
||||||
*/
|
*/
|
||||||
s = "assertion failure";
|
Component.log(s || "assertion failure");
|
||||||
}
|
|
||||||
Component.log(s);
|
|
||||||
throw new Error(s);
|
throw new Error(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -363,7 +363,7 @@ Component.getComponents = function(idRelated)
|
||||||
if ((i = idRelated.indexOf('.')) > 0)
|
if ((i = idRelated.indexOf('.')) > 0)
|
||||||
idRelated = idRelated.substr(0, i + 1);
|
idRelated = idRelated.substr(0, i + 1);
|
||||||
else
|
else
|
||||||
idRelated = undefined;
|
idRelated = "";
|
||||||
}
|
}
|
||||||
for (i = 0; i < Component.all.length; i++) {
|
for (i = 0; i < Component.all.length; i++) {
|
||||||
var component = Component.all[i];
|
var component = Component.all[i];
|
||||||
|
|
@ -427,7 +427,7 @@ Component.getComponentByType = function(sType, idRelated, componentPrev)
|
||||||
if ((i = idRelated.indexOf('.')) > 0) {
|
if ((i = idRelated.indexOf('.')) > 0) {
|
||||||
idRelated = idRelated.substr(0, i + 1);
|
idRelated = idRelated.substr(0, i + 1);
|
||||||
} else {
|
} else {
|
||||||
idRelated = undefined;
|
idRelated = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < Component.all.length; i++) {
|
for (i = 0; i < Component.all.length; i++) {
|
||||||
|
|
@ -605,10 +605,7 @@ Component.prototype = {
|
||||||
/**
|
/**
|
||||||
* setBinding(sHTMLClass, sHTMLType, sBinding, control)
|
* setBinding(sHTMLClass, sHTMLType, sBinding, control)
|
||||||
*
|
*
|
||||||
* Component's setBinding() method is intended to be overridden by subclasses. The only
|
* Component's setBinding() method is intended to be overridden by subclasses.
|
||||||
* exception is the Panel component, which passes two special bindings ("clear" and "print")
|
|
||||||
* back to us if no one else accepted them, so that we can redirect all println() requests
|
|
||||||
* to those controls.
|
|
||||||
*
|
*
|
||||||
* @this {Component}
|
* @this {Component}
|
||||||
* @param {string|null} sHTMLClass is the class of the HTML control (eg, "input", "output")
|
* @param {string|null} sHTMLClass is the class of the HTML control (eg, "input", "output")
|
||||||
|
|
@ -623,7 +620,7 @@ Component.prototype = {
|
||||||
if (!this.bindings[sBinding]) {
|
if (!this.bindings[sBinding]) {
|
||||||
this.bindings[sBinding] = control;
|
this.bindings[sBinding] = control;
|
||||||
control.onclick = (function(component) {
|
control.onclick = (function(component) {
|
||||||
return function() {
|
return function clearPanel() {
|
||||||
if (component.bindings['print']) {
|
if (component.bindings['print']) {
|
||||||
component.bindings['print'].value = "";
|
component.bindings['print'].value = "";
|
||||||
}
|
}
|
||||||
|
|
@ -634,16 +631,23 @@ Component.prototype = {
|
||||||
case "print":
|
case "print":
|
||||||
if (!this.bindings[sBinding]) {
|
if (!this.bindings[sBinding]) {
|
||||||
this.bindings[sBinding] = control;
|
this.bindings[sBinding] = control;
|
||||||
control.value = ""; // this was added for Firefox (Safari automatically clears the <textarea> on a page reload, but Firefox does not)
|
|
||||||
/*
|
/*
|
||||||
* TODO: Get rid of these Component method overrides, because they're going to cause issues
|
* HACK: Save this particular HTML element so that the Debugger can access it, too
|
||||||
* if the day ever comes (and it WILL) that we want multiple machines on a single page with their
|
|
||||||
* own Control Panels.
|
|
||||||
*/
|
*/
|
||||||
Component.println = (function(control) {
|
this.controlPrint = control;
|
||||||
return function printControl(s, type) {
|
/*
|
||||||
|
* This was added for Firefox (Safari automatically clears the <textarea> on a page reload,
|
||||||
|
* but Firefox does not).
|
||||||
|
*/
|
||||||
|
control.value = "";
|
||||||
|
this.println = (function(control) {
|
||||||
|
return function printPanel(s, type) {
|
||||||
s = (type !== undefined? (type + ": ") : "") + (s || "");
|
s = (type !== undefined? (type + ": ") : "") + (s || "");
|
||||||
if (!DEBUG) { // in non-DEBUG builds, prevent the <textarea> from getting too large, otherwise printing becomes slower and slower
|
/*
|
||||||
|
* In non-DEBUG builds, prevent the <textarea> from getting too large;
|
||||||
|
* otherwise, printing becomes slower and slower.
|
||||||
|
*/
|
||||||
|
if (!DEBUG) {
|
||||||
if (control.value.length > 8192) {
|
if (control.value.length > 8192) {
|
||||||
control.value = control.value.substr(control.value.length - 4096);
|
control.value = control.value.substr(control.value.length - 4096);
|
||||||
}
|
}
|
||||||
|
|
@ -653,33 +657,22 @@ Component.prototype = {
|
||||||
if (DEBUG) console.log(s);
|
if (DEBUG) console.log(s);
|
||||||
};
|
};
|
||||||
}(control));
|
}(control));
|
||||||
/*
|
/**
|
||||||
* Override Component.notice() with a replacement function that eliminates the web.alertUser() call
|
* Override this.notice() with a replacement function that eliminates the web.alertUser() call
|
||||||
|
*
|
||||||
|
* @this {Component}
|
||||||
|
* @param {string} s
|
||||||
|
* @param {boolean} [fPrintOnly]
|
||||||
|
* @param {string} [id]
|
||||||
*/
|
*/
|
||||||
Component.notice = function(s, fPrintOnly, id) {
|
this.notice = function noticePanel(s, fPrintOnly, id) {
|
||||||
Component.println(s, "notice", id);
|
this.println(s, "notice", id);
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
* HACK: Save this particular HTML element so that the Debugger can access it, too
|
|
||||||
*/
|
|
||||||
Component.controlPrint = control;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
/*
|
|
||||||
* Now that we're giving the Panel component multiple shots at binding its controls,
|
|
||||||
* to relax initialization dependencies, we need to chill when unrecognized requests come in.
|
|
||||||
*
|
|
||||||
if (sHTMLClass == "input") {
|
|
||||||
control.onclick = function() {
|
|
||||||
Component.println("unsupported " + sHTMLType + ": " + sBinding);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
this.log("setBinding(\"" + sHTMLClass + "\",\"" + sHTMLType + "\",\"" + sBinding + "\"): unrecognized binding");
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* log(s, type)
|
* log(s, type)
|
||||||
|
|
@ -695,7 +688,9 @@ Component.prototype = {
|
||||||
* @param {string} [type] is the message type
|
* @param {string} [type] is the message type
|
||||||
*/
|
*/
|
||||||
log: function(s, type) {
|
log: function(s, type) {
|
||||||
if (DEBUG) Component.log(s, type || this.id || this.type);
|
if (DEBUG) {
|
||||||
|
Component.log(s, type || this.id || this.type);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* println(s, type)
|
* println(s, type)
|
||||||
|
|
@ -724,9 +719,9 @@ Component.prototype = {
|
||||||
/**
|
/**
|
||||||
* notice(s, fPrintOnly)
|
* notice(s, fPrintOnly)
|
||||||
*
|
*
|
||||||
* notice() is like println() but implies a need for user notification, which means calling log() isn't good enough, so we alert() as well;
|
* notice() is like println() but implies a need for user notification, which means calling log() isn't good enough,
|
||||||
* however, if Component.println() is overridden, Component.notice will be replaced with the same override, on the assumption that the override
|
* so we alert() as well; however, if Component.println() is overridden, Component.notice will be replaced with the
|
||||||
* is taking care of user notification.
|
* same override, on the assumption that the override is taking care of alerting the user.
|
||||||
*
|
*
|
||||||
* @this {Component}
|
* @this {Component}
|
||||||
* @param {string} s is the message text
|
* @param {string} s is the message text
|
||||||
|
|
@ -736,24 +731,6 @@ Component.prototype = {
|
||||||
notice: function(s, fPrintOnly, id) {
|
notice: function(s, fPrintOnly, id) {
|
||||||
Component.notice(s, fPrintOnly, id || this.id);
|
Component.notice(s, fPrintOnly, id || this.id);
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* warning(s)
|
|
||||||
*
|
|
||||||
* @this {Component}
|
|
||||||
* @param {string} s describes the warning
|
|
||||||
*/
|
|
||||||
warning: function(s) {
|
|
||||||
Component.warning(s);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* error(s)
|
|
||||||
*
|
|
||||||
* @this {Component}
|
|
||||||
* @param {string} s describes the error; an alert() is displayed as well
|
|
||||||
*/
|
|
||||||
error: function(s) {
|
|
||||||
Component.error(s);
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* setError(s)
|
* setError(s)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue