apple2js/js/cards/langcard.js
2020-01-02 10:57:26 -08:00

211 lines
5.3 KiB
JavaScript

/* Copyright 2010-2019 Will Scullin <scullin@scullinsteel.com>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*/
import RAM from '../ram';
import { debug } from '../util';
export default function LanguageCard(io, rom) {
var _rom = rom;
var _bank1 = null;
var _bank2 = null;
var _ram = null;
var _readbsr = false;
var _writebsr = false;
var _bsr2 = false;
var _prewrite = false;
var _read1 = null;
var _read2 = null;
var _write1 = null;
var _write2 = null;
function _init() {
debug('Language card');
_bank1 = new RAM(0xd0, 0xdf);
_bank2 = new RAM(0xd0, 0xdf);
_ram = new RAM(0xe0, 0xff);
_write1 = _rom;
_write2 = _rom;
_read1 = _rom;
_read2 = _rom;
}
function _debug() {
// debug.apply(null, arguments);
}
_init();
var LOC = {
// Bank 2
READBSR2: 0x80,
WRITEBSR2: 0x81,
OFFBSR2: 0x82,
READWRBSR2: 0x83,
// Bank 1
READBSR1: 0x88,
WRITEBSR1: 0x89,
OFFBSR1: 0x8a,
READWRBSR1: 0x8b,
};
function _updateBanks() {
if (_readbsr) {
_read1 = _bsr2 ? _bank2 : _bank1;
_read2 = _ram;
} else {
_read1 = _rom;
_read2 = _rom;
}
if (_writebsr) {
_write1 = _bsr2 ? _bank2 : _bank1;
_write2 = _ram;
} else {
_write1 = rom;
_write2 = rom;
}
}
function _access(off, val) {
var readMode = val === undefined;
var result = 0;
switch (off & 0x8B) {
case LOC.READBSR2: // 0xC080
_readbsr = true;
_writebsr = false;
_bsr2 = true;
_prewrite = false;
_debug('Bank 2 Read');
break;
case LOC.WRITEBSR2: // 0xC081
_readbsr = false;
if (readMode) {
_writebsr = _prewrite;
}
_bsr2 = true;
_prewrite = readMode;
_debug('Bank 2 Write');
break;
case LOC.OFFBSR2: // 0xC082
_readbsr = false;
_writebsr = false;
_bsr2 = true;
_prewrite = false;
_debug('Bank 2 Off');
break;
case LOC.READWRBSR2: // 0xC083
_readbsr = true;
if (readMode) {
_writebsr = _prewrite;
}
_bsr2 = true;
_prewrite = readMode;
_debug('Bank 2 Read/Write');
break;
case LOC.READBSR1: // 0xC088
_readbsr = true;
_writebsr = false;
_bsr2 = false;
_prewrite = false;
_debug('Bank 1 Read');
break;
case LOC.WRITEBSR1: // 0xC089
_readbsr = false;
if (readMode) {
_writebsr = _prewrite;
}
_bsr2 = false;
_prewrite = readMode;
_debug('Bank 1 Write');
break;
case LOC.OFFBSR1: // 0xC08A
_readbsr = false;
_writebsr = false;
_bsr2 = false;
_prewrite = false;
_debug('Bank 1 Off');
break;
case LOC.READWRBSR1: // 0xC08B
_readbsr = true;
if (readMode) {
_writebsr = _prewrite;
}
_bsr2 = false;
_prewrite = readMode;
_debug('Bank 1 Read/Write');
break;
default:
break;
}
_updateBanks();
return result;
}
return {
start: function() {
return 0xd0;
},
end: function() {
return 0xff;
},
ioSwitch: function(off, val) {
return _access(off, val);
},
read: function(page, off) {
var result = 0;
if (page < 0xe0) {
result = _read1.read(page, off);
} else {
result = _read2.read(page, off);
}
return result;
},
write: function(page, off, val) {
if (page < 0xe0) {
_write1.write(page, off, val);
} else {
_write2.write(page, off, val);
}
},
getState: function() {
return {
readbsr: _readbsr,
writebsr: _writebsr,
bsr2: _bsr2,
prewrite: _prewrite,
ram: _ram.getState(),
bank1: _bank1.getState(),
bank2: _bank2.getState()
};
},
setState: function(state) {
_readbsr = state.readbsr;
_writebsr = state.writebsr;
_bsr2 = state.bsr2;
_prewrite = state.prewrite;
_ram.setState(state.ram);
_bank1.setState(state.bank1);
_bank2.setState(state.bank2);
_updateBanks();
}
};
}