Monday, June 22, 2015

Emulator Release 1.02 and the Move to GitHub

Nigel and I are pleased to announce that version 1.02 of the retro-B5500 emulator was released on 21 June 2015. All changes have been posted to the repository for our GitHub project. The hosting site has also been updated with this release, and for those of you running your own web server, a zip file of the source can be downloaded from the GitHub repository [updated 2022-05-07].

This is a minor release containing corrections for several issues we have discovered since version 1.01 was released. In addition, this release contains the documentation and web site changes made necessary by the move to GitHub.


Project Now Hosted on GitHub


As some may already know, Google announced in early 2015 that it would be discontinuing its Google Code project hosting service. All projects will become read-only in August, and the service will be shut down completely in early 2016.

Google Code served us extremely well, but obviously we had to find a new home for the project. After looking at a few alternatives, Nigel and I settled on GitHub, easily the largest and most popular code project hosting service available today. Public projects like this one can be hosted for free, which was an important consideration for us. Plus, the site does not pester visitors with advertisements. Google provided a service to migrate Google Code projects to GitHub, and we took advantage of that to move the emulator's repository, issues, and wiki pages to their new home.

The new URL for the project site is https://github.com/pkimpel/retro-b5500/.

The former Google Code site for the project now redirects to the GitHub URL above. All further emulator development will be posted to the new GitHub site.

Note that this move affects only the open-source project site. This blog, the hosting site, and the forum are unaffected and remain at their former URLs. References to the project site in previous blogs will be updated to refer to the new site.

One big change in this move concerns the repository. On Google Code, we used Subversion to maintain an archive of the code base. On GitHub, the only option is Git, the distributed version control system developed by Linus Torvalds for the Linux kernel project. I liked Subversion a lot, and there are things about Git that I don't care for, but it is certainly adequate for our purposes.

Interestingly, GitHub provides a Subversion interface to its Git repositories, so it is possible to use Subversion client tools (such as the standard svn command-line client and TortoiseSVN, the Windows Explorer plug-in) to check out GitHub repositories and make commits to them. I'm continuing to use Tortoise with GitHub, but the branching and merging model of Git is significantly different from that of Subversion, so eventually I may have to abandon Subversion and become a git head myself. I have tried a few Git GUI clients, and thus far the one I like the best is Atlassian's SourceTree, which is free, but requires you to register with Atlassian first.

For those of you interested in obtaining a copy of the source code, viewing the commit history, or forking the emulator, GitHub offers some improved capabilities over Subversion:

  • You can download a zip file of the latest version of the source code by clicking the Download ZIP button on the project's home page at the GitHub link above.
  • You can clone the project using a Git command similar to the following:
    git clone https://github.com/pkimpel/retro-b5500 retro-b5500
  • You can use a Subversion client to check out a copy of the code as well, e.g.,
    svn checkout https://github.com/pkimpel/retro-b5500/trunk retro-b5500
  • As a distributed version control system, Git has some powerful forking and merging features that allow you to create a separate copy of the repository, make commits to it, and then pass the result of those commits to other distributed copies of the repository. We have no plans at present to open up the emulator to other committers, but the forking capabilities of Git may be the solution we have been seeking for the community to store and maintain a library of B5500 source code and other software we are gradually recovering. Whether that library should be a part of this project or a separate one is an open question, and one on which we would appreciate hearing feedback, preferably in the forum.
You will notice that the wiki pages have a considerably different look on GitHub than they did on Google Code. The markup notation used to compose the pages, known as "markdown," is also different from the one used by Google Code. The text and images are all there, though, and the links on the hosting site have been updated to point into the new wiki on GitHub.

The GitHub project has an issue tracker, similar to the one we used in Google Code. You are welcome to post issues (suspected bugs, new feature requests, documentation errors, etc.) to the project, but in order to do so you must have a GitHub account. Anonymous issue submission is not supported. Registration for an account is free, and can be initiated from the GitHub home page. You do not need any special permissions -- any GitHub account can submit issues to this project.

Please do not submit items of general discussion or questions on installation, configuration, or use of the emulator as issues. Those should be posted on the forum instead.


Changes in Release 1.02


This release incorporates the following fixes and enhancements over 1.01:

1. Memory Dump Tape Image


Since version 0.18 the emulator has supported a built-in dump of processor state and memory. You obtain this dump by clicking the red MEMORY CHECK lamp on the console panel. The emulator opens a temporary window and formats the processor and memory state into the window as plain text. You can view this data in the window or copy/save it for later analysis. The dump is just a snapshot and does not affect operation of the system. It can be generated at any time, and as often as you wish, even while the MCP is running.

This is a nice capability, but the resulting memory dump is just raw octal, and it is not easy to analyze. The B5500 MCP had a memory dump mechanism that was invoked using the DP MT SPO command, which would pause normal operations, copy the contents of memory to a magnetic tape and resume normal operations. You could then run the DUMP/ANALYZE program to read the tape and produce a formatted dump with a lot of the MCP information broken out in a much more readable manner.

