Skip to content

Instantly share code, notes, and snippets.

@Paguo-86PK
Last active June 28, 2021 22:06
Show Gist options
  • Save Paguo-86PK/67df94e98ab48c8f3117bb5266b3496e to your computer and use it in GitHub Desktop.
Save Paguo-86PK/67df94e98ab48c8f3117bb5266b3496e to your computer and use it in GitHub Desktop.
KISC'a Machine Emulator
<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