diff options
Diffstat (limited to 'src/orgaemu.c')
-rw-r--r-- | src/orgaemu.c | 98 |
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; } |