diff --git a/javatari.js b/javatari.js index bd17384f..4326d966 160000 --- a/javatari.js +++ b/javatari.js @@ -1 +1 @@ -Subproject commit bd17384fd2c6b020497e5e6a625a1b8130e39ea1 +Subproject commit 4326d966e3adf16a8abe4a83f1c98359a825b5d9 diff --git a/src/audio.ts b/src/audio.ts index f9d5ae19..86c6be20 100644 --- a/src/audio.ts +++ b/src/audio.ts @@ -472,3 +472,20 @@ export var SampleAudio = function(clockfreq) { } } } + + +export class SampledAudio { + sa; + constructor(sampleRate : number) { + this.sa = new SampleAudio(sampleRate); + } + feedSample(value:number, count:number) { + this.sa.feedSample(value, count); + } + start() { + this.sa.start(); + } + stop() { + this.sa.stop(); + } +} diff --git a/src/baseplatform.ts b/src/baseplatform.ts index d8026ead..950b4958 100644 --- a/src/baseplatform.ts +++ b/src/baseplatform.ts @@ -17,7 +17,7 @@ export interface OpcodeMetadata { export interface CpuState { PC:number; EPC?:number; // effective PC (for bankswitching) - T?:number; + T?:number; // TODO: remove in favor of 'stable' o?:number;/*opcode*/ SP?:number /* diff --git a/src/nemu/cpu/MOS6502.ts b/src/nemu/cpu/MOS6502.ts index afad2c40..224ed83b 100644 --- a/src/nemu/cpu/MOS6502.ts +++ b/src/nemu/cpu/MOS6502.ts @@ -61,7 +61,7 @@ var _MOS6502 = function() { // Internal decoding registers var T : number = -1; var opcode : number = -1; - var instruction; + var instruction : (() => void)[]; var data : number = 0; var AD : number = 0; var BA : number = 0; @@ -90,6 +90,7 @@ var _MOS6502 = function() { const bC = 0; // Auxiliary variables + // TODO //noinspection JSUnusedGlobalSymbols this.debug = false; //noinspection JSUnusedGlobalSymbols @@ -1888,6 +1889,12 @@ var _MOS6502 = function() { this.getSP = function() { return SP; } this.getPC = function() { return PC; } this.getT = function() { return T; } + + this.isPCStable = function() { + // TODO: gotta fix base class first + //return T < 0 || T == instruction.length-1; + return T == 0; + } }; export interface MOS6502State { @@ -1909,7 +1916,7 @@ export class MOS6502 implements CPU, ClockBased, SavesState, Inter this.cpu.connectBus(bus); } advanceClock() { - if (this.interruptType && this.cpu.getT() == 0) { + if (this.interruptType && this.isStable()) { switch (this.interruptType) { case MOS6502Interrupts.NMI: this.cpu.setNMI(); break; case MOS6502Interrupts.IRQ: this.cpu.setIRQ(); break; @@ -1920,7 +1927,7 @@ export class MOS6502 implements CPU, ClockBased, SavesState, Inter advanceInsn() { do { this.advanceClock(); - } while (this.cpu.getT() != 0); + } while (!this.isStable()); } reset() { this.cpu.reset(); @@ -1944,6 +1951,9 @@ export class MOS6502 implements CPU, ClockBased, SavesState, Inter this.cpu.loadState(s); this.interruptType = s.it; } + isStable() : boolean { + return this.cpu.isPCStable(); + } // TODO: metadata // TODO: disassembler } diff --git a/src/nemu/machine/apple2.ts b/src/nemu/machine/apple2.ts index 77de2227..efed5a0b 100644 --- a/src/nemu/machine/apple2.ts +++ b/src/nemu/machine/apple2.ts @@ -1,7 +1,7 @@ "use strict"; import { MOS6502, MOS6502State } from "../cpu/MOS6502"; -import { Bus, RasterFrameBased, SavesState, AcceptsROM, noise, Resettable } from "../nemu"; +import { Bus, RasterFrameBased, SavesState, AcceptsROM, noise, Resettable, SampledAudioSource, SampledAudioSink } from "../nemu"; import { KeyFlags } from "../../emu"; // TODO import { lzgmini } from "../../util"; @@ -26,11 +26,13 @@ interface AppleIIState extends AppleIIStateBase { c : MOS6502State; } -export class AppleII implements Bus, Resettable, RasterFrameBased, AcceptsROM, AppleIIStateBase, SavesState { +export class AppleII implements Bus, Resettable, RasterFrameBased, SampledAudioSource, AcceptsROM, + AppleIIStateBase, SavesState { ram = new Uint8Array(0x13000); // 64K + 16K LC RAM - 4K hardware + 12K ROM rom : Uint8Array; cpu = new MOS6502(); + audio : SampledAudioSink; pixels : Uint32Array; grdirty = new Array(0xc000 >> 7); grparams = {dirty:this.grdirty, grswitch:GR_TXMODE, mem:this.ram}; @@ -75,6 +77,7 @@ export class AppleII implements Bus, Resettable, RasterFrameBased, AcceptsROM, A loadState(s) { this.cpu.loadState(s.c); this.ram.set(s.ram); + // TODO } reset() { this.cpu.reset(); @@ -175,13 +178,22 @@ export class AppleII implements Bus, Resettable, RasterFrameBased, AcceptsROM, A getVideoParams() { return {width:280, height:192}; } + getAudioParams() { + return {sampleRate:cpuFrequency, stereo:false}; + } connectVideo(pixels:Uint32Array) { this.pixels = pixels; this.ap2disp = pixels && new Apple2Display(this.pixels, this.grparams); } - advanceFrame() : number { - for (var i=0; i> 7); - var grswitch = GR_TXMODE; - var kbdlatch = 0; - var soundstate = 0; - var pgmbin; - // language card switches - var auxRAMselected = false; - var auxRAMbank = 1; - var writeinhibit = true; - // value to add when reading & writing each of these banks - // bank 1 is E000-FFFF, bank 2 is D000-DFFF - var bank2rdoffset=0, bank2wroffset=0; - var grparams : AppleGRParams; - var scanline : number; - - class Apple2Platform extends Base6502Platform implements Platform { - - getPresets() { - return APPLE2_PRESETS; - } - start() { - } - }; - cpu.connectBus(bus); - // create video/audio - video = new RasterVideo(mainElement,280,192); - audio = new SampleAudio(cpuFrequency); - video.create(); - video.setKeyboardEvents((key,code,flags) => { - }); - var idata = video.getFrameData(); - grparams = {dirty:grdirty, grswitch:grswitch, mem:ram.mem}; - ap2disp = new Apple2Display(idata, grparams); - timer = new AnimationTimer(60, this.nextFrame.bind(this)); - } - - advance(novideo : boolean) { - // 262.5 scanlines per frame - var clock = 0; - var debugCond = this.getDebugCallback(); - for (var sl=0; sl<262; sl++) { - scanline = sl; - for (var i=0; i boolean; + export interface FrameBased { - advanceFrame() : number; + advanceFrame(maxClocks:number, trap:TrapCondition) : number; } -export interface VideoFrameBased extends FrameBased { +export interface VideoSource { getVideoParams() : VideoParams; connectVideo(pixels:Uint32Array) : void; } -export interface RasterFrameBased extends VideoFrameBased { +export interface RasterFrameBased extends FrameBased, VideoSource { } export interface VideoParams { @@ -44,9 +46,14 @@ export interface SampledAudioParams { stereo : boolean; } -export interface SampledAudio { - setAudioParams(params:SampledAudioParams) : void; - sendAudioFrame(samples:Uint16Array) : void; +export interface SampledAudioSink { + feedSample(value:number, count:number) : void; + //sendAudioFrame(samples:Uint16Array) : void; +} + +export interface SampledAudioSource { + getAudioParams() : SampledAudioParams; + connectAudio(audio : SampledAudioSink) : void; } export interface AcceptsROM { @@ -94,7 +101,7 @@ export interface Hook { export class BusHook implements Hook { //target : Bus; - constructor(bus : Bus, profiler : ProfilerInterface) { + constructor(bus : Bus, profiler : LogBus) { //this.target = bus; var oldread = bus.read.bind(bus); var oldwrite = bus.write.bind(bus); @@ -117,7 +124,7 @@ export class BusHook implements Hook { export class CPUClockHook implements Hook { //target : CPU&ClockBased; - constructor(cpu : CPU&ClockBased, profiler : ProfilerInterface) { + constructor(cpu : CPU&ClockBased, profiler : LogCPU) { //this.target = cpu; var oldclock = cpu.advanceClock.bind(cpu); cpu.advanceClock = () => { @@ -133,7 +140,7 @@ export class CPUClockHook implements Hook { export class CPUInsnHook implements Hook { //target : CPU&InstructionBased; - constructor(cpu : CPU&InstructionBased, profiler : ProfilerInterface) { + constructor(cpu : CPU&InstructionBased, profiler : LogCPU) { //this.target = cpu; var oldinsn = cpu.advanceInsn.bind(cpu); cpu.advanceInsn = () => { @@ -149,13 +156,22 @@ export class CPUInsnHook implements Hook { /// PROFILER -export interface ProfilerInterface { +export interface LogCPU { logExecute(address:number); + logInterrupt(type:number); +} + +export interface LogBus { logRead(address:number); logWrite(address:number); +} + +export interface LogIO { logIORead(address:number); logIOWrite(address:number); - logInterrupt(type:number); +} + +export interface LogAll extends LogCPU, LogBus, LogIO { } /// DEBUGGING diff --git a/src/platform/apple2.ts b/src/platform/apple2.ts index d75951dd..5847a28f 100644 --- a/src/platform/apple2.ts +++ b/src/platform/apple2.ts @@ -3,7 +3,7 @@ import { Platform, Base6502Platform, BaseMAMEPlatform, getOpcodeMetadata_6502, getToolForFilename_6502 } from "../baseplatform"; import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, KeyFlags, makeKeycodeMap, dumpRAM } from "../emu"; import { hex, lzgmini } from "../util"; -import { SampleAudio } from "../audio"; +import { SampleAudio, SampledAudio } from "../audio"; declare var jt; // 6502 @@ -1068,7 +1068,7 @@ class Apple2MAMEPlatform extends BaseMAMEPlatform implements Platform { /// // TODO: move to own place, debugging -import { CPU, Bus, ClockBased, SavesState, Interruptable } from "../nemu/nemu"; +import { CPU, Bus, ClockBased, SavesState, Interruptable, CPUClockHook } from "../nemu/nemu"; import { MOS6502 } from "../nemu/cpu/MOS6502"; import { AppleII } from "../nemu/machine/apple2"; @@ -1078,6 +1078,7 @@ class NewApple2Platform extends Base6502Platform implements Platform { machine : AppleII; timer : AnimationTimer; video : RasterVideo; + audio : SampledAudio; constructor(mainElement : HTMLElement) { super(); @@ -1097,9 +1098,13 @@ class NewApple2Platform extends Base6502Platform implements Platform { this.timer = new AnimationTimer(60, this.nextFrame.bind(this)); var vp = this.machine.getVideoParams(); this.video = new RasterVideo(this.mainElement, vp.width, vp.height); - //this.audio = new SampleAudio(cpuFrequency); this.video.create(); + this.video.setKeyboardEvents(this.machine.setInput.bind(this.machine)); this.machine.connectVideo(this.video.getFrameData()); + var ap = this.machine.getAudioParams(); + this.audio = new SampledAudio(ap.sampleRate); + this.audio.start(); + this.machine.connectAudio(this.audio); } reset() { this.machine.reset(); @@ -1109,7 +1114,7 @@ class NewApple2Platform extends Base6502Platform implements Platform { this.reset(); } advance(novideo:boolean) { - this.machine.advanceFrame(); + this.machine.advanceFrame(999999, this.getDebugCallback()); if (!novideo) this.video.updateFrame(); } isRunning() { @@ -1117,9 +1122,24 @@ class NewApple2Platform extends Base6502Platform implements Platform { } resume() { this.timer.start(); + this.audio.start(); } pause() { this.timer.stop(); + this.audio.stop(); + } + // debugging + restartDebugging() { + super.restartDebugging(); + // TODO + var clock = 0; + var cpuhook = new CPUClockHook(this.machine.cpu, { + logExecute: (a:number) => { + clock++; + }, + logInterrupt: (a:number) => { + } + }); } } diff --git a/src/ui.ts b/src/ui.ts index 8b6aac14..68ec9e7f 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -958,6 +958,7 @@ function measureBuildTime() { ga('send', 'timing', 'worker', 'build', (measureTimeBuild.getTime() - measureTimeLoad.getTime())); measureTimeLoad = null; // only measure once } + gaEvent('build', platform_id); } function setCompileOutput(data: WorkerResult) {