OSDN Git Service

13bd4fe8227b6f79d7124b8118a7b3ceafab6c93
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / rf5c68.cpp
1 /*
2         Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
3         Date   : 2019.01.29-
4
5         [ADPCM RF6C68 with RAM]
6 */
7
8 #include "../../common.h"
9 #include "./rf5c68.h"
10
11 #define EVENT_DAC_SAMPLE 1
12
13 void RF5C68::initialize()
14 {
15         // DAC
16         memset(wave_memory, 0x00, sizeof(wave_memory));
17
18
19         dac_on = false;
20         dac_bank = 0;
21         dac_ch = 0;
22         for(int i = 0; i < 8; i++) {
23                 dac_addr_st[i].d = 0x00;
24                 dac_env[i] = 0x0000000;
25                 dac_lpan[i] = 0x000000f;
26                 dac_rpan[i] = 0x000000f;
27                 dac_tmpval_l[i] = 0x00000000;
28                 dac_tmpval_r[i] = 0x00000000;
29                 dac_ls[i].d = 0x0000;
30                 dac_fd[i].d = 0x0000;
31                 dac_onoff[i] = false;
32                 dac_addr[i] = 0x00000000;
33                 dac_force_load[i] = true;
34         }
35         dac_on = false;
36         dac_bank = 0;
37         dac_ch = 0;
38
39 }
40
41 void RF5C68::reset()
42 {
43         for(int i = 0; i < 8; i++) {
44                 dac_addr_st[i].d = 0x00;
45                 dac_env[i] = 0x0000000;
46                 dac_lpan[i] = 0x000000f;
47                 dac_rpan[i] = 0x000000f;
48                 dac_tmpval_l[i] = 0x00000000;
49                 dac_tmpval_r[i] = 0x00000000;
50                 dac_ls[i].d = 0x0000;
51                 dac_fd[i].d = 0x0000;
52                 dac_onoff[i] = false;
53                 dac_addr[i] = 0x00000000;
54                 dac_force_load[i] = true;
55         }
56         if((sample_buffer != NULL) && (sample_length > 0)) {
57                 memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
58         }
59         if(event_dac_sample != -1) {
60                 cancel_event(this, event_dac_sample);
61                 event_dac_sample = -1;
62         }
63         if(mix_rate > 0) {
64                 sample_tick_us = 1.0e6 / ((double)mix_rate);
65                 register_event(this, EVENT_DAC_SAMPLE, sample_tick_us, true, &event_dac_sample);
66         } else {
67                 sample_tick_us = 0;
68         }
69         sample_count = 0;
70 }
71
72 uint32_t RF5C68::read_signal(int ch)
73 {
74         return 0x00;
75 }
76
77 void RF5C68::write_signal(int ch, uint32_t data, uint32_t mask)
78 {
79         switch(ch)
80         {
81         case SIG_RF5C68_DAC_PERIOD:
82                 if(dac_on) {
83                         for(int ch = 0; ch < 8; ch++) {
84                                 if(dac_onoff[ch]) {
85                                         uint32_t addr_old = (dac_addr[ch] & 0x7fffffff) >> 11;
86                                         uint32_t addr_new;
87                                         dac_addr[ch] += dac_fd[ch].d;
88                                         dac_addr[ch] = dac_addr[ch] & 0x7fffffff;
89                                         addr_new = dac_addr[ch] >> 11;
90                                         if((addr_old != addr_new) || (dac_force_load[ch])) {
91                                             pair32_t tmpval;
92                                                 tmpval.b.l = wave_memory[addr_new & 0xffff];
93                                                 if((addr_new & 0xf000) != (addr_old & 0xf000)) { // Boundary
94                                                         if((addr_new & 0x1000) != 0) {
95                                                                 write_signals(&interrupt_boundary, ((addr_new & 0xe000) >> 13) | 0x00000008);
96                                                         }
97                                                 }
98                                                 if(dac_force_load[ch]) {
99                                                         dac_addr[ch] = (uint32_t)(dac_addr_st[ch].w.l) << 11;
100                                                         addr_new = dac_addr[ch] >> 11;
101                                                         tmpval.b.l = wave_memory[addr_new & 0xffff];
102                                                 }
103                                                 dac_force_load[ch] = false;
104                                                 
105                                                 if(tmpval.b.l == 0xff) {
106                                                         // Skip
107                                                         dac_force_load[ch] = true;
108                                                         // Q: Is clear data reg?
109                                                         dac_data[ch] = 0;
110                                                         dac_tmpval_l[ch] = 0;
111                                                         dac_tmpval_r[ch] = 0;
112                                                 } else { // Normal OP
113                                                         uint32_t sign = tmpval[ch].d & 0x80;
114                                                         uint32_t val = tmpval[ch].d & 0x7f;
115                                                         uint32_t lval, rval;
116                                                         val = val * dac_env[ch];
117                                                         lval = val * dac_lpan[ch];
118                                                         rval = val * dac_rpan[ch];
119                                                         if(sign != 0) { // ADD
120                                                                 dac_tmpval_l[ch] += lval;
121                                                                 dac_tmpval_r[ch] += rval;
122                                                         } else { // SUB
123                                                                 dac_tmpval_l[ch] -= lval;
124                                                                 dac_tmpval_r[ch] -= rval;
125                                                         }
126                                                         // Limiter
127                                                         if(dac_tmpval_l[ch] >= (127 << 6)) {
128                                                                 dac_tmpval_l[ch] = 127 << 6;
129                                                         } else if(dacval_tmpval_l[ch] < -(127 << 6)) {
130                                                                 dac_tmpval_l[ch] = -(127 << 6);
131                                                         } 
132                                                         if(dac_tmpval_r[ch] >= (127 << 6)) {
133                                                                 dac_tmpval_r[ch] = 127 << 6;
134                                                         } else if(dacval_tmpval_r[ch] < -(127 << 6)) {
135                                                                 dac_tmpval_r[ch] = -(127 << 6);
136                                                         }
137                                                 }
138                                         }
139                                 } else {
140                                         dac_tmpval_l[ch] = 0;
141                                         dac_tmpval_r[ch] = 0;
142                                 }
143                         }
144                 }
145                 break;
146         case SIG_RF5C68_CLEAR_INTR:
147                 write_signals(&interrupt_boundary, 0x80000000);
148                 break;
149         case SIG_RF5C68_SET_ALL_INTR:
150                 write_signals(&interrupt_boundary, 0x80000008);
151                 break;
152         default:
153                 break;
154         }
155 }
156
157 void RF5C68::write_io8(uint32_t addr, uint32_t data)
158 {
159         uint32_t naddr = addr & 0x0f;
160         switch(naddr) {
161         case 0x00: // ENV
162                 dac_env[dac_ch] = data & 0xff;
163                 break;
164         case 0x01: // PAN
165                 dac_lpan[dac_ch] = data & 0x0f;
166                 dac_rpan[dac_ch] = (data & 0xf0) >> 4;
167                 break;
168         case 0x02: // FDL
169                 dac_fd[dac_ch].b.l = data & 0xff;
170                 break;
171         case 0x03: // FDH
172                 dac_fd[dac_ch].b.h = data & 0xff;
173                 break;
174         case 0x04: // LSL
175                 dac_ls[dac_ch].b.l = data & 0xff;
176                 break;
177         case 0x05: // LSH
178                 dac_ls[dac_ch].b.h = data & 0xff;
179                 break;
180         case 0x06: // ST
181                 dac_addr_st[dac_ch].d = 0;
182                 dac_addr_st[dac_ch].b.h = data & 0xff;
183                 break
184         case 0x07: // Control
185                 dac_on = ((data & 0x80) != 0) ? true : false;
186                 if((data & 0x40) != 0) { // CB2-0
187                         dac_ch = data & 0x07;
188                 } else { // WB3-0
189                         dac_bank = ((data & 0x0cf) << 12);
190                 }
191                 break;
192         case 0x08: // ON/OFF per CH
193                 {
194                         uint32_t mask = 0x01;
195                         for(int i = 0; i < 8; i++) {
196                                 bool onoff = dac_onoff[i];
197                                 if((mask & data) != 0) {
198                                         dac_onoff[i] = true;
199                                 } else {
200                                         dac_onoff[i] = false;
201                                 }
202                                 if(onoff != dac_onoff[i]) {
203                                         dac_force_load[i] = true;
204                                 }
205                         }
206                         mask <<= 1;
207                 }
208                 break;
209         default:
210                 break;
211         }
212 }
213
214 uint32_t RF5C68::read_io8(uint32_t addr)
215 {
216         return 0xff;
217 }
218
219 // Read PCM memory
220 uint32_t RF5C68::read_data8(uint32_t addr)
221 {
222         if(dac_on) {
223                 return 0xff;
224         }
225         // dac_off
226         return wave_memory[(addr & 0x0fff) | dac_bank];
227 }
228
229 void RF5C68::write_data8(uint32_t addr, uint32_t data)
230 {
231         // if(dac_on) don't write <- Is correct?
232         if(!dac_on) {
233                 wave_memory[(addr & 0x0fff) | dac_bank] = (uint8_t)data;
234         }
235 }
236
237 void RF5C68::set_volume(int ch, int decibel_l, int decibel_r)
238 {
239         volume_l = decibel_to_volume(decibel_l);
240         volume_r = decibel_to_volume(decibel_r);
241 }
242
243 void RF5C68::event_callback(int id, int err)
244 {
245         if(id == EVENT_DAC_SAMPLE) {
246                 int32_t lval, rval;
247                 lval = 0;
248                 rval = 0;
249                 if(sample_count < sample_length) {
250                         if(dac_on) {
251                                 for(int ch = 0; ch < 8; ch++) {
252                                         if(dac_onoff[ch]) {
253                                                 lval = lval + (dac_tmpval_l[ch] << 0);
254                                                 rval = rval + (dac_tmpval_r[ch] << 0);
255                                         }
256                                 }
257                         }
258                         sample_buffer[sample_count << 1] = lval;
259                         sample_buffer[(sample_count << 1) + 1] = rval;
260                         sample_count++;
261                 }
262         }
263 }
264
265 void RF5C68::mix(int32_t* buffer, int cnt)
266 {
267         
268         int32_t lval, rval;
269         // ToDo: supress pop noise.
270         if(sample_length < cnt) cnt = sample_length;
271         if(sample_length < sample_count) sample_count = sample_length;
272         if(cnt <= 0) return;
273         
274         if(sample_buffer != NULL) {
275                 for(int i = 0; i < (cnt << 1); i += 2) {
276                         // ToDo: interpoolate.
277                         buffer[i]     += apply_volume(sample_buffer[i],     volume_l);
278                         buffer[i + 1] += apply_volume(sample_buffer[i + 1], volume_r);
279                 }
280                 if(sample_count > cnt) {
281                         sample_count -= cnt;
282                         memcpy(&(sample_buffer[0]), &(sample_buffer[cnt * 2]), sample_count * sizeof(int32_t) * 2);
283                         memset(&(sample_buffer[cnt * 2]), 0x00, (sample_length - sample_count)  * sizeof(int32_t) * 2);
284                 } else {
285                         memset(&(sample_buffer[0]), 0x00, sample_length * sizeof(int32_t) * 2);
286                         sample_count = 0;
287                 }
288         }
289 }
290
291 void RF5C68::initialize_sound(int sample_rate, int samples)
292 {
293         if((sample_rate > 0) && (samples > 0)) {
294                 mix_rate = sample_rate;
295                 sample_length = samples;
296                 if(sample_buffer != NULL) {
297                         free(sample_buffer);
298                 }
299                 sample_buffer = (int32_t*)malloc(sample_length * sizeof(int32_t) * 2);
300                 if(sample_buffer != NULL) {
301                         memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
302                 }
303                 if(event_dac_sample != -1) {
304                         cancel_event(this, event_dac_sample);
305                         event_sample = -1;
306                 }
307                 sample_tick_us = 1.0e6 / ((double)mix_rate);
308                 register_event(this, EVENT_DAC_SAMPLE, sample_tick_us, true, &event_dac_sample);
309         } else {
310                 if(sample_buffer != NULL) {
311                         free(sample_buffer);
312                 }
313                 sample_buffer = NULL;
314                 sample_length = 0;
315                 mix_rate = 0;
316                 if(event_dac_sample != -1) {
317                         cancel_event(this, event_dac_sample);
318                         event_dac_sample = -1;
319                 }
320                 sample_tick_us = 0.0;
321         }
322         sample_count = 0;
323 }
324
325 #define STATE_VERSION   1
326
327 bool RF5C68::process_state(FILEIO* state_fio, bool loading)
328 {
329         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
330                 return false;
331         }
332         if(!state_fio->StateCheckInt32(this_device_id)) {
333                 return false;
334         }
335         state_fio->StateValue(dac_on);
336         state_fio->StateValue(dac_bank);
337         state_fio->StateValue(dac_ch);
338         state_fio->StateArray(dac_on);
339         state_fio->StateArray(dac_onoff, sizeof(dac_onoff), 1);
340         state_fio->StateArray(dac_addr_st, sizeof(dac_addr_st), 1);     
341         state_fio->StateArray(dac_addr, sizeof(dac_addr), 1);
342         state_fio->StateArray(dac_env, sizeof(dac_env), 1);
343         state_fio->StateArray(dac_lpan, sizeof(dac_lpan), 1);
344         state_fio->StateArray(dac_rpan, sizeof(dac_rpan), 1);
345         state_fio->StateArray(dac_ls, sizeof(dac_ls), 1);
346         state_fio->StateArray(dac_fd, sizeof(dac_fd), 1);
347         state_fio->StateArray(dac_force_load, sizeof(dac_force_load), 1);
348         state_fio->StateArray(dac_tmpval_l, sizeof(dac_tmpval_l), 1);
349         state_fio->StateArray(dac_tmpval_r, sizeof(dac_tmpval_r), 1);
350         
351         state_fio->StateArray(wave_memory, sizeof(wave_memory), 1);
352
353         // ToDo: OLD_mix_rate != mix_rate.
354         state_fio->StateValue(mix_rate);
355         // ToDo: OLD_sample_length != sample_length.
356         state_fio->StateValue(sample_length);
357         state_fio->StateValue(event_dac_sample);
358         // Post Process
359         if(loading) {
360                 if((sample_buffer != NULL) && (sample_length > 0)) {
361                         memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
362                 } else {
363                         sample_length = 0;
364                 }
365                 sample_count = 0;
366                 if(mix_rate > 0) {
367                         sample_tick_us = 1.0e6 / ((double)mix_rate);
368                 } else {
369                         sample_tick_us = 0;
370                 }
371         }
372         return true;
373 }