Human68k CUI emulator with sound.
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.

v68.c 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <string.h>
  5. #include <limits.h>
  6. #include "v68.h"
  7. #include "v68ipl.h"
  8. #include "v68io.h"
  9. #include "v68periph.h"
  10. #include "v68iocscall.h"
  11. #include "musashi/m68kcpu.h"
  12. struct v68 v68;
  13. int v68_init(int clock, int ram_size, int sample_rate) {
  14. memset(&v68, 0, sizeof(v68));
  15. v68.log_dasm = 0;
  16. v68.verbosity = 0;
  17. v68.ram_size = ram_size;
  18. v68.cpu_clock = clock;
  19. v68.sound_touched = 0;
  20. v68.sample_rate = sample_rate;
  21. v68.samples_remainder = 0;
  22. v68.ram = calloc(v68.ram_size, 1);
  23. if(!v68.ram) return errno;
  24. m68k_init();
  25. m68k_set_cpu_type(M68K_CPU_TYPE_68000);
  26. v68_io_init();
  27. return 0;
  28. }
  29. void v68_boot() {
  30. verbose1("v68_boot\n");
  31. v68_ipl_init();
  32. v68_human_init();
  33. v68_periph_init();
  34. v68_iocs_init();
  35. m68k_pulse_reset();
  36. }
  37. void v68_cpu_reset_instr_cb(void) {
  38. verbose2("RESET peripherals\n");
  39. v68.reset_pulsed = 1;
  40. }
  41. int v68_shutdown() {
  42. free(v68.ram);
  43. return 0;
  44. }
  45. extern int m68ki_initial_cycles;
  46. void v68_run() {
  47. verbose1("v68_run cpu_clock=%d sound_touched=%d running=%d\n", v68.cpu_clock, v68.sound_touched, v68.running);
  48. int remaining_tstates = v68.cpu_clock;
  49. v68.running = 1;
  50. while(!v68.sound_touched) {
  51. while(remaining_tstates > 0 && v68.running) {
  52. int next_int = v68_periph_next_int(remaining_tstates);
  53. verbose2("v68_run executing next_int=%d remaining_tstates=%d\n", next_int, remaining_tstates);
  54. v68.cpu_ended_timeslice = 0;
  55. v68.prev_sound_cycles = 0;
  56. int cycles = m68k_execute(next_int, v68.log_dasm);
  57. int executed_cycles = v68.cpu_ended_timeslice ? next_int - m68ki_initial_cycles : cycles;
  58. verbose2("v68_run ended_timeslice=%d executed_cycles=%d next_int=%d remaining_tstates = %d\n", v68.cpu_ended_timeslice, executed_cycles, next_int, remaining_tstates);
  59. v68.cpu_ended_timeslice = 0;
  60. if(v68.sound_touched) return;
  61. }
  62. }
  63. }
  64. int v68_fill_buffer(int samples, int16_t *bufL, int16_t *bufR, int16_t *tmpBufL, int16_t *tmpBufR) {
  65. verbose1("v68_fill_buffer samples=%d\n", samples);
  66. v68.prev_sound_cycles = 0;
  67. v68.buf_remaining = samples;
  68. v68.bufL = bufL;
  69. v68.bufR = bufR;
  70. v68.tmpBufL = tmpBufL;
  71. v68.tmpBufR = tmpBufR;
  72. memset(bufL, 0, samples * sizeof(*bufL));
  73. memset(bufR, 0, samples * sizeof(*bufR));
  74. int64_t x = (int64_t)samples * v68.cpu_clock + v68.cpu_cycle_remainder;
  75. int cpu_tstates = x / v68.sample_rate;
  76. v68.cpu_cycle_remainder = x - cpu_tstates * v68.sample_rate;
  77. verbose2("v68_fill_buffer cpu_tstates=%d CPU_STOPPED=%d PC=%08x v68.sample_rate=%d\n", cpu_tstates, CPU_STOPPED, REG_PC, v68.sample_rate);
  78. int remaining_tstates = cpu_tstates;
  79. while(remaining_tstates > 0) {
  80. verbose2("v68_fill_buffer remaining_tstates=%d opm_flags=0x%02x\n", remaining_tstates, v68.opm_flags);
  81. int next_int = v68_periph_next_int(remaining_tstates);
  82. verbose2("v68_fill_buffer executing next_int=%d remaining_tstates=%d\n", next_int, remaining_tstates);
  83. v68.cpu_ended_timeslice = 0;
  84. v68.prev_sound_cycles = 0;
  85. int cycles = m68k_execute(next_int, v68.log_dasm);
  86. int executed_cycles = v68.cpu_ended_timeslice ? next_int - m68ki_initial_cycles : cycles;
  87. verbose2("v68_fill_buffer ended_timeslice=%d executed_cycles=%d next_int=%d remaining_tstates = %d\n", v68.cpu_ended_timeslice, executed_cycles, next_int, remaining_tstates);
  88. v68.cpu_ended_timeslice = 0;
  89. verbose2("v68_fill_buffer advancing executed_cycles=%d - prev_sound_cycles=%d = %d\n", executed_cycles, v68.prev_sound_cycles, executed_cycles - v68.prev_sound_cycles);
  90. v68.periph_cycles = v68.prev_sound_cycles;
  91. v68_periph_advance(executed_cycles - v68.prev_sound_cycles);
  92. verbose2("v68_fill_buffer remaining_tstates=%d executed_cycles=%d remaining_tstates-executed_cycles=%d\n", remaining_tstates, executed_cycles, remaining_tstates-executed_cycles);
  93. remaining_tstates -= executed_cycles;
  94. }
  95. verbose2("v68_fill_buffer filled buffer buf_remaining=%d\n", v68.buf_remaining);
  96. return 0;
  97. }
  98. unsigned int m68k_read_memory_8(unsigned int addr) {
  99. if(addr <= 0x0000ffff && !v68.reset_pulsed) {
  100. uint8_t r = v68_ipl_read_8(addr + 0xff0000);
  101. verbose3("READ8 BOOT 0x%08x = 0x%02x\n", addr, r);
  102. return r;
  103. }
  104. if(addr >= 0x00fe0000 && addr <= 0x00ffffff) {
  105. uint8_t r = v68_ipl_read_8(addr);
  106. verbose3("READ8 IPL 0x%08x = 0x%02x\n", addr, r);
  107. return r;
  108. }
  109. if(addr >= 0x00e80000 && addr < 0x00eb0000) {
  110. uint8_t r = v68_read_periph_8(addr);
  111. verbose3("READ8 PERIPH 0x%08x = 0x%02x\n", addr, r);
  112. return r;
  113. }
  114. if(addr >= v68.ram_size) {
  115. fprintf(stderr, "READ8 ERROR 0x%08x\n", addr);
  116. exit(1);
  117. }
  118. uint8_t r = v68.ram[addr];
  119. verbose3("READ8 RAM 0x%08x = 0x%02x\n", addr, r);
  120. return r;
  121. }
  122. unsigned int m68k_read_memory_16(unsigned int addr) {
  123. if(addr <= 0x0000ffff && !v68.reset_pulsed) {
  124. uint16_t r = v68_ipl_read_16(addr + 0xff0000);
  125. verbose3("READ16 BOOT 0x%08x = 0x%04x\n", addr, r);
  126. return r;
  127. }
  128. if(addr >= 0x00fe0000 && addr <= 0x00ffffff) {
  129. uint16_t r = v68_ipl_read_16(addr);
  130. verbose3("READ16 IPL 0x%08x = 0x%04x\n", addr, r);
  131. return r;
  132. }
  133. if(addr >= 0x00e80000 && addr < 0x00eb0000) {
  134. uint16_t r = v68_read_periph_16(addr);
  135. verbose3("READ16 PERIPH 0x%08x = 0x%04x\n", addr, r);
  136. return r;
  137. }
  138. if(addr >= v68.ram_size - 1) {
  139. fprintf(stderr, "READ16 ERROR 0x%08x\n", addr);
  140. exit(1);
  141. }
  142. uint16_t r = (v68.ram[addr] << 8) | v68.ram[addr + 1];
  143. verbose3("READ16 RAM 0x%08x = 0x%04x\n", addr, r);
  144. return r;
  145. }
  146. unsigned int m68k_read_memory_32(unsigned int addr) {
  147. if(addr <= 0x0000ffff && !v68.reset_pulsed) {
  148. uint32_t r = v68_ipl_read_32(addr + 0xff0000);
  149. verbose3("READ32 BOOT 0x%08x = 0x%08x\n", addr, r);
  150. return r;
  151. }
  152. if(addr >= 0x00fe0000 && addr <= 0x00ffffff) {
  153. uint32_t r = v68_ipl_read_32(addr);
  154. verbose3("READ32 IPL 0x%08x = 0x%08x\n", addr, r);
  155. return r;
  156. }
  157. if(addr >= 0x00e80000 && addr < 0x00eb0000) {
  158. uint32_t r = v68_read_periph_32(addr);
  159. verbose3("READ32 PERIPH 0x%08x = 0x%08x\n", addr, r);
  160. return r;
  161. }
  162. if(addr > v68.ram_size) {
  163. fprintf(stderr, "READ32 ERROR 0x%08x\n", addr);
  164. exit(1);
  165. }
  166. uint32_t r =
  167. (v68.ram[addr] << 24) |
  168. (v68.ram[addr+1] << 16) |
  169. (v68.ram[addr+2] << 8) |
  170. v68.ram[addr+3];
  171. verbose3("READ32 RAM 0x%08x = 0x%08x\n", addr, r);
  172. return r;
  173. }
  174. void m68k_write_memory_8(unsigned int addr, unsigned int data) {
  175. if(addr >= 0x00e80000 && addr < 0x00eb0000) {
  176. verbose3("WRITE8 PERIPH 0x%08x = 0x%02x\n", addr, data);
  177. v68_write_periph_8(addr, data);
  178. return;
  179. }
  180. verbose3("WRITE8 RAM 0x%08x = 0x%02x\n", addr, data);
  181. if(addr > v68.ram_size) {
  182. fprintf(stderr, "Could not write RAM at 0x%08x = 0x%02x\n", addr, data);
  183. exit(1);
  184. }
  185. v68.ram[addr] = data;
  186. }
  187. void m68k_write_memory_16(unsigned int addr, unsigned int data) {
  188. verbose3("WRITE16 0x%08x = 0x%04x\n", addr, data);
  189. if(addr >= 0x00e80000 && addr < 0x00eb0000) {
  190. verbose3("WRITE16 PERIPH 0x%08x = 0x%04x\n", addr, data);
  191. v68_write_periph_16(addr, data);
  192. return;
  193. }
  194. if(addr > v68.ram_size) {
  195. fprintf(stderr, "Could not write RAM at 0x%08x = 0x%04x\n", addr, data);
  196. exit(1);
  197. }
  198. v68.ram[addr++] = data >> 8;
  199. v68.ram[addr] = data;
  200. }
  201. void m68k_write_memory_32(unsigned int addr, unsigned int data) {
  202. if(addr >= 0x00e80000 && addr < 0x00eb0000) {
  203. verbose3("WRITE32 PERIPH 0x%08x = 0x%08x\n", addr, data);
  204. v68_write_periph_32(addr, data);
  205. return;
  206. }
  207. verbose3("WRITE32 RAM 0x%08x = 0x%08x\n", addr, data);
  208. if(addr > v68.ram_size) {
  209. fprintf(stderr, "Could not write RAM at 0x%08x = 0x%08x\n", addr, data);
  210. exit(1);
  211. }
  212. v68.ram[addr++] = data >> 24;
  213. v68.ram[addr++] = data >> 16;
  214. v68.ram[addr++] = data >> 8;
  215. v68.ram[addr] = data;
  216. }
  217. unsigned int m68k_read_disassembler_8 (unsigned int addr) {
  218. return m68k_read_memory_8(addr);
  219. }
  220. unsigned int m68k_read_disassembler_16 (unsigned int addr) {
  221. return m68k_read_memory_16(addr);
  222. }
  223. unsigned int m68k_read_disassembler_32 (unsigned int addr) {
  224. return m68k_read_memory_32(addr);
  225. }
  226. int v68_trap(int which) {
  227. verbose1("v68_trap which=%d d0=0x%08x\n", which, m68k_get_reg(NULL, M68K_REG_D0));
  228. switch(which) {
  229. case 15:
  230. /* IOCS */
  231. return v68_iocs_call(m68k_get_reg(NULL, M68K_REG_D0));
  232. default:
  233. verbose2("v68_trap unknown #%d d0=0x%08x\n", which, m68k_get_reg(0, M68K_REG_D0));
  234. }
  235. return 1;
  236. }