OSDN Git Service

[VM][PCENGINE][ADPCM] .
authorK.Ohta <whatisthis.sowhat@gmail.com>
Sun, 10 Feb 2019 17:40:55 +0000 (02:40 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Sun, 10 Feb 2019 17:40:55 +0000 (02:40 +0900)
source/src/vm/pcengine/adpcm.cpp
source/src/vm/pcengine/adpcm.h
source/src/vm/pcengine/pce.cpp

index 3b41639..2bdc7f9 100644 (file)
 
 namespace PCEDEV {
 
-#define PCE_CD_ADPCM_PLAY_FLAG         0x08
-#define PCE_CD_ADPCM_STOP_FLAG         0x01
+#define ADPCM_REMAIN_READ_BUF  0x80    
+#define ADPCM_REMAIN_WRITE_BUF 0x04    
+#define ADPCM_PLAY_FLAG                        0x08
+#define ADPCM_STOP_FLAG                        0x01
 
 #define EVENT_CLEAR_ACK 1
 #define EVENT_SET_ACK   2
@@ -34,12 +36,13 @@ namespace PCEDEV {
        
 void ADPCM::initialize()
 {
-       adpcm_clock_divider = 1;
+       adpcm_clock_divider = 1; // OK?
        event_fader = -1;
        event_ack = -1;
        reg_0c = 0;
        msm_last_cmd = 0;
        reg_0b = 0;
+       adpcm_volume = 0.0;
 
        memset(ram, 0x00, sizeof(ram));
 }
@@ -56,18 +59,14 @@ void ADPCM::reset()
        adpcm_paused = false;
        
        msm_ptr = 0;
-       msm_length = 0;
-       msm_end_addr = 0;
        msm_nibble = 0;
        adpcm_length = 0;
        addr_reg.w = 0;
        half_addr = 0;
-       reg_0c = 0;
        msm_last_cmd = 0;
        reg_0b = 0;
        adpcm_stream = false;
-       
-       adpcm_volume = 100.0;
+       adpcm_stopped = true;   
        if(event_fader != -1) {
                cancel_event(this, event_fader);
        }
@@ -77,9 +76,11 @@ void ADPCM::reset()
        }
        event_ack = -1;
        
-       reg_0c |= PCE_CD_ADPCM_STOP_FLAG;
-       reg_0c &= ~PCE_CD_ADPCM_PLAY_FLAG;
+       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));
 }
