Move //e specific out of apple2io.js (#28)

This commit is contained in:
Will Scullin 2020-08-06 06:31:27 -07:00 committed by GitHub
parent a3d38a12b6
commit 42b30141ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 163 additions and 116 deletions

View File

@ -11,7 +11,7 @@
import { debug } from './util';
export default function Apple2IO(cpu, callbacks)
export default function Apple2IO(cpu, vm)
{
var _slot = [];
var _auxRom = null;
@ -48,21 +48,10 @@ export default function Apple2IO(cpu, callbacks)
var LOC = {
KEYBOARD: 0x00, // keyboard data (latched) (Read),
CLR80VID: 0x0C, // clear 80 column mode
SET80VID: 0x0D, // set 80 column mode
CLRALTCH: 0x0E, // clear mousetext
SETALTCH: 0x0F, // set mousetext
STROBE: 0x10, // clear bit 7 of keyboard data ($C000)
RDTEXT: 0x1A, // using text mode
RDMIXED: 0x1B, // using mixed mode
RDPAGE2: 0x1C, // using text/graphics page2
RDHIRES: 0x1D, // using Hi-res graphics mode
RDALTCH: 0x1E, // using alternate character set
RD80VID: 0x1F, // using 80-column display mode
TAPEOUT: 0x20, // toggle the cassette output.
SPEAKER: 0x30, // toggle speaker diaphragm
C040STB: 0x40, // trigger game port sync
CLRTEXT: 0x50, // display graphics
SETTEXT: 0x51, // display text
CLRMIXED: 0x52, // clear mixed mode- enable full graphics
@ -88,10 +77,7 @@ export default function Apple2IO(cpu, callbacks)
PADDLE2: 0x66, // bit 7: status of pdl-2 timer (read)
PADDLE3: 0x67, // bit 7: status of pdl-3 timer (read)
PDLTRIG: 0x70, // trigger paddles
BANK: 0x73, // Back switched RAM card bank
ACCEL: 0x74, // CPU Speed control
SETIOUDIS:0x7E, // Enable double hires
CLRIOUDIS:0x7F // Disable double hires
};
function init() {
@ -134,83 +120,35 @@ export default function Apple2IO(cpu, callbacks)
var now = cpu.cycles();
var delta = now - _trigger;
switch (off) {
case LOC.CLR80VID:
if (callbacks._80col && val !== undefined) {
_debug('80 Column Mode off');
callbacks._80col(false);
}
break;
case LOC.SET80VID:
if (callbacks._80col && val !== undefined) {
_debug('80 Column Mode on');
callbacks._80col(true);
}
break;
case LOC.CLRALTCH:
if (callbacks.altchar && val !== undefined) {
_debug('Alt Char off');
callbacks.altchar(false);
}
break;
case LOC.SETALTCH:
if (callbacks.altchar && val !== undefined) {
_debug('Alt Char on');
callbacks.altchar(true);
}
break;
case LOC.CLRTEXT:
_debug('Graphics Mode');
callbacks.text(false);
vm.text(false);
break;
case LOC.SETTEXT:
_debug('Text Mode');
callbacks.text(true);
vm.text(true);
break;
case LOC.CLRMIXED:
_debug('Mixed Mode off');
callbacks.mixed(false);
vm.mixed(false);
break;
case LOC.SETMIXED:
_debug('Mixed Mode on');
callbacks.mixed(true);
vm.mixed(true);
break;
case LOC.CLRHIRES:
_debug('LoRes Mode');
callbacks.hires(false);
vm.hires(false);
break;
case LOC.SETHIRES:
_debug('HiRes Mode');
callbacks.hires(true);
vm.hires(true);
break;
case LOC.PAGE1:
callbacks.page(1);
vm.page(1);
break;
case LOC.PAGE2:
callbacks.page(2);
break;
case LOC.RDTEXT:
if (callbacks.isText)
result = callbacks.isText() ? 0x80 : 0x0;
break;
case LOC.RDMIXED:
if (callbacks.isMixed)
result = callbacks.isMixed() ? 0x80 : 0x0;
break;
case LOC.RDPAGE2:
if (callbacks.isPage2)
result = callbacks.isPage2() ? 0x80 : 0x0;
break;
case LOC.RDHIRES:
if (callbacks.isHires)
result = callbacks.isHires() ? 0x80 : 0x0;
break;
case LOC.RD80VID:
if (callbacks.is80Col)
result = callbacks.is80Col() ? 0x80 : 0x0;
break;
case LOC.RDALTCH:
if (callbacks.isAltChar)
result = callbacks.isAltChar() ? 0x80 : 0x0;
vm.page(2);
break;
case LOC.SETAN0:
_debug('Annunciator 0 on');
@ -227,7 +165,6 @@ export default function Apple2IO(cpu, callbacks)
case LOC.SETAN3:
_debug('Annunciator 3 on');
_annunciators[3] = true;
if (callbacks.an3) callbacks.an3(true);
break;
case LOC.CLRAN0:
_debug('Annunciator 0 off');
@ -244,26 +181,6 @@ export default function Apple2IO(cpu, callbacks)
case LOC.CLRAN3:
_debug('Annunciator 3 off');
_annunciators[3] = false;
if (callbacks.an3) callbacks.an3(false);
break;
case LOC.SPEAKER:
_phase = -_phase;
_didAudio = true;
_tick();
break;
case LOC.STROBE:
_key &= 0x7f;
if (_buffer.length > 0) {
val = _buffer.shift();
if (val == '\n') {
val = '\r';
}
_key = val.charCodeAt(0) | 0x80;
}
result = (_keyDown ? 0x80 : 0x00) | _key;
break;
case LOC.KEYBOARD:
result = _key;
break;
case LOC.PB0:
result = _button[0] ? 0x80 : 0;
@ -286,19 +203,11 @@ export default function Apple2IO(cpu, callbacks)
case LOC.PADDLE3:
result = (delta < (_paddle[3] * 2756) ? 0x80 : 0x00);
break;
case LOC.PDLTRIG:
_trigger = cpu.cycles();
break;
case LOC.ACCEL:
if (val !== undefined) {
_updateKHz(val & 0x01 ? 1023 : 4096);
}
break;
case LOC.RDDHIRES:
if (callbacks.isDoubleHires) {
result = callbacks.isDoubleHires() ? 0x80 : 0x0;
}
break;
case LOC.TAPEIN:
if (_tapeOffset == -1) {
_tapeOffset = 0;
@ -318,6 +227,41 @@ export default function Apple2IO(cpu, callbacks)
}
result = _tapeCurrent ? 0x80 : 0x00;
break;
default:
switch (off & 0xf0) {
case LOC.KEYBOARD: // C00x
result = _key;
break;
case LOC.STROBE: // C01x
_key &= 0x7f;
if (_buffer.length > 0) {
val = _buffer.shift();
if (val == '\n') {
val = '\r';
}
_key = val.charCodeAt(0) | 0x80;
}
result = (_keyDown ? 0x80 : 0x00) | _key;
break;
case LOC.TAPEOUT: // C02x
_phase = -_phase;
_didAudio = true;
_tick();
break;
case LOC.SPEAKER: // C03x
_phase = -_phase;
_didAudio = true;
_tick();
break;
case LOC.C040STB: // C04x
// I/O Strobe
break;
case LOC.PDLTRIG: // C07x
_trigger = cpu.cycles();
break;
}
}
if (val !== undefined) {
@ -358,7 +302,7 @@ export default function Apple2IO(cpu, callbacks)
card.reset();
}
}
callbacks.reset();
vm.reset();
},
blit: function apple2io_blit() {

View File

@ -1010,6 +1010,9 @@ export function VideoModes(gr, hgr, gr2, hgr2, e) {
_refresh();
}
},
doubleHires: function(on) {
this.an3(!on);
},
mixed: function(on) {
var old = mixedMode;
mixedMode = on;
@ -1042,6 +1045,9 @@ export function VideoModes(gr, hgr, gr2, hgr2, e) {
isHires: function() {
return hiresMode;
},
isDoubleHires: function() {
return doubleHiresMode;
},
is80Col: function() {
return _80colMode;
},

125
js/mmu.js
View File

@ -26,12 +26,12 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
var _writebsr;
var _prewrite;
// Auxilliary ROM
// Auxillary ROM
var _intcxrom;
var _slot3rom;
var _intc8rom;
// Auxilliary RAM
// Auxillary RAM
var _auxRamRead;
var _auxRamWrite;
var _altzp;
@ -41,6 +41,8 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
var _page2;
var _hires;
var _iouDisable;
var _vbEnd = 0;
/*
@ -67,6 +69,11 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
SLOTC3ROMOFF: 0x0A,
SLOTC3ROMON: 0x0B,
CLR80VID: 0x0C, // clear 80 column mode
SET80VID: 0x0D, // set 80 column mode
CLRALTCH: 0x0E, // clear mousetext
SETALTCH: 0x0F, // set mousetext
// Status
BSRBANK2: 0x11,
BSRREADRAM: 0x12,
@ -78,11 +85,26 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
_80STORE: 0x18,
VERTBLANK: 0x19,
RDTEXT: 0x1A, // using text mode
RDMIXED: 0x1B, // using mixed mode
RDPAGE2: 0x1C, // using text/graphics page2
RDHIRES: 0x1D, // using Hi-res graphics mode
RDALTCH: 0x1E, // using alternate character set
RD80VID: 0x1F, // using 80-column display mode
PAGE1: 0x54, // select text/graphics page1 main/aux
PAGE2: 0x55, // select text/graphics page2 main/aux
RESET_HIRES: 0x56,
SET_HIRES: 0x57,
DHIRESON: 0x5E, // Enable double hires
DHIRESOFF: 0x5F, // Disable double hires
BANK: 0x73, // Back switched RAM card bank
IOUDISON: 0x7E, // W IOU Disable on / R7 IOU Disable
IOUDISOFF: 0x7F, // W IOU Disable off / R7 Double Hires
// Bank 2
READBSR2: 0x80,
WRITEBSR2: 0x81,
@ -125,6 +147,8 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
_80store = false;
_page2 = false;
_hires = false;
_iouDisable = true;
}
function _debug() {
@ -400,12 +424,13 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
function _access(off, val) {
var result;
var readMode = val === undefined;
var writeMode = val !== undefined;
switch (off) {
// Apple //e memory management
case LOC._80STOREOFF:
if (val !== undefined) {
if (writeMode) {
_80store = false;
_debug('80 Store Off');
vm.page(_page2 ? 2 : 1);
@ -415,35 +440,35 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
}
break;
case LOC._80STOREON:
if (val !== undefined) {
if (writeMode) {
_80store = true;
_debug('80 Store On');
} else
result = 0;
break;
case LOC.RAMRDOFF:
if (val !== undefined) {
if (writeMode) {
_auxRamRead = false;
_debug('Aux RAM Read Off');
} else
result = 0;
break;
case LOC.RAMRDON:
if (val !== undefined) {
if (writeMode) {
_auxRamRead = true;
_debug('Aux RAM Read On');
} else
result = 0;
break;
case LOC.RAMWROFF:
if (val !== undefined) {
if (writeMode) {
_auxRamWrite = false;
_debug('Aux RAM Write Off');
} else
result = 0;
break;
case LOC.RAMWRON:
if (val !== undefined) {
if (writeMode) {
_auxRamWrite = true;
_debug('Aux RAM Write On');
} else
@ -451,38 +476,38 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
break;
case LOC.INTCXROMOFF:
if (val !== undefined) {
if (writeMode) {
_intcxrom = false;
_intc8rom = false;
_debug('Int CX ROM Off');
}
break;
case LOC.INTCXROMON:
if (val !== undefined) {
if (writeMode) {
_intcxrom = true;
_debug('Int CX ROM On');
}
break;
case LOC.ALTZPOFF: // 0x08
if (val !== undefined) {
if (writeMode) {
_altzp = false;
_debug('Alt ZP Off');
}
break;
case LOC.ALTZPON: // 0x09
if (val !== undefined) {
if (writeMode) {
_altzp = true;
_debug('Alt ZP On');
}
break;
case LOC.SLOTC3ROMOFF: // 0x0A
if (val !== undefined) {
if (writeMode) {
_slot3rom = false;
_debug('Slot 3 ROM Off');
}
break;
case LOC.SLOTC3ROMON: // 0x0B
if (val !== undefined) {
if (writeMode) {
_slot3rom = true;
_debug('Slot 3 ROM On');
}
@ -490,6 +515,30 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
// Graphics Switches
case LOC.CLR80VID:
if (writeMode) {
_debug('80 Column Mode off');
vm._80col(false);
}
break;
case LOC.SET80VID:
if (writeMode) {
_debug('80 Column Mode on');
vm._80col(true);
}
break;
case LOC.CLRALTCH:
if (writeMode) {
_debug('Alt Char off');
vm.altchar(false);
}
break;
case LOC.SETALTCH:
if (writeMode) {
_debug('Alt Char on');
vm.altchar(true);
}
break;
case LOC.PAGE1:
_page2 = false;
if (!_80store) {
@ -511,12 +560,42 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
_debug('Hires off');
break;
case LOC.DHIRESON:
if (_iouDisable) {
vm.doubleHires(true);
} else {
result = io.ioSwitch(off, val); // an3
}
break;
case LOC.DHIRESOFF:
if (_iouDisable) {
vm.doubleHires(false);
} else {
result = io.ioSwitch(off, val); // an3
}
break;
case LOC.SET_HIRES:
_hires = true;
result = io.ioSwitch(off, val);
_debug('Hires on');
break;
case LOC.IOUDISON:
if (writeMode) {
_iouDisable = true;
}
result = _iouDisable ? 0x00 : 0x80;
break;
case LOC.IOUDISOFF:
if (writeMode) {
_iouDisable = false;
}
result = vm.isDoubleHires() ? 0x80 : 0x00;
break;
// Language Card Switches
case LOC.READBSR2: // 0xC080
@ -622,6 +701,24 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom)
// result = cpu.cycles() % 20 < 5 ? 0x80 : 0x00;
result = (cpu.cycles() < _vbEnd) ? 0x80 : 0x00;
break;
case LOC.RDTEXT:
result = vm.isText() ? 0x80 : 0x0;
break;
case LOC.RDMIXED:
result = vm.isMixed() ? 0x80 : 0x0;
break;
case LOC.RDPAGE2:
result = vm.isPage2() ? 0x80 : 0x0;
break;
case LOC.RDHIRES:
result = vm.isHires() ? 0x80 : 0x0;
break;
case LOC.RD80VID:
result = vm.is80Col() ? 0x80 : 0x0;
break;
case LOC.RDALTCH:
result = vm.isAltChar() ? 0x80 : 0x0;
break;
default:
debug('MMU missing register ' + toHex(off));