NESe (pronounced "Nessie") is a NES emulator based on the e6502 emulator, also written in C with a focus on speed and portability for use on embedded platforms, especially ARM.
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.

511 lines
15KB

  1. #ifndef APU_H_
  2. #define APU_H_
  3. #include "nes.h"
  4. #include "apu.h"
  5. #include "blip-buf/blip_buf.h"
  6. #define apu_gain_square (563U)
  7. #define apu_gain_triangle (723U)
  8. #define apu_gain_noise (482U)
  9. #define apu_gain_dmc (240U)
  10. static const uint8_t apu_length_lut[32] = {
  11. 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06,
  12. 0xA0, 0x08, 0x3C, 0x0A, 0x0E, 0x0C, 0x1A, 0x0E,
  13. 0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16,
  14. 0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E,
  15. };
  16. static const uint16_t noise_period_lut[16] = {
  17. 4, 8, 16, 32, 64, 96, 128, 160,
  18. 202, 254, 380, 508, 762, 1016, 2034, 4068,
  19. };
  20. static const uint16_t dmc_period_lut[16] = {
  21. 428, 380, 340, 320, 286, 254, 226, 214,
  22. 190, 160, 142, 128, 106, 84, 72, 54,
  23. };
  24. static const void dmc_restart(nes_apu_Channel* channel) {
  25. channel->length = (channel->reg[3] * 16) + 1;
  26. channel->addr = 0x4000U | ((uint16_t)channel->reg[2] << 6);
  27. }
  28. static const void nes_apu_dmc_fetch(nes_apu* apu,
  29. nes_apu_Channel* channel) {
  30. channel->data = apu->mem_read(apu->arg_mem,
  31. 0x8000U | channel->addr);
  32. channel->mask = 1;
  33. channel->addr = (channel->addr + 1) & 0x7FFFU;
  34. channel->length--;
  35. if (channel->length <= 0) {
  36. if (channel->reg[0] & apu_DMC_Loop) {
  37. dmc_restart(channel);
  38. } else if (channel->reg[0] & apu_DMC_IRQ_Enable) {
  39. channel->interrupt = 1;
  40. }
  41. }
  42. }
  43. static const void nes_apu_dmc_start(nes_apu* apu,
  44. nes_apu_Channel* channel) {
  45. dmc_restart(channel);
  46. nes_apu_dmc_fetch(apu, channel);
  47. }
  48. static void nes_apu_write_square(nes_apu_Channel* channel,
  49. int reg, uint8_t val) {
  50. APU_LOG("APU: Square %d < %02x\n", reg, val);
  51. // TODO
  52. }
  53. static inline void apu_channel_update_timer(
  54. nes_apu_Channel *channel) {
  55. channel->period = (
  56. channel->reg[2] |
  57. (((uint16_t)channel->reg[3] & 0x7U) << 8)
  58. ) * nes_clock_cpu_div;
  59. }
  60. static void nes_apu_write_triangle(nes_apu_Channel* channel,
  61. int reg, uint8_t val) {
  62. APU_LOG("APU: Triangle %d < %02x\n", reg, val);
  63. if (2 <= reg) {
  64. channel->reg[reg] = val;
  65. apu_channel_update_timer(channel);
  66. if (3 == reg) channel->reload = 1;
  67. }
  68. }
  69. static void nes_apu_write_noise(nes_apu_Channel* channel,
  70. int reg, uint8_t val) {
  71. APU_LOG("APU: Noise %d < %02x\n", reg, val);
  72. if (reg == 0) {
  73. channel->envelope = (val & apu_Envelope_Volume);
  74. } else if (reg == 2) {
  75. channel->period = noise_period_lut[val & apu_Noise_Period] *
  76. nes_clock_cpu_div;
  77. }
  78. }
  79. static void nes_apu_write_dmc(nes_apu_Channel* channel,
  80. int reg, uint8_t val) {
  81. APU_LOG("APU: DMC %d < %02x\n", reg, val);
  82. if (reg == 0) {
  83. channel->period = dmc_period_lut[val & apu_DMC_Period] *
  84. nes_clock_cpu_div;
  85. if (!(val & apu_DMC_IRQ_Enable)) {
  86. channel->interrupt = 0;
  87. }
  88. } else if (reg == 1) {
  89. channel->sample = (val & 0x7FU);
  90. }
  91. }
  92. int nes_apu_init(nes_apu* apu, int clock, int frequency,
  93. uint8_t(*mem_read)(void*, uint16_t),
  94. void* arg_mem) {
  95. int ret = 0;
  96. // 20 ms buffer
  97. apu->blip = blip_new(frequency / 20);
  98. if (NULL == apu->blip) {
  99. APU_ERR("APU: Failed to create resampler\n");
  100. ret = -1;
  101. } else {
  102. blip_set_rates(apu->blip, clock, frequency);
  103. nes_apu_reset(apu);
  104. apu->mem_read = mem_read;
  105. apu->arg_mem = arg_mem;
  106. apu->channels[apu_Channel_Square_0].write = nes_apu_write_square;
  107. apu->channels[apu_Channel_Square_1].write = nes_apu_write_square;
  108. apu->channels[apu_Channel_Triangle].write = nes_apu_write_triangle;
  109. apu->channels[apu_Channel_Noise].write = nes_apu_write_noise;
  110. apu->channels[apu_Channel_DMC].write = nes_apu_write_dmc;
  111. apu->channels[apu_Channel_Square_0].gain = apu_gain_square;
  112. apu->channels[apu_Channel_Square_1].gain = apu_gain_square;
  113. apu->channels[apu_Channel_Triangle].gain = apu_gain_triangle;
  114. apu->channels[apu_Channel_Noise].gain = apu_gain_noise;
  115. apu->channels[apu_Channel_DMC].gain = apu_gain_dmc;
  116. apu->channels[apu_Channel_Noise].lfsr = 0x7FFFU;
  117. apu->frame_period = clock / 240;
  118. }
  119. return ret;
  120. }
  121. void nes_apu_done(nes_apu* apu) {
  122. blip_delete(apu->blip);
  123. }
  124. void nes_apu_reset(nes_apu* apu) {
  125. apu->status = 0;
  126. for (int chan = 0; chan < nes_apu_chan_count; ++chan) {
  127. apu->channels[chan].length = 0;
  128. }
  129. apu->channels[apu_Channel_Triangle].step = 31;
  130. apu->channels[apu_Channel_DMC].reg[1] &= 1;
  131. apu->channels[apu_Channel_DMC].sample = 0;
  132. }
  133. uint8_t nes_apu_read(nes_apu* apu, uint16_t addr) {
  134. uint8_t val = 0;
  135. if (addr == nes_apu_reg_status) {
  136. for (int chan = 0; chan < nes_apu_chan_count; ++chan) {
  137. if (apu->channels[chan].length > 0) {
  138. val |= (1 << chan);
  139. }
  140. }
  141. if (apu->channels[apu_Channel_DMC].interrupt) {
  142. val |= apu_Status_DMC_Int;
  143. }
  144. if (apu->status & apu_Status_Frame_Int) {
  145. val |= apu_Status_Frame_Int;
  146. apu->status &= ~apu_Status_Frame_Int;
  147. }
  148. APU_LOG("APU: Status %02x\n", val);
  149. }
  150. return val;
  151. }
  152. void nes_apu_write(nes_apu* apu, uint16_t addr, uint8_t val) {
  153. if (addr < nes_apu_reg_base +
  154. (nes_apu_chan_count * nes_apu_chan_size)) {
  155. int chan = (addr - nes_apu_reg_base) / nes_apu_chan_size;
  156. int reg = (addr - nes_apu_reg_base) % nes_apu_chan_size;
  157. nes_apu_Channel* channel = &apu->channels[chan];
  158. if (3 == reg) {
  159. if ( chan != apu_Channel_DMC &&
  160. apu->status & (1 << chan)) {
  161. channel->length = apu_length_lut[val >> 3];
  162. // TODO: Handle Envelope vs. Triangle
  163. channel->envelope = 15;
  164. channel->env_period = (channel->reg[0] & apu_Envelope_Volume);
  165. channel->env_delay = channel->env_period;
  166. }
  167. }
  168. channel->write(channel, reg, val);
  169. channel->reg[reg] = val;
  170. } else if (addr == nes_apu_reg_status) {
  171. APU_LOG("APU: Enable %02x\n", val);
  172. for (int chan = 0; chan < nes_apu_chan_count; ++chan) {
  173. if (!(val & (1 << chan))) {
  174. apu->channels[chan].length = 0;
  175. }
  176. }
  177. if ( (val & (1 << apu_Channel_DMC)) &&
  178. !(apu->status & (1 << apu_Channel_DMC))) {
  179. nes_apu_dmc_start(apu,
  180. &apu->channels[apu_Channel_DMC]);
  181. }
  182. if (!(val & (1 << apu_Channel_DMC))) {
  183. apu->channels[apu_Channel_DMC].interrupt = 0;
  184. }
  185. apu->status &= ~((1 << nes_apu_chan_count) - 1);
  186. apu->status |= (val & ((1 << nes_apu_chan_count) - 1));
  187. } else if (addr == nes_apu_reg_frame) {
  188. APU_LOG("APU: Frame %02x\n", val);
  189. apu->frame_reg = val &
  190. (apu_Frame_Mode | apu_Frame_Inhibit);
  191. apu->frame = 0;
  192. apu->frame_delay = 0;
  193. if (val & apu_Frame_Inhibit) {
  194. apu->status &= ~apu_Status_Frame_Int;
  195. }
  196. }
  197. }
  198. static int channel_update(nes_apu_Channel* channel) {
  199. int output = (channel->gain * channel->sample);
  200. int delta = output - channel->output;
  201. channel->output = output;
  202. return delta;
  203. }
  204. static void nes_apu_run_dmc(nes_apu* apu,
  205. nes_apu_Channel* channel,
  206. int cycles) {
  207. if (channel->length <= 0 || channel->period <= 0) return;
  208. int time = apu->time;
  209. int delta = channel_update(channel);
  210. if (delta) {
  211. blip_add_delta(apu->blip, time, delta);
  212. }
  213. while (cycles > 0) {
  214. int run = cycles;
  215. if (run > channel->delay) {
  216. run = channel->delay;
  217. }
  218. channel->delay -= run;
  219. time += run;
  220. if (channel->delay <= 0) {
  221. channel->delay = channel->period;
  222. delta = (channel->mask & channel->data) ? 2 : -2;
  223. int sample = channel->sample + delta;
  224. if ((unsigned)sample <= 0x7FU) {
  225. channel->sample = sample;
  226. delta = channel_update(channel);
  227. if (delta) {
  228. blip_add_delta(apu->blip, time, delta);
  229. }
  230. }
  231. channel->mask <<= 1;
  232. if (!channel->mask) {
  233. nes_apu_dmc_fetch(apu, channel);
  234. }
  235. }
  236. cycles -= run;
  237. }
  238. }
  239. static inline int apu_envelope_volume(nes_apu_Channel* channel) {
  240. return ( (channel->reg[0] & apu_Envelope_Constant) ?
  241. (channel->reg[0] & apu_Envelope_Volume) :
  242. (channel->envelope) );
  243. }
  244. static void nes_apu_run_noise(nes_apu* apu,
  245. nes_apu_Channel* channel,
  246. int cycles) {
  247. if (channel->length <= 0 || channel->period <= 0) return;
  248. int time = apu->time;
  249. while (cycles > 0) {
  250. int run = cycles;
  251. if (run > channel->delay) {
  252. run = channel->delay;
  253. }
  254. channel->delay -= run;
  255. time += run;
  256. if (channel->delay <= 0) {
  257. channel->delay = channel->period;
  258. uint16_t feedback = (1 & (channel->lfsr ^ (
  259. channel->lfsr >> (
  260. (channel->reg[2] & apu_Noise_Mode) ?
  261. 6 : 1
  262. )
  263. )
  264. ));
  265. channel->lfsr = (feedback << 14) |
  266. (channel->lfsr >> 1);
  267. channel->sample = (channel->lfsr & 1) ?
  268. apu_envelope_volume(channel) : 0;
  269. int delta = channel_update(channel);
  270. if (delta) {
  271. blip_add_delta(apu->blip, time, delta);
  272. }
  273. }
  274. cycles -= run;
  275. }
  276. }
  277. static uint8_t triangle_steps[32] = {
  278. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
  279. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  280. };
  281. static void nes_apu_run_triangle(nes_apu* apu,
  282. nes_apu_Channel* channel,
  283. int cycles) {
  284. if ( channel->length <= 0 ||
  285. channel->period <= 0 ||
  286. channel->counter <= 0) {
  287. return;
  288. }
  289. int time = apu->time;
  290. while (cycles > 0) {
  291. int run = cycles;
  292. if (run > channel->delay) {
  293. run = channel->delay;
  294. }
  295. channel->delay -= run;
  296. time += run;
  297. if (channel->delay <= 0) {
  298. channel->delay = channel->period;
  299. channel->step = ((channel->step + 1) & 31U);
  300. channel->sample = triangle_steps[channel->step];
  301. int delta = channel_update(channel);
  302. if (delta) {
  303. blip_add_delta(apu->blip, time, delta);
  304. }
  305. }
  306. cycles -= run;
  307. }
  308. }
  309. static inline void nes_apu_clock_length(nes_apu_Channel* channel,
  310. uint8_t halt_mask) {
  311. if ( channel->length > 0 &&
  312. !(channel->reg[0] & halt_mask)) {
  313. channel->length--;
  314. }
  315. }
  316. static inline void nes_apu_clock_envelope(nes_apu_Channel* channel) {
  317. if (channel->env_delay <= 0) {
  318. channel->env_delay = channel->env_period;
  319. if ( channel->envelope > 0 ||
  320. (channel->reg[0] & apu_Envelope_Halt)) {
  321. channel->envelope = ((channel->envelope - 1) & 0xFU);
  322. }
  323. } else {
  324. channel->env_delay--;
  325. }
  326. }
  327. static inline void nes_apu_clock_linear(nes_apu_Channel* channel) {
  328. if (channel->reload) {
  329. channel->counter = (channel->reg[0] & apu_Triangle_Count);
  330. } else if (channel->counter > 0) {
  331. channel->counter--;
  332. }
  333. if (!(channel->reg[0] & apu_Triangle_Halt)) {
  334. channel->reload = 0;
  335. }
  336. }
  337. nes_apu_Result nes_apu_run(nes_apu* apu, int cycles) {
  338. nes_apu_run_dmc(apu, &apu->channels[apu_Channel_DMC], cycles);
  339. while (cycles > 0) {
  340. int run = cycles;
  341. if (run > apu->frame_delay) {
  342. run = apu->frame_delay;
  343. }
  344. /*
  345. nes_apu_run_square(&apu->channels[apu_Channel_Square_0],
  346. apu->blip, run);
  347. nes_apu_run_square(&apu->channels[apu_Channel_Square_1],
  348. apu->blip, run);
  349. */
  350. nes_apu_run_triangle(
  351. apu, &apu->channels[apu_Channel_Triangle], run
  352. );
  353. nes_apu_run_noise(
  354. apu, &apu->channels[apu_Channel_Noise], run
  355. );
  356. apu->frame_delay -= run;
  357. if (apu->frame_delay <= 0) {
  358. int end = 0;
  359. int clock = 1;
  360. int half_clock = 0;
  361. apu->frame_delay += apu->frame_period;
  362. if (1 == apu->frame) {
  363. half_clock = 1;
  364. }
  365. if (apu->frame_reg & apu_Frame_Mode) {
  366. if (3 == apu->frame) {
  367. clock = 0;
  368. } else if (4 == apu->frame) {
  369. half_clock = 1;
  370. end = 1;
  371. }
  372. } else {
  373. if (3 == apu->frame) {
  374. half_clock = 1;
  375. end = 1;
  376. }
  377. }
  378. if (half_clock) {
  379. /*
  380. nes_apu_clock_length(&apu->channels[apu_Channel_Square_0], apu_Envelope_Halt);
  381. nes_apu_clock_length(&apu->channels[apu_Channel_Square_1], apu_Envelope_Halt);
  382. */
  383. nes_apu_clock_length(&apu->channels[apu_Channel_Triangle], apu_Triangle_Halt);
  384. nes_apu_clock_length(&apu->channels[apu_Channel_Noise], apu_Envelope_Halt);
  385. /*
  386. nes_apu_clock_sweep(&apu->channels[apu_Channel_Square_0], -1);
  387. nes_apu_clock_sweep(&apu->channels[apu_Channel_Square_1], 0);
  388. */
  389. }
  390. if (clock) {
  391. /*
  392. nes_apu_clock_envelope(&apu->channels[apu_Channel_Square_0]);
  393. nes_apu_clock_envelope(&apu->channels[apu_Channel_Square_1]);
  394. */
  395. nes_apu_clock_envelope(&apu->channels[apu_Channel_Noise]);
  396. nes_apu_clock_linear(&apu->channels[apu_Channel_Triangle]);
  397. }
  398. if (end) {
  399. apu->frame = 0;
  400. if (0 == apu->frame_reg) {
  401. apu->status |= apu_Status_Frame_Int;
  402. }
  403. } else {
  404. apu->frame++;
  405. }
  406. }
  407. cycles -= run;
  408. apu->time += run;
  409. }
  410. return ( (apu->status & apu_Status_Frame_Int) ||
  411. apu->channels[apu_Channel_DMC].interrupt ) ?
  412. apu_Result_IRQ : apu_Result_Running;
  413. }
  414. #endif // APU_H_