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.

120 lines
2.3KB

  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. for (int i=0; i<0x100; i++) {
  49. m.iord[i] = NULL;
  50. m.iowr[i] = NULL;
  51. }
  52. Z80RESET(&m.cpu);
  53. m.cpu.memRead = mem_read;
  54. m.cpu.memWrite = mem_write;
  55. m.cpu.ioRead = io_read;
  56. m.cpu.ioWrite = io_write;
  57. return &m;
  58. }
  59. bool emul_step()
  60. {
  61. if (!m.cpu.halted) {
  62. Z80Execute(&m.cpu);
  63. ushort newsp = m.cpu.R1.wr.SP;
  64. if (newsp != 0 && newsp < m.minsp) {
  65. m.minsp = newsp;
  66. }
  67. return true;
  68. } else {
  69. return false;
  70. }
  71. }
  72. bool emul_steps(unsigned int steps)
  73. {
  74. while (steps) {
  75. if (!emul_step()) {
  76. return false;
  77. }
  78. steps--;
  79. }
  80. return true;
  81. }
  82. void emul_loop()
  83. {
  84. while (emul_step());
  85. }
  86. void emul_trace(ushort addr)
  87. {
  88. ushort newval = m.mem[addr+1] << 8 | m.mem[addr];
  89. if (newval != traceval) {
  90. traceval = newval;
  91. fprintf(stderr, "trace: %04x PC: %04x\n", traceval, m.cpu.PC);
  92. }
  93. }
  94. void emul_memdump()
  95. {
  96. fprintf(stderr, "Dumping memory to memdump. PC %04x\n", m.cpu.PC);
  97. FILE *fp = fopen("memdump", "w");
  98. fwrite(m.mem, 0x10000, 1, fp);
  99. fclose(fp);
  100. }
  101. void emul_printdebug()
  102. {
  103. fprintf(stderr, "Min SP: %04x\n", m.minsp);
  104. }