From f75a2fa962051b5f84cfc67538aa851a87e2ce7f Mon Sep 17 00:00:00 2001 From: Will Scullin Date: Sun, 29 Dec 2019 19:13:59 -0800 Subject: [PATCH] Fix acceleration, normalize heavily used signatures. (#18) --- js/apple2.js | 3 +- js/apple2io.js | 39 ++++++++++++++----- js/applesoft/decompiler.js | 2 +- js/cards/langcard.js | 6 +-- js/cpu6502.js | 79 +++++++++++++++++++++----------------- js/mmu.js | 6 +-- js/ui/apple2.js | 10 ++--- js/ui/tape.js | 2 +- 8 files changed, 86 insertions(+), 61 deletions(-) diff --git a/js/apple2.js b/js/apple2.js index 96ce044..ad68106 100644 --- a/js/apple2.js +++ b/js/apple2.js @@ -12,8 +12,6 @@ export function Apple2(options) { renderedFrames: 0 }; - var kHz = 1023; - var paused = false; var DEBUG = false; @@ -77,6 +75,7 @@ export function Apple2(options) { var now, last = Date.now(); var runFn = function() { + var kHz = io.getKHz(); now = Date.now(); var step = (now - last) * kHz, stepMax = kHz * interval; diff --git a/js/apple2io.js b/js/apple2io.js index 67bbb2b..222ad7a 100644 --- a/js/apple2io.js +++ b/js/apple2io.js @@ -16,11 +16,11 @@ export default function Apple2IO(cpu, callbacks) var _slot = []; var _auxRom = null; - var _hz = 1023000; + var _khz = 1023; var _rate = 44000; var _sample_size = 4096; - var _cycles_per_sample = _hz / _rate; + var _cycles_per_sample; var _buffer = []; var _key = 0; @@ -88,10 +88,15 @@ export default function Apple2IO(cpu, callbacks) 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() { + _calcSampleRate(); + } + function _debug() { // debug.apply(this, arguments); } @@ -111,6 +116,17 @@ export default function Apple2IO(cpu, callbacks) } } + function _calcSampleRate() { + _cycles_per_sample = _khz * 1000 / _rate; + } + + function _updateKHz(khz) { + _khz = khz; + _calcSampleRate(); + } + + init(); + function _access(off, val) { var result = 0; var now = cpu.cycles(); @@ -271,6 +287,11 @@ export default function Apple2IO(cpu, callbacks) 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; @@ -353,7 +374,7 @@ export default function Apple2IO(cpu, callbacks) switch (page) { case 0xc0: - result = this.ioSwitch(off); + result = this.ioSwitch(off, undefined); break; case 0xc1: case 0xc2: @@ -448,14 +469,12 @@ export default function Apple2IO(cpu, callbacks) _paddle[p] = v; }, - updateHz: function apple2io_updateHz(hz) { - _hz = hz; - - _cycles_per_sample = _hz / _rate; + updateKHz: function apple2io_updateKHz(khz) { + _updateKHz(khz); }, - getHz: function apple2io_updateHz() { - return _hz; + getKHz: function apple2io_updateKHz() { + return _khz; }, setKeyBuffer: function apple2io_setKeyBuffer(buffer) { @@ -474,7 +493,7 @@ export default function Apple2IO(cpu, callbacks) sampleRate: function sampleRate(rate) { _rate = rate; - _cycles_per_sample = _hz / _rate; + _calcSampleRate(); }, tick: function tick() { diff --git a/js/applesoft/decompiler.js b/js/applesoft/decompiler.js index f33e4e2..b78f899 100644 --- a/js/applesoft/decompiler.js +++ b/js/applesoft/decompiler.js @@ -121,7 +121,7 @@ export default function ApplesoftDump(mem) var page = addr >> 8, off = addr & 0xff; - return _mem.read(page, off, true); + return _mem.read(page, off); } function readWord(addr) { diff --git a/js/cards/langcard.js b/js/cards/langcard.js index bef178f..a780ae7 100644 --- a/js/cards/langcard.js +++ b/js/cards/langcard.js @@ -203,12 +203,12 @@ export default function LanguageCard(io, rom) { ioSwitch: function(off, val) { return _access(off, val); }, - read: function(page, off, dbg) { + read: function(page, off) { var result = 0; if (page < 0xe0) { - result = _read1.read(page, off, dbg); + result = _read1.read(page, off); } else { - result = _read2.read(page, off, dbg); + result = _read2.read(page, off); } return result; }, diff --git a/js/cpu6502.js b/js/cpu6502.js index 67ac350..726b839 100644 --- a/js/cpu6502.js +++ b/js/cpu6502.js @@ -170,33 +170,38 @@ export default function CPU6502(options) return testNZ((a + 0xff) & 0xff); } - function readBytePC(dbg) { - var addr = (pc++) & 0xffff, + function readBytePC() { + var addr = pc, page = addr >> 8, off = addr & 0xff; - var result = readPages[page].read(page, off, dbg); + var result = readPages[page].read(page, off); - if (!dbg) { - cycles++; - } + pc = (pc + 1) & 0xffff; + + cycles++; return result; } - function readByte(addr, dbg) { + function readByte(addr) { var page = addr >> 8, off = addr & 0xff; - var result = readPages[page].read(page, off, dbg); + var result = readPages[page].read(page, off); - if (!dbg) { - cycles++; - } + cycles++; return result; } + function readByteDebug(addr) { + var page = addr >> 8, + off = addr & 0xff; + + return readPages[page].read(page, off); + } + function writeByte(addr, val) { var page = addr >> 8, off = addr & 0xff; @@ -206,19 +211,23 @@ export default function CPU6502(options) cycles++; } - function readWord(addr, dbg) { - return readByte(addr, dbg) | (readByte(addr + 1, dbg) << 8); + function readWord(addr) { + return readByte(addr) | (readByte(addr + 1) << 8); } - function readWordPC(dbg) { - return readBytePC(dbg) | (readBytePC(dbg) << 8); + function readWordDebug(addr) { + return readByteDebug(addr) | (readByteDebug(addr + 1) << 8); } - function readZPWord(addr, dbg) { + function readWordPC() { + return readBytePC() | (readBytePC() << 8); + } + + function readZPWord(addr) { var lsb, msb; - lsb = readByte(addr & 0xff, dbg); - msb = readByte((addr + 1) & 0xff, dbg); + lsb = readByte(addr & 0xff); + msb = readByte((addr + 1) & 0xff); return (msb << 8) | lsb; } @@ -1310,17 +1319,17 @@ export default function CPU6502(options) case modes.implied: break; case modes.immediate: - result = '#' + toHexOrSymbol(readByte(addr, true)); + result = '#' + toHexOrSymbol(readByteDebug(addr)); break; case modes.absolute: - result = '' + toHexOrSymbol(readWord(addr, true), 4); + result = '' + toHexOrSymbol(readWordDebug(addr), 4); break; case modes.zeroPage: - result = '' + toHexOrSymbol(readByte(addr, true)); + result = '' + toHexOrSymbol(readByteDebug(addr)); break; case modes.relative: { - off = readByte(addr, true); + off = readByteDebug(addr); if (off > 127) { off -= 256; } @@ -1329,38 +1338,38 @@ export default function CPU6502(options) } break; case modes.absoluteX: - result = '' + toHexOrSymbol(readWord(addr, true), 4) + ',X'; + result = '' + toHexOrSymbol(readWordDebug(addr), 4) + ',X'; break; case modes.absoluteY: - result = '' + toHexOrSymbol(readWord(addr, true), 4) + ',Y'; + result = '' + toHexOrSymbol(readWordDebug(addr), 4) + ',Y'; break; case modes.zeroPageX: - result = '' + toHexOrSymbol(readByte(addr, true)) + ',X'; + result = '' + toHexOrSymbol(readByteDebug(addr)) + ',X'; break; case modes.zeroPageY: - result = '' + toHexOrSymbol(readByte(addr, true)) + ',Y'; + result = '' + toHexOrSymbol(readByteDebug(addr)) + ',Y'; break; case modes.absoluteIndirect: - result = '(' + toHexOrSymbol(readWord(addr, true), 4) + ')'; + result = '(' + toHexOrSymbol(readWordDebug(addr), 4) + ')'; break; case modes.zeroPageXIndirect: - result = '(' + toHexOrSymbol(readByte(addr, true)) + ',X)'; + result = '(' + toHexOrSymbol(readByteDebug(addr)) + ',X)'; break; case modes.zeroPageIndirectY: - result = '(' + toHexOrSymbol(readByte(addr, true)) + '),Y'; + result = '(' + toHexOrSymbol(readByteDebug(addr)) + '),Y'; break; case modes.accumulator: result = 'A'; break; case modes.zeroPageIndirect: - result = '(' + toHexOrSymbol(readByte(addr, true)) + ')'; + result = '(' + toHexOrSymbol(readByteDebug(addr)) + ')'; break; case modes.absoluteXIndirect: - result = '(' + toHexOrSymbol(readWord(addr, true), 4) + ',X)'; + result = '(' + toHexOrSymbol(readWordDebug(addr), 4) + ',X)'; break; case modes.zeroPage_relative: - val = readByte(addr, true); - off = readByte(addr + 1, true); + val = readByteDebug(addr); + off = readByteDebug(addr + 1); if (off > 127) { off -= 256; } @@ -1534,7 +1543,7 @@ export default function CPU6502(options) for (idx = 0; idx < 16; idx++) { result += toHex(page) + toHex(idx << 4) + ': '; for (jdx = 0; jdx < 16; jdx++) { - b = readByte(page * 256 + idx * 16 + jdx, true); + b = readByteDebug(page * 256 + idx * 16 + jdx); result += toHex(b) + ' '; } result += ' '; @@ -1618,7 +1627,7 @@ export default function CPU6502(options) }, read: function(page, off) { - return readPages[page].read(page, off, false); + return readPages[page].read(page, off); }, write: function(page, off, val) { diff --git a/js/mmu.js b/js/mmu.js index 5aa48e3..145ef79 100644 --- a/js/mmu.js +++ b/js/mmu.js @@ -153,7 +153,7 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom) if (off in locs) { result = _access(off); } else { - result = io.ioSwitch(off); + result = io.ioSwitch(off, undefined); } return result; }, @@ -656,8 +656,8 @@ export default function MMU(cpu, vm, lores1, lores2, hires1, hires2, io, rom) vm.reset(); io.reset(); }, - read: function mmu_read(page, off, debug) { - return _readPages[page].read(page, off, debug); + read: function mmu_read(page, off) { + return _readPages[page].read(page, off); }, write: function mmu_write(page, off, val) { _writePages[page].write(page, off, val); diff --git a/js/ui/apple2.js b/js/ui/apple2.js index 3a28092..3309e81 100644 --- a/js/ui/apple2.js +++ b/js/ui/apple2.js @@ -13,8 +13,6 @@ import ApplesoftCompiler from '../applesoft/compiler'; import { debug, gup, hup } from '../util'; import Prefs from '../prefs'; -var kHz = 1023; - var focused = false; var startTime = Date.now(); var lastCycles = 0; @@ -149,8 +147,8 @@ export function loadAjax(drive, url) { initGamepad(data.gamepad); MicroModal.close('loading-modal'); }).catch(function(error) { - window.alert(error.message); MicroModal.close('loading-modal'); + window.alert(error.message); }); } @@ -494,7 +492,7 @@ function processHash(hash) { } else { doLoadHTTP(idx + 1, file); } - } else { + } else if (file) { loadAjax(idx + 1, 'json/disks/' + file + '.json'); } } @@ -593,8 +591,8 @@ export function updateScreen() { export function updateCPU() { var accelerated = document.querySelector('#accelerator_toggle').checked; - kHz = accelerated ? 4092 : 1023; - io.updateHz(kHz * 1000); + var kHz = accelerated ? 4092 : 1023; + io.updateKHz(kHz); } export function updateUI() { diff --git a/js/ui/tape.js b/js/ui/tape.js index dc4306c..ded5a45 100644 --- a/js/ui/tape.js +++ b/js/ui/tape.js @@ -19,7 +19,7 @@ export default function Tape(io) { return { doLoadLocalTape: function(file, done) { - var kHz = io.getHz() / 1000; + var kHz = io.getKHz(); // Audio Buffer Source var context;