summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.js23
-rw-r--r--src/red/coreclear.red9
-rw-r--r--src/red/wait.red5
-rw-r--r--src/vm/core.js15
-rw-r--r--src/vm/vm.js34
5 files changed, 75 insertions, 11 deletions
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 0000000..ec74ee7
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,23 @@
+'use strict';
+
+const process = require('node:process');
+const fs = require('node:fs');
+
+const { assemble } = require('./parser/parser.js');
+const { RedcodeVm } = require('./vm/vm.js');
+
+
+const files = process.argv.slice(2);
+if (files.length === 0) {
+ console.log("no input files provided!");
+}
+
+
+const warriors = files.map(fname => {
+ const source = fs.readFileSync(fname, 'utf8');
+ return assemble(source);
+});
+
+
+const vm = new RedcodeVm(8000, warriors);
+console.log(vm.run(100000));
diff --git a/src/red/coreclear.red b/src/red/coreclear.red
new file mode 100644
index 0000000..7b4d8bb
--- /dev/null
+++ b/src/red/coreclear.red
@@ -0,0 +1,9 @@
+; coreclear
+; like dwarf but bombs literally everything
+
+
+bomb dat #0, #2
+start add #1, bomb
+ mov bomb, @bomb
+ jmp start
+end start
diff --git a/src/red/wait.red b/src/red/wait.red
new file mode 100644
index 0000000..4c3c2c9
--- /dev/null
+++ b/src/red/wait.red
@@ -0,0 +1,5 @@
+; wait
+; does nothing
+
+wait jmp wait
+end
diff --git a/src/vm/core.js b/src/vm/core.js
index a8fbce7..6363a60 100644
--- a/src/vm/core.js
+++ b/src/vm/core.js
@@ -133,6 +133,21 @@ class Core {
const index = this.getLocation(pc, address);
return this.data[index];
}
+
+
+ pretty(ins) {
+ const prettyMode = {
+ 'immediate': '#',
+ 'direct': ' ',
+ 'indirect': '@',
+ 'predecrement': '<',
+ };
+
+ return `\
+${ins.opcode} \
+${prettyMode[ins.a.mode]}${ins.a.value}, \
+${prettyMode[ins.b.mode]}${ins.b.value}`;
+ }
}
diff --git a/src/vm/vm.js b/src/vm/vm.js
index 6add546..eea949a 100644
--- a/src/vm/vm.js
+++ b/src/vm/vm.js
@@ -23,7 +23,12 @@ class Warrior {
next() {
const pc = this.queue[0];
this.queue = this.queue.slice(1);
- return next;
+ return pc;
+ }
+
+ peek() {
+ const pc = this.queue[0];
+ return pc;
}
};
@@ -38,7 +43,8 @@ class RedcodeVm {
step() {
let running = 0;
- for (let warrior of this.warriors) {
+ for (let i=0; i<this.warriors.length; i++) {
+ const warrior = this.warriors[i];
if (warrior.isDead()) {
continue;
} else {
@@ -48,6 +54,7 @@ class RedcodeVm {
const pc = warrior.next();
const ins = this.core.data[pc];
let next;
+ console.log(i, this.core.pretty(ins));
switch(ins.opcode) {
case 'DAT':
next = DAT(this.core, pc, ins);
@@ -85,25 +92,30 @@ class RedcodeVm {
default:
throw `core corruption: bad instruction ${ins}`
}
+
+ warrior.append(next);
}
return running;
}
+ warriorsAlive() {
+ return this.warriors.reduce(
+ (count, warrior) => warrior.isDead() ? count : count+1,
+ 0
+ );
+ }
+
run(maxSteps) {
let steps = 0;
- let running = this.warriors.length;
- while(running > 0 && steps < maxSteps) {
- running = this.step();
+ while(this.warriorsAlive() > 1 && steps < maxSteps) {
+ this.step();
steps += 1;
}
- if (running !== 0) {
- console.log("draw, maximum steps exceeded");
- }
- for (let i=0; i<this.warriors.length; i++) {
- console.log(`${i} running: ${!this.warriors[i].isDead()}`);
- }
+ return this.warriors.map(
+ (w, i) => ({ warrior: i, alive: !w.isDead() })
+ );
}
};