@@ -89,9 +90,14 @@ uint32_t ADPCM::read_signal(int ch)
        switch(ch) {
        case SIG_ADPCM_DATA:
                if(read_buf > 0) {
+                       reg_0c |= ADPCM_REMAIN_READ_BUF;
                        read_buf--;
+                       if(read_buf == 0) {
+                               reg_0c &= ~ADPCM_REMAIN_READ_BUF;
+                       }
                        return 0x00;
                } else {
+                       reg_0c &= ~ADPCM_REMAIN_READ_BUF;
                        uint8_t _d = ram[read_ptr & 0xffff];
                        read_ptr = (read_ptr + 1) & 0xffff;
                        return _d;
@@ -104,17 +110,7 @@ uint32_t ADPCM::read_signal(int ch)
                return ((play_in_progress) ? 0xffffffff : 0);
                break;
        case SIG_ADPCM_STATUS_REG:
-               {
-                       uint8_t data = reg_0c;
-                       if(play_in_progress) {
-                               data = data & ~0x85;
-                               data = data | 0x08;
-                       } else {
-                               data = data | 0x01;
-                               data = data & ~0x0c;
-                       }
-                       return data;
-               }
+               return reg_0c;
                break;
        case SIG_ADPCM_CMD_REG:
                return msm_last_cmd;
@@ -128,34 +124,37 @@ void ADPCM::reset_adpcm()
        touch_sound();
        // reset ADPCM hardware
        read_ptr = write_ptr = 0;
-       msm_ptr = msm_end_addr = half_addr = 0;
+       msm_ptr = half_addr = 0;
        msm_nibble = 0;
        do_stop(false);
        //d_msm->reset();
        d_msm->reset_w(1);
        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);
        
        // stop ADPCM dma
-       dma_enabled = false;
-       d_pce->write_signal(SIG_PCE_ADPCM_DMA, 0x00000000, 0xffffffff);
+       set_dma_status(false);
        adpcm_repeat = false;
        //adpcm_stream = false;
 }
 
 void ADPCM::do_play()
 {
-       reg_0c &= ~PCE_CD_ADPCM_STOP_FLAG;
-       reg_0c |= PCE_CD_ADPCM_PLAY_FLAG;
+       reg_0c &= ~ADPCM_STOP_FLAG;
+       reg_0c |= ADPCM_PLAY_FLAG;
        play_in_progress = true;
        adpcm_paused = false;
+       adpcm_stopped = false;
 }
 
 void ADPCM::do_pause(bool pause)
 {
+       if(!(play_in_progress)) return;
        if(pause) {
-               if((play_in_progress) && !(adpcm_paused)) {
-                       reg_0c |= PCE_CD_ADPCM_STOP_FLAG;
-                       reg_0c &= ~PCE_CD_ADPCM_PLAY_FLAG;
+               if(!(adpcm_paused)) {
+                       reg_0c |= ADPCM_STOP_FLAG;
+                       reg_0c &= ~ADPCM_PLAY_FLAG;
                        msm_last_cmd &= ~0x60;
                        adpcm_paused = true;
                        d_msm->reset_w(1);
@@ -166,12 +165,8 @@ void ADPCM::do_pause(bool pause)
                if((adpcm_paused)) {
                        adpcm_paused = false;
                        touch_sound();
-                       reg_0c &= ~PCE_CD_ADPCM_STOP_FLAG;
-                       reg_0c |= PCE_CD_ADPCM_PLAY_FLAG;
-                       if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
-                               do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
-                               reg_0c &= ~0x04;
-                       }
+                       reg_0c &= ~ADPCM_STOP_FLAG;
+                       reg_0c |= ADPCM_PLAY_FLAG;
                        d_msm->reset_w(0);
                        out_debug_log(_T("ADPCM UNPAUSE PLAY PTR=%04x\n"), msm_ptr);
                }
@@ -180,42 +175,50 @@ void ADPCM::do_pause(bool pause)
 
 void ADPCM::do_stop(bool do_irq)
 {
-       reg_0c |= PCE_CD_ADPCM_STOP_FLAG;
-       reg_0c &= ~PCE_CD_ADPCM_PLAY_FLAG;
+       reg_0c |= ADPCM_STOP_FLAG;
+       reg_0c &= ~ADPCM_PLAY_FLAG;
        if(do_irq) {
-               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
+               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
        }
        msm_last_cmd &= ~0x60;
        play_in_progress = false;
-       dma_enabled = false;
-       d_pce->write_signal(SIG_PCE_ADPCM_DMA, 0x00000000, 0xffffffff);
+       //set_dma_status(false);
        out_debug_log(_T("ADPCM STOP PLAY PTR=%04x IRQ=%s\n"), msm_ptr, (do_irq) ? _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);
+}
+
 void ADPCM::write_signal(int ch, uint32_t data, uint32_t mask)
 {
        bool flag = ((data & mask) != 0);
        //if(ch != SIG_ADPCM_VCLK) out_debug_log(_T("WRITE_SIGNAL SIG=%d DATA=%04x MASK=%04x\n"), ch, data, mask);
        switch(ch) {
        case SIG_ADPCM_DMACTRL:
+               //if((reg_0b & 0x01) != (data & 0x01)) {
+               //      set_dma_status((reg_0b & 0x01) != 0);
+                       //reg_0b |= 0x02;
+               //}
                reg_0b = data;
                break;
        case SIG_ADPCM_PAUSE:
                do_pause(flag);
                break;
        case SIG_ADPCM_DMA_ENABLED:
-               if((flag) && (flag != dma_enabled)) {
-                       reg_0c |= 0x04;
+               set_dma_status(flag);
+               if((flag)/* && (flag != dma_enabled)*/) {
+                       reg_0c |= ADPCM_REMAIN_WRITE_BUF;
                        if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
                                do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
                                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);
-                               reg_0c &= ~0x04;
                        } else {
                                out_debug_log(_T("Start DMA port $0B/WAIT FOR DATA\n"));
                        }
                }
-               dma_enabled = flag;
-               d_pce->write_signal(SIG_PCE_ADPCM_DMA, (flag) ? 0xffffffff : 0x00000000, 0xffffffff);
                break;
        case SIG_ADPCM_RESET:
                if(flag) {
@@ -230,28 +233,42 @@ void ADPCM::write_signal(int ch, uint32_t data, uint32_t mask)
                break;
        case SIG_ADPCM_DO_DMA_TRANSFER:
                if((play_in_progress) && ((write_ptr & 0xffff) >= (msm_ptr & 0xffff))) {
-                       reg_0b = 0x00;
+                       // now streaming, wait dma not to overwrite buffer before it is played
+                       reg_0b = 0x00;// From Ootake v2.38.
+                       //set_dma_status(false);
                } else {
                        do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
-                       reg_0c &= ~0x04;
                }
                break;
        case SIG_ADPCM_ADDR_HI: // REG $09
                addr_reg.b.h = data;
+               if((msm_last_cmd & 0x10) != 0) {
+                       adpcm_length = (uint32_t)(addr_reg.w);
+                       out_debug_log(_T("SET ADDRESS REGISTER HIGH ; UPDATE LENGTH TO %04x\n"), adpcm_length);
+               }
                break;
        case SIG_ADPCM_ADDR_LO: // REG $08
                addr_reg.b.l = data;
+               if((msm_last_cmd & 0x10) != 0) {
+                       adpcm_length = (uint32_t)(addr_reg.w);
+                       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:
                if(write_buf > 0) {
+                       reg_0c |= ADPCM_REMAIN_WRITE_BUF;
                        write_buf--;
+                       if(write_buf == 0) {
+                               reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
+                       }
                } else {
+                       reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
                        ram[write_ptr & 0xffff] = data;
                        write_ptr = (write_ptr + 1) & 0xffff;
-                       written_size++;
+                       //written_size++;
                }
                break;
        case SIG_ADPCM_FADE_IN:
@@ -274,88 +291,87 @@ void ADPCM::do_cmd(uint8_t cmd)
        if(((cmd & 0x80) != 0) && ((msm_last_cmd & 0x80) == 0)) {
                // Reset ADPCM
                reset_adpcm();
-               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
-               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
                msm_init(); // SAMPLE = 0x800, SSI=0
                out_debug_log(_T("ADPCM CMD RESET\n"));
        }
+       bool req_play = false;
        bool req_play_0 =   ((cmd & 0x40) != 0) ? true : false;
        adpcm_repeat = ((cmd & 0x20) != 0) ? true : false;
        uint32_t _clk = (ADPCM_CLOCK / 6) / adpcm_clock_divider;
-       
+               
+       if((play_in_progress) && !(adpcm_repeat)) {
+               req_play = false;
+       }
+       if(!(play_in_progress) && (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);
+               req_play = true;
+               msm_nibble = 0;
+               msm_init(); // SAMPLE = 0x800, SSI=0
+       }
+       //if(req_play_0) {
+       //      req_play = true;
+       //} else {
+       //      if(/*(play_in_progress) && */(written_size > 0x8000)) {
+       //              req_play = true;
+       //      }
+       //}
        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);
-               out_debug_log(_T("ADPCM SET READ ADDRESS ADDR=%04x\n"), adpcm_length);
+               out_debug_log(_T("ADPCM SET LENGTH TO %04x\n"), adpcm_length);
        }
        
-       if(((cmd & 0x08) != 0) /*&& ((msm_last_cmd & 0x08) == 0)*/) {
+       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 = (read_ptr - (read_buf - 1)) & 0xffff;
+               read_ptr = ((cmd & 0x04) == 0) ? ((read_ptr - 1) & 0xffff) : read_ptr; 
                out_debug_log(_T("ADPCM SET READ ADDRESS ADDR=%04x BUF=%01x \n"), read_ptr, read_buf);
        }
-       if(((cmd & 0x02) != 0) /*&& ((msm_last_cmd & 0x02) == 0)*/) {
+       if(((cmd & 0x02) != 0) && ((msm_last_cmd & 0x02) == 0)) {
                // ADPCM set write address
                write_ptr = (uint32_t)(addr_reg.w);
                write_buf = ((cmd & 0x01) == 0) ? 1 : 0;
                written_size = 0;
                write_ptr = (write_ptr - write_buf) & 0xffff;
                // It's ugly... (;_;)
-               if(((read_ptr & 0xffff) >= 0x4000) &&
-                  ((write_ptr & 0xffff) == 0x0000) &&
-                  (adpcm_length != 0x8000) &&
-                  (adpcm_length != 0xffff) &&
-                  (_clk < 16000)) {
-                       adpcm_length = adpcm_length & 0x7fff;
-               }
+               //if(((read_ptr & 0xffff) >= 0x4000) &&
+               // ((write_ptr & 0xffff) == 0x0000) &&
+               // (adpcm_length != 0x8000) &&
+               // (adpcm_length != 0xffff) &&
+               // (_clk < 16000)) {
+               //      adpcm_length = adpcm_length & 0x7fff;
+               //}
                out_debug_log(_T("ADPCM SET WRITE ADDRESS ADDR=%04x BUF=%01x \n"), write_ptr, write_buf);
        }
-       bool req_play = false;
-       if((play_in_progress) && !(adpcm_repeat)) {
-               req_play = false;
-       }
-       if(!(play_in_progress) && (adpcm_repeat)) {
-               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
-               req_play = true;
-               msm_nibble = 0;
-               msm_init(); // SAMPLE = 0x800, SSI=0
-       }
-       if(req_play_0) {
-               req_play = true;
-       } else {
-               if(/*(adpcm_stream) && */(written_size > 0x8000)) {
-                       req_play = true;
-               }
-       }
-       if((req_play) && !(play_in_progress)) {
-               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
+       if((req_play) /*&& !(play_in_progress)*/) {
                msm_ptr = read_ptr & 0xffff;
-               msm_end_addr = (msm_ptr + adpcm_length) & 0xffff;
-               msm_length = adpcm_length;
-               half_addr = (msm_ptr + (msm_length / 2)) & 0xffff;
-               msm_nibble = 0;
-               do_play();
-               d_msm->reset_w(0);
-               out_debug_log(_T("ADPCM START PLAY(%s) START=%04x END=%04x HALF=%04x\n"), (dma_enabled) ? _T("DMA") : _T("PIO"), msm_ptr, msm_end_addr, half_addr);
-       } else if((req_play) /*&& (cmd != msm_last_cmd)*/){
+               half_addr = (msm_ptr + (adpcm_length / 2)) & 0xffff;
                if(((adpcm_length & 0xffff) >= 0x8000) && ((adpcm_length & 0xffff) <= 0x80ff)) {
                        half_addr = (read_ptr + 0x85) & 0xffff;
-                       msm_end_addr = (msm_end_addr + 0x85) & 0xffff;
-                       //half_addr = (msm_ptr + 0x85) & 0xffff;
-                       //msm_end_addr = (half_addr + 0x85) & 0xffff;
-               } else {
-                       half_addr = (read_ptr + (adpcm_length >> 1)) & 0xffff;
-                       msm_end_addr = (read_ptr + adpcm_length) & 0xffff;
-                       //half_addr = (msm_ptr + (adpcm_length >> 1)) & 0xffff;
-                       //msm_end_addr = (msm_ptr + adpcm_length) & 0xffff;
                }
-               out_debug_log(_T("ADPCM UPDATE HALF ADDRESS HALF=%04x END=%04x\n"), half_addr, msm_end_addr);
+               //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)*/){
+       //if(((adpcm_length & 0xffff) >= 0x8000) && ((adpcm_length & 0xffff) <= 0x80ff)) {
+       //              half_addr = (read_ptr + 0x85) & 0xffff;
+       //      } else {
+       //              half_addr = (read_ptr + (adpcm_length >> 1)) & 0xffff;
+       //      }
+       //      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
-               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
-               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
+               //msm_nibble = 0;
+               if(play_in_progress) {
+                       //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"));                  
        }
        msm_last_cmd = cmd;
@@ -371,38 +387,72 @@ void ADPCM::msm_init()
 
 void ADPCM::do_vclk(bool flag)
 {
-       if((flag) && (play_in_progress)) {
-               //if((msm_ptr & 0xffff) != (msm_end_addr & 0xffff)) {
-               if(play_in_progress) {
-                       uint8_t 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((written_size <= 0) && (dma_enabled)) {
-                               if(!(adpcm_paused)) {
-                                       do_pause(true);
-                                       return;
-                               }
-                       } else if((adpcm_paused) && (dma_enabled)) {
-                               if(written_size > 0) {
-                                       do_pause(false);
-                               } else {
-                                       return;
+       if((flag)) {
+               uint8_t msm_data;
+               {
+                       if(!(adpcm_stopped)) {
+                               msm_data = (msm_nibble != 0) ? (ram[msm_ptr & 0xffff] & 0x0f) : ((ram[msm_ptr & 0xffff] & 0xf0) >> 4);
+                               if(play_in_progress) {
+                                       d_msm->data_w(msm_data);
                                }
                        }
-                       
+                       msm_nibble ^= 1;
                        if(msm_nibble == 0) {
+                               if((written_size > 0) && !(adpcm_stopped)) written_size--;
                                // Increment pointers.
-                               written_size--;
-                               if((msm_ptr & 0xffff) == (msm_end_addr & 0xffff)) {
-                                       //if((adpcm_repeat) && (dma_enabled) &&
-                                       // (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff) /* && (IsHuVideo()) */) {
-                                       //      written_size++;
-                                       //      msm_ptr = (msm_ptr - 1) & 0xffff;
-                                               //goto __skip1;
-                                       //}
+                               if((adpcm_length == 0) && ((msm_last_cmd & 0x10) == 0)) {
+                                       if(!(adpcm_stopped)) {
+                                               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 END ADDR=%08x SIZE=%04x LENGTH=%04x\n"), msm_ptr, written_size, adpcm_length);
+                                       }
+                                       adpcm_stopped = true;
+                               } else  if((msm_ptr & 0xffff) == (half_addr & 0xffff)) {
+                                       if(!(adpcm_stopped)) {
+                                               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, adpcm_length);
+                                       }
+                               }                                       
+
+                               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)) {
+                                                       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;
+                                               }
+                                       }
+                               }
+#if 0
+                               if((adpcm_repeat) && (dma_enabled) &&
+                                  (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff) /* && (IsHuVideo()) */) {
+                                       written_size++;
+                                       msm_ptr = (msm_ptr - 1) & 0xffff;
+                                       goto __skip1;
+                               }
+
+                               if(adpcm_length > 0) adpcm_length--;
+                               if(written_size > 0) written_size--;
+                               if((dma_enabled) && (written_size < 0xffff)) {
+                                       if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
+                                               do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
+                                       }
+                               }
+                               if(adpcm_length == 0) {
                                        d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x0, 0xffffffff);
                                        d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
+                                       adpcm_stopped = true;
                                        out_debug_log(_T("PLAY PASSED TO THE FULL ADDR=%08x SIZE=%04x\n"), msm_ptr, written_size);
                                        do_stop(false);
                                } else if((msm_ptr & 0xffff) == half_addr) {
@@ -419,58 +469,33 @@ void ADPCM::do_vclk(bool flag)
                                        d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
                                        d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
                                } */else if((!((dma_enabled) && (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff)) &&
-                                                  !(adpcm_length < 0x7fff))) {
+                                                        !(adpcm_length < 0x7fff))) {
                                        if(((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);
                                                d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
                                                d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
+                                               adpcm_stopped = false;
                                                out_debug_log(_T("SPECIAL HALF ADDRESS MSM_ADDR=%08x\n"), msm_ptr);
                                        } else if(((msm_ptr & 0xffff) == 0x8001) || ((msm_ptr & 0xffff) == 0x0001)) {
                                                //d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x0, 0xffffffff);
                                        }
                                }
                                msm_ptr++;
-                                       
+#endif
+#if 1
+                       __skip1:
                                if(dma_enabled) {
                                        if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
                                                do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
-                                               reg_0c &= ~0x04;
                                        }
                                } else {
                                                        
                                }
-                       } else {
-//                             written_size--;
+#endif
+                       } else { // nibble = 1
                        }
-               } else if((msm_last_cmd & 0x10) != 0) { // Data empty?
-                       bool _nf = true;
-                       if(dma_enabled) {
-                               if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
-                                       do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
-                                       reg_0c &= ~0x04;
-                                       //_nf = false;
-                               }
-                       }
-                       if(_nf) {
-                               d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
-                               d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
-                               if((msm_last_cmd & 0x40) != 0) {
-                                       do_stop(false);
-                                       //play_in_progress = false;
-                                       out_debug_log(_T("PLAY REACHED TO THE END ADDR=%08x SIZE=%04x\n"), msm_ptr, written_size);
-                               }
-                       }
-               } else {
-                       d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00, 0xffffffff);
-                       d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
-                       if((msm_last_cmd & 0x40) != 0) {
-                               do_stop(false);
-                               //play_in_progress = false;
-                               out_debug_log(_T("PLAY REACHED TO THE END ADDR=%08x SIZE=%04x\n"), msm_ptr, written_size);
-                       }
-               }                       
-               
+               }
        }
 }
        
@@ -479,8 +504,9 @@ bool ADPCM::do_dma(uint8_t data)
        ram[write_ptr & 0xffff] = data;
        write_ptr = (write_ptr + 1) & 0xffff;
        written_size++;
-       d_pce->write_signal(SIG_PCE_CDROM_SET_ACK, 0x04, 0xff);
-       reg_0c &= ~0x04;
+       //set_ack(0);
+
+       reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
        return true;
 }
 
