old-computer-simulator

godot game
git clone git://git.evenfri.xyz/old-computer-simulator.git
Log | Files | Refs

main.c (2737B)


      1 #include "emu.h"
      2 
      3 struct emulator {
      4   byte memory[65536];
      5   byte a;
      6   byte b;
      7   byte c;
      8   byte d;
      9   byte e;
     10   byte h;
     11   byte l;
     12   int pc;
     13 };
     14 
     15 static void set_reg(emulator *e, byte c, byte val) {
     16   switch (c) {
     17     case reg_a: e->a = val; break;
     18     case reg_b: e->b = val; break;
     19     case reg_c: e->c = val; break;
     20     case reg_d: e->d = val; break;
     21     case reg_e: e->e = val; break;
     22     case reg_h: e->h = val; break;
     23     case reg_l: e->l = val; break;
     24     case reg_m: 
     25     { 
     26       uint16_t hl = ((uint16_t)e->h << 8) | e->l;
     27       e->memory[hl] = val;
     28       break;
     29     }
     30   }
     31 }
     32 
     33 emulator* emu_create(void) {
     34   emulator* e = malloc(sizeof(emulator));
     35   memset(e, 0, sizeof(emulator));
     36   return e;
     37 }
     38 
     39 int emu_load_program(emulator *e, const char *filename) {
     40   FILE *f = fopen(filename, "rb"); 
     41   if (!f) return 1;
     42 
     43   size_t bytes_read = fread(e->memory, 1, sizeof(e->memory), f);
     44 
     45   fclose(f);
     46   if (bytes_read == 0) {
     47     return 1;
     48   }
     49   e->pc = 0;
     50   return 0;
     51 }
     52 
     53 void emu_destroy(emulator *e) { free(e); }
     54 
     55 int emu_get_pc(emulator *e) {
     56   return e->pc;
     57 }
     58 
     59 void emu_set_pc(emulator *e, int pc) {
     60   e->pc = pc;
     61 }
     62 
     63 int emu_step(emulator *e) {
     64   byte instr = e->memory[e->pc];
     65 
     66   /* parse instr */
     67   byte part1 = (instr >> 6) & 0x03;  /* 0b[00]000000 */
     68   byte dst = (instr >> 3) & 0x07;    /* 0b00[000]000 */
     69   byte src = instr & 0x07;           /* 0b00000[000] */
     70 
     71   switch (part1) {
     72     case op_mv: 
     73       /* instr = 0b01110110 hlt */
     74       if (dst == reg_m && src == reg_m) {
     75         return 1;
     76       }
     77       set_reg(e, dst, emu_get_reg(e, src));
     78       e->pc++;
     79       break;
     80     case op_n:
     81       if (src == 0b110) {
     82         set_reg(e, dst, e->memory[e->pc+1]);
     83         e->pc += 2;
     84       } else if (src == reg_d) {
     85         uint16_t addr = (uint16_t)e->memory[e->pc + 1] |
     86           ((uint16_t)e->memory[e->pc + 2] << 8);
     87 
     88         if (dst == reg_a) {
     89           e->a = e->memory[addr];
     90         } else if (dst == reg_m) {
     91           e->memory[addr] = e->a;
     92         }
     93         e->pc += 3;
     94       } else {
     95         e->pc++;
     96       }
     97       break;
     98     case op_sum_a:
     99       e->pc++;
    100       break;
    101     case op_jmp:
    102       e->pc++;
    103       break;
    104     default:
    105       return 1;
    106   }
    107 
    108   return 0;
    109 }
    110 
    111 void emu_mem_write(emulator *e, uint16_t addr, byte val) {
    112   e->memory[addr] = val;
    113 }
    114 
    115 byte emu_mem_read(emulator *e, uint16_t addr) {
    116   return e->memory[addr];
    117 }
    118 
    119 byte emu_get_reg(emulator *e, byte c) {
    120   switch (c) {
    121     case reg_a: return e->a;
    122     case reg_b: return e->b;
    123     case reg_c: return e->c;
    124     case reg_d: return e->d;
    125     case reg_e: return e->e;
    126     case reg_h: return e->h;
    127     case reg_l: return e->l;
    128     case reg_m: 
    129     {
    130       uint16_t hl = ((uint16_t)e->h << 8) | e->l;
    131       return e->memory[hl];
    132     }
    133     default: return 0;
    134   }
    135 }