Since "model" properties are strings now, they need to be coerced to numbers
This commit is contained in:
parent
4f04393c3a
commit
bc7ec763ca
19 changed files with 572 additions and 435 deletions
|
|
@ -114,7 +114,7 @@ pcjs:
|
|||
- /modules/pc8080/lib/bus.js
|
||||
- /modules/pc8080/lib/memory.js
|
||||
- /modules/pc8080/lib/cpu.js
|
||||
- /modules/pc8080/lib/cpusim.js
|
||||
- /modules/pc8080/lib/cpustate.js
|
||||
- /modules/pc8080/lib/cpuops.js
|
||||
- /modules/pc8080/lib/chipset.js
|
||||
- /modules/pc8080/lib/rom.js
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
<control type="button" binding="run">Run</control>
|
||||
<control type="button" binding="step">Step</control>
|
||||
<control type="button" binding="reset">Reset</control>
|
||||
<control type="button" binding="setSpeed">Fast</control>
|
||||
<control type="button" binding="setSpeed">Speed</control>
|
||||
<control type="button" binding="save">Save</control>
|
||||
</control>
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
<control type="button" binding="run">Run</control>
|
||||
<control type="button" binding="step">Step</control>
|
||||
<control type="button" binding="reset">Reset</control>
|
||||
<control type="button" binding="setSpeed">Fast</control>
|
||||
<control type="button" binding="setSpeed">Speed</control>
|
||||
<control type="button" binding="save">Save</control>
|
||||
</control>
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<control type="button" binding="step">Step</control>
|
||||
<control type="button" binding="reset">Reset</control>
|
||||
<control type="button" binding="save">Save</control>
|
||||
<control type="button" binding="setSpeed" padleft="16px">Fast</control>
|
||||
<control type="button" binding="setSpeed" padleft="16px">Speed</control>
|
||||
<control type="description" binding="speed" padleft="8px">Stopped</control>
|
||||
</control>
|
||||
</control>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ if (NODE) {
|
|||
* @constructor
|
||||
* @extends Component
|
||||
* @param {Object} parmsBus
|
||||
* @param {CPUSim} cpu
|
||||
* @param {CPUState} cpu
|
||||
* @param {Debugger} dbg
|
||||
*/
|
||||
function Bus(parmsBus, cpu, dbg)
|
||||
|
|
@ -705,7 +705,7 @@ Bus.prototype.saveMemory = function(fAll)
|
|||
/**
|
||||
* restoreMemory(a)
|
||||
*
|
||||
* This restores the contents of all Memory blocks; called by CPUSim.restore().
|
||||
* This restores the contents of all Memory blocks; called by CPUState.restore().
|
||||
*
|
||||
* In theory, we ONLY have to save/restore block contents. Other block attributes,
|
||||
* like the type, the memory controller (if any), and the active memory access functions,
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ function ChipSet(parmsChipSet)
|
|||
var model = parmsChipSet['model'];
|
||||
|
||||
/*
|
||||
* this.model is a numeric version of the 'model' string; when comparing this.model to standard IBM
|
||||
* this.model is a numeric version of the 'model' string; when comparing this.model to "base"
|
||||
* model numbers, you should generally compare (this.model|0) to the target value, which truncates it.
|
||||
*/
|
||||
if (model && !ChipSet.MODELS[model]) {
|
||||
|
|
@ -111,29 +111,29 @@ ChipSet.SI_1978 = {
|
|||
PORT: 0,
|
||||
DIP4: 0x01, // self-test request at power up?
|
||||
ALWAYS_SET: 0x0E, // always set
|
||||
FIRE: 0x10, // fire
|
||||
LEFT: 0x20, // move left
|
||||
RIGHT: 0x40, // move right
|
||||
PORT7: 0x80 // some connection to port 7?
|
||||
FIRE: 0x10, // 1 = fire
|
||||
LEFT: 0x20, // 1 = move left
|
||||
RIGHT: 0x40, // 1 = move right
|
||||
PORT7: 0x80 // some connection to (undocumented) port 7
|
||||
},
|
||||
STATUS1: {
|
||||
PORT: 1,
|
||||
CREDIT: 0x01, // credit
|
||||
P1: 0x02, // 1P start
|
||||
P2: 0x04, // 2P start
|
||||
CREDIT: 0x01, // credit (coin slot)
|
||||
P2: 0x02, // 1 = 2P start
|
||||
P1: 0x04, // 1 = 1P start
|
||||
ALWAYS_SET: 0x08, // always set
|
||||
P1_FIRE: 0x10, // P1 fire (cocktail machines only?)
|
||||
P1_LEFT: 0x20, // P1 left (cocktail machines only?)
|
||||
P1_RIGHT: 0x40 // P1 right (cocktail machines only?)
|
||||
P1_FIRE: 0x10, // 1 = P1 fire (cocktail machines only?)
|
||||
P1_LEFT: 0x20, // 1 = P1 left (cocktail machines only?)
|
||||
P1_RIGHT: 0x40 // 1 = P1 right (cocktail machines only?)
|
||||
},
|
||||
STATUS2: {
|
||||
PORT: 2,
|
||||
DIP3_5: 0x03, // 00 = 3 ships, 01 = 4 ships, 10 = 5 ships, 11 = 6 ships
|
||||
TILT: 0x04,
|
||||
TILT: 0x04, // 1 = tilt detected
|
||||
DIP6: 0x08, // 0 = extra ship at 1500, 1 = extra ship at 1000
|
||||
P2_FIRE: 0x10, // P2 fire (cocktail machines only?)
|
||||
P2_LEFT: 0x20, // P2 left (cocktail machines only?)
|
||||
P2_RIGHT: 0x40, // P2 right (cocktail machines only?)
|
||||
P2_FIRE: 0x10, // 1 = P2 fire (cocktail machines only?)
|
||||
P2_LEFT: 0x20, // 1 = P2 left (cocktail machines only?)
|
||||
P2_RIGHT: 0x40, // 1 = P2 right (cocktail machines only?)
|
||||
DIP7: 0x80 // 0 = display coin info on demo ("attract") screen
|
||||
},
|
||||
SHIFT_RESULT: { // bits 0-7 of barrel shifter result
|
||||
|
|
@ -218,7 +218,7 @@ ChipSet.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
* @this {ChipSet}
|
||||
* @param {Computer} cmp
|
||||
* @param {Bus} bus
|
||||
* @param {CPUSim} cpu
|
||||
* @param {CPUState} cpu
|
||||
* @param {Debugger} dbg
|
||||
*/
|
||||
ChipSet.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||
|
|
|
|||
|
|
@ -145,10 +145,10 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
|
|||
* Find the appropriate CPU (and Debugger and Control Panel, if any)
|
||||
*
|
||||
* CLOSURE COMPILER TIP: To override the type of a right-hand expression (as we need to do here,
|
||||
* where we know getComponentByType() will only return an CPUSim object or null), wrap the expression
|
||||
* where we know getComponentByType() will only return an CPUState object or null), wrap the expression
|
||||
* in parentheses. I never knew this until I stumbled across it in "Closure: The Definitive Guide".
|
||||
*/
|
||||
this.cpu = /** @type {CPUSim} */ (Component.getComponentByType("CPU", this.id));
|
||||
this.cpu = /** @type {CPUState} */ (Component.getComponentByType("CPU", this.id));
|
||||
if (!this.cpu) {
|
||||
Component.error("Unable to find CPU component");
|
||||
return;
|
||||
|
|
@ -1454,7 +1454,7 @@ Computer.prototype.updateFocus = function(fScroll)
|
|||
* neither. In theory, there could be BOTH, but that would be unusual.
|
||||
*
|
||||
* TODO: Consider alternate approaches to these largely register-oriented display updates. Ordinarily, we like to
|
||||
* separate logic from presentation, and currently the CPUSim contains both, since it's the component that intimately
|
||||
* separate logic from presentation, and currently the CPUState contains both, since it's the component that intimately
|
||||
* knows the names, number, sizes, etc, of all the active registers. The Panel component is the logical candidate,
|
||||
* but Panel is an optional component; generally, only machines that include Debugger also include Panel.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ if (NODE) {
|
|||
*
|
||||
* The CPU class supports the following (parmsCPU) properties:
|
||||
*
|
||||
* cycles: the machine's base cycles per second; the CPUSim constructor will
|
||||
* cycles: the machine's base cycles per second; the CPUState constructor will
|
||||
* provide us with a default (based on the CPU model) to use as a fallback.
|
||||
*
|
||||
* multiplier: base cycle multiplier; default is 1.
|
||||
|
|
@ -65,7 +65,7 @@ if (NODE) {
|
|||
* This component is primarily responsible for interfacing the CPU with the outside
|
||||
* world (eg, Panel and Debugger components), and managing overall CPU operation.
|
||||
*
|
||||
* It is extended by the CPUSim component, where the simulation control logic resides.
|
||||
* It is extended by the CPUState component, where the simulation control logic resides.
|
||||
*
|
||||
* @constructor
|
||||
* @extends Component
|
||||
|
|
@ -209,7 +209,7 @@ CPU.prototype.reset = function()
|
|||
/**
|
||||
* save()
|
||||
*
|
||||
* This is a placeholder for save support (overridden by the CPUSim component).
|
||||
* This is a placeholder for save support (overridden by the CPUState component).
|
||||
*
|
||||
* @this {CPU}
|
||||
* @return {Object|null}
|
||||
|
|
@ -222,7 +222,7 @@ CPU.prototype.save = function()
|
|||
/**
|
||||
* restore(data)
|
||||
*
|
||||
* This is a placeholder for restore support (overridden by the CPUSim component).
|
||||
* This is a placeholder for restore support (overridden by the CPUState component).
|
||||
*
|
||||
* @this {CPU}
|
||||
* @param {Object} data
|
||||
|
|
@ -349,7 +349,7 @@ CPU.prototype.isRunning = function()
|
|||
/**
|
||||
* getChecksum()
|
||||
*
|
||||
* This will be implemented by the CPUSim component.
|
||||
* This will be implemented by the CPUState component.
|
||||
*
|
||||
* @this {CPU}
|
||||
* @return {number} a 32-bit summation of key elements of the current CPU state (used by the CPU checksum code)
|
||||
|
|
@ -1046,7 +1046,7 @@ CPU.prototype.startCPU = function(fUpdateFocus)
|
|||
/**
|
||||
* stepCPU(nMinCycles)
|
||||
*
|
||||
* This will be implemented by the CPUSim component.
|
||||
* This will be implemented by the CPUState component.
|
||||
*
|
||||
* @this {CPU}
|
||||
* @param {number} nMinCycles (0 implies a single-step, and therefore breakpoints should be ignored)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -44,9 +44,9 @@ if (NODE) {
|
|||
}
|
||||
|
||||
/**
|
||||
* CPUSim(parmsCPU)
|
||||
* CPUState(parmsCPU)
|
||||
*
|
||||
* The CPUSim class uses the following (parmsCPU) properties:
|
||||
* The CPUState class uses the following (parmsCPU) properties:
|
||||
*
|
||||
* model: a number (eg, 8080) that should match one of the CPUDef.MODEL_* values
|
||||
*
|
||||
|
|
@ -54,16 +54,16 @@ if (NODE) {
|
|||
* constructor, along with a default speed (cycles per second) based on the specified (or default)
|
||||
* CPU model number.
|
||||
*
|
||||
* The CPUSim class was initially written to simulate a 8080 microprocessor, although over time
|
||||
* The CPUState class was initially written to simulate a 8080 microprocessor, although over time
|
||||
* it may evolved to support other microprocessors (eg, the Zilog Z80).
|
||||
*
|
||||
* @constructor
|
||||
* @extends CPU
|
||||
* @param {Object} parmsCPU
|
||||
*/
|
||||
function CPUSim(parmsCPU)
|
||||
function CPUState(parmsCPU)
|
||||
{
|
||||
this.model = parmsCPU['model'] || CPUDef.MODEL_8080;
|
||||
this.model = +parmsCPU['model'] || CPUDef.MODEL_8080;
|
||||
|
||||
var nCyclesDefault = 0;
|
||||
switch(this.model) {
|
||||
|
|
@ -105,17 +105,17 @@ function CPUSim(parmsCPU)
|
|||
this.resetRegs();
|
||||
}
|
||||
|
||||
Component.subclass(CPUSim, CPU);
|
||||
Component.subclass(CPUState, CPU);
|
||||
|
||||
/**
|
||||
* addHaltCheck(fn)
|
||||
*
|
||||
* Records a function that will be called during HLT opcode processing.
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {function(number)} fn
|
||||
*/
|
||||
CPUSim.prototype.addHaltCheck = function(fn)
|
||||
CPUState.prototype.addHaltCheck = function(fn)
|
||||
{
|
||||
this.afnHalt.push(fn);
|
||||
};
|
||||
|
|
@ -129,9 +129,9 @@ CPUSim.prototype.addHaltCheck = function(fn)
|
|||
* a Closure Compiler optimization is defeated when generating the function array at run-time instead of at
|
||||
* compile-time.
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.initProcessor = function()
|
||||
CPUState.prototype.initProcessor = function()
|
||||
{
|
||||
this.aOps = CPUDef.aOps8080;
|
||||
};
|
||||
|
|
@ -139,9 +139,9 @@ CPUSim.prototype.initProcessor = function()
|
|||
/**
|
||||
* reset()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.reset = function()
|
||||
CPUState.prototype.reset = function()
|
||||
{
|
||||
if (this.flags.fRunning) this.stopCPU();
|
||||
this.resetRegs();
|
||||
|
|
@ -153,9 +153,9 @@ CPUSim.prototype.reset = function()
|
|||
/**
|
||||
* resetRegs()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.resetRegs = function()
|
||||
CPUState.prototype.resetRegs = function()
|
||||
{
|
||||
this.regA = 0;
|
||||
this.regB = 0;
|
||||
|
|
@ -183,10 +183,10 @@ CPUSim.prototype.resetRegs = function()
|
|||
/**
|
||||
* setReset(addr)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} addr
|
||||
*/
|
||||
CPUSim.prototype.setReset = function(addr)
|
||||
CPUState.prototype.setReset = function(addr)
|
||||
{
|
||||
this.addrReset = addr;
|
||||
this.setPC(addr);
|
||||
|
|
@ -195,10 +195,10 @@ CPUSim.prototype.setReset = function(addr)
|
|||
/**
|
||||
* getChecksum()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number} a 32-bit summation of key elements of the current CPU state (used by the CPU checksum code)
|
||||
*/
|
||||
CPUSim.prototype.getChecksum = function()
|
||||
CPUState.prototype.getChecksum = function()
|
||||
{
|
||||
var sum = (this.regA + this.regB + this.regC + this.regD + this.regE + this.regH + this.regL)|0;
|
||||
sum = (sum + this.getSP() + this.getPC() + this.getPS())|0;
|
||||
|
|
@ -208,12 +208,12 @@ CPUSim.prototype.getChecksum = function()
|
|||
/**
|
||||
* save()
|
||||
*
|
||||
* This implements save support for the CPUSim component.
|
||||
* This implements save support for the CPUState component.
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {Object|null}
|
||||
*/
|
||||
CPUSim.prototype.save = function()
|
||||
CPUState.prototype.save = function()
|
||||
{
|
||||
var state = new State(this);
|
||||
state.set(0, [this.regA, this.regB, this.regC, this.regD, this.regE, this.regH, this.regL, this.getSP(), this.getPC(), this.getPS()]);
|
||||
|
|
@ -225,13 +225,13 @@ CPUSim.prototype.save = function()
|
|||
/**
|
||||
* restore(data)
|
||||
*
|
||||
* This implements restore support for the CPUSim component.
|
||||
* This implements restore support for the CPUState component.
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {Object} data
|
||||
* @return {boolean} true if restore successful, false if not
|
||||
*/
|
||||
CPUSim.prototype.restore = function(data)
|
||||
CPUState.prototype.restore = function(data)
|
||||
{
|
||||
var a = data[0];
|
||||
this.regA = a[0];
|
||||
|
|
@ -254,14 +254,14 @@ CPUSim.prototype.restore = function(data)
|
|||
/**
|
||||
* setBinding(sHTMLType, sBinding, control, sValue)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
|
||||
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "AX")
|
||||
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
|
||||
* @param {string} [sValue] optional data value
|
||||
* @return {boolean} true if binding was successful, false if unrecognized binding request
|
||||
*/
|
||||
CPUSim.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
||||
CPUState.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
||||
{
|
||||
var fBound = false;
|
||||
switch (sBinding) {
|
||||
|
|
@ -298,10 +298,10 @@ CPUSim.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
/**
|
||||
* getBC()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number}
|
||||
*/
|
||||
CPUSim.prototype.getBC = function()
|
||||
CPUState.prototype.getBC = function()
|
||||
{
|
||||
return (this.regB << 8) | this.regC;
|
||||
};
|
||||
|
|
@ -309,10 +309,10 @@ CPUSim.prototype.getBC = function()
|
|||
/**
|
||||
* setBC(w)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} w
|
||||
*/
|
||||
CPUSim.prototype.setBC = function(w)
|
||||
CPUState.prototype.setBC = function(w)
|
||||
{
|
||||
this.regB = (w >> 8) & 0xff;
|
||||
this.regC = w & 0xff;
|
||||
|
|
@ -321,10 +321,10 @@ CPUSim.prototype.setBC = function(w)
|
|||
/**
|
||||
* getDE()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number}
|
||||
*/
|
||||
CPUSim.prototype.getDE = function()
|
||||
CPUState.prototype.getDE = function()
|
||||
{
|
||||
return (this.regD << 8) | this.regE;
|
||||
};
|
||||
|
|
@ -332,10 +332,10 @@ CPUSim.prototype.getDE = function()
|
|||
/**
|
||||
* setDE(w)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} w
|
||||
*/
|
||||
CPUSim.prototype.setDE = function(w)
|
||||
CPUState.prototype.setDE = function(w)
|
||||
{
|
||||
this.regD = (w >> 8) & 0xff;
|
||||
this.regE = w & 0xff;
|
||||
|
|
@ -344,10 +344,10 @@ CPUSim.prototype.setDE = function(w)
|
|||
/**
|
||||
* getHL()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number}
|
||||
*/
|
||||
CPUSim.prototype.getHL = function()
|
||||
CPUState.prototype.getHL = function()
|
||||
{
|
||||
return (this.regH << 8) | this.regL;
|
||||
};
|
||||
|
|
@ -355,10 +355,10 @@ CPUSim.prototype.getHL = function()
|
|||
/**
|
||||
* setHL(w)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} w
|
||||
*/
|
||||
CPUSim.prototype.setHL = function(w)
|
||||
CPUState.prototype.setHL = function(w)
|
||||
{
|
||||
this.regH = (w >> 8) & 0xff;
|
||||
this.regL = w & 0xff;
|
||||
|
|
@ -367,10 +367,10 @@ CPUSim.prototype.setHL = function(w)
|
|||
/**
|
||||
* getSP()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number}
|
||||
*/
|
||||
CPUSim.prototype.getSP = function()
|
||||
CPUState.prototype.getSP = function()
|
||||
{
|
||||
return this.regSP;
|
||||
};
|
||||
|
|
@ -378,10 +378,10 @@ CPUSim.prototype.getSP = function()
|
|||
/**
|
||||
* setSP(off)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} off
|
||||
*/
|
||||
CPUSim.prototype.setSP = function(off)
|
||||
CPUState.prototype.setSP = function(off)
|
||||
{
|
||||
this.regSP = off & 0xffff;
|
||||
};
|
||||
|
|
@ -389,10 +389,10 @@ CPUSim.prototype.setSP = function(off)
|
|||
/**
|
||||
* getPC()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number}
|
||||
*/
|
||||
CPUSim.prototype.getPC = function()
|
||||
CPUState.prototype.getPC = function()
|
||||
{
|
||||
return this.regPC;
|
||||
};
|
||||
|
|
@ -400,11 +400,11 @@ CPUSim.prototype.getPC = function()
|
|||
/**
|
||||
* offPC()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} off
|
||||
* @return {number}
|
||||
*/
|
||||
CPUSim.prototype.offPC = function(off)
|
||||
CPUState.prototype.offPC = function(off)
|
||||
{
|
||||
return (this.regPC + off) & 0xffff;
|
||||
};
|
||||
|
|
@ -412,10 +412,10 @@ CPUSim.prototype.offPC = function(off)
|
|||
/**
|
||||
* setPC(off)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} off
|
||||
*/
|
||||
CPUSim.prototype.setPC = function(off)
|
||||
CPUState.prototype.setPC = function(off)
|
||||
{
|
||||
this.regPC = off & 0xffff;
|
||||
};
|
||||
|
|
@ -423,9 +423,9 @@ CPUSim.prototype.setPC = function(off)
|
|||
/**
|
||||
* clearCF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.clearCF = function()
|
||||
CPUState.prototype.clearCF = function()
|
||||
{
|
||||
this.resultZeroCarry &= 0xff;
|
||||
};
|
||||
|
|
@ -433,10 +433,10 @@ CPUSim.prototype.clearCF = function()
|
|||
/**
|
||||
* getCF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number} 0 or 1 (CPUDef.PS.CF)
|
||||
*/
|
||||
CPUSim.prototype.getCF = function()
|
||||
CPUState.prototype.getCF = function()
|
||||
{
|
||||
return (this.resultZeroCarry & 0x100)? CPUDef.PS.CF : 0;
|
||||
};
|
||||
|
|
@ -444,9 +444,9 @@ CPUSim.prototype.getCF = function()
|
|||
/**
|
||||
* setCF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.setCF = function()
|
||||
CPUState.prototype.setCF = function()
|
||||
{
|
||||
this.resultZeroCarry |= 0x100;
|
||||
};
|
||||
|
|
@ -454,10 +454,10 @@ CPUSim.prototype.setCF = function()
|
|||
/**
|
||||
* updateCF(CF)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} CF (0x000 or 0x100)
|
||||
*/
|
||||
CPUSim.prototype.updateCF = function(CF)
|
||||
CPUState.prototype.updateCF = function(CF)
|
||||
{
|
||||
this.resultZeroCarry = (this.resultZeroCarry & 0xff) | CF;
|
||||
};
|
||||
|
|
@ -465,9 +465,9 @@ CPUSim.prototype.updateCF = function(CF)
|
|||
/**
|
||||
* clearPF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.clearPF = function()
|
||||
CPUState.prototype.clearPF = function()
|
||||
{
|
||||
if (this.getPF()) this.resultParitySign ^= 0x1;
|
||||
};
|
||||
|
|
@ -475,10 +475,10 @@ CPUSim.prototype.clearPF = function()
|
|||
/**
|
||||
* getPF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number} 0 or CPUDef.PS.PF
|
||||
*/
|
||||
CPUSim.prototype.getPF = function()
|
||||
CPUState.prototype.getPF = function()
|
||||
{
|
||||
return (CPUDef.PARITY[this.resultParitySign & 0xff])? CPUDef.PS.PF : 0;
|
||||
};
|
||||
|
|
@ -486,9 +486,9 @@ CPUSim.prototype.getPF = function()
|
|||
/**
|
||||
* setPF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.setPF = function()
|
||||
CPUState.prototype.setPF = function()
|
||||
{
|
||||
if (!this.getPF()) this.resultParitySign ^= 0x1;
|
||||
};
|
||||
|
|
@ -496,9 +496,9 @@ CPUSim.prototype.setPF = function()
|
|||
/**
|
||||
* clearAF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.clearAF = function()
|
||||
CPUState.prototype.clearAF = function()
|
||||
{
|
||||
this.resultAuxOverflow = (this.resultParitySign & 0x10) | (this.resultAuxOverflow & ~0x10);
|
||||
};
|
||||
|
|
@ -506,10 +506,10 @@ CPUSim.prototype.clearAF = function()
|
|||
/**
|
||||
* getAF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number} 0 or CPUDef.PS.AF
|
||||
*/
|
||||
CPUSim.prototype.getAF = function()
|
||||
CPUState.prototype.getAF = function()
|
||||
{
|
||||
return ((this.resultParitySign ^ this.resultAuxOverflow) & 0x10)? CPUDef.PS.AF : 0;
|
||||
};
|
||||
|
|
@ -517,9 +517,9 @@ CPUSim.prototype.getAF = function()
|
|||
/**
|
||||
* setAF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.setAF = function()
|
||||
CPUState.prototype.setAF = function()
|
||||
{
|
||||
this.resultAuxOverflow = (~this.resultParitySign & 0x10) | (this.resultAuxOverflow & ~0x10);
|
||||
};
|
||||
|
|
@ -527,9 +527,9 @@ CPUSim.prototype.setAF = function()
|
|||
/**
|
||||
* clearZF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.clearZF = function()
|
||||
CPUState.prototype.clearZF = function()
|
||||
{
|
||||
this.resultZeroCarry |= 0xff;
|
||||
};
|
||||
|
|
@ -537,10 +537,10 @@ CPUSim.prototype.clearZF = function()
|
|||
/**
|
||||
* getZF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number} 0 or CPUDef.PS.ZF
|
||||
*/
|
||||
CPUSim.prototype.getZF = function()
|
||||
CPUState.prototype.getZF = function()
|
||||
{
|
||||
return (this.resultZeroCarry & 0xff)? 0 : CPUDef.PS.ZF;
|
||||
};
|
||||
|
|
@ -548,9 +548,9 @@ CPUSim.prototype.getZF = function()
|
|||
/**
|
||||
* setZF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.setZF = function()
|
||||
CPUState.prototype.setZF = function()
|
||||
{
|
||||
this.resultZeroCarry &= ~0xff;
|
||||
};
|
||||
|
|
@ -558,9 +558,9 @@ CPUSim.prototype.setZF = function()
|
|||
/**
|
||||
* clearSF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.clearSF = function()
|
||||
CPUState.prototype.clearSF = function()
|
||||
{
|
||||
if (this.getSF()) this.resultParitySign ^= 0xc0;
|
||||
};
|
||||
|
|
@ -568,10 +568,10 @@ CPUSim.prototype.clearSF = function()
|
|||
/**
|
||||
* getSF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number} 0 or CPUDef.PS.SF
|
||||
*/
|
||||
CPUSim.prototype.getSF = function()
|
||||
CPUState.prototype.getSF = function()
|
||||
{
|
||||
return (this.resultParitySign & 0x80)? CPUDef.PS.SF : 0;
|
||||
};
|
||||
|
|
@ -579,9 +579,9 @@ CPUSim.prototype.getSF = function()
|
|||
/**
|
||||
* setSF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.setSF = function()
|
||||
CPUState.prototype.setSF = function()
|
||||
{
|
||||
if (!this.getSF()) this.resultParitySign ^= 0xc0;
|
||||
};
|
||||
|
|
@ -589,9 +589,9 @@ CPUSim.prototype.setSF = function()
|
|||
/**
|
||||
* clearIF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.clearIF = function()
|
||||
CPUState.prototype.clearIF = function()
|
||||
{
|
||||
this.regPS &= ~CPUDef.PS.IF;
|
||||
};
|
||||
|
|
@ -599,10 +599,10 @@ CPUSim.prototype.clearIF = function()
|
|||
/**
|
||||
* getIF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number} 0 or CPUDef.PS.IF
|
||||
*/
|
||||
CPUSim.prototype.getIF = function()
|
||||
CPUState.prototype.getIF = function()
|
||||
{
|
||||
return (this.regPS & CPUDef.PS.IF);
|
||||
};
|
||||
|
|
@ -610,9 +610,9 @@ CPUSim.prototype.getIF = function()
|
|||
/**
|
||||
* setIF()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.setIF = function()
|
||||
CPUState.prototype.setIF = function()
|
||||
{
|
||||
this.regPS |= CPUDef.PS.IF;
|
||||
};
|
||||
|
|
@ -620,10 +620,10 @@ CPUSim.prototype.setIF = function()
|
|||
/**
|
||||
* getPS()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number}
|
||||
*/
|
||||
CPUSim.prototype.getPS = function()
|
||||
CPUState.prototype.getPS = function()
|
||||
{
|
||||
return (this.regPS & ~CPUDef.PS.RESULT) | (this.getSF() | this.getZF() | this.getAF() | this.getPF() | this.getCF());
|
||||
};
|
||||
|
|
@ -631,10 +631,10 @@ CPUSim.prototype.getPS = function()
|
|||
/**
|
||||
* setPS(regPS)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} regPS
|
||||
*/
|
||||
CPUSim.prototype.setPS = function(regPS)
|
||||
CPUState.prototype.setPS = function(regPS)
|
||||
{
|
||||
this.resultZeroCarry = this.resultParitySign = this.resultAuxOverflow = 0;
|
||||
if (regPS & CPUDef.PS.CF) this.resultZeroCarry |= 0x100;
|
||||
|
|
@ -649,10 +649,10 @@ CPUSim.prototype.setPS = function(regPS)
|
|||
/**
|
||||
* getPSW()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number}
|
||||
*/
|
||||
CPUSim.prototype.getPSW = function()
|
||||
CPUState.prototype.getPSW = function()
|
||||
{
|
||||
return (this.getPS() & CPUDef.PS.MASK) | (this.regA << 8);
|
||||
};
|
||||
|
|
@ -660,10 +660,10 @@ CPUSim.prototype.getPSW = function()
|
|||
/**
|
||||
* setPSW(w)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} w
|
||||
*/
|
||||
CPUSim.prototype.setPSW = function(w)
|
||||
CPUState.prototype.setPSW = function(w)
|
||||
{
|
||||
this.setPS((w & CPUDef.PS.MASK) | (this.regPS & ~CPUDef.PS.MASK));
|
||||
this.regA = w >> 8;
|
||||
|
|
@ -672,11 +672,11 @@ CPUSim.prototype.setPSW = function(w)
|
|||
/**
|
||||
* addByte(src)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} src
|
||||
* @return {number} regA + src
|
||||
*/
|
||||
CPUSim.prototype.addByte = function(src)
|
||||
CPUState.prototype.addByte = function(src)
|
||||
{
|
||||
this.resultAuxOverflow = this.regA ^ src;
|
||||
return this.resultParitySign = (this.resultZeroCarry = this.regA + src) & 0xff;
|
||||
|
|
@ -685,11 +685,11 @@ CPUSim.prototype.addByte = function(src)
|
|||
/**
|
||||
* addByteCarry(src)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} src
|
||||
* @return {number} regA + src + carry
|
||||
*/
|
||||
CPUSim.prototype.addByteCarry = function(src)
|
||||
CPUState.prototype.addByteCarry = function(src)
|
||||
{
|
||||
this.resultAuxOverflow = this.regA ^ src;
|
||||
return this.resultParitySign = (this.resultZeroCarry = this.regA + src + ((this.resultZeroCarry & 0x100)? 1 : 0)) & 0xff;
|
||||
|
|
@ -701,11 +701,11 @@ CPUSim.prototype.addByteCarry = function(src)
|
|||
* Ordinarily, one would expect the Auxiliary Carry flag (AF) to be clear after this operation,
|
||||
* but apparently the 8080 will set AF if bit 3 in either operand is set.
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} src
|
||||
* @return {number} regA & src
|
||||
*/
|
||||
CPUSim.prototype.andByte = function(src)
|
||||
CPUState.prototype.andByte = function(src)
|
||||
{
|
||||
this.resultZeroCarry = this.resultParitySign = this.resultAuxOverflow = this.regA & src;
|
||||
if ((this.regA | src) & 0x8) this.resultAuxOverflow ^= 0x10; // set AF by inverting bit 4 in resultAuxOverflow
|
||||
|
|
@ -718,11 +718,11 @@ CPUSim.prototype.andByte = function(src)
|
|||
* We perform this operation using 8-bit two's complement arithmetic, by negating and then adding
|
||||
* the implied src of 1. This appears to mimic how the 8080 manages the Auxiliary Carry flag (AF).
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} b
|
||||
* @return {number}
|
||||
*/
|
||||
CPUSim.prototype.decByte = function(b)
|
||||
CPUState.prototype.decByte = function(b)
|
||||
{
|
||||
this.resultAuxOverflow = b ^ 0xff;
|
||||
b = this.resultParitySign = (b + 0xff) & 0xff;
|
||||
|
|
@ -733,11 +733,11 @@ CPUSim.prototype.decByte = function(b)
|
|||
/**
|
||||
* incByte(b)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} b
|
||||
* @return {number}
|
||||
*/
|
||||
CPUSim.prototype.incByte = function(b)
|
||||
CPUState.prototype.incByte = function(b)
|
||||
{
|
||||
this.resultAuxOverflow = b;
|
||||
b = this.resultParitySign = (b + 1) & 0xff;
|
||||
|
|
@ -748,11 +748,11 @@ CPUSim.prototype.incByte = function(b)
|
|||
/**
|
||||
* orByte(src)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} src
|
||||
* @return {number} regA | src
|
||||
*/
|
||||
CPUSim.prototype.orByte = function(src)
|
||||
CPUState.prototype.orByte = function(src)
|
||||
{
|
||||
return this.resultParitySign = this.resultZeroCarry = this.resultAuxOverflow = this.regA | src;
|
||||
};
|
||||
|
|
@ -787,11 +787,11 @@ CPUSim.prototype.orByte = function(src)
|
|||
* ---------
|
||||
* 1 0101 0110 (0x56)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} src
|
||||
* @return {number} regA - src
|
||||
*/
|
||||
CPUSim.prototype.subByte = function(src)
|
||||
CPUState.prototype.subByte = function(src)
|
||||
{
|
||||
src ^= 0xff;
|
||||
this.resultAuxOverflow = this.regA ^ src;
|
||||
|
|
@ -808,11 +808,11 @@ CPUSim.prototype.subByte = function(src)
|
|||
* This mimics the behavior of subByte() when the Carry flag (CF) is clear, and hopefully also mimics how the
|
||||
* 8080 manages the Auxiliary Carry flag (AF) when the Carry flag (CF) is set.
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} src
|
||||
* @return {number} regA - src - carry
|
||||
*/
|
||||
CPUSim.prototype.subByteBorrow = function(src)
|
||||
CPUState.prototype.subByteBorrow = function(src)
|
||||
{
|
||||
src ^= 0xff;
|
||||
this.resultAuxOverflow = this.regA ^ src;
|
||||
|
|
@ -822,11 +822,11 @@ CPUSim.prototype.subByteBorrow = function(src)
|
|||
/**
|
||||
* xorByte(src)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} src
|
||||
* @return {number} regA ^ src
|
||||
*/
|
||||
CPUSim.prototype.xorByte = function(src)
|
||||
CPUState.prototype.xorByte = function(src)
|
||||
{
|
||||
return this.resultParitySign = this.resultZeroCarry = this.resultAuxOverflow = this.regA ^ src;
|
||||
};
|
||||
|
|
@ -834,11 +834,11 @@ CPUSim.prototype.xorByte = function(src)
|
|||
/**
|
||||
* getByte(addr)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} addr is a linear address
|
||||
* @return {number} byte (8-bit) value at that address
|
||||
*/
|
||||
CPUSim.prototype.getByte = function(addr)
|
||||
CPUState.prototype.getByte = function(addr)
|
||||
{
|
||||
return this.bus.getByte(addr);
|
||||
};
|
||||
|
|
@ -846,11 +846,11 @@ CPUSim.prototype.getByte = function(addr)
|
|||
/**
|
||||
* getWord(addr)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} addr is a linear address
|
||||
* @return {number} word (16-bit) value at that address
|
||||
*/
|
||||
CPUSim.prototype.getWord = function(addr)
|
||||
CPUState.prototype.getWord = function(addr)
|
||||
{
|
||||
return this.bus.getShort(addr);
|
||||
};
|
||||
|
|
@ -858,11 +858,11 @@ CPUSim.prototype.getWord = function(addr)
|
|||
/**
|
||||
* setByte(addr, b)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} addr is a linear address
|
||||
* @param {number} b is the byte (8-bit) value to write (which we truncate to 8 bits; required by opSTOSb)
|
||||
*/
|
||||
CPUSim.prototype.setByte = function(addr, b)
|
||||
CPUState.prototype.setByte = function(addr, b)
|
||||
{
|
||||
this.bus.setByte(addr, b);
|
||||
};
|
||||
|
|
@ -870,11 +870,11 @@ CPUSim.prototype.setByte = function(addr, b)
|
|||
/**
|
||||
* setWord(addr, w)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} addr is a linear address
|
||||
* @param {number} w is the word (16-bit) value to write (which we truncate to 16 bits to be safe)
|
||||
*/
|
||||
CPUSim.prototype.setWord = function(addr, w)
|
||||
CPUState.prototype.setWord = function(addr, w)
|
||||
{
|
||||
this.bus.setShort(addr, w);
|
||||
};
|
||||
|
|
@ -882,10 +882,10 @@ CPUSim.prototype.setWord = function(addr, w)
|
|||
/**
|
||||
* getPCByte()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number} byte at the current PC; PC advanced by 1
|
||||
*/
|
||||
CPUSim.prototype.getPCByte = function()
|
||||
CPUState.prototype.getPCByte = function()
|
||||
{
|
||||
var b = this.getByte(this.regPC);
|
||||
this.setPC(this.regPC + 1);
|
||||
|
|
@ -895,10 +895,10 @@ CPUSim.prototype.getPCByte = function()
|
|||
/**
|
||||
* getPCWord()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number} word at the current PC; PC advanced by 2
|
||||
*/
|
||||
CPUSim.prototype.getPCWord = function()
|
||||
CPUState.prototype.getPCWord = function()
|
||||
{
|
||||
var w = this.getWord(this.regPC);
|
||||
this.setPC(this.regPC + 2);
|
||||
|
|
@ -908,10 +908,10 @@ CPUSim.prototype.getPCWord = function()
|
|||
/**
|
||||
* popWord()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {number} word popped from the current SP; SP increased by 2
|
||||
*/
|
||||
CPUSim.prototype.popWord = function()
|
||||
CPUState.prototype.popWord = function()
|
||||
{
|
||||
var w = this.getWord(this.regSP);
|
||||
this.setSP(this.regSP + 2);
|
||||
|
|
@ -921,10 +921,10 @@ CPUSim.prototype.popWord = function()
|
|||
/**
|
||||
* pushWord(w)
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} w is the word (16-bit) value to push at current SP; SP decreased by 2
|
||||
*/
|
||||
CPUSim.prototype.pushWord = function(w)
|
||||
CPUState.prototype.pushWord = function(w)
|
||||
{
|
||||
this.setSP(this.regSP - 2);
|
||||
this.setWord(this.regSP, w);
|
||||
|
|
@ -933,10 +933,10 @@ CPUSim.prototype.pushWord = function(w)
|
|||
/**
|
||||
* checkINTR()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @return {boolean} true if h/w interrupt has just been acknowledged, false if not
|
||||
*/
|
||||
CPUSim.prototype.checkINTR = function()
|
||||
CPUState.prototype.checkINTR = function()
|
||||
{
|
||||
if ((this.intFlags & CPUDef.INTFLAG.INTR) && this.getIF()) {
|
||||
var bRST = CPUDef.OPCODE.RST0 | ((this.intFlags & CPUDef.INTFLAG.INTL) << 3);
|
||||
|
|
@ -951,9 +951,9 @@ CPUSim.prototype.checkINTR = function()
|
|||
/**
|
||||
* clearINTR()
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
*/
|
||||
CPUSim.prototype.clearINTR = function()
|
||||
CPUState.prototype.clearINTR = function()
|
||||
{
|
||||
this.intFlags &= ~(CPUDef.INTFLAG.INTL | CPUDef.INTFLAG.INTR);
|
||||
};
|
||||
|
|
@ -973,10 +973,10 @@ CPUSim.prototype.clearINTR = function()
|
|||
* setIF() finally occurs, that interrupt is propagated to intFlags. But for now, we're going to assume that
|
||||
* scenario is rare.
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} nLevel (0-7)
|
||||
*/
|
||||
CPUSim.prototype.requestINTR = function(nLevel)
|
||||
CPUState.prototype.requestINTR = function(nLevel)
|
||||
{
|
||||
this.intFlags = (this.intFlags & ~CPUDef.INTFLAG.INTL) | nLevel | CPUDef.INTFLAG.INTR;
|
||||
};
|
||||
|
|
@ -988,12 +988,12 @@ CPUSim.prototype.requestINTR = function(nLevel)
|
|||
* CPU type before passing the call to displayValue(); in the "old days", updateStatus() called
|
||||
* displayValue() directly (although then it was called displayReg()).
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {string} sReg
|
||||
* @param {number} nValue
|
||||
* @param {number} [cch] (default is 2 hex digits)
|
||||
*/
|
||||
CPUSim.prototype.updateReg = function(sReg, nValue, cch)
|
||||
CPUState.prototype.updateReg = function(sReg, nValue, cch)
|
||||
{
|
||||
this.displayValue(sReg, nValue, cch || 2);
|
||||
};
|
||||
|
|
@ -1007,10 +1007,10 @@ CPUSim.prototype.updateReg = function(sReg, nValue, cch)
|
|||
* Any high-frequency updates should be performed in updateVideo(), which should avoid DOM updates, since updateVideo()
|
||||
* can be called up to 60 times per second (see VIDEO_UPDATES_PER_SECOND).
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {boolean} [fForce] (true will display registers even if the CPU is running and "live" registers are not enabled)
|
||||
*/
|
||||
CPUSim.prototype.updateStatus = function(fForce)
|
||||
CPUState.prototype.updateStatus = function(fForce)
|
||||
{
|
||||
if (this.cLiveRegs) {
|
||||
if (fForce || !this.flags.fRunning || this.flags.fDisplayLiveRegs) {
|
||||
|
|
@ -1052,13 +1052,13 @@ CPUSim.prototype.updateStatus = function(fForce)
|
|||
* As a result, the Debugger's complete independence means you can run other 8086/8088 debuggers
|
||||
* (eg, DEBUG) inside the simulation without interference; you can even "debug" them with the Debugger.
|
||||
*
|
||||
* @this {CPUSim}
|
||||
* @this {CPUState}
|
||||
* @param {number} nMinCycles (0 implies a single-step, and therefore breakpoints should be ignored)
|
||||
* @return {number} of cycles executed; 0 indicates a pre-execution condition (ie, an execution breakpoint
|
||||
* was hit), -1 indicates a post-execution condition (eg, a read or write breakpoint was hit), and a positive
|
||||
* number indicates successful completion of that many cycles (which should always be >= nMinCycles).
|
||||
*/
|
||||
CPUSim.prototype.stepCPU = function(nMinCycles)
|
||||
CPUState.prototype.stepCPU = function(nMinCycles)
|
||||
{
|
||||
/*
|
||||
* The Debugger uses fComplete to determine if the instruction completed (true) or was interrupted
|
||||
|
|
@ -1143,21 +1143,21 @@ CPUSim.prototype.stepCPU = function(nMinCycles)
|
|||
};
|
||||
|
||||
/**
|
||||
* CPUSim.init()
|
||||
* CPUState.init()
|
||||
*
|
||||
* This function operates on every HTML element of class "cpu", extracting the
|
||||
* JSON-encoded parameters for the CPUSim constructor from the element's "data-value"
|
||||
* JSON-encoded parameters for the CPUState constructor from the element's "data-value"
|
||||
* attribute, invoking the constructor (which in turn invokes the CPU constructor)
|
||||
* to create a CPUSim component, and then binding any associated HTML controls to the
|
||||
* to create a CPUState component, and then binding any associated HTML controls to the
|
||||
* new component.
|
||||
*/
|
||||
CPUSim.init = function()
|
||||
CPUState.init = function()
|
||||
{
|
||||
var aeCPUs = Component.getElementsByClass(document, PCJSCLASS, "cpu");
|
||||
for (var iCPU = 0; iCPU < aeCPUs.length; iCPU++) {
|
||||
var eCPU = aeCPUs[iCPU];
|
||||
var parmsCPU = Component.getComponentParms(eCPU);
|
||||
var cpu = new CPUSim(parmsCPU);
|
||||
var cpu = new CPUState(parmsCPU);
|
||||
Component.bindComponentControls(cpu, eCPU, PCJSCLASS);
|
||||
}
|
||||
};
|
||||
|
|
@ -1165,6 +1165,6 @@ CPUSim.init = function()
|
|||
/*
|
||||
* Initialize every CPU module on the page
|
||||
*/
|
||||
web.onInit(CPUSim.init);
|
||||
web.onInit(CPUState.init);
|
||||
|
||||
if (NODE) module.exports = CPUSim;
|
||||
if (NODE) module.exports = CPUState;
|
||||
|
|
@ -709,7 +709,7 @@ if (DEBUGGER) {
|
|||
* @this {Debugger}
|
||||
* @param {Computer} cmp
|
||||
* @param {Bus} bus
|
||||
* @param {CPUSim} cpu
|
||||
* @param {CPUState} cpu
|
||||
* @param {Debugger} dbg
|
||||
*/
|
||||
Debugger.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||
|
|
|
|||
|
|
@ -210,6 +210,143 @@ Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.RBRACK] = Keyboard.ASCII[']']; // 2
|
|||
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.QUOTE] = Keyboard.ASCII["'"]; // 222 -> 39
|
||||
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.FF_DASH] = Keyboard.ASCII['-'];
|
||||
|
||||
/**
|
||||
* setBinding(sHTMLType, sBinding, control, sValue)
|
||||
*
|
||||
* @this {Keyboard}
|
||||
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
|
||||
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "esc")
|
||||
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
|
||||
* @param {string} [sValue] optional data value
|
||||
* @return {boolean} true if binding was successful, false if unrecognized binding request
|
||||
*/
|
||||
Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
||||
{
|
||||
/*
|
||||
* There's a special binding that the Video component uses ("kbd") to effectively bind its
|
||||
* screen to the entire keyboard, in Video.powerUp(); ie:
|
||||
*
|
||||
* video.kbd.setBinding("canvas", "kbd", video.canvasScreen);
|
||||
* or:
|
||||
* video.kbd.setBinding("textarea", "kbd", video.textareaScreen);
|
||||
*
|
||||
* However, it's also possible for the keyboard XML definition to define a control that serves
|
||||
* a similar purpose; eg:
|
||||
*
|
||||
* <control type="text" binding="kbd" width="2em">Kbd</control>
|
||||
*
|
||||
* The latter is purely experimental, while we work on finding ways to trigger the soft keyboard on
|
||||
* certain pesky devices (like the Kindle Fire). Note that even if you use the latter, the former will
|
||||
* still be enabled (there's currently no way to configure the Video component to not bind its screen,
|
||||
* but we could certainly add one if the need ever arose).
|
||||
*/
|
||||
var kbd = this;
|
||||
var id = sHTMLType + '-' + sBinding;
|
||||
|
||||
if (this.bindings[id] === undefined) {
|
||||
switch (sBinding) {
|
||||
case "kbd":
|
||||
/*
|
||||
* Recording the binding ID prevents multiple controls (or components) from attempting to erroneously
|
||||
* bind a control to the same ID, but in the case of a "dual display" configuration, we actually want
|
||||
* to allow BOTH video components to call setBinding() for "kbd", so that it doesn't matter which
|
||||
* display the user gives focus to.
|
||||
*
|
||||
* this.bindings[id] = control;
|
||||
*/
|
||||
control.onkeydown = function onKeyDown(event) {
|
||||
return kbd.onKeyDown(event, true);
|
||||
};
|
||||
control.onkeypress = function onKeyPressKbd(event) {
|
||||
return kbd.onKeyPress(event);
|
||||
};
|
||||
control.onkeyup = function onKeyUp(event) {
|
||||
return kbd.onKeyDown(event, false);
|
||||
};
|
||||
return true;
|
||||
|
||||
case "caps-lock":
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickCapsLock(event) {
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.toggleCapsLock();
|
||||
};
|
||||
return true;
|
||||
|
||||
case "num-lock":
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickNumLock(event) {
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.toggleNumLock();
|
||||
};
|
||||
return true;
|
||||
|
||||
case "scroll-lock":
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickScrollLock(event) {
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.toggleScrollLock();
|
||||
};
|
||||
return true;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Maintain support for older button codes; eg, map button code "ctrl-c" to CLICKCODE "CTRL_C"
|
||||
*/
|
||||
var sCode = sBinding.toUpperCase().replace(/-/g, '_');
|
||||
if (Keyboard.CLICKCODES[sCode] !== undefined && sHTMLType == "button") {
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function(kbd, sKey, simCode) {
|
||||
return function onClickKeyboard(event) {
|
||||
if (!COMPILED && kbd.messageEnabled()) kbd.printMessage(sKey + " clicked", Messages.KEYS);
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
kbd.updateShiftState(simCode, true); // future-proofing if/when any LOCK keys are added to CLICKCODES
|
||||
kbd.addActiveKey(simCode, true);
|
||||
};
|
||||
}(this, sCode, Keyboard.CLICKCODES[sCode]);
|
||||
return true;
|
||||
}
|
||||
else if (Keyboard.SOFTCODES[sBinding] !== undefined) {
|
||||
this.cSoftCodes++;
|
||||
this.bindings[id] = control;
|
||||
var fnDown = function(kbd, sKey, simCode) {
|
||||
return function onMouseOrTouchDownKeyboard(event) {
|
||||
kbd.addActiveKey(simCode);
|
||||
};
|
||||
}(this, sBinding, Keyboard.SOFTCODES[sBinding]);
|
||||
var fnUp = function (kbd, sKey, simCode) {
|
||||
return function onMouseOrTouchUpKeyboard(event) {
|
||||
kbd.removeActiveKey(simCode);
|
||||
};
|
||||
}(this, sBinding, Keyboard.SOFTCODES[sBinding]);
|
||||
if ('ontouchstart' in window) {
|
||||
control.ontouchstart = fnDown;
|
||||
control.ontouchend = fnUp;
|
||||
} else {
|
||||
control.onmousedown = fnDown;
|
||||
control.onmouseup = control.onmouseout = fnUp;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (sValue) {
|
||||
/*
|
||||
* Instead of just having a dedicated "test" control, we now treat any unrecognized control with
|
||||
* a data value as a test control. The only caveat is that such controls must have binding IDs that
|
||||
* do not conflict with predefined controls (which, of course, is the only way you can get here).
|
||||
*/
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickTest(event) {
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.injectKeys(sValue);
|
||||
};
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Keyboard.init()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ Memory.prototype = {
|
|||
* save()
|
||||
*
|
||||
* This gets the contents of a Memory block as an array of 32-bit values; used by Bus.saveMemory(),
|
||||
* which in turn is called by CPUSim.save().
|
||||
* which in turn is called by CPUState.save().
|
||||
*
|
||||
* Memory blocks with custom memory controllers do NOT save their contents; that's the responsibility
|
||||
* of the controller component.
|
||||
|
|
@ -317,7 +317,7 @@ Memory.prototype = {
|
|||
* restore(adw)
|
||||
*
|
||||
* This restores the contents of a Memory block from an array of 32-bit values;
|
||||
* used by Bus.restoreMemory(), which is called by CPUSim.restore(), after all other
|
||||
* used by Bus.restoreMemory(), which is called by CPUState.restore(), after all other
|
||||
* components have been restored and thus all Memory blocks have been allocated
|
||||
* by their respective components.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ Panel.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
* @this {Panel}
|
||||
* @param {Computer} cmp
|
||||
* @param {Bus} bus
|
||||
* @param {CPUSim} cpu
|
||||
* @param {CPUState} cpu
|
||||
* @param {Debugger} dbg
|
||||
*/
|
||||
Panel.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||
|
|
@ -131,7 +131,7 @@ Panel.prototype.powerDown = function(fSave, fShutdown)
|
|||
*
|
||||
* Update function for Panels containing elements with high-frequency display requirements.
|
||||
*
|
||||
* For older (and slower) DOM-based display elements, those are sill being managed by the CPUSim component,
|
||||
* For older (and slower) DOM-based display elements, those are sill being managed by the CPUState component,
|
||||
* so it has its own updateStatus() handler.
|
||||
*
|
||||
* The Computer's updateStatus() handler is currently responsible for calling both our handler and the CPU's handler.
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ Component.subclass(RAM);
|
|||
* @this {RAM}
|
||||
* @param {Computer} cmp
|
||||
* @param {Bus} bus
|
||||
* @param {CPUSim} cpu
|
||||
* @param {CPUState} cpu
|
||||
* @param {Debugger} dbg
|
||||
*/
|
||||
RAM.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||
|
|
@ -97,7 +97,7 @@ RAM.prototype.powerUp = function(data, fRepower)
|
|||
{
|
||||
if (!fRepower) {
|
||||
/*
|
||||
* The Computer powers up the CPU last, at which point CPUSim state is restored,
|
||||
* The Computer powers up the CPU last, at which point CPUState state is restored,
|
||||
* which includes the Bus state, and since we use the Bus to allocate all our memory,
|
||||
* memory contents are already restored for us, so we don't need the usual restore
|
||||
* logic. We just need to call reset(), to allocate memory for the RAM.
|
||||
|
|
@ -118,7 +118,7 @@ RAM.prototype.powerUp = function(data, fRepower)
|
|||
RAM.prototype.powerDown = function(fSave, fShutdown)
|
||||
{
|
||||
/*
|
||||
* The Computer powers down the CPU first, at which point CPUSim state is saved,
|
||||
* The Computer powers down the CPU first, at which point CPUState state is saved,
|
||||
* which includes the Bus state, and since we use the Bus component to allocate all
|
||||
* our memory, memory contents are already saved for us, so we don't need the usual
|
||||
* save logic.
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ ROM.CPM.VECTORS = [ROM.CPM.BIOS.VECTOR, ROM.CPM.BDOS.VECTOR];
|
|||
* @this {ROM}
|
||||
* @param {Computer} cmp
|
||||
* @param {Bus} bus
|
||||
* @param {CPUSim} cpu
|
||||
* @param {CPUState} cpu
|
||||
* @param {Debugger} dbg
|
||||
*/
|
||||
ROM.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ Video.COLORS = {
|
|||
* @this {Video}
|
||||
* @param {Computer} cmp
|
||||
* @param {Bus} bus
|
||||
* @param {CPUSim} cpu
|
||||
* @param {CPUState} cpu
|
||||
* @param {Debugger} dbg
|
||||
*/
|
||||
Video.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ if (NODE) {
|
|||
*
|
||||
* The X86CPU class uses the following (parmsCPU) properties:
|
||||
*
|
||||
* model: a number (eg, 8088) that should match one of the X86.MODEL values (default is 8088)
|
||||
* model: a string (eg, "8088") that should match one of the X86.MODEL values (default is "8088")
|
||||
* stepping: a string (eg, "B1") that should match one of the X86.STEPPING values (default is "")
|
||||
*
|
||||
* This extends the CPU class and passes any remaining parmsCPU properties to the CPU class
|
||||
|
|
@ -82,7 +82,7 @@ if (NODE) {
|
|||
*/
|
||||
function X86CPU(parmsCPU)
|
||||
{
|
||||
this.model = parmsCPU['model'] || X86.MODEL_8088;
|
||||
this.model = +parmsCPU['model'] || X86.MODEL_8088;
|
||||
|
||||
/*
|
||||
* We take the 'stepping' value, convert it to a hex value, and then add that to the model to provide
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@
|
|||
"./modules/pc8080/lib/bus.js",
|
||||
"./modules/pc8080/lib/memory.js",
|
||||
"./modules/pc8080/lib/cpu.js",
|
||||
"./modules/pc8080/lib/cpusim.js",
|
||||
"./modules/pc8080/lib/cpustate.js",
|
||||
"./modules/pc8080/lib/cpuops.js",
|
||||
"./modules/pc8080/lib/chipset.js",
|
||||
"./modules/pc8080/lib/rom.js",
|
||||
|
|
|
|||
Loading…
Reference in a new issue