@@ -588,8 +614,6 @@ bool ADPCM::process_state(FILEIO* state_fio, bool loading)
        
        state_fio->StateValue(msm_ptr);
        state_fio->StateValue(msm_nibble);
-       state_fio->StateValue(msm_length);
-       state_fio->StateValue(msm_end_addr);
        state_fio->StateValue(half_addr);
        state_fio->StateValue(adpcm_length);
        
@@ -599,7 +623,7 @@ 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 bd9d205..f88e745 100644 (file)
@@ -57,8 +57,6 @@ protected:
        
        uint32_t msm_ptr;
        uint32_t msm_nibble;
-       uint32_t msm_length;
-       uint32_t msm_end_addr;
        uint32_t half_addr;
        uint32_t adpcm_length;
        bool adpcm_stream;
@@ -67,6 +65,8 @@ protected:
        bool dma_enabled;
        bool adpcm_paused;
        bool adpcm_repeat;
+       bool adpcm_stopped;
+       
        bool play_in_progress;
 
        double adpcm_volume;
@@ -91,6 +91,7 @@ protected:
        void do_stop(bool do_irq);
        void set_ack(int clocks);
        void clear_ack(int clocks);
+       void set_dma_status(bool flag);
        void fade_in(int usec);
        void fade_out(int usec);
        void reset_adpcm();
