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.

169 lines
3.8KB

  1. /* RC2014 classic
  2. *
  3. * - 8K of ROM in range 0x0000-0x2000
  4. * - 32K of RAM in range 0x8000-0xffff
  5. * - ACIA in ports 0x80 (ctl) and 0x81 (data)
  6. *
  7. * ACIA is hooked to stdin/stdout. CTRL+D exits when in TTY mode.
  8. */
  9. #include <stdint.h>
  10. #include <stdio.h>
  11. #include <unistd.h>
  12. #include <termios.h>
  13. #include "../../emul.h"
  14. #include "acia.h"
  15. #include "sdc.h"
  16. #define RAMSTART 0x8000
  17. #define ACIA_CTL_PORT 0x80
  18. #define ACIA_DATA_PORT 0x81
  19. #define SDC_CTL 0x05
  20. #define SDC_SPI 0x04
  21. #define MAX_ROMSIZE 0x2000
  22. static ACIA acia;
  23. static SDC sdc;
  24. static uint8_t iord_acia_ctl()
  25. {
  26. return acia_ctl_rd(&acia);
  27. }
  28. static uint8_t iord_acia_data()
  29. {
  30. return acia_data_rd(&acia);
  31. }
  32. static void iowr_acia_ctl(uint8_t val)
  33. {
  34. acia_ctl_wr(&acia, val);
  35. }
  36. static void iowr_acia_data(uint8_t val)
  37. {
  38. acia_data_wr(&acia, val);
  39. }
  40. static uint8_t iord_sdc_spi()
  41. {
  42. return sdc_spi_rd(&sdc);
  43. }
  44. static void iowr_sdc_spi(uint8_t val)
  45. {
  46. sdc_spi_wr(&sdc, val);
  47. }
  48. // in emulation, exchanges are always instantaneous, so we
  49. // always report as ready.
  50. static uint8_t iord_sdc_ctl()
  51. {
  52. return 0;
  53. }
  54. static void iowr_sdc_ctl(uint8_t val)
  55. {
  56. sdc_ctl_wr(&sdc, val);
  57. }
  58. int main(int argc, char *argv[])
  59. {
  60. if (argc < 2) {
  61. fprintf(stderr, "Usage: ./classic /path/to/rom [sdcard.img]\n");
  62. return 1;
  63. }
  64. FILE *fp = fopen(argv[1], "r");
  65. if (fp == NULL) {
  66. fprintf(stderr, "Can't open %s\n", argv[1]);
  67. return 1;
  68. }
  69. Machine *m = emul_init();
  70. m->ramstart = RAMSTART;
  71. int i = 0;
  72. int c;
  73. while ((c = fgetc(fp)) != EOF && i < MAX_ROMSIZE) {
  74. m->mem[i++] = c & 0xff;
  75. }
  76. pclose(fp);
  77. if (i == MAX_ROMSIZE) {
  78. fprintf(stderr, "ROM image too large.\n");
  79. return 1;
  80. }
  81. bool tty = isatty(fileno(stdin));
  82. struct termios term, saved_term;
  83. if (tty) {
  84. // Turn echo off: the shell takes care of its own echoing.
  85. if (tcgetattr(0, &term) == -1) {
  86. printf("Can't setup terminal.\n");
  87. return 1;
  88. }
  89. saved_term = term;
  90. term.c_lflag &= ~ECHO;
  91. term.c_lflag &= ~ICANON;
  92. term.c_cc[VMIN] = 0;
  93. term.c_cc[VTIME] = 0;
  94. tcsetattr(0, TCSADRAIN, &term);
  95. }
  96. acia_init(&acia);
  97. sdc_init(&sdc);
  98. if (argc == 3) {
  99. fprintf(stderr, "Setting up SD card image\n");
  100. sdc.fp = fopen(argv[2], "r+");
  101. }
  102. m->iord[ACIA_CTL_PORT] = iord_acia_ctl;
  103. m->iord[ACIA_DATA_PORT] = iord_acia_data;
  104. m->iowr[ACIA_CTL_PORT] = iowr_acia_ctl;
  105. m->iowr[ACIA_DATA_PORT] = iowr_acia_data;
  106. m->iord[SDC_SPI] = iord_sdc_spi;
  107. m->iowr[SDC_SPI] = iowr_sdc_spi;
  108. m->iord[SDC_CTL] = iord_sdc_ctl;
  109. m->iowr[SDC_CTL] = iowr_sdc_ctl;
  110. char tosend = 0;
  111. while (emul_step()) {
  112. // Do we have an interrupt?
  113. if (acia_has_irq(&acia)) {
  114. Z80INT(&m->cpu, 0);
  115. }
  116. // Is the RC2014 transmitting?
  117. if (acia_hastx(&acia)) {
  118. putchar(acia_read(&acia));
  119. fflush(stdout);
  120. }
  121. // Do we have something to send?
  122. if (!tosend) {
  123. char c;
  124. if (read(fileno(stdin), &c, 1) == 1) {
  125. if (c == 5) {
  126. emul_memdump();
  127. c = 0; // don't send to RC2014
  128. }
  129. if (c == 4) { // CTRL+D
  130. // Stop here
  131. break;
  132. }
  133. tosend = c;
  134. } else if (!tty) {
  135. // This means we reached EOF
  136. break;
  137. }
  138. }
  139. if (tosend && !acia_hasrx(&acia)) {
  140. acia_write(&acia, tosend);
  141. tosend = 0;
  142. }
  143. }
  144. if (tty) {
  145. printf("Done!\n");
  146. tcsetattr(0, TCSADRAIN, &saved_term);
  147. emul_printdebug();
  148. }
  149. if (sdc.fp) {
  150. fclose(sdc.fp);
  151. }
  152. return 0;
  153. }