Improved separation of FDC media parameters from drive parameters

This commit is contained in:
Jeff Parsons 2014-10-20 00:24:13 -05:00 • committed by jeffpar
commit 1809543577
32 changed files with 1915 additions and 1887 deletions

View file

@ -16,7 +16,7 @@ when the keyboard's "clock" line is toggled (see *set8042CmdData()* in [chipset.
a 40-track diskette).
+ The BIOS Diskette Reset function does something odd after resetting the Floppy Disk Controller: it
issues not one but *four* "SENSE INTERRUPT STATUS" commands to the FDC, and expects each response to
return an incrementally larger drive number. I found this a bit mystifying, considering that the IBM's
return an incrementally larger drive number. I found this a bit mystifying, considering that IBM's
own FDC/HDC "combo card" supports a maximum of *two* diskette drives. But, there's no point in arguing
with a BIOS that's almost 30 years old.
+ The BIOS attempts to detect what its authors must have considered a common problem: failure to run SETUP
@ -28,22 +28,22 @@ to discover that the ATC had this behavior, and now I'm wondering how many other
immediate "STATUS" register updates.
This PCjs release also fixes a problem reported by a user: if you disable **localStorage** support in your
browser, previous versions would fault. I knew that every browser that supports PCjs also supports
**localStorage**, but I didn't consider what might happen if a user had decided to turn it off.
browser, previous versions of PCjs would fault. While every browser that supports PCjs also supports
**localStorage**, I didn't consider what might happen if a user decided to turn it off.
The only downside to turning off **localStorage** is that none of your PCjs machines will be able save/restore
their state when you leave/return to the page, so they will always reboot.
their state when you leave/return to the page; they will always reboot.
Browser's don't always refer to the **localStorage** feature by its actual name, either. For example, in
Chrome, the setting that enables/disables **localStorage** is hidden under "Advanced Settings" => "Privacy" =>
"Content Settings" => "Cookies" => "Allow local data to be set (recommended)". Which is a little misleading
and annoying, because **localStorage** != **cookie**.
"Content Settings" => "Cookies" => "Allow local data to be set (recommended)". Which is somewhat misleading
and a little annoying, because **localStorage** is *not* a **cookie**.
PCjs *never* sets any cookies. Cookies are bits of data that your browser saves and then automatically sends
off to the server every time you make a request. **localStorage** is nothing more than local storage. Granted,
a JavaScript application could certainly abuse it and send it around like a cookie, but PCjs doesn't do that.
The only exception is when PCjs detects a problem, and even then, you must first agree to submit your machine's
state as part of the bug report.
off to the server every time you make a request. **localStorage** is nothing more than local storage; it is
*not* automatically sent anywhere. Granted, a JavaScript application could abuse it and send it around like a
cookie, but PCjs does *not* do that; the only exception is when PCjs detects a problem, and even then, you must
first agree to submit your machine's state as part of the bug report.
*[@jeffpar](http://twitter.com/jeffpar)*
*October 17, 2014*

View file

@ -45,8 +45,8 @@ The following features are targeted for version 1.16:
### History
+ v1.15 introduced PC AT (Model 5170) emulation, as discussed on our [Blog](/blog/2014/09/13/).
+ v1.14 introduced limited EGA emulation, as discussed on our [Blog](/blog/2014/07/30/).
+ v1.15 introduced PC AT (Model 5170) emulation, as discussed in the [blog](/blog/2014/09/13/).
+ v1.14 introduced limited EGA emulation, as discussed in the [blog](/blog/2014/07/30/).
+ v1.13 introduced manifest files that describe software packages that can be used with PCjs.
More information on software manifests is available [here](/apps/).
+ v1.12.1 coincided with the first release of the new PCjs web server running on [Node.js](http://nodejs.org).

View file

@ -43,13 +43,13 @@ var mkdirp = require("mkdirp");
var DiskAPI = require("../../shared/lib/diskapi");
var DumpAPI = require("../../shared/lib/dumpapi");
var DiskDump = require("../../diskdump");
var FileDump = require("../../filedump");
var UserAPI = require("../../shared/lib/userapi");
var ReportAPI = require("../../shared/lib/reportapi");
var net = require("../../shared/lib/netlib");
var str = require("../../shared/lib/strlib");
var usr = require("../../shared/lib/usrlib");
var DiskDump = require("../../diskdump");
var FileDump = require("../../filedump");
/**
* @type {HTMLOut}

View file

@ -926,7 +926,7 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock)
var sMachineFunc = "embed" + sMachine;
var sMachineClass = sMachine.toLowerCase();
var aMachineParms = aMatch[4].split(':');
var sMachineMessage = "(If you see this message, " + sMachine + "js may still be loading)";
var sMachineMessage = "(If you see this message, " + sMachine + "js is still loading, or JavaScript has been disabled)";
var sMachineID = aMachineParms[0];
var sMachineXSLFile = aMachineParms[1] || "";

View file

@ -738,6 +738,13 @@ FDC.prototype.initController = function(data)
for (iDrive = 0; iDrive < this.aDrives.length; iDrive++) {
var drive = this.aDrives[iDrive];
if (drive === undefined) {
/*
* The first time each drive is initialized, obtain its type (from switches or CMOS) and the physical limits
* of the drive (ie, max tracks and max sectors/track). As for max heads, initDrive() assumes that all drives
* have two heads, and in any case, there's no way to configure/specify a single-sided floppy drive.
*
* TODO: Provide a configuration option for single-sided drives, in case someone really wants to simulate that.
*/
drive = this.aDrives[iDrive] = {};
drive.bType = this.chipset.getSWFloppyDriveType(iDrive);
drive.nCylinders = 40;
@ -823,7 +830,7 @@ FDC.prototype.initDrive = function(drive, iDrive, data)
/*
* Note that when no data is provided (eg, when the controller is being reinitialized), we now take
* care to preserve any drive defaults that initController() already obtained for us, falling back to
* bare minimums only when all else has failed.
* bare minimums only when all else fails.
*/
data[1] = [FDC.DEFAULT_DRIVE_NAME, drive.nCylinders || 40, drive.nHeads || data[3], drive.nSectors || 9, drive.cbSector || 512, data[1]];
}
@ -845,6 +852,18 @@ FDC.prototype.initDrive = function(drive, iDrive, data)
drive.nSectors = data[i][3]; // sectors/track
drive.cbSector = data[i][4]; // bytes/sector
drive.fRemovable = data[i][5];
/*
* If we have current media parameters, restore them; otherwise, default to the drive's physical parameters.
*/
if (drive.nDiskCylinders = data[i][6]) {
drive.nDiskHeads = data[i][7];
drive.nDiskSectors = data[i][8];
} else {
drive.nDiskCylinders = drive.nCylinders;
drive.nDiskHeads = drive.nHeads;
drive.nDiskSectors = drive.nSectors;
}
i++;
/*
@ -888,11 +907,7 @@ FDC.prototype.initDrive = function(drive, iDrive, data)
drive.nBytes = data[i++];
/*
* The next group of properties are set by user requests to load/unload diskette images.
*
* NOTE: I now avoid reinitializing drive.disk in order to retain any previously mounted diskette across resets.
*
* drive.disk = null; // when a "disk" is "inserted" into the "drive", this is a Disk object
* We no longer reinitialize drive.disk, in order to retain previously mounted diskette across resets.
*/
/*
@ -971,7 +986,7 @@ FDC.prototype.saveDrive = function(drive)
var i = 0;
var data = [];
data[i++] = drive.resCode;
data[i++] = [drive.name, drive.nCylinders, drive.nHeads, drive.nSectors, drive.cbSector, drive.fRemovable];
data[i++] = [drive.name, drive.nCylinders, drive.nHeads, drive.nSectors, drive.cbSector, drive.fRemovable, drive.nDiskCylinders, drive.nDiskHeads, drive.nDiskSectors];
data[i++] = drive.bHead;
/*
* We used to store drive.nHeads in the next slot, but now we store bCylinderSeek,
@ -1170,16 +1185,21 @@ FDC.prototype.loadDiskette = function(iDrive, sDisketteName, sDiskettePath, fAut
*/
FDC.prototype.mountDiskette = function(drive, disk, sDisketteName, sDiskettePath)
{
var aDiskInfo;
drive.fBusy = false;
if (disk) {
/*
* We shouldn't mount the diskette unless the drive is able to handle it; for example, DSDD (40-track)
* drives cannot read DSHD (80-track) diskettes.
*/
if (disk && disk.aDiskData.length > drive.nCylinders) {
aDiskInfo = disk.info();
if (disk && aDiskInfo[0] > drive.nCylinders || aDiskInfo[1] > drive.nHeads || aDiskInfo[2] > drive.nSectors) {
this.notice("Diskette \"" + sDisketteName + "\" too large for drive " + String.fromCharCode(0x41 + drive.iDrive));
disk = null;
}
}
if (disk) {
drive.disk = disk;
@ -1205,6 +1225,13 @@ FDC.prototype.mountDiskette = function(drive, disk, sDisketteName, sDiskettePath
* and will not match the drive mappings that DOS ultimately uses (ie, for drives beyond B:).
*/
this.notice("Mounted diskette \"" + sDisketteName + "\" in drive " + String.fromCharCode(0x41 + drive.iDrive), drive.fAutoMount);
/*
* Update the drive's current media parameters to match the disk's.
*/
drive.nDiskCylinders = aDiskInfo[0];
drive.nDiskHeads = aDiskInfo[1];
drive.nDiskSectors = aDiskInfo[2];
}
if (drive.fAutoMount) {
@ -2141,8 +2168,8 @@ FDC.prototype.writeByte = function(drive, b)
/**
* advanceSector(drive)
*
* This increments the sector number; when the sector number reaches drive.nSectors on the current track, we
* increment drive.bHead and reset drive.bSector, and when drive.bHead reaches drive.nHeads, we reset drive.bHead
* This increments the sector number; when the sector number reaches drive.nDiskSectors on the current track, we
* increment drive.bHead and reset drive.bSector, and when drive.bHead reaches drive.nDiskHeads, we reset drive.bHead
* and increment drive.bCylinder.
*
* @this {FDC}
@ -2150,13 +2177,13 @@ FDC.prototype.writeByte = function(drive, b)
*/
FDC.prototype.advanceSector = function(drive)
{
Component.assert(drive.bCylinder < drive.nCylinders);
Component.assert(drive.bCylinder < drive.nDiskCylinders);
drive.bSector++;
var bSectorStart = 1;
if (drive.bSector >= drive.nSectors + bSectorStart) {
if (drive.bSector >= drive.nDiskSectors + bSectorStart) {
drive.bSector = bSectorStart;
drive.bHead++;
if (drive.bHead >= drive.nHeads) {
if (drive.bHead >= drive.nDiskHeads) {
drive.bHead = 0;
drive.bCylinder++;
}

View file

@ -865,7 +865,7 @@ HDC.prototype.initDrive = function(iDrive, drive, driveConfig, data, fReset)
/*
* The next group of properties are set by user requests to load/unload disk images.
*
* NOTE: I now avoid reinitializing drive.disk in order to retain any previously mounted disk across resets.
* We no longer reinitialize drive.disk, in order to retain previously mounted disk across resets.
*/
if (drive.disk === undefined) {
drive.disk = null;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long