index d587a4d..41e6506 100644 (file)
@@ -1892,7 +1892,6 @@ void PCE::cdrom_write(uint16_t addr, uint8_t data)
                d_scsi_host->write_signal(SIG_SCSI_SEL, 1, 1);
                d_scsi_host->write_signal(SIG_SCSI_SEL, 0, 1);
        #ifdef USE_SEPARATED_ADPCM
-               adpcm_dma_enabled = false;
                d_adpcm->write_signal(SIG_ADPCM_DMA_ENABLED, 0x00, 0xff);
        #else
                adpcm_dma_enabled = false;
@@ -1934,14 +1933,13 @@ void PCE::cdrom_write(uint16_t addr, uint8_t data)
                        d_scsi_cdrom->write_signal(SIG_SCSI_CDROM_CDDA_STOP, 0xff, 0xff);
                        // Reset ADPCM hardware
        #ifdef USE_SEPARATED_ADPCM
-                       adpcm_dma_enabled = false;
-                       d_adpcm->write_signal(SIG_ADPCM_DMA_ENABLED, 0x00, 0xff);
                        d_adpcm->write_signal(SIG_ADPCM_RESET, 0xff, 0xff);
+                       d_adpcm->write_signal(SIG_ADPCM_DMA_ENABLED, 0x00, 0xff);
        #else
                        reset_adpcm();
                        adpcm_dma_enabled = false;
        #endif
