31 Commits
V0.0 ... V0.3

Author SHA1 Message Date
Barry Silverman
416cd57947 Backport various fixes from expert 2010-10-04 15:30:25 -04:00
Barry Silverman
e5bd2a5296 Removed save.php 2010-10-04 10:43:04 -04:00
BigEd
f293f2f10b [dev]fixup double-paste in previous commit 2010-09-22 21:34:00 +00:00
BigEd
2ac9d92999 [dev]add adsense to other jssim html page 2010-09-22 21:32:01 +00:00
BigEd
864b82d7b7 [bug]fixup IE version extraction 2010-09-22 20:38:52 +00:00
Barry Silverman
e4ccdcafcd github and google links 2010-09-22 07:34:14 -04:00
BigEd
9477ea64b4 allow IE9 (not tested on IE9, OK on firefox and chrome, IE8) 2010-09-20 13:09:15 +00:00
BigEd
7ef9dc4c43 detect IE, add page of browser trouble, static image 2010-09-20 12:37:15 +00:00
BigEd
efddb36049 remove page Offsets to fix probing in scrolled browser window 2010-09-19 18:27:48 +00:00
Barry Silverman
ef88fdeb90 Fixed console references for Firefox 2010-09-19 03:02:26 -04:00
Barry Silverman
470080015d Change title font and various wording changes from Greg 2010-09-18 19:59:41 -04:00
BigEd
dccef54f2e top link should be absolute 2010-09-18 19:37:50 +00:00
Barry Silverman
18fbd2eb36 Merge branch 'ed' 2010-09-18 14:14:05 -04:00
BigEd
bc901566e3 all layers start off visible 2010-09-18 18:06:42 +00:00
Barry Silverman
6276d019d7 Fixed localx/localy calculation 2010-09-18 14:04:52 -04:00
BigEd
69ab63e406 fixup space above memtable 2010-09-18 17:56:34 +00:00
BigEd
d032580201 improve load sequencing, add layer choosing, link to python sim, add keyboard tips, add example nmi test, tweak navbuttons, enhance chipstatus output 2010-09-18 17:46:24 +00:00
BigEd
0ecb753ec6 fixup nav button positioning 2010-09-18 17:29:45 +00:00
BigEd
e2e88cfae1 more internal busses and latches named 2010-09-18 17:25:33 +00:00
BigEd
1fd86334f7 fixup line ends on one remaining file (by touching every line...) 2010-09-18 17:12:28 +00:00
BigEd
bf2108b9d6 ignore patch detritus 2010-09-18 17:07:48 +00:00
BigEd
2d2d0ef9b6 Merge branch 'master' of git://github.com/trebonian/visual6502
Conflicts:

	segdefs.js
2010-09-18 17:06:09 +00:00
BigEd
3398a6f181 add copyright 2010-09-18 17:01:20 +00:00
Barry Silverman
b6d4ffda6a More copyrights 2010-09-18 13:00:23 -04:00
Barry Silverman
6dd7e9c24e Fixed line endings and Copyright notices 2010-09-18 12:56:48 -04:00
BigEd
51b4d8d7a0 Introduce end-of-line normalization 2010-09-18 16:38:22 +00:00
BigEd
e01093def5 ignore emacs backup files 2010-09-18 16:20:56 +00:00
BigEd
27f085b743 Merge branch 'master' of git://github.com/trebonian/visual6502 2010-09-18 16:17:54 +00:00
Barry Silverman
d3223a9478 Fixed README from Ed 2010-09-18 12:13:48 -04:00
BigEd
f8931fce49 initial README content 2010-09-18 15:59:17 +00:00
Barry Silverman
b9cbe765b2 Fix slow reset loop 2010-09-18 11:42:30 -04:00
15 changed files with 13592 additions and 12821 deletions

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
* text=auto
*.js text
*.css text
*.html text

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# emacs-style backup files
*~
# patch detritus
*.orig
*.rej

10
README
View File

@@ -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
View 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>&nbsp;
<a href="http://blog.visual6502.org">Blog</a>&nbsp;
<a href="http://www.visual6502.org/links.html">Links</a>&nbsp
<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>

View File

@@ -1,208 +1,210 @@
/* /*
Copyright (c) 2010 Brian Silverman, Barry Silverman Copyright (c) 2010 Brian Silverman, Barry Silverman
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
var ctrace = false; var ctrace = false;
var ridx = 0; var noGraphics = false;
var loglevel = 3;
function recalcNodeList(list){ var ridx = 0;
var n = list[0];
var recalclist = new Array(); function recalcNodeList(list){
for(var j=0;j<100;j++){ // loop limiter var n = list[0];
if(list.length==0) return; var recalclist = new Array();
if(ctrace) console.log(j, list); for(var j=0;j<100;j++){ // loop limiter
for(var i in list) recalcNode(list[i], recalclist); if(list.length==0) return;
list = recalclist; if(ctrace) console.log(j, list);
recalclist = new Array(); for(var i in list) recalcNode(list[i], recalclist);
} list = recalclist;
console.log(n,'looping...'); recalclist = new Array();
} }
if(ctrace) console.log(n,'looping...');
function recalcNode(node, recalclist){ }
if(node==ngnd) return;
if(node==npwr) return; function recalcNode(node, recalclist){
var group = getNodeGroup(node); if(node==ngnd) return;
var newv = getNodeValue(group); if(node==npwr) return;
if(ctrace) console.log('recalc', node, group); var group = getNodeGroup(node);
for(var i in group){ var newv = getNodeValue(group);
var n = nodes[group[i]]; if(ctrace) console.log('recalc', node, group);
if(n.state!=newv && ctrace) console.log(group[i], n.state, newv); for(var i in group){
n.state = newv; var n = nodes[group[i]];
for(var t in n.gates) recalcTransistor(n.gates[t], recalclist); 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); function recalcTransistor(tn, recalclist){
else turnTransistorOff(t, 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); function turnTransistorOn(t, recalclist){
t.on = true; if(t.on) return;
addRecalcNode(t.c1, recalclist); if(ctrace) console.log(t.name, 'on', t.gate, t.c1, t.c2);
addRecalcNode(t.c2, recalclist); 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); function turnTransistorOff(t, recalclist){
t.on = false; if(!t.on) return;
floatnode(t.c1); if(ctrace) console.log(t.name, 'off', t.gate, t.c1, t.c2);
floatnode(t.c2); t.on = false;
addRecalcNode(t.c1, recalclist); floatnode(t.c1);
addRecalcNode(t.c2, recalclist); floatnode(t.c2);
} addRecalcNode(t.c1, recalclist);
addRecalcNode(t.c2, recalclist);
function floatnode(nn){ }
if(nn==ngnd) return;
if(nn==npwr) return; function floatnode(nn){
var n = nodes[nn]; if(nn==ngnd) return;
if(n.state=='gnd') n.state = 'fl'; if(nn==npwr) return;
if(n.state=='pd') n.state = 'fl'; var n = nodes[nn];
if(n.state=='vcc') n.state = 'fh'; if(n.state=='gnd') n.state = 'fl';
if(n.state=='pu') n.state = 'fh'; if(n.state=='pd') n.state = 'fl';
if(ctrace) console.log('floating', nn, 'to', n.state); 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; function addRecalcNode(nn, recalclist){
if(arrayContains(recalclist, nn)) return; if(nn==ngnd) return;
recalclist.push(nn); if(nn==npwr) return;
// setAdd(recalclist, nn); if(arrayContains(recalclist, nn)) return;
} recalclist.push(nn);
// setAdd(recalclist, nn);
function getNodeGroup(i){ }
var group = new Array();
addNodeToGroup(i, group); function getNodeGroup(i){
return group; var group = new Array();
} addNodeToGroup(i, group);
return group;
function addNodeToGroup(i, group){ }
if(arrayContains(group, i)) return;
group.push(i); function addNodeToGroup(i, group){
if(i==ngnd) return; if(arrayContains(group, i)) return;
if(i==npwr) return; group.push(i);
for(var t in nodes[i].c1c2s) addNodeTransistor(i, nodes[i].c1c2s[t], group); 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; function addNodeTransistor(node, t, group){
var other; var tr = transistors[t];
if(tr.c1==node) other=tr.c2; if(!tr.on) return;
if(tr.c2==node) other=tr.c1; var other;
addNodeToGroup(other, group); 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'; function getNodeValue(group){
var flstate; if(arrayContains(group, ngnd)) return 'gnd';
for(var i in group){ if(arrayContains(group, npwr)) return 'vcc';
var nn = group[i]; var flstate;
var n = nodes[nn]; for(var i in group){
if(n.pullup) return 'pu'; var nn = group[i];
if(n.pulldown) return 'pd'; var n = nodes[nn];
if((n.state=='fl')&&(flstate==undefined)) flstate = 'fl'; if(n.pullup) return 'pu';
if(n.state=='fh') flstate = 'fh'; if(n.pulldown) return 'pd';
} if((n.state=='fl')&&(flstate==undefined)) flstate = 'fl';
if(flstate==undefined) console.log(group); if(n.state=='fh') flstate = 'fh';
return flstate; }
} if(flstate==undefined && ctrace) console.log(group);
return flstate;
}
function isNodeHigh(nn){
return arrayContains(['vcc','pu','fh'], nodes[nn].state);
} function isNodeHigh(nn){
return arrayContains(['vcc','pu','fh'], nodes[nn].state);
function saveString(name, str){ }
var request = new XMLHttpRequest();
request.onreadystatechange=function(){}; function saveString(name, str){
request.open('PUT', 'save.php?name='+name, true); var request = new XMLHttpRequest();
request.setRequestHeader('Content-Type', 'text/plain'); request.onreadystatechange=function(){};
request.send(str); 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); function allNodes(){
return res; 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 = ''; function stateString(){
for(var i=0;i<1725;i++){ var codes = {gnd: 'g', vcc: 'v', pu: 'p', pd: 'd', fh: 'f', fl: 'l'};
var n = nodes[i]; var res = '';
if(n==undefined) res+='x'; for(var i=0;i<1725;i++){
else if(i==ngnd) res+='g'; var n = nodes[i];
else if(i==npwr) res+='v'; if(n==undefined) res+='x';
else res+= codes[n.state]; else if(i==ngnd) res+='g';
} else if(i==npwr) res+='v';
return res; 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++){ function showState(str){
if(str[i]=='x') continue; var codes = {g: 'gnd', v: 'vcc', p: 'pu', d: 'pd', f: 'fh', l: 'fl'};
nodes[i].state = codes[str[i]]; for(var i=0;i<str.length;i++){
var gates = nodes[i].gates; if(str[i]=='x') continue;
for(var t in gates) transistors[gates[t]].on = isNodeHigh(i); nodes[i].state = codes[str[i]];
} var gates = nodes[i].gates;
refresh(); for(var t in gates) transistors[gates[t]].on = isNodeHigh(i);
} }
refresh();
}
function setPd(name){
var nn = nodenames[name];
nodes[nn].pullup = false; function setPd(name){
nodes[nn].pulldown = true; var nn = nodenames[name];
} nodes[nn].pullup = false;
nodes[nn].pulldown = true;
function setHigh(name){ }
var nn = nodenames[name];
nodes[nn].pullup = true; function setHigh(name){
nodes[nn].pulldown = false; var nn = nodenames[name];
recalcNodeList([nn]); nodes[nn].pullup = true;
} nodes[nn].pulldown = false;
recalcNodeList([nn]);
function setLow(name){ }
var nn = nodenames[name];
nodes[nn].pullup = false; function setLow(name){
nodes[nn].pulldown = true; var nn = nodenames[name];
recalcNodeList([nn]); nodes[nn].pullup = false;
} nodes[nn].pulldown = true;
recalcNodeList([nn]);
function setAdd(arr, el){ }
var idx = ridx%(arr.length+1);
ridx+=131; function setAdd(arr, el){
ridx%=123; var idx = ridx%(arr.length+1);
arr.splice(idx, 0, el); ridx+=131;
return arr; ridx%=123;
} arr.splice(idx, 0, el);
return arr;
function arrayContains(arr, el){return arr.indexOf(el)!=-1;} }
function arrayContains(arr, el){return arr.indexOf(el)!=-1;}

BIN
images/jssim2.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

View File

@@ -1,36 +1,98 @@
<!DOCTYPE html> <!DOCTYPE html>
<head> <head>
<title>6502</title> <title>Visual 6502 in JavaScript</title>
<style type="text/css">@import "wires.css";</style> <style type="text/css">@import "wires.css";</style>
<script src="segdefs.js"></script> <script src="segdefs.js"></script>
<script src="transdefs.js"></script> <script src="transdefs.js"></script>
<script src="nodenames.js"></script> <script src="nodenames.js"></script>
<script src="wires.js"></script> <script src="wires.js"></script>
<script src="chipsim.js"></script> <script src="chipsim.js"></script>
<script src="memtable.js"></script> <script src="memtable.js"></script>
<script src="macros.js"></script> <script src="macros.js"></script>
</head>
<script type="text/javascript">
<body onload="setup();"> function handleOnload() {
<p class="title">The 6502</p> /MSIE (\d+\.\d+);/.test(navigator.appVersion);
<div class="frame" id="frame"> IEVersion=Number(RegExp.$1);
<div class="chip"> if((navigator.appName == 'Microsoft Internet Explorer') && (IEVersion<9)){
<canvas class="chip" id="chipbg"></canvas> document.getElementById('browsertrouble').innerHTML=
<canvas class="chip" id="overlay"></canvas> '<p>Sorry, '+navigator.appName+' not supported - showing you a picture instead!</p>';
<canvas class="chip" id="hilite"></canvas> document.getElementById('frame').innerHTML='<a href="browsertrouble.html"><img src="images/jssim2.png" style="border:10px"></a>';
<canvas class="chip" id="hitbuffer"></canvas> }else{
</div> setTimeout(setup,200);
<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> </script>
<a href ="javascript:resetChip()"><img class="navbutton" src="images/up.png"></a>
<a href ="javascript:stepBack()"><img class="navbutton" src="images/prev.png"></a> </head>
<a href ="javascript:stepForward()"><img class="navbutton" src="images/next.png"></a>
</div> <body onload="handleOnload();">
<p class="status" id="status">x: 0<br>y: 0</p> <br />
<table class="memtable" id="memtable"></table> <span id="title"><a href="http://visual6502.org">The Visual 6502</a></span>
</div> <span id="plain">
</body> <br />
<a href="http://www.visual6502.org/faq.html">FAQ</a>&nbsp;
</html> <a href="http://blog.visual6502.org">Blog</a>&nbsp;
<a href="http://www.visual6502.org/links.html">Links</a>&nbsp
<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
View File

@@ -1,201 +1,318 @@
/* /*
Copyright (c) 2010 Brian Silverman, Barry Silverman Copyright (c) 2010 Brian Silverman, Barry Silverman
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
var memory = Array(); var memory = Array();
var code = [0xa9, 0x00, 0x20, 0x10, 0x00, 0x4c, 0x02, 0x00, var code = [0xa9, 0x00, 0x20, 0x10, 0x00, 0x4c, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe8, 0x88, 0xe6, 0x40, 0x38, 0x69, 0x02, 0x60]; 0xe8, 0x88, 0xe6, 0x40, 0x38, 0x69, 0x02, 0x60];
var cycle = 0; var cycle = 0;
var trace = Array(); var trace = Array();
var running = false; var running = false;
function go(n){ function go(n){
for(var i=0;i<code.length;i++){ for(var i=0;i<code.length;i++){
mWrite(i, code[i]); mWrite(i, code[i]);
setCellValue(i, code[i]); setCellValue(i, code[i]);
} }
mWrite(0xfffc, 0x00); mWrite(0xfffc, 0x00);
mWrite(0xfffd, 0x00); mWrite(0xfffd, 0x00);
steps(); steps();
} }
function steps(){ function steps(){
if(running) step(); if(running) {
setTimeout(steps, 200); step();
} setTimeout(steps, 0); // schedule the next poll
}
function initChip(){ }
for(var nn in nodes) nodes[nn].state = 'fl';
nodes[ngnd].state = 'gnd'; function testNMI(n){
nodes[npwr].state = 'vcc'; initChip();
for(var tn in transistors) transistors[tn].on = false;
setLow('res'); mWrite(0x0000, 0x38); // set carry
setLow('clk0'); mWrite(0x0001, 0x4c); // jump to test code
setHigh('rdy'); setLow('so'); mWrite(0x0002, 0x06);
setHigh('irq'); setHigh('nmi'); mWrite(0x0003, 0x23);
recalcNodeList(allNodes());
for(var i=0;i<8;i++){setHigh('clk0'), setLow('clk0');} mWrite(0x22ff, 0x38); // set carry
setHigh('res'); mWrite(0x2300, 0xea);
for(var i=0;i<14;i++){step();} mWrite(0x2301, 0xea);
refresh(); mWrite(0x2302, 0xea);
cycle = 0; mWrite(0x2303, 0xea);
trace = Array(); mWrite(0x2304, 0xb0); // branch carry set to self
chipStatus(); mWrite(0x2305, 0xfe);
}
mWrite(0x2306, 0xb0); // branch carry set to self
function step(){ mWrite(0x2307, 0x01);
trace[cycle]= {chip: stateString(), mem: getMem()}; mWrite(0x2308, 0x00); // brk should be skipped
halfStep(); mWrite(0x2309, 0xa9); // anything
cycle++; mWrite(0x230a, 0xde); // anything
chipStatus(); mWrite(0x230b, 0xb0); // branch back with page crossing
} mWrite(0x230c, 0xf2);
function halfStep(){ mWrite(0xc018, 0x40); // nmi handler
var clk = isNodeHigh(nodenames['clk0']);
if (clk) {setLow('clk0'); handleBusRead(); } mWrite(0xfffa, 0x18); // nmi vector
else {setHigh('clk0'); handleBusWrite();} mWrite(0xfffb, 0xc0);
refresh(); mWrite(0xfffc, 0x00); // reset vector
} mWrite(0xfffd, 0x00);
function handleBusRead(){ for(var i=0;i<n;i++){step();}
if(isNodeHigh(nodenames['rw'])) writeDataBus(mRead(readAddressBus())); setLow('nmi');
} chipStatus();
for(var i=0;i<8;i++){step();}
function handleBusWrite(){ setHigh('nmi');
if(!isNodeHigh(nodenames['rw'])){ chipStatus();
var a = readAddressBus(); for(var i=0;i<16;i++){step();}
var d = readDataBus(); }
mWrite(a,d);
if(a<0x200) setCellValue(a,d);
} function initChip(){
} var start = now();
for(var nn in nodes) nodes[nn].state = 'fl';
function readAddressBus(){return readBits('ab', 16);} nodes[ngnd].state = 'gnd';
function readDataBus(){return readBits('db', 8);} nodes[npwr].state = 'vcc';
function readA(){return readBits('a', 8);} for(var tn in transistors) transistors[tn].on = false;
function readY(){return readBits('y', 8);} setLow('res');
function readX(){return readBits('x', 8);} setLow('clk0');
function readP(){return readBits('p', 8);} setHigh('rdy'); setLow('so');
function readSP(){return readBits('s', 8);} setHigh('irq'); setHigh('nmi');
recalcNodeList(allNodes());
function readBits(name, n){ for(var i=0;i<8;i++){setHigh('clk0'), setLow('clk0');}
var res = 0; setHigh('res');
for(var i=0;i<n;i++){ for(var i=0;i<18;i++){resetStep();}
var nn = nodenames[name+i]; refresh();
res+=((isNodeHigh(nn))?1:0)<<i; cycle = 0;
} trace = Array();
return res; chipStatus();
} if(ctrace)console.log('initChip done after', now()-start);
}
function writeDataBus(x){
var recalcs = Array(); function step(){
for(var i=0;i<8;i++){ trace[cycle]= {chip: stateString(), mem: getMem()};
var nn = nodenames['db'+i]; halfStep();
var n = nodes[nn]; cycle++;
if((x%2)==0) {n.pulldown=true; n.pullup=false;} chipStatus();
else {n.pulldown=false; n.pullup=true;} }
recalcs.push(nn);
x>>=1; function halfStep(){
} var clk = isNodeHigh(nodenames['clk0']);
recalcNodeList(recalcs); if (clk) {setLow('clk0'); handleBusRead(); }
} else {setHigh('clk0'); handleBusWrite();}
refresh();
function mRead(a){ }
if(memory[a]==undefined) return 0;
else return memory[a]; function resetStep(){
} var clk = isNodeHigh(nodenames['clk0']);
if (clk) {setLow('clk0'); handleBusRead(); }
function mWrite(a, d){memory[a]=d;} else {setHigh('clk0'); handleBusWrite();}
}
function clkNodes(){ function handleBusRead(){
var res = Array(); if(isNodeHigh(nodenames['rw'])) writeDataBus(mRead(readAddressBus()));
res.push(943); }
for(var i in nodes[943].gates){
var t = transistors[nodes[943].gates[i]]; function handleBusWrite(){
if(t.c1==npwr) res.push(t.c2); if(!isNodeHigh(nodenames['rw'])){
if(t.c2==npwr) res.push(t.c1); var a = readAddressBus();
} var d = readDataBus();
hiliteNode(res); mWrite(a,d);
} if(a<0x200) setCellValue(a,d);
}
function runChip(){ }
var start = document.getElementById('start');
var stop = document.getElementById('stop'); function readAddressBus(){return readBits('ab', 16);}
start.style.visibility = 'hidden'; function readDataBus(){return readBits('db', 8);}
stop.style.visibility = 'visible'; function readA(){return readBits('a', 8);}
running = true; function readY(){return readBits('y', 8);}
} function readX(){return readBits('x', 8);}
function readP(){return readBits('p', 8);}
function stopChip(){ function readPstring(){
var start = document.getElementById('start'); var result;
var stop = document.getElementById('stop'); result = (isNodeHigh(nodenames['p7'])?'N':'n') +
start.style.visibility = 'visible'; (isNodeHigh(nodenames['p6'])?'V':'v') +
stop.style.visibility = 'hidden'; '-' +
running = false; (isNodeHigh(nodenames['p3'])?'B':'b') +
} (isNodeHigh(nodenames['p3'])?'D':'d') +
(isNodeHigh(nodenames['p2'])?'I':'i') +
function resetChip(){ (isNodeHigh(nodenames['p1'])?'Z':'z') +
stopChip(); (isNodeHigh(nodenames['p0'])?'C':'c');
initChip(); return result;
} }
function readSP(){return readBits('s', 8);}
function stepForward(){ function readPC(){return (readBits('pch', 8)<<8) + readBits('pcl', 8);}
stopChip(); function readPCL(){return readBits('pcl', 8);}
step(); function readPCH(){return readBits('pch', 8);}
}
function readBit(name){
function stepBack(){ return isNodeHigh(nodenames[name])?1:0;
if(cycle==0) return; }
showState(trace[--cycle].chip); function readBits(name, n){
setMem(trace[cycle].mem); var res = 0;
var clk = isNodeHigh(nodenames['clk0']); for(var i=0;i<n;i++){
if(!clk) writeDataBus(mRead(readAddressBus())); var nn = nodenames[name+i];
chipStatus(); res+=((isNodeHigh(nn))?1:0)<<i;
} }
return res;
function chipStatus(){ }
var pc = readAddressBus();
setStatus('PC:', hexWord(pc), function writeDataBus(x){
'D:', hexByte(readDataBus()), var recalcs = Array();
'SP:',hexByte(readSP()), for(var i=0;i<8;i++){
'cycle:', cycle, '<br>', var nn = nodenames['db'+i];
'A:', hexByte(readA()), var n = nodes[nn];
'X:', hexByte(readX()), if((x%2)==0) {n.pulldown=true; n.pullup=false;}
'Y:', hexByte(readY()), else {n.pulldown=false; n.pullup=true;}
'P:', hexByte(readP()) recalcs.push(nn);
); x>>=1;
selectCell(pc); }
} recalcNodeList(recalcs);
}
function getMem(){
var res = Array(); function mRead(a){
for(var i=0;i<0x200;i++) res.push(mRead(i)); if(memory[a]==undefined) return 0;
return res; else return memory[a];
} }
function setMem(arr){ function mWrite(a, d){memory[a]=d;}
for(var i=0;i<0x200;i++){mWrite(i, arr[i]); setCellValue(i, arr[i]);}
}
function clkNodes(){
function hexWord(n){return (0x10000+n).toString(16).substring(1)} var res = Array();
function hexByte(n){return (0x100+n).toString(16).substring(1)} 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)}

View File

@@ -1,89 +1,89 @@
/* /*
Copyright (c) 2010 Brian Silverman, Barry Silverman Copyright (c) 2010 Brian Silverman, Barry Silverman
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
var table; var table;
var selected; var selected;
function setupTable(){ function setupTable(){
table = document.getElementById('memtable'); table = document.getElementById('memtable');
for(var r=0;r<32;r++){ for(var r=0;r<32;r++){
var row = document.createElement('tr'); var row = document.createElement('tr');
table.appendChild(row); table.appendChild(row);
var col = document.createElement('td'); var col = document.createElement('td');
col.appendChild(document.createTextNode(hexWord(r*16)+':')); col.appendChild(document.createTextNode(hexWord(r*16)+':'));
col.onmousedown = unselectCell; col.onmousedown = unselectCell;
row.appendChild(col); row.appendChild(col);
for(var c=0;c<16;c++){ for(var c=0;c<16;c++){
col = document.createElement('td'); col = document.createElement('td');
col.addr = r*16+c; col.addr = r*16+c;
col.val = 0; col.val = 0;
col.onmousedown = function(e){handleCellClick(e);}; col.onmousedown = function(e){handleCellClick(e);};
col.appendChild(document.createTextNode('00')); col.appendChild(document.createTextNode('00'));
row.appendChild(col); row.appendChild(col);
} }
} }
} }
function handleCellClick(e){ function handleCellClick(e){
var c = e.target; var c = e.target;
selectCell(c.addr); selectCell(c.addr);
} }
function cellKeydown(e){ function cellKeydown(e){
var c = e.keyCode; var c = e.keyCode;
if(c==13) unselectCell(); if(c==13) unselectCell();
else if(c==32) selectCell((selected+1)%0x200); else if(c==32) selectCell((selected+1)%0x200);
else if(c==8) selectCell((selected+0x1ff)%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>=48)&&(c<58)) setCellValue(selected, getCellValue(selected)*16+c-48);
else if((c>=65)&&(c<71)) setCellValue(selected, getCellValue(selected)*16+c-55); else if((c>=65)&&(c<71)) setCellValue(selected, getCellValue(selected)*16+c-55);
mWrite(selected, getCellValue(selected)); mWrite(selected, getCellValue(selected));
} }
function setCellValue(n, val){ function setCellValue(n, val){
val%=256; val%=256;
cellEl(n).val=val; cellEl(n).val=val;
cellEl(n).innerHTML=hexByte(val); cellEl(n).innerHTML=hexByte(val);
} }
function getCellValue(n){return cellEl(n).val;} function getCellValue(n){return cellEl(n).val;}
function selectCell(n){ function selectCell(n){
unselectCell(); unselectCell();
if(n>=0x200) return; if(n>=0x200) return;
cellEl(n).style.background = '#ff8'; cellEl(n).style.background = '#ff8';
selected = n; selected = n;
window.onkeydown = function(e){cellKeydown(e);}; window.onkeydown = function(e){cellKeydown(e);};
} }
function unselectCell(){ function unselectCell(){
if(selected==undefined) return; if(selected==undefined) return;
cellEl(selected).style.background = '#fff'; cellEl(selected).style.background = '#fff';
selected = undefined; selected = undefined;
window.onkeydown = undefined; window.onkeydown = undefined;
} }
function cellEl(n){ function cellEl(n){
var r = n>>4; var r = n>>4;
var c = n%16; var c = n%16;
var e = table.children[r].children[c+1]; var e = table.childNodes[r].childNodes[c+1];
return e; return e;
} }

View File

@@ -1,117 +1,572 @@
/* /*
Copyright (c) 2010 Brian Silverman, Barry Silverman Copyright (c) 2010 Brian Silverman, Barry Silverman, Ed Spittles
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
var nodenames ={ var nodenames ={
db1: 82, res: 159, // pads: reset
db0: 1005, rw: 1156, // pads: read not write
db3: 650, db0: 1005, // pads: databus
db2: 945, db1: 82,
db5: 175, db3: 650,
db4: 1393, db2: 945,
db7: 1349, db5: 175,
db6: 1591, db4: 1393,
a1: 1234, db7: 1349,
ab1: 451, db6: 1591,
ab2: 1340, ab0: 268, // pads: address bus
a2: 978, ab1: 451,
s2: 81, ab2: 1340,
a5: 858, ab3: 211,
a4: 727, ab4: 435,
a7: 1653, ab5: 736,
a6: 1136, ab6: 887,
so: 1672, ab7: 1493,
sync: 539, ab8: 230,
vcc: 657, ab9: 148,
clk1out: 1163, ab12: 1237,
p2: 1421, ab13: 349,
p3: 439, ab10: 1443,
p0: 687, ab11: 399,
p1: 1444, ab14: 672,
p6: 77, ab15: 195,
p7: 1370, sync: 539, // pads
p4: 1119, so: 1672, // pads: set overflow
p5: 0, clk0: 1171, // pads
pcl3: 1359, clk1out: 1163, // pads
pcl2: 655, clk2out: 421, // pads
pcl1: 1022, rdy: 89, // pads: ready
pcl0: 1139, nmi: 1297, // pads: non maskable interrupt
pcl7: 1611, irq: 103, // pads
pcl6: 377, vcc: 657, // pads
pcl5: 622, vss: 558, // pads
pcl4: 900,
clk0: 1171, a0: 737, // machine state: accumulator
s3: 1532, a1: 1234,
res: 159, a2: 978,
s1: 183, a3: 162,
s0: 1403, a4: 727,
s7: 1435, a5: 858,
s6: 1212, a6: 1136,
s5: 1098, a7: 1653,
s4: 1702, y0: 64, // machine state: y index register
rw: 1156, y1: 1148,
x2: 1, y2: 573,
x3: 1648, y3: 305,
x0: 1216, y4: 989,
x1: 98, y5: 615,
x6: 448, y6: 115,
x7: 777, y7: 843,
x4: 85, x0: 1216, // machine state: x index register
x5: 589, x1: 98,
rdy: 89, x2: 1,
clk2out: 421, x3: 1648,
nmi: 1297, x4: 85,
ab12: 1237, x5: 589,
ab13: 349, x6: 448,
ab10: 1443, x7: 777,
ab11: 399, pcl0: 1139, // machine state: program counter low (first storage node)
ab14: 672, pcl1: 1022,
ab15: 195, pcl2: 655,
ab0: 268, pcl3: 1359,
a0: 737, pcl4: 900,
a3: 162, pcl5: 622,
ab3: 211, pcl6: 377,
ab4: 435, pcl7: 1611,
ab5: 736, pclp0: 526, // machine state: program counter low (pre-incremented?, second storage node)
ab6: 887, pclp1: 1102,
ab7: 1493, pclp2: 1411,
ab8: 230, pclp3: 868,
ab9: 148, pclp4: 15,
pch7: 205, pclp5: 1326,
pch6: 1551, pclp6: 993,
pch5: 49, pclp7: 536,
pch4: 948, pch0: 1670, // machine state: program counter high (first storage node)
pch3: 584, pch1: 292,
pch2: 502, pch2: 502,
pch1: 292, pch3: 584,
pch0: 1670, pch4: 948,
irq: 103, pch5: 49,
vss: 558, pch6: 1551,
y1: 1148, pch7: 205,
y0: 64, pchp0: 780, // machine state: program counter high (pre-incremented?, second storage node)
y3: 305, pchp1: 126,
y2: 573, pchp2: 114,
y5: 615, pchp3: 1061,
y4: 989, pchp4: 820,
y7: 843, pchp5: 469,
y6: 115, pchp6: 751,
cclk: 943 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
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

160
wires.css
View File

@@ -1,68 +1,94 @@
body { /*
background: white; Copyright (c) 2010 Brian Silverman, Barry Silverman
color: black;
font-family: cursive; Permission is hereby granted, free of charge, to any person obtaining a copy
font-size: 30px; 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
div.frame { copies of the Software, and to permit persons to whom the Software is
margin-left: 10px; furnished to do so, subject to the following conditions:
position: relative;
width: 1150px; The above copyright notice and this permission notice shall be included in
height: 600px; all copies or substantial portions of the Software.
}
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
div.chip { IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
background: lightgray; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
border: 2px solid gray; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
position: absolute; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
width: 800px; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
height: 600px; THE SOFTWARE.
overflow: hidden; */
}
body {
canvas.chip { background: white;
position: absolute; color: black;
width: 600px; /* font-family: cursive;*/
height: 600px; font-family :Verdana, Arial, Helvetica, Sans-Serif;
} font-size: 12px;
}
div.buttons{
position: absolute; div.frame {
top: -5px; margin-left: 10px;
left: 820px; position: relative;
} width: 1150px;
height: 600px;
p.status { }
position: absolute;
left: 820px; div.chip {
top: 20px; background: lightgray;
font-family: monospace; border: 2px solid gray;
font-size: 12px; position: absolute;
} width: 800px;
height: 600px;
img.navbutton{ overflow: hidden;
margin-left: -5px; }
border: 0px;
} canvas.chip {
position: absolute;
img.navplay{ width: 600px;
margin-left: -5px; height: 600px;
border: 0px; }
}
div.buttons{
img.navstop{ position: absolute;
position: absolute; top: -5px;
left: -5px; left: 820px;
top: 9px; }
border: 0px;
} p.status {
position: absolute;
table.memtable { left: 820px;
position: absolute; top: 20px;
top: 63px; font-family: monospace;
left: 820px; font-size: 12px;
font-family: monospace; }
font-size: 12px;
border-spacing: 0px; 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
View File

@@ -1,338 +1,378 @@
/* /*
Copyright (c) 2010 Brian Silverman, Barry Silverman Copyright (c) 2010 Brian Silverman, Barry Silverman
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
*/ */
var frame, chipbg, overlay, hilite, hitbuffer, ctx; var frame, chipbg, overlay, hilite, hitbuffer, ctx;
var centerx=300, centery=300; var centerx=300, centery=300;
var zoom=1; var zoom=1;
var dragMouseX, dragMouseY, moved; var dragMouseX, dragMouseY, moved;
var statbox; var statbox;
var colors = ['rgba(128,128,128,0.4)','#FFFF00','#FF00FF','#4DFF4D', // Some constants for the graphics presentation
'#FF4D4D','#801AC0','rgba(128,0,255,0.75)']; // the canvas is embedded in an 800x600 clipping div
// which gives rise to some of the 300 and 400 values in the code
var nodes = new Array(); // there are also some 600 values
var transistors = {}; // 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
var ngnd = nodenames['vss']; // chip background - the layout
var npwr = nodenames['vcc']; // 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
// Drawing Setup // 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;
function setup(){ var grCanvasSize=2000;
frame = document.getElementById('frame'); var grLineWidth=1;
statbox = document.getElementById('status');
setupNodes(); // Index of layerNames corresponds to index into drawLayers
setupTransistors(); var layernames = ['metal', 'switched diffusion', 'inputdiode', 'grounded diffusion', 'powered diffusion', 'polysilicon'];
setupBackground(); var colors = ['rgba(128,128,192,0.4)','#FFFF00','#FF00FF','#4DFF4D',
setupOverlay(); '#FF4D4D','#801AC0','rgba(128,0,255,0.75)'];
setupHilite(); var drawlayers = [true, true, true, true, true, true];
setupHitBuffer();
recenter(); var nodes = new Array();
refresh(); var transistors = {};
setupTable();
window.onkeypress = function(e){handleKey(e);} var ngnd = nodenames['vss'];
hilite.onmousedown = function(e){mouseDown(e);} var npwr = nodenames['vcc'];
initChip();
document.getElementById('stop').style.visibility = 'hidden';
go(); /////////////////////////
} //
// Drawing Setup
function setupNodes(){ //
for(var i in segdefs){ /////////////////////////
var seg = segdefs[i];
var w = seg[0]; // try to present a meaningful page before starting expensive work
if(nodes[w]==undefined) function setup(){
nodes[w] = {segs: new Array(), num: w, pullup: seg[1]=='+', statbox = document.getElementById('status');
state: 'fl', gates: new Array(), c1c2s: new Array()}; setStatus('loading 6502...');
if(w==ngnd) continue; setTimeout(setup_part2, 0);
if(w==npwr) continue; }
nodes[w].segs.push(seg.slice(3));
} function setup_part2(){
} frame = document.getElementById('frame');
statbox = document.getElementById('status');
function setupTransistors(){ setupNodes();
for(i in transdefs){ setupTransistors();
var tdef = transdefs[i]; setupLayerVisibility();
var name = tdef[0]; setupBackground();
var gate = tdef[1]; setupOverlay();
var c1 = tdef[2]; setupHilite();
var c2 = tdef[3]; setupHitBuffer();
var trans = {name: name, on: false, gate: gate, c1: c1, c2: c2}; recenter();
nodes[gate].gates.push(name); refresh();
nodes[c1].c1c2s.push(name); setupTable();
nodes[c2].c1c2s.push(name); window.onkeypress = function(e){handleKey(e);}
transistors[name] = trans; hilite.onmousedown = function(e){mouseDown(e);}
} setStatus('resetting 6502...');
} setTimeout(setup_part3, 0);
}
function setupBackground(){ function setup_part3(){
chipbg = document.getElementById('chipbg'); initChip();
chipbg.width = 4000; document.getElementById('stop').style.visibility = 'hidden';
chipbg.height = 4000; go();
var ctx = chipbg.getContext('2d'); }
ctx.scale(chipbg.width/10000, chipbg.height/10000);
ctx.fillStyle = '#000000'; function setupNodes(){
ctx.strokeStyle = 'rgba(255,255,255,0.5)'; for(var i in segdefs){
ctx.lineWidth = 4; var seg = segdefs[i];
ctx.fillRect(0,0,10000,10000); var w = seg[0];
var start = now(); if(nodes[w]==undefined)
for(var i in segdefs){ nodes[w] = {segs: new Array(), num: w, pullup: seg[1]=='+',
var seg = segdefs[i]; state: 'fl', gates: new Array(), c1c2s: new Array()};
var c = seg[2]; if(w==ngnd) continue;
ctx.fillStyle = colors[c]; if(w==npwr) continue;
drawSeg(ctx, segdefs[i].slice(3)); nodes[w].segs.push(seg.slice(3));
ctx.fill(); }
if((c==0)||(c==6)) ctx.stroke(); }
}
// console.log('time to draw: ', now() - start, ' ms'); function setupTransistors(){
} for(i in transdefs){
var tdef = transdefs[i];
function setupOverlay(){ var name = tdef[0];
overlay = document.getElementById('overlay'); var gate = tdef[1];
overlay.width = 4000; var c1 = tdef[2];
overlay.height = 4000; var c2 = tdef[3];
ctx = overlay.getContext('2d'); var trans = {name: name, on: false, gate: gate, c1: c1, c2: c2};
ctx.scale(overlay.width/10000, overlay.height/10000); nodes[gate].gates.push(name);
} nodes[c1].c1c2s.push(name);
nodes[c2].c1c2s.push(name);
function setupHilite(){ transistors[name] = trans;
hilite = document.getElementById('hilite'); }
hilite.width = 4000; }
hilite.height = 4000;
var ctx = hilite.getContext('2d'); function setupLayerVisibility(){
ctx.scale(hilite.width/10000, hilite.height/10000); var x=document.getElementById('updateShow');
} for (var i=0;i<x.childNodes.length;i++) {
if(x.childNodes[i].type='checkbox'){
function setupHitBuffer(){ x.childNodes[i].checked=drawlayers[x.childNodes[i].name];
hitbuffer = document.getElementById('hitbuffer'); }
hitbuffer.width = 4000; }
hitbuffer.height = 4000; }
hitbuffer.style.visibility = 'hidden';
var ctx = hitbuffer.getContext('2d'); function setupBackground(){
ctx.scale(hitbuffer.width/10000, hitbuffer.height/10000); chipbg = document.getElementById('chipbg');
for(i in nodes) hitBufferNode(ctx, i, nodes[i].segs); chipbg.width = grCanvasSize;
} chipbg.height = grCanvasSize;
var ctx = chipbg.getContext('2d');
function hitBufferNode(ctx, i, w){ ctx.fillStyle = '#000000';
var low = hexdigit(i&0xf); ctx.strokeStyle = 'rgba(255,255,255,0.5)';
var mid = hexdigit((i>>4)&0xf); ctx.lineWidth = grLineWidth;
var high = hexdigit((i>>8)&0xf); ctx.fillRect(0,0,grCanvasSize,grCanvasSize);
ctx.fillStyle = '#'+high+'F'+mid+'F'+low+'F'; for(var i in segdefs){
for(i in w) { var seg = segdefs[i];
drawSeg(ctx, w[i]); var c = seg[2];
ctx.fill(); if (drawlayers[c]) {
} ctx.fillStyle = colors[c];
} drawSeg(ctx, segdefs[i].slice(3));
ctx.fill();
function hexdigit(n){return '0123456789ABCDEF'.charAt(n);} if((c==0)||(c==6)) ctx.stroke();
}
}
///////////////////////// }
//
// Drawing Runtime function setupOverlay(){
// overlay = document.getElementById('overlay');
///////////////////////// overlay.width = grCanvasSize;
overlay.height = grCanvasSize;
function refresh(){ ctx = overlay.getContext('2d');
ctx.clearRect(0,0,10000,10000); }
for(i in nodes){
if(isNodeHigh(i)) overlayNode(nodes[i].segs); function setupHilite(){
} hilite = document.getElementById('hilite');
} hilite.width = grCanvasSize;
hilite.height = grCanvasSize;
function overlayNode(w){ var ctx = hilite.getContext('2d');
ctx.fillStyle = 'rgba(255,0,64,0.4)'; }
for(i in w) {
drawSeg(ctx, w[i]); function setupHitBuffer(){
ctx.fill(); hitbuffer = document.getElementById('hitbuffer');
} hitbuffer.width = grCanvasSize;
} hitbuffer.height = grCanvasSize;
hitbuffer.style.visibility = 'hidden';
function hiliteNode(n){ var ctx = hitbuffer.getContext('2d');
var ctx = hilite.getContext('2d'); for(i in nodes) hitBufferNode(ctx, i, nodes[i].segs);
ctx.clearRect(0,0,10000,10000); }
ctx.fillStyle = 'rgba(255,255,255,0.7)';
if(n==-1) return; function hitBufferNode(ctx, i, w){
if(isNodeHigh(n[0])) var low = hexdigit(i&0xf);
ctx.fillStyle = 'rgba(255,0,0,0.7)'; var mid = hexdigit((i>>4)&0xf);
var high = hexdigit((i>>8)&0xf);
for(var i in n){ ctx.fillStyle = '#'+high+'F'+mid+'F'+low+'F';
var segs = nodes[n[i]].segs; for(i in w) {
for(var s in segs){drawSeg(ctx, segs[s]); ctx.fill();} drawSeg(ctx, w[i]);
} ctx.fill();
} }
}
function drawSeg(ctx, seg){ function hexdigit(n){return '0123456789ABCDEF'.charAt(n);}
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]) // Drawing Runtime
} //
/////////////////////////
/////////////////////////
// function refresh(){
// User Interface ctx.clearRect(0,0,grCanvasSize,grCanvasSize);
// for(i in nodes){
///////////////////////// if(isNodeHigh(i)) overlayNode(nodes[i].segs);
}
function handleKey(e){ }
var c = e.charCode;
c = String.fromCharCode(c); function overlayNode(w){
if('<>?np'.indexOf(c)==-1) return; ctx.fillStyle = 'rgba(255,0,64,0.4)';
if(c=='<' && zoom>1) setZoom(zoom/1.2); for(i in w) {
else if(c=='>' && zoom<16) setZoom(zoom*1.2); drawSeg(ctx, w[i]);
else if(c=='?') setZoom(1); ctx.fill();
else if(c=='n') stepForward(); }
else if(c=='p') stepBack(); }
}
function hiliteNode(n){
function mouseDown(e){ var ctx = hilite.getContext('2d');
e.preventDefault(); ctx.clearRect(0,0,grCanvasSize,grCanvasSize);
moved=false; ctx.fillStyle = 'rgba(255,255,255,0.7)';
dragMouseX = e.clientX; if(n==-1) return;
dragMouseY = e.clientY; if(isNodeHigh(n[0]))
window.onmousemove = function(e){mouseMove(e)}; ctx.fillStyle = 'rgba(255,0,0,0.7)';
window.onmouseup = function(e){mouseUp(e)};
} for(var i in n){
var segs = nodes[n[i]].segs;
function mouseMove(e){ for(var s in segs){drawSeg(ctx, segs[s]); ctx.fill();}
moved = true; }
if(zoom==1) return; }
var dx = e.clientX-dragMouseX;
var dy = e.clientY-dragMouseY;
dragMouseX = e.clientX; function drawSeg(ctx, seg){
dragMouseY = e.clientY; if(noGraphics) return;
centerx-=dx/zoom; var dx = 400;
centerx = Math.max(centerx, 400/zoom); ctx.beginPath();
centerx = Math.min(centerx, 600-400/zoom); ctx.moveTo(grScale(seg[0]+dx), grScale(grChipSize-seg[1]));
centery-=dy/zoom; for(var i=2;i<seg.length;i+=2) ctx.lineTo(grScale(seg[i]+dx), grScale(grChipSize-seg[i+1]));
centery = Math.max(centery, 300/zoom); ctx.lineTo(grScale(seg[0]+dx), grScale(grChipSize-seg[1]));
centery = Math.min(centery, 600-300/zoom); }
recenter();
} /////////////////////////
//
function mouseUp(e){ // User Interface
if(!moved) handleClick(e); //
window.onmousemove = undefined; /////////////////////////
window.onmouseup = undefined;
} function handleKey(e){
var c = e.charCode;
function setZoom(n){ c = String.fromCharCode(c);
zoom = n; if('<>?np'.indexOf(c)==-1) return;
setChipStyle({ if(c=='<' && zoom>1) setZoom(zoom/1.2);
width: 600*n+'px', else if(c=='>' && zoom<grMaxZoom) setZoom(zoom*1.2);
height: 600*n+'px' else if(c=='?') setZoom(1);
}); else if(c=='n') stepForward();
recenter(); else if(c=='p') stepBack();
} }
function recenter(){ function mouseDown(e){
var top = -centery*zoom+300; e.preventDefault();
top = Math.min(top, 0); moved=false;
top = Math.max(top, -600*(zoom-1)); dragMouseX = e.clientX;
var left = -centerx*zoom+400; dragMouseY = e.clientY;
left = Math.min(left, 0); window.onmousemove = function(e){mouseMove(e)};
left = Math.max(left, (zoom==1)?100:-600*zoom+800); window.onmouseup = function(e){mouseUp(e)};
setChipStyle({ }
top: top+'px',
left: left+'px', function mouseMove(e){
}); moved = true;
} if(zoom==1) return;
var dx = e.clientX-dragMouseX;
function handleClick(e){ var dy = e.clientY-dragMouseY;
var x = localx(hilite, e.clientX)/zoom; dragMouseX = e.clientX;
var y = localy(hilite, e.clientY)/zoom; dragMouseY = e.clientY;
var w = findNodeNumber(x,y); centerx-=dx/zoom;
if(e.shiftKey) hiliteNode(getNodeGroup(w)); centerx = Math.max(centerx, 400/zoom);
else {var a=new Array(); a.push(w); hiliteNode(a);} centerx = Math.min(centerx, 600-400/zoom);
var cx = Math.round(x*10000/600); centery-=dy/zoom;
var cy = Math.round(y*10000/600); centery = Math.max(centery, 300/zoom);
if(w==-1) setStatus('x:',cx,'<br>','y:',cy); centery = Math.min(centery, 600-300/zoom);
else {setStatus('x:',cx, 'y:', cy,'<br>','node:',w, nodeName(w));} recenter();
} }
function findNodeNumber(x,y){ function mouseUp(e){
var ctx = hitbuffer.getContext('2d'); if(!moved) handleClick(e);
var pixels = ctx.getImageData(x*4000/600, y*4000/600, 2, 2).data; window.onmousemove = undefined;
if(pixels[0]==0) return -1; window.onmouseup = undefined;
var high = pixels[0]>>4; }
var mid = pixels[1]>>4;
var low = pixels[2]>>4; function setZoom(n){
return (high<<8)+(mid<<4)+low; zoom = n;
} setChipStyle({
width: 600*n+'px',
///////////////////////// height: 600*n+'px'
// });
// Etc. recenter();
// }
/////////////////////////
function recenter(){
function setChipStyle(props){ var top = -centery*zoom+300;
for(var i in props){ top = Math.min(top, 0);
chipbg.style[i] = props[i]; top = Math.max(top, -600*(zoom-1));
overlay.style[i] = props[i]; var left = -centerx*zoom+400;
hilite.style[i] = props[i]; left = Math.min(left, 0);
hitbuffer.style[i] = props[i]; left = Math.max(left, (zoom==1)?100:-600*zoom+800);
} setChipStyle({
} top: top+'px',
left: left+'px',
});
function localx(el, gx){ }
var lx = gx+window.pageXOffset;
while(el.offsetLeft!=undefined){ function handleClick(e){
lx-=el.offsetLeft+el.clientLeft; var x = localx(hilite, e.clientX)/zoom;
el = el.parentNode; var y = localy(hilite, e.clientY)/zoom;
} var w = findNodeNumber(x,y);
return lx; if(e.shiftKey) hiliteNode(getNodeGroup(w));
} else {var a=new Array(); a.push(w); hiliteNode(a);}
var cx = Math.round(x*grChipSize/600);
function localy(el, gy){ var cy = Math.round(y*grChipSize/600);
var ly = gy+window.pageYOffset; if(w==-1) setStatus('x:',cx,'<br>','y:',cy);
while(el.offsetTop!=undefined){ else {setStatus('x:',cx, 'y:', cy,'<br>','node:',w, nodeName(w));}
ly-=el.offsetTop+el.clientTop; }
el = el.parentNode;
} function findNodeNumber(x,y){
return ly; var ctx = hitbuffer.getContext('2d');
} var pixels = ctx.getImageData(x*grCanvasSize/600, y*grCanvasSize/600, 2, 2).data;
if(pixels[0]==0) return -1;
function setStatus(){ var high = pixels[0]>>4;
var res = ''; var mid = pixels[1]>>4;
for(var i=0;i<arguments.length;i++) res=res+arguments[i]+' '; var low = pixels[2]>>4;
statbox.innerHTML = res; return (high<<8)+(mid<<4)+low;
} }
function nodeName(n) { function updateShow(layer, on){
for(var i in nodenames){ drawlayers[layer]=on;
if(nodenames[i]==n) return i; setupBackground();
} }
return '';
} /////////////////////////
//
function now(){return new Date().getTime();} // 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();}