From 82b2269ef968651f480b95b074bda7af1a6bddb0 Mon Sep 17 00:00:00 2001 From: "K.Ohta" Date: Sun, 29 Oct 2023 01:48:01 +0900 Subject: [PATCH] [VM][FMTOWNS][CDROM] CDROM checks DMAC's mask as running DMAC CH.3. - If not running (masked), not to assert DRQ . - [FMTOWNS][DMAC] Add some signals to detect mask register. --- source/src/vm/fmtowns/cdrom.h | 8 ++- source/src/vm/fmtowns/cdrom/cdrom.cpp | 91 +++++++++++++++++------------------ source/src/vm/fmtowns/dmac.cpp | 10 +++- source/src/vm/fmtowns/dmac.h | 19 +++++++- source/src/vm/fmtowns/fmtowns.cpp | 10 ++-- 5 files changed, 82 insertions(+), 56 deletions(-) diff --git a/source/src/vm/fmtowns/cdrom.h b/source/src/vm/fmtowns/cdrom.h index c12681e8b..d50711b0e 100644 --- a/source/src/vm/fmtowns/cdrom.h +++ b/source/src/vm/fmtowns/cdrom.h @@ -35,10 +35,13 @@ #define SIG_TOWNS_CDROM_RESET 0x23 #define SIG_TOWNS_CDROM_DMAINT 0x24 #define SIG_TOWNS_CDROM_DMAACK 0x25 +#define SIG_TOWNS_CDROM_DMAMASK 0x26 + #define SIG_TOWNS_CDROM_MUTE_L 0x29 #define SIG_TOWNS_CDROM_MUTE_R 0x2a #define SIG_TOWNS_CDROM_MUTE_ALL 0x2b + class SCSI_HOST; class FIFO; class RINGBUFFER; @@ -341,6 +344,8 @@ protected: bool pio_transfer_phase; bool mcu_ready; bool has_status; + bool dmac_running; + bool command_execute_phase; @@ -499,7 +504,8 @@ protected: void start_time_out(); void stop_time_out(); - void delay_drq(const double usec); + virtual void start_drq(const double usec); + virtual void stop_drq(); void do_drq(); inline void __FASTCALL write_mcuint_signals(const bool val) diff --git a/source/src/vm/fmtowns/cdrom/cdrom.cpp b/source/src/vm/fmtowns/cdrom/cdrom.cpp index 45a26f9c3..2ba7b7b12 100644 --- a/source/src/vm/fmtowns/cdrom/cdrom.cpp +++ b/source/src/vm/fmtowns/cdrom/cdrom.cpp @@ -232,6 +232,7 @@ void TOWNS_CDROM::reset_device() clear_event(this, event_delay_ready); clear_event(this, event_time_out); clear_event(this, event_eot); + clear_event(this, event_drq); // Around internal variables. // if(44100 % emu->get_sound_rate() == 0) { @@ -309,6 +310,11 @@ void TOWNS_CDROM::reset_device() set_subq(0); memcpy(subq_snapshot, subq_bytes, sizeof(subq_snapshot)); + if(d_dmac != NULL) { + dmac_running = (d_dmac->read_signal(SIG_TOWNS_DMAC_MASK_CH3) != 0) ? true : false; + } else { + dmac_running = false; + } // Maybe not need to reset interrupt from I/O 04C0h:bit7 . // write_mcuint_signals(false); // Will Implement @@ -359,9 +365,11 @@ void TOWNS_CDROM::stop_time_out() void TOWNS_CDROM::do_drq() { // Note: EMULATE NONE BUFFER. 20230531 K.O - if(dma_transfer_phase) { - if(!(databuffer->empty())) { - write_signals(&outputs_drq, 0xffffffff); + if((dma_transfer_phase) && (dma_transfer)) { + __LIKELY_IF(!(databuffer->empty())) { + __LIKELY_IF(dmac_running) { + write_signals(&outputs_drq, 0xffffffff); + } } else { if(read_length <= 0) { dma_transfer_epilogue(); // Remove Duplicate calling. @@ -370,12 +378,23 @@ void TOWNS_CDROM::do_drq() } } -void TOWNS_CDROM::delay_drq(const double usec) +void TOWNS_CDROM::stop_drq() { clear_event(this, event_drq); - register_event(this, EVENT_CDROM_DELAY_START_DRQ, - usec, // ALMOST 10us.This is temporally. - false, &event_drq); +} + +void TOWNS_CDROM::start_drq(const double usec) +{ + if(d_dmac != NULL) { + dmac_running = (d_dmac->read_signal(SIG_TOWNS_DMAC_MASK_CH3) != 0) ? true : false; + } else { + dmac_running = false; + } + if(event_drq < 0) { + register_event(this, EVENT_CDROM_DELAY_START_DRQ, + usec, + true, &event_drq); + } } void TOWNS_CDROM::clear_status_queue(const bool is_clear_extra) @@ -455,6 +474,9 @@ void TOWNS_CDROM::write_signal(int id, uint32_t data, uint32_t mask) } } break; + case SIG_TOWNS_CDROM_DMAMASK: + dmac_running = ((data & mask) != 0) ? true : false; + break; default: // ToDo: Implement master devices. break; @@ -1040,7 +1062,7 @@ uint8_t TOWNS_CDROM::read_status() void TOWNS_CDROM::dma_transfer_epilogue() { - clear_event(this, event_drq); + stop_drq(); // ToDo: // ToDo: CD-ROM with cache. stop_time_out(); @@ -1070,7 +1092,7 @@ void TOWNS_CDROM::pio_transfer_epilogue() { // ToDo: // ToDo: CD-ROM with cache. - clear_event(this, event_drq); + stop_drq(); stop_time_out(); dma_transfer_phase = false; @@ -1110,6 +1132,9 @@ uint32_t TOWNS_CDROM::read_dma_io8w(uint32_t addr, int *wait) __LIKELY_IF(wait != NULL) { *wait = 0; // Temporally. } + __UNLIKELY_IF(!(dmac_running) && (dma_transfer_phase) && (dma_transfer)) { // Fallthrough + return 0x00; + } bool is_empty = databuffer->empty(); __UNLIKELY_IF(!(dma_transfer_phase) && !(pio_transfer_phase)) { @@ -1123,8 +1148,6 @@ uint32_t TOWNS_CDROM::read_dma_io8w(uint32_t addr, int *wait) } __LIKELY_IF(dma_transfer_phase) { write_signals(&outputs_drq, 0x0); - delay_drq(4.0 / 16.0); - //do_drq(); } else if(pio_transfer_phase) { if(!(is_empty) && (databuffer->empty())) { cancel_event(this, event_delay_ready); @@ -1150,10 +1173,13 @@ uint32_t TOWNS_CDROM::read_dma_io16w(uint32_t addr, int *wait) __LIKELY_IF(wait != NULL) { *wait = 0; // Temporally. } + __UNLIKELY_IF(!(dmac_running) && (dma_transfer_phase) && (dma_transfer)) { // Fallthrough + return 0x0000; + } bool is_empty = databuffer->empty(); __UNLIKELY_IF(!(dma_transfer_phase) && !(pio_transfer_phase)) { - return 0x00; + return 0x0000; } __UNLIKELY_IF(is_empty) { data_reg.w = 0x0000; @@ -1162,8 +1188,6 @@ uint32_t TOWNS_CDROM::read_dma_io16w(uint32_t addr, int *wait) } __LIKELY_IF(dma_transfer_phase) { write_signals(&outputs_drq, 0x0); - delay_drq(4.0 / 16.0); - //do_drq(); } else if(pio_transfer_phase) { if(!(is_empty) && (databuffer->empty())) { cancel_event(this, event_delay_ready); @@ -1248,7 +1272,7 @@ void TOWNS_CDROM::read_cdrom() dma_intr = false; mcu_intr = false; - clear_event(this, event_drq); + //clear_event(this, event_drq); clear_event(this, event_next_sector); // Kick a first @@ -1262,7 +1286,6 @@ void TOWNS_CDROM::read_cdrom() clear_event(this, event_next_sector); clear_event(this, event_seek); - clear_event(this, event_drq); write_signals(&outputs_drq, 0x00000000); // CLEAR DRQ register_event(this, EVENT_CDROM_READY_TO_READ, usec, false, &event_next_sector); @@ -1980,16 +2003,6 @@ void TOWNS_CDROM::event_callback(int event_id, int err) //read_pos = 0; status_seek = false; // ToDo: Prefetch 20201116 - #if 0 - if(!(databuffer->empty())) { // ToDO: CACHING. - if((dma_transfer) && !(dma_transfer_phase)) { - dma_transfer_phase = true; - do_drq(); - } else if((pio_transfer) && !(pio_transfer_phase)) { - pio_transfer_phase = true; - } - } - #endif if(read_length > 0) { bool stat = false; //status_seek = true; @@ -2034,16 +2047,6 @@ void TOWNS_CDROM::event_callback(int event_id, int err) // This is from Tsugaru, commit 95afde8c, "Support CD-ROM CPU Data Transfer." . status_data_ready(false); start_time_out(); - #if 0 - if(!(databuffer->empty())) { // ToDO: CACHING. - if((dma_transfer) && !(dma_transfer_phase)) { - dma_transfer_phase = true; - do_drq(); - } else if((pio_transfer) && !(pio_transfer_phase)) { - pio_transfer_phase = true; - } - } - #endif if(read_length > 0) { status_seek = true; int physical_size = physical_block_size(); @@ -2057,7 +2060,6 @@ void TOWNS_CDROM::event_callback(int event_id, int err) } break; case EVENT_CDROM_DELAY_START_DRQ: // DELAY START DRQ - event_drq = -1; do_drq(); // First, may (sould) delay from rise up. break; default: @@ -3224,19 +3226,13 @@ void TOWNS_CDROM::write_io8(uint32_t addr, uint32_t data) pio_transfer = false; pio_transfer_phase = false; write_signals(&outputs_drq, 0x0); - #if 1 + double usec = 1.0e6 / ((double)transfer_speed * 150.0e3 * 2.0); + start_drq(usec); dma_transfer_phase = true; - do_drq(); - #else - if(!(dma_transfer_phase) && (!(databuffer->empty()))) { - dma_transfer_phase = true; - delay_drq(1.0); - } - #endif } else if(pio_transfer) { dma_transfer = false; dma_transfer_phase = false; - clear_event(this, event_drq); + stop_drq(); if(!(pio_transfer_phase)) { pio_transfer_phase = true; } @@ -3377,7 +3373,7 @@ bool TOWNS_CDROM::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len) /* * Note: 20200428 K.O: DO NOT USE STATE SAVE, STILL don't implement completely yet. */ -#define STATE_VERSION 35 +#define STATE_VERSION 36 bool TOWNS_CDROM::process_state(FILEIO* state_fio, bool loading) { @@ -3420,6 +3416,7 @@ bool TOWNS_CDROM::process_state(FILEIO* state_fio, bool loading) state_fio->StateValue(next_seek_lba); state_fio->StateValue(pio_transfer); state_fio->StateValue(dma_transfer); + state_fio->StateValue(dmac_running); state_fio->StateValue(reserved_command); if(!(param_queue->process_state((void *)state_fio, loading))) { diff --git a/source/src/vm/fmtowns/dmac.cpp b/source/src/vm/fmtowns/dmac.cpp index 7e623f8f5..b6d86182a 100644 --- a/source/src/vm/fmtowns/dmac.cpp +++ b/source/src/vm/fmtowns/dmac.cpp @@ -38,6 +38,7 @@ void TOWNS_DMAC::reset_from_io() void TOWNS_DMAC::reset() { UPD71071::reset(); + set_mask_reg(mask); dma_wrap = true; reset_from_io(); } @@ -98,6 +99,7 @@ void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data) switch(addr & 0x0f) { case 0x00: UPD71071::write_io8(0, data); + set_mask_reg(mask); check_mask_and_cmd(); if(data & 1) { reset_from_io(); @@ -182,7 +184,7 @@ void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data) break; // MASK case 0x0f: - mask = data; + set_mask_reg(data); check_mask_and_cmd(); break; default: @@ -627,6 +629,11 @@ void TOWNS_DMAC::event_callback(int event_id, int err) } uint32_t TOWNS_DMAC::read_signal(int id) { + if((id >= SIG_TOWNS_DMAC_MASK_CH0) && (id <= SIG_TOWNS_DMAC_MASK_CH3)) { + int ch = id - SIG_TOWNS_DMAC_MASK_CH0; + uint8_t _bit = 1 << ch; + return ((_bit & mask) == 0) ? 0xffffffff : 0x00000000; + } if(id == SIG_TOWNS_DMAC_WRAP) { return (dma_wrap) ? 0xffffffff : 0; } @@ -637,7 +644,6 @@ void TOWNS_DMAC::write_signal(int id, uint32_t data, uint32_t _mask) { if(id == SIG_TOWNS_DMAC_WRAP) { dma_wrap = ((data & _mask) != 0) ? true : false; -// this->write_signal(SIG_TOWNS_DMAC_ADDR_MASK, data, mask); } else if((id >= SIG_TOWNS_DMAC_EOT_CH0) && (id <= SIG_TOWNS_DMAC_EOT_CH3)) { int ch = (id - SIG_TOWNS_DMAC_EOT_CH0) & 3; end_req[ch] = ((data & _mask) != 0) ? true : false; diff --git a/source/src/vm/fmtowns/dmac.h b/source/src/vm/fmtowns/dmac.h index 119267462..508260f7a 100644 --- a/source/src/vm/fmtowns/dmac.h +++ b/source/src/vm/fmtowns/dmac.h @@ -10,6 +10,10 @@ #define SIG_TOWNS_DMAC_EOT_CH1 8193 #define SIG_TOWNS_DMAC_EOT_CH2 8194 #define SIG_TOWNS_DMAC_EOT_CH3 8195 +#define SIG_TOWNS_DMAC_MASK_CH0 8196 +#define SIG_TOWNS_DMAC_MASK_CH1 8197 +#define SIG_TOWNS_DMAC_MASK_CH2 8198 +#define SIG_TOWNS_DMAC_MASK_CH3 8199 namespace FMTOWNS { class TOWNS_DMAC : public UPD71071 @@ -20,6 +24,7 @@ protected: outputs_t outputs_ube[4]; outputs_t outputs_ack[4]; outputs_t outputs_towns_tc[4]; + outputs_t outputs_mask_reg; uint8_t div_count; // Temporally workaround for SCSI.20200318 K.O @@ -40,6 +45,12 @@ protected: { write_signals(&(outputs_ack[ch]), (val) ? 0xffffffff : 0); } + inline void __FASTCALL set_mask_reg(uint8_t val) + { + mask = val; + uint8_t val2 = ~val; + write_signals(&outputs_mask_reg, val2); + } constexpr bool check_address_16bit_bus_changed(int ch) { bool __is_align_bak = address_aligns_16bit[ch]; @@ -130,7 +141,7 @@ public: initialize_output_signals(&outputs_towns_tc[ch]); } clock_multiply = 1; - + initialize_output_signals(&outputs_mask_reg); } ~TOWNS_DMAC() {} // common functions @@ -188,6 +199,12 @@ public: { register_output_signal(&outputs_towns_tc[3], device, id, mask); } + void set_context_mask_bit(DEVICE* device, int id, uint8_t ch) + { + ch = ch & 3; + uint32_t mask_bit = 1 << ch; + register_output_signal(&outputs_mask_reg, device, id, mask_bit); + } }; diff --git a/source/src/vm/fmtowns/fmtowns.cpp b/source/src/vm/fmtowns/fmtowns.cpp index afc0a4c6b..99fec7d01 100644 --- a/source/src/vm/fmtowns/fmtowns.cpp +++ b/source/src/vm/fmtowns/fmtowns.cpp @@ -362,20 +362,20 @@ VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu) dma->set_context_cpu(NULL); //dma->set_context_cpu(cpu); dma->set_context_memory(memory); - // BASE CLOCK is 2MHz * 8. - dma->set_dmac_clock(16 * 1000 * 1000, 8); + // BASE CLOCK is 1MHz * 4. + dma->set_dmac_clock(4 * 1000 * 1000, 4); dma->set_context_ch0(fdc); // This is workaround for FM-Towns's SCSI. dma->set_force_16bit_transfer(1, false); dma->set_context_ch1(scsi_host); //dma->set_context_ch2(printer); dma->set_context_ch3(cdrom); - + dma->set_context_mask_bit(cdrom, SIG_TOWNS_CDROM_DMAMASK, 3); //extra_dma->set_context_cpu(cpu); extra_dma->set_context_cpu(NULL); extra_dma->set_context_memory(memory); - // BASE CLOCK is 2MHz * 8. - extra_dma->set_dmac_clock(16 * 1000 * 1000, 8); + // BASE CLOCK is 1MHz * 4. + extra_dma->set_dmac_clock(4 * 1000 * 1000, 4); //dma->set_context_tc1(scsi, SIG_SCSI_EOT, 0xffffffff); dma->set_context_tc3(cdrom, SIG_TOWNS_CDROM_DMAINT, 0xffffffff); -- 2.11.0