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.

okim6258.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /**********************************************************************************************
  2. *
  3. * OKI MSM6258 ADPCM
  4. *
  5. * TODO:
  6. * 3-bit ADPCM support
  7. * Recording?
  8. *
  9. **********************************************************************************************/
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <stddef.h> // for NULL
  13. #include "v68.h"
  14. #ifdef _DEBUG
  15. #include <stdio.h>
  16. #endif
  17. #include <math.h>
  18. #include "okim6258.h"
  19. #define COMMAND_STOP (1 << 0)
  20. #define COMMAND_PLAY (1 << 1)
  21. #define COMMAND_RECORD (1 << 2)
  22. #define STATUS_PLAYING (1 << 1)
  23. #define STATUS_RECORDING (1 << 2)
  24. static const int dividers[4] = { 1024, 768, 512, 512 };
  25. #define QUEUE_SIZE (1 << 1)
  26. #define QUEUE_MASK (QUEUE_SIZE - 1)
  27. /* step size index shift table */
  28. static const int index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
  29. /* lookup table for the precomputed difference */
  30. static int diff_lookup[49*16];
  31. /* tables computed? */
  32. static int tables_computed = 0;
  33. /**********************************************************************************************
  34. compute_tables -- compute the difference tables
  35. ***********************************************************************************************/
  36. static void compute_tables(void) {
  37. if (tables_computed)
  38. return;
  39. /* nibble to bit map */
  40. static const int nbl2bit[16][4] = {
  41. { 1, 0, 0, 0}, { 1, 0, 0, 1}, { 1, 0, 1, 0}, { 1, 0, 1, 1},
  42. { 1, 1, 0, 0}, { 1, 1, 0, 1}, { 1, 1, 1, 0}, { 1, 1, 1, 1},
  43. {-1, 0, 0, 0}, {-1, 0, 0, 1}, {-1, 0, 1, 0}, {-1, 0, 1, 1},
  44. {-1, 1, 0, 0}, {-1, 1, 0, 1}, {-1, 1, 1, 0}, {-1, 1, 1, 1}
  45. };
  46. int step, nib;
  47. /* loop over all possible steps */
  48. for (step = 0; step <= 48; step++) {
  49. /* compute the step value */
  50. int stepval = floor(16.0 * pow(11.0 / 10.0, (double)step));
  51. /* loop over all nibbles and compute the difference */
  52. for (nib = 0; nib < 16; nib++) {
  53. diff_lookup[step*16 + nib] = nbl2bit[nib][0] *
  54. (stepval * nbl2bit[nib][1] +
  55. stepval/2 * nbl2bit[nib][2] +
  56. stepval/4 * nbl2bit[nib][3] +
  57. stepval/8);
  58. }
  59. }
  60. tables_computed = 1;
  61. }
  62. static int16_t clock_adpcm(struct okim6258 *chip, uint8_t nibble) {
  63. int32_t max = chip->output_mask - 1;
  64. int32_t min = -chip->output_mask;
  65. // original MAME algorithm (causes a DC offset over time)
  66. //chip->signal += diff_lookup[chip->step * 16 + (nibble & 15)];
  67. // awesome algorithm ported from XM6 - it works PERFECTLY
  68. int sample = diff_lookup[chip->step * 16 + (nibble & 15)];
  69. chip->signal = ((sample << 8) + (chip->signal * 245)) >> 8;
  70. /* clamp to the maximum */
  71. if (chip->signal > max)
  72. chip->signal = max;
  73. else if (chip->signal < min)
  74. chip->signal = min;
  75. /* adjust the step size and clamp */
  76. chip->step += index_shift[nibble & 7];
  77. if (chip->step > 48)
  78. chip->step = 48;
  79. else if (chip->step < 0)
  80. chip->step = 0;
  81. /* return the signal scaled up to 32767 */
  82. return chip->signal << 3;
  83. }
  84. /**********************************************************************************************
  85. okim6258_update -- update the sound chip so that it is in sync with CPU execution
  86. ***********************************************************************************************/
  87. void okim6258_update(struct okim6258 *chip, int16_t **outputs, int samples) {
  88. int16_t *bufL = outputs[0];
  89. int16_t *bufR = outputs[1];
  90. if (chip->status & STATUS_PLAYING) {
  91. int nibble_shift = chip->nibble_shift;
  92. while (samples) {
  93. /* Compute the new amplitude and update the current step */
  94. int nibble;
  95. int16_t sample;
  96. if (!nibble_shift) {
  97. // 1st nibble - get data
  98. if (! chip->data_empty) {
  99. chip->data_in = chip->data_buf[chip->data_buf_pos >> 4];
  100. chip->data_buf_pos += 0x10;
  101. chip->data_buf_pos &= 0x7F;
  102. if ((chip->data_buf_pos >> 4) == (chip->data_buf_pos & 0x0F))
  103. chip->data_empty ++;
  104. } else {
  105. if (chip->data_empty < 0x80)
  106. chip->data_empty ++;
  107. }
  108. }
  109. nibble = (chip->data_in >> nibble_shift) & 0xf;
  110. /* Output to the buffer */
  111. if (chip->data_empty < 0x02) {
  112. sample = clock_adpcm(chip, nibble);
  113. chip->last_smpl = sample;
  114. } else {
  115. // Valley Bell: data_empty behaviour (loosely) ported from XM6
  116. if (chip->data_empty >= 0x02 + 0x01) {
  117. chip->data_empty -= 0x01;
  118. chip->signal = chip->signal * 15 / 16;
  119. chip->last_smpl = chip->signal << 4;
  120. }
  121. sample = chip->last_smpl;
  122. }
  123. nibble_shift ^= 4;
  124. // verbose2("okim6258_update samples=%d sample=%d\n", samples, sample);
  125. *bufL++ = (chip->pan & 0x02) ? 0x00 : sample;
  126. *bufR++ = (chip->pan & 0x01) ? 0x00 : sample;
  127. samples--;
  128. }
  129. /* Update the parameters */
  130. chip->nibble_shift = nibble_shift;
  131. } else {
  132. /* Fill with 0 */
  133. while (samples--) {
  134. *bufL++ = 0;
  135. *bufR++ = 0;
  136. }
  137. }
  138. }
  139. /**********************************************************************************************
  140. OKIM6258_start -- start emulation of an OKIM6258-compatible chip
  141. ***********************************************************************************************/
  142. static int get_vclk(struct okim6258 *chip) {
  143. int clk_rnd;
  144. clk_rnd = chip->master_clock;
  145. clk_rnd += chip->divider / 2; // for better rounding - should help some of the streams
  146. return clk_rnd / chip->divider;
  147. }
  148. int okim6258_init(struct okim6258 *chip, int clock, int divider, int adpcm_type, int output_12bits) {
  149. compute_tables();
  150. chip->initial_clock = clock;
  151. chip->initial_div = divider;
  152. chip->master_clock = clock;
  153. chip->adpcm_type = /*intf->*/adpcm_type;
  154. chip->clock_buffer[0x00] = (clock & 0x000000FF) >> 0;
  155. chip->clock_buffer[0x01] = (clock & 0x0000FF00) >> 8;
  156. chip->clock_buffer[0x02] = (clock & 0x00FF0000) >> 16;
  157. chip->clock_buffer[0x03] = (clock & 0xFF000000) >> 24;
  158. /* D/A precision is 10-bits but 12-bit data can be output serially to an external DAC */
  159. chip->output_bits = output_12bits ? 12 : 10;
  160. chip->internal_10_bit = 0;
  161. if (chip->internal_10_bit)
  162. chip->output_mask = (1 << (chip->output_bits - 1));
  163. else
  164. chip->output_mask = (1 << (12 - 1));
  165. chip->divider = dividers[divider];
  166. chip->signal = -2;
  167. chip->step = 0;
  168. return get_vclk(chip);
  169. }
  170. /**********************************************************************************************
  171. OKIM6258_stop -- stop emulation of an OKIM6258-compatible chip
  172. ***********************************************************************************************/
  173. void okim6258_stop(struct okim6258 *chip) {
  174. }
  175. void okim6258_reset(struct okim6258 *chip) {
  176. chip->master_clock = chip->initial_clock;
  177. chip->clock_buffer[0x00] = (chip->initial_clock & 0x000000FF) >> 0;
  178. chip->clock_buffer[0x01] = (chip->initial_clock & 0x0000FF00) >> 8;
  179. chip->clock_buffer[0x02] = (chip->initial_clock & 0x00FF0000) >> 16;
  180. chip->clock_buffer[0x03] = (chip->initial_clock & 0xFF000000) >> 24;
  181. chip->divider = dividers[chip->initial_div];
  182. chip->signal = -2;
  183. chip->step = 0;
  184. chip->status = 0;
  185. // Valley Bell: Added reset of the Data In register.
  186. chip->data_in = 0x00;
  187. chip->data_buf[0] = chip->data_buf[1] = 0x00;
  188. chip->data_buf_pos = 0x00;
  189. chip->data_empty = 0xFF;
  190. chip->pan = 0x00;
  191. }
  192. /**********************************************************************************************
  193. okim6258_set_divider -- set the master clock divider
  194. ***********************************************************************************************/
  195. void okim6258_set_divider(struct okim6258 *chip, int val) {
  196. chip->divider = dividers[val];
  197. }
  198. /**********************************************************************************************
  199. okim6258_set_clock -- set the master clock
  200. ***********************************************************************************************/
  201. void okim6258_set_clock(struct okim6258 *chip, int val) {
  202. if (val) {
  203. chip->master_clock = val;
  204. } else {
  205. chip->master_clock = (chip->clock_buffer[0x00] << 0) |
  206. (chip->clock_buffer[0x01] << 8) |
  207. (chip->clock_buffer[0x02] << 16) |
  208. (chip->clock_buffer[0x03] << 24);
  209. }
  210. }
  211. /**********************************************************************************************
  212. okim6258_get_vclk -- get the VCLK/sampling frequency
  213. ***********************************************************************************************/
  214. int okim6258_get_vclk(struct okim6258 *chip) {
  215. return get_vclk(chip);
  216. }
  217. /**********************************************************************************************
  218. okim6258_data_w -- write to the control port of an OKIM6258-compatible chip
  219. ***********************************************************************************************/
  220. static void okim6258_data_w(struct okim6258 *chip, uint8_t data) {
  221. verbose1("okim6258_data_w data=0x%02x\n", data);
  222. if (chip->data_empty >= 0x02)
  223. chip->data_buf_pos = 0x00;
  224. chip->data_in_last = data;
  225. chip->data_buf[chip->data_buf_pos & 0x0F] = data;
  226. chip->data_buf_pos += 0x01;
  227. chip->data_buf_pos &= 0xF7;
  228. if ((chip->data_buf_pos >> 4) == (chip->data_buf_pos & 0x0F)) {
  229. chip->data_buf_pos = (chip->data_buf_pos & 0xF0) | ((chip->data_buf_pos-1) & 0x07);
  230. }
  231. chip->data_empty = 0x00;
  232. }
  233. /**********************************************************************************************
  234. okim6258_ctrl_w -- write to the control port of an OKIM6258-compatible chip
  235. ***********************************************************************************************/
  236. static void okim6258_ctrl_w(struct okim6258 *chip, uint8_t data) {
  237. if (data & COMMAND_STOP) {
  238. chip->status &= ~(STATUS_PLAYING | STATUS_RECORDING);
  239. return;
  240. }
  241. if (data & COMMAND_PLAY) {
  242. if (!(chip->status & STATUS_PLAYING)) {
  243. chip->status |= STATUS_PLAYING;
  244. /* Also reset the ADPCM parameters */
  245. chip->signal = -2; // Note: XM6 lets this fade to 0 when nothing is going on
  246. chip->step = 0;
  247. chip->nibble_shift = 0;
  248. chip->data_buf[0x00] = data;
  249. chip->data_buf_pos = 0x01; // write pos 01, read pos 00
  250. chip->data_empty = 0x00;
  251. }
  252. chip->step = 0; // this line was verified with the source of XM6
  253. chip->nibble_shift = 0;
  254. } else {
  255. chip->status &= ~STATUS_PLAYING;
  256. }
  257. if(data & COMMAND_RECORD) {
  258. chip->status |= STATUS_RECORDING;
  259. } else {
  260. chip->status &= ~STATUS_RECORDING;
  261. }
  262. }
  263. static void okim6258_set_clock_byte(struct okim6258 *chip, uint8_t Byte, uint8_t val) {
  264. chip->clock_buffer[Byte] = val;
  265. }
  266. static void okim6258_pan_w(struct okim6258 *chip, uint8_t data) {
  267. chip->pan = data;
  268. }
  269. void okim6258_write(struct okim6258 *chip, uint8_t Port, uint8_t Data) {
  270. switch(Port) {
  271. case 0x00:
  272. okim6258_ctrl_w(chip, /*0x00, */Data);
  273. break;
  274. case 0x01:
  275. okim6258_data_w(chip, /*0x00, */Data);
  276. break;
  277. case 0x02:
  278. okim6258_pan_w(chip, Data);
  279. break;
  280. case 0x08:
  281. case 0x09:
  282. case 0x0A:
  283. okim6258_set_clock_byte(chip, Port & 0x03, Data);
  284. break;
  285. case 0x0B:
  286. okim6258_set_clock_byte(chip, Port & 0x03, Data);
  287. okim6258_set_clock(chip, 0);
  288. break;
  289. case 0x0C:
  290. okim6258_set_divider(chip, Data);
  291. break;
  292. }
  293. }
  294. void okim6258_set_options(struct okim6258 *chip, uint16_t options) {
  295. chip->internal_10_bit = (options >> 0) & 0x01;
  296. }