-                       out_debug_log(_T("ADPCM CMD=$04 RESET\n"));
+                       out_debug_log(_T("CMD=$04 ADPCM RESET\n"));
                        cdrom_regs[0x03] = 0x00; // Reset IRQ status at al.
                        set_cdrom_irq_line(0x0, 0x0); // Update IRQ
                }
@@ -1971,7 +1969,7 @@ void PCE::cdrom_write(uint16_t addr, uint8_t data)
                
        case 0x0a:  /* ADPCM RAM data port */
        #ifdef USE_SEPARATED_ADPCM
-                       d_adpcm->write_signal(SIG_ADPCM_DATA, data, 0xff);
+               d_adpcm->write_signal(SIG_ADPCM_DATA, data, 0xff);
        #else
                if(adpcm_write_buf > 0) {
                        adpcm_write_buf--;
@@ -1982,11 +1980,15 @@ void PCE::cdrom_write(uint16_t addr, uint8_t data)
                break;
                
        case 0x0b:  /* ADPCM DMA control */
+       #ifdef USE_SEPARATED_ADPCM
+               d_adpcm->write_signal(SIG_ADPCM_DMACTRL, data, 0xff);
+       #endif
                if(data & 3) {
                        /* Start CD to ADPCM transfer */
                        adpcm_dma_enabled = true;
        #ifdef USE_SEPARATED_ADPCM
                        d_adpcm->write_signal(SIG_ADPCM_DMA_ENABLED, 0xffffffff, 0xffffffff);
+                       data = d_adpcm->read_signal(SIG_ADPCM_DMACTRL);
        #else
                        cdrom_regs[0x0c] |= 0x04;
                        if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
@@ -2372,9 +2374,9 @@ uint8_t PCE::cdrom_read(uint16_t addr)
                break;
                
        case 0x0b:  /* ADPCM DMA control */
-       #ifdef USE_SEPARATED_ADPCM
-               data = d_adpcm->read_signal(SIG_ADPCM_DMACTRL);
-       #endif
+               //#ifdef USE_SEPARATED_ADPCM
+               //data = d_adpcm->read_signal(SIG_ADPCM_DMACTRL);
+               //#endif
                break;
                
        case 0x0c:  /* ADPCM status */
@@ -2522,7 +2524,12 @@ void PCE::clear_ack()
 {
        cdrom_regs[0x03] &= ~0x40; // From Ootake v2.38
        if(d_scsi_host->read_signal(SIG_SCSI_CD) != 0) {
-               cdrom_regs[0x0b] &= 0xfc;
+               //cdrom_regs[0x0b] &= 0xfc;
+               cdrom_regs[0x0b] &= ~1;
+       #ifdef USE_SEPARATED_ADPCM
+               d_adpcm->write_signal(SIG_ADPCM_DMACTRL, cdrom_regs[0x0b], 0xff);
+               d_adpcm->write_signal(SIG_ADPCM_DMA_ENABLED, cdrom_regs[0x0b], 0x03);
+       #endif
        }
        d_scsi_host->write_signal(SIG_SCSI_ACK, 0, 0);
 }
@@ -2681,7 +2688,9 @@ void PCE::write_signal(int id, uint32_t data, uint32_t mask)
                        set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_DONE, CLEAR_LINE);
                        if(/*!(adpcm_play_in_progress) && */(adpcm_dma_enabled)){
        #ifdef USE_SEPARATED_ADPCM
-                               d_adpcm->write_signal(SIG_ADPCM_PAUSE, 0xff, 0xff);
+                               //d_adpcm->write_signal(SIG_ADPCM_DMACTRL, cdrom_regs[0x0b], 0xff);
+                               //d_adpcm->write_signal(SIG_ADPCM_PAUSE, 0xff, 0xff);
+                               //cdrom_regs[0x0b] = d_adpcm->read_signal(SIG_ADPCM_DMACTRL);
        #else
                                adpcm_pause(true);
        #endif
@@ -2695,7 +2704,7 @@ void PCE::write_signal(int id, uint32_t data, uint32_t mask)
                                        d_adpcm->write_signal(SIG_ADPCM_DMACTRL, cdrom_regs[0x0b], 0xff);
                                        d_adpcm->write_signal(SIG_ADPCM_DO_DMA_TRANSFER, 0xff, 0xff);
                                        cdrom_regs[0x0b] = d_adpcm->read_signal(SIG_ADPCM_DMACTRL);
-                                       d_adpcm->write_signal(SIG_ADPCM_PAUSE, 0x00, 0xff);
+                                       //d_adpcm->write_signal(SIG_ADPCM_PAUSE, 0x00, 0xff);
                                }
        #else
                                if(adpcm_play_in_progress) {