Initial v1.18.2 delta: added support for ROM notification parameters that the Video component will accept

This commit is contained in:
Jeff Parsons 2015-05-22 12:33:33 -07:00 committed by jeffpar
commit 0639e8cbd2
151 changed files with 8239 additions and 1383 deletions

View file

@ -84,7 +84,27 @@ function ROM(parmsROM)
this.sFilePath = parmsROM['file'];
this.sFileName = str.getBaseName(this.sFilePath);
/*
* The 'notify' property can now (as of v1.18.2) contain an array of parameters that the notified
* component (typically Video) may use as it sees fit. For example, the Video component is generally
* interested in knowing the offsets of specific font tables within the ROM, which used to be hard-coded
* when all we supported were a few specific IBM video cards, but that's no longer feasible as we move
* beyond the original handful of IBM cards.
*
* It's up to the notified component to decide how to interpret the parameters it receives, if any.
*/
this.idNotify = parmsROM['notify'];
this.aNotifyParms = null;
if (this.idNotify) {
var i = this.idNotify.indexOf('[');
if (i > 0) {
try {
this.aNotifyParms = eval(this.idNotify.substr(i));
} catch (e) {}
this.idNotify = this.idNotify.substr(0, i);
}
}
if (this.sFilePath) {
var sFileURL = this.sFilePath;
if (DEBUG) this.log('load("' + sFileURL + '")');
@ -307,7 +327,7 @@ ROM.prototype.copyROM = function()
if (this.idNotify) {
var component = Component.getComponentByID(this.idNotify, this.id);
if (component) {
component.onROMLoad(this.abROM);
component.onROMLoad(this.abROM, this.aNotifyParms);
} else {
this.notice("Unable to find component: " + this.idNotify);
}

View file

@ -2779,32 +2779,16 @@ Video.prototype.onLoadSetFonts = function(sFontFile, sFontData, nErrorCode)
};
/**
* onROMLoad(abRom)
* onROMLoad(abRom, aParms)
*
* Called by copyROM() whenever a ROM with a 'notify' attribute set to our component ID has been loaded.
*
* For IBM EGA cards, we assume the associated ROM is the original IBM EGA ROM, which stores its 8x14
* font data at 0x2230 (and unlike the MDA/CGA character generator ROM, which splits the first 8 rows and
* remaining 6 rows of each character across separate 2K chunks, the bytes for all the EGA character rows
* are contiguous); the total size of the 8x14 font is 0xE00 bytes.
*
* At 0x3030, there is an "ALPHA SUPPLEMENT" table, which contains 15 bytes per row instead of 14,
* because each row is preceded by one byte containing the corresponding ASCII code; there are 20 entries
* in the supplemental table, for a total size of 0x12C bytes.
*
* Finally, at 0x3160, we have the 8x8 font data (also known as the thicker "double dot" CGA font);
* the total size of the 8x8 font is 0x800 bytes. No other font data is present in the EGA ROM;
* the thin 5x7 "single dot" CGA font is notably absent, which is fine, because we never loaded it for
* the MDA/CGA either.
*
* TODO: Determine how the supplemental table is used and whether we need to add some "run-time"
* font generation to support it (as opposed to "init-time" generation, which is all we do now).
* There's probably a similar need for user-defined fonts; for now, they're simply not supported.
* Called by the ROM's copyROM() function whenever a ROM component with a 'notify' attribute containing
* our component ID has been loaded.
*
* @this {Video}
* @param {Array.<number>} abROM
* @param {Array.<number>} [aParms]
*/
Video.prototype.onROMLoad = function(abROM)
Video.prototype.onROMLoad = function(abROM, aParms)
{
if (this.nCard == Video.CARD.EGA) {
/*
@ -2812,16 +2796,35 @@ Video.prototype.onROMLoad = function(abROM)
* regenerate the color font(s) whenever the foreground and/or background colors have changed.
*/
if (DEBUG) this.printMessage("onROMLoad(): EGA fonts loaded");
this.setFontData(abROM, [0x2230, 0x3160], 8);
/*
* For EGA cards, in the absence of any parameters, we assume that we're receiving the original
* IBM EGA ROM, which stores its 8x14 font data at 0x2230 as a contiguous stream; the total size
* of the 8x14 font is 0xE00 bytes.
*
* At 0x3030, there is an "ALPHA SUPPLEMENT" table, which contains 15 bytes per row instead of 14,
* because each row is preceded by one byte containing the corresponding ASCII code; there are 20
* entries in the supplemental table, for a total size of 0x12C bytes.
*
* Finally, at 0x3160, we have the 8x8 font data (also known as the thicker "double dot" CGA font);
* the total size of the 8x8 font is 0x800 bytes. No other font data is present in the EGA ROM;
* the thin 5x7 "single dot" CGA font is notably absent, which is fine, because we never loaded it for
* the MDA/CGA either.
*
* TODO: Determine how the supplemental table is used and whether we need to add some "run-time"
* font generation to support it (as opposed to "init-time" generation, which is all we do now).
* There's probably a similar need for user-defined fonts; for now, they're simply not supported.
*/
this.setFontData(abROM, aParms || [0x2230, 0x3160], 8);
}
else if (this.nCard == Video.CARD.VGA) {
if (DEBUG) this.printMessage("onROMLoad(): VGA fonts loaded");
/*
* The IBM VGA contains an 8x14 font at 0x3F8D (and corresponding supplemental table at 0x4D8D)
* For VGA cards, in the absence of any parameters, we assume that we're receiving the original
* IBM VGA ROM, which contains an 8x14 font at 0x3F8D (and corresponding supplemental table at 0x4D8D)
* and an 8x8 font at 0x378D; however, it also contains an 8x16 font at 0x4EBA (and corresponding
* supplemental table at 0x5EBA). See our reconstructed source code in ibm-vga.nasm.
*/
this.setFontData(abROM, [0x3f8d, 0x378d], 8);
this.setFontData(abROM, aParms || [0x3f8d, 0x378d], 8);
}
this.setReady();
};

View file

@ -2069,14 +2069,18 @@ X86CPU.prototype.advanceIP = function(inc)
* TR=0010 MS=FFF3 PS=3202 V0 D0 I1 T0 S0 Z0 A0 P0 C0
* 02E0:06F9 C20400 RET 0004
*
* After fetching the 3rd byte of the "RET 0004" opcode at CS:06FB, the CPU wants to automatically
* After fetching the 3rd byte of the "RET 0004" instruction at CS:06FB, the CPU wants to automatically
* advance IP to 06FC, which of course, exceeds the limit, but that doesn't matter unless we actually
* fetch a byte from 06FC, which won't happen. I'm working around this for now by applying a -1
* fudge factor to the fault check.
* fudge factor to the fault check below.
*/
var off = (this.regLIPLimit - this.regLIP)|0;
if (off < 0 && (this.regLIPLimit ^ this.regLIP) >= 0) {
if (this.model <= X86.MODEL_8088) {
/*
* There's no such thing as a GP fault on the 8086/8088, and I'm assuming that, on newer
* processors, when the segment limit is set to the maximum, it's OK for IP to wrap.
*/
if (this.model <= X86.MODEL_8088 || this.segCS.limit == this.segCS.addrMask) {
this.setIP(this.regLIP - this.segCS.base);
} else if (off < -1) { // fudge factor
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
@ -2095,21 +2099,10 @@ X86CPU.prototype.rewindIP = function(dec)
this.assert(dec < 0);
this.regLIP = (this.regLIP + dec)|0;
/*
* Properly comparing regLIP to regLIPLimit would normally require coercing both to unsigned
* (ie, floating-point) values. But instead, we do a subtraction, (regLIPLimit - regLIP), and
* if the result is negative, we need only be concerned if the signs of both numbers are the same
* (ie, the sign of their XOR'ed union is positive).
* Since rewindIP() is used only for discrete "intra-instruction" IP adjustments, there should be no need
* to perform all the same limit checks as advanceIP().
*/
if (((this.regLIPLimit - this.regLIP)|0) >= 0) {
if (PREFETCH) this.advancePrefetch(dec);
}
else if ((this.regLIPLimit ^ this.regLIP) >= 0) {
if (this.model <= X86.MODEL_8088) {
this.setIP(this.regLIP - this.segCS.base);
} else {
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
}
}
if (PREFETCH) this.advancePrefetch(dec);
};
/**
@ -3541,11 +3534,15 @@ X86CPU.prototype.popWord = function()
*
* TODO: I'm combining the old 8088 address-wrap check with the new segment-limit check,
* even though the correct time to do the latter is immediately BEFORE the fetch, not AFTER;
* I'm working around this for now by applying a -1 fudge factor to the fault check.
* I'm working around this for now by applying a -1 fudge factor to the fault check below.
*/
var off = ((this.regLSPLimit - this.regLSP)|0);
if (off < 0 && (this.regLSPLimit ^ this.regLSP) >= 0) {
if (this.model <= X86.MODEL_8088) {
/*
* There's no such thing as an SS fault on the 8086/8088, and I'm assuming that, on newer
* processors, when the stack segment limit is set to the maximum, it's OK for the stack to wrap.
*/
if (this.model <= X86.MODEL_8088 || this.segSS.limit == this.segSS.addrMask) {
this.setSP(this.regLSP - this.segSS.base);
} else if (off < -1) { // fudge factor
X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
@ -3571,7 +3568,12 @@ X86CPU.prototype.pushWord = function(w)
* (ie, the sign of their XOR'ed union is positive).
*/
if (((this.regLSP - this.regLSPLimitLow)|0) < 0 && (this.regLSPLimitLow ^ this.regLSP) >= 0) {
if (this.model <= X86.MODEL_8088) {
/*
* There's no such thing as an SS fault on the 8086/8088, and I'm assuming that, on newer
* processors, when the stack segment is expand-down and the limit is set to the "maximum" of
* zero, it's OK for the stack to wrap.
*/
if (this.model <= X86.MODEL_8088 || this.segSS.fExpDown && !this.segSS.limit) {
this.setSP(this.regLSP - this.segSS.base);
} else {
X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0);