Mirror of CollapseOS
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

242 строки
5.1KB

  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. #define MAX_ROMSIZE 0x2000
  14. #include "emul.h"
  15. #include "acia.h"
  16. #include "sio.h"
  17. #include "sdc.h"
  18. #include "rc2014_spi.h"
  19. #define RAMSTART 0x8000
  20. #define ACIA_CTL_PORT 0x80
  21. #define ACIA_DATA_PORT 0x81
  22. #define SIO_ACTL_PORT 0x80
  23. #define SIO_ADATA_PORT 0x81
  24. #define SDC_CTL 0x05
  25. #define SDC_SPI 0x04
  26. bool use_sio = false;
  27. static ACIA acia;
  28. static SIO sio;
  29. static SDC sdc;
  30. static SPI spi;
  31. static uint8_t iord_acia_ctl()
  32. {
  33. return acia_ctl_rd(&acia);
  34. }
  35. static uint8_t iord_acia_data()
  36. {
  37. return acia_data_rd(&acia);
  38. }
  39. static void iowr_acia_ctl(uint8_t val)
  40. {
  41. acia_ctl_wr(&acia, val);
  42. }
  43. static void iowr_acia_data(uint8_t val)
  44. {
  45. acia_data_wr(&acia, val);
  46. }
  47. static uint8_t iord_sio_ctl()
  48. {
  49. return sio_actl_rd(&sio);
  50. }
  51. static uint8_t iord_sio_data()
  52. {
  53. return sio_adata_rd(&sio);
  54. }
  55. static void iowr_sio_ctl(uint8_t val)
  56. {
  57. sio_actl_wr(&sio, val);
  58. }
  59. static void iowr_sio_data(uint8_t val)
  60. {
  61. sio_adata_wr(&sio, val);
  62. }
  63. static uint8_t iord_spi()
  64. {
  65. return spi_rd(&spi);
  66. }
  67. static void iowr_spi(uint8_t val)
  68. {
  69. spi_wr(&spi, val);
  70. }
  71. byte spix_sdc(byte val) { return sdc_spix(&sdc, val); }
  72. // in emulation, exchanges are always instantaneous, so we
  73. // always report as ready.
  74. static uint8_t iord_spi_ctl()
  75. {
  76. return 0;
  77. }
  78. static void iowr_spi_ctl(uint8_t val)
  79. {
  80. spi_ctl_wr(&spi, val);
  81. }
  82. static bool has_irq()
  83. {
  84. return use_sio ? sio_has_irq(&sio) : acia_has_irq(&acia);
  85. }
  86. static bool hastx()
  87. {
  88. return use_sio ? sio_hastx(&sio) : acia_hastx(&acia);
  89. }
  90. static bool hasrx()
  91. {
  92. return use_sio ? sio_hasrx(&sio) : acia_hasrx(&acia);
  93. }
  94. static uint8_t _read()
  95. {
  96. return use_sio ? sio_read(&sio) : acia_read(&acia);
  97. }
  98. static void _write(uint8_t val)
  99. {
  100. if (use_sio) { sio_write(&sio, val); } else { acia_write(&acia, val); }
  101. }
  102. static void usage()
  103. {
  104. fprintf(stderr, "Usage: ./rc2014 [-s] [-c sdcard.img] /path/to/rom\n");
  105. }
  106. int main(int argc, char *argv[])
  107. {
  108. FILE *fp = NULL;
  109. int ch;
  110. if (argc < 2) {
  111. usage();
  112. return 1;
  113. }
  114. acia_init(&acia);
  115. sio_init(&sio);
  116. sdc_init(&sdc);
  117. spi_init(&spi, spix_sdc);
  118. while ((ch = getopt(argc, argv, "sc:")) != -1) {
  119. switch (ch) {
  120. case 's':
  121. use_sio = true;
  122. break;
  123. case 'c':
  124. fprintf(stderr, "Setting up SD card image with %s\n", optarg);
  125. sdc.fp = fopen(optarg, "r+");
  126. if (sdc.fp == NULL) {
  127. fprintf(stderr, "Can't open file\n");
  128. return 1;
  129. }
  130. break;
  131. }
  132. }
  133. if (optind != argc-1) {
  134. usage();
  135. return 1;
  136. }
  137. Machine *m = emul_init(argv[optind], 0);
  138. if (m == NULL) return 1;
  139. m->ramstart = RAMSTART;
  140. bool tty = isatty(fileno(stdin));
  141. struct termios term, saved_term;
  142. if (tty) {
  143. // Turn echo off: the shell takes care of its own echoing.
  144. if (tcgetattr(0, &term) == -1) {
  145. printf("Can't setup terminal.\n");
  146. return 1;
  147. }
  148. saved_term = term;
  149. term.c_lflag &= ~ECHO;
  150. term.c_lflag &= ~ICANON;
  151. term.c_cc[VMIN] = 0;
  152. term.c_cc[VTIME] = 0;
  153. tcsetattr(0, TCSADRAIN, &term);
  154. }
  155. if (use_sio) {
  156. m->iord[SIO_ACTL_PORT] = iord_sio_ctl;
  157. m->iord[SIO_ADATA_PORT] = iord_sio_data;
  158. m->iowr[SIO_ACTL_PORT] = iowr_sio_ctl;
  159. m->iowr[SIO_ADATA_PORT] = iowr_sio_data;
  160. } else {
  161. m->iord[ACIA_CTL_PORT] = iord_acia_ctl;
  162. m->iord[ACIA_DATA_PORT] = iord_acia_data;
  163. m->iowr[ACIA_CTL_PORT] = iowr_acia_ctl;
  164. m->iowr[ACIA_DATA_PORT] = iowr_acia_data;
  165. }
  166. m->iord[SDC_SPI] = iord_spi;
  167. m->iowr[SDC_SPI] = iowr_spi;
  168. m->iord[SDC_CTL] = iord_spi_ctl;
  169. m->iowr[SDC_CTL] = iowr_spi_ctl;
  170. char tosend = 0;
  171. while (emul_step()) {
  172. // Do we have an interrupt?
  173. if (has_irq()) {
  174. Z80INT(&m->cpu, 0);
  175. }
  176. // Is the RC2014 transmitting?
  177. if (hastx()) {
  178. putchar(_read());
  179. fflush(stdout);
  180. }
  181. // Do we have something to send?
  182. if (!tosend) {
  183. char c;
  184. if (read(fileno(stdin), &c, 1) == 1) {
  185. if (c == 5) {
  186. emul_memdump();
  187. c = 0; // don't send to RC2014
  188. }
  189. if (c == 4) { // CTRL+D
  190. // Stop here
  191. break;
  192. }
  193. tosend = c;
  194. } else if (!tty) {
  195. // This means we reached EOF
  196. break;
  197. }
  198. }
  199. if (tosend && !hasrx()) {
  200. _write(tosend);
  201. tosend = 0;
  202. }
  203. }
  204. if (tty) {
  205. printf("Done!\n");
  206. tcsetattr(0, TCSADRAIN, &saved_term);
  207. emul_printdebug();
  208. }
  209. if (sdc.fp) {
  210. fclose(sdc.fp);
  211. }
  212. return 0;
  213. }