toolbar takes entire width; started exidy
This commit is contained in:
parent
1e2b489b07
commit
2949a35167
88
index.html
88
index.html
|
@ -43,20 +43,24 @@ body {
|
||||||
.tooltipbox:hover .tooltiptext {
|
.tooltipbox:hover .tooltiptext {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
#notebook {
|
#controls_top {
|
||||||
height: 100vh;
|
position: absolute;
|
||||||
width: 50%;
|
padding: 0.5em;
|
||||||
|
height:3em;
|
||||||
|
width:100%;
|
||||||
background-color:#999;
|
background-color:#999;
|
||||||
}
|
}
|
||||||
#controls_top {
|
#notebook {
|
||||||
padding: 0.5em;
|
position:absolute;
|
||||||
width:100%;
|
top:3em;
|
||||||
height:3em;
|
bottom:0;
|
||||||
|
left:0;
|
||||||
|
right:0;
|
||||||
}
|
}
|
||||||
div.editor {
|
div.editor {
|
||||||
position:absolute;
|
position:absolute;
|
||||||
left:0;
|
left:0;
|
||||||
top:3em;
|
top:0;
|
||||||
bottom:0;
|
bottom:0;
|
||||||
right:0;
|
right:0;
|
||||||
width:50%;
|
width:50%;
|
||||||
|
@ -165,40 +169,41 @@ a.dropdown-toggle {
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="notebook">
|
<div id="controls_top">
|
||||||
<div id="controls_top">
|
<span class="dropdown">
|
||||||
<span class="dropdown">
|
<a class="btn btn-secondary dropdown-toggle" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
<a class="btn btn-secondary dropdown-toggle" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
☰ <span class="caret"></span>
|
||||||
☰ <span class="caret"></span>
|
</a>
|
||||||
</a>
|
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
<li><a class="dropdown-item" href="#" id="item_new_file">New File...</a></li>
|
||||||
<li><a class="dropdown-item" href="#" id="item_new_file">New File...</a></li>
|
<li><a class="dropdown-item" href="#" id="item_share_file">Share File...</a></li>
|
||||||
<li><a class="dropdown-item" href="#" id="item_share_file">Share File...</a></li>
|
<li><a class="dropdown-item" href="#" id="item_reset_file">Reset to Original...</a></li>
|
||||||
<li><a class="dropdown-item" href="#" id="item_reset_file">Reset to Original...</a></li>
|
<li class="dropdown dropdown-submenu">
|
||||||
<li class="dropdown dropdown-submenu">
|
<a tabindex="-1" href="#">Platform</a>
|
||||||
<a tabindex="-1" href="#">Platform</a>
|
<ul class="dropdown-menu">
|
||||||
<ul class="dropdown-menu">
|
<li><a class="dropdown-item" href="?platform=vcs" id="item_platform_vcs">Atari VCS</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=vcs" id="item_platform_vcs">Atari VCS</a></li>
|
<li><a class="dropdown-item" href="?platform=apple2" id="item_platform_apple2">Apple ][</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=apple2" id="item_platform_apple2">Apple ][</a></li>
|
<li><a class="dropdown-item" href="?platform=atarivec" id="item_platform_atarivec">Asteroids</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=atarivec" id="item_platform_atarivec">Asteroids</a></li>
|
<li><a class="dropdown-item" href="?platform=exidy" id="item_platform_exidy">Exidy</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
<select id="preset_select" name="">
|
<select id="preset_select" name="">
|
||||||
</select>
|
</select>
|
||||||
<span id="debug_bar">
|
<span id="debug_bar">
|
||||||
<button id="dbg_pause" type="button" title="Pause"><img src="images/pause.png"></button>
|
<button id="dbg_pause" type="button" title="Pause"><img src="images/pause.png"></button>
|
||||||
<button id="dbg_go" type="button" title="Run"><img src="images/play.png"></button>
|
<button id="dbg_go" type="button" title="Run"><img src="images/play.png"></button>
|
||||||
<button id="dbg_step" type="submit" title="Step"><img src="images/singlestep.png"></button>
|
<button id="dbg_step" type="submit" title="Step"><img src="images/singlestep.png"></button>
|
||||||
<button id="dbg_toline" type="submit" title="Run To Line"><img src="images/runtoline.png"></button>
|
<button id="dbg_toline" type="submit" title="Run To Line"><img src="images/runtoline.png"></button>
|
||||||
<button id="dbg_reset" type="submit" title="Reset and Run To Line"><img src="images/resetandrun.png"></button>
|
<button id="dbg_reset" type="submit" title="Reset and Run To Line"><img src="images/resetandrun.png"></button>
|
||||||
<!-- <button id="dbg_stepout" type="submit" title="Step Out of Subroutine">O</button>-->
|
<!-- <button id="dbg_stepout" type="submit" title="Step Out of Subroutine">O</button>-->
|
||||||
<button id="dbg_timing" type="submit" title="See Timing" style="display:none"><img src="images/timing.png"></button>
|
<button id="dbg_timing" type="submit" title="See Timing" style="display:none"><img src="images/timing.png"></button>
|
||||||
<button id="dbg_disasm" type="submit" title="Toggle Disassembly">#</button>
|
<button id="dbg_disasm" type="submit" title="Toggle Disassembly">#</button>
|
||||||
</span>
|
</span>
|
||||||
<span class="dbg_info" id="dbg_info"></span>
|
<span class="dbg_info" id="dbg_info"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="notebook">
|
||||||
<div id="editor_window">
|
<div id="editor_window">
|
||||||
<div id="disassembly" class="editor">
|
<div id="disassembly" class="editor">
|
||||||
</div>
|
</div>
|
||||||
|
@ -253,6 +258,7 @@ a.dropdown-toggle {
|
||||||
<script src="src/platform/vcs.js"></script>
|
<script src="src/platform/vcs.js"></script>
|
||||||
<script src="src/platform/apple2.js"></script>
|
<script src="src/platform/apple2.js"></script>
|
||||||
<script src="src/platform/atarivec.js"></script>
|
<script src="src/platform/atarivec.js"></script>
|
||||||
|
<script src="src/platform/exidy.js"></script>
|
||||||
<script src="src/ui.js"></script>
|
<script src="src/ui.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var EXIDY_PRESETS = [
|
||||||
|
];
|
||||||
|
|
||||||
|
var ExidyPlatform = function(mainElement) {
|
||||||
|
var self = this;
|
||||||
|
var cpuFrequency = 705562;
|
||||||
|
var cyclesPerFrame = Math.round(cpuFrequency/60);
|
||||||
|
var vblankCyclesPerFrame = Math.round(cpuFrequency*3/(262.5*60));
|
||||||
|
var cpu, ram, bus, rom;
|
||||||
|
var video, ap2disp, audio, timer;
|
||||||
|
var port_dsw = 0;
|
||||||
|
var PGM_BASE = 0x1000; // where to JMP after pr#6
|
||||||
|
|
||||||
|
this.getPresets = function() {
|
||||||
|
return EXIDY_PRESETS;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.start = function() {
|
||||||
|
cpu = new jt.M6502();
|
||||||
|
ram = new RAM(0x200); // 64K + 16K LC RAM - 4K hardware
|
||||||
|
rom = new RAM(0x1000);
|
||||||
|
// bus
|
||||||
|
bus = {
|
||||||
|
read: function(address) {
|
||||||
|
address &= 0xffff;
|
||||||
|
if (address < ram.mem.length) {
|
||||||
|
return ram.mem[address];
|
||||||
|
} else if (address >= 0x1000 && address <= 0x1fff) {
|
||||||
|
return rom.mem[address - 0x1000];
|
||||||
|
} else if (address >= 0xf000) {
|
||||||
|
return rom.mem[address - 0xf000];
|
||||||
|
} else if (address == 0xc000) {
|
||||||
|
return port_dsw;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
write: function(address, val) {
|
||||||
|
address &= 0xffff;
|
||||||
|
val &= 0xff;
|
||||||
|
if (address < ram.mem.length) {
|
||||||
|
ram.mem[address] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cpu.connectBus(bus);
|
||||||
|
// create video/audio
|
||||||
|
video = new RasterVideo(mainElement,256,256);
|
||||||
|
video.start();
|
||||||
|
audio = new SampleAudio(cpuFrequency); // TODO
|
||||||
|
audio.start();
|
||||||
|
var idata = video.getFrameData();
|
||||||
|
timer = new AnimationTimer(60, function() {
|
||||||
|
var clock = 0;
|
||||||
|
breakClock = -1;
|
||||||
|
for (var i=0; i<cyclesPerFrame; i++) {
|
||||||
|
if (debugCondition && breakClock < 0 && debugCondition()) { breakClock = clock; }
|
||||||
|
clock++;
|
||||||
|
cpu.clockPulse();
|
||||||
|
port_dsw = (i < vblankCyclesPerFrame) ? 0x80 : 0x0;
|
||||||
|
}
|
||||||
|
video.updateFrame();
|
||||||
|
});
|
||||||
|
// TODO: reset debug state
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: refactor into base
|
||||||
|
|
||||||
|
this.getOpcodeMetadata = function(opcode, offset) {
|
||||||
|
return Javatari.getOpcodeMetadata(opcode, offset); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadROM = function(title, data) {
|
||||||
|
this.reset();
|
||||||
|
if(data.length != 0x1000) {
|
||||||
|
throw "ROM length must be == 0x1000";
|
||||||
|
}
|
||||||
|
rom.mem.set(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getRasterPosition = function() {
|
||||||
|
return {x:0, y:0};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isRunning = function() {
|
||||||
|
return timer.isRunning();
|
||||||
|
}
|
||||||
|
this.pause = function() {
|
||||||
|
timer.stop();
|
||||||
|
audio.stop();
|
||||||
|
}
|
||||||
|
this.resume = function() {
|
||||||
|
timer.start();
|
||||||
|
audio.start();
|
||||||
|
}
|
||||||
|
this.reset = function() {
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
this.getOriginPC = function() {
|
||||||
|
return (this.readAddress(0xfffc) | (this.readAddress(0xfffd) << 8)) & 0xffff;
|
||||||
|
}
|
||||||
|
this.readAddress = function(addr) {
|
||||||
|
return bus.read(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
var onBreakpointHit;
|
||||||
|
var debugCondition;
|
||||||
|
var debugSavedState = null;
|
||||||
|
var debugBreakState = null;
|
||||||
|
var debugTargetClock = 0;
|
||||||
|
var debugClock = 0;
|
||||||
|
var debugFrameStartClock = 0;
|
||||||
|
var breakClock;
|
||||||
|
|
||||||
|
this.setDebugCondition = function(debugCond) {
|
||||||
|
if (debugSavedState) {
|
||||||
|
self.loadState(debugSavedState);
|
||||||
|
} else {
|
||||||
|
debugSavedState = self.saveState();
|
||||||
|
}
|
||||||
|
debugClock = 0;
|
||||||
|
debugCondition = debugCond;
|
||||||
|
self.resume();
|
||||||
|
}
|
||||||
|
this.setupDebug = function(callback) {
|
||||||
|
onBreakpointHit = callback;
|
||||||
|
}
|
||||||
|
this.clearDebug = function() {
|
||||||
|
debugSavedState = null;
|
||||||
|
debugTargetClock = 0;
|
||||||
|
debugClock = 0;
|
||||||
|
debugFrameStartClock = 0;
|
||||||
|
onBreakpointHit = null;
|
||||||
|
debugCondition = null;
|
||||||
|
}
|
||||||
|
this.breakpointHit = function() {
|
||||||
|
debugBreakState = self.saveState();
|
||||||
|
debugBreakState.c.PC = (debugBreakState.c.PC-1) & 0xffff;
|
||||||
|
console.log("Breakpoint at clk", debugClock, "PC", debugBreakState.c.PC.toString(16));
|
||||||
|
this.pause();
|
||||||
|
if (onBreakpointHit) {
|
||||||
|
onBreakpointHit(debugBreakState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.step = function() {
|
||||||
|
var previousPC = -1;
|
||||||
|
self.setDebugCondition(function() {
|
||||||
|
if (debugClock++ > debugTargetClock) {
|
||||||
|
var thisState = cpu.saveState();
|
||||||
|
if (previousPC < 0) {
|
||||||
|
previousPC = thisState.PC;
|
||||||
|
} else {
|
||||||
|
if (thisState.PC != previousPC && thisState.T == 0) {
|
||||||
|
//console.log(previousPC.toString(16), thisPC.toString(16));
|
||||||
|
debugTargetClock = debugClock-1;
|
||||||
|
self.breakpointHit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.runEval = function(evalfunc) {
|
||||||
|
var self = this;
|
||||||
|
self.setDebugCondition(function() {
|
||||||
|
if (debugClock++ > debugTargetClock) {
|
||||||
|
var cpuState = cpu.saveState();
|
||||||
|
cpuState.PC = (cpuState.PC-1)&0xffff;
|
||||||
|
if (evalfunc(cpuState)) {
|
||||||
|
self.breakpointHit();
|
||||||
|
debugTargetClock = debugClock;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadState = function(state) {
|
||||||
|
cpu.loadState(state.c);
|
||||||
|
ram.mem.set(state.b);
|
||||||
|
}
|
||||||
|
this.saveState = function() {
|
||||||
|
return {
|
||||||
|
c:cpu.saveState(),
|
||||||
|
b:ram.mem.slice(0),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
this.getRAMForState = function(state) {
|
||||||
|
return ram.mem;
|
||||||
|
}
|
||||||
|
};
|
|
@ -263,7 +263,7 @@ function arrayCompare(a,b) {
|
||||||
|
|
||||||
worker.onmessage = function(e) {
|
worker.onmessage = function(e) {
|
||||||
// errors?
|
// errors?
|
||||||
var toolbar = $("#notebook");
|
var toolbar = $("#controls_top");
|
||||||
if (e.data.listing.errors.length > 0) {
|
if (e.data.listing.errors.length > 0) {
|
||||||
toolbar.addClass("has-errors");
|
toolbar.addClass("has-errors");
|
||||||
editor.clearGutter("gutter-info");
|
editor.clearGutter("gutter-info");
|
||||||
|
@ -806,6 +806,7 @@ try {
|
||||||
platform_id = qs['platform'] = "vcs";
|
platform_id = qs['platform'] = "vcs";
|
||||||
}
|
}
|
||||||
// load and start platform object
|
// load and start platform object
|
||||||
|
// TODO: self-register platforms
|
||||||
if (platform_id == 'vcs') {
|
if (platform_id == 'vcs') {
|
||||||
platform = new VCSPlatform();
|
platform = new VCSPlatform();
|
||||||
$("#booklink_vcs").show();
|
$("#booklink_vcs").show();
|
||||||
|
@ -813,6 +814,8 @@ try {
|
||||||
platform = new Apple2Platform($("#emulator")[0]);
|
platform = new Apple2Platform($("#emulator")[0]);
|
||||||
} else if (platform_id == 'atarivec') {
|
} else if (platform_id == 'atarivec') {
|
||||||
platform = new AtariVectorPlatform($("#emulator")[0]);
|
platform = new AtariVectorPlatform($("#emulator")[0]);
|
||||||
|
} else if (platform_id == 'exidy') {
|
||||||
|
platform = new ExidyPlatform($("#emulator")[0]);
|
||||||
} else {
|
} else {
|
||||||
alert("Platform " + platform_id + " not recognized");
|
alert("Platform " + platform_id + " not recognized");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue