Compare commits
219 Commits
Author | SHA1 | Date | |
---|---|---|---|
b5c1759f32 | |||
6ceae74e4a | |||
94b306bace | |||
9308b26c42 | |||
335cb06832 | |||
d9440fa160 | |||
10ba01cf12 | |||
e8b964a24f | |||
bbfcf77134 | |||
73f21ffc47 | |||
4e2c84dabc | |||
ca7124b176 | |||
b0710a4cda | |||
baac06bdc3 | |||
9bb8caa025 | |||
b98010206e | |||
7049cef9b7 | |||
9d23382644 | |||
8f5f50d197 | |||
1d21f5ae8b | |||
15b25491b9 | |||
6033109dc6 | |||
0e41f0a9a9 | |||
cb29fb4fad | |||
c02d181d5c | |||
51d0e99389 | |||
d11cf44ae9 | |||
2e69d3a7c3 | |||
f098566335 | |||
e25ac6243c | |||
94e22becb4 | |||
a56ee40bd8 | |||
2ace0e8bad | |||
84b005673b | |||
09c578e361 | |||
167f93f836 | |||
c88e0749cf | |||
6db8836c5c | |||
27fb1d539e | |||
21c7a8ca90 | |||
cfb726d0e7 | |||
d352501c7c | |||
4eb1e4c848 | |||
c3f0d10199 | |||
4398fdaddf | |||
4f7930eef3 | |||
c04f37a3df | |||
fc664c7243 | |||
8bdb9a0682 | |||
ae30a57822 | |||
8a89310e96 | |||
1c66a8af28 | |||
78deb4aaa4 | |||
85c8447064 | |||
6cdbfc0c15 | |||
8ef98d131f | |||
e660736204 | |||
fc46e50289 | |||
4967b58e7f | |||
6f7dab7990 | |||
04196aa36a | |||
94a2b38d27 | |||
e052255c55 | |||
15453f4435 | |||
7572b25453 | |||
93252a0eb1 | |||
172394845a | |||
ec7da19d77 | |||
13e1f51b47 | |||
e6d3c62057 | |||
fbf0830d15 | |||
019bca0a26 | |||
e866a3b58e | |||
611490ad76 | |||
b3e58dcbab | |||
c7ac03edd8 | |||
b51b5c4398 | |||
8f2e296ef6 | |||
ee2fa1befd | |||
7c50999c9e | |||
398060f56b | |||
cdd837dd0c | |||
3df7065b83 | |||
f860067206 | |||
33f00022ca | |||
abf6daef7d | |||
8a6fe3634f | |||
296599890a | |||
580f4585a6 | |||
d045485ec4 | |||
71a85b3135 | |||
b3a6a12ddc | |||
5f472cbe10 | |||
6ced887613 | |||
3bf9ae1fac | |||
6be4dd1673 | |||
c4af64f5e8 | |||
7e6eb926ee | |||
6c899eda1a | |||
82daddcfe4 | |||
6c2217b8fa | |||
50ecadaa00 | |||
f6a86088f0 | |||
8a2342d83c | |||
5c9b4e7581 | |||
2a0e251088 | |||
60b4ecab22 | |||
d2a31398fd | |||
3804eace6e | |||
369a188ad9 | |||
9ff6ae027e | |||
678acd6dc5 | |||
758d53bf5b | |||
e885646e5e | |||
353e0a8f78 | |||
18e1946488 | |||
0c6a90a558 | |||
93e6d662df | |||
0842501bb7 | |||
294918789a | |||
cd05762f20 | |||
ef0bb5cdec | |||
25e8397a0f | |||
44b5c5e9d3 | |||
633a2693ac | |||
da7ec1f3e3 | |||
bed571f10c | |||
192d9a8ba8 | |||
b4747b0cad | |||
62b0b314d5 | |||
39959e711e | |||
0156a72ae7 | |||
759c188ef6 | |||
a406cee106 | |||
e3354a2aa4 | |||
68e022a2bd | |||
c4dcbcb435 | |||
bc8ef61fb9 | |||
86e544a065 | |||
ea9f54c398 | |||
dd95b40c6c | |||
3fcc3ee787 | |||
83af54a47d | |||
c9443e6718 | |||
e93c11ab20 | |||
0d0973b0c6 | |||
4b19e21e66 | |||
df6aaa392c | |||
5a4c574765 | |||
10787078c8 | |||
98ec727c50 | |||
33aa993c8d | |||
b5e1064efb | |||
282c815791 | |||
3258a24c91 | |||
66d42665a9 | |||
cede111a0f | |||
dc0fb1ef06 | |||
e60485fe6a | |||
9705ca4093 | |||
a83cb1533e | |||
971bbd03e3 | |||
0773a9e7cf | |||
ee196947e3 | |||
f439d8fc8d | |||
43f06031b0 | |||
c5e2bfd657 | |||
2cfceefacd | |||
67ad17122c | |||
c15e3ea5b5 | |||
6aec2c96f0 | |||
d6e516cafa | |||
2d20ef2dad | |||
5f24e86c3e | |||
5578726fd3 | |||
1843c17ce9 | |||
455949ceca | |||
f0536dc716 | |||
c8aabd6baa | |||
0b1af8d70e | |||
f3375f4c4b | |||
0892586d75 | |||
0ae95d5338 | |||
a2d20cc403 | |||
e72f11ee72 | |||
4b0316170b | |||
4849ad6ebc | |||
f26a508c4e | |||
d94116d257 | |||
b8d2872246 | |||
730312e594 | |||
46976519fe | |||
4ce8e4291f | |||
c03f3477bd | |||
f67125989c | |||
25f4594fdf | |||
f6f467787a | |||
2e9991c8ec | |||
b50da0d3ed | |||
653379e5d7 | |||
b3606c3b7f | |||
406c9731e8 | |||
40fe1e0a7a | |||
1f21f5283c | |||
b161368455 | |||
eaf55f1f31 | |||
11ab9bafce | |||
8fbcefc2e2 | |||
ea48dae543 | |||
f293f2f10b | |||
2ac9d92999 | |||
864b82d7b7 | |||
e4ccdcafcd | |||
9477ea64b4 | |||
7ef9dc4c43 | |||
efddb36049 | |||
ef88fdeb90 | |||
470080015d | |||
dccef54f2e |
BIN
3rdparty/img/hgrabber.gif
vendored
Normal file
After Width: | Height: | Size: 834 B |
BIN
3rdparty/img/vdockbar.gif
vendored
Normal file
After Width: | Height: | Size: 855 B |
BIN
3rdparty/img/vgrabber.gif
vendored
Normal file
After Width: | Height: | Size: 830 B |
BIN
3rdparty/img/vgrabber2-active.gif
vendored
Normal file
After Width: | Height: | Size: 840 B |
BIN
3rdparty/img/vgrabber2-normal.gif
vendored
Normal file
After Width: | Height: | Size: 843 B |
19
3rdparty/jquery-1.3.2.min.js
vendored
Normal file
92
3rdparty/jquery.cookie.js
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Cookie plugin
|
||||
*
|
||||
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a cookie with the given name and value and other optional parameters.
|
||||
*
|
||||
* @example $.cookie('the_cookie', 'the_value');
|
||||
* @desc Set the value of a cookie.
|
||||
* @example $.cookie('the_cookie', 'the_value', {expires: 7, path: '/', domain: 'jquery.com', secure: true});
|
||||
* @desc Create a cookie with all available options.
|
||||
* @example $.cookie('the_cookie', 'the_value');
|
||||
* @desc Create a session cookie.
|
||||
* @example $.cookie('the_cookie', null);
|
||||
* @desc Delete a cookie by passing null as value.
|
||||
*
|
||||
* @param String name The name of the cookie.
|
||||
* @param String value The value of the cookie.
|
||||
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
|
||||
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
|
||||
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
|
||||
* If set to null or omitted, the cookie will be a session cookie and will not be retained
|
||||
* when the the browser exits.
|
||||
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
|
||||
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
|
||||
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
|
||||
* require a secure protocol (like HTTPS).
|
||||
* @type undefined
|
||||
*
|
||||
* @name $.cookie
|
||||
* @cat Plugins/Cookie
|
||||
* @author Klaus Hartl/klaus.hartl@stilbuero.de
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the value of a cookie with the given name.
|
||||
*
|
||||
* @example $.cookie('the_cookie');
|
||||
* @desc Get the value of a cookie.
|
||||
*
|
||||
* @param String name The name of the cookie.
|
||||
* @return The value of the cookie.
|
||||
* @type String
|
||||
*
|
||||
* @name $.cookie
|
||||
* @cat Plugins/Cookie
|
||||
* @author Klaus Hartl/klaus.hartl@stilbuero.de
|
||||
*/
|
||||
jQuery.cookie = function(name, value, options) {
|
||||
if (typeof value != 'undefined') { // name and value given, set cookie
|
||||
options = options || {};
|
||||
if (value === null) {
|
||||
value = '';
|
||||
options.expires = -1;
|
||||
}
|
||||
var expires = '';
|
||||
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
|
||||
var date;
|
||||
if (typeof options.expires == 'number') {
|
||||
date = new Date();
|
||||
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
|
||||
} else {
|
||||
date = options.expires;
|
||||
}
|
||||
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
|
||||
}
|
||||
var path = options.path ? '; path=' + options.path : '';
|
||||
var domain = options.domain ? '; domain=' + options.domain : '';
|
||||
var secure = options.secure ? '; secure' : '';
|
||||
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
|
||||
} else { // only name given, get cookie
|
||||
var cookieValue = null;
|
||||
if (document.cookie && document.cookie != '') {
|
||||
var cookies = document.cookie.split(';');
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
var cookie = jQuery.trim(cookies[i]);
|
||||
// Does this cookie string begin with the name we want?
|
||||
if (cookie.substring(0, name.length + 1) == (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
};
|
213
3rdparty/splitter.js
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* jQuery.splitter.js - two-pane splitter window plugin
|
||||
*
|
||||
* version 1.51 (2009/01/09)
|
||||
*
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* The splitter() plugin implements a two-pane resizable splitter window.
|
||||
* The selected elements in the jQuery object are converted to a splitter;
|
||||
* each selected element should have two child elements, used for the panes
|
||||
* of the splitter. The plugin adds a third child element for the splitbar.
|
||||
*
|
||||
* For more details see: http://methvin.com/splitter/
|
||||
*
|
||||
*
|
||||
* @example $('#MySplitter').splitter();
|
||||
* @desc Create a vertical splitter with default settings
|
||||
*
|
||||
* @example $('#MySplitter').splitter({type: 'h', accessKey: 'M'});
|
||||
* @desc Create a horizontal splitter resizable via Alt+Shift+M
|
||||
*
|
||||
* @name splitter
|
||||
* @type jQuery
|
||||
* @param Object options Options for the splitter (not required)
|
||||
* @cat Plugins/Splitter
|
||||
* @return jQuery
|
||||
* @author Dave Methvin (dave.methvin@gmail.com)
|
||||
*/
|
||||
;(function($){
|
||||
|
||||
$.fn.splitter = function(args){
|
||||
args = args || {};
|
||||
return this.each(function() {
|
||||
var zombie; // left-behind splitbar for outline resizes
|
||||
function startSplitMouse(evt) {
|
||||
if ( opts.outline )
|
||||
zombie = zombie || bar.clone(false).insertAfter(A);
|
||||
panes.css("-webkit-user-select", "none"); // Safari selects A/B text on a move
|
||||
bar.addClass(opts.activeClass);
|
||||
A._posSplit = A[0][opts.pxSplit] - evt[opts.eventPos];
|
||||
$(document)
|
||||
.bind("mousemove", doSplitMouse)
|
||||
.bind("mouseup", endSplitMouse);
|
||||
}
|
||||
function doSplitMouse(evt) {
|
||||
var newPos = A._posSplit+evt[opts.eventPos];
|
||||
if ( opts.outline ) {
|
||||
newPos = Math.max(0, Math.min(newPos, splitter._DA - bar._DA));
|
||||
bar.css(opts.origin, newPos);
|
||||
} else
|
||||
resplit(newPos);
|
||||
}
|
||||
function endSplitMouse(evt) {
|
||||
bar.removeClass(opts.activeClass);
|
||||
var newPos = A._posSplit+evt[opts.eventPos];
|
||||
if ( opts.outline ) {
|
||||
zombie.remove(); zombie = null;
|
||||
resplit(newPos);
|
||||
}
|
||||
panes.css("-webkit-user-select", "text"); // let Safari select text again
|
||||
$(document)
|
||||
.unbind("mousemove", doSplitMouse)
|
||||
.unbind("mouseup", endSplitMouse);
|
||||
}
|
||||
function resplit(newPos) {
|
||||
// Constrain new splitbar position to fit pane size limits
|
||||
newPos = Math.max(A._min, splitter._DA - B._max,
|
||||
Math.min(newPos, A._max, splitter._DA - bar._DA - B._min));
|
||||
// Resize/position the two panes
|
||||
bar._DA = bar[0][opts.pxSplit]; // bar size may change during dock
|
||||
bar.css(opts.origin, newPos).css(opts.fixed, splitter._DF);
|
||||
A.css(opts.origin, 0).css(opts.split, newPos).css(opts.fixed, splitter._DF);
|
||||
B.css(opts.origin, newPos+bar._DA)
|
||||
.css(opts.split, splitter._DA-bar._DA-newPos).css(opts.fixed, splitter._DF);
|
||||
// IE fires resize for us; all others pay cash
|
||||
if ( !$.browser.msie )
|
||||
panes.trigger("resize");
|
||||
}
|
||||
function dimSum(jq, dims) {
|
||||
// Opera returns -1 for missing min/max width, turn into 0
|
||||
var sum = 0;
|
||||
for ( var i=1; i < arguments.length; i++ )
|
||||
sum += Math.max(parseInt(jq.css(arguments[i])) || 0, 0);
|
||||
return sum;
|
||||
}
|
||||
|
||||
// Determine settings based on incoming opts, element classes, and defaults
|
||||
var vh = (args.splitHorizontal? 'h' : args.splitVertical? 'v' : args.type) || 'v';
|
||||
var opts = $.extend({
|
||||
activeClass: 'active', // class name for active splitter
|
||||
pxPerKey: 8, // splitter px moved per keypress
|
||||
tabIndex: 0, // tab order indicator
|
||||
accessKey: '' // accessKey for splitbar
|
||||
},{
|
||||
v: { // Vertical splitters:
|
||||
keyLeft: 39, keyRight: 37, cursor: "e-resize",
|
||||
splitbarClass: "vsplitbar", outlineClass: "voutline",
|
||||
type: 'v', eventPos: "pageX", origin: "left",
|
||||
split: "width", pxSplit: "offsetWidth", side1: "Left", side2: "Right",
|
||||
fixed: "height", pxFixed: "offsetHeight", side3: "Top", side4: "Bottom"
|
||||
},
|
||||
h: { // Horizontal splitters:
|
||||
keyTop: 40, keyBottom: 38, cursor: "n-resize",
|
||||
splitbarClass: "hsplitbar", outlineClass: "houtline",
|
||||
type: 'h', eventPos: "pageY", origin: "top",
|
||||
split: "height", pxSplit: "offsetHeight", side1: "Top", side2: "Bottom",
|
||||
fixed: "width", pxFixed: "offsetWidth", side3: "Left", side4: "Right"
|
||||
}
|
||||
}[vh], args);
|
||||
|
||||
// Create jQuery object closures for splitter and both panes
|
||||
var splitter = $(this).css({position: "relative"});
|
||||
var panes = $(">*", splitter[0]).css({
|
||||
position: "absolute", // positioned inside splitter container
|
||||
"z-index": "1", // splitbar is positioned above
|
||||
"-moz-outline-style": "none" // don't show dotted outline
|
||||
});
|
||||
var A = $(panes[0]); // left or top
|
||||
var B = $(panes[1]); // right or bottom
|
||||
|
||||
// Focuser element, provides keyboard support; title is shown by Opera accessKeys
|
||||
var focuser = $('<a href="javascript:void(0)"></a>')
|
||||
.attr({accessKey: opts.accessKey, tabIndex: opts.tabIndex, title: opts.splitbarClass})
|
||||
.bind($.browser.opera?"click":"focus", function(){ this.focus(); bar.addClass(opts.activeClass) })
|
||||
.bind("keydown", function(e){
|
||||
var key = e.which || e.keyCode;
|
||||
var dir = key==opts["key"+opts.side1]? 1 : key==opts["key"+opts.side2]? -1 : 0;
|
||||
if ( dir )
|
||||
resplit(A[0][opts.pxSplit]+dir*opts.pxPerKey, false);
|
||||
})
|
||||
.bind("blur", function(){ bar.removeClass(opts.activeClass) });
|
||||
|
||||
// Splitbar element, can be already in the doc or we create one
|
||||
var bar = $(panes[2] || '<div></div>')
|
||||
.insertAfter(A).css("z-index", "100").append(focuser)
|
||||
.attr({"class": opts.splitbarClass, unselectable: "on"})
|
||||
.css({position: "absolute", "user-select": "none", "-webkit-user-select": "none",
|
||||
"-khtml-user-select": "none", "-moz-user-select": "none"})
|
||||
.bind("mousedown", startSplitMouse);
|
||||
// Use our cursor unless the style specifies a non-default cursor
|
||||
if ( /^(auto|default|)$/.test(bar.css("cursor")) )
|
||||
bar.css("cursor", opts.cursor);
|
||||
|
||||
// Cache several dimensions for speed, rather than re-querying constantly
|
||||
bar._DA = bar[0][opts.pxSplit];
|
||||
splitter._PBF = $.boxModel? dimSum(splitter, "border"+opts.side3+"Width", "border"+opts.side4+"Width") : 0;
|
||||
splitter._PBA = $.boxModel? dimSum(splitter, "border"+opts.side1+"Width", "border"+opts.side2+"Width") : 0;
|
||||
A._pane = opts.side1;
|
||||
B._pane = opts.side2;
|
||||
$.each([A,B], function(){
|
||||
this._min = opts["min"+this._pane] || dimSum(this, "min-"+opts.split);
|
||||
this._max = opts["max"+this._pane] || dimSum(this, "max-"+opts.split) || 9999;
|
||||
this._init = opts["size"+this._pane]===true ?
|
||||
parseInt($.curCSS(this[0],opts.split)) : opts["size"+this._pane];
|
||||
});
|
||||
|
||||
// Determine initial position, get from cookie if specified
|
||||
var initPos = A._init;
|
||||
if ( !isNaN(B._init) ) // recalc initial B size as an offset from the top or left side
|
||||
initPos = splitter[0][opts.pxSplit] - splitter._PBA - B._init - bar._DA;
|
||||
if ( opts.cookie ) {
|
||||
if ( !$.cookie )
|
||||
alert('jQuery.splitter(): jQuery cookie plugin required');
|
||||
var ckpos = parseInt($.cookie(opts.cookie));
|
||||
if ( !isNaN(ckpos) )
|
||||
initPos = ckpos;
|
||||
$(window).bind("unload", function(){
|
||||
var state = String(bar.css(opts.origin)); // current location of splitbar
|
||||
$.cookie(opts.cookie, state, {expires: opts.cookieExpires || 365,
|
||||
path: opts.cookiePath || document.location.pathname});
|
||||
});
|
||||
}
|
||||
if ( isNaN(initPos) ) // King Solomon's algorithm
|
||||
initPos = Math.round((splitter[0][opts.pxSplit] - splitter._PBA - bar._DA)/2);
|
||||
|
||||
// Resize event propagation and splitter sizing
|
||||
if ( opts.anchorToWindow ) {
|
||||
// Account for margin or border on the splitter container and enforce min height
|
||||
splitter._hadjust = dimSum(splitter, "borderTopWidth", "borderBottomWidth", "marginBottom");
|
||||
splitter._hmin = Math.max(dimSum(splitter, "minHeight"), 20);
|
||||
$(window).bind("resize", function(){
|
||||
var top = splitter.offset().top;
|
||||
var wh = $(window).height();
|
||||
splitter.css("height", Math.max(wh-top-splitter._hadjust, splitter._hmin)+"px");
|
||||
if ( !$.browser.msie ) splitter.trigger("resize");
|
||||
}).trigger("resize");
|
||||
}
|
||||
else if ( opts.resizeToWidth && !$.browser.msie )
|
||||
$(window).bind("resize", function(){
|
||||
splitter.trigger("resize");
|
||||
});
|
||||
|
||||
// Resize event handler; triggered immediately to set initial position
|
||||
splitter.bind("resize", function(e, size){
|
||||
// Custom events bubble in jQuery 1.3; don't Yo Dawg
|
||||
if ( e.target != this ) return;
|
||||
// Determine new width/height of splitter container
|
||||
splitter._DF = splitter[0][opts.pxFixed] - splitter._PBF;
|
||||
splitter._DA = splitter[0][opts.pxSplit] - splitter._PBA;
|
||||
// Bail if splitter isn't visible or content isn't there yet
|
||||
if ( splitter._DF <= 0 || splitter._DA <= 0 ) return;
|
||||
// Re-divvy the adjustable dimension; maintain size of the preferred pane
|
||||
resplit(!isNaN(size)? size : (!(opts.sizeRight||opts.sizeBottom)? A[0][opts.pxSplit] :
|
||||
splitter._DA-B[0][opts.pxSplit]-bar._DA));
|
||||
}).trigger("resize" , [initPos]);
|
||||
});
|
||||
};
|
||||
|
||||
})(jQuery);
|
12
README
@ -1,8 +1,12 @@
|
||||
This is the javascript simulator from the visual5602.org project.
|
||||
This is the javascript simulator from the visual5602.org project:
|
||||
www.visual6502.org/JSSim
|
||||
|
||||
It includes a general purpose switch-level simulator, layout browser,
|
||||
and data from a 6502D chip.
|
||||
It includes a general purpose transistor-level simulator, layout browser,
|
||||
and the data from a 6502 revD chip.
|
||||
|
||||
Please note the various licenses of the different files.
|
||||
Recently added: polygon data for the 6800 chip. The simulation is not yet working,
|
||||
|
||||
Note the various licenses and Copyright associated with each file.
|
||||
|
||||
Enjoy!
|
||||
- The Visual 6502 Team
|
||||
|
46
browsertrouble.html
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<title>Visual 6502 in JavaScript</title>
|
||||
<style type="text/css">@import "kiosk.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>
|
868
chip-6800/nodenames.js
Normal file
@ -0,0 +1,868 @@
|
||||
/*
|
||||
Copyright (c) 2011 Ijor, Segher Boessenkool, 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 ={
|
||||
gnd: 663, // pads: ground
|
||||
vcc: 31, // pads: power
|
||||
phi1: 1507, // pads: phase 1 clock input
|
||||
phi2: 1511, // pads: phase 2 clock input
|
||||
reset: 1461, // pads: reset
|
||||
db0: 686, // pads: data bus
|
||||
db1: 683,
|
||||
db2: 677,
|
||||
db3: 676,
|
||||
db4: 669,
|
||||
db5: 670,
|
||||
db6: 664,
|
||||
db7: 691,
|
||||
ab0: 1854, // pads: address bus
|
||||
ab1: 1857,
|
||||
ab2: 1855,
|
||||
ab3: 1858,
|
||||
ab4: 1856,
|
||||
ab5: 1859,
|
||||
ab6: 1860,
|
||||
ab7: 1865,
|
||||
ab8: 1861,
|
||||
ab9: 1863,
|
||||
ab10: 1862,
|
||||
ab11: 1864,
|
||||
ab12: 1948,
|
||||
ab13: 1946,
|
||||
ab14: 1949,
|
||||
ab15: 1947,
|
||||
irq: 1496, // input pads: interrupt request (active low)
|
||||
nmi: 1501, // pads: non maskable interrupt (active low)
|
||||
dbe: 1456, // pads: data bus enable
|
||||
halt: 1492, // pads: halt (active low)
|
||||
tsc: 1459, // pads: tristate control
|
||||
rw: 1965, // output pads: read / not write
|
||||
vma: 1971, // pads: valid memory address
|
||||
ba: 1964, // pads: bus available
|
||||
//
|
||||
|
||||
// internal state: Instruction Register
|
||||
ir0: 1301,
|
||||
ir1: 1285,
|
||||
ir2: 1286,
|
||||
ir3: 1287,
|
||||
ir4: 1288,
|
||||
ir5: 1289,
|
||||
ir6: 1274,
|
||||
ir7: 1277,
|
||||
|
||||
// internal control signals
|
||||
sync: 1528, // aka #decode_0
|
||||
|
||||
// many other internal busses registers and signals
|
||||
abh0: 267,
|
||||
abh1: 258,
|
||||
abh2: 266,
|
||||
abh3: 257,
|
||||
abh4: 265,
|
||||
abh5: 256,
|
||||
abh6: 259,
|
||||
abh7: 255,
|
||||
ablx0: 1683,
|
||||
ablx1: 1682,
|
||||
ablx2: 1689,
|
||||
ablx3: 1687,
|
||||
ablx4: 1694,
|
||||
ablx5: 1693,
|
||||
ablx6: 1698,
|
||||
ablx7: 1697,
|
||||
abl0: 1670,
|
||||
abl1: 1671,
|
||||
abl2: 1653,
|
||||
abl3: 1667,
|
||||
abl4: 1655,
|
||||
abl5: 1657,
|
||||
abl6: 1656,
|
||||
abl7: 1658,
|
||||
acca0: 1934,
|
||||
acca1: 1688,
|
||||
acca2: 1700,
|
||||
acca3: 1699,
|
||||
acca4: 1701,
|
||||
acca5: 1702,
|
||||
acca6: 1703,
|
||||
acca7: 1784,
|
||||
accb0: 1919,
|
||||
accb1: 1927,
|
||||
accb2: 1921,
|
||||
accb3: 1929,
|
||||
accb4: 1923,
|
||||
accb5: 1931,
|
||||
accb6: 1925,
|
||||
accb7: 1933,
|
||||
adda0: 1680,
|
||||
adda1: 1681,
|
||||
adda2: 1685,
|
||||
adda3: 1686,
|
||||
adda4: 1691,
|
||||
adda5: 1692,
|
||||
adda6: 1695,
|
||||
adda7: 1696,
|
||||
adda0in: 1938,
|
||||
adda1in: 1940,
|
||||
adda2in: 1939,
|
||||
adda3in: 1942,
|
||||
adda4in: 1941,
|
||||
adda5in: 1944,
|
||||
adda6in: 1943,
|
||||
adda7in: 1945,
|
||||
addb0: 569,
|
||||
addb1: 568,
|
||||
addb2: 561,
|
||||
addb3: 560,
|
||||
addb4: 553,
|
||||
addb5: 552,
|
||||
addb6: 545,
|
||||
addb7: 544,
|
||||
idb0: 610,
|
||||
idb1: 1593,
|
||||
idb2: 387,
|
||||
idb3: 386,
|
||||
idb4: 311,
|
||||
idb5: 310,
|
||||
idb6: 393,
|
||||
idb7: 1651,
|
||||
dbi0: 608,
|
||||
dbi1: 599,
|
||||
dbi2: 598,
|
||||
dbi3: 400,
|
||||
dbi4: 405,
|
||||
dbi5: 395,
|
||||
dbi6: 389,
|
||||
dbi7: 650,
|
||||
dbo0: 609,
|
||||
dbo1: 602,
|
||||
dbo2: 601,
|
||||
dbo3: 402,
|
||||
dbo4: 406,
|
||||
dbo5: 397,
|
||||
dbo6: 390,
|
||||
dbo7: 649,
|
||||
decode: 1225,
|
||||
i0: 1271, // pla word lines
|
||||
i1: 1269,
|
||||
i2: 1268,
|
||||
i3: 1267,
|
||||
i4: 1265,
|
||||
i5: 1264,
|
||||
i6: 1263,
|
||||
i7: 1261,
|
||||
inch0: 198,
|
||||
inch1: 199,
|
||||
inch2: 200,
|
||||
inch3: 201,
|
||||
inch4: 202,
|
||||
inch5: 203,
|
||||
inch6: 204,
|
||||
inch7: 205,
|
||||
incl0: 154,
|
||||
incl1: 143,
|
||||
incl2: 144,
|
||||
incl3: 147,
|
||||
incl4: 148,
|
||||
incl5: 151,
|
||||
incl6: 152,
|
||||
incl7: 156,
|
||||
ixh0: 1910,
|
||||
ixh1: 1914,
|
||||
ixh2: 1911,
|
||||
ixh3: 1915,
|
||||
ixh4: 1912,
|
||||
ixh5: 1916,
|
||||
ixh6: 1913,
|
||||
ixh7: 1917,
|
||||
ixl0: 1918,
|
||||
ixl1: 1926,
|
||||
ixl2: 1920,
|
||||
ixl3: 1928,
|
||||
ixl4: 1922,
|
||||
ixl5: 1930,
|
||||
ixl6: 1924,
|
||||
ixl7: 1932,
|
||||
ob: 1308,
|
||||
obl0: 27,
|
||||
obl1: 30,
|
||||
obl2: 28,
|
||||
obl3: 32,
|
||||
obl4: 29,
|
||||
obl5: 33,
|
||||
obl6: 1073,
|
||||
obl7: 35,
|
||||
pch0: 1878,
|
||||
pch1: 1882,
|
||||
pch2: 1879,
|
||||
pch3: 1883,
|
||||
pch4: 1880,
|
||||
pch5: 1884,
|
||||
pch6: 1881,
|
||||
pch7: 1885,
|
||||
pcl0: 1877,
|
||||
pcl1: 1873,
|
||||
pcl2: 1876,
|
||||
pcl3: 1872,
|
||||
pcl4: 1875,
|
||||
pcl5: 1871,
|
||||
pcl6: 1874,
|
||||
pcl7: 1870,
|
||||
res: 1512,
|
||||
sph0: 1909,
|
||||
sph1: 1908,
|
||||
sph2: 1907,
|
||||
sph3: 1906,
|
||||
sph4: 1905,
|
||||
sph5: 1904,
|
||||
sph6: 1903,
|
||||
sph7: 1902,
|
||||
spl0: 1894,
|
||||
spl1: 1898,
|
||||
spl2: 1895,
|
||||
spl3: 1899,
|
||||
spl4: 1896,
|
||||
spl5: 1900,
|
||||
spl6: 1897,
|
||||
spl7: 1901,
|
||||
sum0: 644,
|
||||
sum1: 643,
|
||||
sum2: 642,
|
||||
sum3: 641,
|
||||
sum4: 640,
|
||||
sum5: 639,
|
||||
sum6: 638,
|
||||
sum7: 412,
|
||||
sumab0: 564,
|
||||
sumab1: 566,
|
||||
sumab2: 556,
|
||||
sumab3: 558,
|
||||
sumab4: 548,
|
||||
sumab5: 550,
|
||||
sumab6: 541,
|
||||
sumab7: 543,
|
||||
tmp0: 1893,
|
||||
tmp1: 1892,
|
||||
tmp2: 1891,
|
||||
tmp3: 1890,
|
||||
tmp4: 1889,
|
||||
tmp5: 1888,
|
||||
tmp6: 1887,
|
||||
tmp7: 1886,
|
||||
enrwa: 1318,
|
||||
flagc: 1160,
|
||||
flagh: 785,
|
||||
flagi: 1007,
|
||||
flagn: 1005,
|
||||
flagv: 1124,
|
||||
flagz: 1026,
|
||||
qaddgen0: 593,
|
||||
acca0_1: 342,
|
||||
acca1_1: 350,
|
||||
acca2_1: 344,
|
||||
acca3_1: 352,
|
||||
acca4_1: 346,
|
||||
acca5_1: 354,
|
||||
acca6_1: 348,
|
||||
acca7_1: 356,
|
||||
accb0_1: 343,
|
||||
accb1_1: 351,
|
||||
accb2_1: 345,
|
||||
accb3_1: 353,
|
||||
accb4_1: 347,
|
||||
accb5_1: 355,
|
||||
accb6_1: 349,
|
||||
accb7_1: 357,
|
||||
ahd0_0: 237,
|
||||
ahd1_0: 240,
|
||||
ahd2_0: 236,
|
||||
ahd3_0: 239,
|
||||
ahd4_0: 235,
|
||||
ahd5_0: 238,
|
||||
ahd6_0: 234,
|
||||
ahd7_0: 252,
|
||||
ald0_0: 74,
|
||||
ald1_0: 71,
|
||||
ald2_0: 68,
|
||||
ald3_0: 65,
|
||||
ald4_0: 62,
|
||||
ald5_0: 34,
|
||||
ald6_0: 56,
|
||||
ald7_0: 53,
|
||||
ba_0: 1228,
|
||||
idb0_2: 521,
|
||||
idb1_2: 520,
|
||||
idb2_2: 517,
|
||||
idb3_2: 516,
|
||||
idb4_2: 513,
|
||||
idb5_2: 512,
|
||||
idb6_2: 509,
|
||||
idb7_2: 508,
|
||||
decode_1: 1304,
|
||||
halt_0: 1491,
|
||||
inchi0_0: 206,
|
||||
inchi1_0: 208,
|
||||
inchi2_0: 207,
|
||||
inchi4_0: 245,
|
||||
inchi5_0: 243,
|
||||
inchi6_0: 242,
|
||||
incli0_0: 89,
|
||||
incli1_0: 90,
|
||||
incli2_0: 88,
|
||||
incli4_0: 93,
|
||||
incli5_0: 91,
|
||||
incli6_0: 92,
|
||||
ir0_1: 1300,
|
||||
ir1_1: 1280,
|
||||
ir2_1: 1281,
|
||||
ir3_1: 1282,
|
||||
ir4_1: 1283,
|
||||
ir5_1: 1284,
|
||||
ir6_1: 1272,
|
||||
ir7_1: 1273,
|
||||
ixh0_1: 365,
|
||||
ixh1_1: 364,
|
||||
ixh2_1: 363,
|
||||
ixh3_1: 362,
|
||||
ixh4_1: 361,
|
||||
ixh5_1: 360,
|
||||
ixh6_1: 359,
|
||||
ixh7_1: 358,
|
||||
ixl0_1: 373,
|
||||
ixl1_1: 372,
|
||||
ixl2_1: 371,
|
||||
ixl3_1: 370,
|
||||
ixl4_1: 369,
|
||||
ixl5_1: 368,
|
||||
ixl6_1: 367,
|
||||
ixl7_1: 366,
|
||||
pch0_1: 197,
|
||||
pch1_1: 193,
|
||||
pch2_1: 196,
|
||||
pch3_1: 192,
|
||||
pch4_1: 195,
|
||||
pch5_1: 191,
|
||||
pch6_1: 194,
|
||||
pch7_1: 190,
|
||||
pcl0_1: 153,
|
||||
pcl1_1: 141,
|
||||
pcl2_1: 142,
|
||||
pcl3_1: 145,
|
||||
pcl4_1: 146,
|
||||
pcl5_1: 149,
|
||||
pcl6_1: 150,
|
||||
pcl7_1: 155,
|
||||
reset_0: 1462,
|
||||
sph0_1: 303,
|
||||
sph1_1: 302,
|
||||
sph2_1: 301,
|
||||
sph3_1: 300,
|
||||
sph4_1: 299,
|
||||
sph5_1: 298,
|
||||
sph6_1: 297,
|
||||
sph7_1: 296,
|
||||
spl0_1: 295,
|
||||
spl1_1: 294,
|
||||
spl2_1: 293,
|
||||
spl3_1: 292,
|
||||
spl4_1: 291,
|
||||
spl5_1: 290,
|
||||
spl6_1: 289,
|
||||
spl7_1: 288,
|
||||
tmp0_1: 284,
|
||||
tmp1_1: 283,
|
||||
tmp2_1: 282,
|
||||
tmp3_1: 281,
|
||||
tmp4_1: 280,
|
||||
tmp5_1: 279,
|
||||
tmp6_1: 278,
|
||||
tmp7_1: 254,
|
||||
vma_0: 1498,
|
||||
phi2_1: 478,
|
||||
"#abh0_0": 1070,
|
||||
"#abh0_1": 277,
|
||||
"#abh1_0": 818,
|
||||
"#abh1_1": 271,
|
||||
"#abh2_0": 810,
|
||||
"#abh2_1": 276,
|
||||
"#abh3_0": 812,
|
||||
"#abh3_1": 270,
|
||||
"#abh4_0": 816,
|
||||
"#abh4_1": 275,
|
||||
"#abh5_0": 808,
|
||||
"#abh5_1": 269,
|
||||
"#abh6_0": 814,
|
||||
"#abh6_1": 272,
|
||||
"#abh7_0": 572,
|
||||
"#abh7_1": 268,
|
||||
"#abl0_0": 76,
|
||||
"#abl10_0": 500,
|
||||
"#abl11_0": 501,
|
||||
"#abl12_0": 498,
|
||||
"#abl13_0": 499,
|
||||
"#abl14_0": 496,
|
||||
"#abl15_0": 497,
|
||||
"#abl16_0": 494,
|
||||
"#abl17_0": 495,
|
||||
"#abl1_0": 73,
|
||||
"#abl2_0": 70,
|
||||
"#abl3_0": 67,
|
||||
"#abl4_0": 64,
|
||||
"#abl5_0": 61,
|
||||
"#abl6_0": 58,
|
||||
"#abl7_0": 55,
|
||||
"#acca0_0": 1710,
|
||||
"#acca1_0": 1718,
|
||||
"#acca2_0": 1711,
|
||||
"#acca3_0": 1719,
|
||||
"#acca4_0": 1723,
|
||||
"#acca5_0": 1727,
|
||||
"#acca6_0": 1731,
|
||||
"#acca7_0": 1783,
|
||||
"#accb0_0": 1704,
|
||||
"#accb1_0": 1712,
|
||||
"#accb2_0": 1705,
|
||||
"#accb3_0": 1713,
|
||||
"#accb4_0": 1720,
|
||||
"#accb5_0": 1724,
|
||||
"#accb6_0": 1728,
|
||||
"#accb7_0": 1732,
|
||||
"#addb0_0": 492,
|
||||
"#addb1_0": 493,
|
||||
"#addb2_0": 502,
|
||||
"#addb3_0": 503,
|
||||
"#addb4_0": 504,
|
||||
"#addb5_0": 505,
|
||||
"#addb6_0": 522,
|
||||
"#addb7_0": 523,
|
||||
"#addc01": 591,
|
||||
"#addc12": 588,
|
||||
"#addc23": 587,
|
||||
"#addc45": 583,
|
||||
"#addc56": 580,
|
||||
"#addc67": 579,
|
||||
"#ahd0": 264,
|
||||
"#ahd1": 274,
|
||||
"#ahd2": 263,
|
||||
"#ahd3": 273,
|
||||
"#ahd4": 262,
|
||||
"#ahd5": 261,
|
||||
"#ahd6": 260,
|
||||
"#ahd7": 1780,
|
||||
"#ald0": 1672,
|
||||
"#ald1": 1673,
|
||||
"#ald2": 1654,
|
||||
"#ald3": 1668,
|
||||
"#ald4": 1659,
|
||||
"#ald5": 1661,
|
||||
"#ald6": 1660,
|
||||
"#ald7": 1662,
|
||||
"#ccr/db": 287,
|
||||
"#d0_0": 607,
|
||||
"#d1_0": 597,
|
||||
"#d2_0": 596,
|
||||
"#d3_0": 399,
|
||||
"#d4_0": 404,
|
||||
"#d5_0": 394,
|
||||
"#d6_0": 388,
|
||||
"#d7_0": 661,
|
||||
"#db0_0": 75,
|
||||
"#db0_1": 519,
|
||||
"#db1_0": 72,
|
||||
"#db1_1": 518,
|
||||
"#db2_0": 69,
|
||||
"#db2_1": 515,
|
||||
"#db3_0": 66,
|
||||
"#db3_1": 514,
|
||||
"#db4_0": 63,
|
||||
"#db4_1": 511,
|
||||
"#db5_0": 60,
|
||||
"#db5_1": 510,
|
||||
"#db6_0": 57,
|
||||
"#db6_1": 507,
|
||||
"#db7_0": 54,
|
||||
"#db7_1": 506,
|
||||
"#dbi0_0": 611,
|
||||
"#dbi1_0": 605,
|
||||
"#dbi2_0": 603,
|
||||
"#dbi3_0": 403,
|
||||
"#dbi4_0": 407,
|
||||
"#dbi5_0": 398,
|
||||
"#dbi6_0": 391,
|
||||
"#dbi7_0": 654,
|
||||
// "#decode_0": 1528, aka sync
|
||||
"#decode_2": 1259,
|
||||
"#i0": 1270,
|
||||
"#i1": 1197,
|
||||
"#i2": 1198,
|
||||
"#i3": 1266,
|
||||
"#i4": 1199,
|
||||
"#i5": 1200,
|
||||
"#i6": 1262,
|
||||
"#i7": 1260,
|
||||
"#inch0_0": 218,
|
||||
"#inch1_0": 214,
|
||||
"#inch2_0": 217,
|
||||
"#inch3_0": 213,
|
||||
"#inch4_0": 216,
|
||||
"#inch5_0": 212,
|
||||
"#inch6_0": 215,
|
||||
"#inch7_0": 211,
|
||||
"#inchc01": 1758,
|
||||
"#inchc12": 1759,
|
||||
"#inchc23": 1763,
|
||||
"#inchc34": 1764,
|
||||
"#inchc45": 1767,
|
||||
"#inchc56": 1768,
|
||||
"#inchc67": 1779,
|
||||
"#inchcin": 186,
|
||||
"#inchi0": 247,
|
||||
"#inchi1": 250,
|
||||
"#inchi2": 246,
|
||||
"#inchi3": 249,
|
||||
"#inchi4": 244,
|
||||
"#inchi5": 248,
|
||||
"#inchi6": 241,
|
||||
"#incho0": 225,
|
||||
"#incho1": 221,
|
||||
"#incho2": 224,
|
||||
"#incho3": 220,
|
||||
"#incho4": 223,
|
||||
"#incho5": 219,
|
||||
"#incho6": 222,
|
||||
"#incho7": 210,
|
||||
"#incl0_0": 119,
|
||||
"#incl1_0": 115,
|
||||
"#incl2_0": 118,
|
||||
"#incl3_0": 114,
|
||||
"#incl4_0": 117,
|
||||
"#incl5_0": 113,
|
||||
"#incl6_0": 116,
|
||||
"#incl7_0": 96,
|
||||
"#inclc01": 1675,
|
||||
"#inclc12": 1652,
|
||||
"#inclc23": 1676,
|
||||
"#inclc34": 1663,
|
||||
"#inclc45": 1665,
|
||||
"#inclc56": 1664,
|
||||
"#inclc67": 1666,
|
||||
"#inclcin": 1674,
|
||||
"#incli0": 50,
|
||||
"#incli1": 46,
|
||||
"#incli2": 49,
|
||||
"#incli3": 45,
|
||||
"#incli4": 48,
|
||||
"#incli5": 44,
|
||||
"#incli6": 47,
|
||||
"#incli7": 43,
|
||||
"#inclo0": 104,
|
||||
"#inclo1": 100,
|
||||
"#inclo2": 103,
|
||||
"#inclo3": 99,
|
||||
"#inclo4": 102,
|
||||
"#inclo5": 98,
|
||||
"#inclo6": 101,
|
||||
"#inclo7": 97,
|
||||
"#ir0_0": 1302,
|
||||
"#ir1_0": 1290,
|
||||
"#ir2_0": 1296,
|
||||
"#ir3_0": 1297,
|
||||
"#ir4_0": 1298,
|
||||
"#ir5_0": 1299,
|
||||
"#ir6_0": 1278,
|
||||
"#ir7_0": 1279,
|
||||
"#ixh0_0": 1706,
|
||||
"#ixh1_0": 1714,
|
||||
"#ixh2_0": 1707,
|
||||
"#ixh3_0": 1715,
|
||||
"#ixh4_0": 1721,
|
||||
"#ixh5_0": 1725,
|
||||
"#ixh6_0": 1729,
|
||||
"#ixh7_0": 1781,
|
||||
"#ixl0_0": 1708,
|
||||
"#ixl1_0": 1716,
|
||||
"#ixl2_0": 1709,
|
||||
"#ixl3_0": 1717,
|
||||
"#ixl4_0": 1722,
|
||||
"#ixl5_0": 1726,
|
||||
"#ixl6_0": 1730,
|
||||
"#ixl7_0": 1782,
|
||||
"#obh0": 1071,
|
||||
"#obh1": 819,
|
||||
"#obh2": 811,
|
||||
"#obh3": 813,
|
||||
"#obh4": 817,
|
||||
"#obh5": 809,
|
||||
"#obh6": 815,
|
||||
"#obh7": 574,
|
||||
"#pch0_0": 1760,
|
||||
"#pch1_0": 1757,
|
||||
"#pch2_0": 1761,
|
||||
"#pch3_0": 1762,
|
||||
"#pch4_0": 1765,
|
||||
"#pch5_0": 1766,
|
||||
"#pch6_0": 1769,
|
||||
"#pch7_0": 1778,
|
||||
"#pcl0_0": 1770,
|
||||
"#pcl1_0": 1775,
|
||||
"#pcl2_0": 1771,
|
||||
"#pcl3_0": 1776,
|
||||
"#pcl4_0": 1772,
|
||||
"#pcl5_0": 1777,
|
||||
"#pcl6_0": 1773,
|
||||
"#pcl7_0": 1774,
|
||||
"#reset_1": 1463,
|
||||
"#sph0_0": 1735,
|
||||
"#sph1_0": 1738,
|
||||
"#sph2_0": 1741,
|
||||
"#sph3_0": 1744,
|
||||
"#sph4_0": 1747,
|
||||
"#sph5_0": 1750,
|
||||
"#sph6_0": 1753,
|
||||
"#sph7_0": 1756,
|
||||
"#spl0_0": 1734,
|
||||
"#spl1_0": 1737,
|
||||
"#spl2_0": 1740,
|
||||
"#spl3_0": 1743,
|
||||
"#spl4_0": 1746,
|
||||
"#spl5_0": 1749,
|
||||
"#spl6_0": 1752,
|
||||
"#spl7_0": 1755,
|
||||
"#sum0_0": 616,
|
||||
"#sum1_0": 632,
|
||||
"#sum2_0": 615,
|
||||
"#sum3_0": 627,
|
||||
"#sum4_0": 614,
|
||||
"#sum5_0": 622,
|
||||
"#sum6_0": 613,
|
||||
"#sum7_0": 617,
|
||||
"#sumo0": 634,
|
||||
"#sumo1": 633,
|
||||
"#sumo2": 629,
|
||||
"#sumo3": 628,
|
||||
"#sumo4": 624,
|
||||
"#sumo5": 623,
|
||||
"#sumo6": 619,
|
||||
"#sumo7": 618,
|
||||
"#tmp0_0": 1733,
|
||||
"#tmp1_0": 1736,
|
||||
"#tmp2_0": 1739,
|
||||
"#tmp3_0": 1742,
|
||||
"#tmp4_0": 1745,
|
||||
"#tmp5_0": 1748,
|
||||
"#tmp6_0": 1751,
|
||||
"#tmp7_0": 1754,
|
||||
"#ena": 1646,
|
||||
"#enrw": 1168,
|
||||
"#flagc_0": 1129,
|
||||
"#flagcx": 1128,
|
||||
"#flagh_0": 787,
|
||||
"#flaghx": 781,
|
||||
"#flagi_0": 1576,
|
||||
"#flagix": 1006,
|
||||
"#flagn_0": 997,
|
||||
"#flagnx": 996,
|
||||
"#flagv_0": 1103,
|
||||
"#flagvx": 1566,
|
||||
"#flagz_0": 1579,
|
||||
"#flagzx": 1024,
|
||||
"#n0n-0": 1250,
|
||||
"#n0n-1": 1251,
|
||||
"#n0n-2": 1252,
|
||||
"#n0n-3": 1253,
|
||||
"#n0n-4": 1254,
|
||||
"#n0n-5": 1247,
|
||||
"#n0n-6": 1243,
|
||||
"#n0n-7": 1244,
|
||||
"#n0n.2-0": 1249,
|
||||
"#n0n.2-1": 1255,
|
||||
"#n0n.2-2": 1256,
|
||||
"#n0n.2-3": 1257,
|
||||
"#n0n.2-4": 1258,
|
||||
"#n0n.2-5": 1248,
|
||||
"#n0n.2-6": 1241,
|
||||
"#n0n.2-7": 1242,
|
||||
"#phi2_0": 477,
|
||||
"#phi2_2": 576,
|
||||
"#qand0": 571,
|
||||
"#x0/abh": 979,
|
||||
"#x0/abl1": 438,
|
||||
"#x0/db0": 127,
|
||||
"#x0/db1": 129,
|
||||
"#x0/db2": 132,
|
||||
"#xab/ix": 456,
|
||||
"#xab/sp": 167,
|
||||
"#xabl/abl1": 426,
|
||||
"#xabl/ald": 82,
|
||||
"#xacca/abl1": 428,
|
||||
"#xacca/db": 466,
|
||||
"#xaccb/abl1": 460,
|
||||
"#xaccb/db": 760,
|
||||
"#xda/adda": 434,
|
||||
"#xdb/acca": 464,
|
||||
"#xdb/accb": 430,
|
||||
"#xdb/adda": 436,
|
||||
"#xdb/ald": 84,
|
||||
"#xdb/ixh": 454,
|
||||
"#xdb/ixl": 458,
|
||||
"#xdb/sph": 739,
|
||||
"#xdb/spl": 445,
|
||||
"#xdb/tmp": 448,
|
||||
"#xinc/ab": 121,
|
||||
"#xinc/pc": 701,
|
||||
"#xixh/abh": 421,
|
||||
"#xixh/abl1": 757,
|
||||
"#xixh/db": 424,
|
||||
"#xixl/abl1": 462,
|
||||
"#xixl/db": 432,
|
||||
"#xpc/ab": 123,
|
||||
"#xpch/db": 157,
|
||||
"#xpcl/db": 125,
|
||||
"#xsp/ab": 745,
|
||||
"#xsph/db": 452,
|
||||
"#xspl/db": 738,
|
||||
"#xsr/adda": 468,
|
||||
"#xtmp/abh": 443,
|
||||
"#xtmp/db": 450,
|
||||
"#xndb/adda": 471,
|
||||
"0/abh": 181,
|
||||
"0/abl1": 316,
|
||||
"0/db0": 136,
|
||||
"0/db1": 135,
|
||||
"0/db2": 134,
|
||||
"a0-high": 13,
|
||||
"a0-low": 21,
|
||||
"a1-high": 16,
|
||||
"a1-low": 24,
|
||||
"a10-high": 803,
|
||||
"a10-low": 39,
|
||||
"a11-high": 804,
|
||||
"a11-low": 41,
|
||||
"a12-high": 806,
|
||||
"a12-low": 689,
|
||||
"a13-high": 802,
|
||||
"a13-low": 687,
|
||||
"a14-high": 805,
|
||||
"a14-low": 690,
|
||||
"a15-high": 801,
|
||||
"a15-low": 688,
|
||||
"a2-high": 14,
|
||||
"a2-low": 22,
|
||||
"a3-high": 17,
|
||||
"a3-low": 25,
|
||||
"a4-high": 15,
|
||||
"a4-low": 23,
|
||||
"a5-high": 18,
|
||||
"a5-low": 26,
|
||||
"a6-high": 19,
|
||||
"a6-low": 20,
|
||||
"a7-high": 37,
|
||||
"a7-low": 36,
|
||||
"a8-high": 1072,
|
||||
"a8-low": 38,
|
||||
"a9-high": 807,
|
||||
"a9-low": 40,
|
||||
"ab/ix": 329,
|
||||
"ab/ob": 1647,
|
||||
"ab/sp": 171,
|
||||
"abh/ahd": 176,
|
||||
"abl/abl1": 326,
|
||||
"abl/ald": 6,
|
||||
"acca/abl1": 325,
|
||||
"acca/db": 314,
|
||||
"accb/abl1": 318,
|
||||
"accb/db": 324,
|
||||
"ba-high": 1237,
|
||||
"ba-low": 1227,
|
||||
"d0-high": 681,
|
||||
"d0-low": 684,
|
||||
"d1-high": 682,
|
||||
"d1-low": 685,
|
||||
"d2-high": 674,
|
||||
"d2-low": 679,
|
||||
"d3-high": 675,
|
||||
"d3-low": 680,
|
||||
"d4-high": 666,
|
||||
"d4-low": 671,
|
||||
"d5-high": 667,
|
||||
"d5-low": 672,
|
||||
"d6-high": 662,
|
||||
"d6-low": 665,
|
||||
"d7-high": 653,
|
||||
"d7-low": 652,
|
||||
"da/adda": 418,
|
||||
"db/acca": 315,
|
||||
"db/accb": 323,
|
||||
"db/adda": 417,
|
||||
"db/ald": 7,
|
||||
"db/ixh": 285,
|
||||
"db/ixl": 320,
|
||||
"db/sph": 180,
|
||||
"db/spl": 177,
|
||||
"db/tmp": 174,
|
||||
"dbi0-fb": 612,
|
||||
"dbi1-fb": 600,
|
||||
"dbi2-fb": 606,
|
||||
"dbi3-fb": 401,
|
||||
"dbi4-fb": 408,
|
||||
"dbi5-fb": 396,
|
||||
"dbi6-fb": 392,
|
||||
"dbi7-fb": 651,
|
||||
"inc/ab": 140,
|
||||
"inc/pc": 138,
|
||||
"ixh/abh": 327,
|
||||
"ixh/abl1": 319,
|
||||
"ixh/db": 328,
|
||||
"ixl/abl1": 317,
|
||||
"ixl/db": 322,
|
||||
"pch/abh": 161,
|
||||
"pch/db": 162,
|
||||
"pcl/abl": 139,
|
||||
"pcl/db": 137,
|
||||
"rw-high": 1306,
|
||||
"rw-low": 1307,
|
||||
"sph/abh": 286,
|
||||
"sph/db": 172,
|
||||
"spl/abl": 178,
|
||||
"spl/db": 175,
|
||||
"sr/adda": 416,
|
||||
"sum/db": 532,
|
||||
"tmp/abh": 179,
|
||||
"tmp/db": 173,
|
||||
"vma-high": 1500,
|
||||
"vma-low": 1499,
|
||||
"flag0/db1": 321,
|
||||
"flag0/db2": 375,
|
||||
"flag0/db3": 376,
|
||||
"flag0/db4": 309,
|
||||
"flag0/db5": 308,
|
||||
"n1n-0": 1303,
|
||||
"n1n-1": 1291,
|
||||
"n1n-2": 1294,
|
||||
"n1n-3": 1292,
|
||||
"n1n-4": 1295,
|
||||
"n1n-5": 1293,
|
||||
"n1n-6": 1275,
|
||||
"ndb/adda": 415,
|
||||
"nin-7": 1276,
|
||||
}
|
9818
chip-6800/segdefs.js
Normal file
457
chip-6800/support.js
Normal file
@ -0,0 +1,457 @@
|
||||
// chip-specific support functions
|
||||
//
|
||||
// may override function definitions made previously
|
||||
|
||||
chipname='6800';
|
||||
|
||||
grChipSize=7000;
|
||||
|
||||
ngnd = nodenames['gnd'];
|
||||
npwr = nodenames['vcc'];
|
||||
|
||||
nodenamereset = 'reset';
|
||||
|
||||
presetLogLists=[
|
||||
['cycle','phi1','phi2'],
|
||||
['ab','db','rw','vma','Fetch','pc','acca','accb','ix','sp','p'],
|
||||
['ir','sync','Execute'], // instruction fetch and execution control
|
||||
['dbi','dbo','tmp'], // internal state
|
||||
['idb','abh','abl','ablx'], // internal busses
|
||||
['irq','nmi',nodenamereset,'tsc','dbe','halt','ba'], // other pins
|
||||
];
|
||||
|
||||
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 bb = tdef[4];
|
||||
if(tdef[6])
|
||||
// just ignore all the 'weak' transistors for now
|
||||
continue;
|
||||
if(c1==ngnd) {c1=c2;c2=ngnd;}
|
||||
if(c1==npwr) {c1=c2;c2=npwr;}
|
||||
var trans = {name: name, on: false, gate: gate, c1: c1, c2: c2, bb: bb};
|
||||
nodes[gate].gates.push(trans);
|
||||
nodes[c1].c1c2s.push(trans);
|
||||
nodes[c2].c1c2s.push(trans);
|
||||
transistors[name] = trans;
|
||||
}
|
||||
}
|
||||
|
||||
// simulate a single clock phase with no update to graphics or trace
|
||||
function halfStep(){
|
||||
var clk = isNodeHigh(nodenames['phi2']);
|
||||
eval(clockTriggers[cycle]);
|
||||
if (clk) {setLow('phi2'); setLow('dbe'); setHigh('phi1'); handleBusRead(); }
|
||||
else {setHigh('phi1'); setLow('phi1'); setHigh('phi2'); setHigh('dbe'); handleBusWrite();}
|
||||
}
|
||||
|
||||
function goUntilSyncOrWrite(){
|
||||
halfStep();
|
||||
cycle++;
|
||||
while(
|
||||
!isNodeHigh(nodenames['phi2']) ||
|
||||
( !isNodeHigh(nodenames['sync']) && isNodeHigh(nodenames['rw']) )
|
||||
) {
|
||||
halfStep();
|
||||
cycle++;
|
||||
}
|
||||
chipStatus();
|
||||
}
|
||||
|
||||
function initChip(){
|
||||
var start = now();
|
||||
for(var nn in nodes) {
|
||||
nodes[nn].state = false;
|
||||
nodes[nn].float = true;
|
||||
}
|
||||
|
||||
nodes[ngnd].state = false;
|
||||
nodes[ngnd].float = false;
|
||||
nodes[npwr].state = true;
|
||||
nodes[npwr].float = false;
|
||||
for(var tn in transistors) transistors[tn].on = false;
|
||||
setLow(nodenamereset);
|
||||
setHigh('phi1'); setLow('phi2'); setLow('dbe');
|
||||
setHigh('dbe'); setLow('tsc'); setHigh('halt');
|
||||
setHigh('irq'); setHigh('nmi');
|
||||
recalcNodeList(allNodes());
|
||||
for(var i=0;i<8;i++){
|
||||
setLow('phi1');
|
||||
setHigh('phi2'); setHigh('dbe');
|
||||
setLow('phi2'); setLow('dbe');
|
||||
setHigh('phi1');
|
||||
}
|
||||
setHigh(nodenamereset);
|
||||
for(var i=0;i<18;i++){halfStep();} // avoid updating graphics and trace buffer before user code
|
||||
refresh();
|
||||
cycle = 0;
|
||||
trace = Array();
|
||||
if(typeof expertMode != "undefined")
|
||||
updateLogList();
|
||||
chipStatus();
|
||||
if(ctrace)console.log('initChip done after', now()-start);
|
||||
}
|
||||
|
||||
function handleBusRead(){
|
||||
if(isNodeHigh(nodenames['rw'])){
|
||||
var a = readAddressBus();
|
||||
var d = eval(readTriggers[a]);
|
||||
if(d == undefined)
|
||||
d = mRead(readAddressBus());
|
||||
if(isNodeHigh(nodenames['sync']))
|
||||
eval(fetchTriggers[d]);
|
||||
writeDataBus(d);
|
||||
}
|
||||
}
|
||||
|
||||
function readAccA(){return readBits('acca', 8);}
|
||||
function readAccB(){return readBits('accb', 8);}
|
||||
function readIX(){return (readBits('ixh', 8)<<8) + readBits('ixl', 8);}
|
||||
function readSP(){return (readBits('sph', 8)<<8) + readBits('spl', 8);}
|
||||
function readPstring(){
|
||||
var result;
|
||||
result = '‑' + // non-breaking hyphen
|
||||
'‑' + // non-breaking hyphen
|
||||
(isNodeHigh(nodenames['flagh'])?'H':'h') +
|
||||
(isNodeHigh(nodenames['flagi'])?'I':'i') +
|
||||
(isNodeHigh(nodenames['flagn'])?'N':'n') +
|
||||
(isNodeHigh(nodenames['flagz'])?'Z':'z') +
|
||||
(isNodeHigh(nodenames['flagv'])?'V':'v') +
|
||||
(isNodeHigh(nodenames['flagc'])?'C':'c');
|
||||
return result;
|
||||
}
|
||||
|
||||
function busToString(busname){
|
||||
// takes a signal name or prefix
|
||||
// returns an appropriate string representation
|
||||
// some 'signal names' are CPU-specific aliases to user-friendly string output
|
||||
if(busname=='cycle')
|
||||
return cycle>>1;
|
||||
if(busname=='pc')
|
||||
return busToHex('pch') + busToHex('pcl');
|
||||
if(busname=='sp')
|
||||
return busToHex('sph') + busToHex('spl');
|
||||
if(busname=='ix')
|
||||
return busToHex('ixh') + busToHex('ixl');
|
||||
if(busname=='p')
|
||||
return readPstring();
|
||||
if(busname=='State')
|
||||
return listActiveTCStates();
|
||||
if(busname=='Execute')
|
||||
return disassemblytoHTML(readBits('ir',8));
|
||||
if(busname=='Fetch')
|
||||
return isNodeHigh(nodenames['sync'])?disassemblytoHTML(readDataBus()):"";
|
||||
if(busname=='plaOutputs')
|
||||
// PLA outputs are mostly ^op- but some have a prefix too
|
||||
// - we'll allow the x and xx prefix but ignore the #
|
||||
return listActiveSignals('^([x]?x-)?op-');
|
||||
if(busname=='DPControl')
|
||||
return listActiveSignals('^dpc[0-9]+_');
|
||||
if(busname[0]=="-"){
|
||||
// invert the value of the bus for display
|
||||
var value=busToHex(busname.slice(1))
|
||||
if(typeof value != "undefined")
|
||||
return value.replace(/./g,function(x){return (15-parseInt(x,16)).toString(16)});
|
||||
else
|
||||
return undefined;;
|
||||
} else {
|
||||
return busToHex(busname);
|
||||
}
|
||||
}
|
||||
|
||||
function chipStatus(){
|
||||
var ab = readAddressBus();
|
||||
var machine1 =
|
||||
' halfcyc:' + cycle +
|
||||
' phi0:' + readBit('phi2') +
|
||||
' AB:' + hexWord(ab) +
|
||||
' D:' + hexByte(readDataBus()) +
|
||||
' RnW:' + readBit('rw') +
|
||||
' VMA:' + readBit('vma');
|
||||
var machine2 =
|
||||
' PC:' + hexWord(readPC()) +
|
||||
' A:' + hexByte(readAccA()) +
|
||||
' B:' + hexByte(readAccB()) +
|
||||
' IX:' + hexWord(readIX()) +
|
||||
' SP:' + hexWord(readSP()) +
|
||||
' ' + readPstring();
|
||||
var machine3 =
|
||||
'Hz: ' + estimatedHz().toFixed(1);
|
||||
if(typeof expertMode != "undefined") {
|
||||
machine3 += ' Exec: ' + busToString('Execute'); // no T-state info for 6800 yet
|
||||
if(isNodeHigh(nodenames['sync']))
|
||||
machine3 += ' (Fetch: ' + busToString('Fetch') + ')';
|
||||
if(goldenChecksum != undefined)
|
||||
machine3 += " Chk:" + traceChecksum + ((traceChecksum==goldenChecksum)?" OK":" no match");
|
||||
}
|
||||
|
||||
setStatus(machine1, machine2, machine3);
|
||||
if (loglevel>0) {
|
||||
updateLogbox(logThese);
|
||||
}
|
||||
selectCell(ab);
|
||||
}
|
||||
|
||||
// javascript derived from http://segher.ircgeeks.net/6800/OPS
|
||||
var disassembly={
|
||||
0x00: "!",
|
||||
0x01: "nop",
|
||||
0x02: "!",
|
||||
0x03: "!",
|
||||
0x04: "!",
|
||||
0x05: "!",
|
||||
0x06: "tap",
|
||||
0x07: "tpa",
|
||||
0x10: "sba",
|
||||
0x11: "cba",
|
||||
0x12: "!",
|
||||
0x13: "!",
|
||||
0x14: "!nba",
|
||||
0x15: "!",
|
||||
0x16: "tab",
|
||||
0x17: "tba",
|
||||
0x20: "bra N",
|
||||
0x21: "!",
|
||||
0x22: "bhi N",
|
||||
0x23: "bls N",
|
||||
0x24: "bcc N",
|
||||
0x25: "bcs N",
|
||||
0x26: "bne N",
|
||||
0x27: "beq N",
|
||||
0x30: "tsx",
|
||||
0x31: "ins",
|
||||
0x32: "pul a",
|
||||
0x33: "pul b",
|
||||
0x34: "des",
|
||||
0x35: "txs",
|
||||
0x36: "psh a",
|
||||
0x37: "psh b",
|
||||
0x40: "neg a",
|
||||
0x41: "!",
|
||||
0x42: "!",
|
||||
0x43: "com a",
|
||||
0x44: "lsr a",
|
||||
0x45: "!",
|
||||
0x46: "ror a",
|
||||
0x47: "asr a",
|
||||
0x50: "neg b",
|
||||
0x51: "!",
|
||||
0x52: "!",
|
||||
0x53: "com b",
|
||||
0x54: "lsr b",
|
||||
0x55: "!",
|
||||
0x56: "ror b",
|
||||
0x57: "asr b",
|
||||
0x60: "neg Nx",
|
||||
0x61: "!",
|
||||
0x62: "!",
|
||||
0x63: "com Nx",
|
||||
0x64: "lsr Nx",
|
||||
0x65: "!",
|
||||
0x66: "ror Nx",
|
||||
0x67: "asr Nx",
|
||||
0x70: "neg NN",
|
||||
0x71: "!",
|
||||
0x72: "!",
|
||||
0x73: "com NN",
|
||||
0x74: "lsr NN",
|
||||
0x75: "!",
|
||||
0x76: "ror NN",
|
||||
0x77: "asr NN",
|
||||
0x80: "sub a #",
|
||||
0x81: "cmp a #",
|
||||
0x82: "sbc a #",
|
||||
0x83: "!",
|
||||
0x84: "and a #",
|
||||
0x85: "bit a #",
|
||||
0x86: "lda a #",
|
||||
0x87: "!",
|
||||
0x90: "sub a N",
|
||||
0x91: "cmp a N",
|
||||
0x92: "sbc a N",
|
||||
0x93: "!",
|
||||
0x94: "and a N",
|
||||
0x95: "bit a N",
|
||||
0x96: "lda a N",
|
||||
0x97: "sta a N",
|
||||
0xa0: "sub a Nx",
|
||||
0xa1: "cmp a Nx",
|
||||
0xa2: "sbc a Nx",
|
||||
0xa3: "!",
|
||||
0xa4: "and a Nx",
|
||||
0xa5: "bit a Nx",
|
||||
0xa6: "lda a Nx",
|
||||
0xa7: "sta a Nx",
|
||||
0xb0: "sub a NN",
|
||||
0xb1: "cmp a NN",
|
||||
0xb2: "sbc a NN",
|
||||
0xb3: "!",
|
||||
0xb4: "and a NN",
|
||||
0xb5: "bit a NN",
|
||||
0xb6: "lda a NN",
|
||||
0xb7: "sta a NN",
|
||||
0xc0: "sub b #",
|
||||
0xc1: "cmp b #",
|
||||
0xc2: "sbc b #",
|
||||
0xc3: "!",
|
||||
0xc4: "and b #",
|
||||
0xc5: "bit b #",
|
||||
0xc6: "lda b #",
|
||||
0xc7: "!",
|
||||
0xd0: "sub b N",
|
||||
0xd1: "cmp b N",
|
||||
0xd2: "sbc b N",
|
||||
0xd3: "!",
|
||||
0xd4: "and b N",
|
||||
0xd5: "bit b N",
|
||||
0xd6: "lda b N",
|
||||
0xd7: "sta b N",
|
||||
0xe0: "sub b Nx",
|
||||
0xe1: "cmp b Nx",
|
||||
0xe2: "sbc b Nx",
|
||||
0xe3: "!",
|
||||
0xe4: "and b Nx",
|
||||
0xe5: "bit b Nx",
|
||||
0xe6: "lda b Nx",
|
||||
0xe7: "sta b Nx",
|
||||
0xf0: "sub b NN",
|
||||
0xf1: "cmp b NN",
|
||||
0xf2: "sbc b NN",
|
||||
0xf3: "!",
|
||||
0xf4: "and b NN",
|
||||
0xf5: "bit b NN",
|
||||
0xf6: "lda b NN",
|
||||
0xf7: "sta b NN",
|
||||
0x08: "inx",
|
||||
0x09: "dex",
|
||||
0x0a: "clv",
|
||||
0x0b: "sev",
|
||||
0x0c: "clc",
|
||||
0x0d: "sec",
|
||||
0x0e: "cli",
|
||||
0x0f: "sei",
|
||||
0x18: "!",
|
||||
0x19: "daa",
|
||||
0x1a: "!",
|
||||
0x1b: "aba",
|
||||
0x1c: "!",
|
||||
0x1d: "!",
|
||||
0x1e: "!",
|
||||
0x1f: "!",
|
||||
0x28: "bvc N",
|
||||
0x29: "bvs N",
|
||||
0x2a: "bpl N",
|
||||
0x2b: "bmi N",
|
||||
0x2c: "bge N",
|
||||
0x2d: "blt N",
|
||||
0x2e: "bgt N",
|
||||
0x2f: "ble N",
|
||||
0x38: "!",
|
||||
0x39: "rts",
|
||||
0x3a: "!",
|
||||
0x3b: "rti",
|
||||
0x3c: "!",
|
||||
0x3d: "!",
|
||||
0x3e: "wai",
|
||||
0x3f: "swi",
|
||||
0x48: "asl a",
|
||||
0x49: "rol a",
|
||||
0x4a: "dec a",
|
||||
0x4b: "!",
|
||||
0x4c: "inc a",
|
||||
0x4d: "tst a",
|
||||
0x4e: "!",
|
||||
0x4f: "clr a",
|
||||
0x58: "asl b",
|
||||
0x59: "rol b",
|
||||
0x5a: "dec b",
|
||||
0x5b: "!",
|
||||
0x5c: "inc b",
|
||||
0x5d: "tst b",
|
||||
0x5e: "!",
|
||||
0x5f: "clr b",
|
||||
0x68: "asl Nx",
|
||||
0x69: "rol Nx",
|
||||
0x6a: "dec Nx",
|
||||
0x6b: "!",
|
||||
0x6c: "inc Nx",
|
||||
0x6d: "tst Nx",
|
||||
0x6e: "jmp Nx",
|
||||
0x6f: "clr Nx",
|
||||
0x78: "asl NN",
|
||||
0x79: "rol NN",
|
||||
0x7a: "dec NN",
|
||||
0x7b: "!",
|
||||
0x7c: "inc NN",
|
||||
0x7d: "tst NN",
|
||||
0x7e: "jmp NN",
|
||||
0x7f: "clr NN",
|
||||
0x88: "eor a #",
|
||||
0x89: "adc a #",
|
||||
0x8a: "ora a #",
|
||||
0x8b: "add a #",
|
||||
0x8c: "cpx ##",
|
||||
0x8d: "bsr N",
|
||||
0x8e: "lds ##",
|
||||
0x8f: "!",
|
||||
0x98: "eor a N",
|
||||
0x99: "adc a N",
|
||||
0x9a: "ora a N",
|
||||
0x9b: "add a N",
|
||||
0x9c: "cpx N",
|
||||
0x9d: "!hcf",
|
||||
0x9e: "lds N",
|
||||
0x9f: "sts N",
|
||||
0xa8: "eor a Nx",
|
||||
0xa9: "adc a Nx",
|
||||
0xaa: "ora a Nx",
|
||||
0xab: "add a Nx",
|
||||
0xac: "cpx Nx",
|
||||
0xad: "jsr Nx",
|
||||
0xae: "lds Nx",
|
||||
0xaf: "sts Nx",
|
||||
0xb8: "eor a NN",
|
||||
0xb9: "adc a NN",
|
||||
0xba: "ora a NN",
|
||||
0xbb: "add a NN",
|
||||
0xbc: "cpx NN",
|
||||
0xbd: "jsr NN",
|
||||
0xbe: "lds NN",
|
||||
0xbf: "sts NN",
|
||||
0xc8: "eor b #",
|
||||
0xc9: "adc b #",
|
||||
0xca: "ora b #",
|
||||
0xcb: "add b #",
|
||||
0xcc: "!",
|
||||
0xcd: "!",
|
||||
0xce: "ldx ##",
|
||||
0xcf: "!",
|
||||
0xd8: "eor b N",
|
||||
0xd9: "adc b N",
|
||||
0xda: "ora b N",
|
||||
0xdb: "add b N",
|
||||
0xdc: "!",
|
||||
0xdd: "!hcf",
|
||||
0xde: "ldx N",
|
||||
0xdf: "stx N",
|
||||
0xe8: "eor b Nx",
|
||||
0xe9: "adc b Nx",
|
||||
0xea: "ora b Nx",
|
||||
0xeb: "add b Nx",
|
||||
0xec: "!",
|
||||
0xed: "!",
|
||||
0xee: "ldx Nx",
|
||||
0xef: "stx Nx",
|
||||
0xf8: "eor b NN",
|
||||
0xf9: "adc b NN",
|
||||
0xfa: "ora b NN",
|
||||
0xfb: "add b NN",
|
||||
0xfc: "!",
|
||||
0xfd: "!",
|
||||
0xfe: "ldx NN",
|
||||
0xff: "stx NN",
|
||||
};
|
25
chip-6800/testprogram.js
Normal file
@ -0,0 +1,25 @@
|
||||
// This file testprogram.js can be substituted by one of several tests
|
||||
testprogramAddress=0x0000;
|
||||
|
||||
// we want to auto-clear the console if any output is sent by the program
|
||||
var consoleboxStream="";
|
||||
|
||||
// for opcodes, see ftp://ftp.comlab.ox.ac.uk/pub/Cards/txt/6800.txt
|
||||
|
||||
testprogram = [
|
||||
0x01, // NOP
|
||||
0x01, // NOP
|
||||
0x01, // NOP
|
||||
0xce, 0x43, 0x21, // LDX #4321
|
||||
0x35, // TXS
|
||||
0xc6, 0x00, // LDAA #$00
|
||||
0xbd, 0x00, 0x10, // JSR $0010
|
||||
0x7e, 0x00, 0x02, // JMP $0002
|
||||
0x01, // NOP
|
||||
0x08, // INX
|
||||
0x5a, // DECB
|
||||
0x7c, 0x00, 0x0f, // INC $0F
|
||||
0x0d, // SEC
|
||||
0xc9, 0x02, // ADCA #$02
|
||||
0x39, // RTS
|
||||
]
|
3598
chip-6800/transdefs.js
Normal file
164
chipsim.js
@ -21,123 +21,116 @@
|
||||
*/
|
||||
|
||||
var ctrace = false;
|
||||
var noGraphics = false;
|
||||
var loglevel = 3;
|
||||
var ridx = 0;
|
||||
var traceTheseNodes = [];
|
||||
var traceTheseTransistors = [];
|
||||
var loglevel = 0;
|
||||
var recalclist = new Array();
|
||||
var recalcHash = new Array();
|
||||
var group = new Array();
|
||||
|
||||
function recalcNodeList(list){
|
||||
var n = list[0];
|
||||
var recalclist = new Array();
|
||||
recalclist = new Array();
|
||||
recalcHash = 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);
|
||||
if(ctrace) {
|
||||
var i;
|
||||
for(i=0;i<traceTheseNodes.length;i++) {
|
||||
if(list.indexOf(traceTheseNodes[i])!=-1) break;
|
||||
}
|
||||
if((traceTheseNodes.length==0)||(list.indexOf(traceTheseNodes[i])==-1)) {
|
||||
console.log('recalcNodeList iteration: ', j, list.length, 'nodes');
|
||||
} else {
|
||||
console.log('recalcNodeList iteration: ', j, list.length, 'nodes', list);
|
||||
}
|
||||
}
|
||||
list.forEach(recalcNode);
|
||||
list = recalclist;
|
||||
recalclist = new Array();
|
||||
recalcHash = new Array();
|
||||
}
|
||||
console.log(n,'looping...');
|
||||
if(ctrace) console.log(n,'looping...');
|
||||
}
|
||||
|
||||
function recalcNode(node, recalclist){
|
||||
function recalcNode(node){
|
||||
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);
|
||||
}
|
||||
getNodeGroup(node);
|
||||
var newState = getNodeValue();
|
||||
if(ctrace && (traceTheseNodes.indexOf(node)!=-1))
|
||||
console.log('recalc', node, group);
|
||||
group.forEach(function(i){
|
||||
var n = nodes[i];
|
||||
if(n.state==newState) return;
|
||||
n.state = newState;
|
||||
n.gates.forEach(function(t){
|
||||
if(n.state) turnTransistorOn(t);
|
||||
else turnTransistorOff(t);});
|
||||
});
|
||||
}
|
||||
|
||||
function recalcTransistor(tn, recalclist){
|
||||
var t = transistors[tn];
|
||||
if(isNodeHigh(t.gate)) turnTransistorOn(t, recalclist);
|
||||
else turnTransistorOff(t, recalclist);
|
||||
}
|
||||
|
||||
function turnTransistorOn(t, recalclist){
|
||||
function turnTransistorOn(t){
|
||||
if(t.on) return;
|
||||
if(ctrace) console.log(t.name, 'on', t.gate, t.c1, t.c2);
|
||||
if(ctrace && (traceTheseTransistors.indexOf(t.name)!=-1))
|
||||
console.log(t.name, 'on', t.gate, t.c1, t.c2);
|
||||
t.on = true;
|
||||
addRecalcNode(t.c1, recalclist);
|
||||
addRecalcNode(t.c2, recalclist);
|
||||
addRecalcNode(t.c1);
|
||||
}
|
||||
|
||||
function turnTransistorOff(t, recalclist){
|
||||
function turnTransistorOff(t){
|
||||
if(!t.on) return;
|
||||
if(ctrace) console.log(t.name, 'off', t.gate, t.c1, t.c2);
|
||||
if(ctrace && (traceTheseTransistors.indexOf(t.name)!=-1))
|
||||
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);
|
||||
addRecalcNode(t.c1);
|
||||
addRecalcNode(t.c2);
|
||||
}
|
||||
|
||||
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 addRecalcNode(nn){
|
||||
if(nn==ngnd) return;
|
||||
if(nn==npwr) return;
|
||||
if(recalcHash[nn] == 1)return;
|
||||
recalclist.push(nn);
|
||||
recalcHash[nn] = 1;
|
||||
}
|
||||
|
||||
function getNodeGroup(i){
|
||||
var group = new Array();
|
||||
addNodeToGroup(i, group);
|
||||
return group;
|
||||
group = new Array();
|
||||
addNodeToGroup(i);
|
||||
}
|
||||
|
||||
function addNodeToGroup(i, group){
|
||||
if(arrayContains(group, i)) return;
|
||||
function addNodeToGroup(i){
|
||||
if(group.indexOf(i) != -1) 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);
|
||||
nodes[i].c1c2s.forEach(
|
||||
function(t){
|
||||
if(!t.on) return;
|
||||
var other;
|
||||
if(t.c1==i) other=t.c2;
|
||||
if(t.c2==i) other=t.c1;
|
||||
addNodeToGroup(other);});
|
||||
}
|
||||
|
||||
|
||||
function getNodeValue(group){
|
||||
if(arrayContains(group, ngnd)) return 'gnd';
|
||||
if(arrayContains(group, npwr)) return 'vcc';
|
||||
var flstate;
|
||||
function getNodeValue(){
|
||||
if(arrayContains(group, ngnd)) return false;
|
||||
if(arrayContains(group, npwr)) return true;
|
||||
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(n.pullup) return true;
|
||||
if(n.pulldown) return false;
|
||||
if(n.state) return true;
|
||||
}
|
||||
if(flstate==undefined) console.log(group);
|
||||
return flstate;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function isNodeHigh(nn){
|
||||
return arrayContains(['vcc','pu','fh'], nodes[nn].state);
|
||||
return(nodes[nn].state);
|
||||
}
|
||||
|
||||
function saveString(name, str){
|
||||
@ -155,25 +148,26 @@ function allNodes(){
|
||||
}
|
||||
|
||||
function stateString(){
|
||||
var codes = {gnd: 'g', vcc: 'v', pu: 'p', pd: 'd', fh: 'f', fl: 'l'};
|
||||
var codes = ['l','h'];
|
||||
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];
|
||||
else res+= codes[0+n.state];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function showState(str){
|
||||
var codes = {g: 'gnd', v: 'vcc', p: 'pu', d: 'pd', f: 'fh', l: 'fl'};
|
||||
var codes = {g: false, h: true, v: true, l: false};
|
||||
for(var i=0;i<str.length;i++){
|
||||
if(str[i]=='x') continue;
|
||||
nodes[i].state = codes[str[i]];
|
||||
var state = codes[str[i]];
|
||||
nodes[i].state = state;
|
||||
var gates = nodes[i].gates;
|
||||
for(var t in gates) transistors[gates[t]].on = isNodeHigh(i);
|
||||
gates.forEach(function(t){t.on=state;});
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
@ -199,12 +193,4 @@ function setLow(name){
|
||||
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;}
|
||||
|
153
expert-6800.html
Normal file
@ -0,0 +1,153 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<title>Visual 6800 in JavaScript</title>
|
||||
<style type="text/css">@import "expert.css";</style>
|
||||
<script src="chip-6800/segdefs.js"></script>
|
||||
<script src="chip-6800/transdefs.js"></script>
|
||||
<script src="chip-6800/nodenames.js"></script>
|
||||
<script src="wires.js"></script>
|
||||
<script src="expertWires.js"></script>
|
||||
<script src="chipsim.js"></script>
|
||||
<script src="memtable.js"></script>
|
||||
<script src="macros.js"></script>
|
||||
<script src="chip-6800/support.js"></script>
|
||||
<script src="chip-6800/testprogram.js"></script>
|
||||
<script src="3rdparty/jquery-1.3.2.min.js"></script>
|
||||
<script src="3rdparty/jquery.cookie.js"></script>
|
||||
<script src="3rdparty/splitter.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);
|
||||
}
|
||||
};
|
||||
|
||||
// initialise splitter (built on jquery)
|
||||
$().ready(function(){
|
||||
$("#frame").splitter({
|
||||
type: "v",
|
||||
outline: true,
|
||||
minLeft: 20,
|
||||
sizeLeft: 810,
|
||||
resizeToWidth: true,
|
||||
anchorToWindow: true,
|
||||
});
|
||||
$("#rightcolumn").splitter({
|
||||
type: "h",
|
||||
outline: true,
|
||||
sizeBottom: 180,
|
||||
minTop: 100,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="handleOnload();">
|
||||
<span id="plain">
|
||||
<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>
|
||||
<a href="http://github.com/trebonian/visual6502">Source</a>
|
||||
<a href="ftp://ftp.comlab.ox.ac.uk/pub/Cards/txt/6800.txt">6800 instruction card</a>
|
||||
<a href="http://www.sbprojects.com/sbasm/6800.htm#model">programming model</a>
|
||||
</span>
|
||||
<div class="frame" id="frame">
|
||||
<div class="leftcolumn" id="leftcolumn">
|
||||
<div id="chipsurround" tabindex="1">
|
||||
<div class="chip" id="chip">
|
||||
<span id="waiting">Please wait, graphics initialising...</span>
|
||||
<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> <!-- chipsurround -->
|
||||
<div class="nochip" id="nochip">
|
||||
<form>
|
||||
<input type="button" value="Show chip layout" onclick="updateChipLayoutVisibility(true)" />
|
||||
</form>
|
||||
</div>
|
||||
<div id="layoutControlPanel">
|
||||
Use 'z' or '>' to zoom in, 'x' or '<' to zoom out, click to probe signals and drag to pan.
|
||||
<form id="updateShow"> Show:
|
||||
<input type="checkbox" name="1" id="updateShow1" onchange="updateShow(this.name,this.checked)" />(diffusion)
|
||||
<input type="checkbox" name="3" id="updateShow3" onchange="updateShow(this.name,this.checked)" />(grounded diffusion)
|
||||
<input type="checkbox" name="4" id="updateShow4" onchange="updateShow(this.name,this.checked)" />(powered diffusion)
|
||||
<input type="checkbox" name="5" id="updateShow5" onchange="updateShow(this.name,this.checked)" />(polysilicon)
|
||||
<input type="checkbox" name="0" id="updateShow0" onchange="updateShow(this.name,this.checked)" />(metal)
|
||||
<input type="checkbox" name="2" id="updateShow2" onchange="updateShow(this.name,this.checked)" />(protection)
|
||||
</form>
|
||||
<form action="javascript:hiliteNodeList();">
|
||||
<input type="button" value="Find:" onclick="hiliteNodeList();" />
|
||||
<input type="text" id="HighlightThese" name="HighlightThese" value="" />
|
||||
<input type="button" value="Clear Highlighting" onclick="clearHighlight();" />
|
||||
<span class="animatebox">
|
||||
Animate during simulation:
|
||||
<input type="checkbox" id="animateModeCheckbox" onchange="updateChipLayoutAnimation(this.checked)"
|
||||
/></span>
|
||||
</form>
|
||||
<form>
|
||||
<input type="button" value="Hide Chip Layout" onclick="updateChipLayoutVisibility(false)" />
|
||||
<a href="" id="linkHere" >Link to this location</a>
|
||||
</form>
|
||||
</div>
|
||||
</div> <!-- closing leftcolumn -->
|
||||
<div class="rightcolumn" id="rightcolumn">
|
||||
<div id="righttopdiv">
|
||||
<div class = "buttons">
|
||||
<div class="twobuttons">
|
||||
<a href ="javascript:stopChip()" id="stop"><img class="navstop" src="images/stop.png" title="stop"></a>
|
||||
<a href ="javascript:runChip()" id="start"><img class="navplay" src="images/play.png" title="run"></a>
|
||||
</div>
|
||||
<div class="morebuttons">
|
||||
<a href ="javascript:resetChip()"><img class="navbutton" src="images/up.png" title="reset"></a>
|
||||
<a href ="javascript:stepBack()"><img class="navbutton" src="images/prev.png" title="back"></a>
|
||||
<a href ="javascript:stepForward()"><img class="navbutton" src="images/next.png" title="forward"></a>
|
||||
<a href ="javascript:goUntilSyncOrWrite()"><img class="navbutton" src="images/singlestep.png" title="step"></a>
|
||||
<a href ="javascript:goFor()"><img class="navbutton" src="images/fastforward.png" title="fastforward"></a>
|
||||
</div>
|
||||
<div style="float:right;">
|
||||
<a href="http://visual6502.org/wiki/index.php?title=JssimUserHelp" target="_blank">User Guide</a>
|
||||
|
||||
</div>
|
||||
</div> <!-- buttons -->
|
||||
<div class="status" id="status"><p>x: 0<br>y: 0</p>
|
||||
</div> <!-- status -->
|
||||
|
||||
<div id="memtablediv">
|
||||
<table class="memtable" id="memtable" tabindex="2"></table>
|
||||
</div>
|
||||
</div> <!-- righttopdiv -->
|
||||
|
||||
<div id="tracingdiv">
|
||||
<textarea id="consolebox">
|
||||
click here and type if your program handles input
|
||||
</textarea>
|
||||
<div id="expertControlPanel" tabindex="3">
|
||||
<form action="javascript:updateLogList()">
|
||||
<input type="button" value="Trace more" onclick="updateLoglevel(++loglevel)" />
|
||||
<input type="button" value="Trace less" onclick="updateLoglevel(--loglevel)" />
|
||||
<input type="button" value="Trace these too:" onclick="updateLogList()" />
|
||||
<input type="text" id="LogThese" name="LogThese" value="" />
|
||||
<input type="button" value="Log Up/Down" onclick="updateLogDirection();" />
|
||||
<input type="button" value="Clear Log" onclick="updateLoglevel(loglevel)" />
|
||||
</form>
|
||||
<br />
|
||||
</div>
|
||||
<div id="logstreamscroller">
|
||||
<table class="logstream" id="logstream"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- closing rightcolumn -->
|
||||
</div> <!-- closing 'frame' div -->
|
||||
</body>
|
||||
</html>
|
14858
expert-allinone.js
Normal file
228
expert.css
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
body {
|
||||
background: white;
|
||||
color: black;
|
||||
font-family :Verdana, Arial, Helvetica, Sans-Serif;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#title {
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.frame {
|
||||
margin-left: 10px;
|
||||
min-width: 1120px; /* ugh - prevent memtable flowing underneath chip */
|
||||
}
|
||||
|
||||
div.leftcolumn {
|
||||
width: 804px; /* ugh - matches the div.chip width + border */
|
||||
}
|
||||
|
||||
div.rightcolumn {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
clear: both;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
div.nochip {
|
||||
display:none;
|
||||
}
|
||||
|
||||
div#chipsurround {
|
||||
height: 600px; /* matches the div.chip height */
|
||||
}
|
||||
|
||||
div.chip {
|
||||
background: lightgray;
|
||||
border: 2px solid gray;
|
||||
position: absolute; /* must be absolute to contain the canvas */
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
canvas.chip {
|
||||
position: absolute;
|
||||
width: 600px; /* square chip image same height as div.chip */
|
||||
height: 600px; /* square */
|
||||
}
|
||||
|
||||
div.twobuttons{
|
||||
float:left;
|
||||
}
|
||||
|
||||
div.morebuttons{
|
||||
float:left;
|
||||
}
|
||||
|
||||
div.buttons{
|
||||
/* top: -5px; */
|
||||
}
|
||||
|
||||
div.status {
|
||||
clear: left;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
img.navbutton {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
img.navplay {
|
||||
margin-right: 5px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
img.navstop {
|
||||
position: absolute;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
span.expertcheckbox {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
table.memtable {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
border-spacing: 0px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
div#layoutControlPanel{
|
||||
display:none;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
div#expertControlPanel{
|
||||
display:none;
|
||||
}
|
||||
|
||||
span.animatebox{
|
||||
border:thin solid;
|
||||
padding:2px;
|
||||
border-color:gray;
|
||||
}
|
||||
|
||||
a#linkHere{
|
||||
padding:2px;
|
||||
}
|
||||
|
||||
textarea#consolebox{
|
||||
font-family:courier,monospace;
|
||||
border: 1px solid gray;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
width: 80em;
|
||||
}
|
||||
|
||||
div#logstreamscroller{
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
table.logstream {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
border-collapse: collapse;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
td {
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
td.header {
|
||||
background-color: rgb(187, 204, 255); /* medium-dark blue */
|
||||
}
|
||||
|
||||
td.oddcol {
|
||||
background-color: rgb(227, 233, 255); /* light blue */
|
||||
}
|
||||
|
||||
td.oddrow {
|
||||
background-color: rgb(207, 218, 255); /* medium blue */
|
||||
}
|
||||
|
||||
td.oddrowcol {
|
||||
background-color: rgb(227, 233, 255); /* light blue */
|
||||
}
|
||||
|
||||
/* Splitter */
|
||||
#frame {
|
||||
height: 750px;
|
||||
}
|
||||
|
||||
div.leftcolumn, div.rightcolumn, {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
div#righttopdiv, div#tracingdiv {
|
||||
overflow: auto;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
div.rightcolumn {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.vsplitbar {
|
||||
width: 5px;
|
||||
background: #aaa;
|
||||
}
|
||||
|
||||
.vsplitbar {
|
||||
width: 6px;
|
||||
background: #669 url(3rdparty/img/vgrabber.gif) no-repeat center;
|
||||
}
|
||||
|
||||
.vsplitbar:hover, .vsplitbar.active {
|
||||
background: #c66 url(3rdparty/img/vgrabber.gif) no-repeat center;
|
||||
opacity: 0.7;
|
||||
filter: alpha(opacity=70); /* IE */
|
||||
background: #c99;
|
||||
}
|
||||
|
||||
.hsplitbar {
|
||||
height: 6px;
|
||||
background: #669 url(3rdparty/img/hgrabber.gif) no-repeat center;
|
||||
}
|
||||
|
||||
.hsplitbar.active, .hsplitbar:hover {
|
||||
background: #c66 url(3rdparty/img/hgrabber.gif) no-repeat center;
|
||||
}
|
||||
|
||||
span#plain {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
}
|
152
expert.html
Normal file
@ -0,0 +1,152 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<title>Visual 6502 in JavaScript</title>
|
||||
<style type="text/css">@import "expert.css";</style>
|
||||
<script src="segdefs.js"></script>
|
||||
<script src="transdefs.js"></script>
|
||||
<script src="nodenames.js"></script>
|
||||
<script src="wires.js"></script>
|
||||
<script src="expertWires.js"></script>
|
||||
<script src="chipsim.js"></script>
|
||||
<script src="memtable.js"></script>
|
||||
<script src="macros.js"></script>
|
||||
<script src="testprogram.js"></script>
|
||||
<script src="3rdparty/jquery-1.3.2.min.js"></script>
|
||||
<script src="3rdparty/jquery.cookie.js"></script>
|
||||
<script src="3rdparty/splitter.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);
|
||||
}
|
||||
};
|
||||
|
||||
// initialise splitter (built on jquery)
|
||||
$().ready(function(){
|
||||
$("#frame").splitter({
|
||||
type: "v",
|
||||
outline: true,
|
||||
minLeft: 20,
|
||||
sizeLeft: 810,
|
||||
resizeToWidth: true,
|
||||
anchorToWindow: true,
|
||||
});
|
||||
$("#rightcolumn").splitter({
|
||||
type: "h",
|
||||
outline: true,
|
||||
sizeBottom: 180,
|
||||
minTop: 100,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="handleOnload();">
|
||||
<span id="plain">
|
||||
<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>
|
||||
<a href="http://github.com/trebonian/visual6502">Source</a>
|
||||
<a href="http://www.6502asm.com/">6502asm assembler</a>
|
||||
<a href="http://www.e-tradition.net/bytes/6502/disassembler.html">e-tradition disassembler</a>
|
||||
</span>
|
||||
<div class="frame" id="frame">
|
||||
<div class="leftcolumn" id="leftcolumn">
|
||||
<div id="chipsurround" tabindex="1">
|
||||
<div class="chip" id="chip">
|
||||
<span id="waiting">Please wait, graphics initialising...</span>
|
||||
<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> <!-- chipsurround -->
|
||||
<div class="nochip" id="nochip">
|
||||
<form>
|
||||
<input type="button" value="Show chip layout" onclick="updateChipLayoutVisibility(true)" />
|
||||
</form>
|
||||
</div>
|
||||
<div id="layoutControlPanel">
|
||||
Use 'z' or '>' to zoom in, 'x' or '<' to zoom out, click to probe signals and drag to pan.
|
||||
<form id="updateShow"> Show:
|
||||
<input type="checkbox" name="1" id="updateShow1" onchange="updateShow(this.name,this.checked)" />(diffusion)
|
||||
<input type="checkbox" name="3" id="updateShow3" onchange="updateShow(this.name,this.checked)" />(grounded diffusion)
|
||||
<input type="checkbox" name="4" id="updateShow4" onchange="updateShow(this.name,this.checked)" />(powered diffusion)
|
||||
<input type="checkbox" name="5" id="updateShow5" onchange="updateShow(this.name,this.checked)" />(polysilicon)
|
||||
<input type="checkbox" name="0" id="updateShow0" onchange="updateShow(this.name,this.checked)" />(metal)
|
||||
<input type="checkbox" name="2" id="updateShow2" onchange="updateShow(this.name,this.checked)" />(protection)
|
||||
</form>
|
||||
<form action="javascript:hiliteNodeList();">
|
||||
<input type="button" value="Find:" onclick="hiliteNodeList();" />
|
||||
<input type="text" id="HighlightThese" name="HighlightThese" value="" />
|
||||
<input type="button" value="Clear Highlighting" onclick="clearHighlight();" />
|
||||
<span class="animatebox">
|
||||
Animate during simulation:
|
||||
<input type="checkbox" id="animateModeCheckbox" onchange="updateChipLayoutAnimation(this.checked)"
|
||||
/></span>
|
||||
</form>
|
||||
<form>
|
||||
<input type="button" value="Hide Chip Layout" onclick="updateChipLayoutVisibility(false)" />
|
||||
<a href="" id="linkHere" >Link to this location</a>
|
||||
</form>
|
||||
</div>
|
||||
</div> <!-- closing leftcolumn -->
|
||||
<div class="rightcolumn" id="rightcolumn">
|
||||
<div id="righttopdiv">
|
||||
<div class = "buttons">
|
||||
<div class="twobuttons">
|
||||
<a href ="javascript:stopChip()" id="stop"><img class="navstop" src="images/stop.png" title="stop"></a>
|
||||
<a href ="javascript:runChip()" id="start"><img class="navplay" src="images/play.png" title="run"></a>
|
||||
</div>
|
||||
<div class="morebuttons">
|
||||
<a href ="javascript:resetChip()"><img class="navbutton" src="images/up.png" title="reset"></a>
|
||||
<a href ="javascript:stepBack()"><img class="navbutton" src="images/prev.png" title="back"></a>
|
||||
<a href ="javascript:stepForward()"><img class="navbutton" src="images/next.png" title="forward"></a>
|
||||
<a href ="javascript:goUntilSyncOrWrite()"><img class="navbutton" src="images/singlestep.png" title="step"></a>
|
||||
<a href ="javascript:goFor()"><img class="navbutton" src="images/fastforward.png" title="fastforward"></a>
|
||||
</div>
|
||||
<div style="float:right;">
|
||||
<a href="http://visual6502.org/wiki/index.php?title=JssimUserHelp" target="_blank">User Guide</a>
|
||||
|
||||
</div>
|
||||
</div> <!-- buttons -->
|
||||
<div class="status" id="status"><p>x: 0<br>y: 0</p>
|
||||
</div> <!-- status -->
|
||||
|
||||
<div id="memtablediv">
|
||||
<table class="memtable" id="memtable" tabindex="2"></table>
|
||||
</div>
|
||||
</div> <!-- righttopdiv -->
|
||||
|
||||
<div id="tracingdiv">
|
||||
<textarea id="consolebox">
|
||||
click here and type if your program handles input
|
||||
</textarea>
|
||||
<div id="expertControlPanel" tabindex="3">
|
||||
<form action="javascript:updateLogList()">
|
||||
<input type="button" value="Trace more" onclick="updateLoglevel(++loglevel)" />
|
||||
<input type="button" value="Trace less" onclick="updateLoglevel(--loglevel)" />
|
||||
<input type="button" value="Trace these too:" onclick="updateLogList()" />
|
||||
<input type="text" id="LogThese" name="LogThese" value="" />
|
||||
<input type="button" value="Log Up/Down" onclick="updateLogDirection();" />
|
||||
<input type="button" value="Clear Log" onclick="updateLoglevel(loglevel)" />
|
||||
</form>
|
||||
<br />
|
||||
</div>
|
||||
<div id="logstreamscroller">
|
||||
<table class="logstream" id="logstream"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- closing rightcolumn -->
|
||||
</div> <!-- closing 'frame' div -->
|
||||
</body>
|
||||
</html>
|
615
expertWires.js
Normal file
@ -0,0 +1,615 @@
|
||||
/*
|
||||
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 centerx=300, centery=300;
|
||||
var zoom=1;
|
||||
var dragMouseX, dragMouseY, moved;
|
||||
var statbox;
|
||||
var findThese;
|
||||
var labelThese=[];
|
||||
|
||||
// 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];
|
||||
|
||||
// some modes and parameters which can be passed in from the URL query
|
||||
var moveHereFirst;
|
||||
var expertMode=true;
|
||||
var animateChipLayout = true;
|
||||
var userCode=[];
|
||||
var userResetLow;
|
||||
var userResetHigh;
|
||||
var headlessSteps=1000;
|
||||
var noSimulation=false;
|
||||
var testprogram=[];
|
||||
var testprogramAddress;
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// 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');
|
||||
// load the circuit before acting on URL parameters
|
||||
setupNodes();
|
||||
setupTransistors();
|
||||
setupParams();
|
||||
setupExpertMode();
|
||||
detectOldBrowser();
|
||||
setStatus('loading graphics...');
|
||||
setTimeout(setup_part3, 0);
|
||||
}
|
||||
|
||||
function setup_part3(){
|
||||
if(chipLayoutIsVisible){
|
||||
// if user requests no chip layout, we can skip all canvas operations
|
||||
// which saves a lot of memory and allows us to run on small systems
|
||||
updateChipLayoutVisibility(true);
|
||||
}
|
||||
setStatus('resetting ' + chipname + '...');
|
||||
setTimeout(setup_part4, 0);
|
||||
}
|
||||
|
||||
function setup_part4(){
|
||||
setupTable();
|
||||
setupNodeNameList();
|
||||
logThese=signalSet(loglevel);
|
||||
loadProgram();
|
||||
setupConsole();
|
||||
if(noSimulation){
|
||||
stopChip();
|
||||
running=undefined;
|
||||
setStatus('Ready!');
|
||||
} else {
|
||||
initChip();
|
||||
document.getElementById('stop').style.visibility = 'hidden';
|
||||
go();
|
||||
}
|
||||
}
|
||||
|
||||
function detectOldBrowser(){
|
||||
if(!("getBoundingClientRect" in document.documentElement)){
|
||||
// simplify these functions (and adjust layout window position)
|
||||
localx= function(el, gx){
|
||||
return gx-el.offsetLeft;
|
||||
}
|
||||
localy= function(el, gy){
|
||||
return gy-el.offsetTop;
|
||||
}
|
||||
document.getElementById('plain').style["float"]="right";
|
||||
document.getElementById('chip').style.left=0;
|
||||
document.getElementById('chip').style.top=0;
|
||||
document.getElementById('chip').style.border=0;
|
||||
}
|
||||
}
|
||||
|
||||
function setupParams(){
|
||||
if(location.search=="")
|
||||
return
|
||||
var queryParts=location.search.slice(1).split('&');
|
||||
var panx;
|
||||
var pany;
|
||||
var zoom;
|
||||
var userAddress;
|
||||
for(var i=0;i<queryParts.length;i++){
|
||||
var params=queryParts[i].split("=");
|
||||
if(params.length!=2){
|
||||
if(loglevel>0)
|
||||
console.log('malformed parameters',params);
|
||||
break;
|
||||
}
|
||||
var name=params[0];
|
||||
var value=params[1].replace(/\/$/,""); // chrome sometimes adds trailing slash
|
||||
// be (relatively) forgiving in what we accept
|
||||
//
|
||||
// user interface mode control
|
||||
if(name=="loglevel" && parseInt(value)!=NaN){
|
||||
updateLoglevel(value);
|
||||
} else if(name=="logmore" && value!=""){
|
||||
updateLogList(value);
|
||||
} else if(name=="headlesssteps" && parseInt(value)!=NaN){
|
||||
headlessSteps=parseInt(value);
|
||||
} else if(name=="graphics" && value.indexOf("f")==0){
|
||||
updateChipLayoutVisibility(false);
|
||||
} else if(name=="canvas" && parseInt(value)!=NaN){
|
||||
grCanvasSize=value;
|
||||
// suppress simulation (for layout viewing only on slow browsers)
|
||||
} else if(name=="nosim" && value.indexOf("t")==0){
|
||||
noSimulation=true;
|
||||
} else
|
||||
// place the graphics window at a point of interest
|
||||
if(name=="panx" && parseInt(value)!=NaN){
|
||||
panx=parseInt(value);
|
||||
} else if(name=="pany" && parseInt(value)!=NaN){
|
||||
pany=parseInt(value);
|
||||
} else if(name=="zoom" && parseInt(value)!=NaN){
|
||||
zoom=parseInt(value);
|
||||
} else
|
||||
// perform a search, highlight and zoom to object(s)
|
||||
if(name=="find" && value.length>0){
|
||||
findThese=value;
|
||||
} else
|
||||
// affix label with optional box to highlight an area of interest
|
||||
if(name=="label" && value.length>0){
|
||||
labelThese.push(value.split(","));
|
||||
} else
|
||||
// load a test program: Address, Data and Reset
|
||||
if(name=="a" && parseInt(value,16)!=NaN){
|
||||
userAddress=parseInt(value,16);
|
||||
} else if(name=="d" && value.match(/[0-9a-fA-F]*/)[0].length==value.length){
|
||||
for(var j=0;j<value.length;j+=2)
|
||||
userCode[userAddress++]=parseInt(value.slice(j,j+2),16);
|
||||
} else if(name=="r" && parseInt(value,16)!=NaN){
|
||||
userResetLow=parseInt(value,16)%256;
|
||||
userResetHigh=(parseInt(value,16)>>8)%256;
|
||||
} else
|
||||
// setup input pin events, breakpoints, watchpoints
|
||||
if(name=="reset0" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]=[clockTriggers[value],"setLow(nodenamereset);"].join("");
|
||||
} else if(name=="reset1" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]=[clockTriggers[value],"setHigh(nodenamereset);"].join("");
|
||||
} else if(name=="irq0" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]=[clockTriggers[value],"setLow('irq');"].join("");
|
||||
} else if(name=="irq1" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]=[clockTriggers[value],"setHigh('irq');"].join("");
|
||||
} else if(name=="nmi0" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]=[clockTriggers[value],"setLow('nmi');"].join("");
|
||||
} else if(name=="nmi1" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]=[clockTriggers[value],"setHigh('nmi');"].join("");
|
||||
} else if(name=="rdy0" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]=[clockTriggers[value],"setLow('rdy');"].join("");
|
||||
} else if(name=="rdy1" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]=[clockTriggers[value],"setHigh('rdy');"].join("");
|
||||
} else if(name=="time" && parseInt(value)!=NaN){
|
||||
eventTime=value;
|
||||
} else if(name=="databus" && parseInt(value)!=NaN){
|
||||
clockTriggers[eventTime]=[clockTriggers[eventTime],"writeDataBus(0x"+value+");"].join("");
|
||||
} else
|
||||
// run a test program, and optionally check against a golden checksum
|
||||
if(name=="steps" && parseInt(value)!=NaN){
|
||||
userSteps=parseInt(value);
|
||||
running=true;
|
||||
} else if(name=="checksum" && parseInt(value,16)!=NaN){
|
||||
goldenChecksum=(0x100000000+parseInt(value,16)).toString(16).slice(-8);
|
||||
} else {
|
||||
if(loglevel>0)
|
||||
console.log('unrecognised parameters:',params);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(panx!=null && pany!=null && zoom!=null)
|
||||
moveHereFirst=[panx,pany,zoom];
|
||||
}
|
||||
|
||||
function updateChipLayoutAnimation(isOn){
|
||||
// simulation is much faster if we don't update the chip layout on every step
|
||||
animateChipLayout=isOn;
|
||||
document.getElementById('animateModeCheckbox').checked = animateChipLayout;
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// User Interface
|
||||
//
|
||||
/////////////////////////
|
||||
|
||||
|
||||
// these keyboard actions are primarily for the chip display
|
||||
function handleKey(e){
|
||||
var c = e.charCode || e.keyCode;
|
||||
c = String.fromCharCode(c);
|
||||
if('<>?npZzx'.indexOf(c)==-1) return;
|
||||
if((c=='Z'||c=='x'||c=='<') && zoom>1) setZoom(zoom/1.2);
|
||||
else if((c=='z'||c=='>') && zoom<grMaxZoom) setZoom(zoom*1.2);
|
||||
else if(c=='?') setZoom(1);
|
||||
// FIXME these keys are for the simulator (but not when focus is in a textbox)
|
||||
else if(c=='n') stepForward();
|
||||
else if(c=='p') stepBack();
|
||||
}
|
||||
|
||||
// handler for mousedown events over chip display
|
||||
// must handle click-to-select (and focus), and drag to pan
|
||||
function mouseDown(e){
|
||||
chipsurround.focus();
|
||||
e.preventDefault();
|
||||
moved=false;
|
||||
dragMouseX = e.clientX;
|
||||
dragMouseY = e.clientY;
|
||||
chipsurround.onmousemove = function(e){mouseMove(e)};
|
||||
chipsurround.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);
|
||||
chipsurround.onmousemove = undefined;
|
||||
chipsurround.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',
|
||||
});
|
||||
updateLinkHere();
|
||||
}
|
||||
|
||||
function updateLinkHere(){
|
||||
var target = location.pathname + "?nosim=t&";
|
||||
var findlist = document.getElementById('HighlightThese').value.split(/[\s,]+/).join(",");
|
||||
if (findlist != "")
|
||||
target = target + "find=" + findlist + "&";
|
||||
target = target + whereAmIAsQuery();
|
||||
document.getElementById('linkHere').href=target;
|
||||
}
|
||||
|
||||
// place a text label on the highlight layer
|
||||
// with an optional box around an area of interest
|
||||
// coordinates used are those reported by a click
|
||||
// for example:
|
||||
// boxLabel(['PD', 50, 8424, 3536, 9256, 2464])
|
||||
// boxLabel(['IR', 50, 8432, 2332, 9124, 984])
|
||||
// boxLabel(['PLA', 100, 1169, 2328, 8393, 934])
|
||||
// boxLabel(['Y', 50, 2143, 8820, 2317, 5689])
|
||||
// boxLabel(['X', 50, 2317, 8820, 2490, 5689])
|
||||
// boxLabel(['S', 50, 2490, 8820, 2814, 5689])
|
||||
// boxLabel(['ALU', 50, 2814, 8820, 4525, 5689])
|
||||
// boxLabel(['DAdj', 40, 4525, 8820, 5040, 5689])
|
||||
// boxLabel(['A', 50, 5040, 8820, 5328, 5689])
|
||||
// boxLabel(['PC', 50, 5559, 8820, 6819, 5689])
|
||||
// boxLabel(['ID', 50, 7365, 8820, 7676, 5689])
|
||||
// boxLabel(['TimC', 40, 600, 1926, 1174, 604])
|
||||
|
||||
function flashBoxLabel(args) {
|
||||
clearHighlight();
|
||||
var callBack = function(){boxLabel(args);};
|
||||
setTimeout(callBack, 400);
|
||||
setTimeout(clearHighlight, 800);
|
||||
setTimeout(callBack, 1200);
|
||||
}
|
||||
|
||||
function boxLabel(args) {
|
||||
var text = args[0];
|
||||
var textsize = args[1];
|
||||
var thickness = 1+ textsize / 20;
|
||||
var boxXmin = args[2] * grCanvasSize / grChipSize;
|
||||
var boxYmin = args[3] * grCanvasSize / grChipSize;
|
||||
var boxXmax = args[4] * grCanvasSize / grChipSize;
|
||||
var boxYmax = args[5] * grCanvasSize / grChipSize;
|
||||
ctx.lineWidth = thickness;
|
||||
ctx.font = textsize + 'px sans-serif';
|
||||
ctx.fillStyle = '#ff0'; // yellow
|
||||
ctx.fillStyle = '#f8f'; // magenta
|
||||
ctx.fillStyle = '#fff'; // white
|
||||
ctx.strokeStyle = '#fff'; // white
|
||||
if(args.length>4){
|
||||
ctxDrawBox(ctx, boxXmin, boxYmin, boxXmax, boxYmax);
|
||||
// offset the text label to the interior of the box
|
||||
boxYmin -= thickness * 2;
|
||||
}
|
||||
ctx.strokeStyle = '#fff'; // white
|
||||
ctx.strokeStyle = '#000'; // black
|
||||
ctx.lineWidth = thickness*2;
|
||||
ctx.strokeText(text, boxXmin, boxYmin);
|
||||
ctx.fillText(text, boxXmin, boxYmin);
|
||||
}
|
||||
|
||||
var highlightThese;
|
||||
|
||||
// flash some set of nodes according to user input
|
||||
// also zoom to fit those nodes (not presently optional)
|
||||
function hiliteNodeList(){
|
||||
var tmplist = document.getElementById('HighlightThese').value.split(/[\s,]+/);
|
||||
if(tmplist.join("").length==0){
|
||||
// request to highlight nothing, so switch off any signal highlighting
|
||||
hiliteNode(-1);
|
||||
return;
|
||||
}
|
||||
highlightThese = [];
|
||||
var seglist=[];
|
||||
var report="";
|
||||
for(var i=0;i<tmplist.length;i++){
|
||||
// get a node number from a signal name or a node number
|
||||
var name = tmplist[i];
|
||||
var value = parseInt(tmplist[i]);
|
||||
if((value!=NaN) && (typeof nodes[value] != "undefined")) {
|
||||
highlightThese.push(value);
|
||||
report="node: " + value + ' ' + nodeName(value);
|
||||
for(var s in nodes[value].segs)
|
||||
seglist.push(nodes[value].segs[s]);
|
||||
} else if(typeof nodenames[name] != "undefined") {
|
||||
highlightThese.push(nodenames[name]);
|
||||
report="node: " + nodenames[name] + ' ' + name;
|
||||
for(var s in nodes[nodenames[name]].segs)
|
||||
seglist.push(nodes[nodenames[name]].segs[s]);
|
||||
} else if(typeof transistors[name] != "undefined") {
|
||||
// normally we push numbers: a non-number is a transistor name
|
||||
highlightThese.push(name);
|
||||
report="transistor: " + name;
|
||||
seglist.push([
|
||||
transistors[name].bb[0],transistors[name].bb[2],
|
||||
transistors[name].bb[1],transistors[name].bb[3]
|
||||
]);
|
||||
} else {
|
||||
// allow match of underscore-delimited components, so
|
||||
// SUMS and dpc17 both match the node dpc17_SUMS
|
||||
for(var i in nodenames){
|
||||
re=new RegExp("(^" + name + "_|_" + name + "$)");
|
||||
if (re.test(i)){
|
||||
value = nodenames[i];
|
||||
highlightThese.push(value);
|
||||
report="node: " + value + ' ' + nodeName(value);
|
||||
for(var s in nodes[value].segs)
|
||||
seglist.push(nodes[value].segs[s]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(highlightThese.length==0){
|
||||
setStatus('Find: nothing found!','(Enter a list of nodenumbers, names or transistor names)');
|
||||
return;
|
||||
} else if (highlightThese.length==1){
|
||||
setStatus('Find results:',report);
|
||||
} else {
|
||||
setStatus('Find: multiple objects found','(' + highlightThese.length + ' objects)');
|
||||
}
|
||||
var xmin=seglist[0][0], xmax=seglist[0][0];
|
||||
var ymin=seglist[0][1], ymax=seglist[0][1];
|
||||
for(var s in seglist){
|
||||
for(var i=0;i<seglist[s].length;i+=2){
|
||||
if(seglist[s][i]<xmin) xmin=seglist[s][i];
|
||||
if(seglist[s][i]>xmax) xmax=seglist[s][i];
|
||||
if(seglist[s][i+1]<ymin) ymin=seglist[s][i+1];
|
||||
if(seglist[s][i+1]>ymax) ymax=seglist[s][i+1];
|
||||
}
|
||||
}
|
||||
zoomToBox(xmin,xmax,ymin,ymax);
|
||||
updateLinkHere();
|
||||
clearHighlight(); // nullify the simulation overlay (orange/purple)
|
||||
hiliteNode(-1); // unhighlight all nodes
|
||||
setTimeout("hiliteNode(highlightThese);", 400);
|
||||
setTimeout("hiliteNode(-1);", 800);
|
||||
setTimeout("hiliteNode(highlightThese);", 1200);
|
||||
}
|
||||
|
||||
// some notes on coordinates:
|
||||
// the localx and localy functions return canvas coordinate offsets from the canvas window top left corner
|
||||
// we divide the results by 'zoom' to get drawn coordinates useful in findNodeNumber
|
||||
// to convert to reported user chip coordinates we multiply by grChipSize/600
|
||||
// to compare to segdefs and transdefs coordinates we subtract 400 from x and subtract y from grChipSize
|
||||
|
||||
function handleClick(e){
|
||||
var x = localx(hilite, e.clientX)/zoom;
|
||||
var y = localy(hilite, e.clientY)/zoom;
|
||||
var w = findNodeNumber(x,y);
|
||||
// convert to chip coordinates
|
||||
var cx = Math.round(x*grChipSize/600);
|
||||
var cy = Math.round(y*grChipSize/600);
|
||||
// prepare two lines of status report
|
||||
var s1='x: ' + cx + ' y: ' + cy;
|
||||
var s2='node: ' + w + ' ' + nodeName(w);
|
||||
if(w==-1) {
|
||||
setStatus(s1); // no node found, so report only coordinates
|
||||
return;
|
||||
}
|
||||
// we have a node, but maybe we clicked over a transistor
|
||||
var nodelist=[w];
|
||||
// match the coordinate against transistor gate bounding boxes
|
||||
x=cx-400;
|
||||
y=grChipSize-cy;
|
||||
for(var i=0;i<nodes[w].gates.length;i++){
|
||||
var xmin=nodes[w].gates[i].bb[0], xmax=nodes[w].gates[i].bb[1];
|
||||
var ymin=nodes[w].gates[i].bb[2], ymax=nodes[w].gates[i].bb[3];
|
||||
if((x >= xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax)){
|
||||
// only one match at most, so we replace rather than push
|
||||
nodelist=[nodes[w].gates[i].name];
|
||||
s2='transistor: ' + nodes[w].gates[i].name + ' on ' + s2;
|
||||
}
|
||||
}
|
||||
// if this is a shift-click, just find and highlight the pass-connected group
|
||||
// and list the nodes (or nodenames, preferably)
|
||||
if(e.shiftKey) {
|
||||
getNodeGroup(w);
|
||||
nodelist = group;
|
||||
s2 = "nodegroup from " + s2 +
|
||||
" (nodes: " +
|
||||
group.map(function(x){return nodeName(x)?nodeName(x):x;}).join(",") +
|
||||
")";
|
||||
}
|
||||
hiliteNode(nodelist);
|
||||
setStatus(s1, s2);
|
||||
if(ctrace) console.log(s1, s2);
|
||||
}
|
||||
|
||||
function updateLoglevel(value){
|
||||
loglevel = value;
|
||||
logThese = signalSet(loglevel);
|
||||
initLogbox(logThese);
|
||||
}
|
||||
|
||||
function setupExpertMode(isOn){
|
||||
document.getElementById('expertControlPanel').style.display = 'block';
|
||||
if(loglevel==0)
|
||||
updateLoglevel(1);
|
||||
if(chipLayoutIsVisible)
|
||||
document.getElementById('layoutControlPanel').style.display = 'block';
|
||||
}
|
||||
|
||||
var consolegetc; // global variable to hold last keypress in the console area
|
||||
var consolebox;
|
||||
|
||||
function setupConsole(){
|
||||
consolebox=document.getElementById('consolebox');
|
||||
consolebox.onkeypress=function(e){consolegetc=e.charCode || e.keyCode;};
|
||||
}
|
||||
|
||||
var chipsurround;
|
||||
|
||||
function updateChipLayoutVisibility(isOn){
|
||||
chipLayoutIsVisible=isOn;
|
||||
if(chipLayoutIsVisible) {
|
||||
updateChipLayoutAnimation(true);
|
||||
// resize the two panes appropriately
|
||||
$("#frame").trigger("resize", [ 810 ]);
|
||||
$("#rightcolumn").trigger("resize", [ 738 - 180 ]);
|
||||
// replace the Show Chip button with the chip graphics
|
||||
chipsurround=document.getElementById('chipsurround');
|
||||
chipsurround.style.display = 'block';
|
||||
document.getElementById('layoutControlPanel').style.display = 'block';
|
||||
document.getElementById('nochip').style.display = 'none';
|
||||
// allow the browser to respond while we load the graphics
|
||||
setStatus('loading graphics...');
|
||||
setTimeout(setupChipLayoutGraphics, 0);
|
||||
} else {
|
||||
// cannot animate the layout if there is no canvas
|
||||
updateChipLayoutAnimation(false);
|
||||
// resize the two panes appropriately
|
||||
$("#frame").trigger("resize", [ 120 ]);
|
||||
$("#rightcolumn").trigger("resize", [ 200 ]);
|
||||
// replace the layout display with a button to show it
|
||||
document.getElementById('chipsurround').style.display = 'none';
|
||||
document.getElementById('layoutControlPanel').style.display = 'none';
|
||||
document.getElementById('nochip').style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
function setupChipLayoutGraphics(){
|
||||
setupLayerVisibility();
|
||||
setupBackground();
|
||||
setupOverlay();
|
||||
setupHilite();
|
||||
setupHitBuffer();
|
||||
recenter();
|
||||
refresh();
|
||||
document.getElementById('waiting').style.display = 'none';
|
||||
setStatus('Ready!'); // would prefer chipStatus but it's not idempotent
|
||||
// pre-fill the Find box if parameters supplied
|
||||
if(typeof findThese != "undefined") {
|
||||
document.getElementById('HighlightThese').value = findThese;
|
||||
hiliteNodeList(); // will pan and zoom to fit
|
||||
}
|
||||
// pre-pan and zoom if requested (will override any zoom-to-fit by hiliteNodeList)
|
||||
if(moveHereFirst!=null)
|
||||
moveHere(moveHereFirst);
|
||||
// draw any URL-requested labels and boxes
|
||||
if(labelThese.length>0) {
|
||||
for(var i=0;i<labelThese.length;i+=1)
|
||||
flashBoxLabel(labelThese[i]);
|
||||
}
|
||||
// grant focus to the chip display to enable zoom keys
|
||||
chipsurround.focus();
|
||||
chipsurround.onmousedown = function(e){mouseDown(e);};
|
||||
chipsurround.onkeypress = function(e){handleKey(e);};
|
||||
}
|
||||
|
||||
// utility function to save graphics pan and zoom
|
||||
function whereAmIAsQuery(){
|
||||
var w=whereAmI();
|
||||
return "panx="+w[0].toFixed(1)+"&pany="+w[1].toFixed(1)+"&zoom="+w[2].toFixed(1);
|
||||
}
|
||||
function whereAmI(){
|
||||
return [centerx, centery, zoom];
|
||||
}
|
||||
|
||||
// restore graphics pan and zoom (perhaps as given in the URL)
|
||||
function moveHere(place){
|
||||
centerx = place[0];
|
||||
centery = place[1];
|
||||
setZoom(place[2]);
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// 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];
|
||||
}
|
||||
}
|
BIN
images/fastforward.png
Normal file
After Width: | Height: | Size: 321 B |
BIN
images/jssim2.png
Executable file
After Width: | Height: | Size: 312 KiB |
BIN
images/singlestep.png
Normal file
After Width: | Height: | Size: 319 B |
90
index.html
@ -1,34 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<title>6502</title>
|
||||
<style type="text/css">@import "wires.css";</style>
|
||||
<title>Visual 6502 in JavaScript</title>
|
||||
|
||||
<!-- by default, index.html will run in kiosk mode -->
|
||||
<style type="text/css">@import "kiosk.css";</style>
|
||||
<script src="segdefs.js"></script>
|
||||
<script src="transdefs.js"></script>
|
||||
<script src="nodenames.js"></script>
|
||||
<script src="kioskWires.js"></script>
|
||||
<script src="wires.js"></script>
|
||||
<script src="chipsim.js"></script>
|
||||
<script src="memtable.js"></script>
|
||||
<script src="macros.js"></script>
|
||||
<script src="testprogram.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
function handleOnload() {
|
||||
// two checks and fixes here:
|
||||
// - replace the dynamic content with an image if running older versions of IE
|
||||
// - redirect to the expert page if we find any query parameters
|
||||
//
|
||||
/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{
|
||||
var suffix=location.search;
|
||||
var path=location.pathname;
|
||||
// ensure we always have a trailing slash
|
||||
path=path.replace("index.html","").replace(/\/?$/,"/");
|
||||
|
||||
if (suffix != "") {
|
||||
// redirect to the expert page
|
||||
var prefix=location.protocol+"//"+location.host+path;
|
||||
window.location.replace(prefix+"expert.html"+suffix);
|
||||
return;
|
||||
} else {
|
||||
// normal case: start the simulator
|
||||
setTimeout(setup,200);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="setTimeout(setup,200)">
|
||||
<body onload="handleOnload();">
|
||||
<br />
|
||||
<span id="title"><a href="/">The Visual 6502</a></span><br /><br />
|
||||
<span id="title"><a href="http://visual6502.org">The Visual 6502</a></span>
|
||||
<span id="plain">
|
||||
If the chip does not load, try another browser: Chrome, Safari, or Firefox
|
||||
<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 />
|
||||
Hit '>' to zoom in, '<' to zoom out
|
||||
<span id="browsertrouble"></span>
|
||||
<br />
|
||||
Right-click to scroll around
|
||||
Keyboard controls: 'z' to zoom in, 'x' to zoom out, 'n' to step the simulation.
|
||||
<br />
|
||||
Enter your own program into the array of RAM
|
||||
Mouse controls: Left-click and drag to scroll around (when you're zoomed in.)
|
||||
<br />
|
||||
More information in the <a href="http://visual6502.org/wiki/index.php?title=JssimUserHelp">User Guide<a>.
|
||||
<br />
|
||||
<br />
|
||||
</span>
|
||||
<div class="frame" id="frame">
|
||||
<div class="chip">
|
||||
<div class="chip" id="chip">
|
||||
<canvas class="chip" id="chipbg"></canvas>
|
||||
<canvas class="chip" id="overlay"></canvas>
|
||||
<canvas class="chip" id="hilite"></canvas>
|
||||
@ -44,21 +87,34 @@ Enter your own program into the array of RAM
|
||||
<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 style="float:right; margin-left:20px;">... or try <a href="expert.html">Advanced</a></div>
|
||||
</div>
|
||||
<p class="status" id="status">x: 0<br>y: 0</p>
|
||||
<table class="memtable" id="memtable"></table>
|
||||
</div>
|
||||
<div id="updateShow"> Show:
|
||||
<input type="checkbox" name="0" id="updateShow0" onchange="updateShow(this.name,this.checked)" />(metal)
|
||||
<input type="checkbox" name="1" id="updateShow1" onchange="updateShow(this.name,this.checked)" />(diff)
|
||||
<input type="checkbox" name="2" id="updateShow2" onchange="updateShow(this.name,this.checked)" />(diode)
|
||||
<input type="checkbox" name="3" id="updateShow3" onchange="updateShow(this.name,this.checked)" />(diff0)
|
||||
<input type="checkbox" name="4" id="updateShow4" onchange="updateShow(this.name,this.checked)" />(diff1)
|
||||
<input type="checkbox" name="5" id="updateShow5" onchange="updateShow(this.name,this.checked)" />(poly)
|
||||
<div id="updateShow">
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
In addition to this JavaScript project, see our <a href="../python6502.html">Python-based simulator</a> which may be easier to customize, verify, and apply to the study of long programs.<br />
|
||||
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="expert.html">Advanced</a> page.
|
||||
<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>
|
||||
|
@ -23,7 +23,8 @@
|
||||
body {
|
||||
background: white;
|
||||
color: black;
|
||||
font-family: cursive;
|
||||
/* font-family: cursive;*/
|
||||
font-family :Verdana, Arial, Helvetica, Sans-Serif;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@ -86,3 +87,8 @@ table.memtable {
|
||||
font-size: 12px;
|
||||
border-spacing: 0px;
|
||||
}
|
||||
|
||||
#title {
|
||||
font-size:30px;
|
||||
font-weight:bold;
|
||||
}
|
200
kioskWires.js
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
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 centerx=300, centery=300;
|
||||
var zoom=1;
|
||||
var dragMouseX, dragMouseY, moved;
|
||||
var statbox;
|
||||
var animateChipLayout = true;
|
||||
var userCode=[];
|
||||
var userResetLow;
|
||||
var userResetHigh;
|
||||
|
||||
// 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];
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// 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(){
|
||||
loadProgram();
|
||||
writeTriggers={}; // kiosk mode does not handle I/O
|
||||
initChip();
|
||||
document.getElementById('stop').style.visibility = 'hidden';
|
||||
go();
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// User Interface
|
||||
//
|
||||
/////////////////////////
|
||||
|
||||
function handleKey(e){
|
||||
var c = e.charCode || e.keyCode;
|
||||
c = String.fromCharCode(c);
|
||||
if('zx<>?np'.indexOf(c)==-1) return;
|
||||
if((c=='x' || c=='<') && zoom>1) setZoom(zoom/1.2);
|
||||
else if((c=='z' || 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) {
|
||||
getNodeGroup(w);
|
||||
hiliteNode(group);
|
||||
}
|
||||
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 {
|
||||
var s1='x: ' + cx + ' y: ' + cy;
|
||||
var s2='node: ' + w + ' ' + nodeName(w);
|
||||
setStatus(s1, s2);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//
|
||||
// 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];
|
||||
}
|
||||
}
|
604
macros.js
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman, Ed Spittles, Achim Breidenbach
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -21,30 +21,82 @@
|
||||
*/
|
||||
|
||||
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 logstream = Array();
|
||||
var running = false;
|
||||
var logThese=[];
|
||||
var chipname='6502';
|
||||
var nodenamereset='res';
|
||||
var presetLogLists=[
|
||||
['cycle'],
|
||||
['ab','db','rw','Fetch','pc','a','x','y','s','p'],
|
||||
['Execute','State'],
|
||||
['ir','tcstate','-pd'],
|
||||
['adl','adh','sb','alu'],
|
||||
['alucin','alua','alub','alucout','aluvout','dasb'],
|
||||
['plaOutputs','DPControl'],
|
||||
['idb','dor'],
|
||||
['irq','nmi',nodenamereset],
|
||||
];
|
||||
|
||||
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 loadProgram(){
|
||||
// a moderate size of static testprogram might be loaded
|
||||
if(testprogram.length!=0 && testprogramAddress != undefined)
|
||||
for(var i=0;testprogram[i]!=undefined;i++){
|
||||
var a=testprogramAddress+i;
|
||||
mWrite(a, testprogram[i]);
|
||||
if(a<0x200)
|
||||
setCellValue(a, testprogram[i]);
|
||||
}
|
||||
// a small test program or patch might be passed in the URL
|
||||
if(userCode.length!=0)
|
||||
for(var i=0;i<userCode.length;i++){
|
||||
if(userCode[i] != undefined){
|
||||
mWrite(i, userCode[i]);
|
||||
if(i<0x200)
|
||||
setCellValue(i, userCode[i]);
|
||||
}
|
||||
}
|
||||
// default reset vector will be 0x0000 because undefined memory reads as zero
|
||||
if(userResetLow!=undefined)
|
||||
mWrite(0xfffc, userResetLow);
|
||||
if(userResetHigh!=undefined)
|
||||
mWrite(0xfffd, userResetHigh);
|
||||
}
|
||||
|
||||
function steps(){
|
||||
function go(){
|
||||
if(typeof userSteps != "undefined"){
|
||||
if(--userSteps==0){
|
||||
running=false;
|
||||
userSteps=undefined;
|
||||
}
|
||||
}
|
||||
if(running) {
|
||||
step();
|
||||
setTimeout(steps, 0); // schedule the next poll
|
||||
setTimeout(go, 0); // schedule the next poll
|
||||
}
|
||||
}
|
||||
|
||||
function goUntilSync(){
|
||||
halfStep();
|
||||
while(!isNodeHigh(nodenames['sync']) || isNodeHigh(nodenames['clk0']))
|
||||
halfStep();
|
||||
}
|
||||
|
||||
function goUntilSyncOrWrite(){
|
||||
halfStep();
|
||||
cycle++;
|
||||
while(
|
||||
!isNodeHigh(nodenames['clk0']) ||
|
||||
( !isNodeHigh(nodenames['sync']) && isNodeHigh(nodenames['rw']) )
|
||||
) {
|
||||
halfStep();
|
||||
cycle++;
|
||||
}
|
||||
chipStatus();
|
||||
}
|
||||
|
||||
function testNMI(n){
|
||||
initChip();
|
||||
|
||||
@ -85,56 +137,117 @@ function testNMI(n){
|
||||
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 nn in nodes) {
|
||||
nodes[nn].state = false;
|
||||
nodes[nn].float = true;
|
||||
}
|
||||
|
||||
nodes[ngnd].state = false;
|
||||
nodes[ngnd].float = false;
|
||||
nodes[npwr].state = true;
|
||||
nodes[npwr].float = false;
|
||||
for(var tn in transistors) transistors[tn].on = false;
|
||||
setLow('res');
|
||||
setLow(nodenamereset);
|
||||
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();}
|
||||
setHigh(nodenamereset);
|
||||
for(var i=0;i<18;i++){halfStep();} // avoid updating graphics and trace buffer before user code
|
||||
refresh();
|
||||
cycle = 0;
|
||||
trace = Array();
|
||||
if(typeof expertMode != "undefined")
|
||||
updateLogList();
|
||||
chipStatus();
|
||||
console.log('initChip done after', now()-start);
|
||||
if(ctrace)console.log('initChip done after', now()-start);
|
||||
}
|
||||
|
||||
function signalSet(n){
|
||||
var signals=[];
|
||||
for (var i=0; (i<=n)&&(i<presetLogLists.length) ; i++){
|
||||
for (var j=0; j<presetLogLists[i].length; j++){
|
||||
signals.push(presetLogLists[i][j]);
|
||||
}
|
||||
}
|
||||
return signals;
|
||||
}
|
||||
|
||||
function updateLogList(names){
|
||||
// user supplied a list of signals, which we append to the set defined by loglevel
|
||||
logThese = signalSet(loglevel);
|
||||
if(typeof names == "undefined")
|
||||
// this is a UI call - read the text input
|
||||
names = document.getElementById('LogThese').value;
|
||||
else
|
||||
// this is an URL call - update the text input box
|
||||
document.getElementById('LogThese').value = names;
|
||||
names = names.split(/[\s,]+/);
|
||||
for(var i=0;i<names.length;i++){
|
||||
// could be a signal name, a node number, or a special name
|
||||
if(typeof busToString(names[i]) != "undefined")
|
||||
logThese.push(names[i]);
|
||||
}
|
||||
initLogbox(logThese);
|
||||
}
|
||||
|
||||
var traceChecksum='';
|
||||
var goldenChecksum;
|
||||
|
||||
// simulate a single clock phase, updating trace and highlighting layout
|
||||
function step(){
|
||||
trace[cycle]= {chip: stateString(), mem: getMem()};
|
||||
var s=stateString();
|
||||
var m=getMem();
|
||||
trace[cycle]= {chip: s, mem: m};
|
||||
if(goldenChecksum != undefined)
|
||||
traceChecksum=adler32(traceChecksum+s+m.slice(0,511).toString(16));
|
||||
halfStep();
|
||||
if(animateChipLayout)
|
||||
refresh();
|
||||
cycle++;
|
||||
chipStatus();
|
||||
}
|
||||
|
||||
// triggers for breakpoints, watchpoints, input pin events
|
||||
// almost always are undefined when tested, so minimal impact on performance
|
||||
clockTriggers={};
|
||||
writeTriggers={};
|
||||
readTriggers={};
|
||||
fetchTriggers={};
|
||||
|
||||
// example instruction tracing triggers
|
||||
// fetchTriggers[0x20]="console.log('0x'+readAddressBus().toString(16)+': JSR');";
|
||||
// fetchTriggers[0x60]="console.log('0x'+readAddressBus().toString(16)+': RTS');";
|
||||
// fetchTriggers[0x4c]="console.log('0x'+readAddressBus().toString(16)+': JMP');";
|
||||
|
||||
// simulate a single clock phase with no update to graphics or trace
|
||||
function halfStep(){
|
||||
var clk = isNodeHigh(nodenames['clk0']);
|
||||
eval(clockTriggers[cycle]);
|
||||
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()));
|
||||
if(isNodeHigh(nodenames['rw'])){
|
||||
var a = readAddressBus();
|
||||
var d = eval(readTriggers[a]);
|
||||
if(d == undefined)
|
||||
d = mRead(readAddressBus());
|
||||
if(isNodeHigh(nodenames['sync']))
|
||||
eval(fetchTriggers[d]);
|
||||
writeDataBus(d);
|
||||
}
|
||||
}
|
||||
|
||||
function handleBusWrite(){
|
||||
if(!isNodeHigh(nodenames['rw'])){
|
||||
var a = readAddressBus();
|
||||
var d = readDataBus();
|
||||
eval(writeTriggers[a]);
|
||||
mWrite(a,d);
|
||||
if(a<0x200) setCellValue(a,d);
|
||||
}
|
||||
@ -150,8 +263,8 @@ function readPstring(){
|
||||
var result;
|
||||
result = (isNodeHigh(nodenames['p7'])?'N':'n') +
|
||||
(isNodeHigh(nodenames['p6'])?'V':'v') +
|
||||
'-' +
|
||||
(isNodeHigh(nodenames['p3'])?'B':'b') +
|
||||
'‑' + // non-breaking hyphen
|
||||
(isNodeHigh(nodenames['p4'])?'B':'b') +
|
||||
(isNodeHigh(nodenames['p3'])?'D':'d') +
|
||||
(isNodeHigh(nodenames['p2'])?'I':'i') +
|
||||
(isNodeHigh(nodenames['p1'])?'Z':'z') +
|
||||
@ -163,6 +276,33 @@ function readPC(){return (readBits('pch', 8)<<8) + readBits('pcl', 8);}
|
||||
function readPCL(){return readBits('pcl', 8);}
|
||||
function readPCH(){return readBits('pch', 8);}
|
||||
|
||||
// for one-hot or few-hot signal collections we want to list the active ones
|
||||
// and for brevity we remove the common prefix
|
||||
function listActiveSignals(pattern){
|
||||
var r=new RegExp(pattern);
|
||||
var list=[];
|
||||
for(var i in nodenamelist){
|
||||
if(r.test(nodenamelist[i])) {
|
||||
if(isNodeHigh(nodenames[nodenamelist[i]]))
|
||||
// also map hyphen to a non-breaking version
|
||||
list.push(nodenamelist[i].replace(r,'').replace(/-/g,'‑'));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// The 6502 TCState is almost but not quite an inverted one-hot shift register
|
||||
function listActiveTCStates() {
|
||||
var s=[];
|
||||
if(!isNodeHigh(nodenames['clock1'])) s.push("T0");
|
||||
if(!isNodeHigh(nodenames['clock2'])) s.push("T1");
|
||||
if(!isNodeHigh(nodenames['t2'])) s.push("T2");
|
||||
if(!isNodeHigh(nodenames['t3'])) s.push("T3");
|
||||
if(!isNodeHigh(nodenames['t4'])) s.push("T4");
|
||||
if(!isNodeHigh(nodenames['t5'])) s.push("T5");
|
||||
return s.join("+");
|
||||
}
|
||||
|
||||
function readBit(name){
|
||||
return isNodeHigh(nodenames[name])?1:0;
|
||||
}
|
||||
@ -175,6 +315,65 @@ function readBits(name, n){
|
||||
return res;
|
||||
}
|
||||
|
||||
function busToString(busname){
|
||||
// takes a signal name or prefix
|
||||
// returns an appropriate string representation
|
||||
// some 'signal names' are CPU-specific aliases to user-friendly string output
|
||||
if(busname=='cycle')
|
||||
return cycle>>1;
|
||||
if(busname=='pc')
|
||||
return busToHex('pch') + busToHex('pcl');
|
||||
if(busname=='p')
|
||||
return readPstring();
|
||||
if(busname=='tcstate')
|
||||
return ['clock1','clock2','t2','t3','t4','t5'].map(busToHex).join("");
|
||||
if(busname=='State')
|
||||
return listActiveTCStates();
|
||||
if(busname=='Execute')
|
||||
return disassemblytoHTML(readBits('ir',8));
|
||||
if(busname=='Fetch')
|
||||
return isNodeHigh(nodenames['sync'])?disassemblytoHTML(readDataBus()):"";
|
||||
if(busname=='plaOutputs')
|
||||
// PLA outputs are mostly ^op- but some have a prefix too
|
||||
// - we'll allow the x and xx prefix but ignore the #
|
||||
return listActiveSignals('^([x]?x-)?op-');
|
||||
if(busname=='DPControl')
|
||||
return listActiveSignals('^dpc[0-9]+_');
|
||||
if(busname[0]=="-"){
|
||||
// invert the value of the bus for display
|
||||
var value=busToHex(busname.slice(1))
|
||||
if(typeof value != "undefined")
|
||||
return value.replace(/./g,function(x){return (15-parseInt(x,16)).toString(16)});
|
||||
else
|
||||
return undefined;;
|
||||
} else {
|
||||
return busToHex(busname);
|
||||
}
|
||||
}
|
||||
|
||||
function busToHex(busname){
|
||||
// may be passed a bus or a signal, so allow multiple signals
|
||||
var width=0;
|
||||
var r=new RegExp('^' + busname + '[0-9]+$');
|
||||
for(var i in nodenamelist){
|
||||
if(r.test(nodenamelist[i])) {
|
||||
width++;
|
||||
}
|
||||
}
|
||||
if(width==0) {
|
||||
// not a bus, so could be a signal, a nodenumber or a mistake
|
||||
if(typeof nodenames[busname] != "undefined")
|
||||
return isNodeHigh(nodenames[busname])?"1":"0";
|
||||
if((parseInt(busname)!=NaN) && (typeof nodes[busname] != "undefined"))
|
||||
return isNodeHigh(busname)?"1":"0";
|
||||
return undefined;
|
||||
}
|
||||
if(width>16)
|
||||
return undefined;
|
||||
// finally, convert from logic values to hex
|
||||
return (0x10000+readBits(busname,width)).toString(16).slice(-(width-1)/4-1);
|
||||
}
|
||||
|
||||
function writeDataBus(x){
|
||||
var recalcs = Array();
|
||||
for(var i=0;i<8;i++){
|
||||
@ -195,12 +394,11 @@ function mRead(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]];
|
||||
var t = nodes[943].gates[i];
|
||||
if(t.c1==npwr) res.push(t.c2);
|
||||
if(t.c2==npwr) res.push(t.c1);
|
||||
}
|
||||
@ -212,8 +410,10 @@ function runChip(){
|
||||
var stop = document.getElementById('stop');
|
||||
start.style.visibility = 'hidden';
|
||||
stop.style.visibility = 'visible';
|
||||
if(typeof running == "undefined")
|
||||
initChip();
|
||||
running = true;
|
||||
steps();
|
||||
go();
|
||||
}
|
||||
|
||||
function stopChip(){
|
||||
@ -226,11 +426,13 @@ function stopChip(){
|
||||
|
||||
function resetChip(){
|
||||
stopChip();
|
||||
setStatus('resetting 6502...');
|
||||
setStatus('resetting ' + chipname + '...');
|
||||
setTimeout(initChip,0);
|
||||
}
|
||||
|
||||
function stepForward(){
|
||||
if(typeof running == "undefined")
|
||||
initChip();
|
||||
stopChip();
|
||||
step();
|
||||
}
|
||||
@ -259,28 +461,146 @@ function chipStatus(){
|
||||
' Y:' + hexByte(readY()) +
|
||||
' SP:' + hexByte(readSP()) +
|
||||
' ' + readPstring();
|
||||
var machine3 =
|
||||
' Sync:' + readBit('sync')
|
||||
' IRQ:' + readBit('irq') +
|
||||
' NMI:' + readBit('nmi');
|
||||
var machine4 =
|
||||
' IR:' + hexByte(255 - readBits('notir', 8)) +
|
||||
' idl:' + hexByte(255 - readBits('idl', 8)) +
|
||||
' alu:' + hexByte(255 - readBits('alu', 8)) +
|
||||
' TCstate:' + readBit('clock1') + readBit('clock2') +
|
||||
readBit('t2') + readBit('t3') + readBit('t4') + readBit('t5');
|
||||
var machine5 =
|
||||
' notRdy0:' + readBit('notRdy0') +
|
||||
' fetch:' + readBit('fetch') +
|
||||
' clearIR:' + readBit('clearIR') +
|
||||
' D1x1:' + readBit('D1x1');
|
||||
setStatus(machine1 + "<br>" + machine2);
|
||||
if (loglevel>2) {
|
||||
console.log(machine1 + " " + machine2 + " " + machine3 + " " + machine4 + " " + machine5);
|
||||
var machine3 =
|
||||
'Hz: ' + estimatedHz().toFixed(1);
|
||||
if(typeof expertMode != "undefined") {
|
||||
machine3 += ' Exec: ' + busToString('Execute') + '(' + busToString('State') + ')';
|
||||
if(isNodeHigh(nodenames['sync']))
|
||||
machine3 += ' (Fetch: ' + busToString('Fetch') + ')';
|
||||
if(goldenChecksum != undefined)
|
||||
machine3 += " Chk:" + traceChecksum + ((traceChecksum==goldenChecksum)?" OK":" no match");
|
||||
}
|
||||
setStatus(machine1, machine2, machine3);
|
||||
if (loglevel>0) {
|
||||
updateLogbox(logThese);
|
||||
}
|
||||
selectCell(ab);
|
||||
}
|
||||
|
||||
// run for an extended number of cycles, with low overhead, for interactive programs or for benchmarking
|
||||
// note: to run an interactive program, use an URL like
|
||||
// http://visual6502.org/JSSim/expert.html?graphics=f&loglevel=-1&headlesssteps=-500
|
||||
function goFor(){
|
||||
var n = headlessSteps; // a negative value is a request to free-run
|
||||
if(headlessSteps<0)
|
||||
n=-n;
|
||||
var start = document.getElementById('start');
|
||||
var stop = document.getElementById('stop');
|
||||
start.style.visibility = 'hidden';
|
||||
stop.style.visibility = 'visible';
|
||||
if(typeof running == "undefined") {
|
||||
initChip();
|
||||
}
|
||||
running = true;
|
||||
setTimeout("instantaneousHz(); goForN("+n+")",0);
|
||||
}
|
||||
|
||||
// helper function: allows us to poll 'running' without resetting it when we're re-scheduled
|
||||
function goForN(n){
|
||||
var n2=n; // save our parameter so we can re-submit ourselves
|
||||
while(n--){
|
||||
halfStep();
|
||||
cycle++;
|
||||
}
|
||||
instantaneousHz();
|
||||
chipStatus();
|
||||
if((headlessSteps<0) && running){
|
||||
setTimeout("goForN("+n2+")",0); // re-submit ourselves if we are meant to free-run
|
||||
return;
|
||||
}
|
||||
running = false;
|
||||
start.style.visibility = 'visible';
|
||||
stop.style.visibility = 'hidden';
|
||||
}
|
||||
|
||||
var prevHzTimeStamp=0;
|
||||
var prevHzCycleCount=0;
|
||||
var prevHzEstimate1=1;
|
||||
var prevHzEstimate2=1;
|
||||
var HzSamplingRate=10;
|
||||
|
||||
// return an averaged speed: called periodically during normal running
|
||||
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
|
||||
}
|
||||
|
||||
// return instantaneous speed: called twice, before and after a timed run using goFor()
|
||||
function instantaneousHz(){
|
||||
var HzTimeStamp = now();
|
||||
var HzEstimate = (cycle-prevHzCycleCount+.01)/(HzTimeStamp-prevHzTimeStamp+.01);
|
||||
HzEstimate=HzEstimate*1000/2; // convert from phases per millisecond to Hz
|
||||
prevHzEstimate1=HzEstimate;
|
||||
prevHzEstimate2=prevHzEstimate1;
|
||||
prevHzTimeStamp=HzTimeStamp;
|
||||
prevHzCycleCount=cycle;
|
||||
return prevHzEstimate1
|
||||
}
|
||||
|
||||
var logbox;
|
||||
function initLogbox(names){
|
||||
logbox=document.getElementById('logstream');
|
||||
if(logbox==null)return;
|
||||
|
||||
names=names.map(function(x){return x.replace(/^-/,'')});
|
||||
logStream = [];
|
||||
logStream.push("<td class=header>" + names.join("</td><td class=header>") + "</td>");
|
||||
logbox.innerHTML = "<tr>"+logStream.join("</tr><tr>")+"</tr>";
|
||||
}
|
||||
|
||||
var logboxAppend=true;
|
||||
|
||||
// can append or prepend new states to the log table
|
||||
// when we reverse direction we need to reorder the log stream
|
||||
function updateLogDirection(){
|
||||
var loglines=[];
|
||||
logboxAppend=!logboxAppend;
|
||||
// the first element is the header so we can't reverse()
|
||||
for (var i=1;i<logStream.length;i++) {
|
||||
loglines.unshift(logStream[i]);
|
||||
}
|
||||
loglines.unshift(logStream[0]);
|
||||
logStream=loglines;
|
||||
logbox.innerHTML = "<tr>"+logStream.join("</tr><tr>")+"</tr>";
|
||||
}
|
||||
|
||||
// update the table of signal values, by prepending or appending
|
||||
function updateLogbox(names){
|
||||
var signals=[];
|
||||
var odd=true;
|
||||
var bg;
|
||||
var row;
|
||||
|
||||
for(var i in names){
|
||||
if(cycle % 4 < 2){
|
||||
bg = odd ? " class=oddcol":"";
|
||||
} else {
|
||||
bg = odd ? " class=oddrow":" class=oddrowcol";
|
||||
}
|
||||
signals.push("<td" + bg + ">" + busToString(names[i]) + "</td>");
|
||||
odd =! odd;
|
||||
}
|
||||
row = "<tr>" + signals.join("") + "</tr>";
|
||||
if(logboxAppend)
|
||||
logStream.push(row);
|
||||
else
|
||||
logStream.splice(1,0,row);
|
||||
|
||||
logbox.innerHTML = logStream.join("");
|
||||
}
|
||||
|
||||
function getMem(){
|
||||
var res = Array();
|
||||
for(var i=0;i<0x200;i++) res.push(mRead(i));
|
||||
@ -293,3 +613,177 @@ function setMem(arr){
|
||||
|
||||
function hexWord(n){return (0x10000+n).toString(16).substring(1)}
|
||||
function hexByte(n){return (0x100+n).toString(16).substring(1)}
|
||||
|
||||
function adler32(x){
|
||||
var a=1;
|
||||
var b=0;
|
||||
for(var i=0;i<x.length;i++){
|
||||
a=(a+x.charCodeAt(i))%65521;
|
||||
b=(b+a)%65521;
|
||||
}
|
||||
return (0x100000000+(b<<16)+a).toString(16).slice(-8);
|
||||
}
|
||||
|
||||
// sanitised opcode for HTML output
|
||||
function disassemblytoHTML(byte){
|
||||
var opcode=disassembly[byte];
|
||||
if(typeof opcode == "undefined")
|
||||
return "unknown"
|
||||
return opcode.replace(/ /,' ');
|
||||
}
|
||||
|
||||
// opcode lookup for 6502 - not quite a disassembly
|
||||
// javascript derived from Debugger.java by Achim Breidenbach
|
||||
var disassembly={
|
||||
0x00:"BRK",
|
||||
0x01:"ORA (zp,X)",
|
||||
0x05:"ORA zp",
|
||||
0x06:"ASL zp",
|
||||
0x08:"PHP",
|
||||
0x09:"ORA #",
|
||||
0x0A:"ASL ",
|
||||
0x0D:"ORA Abs",
|
||||
0x0E:"ASL Abs",
|
||||
0x10:"BPL ",
|
||||
0x11:"ORA (zp),Y",
|
||||
0x15:"ORA zp,X",
|
||||
0x16:"ASL zp,X",
|
||||
0x18:"CLC",
|
||||
0x19:"ORA Abs,Y",
|
||||
0x1D:"ORA Abs,X",
|
||||
0x1E:"ASL Abs,X",
|
||||
0x20:"JSR Abs",
|
||||
0x21:"AND (zp,X)",
|
||||
0x24:"BIT zp",
|
||||
0x25:"AND zp",
|
||||
0x26:"ROL zp",
|
||||
0x28:"PLP",
|
||||
0x29:"AND #",
|
||||
0x2A:"ROL ",
|
||||
0x2C:"BIT Abs",
|
||||
0x2D:"AND Abs",
|
||||
0x2E:"ROL Abs",
|
||||
0x30:"BMI ",
|
||||
0x31:"AND (zp),Y",
|
||||
0x35:"AND zp,X",
|
||||
0x36:"ROL zp,X",
|
||||
0x38:"SEC",
|
||||
0x39:"AND Abs,Y",
|
||||
0x3D:"AND Abs,X",
|
||||
0x3E:"ROL Abs,X",
|
||||
0x40:"RTI",
|
||||
0x41:"EOR (zp,X)",
|
||||
0x45:"EOR zp",
|
||||
0x46:"LSR zp",
|
||||
0x48:"PHA",
|
||||
0x49:"EOR #",
|
||||
0x4A:"LSR ",
|
||||
0x4C:"JMP Abs",
|
||||
0x4D:"EOR Abs",
|
||||
0x4E:"LSR Abs",
|
||||
0x50:"BVC ",
|
||||
0x51:"EOR (zp),Y",
|
||||
0x55:"EOR zp,X",
|
||||
0x56:"LSR zp,X",
|
||||
0x58:"CLI",
|
||||
0x59:"EOR Abs,Y",
|
||||
0x5D:"EOR Abs,X",
|
||||
0x5E:"LSR Abs,X",
|
||||
0x60:"RTS",
|
||||
0x61:"ADC (zp,X)",
|
||||
0x65:"ADC zp",
|
||||
0x66:"ROR zp",
|
||||
0x68:"PLA",
|
||||
0x69:"ADC #",
|
||||
0x6A:"ROR ",
|
||||
0x6C:"JMP zp",
|
||||
0x6D:"ADC Abs",
|
||||
0x6E:"ROR Abs",
|
||||
0x70:"BVS ",
|
||||
0x71:"ADC (zp),Y",
|
||||
0x75:"ADC zp,X",
|
||||
0x76:"ROR zp,X",
|
||||
0x78:"SEI",
|
||||
0x79:"ADC Abs,Y",
|
||||
0x7D:"ADC Abs,X",
|
||||
0x7E:"ROR Abs,X",
|
||||
0x81:"STA (zp,X)",
|
||||
0x84:"STY zp",
|
||||
0x85:"STA zp",
|
||||
0x86:"STX zp",
|
||||
0x88:"DEY",
|
||||
0x8A:"TXA",
|
||||
0x8C:"STY Abs",
|
||||
0x8D:"STA Abs",
|
||||
0x8E:"STX Abs",
|
||||
0x90:"BCC ",
|
||||
0x91:"STA (zp),Y",
|
||||
0x94:"STY zp,X",
|
||||
0x95:"STA zp,X",
|
||||
0x96:"STX zp,Y",
|
||||
0x98:"TYA",
|
||||
0x99:"STA Abs,Y",
|
||||
0x9A:"TXS",
|
||||
0x9D:"STA Abs,X",
|
||||
0xA0:"LDY #",
|
||||
0xA1:"LDA (zp,X)",
|
||||
0xA2:"LDX #",
|
||||
0xA4:"LDY zp",
|
||||
0xA5:"LDA zp",
|
||||
0xA6:"LDX zp",
|
||||
0xA8:"TAY",
|
||||
0xA9:"LDA #",
|
||||
0xAA:"TAX",
|
||||
0xAC:"LDY Abs",
|
||||
0xAD:"LDA Abs",
|
||||
0xAE:"LDX Abs",
|
||||
0xB0:"BCS ",
|
||||
0xB1:"LDA (zp),Y",
|
||||
0xB4:"LDY zp,X",
|
||||
0xB5:"LDA zp,X",
|
||||
0xB6:"LDX zp,Y",
|
||||
0xB8:"CLV",
|
||||
0xB9:"LDA Abs,Y",
|
||||
0xBA:"TSX",
|
||||
0xBC:"LDY Abs,X",
|
||||
0xBD:"LDA Abs,X",
|
||||
0xBE:"LDX Abs,Y",
|
||||
0xC0:"CPY #",
|
||||
0xC1:"CMP (zp,X)",
|
||||
0xC4:"CPY zp",
|
||||
0xC5:"CMP zp",
|
||||
0xC6:"DEC zp",
|
||||
0xC8:"INY",
|
||||
0xC9:"CMP #",
|
||||
0xCA:"DEX",
|
||||
0xCC:"CPY Abs",
|
||||
0xCD:"CMP Abs",
|
||||
0xCE:"DEC Abs",
|
||||
0xD0:"BNE ",
|
||||
0xD1:"CMP (zp),Y",
|
||||
0xD5:"CMP zp,X",
|
||||
0xD6:"DEC zp,X",
|
||||
0xD8:"CLD",
|
||||
0xD9:"CMP Abs,Y",
|
||||
0xDD:"CMP Abs,X",
|
||||
0xDE:"DEC Abs,X",
|
||||
0xE0:"CPX #",
|
||||
0xE1:"SBC (zp,X)",
|
||||
0xE4:"CPX zp",
|
||||
0xE5:"SBC zp",
|
||||
0xE6:"INC zp",
|
||||
0xE8:"INX",
|
||||
0xE9:"SBC #",
|
||||
0xEA:"NOP",
|
||||
0xEC:"CPX Abs",
|
||||
0xED:"SBC Abs",
|
||||
0xEE:"INC Abs",
|
||||
0xF0:"BEQ ",
|
||||
0xF1:"SBC (zp),Y",
|
||||
0xF5:"SBC zp,X",
|
||||
0xF6:"INC zp,X",
|
||||
0xF8:"SED",
|
||||
0xF9:"SBC Abs,Y",
|
||||
0xFD:"SBC Abs,X",
|
||||
0xFE:"INC Abs,X",
|
||||
};
|
||||
|
@ -59,7 +59,9 @@ function cellKeydown(e){
|
||||
}
|
||||
|
||||
function setCellValue(n, val){
|
||||
val%=256;
|
||||
if(val==undefined)
|
||||
val=0x00;
|
||||
val%=256;
|
||||
cellEl(n).val=val;
|
||||
cellEl(n).innerHTML=hexByte(val);
|
||||
}
|
||||
@ -71,7 +73,7 @@ function selectCell(n){
|
||||
if(n>=0x200) return;
|
||||
cellEl(n).style.background = '#ff8';
|
||||
selected = n;
|
||||
window.onkeydown = function(e){cellKeydown(e);};
|
||||
table.onkeydown = function(e){cellKeydown(e);};
|
||||
}
|
||||
|
||||
function unselectCell(){
|
||||
@ -84,6 +86,6 @@ function unselectCell(){
|
||||
function cellEl(n){
|
||||
var r = n>>4;
|
||||
var c = n%16;
|
||||
var e = table.children[r].children[c+1];
|
||||
var e = table.childNodes[r].childNodes[c+1];
|
||||
return e;
|
||||
}
|
||||
|
896
nodenames.js
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman, Ed Spittles, Segher Boessenkool
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -21,89 +21,19 @@
|
||||
*/
|
||||
|
||||
var nodenames ={
|
||||
res: 159, // pads: reset
|
||||
rw: 1156, // pads: read not write
|
||||
db0: 1005, // pads: databus
|
||||
db1: 82,
|
||||
db0: 1005,
|
||||
db3: 650,
|
||||
db2: 945,
|
||||
db5: 175,
|
||||
db4: 1393,
|
||||
db7: 1349,
|
||||
db6: 1591,
|
||||
idl0: 116,
|
||||
idl1: 576,
|
||||
idl2: 1485,
|
||||
idl3: 1284,
|
||||
idl4: 1516,
|
||||
idl5: 498,
|
||||
idl6: 1537,
|
||||
idl7: 529,
|
||||
a1: 1234,
|
||||
ab0: 268, // pads: address bus
|
||||
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,
|
||||
nots0: 418,
|
||||
nots1: 1064,
|
||||
nots2: 752,
|
||||
nots3: 828,
|
||||
nots4: 1603,
|
||||
nots5: 601,
|
||||
nots6: 1029,
|
||||
nots7: 181,
|
||||
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,
|
||||
@ -111,69 +41,187 @@ 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,
|
||||
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,
|
||||
y0: 64,
|
||||
y3: 305,
|
||||
y2: 573,
|
||||
y5: 615,
|
||||
y3: 305,
|
||||
y4: 989,
|
||||
y7: 843,
|
||||
y5: 615,
|
||||
y6: 115,
|
||||
cclk: 943, // aka cp2
|
||||
clock1: 156,
|
||||
clock2: 1536,
|
||||
notir7: 1320,
|
||||
notir6: 895, // OK
|
||||
notir5: 1394, // OK
|
||||
notir4: 26,
|
||||
notir3: 1125,
|
||||
notir2: 1182,
|
||||
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 output)
|
||||
pcl1: 1022,
|
||||
pcl2: 655,
|
||||
pcl3: 1359,
|
||||
pcl4: 900,
|
||||
pcl5: 622,
|
||||
pcl6: 377,
|
||||
pcl7: 1611,
|
||||
pclp0: 488, // machine state: program counter low (pre-incremented?, second storage node)
|
||||
pclp1: 976,
|
||||
pclp2: 481,
|
||||
pclp3: 723,
|
||||
pclp4: 208,
|
||||
pclp5: 72,
|
||||
pclp6: 1458,
|
||||
pclp7: 1647,
|
||||
"#pclp0": 1227, // machine state: program counter low (pre-incremented?, inverse second storage node)
|
||||
"#pclp1": 1102,
|
||||
"#pclp2": 1079,
|
||||
"#pclp3": 868,
|
||||
"#pclp4": 39,
|
||||
"#pclp5": 1326,
|
||||
"#pclp6": 731,
|
||||
"#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: 1722, // machine state: program counter high (pre-incremented?, second storage node output)
|
||||
pchp1: 209,
|
||||
pchp2: 1496,
|
||||
pchp3: 141,
|
||||
pchp4: 27,
|
||||
pchp5: 1301,
|
||||
pchp6: 652,
|
||||
pchp7: 1206,
|
||||
"#pchp0": 780, // machine state: program counter high (pre-incremented?, inverse second storage node)
|
||||
"#pchp1": 113,
|
||||
"#pchp2": 114,
|
||||
"#pchp3": 124,
|
||||
"#pchp4": 820,
|
||||
"#pchp5": 33,
|
||||
"#pchp6": 751,
|
||||
"#pchp7": 535,
|
||||
// machine state: status register (not the storage nodes)
|
||||
p0: 32, // C bit of status register (storage node)
|
||||
p1: 627, // Z bit of status register (storage node)
|
||||
p2: 1553, // I bit of status register (storage node)
|
||||
p3: 348, // D bit of status register (storage node)
|
||||
p4: 1119, // there is no bit4 in the status register! (not a storage node)
|
||||
p5: -1, // there is no bit5 in the status register! (not a storage node)
|
||||
p6: 77, // V bit of status register (storage node)
|
||||
p7: 1370, // N bit of status register (storage node)
|
||||
|
||||
// internal bus: status register outputs for push P
|
||||
Pout0: 687,
|
||||
Pout1: 1444,
|
||||
Pout2: 1421,
|
||||
Pout3: 439,
|
||||
Pout4: 1119, // there is no bit4 in the status register!
|
||||
Pout5: -1, // there is no bit5 in the status register!
|
||||
Pout6: 77,
|
||||
Pout7: 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,
|
||||
notir0: 194,
|
||||
t2: 971,
|
||||
notir2: 1182,
|
||||
notir3: 1125,
|
||||
notir4: 26,
|
||||
notir5: 1394,
|
||||
notir6: 895,
|
||||
notir7: 1320,
|
||||
irline3: 996, // internal signal: PLA input - ir0 AND ir1
|
||||
clock1: 1536, // internal state: timing control aka #T0
|
||||
clock2: 156, // internal state: timing control aka #T+
|
||||
t2: 971, // internal state: timing control
|
||||
t3: 1567,
|
||||
t4: 690,
|
||||
t5: 909,
|
||||
cp1: 710,
|
||||
fetch: 879,
|
||||
clearIR: 1077,
|
||||
D1x1: 827,
|
||||
notRdy0: 248,
|
||||
alu0: 394,
|
||||
alu1: 697,
|
||||
alu2: 276,
|
||||
alu3: 495,
|
||||
alu4: 1490,
|
||||
alu5: 893,
|
||||
alu6: 68,
|
||||
alu7: 1123,
|
||||
adl0: 413,
|
||||
adl1: 1282,
|
||||
adl2: 1242,
|
||||
adl3: 684,
|
||||
adl4: 1437,
|
||||
adl5: 1630,
|
||||
adl6: 121,
|
||||
adl7: 1299,
|
||||
adh0: 407,
|
||||
adh1: 52,
|
||||
adh2: 1651,
|
||||
adh3: 315,
|
||||
adh4: 1160,
|
||||
adh5: 483,
|
||||
adh6: 13,
|
||||
adh7: 1539,
|
||||
sb0: 54,
|
||||
noty0: 1025, // datapath state: not Y register
|
||||
noty1: 1138,
|
||||
noty2: 1484,
|
||||
noty3: 184,
|
||||
noty4: 565,
|
||||
noty5: 981,
|
||||
noty6: 1439,
|
||||
noty7: 1640,
|
||||
notx0: 987, // datapath state: not X register
|
||||
notx1: 1434,
|
||||
notx2: 890,
|
||||
notx3: 1521,
|
||||
notx4: 485,
|
||||
notx5: 1017,
|
||||
notx6: 730,
|
||||
notx7: 1561,
|
||||
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,
|
||||
@ -181,7 +229,48 @@ sb4: 1405,
|
||||
sb5: 166,
|
||||
sb6: 1336,
|
||||
sb7: 1001,
|
||||
idb0: 1108,
|
||||
notalu0: 394, // datapath state: alu output storage node (inverse) aka #ADD0
|
||||
notalu1: 697,
|
||||
notalu2: 276,
|
||||
notalu3: 495,
|
||||
notalu4: 1490,
|
||||
notalu5: 893,
|
||||
notalu6: 68,
|
||||
notalu7: 1123,
|
||||
alu0: 401, // datapath signal: ALU output aka ADD0out
|
||||
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 bus: address low
|
||||
adl1: 1282,
|
||||
adl2: 1242,
|
||||
adl3: 684,
|
||||
adl4: 1437,
|
||||
adl5: 1630,
|
||||
adl6: 121,
|
||||
adl7: 1299,
|
||||
adh0: 407, // internal bus: address high
|
||||
adh1: 52,
|
||||
adh2: 1651,
|
||||
adh3: 315,
|
||||
adh4: 1160,
|
||||
adh5: 483,
|
||||
adh6: 13,
|
||||
adh7: 1539,
|
||||
idb0: 1108, // internal bus: data bus
|
||||
idb1: 991,
|
||||
idb2: 1473,
|
||||
idb3: 1302,
|
||||
@ -189,15 +278,31 @@ idb4: 892,
|
||||
idb5: 1503,
|
||||
idb6: 833,
|
||||
idb7: 493,
|
||||
dor0: 222,
|
||||
dor1: 527,
|
||||
dor2: 1288,
|
||||
dor3: 823,
|
||||
dor4: 873,
|
||||
dor5: 1266,
|
||||
dor6: 1418,
|
||||
dor7: 158,
|
||||
pd0: 758,
|
||||
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.clearIR": 1622, // internal state: predecode register output (anded with not ClearIR)
|
||||
"pd1.clearIR": 809,
|
||||
"pd2.clearIR": 1671,
|
||||
"pd3.clearIR": 1587,
|
||||
"pd4.clearIR": 540,
|
||||
"pd5.clearIR": 667,
|
||||
"pd6.clearIR": 1460,
|
||||
"pd7.clearIR": 1410,
|
||||
pd0: 758, // internal state: predecode register (storage node)
|
||||
pd1: 361,
|
||||
pd2: 955,
|
||||
pd3: 894,
|
||||
@ -205,5 +310,514 @@ pd4: 369,
|
||||
pd5: 829,
|
||||
pd6: 1669,
|
||||
pd7: 1690,
|
||||
h1x1: 1042, // drive status byte onto databus
|
||||
// internal signals: predecode latch partial decodes
|
||||
"PD-xxxx10x0": 1019,
|
||||
"PD-1xx000x0": 1294,
|
||||
"PD-0xx0xx0x": 365,
|
||||
"PD-xxx010x1": 302,
|
||||
"PD-n-0xx0xx0x": 125,
|
||||
"#TWOCYCLE": 851,
|
||||
"#TWOCYCLE.phi1": 792,
|
||||
"ONEBYTE": 778,
|
||||
|
||||
abl0: 1096, // internal bus: address bus low latched data out (inverse of inverted storage node)
|
||||
abl1: 376,
|
||||
abl2: 1502,
|
||||
abl3: 1250,
|
||||
abl4: 1232,
|
||||
abl5: 234,
|
||||
abl6: 178,
|
||||
abl7: 567,
|
||||
"#ABL0": 153, // internal state: address bus low latched data out (storage node, inverted)
|
||||
"#ABL1": 107,
|
||||
"#ABL2": 707,
|
||||
"#ABL3": 825,
|
||||
"#ABL4": 364,
|
||||
"#ABL5": 1513,
|
||||
"#ABL6": 1307,
|
||||
"#ABL7": 28,
|
||||
abh0: 1429, // internal bus: address bus high latched data out (inverse of inverted storage node)
|
||||
abh1: 713,
|
||||
abh2: 287,
|
||||
abh3: 422,
|
||||
abh4: 1143,
|
||||
abh5: 775,
|
||||
abh6: 997,
|
||||
abh7: 489,
|
||||
"#ABH0": 1062, // internal state: address bus high latched data out (storage node, inverted)
|
||||
"#ABH1": 907,
|
||||
"#ABH2": 768,
|
||||
"#ABH3": 92,
|
||||
"#ABH4": 668,
|
||||
"#ABH5": 1128,
|
||||
"#ABH6": 289,
|
||||
"#ABH7": 429,
|
||||
|
||||
"branch-back": 626, // distinguish forward from backward branches
|
||||
"branch-forward.phi1": 1110, // distinguish forward from backward branches
|
||||
"branch-back.phi1": 771, // distinguish forward from backward branches in IPC logic
|
||||
notRdy0: 248, // internal signal: global pipeline control
|
||||
"notRdy0.phi1": 1272, // delayed pipeline control
|
||||
"notRdy0.delay": 770, // global pipeline control latched by phi1 and then phi2
|
||||
"#notRdy0.delay": 559, // global pipeline control latched by phi1 and then phi2 (storage node)
|
||||
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, aka TRISTATE
|
||||
"#DBE": 1035, // internal signal: formerly from DBE pad (6501)
|
||||
cp1: 710, // internal signal: clock phase 1
|
||||
cclk: 943, // unbonded pad: internal non-overlappying phi2
|
||||
fetch: 879, // internal signal
|
||||
clearIR: 1077, // internal signal
|
||||
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
|
||||
"op-sty/cpy-mem": 1601, // pla0
|
||||
"op-T3-ind-y": 60, // pla1
|
||||
"op-T2-abs-y": 1512, // pla2
|
||||
"op-T0-iny/dey": 382, // pla3
|
||||
"x-op-T0-tya": 1173, // pla4
|
||||
"op-T0-cpy/iny": 1233, // pla5
|
||||
|
||||
// internal signal: pla outputs block 2
|
||||
"op-T2-idx-x-xy": 258, // pla6
|
||||
"op-xy": 1562, // pla7
|
||||
"op-T2-ind-x": 84, // pla8
|
||||
"x-op-T0-txa": 1543, // pla9
|
||||
"op-T0-dex": 76, // pla10
|
||||
"op-T0-cpx/inx": 1658, // pla11
|
||||
"op-from-x": 1540, // pla12
|
||||
"op-T0-txs": 245, // pla13
|
||||
"op-T0-ldx/tax/tsx": 985, // pla14
|
||||
"op-T+-dex": 786, // pla15
|
||||
"op-T+-inx": 1664, // pla16
|
||||
"op-T0-tsx": 682, // pla17
|
||||
"op-T+-iny/dey": 1482, // pla18
|
||||
"op-T0-ldy-mem": 665, // pla19
|
||||
"op-T0-tay/ldy-not-idx": 286, // pla20
|
||||
|
||||
// internal signal: pla outputs block 3
|
||||
// not pla, feed through
|
||||
"op-T0-jsr": 271, // pla21
|
||||
"op-T5-brk": 370, // pla22
|
||||
"op-T0-php/pha": 552, // pla23
|
||||
"op-T4-rts": 1612, // pla24
|
||||
"op-T3-plp/pla": 1487, // pla25
|
||||
"op-T5-rti": 784, // pla26
|
||||
"op-ror": 244, // pla27
|
||||
"op-T2": 788, // pla28
|
||||
"op-T0-eor": 1623, // pla29
|
||||
"op-jmp": 764, // pla30
|
||||
"op-T2-abs": 1057, // pla31
|
||||
"op-T0-ora": 403, // pla32
|
||||
"op-T2-ADL/ADD":204, // pla33
|
||||
"op-T0":1273, // pla34
|
||||
"op-T2-stack":1582, // pla35
|
||||
"op-T3-stack/bit/jmp":1031, // pla36
|
||||
|
||||
// internal signal: pla outputs block 4
|
||||
"op-T4-brk/jsr":804, // pla37
|
||||
"op-T4-rti":1311, // pla38
|
||||
"op-T3-ind-x":1428, // pla39
|
||||
"op-T4-ind-y":492, // pla40
|
||||
"op-T2-ind-y":1204, // pla41
|
||||
"op-T3-abs-idx":58, // pla42
|
||||
"op-plp/pla":1520, // pla43
|
||||
"op-inc/nop":324, // pla44
|
||||
"op-T4-ind-x":1259, // pla45
|
||||
"x-op-T3-ind-y":342, // pla46
|
||||
"op-rti/rts":857, // pla47
|
||||
"op-T2-jsr":712, // pla48
|
||||
"op-T0-cpx/cpy/inx/iny":1337, // pla49
|
||||
"op-T0-cmp":1355, // pla50
|
||||
"op-T0-sbc":787, // pla51 // 52:111XXXXX 1 0 T0SBC
|
||||
"op-T0-adc/sbc":575, // pla52 // 51:X11XXXXX 1 0 T0ADCSBC
|
||||
"op-rol/ror":1466, // pla53
|
||||
|
||||
// internal signal: pla outputs block 5
|
||||
"op-T3-jmp":1381, // pla54
|
||||
"op-shift":546, // pla55
|
||||
"op-T5-jsr":776, // pla56
|
||||
"op-T2-stack-access":157, // pla57
|
||||
"op-T0-tya":257, // pla58
|
||||
"op-T+-ora/and/eor/adc":1243, // pla59
|
||||
"op-T+-adc/sbc":822, // pla60
|
||||
"op-T+-shift-a":1324, // pla61
|
||||
"op-T0-txa":179, // pla62
|
||||
"op-T0-pla":131, // pla63
|
||||
"op-T0-lda":1420, // pla64
|
||||
"op-T0-acc":1342, // pla65
|
||||
"op-T0-tay":4, // pla66
|
||||
"op-T0-shift-a":1396, // pla67
|
||||
"op-T0-tax":167, // pla68
|
||||
"op-T0-bit":303, // pla69
|
||||
"op-T0-and":1504, // pla70
|
||||
"op-T4-abs-idx":354, // pla71
|
||||
"op-T5-ind-y":1168, // pla72
|
||||
|
||||
// internal signal: pla outputs block 6
|
||||
"op-branch-done":1721, // pla73 // has extra non-pla input
|
||||
"op-T2-pha":1086, // pla74
|
||||
"op-T0-shift-right-a":1074, // pla75
|
||||
"op-shift-right":1246, // pla76
|
||||
"op-T2-brk":487, // pla77
|
||||
"op-T3-jsr":579, // pla78
|
||||
"op-sta/cmp":145, // pla79
|
||||
"op-T2-branch":1239, // pla80 // T2BR, 83 for Balazs
|
||||
"op-T2-zp/zp-idx":285, // pla81
|
||||
// not pla, feed through
|
||||
// not pla, feed through
|
||||
"op-T2-ind":1524, // pla82
|
||||
"op-T2-abs-access":273, // pla83 // has extra pulldown: pla97
|
||||
"op-T5-rts":0, // pla84
|
||||
"op-T4":341, // pla85
|
||||
"op-T3":120, // pla86
|
||||
"op-T0-brk/rti":1478, // pla87
|
||||
"op-T0-jmp":594, // pla88
|
||||
"op-T5-ind-x":1210, // pla89
|
||||
"op-T3-abs/idx/ind":677, // pla90 // has extra pulldown: pla97
|
||||
|
||||
// internal signal: pla outputs block 7
|
||||
"x-op-T4-ind-y":461, // pla91
|
||||
"x-op-T3-abs-idx":447, // pla92
|
||||
"op-T3-branch":660, // pla93
|
||||
"op-brk/rti":1557, // pla94
|
||||
"op-jsr":259, // pla95
|
||||
"x-op-jmp":1052, // pla96
|
||||
// gap
|
||||
"op-push/pull":791, // pla97 // feeds into pla83 and pla90 (no normal pla output)
|
||||
"op-store":517, // pla98
|
||||
"op-T4-brk":352, // pla99
|
||||
"op-T2-php":750, // pla100
|
||||
"op-T2-php/pha":932, // pla101
|
||||
"op-T4-jmp":1589, // pla102
|
||||
// gap
|
||||
"op-T5-rti/rts":446, // pla103
|
||||
"xx-op-T5-jsr":528, // pla104
|
||||
|
||||
// internal signal: pla outputs block 8
|
||||
"op-T2-jmp-abs":309, // pla105
|
||||
"x-op-T3-plp/pla":1430, // pla106
|
||||
"op-lsr/ror/dec/inc":53, // pla107
|
||||
"op-asl/rol":691, // pla108
|
||||
"op-T0-cli/sei":1292, // pla109
|
||||
// gap
|
||||
"op-T+-bit":1646, // pla110
|
||||
"op-T0-clc/sec":1114, // pla111
|
||||
"op-T3-mem-zp-idx":904, // pla112
|
||||
"x-op-T+-adc/sbc":1155, // pla113
|
||||
"x-op-T0-bit":1476, // pla114
|
||||
"op-T0-plp":1226, // pla115
|
||||
"x-op-T4-rti":1569, // pla116
|
||||
"op-T+-cmp":301, // pla117
|
||||
"op-T+-cpx/cpy-abs":950, // pla118
|
||||
"op-T+-asl/rol-a":1665, // pla119
|
||||
|
||||
// internal signal: pla outputs block 9
|
||||
"op-T+-cpx/cpy-imm/zp":1710, // pla120
|
||||
"x-op-push/pull":1050, // pla121 // feeds into pla130 (no normal pla output)
|
||||
"op-T0-cld/sed":1419, // pla122
|
||||
"#op-branch-bit6":840, // pla123 // IR bit6 used only to detect branch type
|
||||
"op-T3-mem-abs":607, // pla124
|
||||
"op-T2-mem-zp":219, // pla125
|
||||
"op-T5-mem-ind-idx":1385, // pla126
|
||||
"op-T4-mem-abs-idx":281, // pla127
|
||||
"#op-branch-bit7":1174, // pla128 // IR bit7 used only to detect branch type
|
||||
"op-clv":1164, // pla129
|
||||
"op-implied":1006, // pla130 // has extra pulldowns: pla121 and ir0
|
||||
|
||||
// internal signals: derived from pla outputs
|
||||
"#op-branch-done": 1048,
|
||||
"#op-T3-branch": 1708,
|
||||
"op-ANDS": 1228,
|
||||
"op-EORS": 1689,
|
||||
"op-ORS": 522,
|
||||
"op-SUMS": 1196,
|
||||
"op-SRS": 934,
|
||||
"#op-store": 925,
|
||||
"#WR": 1352,
|
||||
"op-rmw": 434,
|
||||
"short-circuit-idx-add": 1185,
|
||||
"short-circuit-branch-add": 430,
|
||||
"#op-set-C": 252,
|
||||
|
||||
// internal signals: control signals
|
||||
nnT2BR: 967, // doubly inverted
|
||||
BRtaken: 1544, // aka #TAKEN
|
||||
|
||||
// internal signals and state: interrupt and vector related
|
||||
// segher says:
|
||||
// "P" are the latched external signals.
|
||||
// "G" are the signals that actually trigger the interrupt.
|
||||
// "NMIL" is to do the edge detection -- it's pretty much just a delayed NMIG.
|
||||
// INTG is IRQ and NMI taken together.
|
||||
IRQP: 675,
|
||||
"#IRQP": 888,
|
||||
NMIP: 1032,
|
||||
"#NMIP": 297,
|
||||
"#NMIG": 264,
|
||||
NMIL: 1374,
|
||||
RESP: 67,
|
||||
RESG: 926,
|
||||
VEC0: 1465,
|
||||
VEC1: 1481,
|
||||
"#VEC": 1134,
|
||||
D1x1: 827, // internal signal: interrupt handler related
|
||||
"brk-done": 1382, // internal signal: interrupt handler related
|
||||
INTG: 1350, // internal signal: interrupt handler related
|
||||
|
||||
// internal state: misc pipeline state clocked by cclk (phi2)
|
||||
"pipe#VEC": 1431, // latched #VEC
|
||||
"pipeT-SYNC": 537,
|
||||
pipeT2out: 40,
|
||||
pipeT3out: 706,
|
||||
pipeT4out: 1373,
|
||||
pipeT5out: 940,
|
||||
pipeIPCrelated: 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,
|
||||
"pipe#WR.phi2": 1131,
|
||||
pipeUNK39: 151,
|
||||
pipeUNK40: 456,
|
||||
pipeUNK41: 1438,
|
||||
pipeUNK42: 1104,
|
||||
"pipe#T0": 554, // aka #T0.phi2
|
||||
|
||||
// internal state: vector address pulldown control
|
||||
pipeVectorA0: 357,
|
||||
pipeVectorA1: 170,
|
||||
pipeVectorA2: 45,
|
||||
|
||||
// internal signals: vector address pulldown control
|
||||
"0/ADL0": 217,
|
||||
"0/ADL1": 686,
|
||||
"0/ADL2": 1193,
|
||||
|
||||
// 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,
|
||||
|
||||
// alu carry chain and decimal mode
|
||||
C01: 1285,
|
||||
C12: 505,
|
||||
C23: 1023,
|
||||
C34: 78,
|
||||
C45: 142,
|
||||
C56: 500,
|
||||
C67: 1314,
|
||||
C78: 808,
|
||||
"C78.phi2": 560,
|
||||
DC34: 1372, // lower nibble decimal carry
|
||||
DC78: 333, // carry for decimal mode
|
||||
"DC78.phi2": 164,
|
||||
"#C01": 1506,
|
||||
"#C12": 1122,
|
||||
"#C23": 1003,
|
||||
"#C34": 1425,
|
||||
"#C45": 1571,
|
||||
"#C56": 427,
|
||||
"#C67": 592,
|
||||
"#C78": 1327,
|
||||
"DA-C01": 623,
|
||||
"DA-AB2": 216,
|
||||
"DA-AxB2": 516,
|
||||
"DA-C45": 1144,
|
||||
"#DA-ADD1": 901,
|
||||
"#DA-ADD2": 699,
|
||||
|
||||
// misc alu internals
|
||||
"#(AxBxC)0": 371,
|
||||
"#(AxBxC)1": 965,
|
||||
"#(AxBxC)2": 22,
|
||||
"#(AxBxC)3": 274,
|
||||
"#(AxBxC)4": 651,
|
||||
"#(AxBxC)5": 486,
|
||||
"#(AxBxC)6": 1197,
|
||||
"#(AxBxC)7": 532,
|
||||
AxB1: 425,
|
||||
AxB3: 640,
|
||||
AxB5: 1220,
|
||||
AxB7: 1241,
|
||||
"#(AxB)0": 1525,
|
||||
"#(AxB)2": 701,
|
||||
"#(AxB)4": 308,
|
||||
"#(AxB)6": 1459,
|
||||
"(AxB)0.#C0in": 555,
|
||||
"(AxB)2.#C12": 193,
|
||||
"(AxB)4.#C34": 65,
|
||||
"(AxB)6.#C56": 174,
|
||||
"#(AxB1).C01": 295,
|
||||
"#(AxB3).C23": 860,
|
||||
"#(AxB5).C45": 817,
|
||||
"#(AxB7).C67": 1217,
|
||||
"#A.B0": 1628,
|
||||
"#A.B1": 841,
|
||||
"#A.B2": 681,
|
||||
"#A.B3": 350,
|
||||
"#A.B4": 1063,
|
||||
"#A.B5": 477,
|
||||
"#A.B6": 336,
|
||||
"#A.B7": 1318,
|
||||
"A+B0": 693,
|
||||
"A+B1": 1021,
|
||||
"A+B2": 110,
|
||||
"A+B3": 1313,
|
||||
"A+B4": 918,
|
||||
"A+B5": 1236,
|
||||
"A+B6": 803,
|
||||
"A+B7": 117,
|
||||
"#(A+B)0": 143,
|
||||
"#(A+B)1": 155,
|
||||
"#(A+B)2": 1691,
|
||||
"#(A+B)3": 649,
|
||||
"#(A+B)4": 404,
|
||||
"#(A+B)5": 1632,
|
||||
"#(A+B)6": 1084,
|
||||
"#(A+B)7": 1398,
|
||||
"#(AxB)0": 1525,
|
||||
"#(AxB)2": 701,
|
||||
"#(AxB)4": 308,
|
||||
"#(AxB)6": 1459,
|
||||
"#(AxB)1": 953,
|
||||
"#(AxB)3": 884,
|
||||
"#(AxB)5": 1469,
|
||||
"#(AxB)7": 177,
|
||||
"#aluresult0": 957, // alu result latch input
|
||||
"#aluresult1": 250,
|
||||
"#aluresult2": 740,
|
||||
"#aluresult3": 1071,
|
||||
"#aluresult4": 296,
|
||||
"#aluresult5": 277,
|
||||
"#aluresult6": 722,
|
||||
"#aluresult7": 304,
|
||||
|
||||
// internal signals: datapath control signals
|
||||
|
||||
"ADL/ABL": 639, // load ABL latches from ADL bus
|
||||
"ADH/ABH": 821, // load ABH latches from ADH bus
|
||||
|
||||
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 (inverted)
|
||||
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)
|
||||
notalucout: 412, // alu carry out (inverted)
|
||||
alucout: 1146, // alu carry out (latched by phi2)
|
||||
"#alucout": 206,
|
||||
"##alucout": 465,
|
||||
notaluvout: 1308, // alu overflow out
|
||||
aluvout: 938, // alu overflow out (latched by phi2)
|
||||
|
||||
"#DBZ": 1268, // internal signal: not (databus is zero)
|
||||
DBZ: 744, // internal signal: databus is zero
|
||||
DBNeg: 1200, // internal signal: databus is negative (top bit of db) aka P-#DB7in
|
||||
|
||||
"dpc22_#DSA": 725, // decimal related/SBC only (inverted)
|
||||
dpc23_SBAC: 534, // (optionalls decimal-adjusted) sb to acc
|
||||
dpc24_ACSB: 1698, // acc to sb
|
||||
dpc25_SBDB: 1060, // sb pass-connects to idb (bi-directionally)
|
||||
dpc26_ACDB: 1331, // acc to idb
|
||||
dpc27_SBADH: 140, // sb pass-connects to adh (bi-directionally)
|
||||
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_PCHC: 1334, // pcl 0x?F detect - half-carry
|
||||
"dpc36_#IPC": 379, // pcl carry in (inverted)
|
||||
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_DL/ADL": 1564,// pass-connect adl to mux node driven by idl
|
||||
"dpc42_DL/ADH": 41, // pass-connect adh to mux node driven by idl
|
||||
"dpc43_DL/DB": 863, // pass-connect idb to mux node driven by idl
|
||||
|
||||
}
|
||||
|
||||
/* many bus names taken from Donald F. Hanson's block diagram, found
|
||||
* http://www.weihenstephan.org/~michaste/pagetable/6502/6502.jpg
|
||||
* from his paper "A VHDL conversion tool for logic equations with embedded D latches"
|
||||
* http://portal.acm.org/citation.cfm?id=1275143.1275151
|
||||
* also available at
|
||||
* http://www.ncsu.edu/wcae/WCAE1/hanson.pdf
|
||||
*/
|
||||
|
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;
|
||||
}
|
||||
|
||||
?>
|
||||
|
36
testprogram.js
Normal file
@ -0,0 +1,36 @@
|
||||
// This file testprogram.js can be substituted by one of several tests
|
||||
// which may not be redistributable
|
||||
// for example
|
||||
// cbmbasic loaded at 0xa000 with entry point 0xe394
|
||||
// test6502 (by Bird Computer) loaded at 0x8000 with entry point 0x8000
|
||||
//
|
||||
// (can use xxd -i to convert binary into C include syntax, as a starting point)
|
||||
//
|
||||
testprogramAddress=0x0000;
|
||||
|
||||
// we want to auto-clear the console if any output is sent by the program
|
||||
var consoleboxStream="";
|
||||
|
||||
// demonstrate write hook
|
||||
writeTriggers[0x000F]="consoleboxStream += String.fromCharCode(d);"+
|
||||
"consolebox.innerHTML = consoleboxStream;";
|
||||
|
||||
// demonstrate read hook (not used by this test program)
|
||||
readTriggers[0xD011]="((consolegetc==undefined)?0:0xff)"; // return zero until we have a char
|
||||
readTriggers[0xD010]="var c=consolegetc; consolegetc=undefined; (c)";
|
||||
|
||||
testprogram = [
|
||||
0xa9, 0x00, // LDA #$00
|
||||
0x20, 0x10, 0x00, // JSR $0010
|
||||
0x4c, 0x02, 0x00, // JMP $0002
|
||||
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x40,
|
||||
|
||||
0xe8, // INX
|
||||
0x88, // DEY
|
||||
0xe6, 0x0F, // INC $0F
|
||||
0x38, // SEC
|
||||
0x69, 0x02, // ADC #$02
|
||||
0x60 // RTS
|
||||
];
|
7035
transdefs.js
279
wires.js
@ -21,60 +21,15 @@
|
||||
*/
|
||||
|
||||
var frame, chipbg, overlay, hilite, hitbuffer, ctx;
|
||||
var centerx=300, centery=300;
|
||||
var zoom=1;
|
||||
var dragMouseX, dragMouseY, moved;
|
||||
var statbox;
|
||||
|
||||
var layernames = ['metal', 'diff', 'inputdiode', 'diff0', 'diff1', 'poly'];
|
||||
var colors = ['rgba(128,128,192,0.4)','#FFFF00','#FF00FF','#4DFF4D',
|
||||
'#FF4D4D','#801AC0','rgba(128,0,255,0.75)'];
|
||||
var drawlayers = [true, true, true, true, true, true];
|
||||
|
||||
var nodes = new Array();
|
||||
var transistors = {};
|
||||
var nodenamelist=[];
|
||||
|
||||
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();
|
||||
}
|
||||
var chipLayoutIsVisible = true; // only modified in expert mode
|
||||
var hilited = [];
|
||||
|
||||
function setupNodes(){
|
||||
for(var i in segdefs){
|
||||
@ -82,7 +37,7 @@ function setupNodes(){
|
||||
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()};
|
||||
state: false, gates: new Array(), c1c2s: new Array()};
|
||||
if(w==ngnd) continue;
|
||||
if(w==npwr) continue;
|
||||
nodes[w].segs.push(seg.slice(3));
|
||||
@ -96,10 +51,13 @@ function setupTransistors(){
|
||||
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);
|
||||
var bb = tdef[4];
|
||||
if(c1==ngnd) {c1=c2;c2=ngnd;}
|
||||
if(c1==npwr) {c1=c2;c2=npwr;}
|
||||
var trans = {name: name, on: false, gate: gate, c1: c1, c2: c2, bb: bb};
|
||||
nodes[gate].gates.push(trans);
|
||||
nodes[c1].c1c2s.push(trans);
|
||||
nodes[c2].c1c2s.push(trans);
|
||||
transistors[name] = trans;
|
||||
}
|
||||
}
|
||||
@ -114,16 +72,14 @@ function setupLayerVisibility(){
|
||||
}
|
||||
|
||||
function setupBackground(){
|
||||
console.log('starting setupBackground');
|
||||
chipbg = document.getElementById('chipbg');
|
||||
chipbg.width = 4000;
|
||||
chipbg.height = 4000;
|
||||
chipbg.width = grCanvasSize;
|
||||
chipbg.height = grCanvasSize;
|
||||
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);
|
||||
ctx.lineWidth = grLineWidth;
|
||||
ctx.fillRect(0,0,grCanvasSize,grCanvasSize);
|
||||
for(var i in segdefs){
|
||||
var seg = segdefs[i];
|
||||
var c = seg[2];
|
||||
@ -138,27 +94,24 @@ function setupBackground(){
|
||||
|
||||
function setupOverlay(){
|
||||
overlay = document.getElementById('overlay');
|
||||
overlay.width = 4000;
|
||||
overlay.height = 4000;
|
||||
overlay.width = grCanvasSize;
|
||||
overlay.height = grCanvasSize;
|
||||
ctx = overlay.getContext('2d');
|
||||
ctx.scale(overlay.width/10000, overlay.height/10000);
|
||||
}
|
||||
|
||||
function setupHilite(){
|
||||
hilite = document.getElementById('hilite');
|
||||
hilite.width = 4000;
|
||||
hilite.height = 4000;
|
||||
hilite.width = grCanvasSize;
|
||||
hilite.height = grCanvasSize;
|
||||
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.width = grCanvasSize;
|
||||
hitbuffer.height = grCanvasSize;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -183,10 +136,12 @@ function hexdigit(n){return '0123456789ABCDEF'.charAt(n);}
|
||||
/////////////////////////
|
||||
|
||||
function refresh(){
|
||||
ctx.clearRect(0,0,10000,10000);
|
||||
if(!chipLayoutIsVisible) return;
|
||||
ctx.clearRect(0,0,grCanvasSize,grCanvasSize);
|
||||
for(i in nodes){
|
||||
if(isNodeHigh(i)) overlayNode(nodes[i].segs);
|
||||
}
|
||||
hiliteNode(hilited);
|
||||
}
|
||||
|
||||
function overlayNode(w){
|
||||
@ -197,115 +152,75 @@ function overlayNode(w){
|
||||
}
|
||||
}
|
||||
|
||||
// originally to highlight using a list of node numbers
|
||||
// but can now include transistor names
|
||||
function hiliteNode(n){
|
||||
var ctx = hilite.getContext('2d');
|
||||
ctx.clearRect(0,0,10000,10000);
|
||||
ctx.fillStyle = 'rgba(255,255,255,0.7)';
|
||||
ctx.clearRect(0,0,grCanvasSize,grCanvasSize);
|
||||
if(n==-1) return;
|
||||
if(isNodeHigh(n[0]))
|
||||
ctx.fillStyle = 'rgba(255,0,0,0.7)';
|
||||
hilited = n;
|
||||
|
||||
for(var i in n){
|
||||
if(typeof n[i] != "number") {
|
||||
hiliteTrans([n[i]]);
|
||||
continue;
|
||||
}
|
||||
if(isNodeHigh(n[i])) {
|
||||
ctx.fillStyle = 'rgba(255,0,0,0.7)';
|
||||
} else {
|
||||
ctx.fillStyle = 'rgba(255,255,255,0.7)';
|
||||
}
|
||||
var segs = nodes[n[i]].segs;
|
||||
for(var s in segs){drawSeg(ctx, segs[s]); ctx.fill();}
|
||||
}
|
||||
}
|
||||
|
||||
// highlight a single transistor (additively - does not clear highlighting)
|
||||
function hiliteTrans(n){
|
||||
var ctx = hilite.getContext('2d');
|
||||
ctx.strokeStyle = 'rgba(255,255,255,0.7)';
|
||||
ctx.lineWidth = 4
|
||||
for(var t in n){
|
||||
var bb = transistors[n[t]].bb
|
||||
var segs = [[bb[0], bb[2], bb[1], bb[2], bb[1], bb[3], bb[0], bb[3]]]
|
||||
for(var s in segs){drawSeg(ctx, segs[s]); ctx.stroke();}
|
||||
}
|
||||
}
|
||||
|
||||
function ctxDrawBox(ctx, xMin, yMin, xMax, yMax){
|
||||
var cap=ctx.lineCap;
|
||||
ctx.lineCap="square";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(xMin, yMin);
|
||||
ctx.lineTo(xMin, yMax);
|
||||
ctx.lineTo(xMax, yMax);
|
||||
ctx.lineTo(xMax, yMin);
|
||||
ctx.lineTo(xMin, yMin);
|
||||
ctx.stroke();
|
||||
ctx.lineCap=cap;
|
||||
}
|
||||
|
||||
// takes a bounding box in chip coords and centres the display over it
|
||||
function zoomToBox(xmin,xmax,ymin,ymax){
|
||||
var xmid=(xmin+xmax)/2;
|
||||
var ymid=(ymin+ymax)/2;
|
||||
var x=(xmid+400)/grChipSize*600;
|
||||
var y=600-ymid/grChipSize*600;
|
||||
var zoom=5; // pending a more careful calculation
|
||||
moveHere([x,y,zoom]);
|
||||
}
|
||||
|
||||
function drawSeg(ctx, seg){
|
||||
if(noGraphics) return;
|
||||
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));}
|
||||
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]));
|
||||
}
|
||||
|
||||
function findNodeNumber(x,y){
|
||||
var ctx = hitbuffer.getContext('2d');
|
||||
var pixels = ctx.getImageData(x*4000/600, y*4000/600, 2, 2).data;
|
||||
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;
|
||||
@ -313,45 +228,47 @@ function findNodeNumber(x,y){
|
||||
return (high<<8)+(mid<<4)+low;
|
||||
}
|
||||
|
||||
function clearHighlight(){
|
||||
// remove red/white overlay according to logic value
|
||||
// for easier layout navigation
|
||||
ctx.clearRect(0,0,grCanvasSize,grCanvasSize);
|
||||
}
|
||||
|
||||
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){
|
||||
var lx = gx+window.pageXOffset;
|
||||
lx-=el.getBoundingClientRect().left
|
||||
return lx;
|
||||
return gx-el.getBoundingClientRect().left;
|
||||
}
|
||||
|
||||
function localy(el, gy){
|
||||
var ly = gy+window.pageYOffset;
|
||||
ly-=el.getBoundingClientRect().top
|
||||
return ly;
|
||||
return gy-el.getBoundingClientRect().top;
|
||||
}
|
||||
|
||||
function setStatus(){
|
||||
var res = '';
|
||||
for(var i=0;i<arguments.length;i++) res=res+arguments[i]+' ';
|
||||
// pad the arguments to make this a three-line display
|
||||
// there must be a clean way to do this
|
||||
if(arguments[1]==undefined)arguments[1]="";
|
||||
if(arguments[2]==undefined)arguments[2]="";
|
||||
arguments.length=3;
|
||||
for(var i=0;i<arguments.length;i++) res=res+arguments[i]+'<br>';
|
||||
statbox.innerHTML = res;
|
||||
}
|
||||
|
||||
function setupNodeNameList(){
|
||||
for(var i in nodenames)
|
||||
nodenamelist.push(i);
|
||||
}
|
||||
|
||||
function nodeName(n) {
|
||||
for(var i in nodenames){
|
||||
if(nodenames[i]==n) return i;
|
||||
|