Last active
June 28, 2021 22:06
-
-
Save Paguo-86PK/67df94e98ab48c8f3117bb5266b3496e to your computer and use it in GitHub Desktop.
KISC'a Machine Emulator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<meta http-equiv=refresh content='600'> | |
<title>My KISC!</title> | |
<script> | |
Number.prototype.HEX = function(n) { | |
return (n < 0 ? "0x" : "") + ("0000000" + this.toString(16)).substr(-Math.abs(n)).toUpperCase(); | |
} | |
</script> | |
<script> | |
const hRefresh = setTimeout | |
(function() { | |
window.location = ""; | |
}, 3000); | |
window.addEventListener("mouseover", | |
function() { | |
clearTimeout(hRefresh); | |
} | |
); | |
</script> | |
<script> | |
setTimeout(main, 100); | |
Number.prototype.__defineGetter__('right', | |
function() { | |
return this & 15; | |
} | |
); | |
Number.prototype.__defineGetter__('left', | |
function() { | |
return (this >> 4) & 15; | |
} | |
); | |
Number.prototype.__defineGetter__('low', | |
function() { | |
return this & 255; | |
} | |
); | |
Number.prototype.__defineGetter__('high', | |
function() { | |
return (this >> 8) & 255; | |
} | |
); | |
Number.prototype.__defineGetter__('isNum', | |
function() { | |
return this <= 9; | |
} | |
); | |
Number.prototype.__defineGetter__('isReg', | |
function() { | |
return this >= 0xA && this <= 0xD; | |
} | |
); | |
var i; | |
var KOY | |
= function() { | |
this.cps = 1; // Cycles Per Second | |
this.is_peek = false; | |
this.cycles = 0; | |
this.ticks = 0; | |
this.dis_pointer = 0; | |
this.dis_address = 0x0000; | |
this.dis_lines = 16; | |
this.dis_lines_points = []; | |
this.dis_points_lines = []; | |
this.dis_lines_tables = []; | |
////////////////////////////////////////////////////////////////////// | |
this.devices | |
= { | |
i8255 :{ | |
init : | |
function() { | |
this.state = []; | |
for(var i = 0; i < 256; ++ i) | |
this.state[i] = [0x00, 0x00, 0x00, 0x00]; | |
} | |
, | |
clock : | |
function() { | |
} | |
, | |
read : | |
function(index, port) { | |
return this.state[index][port & 3]; | |
} | |
, | |
write : | |
function(index, port, data) { | |
this.state[index][port & 3] = data & 0xFF; | |
} | |
}, | |
i8279 :{ | |
init : | |
function() { | |
this.state = []; | |
this.mode = []; | |
this.freq = []; | |
for(var i = 0; i < 256; ++ i) { | |
this.state[i] = 0; | |
this.mode[i] = 0; | |
this.freq[i] = 0; | |
} | |
} | |
, | |
clock : | |
function() { | |
} | |
, | |
read : | |
function(index, port) { | |
switch(port) { | |
case 0x00: | |
var code = hUserPad.value.charCodeAt(0) & 0xFF; | |
if(!this._this.is_peek) | |
hUserPad.value = hUserPad.value.substr(1); | |
return code; | |
} | |
return 0xFF; | |
} | |
, | |
write : | |
function(index, port, data) { | |
switch(port) { | |
case 0x01: | |
if((port & 0xE0) == 0x00) | |
// 0_0_0_D_D_K_K_K | |
// 0 0 -------> 8×8 character display - left entry | |
// 0 1 -------> 16×8 character display - left entry | |
// 1 0 -------> 8×8 character display - right entry | |
// 1 1 -------> 16×8 character display - right entry | |
// 0 0 0 -> Encoded Scan Keyboard - 2-Key Lock-out | |
// 0 0 1 -> Decoded Scan Keyboard - 2-Key Lock-out | |
// 0 1 0 -> Encoded Scan Keyboard - N-Key Roll-over | |
// 0 1 1 -> Decoded Scan Keyboard - N-Key Roll-over | |
// 1 0 0 -> Encoded Scan Sensor Matrix | |
// 1 0 1 -> Decoded Scan Sensor Matrix | |
// 1 1 0 -> Strobed Input. Encoded Display Scan | |
// 1 1 1 -> Strobed Input. Decoded Display Scan | |
this.mode[index] = data & 0x1F; | |
if((port & 0xE0) == 0x20) | |
this.freq[index] = data & 0x1F; | |
break; | |
} | |
} | |
}, | |
i82C0 :{ | |
init : | |
function() { | |
} | |
, | |
clock : | |
function() { | |
} | |
, | |
read : | |
function(index, port) { | |
return this.state[index][port & 3]; | |
} | |
, | |
write : | |
function(index, port, data) { | |
if(data == 0x00) | |
hEmuLog.textContent = ""; | |
else | |
hEmuLog.textContent += String.fromCharCode(data); | |
} | |
}, | |
i82CB :{ | |
init : | |
function() { | |
this.buffer = new Uint8Array(256 * 8); | |
} | |
, | |
clock : | |
function() { | |
} | |
, | |
read : | |
function(index, port) { | |
return 0; | |
} | |
, | |
write : | |
function(index, port, data) { | |
var addr = (index & 0xFF) << 3; | |
var x = (index & 0x0F) << 3; | |
var y = (index & 0xF0) >> 1; | |
var pixels; | |
var alfa = 0; | |
this.buffer[addr + (port & 7)] = data & 0xFF; | |
} | |
}, | |
i82CD :{ | |
init : | |
function() { | |
this.buffer = new Uint8Array(256 * 8); | |
} | |
, | |
clock : | |
function() { | |
} | |
, | |
read : | |
function(index, port) { | |
return 0; | |
} | |
, | |
write : | |
function(index, port, data) { | |
var addr = (index & 0xFF) << 3; | |
var x = (index & 0x0F) << 3; | |
var y = (index & 0xF0) >> 1; | |
var pixels; | |
var alfa = 0; | |
this.buffer[addr + (port & 7)] = data & 0xFF; | |
if((this.buffer[addr] | this.buffer[addr + 1] | |
| this.buffer[addr + 2] | this.buffer[addr + 3] | |
| this.buffer[addr + 4] | this.buffer[addr + 5] | |
| this.buffer[addr + 6] | this.buffer[addr + 7]) != 0) | |
alfa = 255; | |
for(var h = 0; h < 8; ++ h) { | |
pixels = hDisplay.getImageData(x + h, y, 1, 8); | |
data = this.buffer[addr + h]; | |
for(var i = 0; i < 8; ++ i) { | |
pixels.data[i * 4 + 0] = data & 1 ? 0xFF : 0x00; | |
pixels.data[i * 4 + 1] = data & 1 ? 0xFF : 0x00; | |
pixels.data[i * 4 + 2] = data & 1 ? 0xFF : 0x00; | |
pixels.data[i * 4 + 3] = alfa; | |
data >>= 1; | |
} | |
hDisplay.putImageData(pixels, x + h, y); | |
} | |
} | |
} | |
}; | |
////////////////////////////////////////////////////////////////////// | |
this.ram = new Array(65536); | |
////////////////////////////////////////////////////////////////////// | |
this.rams | |
= new Proxy | |
(new Array(65536), | |
{ | |
get: function(target, name) { | |
if(0x00D0 <= name && name <= 0x00D9) { | |
if(name <= 0x00D7) { | |
if(("i82" + target[0x00D9].HEX(2)) in target.devices) { | |
return target.devices["i82" + target[0x00D9].HEX(2)].read(target[0x00D8], (+name & 0x7)); | |
} | |
} | |
} | |
return target[name]; | |
}, | |
set: function(target, name, data) { | |
if(0x00D0 <= name && name <= 0x00D9) { | |
if(name <= 0x00D7) { | |
target[0xD000 + +target[0x00D9] * 16 + (+name & 0x000F)] = data; | |
if(("i82" + target[0x00D9].HEX(2)) in target.devices) { | |
target.devices["i82" + target[0x00D9].HEX(2)].write(target[0x00D8], (+name & 0x7), +data); | |
} | |
} else | |
if(name == 0x00D8) | |
target[0xD000 + +target[0x00D9] * 16 + (+name & 0x000F)] = data; | |
else { | |
if(data == 0xCB) | |
hScreen.canvas.style.zoom = 1; | |
target[0x00D9] = data; | |
} | |
/* switch(target[0x00D9]) { | |
case 0xC0: | |
switch(+name) { | |
case 0x00D0: | |
if(data == 0x00) | |
hEmuLog.textContent = ""; | |
else | |
hEmuLog.textContent += String.fromCharCode(data); | |
} | |
break; | |
default: | |
}*/ | |
} | |
if(name >= 0x7000 && 0x9FFF >= name) { | |
var addr = +name - 0x7000; | |
var x = addr % 120; | |
var y = (addr - x) / 120; | |
hGraphic.data[addr * 16 + 0] = +data; | |
hGraphic.data[addr * 16 + 1] = +data; | |
hGraphic.data[addr * 16 + 2] = +data; | |
hGraphic.data[addr * 16 + 3] = 0xFF; | |
hGraphic.data[addr * 16 + 4] = +data; | |
hGraphic.data[addr * 16 + 5] = +data; | |
hGraphic.data[addr * 16 + 6] = +data; | |
hGraphic.data[addr * 16 + 7] = 0xFF; | |
hGraphic.data[addr * 16 + 8] = +data; | |
hGraphic.data[addr * 16 + 9] = +data; | |
hGraphic.data[addr * 16 + 10] = +data; | |
hGraphic.data[addr * 16 + 11] = 0xFF; | |
hGraphic.data[addr * 16 + 12] = +data; | |
hGraphic.data[addr * 16 + 13] = +data; | |
hGraphic.data[addr * 16 + 14] = +data; | |
hGraphic.data[addr * 16 + 15] = 0xFF; | |
hScreen.putImageData(hGraphic, 0, 0); | |
//hScreen.fillStyle = "#" + (+data * 0x010101).HEX(6); | |
//hScreen.fillRect(x * 2, y * 2, 2, 2); | |
} | |
return target[name] = data; | |
} | |
} | |
); | |
////////////////////////////////////////////////////////////////////// | |
this.ram.base = 0x0000; | |
this.ctx = new Array(0xFFF + 1); | |
for(i = 0; i < this.ctx.length; ++ i) | |
this.ctx[i] = 0; | |
this.ctx.devices = this.devices; | |
for(i = 0; i < 8; ++ i) { | |
Object.defineProperty(this.ctx, 0xD0 + i, | |
{ | |
set: ( | |
function(data) { | |
var id = this._this.ctx[0xD9]; | |
var name = `i82${id.HEX(2)}`; | |
if(name in this._this.devices) | |
this._this.devices[name].write(this._this.ctx[0xD8], this.index, data); | |
else | |
this._this.ctx[0xE0 + id] = data; | |
} | |
).bind( | |
{ | |
_this :this, | |
index :i | |
} | |
), | |
get: ( | |
function() { | |
var id = this._this.ctx[0xD9]; | |
var name = `i82${id.HEX(2)}`; | |
if(name in this._this.devices) | |
return this._this.devices[name].read(this._this.ctx[0xD8], this.index); | |
return this._this.ctx[0xE0 + id]; | |
} | |
).bind( | |
{ | |
_this :this, | |
index :i | |
} | |
) | |
} | |
); | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.ctx.receiver | |
= function(data) { | |
var vector = this[this[0x00AE] | 0x0F]; | |
if(isFinite(data)) | |
this[vector] = data.low; | |
else | |
if(typeof data == "string") | |
return vector.HEX(2).toLowerCase() + data; | |
return this[vector]; | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.ctx.translator | |
= function(data) { | |
var vector = this[(this[0x00AE].right << 4) | 0x000F]; | |
if(isFinite(data)) | |
this[vector] = data.low; | |
else | |
if(typeof data == "string") | |
return vector.HEX(2).toLowerCase() + data; | |
return this[vector]; | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.ctx.state | |
= function(data) { | |
if(isFinite(data)) | |
this[0x00A0] = (data & 0xFF ? 0 : 1) | (data & 0x100 ? 2 : 0) | (data & 0x80 ? 8 : 0); | |
return this[0x00A0]; | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.ctx.pointer | |
= function(index, address) { | |
if(typeof address == "string") | |
return (0x0BC0 | index).HEX(3) + address; | |
else | |
if(isFinite(address)) { | |
this[this.base | index] = address.high; | |
this[(this.base | index) + 0x10] = address.low; | |
} | |
return (this[this.base | index] << 8) | this[(this.base | index) + 0x10]; | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.ram.toDump | |
= function(address, width) { | |
var i; | |
var n = address.low; | |
var row, data; | |
var dump = []; | |
address &= 0xFF00; | |
for(i = 0; i < 256; ++ i) { | |
if(i.right == 0) | |
row = [(address + i).HEX(4) + ":"]; | |
data = this[address + i]; | |
if(isFinite(data)) | |
data = data.HEX(2); | |
else | |
data = "--"; | |
/*row += ( | |
(i == n ? "[" | |
: i % 16 && i >= n && (i <= n + width) ? "" : " ") + data + | |
(i >= n ? i < n + width - 1 ? "_" : i == n + width - 1 ? "]" : "" : i % 16 == 15 ? " " : "") | |
);*/ | |
row.push( | |
(i == n ? "<span class=ActiveByte>" + data + "</span>": | |
(i > n && i <= n + width - 1 ? "<span class=ActiveByte>" + data + "</span>" : data) | |
)); | |
if(i.right == 15) | |
dump.push(row.join(" ")); | |
} | |
return dump; | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.ram.set | |
= function(data) { | |
var address; | |
var ram = this; | |
// | |
if("string" == typeof data) { | |
data | |
.split(/\r?\n/) | |
.forEach | |
(function(row) { | |
row | |
.split(/\s+|\t+/) | |
.forEach | |
(function(chars) { | |
data = chars.match(/[0-9A-F]{2,4}/); | |
if(data) | |
switch(data[0].length) { | |
case 4: | |
address = parseInt(data[0], 16); | |
break; | |
case 2: | |
ram[address ++] = parseInt(data[0], 16); | |
break; | |
} | |
else | |
if(chars.match(/'./)) | |
ram[address ++] = chars.charCodeAt(1) & 0xFF; | |
}); | |
}); | |
} else | |
address = this.length; | |
while(address -- > 0) | |
this[address] = isFinite(data) ? data : 0; | |
return this; | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.context | |
= function() { | |
var i; | |
var text = []; | |
var flags = this.ctx[0xA0]; | |
text.push(`TICKS: ${this.ticks}`); | |
text.push(`PC:${this.ctx.pointer(0x00BE).HEX(4)}`); | |
text.push(`AF:${flags & 0x08 ? "AF(Is Among)" : "NA(No Among)"}`); | |
text.push(`BF:${flags & 0x04 ? "BF(Is ???)" : "NB(No ???)"}`); | |
text.push(`CF:${flags & 0x02 ? "CF(Is Carry)" : "NC(No Carry)"}`); | |
text.push(`DF:${flags & 0x01 ? "DF(Is Duplex)" : "ND(No Duplex)"}`); | |
this.is_peek = true; | |
for(i = 0; i <= 9; ++ i) { | |
text.push(`A${i}:${this.ctx[0xA0 + i].HEX(2)} BC${i}:${this.ctx.pointer(0xB0 | i).HEX(4)} D${i}:${this.ctx[0xD0 + i].HEX(2)}`); | |
} | |
this.is_peek = false; | |
return text.join("\r\n"); | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.prepareImage | |
= function(im) { | |
var pScr = []; | |
var hSrc = document.createElement("canvas").getContext("2d"); | |
hSrc.canvas.width = im.width; | |
hSrc.canvas.height = im.height; | |
hSrc.canvas.setAttribute("crossOrigin", ""); | |
hSrc.drawImage(im, 0, 0); | |
var imdt = hSrc.getImageData(0, 0, hSrc.canvas.width, hSrc.canvas.height); | |
var data = imdt.data; | |
var len = data.length; | |
var i, bytes, code = 0; | |
var bc, gc, rc; | |
var sprite = false; | |
var flag, index; | |
var paper, sprite, indexes, output; | |
var rrggbb; | |
// | |
for(i = 0; i < len; i += 4) { | |
paper = { | |
b: (data[i] & 0x30) << 2, | |
g: (data[i + 1] & 0x30) << 2, | |
r: (data[i + 2] & 0x30) << 2 | |
}; | |
sprite = { | |
b: (data[i] & 0xC0), | |
g: (data[i + 1] & 0xC0), | |
r: (data[i + 2] & 0xC0) | |
}; | |
indexes = { | |
b: (data[i] & 0x0C) << 4, | |
g: (data[i + 1] & 0x0C) << 4, | |
r: (data[i + 2] & 0x0C) << 4 | |
}; | |
flag = paper.r == sprite.r && paper.g == sprite.g && paper.b == sprite.b; | |
if(flag) { | |
output = { | |
r: paper.r & 0xC0, | |
g: paper.g & 0xC0, | |
b: paper.b & 0xC0 | |
}; | |
} else { | |
output = { | |
r: sprite.r & 0xC0, | |
g: sprite.g & 0xC0, | |
b: sprite.b & 0xC0 | |
}; | |
} | |
data[i] = output.b; | |
data[i + 1] = output.g; | |
data[i + 2] = output.r; | |
code = ((indexes.r & 0xC0) >> 2) | ((indexes.g & 0xC0) >> 4) | ((indexes.b & 0xC0) >> 6); | |
output_rrggbb = (output.r >> 2) | (output.g >> 4) | (output.b >> 6); | |
paper_rrggbb = (paper.r >> 2) | (paper.g >> 4) | (paper.b >> 6); | |
sprite_rrggbb = (sprite.r >> 2) | (sprite.g >> 4) | (sprite.b >> 6); | |
if(index != code) { | |
index = code; | |
pScr.push(index); | |
pScr.push(128 + paper_rrggbb); | |
} else { | |
pScr.push(128 + 64 + sprite_rrggbb); | |
pScr.push(128 + 0 + paper_rrggbb); | |
} | |
} | |
// | |
pScr.width = hSrc.canvas.width; | |
pScr.height = hSrc.canvas.height; | |
return pScr; | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.render | |
= function(hCnv, pScr) { | |
//if(!hClock) | |
// return; | |
if(hCnv.canvas.width != pScr.width || hCnv.canvas.height != pScr.height) { | |
hCnv.canvas.width = pScr.width * 2; | |
hCnv.canvas.height = pScr.height * 2; | |
} | |
var imdt = hCnv.getImageData(0, 0, hCnv.canvas.width, hCnv.canvas.height); | |
var data = imdt.data; | |
var r = 0, g = 0, b = 0; | |
var len = data.length / 3; | |
var dup = hCnv.canvas.width * 4; | |
var i = 0, bytes, index = 0, shift = 0; | |
var d, x, y; | |
var s = 0; | |
var mask = this.devices.i82CB.buffer.slice(0x0, 0x08); | |
var rn, gn, bn, noisel = 0; | |
// | |
for(y = 0; y < hCnv.canvas.height; ++ y) { | |
for(x = 0; x < hCnv.canvas.width; ++ x) { | |
if(-- noisel < 0) { | |
noisel = Math.floor(Math.random() * 64 * this.render.noise / 100) + 8; | |
rn = Math.floor(Math.random() * 256 * this.render.noise / 100); | |
gn = Math.floor(Math.random() * 256 * this.render.noise / 100); | |
bn = Math.floor(Math.random() * 256 * this.render.noise / 100); | |
} | |
d = pScr[s ++]; | |
if(d & 128) { | |
if(((d >> 6) & 1) == ((mask[index] >> shift) & 1)) { | |
b = ((d & 3) << 6) ^ bn; | |
g = ((d & 12) << 4) ^ gn; | |
r = ((d & 48) << 2) ^ rn; | |
} | |
} else { | |
index = (d >> 3) & 15; | |
shift = d & 7; | |
} | |
data[i] = b; | |
data[i + 1] = g; | |
data[i + 2] = r; | |
data[i + 3] = 255; | |
data[i + dup] = b; | |
data[i + dup + 1] = g; | |
data[i + dup + 2] = r; | |
data[i + dup + 3] = 255; | |
i += 4; | |
if(x == hCnv.canvas.width - 1) | |
i += dup; | |
} | |
} | |
hCnv.putImageData(imdt, 0, 0); | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.assembly | |
= function(text, head) { | |
var _this = this; | |
var rows = text.split(/\r?\n/); | |
var i; | |
var ri, ti; | |
var part, text; | |
var curLabel = ""; | |
var address = 0x0000; | |
var command, code; | |
var rcv = "X", trs = "X"; | |
var regs = {A:0xA0, B:0xB0, C:0xC0, D:0xD0}; | |
var alu = {ADD:10, ADC:10, SUB:11, SBB:11, AND:12, CON:12, OR:13, DIS:13, XOR:14, EOR:14, MOV:15, FOR:15}; | |
var defs = {}; | |
var labels = []; | |
var label; | |
var review = 0; | |
var usr; | |
var vector, offset; | |
do { | |
label = []; | |
for(i = 0; i < rows.length; ++ i) { | |
this.dis_lines_points[i + head] = address; | |
this.dis_points_lines[address] = i + head; | |
part = /([^:;"'`\s]*(?::| ?))?(?:\s)*([^\s;]*)(?:\s*)([^\s,;"'`]*)(?:[,\s]*)?([^\s,;"'`]*)(?:[,\s]*)?(?:(?:("(?:\\.|.)*?")|('(?:\\.|.)*?')|(`(?:\\.|.)*?`)|[^;"'`]*)*)*(\.*)/.exec(rows[i]); | |
if(part[1]) { | |
switch(part[2].toUpperCase()) { | |
case ".DEF": | |
defs[part[1].toUpperCase()] = { bytes: 0, code: parseInt(part[3])}; | |
this.dis_lines_points[i + head] = parseInt(part[3]) << 8; | |
break; | |
case ".DEFB": | |
defs[part[1].toUpperCase()] = { bytes: 1, code: parseInt(part[3])}; | |
this.dis_lines_points[i + head] = parseInt(part[3]) << 8; | |
break; | |
case ".DEFW": | |
defs[part[1].toUpperCase()] = { bytes: 2, code: parseInt(part[3])}; | |
this.dis_lines_points[i + head] = parseInt(part[3]) << 8; | |
break; | |
default: | |
part[1] = part[1].replace(/[ :]$/, ""); | |
tmp = part[1].replace(/:/g, "..").match(/(\.*)(.*)/); | |
label = label.slice(0, tmp[1].length).concat(tmp[2].split(".")); | |
part[1] = label.join("."); | |
if(labels[part[1]] != address) | |
delete labels[labels[part[1].toUpperCase()]]; | |
labels[address] = part[1]; | |
labels[part[1].toUpperCase()] = address; | |
break; | |
} | |
} | |
if(part[2].toUpperCase() == ".DEF") { | |
rcv = "X", trs = "X"; | |
regs.A = 0xFA; | |
regs.B = 0xFB; | |
regs.C = 0xFC; | |
regs.D = 0xFD; | |
if(part[3].toUpperCase() in defs) | |
address = defs[part[3].toUpperCase()].code << 8; | |
this.dis_lines_points[i + head] = address; | |
this.dis_points_lines[address] = i + head; | |
} else | |
if(part[2].charAt(0) == ".") { | |
switch(part[2].toUpperCase()) { | |
case ".ORG": | |
rcv = "X", trs = "X"; | |
regs.A = 0xFA; | |
regs.B = 0xFB; | |
regs.C = 0xFC; | |
regs.D = 0xFD; | |
if(part[3].toUpperCase() in defs) | |
address = defs[part[3].toUpperCase()].code << 8; | |
else | |
address = parseInt(part[3]); | |
this.dis_lines_points[i + head] = address; | |
this.dis_points_lines[address] = i + head; | |
break; | |
case ".EQU": | |
labels[part[1].toUpperCase()] = parseInt(part[3]); | |
this.dis_lines_points[i + head] = parseInt(part[3]); | |
break; | |
case ".DB": | |
if(part[5] && (part[5].charAt(0) == '"')) { | |
this.dis_lines_points[i + head] = address; | |
part[5].substr(1, part[5].length - 2) | |
.replace(/\\0/g, "\0") | |
.replace(/\\n/g, "\n") | |
.replace(/\\r/g, "\r") | |
.replace(/\\t/g, "\t") | |
.split("") | |
.forEach | |
(function(ascii) { | |
_this.dis_lines_tables[address] = true; | |
_this.dis_points_lines[address] = i + head; | |
_this.ram[address ++] = ascii.charCodeAt(0); | |
return 0; | |
}); | |
} else { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3]); | |
} | |
break; | |
case ".DW": | |
code = parseInt(part[3]); | |
this.dis_lines_points[i + head] = address; | |
this.dis_points_lines[address] = i + head; | |
this.dis_lines_tables[address] = true; | |
this.ram[address ++] = code.low; | |
this.dis_points_lines[address] = i + head; | |
this.dis_lines_tables[address] = true; | |
this.ram[address ++] = code.high; | |
break; | |
case ".CLR": | |
rcv = "X", trs = "X"; | |
break; | |
case ".DEF": | |
if(!part[1]) | |
this.dis_lines_points[i + head] = parseInt(part[4]) << 8, | |
defs[part[3].toUpperCase()] = { bytes: 0, code: parseInt(part[4])}; | |
break; | |
case ".DEFB": | |
if(!part[1]) | |
this.dis_lines_points[i + head] = parseInt(part[4]) << 8, | |
defs[part[3].toUpperCase()] = { bytes: 1, code: parseInt(part[4])}; | |
break; | |
case ".DEFW": | |
if(!part[1]) | |
this.dis_lines_points[i + head] = parseInt(part[4]) << 8, | |
defs[part[3].toUpperCase()] = { bytes: 2, code: parseInt(part[4])}; | |
break; | |
} | |
} | |
part[3] = part[3].replace(/(\.*)([A-Z_a-z][A-Z_a-z.0-9]*)/g, function(str, nest, tag) { | |
var tmp; | |
if(label && labels.length) { | |
tmp = labels[label.slice(0, nest.length).concat(tag.split(".")).join(".").toUpperCase()]; | |
//console.log(ip.Hex(4) + " " +str + "::" + nest + ":" + tag + "=" + tmp); | |
if(isFinite(tmp)) | |
return Number(tmp); | |
return nest + tag; | |
} | |
return str; | |
}); | |
part[4] = part[4].replace(/(\.*)([A-Z_a-z][A-Z_a-z.0-9]*)/g, function(str, nest, tag) { | |
var tmp; | |
if(label && labels.length) { | |
tmp = labels[label.slice(0, nest.length).concat(tag.split(".")).join(".").toUpperCase()]; | |
//console.log(ip.Hex(4) + " " +str + "::" + nest + ":" + tag + "=" + tmp); | |
if(isFinite(tmp)) | |
return Number(tmp); | |
return nest + tag; | |
} | |
return str; | |
}); | |
command = (part[2] + " " + part[3] + (part[4] ? "," + part[4] : "")).toUpperCase(); | |
if(part[2].toUpperCase() in defs) { | |
usr = defs[part[2].toUpperCase()]; | |
switch(usr.bytes) { | |
case 0: | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = usr.code; | |
break; | |
case 1: | |
if(part[3].match(/[ABC]\d/i)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3], 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = usr.code; | |
this.dis_lines_tables[address] = true; | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[4]); | |
} else { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = usr.code; | |
this.dis_points_lines[address] = i + head; | |
this.dis_lines_tables[address] = true; | |
this.ram[address ++] = parseInt(part[3]); | |
} | |
rcv = "X", trs = "X"; | |
regs.A = 0xFA; | |
regs.B = 0xFB; | |
regs.C = 0xFC; | |
regs.D = 0xFD; | |
break; | |
case 2: | |
if(part[3].match(/BC\d/i)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(0) + part[3].charAt(2), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].substr(1), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = usr.code; | |
this.dis_points_lines[address] = i + head; | |
this.dis_lines_tables[address] = true; | |
this.ram[address ++] = parseInt(part[4]).low; | |
this.dis_points_lines[address] = i + head; | |
this.dis_lines_tables[address] = true; | |
this.ram[address ++] = parseInt(part[4]).high; | |
} else { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = usr.code; | |
this.dis_points_lines[address] = i + head; | |
this.dis_lines_tables[address] = true; | |
this.ram[address ++] = parseInt(part[3]).low; | |
this.dis_points_lines[address] = i + head; | |
this.dis_lines_tables[address] = true; | |
this.ram[address ++] = parseInt(part[3]).high; | |
} | |
rcv = "X", trs = "X"; | |
regs.A = 0xFA; | |
regs.B = 0xFB; | |
regs.C = 0xFC; | |
regs.D = 0xFD; | |
break; | |
} | |
} | |
if(command.match(/REG BC\d/)) { | |
code = parseInt(part[3].charAt(2), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = 0xB0 + code; | |
regs.B = 0xB0 + code; | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = 0xC0 + code; | |
regs.C = 0xC0 + code; | |
} else | |
if(command.match(/REG [ABCD]\d/)) { | |
code = parseInt(part[3], 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = code; | |
regs[part[3].charAt(0).toUpperCase()] = code; | |
} | |
if(command.match(/ARG [ABCD]\d?,[ABCD]\d?/)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(0) + part[4].charAt(0), 16); | |
if(part[3].length == 2) { | |
code = parseInt(part[3], 16); | |
regs[part[3].charAt(0).toUpperCase()] = code; | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = code; | |
rcv = part[3].charAt(0).toUpperCase(); | |
} | |
if(part[4].length == 2) { | |
code = parseInt(part[4], 16); | |
regs[part[4].charAt(0).toUpperCase()] = code; | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = code; | |
trs = part[4].charAt(0).toUpperCase(); | |
} | |
} | |
if(tmp = command.match(/MOV \[BC(\d+)\+(\d+)\],([ABCD]\d)/)) { | |
vector = tmp[1].padEnd(tmp[2].length, tmp[1].charAt(0)); | |
offset = parseInt(tmp[2]); | |
while(vector != "") { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(vector.charAt(0)) * 16 + Math.floor(offset / Math.pow(10, vector.length - 1)) % 10; | |
vector = vector.substr(1); | |
} | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(tmp[3], 16); | |
} else | |
if(tmp = command.match(/LEA BC(\d),\[BC(\d+)\+(\d+)\]/)) { | |
vector = tmp[2].padEnd(tmp[3].length, tmp[2].charAt(0)); | |
offset = parseInt(tmp[3]); | |
while(vector != "") { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(vector.charAt(0)) * 16 + Math.floor(offset / Math.pow(10, vector.length - 1)) % 10; | |
vector = vector.substr(1); | |
} | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = 0xDD; | |
} else | |
if(command.match(/ADD BC\d\,BC\d/)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(2) + part[4].charAt(2), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = 0xDD; | |
} else | |
if(command.match(/SWP [ABC]\d,[ABC]\d/)) { | |
ri = parseInt(part[3].charAt(1)); | |
ti = parseInt(part[4].charAt(1)); | |
if(ri < ti) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(1) + part[4].charAt(1), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(0) + part[4].charAt(0), 16); | |
} else { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[4].charAt(1) + part[3].charAt(1), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[4].charAt(0) + part[3].charAt(0), 16); | |
} | |
} else | |
if(command.match(/DIV BC\d/)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(2), 16) * 0x11; | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = 0xAA; | |
} else | |
if(command.match(/MIL BC\d/)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(2), 16) * 0x11; | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = 0xBB; | |
} else | |
if(command.match(/MUL BC\d/)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(2), 16) * 0x11; | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = 0xCC; | |
} else | |
if(tmp = command.match(/(ADD|ADC|SUB|SBB|AND|CON|OR|DIS|XOR|EOR|MOV|FOR) ([ABCD]\d?,)?\[BC(\d+)(\+\d+)?(\+[ABCD]\d)?\]/)) { | |
var cmd = tmp[1]; | |
var dst = tmp[2]; | |
vector = tmp[3].padEnd((tmp[4] || "+").length - 1, tmp[3].charAt(0)); | |
offset = parseInt(tmp[4]) || 0; | |
var idx = parseInt(tmp[5], 16); | |
if(dst) { | |
if(rcv != dst.charAt(0) || (tmp[5] ? trs != tmp[5].charAt(1) : false)) { | |
rcv = dst.charAt(0); | |
if(idx) | |
trs = tmp[5].charAt(1); | |
if(trs == "X") | |
trs = rcv; | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(rcv + trs, 16); | |
} | |
code = parseInt(dst, 16); | |
if(code != regs[rcv] && code >= 0xA0) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = code; | |
regs[rcv] = code; | |
} | |
} | |
while(vector != "") { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(vector.charAt(0)) * 16 + Math.floor(offset / Math.pow(10, vector.length - 1)) % 10; | |
vector = vector.substr(1); | |
} | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = +(tmp[5] ? +tmp[5].charAt(2) : 0) * 16 + alu[cmd]; | |
console.log(tmp); | |
} else | |
/* if(command.match(/(ADD|ADC|SUB|SBB|AND|CON|OR|DIS|XOR|EOR|MOV|FOR) ([ABCD]\d?,)?\[BC\d\+\d\+[ABCD]\d\]/)) { | |
if(!part[4]) { | |
if(trs != part[3].charAt(5).toUpperCase()) { | |
trs = part[3].charAt(7).toUpperCase(); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(rcv + trs, 16); | |
} | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(3) + part[3].charAt(5), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = +(part[3].charAt(8)) * 16 + alu[part[2].toUpperCase()]; | |
} else { | |
if(rcv != part[3].charAt(0).toUpperCase() || trs != part[4].charAt(5).toUpperCase()) { | |
rcv = part[3].charAt(0).toUpperCase(); | |
trs = part[4].charAt(7).toUpperCase(); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(rcv + trs, 16); | |
} | |
if(parseInt(part[3], 16) != regs[part[3].charAt(0).toUpperCase()]) { | |
code = parseInt(part[3], 16); | |
if(code >= 0xA0) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = code; | |
regs[part[3].charAt(0).toUpperCase()] = parseInt(part[3], 16); | |
} | |
} | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[4].charAt(3) + part[4].charAt(5), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = +(part[4].charAt(8)) * 16 + alu[part[2].toUpperCase()]; | |
} | |
} else | |
if(command.match(/(ADD|ADC|SUB|SBB|AND|CON|OR|DIS|XOR|EOR|MOV|FOR) ([ABCD]\d?,)?\[BC\d\+\d\]/)) { | |
if(!part[4]) { | |
if(rcv != part[3].charAt(5).toUpperCase()) { | |
rcv = part[3].charAt(7).toUpperCase(); | |
if(trs == "X") | |
trs = "A"; | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(rcv + trs, 16); | |
} | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(3) + part[3].charAt(5), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = +alu[part[2].toUpperCase()]; | |
} else { | |
if(rcv != part[3].charAt(0).toUpperCase()) { | |
rcv = part[3].charAt(0).toUpperCase(); | |
if(trs == "X") | |
trs = "A"; | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(rcv + trs, 16); | |
} | |
if(part[3].length > 1 && regs[rcv] != parseInt(part[3], 16)) { | |
regs[rcv] = parseInt(part[3], 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = regs[rcv]; | |
} | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[4].charAt(3) + part[4].charAt(5), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = alu[part[2].toUpperCase()]; | |
} | |
} else | |
*/ if(command.match(/(ADD|ADC|SUB|SBB|AND|CON|OR|DIS|XOR|EOR|MOV|FOR) ([ABCD]\d?,)?[ABCD]?\d/)) { | |
//if(command == "MOV D9,A9") | |
// console.log(command); | |
if(!part[4]) { | |
if(isFinite(part[3])) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = +part[3] * 16 + alu[part[2]]; | |
} else { | |
if(trs != part[3].charAt(0).toUpperCase()) { | |
trs = part[3].charAt(0).toUpperCase(); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(rcv + trs, 16); | |
} | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = +(part[3].charAt(1)) * 16 + alu[part[2].toUpperCase()]; | |
} | |
} else { | |
if(rcv != part[3].charAt(0).toUpperCase() || trs != part[4].charAt(0).toUpperCase()) { | |
rcv = part[3].charAt(0).toUpperCase(); | |
trs = part[4].charAt(0).toUpperCase(); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(rcv + trs, 16); | |
} | |
if(parseInt(part[3], 16) != regs[part[3].charAt(0).toUpperCase()]) { | |
code = parseInt(part[3], 16); | |
if(code >= 0xA0) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = code; | |
regs[part[3].charAt(0).toUpperCase()] = parseInt(part[3], 16); | |
} | |
} | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = +(part[4].charAt(1)) * 16 + alu[part[2].toUpperCase()]; | |
} | |
} | |
if(command.match(/^(CMA|CMB|CMC|CMD|AF|BF|CF|DF)/)) { | |
if(part[2].length == 2) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[2], 16); | |
} else { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[2].charAt(2) + "F", 16); | |
} | |
} | |
if(command.match(/(JAE|JBE|JCE|JDE) BC\d\+\d/)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(2) + part[3].charAt(4), 16); | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[2].charAt(1) + "E", 16); | |
} else | |
if(command.match(/(JAF|JBF|JCF|JND|JDF) BC\d\+\d/)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[3].charAt(2) + part[3].charAt(4), 16); | |
if(part[2].charAt(1) == "N") { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[2].charAt(2) + "F", 16); | |
} else { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[2].charAt(1) + "F", 16); | |
} | |
} else | |
if(command.match(/(JAE|JBE|JCE|JDE)/)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = parseInt(part[2].charAt(1) + "E", 16); | |
} | |
if(command.match(/(INT) ([0-9A-F]{2}){1,2}/)) { | |
code = parseInt(part[3], 16); | |
if(part[3].length > 2) { | |
if(code.low) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = code.low; | |
} | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = code.high; | |
} else { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = code.low; | |
} | |
rcv = "X", trs = "X"; | |
regs.A = 0xFA; | |
regs.B = 0xFB; | |
regs.C = 0xFC; | |
regs.D = 0xFD; | |
} | |
if(command.match(/HLT|HALT/)) { | |
this.dis_points_lines[address] = i + head; | |
this.ram[address ++] = 0x00; | |
} | |
} | |
} while(review ++ < 2); | |
} | |
////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////// | |
i = (function() { | |
var arr = new Array(256, 0x00); | |
var i; | |
arr._this = this.ram; | |
/*Object.defineProperty(arr, 0xD9, | |
{ | |
set(data) { | |
; | |
} | |
} | |
);*/ | |
for(i = 0xD0; i <= 0xD8; ++ i) { | |
Object.defineProperty(arr, i, | |
{ | |
set() { | |
this._this.devices[this[0xD9]](this._this.ram[0xD900], i & 15, data); | |
} | |
} | |
); | |
} | |
return arr; | |
})(); | |
////////////////////////////////////////////////////////////////////// | |
this.disassm | |
= function(pc) { | |
var i; | |
var address, offset; | |
var ic; // Instruction Code | |
var id = 0; // Instruction Data / Prefix | |
var ip = isFinite(pc) ? pc : this.ctx.pointer(0x00BE); | |
var ctx = this.ctx;//this.ram.slice(this.base, 256); | |
var pointer; | |
var bytes; | |
var rows; | |
var text; | |
var active = 0; | |
var prefix, receiver, args; | |
var vector, source; | |
var arg = ctx[0x00AE]; | |
var reg = { | |
0x0F: "??", | |
0xAF: ctx[0x00AF] ? ctx[0x00AF].HEX(2) : "A?", | |
0xBF: ctx[0x00BF] ? ctx[0x00BF].HEX(2) : "B?", | |
0xCF: ctx[0x00CF] ? ctx[0x00CF].HEX(2) : "C?", | |
0xDF: ctx[0x00DF] ? ctx[0x00DF].HEX(2) : "D?" | |
}; | |
// | |
if(this.dis_address > ip) | |
this.dis_address = ip; | |
do { | |
pointer = this.dis_address; | |
this.dis_pointer = pointer; | |
bytes = []; | |
rows = []; | |
for(i = 0; i < 16; ++ i) { | |
text = ""; | |
vector = ""; | |
offset = 0; | |
address = [pointer.HEX(4)]; | |
while(this.dis_lines_tables[pointer]) { | |
address.push(this.ram[pointer].HEX(2)); | |
pointer ++; | |
text = "...DATA..."; | |
} | |
if(text == "") | |
do { | |
if(pointer == ip) | |
active = i; | |
ic = this.ram[pointer ++]; | |
if(!isFinite(ic)) | |
ic = 0; | |
address.push(ic.HEX(2)); | |
id = 0; | |
while(ic.left.isNum && ic.right.isNum && ic != 0x00) { | |
if(id == 0) { | |
id = ic; | |
vector = this.ctx.pointer(id.left, ""); | |
} else | |
if(id.left != ic.left) | |
vector += "" + ic.left; | |
offset = offset * 10 + ic.right; | |
ic = this.ram[pointer ++]; | |
if(!isFinite(ic)) | |
ic = 0; | |
address.push(ic.HEX(2)); | |
} | |
if(id > 0) | |
vector += "+" + offset; | |
if(ic == 0x00) { | |
if(id == 0) | |
text = "HLT"; | |
else | |
text = "RET " + vector; | |
} | |
if(ic.left.isNum && ic.right >= 0xA) { | |
if(ctx[0x00F9].left == 0xD) { | |
if(arg > 0) | |
source = ((arg.right << 4) | ic.left).HEX(2); | |
else | |
source = "?" + ic.left.HEX(1); | |
if(id > 0) | |
text = "MOV " + reg[arg | 0x0F] + ",[" + vector + "+" + source + "]"; | |
else | |
if(ic.right == 0xF) | |
text = "MOV " + reg[arg | 0x0F] + "," + source; | |
else | |
text = "??? " + reg[arg | 0x0F] + "," + source; | |
} else | |
if(ctx[0x00F9].right == 0xD && id > 0) { | |
} else { | |
text = "ADD SUB AND OR EOR MOV".split(/\s+/)[ic.right - 0xA]; | |
text += " " + reg[arg | 0x0F] + ","; | |
if(arg > 0) | |
source = ((arg.right << 4) | ic.left).HEX(2); | |
else | |
source = "?" + ic.left.HEX(1); | |
if(id > 0) { | |
if(ic.left > 0) | |
text += "[" + vector + "+" + source + "]"; | |
else | |
text += "[" + vector + "]"; | |
} else | |
text += source; | |
} | |
} | |
if(ic.left.isReg && ic.right.isNum) { | |
if(id > 0) | |
text = "MOV [" + vector + "]," + ic.HEX(2); | |
else | |
reg[ic | 0x0F] = ic.HEX(2); | |
} | |
if(ic.left.isReg && ic.right.isReg) { | |
if(id > 0) { | |
if(ic == 0xDD) { | |
text = "ADD " + this.ctx.pointer(id.left, ",") + this.ctx.pointer(id.right, ""); | |
} else { | |
if(ic.left == ic.right && id.left == id.right) { | |
switch(ic) { | |
case 0xAA: | |
text = "DIV " + this.ctx.pointer(id.left, `,A${id.right}`); | |
break; | |
case 0xBB: | |
text = "MIL " + this.ctx.pointer(id.left, `,B${id.right},C${id.right}`); | |
break; | |
case 0xCC: | |
text = "MUL " + this.ctx.pointer(id.left, `,B${id.right},C${id.right}`); | |
break; | |
} | |
} else { | |
if(id.left < id.right) | |
text = "SWP " + ((ic.left << 4) | id.left).HEX(2) +"," + ((ic.right << 4) | id.right).HEX(2); | |
else | |
text = "??? " + ((ic.left << 4) | id.left).HEX(2) +"," + ((ic.right << 4) | id.right).HEX(2); | |
} | |
} | |
} else { | |
if(ic == 0xDD) | |
text = "DBG"; | |
else | |
arg = ic; | |
} | |
} | |
if(ic.left.isReg && ic.right == 0xE) { | |
if(id > 0) { | |
text = "JCE JDE JAE JBE".split(/\s+/)[ic.left & 3] + " " + vector; | |
} else | |
text = "JCE JDE JAE JBE".split(/\s+/)[ic.left & 3]; | |
} | |
if(ic.left.isReg && ic.right == 0xF) { | |
if(id > 0) { | |
text = "JCF JDF JAF JBF".split(/\s+/)[ic.left & 3] + " " + vector; | |
} else | |
text = "CMC CMD CMA CMB".split(/\s+/)[ic.left & 3]; | |
} | |
if(ic >= 0xE0) { | |
text = "INT " + ((ic << 8) | id).HEX(-4); | |
} | |
} while(text == ""); | |
while(address.length < 5) | |
address.splice(1, 0, "--"); | |
if(address.length > 5) | |
address.splice(2, address.length - 3, "..", ".."); | |
rows.push(address.join(" ") + "|" + (text + " ").substr(0, 17)); | |
} | |
if(pointer < ip) { | |
this.dis_address = ip; | |
continue; | |
} | |
} while(false); | |
return { | |
active :active, | |
content :rows.join("\r\n").replace(/^(.+)$/gm, "<span>$1</span>") | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.init | |
= function() { | |
this.render.noise = 25; | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.reset | |
= function() { | |
this.ctx.pointer(0x00B0, 0x0000); | |
this.ctx.pointer(0x00BE, 0x0000); | |
for(var dev in this.devices) { | |
try { | |
this.devices[dev]._this = this; | |
this.devices[dev].init(); | |
} catch(e) { | |
console.log(e); | |
} | |
} | |
} | |
////////////////////////////////////////////////////////////////////// | |
this.step | |
= function() { | |
const apr = this.ram.base | 0x00F0; | |
var address, offset = 0; | |
var x, y, z; | |
var flags; | |
var ic; // Instruction Code | |
var id = 0; // Instruction Data / Prefix | |
var ip = this.ctx.pointer(0x00BE); | |
var pn = 0; // Prefixes Number | |
// | |
this.ticks ++; | |
address = this.ctx.pointer(0x00B0); | |
ic = this.ram[ip]; | |
while(ic.left.isNum && ic.right.isNum && ic != 0x00) { | |
// 01..99 | |
offset += offset << 2; | |
offset <<= 1; | |
offset += ic.right; | |
if(ic.left != id.left || pn == 0) | |
address = (pn > 0 ? address : 0) + this.ctx.pointer(0x00B0 | ic.left); | |
if(pn == 0) | |
id = ic; | |
ic = this.ram[++ ip]; | |
++ pn; | |
} | |
address += offset; | |
address &= 0xFFFF; | |
if(ic == 0x00) { | |
if(id == 0x00) { | |
// HLT | |
this.ctx.pointer(0x00B0, ip); | |
this.ctx.pointer(0x00BE, 0x0000); | |
} else { | |
// HLT vector | |
this.ctx.pointer(0x00B0, ip); | |
this.ctx.pointer(0x00BE, address); | |
} | |
return false; | |
} | |
if(ic.left.isNum && ic.right >= 0xA) { | |
// ALU Rn,Ti | |
//y = this.ram.translator(); | |
if(id > 0 && ic.left == 0) | |
y = 0; | |
else | |
y = this.ctx[(this.ctx[0xAE].right << 4) | ic.left]; | |
x = this.ctx.receiver(); | |
if(id > 0) { | |
// ALU Rn,[BCi+k+Tm] | |
y = this.ram[address + y]; | |
} | |
switch(ic.right) { | |
case 0xA: // ADD / ADC | |
x += y + ((this.ctx.state() >> 1) & 1); | |
this.ctx.state(x); | |
break; | |
case 0xB: // SUB / SBB | |
x -= y + ((this.ctx.state() >> 1) & 1); | |
this.ctx.state(x); | |
break; | |
case 0xC: // CON / AND | |
x &= y; | |
this.ctx.state(x); | |
break; | |
case 0xD: // DIS / OR | |
x |= y; | |
this.ctx.state(x); | |
break; | |
case 0xE: // EOR / XOR | |
x ^= y; | |
this.ctx.state(x); | |
break; | |
case 0xF: // FOR / MOV | |
x = y; | |
break; | |
} | |
this.ctx.receiver(x); | |
ip ++; | |
} | |
if(ic.left.isReg && ic.right.isNum) { | |
if(id > 0) { | |
// MOV [BCi+k],Rn | |
this.ram[address] = this.ctx[ic]; | |
} else { | |
// REG Rn | |
this.ctx[ic | 0x0F] = ic; | |
} | |
ip ++; | |
} | |
if(ic.left.isReg && ic.right.isReg) { | |
if(pn > 1) { | |
// Has few prefixes | |
} else | |
if(pn == 1) { | |
// Has one prefix | |
if(ic == 0xDD) { | |
// ADD BCi,BCk | |
x = this.ctx.pointer(0x00B0 | id.left); | |
y = this.ctx.pointer(0x00B0 | id.right); | |
address = x + y + ((this.ctx[0x00A0] >> 1) & 1); | |
this.ctx.pointer(0x00B0 | id.left, address); | |
this.ctx[0xA0] = (this.ctx[0xA0] & 0xFD) | ((address >> 15) & 2); | |
} else { | |
if(ic.left == ic.right && id.left == id.right) { | |
switch(ic) { | |
case 0xAA: | |
// DIV BCi,Ak | |
x = this.ctx.pointer(0x00B0 | id.left); | |
y = this.ctx[0x0A0 | id.left]; | |
if(y == 0) | |
y = 256; | |
this.ctx.pointer(0x00B0 | id.left, Math.floor(x / y)); | |
this.ctx[0x0A0 | id.left] = (x % y).low; | |
break; | |
case 0xBB: | |
x = this.ctx.pointer(0x00B0 | id.left); | |
y = x.high; | |
x = x.low; | |
y -= (y & 128) << 1; | |
x -= (x & 128) << 1; | |
x *= y; | |
this.ctx.pointer(0x00B0 | id.left, x >= 0 ? x : x + 65536); | |
break; | |
case 0xCC: | |
x = this.ctx.pointer(0x00B0 | id.left); | |
y = x.high; | |
x = x.low; | |
this.ctx.pointer(0x00B0 | id.left, x * y); | |
break; | |
} | |
} else { | |
if(id.left < id.right) { | |
// SWP Ri,Tk | |
x = this.ctx[(ic & 0xF0) | id.left]; | |
y = this.ctx[(ic.right << 4) | id.right]; | |
this.ctx[(ic & 0xF0) | id.left] = y; | |
this.ctx[(ic.right << 4) | id.right] = x; | |
} else { | |
// ??? Ri,Tk | |
} | |
} | |
} | |
ip ++; | |
} else { | |
if(ic == 0xDD) { | |
// DBG | |
this.ctx.pointer(0x00B0, ip); | |
ip = (ic << 8); | |
this.dis_address = ip; | |
} else { | |
// ARG R,T | |
this.ctx[0xAE] = ic; | |
ip ++; | |
} | |
} | |
} | |
if(ic.left.isReg && ic.right == 0xE) { | |
if(this.ctx.state() & [2, 1, 8, 4][ic.left & 3]) { | |
// AE / BE / CE / DE / JA / JB / JC / JD | |
this.ctx.pointer(0x00B0, ip); | |
ip = address; | |
this.dis_address = ip; | |
} else | |
ip ++; | |
} | |
if(ic.left.isReg && ic.right == 0xF) { | |
if(id > 0) { | |
if(!(this.ctx.state() & [2, 1, 8, 4][ic.left & 3])) { | |
// JAF / JBF / JCF / JDF / JNA / JNB / JNC / JND | |
this.ctx.pointer(0x00B0, ip); | |
ip = address; | |
this.dis_address = ip; | |
} else | |
ip ++; | |
} else { | |
// AF / BF / CF / DF | CMA / CMB / CMC / CMD | |
this.ctx[0xA0] ^= [2, 1, 8, 4][ic.left & 3]; | |
ip ++; | |
} | |
} | |
if(ic >= 0xE0) { | |
// E000..FF99 | CALL 0xE000..0xFF99 | |
this.ctx.pointer(this.process | 0x00B0, ip); | |
ip = (ic << 8) | id; | |
this.dis_address = ip; | |
} | |
this.ctx.pointer(0x00BE, ip); | |
return true; | |
} | |
} | |
var cpu = new KOY(); | |
var hDebugger; | |
var hDisplay; | |
var hScreen; | |
var hClock; | |
var hGraphic; | |
var hUserPad; | |
var hEmuDump; | |
var hEmuDis; | |
var hEmuCtx; | |
var hEmuLog; | |
var hUserLines; | |
var hUserDump; | |
var hUserAddr; | |
var hUserAssm; | |
var hFiles; | |
function showState(addr) { | |
var ip = isFinite(addr) ? addr : cpu.ctx.pointer(0x00BE); | |
var ic; | |
i = 0; | |
do { | |
ic = cpu.ram[ip + i ++]; | |
} while(ic > 0 && ic.left.isNum && ic.right.isNum); | |
hEmuDump.innerHTML = cpu.ram.toDump(ip, i).join("\r\n"); | |
tmp = cpu.disassm(ip + 1);//.join("\r\n"); | |
tmp = cpu.disassm(ip);//.join("\r\n"); | |
if(!isFinite(addr) && isFinite(cpu.dis_points_lines[cpu.dis_pointer])) { | |
hUserDump.scrollTop = cpu.dis_points_lines[cpu.dis_pointer] * (hUserDump.scrollHeight / (hUserDump.value.split(/\r?\n/).length + 1)); | |
var line = cpu.dis_points_lines[cpu.dis_pointer]; | |
var lines = hUserDump.value.split(/\r?\n/); | |
hUserDump.selectionStart = lines.slice(0, line).join().length; | |
hUserDump.selectionEnd = lines.slice(0, line + 1).join().length; | |
} | |
hEmuDis.innerHTML = tmp.content; | |
hEmuDis.className = "line" + tmp.active; | |
hEmuCtx.textContent = cpu.context(); | |
} | |
HTMLTextAreaElement.prototype.insertAtCursor | |
= function(szChar) { | |
//IE support | |
if(document.selection) { | |
this.focus(); | |
sel = document.selection.createRange(); | |
sel.text = szChar; | |
} else | |
//MOZILLA and others | |
if(this.selectionStart || this.selectionStart == '0') { | |
var startPos = this.selectionStart; | |
var endPos = this.selectionEnd; | |
this.value = this.value.substring(0, startPos) | |
+ szChar | |
+ this.value.substring(endPos, this.value.length); | |
this.selectionStart = startPos + szChar.length; | |
this.selectionEnd = this.selectionStart; | |
} else | |
this.value += szChar; | |
} | |
function onUserDump_RefreshState(e) { | |
window.localStorage.listingSelectAt = e.srcElement.selectionStart; | |
window.localStorage.listingSelectTo = e.srcElement.selectionEnd; | |
showState(cpu.dis_lines_points[e.srcElement.value.substr(0, e.srcElement.selectionStart).split(/\r?\n/).length - 1]); | |
var row = e.srcElement.value.substr(0, e.srcElement.selectionStart).split(/\r?\n/).length; | |
var col = e.srcElement.value.substr(0, e.srcElement.selectionEnd).split(/\r?\n/).pop().length + 1; | |
hEmuLog.textContent = `${row}:${col}`; | |
return true; | |
} | |
var pVideo; | |
function main() { | |
hDebugger = document.getElementById("Debugger"); | |
hUserPad = document.getElementById("UserPad"); | |
hSprites = document.getElementById("Sprites"); | |
hDisplay = document.getElementById("Display").getContext("2d"); | |
hScreen = document.getElementById("Screen").getContext("2d"); | |
hGraphic = hScreen.getImageData(0, 0, hScreen.canvas.width, hScreen.canvas.height); | |
hUserAddr = document.getElementById("UserAddr"); | |
hUserAssm = document.getElementById("UserAssm"); | |
hUserLines = document.getElementById("UserLines"); | |
hFiles = document.getElementById("Files"); | |
hEmuDump = document.getElementById("EmuDump"); | |
hEmuDis = document.getElementById("EmuDis"); | |
hEmuCtx = document.getElementById("EmuCtx"); | |
hUserDump = document.getElementById("UserDump"); | |
hEmuLog = document.getElementById("EmuLog"); | |
hCaption = document.getElementById("Caption"); | |
document.body.style.paddingTop = hCaption.offsetHeight; | |
document.body.style.visibility = "visible"; | |
// | |
/* var as = document.getElementsByTagName("caption-bar")[0]; | |
var at = as.addEventListener("minimize-bar", function() { | |
document.webkitCancelFullScreen(); | |
}); | |
var at = as.addEventListener("maximize-bar", function() { | |
document.getElementsByTagName("caption-bar")[0].webkitRequestFullScreen(); | |
hSprites.webkitRequestFullScreen(); | |
});*/ | |
// | |
hFiles.addEventListener("change", function(e) { | |
if(e.srcElement.files[0]) { | |
var reader = new FileReader(); | |
reader.onload = function() { | |
var dataUrl = reader.result; | |
var base64 = dataUrl.split(',')[1]; | |
hSprites.style.height = ""; | |
hSprites.style.width = ""; | |
hSprites.src = dataUrl; | |
}; | |
reader.readAsDataURL(e.srcElement.files[0]); | |
e.srcElement.style.display = "none"; | |
} | |
} | |
); | |
hUserPad.addEventListener("focus", function(e) { | |
if(hClock) | |
clearInterval(hClock); | |
hClock = setInterval("while(cpu.step()) {} showState();", 1000 / cpu.cps); | |
hDebugger.style.display = "none"; | |
} | |
); | |
hUserPad.addEventListener("blur", function(e) { | |
if(hClock) | |
clearInterval(hClock); | |
hClock = null; | |
hDebugger.style.display = "block"; | |
} | |
); | |
hSprites.src = hSprites.src; | |
hSprites.addEventListener("load", | |
function(e) { | |
e.srcElement.style.display = "inline"; | |
pVideo = cpu.prepareImage(e.srcElement); | |
setInterval("cpu.render(hScreen, pVideo)" , 40); | |
} | |
); | |
hUserAddr.addEventListener("input", | |
function(e) { | |
showState(parseInt(e.srcElement.value, 16)); | |
showState(parseInt(e.srcElement.value, 16)); | |
} | |
); | |
hUserDump.addEventListener("input", | |
function(e) { | |
window.localStorage.listing = e.srcElement.value; | |
clearTimeout(hRefresh); | |
} | |
); | |
hUserDump.addEventListener("scroll", | |
function(e) { | |
var el = e.srcElement; | |
//var scr = el.scrollTop + el.offsetHeight) / el.scrollHeight * 100 | |
//hUserLines.start = el.scrollTop / (el.scrollHeight / el.value.split(/\r?\n/).length) + 1; | |
hUserLines.scrollTop = el.scrollTop; | |
} | |
); | |
hUserDump.addEventListener("mousedown", onUserDump_RefreshState); | |
hUserDump.addEventListener("keyup", onUserDump_RefreshState); | |
/* function(e) { | |
window.localStorage.listingSelectAt = e.srcElement.selectionStart; | |
window.localStorage.listingSelectTo = e.srcElement.selectionEnd; | |
showState(cpu.dis_lines_points[e.srcElement.value.substr(0, e.srcElement.selectionStart).split(/\r?\n/).length - 1]); | |
hEmuLog.textContent = e.srcElement.value.substr(0, e.srcElement.selectionStart).split(/\r?\n/).length; | |
} | |
);*/ | |
hUserDump.addEventListener("keydown", | |
function(e) { | |
var keyCode = e.keyCode || e.which; | |
if(keyCode === 0x09) { | |
document.execCommand('insertText', false, '\t'.repeat(1)); | |
//e.srcElement.insertAtCursor("\t"); | |
e.preventDefault(); | |
} | |
onUserDump_RefreshState(e); | |
} | |
); | |
hUserPad.addEventListener("keydown", | |
function(e) { | |
var keyCode = e.keyCode || e.which; | |
if(keyCode === 0x09) { | |
document.execCommand('insertText', false, '\t'.repeat(1)); | |
//e.srcElement.insertAtCursor("\t"); | |
e.preventDefault(); | |
} | |
} | |
); | |
if(window.localStorage.listing) { | |
var listing = window.localStorage.listing; | |
if(listing.indexOf("20210628") > 0) { | |
hUserDump.value = listing; | |
hUserDump.selectionStart = window.localStorage.listingSelectAt; | |
hUserDump.selectionEnd = window.localStorage.listingSelectTo; | |
hUserDump.focus(); | |
hUserLines.scrollTop = hUserDump.scrollTop; | |
} | |
} | |
hUserAssm.addEventListener("input", | |
function(e) { | |
var txt = "\t.ORG\t0x" + hUserAddr.value + "\r\n\t" + e.srcElement.value; | |
cpu.assembly(txt); | |
showState(parseInt(hUserAddr.value, 16)); | |
showState(parseInt(hUserAddr.value, 16)); | |
} | |
); | |
//for(i = 1; i <= hUserDump.rows; ++ i) | |
// hUserLines.appendChild(document.createElement("li")); | |
//hUserLines.start = 1; | |
n = hUserDump.value.match(/\r?\n/g).length; | |
rows = []; | |
for(i = 1; i <= n; ++ i) | |
rows.push(i); | |
hUserLines.textContent = rows.join("\r\n"); | |
hUserLines.rows = hUserDump.rows; | |
cpu.init(); | |
cpu.ram.set(0).set(hUserDump.value.split(".assm")[0]); | |
cpu.assembly(hUserDump.value.split(".assm")[1], hUserDump.value.split(".assm")[0].split(/\r?\n/).length - 1); | |
cpu.reset(); | |
showState(); | |
if(window.location.href.match(/autorun/i)) | |
hUserPad.focus(), | |
clearTimeout(hRefresh); | |
} | |
</script> | |
<style> | |
body | |
{ | |
visibility :hidden; | |
background-color:silver; | |
padding-bottom :0px; | |
margin-bottom :0px; | |
padding-right :0px; | |
margin-right :0px; | |
padding-left :0px; | |
margin-left :0px; | |
padding-top :0px; | |
margin-top :0px; | |
} | |
hr | |
{ | |
padding-bottom :0px; | |
margin-bottom :0px; | |
padding-right :0px; | |
margin-right :0px; | |
padding-left :0px; | |
margin-left :0px; | |
padding-top :0px; | |
margin-top :0px; | |
} | |
input#UserPad | |
{ | |
width :100%; | |
} | |
textarea#UserLines { | |
border-bottom :thin ButtonFace inset; | |
border-left :thin ButtonFace inset; | |
border-top :thin ButtonFace inset; | |
border-right :thin green dashed; | |
display :inline-block; | |
font-family :Courier New; | |
font-size :12px; | |
white-space :pre; | |
font-weight :normal; | |
margin :0px 0px 0px 0px; | |
padding-top :0px; | |
padding-right :0px; | |
color :green; | |
background-color:lightgreen; | |
overflow :hidden; | |
resize :none; | |
text-align :right; | |
} | |
pre#EmuLog | |
{ | |
background-color:Menu; | |
color :MenuText; | |
border :thin ButtonFace inset; | |
display :inline-block; | |
font-family :Courier New; | |
font-size :12px; | |
margin :0px 0px 0px 0px; | |
resize :none; | |
padding :0px 0px 0px 0px; | |
display:inline-block; | |
position:fixed; | |
right:0%; | |
text-align:right; | |
} | |
textarea#UserDump | |
{ | |
background-color:lightgreen; | |
color :green; | |
border-left :none; | |
border-top :thin ButtonFace inset; | |
border-right :thin ButtonFace inset; | |
border-bottom :thin ButtonFace inset; | |
display :inline-block; | |
font-family :Courier New; | |
font-size :12px; | |
margin-left :0px; | |
resize :none; | |
padding :0px 0px 0px 0px; | |
} | |
textarea#UserDump:focus, | |
textarea#UserLines:focus | |
{ | |
outline :none; | |
} | |
pre#EmuDis, pre#EmuDump, | |
pre#EmuCtx | |
{ | |
border :thin ButtonFace inset; | |
display :block; | |
font-family :Courier New; | |
font-size :12px; | |
} | |
span.ActiveByte | |
{ | |
color :white; | |
font-weight :bolder; | |
} | |
pre#EmuDis { | |
background-color:darkgreen; | |
color :lightgreen; | |
font-family :Courier New; | |
font-size :12px; | |
} | |
pre#EmuDis.line0 > span:nth-child(1), | |
pre#EmuDis.line1 > span:nth-child(2), | |
pre#EmuDis.line2 > span:nth-child(3), | |
pre#EmuDis.line3 > span:nth-child(4), | |
pre#EmuDis.line4 > span:nth-child(5), | |
pre#EmuDis.line5 > span:nth-child(6), | |
pre#EmuDis.line6 > span:nth-child(7), | |
pre#EmuDis.line7 > span:nth-child(8), | |
pre#EmuDis.line8 > span:nth-child(9), | |
pre#EmuDis.line9 > span:nth-child(10), | |
pre#EmuDis.line10 > span:nth-child(11), | |
pre#EmuDis.line11 > span:nth-child(12), | |
pre#EmuDis.line12 > span:nth-child(13), | |
pre#EmuDis.line13 > span:nth-child(14), | |
pre#EmuDis.line14 > span:nth-child(15), | |
pre#EmuDis.line15 > span:nth-child(16) { | |
background-color:green; | |
} | |
tr | |
{ | |
border-top :none; | |
padding-top :0px; | |
margin-top :0px; | |
} | |
table#Caption | |
{ | |
border :none; | |
z-index :1000; | |
} | |
caption-bar | |
{ | |
background-color:red;/*Menu;*/ | |
color :MenuText; | |
display :block; | |
} | |
label | |
{ | |
background-color:Menu; | |
color :MenuText; | |
display :block; | |
} | |
label input#CaptionMenu | |
{ | |
display :none; | |
} | |
label input#CaptionMenu ~ menu li menu ul::before | |
{ | |
color :HighlightText; | |
left :-1em; | |
position :absolute; | |
content :'►' | |
} | |
label input#CaptionMenu ~ menu | |
{ | |
background-color:inherit; | |
color :inherit; | |
border :none; | |
padding :1px 9px 1px 9px; | |
margin :0 0 0 0; | |
display :inline-block; | |
} | |
label input#CaptionMenu ~ menu:hover | |
{ | |
border :1px outset; | |
padding :0px 8px 0px 8px; | |
} | |
label input#CaptionMenu:checked ~ menu:hover | |
{ | |
border :1px inset; | |
padding :0px 8px 0px 8px; | |
} | |
label input#CaptionMenu:checked ~ menu:active | |
{ | |
border :1px inset; | |
} | |
label input#CaptionMenu ~ menu ul | |
{ | |
background-color:inherit; | |
color :inherit; | |
position :absolute; | |
border :1px outset; | |
display :none; | |
list-style-type :none; | |
list-style-type :none; | |
list-style-position :outside; | |
} | |
label input#CaptionMenu ~ li | |
{ | |
background-color:inherit; | |
color :inherit; | |
} | |
label input#CaptionMenu:checked ~ menu:hover ul | |
{ | |
background-color:inherit; | |
color :inherit; | |
display :block; | |
padding :0px 0px 0px 0px; | |
margin :0px 0px 0px 0px; | |
} | |
label input#CaptionMenu:checked ~ menu:hover li:hover | |
{ | |
background-color:Highlight; | |
color :HighlightText; | |
width :100%; | |
} | |
label input#CaptionMenu:checked ~ menu:hover li menu | |
{ | |
padding :0px 0px 0px 0px; | |
margin :0px 0px 0px 0px; | |
width :100%; | |
} | |
label input#CaptionMenu:checked ~ menu:hover li menu ul | |
{ | |
left :100%; | |
background-color:Menu; | |
color :MenuText; | |
display :none; | |
width :100%; | |
} | |
label input#CaptionMenu:checked ~ menu:hover li:hover menu ul | |
{ | |
background-color:Menu; | |
color :MenuText; | |
display :inline-block; | |
} | |
label input#CaptionMenu:checked ~ menu:hover li:hover menu ul li:hover | |
{ | |
background-color:Highlight; | |
color :HighlightText; | |
display :inline-block; | |
} | |
table#Caption | |
{ | |
width :100%; | |
position :fixed; | |
left :0px; | |
top :0px; | |
background-color:ActiveCaption; | |
color :CaptionText; | |
} | |
table#Caption tr td:nth-child(2) | |
{ | |
font-family :Courier New; | |
font-weight :bold; | |
width :100%; | |
} | |
table#Caption tr td:nth-child(3) | |
{ | |
white-space :nowrap; | |
} | |
table#Caption tr td:nth-child(3) button | |
{ | |
font-family :Marlett; | |
} | |
input#Files | |
{ | |
display :none; | |
} | |
canvas#Display | |
{ | |
position :absolute; | |
} | |
</style> | |
</head> | |
<body> | |
<table id=Caption cellPadding=0 cellSpacing=0 border=0> | |
<tr> | |
<td><blink><b style=color:red>K</b></blink></td> | |
<td>KISC-Machine Emulator v1.01</td> | |
<td><button>0</button><button>2</button><button>r</button></td> | |
</tr> | |
<tr> | |
<td colSpan=3> | |
<label id=MenuBar> | |
<input id=CaptionMenu type=checkbox /> | |
<menu>File<ul> | |
<li onclick='hFiles.click()'>Load</li> | |
<li onclick='window.localStorage.clear(); window.location=""'>New</li> | |
</ul> | |
</menu><menu>Edit<ul> | |
<li onclick='hUserDump.focus(); document.execCommand("cut", false)'>Cut</li> | |
<li onclick='hUserDump.focus(); document.execCommand("copy", false)'>Copy</li> | |
<li onclick='hUserDump.focus(); document.execCommand("selectAll", false)'>Select all</li> | |
</ul> | |
</menu><menu>Machine<ul> | |
<li onclick='cpu.reset()'>Reset</li> | |
<li onclick='cpu.cps = 1; hUserPad.focus()'>1 Cycle Per Second</li> | |
<li onclick='cpu.cps = 10; hUserPad.focus()'>10 Cycle Per Second</li> | |
<li onclick='cpu.cps = 100; hUserPad.focus()'>100 Cycle Per Second</li> | |
</ul> | |
</menu><menu>View<ul> | |
<li><menu>Render<ul> | |
<li onclick='cpu.render.noise = 0'>Clean</li> | |
<li onclick='cpu.render.noise = 25'>Noised</li> | |
<li onclick='cpu.render.noise = 50 '>Dirty</li> | |
</ul></menu></li> | |
<li onclick='hEmuCtx.style.display = hEmuCtx.style.display != "none" ? "none" : "block"'>Context</li> | |
<li onclick='hEmuDis.style.display = hEmuDis.style.display != "none" ? "none" : "block"'>Disassembly</li> | |
<li onclick='hUserLines.style.display = hUserDump.style.display = hUserDump.style.display != "none" ? "none" : "block"'>Listing</li> | |
<li onclick='hEmuDump.style.display = hEmuDump.style.display != "none" ? "none" : "block"'>Memory</li> | |
</ul></menu><menu>Help<ul> | |
<li onclick='hRegs.innerHTML = sHint'>Info</li> | |
<li>Help</li> | |
<li onclick='return false'>About</li> | |
</ul></menu><pre id=EmuLog>Status</pre></label> | |
</td> | |
</tr> | |
</table> | |
<span id=State></span> | |
<input id=UserPad type=text placeholder='User input Terminal' value='1242124212421323132646564675767573732' /> | |
<hr /> | |
<table id=Debugger cellspacing=0 cellpadding=0> | |
<tr> | |
<td colspan=4> | |
<button onclick='while(cpu.step()) {} showState();' | |
title='Run until HALT'>RUN</button> | |
<button onclick='cpu.step(); showState();' | |
title='One instruction step'>STEP</button> | |
<input id=UserAddr type=text maxlength=4 style=width:4em value='00F0' | |
title='Address for instruction' /><input id=UserAssm type=text value='EOR A1,[BC0123+45678+C9]' | |
title='User assembly code' /><br /> | |
</td> | |
</tr> | |
<tr> | |
<td> | |
<pre id=EmuCtx> | |
</pre> | |
</td> | |
<td> | |
<pre id=EmuDis> | |
</pre> | |
</td> | |
<td><textarea id=UserLines cols=4 disabled></textarea></td> | |
<td><textarea id=UserDump rows=16 cols=56> | |
.assm ; revision 20210628 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
CALL .DEFW 0xFE ; CALL LABEL | |
RET .DEF 0xE9 ; RETURN | |
JC .DEFW 0xEC ; JUMP IF CARRY | |
JNC .DEFW 0xED ; JUMP IF NO CARRY | |
JZ .DEFW 0xEE ; JUMP IF ZERO | |
JNZ .DEFW 0xEF ; JUMP IF NO ZERO | |
SHR .DEF 0xF9 ; SHIFT RIGHT | |
LDA .DEFB 0xFA ; LOAD A | |
LDB .DEFB 0xFB ; LOAD B | |
LDC .DEFB 0xFC ; LOAD C | |
LOAD .DEFW 0xFD ; LOAD BC | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
STACK .EQU 0x00A0 ; STACK BASE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; CALL ADDRESS | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF CALL | |
OR A9,A9 ; CLC | |
ADD BC4,BC9 ; ADC SP,-1 | |
CMC ; CMC | |
ADD BC4,BC9 ; ADC SP,-1 | |
MOV C8,[BC0+1] | |
MOV B8,[BC0+2] | |
ADD BC0,BC1 | |
ADD BC0,BC1 | |
MOV [BC4+0],C0 ; MOV [SP],C0 | |
MOV [BC4+1],B0 ; MOV [SP+1],B0 | |
JCF BC8+0 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; RET | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF RET | |
MOV B0,[BC4+1] | |
MOV C0,[BC4+0] | |
OR C0,C0 | |
ADD BC4,BC1 | |
ADD BC4,BC1 | |
CMC | |
JCE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; JC ADDRESS | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF JC | |
JCF BC0+3 | |
MOV A0,[BC0+1] | |
MOV B0,[BC0+2] | |
MOV C0,A0 | |
JCE | |
CMC | |
JCE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; JNC ADDRESS | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF JNC | |
JCE BC0+3 | |
MOV A0,[BC0+1] | |
MOV B0,[BC0+2] | |
MOV C0,A0 | |
JCE | |
CMC | |
JCE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; JZ ADDRESS | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF JZ | |
JDF BC0+3 | |
MOV A0,[BC0+1] | |
MOV B0,[BC0+2] | |
MOV C0,A0 | |
JDE | |
CMD | |
JDE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; JNZ ADDRESS | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF JNZ | |
JDE BC0+3 | |
MOV A0,[BC0+1] | |
MOV B0,[BC0+2] | |
MOV C0,A0 | |
JDE | |
CMD | |
JDE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; SHR | |
; SHIFT RIGHT A9 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF SHR | |
ADD A9,A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
ADD A9 | |
JAE BC0+1 | |
JAF BC0+1 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; LOAD A,DATA | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF LDA | |
MOV A,[BC0+1] | |
JAE BC0+2 | |
JAF BC0+2 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; LOAD B,DATA | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF LDB | |
MOV B,[BC0+1] | |
JAE BC0+2 | |
JAF BC0+2 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; LOAD C,DATA | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF LDC | |
MOV C,[BC0+1] | |
JAE BC0+2 | |
JAF BC0+2 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; LOAD BC,ADDRESS | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEF LOAD | |
MOV C,[BC0+1] | |
MOV B,[BC0+2] | |
JAE BC0+3 | |
JAF BC0+3 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0x0000 | |
;;;;;;;;;;;;;;;;;;;;;;;;; | |
OR C0,B0 ; IS WARM START? | |
JNZ WARM ; GOTO WARM | |
;;;;;;;;;;;;;;;;;;;;;;;;; | |
LOAD BC1,1 | |
LOAD BC4,STACK | |
LOAD BC9,-1 | |
;;;;;;;;;;;;;;;;;;;;;;;;; TEST FOR x86-LEA | |
MOV A9,[BC4999999999] | |
;;;;;;;;;;;;;;;;; | |
LDA A9,0xCD ; Crystal Display | |
MOV D9,A9 | |
EOR A9,A9 | |
LOAD BC6,LETTERS | |
PIXELS OR A9,A9 | |
MOV D8,A9 | |
MOV D0,[BC6+0] | |
ADD BC6,BC1 | |
MOV D1,[BC6+0] | |
ADD BC6,BC1 | |
MOV D2,[BC6+0] | |
ADD BC6,BC1 | |
MOV D3,[BC6+0] | |
ADD BC6,BC1 | |
MOV D4,[BC6+0] | |
ADD BC6,BC1 | |
MOV D5,[BC6+0] | |
ADD BC6,BC1 | |
MOV D6,[BC6+0] | |
ADD BC6,BC1 | |
MOV D7,[BC6+0] | |
ADD BC6,BC1 | |
ADD A9,C1 | |
JNZ PIXELS | |
LOAD BC6,SCENE | |
;;;;;;;;;;;;;;;;; COLOURED BUFFER | |
EOR A9,A9 | |
MOV D9,A9 | |
MOV D8,A9 | |
LDA A9,0xCB ; Coloured Buffer | |
MOV D9,A9 | |
LDA A9,0xA5 | |
MOV D4,A9 | |
MOV D3,A9 | |
LDA A1,0x30 | |
HALT | |
SCENE .DW 0x5AA5 | |
.DW 0xA55A | |
.DW 0x5AA5 | |
.DW 0xA55A | |
LETTERS .DB 0x7F | |
.DB 0x08 | |
.DB 0x7F | |
.DB 0x00 | |
.DB 0x7F | |
.DB 0x49 | |
.DB 0x49 | |
.DB 0x41 | |
.DB 0x00 | |
.DB 0x7F | |
.DB 0x40 | |
.DB 0x40 | |
.DB 0x60 | |
.DB 0x00 | |
.DB 0x7F | |
.DB 0x40 | |
.DB 0x40 | |
.DB 0x60 | |
.DB 0x00 | |
.DB 0x3E | |
.DB 0x41 | |
.DB 0x41 | |
.DB 0x3E | |
.DB 0x00 | |
.DB 0x40 | |
.DB 0x00 | |
.DB 0x7E | |
.DB 0x81 | |
.DB 0x95 | |
.DB 0xA1 | |
.DB 0xA1 | |
.DB 0x95 | |
.DB 0x81 | |
.DB 0x7E | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DB 0x01 | |
.DB 0x23 | |
.DB 0x45 | |
.DB 0x67 | |
.DB 0x00 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0x0100 | |
WARM LDA A9,0x79 | |
MOV D9,A9 ; i8279 | |
MOV A8,D0 | |
ADD A8 | |
ADD A8 | |
ADD A8 | |
ADD A8 | |
ADD A8 | |
EOR A9,A9 | |
MOV D9,A9 | |
MOV D8,A9 | |
LDA A9,0xCB ; Coloured Buffer | |
MOV D9,A9 | |
MOV D0,A1 | |
MOV D1,C8 | |
MOV D2,B8 | |
MOV D3,A8 | |
MOV A9,D3 ; CARS | |
MOV B8,[BC6+6] ; B8 = BOTTOM BORDERS | |
AND A9,B8 | |
;JNZ 0xFF ; IS CRASHED? | |
MOV C8,[BC6+5]; C8 = MID BORDERS | |
EOR A9,A9 | |
EOR A7,A7 | |
EOR A7,[BC6+4] | |
MOV A8,A7 ; A8 = TOP BORDERS | |
ADD A8,A8 | |
ADD BC8,BC8 | |
ADD A9,A9 | |
ADD A7,A9 | |
SUB A7,B8 | |
ADD A7,C8 | |
OR A8,A8 | |
ADD A8,A8 | |
ADD BC8,BC8 | |
ADD A9,A9 | |
SUB A7,A9 | |
ADD A7,B8 | |
SUB A7,C8 | |
OR A8,A8 | |
ADD A8,A8 | |
ADD BC8,BC8 | |
ADD A9,A9 | |
ADD A7,A9 | |
SUB A7,B8 | |
ADD A7,C8 | |
OR A8,A8 | |
ADD A8,A8 | |
ADD BC8,BC8 ; BCA8 <<= 4 | |
ADD A9,A9 | |
MOV D6,B8 | |
MOV D5,C8 | |
LDA A6,0x0F | |
AND A7,A6 | |
MOV A6,A7 | |
ADD A6,A6 | |
ADD A6,A6 | |
ADD A6,A6 | |
ADD A6,A6 | |
OR A6,A8 | |
LDA A5,0xE0 | |
AND A6,A5 | |
SUB A6,A5 | |
JZ GO | |
OR A8,A7 | |
GO MOV D4,A8 | |
MOV [BC6+4],A8 | |
MOV [BC6+5],C8 | |
MOV [BC6+6],B8 | |
; HALT | |
LDA A9,0xCD ; LCD | |
MOV D9,A9 | |
ADD A1,C9 | |
MOV D8,A1 | |
EOR A2,A2 | |
MOV D7,A2 | |
MOV D6,A2 | |
MOV D5,A2 | |
MOV D4,A2 | |
MOV D3,A2 | |
MOV D2,A2 | |
MOV D1,A2 | |
MOV D0,A2 | |
</textarea> | |
<!-- | |
X X . | |
X . . | |
. . X | |
____ .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F | |
7000 FE FF 3F FF FF FF FF FF | |
.assm ; 20210608 | |
RET .DEF 0xE9 ; RETURN | |
JC .DEFW 0xEC ; JUMP IF CARRY | |
JNC .DEFW 0xED ; JUMP IF NO CARRY | |
JZ .DEFW 0xEE ; JUMP IF ZERO | |
JNZ .DEFW 0xEF ; JUMP IF NO ZERO | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.DEFB LDA ,0xFA ; LDA IS [FA] | |
.DEFB LDB ,0xFB ; LDB IS [FB] | |
.DEFB LDC ,0xFC ; LDC IS [FC] | |
.DEFW LOAD ,0xFD ; LOAD IS [FD,LO,HI] | |
.DEFW CALL ,0xFE ; CALL IS [FE,LO,HI] | |
;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0x0000 | |
OR C0,D0 | |
JNZ HALTED | |
;JNZ 0x0100 | |
; | |
LOAD BC1,0x0001 ; FOR INCREMENT | |
LOAD BC4,0x00A0 ; STACK POINTER | |
LOAD BC9,0xFFFF ; FOR DECREMENT | |
LDA A9,0xC0 ; PORT: Con_Out | |
MOV D9,A9 | |
LOAD BC3,HELLO ; LOAD BC3,HELLO | |
INT E0 ; PRINT TEXT[BC3] | |
LOAD BC3,0x0099 ; LOAD BC3,0x0099 | |
LDA A3,10 ; LOAD A3,10 | |
LDA A6,0x30 ; LOAD A6,'0' | |
LOAD BC5,65535 ; LOAD BC5,65535 | |
INT F9 ; CALL IntToString | |
INT E0 ; PRINT TEXT[BC3] | |
LOAD BC5,0x7000 ; LOAD BC5,0x7000 | |
LDA A6,0xA0 ; LOAD A6,0xA0 | |
;INT F1 ; FILL(0x7000..0xA000) | |
LDA A9,0xCB | |
MOV D9,A9 | |
LDA A5,10 | |
LOAD BC2,0x0010 | |
LOAD BC7,0x0700 | |
HLT | |
;;;;;;;; | |
.ORG 0x0080 | |
HELLO .DB "HELLO WORLD!\r\n\0" | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0x0100 | |
HALTED ;CALL 0x0200 | |
;LOAD BC3,0x0080 | |
;LDA A3,0xCB | |
;MOV D9,A3 ; D9 = ColorBuffer | |
;MOV D0,A3 | |
;INT E0 | |
;;;;;;;;;;;;;;;;;;;;;;;;; | |
OR A1,A1 | |
ADD A1,C1 | |
MOV D0,[BC7+0+A1] | |
EOR A9,A9 | |
EOR A9,A1 | |
SUB A9,A5 | |
JC 0x00FF | |
EOR A1,A1 | |
ADD A2,C1 | |
MOV D0,[BC7+0+A1] | |
MOV D1,[BC7+0+A2] | |
;;;;;;;;;;;;;;;;;;;;;;;;; | |
HLT | |
;;;;;;;;;;;;;;;;;;;;;;;;; | |
MOV D0,[BC5+0] | |
MOV D1,[BC5+1] | |
MOV D2,[BC5+2] | |
MOV D3,[BC5+3] | |
MOV D4,[BC5+4] | |
MOV D5,[BC5+5] | |
MOV D6,[BC5+6] | |
MOV D7,[BC5+7] | |
MOV D8,[BC5+8] | |
OR A9,A9 | |
;ADD BC5,BC2 | |
;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0x0200 | |
RET | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0x0700 | |
TABLE .DB 0x3F ; 0 | |
.DB 0x06 ; 1 | |
.DB 0x5B ; 2 | |
.DB 0x4F ; 3 | |
.DB 0x66 ; 4 | |
.DB 0x6D ; 5 | |
.DB 0x7D ; 6 | |
.DB 0x07 ; 7 | |
.DB 0x7F ; 8 | |
.DB 0x6F ; 9 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; | |
; FILL MEMORY | |
; | |
.ORG 0xF100 | |
MOV B7,B5 | |
MOV C7,C5 | |
MOV A7,B7 | |
ADD A7,C7 | |
DIV BC7 | |
ADD A7,C7 | |
ADD A7,B7 | |
; [BC5++]= | |
; BC5/(B5+C5)+ | |
; BC5%(B5+C5) | |
ADD A7,[BC5+0] | |
MOV [BC5+0],A7 | |
XOR A9,A9 | |
ADD BC5,BC1 | |
OR A9,B5 | |
SUB A9,A6 | |
JCE | |
JCF BC0+1 | |
; | |
; DECIMALS [BC3] | |
; | |
.ORG 0xF900 | |
OR A5,A5 | |
ADD BC3,BC9 | |
MOV A5,A3 | |
DIV BC5 | |
OR A5,A5 | |
ADD A5,A6 | |
MOV [BC3+0],A5 | |
MOV A5,B5 | |
OR A5,C5 | |
JDE BC0+1 | |
CMD | |
JDE | |
; | |
; TEXT [BC3] | |
; | |
.ORG 0xE000 | |
EOR A9,A9 | |
EOR A9,[BC3+0] | |
JDE BC0+1 | |
MOV D0,A9 | |
ADD BC3,BC1 | |
CMD | |
JDE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; RET | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0xE900 | |
MOV B0,[BC4+1] | |
MOV C0,[BC4+0] | |
OR C0,C0 | |
ADD BC4,BC1 | |
ADD BC4,BC1 | |
CMC | |
JCE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; JC | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0xEC00 | |
JCF BC0+3 | |
MOV A0,[BC0+1] | |
MOV B0,[BC0+2] | |
MOV C0,A0 | |
JCE | |
CMC | |
JCE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; JNC | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0xED00 | |
JCE BC0+3 | |
MOV A0,[BC0+1] | |
MOV B0,[BC0+2] | |
MOV C0,A0 | |
JCE | |
CMC | |
JCE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; JZ | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0xEE00 | |
JDF BC0+3 | |
MOV A0,[BC0+1] | |
MOV B0,[BC0+2] | |
MOV C0,A0 | |
JCE | |
CMC | |
JCE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; JNZ | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0xEF00 | |
JDE BC0+3 | |
MOV A0,[BC0+1] | |
MOV B0,[BC0+2] | |
MOV C0,A0 | |
JCE | |
CMC | |
JCE | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; LOAD A | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0xFA00 | |
MOV A,[BC0+1] | |
JAE BC0+2 | |
JAF BC0+2 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; LOAD B | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0xFB00 | |
MOV B,[BC0+1] | |
JAE BC0+2 | |
JAF BC0+2 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; LOAD C | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0xFC00 | |
MOV C,[BC0+1] | |
JAE BC0+2 | |
JAF BC0+2 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; LOAD BC | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0xFD00 | |
MOV C,[BC0+1] | |
MOV B,[BC0+2] | |
JAE BC0+3 | |
JAF BC0+3 | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; CALL ADDRESS | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.ORG 0xFE00 | |
OR A9,A9 ; CLC | |
ADD BC4,BC9 ; ADC SP,-1 | |
CMC ; CMC | |
ADD BC4,BC9 ; ADC SP,-1 | |
MOV C8,[BC0+1] | |
MOV B8,[BC0+2] | |
ADD BC0,BC1 | |
ADD BC0,BC1 | |
MOV [BC4+0],C0 ; MOV [SP],C0 | |
MOV [BC4+1],B0 ; MOV [SP+1],B0 | |
JCF BC8+0 | |
</textarea> | |
<!-- | |
____ .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F | |
0000 B4 C4 EE A0 00 B1 C1 EE 01 00 B9 C9 EE FF FF B5 | |
0010 C5 EE C0 C0 D9 DC 5F EC 'H 'E 'L 'L 'O 20 'W 'O | |
0020 'R 'L 'D 21 00 | |
EC00 BB B5 0F CC C5 0F 10 EC 51 CE CF 51 CE | |
EC10 AA A9 9E 09 DD 9E 51 DD 50 9D 02 DE D0 DA 9F DF | |
EC20 DE | |
EE00 CC 01 8F BB 02 8F 03 CE 03 CF | |
.assm | |
; Assembly Section | |
.ORG 0x0000 | |
REG B4 | |
REG C4 | |
CALL EE | |
.DW 0x00A0 | |
REG B1 | |
REG C1 | |
CALL EE | |
.DW 0x0001 | |
REG B9 | |
REG C9 | |
CALL EE | |
.DW 0xFFFF | |
REG B5 | |
REG C5 | |
CALL EE | |
.DW 0xC0C0 | |
MOV D9,C5 | |
CALL EC | |
.DB "HELLO WORLD!\0" | |
HLT | |
;;;;;;;; | |
.ORG 0xEC00 | |
MOV B5,B0 | |
MOV C5,C0 | |
CALL EC10 | |
JC BC5+1 | |
CMC | |
JC BC5+1 | |
.ORG 0xEC10 | |
EOR A9,A9 | |
ADD BC0,BC9 | |
EOR 9 | |
ADD BC5,BC1 | |
OR [BC5+0+A9] | |
JD BC0+2 | |
MOV D0,A9 | |
CMD | |
JD | |
;;;;;;;; | |
.ORG 0xEE00 | |
MOV C,[BC0+1+C8] | |
MOV B,[BC0+2+B8] | |
JC BC0+3 | |
;CMC | |
JNC BC0+3 | |
;;;;;;;; | |
.ORG 0xFF00 | |
Start MOV [BC1+2],D4 | |
ADD BC5,BC8 | |
SUB C3,B5 | |
AND [BC6+7+C8] | |
XOR D9,[BC8+7+C6] | |
INT E0--> | |
</td> | |
<td><pre id=EmuDump> | |
</pre> | |
</td> | |
</tr> | |
</table> | |
<hr /> | |
<canvas id=Display width=128 height=128 style=zoom:3></canvas> | |
<canvas id=Screen width=128 height=128></canvas> | |
<img id=Sprites style=display:none crossorigin='' src='https://i.imgur.com/OysxF9E.png' src4='https://i.imgur.com/kUeYpDl.png' src3='https://i.imgur.com/AKvx7ER.png' src2='https://i.imgur.com/xPIE14m.png' src1='https://i.imgur.com/MQ1x2Bf.png' /> | |
<input id=Files type=file accesskey=f accept='image/png' /> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment