/* Copyright 2010-2019 Will Scullin * * 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(); } }; }