if(BUILD_X1TWIN)
add_library(vm_pcengine
pce.cpp
+
)
else()
add_library(vm_pcengine
- pce.cpp
+ pce.cpp
+ adpcm.cpp
pcengine.cpp
)
-endif()
\ No newline at end of file
+endif()
--- /dev/null
+/*
+ NEC-HE PC Engine Emulator 'ePCEngine'
+ SHARP X1twin Emulator 'eX1twin'
+
+ Origin : Ootake (joypad/cdrom)
+ : xpce (psg)
+ : MESS (vdc/vce/vpc/cdrom)
+ Author : Takeda.Toshiya
+ Date : 2009.03.11-
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.02.09- Split from pce.cpp
+
+ [ PC-Engine around ADPCM]
+*/
+
+#include "./adpcm.h"
+#include "./pce.h"
+
+
+#include "../msm5205.h"
+#include "../scsi_host.h"
+#include "../scsi_cdrom.h"
+
+
+namespace PCEDEV {
+
+#define PCE_CD_ADPCM_PLAY_FLAG 0x08
+#define PCE_CD_ADPCM_STOP_FLAG 0x01
+
+#define EVENT_CLEAR_ACK 1
+#define EVENT_SET_ACK 2
+#define EVENT_FADE_IN 3
+#define EVENT_FADE_OUT 4
+
+void ADPCM::initialize()
+{
+ adpcm_clock_divider = 1;
+ event_fader = -1;
+ event_ack = -1;
+ reg_0c = 0;
+ msm_last_cmd = 0;
+ reg_0b = 0;
+
+ memset(ram, 0x00, sizeof(ram));
+}
+
+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_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;
+ 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 |= PCE_CD_ADPCM_STOP_FLAG;
+ reg_0c &= ~PCE_CD_ADPCM_PLAY_FLAG;
+
+ d_msm->set_volume((int)adpcm_volume);
+ //memset(ram, 0x00, sizeof(ram));
+}
+
+uint32_t ADPCM::read_signal(int ch)
+{
+ switch(ch) {
+ case SIG_ADPCM_DATA:
+ if(read_buf > 0) {
+ read_buf--;
+ return 0x00;
+ } else {
+ uint8_t _d = ram[read_ptr & 0xffff];
+ read_ptr = (read_ptr + 1) & 0xffff;
+ return _d;
+ }
+ break;
+ case SIG_ADPCM_DMACTRL:
+ return reg_0b;
+ break;
+ case SIG_ADPCM_PLAY_IN_PROGRESS:
+ 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;
+ }
+ break;
+ case SIG_ADPCM_CMD_REG:
+ return msm_last_cmd;
+ break;
+ }
+ return 0x00;
+}
+
+void ADPCM::reset_adpcm()
+{
+ touch_sound();
+ // reset ADPCM hardware
+ read_ptr = write_ptr = 0;
+ msm_ptr = msm_end_addr = half_addr = 0;
+ msm_nibble = 0;
+ do_stop(false);
+ //d_msm->reset();
+ d_msm->reset_w(1);
+ out_debug_log(_T("RESET ADPCM\n"));
+
+ // stop ADPCM dma
+ dma_enabled = false;
+ d_pce->write_signal(SIG_PCE_ADPCM_DMA, 0x00000000, 0xffffffff);
+ adpcm_repeat = false;
+ //adpcm_stream = false;
+}
+
+void ADPCM::do_play()
+{
+ reg_0c &= ~PCE_CD_ADPCM_STOP_FLAG;
+ reg_0c |= PCE_CD_ADPCM_PLAY_FLAG;
+ play_in_progress = true;
+ adpcm_paused = false;
+}
+
+void ADPCM::do_pause(bool pause)
+{
+ if(pause) {
+ if((play_in_progress) && !(adpcm_paused)) {
+ reg_0c |= PCE_CD_ADPCM_STOP_FLAG;
+ reg_0c &= ~PCE_CD_ADPCM_PLAY_FLAG;
+ msm_last_cmd &= ~0x60;
+ adpcm_paused = true;
+ d_msm->reset_w(1);
+ out_debug_log(_T("ADPCM PAUSE PLAY PTR=%04x\n"), msm_ptr);
+ touch_sound();
+ }
+ } else {
+ 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;
+ }
+ d_msm->reset_w(0);
+ out_debug_log(_T("ADPCM UNPAUSE PLAY PTR=%04x\n"), msm_ptr);
+ }
+ }
+}
+
+void ADPCM::do_stop(bool do_irq)
+{
+ reg_0c |= PCE_CD_ADPCM_STOP_FLAG;
+ reg_0c &= ~PCE_CD_ADPCM_PLAY_FLAG;
+ if(do_irq) {
+ d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
+ }
+ msm_last_cmd &= ~0x60;
+ play_in_progress = false;
+ dma_enabled = false;
+ d_pce->write_signal(SIG_PCE_ADPCM_DMA, 0x00000000, 0xffffffff);
+ out_debug_log(_T("ADPCM STOP PLAY PTR=%04x IRQ=%s\n"), msm_ptr, (do_irq) ? _T("YES") : _T("NO"));
+
+}
+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:
+ 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;
+ 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) {
+ reset_adpcm();
+ }
+ break;
+ case SIG_ADPCM_COMMAND: // REG $0D
+ do_cmd(data);
+ break;
+ case SIG_ADPCM_WRITE_DMA_DATA:
+ do_dma(data);
+ break;
+ case SIG_ADPCM_DO_DMA_TRANSFER:
+ if((play_in_progress) && ((write_ptr & 0xffff) >= (msm_ptr & 0xffff))) {
+ reg_0b = 0x00;
+ } 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;
+ break;
+ case SIG_ADPCM_ADDR_LO: // REG $08
+ addr_reg.b.l = data;
+ break;
+ case SIG_ADPCM_VCLK:
+ do_vclk(flag);
+ break;
+ case SIG_ADPCM_DATA:
+ if(write_buf > 0) {
+ write_buf--;
+ } else {
+ ram[write_ptr & 0xffff] = data;
+ write_ptr = (write_ptr + 1) & 0xffff;
+ written_size++;
+ }
+ break;
+ case SIG_ADPCM_FADE_IN:
+ fade_in(data);
+ break;
+ case SIG_ADPCM_FADE_OUT:
+ fade_out(data);
+ break;
+ case SIG_ADPCM_SET_DIVIDER:
+ adpcm_clock_divider = 0x10 - (data & 0x0f);
+ d_msm->change_clock_w((ADPCM_CLOCK / 6) / adpcm_clock_divider);
+ break;
+ }
+}
+
+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)) {
+ // 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_0 = ((cmd & 0x40) != 0) ? true : false;
+ adpcm_repeat = ((cmd & 0x20) != 0) ? true : false;
+ uint32_t _clk = (ADPCM_CLOCK / 6) / adpcm_clock_divider;
+
+ if(((cmd & 0x10) != 0) /*&& ((msm_last_cmd & 0x10) == 0)*/){
+ // ADPCM set length
+ d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
+ adpcm_length = (uint32_t)(addr_reg.w);
+ out_debug_log(_T("ADPCM SET READ ADDRESS ADDR=%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 = (read_ptr - (read_buf - 1)) & 0xffff;
+ 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)*/) {
+ // 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;
+ }
+ 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);
+ 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)*/){
+ 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);
+ } 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);
+ out_debug_log(_T("ADPCM STATUS UPDATE PLAY=%s\n"), (play_in_progress) ? _T("YES") : _T("NO"));
+ }
+ msm_last_cmd = cmd;
+
+}
+
+void ADPCM::msm_init()
+{
+ //d_msm->reset();
+ //d_msm->reset_w(1);
+ d_msm->reset_w(0);
+}
+
+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(msm_nibble == 0) {
+ // 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;
+ //}
+ d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0x0, 0xffffffff);
+ d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0xffffffff, 0xffffffff);
+ 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) {
+ // 20181213 K.O: Porting from Ootake v2.83.Thanks to developers of Ootake.
+ if((dma_enabled) && (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff)) {
+ half_addr = (half_addr + 0x85) & 0xffff;
+ } else if(adpcm_length < 0x7fff) {
+ half_addr = (half_addr + (uint16_t)(adpcm_length - 1024)) & 0xffff;
+ }
+ d_pce->write_signal(SIG_PCE_ADPCM_HALF, 0xffffffff, 0xffffffff);
+ d_pce->write_signal(SIG_PCE_ADPCM_FULL, 0x00, 0xffffffff);
+ out_debug_log(_T("PLAY PASSED TO THE HALF ADDR=%08x SIZE=%04x\n"), msm_ptr, written_size);
+ } /*else if((msm_ptr & 0xffff) == ((half_addr + 1) & 0xffff)) {
+ 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))) {
+ 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);
+ 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++;
+
+ 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--;
+ }
+ } 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);
+ }
+ }
+
+ }
+}
+
+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;
+ return true;
+}
+
+
+void ADPCM::set_ack(int clocks)
+{
+ if(event_ack != -1) cancel_event(this, event_ack);
+ event_ack = -1;
+ if(clocks <= 0) {
+ d_pce->write_signal(SIG_PCE_CDROM_SET_ACK, 0xff, 0xff);
+ } else {
+ double us = (((double)clocks) * 1.0e6) / ((double)CPU_CLOCKS);
+ register_event(this, EVENT_SET_ACK, us, false, &event_ack);
+ }
+}
+
+void ADPCM::clear_ack(int clocks)
+{
+ if(event_ack != -1) cancel_event(this, event_ack);
+ event_ack = -1;
+ if(clocks <= 0) {
+ d_pce->write_signal(SIG_PCE_CDROM_CLEAR_ACK, 0xff, 0xff);
+ } else {
+ double us = (((double)clocks) * 1.0e6) / ((double)CPU_CLOCKS);
+ register_event(this, EVENT_CLEAR_ACK, us, false, &event_ack);
+ }
+}
+
+void ADPCM::fade_in(int usec)
+{
+ if(event_fader != -1) {
+ cancel_event(this, event_fader);
+ }
+ register_event(this, EVENT_FADE_IN, (double)usec, true, &event_fader);
+ adpcm_volume = 0.0;
+ d_msm->set_volume((int)adpcm_volume);
+}
+
+void ADPCM::fade_out(int usec)
+{
+ if(event_fader != -1) {
+ cancel_event(this, event_fader);
+ }
+ register_event(this, EVENT_FADE_OUT, (double)usec, true, &event_fader);
+ adpcm_volume = 100.0;
+ d_msm->set_volume((int)adpcm_volume);
+}
+
+void ADPCM::event_callback(int id, int err)
+{
+ switch(id) {
+ case EVENT_CLEAR_ACK:
+ event_ack = -1;
+ d_pce->write_signal(SIG_PCE_CDROM_CLEAR_ACK, 0xff, 0xff);
+ break;
+ case EVENT_SET_ACK:
+ event_ack = -1;
+ d_pce->write_signal(SIG_PCE_CDROM_SET_ACK, 0xff, 0xff);
+ break;
+ case EVENT_FADE_IN:
+ if((adpcm_volume += 0.1) >= 100.0) {
+ cancel_event(this, event_fader);
+ event_fader = -1;
+ adpcm_volume = 100.0;
+ }
+ d_msm->set_volume((int)adpcm_volume);
+ break;
+ case EVENT_FADE_OUT:
+ if((adpcm_volume -= 0.1) <= 0.0) {
+ cancel_event(this, event_fader);
+ event_fader = -1;
+ adpcm_volume = 0.0;
+ }
+ d_msm->set_volume((int)adpcm_volume);
+ break;
+ }
+}
+
+void ADPCM::mix(int32_t* buffer, int cnt)
+{
+ d_msm->mix(buffer, cnt);
+}
+
+#define STATE_VERSION 7
+
+bool ADPCM::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ state_fio->StateValue(addr_reg);
+ state_fio->StateValue(reg_0b);
+ state_fio->StateValue(reg_0c);
+ state_fio->StateValue(msm_last_cmd);
+
+ state_fio->StateBuffer(ram, sizeof(ram), 1);
+
+ state_fio->StateValue(read_ptr);
+ state_fio->StateValue(read_buf);
+ state_fio->StateValue(write_ptr);
+ state_fio->StateValue(write_buf);
+
+ 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);
+
+ state_fio->StateValue(written_size);
+ state_fio->StateValue(dma_enabled);
+ 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_volume);
+ state_fio->StateValue(event_fader);
+ state_fio->StateValue(event_ack);
+
+ return true;
+}
+
+}
+
--- /dev/null
+/*
+ NEC-HE PC Engine Emulator 'ePCEngine'
+ SHARP X1twin Emulator 'eX1twin'
+
+ Origin : Ootake (joypad/cdrom)
+ : xpce (psg)
+ : MESS (vdc/vce/vpc/cdrom)
+ Author : Takeda.Toshiya
+ Date : 2009.03.11-
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2019.02.09- Split from pce.cpp
+
+ [ PC-Engine around ADPCM]
+*/
+
+#ifndef _PCE_ADPCM_H_
+#define _PCE_ADPCM_H_
+
+#include "../vm.h"
+#include "../../emu.h"
+#include "../device.h"
+
+#define SIG_ADPCM_RESET 0
+#define SIG_ADPCM_DATA 1
+#define SIG_ADPCM_DMACTRL 2
+#define SIG_ADPCM_DMA_ENABLED 3
+#define SIG_ADPCM_WRITE_DMA_DATA 4
+#define SIG_ADPCM_DO_DMA_TRANSFER 5
+#define SIG_ADPCM_PLAY_IN_PROGRESS 6
+#define SIG_ADPCM_VCLK 7
+#define SIG_ADPCM_STATUS_REG 8
+#define SIG_ADPCM_COMMAND 9
+#define SIG_ADPCM_PAUSE 10
+#define SIG_ADPCM_FADE_IN 11
+#define SIG_ADPCM_FADE_OUT 12
+#define SIG_ADPCM_ADDR_HI 13
+#define SIG_ADPCM_ADDR_LO 14
+#define SIG_ADPCM_SET_DIVIDER 15
+#define SIG_ADPCM_CMD_REG 16
+
+class MSM5205;
+
+namespace PCEDEV {
+
+class PCE;
+
+class ADPCM : public DEVICE
+{
+protected:
+ PCE* d_pce;
+ MSM5205* d_msm;
+
+ uint32_t read_ptr;
+ uint32_t write_ptr;
+ uint32_t read_buf;
+ uint32_t write_buf;
+
+ 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;
+ int written_size;
+
+ bool dma_enabled;
+ bool adpcm_paused;
+ bool adpcm_repeat;
+ bool play_in_progress;
+
+ double adpcm_volume;
+
+ int adpcm_clock_divider;
+ int event_fader;
+ int event_ack;
+
+ pair16_t addr_reg;
+ uint8_t reg_0b;
+ uint8_t reg_0c;
+ uint8_t msm_last_cmd; // REG $0D
+
+ uint8_t ram[0x10000];
+
+ void do_vclk(bool flag);
+ void msm_init();
+ bool do_dma(uint8_t data);
+ void do_cmd(uint8_t cmd);
+ void do_play();
+ void do_pause(bool pause);
+ void do_stop(bool do_irq);
+ void set_ack(int clocks);
+ void clear_ack(int clocks);
+ void fade_in(int usec);
+ void fade_out(int usec);
+ void reset_adpcm();
+public:
+ ADPCM(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+ {
+ set_device_name(_T("PC-Engine CD-ROM^2 around ADPCM"));
+ }
+ ~ADPCM() { }
+
+ void initialize();
+ void reset();
+
+ uint32_t read_signal(int ch);
+ void write_signal(int ch, uint32_t data, uint32_t mask);
+
+ void event_callback(int id, int err);
+ void mix(int32_t* buffer, int cnt);
+ bool process_state(FILEIO* state_fio, bool loading);
+
+ void set_context_msm(MSM5205* dev)
+ {
+ d_msm = dev;
+ }
+
+ void set_context_pce(PCE* dev)
+ {
+ d_pce = dev;
+ }
+
+};
+
+}
+#endif
#include "../scsi_host.h"
#include "../scsi_cdrom.h"
#endif
-
+#ifdef USE_SEPARATED_ADPCM
+#include "./adpcm.h"
+#endif
#define STATE_VSW 0
#define STATE_VDS 1
#define STATE_VDW 2
}
#ifdef SUPPORT_CDROM
if(support_cdrom) {
+ #ifndef USE_SEPARATED_ADPCM
if(!msm_idle) {
d_msm->mix(buffer, cnt);
}
+ #endif
d_scsi_cdrom->mix(buffer, cnt);
}
#endif
d_scsi_host->write_signal(SIG_SCSI_SEL, 1, 1);
d_scsi_host->write_signal(SIG_SCSI_SEL, 0, 1);
#ifdef USE_SEPARATED_ADPCM
- d_adpcm->write_signal(SIG_PCE_ADPCM_DMA_ENABLED, 0x00, 0xff);
+ adpcm_dma_enabled = false;
+ d_adpcm->write_signal(SIG_ADPCM_DMA_ENABLED, 0x00, 0xff);
#else
adpcm_dma_enabled = false;
#endif
d_scsi_cdrom->write_signal(SIG_SCSI_CDROM_CDDA_STOP, 0xff, 0xff);
// Reset ADPCM hardware
#ifdef USE_SEPARATED_ADPCM
- d_adpcm->write_signal(SIG_PCE_ADPCM_RESET, 0xff, 0xff);
- d_adpcm->write_signal(SIG_PCE_ADPCM_DMA_ENABLED, 0x00, 0xff);
+ adpcm_dma_enabled = false;
+ d_adpcm->write_signal(SIG_ADPCM_DMA_ENABLED, 0x00, 0xff);
+ d_adpcm->write_signal(SIG_ADPCM_RESET, 0xff, 0xff);
#else
reset_adpcm();
adpcm_dma_enabled = false;
break;
case 0x08: /* ADPCM address (LSB) / CD data */
+ #ifdef USE_SEPARATED_ADPCM
+ d_adpcm->write_signal(SIG_ADPCM_ADDR_LO, data, 0xff);
+ #endif
+ break;
case 0x09: /* ADPCM address (MSB) */
+ #ifdef USE_SEPARATED_ADPCM
+ d_adpcm->write_signal(SIG_ADPCM_ADDR_HI, data, 0xff);
+ #endif
break;
case 0x0a: /* ADPCM RAM data port */
- if(adpcm_write_buf > 0) {
- adpcm_write_buf--;
- } else {
#ifdef USE_SEPARATED_ADPCM
d_adpcm->write_signal(SIG_ADPCM_DATA, data, 0xff);
#else
+ if(adpcm_write_buf > 0) {
+ adpcm_write_buf--;
+ } else {
write_adpcm_ram(data);
- #endif
}
+ #endif
break;
case 0x0b: /* ADPCM DMA control */
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);
+ #else
cdrom_regs[0x0c] |= 0x04;
if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
} else {
out_debug_log(_T("Start DMA port $0B/WAIT FOR DATA\n"));
}
+ #endif
} else {
//adpcm_dma_enabled = false;
}
+
break;
case 0x0c: /* ADPCM status */
break;
case 0x0d: /* ADPCM address control */
+ out_debug_log(_T("ADPCM CMD=%02x\n"), data);
+ #ifdef USE_SEPARATED_ADPCM
+ d_adpcm->write_signal(SIG_ADPCM_COMMAND, data, 0xff);
+ #else
{
uint8_t reg_bak = cdrom_regs[0x0d];
cdrom_regs[0x0d] = data;
msm_half_addr = (adpcm_read_ptr + (adpcm_length >> 1)) & 0xffff;
}
out_debug_log(_T("ADPCM UPDATE HALF ADDRESS HALF=%04x\n"), msm_half_addr);
+ adpcm_pause(false);
}
+
} else {
adpcm_stream = false;
adpcm_repeat = false;
set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
- out_debug_log(_T("ADPCM STATUS UPDATE PLAY=%s\n"), (adpcm_play_in_progress) ? _T("YES") : _T("NO")); if(adpcm_play_in_progress) {
- adpcm_stop(true);
- d_msm->reset_w(1);
- } else {
+ out_debug_log(_T("ADPCM STATUS UPDATE PLAY=%s\n"), (adpcm_play_in_progress) ? _T("YES") : _T("NO")); //if(adpcm_play_in_progress) {
+ // adpcm_stop(true);
+ // d_msm->reset_w(1);
+ //} else {
+ //adpcm_pause(true);
+ //d_msm->reset_w(1);
set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
- }
+ //}
}
// used by Buster Bros to cancel an in-flight sample
// if repeat flag (bit5) is high, ADPCM should be fully played (from Ootake)
d_msm->reset_w(1);
}*/
}
-
+ #endif
break;
case 0x0e: /* ADPCM playback rate */
+ #ifdef USE_SEPARATED_ADPCM
+ d_adpcm->write_signal(SIG_ADPCM_SET_DIVIDER, data, 0x0f);
+ #else
adpcm_clock_divider = 0x10 - (data & 0x0f);
d_msm->change_clock_w((ADPCM_CLOCK / 6) / adpcm_clock_divider);
+ #endif
break;
case 0x0f: /* ADPCM and CD audio fade timer */
switch(data & 0x0f) {
case 0x00: // CD-DA / ADPCM enable (100 msecs)
cdda_fade_in(100);
+ #ifdef USE_SEPARATED_ADPCM
+ d_adpcm->write_signal(SIG_ADPCM_FADE_IN, 100, 0xffffffff);
+ #else
adpcm_fade_in(100);
+ #endif
break;
case 0x01: // CD-DA enable (100 msecs)
cdda_fade_in(100);
case 0x08: // CD-DA short (1500 msecs) fade out / ADPCM enable
case 0x0c: // CD-DA short (1500 msecs) fade out / ADPCM enable
cdda_fade_out(1500);
+ #ifdef USE_SEPARATED_ADPCM
+ d_adpcm->write_signal(SIG_ADPCM_FADE_IN, 100, 0xffffffff);
+ #else
adpcm_fade_in(100);
+ #endif
break;
case 0x09: // CD-DA long (5000 msecs) fade out
cdda_fade_out(5000);
break;
case 0x0a: // ADPCM long (5000 msecs) fade out
+ #ifdef USE_SEPARATED_ADPCM
+ d_adpcm->write_signal(SIG_ADPCM_FADE_OUT, 5000, 0xffffffff);
+ #else
adpcm_fade_out(5000);
+ #endif
break;
case 0x0d: // CD-DA short (1500 msecs) fade out
cdda_fade_out(1500);
break;
case 0x0e: // ADPCM short (1500 msecs) fade out
+ #ifdef USE_SEPARATED_ADPCM
+ d_adpcm->write_signal(SIG_ADPCM_FADE_OUT, 1500, 0xffffffff);
+ #else
adpcm_fade_out(1500);
+ #endif
break;
}
}
break;
case 0x0a: /* ADPCM RAM data port */
+ #ifdef USE_SEPARATED_ADPCM
+ data = d_adpcm->read_signal(SIG_ADPCM_DATA);
+ #else
if(adpcm_read_buf > 0) {
adpcm_read_buf--;
data = 0x00;
} else {
data = read_adpcm_ram();
}
+ #endif
break;
case 0x0b: /* ADPCM DMA control */
+ #ifdef USE_SEPARATED_ADPCM
+ data = d_adpcm->read_signal(SIG_ADPCM_DMACTRL);
+ #endif
break;
case 0x0c: /* ADPCM status */
+ #ifdef USE_SEPARATED_ADPCM
+ data = d_adpcm->read_signal(SIG_ADPCM_STATUS_REG);
+ #else
// Hack from Ootake v2.83.
if((adpcm_play_in_progress) && (msm_idle == 0)){
data = data & ~0x85;
data = data | 0x01;
data = data & ~0x0c;
}
+ #endif
cdrom_regs[0x0c] = data;
// ToDo: HuVideo
//cdrom_regs[0x03] &= ~0x04;
d_msm->set_volume((int)(adpcm_volume = 100.0));
}
+uint32_t PCE::read_signal(int id)
+{
+ uint32_t data = 0;
+#ifdef USE_SEPARATED_ADPCM
+ switch(id) {
+ case SIG_PCE_CDROM_RAW_DATA:
+ data = read_cdrom_data();
+ set_ack();
+ //cdrom_regs[0x0c] &= ~0x04;
+ break;
+ case SIG_PCE_CDROM_DATA_IN:
+ {
+ uint8_t cmd = d_scsi_cdrom->get_cur_command();
+ if(((cmd == SCSI_CMD_READ6) || (cmd == SCSI_CMD_READ10) || (cmd == SCSI_CMD_READ12)) &&
+ d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
+ d_scsi_host->read_signal(SIG_SCSI_REQ) != 0 &&
+ d_scsi_host->read_signal(SIG_SCSI_CD ) == 0 &&
+ d_scsi_host->read_signal(SIG_SCSI_MSG) == 0 &&
+ d_scsi_host->read_signal(SIG_SCSI_IO ) != 0) {
+ return 0xffffffff;
+ }
+ }
+ break;
+ }
+#endif
+ return data;
+}
void PCE::write_signal(int id, uint32_t data, uint32_t mask)
{
switch(id) {
// clear busreq because next REQ signal is raised
d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
- // out_debug_log(_T("CDROM DRQ(ADPCM)\n"));
+ //out_debug_log(_T("CDROM DRQ(ADPCM)\n"));
+ #ifdef USE_SEPARATED_ADPCM
+ if(adpcm_dma_enabled) {
+ 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);
+ }
+ #else
if(adpcm_dma_enabled) {
if(!(msm_idle) && ((adpcm_write_ptr & 0xffff) >= (msm_start_addr & 0xffff))) {
// now streaming, wait dma not to overwrite buffer before it is played
adpcm_do_dma();
}
}
+ #endif
}
} else {
if(drq_status) {
set_cdrom_irq_line(PCE_CD_IRQ_TRANSFER_READY, CLEAR_LINE);
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);
+ #else
adpcm_pause(true);
+ #endif
//adpcm_dma_enabled = false;
out_debug_log(_T("SIG_PCE_SCSI_BSY: PAUSE ADPCM\n"));
}
} else {
if(/*!(adpcm_play_in_progress) && */(adpcm_dma_enabled)){
+ #ifdef USE_SEPARATED_ADPCM
+ {
+ 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);
+ }
+ #else
if(adpcm_play_in_progress) {
adpcm_do_dma();
adpcm_pause(false);
}
+ #endif
//adpcm_dma_enabled = false;
out_debug_log(_T("SIG_PCE_SCSI_BSY: UNPAUSE ADPCM\n"));
}
break;
case SIG_PCE_ADPCM_VCLK:
+ #ifdef USE_SEPARATED_ADPCM
+ d_adpcm->write_signal(SIG_ADPCM_VCLK, data, mask);
+ #else
// Callback for new data from the MSM5205.
// The PCE cd unit actually divides the clock signal supplied to
// the MSM5205. Currently we can only use static clocks for the
out_debug_log(_T("END ADDRESS(NON-DMA) MSM_ADDR=%08x\n"), msm_start_addr);
adpcm_stream = false;
adpcm_repeat = false;
- } else if(((msm_start_addr & 0xffff) == msm_end_addr) && (adpcm_written <= 0) && (adpcm_dma_enabled)) {
+ } else if(((msm_start_addr & 0xffff) == msm_end_addr) && (adpcm_dma_enabled)) {
// reached to end address
if((adpcm_repeat) &&
(adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff) /* && (IsHuVideo()) */) {
msm_start_addr = msm_start_addr - 1;
goto __skip1;
}
- if(adpcm_written == 0) {
+ /*if(adpcm_written == 0) */{
// restart streaming
set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
- set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
+ set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
//set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
out_debug_log(_T("END ADDRESS(DMA) MSM_ADDR=%08x\n"), msm_start_addr);
//msm_start_addr = msm_start_addr & 0xffff; // Continue
-#if 0
- if(!(adpcm_repeat)) {
- adpcm_stop(true); // true?
- d_msm->reset_w(1);
- } else {
- adpcm_stop(true);
- d_msm->reset_w(0);
- }
+#if 1
+ //if(!(adpcm_repeat)) {
+ adpcm_stop(true); // true?
+ d_msm->reset_w(1);
+ //} else {
+ //adpcm_pause(true);
+ //d_msm->reset_w(0);
+ //}
#endif
adpcm_stream = false;
adpcm_repeat = false;
}
- } else if(adpcm_dma_enabled && adpcm_written < 0) {
+ } else if(adpcm_dma_enabled && adpcm_written == 0) {
// finish streaming when all samples are played
set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
- set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
+ set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
out_debug_log(_T("ADPCM DMA QUEUE EMPTY MSM_ADDR=%08x\n"), msm_start_addr);
- adpcm_stop(false);
- d_msm->reset_w(1);
- adpcm_stream = false;
- adpcm_repeat = false;
- goto __skip1;
- } else if((msm_start_addr & 0xffff) == msm_half_addr) {
+ //adpcm_stop(true);
+ //d_msm->reset_w(1);
+ //adpcm_stream = false;
+ //adpcm_repeat = false;
+ //goto __skip1;
+ } else if((msm_start_addr & 0xffff) == msm_half_addr) {
// reached to half address
// 20181213 K.O: Porting from Ootake v2.83.Thanks to developers of Ootake.
if((adpcm_dma_enabled) && (adpcm_length >= 0x8000) && (adpcm_length <= 0x80ff)) {
!(adpcm_length < 0x7fff)) &&
(((msm_start_addr & 0xffff) == 0x8000) || ((msm_start_addr & 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);
+ //set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, ASSERT_LINE);
out_debug_log(_T("SPECIAL HALF ADDRESS MSM_ADDR=%08x\n"), msm_start_addr);
}
msm_start_addr++;
__skip1:
if(adpcm_dma_enabled) {
- if(!(msm_idle) && (adpcm_write_ptr < msm_start_addr)) {
+ if(((adpcm_write_ptr & 0xffff) < (msm_start_addr & 0xffff) )) {
if(d_scsi_cdrom->get_cur_command() == SCSI_CMD_READ6 &&
d_scsi_host->read_signal(SIG_SCSI_BSY) != 0 &&
d_scsi_host->read_signal(SIG_SCSI_REQ) != 0 &&
}
}
}
+ #endif
+ break;
+#ifdef USE_SEPARATED_ADPCM
+ case SIG_PCE_CDROM_SET_ACK:
+ if((data & mask) != 0) {
+ set_ack();
+ }
+ break;
+ case SIG_PCE_CDROM_CLEAR_ACK:
+ if((data & mask) != 0) {
+ clear_ack();
+ }
+ break;
+ case SIG_PCE_ADPCM_HALF:
+ if((data & mask) != 0) {
+ set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, ASSERT_LINE);
+ } else {
+ set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_HALF_PLAY, CLEAR_LINE);
+ }
+ break;
+ case SIG_PCE_ADPCM_FULL:
+ if((data & mask) != 0) {
+ set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, ASSERT_LINE);
+ } else {
+ set_cdrom_irq_line(PCE_CD_IRQ_SAMPLE_FULL_PLAY, CLEAR_LINE);
+ }
break;
+ case SIG_PCE_ADPCM_DMA:
+ if((data & mask) != 0) {
+ adpcm_dma_enabled = true;
+ } else {
+ adpcm_dma_enabled = false;
+ }
+ break;
+#endif
}
}
Author : Takeda.Toshiya
Date : 2009.03.11-
- [ PC-Eninge ]
+ [ PC-Engine ]
*/
#ifndef _PCE_H_
#include "../../emu.h"
#include "../device.h"
+
#ifdef SUPPORT_CDROM
#define SIG_PCE_SCSI_IRQ 0
#define SIG_PCE_SCSI_DRQ 1
#define SIG_PCE_ADPCM_VCLK 4
#endif
+#define SIG_PCE_CDROM_RAW_DATA 10
+#define SIG_PCE_CDROM_DATA_IN 11
+#define SIG_PCE_CDROM_SET_ACK 12
+#define SIG_PCE_CDROM_CLEAR_ACK 13
+#define SIG_PCE_ADPCM_HALF 14
+#define SIG_PCE_ADPCM_FULL 15
+#define SIG_PCE_ADPCM_DMA 16
+
+
#define VDC_WPF 684 /* width of a line in frame including blanking areas */
#define VDC_LPF 262 /* number of lines in a single frame */
#ifdef SUPPORT_CDROM
class SCSI_CDROM;
#endif
+#ifdef USE_SEPARATED_ADPCM
+namespace PCEDEV {
+ class ADPCM;
+}
+#endif
namespace PCEDEV {
typedef struct vdc_s {
SCSI_HOST* d_scsi_host;
SCSI_CDROM* d_scsi_cdrom;
#endif
-
+#ifdef USE_SEPARATED_ADPCM
+ ADPCM* d_adpcm;
+#endif
bool support_6btn_pad;
bool support_multi_tap;
#ifdef SUPPORT_SUPER_GFX
void write_io8(uint32_t addr, uint32_t data);
uint32_t read_io8(uint32_t addr);
#ifdef SUPPORT_CDROM
+ uint32_t read_signal(int id);
void write_signal(int id, uint32_t data, uint32_t mask);
void event_callback(int event_id, int err);
#endif
d_scsi_cdrom = device;
}
#endif
+#ifdef USE_SEPARATED_ADPCM
+ void set_context_adpcm(ADPCM* device)
+ {
+ d_adpcm = device;
+ }
+#endif
void initialize_sound(int rate)
{
sample_rate = rate;
#endif
#include "pce.h"
+#ifdef USE_SEPARATED_ADPCM
+#include "./adpcm.h"
+using PCEDEV::ADPCM;
+#endif
using PCEDEV::PCE;
// ----------------------------------------------------------------------------
// initialize
// scsi_cdrom->set_context_event_manager(pceevent);
pce = new PCE(this, emu);
+#ifdef USE_SEPARATED_ADPCM
+ pce_adpcm = new ADPCM(this, emu);
+#endif
// pce->set_context_event_manager(pceevent);
#if defined(_USE_QT)
pce->set_device_name(_T("PC-ENGINE MAIN"));
pceevent->set_context_cpu(pcecpu, CPU_CLOCKS);
pceevent->set_context_sound(pce);
+#ifdef USE_SEPARATED_ADPCM
+ pceevent->set_context_sound(pce_adpcm);
+#endif
// NOTE: adpcm::mix() and scsi_cdrom::mix() will be called in pce::mix()
// pceevent->set_context_sound(adpcm);
// pceevent->set_context_sound(scsi_cdrom);
pce->set_context_scsi_host(scsi_host);
pce->set_context_scsi_cdrom(scsi_cdrom);
+#ifdef USE_SEPARATED_ADPCM
+ pce->set_context_adpcm(pce_adpcm);
+ pce_adpcm->set_context_msm(adpcm);
+ pce_adpcm->set_context_pce(pce);
+#endif
// initialize all devices
#if defined(__GIT_REPO_VERSION)
strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
#define USE_JOY_BUTTON_CAPTIONS
#define USE_DEBUGGER
#define USE_STATE
+#define USE_SEPARATED_ADPCM
#include "../../common.h"
#include "../../fileio.h"
namespace PCEDEV {
class PCE;
+#ifdef USE_SEPARATED_ADPCM
+ class ADPCM;
+#endif
}
class VM : public VM_TEMPLATE
{
SCSI_HOST* scsi_host;
SCSI_CDROM* scsi_cdrom;
PCEDEV::PCE* pce;
-
+#ifdef USE_SEPARATED_ADPCM
+ PCEDEV::ADPCM* pce_adpcm;
+#endif
public:
// ----------------------------------------
// initialize