#include #include #include #include #include #include "emul.h" #define WCOLS 80 #define WLINES 24 #define RAMSTART 0 #define BINSTART 0x3000 WINDOW *bw, *dw, *w; static FILE *blkfp = NULL; void debug_panel() { char buf[30]; emul_debugstr(buf); mvwaddnstr(dw, 0, 0, buf, 30); wrefresh(dw); } static void pchookfunc(Machine *m) { byte val; switch (m->cpu.R1.br.A) { case 0x01: // @KEY debug_panel(); m->cpu.R1.br.A = wgetch(w); break; case 0x02: // @DSP val = m->cpu.R1.br.C; if (val == '\r') { val = '\n'; } if (val >= 0x20 || val == '\n') { wechochar(w, val); } else if (val == 0x08) { int y, x; getyx(w, y, x); wmove(w, y, x-1); } break; case 0x08: // @KBD TODO: make non-blocking debug_panel(); m->cpu.R1.br.A = wgetch(w); m->cpu.R1.br.F |= F_Z; break; case 0x0f: // @VDCTL wmove(w, m->cpu.R1.br.H, m->cpu.R1.br.L); break; case 0x16: // @EXIT m->cpu.halted = true; break; case 0x28: // @DCSTAT // set Z to indicate floppy presence if (blkfp != NULL) { m->cpu.R1.br.F |= F_Z; } else { m->cpu.R1.br.F &= ~F_Z; } break; // 0x100b per sector. 10 sector per cylinder, 40 cylinders per floppy. // TODO: support swapping floppies. only 1 floppy for now. case 0x31: // @RDSEC case 0x35: // @WRSEC if (blkfp != NULL) { fseek( blkfp, /* D = cylinder, E = sector */ ((m->cpu.R1.br.D * 10) + m->cpu.R1.br.E) * 0x100, SEEK_SET); if (m->cpu.R1.br.A == 0x31) { // @RDSEC fread(&m->mem[m->cpu.R1.wr.HL], 0x100, 1, blkfp); } else { fwrite(&m->mem[m->cpu.R1.wr.HL], 0x100, 1, blkfp); } m->cpu.R1.br.F |= F_Z; } break; default: fprintf(stderr, "Unhandled RST28: %x\n", m->cpu.R1.br.A); } } static void usage() { fprintf(stderr, "Usage: ./trs80 [-f floppies.img] /path/to/rom\n"); } int main(int argc, char *argv[]) { if (argc < 2) { usage(); return 1; } int ch; while ((ch = getopt(argc, argv, "f:")) != -1) { switch (ch) { case 'f': fprintf(stderr, "Setting up floppies image with %s\n", optarg); blkfp = fopen(optarg, "r+"); if (blkfp == NULL) { fprintf(stderr, "Can't open file\n"); return 1; } break; } } if (optind != argc-1) { usage(); return 1; } Machine *m = emul_init(argv[optind], BINSTART); if (m == NULL) return 1; m->ramstart = RAMSTART; m->pchookfunc = pchookfunc; m->pchooks_cnt = 1; m->pchooks[0] = 0x28; // RST 28 // Place a RET at 0x28 so that it properly returns after pchookfunc(). m->mem[0x28] = 0xc9; // RET m->cpu.PC = BINSTART; initscr(); cbreak(); noecho(); nl(); clear(); // border window bw = newwin(WLINES+2, WCOLS+2, 0, 0); wborder(bw, 0, 0, 0, 0, 0, 0, 0, 0); wrefresh(bw); // debug panel dw = newwin(1, 30, LINES-1, COLS-30); w = newwin(WLINES, WCOLS, 1, 1); scrollok(w, 1); while (emul_steps(1000)) { debug_panel(); } nocbreak(); echo(); delwin(w); delwin(bw); delwin(dw); endwin(); printf("\nDone!\n"); emul_printdebug(); printf("PC: %x\n", m->cpu.PC); return 0; }