README updates (and some code inspection fixes)

This commit is contained in:
Jeff Parsons 2014-09-28 18:18:53 -07:00 committed by jeffpar
commit 383de1cd8a
12 changed files with 262 additions and 820 deletions

243
README.md
View file

@ -50,70 +50,114 @@ and the original machine are available in the [C1Pjs Documentation](/docs/c1pjs/
<!--BEGIN:EXCLUDE-->
Updating PCjs
===
Developing
Installing PCjs
---
Let's say you just finished developing, testing and deploying version 1.12.1, and you want to start developing some
new features for version 1.13.0. Here are the recommended steps:
1. Create and switch to a new Git development branch (eg, "node_dev")
2. Change the version number in [package.json](/package.json) (eg, to "1.13.0")
3. Run "grunt" (the default task will build fresh "1.13.0" copies of everything under "/versions")
4. Run "grunt promote" to bump the version in all the site's machine XML files to match (ie, to "1.13.0")
You may not want to do the last step until you're ready to start testing the new version. In fact, you may want to
manually edit the version in only a few machine configuration files for testing, leaving the rest set to the previous
version to make comparison runs easier, and then run "grunt promote" when the new version is much closer to being
released.
The following instructions were written for OS X users. However, users of other operating systems should have
no problem following along.
Commit the development branch to GitHub as often as desired. I probably tend to "over-commit", checking in lots of
intermediate changes before I finally decide that the new version is "good enough". But having too much delta history is
probably better than too little. Note that the initial "node_dev" commit may not get pushed to GituHub without first
running:
Open Terminal and `cd` to a directory where you'd like to install *pcjs*, and run the following commands:
git push --set-upstream origin node_dev
git clone git@github.com:jeffpar/pcjs.git pcjs
cd pcjs
npm install
node server.js
One downside to intermediate commits to GitHub is that compiled versions of the sources (such as those in
[/docs/pcjs/demos/](/docs/pcjs/demos/)) may keep changing, and those particular commits are pretty useless.
To temporarily ignore changes to those files:
Now open a web browser and go to `http://localhost:8088/`. You're done!
cd docs/pcjs/demos
git update-index --assume-unchanged components.xsl pc.js pc-dbg.js samples.zip
It's assumed that the OS X Developer Tools (which include Git) have already been installed, as well as
Node and NPM. Node (which now includes NPM) should be downloaded from [nodejs.org](http://nodejs.org/download/).
The current version of Node ([0.10.32](http://nodejs.org/dist/v0.10.32/node-v0.10.32.pkg) at the time of this
writing) should work fine, but version [0.10.26](http://nodejs.org/dist/v0.10.26/node-v0.10.26.pkg)
is what's been used to develop and test PCjs so far.
Also, [server.js](server.js) was originally written using [Express](http://expressjs.com/) v3.x. Since then,
Express v4.x has been released, but `npm install` will make sure that v3.x is installed locally.
The plan is to eventually move development to a newer version of Node, and migrate the PCjs server to a newer
version of Express; there's no desire to remain stuck in the past (well, ignoring the fact that PCjs is the
quintessential "stuck in the past" project), but there's also no urgency to update.
### Building PCjs
Unlike a typical project, where you have to *build* or *configure* or *make* something, PCjs is "ready to run".
That's because both the compiled and uncompiled versions of PCjs are checked into the project, making deployment
to a web server easy.
However, in order to build and test PCjs modifications, you'll want to use [Grunt](http://gruntjs.com/) and the
Grunt tasks defined by [Gruntfile.js](Gruntfile.js).
Although Grunt was installed locally when you ran `npm install`, you'll also want to install the command-line
interface to Grunt; you can install that locally as well, but it's recommended that you install it globally, with
the "-g" option:
sudo npm install grunt-cli -g
Now you can run `grunt` anywhere within the PCjs project to build an updated version. If no command-line arguments
are specified, `grunt` runs the "default" task defined by [Gruntfile.js](Gruntfile.js); that task runs Google's
[Closure Compiler](https://developers.google.com/closure/compiler/) if any of the target files (eg, pc.js, pc-dbg.js,
etc) are out-of date.
To ensure identical compilation results for everyone, a copy of the Closure Compiler has been checked into the
[bin](bin/) folder. This version of Closure Compiler, in turn, requires Java v7.x or later. Use the following
commands to confirm that everything is working properly:
java -version
To see a list of all files that are marked as "assume-unchanged", use this command:
git ls-files -v | grep '^[[:lower:]]'
which should report a version >= 1.7.x; eg:
The same issue would exist for all new files created under "/versions", but fortunately, those files are ignored until
you explicitly add them to Git, which you'll want to do just prior to deployment:
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
git add versions/pcjs/1.13.0/*
git add versions/c1pjs/1.13.0/*
which is when you'll also want to do undo the "assume-unchanged" operation above:
Then run:
cd docs/pcjs/demos
git update-index --no-assume-unchanged components.xsl pc.js pc-dbg.js samples.zip
java -jar bin/compiler.jar --version
Testing
which should report:
Closure Compiler (http://code.google.com/closure/compiler)
Version: v20140407
Built on: 2014/04/07 14:04
If you don't have Java installed, it's recommended that you install the JDK (*not* the JRE), because the JRE may not
update your command-line tools properly. Note that Java is used *only* by the Closure Compiler; none of the PCjs
client or server components use Java.
Newer versions of the Closure Compiler should work as well, and at some point, a newer version will be checked into the
project.
Using PCjs
---
PCjs can now be run from the command-line mode using Node, making it possible to script the application,
### From The Browser
The PCjs web server is little more than a file/directory browser for the PCjs project, plus a collection of APIs.
If a URL corresponds to a PCjs project folder and no "index.html" exists in that folder, the server loads an HTML
template ([common.html](my_modules/shared/templates/common.html)) and generates an "index.html" for that folder.
The contents of the "index.html" will vary depending on the contents of the folder; for example, if the folder
contains a README.md, then that file is converted to HTML and embedded in the "index.html". Similarly, if the folder
contains a machine XML file, that is embedded as well.
### From The Command-Line
The PCjs client app can also be run from the command-line mode using Node, making it possible to script the application,
run a series of automated tests, etc:
cd ./my_modules/pcjs-client/bin
node pcjs
The [pcjs](/my_modules/pcjs-client/bin/pcjs) script in the *bin* directory loads all the PCjs browser scripts listed
in [package.json](/package.json), and then it starts a Node REPL ("read-eval-print loop"). The REPL handles a few
special commands (eg, "load", "quit") and passes anything else to the PCjs Debugger component. If no Debugger component
has been created yet, or if the Debugger didn't recognize the command, then it's passed on to *eval()*, like a good
little REPL.
The [pcjs](my_modules/pcjs-client/bin/pcjs) script in [/my_modules/pcjs-client/bin](my_modules/pcjs-client/bin) loads
all the PCjs browser scripts listed in [package.json](/package.json), and then it starts a Node REPL ("read-eval-print loop").
The REPL handles a few special commands (eg, "load", "quit") and passes anything else to the PCjs Debugger component.
If no Debugger component has been created yet, or if the Debugger didn't recognize the command, then it's passed on to *eval()*,
like a good little REPL.
Use the "load" command to load a JSON machine configuration file. A sample [machine.json](/my_modules/pcjs-client/bin/machine.json)
is provided in the *bin* directory, which is a "JSON-ified" version of the [machine.xml](/configs/pc/machines/5150/mda/64kb/machine.xml)
displayed on the [pcjs.org](http://www.pcjs.org/) home page.
Use the "load" command to load a JSON machine configuration file. A sample [machine.json](my_modules/pcjs-client/bin/machine.json)
is provided in the *bin* directory, which is a "JSON-ified" version of the [machine.xml](configs/pc/machines/5150/mda/64kb/machine.xml)
displayed on the [pcjs.org](/) home page.
The command-line loader creates all the JSON-defined machine components in the same order that the browser creates
XML-defined components. You can also issue the "load" command directly from the command-line:
@ -139,65 +183,72 @@ supports *only* JSON machine configuration files.
I haven't decided whether I'll add support for JSON configuration files to the client, or add some XML-to-JSON conversion
to the server, or both.
Deploying
Debugging PCjs
---
I like to use the AWS Elastic Beanstalk web interface to create a new "development" environment ("pcjs-dev") for testing:
### Server Components
To help test/debug changes to PCjs server components (eg, [DiskDump](my_modules/diskdump/), [HTMLOut](my_modules/htmlout/)),
you can start the server with some additional options; eg:
node server.js --logging --console --debug
The `--logging` option will create a [node.log](/logs/node.log) that records all the HTTP requests, `--debug`
will generate additional debug-only messages (which will also be logged if `--logging` is enabled), and `--console`
will replicate any messages to your console as well.
A complete list of command-line options can be found in [server.js](server.js).
### Client Components
A special parameter ("gort") can be appended to the URL to request uncompiled client source files, making problems
much easier to debug:
http://localhost:8088/?gort=debug
However, the "gort=debug" parameter is unnecessary if the server was started with `--debug`; the server always
serves uncompiled 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:
http://localhost:8088/?gort=release
and the server will serve compiled JavaScript files, regardless whether the server is running in "debug" or "release"
mode.
Updating PCjs
---
### Developing
To start developing features for a new version of PCjs, here are the recommended steps:
1. Save the current production environment ("pcjs-env") as configuration "pcjs-config"
2. Create a new environment ("pcjs-dev") using the "pcjs-config" configuration
3. Wait for the new environment ("pcjs-dev") to start (ie, for its health to become "Green")
4. From Terminal, go to the `~/Sites/pcjs` folder and run `eb branch` followed by `git aws.push`
1. Change the version number in [package.json](/package.json)
2. Run the "grunt promote" task to bump the version in all machine XML files
3. Make changes
4. Run "grunt" to build new versions of the apps (eg, "/versions/pcjs/1.xx/pc.js")
The `eb branch` command will display:
However, you may 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,
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.
The current branch is "node_dev".
Enter an AWS Elastic Beanstalk environment name (auto-generated value is "pcjs-nodedev-env"): pcjs-dev
Do you want to copy the settings from environment "pcjs-env" for the new branch? [y/n]: y
after which we're ready for `git aws.push` to the new "pcjs-dev" environment.
### Testing
See the "[Develop, Test, and Deploy](http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs.sdlc.html)"
AWS documentation for more details.
In the course of testing PCjs, there may be stale "index.html" files that prevent you from seeing application
updates, changes to README.md files, etc. So, before running Node, you may want to "touch" the default HTML template:
On a local machine, the process is similar. If this is a "virgin" machine, you must first install Node and NPM;
see my notes on "[Installing Node (and NPM)](/my_modules/#installing-node-and-npm)" for more details.
Then install and run the PCjs web server files:
[iMac:~/Sites] git clone git@github.com:jeffpar/jsmachines.git pcjs
[iMac:~/Sites] cd pcjs
[iMac:~/Sites/pcjs] git checkout node_dev
[iMac:~/Sites/pcjs] npm install --production
[iMac:~/Sites/pcjs] export PORT=8086 (this is optional)
[iMac:~/Sites/pcjs] node server.js
For a machine that is simply out-of-date, you can do something like this:
[iMac:~/Sites/pcjs] git pull
[iMac:~/Sites/pcjs] npm update --production
[iMac:~/Sites/pcjs] export PORT=8086 (this is optional)
[iMac:~/Sites/pcjs] node server.js
In the second scenario, there may be stale "index.html" files that prevent you from seeing the latest versions
of everything, so before running Node, you may want to do this first:
[iMac:~/Sites/pcjs] touch my_modules/shared/templates/common.html
touch my_modules/shared/templates/common.html
The [HTMLOut](/my_modules/htmlout/) module compares the timestamp of that template file to the timestamp of any
"index.html" and will regenerate the latter if it's out-of-date. There's a TODO to expand that check to include
the timestamp of any local README.md file, but there are many other factors that contribute to stale "index.html"
files, so the safest thing to do is touch the [common.html](/my_modules/shared/templates/common.html) template,
or delete all existing "index.html" files -- either by hand, or by using:
"index.html" and will regenerate the latter if it's out-of-date.
[iMac:~/Sites/pcjs] grunt clean
However, if you included "--production" in your NPM install/update commands, you won't have the necessary grunt
task files. You may not even have grunt itself installed, unless you've previously run:
There's a TODO to expand that check to include the timestamp of any local README.md file, but there are many other
factors that can contribute to stale "index.html" files, so usually the safest thing to do is "touch" the
[common.html](/my_modules/shared/templates/common.html) template, or delete all existing "index.html" files, either
manually or with the Grunt "clean" task:
[iMac:~/Sites/pcjs] sudo npm install grunt-cli -g
Stale "index.html" files may be a non-issue on AWS, because it appears to create a completely new directory
structure when it rebuilds the environment following a `git aws.push` -- but I'm not sure that's always true.
grunt clean
<!--END:EXCLUDE-->

View file

@ -1,649 +1,7 @@
Private Node Modules
===
**my_modules** contains all the *private* **JSMachines** Node modules. It is the counterpart to
**my_modules** contains all the *private* **PCjs** Node modules. It is the counterpart to
**node_modules**, where all the *public* Node modules are installed. Only private Node modules are checked
into GitHub; if we later decide to publish any or all of these on [npmjs.org](http://npmjs.org), then they will
into GitHub; if any of these are later published on [npmjs.org](http://npmjs.org), then they will
be moved to **node_modules** and removed from this folder.
The rest of this file documents some of the early steps involved in porting the **JSMachines** project,
which required a web server running PHP, to the new **PCjs** web server running Node. That includes setting up
my first Node web server and then extending its functionality with these private Node modules.
For more details on the private Node modules stored here, refer to the README.md for each module (which, alas,
may be nothing more than placeholders at this point, but I have good intentions).
Creating My First Node Project
===
Plan A: Fork jsmachines.net -> pcjs.org
---
The original **JSMachines** project assumed a web server running PHP
(eg, [http://jsmachines.net](http://jsmachines.net)). However, to improve client-server integration, reduce
the number of languages/frameworks used, and implement some new features, such as socket-based disk I/O interfaces,
I decided to create a fork, **PCjs**, and port all the server-side PHP to JavaScript, running on a Node web server.
Unfortunately, when I tried to fork my private **JSMachines** project on GitHub, I discovered that you're
not allowed to [fork](https://help.github.com/articles/fork-a-repo) your own projects. Adding to the confusion: GitHub
displays the "Fork" button on my project's home page, and even lets me click it, but then quietly does nothing.
The recommended work-around (as per [this post](http://bitdrift.com/post/4534738938/fork-your-own-project-on-github))
seemed to be:
- Create new project on GitHub
- Clone old project with new name
- Replace new project's "origin URL" with URL for new GitHub project
- Add original project as an "upstream source"
- Push new project to GitHub
Plan B: Branch jsmachines -> node_dev
---
The above seemed a bit clunky, so I decided to branch instead of fork. This new development branch was called
**node_pcjs**, but I've since branched to **node_dev**. I should probably remove the original **node_pcjs** branch,
but for now, it's still there.
Then I pushed the **node_dev** branch to the remote, as per [GitHub](https://help.github.com/articles/pushing-to-a-remote):
[~/Sites/jsmachines] git push origin node_dev
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:jeffpar/jsmachines.git
* [new branch] node_dev -> node_dev
[~/Sites/jsmachines]
That seemed to work fine, so I then created a new folder and cloned the project, as per
[GitHub](https://help.github.com/articles/fetching-a-remote):
[~/Sites] git clone git@github.com:jeffpar/jsmachines.git pcjs
Cloning into 'pcjs'...
remote: Reusing existing pack: 2725, done.
remote: Total 2725 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (2725/2725), 59.48 MiB | 2.67 MiB/s, done.
Resolving deltas: 100% (1543/1543), done.
Checking connectivity... done
Then I checked-out the new branch:
[~/Sites] cd pcjs
[~/Sites/pcjs] git checkout node_dev
Branch node_dev set up to track remote branch node_dev from origin.
Switched to a new branch 'node_dev'
If I have to make any changes to the "master" branch (ie, the original jsmachines project) in the interim,
then after I've pushed those changes to GitHub, I can pull them into the **node_dev** branch like so:
[~/Sites/pcjs] git pull origin master
Installing Node (and NPM)
---
I downloaded the latest Node installation package for my MacBook from [nodejs.org](http://nodejs.org/),
which provided the usual `node` and `npm` commands. Here are the versions they reported:
[~/Sites/pcjs] node -v
v0.10.26
[~/Sites/pcjs] npm -v
1.4.3
I also installed a Node helper on my MacBook called `n` that makes it easy to keep Node up-to-date, per this tip on
[stackoverflow](http://stackoverflow.com/questions/8191459/how-to-update-node-js-npm-and-all-other-dependencies):
1) Clear NPM's cache:
[~/Sites/pcjs] sudo npm cache clean -f
2) Install a little helper called 'n':
[~/Sites/pcjs] sudo npm install -g n
3) Install latest stable NodeJS version:
[~/Sites/pcjs] sudo n stable
Alternatively pick a specific version and install like so:
[~/Sites/pcjs] sudo n 0.8.20
I'm not sure I like the generic name for this command ("n"); what would have been wrong with "node-update"
or "update-node"? Oh well.
Next, I wanted to make sure `npm` was up-to-date. According to
[FAQ on npmjs.org](https://npmjs.org/doc/faq.html#How-do-I-update-npm), that's as easy as:
[~/Sites/pcjs] sudo npm update npm -g
although occasionally `npm` won't be able to update itself, in which case the fallback is:
[~/Sites/pcjs] curl https://npmjs.org/install.sh | sh
So, I made sure `npm` itself, along with `n` and all my other globally installed packages, were up-to-date,
and then I used `n` to make sure I was running the latest stable version of Node:
[~/Sites/pcjs] sudo npm update -g
[~/Sites/pcjs] sudo n stable
[~/Sites/pcjs] node -v
v0.10.26
I've also seen suggestions to run this command before the preceding commands, but I don't know how often this is
recommended:
[~/Sites/pcjs] sudo npm cache clean -f
Next, I ran `npm init`:
[~/Sites/pcjs] npm adduser
Username: jeffpar
Password:
Email: (this IS public) jeff@pcjs.org
npm http PUT http://registry.npmjs.org/-/user/org.couchdb.user:jeffpar
npm http 201 http://registry.npmjs.org/-/user/org.couchdb.user:jeffpar
[~/Sites/pcjs] npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
name: (pcjs)
version: (0.0.0) 0.1.0
description: Node-enabled version of PCjs
entry point: (server.js)
test command:
git repository: (git://github.com/jeffpar/jsmachines.git)
keywords: pcjs,ibm pc,emulator
author: Jeff Parsons <Jeff@pcjs.org>
license: (ISC)
About to write to /Users/Jeff/Sites/pcjs/package.json:
{
"name": "pcjs",
"version": "0.1.0",
"description": "Node-enabled version of PCjs",
"main": "server.js",
"directories": {
"doc": "docs",
"test": "tests"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git://github.com/jeffpar/jsmachines.git"
},
"keywords": [
"pcjs",
"ibm",
"pc",
"emulator"
],
"author": "Jeff Parsons <Jeff@pcjs.org>",
"license": "ISC",
"bugs": {
"url": "https://github.com/jeffpar/jsmachines/issues"
},
"homepage": "https://github.com/jeffpar/jsmachines"
}
Is this ok? (yes)
Next, I installed `express` using `npm install --save express`:
[~/Sites/pcjs] npm install --save express
npm http GET http://registry.npmjs.org/express
...
express@3.4.8 node_modules/express
├── methods@0.1.0
├── merge-descriptors@0.0.1
├── range-parser@0.0.4
├── cookie-signature@1.0.1
├── fresh@0.2.0
├── debug@0.7.4
├── buffer-crc32@0.2.1
├── cookie@0.1.0
├── mkdirp@0.3.5
├── commander@1.3.2 (keypress@0.1.0)
├── send@0.1.4 (mime@1.2.11)
└── connect@2.12.0 (uid2@0.0.3, pause@0.0.1, qs@0.6.6, bytes@0.2.1, raw-body@1.1.2, batch@0.5.0, negotiator@0.3.0, multiparty@2.2.0)
This added the following lines to my "package.json" file:
"dependencies": {
"express": "~3.4.8"
}
Then I created a test "server.js" in the root of the project:
var http = require("http");
var express = require("express");
var app = express();
app.get("/", function(req, res) {
res.end("Testing");
});
http.createServer(app).listen(3000);
and ran `node server.js` and verified that all was working as expected.
Creating My First Node Module
---
The first module I decided to write was a port of the diskconv.php script I'd written to convert disk images to/from
JSON. I decided to call this new module **DiskDump**, since it will output disk images in a variety of formats, although
initially only as JSON.
[~/Sites/pcjs/my_modules] mkdir diskdump
[~/Sites/pcjs/my_modules] cd diskdump
[~/Sites/pcjs/my_modules/diskdump] npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
name: (diskdump)
version: (0.0.0) 0.1.0
description: Convert disk images to/from JSON
entry point: (index.js)
test command:
git repository:
keywords:
author: Jeff Parsons <Jeff@pcjs.org>
license: (ISC)
About to write to /Users/Jeff/Sites/pcjs/my_modules/diskdump/package.json:
{
"name": "diskdump",
"version": "0.1.0",
"description": "Convert disk images to/from JSON",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jeff Parsons <Jeff@pcjs.org>",
"license": "ISC"
}
Is this ok? (yes)
Next, I followed the steps outlined [here](http://www.anupshinde.com/posts/how-to-create-nodejs-npm-package/) to
create a package skeleton with a CLI (command-line interface).
Filtering Web Server Requests
---
The next module I created was [HTMLOut](/my_modules/htmlout/), which provides a filter() function for the Express module,
taking an early crack at the server's HTTP requests.
If the request is for a directory, **HTMLOut** builds an "index.html" from a common HTML template file, and then saves
the file in that directory, so that future requests can be served by the Express static() function. The HTML template
file can specify a variety of replacement tokens, including a reference to a "README.md" file in the same directory,
which **HTMLOut** will load and pass to the private **MarkOut** Node module for conversion from Markdown to HTML.
Similarly, if the URL is an API request, **HTMLOut** will direct the request to the appropriate private Node module
(eg, **DiskDump** or **FileDump**).
What's The Right Way To Incorporate Node Module Fixes?
---
My current version of Express was 3.4.8, and looking at its dependencies in package.json, it wanted "fresh" v0.2.0.
Unfortunately, there seemed to be a problem with Safari and that version of "fresh", occasionally resulting in
blank pages, as discussed [here](http://stackoverflow.com/questions/18811286/nodejs-express-cache-and-304-status-code):
Safari sends Cache-Control: max-age=0 on reload. Express (or more specifically, Express's dependency, node-fresh)
considers the cache stale when Cache-Control: no-cache headers are received, but it doesn't do the same for
Cache-Control: max-age=0.
Further investigation revealed that [node-fresh](https://github.com/visionmedia/node-fresh) v0.2.1 added a fix for
that problem. But what was the right (or best) way to incorporate that fix into my local Express installation?
I decided to hand-edit the "fresh" dependency in Express' package.json and then run "npm update" in the Express folder.
That pulled in the newer "fresh" module. But I noticed that other modules that Express depends on include their OWN
version of "fresh", which were also locked at v0.2.0. Even after creating an "npm-shrinkwrap.json" and hand-editing
it, "npm update" refused to upgrade them from v0.2.0. I could edit the package.json files in each of the Express
"connect" and "send" folders, run "npm update" in those folders, and force v0.2.1 that way, but as soon as I ran another
"npm update" in the root, those folders reverted to v0.2.0 again.
However, this all turned out to be moot. The "Cache-Control: max-age=0" work-around added to "fresh" v0.2.1 was later
backed-out in v0.2.2. And I discovered that the "blank page" problem went away at the same time I added trailing-slash
redirects (see below), so there was likely a connection. The underlying issue with Safari is discussed in more detail
[here](https://github.com/visionmedia/node-fresh/issues/8); it seems likely the problem wasn't related to "fresh" after all.
Problems With Directory URLs and Slashes
---
I discovered that I needed to install "express-slash", enable Express "strict routing", and make HTMLOut.filter()
pass on directory requests that didn't include a trailing slash, so that the Node web server could call slash() and
trigger a trailing-slash redirect. This is apparently what apache's "mod_dir" module does automatically, and why
I never had a problem with apache. Without trailing slashes on directories, client-side requests for files relative to
those "slash-less" directories can fail. More details on this issue can be found in [htmlout.js](htmlout/lib/htmlout.js).
npm install express-slash --save
Moving from Make to Grunt
---
Step 1:
sudo npm install grunt-cli -g
Step 2:
npm install grunt --save-dev
which automatically adds the following to my package.json:
"devDependencies": {
"grunt": "^0.4.3"
}
Step 3: Create a basic Gruntfile.js:
module.exports = function(grunt) {
grunt.initConfig({
});
grunt.registerTask("default", []);
};
Step 4: Install some grunt modules; eg:
npm install grunt-contrib-uglify --save-dev
Step 5: Add a task (eg, uglify):
module.exports = function(grunt) {
grunt.initConfig({
uglify: {
dist: {
src: "dist/myfile.js",
dest: "dist/myfile.min.js"
}
}
});
grunt.loadNpmTasks("grunt-contrib-uglify");
grunt.registerTask("default", ["uglify"]);
};
However, while all of the above is a very nice example, I'm not really interested in uglify.
I use Google's Closure Compiler, so I needed to do this instead:
npm install grunt-closure-tools --save-dev
There was also an NPM module called "grunt-closure-compiler", but it hadn't been updated as recently, and from
the examples it provided, it wasn't clear that it included support for all the Closure Compiler options, like
"output_wrapper", so I went with "grunt-closure-tools", even though it also contains support for other tools that
I'm not currently using.
So now my package.json includes:
"devDependencies": {
"grunt": "^0.4.3",
"grunt-closure-tools": "^0.9.4"
}
Optional Node Modules
===
replace
---
I use the Node "replace" module to perform project-wide search-and-replace operations on files; eg:
node node_modules/replace/bin/replace.js '(<machine.*class)="c1pjs"' '$1="c1p"' . -r --include=*.xml --preview
node node_modules/replace/bin/replace.js '(<machine.*class)="pcjs"' '$1="pc"' . -r --include=*.xml --preview
node node_modules/replace/bin/replace.js '(href="/versions/c1pjs)/[^/]*/(.*)' '$1/1.12.1/$2' . -r --include=*.xml --preview
node node_modules/replace/bin/replace.js '(href="/versions/pcjs)/[^/]*/(.*)' '$1/1.12.1/$2' . -r --include=*.xml --preview
Most people probably install modules like this globally, but I'd rather just define a command-line alias
("replace" => "node node_modules/replace/bin/replace.js") instead of cluttering my system-level directories.
Testing with Azure
===
> NOTE: I've since abandoned Azure in favor of AWS Elastic Beanstalk, because Amazon's service has a simpler UI,
provides more control over the virtual machine environment (you can even log into the machine via SSH), and
the logging services for Node on AWS are more reliable. I also wrote a short [blog post](/blog/2014/03/30/)
on some of my frustrations with Azure.
I subscribed to Azure (formerly Windows Azure, now [Microsoft Azure](http://azure.microsoft.com/)), and started
watching this YouTube video "[Lightning nodejs dev in Windows Azure](http://www.youtube.com/watch?v=WbtV1bX_m2I)"
by Glenn Block ([@gblock](http://twitter.com/gblock)). I was glad to see that he used a Mac, because a number of
other Azure videos on Youtube were made using Windows.
The first recommendation was to install the "azure-cli" command-line tools:
sudo npm install azure-cli -g
To display available commands:
azure
To connect the command-line tools to my Azure account (after setting my default browser to Chrome, since I used
Chrome to set up my Azure account and browse the Azure portal):
azure account download
To import my acount info:
azure account import ~/Downloads/Pay-As-You-Go-3-30-2014-credentials.publishsettings
To create a site, the video recommends:
azure site create pcjs --git
However, I'm holding off until I understand how to link a new Azure site deployment with an existing GitHub repository,
as discussed [here](http://www.windowsazure.com/en-us/documentation/articles/web-sites-publish-source-control/),
because the above command appears intended for new project folders, which are then associated with a remote Azure-hosted
Git repository -- not what I need or want.
The following command would show the remote Azure repository:
git remote -v
In my case, that command shows:
origin git@github.com:jeffpar/jsmachines.git (fetch)
origin git@github.com:jeffpar/jsmachines.git (push)
The following command would then be used to push updates to Azure:
git push azure master
Although in my case, I'm guessing it would be:
git push origin master
Or, rather:
git push origin node_dev
Since my local "pcjs" project is based on the **node_dev** branch.
If I was using an Azure-hosted Git repository, I could then run:
azure site browse
because the `git push azure master` command would have triggered a website update.
The video goes on to show how I can specify the version Node I want Azure to use, by adding the
following to my "package.json":
"engines": {
"node": "0.8.x"
}
This command:
azure site deployment list
will list all the deployments so far, any one of which can be redeployed like so:
azure site deployment redeploy xxx
The video finally gets that what I *really* care about, which is deploying via GitHub. This command
lists some of the commands we care about:
azure site create --help
To create a site from a repository on GitHub:
azure site create pcjs --github
JavaScript Coding Conventions
===
This is not intended to be an exhaustive list. It just lists a few things that came to mind, and I'll
probably update it over time.
Tabs
---
I've configured my IDE (PhpStorm) to NEVER use tab characters in .js files (spaces only) and to
ALWAYS use tab characters in almost every other type of text file. This is largely because when a web
browser displays a JavaScript file (either in the main window or in the Developer Tools window), tabs
usually screw up the formatting, which I find annoying when I'm debugging. XML files, on the other hand,
are usually reformatted by the browser, so in those cases, I opt for smaller files and use real tabs.
Moreover, most of the JavaScript delivered by a production server will have been pre-compiled by Google's
Closure Compiler, which completely eliminates all non-essential whitespace, so this is really a development
preference, with little to no impact on production files.
Regardless of the choice of tab character however, I almost always use 4-column tab stops, except
in legacy .asm files, where 8-column tab stops were the norm. I know that 2-column tab stops have
recently become "all the rage," especially in Node projects; NPM, for example, will rewrite package.json
files, replacing all the 4-column tabs with 2-column tabs, and I don't fight that trend -- I just ignore it.
JSDoc
---
I've taken a great deal of care to "[JSDoc](http://usejsdoc.org/)-ify" nearly all my JavaScript code, not
because I want to be able to generate documentation (although that's something to think about), but because
it's the only way to tell both Google's Closure Compiler and my IDE (PhpStorm) exactly what data
types are passed into/out of every function. The goals are to minimize the number of "code inspection"
warnings in the IDE and produce warning-free compilations.
In order to use the Closure Compiler's ADVANCED_OPTIMIZATIONS option and get maximum performance
(and maximum "minification", sometimes called "uglification"), every function and its parameters needs to
be fully typed; otherwise, the Compiler will generate WAY too many warnings/errors -- at least, that was the
case when I first started using it a couple of years ago.
So, I've adopted a zero-tolerance policy for warnings: no check-ins allowed if the Closure Compiler generates
even a SINGLE warning.
I'm not sure the [JSDoc](http://usejsdoc.org/) folks and the
[Closure Compiler](https://developers.google.com/closure/compiler/docs/js-for-compiler) are totally in sync on
everything. And then there's [PhpStorm](http://www.jetbrains.com/phpstorm/webhelp/creating-jsdoc-comments.html),
whose code inspections occasionally fail; sometimes a bogus code inspection warning can be fixed with some
additional JSDoc @name or @class annotations, but not always.
In any case, the subset of variable and function type declarations I use works pretty well across the board;
code inspection warnings are allowed in the IDE, as long as they are clearly erroneous (or clearly innocuous).
Braces, Parentheses, etc.
---
Most of my opening braces appear at the end of the line containing the associated "if", "while", "for", "switch",
"function" etc, preceded by a single space. And most of my opening parentheses are also preceded by a single space,
except when following "function" or a function name, in which case there is NO space. This is just an historical
preference, dating back to my BASIC and C programming days; it's not that those preferences matter anymore, it's just
that I see no reason to change them.
I'm not obsessed with these conventions. Sometimes, for example, I'll write a bunch of code where the opening
brace of every function body begins underneath the "function" keyword, because the extra whitespace can make the
file a bit more readable. It may sometimes depend on my mood, but I do try to be consistent within a given file
at least.
Variable Names
---
I still tend to follow Charles Simonyi's "[Hungarian](http://en.wikipedia.org/wiki/Hungarian_notation)" naming
conventions -- or rather, a naming convention loosely inspired by Hungarian. I know lots of people sneer at
those conventions and think they're useless, and all I can say is, they're wrong: they are not useless to ME.
I admit they may be useless to anyone who has a phenomenal memory and can remember that an obscure variable named
"foo" was initialized with a string or a number, or who has an IDE that can answer that question with the press
of a key (or two), but for me, with my non-phenomenal memory and lazy fingers, I prefer being able to simply
look at a variable to immediately know what *type* of data it contains, if nothing else.
I rarely name a string or numeric variable something vague like "foo." At worst, I would name it "sFoo" if it
was a string or "iFoo" if it was a number (or possibly "nFoo" or "cFoo" if it represented a total of Foos or a
counter of Foos). And if a string or numeric variable has a very short-term use, I often just call it "s" or "i"
(or "n").
As I mention [below](./#quotation-marks), I still tend to distinguish single characters from strings too,
which means I may sometimes prefix character variables with "ch" and character counters with "cch".
Of course, these letter prefixes like "s" and "n" are irrelevant if you already give your variables meaningful
names like "nameOfPerson" or "numberOfPeople". And that's fine -- I do that sometimes, too. But in general,
I still prefer variable names like "sPerson" and "nPeople".
I don't try to come up with special prefixes for Objects. If there's a Person object, for example, I'll probably
use colloquial names like "personHere" or "personThere". I am stricter about Arrays though: I prefix array variables
with "a", arrays of strings and numbers with "as" and "ai" (or "an"), and arrays of arrays with "aa". As for Arrays
of anything else, I usually don't bother with anything more than an "a" prefix.
Quotation Marks
---
Coming from a long C background, I prefer to use double-quotes around multi-character strings and single quotes
around single-character strings. While the reasons for doing so are largely historical and currently irrelevant,
characters are STILL the building blocks of strings, and even the JavaScript String class contains methods that
deal with individual characters (eg, charCodeAt() and fromCharCode()). So for any code that knowingly deals with
single characters, I like to reinforce that distinction with single quotes.
Also, to emphasize that an object property name isn't really a string, I tend to use single quotes around property
names as well. I realize that the JSON standard insists on property names with double-quotes, but functions like
JSON.stringify() take care of that for us -- besides, I find that aspect of the JSON standard to be rather annoying
(not to mention JSON's disapproval of comments).
Obviously, it's possible to set and get object properties without any quotes at all, as in:
obj.prop = true;
instead of:
obj['prop'] = true;
but that works only if the property name conforms to the same syntax that variable names use. Also, the "dot"
syntax can create problems for code compiled with Google's Closure Compiler (using ADVANCED_OPTIMIZATIONS),
because it likes to rename "dot" property names to smaller "minified" property names. Which means if you
need to export your objects as JSON later, or if you ever need to access a property using an externally defined
string, you must avoid the "dot" syntax.
However, if an object and all its properties are purely internal, there's usually no reason not to use it:
obj = {foo: "old", modified: false};
obj.foo = "new";
obj.modified = true;
I break my own quoting rules slightly when dealing with strings that *contain* double-quotes, since it's more readable
to put double-quotes inside single-quoted strings than to "escape" every double-quote with a backslash.
For code that was originally written in PHP and later ported to JavaScript, there was a tendency in the original
code to always use double-quotes around strings and "escape" double-quotes regardless, and that tendency may linger
in code I didn't feel like rewriting much, but the tendency was due more to idiosyncrasies of PHP than any convention
of mine; for example:
- single-quoted PHP strings may not include any escaped characters (except for single-quote and backslash)
- single-quoted PHP strings cannot resolve references to string variables (eg, "the value of foo is {$foo}")
Because of PHP's restrictions on single-quoted strings, I tended to avoid them. However, in JavaScript, the
first restriction isn't true, and the second isn't even a feature of the language, so they have no bearing on the use
of single-quoted strings in JavaScript.
Arrays
---
In [this article](http://stackoverflow.com/questions/8668174/indexof-method-in-an-object-array), it's asserted,
without disagreement, that searching arrays of objects for a particular object is best performed with code that looks
like this:
pos = myArray.map(function(e) { return e.hello; }).indexOf('stevie');
I disagree. Depending on how often that function is called, creating a new array by iterating over every element
of the original array, and doing that every time you want to search for an array object with a property (eg, `hello`)
equal to some value (eg, 'stevie'), is a bad idea; I don't care how fast your JavaScript engine is or how fantastic
your garbage collector is.
My preferred approach is to create parallel arrays: one array for each property that you might want to search on, and
another array of objects that contain all the other object properties. Then searching doesn't involve creating new
arrays:
pos = myArrayOfHello.indexOf('stevie');
Yes, it's not quite as *clean* as one, unified array of objects, and yes, it would be nicer if the JavaScript Array
class had better search methods, but I think this is the right trade-off given the current reality.

View file

@ -72,8 +72,8 @@ var fCache = true;
var fConsole = false;
/*
* fServerDebug controls debug console messages; it is false by default and can be enabled using the setOptions()
* 'debug' property (or from the command-line interface using "--debug").
* 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").
*/
var fServerDebug = false;
@ -262,8 +262,11 @@ function HTMLOut(sDir, sFile, fRebuild, req, done)
* of fDebug to simply never cache, instead of always rebuilding the cache.
*
* if (this.fDebug) this.fRebuild = true;
*
* Note that a production server should not need the GORT_REBUILD command, so we accept
* it only if fServerDebug is true.
*/
if (net.hasParm(net.GORT_COMMAND, net.GORT_REBUILD, req)) {
if (fServerDebug && net.hasParm(net.GORT_COMMAND, net.GORT_REBUILD, req)) {
req.query[net.GORT_COMMAND] = undefined;
this.fRebuild = true;
}
@ -887,9 +890,15 @@ HTMLOut.prototype.getVersion = function(sToken, sIndent, aParms)
{
/*
* Use the same test that processMachines() uses for setting fCompiled: if we're not using compiled code,
* then we should be using "current" CSS and template files (as opposed to version-specific template files) as well.
* then we should be using "current" CSS and template files (as opposed to version-specific template files).
*
* NOTE: I used to create a symlink in each app's "versions" directory (eg, /versions/pcjs/current ->
* ../../my_modules/shared/templates), so that when fDebug was true, I could simply insert "current" in
* place of a version number. However, that symlink didn't get added to the repository, and I'm not sure
* all operating systems would deal with it properly even if was added, so now I'm treating the "version"
* token as the equivalent of a symlink here.
*/
this.aTokens[sToken] = this.fDebug? "current" : pkg.version;
this.aTokens[sToken] = this.fDebug? "../../my_modules/shared/templates" : pkg.version;
};
/**
@ -1432,6 +1441,8 @@ HTMLOut.prototype.getManifestXML = function(sToken, sIndent, aParms)
case "default":
sDefault = matchParams[2];
break;
default:
break;
}
}
if (sLabel) {

View file

@ -386,6 +386,7 @@ MarkOut.prototype.convertMD = function(sIndent)
*/
var aMatch;
var re = /(^|\n)( ? ?)([\*+-]|[0-9]+\.)([^\n]*\n)([ \t]+[^\n]*\n|\n)+([ \t]+[^\n]+)/g;
//noinspection UnnecessaryLocalVariableJS
var sMDOrig = sMD;
while ((aMatch = re.exec(sMDOrig))) {
var sReplace = aMatch[0].replace(/\n\n/g, "\n\t\n");

View file

@ -6,12 +6,12 @@ Structure
All the code for PCjs is contained in the following JavaScript files, which roughly divide the
functionality into major PC components, aka "devices". However, not every file implements a device,
and "component" is an overloaded term, since *[Component](/docs/pcjs/component/)* is also the name of
the shared base class used for most PCjs objects (see [component.js](../../shared/lib/component.js)).
the shared base class used for most PCjs devices (see [component.js](../../shared/lib/component.js)).
So it's best to refer to these files generically as "modules", and more specifically as "device modules"
whenever they implement a specific device (or set of devices, in the case of [*Chipset*](/docs/pcjs/chipset/)).
Examples of non-device modules include UI modules like [panel.js](panel.js) and [debugger.js](debugger.js),
and sub-modules like [x86code.js](x86code.js), [x86mode.js](x86mode.js) and [x86help.js](x86help.js)
and sub-modules like [x86opxx.js](x86opxx.js), [x86mods.js](x86mods.js) and [x86help.js](x86help.js)
that separate the CPU functionality of [x86.js](x86.js) into more manageable pieces.
These modules should always be loaded or compiled in the order listed by the *pcJSFiles* property in
@ -32,11 +32,14 @@ At the time of this writing, the order is:
* [pcjs-client/bus.js](bus.js)
* [pcjs-client/mem.js](mem.js)
* [pcjs-client/cpu.js](cpu.js)
* [pcjs-client/x86defs.js](x86defs.js)
* [pcjs-client/x86help.js](x86help.js)
* [pcjs-client/x86code.js](x86code.js)
* [pcjs-client/x86mode.js](x86mode.js)
* [pcjs-client/x86.js](x86.js)
* [pcjs-client/x86seg.js](x86seg.js)
* [pcjs-client/x86cpu.js](x86cpu.js)
* [pcjs-client/x86grps.js](x86grps.js)
* [pcjs-client/x86help.js](x86help.js)
* [pcjs-client/x86mods.js](x86mods.js)
* [pcjs-client/x86op0f.js](x86op0f.js)
* [pcjs-client/x86opxx.js](x86opxx.js)
* [pcjs-client/chipset.js](chipset.js)
* [pcjs-client/rom.js](rom.js)
* [pcjs-client/ram.js](ram.js)
@ -55,16 +58,10 @@ At the time of this writing, the order is:
Some of the modules *can* be reordered or even omitted (eg, [debugger.js](debugger.js) or
[embed.js](../../shared/lib/embed.js)), but you should observe the following:
* [component.js](../../shared/lib/component.js) should be listed before any module that extends [*Component*](/docs/pcjs/component/)
* [component.js](../../shared/lib/component.js) must be listed before any module that extends [*Component*](/docs/pcjs/component/)
* [panel.js](panel.js) should be loaded early to initialize the Control Panel (if any) as soon as possible
* [computer.js](computer.js) should be the last device module, as it supervises and notifies all the other device modules
To minimize ordering requirements, the init() handlers and constructors of all modules should avoid
referencing other modules. Device modules should define an initBus() notification handler, which the
[*Computer*](/docs/pcjs/computer/) will call after it has created/initialized the *Bus* object.
What's Next
---
EGA support. I've added the infrastructure for EGA I/O operations, but there's no "meat" yet. All the EGA
code is in [video.js](video.js), alongside the CGA and MDA support, but EGA functionality is pretty isolated; you have
to set the "model" attribute of the video component to "ega" to enable it.

View file

@ -1713,12 +1713,14 @@ ChipSet.prototype.toggleSwitch = function(control)
var asParts = sID.split("-");
var b = (0x1 << (parseInt(asParts[1], 10) - 1));
switch (asParts[0]) {
case "sw1":
this.sw1Init = (this.sw1Init & ~b) | (f? 0 : b);
break;
case "sw2":
this.sw2Init = (this.sw2Init & ~b) | (f? 0 : b);
break;
case "sw1":
this.sw1Init = (this.sw1Init & ~b) | (f? 0 : b);
break;
case "sw2":
this.sw2Init = (this.sw2Init & ~b) | (f? 0 : b);
break;
default:
break;
}
this.updateSwitchDesc();
};

View file

@ -72,34 +72,37 @@ var PREFETCH = false;
/**
* @define {boolean}
*
* FASTDISABLE turns on memory-function switching to dynamically disable
* memory accesses whenever the CPU wants to disable spurious memory reads
* (or stale memory writes, which are worse). If FASTDISABLE is false, then
* the code falls back to setting/testing internal OP_NOREAD and OP_NOWRITE
* CPU opFlags as needed.
* FASTDISABLE turns on memory-function switching to dynamically disable memory accesses whenever the CPU wants
* to disable spurious memory reads (which are mostly harmless) or stale memory writes (which tend to be destructive
* and are NOT mostly harmless).
*
* At the moment, it seems that FASTDISABLE is a bit slower than relying on
* the OP_NOREAD/OP_NOWRITE flags, so it's turned off.
* If FASTDISABLE is false, then the code falls back to setting/testing internal OP_NOREAD and OP_NOWRITE opFlags
* as needed.
*
* At the moment, it seems that FASTDISABLE is a bit slower than relying on the OP_NOREAD/OP_NOWRITE flags, so it's
* turned off; apparently, I was a bit too optimistic calling it "FAST". But your mileage may vary, depending on the
* browser and its version.
*
* See the Bus component for details.
* See the X86CPU component for details, since it is the CPU, not the underlying Bus or Memory components, that needs
* to be able to do this.
*/
var FASTDISABLE = false;
/**
* @define {boolean}
*
* FATARRAYS is a Closure Compiler compile-time option that allocates 1 number per byte
* for Memory blocks; wasteful, but slightly faster.
* FATARRAYS is a Closure Compiler compile-time option that allocates 1 number per byte for Memory blocks;
* wasteful, but potentially slightly faster.
*
* See the Memory component for details.
*/
var FATARRAYS = false;
/**
* TYPEDARRAYS enables use of typed arrays for Memory blocks. This used to be a compile-time
* option, but since I've added memory access functions for typed arrays (see Memory.afnTArray),
* I can turn the support on dynamically now. Originally, I didn't see much of a speed increase
* over the original (non-typed) implementation, but that will probably change over time.
* TYPEDARRAYS enables use of typed arrays for Memory blocks. This used to be a compile-time * option, but since I've
* added memory access functions for typed arrays (see Memory.afnTArray), I can turn the support on dynamically now.
* Originally, I didn't see much of a speed increase over the original (non-typed) implementation, but that will probably
* change over time.
*
* See the Memory component for details.
*/

View file

@ -439,20 +439,22 @@ Mouse.prototype.clickMouse = function(iButton, fDown) {
if (this.isActive()) {
var sDiag;
switch (iButton) {
case 0:
if (this.fButton1 != fDown) {
this.fButton1 = fDown;
sDiag = DEBUGGER ? ("mouse button1 " + (fDown ? "dn" : "up")) : null;
this.sendPacket(sDiag);
}
break;
case 2:
if (this.fButton2 != fDown) {
this.fButton2 = fDown;
sDiag = DEBUGGER ? ("mouse button2 " + (fDown ? "dn" : "up")) : null;
this.sendPacket(sDiag);
}
break;
case 0:
if (this.fButton1 != fDown) {
this.fButton1 = fDown;
sDiag = DEBUGGER ? ("mouse button1 " + (fDown ? "dn" : "up")) : null;
this.sendPacket(sDiag);
}
break;
case 2:
if (this.fButton2 != fDown) {
this.fButton2 = fDown;
sDiag = DEBUGGER ? ("mouse button2 " + (fDown ? "dn" : "up")) : null;
this.sendPacket(sDiag);
}
break;
default:
break;
}
}
};

View file

@ -316,6 +316,9 @@ SerialPort.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, cont
serial.sendRBR([charCode]);
};
return true;
default:
break;
}
return false;
};

View file

@ -3158,6 +3158,8 @@ Video.prototype.getAccess = function()
case Card.GRC.DATAROT.XOR:
nWriteAccess = Card.ACCESS.WRITE.MODE0XOR;
break;
default:
break;
}
card.nDataRotate = regDataRotate & Card.GRC.DATAROT.COUNT;
}
@ -3463,6 +3465,8 @@ Video.prototype.checkMode = function(fForce)
card.sizeBuffer = cbBufferText;
nMode = (this.nMonitorType == ChipSet.MONITOR.MONO? Video.MODES.CGA_80X25_BW : Video.MODES.CGA_80X25);
break;
default:
break;
}
var fSEQDotClock = (card.aSEQRegs[Card.SEQ.CLK.INDX] & Card.SEQ.CLK.DOTCLOCK);
@ -4532,6 +4536,8 @@ Video.prototype.outGRCData = function(port, bOut, addrFrom)
case Card.GRC.BITMASK.INDX:
this.cardEGA.nBitMapMask = bOut | (bOut << 8) | (bOut << 16) | (bOut << 24);
break;
default:
break;
}
};

View file

@ -344,6 +344,8 @@ var X86Help = {
case 0x7: // BH
this.regBX = (this.regBX & 0xff) | (dst << 8);
break;
default:
break; // there IS no other case, but JavaScript inspections don't know that
}
this.nStepCycles -= this.nOpCyclesXchgRR;
} else {
@ -390,6 +392,8 @@ var X86Help = {
case 0x7: // DI
this.regDI = dst;
break;
default:
break; // there IS no other case, but JavaScript inspections don't know that
}
this.nStepCycles -= this.nOpCyclesXchgRR;
} else {

View file

@ -1807,43 +1807,47 @@ var X86OpXX = {
case 0x7: // this form of MOV to DS is undocumented on 8086/8088/80186/80188, invalid on 80286 and up
temp = this.regDI;
break;
default:
break;
}
break;
}
X86Mods.aOpModsRegWord[bModRM].call(this, X86Help.opHelpMOV);
switch (reg) {
case 0x0:
this.setES(this.regAX);
this.regAX = temp;
break;
case 0x1:
this.setCS(this.regCX);
this.regCX = temp;
break;
case 0x2:
this.setSS(this.regDX);
this.regDX = temp;
break;
case 0x3:
this.setDS(this.regBX);
this.regBX = temp;
break;
case 0x4:
this.setES(this.regSP);
this.regSP = temp;
break;
case 0x5:
this.setCS(this.regBP);
this.regBP = temp;
break;
case 0x6:
this.setSS(this.regSI);
this.regSI = temp;
break;
case 0x7:
this.setDS(this.regDI);
this.regDI = temp;
break;
case 0x0:
this.setES(this.regAX);
this.regAX = temp;
break;
case 0x1:
this.setCS(this.regCX);
this.regCX = temp;
break;
case 0x2:
this.setSS(this.regDX);
this.regDX = temp;
break;
case 0x3:
this.setDS(this.regBX);
this.regBX = temp;
break;
case 0x4:
this.setES(this.regSP);
this.regSP = temp;
break;
case 0x5:
this.setCS(this.regBP);
this.regBP = temp;
break;
case 0x6:
this.setSS(this.regSI);
this.regSI = temp;
break;
case 0x7:
this.setDS(this.regDI);
this.regDI = temp;
break;
default:
break; // there IS no other case, but JavaScript inspections don't know that
}
},
/**