mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
223 lines
5.6 KiB
JavaScript
223 lines
5.6 KiB
JavaScript
|
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||
|
/* Copyright 2010-2013 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.
|
||
|
*/
|
||
|
|
||
|
/*globals RAM */
|
||
|
/*exported LanguageCard */
|
||
|
|
||
|
function LanguageCard(io, rom) {
|
||
|
var _io = io;
|
||
|
var _rom = rom;
|
||
|
var _bank1 = null;
|
||
|
var _bank2 = null;
|
||
|
var _ram = null;
|
||
|
|
||
|
var _readbsr = false;
|
||
|
var _writebsr = false;
|
||
|
var _bsr2 = false;
|
||
|
|
||
|
var _last = 0x00;
|
||
|
|
||
|
var _read1 = null;
|
||
|
var _read2 = null;
|
||
|
|
||
|
var _write1 = null;
|
||
|
var _write2 = null;
|
||
|
|
||
|
function _init() {
|
||
|
_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(arguments);
|
||
|
}
|
||
|
|
||
|
_init();
|
||
|
|
||
|
var LOC = {
|
||
|
// Status
|
||
|
BSRBANK2: 0x11,
|
||
|
BSRREADRAM: 0x12,
|
||
|
|
||
|
// Bank 2
|
||
|
READBSR2: 0x80,
|
||
|
WRITEBSR2: 0x81,
|
||
|
OFFBSR2: 0x82,
|
||
|
READWRBSR2: 0x83,
|
||
|
|
||
|
// Shadow Bank 2
|
||
|
_READBSR2: 0x84,
|
||
|
_WRITEBSR2: 0x85,
|
||
|
_OFFBSR2: 0x86,
|
||
|
_READWRBSR2: 0x87,
|
||
|
|
||
|
// Bank 1
|
||
|
READBSR1: 0x88,
|
||
|
WRITEBSR1: 0x89,
|
||
|
OFFBSR1: 0x8a,
|
||
|
READWRBSR1: 0x8b,
|
||
|
|
||
|
// Shadow Bank 1
|
||
|
_READBSR1: 0x8c,
|
||
|
_WRITEBSR1: 0x8d,
|
||
|
_OFFBSR1: 0x8e,
|
||
|
_READWRBSR1: 0x8f
|
||
|
};
|
||
|
|
||
|
function _access(off) {
|
||
|
var result = 0;
|
||
|
switch (off) {
|
||
|
case LOC.READBSR2:
|
||
|
case LOC._READBSR2:
|
||
|
_readbsr = true;
|
||
|
_writebsr = false;
|
||
|
_bsr2 = true;
|
||
|
_debug("Bank 2 Read");
|
||
|
break;
|
||
|
case LOC.WRITEBSR2:
|
||
|
case LOC._WRITEBSR2:
|
||
|
_readbsr = false;
|
||
|
_writebsr = ((_last & 0xF3) == (off & 0xF3));
|
||
|
_bsr2 = true;
|
||
|
_debug("Bank 2 Write");
|
||
|
break;
|
||
|
case LOC.OFFBSR2:
|
||
|
case LOC._OFFBSR2:
|
||
|
_readbsr = false;
|
||
|
_writebsr = false;
|
||
|
_bsr2 = true;
|
||
|
_debug("Bank 2 Off");
|
||
|
break;
|
||
|
case LOC.READWRBSR2:
|
||
|
case LOC._READWRBSR2:
|
||
|
_readbsr = true;
|
||
|
_writebsr = ((_last & 0xF3) == (off & 0xF3));
|
||
|
_bsr2 = true;
|
||
|
_debug("Bank 2 Read/Write");
|
||
|
break;
|
||
|
|
||
|
case LOC.READBSR1:
|
||
|
case LOC._READBSR1:
|
||
|
_readbsr = true;
|
||
|
_writebsr = false;
|
||
|
_bsr2 = false;
|
||
|
_debug("Bank 1 Read");
|
||
|
break;
|
||
|
case LOC.WRITEBSR1:
|
||
|
case LOC._WRITEBSR1:
|
||
|
_readbsr = false;
|
||
|
_writebsr = ((_last & 0xF3) == (off & 0xF3));
|
||
|
_bsr2 = false;
|
||
|
_debug("Bank 1 Write");
|
||
|
break;
|
||
|
case LOC.OFFBSR1:
|
||
|
case LOC._OFFBSR1:
|
||
|
_readbsr = false;
|
||
|
_writebsr = false;
|
||
|
_bsr2 = false;
|
||
|
_debug("Bank 1 Off");
|
||
|
break;
|
||
|
case LOC.READWRBSR1:
|
||
|
case LOC._READWRBSR1:
|
||
|
_readbsr = true;
|
||
|
_writebsr = ((_last & 0xF3) == (off & 0xF3));
|
||
|
_bsr2 = false;
|
||
|
_debug("Bank 1 Read/Write");
|
||
|
break;
|
||
|
|
||
|
case LOC.BSRBANK2:
|
||
|
result = _bsr2 ? 0x80 : 0x00;
|
||
|
_debug("Bank 2 Read " + _bsr2);
|
||
|
break;
|
||
|
case LOC.BSRREADRAM:
|
||
|
result = _readbsr ? 0x80 : 0x00;
|
||
|
_debug("Bank SW RAM Read " + _readbsr);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
_last = off;
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
return {
|
||
|
start: function() {
|
||
|
_io.registerSwitches(this, LOC);
|
||
|
return 0xd0;
|
||
|
},
|
||
|
end: function() {
|
||
|
return 0xff;
|
||
|
},
|
||
|
ioSwitch: function(off, val) {
|
||
|
return _access(off, val);
|
||
|
},
|
||
|
read: function(page, off, dbg) {
|
||
|
var result = 0;
|
||
|
if (page < 0xe0) {
|
||
|
result = _read1.read(page, off, dbg);
|
||
|
} else {
|
||
|
result = _read2.read(page, off, dbg);
|
||
|
}
|
||
|
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,
|
||
|
last: _last,
|
||
|
bank1: _bank1.getState(),
|
||
|
bank2: _bank2.getState()
|
||
|
};
|
||
|
},
|
||
|
setState: function(state) {
|
||
|
_readbsr = state.readbsr;
|
||
|
_writebsr = state.writebsr;
|
||
|
_bsr2 = state.bsr2;
|
||
|
_bank1.setState(state.bank1);
|
||
|
_bank2.setState(state.bank2);
|
||
|
_access(-1);
|
||
|
_last = state.last;
|
||
|
}
|
||
|
};
|
||
|
}
|