Human68k CUI emulator with sound.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

v68periph.c 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. #include "platform.h"
  2. #include "v68.h"
  3. #include "v68periph.h"
  4. #include "v68doscall.h"
  5. #include "v68fecall.h"
  6. #include "v68iocscall.h"
  7. #include "musashi/m68kcpu.h"
  8. #include "tools.h"
  9. /* YM2151 OPM */
  10. #define OPM_CLOCK 4000000
  11. unsigned int v68_read_periph_32(unsigned int addr);
  12. unsigned int v68_read_periph_16(unsigned int addr);
  13. unsigned int v68_read_periph_8(unsigned int addr);
  14. void v68_write_periph_32(unsigned int addr, unsigned int data);
  15. void v68_write_periph_16(unsigned int addr, unsigned int data);
  16. void v68_write_periph_8(unsigned int addr, unsigned int data);
  17. void v68_opm_write_8(uint32_t addr, uint8_t data);
  18. uint8_t v68_opm_read_8(uint32_t addr);
  19. void v68_mfp_write_8(uint32_t addr, uint8_t value);
  20. uint8_t v68_mfp_read_8(uint32_t addr);
  21. void v68_adpcm_write_8(uint32_t addr, uint8_t value);
  22. uint8_t v68_adpcm_read_8(uint32_t addr);
  23. void v68_ppi_write_8(uint32_t addr, uint8_t value);
  24. uint8_t v68_ppi_read_8(uint32_t addr);
  25. void v68_emu_write_16(uint32_t addr, uint16_t data);
  26. static uint32_t v68_opm_calc_timera(void);
  27. static uint32_t v68_opm_calc_timerb(void);
  28. static void v68_adpcm_update_clock_div(void);
  29. void v68_periph_init() {
  30. verbose1("v68_periph_init\n");
  31. // for mapping $ff0000 at $000000 at startup
  32. v68.reset_pulsed = 0;
  33. ym2151_init(&v68.opm, OPM_CLOCK, v68.sample_rate);
  34. okim6258_init(&v68.oki, 8000000, FOSC_DIV_BY_512, TYPE_4BITS, OUTPUT_12BITS);
  35. dmac_init(&v68.dmac);
  36. }
  37. void v68_periph_deinit() {
  38. dmac_deinit(&v68.dmac);
  39. okim6258_stop(&v68.oki);
  40. }
  41. void v68_periph_reset() {
  42. // Memory controller
  43. v68.reset_pulsed = 1;
  44. // OPM reset
  45. ym2151_reset_chip(&v68.opm);
  46. v68.opm_clka = 0;
  47. v68.opm_clkb = 0;
  48. v68.opm_addr_latch = 0;
  49. v68.opm_timera_counter = 0;
  50. v68.opm_timerb_counter = 0;
  51. v68.opm_timera_cycles = v68_opm_calc_timera();
  52. v68.opm_timerb_cycles = v68_opm_calc_timerb();
  53. v68.opm_flags = 0;
  54. // OKI ADPCM reset
  55. okim6258_reset(&v68.oki);
  56. v68.oki_freq = 15625;
  57. v68.oki_sample_counter = 0;
  58. v68.oki_prev_sample[0] = v68.oki_prev_sample[1] = 0;
  59. v68_adpcm_update_clock_div();
  60. dmac_reset(&v68.dmac);
  61. }
  62. uint32_t v68_int_ack_handler(int int_level) {
  63. verbose1("v68_int_ack_handler int_level=%d int_vec=0x%02x\n", int_level, v68.int_vec);
  64. if(int_level == 6) { /* MFP */
  65. CPU_INT_LEVEL = 0;
  66. int vec = v68.int_vec;
  67. if(vec) {
  68. verbose2("v68_int_ack_handler MFP int ack vec=0x%04x vector address at 0x%08x points to 0x%08x)\n", v68.int_vec, v68.int_vec * 4, m68k_read_memory_32(v68.int_vec * 4));
  69. v68.int_vec = 0;
  70. return vec;
  71. }
  72. } else if(int_level == 3) { /* DMAC */
  73. CPU_INT_LEVEL = 0;
  74. int vec = v68.int_vec;
  75. if(vec) {
  76. verbose2("v68_int_ack_handler DMAC int ack vec=0x%04x vector address at 0x%08x points to 0x%08x)\n", v68.int_vec, v68.int_vec * 4, m68k_read_memory_32(v68.int_vec * 4));
  77. v68.int_vec = 0;
  78. return vec;
  79. }
  80. }
  81. return M68K_INT_ACK_SPURIOUS;
  82. }
  83. void v68_periph_render_sample(int16_t *l, int16_t *r) {
  84. verbose1("v68_periph_render_sample\n");
  85. #ifndef __EMSCRIPTEN__
  86. if(v68.logger) {
  87. vgm_logger_wait(v68.logger, 1);
  88. }
  89. #endif
  90. int16_t *buf[2] = { l, r };
  91. ym2151_update_one(&v68.opm, buf, 1);
  92. int prev_oki_remainder = v68.oki_resample_remainder;
  93. int x = v68.oki_freq + v68.oki_resample_remainder;
  94. int oki_samples = x / v68.sample_rate;
  95. v68.oki_resample_remainder = x - oki_samples * v68.sample_rate;
  96. verbose2("v68_periph_render_samples oki_samples=%d\n", oki_samples);
  97. if(oki_samples) {
  98. int16_t tl, tr;
  99. buf[0] = &tl;
  100. buf[1] = &tr;
  101. okim6258_update(&v68.oki, buf, oki_samples);
  102. v68.oki_prev_sample[0] = tl;
  103. v68.oki_prev_sample[1] = tr;
  104. int j = 0;
  105. int x = v68.oki_freq + prev_oki_remainder;
  106. int s = x / v68.sample_rate;
  107. prev_oki_remainder = x - s * v68.sample_rate;
  108. if(s > 0 && j < oki_samples - 1)
  109. j++;
  110. *l += tl;
  111. *r += tr;
  112. } else {
  113. *l += v68.oki_prev_sample[0];
  114. *r += v68.oki_prev_sample[1];
  115. }
  116. }
  117. void v68_periph_advance(uint32_t cycles) {
  118. verbose1("v68_periph_advance cycles=%d\n", cycles);
  119. verbose2("v68_periph_advance opm_timera_counter=%d opm_timera_cycles=%d\n", v68.opm_timera_counter, v68.opm_timera_cycles);
  120. verbose2("v68_periph_advance opm_timerb_counter=%d opm_timerb_cycles=%d\n", v68.opm_timerb_counter, v68.opm_timerb_cycles);
  121. verbose2("v68_periph_advance oki_sample_counter=%d oki_sample_cycles=%d\n", v68.oki_sample_counter, v68.oki_sample_cycles);
  122. /* If timer A enabled */
  123. if((v68.opm_flags & 0x01) && v68.opm_timera_counter < v68.opm_timera_cycles) {
  124. v68.opm_timera_counter += cycles;
  125. if(v68.opm_timera_counter >= v68.opm_timera_cycles && (v68.opm_flags & 0x04)) {
  126. v68.int_vec = 0x43;
  127. verbose2("v68_periph_advance generating IRQ 6 Timer A\n");
  128. m68k_set_irq(6);
  129. }
  130. }
  131. /* If timer B enabled */
  132. if((v68.opm_flags & 0x02) && v68.opm_timerb_counter < v68.opm_timerb_cycles) {
  133. v68.opm_timerb_counter += cycles;
  134. if(v68.opm_timerb_counter >= v68.opm_timerb_cycles && (v68.opm_flags & 0x08)) {
  135. v68.int_vec = 0x43;
  136. verbose2("v68_periph_advance generating IRQ 6 Timer B\n");
  137. m68k_set_irq(6);
  138. }
  139. }
  140. /* If OKI is playing, trigger a DMA transfer */
  141. if(v68.oki.status & 0x02) {
  142. v68.oki_sample_counter += cycles;
  143. while(v68.oki_sample_counter >= v68.oki_sample_cycles) {
  144. verbose2("v68_periph_advance DMA Tick oki_sample_counter=%d oki_sample_cycles=%d\n", v68.oki_sample_counter, v68.oki_sample_cycles);
  145. v68.oki_sample_counter -= v68.oki_sample_cycles;
  146. // Trigger transfer
  147. dmac_channel_request(&v68.dmac, 3);
  148. }
  149. }
  150. verbose2("v68_periph_advance done\n");
  151. }
  152. static void v68_periph_before_write(uint32_t addr) {
  153. /* Check if sound is touched */
  154. if(!v68.sound_touched) {
  155. if(addr == 0xe92001 || addr == 0xe92003 || addr == 0xe90003) {
  156. verbose1("sound touched\n");
  157. v68.sound_touched = 1;
  158. }
  159. }
  160. }
  161. unsigned int v68_read_periph_32(unsigned int addr) {
  162. if(addr < 0xe82000) { /* CRTコントローラ ◆ CRT controller */
  163. } else if(addr < 0xe84000) { /* ビデオコントローラ ◆ Video controller */
  164. } else if(addr < 0xe86000) { /* DMAC ◆ DMA controller */
  165. return (dmac_read_16(&v68.dmac, addr & 0xfe) << 16) | dmac_read_16(&v68.dmac, (addr & 0xfe) + 2);
  166. } else if(addr < 0xe88000) { /* エリアセット ◆ Area set */
  167. } else if(addr < 0xe8a000) { /* MFP ◆ Multi-function peripheral */
  168. return
  169. (v68_mfp_read_8((addr & 0xff) + 0) << 24) |
  170. (v68_mfp_read_8((addr & 0xff) + 1) << 16) |
  171. (v68_mfp_read_8((addr & 0xff) + 2) << 8) |
  172. (v68_mfp_read_8((addr & 0xff) + 3) );
  173. } else if(addr < 0xe8c000) { /* RTC ◆ Realtime clock */
  174. } else if(addr < 0xe8e000) { /* プリンタ ◆ Printer */
  175. } else if(addr < 0xe90000) { /* システムポート ◆ System port */
  176. } else if(addr < 0xe92000) { /* FM音源 ◆ FM sound source (OPM) */
  177. return
  178. (v68_opm_read_8((addr & 0xff) + 0) << 24) |
  179. (v68_opm_read_8((addr & 0xff) + 1) << 16) |
  180. (v68_opm_read_8((addr & 0xff) + 2) << 8) |
  181. (v68_opm_read_8((addr & 0xff) + 3) );
  182. } else if(addr < 0xe94000) { /* ADPCM ◆ OKI M6258 ADPCM */
  183. return
  184. (v68_adpcm_read_8((addr & 0xff) + 0) << 24) |
  185. (v68_adpcm_read_8((addr & 0xff) + 1) << 16) |
  186. (v68_adpcm_read_8((addr & 0xff) + 2) << 8) |
  187. (v68_adpcm_read_8((addr & 0xff) + 3) );
  188. } else if(addr < 0xe96000) { /* FDC ◆ Floppy drive controller */
  189. } else if(addr < 0xe98000) { /* HDC ◆ Hard disk controller */
  190. } else if(addr < 0xe9a000) { /* SCC ◆ Serial communications */
  191. } else if(addr < 0xe9C000) { /* i8255 ◆ Programmable peripheral interface */
  192. return
  193. (v68_ppi_read_8((addr & 0xff) + 0) << 24) |
  194. (v68_ppi_read_8((addr & 0xff) + 1) << 16) |
  195. (v68_ppi_read_8((addr & 0xff) + 2) << 8) |
  196. (v68_ppi_read_8((addr & 0xff) + 3) );
  197. } else if(addr < 0xe9e000) { /* I/O コントローラ ◆ I/O controller */
  198. }
  199. return 0xffffffff;
  200. }
  201. unsigned int v68_read_periph_16(unsigned int addr) {
  202. if(addr < 0xe82000) { /* CRTコントローラ ◆ CRT controller */
  203. } else if(addr < 0xe84000) { /* ビデオコントローラ ◆ Video controller */
  204. } else if(addr < 0xe86000) { /* DMAC ◆ DMA controller */
  205. return dmac_read_16(&v68.dmac, addr & 0xfe);
  206. } else if(addr < 0xe88000) { /* エリアセット ◆ Area set */
  207. } else if(addr < 0xe8a000) { /* MFP ◆ Multi-function peripheral */
  208. return
  209. (v68_mfp_read_8((addr & 0xff) + 0) << 8) |
  210. (v68_mfp_read_8((addr & 0xff) + 1) );
  211. } else if(addr < 0xe8c000) { /* RTC ◆ Realtime clock */
  212. } else if(addr < 0xe8e000) { /* プリンタ ◆ Printer */
  213. } else if(addr < 0xe90000) { /* システムポート ◆ System port */
  214. } else if(addr < 0xe92000) { /* FM音源 ◆ FM sound source (OPM) */
  215. return
  216. (v68_opm_read_8((addr & 0xff) + 0) << 8) |
  217. (v68_opm_read_8((addr & 0xff) + 1) );
  218. } else if(addr < 0xe94000) { /* ADPCM ◆ OKI M6258 ADPCM */
  219. return
  220. (v68_adpcm_read_8((addr & 0xff) + 0) << 8) |
  221. (v68_adpcm_read_8((addr & 0xff) + 1) );
  222. } else if(addr < 0xe96000) { /* FDC ◆ Floppy drive controller */
  223. } else if(addr < 0xe98000) { /* HDC ◆ Hard disk controller */
  224. } else if(addr < 0xe9a000) { /* SCC ◆ Serial communications */
  225. } else if(addr < 0xe9C000) { /* i8255 ◆ Programmable peripheral interface */
  226. return
  227. (v68_ppi_read_8((addr & 0xff) + 0) << 8) |
  228. (v68_ppi_read_8((addr & 0xff) + 1) );
  229. } else if(addr < 0xe9e000) { /* I/O コントローラ ◆ I/O controller */
  230. }
  231. return 0xffff;
  232. }
  233. unsigned int v68_read_periph_8(unsigned int addr) {
  234. if(addr < 0xe82000) { /* CRTコントローラ ◆ CRT controller */
  235. } else if(addr < 0xe84000) { /* ビデオコントローラ ◆ Video controller */
  236. } else if(addr < 0xe86000) { /* DMAC ◆ DMA controller */
  237. return dmac_read_8(&v68.dmac, addr);
  238. } else if(addr < 0xe88000) { /* エリアセット ◆ Area set */
  239. } else if(addr < 0xe8a000) { /* MFP ◆ Multi-function peripheral */
  240. return v68_mfp_read_8(addr & 0xff);
  241. } else if(addr < 0xe8c000) { /* RTC ◆ Realtime clock */
  242. } else if(addr < 0xe8e000) { /* プリンタ ◆ Printer */
  243. } else if(addr < 0xe90000) { /* システムポート ◆ System port */
  244. } else if(addr < 0xe92000) { /* FM音源 ◆ FM sound source (OPM) */
  245. return v68_opm_read_8(addr & 0xff);
  246. } else if(addr < 0xe94000) { /* ADPCM ◆ OKI M6258 ADPCM */
  247. return v68_adpcm_read_8(addr & 0xff);
  248. } else if(addr < 0xe96000) { /* FDC ◆ Floppy drive controller */
  249. } else if(addr < 0xe98000) { /* HDC ◆ Hard disk controller */
  250. } else if(addr < 0xe9a000) { /* SCC ◆ Serial communications */
  251. } else if(addr < 0xe9C000) { /* i8255 ◆ Programmable peripheral interface */
  252. return v68_ppi_read_8(addr & 0xff);
  253. } else if(addr < 0xe9e000) { /* I/O コントローラ ◆ I/O controller */
  254. }
  255. return 0xff;
  256. }
  257. void v68_write_periph_32(unsigned int addr, unsigned int data) {
  258. verbose2("write_periph_32 addr=0x%08x data=0x%08x cycles=%d remaining=%d\n", addr, data, m68k_cycles_run(), m68k_cycles_remaining());
  259. v68_periph_before_write(addr);
  260. if(addr < 0xe82000) { /* CRTコントローラ ◆ CRT controller */
  261. } else if(addr < 0xe84000) { /* ビデオコントローラ ◆ Video controller */
  262. } else if(addr < 0xe86000) { /* DMAC ◆ DMA controller */
  263. dmac_write_16(&v68.dmac, (addr & 0x0fff) + 0, data >> 16);
  264. dmac_write_16(&v68.dmac, (addr & 0x0fff) + 2, data);
  265. } else if(addr < 0xe88000) { /* エリアセット ◆ Area set */
  266. } else if(addr < 0xe8a000) { /* MFP ◆ Multi-function peripheral */
  267. v68_mfp_write_8((addr & 0xff) + 0, (data >> 24) & 0xff);
  268. v68_mfp_write_8((addr & 0xff) + 1, (data >> 16) & 0xff);
  269. v68_mfp_write_8((addr & 0xff) + 2, (data >> 8) & 0xff);
  270. v68_mfp_write_8((addr & 0xff) + 3, (data ) & 0xff);
  271. } else if(addr < 0xe8c000) { /* RTC ◆ Realtime clock */
  272. } else if(addr < 0xe8e000) { /* プリンタ ◆ Printer */
  273. } else if(addr < 0xe90000) { /* システムポート ◆ System port */
  274. } else if(addr < 0xe92000) { /* FM音源 ◆ FM sound source (OPM) */
  275. v68_opm_write_8((addr & 0xff) + 0, (data >> 24) & 0xff);
  276. v68_opm_write_8((addr & 0xff) + 1, (data >> 16) & 0xff);
  277. v68_opm_write_8((addr & 0xff) + 2, (data >> 8) & 0xff);
  278. v68_opm_write_8((addr & 0xff) + 3, (data ) & 0xff);
  279. } else if(addr < 0xe94000) { /* ADPCM ◆ OKI M6258 ADPCM */
  280. v68_adpcm_write_8((addr & 0xff) + 0, (data >> 24) & 0xff);
  281. v68_adpcm_write_8((addr & 0xff) + 1, (data >> 16) & 0xff);
  282. v68_adpcm_write_8((addr & 0xff) + 2, (data >> 8) & 0xff);
  283. v68_adpcm_write_8((addr & 0xff) + 3, (data ) & 0xff);
  284. } else if(addr < 0xe96000) { /* FDC ◆ Floppy drive controller */
  285. } else if(addr < 0xe98000) { /* HDC ◆ Hard disk controller */
  286. } else if(addr < 0xe9a000) { /* SCC ◆ Serial communications */
  287. } else if(addr < 0xe9c000) { /* i8255 ◆ Programmable peripheral interface */
  288. v68_ppi_write_8((addr & 0xff) + 0, (data >> 24) & 0xff);
  289. v68_ppi_write_8((addr & 0xff) + 1, (data >> 16) & 0xff);
  290. v68_ppi_write_8((addr & 0xff) + 2, (data >> 8) & 0xff);
  291. v68_ppi_write_8((addr & 0xff) + 3, (data ) & 0xff);
  292. } else if(addr < 0xe9e000) { /* I/O コントローラ ◆ I/O controller */
  293. }
  294. }
  295. void v68_write_periph_16(unsigned int addr, unsigned int data) {
  296. verbose2("write_periph_16 addr=0x%08x data=0x%04x cycles=%d remaining=%d\n", addr, data, m68k_cycles_run(), m68k_cycles_remaining());
  297. v68_periph_before_write(addr);
  298. if(addr < 0xe82000) { /* CRTコントローラ ◆ CRT controller */
  299. } else if(addr < 0xe84000) { /* ビデオコントローラ ◆ Video controller */
  300. } else if(addr < 0xe86000) { /* DMAC ◆ DMA controller */
  301. dmac_write_16(&v68.dmac, addr & 0xff, data);
  302. } else if(addr < 0xe88000) { /* エリアセット ◆ Area set */
  303. } else if(addr < 0xe8a000) { /* MFP ◆ Multi-function peripheral */
  304. v68_mfp_write_8((addr & 0xff) + 0, (data >> 8) & 0xff);
  305. v68_mfp_write_8((addr & 0xff) + 1, (data ) & 0xff);
  306. } else if(addr < 0xe8c000) { /* RTC ◆ Realtime clock */
  307. } else if(addr < 0xe8e000) { /* プリンタ ◆ Printer */
  308. } else if(addr < 0xe90000) { /* システムポート ◆ System port */
  309. } else if(addr < 0xe92000) { /* FM音源 ◆ FM sound source (OPM) */
  310. v68_opm_write_8((addr & 0xff) + 0, (data >> 8) & 0xff);
  311. v68_opm_write_8((addr & 0xff) + 1, (data ) & 0xff);
  312. } else if(addr < 0xe94000) { /* ADPCM ◆ OKI M6258 ADPCM */
  313. v68_adpcm_write_8((addr & 0xff) + 0, (data >> 8) & 0xff);
  314. v68_adpcm_write_8((addr & 0xff) + 1, (data ) & 0xff);
  315. } else if(addr < 0xe96000) { /* FDC ◆ Floppy drive controller */
  316. } else if(addr < 0xe98000) { /* HDC ◆ Hard disk controller */
  317. } else if(addr < 0xe9a000) { /* SCC ◆ Serial communications */
  318. } else if(addr < 0xe9C000) { /* i8255 ◆ Programmable peripheral interface */
  319. v68_ppi_write_8((addr & 0xff) + 0, (data >> 8) & 0xff);
  320. v68_ppi_write_8((addr & 0xff) + 1, (data ) & 0xff);
  321. } else if(addr < 0xe9e000) { /* I/O コントローラ ◆ I/O controller */
  322. } else if(addr < 0xeb0000) { /* Emulator port */
  323. v68_emu_write_16(addr, data);
  324. }
  325. }
  326. void v68_write_periph_8(unsigned int addr, unsigned int data) {
  327. verbose1("v68_write_periph_8 addr=0x%08x data=0x%02x cycles=%d remaining=%d\n", addr, data, m68k_cycles_run(), m68k_cycles_remaining());
  328. v68_periph_before_write(addr);
  329. if(addr < 0xe82000) { /* CRTコントローラ ◆ CRT controller */
  330. } else if(addr < 0xe84000) { /* ビデオコントローラ ◆ Video controller */
  331. } else if(addr < 0xe86000) { /* DMAC ◆ DMA controller */
  332. dmac_write_8(&v68.dmac, addr, data);
  333. } else if(addr < 0xe88000) { /* エリアセット ◆ Area set */
  334. } else if(addr < 0xe8a000) { /* MFP ◆ Multi-function peripheral */
  335. v68_mfp_write_8(addr & 0xff, data);
  336. } else if(addr < 0xe8c000) { /* RTC ◆ Realtime clock */
  337. } else if(addr < 0xe8e000) { /* プリンタ ◆ Printer */
  338. } else if(addr < 0xe90000) { /* システムポート ◆ System port */
  339. } else if(addr < 0xe92000) { /* FM音源 ◆ FM sound source (OPM) */
  340. v68_opm_write_8(addr & 0xff, data);
  341. } else if(addr < 0xe94000) { /* ADPCM ◆ OKI M6258 ADPCM */
  342. v68_adpcm_write_8(addr & 0xff, data);
  343. } else if(addr < 0xe96000) { /* FDC ◆ Floppy drive controller */
  344. } else if(addr < 0xe98000) { /* HDC ◆ Hard disk controller */
  345. } else if(addr < 0xe9a000) { /* SCC ◆ Serial communications */
  346. } else if(addr < 0xe9C000) { /* i8255 ◆ Programmable peripheral interface */
  347. v68_ppi_write_8(addr & 0xff, data);
  348. } else if(addr < 0xe9e000) { /* I/O コントローラ ◆ I/O controller */
  349. }
  350. }
  351. /* FM音源 ◆ FM sound source (OPM) */
  352. static uint32_t v68_opm_calc_timera() {
  353. uint64_t x = 1024 * v68.opm_clka;
  354. x *= v68.cpu_clock;
  355. x /= 62500;
  356. return x;
  357. }
  358. static uint32_t v68_opm_calc_timerb() {
  359. uint64_t x = 1024 * (256 - v68.opm_clkb);
  360. x *= v68.cpu_clock;
  361. x /= 4000000;
  362. return x;
  363. }
  364. void v68_opm_write_8(uint32_t addr, uint8_t data) {
  365. verbose1("v68_opm_write_8 0x%08x 0x%02x\n", addr, data);
  366. switch(addr) {
  367. case 0x01:
  368. v68.opm_addr_latch = data;
  369. break;
  370. case 0x03: {
  371. verbose2("v68_opm_write_8 DATA opm_addr_latch=0x%02x data=0x%02x\n", v68.opm_addr_latch, data);
  372. ym2151_write_reg(&v68.opm, v68.opm_addr_latch, data);
  373. #ifndef __EMSCRIPTEN__
  374. if(v68.logger)
  375. vgm_logger_write_ym2151(v68.logger, v68.opm_addr_latch, data);
  376. #endif
  377. int clka = v68.opm_clka, clkb = v68.opm_clkb;
  378. switch(v68.opm_addr_latch) {
  379. case 0x10:
  380. clka &= 0x0003;
  381. clka |= data << 2;
  382. if(v68.opm_clka != clka) {
  383. v68.opm_clka = clka;
  384. v68.opm_timera_cycles = v68_opm_calc_timera();
  385. }
  386. break;
  387. case 0x11:
  388. clka &= 0x03fc;
  389. clka |= data & 0x03;
  390. if(v68.opm_clka != clka) {
  391. v68.opm_clka = clka;
  392. v68.opm_timera_cycles = v68_opm_calc_timera();
  393. }
  394. break;
  395. case 0x12:
  396. clkb = data;
  397. if(v68.opm_clkb != clkb) {
  398. v68.opm_clkb = clkb;
  399. v68.opm_timerb_cycles = v68_opm_calc_timerb();
  400. }
  401. break;
  402. case 0x14: {
  403. v68.opm_flags = data & 0x0f;
  404. /* Check for reset */
  405. if(data & 0x10) {
  406. v68.opm_timera_counter = 0;
  407. }
  408. if(data & 0x20) {
  409. v68.opm_timerb_counter = 0;
  410. }
  411. }
  412. break;
  413. case 0x1b: {
  414. v68.opm_ct = data & 0xc0;
  415. int clock = v68.opm_ct & 0x80 ? 4000000 : 8000000;
  416. verbose2("v68_opm_write_8 setting ADPCM Clock CT1=%d CT2=%d clock=%d\n", v68.opm_ct >> 7, v68.opm_ct >> 6 & 0x01, clock)
  417. okim6258_set_clock(&v68.oki, clock);
  418. v68_adpcm_update_clock_div();
  419. }
  420. break;
  421. }
  422. }
  423. break;
  424. }
  425. }
  426. uint8_t v68_opm_read_8(uint32_t addr) {
  427. verbose1("v68_opm_read_8 addr=0x%08x\n", addr);
  428. switch(addr) {
  429. case 0x03: {
  430. uint8_t ret = 0;
  431. if(v68.opm_timera_counter >= v68.opm_timera_cycles) ret |= 0x01;
  432. if(v68.opm_timerb_counter >= v68.opm_timerb_cycles) ret |= 0x02;
  433. return ret;
  434. }
  435. }
  436. return 0x00;
  437. }
  438. /* MFP ◆ Multi-function peripheral */
  439. void v68_mfp_write_8(uint32_t addr, uint8_t value) {
  440. verbose2("v68_mfp_write_8 *STUB* 0x%08x = 0x%02x\n", addr, value);
  441. }
  442. uint8_t v68_mfp_read_8(uint32_t addr) {
  443. verbose2("v68_mfp_read_8 *STUB* %08x\n", addr);
  444. return 0x00;
  445. }
  446. /* ADPCM ◆ OKI M6258 ADPCM */
  447. void v68_adpcm_write_8(uint32_t addr, uint8_t value) {
  448. verbose1("v68_adpcm_write_8 addr=0x%08x value=0x%02x\n", addr, value);
  449. switch(addr) {
  450. case 0x01: /* 0xe92001 ADPCM command */
  451. okim6258_write(&v68.oki, 0x00, value);
  452. #ifndef __EMSCRIPTEN__
  453. if(v68.logger)
  454. vgm_logger_write_okim6258(v68.logger, 0x00, value);
  455. #endif
  456. if(value & 0x02) {
  457. v68_adpcm_update_clock_div();
  458. }
  459. break;
  460. case 0x03: /* 0xe92003 Data input / output */
  461. okim6258_write(&v68.oki, 0x01, value);
  462. #ifndef __EMSCRIPTEN__
  463. if(v68.logger)
  464. vgm_logger_write_okim6258(v68.logger, 0x01, value);
  465. #endif
  466. break;
  467. }
  468. }
  469. uint8_t v68_adpcm_read_8(uint32_t addr) {
  470. verbose1("v68_adpcm_read_8 0x%08x\n", addr);
  471. return 0x00;
  472. }
  473. static void v68_adpcm_update_clock_div() {
  474. /* it's actually cpu_clock / (sample rate / 2), 1 byte contains 2 samples */
  475. //v68.oki_sample_cycles = v68.cpu_clock * 2 / 15625;
  476. uint64_t cycles = v68.cpu_clock;
  477. cycles *= v68.oki.divider;
  478. cycles *= 2;
  479. cycles /= v68.oki.master_clock;
  480. v68.oki_sample_cycles = cycles;
  481. v68.oki_freq = v68.oki.master_clock / v68.oki.divider;
  482. verbose2("v68_adpcm_update_clock_div cpu_clock=%d divider=%d oki_clock=%d oki_sample_cycles=%d oki_freq=%d\n", v68.cpu_clock, v68.oki.divider, v68.oki.master_clock, v68.oki_sample_cycles, v68.oki_freq);
  483. }
  484. /* i8255 ◆ Programmable peripheral interface */
  485. void v68_ppi_write_8(uint32_t addr, uint8_t value) {
  486. if(addr == 0x05) {
  487. uint8_t new_oki_div = value >> 2 & 0x03;
  488. okim6258_set_divider(&v68.oki, new_oki_div);
  489. v68_adpcm_update_clock_div();
  490. verbose2("v68_ppi_write_8 Port C %02x -> %02x\n", v68.ppi_port_c, value);
  491. v68.ppi_port_c = value;
  492. } else if(addr == 0x07) {
  493. if(value & 0x80) {
  494. verbose2("v68_ppi_ctr %02x -> %02x\n", v68.ppi_ctrl, value & 0x7f);
  495. v68.ppi_ctrl = value & 0x7f;
  496. } else {
  497. uint8_t port_c = v68.ppi_port_c;
  498. uint8_t bitsel = (value >> 1) & 0x07;
  499. uint8_t bit = 1 << bitsel;
  500. if(value & 0x01) {
  501. port_c = port_c | bit;
  502. } else {
  503. port_c = port_c & ~bit;
  504. }
  505. verbose2("v68_ppi_write_8 Port C %02x -> %02x\n", v68.ppi_port_c, port_c);
  506. if(bitsel >= 2 && bitsel <= 3) {
  507. uint8_t new_oki_div = (port_c >> 2) & 0x03;
  508. verbose2("v68_ppi_write_8 setting ADPCM divider %d\n", new_oki_div)
  509. okim6258_set_divider(&v68.oki, new_oki_div);
  510. v68_adpcm_update_clock_div();
  511. }
  512. v68.ppi_port_c = port_c;
  513. }
  514. }
  515. verbose2("v68_ppi_write_8 0x%08x = 0x%02x\n", addr, value);
  516. }
  517. uint8_t v68_ppi_read_8(uint32_t addr) {
  518. verbose2("v68_ppi_read_8 0x%08x\n", addr);
  519. if(addr == 0x05) {
  520. return v68.ppi_port_c;
  521. }
  522. return 0x00;
  523. }
  524. /* Emulator specific ports */
  525. void v68_emu_write_16(uint32_t addr, uint16_t data) {
  526. verbose1("v68_emu_write_16 addr=0x%08x data=0x%04x\n", addr, data);
  527. if(addr == 0xea0000) {
  528. if((data & 0xff00) == 0xff00)
  529. v68_dos_call(data);
  530. else if((data & 0xff00) == 0xfe00)
  531. v68_fe_call(data);
  532. } else if(addr == 0xea0004) {
  533. v68_iocs_call(data);
  534. } else if(addr == 0xea0008) {
  535. v68_queue_next_command();
  536. }
  537. }