Mercurial > repos > blastem
annotate pico_pcm.c @ 2476:aaf7bb58ffca
Fix bug in Gen/MD serialize routine that could cause a use-after free in some cases
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 03 Mar 2024 13:47:59 -0800 |
parents | f50b9ed42ebd |
children | e8eba0cd5444 |
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 |
2436
f50b9ed42ebd
Fix polarity of pico ADPCM busy flag
Michael Pavone <pavone@retrodev.com>
parents:
2435
diff
changeset
|
5 #define PCM_BUSY PCM_RESET |
2431
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
6 #define PCM_INT_EN 0x4000 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
7 #define PCM_ENABLED 0x0800 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
8 #define PCM_FILTER 0x00C0 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
9 #define PCM_VOLUME 0x0007 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
10 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
11 void pico_pcm_reset(pico_pcm *pcm) |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
12 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
13 pcm->fifo_read = sizeof(pcm->fifo); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
14 pcm->fifo_write = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
15 pcm->adpcm_state = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
16 pcm->output = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
17 pcm->nibble_store = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
18 pcm->counter = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
19 pcm->samples = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
20 pcm->rate = 0; |
2436
f50b9ed42ebd
Fix polarity of pico ADPCM busy flag
Michael Pavone <pavone@retrodev.com>
parents:
2435
diff
changeset
|
21 pcm->ctrl |= PCM_BUSY; |
2431
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 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
24 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
|
25 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
26 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
|
27 pcm->scope = NULL; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
28 pcm->scope_channel = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
29 pcm->clock_inc = divider * 4; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
30 pico_pcm_reset(pcm); |
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 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
33 void pico_pcm_free(pico_pcm *pcm) |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
34 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
35 render_free_source(pcm->audio); |
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 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
38 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
|
39 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
40 #ifndef IS_LIB |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
41 pcm->scope = scope; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
42 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
|
43 #endif |
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 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
46 static uint8_t pcm_fifo_read(pico_pcm *pcm) |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
47 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
48 if (pcm->fifo_read == sizeof(pcm->fifo)) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
49 return 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
50 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
51 uint8_t ret = pcm->fifo[pcm->fifo_read++]; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
52 pcm->fifo_read &= sizeof(pcm->fifo) - 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
53 if (pcm->fifo_read == pcm->fifo_write) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
54 pcm->fifo_read = sizeof(pcm->fifo); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
55 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
56 return ret; |
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 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
59 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
|
60 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
61 //Tables from MAME |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
62 static const int16_t sample_delta[256] = { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
63 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
|
64 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
|
65 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
|
66 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
|
67 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
|
68 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
|
69 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
|
70 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
|
71 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
|
72 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
|
73 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
|
74 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
|
75 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
|
76 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
|
77 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
|
78 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
|
79 }; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
80 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
|
81 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
|
82 int diff = state_delta[sample]; |
2431
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
83 if (diff >= 0 || *state > 0) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
84 *state += diff; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
85 if (*state > 15) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
86 *state = 15; |
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 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
89 return ret; |
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 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
92 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
|
93 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
94 while (pcm->cycle < cycle) |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
95 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
96 pcm->cycle += pcm->clock_inc; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
97 //TODO: Figure out actual attenuation |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
98 int16_t shift = pcm->ctrl & PCM_VOLUME; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
99 #ifndef IS_LIB |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
100 if (pcm->scope) { |
2432
18816c5c11d4
Fix Pico ADPCM decoding and get relative volume approximately correct
Michael Pavone <pavone@retrodev.com>
parents:
2431
diff
changeset
|
101 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
|
102 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
103 #endif |
2432
18816c5c11d4
Fix Pico ADPCM decoding and get relative volume approximately correct
Michael Pavone <pavone@retrodev.com>
parents:
2431
diff
changeset
|
104 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
|
105 /* |
2ee25a487e2b
Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents:
2432
diff
changeset
|
106 Unclear what this bit is actually supposed to do |
2ee25a487e2b
Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents:
2432
diff
changeset
|
107 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
|
108 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
|
109 if (!(pcm->ctrl & PCM_ENABLED)) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
110 continue; |
2434
2ee25a487e2b
Fix some Pico ADPCM behaviors
Michael Pavone <pavone@retrodev.com>
parents:
2432
diff
changeset
|
111 }*/ |
2431
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
112 if (pcm->counter) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
113 pcm->counter--; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
114 } else if (pcm->samples) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
115 pcm->samples--; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
116 uint8_t sample; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
117 if (pcm->nibble_store) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
118 sample = pcm->nibble_store & 0xF; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
119 pcm->nibble_store = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
120 } else { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
121 uint8_t byte = pcm_fifo_read(pcm); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
122 sample = byte >> 4; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
123 pcm->nibble_store = 0x80 | (byte & 0xF); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
124 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
125 uint8_t old_state = pcm->adpcm_state; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
126 pcm->output += upd7755_calc_sample(sample, &pcm->adpcm_state); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
127 if (pcm->output > 255) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
128 pcm->output = 255; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
129 } else if (pcm->output < -256) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
130 pcm->output = -256; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
131 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
132 //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
|
133 pcm->counter = pcm->rate; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
134 } else { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
135 uint8_t cmd = pcm_fifo_read(pcm); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
136 if (cmd) { |
2436
f50b9ed42ebd
Fix polarity of pico ADPCM busy flag
Michael Pavone <pavone@retrodev.com>
parents:
2435
diff
changeset
|
137 pcm->ctrl &= ~PCM_BUSY; |
2431
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
138 } else { |
2436
f50b9ed42ebd
Fix polarity of pico ADPCM busy flag
Michael Pavone <pavone@retrodev.com>
parents:
2435
diff
changeset
|
139 pcm->ctrl |= PCM_BUSY; |
2431
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 switch (cmd & 0xC0) |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
142 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
143 case 0: |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
144 pcm->output = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
145 pcm->adpcm_state = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
146 pcm->counter = (cmd & 0x3F) * 160; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
147 break; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
148 case 0x40: |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
149 pcm->rate = (cmd & 0x3F); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
150 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
|
151 pcm->nibble_store = 0; |
2431
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
152 break; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
153 case 0x80: |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
154 pcm->rate = (cmd & 0x3F); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
155 //FIXME: this probably does not happen instantly |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
156 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
|
157 pcm->nibble_store = 0; |
2431
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
158 break; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
159 case 0xC0: |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
160 //FIXME: this probably does not happen instantly |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
161 //TODO: Does repeat mode even work on this chip? |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
162 // Does it work on a uPD7759 in slave mode? |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
163 // Is this correct behavior if it does work? |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
164 pcm->counter = pcm->rate = pcm_fifo_read(pcm) & 0x3F; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
165 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
|
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 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
169 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
170 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
171 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
172 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
173 // RI??E???FF???VVV |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
174 // R: 1 = Reset request, 0 = normal operation |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
175 // I: 1 = interrupts enabled, 0 = disabled |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
176 // 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
|
177 // 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
|
178 // 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
|
179 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
|
180 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
181 if (value & PCM_RESET) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
182 pico_pcm_reset(pcm); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
183 } |
2436
f50b9ed42ebd
Fix polarity of pico ADPCM busy flag
Michael Pavone <pavone@retrodev.com>
parents:
2435
diff
changeset
|
184 pcm->ctrl &= PCM_BUSY; |
f50b9ed42ebd
Fix polarity of pico ADPCM busy flag
Michael Pavone <pavone@retrodev.com>
parents:
2435
diff
changeset
|
185 pcm->ctrl |= value & ~(PCM_BUSY); |
2431
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
186 //TODO: update low-pass filter |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
187 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
188 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
189 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
|
190 { |
2435
b8d894f7f9dc
Fix playback of ADPCM blocks with an odd number of samples
Michael Pavone <pavone@retrodev.com>
parents:
2434
diff
changeset
|
191 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
|
192 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
|
193 } |
2431
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
194 if (pcm->fifo_read == sizeof(pcm->fifo)) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
195 pcm->fifo_read = pcm->fifo_write; |
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 pcm->fifo[pcm->fifo_write++] = value >> 8; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
198 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
|
199 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
|
200 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
|
201 } |
2431
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
202 pcm->fifo[pcm->fifo_write++] = value; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
203 pcm->fifo_write &= sizeof(pcm->fifo)-1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
204 } |
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 uint16_t pico_pcm_ctrl_read(pico_pcm *pcm) |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
207 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
208 return pcm->ctrl; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
209 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
210 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
211 uint16_t pico_pcm_data_read(pico_pcm *pcm) |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
212 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
213 if (pcm->fifo_read == sizeof(pcm->fifo)) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
214 return sizeof(pcm->fifo) - 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
215 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
216 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
|
217 } |
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 #define FIFO_THRESHOLD 48 |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
220 uint32_t pico_pcm_next_int(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->ctrl & PCM_INT_EN)) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
223 return CYCLE_NEVER; |
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 uint32_t fifo_bytes; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
226 if (pcm->fifo_read == sizeof(pcm->fifo)) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
227 fifo_bytes = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
228 } else if (pcm->fifo_read == pcm->fifo_write) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
229 fifo_bytes = sizeof(pcm->fifo); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
230 } else { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
231 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
|
232 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
233 if (fifo_bytes < FIFO_THRESHOLD) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
234 return pcm->cycle; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
235 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
236 uint32_t cycles_to_threshold = pcm->counter + 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
237 if (pcm->samples) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
238 uint16_t samples = pcm->samples; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
239 if (pcm->nibble_store) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
240 cycles_to_threshold += pcm->rate + 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
241 samples--; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
242 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
243 uint16_t bytes = (samples >> 1) + (samples & 1); |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
244 if (bytes > (fifo_bytes - FIFO_THRESHOLD)) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
245 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
|
246 fifo_bytes = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
247 } else { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
248 cycles_to_threshold += bytes * (pcm->rate + 1) * 2; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
249 fifo_bytes -= bytes; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
250 } |
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 uint8_t fifo_read = pcm->fifo_read; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
253 uint8_t cmd = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
254 while (fifo_bytes >= FIFO_THRESHOLD) |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
255 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
256 if (cmd) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
257 switch(cmd & 0xC0) |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
258 { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
259 case 0: |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
260 cycles_to_threshold += 640 * (cmd & 0x3F) + 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
261 break; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
262 case 0x40: |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
263 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
|
264 fifo_bytes = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
265 break; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
266 case 0x80: { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
267 uint32_t samples = pcm->fifo[fifo_read++]; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
268 fifo_bytes--; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
269 fifo_read &= sizeof(pcm->fifo) - 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
270 if (fifo_bytes < FIFO_THRESHOLD) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
271 break; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
272 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
273 uint32_t bytes = (samples +1) >> 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
274 if (bytes > (fifo_bytes - FIFO_THRESHOLD)) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
275 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
|
276 fifo_bytes = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
277 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
278 break; } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
279 case 0xC0: { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
280 uint32_t rate = pcm->fifo[fifo_read++] & 0x3F; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
281 fifo_bytes--; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
282 fifo_read &= sizeof(pcm->fifo) - 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
283 uint32_t samples = pcm->fifo[fifo_read++] & 0x3F; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
284 fifo_bytes--; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
285 fifo_read &= sizeof(pcm->fifo) - 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
286 if (fifo_bytes < FIFO_THRESHOLD) { |
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 } |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
289 samples++; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
290 samples *= (cmd & 7) + 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
291 uint32_t bytes = (samples + 1) >> 1; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
292 if (bytes > (fifo_bytes - FIFO_THRESHOLD)) { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
293 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
|
294 fifo_bytes = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
295 } |
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 cmd = 0; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
299 } else { |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
300 cycles_to_threshold++; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
301 cmd = pcm->fifo[fifo_read++]; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
302 fifo_bytes--; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
303 fifo_read &= sizeof(pcm->fifo) - 1; |
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 } |
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 return pcm->cycle + cycles_to_threshold * pcm->clock_inc; |
61c0bfe10887
Somewhat busted support for Pico ADPCM
Michael Pavone <pavone@retrodev.com>
parents:
diff
changeset
|
308 } |