Mirror of CollapseOS
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

251 linhas
5.3KB

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