mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-26 10:49:17 +00:00
Merge branch 'master' of github.com:sehugg/8bitworkshop
This commit is contained in:
commit
8d635bcf5d
@ -42,12 +42,13 @@ export type SymbolMap = {[ident:string]:number};
|
|||||||
export type AddrSymbolMap = {[address:number]:string};
|
export type AddrSymbolMap = {[address:number]:string};
|
||||||
|
|
||||||
export class DebugSymbols {
|
export class DebugSymbols {
|
||||||
symbolmap : SymbolMap; // symbol -> address
|
symbolmap : SymbolMap; // symbol -> address
|
||||||
addr2symbol : AddrSymbolMap; // address -> symbol
|
addr2symbol : AddrSymbolMap; // address -> symbol
|
||||||
|
|
||||||
constructor(symbolmap : SymbolMap) {
|
constructor(symbolmap : SymbolMap) {
|
||||||
this.symbolmap = symbolmap;
|
this.symbolmap = symbolmap;
|
||||||
this.addr2symbol = invertMap(symbolmap);
|
this.addr2symbol = invertMap(symbolmap);
|
||||||
|
// TODO: shouldn't be necc.
|
||||||
if (!this.addr2symbol[0x0]) this.addr2symbol[0x0] = '__START__'; // needed for ...
|
if (!this.addr2symbol[0x0]) this.addr2symbol[0x0] = '__START__'; // needed for ...
|
||||||
this.addr2symbol[0x10000] = '__END__'; // ... dump memory to work
|
this.addr2symbol[0x10000] = '__END__'; // ... dump memory to work
|
||||||
}
|
}
|
||||||
@ -75,8 +76,7 @@ export interface Platform {
|
|||||||
setFrameRate?(fps:number) : void;
|
setFrameRate?(fps:number) : void;
|
||||||
getFrameRate?() : number;
|
getFrameRate?() : number;
|
||||||
|
|
||||||
isDebugging() : boolean;
|
setupDebug?(callback : BreakpointCallback) : void;
|
||||||
setupDebug?(debugfn : (state)=>void) : void;
|
|
||||||
clearDebug?() : void;
|
clearDebug?() : void;
|
||||||
step?() : void;
|
step?() : void;
|
||||||
runToVsync?() : void;
|
runToVsync?() : void;
|
||||||
@ -99,6 +99,7 @@ export interface Platform {
|
|||||||
resize?() : void;
|
resize?() : void;
|
||||||
|
|
||||||
startProfiling?() : ProfilerOutput;
|
startProfiling?() : ProfilerOutput;
|
||||||
|
stopProfiling?() : void;
|
||||||
getRasterScanline?() : number;
|
getRasterScanline?() : number;
|
||||||
|
|
||||||
debugSymbols? : DebugSymbols;
|
debugSymbols? : DebugSymbols;
|
||||||
@ -119,6 +120,25 @@ export interface MemoryBus {
|
|||||||
export type DebugCondition = () => boolean;
|
export type DebugCondition = () => boolean;
|
||||||
export type DebugEvalCondition = (c:CpuState) => boolean;
|
export type DebugEvalCondition = (c:CpuState) => boolean;
|
||||||
export type BreakpointCallback = (s:EmuState) => void;
|
export type BreakpointCallback = (s:EmuState) => void;
|
||||||
|
// for composite breakpoints w/ single debug function
|
||||||
|
export class BreakpointList {
|
||||||
|
id2bp : {[id:string] : Breakpoint} = {};
|
||||||
|
getDebugCondition() : DebugCondition {
|
||||||
|
if (Object.keys(this.id2bp).length == 0) {
|
||||||
|
return null; // no breakpoints
|
||||||
|
} else {
|
||||||
|
// evaluate all breakpoints
|
||||||
|
return () => {
|
||||||
|
var result = false;
|
||||||
|
for (var id in this.id2bp)
|
||||||
|
if (this.id2bp[id].cond())
|
||||||
|
result = true;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export type Breakpoint = {cond:DebugCondition};
|
||||||
|
|
||||||
export interface EmuRecorder {
|
export interface EmuRecorder {
|
||||||
frameRequested() : boolean;
|
frameRequested() : boolean;
|
||||||
@ -157,13 +177,38 @@ export abstract class BasePlatform {
|
|||||||
this.recorder.recordFrame(this.saveState());
|
this.recorder.recordFrame(this.saveState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class BaseDebugPlatform extends BasePlatform {
|
||||||
|
onBreakpointHit : BreakpointCallback;
|
||||||
|
debugCallback : DebugCondition;
|
||||||
|
debugSavedState : EmuState = null;
|
||||||
|
debugBreakState : EmuState = null;
|
||||||
|
debugTargetClock : number = 0;
|
||||||
|
debugClock : number = 0;
|
||||||
|
breakpoints : BreakpointList = new BreakpointList();
|
||||||
|
|
||||||
|
abstract getCPUState() : CpuState;
|
||||||
|
abstract readAddress(addr:number) : number;
|
||||||
|
|
||||||
|
setBreakpoint(id : string, cond : DebugCondition) {
|
||||||
|
if (cond) {
|
||||||
|
this.breakpoints.id2bp[id] = {cond:cond};
|
||||||
|
this.restartDebugging();
|
||||||
|
} else {
|
||||||
|
this.clearBreakpoint(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearBreakpoint(id : string) {
|
||||||
|
delete this.breakpoints.id2bp[id];
|
||||||
|
}
|
||||||
startProfiling() : ProfilerOutput {
|
startProfiling() : ProfilerOutput {
|
||||||
var frame = null;
|
var frame = null;
|
||||||
var output = {frame:null};
|
var output = {frame:null};
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var lastsl = 9999;
|
var lastsl = 9999;
|
||||||
var start = 0;
|
var start = 0;
|
||||||
(this as any).runEval((c:CpuState) => {
|
this.setBreakpoint('profile', () => {
|
||||||
var sl = (this as any).getRasterScanline();
|
var sl = (this as any).getRasterScanline();
|
||||||
if (sl != lastsl) {
|
if (sl != lastsl) {
|
||||||
if (frame) {
|
if (frame) {
|
||||||
@ -177,31 +222,19 @@ export abstract class BasePlatform {
|
|||||||
start = i;
|
start = i;
|
||||||
lastsl = sl;
|
lastsl = sl;
|
||||||
}
|
}
|
||||||
|
var c = this.getCPUState();
|
||||||
frame.iptab[i++] = c.EPC || c.PC;
|
frame.iptab[i++] = c.EPC || c.PC;
|
||||||
return false; // profile forever
|
return false; // profile forever
|
||||||
});
|
});
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
stopProfiling() {
|
||||||
|
this.clearBreakpoint('profile');
|
||||||
export abstract class BaseDebugPlatform extends BasePlatform {
|
}
|
||||||
onBreakpointHit : BreakpointCallback;
|
|
||||||
debugCondition : DebugCondition;
|
|
||||||
debugSavedState : EmuState = null;
|
|
||||||
debugBreakState : EmuState = null;
|
|
||||||
debugTargetClock : number = 0;
|
|
||||||
debugClock : number = 0;
|
|
||||||
|
|
||||||
abstract getCPUState() : CpuState;
|
|
||||||
abstract readAddress(addr:number) : number;
|
|
||||||
|
|
||||||
getDebugCallback() : DebugCondition {
|
getDebugCallback() : DebugCondition {
|
||||||
return this.debugCondition;
|
return this.breakpoints.getDebugCondition();
|
||||||
}
|
}
|
||||||
isDebugging() : boolean {
|
setupDebug(callback : BreakpointCallback) : void {
|
||||||
return this.debugCondition != null;
|
|
||||||
}
|
|
||||||
setupDebug(callback : BreakpointCallback) {
|
|
||||||
this.onBreakpointHit = callback;
|
this.onBreakpointHit = callback;
|
||||||
}
|
}
|
||||||
clearDebug() {
|
clearDebug() {
|
||||||
@ -210,16 +243,19 @@ export abstract class BaseDebugPlatform extends BasePlatform {
|
|||||||
this.debugTargetClock = -1;
|
this.debugTargetClock = -1;
|
||||||
this.debugClock = 0;
|
this.debugClock = 0;
|
||||||
this.onBreakpointHit = null;
|
this.onBreakpointHit = null;
|
||||||
this.debugCondition = null;
|
this.clearBreakpoint('debug');
|
||||||
}
|
}
|
||||||
setDebugCondition(debugCond : DebugCondition) {
|
setDebugCondition(debugCond : DebugCondition) {
|
||||||
|
this.setBreakpoint('debug', debugCond);
|
||||||
|
}
|
||||||
|
restartDebugging() {
|
||||||
if (this.debugSavedState) {
|
if (this.debugSavedState) {
|
||||||
this.loadState(this.debugSavedState);
|
this.loadState(this.debugSavedState);
|
||||||
} else {
|
} else {
|
||||||
this.debugSavedState = this.saveState();
|
this.debugSavedState = this.saveState();
|
||||||
}
|
}
|
||||||
this.debugClock = 0;
|
this.debugClock = 0;
|
||||||
this.debugCondition = debugCond;
|
this.debugCallback = this.getDebugCallback();
|
||||||
this.debugBreakState = null;
|
this.debugBreakState = null;
|
||||||
this.resume();
|
this.resume();
|
||||||
}
|
}
|
||||||
@ -254,13 +290,13 @@ export abstract class Base6502Platform extends BaseDebugPlatform {
|
|||||||
debugPCDelta = -1;
|
debugPCDelta = -1;
|
||||||
|
|
||||||
evalDebugCondition() {
|
evalDebugCondition() {
|
||||||
if (this.debugCondition && !this.debugBreakState) {
|
if (this.debugCallback && !this.debugBreakState) {
|
||||||
this.debugCondition();
|
this.debugCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postFrame() {
|
postFrame() {
|
||||||
// save state every frame and rewind debug clocks
|
// save state every frame and rewind debug clocks
|
||||||
var debugging = this.debugCondition && !this.debugBreakState;
|
var debugging = this.debugCallback && !this.debugBreakState;
|
||||||
if (debugging) {
|
if (debugging) {
|
||||||
this.debugSavedState = this.saveState();
|
this.debugSavedState = this.saveState();
|
||||||
this.debugTargetClock -= this.debugClock;
|
this.debugTargetClock -= this.debugClock;
|
||||||
@ -505,7 +541,7 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform {
|
|||||||
cpu.requestInterrupt(data);
|
cpu.requestInterrupt(data);
|
||||||
}
|
}
|
||||||
postFrame() {
|
postFrame() {
|
||||||
if (this.debugCondition && !this.debugBreakState) {
|
if (this.debugCallback && !this.debugBreakState) {
|
||||||
this.debugSavedState = this.saveState();
|
this.debugSavedState = this.saveState();
|
||||||
if (this.debugTargetClock > 0)
|
if (this.debugTargetClock > 0)
|
||||||
this.debugTargetClock -= this.debugSavedState.c.T;
|
this.debugTargetClock -= this.debugSavedState.c.T;
|
||||||
@ -918,9 +954,6 @@ export abstract class BaseMAMEPlatform {
|
|||||||
getDebugCallback() {
|
getDebugCallback() {
|
||||||
return this.onBreakpointHit;// TODO?
|
return this.onBreakpointHit;// TODO?
|
||||||
}
|
}
|
||||||
isDebugging() : boolean {
|
|
||||||
return this.onBreakpointHit != null;
|
|
||||||
}
|
|
||||||
setupDebug(callback) {
|
setupDebug(callback) {
|
||||||
if (this.loaded) { // TODO?
|
if (this.loaded) { // TODO?
|
||||||
this.initlua();
|
this.initlua();
|
||||||
|
13
src/views.ts
13
src/views.ts
@ -11,7 +11,7 @@ import { platform, platform_id, compparams, current_project, lastDebugState, pro
|
|||||||
|
|
||||||
export interface ProjectView {
|
export interface ProjectView {
|
||||||
createDiv(parent:HTMLElement, text:string) : HTMLElement;
|
createDiv(parent:HTMLElement, text:string) : HTMLElement;
|
||||||
dispose?() : void;
|
setVisible?(showing : boolean) : void;
|
||||||
refresh(moveCursor:boolean) : void;
|
refresh(moveCursor:boolean) : void;
|
||||||
tick?() : void;
|
tick?() : void;
|
||||||
getPath?() : string;
|
getPath?() : string;
|
||||||
@ -914,13 +914,12 @@ export class ProfileView implements ProjectView {
|
|||||||
this.addProfileLine(div[0], row);
|
this.addProfileLine(div[0], row);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// TODO: better way to keep it profiling single-frame? also, it clears the buffer
|
|
||||||
if (platform.isRunning() /* && !platform.isDebugging()*/ ) {
|
|
||||||
this.prof = platform.startProfiling();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() : void {
|
setVisible(showing : boolean) : void {
|
||||||
platform.clearDebug();
|
if (showing)
|
||||||
|
this.prof = platform.startProfiling();
|
||||||
|
else
|
||||||
|
platform.stopProfiling();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,13 +41,15 @@ export class ProjectWindows {
|
|||||||
if (this.activewnd != wnd) {
|
if (this.activewnd != wnd) {
|
||||||
if (this.activediv)
|
if (this.activediv)
|
||||||
$(this.activediv).hide();
|
$(this.activediv).hide();
|
||||||
if (this.activewnd && this.activewnd.dispose)
|
if (this.activewnd && this.activewnd.setVisible)
|
||||||
this.activewnd.dispose();
|
this.activewnd.setVisible(false);
|
||||||
this.activediv = div;
|
this.activediv = div;
|
||||||
this.activewnd = wnd;
|
this.activewnd = wnd;
|
||||||
$(div).show();
|
$(div).show();
|
||||||
this.refresh(true);
|
this.refresh(true);
|
||||||
this.refreshErrors();
|
this.refreshErrors();
|
||||||
|
if (wnd.setVisible)
|
||||||
|
wnd.setVisible(true);
|
||||||
}
|
}
|
||||||
this.activeid = id;
|
this.activeid = id;
|
||||||
return wnd;
|
return wnd;
|
||||||
|
Loading…
Reference in New Issue
Block a user