OSDN Git Service

[VM][PCENGINE][ADPCM] Re-Implement adpcm.[cpp|h] . Partly useful.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Tue, 12 Feb 2019 10:21:48 +0000 (19:21 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Tue, 12 Feb 2019 10:21:48 +0000 (19:21 +0900)
source/src/vm/pcengine/adpcm.cpp
source/src/vm/pcengine/adpcm.h
source/src/vm/pcengine/pce.cpp
source/src/vm/pcengine/pcengine.h

index f4a3d17..fc068d2 100644 (file)
@@ -49,43 +49,9 @@ void ADPCM::initialize()
 
 void ADPCM::reset()
 {
-       touch_sound();
-
-       read_ptr = write_ptr = 0;
-       read_buf = write_buf = 0;
        written_size = 0;
-       dma_enabled = false;
-       play_in_progress = false;
-       adpcm_paused = false;
-       
-       msm_data = 0x00;
-       msm_ptr = 0;
-       msm_nibble = 0;
-       msm_length = 0;
-       
-       adpcm_length = 0;
-       addr_reg.w = 0;
-       half_addr = 0;
-       msm_last_cmd = 0;
-       reg_0b = 0;
-       adpcm_stream = false;
-       adpcm_stopped = true;   
-       if(event_fader != -1) {
-               cancel_event(this, event_fader);
-       }
-       event_fader = -1;
-       if(event_ack != -1) {
-               cancel_event(this, event_ack);
-       }
-       event_ack = -1;
-       
-       reg_0c |= ADPCM_STOP_FLAG;
-       reg_0c &= ~ADPCM_PLAY_FLAG;
-       
-       //d_msm->change_clock_w((ADPCM_CLOCK / 6) / adpcm_clock_divider);  // From mednafen 1.22.1
-       //adpcm_volume = 0.0;
-       d_msm->set_volume((int)adpcm_volume);
-       //memset(ram, 0x00, sizeof(ram));
+
+       reset_adpcm();
 }
 
 uint32_t ADPCM::read_signal(int ch)
@@ -93,14 +59,15 @@ uint32_t ADPCM::read_signal(int ch)
        switch(ch) {
        case SIG_ADPCM_DATA:
                if(read_buf > 0) {
-                       reg_0c |= ADPCM_REMAIN_READ_BUF;
+                       // Don't need to modify FLAGS 20190212 K.O
+//                     reg_0c |= ADPCM_REMAIN_READ_BUF;
                        read_buf--;
-                       if(read_buf == 0) {
-                               reg_0c &= ~ADPCM_REMAIN_READ_BUF;
-                       }
+//                     if(read_buf == 0) {
+//                             reg_0c &= ~ADPCM_REMAIN_READ_BUF;
+//                     }
                        return 0x00;
                } else {
-                       reg_0c &= ~ADPCM_REMAIN_READ_BUF;
+//                     reg_0c &= ~ADPCM_REMAIN_READ_BUF;
                        uint8_t _d = ram[read_ptr & 0xffff];
                        read_ptr = (read_ptr + 1) & 0xffff;
                        return _d;
@@ -139,22 +106,50 @@ void ADPCM::reset_adpcm()
        // reset ADPCM hardware
        read_ptr = write_ptr = 0;
        read_buf = write_buf = 0;
+       msm_data = 0x00;
        msm_ptr = half_addr = 0;
        msm_nibble = 0;
        msm_last_cmd = 0x00;
+       msm_length = 0x00;
+       
        addr_reg.w = 0x0000;
-       do_stop(false);
+       adpcm_length = 0;
+       half_addr = 0;
+
+       reg_0b = 0x00; // OK?
+       
+       adpcm_stream = false;
+       adpcm_repeat = false;
+       dma_enabled = false;
+       play_in_progress = false;
+       adpcm_paused = false;
+       
+       if(event_fader != -1) {
+               cancel_event(this, event_fader);
+       }
+       event_fader = -1;
+       if(event_ack != -1) {
+               cancel_event(this, event_ack);
+       }
+       event_ack = -1;
+       
+       reg_0c |= ADPCM_STOP_FLAG;
+       reg_0c &= ~ADPCM_PLAY_FLAG;
+       
+       do_stop(true);
+       set_dma_status(false);
        //d_msm->reset();
        d_msm->reset_w(1);
+       
+       //d_msm->change_clock_w((ADPCM_CLOCK / 6) / adpcm_clock_divider);  // From mednafen 1.22.1
+       //adpcm_volume = 0.0;
+       d_msm->set_volume((int)adpcm_volume);
+       //memset(ram, 0x00, sizeof(ram));
+       
        out_debug_log(_T("RESET ADPCM\n"));
        d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
        d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
-       msm_data = 0x00;
-       
-       // stop ADPCM dma
-       set_dma_status(false);
-       adpcm_repeat = false;
-       //adpcm_stream = false;
+
 }
 
 void ADPCM::do_play()
@@ -163,7 +158,6 @@ void ADPCM::do_play()
        reg_0c |= ADPCM_PLAY_FLAG;
        play_in_progress = true;
        adpcm_paused = false;
-       adpcm_stopped = false;
 }
 
 void ADPCM::do_pause(bool pause)
@@ -187,24 +181,22 @@ void ADPCM::do_pause(bool pause)
        }
 }
 