In order for this dump mechanism to work, of course, the MCP must be up and running. To support a similar dump mechanism independently of the MCP, the emulator now supports an in-built tape dump. If you click the white NOT READY lamp on the console panel, the emulator will open a temporary window and format the contents of memory into this window, much as it does when clicking the MEMORY CHECK lamp. The difference is that the data is output as a tape image in the format used by the DUMP/ANALYZE program. Simply copy/save this tape image to a file on your local system, the same way you would for a tape image that is created when you unload a tape drive, and run the analyzer program against that tape, For example, from the SPO:

    ?RUN DUMP/ANALYZE; FILE MDUMP=MEMORY/DUMP001; END

Note that DUMP/ANALYZE is for the Datacom MCP. If running under the Timesharing MCP, you must use TSDUMP/ANALYZE. Also, it appears that the dump analysis utilities may have been quite new in Mark XIII, because there are complete source file replacements for both of them on the Mark XIII SYSTEM tape under PATCH/DUMPANL and PATCH/TSDUMP. You may wish to compile and use those newer versions instead of the compiled versions on the SYSTEM tape.

2. Capturing Printer and Punch Output


The emulator's implementation of the B5500 line printer works under the idea that to save the printed output, you would save the line printer text area or copy/paste its contents into another program for saving. In early releases this worked quite well, but starting with 1.00, the line printer implemented optional "green-bar" shading of the output. That shading works by grouping every three lines into a <pre> element and applying the shading to every other element. Disabling the shading simply removes the green color style from the elements -- the grouping into <pre> elements occurs regardless.

Alas, when copying or saving the contents of the printer's text area, some browsers (particularly Firefox) insert a blank line between each of the <pre> elements when rendering them as plain text. This makes the saved or copied text appear as if every third line is double-spaced.

To eliminate this problem, the line printer now supports a new way of capturing the contents of its text area, copied from the approach used with the SPO and datacom terminal. If you double-click anywhere in the printed text, the emulator will open a temporary window, render the entire contents of the text area into that window as plain text (without the extra blank lines), and clear the entire contents of the text area. You can then copy/save the contents of that temporary window as you would any other. When you are finished with the temporary window, simply close it. One advantage of this new mechanism is that you can do it at any time, even while the printer is in a ready state and printing.

The old method of clearing the print area by making the printer not ready and triple-clicking the FORM FEED button still works. There was a bug in the implementation of this method that was introduced in release 1.00, however. It has been fixed in this release.

This mechanism of double-clicking in the output text and opening a temporary window to receive the contents of the text area has also been implemented for both stackers on the card punch.

3. SPO Double-Click Problem


Double-clicking the INPUT REQUEST button on the SPO appeared to enable the SPO for input, but no characters were accepted from the keyboard. The problem could be resolved by clicking END OF MESSAGE and starting over.

What was actually happening was that the first click sent the keyboard-request interrupt to the system and the MCP responded by issuing a read to the SPO device. That usually happened fast enough that by the time the second click registered on the button, the read had already been issued and the input text box in the SPO paper area had been enabled and given the focus. The second click simply moved the focus to the INPUT REQUEST button, which of course ignored any keystrokes sent to it. The problem could also be resolved by clicking in the input box to give it back the focus.

The SPO driver now detects when the INPUT REQUEST button is clicked while the SPO is in the middle of a read operation. In such an event it returns the focus to the input box.

Also, the ability of the SPO to wrap output messages longer than 72 characters to a new line was lost in release 1.00. That ability has been reinstated in this release.

4. Miscellaneous Changes

  1. The disk driver will now report a not-ready error if a read or write transaction is aborted by the IndexedDB API in the browser. See the next section on disk quota problems in Firefox for more information.
  2. The disk driver now reports in the result descriptor for a Read Interrogate operation whether the addressed EU has Model IB (also known as "bulk" or "slow") Storage Units attached to it.
  3. The handling of Ctrl-B (break), Ctrl-D (disconnect request), Ctrl-E (WRU), Ctrl-L (clear input buffer), and Ctrl-Q (alternate end-of-message) keystrokes by the datacom terminal was not working. These keystrokes now generate the appropriate status indicators sent to the I/O Units.
  4. Sensing of the Beginning-of-Tape (BOT) marker for a magnetic tape by a Write Interrogate operation was being reported in the result descriptor in a way the MCP did not like. This was causing problems in purging blank tapes. Write Interrogate no longer reports BOT status, which seems to satisfy the MCP.
  5. The X register in the Processor was not being set properly at the end of some arithmetic operators. The X register is cleared at the end of each operator in Word Mode, so this did not affect operation under the normal user interface, but it did cause problems in the B5500SyllableDebugger interface. The guilty operators have been corrected.
  6. The B5500SetCallback.js module, which controls the synchronous interleaving and timing of all emulator activities, has a mechanism that adjusts future timing behavior based on the deviation between the execution delays it requests and those it actually receives. Tuning this mechanism has been an on-going process, and further tuning adjustments were made in this release.
  7. The ESU card in the standard cold-start card deck (tools/COLDSTART-XIII.card) has been changed to indicate the system has two disk EUs instead of three. When cold-starting a disk subsystem, you should always change this card to reflect the actual number of EUs configured for the disk subsystem.
  8. Preliminary decks for cool-starting and loading an MCP from tape to disk have been created in the tools/ folder as COOLSTART-XIII.card and MCPTAPEDISK-XIII.card, respectively.
  9. The B5500ColdLoad.html cold-start script (which is now deprecated) could not open the IndexedDB database for the disk subsystem in Google Chrome. This was caused by a differing interpretation between Firefox and Chrome of the second parameter to the IDB open() method, and has been fixed.
  10. Most of the disk subsystem utility scripts in the tools/ folder (B5500DiskDirList.html, etc.) would work only with the default disk subsystem, named B5500DiskUnit. These scripts now support a "db" query string parameter that specifies the name of the disk subsystem. For example, you can now invoke these scripts with a URL of the form: ".../tools/B5500DiskDirList.html?db=MyNewDisk".


