Skip to content

Commit 402820d

Browse files
committed
Merge remote-tracking branch 'origin/main' into mg/new_via
2 parents c064a7a + 53b1313 commit 402820d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+4262
-2124
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@
88
/perf.data
99
.eslintcache
1010
**/.DS_Store
11+
12+
coverage

.husky/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
_
2+
3+
coverage

.idea/.gitignore

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

6502.js

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"use strict";
22
import * as utils from "./utils.js";
3-
import * as opcodes from "./6502.opcodes.js";
43
import * as via from "./via.js";
54
import { Acia } from "./acia.js";
65
import { Serial } from "./serial.js";
@@ -107,7 +106,7 @@ class Base6502 {
107106
this.a = this.x = this.y = this.s = 0;
108107
this.p = new Flags();
109108
this.pc = 0;
110-
this.opcodes = model.nmos ? opcodes.Cpu6502(this) : opcodes.Cpu65c12(this);
109+
this.opcodes = model.opcodesFactory(this);
111110
this.disassembler = this.opcodes.disassembler;
112111
this.forceTracing = false;
113112
this.runner = this.opcodes.runInstruction;
@@ -736,12 +735,13 @@ export class Cpu6502 extends Base6502 {
736735
}
737736

738737
handleEconetStationId() {
738+
if (!this.econet) return 0xff;
739739
this.econet.econetNMIEnabled = false;
740740
return this.econet.stationId;
741741
}
742742

743743
handleEconetNMIEnable() {
744-
if (!this.econet.econetNMIEnabled) {
744+
if (this.econet && !this.econet.econetNMIEnabled) {
745745
// was off
746746
this.econet.econetNMIEnabled = true;
747747
if (this.econet.ADLC.status1 & 128) {
@@ -1072,34 +1072,24 @@ export class Cpu6502 extends Base6502 {
10721072
if (/\.zip/i.test(name)) {
10731073
data = utils.unzipRomImage(data).data;
10741074
}
1075-
const len = data.length;
1076-
if (len !== 16384 && len !== 8192) {
1077-
throw new Error("Broken rom file");
1078-
}
1079-
for (let i = 0; i < len; ++i) {
1080-
ramRomOs[offset + i] = data[i];
1081-
}
1075+
ramRomOs.set(data, offset);
10821076
}
10831077

10841078
async loadOs(os) {
10851079
const extraRoms = Array.prototype.slice.call(arguments, 1).concat(this.config.extraRoms);
10861080
os = "roms/" + os;
1087-
console.log("Loading OS from " + os);
1081+
console.log(`Loading OS from ${os}`);
10881082
const ramRomOs = this.ramRomOs;
10891083
const data = await utils.loadData(os);
10901084
const len = data.length;
1091-
if (len < 16384 || len & 16383) throw new Error("Broken ROM file (length=" + len + ")");
1092-
for (let i = 0; i < 16384; ++i) {
1093-
ramRomOs[this.osOffset + i] = data[i];
1094-
}
1085+
if (len < 16384 || len & 16383) throw new Error(`Broken OS ROM file (length=${len})`);
1086+
ramRomOs.set(data, this.osOffset);
10951087
const numExtraBanks = (len - 16384) / 16384;
10961088
let romIndex = 16 - numExtraBanks;
10971089
for (let i_1 = 0; i_1 < numExtraBanks; ++i_1) {
10981090
const srcBase = 16384 + 16384 * i_1;
10991091
const destBase = this.romOffset + (romIndex + i_1) * 16384;
1100-
for (let j = 0; j < 16384; ++j) {
1101-
ramRomOs[destBase + j] = data[srcBase + j];
1102-
}
1092+
ramRomOs.set(data.subarray(srcBase, srcBase + 16384), destBase);
11031093
}
11041094
const awaiting = [];
11051095
for (let i_2 = 0; i_2 < extraRoms.length; ++i_2) {

6502.opcodes.js

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,8 +469,52 @@ function getOp(op, arg) {
469469
read: true,
470470
write: true,
471471
};
472+
case "RMB0":
473+
case "RMB1":
474+
case "RMB2":
475+
case "RMB3":
476+
case "RMB4":
477+
case "RMB5":
478+
case "RMB6":
479+
case "RMB7":
480+
return {
481+
op: [`REG = REG & (${~(1 << (op[3] - "0"))});`],
482+
read: true,
483+
write: true,
484+
};
485+
case "SMB0":
486+
case "SMB1":
487+
case "SMB2":
488+
case "SMB3":
489+
case "SMB4":
490+
case "SMB5":
491+
case "SMB6":
492+
case "SMB7":
493+
return {
494+
op: [`REG = REG | ${1 << (op[3] - "0")};`],
495+
read: true,
496+
write: true,
497+
};
498+
case "BBR0":
499+
case "BBR1":
500+
case "BBR2":
501+
case "BBR3":
502+
case "BBR4":
503+
case "BBR5":
504+
case "BBR6":
505+
case "BBR7":
506+
return { op: `cpu.branch(!(REG & ${1 << (op[3] - "0")}));`, read: true };
507+
case "BBS0":
508+
case "BBS1":
509+
case "BBS2":
510+
case "BBS3":
511+
case "BBS4":
512+
case "BBS5":
513+
case "BBS6":
514+
case "BBS7":
515+
return { op: `cpu.branch(REG & ${1 << (op[3] - "0")});`, read: true };
472516
}
473-
return null;
517+
throw new Error(`Unrecognised operation '${op}'`);
474518
}
475519

476520
const opcodes6502 = {
@@ -902,6 +946,42 @@ const opcodes65c12 = {
902946
0xfe: "INC abs,x",
903947
};
904948

949+
const opcodes65c02 = {
950+
...opcodes65c12,
951+
0x07: "RMB0 zp",
952+
0x17: "RMB1 zp",
953+
0x27: "RMB2 zp",
954+
0x37: "RMB3 zp",
955+
0x47: "RMB4 zp",
956+
0x57: "RMB5 zp",
957+
0x67: "RMB6 zp",
958+
0x77: "RMB7 zp",
959+
0x87: "SMB0 zp",
960+
0x97: "SMB1 zp",
961+
0xa7: "SMB2 zp",
962+
0xb7: "SMB3 zp",
963+
0xc7: "SMB4 zp",
964+
0xd7: "SMB5 zp",
965+
0xe7: "SMB6 zp",
966+
0xf7: "SMB7 zp",
967+
0x0f: "BBR0 zp,branch",
968+
0x1f: "BBR1 zp,branch",
969+
0x2f: "BBR2 zp,branch",
970+
0x3f: "BBR3 zp,branch",
971+
0x4f: "BBR4 zp,branch",
972+
0x5f: "BBR5 zp,branch",
973+
0x6f: "BBR6 zp,branch",
974+
0x7f: "BBR7 zp,branch",
975+
0x8f: "BBS0 zp,branch",
976+
0x9f: "BBS1 zp,branch",
977+
0xaf: "BBS2 zp,branch",
978+
0xbf: "BBS3 zp,branch",
979+
0xcf: "BBS4 zp,branch",
980+
0xdf: "BBS5 zp,branch",
981+
0xef: "BBS6 zp,branch",
982+
0xff: "BBS7 zp,branch",
983+
};
984+
905985
class Disassemble6502 {
906986
constructor(cpu, opcodes) {
907987
this.cpu = cpu;
@@ -986,7 +1066,7 @@ function makeCpuFunctions(cpu, opcodes, is65c12) {
9861066
switch (arg) {
9871067
case undefined:
9881068
// Many of these ops need a little special casing.
989-
if (op.read || op.write) throw "Unsupported " + opcodeString;
1069+
if (op.read || op.write) throw new Error(`Unsupported ${opcodeString}`);
9901070
ig.append(op.preop);
9911071
ig.tick(Math.max(2, 1 + (op.extra || 0)));
9921072
ig.append(op.op);
@@ -995,6 +1075,19 @@ function makeCpuFunctions(cpu, opcodes, is65c12) {
9951075
case "branch":
9961076
return [op.op]; // special cased here, would be nice to pull out of cpu
9971077

1078+
case "zp,branch":
1079+
ig.tick(2);
1080+
ig.append("const addr = cpu.getb() | 0;");
1081+
if (op.read) {
1082+
ig.zpReadOp("addr", "REG");
1083+
if (op.write) {
1084+
ig.tick(1); // Spurious write
1085+
}
1086+
}
1087+
ig.append(op.op);
1088+
if (op.write) ig.zpWriteOp("addr", "REG");
1089+
return ig.render();
1090+
9981091
case "zp":
9991092
case "zpx": // Seems to be enough to keep tests happy, but needs investigation.
10001093
case "zp,x":
@@ -1082,7 +1175,7 @@ function makeCpuFunctions(cpu, opcodes, is65c12) {
10821175

10831176
case "imm":
10841177
if (op.write) {
1085-
throw "This isn't possible";
1178+
throw new Error("This isn't possible");
10861179
}
10871180
if (op.read) {
10881181
// NOP imm
@@ -1188,7 +1281,7 @@ function makeCpuFunctions(cpu, opcodes, is65c12) {
11881281
return ig.render();
11891282

11901283
default:
1191-
throw "Unknown arg type " + arg;
1284+
throw new Error(`Unknown arg type ${arg}`);
11921285
}
11931286
}
11941287

@@ -1309,3 +1402,7 @@ export function Cpu6502(cpu) {
13091402
export function Cpu65c12(cpu) {
13101403
return makeCpuFunctions(cpu, opcodes65c12, true);
13111404
}
1405+
1406+
export function Cpu65c02(cpu) {
1407+
return makeCpuFunctions(cpu, opcodes65c02, true);
1408+
}

0 commit comments

Comments
 (0)