mirror of
https://github.com/trebonian/visual6502.git
synced 2025-07-15 13:24:23 +00:00
Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
416cd57947 | ||
|
e5bd2a5296 | ||
|
f293f2f10b | ||
|
2ac9d92999 | ||
|
864b82d7b7 | ||
|
e4ccdcafcd | ||
|
9477ea64b4 | ||
|
7ef9dc4c43 | ||
|
efddb36049 | ||
|
ef88fdeb90 | ||
|
470080015d | ||
|
dccef54f2e | ||
|
18fbd2eb36 | ||
|
bc901566e3 | ||
|
6276d019d7 | ||
|
69ab63e406 | ||
|
d032580201 | ||
|
0ecb753ec6 | ||
|
e2e88cfae1 | ||
|
1fd86334f7 | ||
|
bf2108b9d6 | ||
|
2d2d0ef9b6 | ||
|
3398a6f181 | ||
|
b6d4ffda6a | ||
|
6dd7e9c24e | ||
|
51b4d8d7a0 | ||
|
e01093def5 | ||
|
27f085b743 | ||
|
d3223a9478 | ||
|
f8931fce49 | ||
|
b9cbe765b2 |
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
* text=auto
|
||||
*.js text
|
||||
*.css text
|
||||
*.html text
|
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# emacs-style backup files
|
||||
*~
|
||||
# patch detritus
|
||||
*.orig
|
||||
*.rej
|
10
README
10
README
@@ -0,0 +1,10 @@
|
||||
This is the javascript simulator from the visual5602.org project:
|
||||
www.visual6502.org/JSSim
|
||||
|
||||
It includes a general purpose transistor-level simulator, layout browser,
|
||||
and the data from a 6502 revD chip.
|
||||
|
||||
Note the various licenses and Copyright associated with each file.
|
||||
|
||||
Enjoy!
|
||||
- The Visual 6502 Team
|
||||
|
46
browsertrouble.html
Normal file
46
browsertrouble.html
Normal file
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<title>Visual 6502 in JavaScript</title>
|
||||
<style type="text/css">@import "wires.css";</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<span id="title"><a href="http://visual6502.org">The Visual 6502</a></span>
|
||||
<span id="plain">
|
||||
<br />
|
||||
<span id="title">Browser Trouble?</span>
|
||||
<br />
|
||||
<a href="http://www.visual6502.org/faq.html">FAQ</a>
|
||||
<a href="http://blog.visual6502.org">Blog</a>
|
||||
<a href="http://www.visual6502.org/links.html">Links</a> 
|
||||
<p>
|
||||
Our chip simulator makes heavy use of the latest version of HTML5 drawing technology.
|
||||
<p>
|
||||
It will only run on recent browsers and on a computer with sufficient memory (we recommend at least 2Gbytes.)
|
||||
<p>
|
||||
We've tested it on Chrome, Firefox, Safari and Opera. Unfortunately Internet Explorer isn't yet capable of running the graphics.
|
||||
<p>
|
||||
If you're using one of the above browsers and having trouble, please restart the browser.
|
||||
<p>
|
||||
If you have a problem report or you're able to help us with compatilibity, please get in touch - our contact details are on the main page.
|
||||
<p>
|
||||
In the meantime, here's a picture of what you're missing:
|
||||
<p>
|
||||
<a href="http://visual6502.org"><img src="images/jssim2.png" style="border:10px"></a>
|
||||
</span>
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
google_ad_client = "pub-9008420149077488";
|
||||
/* 728x90, created 9/22/10 */
|
||||
google_ad_slot = "4303982675";
|
||||
google_ad_width = 728;
|
||||
google_ad_height = 90;
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript"
|
||||
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
418
chipsim.js
418
chipsim.js
@@ -1,208 +1,210 @@
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
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;}
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
var ctrace = false;
|
||||
var noGraphics = false;
|
||||
var loglevel = 3;
|
||||
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();
|
||||
}
|
||||
if(ctrace) 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 && ctrace) 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;}
|
||||
|
BIN
images/jssim2.png
Executable file
BIN
images/jssim2.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 312 KiB |
134
index.html
134
index.html
@@ -1,36 +1,98 @@
|
||||
<!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>
|
||||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<title>Visual 6502 in JavaScript</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>
|
||||
|
||||
<script type="text/javascript">
|
||||
function handleOnload() {
|
||||
/MSIE (\d+\.\d+);/.test(navigator.appVersion);
|
||||
IEVersion=Number(RegExp.$1);
|
||||
if((navigator.appName == 'Microsoft Internet Explorer') && (IEVersion<9)){
|
||||
document.getElementById('browsertrouble').innerHTML=
|
||||
'<p>Sorry, '+navigator.appName+' not supported - showing you a picture instead!</p>';
|
||||
document.getElementById('frame').innerHTML='<a href="browsertrouble.html"><img src="images/jssim2.png" style="border:10px"></a>';
|
||||
}else{
|
||||
setTimeout(setup,200);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="handleOnload();">
|
||||
<br />
|
||||
<span id="title"><a href="http://visual6502.org">The Visual 6502</a></span>
|
||||
<span id="plain">
|
||||
<br />
|
||||
<a href="http://www.visual6502.org/faq.html">FAQ</a>
|
||||
<a href="http://blog.visual6502.org">Blog</a>
|
||||
<a href="http://www.visual6502.org/links.html">Links</a> 
|
||||
<br /><br />
|
||||
This simulator uses HTML5 features only found on the latest versions of browsers and needs
|
||||
lots of RAM. If you have trouble, please <a href="browsertrouble.html">check compatibility.</a>
|
||||
<br />
|
||||
<span id="browsertrouble"></span>
|
||||
<br />
|
||||
Hit '>' to zoom in, '<' to zoom out
|
||||
<br />
|
||||
Left-click and drag to scroll around
|
||||
<br />
|
||||
Enter your own program into the array of RAM
|
||||
<br />
|
||||
<br />
|
||||
</span>
|
||||
<div class="frame" id="frame">
|
||||
<div class="chip" id="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">
|
||||
<div style="position:relative; float:left;">
|
||||
<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>
|
||||
</div>
|
||||
<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>
|
||||
<p class="status" id="status">x: 0<br>y: 0</p>
|
||||
<table class="memtable" id="memtable"></table>
|
||||
</div>
|
||||
<div id="updateShow">
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
Source code is available on <a href="http://github.com/trebonian/visual6502">github visual6502</a>.
|
||||
Use the online <a href="http://www.6502asm.com/">emulator and assembler</a> from 6502asm.com
|
||||
and <a href="http://www.e-tradition.net/bytes/6502/disassembler.html">disassembler</a> from e-tradition.net
|
||||
<br />
|
||||
For in-depth 6502 investigation and some more advanced features, try our <a href="/stage/JSSim/index.html">Experimenter's (Beta) version</a>.
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
google_ad_client = "pub-9008420149077488";
|
||||
/* 728x90, created 9/22/10 */
|
||||
google_ad_slot = "4303982675";
|
||||
google_ad_width = 728;
|
||||
google_ad_height = 90;
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript"
|
||||
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
519
macros.js
519
macros.js
@@ -1,201 +1,318 @@
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
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)}
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
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, 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(){
|
||||
var start = now();
|
||||
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<18;i++){resetStep();}
|
||||
refresh();
|
||||
cycle = 0;
|
||||
trace = Array();
|
||||
chipStatus();
|
||||
if(ctrace)console.log('initChip done after', now()-start);
|
||||
}
|
||||
|
||||
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 resetStep(){
|
||||
var clk = isNodeHigh(nodenames['clk0']);
|
||||
if (clk) {setLow('clk0'); handleBusRead(); }
|
||||
else {setHigh('clk0'); handleBusWrite();}
|
||||
}
|
||||
|
||||
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 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 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){
|
||||
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;
|
||||
steps();
|
||||
}
|
||||
|
||||
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();
|
||||
setStatus('resetting 6502...');
|
||||
setTimeout(initChip,0);
|
||||
}
|
||||
|
||||
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 ab = readAddressBus();
|
||||
var machine1 =
|
||||
' halfcyc:' + cycle +
|
||||
' phi0:' + readBit('clk0') +
|
||||
' AB:' + hexWord(ab) +
|
||||
' D:' + hexByte(readDataBus()) +
|
||||
' RnW:' + readBit('rw');
|
||||
var machine2 =
|
||||
' PC:' + hexWord(readPC()) +
|
||||
' A:' + hexByte(readA()) +
|
||||
' 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 + "<br>Hz: " + estimatedHz().toFixed(1));
|
||||
if (loglevel>2 && ctrace) {
|
||||
console.log(machine1 + " " + machine2 + " " + machine3 + " " + machine4 + " " + machine5);
|
||||
}
|
||||
selectCell(ab);
|
||||
}
|
||||
|
||||
var prevHzTimeStamp=0;
|
||||
var prevHzCycleCount=0;
|
||||
var prevHzEstimate1=1;
|
||||
var prevHzEstimate2=1;
|
||||
var HzSamplingRate=10;
|
||||
function estimatedHz(){
|
||||
if(cycle%HzSamplingRate!=3)
|
||||
return prevHzEstimate1;
|
||||
var HzTimeStamp = now();
|
||||
var HzEstimate = (cycle-prevHzCycleCount+.01)/(HzTimeStamp-prevHzTimeStamp+.01);
|
||||
HzEstimate=HzEstimate*1000/2; // convert from phases per millisecond to Hz
|
||||
if(HzEstimate<5)
|
||||
HzSamplingRate=5; // quicker
|
||||
if(HzEstimate>10)
|
||||
HzSamplingRate=10; // smoother
|
||||
prevHzEstimate2=prevHzEstimate1;
|
||||
prevHzEstimate1=(HzEstimate+prevHzEstimate1+prevHzEstimate2)/3; // wrong way to average speeds
|
||||
prevHzTimeStamp=HzTimeStamp;
|
||||
prevHzCycleCount=cycle;
|
||||
return prevHzEstimate1
|
||||
}
|
||||
|
||||
|
||||
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)}
|
||||
|
178
memtable.js
178
memtable.js
@@ -1,89 +1,89 @@
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
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.childNodes[r].childNodes[c+1];
|
||||
return e;
|
||||
}
|
||||
|
689
nodenames.js
689
nodenames.js
@@ -1,117 +1,572 @@
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
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
|
||||
}
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman, Ed Spittles
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
var nodenames ={
|
||||
res: 159, // pads: reset
|
||||
rw: 1156, // pads: read not write
|
||||
db0: 1005, // pads: databus
|
||||
db1: 82,
|
||||
db3: 650,
|
||||
db2: 945,
|
||||
db5: 175,
|
||||
db4: 1393,
|
||||
db7: 1349,
|
||||
db6: 1591,
|
||||
ab0: 268, // pads: address bus
|
||||
ab1: 451,
|
||||
ab2: 1340,
|
||||
ab3: 211,
|
||||
ab4: 435,
|
||||
ab5: 736,
|
||||
ab6: 887,
|
||||
ab7: 1493,
|
||||
ab8: 230,
|
||||
ab9: 148,
|
||||
ab12: 1237,
|
||||
ab13: 349,
|
||||
ab10: 1443,
|
||||
ab11: 399,
|
||||
ab14: 672,
|
||||
ab15: 195,
|
||||
sync: 539, // pads
|
||||
so: 1672, // pads: set overflow
|
||||
clk0: 1171, // pads
|
||||
clk1out: 1163, // pads
|
||||
clk2out: 421, // pads
|
||||
rdy: 89, // pads: ready
|
||||
nmi: 1297, // pads: non maskable interrupt
|
||||
irq: 103, // pads
|
||||
vcc: 657, // pads
|
||||
vss: 558, // pads
|
||||
|
||||
a0: 737, // machine state: accumulator
|
||||
a1: 1234,
|
||||
a2: 978,
|
||||
a3: 162,
|
||||
a4: 727,
|
||||
a5: 858,
|
||||
a6: 1136,
|
||||
a7: 1653,
|
||||
y0: 64, // machine state: y index register
|
||||
y1: 1148,
|
||||
y2: 573,
|
||||
y3: 305,
|
||||
y4: 989,
|
||||
y5: 615,
|
||||
y6: 115,
|
||||
y7: 843,
|
||||
x0: 1216, // machine state: x index register
|
||||
x1: 98,
|
||||
x2: 1,
|
||||
x3: 1648,
|
||||
x4: 85,
|
||||
x5: 589,
|
||||
x6: 448,
|
||||
x7: 777,
|
||||
pcl0: 1139, // machine state: program counter low (first storage node)
|
||||
pcl1: 1022,
|
||||
pcl2: 655,
|
||||
pcl3: 1359,
|
||||
pcl4: 900,
|
||||
pcl5: 622,
|
||||
pcl6: 377,
|
||||
pcl7: 1611,
|
||||
pclp0: 526, // machine state: program counter low (pre-incremented?, second storage node)
|
||||
pclp1: 1102,
|
||||
pclp2: 1411,
|
||||
pclp3: 868,
|
||||
pclp4: 15,
|
||||
pclp5: 1326,
|
||||
pclp6: 993,
|
||||
pclp7: 536,
|
||||
pch0: 1670, // machine state: program counter high (first storage node)
|
||||
pch1: 292,
|
||||
pch2: 502,
|
||||
pch3: 584,
|
||||
pch4: 948,
|
||||
pch5: 49,
|
||||
pch6: 1551,
|
||||
pch7: 205,
|
||||
pchp0: 780, // machine state: program counter high (pre-incremented?, second storage node)
|
||||
pchp1: 126,
|
||||
pchp2: 114,
|
||||
pchp3: 1061,
|
||||
pchp4: 820,
|
||||
pchp5: 469,
|
||||
pchp6: 751,
|
||||
pchp7: 663,
|
||||
p0: 687, // machine state: status register
|
||||
p1: 1444,
|
||||
p2: 1421,
|
||||
p3: 439,
|
||||
p4: 1119, // there is no bit4 in the status register!
|
||||
p5: -1, // there is no bit5 in the status register!
|
||||
p6: 77,
|
||||
p7: 1370,
|
||||
s0: 1403, // machine state: stack pointer
|
||||
s1: 183,
|
||||
s2: 81,
|
||||
s3: 1532,
|
||||
s4: 1702,
|
||||
s5: 1098,
|
||||
s6: 1212,
|
||||
s7: 1435,
|
||||
ir0: 328, // internal state: instruction register
|
||||
ir1: 1626,
|
||||
ir2: 1384,
|
||||
ir3: 1576,
|
||||
ir4: 1112,
|
||||
ir5: 1329, // ir5 distinguishes branch set from branch clear
|
||||
ir6: 337,
|
||||
ir7: 1328,
|
||||
notir0: 194, // internal signal: instruction register inverted outputs
|
||||
notir1: 702,
|
||||
notir2: 1182,
|
||||
notir3: 1125,
|
||||
notir4: 26,
|
||||
notir5: 1394,
|
||||
notir6: 895,
|
||||
notir7: 1320,
|
||||
irline3: 996, // internal signal: PLA input - ir0 AND ir1
|
||||
clock1: 156, // internal state: timing control
|
||||
clock2: 1536, // internal state: timing control
|
||||
t2: 971, // internal state: timing control
|
||||
t3: 1567,
|
||||
t4: 690,
|
||||
t5: 909,
|
||||
nots0: 418, // datapath state: not stack pointer
|
||||
nots1: 1064,
|
||||
nots2: 752,
|
||||
nots3: 828,
|
||||
nots4: 1603,
|
||||
nots5: 601,
|
||||
nots6: 1029,
|
||||
nots7: 181,
|
||||
notidl0: 116, // datapath state: internal data latch (first storage node)
|
||||
notidl1: 576,
|
||||
notidl2: 1485,
|
||||
notidl3: 1284,
|
||||
notidl4: 1516,
|
||||
notidl5: 498,
|
||||
notidl6: 1537,
|
||||
notidl7: 529,
|
||||
idl0: 1597, // datapath signal: internal data latch (driven output)
|
||||
idl1: 870,
|
||||
idl2: 1066,
|
||||
idl3: 464,
|
||||
idl4: 1306,
|
||||
idl5: 240,
|
||||
idl6: 1116,
|
||||
idl7: 391,
|
||||
sb0: 54, // datapath bus: special bus
|
||||
sb1: 1150,
|
||||
sb2: 1287,
|
||||
sb3: 1188,
|
||||
sb4: 1405,
|
||||
sb5: 166,
|
||||
sb6: 1336,
|
||||
sb7: 1001,
|
||||
notalu0: 394, // datapath state: alu output storage node (inverse)
|
||||
notalu1: 697,
|
||||
notalu2: 276,
|
||||
notalu3: 495,
|
||||
notalu4: 1490,
|
||||
notalu5: 893,
|
||||
notalu6: 68,
|
||||
notalu7: 1123,
|
||||
alu0: 401, // datapath signal: ALU output
|
||||
alu1: 872,
|
||||
alu2: 1637,
|
||||
alu3: 1414,
|
||||
alu4: 606,
|
||||
alu5: 314,
|
||||
alu6: 331,
|
||||
alu7: 765,
|
||||
// datapath signal: decimally adjusted special bus
|
||||
dasb0: 54, // same node as sb0
|
||||
dasb1: 1009,
|
||||
dasb2: 450,
|
||||
dasb3: 1475,
|
||||
dasb4: 1405, // same node as sb4
|
||||
dasb5: 263,
|
||||
dasb6: 679,
|
||||
dasb7: 1494,
|
||||
adl0: 413, // internal state: address latch low
|
||||
adl1: 1282,
|
||||
adl2: 1242,
|
||||
adl3: 684,
|
||||
adl4: 1437,
|
||||
adl5: 1630,
|
||||
adl6: 121,
|
||||
adl7: 1299,
|
||||
adh0: 407, // internal state: address latch high
|
||||
adh1: 52,
|
||||
adh2: 1651,
|
||||
adh3: 315,
|
||||
adh4: 1160,
|
||||
adh5: 483,
|
||||
adh6: 13,
|
||||
adh7: 1539,
|
||||
idb0: 1108, // internal state: data buffer
|
||||
idb1: 991,
|
||||
idb2: 1473,
|
||||
idb3: 1302,
|
||||
idb4: 892,
|
||||
idb5: 1503,
|
||||
idb6: 833,
|
||||
idb7: 493,
|
||||
notdor0: 222, // internal state: data output register (storage node)
|
||||
notdor1: 527,
|
||||
notdor2: 1288,
|
||||
notdor3: 823,
|
||||
notdor4: 873,
|
||||
notdor5: 1266,
|
||||
notdor6: 1418,
|
||||
notdor7: 158,
|
||||
dor0: 97, // internal signal: data output register
|
||||
dor1: 746,
|
||||
dor2: 1634,
|
||||
dor3: 444,
|
||||
dor4: 1088,
|
||||
dor5: 1453,
|
||||
dor6: 1415,
|
||||
dor7: 63,
|
||||
pd0: 758, // internal state: predecode register
|
||||
pd1: 361,
|
||||
pd2: 955,
|
||||
pd3: 894,
|
||||
pd4: 369,
|
||||
pd5: 829,
|
||||
pd6: 1669,
|
||||
pd7: 1690,
|
||||
notRdy0: 248, // internal signal: global pipeline control
|
||||
Reset0: 67, // internal signal: retimed reset from pin
|
||||
C1x5Reset: 926, // retimed and pipelined reset in progress
|
||||
notRnWprepad: 187, // internal signal: to pad, yet to be inverted and retimed
|
||||
RnWstretched: 353, // internal signal: control datapad output drivers
|
||||
cp1: 710, // internal signal: clock phase 1
|
||||
cclk: 943, // unbonded pad: internal non-overlappying phi2
|
||||
fetch: 879, // internal signal
|
||||
clearIR: 1077, // internal signal
|
||||
D1x1: 827, // internal signal: interrupt handler related
|
||||
H1x1: 1042, // internal signal: drive status byte onto databus
|
||||
|
||||
// internal signal: pla outputs block 1 (west/left edge of die)
|
||||
// often 130 pla outputs are mentioned - we have 131 here
|
||||
pla0: 1601,
|
||||
pla1: 60,
|
||||
pla2: 1512,
|
||||
pla3: 382,
|
||||
pla4: 1173,
|
||||
pla5: 1233,
|
||||
|
||||
// internal signal: pla outputs block 2
|
||||
pla6: 258,
|
||||
pla7: 1562,
|
||||
pla8: 84,
|
||||
pla9: 1543,
|
||||
pla10: 76,
|
||||
pla11: 1658,
|
||||
pla12: 1540,
|
||||
pla13: 245,
|
||||
pla14: 985,
|
||||
pla15: 786,
|
||||
pla16: 1664,
|
||||
pla17: 682,
|
||||
pla18: 1482,
|
||||
pla19: 665,
|
||||
pla20: 286,
|
||||
|
||||
// internal signal: pla outputs block 3
|
||||
// not pla, feed through
|
||||
pla21: 271,
|
||||
pla22: 370,
|
||||
pla23: 552,
|
||||
pla24: 1612,
|
||||
pla25: 1487,
|
||||
pla26: 784,
|
||||
pla27: 244,
|
||||
pla28: 788,
|
||||
pla29: 1623,
|
||||
pla30: 764,
|
||||
pla31: 1057,
|
||||
pla32: 403,
|
||||
pla33: 204,
|
||||
pla34: 1273,
|
||||
pla35: 1582,
|
||||
pla36: 1031,
|
||||
|
||||
// internal signal: pla outputs block 4
|
||||
pla37: 804,
|
||||
pla38: 1311,
|
||||
pla39: 1428,
|
||||
pla40: 492,
|
||||
pla41: 1204,
|
||||
pla42: 58,
|
||||
pla43: 1520,
|
||||
pla44: 324,
|
||||
pla45: 1259,
|
||||
pla46: 342,
|
||||
pla47: 857,
|
||||
pla48: 712,
|
||||
pla49: 1337,
|
||||
pla50: 1355,
|
||||
pla51_T0SBC: 787, // 52:111XXXXX 1 0 T0SBC
|
||||
pla52_T0ADCSBC: 575, // 51:X11XXXXX 1 0 T0ADCSBC
|
||||
pla53: 1466,
|
||||
|
||||
// internal signal: pla outputs block 5
|
||||
pla54: 1381,
|
||||
pla55: 546,
|
||||
pla56: 776,
|
||||
pla57: 157,
|
||||
pla58: 257,
|
||||
pla59: 1243,
|
||||
pla60: 822,
|
||||
pla61: 1324,
|
||||
pla62: 179,
|
||||
pla63: 131,
|
||||
pla64: 1420,
|
||||
pla65: 1342,
|
||||
pla66: 4,
|
||||
pla67: 1396,
|
||||
pla68: 167,
|
||||
pla69: 303,
|
||||
pla70: 1504,
|
||||
pla71: 354,
|
||||
pla72: 1168,
|
||||
|
||||
// internal signal: pla outputs block 6
|
||||
pla73: 1721, // has extra non-pla input
|
||||
pla74: 1086,
|
||||
pla75: 1074,
|
||||
pla76: 1246,
|
||||
pla77: 487,
|
||||
pla78: 579,
|
||||
pla79: 145,
|
||||
pla80_T2BR: 1239, // T2BR, 83 for Balazs
|
||||
pla81: 285,
|
||||
// not pla, feed through
|
||||
// not pla, feed through
|
||||
pla82: 1524,
|
||||
pla83: 273, // has extra pulldown: pla97
|
||||
pla84: 0,
|
||||
pla85: 341,
|
||||
pla86: 120,
|
||||
pla87: 1478,
|
||||
pla88: 594,
|
||||
pla89: 1210,
|
||||
pla90: 677, // has extra pulldown: pla97
|
||||
|
||||
// internal signal: pla outputs block 7
|
||||
pla91: 461,
|
||||
pla92: 447,
|
||||
pla93: 660,
|
||||
pla94: 1557,
|
||||
pla95: 259,
|
||||
pla96: 1052,
|
||||
// gap
|
||||
pla97: 791, // feeds into pla83 and pla90 (no normal pla output)
|
||||
pla98: 517,
|
||||
pla99: 352,
|
||||
pla100: 750,
|
||||
pla101: 932,
|
||||
pla102: 1589,
|
||||
// gap
|
||||
pla103: 446,
|
||||
pla104: 528,
|
||||
|
||||
// internal signal: pla outputs block 8
|
||||
pla105: 309,
|
||||
pla106: 1430,
|
||||
pla107: 53,
|
||||
pla108: 691,
|
||||
pla109: 1292,
|
||||
// gap
|
||||
pla110: 1646,
|
||||
pla111: 1114,
|
||||
pla112: 904,
|
||||
pla113: 1155,
|
||||
pla114: 1476,
|
||||
pla115: 1226,
|
||||
pla116: 1569,
|
||||
pla117: 301,
|
||||
pla118: 950,
|
||||
pla119: 1665,
|
||||
|
||||
// internal signal: pla outputs block 9
|
||||
pla120: 1710,
|
||||
pla121: 1050, // feeds into pla130 (no normal pla output)
|
||||
pla122: 1419,
|
||||
pla123: 840,
|
||||
pla124: 607,
|
||||
pla125: 219,
|
||||
pla126: 1385,
|
||||
pla127: 281,
|
||||
pla128: 1174,
|
||||
pla129: 1164,
|
||||
pla130: 1006, // has extra pulldowns: pla121 and ir0
|
||||
|
||||
// internal signals: control signals
|
||||
nnT2BR: 967, // doubly inverted
|
||||
BRtaken: 1544,
|
||||
|
||||
// internal state: misc pipeline state clocked by cclk (phi2)
|
||||
pipeBRtaken: 832,
|
||||
pipeUNK01: 1530,
|
||||
pipeUNK02: 974,
|
||||
pipeUNK03: 1436,
|
||||
pipeUNK04: 99,
|
||||
pipeUNK05: 44,
|
||||
pipeUNK06: 443,
|
||||
pipeUNK07: 215,
|
||||
pipeUNK08: 338,
|
||||
pipeUNK09: 199,
|
||||
pipeUNK10: 215,
|
||||
pipeUNK11: 1011,
|
||||
pipeUNK12: 1283,
|
||||
pipeUNK13: 1442,
|
||||
pipeUNK14: 1607,
|
||||
pipeUNK15: 1577, // inverse of H1x1, write P onto idb (PHP, interrupt)
|
||||
pipeUNK16: 1051,
|
||||
pipeUNK17: 1078,
|
||||
pipeUNK18: 899,
|
||||
pipeUNK19: 832,
|
||||
pipeUNK20: 294,
|
||||
pipeUNK21: 1176,
|
||||
pipeUNK22: 561, // becomes dpc22
|
||||
pipeUNK23: 596,
|
||||
pipephi2Reset0: 449,
|
||||
pipephi2Reset0x: 1036, // a second copy of the same latch
|
||||
pipeUNK26: 1321,
|
||||
pipeUNK27: 73,
|
||||
pipeUNK28: 685,
|
||||
pipeUNK29: 1008,
|
||||
pipeUNK30: 1652,
|
||||
pipeUNK31: 614,
|
||||
pipeUNK32: 960,
|
||||
pipeUNK33: 848,
|
||||
pipeUNK34: 56,
|
||||
pipeUNK35: 1713,
|
||||
pipeUNK36: 729,
|
||||
pipeUNK37: 197,
|
||||
pipeUNK38: 1131,
|
||||
pipeUNK39: 151,
|
||||
pipeUNK40: 456,
|
||||
pipeUNK41: 1438,
|
||||
pipeUNK42: 1104,
|
||||
pipeUNK43: 554,
|
||||
|
||||
|
||||
|
||||
// internal state: vector address pulldown control
|
||||
pipeVectorA0: 357,
|
||||
pipeVectorA1: 170,
|
||||
pipeVectorA2: 45,
|
||||
|
||||
// internal state: datapath control drivers
|
||||
pipedpc28: 683,
|
||||
|
||||
// internal signals: alu internal (private) busses
|
||||
alua0: 1167,
|
||||
alua1: 1248,
|
||||
alua2: 1332,
|
||||
alua3: 1680,
|
||||
alua4: 1142,
|
||||
alua5: 530,
|
||||
alua6: 1627,
|
||||
alua7: 1522,
|
||||
alub0: 977,
|
||||
alub1: 1432,
|
||||
alub2: 704,
|
||||
alub3: 96,
|
||||
alub4: 1645,
|
||||
alub5: 1678,
|
||||
alub6: 235,
|
||||
alub7: 1535,
|
||||
|
||||
aluanorb0: 143,
|
||||
aluanandb0: 1628,
|
||||
aluaorb0: 693,
|
||||
notaluoutmux0: 957, // alu result latch input
|
||||
|
||||
aluanorb1: 155,
|
||||
aluanandb1: 841,
|
||||
aluaorb1: 1021,
|
||||
notaluoutmux1: 250, // alu result latch input
|
||||
|
||||
// internal signals: datapath control signals
|
||||
dpc0_YSB: 801, // drive sb from y
|
||||
dpc1_SBY: 325, // load y from sb
|
||||
dpc2_XSB: 1263, // drive sb from x
|
||||
dpc3_SBX: 1186, // load x from sb
|
||||
dpc4_SSB: 1700, // drive sb from stack pointer
|
||||
dpc5_SADL: 1468, // drive adl from stack pointer
|
||||
dpc6_SBS: 874, // load stack pointer from sb
|
||||
dpc7_SS: 654, // recirculate stack pointer
|
||||
dpc8_nDBADD: 1068, // alu b side: select not-idb input
|
||||
dpc9_DBADD: 859, // alu b side: select idb input
|
||||
|
||||
dpc10_ADLADD: 437, // alu b side: select adl input
|
||||
dpc11_SBADD: 549, // alu a side: select sb
|
||||
dpc12_0ADD: 984, // alu a side: select zero
|
||||
dpc13_ORS: 59, // alu op: a or b
|
||||
dpc14_SRS: 362, // alu op: logical right shift
|
||||
dpc15_ANDS: 574, // alu op: a and b
|
||||
dpc16_EORS: 1666, // alu op: a xor b (?)
|
||||
dpc17_SUMS: 921, // alu op: a plus b (?)
|
||||
alucin: 910, // alu carry in
|
||||
notalucin: 1165,
|
||||
dpc18_DAA: 1201, // decimal related
|
||||
dpc19_ADDSB7: 214, // alu to sb bit 7 only
|
||||
|
||||
dpc20_ADDSB06: 129, // alu to sb bits 6-0 only
|
||||
dpc21_ADDADL: 1015, // alu to adl
|
||||
alurawcout: 808, // alu raw carry out (no decimal adjust)
|
||||
alucout: 1146, // alu carry out (latched by phi2)
|
||||
notaluvout: 1308, // alu overflow out
|
||||
aluvout: 938, // alu overflow out (latched by phi2)
|
||||
dpc22_DSA: 725, // decimal related/SBC only
|
||||
dpc23_SBAC: 534, // (optionalls decimal-adjusted) sb to acc
|
||||
dpc24_ACSB: 1698, // acc to sb
|
||||
dpc25_SBDB: 1060, // sb pass-connects to idb
|
||||
dpc26_ACDB: 1331, // acc to idb
|
||||
dpc27_SBADH: 140, // sb pass-connects to adh
|
||||
dpc28_0ADH0: 229, // zero to adh0 bit0 only
|
||||
dpc29_0ADH17: 203, // zero to adh bits 7-1 only
|
||||
|
||||
dpc30_ADHPCH: 48, // load pch from adh
|
||||
dpc31_PCHPCH: 741, // load pch from pch incremented
|
||||
dpc32_PCHADH: 1235, // drive adh from pch incremented
|
||||
dpc33_PCHDB: 247, // drive idb from pch incremented
|
||||
dpc34_PCLC: 1704, // pch carry in and pcl FF detect?
|
||||
dpc35: 1334, // pcl 0x?F detect - half-carry
|
||||
dpc36_IPC: 379, // pcl carry in
|
||||
dpc37_PCLDB: 283, // drive idb from pcl incremented
|
||||
dpc38_PCLADL: 438, // drive adl from pcl incremented
|
||||
dpc39_PCLPCL: 898, // load pcl from pcl incremented
|
||||
|
||||
dpc40_ADLPCL: 414, // load pcl from adl
|
||||
dpc41: 1564, // pass-connect adl to mux node driven by idl
|
||||
dpc42: 41, // pass-connect adh to mux node driven by idl
|
||||
dpc43: 863, // pass-connect idb to mux node driven by idl
|
||||
}
|
||||
|
18
save.php
18
save.php
@@ -1,18 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
|
||||
?>
|
||||
|
16481
segdefs.js
16481
segdefs.js
File diff suppressed because it is too large
Load Diff
7035
transdefs.js
7035
transdefs.js
File diff suppressed because it is too large
Load Diff
160
wires.css
160
wires.css
@@ -1,68 +1,94 @@
|
||||
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;
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
body {
|
||||
background: white;
|
||||
color: black;
|
||||
/* font-family: cursive;*/
|
||||
font-family :Verdana, Arial, Helvetica, Sans-Serif;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
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{
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
img.navplay{
|
||||
position: relative;
|
||||
margin-right: 5px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
img.navstop{
|
||||
position: absolute;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
table.memtable {
|
||||
position: absolute;
|
||||
top: 78px;
|
||||
left: 820px;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
border-spacing: 0px;
|
||||
}
|
||||
|
||||
#title {
|
||||
font-size:30px;
|
||||
font-weight:bold;
|
||||
}
|
716
wires.js
716
wires.js
@@ -1,338 +1,378 @@
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
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();}
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
var frame, chipbg, overlay, hilite, hitbuffer, ctx;
|
||||
var centerx=300, centery=300;
|
||||
var zoom=1;
|
||||
var dragMouseX, dragMouseY, moved;
|
||||
var statbox;
|
||||
|
||||
// Some constants for the graphics presentation
|
||||
// the canvas is embedded in an 800x600 clipping div
|
||||
// which gives rise to some of the 300 and 400 values in the code
|
||||
// there are also some 600 values
|
||||
// the 6502D chip coords are in the box (216,179) to (8983,9807)
|
||||
// we have 4 canvases all the same size, now 2000 pixels square
|
||||
// chip background - the layout
|
||||
// overlay - a red/white transparency to show logic high or low
|
||||
// hilite - to show the selected polygon
|
||||
// hitbuffer - abusing color values to return which polygon is under a point
|
||||
// we no longer use a scaling transform - we now scale the chip data at
|
||||
// the point of drawing line segments
|
||||
// if the canvas is any smaller than chip coordinates there will be
|
||||
// rounding artifacts, and at high zoom there will be anti-aliasing on edges.
|
||||
var grMaxZoom=12;
|
||||
var grChipSize=10000;
|
||||
var grCanvasSize=2000;
|
||||
var grLineWidth=1;
|
||||
|
||||
// Index of layerNames corresponds to index into drawLayers
|
||||
var layernames = ['metal', 'switched diffusion', 'inputdiode', 'grounded diffusion', 'powered diffusion', 'polysilicon'];
|
||||
var colors = ['rgba(128,128,192,0.4)','#FFFF00','#FF00FF','#4DFF4D',
|
||||
'#FF4D4D','#801AC0','rgba(128,0,255,0.75)'];
|
||||
var drawlayers = [true, true, true, true, true, true];
|
||||
|
||||
var nodes = new Array();
|
||||
var transistors = {};
|
||||
|
||||
var ngnd = nodenames['vss'];
|
||||
var npwr = nodenames['vcc'];
|
||||
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// Drawing Setup
|
||||
//
|
||||
/////////////////////////
|
||||
|
||||
// try to present a meaningful page before starting expensive work
|
||||
function setup(){
|
||||
statbox = document.getElementById('status');
|
||||
setStatus('loading 6502...');
|
||||
setTimeout(setup_part2, 0);
|
||||
}
|
||||
|
||||
function setup_part2(){
|
||||
frame = document.getElementById('frame');
|
||||
statbox = document.getElementById('status');
|
||||
setupNodes();
|
||||
setupTransistors();
|
||||
setupLayerVisibility();
|
||||
setupBackground();
|
||||
setupOverlay();
|
||||
setupHilite();
|
||||
setupHitBuffer();
|
||||
recenter();
|
||||
refresh();
|
||||
setupTable();
|
||||
window.onkeypress = function(e){handleKey(e);}
|
||||
hilite.onmousedown = function(e){mouseDown(e);}
|
||||
setStatus('resetting 6502...');
|
||||
setTimeout(setup_part3, 0);
|
||||
}
|
||||
|
||||
function setup_part3(){
|
||||
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 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(){
|
||||
chipbg = document.getElementById('chipbg');
|
||||
chipbg.width = grCanvasSize;
|
||||
chipbg.height = grCanvasSize;
|
||||
var ctx = chipbg.getContext('2d');
|
||||
ctx.fillStyle = '#000000';
|
||||
ctx.strokeStyle = 'rgba(255,255,255,0.5)';
|
||||
ctx.lineWidth = grLineWidth;
|
||||
ctx.fillRect(0,0,grCanvasSize,grCanvasSize);
|
||||
for(var i in segdefs){
|
||||
var seg = segdefs[i];
|
||||
var c = seg[2];
|
||||
if (drawlayers[c]) {
|
||||
ctx.fillStyle = colors[c];
|
||||
drawSeg(ctx, segdefs[i].slice(3));
|
||||
ctx.fill();
|
||||
if((c==0)||(c==6)) ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupOverlay(){
|
||||
overlay = document.getElementById('overlay');
|
||||
overlay.width = grCanvasSize;
|
||||
overlay.height = grCanvasSize;
|
||||
ctx = overlay.getContext('2d');
|
||||
}
|
||||
|
||||
function setupHilite(){
|
||||
hilite = document.getElementById('hilite');
|
||||
hilite.width = grCanvasSize;
|
||||
hilite.height = grCanvasSize;
|
||||
var ctx = hilite.getContext('2d');
|
||||
}
|
||||
|
||||
function setupHitBuffer(){
|
||||
hitbuffer = document.getElementById('hitbuffer');
|
||||
hitbuffer.width = grCanvasSize;
|
||||
hitbuffer.height = grCanvasSize;
|
||||
hitbuffer.style.visibility = 'hidden';
|
||||
var ctx = hitbuffer.getContext('2d');
|
||||
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,grCanvasSize,grCanvasSize);
|
||||
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,grCanvasSize,grCanvasSize);
|
||||
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){
|
||||
if(noGraphics) return;
|
||||
var dx = 400;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(grScale(seg[0]+dx), grScale(grChipSize-seg[1]));
|
||||
for(var i=2;i<seg.length;i+=2) ctx.lineTo(grScale(seg[i]+dx), grScale(grChipSize-seg[i+1]));
|
||||
ctx.lineTo(grScale(seg[0]+dx), grScale(grChipSize-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<grMaxZoom) 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*grChipSize/600);
|
||||
var cy = Math.round(y*grChipSize/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*grCanvasSize/600, y*grCanvasSize/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;
|
||||
}
|
||||
|
||||
function updateShow(layer, on){
|
||||
drawlayers[layer]=on;
|
||||
setupBackground();
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// 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];
|
||||
}
|
||||
}
|
||||
|
||||
// we draw the chip data scaled down to the canvas
|
||||
// and so avoid scaling a large canvas
|
||||
function grScale(x){
|
||||
return Math.round(x*grCanvasSize/grChipSize);
|
||||
}
|
||||
|
||||
function localx(el, gx){
|
||||
return gx-el.getBoundingClientRect().left;
|
||||
}
|
||||
|
||||
function localy(el, gy){
|
||||
return gy-el.getBoundingClientRect().top;
|
||||
}
|
||||
|
||||
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();}
|
||||
|
Reference in New Issue
Block a user