Firefox Disk Quota Woes


Beginning with release 1.00, the emulator supports multiple disk subsystems. Using the configuration interface (entered by clicking the B5500 logo on the console panel while the emulator is in a powered-off state), you can easily create and switch among disk subsystems to, for example, move between datacom and timesharing MCPs or operate multiple versions of the MCP.

Several users have found multiple disk subsystems to be a nice thing to have, but its use has recently brought a problem to light when running under Firefox.

I have encountered the problem most often after setting up a second or third disk subsystem and during the process of loading system or symbol files to the new subsystem. Suddenly the tape load stops and the console shows the DKA lamp and one of the IOUn lamps lit. The rest of the system quickly ceases operating as well, except that the TIMR lamp for the interval timer interrupt continues to blink. A halt/load will often bring the system back up, but attempts to continue loading files from tape, or doing anything that uses more disk space, quickly results in the system locking up again.

It took a while to track down the cause of this. It was clear fairly early on that an IndexedDB write transaction never reported completion. Without that completion event, the emulated B5500 I/O never finished, so the Disk File Control Unit (DKA) and the I/O Control Unit (IOUn) remained in a busy state. Additional disk I/Os in the system quickly queued behind the write that never completed, and being denied further disk access, the MCP and its tasks quickly came to a standstill.

After several frustrating attempts to trace the I/O causing this problem, I finally discovered what was happening, which in turn revealed a rather serious bug in the emulator's disk driver. The IndexedDB API in Firefox was reporting a Quota Exceeded exception and aborting the write transaction. Unfortunately, the API reports this condition through the transaction's onabort event handler, not its onerror handler, and even more unfortunately, I had not implemented an onabort handler for either disk reads or writes, so the quota error went undetected by the emulator.

On abort event handlers have been implemented in release 1.02. They simply terminate the I/O operation, reporting the EU as not ready. That does not get around the quota problem, but it does cause a message reporting the not-ready condition to be printed on the SPO, so at least you will now know that there is a problem with the disk subsystem. The system as a whole will still stop operating. No further data can be inserted into any of the disk subsystems.

I have not been able to find any documentation on disk quotas for Firefox, and in fact the MDN web site clearly states there isn't one. The best I have been able to determine after a good deal of searching is that Firefox currently has a fixed 2GB upper limit on the amount of off-line storage that can be used by applications from the same source (i.e., same website). That limit appears to be hard-coded in Firefox and cannot be changed in the browser configuration. The only solution to the quota limit I have found is to delete one of the disk subsystems so that total off-line storage will fall below the quota limit.

Google Chrome also has quota limits for off-line storage used by web sites, but its limits are based on the amount of free disk space available on the workstation.

2GB is a lot of disk space, and should be sufficient to support many large B5500 disk subsystems, but I've also found that with the Uint8Array structure currently used to represent data in a disk sector, Firefox is storing that data in an extremely inefficient fashion. The overhead appears to be on the order of 30 times the size of the raw data being stored. I have a disk subsystem that contains perhaps 50-60 million (B5500) characters. Each six-bit B5500 character is stored as an eight-bit byte. The SQLite database used by Firefox for that IndexedDB instance currently occupies 1.8GB on disk. That means I'm already close to the 2GB limit, and a second disk subsystem does not need to get very large to exceed it.

The real problem here is the bloated storage overhead. My guess is that instead of storing a Uint8Array(240) disk sector image as simply a string of 240 bytes, Firefox is storing it as hash table containing 240 index:value pairs.

I am hopeful that we can find another data representation that will not carry so much storage overhead. This will require some research. If we are successful in reducing the storage overhead, however, that will invalidate all disk subsystems currently out there, and we will need a plan and some tooling to covert the existing subsystems to whatever new format we come up with.

For now, the best advice I can offer to those experiencing this problem is to try to keep your disk subsystems fairly small, or not to create multiple of them. Note that the quota limit is per website, so if you can split your emulator environments across multiple web sites, each will have a separate quota limit. Also note that a website is determined by the host portion of a URL, so for example, http://www.phkimpel.us/B5500/ and http://phkimpel.us/B5500/ are considered to be separate web sites by browsers, even though both URLs go to exactly the same place.

As always, if you have questions or need help with emulator issues, please raise them on the forum, so everyone can participate and share in the knowledge.