Clean up the CPU/ChipSet interface, and get the PC8080 Video component ready to actually do something

This commit is contained in:
Jeff Parsons 2016-05-01 10:13:43 -07:00
commit 8c5ab8d73b
19 changed files with 1210 additions and 993 deletions

View file

@ -68,7 +68,7 @@ function ChipSet(parmsChipSet)
Component.notice("Unrecognized ChipSet model: " + model);
}
this.model = ChipSet.MODELS[model];
this.model = ChipSet.MODELS[model] || ChipSet.SI_1978.MODEL;
this.bSwitches = this.parseDIPSwitches(parmsChipSet['swDIP']);
@ -276,7 +276,7 @@ ChipSet.prototype.reset = function()
this.bStatus0 = 0;
this.bStatus1 = 0;
this.bStatus2 = 0;
this.bShiftData = 0;
this.wShiftData = 0;
this.bShiftCount = 0;
this.bSound1 = this.bSound2 = 0;
};
@ -293,7 +293,7 @@ ChipSet.prototype.save = function()
{
var state = new State(this);
if (this.model == ChipSet.SI_1978.MODEL) {
state.set(0, [this.bStatus0, this.bStatus1, this.bStatus2, this.bShiftData, this.bShiftCount, this.bSound1, this.bSound2]);
state.set(0, [this.bStatus0, this.bStatus1, this.bStatus2, this.wShiftData, this.bShiftCount, this.bSound1, this.bSound2]);
}
return state.data();
};
@ -315,7 +315,7 @@ ChipSet.prototype.restore = function(data)
this.bStatus0 = a[0];
this.bStatus1 = a[1];
this.bStatus2 = a[2];
this.bShiftData = a[3];
this.wShiftData = a[3];
this.bShiftCount = a[4];
this.bSound1 = a[5];
this.bSound2 = a[6];
@ -323,6 +323,34 @@ ChipSet.prototype.restore = function(data)
return true;
};
/**
* start()
*
* Notification from the CPU that it's starting.
*
* @this {ChipSet}
*/
ChipSet.prototype.start = function()
{
/*
* Currently, all we (may) do with this notification is allow the speaker to make noise.
*/
};
/**
* stop()
*
* Notification from the CPU that it's stopping.
*
* @this {ChipSet}
*/
ChipSet.prototype.stop = function()
{
/*
* Currently, all we (may) do with this notification is prevent the speaker from making noise.
*/
};
/**
* inSIStatus0(port, addrFrom)
*
@ -378,7 +406,7 @@ ChipSet.prototype.inSIStatus2 = function(port, addrFrom)
*/
ChipSet.prototype.inSIShiftResult = function(port, addrFrom)
{
var b = ((this.bShiftData << this.bShiftCount) >> 8) & 0xff;
var b = (this.wShiftData >> (8 - this.bShiftCount)) & 0xff;
this.printMessageIO(port, null, addrFrom, "SHIFT.RESULT", b, true);
return b;
};
@ -422,7 +450,7 @@ ChipSet.prototype.outSISound1 = function(port, b, addrFrom)
ChipSet.prototype.outSIShiftData = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "SHIFT.DATA", null, true);
this.bShiftData = b;
this.wShiftData = (b << 8) | (this.wShiftData >> 8);
};
/**
@ -439,6 +467,19 @@ ChipSet.prototype.outSISound2 = function(port, b, addrFrom)
this.bSound2 = b;
};
/**
* outSIWatchdog(port, b, addrFrom)
*
* @this {ChipSet}
* @param {number} port (0x06)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
ChipSet.prototype.outSIWatchdog = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "WATCHDOG", null, true);
};
/*
* Port input notification tables
*/
@ -456,7 +497,8 @@ ChipSet.aPortOutput = {
0x02: ChipSet.prototype.outSIShiftCount,
0x03: ChipSet.prototype.outSISound1,
0x04: ChipSet.prototype.outSIShiftData,
0x05: ChipSet.prototype.outSISound2
0x05: ChipSet.prototype.outSISound2,
0x06: ChipSet.prototype.outSIWatchdog
};
/**

View file

@ -1047,7 +1047,7 @@ CPU.prototype.startCPU = function(fUpdateFocus)
if (this.cmp) this.cmp.start(this.aCounts.msStartRun, this.getCycles());
this.flags.fRunning = true;
this.flags.fStarting = true;
if (this.chipset) this.chipset.setSpeaker();
if (this.chipset) this.chipset.start();
var controlRun = this.bindings["run"];
if (controlRun) controlRun.textContent = "Halt";
if (this.cmp) {
@ -1091,7 +1091,7 @@ CPU.prototype.stopCPU = function(fComplete)
this.nRunCycles = 0;
if (this.flags.fRunning) {
this.flags.fRunning = false;
if (this.chipset) this.chipset.setSpeaker();
if (this.chipset) this.chipset.stop();
var controlRun = this.bindings["run"];
if (controlRun) controlRun.textContent = "Run";
}

View file

@ -2362,7 +2362,7 @@ CPUDef.opJNC = function()
CPUDef.opOUT = function()
{
var port = this.getPCByte();
this.bus.checkPortOutputNotify(port, 1, this.regA);
this.bus.checkPortOutputNotify(port, 1, this.regA, this.offPC(-2));
this.nStepCycles -= 10;
};
@ -2450,7 +2450,7 @@ CPUDef.opJC = function()
CPUDef.opIN = function()
{
var port = this.getPCByte();
this.regA = this.bus.checkPortInputNotify(port, 1) & 0xff;
this.regA = this.bus.checkPortInputNotify(port, 1, this.offPC(-2)) & 0xff;
this.nStepCycles -= 10;
};

View file

@ -450,6 +450,18 @@ CPUSim.prototype.getPC = function()
return this.regPC;
};
/**
* offPC()
*
* @this {CPUSim}
* @param {number} off
* @return {number}
*/
CPUSim.prototype.offPC = function(off)
{
return (this.regPC + off) & 0xffff;
};
/**
* setPC(off)
*

View file

@ -1578,6 +1578,9 @@ if (DEBUGGER) {
/**
* messageIO(component, port, bOut, addrFrom, name, bIn, bitsMessage)
*
* Most (if not all) port handlers should provide a name for their respective ports, so if no name is provided,
* we assume this is an unknown port, and display a message by default.
*
* @this {Debugger}
* @param {Component} component
* @param {number} port
@ -1590,7 +1593,7 @@ if (DEBUGGER) {
Debugger.prototype.messageIO = function(component, port, bOut, addrFrom, name, bIn, bitsMessage)
{
bitsMessage |= Messages.PORT;
if (addrFrom == null || (this.bitsMessage & bitsMessage) == bitsMessage) {
if (name == null || (this.bitsMessage & bitsMessage) == bitsMessage) {
this.message(component.idComponent + '.' + (bOut != null? "outPort" : "inPort") + '(' + str.toHexWord(port) + ',' + (name? name : "unknown") + (bOut != null? ',' + str.toHexByte(bOut) : "") + ')' + (bIn != null? (": " + str.toHexByte(bIn)) : "") + (addrFrom != null? (" at " + this.toHexOffset(addrFrom)) : ""));
}
};
@ -4499,7 +4502,11 @@ if (DEBUGGER) {
{
if (fSave) {
if (!sCmd) {
sCmd = this.aPrevCmds[this.iPrevCmd+1];
if (this.fAssemble) {
sCmd = "end";
} else {
sCmd = this.aPrevCmds[this.iPrevCmd+1];
}
} else {
if (this.iPrevCmd < 0 && this.aPrevCmds.length) {
this.iPrevCmd = 0;

View file

@ -50,11 +50,19 @@ if (NODE) {
* screenWidth: width of the screen canvas, in pixels
* screenHeight: height of the screen canvas, in pixels
* screenColor: background color of the screen canvas (default is black)
* aspectRatio
* frameBuffer
* interruptRate (eg, 120)
* refreshRate (eg, 60)
* rotation (eg, 90)
* screenRotation: the amount of counter-clockwise rotation required (eg, 90)
* aspectRatio (eg, 1.33)
* bufferAddr: the starting address of the frame buffer (eg, 0x2400)
* bufferCols: the width of a single frame buffer row, in pixels (eg, 256)
* bufferRows: the number of frame buffer rows (eg, 224)
* bufferBits: the number of bits per pixel (eg, 1)
* interruptRate: normally the same as (or some multiple of) the refreshRate (eg, 120)
* refreshRate: how many times updateScreen() should be called per second (eg, 60)
*
* We record all the above values now, but we defer creation of the frame buffer until our initBus()
* handler is called. At that point, we will also compute the extent of the frame buffer, determine the
* appropriate "cell" size (ie, the number of pixels that updateScreen() will fetch and process at once),
* and allocate our cell cache.
*
* @constructor
* @extends Component