OSDN Git Service

[VM][PCENGINE][ADPCM] pce.cpp : porting logics from mednafen and Ootake.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pcengine / adpcm.cpp
1 /*
2         NEC-HE PC Engine Emulator 'ePCEngine'
3         SHARP X1twin Emulator 'eX1twin'
4
5         Origin : Ootake (joypad/cdrom)
6                : xpce (psg)
7                : MESS (vdc/vce/vpc/cdrom)
8         Author : Takeda.Toshiya
9         Date   : 2009.03.11-
10         Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
11         Date   : 2019.02.09-  Split from pce.cpp
12
13         [ PC-Engine around ADPCM]
14 */
15
16 #include "./adpcm.h"
17 #include "./pce.h"
18
19
20 #include "../msm5205.h"
21 #include "../scsi_host.h"
22 #include "../scsi_cdrom.h"
23
24
25 namespace PCEDEV {
26
27 #define ADPCM_REMAIN_READ_BUF   0x80    
28 #define ADPCM_REMAIN_WRITE_BUF  0x04    
29 #define ADPCM_PLAY_FLAG                 0x08
30 #define ADPCM_STOP_FLAG                 0x01
31
32 #define EVENT_CLEAR_ACK 1
33 #define EVENT_SET_ACK   2
34 #define EVENT_FADE_IN   3
35 #define EVENT_FADE_OUT  4
36         
37 void ADPCM::initialize()
38 {
39         adpcm_clock_divider = 1; // OK?
40         event_fader = -1;
41         event_ack = -1;
42         reg_0c = 0;
43         msm_last_cmd = 0;
44         reg_0b = 0;
45         adpcm_volume = 100.0;
46
47         memset(ram, 0x00, sizeof(ram));
48 }
49
50 void ADPCM::reset()
51 {
52         touch_sound();
53
54         read_ptr = write_ptr = 0;
55         read_buf = write_buf = 0;
56         written_size = 0;
57         dma_enabled = false;
58         play_in_progress = false;
59         adpcm_paused = false;
60         
61         msm_data = 0x00;
62         msm_ptr = 0;
63         msm_nibble = 0;
64         msm_length = 0;
65         
66         adpcm_length = 0;
67         addr_reg.w = 0;
68         half_addr = 0;
69         msm_last_cmd = 0;
70         reg_0b = 0;
71         adpcm_stream = false;
72         adpcm_stopped = true;   
73         if(event_fader != -1) {
74                 cancel_event(this, event_fader);
75         }
76         event_fader = -1;
77         if(event_ack != -1) {
78                 cancel_event(this, event_ack);
79         }
80         event_ack = -1;
81         
82         reg_0c |= ADPCM_STOP_FLAG;
83         reg_0c &= ~ADPCM_PLAY_FLAG;
84         
85         //d_msm->change_clock_w((ADPCM_CLOCK / 6) / adpcm_clock_divider);  // From mednafen 1.22.1
86         //adpcm_volume = 0.0;
87         d_msm->set_volume((int)adpcm_volume);
88         //memset(ram, 0x00, sizeof(ram));
89 }
90
91 uint32_t ADPCM::read_signal(int ch)
92 {
93         switch(ch) {
94         case SIG_ADPCM_DATA:
95                 if(read_buf > 0) {
96                         reg_0c |= ADPCM_REMAIN_READ_BUF;
97                         read_buf--;
98                         if(read_buf == 0) {
99                                 reg_0c &= ~ADPCM_REMAIN_READ_BUF;
100                         }
101                         return 0x00;
102                 } else {
103                         reg_0c &= ~ADPCM_REMAIN_READ_BUF;
104                         uint8_t _d = ram[read_ptr & 0xffff];
105                         read_ptr = (read_ptr + 1) & 0xffff;
106                         return _d;
107                 }
108                 break;
109         case SIG_ADPCM_DMACTRL:
110                 return reg_0b;
111                 break;
112         case SIG_ADPCM_PLAY_IN_PROGRESS:
113                 return ((play_in_progress) ? 0xffffffff : 0);
114                 break;
115         case SIG_ADPCM_STATUS_REG:
116                 {
117                         uint8_t data = reg_0c;
118                         // Hack from Ootake v2.83.
119                         if((play_in_progress)) {
120                                 data = data & ~0x85;
121                                 data = data | 0x08;
122                         } else {
123                                 data = data | 0x01;
124                                 data = data & ~0x0c;
125                         }
126                         return data;
127                 }
128                 break;
129         case SIG_ADPCM_CMD_REG:
130                 return msm_last_cmd;
131                 break;
132         }
133         return 0x00;
134 }
135
136 void ADPCM::reset_adpcm()
137 {
138         touch_sound();
139         // reset ADPCM hardware
140         read_ptr = write_ptr = 0;
141         read_buf = write_buf = 0;
142         msm_ptr = half_addr = 0;
143         msm_nibble = 0;
144         msm_last_cmd = 0x00;
145         addr_reg.w = 0x0000;
146         do_stop(false);
147         //d_msm->reset();
148         d_msm->reset_w(1);
149         out_debug_log(_T("RESET ADPCM\n"));
150         d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
151         d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
152         msm_data = 0x00;
153         
154         // stop ADPCM dma
155         set_dma_status(false);
156         adpcm_repeat = false;
157         //adpcm_stream = false;
158 }
159
160 void ADPCM::do_play()
161 {
162         reg_0c &= ~ADPCM_STOP_FLAG;
163         reg_0c |= ADPCM_PLAY_FLAG;
164         play_in_progress = true;
165         adpcm_paused = false;
166         adpcm_stopped = false;
167 }
168
169 void ADPCM::do_pause(bool pause)
170 {
171         //if(!(play_in_progress)) return;
172         if(pause) {
173                 reg_0c |= ADPCM_STOP_FLAG;
174                 reg_0c &= ~ADPCM_PLAY_FLAG;
175                 msm_last_cmd &= ~0x60;
176                 adpcm_paused = true;
177                 d_msm->reset_w(1);
178                 out_debug_log(_T("ADPCM PAUSE PLAY PTR=%04x\n"), msm_ptr);
179                 touch_sound();
180         } else {
181                 adpcm_paused = false;
182                 touch_sound();
183                 reg_0c &= ~ADPCM_STOP_FLAG;
184                 reg_0c |= ADPCM_PLAY_FLAG;
185                 d_msm->reset_w(0);
186                 out_debug_log(_T("ADPCM UNPAUSE PLAY PTR=%04x\n"), msm_ptr);
187         }
188 }
189
190 void ADPCM::do_stop(bool do_irq)
191 {
192         reg_0c |= ADPCM_STOP_FLAG;
193         reg_0c &= ~ADPCM_PLAY_FLAG;
194         if(do_irq) {
195                 d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
196         }
197         msm_last_cmd &= ~0x60;
198         play_in_progress = false;
199         //set_dma_status(false);
200         out_debug_log(_T("ADPCM STOP PLAY PTR=%04x IRQ=%s\n"), msm_ptr, (do_irq) ? _T("YES") : _T("NO"));
201         
202 }
203
204 void ADPCM::set_dma_status(bool flag)
205 {
206         dma_enabled = flag;
207         //d_pce->write_signal(SIG_PCE_ADPCM_DMA, (flag) ? 0xffffffff : 0x00000000, 0xffffffff);
208 }
209
210 void ADPCM::write_signal(int ch, uint32_t data, uint32_t mask)
211 {
212         bool flag = ((data & mask) != 0);
213         //if(ch != SIG_ADPCM_VCLK) out_debug_log(_T("WRITE_SIGNAL SIG=%d DATA=%04x MASK=%04x\n"), ch, data, mask);
214         switch(ch) {
215         case SIG_ADPCM_DMACTRL:
216                 if((data & 0x03) != 0) {
217                         set_dma_status(true);
218                         //reg_0b |= 0x02;
219                 }
220                 reg_0b = data;
221                 break;
222         case SIG_ADPCM_PAUSE:
223                 //do_pause(flag);
224                 break;
225         case SIG_ADPCM_DMA_ENABLED:
226                 set_dma_status(flag);
227                 if((flag)/* && (flag != dma_enabled)*/) {
228                         reg_0c |= ADPCM_REMAIN_WRITE_BUF;
229                         if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
230                                 do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
231                                 out_debug_log(_T("Start DMA port $0B/ALREADY READ DATA ADPCM_WRITE_PTR=%04x ADPCM_READ_PTR=%04x MSM_START_ADDR=%04x\n"),write_ptr, read_ptr, msm_ptr);
232                         } else {
233                                 out_debug_log(_T("Start DMA port $0B/WAIT FOR DATA\n"));
234                         }
235                 }
236                 break;
237         case SIG_ADPCM_RESET:
238                 if(flag) {
239                         reset_adpcm();
240                 }
241                 break;
242         case SIG_ADPCM_COMMAND: // REG $0D
243                 do_cmd(data);
244                 break;
245         case SIG_ADPCM_WRITE_DMA_DATA:
246                 do_dma(data);
247                 break;
248         case SIG_ADPCM_DO_DMA_TRANSFER:
249                 if((play_in_progress) && !(adpcm_paused) && ((write_ptr & 0xffff) >= (msm_ptr & 0xffff))) {
250                         // now streaming, wait dma not to overwrite buffer before it is played
251                         reg_0b = 0x00;// From Ootake v2.38.
252                         set_dma_status(false);  // DON'T MODIFY PCE's DMA STATUS (HACK by K.O 20190212)
253                 } else {
254                         set_dma_status(true);
255                         do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
256                 }
257                 break;
258         case SIG_ADPCM_ADDR_HI: // REG $09
259                 if((msm_last_cmd & 0x80) != 0) {
260                         break;
261                 }
262                 addr_reg.b.h = data;
263                 if((msm_last_cmd & 0x10) != 0) {
264                         adpcm_length = (uint32_t)(addr_reg.w);
265                         msm_length = adpcm_length;
266                         out_debug_log(_T("SET ADDRESS REGISTER HIGH ; UPDATE LENGTH TO %04x\n"), adpcm_length);
267                 }
268                 break;
269         case SIG_ADPCM_ADDR_LO: // REG $08
270                 if((msm_last_cmd & 0x80) != 0) {
271                         break;
272                 }
273                 addr_reg.b.l = data;
274                 if((msm_last_cmd & 0x10) != 0) {
275                         adpcm_length = (uint32_t)(addr_reg.w);
276                         msm_length = adpcm_length;
277                         out_debug_log(_T("SET ADDRESS REGISTER LOW ; UPDATE LENGTH TO %04x\n"), adpcm_length);
278                 }
279                 break;
280         case SIG_ADPCM_VCLK:
281                 do_vclk(flag);
282                 break;
283         case SIG_ADPCM_DATA:
284                 if(write_buf > 0) {
285                         reg_0c |= ADPCM_REMAIN_WRITE_BUF;
286                         write_buf--;
287                         if(write_buf == 0) {
288                                 reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
289                         }
290                 } else {
291                         reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
292                         ram[write_ptr & 0xffff] = data;
293                         write_ptr = (write_ptr + 1) & 0xffff;
294                         //written_size++;
295                 }
296                 break;
297         case SIG_ADPCM_FADE_IN:
298                 fade_in(data);
299                 break;
300         case SIG_ADPCM_FADE_OUT:
301                 fade_out(data);
302                 break;
303         case SIG_ADPCM_SET_DIVIDER:
304                 adpcm_clock_divider = 0x10 - (data & 0x0f);
305                 d_msm->change_clock_w((ADPCM_CLOCK / 6) / adpcm_clock_divider);
306                 break;
307         case SIG_ADPCM_CLEAR_ACK:
308                 reg_0b &= 0xfc; // Clear status register.
309                 dma_enabled = false;
310                 break;
311         }
312 }
313         
314 void ADPCM::do_cmd(uint8_t cmd)
315 {
316         // Register 0x0d.
317         //out_debug_log(_T("ADPCM CMD=%02x\n"), cmd);
318         if(((cmd & 0x80) != 0) /*&& ((msm_last_cmd & 0x80) == 0)*/) {
319                 // Reset ADPCM
320                 reset_adpcm();
321                 msm_init(); // SAMPLE = 0x800, SSIS=0
322                 out_debug_log(_T("ADPCM CMD RESET\n"));
323                 msm_last_cmd = cmd;
324                 return;
325         }
326         
327         if(((cmd & 0x02) != 0) /*&& ((msm_last_cmd & 0x02) == 0)*/) {
328                 // ADPCM set write address
329                 write_ptr = (uint32_t)(addr_reg.w);
330                 write_buf = ((cmd & 0x01) == 0) ? 1 : 0;
331                 written_size = 0; // OK?
332                 //write_ptr = (write_ptr - write_buf) & 0xffff;
333                 // It's ugly... (;_;)
334                 uint32_t _clk = (ADPCM_CLOCK / 6) / adpcm_clock_divider;
335                 if(((read_ptr & 0xffff) >= 0x4000) &&
336                  ((write_ptr & 0xffff) == 0x0000) &&
337                  (adpcm_length != 0x8000) &&
338                  (adpcm_length != 0xffff) &&
339                  (_clk < 16000)) {
340                         adpcm_length = adpcm_length & 0x7fff;
341                 }
342                 msm_length = adpcm_length;
343                 out_debug_log(_T("ADPCM SET WRITE ADDRESS ADDR=%04x BUF=%01x \n"), write_ptr, write_buf);
344         }
345         if(((cmd & 0x08) != 0) /*&& ((msm_last_cmd & 0x08) == 0)*/) {
346                 // ADPCM set read address
347                 read_ptr = (uint32_t)(addr_reg.w);
348                 read_buf = ((cmd & 0x04) == 0) ? 2 : 1;
349                 //read_ptr = ((cmd & 0x04) == 0) ? ((read_ptr - 1) & 0xffff) : read_ptr;
350                 msm_ptr = read_ptr;
351                 out_debug_log(_T("ADPCM SET READ ADDRESS ADDR=%04x BUF=%01x \n"), read_ptr, read_buf);
352         }
353         if(((cmd & 0x10) != 0) /*&& ((msm_last_cmd & 0x10) == 0)*/){
354                 // ADPCM set length
355                 //d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
356                 adpcm_stopped = false;
357                 adpcm_length = (uint32_t)(addr_reg.w);
358                 msm_length = adpcm_length;
359                 out_debug_log(_T("ADPCM SET LENGTH TO %04x\n"), adpcm_length);
360         }
361         bool req_play = false;
362         bool req_play_0 =   ((cmd & 0x40) != 0) ? true : false;
363         adpcm_repeat = ((cmd & 0x20) != 0) ? true : false;
364                 
365         if((play_in_progress) && !(adpcm_paused) && !(adpcm_repeat)) {
366                 req_play = false;
367         }
368         if(!(play_in_progress) && !(adpcm_paused) && (adpcm_repeat)) {
369                 d_msm->change_clock_w((ADPCM_CLOCK / 6) / adpcm_clock_divider);  // From mednafen 1.22.1
370                 d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
371                 req_play = true;
372                 msm_nibble = 0;
373                 msm_init(); // SAMPLE = 0x800, SSI=0
374         }
375 #if 1
376         if((play_in_progress) && !(adpcm_paused)) {
377                 if(req_play) { // Update only
378                         msm_ptr = read_ptr & 0xffff;
379                         msm_nibble = 0;
380                         if(((adpcm_length & 0xffff) >= 0x8000) && ((adpcm_length & 0xffff) <= 0x80ff)) {
381                                 half_addr = (read_ptr + 0x85) & 0xffff;
382                         } else {
383                                 half_addr = (read_ptr + (adpcm_length >> 1)) & 0xffff;
384                         }
385                         //do_pause(false);
386                         //
387                 } else {
388                         d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
389                         d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
390                         adpcm_stream = false;
391                         adpcm_repeat = false;
392                 }
393         } else { // Not playing
394                 if(req_play) {
395                         msm_ptr = read_ptr & 0xffff;
396                         half_addr = (msm_ptr + (adpcm_length / 2)) & 0xffff;
397                         write_ptr &= 0xffff;
398                         msm_nibble = 0;
399                         do_play();
400                         d_msm->reset_w(0);
401                 } else {
402                         d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
403                         d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
404                         adpcm_stream = false;
405                         adpcm_repeat = false;
406                 }
407         }
408 #else
409         if((req_play) && !(play_in_progress)) {
410                 msm_ptr = read_ptr & 0xffff;
411                 half_addr = (msm_ptr + ((adpcm_length + 1) / 2)) & 0xffff;
412                 if(((adpcm_length & 0xffff) >= 0x8000) && ((adpcm_length & 0xffff) <= 0x80ff)) {
413                         half_addr = (read_ptr + 0x85) & 0xffff;
414                 }
415                 msm_nibble = 0;
416                 do_play();
417                 d_msm->reset_w(0);
418                 out_debug_log(_T("ADPCM START PLAY(%s) START=%04x LENGTH=%04x HALF=%04x\n"), (dma_enabled) ? _T("DMA") : _T("PIO"), msm_ptr, adpcm_length, half_addr);
419         } else if((req_play) /*&& (cmd != msm_last_cmd)*/){
420                 msm_ptr = read_ptr & 0xffff;
421                 half_addr = (msm_ptr + (adpcm_length / 2)) & 0xffff;
422                 if(((adpcm_length & 0xffff) >= 0x8000) && ((adpcm_length & 0xffff) <= 0x80ff)) {
423                         half_addr = (read_ptr + 0x85) & 0xffff;
424                 } else {
425                         half_addr = (read_ptr + (adpcm_length >> 1)) & 0xffff;
426                 }
427                 out_debug_log(_T("ADPCM UPDATE HALF ADDRESS HALF=%04x LENGTH=%04x\n"), half_addr, adpcm_length);
428         } else /*if(cmd != msm_last_cmd)*/ { // !req_play
429                 adpcm_repeat = false;
430                 if(play_in_progress && !(adpcm_paused)) {
431                         //adpcm_stopped = true;
432                         //play_in_progress = false;
433                         //d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
434                         //d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
435                         //do_stop(false);
436                 }
437                 //adpcm_stopped = true;
438                 out_debug_log(_T("ADPCM STATUS UPDATE PLAY=%s\n"), (play_in_progress) ? _T("YES") : _T("NO"));                  
439         }
440         // used by Buster Bros to cancel an in-flight sample
441         // if repeat flag (bit5) is high, ADPCM should be fully played (from Ootake)
442         //if(!(req_play) && !(adpcm_repeat)) {
443         //      d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
444         //      d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
445         //      do_stop(false);
446         //      d_msm->reset_w(1);
447         //}
448 #endif
449         msm_last_cmd = cmd;
450         
451 }
452
453 void ADPCM::msm_init()
454 {
455         //d_msm->reset();
456         //d_msm->reset_w(1);
457         //d_msm->reset_w(0);
458 }
459
460 void ADPCM::do_vclk(bool flag)
461 {
462         if((flag)) {
463                 {
464                         if((play_in_progress) && !(adpcm_paused) && (adpcm_length > 0)) {
465                                 if(!((adpcm_length == 1) && ((msm_nibble & 1) == 0))) {
466                                         msm_data = (msm_nibble != 0) ? (ram[msm_ptr & 0xffff] & 0x0f) : ((ram[msm_ptr & 0xffff] & 0xf0) >> 4);
467                                 }
468                                 d_msm->data_w(msm_data);
469                                 msm_nibble ^= 1;
470                         }
471                         if((msm_nibble == 0) && (play_in_progress) && !(adpcm_paused)) {
472                                 if((written_size > 0) /*&& !(adpcm_stopped)*/) written_size--;
473                                 // Increment pointers.
474 #if 0
475                                 if((adpcm_length == 0) && ((msm_last_cmd & 0x10) == 0)){
476                                         d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
477                                         d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
478                                         if((msm_last_cmd & 0x40) != 0) {
479                                                 do_stop(false);
480                                                 d_msm->reset_w(1); 
481                                         }
482                                         adpcm_repeat = false;
483                                         adpcm_stream = false;
484                                 } else {
485                                         if(adpcm_length > 0) adpcm_length--;
486                                         msm_ptr = (msm_ptr + 1) & 0xffff;
487                                         read_ptr = msm_ptr;
488                                         if((adpcm_repeat) && (msm_length >= 0x8000) && (msm_length <= 0x80ff)) {
489                                                 if(msm_ptr == (half_addr & 0xffff)) {
490                                                         half_addr = (half_addr + 0x85) & 0xffff;
491                                                         d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
492                                                         d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
493                                                 }
494                                                 //out_debug_log(_T("PLAY PASSED TO THE HALF ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, msm_length);
495                                         } else if(msm_length < 0x7fff) {
496                                                 if(msm_ptr == (half_addr & 0xffff)) {
497                                                         half_addr = (half_addr + (msm_length & 0xffff) - 1024) & 0xffff;
498                                                         d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
499                                                         d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
500                                                 }
501                                                 //out_debug_log(_T("PLAY PASSED TO THE HALF ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, msm_length);
502                                         } else {
503                                                 if((msm_ptr == 0x8000) || (msm_ptr == 0x0000)) {
504                                                         d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
505                                                         d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
506                                                 }
507                                         }
508                                 }
509                                                 
510 #else
511                                 if((adpcm_length == 0)) {
512                                         if((msm_last_cmd & 0x10) == 0) {
513                                                 if(!(adpcm_stopped)) {
514                                                         d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x0, 0xffffffff);
515                                                         d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
516                                                         if((msm_last_cmd & 0x40) != 0) {
517                                                                 do_stop(false);
518                                                                 d_msm->reset_w(1); 
519                                                         }
520                                                         out_debug_log(_T("PLAY REACHED TO THE END ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, adpcm_length);
521                                                         adpcm_stopped = true;
522                                                 } else {
523                                                         d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x0, 0xffffffff);
524                                                 }
525                                         }
526                                 } else  if((msm_ptr & 0xffff) == (half_addr & 0xffff)) {
527                                         //if(!(adpcm_stopped)) {
528                                         if((msm_last_cmd & 0x10) == 0) {
529                                                 d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
530                                                 d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x0, 0xffffffff);
531                                                 out_debug_log(_T("PLAY PASSED TO THE HALF ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, adpcm_length);
532                                         }
533                                                 //}
534                                 }
535 #if 1
536                                 else if((!((dma_enabled) && (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff)) &&
537                                                    !(adpcm_length < 0x7fff)) &&
538                                                   (((msm_ptr & 0xffff) == 0x8000) || ((msm_ptr & 0xffff) == 0x0000))) {
539                                         // 20181213 K.O: Porting from Ootake v2.83.Thanks to developers of Ootake.
540                                         //set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
541                                         if((msm_last_cmd & 0x10) == 0) {
542                                                 d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
543                                                 d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x0, 0xffffffff);
544                                         }
545                                         out_debug_log(_T("SPECIAL HALF ADDRESS MSM_ADDR=%08x\n"), msm_ptr);
546                                 }
547 #endif
548                                 if(!(adpcm_stopped)) {
549                                         msm_ptr = (msm_ptr + 1) & 0xffff;
550                                         read_ptr = msm_ptr;
551                                 }
552                                 if((msm_last_cmd & 0x10) == 0) {
553                                         if(adpcm_length > 0) {
554                                                 adpcm_length--;
555                                         } else {
556                                                 if(!(adpcm_stopped)) {
557                                                         if((msm_last_cmd & 0x10) == 0) {
558                                                                 d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x0, 0xffffffff);
559                                                                 d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
560                                                                 if((msm_last_cmd & 0x40) != 0) {
561                                                                         do_stop(false);
562                                                                 }
563                                                                 out_debug_log(_T("PLAY REACHED TO THE END2 ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, adpcm_length);
564                                                         adpcm_stopped = true;
565                                                         }
566                                                 }
567                                         }
568                                 }
569 #endif
570                         
571 #if 1
572                         __skip1:
573                                 if((dma_enabled) /*&& (written_size <= 0) && !(adpcm_stopped)*/) {
574                                         if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
575                                                 //do_pause(false); // Unpause if paused && data in.
576                                                 do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
577                                         }
578                                 } else {
579                                                         
580                                 }
581 #endif
582                         } else { // nibble = 1
583                         }
584                 }
585         }
586 }
587         
588 bool ADPCM::do_dma(uint8_t data)
589 {
590         ram[write_ptr & 0xffff] = data;
591         write_ptr = (write_ptr + 1) & 0xffff;
592         written_size = (written_size + 1) & 0xffff;;
593         //set_ack(0);
594
595         reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
596         return true;
597 }
598
599
600 void ADPCM::set_ack(int clocks)
601 {
602         if(event_ack != -1) cancel_event(this, event_ack);
603         event_ack = -1;
604         if(clocks <= 0) {
605                 d_pce->write_signal(SIG_PCE_CDROM_SET_ACK, 0xff, 0xff);
606         } else {
607                 double us = (((double)clocks) * 1.0e6) / ((double)CPU_CLOCKS);
608                 register_event(this, EVENT_SET_ACK, us, false, &event_ack);
609         }
610 }
611
612 void ADPCM::clear_ack(int clocks)
613 {
614         if(event_ack != -1) cancel_event(this, event_ack);
615         event_ack = -1;
616         if(clocks <= 0) {
617                 d_pce->write_signal(SIG_PCE_CDROM_CLEAR_ACK, 0xff, 0xff);
618         } else {
619                 double us = (((double)clocks) * 1.0e6) / ((double)CPU_CLOCKS);
620                 register_event(this, EVENT_CLEAR_ACK, us, false, &event_ack);
621         }
622 }
623
624 void ADPCM::fade_in(int usec)
625 {
626         if(event_fader != -1) {
627                 cancel_event(this, event_fader);
628         }
629         register_event(this, EVENT_FADE_IN, (double)usec, true, &event_fader);
630         adpcm_volume = 0.0;
631         d_msm->set_volume((int)adpcm_volume);
632 }
633
634 void ADPCM::fade_out(int usec)
635 {
636         if(event_fader != -1) {
637                 cancel_event(this, event_fader);
638         }
639         register_event(this, EVENT_FADE_OUT, (double)usec, true, &event_fader);
640         adpcm_volume = 100.0;
641         d_msm->set_volume((int)adpcm_volume);
642 }
643         
644 void ADPCM::event_callback(int id, int err)
645 {
646         switch(id) {
647         case EVENT_CLEAR_ACK:
648                 event_ack = -1;
649                 d_pce->write_signal(SIG_PCE_CDROM_CLEAR_ACK, 0xff, 0xff);
650                 break;
651         case EVENT_SET_ACK:
652                 event_ack = -1;
653                 d_pce->write_signal(SIG_PCE_CDROM_SET_ACK, 0xff, 0xff);
654                 break;
655         case EVENT_FADE_IN:             
656                 if((adpcm_volume += 0.1) >= 100.0) {
657                         cancel_event(this, event_fader);
658                         event_fader = -1;
659                         adpcm_volume = 100.0;
660                 }
661                 d_msm->set_volume((int)adpcm_volume);
662                 break;
663         case EVENT_FADE_OUT:            
664                 if((adpcm_volume -= 0.1) <= 0.0) {
665                         cancel_event(this, event_fader);
666                         event_fader = -1;
667                         adpcm_volume = 0.0;
668                 }
669                 d_msm->set_volume((int)adpcm_volume);
670                 break;
671         }
672 }
673
674 void ADPCM::mix(int32_t* buffer, int cnt)
675 {
676         d_msm->mix(buffer, cnt);
677 }
678
679 #define STATE_VERSION   7
680
681 bool ADPCM::process_state(FILEIO* state_fio, bool loading)
682 {
683         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
684                 return false;
685         }
686         if(!state_fio->StateCheckInt32(this_device_id)) {
687                 return false;
688         }
689         state_fio->StateValue(addr_reg);
690         state_fio->StateValue(reg_0b);
691         state_fio->StateValue(reg_0c);
692         state_fio->StateValue(msm_last_cmd);
693         
694         state_fio->StateBuffer(ram, sizeof(ram), 1);
695         
696         state_fio->StateValue(read_ptr);
697         state_fio->StateValue(read_buf);
698         state_fio->StateValue(write_ptr);
699         state_fio->StateValue(write_buf);
700         
701         state_fio->StateValue(msm_data);
702         state_fio->StateValue(msm_ptr);
703         state_fio->StateValue(msm_nibble);
704         state_fio->StateValue(msm_length);
705         state_fio->StateValue(half_addr);
706         state_fio->StateValue(adpcm_length);
707         
708         state_fio->StateValue(written_size);
709         state_fio->StateValue(dma_enabled);
710         state_fio->StateValue(play_in_progress);
711         state_fio->StateValue(adpcm_paused);
712         state_fio->StateValue(adpcm_stream);
713         state_fio->StateValue(adpcm_repeat);
714         state_fio->StateValue(adpcm_stopped);   
715         state_fio->StateValue(adpcm_volume);
716         state_fio->StateValue(event_fader);
717         state_fio->StateValue(event_ack);
718
719         return true;
720 }
721
722 }
723