aboutsummaryrefslogtreecommitdiff
path: root/src/orgaemu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/orgaemu.c')
-rw-r--r--src/orgaemu.c98
1 files changed, 97 insertions, 1 deletions
diff --git a/src/orgaemu.c b/src/orgaemu.c
index 00c30cf..be53a22 100644
--- a/src/orgaemu.c
+++ b/src/orgaemu.c
@@ -1,8 +1,104 @@
+#include "drain.h"
+#include "ops.h"
#include <stdio.h>
+#include <stdint.h>
+
+#define MEM_SIZE 0xffff
+
+static uint16_t *stack = NULL;
+static size_t stack_ptr = 0;
+
+static uint16_t
+get_short(const unsigned char *s)
+{
+ return s[0] | (s[1] * 0x0100);
+}
+
+static void
+push(uint16_t v)
+{
+ stack[stack_ptr] = v;
+ stack_ptr += 1;
+ if (stack_ptr >= MEM_SIZE) {
+ fprintf(stderr, "stack overflow\n");
+ return;
+ }
+}
+
+static uint16_t
+pop(void)
+{
+ if (stack_ptr == 0) {
+ fprintf(stderr, "stack underflow\n");
+ return 0;
+ }
+ stack_ptr -= 1;
+ return stack[stack_ptr];
+}
+
+static void
+exec_data(uint16_t *mem)
+{
+ for (long pc = 0; pc < MEM_SIZE; pc++) {
+ switch (mem[pc]) {
+ case OP_NOP:
+ break;
+ case OP_LIT:
+ push(mem[pc + 1]);
+ pc += 1;
+ break;
+ case OP_WRT:
+ putchar(pop());
+ break;
+ case OP_RET:
+ return;
+ default:
+ fprintf(stderr, "unhandled opcode %04x\n", mem[pc]);
+ return;
+ }
+ }
+}
int
main(int argc, char **argv)
{
- (void)argc, (void)argv;
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <rom>\n", argv[0]);
+ return 1;
+ }
+
+ FILE *file = fopen(argv[1], "rb");
+ if (file == NULL) {
+ perror(argv[1]);
+ return 1;
+ }
+
+ long size;
+ unsigned char *const data = (unsigned char*)drain(file, &size);
+ fclose(file);
+ if (data == NULL)
+ return 1;
+
+ uint16_t *mem = calloc(MEM_SIZE, sizeof(uint16_t));
+ if (mem == NULL) {
+ perror("main:calloc");
+ free(data);
+ return 1;
+ }
+
+ for (long i = 0; i < size; i += 2)
+ mem[i / 2] = get_short(data + i);
+ free(data);
+
+ stack = calloc(MEM_SIZE, sizeof(uint16_t));
+ if (stack == NULL) {
+ perror("main:calloc");
+ free(mem);
+ return 1;
+ }
+
+ exec_data(mem);
+ free(mem);
+ free(stack);
return 0;
}