mirror of
https://github.com/trebonian/visual6502.git
synced 2024-12-23 03:30:03 +00:00
improve load sequencing, add layer choosing, link to python sim, add keyboard tips, add example nmi test, tweak navbuttons, enhance chipstatus output
This commit is contained in:
parent
0ecb753ec6
commit
d032580201
@ -21,6 +21,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
var ctrace = false;
|
var ctrace = false;
|
||||||
|
var noGraphics = false;
|
||||||
|
var loglevel = 3;
|
||||||
var ridx = 0;
|
var ridx = 0;
|
||||||
|
|
||||||
function recalcNodeList(list){
|
function recalcNodeList(list){
|
||||||
|
45
index.html
45
index.html
@ -8,12 +8,26 @@
|
|||||||
<script src="nodenames.js"></script>
|
<script src="nodenames.js"></script>
|
||||||
<script src="wires.js"></script>
|
<script src="wires.js"></script>
|
||||||
<script src="chipsim.js"></script>
|
<script src="chipsim.js"></script>
|
||||||
|
<br>
|
||||||
<script src="memtable.js"></script>
|
<script src="memtable.js"></script>
|
||||||
<script src="macros.js"></script>
|
<script src="macros.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body onload="setup();">
|
<body onload="setTimeout(setup,200)">
|
||||||
<p class="title">The 6502</p>
|
<br />
|
||||||
|
<span id="title"><a href="/">The Visual 6502</a></span><br /><br />
|
||||||
|
<span id="plain">
|
||||||
|
If the chip does not load, try another browser: Chrome, Safari, or Firefox
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Hit '>' to zoom in, '<' to zoom out
|
||||||
|
<br />
|
||||||
|
Right-click to scroll around
|
||||||
|
<br />
|
||||||
|
Enter your own program into the array of RAM
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
</span>
|
||||||
<div class="frame" id="frame">
|
<div class="frame" id="frame">
|
||||||
<div class="chip">
|
<div class="chip">
|
||||||
<canvas class="chip" id="chipbg"></canvas>
|
<canvas class="chip" id="chipbg"></canvas>
|
||||||
@ -22,15 +36,30 @@
|
|||||||
<canvas class="chip" id="hitbuffer"></canvas>
|
<canvas class="chip" id="hitbuffer"></canvas>
|
||||||
</div>
|
</div>
|
||||||
<div class = "buttons">
|
<div class = "buttons">
|
||||||
<a href ="javascript:stopChip()"id="stop"><img class="navstop" src="images/stop.png"></a>
|
<div style="position:relative; float:left;">
|
||||||
<a href ="javascript:runChip()" id="start"><img class="navplay" src="images/play.png"></a>
|
<a href ="javascript:stopChip()"id="stop"><img class="navstop" src="images/stop.png"></a>
|
||||||
<a href ="javascript:resetChip()"><img class="navbutton" src="images/up.png"></a>
|
<a href ="javascript:runChip()" id="start"><img class="navplay" src="images/play.png"></a>
|
||||||
<a href ="javascript:stepBack()"><img class="navbutton" src="images/prev.png"></a>
|
</div>
|
||||||
<a href ="javascript:stepForward()"><img class="navbutton" src="images/next.png"></a>
|
<div style="float:left;">
|
||||||
|
<a href ="javascript:resetChip()"><img class="navbutton" src="images/up.png"></a>
|
||||||
|
<a href ="javascript:stepBack()"><img class="navbutton" src="images/prev.png"></a>
|
||||||
|
<a href ="javascript:stepForward()"><img class="navbutton" src="images/next.png"></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="status" id="status">x: 0<br>y: 0</p>
|
<p class="status" id="status">x: 0<br>y: 0</p>
|
||||||
<table class="memtable" id="memtable"></table>
|
<table class="memtable" id="memtable"></table>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="updateShow"> Show:
|
||||||
|
<input type="checkbox" name="0" id="updateShow0" onchange="updateShow(this.name,this.checked)" />(metal)
|
||||||
|
<input type="checkbox" name="1" id="updateShow1" onchange="updateShow(this.name,this.checked)" />(diff)
|
||||||
|
<input type="checkbox" name="2" id="updateShow2" onchange="updateShow(this.name,this.checked)" />(diode)
|
||||||
|
<input type="checkbox" name="3" id="updateShow3" onchange="updateShow(this.name,this.checked)" />(diff0)
|
||||||
|
<input type="checkbox" name="4" id="updateShow4" onchange="updateShow(this.name,this.checked)" />(diff1)
|
||||||
|
<input type="checkbox" name="5" id="updateShow5" onchange="updateShow(this.name,this.checked)" />(poly)
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In addition to this JavaScript project, see our <a href="../python6502.html">Python-based simulator</a> which may be easier to customize, verify, and apply to the study of long programs.<br />
|
||||||
|
<br />
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
117
macros.js
117
macros.js
@ -39,11 +39,55 @@ function go(n){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function steps(){
|
function steps(){
|
||||||
if(running) step();
|
if(running) {
|
||||||
setTimeout(steps, 200);
|
step();
|
||||||
|
setTimeout(steps, 0); // schedule the next poll
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testNMI(n){
|
||||||
|
initChip();
|
||||||
|
|
||||||
|
mWrite(0x0000, 0x38); // set carry
|
||||||
|
mWrite(0x0001, 0x4c); // jump to test code
|
||||||
|
mWrite(0x0002, 0x06);
|
||||||
|
mWrite(0x0003, 0x23);
|
||||||
|
|
||||||
|
mWrite(0x22ff, 0x38); // set carry
|
||||||
|
mWrite(0x2300, 0xea);
|
||||||
|
mWrite(0x2301, 0xea);
|
||||||
|
mWrite(0x2302, 0xea);
|
||||||
|
mWrite(0x2303, 0xea);
|
||||||
|
mWrite(0x2304, 0xb0); // branch carry set to self
|
||||||
|
mWrite(0x2305, 0xfe);
|
||||||
|
|
||||||
|
mWrite(0x2306, 0xb0); // branch carry set to self
|
||||||
|
mWrite(0x2307, 0x01);
|
||||||
|
mWrite(0x2308, 0x00); // brk should be skipped
|
||||||
|
mWrite(0x2309, 0xa9); // anything
|
||||||
|
mWrite(0x230a, 0xde); // anything
|
||||||
|
mWrite(0x230b, 0xb0); // branch back with page crossing
|
||||||
|
mWrite(0x230c, 0xf2);
|
||||||
|
|
||||||
|
mWrite(0xc018, 0x40); // nmi handler
|
||||||
|
|
||||||
|
mWrite(0xfffa, 0x18); // nmi vector
|
||||||
|
mWrite(0xfffb, 0xc0);
|
||||||
|
mWrite(0xfffc, 0x00); // reset vector
|
||||||
|
mWrite(0xfffd, 0x00);
|
||||||
|
|
||||||
|
for(var i=0;i<n;i++){step();}
|
||||||
|
setLow('nmi');
|
||||||
|
chipStatus();
|
||||||
|
for(var i=0;i<8;i++){step();}
|
||||||
|
setHigh('nmi');
|
||||||
|
chipStatus();
|
||||||
|
for(var i=0;i<16;i++){step();}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function initChip(){
|
function initChip(){
|
||||||
|
var start = now();
|
||||||
for(var nn in nodes) nodes[nn].state = 'fl';
|
for(var nn in nodes) nodes[nn].state = 'fl';
|
||||||
nodes[ngnd].state = 'gnd';
|
nodes[ngnd].state = 'gnd';
|
||||||
nodes[npwr].state = 'vcc';
|
nodes[npwr].state = 'vcc';
|
||||||
@ -60,6 +104,7 @@ function initChip(){
|
|||||||
cycle = 0;
|
cycle = 0;
|
||||||
trace = Array();
|
trace = Array();
|
||||||
chipStatus();
|
chipStatus();
|
||||||
|
console.log('initChip done after', now()-start);
|
||||||
}
|
}
|
||||||
|
|
||||||
function step(){
|
function step(){
|
||||||
@ -82,7 +127,6 @@ function resetStep(){
|
|||||||
else {setHigh('clk0'); handleBusWrite();}
|
else {setHigh('clk0'); handleBusWrite();}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function handleBusRead(){
|
function handleBusRead(){
|
||||||
if(isNodeHigh(nodenames['rw'])) writeDataBus(mRead(readAddressBus()));
|
if(isNodeHigh(nodenames['rw'])) writeDataBus(mRead(readAddressBus()));
|
||||||
}
|
}
|
||||||
@ -102,8 +146,26 @@ function readA(){return readBits('a', 8);}
|
|||||||
function readY(){return readBits('y', 8);}
|
function readY(){return readBits('y', 8);}
|
||||||
function readX(){return readBits('x', 8);}
|
function readX(){return readBits('x', 8);}
|
||||||
function readP(){return readBits('p', 8);}
|
function readP(){return readBits('p', 8);}
|
||||||
|
function readPstring(){
|
||||||
|
var result;
|
||||||
|
result = (isNodeHigh(nodenames['p7'])?'N':'n') +
|
||||||
|
(isNodeHigh(nodenames['p6'])?'V':'v') +
|
||||||
|
'-' +
|
||||||
|
(isNodeHigh(nodenames['p3'])?'B':'b') +
|
||||||
|
(isNodeHigh(nodenames['p3'])?'D':'d') +
|
||||||
|
(isNodeHigh(nodenames['p2'])?'I':'i') +
|
||||||
|
(isNodeHigh(nodenames['p1'])?'Z':'z') +
|
||||||
|
(isNodeHigh(nodenames['p0'])?'C':'c');
|
||||||
|
return result;
|
||||||
|
}
|
||||||
function readSP(){return readBits('s', 8);}
|
function readSP(){return readBits('s', 8);}
|
||||||
|
function readPC(){return (readBits('pch', 8)<<8) + readBits('pcl', 8);}
|
||||||
|
function readPCL(){return readBits('pcl', 8);}
|
||||||
|
function readPCH(){return readBits('pch', 8);}
|
||||||
|
|
||||||
|
function readBit(name){
|
||||||
|
return isNodeHigh(nodenames[name])?1:0;
|
||||||
|
}
|
||||||
function readBits(name, n){
|
function readBits(name, n){
|
||||||
var res = 0;
|
var res = 0;
|
||||||
for(var i=0;i<n;i++){
|
for(var i=0;i<n;i++){
|
||||||
@ -151,6 +213,7 @@ function runChip(){
|
|||||||
start.style.visibility = 'hidden';
|
start.style.visibility = 'hidden';
|
||||||
stop.style.visibility = 'visible';
|
stop.style.visibility = 'visible';
|
||||||
running = true;
|
running = true;
|
||||||
|
steps();
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopChip(){
|
function stopChip(){
|
||||||
@ -163,7 +226,8 @@ function stopChip(){
|
|||||||
|
|
||||||
function resetChip(){
|
function resetChip(){
|
||||||
stopChip();
|
stopChip();
|
||||||
initChip();
|
setStatus('resetting 6502...');
|
||||||
|
setTimeout(initChip,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stepForward(){
|
function stepForward(){
|
||||||
@ -181,17 +245,40 @@ function stepBack(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function chipStatus(){
|
function chipStatus(){
|
||||||
var pc = readAddressBus();
|
var ab = readAddressBus();
|
||||||
setStatus('PC:', hexWord(pc),
|
var machine1 =
|
||||||
'D:', hexByte(readDataBus()),
|
' halfcyc:' + cycle +
|
||||||
'SP:',hexByte(readSP()),
|
' phi0:' + readBit('clk0') +
|
||||||
'cycle:', cycle, '<br>',
|
' AB:' + hexWord(ab) +
|
||||||
'A:', hexByte(readA()),
|
' D:' + hexByte(readDataBus()) +
|
||||||
'X:', hexByte(readX()),
|
' RnW:' + readBit('rw');
|
||||||
'Y:', hexByte(readY()),
|
var machine2 =
|
||||||
'P:', hexByte(readP())
|
' PC:' + hexWord(readPC()) +
|
||||||
);
|
' A:' + hexByte(readA()) +
|
||||||
selectCell(pc);
|
' X:' + hexByte(readX()) +
|
||||||
|
' Y:' + hexByte(readY()) +
|
||||||
|
' SP:' + hexByte(readSP()) +
|
||||||
|
' ' + readPstring();
|
||||||
|
var machine3 =
|
||||||
|
' Sync:' + readBit('sync')
|
||||||
|
' IRQ:' + readBit('irq') +
|
||||||
|
' NMI:' + readBit('nmi');
|
||||||
|
var machine4 =
|
||||||
|
' IR:' + hexByte(255 - readBits('notir', 8)) +
|
||||||
|
' idl:' + hexByte(255 - readBits('idl', 8)) +
|
||||||
|
' alu:' + hexByte(255 - readBits('alu', 8)) +
|
||||||
|
' TCstate:' + readBit('clock1') + readBit('clock2') +
|
||||||
|
readBit('t2') + readBit('t3') + readBit('t4') + readBit('t5');
|
||||||
|
var machine5 =
|
||||||
|
' notRdy0:' + readBit('notRdy0') +
|
||||||
|
' fetch:' + readBit('fetch') +
|
||||||
|
' clearIR:' + readBit('clearIR') +
|
||||||
|
' D1x1:' + readBit('D1x1');
|
||||||
|
setStatus(machine1 + "<br>" + machine2);
|
||||||
|
if (loglevel>2) {
|
||||||
|
console.log(machine1 + " " + machine2 + " " + machine3 + " " + machine4 + " " + machine5);
|
||||||
|
}
|
||||||
|
selectCell(ab);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMem(){
|
function getMem(){
|
||||||
|
36
wires.js
36
wires.js
@ -26,8 +26,10 @@ var zoom=1;
|
|||||||
var dragMouseX, dragMouseY, moved;
|
var dragMouseX, dragMouseY, moved;
|
||||||
var statbox;
|
var statbox;
|
||||||
|
|
||||||
var colors = ['rgba(128,128,128,0.4)','#FFFF00','#FF00FF','#4DFF4D',
|
var layernames = ['metal', 'diff', 'inputdiode', 'diff0', 'diff1', 'poly'];
|
||||||
|
var colors = ['rgba(128,128,192,0.4)','#FFFF00','#FF00FF','#4DFF4D',
|
||||||
'#FF4D4D','#801AC0','rgba(128,0,255,0.75)'];
|
'#FF4D4D','#801AC0','rgba(128,0,255,0.75)'];
|
||||||
|
var drawlayers = [true, true, false, false, false, false];
|
||||||
|
|
||||||
var nodes = new Array();
|
var nodes = new Array();
|
||||||
var transistors = {};
|
var transistors = {};
|
||||||
@ -42,11 +44,19 @@ var npwr = nodenames['vcc'];
|
|||||||
//
|
//
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
|
|
||||||
|
// try to present a meaningful page before starting expensive work
|
||||||
function setup(){
|
function setup(){
|
||||||
|
statbox = document.getElementById('status');
|
||||||
|
setStatus('loading 6502...');
|
||||||
|
setTimeout(setup_part2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_part2(){
|
||||||
frame = document.getElementById('frame');
|
frame = document.getElementById('frame');
|
||||||
statbox = document.getElementById('status');
|
statbox = document.getElementById('status');
|
||||||
setupNodes();
|
setupNodes();
|
||||||
setupTransistors();
|
setupTransistors();
|
||||||
|
setupLayerVisibility();
|
||||||
setupBackground();
|
setupBackground();
|
||||||
setupOverlay();
|
setupOverlay();
|
||||||
setupHilite();
|
setupHilite();
|
||||||
@ -56,6 +66,11 @@ function setup(){
|
|||||||
setupTable();
|
setupTable();
|
||||||
window.onkeypress = function(e){handleKey(e);}
|
window.onkeypress = function(e){handleKey(e);}
|
||||||
hilite.onmousedown = function(e){mouseDown(e);}
|
hilite.onmousedown = function(e){mouseDown(e);}
|
||||||
|
setStatus('resetting 6502...');
|
||||||
|
setTimeout(setup_part3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_part3(){
|
||||||
initChip();
|
initChip();
|
||||||
document.getElementById('stop').style.visibility = 'hidden';
|
document.getElementById('stop').style.visibility = 'hidden';
|
||||||
go();
|
go();
|
||||||
@ -89,8 +104,17 @@ function setupTransistors(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupLayerVisibility(){
|
||||||
|
var x=document.getElementById('updateShow');
|
||||||
|
for (var i=0;i<x.childNodes.length;i++) {
|
||||||
|
if(x.childNodes[i].type='checkbox'){
|
||||||
|
x.childNodes[i].checked=drawlayers[x.childNodes[i].name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setupBackground(){
|
function setupBackground(){
|
||||||
|
console.log('starting setupBackground');
|
||||||
chipbg = document.getElementById('chipbg');
|
chipbg = document.getElementById('chipbg');
|
||||||
chipbg.width = 4000;
|
chipbg.width = 4000;
|
||||||
chipbg.height = 4000;
|
chipbg.height = 4000;
|
||||||
@ -100,16 +124,16 @@ function setupBackground(){
|
|||||||
ctx.strokeStyle = 'rgba(255,255,255,0.5)';
|
ctx.strokeStyle = 'rgba(255,255,255,0.5)';
|
||||||
ctx.lineWidth = 4;
|
ctx.lineWidth = 4;
|
||||||
ctx.fillRect(0,0,10000,10000);
|
ctx.fillRect(0,0,10000,10000);
|
||||||
var start = now();
|
|
||||||
for(var i in segdefs){
|
for(var i in segdefs){
|
||||||
var seg = segdefs[i];
|
var seg = segdefs[i];
|
||||||
var c = seg[2];
|
var c = seg[2];
|
||||||
|
if (drawlayers[c]) {
|
||||||
ctx.fillStyle = colors[c];
|
ctx.fillStyle = colors[c];
|
||||||
drawSeg(ctx, segdefs[i].slice(3));
|
drawSeg(ctx, segdefs[i].slice(3));
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
if((c==0)||(c==6)) ctx.stroke();
|
if((c==0)||(c==6)) ctx.stroke();
|
||||||
}
|
}
|
||||||
// console.log('time to draw: ', now() - start, ' ms');
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupOverlay(){
|
function setupOverlay(){
|
||||||
@ -189,6 +213,7 @@ function hiliteNode(n){
|
|||||||
|
|
||||||
|
|
||||||
function drawSeg(ctx, seg){
|
function drawSeg(ctx, seg){
|
||||||
|
if(noGraphics) return;
|
||||||
var dx = 400;
|
var dx = 400;
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.moveTo(seg[0]+dx, 10000-seg[1])
|
ctx.moveTo(seg[0]+dx, 10000-seg[1])
|
||||||
@ -288,6 +313,11 @@ function findNodeNumber(x,y){
|
|||||||
return (high<<8)+(mid<<4)+low;
|
return (high<<8)+(mid<<4)+low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateShow(layer, on){
|
||||||
|
drawlayers[layer]=on;
|
||||||
|
setupBackground();
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
//
|
//
|
||||||
// Etc.
|
// Etc.
|
||||||
|
Loading…
Reference in New Issue
Block a user