mirror of
https://github.com/trebonian/visual6502.git
synced 2024-09-18 05:56:41 +00:00
removing gh-pages project preview
This commit is contained in:
parent
7c50999c9e
commit
ee2fa1befd
BIN
3rdparty/img/hgrabber.gif
vendored
BIN
3rdparty/img/hgrabber.gif
vendored
Binary file not shown.
Before Width: | Height: | Size: 834 B |
BIN
3rdparty/img/vdockbar.gif
vendored
BIN
3rdparty/img/vdockbar.gif
vendored
Binary file not shown.
Before Width: | Height: | Size: 855 B |
BIN
3rdparty/img/vgrabber.gif
vendored
BIN
3rdparty/img/vgrabber.gif
vendored
Binary file not shown.
Before Width: | Height: | Size: 830 B |
BIN
3rdparty/img/vgrabber2-active.gif
vendored
BIN
3rdparty/img/vgrabber2-active.gif
vendored
Binary file not shown.
Before Width: | Height: | Size: 840 B |
BIN
3rdparty/img/vgrabber2-normal.gif
vendored
BIN
3rdparty/img/vgrabber2-normal.gif
vendored
Binary file not shown.
Before Width: | Height: | Size: 843 B |
19
3rdparty/jquery-1.3.2.min.js
vendored
19
3rdparty/jquery-1.3.2.min.js
vendored
File diff suppressed because one or more lines are too long
92
3rdparty/jquery.cookie.js
vendored
92
3rdparty/jquery.cookie.js
vendored
@ -1,92 +0,0 @@
|
||||
/**
|
||||
* 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
213
3rdparty/splitter.js
vendored
@ -1,213 +0,0 @@
|
||||
/*
|
||||
* 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);
|
10
README
10
README
@ -1,10 +0,0 @@
|
||||
This is the javascript simulator from the visual5602.org project:
|
||||
www.visual6502.org/JSSim
|
||||
|
||||
It includes a general purpose transistor-level simulator, layout browser,
|
||||
and the data from a 6502 revD chip.
|
||||
|
||||
Note the various licenses and Copyright associated with each file.
|
||||
|
||||
Enjoy!
|
||||
- The Visual 6502 Team
|
@ -1,46 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<title>Visual 6502 in JavaScript</title>
|
||||
<style type="text/css">@import "wires.css";</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<span id="title"><a href="http://visual6502.org">The Visual 6502</a></span>
|
||||
<span id="plain">
|
||||
<br />
|
||||
<span id="title">Browser Trouble?</span>
|
||||
<br />
|
||||
<a href="http://www.visual6502.org/faq.html">FAQ</a>
|
||||
<a href="http://blog.visual6502.org">Blog</a>
|
||||
<a href="http://www.visual6502.org/links.html">Links</a> 
|
||||
<p>
|
||||
Our chip simulator makes heavy use of the latest version of HTML5 drawing technology.
|
||||
<p>
|
||||
It will only run on recent browsers and on a computer with sufficient memory (we recommend at least 2Gbytes.)
|
||||
<p>
|
||||
We've tested it on Chrome, Firefox, Safari and Opera. Unfortunately Internet Explorer isn't yet capable of running the graphics.
|
||||
<p>
|
||||
If you're using one of the above browsers and having trouble, please restart the browser.
|
||||
<p>
|
||||
If you have a problem report or you're able to help us with compatilibity, please get in touch - our contact details are on the main page.
|
||||
<p>
|
||||
In the meantime, here's a picture of what you're missing:
|
||||
<p>
|
||||
<a href="http://visual6502.org"><img src="images/jssim2.png" style="border:10px"></a>
|
||||
</span>
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
google_ad_client = "pub-9008420149077488";
|
||||
/* 728x90, created 9/22/10 */
|
||||
google_ad_slot = "4303982675";
|
||||
google_ad_width = 728;
|
||||
google_ad_height = 90;
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript"
|
||||
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
196
chipsim.js
196
chipsim.js
@ -1,196 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2010 Brian Silverman, Barry Silverman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
var ctrace = false;
|
||||
var 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];
|
||||
recalclist = new Array();
|
||||
recalcHash = new Array();
|
||||
for(var j=0;j<100;j++){ // loop limiter
|
||||
if(list.length==0) return;
|
||||
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();
|
||||
}
|
||||
if(ctrace) console.log(n,'looping...');
|
||||
}
|
||||
|
||||
function recalcNode(node){
|
||||
if(node==ngnd) return;
|
||||
if(node==npwr) return;
|
||||
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 turnTransistorOn(t){
|
||||
if(t.on) return;
|
||||
if(ctrace && (traceTheseTransistors.indexOf(t.name)!=-1))
|
||||
console.log(t.name, 'on', t.gate, t.c1, t.c2);
|
||||
t.on = true;
|
||||
addRecalcNode(t.c1);
|
||||
}
|
||||
|
||||
function turnTransistorOff(t){
|
||||
if(!t.on) return;
|
||||
if(ctrace && (traceTheseTransistors.indexOf(t.name)!=-1))
|
||||
console.log(t.name, 'off', t.gate, t.c1, t.c2);
|
||||
t.on = false;
|
||||
addRecalcNode(t.c1);
|
||||
addRecalcNode(t.c2);
|
||||
}
|
||||
|
||||
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){
|
||||
group = new Array();
|
||||
addNodeToGroup(i);
|
||||
}
|
||||
|
||||
function addNodeToGroup(i){
|
||||
if(group.indexOf(i) != -1) return;
|
||||
group.push(i);
|
||||
if(i==ngnd) return;
|
||||
if(i==npwr) return;
|
||||
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(){
|
||||
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 true;
|
||||
if(n.pulldown) return false;
|
||||
if(n.state) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function isNodeHigh(nn){
|
||||
return(nodes[nn].state);
|
||||
}
|
||||
|
||||
function saveString(name, str){
|
||||
var request = new XMLHttpRequest();
|
||||
request.onreadystatechange=function(){};
|
||||
request.open('PUT', 'save.php?name='+name, true);
|
||||
request.setRequestHeader('Content-Type', 'text/plain');
|
||||
request.send(str);
|
||||
}
|
||||
|
||||
function allNodes(){
|
||||
var res = new Array();
|
||||
for(var i in nodes) if((i!=npwr)&&(i!=ngnd)) res.push(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
function stateString(){
|
||||
var codes = ['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[0+n.state];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function showState(str){
|
||||
var codes = {g: false, h: true, v: true, l: false};
|
||||
for(var i=0;i<str.length;i++){
|
||||
if(str[i]=='x') continue;
|
||||
var state = codes[str[i]];
|
||||
nodes[i].state = state;
|
||||
var gates = nodes[i].gates;
|
||||
gates.forEach(function(t){t.on=state;});
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
||||
function setPd(name){
|
||||
var nn = nodenames[name];
|
||||
nodes[nn].pullup = false;
|
||||
nodes[nn].pulldown = true;
|
||||
}
|
||||
|
||||
function setHigh(name){
|
||||
var nn = nodenames[name];
|
||||
nodes[nn].pullup = true;
|
||||
nodes[nn].pulldown = false;
|
||||
recalcNodeList([nn]);
|
||||
}
|
||||
|
||||
function setLow(name){
|
||||
var nn = nodenames[name];
|
||||
nodes[nn].pullup = false;
|
||||
nodes[nn].pulldown = true;
|
||||
recalcNodeList([nn]);
|
||||
}
|
||||
|
||||
function arrayContains(arr, el){return arr.indexOf(el)!=-1;}
|
209
expert.css
209
expert.css
@ -1,209 +0,0 @@
|
||||
/*
|
||||
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-spacing: 2px;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
148
expert.html
148
expert.html
@ -1,148 +0,0 @@
|
||||
<!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 '>' to zoom in, '<' 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="Highlight:" 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> <!-- 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>
|
449
expertWires.js
449
expertWires.js
@ -1,449 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
|
||||
// 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 6502...');
|
||||
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
|
||||
// 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]="setLow('res');";
|
||||
} else if(name=="reset1" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]="setHigh('res');";
|
||||
} else if(name=="irq0" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]="setLow('irq');";
|
||||
} else if(name=="irq1" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]="setHigh('irq');";
|
||||
} else if(name=="nmi0" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]="setLow('nmi');";
|
||||
} else if(name=="nmi1" && parseInt(value)!=NaN){
|
||||
clockTriggers[value]="setHigh('nmi');";
|
||||
} 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;
|
||||
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',
|
||||
});
|
||||
document.getElementById('linkHere').href=location.pathname+"?"+whereAmIAsQuery();
|
||||
}
|
||||
|
||||
var highlightThese;
|
||||
|
||||
// flash some set of nodes according to user input
|
||||
function hiliteNodeList(){
|
||||
var tmplist = document.getElementById('HighlightThese').value.split(/[\s,]+/);
|
||||
if(tmplist.length==0){
|
||||
// request to highlight nothing, so switch off any signal highlighting
|
||||
hiliteNode(-1);
|
||||
return;
|
||||
}
|
||||
highlightThese = [];
|
||||
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[name] != "undefined")) {
|
||||
highlightThese.push(value);
|
||||
} else if(typeof nodenames[name] != "undefined") {
|
||||
highlightThese.push(nodenames[name]);
|
||||
}
|
||||
// invalid input: how to tell the user?
|
||||
}
|
||||
if(highlightThese.length==0){
|
||||
// all input rejected: how to tell the user?
|
||||
return;
|
||||
}
|
||||
clearHighlight(); // nullify the simulation overlay (orange/purple)
|
||||
hiliteNode(-1); // unhighlight all nodes
|
||||
setTimeout("hiliteNode(highlightThese);", 400);
|
||||
setTimeout("hiliteNode(-1);", 800);
|
||||
setTimeout("hiliteNode(highlightThese);", 1200);
|
||||
}
|
||||
|
||||
function handleClick(e){
|
||||
var x = localx(hilite, e.clientX)/zoom;
|
||||
var y = localy(hilite, e.clientY)/zoom;
|
||||
var w = findNodeNumber(x,y);
|
||||
if(e.shiftKey) hiliteNode(getNodeGroup(w));
|
||||
else {var a=new Array(); a.push(w); hiliteNode(a);}
|
||||
var cx = Math.round(x*grChipSize/600);
|
||||
var cy = Math.round(y*grChipSize/600);
|
||||
if(w==-1) {
|
||||
setStatus('x: '+cx, 'y: '+cy);
|
||||
} else {
|
||||
var s1='x: ' + cx + ' y: ' + cy;
|
||||
var s2='node: ' + w + ' ' + nodeName(w);
|
||||
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;};
|
||||
}
|
||||
|
||||
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
|
||||
if(moveHereFirst!=null)
|
||||
moveHere(moveHereFirst);
|
||||
// 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];
|
||||
|