Mercurial > repos > blastem
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 |
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 } |