annotate pico_pcm.c @ 2435:b8d894f7f9dc

Fix playback of ADPCM blocks with an odd number of samples
author Michael Pavone <pavone@retrodev.com>
date Thu, 08 Feb 2024 21:05:49 -0800
parents 2ee25a487e2b
children f50b9ed42ebd
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
1 #include "pico_pcm.h"
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
2 #include "backend.h"
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
3
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
4 #define PCM_RESET 0x8000
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
5 #define PCM_INT_EN 0x4000
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
6 #define PCM_ENABLED 0x0800
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
7 #define PCM_FILTER 0x00C0
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
8 #define PCM_VOLUME 0x0007
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
9
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
10 void pico_pcm_reset(pico_pcm *pcm)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
11 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
12 pcm->fifo_read = sizeof(pcm->fifo);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
13 pcm->fifo_write = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
14 pcm->adpcm_state = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
15 pcm->output = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
16 pcm->nibble_store = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
17 pcm->counter = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
18 pcm->samples = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
19 pcm->rate = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
20 pcm->ctrl &= 0x7FFF;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
21 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
22
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
23 void pico_pcm_init(pico_pcm *pcm, uint32_t master_clock, uint32_t divider)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
24 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
25 pcm->audio = render_audio_source("PICO ADPCM", master_clock, divider * 4, 1);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
26 pcm->scope = NULL;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
27 pcm->scope_channel = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
28 pcm->clock_inc = divider * 4;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
29 pico_pcm_reset(pcm);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
30 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
31
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
32 void pico_pcm_free(pico_pcm *pcm)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
33 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
34 render_free_source(pcm->audio);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
35 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
36
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
37 void pico_pcm_enable_scope(pico_pcm *pcm, oscilloscope *scope, uint32_t master_clock)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
38 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
39 #ifndef IS_LIB
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
40 pcm->scope = scope;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
41 pcm->scope_channel = scope_add_channel(scope, "PICO ADPCM", master_clock / pcm->clock_inc);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
42 #endif
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
43 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
44
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
45 static uint8_t pcm_fifo_read(pico_pcm *pcm)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
46 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
47 if (pcm->fifo_read == sizeof(pcm->fifo)) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
48 return 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
49 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
50 uint8_t ret = pcm->fifo[pcm->fifo_read++];
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
51 pcm->fifo_read &= sizeof(pcm->fifo) - 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
52 if (pcm->fifo_read == pcm->fifo_write) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
53 pcm->fifo_read = sizeof(pcm->fifo);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
54 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
55 return ret;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
56 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
57
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
58 int16_t upd7755_calc_sample(uint8_t sample, uint8_t *state)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
59 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
60 //Tables from MAME
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
61 static const int16_t sample_delta[256] = {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
62 0, 0, 1, 2, 3, 5, 7, 10, 0, 0, -1, -2, -3, -5, -7, -10,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
63 0, 1, 2, 3, 4, 6, 8, 13, 0, -1, -2, -3, -4, -6, -8, -13,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
64 0, 1, 2, 4, 5, 7, 10, 15, 0, -1, -2, -4, -5, -7, -10, -15,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
65 0, 1, 3, 4, 6, 9, 13, 19, 0, -1, -3, -4, -6, -9, -13, -19,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
66 0, 2, 3, 5, 8, 11, 15, 23, 0, -2, -3, -5, -8, -11, -15, -23,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
67 0, 2, 4, 7, 10, 14, 19, 29, 0, -2, -4, -7, -10, -14, -19, -29,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
68 0, 3, 5, 8, 12, 16, 22, 33, 0, -3, -5, -8, -12, -16, -22, -33,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
69 1, 4, 7, 10, 15, 20, 29, 43, -1, -4, -7, -10, -15, -20, -29, -43,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
70 1, 4, 8, 13, 18, 25, 35, 53, -1, -4, -8, -13, -18, -25, -35, -53,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
71 1, 6, 10, 16, 22, 31, 43, 64, -1, -6, -10, -16, -22, -31, -43, -64,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
72 2, 7, 12, 19, 27, 37, 51, 76, -2, -7, -12, -19, -27, -37, -51, -76,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
73 2, 9, 16, 24, 34, 46, 64, 96, -2, -9, -16, -24, -34, -46, -64, -96,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
74 3, 11, 19, 29, 41, 57, 79, 117, -3, -11, -19, -29, -41, -57, -79, -117,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
75 4, 13, 24, 36, 50, 69, 96, 143, -4, -13, -24, -36, -50, -69, -96, -143,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
76 4, 16, 29, 44, 62, 85, 118, 175, -4, -16, -29, -44, -62, -85, -118, -175,
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
77 6, 20, 36, 54, 76, 104, 144, 214, -6, -20, -36, -54, -76, -104, -144, -214
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
78 };
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
79 static const int state_delta[16] = {-1, -1, 0, 0, 1, 2, 2, 3, -1, -1, 0, 0, 1, 2, 2, 3};
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
80 int16_t ret = sample_delta[(*state << 4) + sample];
2432
18816c5c11d4 Fix Pico ADPCM decoding and get relative volume approximately correct
Michael Pavone <pavone@retrodev.com>
parents: 2431
diff changeset
81 int diff = state_delta[sample];
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
82 if (diff >= 0 || *state > 0) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
83 *state += diff;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
84 if (*state > 15) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
85 *state = 15;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
86 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
87 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
88 return ret;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
89 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
90
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
91 void pico_pcm_run(pico_pcm *pcm, uint32_t cycle)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
92 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
93 while (pcm->cycle < cycle)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
94 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
95 pcm->cycle += pcm->clock_inc;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
96 //TODO: Figure out actual attenuation
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
97 int16_t shift = pcm->ctrl & PCM_VOLUME;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
98 #ifndef IS_LIB
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
99 if (pcm->scope) {
2432
18816c5c11d4 Fix Pico ADPCM decoding and get relative volume approximately correct
Michael Pavone <pavone@retrodev.com>
parents: 2431
diff changeset
100 scope_add_sample(pcm->scope, pcm->scope_channel, (pcm->output >> shift) * 32, 0);
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
101 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
102 #endif
2432
18816c5c11d4 Fix Pico ADPCM decoding and get relative volume approximately correct
Michael Pavone <pavone@retrodev.com>
parents: 2431
diff changeset
103 render_put_mono_sample(pcm->audio, (pcm->output >> shift) * 32);
2434
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
104 if (pcm->ctrl & PCM_RESET) {
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
105 //Anpanman Pico: Waku Waku Pan Koujou seems to expect the BUSY/RESET flag
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
106 //to be set for a while after reset
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
107 if (pcm->counter) {
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
108 pcm->counter--;
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
109 continue;
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
110 } else {
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
111 pcm->ctrl &= ~PCM_RESET;
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
112 }
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
113 }
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
114 /*
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
115 Unclear what this bit is actually supposed to do
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
116 But some games expect ADPCM to work with it cleared
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
117 Anpanman Pico: Waku Waku Pan Koujou sets the ctrl reg to $6040
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
118 if (!(pcm->ctrl & PCM_ENABLED)) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
119 continue;
2434
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
120 }*/
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
121 if (pcm->counter) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
122 pcm->counter--;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
123 } else if (pcm->samples) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
124 pcm->samples--;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
125 uint8_t sample;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
126 if (pcm->nibble_store) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
127 sample = pcm->nibble_store & 0xF;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
128 pcm->nibble_store = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
129 } else {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
130 uint8_t byte = pcm_fifo_read(pcm);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
131 sample = byte >> 4;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
132 pcm->nibble_store = 0x80 | (byte & 0xF);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
133 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
134 uint8_t old_state = pcm->adpcm_state;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
135 pcm->output += upd7755_calc_sample(sample, &pcm->adpcm_state);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
136 if (pcm->output > 255) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
137 pcm->output = 255;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
138 } else if (pcm->output < -256) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
139 pcm->output = -256;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
140 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
141 //printf("Sample %d, old_state %d, new_state %d, output %d\n", sample, old_state, pcm->adpcm_state, pcm->output);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
142 pcm->counter = pcm->rate;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
143 } else {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
144 uint8_t cmd = pcm_fifo_read(pcm);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
145 if (cmd) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
146 pcm->ctrl |= 0x8000;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
147 } else {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
148 pcm->ctrl &= 0x7FFF;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
149 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
150 switch (cmd & 0xC0)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
151 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
152 case 0:
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
153 pcm->output = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
154 pcm->adpcm_state = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
155 pcm->counter = (cmd & 0x3F) * 160;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
156 break;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
157 case 0x40:
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
158 pcm->rate = (cmd & 0x3F);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
159 pcm->samples = 256;
2435
b8d894f7f9dc Fix playback of ADPCM blocks with an odd number of samples
Michael Pavone <pavone@retrodev.com>
parents: 2434
diff changeset
160 pcm->nibble_store = 0;
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
161 break;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
162 case 0x80:
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
163 pcm->rate = (cmd & 0x3F);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
164 //FIXME: this probably does not happen instantly
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
165 pcm->samples = pcm_fifo_read(pcm) + 1;
2435
b8d894f7f9dc Fix playback of ADPCM blocks with an odd number of samples
Michael Pavone <pavone@retrodev.com>
parents: 2434
diff changeset
166 pcm->nibble_store = 0;
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
167 break;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
168 case 0xC0:
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
169 //FIXME: this probably does not happen instantly
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
170 //TODO: Does repeat mode even work on this chip?
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
171 // Does it work on a uPD7759 in slave mode?
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
172 // Is this correct behavior if it does work?
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
173 pcm->counter = pcm->rate = pcm_fifo_read(pcm) & 0x3F;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
174 pcm->samples = (pcm_fifo_read(pcm) + 1) * ((cmd & 7) + 1);
2435
b8d894f7f9dc Fix playback of ADPCM blocks with an odd number of samples
Michael Pavone <pavone@retrodev.com>
parents: 2434
diff changeset
175 pcm->nibble_store = 0;
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
176 break;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
177 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
178 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
179 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
180 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
181
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
182 // RI??E???FF???VVV
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
183 // R: 1 = Reset request, 0 = normal operation
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
184 // I: 1 = interrupts enabled, 0 = disabled
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
185 // E: 1 = Enabled? Sega code always sets this to 1 outside of reset
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
186 // F: Low-pass Filter 1 = 6 kHz, 2 = 12 kHz 3 = 16 kHz
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
187 // V: volume, probably attenuation value since converter defaults to "0"
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
188 void pico_pcm_ctrl_write(pico_pcm *pcm, uint16_t value)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
189 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
190 if (value & PCM_RESET) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
191 pico_pcm_reset(pcm);
2434
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
192 pcm->counter = 2;
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
193 }
2434
2ee25a487e2b Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents: 2432
diff changeset
194 pcm->ctrl = value;
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
195 //TODO: update low-pass filter
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
196 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
197
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
198 void pico_pcm_data_write(pico_pcm *pcm, uint16_t value)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
199 {
2435
b8d894f7f9dc Fix playback of ADPCM blocks with an odd number of samples
Michael Pavone <pavone@retrodev.com>
parents: 2434
diff changeset
200 if (pcm->fifo_read == pcm->fifo_write) {
b8d894f7f9dc Fix playback of ADPCM blocks with an odd number of samples
Michael Pavone <pavone@retrodev.com>
parents: 2434
diff changeset
201 puts("ADPCM fifo overflow");
b8d894f7f9dc Fix playback of ADPCM blocks with an odd number of samples
Michael Pavone <pavone@retrodev.com>
parents: 2434
diff changeset
202 }
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
203 if (pcm->fifo_read == sizeof(pcm->fifo)) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
204 pcm->fifo_read = pcm->fifo_write;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
205 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
206 pcm->fifo[pcm->fifo_write++] = value >> 8;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
207 pcm->fifo_write &= sizeof(pcm->fifo)-1;
2435
b8d894f7f9dc Fix playback of ADPCM blocks with an odd number of samples
Michael Pavone <pavone@retrodev.com>
parents: 2434
diff changeset
208 if (pcm->fifo_read == pcm->fifo_write) {
b8d894f7f9dc Fix playback of ADPCM blocks with an odd number of samples
Michael Pavone <pavone@retrodev.com>
parents: 2434
diff changeset
209 puts("ADPCM fifo overflow");
b8d894f7f9dc Fix playback of ADPCM blocks with an odd number of samples
Michael Pavone <pavone@retrodev.com>
parents: 2434
diff changeset
210 }
2431
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
211 pcm->fifo[pcm->fifo_write++] = value;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
212 pcm->fifo_write &= sizeof(pcm->fifo)-1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
213 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
214
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
215 uint16_t pico_pcm_ctrl_read(pico_pcm *pcm)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
216 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
217 return pcm->ctrl;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
218 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
219
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
220 uint16_t pico_pcm_data_read(pico_pcm *pcm)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
221 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
222 if (pcm->fifo_read == sizeof(pcm->fifo)) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
223 return sizeof(pcm->fifo) - 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
224 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
225 return (pcm->fifo_read - pcm->fifo_write) & (sizeof(pcm->fifo)-1);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
226 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
227
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
228 #define FIFO_THRESHOLD 48
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
229 uint32_t pico_pcm_next_int(pico_pcm *pcm)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
230 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
231 if (!(pcm->ctrl & PCM_INT_EN)) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
232 return CYCLE_NEVER;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
233 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
234 uint32_t fifo_bytes;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
235 if (pcm->fifo_read == sizeof(pcm->fifo)) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
236 fifo_bytes = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
237 } else if (pcm->fifo_read == pcm->fifo_write) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
238 fifo_bytes = sizeof(pcm->fifo);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
239 } else {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
240 fifo_bytes = (pcm->fifo_write - pcm->fifo_read) & (sizeof(pcm->fifo) - 1);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
241 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
242 if (fifo_bytes < FIFO_THRESHOLD) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
243 return pcm->cycle;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
244 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
245 uint32_t cycles_to_threshold = pcm->counter + 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
246 if (pcm->samples) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
247 uint16_t samples = pcm->samples;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
248 if (pcm->nibble_store) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
249 cycles_to_threshold += pcm->rate + 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
250 samples--;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
251 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
252 uint16_t bytes = (samples >> 1) + (samples & 1);
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
253 if (bytes > (fifo_bytes - FIFO_THRESHOLD)) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
254 cycles_to_threshold += (fifo_bytes - FIFO_THRESHOLD + 1) * (pcm->rate + 1) * 2;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
255 fifo_bytes = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
256 } else {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
257 cycles_to_threshold += bytes * (pcm->rate + 1) * 2;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
258 fifo_bytes -= bytes;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
259 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
260 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
261 uint8_t fifo_read = pcm->fifo_read;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
262 uint8_t cmd = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
263 while (fifo_bytes >= FIFO_THRESHOLD)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
264 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
265 if (cmd) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
266 switch(cmd & 0xC0)
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
267 {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
268 case 0:
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
269 cycles_to_threshold += 640 * (cmd & 0x3F) + 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
270 break;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
271 case 0x40:
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
272 cycles_to_threshold += (fifo_bytes - FIFO_THRESHOLD + 1) * ((cmd & 0x3F) + 1) * 2;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
273 fifo_bytes = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
274 break;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
275 case 0x80: {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
276 uint32_t samples = pcm->fifo[fifo_read++];
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
277 fifo_bytes--;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
278 fifo_read &= sizeof(pcm->fifo) - 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
279 if (fifo_bytes < FIFO_THRESHOLD) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
280 break;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
281 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
282 uint32_t bytes = (samples +1) >> 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
283 if (bytes > (fifo_bytes - FIFO_THRESHOLD)) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
284 cycles_to_threshold += (fifo_bytes - FIFO_THRESHOLD + 1) * ((cmd & 0x3F) + 1) * 2;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
285 fifo_bytes = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
286 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
287 break; }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
288 case 0xC0: {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
289 uint32_t rate = pcm->fifo[fifo_read++] & 0x3F;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
290 fifo_bytes--;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
291 fifo_read &= sizeof(pcm->fifo) - 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
292 uint32_t samples = pcm->fifo[fifo_read++] & 0x3F;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
293 fifo_bytes--;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
294 fifo_read &= sizeof(pcm->fifo) - 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
295 if (fifo_bytes < FIFO_THRESHOLD) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
296 break;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
297 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
298 samples++;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
299 samples *= (cmd & 7) + 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
300 uint32_t bytes = (samples + 1) >> 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
301 if (bytes > (fifo_bytes - FIFO_THRESHOLD)) {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
302 cycles_to_threshold += (fifo_bytes - FIFO_THRESHOLD + 1) * ((cmd & 0x3F) + 1) * 2;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
303 fifo_bytes = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
304 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
305 break; }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
306 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
307 cmd = 0;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
308 } else {
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
309 cycles_to_threshold++;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
310 cmd = pcm->fifo[fifo_read++];
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
311 fifo_bytes--;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
312 fifo_read &= sizeof(pcm->fifo) - 1;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
313 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
314 }
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
315
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
316 return pcm->cycle + cycles_to_threshold * pcm->clock_inc;
61c0bfe10887 Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
317 }