First Commit
This commit is contained in:
commit
4d8da5b680
|
@ -0,0 +1,186 @@
|
||||||
|
var ctrace = false;
|
||||||
|
var ridx = 0;
|
||||||
|
|
||||||
|
function recalcNodeList(list){
|
||||||
|
var n = list[0];
|
||||||
|
var recalclist = new Array();
|
||||||
|
for(var j=0;j<100;j++){ // loop limiter
|
||||||
|
if(list.length==0) return;
|
||||||
|
if(ctrace) console.log(j, list);
|
||||||
|
for(var i in list) recalcNode(list[i], recalclist);
|
||||||
|
list = recalclist;
|
||||||
|
recalclist = new Array();
|
||||||
|
}
|
||||||
|
console.log(n,'looping...');
|
||||||
|
}
|
||||||
|
|
||||||
|
function recalcNode(node, recalclist){
|
||||||
|
if(node==ngnd) return;
|
||||||
|
if(node==npwr) return;
|
||||||
|
var group = getNodeGroup(node);
|
||||||
|
var newv = getNodeValue(group);
|
||||||
|
if(ctrace) console.log('recalc', node, group);
|
||||||
|
for(var i in group){
|
||||||
|
var n = nodes[group[i]];
|
||||||
|
if(n.state!=newv && ctrace) console.log(group[i], n.state, newv);
|
||||||
|
n.state = newv;
|
||||||
|
for(var t in n.gates) recalcTransistor(n.gates[t], recalclist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function recalcTransistor(tn, recalclist){
|
||||||
|
var t = transistors[tn];
|
||||||
|
if(isNodeHigh(t.gate)) turnTransistorOn(t, recalclist);
|
||||||
|
else turnTransistorOff(t, recalclist);
|
||||||
|
}
|
||||||
|
|
||||||
|
function turnTransistorOn(t, recalclist){
|
||||||
|
if(t.on) return;
|
||||||
|
if(ctrace) console.log(t.name, 'on', t.gate, t.c1, t.c2);
|
||||||
|
t.on = true;
|
||||||
|
addRecalcNode(t.c1, recalclist);
|
||||||
|
addRecalcNode(t.c2, recalclist);
|
||||||
|
}
|
||||||
|
|
||||||
|
function turnTransistorOff(t, recalclist){
|
||||||
|
if(!t.on) return;
|
||||||
|
if(ctrace) console.log(t.name, 'off', t.gate, t.c1, t.c2);
|
||||||
|
t.on = false;
|
||||||
|
floatnode(t.c1);
|
||||||
|
floatnode(t.c2);
|
||||||
|
addRecalcNode(t.c1, recalclist);
|
||||||
|
addRecalcNode(t.c2, recalclist);
|
||||||
|
}
|
||||||
|
|
||||||
|
function floatnode(nn){
|
||||||
|
if(nn==ngnd) return;
|
||||||
|
if(nn==npwr) return;
|
||||||
|
var n = nodes[nn];
|
||||||
|
if(n.state=='gnd') n.state = 'fl';
|
||||||
|
if(n.state=='pd') n.state = 'fl';
|
||||||
|
if(n.state=='vcc') n.state = 'fh';
|
||||||
|
if(n.state=='pu') n.state = 'fh';
|
||||||
|
if(ctrace) console.log('floating', nn, 'to', n.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addRecalcNode(nn, recalclist){
|
||||||
|
if(nn==ngnd) return;
|
||||||
|
if(nn==npwr) return;
|
||||||
|
if(arrayContains(recalclist, nn)) return;
|
||||||
|
recalclist.push(nn);
|
||||||
|
// setAdd(recalclist, nn);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNodeGroup(i){
|
||||||
|
var group = new Array();
|
||||||
|
addNodeToGroup(i, group);
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNodeToGroup(i, group){
|
||||||
|
if(arrayContains(group, i)) return;
|
||||||
|
group.push(i);
|
||||||
|
if(i==ngnd) return;
|
||||||
|
if(i==npwr) return;
|
||||||
|
for(var t in nodes[i].c1c2s) addNodeTransistor(i, nodes[i].c1c2s[t], group);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNodeTransistor(node, t, group){
|
||||||
|
var tr = transistors[t];
|
||||||
|
if(!tr.on) return;
|
||||||
|
var other;
|
||||||
|
if(tr.c1==node) other=tr.c2;
|
||||||
|
if(tr.c2==node) other=tr.c1;
|
||||||
|
addNodeToGroup(other, group);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getNodeValue(group){
|
||||||
|
if(arrayContains(group, ngnd)) return 'gnd';
|
||||||
|
if(arrayContains(group, npwr)) return 'vcc';
|
||||||
|
var flstate;
|
||||||
|
for(var i in group){
|
||||||
|
var nn = group[i];
|
||||||
|
var n = nodes[nn];
|
||||||
|
if(n.pullup) return 'pu';
|
||||||
|
if(n.pulldown) return 'pd';
|
||||||
|
if((n.state=='fl')&&(flstate==undefined)) flstate = 'fl';
|
||||||
|
if(n.state=='fh') flstate = 'fh';
|
||||||
|
}
|
||||||
|
if(flstate==undefined) console.log(group);
|
||||||
|
return flstate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function isNodeHigh(nn){
|
||||||
|
return arrayContains(['vcc','pu','fh'], nodes[nn].state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveString(name, str){
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.onreadystatechange=function(){};
|
||||||
|
request.open('PUT', 'save.php?name='+name, true);
|
||||||
|
request.setRequestHeader('Content-Type', 'text/plain');
|
||||||
|
request.send(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function allNodes(){
|
||||||
|
var res = new Array();
|
||||||
|
for(var i in nodes) if((i!=npwr)&&(i!=ngnd)) res.push(i);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stateString(){
|
||||||
|
var codes = {gnd: 'g', vcc: 'v', pu: 'p', pd: 'd', fh: 'f', fl: 'l'};
|
||||||
|
var res = '';
|
||||||
|
for(var i=0;i<1725;i++){
|
||||||
|
var n = nodes[i];
|
||||||
|
if(n==undefined) res+='x';
|
||||||
|
else if(i==ngnd) res+='g';
|
||||||
|
else if(i==npwr) res+='v';
|
||||||
|
else res+= codes[n.state];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showState(str){
|
||||||
|
var codes = {g: 'gnd', v: 'vcc', p: 'pu', d: 'pd', f: 'fh', l: 'fl'};
|
||||||
|
for(var i=0;i<str.length;i++){
|
||||||
|
if(str[i]=='x') continue;
|
||||||
|
nodes[i].state = codes[str[i]];
|
||||||
|
var gates = nodes[i].gates;
|
||||||
|
for(var t in gates) transistors[gates[t]].on = isNodeHigh(i);
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setPd(name){
|
||||||
|
var nn = nodenames[name];
|
||||||
|
nodes[nn].pullup = false;
|
||||||
|
nodes[nn].pulldown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHigh(name){
|
||||||
|
var nn = nodenames[name];
|
||||||
|
nodes[nn].pullup = true;
|
||||||
|
nodes[nn].pulldown = false;
|
||||||
|
recalcNodeList([nn]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLow(name){
|
||||||
|
var nn = nodenames[name];
|
||||||
|
nodes[nn].pullup = false;
|
||||||
|
nodes[nn].pulldown = true;
|
||||||
|
recalcNodeList([nn]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAdd(arr, el){
|
||||||
|
var idx = ridx%(arr.length+1);
|
||||||
|
ridx+=131;
|
||||||
|
ridx%=123;
|
||||||
|
arr.splice(idx, 0, el);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function arrayContains(arr, el){return arr.indexOf(el)!=-1;}
|
Binary file not shown.
After Width: | Height: | Size: 358 B |
Binary file not shown.
After Width: | Height: | Size: 439 B |
Binary file not shown.
After Width: | Height: | Size: 355 B |
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 334 B |
|
@ -0,0 +1,36 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>6502</title>
|
||||||
|
<style type="text/css">@import "wires.css";</style>
|
||||||
|
<script src="segdefs.js"></script>
|
||||||
|
<script src="transdefs.js"></script>
|
||||||
|
<script src="nodenames.js"></script>
|
||||||
|
<script src="wires.js"></script>
|
||||||
|
<script src="chipsim.js"></script>
|
||||||
|
<script src="memtable.js"></script>
|
||||||
|
<script src="macros.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="setup();">
|
||||||
|
<p class="title">The 6502</p>
|
||||||
|
<div class="frame" id="frame">
|
||||||
|
<div class="chip">
|
||||||
|
<canvas class="chip" id="chipbg"></canvas>
|
||||||
|
<canvas class="chip" id="overlay"></canvas>
|
||||||
|
<canvas class="chip" id="hilite"></canvas>
|
||||||
|
<canvas class="chip" id="hitbuffer"></canvas>
|
||||||
|
</div>
|
||||||
|
<div class = "buttons">
|
||||||
|
<a href ="javascript:stopChip()"id="stop"><img class="navstop" src="images/stop.png"></a>
|
||||||
|
<a href ="javascript:runChip()" id="start"><img class="navplay" src="images/play.png"></a>
|
||||||
|
<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>
|
||||||
|
<p class="status" id="status">x: 0<br>y: 0</p>
|
||||||
|
<table class="memtable" id="memtable"></table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,179 @@
|
||||||
|
var memory = Array();
|
||||||
|
var code = [0xa9, 0x00, 0x20, 0x10, 0x00, 0x4c, 0x02, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xe8, 0x88, 0xe6, 0x40, 0x38, 0x69, 0x02, 0x60];
|
||||||
|
var cycle = 0;
|
||||||
|
var trace = Array();
|
||||||
|
var running = false;
|
||||||
|
|
||||||
|
function go(n){
|
||||||
|
for(var i=0;i<code.length;i++){
|
||||||
|
mWrite(i, code[i]);
|
||||||
|
setCellValue(i, code[i]);
|
||||||
|
}
|
||||||
|
mWrite(0xfffc, 0x00);
|
||||||
|
mWrite(0xfffd, 0x00);
|
||||||
|
steps();
|
||||||
|
}
|
||||||
|
|
||||||
|
function steps(){
|
||||||
|
if(running) step();
|
||||||
|
setTimeout(steps, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initChip(){
|
||||||
|
for(var nn in nodes) nodes[nn].state = 'fl';
|
||||||
|
nodes[ngnd].state = 'gnd';
|
||||||
|
nodes[npwr].state = 'vcc';
|
||||||
|
for(var tn in transistors) transistors[tn].on = false;
|
||||||
|
setLow('res');
|
||||||
|
setLow('clk0');
|
||||||
|
setHigh('rdy'); setLow('so');
|
||||||
|
setHigh('irq'); setHigh('nmi');
|
||||||
|
recalcNodeList(allNodes());
|
||||||
|
for(var i=0;i<8;i++){setHigh('clk0'), setLow('clk0');}
|
||||||
|
setHigh('res');
|
||||||
|
for(var i=0;i<14;i++){step();}
|
||||||
|
refresh();
|
||||||
|
cycle = 0;
|
||||||
|
trace = Array();
|
||||||
|
chipStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function step(){
|
||||||
|
trace[cycle]= {chip: stateString(), mem: getMem()};
|
||||||
|
halfStep();
|
||||||
|
cycle++;
|
||||||
|
chipStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function halfStep(){
|
||||||
|
var clk = isNodeHigh(nodenames['clk0']);
|
||||||
|
if (clk) {setLow('clk0'); handleBusRead(); }
|
||||||
|
else {setHigh('clk0'); handleBusWrite();}
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBusRead(){
|
||||||
|
if(isNodeHigh(nodenames['rw'])) writeDataBus(mRead(readAddressBus()));
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBusWrite(){
|
||||||
|
if(!isNodeHigh(nodenames['rw'])){
|
||||||
|
var a = readAddressBus();
|
||||||
|
var d = readDataBus();
|
||||||
|
mWrite(a,d);
|
||||||
|
if(a<0x200) setCellValue(a,d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readAddressBus(){return readBits('ab', 16);}
|
||||||
|
function readDataBus(){return readBits('db', 8);}
|
||||||
|
function readA(){return readBits('a', 8);}
|
||||||
|
function readY(){return readBits('y', 8);}
|
||||||
|
function readX(){return readBits('x', 8);}
|
||||||
|
function readP(){return readBits('p', 8);}
|
||||||
|
function readSP(){return readBits('s', 8);}
|
||||||
|
|
||||||
|
function readBits(name, n){
|
||||||
|
var res = 0;
|
||||||
|
for(var i=0;i<n;i++){
|
||||||
|
var nn = nodenames[name+i];
|
||||||
|
res+=((isNodeHigh(nn))?1:0)<<i;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeDataBus(x){
|
||||||
|
var recalcs = Array();
|
||||||
|
for(var i=0;i<8;i++){
|
||||||
|
var nn = nodenames['db'+i];
|
||||||
|
var n = nodes[nn];
|
||||||
|
if((x%2)==0) {n.pulldown=true; n.pullup=false;}
|
||||||
|
else {n.pulldown=false; n.pullup=true;}
|
||||||
|
recalcs.push(nn);
|
||||||
|
x>>=1;
|
||||||
|
}
|
||||||
|
recalcNodeList(recalcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mRead(a){
|
||||||
|
if(memory[a]==undefined) return 0;
|
||||||
|
else return memory[a];
|
||||||
|
}
|
||||||
|
|
||||||
|
function mWrite(a, d){memory[a]=d;}
|
||||||
|
|
||||||
|
|
||||||
|
function clkNodes(){
|
||||||
|
var res = Array();
|
||||||
|
res.push(943);
|
||||||
|
for(var i in nodes[943].gates){
|
||||||
|
var t = transistors[nodes[943].gates[i]];
|
||||||
|
if(t.c1==npwr) res.push(t.c2);
|
||||||
|
if(t.c2==npwr) res.push(t.c1);
|
||||||
|
}
|
||||||
|
hiliteNode(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
function runChip(){
|
||||||
|
var start = document.getElementById('start');
|
||||||
|
var stop = document.getElementById('stop');
|
||||||
|
start.style.visibility = 'hidden';
|
||||||
|
stop.style.visibility = 'visible';
|
||||||
|
running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopChip(){
|
||||||
|
var start = document.getElementById('start');
|
||||||
|
var stop = document.getElementById('stop');
|
||||||
|
start.style.visibility = 'visible';
|
||||||
|
stop.style.visibility = 'hidden';
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetChip(){
|
||||||
|
stopChip();
|
||||||
|
initChip();
|
||||||
|
}
|
||||||
|
|
||||||
|
function stepForward(){
|
||||||
|
stopChip();
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
|
||||||
|
function stepBack(){
|
||||||
|
if(cycle==0) return;
|
||||||
|
showState(trace[--cycle].chip);
|
||||||
|
setMem(trace[cycle].mem);
|
||||||
|
var clk = isNodeHigh(nodenames['clk0']);
|
||||||
|
if(!clk) writeDataBus(mRead(readAddressBus()));
|
||||||
|
chipStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function chipStatus(){
|
||||||
|
var pc = readAddressBus();
|
||||||
|
setStatus('PC:', hexWord(pc),
|
||||||
|
'D:', hexByte(readDataBus()),
|
||||||
|
'SP:',hexByte(readSP()),
|
||||||
|
'cycle:', cycle, '<br>',
|
||||||
|
'A:', hexByte(readA()),
|
||||||
|
'X:', hexByte(readX()),
|
||||||
|
'Y:', hexByte(readY()),
|
||||||
|
'P:', hexByte(readP())
|
||||||
|
);
|
||||||
|
selectCell(pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMem(){
|
||||||
|
var res = Array();
|
||||||
|
for(var i=0;i<0x200;i++) res.push(mRead(i));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMem(arr){
|
||||||
|
for(var i=0;i<0x200;i++){mWrite(i, arr[i]); setCellValue(i, arr[i]);}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hexWord(n){return (0x10000+n).toString(16).substring(1)}
|
||||||
|
function hexByte(n){return (0x100+n).toString(16).substring(1)}
|
|
@ -0,0 +1,67 @@
|
||||||
|
var table;
|
||||||
|
var selected;
|
||||||
|
|
||||||
|
function setupTable(){
|
||||||
|
table = document.getElementById('memtable');
|
||||||
|
for(var r=0;r<32;r++){
|
||||||
|
var row = document.createElement('tr');
|
||||||
|
table.appendChild(row);
|
||||||
|
var col = document.createElement('td');
|
||||||
|
col.appendChild(document.createTextNode(hexWord(r*16)+':'));
|
||||||
|
col.onmousedown = unselectCell;
|
||||||
|
row.appendChild(col);
|
||||||
|
for(var c=0;c<16;c++){
|
||||||
|
col = document.createElement('td');
|
||||||
|
col.addr = r*16+c;
|
||||||
|
col.val = 0;
|
||||||
|
col.onmousedown = function(e){handleCellClick(e);};
|
||||||
|
col.appendChild(document.createTextNode('00'));
|
||||||
|
row.appendChild(col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCellClick(e){
|
||||||
|
var c = e.target;
|
||||||
|
selectCell(c.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cellKeydown(e){
|
||||||
|
var c = e.keyCode;
|
||||||
|
if(c==13) unselectCell();
|
||||||
|
else if(c==32) selectCell((selected+1)%0x200);
|
||||||
|
else if(c==8) selectCell((selected+0x1ff)%0x200);
|
||||||
|
else if((c>=48)&&(c<58)) setCellValue(selected, getCellValue(selected)*16+c-48);
|
||||||
|
else if((c>=65)&&(c<71)) setCellValue(selected, getCellValue(selected)*16+c-55);
|
||||||
|
mWrite(selected, getCellValue(selected));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCellValue(n, val){
|
||||||
|
val%=256;
|
||||||
|
cellEl(n).val=val;
|
||||||
|
cellEl(n).innerHTML=hexByte(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCellValue(n){return cellEl(n).val;}
|
||||||
|
|
||||||
|
function selectCell(n){
|
||||||
|
unselectCell();
|
||||||
|
if(n>=0x200) return;
|
||||||
|
cellEl(n).style.background = '#ff8';
|
||||||
|
selected = n;
|
||||||
|
window.onkeydown = function(e){cellKeydown(e);};
|
||||||
|
}
|
||||||
|
|
||||||
|
function unselectCell(){
|
||||||
|
if(selected==undefined) return;
|
||||||
|
cellEl(selected).style.background = '#fff';
|
||||||
|
selected = undefined;
|
||||||
|
window.onkeydown = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cellEl(n){
|
||||||
|
var r = n>>4;
|
||||||
|
var c = n%16;
|
||||||
|
var e = table.children[r].children[c+1];
|
||||||
|
return e;
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
var nodenames ={
|
||||||
|
db1: 82,
|
||||||
|
db0: 1005,
|
||||||
|
db3: 650,
|
||||||
|
db2: 945,
|
||||||
|
db5: 175,
|
||||||
|
db4: 1393,
|
||||||
|
db7: 1349,
|
||||||
|
db6: 1591,
|
||||||
|
a1: 1234,
|
||||||
|
ab1: 451,
|
||||||
|
ab2: 1340,
|
||||||
|
a2: 978,
|
||||||
|
s2: 81,
|
||||||
|
a5: 858,
|
||||||
|
a4: 727,
|
||||||
|
a7: 1653,
|
||||||
|
a6: 1136,
|
||||||
|
so: 1672,
|
||||||
|
sync: 539,
|
||||||
|
vcc: 657,
|
||||||
|
clk1out: 1163,
|
||||||
|
p2: 1421,
|
||||||
|
p3: 439,
|
||||||
|
p0: 687,
|
||||||
|
p1: 1444,
|
||||||
|
p6: 77,
|
||||||
|
p7: 1370,
|
||||||
|
p4: 1119,
|
||||||
|
p5: 0,
|
||||||
|
pcl3: 1359,
|
||||||
|
pcl2: 655,
|
||||||
|
pcl1: 1022,
|
||||||
|
pcl0: 1139,
|
||||||
|
pcl7: 1611,
|
||||||
|
pcl6: 377,
|
||||||
|
pcl5: 622,
|
||||||
|
pcl4: 900,
|
||||||
|
clk0: 1171,
|
||||||
|
s3: 1532,
|
||||||
|
res: 159,
|
||||||
|
s1: 183,
|
||||||
|
s0: 1403,
|
||||||
|
s7: 1435,
|
||||||
|
s6: 1212,
|
||||||
|
s5: 1098,
|
||||||
|
s4: 1702,
|
||||||
|
rw: 1156,
|
||||||
|
x2: 1,
|
||||||
|
x3: 1648,
|
||||||
|
x0: 1216,
|
||||||
|
x1: 98,
|
||||||
|
x6: 448,
|
||||||
|
x7: 777,
|
||||||
|
x4: 85,
|
||||||
|
x5: 589,
|
||||||
|
rdy: 89,
|
||||||
|
clk2out: 421,
|
||||||
|
nmi: 1297,
|
||||||
|
ab12: 1237,
|
||||||
|
ab13: 349,
|
||||||
|
ab10: 1443,
|
||||||
|
ab11: 399,
|
||||||
|
ab14: 672,
|
||||||
|
ab15: 195,
|
||||||
|
ab0: 268,
|
||||||
|
a0: 737,
|
||||||
|
a3: 162,
|
||||||
|
ab3: 211,
|
||||||
|
ab4: 435,
|
||||||
|
ab5: 736,
|
||||||
|
ab6: 887,
|
||||||
|
ab7: 1493,
|
||||||
|
ab8: 230,
|
||||||
|
ab9: 148,
|
||||||
|
pch7: 205,
|
||||||
|
pch6: 1551,
|
||||||
|
pch5: 49,
|
||||||
|
pch4: 948,
|
||||||
|
pch3: 584,
|
||||||
|
pch2: 502,
|
||||||
|
pch1: 292,
|
||||||
|
pch0: 1670,
|
||||||
|
irq: 103,
|
||||||
|
vss: 558,
|
||||||
|
y1: 1148,
|
||||||
|
y0: 64,
|
||||||
|
y3: 305,
|
||||||
|
y2: 573,
|
||||||
|
y5: 615,
|
||||||
|
y4: 989,
|
||||||
|
y7: 843,
|
||||||
|
y6: 115,
|
||||||
|
cclk: 943
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$filename = $_REQUEST['name'];
|
||||||
|
file_put_contents($filename, file_get_contents("php://input"));
|
||||||
|
|
||||||
|
function file_put_contents($filename, $data) {
|
||||||
|
$f = @fopen($filename, 'w');
|
||||||
|
if ($f) {
|
||||||
|
$bytes = fwrite($f, $data);
|
||||||
|
fclose($f);
|
||||||
|
return $bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,68 @@
|
||||||
|
body {
|
||||||
|
background: white;
|
||||||
|
color: black;
|
||||||
|
font-family: cursive;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.frame {
|
||||||
|
margin-left: 10px;
|
||||||
|
position: relative;
|
||||||
|
width: 1150px;
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.chip {
|
||||||
|
background: lightgray;
|
||||||
|
border: 2px solid gray;
|
||||||
|
position: absolute;
|
||||||
|
width: 800px;
|
||||||
|
height: 600px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.chip {
|
||||||
|
position: absolute;
|
||||||
|
width: 600px;
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.buttons{
|
||||||
|
position: absolute;
|
||||||
|
top: -5px;
|
||||||
|
left: 820px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.status {
|
||||||
|
position: absolute;
|
||||||
|
left: 820px;
|
||||||
|
top: 20px;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.navbutton{
|
||||||
|
margin-left: -5px;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.navplay{
|
||||||
|
margin-left: -5px;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.navstop{
|
||||||
|
position: absolute;
|
||||||
|
left: -5px;
|
||||||
|
top: 9px;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.memtable {
|
||||||
|
position: absolute;
|
||||||
|
top: 63px;
|
||||||
|
left: 820px;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 12px;
|
||||||
|
border-spacing: 0px;
|
||||||
|
}
|
|
@ -0,0 +1,316 @@
|
||||||
|
var frame, chipbg, overlay, hilite, hitbuffer, ctx;
|
||||||
|
var centerx=300, centery=300;
|
||||||
|
var zoom=1;
|
||||||
|
var dragMouseX, dragMouseY, moved;
|
||||||
|
var statbox;
|
||||||
|
|
||||||
|
var colors = ['rgba(128,128,128,0.4)','#FFFF00','#FF00FF','#4DFF4D',
|
||||||
|
'#FF4D4D','#801AC0','rgba(128,0,255,0.75)'];
|
||||||
|
|
||||||
|
var nodes = new Array();
|
||||||
|
var transistors = {};
|
||||||
|
|
||||||
|
var ngnd = nodenames['vss'];
|
||||||
|
var npwr = nodenames['vcc'];
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////
|
||||||
|
//
|
||||||
|
// Drawing Setup
|
||||||
|
//
|
||||||
|
/////////////////////////
|
||||||
|
|
||||||
|
function setup(){
|
||||||
|
frame = document.getElementById('frame');
|
||||||
|
statbox = document.getElementById('status');
|
||||||
|
setupNodes();
|
||||||
|
setupTransistors();
|
||||||
|
setupBackground();
|
||||||
|
setupOverlay();
|
||||||
|
setupHilite();
|
||||||
|
setupHitBuffer();
|
||||||
|
recenter();
|
||||||
|
refresh();
|
||||||
|
setupTable();
|
||||||
|
window.onkeypress = function(e){handleKey(e);}
|
||||||
|
hilite.onmousedown = function(e){mouseDown(e);}
|
||||||
|
initChip();
|
||||||
|
document.getElementById('stop').style.visibility = 'hidden';
|
||||||
|
go();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupNodes(){
|
||||||
|
for(var i in segdefs){
|
||||||
|
var seg = segdefs[i];
|
||||||
|
var w = seg[0];
|
||||||
|
if(nodes[w]==undefined)
|
||||||
|
nodes[w] = {segs: new Array(), num: w, pullup: seg[1]=='+',
|
||||||
|
state: 'fl', gates: new Array(), c1c2s: new Array()};
|
||||||
|
if(w==ngnd) continue;
|
||||||
|
if(w==npwr) continue;
|
||||||
|
nodes[w].segs.push(seg.slice(3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupTransistors(){
|
||||||
|
for(i in transdefs){
|
||||||
|
var tdef = transdefs[i];
|
||||||
|
var name = tdef[0];
|
||||||
|
var gate = tdef[1];
|
||||||
|
var c1 = tdef[2];
|
||||||
|
var c2 = tdef[3];
|
||||||
|
var trans = {name: name, on: false, gate: gate, c1: c1, c2: c2};
|
||||||
|
nodes[gate].gates.push(name);
|
||||||
|
nodes[c1].c1c2s.push(name);
|
||||||
|
nodes[c2].c1c2s.push(name);
|
||||||
|
transistors[name] = trans;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setupBackground(){
|
||||||
|
chipbg = document.getElementById('chipbg');
|
||||||
|
chipbg.width = 4000;
|
||||||
|
chipbg.height = 4000;
|
||||||
|
var ctx = chipbg.getContext('2d');
|
||||||
|
ctx.scale(chipbg.width/10000, chipbg.height/10000);
|
||||||
|
ctx.fillStyle = '#000000';
|
||||||
|
ctx.strokeStyle = 'rgba(255,255,255,0.5)';
|
||||||
|
ctx.lineWidth = 4;
|
||||||
|
ctx.fillRect(0,0,10000,10000);
|
||||||
|
var start = now();
|
||||||
|
for(var i in segdefs){
|
||||||
|
var seg = segdefs[i];
|
||||||
|
var c = seg[2];
|
||||||
|
ctx.fillStyle = colors[c];
|
||||||
|
drawSeg(ctx, segdefs[i].slice(3));
|
||||||
|
ctx.fill();
|
||||||
|
if((c==0)||(c==6)) ctx.stroke();
|
||||||
|
}
|
||||||
|
// console.log('time to draw: ', now() - start, ' ms');
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupOverlay(){
|
||||||
|
overlay = document.getElementById('overlay');
|
||||||
|
overlay.width = 4000;
|
||||||
|
overlay.height = 4000;
|
||||||
|
ctx = overlay.getContext('2d');
|
||||||
|
ctx.scale(overlay.width/10000, overlay.height/10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupHilite(){
|
||||||
|
hilite = document.getElementById('hilite');
|
||||||
|
hilite.width = 4000;
|
||||||
|
hilite.height = 4000;
|
||||||
|
var ctx = hilite.getContext('2d');
|
||||||
|
ctx.scale(hilite.width/10000, hilite.height/10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupHitBuffer(){
|
||||||
|
hitbuffer = document.getElementById('hitbuffer');
|
||||||
|
hitbuffer.width = 4000;
|
||||||
|
hitbuffer.height = 4000;
|
||||||
|
hitbuffer.style.visibility = 'hidden';
|
||||||
|
var ctx = hitbuffer.getContext('2d');
|
||||||
|
ctx.scale(hitbuffer.width/10000, hitbuffer.height/10000);
|
||||||
|
for(i in nodes) hitBufferNode(ctx, i, nodes[i].segs);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hitBufferNode(ctx, i, w){
|
||||||
|
var low = hexdigit(i&0xf);
|
||||||
|
var mid = hexdigit((i>>4)&0xf);
|
||||||
|
var high = hexdigit((i>>8)&0xf);
|
||||||
|
ctx.fillStyle = '#'+high+'F'+mid+'F'+low+'F';
|
||||||
|
for(i in w) {
|
||||||
|
drawSeg(ctx, w[i]);
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hexdigit(n){return '0123456789ABCDEF'.charAt(n);}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////
|
||||||
|
//
|
||||||
|
// Drawing Runtime
|
||||||
|
//
|
||||||
|
/////////////////////////
|
||||||
|
|
||||||
|
function refresh(){
|
||||||
|
ctx.clearRect(0,0,10000,10000);
|
||||||
|
for(i in nodes){
|
||||||
|
if(isNodeHigh(i)) overlayNode(nodes[i].segs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function overlayNode(w){
|
||||||
|
ctx.fillStyle = 'rgba(255,0,64,0.4)';
|
||||||
|
for(i in w) {
|
||||||
|
drawSeg(ctx, w[i]);
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hiliteNode(n){
|
||||||
|
var ctx = hilite.getContext('2d');
|
||||||
|
ctx.clearRect(0,0,10000,10000);
|
||||||
|
ctx.fillStyle = 'rgba(255,255,255,0.7)';
|
||||||
|
if(n==-1) return;
|
||||||
|
if(isNodeHigh(n[0]))
|
||||||
|
ctx.fillStyle = 'rgba(255,0,0,0.7)';
|
||||||
|
|
||||||
|
for(var i in n){
|
||||||
|
var segs = nodes[n[i]].segs;
|
||||||
|
for(var s in segs){drawSeg(ctx, segs[s]); ctx.fill();}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function drawSeg(ctx, seg){
|
||||||
|
var dx = 400;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(seg[0]+dx, 10000-seg[1])
|
||||||
|
for(var i=2;i<seg.length;i+=2) ctx.lineTo(seg[i]+dx, 10000-seg[i+1]);
|
||||||
|
ctx.lineTo(seg[0]+dx, 10000-seg[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////
|
||||||
|
//
|
||||||
|
// User Interface
|
||||||
|
//
|
||||||
|
/////////////////////////
|
||||||
|
|
||||||
|
function handleKey(e){
|
||||||
|
var c = e.charCode;
|
||||||
|
c = String.fromCharCode(c);
|
||||||
|
if('<>?np'.indexOf(c)==-1) return;
|
||||||
|
if(c=='<' && zoom>1) setZoom(zoom/1.2);
|
||||||
|
else if(c=='>' && zoom<16) setZoom(zoom*1.2);
|
||||||
|
else if(c=='?') setZoom(1);
|
||||||
|
else if(c=='n') stepForward();
|
||||||
|
else if(c=='p') stepBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseDown(e){
|
||||||
|
e.preventDefault();
|
||||||
|
moved=false;
|
||||||
|
dragMouseX = e.clientX;
|
||||||
|
dragMouseY = e.clientY;
|
||||||
|
window.onmousemove = function(e){mouseMove(e)};
|
||||||
|
window.onmouseup = function(e){mouseUp(e)};
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseMove(e){
|
||||||
|
moved = true;
|
||||||
|
if(zoom==1) return;
|
||||||
|
var dx = e.clientX-dragMouseX;
|
||||||
|
var dy = e.clientY-dragMouseY;
|
||||||
|
dragMouseX = e.clientX;
|
||||||
|
dragMouseY = e.clientY;
|
||||||
|
centerx-=dx/zoom;
|
||||||
|
centerx = Math.max(centerx, 400/zoom);
|
||||||
|
centerx = Math.min(centerx, 600-400/zoom);
|
||||||
|
centery-=dy/zoom;
|
||||||
|
centery = Math.max(centery, 300/zoom);
|
||||||
|
centery = Math.min(centery, 600-300/zoom);
|
||||||
|
recenter();
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseUp(e){
|
||||||
|
if(!moved) handleClick(e);
|
||||||
|
window.onmousemove = undefined;
|
||||||
|
window.onmouseup = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setZoom(n){
|
||||||
|
zoom = n;
|
||||||
|
setChipStyle({
|
||||||
|
width: 600*n+'px',
|
||||||
|
height: 600*n+'px'
|
||||||
|
});
|
||||||
|
recenter();
|
||||||
|
}
|
||||||
|
|
||||||
|
function recenter(){
|
||||||
|
var top = -centery*zoom+300;
|
||||||
|
top = Math.min(top, 0);
|
||||||
|
top = Math.max(top, -600*(zoom-1));
|
||||||
|
var left = -centerx*zoom+400;
|
||||||
|
left = Math.min(left, 0);
|
||||||
|
left = Math.max(left, (zoom==1)?100:-600*zoom+800);
|
||||||
|
setChipStyle({
|
||||||
|
top: top+'px',
|
||||||
|
left: left+'px',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClick(e){
|
||||||
|
var x = localx(hilite, e.clientX)/zoom;
|
||||||
|
var y = localy(hilite, e.clientY)/zoom;
|
||||||
|
var w = findNodeNumber(x,y);
|
||||||
|
if(e.shiftKey) hiliteNode(getNodeGroup(w));
|
||||||
|
else {var a=new Array(); a.push(w); hiliteNode(a);}
|
||||||
|
var cx = Math.round(x*10000/600);
|
||||||
|
var cy = Math.round(y*10000/600);
|
||||||
|
if(w==-1) setStatus('x:',cx,'<br>','y:',cy);
|
||||||
|
else {setStatus('x:',cx, 'y:', cy,'<br>','node:',w, nodeName(w));}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findNodeNumber(x,y){
|
||||||
|
var ctx = hitbuffer.getContext('2d');
|
||||||
|
var pixels = ctx.getImageData(x*4000/600, y*4000/600, 2, 2).data;
|
||||||
|
if(pixels[0]==0) return -1;
|
||||||
|
var high = pixels[0]>>4;
|
||||||
|
var mid = pixels[1]>>4;
|
||||||
|
var low = pixels[2]>>4;
|
||||||
|
return (high<<8)+(mid<<4)+low;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////
|
||||||
|
//
|
||||||
|
// Etc.
|
||||||
|
//
|
||||||
|
/////////////////////////
|
||||||
|
|
||||||
|
function setChipStyle(props){
|
||||||
|
for(var i in props){
|
||||||
|
chipbg.style[i] = props[i];
|
||||||
|
overlay.style[i] = props[i];
|
||||||
|
hilite.style[i] = props[i];
|
||||||
|
hitbuffer.style[i] = props[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function localx(el, gx){
|
||||||
|
var lx = gx+window.pageXOffset;
|
||||||
|
while(el.offsetLeft!=undefined){
|
||||||
|
lx-=el.offsetLeft+el.clientLeft;
|
||||||
|
el = el.parentNode;
|
||||||
|
}
|
||||||
|
return lx;
|
||||||
|
}
|
||||||
|
|
||||||
|
function localy(el, gy){
|
||||||
|
var ly = gy+window.pageYOffset;
|
||||||
|
while(el.offsetTop!=undefined){
|
||||||
|
ly-=el.offsetTop+el.clientTop;
|
||||||
|
el = el.parentNode;
|
||||||
|
}
|
||||||
|
return ly;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStatus(){
|
||||||
|
var res = '';
|
||||||
|
for(var i=0;i<arguments.length;i++) res=res+arguments[i]+' ';
|
||||||
|
statbox.innerHTML = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nodeName(n) {
|
||||||
|
for(var i in nodenames){
|
||||||
|
if(nodenames[i]==n) return i;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function now(){return new Date().getTime();}
|
Loading…
Reference in New Issue