-void ADPCM::do_stop(bool do_irq)
+void ADPCM::do_stop(bool do_notify)
 {
+       touch_sound();
        reg_0c |= ADPCM_STOP_FLAG;
        reg_0c &= ~ADPCM_PLAY_FLAG;
-       if(do_irq) {
-               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
-       }
        msm_last_cmd &= ~0x60;
        play_in_progress = false;
-       //set_dma_status(false);
-       out_debug_log(_T("ADPCM STOP PLAY PTR=%04x IRQ=%s\n"), msm_ptr, (do_irq) ? _T("YES") : _T("NO"));
+       if(do_notify) set_dma_status(false);
+       out_debug_log(_T("ADPCM STOP PLAY PTR=%04x DMA CLEAR=%s\n"), msm_ptr, (do_notify) ? _T("YES") : _T("NO"));
        
 }
 
 void ADPCM::set_dma_status(bool flag)
 {
        dma_enabled = flag;
-       //d_pce->write_signal(SIG_PCE_ADPCM_DMA, (flag) ? 0xffffffff : 0x00000000, 0xffffffff);
+       d_pce->write_signal(SIG_PCE_ADPCM_DMA, (flag) ? 0xffffffff : 0x00000000, 0xffffffff);
 }
 
 void ADPCM::write_signal(int ch, uint32_t data, uint32_t mask)
@@ -246,51 +238,54 @@ void ADPCM::write_signal(int ch, uint32_t data, uint32_t mask)
                do_dma(data);
                break;
        case SIG_ADPCM_DO_DMA_TRANSFER:
