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.

646 line
19KB

  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 inline int apu_channel_raw_timer_value(
  49. nes_apu_Channel *channel) {
  50. return ( channel->reg[2] |
  51. (((uint16_t)channel->reg[3] & 0x7U) << 8));
  52. }
  53. static inline void apu_channel_update_timer(
  54. nes_apu_Channel *channel) {
  55. channel->period = apu_channel_raw_timer_value(channel) *
  56. nes_clock_cpu_div;
  57. }
  58. static void nes_apu_write_square(nes_apu_Channel* channel,
  59. int reg, uint8_t val) {
  60. APU_LOG("APU: Square %d < %02x\n", reg, val);
  61. if (0 == reg) {
  62. channel->env_period = (val & apu_Envelope_Volume);
  63. } else if (1 == reg) {
  64. channel->sweep_period = (
  65. ((val & apu_Square_Period) >> 4)
  66. );
  67. channel->flags |= apu_Channel_Reload;
  68. } else if (2 <= reg) {
  69. channel->reg[reg] = val;
  70. channel->period = (
  71. (apu_channel_raw_timer_value(channel) /*+ 1*/) * 2
  72. ) * nes_clock_cpu_div;
  73. if (3 == reg) {
  74. // channel->flags |= apu_Channel_Reload;
  75. channel->delay = 0;
  76. // Envelope and step are already restarted
  77. }
  78. }
  79. }
  80. static void nes_apu_write_triangle(nes_apu_Channel* channel,
  81. int reg, uint8_t val) {
  82. APU_LOG("APU: Triangle %d < %02x\n", reg, val);
  83. if (2 <= reg) {
  84. channel->reg[reg] = val;
  85. apu_channel_update_timer(channel);
  86. if (3 == reg) channel->flags |= apu_Channel_Reload;
  87. }
  88. }
  89. static void nes_apu_write_noise(nes_apu_Channel* channel,
  90. int reg, uint8_t val) {
  91. APU_LOG("APU: Noise %d < %02x\n", reg, val);
  92. if (reg == 0) {
  93. channel->env_period = (val & apu_Envelope_Volume);
  94. } else if (reg == 2) {
  95. channel->period = noise_period_lut[val & apu_Noise_Period] *
  96. nes_clock_cpu_div;
  97. }
  98. }
  99. static void nes_apu_write_dmc(nes_apu_Channel* channel,
  100. int reg, uint8_t val) {
  101. APU_LOG("APU: DMC %d < %02x\n", reg, val);
  102. if (reg == 0) {
  103. channel->period = dmc_period_lut[val & apu_DMC_Period] *
  104. nes_clock_cpu_div;
  105. if (!(val & apu_DMC_IRQ_Enable)) {
  106. channel->interrupt = 0;
  107. }
  108. } else if (reg == 1) {
  109. channel->sample = (val & 0x7FU);
  110. }
  111. }
  112. int nes_apu_init(nes_apu* apu, int clock, int frequency,
  113. uint8_t(*mem_read)(void*, uint16_t),
  114. void* arg_mem) {
  115. int ret = 0;
  116. // 20 ms buffer
  117. apu->blip = blip_new(frequency / 50);
  118. if (NULL == apu->blip) {
  119. APU_ERR("APU: Failed to create resampler\n");
  120. ret = -1;
  121. } else {
  122. blip_set_rates(apu->blip, clock, frequency);
  123. nes_apu_reset(apu);
  124. apu->mem_read = mem_read;
  125. apu->arg_mem = arg_mem;
  126. apu->channels[apu_Channel_Square_0].write = nes_apu_write_square;
  127. apu->channels[apu_Channel_Square_1].write = nes_apu_write_square;
  128. apu->channels[apu_Channel_Triangle].write = nes_apu_write_triangle;
  129. apu->channels[apu_Channel_Noise].write = nes_apu_write_noise;
  130. apu->channels[apu_Channel_DMC].write = nes_apu_write_dmc;
  131. apu->channels[apu_Channel_Square_0].gain = apu_gain_square;
  132. apu->channels[apu_Channel_Square_1].gain = apu_gain_square;
  133. apu->channels[apu_Channel_Triangle].gain = apu_gain_triangle;
  134. apu->channels[apu_Channel_Noise].gain = apu_gain_noise;
  135. apu->channels[apu_Channel_DMC].gain = apu_gain_dmc;
  136. apu->channels[apu_Channel_Noise].lfsr = 0x7FFFU;
  137. apu->frame_period = (clock / 240) +
  138. (nes_clock_cpu_div / 2);
  139. apu->frame_delay = apu->frame_period;
  140. }
  141. return ret;
  142. }
  143. void nes_apu_done(nes_apu* apu) {
  144. blip_delete(apu->blip);
  145. }
  146. void nes_apu_reset(nes_apu* apu) {
  147. apu->status = 0;
  148. for (int chan = 0; chan < nes_apu_chan_count; ++chan) {
  149. apu->channels[chan].length = 0;
  150. }
  151. apu->channels[apu_Channel_Triangle].step = 31;
  152. apu->channels[apu_Channel_DMC].reg[1] &= 1;
  153. apu->channels[apu_Channel_DMC].sample = 0;
  154. apu->channels[apu_Channel_DMC].mask = 0;
  155. }
  156. uint8_t nes_apu_read(nes_apu* apu, uint16_t addr) {
  157. uint8_t val = 0;
  158. if (addr == nes_apu_reg_status) {
  159. for (int chan = 0; chan < nes_apu_chan_count; ++chan) {
  160. if (apu->channels[chan].length > 0) {
  161. val |= (1 << chan);
  162. }
  163. }
  164. if (apu->channels[apu_Channel_DMC].interrupt) {
  165. val |= apu_Status_DMC_Int;
  166. }
  167. if (apu->status & apu_Status_Frame_Int) {
  168. val |= apu_Status_Frame_Int;
  169. apu->status &= ~apu_Status_Frame_Int;
  170. }
  171. APU_LOG("APU: Status %02x @ %d\n", val, apu->frame_time_elapsed);
  172. }
  173. return val;
  174. }
  175. static inline void nes_apu_clock_length(nes_apu_Channel* channel,
  176. uint8_t halt_mask) {
  177. if ( channel->length > 0 &&
  178. !(channel->reg[0] & halt_mask)) {
  179. channel->length--;
  180. APU_LOG("APU: Clock Length %p -> %d\n", channel, channel->length);
  181. }
  182. }
  183. static inline void nes_apu_clock_sweep(nes_apu_Channel* channel,
  184. int adjust) {
  185. int decrement = 1;
  186. if (channel->flags & apu_Channel_Reload) {
  187. channel->flags &= ~apu_Channel_Reload;
  188. decrement = 0;
  189. }
  190. if (channel->sweep_delay == 0) {
  191. decrement = 0;
  192. if (channel->period < 8 * nes_clock_cpu_div) {
  193. channel->period = 0;
  194. channel->length = 0;
  195. } else if ( (channel->reg[1] & apu_Square_Enable) &&
  196. 0 != (channel->reg[1] & apu_Square_Shift)) {
  197. int delta = (
  198. apu_channel_raw_timer_value(channel) >>
  199. (channel->reg[1] & apu_Square_Shift)
  200. );
  201. if (channel->reg[1] & apu_Square_Negate) {
  202. delta = adjust - delta;
  203. }
  204. channel->period += delta * nes_clock_apu_div;
  205. if ( channel < 0 ||
  206. channel->period > 0x7FFU * nes_clock_cpu_div) {
  207. channel->period = 0;
  208. channel->length = 0;
  209. }
  210. }
  211. }
  212. if (decrement) {
  213. channel->sweep_delay--;
  214. } else {
  215. channel->sweep_delay = channel->sweep_period;
  216. }
  217. }
  218. static inline void nes_apu_clock_envelope(nes_apu_Channel* channel) {
  219. if (channel->flags & apu_Channel_Start) {
  220. channel->flags &= ~apu_Channel_Start;
  221. channel->envelope = 15;
  222. channel->env_delay = channel->env_period;
  223. } else if (channel->env_delay <= 0) {
  224. channel->env_delay = channel->env_period;
  225. if ( channel->envelope > 0 ||
  226. (channel->reg[0] & apu_Envelope_Halt)) {
  227. channel->envelope = ((channel->envelope - 1) & 0xFU);
  228. }
  229. } else {
  230. channel->env_delay--;
  231. }
  232. }
  233. static inline void nes_apu_clock_linear(nes_apu_Channel* channel) {
  234. if (channel->flags & apu_Channel_Reload) {
  235. channel->counter = (channel->reg[0] & apu_Triangle_Count);
  236. } else if (channel->counter > 0) {
  237. channel->counter--;
  238. }
  239. if (!(channel->reg[0] & apu_Triangle_Halt)) {
  240. channel->flags &= ~apu_Channel_Reload;
  241. }
  242. }
  243. static void nes_apu_clock_quarter_frame(nes_apu* apu) {
  244. nes_apu_clock_envelope(&apu->channels[apu_Channel_Square_0]);
  245. nes_apu_clock_envelope(&apu->channels[apu_Channel_Square_1]);
  246. nes_apu_clock_envelope(&apu->channels[apu_Channel_Noise]);
  247. nes_apu_clock_linear(&apu->channels[apu_Channel_Triangle]);
  248. }
  249. static void nes_apu_clock_half_frame(nes_apu* apu) {
  250. nes_apu_clock_length(&apu->channels[apu_Channel_Square_0], apu_Envelope_Halt);
  251. nes_apu_clock_length(&apu->channels[apu_Channel_Square_1], apu_Envelope_Halt);
  252. nes_apu_clock_length(&apu->channels[apu_Channel_Triangle], apu_Triangle_Halt);
  253. nes_apu_clock_length(&apu->channels[apu_Channel_Noise], apu_Envelope_Halt);
  254. nes_apu_clock_sweep(&apu->channels[apu_Channel_Square_0], -1);
  255. nes_apu_clock_sweep(&apu->channels[apu_Channel_Square_1], 0);
  256. }
  257. void nes_apu_write(nes_apu* apu, uint16_t addr, uint8_t val) {
  258. if (addr < nes_apu_reg_base +
  259. (nes_apu_chan_count * nes_apu_chan_size)) {
  260. int chan = (addr - nes_apu_reg_base) / nes_apu_chan_size;
  261. int reg = (addr - nes_apu_reg_base) % nes_apu_chan_size;
  262. nes_apu_Channel* channel = &apu->channels[chan];
  263. if (3 == reg) {
  264. if ( chan != apu_Channel_DMC &&
  265. (apu->status & (1 << chan))) {
  266. channel->length = apu_length_lut[val >> 3];
  267. channel->step = (uint8_t)-1;
  268. channel->flags |= apu_Channel_Start;
  269. }
  270. }
  271. channel->write(channel, reg, val);
  272. channel->reg[reg] = val;
  273. } else if (addr == nes_apu_reg_status) {
  274. APU_LOG("APU: Enable %02x\n", val);
  275. // Clear this now in case nes_apu_dmc_start resets it
  276. apu->channels[apu_Channel_DMC].interrupt = 0;
  277. for (int chan = 0; chan < nes_apu_chan_count; ++chan) {
  278. if (!(val & (1 << chan))) {
  279. apu->channels[chan].length = 0;
  280. }
  281. }
  282. if (!(val & (1 << apu_Channel_DMC))) {
  283. apu->channels[apu_Channel_DMC].mask = 0;
  284. } else if ( (val & (1 << apu_Channel_DMC)) &&
  285. apu->channels[apu_Channel_DMC].length <= 0) {
  286. nes_apu_dmc_start(apu,
  287. &apu->channels[apu_Channel_DMC]);
  288. }
  289. apu->status &= ~((1 << nes_apu_chan_count) - 1);
  290. apu->status |= (val & ((1 << nes_apu_chan_count) - 1));
  291. } else if (addr == nes_apu_reg_frame) {
  292. APU_LOG("APU: Frame %02x\n", val);
  293. apu->frame_reg = val &
  294. (apu_Frame_Mode | apu_Frame_Inhibit);
  295. apu->frame = 0;
  296. apu->frame_time_elapsed = 0;
  297. apu->frame_delay = apu->frame_period;
  298. if (val & apu_Frame_Mode) {
  299. nes_apu_clock_quarter_frame(apu);
  300. nes_apu_clock_half_frame(apu);
  301. }
  302. if (val & apu_Frame_Inhibit) {
  303. apu->status &= ~apu_Status_Frame_Int;
  304. }
  305. }
  306. }
  307. static int channel_update(nes_apu_Channel* channel) {
  308. int output = (channel->gain * channel->sample);
  309. int delta = output - channel->output;
  310. channel->output = output;
  311. return delta;
  312. }
  313. static void nes_apu_run_dmc(nes_apu* apu,
  314. nes_apu_Channel* channel,
  315. int cycles) {
  316. if (channel->length <= 0 || channel->period <= 0) return;
  317. int time = apu->time;
  318. int delta = channel_update(channel);
  319. if (delta) {
  320. blip_add_delta(apu->blip, time, delta);
  321. }
  322. while (cycles > 0) {
  323. int run = cycles;
  324. if (run > channel->delay) {
  325. run = channel->delay;
  326. }
  327. channel->delay -= run;
  328. time += run;
  329. if (channel->delay <= 0) {
  330. channel->delay = channel->period;
  331. delta = (channel->mask & channel->data) ? 2 : -2;
  332. int sample = channel->sample + delta;
  333. if ((unsigned)sample <= 0x7FU) {
  334. channel->sample = sample;
  335. delta = channel_update(channel);
  336. if (delta) {
  337. blip_add_delta(apu->blip, time, delta);
  338. }
  339. }
  340. channel->mask <<= 1;
  341. if (!channel->mask) {
  342. nes_apu_dmc_fetch(apu, channel);
  343. }
  344. }
  345. cycles -= run;
  346. }
  347. }
  348. static inline int apu_envelope_volume(nes_apu_Channel* channel) {
  349. return ( (channel->reg[0] & apu_Envelope_Constant) ?
  350. (channel->reg[0] & apu_Envelope_Volume) :
  351. channel->envelope );
  352. }
  353. static void nes_apu_run_noise(nes_apu* apu,
  354. nes_apu_Channel* channel,
  355. int cycles) {
  356. if (channel->length <= 0 || channel->period <= 0) return;
  357. int time = apu->time;
  358. while (cycles > 0) {
  359. int run = cycles;
  360. if (run > channel->delay) {
  361. run = channel->delay;
  362. }
  363. channel->delay -= run;
  364. time += run;
  365. if (channel->delay <= 0) {
  366. channel->delay = channel->period;
  367. uint16_t feedback = (1 & (channel->lfsr ^ (
  368. channel->lfsr >> (
  369. (channel->reg[2] & apu_Noise_Mode) ?
  370. 6 : 1
  371. )
  372. )
  373. ));
  374. channel->lfsr = (feedback << 14) |
  375. (channel->lfsr >> 1);
  376. channel->sample = (channel->lfsr & 1) ?
  377. apu_envelope_volume(channel) : 0;
  378. int delta = channel_update(channel);
  379. if (delta) {
  380. blip_add_delta(apu->blip, time, delta);
  381. }
  382. }
  383. cycles -= run;
  384. }
  385. }
  386. static uint8_t triangle_steps[32] = {
  387. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
  388. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  389. };
  390. static void nes_apu_run_triangle(nes_apu* apu,
  391. nes_apu_Channel* channel,
  392. int cycles) {
  393. if ( channel->length <= 0 ||
  394. channel->period <= 0 ||
  395. channel->counter <= 0) {
  396. return;
  397. }
  398. int time = apu->time;
  399. while (cycles > 0) {
  400. int run = cycles;
  401. if (run > channel->delay) {
  402. run = channel->delay;
  403. }
  404. channel->delay -= run;
  405. time += run;
  406. if (channel->delay <= 0) {
  407. channel->delay = channel->period;
  408. channel->step = ((channel->step + 1) & 31U);
  409. channel->sample = triangle_steps[channel->step];
  410. int delta = channel_update(channel);
  411. if (delta) {
  412. blip_add_delta(apu->blip, time, delta);
  413. }
  414. }
  415. cycles -= run;
  416. }
  417. }
  418. static const uint8_t square_sequence[4] = {
  419. 0b00000010,
  420. 0b00000110,
  421. 0b00011110,
  422. 0b11111001,
  423. };
  424. static void nes_apu_run_square(nes_apu* apu,
  425. nes_apu_Channel* channel,
  426. int cycles) {
  427. if ( channel->length <= 0 ||
  428. channel->period <= 0) {
  429. return;
  430. }
  431. int time = apu->time;
  432. while (cycles > 0) {
  433. int run = cycles;
  434. if (run > channel->delay) {
  435. run = channel->delay;
  436. }
  437. channel->delay -= run;
  438. time += run;
  439. if (channel->delay <= 0) {
  440. channel->delay = channel->period;
  441. channel->step = ((channel->step + 1) & 7U);
  442. channel->sample = ((
  443. square_sequence[channel->reg[0] >> 6] &
  444. (1 << channel->step)
  445. ) ? apu_envelope_volume(channel) : 0);
  446. int delta = channel_update(channel);
  447. if (delta) {
  448. blip_add_delta(apu->blip, time, delta);
  449. }
  450. }
  451. cycles -= run;
  452. }
  453. }
  454. nes_apu_Result nes_apu_run(nes_apu* apu, int cycles) {
  455. nes_apu_run_dmc(apu, &apu->channels[apu_Channel_DMC], cycles);
  456. while (cycles > 0) {
  457. int run = cycles;
  458. if (run > apu->frame_delay) {
  459. run = apu->frame_delay;
  460. }
  461. apu->frame_time_elapsed += run;
  462. nes_apu_run_square(
  463. apu, &apu->channels[apu_Channel_Square_0], run
  464. );
  465. nes_apu_run_square(
  466. apu, &apu->channels[apu_Channel_Square_1], run
  467. );
  468. nes_apu_run_triangle(
  469. apu, &apu->channels[apu_Channel_Triangle], run
  470. );
  471. nes_apu_run_noise(
  472. apu, &apu->channels[apu_Channel_Noise], run
  473. );
  474. apu->frame_delay -= run;
  475. if (apu->frame_delay <= 0) {
  476. APU_LOG("APU: End of quarter frame: %d\n", apu->frame_time_elapsed);
  477. int end = 0;
  478. int quarter_frame = 1;
  479. int half_frame = 0;
  480. apu->frame_delay += apu->frame_period;
  481. if (1 == apu->frame) {
  482. half_frame = 1;
  483. }
  484. if (apu->frame_reg & apu_Frame_Mode) {
  485. if (3 == apu->frame) {
  486. quarter_frame = 0;
  487. } else if (4 <= apu->frame) {
  488. half_frame = 1;
  489. end = 1;
  490. }
  491. } else {
  492. if (3 <= apu->frame) {
  493. half_frame = 1;
  494. end = 1;
  495. }
  496. }
  497. if (half_frame) {
  498. nes_apu_clock_half_frame(apu);
  499. }
  500. if (quarter_frame) {
  501. nes_apu_clock_quarter_frame(apu);
  502. }
  503. if (end) {
  504. if (0 == apu->frame_reg) {
  505. apu->status |= apu_Status_Frame_Int;
  506. APU_LOG("APU: Frame Interrupt @ %d\n", apu->frame_time_elapsed);
  507. }
  508. apu->frame = 0;
  509. apu->frame_time_elapsed = 0;
  510. } else {
  511. apu->frame++;
  512. }
  513. }
  514. cycles -= run;
  515. apu->time += run;
  516. }
  517. return ( (apu->status & apu_Status_Frame_Int) ||
  518. apu->channels[apu_Channel_DMC].interrupt ) ?
  519. apu_Result_IRQ : apu_Result_Running;
  520. }
  521. #endif // APU_H_