OSDN Git Service

6f09b84470176a6fd3abee34906bc864c29ae9c7
[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 #include "../debugger.h"
11
12 #define EVENT_DAC_SAMPLE 1
13
14 void RF5C68::initialize()
15 {
16         // DAC
17         memset(wave_memory, 0x00, sizeof(wave_memory));
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] = 0x0000080;
25                 dac_pan[(i << 1) + 0] = 0x000000f;
26                 dac_pan[(i << 1) + 1] = 0x000000f;
27                 dac_ls[i].d = 0x0000;
28                 dac_fd[i].d = 0x0000;
29                 dac_onoff[i] = false;
30                 dac_addr[i] = 0x00000000;
31                 dac_force_load[i] = false;
32         }
33         dac_on = false;
34         dac_bank = 0;
35         dac_ch = 0;
36         sample_buffer = NULL;
37
38         if(d_debugger != NULL) {
39                 d_debugger->set_device_name(_T("Debugger (RICOH RF5C68)"));
40                 d_debugger->set_context_mem(this);
41                 d_debugger->set_context_io(vm->dummy);
42         }
43 }
44
45 void RF5C68::release()
46 {
47         if(sample_buffer != NULL) free(sample_buffer);
48         sample_buffer = NULL;
49 }
50
51 void RF5C68::reset()
52 {
53         is_mute = true; // OK?
54         for(int i = 0; i < 8; i++) {
55                 dac_addr_st[i].d = 0x00;
56                 dac_env[i] = 0x0000080;
57                 dac_pan[(i << 1) + 0] = 0x0000008;
58                 dac_pan[(i << 1) + 1] = 0x0000008;
59                 dac_ls[i].d = 0x0000;
60                 dac_fd[i].d = 0x0000;
61                 dac_onoff[i] = false;
62                 dac_addr[i] = 0x00000000;
63                 dac_force_load[i] = false;
64         }
65         for(int i = 0; i < 16; i++) {
66                 dac_tmpval[i] = 0x00000000;
67         }
68         if((sample_buffer != NULL) && (sample_length > 0)) {
69                 memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
70         }
71         if(event_dac_sample != -1) {
72                 cancel_event(this, event_dac_sample);
73                 event_dac_sample = -1;
74         }
75         if(mix_rate > 0) {
76                 sample_tick_us = 1.0e6 / ((double)mix_rate);
77                 register_event(this, EVENT_DAC_SAMPLE, sample_tick_us, true, &event_dac_sample);
78         } else {
79                 sample_tick_us = 0;
80         }
81         sample_count = 0;
82 }
83
84 uint32_t RF5C68::read_signal(int ch)
85 {
86         if(ch >= SIG_RF5C68_REG_ADDR_ST) {
87                 if(ch >= 0x100) return 0x00;
88                 int major_num = ch & 0xf8;
89                 int local_ch = ch & 0x07;
90                 switch(major_num) {
91                 case SIG_RF5C68_REG_ADDR_ST:
92                         return dac_addr_st[local_ch].d;
93                         break;
94                 case SIG_RF5C68_REG_ADDR:
95                         return dac_addr[local_ch];
96                         break;
97                 case SIG_RF5C68_REG_ENV:
98                         return dac_env[local_ch];
99                         break;
100                 case SIG_RF5C68_REG_LPAN:
101                         return dac_pan[(local_ch << 1) + 0];
102                         break;
103                 case SIG_RF5C68_REG_RPAN:
104                         return dac_pan[(local_ch << 1) + 1];
105                         break;
106                 case SIG_RF5C68_REG_LS:
107                         return dac_ls[local_ch].d;
108                         break;
109                 case SIG_RF5C68_REG_FD:
110                         return dac_fd[local_ch].d;
111                         break;
112                 case SIG_RF5C68_FORCE_LOAD:
113                         return ((dac_force_load[local_ch]) ? 0xffffffff : 0x00000000);
114                         break;
115                 default:
116                         break;
117                 }
118         } else {
119                 switch(ch) {
120                 case SIG_RF5C68_MUTE:
121                         return ((is_mute) ? 0xffffffff : 0x00000000);
122                         break;
123                 case SIG_RF5C68_REG_ON:
124                         return ((dac_on) ? 0xffffffff : 0x00000000);
125                         break;
126                 case SIG_RF5C68_REG_BANK:
127                         return dac_bank;
128                         break;
129                 case SIG_RF5C68_REG_CH:
130                         return dac_ch;
131                         break;
132                 default:
133                         break;
134                 }
135         }
136         return 0x00;
137 }
138
139 void RF5C68::write_signal(int ch, uint32_t data, uint32_t mask)
140 {
141         switch(ch)
142         {
143         case SIG_RF5C68_DAC_PERIOD:
144                 if(dac_on) {
145                 __DECL_ALIGNED(16) uint8_t tmpval[8] = {0};
146 __DECL_VECTORIZED_LOOP
147                         for(int i = 0; i < 16; i++) {
148                                 dac_tmpval[i] = 0;
149                         }
150                         for(int ch = 0; ch < 8; ch++) {
151                                 if(dac_onoff[ch]) {
152                                         uint32_t addr_old = (dac_addr[ch] & 0x7fffffff) >> 11;
153                                         uint32_t addr_new;
154                                         if((addr_old & 0x0fff) == 0x0fff) {
155                                                 // Will beyond of boundary
156                                                 write_signals(&interrupt_boundary, ((addr_old & 0xe000) >> 13) | 0x00000008);
157 //                                              out_debug_log(_T("PCM INTERRUPT CH=%d ADDR=%04X"), ch, addr_old & 0xffff);
158                                         }
159                                 
160                                         int chd = ch << 1;
161                                         tmpval[ch] = wave_memory[addr_old & 0xffff];
162                                         if(tmpval[ch] == 0xff) {
163                                                 // Loop
164                                                 dac_addr[ch] = (uint32_t)(dac_ls[ch].w.l) << 11;
165                                                 addr_old = dac_addr[ch] >> 11;
166                                                 tmpval[ch] = wave_memory[addr_old & 0xffff];
167                                                 if(tmpval[ch] == 0xff) {
168                                                         tmpval[ch] = 0x00;
169                                                         //      dac_onoff[ch] = false; // STOP
170                                                         continue; // This channel will stop
171                                                 } 
172                                         }
173                                         dac_addr[ch] += dac_fd[ch].d;
174                                         dac_addr[ch] = dac_addr[ch] & 0x7fffffff;
175                                 }
176                         }
177                         __DECL_ALIGNED(16) bool sign[16] = {false};
178                         __DECL_ALIGNED(16) int32_t val[16] = {0};
179 __DECL_VECTORIZED_LOOP                  
180                         for(int ch = 0; ch < 8; ch++) {
181                                 int chd = ch << 1;
182                                 sign[chd + 0] = (dac_onoff[ch]) ? ((tmpval[ch] & 0x80) == 0) : false; // 0 = minus
183                                 sign[chd + 1] = sign[chd + 0];
184                                 val[chd + 0] = (dac_onoff[ch]) ? (tmpval[ch] & 0x7f) : 0;
185                                 val[chd + 1] = val[chd + 0];
186                         }
187                         // VAL = VAL * ENV * PAN
188 __DECL_VECTORIZED_LOOP                  
189                         for(int chd = 0; chd < 16; chd++) {
190                                 val[chd] = val[chd] * dac_env[chd >> 1];
191                                 val[chd] = val[chd] * dac_pan[chd];
192                         }
193                         // Sign
194 __DECL_VECTORIZED_LOOP                  
195                         for(int chd = 0; chd < 16; chd++) {
196                                 dac_tmpval[chd] = (sign[chd]) ? -val[chd] : val[chd];
197                         }
198                         // Re-Init sample buffer
199 __DECL_VECTORIZED_LOOP
200                         for(int i = 0; i < 2; i++) {
201                                 sample_buffer[i] = 0;
202                         }
203                         // ADD or SUB
204 __DECL_VECTORIZED_LOOP
205                         for(int chd = 0; chd < 16; chd++) {
206                                 sample_buffer[chd & 1] += dac_tmpval[chd];
207                         }
208                         __DECL_ALIGNED(16) static const int32_t uplimit[16]  = {(127 << 6)};
209                         __DECL_ALIGNED(16) static const int32_t lowlimit[16] = {(-127 << 6)};
210                         // Limiter
211 __DECL_VECTORIZED_LOOP
212                         for(int chd = 0; chd < 16; chd++) {
213                                 dac_tmpval[chd] = (dac_tmpval[chd] > uplimit[chd]) ? uplimit[chd] : ((dac_tmpval[chd] < lowlimit[chd]) ? lowlimit[chd] : dac_tmpval[chd]);
214                         }
215                 }
216                 break;
217         case SIG_RF5C68_CLEAR_INTR:
218                 write_signals(&interrupt_boundary, 0x80000000);
219                 break;
220         case SIG_RF5C68_SET_ALL_INTR:
221                 write_signals(&interrupt_boundary, 0x80000008);
222                 break;
223         case SIG_RF5C68_MUTE:
224                 is_mute = ((data & mask) != 0) ? true : false;
225                 break;
226         default:
227                 break;
228         }
229 }
230
231 void RF5C68::write_io8(uint32_t addr, uint32_t data)
232 {
233         uint32_t naddr = addr & 0x0f;
234         switch(naddr) {
235         case 0x00: // ENV
236                 dac_env[dac_ch] = data & 0xff;
237                 out_debug_log(_T("DAC REG 00 (ENV) CH=%d RAW=%02X"),
238                                           dac_ch, data);
239                 break;
240         case 0x01: // PAN
241                 dac_pan[(dac_ch << 1) + 0] = data & 0x0f;
242                 dac_pan[(dac_ch << 1) + 1] = (data & 0xf0) >> 4;
243                 out_debug_log(_T("DAC REG 01 (PAN) CH=%d L=%01X R=%01X"),
244                                           dac_ch, data & 0x0f, (data & 0xf0) >> 4);
245                 break;
246         case 0x02: // FDL
247                 dac_fd[dac_ch].b.l = data & 0xff;
248                 out_debug_log(_T("DAC REG 02 (FD LOW) CH=%d RAW=%02X"),
249                                           dac_ch, data);
250                 break;
251         case 0x03: // FDH
252                 dac_fd[dac_ch].b.h = data & 0xff;
253                 out_debug_log(_T("DAC REG 03 (FD HIGH) CH=%d RAW=%02X"),
254                                           dac_ch, data);
255                 break;
256         case 0x04: // LSL
257                 dac_ls[dac_ch].b.l = data & 0xff;
258                 out_debug_log(_T("DAC REG 04 (LS) CH=%d RAW=%02X"),
259                                           dac_ch, data);
260                 break;
261         case 0x05: // LSH
262                 dac_ls[dac_ch].b.h = data & 0xff;
263                 out_debug_log(_T("DAC REG 05 (ADDR STEP HIGH) CH=%d RAW=%02X"),
264                                           dac_ch, data);
265                 break;
266         case 0x06: // ST
267                 dac_addr_st[dac_ch].d = 0;
268                 dac_addr_st[dac_ch].b.h = data & 0xff;
269                 dac_addr[dac_ch] = (uint32_t)(dac_addr_st[dac_ch].w.l) << 11;
270                 out_debug_log(_T("DAC REG 06 (ADDR STEP HIGH) CH=%d RAW=%02X"),
271                                           dac_ch, data);
272                 break;
273         case 0x07: // Control
274                 dac_on = ((data & 0x80) != 0) ? true : false;
275                 if((data & 0x40) != 0) { // CB2-0
276                         dac_ch = data & 0x07;
277                 } else { // WB3-0
278                         dac_bank = ((data & 0x0f) << 12);
279                 }
280                 out_debug_log(_T("DAC REG 07 RAW=%02X ON=%s CH=%d BANK=%04X"),
281                                            data,
282                                            (dac_on) ? _T("ON ") :_T("OFF"),
283                                            dac_ch, dac_bank);
284                 break;
285         case 0x08: // ON/OFF per CH
286                 {
287                         uint32_t mask = 0x01;
288                         for(int i = 0; i < 8; i++) {
289                                 bool onoff = dac_onoff[i];
290                                 if((mask & data) == 0) {
291                                         dac_onoff[i] = true;
292                                 } else {
293                                         dac_onoff[i] = false;
294                                 }
295 //                              if(!(onoff) && (dac_onoff[i])) { // Force reload
296 //                                      dac_addr[ch] = (uint32_t)(dac_addr_st[ch].w.l) << 11;
297 //                              }
298                                 mask <<= 1;
299                         }
300                 }
301                 out_debug_log(_T("DAC REG 08 (DAC/ONOFF) RAW=%02X"),
302                                            data);
303                 break;
304         default:
305                 break;
306         }
307 }
308
309 uint32_t RF5C68::read_io8(uint32_t addr)
310 {
311         return 0xff;
312 }
313
314 // Read PCM memory
315 uint32_t RF5C68::read_memory_mapped_io8(uint32_t addr)
316 {
317         addr = (addr & 0xfff) | dac_bank;
318         if(d_debugger != NULL && d_debugger->now_device_debugging) {
319                 return d_debugger->read_via_debugger_data8(addr);
320         } else {
321 //              if(dac_on) {
322 //                      return 0xff;
323 //              }
324                 return read_via_debugger_data8(addr);   
325         }
326         return 0xff;
327 }
328
329 uint32_t RF5C68::read_memory_mapped_io16(uint32_t addr)
330 {
331         addr = (addr & 0xfff) | dac_bank;
332         if(d_debugger != NULL && d_debugger->now_device_debugging) {
333                 return d_debugger->read_via_debugger_data16(addr);
334         } else {
335 //              if(dac_on) {
336 //                      return 0xffff;
337 //              }
338                 return read_via_debugger_data16(addr);  
339         }
340         return 0xffff;
341 }
342
343 void RF5C68::write_memory_mapped_io8(uint32_t addr, uint32_t data)
344 {
345         addr = (addr & 0xfff) | dac_bank;
346         // if(dac_on) don't write <- Is correct?
347         if(d_debugger != NULL && d_debugger->now_device_debugging) {
348                 d_debugger->write_via_debugger_data8(addr, data);
349         } else {
350 //              if(!dac_on) {
351                         write_via_debugger_data8(addr, data);
352                         return;
353 //              }
354         }
355 }
356
357 void RF5C68::write_memory_mapped_io16(uint32_t addr, uint32_t data)
358 {
359         addr = (addr & 0xfff) | dac_bank;
360         if(d_debugger != NULL && d_debugger->now_device_debugging) {
361                 d_debugger->write_via_debugger_data16(addr, data);
362         } else {
363 //              if(!dac_on) {
364                         write_via_debugger_data16(addr, data);
365                         return;
366 //              }
367         }
368 }       
369
370 void RF5C68::set_volume(int ch, int decibel_l, int decibel_r)
371 {
372         volume_l = decibel_to_volume(decibel_l);
373         volume_r = decibel_to_volume(decibel_r);
374 }
375
376 void RF5C68::event_callback(int id, int err)
377 {
378         if(id == EVENT_DAC_SAMPLE) {
379                 __DECL_ALIGNED(16) int32_t val[2] = {0}; // l,r
380                 if(sample_count < sample_length) {
381 //                      if(dac_on) {
382                                 for(int ch = 0; ch < 16; ch++) {
383                                         val[ch & 1] += (dac_onoff[ch >> 1]) ? dac_tmpval[ch] : 0;
384                                 }
385 //                      }
386                         int32_t* p = &(sample_buffer[sample_count << 1]);       
387                         for(int i = 0; i < 2; i++) {    
388                                 p[i] = val[i];
389                         }
390                         sample_count++;
391                 }
392         }
393 }
394
395 void RF5C68::mix(int32_t* buffer, int cnt)
396 {
397         
398         int32_t lval, rval;
399         // ToDo: supress pop noise.
400         if(cnt <= 0) return;
401         if(is_mute) return;
402         
403         if(sample_buffer != NULL) {
404                 for(int i = 0; i < (cnt << 1); i += 2) {
405                         // ToDo: interpoolate.
406                         buffer[i]     += (apply_volume(sample_buffer[0], volume_l) >> 2);
407                         buffer[i + 1] += (apply_volume(sample_buffer[1], volume_r) >> 2);
408                 }
409         }
410 }
411
412 void RF5C68::initialize_sound(int sample_rate, int samples)
413 {
414         if((sample_rate > 0) && (samples > 0)) {
415                 mix_rate = sample_rate;
416                 sample_length = samples;
417                 if(sample_buffer != NULL) {
418                         free(sample_buffer);
419                 }
420                 sample_buffer = (int32_t*)malloc(sample_length * sizeof(int32_t) * 2);
421                 if(sample_buffer != NULL) {
422                         memset(sample_buffer, 0x00, sample_length * sizeof(int32_t) * 2);
423                 }
424                 if(event_dac_sample != -1) {
425                         cancel_event(this, event_dac_sample);
426                         event_dac_sample = -1;
427                 }
428                 if(mix_rate > 0) {
429                         // TOWNS::ADPCM::event_callback() -> SIG_RF5C68_DAC_PERIOD(=DRIVE CLOCK from VM)
430                         // -> RF5C68::event_callback()(=AUDIO MIXING CLOCK by EMU)
431                         // -> RF5C68::mix() -> OSD::SOUND
432                         sample_tick_us = 1.0e6 / ((double)mix_rate);
433 //                      register_event(this, EVENT_DAC_SAMPLE, sample_tick_us, true, &event_dac_sample);
434                 }
435         } else {
436                 if(sample_buffer != NULL) {
437                         free(sample_buffer);
438                 }
439                 sample_buffer = NULL;
440                 sample_length = 0;
441                 mix_rate = 0;
442                 if(event_dac_sample != -1) {
443                         cancel_event(this, event_dac_sample);
444                         event_dac_sample = -1;
445                 }
446                 sample_tick_us = 0.0;
447         }
448         sample_count = 0;
449 }
450
451 void RF5C68::write_debug_data8(uint32_t addr, uint32_t data)
452 {
453         wave_memory[addr & 0xffff] = data;
454 }
455
456 uint32_t RF5C68::read_debug_data8(uint32_t addr)
457 {
458         return wave_memory[addr & 0xffff];
459 }
460
461 void RF5C68::write_via_debugger_data8(uint32_t addr, uint32_t data)
462 {
463         wave_memory[addr] = data;
464 }
465
466 void RF5C68::write_via_debugger_data16(uint32_t addr, uint32_t data)
467 {
468         pair32_t _b;
469         _b.d = data;
470         wave_memory[addr + 0] = _b.b.l;
471         wave_memory[(addr + 1) & 0xffff] = _b.b.h;
472 }
473
474
475 uint32_t RF5C68::read_via_debugger_data8(uint32_t addr)
476 {
477         return wave_memory[addr];
478 }
479
480 uint32_t RF5C68::read_via_debugger_data16(uint32_t addr)
481 {
482         pair16_t _b;
483         _b.b.l = wave_memory[addr + 0];
484         _b.b.h = wave_memory[(addr + 1) & 0xffff];
485         return _b.w;
486 }
487
488 bool RF5C68::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
489 {
490         _TCHAR sbuf[8][512] = {0};
491         _TCHAR sbuf2[4096] = {0};
492         for(int i = 0; i < 8; i++) {
493                 my_stprintf_s(sbuf[i], sizeof(sbuf[i]),
494                                           _T("CH%d: %s: ENV=%02X LPAN=%02X RPAN=%02X FD=%04X LS=%04X ADDR=%08X ADDR_ST=%08X\n")
495                                           , i, (dac_onoff[i]) ? _T("ON ") : _T("OFF")
496                                           , dac_env[i], dac_pan[(i << 1) + 0], dac_pan[(i << 1) + 1]
497                                           , dac_fd[i].w.l, dac_ls[i].w.l
498                                           , dac_addr[i], dac_addr_st[i].w.l
499                         );
500         }
501         for(int i = 0; i < 8; i++) {
502                 my_tcscat_s(sbuf2, sizeof(sbuf2), sbuf[i]);
503         }
504         my_stprintf_s(buffer, buffer_len,
505                                   _T("DAC %s BANK=%01X CH=%d MUTE=%s\n")
506                                   _T("%s")
507                                   , (dac_on) ? _T("ON ") : _T("OFF"), dac_bank, dac_ch, (is_mute) ? _T("ON ") : _T("OFF")
508                                   , sbuf2);
509         return true;
510 }
511
512 #define STATE_VERSION   1
513
514 bool RF5C68::process_state(FILEIO* state_fio, bool loading)
515 {
516         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
517                 return false;
518         }
519         if(!state_fio->StateCheckInt32(this_device_id)) {
520                 return false;
521         }
522         state_fio->StateValue(dac_on);
523         state_fio->StateValue(dac_bank);
524         state_fio->StateValue(dac_ch);
525         state_fio->StateValue(is_mute);
526         state_fio->StateArray(dac_onoff, sizeof(dac_onoff), 1);
527         state_fio->StateArray(dac_addr_st, sizeof(dac_addr_st), 1);     
528         state_fio->StateArray(dac_addr, sizeof(dac_addr), 1);
529         state_fio->StateArray(dac_env, sizeof(dac_env), 1);
530         state_fio->StateArray(dac_pan, sizeof(dac_pan), 1);
531         state_fio->StateArray(dac_ls, sizeof(dac_ls), 1);
532         state_fio->StateArray(dac_fd, sizeof(dac_fd), 1);
533         state_fio->StateArray(dac_force_load, sizeof(dac_force_load), 1);
534         state_fio->StateArray(dac_tmpval, sizeof(dac_tmpval), 1);
535         
536         state_fio->StateArray(wave_memory, sizeof(wave_memory), 1);
537         state_fio->StateValue(event_dac_sample);
538
539         // Post Process
540         if(loading) {
541                 if(event_dac_sample != -1) {
542                         cancel_event(this, event_dac_sample);
543                         event_dac_sample = -1;
544                 }
545                 if(mix_rate > 0) {
546                         sample_tick_us = 1.0e6 / ((double)mix_rate);
547                         register_event(this, EVENT_DAC_SAMPLE, sample_tick_us, true, &event_dac_sample);
548                 } else {
549                         sample_tick_us = 0;
550                 }
551                 sample_count = 0;
552         }
553         return true;
554 }