Mirror of CollapseOS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.6KB

  1. #include <stdint.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <curses.h>
  5. #include <termios.h>
  6. #include "emul.h"
  7. #define WCOLS 80
  8. #define WLINES 24
  9. #define RAMSTART 0
  10. #define BINSTART 0x3000
  11. WINDOW *bw, *dw, *w;
  12. static FILE *blkfp = NULL;
  13. void debug_panel()
  14. {
  15. char buf[30];
  16. emul_debugstr(buf);
  17. mvwaddnstr(dw, 0, 0, buf, 30);
  18. wrefresh(dw);
  19. }
  20. static void pchookfunc(Machine *m)
  21. {
  22. byte val;
  23. switch (m->cpu.R1.br.A) {
  24. case 0x01: // @KEY
  25. debug_panel();
  26. m->cpu.R1.br.A = wgetch(w);
  27. break;
  28. case 0x02: // @DSP
  29. val = m->cpu.R1.br.C;
  30. if (val == '\r') {
  31. val = '\n';
  32. }
  33. if (val >= 0x20 || val == '\n') {
  34. wechochar(w, val);
  35. } else if (val == 0x08) {
  36. int y, x; getyx(w, y, x);
  37. wmove(w, y, x-1);
  38. }
  39. break;
  40. case 0x08: // @KBD TODO: make non-blocking
  41. debug_panel();
  42. m->cpu.R1.br.A = wgetch(w);
  43. m->cpu.R1.br.F |= F_Z;
  44. break;
  45. case 0x0f: // @VDCTL
  46. wmove(w, m->cpu.R1.br.H, m->cpu.R1.br.L);
  47. break;
  48. case 0x16: // @EXIT
  49. m->cpu.halted = true;
  50. break;
  51. case 0x28: // @DCSTAT
  52. // set Z to indicate floppy presence
  53. if (blkfp != NULL) {
  54. m->cpu.R1.br.F |= F_Z;
  55. } else {
  56. m->cpu.R1.br.F &= ~F_Z;
  57. }
  58. break;
  59. // 0x100b per sector. 10 sector per cylinder, 40 cylinders per floppy.
  60. // TODO: support swapping floppies. only 1 floppy for now.
  61. case 0x31: // @RDSEC
  62. case 0x35: // @WRSEC
  63. if (blkfp != NULL) {
  64. fseek(
  65. blkfp, /* D = cylinder, E = sector */
  66. ((m->cpu.R1.br.D * 10) + m->cpu.R1.br.E) * 0x100,
  67. SEEK_SET);
  68. if (m->cpu.R1.br.A == 0x31) { // @RDSEC
  69. fread(&m->mem[m->cpu.R1.wr.HL], 0x100, 1, blkfp);
  70. } else {
  71. fwrite(&m->mem[m->cpu.R1.wr.HL], 0x100, 1, blkfp);
  72. }
  73. m->cpu.R1.br.F |= F_Z;
  74. }
  75. break;
  76. default:
  77. fprintf(stderr, "Unhandled RST28: %x\n", m->cpu.R1.br.A);
  78. }
  79. }
  80. static void usage()
  81. {
  82. fprintf(stderr, "Usage: ./trs80 [-f floppies.img] /path/to/rom\n");
  83. }
  84. int main(int argc, char *argv[])
  85. {
  86. if (argc < 2) {
  87. usage();
  88. return 1;
  89. }
  90. int ch;
  91. while ((ch = getopt(argc, argv, "f:")) != -1) {
  92. switch (ch) {
  93. case 'f':
  94. fprintf(stderr, "Setting up floppies image with %s\n", optarg);
  95. blkfp = fopen(optarg, "r+");
  96. if (blkfp == NULL) {
  97. fprintf(stderr, "Can't open file\n");
  98. return 1;
  99. }
  100. break;
  101. }
  102. }
  103. if (optind != argc-1) {
  104. usage();
  105. return 1;
  106. }
  107. Machine *m = emul_init(argv[optind], BINSTART);
  108. if (m == NULL) return 1;
  109. m->ramstart = RAMSTART;
  110. m->pchookfunc = pchookfunc;
  111. m->pchooks_cnt = 1;
  112. m->pchooks[0] = 0x28; // RST 28
  113. // Place a RET at 0x28 so that it properly returns after pchookfunc().
  114. m->mem[0x28] = 0xc9; // RET
  115. m->cpu.PC = BINSTART;
  116. initscr(); cbreak(); noecho(); nl(); clear();
  117. // border window
  118. bw = newwin(WLINES+2, WCOLS+2, 0, 0);
  119. wborder(bw, 0, 0, 0, 0, 0, 0, 0, 0);
  120. wrefresh(bw);
  121. // debug panel
  122. dw = newwin(1, 30, LINES-1, COLS-30);
  123. w = newwin(WLINES, WCOLS, 1, 1);
  124. scrollok(w, 1);
  125. while (emul_steps(1000)) {
  126. debug_panel();
  127. }
  128. nocbreak(); echo(); delwin(w); delwin(bw); delwin(dw); endwin();
  129. printf("\nDone!\n");
  130. emul_printdebug();
  131. printf("PC: %x\n", m->cpu.PC);
  132. return 0;
  133. }