-               if((play_in_progress) && !(adpcm_paused) && ((write_ptr & 0xffff) >= (msm_ptr & 0xffff))) {
+               if((play_in_progress) && ((write_ptr & 0xffff) >= (msm_ptr & 0xffff))) {
                        // now streaming, wait dma not to overwrite buffer before it is played
                        reg_0b = 0x00;// From Ootake v2.38.
-                       set_dma_status(false);  // DON'T MODIFY PCE's DMA STATUS (HACK by K.O 20190212)
+                       //set_dma_status(false);  // DON'T MODIFY PCE's DMA STATUS (HACK by K.O 20190212)
                } else {
                        set_dma_status(true);
                        do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
                }
                break;
-       case SIG_ADPCM_ADDR_HI: // REG $09
-               if((msm_last_cmd & 0x80) != 0) {
-                       break;
+       case SIG_ADPCM_FORCE_DMA_TRANSFER:
+               if(flag) {
+                       do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
                }
+               break;
+       case SIG_ADPCM_ADDR_HI: // REG $09
+               if((msm_last_cmd & 0x80) == 0) {
                addr_reg.b.h = data;
-               if((msm_last_cmd & 0x10) != 0) {
-                       adpcm_length = (uint32_t)(addr_reg.w);
-                       msm_length = adpcm_length;
-                       out_debug_log(_T("SET ADDRESS REGISTER HIGH ; UPDATE LENGTH TO %04x\n"), adpcm_length);
+                       if((msm_last_cmd & 0x10) != 0) {
+                               update_length();
+                               out_debug_log(_T("SET ADDRESS REGISTER HIGH ; UPDATE LENGTH TO %04x\n"), adpcm_length);
+                       }
                }
                break;
        case SIG_ADPCM_ADDR_LO: // REG $08
-               if((msm_last_cmd & 0x80) != 0) {
-                       break;
-               }
-               addr_reg.b.l = data;
-               if((msm_last_cmd & 0x10) != 0) {
-                       adpcm_length = (uint32_t)(addr_reg.w);
-                       msm_length = adpcm_length;
-                       out_debug_log(_T("SET ADDRESS REGISTER LOW ; UPDATE LENGTH TO %04x\n"), adpcm_length);
+               if((msm_last_cmd & 0x80) == 0) {
+                       addr_reg.b.l = data;
+                       if((msm_last_cmd & 0x10) != 0) {
+                               update_length();
+                               out_debug_log(_T("SET ADDRESS REGISTER LOW ; UPDATE LENGTH TO %04x\n"), adpcm_length);
+                       }
                }
                break;
        case SIG_ADPCM_VCLK:
                do_vclk(flag);
                break;
        case SIG_ADPCM_DATA:
+               // Don't need to modify FLAGS 20190212 K.O
                if(write_buf > 0) {
-                       reg_0c |= ADPCM_REMAIN_WRITE_BUF;
+                       //reg_0c |= ADPCM_REMAIN_WRITE_BUF;
                        write_buf--;
-                       if(write_buf == 0) {
-                               reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
-                       }
+                       //if(write_buf == 0) {
+                       //      reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
+                       //}
                } else {
-                       reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
+                       //reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
                        ram[write_ptr & 0xffff] = data;
                        write_ptr = (write_ptr + 1) & 0xffff;
+                       //if(msm_length < 0x10000) msm_length++;
                        //written_size++;
                }
                break;
@@ -306,150 +301,130 @@ void ADPCM::write_signal(int ch, uint32_t data, uint32_t mask)
                break;
        case SIG_ADPCM_CLEAR_ACK:
                reg_0b &= 0xfc; // Clear status register.
-               dma_enabled = false;
                break;
        }
 }
-       
+
+void ADPCM::update_length()
+{
+       adpcm_length = (uint32_t)(addr_reg.w) & 0xffff; 
+       msm_length = adpcm_length;
+       out_debug_log(_T("ADPCM SET LENGTH TO %04x\n"), adpcm_length);
+}
+
 void ADPCM::do_cmd(uint8_t cmd)
 {
        // Register 0x0d.
        //out_debug_log(_T("ADPCM CMD=%02x\n"), cmd);
-       if(((cmd & 0x80) != 0) /*&& ((msm_last_cmd & 0x80) == 0)*/) {
+       if(((cmd & 0x80) != 0) && ((msm_last_cmd & 0x80) == 0)) {
                // Reset ADPCM
                reset_adpcm();
-               msm_init(); // SAMPLE = 0x800, SSIS=0
+               //msm_init(); // SAMPLE = 0x800, SSIS=0
                out_debug_log(_T("ADPCM CMD RESET\n"));
-               msm_last_cmd = cmd;
-               return;
+               //msm_last_cmd = cmd;
+               //return;
        }
        
-       if(((cmd & 0x02) != 0) /*&& ((msm_last_cmd & 0x02) == 0)*/) {
+       if(((cmd & 0x08) != 0) && ((msm_last_cmd & 0x08) == 0)) {
+               // ADPCM set read address
+               read_ptr = (uint32_t)(addr_reg.w) & 0xffff;
+               read_buf = ((cmd & 0x04) == 0) ? 2 : 1;
+               msm_ptr = read_ptr;
+               msm_ptr = ((cmd & 0x04) == 0) ? ((msm_ptr - 1) & 0xffff) : msm_ptr;
+               out_debug_log(_T("ADPCM SET READ ADDRESS ADDR=%04x BUF=%01x \n"), read_ptr, read_buf);
+       }
+       if(((cmd & 0x10) != 0) /*&& ((msm_last_cmd & 0x10) == 0)*/){
+               // ADPCM set length
+               update_length();
+       }
+       if(((cmd & 0x02) != 0) && ((msm_last_cmd & 0x02) == 0)) {
                // ADPCM set write address
-               write_ptr = (uint32_t)(addr_reg.w);
+               write_ptr = (uint32_t)(addr_reg.w) & 0xffff;
                write_buf = ((cmd & 0x01) == 0) ? 1 : 0;
-               written_size = 0; // OK?
                //write_ptr = (write_ptr - write_buf) & 0xffff;
+               //written_size = 0; // OK?
+               
+       }
+       if((cmd & 0x10) != 0) {
                // It's ugly... (;_;)
                uint32_t _clk = (ADPCM_CLOCK / 6) / adpcm_clock_divider;
                if(((read_ptr & 0xffff) >= 0x4000) &&
-                ((write_ptr & 0xffff) == 0x0000) &&
-                (adpcm_length != 0x8000) &&
-                (adpcm_length != 0xffff) &&
-                (_clk < 16000)) {
+                  ((write_ptr & 0xffff) == 0x0000) &&
+                  (adpcm_length != 0x8000) &&
+                  (adpcm_length != 0xffff) &&
+                  (_clk < 16000)) {
                        adpcm_length = adpcm_length & 0x7fff;
                }
                msm_length = adpcm_length;
-               out_debug_log(_T("ADPCM SET WRITE ADDRESS ADDR=%04x BUF=%01x \n"), write_ptr, write_buf);
-       }
-       if(((cmd & 0x08) != 0) /*&& ((msm_last_cmd & 0x08) == 0)*/) {
-               // ADPCM set read address
-               read_ptr = (uint32_t)(addr_reg.w);
-               read_buf = ((cmd & 0x04) == 0) ? 2 : 1;
-               //read_ptr = ((cmd & 0x04) == 0) ? ((read_ptr - 1) & 0xffff) : read_ptr;
-               msm_ptr = read_ptr;
-               out_debug_log(_T("ADPCM SET READ ADDRESS ADDR=%04x BUF=%01x \n"), read_ptr, read_buf);
+               out_debug_log(_T("ADPCM SET LENGTH LENGTH=%04x\n"), adpcm_length);
        }
-       if(((cmd & 0x10) != 0) /*&& ((msm_last_cmd & 0x10) == 0)*/){
-               // ADPCM set length
-               //d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
-               adpcm_stopped = false;
-               adpcm_length = (uint32_t)(addr_reg.w);
-               msm_length = adpcm_length;
-               out_debug_log(_T("ADPCM SET LENGTH TO %04x\n"), adpcm_length);
+       if(((cmd & 0x02) != 0) && ((msm_last_cmd & 0x02) == 0)) {
+               if((write_ptr == 0) || (write_ptr == 0x8000) || ((write_ptr & 0x1fff) == 0x1fff)) {
+                       if((((read_ptr + adpcm_length) & 0x1fff) == 0x1fff) ||
+                          ((read_ptr == 0) && (adpcm_length == 0x8000))) {
+                               adpcm_stream = true;
+                       }
+               }
+               out_debug_log(_T("ADPCM SET WRITE ADDRESS ADDR=%04x BUF=%01x STREAM=%s\n"), write_ptr, write_buf, (adpcm_stream) ? _T("YES") : _T("NO"));
        }
-       bool req_play = false;
-       bool req_play_0 =   ((cmd & 0x40) != 0) ? true : false;
+       //bool req_play = false;
+       bool req_play = play_in_progress;
        adpcm_repeat = ((cmd & 0x20) != 0) ? true : false;
                
-       if((play_in_progress) && !(adpcm_paused) && !(adpcm_repeat)) {
+       if((play_in_progress) && !(adpcm_stream) && !(adpcm_repeat)) {
                req_play = false;
        }
-       if(!(play_in_progress) && !(adpcm_paused) && (adpcm_repeat)) {
-               d_msm->change_clock_w((ADPCM_CLOCK / 6) / adpcm_clock_divider);  // From mednafen 1.22.1
-               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
+       if(!(play_in_progress) && (adpcm_repeat)) {
                req_play = true;
-               msm_nibble = 0;
-               msm_init(); // SAMPLE = 0x800, SSI=0
        }
-#if 1
-       if((play_in_progress) && !(adpcm_paused)) {
-               if(req_play) { // Update only
-                       msm_ptr = read_ptr & 0xffff;
-                       msm_nibble = 0;
-                       if(((adpcm_length & 0xffff) >= 0x8000) && ((adpcm_length & 0xffff) <= 0x80ff)) {
-                               half_addr = (read_ptr + 0x85) & 0xffff;
+       if((cmd & 0x40) != 0) {
+               req_play = true;
+       } else {
+               if(adpcm_stream) {
+                       if(written_size > 0x8000) {
+                               req_play = false;
                        } else {
-                               half_addr = (read_ptr + (adpcm_length >> 1)) & 0xffff;
+                               msm_last_cmd = cmd;
+                               return; // Exit from command. 20190212 K.O
                        }
-                       //do_pause(false);
-                       //
-               } else {
-                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
-                       d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
-                       adpcm_stream = false;
-                       adpcm_repeat = false;
                }
-       } else { // Not playing
-               if(req_play) {
-                       msm_ptr = read_ptr & 0xffff;
-                       half_addr = (msm_ptr + (adpcm_length / 2)) & 0xffff;
+       }
+       if(req_play) {
+//                             msm_start_addr = (adpcm_read_ptr) & 0xffff;
+               if(((cmd & 0x40) != 0) /*&& !(adpcm_play_in_progress)*/) {
+                       // ADPCM play
+                       half_addr = (read_ptr + ((adpcm_length + 1) >> 1)) & 0xffff;
                        write_ptr &= 0xffff;
+                       //written_size = 0; // OK?
                        msm_nibble = 0;
+                       play_in_progress = true;
                        do_play();
                        d_msm->reset_w(0);
+                       out_debug_log(_T("ADPCM START PLAY(%s) START=%04x LENGTH=%04x HALF=%04x STREAM=%s\n"), (dma_enabled) ? _T("DMA") : _T("PIO"), msm_ptr, msm_length, half_addr, (adpcm_stream) ? _T("YES") : _T("NO"));
                } else {
-                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
-                       d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
-                       adpcm_stream = false;
-                       adpcm_repeat = false;
-               }
-       }
-#else
-       if((req_play) && !(play_in_progress)) {
-               msm_ptr = read_ptr & 0xffff;
-               half_addr = (msm_ptr + ((adpcm_length + 1) / 2)) & 0xffff;
-               if(((adpcm_length & 0xffff) >= 0x8000) && ((adpcm_length & 0xffff) <= 0x80ff)) {
-                       half_addr = (read_ptr + 0x85) & 0xffff;
-               }
-               msm_nibble = 0;
-               do_play();
-               d_msm->reset_w(0);
-               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);
-       } else if((req_play) /*&& (cmd != msm_last_cmd)*/){
-               msm_ptr = read_ptr & 0xffff;
-               half_addr = (msm_ptr + (adpcm_length / 2)) & 0xffff;
-               if(((adpcm_length & 0xffff) >= 0x8000) && ((adpcm_length & 0xffff) <= 0x80ff)) {
-                       half_addr = (read_ptr + 0x85) & 0xffff;
-               } else {
-                       half_addr = (read_ptr + (adpcm_length >> 1)) & 0xffff;
+                       // 20181213 K.O: Import from Ootake v2.83.Thanks to developers of Ootake.
+                       if(((adpcm_length & 0xffff) >= 0x8000) && ((adpcm_length & 0xffff) <= 0x80ff)) {
+                               half_addr = (read_ptr + 0x85) & 0xffff;
+                       } else {
+                               half_addr = (read_ptr + ((adpcm_length + 1) >> 1)) & 0xffff;
+                       }
+                       out_debug_log(_T("ADPCM UPDATE HALF ADDRESS HALF=%04x\n"), half_addr);
                }
-               out_debug_log(_T("ADPCM UPDATE HALF ADDRESS HALF=%04x LENGTH=%04x\n"), half_addr, adpcm_length);
-       } else /*if(cmd != msm_last_cmd)*/ { // !req_play
+       
+       } else {
+               //set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
+               //      set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
+               adpcm_stream = false;
                adpcm_repeat = false;
-               if(play_in_progress && !(adpcm_paused)) {
-                       //adpcm_stopped = true;
-                       //play_in_progress = false;
-                       //d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
-                       //d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
-                       //do_stop(false);
-               }
-               //adpcm_stopped = true;
-               out_debug_log(_T("ADPCM STATUS UPDATE PLAY=%s\n"), (play_in_progress) ? _T("YES") : _T("NO"));                  
+               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00000000, 0xffffffff);
+               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
+               do_stop(false);
+               out_debug_log(_T("ADPCM STATUS UPDATE PLAY=%s\n"), (play_in_progress) ? _T("YES") : _T("NO"));
        }
-       // used by Buster Bros to cancel an in-flight sample
-       // if repeat flag (bit5) is high, ADPCM should be fully played (from Ootake)
-       //if(!(req_play) && !(adpcm_repeat)) {
-       //      d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
-       //      d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
-       //      do_stop(false);
-       //      d_msm->reset_w(1);
-       //}
-#endif
        msm_last_cmd = cmd;
-       
 }
 
+
 void ADPCM::msm_init()
 {
        //d_msm->reset();
@@ -461,136 +436,100 @@ void ADPCM::do_vclk(bool flag)
 {
        if((flag)) {
                {
-                       if((play_in_progress) && !(adpcm_paused) && (adpcm_length > 0)) {
-                               if(!((adpcm_length == 1) && ((msm_nibble & 1) == 0))) {
-                                       msm_data = (msm_nibble != 0) ? (ram[msm_ptr & 0xffff] & 0x0f) : ((ram[msm_ptr & 0xffff] & 0xf0) >> 4);
-                               }
+                       if((play_in_progress) && !(adpcm_paused)) {
+                               //if(!((adpcm_length == 1) && ((msm_nibble & 1) == 0))) {
+                               msm_data = (msm_nibble != 0) ? (ram[msm_ptr & 0xffff] & 0x0f) : ((ram[msm_ptr & 0xffff] & 0xf0) >> 4);
+                               //}
                                d_msm->data_w(msm_data);
                                msm_nibble ^= 1;
-                       }
-                       if((msm_nibble == 0) && (play_in_progress) && !(adpcm_paused)) {
-                               if((written_size > 0) /*&& !(adpcm_stopped)*/) written_size--;
-                               // Increment pointers.
-#if 0
-                               if((adpcm_length == 0) && ((msm_last_cmd & 0x10) == 0)){
-                                       d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
-                                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
-                                       if((msm_last_cmd & 0x40) != 0) {
-                                               do_stop(false);
-                                               d_msm->reset_w(1); 
-                                       }
-                                       adpcm_repeat = false;
-                                       adpcm_stream = false;
-                               } else {
-                                       if(adpcm_length > 0) adpcm_length--;
-                                       msm_ptr = (msm_ptr + 1) & 0xffff;
-                                       read_ptr = msm_ptr;
-                                       if((adpcm_repeat) && (msm_length >= 0x8000) && (msm_length <= 0x80ff)) {
-                                               if(msm_ptr == (half_addr & 0xffff)) {
-                                                       half_addr = (half_addr + 0x85) & 0xffff;
-                                                       d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
-                                                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
-                                               }
-                                               //out_debug_log(_T("PLAY PASSED TO THE HALF ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, msm_length);
-                                       } else if(msm_length < 0x7fff) {
-                                               if(msm_ptr == (half_addr & 0xffff)) {
-                                                       half_addr = (half_addr + (msm_length & 0xffff) - 1024) & 0xffff;
-                                                       d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
-                                                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
-                                               }
-                                               //out_debug_log(_T("PLAY PASSED TO THE HALF ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, msm_length);
-                                       } else {
-                                               if((msm_ptr == 0x8000) || (msm_ptr == 0x0000)) {
-                                                       d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
-                                                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
-                                               }
-                                       }
-                               }
-                                               
-#else
-                               if((adpcm_length == 0)) {
-                                       if((msm_last_cmd & 0x10) == 0) {
-                                               if(!(adpcm_stopped)) {
-                                                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x0, 0xffffffff);
+                               bool need_wait =false;
+                               if((msm_nibble == 0)) {
+                                       if((written_size > 0) /*&& !(adpcm_stopped)*/) written_size--;
+                                       // Increment pointers.
+                                       // 20181213 K.O: Re-order sequence from Ootake v2.83.Thanks to developers of Ootake.
+                                       if((msm_length == 0) && ((msm_last_cmd & 0x10) == 0)) {
+                                               if((adpcm_repeat) && ((adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff))) {
+                                                       need_wait = true;
+                                                       msm_length++;
+                                               } else {
+                                                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00000000, 0xffffffff);
                                                        d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
                                                        if((msm_last_cmd & 0x40) != 0) {
-                                                               do_stop(false);
-                                                               d_msm->reset_w(1); 
+                                                               do_stop(true); // true?
+                                                               d_msm->reset_w(1);
                                                        }
-                                                       out_debug_log(_T("PLAY REACHED TO THE END ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, adpcm_length);
-                                                       adpcm_stopped = true;
-                                               } else {
-                                                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x0, 0xffffffff);
+                                                       adpcm_stream = false;
+                                                       adpcm_repeat = false;
                                                }
                                        }
-                               } else  if((msm_ptr & 0xffff) == (half_addr & 0xffff)) {
-                                       //if(!(adpcm_stopped)) {
-                                       if((msm_last_cmd & 0x10) == 0) {
-                                               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
-                                               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x0, 0xffffffff);
-                                               out_debug_log(_T("PLAY PASSED TO THE HALF ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, adpcm_length);
+                          
+                               __skip0:
+                                       if(!(need_wait)) {
+                                               msm_ptr++;
+                                               msm_ptr = msm_ptr & 0xffff;
+                                               read_ptr = msm_ptr;
+                                               if(msm_length > 0) msm_length--;
+                                               if(msm_length >= 0x10000) msm_length = 0xffff;
+                                               if((adpcm_repeat) && (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff)) {
+                                                       if(msm_ptr == (half_addr & 0xffff)) {
+                                                               half_addr = half_addr + 0x85;
+                                                               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
+                                                               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00000000, 0xffffffff);
+                                                       }                                               
+                                               } else if(adpcm_length < 0x7fff) {
+                                                       if(msm_ptr == (half_addr & 0xffff)) {
+                                                               half_addr = half_addr + ((adpcm_length - 1024) & 0xffff);
+                                                               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
+                                                               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00000000, 0xffffffff);
+                                                       }                                               
+                                               } else if((msm_ptr == 0x8000) || (msm_ptr == 0x0000)) {
+                                                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
+                                                       d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00000000, 0xffffffff);
+                                               } /*else if((msm_length == 0) && ((msm_last_cmd & 0x10) == 0)){
+                                                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00000000, 0xffffffff);
+                                                       d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
+                                                       if((msm_last_cmd & 0x40) != 0) {
+                                                               do_stop(true); // true?
+                                                               d_msm->reset_w(1);
+                                                               adpcm_stream = false;
+                                                               adpcm_repeat = false;
+                                                       }
+                                                       }*/
+                                       
                                        }
-                                               //}
-                               }
 #if 1
-                               else if((!((dma_enabled) && (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff)) &&
-                                                  !(adpcm_length < 0x7fff)) &&
-                                                 (((msm_ptr & 0xffff) == 0x8000) || ((msm_ptr & 0xffff) == 0x0000))) {
-                                       // 20181213 K.O: Porting from Ootake v2.83.Thanks to developers of Ootake.
-                                       //set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
-                                       if((msm_last_cmd & 0x10) == 0) {
-                                               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
-                                               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x0, 0xffffffff);
-                                       }
-                                       out_debug_log(_T("SPECIAL HALF ADDRESS MSM_ADDR=%08x\n"), msm_ptr);
-                               }
-#endif
-                               if(!(adpcm_stopped)) {
-                                       msm_ptr = (msm_ptr + 1) & 0xffff;
-                                       read_ptr = msm_ptr;
-                               }
-                               if((msm_last_cmd & 0x10) == 0) {
-                                       if(adpcm_length > 0) {
-                                               adpcm_length--;
-                                       } else {
-                                               if(!(adpcm_stopped)) {
-                                                       if((msm_last_cmd & 0x10) == 0) {
-                                                               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x0, 0xffffffff);
-                                                               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
-                                                               if((msm_last_cmd & 0x40) != 0) {
-                                                                       do_stop(false);
-                                                               }
-                                                               out_debug_log(_T("PLAY REACHED TO THE END2 ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, adpcm_length);
-                                                       adpcm_stopped = true;
+                       __skip1:
+                                       if(dma_enabled) {
+                                               if((write_ptr & 0xffff) < (msm_ptr & 0xffff)) { 
+                                                       if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
+                                                               //do_pause(false); // Unpause if paused && data in.
+                                                               do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
                                                        }
                                                }
+                                       } else {
                                        }
-                               }
 #endif
-                       
-#if 1
-                       __skip1:
-                               if((dma_enabled) /*&& (written_size <= 0) && !(adpcm_stopped)*/) {
+                               } else { // nibble = 1
+                               }
+                       } else {
+                               if((dma_enabled) && (play_in_progress)) {
                                        if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
                                                //do_pause(false); // Unpause if paused && data in.
                                                do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
                                        }
-                               } else {
-                                                       
                                }
-#endif
-                       } else { // nibble = 1
                        }
                }
        }
 }
-       
+
 bool ADPCM::do_dma(uint8_t data)
 {
        ram[write_ptr & 0xffff] = data;
        write_ptr = (write_ptr + 1) & 0xffff;
        written_size = (written_size + 1) & 0xffff;;
-       //set_ack(0);
+       //if(msm_length < 0x10000) msm_length++;
+       set_ack(0);
 
        reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
        return true;
@@ -711,7 +650,6 @@ bool ADPCM::process_state(FILEIO* state_fio, bool loading)
        state_fio->StateValue(adpcm_paused);
        state_fio->StateValue(adpcm_stream);
        state_fio->StateValue(adpcm_repeat);
-       state_fio->StateValue(adpcm_stopped);   
        state_fio->StateValue(adpcm_volume);
        state_fio->StateValue(event_fader);
        state_fio->StateValue(event_ack);
index 722a885..0aed6b9 100644 (file)
@@ -38,7 +38,7 @@
 #define SIG_ADPCM_SET_DIVIDER      15
 #define SIG_ADPCM_CMD_REG          16
 #define SIG_ADPCM_CLEAR_ACK        17
-
+#define SIG_ADPCM_FORCE_DMA_TRANSFER 18
 class MSM5205;
 
 namespace PCEDEV {
@@ -68,7 +68,6 @@ protected:
        bool dma_enabled;
        bool adpcm_paused;
        bool adpcm_repeat;
-       bool adpcm_stopped;
        
        bool play_in_progress;
 
@@ -91,7 +90,8 @@ protected:
        void do_cmd(uint8_t cmd);
        void do_play();
        void do_pause(bool pause);
-       void do_stop(bool do_irq);
+       void do_stop(bool do_notify);
+       void update_length();
        void set_ack(int clocks);
        void clear_ack(int clocks);
        void set_dma_status(bool flag);
index 8c3f2d8..30998b1 100644 (file)
@@ -1869,6 +1869,7 @@ void PCE::cdrom_reset()
        adpcm_written = 0;
        msm_idle = 1;
        #ifdef USE_SEPARATED_ADPCM
+       adpcm_dma_enabled = false;
        d_adpcm->write_signal(SIG_ADPCM_DMA_ENABLED, 0x00, 0x03);
        #endif
        if(event_cdda_fader != -1) {
@@ -2031,7 +2032,7 @@ void PCE::cdrom_write(uint16_t addr, uint8_t data)
                {
                        uint8_t reg_bak = cdrom_regs[0x0d];
                        cdrom_regs[0x0d] = data;
-                       if(((reg_bak & 0x80) == 0) && (data & 0x80)) {
+                       if(((reg_bak & 0x80) == 0) && ((data & 0x80) != 0)) {
                                // Reset ADPCM hardware
                                reset_adpcm();
                                adpcm_stop(true);
@@ -2073,7 +2074,7 @@ void PCE::cdrom_write(uint16_t addr, uint8_t data)
                                                adpcm_stream = true;
                                        }
                                }
-                               out_debug_log(_T("ADPCM SET WRITE ADDRESS ADDR=%04x STREAM=%s\n"), adpcm_write_ptr, (adpcm_stream) ? _T("YES") : _T("NO"));
+                               out_debug_log(_T("ADPCM SET WRITE ADDRESS ADDR=%04x STREAM=%s\n"), write_ptr, (adpcm_stream) ? _T("YES") : _T("NO"));
                        }
                        if(data & 0x10) {
                                if(((adpcm_read_ptr & 0xffff) >= 0x4000) &&
@@ -2702,7 +2703,7 @@ void PCE::write_signal(int id, uint32_t data, uint32_t mask)
                } else {
                        if(/*!(adpcm_play_in_progress) && */(adpcm_dma_enabled)){
        #ifdef USE_SEPARATED_ADPCM
-                               d_adpcm->write_signal(SIG_ADPCM_DO_DMA_TRANSFER, 0xff, 0xff);
+                               d_adpcm->write_signal(SIG_ADPCM_FORCE_DMA_TRANSFER, 0xff, 0xff);
        #else
                                adpcm_do_dma();
        #endif
index b0757ed..37ac483 100644 (file)
@@ -39,7 +39,7 @@
 #define USE_JOY_BUTTON_CAPTIONS
 #define USE_DEBUGGER
 #define USE_STATE
-//#define USE_SEPARATED_ADPCM
+#define USE_SEPARATED_ADPCM
 
 #include "../../common.h"
 #include "../../fileio.h"