1 module ben_eater;
2 
3 import std.stdio;
4 
5 class BenEaterEmulator {
6 	public this(ubyte[16] program) {
7 		memory[]= program;
8 	}
9 
10 	public void run() {
11 		while (true) {
12 			ubyte instruction = memory[pc++];
13 			ubyte opcode = instruction >> 4;
14 			ubyte argument = instruction & 0x0f;
15 
16 			switch (opcode) with (Opcodes) {
17 				case LDA:
18 					regA = memory[argument];
19 					break;
20 				case ADD:
21 					ubyte temp = regA;
22 					regA += memory[argument];
23 					if (regA < temp) carryFlag = true;
24 					break;
25 				case SUB:
26 					ubyte temp = regA;
27 					regA -= memory[argument];
28 					if (regA > temp) carryFlag = true;
29 					break;
30 				case STA:
31 					memory[argument] = regA;
32 					break;
33 				case OUT:
34 					writeln(regA);
35 					break;
36 				case JMP:
37 					pc = argument;
38 					break;
39 				case LDI:
40 					regA = argument;
41 					break;
42 				case JC:
43 					if (carryFlag) pc = argument;
44 					break;
45 				case NOP:
46 					break;
47 				case HLT:
48 					writeln("Done");
49 					return;
50 				default:
51 					writefln("Invalid.\nOpcode: %08b\nArgument: %08b", opcode, argument);
52 					break;
53 			}
54 			//writefln("%08b", instruction);
55 		}
56 	}
57 
58 	private ubyte[16] memory; // Both the program and the variables it uses
59 	private ubyte pc = 0; // Program counter
60 	private ubyte regA; // Register A
61 	private ubyte regB; // Register B
62 	private bool carryFlag; // When there was an overflow or underflow in the last operation
63 
64 	enum Opcodes {
65 		LDA = 0b0001,
66 		ADD = 0b0010,
67 		SUB = 0b0011,
68 		STA = 0b0100,
69 		OUT = 0b0101,
70 		JMP = 0b0110,
71 		LDI = 0b0111,
72 		JC  = 0b1000,
73 		NOP = 0b1001,
74 		HLT = 0b1111
75 	}
76 }