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)
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;
data = data & ~0x85;
data = data | 0x08;
} else {
- data = data | 0x01;
data = data & ~0x0c;
+ data = data | 0x01;
}
+ d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x00000000, 0xffffffff);
return data;
}
break;
// 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;
+ dma_connected = 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()
reg_0c |= ADPCM_PLAY_FLAG;
play_in_progress = true;
adpcm_paused = false;
- adpcm_stopped = false;
}
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);
+ if(!(flag)) {
+ dma_connected = false;
+ }
+ d_pce->write_signal(SIG_PCE_ADPCM_DMA, (flag) ? 0xffffffff : 0x00000000, 0xffffffff);
}
void ADPCM::write_signal(int ch, uint32_t data, uint32_t mask)
case SIG_ADPCM_DMA_ENABLED:
set_dma_status(flag);
if((flag)/* && (flag != dma_enabled)*/) {
+ dma_connected = true;
reg_0c |= ADPCM_REMAIN_WRITE_BUF;
+ written_size = 0;
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);
do_dma(data);
break;
case SIG_ADPCM_DO_DMA_TRANSFER:
- if((play_in_progress) && !(adpcm_paused) && ((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)
- } else {
- set_dma_status(true);
- do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
+ //set_dma_status(true);
+ dma_connected = true;
+ do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
+ break;
+ case SIG_ADPCM_FORCE_DMA_TRANSFER:
+ if(flag) {
+ dma_connected = true;
+ if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
+ 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_DMA_RELEASED:
+ if(flag) {
+ dma_connected = false;
}
+ 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;
ram[write_ptr & 0xffff] = data;
- write_ptr = (write_ptr + 1) & 0xffff;
- //written_size++;
+ write_ptr++;
}
break;
case SIG_ADPCM_FADE_IN:
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);
+ half_addr = (read_ptr + ((adpcm_length + 1) >> 1)) & 0xffff;
+ }
+ 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;
+ write_ptr = (write_ptr - write_buf) & 0xffff;
+ written_size = written_size & 0xffff; // OK?
+ //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;
}
+ half_addr = (read_ptr + ((adpcm_length + 1) >> 1)) & 0xffff;
msm_length = adpcm_length;
- out_debug_log(_T("ADPCM SET WRITE ADDRESS ADDR=%04x BUF=%01x \n"), write_ptr, write_buf);
+ out_debug_log(_T("ADPCM SET LENGTH LENGTH=%04x\n"), adpcm_length);
}
- 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);
- }
- 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 & 0xffff) == 0) || ((write_ptr & 0xffff) == 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) /*&& !(play_in_progress) */) {
+ // ADPCM play
+ half_addr = (read_ptr + ((adpcm_length + 1) >> 1)) & 0xffff;
write_ptr &= 0xffff;
+ //msm_ptr = msm_ptr & 0xffff;
+ msm_ptr = read_ptr;
msm_nibble = 0;
+ play_in_progress = true;
+ msm_length = adpcm_length; // OK?
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;
+ // 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);
}
- 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;
+
+ } 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);
+ if(play_in_progress) {
+ 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);
+ return;
+ }
}
- 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
+ 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"));
+ out_debug_log(_T("ADPCM STATUS UPDATE / STOP\n"));
}
- // 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();
void ADPCM::do_vclk(bool flag)
{
+ bool need_wait =false;
if((flag)) {
+ // 20190216 K.O: Must wait when dma enabled and PCM data will empty, when DMA transferring.
+ if((play_in_progress) && !(adpcm_paused)) {
+ if(((dma_enabled ) && (dma_connected)) &&
+ ((written_size < 0x10) /*&& (msm_length > 0)*/
+ /*&& ((write_ptr & 0xffff) <= (msm_ptr & 0xffff))*/)) { // OK?
+ // ToDo: exception
+ d_msm->pause_w(1);
+ //d_msm->reset_w(1);
+ return;
+ }
+ }
{
- 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)) {
+ d_msm->pause_w(0);
+ //d_msm->reset_w(0);
+ //if(dma_enabled) {
+ 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);
+ if((msm_nibble == 0)) {
+ // Increment pointers.
+ // 20181213 K.O: Re-order sequence from Ootake v2.83.Thanks to developers of Ootake.
+ //if(need_wait) goto __skip0;
+ 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(false); // 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);
- }
- //}
- }
-#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);
+
+ if((written_size > 0) /*&& !(adpcm_stopped)*/) written_size--;
+
+ __skip0:
+ if(!(need_wait)) {
+
+ msm_ptr++;
+ read_ptr = msm_ptr & 0xffff;
+ if(msm_length > 0) msm_length--;
+ if((adpcm_repeat) && (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff)) {
+ if((msm_ptr & 0xffff) == (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 & 0xffff) == (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 & 0xffff) == 0x8000) || ((msm_ptr & 0xffff) == 0x0000)) {
+ d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
+ d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00000000, 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;
+
+ // 20190216 K.O: DO NOT DMA WITHIN VCLK.MUST DO ONLY BY DRQ.
+#if 0
+ if(written_size <= 0x10) {
+ if((dma_connected) && (dma_enabled)) {
+ if(d_pce->read_signal(SIG_PCE_CDROM_DATA_IN) != 0) {
+ do_dma(d_pce->read_signal(SIG_PCE_CDROM_RAW_DATA));
}
}
}
- }
#endif
-
-#if 1
- __skip1:
- if((dma_enabled) /*&& (written_size <= 0) && !(adpcm_stopped)*/) {
- 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 {
-
+// __skip1:
+ } else { // nibble = 1
}
-#endif
- } else { // nibble = 1
+ } else {
}
}
}
}
-
+
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);
+ write_ptr = write_ptr + 1;
+ if(written_size < 0) written_size = 0;
+ written_size = written_size + 1;
+ if(written_size >= 0x10000) written_size = 0x10000;
+ msm_length++;
+ //msm_length &= 0xffff;
+ //if(msm_length > 0x10000) msm_length = 0x10000;
+ set_ack(0);
reg_0c &= ~ADPCM_REMAIN_WRITE_BUF;
return true;
state_fio->StateValue(written_size);
state_fio->StateValue(dma_enabled);
+ state_fio->StateValue(dma_connected);
state_fio->StateValue(play_in_progress);
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);