Compare commits
44 Commits
Author | SHA1 | Date |
---|---|---|
Dennis Brown | f1d06fa908 | |
dependabot[bot] | 5b6f6d5e04 | |
Dennis Brown | 40e46dc4ed | |
dependabot[bot] | e938df6bf5 | |
Dennis Brown | b3cc4bba70 | |
dependabot[bot] | a0f2a772d2 | |
Dennis Brown | a7c68787f1 | |
dependabot[bot] | f0844da6e0 | |
Dennis Brown | 4ba0539403 | |
dependabot[bot] | 264acbbb03 | |
Dennis Brown | 73fd49d000 | |
dependabot[bot] | 6b6a1de839 | |
Dennis Brown | 36e7d61d4b | |
dependabot[bot] | 2a764cbc8c | |
Dennis Brown | 9d470ec1bb | |
dependabot[bot] | 972b813daa | |
Dennis Brown | 9c128b0f77 | |
dependabot[bot] | a1925a1971 | |
Dennis Brown | 7fc4986f8d | |
Dennis Brown | 9e986e559a | |
dependabot[bot] | 96ef1698b9 | |
Dennis Brown | a4de1542b3 | |
Dennis Brown | 3d16673d65 | |
Dennis Brown | af685c697d | |
Dennis Brown | e9806fc87a | |
Dennis Brown | 05e15076fc | |
dependabot[bot] | 8d78e5505e | |
dependabot[bot] | 392e1eeb2f | |
dependabot[bot] | f78c5d49a9 | |
dependabot[bot] | aad2cb00b8 | |
Dennis Brown | a628ad2004 | |
Dennis Brown | 5cb1005bb6 | |
Dennis Brown | 1791322734 | |
Dennis Brown | 7109f53a5f | |
Dennis Brown | 12e51b51c9 | |
Dennis Brown | af7ba72f5e | |
Dennis Brown | e4f1f9f03f | |
Dennis Brown | 824cd8c56b | |
Dennis Brown | 93de55b17c | |
Dennis Brown | 2c3ba3d21e | |
Dennis Brown | b4fafbcb7e | |
Dennis Brown | e547439170 | |
Dennis Brown | ed18056cf8 | |
Dennis Brown | f96ec3e09a |
|
@ -42,7 +42,7 @@ rules:
|
||||||
no-throw-literal: 2
|
no-throw-literal: 2
|
||||||
no-unused-labels: 2
|
no-unused-labels: 2
|
||||||
no-useless-call: 2
|
no-useless-call: 2
|
||||||
no-useless-escape: 2
|
no-useless-escape: 0
|
||||||
no-void: 2
|
no-void: 2
|
||||||
no-with: 2
|
no-with: 2
|
||||||
|
|
||||||
|
|
45
README.md
45
README.md
|
@ -7,28 +7,51 @@ What would make it even easier is having your own Desktop 6502 Simulator to use.
|
||||||
I went ahead and did exactly that. While I am not finished it is usable, and I plan to do whatever I can to
|
I went ahead and did exactly that. While I am not finished it is usable, and I plan to do whatever I can to
|
||||||
make it a great desktop app in the near future.
|
make it a great desktop app in the near future.
|
||||||
|
|
||||||
|
![6502 Desktop Simulator](/assets/6502Desktop_SS.png "6502Desktop on OSX")
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
_At this time there are not any static builds (yet). You will find future builds here in the future._
|
# Getting Started
|
||||||
|
|
||||||
First things first, clone the repository!
|
|
||||||
|
|
||||||
*yarn install* (or npm install)
|
## Binary Downloads
|
||||||
*npm start*
|
|
||||||
|
[OSX Build 0.3.7](https://github.com/3DEsprit/6502SimDesktop/releases/download/0.3.7/6502Desktop-OSX_0.3.7.zip)
|
||||||
|
[Windows Build 0.3.7](https://github.com/3DEsprit/6502SimDesktop/releases/download/0.3.7/6502Desktop-Win_0.3.7.zip)
|
||||||
|
[Linux Build 0.3.7](https://github.com/3DEsprit/6502SimDesktop/releases/download/0.3.7/6502Desktop-Linux_0.3.7.zip)
|
||||||
|
|
||||||
|
|
||||||
|
## Install Manually
|
||||||
|
|
||||||
|
_If there is not a build for your OS or if you would like to compile from source, you can install manually:_
|
||||||
|
|
||||||
|
First things first, clone the repository by downloading with the Green Download button above, or cloning on your system.
|
||||||
|
|
||||||
|
`git clone https://github.com/3DEsprit/6502SimDesktop.git`
|
||||||
|
|
||||||
|
`yarn install` (or `npm install` without [Yarn](https://github.com/yarnpkg/yarn))
|
||||||
|
|
||||||
|
`npm start`
|
||||||
|
|
||||||
|
Have fun!
|
||||||
|
|
||||||
|
|
||||||
## ToDo List
|
## ToDo List
|
||||||
|
|
||||||
* Fix Hexdump
|
* Finish Memory Monitor *In Progress*
|
||||||
|
* Add Menu/Hotkey Support for functions
|
||||||
|
* Update Register/Flag Viewing
|
||||||
|
* Addition of UI Animations
|
||||||
* Create Snazzy Icon (In process)
|
* Create Snazzy Icon (In process)
|
||||||
* Test on Windows/Linux
|
* Test on Linux
|
||||||
* Build Packages for Win/Linux Platforms (Mac build done)
|
* Build Packages for Win/Linux Platforms
|
||||||
* Reactive CSS with the window size
|
* ~~Reactive CSS with the window size~~
|
||||||
* Make the the sim integration more desktop-ish (hotkeys/menu items for assemble debug, and other options).
|
* Make the the sim integration more desktop-ish *In Progress*.
|
||||||
* Various Colored Themes
|
* Various Colored Themes
|
||||||
* Look at options to offer on Mac App Store, and Windows App Store
|
* Look at options to offer on Mac App Store, and Windows App Store
|
||||||
|
* Switch to Electron-Builder for Builds
|
||||||
|
* Change Linux Builds to AppImage
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
The simulator used in this Electron app was created by [Nick Morgon](https://twitter.com/skilldrick), and you can find the original code in the [6502js Repo](https://github.com/skilldrick/6502js).
|
The base simulator used in this app was created by [Nick Morgon](https://twitter.com/skilldrick), and you can find the original code in the [6502js Repo](https://github.com/skilldrick/6502js).
|
||||||
|
|
||||||
|
|
370
app/assembler.js
370
app/assembler.js
|
@ -33,7 +33,7 @@ function SimulatorWidget(node) {
|
||||||
$node.find('.runButton').click(simulator.runBinary);
|
$node.find('.runButton').click(simulator.runBinary);
|
||||||
$node.find('.runButton').click(simulator.stopDebugger);
|
$node.find('.runButton').click(simulator.stopDebugger);
|
||||||
$node.find('.resetButton').click(simulator.reset);
|
$node.find('.resetButton').click(simulator.reset);
|
||||||
$node.find('.hexdumpButton').click(assembler.hexdump);
|
$node.find('.hexdumpButton').click(assembler.hexdump).trigger('keydown', {which: 65});
|
||||||
$node.find('.disassembleButton').click(assembler.disassemble);
|
$node.find('.disassembleButton').click(assembler.disassemble);
|
||||||
$node.find('.debug').on('click', function () {
|
$node.find('.debug').on('click', function () {
|
||||||
$(this).toggleClass('active');
|
$(this).toggleClass('active');
|
||||||
|
@ -49,7 +49,7 @@ function SimulatorWidget(node) {
|
||||||
$node.find('.monitoring').on('click', function () {
|
$node.find('.monitoring').on('click', function () {
|
||||||
$(this).toggleClass('active');
|
$(this).toggleClass('active');
|
||||||
if($(this).hasClass('active')) {
|
if($(this).hasClass('active')) {
|
||||||
|
|
||||||
}
|
}
|
||||||
ui.toggleMonitor();
|
ui.toggleMonitor();
|
||||||
simulator.toggleMonitor();
|
simulator.toggleMonitor();
|
||||||
|
@ -177,10 +177,10 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
// Insert tab at caret position (instead of losing focus)
|
// Insert tab at caret position (instead of losing focus)
|
||||||
var caretStart = this.selectionStart,
|
var caretStart = this.selectionStart,
|
||||||
caretEnd = this.selectionEnd,
|
caretEnd = this.selectionEnd,
|
||||||
currentValue = this.value;
|
currentValue = this.value;
|
||||||
|
|
||||||
this.value = currentValue.substring(0, caretStart) + "\t" + currentValue.substring(caretEnd);
|
this.value = currentValue.substring(0, caretStart) + '\t' + currentValue.substring(caretEnd);
|
||||||
|
|
||||||
// Move cursor forwards one (after tab)
|
// Move cursor forwards one (after tab)
|
||||||
this.selectionStart = this.selectionEnd = caretStart + 1;
|
this.selectionStart = this.selectionEnd = caretStart + 1;
|
||||||
|
@ -204,10 +204,10 @@ function SimulatorWidget(node) {
|
||||||
function Display() {
|
function Display() {
|
||||||
var displayArray = [];
|
var displayArray = [];
|
||||||
var palette = [
|
var palette = [
|
||||||
"#000000", "#ffffff", "#880000", "#aaffee",
|
'#000000', '#ffffff', '#880000', '#aaffee',
|
||||||
"#cc44cc", "#00cc55", "#0000aa", "#eeee77",
|
'#cc44cc', '#00cc55', '#0000aa', '#eeee77',
|
||||||
"#dd8855", "#664400", "#ff7777", "#333333",
|
'#dd8855', '#664400', '#ff7777', '#333333',
|
||||||
"#777777", "#aaff66", "#0088ff", "#bbbbbb"
|
'#777777', '#aaff66', '#0088ff', '#bbbbbb'
|
||||||
];
|
];
|
||||||
var ctx;
|
var ctx;
|
||||||
var width;
|
var width;
|
||||||
|
@ -226,7 +226,7 @@ function SimulatorWidget(node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
ctx.fillStyle = "black";
|
ctx.fillStyle = 'black';
|
||||||
ctx.fillRect(0, 0, width, height);
|
ctx.fillRect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,14 +279,14 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
for (var x = 0; x < length; x++) {
|
for (var x = 0; x < length; x++) {
|
||||||
if ((x & 15) === 0) {
|
if ((x & 15) === 0) {
|
||||||
if (x > 0) { html += "\n"; }
|
if (x > 0) { html += '\n'; }
|
||||||
n = (start + x);
|
n = (start + x);
|
||||||
html += num2hex(((n >> 8) & 0xff));
|
html += num2hex(((n >> 8) & 0xff));
|
||||||
html += num2hex((n & 0xff));
|
html += num2hex((n & 0xff));
|
||||||
html += ": ";
|
html += ': ';
|
||||||
}
|
}
|
||||||
html += num2hex(memory.get(start + x));
|
html += num2hex(memory.get(start + x));
|
||||||
html += " ";
|
html += ' ';
|
||||||
}
|
}
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
@ -871,7 +871,7 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
i58: function () {
|
i58: function () {
|
||||||
regP &= ~0x04;
|
regP &= ~0x04;
|
||||||
throw new Error("Interrupts not implemented");
|
throw new Error('Interrupts not implemented');
|
||||||
//CLI
|
//CLI
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1006,7 +1006,7 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
i78: function () {
|
i78: function () {
|
||||||
regP |= 0x04;
|
regP |= 0x04;
|
||||||
throw new Error("Interrupts not implemented");
|
throw new Error('Interrupts not implemented');
|
||||||
//SEI
|
//SEI
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1499,7 +1499,7 @@ function SimulatorWidget(node) {
|
||||||
},
|
},
|
||||||
|
|
||||||
ierr: function () {
|
ierr: function () {
|
||||||
message("Address $" + addr2hex(regPC) + " - unknown opcode");
|
message('Address $' + addr2hex(regPC) + ' - unknown opcode');
|
||||||
codeRunning = false;
|
codeRunning = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1509,7 +1509,7 @@ function SimulatorWidget(node) {
|
||||||
regSP--;
|
regSP--;
|
||||||
if (regSP < 0) {
|
if (regSP < 0) {
|
||||||
regSP &= 0xff;
|
regSP &= 0xff;
|
||||||
message("6502 Stack filled! Wrapping...");
|
message('6502 Stack filled! Wrapping...');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,7 +1518,7 @@ function SimulatorWidget(node) {
|
||||||
regSP++;
|
regSP++;
|
||||||
if (regSP >= 0x100) {
|
if (regSP >= 0x100) {
|
||||||
regSP &= 0xff;
|
regSP &= 0xff;
|
||||||
message("6502 Stack emptied! Wrapping...");
|
message('6502 Stack emptied! Wrapping...');
|
||||||
}
|
}
|
||||||
value = memory.get(regSP + 0x100);
|
value = memory.get(regSP + 0x100);
|
||||||
return value;
|
return value;
|
||||||
|
@ -1582,7 +1582,7 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
if ((regPC === 0) || (!codeRunning && !debugging)) {
|
if ((regPC === 0) || (!codeRunning && !debugging)) {
|
||||||
stop();
|
stop();
|
||||||
message("Program end at PC=$" + addr2hex(regPC - 1));
|
message('Program end at PC=$' + addr2hex(regPC - 1));
|
||||||
ui.stop();
|
ui.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1611,10 +1611,10 @@ function SimulatorWidget(node) {
|
||||||
function handleMonitorRangeChange() {
|
function handleMonitorRangeChange() {
|
||||||
|
|
||||||
var $start = $node.find('.start'),
|
var $start = $node.find('.start'),
|
||||||
$length = $node.find('.length'),
|
$length = $node.find('.length'),
|
||||||
start = parseInt($start.val(), 16),
|
start = parseInt($start.val(), 16),
|
||||||
length = parseInt($length.val(), 16),
|
length = parseInt($length.val(), 16),
|
||||||
end = start + length - 1;
|
end = start + length - 1;
|
||||||
|
|
||||||
$start.removeClass('monitor-invalid');
|
$start.removeClass('monitor-invalid');
|
||||||
$length.removeClass('monitor-invalid');
|
$length.removeClass('monitor-invalid');
|
||||||
|
@ -1632,15 +1632,15 @@ function SimulatorWidget(node) {
|
||||||
// Execute one instruction and print values
|
// Execute one instruction and print values
|
||||||
function debugExec() {
|
function debugExec() {
|
||||||
//if (codeRunning) {
|
//if (codeRunning) {
|
||||||
execute(true);
|
execute(true);
|
||||||
//}
|
//}
|
||||||
updateDebugInfo();
|
updateDebugInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDebugInfo() {
|
function updateDebugInfo() {
|
||||||
var html = "A=$" + num2hex(regA) + " X=$" + num2hex(regX) + " Y=$" + num2hex(regY) +
|
var html = 'A=$' + num2hex(regA) + ' X=$' + num2hex(regX) + ' Y=$' + num2hex(regY) +
|
||||||
" SP=$" + num2hex(regSP) + " PC=$" + addr2hex(regPC) + " NV-BDIZC: ";
|
' SP=$' + num2hex(regSP) + ' PC=$' + addr2hex(regPC) + ' NV-BDIZC: ';
|
||||||
for (var i = 7; i >=0; i--) {
|
for (var i = 7; i >= 0; i--) {
|
||||||
html += regP >> i & 1;
|
html += regP >> i & 1;
|
||||||
}
|
}
|
||||||
$node.find('.minidebugger').html(html);
|
$node.find('.minidebugger').html(html);
|
||||||
|
@ -1649,21 +1649,21 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
// gotoAddr() - Set PC to address (or address of label)
|
// gotoAddr() - Set PC to address (or address of label)
|
||||||
function gotoAddr() {
|
function gotoAddr() {
|
||||||
var inp = prompt("Enter address or label", "");
|
var inp = prompt('Enter address or label', '');
|
||||||
var addr = 0;
|
var addr = 0;
|
||||||
if (labels.find(inp)) {
|
if (labels.find(inp)) {
|
||||||
addr = labels.getPC(inp);
|
addr = labels.getPC(inp);
|
||||||
} else {
|
} else {
|
||||||
if (inp.match(/^0x[0-9a-f]{1,4}$/i)) {
|
if (inp.match(/^0x[0-9a-f]{1,4}$/i)) {
|
||||||
inp = inp.replace(/^0x/, "");
|
inp = inp.replace(/^0x/, '');
|
||||||
addr = parseInt(inp, 16);
|
addr = parseInt(inp, 16);
|
||||||
} else if (inp.match(/^\$[0-9a-f]{1,4}$/i)) {
|
} else if (inp.match(/^\$[0-9a-f]{1,4}$/i)) {
|
||||||
inp = inp.replace(/^\$/, "");
|
inp = inp.replace(/^\$/, '');
|
||||||
addr = parseInt(inp, 16);
|
addr = parseInt(inp, 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (addr === 0) {
|
if (addr === 0) {
|
||||||
message("Unable to find/parse given address/label");
|
message('Unable to find/parse given address/label');
|
||||||
} else {
|
} else {
|
||||||
regPC = addr;
|
regPC = addr;
|
||||||
}
|
}
|
||||||
|
@ -1698,7 +1698,7 @@ function SimulatorWidget(node) {
|
||||||
function stop() {
|
function stop() {
|
||||||
codeRunning = false;
|
codeRunning = false;
|
||||||
clearInterval(executeId);
|
clearInterval(executeId);
|
||||||
message("\nStopped\n");
|
message('\nStopped\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleMonitor() {
|
function toggleMonitor() {
|
||||||
|
@ -1725,7 +1725,7 @@ function SimulatorWidget(node) {
|
||||||
function indexLines(lines, symbols) {
|
function indexLines(lines, symbols) {
|
||||||
for (var i = 0; i < lines.length; i++) {
|
for (var i = 0; i < lines.length; i++) {
|
||||||
if (!indexLine(lines[i], symbols)) {
|
if (!indexLine(lines[i], symbols)) {
|
||||||
message("**Label already defined at line " + (i + 1) + ":** " + lines[i]);
|
message('**Label already defined at line ' + (i + 1) + ':** ' + lines[i]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1735,21 +1735,21 @@ function SimulatorWidget(node) {
|
||||||
// Extract label if line contains one and calculate position in memory.
|
// Extract label if line contains one and calculate position in memory.
|
||||||
// Return false if label already exists.
|
// Return false if label already exists.
|
||||||
function indexLine(input, symbols) {
|
function indexLine(input, symbols) {
|
||||||
|
|
||||||
// Figure out how many bytes this instruction takes
|
// Figure out how many bytes this instruction takes
|
||||||
var currentPC = assembler.getCurrentPC();
|
var currentPC = assembler.getCurrentPC();
|
||||||
assembler.assembleLine(input, 0, symbols); //TODO: find a better way for Labels to have access to assembler
|
assembler.assembleLine(input, 0, symbols); //TODO: find a better way for Labels to have access to assembler
|
||||||
|
|
||||||
// Find command or label
|
// Find command or label
|
||||||
if (input.match(/^\w+:/)) {
|
if (input.match(/^\w+:/)) {
|
||||||
var label = input.replace(/(^\w+):.*$/, "$1");
|
var label = input.replace(/(^\w+):.*$/, '$1');
|
||||||
|
|
||||||
if (symbols.lookup(label)) {
|
if (symbols.lookup(label)) {
|
||||||
message("**Label " + label + "is already used as a symbol; please rename one of them**");
|
message('**Label ' + label + 'is already used as a symbol; please rename one of them**');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return push(label + "|" + currentPC);
|
return push(label + '|' + currentPC);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1759,7 +1759,7 @@ function SimulatorWidget(node) {
|
||||||
if (find(name)) {
|
if (find(name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
labelIndex.push(name + "|");
|
labelIndex.push(name + '|');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1767,7 +1767,7 @@ function SimulatorWidget(node) {
|
||||||
function find(name) {
|
function find(name) {
|
||||||
var nameAndAddr;
|
var nameAndAddr;
|
||||||
for (var i = 0; i < labelIndex.length; i++) {
|
for (var i = 0; i < labelIndex.length; i++) {
|
||||||
nameAndAddr = labelIndex[i].split("|");
|
nameAndAddr = labelIndex[i].split('|');
|
||||||
if (name === nameAndAddr[0]) {
|
if (name === nameAndAddr[0]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1779,9 +1779,9 @@ function SimulatorWidget(node) {
|
||||||
function setPC(name, addr) {
|
function setPC(name, addr) {
|
||||||
var nameAndAddr;
|
var nameAndAddr;
|
||||||
for (var i = 0; i < labelIndex.length; i++) {
|
for (var i = 0; i < labelIndex.length; i++) {
|
||||||
nameAndAddr = labelIndex[i].split("|");
|
nameAndAddr = labelIndex[i].split('|');
|
||||||
if (name === nameAndAddr[0]) {
|
if (name === nameAndAddr[0]) {
|
||||||
labelIndex[i] = name + "|" + addr;
|
labelIndex[i] = name + '|' + addr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1792,7 +1792,7 @@ function SimulatorWidget(node) {
|
||||||
function getPC(name) {
|
function getPC(name) {
|
||||||
var nameAndAddr;
|
var nameAndAddr;
|
||||||
for (var i = 0; i < labelIndex.length; i++) {
|
for (var i = 0; i < labelIndex.length; i++) {
|
||||||
nameAndAddr = labelIndex[i].split("|");
|
nameAndAddr = labelIndex[i].split('|');
|
||||||
if (name === nameAndAddr[0]) {
|
if (name === nameAndAddr[0]) {
|
||||||
return (nameAndAddr[1]);
|
return (nameAndAddr[1]);
|
||||||
}
|
}
|
||||||
|
@ -1801,11 +1801,11 @@ function SimulatorWidget(node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayMessage() {
|
function displayMessage() {
|
||||||
var str = "Found " + labelIndex.length + " label";
|
var str = 'Found ' + labelIndex.length + ' label';
|
||||||
if (labelIndex.length !== 1) {
|
if (labelIndex.length !== 1) {
|
||||||
str += "s";
|
str += 's';
|
||||||
}
|
}
|
||||||
message(str + ".");
|
message(str + '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
|
@ -1830,86 +1830,86 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
var Opcodes = [
|
var Opcodes = [
|
||||||
/* Name, Imm, ZP, ZPX, ZPY, ABS, ABSX, ABSY, IND, INDX, INDY, SNGL, BRA */
|
/* Name, Imm, ZP, ZPX, ZPY, ABS, ABSX, ABSY, IND, INDX, INDY, SNGL, BRA */
|
||||||
["ADC", 0x69, 0x65, 0x75, null, 0x6d, 0x7d, 0x79, null, 0x61, 0x71, null, null],
|
['ADC', 0x69, 0x65, 0x75, null, 0x6d, 0x7d, 0x79, null, 0x61, 0x71, null, null],
|
||||||
["AND", 0x29, 0x25, 0x35, null, 0x2d, 0x3d, 0x39, null, 0x21, 0x31, null, null],
|
['AND', 0x29, 0x25, 0x35, null, 0x2d, 0x3d, 0x39, null, 0x21, 0x31, null, null],
|
||||||
["ASL", null, 0x06, 0x16, null, 0x0e, 0x1e, null, null, null, null, 0x0a, null],
|
['ASL', null, 0x06, 0x16, null, 0x0e, 0x1e, null, null, null, null, 0x0a, null],
|
||||||
["BIT", null, 0x24, null, null, 0x2c, null, null, null, null, null, null, null],
|
['BIT', null, 0x24, null, null, 0x2c, null, null, null, null, null, null, null],
|
||||||
["BPL", null, null, null, null, null, null, null, null, null, null, null, 0x10],
|
['BPL', null, null, null, null, null, null, null, null, null, null, null, 0x10],
|
||||||
["BMI", null, null, null, null, null, null, null, null, null, null, null, 0x30],
|
['BMI', null, null, null, null, null, null, null, null, null, null, null, 0x30],
|
||||||
["BVC", null, null, null, null, null, null, null, null, null, null, null, 0x50],
|
['BVC', null, null, null, null, null, null, null, null, null, null, null, 0x50],
|
||||||
["BVS", null, null, null, null, null, null, null, null, null, null, null, 0x70],
|
['BVS', null, null, null, null, null, null, null, null, null, null, null, 0x70],
|
||||||
["BCC", null, null, null, null, null, null, null, null, null, null, null, 0x90],
|
['BCC', null, null, null, null, null, null, null, null, null, null, null, 0x90],
|
||||||
["BCS", null, null, null, null, null, null, null, null, null, null, null, 0xb0],
|
['BCS', null, null, null, null, null, null, null, null, null, null, null, 0xb0],
|
||||||
["BNE", null, null, null, null, null, null, null, null, null, null, null, 0xd0],
|
['BNE', null, null, null, null, null, null, null, null, null, null, null, 0xd0],
|
||||||
["BEQ", null, null, null, null, null, null, null, null, null, null, null, 0xf0],
|
['BEQ', null, null, null, null, null, null, null, null, null, null, null, 0xf0],
|
||||||
["BRK", null, null, null, null, null, null, null, null, null, null, 0x00, null],
|
['BRK', null, null, null, null, null, null, null, null, null, null, 0x00, null],
|
||||||
["CMP", 0xc9, 0xc5, 0xd5, null, 0xcd, 0xdd, 0xd9, null, 0xc1, 0xd1, null, null],
|
['CMP', 0xc9, 0xc5, 0xd5, null, 0xcd, 0xdd, 0xd9, null, 0xc1, 0xd1, null, null],
|
||||||
["CPX", 0xe0, 0xe4, null, null, 0xec, null, null, null, null, null, null, null],
|
['CPX', 0xe0, 0xe4, null, null, 0xec, null, null, null, null, null, null, null],
|
||||||
["CPY", 0xc0, 0xc4, null, null, 0xcc, null, null, null, null, null, null, null],
|
['CPY', 0xc0, 0xc4, null, null, 0xcc, null, null, null, null, null, null, null],
|
||||||
["DEC", null, 0xc6, 0xd6, null, 0xce, 0xde, null, null, null, null, null, null],
|
['DEC', null, 0xc6, 0xd6, null, 0xce, 0xde, null, null, null, null, null, null],
|
||||||
["EOR", 0x49, 0x45, 0x55, null, 0x4d, 0x5d, 0x59, null, 0x41, 0x51, null, null],
|
['EOR', 0x49, 0x45, 0x55, null, 0x4d, 0x5d, 0x59, null, 0x41, 0x51, null, null],
|
||||||
["CLC", null, null, null, null, null, null, null, null, null, null, 0x18, null],
|
['CLC', null, null, null, null, null, null, null, null, null, null, 0x18, null],
|
||||||
["SEC", null, null, null, null, null, null, null, null, null, null, 0x38, null],
|
['SEC', null, null, null, null, null, null, null, null, null, null, 0x38, null],
|
||||||
["CLI", null, null, null, null, null, null, null, null, null, null, 0x58, null],
|
['CLI', null, null, null, null, null, null, null, null, null, null, 0x58, null],
|
||||||
["SEI", null, null, null, null, null, null, null, null, null, null, 0x78, null],
|
['SEI', null, null, null, null, null, null, null, null, null, null, 0x78, null],
|
||||||
["CLV", null, null, null, null, null, null, null, null, null, null, 0xb8, null],
|
['CLV', null, null, null, null, null, null, null, null, null, null, 0xb8, null],
|
||||||
["CLD", null, null, null, null, null, null, null, null, null, null, 0xd8, null],
|
['CLD', null, null, null, null, null, null, null, null, null, null, 0xd8, null],
|
||||||
["SED", null, null, null, null, null, null, null, null, null, null, 0xf8, null],
|
['SED', null, null, null, null, null, null, null, null, null, null, 0xf8, null],
|
||||||
["INC", null, 0xe6, 0xf6, null, 0xee, 0xfe, null, null, null, null, null, null],
|
['INC', null, 0xe6, 0xf6, null, 0xee, 0xfe, null, null, null, null, null, null],
|
||||||
["JMP", null, null, null, null, 0x4c, null, null, 0x6c, null, null, null, null],
|
['JMP', null, null, null, null, 0x4c, null, null, 0x6c, null, null, null, null],
|
||||||
["JSR", null, null, null, null, 0x20, null, null, null, null, null, null, null],
|
['JSR', null, null, null, null, 0x20, null, null, null, null, null, null, null],
|
||||||
["LDA", 0xa9, 0xa5, 0xb5, null, 0xad, 0xbd, 0xb9, null, 0xa1, 0xb1, null, null],
|
['LDA', 0xa9, 0xa5, 0xb5, null, 0xad, 0xbd, 0xb9, null, 0xa1, 0xb1, null, null],
|
||||||
["LDX", 0xa2, 0xa6, null, 0xb6, 0xae, null, 0xbe, null, null, null, null, null],
|
['LDX', 0xa2, 0xa6, null, 0xb6, 0xae, null, 0xbe, null, null, null, null, null],
|
||||||
["LDY", 0xa0, 0xa4, 0xb4, null, 0xac, 0xbc, null, null, null, null, null, null],
|
['LDY', 0xa0, 0xa4, 0xb4, null, 0xac, 0xbc, null, null, null, null, null, null],
|
||||||
["LSR", null, 0x46, 0x56, null, 0x4e, 0x5e, null, null, null, null, 0x4a, null],
|
['LSR', null, 0x46, 0x56, null, 0x4e, 0x5e, null, null, null, null, 0x4a, null],
|
||||||
["NOP", null, null, null, null, null, null, null, null, null, null, 0xea, null],
|
['NOP', null, null, null, null, null, null, null, null, null, null, 0xea, null],
|
||||||
["ORA", 0x09, 0x05, 0x15, null, 0x0d, 0x1d, 0x19, null, 0x01, 0x11, null, null],
|
['ORA', 0x09, 0x05, 0x15, null, 0x0d, 0x1d, 0x19, null, 0x01, 0x11, null, null],
|
||||||
["TAX", null, null, null, null, null, null, null, null, null, null, 0xaa, null],
|
['TAX', null, null, null, null, null, null, null, null, null, null, 0xaa, null],
|
||||||
["TXA", null, null, null, null, null, null, null, null, null, null, 0x8a, null],
|
['TXA', null, null, null, null, null, null, null, null, null, null, 0x8a, null],
|
||||||
["DEX", null, null, null, null, null, null, null, null, null, null, 0xca, null],
|
['DEX', null, null, null, null, null, null, null, null, null, null, 0xca, null],
|
||||||
["INX", null, null, null, null, null, null, null, null, null, null, 0xe8, null],
|
['INX', null, null, null, null, null, null, null, null, null, null, 0xe8, null],
|
||||||
["TAY", null, null, null, null, null, null, null, null, null, null, 0xa8, null],
|
['TAY', null, null, null, null, null, null, null, null, null, null, 0xa8, null],
|
||||||
["TYA", null, null, null, null, null, null, null, null, null, null, 0x98, null],
|
['TYA', null, null, null, null, null, null, null, null, null, null, 0x98, null],
|
||||||
["DEY", null, null, null, null, null, null, null, null, null, null, 0x88, null],
|
['DEY', null, null, null, null, null, null, null, null, null, null, 0x88, null],
|
||||||
["INY", null, null, null, null, null, null, null, null, null, null, 0xc8, null],
|
['INY', null, null, null, null, null, null, null, null, null, null, 0xc8, null],
|
||||||
["ROR", null, 0x66, 0x76, null, 0x6e, 0x7e, null, null, null, null, 0x6a, null],
|
['ROR', null, 0x66, 0x76, null, 0x6e, 0x7e, null, null, null, null, 0x6a, null],
|
||||||
["ROL", null, 0x26, 0x36, null, 0x2e, 0x3e, null, null, null, null, 0x2a, null],
|
['ROL', null, 0x26, 0x36, null, 0x2e, 0x3e, null, null, null, null, 0x2a, null],
|
||||||
["RTI", null, null, null, null, null, null, null, null, null, null, 0x40, null],
|
['RTI', null, null, null, null, null, null, null, null, null, null, 0x40, null],
|
||||||
["RTS", null, null, null, null, null, null, null, null, null, null, 0x60, null],
|
['RTS', null, null, null, null, null, null, null, null, null, null, 0x60, null],
|
||||||
["SBC", 0xe9, 0xe5, 0xf5, null, 0xed, 0xfd, 0xf9, null, 0xe1, 0xf1, null, null],
|
['SBC', 0xe9, 0xe5, 0xf5, null, 0xed, 0xfd, 0xf9, null, 0xe1, 0xf1, null, null],
|
||||||
["STA", null, 0x85, 0x95, null, 0x8d, 0x9d, 0x99, null, 0x81, 0x91, null, null],
|
['STA', null, 0x85, 0x95, null, 0x8d, 0x9d, 0x99, null, 0x81, 0x91, null, null],
|
||||||
["TXS", null, null, null, null, null, null, null, null, null, null, 0x9a, null],
|
['TXS', null, null, null, null, null, null, null, null, null, null, 0x9a, null],
|
||||||
["TSX", null, null, null, null, null, null, null, null, null, null, 0xba, null],
|
['TSX', null, null, null, null, null, null, null, null, null, null, 0xba, null],
|
||||||
["PHA", null, null, null, null, null, null, null, null, null, null, 0x48, null],
|
['PHA', null, null, null, null, null, null, null, null, null, null, 0x48, null],
|
||||||
["PLA", null, null, null, null, null, null, null, null, null, null, 0x68, null],
|
['PLA', null, null, null, null, null, null, null, null, null, null, 0x68, null],
|
||||||
["PHP", null, null, null, null, null, null, null, null, null, null, 0x08, null],
|
['PHP', null, null, null, null, null, null, null, null, null, null, 0x08, null],
|
||||||
["PLP", null, null, null, null, null, null, null, null, null, null, 0x28, null],
|
['PLP', null, null, null, null, null, null, null, null, null, null, 0x28, null],
|
||||||
["STX", null, 0x86, null, 0x96, 0x8e, null, null, null, null, null, null, null],
|
['STX', null, 0x86, null, 0x96, 0x8e, null, null, null, null, null, null, null],
|
||||||
["STY", null, 0x84, 0x94, null, 0x8c, null, null, null, null, null, null, null],
|
['STY', null, 0x84, 0x94, null, 0x8c, null, null, null, null, null, null, null],
|
||||||
["WDM", 0x42, 0x42, null, null, null, null, null, null, null, null, null, null],
|
['WDM', 0x42, 0x42, null, null, null, null, null, null, null, null, null, null],
|
||||||
["---", null, null, null, null, null, null, null, null, null, null, null, null]
|
['---', null, null, null, null, null, null, null, null, null, null, null, null]
|
||||||
];
|
];
|
||||||
|
|
||||||
// Assembles the code into memory
|
// Assembles the code into memory
|
||||||
function assembleCode() {
|
function assembleCode() {
|
||||||
var BOOTSTRAP_ADDRESS = 0x600;
|
var BOOTSTRAP_ADDRESS = 0x600;
|
||||||
|
|
||||||
wasOutOfRangeBranch = false;
|
wasOutOfRangeBranch = false;
|
||||||
|
|
||||||
simulator.reset();
|
simulator.reset();
|
||||||
labels.reset();
|
labels.reset();
|
||||||
defaultCodePC = BOOTSTRAP_ADDRESS;
|
defaultCodePC = BOOTSTRAP_ADDRESS;
|
||||||
$node.find('.messages code').empty();
|
$node.find('.messages code').empty();
|
||||||
|
|
||||||
var code = $node.find('.code').val();
|
var code = $node.find('.code').val();
|
||||||
code += "\n\n";
|
code += '\n\n';
|
||||||
var lines = code.split("\n");
|
var lines = code.split('\n');
|
||||||
codeAssembledOK = true;
|
codeAssembledOK = true;
|
||||||
|
|
||||||
message("Preprocessing ...");
|
message('Preprocessing ...');
|
||||||
var symbols = preprocess(lines);
|
var symbols = preprocess(lines);
|
||||||
|
|
||||||
message("Indexing labels ...");
|
message('Indexing labels ...');
|
||||||
defaultCodePC = BOOTSTRAP_ADDRESS;
|
defaultCodePC = BOOTSTRAP_ADDRESS;
|
||||||
if (!labels.indexLines(lines, symbols)) {
|
if (!labels.indexLines(lines, symbols)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1917,8 +1917,8 @@ function SimulatorWidget(node) {
|
||||||
labels.displayMessage();
|
labels.displayMessage();
|
||||||
|
|
||||||
defaultCodePC = BOOTSTRAP_ADDRESS;
|
defaultCodePC = BOOTSTRAP_ADDRESS;
|
||||||
message("Assembling code ...");
|
message('Assembling code ...');
|
||||||
|
|
||||||
codeLen = 0;
|
codeLen = 0;
|
||||||
for (var i = 0; i < lines.length; i++) {
|
for (var i = 0; i < lines.length; i++) {
|
||||||
if (!assembleLine(lines[i], i, symbols)) {
|
if (!assembleLine(lines[i], i, symbols)) {
|
||||||
|
@ -1929,7 +1929,7 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
if (codeLen === 0) {
|
if (codeLen === 0) {
|
||||||
codeAssembledOK = false;
|
codeAssembledOK = false;
|
||||||
message("No code to run.");
|
message('No code to run.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (codeAssembledOK) {
|
if (codeAssembledOK) {
|
||||||
|
@ -1937,10 +1937,10 @@ function SimulatorWidget(node) {
|
||||||
memory.set(defaultCodePC, 0x00); //set a null byte at the end of the code
|
memory.set(defaultCodePC, 0x00); //set a null byte at the end of the code
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
var str = lines[i].replace("<", "<").replace(">", ">");
|
var str = lines[i].replace('<', '<').replace('>', '>');
|
||||||
|
|
||||||
if(!wasOutOfRangeBranch) {
|
if(!wasOutOfRangeBranch) {
|
||||||
message("**Syntax error line " + (i + 1) + ": " + str + "**");
|
message('**Syntax error line ' + (i + 1) + ': ' + str + '**');
|
||||||
} else {
|
} else {
|
||||||
message('**Out of range branch on line ' + (i + 1) + ' (branches are limited to -128 to +127): ' + str + '**');
|
message('**Out of range branch on line ' + (i + 1) + ' (branches are limited to -128 to +127): ' + str + '**');
|
||||||
}
|
}
|
||||||
|
@ -1949,51 +1949,51 @@ function SimulatorWidget(node) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
message("Code assembled successfully, " + codeLen + " bytes.");
|
message('Code assembled successfully, ' + codeLen + ' bytes.');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanitize input: remove comments and trim leading/trailing whitespace
|
// Sanitize input: remove comments and trim leading/trailing whitespace
|
||||||
function sanitize(line) {
|
function sanitize(line) {
|
||||||
// remove comments
|
// remove comments
|
||||||
var no_comments = line.replace(/^(.*?);.*/, "$1");
|
var no_comments = line.replace(/^(.*?);.*/, '$1');
|
||||||
|
|
||||||
// trim line
|
// trim line
|
||||||
return no_comments.replace(/^\s+/, "").replace(/\s+$/, "");
|
return no_comments.replace(/^\s+/, '').replace(/\s+$/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function preprocess(lines) {
|
function preprocess(lines) {
|
||||||
var table = [];
|
var table = [];
|
||||||
var PREFIX = "__"; // Using a prefix avoids clobbering any predefined properties
|
var PREFIX = '__'; // Using a prefix avoids clobbering any predefined properties
|
||||||
|
|
||||||
function lookup(key) {
|
function lookup(key) {
|
||||||
if (table.hasOwnProperty(PREFIX + key)) return table[PREFIX + key];
|
if (table.hasOwnProperty(PREFIX + key)) return table[PREFIX + key];
|
||||||
else return undefined;
|
else return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function add(key, value) {
|
function add(key, value) {
|
||||||
var valueAlreadyExists = table.hasOwnProperty(PREFIX + key)
|
var valueAlreadyExists = table.hasOwnProperty(PREFIX + key)
|
||||||
if (!valueAlreadyExists) {
|
if (!valueAlreadyExists) {
|
||||||
table[PREFIX + key] = value;
|
table[PREFIX + key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the substitution table
|
// Build the substitution table
|
||||||
for (var i = 0; i < lines.length; i++) {
|
for (var i = 0; i < lines.length; i++) {
|
||||||
lines[i] = sanitize(lines[i]);
|
lines[i] = sanitize(lines[i]);
|
||||||
var match_data = lines[i].match(/^define\s+(\w+)\s+(\S+)/);
|
var match_data = lines[i].match(/^define\s+(\w+)\s+(\S+)/);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
add(match_data[1], sanitize(match_data[2]));
|
add(match_data[1], sanitize(match_data[2]));
|
||||||
lines[i] = ""; // We're done with this preprocessor directive, so delete it
|
lines[i] = ''; // We're done with this preprocessor directive, so delete it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callers will only need the lookup function
|
// Callers will only need the lookup function
|
||||||
return {
|
return {
|
||||||
lookup: lookup
|
lookup: lookup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assembles one line of code.
|
// Assembles one line of code.
|
||||||
// Returns true if it assembled successfully, false otherwise.
|
// Returns true if it assembled successfully, false otherwise.
|
||||||
function assembleLine(input, lineno, symbols) {
|
function assembleLine(input, lineno, symbols) {
|
||||||
|
@ -2001,19 +2001,19 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
// Find command or label
|
// Find command or label
|
||||||
if (input.match(/^\w+:/)) {
|
if (input.match(/^\w+:/)) {
|
||||||
label = input.replace(/(^\w+):.*$/, "$1");
|
label = input.replace(/(^\w+):.*$/, '$1');
|
||||||
if (input.match(/^\w+:[\s]*\w+.*$/)) {
|
if (input.match(/^\w+:[\s]*\w+.*$/)) {
|
||||||
input = input.replace(/^\w+:[\s]*(.*)$/, "$1");
|
input = input.replace(/^\w+:[\s]*(.*)$/, '$1');
|
||||||
command = input.replace(/^(\w+).*$/, "$1");
|
command = input.replace(/^(\w+).*$/, '$1');
|
||||||
} else {
|
} else {
|
||||||
command = "";
|
command = '';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
command = input.replace(/^(\w+).*$/, "$1");
|
command = input.replace(/^(\w+).*$/, '$1');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing to do for blank lines
|
// Nothing to do for blank lines
|
||||||
if (command === "") {
|
if (command === '') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2021,15 +2021,15 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
if (input.match(/^\*\s*=\s*\$?[0-9a-f]*$/)) {
|
if (input.match(/^\*\s*=\s*\$?[0-9a-f]*$/)) {
|
||||||
// equ spotted
|
// equ spotted
|
||||||
param = input.replace(/^\s*\*\s*=\s*/, "");
|
param = input.replace(/^\s*\*\s*=\s*/, '');
|
||||||
if (param[0] === "$") {
|
if (param[0] === '$') {
|
||||||
param = param.replace(/^\$/, "");
|
param = param.replace(/^\$/, '');
|
||||||
addr = parseInt(param, 16);
|
addr = parseInt(param, 16);
|
||||||
} else {
|
} else {
|
||||||
addr = parseInt(param, 10);
|
addr = parseInt(param, 10);
|
||||||
}
|
}
|
||||||
if ((addr < 0) || (addr > 0xffff)) {
|
if ((addr < 0) || (addr > 0xffff)) {
|
||||||
message("Unable to relocate code outside 64k memory");
|
message('Unable to relocate code outside 64k memory');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
defaultCodePC = addr;
|
defaultCodePC = addr;
|
||||||
|
@ -2037,16 +2037,16 @@ function SimulatorWidget(node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.match(/^\w+\s+.*?$/)) {
|
if (input.match(/^\w+\s+.*?$/)) {
|
||||||
param = input.replace(/^\w+\s+(.*?)/, "$1");
|
param = input.replace(/^\w+\s+(.*?)/, '$1');
|
||||||
} else if (input.match(/^\w+$/)) {
|
} else if (input.match(/^\w+$/)) {
|
||||||
param = "";
|
param = '';
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
param = param.replace(/[ ]/g, "");
|
param = param.replace(/[ ]/g, '');
|
||||||
|
|
||||||
if (command === "DCB") {
|
if (command === 'DCB') {
|
||||||
return DCB(param);
|
return DCB(param);
|
||||||
}
|
}
|
||||||
for (var o = 0; o < Opcodes.length; o++) {
|
for (var o = 0; o < Opcodes.length; o++) {
|
||||||
|
@ -2065,22 +2065,22 @@ function SimulatorWidget(node) {
|
||||||
if (checkBranch(param, Opcodes[o][12])) { return true; }
|
if (checkBranch(param, Opcodes[o][12])) { return true; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false; // Unknown syntax
|
return false; // Unknown syntax
|
||||||
}
|
}
|
||||||
|
|
||||||
function DCB(param) {
|
function DCB(param) {
|
||||||
var values, number, str, ch;
|
var values, number, str, ch;
|
||||||
values = param.split(",");
|
values = param.split(',');
|
||||||
if (values.length === 0) { return false; }
|
if (values.length === 0) { return false; }
|
||||||
for (var v = 0; v < values.length; v++) {
|
for (var v = 0; v < values.length; v++) {
|
||||||
str = values[v];
|
str = values[v];
|
||||||
if (str) {
|
if (str) {
|
||||||
ch = str.substring(0, 1);
|
ch = str.substring(0, 1);
|
||||||
if (ch === "$") {
|
if (ch === '$') {
|
||||||
number = parseInt(str.replace(/^\$/, ""), 16);
|
number = parseInt(str.replace(/^\$/, ''), 16);
|
||||||
pushByte(number);
|
pushByte(number);
|
||||||
} else if (ch >= "0" && ch <= "9") {
|
} else if (ch >= '0' && ch <= '9') {
|
||||||
number = parseInt(str, 10);
|
number = parseInt(str, 10);
|
||||||
pushByte(number);
|
pushByte(number);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2090,7 +2090,7 @@ function SimulatorWidget(node) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to parse the given parameter as a byte operand.
|
// Try to parse the given parameter as a byte operand.
|
||||||
// Returns the (positive) value if successful, otherwise -1
|
// Returns the (positive) value if successful, otherwise -1
|
||||||
function tryParseByteOperand(param, symbols) {
|
function tryParseByteOperand(param, symbols) {
|
||||||
|
@ -2100,9 +2100,9 @@ function SimulatorWidget(node) {
|
||||||
param = lookupVal;
|
param = lookupVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var value;
|
var value;
|
||||||
|
|
||||||
// Is it a hexadecimal operand?
|
// Is it a hexadecimal operand?
|
||||||
var match_data = param.match(/^\$([0-9a-f]{1,2})$/i);
|
var match_data = param.match(/^\$([0-9a-f]{1,2})$/i);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
|
@ -2114,15 +2114,15 @@ function SimulatorWidget(node) {
|
||||||
value = parseInt(match_data[1], 10);
|
value = parseInt(match_data[1], 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate range
|
// Validate range
|
||||||
if (value >= 0 && value <= 0xff) {
|
if (value >= 0 && value <= 0xff) {
|
||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to parse the given parameter as a word operand.
|
// Try to parse the given parameter as a word operand.
|
||||||
// Returns the (positive) value if successful, otherwise -1
|
// Returns the (positive) value if successful, otherwise -1
|
||||||
function tryParseWordOperand(param, symbols) {
|
function tryParseWordOperand(param, symbols) {
|
||||||
|
@ -2132,9 +2132,9 @@ function SimulatorWidget(node) {
|
||||||
param = lookupVal;
|
param = lookupVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var value;
|
var value;
|
||||||
|
|
||||||
// Is it a hexadecimal operand?
|
// Is it a hexadecimal operand?
|
||||||
var match_data = param.match(/^\$([0-9a-f]{3,4})$/i);
|
var match_data = param.match(/^\$([0-9a-f]{3,4})$/i);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
|
@ -2146,7 +2146,7 @@ function SimulatorWidget(node) {
|
||||||
value = parseInt(match_data[1], 10);
|
value = parseInt(match_data[1], 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate range
|
// Validate range
|
||||||
if (value >= 0 && value <= 0xffff) {
|
if (value >= 0 && value <= 0xffff) {
|
||||||
return value;
|
return value;
|
||||||
|
@ -2170,8 +2170,8 @@ function SimulatorWidget(node) {
|
||||||
var distance = addr - defaultCodePC - 1;
|
var distance = addr - defaultCodePC - 1;
|
||||||
|
|
||||||
if(distance < -128 || distance > 127) {
|
if(distance < -128 || distance > 127) {
|
||||||
wasOutOfRangeBranch = true;
|
wasOutOfRangeBranch = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pushByte(distance);
|
pushByte(distance);
|
||||||
|
@ -2182,7 +2182,7 @@ function SimulatorWidget(node) {
|
||||||
function checkImmediate(param, opcode, symbols) {
|
function checkImmediate(param, opcode, symbols) {
|
||||||
var value, label, hilo, addr;
|
var value, label, hilo, addr;
|
||||||
if (opcode === null) { return false; }
|
if (opcode === null) { return false; }
|
||||||
|
|
||||||
var match_data = param.match(/^#([\w\$]+)$/i);
|
var match_data = param.match(/^#([\w\$]+)$/i);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
var operand = tryParseByteOperand(match_data[1], symbols);
|
var operand = tryParseByteOperand(match_data[1], symbols);
|
||||||
|
@ -2192,30 +2192,30 @@ function SimulatorWidget(node) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Label lo/hi
|
// Label lo/hi
|
||||||
if (param.match(/^#[<>]\w+$/)) {
|
if (param.match(/^#[<>]\w+$/)) {
|
||||||
label = param.replace(/^#[<>](\w+)$/, "$1");
|
label = param.replace(/^#[<>](\w+)$/, '$1');
|
||||||
hilo = param.replace(/^#([<>]).*$/, "$1");
|
hilo = param.replace(/^#([<>]).*$/, '$1');
|
||||||
pushByte(opcode);
|
pushByte(opcode);
|
||||||
if (labels.find(label)) {
|
if (labels.find(label)) {
|
||||||
addr = labels.getPC(label);
|
addr = labels.getPC(label);
|
||||||
switch(hilo) {
|
switch(hilo) {
|
||||||
case ">":
|
case '>':
|
||||||
pushByte((addr >> 8) & 0xff);
|
pushByte((addr >> 8) & 0xff);
|
||||||
return true;
|
return true;
|
||||||
case "<":
|
case '<':
|
||||||
pushByte(addr & 0xff);
|
pushByte(addr & 0xff);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pushByte(0x00);
|
pushByte(0x00);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2223,7 +2223,7 @@ function SimulatorWidget(node) {
|
||||||
function checkIndirect(param, opcode, symbols) {
|
function checkIndirect(param, opcode, symbols) {
|
||||||
var value;
|
var value;
|
||||||
if (opcode === null) { return false; }
|
if (opcode === null) { return false; }
|
||||||
|
|
||||||
var match_data = param.match(/^\(([\w\$]+)\)$/i);
|
var match_data = param.match(/^\(([\w\$]+)\)$/i);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
var operand = tryParseWordOperand(match_data[1], symbols);
|
var operand = tryParseWordOperand(match_data[1], symbols);
|
||||||
|
@ -2240,7 +2240,7 @@ function SimulatorWidget(node) {
|
||||||
function checkIndirectX(param, opcode, symbols) {
|
function checkIndirectX(param, opcode, symbols) {
|
||||||
var value;
|
var value;
|
||||||
if (opcode === null) { return false; }
|
if (opcode === null) { return false; }
|
||||||
|
|
||||||
var match_data = param.match(/^\(([\w\$]+),X\)$/i);
|
var match_data = param.match(/^\(([\w\$]+),X\)$/i);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
var operand = tryParseByteOperand(match_data[1], symbols);
|
var operand = tryParseByteOperand(match_data[1], symbols);
|
||||||
|
@ -2257,7 +2257,7 @@ function SimulatorWidget(node) {
|
||||||
function checkIndirectY(param, opcode, symbols) {
|
function checkIndirectY(param, opcode, symbols) {
|
||||||
var value;
|
var value;
|
||||||
if (opcode === null) { return false; }
|
if (opcode === null) { return false; }
|
||||||
|
|
||||||
var match_data = param.match(/^\(([\w\$]+)\),Y$/i);
|
var match_data = param.match(/^\(([\w\$]+)\),Y$/i);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
var operand = tryParseByteOperand(match_data[1], symbols);
|
var operand = tryParseByteOperand(match_data[1], symbols);
|
||||||
|
@ -2274,7 +2274,7 @@ function SimulatorWidget(node) {
|
||||||
function checkSingle(param, opcode) {
|
function checkSingle(param, opcode) {
|
||||||
if (opcode === null) { return false; }
|
if (opcode === null) { return false; }
|
||||||
// Accumulator instructions are counted as single-byte opcodes
|
// Accumulator instructions are counted as single-byte opcodes
|
||||||
if (param !== "" && param !== "A") { return false; }
|
if (param !== '' && param !== 'A') { return false; }
|
||||||
pushByte(opcode);
|
pushByte(opcode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2290,7 +2290,7 @@ function SimulatorWidget(node) {
|
||||||
pushByte(operand);
|
pushByte(operand);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2298,7 +2298,7 @@ function SimulatorWidget(node) {
|
||||||
function checkAbsoluteX(param, opcode, symbols) {
|
function checkAbsoluteX(param, opcode, symbols) {
|
||||||
var number, value, addr;
|
var number, value, addr;
|
||||||
if (opcode === null) { return false; }
|
if (opcode === null) { return false; }
|
||||||
|
|
||||||
var match_data = param.match(/^([\w\$]+),X$/i);
|
var match_data = param.match(/^([\w\$]+),X$/i);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
var operand = tryParseWordOperand(match_data[1], symbols);
|
var operand = tryParseWordOperand(match_data[1], symbols);
|
||||||
|
@ -2311,7 +2311,7 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
// it could be a label too..
|
// it could be a label too..
|
||||||
if (param.match(/^\w+,X$/i)) {
|
if (param.match(/^\w+,X$/i)) {
|
||||||
param = param.replace(/,X$/i, "");
|
param = param.replace(/,X$/i, '');
|
||||||
pushByte(opcode);
|
pushByte(opcode);
|
||||||
if (labels.find(param)) {
|
if (labels.find(param)) {
|
||||||
addr = labels.getPC(param);
|
addr = labels.getPC(param);
|
||||||
|
@ -2331,7 +2331,7 @@ function SimulatorWidget(node) {
|
||||||
function checkAbsoluteY(param, opcode, symbols) {
|
function checkAbsoluteY(param, opcode, symbols) {
|
||||||
var number, value, addr;
|
var number, value, addr;
|
||||||
if (opcode === null) { return false; }
|
if (opcode === null) { return false; }
|
||||||
|
|
||||||
var match_data = param.match(/^([\w\$]+),Y$/i);
|
var match_data = param.match(/^([\w\$]+),Y$/i);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
var operand = tryParseWordOperand(match_data[1], symbols);
|
var operand = tryParseWordOperand(match_data[1], symbols);
|
||||||
|
@ -2344,7 +2344,7 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
// it could be a label too..
|
// it could be a label too..
|
||||||
if (param.match(/^\w+,Y$/i)) {
|
if (param.match(/^\w+,Y$/i)) {
|
||||||
param = param.replace(/,Y$/i, "");
|
param = param.replace(/,Y$/i, '');
|
||||||
pushByte(opcode);
|
pushByte(opcode);
|
||||||
if (labels.find(param)) {
|
if (labels.find(param)) {
|
||||||
addr = labels.getPC(param);
|
addr = labels.getPC(param);
|
||||||
|
@ -2363,7 +2363,7 @@ function SimulatorWidget(node) {
|
||||||
function checkZeroPageX(param, opcode, symbols) {
|
function checkZeroPageX(param, opcode, symbols) {
|
||||||
var number, value;
|
var number, value;
|
||||||
if (opcode === null) { return false; }
|
if (opcode === null) { return false; }
|
||||||
|
|
||||||
var match_data = param.match(/^([\w\$]+),X$/i);
|
var match_data = param.match(/^([\w\$]+),X$/i);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
var operand = tryParseByteOperand(match_data[1], symbols);
|
var operand = tryParseByteOperand(match_data[1], symbols);
|
||||||
|
@ -2373,7 +2373,7 @@ function SimulatorWidget(node) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2381,7 +2381,7 @@ function SimulatorWidget(node) {
|
||||||
function checkZeroPageY(param, opcode, symbols) {
|
function checkZeroPageY(param, opcode, symbols) {
|
||||||
var number, value;
|
var number, value;
|
||||||
if (opcode === null) { return false; }
|
if (opcode === null) { return false; }
|
||||||
|
|
||||||
var match_data = param.match(/^([\w\$]+),Y$/i);
|
var match_data = param.match(/^([\w\$]+),Y$/i);
|
||||||
if (match_data) {
|
if (match_data) {
|
||||||
var operand = tryParseByteOperand(match_data[1], symbols);
|
var operand = tryParseByteOperand(match_data[1], symbols);
|
||||||
|
@ -2391,7 +2391,7 @@ function SimulatorWidget(node) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2637,7 +2637,7 @@ function SimulatorWidget(node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function num2hex(nr) {
|
function num2hex(nr) {
|
||||||
var str = "0123456789abcdef";
|
var str = '0123456789abcdef';
|
||||||
var hi = ((nr & 0xf0) >> 4);
|
var hi = ((nr & 0xf0) >> 4);
|
||||||
var lo = (nr & 15);
|
var lo = (nr & 15);
|
||||||
return str.substring(hi, hi + 1) + str.substring(lo, lo + 1);
|
return str.substring(hi, hi + 1) + str.substring(lo, lo + 1);
|
||||||
|
@ -2645,7 +2645,7 @@ function SimulatorWidget(node) {
|
||||||
|
|
||||||
// Prints text in the message window
|
// Prints text in the message window
|
||||||
function message(text) {
|
function message(text) {
|
||||||
if (text.length>1)
|
if (text.length > 1)
|
||||||
text += '\n'; // allow putc operations from the simulator (WDM opcode)
|
text += '\n'; // allow putc operations from the simulator (WDM opcode)
|
||||||
$node.find('.messages code').append(text).scrollTop(10000);
|
$node.find('.messages code').append(text).scrollTop(10000);
|
||||||
}
|
}
|
||||||
|
|
1105
app/es5-shim.js
1105
app/es5-shim.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 77 KiB |
2
main.js
2
main.js
|
@ -19,7 +19,7 @@ function createWindow () {
|
||||||
if(process.platform === 'darwin') {
|
if(process.platform === 'darwin') {
|
||||||
Menu.setApplicationMenu(Menu.buildFromTemplate(OSXtemplate))
|
Menu.setApplicationMenu(Menu.buildFromTemplate(OSXtemplate))
|
||||||
} else if(process.platform !== 'darwin') {
|
} else if(process.platform !== 'darwin') {
|
||||||
BrowserWindow.setMenu(Menu.buildFromTemplate(PCtemplate))
|
mainWindow.setMenu(Menu.buildFromTemplate(PCtemplate))
|
||||||
}
|
}
|
||||||
|
|
||||||
mainWindow.on('closed', function () {
|
mainWindow.on('closed', function () {
|
||||||
|
|
|
@ -6,16 +6,15 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"start": "electron .",
|
"start": "electron .",
|
||||||
|
"dev": "NODE_ENV='development' electron .",
|
||||||
"pack-mac": "electron-packager . 6502Desktop --asar.unpack=protocol-link.html --overwrite --platform=darwin --arch=x64 --icon=assets/mac/app.icns --out=out --osx-sign.identity='Developer ID Application: 3DEsprit' --appBundleId='6502Desktop' appCategoryType=public.app-category.education",
|
"pack-mac": "electron-packager . 6502Desktop --asar.unpack=protocol-link.html --overwrite --platform=darwin --arch=x64 --icon=assets/mac/app.icns --out=out --osx-sign.identity='Developer ID Application: 3DEsprit' --appBundleId='6502Desktop' appCategoryType=public.app-category.education",
|
||||||
"pack-win": "electron-packager . --asar.unpack=protocol-link.html --overwrite --platform=win32 --arch=ia32 --icon=assets/win/app.ico --out=out --version-string.CompanyName='3DEsprit' --version-string.FileDescription='6502 Simulator Desktop' --version-string.ProductName='6502 Simulator Desktop'",
|
"pack-win": "electron-packager . 6502Desktop --asar.unpack=protocol-link.html --overwrite --platform=win32 --arch=x64 --icon=assets/win/app.ico --out=out",
|
||||||
"pack-linux": "electron-packager . --asar.unpack=protocol-link.html --overwrite --platform=linux --arch=x64 --out=out"
|
"pack-linux": "electron-packager . 6502Desktop --asar.unpack=protocol-link.html --overwrite --platform=linux --arch=x64 --out=out --prune=true"
|
||||||
},
|
},
|
||||||
"author": "DBrown",
|
"author": "DBrown",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"electron": "^1.6.2",
|
"electron": "^18.3.7"
|
||||||
"electron-debug": "^1.1.0",
|
|
||||||
"electron-prebuilt": "^1.4.13"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {}
|
"devDependencies": {}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue