Mirror of CollapseOS
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

125 líneas
2.5KB

  1. /* Common code between shell, zasm and runbin.
  2. They all run on the same kind of virtual machine: A z80 CPU, 64K of RAM/ROM.
  3. */
  4. #include <string.h>
  5. #include "emul.h"
  6. static Machine m;
  7. static ushort traceval = 0;
  8. static uint8_t io_read(int unused, uint16_t addr)
  9. {
  10. addr &= 0xff;
  11. IORD fn = m.iord[addr];
  12. if (fn != NULL) {
  13. return fn();
  14. } else {
  15. fprintf(stderr, "Out of bounds I/O read: %d\n", addr);
  16. return 0;
  17. }
  18. }
  19. static void io_write(int unused, uint16_t addr, uint8_t val)
  20. {
  21. addr &= 0xff;
  22. IOWR fn = m.iowr[addr];
  23. if (fn != NULL) {
  24. fn(val);
  25. } else {
  26. fprintf(stderr, "Out of bounds I/O write: %d / %d (0x%x)\n", addr, val, val);
  27. }
  28. }
  29. static uint8_t mem_read(int unused, uint16_t addr)
  30. {
  31. return m.mem[addr];
  32. }
  33. static void mem_write(int unused, uint16_t addr, uint8_t val)
  34. {
  35. if (addr < m.ramstart) {
  36. fprintf(stderr, "Writing to ROM (%d)!\n", addr);
  37. emul_memdump();
  38. fprintf(stderr, "Press any key to continue...\n");
  39. while (getchar() > 0x100);
  40. }
  41. m.mem[addr] = val;
  42. }
  43. Machine* emul_init()
  44. {
  45. memset(m.mem, 0, 0x10000);
  46. m.ramstart = 0;
  47. m.minsp = 0xffff;
  48. m.maxix = 0;
  49. for (int i=0; i<0x100; i++) {
  50. m.iord[i] = NULL;
  51. m.iowr[i] = NULL;
  52. }
  53. Z80RESET(&m.cpu);
  54. m.cpu.memRead = mem_read;
  55. m.cpu.memWrite = mem_write;
  56. m.cpu.ioRead = io_read;
  57. m.cpu.ioWrite = io_write;
  58. return &m;
  59. }
  60. bool emul_step()
  61. {
  62. if (!m.cpu.halted) {
  63. Z80Execute(&m.cpu);
  64. ushort newsp = m.cpu.R1.wr.SP;
  65. if (newsp != 0 && newsp < m.minsp) {
  66. m.minsp = newsp;
  67. }
  68. if (m.cpu.R1.wr.IX > m.maxix) {
  69. m.maxix = m.cpu.R1.wr.IX;
  70. }
  71. return true;
  72. } else {
  73. return false;
  74. }
  75. }
  76. bool emul_steps(unsigned int steps)
  77. {
  78. while (steps) {
  79. if (!emul_step()) {
  80. return false;
  81. }
  82. steps--;
  83. }
  84. return true;
  85. }
  86. void emul_loop()
  87. {
  88. while (emul_step());
  89. }
  90. void emul_trace(ushort addr)
  91. {
  92. ushort newval = m.mem[addr+1] << 8 | m.mem[addr];
  93. if (newval != traceval) {
  94. traceval = newval;
  95. fprintf(stderr, "trace: %04x PC: %04x\n", traceval, m.cpu.PC);
  96. }
  97. }
  98. void emul_memdump()
  99. {
  100. fprintf(stderr, "Dumping memory to memdump. PC %04x\n", m.cpu.PC);
  101. FILE *fp = fopen("memdump", "w");
  102. fwrite(m.mem, 0x10000, 1, fp);
  103. fclose(fp);
  104. }
  105. void emul_printdebug()
  106. {
  107. fprintf(stderr, "Min SP: %04x\n", m.minsp);
  108. fprintf(stderr, "Max IX: %04x\n", m.maxix);
  109. }