Initial commit (a clone of the jsmachines project as of v1.15.3)
50
blog/2013/11/README.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
A Blog That's Not A Blog
|
||||
---
|
||||
As you may have noticed (or not), the [JSMachines](http://jsmachines.net/) website had a very modest makeover
|
||||
recently.
|
||||
|
||||
Originally, the site was a smattering of HTML files, along with some XML files that I was rendering as HTML
|
||||
using some simple XSL stylesheets. However, I was tired of having one set of files for the website to explain
|
||||
things and a different set of files on [GitHub](http://github.com) that explained other things -- many
|
||||
of those things being the SAME things.
|
||||
|
||||
So this month, I decided to eliminate all the HTML files. As you browse the site, you're simply navigating
|
||||
folders from the **GitHub** project and reading the project's **README.md** files.
|
||||
|
||||
There's a single PHP script responsible for transforming a folder's default document (either **README.md**
|
||||
or **machine.xml**) to HTML, as well as displaying the current directory across the top and a directory listing
|
||||
down the left-hand side.
|
||||
|
||||
The same script provides support for a subset of the [Markdown](http://daringfireball.net/projects/markdown/)
|
||||
syntax, which is more than sufficient to handle all the site's **README.md** files. I probably should
|
||||
have used a third-party Markdown library, but this was more educational, and it was easy to add extra features,
|
||||
like the ability to embed JavaScript machines with a single Markdown-style link; eg:
|
||||
|
||||
[IBM PC](/configs/pc/machines/5150/mda/64kb/ "PCjs:ibm5150")
|
||||
|
||||
The script takes care of the rest, adding the appropriate stylesheets and PCjs scripts automatically.
|
||||
|
||||
I had more grandiose plans, including a command-line prompt written in JavaScript that would allow you to
|
||||
navigate the site exactly as you would an IBM PC hard drive from a "DOS prompt", and I may try something
|
||||
like that later, but don't hold your breath.
|
||||
|
||||
I've tried to improve the organization of all the [Machine Configuration Files](/configs/pc/machines/) as well.
|
||||
The variety of configurations was getting out of hand. It's a bit tidier now, but there's still room for
|
||||
improvement.
|
||||
|
||||
My workflow is improving, too. I'm more comfortable with [GitHub](http://github.com) now,
|
||||
and I recently switched from Eclipse to JetBrains' [WebStorm](http://www.jetbrains.com/webstorm) (well,
|
||||
actually [PhpStorm](http://www.jetbrains.com/phpstorm), since it's a superset of WebStorm, although I did start
|
||||
with WebStorm), and the new development environment is feeling pretty good now. I've had zero problems with
|
||||
[JetBrains](http://www.jetbrains.com) products and I'm seriously impressed with their quality and completeness,
|
||||
so I have no qualms about moving from the "free" Eclipse platform to the $99 PhpStorm IDE.
|
||||
|
||||
The nice thing about the new GitHub-centric approach is that it's easy to "push" changes to both the repository
|
||||
and the website. I update one or more **README.md** files, "Commit and Push" from the IDE, then "pull" from GitHub
|
||||
on the web server.
|
||||
|
||||
This so-called blog is more of the same: **README.md** files in a series of folders. The only question now:
|
||||
will this actually evolve into a series...?
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*November 20, 2013*
|
||||
13
blog/2014/01/README.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
New Year, New Directions
|
||||
---
|
||||
Initial goals for 2014 include:
|
||||
|
||||
- Setting up a new web server running node.js, using either AWS, Google Compute Engine or Windows Azure;
|
||||
- Porting this project to work with node.js, which includes rewriting all the PHP code as server-side JavaScript;
|
||||
- Deciding whether to separate PCjs from C1Pjs for the new web site, or simply make PCjs.org a mirror of jsmachines.net;
|
||||
- Deciding how best (or even whether) to accomodate PCjs running from both **node** and **non-node** web servers.
|
||||
|
||||
I guess we'll learn more as the year progresses.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*January 20, 2014*
|
||||
50
blog/2014/03/30/README.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
Running on Azure
|
||||
---
|
||||
Publishing a Node-based site to [Azure](http://azure.com) was painless, thanks to their friendly web portal and
|
||||
GitHub integration. Getting a fully operational site, however, took a bit more time.
|
||||
|
||||
Unfortunately, because Azure's underlying server technology is Windows-based (IIS), some of the same Windows/Unix
|
||||
portability problems that have plagued us for decades still plague us today: **carriage returns** and **backslashes**.
|
||||
|
||||
Even though all PCjs text files in my project contain only linefeeds, IIS would serve them up with CR/LF
|
||||
instead. I first noticed this on the client side, when an XML file retrieved via *XMLHttpRequest()* came back
|
||||
full of CR/LFs, and later on the server side, when *fs.readFile()* returned a Markdown file filled with CR/LFs.
|
||||
|
||||
I wondered if the CR/LF transformation had happened when Azure pulled all my files from GitHub, because
|
||||
while I can understand some whitespace inconsistencies across web servers, I would never expect file system calls
|
||||
on the server to modify file contents.
|
||||
|
||||
I finally confirmed that the files were indeed modified on the server, by using Azure's FTP browser. For example,
|
||||
[minimal.xml](/configs/pc/keyboards/minimal.xml) is currently 622 bytes locally, but on the Azure server, the
|
||||
reported size is 632 bytes -- one extra CR for each of the file's 10 lines. After a little more digging, I
|
||||
[learned something new](http://git-scm.com/book/ch7-1.html#Formatting-and-Whitespace) about **Git**: it has a
|
||||
setting called `core.autocrlf` which, for me on OS X, defaults to `input` (meaning "convert CR/LF to LF on commit
|
||||
but do NOT convert LF back to CR/LF on check-out"). But Azure apparently sets this to `true`, causing all LFs to be
|
||||
converted to CR/LF.
|
||||
|
||||
Regarding slashes, even when path components contained only slashes, *path.join()* would return paths with
|
||||
backslashes. And unfortunately, this behavior varies from Node module to module. For example, I use the NPM
|
||||
[glob](https://www.npmjs.org/package/glob) module, and even when the input path to *glob()* contains backslashes,
|
||||
its output paths do not.
|
||||
|
||||
In the process of fixing those portability issues, I also had some trouble getting Azure logging to work as
|
||||
documented. Setting `loggingEnabled: true` in **/IISNode.yml** would generate logs in **/site/wwwroot/iisnode/**,
|
||||
but the logs were numerous and poorly organized.
|
||||
|
||||
And the Azure command-line tool that was *supposed* to enable real-time log-streaming to the console:
|
||||
|
||||
azure site log tail pcjs
|
||||
|
||||
would happily report:
|
||||
|
||||
Welcome, you are now connected to log-streaming service
|
||||
|
||||
but it would NEVER display anything but deployment information. Instead, I had to browse the log files using Azure's
|
||||
"FTP DIAGNOSTIC LOGS" link on the web portal -- which presents the logs as one big, ugly, fragmented mess:
|
||||
|
||||

|
||||
|
||||
Sigh. But at least the site is up and fully operational now.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*March 30, 2014*
|
||||
BIN
blog/2014/03/30/iisnode_logs.png
Normal file
|
After Width: | Height: | Size: 315 KiB |
41
blog/2014/03/31/README.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
Browser Compatibility Woes
|
||||
---
|
||||
While JavaScript has been doing a good job of delivering on the old "write once, run everywhere" promise that its
|
||||
[unrelated namesake](http://www.java.com) coined, the "hook once, deliver everywhere" promise seems less fulfilled.
|
||||
|
||||
Not that anyone ever made such a promise.
|
||||
|
||||
Specifically, I'm talking about DOM events. Take the HTML5 <canvas> element, for example. If I give
|
||||
it a `contenteditable="true"` attribute, it will play nicely with my JavaScript app in a Mobile Safari browser,
|
||||
by popping up the device's soft keyboard in response to the canvas element receiving focus (ie, when you tap on it).
|
||||
|
||||
The Silk browser on a Kindle Fire, however, is another story -- it acts like it has no idea what `contenteditable`
|
||||
means. Even if I display an actual <input> text field alongside the <canvas>, and attach all the same
|
||||
input event handlers to the text field instead of the canvas, the Kindle Fire's soft keyboard will pop up, but my
|
||||
input event handlers still won't fire.
|
||||
|
||||
I've done what testing I can with the Android SDK and the "Android Virtual Device Manager", and in general, support
|
||||
looks fine -- you click/tap on the PC's screen, the soft keyboard pops up, and typing works. So I guess Silk is just
|
||||
an outlier. I'm not sure what I'll do about it yet (or even what I can do).
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
Here's another issue I've yet to resolve.
|
||||
|
||||
When Apple released iOS 7.0, PCjs went from being a rock-solid web application on
|
||||
2nd/3rd/4th-generation iPads to a very flaky web application. It's still rock-solid on 5th-generation iPads
|
||||
(the iPad Air and iPad Mini w/Retina Display), and so I suspect a bug in Apple's JavaScript engine that's specific
|
||||
to their older A5 processor.
|
||||
|
||||
It may be possible to work around the bug, but I haven't yet isolated exactly what code
|
||||
sequence(s) are failing. For now, this is the most serious unresolved PCjs bug I'm aware of.
|
||||
|
||||
---
|
||||
|
||||
If you're having a problem (or trouble with a device) that I've not already mentioned, [let me know](mailto:Jeff@pcjs.org).
|
||||
Thanks.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*March 31, 2014*
|
||||
BIN
blog/2014/03/31/avd_tablet.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
17
blog/2014/04/01/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
The Latest in Emulator Technology
|
||||
---
|
||||
Announcing **InternetJS: The Internet Emulator**, the world's smallest JavaScript application capable of emulating the entire Internet.
|
||||
And like all PCjs applications, there's nothing to install. It runs safely and securely from any web browser.
|
||||
|
||||
Check out the ALPHA release demo below.
|
||||
|
||||
<iframe width="720" height="512" src="http://bing.com/" style="border-webkit-transform:scale(0.5);-moz-transform-scale(0.5);border:1px solid black;border-radius:15px;overflow:auto;width:100%;background-color:#FAEBD7;"></iframe>
|
||||
|
||||
Disclaimer: InternetJS may not be suitable for everyone. Ask your doctor if InternetJS is right for you. Side-effects may include:
|
||||
|
||||
- Increased awareness
|
||||
- Loss of appetite after eating large meals
|
||||
- Inability to forget things you never wanted to remember
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*April 1, 2014*
|
||||
20
blog/2014/04/12/README.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
What's New in 1.13.0
|
||||
---
|
||||
The latest version adds support for "software manifests", which you can read more about [here](/apps/). Basically, manifests
|
||||
are simple XML files that describe a piece of software (an application, an operating system, whatever). They can also
|
||||
link to a PCjs machine configuration capable of running the software, along with a "ready-to-run" machine state file.
|
||||
Conversely, a PCjs machine XML file can refer back to the manifest, to obtain a list of disk images.
|
||||
|
||||
Here are some [demos](/apps/pc/) of "ready-to-run" apps on [PCjs](/docs/about/pcjs/).
|
||||
|
||||
There have been lots of server-side changes recently, including API improvements that make it easy (well, *easier*)
|
||||
to dynamically create diskette images from a list of files, or even an entire folder (including all subfolders),
|
||||
as long as the total size of all the files will fit on a PCjs-supported diskette image. Support for creating hard disk
|
||||
images is still on the "TODO" list (the original **convdisk** PHP script supported hard disk images, but that functionality
|
||||
hasn't been ported to the newer **diskdump** Node module yet).
|
||||
|
||||
Almost nothing has changed in the PCjs client-side code (which is where the emulator runs), except for changes to use
|
||||
the new **diskdump** API.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*April 12, 2014*
|
||||
148
blog/2014/04/14/README.md
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
Node + Express != Safari
|
||||
---
|
||||
There's something very odd going on with between Node+Express and Safari, resulting in blank web pages.
|
||||
Don't believe me? Just ask [Google](https://www.google.com/#q=node+express+safari+blank+page).
|
||||
|
||||
[pcjs.org](http://www.pcjs.org/) contains a lot of XML files that are rendered as web pages using XML
|
||||
stylesheets. And occasionally Safari -- and ONLY Safari -- will render those XML files as blank pages.
|
||||
|
||||
For example, here's the
|
||||
[machine.xml](/configs/pc/machines/5150/mda/64kb/machine.xml) file that's also embedded on the
|
||||
[pcjs.org](http://www.pcjs.org/) home page.
|
||||
|
||||
When Safari fetched that XML file from an Apache web server (what I used before switching to Node),
|
||||
the request would look like:
|
||||
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
Cache-Control: max-age=0
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14
|
||||
|
||||
and the response would look like:
|
||||
|
||||
Date: Mon, 14 Apr 2014 22:11:20 GMT
|
||||
Last-Modified: Sun, 13 Apr 2014 01:59:06 GMT
|
||||
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.24 mod_ssl/2.2.26 OpenSSL/0.9.8y
|
||||
Etag: "37a10b3-492-4f6e2e96b2e80"
|
||||
Content-Type: text/xml
|
||||
Connection: Keep-Alive
|
||||
Accept-Ranges: bytes
|
||||
Keep-Alive: timeout=5, max=100
|
||||
Content-Length: 1170
|
||||
|
||||
with a status code of 200 ("OK"). And no matter how many times I hit Safari's Reload button, the response was the same.
|
||||
|
||||
Now with Node+Express, the same exact request would look like:
|
||||
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14
|
||||
|
||||
with a response of:
|
||||
|
||||
Date: Mon, 14 Apr 2014 22:16:42 GMT
|
||||
Etag: "1170-1397354346000"
|
||||
Last-Modified: Sun, 13 Apr 2014 01:59:06 GMT
|
||||
X-Powered-By: Express
|
||||
Content-Type: application/xml
|
||||
Cache-Control: public, max-age=0
|
||||
Connection: keep-alive
|
||||
Accept-Ranges: bytes
|
||||
Content-Length: 1170
|
||||
|
||||
HOWEVER, as soon as I used Safari's Back button to return to the home page, and then pressed the Forward button to return to
|
||||
the XML file, the XML request changed to:
|
||||
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
Cache-Control: max-age=0
|
||||
If-None-Match: "1170-1397354346000"
|
||||
If-Modified-Since: Sun, 13 Apr 2014 01:59:06 GMT
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14
|
||||
|
||||
with a response of 304 ("Not Modified") and the following response headers:
|
||||
|
||||
Date: Mon, 14 Apr 2014 22:18:26 GMT
|
||||
Cache-Control: public, max-age=0
|
||||
Etag: "1170-1397354346000"
|
||||
Last-Modified: Sun, 13 Apr 2014 01:59:06 GMT
|
||||
Connection: keep-alive
|
||||
Accept-Ranges: bytes
|
||||
X-Powered-By: Express
|
||||
|
||||
And here's where the "blank page" problem occurs: pressing Safari's Reload button. Again, the request looks the same as before,
|
||||
and the response is still be 304 ("Not Modified"), but the page is blank, and the response now looks like:
|
||||
|
||||
Date: Mon, 14 Apr 2014 22:21:15 GMT
|
||||
Cache-Control: public, max-age=0
|
||||
Last-Modified: Sun, 13 Apr 2014 01:59:06 GMT
|
||||
Connection: keep-alive
|
||||
Accept-Ranges: bytes
|
||||
X-Powered-By: Express
|
||||
Etag: "1170-1397354346000"
|
||||
|
||||
and no matter how many times I press Reload, the response is the same (except for an updated *Date*), and the page is still blank.
|
||||
|
||||
So, here's the kludge I've added to my Express server code, to prevent Safari from displaying blank pages for those XML files:
|
||||
|
||||
/*
|
||||
* The Safari "blank page" problem continues to plague us. Our first work-around was for directory
|
||||
* "index.html" documents, which we resolved by always sending the document ourselves, along with an
|
||||
* "ok" (200) response, instead of letting next() handle it, which would result in a "not modified"
|
||||
* (304) response.
|
||||
*
|
||||
* However, the problem also extends to any XML files that we serve to an initial Safari request
|
||||
* (eg, the machine.xml and manifest.xml files that we style as web pages). Safari includes
|
||||
* "Cache-Control max-age=0" in the request, and if the response is "Cache-Control public, max-age=0"
|
||||
* along with a 304 response code, Safari may once again display a blank page.
|
||||
*
|
||||
* This problem appears limited to the initial resource request for a particular URL. When these XML
|
||||
* files are requested by Safari while loading another web page, Safari's caching logic is different
|
||||
* (eg, it doesn't include the same "Cache-Control" setting).
|
||||
*/
|
||||
if (sBaseName == "machine.xml" || sBaseName == "manifest.xml") {
|
||||
var sAgent = req.headers['user-agent'];
|
||||
if (sAgent && sAgent.indexOf("Safari/") >= 0 && sAgent.indexOf("Chrome/") < 0 && sAgent.indexOf("OPR/") < 0) {
|
||||
var sCacheControl = req.headers['cache-control'];
|
||||
if (sCacheControl && sCacheControl.indexOf("max-age=0") >= 0) {
|
||||
fs.readFile(sPath, {encoding: "utf8"}, function doneReadFile(err, sData) {
|
||||
if (err) {
|
||||
next(); // alternatively: res.status(404).send("Cannot GET " + req.path);
|
||||
} else {
|
||||
/*
|
||||
* HACK: Express may still modify our response, turning our 200 status code into a 304
|
||||
* 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
|
||||
* Express from changing the status code, and I'm tired of testing work-arounds for this
|
||||
* irritating behavior in Safari.
|
||||
*/
|
||||
req.method = "NONE";
|
||||
res.set("Content-Type", "application/xml");
|
||||
res.status(200).send(sData);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
I should add that this problem wasn't limited to XML files. It's a problem for the first resource requested by
|
||||
Safari for any URL on the site (eg, URLs that default to "index.html" files).
|
||||
|
||||
I'm also rather surprised that no one yet seems to have figured out exactly what's going on here between Node+Express
|
||||
and Safari. Or maybe they have, and I haven't been keeping my Node.js config up-to-date. I've tried to avoid changing
|
||||
too many variables.
|
||||
|
||||
Lots of people have run into this problem. For example, on
|
||||
[StackOverflow](http://stackoverflow.com/questions/18811286/nodejs-express-cache-and-304-status-code), someone
|
||||
concluded that the [node-fresh](https://github.com/visionmedia/node-fresh) module should be changed. And for a while,
|
||||
it was changed, until the change was [reverted](https://github.com/visionmedia/node-fresh/issues/8) -- along with a
|
||||
lengthy discussion about why the change was wrong and that this was really a bug in Safari.
|
||||
|
||||
This "blank page" behavior may well be a bug in Safari, but that doesn't mean Express server components can't
|
||||
or shouldn't provide a work-around for that behavior in the meantime. It also seems that some people who decided
|
||||
this was a bug in Safari did not actually reproduce the bug themselves.
|
||||
|
||||
I don't know the right answer, but I do know that the current situation adversely affects users of other Node-powered
|
||||
websites, who will probably get blank pages when they shouldn't, and other developers, who must all discover/debug/work-around
|
||||
this problem on their own.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*April 14, 2014*
|
||||
39
blog/2014/04/30/README.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
Heading to New York
|
||||
---
|
||||
Lots of tinkering has been going on here at pcjs.org the past couple of weeks, but with nothing substantial to show for it.
|
||||
Fixing lots of little problems requires only small bits of time, whereas buckling down and tackling "the next BIG thing" for
|
||||
PCjs requires a much more serious time commitment, with limited interruptions.
|
||||
|
||||
And I certainly can't start on "the next BIG thing" now, because I'm heading to New York tomorrow, for [EmpireJS](http://2014.empirejs.org),
|
||||
my first JavaScript conference *and* my first trip to New York in about 20 years.
|
||||
|
||||
I'm going to the conference partly because it was a great excuse to finally visit New York again (and with the whole family,
|
||||
since all three of us are computer nerds), but also to get a more up-close-and-personal sense of where this whole JavaScript
|
||||
renaissance is headed.
|
||||
|
||||
Is it headed for a fiery crash? This recent blog post
|
||||
("[you have ruined javascript](http://codeofrob.com/entries/you-have-ruined-javascript.html)")
|
||||
suggests it already has for some people. Is it drowning in the Sea of Endless Proliferation, as this still-relevant two-year-old
|
||||
[parody](http://www.webmonkey.com/2012/05/jokes-for-nerds-html9-responsive-boilerstrap-js/) implies? Excerpt:
|
||||
|
||||
> *If you’re feeling overwhelmed by the endless proliferation of responsive grids, adaptive images, HTML boilerplates,
|
||||
CSS frameworks and JavaScript whirligigs then what you need is the HTML9 Responsive Boilerstrap JS.*
|
||||
|
||||
> *To install HTML9 Responsive Boilerstrap JS just “attackclone the grit repo pushmerge, then rubygem the lymphnode js shawarma
|
||||
module — and presto!”*
|
||||
|
||||
> *If you’re wondering what H9RBS.js actually is, well, you can abandon any hopes of one day being hip. But if you must know,
|
||||
H9RBS.js is a “flexible, dependency-free, lightweight, device-agnostic, modular, baked-in, component framework MVC library
|
||||
shoelacestrap to help you kickstart your responsive CSS-based app architecture backbone kitchensink tweetybirds.”*
|
||||
|
||||
Seriously, I'm concerned about how the JavaScript language (rather than the endless procession of frameworks) is going to evolve,
|
||||
and whether it even can. Two examples: at a high-level, we have Microsoft pushing [TypeScript](http://www.typescriptlang.org/),
|
||||
and at a much lower level, we have Mozilla pushing [asm.js](http://asmjs.org). And while I like aspects of both those efforts,
|
||||
I'm relunctant to go very far down either of those paths right now, because I don't want to get suckered. Inevitably, someone will
|
||||
see a *different* shiny object along another fork in the road, and everyone will chase after that instead.
|
||||
|
||||
Will [EmpireJS](http://2014.empirejs.org) answer any of these big questions? It doesn't really matter. I just expect to learn stuff,
|
||||
and learning is fun!
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*April 30, 2014*
|
||||
27
blog/2014/05/12/README.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
Chrome Kicks Butt
|
||||
---
|
||||
I haven't been closely monitoring the performance of PCjs across various browsers. Most of my browser testing has
|
||||
been limited to "Does the latest version still work in all current web browsers?"
|
||||
|
||||
However, at some point during the last couple months, Chrome's performance suddenly jumped through the roof. On my
|
||||
2.8GHz Intel Core i7 MacBook Pro, Chrome v34.0.1847.131 easily punches through the 120Mhz barrier on a PCjs machine
|
||||
running PC-DOS 2.00.
|
||||
|
||||
That's roughly a 3x-4x increase over previous versions of Chrome. Safari used to be the performance champ, capable
|
||||
of running a PCjs machine at a top speed of around 70-80MHz, while Chrome was less than half that, and Firefox was
|
||||
slower still.
|
||||
|
||||
Chrome has now leap-frogged Safari in a big way, almost doubling Safari's speed. And with Chrome's superior
|
||||
Developer Tools, Chrome is clearly the "Browser of Choice," whether you're just playing with PCjs or actually
|
||||
debugging it.
|
||||
|
||||
Firefox is a bit of a disappointment, given all the hoopla over [asm.js](http://asmjs.org/) and other investments
|
||||
that Mozilla is making. I've taken a "wait-and-see" attitude toward asm.js, because PCjs is hand-coded JavaScript,
|
||||
and I'm not prepared to build a preprocessor that converts the code to asm.js semantics solely for the benefit of a
|
||||
single browser.
|
||||
|
||||
Chrome's approach to making regular JavaScript run faster seems to be a winning strategy so far, at least for apps
|
||||
like PCjs.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*May 12, 2014*
|
||||
BIN
blog/2014/06/14/Halt_and_Catch_Liar-thumbnail.jpg
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
blog/2014/06/14/Halt_and_Catch_Liar.jpg
Normal file
|
After Width: | Height: | Size: 316 KiB |
75
blog/2014/06/14/README.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
Halt and Catch Liar
|
||||
---
|
||||
I had high hopes for the new AMC series "[Halt and Catch Fire](http://www.amctv.com/shows/halt-and-catch-fire),"
|
||||
but it has proven to be an utter disappointment. I think I can suspend my disbelief as well as anyone, but this
|
||||
show requires you to completely turn your brain off in order to be believed. I'm also baffled by the show's
|
||||
high [IMDb score](http://www.imdb.com/title/tt2543312/), which is currently 8.4 (out of 10). Either AMC has figured
|
||||
out how to game the system, or viewers are easily turned on by clichés, like the know-it-all Hot Programmer,
|
||||
the self-assured Sales Guy, and the non-plot-advancing sex that they almost instantly engage in.
|
||||
|
||||
The premise: ex-IBM Sales Guy waltzes into a fictional computer company, smooth-talks his way into a top
|
||||
marketing position without so much as a resumé, and then immediately risks all, including a huge potential lawsuit
|
||||
with IBM, because he has dreams of building IBM clones that are "2x fast" at "1/2 price" -- with *handles*!
|
||||
|
||||
And the first thing they must do to achieve this dream is clone the IBM PC ROM BIOS, which the show pretends
|
||||
was so secret that you couldn't even tell which chips on the IBM PC motherboard contained the ROM. Never mind
|
||||
that IBM published the entire ROM BIOS listing in their Technical Reference Manual, which also included system
|
||||
diagrams identifying every chip in the machine. I think if you're going to weave facts into your fiction,
|
||||
the least you can do is get your facts right.
|
||||
|
||||
And centerpiece of this whole conceit -- the cloning of the IBM PC ROM BIOS. What a farce! Check out this
|
||||
scene from Episode 2, where Brilliant Engineer looks at Hot Programmer's whiteboard in awe. Apparently, he
|
||||
is easily awed, because he did the same thing when Sales Guy wrote "2x fast, 1/2 price" on an earlier whiteboard.
|
||||
|
||||

|
||||
|
||||
So if you deconstruct the code on this whiteboard, you quickly notice that while it IS assembly language, it is
|
||||
NOT the sort of assembly language you would find in a ROM BIOS, let alone ANYTHING that would leave you in awe.
|
||||
|
||||
Here are some excerpts:
|
||||
|
||||
Initialization
|
||||
MOV AX,CX ; set up DS
|
||||
MOV DS,AX
|
||||
MOV SS,AX ; and SS
|
||||
LEA AX,BEGINSTACK
|
||||
MOV SP,AX
|
||||
MOV AL,OUTINT
|
||||
...
|
||||
TSTART
|
||||
LEA AX,BEGTRACE
|
||||
MOV POINT,AX
|
||||
MOV AL,YES ; TURN TRACE ON
|
||||
MOV TFLAG,AL
|
||||
MOV AL,NO ; NOT WRAPPED
|
||||
MOV WRAP,AL
|
||||
MOV AX,CS ; CONVERT ADDRESS FOR OUTPUT
|
||||
LEA SI,LOADCS
|
||||
CALL HEXPRT
|
||||
MOV AX,100H
|
||||
LEA SI,LOADIP
|
||||
CALL HEXPRT
|
||||
LEA DX,SIGNIN
|
||||
MOV AH,9
|
||||
INT DOSINT
|
||||
LEA DX,OUTPUT
|
||||
MOV AL,OUTPUT (?)
|
||||
MOV AH,25H ; Set Interrupt Vector
|
||||
INT DOSINT ; Have DOS place the interrupt...
|
||||
...
|
||||
|
||||
This is clearly **NOT** code for a PC ROM BIOS, because no PC BIOS would ever issue a DOS interrupt.
|
||||
A BIOS is designed to be called *by* DOS, not the other way around.
|
||||
|
||||
This turns out to be code largely copied from a file I found online: [PCTRACE.ASM](http://ftpmirror.your.org/pub/misc/dos/RbbsInABoxVol1No2_640/files/007P/PCTRACE.ZIP-contents/PCTRACE.ASM)
|
||||
|
||||
Another curiosity is that searching for this resulted in a "[Googlewhack](http://en.wikipedia.org/wiki/Googlewhack)"
|
||||
of sorts:
|
||||
|
||||

|
||||
|
||||
Technically, a Googlewhack (a two-word search that yields exactly one result) must use two words found in an actual
|
||||
dictionary. But dictionaries are so passé.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*June 14, 2014*
|
||||
BIN
blog/2014/06/14/googlewhack.jpg
Normal file
|
After Width: | Height: | Size: 71 KiB |
13
blog/2014/06/26/README.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
More Under-The-Hood Changes
|
||||
---
|
||||
v1.13.7 of PCjs contains a few minor improvements, mostly in terms of rendering video modes a little more
|
||||
efficiently. The rest of the changes to the website involved beefing up support for both "software manifests"
|
||||
and "document manifests."
|
||||
|
||||
To that end, there's a new [/pubs/]() directory for old documents, and [/disks/pc/]() contains more disk images,
|
||||
with more on the way. I have a TON of old diskette images, and it has taken more time to organize them and create
|
||||
manifests than I would like. I have managed to streamline the process somewhat, however, as discussed in
|
||||
[/disks/pc/personal/]().
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*June 26, 2014*
|
||||
38
blog/2014/07/30/README.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
EGA Support
|
||||
---
|
||||
PCjs v1.14.0 now includes basic EGA support. It emulates the EGA hardware well enough to pass the IBM EGA BIOS
|
||||
diagnostics and run [Windows 1.01](/configs/pc/machines/5160/ega/640kb/win101/) in color. Check out our
|
||||
[Windows 1.01 "Server Array"](/configs/pc/machines/5160/ega/640kb/array/) demo.
|
||||
|
||||

|
||||
|
||||
EGA support is added to a **machine.xml** file using two XML elements; eg:
|
||||
|
||||
<video id="videoEGA" model="ega" memory="0x20000" screenwidth="640" screenheight="350"/>
|
||||
|
||||
The *model* attribute must be set to "ega" and the *memory* attribute should be set to the amount of memory
|
||||
desired on the card; valid memory sizes are:
|
||||
|
||||
- 0x10000 (64Kb)
|
||||
- 0x20000 (128Kb)
|
||||
- 0x40000 (256Kb)
|
||||
|
||||
As with the MDA and CGA video cards, the *screenwidth* and *screenheight* attributes specify the size of display
|
||||
window, which the browser will then scale up or down, unless a specific overall size has been specified on the
|
||||
<machine> element.
|
||||
|
||||
The second required XML element is a <rom> element to load the EGA ROM; eg:
|
||||
|
||||
<rom id="romEGA" addr="0xc0000" size="0x4000" file="/devices/pc/video/ibm-ega.json" notify="videoEGA"/>
|
||||
|
||||
The *notify* attribute must match the *id* of the <video> element, so that the Video component can load
|
||||
the initial 8x14 and 8x8 fonts from the ROM. Support for dynamic loading of fonts from plane 2 of the EGA's memory
|
||||
will be added later; however, current support works well enough to allow switching from 25-line mode to 43-line mode,
|
||||
which essentially switches from the 8x14 font to the 8x8 font.
|
||||
|
||||
The <video> element also supports a *switches* attribute to specify the type of monitor connected to the EGA;
|
||||
this attribute corresponds to the actual switch settings on the EGA card; our default *switches* setting is "0110",
|
||||
which selects an Enhanced Color Monitor, enabling the EGA's maximum resolution of 640x350.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*July 30, 2014*
|
||||
BIN
blog/2014/07/30/win101-array-demo-small.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
blog/2014/07/30/win101-array-demo.jpg
Normal file
|
After Width: | Height: | Size: 252 KiB |
26
blog/2014/08/01/README.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
PC Tech Journal, 1987
|
||||
---
|
||||
As part of an ongoing effort to make classic PC technical literature more accessible, I just finished
|
||||
scanning and posting the 12 issues of [PC Tech Journal](/pubs/pc/magazines/pctj/) from 1987.
|
||||
|
||||

|
||||
|
||||
Future PC Tech Journal postings will include:
|
||||
|
||||
- Vol. 1, No. 1, July-August 1983
|
||||
- Vol. 3, No. 12, December 1985
|
||||
- Vol. 4, Nos. 1-12, 1986
|
||||
- Vol. 6, Nos. 1-12, 1988
|
||||
|
||||
I'm missing the rest of 1983, all of 1984, most of 1985, and all of 1989 (well, through April 1989, which was
|
||||
apparently the last issue).
|
||||
|
||||
For a nice overview and brief history of PC Tech Journal, check out the [OS/2 Museum](http://www.os2museum.com/wp/?p=2478).
|
||||
|
||||
In the meantime, if you have old PC Tech Journal issues that would fill any of the above holes, let me know.
|
||||
I'd be happy to buy them, scan them, and recycle them.
|
||||
|
||||
Thanks.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*August 1, 2014*
|
||||
45
blog/2014/08/28/README.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
Supporting the 80286
|
||||
---
|
||||
The next milestone for PCjs is complete 80286 emulation. My hope is to have it working by the end of the year.
|
||||
|
||||
PCjs version 1.15.0 is the first step on the path to full 80286 support. It includes changes to the physical
|
||||
memory manager and separate real-mode and protected-mode address evaluators. The Debugger supports physical
|
||||
addresses (eg, %FE05B is the same as F000:E05B, assuming real-mode operation), along with breakpoint commands that
|
||||
stop execution on port input/output operations. And the ChipSet component now contains "infrastructure" (a
|
||||
fancy way of saying "partial support") for multiple PICs, DMA controllers, the 8042 keyboard controller (including
|
||||
A20 support), and a bit more -- but not much.
|
||||
|
||||
One of the challenges is creating a single "universal" version of PCjs that can adapt itself to different machine
|
||||
types without impacting performance. There will not be a **pc8088.js** or a **pc80286.js** or whatever. There will
|
||||
only be **pc.js**.
|
||||
|
||||
Up until now, all PCjs machine XML files assumed an 8088 CPU with a 20-bit bus and a model 5150 or 5160 motherboard.
|
||||
But now, a machine XML file can specify:
|
||||
|
||||
<computer name="IBM PC AT" buswidth="24"/>
|
||||
<cpu model="80286"/>
|
||||
<chipset model="5170"/>
|
||||
...
|
||||
|
||||
Conventional emulators are usually NOT able to run original BIOS images, or simulate original PC hardware,
|
||||
or even run at the same speed as the original PC, making some software difficult or impossible to use. PCjs takes a
|
||||
different approach, by attempting to simulate an entire PC as it originally existed. Which is why a PCjs simulation
|
||||
of an IBM PC does NOT run at whatever speed your modern PC happens to run in V86-mode or whatever speed your
|
||||
browser's JavaScript engine tops out at.
|
||||
|
||||
No, a PCjs simulation of a 4.77Mhz IBM PC runs at 4.77Mhz. And a PCjs simulation of a 6Mhz IBM PC AT will run at
|
||||
6Mhz. If you want to run the simulation faster, you have that option, but that's not the default. And I'm not saying
|
||||
that PCjs is *exact* -- exactness is an exercise I'm leaving for another day and/or to other developers who are even
|
||||
more obsessive than I am. I'm just saying that original PCs represent the targets that PCjs is shooting for.
|
||||
|
||||
PCjs 1.15.0 can now load and run the IBM 5170 ROM BIOS up to the first 80286-specific opcode, so it's off and running.
|
||||
Although "running" isn't quite the right metaphor, because the process of bringing a new machine simulation to
|
||||
completion is a *very* long series of baby steps.
|
||||
|
||||
Also, in preparation for this new phase, I recently dug up a variety of old [80286 CPU Documentation](/pubs/pc/reference/intel/80286/)
|
||||
and posted excerpts. I'm sure none of this information is "new" at this point, but it might have some historical interest.
|
||||
|
||||
Enjoy.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*August 28, 2014*
|
||||
27
blog/2014/09/02/README.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
Minor Fixes and Additions
|
||||
---
|
||||
|
||||
The following fixes were made in PCjs v1.15.1:
|
||||
|
||||
1. Using the "User-defined URL" option when loading a disk image from a 3rd-party server was broken if the URL
|
||||
contained certain special characters; that should be fixed now, but be aware that only web servers (ie, URLs
|
||||
using the HTTP protocol) are supported. URLs that trigger a redirect may also not work (more testing required).
|
||||
2. Any errors that occur during the call to either *embedPC()* or *embedC1P()* should be properly displayed on the
|
||||
caller's page now.
|
||||
3. Two embedding helper functions have been added to provide more control over the machine startup
|
||||
and shutdown process:
|
||||
+ *enableEvents(boolean)*: pass *false* to disable delivery of all page events to all machines on the page,
|
||||
or *true* to re-enable;
|
||||
+ *sendEvent(string)*: pass *"init"*, *"show"* or *"exit"* to simulate the corresponding browser event
|
||||
(*onload*, *onpageshow* or *onbeforeunload*, respectively).
|
||||
|
||||
If a page calls *enableEvents(false)* before calling *embedPC()*, all machine layouts will be instantiated
|
||||
but the machines themselves will not be initialized. When the page is ready, call *enableEvents(true)* to restore
|
||||
normal event processing, and if the browser has already sent the *onload* event, then call *sendEvent("init")*
|
||||
to manually initialize the machine(s).
|
||||
|
||||
These two new functions are designed to assist in testing the starting up, shutting down and restarting of machines,
|
||||
by allowing scripts to control the overall process, without requiring use of the browser's back/forward/close controls.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*September 2, 2014*
|
||||
66
blog/2014/09/13/README.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
The IBM PC AT: Alive and Booting
|
||||
---
|
||||
|
||||
My first IBM PC AT (Model 5170) [Test Configuration](/configs/pc/machines/5170/ega/640kb/debugger/) finally
|
||||
boots to a PC-DOS prompt. The configuration uses the original [IBM Model 5170 ROM BIOS](/devices/pc/bios/5170/),
|
||||
dated January 10, 1984.
|
||||
|
||||
Getting through the BIOS "POST" (Power-On Self Test) diagnostics was like running an obstacle course, with various
|
||||
tests derailing the simulation at every turn.
|
||||
|
||||
Sometimes the problems were as simple as missing hardware. For example, I knew that the PC AT contained two DMA
|
||||
controllers, for a total of 8 DMA channels, but what I didn't know (or had forgotten) is that it also contained 16
|
||||
DMA page registers, some of which the BIOS uses as scratch registers. Since DMA page registers are accessed with
|
||||
I/O instructions that work identically in both real-mode and protected-mode, they obviously offer some advantages
|
||||
over RAM, especially when the BIOS hasn't yet tested all the RAM, or determined how much RAM is installed, or set up
|
||||
descriptors that allow the RAM to be accessed from protected-mode.
|
||||
|
||||
Aside from the additional DMA Controller, other major new motherboard components on the PC AT included a second
|
||||
8259 Interrupt Controller, an 8042 Keyboard ("Kitchen Sink") Controller, and an MC146818 Real-Time Clock/CMOS chip.
|
||||
The Keyboard Controller and Real-Time Clock/CMOS components required the most tinkering to pass through the ROM BIOS
|
||||
gauntlet.
|
||||
|
||||
For example, at one point, the BIOS ("[TEST.21](../../../../pubs/pc/reference/ibm/static/5170/techref/pages/IBM-5170-TECHREF 202.pdf)")
|
||||
reset the keyboard ("[KBD_RESET](../../../../pubs/pc/reference/ibm/static/5170/techref/pages/IBM-5170-TECHREF 212.pdf)"),
|
||||
which unmasked the keyboard IRQ and waited for an interrupt, using a loop where CX was initialized to zero and then
|
||||
decremented until either CX wrapped around to zero again *or* an interrupt occurred. The "TEST.21" code then assumed
|
||||
that if "KBD_RESET" returned zero in CX, no interrupt had occurred.
|
||||
|
||||
Unfortunately, my Keyboard Controller was a bit too fast: it generated an interrupt as soon as the keyboard IRQ was
|
||||
unmasked; as a result, CX was never decremented, leaving it at zero.
|
||||
|
||||
---
|
||||
|
||||
Most of the effort getting to this point involved adding support for 80286 protected-mode. That work is still far
|
||||
from complete, but getting through multiple real-mode/protected-mode round trips in the BIOS was an important
|
||||
milestone. Some of the work was outside the CPU component, such as A20 support and processor reset via the 8042
|
||||
controller. Work inside the CPU component included:
|
||||
|
||||
- New 80286 general-purpose instructions (eg, ENTER, LEAVE, new PUSH SP behavior, etc)
|
||||
- New protected-mode instructions (eg, ARPL, LGDT, LIDT, LAR, LSL, VERR, VERW, etc)
|
||||
- Protected-mode segment loading, addressing, and fault handling
|
||||
|
||||
Another "feature" I spent considerable time on was ensuring that 80286 protected-mode support did not adversely
|
||||
real-mode performance, so that the PC and PC XT simulations still run (almost) as fast as before. PCjs dynamically
|
||||
reconfigures itself according to the requirements of the processor and platform it's emulating.
|
||||
|
||||
---
|
||||
|
||||
There's still no support for [LOADALL](/pubs/pc/reference/intel/80286/loadall/) or triple-fault resets, nor for
|
||||
call gates or task gates, nor for conforming code segments or expand-down data segments. 80286-specific cycle
|
||||
counts haven't been incorporated yet, either. The list of remaining 80286 features is long.
|
||||
|
||||
And there's plenty of hardware support left to do: I haven't looked at the AT hard disk controller yet (which
|
||||
I believe is significantly different from the XT hard disk controller), and the keyboard *barely* works; the 8042
|
||||
Keyboard Controller and AT keyboard had a number of features that older PC/XT keyboards did not (like LEDs and
|
||||
programmable repeat rate).
|
||||
|
||||
And there are plenty of issues to investigate. For example, PC-DOS is picking up the correct RTC time, but not the
|
||||
date (PCjs initializes the RTC to the browser's current date/time, unless a hard-coded date/time is specified in the
|
||||
machine XML). And diskette I/O seems a bit slow; I'm concerned that the BIOS is spinning its wheels somewhere
|
||||
unnecessarily. And even though the test machine is configured with 640Kb of RAM, the BIOS is reporting only 64Kb.
|
||||
|
||||
Hmmmm.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*September 13, 2014*
|
||||