mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-01-11 08:30:02 +00:00
made BaseMachinePlatform, test with NewApple2Platform (work on debugging)
This commit is contained in:
parent
30db326f57
commit
20bc3620ac
@ -27,6 +27,7 @@ export interface CpuState {
|
|||||||
export interface EmuState {
|
export interface EmuState {
|
||||||
c?:CpuState, // CPU state
|
c?:CpuState, // CPU state
|
||||||
b?:Uint8Array|number[], // RAM (TODO: not for vcs, support Uint8Array)
|
b?:Uint8Array|number[], // RAM (TODO: not for vcs, support Uint8Array)
|
||||||
|
ram?:Uint8Array,
|
||||||
o?:{}, // verilog
|
o?:{}, // verilog
|
||||||
T?:number, // verilog
|
T?:number, // verilog
|
||||||
};
|
};
|
||||||
@ -95,6 +96,7 @@ export interface Platform {
|
|||||||
|
|
||||||
getOpcodeMetadata?(opcode:number, offset:number) : OpcodeMetadata; //TODO
|
getOpcodeMetadata?(opcode:number, offset:number) : OpcodeMetadata; //TODO
|
||||||
getSP?() : number;
|
getSP?() : number;
|
||||||
|
getPC?() : number;
|
||||||
getOriginPC?() : number;
|
getOriginPC?() : number;
|
||||||
newCodeAnalyzer?() : CodeAnalyzer;
|
newCodeAnalyzer?() : CodeAnalyzer;
|
||||||
|
|
||||||
@ -413,8 +415,8 @@ export abstract class Base6502Platform extends BaseDebugPlatform {
|
|||||||
getDebugInfo(category:string, state:EmuState) : string {
|
getDebugInfo(category:string, state:EmuState) : string {
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case 'CPU': return cpuStateToLongString_6502(state.c);
|
case 'CPU': return cpuStateToLongString_6502(state.c);
|
||||||
case 'ZPRAM': return dumpRAM(state.b, 0x0, 0x100);
|
case 'ZPRAM': return dumpRAM(state.b||state.ram, 0x0, 0x100);
|
||||||
case 'Stack': return dumpStackToString(<Platform><any>this, state.b, 0x100, 0x1ff, 0x100+state.c.SP, 0x20);
|
case 'Stack': return dumpStackToString(<Platform><any>this, state.b||state.ram, 0x100, 0x1ff, 0x100+state.c.SP, 0x20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1185,3 +1187,174 @@ export abstract class BasicZ80ScanlinePlatform extends BaseZ80Platform {
|
|||||||
this.cpu.setTstates(0);
|
this.cpu.setTstates(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// new style
|
||||||
|
|
||||||
|
import { Bus, Resettable, FrameBased, VideoSource, SampledAudioSource, AcceptsROM, AcceptsInput, SavesState, HasCPU } from "./devices";
|
||||||
|
import { SampledAudio } from "./audio";
|
||||||
|
|
||||||
|
interface Machine extends Bus, Resettable, FrameBased, AcceptsROM, HasCPU, SavesState<EmuState> {
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasVideo(arg:any): arg is VideoSource {
|
||||||
|
return typeof arg.connectVideo === 'function';
|
||||||
|
}
|
||||||
|
function hasAudio(arg:any): arg is SampledAudioSource {
|
||||||
|
return typeof arg.connectAudio === 'function';
|
||||||
|
}
|
||||||
|
function hasInput<CS>(arg:any): arg is AcceptsInput<CS> {
|
||||||
|
return typeof arg.setInput === 'function';
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class BaseMachinePlatform<T extends Machine> extends BaseDebugPlatform implements Platform {
|
||||||
|
machine : T;
|
||||||
|
mainElement : HTMLElement;
|
||||||
|
timer : AnimationTimer;
|
||||||
|
video : RasterVideo;
|
||||||
|
audio : SampledAudio;
|
||||||
|
|
||||||
|
abstract newMachine() : T;
|
||||||
|
abstract getToolForFilename(s:string) : string;
|
||||||
|
abstract getDefaultExtension() : string;
|
||||||
|
abstract getPresets() : Preset[];
|
||||||
|
|
||||||
|
constructor(mainElement : HTMLElement) {
|
||||||
|
super();
|
||||||
|
this.mainElement = mainElement;
|
||||||
|
this.machine = this.newMachine();
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() { this.machine.reset(); }
|
||||||
|
loadState(s) { this.machine.loadState(s); }
|
||||||
|
saveState() { return this.machine.saveState(); }
|
||||||
|
getSP() { return this.machine.cpu.getSP(); }
|
||||||
|
getPC() { return this.machine.cpu.getPC(); }
|
||||||
|
getCPUState() { return this.machine.cpu.saveState(); }
|
||||||
|
loadControlsState(s) { if (hasInput(this.machine)) this.machine.loadControlsState(s); }
|
||||||
|
saveControlsState() { return hasInput(this.machine) && this.machine.saveControlsState(); }
|
||||||
|
|
||||||
|
start() {
|
||||||
|
var m = this.machine;
|
||||||
|
this.timer = new AnimationTimer(60, this.nextFrame.bind(this));
|
||||||
|
if (hasVideo(m)) {
|
||||||
|
var vp = m.getVideoParams();
|
||||||
|
this.video = new RasterVideo(this.mainElement, vp.width, vp.height);
|
||||||
|
this.video.create();
|
||||||
|
m.connectVideo(this.video.getFrameData());
|
||||||
|
}
|
||||||
|
if (hasAudio(m)) {
|
||||||
|
var ap = m.getAudioParams();
|
||||||
|
this.audio = new SampledAudio(ap.sampleRate);
|
||||||
|
this.audio.start();
|
||||||
|
m.connectAudio(this.audio);
|
||||||
|
}
|
||||||
|
if (hasInput(m)) {
|
||||||
|
this.video.setKeyboardEvents(m.setInput.bind(m));
|
||||||
|
// TODO: ControllerPoller
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadROM(title, data) {
|
||||||
|
this.machine.loadROM(data);
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
advance(novideo:boolean) {
|
||||||
|
this.machine.advanceFrame(999999, this.getDebugCallback());
|
||||||
|
if (!novideo) this.video.updateFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
isRunning() {
|
||||||
|
return this.timer.isRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
resume() {
|
||||||
|
this.timer.start();
|
||||||
|
this.audio && this.audio.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
pause() {
|
||||||
|
this.timer.stop();
|
||||||
|
this.audio && this.audio.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
breakpointHit(targetClock : number) {
|
||||||
|
console.log(this.debugTargetClock, targetClock, this.debugClock, this.machine.cpu.isStable());
|
||||||
|
this.debugTargetClock = targetClock;
|
||||||
|
this.debugBreakState = this.saveState();
|
||||||
|
console.log("Breakpoint at clk", this.debugClock, "PC", this.debugBreakState.c.PC.toString(16));
|
||||||
|
this.pause();
|
||||||
|
if (this.onBreakpointHit) {
|
||||||
|
this.onBreakpointHit(this.debugBreakState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runEval(evalfunc : DebugEvalCondition) {
|
||||||
|
this.setDebugCondition( () => {
|
||||||
|
if (++this.debugClock >= this.debugTargetClock && this.machine.cpu.isStable()) {
|
||||||
|
var cpuState = this.getCPUState();
|
||||||
|
if (evalfunc(cpuState)) {
|
||||||
|
this.breakpointHit(this.debugClock);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
runUntilReturn() {
|
||||||
|
var SP0 = this.machine.cpu.getSP();
|
||||||
|
this.runEval( (c:CpuState) : boolean => {
|
||||||
|
return c.SP > SP0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
runToFrameClock(clock : number) : void {
|
||||||
|
this.restartDebugging();
|
||||||
|
this.debugTargetClock = clock;
|
||||||
|
this.runEval(() : boolean => { return true; });
|
||||||
|
}
|
||||||
|
step() {
|
||||||
|
this.runToFrameClock(this.debugClock+1);
|
||||||
|
}
|
||||||
|
stepBack() {
|
||||||
|
var prevState;
|
||||||
|
var prevClock;
|
||||||
|
var clock0 = this.debugTargetClock;
|
||||||
|
this.restartDebugging();
|
||||||
|
this.debugTargetClock = clock0 - 25; // TODO: depends on CPU
|
||||||
|
this.runEval( (c:CpuState) : boolean => {
|
||||||
|
if (this.debugClock < clock0) {
|
||||||
|
prevState = this.saveState();
|
||||||
|
prevClock = this.debugClock;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (prevState) {
|
||||||
|
this.loadState(prevState);
|
||||||
|
this.debugClock = prevClock;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class Base6502MachinePlatform<T extends Machine> extends BaseMachinePlatform<T> {
|
||||||
|
|
||||||
|
getOpcodeMetadata = getOpcodeMetadata_6502;
|
||||||
|
getToolForFilename = getToolForFilename_6502;
|
||||||
|
|
||||||
|
disassemble(pc:number, read:(addr:number)=>number) : DisasmLine {
|
||||||
|
return disassemble6502(pc, read(pc), read(pc+1), read(pc+2));
|
||||||
|
}
|
||||||
|
getDebugCategories() {
|
||||||
|
return ['CPU','ZPRAM','Stack'];
|
||||||
|
}
|
||||||
|
getDebugInfo(category:string, state:EmuState) : string {
|
||||||
|
switch (category) {
|
||||||
|
case 'CPU': return cpuStateToLongString_6502(state.c);
|
||||||
|
case 'ZPRAM': return dumpRAM(state.b||state.ram, 0x0, 0x100);
|
||||||
|
case 'Stack': return dumpStackToString(<Platform><any>this, state.b||state.ram, 0x100, 0x1ff, 0x100+state.c.SP, 0x20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1755,7 +1755,8 @@ var _MOS6502 = function() {
|
|||||||
|
|
||||||
this.saveState = function():MOS6502State {
|
this.saveState = function():MOS6502State {
|
||||||
return {
|
return {
|
||||||
PC: PC, A: A, X: X, Y: Y, SP: SP,
|
PC: (PC-1) & 0xffff,
|
||||||
|
A: A, X: X, Y: Y, SP: SP,
|
||||||
N: N, V: V, D: D, I: I, Z: Z, C: C,
|
N: N, V: V, D: D, I: I, Z: Z, C: C,
|
||||||
T: T, o: opcode, R: RDY?1:0,
|
T: T, o: opcode, R: RDY?1:0,
|
||||||
d: data, AD: AD, BA: BA, BC: BALCrossed?1:0, IA: IA,
|
d: data, AD: AD, BA: BA, BC: BALCrossed?1:0, IA: IA,
|
||||||
@ -1764,7 +1765,8 @@ var _MOS6502 = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.loadState = function(state:MOS6502State) {
|
this.loadState = function(state:MOS6502State) {
|
||||||
PC = state.PC; A = state.A; X = state.X; Y = state.Y; SP = state.SP;
|
PC = (state.PC+1) & 0xffff;
|
||||||
|
A = state.A; X = state.X; Y = state.Y; SP = state.SP;
|
||||||
N = state.N; V = state.V; D = state.D; I = state.I; Z = state.Z; C = state.C;
|
N = state.N; V = state.V; D = state.D; I = state.I; Z = state.Z; C = state.C;
|
||||||
T = state.T; opcode = state.o; RDY = !!state.R;
|
T = state.T; opcode = state.o; RDY = !!state.R;
|
||||||
data = state.d; AD = state.AD; BA = state.BA; BALCrossed = !!state.BC; IA = state.IA;
|
data = state.d; AD = state.AD; BA = state.BA; BALCrossed = !!state.BC; IA = state.IA;
|
||||||
@ -1887,12 +1889,10 @@ var _MOS6502 = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.getSP = function() { return SP; }
|
this.getSP = function() { return SP; }
|
||||||
this.getPC = function() { return PC; }
|
this.getPC = function() { return (PC-1) & 0xffff; }
|
||||||
this.getT = function() { return T; }
|
this.getT = function() { return T; }
|
||||||
|
|
||||||
this.isPCStable = function() {
|
this.isPCStable = function() {
|
||||||
// TODO: gotta fix base class first
|
|
||||||
//return T < 0 || T == instruction.length-1;
|
|
||||||
return T == 0;
|
return T == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1936,7 +1936,7 @@ export class MOS6502 implements CPU, ClockBased, SavesState<MOS6502State>, Inter
|
|||||||
interrupt(itype:number) {
|
interrupt(itype:number) {
|
||||||
this.interruptType = itype;
|
this.interruptType = itype;
|
||||||
}
|
}
|
||||||
getSP() {
|
getSP() {
|
||||||
return this.cpu.getSP();
|
return this.cpu.getSP();
|
||||||
}
|
}
|
||||||
getPC() {
|
getPC() {
|
||||||
|
@ -1742,6 +1742,7 @@ export class Z80 implements CPU, InstructionBased, IOBusConnected, SavesState<Z8
|
|||||||
loadState(s) {
|
loadState(s) {
|
||||||
this.cpu.loadState(s);
|
this.cpu.loadState(s);
|
||||||
}
|
}
|
||||||
|
isStable() { return true; }
|
||||||
// TODO: metadata
|
// TODO: metadata
|
||||||
// TODO: disassembler
|
// TODO: disassembler
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
export interface SavesState<T> {
|
export interface SavesState<S> {
|
||||||
saveState() : T;
|
saveState() : S;
|
||||||
loadState(state:T) : void;
|
loadState(state:S) : void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Bus {
|
export interface Bus {
|
||||||
@ -72,20 +72,25 @@ export interface IOBusConnected {
|
|||||||
connectIOBus(bus:Bus) : void;
|
connectIOBus(bus:Bus) : void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CPU extends MemoryBusConnected, Resettable {
|
export interface CPU extends MemoryBusConnected, Resettable, SavesState<any> {
|
||||||
getPC() : number;
|
getPC() : number;
|
||||||
getSP() : number;
|
getSP() : number;
|
||||||
|
isStable() : boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Interruptable<T> {
|
export interface HasCPU {
|
||||||
interrupt(type:T) : void;
|
cpu : CPU;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Interruptable<IT> {
|
||||||
|
interrupt(type:IT) : void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
export interface AcceptsInput {
|
export interface AcceptsInput<CS> {
|
||||||
setInput(key:number, code:number, flags:number) : void;
|
setInput(key:number, code:number, flags:number) : void;
|
||||||
//loadControlState();
|
loadControlsState(cs:CS);
|
||||||
//saveControlState();
|
saveControlsState() : CS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO?
|
// TODO?
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import { MOS6502, MOS6502State } from "../cpu/MOS6502";
|
import { MOS6502, MOS6502State } from "../cpu/MOS6502";
|
||||||
import { Bus, RasterFrameBased, SavesState, AcceptsROM, noise, Resettable, SampledAudioSource, SampledAudioSink } from "../devices";
|
import { Bus, RasterFrameBased, SavesState, AcceptsROM, AcceptsInput, noise, Resettable, SampledAudioSource, SampledAudioSink, HasCPU } from "../devices";
|
||||||
import { KeyFlags } from "../emu"; // TODO
|
import { KeyFlags } from "../emu"; // TODO
|
||||||
import { lzgmini } from "../util";
|
import { lzgmini } from "../util";
|
||||||
|
|
||||||
@ -16,18 +16,22 @@ const HDR_SIZE = PGM_BASE - LOAD_BASE;
|
|||||||
|
|
||||||
interface AppleIIStateBase {
|
interface AppleIIStateBase {
|
||||||
ram : Uint8Array;
|
ram : Uint8Array;
|
||||||
rnd,kbdlatch,soundstate : number;
|
rnd,soundstate : number;
|
||||||
auxRAMselected,writeinhibit : boolean;
|
auxRAMselected,writeinhibit : boolean;
|
||||||
auxRAMbank,bank2rdoffset,bank2wroffset : number;
|
auxRAMbank : number;
|
||||||
grdirty : boolean[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AppleIIState extends AppleIIStateBase {
|
interface AppleIIControlsState {
|
||||||
|
kbdlatch : number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AppleIIState extends AppleIIStateBase, AppleIIControlsState {
|
||||||
c : MOS6502State;
|
c : MOS6502State;
|
||||||
|
grswitch : number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AppleII implements Bus, Resettable, RasterFrameBased, SampledAudioSource, AcceptsROM,
|
export class AppleII implements HasCPU, Bus, Resettable, RasterFrameBased, SampledAudioSource, AcceptsROM,
|
||||||
AppleIIStateBase, SavesState<AppleIIState> {
|
AppleIIStateBase, SavesState<AppleIIState>, AcceptsInput<AppleIIControlsState> {
|
||||||
|
|
||||||
ram = new Uint8Array(0x13000); // 64K + 16K LC RAM - 4K hardware + 12K ROM
|
ram = new Uint8Array(0x13000); // 64K + 16K LC RAM - 4K hardware + 12K ROM
|
||||||
rom : Uint8Array;
|
rom : Uint8Array;
|
||||||
@ -58,7 +62,7 @@ export class AppleII implements Bus, Resettable, RasterFrameBased, SampledAudioS
|
|||||||
this.ram[0xbf6f] = 0x01; // fake DOS detect for C
|
this.ram[0xbf6f] = 0x01; // fake DOS detect for C
|
||||||
this.cpu.connectMemoryBus(this);
|
this.cpu.connectMemoryBus(this);
|
||||||
}
|
}
|
||||||
saveState() {
|
saveState() : AppleIIState {
|
||||||
// TODO: automagic
|
// TODO: automagic
|
||||||
return {
|
return {
|
||||||
c: this.cpu.saveState(),
|
c: this.cpu.saveState(),
|
||||||
@ -66,27 +70,45 @@ export class AppleII implements Bus, Resettable, RasterFrameBased, SampledAudioS
|
|||||||
rnd: this.rnd,
|
rnd: this.rnd,
|
||||||
kbdlatch: this.kbdlatch,
|
kbdlatch: this.kbdlatch,
|
||||||
soundstate: this.soundstate,
|
soundstate: this.soundstate,
|
||||||
|
grswitch: this.grparams.grswitch,
|
||||||
auxRAMselected: this.auxRAMselected,
|
auxRAMselected: this.auxRAMselected,
|
||||||
writeinhibit: this.writeinhibit,
|
|
||||||
auxRAMbank: this.auxRAMbank,
|
auxRAMbank: this.auxRAMbank,
|
||||||
bank2rdoffset: this.bank2rdoffset,
|
writeinhibit: this.writeinhibit,
|
||||||
bank2wroffset: this.bank2wroffset,
|
|
||||||
grdirty: this.grdirty.slice(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
loadState(s) {
|
loadState(s:AppleIIState) {
|
||||||
this.cpu.loadState(s.c);
|
this.cpu.loadState(s.c);
|
||||||
this.ram.set(s.ram);
|
this.ram.set(s.ram);
|
||||||
// TODO
|
this.rnd = s.rnd;
|
||||||
|
this.kbdlatch = s.kbdlatch;
|
||||||
|
this.soundstate = s.soundstate;
|
||||||
|
this.grparams.grswitch = s.grswitch;
|
||||||
|
this.auxRAMselected = s.auxRAMselected;
|
||||||
|
this.auxRAMbank = s.auxRAMbank;
|
||||||
|
this.writeinhibit = s.writeinhibit;
|
||||||
|
this.setupLanguageCardConstants();
|
||||||
|
this.ap2disp.invalidate(); // repaint entire screen
|
||||||
|
}
|
||||||
|
saveControlsState() : AppleIIControlsState {
|
||||||
|
return {kbdlatch:this.kbdlatch};
|
||||||
|
}
|
||||||
|
loadControlsState(s:AppleIIControlsState) {
|
||||||
|
this.kbdlatch = s.kbdlatch;
|
||||||
}
|
}
|
||||||
reset() {
|
reset() {
|
||||||
this.cpu.reset();
|
this.cpu.reset();
|
||||||
|
// execute until $c600 boot
|
||||||
|
for (var i=0; i<2000000; i++) {
|
||||||
|
this.cpu.advanceClock();
|
||||||
|
if (this.cpu.getPC() == 0xc602) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
noise() : number {
|
noise() : number {
|
||||||
return (this.rnd = noise(this.rnd)) & 0xff;
|
return (this.rnd = noise(this.rnd)) & 0xff;
|
||||||
}
|
}
|
||||||
read(address:number) : number {
|
readConst(address:number) : number {
|
||||||
address &= 0xffff;
|
|
||||||
if (address < 0xc000) {
|
if (address < 0xc000) {
|
||||||
return this.ram[address];
|
return this.ram[address];
|
||||||
} else if (address >= 0xd000) {
|
} else if (address >= 0xd000) {
|
||||||
@ -96,6 +118,13 @@ export class AppleII implements Bus, Resettable, RasterFrameBased, SampledAudioS
|
|||||||
return this.ram[address];
|
return this.ram[address];
|
||||||
else
|
else
|
||||||
return this.ram[address + this.bank2rdoffset];
|
return this.ram[address + this.bank2rdoffset];
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
read(address:number) : number {
|
||||||
|
address &= 0xffff;
|
||||||
|
if (address < 0xc000 || address >= 0xd000) {
|
||||||
|
return this.readConst(address);
|
||||||
} else if (address < 0xc100) {
|
} else if (address < 0xc100) {
|
||||||
var slot = (address >> 4) & 0x0f;
|
var slot = (address >> 4) & 0x0f;
|
||||||
switch (slot)
|
switch (slot)
|
||||||
@ -191,7 +220,7 @@ export class AppleII implements Bus, Resettable, RasterFrameBased, SampledAudioS
|
|||||||
advanceFrame(maxCycles, trap) : number {
|
advanceFrame(maxCycles, trap) : number {
|
||||||
maxCycles = Math.min(maxCycles, cpuCyclesPerFrame);
|
maxCycles = Math.min(maxCycles, cpuCyclesPerFrame);
|
||||||
for (var i=0; i<maxCycles; i++) {
|
for (var i=0; i<maxCycles; i++) {
|
||||||
if (trap && this.cpu.isStable() && trap()) break;
|
if (trap && trap()) break;
|
||||||
this.cpu.advanceClock();
|
this.cpu.advanceClock();
|
||||||
this.audio.feedSample(this.soundstate, 1);
|
this.audio.feedSample(this.soundstate, 1);
|
||||||
}
|
}
|
||||||
@ -301,46 +330,6 @@ const GR_HIRES = 8;
|
|||||||
|
|
||||||
type AppleGRParams = {dirty:boolean[], grswitch:number, mem:Uint8Array};
|
type AppleGRParams = {dirty:boolean[], grswitch:number, mem:Uint8Array};
|
||||||
|
|
||||||
/*
|
|
||||||
readAddress(addr : number) {
|
|
||||||
return ((addr & 0xf000) != 0xc000) ? bus.read(addr) : null; // ignore I/O space
|
|
||||||
}
|
|
||||||
|
|
||||||
loadState(state) {
|
|
||||||
this.unfixPC(state.c);
|
|
||||||
cpu.loadState(state.c);
|
|
||||||
this.fixPC(state.c);
|
|
||||||
ram.mem.set(state.b);
|
|
||||||
kbdlatch = state.kbd;
|
|
||||||
grswitch = state.gr;
|
|
||||||
auxRAMselected = state.lc.s;
|
|
||||||
auxRAMbank = state.lc.b;
|
|
||||||
writeinhibit = state.lc.w;
|
|
||||||
setupLanguageCardConstants();
|
|
||||||
ap2disp.invalidate(); // repaint entire screen
|
|
||||||
}
|
|
||||||
saveState() {
|
|
||||||
return {
|
|
||||||
c:this.getCPUState(),
|
|
||||||
b:ram.mem.slice(0),
|
|
||||||
kbd:kbdlatch,
|
|
||||||
gr:grswitch,
|
|
||||||
lc:{s:auxRAMselected,b:auxRAMbank,w:writeinhibit},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
loadControlsState(state) {
|
|
||||||
kbdlatch = state.kbd;
|
|
||||||
}
|
|
||||||
saveControlsState() {
|
|
||||||
return {
|
|
||||||
kbd:kbdlatch
|
|
||||||
};
|
|
||||||
}
|
|
||||||
getCPUState() {
|
|
||||||
return this.fixPC(cpu.saveState());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Apple2Display = function(pixels : Uint32Array, apple : AppleGRParams) {
|
var Apple2Display = function(pixels : Uint32Array, apple : AppleGRParams) {
|
||||||
var XSIZE = 280;
|
var XSIZE = 280;
|
||||||
var YSIZE = 192;
|
var YSIZE = 192;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,7 @@ describe('MOS6502', function() {
|
|||||||
s0.PC = 0x400;
|
s0.PC = 0x400;
|
||||||
cpu.loadState(s0);
|
cpu.loadState(s0);
|
||||||
for (var i=0; i<100000000; i++) {
|
for (var i=0; i<100000000; i++) {
|
||||||
|
//console.log(cpu.isStable(), cpu.saveState().o);
|
||||||
cpu.advanceClock();
|
cpu.advanceClock();
|
||||||
var pc = cpu.getPC();
|
var pc = cpu.getPC();
|
||||||
if (pc == 0x3469) break; // success!
|
if (pc == 0x3469) break; // success!
|
||||||
|
@ -27,11 +27,14 @@ includeInThisContext('tss/js/tss/AudioLooper.js');
|
|||||||
//includeInThisContext("jsnes/dist/jsnes.min.js");
|
//includeInThisContext("jsnes/dist/jsnes.min.js");
|
||||||
global.jsnes = require("jsnes/dist/jsnes.min.js");
|
global.jsnes = require("jsnes/dist/jsnes.min.js");
|
||||||
|
|
||||||
|
//var devices = require('gen/devices.js');
|
||||||
var emu = require('gen/emu.js');
|
var emu = require('gen/emu.js');
|
||||||
var Keys = emu.Keys;
|
var Keys = emu.Keys;
|
||||||
var audio = require('gen/audio.js');
|
var audio = require('gen/audio.js');
|
||||||
var recorder = require('gen/recorder.js');
|
var recorder = require('gen/recorder.js');
|
||||||
|
//var _6502 = require('gen/cpu/MOS6502.js');
|
||||||
var _apple2 = require('gen/platform/apple2.js');
|
var _apple2 = require('gen/platform/apple2.js');
|
||||||
|
//var m_apple2 = require('gen/machine/apple2.js');
|
||||||
var _vcs = require('gen/platform/vcs.js');
|
var _vcs = require('gen/platform/vcs.js');
|
||||||
var _nes = require('gen/platform/nes.js');
|
var _nes = require('gen/platform/nes.js');
|
||||||
var _vicdual = require('gen/platform/vicdual.js');
|
var _vicdual = require('gen/platform/vicdual.js');
|
||||||
@ -171,7 +174,7 @@ describe('Platform Replay', () => {
|
|||||||
keycallback(32, 32, 128); // space bar
|
keycallback(32, 32, 128); // space bar
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
assert.equal(platform.saveState().kbd, 0x20); // strobe cleared
|
assert.equal(platform.saveState().kbdlatch, 0x20); // strobe cleared
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should run > 120 secs', () => {
|
it('Should run > 120 secs', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user