diff options
Diffstat (limited to 'src/devices/machine')
251 files changed, 7902 insertions, 10910 deletions
diff --git a/src/devices/machine/6525tpi.cpp b/src/devices/machine/6525tpi.cpp index 83d28fc0355..a82b09d104c 100644 --- a/src/devices/machine/6525tpi.cpp +++ b/src/devices/machine/6525tpi.cpp @@ -294,12 +294,12 @@ WRITE_LINE_MEMBER( tpi6525_device::i4_w ) } } -uint8_t tpi6525_device::pa_r() +READ8_MEMBER( tpi6525_device::pa_r ) { uint8_t data = m_in_a; if (!m_in_pa_cb.isnull()) - data = m_in_pa_cb(); + data = m_in_pa_cb(offset); data = (data & ~m_ddr_a) | (m_ddr_a & m_port_a); @@ -307,18 +307,18 @@ uint8_t tpi6525_device::pa_r() } -void tpi6525_device::pa_w(uint8_t data) +WRITE8_MEMBER( tpi6525_device::pa_w ) { m_in_a = data; } -uint8_t tpi6525_device::pb_r() +READ8_MEMBER( tpi6525_device::pb_r ) { uint8_t data = m_in_b; if (!m_in_pb_cb.isnull()) - data = m_in_pb_cb(); + data = m_in_pb_cb(offset); data = (data & ~m_ddr_b) | (m_ddr_b & m_port_b); @@ -326,18 +326,18 @@ uint8_t tpi6525_device::pb_r() } -void tpi6525_device::pb_w(uint8_t data) +WRITE8_MEMBER( tpi6525_device::pb_w ) { m_in_b = data; } -uint8_t tpi6525_device::pc_r() +READ8_MEMBER( tpi6525_device::pc_r ) { uint8_t data = m_in_c; if (!m_in_pc_cb.isnull()) - data &= m_in_pc_cb(); + data &= m_in_pc_cb(offset); data = (data & ~m_ddr_c) | (m_ddr_c & m_port_c); @@ -345,13 +345,13 @@ uint8_t tpi6525_device::pc_r() } -void tpi6525_device::pc_w(uint8_t data) +WRITE8_MEMBER( tpi6525_device::pc_w ) { m_in_c = data; } -uint8_t tpi6525_device::read(offs_t offset) +READ8_MEMBER( tpi6525_device::read ) { uint8_t data = 0xff; @@ -466,7 +466,7 @@ uint8_t tpi6525_device::read(offs_t offset) } -void tpi6525_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( tpi6525_device::write ) { DBG_LOG(machine(), 2, "tpi6525", ("%s write %.2x %.2x\n", tag(), offset, data)); diff --git a/src/devices/machine/6525tpi.h b/src/devices/machine/6525tpi.h index 4052662d50a..5e1ec394fe4 100644 --- a/src/devices/machine/6525tpi.h +++ b/src/devices/machine/6525tpi.h @@ -53,8 +53,8 @@ public: auto out_ca_cb() { return m_out_ca_cb.bind(); } auto out_cb_cb() { return m_out_cb_cb.bind(); } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); DECLARE_WRITE_LINE_MEMBER( i0_w ); DECLARE_WRITE_LINE_MEMBER( i1_w ); @@ -62,12 +62,12 @@ public: DECLARE_WRITE_LINE_MEMBER( i3_w ); DECLARE_WRITE_LINE_MEMBER( i4_w ); - uint8_t pa_r(); - uint8_t pb_r(); - uint8_t pc_r(); - void pa_w(uint8_t data); - void pb_w(uint8_t data); - void pc_w(uint8_t data); + DECLARE_READ8_MEMBER( pa_r ); + DECLARE_READ8_MEMBER( pb_r ); + DECLARE_READ8_MEMBER( pc_r ); + DECLARE_WRITE8_MEMBER( pa_w ); + DECLARE_WRITE8_MEMBER( pb_w ); + DECLARE_WRITE8_MEMBER( pc_w ); WRITE_LINE_MEMBER( pb0_w ) { port_line_w(m_in_b, 0, state); } WRITE_LINE_MEMBER( pb1_w ) { port_line_w(m_in_b, 1, state); } diff --git a/src/devices/machine/68153bim.cpp b/src/devices/machine/68153bim.cpp index 8df821a813e..30be9ea5e81 100644 --- a/src/devices/machine/68153bim.cpp +++ b/src/devices/machine/68153bim.cpp @@ -67,13 +67,12 @@ DEFINE_DEVICE_TYPE(EI68C153, ei68c153_device, "ei68c153", "EPIC // device_add_mconfig - add device configuration //------------------------------------------------- -void bim68153_device::device_add_mconfig(machine_config &config) -{ - MC68153_CHANNEL(config, m_chn[0], 0); - MC68153_CHANNEL(config, m_chn[1], 0); - MC68153_CHANNEL(config, m_chn[2], 0); - MC68153_CHANNEL(config, m_chn[3], 0); -} +MACHINE_CONFIG_START(bim68153_device::device_add_mconfig) + MCFG_DEVICE_ADD(CHN0_TAG, MC68153_CHANNEL, 0) + MCFG_DEVICE_ADD(CHN1_TAG, MC68153_CHANNEL, 0) + MCFG_DEVICE_ADD(CHN2_TAG, MC68153_CHANNEL, 0) + MCFG_DEVICE_ADD(CHN3_TAG, MC68153_CHANNEL, 0) +MACHINE_CONFIG_END //************************************************************************** // LIVE DEVICE diff --git a/src/devices/machine/6821pia.cpp b/src/devices/machine/6821pia.cpp index 60efe473f19..3bf21c9483b 100644 --- a/src/devices/machine/6821pia.cpp +++ b/src/devices/machine/6821pia.cpp @@ -576,7 +576,7 @@ uint8_t pia6821_device::control_b_r() // read //------------------------------------------------- -uint8_t pia6821_device::read(offs_t offset) +uint8_t pia6821_device::reg_r(uint8_t offset) { uint8_t ret; @@ -846,7 +846,7 @@ void pia6821_device::control_b_w(uint8_t data) // write //------------------------------------------------- -void pia6821_device::write(offs_t offset, uint8_t data) +void pia6821_device::reg_w(uint8_t offset, uint8_t data) { switch (offset & 0x03) { diff --git a/src/devices/machine/6821pia.h b/src/devices/machine/6821pia.h index 8457399cf1a..b31bf03183c 100644 --- a/src/devices/machine/6821pia.h +++ b/src/devices/machine/6821pia.h @@ -55,10 +55,13 @@ public: auto irqa_handler() { return m_irqa_handler.bind(); } auto irqb_handler() { return m_irqb_handler.bind(); } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); - uint8_t read_alt(offs_t offset) { return read(((offset << 1) & 0x02) | ((offset >> 1) & 0x01)); } - void write_alt(offs_t offset, uint8_t data) { write(((offset << 1) & 0x02) | ((offset >> 1) & 0x01), data); } + uint8_t reg_r(uint8_t offset); + void reg_w(uint8_t offset, uint8_t data); + + DECLARE_READ8_MEMBER( read ) { return reg_r(offset); } + DECLARE_WRITE8_MEMBER( write ) { reg_w(offset, data); } + DECLARE_READ8_MEMBER( read_alt ) { return reg_r(((offset << 1) & 0x02) | ((offset >> 1) & 0x01)); } + DECLARE_WRITE8_MEMBER( write_alt ) { reg_w(((offset << 1) & 0x02) | ((offset >> 1) & 0x01), data); } uint8_t port_b_z_mask() const { return ~m_ddr_b; } // see first note in .c void set_port_a_z_mask(uint8_t data) { m_port_a_z_mask = data; }// see second note in .c diff --git a/src/devices/machine/68307.cpp b/src/devices/machine/68307.cpp index ae13e090488..421d5f06da2 100644 --- a/src/devices/machine/68307.cpp +++ b/src/devices/machine/68307.cpp @@ -40,15 +40,14 @@ void m68307_cpu_device::m68307_internal_map(address_map &map) } -void m68307_cpu_device::device_add_mconfig(machine_config &config) -{ - MC68681(config, m_duart, 16000000/4); // ?? Mhz - should be specified in inline config - m_duart->irq_cb().set(FUNC(m68307_cpu_device::m68307_duart_irq_handler)); - m_duart->a_tx_cb().set(FUNC(m68307_cpu_device::m68307_duart_txa)); - m_duart->b_tx_cb().set(FUNC(m68307_cpu_device::m68307_duart_txb)); - m_duart->inport_cb().set(FUNC(m68307_cpu_device::m68307_duart_input_r)); - m_duart->outport_cb().set(FUNC(m68307_cpu_device::m68307_duart_output_w)); -} +MACHINE_CONFIG_START(m68307_cpu_device::device_add_mconfig) + MCFG_DEVICE_ADD("internal68681", MC68681, 16000000/4) // ?? Mhz - should be specified in inline config + MCFG_MC68681_IRQ_CALLBACK(WRITELINE(*this, m68307_cpu_device, m68307_duart_irq_handler)) + MCFG_MC68681_A_TX_CALLBACK(WRITELINE(*this, m68307_cpu_device, m68307_duart_txa)) + MCFG_MC68681_B_TX_CALLBACK(WRITELINE(*this, m68307_cpu_device, m68307_duart_txb)) + MCFG_MC68681_INPORT_CALLBACK(READ8(*this, m68307_cpu_device, m68307_duart_input_r)) + MCFG_MC68681_OUTPORT_CALLBACK(WRITE8(*this, m68307_cpu_device, m68307_duart_output_w)) +MACHINE_CONFIG_END m68307_cpu_device::m68307_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) @@ -90,14 +89,6 @@ void m68307_cpu_device::device_reset() set_ipl(0); } -void m68307_cpu_device::m68k_reset_peripherals() -{ - m_duart->reset(); - - if (m_m68307MBUS) m_m68307MBUS->reset(); - if (m_m68307TIMER) m_m68307TIMER->reset(); -} - /* todo: is it possible to calculate the address map based on CS when they change and install handlers? Going through this logic for every memory access is diff --git a/src/devices/machine/68307.h b/src/devices/machine/68307.h index 6d5ef10b61c..591d0c9cced 100644 --- a/src/devices/machine/68307.h +++ b/src/devices/machine/68307.h @@ -44,8 +44,6 @@ protected: virtual uint32_t execute_min_cycles() const override { return 4; } virtual uint32_t execute_max_cycles() const override { return 158; } - virtual void m68k_reset_peripherals() override; - private: void set_ipl(int level); DECLARE_WRITE_LINE_MEMBER(timer0_interrupt); diff --git a/src/devices/machine/68340.cpp b/src/devices/machine/68340.cpp index bae8be35b62..e9f8ba7ba8e 100644 --- a/src/devices/machine/68340.cpp +++ b/src/devices/machine/68340.cpp @@ -262,12 +262,3 @@ void m68340_cpu_device::device_start() m_int_ack_callback = device_irq_acknowledge_delegate(FUNC(m68340_cpu_device::int_ack), this); } - -void m68340_cpu_device::m68k_reset_peripherals() -{ - m_m68340SIM->module_reset(); - m_m68340DMA->module_reset(); - m_serial->module_reset(); - m_timer[0]->module_reset(); - m_timer[1]->module_reset(); -} diff --git a/src/devices/machine/68340.h b/src/devices/machine/68340.h index 23f3ed6b147..12af250c5b2 100644 --- a/src/devices/machine/68340.h +++ b/src/devices/machine/68340.h @@ -49,8 +49,6 @@ protected: virtual void device_reset() override; virtual void device_add_mconfig(machine_config &config) override; - virtual void m68k_reset_peripherals() override; - private: required_device<mc68340_serial_module_device> m_serial; required_device_array<mc68340_timer_module_device, 2> m_timer; diff --git a/src/devices/machine/68340dma.cpp b/src/devices/machine/68340dma.cpp index 4a79a4504fc..6649aeb2a94 100644 --- a/src/devices/machine/68340dma.cpp +++ b/src/devices/machine/68340dma.cpp @@ -26,9 +26,4 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_dma_w ) void m68340_dma::reset() { - module_reset(); -} - -void m68340_dma::module_reset() -{ } diff --git a/src/devices/machine/68340dma.h b/src/devices/machine/68340dma.h index 8bec4fb88a7..3a92b4e9a49 100644 --- a/src/devices/machine/68340dma.h +++ b/src/devices/machine/68340dma.h @@ -10,7 +10,6 @@ class m68340_dma { public: void reset(); - void module_reset(); }; #endif // MAME_MACHINE_68340DMA_H diff --git a/src/devices/machine/68340ser.cpp b/src/devices/machine/68340ser.cpp index e0fc3b29fde..fcf6708305e 100644 --- a/src/devices/machine/68340ser.cpp +++ b/src/devices/machine/68340ser.cpp @@ -157,9 +157,4 @@ mc68340_serial_module_device::mc68340_serial_module_device(const machine_config { } -void mc68340_serial_module_device::module_reset() -{ - mc68340_duart_device::device_reset(); -} - DEFINE_DEVICE_TYPE(MC68340_SERIAL_MODULE, mc68340_serial_module_device, "mc68340sermod", "MC68340 Serial Module") diff --git a/src/devices/machine/68340ser.h b/src/devices/machine/68340ser.h index b9775f2ad86..e658d719c05 100644 --- a/src/devices/machine/68340ser.h +++ b/src/devices/machine/68340ser.h @@ -7,6 +7,11 @@ #include "machine/mc68681.h" +// MCFG macros to hide the implementation +#define MCFG_MC68340SER_IRQ_CALLBACK(_cb) MCFG_MC68681_IRQ_CALLBACK(_cb) +#define MCFG_MC68340SER_A_TX_CALLBACK(_cb) MCFG_MC68681_A_TX_CALLBACK(_cb) +#define MCFG_MC68340SER_B_TX_CALLBACK(_cb) MCFG_MC68681_B_TX_CALLBACK(_cb) + class m68340_cpu_device; class mc68340_serial_module_device : public mc68340_duart_device @@ -27,8 +32,6 @@ public: uint8_t irq_vector() const { return m_ivr; } uint8_t arbitrate(uint8_t level) const { return (irq_level() == level) ? (m_mcrl & REG_MCRL_ARBLV) : 0; } - void module_reset(); - protected: m68340_cpu_device *m_cpu; diff --git a/src/devices/machine/68340sim.cpp b/src/devices/machine/68340sim.cpp index 3dbbfcb0733..cf299ba2b22 100644 --- a/src/devices/machine/68340sim.cpp +++ b/src/devices/machine/68340sim.cpp @@ -493,12 +493,6 @@ void m68340_sim::reset() m_pit_irq = false; } -void m68340_sim::module_reset() -{ - // SYS set in RSR, nothing else happens - m_avr_rsr = (m_avr_rsr & 0xff00) | 0x02; -} - /* do_tick_pit works on whole clock cycles, no flank support */ void m68340_cpu_device::do_tick_pit() { diff --git a/src/devices/machine/68340sim.h b/src/devices/machine/68340sim.h index 34358e02eff..3c839984db2 100644 --- a/src/devices/machine/68340sim.h +++ b/src/devices/machine/68340sim.h @@ -35,7 +35,6 @@ public: bool m_pit_irq; void reset(); - void module_reset(); enum { REG_MCR = 0x00, diff --git a/src/devices/machine/68340tmu.cpp b/src/devices/machine/68340tmu.cpp index 801a9802557..1ceaf65f600 100644 --- a/src/devices/machine/68340tmu.cpp +++ b/src/devices/machine/68340tmu.cpp @@ -308,16 +308,6 @@ void mc68340_timer_module_device::device_start() m_tin_in_cb.resolve_safe(); } -void mc68340_timer_module_device::device_reset() -{ - module_reset(); -} - -void mc68340_timer_module_device::module_reset() -{ - // TODO -} - void mc68340_timer_module_device::do_timer_irq() { assert((m_sr & (REG_SR_TO | REG_SR_TG | REG_SR_TC)) != 0); diff --git a/src/devices/machine/68340tmu.h b/src/devices/machine/68340tmu.h index 8952632792b..0582debd475 100644 --- a/src/devices/machine/68340tmu.h +++ b/src/devices/machine/68340tmu.h @@ -14,6 +14,9 @@ class mc68340_timer_module_device : public device_t public: mc68340_timer_module_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + // device-level overrides + virtual void device_start() override; + READ16_MEMBER( read ); WRITE16_MEMBER( write ); DECLARE_WRITE_LINE_MEMBER( tin_w ); @@ -23,13 +26,7 @@ public: uint8_t irq_vector() const { return m_ir & REG_IR_INTVEC; } uint8_t arbitrate(uint8_t level) const { return (irq_level() == level) ? (m_mcr & REG_MCR_ARBLV) : 0; } - void module_reset(); - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - + protected: m68340_cpu_device *m_cpu; uint16_t m_mcr; diff --git a/src/devices/machine/6840ptm.cpp b/src/devices/machine/6840ptm.cpp index 36b2cd5002b..bf1e6f4adb1 100644 --- a/src/devices/machine/6840ptm.cpp +++ b/src/devices/machine/6840ptm.cpp @@ -423,7 +423,7 @@ void ptm6840_device::reload_count(int idx) // read - Read Timer //------------------------------------------------- -uint8_t ptm6840_device::read(offs_t offset) +READ8_MEMBER( ptm6840_device::read ) { int val; @@ -487,7 +487,7 @@ uint8_t ptm6840_device::read(offs_t offset) // write - Write Timer //------------------------------------------------- -void ptm6840_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( ptm6840_device::write ) { switch ( offset ) { diff --git a/src/devices/machine/6840ptm.h b/src/devices/machine/6840ptm.h index 2c913a97b4c..ad5859b771b 100644 --- a/src/devices/machine/6840ptm.h +++ b/src/devices/machine/6840ptm.h @@ -39,8 +39,8 @@ public: void set_ext_clock(int counter, double clock); // set clock frequency int ext_clock(int counter) const { return m_external_clock[counter]; } // get clock frequency - void write(offs_t offset, uint8_t data); - uint8_t read(offs_t offset); + DECLARE_WRITE8_MEMBER( write ); + DECLARE_READ8_MEMBER( read ); void set_gate(int idx, int state); DECLARE_WRITE_LINE_MEMBER( set_g1 ); diff --git a/src/devices/machine/6850acia.cpp b/src/devices/machine/6850acia.cpp index 08e8459fd36..6527608bf0f 100644 --- a/src/devices/machine/6850acia.cpp +++ b/src/devices/machine/6850acia.cpp @@ -150,27 +150,24 @@ void acia6850_device::device_reset() output_irq(1); } -uint8_t acia6850_device::status_r() +READ8_MEMBER( acia6850_device::status_r ) { uint8_t status = m_status; - if (!machine().side_effects_disabled()) + if (status & SR_CTS) { - if (status & SR_CTS) - { - status &= ~SR_TDRE; - } + status &= ~SR_TDRE; + } - if (m_dcd_irq_pending == DCD_IRQ_READ_STATUS) - { - m_dcd_irq_pending = DCD_IRQ_READ_DATA; - } + if (m_dcd_irq_pending == DCD_IRQ_READ_STATUS) + { + m_dcd_irq_pending = DCD_IRQ_READ_DATA; } return status; } -void acia6850_device::control_w(uint8_t data) +WRITE8_MEMBER( acia6850_device::control_w ) { LOG("MC6850 '%s' Control: %02x\n", tag(), data); @@ -240,7 +237,7 @@ void acia6850_device::update_irq() output_irq(calculate_txirq() && calculate_rxirq()); } -void acia6850_device::data_w(uint8_t data) +WRITE8_MEMBER( acia6850_device::data_w ) { LOG("MC6850 '%s' Data: %02x\n", tag(), data); @@ -257,43 +254,40 @@ void acia6850_device::data_w(uint8_t data) update_irq(); } -uint8_t acia6850_device::data_r() +READ8_MEMBER( acia6850_device::data_r ) { - if (!machine().side_effects_disabled()) + if (m_overrun_pending) { - if (m_overrun_pending) - { - m_status |= SR_OVRN; - m_overrun_pending = false; - } - else - { - m_status &= ~SR_OVRN; - m_status &= ~SR_RDRF; - } - - if (m_dcd_irq_pending == DCD_IRQ_READ_DATA) - { - m_dcd_irq_pending = DCD_IRQ_NONE; - } + m_status |= SR_OVRN; + m_overrun_pending = false; + } + else + { + m_status &= ~SR_OVRN; + m_status &= ~SR_RDRF; + } - update_irq(); + if (m_dcd_irq_pending == DCD_IRQ_READ_DATA) + { + m_dcd_irq_pending = DCD_IRQ_NONE; } + update_irq(); + return m_rdr; } -void acia6850_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( acia6850_device::write ) { if (BIT(offset, 0)) - data_w(data); + data_w(space, 0, data); else - control_w(data); + control_w(space, 0, data); } -uint8_t acia6850_device::read(offs_t offset) +READ8_MEMBER( acia6850_device::read ) { - return BIT(offset, 0) ? data_r() : status_r(); + return BIT(offset, 0) ? data_r(space, 0) : status_r(space, 0); } DECLARE_WRITE_LINE_MEMBER( acia6850_device::write_cts ) diff --git a/src/devices/machine/6850acia.h b/src/devices/machine/6850acia.h index 4d99209d519..4c40e2dc69f 100644 --- a/src/devices/machine/6850acia.h +++ b/src/devices/machine/6850acia.h @@ -24,12 +24,12 @@ public: auto rts_handler() { return m_rts_handler.bind(); } auto irq_handler() { return m_irq_handler.bind(); } - void control_w(uint8_t data); - uint8_t status_r(); - void data_w(uint8_t data); - uint8_t data_r(); - void write(offs_t offset, uint8_t data); - uint8_t read(offs_t offset); + DECLARE_WRITE8_MEMBER( control_w ); + DECLARE_READ8_MEMBER( status_r ); + DECLARE_WRITE8_MEMBER( data_w ); + DECLARE_READ8_MEMBER( data_r ); + DECLARE_WRITE8_MEMBER( write ); + DECLARE_READ8_MEMBER( read ); DECLARE_WRITE_LINE_MEMBER( write_cts ); DECLARE_WRITE_LINE_MEMBER( write_dcd ); diff --git a/src/devices/machine/74157.cpp b/src/devices/machine/74157.cpp index 1dc7eb1289b..f5a68cc4465 100644 --- a/src/devices/machine/74157.cpp +++ b/src/devices/machine/74157.cpp @@ -35,7 +35,7 @@ DEFINE_DEVICE_TYPE(LS157_X2, ls157_x2_device, "ls157_x2", "74LS157 Quad 2-to-1 M // ls157_device - constructor //------------------------------------------------- -ls157_device::ls157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +ls157_device::ls157_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : ls157_device(mconfig, LS157, tag, owner, clock, 0x0f) { } @@ -58,7 +58,7 @@ ls157_device::ls157_device(const machine_config &mconfig, device_type type, cons // ls157_x2_device - constructor //------------------------------------------------- -ls157_x2_device::ls157_x2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +ls157_x2_device::ls157_x2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : ls157_device(mconfig, LS157_X2, tag, owner, clock, 0xff) { } @@ -92,7 +92,7 @@ void ls157_device::device_start() // a_w -- write nibble to A1-A4 //------------------------------------------------- -void ls157_device::a_w(u8 data) +void ls157_device::write_a(u8 data) { m_a = data & m_data_mask; update_output(); @@ -103,7 +103,7 @@ void ls157_device::a_w(u8 data) // b_w -- write nibble to B1-B4 //------------------------------------------------- -void ls157_device::b_w(u8 data) +void ls157_device::write_b(u8 data) { m_b = data & m_data_mask; update_output(); @@ -115,7 +115,7 @@ void ls157_device::b_w(u8 data) // low nibble to B1-B4 //------------------------------------------------- -void ls157_device::ab_w(u8 data) +void ls157_device::write_ab(u8 data) { assert(m_data_mask == 0x0f); m_a = data >> 4; @@ -129,7 +129,7 @@ void ls157_device::ab_w(u8 data) // low nibble to A1-A4 //------------------------------------------------- -void ls157_device::ba_w(u8 data) +void ls157_device::write_ba(u8 data) { assert(m_data_mask == 0x0f); m_b = data >> 4; @@ -143,7 +143,7 @@ void ls157_device::ba_w(u8 data) // A1-A4 and write odd-numbered bits to B1-B4 //------------------------------------------------- -void ls157_device::interleave_w(u8 data) +void ls157_device::write_interleave(u8 data) { assert(m_data_mask == 0x0f); m_b = bitswap<4>(data, 7, 5, 3, 1); @@ -260,7 +260,7 @@ void ls157_device::update_output() // DATA OUTPUTS //************************************************************************** -u8 ls157_device::output_r() +READ8_MEMBER(ls157_device::output_r) { if (m_strobe) return 0; @@ -277,7 +277,7 @@ u8 ls157_device::output_r() DEFINE_DEVICE_TYPE(HC157, hc157_device, "hc157", "74HC157 Quad 2-to-1 Multiplexer") -hc157_device::hc157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +hc157_device::hc157_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : ls157_device(mconfig, HC157, tag, owner, clock, 0x0f) { } @@ -289,7 +289,7 @@ hc157_device::hc157_device(const machine_config &mconfig, const char *tag, devic DEFINE_DEVICE_TYPE(HCT157, hct157_device, "hct157", "74HCT157 Quad 2-to-1 Multiplexer") -hct157_device::hct157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +hct157_device::hct157_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : ls157_device(mconfig, HCT157, tag, owner, clock, 0x0f) { } diff --git a/src/devices/machine/74157.h b/src/devices/machine/74157.h index 52875cc0a76..4bd4685546c 100644 --- a/src/devices/machine/74157.h +++ b/src/devices/machine/74157.h @@ -42,11 +42,16 @@ public: auto out_callback() { return m_out_cb.bind(); } // data writes - void a_w(u8 data); - void b_w(u8 data); - void ab_w(u8 data); - void ba_w(u8 data); - void interleave_w(u8 data); + DECLARE_WRITE8_MEMBER(a_w) { write_a(data); } + void write_a(u8 data); + DECLARE_WRITE8_MEMBER(b_w) { write_b(data); } + void write_b(u8 data); + DECLARE_WRITE8_MEMBER(ab_w) { write_ab(data); } + void write_ab(u8 data); + DECLARE_WRITE8_MEMBER(ba_w) { write_ba(data); } + void write_ba(u8 data); + DECLARE_WRITE8_MEMBER(interleave_w) { write_interleave(data); } + void write_interleave(u8 data); // data line writes DECLARE_WRITE_LINE_MEMBER(a0_w); @@ -63,7 +68,7 @@ public: DECLARE_WRITE_LINE_MEMBER(strobe_w); // output read - u8 output_r(); + DECLARE_READ8_MEMBER(output_r); protected: ls157_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 mask); diff --git a/src/devices/machine/74165.cpp b/src/devices/machine/74165.cpp index 9ba4415d56c..d33033d5ab7 100644 --- a/src/devices/machine/74165.cpp +++ b/src/devices/machine/74165.cpp @@ -22,10 +22,9 @@ DEFINE_DEVICE_TYPE(TTL165, ttl165_device, "ttl165", "SN54/74165") // device_add_mconfig - add device configuration //------------------------------------------------- -void ttl165_device::device_add_mconfig(machine_config &config) -{ - TIMER(config, m_timer).configure_generic(FUNC(ttl165_device::qh_output)); -} +MACHINE_CONFIG_START(ttl165_device::device_add_mconfig) + MCFG_TIMER_DRIVER_ADD("timer", ttl165_device, qh_output) +MACHINE_CONFIG_END //************************************************************************** diff --git a/src/devices/machine/74166.cpp b/src/devices/machine/74166.cpp index 1611b526762..07a9de653a5 100644 --- a/src/devices/machine/74166.cpp +++ b/src/devices/machine/74166.cpp @@ -22,10 +22,9 @@ DEFINE_DEVICE_TYPE(TTL166, ttl166_device, "ttl166", "SN54/74166") // device_add_mconfig - add device configuration //------------------------------------------------- -void ttl166_device::device_add_mconfig(machine_config &config) -{ - TIMER(config, m_timer).configure_generic(FUNC(ttl166_device::qh_output)); -} +MACHINE_CONFIG_START(ttl166_device::device_add_mconfig) + MCFG_TIMER_DRIVER_ADD("timer", ttl166_device, qh_output) +MACHINE_CONFIG_END //************************************************************************** diff --git a/src/devices/machine/7474.h b/src/devices/machine/7474.h index 0f9d87fa5bf..0a6a678ddfb 100644 --- a/src/devices/machine/7474.h +++ b/src/devices/machine/7474.h @@ -45,6 +45,19 @@ #pragma once + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_7474_OUTPUT_CB(_devcb) \ + downcast<ttl7474_device &>(*device).set_output_cb(DEVCB_##_devcb); + +#define MCFG_7474_COMP_OUTPUT_CB(_devcb) \ + downcast<ttl7474_device &>(*device).set_comp_output_cb(DEVCB_##_devcb); + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -58,6 +71,8 @@ public: ttl7474_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // static configuration helpers + template <class Object> devcb_base &set_output_cb(Object &&cb) { return m_output_func.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_comp_output_cb(Object &&cb) { return m_comp_output_func.set_callback(std::forward<Object>(cb)); } auto output_cb() { return m_output_func.bind(); } auto comp_output_cb() { return m_comp_output_func.bind(); } diff --git a/src/devices/machine/8042kbdc.cpp b/src/devices/machine/8042kbdc.cpp index 541e7575b63..602435369ab 100644 --- a/src/devices/machine/8042kbdc.cpp +++ b/src/devices/machine/8042kbdc.cpp @@ -45,11 +45,9 @@ kbdc8042_device::kbdc8042_device(const machine_config &mconfig, const char *tag, { } -void kbdc8042_device::device_add_mconfig(machine_config &config) -{ - AT_KEYB(config, m_keyboard_dev, pc_keyboard_device::KEYBOARD_TYPE::AT, 1); - m_keyboard_dev->keypress().set(FUNC(kbdc8042_device::keyboard_w)); -} +MACHINE_CONFIG_START(kbdc8042_device::device_add_mconfig) + MCFG_AT_KEYB_ADD("at_keyboard", 1, WRITELINE(*this, kbdc8042_device, keyboard_w)) +MACHINE_CONFIG_END /*------------------------------------------------- @@ -71,9 +69,6 @@ void kbdc8042_device::device_start() m_sending = 0; m_last_write_to_control = 0; m_status_read_mode = 0; - - m_update_timer = timer_alloc(TIMER_UPDATE); - m_update_timer->adjust(attotime::never); } /*------------------------------------------------- @@ -91,8 +86,6 @@ void kbdc8042_device::device_reset() m_mouse_x = 0; m_mouse_y = 0; m_mouse_btn = 0; - - m_update_timer->adjust(attotime::from_hz(100), 0, attotime::from_hz(100)); } void kbdc8042_device::at_8042_set_outport(uint8_t data, int initial) @@ -202,14 +195,7 @@ void kbdc8042_device::at_8042_clear_keyboard_received() m_mouse.received = 0; } -void kbdc8042_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - if (id == TIMER_UPDATE) - { - at_8042_check_keyboard(); - at_8042_check_mouse(); - } -} + /* ************************************************************************** * Port 0x60 Input and Output Buffer (keyboard and mouse data) diff --git a/src/devices/machine/8042kbdc.h b/src/devices/machine/8042kbdc.h index 38bdbe3814a..f2e7fdfbf04 100644 --- a/src/devices/machine/8042kbdc.h +++ b/src/devices/machine/8042kbdc.h @@ -58,11 +58,8 @@ protected: virtual void device_start() override; virtual void device_reset() override; virtual void device_add_mconfig(machine_config &config) override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; virtual ioport_constructor device_input_ports() const override; - static const device_timer_id TIMER_UPDATE = 0; - private: uint8_t m_inport; uint8_t m_outport; @@ -115,8 +112,6 @@ private: uint16_t m_mouse_y; uint8_t m_mouse_btn; - emu_timer * m_update_timer; - DECLARE_WRITE_LINE_MEMBER( keyboard_w ); }; diff --git a/src/devices/machine/8364_paula.h b/src/devices/machine/8364_paula.h index 412fe7679e6..c889a831b67 100644 --- a/src/devices/machine/8364_paula.h +++ b/src/devices/machine/8364_paula.h @@ -43,6 +43,18 @@ #pragma once + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_PAULA_MEM_READ_CB(_devcb) \ + downcast<paula_8364_device &>(*device).set_mem_r_callback(DEVCB_##_devcb); + +#define MCFG_PAULA_INT_CB(_devcb) \ + downcast<paula_8364_device &>(*device).set_int_w_callback(DEVCB_##_devcb); + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -55,6 +67,8 @@ public: paula_8364_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // configuration + template <class Object> devcb_base &set_mem_r_callback(Object &&cb) { return m_mem_r.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_int_w_callback(Object &&cb) { return m_int_w.set_callback(std::forward<Object>(cb)); } auto mem_read_cb() { return m_mem_r.bind(); } auto int_cb() { return m_int_w.bind(); } diff --git a/src/devices/machine/adc0808.cpp b/src/devices/machine/adc0808.cpp index 11aafe276fb..5f8aeb8f93c 100644 --- a/src/devices/machine/adc0808.cpp +++ b/src/devices/machine/adc0808.cpp @@ -156,7 +156,7 @@ void adc0808_device::device_timer(emu_timer &timer, device_timer_id id, int para // INTERFACE //************************************************************************** -u8 adc0808_device::data_r() +READ8_MEMBER( adc0808_device::data_r ) { if (!machine().side_effects_disabled()) { @@ -170,7 +170,7 @@ u8 adc0808_device::data_r() return m_sar; } -void adc0808_device::address_w(u8 data) +WRITE8_MEMBER( adc0808_device::address_w ) { m_address = data & 7; } @@ -198,22 +198,22 @@ READ_LINE_MEMBER( adc0808_device::eoc_r ) return m_eoc; } -void adc0808_device::address_offset_start_w(offs_t offset, u8 data) +WRITE8_MEMBER( adc0808_device::address_offset_start_w ) { if (VERBOSE) logerror("address_offset_start_w %02x %02x\n", offset, data); start_w(1); - address_w(offset); + address_w(space, 0, offset); start_w(0); } -void adc0808_device::address_data_start_w(u8 data) +WRITE8_MEMBER( adc0808_device::address_data_start_w ) { if (VERBOSE) - logerror("address_data_start_w %02x\n", data); + logerror("address_data_start_w %02x %02x\n", offset, data); start_w(1); - address_w(data); + address_w(space, 0, data); start_w(0); } diff --git a/src/devices/machine/adc0808.h b/src/devices/machine/adc0808.h index 1fa97aff47e..46943998dca 100644 --- a/src/devices/machine/adc0808.h +++ b/src/devices/machine/adc0808.h @@ -51,14 +51,14 @@ public: auto eoc_ff_callback() { return m_eoc_ff_cb.bind(); } template <std::size_t Bit> auto in_callback() { return m_in_cb[Bit].bind(); } - u8 data_r(); - void address_w(u8 data); + DECLARE_READ8_MEMBER(data_r); + DECLARE_WRITE8_MEMBER(address_w); DECLARE_WRITE_LINE_MEMBER(start_w); DECLARE_READ_LINE_MEMBER(eoc_r); // common hookups - void address_offset_start_w(offs_t offset, u8 data); // start and ale connected, address to the address bus - void address_data_start_w(u8 data); // start and ale connected, address to the data bus + DECLARE_WRITE8_MEMBER(address_offset_start_w); // start and ale connected, address to the address bus + DECLARE_WRITE8_MEMBER(address_data_start_w); // start and ale connected, address to the data bus protected: adc0808_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); diff --git a/src/devices/machine/adc0844.cpp b/src/devices/machine/adc0844.cpp index c3616035927..103702a8d14 100644 --- a/src/devices/machine/adc0844.cpp +++ b/src/devices/machine/adc0844.cpp @@ -182,14 +182,14 @@ void adc0848_device::device_timer(emu_timer &timer, device_timer_id id, int para // INTERFACE //************************************************************************** -u8 adc0844_device::read() +READ8_MEMBER( adc0844_device::read ) { m_intr_cb(CLEAR_LINE); return m_result; } -void adc0844_device::write(u8 data) +WRITE8_MEMBER( adc0844_device::write ) { m_intr_cb(CLEAR_LINE); @@ -198,7 +198,7 @@ void adc0844_device::write(u8 data) m_conversion_timer->adjust(attotime::from_usec(40)); } -void adc0848_device::write(u8 data) +WRITE8_MEMBER( adc0848_device::write ) { m_intr_cb(CLEAR_LINE); diff --git a/src/devices/machine/adc0844.h b/src/devices/machine/adc0844.h index 51dff681f16..d20d9697a09 100644 --- a/src/devices/machine/adc0844.h +++ b/src/devices/machine/adc0844.h @@ -43,8 +43,8 @@ public: auto ch3_callback() { return m_ch3_cb.bind(); } auto ch4_callback() { return m_ch4_cb.bind(); } - u8 read(); - virtual void write(u8 data); + DECLARE_READ8_MEMBER(read); + virtual DECLARE_WRITE8_MEMBER(write); protected: adc0844_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -78,7 +78,7 @@ public: auto ch7_callback() { return m_ch7_cb.bind(); } auto ch8_callback() { return m_ch8_cb.bind(); } - virtual void write(u8 data) override; + virtual DECLARE_WRITE8_MEMBER(write) override; protected: // device-level overrides diff --git a/src/devices/machine/aic6250.cpp b/src/devices/machine/aic6250.cpp index adf90fe99b5..769968569c8 100644 --- a/src/devices/machine/aic6250.cpp +++ b/src/devices/machine/aic6250.cpp @@ -41,14 +41,13 @@ #include "logmacro.h" -DEFINE_DEVICE_TYPE(AIC6250, aic6250_device, "aic6250", "Adaptec AIC-6250 High-Performance SCSI Protocol Chip") -DEFINE_DEVICE_TYPE(AIC6251A, aic6251a_device, "aic6251a", "Adaptec AIC-6251A Fast SCSI Protocol Chip") +DEFINE_DEVICE_TYPE(AIC6250, aic6250_device, "aic6250", "Adaptec 6250 High-Performance SCSI Protocol Chip") static char const *const nscsi_phase[] = { "DATA OUT", "DATA IN", "COMMAND", "STATUS", "*", "*", "MESSAGE OUT", "MESSAGE IN" }; static char const *const aic6250_phase[] = { "DATA OUT", "*", "DATA IN", "*", "COMMAND", "MESSAGE OUT", "STATUS", "MESSAGE IN" }; -aic6250_device::aic6250_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : nscsi_device(mconfig, type, tag, owner, clock) +aic6250_device::aic6250_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : nscsi_device(mconfig, AIC6250, tag, owner, clock) , m_int_cb(*this) , m_breq_cb(*this) , m_port_a_r_cb(*this) @@ -58,16 +57,6 @@ aic6250_device::aic6250_device(const machine_config &mconfig, device_type type, { } -aic6250_device::aic6250_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : aic6250_device(mconfig, AIC6250, tag, owner, clock) -{ -} - -aic6251a_device::aic6251a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : aic6250_device(mconfig, AIC6251A, tag, owner, clock) -{ -} - void aic6250_device::map(address_map &map) { map(0x0, 0x0).rw(FUNC(aic6250_device::dma_count_l_r), FUNC(aic6250_device::dma_count_l_w)); diff --git a/src/devices/machine/aic6250.h b/src/devices/machine/aic6250.h index 2a4ba02d118..029c7f72dca 100644 --- a/src/devices/machine/aic6250.h +++ b/src/devices/machine/aic6250.h @@ -34,8 +34,6 @@ public: void dma16_w(u16 data); protected: - aic6250_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - // standard device_interface overrides virtual void device_start() override; virtual void device_reset() override; @@ -54,11 +52,11 @@ protected: u8 status_reg_1_r(); u8 scsi_signal_reg_r(); u8 scsi_id_data_r(); - u8 source_dest_id_r() { return m_source_dest_id; } + u8 source_dest_id_r() { logerror("source_dest_id_r\n"); return m_source_dest_id; } u8 memory_data_r(); u8 port_a_r(); u8 port_b_r(); - u8 scsi_latch_data_r() { return m_scsi_latch_data; } + u8 scsi_latch_data_r() { logerror("scsi_latch_data_r 0x%02x\n", m_scsi_latch_data); return m_scsi_latch_data; } void dma_count_l_w(u8 data) { m_dma_count &= ~0x0000ff; m_dma_count |= (data << 0); } void dma_count_m_w(u8 data) { m_dma_count &= ~0x00ff00; m_dma_count |= (data << 8); } @@ -279,13 +277,6 @@ private: util::fifo <u8, 8> m_fifo; }; -class aic6251a_device : public aic6250_device -{ -public: - aic6251a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - DECLARE_DEVICE_TYPE(AIC6250, aic6250_device) -DECLARE_DEVICE_TYPE(AIC6251A, aic6251a_device) #endif // MAME_MACHINE_AIC6250_H diff --git a/src/devices/machine/aicartc.h b/src/devices/machine/aicartc.h index 71c8cdd55ad..757c0a58c1d 100644 --- a/src/devices/machine/aicartc.h +++ b/src/devices/machine/aicartc.h @@ -9,6 +9,13 @@ //************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_AICARTC_ADD(_tag,_freq) \ + MCFG_DEVICE_ADD(_tag, AICARTC, _freq) + +//************************************************************************** // TYPE DEFINITIONS //************************************************************************** diff --git a/src/devices/machine/akiko.cpp b/src/devices/machine/akiko.cpp index eb5fa929059..0394750fe30 100644 --- a/src/devices/machine/akiko.cpp +++ b/src/devices/machine/akiko.cpp @@ -38,9 +38,8 @@ DEFINE_DEVICE_TYPE(AKIKO, akiko_device, "akiko", "CBM AKIKO") // device_add_mconfig - add device configuration //------------------------------------------------- -void akiko_device::device_add_mconfig(machine_config &config) -{ -} +MACHINE_CONFIG_START(akiko_device::device_add_mconfig) +MACHINE_CONFIG_END //************************************************************************** diff --git a/src/devices/machine/am9513.cpp b/src/devices/machine/am9513.cpp index 6506510369f..c17ae1f09fe 100644 --- a/src/devices/machine/am9513.cpp +++ b/src/devices/machine/am9513.cpp @@ -1382,7 +1382,7 @@ void am9513_device::data_write(u16 data) // read8 - 8-bit read access //------------------------------------------------- -u8 am9513_device::read8(offs_t offset) +READ8_MEMBER(am9513_device::read8) { if (BIT(offset, 0)) return status_read(); @@ -1395,7 +1395,7 @@ u8 am9513_device::read8(offs_t offset) // write8 - 8-bit write access //------------------------------------------------- -void am9513_device::write8(offs_t offset, u8 data) +WRITE8_MEMBER(am9513_device::write8) { if (BIT(offset, 0)) { @@ -1412,7 +1412,7 @@ void am9513_device::write8(offs_t offset, u8 data) // read16 - 16-bit read access //------------------------------------------------- -u16 am9513_device::read16(offs_t offset) +READ16_MEMBER(am9513_device::read16) { if (BIT(offset, 0)) return status_read() | 0xff00; @@ -1429,7 +1429,7 @@ u16 am9513_device::read16(offs_t offset) // write16 - 16-bit write access //------------------------------------------------- -void am9513_device::write16(offs_t offset, u16 data) +WRITE16_MEMBER(am9513_device::write16) { if ((!bus_is_16_bit() || BIT(offset, 0)) && (data & 0xff00) != 0xff00) logerror("Errant write of %02X to upper byte of %s register in %d-bit bus mode\n", diff --git a/src/devices/machine/am9513.h b/src/devices/machine/am9513.h index ea3fcfe6443..b591294d9b7 100644 --- a/src/devices/machine/am9513.h +++ b/src/devices/machine/am9513.h @@ -55,12 +55,12 @@ public: auto fout_cb() { return m_fout_cb.bind(); } // 8-bit data bus interface - u8 read8(offs_t offset); - void write8(offs_t offset, u8 data); + DECLARE_READ8_MEMBER(read8); + DECLARE_WRITE8_MEMBER(write8); // 16-bit data bus interface - u16 read16(offs_t offset); - void write16(offs_t offset, u16 data); + DECLARE_READ16_MEMBER(read16); + DECLARE_WRITE16_MEMBER(write16); // Source N inputs DECLARE_WRITE_LINE_MEMBER(source1_w) { write_source(0, state); } diff --git a/src/devices/machine/am9517a.cpp b/src/devices/machine/am9517a.cpp index 5fda6ed486c..463f1c447ef 100644 --- a/src/devices/machine/am9517a.cpp +++ b/src/devices/machine/am9517a.cpp @@ -39,18 +39,6 @@ */ -/* - * The EISA_DMA device represents the 82C37A-compatible DMA devices present in - * EISA bus systems, in particular those embedded within the i82357 Integrated - * System Peripheral. The device supports 32 bit addressing, 32 bit data sizes, - * and 24 bit transfer counts, allowing DMA across 64k boundaries. It also adds - * stop registers, supporting ring-buffer memory arrangements. - * - * TODO - * - stop registers - * - 16/32-bit transfer sizes - */ - #include "emu.h" #include "am9517a.h" @@ -66,7 +54,6 @@ DEFINE_DEVICE_TYPE(AM9517A, am9517a_device, "am9517a", "AM9517A") DEFINE_DEVICE_TYPE(V5X_DMAU, v5x_dmau_device, "v5x_dmau", "V5X DMAU") DEFINE_DEVICE_TYPE(PCXPORT_DMAC, pcxport_dmac_device, "pcx_dmac", "PC Transporter DMAC") -DEFINE_DEVICE_TYPE(EISA_DMA, eisa_dma_device, "eisa_dma", "EISA DMA") //************************************************************************** @@ -303,6 +290,8 @@ inline void am9517a_device::dma_advance() { bool msb_changed = false; + m_channel[m_current_channel].m_count--; + if (m_current_channel || !COMMAND_MEM_TO_MEM || !COMMAND_CH0_ADDRESS_HOLD) { if (MODE_ADDRESS_DECREMENT) @@ -327,7 +316,7 @@ inline void am9517a_device::dma_advance() } } - if (m_channel[m_current_channel].m_count-- == 0) + if (m_channel[m_current_channel].m_count == 0xffff) { end_of_process(); } @@ -723,7 +712,7 @@ void am9517a_device::execute_run() // read - //------------------------------------------------- -uint8_t am9517a_device::read(offs_t offset) +READ8_MEMBER( am9517a_device::read ) { uint8_t data = 0; @@ -787,7 +776,7 @@ uint8_t am9517a_device::read(offs_t offset) // write - //------------------------------------------------- -void am9517a_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( am9517a_device::write ) { if (!BIT(offset, 3)) { @@ -1024,7 +1013,7 @@ void v5x_dmau_device::device_reset() } -uint8_t v5x_dmau_device::read(offs_t offset) +READ8_MEMBER(v5x_dmau_device::read) { uint8_t ret = 0; int channel = m_selected_channel; @@ -1108,7 +1097,7 @@ uint8_t v5x_dmau_device::read(offs_t offset) return ret; } -void v5x_dmau_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(v5x_dmau_device::write) { int channel = m_selected_channel; @@ -1119,12 +1108,12 @@ void v5x_dmau_device::write(offs_t offset, uint8_t data) //m_buswidth = data & 0x02; //if (data & 0x01) // soft_reset(); - LOG("DMA: Initialise [%02x]\n", data); + logerror("DMA: Initialise [%02x]\n", data); break; case 0x01: // Channel m_selected_channel = data & 0x03; m_base = data & 0x04; - LOG("DMA: Channel selected [%02x]\n", data); + logerror("DMA: Channel selected [%02x]\n", data); break; case 0x02: // Count (low) m_channel[channel].m_base_count = @@ -1132,7 +1121,7 @@ void v5x_dmau_device::write(offs_t offset, uint8_t data) if (m_base == 0) m_channel[channel].m_count = (m_channel[channel].m_count & 0xff00) | data; - LOG("DMA: Channel %i Counter set [%04x]\n", m_selected_channel, m_channel[channel].m_base_count); + logerror("DMA: Channel %i Counter set [%04x]\n", m_selected_channel, m_channel[channel].m_base_count); break; case 0x03: // Count (high) m_channel[channel].m_base_count = @@ -1140,7 +1129,7 @@ void v5x_dmau_device::write(offs_t offset, uint8_t data) if (m_base == 0) m_channel[channel].m_count = (m_channel[channel].m_count & 0x00ff) | (data << 8); - LOG("DMA: Channel %i Counter set [%04x]\n", m_selected_channel, m_channel[channel].m_base_count); + logerror("DMA: Channel %i Counter set [%04x]\n", m_selected_channel, m_channel[channel].m_base_count); break; case 0x04: // Address (low) m_channel[channel].m_base_address = @@ -1148,7 +1137,7 @@ void v5x_dmau_device::write(offs_t offset, uint8_t data) if (m_base == 0) m_channel[channel].m_address = (m_channel[channel].m_address & 0xffffff00) | data; - LOG("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address); + logerror("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address); break; case 0x05: // Address (mid) m_channel[channel].m_base_address = @@ -1156,7 +1145,7 @@ void v5x_dmau_device::write(offs_t offset, uint8_t data) if (m_base == 0) m_channel[channel].m_address = (m_channel[channel].m_address & 0xffff00ff) | (data << 8); - LOG("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address); + logerror("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address); break; case 0x06: // Address (high) m_channel[channel].m_base_address = @@ -1164,7 +1153,7 @@ void v5x_dmau_device::write(offs_t offset, uint8_t data) if (m_base == 0) m_channel[channel].m_address = (m_channel[channel].m_address & 0xff00ffff) | (data << 16); - LOG("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address); + logerror("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address); break; case 0x07: // Address (highest) m_channel[channel].m_base_address = @@ -1172,31 +1161,31 @@ void v5x_dmau_device::write(offs_t offset, uint8_t data) if (m_base == 0) m_channel[channel].m_address = (m_channel[channel].m_address & 0x00ffffff) | (data << 24); - LOG("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address); + logerror("DMA: Channel %i Address set [%08x]\n", m_selected_channel, m_channel[channel].m_base_address); break; case 0x0a: // Mode control m_channel[channel].m_mode = data; // clear terminal count m_status &= ~(1 << channel); - LOG("DMA: Channel %i Mode control set [%02x]\n",m_selected_channel,m_channel[channel].m_mode); + logerror("DMA: Channel %i Mode control set [%02x]\n",m_selected_channel,m_channel[channel].m_mode); break; case 0x08: // Device control (low) m_command = data; - LOG("DMA: Device control low set [%02x]\n",data); + logerror("DMA: Device control low set [%02x]\n",data); break; case 0x09: // Device control (high) m_command_high = data; - LOG("DMA: Device control high set [%02x]\n",data); + logerror("DMA: Device control high set [%02x]\n",data); break; case 0x0e: // Request //m_reg.request = data; - LOG("(invalid) DMA: Request set [%02x]\n",data); // no software requests on the v53 integrated version + logerror("(invalid) DMA: Request set [%02x]\n",data); // no software requests on the v53 integrated version break; case 0x0f: // Mask m_mask = data & 0x0f; - LOG("DMA: Mask set [%02x]\n",data); + logerror("DMA: Mask set [%02x]\n",data); break; @@ -1309,17 +1298,3 @@ void pcxport_dmac_device::end_of_process() m_state = STATE_SI; } - -eisa_dma_device::eisa_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : am9517a_device(mconfig, EISA_DMA, tag, owner, clock) -{ -} - -void eisa_dma_device::device_start() -{ - am9517a_device::device_start(); - - m_address_mask = 0xffffffffU; - - save_item(NAME(m_stop)); -} diff --git a/src/devices/machine/am9517a.h b/src/devices/machine/am9517a.h index a1e9215d125..37390a930d3 100644 --- a/src/devices/machine/am9517a.h +++ b/src/devices/machine/am9517a.h @@ -61,8 +61,8 @@ public: template <unsigned C> auto out_iow_callback() { return m_out_iow_cb[C].bind(); } template <unsigned C> auto out_dack_callback() { return m_out_dack_cb[C].bind(); } - virtual uint8_t read(offs_t offset); - virtual void write(offs_t offset, uint8_t data); + virtual DECLARE_READ8_MEMBER( read ); + virtual DECLARE_WRITE8_MEMBER( write ); DECLARE_WRITE_LINE_MEMBER( hack_w ); DECLARE_WRITE_LINE_MEMBER( ready_w ); @@ -95,9 +95,9 @@ protected: struct { uint32_t m_address; - uint32_t m_count; + uint16_t m_count; uint32_t m_base_address; - uint32_t m_base_count; + uint16_t m_base_count; uint8_t m_mode; } m_channel[4]; @@ -149,8 +149,8 @@ public: template <unsigned C> auto in_io16r_callback() { return m_in_io16r_cb[C].bind(); } template <unsigned C> auto out_io16w_callback() { return m_out_io16w_cb[C].bind(); } - virtual uint8_t read(offs_t offset) override; - virtual void write(offs_t offset, uint8_t data) override; + virtual DECLARE_READ8_MEMBER( read ) override; + virtual DECLARE_WRITE8_MEMBER( write ) override; protected: // device-level overrides @@ -186,50 +186,11 @@ protected: virtual void end_of_process() override; }; -class eisa_dma_device : public am9517a_device -{ -public: - eisa_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - template <unsigned Channel> u8 get_address_page() { return m_channel[Channel].m_address >> 16; } - template <unsigned Channel> void set_address_page(u8 data) - { - m_channel[Channel].m_base_address = (m_channel[Channel].m_base_address & 0x0000ffffU) | (u32(data) << 16); - m_channel[Channel].m_address = (m_channel[Channel].m_address & 0x0000ffffU) | (u32(data) << 16); - } - - template <unsigned Channel> u8 get_address_page_high() { return m_channel[Channel].m_address >> 24; } - template <unsigned Channel> void set_address_page_high(u8 data) - { - m_channel[Channel].m_base_address = (m_channel[Channel].m_base_address & 0x00ffffffU) | (u32(data) << 24); - m_channel[Channel].m_address = (m_channel[Channel].m_address & 0x00ffffffU) | (u32(data) << 24); - } - - template <unsigned Channel> u8 get_count_high() { return m_channel[Channel].m_count >> 16; } - template <unsigned Channel> void set_count_high(u8 data) - { - m_channel[Channel].m_base_count = (m_channel[Channel].m_base_count & 0x0000ffffU) | (u32(data) << 16); - m_channel[Channel].m_count = (m_channel[Channel].m_count & 0x0000ffffU) | (u32(data) << 16); - } - template <unsigned Channel> u32 get_stop() { return m_stop[Channel]; } - template <unsigned Channel> void set_stop(offs_t offset, u32 data, u32 mem_mask) - { - mem_mask &= 0x00fffffcU; - COMBINE_DATA(&m_stop[Channel]); - } - -protected: - virtual void device_start() override; - -private: - u32 m_stop[4]; -}; // device type definition DECLARE_DEVICE_TYPE(AM9517A, am9517a_device) DECLARE_DEVICE_TYPE(V5X_DMAU, v5x_dmau_device) DECLARE_DEVICE_TYPE(PCXPORT_DMAC, pcxport_dmac_device) -DECLARE_DEVICE_TYPE(EISA_DMA, eisa_dma_device) #endif // MAME_MACHINE_AM9517_H diff --git a/src/devices/machine/am9519.cpp b/src/devices/machine/am9519.cpp index be0b8c3da10..b1700b38492 100644 --- a/src/devices/machine/am9519.cpp +++ b/src/devices/machine/am9519.cpp @@ -103,7 +103,7 @@ IRQ_CALLBACK_MEMBER(am9519_device::iack_cb) } -u8 am9519_device::stat_r() +READ8_MEMBER( am9519_device::stat_r ) { u8 stat = 0; for(int n = 0, irq = m_prio; n < 8; n++, irq = (irq + 1) & 7) @@ -121,7 +121,7 @@ u8 am9519_device::stat_r() return stat; } -u8 am9519_device::data_r() +READ8_MEMBER( am9519_device::data_r ) { switch((m_mode & 0x60) >> 5) { @@ -137,7 +137,7 @@ u8 am9519_device::data_r() return 0; } -void am9519_device::cmd_w(u8 data) +WRITE8_MEMBER( am9519_device::cmd_w ) { m_cmd = data; switch(data >> 3) @@ -222,7 +222,7 @@ void am9519_device::cmd_w(u8 data) set_timer(); } -void am9519_device::data_w(u8 data) +WRITE8_MEMBER( am9519_device::data_w ) { if((m_cmd & 0xf0) >= 0xb0) { diff --git a/src/devices/machine/am9519.h b/src/devices/machine/am9519.h index 315e0bd890d..ddd4925696b 100644 --- a/src/devices/machine/am9519.h +++ b/src/devices/machine/am9519.h @@ -36,10 +36,10 @@ public: auto out_int_callback() { return m_out_int_func.bind(); } - u8 stat_r(); - u8 data_r(); - void cmd_w(u8 data); - void data_w(u8 data); + DECLARE_READ8_MEMBER( stat_r ); + DECLARE_READ8_MEMBER( data_r ); + DECLARE_WRITE8_MEMBER( cmd_w ); + DECLARE_WRITE8_MEMBER( data_w ); u32 acknowledge(); DECLARE_WRITE_LINE_MEMBER( ireq0_w ) { set_irq_line(0, state); } diff --git a/src/devices/machine/appldriv.h b/src/devices/machine/appldriv.h index 6d23284f46a..1a396990167 100644 --- a/src/devices/machine/appldriv.h +++ b/src/devices/machine/appldriv.h @@ -63,4 +63,33 @@ private: // device type definition DECLARE_DEVICE_TYPE(FLOPPY_APPLE, apple525_floppy_image_device) +#define MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ + downcast<apple525_floppy_image_device *>(device)->set_params(_dividend,_divisor); + +#define MCFG_LEGACY_FLOPPY_APPLE_2_DRIVES_ADD(_config,_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY_APPLE, 0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY_APPLE, 0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) + +#define MCFG_LEGACY_FLOPPY_APPLE_4_DRIVES_ADD(_config,_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY_APPLE, 0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY_APPLE, 0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_2, FLOPPY_APPLE, 0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_3, FLOPPY_APPLE, 0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) + +#define MCFG_LEGACY_FLOPPY_APPLE_2_DRIVES_REMOVE() \ + MCFG_DEVICE_REMOVE(FLOPPY_0) \ + MCFG_DEVICE_REMOVE(FLOPPY_1) + #endif // MAME_MACHINE_APPLDRIV_H diff --git a/src/devices/machine/applefdc.h b/src/devices/machine/applefdc.h index 87cc89f36dc..eede57199f7 100644 --- a/src/devices/machine/applefdc.h +++ b/src/devices/machine/applefdc.h @@ -124,12 +124,6 @@ private: class applefdc_device : public applefdc_base_device { public: - applefdc_device(const machine_config &mconfig, const char *tag, device_t *owner, const applefdc_interface *intrf) - : applefdc_device(mconfig, tag, owner, (uint32_t)0) - { - set_config(intrf); - } - applefdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; @@ -151,4 +145,30 @@ public: iwm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; + + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define MCFG_APPLEFDC_CONFIG(_intrf) \ + downcast<applefdc_base_device &>(*device).set_config(&(_intrf)); + +#define MCFG_APPLEFDC_ADD(_tag, _intrf) \ + MCFG_DEVICE_ADD(_tag, APPLEFDC, 0) \ + MCFG_APPLEFDC_CONFIG(_intrf) + +#define MCFG_APPLEFDC_MODIFY(_tag, _intrf) \ + MCFG_DEVICE_MODIFY(_tag) \ + MCFG_APPLEFDC_CONFIG(_intrf) + +#define MCFG_IWM_ADD(_tag, _intrf) \ + MCFG_DEVICE_ADD(_tag, IWM, 0) \ + MCFG_APPLEFDC_CONFIG(_intrf) + +#define MCFG_IWM_MODIFY(_tag, _intrf) \ + MCFG_DEVICE_MODIFY(_tag) \ + MCFG_APPLEFDC_CONFIG(_intrf) + + #endif // MAME_MACHINE_APPLEFDC_H diff --git a/src/devices/machine/at29x.cpp b/src/devices/machine/at29x.cpp index 3f31e44c0a8..482faf24221 100644 --- a/src/devices/machine/at29x.cpp +++ b/src/devices/machine/at29x.cpp @@ -195,7 +195,7 @@ void at29x_device::sync_flags() /* read a byte from FEEPROM */ -uint8_t at29x_device::read(offs_t offset) +READ8_MEMBER( at29x_device::read ) { int reply; @@ -271,7 +271,7 @@ uint8_t at29x_device::read(offs_t offset) /* Write a byte to FEEPROM */ -void at29x_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( at29x_device::write ) { offset &= m_address_mask; LOGMASKED(LOG_WRITE, "%05x <- %02x\n", offset, data); diff --git a/src/devices/machine/at29x.h b/src/devices/machine/at29x.h index 265ef1587c2..435bcaafabc 100644 --- a/src/devices/machine/at29x.h +++ b/src/devices/machine/at29x.h @@ -20,8 +20,8 @@ DECLARE_DEVICE_TYPE(AT29C040A, at29c040a_device) class at29x_device : public device_t, public device_nvram_interface { public: - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); protected: at29x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int memory_size, int device_id, int sector_size); diff --git a/src/devices/machine/at_keybc.cpp b/src/devices/machine/at_keybc.cpp index 5e6ac779569..aec9154a38f 100644 --- a/src/devices/machine/at_keybc.cpp +++ b/src/devices/machine/at_keybc.cpp @@ -74,8 +74,6 @@ ROM_START(at_kbc) ROMX_LOAD("1503033.bin", 0x0000, 0x0800, CRC(5a81c0d2) SHA1(0100f8789fb4de74706ae7f9473a12ec2b9bd729), ROM_BIOS(0)) ROM_SYSTEM_BIOS(1, "ptl", "PTL 1986") // unknown controller BIOS, (c) 1985, 1986 PTL ROMX_LOAD("yan25d05.bin", 0x0000, 0x0800, CRC(70c798f1) SHA1(ae9a79c7184a17331b70a50035ff63c757df094c), ROM_BIOS(1)) - ROM_SYSTEM_BIOS(2, "award15", "Award 1985 V1.5") // MIPS Rx2030 i8742 keyboard controller - ROMX_LOAD("keyboard_1.5.bin", 0x0000, 0x0800, CRC(f86ba0f7) SHA1(1ad475451db35a76d929824c035d582279fbe3a3), ROM_BIOS(2)) ROM_END ROM_START(ps2_kbc) @@ -110,22 +108,22 @@ DEFINE_DEVICE_TYPE(PS2_KEYBOARD_CONTROLLER, ps2_keyboard_controller_device, "ps2 // KEYBOARD CONTROLLER DEVICE BASE //************************************************************************** -uint8_t at_kbc_device_base::data_r() +READ8_MEMBER(at_kbc_device_base::data_r) { - return m_mcu->upi41_master_r(machine().dummy_space(), 0U); + return m_mcu->upi41_master_r(space, 0U); } -uint8_t at_kbc_device_base::status_r() +READ8_MEMBER(at_kbc_device_base::status_r) { - return m_mcu->upi41_master_r(machine().dummy_space(), 1U); + return m_mcu->upi41_master_r(space, 1U); } -void at_kbc_device_base::data_w(uint8_t data) +WRITE8_MEMBER(at_kbc_device_base::data_w) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(at_kbc_device_base::write_data), this), unsigned(data)); } -void at_kbc_device_base::command_w(uint8_t data) +WRITE8_MEMBER(at_kbc_device_base::command_w) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(at_kbc_device_base::write_command), this), unsigned(data)); } @@ -265,7 +263,7 @@ ioport_constructor at_keyboard_controller_device::device_input_ports() const return INPUT_PORTS_NAME(at_kbc); } -void at_keyboard_controller_device::p2_w(uint8_t data) +WRITE8_MEMBER(at_keyboard_controller_device::p2_w) { set_hot_res(BIT(~data, 0)); set_gate_a20(BIT(data, 1)); @@ -279,11 +277,11 @@ void at_keyboard_controller_device::p2_w(uint8_t data) // PS/2 KEYBOARD/MOUSE CONTROLLER DEVICE //************************************************************************** -uint8_t ps2_keyboard_controller_device::data_r() +READ8_MEMBER(ps2_keyboard_controller_device::data_r) { set_kbd_irq(0U); set_mouse_irq(0U); - return m_mcu->upi41_master_r(machine().dummy_space(), 0U); + return m_mcu->upi41_master_r(space, 0U); } WRITE_LINE_MEMBER(ps2_keyboard_controller_device::mouse_clk_w) @@ -385,12 +383,12 @@ TIMER_CALLBACK_MEMBER(ps2_keyboard_controller_device::set_mouse_data_in) m_mouse_data_in = param ? 1U : 0U; } -uint8_t ps2_keyboard_controller_device::p1_r() +READ8_MEMBER(ps2_keyboard_controller_device::p1_r) { return kbd_data_r() | (mouse_data_r() << 1) | 0xfcU; } -void ps2_keyboard_controller_device::p2_w(uint8_t data) +WRITE8_MEMBER(ps2_keyboard_controller_device::p2_w) { set_hot_res(BIT(~data, 0)); set_gate_a20(BIT(data, 1)); diff --git a/src/devices/machine/at_keybc.h b/src/devices/machine/at_keybc.h index 5ff11aa6ba1..77bf039a7a1 100644 --- a/src/devices/machine/at_keybc.h +++ b/src/devices/machine/at_keybc.h @@ -30,10 +30,10 @@ public: auto kbd_data() { return m_kbd_data_cb.bind(); } // open collector with 10kΩ pull-up // host interface - virtual uint8_t data_r(); - virtual uint8_t status_r(); - void data_w(uint8_t data); - void command_w(uint8_t data); + virtual DECLARE_READ8_MEMBER(data_r); + virtual DECLARE_READ8_MEMBER(status_r); + DECLARE_WRITE8_MEMBER(data_w); + DECLARE_WRITE8_MEMBER(command_w); // inputs from keyboard DECLARE_WRITE_LINE_MEMBER(kbd_clk_w); @@ -93,7 +93,7 @@ protected: private: // MCU I/O handlers - void p2_w(uint8_t data); + DECLARE_WRITE8_MEMBER(p2_w); }; @@ -112,7 +112,7 @@ public: auto mouse_data() { return m_mouse_data_cb.bind(); } // open collector with 10kΩ pull-up // host interface - virtual uint8_t data_r() override; + virtual DECLARE_READ8_MEMBER(data_r) override; // inputs from mouse DECLARE_WRITE_LINE_MEMBER(mouse_clk_w); @@ -143,8 +143,8 @@ private: TIMER_CALLBACK_MEMBER(set_mouse_data_in); // MCU I/O handlers - uint8_t p1_r(); - void p2_w(uint8_t data); + DECLARE_READ8_MEMBER(p1_r); + DECLARE_WRITE8_MEMBER(p2_w); devcb_write_line m_mouse_irq_cb; devcb_write_line m_mouse_clk_cb, m_mouse_data_cb; diff --git a/src/devices/machine/atapicdr.cpp b/src/devices/machine/atapicdr.cpp index 33cb0cb154e..c13b6ff001e 100644 --- a/src/devices/machine/atapicdr.cpp +++ b/src/devices/machine/atapicdr.cpp @@ -30,11 +30,11 @@ atapi_fixed_cdrom_device::atapi_fixed_cdrom_device(const machine_config &mconfig // device_add_mconfig - add device configuration //------------------------------------------------- -void atapi_cdrom_device::device_add_mconfig(machine_config &config) -{ - CDROM(config, "image").set_interface("cdrom"); - CDDA(config, "cdda"); -} +MACHINE_CONFIG_START(atapi_cdrom_device::device_add_mconfig) + MCFG_CDROM_ADD("image") + MCFG_CDROM_INTERFACE("cdrom") + MCFG_DEVICE_ADD("cdda", CDDA) +MACHINE_CONFIG_END void atapi_cdrom_device::device_start() { diff --git a/src/devices/machine/ay31015.cpp b/src/devices/machine/ay31015.cpp index 6ab1103b28a..b9cc6c74a9b 100644 --- a/src/devices/machine/ay31015.cpp +++ b/src/devices/machine/ay31015.cpp @@ -116,10 +116,14 @@ ay31015_device::ay31015_device(const machine_config &mconfig, device_type type, m_rx_bit_count(0), m_rx_parity(0), m_rx_pulses(0), + m_rx_clock(0), + m_rx_timer(nullptr), m_tx_data(0), m_tx_buffer(0), m_tx_parity(0), m_tx_pulses(0), + m_tx_clock(0), + m_tx_timer(nullptr), m_read_si_cb(*this), m_write_so_cb(*this), m_write_pe_cb(*this), @@ -169,6 +173,14 @@ void ay31015_device::device_resolve_objects() void ay31015_device::device_start() { + m_rx_timer = timer_alloc(TIMER_RX); + m_rx_timer->adjust(attotime::never); + update_rx_timer(); + + m_tx_timer = timer_alloc(TIMER_TX); + m_tx_timer->adjust(attotime::never); + update_tx_timer(); + save_item(NAME(m_pins)); save_item(NAME(m_control_reg)); save_item(NAME(m_status_reg)); @@ -182,12 +194,14 @@ void ay31015_device::device_start() save_item(NAME(m_rx_bit_count)); save_item(NAME(m_rx_parity)); save_item(NAME(m_rx_pulses)); + save_item(NAME(m_rx_clock)); save_item(NAME(m_tx_state)); save_item(NAME(m_tx_data)); save_item(NAME(m_tx_buffer)); save_item(NAME(m_tx_parity)); save_item(NAME(m_tx_pulses)); + save_item(NAME(m_tx_clock)); } //------------------------------------------------- @@ -256,6 +270,14 @@ void ay31015_device::update_status_pins() update_status_pin(STATUS_EOC, EOC, m_write_eoc_cb); } +void ay31015_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_RX) + rx_process(); + else if(id == TIMER_TX) + tx_process(); +} + /*************************************************** RECEIVE CONTROLS *************************************************/ @@ -710,6 +732,54 @@ int ay31015_device::get_output_pin( ay31015_device::output_pin pin ) } +inline void ay31015_device::update_rx_timer() +{ + if (m_rx_clock > 0.0) + { + m_rx_timer->adjust(attotime::from_hz(m_rx_clock), 0, attotime::from_hz(m_rx_clock)); + } + else + { + m_rx_timer->enable(0); + } +} + + +inline void ay31015_device::update_tx_timer() +{ + if (m_tx_clock > 0.0) + { + m_tx_timer->adjust(attotime::from_hz(m_tx_clock), 0, attotime::from_hz(m_tx_clock)); + } + else + { + m_tx_timer->enable(0); + } +} + + +/*------------------------------------------------- + ay31015_set_receiver_clock - set receive clock +-------------------------------------------------*/ + +void ay31015_device::set_receiver_clock( double new_clock ) +{ + m_rx_clock = new_clock; + update_rx_timer(); +} + + +/*------------------------------------------------- + ay31015_set_transmitter_clock - set transmit clock +-------------------------------------------------*/ + +void ay31015_device::set_transmitter_clock( double new_clock ) +{ + m_tx_clock = new_clock; + update_tx_timer(); +} + + /*------------------------------------------------- ay31015_get_received_data - return a byte to the computer -------------------------------------------------*/ diff --git a/src/devices/machine/ay31015.h b/src/devices/machine/ay31015.h index 42518cb9a85..497c6b6a9f9 100644 --- a/src/devices/machine/ay31015.h +++ b/src/devices/machine/ay31015.h @@ -20,6 +20,10 @@ class ay31015_device : public device_t public: ay31015_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + void set_tx_clock(double tx_clock) { m_tx_clock = tx_clock; } + void set_tx_clock(const XTAL &xtal) { set_tx_clock(xtal.dvalue()); } + void set_rx_clock(double rx_clock) { m_rx_clock = rx_clock; } + void set_rx_clock(const XTAL &xtal) { set_rx_clock(xtal.dvalue()); } void set_auto_rdav(bool auto_rdav) { m_auto_rdav = auto_rdav; } auto read_si_callback() { return m_read_si_cb.bind(); } @@ -54,6 +58,12 @@ public: DECLARE_READ_LINE_MEMBER(eoc_r) { return get_output_pin(EOC); } DECLARE_READ_LINE_MEMBER(so_r) { return get_output_pin(SO); } + /* Set a new transmitter clock (new_clock is in Hz) */ + void set_transmitter_clock( double new_clock ); + + /* Set a new receiver clock (new_clock is in Hz) */ + void set_receiver_clock( double new_clock ); + /* Reead the received data */ /* The received data is available on RD8-RD1 (pins 5-12) */ uint8_t get_received_data(); @@ -104,12 +114,16 @@ protected: PREP_TIME }; + static constexpr device_timer_id TIMER_RX = 0; + static constexpr device_timer_id TIMER_TX = 1; + ay31015_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); // device-level overrides virtual void device_resolve_objects() override; virtual void device_start() override; virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; void rx_process(); void tx_process(); @@ -123,6 +137,8 @@ protected: void transfer_control_pins(); void set_input_pin(input_pin pin, int data); int get_output_pin(output_pin pin); + inline void update_rx_timer(); + inline void update_tx_timer(); int m_pins[41]; @@ -138,12 +154,16 @@ protected: uint8_t m_rx_bit_count; uint8_t m_rx_parity; uint16_t m_rx_pulses; // total pulses left + double m_rx_clock; /* RCP - pin 17 */ + emu_timer *m_rx_timer; state_t m_tx_state; uint8_t m_tx_data; // byte being sent uint8_t m_tx_buffer; // next byte to send uint8_t m_tx_parity; uint16_t m_tx_pulses; // total pulses left + double m_tx_clock; /* TCP - pin 40 */ + emu_timer *m_tx_timer; devcb_read_line m_read_si_cb; // SI - pin 20 - This will be called whenever the SI pin is sampled. Optional devcb_write_line m_write_so_cb; // SO - pin 25 - This will be called whenever data is put on the SO pin. Optional diff --git a/src/devices/machine/bankdev.cpp b/src/devices/machine/bankdev.cpp index e8e141ff7e6..8c10286ccfa 100644 --- a/src/devices/machine/bankdev.cpp +++ b/src/devices/machine/bankdev.cpp @@ -6,7 +6,7 @@ // device type definition DEFINE_DEVICE_TYPE(ADDRESS_MAP_BANK, address_map_bank_device, "address_map_bank", "Address Map Bank") -address_map_bank_device::address_map_bank_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +address_map_bank_device::address_map_bank_device( const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock ) : device_t(mconfig, ADDRESS_MAP_BANK, tag, owner, clock), device_memory_interface(mconfig, *this), m_endianness(ENDIANNESS_NATIVE), @@ -46,42 +46,42 @@ void address_map_bank_device::amap64(address_map &map) map(0x00000000, 0xffffffff).rw(FUNC(address_map_bank_device::read64), FUNC(address_map_bank_device::write64)); } -void address_map_bank_device::write8(offs_t offset, u8 data) +WRITE8_MEMBER(address_map_bank_device::write8) { m_program->write_byte(m_offset + offset, data); } -void address_map_bank_device::write16(offs_t offset, u16 data, u16 mem_mask) +WRITE16_MEMBER(address_map_bank_device::write16) { m_program->write_word(m_offset + (offset << (m_shift+1)), data, mem_mask); } -void address_map_bank_device::write32(offs_t offset, u32 data, u32 mem_mask) +WRITE32_MEMBER(address_map_bank_device::write32) { m_program->write_dword(m_offset + (offset << (m_shift+2)), data, mem_mask); } -void address_map_bank_device::write64(offs_t offset, u64 data, u64 mem_mask) +WRITE64_MEMBER(address_map_bank_device::write64) { m_program->write_qword(m_offset + (offset << (m_shift+3)), data, mem_mask); } -u8 address_map_bank_device::read8(offs_t offset) +READ8_MEMBER(address_map_bank_device::read8) { return m_program->read_byte(m_offset + offset); } -u16 address_map_bank_device::read16(offs_t offset, u16 mem_mask) +READ16_MEMBER(address_map_bank_device::read16) { return m_program->read_word(m_offset + (offset << (m_shift+1)), mem_mask); } -u32 address_map_bank_device::read32(offs_t offset, u32 mem_mask) +READ32_MEMBER(address_map_bank_device::read32) { return m_program->read_dword(m_offset + (offset << (m_shift+2)), mem_mask); } -u64 address_map_bank_device::read64(offs_t offset, u64 mem_mask) +READ64_MEMBER(address_map_bank_device::read64) { return m_program->read_qword(m_offset + (offset << (m_shift+3)), mem_mask); } diff --git a/src/devices/machine/bankdev.h b/src/devices/machine/bankdev.h index 05a3c2eb411..39bcfdcf08a 100644 --- a/src/devices/machine/bankdev.h +++ b/src/devices/machine/bankdev.h @@ -12,16 +12,16 @@ class address_map_bank_device : { public: // construction/destruction - address_map_bank_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + address_map_bank_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); // configuration helpers template <typename... T> address_map_bank_device& set_map(T &&... args) { set_addrmap(0, std::forward<T>(args)...); return *this; } address_map_bank_device& set_endianness(endianness_t endianness) { m_endianness = endianness; return *this; } - address_map_bank_device& set_data_width(u8 data_width) { m_data_width = data_width; return *this; } - address_map_bank_device& set_addr_width(u8 addr_width) { m_addr_width = addr_width; return *this; } - address_map_bank_device& set_stride(u32 stride) { m_stride = stride; return *this; } - address_map_bank_device& set_shift(u32 shift) { m_shift = shift; return *this; } - address_map_bank_device& set_options(endianness_t endianness, u8 data_width, u8 addr_width, u32 stride = 1) + address_map_bank_device& set_data_width(uint8_t data_width) { m_data_width = data_width; return *this; } + address_map_bank_device& set_addr_width(uint8_t addr_width) { m_addr_width = addr_width; return *this; } + address_map_bank_device& set_stride(uint32_t stride) { m_stride = stride; return *this; } + address_map_bank_device& set_shift(uint32_t shift) { m_shift = shift; return *this; } + address_map_bank_device& set_options(endianness_t endianness, uint8_t data_width, uint8_t addr_width, uint32_t stride = 1) { set_endianness(endianness); set_data_width(data_width); @@ -32,25 +32,25 @@ public: template <typename... T> address_map_bank_device& map(T &&... args) { set_addrmap(0, std::forward<T>(args)...); return *this; } address_map_bank_device& endianness(endianness_t endianness) { m_endianness = endianness; return *this; } - address_map_bank_device& data_width(u8 data_width) { m_data_width = data_width; return *this; } - address_map_bank_device& addr_width(u8 addr_width) { m_addr_width = addr_width; return *this; } - address_map_bank_device& stride(u32 stride) { m_stride = stride; return *this; } - address_map_bank_device& shift(u32 shift) { m_shift = shift; return *this; } + address_map_bank_device& data_width(uint8_t data_width) { m_data_width = data_width; return *this; } + address_map_bank_device& addr_width(uint8_t addr_width) { m_addr_width = addr_width; return *this; } + address_map_bank_device& stride(uint32_t stride) { m_stride = stride; return *this; } + address_map_bank_device& shift(uint32_t shift) { m_shift = shift; return *this; } void amap8(address_map &map); void amap16(address_map &map); void amap32(address_map &map); void amap64(address_map &map); - void write8(offs_t offset, u8 data); - void write16(offs_t offset, u16 data, u16 mem_mask = 0xffff); - void write32(offs_t offset, u32 data, u32 mem_mask = 0xffffffff); - void write64(offs_t offset, u64 data, u64 mem_mask = ~u64(0)); + DECLARE_WRITE8_MEMBER(write8); + DECLARE_WRITE16_MEMBER(write16); + DECLARE_WRITE32_MEMBER(write32); + DECLARE_WRITE64_MEMBER(write64); - u8 read8(offs_t offset); - u16 read16(offs_t offset, u16 mem_mask = 0xffff); - u32 read32(offs_t offset, u32 mem_mask = 0xffffffff); - u64 read64(offs_t offset, u64 mem_mask = ~u64(0)); + DECLARE_READ8_MEMBER(read8); + DECLARE_READ16_MEMBER(read16); + DECLARE_READ32_MEMBER(read32); + DECLARE_READ64_MEMBER(read64); void set_bank(offs_t offset); @@ -64,9 +64,9 @@ protected: private: // internal state endianness_t m_endianness; - u8 m_data_width; - u8 m_addr_width; - u32 m_stride; + uint8_t m_data_width; + uint8_t m_addr_width; + uint32_t m_stride; address_space_config m_program_config; address_space *m_program; offs_t m_offset; diff --git a/src/devices/machine/clock.h b/src/devices/machine/clock.h index 4bf0bed47a0..32989a15149 100644 --- a/src/devices/machine/clock.h +++ b/src/devices/machine/clock.h @@ -6,11 +6,17 @@ #pragma once +#define MCFG_CLOCK_ADD(_tag, _clock) \ + MCFG_DEVICE_ADD(_tag, CLOCK, _clock) + +#define MCFG_CLOCK_SIGNAL_HANDLER(_devcb) \ + downcast<clock_device &>(*device).set_signal_handler(DEVCB_##_devcb); + class clock_device : public device_t { public: + template <class Object> devcb_base &set_signal_handler(Object &&cb) { return m_signal_handler.set_callback(std::forward<Object>(cb)); } auto signal_handler() { return m_signal_handler.bind(); } - DECLARE_READ_LINE_MEMBER(signal_r) { return m_signal; } clock_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); diff --git a/src/devices/machine/com8116.cpp b/src/devices/machine/com8116.cpp index 06ebfb2f5b0..0a3da24042e 100644 --- a/src/devices/machine/com8116.cpp +++ b/src/devices/machine/com8116.cpp @@ -25,7 +25,6 @@ DEFINE_DEVICE_TYPE(COM8116, com8116_device, "com8116", "COM8116 Dual BRG") DEFINE_DEVICE_TYPE(COM8116_003, com8116_003_device, "com8116_003", "COM8116-003 Dual BRG") DEFINE_DEVICE_TYPE(COM5016_5, com5016_5_device, "com5016_5", "COM5016-5 Dual BRG") DEFINE_DEVICE_TYPE(COM5016_013, com5016_013_device, "com5016_013", "COM5016-013 Dual BRG") -DEFINE_DEVICE_TYPE(COM8116_020, com8116_020_device, "com8116_020", "COM8116-020 Dual BRG") // Parts with T after the number do not have an internal oscillator and require an external clock source // The SMC/COM 5xxx parts are all dual 5v/12v parts, while the 8xxx parts are 5v only @@ -41,6 +40,7 @@ const int com8116_device::divisors_16X_5_0688MHz[16] = // SMC/COM8116-003 and WD WD-1943-03 // from http://www.vintagecomputer.net/fjkraan/comp/divcomp/doc/SMC_BaudGen.pdf page 283 (pdf page 20) // baud rates are 50, 75, 110, 134.5, 150, 200, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800, 9600, 19200 +// SMC/COM8116T-020 should have similar output rates, but clock is unknown and probably different const int com8116_device::divisors_16X_6_01835MHz[16] = { 7523, 5015, 3420, 2797, 2508, 1881, 1254, 627, 313, 209, 188, 157, 104, 78, 39, 20 }; @@ -63,12 +63,6 @@ const int com8116_device::divisors_32X_5_0688MHz[16] = const int com8116_device::divisors_16X_2_7648MHz[16] = { 3456, 2304, 1571, 1285, 1152, 864, 576, 288, 144, 96, 86, 72, 48, 36, 18, 9 }; -// SMC/COM8116T-020 (corrected from http://bitsavers.org/pdf/visualTechnology/Visual_100/MM-100-001-0A_Visual_100_and_Visual_400_Video_Display_Terminal_Maintenance_Manual_Sep1980.pdf (pdf page 99)) -// (75, 134.5 and 2000 baud divisors given as 1,807, 856 and 57, which do not match stated actual frequencies) -// baud rates are 50, 75, 110, 134.5, 150, 200, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800, 9600, 19200 -const int com8116_device::divisors_16X_1_8432MHz[16] = - { 2304, 1536, 1047, 857, 768, 576, 384, 192, 96, 64, 58, 48, 32, 24, 12, 6 }; - // SMC/COM5026(T)-030 (non-standard serial rates, from http://bitsavers.informatik.uni-stuttgart.de/pdf/standardMicrosystems/_dataBooks/1979_StandardMicrosystems.pdf page 135) const int com8116_device::divisors_16X_5_0688MHz_030[16] = { 731, 733, 735, 737, 741, 743, 745, 751, 6970, 5569, 5433, 4752, 4269, 1920, 1584, 301 }; @@ -126,11 +120,6 @@ com5016_013_device::com5016_013_device(const machine_config &mconfig, const char { } -com8116_020_device::com8116_020_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - com8116_device(mconfig, COM8116_020, tag, owner, clock, divisors_16X_1_8432MHz) -{ -} - //------------------------------------------------- // device_start - device-specific startup @@ -204,7 +193,7 @@ void com8116_device::device_timer(emu_timer &timer, device_timer_id id, int para // str_w - //------------------------------------------------- -void com8116_device::str_w(uint8_t data) +void com8116_device::write_str(uint8_t data) { int fr_divider = data & 0x0f; int fr_clock = clock() / m_divisors[fr_divider]; @@ -219,7 +208,7 @@ void com8116_device::str_w(uint8_t data) // stt_w - //------------------------------------------------- -void com8116_device::stt_w(uint8_t data) +void com8116_device::write_stt(uint8_t data) { int ft_divider = data & 0x0f; int ft_clock = clock() / m_divisors[ft_divider]; @@ -234,10 +223,10 @@ void com8116_device::stt_w(uint8_t data) // str_stt_w - //------------------------------------------------- -void com8116_device::str_stt_w(uint8_t data) +WRITE8_MEMBER(com8116_device::str_stt_w) { - str_w(data >> 4); - stt_w(data & 0x0f); + write_str(data >> 4); + write_stt(data & 0x0f); } @@ -245,8 +234,8 @@ void com8116_device::str_stt_w(uint8_t data) // stt_str_w - //------------------------------------------------- -void com8116_device::stt_str_w(uint8_t data) +WRITE8_MEMBER(com8116_device::stt_str_w) { - stt_w(data >> 4); - str_w(data & 0x0f); + write_stt(data >> 4); + write_str(data & 0x0f); } diff --git a/src/devices/machine/com8116.h b/src/devices/machine/com8116.h index d073ceac91f..50c8849e2ee 100644 --- a/src/devices/machine/com8116.h +++ b/src/devices/machine/com8116.h @@ -43,10 +43,12 @@ public: auto fr_handler() { return m_fr_handler.bind(); } auto ft_handler() { return m_ft_handler.bind(); } - void str_w(uint8_t data); - void stt_w(uint8_t data); - void str_stt_w(uint8_t data); - void stt_str_w(uint8_t data); + void write_str(uint8_t data); + void write_stt(uint8_t data); + DECLARE_WRITE8_MEMBER(str_w) { write_str(data); } + DECLARE_WRITE8_MEMBER(stt_w) { write_stt(data); } + DECLARE_WRITE8_MEMBER(str_stt_w); + DECLARE_WRITE8_MEMBER(stt_str_w); protected: com8116_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const int *divisors); @@ -56,7 +58,6 @@ protected: static const int divisors_16X_4_9152MHz[16]; static const int divisors_32X_5_0688MHz[16]; static const int divisors_16X_2_7648MHz[16]; - static const int divisors_16X_1_8432MHz[16]; static const int divisors_16X_5_0688MHz_030[16]; static const int divisors_16X_4_6080MHz[16]; static const int divisors_16X_4_9152MHz_SY2661_1[16]; @@ -122,21 +123,10 @@ public: }; -// ======================> com8116_020_device - -class com8116_020_device : public com8116_device -{ -public: - // construction/destruction - com8116_020_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - - // device type definition DECLARE_DEVICE_TYPE(COM8116, com8116_device) DECLARE_DEVICE_TYPE(COM8116_003, com8116_003_device) DECLARE_DEVICE_TYPE(COM5016_5, com5016_5_device) DECLARE_DEVICE_TYPE(COM5016_013, com5016_013_device) -DECLARE_DEVICE_TYPE(COM8116_020, com8116_020_device) #endif // MAME_MACHINE_COM8116_H diff --git a/src/devices/machine/cr511b.cpp b/src/devices/machine/cr511b.cpp index 6a4309f12c9..066f08575ac 100644 --- a/src/devices/machine/cr511b.cpp +++ b/src/devices/machine/cr511b.cpp @@ -23,13 +23,13 @@ DEFINE_DEVICE_TYPE(CR511B, cr511b_device, "cr511b", "CR-511-B CD-ROM drive") // device_add_mconfig - add device configuration //------------------------------------------------- -void cr511b_device::device_add_mconfig(machine_config &config) -{ - CDROM(config, m_cdrom).set_interface("cdrom"); - CDDA(config, m_cdda); - m_cdda->add_route(0, ":lspeaker", 1.0); - m_cdda->add_route(1, ":rspeaker", 1.0); -} +MACHINE_CONFIG_START(cr511b_device::device_add_mconfig) + MCFG_CDROM_ADD("cdrom") + MCFG_CDROM_INTERFACE("cdrom") + MCFG_DEVICE_ADD("cdda", CDDA) + MCFG_SOUND_ROUTE(0, ":lspeaker", 1.0) + MCFG_SOUND_ROUTE(1, ":rspeaker", 1.0) +MACHINE_CONFIG_END //************************************************************************** diff --git a/src/devices/machine/cs4031.cpp b/src/devices/machine/cs4031.cpp index 13ec9b90a6d..fb1ac37b698 100644 --- a/src/devices/machine/cs4031.cpp +++ b/src/devices/machine/cs4031.cpp @@ -263,19 +263,19 @@ void cs4031_device::device_start() m_space->install_rom(0xffff0000, 0xffffffff, m_bios + 0xf0000); // install i/o accesses - m_space_io->install_readwrite_handler(0x0000, 0x000f, read8sm_delegate(FUNC(am9517a_device::read), &(*m_dma1)), write8sm_delegate(FUNC(am9517a_device::write), &(*m_dma1)), 0xffffffff); + m_space_io->install_readwrite_handler(0x0000, 0x000f, read8_delegate(FUNC(am9517a_device::read), &(*m_dma1)), write8_delegate(FUNC(am9517a_device::write), &(*m_dma1)), 0xffffffff); m_space_io->install_readwrite_handler(0x0020, 0x0023, read8sm_delegate(FUNC(pic8259_device::read), &(*m_intc1)), write8sm_delegate(FUNC(pic8259_device::write), &(*m_intc1)), 0x0000ffff); - m_space_io->install_write_handler(0x0020, 0x0023, write8smo_delegate(FUNC(cs4031_device::config_address_w), this), 0x00ff0000); - m_space_io->install_readwrite_handler(0x0020, 0x0023, read8smo_delegate(FUNC(cs4031_device::config_data_r), this), write8smo_delegate(FUNC(cs4031_device::config_data_w), this), 0xff000000); + m_space_io->install_write_handler(0x0020, 0x0023, write8_delegate(FUNC(cs4031_device::config_address_w), this), 0x00ff0000); + m_space_io->install_readwrite_handler(0x0020, 0x0023, read8_delegate(FUNC(cs4031_device::config_data_r), this), write8_delegate(FUNC(cs4031_device::config_data_w), this), 0xff000000); m_space_io->install_readwrite_handler(0x0040, 0x0043, read8sm_delegate(FUNC(pit8254_device::read), &(*m_ctc)), write8sm_delegate(FUNC(pit8254_device::write), &(*m_ctc)), 0xffffffff); - m_space_io->install_readwrite_handler(0x0060, 0x0063, read8smo_delegate(FUNC(cs4031_device::keyb_data_r), this), write8smo_delegate(FUNC(cs4031_device::keyb_data_w), this), 0x000000ff); - m_space_io->install_readwrite_handler(0x0060, 0x0063, read8smo_delegate(FUNC(cs4031_device::portb_r), this), write8smo_delegate(FUNC(cs4031_device::portb_w), this), 0x0000ff00); - m_space_io->install_readwrite_handler(0x0064, 0x0067, read8smo_delegate(FUNC(cs4031_device::keyb_status_r), this), write8smo_delegate(FUNC(cs4031_device::keyb_command_w), this), 0x000000ff); - m_space_io->install_readwrite_handler(0x0070, 0x0073, read8sm_delegate(FUNC(mc146818_device::read), &(*m_rtc)), write8sm_delegate(FUNC(cs4031_device::rtc_w), this), 0x0000ffff); - m_space_io->install_readwrite_handler(0x0080, 0x008f, read8sm_delegate(FUNC(cs4031_device::dma_page_r), this), write8sm_delegate(FUNC(cs4031_device::dma_page_w), this), 0xffffffff); - m_space_io->install_readwrite_handler(0x0090, 0x0093, read8smo_delegate(FUNC(cs4031_device::sysctrl_r), this), write8smo_delegate(FUNC(cs4031_device::sysctrl_w), this), 0x00ff0000); + m_space_io->install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(cs4031_device::keyb_data_r), this), write8_delegate(FUNC(cs4031_device::keyb_data_w), this), 0x000000ff); + m_space_io->install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(cs4031_device::portb_r), this), write8_delegate(FUNC(cs4031_device::portb_w), this), 0x0000ff00); + m_space_io->install_readwrite_handler(0x0064, 0x0067, read8_delegate(FUNC(cs4031_device::keyb_status_r), this), write8_delegate(FUNC(cs4031_device::keyb_command_w), this), 0x000000ff); + m_space_io->install_readwrite_handler(0x0070, 0x0073, read8_delegate(FUNC(mc146818_device::read), &(*m_rtc)), write8_delegate(FUNC(cs4031_device::rtc_w), this), 0x0000ffff); + m_space_io->install_readwrite_handler(0x0080, 0x008f, read8_delegate(FUNC(cs4031_device::dma_page_r), this), write8_delegate(FUNC(cs4031_device::dma_page_w), this), 0xffffffff); + m_space_io->install_readwrite_handler(0x0090, 0x0093, read8_delegate(FUNC(cs4031_device::sysctrl_r), this), write8_delegate(FUNC(cs4031_device::sysctrl_w), this), 0x00ff0000); m_space_io->install_readwrite_handler(0x00a0, 0x00a3, read8sm_delegate(FUNC(pic8259_device::read), &(*m_intc2)), write8sm_delegate(FUNC(pic8259_device::write), &(*m_intc2)), 0x0000ffff); - m_space_io->install_readwrite_handler(0x00c0, 0x00df, read8sm_delegate(FUNC(cs4031_device::dma2_r),this), write8sm_delegate(FUNC(cs4031_device::dma2_w),this), 0xffffffff); + m_space_io->install_readwrite_handler(0x00c0, 0x00df, read8_delegate(FUNC(cs4031_device::dma2_r),this), write8_delegate(FUNC(cs4031_device::dma2_w),this), 0xffffffff); } //------------------------------------------------- @@ -328,7 +328,7 @@ offs_t cs4031_device::page_offset() return 0xff0000; } -uint8_t cs4031_device::dma_read_byte(offs_t offset) +READ8_MEMBER( cs4031_device::dma_read_byte ) { if (m_dma_channel == -1) return 0xff; @@ -336,7 +336,7 @@ uint8_t cs4031_device::dma_read_byte(offs_t offset) return m_space->read_byte(page_offset() + offset); } -void cs4031_device::dma_write_byte(offs_t offset, uint8_t data) +WRITE8_MEMBER( cs4031_device::dma_write_byte ) { if (m_dma_channel == -1) return; @@ -344,7 +344,7 @@ void cs4031_device::dma_write_byte(offs_t offset, uint8_t data) m_space->write_byte(page_offset() + offset, data); } -uint8_t cs4031_device::dma_read_word(offs_t offset) +READ8_MEMBER( cs4031_device::dma_read_word ) { if (m_dma_channel == -1) return 0xff; @@ -355,7 +355,7 @@ uint8_t cs4031_device::dma_read_word(offs_t offset) return result; } -void cs4031_device::dma_write_word(offs_t offset, uint8_t data) +WRITE8_MEMBER( cs4031_device::dma_write_word ) { if (m_dma_channel == -1) return; @@ -377,8 +377,6 @@ WRITE_LINE_MEMBER( cs4031_device::dma1_eop_w ) void cs4031_device::set_dma_channel(int channel, bool state) { - //m_write_dack(channel, state); - if (!state) { m_dma_channel = channel; @@ -431,7 +429,7 @@ void cs4031_device::trigger_nmi() } } -uint8_t cs4031_device::intc1_slave_ack_r(offs_t offset) +READ8_MEMBER( cs4031_device::intc1_slave_ack_r ) { if (offset == 2) // IRQ 2 return m_intc2->acknowledge(); @@ -478,13 +476,13 @@ WRITE_LINE_MEMBER( cs4031_device::ctc_out2_w ) // CHIPSET CONFIGURATION //************************************************************************** -void cs4031_device::config_address_w(uint8_t data) +WRITE8_MEMBER( cs4031_device::config_address_w ) { m_address = data; m_address_valid = (m_address < 0x20) ? true : false; } -uint8_t cs4031_device::config_data_r() +READ8_MEMBER( cs4031_device::config_data_r ) { uint8_t result = 0xff; @@ -501,7 +499,7 @@ uint8_t cs4031_device::config_data_r() return result; } -void cs4031_device::config_data_w(uint8_t data) +WRITE8_MEMBER( cs4031_device::config_data_w ) { if (m_address_valid) { @@ -694,21 +692,21 @@ void cs4031_device::keyboard_gatea20(int state) update_a20m(); } -uint8_t cs4031_device::keyb_status_r() +READ8_MEMBER( cs4031_device::keyb_status_r ) { LOGKEYBOARD("cs4031_device::keyb_status_r\n"); - return m_keybc->status_r(); + return m_keybc->status_r(space, 0); } -void cs4031_device::keyb_command_blocked_w(uint8_t data) +WRITE8_MEMBER( cs4031_device::keyb_command_blocked_w ) { // command is optionally blocked if (!BIT(m_registers[SOFT_RESET_AND_GATEA20], 7)) - m_keybc->command_w(data); + m_keybc->command_w(space, 0, data); } -void cs4031_device::keyb_command_w(uint8_t data) +WRITE8_MEMBER( cs4031_device::keyb_command_w ) { LOGKEYBOARD("cs4031_device::keyb_command_w: %02x\n", data); @@ -722,12 +720,12 @@ void cs4031_device::keyb_command_w(uint8_t data) emulated_gatea20(1); // self-test is never blocked - m_keybc->command_w(data); + m_keybc->command_w(space, 0, data); break; case 0xd1: m_keybc_d1_written = true; - keyb_command_blocked_w(data); + keyb_command_blocked_w(space, 0, data); break; case 0xf0: @@ -756,7 +754,7 @@ void cs4031_device::keyb_command_w(uint8_t data) emulated_gatea20(1); } - keyb_command_blocked_w(data); + keyb_command_blocked_w(space, 0, data); break; @@ -765,28 +763,28 @@ void cs4031_device::keyb_command_w(uint8_t data) if (m_keybc_data_blocked) { m_keybc_data_blocked = false; - keyb_command_blocked_w(data); + keyb_command_blocked_w(space, 0, data); } else - m_keybc->command_w(data); + m_keybc->command_w(space, 0, data); break; // everything else goes directly to the keyboard controller default: - m_keybc->command_w(data); + m_keybc->command_w(space, 0, data); break; } } -uint8_t cs4031_device::keyb_data_r() +READ8_MEMBER( cs4031_device::keyb_data_r ) { LOGKEYBOARD("cs4031_device::keyb_data_r\n"); - return m_keybc->data_r(); + return m_keybc->data_r(space, 0); } -void cs4031_device::keyb_data_w(uint8_t data) +WRITE8_MEMBER( cs4031_device::keyb_data_w ) { LOGKEYBOARD("cs4031_device::keyb_data_w: %02x\n", data); @@ -800,7 +798,7 @@ void cs4031_device::keyb_data_w(uint8_t data) else { m_keybc_data_blocked = false; - m_keybc->data_w(data); + m_keybc->data_w(space, 0, data); } } @@ -839,7 +837,7 @@ WRITE_LINE_MEMBER( cs4031_device::kbrst_w ) 1 - Fast Gate A20 */ -void cs4031_device::sysctrl_w(uint8_t data) +WRITE8_MEMBER( cs4031_device::sysctrl_w ) { LOGIO("cs4031_device::sysctrl_w: %u\n", data); @@ -855,7 +853,7 @@ void cs4031_device::sysctrl_w(uint8_t data) m_cpureset = BIT(data, 0); } -uint8_t cs4031_device::sysctrl_r() +READ8_MEMBER( cs4031_device::sysctrl_r ) { uint8_t result = 0; // reserved bits read as 0? @@ -885,7 +883,7 @@ uint8_t cs4031_device::sysctrl_r() 7 - Parity check latch (r) [not emulated] */ -uint8_t cs4031_device::portb_r() +READ8_MEMBER( cs4031_device::portb_r ) { if (0) logerror("cs4031_device::portb_r: %02x\n", m_portb); @@ -893,7 +891,7 @@ uint8_t cs4031_device::portb_r() return m_portb; } -void cs4031_device::portb_w(uint8_t data) +WRITE8_MEMBER( cs4031_device::portb_w ) { if (0) logerror("cs4031_device::portb_w: %02x\n", data); @@ -919,7 +917,7 @@ void cs4031_device::portb_w(uint8_t data) 7 - NMI mask 6:0 - RTC address */ -void cs4031_device::rtc_w(offs_t offset, uint8_t data) +WRITE8_MEMBER( cs4031_device::rtc_w ) { if (0) logerror("cs4031_device::rtc_w: %02x\n", data); @@ -930,5 +928,5 @@ void cs4031_device::rtc_w(offs_t offset, uint8_t data) data &= 0x7f; } - m_rtc->write(offset, data); + m_rtc->write(space, offset, data); } diff --git a/src/devices/machine/cs4031.h b/src/devices/machine/cs4031.h index 3e554e91904..e8b6e314f93 100644 --- a/src/devices/machine/cs4031.h +++ b/src/devices/machine/cs4031.h @@ -59,23 +59,23 @@ public: auto spkr() { return m_write_spkr.bind(); } // internal io - void config_address_w(uint8_t data); - uint8_t config_data_r(); - void config_data_w(uint8_t data); - uint8_t portb_r(); - void portb_w(uint8_t data); - void rtc_w(offs_t offset, uint8_t data); - void sysctrl_w(uint8_t data); - uint8_t sysctrl_r(); - uint8_t dma_page_r(offs_t offset) { return m_dma_page[offset]; } - void dma_page_w(offs_t offset, uint8_t data) { m_dma_page[offset] = data; } - uint8_t dma2_r(offs_t offset) { return m_dma2->read(offset / 2); } - void dma2_w(offs_t offset, uint8_t data) { m_dma2->write(offset / 2, data); } - uint8_t keyb_data_r(); - void keyb_data_w(uint8_t data); - uint8_t keyb_status_r(); - void keyb_command_w(uint8_t data); - void keyb_command_blocked_w(uint8_t data); + DECLARE_WRITE8_MEMBER( config_address_w ); + DECLARE_READ8_MEMBER( config_data_r ); + DECLARE_WRITE8_MEMBER( config_data_w ); + DECLARE_READ8_MEMBER( portb_r ); + DECLARE_WRITE8_MEMBER( portb_w ); + DECLARE_WRITE8_MEMBER( rtc_w ); + DECLARE_WRITE8_MEMBER( sysctrl_w ); + DECLARE_READ8_MEMBER( sysctrl_r ); + DECLARE_READ8_MEMBER( dma_page_r ) { return m_dma_page[offset]; } + DECLARE_WRITE8_MEMBER( dma_page_w ) { m_dma_page[offset] = data; } + DECLARE_READ8_MEMBER( dma2_r ) { return m_dma2->read(space, offset / 2); } + DECLARE_WRITE8_MEMBER( dma2_w ) { m_dma2->write(space, offset / 2, data); } + DECLARE_READ8_MEMBER( keyb_data_r ); + DECLARE_WRITE8_MEMBER( keyb_data_w ); + DECLARE_READ8_MEMBER( keyb_status_r ); + DECLARE_WRITE8_MEMBER( keyb_command_w ); + DECLARE_WRITE8_MEMBER( keyb_command_blocked_w ); // input lines DECLARE_WRITE_LINE_MEMBER( irq01_w ) { m_intc1->ir1_w(state); } @@ -205,25 +205,25 @@ private: uint8_t m_registers[0x20]; - uint8_t dma_read_byte(offs_t offset); - void dma_write_byte(offs_t offset, uint8_t data); - uint8_t dma_read_word(offs_t offset); - void dma_write_word(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( dma_read_byte ); + DECLARE_WRITE8_MEMBER( dma_write_byte ); + DECLARE_READ8_MEMBER( dma_read_word ); + DECLARE_WRITE8_MEMBER( dma_write_word ); DECLARE_WRITE_LINE_MEMBER( dma1_eop_w ); - uint8_t dma1_ior0_r() { return m_read_ior(0); } - uint8_t dma1_ior1_r() { return m_read_ior(1); } - uint8_t dma1_ior2_r() { return m_read_ior(2); } - uint8_t dma1_ior3_r() { return m_read_ior(3); } - uint8_t dma2_ior1_r() { uint16_t const result = m_read_ior(5); m_dma_high_byte = result >> 8; return result; } - uint8_t dma2_ior2_r() { uint16_t const result = m_read_ior(6); m_dma_high_byte = result >> 8; return result; } - uint8_t dma2_ior3_r() { uint16_t const result = m_read_ior(7); m_dma_high_byte = result >> 8; return result; } - void dma1_iow0_w(uint8_t data) { m_write_iow(0, data, 0xffff); } - void dma1_iow1_w(uint8_t data) { m_write_iow(1, data, 0xffff); } - void dma1_iow2_w(uint8_t data) { m_write_iow(2, data, 0xffff); } - void dma1_iow3_w(uint8_t data) { m_write_iow(3, data, 0xffff); } - void dma2_iow1_w(uint8_t data) { m_write_iow(5, (m_dma_high_byte << 8) | data, 0xffff); } - void dma2_iow2_w(uint8_t data) { m_write_iow(6, (m_dma_high_byte << 8) | data, 0xffff); } - void dma2_iow3_w(uint8_t data) { m_write_iow(7, (m_dma_high_byte << 8) | data, 0xffff); } + DECLARE_READ8_MEMBER( dma1_ior0_r ) { return m_read_ior(0); } + DECLARE_READ8_MEMBER( dma1_ior1_r ) { return m_read_ior(1); } + DECLARE_READ8_MEMBER( dma1_ior2_r ) { return m_read_ior(2); } + DECLARE_READ8_MEMBER( dma1_ior3_r ) { return m_read_ior(3); } + DECLARE_READ8_MEMBER( dma2_ior1_r ) { uint16_t const result = m_read_ior(5); m_dma_high_byte = result >> 8; return result; } + DECLARE_READ8_MEMBER( dma2_ior2_r ) { uint16_t const result = m_read_ior(6); m_dma_high_byte = result >> 8; return result; } + DECLARE_READ8_MEMBER( dma2_ior3_r ) { uint16_t const result = m_read_ior(7); m_dma_high_byte = result >> 8; return result; } + DECLARE_WRITE8_MEMBER( dma1_iow0_w ) { m_write_iow(0, data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma1_iow1_w ) { m_write_iow(1, data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma1_iow2_w ) { m_write_iow(2, data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma1_iow3_w ) { m_write_iow(3, data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma2_iow1_w ) { m_write_iow(5, (m_dma_high_byte << 8) | data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma2_iow2_w ) { m_write_iow(6, (m_dma_high_byte << 8) | data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma2_iow3_w ) { m_write_iow(7, (m_dma_high_byte << 8) | data, 0xffff); } DECLARE_WRITE_LINE_MEMBER( dma1_dack0_w ) { set_dma_channel(0, state); } DECLARE_WRITE_LINE_MEMBER( dma1_dack1_w ) { set_dma_channel(1, state); } DECLARE_WRITE_LINE_MEMBER( dma1_dack2_w ) { set_dma_channel(2, state); } @@ -234,7 +234,7 @@ private: DECLARE_WRITE_LINE_MEMBER( dma2_dack3_w ) { set_dma_channel(7, state); } DECLARE_WRITE_LINE_MEMBER( dma2_hreq_w ) { m_write_hold(state); } DECLARE_WRITE_LINE_MEMBER( intc1_int_w ) { m_write_intr(state); } - uint8_t intc1_slave_ack_r(offs_t offset); + DECLARE_READ8_MEMBER( intc1_slave_ack_r ); DECLARE_WRITE_LINE_MEMBER( ctc_out1_w ); DECLARE_WRITE_LINE_MEMBER( ctc_out2_w ); }; diff --git a/src/devices/machine/diablo_hd.cpp b/src/devices/machine/diablo_hd.cpp index 36c57cbd0d7..669285ccb08 100644 --- a/src/devices/machine/diablo_hd.cpp +++ b/src/devices/machine/diablo_hd.cpp @@ -1324,9 +1324,11 @@ void diablo_hd_device::device_start() void diablo_hd_device::device_reset() { // free previous page cache - for (int page = 0; page < m_pages; page++) - if (m_cache[page]) - m_cache[page] = nullptr; + if (m_cache) { + for (int page = 0; page < m_pages; page++) + if (m_cache[page]) + m_cache[page] = nullptr; + } // free previous bits cache if (m_bits) { for (int page = 0; page < m_pages; page++) @@ -1440,10 +1442,9 @@ void diablo_hd_device::device_timer(emu_timer &timer, device_timer_id id, int pa } } -void diablo_hd_device::device_add_mconfig(machine_config &config) -{ - DIABLO(config, "drive", 0); -} +MACHINE_CONFIG_START(diablo_hd_device::device_add_mconfig) + MCFG_DIABLO_ADD("drive") +MACHINE_CONFIG_END DEFINE_DEVICE_TYPE(DIABLO_HD, diablo_hd_device, "diablo_hd", "Diablo Disk") diff --git a/src/devices/machine/diablo_hd.h b/src/devices/machine/diablo_hd.h index 93915e628e3..41f206cc531 100644 --- a/src/devices/machine/diablo_hd.h +++ b/src/devices/machine/diablo_hd.h @@ -162,4 +162,7 @@ private: void sector_mark_0(); }; +#define MCFG_DIABLO_DRIVES_ADD() \ + MCFG_DEVICE_ADD(DIABLO_HD_0, DIABLO_HD, 3333333) \ + MCFG_DEVICE_ADD(DIABLO_HD_1, DIABLO_HD, 3333333) #endif // !defined(_DIABLO_HD_DEVICE_) diff --git a/src/devices/machine/dp8390.h b/src/devices/machine/dp8390.h index c13fe53e1d3..74b57f027d1 100644 --- a/src/devices/machine/dp8390.h +++ b/src/devices/machine/dp8390.h @@ -8,13 +8,38 @@ // device stuff +#define MCFG_DP8390D_IRQ_CB(_devcb) \ + downcast<dp8390_device &>(*device).set_irq_callback(DEVCB_##_devcb); + +#define MCFG_DP8390D_BREQ_CB(_devcb) \ + downcast<dp8390_device &>(*device).set_breq_callback(DEVCB_##_devcb); + +#define MCFG_DP8390D_MEM_READ_CB(_devcb) \ + downcast<dp8390_device &>(*device).set_mem_read_callback(DEVCB_##_devcb); + +#define MCFG_DP8390D_MEM_WRITE_CB(_devcb) \ + downcast<dp8390_device &>(*device).set_mem_write_callback(DEVCB_##_devcb); + +#define MCFG_RTL8019A_IRQ_CB(_devcb) \ + downcast<rtl8019a_device &>(*device).set_irq_callback(DEVCB_##_devcb); + +#define MCFG_RTL8019A_BREQ_CB(_devcb) \ + downcast<rtl8019a_device &>(*device).set_breq_callback(DEVCB_##_devcb); + +#define MCFG_RTL8019A_MEM_READ_CB(_devcb) \ + downcast<rtl8019a_device &>(*device).set_mem_read_callback(DEVCB_##_devcb); + +#define MCFG_RTL8019A_MEM_WRITE_CB(_devcb) \ + downcast<rtl8019a_device &>(*device).set_mem_write_callback(DEVCB_##_devcb); + + class dp8390_device : public device_t, public device_network_interface { public: - auto irq_callback() { return m_irq_cb.bind(); } - auto breq_callback() { return m_breq_cb.bind(); } - auto mem_read_callback() { return m_mem_read_cb.bind(); } - auto mem_write_callback() { return m_mem_write_cb.bind(); } + template <class Object> devcb_base &set_irq_callback(Object &&cb) { return m_irq_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_breq_callback(Object &&cb) { return m_breq_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_mem_read_callback(Object &&cb) { return m_mem_read_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_mem_write_callback(Object &&cb) { return m_mem_write_cb.set_callback(std::forward<Object>(cb)); } DECLARE_WRITE16_MEMBER( dp8390_w ); DECLARE_READ16_MEMBER( dp8390_r ); diff --git a/src/devices/machine/dp83932c.cpp b/src/devices/machine/dp83932c.cpp index 82d70f02797..c8c7fcfcd9e 100644 --- a/src/devices/machine/dp83932c.cpp +++ b/src/devices/machine/dp83932c.cpp @@ -20,99 +20,112 @@ #define VERBOSE 0 #include "logmacro.h" -DEFINE_DEVICE_TYPE(DP83932C, dp83932c_device, "dp83932c", "National Semiconductor DP83932C SONIC") +DEFINE_DEVICE_TYPE(DP83932C_BE, dp83932c_be_device, "dp83932c_be", "National Semiconductor DP83932C SONIC (big)") +DEFINE_DEVICE_TYPE(DP83932C_LE, dp83932c_le_device, "dp83932c_le", "National Semiconductor DP83932C SONIC (little)") -dp83932c_device::dp83932c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, DP83932C, tag, owner, clock) +dp83932c_device::dp83932c_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endian) + : device_t(mconfig, type, tag, owner, clock) + , device_memory_interface(mconfig, *this) , device_network_interface(mconfig, *this, 10.0f) - , m_ram(*this, finder_base::DUMMY_TAG) + , m_space_config("shared", endian, 32, 32) , m_out_int(*this) { } +dp83932c_be_device::dp83932c_be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : dp83932c_device(mconfig, DP83932C_BE, tag, owner, clock, ENDIANNESS_BIG) +{ +} + +dp83932c_le_device::dp83932c_le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : dp83932c_device(mconfig, DP83932C_LE, tag, owner, clock, ENDIANNESS_LITTLE) +{ +} + void dp83932c_device::map(address_map &map) { - // datasheet uses unshifted register addresses - int const shift = 1; - - // command and status registers - map(0x00 << shift, (0x00 << shift) | 0x01).rw(FUNC(dp83932c_device::cr_r), FUNC(dp83932c_device::cr_w)); - //map(0x01 << shift, (0x01 << shift) | 0x01).rw(FUNC(dp83932c_device::dcr_r), FUNC(dp83932c_device::dcr_w)); - //map(0x02 << shift, (0x02 << shift) | 0x01).rw(FUNC(dp83932c_device::rcr_r), FUNC(dp83932c_device::rcr_w)); - map(0x03 << shift, (0x03 << shift) | 0x01).rw(FUNC(dp83932c_device::tcr_r), FUNC(dp83932c_device::tcr_w)); - //map(0x04 << shift, (0x04 << shift) | 0x01).rw(FUNC(dp83932c_device::imr_r), FUNC(dp83932c_device::imr_w)); - map(0x05 << shift, (0x05 << shift) | 0x01).rw(FUNC(dp83932c_device::isr_r), FUNC(dp83932c_device::isr_w)); - - // transmit registers - map(0x06 << shift, (0x06 << shift) | 0x01).rw(FUNC(dp83932c_device::utda_r), FUNC(dp83932c_device::utda_w)); - //map(0x07 << shift, (0x07 << shift) | 0x01).rw(FUNC(dp83932c_device::ctda_r), FUNC(dp83932c_device::ctda_w)); - - // tps - // tfc - // tsa0 - // tsa1 - // tfs - - // receive registers - //map(0x0d << shift, (0x0d << shift) | 0x01).rw(FUNC(dp83932c_device::urda_r), FUNC(dp83932c_device::urda_w)); - map(0x0e << shift, (0x0e << shift) | 0x01).rw(FUNC(dp83932c_device::crda_r), FUNC(dp83932c_device::crda_w)); - - // crba0 - // crba1 - // rbwc0 - // rbwc1 - // eobc - // urra - // rsa - // rea - map(0x17 << shift, (0x17 << shift) | 0x01).rw(FUNC(dp83932c_device::rrp_r), FUNC(dp83932c_device::rrp_w)); - map(0x18 << shift, (0x18 << shift) | 0x01).rw(FUNC(dp83932c_device::rwp_r), FUNC(dp83932c_device::rwp_w)); - // trba0 - // trba1 - // tbwc0 - // tbwc1 - // addr0 - // addr1 - // llfa - // ttda - // cep - // cap2 - // cap1 - // cap0 - map(0x25 << shift, (0x25 << shift) | 0x01).rw(FUNC(dp83932c_device::ce_r), FUNC(dp83932c_device::ce_w)); - // cdp - // cdc - // sr - map(0x29 << shift, (0x29 << shift) | 0x01).rw(FUNC(dp83932c_device::wt0_r), FUNC(dp83932c_device::wt0_w)); - map(0x2a << shift, (0x2a << shift) | 0x01).rw(FUNC(dp83932c_device::wt1_r), FUNC(dp83932c_device::wt1_w)); - map(0x2b << shift, (0x2b << shift) | 0x01).rw(FUNC(dp83932c_device::rsc_r), FUNC(dp83932c_device::rsc_w)); - // crct - map(0x2d << shift, (0x2d << shift) | 0x01).rw(FUNC(dp83932c_device::faet_r), FUNC(dp83932c_device::faet_w)); - // mpt - // mdt - - // 30-3e internal use registers - // dcr2 +/* + // command and status registers + map(0x00, 0x03).rw(FUNC(dp83932c_device::cr_r), FUNC(dp83932c_device::cr_w)); + map(0x04, 0x07).rw(FUNC(dp83932c_device::dcr_r), FUNC(dp83932c_device::dcr_w)); + map(0x08, 0x0b).rw(FUNC(dp83932c_device::rcr_r), FUNC(dp83932c_device::rcr_w)); + map(0x0c, 0x0f).rw(FUNC(dp83932c_device::tcr_r), FUNC(dp83932c_device::tcr_w)); + map(0x10, 0x13).rw(FUNC(dp83932c_device::imr_r), FUNC(dp83932c_device::imr_w)); + map(0x14, 0x17).rw(FUNC(dp83932c_device::isr_r), FUNC(dp83932c_device::isr_w)); + + // transmit registers + map(0x18, 0x1b).rw(FUNC(dp83932c_device::utda_r), FUNC(dp83932c_device::utda_w)); + map(0x1c, 0x1f).rw(FUNC(dp83932c_device::ctda_r), FUNC(dp83932c_device::ctda_w)); + + // tps + // tfc + // tsa0 + // tsa1 + // tfs + + // receive registers + map(0x34, 0x37).rw(FUNC(dp83932c_device::urda_r), FUNC(dp83932c_device::urda_w)); + map(0x38, 0x3b).rw(FUNC(dp83932c_device::crda_r), FUNC(dp83932c_device::crda_w)); + + // crba0 + // crba1 + // rbwc0 + // rbwc1 + // eobc + // urra + // rsa + // rea + // rrp + // rwp + // trba0 + // trba1 + // tbwc0 + // tbwc1 + // addr0 + // addr1 + // llfa + // ttda + // cep + // cap2 + // cap1 + // cap0 + // ce + // cdp + // cdc + // sr + // wt0 + // wt1 + // rsc + // crct + // faet + // mpt + // mdt + + // 30-3e internal use registers +*/ } void dp83932c_device::device_start() { + m_space = &space(0); m_out_int.resolve(); } void dp83932c_device::device_reset() { - m_cr = RST | STP | RXDIS; - m_tcr = NCRS | PTX; - m_isr = 0; - m_ce = 0; - m_rsc = 0; } void dp83932c_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { } +device_memory_interface::space_config_vector dp83932c_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(0, &m_space_config) + }; +} + void dp83932c_device::send_complete_cb(int result) { } diff --git a/src/devices/machine/dp83932c.h b/src/devices/machine/dp83932c.h index e608f7508a6..27f5ae60d85 100644 --- a/src/devices/machine/dp83932c.h +++ b/src/devices/machine/dp83932c.h @@ -6,113 +6,54 @@ #pragma once -#include "machine/ram.h" - -class dp83932c_device - : public device_t - , public device_network_interface +class dp83932c_device : + public device_t, + public device_memory_interface, + public device_network_interface { public: - dp83932c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - static constexpr feature_type imperfect_features() { return feature::LAN; } - - // configuration - template <typename T> void set_ram(T &&tag) { m_ram.set_tag(std::forward<T>(tag)); } + // callback configuration auto out_int_cb() { return m_out_int.bind(); } void map(address_map &map); protected: + dp83932c_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endian); + // device_t overrides virtual void device_start() override; virtual void device_reset() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + // device_network_interface overrides virtual void send_complete_cb(int result) override; virtual int recv_start_cb(u8 *buf, int length) override; virtual void recv_complete_cb(int result) override; - enum cr_mask : u16 - { - HTX = 0x0001, // halt transmission - TXP = 0x0002, // transmit packets - RXDIS = 0x0004, // receiver disable - RXEN = 0x0008, // receiver enable - STP = 0x0010, // stop timer - ST = 0x0020, // start timer - RST = 0x0080, // software reset - RRRA = 0x0100, // read rra - LCAM = 0x0200, // load cam - - CR_WMASK = 0x03bf - }; - - enum tcr_mask : u16 - { - PTX = 0x0001, // packet transmitted ok - BCM = 0x0002, // byte count mismatch - FU = 0x0004, // fifo underrun - PMB = 0x0008, // packet monitored bad - OWC = 0x0020, // out of window collision - EXC = 0x0040, // excessive collisions - CRSL = 0x0080, // crs lost - NCRS = 0x0100, // no crs - DEF = 0x0200, // deferred transmission - EXD = 0x0400, // excessive deferral - EXDIS = 0x1000, // disable excessive deferral timer - CRCI = 0x2000, // crc inhibit - POWC = 0x4000, // programmed out of window collision timer - PINT = 0x8000, // programmable interrupt - - TCR_WMASK = 0xf000 - }; - - u16 cr_r() { return m_cr; } - u16 tcr_r() { return m_tcr; } - u16 utda_r() { return m_utda; } - u16 crda_r() { return m_crda; } - u16 rrp_r() { return m_rrp; } - u16 rwp_r() { return m_rwp; } - u16 isr_r() { return m_isr; } - u16 ce_r() { return m_ce; } - u16 wt0_r() { return m_wt0; } - u16 wt1_r() { return m_wt1; } - u16 rsc_r() { return m_rsc; } - u16 faet_r() { return m_faet; } - - void cr_w(u16 data) { m_cr = (data & CR_WMASK) | (m_cr & ~CR_WMASK); } - void tcr_w(u16 data) { m_tcr = (data & TCR_WMASK) | (m_tcr & ~TCR_WMASK); } - void utda_w(u16 data) { m_utda = data; } - void crda_w(u16 data) { m_crda = data; } - void rrp_w(u16 data) { m_rrp = data; } - void rwp_w(u16 data) { m_rwp = data; } - void isr_w(u16 data) { m_isr = data; } - void ce_w(u16 data) { m_ce = data; } - void wt0_w(u16 data) { m_wt0 = data; } - void wt1_w(u16 data) { m_wt1 = data; } - void rsc_w(u16 data) { m_rsc = data; } - void faet_w(u16 data) { m_faet = ~data; } - private: - required_device<ram_device> m_ram; + // device_memory_interface members + const address_space_config m_space_config; + address_space *m_space; devcb_write_line m_out_int; +}; + +class dp83932c_be_device : public dp83932c_device +{ +public: + dp83932c_be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; - u16 m_cr; - u16 m_tcr; - u16 m_utda; - u16 m_crda; - u16 m_rrp; - u16 m_rwp; - u16 m_isr; - u16 m_ce; - u16 m_wt0; - u16 m_wt1; - u16 m_rsc; - u16 m_faet; +class dp83932c_le_device : public dp83932c_device +{ +public: + dp83932c_le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; -DECLARE_DEVICE_TYPE(DP83932C, dp83932c_device) +DECLARE_DEVICE_TYPE(DP83932C_BE, dp83932c_be_device) +DECLARE_DEVICE_TYPE(DP83932C_LE, dp83932c_le_device) #endif // MAME_MACHINE_DP83932C_H diff --git a/src/devices/machine/ds1204.h b/src/devices/machine/ds1204.h index 59dc5718989..12bc61657e4 100644 --- a/src/devices/machine/ds1204.h +++ b/src/devices/machine/ds1204.h @@ -13,6 +13,9 @@ #pragma once +#define MCFG_DS1204_ADD( _tag ) \ + MCFG_DEVICE_ADD( _tag, DS1204, 0 ) + class ds1204_device : public device_t, public device_nvram_interface { public: diff --git a/src/devices/machine/ds1205.h b/src/devices/machine/ds1205.h index ad7432e1ac7..7f854d901fc 100644 --- a/src/devices/machine/ds1205.h +++ b/src/devices/machine/ds1205.h @@ -13,6 +13,9 @@ #pragma once +#define MCFG_DS1205_ADD( _tag ) \ + MCFG_DEVICE_ADD( _tag, DS1205, 0 ) + class ds1205_device : public device_t, public device_nvram_interface { public: diff --git a/src/devices/machine/ds128x.cpp b/src/devices/machine/ds128x.cpp index 91e022e07e7..7a397aab303 100644 --- a/src/devices/machine/ds128x.cpp +++ b/src/devices/machine/ds128x.cpp @@ -10,12 +10,7 @@ DEFINE_DEVICE_TYPE(DS12885, ds12885_device, "ds12885", "DS12885 RTC/NVRAM") //------------------------------------------------- ds12885_device::ds12885_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ds12885_device(mconfig, DS12885, tag, owner, clock) -{ -} - -ds12885_device::ds12885_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : mc146818_device(mconfig, type, tag, owner, clock) + : mc146818_device(mconfig, DS12885, tag, owner, clock) { } @@ -28,54 +23,3 @@ int ds12885_device::get_timer_bypass() return 22; // No tick } - -DEFINE_DEVICE_TYPE(DS12885EXT, ds12885ext_device, "ds12885ext", "DS12885 RTC/NVRAM size 256 bytes") - -//------------------------------------------------- -// ds12885ext_device - constructor -//------------------------------------------------- - -ds12885ext_device::ds12885ext_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ds12885_device(mconfig, DS12885EXT, tag, owner, clock) -{ -} - -//------------------------------------------------- -// ds12885ext_device - handlers that allow acces to extended memory size -//------------------------------------------------- - -uint8_t ds12885ext_device::read_extended(offs_t offset) -{ - switch (offset) - { - case 0: - case 1: - return read(offset); - break; - case 2: - case 3: - return read(offset - 2); - break; - default: - return 0xff; - } -} - -void ds12885ext_device::write_extended(offs_t offset, uint8_t data) -{ - switch (offset) - { - case 0: - write(offset, data & 127); - break; - case 1: - write(offset, data); - break; - case 2: - write(offset - 2, data); - break; - case 3: - write(offset - 2, data); - break; - } -} diff --git a/src/devices/machine/ds128x.h b/src/devices/machine/ds128x.h index 7ade1bfa431..671d3ee0a6f 100644 --- a/src/devices/machine/ds128x.h +++ b/src/devices/machine/ds128x.h @@ -5,8 +5,10 @@ #include "mc146818.h" +#define MCFG_DS12885_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, DS12885, XTAL(32'768)) -// ======================> ds12885_device +// ======================> mc146818_device class ds12885_device : public mc146818_device { @@ -15,8 +17,6 @@ public: ds12885_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 32'768); protected: - ds12885_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - virtual int data_size() override { return 128; } virtual int get_timer_bypass() override; }; @@ -24,23 +24,4 @@ protected: // device type definition DECLARE_DEVICE_TYPE(DS12885, ds12885_device) -// ======================> ds12885ext_device - -class ds12885ext_device : public ds12885_device -{ -public: - // construction/destruction - ds12885ext_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 32'768); - - // read/write access to extended ram - uint8_t read_extended(offs_t offset); - void write_extended(offs_t offset, uint8_t data); - -protected: - virtual int data_size() override { return 256; } -}; - -// device type definition -DECLARE_DEVICE_TYPE(DS12885EXT, ds12885ext_device) - #endif // MAME_MACHINE_DS128X_H diff --git a/src/devices/machine/ds1315.cpp b/src/devices/machine/ds1315.cpp index 2a574dca399..6b37957f9eb 100644 --- a/src/devices/machine/ds1315.cpp +++ b/src/devices/machine/ds1315.cpp @@ -87,17 +87,17 @@ static const uint8_t ds1315_pattern[] = ***************************************************************************/ // automated read, does all the work the real Dallas chip does -uint8_t ds1315_device::read(offs_t offset) +READ8_MEMBER( ds1315_device::read ) { if (m_mode == DS_SEEK_MATCHING) { if (offset & 1) { - read_1(); + read_1(space, 0); } else { - read_0(); + read_0(space, 0); } if (offset & 4) @@ -110,7 +110,7 @@ uint8_t ds1315_device::read(offs_t offset) } else if (m_mode == DS_CALENDAR_IO) { - return read_data(); + return read_data(space, offset); } return 0xff; // shouldn't happen, but compilers don't know that @@ -121,7 +121,7 @@ uint8_t ds1315_device::read(offs_t offset) read_0 (actual data) -------------------------------------------------*/ -uint8_t ds1315_device::read_0() +READ8_MEMBER( ds1315_device::read_0 ) { if (ds1315_pattern[m_count++] == 0) { @@ -145,7 +145,7 @@ uint8_t ds1315_device::read_0() read_1 (actual data) -------------------------------------------------*/ -uint8_t ds1315_device::read_1() +READ8_MEMBER( ds1315_device::read_1 ) { if (ds1315_pattern[m_count++] == 1) { @@ -163,7 +163,7 @@ uint8_t ds1315_device::read_1() read_data -------------------------------------------------*/ -uint8_t ds1315_device::read_data() +READ8_MEMBER( ds1315_device::read_data ) { uint8_t result; @@ -228,7 +228,7 @@ void ds1315_device::fill_raw_data() write_data -------------------------------------------------*/ -uint8_t ds1315_device::write_data(offs_t offset) +READ8_MEMBER(ds1315_device::write_data) { static int write_count; if (write_count >= 64) diff --git a/src/devices/machine/ds1315.h b/src/devices/machine/ds1315.h index 720c4a08202..a5b70c38c76 100644 --- a/src/devices/machine/ds1315.h +++ b/src/devices/machine/ds1315.h @@ -24,12 +24,12 @@ public: auto read_backing() { return m_backing_read.bind(); } // this handler automates the bits 0/2 stuff - uint8_t read(offs_t offset); + DECLARE_READ8_MEMBER(read); - uint8_t read_0(); - uint8_t read_1(); - uint8_t read_data(); - uint8_t write_data(offs_t offset); + DECLARE_READ8_MEMBER(read_0); + DECLARE_READ8_MEMBER(read_1); + DECLARE_READ8_MEMBER(read_data); + DECLARE_READ8_MEMBER(write_data); bool chip_enable(); void chip_reset(); diff --git a/src/devices/machine/ds75160a.h b/src/devices/machine/ds75160a.h index bdc03e9dc99..2f2a2147a5e 100644 --- a/src/devices/machine/ds75160a.h +++ b/src/devices/machine/ds75160a.h @@ -25,6 +25,18 @@ #pragma once + + +///************************************************************************* +// INTERFACE CONFIGURATION MACROS +///************************************************************************* + +#define MCFG_DS75160A_ADD(_tag, _read, _write) \ + MCFG_DEVICE_ADD(_tag, DS75160A, 0) \ + downcast<ds75160a_device *>(device)->set_callbacks(DEVCB_##_read, DEVCB_##_write); + + + ///************************************************************************* // TYPE DEFINITIONS ///************************************************************************* diff --git a/src/devices/machine/f3853.cpp b/src/devices/machine/f3853.cpp index 45511f334ab..f4713f3fa3a 100644 --- a/src/devices/machine/f3853.cpp +++ b/src/devices/machine/f3853.cpp @@ -1,29 +1,19 @@ // license:BSD-3-Clause -// copyright-holders:Wilbert Pol, hap +// copyright-holders:Wilbert Pol /********************************************************************** -Fairchild F3853 SMI, F3851 PSU, F3856 PSU, F38T56 PSU + Fairchild F3853 SRAM interface with integrated interrupt + controller and timer (SMI) -This device only emulates the I/O, interrupt, timer functions. Not the -low-level ROMC signals. + This chip is a timer shift register, basically the same as in the + F3851. -F3853: Static memory interface with integrated interrupt controller and timer. + Based on a datasheet obtained from www.freetradezone.com -The timer is an 8-bit linear feedback shift register: -Feedback in0 = !((out3 ^ out4) ^ (out5 ^ out7)) -Interrupts are at 0xfe -0xff stops the register (0xfe is never reached) - -F3851: Program Storage Unit, same timer and interrupt controller as F3853, -but has 2 I/O ports instead of a programmable interrupt vector. - -F3856/F38T56 Program Storage Unit: similar interrupt controller, timer -is more versatile, a simple downcounter instead of shift register. - -TODO: -- emulate at lower level and place this stuff into devices/cpu/f8 folder -- interrupt priority pin -- 3856/38T56 timer pulse counter mode, event counter mode + 8-bit shift register: + Feedback in0 = !((out3 ^ out4) ^ (out5 ^ out7)) + Interrupts are at 0xfe + 0xff stops the register (0xfe is never reached) **********************************************************************/ @@ -31,60 +21,31 @@ TODO: #include "f3853.h" -// device type definition - -DEFINE_DEVICE_TYPE(F3853, f3853_device, "f3853_smi", "Fairchild F3853 SMI") -DEFINE_DEVICE_TYPE(F3851, f3851_device, "f3851_psu", "Fairchild F3851 PSU") -DEFINE_DEVICE_TYPE(F3856, f3856_device, "f3856_psu", "Fairchild F3856 PSU") -DEFINE_DEVICE_TYPE(F38T56, f38t56_device, "f38t56_psu", "Fairchild F38T56 PSU") - - -//------------------------------------------------- -// constructor -//------------------------------------------------- - -f3853_device::f3853_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : - device_t(mconfig, type, tag, owner, clock), - m_int_req_callback(*this), - m_pri_out_callback(*this), - m_int_vector(0), - m_prescaler(31), - m_priority_line(false), - m_external_interrupt_line(true) -{ } - -f3853_device::f3853_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - f3853_device(mconfig, F3853, tag, owner, clock) -{ } - -f3851_device::f3851_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : - f3853_device(mconfig, type, tag, owner, clock), - m_read_port{{*this}, {*this}}, - m_write_port{{*this}, {*this}} -{ } - -f3851_device::f3851_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - f3851_device(mconfig, F3851, tag, owner, clock) -{ } - -f3856_device::f3856_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : - f3851_device(mconfig, type, tag, owner, clock) -{ } - -f3856_device::f3856_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - f3856_device(mconfig, F3856, tag, owner, clock) -{ } -f38t56_device::f38t56_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - f3856_device(mconfig, F38T56, tag, owner, clock) -{ } +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ +//************************************************************************** +// LIVE DEVICE +//************************************************************************** +// device type definition +DEFINE_DEVICE_TYPE(F3853, f3853_device, "f3853_device", "F3853 SMI") //------------------------------------------------- -// initialisation +// f3853_device - constructor //------------------------------------------------- +f3853_device::f3853_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, F3853, tag, owner, clock) + , m_int_req_callback(*this) + , m_pri_out_callback(*this) + , m_priority_line(false) + , m_external_interrupt_line(true) +{ +} + void f3853_device::device_resolve_objects() { m_int_req_callback.resolve_safe(); @@ -92,20 +53,12 @@ void f3853_device::device_resolve_objects() m_int_daisy_chain_callback.bind_relative_to(*owner()); } -void f3851_device::device_resolve_objects() -{ - f3853_device::device_resolve_objects(); - - // 2 I/O ports - for (devcb_read8 &cb : m_read_port) - cb.resolve_safe(0); - for (devcb_write8 &cb : m_write_port) - cb.resolve_safe(); -} +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- void f3853_device::device_start() { - // lookup table for 3851/3853 lfsr timer uint8_t reg = 0xfe; // Known to get 0xfe after 255 cycles for(int i = reg; i >= 0; i--) { @@ -115,62 +68,47 @@ void f3853_device::device_start() m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(f3853_device::timer_callback),this)); - // zerofill (what's not in constructor) - m_external_int_enable = false; - m_timer_int_enable = false; - m_request_flipflop = false; - - // register for savestates save_item(NAME(m_int_vector)); - save_item(NAME(m_prescaler)); - save_item(NAME(m_external_int_enable)); - save_item(NAME(m_timer_int_enable)); + save_item(NAME(m_external_enable)); + save_item(NAME(m_timer_enable)); save_item(NAME(m_request_flipflop)); save_item(NAME(m_priority_line)); save_item(NAME(m_external_interrupt_line)); } -void f3856_device::device_start() -{ - f3853_device::device_start(); - m_timer_count = 0; - m_timer_modulo = 0; - m_timer_start = false; - - save_item(NAME(m_timer_count)); - save_item(NAME(m_timer_modulo)); - save_item(NAME(m_timer_start)); -} +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- void f3853_device::device_reset() { - // note that standalone peripherals don't have a reset pin, but 3870 does + m_int_vector = 0; + m_external_enable = false; + m_timer_enable = false; + m_request_flipflop = false; + m_external_interrupt_line = true; + set_interrupt_request_line(); - // clear ports at power-on - for (int i = 0; i < 4; i++) - write(machine().dummy_space(), i, 0); + m_timer->enable(false); } -//------------------------------------------------- -// implementation -//------------------------------------------------- - void f3853_device::set_interrupt_request_line() { m_int_req_callback(m_request_flipflop && !m_priority_line ? ASSERT_LINE : CLEAR_LINE); } + IRQ_CALLBACK_MEMBER(f3853_device::int_acknowledge) { - if (m_external_int_enable && !m_priority_line && m_request_flipflop) + if (m_external_enable && !m_priority_line && m_request_flipflop) { m_request_flipflop = false; set_interrupt_request_line(); return external_interrupt_vector(); } - else if (m_timer_int_enable && !m_priority_line && m_request_flipflop) + else if (m_timer_enable && !m_priority_line && m_request_flipflop) { m_request_flipflop = false; set_interrupt_request_line(); @@ -189,14 +127,14 @@ IRQ_CALLBACK_MEMBER(f3853_device::int_acknowledge) void f3853_device::timer_start(uint8_t value) { - attotime period = (value != 0xff) ? attotime::from_hz(clock()) * (m_value_to_cycle[value] * m_prescaler) : attotime::never; + attotime period = (value != 0xff) ? attotime::from_hz(clock()) * (m_value_to_cycle[value]*31) : attotime::never; m_timer->adjust(period); } TIMER_CALLBACK_MEMBER(f3853_device::timer_callback) { - if(m_timer_int_enable) + if(m_timer_enable) { m_request_flipflop = true; set_interrupt_request_line(); @@ -204,10 +142,9 @@ TIMER_CALLBACK_MEMBER(f3853_device::timer_callback) timer_start(0xfe); } - WRITE_LINE_MEMBER(f3853_device::ext_int_w) { - if(m_external_interrupt_line && !state && m_external_int_enable) + if(m_external_interrupt_line && !state && m_external_enable) { m_request_flipflop = true; } @@ -224,201 +161,49 @@ WRITE_LINE_MEMBER(f3853_device::pri_in_w) READ8_MEMBER(f3853_device::read) { - switch (offset & 3) + uint8_t data = 0; + + switch (offset) { - // interrupt vector case 0: - return m_int_vector >> 8; + data = m_int_vector >> 8; + break; + case 1: - return m_int_vector & 0xff; + data = m_int_vector & 0xff; + break; - // interrupt control, timer: write-only - default: - return 0; + case 2: // Interrupt control; not readable + case 3: // Timer; not readable + break; } + + return data; } + WRITE8_MEMBER(f3853_device::write) { - switch (offset & 3) + switch(offset) { - // interrupt vector case 0: m_int_vector = (data << 8) | (m_int_vector & 0x00ff); break; + case 1: m_int_vector = data | (m_int_vector & 0xff00); break; - // interrupt control - case 2: - m_external_int_enable = (data & 3) == 1; - m_timer_int_enable = (data & 3) == 3; + case 2: //interrupt control + m_external_enable = ((data & 3) == 1); + m_timer_enable = ((data & 3) == 3); set_interrupt_request_line(); break; - // set timer - case 3: + case 3: //timer m_request_flipflop = false; set_interrupt_request_line(); timer_start(data); break; } } - - -//------------------------------------------------- -// f3851_device-specific handlers -//------------------------------------------------- - -READ8_MEMBER(f3851_device::read) -{ - switch (offset & 3) - { - // I/O ports - case 0: case 1: - return (m_read_port[offset & 1])(offs_t(offset & 1)); - - // interrupt control, timer: write-only - default: - return 0; - } -} - -WRITE8_MEMBER(f3851_device::write) -{ - switch (offset & 3) - { - // I/O ports - case 0: case 1: - (m_write_port[offset & 1])(offs_t(offset & 1), data); - break; - - // interrupt control, timer: same as 3853 - case 2: case 3: - f3853_device::write(space, offset, data); - break; - } -} - - -//------------------------------------------------- -// f3856_device-specific handlers -//------------------------------------------------- - -void f3856_device::timer_start(uint8_t value) -{ - m_timer_count = value; - attotime period = (m_timer_start) ? (attotime::from_hz(clock()) * m_prescaler) : attotime::never; - - m_timer->adjust(period); -} - -TIMER_CALLBACK_MEMBER(f3856_device::timer_callback) -{ - if (--m_timer_count == 0) - { - m_timer_count = m_timer_modulo; - if (m_timer_int_enable) - { - m_request_flipflop = true; - set_interrupt_request_line(); - } - } - - timer_start(m_timer_count); -} - -READ8_MEMBER(f3856_device::read) -{ - switch (offset & 3) - { - // timer: active counter - case 3: - return m_timer_count; - - // other: same as 3851 - default: - return f3851_device::read(space, offset); - } -} - -WRITE8_MEMBER(f3856_device::write) -{ - switch (offset & 3) - { - // I/O ports: same as 3851 - case 0: case 1: - f3851_device::write(space, offset, data); - break; - - // interrupt/timer control - case 2: - { - // timer prescaler - static const u8 prescaler[8] = { 32, 128, 8, 2 }; - m_prescaler = prescaler[data >> 5 & 7]; - - // start/stop timer - bool prev = m_timer_start; - m_timer_start = bool(~data & 0x10); - if (m_timer_start != prev) - timer_start(m_timer_count); - - // enable interrupts - m_external_int_enable = (data & 3) == 1 || (data & 3) == 2; - m_timer_int_enable = bool(data & 2); - set_interrupt_request_line(); - break; - } - - // set timer - case 3: - f3853_device::write(space, offset, data); - break; - } -} - - -//------------------------------------------------- -// f38t56_device-specific handlers -//------------------------------------------------- - -WRITE8_MEMBER(f38t56_device::write) -{ - switch (offset & 3) - { - // I/O ports: same as 3851 - case 0: case 1: - f3851_device::write(space, offset, data); - break; - - // interrupt/timer control - case 2: - { - // timer prescaler - m_prescaler = 200; - if (~data & 0x80) m_prescaler /= 20; - if (~data & 0x40) m_prescaler /= 5; - if (~data & 0x20) m_prescaler /= 2; - - // start/stop timer - bool prev = m_timer_start; - m_timer_start = bool(data & 8); - if (m_timer_start != prev) - timer_start(m_timer_count); - - // enable interrupts - m_external_int_enable = bool(data & 1); - m_timer_int_enable = bool(data & 2); - set_interrupt_request_line(); - break; - } - - // set timer - case 3: - m_timer_modulo = data; - f3853_device::write(space, offset, data); - break; - } -} diff --git a/src/devices/machine/f3853.h b/src/devices/machine/f3853.h index 762f46950fb..14c922871b1 100644 --- a/src/devices/machine/f3853.h +++ b/src/devices/machine/f3853.h @@ -1,67 +1,49 @@ // license:BSD-3-Clause -// copyright-holders:Wilbert Pol, hap -/* - - Fairchild F3853 SMI, F3851 PSU, F3856 PSU, F38T56 PSU - -*/ +// copyright-holders:Wilbert Pol +/*************************************************************************** + + Fairchild F3853 SRAM interface with integrated interrupt + controller and timer + + This chip is a timer shift register, basically the same as in the + F3851. + +**************************************************************************** + _____ _____ + Vgg 1 |* \_/ | 40 Vdd + PHI 2 | | 39 ROMC4 + WRITE 3 | | 38 ROMC3 + _INT REQ 4 | | 37 ROMC2 + _PRI IN 5 | | 36 ROMC1 + _RAM WRITE 6 | | 35 ROMC0 + _EXT INT 7 | | 34 CPU READ + ADDR7 8 | | 33 REG DR + ADDR6 9 | | 32 ADDR15 + ADDR5 10 | F3853 | 31 ADDR14 + ADDR4 11 | | 30 ADDR13 + ADDR3 12 | | 29 ADDR12 + ADDR2 13 | | 28 ADDR11 + ADDR1 14 | | 27 ADDR10 + ADDR0 15 | | 26 ADDR9 + DB0 16 | | 25 ADDR8 + DB1 17 | | 24 DB7 + DB2 18 | | 23 DB6 + DB3 19 | | 22 DB5 + Vss 20 |_____________| 21 DB4 + +***************************************************************************/ #ifndef MAME_MACHINE_F3853_H #define MAME_MACHINE_F3853_H #pragma once -// pinout reference - -/* - _____ _____ - Vgg 1 |* \_/ | 40 Vdd - PHI 2 | | 39 ROMC4 - WRITE 3 | | 38 ROMC3 - _INT REQ 4 | | 37 ROMC2 - _PRI IN 5 | | 36 ROMC1 - _RAM WRITE 6 | | 35 ROMC0 - _EXT INT 7 | | 34 CPU READ - ADDR7 8 | | 33 REG DR - ADDR6 9 | | 32 ADDR15 - ADDR5 10 | F3853 | 31 ADDR14 - ADDR4 11 | | 30 ADDR13 - ADDR3 12 | | 29 ADDR12 - ADDR2 13 | | 28 ADDR11 - ADDR1 14 | | 27 ADDR10 - ADDR0 15 | | 26 ADDR9 - DB0 16 | | 25 ADDR8 - DB1 17 | | 24 DB7 - DB2 18 | | 23 DB6 - DB3 19 | | 22 DB5 - Vss 20 |_____________| 21 DB4 - - _____ _____ - _I/O B7 1 |* \_/ | 40 DB7 - _I/O A7 2 | | 39 DB6 - Vgg 3 | | 38 _I/O B6 - Vdd 4 | | 37 _I/O A6 - _EXT INT 5 | | 36 _I/O A5 - _PRI OUT 6 | | 35 _I/O B5 - WRITE 7 | | 34 DB5 - PHI 8 | | 33 DB4 - _INT REQ 9 | F3851 | 32 _I/O B4 - _PRI IN 10 | F3856 | 31 _I/O A4 - _DBDR 11 | F38T56 | 30 _I/O A3 - STROBE 12 | | 29 _I/O B3 - ROMC4 13 | | 28 DB3 - ROMC3 14 | | 27 DB2 - ROMC2 15 | | 26 _I/O B2 - ROMC1 16 | | 25 _I/O A2 - ROMC0 17 | | 24 _I/O A1 - Vss 18 | | 23 _I/O B1 - _I/O A0 19 | | 22 DB1 - _I/O B0 20 |_____________| 21 DB0 - - F38T56 is internal in F3870 - note: STROBE is N/C on F3851 -*/ +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +// ======================> f3853_device class f3853_device : public device_t { @@ -73,38 +55,36 @@ public: auto pri_out_callback() { return m_pri_out_callback.bind(); } template<typename Object> void set_int_daisy_chain_callback(Object &&cb) { m_int_daisy_chain_callback = std::forward<Object>(cb); } - virtual DECLARE_READ8_MEMBER(read); - virtual DECLARE_WRITE8_MEMBER(write); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); DECLARE_WRITE_LINE_MEMBER(ext_int_w); DECLARE_WRITE_LINE_MEMBER(pri_in_w); - virtual TIMER_CALLBACK_MEMBER(timer_callback); + TIMER_CALLBACK_MEMBER(timer_callback); IRQ_CALLBACK_MEMBER(int_acknowledge); protected: - f3853_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - // device-level overrides virtual void device_resolve_objects() override; virtual void device_start() override; virtual void device_reset() override; +private: uint16_t timer_interrupt_vector() const { return m_int_vector & ~uint16_t(0x0080); } uint16_t external_interrupt_vector() const { return m_int_vector | uint16_t(0x0080); } void set_interrupt_request_line(); - virtual void timer_start(uint8_t value); + void timer_start(uint8_t value); devcb_write_line m_int_req_callback; devcb_write_line m_pri_out_callback; device_irq_acknowledge_delegate m_int_daisy_chain_callback; uint16_t m_int_vector; // Bit 7 is set to 0 for timer interrupts, 1 for external interrupts - u8 m_prescaler; - bool m_external_int_enable; - bool m_timer_int_enable; + bool m_external_enable; + bool m_timer_enable; bool m_request_flipflop; @@ -116,66 +96,8 @@ protected: uint8_t m_value_to_cycle[0x100]; }; -class f3851_device : public f3853_device -{ -public: - f3851_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // interrupt vector is a mask option on 3851 and 3856 - void set_int_vector(u16 vector) { m_int_vector = vector; } - - // bidirectional I/O ports A and B - auto read_a() { return m_read_port[0].bind(); } - auto read_b() { return m_read_port[1].bind(); } - auto write_a() { return m_write_port[0].bind(); } - auto write_b() { return m_write_port[1].bind(); } - - virtual DECLARE_READ8_MEMBER(read) override; - virtual DECLARE_WRITE8_MEMBER(write) override; - -protected: - f3851_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_resolve_objects() override; - - devcb_read8 m_read_port[2]; - devcb_write8 m_write_port[2]; -}; - -class f3856_device : public f3851_device -{ -public: - f3856_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual DECLARE_READ8_MEMBER(read) override; - virtual DECLARE_WRITE8_MEMBER(write) override; - - virtual TIMER_CALLBACK_MEMBER(timer_callback) override; - -protected: - f3856_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - - virtual void timer_start(uint8_t value) override; - - u8 m_timer_count; - u8 m_timer_modulo; - bool m_timer_start; -}; - -class f38t56_device : public f3856_device -{ -public: - f38t56_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual DECLARE_WRITE8_MEMBER(write) override; -}; // device type definition DECLARE_DEVICE_TYPE(F3853, f3853_device) -DECLARE_DEVICE_TYPE(F3851, f3851_device) -DECLARE_DEVICE_TYPE(F3856, f3856_device) -DECLARE_DEVICE_TYPE(F38T56, f38t56_device) #endif // MAME_MACHINE_F3853_H diff --git a/src/devices/machine/fdc37c665gt.cpp b/src/devices/machine/fdc37c665gt.cpp index f2df880d2e8..4c6f23651db 100644 --- a/src/devices/machine/fdc37c665gt.cpp +++ b/src/devices/machine/fdc37c665gt.cpp @@ -49,10 +49,9 @@ void fdc37c665gt_device::device_start() { } -void fdc37c665gt_device::device_add_mconfig(machine_config &config) -{ - NS16550(config, m_uart1, XTAL(24'000'000)/13); - NS16550(config, m_uart2, XTAL(24'000'000)/13); -} +MACHINE_CONFIG_START(fdc37c665gt_device::device_add_mconfig) + MCFG_DEVICE_ADD("uart1", NS16550, XTAL(24'000'000)/13) + MCFG_DEVICE_ADD("uart2", NS16550, XTAL(24'000'000)/13) +MACHINE_CONFIG_END DEFINE_DEVICE_TYPE(FDC37C665GT, fdc37c665gt_device, "fdc37c665gt", "FDC37C665GT") diff --git a/src/devices/machine/fdc37c93x.cpp b/src/devices/machine/fdc37c93x.cpp index 8ff5afc76d4..05c87fd38ef 100644 --- a/src/devices/machine/fdc37c93x.cpp +++ b/src/devices/machine/fdc37c93x.cpp @@ -639,12 +639,12 @@ void fdc37c93x_device::map_rtc(address_map &map) READ8_MEMBER(fdc37c93x_device::rtc_read) { - return ds12885_rtcdev->read(offset); + return ds12885_rtcdev->read(space, offset, mem_mask); } WRITE8_MEMBER(fdc37c93x_device::rtc_write) { - ds12885_rtcdev->write(offset, data); + ds12885_rtcdev->write(space, offset, data, mem_mask); } void fdc37c93x_device::map_rtc_addresses() diff --git a/src/devices/machine/gen_fifo.h b/src/devices/machine/gen_fifo.h index 0ef98fb20c3..4db8a75d8c1 100644 --- a/src/devices/machine/gen_fifo.h +++ b/src/devices/machine/gen_fifo.h @@ -72,6 +72,13 @@ */ +#define MCFG_GENERIC_FIFO_EMPTY_CALLBACK(_devcb) \ + downcast<screen_device &>(*device).set_empty_cb(DEVCB_##_devcb); + +#define MCFG_GENERIC_FIFO_FULL_CALLBACK(_devcb) \ + downcast<screen_device &>(*device).set_full_cb(DEVCB_##_devcb); + + template<typename T> class generic_fifo_device_base : public device_t { public: /* The general setup. Call be called multiple times, clears the fifo. */ @@ -111,8 +118,8 @@ public: void clear(); /* Callbacks signalling empty (true)/nonempty (false) and full (true)/nonfull (false) */ - auto empty_cb() { return m_empty_cb.bind(); } - auto full_cb() { return m_full_cb.bind(); } + template<class Object> devcb_base &set_empty_cb(Object &&object) { return m_empty_cb.set_callback(std::forward<Object>(object)); } + template<class Object> devcb_base &set_full_cb(Object &&object) { return m_full_cb.set_callback(std::forward<Object>(object)); } /* Get the fifo current size - Note that real hardware usually can't do that. May be bigger that the fifo size if some extra diff --git a/src/devices/machine/genpc.cpp b/src/devices/machine/genpc.cpp index e626bf96b30..269c1915bb0 100644 --- a/src/devices/machine/genpc.cpp +++ b/src/devices/machine/genpc.cpp @@ -135,8 +135,6 @@ WRITE_LINE_MEMBER( ibm5160_mb_device::pc_dma8237_out_eop ) void ibm5160_mb_device::pc_select_dma_channel(int channel, bool state) { - m_isabus->dack_line_w(channel, state); - if(!state) { m_dma_channel = channel; if(m_cur_eop) @@ -395,16 +393,8 @@ WRITE8_MEMBER( ibm5160_mb_device::pc_ppi_portb_w ) WRITE8_MEMBER( ibm5160_mb_device::nmi_enable_w ) { m_nmi_enabled = BIT(data,7); - if (!m_nmi_enabled) - m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); -} - -WRITE_LINE_MEMBER( ibm5160_mb_device::iochck_w ) -{ - if (m_nmi_enabled && !state) - m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); + m_isabus->set_nmi_state(m_nmi_enabled); } - //************************************************************************** // GLOBAL VARIABLES //************************************************************************** @@ -420,9 +410,8 @@ DEFINE_DEVICE_TYPE(IBM5160_MOTHERBOARD, ibm5160_mb_device, "ibm5160_mb", "IBM 51 // device_add_mconfig - add device configuration //------------------------------------------------- -void ibm5160_mb_device::device_add_mconfig(machine_config &config) -{ - PIT8253(config, m_pit8253); +MACHINE_CONFIG_START(ibm5160_mb_device::device_add_mconfig) + PIT8253(config, m_pit8253, 0); m_pit8253->set_clk<0>(XTAL(14'318'181)/12.0); // heartbeat IRQ m_pit8253->out_handler<0>().set(m_pic8259, FUNC(pic8259_device::ir0_w)); m_pit8253->set_clk<1>(XTAL(14'318'181)/12.0); // DRAM refresh @@ -447,7 +436,7 @@ void ibm5160_mb_device::device_add_mconfig(machine_config &config) m_dma8237->out_dack_callback<2>().set(FUNC(ibm5160_mb_device::pc_dack2_w)); m_dma8237->out_dack_callback<3>().set(FUNC(ibm5160_mb_device::pc_dack3_w)); - PIC8259(config, m_pic8259); + PIC8259(config, m_pic8259, 0); m_pic8259->out_int_callback().set(FUNC(ibm5160_mb_device::pic_int_w)); I8255A(config, m_ppi8255, 0); @@ -456,8 +445,7 @@ void ibm5160_mb_device::device_add_mconfig(machine_config &config) m_ppi8255->in_pc_callback().set(FUNC(ibm5160_mb_device::pc_ppi_portc_r)); ISA8(config, m_isabus, 0); - m_isabus->set_memspace(":maincpu", AS_PROGRAM); - m_isabus->set_iospace(":maincpu", AS_IO); + m_isabus->set_cputag(":maincpu"); m_isabus->irq2_callback().set(m_pic8259, FUNC(pic8259_device::ir2_w)); m_isabus->irq3_callback().set(m_pic8259, FUNC(pic8259_device::ir3_w)); m_isabus->irq4_callback().set(m_pic8259, FUNC(pic8259_device::ir4_w)); @@ -467,16 +455,15 @@ void ibm5160_mb_device::device_add_mconfig(machine_config &config) m_isabus->drq1_callback().set(m_dma8237, FUNC(am9517a_device::dreq1_w)); m_isabus->drq2_callback().set(m_dma8237, FUNC(am9517a_device::dreq2_w)); m_isabus->drq3_callback().set(m_dma8237, FUNC(am9517a_device::dreq3_w)); - m_isabus->iochck_callback().set(FUNC(ibm5160_mb_device::iochck_w)); - PC_KBDC(config, m_pc_kbdc, 0); - m_pc_kbdc->out_clock_cb().set(FUNC(ibm5160_mb_device::keyboard_clock_w)); - m_pc_kbdc->out_data_cb().set(FUNC(ibm5160_mb_device::keyboard_data_w)); + MCFG_DEVICE_ADD("pc_kbdc", PC_KBDC, 0) + MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE(*this, ibm5160_mb_device, keyboard_clock_w)) + MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE(*this, ibm5160_mb_device, keyboard_data_w)) /* sound hardware */ SPEAKER(config, "mono").front_center(); SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 1.00); -} +MACHINE_CONFIG_END static INPUT_PORTS_START( ibm5160_mb ) @@ -608,18 +595,18 @@ DEFINE_DEVICE_TYPE(IBM5150_MOTHERBOARD, ibm5150_mb_device, "ibm5150_mb", "IBM 51 // device_add_mconfig - add device configuration //------------------------------------------------- -void ibm5150_mb_device::device_add_mconfig(machine_config &config) -{ +MACHINE_CONFIG_START(ibm5150_mb_device::device_add_mconfig) ibm5160_mb_device::device_add_mconfig(config); - subdevice<pc_kbdc_device>("pc_kbdc")->out_clock_cb().set(FUNC(ibm5150_mb_device::keyboard_clock_w)); + MCFG_DEVICE_MODIFY("pc_kbdc") + MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE(*this, ibm5150_mb_device, keyboard_clock_w)) m_ppi8255->out_pb_callback().set(FUNC(ibm5150_mb_device::pc_ppi_portb_w)); m_ppi8255->in_pc_callback().set(FUNC(ibm5150_mb_device::pc_ppi_portc_r)); - CASSETTE(config, m_cassette); - m_cassette->set_default_state(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_ENABLED); -} + MCFG_CASSETTE_ADD( "cassette" ) + MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_ENABLED) +MACHINE_CONFIG_END //************************************************************************** // LIVE DEVICE @@ -785,15 +772,15 @@ DEFINE_DEVICE_TYPE(EC1841_MOTHERBOARD, ec1841_mb_device, "ec1841_mb", "EC-1840 m // device_add_mconfig - add device configuration //------------------------------------------------- -void ec1841_mb_device::device_add_mconfig(machine_config &config) -{ +MACHINE_CONFIG_START(ec1841_mb_device::device_add_mconfig) ibm5160_mb_device::device_add_mconfig(config); m_ppi8255->out_pb_callback().set(FUNC(ec1841_mb_device::pc_ppi_portb_w)); m_ppi8255->in_pc_callback().set(FUNC(ec1841_mb_device::pc_ppi_portc_r)); - subdevice<pc_kbdc_device>("pc_kbdc")->out_clock_cb().set(FUNC(ec1841_mb_device::keyboard_clock_w)); -} + MCFG_DEVICE_MODIFY("pc_kbdc") + MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE(*this, ec1841_mb_device, keyboard_clock_w)) +MACHINE_CONFIG_END static INPUT_PORTS_START( ec1841_mb ) PORT_START("DSW0") /* SA1 */ @@ -911,13 +898,12 @@ pc_noppi_mb_device::pc_noppi_mb_device(const machine_config &mconfig, device_typ // device_add_mconfig - add device configuration //------------------------------------------------- -void pc_noppi_mb_device::device_add_mconfig(machine_config &config) -{ +MACHINE_CONFIG_START(pc_noppi_mb_device::device_add_mconfig) ibm5160_mb_device::device_add_mconfig(config); - config.device_remove("pc_kbdc"); - config.device_remove("ppi8255"); -} + MCFG_DEVICE_REMOVE("pc_kbdc") + MCFG_DEVICE_REMOVE("ppi8255") +MACHINE_CONFIG_END static INPUT_PORTS_START( pc_noppi_mb ) INPUT_PORTS_END diff --git a/src/devices/machine/genpc.h b/src/devices/machine/genpc.h index e222b975873..4c412a9a720 100644 --- a/src/devices/machine/genpc.h +++ b/src/devices/machine/genpc.h @@ -23,6 +23,11 @@ #include "bus/pc_kbd/pc_kbdc.h" +#define MCFG_IBM5160_MOTHERBOARD_ADD(_tag, _cputag) \ + MCFG_DEVICE_ADD(_tag, IBM5160_MOTHERBOARD, 0) \ + downcast<ibm5160_mb_device &>(*device).set_cputag(_cputag); \ + (*device->subdevice<isa8_device>("isa")).set_cputag(_cputag); + // ======================> ibm5160_mb_device class ibm5160_mb_device : public device_t { @@ -31,12 +36,7 @@ public: ibm5160_mb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // inline configuration - template <typename T> void set_cputag(T &&tag) - { - m_maincpu.set_tag(std::forward<T>(tag)); - subdevice<isa8_device>("isa")->set_memspace(std::forward<T>(tag), AS_PROGRAM); - subdevice<isa8_device>("isa")->set_iospace(std::forward<T>(tag), AS_IO); - } + void set_cputag(const char *tag) { m_maincpu.set_tag(tag); } void map(address_map &map); @@ -119,7 +119,6 @@ protected: DECLARE_WRITE_LINE_MEMBER( pc_dack1_w ); DECLARE_WRITE_LINE_MEMBER( pc_dack2_w ); DECLARE_WRITE_LINE_MEMBER( pc_dack3_w ); - DECLARE_WRITE_LINE_MEMBER( iochck_w ); void pc_select_dma_channel(int channel, bool state); }; @@ -129,6 +128,11 @@ protected: DECLARE_DEVICE_TYPE(IBM5160_MOTHERBOARD, ibm5160_mb_device) +#define MCFG_IBM5150_MOTHERBOARD_ADD(_tag, _cputag) \ + MCFG_DEVICE_ADD(_tag, IBM5150_MOTHERBOARD, 0) \ + downcast<ibm5150_mb_device &>(*device).set_cputag(_cputag); \ + (*device->subdevice<isa8_device>("isa")).set_cputag(_cputag); + // ======================> ibm5150_mb_device class ibm5150_mb_device : public ibm5160_mb_device { @@ -158,6 +162,12 @@ private: // device type definition DECLARE_DEVICE_TYPE(IBM5150_MOTHERBOARD, ibm5150_mb_device) + +#define MCFG_EC1841_MOTHERBOARD_ADD(_tag, _cputag) \ + MCFG_DEVICE_ADD(_tag, EC1841_MOTHERBOARD, 0) \ + downcast<ec1841_mb_device &>(*device).set_cputag(_cputag); \ + (*device->subdevice<isa8_device>("isa")).set_cputag(_cputag); + class ec1841_mb_device : public ibm5160_mb_device { public: @@ -179,13 +189,16 @@ private: DECLARE_DEVICE_TYPE(EC1841_MOTHERBOARD, ec1841_mb_device) +#define MCFG_PCNOPPI_MOTHERBOARD_ADD(_tag, _cputag) \ + MCFG_DEVICE_ADD(_tag, PCNOPPI_MOTHERBOARD, 0) \ + downcast<pc_noppi_mb_device &>(*device).set_cputag(_cputag); \ + (*device->subdevice<isa8_device>("isa")).set_cputag(_cputag); class pc_noppi_mb_device : public ibm5160_mb_device { public: // construction/destruction pc_noppi_mb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - uint8_t pit_out2() { return m_pit_out2; } // helper for near-clones with multifunction ics instead of 8255s void map(address_map &map); diff --git a/src/devices/machine/hdc92x4.cpp b/src/devices/machine/hdc92x4.cpp index 4354711738f..e7c42d31452 100644 --- a/src/devices/machine/hdc92x4.cpp +++ b/src/devices/machine/hdc92x4.cpp @@ -4265,7 +4265,7 @@ uint16_t hdc92x4_device::encode_a1_hd() Read a byte of data from the controller The address (offset) encodes the C/D* line (command and /data) */ -uint8_t hdc92x4_device::read(offs_t offset) +READ8_MEMBER( hdc92x4_device::read ) { uint8_t reply; if ((offset & 1) == 0) @@ -4300,7 +4300,7 @@ uint8_t hdc92x4_device::read(offs_t offset) The operation terminates immediately, and the controller picks up the values stored in this phase at a later time. */ -void hdc92x4_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( hdc92x4_device::write ) { if ((offset & 1) == 0) { diff --git a/src/devices/machine/hdc92x4.h b/src/devices/machine/hdc92x4.h index c4850ffa103..e0c25d1a524 100644 --- a/src/devices/machine/hdc92x4.h +++ b/src/devices/machine/hdc92x4.h @@ -45,8 +45,8 @@ public: }; // Accessors from the CPU side - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); DECLARE_WRITE_LINE_MEMBER( reset ); DECLARE_WRITE_LINE_MEMBER( dmaack ); diff --git a/src/devices/machine/i2cmem.cpp b/src/devices/machine/i2cmem.cpp index 34e75569a49..94670ff5326 100644 --- a/src/devices/machine/i2cmem.cpp +++ b/src/devices/machine/i2cmem.cpp @@ -58,14 +58,8 @@ static inline void ATTR_PRINTF( 3, 4 ) verboselog( device_t *device, int n_level //************************************************************************** // device type definition -DEFINE_DEVICE_TYPE(I2CMEM, i2cmem_device, "i2cmem", "I2C Memory") -DEFINE_DEVICE_TYPE(I2C_X2404P, i2c_x2404p_device, "x2404p", "X2404P I2C Memory") -DEFINE_DEVICE_TYPE(I2C_24C01, i2c_24c01_device, "24c01", "24C01 I2C Memory") -DEFINE_DEVICE_TYPE(I2C_24C02, i2c_24c02_device, "24c02", "24C02 I2C Memory") -DEFINE_DEVICE_TYPE(I2C_24C08, i2c_24c08_device, "24c08", "24C08 I2C Memory") -DEFINE_DEVICE_TYPE(I2C_24C16, i2c_24c16_device, "24c16", "24C16 I2C Memory") -DEFINE_DEVICE_TYPE(I2C_24C16A, i2c_24c16a_device, "24c16a", "24C16A I2C Memory") -DEFINE_DEVICE_TYPE(I2C_24C64, i2c_24c64_device, "24c64", "24C64 I2C Memory") +DEFINE_DEVICE_TYPE(I2CMEM, i2cmem_device, "i2cmem", "I2C Memory") +DEFINE_DEVICE_TYPE(X2404P, x2404p_device, "x2404p", "X2404P I2C Memory") //************************************************************************** // LIVE DEVICE @@ -75,76 +69,36 @@ DEFINE_DEVICE_TYPE(I2C_24C64, i2c_24c64_device, "24c64", "24C64 I2C Memory") // i2cmem_device - constructor //------------------------------------------------- -i2cmem_device::i2cmem_device( - const machine_config &mconfig, - device_type type, - const char *tag, - device_t *owner, - uint32_t clock, - int page_size, - int data_size) : - device_t(mconfig, type, tag, owner, clock), +i2cmem_device::i2cmem_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock), device_nvram_interface(mconfig, *this), m_region(*this, DEVICE_SELF), - m_slave_address(I2CMEM_SLAVE_ADDRESS), - m_page_size(page_size), - m_data_size(data_size), - m_scl(0), - m_sdaw(0), - m_e0(0), - m_e1(0), - m_e2(0), - m_wc(0), - m_sdar(1), - m_state(STATE_IDLE), - m_shift(0), - m_byteaddr(0), - m_page_offset(0), - m_page_written_size(0), - m_in_write(false) + m_slave_address( I2CMEM_SLAVE_ADDRESS ), + m_page_size( 0 ), + m_data_size( 0 ), + m_scl( 0 ), + m_sdaw( 0 ), + m_e0( 0 ), + m_e1( 0 ), + m_e2( 0 ), + m_wc( 0 ), + m_sdar( 1 ), + m_state( STATE_IDLE ), + m_shift( 0 ), + m_byteaddr( 0 ) { - // these memories work off the I2C clock only - assert(!clock); } -i2cmem_device::i2cmem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - i2cmem_device(mconfig, I2CMEM, tag, owner, clock, 0, 0) +i2cmem_device::i2cmem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : i2cmem_device(mconfig, I2CMEM, tag, owner, clock) { } -i2c_x2404p_device::i2c_x2404p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - i2cmem_device(mconfig, I2C_X2404P, tag, owner, clock, 8, 0x200) -{ -} - -i2c_24c01_device::i2c_24c01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - i2cmem_device(mconfig, I2C_24C01, tag, owner, clock, 4, 0x80) -{ -} - -i2c_24c02_device::i2c_24c02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - i2cmem_device(mconfig, I2C_24C02, tag, owner, clock, 4, 0x100) -{ -} - -i2c_24c08_device::i2c_24c08_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - i2cmem_device(mconfig, I2C_24C08, tag, owner, clock, 0, 0x400) -{ -} - -i2c_24c16_device::i2c_24c16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - i2cmem_device(mconfig, I2C_24C16, tag, owner, clock, 8, 0x800) -{ -} - -i2c_24c16a_device::i2c_24c16a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - i2cmem_device(mconfig, I2C_24C16A, tag, owner, clock, 0, 0x800) -{ -} - -i2c_24c64_device::i2c_24c64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - i2cmem_device(mconfig, I2C_24C64, tag, owner, clock, 8, 0x2000) +x2404p_device::x2404p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : i2cmem_device(mconfig, X2404P, tag, owner, clock) { + set_page_size(8); + set_data_size(0x200); } //------------------------------------------------- @@ -168,9 +122,6 @@ void i2cmem_device::device_start() save_item( NAME(m_shift) ); save_item( NAME(m_devsel) ); save_item( NAME(m_byteaddr) ); - save_item( NAME(m_in_write) ); - save_item( NAME(m_page_offset) ); - save_item( NAME(m_page_written_size) ); save_pointer( &m_data[0], "m_data", m_data_size ); if ( m_page_size > 0 ) { @@ -185,7 +136,6 @@ void i2cmem_device::device_start() void i2cmem_device::device_reset() { - m_in_write = false; } @@ -287,15 +237,6 @@ WRITE_LINE_MEMBER( i2cmem_device::write_sda ) { if( m_sdaw ) { - if( m_in_write ) - { - int base = data_offset(); - int root = base & ~( m_page_size - 1); - for( int i=0; i < m_page_written_size; i++) - m_data[root | ((base + i) & (m_page_size - 1))] = m_page[i]; - m_in_write = false; - verboselog( this, 1, "data[ %04x to %04x ] = %x bytes\n", base, root | ((base + m_page_written_size - 1) & (m_page_size - 1)), m_page_written_size ); - } verboselog( this, 1, "stop\n" ); m_state = STATE_IDLE; } @@ -360,7 +301,6 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl ) case STATE_BYTEADDR: m_byteaddr = m_shift; m_page_offset = 0; - m_page_written_size = 0; verboselog( this, 1, "byteaddr %02x\n", m_byteaddr ); @@ -375,16 +315,23 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl ) } else if( m_page_size > 0 ) { - m_in_write = true; m_page[ m_page_offset ] = m_shift; verboselog( this, 1, "page[ %04x ] <- %02x\n", m_page_offset, m_page[ m_page_offset ] ); m_page_offset++; if( m_page_offset == m_page_size ) + { + int offset = data_offset() & ~( m_page_size - 1 ); + + verboselog( this, 1, "data[ %04x to %04x ] = page\n", offset, offset + m_page_size - 1 ); + + for( int i = 0; i < m_page_size; i++ ) + { + m_data[offset + i] = m_page[ i ]; + } + m_page_offset = 0; - m_page_written_size++; - if( m_page_written_size > m_page_size) - m_page_written_size = m_page_size; + } } else { diff --git a/src/devices/machine/i2cmem.h b/src/devices/machine/i2cmem.h index c912709871d..d67fa463c2e 100644 --- a/src/devices/machine/i2cmem.h +++ b/src/devices/machine/i2cmem.h @@ -23,6 +23,61 @@ //************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_I2CMEM_ADD( _tag ) \ + MCFG_DEVICE_ADD( _tag, I2CMEM, 0 ) + +#define MCFG_I2CMEM_ADDRESS( address ) \ + downcast<i2cmem_device &>(*device).set_address(address); +#define MCFG_I2CMEM_PAGE_SIZE( page_size ) \ + downcast<i2cmem_device &>(*device).set_page_size(page_size); +#define MCFG_I2CMEM_DATA_SIZE(data_size) \ + downcast<i2cmem_device &>(*device).set_data_size(data_size); +#define MCFG_I2CMEM_E0(e0) \ + downcast<i2cmem_device &>(*device).set_e0(e0); +#define MCFG_I2CMEM_E1(e1) \ + downcast<i2cmem_device &>(*device).set_e1(e1); +#define MCFG_I2CMEM_E2(e2) \ + downcast<i2cmem_device &>(*device).set_e2(e2); +#define MCFG_I2CMEM_WC(wc) \ + downcast<i2cmem_device &>(*device).set_wc(wc); + +#define MCFG_X2404P_ADD( _tag ) \ + MCFG_I2CMEM_ADD( _tag ) \ + MCFG_I2CMEM_PAGE_SIZE(8) \ + MCFG_I2CMEM_DATA_SIZE(0x200) + +#define MCFG_24C01_ADD( _tag ) \ + MCFG_I2CMEM_ADD( _tag ) \ + MCFG_I2CMEM_PAGE_SIZE(4) \ + MCFG_I2CMEM_DATA_SIZE(0x80) + +#define MCFG_24C02_ADD( _tag ) \ + MCFG_I2CMEM_ADD( _tag ) \ + MCFG_I2CMEM_PAGE_SIZE(4) \ + MCFG_I2CMEM_DATA_SIZE(0x100) + +#define MCFG_24C08_ADD( _tag ) \ + MCFG_I2CMEM_ADD( _tag ) \ + MCFG_I2CMEM_DATA_SIZE(0x400) + +#define MCFG_24C16_ADD( _tag ) \ + MCFG_I2CMEM_ADD( _tag ) \ + MCFG_I2CMEM_PAGE_SIZE(8) \ + MCFG_I2CMEM_DATA_SIZE(0x800) + +#define MCFG_24C16A_ADD( _tag ) \ + MCFG_I2CMEM_ADD( _tag ) \ + MCFG_I2CMEM_DATA_SIZE(0x800) + +#define MCFG_24C64_ADD( _tag ) \ + MCFG_I2CMEM_ADD( _tag ) \ + MCFG_I2CMEM_PAGE_SIZE(8) \ + MCFG_I2CMEM_DATA_SIZE(0x2000) + +//************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -55,7 +110,7 @@ public: protected: // construction/destruction - i2cmem_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int page_size, int data_size); + i2cmem_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0); // device-level overrides virtual void device_start() override; @@ -92,33 +147,17 @@ protected: int m_byteaddr; std::vector<uint8_t> m_page; int m_page_offset; - int m_page_written_size; - bool m_in_write; }; -#define DECLARE_I2C_DEVICE(name) \ - class i2c_##name##_device : public i2cmem_device \ - { \ - public: \ - i2c_##name##_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); \ - }; - -DECLARE_I2C_DEVICE(x2404p) -DECLARE_I2C_DEVICE(24c01) -DECLARE_I2C_DEVICE(24c02) -DECLARE_I2C_DEVICE(24c08) -DECLARE_I2C_DEVICE(24c16); -DECLARE_I2C_DEVICE(24c16a); -DECLARE_I2C_DEVICE(24c64); +class x2404p_device : public i2cmem_device +{ +public: + // construction/destruction + x2404p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); +}; // device type definition -DECLARE_DEVICE_TYPE(I2CMEM, i2cmem_device) -DECLARE_DEVICE_TYPE(I2C_X2404P, i2c_x2404p_device) -DECLARE_DEVICE_TYPE(I2C_24C01, i2c_24c01_device) -DECLARE_DEVICE_TYPE(I2C_24C02, i2c_24c02_device) -DECLARE_DEVICE_TYPE(I2C_24C08, i2c_24c08_device) -DECLARE_DEVICE_TYPE(I2C_24C16, i2c_24c16_device) -DECLARE_DEVICE_TYPE(I2C_24C16A, i2c_24c16a_device) -DECLARE_DEVICE_TYPE(I2C_24C64, i2c_24c64_device) +DECLARE_DEVICE_TYPE(I2CMEM, i2cmem_device) +DECLARE_DEVICE_TYPE(X2404P, x2404p_device) #endif // MAME_MACHINE_I2CMEM_H diff --git a/src/devices/machine/i7220.cpp b/src/devices/machine/i7220.cpp index 0e86dc081bb..8543d9f61f2 100644 --- a/src/devices/machine/i7220.cpp +++ b/src/devices/machine/i7220.cpp @@ -29,16 +29,17 @@ #include "i7220.h" -//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already -#define LOG_REGISTER (1U << 1) -#define LOG_DEBUG (1U << 2) +#define VERBOSE_DBG 2 /* general debug messages */ -//#define VERBOSE (LOG_DEBUG) -//#define LOG_OUTPUT_FUNC printf -#include "logmacro.h" - -#define LOGREG(...) LOGMASKED(LOG_REGISTER, __VA_ARGS__) -#define LOGDBG(...) LOGMASKED(LOG_DEBUG, __VA_ARGS__) +#define DBG_LOG(N,M,A) \ + do { \ + if(VERBOSE_DBG>=N) \ + { \ + if( M ) \ + logerror("%11.6f at %s: %-10s",machine().time().as_double(),machine().describe_context(),(char*)M ); \ + logerror A; \ + } \ + } while (0) // device type definition @@ -223,8 +224,8 @@ void i7220_device::start_command(int cmd) // NFC bits in BLR MSB must be set to 0001 before issuing this command. // MBM GROUP SELECT bits in the AR must select the last MBM in the system. case C_INIT: - LOG("BMC INIT: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n", - m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER]); + DBG_LOG(1, "BMC", ("INIT: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n", + m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER])); if (blr_nfc != 2) { command_fail_start(bi); @@ -241,8 +242,8 @@ void i7220_device::start_command(int cmd) // all parametric registers must be properly set up before issuing Read Bubble Data command case C_READ: - LOG("BMC RBD: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n", - m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER]); + DBG_LOG(1, "BMC", ("RBD: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n", + m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER])); if (ar_mbm >= m_data_size || blr_nfc != 2) { command_fail_start(bi); @@ -254,8 +255,8 @@ void i7220_device::start_command(int cmd) break; case C_WRITE: - LOG("BMC WBD: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n", - m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER]); + DBG_LOG(1, "BMC", ("WBD: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n", + m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER])); if (ar_mbm >= m_data_size || blr_nfc != 2) { command_fail_start(bi); @@ -338,7 +339,7 @@ void i7220_device::general_continue(bubble_info &bi) break; default: - LOG("BMC general_continue on unknown main-state %d\n", bi.main_state); + DBG_LOG(1,"BMC",("general_continue on unknown main-state %d\n", bi.main_state)); break; } } @@ -388,7 +389,7 @@ void i7220_device::command_fail_continue(bubble_info &bi) return; default: - LOG("BMC fail unknown sub-state %d\n", bi.sub_state); + DBG_LOG(1,"BMC",("fail unknown sub-state %d\n", bi.sub_state)); return; } } @@ -422,7 +423,7 @@ void i7220_device::init_continue(bubble_info &bi) return; default: - LOG("BMC init unknown sub-state %d\n", bi.sub_state); + DBG_LOG(1,"BMC",("init unknown sub-state %d\n", bi.sub_state)); return; } } @@ -462,7 +463,7 @@ void i7220_device::read_fsa_continue(bubble_info &bi) return; default: - LOG("BMC read fsa unknown sub-state %d\n", bi.sub_state); + DBG_LOG(1,"BMC",("read fsa unknown sub-state %d\n", bi.sub_state)); return; } } @@ -496,7 +497,7 @@ void i7220_device::read_data_continue(bubble_info &bi) break; case WAIT_FSA_REPLY: - LOGDBG("BMC read data: ct %02d limit %02d\n", bi.counter, bi.limit); + DBG_LOG(3,"BMC",("read data: ct %02d limit %02d\n", bi.counter, bi.limit)); if (bi.counter < bi.limit) { for (int a = 0; a < 32; a++) @@ -514,7 +515,7 @@ void i7220_device::read_data_continue(bubble_info &bi) return; default: - LOG("BMC read data unknown sub-state %d\n", bi.sub_state); + DBG_LOG(1,"BMC",("read data unknown sub-state %d\n", bi.sub_state)); return; } } @@ -542,7 +543,7 @@ void i7220_device::write_data_continue(bubble_info &bi) return; case WAIT_FIFO: - LOGDBG("BMC write data: fifo %02d ct %02d limit %02d\n", m_fifo_size, bi.counter, bi.limit); + DBG_LOG(3,"BMC",("write data: fifo %02d ct %02d limit %02d\n", m_fifo_size, bi.counter, bi.limit)); if (m_fifo_size >= 32) { for (int a = 0; a < 32; a++) @@ -564,7 +565,7 @@ void i7220_device::write_data_continue(bubble_info &bi) return; default: - LOG("BMC write data unknown sub-state %d\n", bi.sub_state); + DBG_LOG(1,"BMC",("write data unknown sub-state %d\n", bi.sub_state)); return; } } @@ -585,14 +586,14 @@ READ8_MEMBER(i7220_device::read) if (m_rac) { data = m_regs[m_rac]; - LOGREG("BMC R reg @ %02x == %02x\n", m_rac, data); + DBG_LOG(2, "BMC", ("R reg @ %02x == %02x\n", m_rac, data)); m_rac++; m_rac &= 15; } else { data = fifo_pop(); - LOGREG("BMC R fifo == %02x\n", data); + DBG_LOG(2, "BMC", ("R fifo == %02x\n", data)); } break; @@ -625,8 +626,8 @@ READ8_MEMBER(i7220_device::read) data |= SR_FIFO; } } - LOGREG("BMC R status == %02x (phase %d state %d:%d fifo %d drq %d)\n", - data, main_phase, bi.main_state, bi.sub_state, m_fifo_size, drq); + DBG_LOG(2, "BMC", ("R status == %02x (phase %d state %d:%d fifo %d drq %d)\n", + data, main_phase, bi.main_state, bi.sub_state, m_fifo_size, drq)); if (main_phase == PHASE_RESULT) { main_phase = PHASE_IDLE; @@ -634,7 +635,7 @@ READ8_MEMBER(i7220_device::read) break; } - LOGDBG("BMC R @ %d == %02x\n", offset, data); + DBG_LOG(3, "BMC", ("R @ %d == %02x\n", offset, data)); return data; } @@ -664,14 +665,14 @@ WRITE8_MEMBER( i7220_device::write ) "Software Reset" }; - LOGDBG("BMC W @ %d <- %02x\n", offset, data); + DBG_LOG(3, "BMC", ("W @ %d <- %02x\n", offset, data)); switch (offset & 1) { case 0: if (m_rac) { - LOGREG("BMC W reg @ %02x <- %02x\n", m_rac, data); + DBG_LOG(2, "BMC", ("W reg @ %02x <- %02x\n", m_rac, data)); m_regs[m_rac] = data; update_regs(); m_rac++; @@ -679,7 +680,7 @@ WRITE8_MEMBER( i7220_device::write ) } else { - LOGREG("BMC W fifo <- %02x\n", data); + DBG_LOG(2, "BMC", ("W fifo <- %02x\n", data)); fifo_push(data); } break; @@ -694,7 +695,7 @@ WRITE8_MEMBER( i7220_device::write ) m_cmdr = data & 15; if (main_phase == PHASE_IDLE) { - LOG("BMC command %02x '%s'\n", data, commands[m_cmdr]); + DBG_LOG(1, "BMC", ("command %02x '%s'\n", data, commands[m_cmdr])); main_phase = PHASE_CMD; start_command(m_cmdr); } diff --git a/src/devices/machine/i8087.cpp b/src/devices/machine/i8087.cpp index e137ae105e4..15d5e51bea2 100644 --- a/src/devices/machine/i8087.cpp +++ b/src/devices/machine/i8087.cpp @@ -169,7 +169,7 @@ DEFINE_DEVICE_TYPE(I8087, i8087_device, "i8087", "Intel 8087") i8087_device::i8087_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, type, tag, owner, clock), - m_space(*this, finder_base::DUMMY_TAG, -1), + device_memory_interface(mconfig, *this), m_int_handler(*this), m_busy_handler(*this) { @@ -180,6 +180,13 @@ i8087_device::i8087_device(const machine_config &mconfig, const char *tag, devic { } +device_memory_interface::space_config_vector i8087_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_space_config), + }; +} + void i8087_device::device_start() { save_item(NAME(m_reg[0].high)); @@ -215,6 +222,11 @@ void i8087_device::device_start() build_opcode_table(); } +void i8087_device::device_config_complete() +{ + m_space_config = address_space_config("program", ENDIANNESS_LITTLE, m_data_width, 20); +} + void i8087_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { m_busy_handler(1); diff --git a/src/devices/machine/i8087.h b/src/devices/machine/i8087.h index 9344ca2e68e..290b9a95b16 100644 --- a/src/devices/machine/i8087.h +++ b/src/devices/machine/i8087.h @@ -10,12 +10,12 @@ DECLARE_DEVICE_TYPE(I8087, i8087_device) -class i8087_device : public device_t +class i8087_device : public device_t, + public device_memory_interface { public: i8087_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - template <class Object> void set_space_88(Object &&tag, int spacenum) { m_space.set_tag(std::forward<Object>(tag), spacenum); m_space.set_data_width(8); } - template <class Object> void set_space_86(Object &&tag, int spacenum) { m_space.set_tag(std::forward<Object>(tag), spacenum); m_space.set_data_width(16); } + void set_data_width(u8 data_width) { m_data_width = data_width; } auto irq() { return m_int_handler.bind(); } auto busy() { return m_busy_handler.bind(); } @@ -26,13 +26,13 @@ protected: i8087_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); virtual void device_start() override; virtual void device_reset() override; + virtual void device_config_complete() override; + virtual space_config_vector memory_space_config() const override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; private: - address_space &space() { return *m_space; } - typedef void (i8087_device::*x87_func)(u8 modrm); - required_address_space m_space; + address_space_config m_space_config; devcb_write_line m_int_handler; devcb_write_line m_busy_handler; emu_timer *m_timer; @@ -45,6 +45,7 @@ private: u16 m_cw; u16 m_sw; u16 m_tw; + int m_data_width; int m_icount; x87_func m_opcode_table_d8[256]; diff --git a/src/devices/machine/i8155.cpp b/src/devices/machine/i8155.cpp index b5027368633..779874a244d 100644 --- a/src/devices/machine/i8155.cpp +++ b/src/devices/machine/i8155.cpp @@ -406,7 +406,7 @@ void i8155_device::device_timer(emu_timer &timer, device_timer_id id, int param, // io_r - register read //------------------------------------------------- -uint8_t i8155_device::io_r(offs_t offset) +READ8_MEMBER( i8155_device::io_r ) { uint8_t data = 0; @@ -539,7 +539,7 @@ void i8155_device::register_w(int offset, uint8_t data) // io_w - register write //------------------------------------------------- -void i8155_device::io_w(offs_t offset, uint8_t data) +WRITE8_MEMBER( i8155_device::io_w ) { register_w(offset, data); } @@ -549,7 +549,7 @@ void i8155_device::io_w(offs_t offset, uint8_t data) // memory_r - internal RAM read //------------------------------------------------- -uint8_t i8155_device::memory_r(offs_t offset) +READ8_MEMBER( i8155_device::memory_r ) { return m_ram[offset & 0xff]; } @@ -559,7 +559,7 @@ uint8_t i8155_device::memory_r(offs_t offset) // memory_w - internal RAM write //------------------------------------------------- -void i8155_device::memory_w(offs_t offset, uint8_t data) +WRITE8_MEMBER( i8155_device::memory_w ) { m_ram[offset & 0xff] = data; } @@ -569,7 +569,7 @@ void i8155_device::memory_w(offs_t offset, uint8_t data) // ale_w - address latch write //------------------------------------------------- -void i8155_device::ale_w(offs_t offset, uint8_t data) +WRITE8_MEMBER( i8155_device::ale_w ) { // I/O / memory select m_io_m = BIT(offset, 0); @@ -580,21 +580,21 @@ void i8155_device::ale_w(offs_t offset, uint8_t data) //------------------------------------------------- -// data_r - memory or I/O read +// read - memory or I/O read //------------------------------------------------- -uint8_t i8155_device::data_r() +READ8_MEMBER( i8155_device::read ) { uint8_t data = 0; switch (m_io_m) { case MEMORY: - data = memory_r(m_ad); + data = memory_r(space, m_ad); break; case IO: - data = io_r(m_ad); + data = io_r(space, m_ad); break; } @@ -603,19 +603,19 @@ uint8_t i8155_device::data_r() //------------------------------------------------- -// data_w - memory or I/O write +// write - memory or I/O write //------------------------------------------------- -void i8155_device::data_w(uint8_t data) +WRITE8_MEMBER( i8155_device::write ) { switch (m_io_m) { case MEMORY: - memory_w(m_ad, data); + memory_w(space, m_ad, data); break; case IO: - io_w(m_ad, data); + io_w(space, m_ad, data); break; } } diff --git a/src/devices/machine/i8155.h b/src/devices/machine/i8155.h index 2d6e49b2063..a17692211e6 100644 --- a/src/devices/machine/i8155.h +++ b/src/devices/machine/i8155.h @@ -55,15 +55,15 @@ public: auto out_pc_callback() { return m_out_pc_cb.bind(); } auto out_to_callback() { return m_out_to_cb.bind(); } - uint8_t io_r(offs_t offset); - void io_w(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( io_r ); + DECLARE_WRITE8_MEMBER( io_w ); - uint8_t memory_r(offs_t offset); - void memory_w(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( memory_r ); + DECLARE_WRITE8_MEMBER( memory_w ); - void ale_w(offs_t offset, uint8_t data); - uint8_t data_r(); - void data_w(uint8_t data); + DECLARE_WRITE8_MEMBER( ale_w ); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); protected: i8155_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); diff --git a/src/devices/machine/i82357.cpp b/src/devices/machine/i82357.cpp deleted file mode 100644 index 9b3be9c0905..00000000000 --- a/src/devices/machine/i82357.cpp +++ /dev/null @@ -1,307 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Patrick Mackinlay - -/* - * An implementation of the Intel 82357 Integrated System Peripheral. - * - * This device was one part of the 3-chip Intel 82350 EISA bus chipset. - * - * Sources: - * - * http://bitsavers.org/components/intel/_dataBooks/1996_Intel_Peripheral_Components.pdf - * - * TODO - * - expose everything to an actual EISA bus - * - 32-bit dma functionality - * - */ - -#include "emu.h" -#include "i82357.h" - -#define LOG_GENERAL (1U << 0) - -//#define VERBOSE (LOG_GENERAL) - -#include "logmacro.h" - -DEFINE_DEVICE_TYPE(I82357, i82357_device, "i82357", "Intel 82357 Integrated System Peripheral") - -i82357_device::i82357_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : device_t(mconfig, I82357, tag, owner, clock) - , m_pic(*this, "pic%u", 0) - , m_pit(*this, "pit%u", 0) - , m_dma(*this, "dma%u", 0) - , m_out_rtc(*this) - , m_out_nmi(*this) - , m_out_spkr(*this) -{ -} - -void i82357_device::device_add_mconfig(machine_config &config) -{ - PIC8259(config, m_pic[0], 0); - m_pic[0]->in_sp_callback().set_constant(1); - m_pic[0]->read_slave_ack_callback().set( - [this](offs_t offset) - { - if (offset == 2) - return m_pic[1]->acknowledge(); - - return u32(0); - }); - - PIC8259(config, m_pic[1], 0); - m_pic[1]->out_int_callback().set(m_pic[0], FUNC(pic8259_device::ir2_w)); - m_pic[1]->in_sp_callback().set_constant(0); - - PIT8254(config, m_pit[0], 0); - PIT8254(config, m_pit[1], 0); - - // timer 1 counter 0: system timer - m_pit[0]->set_clk<0>(clock() / 12); - m_pit[0]->out_handler<0>().set(m_pic[0], FUNC(pic8259_device::ir0_w)); - - // timer 1 counter 1: refresh request - m_pit[0]->set_clk<1>(clock() / 12); - m_pit[0]->out_handler<1>().set( - [this](int state) - { - // FIXME: not accurate, but good enough to pass diagnostic - if (state) - m_nmi_reg ^= NMI_REFRESH; - - m_pit[1]->write_gate2(state); - }); - - // timer 1 counter 2: speaker - m_pit[0]->set_clk<2>(clock() / 12); - m_pit[0]->out_handler<2>().set( - [this](int state) - { - if (state) - m_nmi_reg |= NMI_T1C2_STATE; - else - m_nmi_reg &= ~NMI_T1C2_STATE; - - m_out_spkr((m_nmi_reg & NMI_T1C2_STATE) && (m_nmi_reg & NMI_SPEAKER_DATA)); - }); - - // timer 2 counter 0: fail-safe timer - m_pit[1]->set_clk<0>(clock() / 48); - m_pit[1]->out_handler<0>().set( - [this](int state) - { - if (state && (m_nmi_ext & NMI_EXT_EN_FAILSAFE)) - { - m_nmi_ext |= NMI_EXT_FAILSAFE; - - m_nmi_check->adjust(attotime::zero); - } - }); - - // timer 2 counter 1: does not exist - - // timer 2 counter 2: cpu speed control - m_pit[1]->set_clk<2>(8_MHz_XTAL); - //m_pit[1]->out_handler<2>().set(); - - EISA_DMA(config, m_dma[0], clock() / 3); - EISA_DMA(config, m_dma[1], clock() / 3); - m_dma[1]->out_dack_callback<0>().set(m_dma[0], FUNC(eisa_dma_device::hack_w)).invert(); -} - -void i82357_device::map(address_map &map) -{ - map(0x000, 0x00f).rw(m_dma[0], FUNC(eisa_dma_device::read), FUNC(eisa_dma_device::write)); - map(0x020, 0x021).rw(m_pic[0], FUNC(pic8259_device::read), FUNC(pic8259_device::write)); - map(0x040, 0x043).rw(m_pit[0], FUNC(pit8254_device::read), FUNC(pit8254_device::write)); - map(0x048, 0x04b).rw(m_pit[1], FUNC(pit8254_device::read), FUNC(pit8254_device::write)); - - // FIXME: also 0x065 - "NMI Status" - map(0x061, 0x061).rw(FUNC(i82357_device::nmi_reg_r), FUNC(i82357_device::nmi_reg_w)); - - // NMI Enable Register (0x70, 72, 74, 76) - map(0x070, 0x077).lw8("nmi_rtc", - [this](address_space &space, offs_t offset, u8 data) - { - m_nmi_enabled = !BIT(data, 7); - - m_out_rtc(space, 0, data & 0x7f); - - m_nmi_check->adjust(attotime::zero); - }).umask64(0xff); - - map(0x081, 0x081).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page<2>), FUNC(eisa_dma_device::set_address_page<2>)); - map(0x082, 0x082).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page<3>), FUNC(eisa_dma_device::set_address_page<3>)); - map(0x083, 0x083).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page<1>), FUNC(eisa_dma_device::set_address_page<1>)); - map(0x087, 0x087).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page<0>), FUNC(eisa_dma_device::set_address_page<0>)); - map(0x089, 0x089).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page<2>), FUNC(eisa_dma_device::set_address_page<2>)); - map(0x08a, 0x08a).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page<3>), FUNC(eisa_dma_device::set_address_page<3>)); - map(0x08b, 0x08b).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page<1>), FUNC(eisa_dma_device::set_address_page<1>)); - map(0x08f, 0x08f).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page<0>), FUNC(eisa_dma_device::set_address_page<0>)); - - // TODO: also 0xa4, a8, ac, b0, b4, b8, bc - map(0x0a0, 0x0a1).rw(m_pic[1], FUNC(pic8259_device::read), FUNC(pic8259_device::write)); - map(0x0c0, 0x0df).rw(m_dma[1], FUNC(eisa_dma_device::read), FUNC(eisa_dma_device::write)).umask16(0x00ff); - - map(0x401, 0x401).rw(m_dma[0], FUNC(eisa_dma_device::get_count_high<0>), FUNC(eisa_dma_device::set_count_high<0>)); - map(0x403, 0x403).rw(m_dma[0], FUNC(eisa_dma_device::get_count_high<1>), FUNC(eisa_dma_device::set_count_high<1>)); - map(0x405, 0x405).rw(m_dma[0], FUNC(eisa_dma_device::get_count_high<2>), FUNC(eisa_dma_device::set_count_high<2>)); - map(0x407, 0x407).rw(m_dma[0], FUNC(eisa_dma_device::get_count_high<3>), FUNC(eisa_dma_device::set_count_high<3>)); - - //map(0x40a, 0x40a); // DMA1 Set Chaining Mode (w)/Interrupt Status (r) - //map(0x40b, 0x40b); // DMA1 Ext Write Mode (w) - //map(0x40c, 0x40c); // Chain Buffer Control - //map(0x40d, 0x40d); // Stepping Level Register (ro) - //map(0x40e, 0x40e); // ISP Test Register - //map(0x40f, 0x40f); // ISP Test Register - - map(0x461, 0x461).rw(FUNC(i82357_device::nmi_ext_r), FUNC(i82357_device::nmi_ext_w)); - map(0x462, 0x462).lw8("nmi_ioport", - [this](u8 data) - { - if (m_nmi_ext & NMI_EXT_EN_IOPORT) - { - m_nmi_ext |= NMI_EXT_IOPORT; - - m_nmi_check->adjust(attotime::zero); - } - }); - //map(0x464, 0x464); // Last 32-bit bus master granted (L) - - map(0x481, 0x481).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page_high<2>), FUNC(eisa_dma_device::set_address_page_high<2>)); - map(0x482, 0x482).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page_high<3>), FUNC(eisa_dma_device::set_address_page_high<3>)); - map(0x483, 0x483).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page_high<1>), FUNC(eisa_dma_device::set_address_page_high<1>)); - map(0x487, 0x487).rw(m_dma[0], FUNC(eisa_dma_device::get_address_page_high<0>), FUNC(eisa_dma_device::set_address_page_high<0>)); - map(0x489, 0x489).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page_high<2>), FUNC(eisa_dma_device::set_address_page_high<2>)); - map(0x48a, 0x48a).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page_high<3>), FUNC(eisa_dma_device::set_address_page_high<3>)); - map(0x48b, 0x48b).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page_high<1>), FUNC(eisa_dma_device::set_address_page_high<1>)); - map(0x48f, 0x48f).rw(m_dma[1], FUNC(eisa_dma_device::get_address_page_high<0>), FUNC(eisa_dma_device::set_address_page_high<0>)); - - map(0x4c2, 0x4c2).rw(m_dma[1], FUNC(eisa_dma_device::get_count_high<0>), FUNC(eisa_dma_device::set_count_high<0>)); - map(0x4c6, 0x4c6).rw(m_dma[1], FUNC(eisa_dma_device::get_count_high<1>), FUNC(eisa_dma_device::set_count_high<1>)); - map(0x4ca, 0x4ca).rw(m_dma[1], FUNC(eisa_dma_device::get_count_high<2>), FUNC(eisa_dma_device::set_count_high<2>)); - map(0x4ce, 0x4ce).rw(m_dma[1], FUNC(eisa_dma_device::get_count_high<3>), FUNC(eisa_dma_device::set_count_high<3>)); - map(0x4d0, 0x4d1).lrw8("elcr", - [this](offs_t offset) { return m_elcr[offset]; }, - [this](offs_t offset, u8 data) { m_elcr[offset] = data; }); - - //map(0x4d4, 0x4d4); // DMA2 Set Chaining Mode - //map(0x4d6, 0x4d6); // DMA2 Ext Write Mode Register - - map(0x4e0, 0x4e3).rw(m_dma[0], FUNC(eisa_dma_device::get_stop<0>), FUNC(eisa_dma_device::set_stop<0>)); - map(0x4e4, 0x4e7).rw(m_dma[0], FUNC(eisa_dma_device::get_stop<1>), FUNC(eisa_dma_device::set_stop<1>)); - map(0x4e8, 0x4eb).rw(m_dma[0], FUNC(eisa_dma_device::get_stop<2>), FUNC(eisa_dma_device::set_stop<2>)); - map(0x4ec, 0x4ef).rw(m_dma[0], FUNC(eisa_dma_device::get_stop<3>), FUNC(eisa_dma_device::set_stop<3>)); - - map(0x4f0, 0x4f3).rw(m_dma[1], FUNC(eisa_dma_device::get_stop<0>), FUNC(eisa_dma_device::set_stop<0>)); // reserved - map(0x4f4, 0x4f7).rw(m_dma[1], FUNC(eisa_dma_device::get_stop<1>), FUNC(eisa_dma_device::set_stop<1>)); - map(0x4f8, 0x4fb).rw(m_dma[1], FUNC(eisa_dma_device::get_stop<2>), FUNC(eisa_dma_device::set_stop<2>)); - map(0x4fc, 0x4ff).rw(m_dma[1], FUNC(eisa_dma_device::get_stop<3>), FUNC(eisa_dma_device::set_stop<3>)); -} - -void i82357_device::device_start() -{ - m_out_rtc.resolve_safe(); - m_out_nmi.resolve_safe(); - m_out_spkr.resolve_safe(); - - m_nmi_check = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(i82357_device::nmi_check), this)); -} - -void i82357_device::device_reset() -{ - m_elcr[0] = 0; - m_elcr[1] = 0; - - m_nmi_enabled = true; - m_nmi_reg = 0; - m_nmi_ext = 0; - - m_nmi_check->adjust(attotime::zero); -} - -void i82357_device::nmi_reg_w(u8 data) -{ - m_pit[0]->write_gate2(!!(data & NMI_T1C2_GATE)); - - // clear parity nmi - if (data & NMI_PARITY_DISABLE) - m_nmi_reg &= ~NMI_PARITY; - - // clear iochk nmi - if (data & NMI_IOCHK_DISABLE) - m_nmi_reg &= ~NMI_IOCHK; - - m_nmi_reg = (m_nmi_reg & ~NMI_WMASK) | (data & NMI_WMASK); - - // update speaker state - m_out_spkr((m_nmi_reg & NMI_T1C2_STATE) && (m_nmi_reg & NMI_SPEAKER_DATA)); - - m_nmi_check->adjust(attotime::zero); -} - -void i82357_device::nmi_ext_w(u8 data) -{ - if (!(data & NMI_EXT_EN_IOPORT)) - m_nmi_ext &= ~NMI_EXT_IOPORT; - - if (!(data & NMI_EXT_EN_TIMEOUT)) - m_nmi_ext &= ~NMI_EXT_TIMEOUT; - - if (!(data & NMI_EXT_EN_FAILSAFE)) - m_nmi_ext &= ~NMI_EXT_FAILSAFE; - - m_nmi_ext = (m_nmi_ext & ~NMI_EXT_WMASK) | (data & NMI_EXT_WMASK); - - m_nmi_check->adjust(attotime::zero); -} - -WRITE_LINE_MEMBER(i82357_device::in_iochk) -{ - if (!state && !(m_nmi_reg & NMI_PARITY_DISABLE)) - { - m_nmi_reg |= NMI_IOCHK; - - m_nmi_check->adjust(attotime::zero); - } - else - m_nmi_reg &= ~NMI_IOCHK; -} - -WRITE_LINE_MEMBER(i82357_device::in_parity) -{ - if (!state && !(m_nmi_reg & NMI_IOCHK_DISABLE)) - { - m_nmi_reg |= NMI_PARITY; - - m_nmi_check->adjust(attotime::zero); - } - else - m_nmi_reg &= ~NMI_PARITY; -} - -TIMER_CALLBACK_MEMBER(i82357_device::nmi_check) -{ - if (m_nmi_enabled) - { - if ((m_nmi_reg & NMI_NMI) || (m_nmi_ext & NMI_EXT_NMI)) - { - if (!m_out_nmi_asserted) - { - m_out_nmi_asserted = true; - m_out_nmi(1); - } - - return; - } - } - - // disabled or no source - if (m_out_nmi_asserted) - { - m_out_nmi_asserted = false; - m_out_nmi(0); - } -} diff --git a/src/devices/machine/i82357.h b/src/devices/machine/i82357.h deleted file mode 100644 index 3c5a7756061..00000000000 --- a/src/devices/machine/i82357.h +++ /dev/null @@ -1,91 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Patrick Mackinlay - -#ifndef MAME_MACHINE_I82357_H -#define MAME_MACHINE_I82357_H - -#pragma once - -#include "machine/pic8259.h" -#include "machine/pit8253.h" -#include "machine/am9517a.h" - -class i82357_device : public device_t -{ -public: - i82357_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - - auto out_rtc_cb() { return m_out_rtc.bind(); } - auto out_int_cb() { return subdevice<pic8259_device>("pic0")->out_int_callback(); } - auto out_nmi_cb() { return m_out_nmi.bind(); } - auto out_spkr_cb() { return m_out_spkr.bind(); } - - u32 eisa_irq_ack() { return m_pic[0]->acknowledge(); } - - DECLARE_WRITE_LINE_MEMBER(in_iochk); - DECLARE_WRITE_LINE_MEMBER(in_parity); - - void map(address_map &map); - -protected: - // standard device_t overrides - virtual void device_add_mconfig(machine_config &config) override; - virtual void device_start() override; - virtual void device_reset() override; - - void nmi_reg_w(u8 data); - void nmi_ext_w(u8 data); - u8 nmi_reg_r() { return m_nmi_reg; } - u8 nmi_ext_r() { return m_nmi_ext; } - - TIMER_CALLBACK_MEMBER(nmi_check); - -private: - required_device_array<pic8259_device, 2> m_pic; - required_device_array<pit8254_device, 2> m_pit; - required_device_array<eisa_dma_device, 2> m_dma; - - devcb_write8 m_out_rtc; - devcb_write_line m_out_nmi; - devcb_write_line m_out_spkr; - - enum nmi_reg_mask : u8 - { - NMI_T1C2_GATE = 0x01, - NMI_SPEAKER_DATA = 0x02, - NMI_PARITY_DISABLE = 0x04, - NMI_IOCHK_DISABLE = 0x08, - NMI_REFRESH = 0x10, - NMI_T1C2_STATE = 0x20, - NMI_IOCHK = 0x40, - NMI_PARITY = 0x80, - - NMI_WMASK = 0x0f, - NMI_NMI = 0xc0, - }; - enum nmi_ext_mask : u8 - { - NMI_EXT_BUS_RESET = 0x01, // bus reset (read/write) - NMI_EXT_EN_IOPORT = 0x02, - NMI_EXT_EN_FAILSAFE = 0x04, - NMI_EXT_EN_TIMEOUT = 0x08, - NMI_EXT_8US_TIMEOUT = 0x10, // 8us EISA bus master timeout occurred - NMI_EXT_IOPORT = 0x20, // NMI I/O port interrupt pending - NMI_EXT_TIMEOUT = 0x40, // EISA bus master timeout occurred, NMI requested - NMI_EXT_FAILSAFE = 0x80, // Fail-safe timer is active, NMI requested - - NMI_EXT_WMASK = 0x0f, - NMI_EXT_NMI = 0xe0, - }; - u8 m_elcr[2]; - - emu_timer *m_nmi_check; - bool m_out_nmi_asserted; - bool m_nmi_enabled; - u8 m_nmi_reg; - u8 m_nmi_ext; -}; - -DECLARE_DEVICE_TYPE(I82357, i82357_device) - -#endif // MAME_MACHINE_I82357_H diff --git a/src/devices/machine/i82371sb.cpp b/src/devices/machine/i82371sb.cpp index b149d98a48f..579d678906a 100644 --- a/src/devices/machine/i82371sb.cpp +++ b/src/devices/machine/i82371sb.cpp @@ -49,7 +49,7 @@ void i82371sb_isa_device::internal_io_map(address_map &map) void i82371sb_isa_device::device_add_mconfig(machine_config &config) { - PIT8254(config, m_pit8254); + PIT8254(config, m_pit8254, 0); m_pit8254->set_clk<0>(4772720/4); // heartbeat IRQ m_pit8254->out_handler<0>().set(FUNC(i82371sb_isa_device::at_pit8254_out0_changed)); m_pit8254->set_clk<1>(4772720/4); // DRAM refresh @@ -90,12 +90,12 @@ void i82371sb_isa_device::device_add_mconfig(machine_config &config) m_dma8237_2->out_dack_callback<2>().set(FUNC(i82371sb_isa_device::pc_dack6_w)); m_dma8237_2->out_dack_callback<3>().set(FUNC(i82371sb_isa_device::pc_dack7_w)); - PIC8259(config, m_pic8259_master); + PIC8259(config, m_pic8259_master, 0); m_pic8259_master->out_int_callback().set_inputline(m_maincpu, 0); m_pic8259_master->in_sp_callback().set_constant(1); m_pic8259_master->read_slave_ack_callback().set(FUNC(i82371sb_isa_device::get_slave_ack)); - PIC8259(config, m_pic8259_slave); + PIC8259(config, m_pic8259_slave, 0); m_pic8259_slave->out_int_callback().set(m_pic8259_master, FUNC(pic8259_device::ir2_w)); m_pic8259_slave->in_sp_callback().set_constant(0); @@ -104,8 +104,7 @@ void i82371sb_isa_device::device_add_mconfig(machine_config &config) SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50); ISA16(config, m_isabus, 0); - m_isabus->set_memspace(":maincpu", AS_PROGRAM); - m_isabus->set_iospace(":maincpu", AS_IO); + m_isabus->set_cputag(":maincpu"); m_isabus->irq3_callback().set(FUNC(i82371sb_isa_device::pc_irq3_w)); m_isabus->irq4_callback().set(FUNC(i82371sb_isa_device::pc_irq4_w)); m_isabus->irq5_callback().set(FUNC(i82371sb_isa_device::pc_irq5_w)); @@ -124,7 +123,6 @@ void i82371sb_isa_device::device_add_mconfig(machine_config &config) m_isabus->drq5_callback().set(m_dma8237_2, FUNC(am9517a_device::dreq1_w)); m_isabus->drq6_callback().set(m_dma8237_2, FUNC(am9517a_device::dreq2_w)); m_isabus->drq7_callback().set(m_dma8237_2, FUNC(am9517a_device::dreq3_w)); - m_isabus->iochck_callback().set(FUNC(i82371sb_isa_device::iochck_w)); } i82371sb_isa_device::i82371sb_isa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : @@ -658,8 +656,6 @@ WRITE_LINE_MEMBER( i82371sb_isa_device::at_dma8237_out_eop ) void i82371sb_isa_device::pc_select_dma_channel(int channel, bool state) { - m_isabus->dack_line_w(channel, state); - if(!state) { m_dma_channel = channel; if(m_cur_eop) @@ -822,24 +818,17 @@ WRITE8_MEMBER( i82371sb_isa_device::at_portb_w ) m_pit8254->write_gate2(BIT(data, 0)); at_speaker_set_spkrdata( BIT(data, 1)); m_channel_check = BIT(data, 3); - if (m_channel_check) - m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); -} - -WRITE_LINE_MEMBER( i82371sb_isa_device::iochck_w ) -{ - if (!state && !m_channel_check && m_nmi_enabled) - m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); + m_isabus->set_nmi_state((m_nmi_enabled==0) && (m_channel_check==0)); } READ8_MEMBER( i82371sb_isa_device::at_dma8237_2_r ) { - return m_dma8237_2->read(offset / 2); + return m_dma8237_2->read( space, offset / 2); } WRITE8_MEMBER( i82371sb_isa_device::at_dma8237_2_w ) { - m_dma8237_2->write(offset / 2, data); + m_dma8237_2->write( space, offset / 2, data); } READ8_MEMBER(i82371sb_isa_device::eisa_irq_read) diff --git a/src/devices/machine/i82371sb.h b/src/devices/machine/i82371sb.h index 5d79eec29ef..ea7976ad845 100644 --- a/src/devices/machine/i82371sb.h +++ b/src/devices/machine/i82371sb.h @@ -146,7 +146,6 @@ private: DECLARE_WRITE8_MEMBER(at_page8_w); DECLARE_READ8_MEMBER(at_portb_r); DECLARE_WRITE8_MEMBER(at_portb_w); - DECLARE_WRITE_LINE_MEMBER(iochck_w); DECLARE_READ8_MEMBER(ide_read_cs1_r); DECLARE_WRITE8_MEMBER(ide_write_cs1_w); DECLARE_READ8_MEMBER(ide2_read_cs1_r); diff --git a/src/devices/machine/i8251.cpp b/src/devices/machine/i8251.cpp index 1c3189d8f8f..773262b617e 100644 --- a/src/devices/machine/i8251.cpp +++ b/src/devices/machine/i8251.cpp @@ -674,11 +674,9 @@ uint8_t i8251_device::data_r() { LOG("read data: %02x, STATUS=%02x\n",m_rx_data,m_status); /* reading clears */ - if (!machine().side_effects_disabled()) - { - m_status &= ~I8251_STATUS_RX_READY; - update_rx_ready(); - } + m_status &= ~I8251_STATUS_RX_READY; + + update_rx_ready(); return m_rx_data; } diff --git a/src/devices/machine/i8251.h b/src/devices/machine/i8251.h index f8b92725b05..4e2773c3e40 100644 --- a/src/devices/machine/i8251.h +++ b/src/devices/machine/i8251.h @@ -54,7 +54,10 @@ public: DECLARE_READ_LINE_MEMBER(txrdy_r); -protected: + /// TODO: REMOVE THIS + void receive_character(uint8_t ch); + + /// TODO: this shouldn't be public enum { I8251_STATUS_FRAMING_ERROR = 0x20, @@ -65,6 +68,7 @@ protected: I8251_STATUS_TX_READY = 0x01 }; +protected: i8251_device( const machine_config &mconfig, device_type type, @@ -79,8 +83,6 @@ protected: void command_w(uint8_t data); void mode_w(uint8_t data); - void receive_character(uint8_t ch); - void update_rx_ready(); void update_tx_ready(); void update_tx_empty(); diff --git a/src/devices/machine/i8271.cpp b/src/devices/machine/i8271.cpp index 1bac233f955..3a309c4ea16 100644 --- a/src/devices/machine/i8271.cpp +++ b/src/devices/machine/i8271.cpp @@ -132,7 +132,7 @@ void i8271_device::set_floppy(floppy_image_device *flop) flop->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&i8271_device::index_callback, this)); } -uint8_t i8271_device::sr_r() +READ8_MEMBER(i8271_device::sr_r) { uint32_t ret = (irq ? SR_IRQ : 0); switch(main_phase) { @@ -151,13 +151,11 @@ uint8_t i8271_device::sr_r() return ret; } -uint8_t i8271_device::rr_r() +READ8_MEMBER(i8271_device::rr_r) { - if (!machine().side_effects_disabled()) { - if (main_phase == PHASE_RESULT) - main_phase = PHASE_IDLE; - set_irq(false); - } + if(main_phase == PHASE_RESULT) + main_phase = PHASE_IDLE; + set_irq(false); return rr; } @@ -166,32 +164,31 @@ void i8271_device::set_rate(int rate) cur_rate = rate; } -uint8_t i8271_device::read(offs_t offset) +READ8_MEMBER(i8271_device::read) { switch(offset & 0x03) { - case 0x00: return sr_r(); - case 0x01: return rr_r(); + case 0x00: return sr_r(space, 0); + case 0x01: return rr_r(space, 0); } return 0xff; } -void i8271_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(i8271_device::write) { switch(offset & 0x03) { - case 0x00: cmd_w(data); break; - case 0x01: param_w(data); break; - case 0x02: reset_w(data); break; + case 0x00: cmd_w(space, 0, data); break; + case 0x01: param_w(space, 0, data); break; + case 0x02: reset_w(space, 0, data); break; } } -uint8_t i8271_device::data_r() +READ8_MEMBER(i8271_device::data_r) { - if (!machine().side_effects_disabled()) - set_drq(false); + set_drq(false); return dma_data; } -void i8271_device::data_w(uint8_t data) +WRITE8_MEMBER(i8271_device::data_w) { if(drq) { set_drq(false); @@ -199,7 +196,7 @@ void i8271_device::data_w(uint8_t data) } } -void i8271_device::cmd_w(uint8_t data) +WRITE8_MEMBER(i8271_device::cmd_w) { if(main_phase == PHASE_IDLE) { command[0] = data; @@ -214,7 +211,7 @@ void i8271_device::cmd_w(uint8_t data) } } -void i8271_device::param_w(uint8_t data) +WRITE8_MEMBER(i8271_device::param_w) { if(main_phase == PHASE_CMD) { command[command_pos++] = data; diff --git a/src/devices/machine/i8271.h b/src/devices/machine/i8271.h index 88e9a6146e6..701085f58d4 100644 --- a/src/devices/machine/i8271.h +++ b/src/devices/machine/i8271.h @@ -24,10 +24,10 @@ public: auto hdl_wr_callback() { return hdl_cb.bind(); } auto opt_wr_callback() { return opt_cb.bind(); } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); - uint8_t data_r(); - void data_w(uint8_t data); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); + DECLARE_READ8_MEMBER (data_r); + DECLARE_WRITE8_MEMBER(data_w); void ready_w(bool val); @@ -228,11 +228,11 @@ private: C_INCOMPLETE }; - uint8_t sr_r(); - uint8_t rr_r(); - void reset_w(uint8_t data) { if(data == 1) soft_reset(); } - void cmd_w(uint8_t data); - void param_w(uint8_t data); + DECLARE_READ8_MEMBER (sr_r); + DECLARE_READ8_MEMBER (rr_r); + DECLARE_WRITE8_MEMBER(reset_w) { if(data == 1) soft_reset(); } + DECLARE_WRITE8_MEMBER(cmd_w); + DECLARE_WRITE8_MEMBER(param_w); void delay_cycles(emu_timer *tm, int cycles); void set_drq(bool state); diff --git a/src/devices/machine/idectrl.cpp b/src/devices/machine/idectrl.cpp index 45f6ab6f703..b8ab541fc8d 100644 --- a/src/devices/machine/idectrl.cpp +++ b/src/devices/machine/idectrl.cpp @@ -222,7 +222,6 @@ DEFINE_DEVICE_TYPE(BUS_MASTER_IDE_CONTROLLER, bus_master_ide_controller_device, bus_master_ide_controller_device::bus_master_ide_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : ide_controller_32_device(mconfig, BUS_MASTER_IDE_CONTROLLER, tag, owner, clock), - m_dma_space(*this, finder_base::DUMMY_TAG, -1, 32), m_dma_address(0), m_dma_bytes_left(0), m_dma_descriptor(0), @@ -240,7 +239,17 @@ void bus_master_ide_controller_device::device_start() ide_controller_32_device::device_start(); /* find the bus master space */ - m_dma_address_xor = (m_dma_space->endianness() == ENDIANNESS_LITTLE) ? 0 : 3; + if (m_bmcpu != nullptr) + { + device_t *bmtarget = machine().device(m_bmcpu); + if (bmtarget == nullptr) + throw emu_fatalerror("IDE controller '%s' bus master target '%s' doesn't exist!", tag(), m_bmcpu); + device_memory_interface *memory; + if (!bmtarget->interface(memory)) + throw emu_fatalerror("IDE controller '%s' bus master target '%s' has no memory!", tag(), m_bmcpu); + m_dma_space = &memory->space(m_bmspace); + m_dma_address_xor = (m_dma_space->endianness() == ENDIANNESS_LITTLE) ? 0 : 3; + } save_item(NAME(m_dma_address)); save_item(NAME(m_dma_bytes_left)); diff --git a/src/devices/machine/idectrl.h b/src/devices/machine/idectrl.h index c0e84e3c562..3a0886a5185 100644 --- a/src/devices/machine/idectrl.h +++ b/src/devices/machine/idectrl.h @@ -105,7 +105,7 @@ class bus_master_ide_controller_device : public ide_controller_32_device { public: bus_master_ide_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); - template <typename T> void set_bus_master_space(T &&bmtag, int bmspace) { m_dma_space.set_tag(std::forward<T>(bmtag), bmspace); } + void set_bus_master_space(const char *bmcpu, uint32_t bmspace) { m_bmcpu = bmcpu; m_bmspace = bmspace; } template <typename T> bus_master_ide_controller_device &master(T &&opts, const char *dflt = nullptr, bool fixed = false) { @@ -140,7 +140,9 @@ protected: private: void execute_dma(); - required_address_space m_dma_space; + const char *m_bmcpu; + uint32_t m_bmspace; + address_space *m_dma_space; uint8_t m_dma_address_xor; offs_t m_dma_address; diff --git a/src/devices/machine/idehd.cpp b/src/devices/machine/idehd.cpp index 1f4be38d491..b9f6ddbbe70 100644 --- a/src/devices/machine/idehd.cpp +++ b/src/devices/machine/idehd.cpp @@ -869,7 +869,6 @@ uint8_t ide_hdd_device::calculate_status() // device_add_mconfig - add device configuration //------------------------------------------------- -void ide_hdd_device::device_add_mconfig(machine_config &config) -{ - HARDDISK(config, "image"); -} +MACHINE_CONFIG_START(ide_hdd_device::device_add_mconfig) + MCFG_HARDDISK_ADD( "image" ) +MACHINE_CONFIG_END diff --git a/src/devices/machine/ie15.cpp b/src/devices/machine/ie15.cpp index 65a71ae23c3..4f1a8a25bfc 100644 --- a/src/devices/machine/ie15.cpp +++ b/src/devices/machine/ie15.cpp @@ -568,25 +568,25 @@ static GFXDECODE_START( gfx_ie15 ) GFXDECODE_ENTRY("chargen", 0x0000, ie15_charlayout, 0, 1) GFXDECODE_END -void ie15_device::ie15core(machine_config &config) -{ +MACHINE_CONFIG_START(ie15_device::ie15core) /* Basic machine hardware */ - IE15_CPU(config, m_maincpu, XTAL(30'800'000)/10); - m_maincpu->set_addrmap(AS_PROGRAM, &ie15_device::ie15_mem); - m_maincpu->set_addrmap(AS_IO, &ie15_device::ie15_io); + MCFG_DEVICE_ADD("maincpu", IE15_CPU, XTAL(30'800'000)/10) + MCFG_DEVICE_PROGRAM_MAP(ie15_mem) + MCFG_DEVICE_IO_MAP(ie15_io) config.set_default_layout(layout_ie15); /* Devices */ - IE15_KEYBOARD(config, m_keyboard, 0).keyboard_cb().set(FUNC(ie15_device::kbd_put)); + IE15_KEYBOARD(config, m_keyboard, 0) + .keyboard_cb().set(FUNC(ie15_device::kbd_put)); RS232_PORT(config, m_rs232, default_rs232_devices, "null_modem"); m_rs232->rxd_handler().set(FUNC(ie15_device::serial_rx_callback)); SPEAKER(config, "mono").front_center(); - BEEP(config, m_beeper, 2400); - m_beeper->add_route(ALL_OUTPUTS, "mono", 0.15); -} + MCFG_DEVICE_ADD("beeper", BEEP, 2400) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.15) +MACHINE_CONFIG_END /* ROM definition */ ROM_START( ie15 ) @@ -603,20 +603,18 @@ ROM_START( ie15 ) ROM_LOAD("chargen-15ie.bin", 0x0000, 0x0800, CRC(ed16bf6b) SHA1(6af9fb75f5375943d5c0ce9ed408e0fb4621b17e)) ROM_END -void ie15_device::device_add_mconfig(machine_config &config) -{ - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_color(rgb_t::green()); - m_screen->set_screen_update(FUNC(ie15_device::screen_update)); - m_screen->set_raw(XTAL(30'800'000)/2, +MACHINE_CONFIG_START(ie15_device::device_add_mconfig) + MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::green()) + MCFG_SCREEN_UPDATE_DRIVER(ie15_device, screen_update) + MCFG_SCREEN_RAW_PARAMS(XTAL(30'800'000)/2, IE15_TOTAL_HORZ, IE15_HORZ_START, IE15_HORZ_START+IE15_DISP_HORZ, IE15_TOTAL_VERT, IE15_VERT_START, IE15_VERT_START+IE15_DISP_VERT); ie15core(config); - GFXDECODE(config, "gfxdecode", "palette", gfx_ie15); + MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_ie15) PALETTE(config, "palette", palette_device::MONOCHROME); -} +MACHINE_CONFIG_END ioport_constructor ie15_device::device_input_ports() const { diff --git a/src/devices/machine/ie15_kbd.cpp b/src/devices/machine/ie15_kbd.cpp index 79a4bb86aad..13ee3ea5744 100644 --- a/src/devices/machine/ie15_kbd.cpp +++ b/src/devices/machine/ie15_kbd.cpp @@ -122,9 +122,8 @@ const tiny_rom_entry *ie15_keyboard_device::device_rom_region() const return ROM_NAME( ie15_keyboard ); } -void ie15_keyboard_device::device_add_mconfig(machine_config &config) -{ -} +MACHINE_CONFIG_START(ie15_keyboard_device::device_add_mconfig) +MACHINE_CONFIG_END void ie15_keyboard_device::device_start() diff --git a/src/devices/machine/input_merger.h b/src/devices/machine/input_merger.h index aa5e66cc1f1..53af1a38cfd 100644 --- a/src/devices/machine/input_merger.h +++ b/src/devices/machine/input_merger.h @@ -15,6 +15,27 @@ #pragma once + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_INPUT_MERGER_ANY_HIGH(_tag) \ + MCFG_DEVICE_ADD(_tag, INPUT_MERGER_ANY_HIGH, 0) + +#define MCFG_INPUT_MERGER_ALL_HIGH(_tag) \ + MCFG_DEVICE_ADD(_tag, INPUT_MERGER_ALL_HIGH, 0) + +#define MCFG_INPUT_MERGER_ANY_LOW(_tag) \ + MCFG_DEVICE_ADD(_tag, INPUT_MERGER_ANY_LOW, 0) + +#define MCFG_INPUT_MERGER_ALL_LOW(_tag) \ + MCFG_DEVICE_ADD(_tag, INPUT_MERGER_ALL_LOW, 0) + +#define MCFG_INPUT_MERGER_OUTPUT_HANDLER(_devcb) \ + downcast<input_merger_device &>(*device).set_output_handler(DEVCB_##_devcb); + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -23,6 +44,7 @@ class input_merger_device : public device_t { public: // callback + template <class Object> devcb_base &set_output_handler(Object &&cb) { return m_output_handler.set_callback(std::forward<Object>(cb)); } auto output_handler() { return m_output_handler.bind(); } // input lines diff --git a/src/devices/machine/ins8154.cpp b/src/devices/machine/ins8154.cpp index 11943cdee2c..8a134000f3f 100644 --- a/src/devices/machine/ins8154.cpp +++ b/src/devices/machine/ins8154.cpp @@ -1,24 +1,21 @@ // license:GPL-2.0+ // copyright-holders:Dirk Best -/****************************************************************************** +/*************************************************************************** National Semiconductor INS8154 N-Channel 128-by-8 Bit RAM Input/Output (RAM I/O) TODO: Strobed modes - TODO: Check the ODRx register for where to get pin values, _cb() vs m_out_x -*******************************************************************************/ +***************************************************************************/ #include "emu.h" #include "ins8154.h" -#define LOG_BITS (1U << 1) -//#define VERBOSE (LOG_BITS) // (LOG_GENERAL|LOG_BITS) +#define VERBOSE 1 #include "logmacro.h" -#define LOGBITS(...) LOGMASKED(LOG_BITS, __VA_ARGS__) /*************************************************************************** CONSTANTS @@ -78,7 +75,6 @@ void ins8154_device::device_start() save_item(NAME(m_mdr)); save_item(NAME(m_odra)); save_item(NAME(m_odrb)); - save_item(NAME(m_ram)); } @@ -98,7 +94,7 @@ void ins8154_device::device_reset() } -uint8_t ins8154_device::read_io(offs_t offset) +READ8_MEMBER(ins8154_device::ins8154_r) { uint8_t val = 0xff; @@ -123,23 +119,17 @@ uint8_t ins8154_device::read_io(offs_t offset) break; default: - val = 0; - if (offset < 0x08) // Read a bit in Port A + if (offset < 0x08) { if (!m_in_a_cb.isnull()) - { - //val = (m_in_a_cb(0) << (8 - offset)) & 0x80; - val = (m_in_a_cb(0) & ~m_odra & (1 << (offset & 0x07))) ? 0x80 : 0x00; - } - LOGBITS("%s: INS8154 Port A read bit %02x: %02x\n", machine().describe_context(), offset & 0x07, val); + val = (m_in_a_cb(0) << (8 - offset)) & 0x80; + m_in_a = val; } - else // Read a bit in Port B + else { if (!m_in_b_cb.isnull()) - { - val = (m_in_b_cb(0) & ~m_odrb & (1 << (offset & 0x07))) ? 0x80 : 0x00; - } - LOGBITS("%s: INS8154 Port B read bit %02x: %02x\n", machine().describe_context(), offset & 0x07, val); + val = (m_in_b_cb(0) << (8 - (offset >> 4))) & 0x80; + m_in_b = val; } break; } @@ -147,12 +137,7 @@ uint8_t ins8154_device::read_io(offs_t offset) return val; } -uint8_t ins8154_device::read_ram(offs_t offset) -{ - return m_ram[offset & 0x7f]; -} - -void ins8154_device::porta_w(uint8_t data) +WRITE8_MEMBER(ins8154_device::ins8154_porta_w) { m_out_a = data; @@ -161,9 +146,8 @@ void ins8154_device::porta_w(uint8_t data) m_out_a_cb(offs_t(0), (data & m_odra) | (m_odra ^ 0xff)); } -void ins8154_device::portb_w(uint8_t data) +WRITE8_MEMBER(ins8154_device::ins8154_portb_w) { - LOG("%s: INS8154 Write PortB %02x with odrb: %02x\n", machine().describe_context(), data, m_odrb); m_out_b = data; /* Test if any pins are set as outputs */ @@ -171,7 +155,7 @@ void ins8154_device::portb_w(uint8_t data) m_out_b_cb(offs_t(0), (data & m_odrb) | (m_odrb ^ 0xff)); } -void ins8154_device::write_io(offs_t offset, uint8_t data) +WRITE8_MEMBER(ins8154_device::ins8154_w) { if (offset > 0x24) { @@ -182,11 +166,11 @@ void ins8154_device::write_io(offs_t offset, uint8_t data) switch (offset) { case 0x20: - porta_w(data); + ins8154_porta_w(space, 0, data); break; case 0x21: - portb_w(data); + ins8154_portb_w(space, 0, data); break; case 0x22: @@ -209,35 +193,18 @@ void ins8154_device::write_io(offs_t offset, uint8_t data) { /* Set bit */ if (offset < 0x08) - { - LOGBITS("%s: INS8154 Port A set bit %02x\n", machine().describe_context(), offset & 0x07); - porta_w(m_out_a |= (1 << (offset & 0x07))); - } + ins8154_porta_w(space, 0, m_out_a |= offset & 0x07); else - { - LOGBITS("%s: INS8154 Port B set bit %02x\n", machine().describe_context(), offset & 0x07); - portb_w(m_out_b |= (1 << (offset & 0x07))); - } + ins8154_portb_w(space, 0, m_out_b |= (offset >> 4) & 0x07); } else { /* Clear bit */ if (offset < 0x08) - { - LOGBITS("%s: INS8154 Port A clear bit %02x\n", machine().describe_context(), offset & 0x07); - porta_w(m_out_a & ~(1 << (offset & 0x07))); - } + ins8154_porta_w(space, 0, m_out_a & ~(offset & 0x07)); else - { - LOGBITS("%s: INS8154 Port B clear bit %02x\n", machine().describe_context(), offset & 0x07); - portb_w(m_out_b & ~(1 << (offset & 0x07))); - } + ins8154_portb_w(space, 0, m_out_b & ~((offset >> 4) & 0x07)); } break; } } - -void ins8154_device::write_ram(offs_t offset, uint8_t data) -{ - m_ram[offset & 0x7f] = data; -} diff --git a/src/devices/machine/ins8154.h b/src/devices/machine/ins8154.h index 2ce40ec9e70..5ba94ab9cda 100644 --- a/src/devices/machine/ins8154.h +++ b/src/devices/machine/ins8154.h @@ -47,13 +47,11 @@ public: auto out_b() { return m_out_b_cb.bind(); } auto out_irq() { return m_out_irq_cb.bind(); } - uint8_t read_io(offs_t offset); - void write_io(offs_t offset, uint8_t data); - uint8_t read_ram(offs_t offset); - void write_ram(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( ins8154_r ); + DECLARE_WRITE8_MEMBER( ins8154_w ); - void porta_w(uint8_t data); - void portb_w(uint8_t data); + DECLARE_WRITE8_MEMBER( ins8154_porta_w ); + DECLARE_WRITE8_MEMBER( ins8154_portb_w ); protected: // device-level overrides @@ -79,9 +77,6 @@ private: uint8_t m_mdr; /* Mode Definition Register */ uint8_t m_odra; /* Output Definition Register Port A */ uint8_t m_odrb; /* Output Definition Register Port B */ - - /* on-board RAM */ - uint8_t m_ram[0x80]; }; diff --git a/src/devices/machine/ins8250.cpp b/src/devices/machine/ins8250.cpp index d127ce0e40d..88262cdbac2 100644 --- a/src/devices/machine/ins8250.cpp +++ b/src/devices/machine/ins8250.cpp @@ -390,8 +390,6 @@ WRITE8_MEMBER( ins8250_uart_device::ins8250_w ) if ( m_regs.msr & 0x0f ) trigger_int(COM_INT_PENDING_MODEM_STATUS_REGISTER); - else - clear_int(COM_INT_PENDING_MODEM_STATUS_REGISTER); break; case 7: m_regs.scr = data; diff --git a/src/devices/machine/intelfsh.h b/src/devices/machine/intelfsh.h index edaa23d69f6..7dcf9f7e173 100644 --- a/src/devices/machine/intelfsh.h +++ b/src/devices/machine/intelfsh.h @@ -102,8 +102,8 @@ class intelfsh8_device : public intelfsh_device { public: // public interface - uint8_t read(offs_t offset) { return read_full(offset); } - void write(offs_t offset, uint8_t data) { write_full(offset, data); } + DECLARE_READ8_MEMBER(read) { return read_full(offset); } + DECLARE_WRITE8_MEMBER(write) { write_full(offset, data); } uint8_t read_raw(offs_t offset) { return m_data[offset]; } void write_raw(offs_t offset, uint8_t data) { m_data[offset] = data; } @@ -120,8 +120,8 @@ class intelfsh16_device : public intelfsh_device { public: // public interface - uint16_t read(offs_t offset) { return read_full(offset); } - void write(offs_t offset, uint16_t data) { write_full(offset, data); } + DECLARE_READ16_MEMBER(read) { return read_full(offset); } + DECLARE_WRITE16_MEMBER(write) { write_full(offset, data); } uint16_t read_raw(offs_t offset) { return m_data[offset*2] | (m_data[offset*2+1] << 8); } void write_raw(offs_t offset, uint16_t data) { m_data[offset*2] = data; m_data[offset*2+1] = data >> 8; } diff --git a/src/devices/machine/k054321.cpp b/src/devices/machine/k054321.cpp index 592bc74582a..21e02e9042f 100644 --- a/src/devices/machine/k054321.cpp +++ b/src/devices/machine/k054321.cpp @@ -11,7 +11,7 @@ /* The 054321 is a sound communication latch/volume manager chip, that - is integrated into the 054544 and 054986A hybrid chips. The hybrid + is integrated into the 054544 and 05489A hybrid chips. The hybrid chips also include the DACs, capacitors, etc needed for the audio output. diff --git a/src/devices/machine/keyboard.cpp b/src/devices/machine/keyboard.cpp index 52502597227..03e73f3ac05 100644 --- a/src/devices/machine/keyboard.cpp +++ b/src/devices/machine/keyboard.cpp @@ -9,10 +9,10 @@ or for the case of a computer with an inbuilt (not serial) ascii keyboard. Example of usage in a driver. -In the machine config function: +In MACHINE_CONFIG - generic_keyboard_device &kbd(GENERIC_KEYBOARD(config, KEYBOARD_TAG, 0)); - kbd.set_keyboard_callback(FUNC(xxx_state::kbd_put)); + MCFG_DEVICE_ADD(KEYBOARD_TAG, GENERIC_KEYBOARD, 0) + MCFG_GENERIC_KEYBOARD_CB(WRITE8(*this, xxx_state, kbd_put)) In the code: diff --git a/src/devices/machine/ldp1000.h b/src/devices/machine/ldp1000.h index b3f420afb6e..1f3140f14e8 100644 --- a/src/devices/machine/ldp1000.h +++ b/src/devices/machine/ldp1000.h @@ -15,6 +15,13 @@ //************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_LASERDISC_LDP1000_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, SONY_LDP1000, 0) + +//************************************************************************** // TYPE DEFINITIONS //************************************************************************** diff --git a/src/devices/machine/ldp1450.h b/src/devices/machine/ldp1450.h index 67a429845e1..3ef9fab0939 100644 --- a/src/devices/machine/ldp1450.h +++ b/src/devices/machine/ldp1450.h @@ -15,6 +15,13 @@ //************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_LASERDISC_LDP1450_ADD(_tag, clock) \ + MCFG_DEVICE_ADD(_tag, SONY_LDP1450, clock) + +//************************************************************************** // TYPE DEFINITIONS //************************************************************************** diff --git a/src/devices/machine/ldpr8210.h b/src/devices/machine/ldpr8210.h index fc0a28d6d26..f142229314c 100644 --- a/src/devices/machine/ldpr8210.h +++ b/src/devices/machine/ldpr8210.h @@ -23,6 +23,8 @@ #define MCFG_LASERDISC_PR8210_ADD(_tag) \ MCFG_DEVICE_ADD(_tag, PIONEER_PR8210, 0) +#define MCFG_LASERDISC_SIMUTREK_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, SIMUTREK_SPECIAL, 0) //************************************************************************** diff --git a/src/devices/machine/ldstub.cpp b/src/devices/machine/ldstub.cpp index c0c9a7ac05a..9d3dab58ce3 100644 --- a/src/devices/machine/ldstub.cpp +++ b/src/devices/machine/ldstub.cpp @@ -17,8 +17,8 @@ //************************************************************************** // device type definition -DEFINE_DEVICE_TYPE(PIONEER_PR7820, pioneer_pr7820_device, "pr7820", "Pioneer PR-7820") -DEFINE_DEVICE_TYPE(PHILIPS_22VP932, philips_22vp932_device, "22vp932", "Philips 22VP932") +DEFINE_DEVICE_TYPE(PIONEER_PR7820, pioneer_pr7820_device, "pr7820", "Pioneer PR-7820") +DEFINE_DEVICE_TYPE(PHILLIPS_22VP932, phillips_22vp932_device, "22vp932", "Phillips 22VP932") pioneer_pr7820_device::pioneer_pr7820_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) @@ -27,7 +27,7 @@ pioneer_pr7820_device::pioneer_pr7820_device(const machine_config &mconfig, cons } -philips_22vp932_device::philips_22vp932_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : laserdisc_device(mconfig, PHILIPS_22VP932, tag, owner, clock) +phillips_22vp932_device::phillips_22vp932_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : laserdisc_device(mconfig, PHILLIPS_22VP932, tag, owner, clock) { } diff --git a/src/devices/machine/ldstub.h b/src/devices/machine/ldstub.h index 9fbc756b240..4bf463b897d 100644 --- a/src/devices/machine/ldstub.h +++ b/src/devices/machine/ldstub.h @@ -17,12 +17,23 @@ //************************************************************************** +// DEVICE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_LASERDISC_PR7820_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, PIONEER_PR7820, 0) +#define MCFG_LASERDISC_22VP932_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, PHILLIPS_22VP932, 0) + + +//************************************************************************** // GLOBAL VARIABLES //************************************************************************** // device type definition -DECLARE_DEVICE_TYPE(PIONEER_PR7820, pioneer_pr7820_device) -DECLARE_DEVICE_TYPE(PHILIPS_22VP932, philips_22vp932_device) +DECLARE_DEVICE_TYPE(PIONEER_PR7820, pioneer_pr7820_device) +DECLARE_DEVICE_TYPE(PHILLIPS_22VP932, phillips_22vp932_device) + //************************************************************************** @@ -52,13 +63,13 @@ protected: }; -// ======================> philips_22vp932_device +// ======================> phillips_22vp932_device -class philips_22vp932_device : public laserdisc_device +class phillips_22vp932_device : public laserdisc_device { public: // construction/destruction - philips_22vp932_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + phillips_22vp932_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // input/output uint8_t data_r() { return 0; } diff --git a/src/devices/machine/ldv1000.cpp b/src/devices/machine/ldv1000.cpp index 4f7a0196e40..4a9b1295b75 100644 --- a/src/devices/machine/ldv1000.cpp +++ b/src/devices/machine/ldv1000.cpp @@ -272,8 +272,7 @@ const tiny_rom_entry *pioneer_ldv1000_device::device_rom_region() const // device_add_mconfig - add device configuration //------------------------------------------------- -void pioneer_ldv1000_device::device_add_mconfig(machine_config &config) -{ +MACHINE_CONFIG_START(pioneer_ldv1000_device::device_add_mconfig) Z80(config, m_z80_cpu, XTAL(5'000'000)/2); m_z80_cpu->set_daisy_config(daisy_chain); m_z80_cpu->set_addrmap(AS_PROGRAM, &pioneer_ldv1000_device::ldv1000_map); @@ -292,7 +291,7 @@ void pioneer_ldv1000_device::device_add_mconfig(machine_config &config) ldvppi1.in_pa_callback().set(FUNC(pioneer_ldv1000_device::ppi1_porta_r)); ldvppi1.out_pb_callback().set(FUNC(pioneer_ldv1000_device::ppi1_portb_w)); ldvppi1.out_pc_callback().set(FUNC(pioneer_ldv1000_device::ppi1_portc_w)); -} +MACHINE_CONFIG_END //------------------------------------------------- diff --git a/src/devices/machine/ldv1000.h b/src/devices/machine/ldv1000.h index 55516da36fe..661d0a44f0b 100644 --- a/src/devices/machine/ldv1000.h +++ b/src/devices/machine/ldv1000.h @@ -26,6 +26,10 @@ #define MCFG_LASERDISC_LDV1000_ADD(_tag) \ MCFG_DEVICE_ADD(_tag, PIONEER_LDV1000, 0) +#define MCFG_LASERDISC_LDV1000_COMMAND_STROBE_CB(_cb) \ + downcast<pioneer_ldv1000_device *>(device)->set_command_strobe_callback(DEVCB_##_cb); + + //************************************************************************** // GLOBAL VARIABLES @@ -49,7 +53,7 @@ public: // construction/destruction pioneer_ldv1000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - auto command_strobe_callback() { return m_command_strobe_cb.bind(); } + template <class cmd_strobe_cb> devcb_base &set_command_strobe_callback(cmd_strobe_cb &&latch) { return m_command_strobe_cb.set_callback(std::forward<cmd_strobe_cb>(latch)); } // input and output void data_w(uint8_t data); diff --git a/src/devices/machine/ldvp931.cpp b/src/devices/machine/ldvp931.cpp index 4bcb74e1b6a..7a688736a93 100644 --- a/src/devices/machine/ldvp931.cpp +++ b/src/devices/machine/ldvp931.cpp @@ -45,7 +45,7 @@ //************************************************************************** // devices -DEFINE_DEVICE_TYPE(PHILIPS_22VP931, philips_22vp931_device, "22vp931", "Philips 22VP931") +DEFINE_DEVICE_TYPE(PHILLIPS_22VP931, phillips_22vp931_device, "22vp931", "Phillips 22VP931") @@ -53,12 +53,12 @@ DEFINE_DEVICE_TYPE(PHILIPS_22VP931, philips_22vp931_device, "22vp931", "Philips // 22VP931 ROM AND MACHINE INTERFACES //************************************************************************** -void philips_22vp931_device::vp931_portmap(address_map &map) +void phillips_22vp931_device::vp931_portmap(address_map &map) { - map(0x00, 0x00).mirror(0xcf).rw(FUNC(philips_22vp931_device::i8049_keypad_r), FUNC(philips_22vp931_device::i8049_output0_w)); - map(0x10, 0x10).mirror(0xcf).rw(FUNC(philips_22vp931_device::i8049_unknown_r), FUNC(philips_22vp931_device::i8049_output1_w)); - map(0x20, 0x20).mirror(0xcf).rw(FUNC(philips_22vp931_device::i8049_datic_r), FUNC(philips_22vp931_device::i8049_lcd_w)); - map(0x30, 0x30).mirror(0xcf).rw(FUNC(philips_22vp931_device::i8049_from_controller_r), FUNC(philips_22vp931_device::i8049_to_controller_w)); + map(0x00, 0x00).mirror(0xcf).rw(FUNC(phillips_22vp931_device::i8049_keypad_r), FUNC(phillips_22vp931_device::i8049_output0_w)); + map(0x10, 0x10).mirror(0xcf).rw(FUNC(phillips_22vp931_device::i8049_unknown_r), FUNC(phillips_22vp931_device::i8049_output1_w)); + map(0x20, 0x20).mirror(0xcf).rw(FUNC(phillips_22vp931_device::i8049_datic_r), FUNC(phillips_22vp931_device::i8049_lcd_w)); + map(0x30, 0x30).mirror(0xcf).rw(FUNC(phillips_22vp931_device::i8049_from_controller_r), FUNC(phillips_22vp931_device::i8049_to_controller_w)); } @@ -70,15 +70,15 @@ ROM_END //************************************************************************** -// PHILIPS 22VP931 IMPLEMENTATION +// PHILLIPS 22VP931 IMPLEMENTATION //************************************************************************** //------------------------------------------------- -// philips_22vp931_device - constructor +// phillips_22vp931_device - constructor //------------------------------------------------- -philips_22vp931_device::philips_22vp931_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : laserdisc_device(mconfig, PHILIPS_22VP931, tag, owner, clock), +phillips_22vp931_device::phillips_22vp931_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : laserdisc_device(mconfig, PHILLIPS_22VP931, tag, owner, clock), m_i8049_cpu(*this, "vp931"), m_tracktimer(nullptr), m_i8049_out0(0), @@ -103,7 +103,7 @@ philips_22vp931_device::philips_22vp931_device(const machine_config &mconfig, co // reset_w - write to the reset line //------------------------------------------------- -void philips_22vp931_device::reset_w(uint8_t data) +void phillips_22vp931_device::reset_w(uint8_t data) { // control the CPU state m_i8049_cpu->set_input_line(INPUT_LINE_RESET, data); @@ -119,7 +119,7 @@ void philips_22vp931_device::reset_w(uint8_t data) // 22VP931 //------------------------------------------------- -uint8_t philips_22vp931_device::data_r() +uint8_t phillips_22vp931_device::data_r() { // if data is pending, clear the pending flag and notify any callbacks if (m_tocontroller_pending) @@ -139,7 +139,7 @@ uint8_t philips_22vp931_device::data_r() // device_start - device initialization //------------------------------------------------- -void philips_22vp931_device::device_start() +void phillips_22vp931_device::device_start() { // pass through to the parent laserdisc_device::device_start(); @@ -153,7 +153,7 @@ void philips_22vp931_device::device_start() // device_reset - device reset //------------------------------------------------- -void philips_22vp931_device::device_reset() +void phillips_22vp931_device::device_reset() { // pass through to the parent laserdisc_device::device_reset(); @@ -185,7 +185,7 @@ void philips_22vp931_device::device_reset() // device //------------------------------------------------- -void philips_22vp931_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +void phillips_22vp931_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { switch (id) { @@ -276,7 +276,7 @@ void philips_22vp931_device::device_timer(emu_timer &timer, device_timer_id id, // ROM region definitions //------------------------------------------------- -const tiny_rom_entry *philips_22vp931_device::device_rom_region() const +const tiny_rom_entry *phillips_22vp931_device::device_rom_region() const { return ROM_NAME(vp931); } @@ -286,16 +286,16 @@ const tiny_rom_entry *philips_22vp931_device::device_rom_region() const // device_add_mconfig - add device configuration //------------------------------------------------- -void philips_22vp931_device::device_add_mconfig(machine_config &config) +void phillips_22vp931_device::device_add_mconfig(machine_config &config) { I8049(config, m_i8049_cpu, XTAL(11'000'000)); - m_i8049_cpu->set_addrmap(AS_IO, &philips_22vp931_device::vp931_portmap); - m_i8049_cpu->p1_in_cb().set(FUNC(philips_22vp931_device::i8049_port1_r)); - m_i8049_cpu->p1_out_cb().set(FUNC(philips_22vp931_device::i8049_port1_w)); - m_i8049_cpu->p2_in_cb().set(FUNC(philips_22vp931_device::i8049_port2_r)); - m_i8049_cpu->p2_out_cb().set(FUNC(philips_22vp931_device::i8049_port2_w)); - m_i8049_cpu->t0_in_cb().set(FUNC(philips_22vp931_device::i8049_t0_r)); - m_i8049_cpu->t1_in_cb().set(FUNC(philips_22vp931_device::i8049_t1_r)); + m_i8049_cpu->set_addrmap(AS_IO, &phillips_22vp931_device::vp931_portmap); + m_i8049_cpu->p1_in_cb().set(FUNC(phillips_22vp931_device::i8049_port1_r)); + m_i8049_cpu->p1_out_cb().set(FUNC(phillips_22vp931_device::i8049_port1_w)); + m_i8049_cpu->p2_in_cb().set(FUNC(phillips_22vp931_device::i8049_port2_r)); + m_i8049_cpu->p2_out_cb().set(FUNC(phillips_22vp931_device::i8049_port2_w)); + m_i8049_cpu->t0_in_cb().set(FUNC(phillips_22vp931_device::i8049_t0_r)); + m_i8049_cpu->t1_in_cb().set(FUNC(phillips_22vp931_device::i8049_t1_r)); } @@ -304,7 +304,7 @@ void philips_22vp931_device::device_add_mconfig(machine_config &config) // start of the blanking period //------------------------------------------------- -void philips_22vp931_device::player_vsync(const vbi_metadata &vbi, int fieldnum, const attotime &curtime) +void phillips_22vp931_device::player_vsync(const vbi_metadata &vbi, int fieldnum, const attotime &curtime) { // reset our command counter (debugging only) m_cmdcount = 0; @@ -320,7 +320,7 @@ void philips_22vp931_device::player_vsync(const vbi_metadata &vbi, int fieldnum, // the first visible line of the frame //------------------------------------------------- -int32_t philips_22vp931_device::player_update(const vbi_metadata &vbi, int fieldnum, const attotime &curtime) +int32_t phillips_22vp931_device::player_update(const vbi_metadata &vbi, int fieldnum, const attotime &curtime) { // set the first VBI timer to go at the start of line 16 timer_set(screen().time_until_pos(16*2), TID_VBI_DATA_FETCH, LASERDISC_CODE_LINE16 << 2); @@ -335,7 +335,7 @@ int32_t philips_22vp931_device::player_update(const vbi_metadata &vbi, int field // and other bits //------------------------------------------------- -WRITE8_MEMBER( philips_22vp931_device::i8049_output0_w ) +WRITE8_MEMBER( phillips_22vp931_device::i8049_output0_w ) { /* $80 = n/c @@ -374,7 +374,7 @@ WRITE8_MEMBER( philips_22vp931_device::i8049_output0_w ) // i8049_output1_w - controls scanning behaviors //------------------------------------------------- -WRITE8_MEMBER( philips_22vp931_device::i8049_output1_w ) +WRITE8_MEMBER( phillips_22vp931_device::i8049_output1_w ) { /* $80 = n/c @@ -418,7 +418,7 @@ WRITE8_MEMBER( philips_22vp931_device::i8049_output1_w ) // i8049_lcd_w - vestigial LCD frame display //------------------------------------------------- -WRITE8_MEMBER( philips_22vp931_device::i8049_lcd_w ) +WRITE8_MEMBER( phillips_22vp931_device::i8049_lcd_w ) { /* Frame number is written as 5 digits here; however, it is not actually @@ -431,7 +431,7 @@ WRITE8_MEMBER( philips_22vp931_device::i8049_lcd_w ) // i8049_unknown_r - unknown input port //------------------------------------------------- -READ8_MEMBER( philips_22vp931_device::i8049_unknown_r ) +READ8_MEMBER( phillips_22vp931_device::i8049_unknown_r ) { // only bit $80 is checked and its effects are minor return 0x00; @@ -443,7 +443,7 @@ READ8_MEMBER( philips_22vp931_device::i8049_unknown_r ) // controls //------------------------------------------------- -READ8_MEMBER( philips_22vp931_device::i8049_keypad_r ) +READ8_MEMBER( phillips_22vp931_device::i8049_keypad_r ) { /* From the code, this is apparently a vestigial keypad with basic controls: @@ -465,7 +465,7 @@ READ8_MEMBER( philips_22vp931_device::i8049_keypad_r ) // DATIC circuit //------------------------------------------------- -READ8_MEMBER( philips_22vp931_device::i8049_datic_r ) +READ8_MEMBER( phillips_22vp931_device::i8049_datic_r ) { return m_daticval; } @@ -476,7 +476,7 @@ READ8_MEMBER( philips_22vp931_device::i8049_datic_r ) // external controller wrote //------------------------------------------------- -READ8_MEMBER( philips_22vp931_device::i8049_from_controller_r ) +READ8_MEMBER( phillips_22vp931_device::i8049_from_controller_r ) { // clear the pending flag and return the data m_fromcontroller_pending = false; @@ -489,7 +489,7 @@ READ8_MEMBER( philips_22vp931_device::i8049_from_controller_r ) // the external controller //------------------------------------------------- -WRITE8_MEMBER( philips_22vp931_device::i8049_to_controller_w ) +WRITE8_MEMBER( phillips_22vp931_device::i8049_to_controller_w ) { // set the pending flag and stash the data m_tocontroller_pending = true; @@ -508,7 +508,7 @@ WRITE8_MEMBER( philips_22vp931_device::i8049_to_controller_w ) // i8049_port1_r - read the 8048 I/O port 1 //------------------------------------------------- -READ8_MEMBER( philips_22vp931_device::i8049_port1_r ) +READ8_MEMBER( phillips_22vp931_device::i8049_port1_r ) { /* $80 = P17 = (in) unsure @@ -527,7 +527,7 @@ READ8_MEMBER( philips_22vp931_device::i8049_port1_r ) // i8049_port1_w - write the 8048 I/O port 1 //------------------------------------------------- -WRITE8_MEMBER( philips_22vp931_device::i8049_port1_w ) +WRITE8_MEMBER( phillips_22vp931_device::i8049_port1_w ) { /* $10 = P14 = (out) D104 -> /SPEED @@ -598,7 +598,7 @@ WRITE8_MEMBER( philips_22vp931_device::i8049_port1_w ) // i8049_port2_r - read from the 8048 I/O port 2 //------------------------------------------------- -READ8_MEMBER( philips_22vp931_device::i8049_port2_r ) +READ8_MEMBER( phillips_22vp931_device::i8049_port2_r ) { /* $80 = P27 = (in) set/reset latch; set by FOC LS, reset by IGR @@ -619,7 +619,7 @@ READ8_MEMBER( philips_22vp931_device::i8049_port2_r ) // i8049_port2_w - write the 8048 I/O port 2 //------------------------------------------------- -WRITE8_MEMBER( philips_22vp931_device::i8049_port2_w ) +WRITE8_MEMBER( phillips_22vp931_device::i8049_port2_w ) { /* $40 = P26 = (out) cleared while data is sent back & forth; set afterwards @@ -633,7 +633,7 @@ WRITE8_MEMBER( philips_22vp931_device::i8049_port2_w ) // connected to the DATIC's data strobe line //------------------------------------------------- -READ_LINE_MEMBER( philips_22vp931_device::i8049_t0_r ) +READ_LINE_MEMBER( phillips_22vp931_device::i8049_t0_r ) { return m_datastrobe; } @@ -645,7 +645,7 @@ READ_LINE_MEMBER( philips_22vp931_device::i8049_t0_r ) // to count the number of tracks advanced //------------------------------------------------- -READ_LINE_MEMBER( philips_22vp931_device::i8049_t1_r ) +READ_LINE_MEMBER( phillips_22vp931_device::i8049_t1_r ) { return m_trackstate; } diff --git a/src/devices/machine/ldvp931.h b/src/devices/machine/ldvp931.h index fd69f52429e..0bf2e263558 100644 --- a/src/devices/machine/ldvp931.h +++ b/src/devices/machine/ldvp931.h @@ -18,11 +18,19 @@ //************************************************************************** +// DEVICE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_LASERDISC_22VP931_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, PHILLIPS_22VP931, 0) + + +//************************************************************************** // GLOBAL VARIABLES //************************************************************************** // device type definition -DECLARE_DEVICE_TYPE(PHILIPS_22VP931, philips_22vp931_device) +DECLARE_DEVICE_TYPE(PHILLIPS_22VP931, phillips_22vp931_device) @@ -30,17 +38,17 @@ DECLARE_DEVICE_TYPE(PHILIPS_22VP931, philips_22vp931_device) // TYPE DEFINITIONS //************************************************************************** -// ======================> philips_22vp931_device +// ======================> phillips_22vp931_device // base _22vp931 class -class philips_22vp931_device : public laserdisc_device +class phillips_22vp931_device : public laserdisc_device { public: // types - typedef delegate<void (philips_22vp931_device &, int)> data_ready_delegate; + typedef delegate<void (phillips_22vp931_device &, int)> data_ready_delegate; // construction/destruction - philips_22vp931_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + phillips_22vp931_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // input and output void data_w(uint8_t data) { synchronize(TID_DEFERRED_DATA, data); } diff --git a/src/devices/machine/legscsi.h b/src/devices/machine/legscsi.h index 229580bc0bf..fee1b333061 100644 --- a/src/devices/machine/legscsi.h +++ b/src/devices/machine/legscsi.h @@ -7,6 +7,8 @@ #include "bus/scsi/scsihle.h" +#define MCFG_LEGACY_SCSI_PORT(_tag) \ + downcast<legacy_scsi_host_adapter &>(*device).set_scsi_port(_tag); class legacy_scsi_host_adapter : public device_t { diff --git a/src/devices/machine/mb8421.cpp b/src/devices/machine/mb8421.cpp index e6344843f92..a5b08f5ea90 100644 --- a/src/devices/machine/mb8421.cpp +++ b/src/devices/machine/mb8421.cpp @@ -129,14 +129,14 @@ void mb8421_master_device::update_intr(offs_t offset) // (write to 7FF asserts INTR) //------------------------------------------------- -void mb8421_device::left_w(offs_t offset, u8 data) +WRITE8_MEMBER(mb8421_device::left_w) { offset &= 0x7ff; m_ram[offset] = data; update_intr<read_or_write::WRITE, false>(offset); } -void mb8421_mb8431_16_device::left_w(offs_t offset, u16 data, u16 mem_mask) +WRITE16_MEMBER(mb8421_mb8431_16_device::left_w) { offset &= 0x7ff; COMBINE_DATA(&m_ram[offset]); @@ -148,14 +148,14 @@ void mb8421_mb8431_16_device::left_w(offs_t offset, u16 data, u16 mem_mask) // (read from 7FE acknowledges INTL) //------------------------------------------------- -u8 mb8421_device::left_r(offs_t offset) +READ8_MEMBER(mb8421_device::left_r) { offset &= 0x7ff; update_intr<read_or_write::READ, false>(offset); return m_ram[offset]; } -u16 mb8421_mb8431_16_device::left_r(offs_t offset, u16 mem_mask) +READ16_MEMBER(mb8421_mb8431_16_device::left_r) { offset &= 0x7ff; update_intr<read_or_write::READ, false>(offset); @@ -167,14 +167,14 @@ u16 mb8421_mb8431_16_device::left_r(offs_t offset, u16 mem_mask) // (write to 7FE asserts INTL) //------------------------------------------------- -void mb8421_device::right_w(offs_t offset, u8 data) +WRITE8_MEMBER(mb8421_device::right_w) { offset &= 0x7ff; m_ram[offset] = data; update_intr<read_or_write::WRITE, true>(offset); } -void mb8421_mb8431_16_device::right_w(offs_t offset, u16 data, u16 mem_mask) +WRITE16_MEMBER(mb8421_mb8431_16_device::right_w) { offset &= 0x7ff; COMBINE_DATA(&m_ram[offset]); @@ -186,14 +186,14 @@ void mb8421_mb8431_16_device::right_w(offs_t offset, u16 data, u16 mem_mask) // (read from 7FF acknowledges INTR) //------------------------------------------------- -u8 mb8421_device::right_r(offs_t offset) +READ8_MEMBER(mb8421_device::right_r) { offset &= 0x7ff; update_intr<read_or_write::READ, true>(offset); return m_ram[offset]; } -u16 mb8421_mb8431_16_device::right_r(offs_t offset, u16 mem_mask) +READ16_MEMBER(mb8421_mb8431_16_device::right_r) { offset &= 0x7ff; update_intr<read_or_write::READ, true>(offset); diff --git a/src/devices/machine/mb8421.h b/src/devices/machine/mb8421.h index 00e8f8d207f..4ef0a010c9b 100644 --- a/src/devices/machine/mb8421.h +++ b/src/devices/machine/mb8421.h @@ -108,10 +108,10 @@ public: u8 peek(offs_t offset) const { return m_ram[offset & 0x7ff]; } - void left_w(offs_t offset, u8 data); - u8 left_r(offs_t offset); - void right_w(offs_t offset, u8 data); - u8 right_r(offs_t offset); + DECLARE_WRITE8_MEMBER(left_w); + DECLARE_READ8_MEMBER(left_r); + DECLARE_WRITE8_MEMBER(right_w); + DECLARE_READ8_MEMBER(right_r); protected: mb8421_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); @@ -140,10 +140,10 @@ public: u16 peek(offs_t offset) const { return m_ram[offset & 0x7ff]; } - void left_w(offs_t offset, u16 data, u16 mem_mask = 0xffff); - u16 left_r(offs_t offset, u16 mem_mask = 0xffff); - void right_w(offs_t offset, u16 data, u16 mem_mask = 0xffff); - u16 right_r(offs_t offset, u16 mem_mask = 0xffff); + DECLARE_WRITE16_MEMBER(left_w); + DECLARE_READ16_MEMBER(left_r); + DECLARE_WRITE16_MEMBER(right_w); + DECLARE_READ16_MEMBER(right_r); protected: // device-level overrides diff --git a/src/devices/machine/mc146818.cpp b/src/devices/machine/mc146818.cpp index 1259e1502ca..990d6f3ec35 100644 --- a/src/devices/machine/mc146818.cpp +++ b/src/devices/machine/mc146818.cpp @@ -510,7 +510,7 @@ void mc146818_device::update_irq() // read - I/O handler for reading //------------------------------------------------- -uint8_t mc146818_device::read(offs_t offset) +READ8_MEMBER( mc146818_device::read ) { uint8_t data = 0; switch (offset) @@ -520,14 +520,14 @@ uint8_t mc146818_device::read(offs_t offset) break; case 1: - data = read_direct(m_index); + data = read_direct(space, m_index); break; } return data; } -uint8_t mc146818_device::read_direct(offs_t offset) +READ8_MEMBER( mc146818_device::read_direct ) { uint8_t data = 0; @@ -569,7 +569,7 @@ uint8_t mc146818_device::read_direct(offs_t offset) // write - I/O handler for writing //------------------------------------------------- -void mc146818_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( mc146818_device::write ) { switch (offset) { @@ -578,12 +578,12 @@ void mc146818_device::write(offs_t offset, uint8_t data) break; case 1: - write_direct(m_index, data); + write_direct(space, m_index, data); break; } } -void mc146818_device::write_direct(offs_t offset, uint8_t data) +WRITE8_MEMBER( mc146818_device::write_direct ) { LOG("mc146818_port_w(): offset=0x%02x data=0x%02x\n", offset, data); diff --git a/src/devices/machine/mc146818.h b/src/devices/machine/mc146818.h index b1431964dde..499698a84cd 100644 --- a/src/devices/machine/mc146818.h +++ b/src/devices/machine/mc146818.h @@ -39,12 +39,12 @@ public: void set_binary_year(int bin) { m_binyear = bin; } // read/write access - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); // direct-mapped read/write access - uint8_t read_direct(offs_t offset); - void write_direct(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read_direct ); + DECLARE_WRITE8_MEMBER( write_direct ); protected: mc146818_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); diff --git a/src/devices/machine/mc6843.h b/src/devices/machine/mc6843.h index 63052970edb..29f3b862bda 100644 --- a/src/devices/machine/mc6843.h +++ b/src/devices/machine/mc6843.h @@ -15,6 +15,8 @@ #include "imagedev/flopdrv.h" +#define MCFG_MC6843_IRQ_CALLBACK(_write) \ + downcast<mc6843_device &>(*device).set_irq_wr_callback(DEVCB_##_write); class mc6843_device : public device_t { diff --git a/src/devices/machine/mc6852.cpp b/src/devices/machine/mc6852.cpp index 6d5a9876153..d2021a450a2 100644 --- a/src/devices/machine/mc6852.cpp +++ b/src/devices/machine/mc6852.cpp @@ -147,7 +147,7 @@ void mc6852_device::rcv_complete() // read - //------------------------------------------------- -uint8_t mc6852_device::read(offs_t offset) +READ8_MEMBER( mc6852_device::read ) { uint8_t data = 0; @@ -156,8 +156,7 @@ uint8_t mc6852_device::read(offs_t offset) if (m_rx_fifo.size() > 0) { data = m_rx_fifo.front(); - if (!machine().side_effects_disabled()) - m_rx_fifo.pop(); + m_rx_fifo.pop(); } } else @@ -173,7 +172,7 @@ uint8_t mc6852_device::read(offs_t offset) // write - //------------------------------------------------- -void mc6852_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( mc6852_device::write ) { if (BIT(offset, 0)) { diff --git a/src/devices/machine/mc6852.h b/src/devices/machine/mc6852.h index 3f05182ed6f..798529db3ef 100644 --- a/src/devices/machine/mc6852.h +++ b/src/devices/machine/mc6852.h @@ -32,6 +32,30 @@ //************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MC6852_RX_CLOCK(_clock) \ + downcast<mc6852_device &>(*device).set_rx_clock(_clock); + +#define MCFG_MC6852_TX_CLOCK(_clock) \ + downcast<mc6852_device &>(*device).set_tx_clock(_clock); + +#define MCFG_MC6852_TX_DATA_CALLBACK(_write) \ + downcast<mc6852_device &>(*device).set_tx_data_wr_callback(DEVCB_##_write); + +#define MCFG_MC6852_IRQ_CALLBACK(_write) \ + downcast<mc6852_device &>(*device).set_irq_wr_callback(DEVCB_##_write); + +#define MCFG_MC6852_SM_DTR_CALLBACK(_write) \ + downcast<mc6852_device &>(*device).set_sm_dtr_wr_callback(DEVCB_##_write); + +#define MCFG_MC6852_TUF_CALLBACK(_write) \ + downcast<mc6852_device &>(*device).set_tuf_wr_callback(DEVCB_##_write); + + + +//************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -46,14 +70,18 @@ public: void set_rx_clock(int clock) { m_rx_clock = clock; } void set_tx_clock(int clock) { m_tx_clock = clock; } + template <class Object> devcb_base &set_tx_data_wr_callback(Object &&cb) { return m_write_tx_data.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_irq_wr_callback(Object &&cb) { return m_write_irq.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_sm_dtr_wr_callback(Object &&cb) { return m_write_sm_dtr.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_tuf_wr_callback(Object &&cb) { return m_write_tuf.set_callback(std::forward<Object>(cb)); } auto tx_data_callback() { return m_write_tx_data.bind(); } auto irq_callback() { return m_write_irq.bind(); } auto sm_dtr_callback() { return m_write_sm_dtr.bind(); } auto tuf_callback() { return m_write_tuf.bind(); } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); DECLARE_WRITE_LINE_MEMBER( rx_data_w ) { device_serial_interface::rx_w(state); } DECLARE_WRITE_LINE_MEMBER( rx_clk_w ) { rx_clock_w(state); } diff --git a/src/devices/machine/mc6854.cpp b/src/devices/machine/mc6854.cpp index acaa74b0cf9..43e09eba5d2 100644 --- a/src/devices/machine/mc6854.cpp +++ b/src/devices/machine/mc6854.cpp @@ -809,7 +809,7 @@ void mc6854_device::update_sr1( ) -uint8_t mc6854_device::read(offs_t offset) +READ8_MEMBER( mc6854_device::read ) { switch ( offset ) { @@ -850,7 +850,7 @@ uint8_t mc6854_device::read(offs_t offset) -void mc6854_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( mc6854_device::write ) { switch ( offset ) { diff --git a/src/devices/machine/mc6854.h b/src/devices/machine/mc6854.h index 0f90544336b..99f09f5d3a7 100644 --- a/src/devices/machine/mc6854.h +++ b/src/devices/machine/mc6854.h @@ -40,8 +40,8 @@ public: } /* interface to CPU via address/data bus*/ - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); /* low-level, bit-based interface */ DECLARE_WRITE_LINE_MEMBER( set_rx ); diff --git a/src/devices/machine/mc68681.cpp b/src/devices/machine/mc68681.cpp index a3a3b480979..b60567aa3f7 100644 --- a/src/devices/machine/mc68681.cpp +++ b/src/devices/machine/mc68681.cpp @@ -268,25 +268,22 @@ void xr68c681_device::device_reset() m_XTXA = m_XRXA = m_XTXB = m_XRXB = false; } -void duart_base_device::device_add_mconfig(machine_config &config) -{ - DUART_CHANNEL(config, CHANA_TAG, 0); - DUART_CHANNEL(config, CHANB_TAG, 0); -} - -void sc28c94_device::device_add_mconfig(machine_config &config) -{ - DUART_CHANNEL(config, CHANA_TAG, 0); - DUART_CHANNEL(config, CHANB_TAG, 0); - DUART_CHANNEL(config, CHANC_TAG, 0); - DUART_CHANNEL(config, CHAND_TAG, 0); -} - -void mc68340_duart_device::device_add_mconfig(machine_config &config) -{ - DUART_CHANNEL(config, CHANA_TAG, 0); - DUART_CHANNEL(config, CHANB_TAG, 0); -} +MACHINE_CONFIG_START(duart_base_device::device_add_mconfig) + MCFG_DEVICE_ADD(CHANA_TAG, DUART_CHANNEL, 0) + MCFG_DEVICE_ADD(CHANB_TAG, DUART_CHANNEL, 0) +MACHINE_CONFIG_END + +MACHINE_CONFIG_START(sc28c94_device::device_add_mconfig) + MCFG_DEVICE_ADD(CHANA_TAG, DUART_CHANNEL, 0) + MCFG_DEVICE_ADD(CHANB_TAG, DUART_CHANNEL, 0) + MCFG_DEVICE_ADD(CHANC_TAG, DUART_CHANNEL, 0) + MCFG_DEVICE_ADD(CHAND_TAG, DUART_CHANNEL, 0) +MACHINE_CONFIG_END + +MACHINE_CONFIG_START(mc68340_duart_device::device_add_mconfig) + MCFG_DEVICE_ADD(CHANA_TAG, DUART_CHANNEL, 0) + MCFG_DEVICE_ADD(CHANB_TAG, DUART_CHANNEL, 0) +MACHINE_CONFIG_END void duart_base_device::update_interrupts() { diff --git a/src/devices/machine/mc68681.h b/src/devices/machine/mc68681.h index 50e5cdd1489..ea4fd63e3af 100644 --- a/src/devices/machine/mc68681.h +++ b/src/devices/machine/mc68681.h @@ -7,6 +7,32 @@ #include "diserial.h" +#define MCFG_MC68681_IRQ_CALLBACK(_cb) \ + downcast<duart_base_device &>(*device).set_irq_cb(DEVCB_##_cb); + +#define MCFG_MC68681_A_TX_CALLBACK(_cb) \ + downcast<duart_base_device &>(*device).set_a_tx_cb(DEVCB_##_cb); + +#define MCFG_MC68681_B_TX_CALLBACK(_cb) \ + downcast<duart_base_device &>(*device).set_b_tx_cb(DEVCB_##_cb); + +// deprecated: use ipX_w() instead +#define MCFG_MC68681_INPORT_CALLBACK(_cb) \ + downcast<duart_base_device &>(*device).set_inport_cb(DEVCB_##_cb); + +#define MCFG_MC68681_OUTPORT_CALLBACK(_cb) \ + downcast<duart_base_device &>(*device).set_outport_cb(DEVCB_##_cb); + +#define MCFG_MC68681_SET_EXTERNAL_CLOCKS(_a, _b, _c, _d) \ + downcast<duart_base_device &>(*device).set_clocks(_a, _b, _c, _d); + +// SC28C94 specific callbacks +#define MCFG_SC28C94_C_TX_CALLBACK(_cb) \ + downcast<sc28c94_device &>(*device).set_c_tx_cb(DEVCB_##_cb); + +#define MCFG_SC28C94_D_TX_CALLBACK(_cb) \ + downcast<sc28c94_device &>(*device).set_d_tx_cb(DEVCB_##_cb); + #define MC68681_RX_FIFO_SIZE 3 // forward declaration @@ -101,10 +127,15 @@ public: DECLARE_WRITE_LINE_MEMBER(rx_a_w) { m_chanA->device_serial_interface::rx_w((uint8_t)state); } DECLARE_WRITE_LINE_MEMBER(rx_b_w) { m_chanB->device_serial_interface::rx_w((uint8_t)state); } + template <class Object> devcb_base &set_irq_cb(Object &&cb) { return write_irq.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_a_tx_cb(Object &&cb) { return write_a_tx.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_b_tx_cb(Object &&cb) { return write_b_tx.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_inport_cb(Object &&cb) { return read_inport.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_outport_cb(Object &&cb) { return write_outport.set_callback(std::forward<Object>(cb)); } auto irq_cb() { return write_irq.bind(); } auto a_tx_cb() { return write_a_tx.bind(); } auto b_tx_cb() { return write_b_tx.bind(); } - auto inport_cb() { return read_inport.bind(); } // deprecated: use ipX_w() instead + auto inport_cb() { return read_inport.bind(); } auto outport_cb() { return write_outport.bind(); } // new-style push handlers for input port bits @@ -216,8 +247,8 @@ class sc28c94_device : public duart_base_device public: sc28c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - auto c_tx_cb() { return write_c_tx.bind(); } - auto d_tx_cb() { return write_d_tx.bind(); } + template <class Object> devcb_base &set_c_tx_cb(Object &&cb) { return write_c_tx.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_d_tx_cb(Object &&cb) { return write_d_tx.set_callback(std::forward<Object>(cb)); } DECLARE_WRITE_LINE_MEMBER(rx_c_w) { m_chanC->device_serial_interface::rx_w((uint8_t)state); } DECLARE_WRITE_LINE_MEMBER(rx_d_w) { m_chanD->device_serial_interface::rx_w((uint8_t)state); } diff --git a/src/devices/machine/mccs1850.h b/src/devices/machine/mccs1850.h index 62b7f5d5afc..bd7771bc6a0 100644 --- a/src/devices/machine/mccs1850.h +++ b/src/devices/machine/mccs1850.h @@ -25,6 +25,22 @@ #include "dirtc.h" + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MCCS1850_INT_CALLBACK(_write) \ + downcast<mccs1850_device &>(*device).set_int_wr_callback(DEVCB_##_write); + +#define MCFG_MCCS1850_PSE_CALLBACK(_write) \ + downcast<mccs1850_device &>(*device).set_pse_wr_callback(DEVCB_##_write); + +#define MCFG_MCCS1850_NUC_CALLBACK(_write) \ + downcast<mccs1850_device &>(*device).set_nuc_wr_callback(DEVCB_##_write); + + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -39,9 +55,9 @@ public: // construction/destruction mccs1850_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - auto int_wr_callback() { return int_cb.bind(); } - auto pse_wr_callback() { return pse_cb.bind(); } - auto nuc_wr_callback() { return nuc_cb.bind(); } + template <class Object> devcb_base &set_int_wr_callback(Object &&cb) { return int_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_pse_wr_callback(Object &&cb) { return pse_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_nuc_wr_callback(Object &&cb) { return nuc_cb.set_callback(std::forward<Object>(cb)); } DECLARE_WRITE_LINE_MEMBER( ce_w ); DECLARE_WRITE_LINE_MEMBER( sck_w ); diff --git a/src/devices/machine/mcf5206e.cpp b/src/devices/machine/mcf5206e.cpp index cea38ca7f0f..085afac92ec 100644 --- a/src/devices/machine/mcf5206e.cpp +++ b/src/devices/machine/mcf5206e.cpp @@ -826,7 +826,7 @@ DEFINE_DEVICE_TYPE(MCF5206E_PERIPHERAL, mcf5206e_peripheral_device, "mcf5206e_pe mcf5206e_peripheral_device::mcf5206e_peripheral_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, MCF5206E_PERIPHERAL, tag, owner, clock), device_memory_interface(mconfig, *this), - m_space_config("coldfire_regs", ENDIANNESS_BIG, 32,10, 0, address_map_constructor(FUNC(mcf5206e_peripheral_device::coldfire_regs_map), this)) + m_space_config("coldfire_regs", ENDIANNESS_BIG, 32,10, 0, address_map_constructor(), address_map_constructor(FUNC(mcf5206e_peripheral_device::coldfire_regs_map), this)) { } diff --git a/src/devices/machine/mcf5206e.h b/src/devices/machine/mcf5206e.h index a910849a25d..3bf54bbefd5 100644 --- a/src/devices/machine/mcf5206e.h +++ b/src/devices/machine/mcf5206e.h @@ -12,6 +12,15 @@ #pragma once + + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define MCFG_MCF5206E_PERIPHERAL_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, MCF5206E_PERIPHERAL, 0) + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ diff --git a/src/devices/machine/meters.h b/src/devices/machine/meters.h index c9a11790931..1a349f82485 100644 --- a/src/devices/machine/meters.h +++ b/src/devices/machine/meters.h @@ -15,6 +15,9 @@ #pragma once +#define MCFG_METERS_NUMBER(_number) \ + downcast<meters_device &>(*device).set_number_meters(_number); + class meters_device : public device_t { public: @@ -24,7 +27,7 @@ public: meters_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - void set_number(int number) { m_number_mtr = number; } + void set_number_meters(int number) { m_number_mtr = number; } int update(int id, int state); int GetActivity(int id); diff --git a/src/devices/machine/microtch.h b/src/devices/machine/microtch.h index 0cb486aa3f1..592b0a669da 100644 --- a/src/devices/machine/microtch.h +++ b/src/devices/machine/microtch.h @@ -13,14 +13,15 @@ class microtouch_device : { public: microtouch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template <class Object> devcb_base &set_stx_callback(Object &&cb) { return m_out_stx_func.set_callback(std::forward<Object>(cb)); } auto stx() { return m_out_stx_func.bind(); } virtual ioport_constructor device_input_ports() const override; DECLARE_WRITE_LINE_MEMBER(rx) { device_serial_interface::rx_w(state); } DECLARE_INPUT_CHANGED_MEMBER(touch); - typedef device_delegate<int (int *, int *)> touch_cb; - template <typename... T> void set_touch_callback(T &&... args) { m_out_touch_cb = touch_cb(std::forward<T>(args)...); } + typedef delegate<int (int *, int *)> touch_cb; + template <typename Object> void set_touch_callback(Object &&cb) { m_out_touch_cb = std::forward<Object>(cb); } protected: virtual void device_start() override; @@ -72,4 +73,11 @@ private: DECLARE_DEVICE_TYPE(MICROTOUCH, microtouch_device) +#define MCFG_MICROTOUCH_ADD(_tag, _clock, _devcb) \ + MCFG_DEVICE_ADD(_tag, MICROTOUCH, _clock) \ + downcast<microtouch_device &>(*device).set_stx_callback(DEVCB_##_devcb); + +#define MCFG_MICROTOUCH_TOUCH_CB(_class, _touch_cb) \ + downcast<microtouch_device &>(*device).set_touch_callback(microtouch_device::touch_cb(&_class::_touch_cb, this)); + #endif // MAME_MACHINE_MICROTCH_H diff --git a/src/devices/machine/mm5740.h b/src/devices/machine/mm5740.h index 1896f568e4c..e28fbdc0956 100644 --- a/src/devices/machine/mm5740.h +++ b/src/devices/machine/mm5740.h @@ -80,6 +80,23 @@ Vgg 18 -12V //************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MM5740_MATRIX_X1(_cb) downcast<mm5740_device &>(*device).set_x_cb<0>(DEVCB_##_cb); +#define MCFG_MM5740_MATRIX_X2(_cb) downcast<mm5740_device &>(*device).set_x_cb<1>(DEVCB_##_cb); +#define MCFG_MM5740_MATRIX_X3(_cb) downcast<mm5740_device &>(*device).set_x_cb<2>(DEVCB_##_cb); +#define MCFG_MM5740_MATRIX_X4(_cb) downcast<mm5740_device &>(*device).set_x_cb<3>(DEVCB_##_cb); +#define MCFG_MM5740_MATRIX_X5(_cb) downcast<mm5740_device &>(*device).set_x_cb<4>(DEVCB_##_cb); +#define MCFG_MM5740_MATRIX_X6(_cb) downcast<mm5740_device &>(*device).set_x_cb<5>(DEVCB_##_cb); +#define MCFG_MM5740_MATRIX_X7(_cb) downcast<mm5740_device &>(*device).set_x_cb<6>(DEVCB_##_cb); +#define MCFG_MM5740_MATRIX_X8(_cb) downcast<mm5740_device &>(*device).set_x_cb<7>(DEVCB_##_cb); +#define MCFG_MM5740_MATRIX_X9(_cb) downcast<mm5740_device &>(*device).set_x_cb<8>(DEVCB_##_cb); +#define MCFG_MM5740_SHIFT_CB(_cb) downcast<mm5740_device &>(*device).set_shift_cb(DEVCB_##_cb); +#define MCFG_MM5740_CONTROL_CB(_cb) downcast<mm5740_device &>(*device).set_control_cb(DEVCB_##_cb); +#define MCFG_MM5740_DATA_READY_CB(_cb) downcast<mm5740_device &>(*device).set_data_ready_cb(DEVCB_##_cb); + +//************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -94,11 +111,22 @@ public: // public interface uint16_t b_r(); - template <unsigned N> auto x_cb() { return m_read_x[N].bind(); } - auto shift_cb() { return m_read_shift.bind(); } - auto control_cb() { return m_read_control.bind(); } - auto data_ready_cb() { return m_write_data_ready.bind(); } - + template <unsigned N, typename Object> devcb_base &set_x_cb(Object &&cb) + { + return m_read_x[N].set_callback(std::forward<Object>(cb)); + } + template <typename Object> devcb_base &set_shift_cb(Object &&cb) + { + return m_read_shift.set_callback(std::forward<Object>(cb)); + } + template <typename Object> devcb_base &set_control_cb(Object &&cb) + { + return m_read_control.set_callback(std::forward<Object>(cb)); + } + template <typename Object> devcb_base &set_data_ready_cb(Object &&cb) + { + return m_write_data_ready.set_callback(std::forward<Object>(cb)); + } static uint32_t calc_effective_clock_key_debounce(uint32_t capacitance); protected: diff --git a/src/devices/machine/mm58167.cpp b/src/devices/machine/mm58167.cpp index f226590e9d2..22b49f4a7dd 100644 --- a/src/devices/machine/mm58167.cpp +++ b/src/devices/machine/mm58167.cpp @@ -180,7 +180,7 @@ void mm58167_device::update_rtc() m_milliseconds = (bcd_to_integer(m_regs[R_CNT_HUNDTENTHS]) * 10) + (bcd_to_integer(m_regs[R_CNT_MILLISECONDS] >> 4) % 10); } -uint8_t mm58167_device::read(offs_t offset) +READ8_MEMBER(mm58167_device::read) { // printf("read reg %x = %02x\n", offset, m_regs[offset]); @@ -196,7 +196,7 @@ uint8_t mm58167_device::read(offs_t offset) return m_regs[offset]; } -void mm58167_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(mm58167_device::write) { // printf("%02x to reg %x\n", data, offset); diff --git a/src/devices/machine/mm58167.h b/src/devices/machine/mm58167.h index c12b151b676..2c6bb5add34 100644 --- a/src/devices/machine/mm58167.h +++ b/src/devices/machine/mm58167.h @@ -15,6 +15,14 @@ //************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MM58167_IRQ_CALLBACK(_cb) \ + downcast<mm58167_device &>(*device).set_irq_cb(DEVCB_##_cb); + + +//************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -27,9 +35,10 @@ public: // construction/destruction mm58167_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); + template <class Object> devcb_base &set_irq_cb(Object &&wr) { return m_irq_w.set_callback(std::forward<Object>(wr)); } auto irq() { return m_irq_w.bind(); } devcb_write_line m_irq_w; diff --git a/src/devices/machine/mm58274c.cpp b/src/devices/machine/mm58274c.cpp index c7e7f49a78e..61904923326 100644 --- a/src/devices/machine/mm58274c.cpp +++ b/src/devices/machine/mm58274c.cpp @@ -152,7 +152,7 @@ attotime mm58274c_device::interrupt_period_table(int val) } } -uint8_t mm58274c_device::read(offs_t offset) +READ8_MEMBER( mm58274c_device::read ) { int reply; @@ -242,7 +242,7 @@ uint8_t mm58274c_device::read(offs_t offset) } -void mm58274c_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( mm58274c_device::write ) { offset &= 0xf; data &= 0xf; diff --git a/src/devices/machine/mm58274c.h b/src/devices/machine/mm58274c.h index c6fcbee3c46..cee2df48db9 100644 --- a/src/devices/machine/mm58274c.h +++ b/src/devices/machine/mm58274c.h @@ -16,8 +16,8 @@ public: void set_day1(int day) { m_day1 = day; } void set_mode_and_day(int mode, int day) { m_mode24 = mode; m_day1 = day; } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); TIMER_CALLBACK_MEMBER(rtc_increment_cb); TIMER_CALLBACK_MEMBER(rtc_interrupt_cb); @@ -30,7 +30,7 @@ protected: private: // internal state - // Initialization of the clock chip: + // Initializion the clock chip: // m_day1 must be set to a value from 0 (sunday), 1 (monday)... // to 6 (saturday) and is needed to correctly retrieve the // day-of-week from the host system clock. @@ -66,4 +66,15 @@ private: DECLARE_DEVICE_TYPE(MM58274C, mm58274c_device) + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define MCFG_MM58274C_MODE24(_mode) \ + downcast<mm58274c_device &>(*device).set_mode24(_mode); + +#define MCFG_MM58274C_DAY1(_day) \ + downcast<mm58274c_device &>(*device).set_day1(_day); + #endif // MAME_MACHINE_MM58274C_H diff --git a/src/devices/machine/mm74c922.h b/src/devices/machine/mm74c922.h index dce81dd40dc..bd448c2eb22 100644 --- a/src/devices/machine/mm74c922.h +++ b/src/devices/machine/mm74c922.h @@ -36,6 +36,38 @@ #pragma once + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MM74C922_OSC(_value) \ + downcast<mm74c922_device &>(*device).set_cap_osc(_value); + +#define MCFG_MM74C922_DEBOUNCE(_value) \ + downcast<mm74c922_device &>(*device).set_cap_debounce(_value); + +#define MCFG_MM74C922_DA_CALLBACK(_write) \ + downcast<mm74c922_device &>(*device).set_da_wr_callback(DEVCB_##_write); + +#define MCFG_MM74C922_X1_CALLBACK(_read) \ + downcast<mm74c922_device &>(*device).set_x1_rd_callback(DEVCB_##_read); + +#define MCFG_MM74C922_X2_CALLBACK(_read) \ + downcast<mm74c922_device &>(*device).set_x2_rd_callback(DEVCB_##_read); + +#define MCFG_MM74C922_X3_CALLBACK(_read) \ + downcast<mm74c922_device &>(*device).set_x3_rd_callback(DEVCB_##_read); + +#define MCFG_MM74C922_X4_CALLBACK(_read) \ + downcast<mm74c922_device &>(*device).set_x4_rd_callback(DEVCB_##_read); + +#define MCFG_MM74C922_X5_CALLBACK(_read) \ + downcast<mm74c922_device &>(*device).set_x5_rd_callback(DEVCB_##_read); + + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -51,12 +83,12 @@ public: void set_cap_osc(double value) { m_cap_osc = value; } void set_cap_debounce(double value) { m_cap_debounce = value; } - auto da_wr_callback() { return m_write_da.bind(); } - auto x1_rd_callback() { return m_read_x1.bind(); } - auto x2_rd_callback() { return m_read_x2.bind(); } - auto x3_rd_callback() { return m_read_x3.bind(); } - auto x4_rd_callback() { return m_read_x4.bind(); } - auto x5_rd_callback() { return m_read_x5.bind(); } + template <class Object> devcb_base &set_da_wr_callback(Object &&cb) { return m_write_da.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_x1_rd_callback(Object &&cb) { return m_read_x1.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_x2_rd_callback(Object &&cb) { return m_read_x2.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_x3_rd_callback(Object &&cb) { return m_read_x3.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_x4_rd_callback(Object &&cb) { return m_read_x4.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_x5_rd_callback(Object &&cb) { return m_read_x5.set_callback(std::forward<Object>(cb)); } uint8_t read(); diff --git a/src/devices/machine/mos6526.cpp b/src/devices/machine/mos6526.cpp index e1f40b109c1..9df653c4c5f 100644 --- a/src/devices/machine/mos6526.cpp +++ b/src/devices/machine/mos6526.cpp @@ -788,7 +788,7 @@ void mos6526_device::execute_run() // read - //------------------------------------------------- -uint8_t mos6526_device::read(offs_t offset) +READ8_MEMBER( mos6526_device::read ) { uint8_t data = 0; @@ -926,7 +926,7 @@ uint8_t mos6526_device::read(offs_t offset) return data; } -uint8_t mos8520_device::read(offs_t offset) +READ8_MEMBER( mos8520_device::read ) { uint8_t data; @@ -947,7 +947,7 @@ uint8_t mos8520_device::read(offs_t offset) break; default: - data = mos6526_device::read(offset); + data = mos6526_device::read(space, offset); } return data; @@ -957,7 +957,7 @@ uint8_t mos8520_device::read(offs_t offset) // write - //------------------------------------------------- -void mos6526_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( mos6526_device::write ) { switch (offset & 0x0f) { @@ -1099,12 +1099,12 @@ void mos6526_device::write(offs_t offset, uint8_t data) } } -void mos8520_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( mos8520_device::write ) { switch (offset & 0x0f) { default: - mos6526_device::write(offset, data); + mos6526_device::write(space, offset, data); break; case TOD_MIN: diff --git a/src/devices/machine/mos6526.h b/src/devices/machine/mos6526.h index 33ccc6dd26d..07001edf4d6 100644 --- a/src/devices/machine/mos6526.h +++ b/src/devices/machine/mos6526.h @@ -61,6 +61,41 @@ #pragma once + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MOS6526_TOD(_clock) \ + downcast<mos6526_device &>(*device).set_tod_clock(_clock); + +#define MCFG_MOS6526_IRQ_CALLBACK(_write) \ + downcast<mos6526_device &>(*device).set_irq_wr_callback(DEVCB_##_write); + +#define MCFG_MOS6526_CNT_CALLBACK(_write) \ + downcast<mos6526_device &>(*device).set_cnt_wr_callback(DEVCB_##_write); + +#define MCFG_MOS6526_SP_CALLBACK(_write) \ + downcast<mos6526_device &>(*device).set_sp_wr_callback(DEVCB_##_write); + +#define MCFG_MOS6526_PA_INPUT_CALLBACK(_read) \ + downcast<mos6526_device &>(*device).set_pa_rd_callback(DEVCB_##_read); + +#define MCFG_MOS6526_PA_OUTPUT_CALLBACK(_write) \ + downcast<mos6526_device &>(*device).set_pa_wr_callback(DEVCB_##_write); + +#define MCFG_MOS6526_PB_INPUT_CALLBACK(_read) \ + downcast<mos6526_device &>(*device).set_pb_rd_callback(DEVCB_##_read); + +#define MCFG_MOS6526_PB_OUTPUT_CALLBACK(_write) \ + downcast<mos6526_device &>(*device).set_pb_wr_callback(DEVCB_##_write); + +#define MCFG_MOS6526_PC_CALLBACK(_write) \ + downcast<mos6526_device &>(*device).set_pc_wr_callback(DEVCB_##_write); + + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -76,6 +111,14 @@ public: void set_tod_clock(int clock) { m_tod_clock = clock; } + template <class Object> devcb_base &set_irq_wr_callback(Object &&cb) { return m_write_irq.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_cnt_wr_callback(Object &&cb) { return m_write_cnt.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_sp_wr_callback(Object &&cb) { return m_write_sp.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_pa_rd_callback(Object &&cb) { return m_read_pa.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_pa_wr_callback(Object &&cb) { return m_write_pa.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_pb_rd_callback(Object &&cb) { return m_read_pb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_pb_wr_callback(Object &&cb) { return m_write_pb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_pc_wr_callback(Object &&cb) { return m_write_pc.set_callback(std::forward<Object>(cb)); } auto irq_wr_callback() { return m_write_irq.bind(); } auto cnt_wr_callback() { return m_write_cnt.bind(); } auto sp_wr_callback() { return m_write_sp.bind(); } @@ -85,11 +128,13 @@ public: auto pb_wr_callback() { return m_write_pb.bind(); } auto pc_wr_callback() { return m_write_pc.bind(); } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); - uint8_t pa_r() { return m_pa; } - uint8_t pb_r() { return m_pb; } + uint8_t read_pa() { return m_pa; } + DECLARE_READ8_MEMBER( pa_r ) { return m_pa; } + uint8_t read_pb() { return m_pb; } + DECLARE_READ8_MEMBER( pb_r ) { return m_pb; } DECLARE_READ_LINE_MEMBER( sp_r ) { return m_sp; } DECLARE_WRITE_LINE_MEMBER( sp_w ); @@ -228,8 +273,8 @@ class mos8520_device : public mos6526_device public: mos8520_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); protected: virtual inline void clock_tod() override; @@ -243,8 +288,8 @@ class mos5710_device : public mos6526_device public: mos5710_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - //uint8_t read(offs_t offset); - //void write(offs_t offset, uint8_t data); + //DECLARE_READ8_MEMBER( read ); + //DECLARE_WRITE8_MEMBER( write ); }; diff --git a/src/devices/machine/mos6530.h b/src/devices/machine/mos6530.h index 6bbeb8db9de..cc930fa8613 100644 --- a/src/devices/machine/mos6530.h +++ b/src/devices/machine/mos6530.h @@ -48,10 +48,10 @@ class mos6530_device : public device_t public: mos6530_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - auto in_pa_callback() { return m_in_pa_cb.bind(); } - auto out_pa_callback() { return m_out_pa_cb.bind(); } - auto in_pb_callback() { return m_in_pb_cb.bind(); } - auto out_pb_callback() { return m_out_pb_cb.bind(); } + template <class Object> devcb_base &set_in_pa_callback(Object &&cb) { return m_in_pa_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_out_pa_callback(Object &&cb) { return m_out_pa_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_in_pb_callback(Object &&cb) { return m_in_pb_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_out_pb_callback(Object &&cb) { return m_out_pb_cb.set_callback(std::forward<Object>(cb)); } DECLARE_READ8_MEMBER( read ); DECLARE_WRITE8_MEMBER( write ); @@ -108,4 +108,17 @@ private: DECLARE_DEVICE_TYPE(MOS6530, mos6530_device) + +#define MCFG_MOS6530_IN_PA_CB(_devcb) \ + downcast<mos6530_device &>(*device).set_in_pa_callback(DEVCB_##_devcb); + +#define MCFG_MOS6530_OUT_PA_CB(_devcb) \ + downcast<mos6530_device &>(*device).set_out_pa_callback(DEVCB_##_devcb); + +#define MCFG_MOS6530_IN_PB_CB(_devcb) \ + downcast<mos6530_device &>(*device).set_in_pb_callback(DEVCB_##_devcb); + +#define MCFG_MOS6530_OUT_PB_CB(_devcb) \ + downcast<mos6530_device &>(*device).set_out_pb_callback(DEVCB_##_devcb); + #endif // MAME_MACHINE_MOS6530_H diff --git a/src/devices/machine/mos6530n.h b/src/devices/machine/mos6530n.h index 0042a73e429..a5dfd3ee6fe 100644 --- a/src/devices/machine/mos6530n.h +++ b/src/devices/machine/mos6530n.h @@ -57,6 +57,125 @@ #pragma once + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MOS6530n_IRQ_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_irq_wr_callback(DEVCB_##_write); + +#define MCFG_MOS6530n_IN_PA_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pa_rd_callback(DEVCB_##_read); + +#define MCFG_MOS6530n_OUT_PA_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pa_wr_callback(DEVCB_##_write); + +#define MCFG_MOS6530n_IN_PB_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pb_rd_callback(DEVCB_##_read); + +#define MCFG_MOS6530n_OUT_PB_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pb_wr_callback(DEVCB_##_write); + +#define MCFG_MOS6530n_IN_PA0_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pa_rd_callback<0>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PA1_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pa_rd_callback<1>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PA2_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pa_rd_callback<2>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PA3_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pa_rd_callback<3>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PA4_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pa_rd_callback<4>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PA5_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pa_rd_callback<5>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PA6_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pa_rd_callback<6>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PA7_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pa_rd_callback<7>(DEVCB_##_read); + +#define MCFG_MOS6530n_OUT_PA0_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pa_wr_callback<0>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PA1_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pa_wr_callback<1>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PA2_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pa_wr_callback<2>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PA3_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pa_wr_callback<3>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PA4_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pa_wr_callback<4>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PA5_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pa_wr_callback<5>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PA6_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pa_wr_callback<6>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PA7_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pa_wr_callback<7>(DEVCB_##_write); + +#define MCFG_MOS6530n_IN_PB0_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pb_rd_callback<0>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PB1_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pb_rd_callback<1>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PB2_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pb_rd_callback<2>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PB3_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pb_rd_callback<3>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PB4_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pb_rd_callback<4>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PB5_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pb_rd_callback<5>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PB6_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pb_rd_callback<6>(DEVCB_##_read); + +#define MCFG_MOS6530n_IN_PB7_CB(_read) \ + downcast<mos6530_device_base &>(*device).set_pb_rd_callback<7>(DEVCB_##_read); + +#define MCFG_MOS6530n_OUT_PB0_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pb_wr_callback<0>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PB1_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pb_wr_callback<1>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PB2_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pb_wr_callback<2>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PB3_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pb_wr_callback<3>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PB4_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pb_wr_callback<4>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PB5_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pb_wr_callback<5>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PB6_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pb_wr_callback<6>(DEVCB_##_write); + +#define MCFG_MOS6530n_OUT_PB7_CB(_write) \ + downcast<mos6530_device_base &>(*device).set_pb_wr_callback<7>(DEVCB_##_write); + + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -66,6 +185,15 @@ class mos6530_device_base : public device_t { public: + template <class Object> devcb_base &set_irq_wr_callback(Object &&cb) { return m_irq_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_pa_rd_callback(Object &&cb) { return m_in8_pa_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_pa_wr_callback(Object &&cb) { return m_out8_pa_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_pb_rd_callback(Object &&cb) { return m_in8_pb_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_pb_wr_callback(Object &&cb) { return m_out8_pb_cb.set_callback(std::forward<Object>(cb)); } + template <unsigned N, class Object> devcb_base &set_pa_rd_callback(Object &&cb) { return m_in_pa_cb[N].set_callback(std::forward<Object>(cb)); } + template <unsigned N, class Object> devcb_base &set_pa_wr_callback(Object &&cb) { return m_out_pa_cb[N].set_callback(std::forward<Object>(cb)); } + template <unsigned N, class Object> devcb_base &set_pb_rd_callback(Object &&cb) { return m_in_pb_cb[N].set_callback(std::forward<Object>(cb)); } + template <unsigned N, class Object> devcb_base &set_pb_wr_callback(Object &&cb) { return m_out_pb_cb[N].set_callback(std::forward<Object>(cb)); } auto irq_wr_callback() { return m_irq_cb.bind(); } auto pa_rd_callback() { return m_in8_pa_cb.bind(); } auto pa_wr_callback() { return m_out8_pa_cb.bind(); } diff --git a/src/devices/machine/mos6551.cpp b/src/devices/machine/mos6551.cpp index f9edbd39cee..37bb874aaf4 100644 --- a/src/devices/machine/mos6551.cpp +++ b/src/devices/machine/mos6551.cpp @@ -63,11 +63,10 @@ const int mos6551_device::transmitter_controls[4][3] = {0, 1, 1} }; -void mos6551_device::device_add_mconfig(machine_config &config) -{ - CLOCK(config, m_internal_clock, 0); - m_internal_clock->signal_handler().set(FUNC(mos6551_device::internal_clock)); -} +MACHINE_CONFIG_START(mos6551_device::device_add_mconfig) + MCFG_DEVICE_ADD("clock", CLOCK, 0) + MCFG_CLOCK_SIGNAL_HANDLER(WRITELINE(*this, mos6551_device, internal_clock)) +MACHINE_CONFIG_END void mos6551_device::device_start() @@ -271,8 +270,7 @@ void mos6551_device::update_divider() uint8_t mos6551_device::read_rdr() { - if (!machine().side_effects_disabled()) - m_status &= ~(SR_PARITY_ERROR | SR_FRAMING_ERROR | SR_OVERRUN | SR_RDRF); + m_status &= ~(SR_PARITY_ERROR | SR_FRAMING_ERROR | SR_OVERRUN | SR_RDRF); return m_rdr; } @@ -280,18 +278,15 @@ uint8_t mos6551_device::read_status() { uint8_t status = m_status; - if (!machine().side_effects_disabled()) + if (m_cts) { - if (m_cts) - { - status &= ~SR_TDRE; - } + status &= ~SR_TDRE; + } - if (m_irq_state != 0) - { - m_irq_state = 0; - update_irq(); - } + if (m_irq_state != 0) + { + m_irq_state = 0; + update_irq(); } return status; @@ -379,8 +374,11 @@ void mos6551_device::write_command(uint8_t data) update_divider(); } -uint8_t mos6551_device::read(offs_t offset) +READ8_MEMBER( mos6551_device::read ) { + if (machine().side_effects_disabled()) + return 0xff; + switch (offset & 0x03) { case 0: @@ -398,7 +396,7 @@ uint8_t mos6551_device::read(offs_t offset) } } -void mos6551_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( mos6551_device::write ) { switch (offset & 0x03) { diff --git a/src/devices/machine/mos6551.h b/src/devices/machine/mos6551.h index b7afabfa603..626c17fd0b2 100644 --- a/src/devices/machine/mos6551.h +++ b/src/devices/machine/mos6551.h @@ -33,7 +33,7 @@ class mos6551_device : public device_t { public: - mos6551_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + mos6551_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); auto irq_handler() { return m_irq_handler.bind(); } auto txd_handler() { return m_txd_handler.bind(); } @@ -41,8 +41,8 @@ public: auto rts_handler() { return m_rts_handler.bind(); } auto dtr_handler() { return m_dtr_handler.bind(); } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); DECLARE_WRITE_LINE_MEMBER(write_xtal1); // txc DECLARE_WRITE_LINE_MEMBER(write_rxd); diff --git a/src/devices/machine/mos6702.cpp b/src/devices/machine/mos6702.cpp index 1b552054cb4..a5fa3d4c088 100644 --- a/src/devices/machine/mos6702.cpp +++ b/src/devices/machine/mos6702.cpp @@ -49,7 +49,7 @@ void mos6702_device::device_start() // read - //------------------------------------------------- -uint8_t mos6702_device::read(offs_t offset) +READ8_MEMBER( mos6702_device::read ) { return 0; } @@ -59,6 +59,6 @@ uint8_t mos6702_device::read(offs_t offset) // write - //------------------------------------------------- -void mos6702_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( mos6702_device::write ) { } diff --git a/src/devices/machine/mos6702.h b/src/devices/machine/mos6702.h index ab1ea945e6e..4e7ef027b6e 100644 --- a/src/devices/machine/mos6702.h +++ b/src/devices/machine/mos6702.h @@ -25,6 +25,16 @@ #pragma once + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MOS6702_ADD(tag, clock) \ + MCFG_DEVICE_ADD(tag, MOS6702, clock) + + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -37,8 +47,8 @@ public: // construction/destruction mos6702_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); protected: // device-level overrides diff --git a/src/devices/machine/mos8706.h b/src/devices/machine/mos8706.h index a3a6247bf5a..36cb6d55d5d 100644 --- a/src/devices/machine/mos8706.h +++ b/src/devices/machine/mos8706.h @@ -29,6 +29,17 @@ #pragma once + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MOS8706_ADD(tag, clock) \ + MCFG_DEVICE_ADD((tag), MOS8706, (clock)) + + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** diff --git a/src/devices/machine/mos8722.cpp b/src/devices/machine/mos8722.cpp index 0364460b63e..b55d8393a9f 100644 --- a/src/devices/machine/mos8722.cpp +++ b/src/devices/machine/mos8722.cpp @@ -171,7 +171,7 @@ uint8_t mos8722_device::read(offs_t offset, uint8_t data) // write - register write //------------------------------------------------- -void mos8722_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( mos8722_device::write ) { if (MCR_C64) return; diff --git a/src/devices/machine/mos8722.h b/src/devices/machine/mos8722.h index 2b80aa846c2..e5d32d4e4ea 100644 --- a/src/devices/machine/mos8722.h +++ b/src/devices/machine/mos8722.h @@ -57,7 +57,7 @@ public: auto sense40() { return m_read_sense40.bind(); } uint8_t read(offs_t offset, uint8_t data); - void write(offs_t offset, uint8_t data); + DECLARE_WRITE8_MEMBER( write ); DECLARE_READ_LINE_MEMBER( fsdir_r ); diff --git a/src/devices/machine/mos8726.cpp b/src/devices/machine/mos8726.cpp index e1f167d70d3..0c2286788a7 100644 --- a/src/devices/machine/mos8726.cpp +++ b/src/devices/machine/mos8726.cpp @@ -90,7 +90,7 @@ void mos8726_device::execute_run() // read - //------------------------------------------------- -uint8_t mos8726_device::read(offs_t offset) +READ8_MEMBER( mos8726_device::read ) { uint8_t data = 0; @@ -102,7 +102,7 @@ uint8_t mos8726_device::read(offs_t offset) // write - //------------------------------------------------- -void mos8726_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( mos8726_device::write ) { } diff --git a/src/devices/machine/mos8726.h b/src/devices/machine/mos8726.h index 90b78ec8412..8435bf0f544 100644 --- a/src/devices/machine/mos8726.h +++ b/src/devices/machine/mos8726.h @@ -47,6 +47,17 @@ #pragma once + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MOS8726_ADD(tag) \ + MCFG_DEVICE_ADD((tag), MOS8726, 1000000) // dummy clock + + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -60,8 +71,8 @@ public: // construction/destruction mos8726_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); DECLARE_WRITE_LINE_MEMBER( bs_w ); diff --git a/src/devices/machine/mpu401.cpp b/src/devices/machine/mpu401.cpp index 48cc04b455d..578ad206721 100644 --- a/src/devices/machine/mpu401.cpp +++ b/src/devices/machine/mpu401.cpp @@ -81,8 +81,7 @@ DEFINE_DEVICE_TYPE(MPU401, mpu401_device, "mpu401", "Roland MPU-401 I/O box") // device_add_mconfig - add device configuration //------------------------------------------------- -void mpu401_device::device_add_mconfig(machine_config &config) -{ +MACHINE_CONFIG_START(mpu401_device::device_add_mconfig) M6801(config, m_ourcpu, 4000000); /* 4 MHz as per schematics */ m_ourcpu->set_addrmap(AS_PROGRAM, &mpu401_device::mpu401_map); m_ourcpu->in_p1_cb().set(FUNC(mpu401_device::port1_r)); @@ -91,10 +90,11 @@ void mpu401_device::device_add_mconfig(machine_config &config) m_ourcpu->out_p2_cb().set(FUNC(mpu401_device::port2_w)); m_ourcpu->out_ser_tx_cb().set(MIDIOUT_TAG, FUNC(midi_port_device::write_txd)); - MIDI_PORT(config, MIDIIN_TAG, midiin_slot, "midiin").rxd_handler().set(DEVICE_SELF, FUNC(mpu401_device::midi_rx_w)); + MCFG_MIDI_PORT_ADD(MIDIIN_TAG, midiin_slot, "midiin") + MCFG_MIDI_RX_HANDLER(WRITELINE(DEVICE_SELF, mpu401_device, midi_rx_w)) - MIDI_PORT(config, MIDIOUT_TAG, midiout_slot, "midiout"); -} + MCFG_MIDI_PORT_ADD(MIDIOUT_TAG, midiout_slot, "midiout") +MACHINE_CONFIG_END //------------------------------------------------- // rom_region - device-specific ROM region diff --git a/src/devices/machine/msm58321.h b/src/devices/machine/msm58321.h index d5b7a5d78c3..1842b4f2036 100644 --- a/src/devices/machine/msm58321.h +++ b/src/devices/machine/msm58321.h @@ -39,6 +39,32 @@ #include "dirtc.h" + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MSM58321_D0_HANDLER(_devcb) \ + downcast<msm58321_device &>(*device).set_d0_handler(DEVCB_##_devcb); + +#define MCFG_MSM58321_D1_HANDLER(_devcb) \ + downcast<msm58321_device &>(*device).set_d1_handler(DEVCB_##_devcb); + +#define MCFG_MSM58321_D2_HANDLER(_devcb) \ + downcast<msm58321_device &>(*device).set_d2_handler(DEVCB_##_devcb); + +#define MCFG_MSM58321_D3_HANDLER(_devcb) \ + downcast<msm58321_device &>(*device).set_d3_handler(DEVCB_##_devcb); + +#define MCFG_MSM58321_BUSY_HANDLER(_devcb) \ + downcast<msm58321_device &>(*device).set_busy_handler(DEVCB_##_devcb); + +#define MCFG_MSM58321_YEAR0(_year0) \ + downcast<msm58321_device &>(*device).set_year0(_year0); + +#define MCFG_MSM58321_DEFAULT_24H(_default_24h) \ + downcast<msm58321_device &>(*device).set_default_24h(_default_24h); + // ======================> msm58321_device class msm58321_device : public device_t, @@ -50,6 +76,11 @@ public: msm58321_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // configuration helpers + template <class Object> devcb_base &set_d0_handler(Object &&cb) { return m_d0_handler.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_d1_handler(Object &&cb) { return m_d1_handler.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_d2_handler(Object &&cb) { return m_d2_handler.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_d3_handler(Object &&cb) { return m_d3_handler.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_busy_handler(Object &&cb) { return m_busy_handler.set_callback(std::forward<Object>(cb)); } auto d0_handler() { return m_d0_handler.bind(); } auto d1_handler() { return m_d1_handler.bind(); } auto d2_handler() { return m_d2_handler.bind(); } diff --git a/src/devices/machine/msm6242.h b/src/devices/machine/msm6242.h index 430bbbc10f0..bd6bd89403e 100644 --- a/src/devices/machine/msm6242.h +++ b/src/devices/machine/msm6242.h @@ -40,6 +40,10 @@ #include "dirtc.h" +#define MCFG_MSM6242_OUT_INT_HANDLER(_devcb) \ + downcast<msm6242_device &>(*device).set_out_int_handler(DEVCB_##_devcb); + + // ======================> msm6242_device class msm6242_device : public device_t, public device_rtc_interface @@ -48,6 +52,7 @@ public: // construction/destruction msm6242_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template <class Object> devcb_base &set_out_int_handler(Object &&cb) { return m_out_int_handler.set_callback(std::forward<Object>(cb)); } auto out_int_handler() { return m_out_int_handler.bind(); } // I/O operations diff --git a/src/devices/machine/myb3k_kbd.h b/src/devices/machine/myb3k_kbd.h index 34c2c5cc414..747289a53f1 100644 --- a/src/devices/machine/myb3k_kbd.h +++ b/src/devices/machine/myb3k_kbd.h @@ -14,6 +14,9 @@ is responsible for storing the byte into the serial/parallell converter (that can be read through IN from port 0x04) and then trigger an interrupt. + MCFG_DEVICE_ADD("myb3k_keyboard", MYB3K_KEYBOARD, 0) + MCFG_MYB3K_KEYBOARD_CB(PUT(myb3k_state, kbd_set_data_and_interrupt)) + **********************************************************************/ #ifndef MAME_MACHINE_MYB3K_KBD_H @@ -21,6 +24,11 @@ #pragma once +#define MYB3K_KBD_CB_PUT(cls, fnc) myb3k_keyboard_device::output_delegate((&cls::fnc), (#cls "::" #fnc), DEVICE_SELF, ((cls *)nullptr)) +#define MYB3K_KBD_CB_DEVPUT(tag, cls, fnc) myb3k_keyboard_device::output_delegate((&cls::fnc), (#cls "::" #fnc), (tag), ((cls *)nullptr)) + +#define MCFG_MYB3K_KEYBOARD_CB(cb) downcast<myb3k_keyboard_device &>(*device).set_keyboard_callback((MYB3K_KBD_CB_##cb)); + DECLARE_DEVICE_TYPE(MYB3K_KEYBOARD, myb3k_keyboard_device) DECLARE_DEVICE_TYPE(JB3000_KEYBOARD, jb3000_keyboard_device) DECLARE_DEVICE_TYPE(STEPONE_KEYBOARD, stepone_keyboard_device) @@ -43,18 +51,7 @@ public: TIMER_ID_SECOND_BYTE }; - template <class FunctionClass> - void set_keyboard_callback(void (FunctionClass::*callback)(u8 character), const char *name) - { - set_keyboard_callback(output_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr))); - } - // FIXME: this should be aware of current device for resolving the tag - template <class FunctionClass> - void set_keyboard_callback(const char *devname, void (FunctionClass::*callback)(u8 character), const char *name) - { - set_keyboard_callback(output_delegate(callback, name, devname, static_cast<FunctionClass *>(nullptr))); - } - void set_keyboard_callback(output_delegate callback) { m_keyboard_cb = callback; } + template <class Object> void set_keyboard_callback(Object &&cb) { m_keyboard_cb = std::forward<Object>(cb); } protected: myb3k_keyboard_device( diff --git a/src/devices/machine/ncr5380.h b/src/devices/machine/ncr5380.h index 9d9d7b96617..b2f7e4f2509 100644 --- a/src/devices/machine/ncr5380.h +++ b/src/devices/machine/ncr5380.h @@ -36,6 +36,8 @@ enum // device stuff +#define MCFG_NCR5380_IRQ_CB(_devcb) \ + downcast<ncr5380_device &>(*device).set_irq_callback(DEVCB_##_devcb); class ncr5380_device : public legacy_scsi_host_adapter { @@ -43,6 +45,7 @@ public: // construction/destruction ncr5380_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template <class Object> devcb_base &set_irq_callback(Object &&cb) { return m_irq_cb.set_callback(std::forward<Object>(cb)); } auto irq_callback() { return m_irq_cb.bind(); } // our API diff --git a/src/devices/machine/ncr5380n.cpp b/src/devices/machine/ncr5380n.cpp index e5132603609..4d09a910e46 100644 --- a/src/devices/machine/ncr5380n.cpp +++ b/src/devices/machine/ncr5380n.cpp @@ -288,12 +288,12 @@ void ncr5380n_device::delay_cycles(int cycles) tm->adjust(clocks_to_attotime(cycles)); } -uint8_t ncr5380n_device::scsidata_r() +READ8_MEMBER(ncr5380n_device::scsidata_r) { return scsi_bus->data_r(); } -void ncr5380n_device::outdata_w(uint8_t data) +WRITE8_MEMBER(ncr5380n_device::outdata_w) { m_outdata = data; @@ -304,12 +304,12 @@ void ncr5380n_device::outdata_w(uint8_t data) } } -uint8_t ncr5380n_device::icmd_r() +READ8_MEMBER(ncr5380n_device::icmd_r) { return m_icommand; } -void ncr5380n_device::icmd_w(uint8_t data) +WRITE8_MEMBER(ncr5380n_device::icmd_w) { // asserting to drive the data bus? if ((data & IC_DBUS) && !(m_icommand & IC_DBUS)) @@ -340,12 +340,12 @@ void ncr5380n_device::icmd_w(uint8_t data) delay(2); } -uint8_t ncr5380n_device::mode_r() +READ8_MEMBER(ncr5380n_device::mode_r) { return m_mode; } -void ncr5380n_device::mode_w(uint8_t data) +WRITE8_MEMBER(ncr5380n_device::mode_w) { // logerror("%s: mode_w %02x (%s)\n", tag(), data, machine().describe_context()); // arbitration bit being set? @@ -373,13 +373,13 @@ void ncr5380n_device::mode_w(uint8_t data) m_mode = data; } -uint8_t ncr5380n_device::command_r() +READ8_MEMBER(ncr5380n_device::command_r) { // logerror("%s: command_r %02x (%s)\n", tag(), m_tcommand, machine().describe_context()); return m_tcommand; } -void ncr5380n_device::command_w(uint8_t data) +WRITE8_MEMBER(ncr5380n_device::command_w) { // logerror("%s: command_w %02x (%s)\n", tag(), data, machine().describe_context()); m_tcommand = data; @@ -413,7 +413,7 @@ void ncr5380n_device::check_irq() #endif } -uint8_t ncr5380n_device::status_r() +READ8_MEMBER(ncr5380n_device::status_r) { uint32_t ctrl = scsi_bus->ctrl_r(); uint8_t res = status | @@ -429,11 +429,11 @@ uint8_t ncr5380n_device::status_r() return res; } -void ncr5380n_device::selenable_w(uint8_t data) +WRITE8_MEMBER(ncr5380n_device::selenable_w) { } -uint8_t ncr5380n_device::busandstatus_r() +READ8_MEMBER(ncr5380n_device::busandstatus_r) { uint32_t ctrl = scsi_bus->ctrl_r(); uint8_t res = m_busstatus | @@ -445,28 +445,28 @@ uint8_t ncr5380n_device::busandstatus_r() return res; } -void ncr5380n_device::startdmasend_w(uint8_t data) +WRITE8_MEMBER(ncr5380n_device::startdmasend_w) { logerror("%02x to start dma send\n", data); drq_set(); } -uint8_t ncr5380n_device::indata_r() +READ8_MEMBER(ncr5380n_device::indata_r) { return dma_r(); } -void ncr5380n_device::startdmatargetrx_w(uint8_t data) +WRITE8_MEMBER(ncr5380n_device::startdmatargetrx_w) { logerror("%02x to start dma target Rx\n", data); } -uint8_t ncr5380n_device::resetparityirq_r() +READ8_MEMBER(ncr5380n_device::resetparityirq_r) { return 0; } -void ncr5380n_device::startdmainitrx_w(uint8_t data) +WRITE8_MEMBER(ncr5380n_device::startdmainitrx_w) { // logerror("%02x to start dma initiator Rx\n", data); recv_byte(); @@ -518,73 +518,73 @@ void ncr5380n_device::drq_clear() } } -uint8_t ncr5380n_device::read(offs_t offset) +READ8_MEMBER(ncr5380n_device::read) { switch (offset & 7) { - case 0: - return scsidata_r(); + case 0: + return scsidata_r(space, offset); - case 1: - return icmd_r(); + case 1: + return icmd_r(space, offset); - case 2: - return mode_r(); + case 2: + return mode_r(space, offset); - case 3: - return command_r(); + case 3: + return command_r(space, offset); - case 4: - return status_r(); + case 4: + return status_r(space, offset); - case 5: - return busandstatus_r(); + case 5: + return busandstatus_r(space, offset); - case 6: - return indata_r(); + case 6: + return indata_r(space, offset); - case 7: - return resetparityirq_r(); + case 7: + return resetparityirq_r(space, offset); } return 0xff; } -void ncr5380n_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(ncr5380n_device::write) { // logerror("%x to 5380 @ %x\n", data, offset); switch (offset & 7) { - case 0: - outdata_w(data); - break; + case 0: + outdata_w(space, offset, data); + break; - case 1: - icmd_w(data); - break; + case 1: + icmd_w(space, offset, data); + break; - case 2: - mode_w(data); - break; + case 2: + mode_w(space, offset, data); + break; - case 3: - command_w(data); - break; + case 3: + command_w(space, offset, data); + break; - case 4: - selenable_w(data); - break; + case 4: + selenable_w(space, offset, data); + break; - case 5: - startdmasend_w(data); - break; + case 5: + startdmasend_w(space, offset, data); + break; - case 6: - startdmatargetrx_w(data); - break; + case 6: + startdmatargetrx_w(space, offset, data); + break; - case 7: - startdmainitrx_w(data); - break; + case 7: + startdmainitrx_w(space, offset, data); + break; } } diff --git a/src/devices/machine/ncr5380n.h b/src/devices/machine/ncr5380n.h index 365df032419..973616c65a3 100644 --- a/src/devices/machine/ncr5380n.h +++ b/src/devices/machine/ncr5380n.h @@ -15,6 +15,11 @@ #include "machine/nscsi_bus.h" +#define MCFG_NCR5380N_IRQ_HANDLER(_devcb) \ + downcast<ncr5380n_device &>(*device).set_irq_handler(DEVCB_##_devcb); + +#define MCFG_NCR5380N_DRQ_HANDLER(_devcb) \ + downcast<ncr5380n_device &>(*device).set_drq_handler(DEVCB_##_devcb); class ncr5380n_device : public nscsi_device { @@ -22,11 +27,11 @@ public: ncr5380n_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // configuration helpers - auto irq_handler() { return m_irq_handler.bind(); } - auto drq_handler() { return m_drq_handler.bind(); } + template <class Object> devcb_base &set_irq_handler(Object &&cb) { return m_irq_handler.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_drq_handler(Object &&cb) { return m_drq_handler.set_callback(std::forward<Object>(cb)); } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); uint8_t dma_r(); void dma_w(uint8_t val); @@ -198,22 +203,22 @@ private: void map(address_map &map); - uint8_t scsidata_r(); - void outdata_w(uint8_t data); - uint8_t icmd_r(); - void icmd_w(uint8_t data); - uint8_t mode_r(); - void mode_w(uint8_t data); - uint8_t command_r(); - void command_w(uint8_t data); - uint8_t status_r(); - void selenable_w(uint8_t data); - uint8_t busandstatus_r(); - void startdmasend_w(uint8_t data); - uint8_t indata_r(); - void startdmatargetrx_w(uint8_t data); - uint8_t resetparityirq_r(); - void startdmainitrx_w(uint8_t data); + DECLARE_READ8_MEMBER(scsidata_r); + DECLARE_WRITE8_MEMBER(outdata_w); + DECLARE_READ8_MEMBER(icmd_r); + DECLARE_WRITE8_MEMBER(icmd_w); + DECLARE_READ8_MEMBER(mode_r); + DECLARE_WRITE8_MEMBER(mode_w); + DECLARE_READ8_MEMBER(command_r); + DECLARE_WRITE8_MEMBER(command_w); + DECLARE_READ8_MEMBER(status_r); + DECLARE_WRITE8_MEMBER(selenable_w); + DECLARE_READ8_MEMBER(busandstatus_r); + DECLARE_WRITE8_MEMBER(startdmasend_w); + DECLARE_READ8_MEMBER(indata_r); + DECLARE_WRITE8_MEMBER(startdmatargetrx_w); + DECLARE_READ8_MEMBER(resetparityirq_r); + DECLARE_WRITE8_MEMBER(startdmainitrx_w); devcb_write_line m_irq_handler; devcb_write_line m_drq_handler; diff --git a/src/devices/machine/ncr5385.cpp b/src/devices/machine/ncr5385.cpp index 6c1f4a3bb4e..d5cd98a4a5f 100644 --- a/src/devices/machine/ncr5385.cpp +++ b/src/devices/machine/ncr5385.cpp @@ -34,7 +34,7 @@ void ncr5385_device::device_reset() m_diag_status_reg = DIAG_COMPLETE; } -void ncr5385_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(ncr5385_device::write) { switch (offset) { @@ -96,7 +96,7 @@ void ncr5385_device::write(offs_t offset, uint8_t data) } } -uint8_t ncr5385_device::read(offs_t offset) +READ8_MEMBER(ncr5385_device::read) { switch (offset) { diff --git a/src/devices/machine/ncr5385.h b/src/devices/machine/ncr5385.h index a1dec052045..3a60ca0a6c8 100644 --- a/src/devices/machine/ncr5385.h +++ b/src/devices/machine/ncr5385.h @@ -44,6 +44,14 @@ #pragma once + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_NCR5385_INT_CB(_int) \ + downcast<ncr5385_device &>(*device).set_int_callback(DEVCB_##_int); + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -56,10 +64,11 @@ public: // construction/destruction ncr5385_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template <class Object> devcb_base &set_int_callback(Object &&cb) { return m_int.set_callback(std::forward<Object>(cb)); } auto irq() { return m_int.bind(); } - void write(offs_t offset, uint8_t data); - uint8_t read(offs_t offset); + DECLARE_WRITE8_MEMBER(write); + DECLARE_READ8_MEMBER(read); protected: // device-level overrides diff --git a/src/devices/machine/ncr5390.cpp b/src/devices/machine/ncr5390.cpp index 10b7510d707..62c62a038b6 100644 --- a/src/devices/machine/ncr5390.cpp +++ b/src/devices/machine/ncr5390.cpp @@ -1,12 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Olivier Galibert -/* - * TODO - * - 16 bit dma order, alignment and last byte handling - * - clean up variable naming and protection - */ - #include "emu.h" #include "ncr5390.h" @@ -20,10 +14,9 @@ #define DELAY_HACK -DEFINE_DEVICE_TYPE(NCR5390, ncr5390_device, "ncr5390", "NCR 5390 SCSI Controller") -DEFINE_DEVICE_TYPE(NCR53C90A, ncr53c90a_device, "ncr53c90a", "NCR 53C90A Advanced SCSI Controller") -DEFINE_DEVICE_TYPE(NCR53C94, ncr53c94_device, "ncr53c94", "NCR 53C94 Advanced SCSI Controller") -DEFINE_DEVICE_TYPE(NCR53CF94, ncr53cf94_device, "ncr53cf94", "NCR 53CF94-2 Fast SCSI Controller") // TODO: differences not emulated +DEFINE_DEVICE_TYPE(NCR5390, ncr5390_device, "ncr5390", "NCR 5390 SCSI") +DEFINE_DEVICE_TYPE(NCR53C90A, ncr53c90a_device, "ncr53c90a", "NCR 53C90A SCSI") +DEFINE_DEVICE_TYPE(NCR53C94, ncr53c94_device, "ncr53c94", "NCR 53C94 SCSI") void ncr5390_device::map(address_map &map) { @@ -40,38 +33,38 @@ void ncr5390_device::map(address_map &map) map(0x9, 0x9).w(FUNC(ncr5390_device::clock_w)); } -uint8_t ncr5390_device::read(offs_t offset) +READ8_MEMBER(ncr5390_device::read) { switch (offset) { - case 0: return tcounter_lo_r(); - case 1: return tcounter_hi_r(); - case 2: return fifo_r(); - case 3: return command_r(); - case 4: return status_r(); - case 5: return istatus_r(); - case 6: return seq_step_r(); - case 7: return fifo_flags_r(); - case 8: return conf_r(); - default: return 0xff; + case 0: return tcounter_lo_r(space, 0); + case 1: return tcounter_hi_r(space, 0); + case 2: return fifo_r(space, 0); + case 3: return command_r(space, 0); + case 4: return status_r(space, 0); + case 5: return istatus_r(space, 0); + case 6: return seq_step_r(space, 0); + case 7: return fifo_flags_r(space, 0); + case 8: return conf_r(space, 0); + default: return 0; } } -void ncr5390_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(ncr5390_device::write) { switch (offset) { - case 0: tcount_lo_w(data); break; - case 1: tcount_hi_w(data); break; - case 2: fifo_w(data); break; - case 3: command_w(data); break; - case 4: bus_id_w(data); break; - case 5: timeout_w(data); break; - case 6: sync_period_w(data); break; - case 7: sync_offset_w(data); break; - case 8: conf_w(data); break; - case 9: clock_w(data); break; - case 10: test_w(data); break; + case 0: tcount_lo_w(space, 0, data); break; + case 1: tcount_hi_w(space, 0, data); break; + case 2: fifo_w(space, 0, data); break; + case 3: command_w(space, 0, data); break; + case 4: bus_id_w(space, 0, data); break; + case 5: timeout_w(space, 0, data); break; + case 6: sync_period_w(space, 0, data); break; + case 7: sync_offset_w(space, 0, data); break; + case 8: conf_w(space, 0, data); break; + case 9: clock_w(space, 0, data); break; + case 10: test_w(space, 0, data); break; default: break; } } @@ -83,18 +76,18 @@ void ncr53c90a_device::map(address_map &map) map(0xb, 0xb).rw(FUNC(ncr53c90a_device::conf2_r), FUNC(ncr53c90a_device::conf2_w)); } -uint8_t ncr53c90a_device::read(offs_t offset) +READ8_MEMBER(ncr53c90a_device::read) { if (offset == 11) - return conf2_r(); - return ncr5390_device::read(offset); + return conf2_r(space, 0); + return ncr5390_device::read(space, offset); } -void ncr53c90a_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(ncr53c90a_device::write) { if (offset == 11) - return conf2_w(data); - ncr5390_device::write(offset, data); + return conf2_w(space, 0, data); + ncr5390_device::write(space, offset, data); } void ncr53c94_device::map(address_map &map) @@ -105,21 +98,21 @@ void ncr53c94_device::map(address_map &map) map(0xf, 0xf).w(FUNC(ncr53c94_device::fifo_align_w)); } -uint8_t ncr53c94_device::read(offs_t offset) +READ8_MEMBER(ncr53c94_device::read) { if (offset == 12) - return conf3_r(); - return ncr53c90a_device::read(offset); + return conf3_r(space, 0); + return ncr53c90a_device::read(space, offset); } -void ncr53c94_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(ncr53c94_device::write) { if (offset == 11) - conf3_w(data); + conf3_w(space, 0, data); else if (offset == 15) - fifo_align_w(data); + fifo_align_w(space, 0, data); else - ncr53c90a_device::write(offset, data); + ncr53c90a_device::write(space, offset, data); } ncr5390_device::ncr5390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) @@ -148,19 +141,8 @@ ncr53c90a_device::ncr53c90a_device(const machine_config &mconfig, const char *ta } ncr53c94_device::ncr53c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ncr53c94_device(mconfig, NCR53C94, tag, owner, clock) -{ -} - -ncr53c94_device::ncr53c94_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : ncr53c90a_device(mconfig, type, tag, owner, clock) + : ncr53c90a_device(mconfig, NCR53C94, tag, owner, clock) , config3(0) - , m_busmd(BUSMD_0) -{ -} - -ncr53cf94_device::ncr53cf94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ncr53c94_device(mconfig, NCR53CF94, tag, owner, clock) { } @@ -195,7 +177,10 @@ void ncr5390_device::device_start() m_irq_handler.resolve_safe(); m_drq_handler.resolve_safe(); + tcount = 0; + tcounter = 0; config = 0; + status = 0; bus_id = 0; select_timeout = 0; tm = timer_alloc(0); @@ -211,28 +196,26 @@ void ncr5390_device::device_reset() sync_offset = 0; seq = 0; config &= 7; - status = 0; + status &= 0x90; istatus = 0; irq = false; m_irq_handler(irq); + reset_soft(); +} +void ncr5390_device::reset_soft() +{ state = IDLE; scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); + status &= 0xef; drq = false; test_mode = false; m_drq_handler(drq); - - scsi_bus->ctrl_w(scsi_refid, 0, S_RST); - tcount = 0; - tcounter = 0; - reset_disconnect(); } void ncr5390_device::reset_disconnect() { - scsi_bus->ctrl_w(scsi_refid, 0, ~S_RST); - command_pos = 0; command_length = 0; memset(command, 0, sizeof(command)); @@ -275,17 +258,6 @@ void ncr5390_device::step(bool timeout) case IDLE: break; - case BUSRESET_WAIT_INT: - state = IDLE; - scsi_bus->ctrl_w(scsi_refid, 0, S_RST); - reset_disconnect(); - - if (!(config & 0x40)) { - istatus |= I_SCSI_RESET; - check_irq(); - } - break; - case ARB_COMPLETE << SUB_SHIFT: { if(!timeout) break; @@ -295,7 +267,7 @@ void ncr5390_device::step(bool timeout) if(win != scsi_id) { scsi_bus->data_w(scsi_refid, 0); scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); - fatalerror("ncr5390_device::step need to wait for bus free\n"); + fatalerror("need to wait for bus free\n"); } state = (state & STATE_MASK) | (ARB_ASSERT_SEL << SUB_SHIFT); scsi_bus->ctrl_w(scsi_refid, S_SEL, S_SEL); @@ -435,13 +407,15 @@ void ncr5390_device::step(bool timeout) case DISC_SEL_ARBITRATION_INIT: // wait until a command is in the fifo - if (!fifo_pos) { + if (!fifo_pos && dma_command && !(status & S_TC0)) { // dma starts after bus arbitration/selection is complete - check_drq(); + dma_set(DMA_OUT); + step(false); break; } - command_length = fifo_pos + tcounter; + // "with atn" variants have a message byte before the command descriptor + command_length = (c == CD_SELECT) ? derive_msg_size(fifo[0]) : 1; state = DISC_SEL_ARBITRATION; step(false); break; @@ -475,6 +449,7 @@ void ncr5390_device::step(bool timeout) seq = 1; function_bus_complete(); } else { + command_length = derive_msg_size(fifo[0]); state = DISC_SEL_WAIT_REQ; } break; @@ -485,8 +460,6 @@ void ncr5390_device::step(bool timeout) if((ctrl & S_PHASE_MASK) != S_PHASE_COMMAND) { if(!command_length) seq = 4; - else - seq = 2; scsi_bus->ctrl_wait(scsi_refid, 0, S_REQ); function_bus_complete(); break; @@ -707,7 +680,7 @@ void ncr5390_device::function_bus_complete() state = IDLE; istatus |= I_FUNCTION|I_BUS; dma_set(DMA_NONE); - check_drq(); + drq_clear(); check_irq(); } @@ -717,7 +690,7 @@ void ncr5390_device::function_complete() state = IDLE; istatus |= I_FUNCTION; dma_set(DMA_NONE); - check_drq(); + drq_clear(); check_irq(); } @@ -727,7 +700,7 @@ void ncr5390_device::bus_complete() state = IDLE; istatus |= I_BUS; dma_set(DMA_NONE); - check_drq(); + drq_clear(); check_irq(); } @@ -744,25 +717,25 @@ void ncr5390_device::delay_cycles(int cycles) tm->adjust(clocks_to_attotime(cycles)); } -uint8_t ncr5390_device::tcounter_lo_r() +READ8_MEMBER(ncr5390_device::tcounter_lo_r) { LOG("tcounter_lo_r %02x (%s)\n", tcounter & 0xff, machine().describe_context()); return tcounter; } -void ncr5390_device::tcount_lo_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::tcount_lo_w) { tcount = (tcount & 0xff00) | data; LOG("tcount_lo_w %02x (%s)\n", data, machine().describe_context()); } -uint8_t ncr5390_device::tcounter_hi_r() +READ8_MEMBER(ncr5390_device::tcounter_hi_r) { LOG("tcounter_hi_r %02x (%s)\n", tcounter >> 8, machine().describe_context()); return tcounter >> 8; } -void ncr5390_device::tcount_hi_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::tcount_hi_w) { tcount = (tcount & 0x00ff) | (data << 8); LOG("tcount_hi_w %02x (%s)\n", data, machine().describe_context()); @@ -773,17 +746,19 @@ uint8_t ncr5390_device::fifo_pop() uint8_t r = fifo[0]; fifo_pos--; memmove(fifo, fifo+1, fifo_pos); - check_drq(); + if((!fifo_pos) && dma_dir == DMA_OUT && !(status & S_TC0)) + drq_set(); return r; } void ncr5390_device::fifo_push(uint8_t val) { fifo[fifo_pos++] = val; - check_drq(); + if(!drq && dma_dir == DMA_IN && !(status & S_TC0)) + drq_set(); } -uint8_t ncr5390_device::fifo_r() +READ8_MEMBER(ncr5390_device::fifo_r) { uint8_t r; if(fifo_pos) { @@ -796,20 +771,20 @@ uint8_t ncr5390_device::fifo_r() return r; } -void ncr5390_device::fifo_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::fifo_w) { LOGMASKED(LOG_FIFO, "fifo_w 0x%02x fifo_pos %d (%s)\n", data, fifo_pos, machine().describe_context()); if(fifo_pos != 16) fifo[fifo_pos++] = data; } -uint8_t ncr5390_device::command_r() +READ8_MEMBER(ncr5390_device::command_r) { LOG("command_r (%s)\n", machine().describe_context()); return command[0]; } -void ncr5390_device::command_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::command_w) { LOG("command_w %02x command_pos %d (%s)\n", data, command_pos, machine().describe_context()); if(command_pos == 2) { @@ -859,8 +834,6 @@ void ncr5390_device::start_command() // clear transfer count zero flag when counter is reloaded status &= ~S_TC0; } - else - tcounter = 0; switch(c) { case CM_NOP: @@ -881,9 +854,13 @@ void ncr5390_device::start_command() case CM_RESET_BUS: LOGMASKED(LOG_COMMAND, "Reset SCSI bus\n"); - state = BUSRESET_WAIT_INT; - scsi_bus->ctrl_w(scsi_refid, S_RST, S_RST); - delay(130); + reset_soft(); + // FIXME: this interrupt should be generated when the reset is reflected + // back into the device, and not when the device starts the scsi reset + if (!(config & 0x40)) { + istatus = I_SCSI_RESET; + check_irq(); + } break; case CD_RESELECT: @@ -901,7 +878,6 @@ void ncr5390_device::start_command() "Select with ATN and stop sequence\n"); seq = 0; state = DISC_SEL_ARBITRATION_INIT; - dma_set(dma_command ? DMA_OUT : DMA_NONE); arbitrate(); break; @@ -920,7 +896,6 @@ void ncr5390_device::start_command() state = INIT_XFR; xfr_phase = scsi_bus->ctrl_r() & S_PHASE_MASK; dma_set(dma_command ? ((xfr_phase & S_INP) ? DMA_IN : DMA_OUT) : DMA_NONE); - check_drq(); step(false); break; @@ -961,14 +936,8 @@ void ncr5390_device::start_command() command_pop_and_chain(); break; - case CI_RESET_ATN: - LOGMASKED(LOG_COMMAND, "Reset ATN\n"); - scsi_bus->ctrl_w(scsi_refid, 0, S_ATN); - command_pop_and_chain(); - break; - default: - fatalerror("ncr5390_device::start_command unimplemented command %02x\n", c); + fatalerror("start unimplemented command %02x\n", c); } } @@ -984,6 +953,12 @@ bool ncr5390_device::check_valid_command(uint8_t cmd) return false; } +int ncr5390_device::derive_msg_size(uint8_t msg_id) +{ + const static int sizes[8] = { 6, 10, 6, 6, 6, 12, 6, 10 }; + return sizes[msg_id >> 5]; +} + void ncr5390_device::arbitrate() { state = (state & STATE_MASK) | (ARB_COMPLETE << SUB_SHIFT); @@ -1001,7 +976,7 @@ void ncr5390_device::check_irq() } -uint8_t ncr5390_device::status_r() +READ8_MEMBER(ncr5390_device::status_r) { uint32_t ctrl = scsi_bus->ctrl_r(); uint8_t res = status | (ctrl & S_MSG ? 4 : 0) | (ctrl & S_CTL ? 2 : 0) | (ctrl & S_INP ? 1 : 0); @@ -1010,13 +985,13 @@ uint8_t ncr5390_device::status_r() return res; } -void ncr5390_device::bus_id_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::bus_id_w) { bus_id = data & 7; LOG("bus_id=%d\n", bus_id); } -uint8_t ncr5390_device::istatus_r() +READ8_MEMBER(ncr5390_device::istatus_r) { uint8_t res = istatus; @@ -1034,39 +1009,39 @@ uint8_t ncr5390_device::istatus_r() return res; } -void ncr5390_device::timeout_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::timeout_w) { LOG("timeout_w 0x%02x\n", data); select_timeout = data; } -uint8_t ncr5390_device::seq_step_r() +READ8_MEMBER(ncr5390_device::seq_step_r) { LOG("seq_step_r %d (%s)\n", seq, machine().describe_context()); return seq; } -void ncr5390_device::sync_period_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::sync_period_w) { sync_period = data & 0x1f; } -uint8_t ncr5390_device::fifo_flags_r() +READ8_MEMBER(ncr5390_device::fifo_flags_r) { return fifo_pos; } -void ncr5390_device::sync_offset_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::sync_offset_w) { sync_offset = data & 0x0f; } -uint8_t ncr5390_device::conf_r() +READ8_MEMBER(ncr5390_device::conf_r) { return config; } -void ncr5390_device::conf_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::conf_w) { config = data; scsi_id = data & 7; @@ -1076,13 +1051,13 @@ void ncr5390_device::conf_w(uint8_t data) test_mode = true; } -void ncr5390_device::test_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::test_w) { if (test_mode) logerror("test_w %d (%s) - test mode not implemented\n", data, machine().describe_context()); } -void ncr5390_device::clock_w(uint8_t data) +WRITE8_MEMBER(ncr5390_device::clock_w) { clock_conv = data & 0x07; } @@ -1090,17 +1065,16 @@ void ncr5390_device::clock_w(uint8_t data) void ncr5390_device::dma_set(int dir) { dma_dir = dir; - - // account for data already in the fifo - if (dir == DMA_OUT && fifo_pos) - decrement_tcounter(fifo_pos); + if(dma_dir == DMA_OUT && fifo_pos != 16 && ((tcounter > fifo_pos) || !tcounter)) + drq_set(); } void ncr5390_device::dma_w(uint8_t val) { fifo_push(val); decrement_tcounter(); - check_drq(); + if(fifo_pos == 16 || (status & S_TC0)) + drq_clear(); step(false); } @@ -1108,41 +1082,34 @@ uint8_t ncr5390_device::dma_r() { uint8_t r = fifo_pop(); decrement_tcounter(); - check_drq(); + if(!fifo_pos || (status & S_TC0)) + drq_clear(); step(false); return r; } -void ncr5390_device::check_drq() +void ncr5390_device::drq_set() { - bool drq_state = drq; - - switch (dma_dir) { - case DMA_NONE: - drq_state = false; - break; - - case DMA_IN: // device to memory - drq_state = !(status & S_TC0) && fifo_pos; - break; - - case DMA_OUT: // memory to device - drq_state = !(status & S_TC0) && fifo_pos < 16; - break; + if(!drq) { + drq = true; + m_drq_handler(drq); } +} - if (drq_state != drq) { - drq = drq_state; +void ncr5390_device::drq_clear() +{ + if(drq) { + drq = false; m_drq_handler(drq); } } -void ncr5390_device::decrement_tcounter(int count) +void ncr5390_device::decrement_tcounter() { if (!dma_command) return; - tcounter -= count; + tcounter--; if (tcounter == 0) status |= S_TC0; } @@ -1175,14 +1142,14 @@ void ncr53c90a_device::device_start() ncr5390_device::device_start(); } -void ncr53c90a_device::device_reset() +void ncr53c90a_device::reset_soft() { config2 = 0; - ncr5390_device::device_reset(); + ncr5390_device::reset_soft(); } -uint8_t ncr53c90a_device::status_r() +READ8_MEMBER(ncr53c90a_device::status_r) { uint32_t ctrl = scsi_bus->ctrl_r(); uint8_t res = (irq ? S_INTERRUPT : 0) | status | (ctrl & S_MSG ? 4 : 0) | (ctrl & S_CTL ? 2 : 0) | (ctrl & S_INP ? 1 : 0); @@ -1213,75 +1180,9 @@ void ncr53c94_device::device_start() ncr53c90a_device::device_start(); } -void ncr53c94_device::device_reset() +void ncr53c94_device::reset_soft() { config3 = 0; - ncr53c90a_device::device_reset(); -} - -u16 ncr53c94_device::dma16_r() -{ - // check fifo underflow - if (fifo_pos < 2) - fatalerror("ncr53c94_device::dma16_r fifo_pos %d\n", fifo_pos); - - // pop two bytes from fifo - u16 const data = (fifo[0] << 8) | fifo[1]; - fifo_pos -= 2; - memmove(fifo, fifo + 2, fifo_pos); - - // update drq - decrement_tcounter(2); - check_drq(); - - step(false); - - return data; -} - -void ncr53c94_device::dma16_w(u16 data) -{ - // check fifo overflow - if (fifo_pos > 14) - fatalerror("ncr53c94_device::dma16_w fifo_pos %d\n", fifo_pos); - - // push two bytes into fifo - fifo[fifo_pos++] = data >> 8; - fifo[fifo_pos++] = data; - - // update drq - decrement_tcounter(2); - check_drq(); - - step(false); -} - -void ncr53c94_device::check_drq() -{ - if (m_busmd != BUSMD_0) - { - bool drq_state = drq; - - switch (dma_dir) { - case DMA_NONE: - drq_state = false; - break; - - case DMA_IN: // device to memory - drq_state = !(status & S_TC0) && fifo_pos > 1; - break; - - case DMA_OUT: // memory to device - drq_state = !(status & S_TC0) && fifo_pos < 15; - break; - } - - if (drq_state != drq) { - drq = drq_state; - m_drq_handler(drq); - } - } - else - ncr5390_device::check_drq(); + ncr53c90a_device::reset_soft(); } diff --git a/src/devices/machine/ncr5390.h b/src/devices/machine/ncr5390.h index 7cc2469bde5..bf301bed266 100644 --- a/src/devices/machine/ncr5390.h +++ b/src/devices/machine/ncr5390.h @@ -7,46 +7,59 @@ #include "machine/nscsi_bus.h" +#define MCFG_NCR5390_IRQ_HANDLER(_devcb) \ + downcast<ncr5390_device &>(*device).set_irq_handler(DEVCB_##_devcb); + +#define MCFG_NCR5390_DRQ_HANDLER(_devcb) \ + downcast<ncr5390_device &>(*device).set_drq_handler(DEVCB_##_devcb); + class ncr5390_device : public nscsi_device { public: ncr5390_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // configuration helpers + template <class Object> devcb_base &set_irq_handler(Object &&cb) { return m_irq_handler.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_drq_handler(Object &&cb) { return m_drq_handler.set_callback(std::forward<Object>(cb)); } + auto irq_handler_cb() { return m_irq_handler.bind(); } auto drq_handler_cb() { return m_drq_handler.bind(); } virtual void map(address_map &map); - uint8_t tcounter_lo_r(); - void tcount_lo_w(uint8_t data); - uint8_t tcounter_hi_r(); - void tcount_hi_w(uint8_t data); - uint8_t fifo_r(); - void fifo_w(uint8_t data); - uint8_t command_r(); - void command_w(uint8_t data); - virtual uint8_t status_r(); - void bus_id_w(uint8_t data); - uint8_t istatus_r(); - void timeout_w(uint8_t data); - uint8_t seq_step_r(); - void sync_period_w(uint8_t data); - uint8_t fifo_flags_r(); - void sync_offset_w(uint8_t data); - uint8_t conf_r(); - void conf_w(uint8_t data); - void test_w(uint8_t data); - void clock_w(uint8_t data); - - virtual uint8_t read(offs_t offset); - virtual void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(tcounter_lo_r); + DECLARE_WRITE8_MEMBER(tcount_lo_w); + DECLARE_READ8_MEMBER(tcounter_hi_r); + DECLARE_WRITE8_MEMBER(tcount_hi_w); + DECLARE_READ8_MEMBER(fifo_r); + DECLARE_WRITE8_MEMBER(fifo_w); + DECLARE_READ8_MEMBER(command_r); + DECLARE_WRITE8_MEMBER(command_w); + virtual DECLARE_READ8_MEMBER(status_r); + DECLARE_WRITE8_MEMBER(bus_id_w); + DECLARE_READ8_MEMBER(istatus_r); + DECLARE_WRITE8_MEMBER(timeout_w); + DECLARE_READ8_MEMBER(seq_step_r); + DECLARE_WRITE8_MEMBER(sync_period_w); + DECLARE_READ8_MEMBER(fifo_flags_r); + DECLARE_WRITE8_MEMBER(sync_offset_w); + DECLARE_READ8_MEMBER(conf_r); + DECLARE_WRITE8_MEMBER(conf_w); + DECLARE_WRITE8_MEMBER(test_w); + DECLARE_WRITE8_MEMBER(clock_w); + + virtual DECLARE_READ8_MEMBER(read); + virtual DECLARE_WRITE8_MEMBER(write); virtual void scsi_ctrl_changed() override; uint8_t dma_r(); void dma_w(uint8_t val); + // memory mapped wrappers for dma read/write + DECLARE_READ8_MEMBER(mdma_r) { return dma_r(); } + DECLARE_WRITE8_MEMBER(mdma_w) { dma_w(data); } + protected: ncr5390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -207,11 +220,13 @@ protected: bool test_mode; void dma_set(int dir); - virtual void check_drq(); + void drq_set(); + void drq_clear(); void start_command(); void step(bool timeout); virtual bool check_valid_command(uint8_t cmd); + int derive_msg_size(uint8_t msg_id); void function_complete(); void function_bus_complete(); void bus_complete(); @@ -220,6 +235,10 @@ protected: void command_pop_and_chain(); void check_irq(); +protected: + virtual void reset_soft(); + +private: void reset_disconnect(); uint8_t fifo_pop(); @@ -230,7 +249,7 @@ protected: void delay(int cycles); void delay_cycles(int cycles); - void decrement_tcounter(int count = 1); + void decrement_tcounter(); devcb_write_line m_irq_handler; devcb_write_line m_drq_handler; @@ -243,19 +262,19 @@ public: virtual void map(address_map &map) override; - virtual uint8_t status_r() override; + virtual DECLARE_READ8_MEMBER(status_r) override; - uint8_t conf2_r() { return config2; }; - void conf2_w(uint8_t data) { config2 = data; }; + DECLARE_READ8_MEMBER(conf2_r) { return config2; }; + DECLARE_WRITE8_MEMBER(conf2_w) { config2 = data; }; - virtual uint8_t read(offs_t offset) override; - virtual void write(offs_t offset, uint8_t data) override; + virtual DECLARE_READ8_MEMBER(read) override; + virtual DECLARE_WRITE8_MEMBER(write) override; protected: ncr53c90a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); virtual void device_start() override; - virtual void device_reset() override; + virtual void reset_soft() override; virtual bool check_valid_command(uint8_t cmd) override; @@ -264,18 +283,6 @@ protected: S_INTERRUPT = 0x80, }; - enum conf2_mask : u8 - { - PGDP = 0x01, // pass through/generate data parity - PGRP = 0x02, // pass through/generate register parity - ACDPE = 0x04, // abort on command/data parity error - S2FE = 0x08, // scsi-2 features enable - TSDR = 0x10, // tri-state dma request - SBO = 0x20, // select byte order - LSP = 0x40, // latch scsi phase - DAE = 0x80, // data alignment enable - }; - private: u8 config2; }; @@ -285,56 +292,26 @@ class ncr53c94_device : public ncr53c90a_device public: ncr53c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - enum busmd_t : u8 - { - BUSMD_0 = 0, // single bus: 8-bit host, 8 bit dma - BUSMD_1 = 1, // single bus: 8 bit host, 16 bit dma - BUSMD_2 = 2, // two buses: 8 bit multiplexed host, 16 bit dma - BUSMD_3 = 3, // two buses: 8 bit host, 16 bit dma - }; - void set_busmd(busmd_t const busmd) { m_busmd = busmd; } - virtual void map(address_map &map) override; - uint8_t conf3_r() { return config3; }; - void conf3_w(uint8_t data) { config3 = data; }; - void fifo_align_w(uint8_t data) { fifo_align = data; }; - - virtual uint8_t read(offs_t offset) override; - virtual void write(offs_t offset, uint8_t data) override; + DECLARE_READ8_MEMBER(conf3_r) { return config3; }; + DECLARE_WRITE8_MEMBER(conf3_w) { config3 = data; }; + DECLARE_WRITE8_MEMBER(fifo_align_w) { fifo_align = data; }; - u16 dma16_r(); - void dma16_w(u16 data); + virtual DECLARE_READ8_MEMBER(read) override; + virtual DECLARE_WRITE8_MEMBER(write) override; protected: - ncr53c94_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - enum conf3_mask : u8 - { - BS8 = 0x01, // burst size 8 - MDM = 0x02, // modify dma mode - LBTM = 0x04, // last byte transfer mode - }; - virtual void device_start() override; - virtual void device_reset() override; - virtual void check_drq() override; + virtual void reset_soft() override; private: u8 config3; u8 fifo_align; - busmd_t m_busmd; -}; - -class ncr53cf94_device : public ncr53c94_device -{ -public: - ncr53cf94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; DECLARE_DEVICE_TYPE(NCR5390, ncr5390_device) DECLARE_DEVICE_TYPE(NCR53C90A, ncr53c90a_device) DECLARE_DEVICE_TYPE(NCR53C94, ncr53c94_device) -DECLARE_DEVICE_TYPE(NCR53CF94, ncr53cf94_device) #endif // MAME_MACHINE_NCR5390_H diff --git a/src/devices/machine/ncr539x.cpp b/src/devices/machine/ncr539x.cpp index 09e0bee9f21..58c69a16ad1 100644 --- a/src/devices/machine/ncr539x.cpp +++ b/src/devices/machine/ncr539x.cpp @@ -280,7 +280,7 @@ void ncr539x_device::device_timer(emu_timer &timer, device_timer_id tid, int par } } -uint8_t ncr539x_device::read(offs_t offset) +READ8_MEMBER( ncr539x_device::read ) { uint8_t rv = 0; @@ -412,7 +412,7 @@ uint8_t ncr539x_device::read(offs_t offset) return rv; } -void ncr539x_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( ncr539x_device::write ) { //if (offset != 2) LOG("539x: Write %02x @ %s (%02x) (%s)\n", data, wrregs[offset], offset, machine().describe_context()); diff --git a/src/devices/machine/ncr539x.h b/src/devices/machine/ncr539x.h index 8172f4ea5f2..8caa26c25a1 100644 --- a/src/devices/machine/ncr539x.h +++ b/src/devices/machine/ncr539x.h @@ -14,6 +14,11 @@ // device stuff +#define MCFG_NCR539X_OUT_IRQ_CB(_devcb) \ + downcast<ncr539x_device &>(*device).set_out_irq_callback(DEVCB_##_devcb); + +#define MCFG_NCR539X_OUT_DRQ_CB(_devcb) \ + downcast<ncr539x_device &>(*device).set_out_drq_callback(DEVCB_##_devcb); class ncr539x_device : public legacy_scsi_host_adapter { @@ -21,12 +26,14 @@ public: // construction/destruction ncr539x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template <class Object> devcb_base &set_out_irq_callback(Object &&cb) { return m_out_irq_cb.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_out_drq_callback(Object &&cb) { return m_out_drq_cb.set_callback(std::forward<Object>(cb)); } auto irq_callback() { return m_out_irq_cb.bind(); } auto drq_callback() { return m_out_drq_cb.bind(); } // our API - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); void dma_read_data(int bytes, uint8_t *pData); void dma_write_data(int bytes, uint8_t *pData); diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp index 3e7580be5b9..648d435ace8 100644 --- a/src/devices/machine/netlist.cpp +++ b/src/devices/machine/netlist.cpp @@ -49,16 +49,21 @@ DEFINE_DEVICE_TYPE(NETLIST_STREAM_OUTPUT, netlist_mame_stream_output_device, "nl // Special netlist extension devices .... // ---------------------------------------------------------------------------------------- -class netlist_mame_device::netlist_mame_callbacks_t : public netlist::callbacks_t +class netlist_mame_device::netlist_mame_t : public netlist::netlist_t { public: - netlist_mame_callbacks_t(netlist_mame_device &parent) - : netlist::callbacks_t() + netlist_mame_t(netlist_mame_device &parent, const pstring &aname) + : netlist::netlist_t(aname) , m_parent(parent) { } + running_machine &machine() { return m_parent.machine(); } + + + netlist_mame_device &parent() { return m_parent; } + protected: void vlog(const plib::plog_level &l, const pstring &ls) const override { @@ -90,24 +95,6 @@ private: }; -class netlist_mame_device::netlist_mame_t : public netlist::netlist_t -{ -public: - - netlist_mame_t(netlist_mame_device &parent, const pstring &aname) - : netlist::netlist_t(aname, plib::make_unique<netlist_mame_device::netlist_mame_callbacks_t>(parent)) - , m_parent(parent) - { - } - - running_machine &machine() { return m_parent.machine(); } - netlist_mame_device &parent() { return m_parent; } - -private: - netlist_mame_device &m_parent; -}; - - namespace { // ---------------------------------------------------------------------------------------- @@ -117,13 +104,13 @@ namespace { class NETLIB_NAME(analog_callback) : public netlist::device_t { public: - NETLIB_NAME(analog_callback)(netlist::netlist_state_t &anetlist, const pstring &name) + NETLIB_NAME(analog_callback)(netlist::netlist_t &anetlist, const pstring &name) : device_t(anetlist, name) , m_in(*this, "IN") , m_cpu_device(nullptr) , m_last(*this, "m_last", 0) { - m_cpu_device = downcast<netlist_mame_cpu_device *>(&static_cast<netlist_mame_device::netlist_mame_t &>(exec()).parent()); + m_cpu_device = downcast<netlist_mame_cpu_device *>(&downcast<netlist_mame_device::netlist_mame_t &>(netlist()).parent()); } ATTR_COLD void reset() override @@ -144,7 +131,7 @@ public: // avoid calls due to noise if (std::fabs(cur - m_last) > 1e-6) { - m_cpu_device->update_icount(exec().time()); + m_cpu_device->update_time_x(); m_callback(cur, m_cpu_device->local_time()); m_cpu_device->check_mame_abort_slice(); m_last = cur; @@ -165,13 +152,13 @@ private: class NETLIB_NAME(logic_callback) : public netlist::device_t { public: - NETLIB_NAME(logic_callback)(netlist::netlist_state_t &anetlist, const pstring &name) + NETLIB_NAME(logic_callback)(netlist::netlist_t &anetlist, const pstring &name) : device_t(anetlist, name) , m_in(*this, "IN") , m_cpu_device(nullptr) , m_last(*this, "m_last", 0) { - m_cpu_device = downcast<netlist_mame_cpu_device *>(&static_cast<netlist_mame_device::netlist_mame_t &>(exec()).parent()); + m_cpu_device = downcast<netlist_mame_cpu_device *>(&downcast<netlist_mame_device::netlist_mame_t &>(netlist()).parent()); } ATTR_COLD void reset() override @@ -186,13 +173,13 @@ public: NETLIB_UPDATEI() { - netlist::netlist_sig_t cur = m_in(); + netlist_sig_t cur = m_in(); // FIXME: make this a parameter // avoid calls due to noise if (cur != m_last) { - m_cpu_device->update_icount(exec().time()); + m_cpu_device->update_time_x(); m_callback(cur, m_cpu_device->local_time()); m_cpu_device->check_mame_abort_slice(); m_last = cur; @@ -203,10 +190,9 @@ private: netlist::logic_input_t m_in; netlist_mame_logic_output_device::output_delegate m_callback; netlist_mame_cpu_device *m_cpu_device; - netlist::state_var<netlist::netlist_sig_t> m_last; + netlist::state_var<netlist_sig_t> m_last; }; - // ---------------------------------------------------------------------------------------- // Extensions to interface netlist with MAME code .... // ---------------------------------------------------------------------------------------- @@ -214,26 +200,22 @@ private: class netlist_source_memregion_t : public netlist::source_t { public: - netlist_source_memregion_t(device_t &dev, pstring name) - : netlist::source_t(), m_dev(dev), m_name(name) + netlist_source_memregion_t(netlist::setup_t &setup, pstring name) + : netlist::source_t(setup), m_name(name) { } - virtual plib::unique_ptr<plib::pistream> stream(const pstring &name) override; + virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override; private: - device_t &m_dev; pstring m_name; }; class netlist_data_memregions_t : public netlist::source_t { public: - netlist_data_memregions_t(device_t &dev); + netlist_data_memregions_t(netlist::setup_t &setup); - virtual plib::unique_ptr<plib::pistream> stream(const pstring &name) override; - -private: - device_t &m_dev; + virtual std::unique_ptr<plib::pistream> stream(const pstring &name) override; }; @@ -241,31 +223,30 @@ private: // memregion source support // ---------------------------------------------------------------------------------------- -plib::unique_ptr<plib::pistream> netlist_source_memregion_t::stream(const pstring &name) +std::unique_ptr<plib::pistream> netlist_source_memregion_t::stream(const pstring &name) { - //memory_region *mem = static_cast<netlist_mame_device::netlist_mame_t &>(setup().setup().exec()).machine().root_device().memregion(m_name.c_str()); - memory_region *mem = m_dev.machine().root_device().memregion(m_name.c_str()); - return plib::make_unique<plib::pimemstream>(mem->base(), mem->bytes()); + memory_region *mem = downcast<netlist_mame_device::netlist_mame_t &>(setup().netlist()).machine().root_device().memregion(m_name.c_str()); + return plib::make_unique_base<plib::pistream, plib::pimemstream>(mem->base(), mem->bytes()); } -netlist_data_memregions_t::netlist_data_memregions_t(device_t &dev) - : netlist::source_t(netlist::source_t::DATA), m_dev(dev) +netlist_data_memregions_t::netlist_data_memregions_t(netlist::setup_t &setup) + : netlist::source_t(setup, netlist::source_t::DATA) { } -plib::unique_ptr<plib::pistream> netlist_data_memregions_t::stream(const pstring &name) +std::unique_ptr<plib::pistream> netlist_data_memregions_t::stream(const pstring &name) { - //memory_region *mem = static_cast<netlist_mame_device::netlist_mame_t &>(setup().setup().exec()).parent().memregion(name.c_str()); - memory_region *mem = m_dev.memregion(name.c_str()); + memory_region *mem = downcast<netlist_mame_device::netlist_mame_t &>(setup().netlist()).parent().memregion(name.c_str()); + //memory_region *mem = downcast<netlist_mame_t &>(setup().netlist()).machine().root_device().memregion(name.c_str()); if (mem != nullptr) { - return plib::make_unique<plib::pimemstream>(mem->base(), mem->bytes()); + return plib::make_unique_base<plib::pistream, plib::pimemstream>(mem->base(), mem->bytes()); } else { // This should be the last data provider being called - last resort fatalerror("data named %s not found in device rom regions\n", name.c_str()); - return plib::unique_ptr<plib::pistream>(nullptr); + return std::unique_ptr<plib::pistream>(nullptr); } } @@ -280,55 +261,44 @@ plib::unique_ptr<plib::pistream> netlist_data_memregions_t::stream(const pstring class NETLIB_NAME(sound_out) : public netlist::device_t { public: - NETLIB_NAME(sound_out)(netlist::netlist_state_t &anetlist, const pstring &name) + NETLIB_NAME(sound_out)(netlist::netlist_t &anetlist, const pstring &name) : netlist::device_t(anetlist, name) , m_channel(*this, "CHAN", 0) , m_mult(*this, "MULT", 1000.0) , m_offset(*this, "OFFSET", 0.0) , m_buffer(nullptr) - , m_bufsize(0) - , m_sample_time(netlist::netlist_time::from_hz(1)) //sufficiently big enough + , m_sample(netlist::netlist_time::from_hz(1)) //sufficiently big enough , m_in(*this, "IN") , m_cur(0.0) , m_last_pos(0) - , m_last_buffer_time(*this, "m_last_buffer", netlist::netlist_time::zero()) + , m_last_buffer(*this, "m_last_buffer", netlist::netlist_time::zero()) { } - //static const int BUFSIZE = 2048; + static const int BUFSIZE = 2048; ATTR_COLD void reset() override { m_cur = 0.0; m_last_pos = 0; - m_last_buffer_time = netlist::netlist_time::zero(); + m_last_buffer = netlist::netlist_time::zero(); } ATTR_HOT void sound_update(const netlist::netlist_time &upto) { - int pos = (upto - m_last_buffer_time) / m_sample_time; - if (pos > m_bufsize) - throw emu_fatalerror("sound %s: pos %d exceeded bufsize %d\n", name().c_str(), pos, m_bufsize); + int pos = (upto - m_last_buffer) / m_sample; + if (pos >= BUFSIZE) + netlist().log().fatal("sound {1}: exceeded BUFSIZE\n", name().c_str()); while (m_last_pos < pos ) { m_buffer[m_last_pos++] = (stream_sample_t) m_cur; } } - ATTR_HOT void sound_update_fill(int samples) - { - if (samples > m_bufsize) - throw emu_fatalerror("sound %s: pos %d exceeded bufsize %d\n", name().c_str(), samples, m_bufsize); - while (m_last_pos < samples ) - { - m_buffer[m_last_pos++] = (stream_sample_t) m_cur; - } - } - NETLIB_UPDATEI() { nl_double val = m_in() * m_mult() + m_offset(); - sound_update(exec().time()); + sound_update(netlist().time()); /* ignore spikes */ if (std::abs(val) < 32767.0) m_cur = val; @@ -343,22 +313,21 @@ public: ATTR_HOT void buffer_reset(const netlist::netlist_time &upto) { m_last_pos = 0; - m_last_buffer_time = upto; + m_last_buffer = upto; + m_cur = 0.0; } netlist::param_int_t m_channel; netlist::param_double_t m_mult; netlist::param_double_t m_offset; stream_sample_t *m_buffer; - int m_bufsize; - - netlist::netlist_time m_sample_time; + netlist::netlist_time m_sample; private: netlist::analog_input_t m_in; double m_cur; int m_last_pos; - netlist::state_var<netlist::netlist_time> m_last_buffer_time; + netlist::state_var<netlist::netlist_time> m_last_buffer; }; // ---------------------------------------------------------------------------------------- @@ -368,57 +337,58 @@ private: class NETLIB_NAME(sound_in) : public netlist::device_t { public: - - static const int MAX_INPUT_CHANNELS = 16; - - NETLIB_NAME(sound_in)(netlist::netlist_state_t &anetlist, const pstring &name) + NETLIB_NAME(sound_in)(netlist::netlist_t &anetlist, const pstring &name) : netlist::device_t(anetlist, name) - , m_inc(netlist::netlist_time::from_nsec(1)) , m_feedback(*this, "FB") // clock part , m_Q(*this, "Q") , m_pos(0) - , m_num_channels(0) + , m_num_channel(0) { connect(m_feedback, m_Q); + m_inc = netlist::netlist_time::from_nsec(1); + for (int i = 0; i < MAX_INPUT_CHANNELS; i++) { - m_channels[i].m_param_name = netlist::pool().make_poolptr<netlist::param_str_t>(*this, plib::pfmt("CHAN{1}")(i), ""); - m_channels[i].m_param_mult = netlist::pool().make_poolptr<netlist::param_double_t>(*this, plib::pfmt("MULT{1}")(i), 1.0); - m_channels[i].m_param_offset = netlist::pool().make_poolptr<netlist::param_double_t>(*this, plib::pfmt("OFFSET{1}")(i), 0.0); + m_param_name[i] = std::make_unique<netlist::param_str_t>(*this, plib::pfmt("CHAN{1}")(i), ""); + m_param_mult[i] = std::make_unique<netlist::param_double_t>(*this, plib::pfmt("MULT{1}")(i), 1.0); + m_param_offset[i] = std::make_unique<netlist::param_double_t>(*this, plib::pfmt("OFFSET{1}")(i), 0.0); } } + static const int MAX_INPUT_CHANNELS = 10; + ATTR_COLD void reset() override { m_pos = 0; - for (auto & elem : m_channels) - elem.m_buffer = nullptr; + for (auto & elem : m_buffer) + elem = nullptr; } - ATTR_COLD void resolve() + ATTR_COLD int resolve() { m_pos = 0; for (int i = 0; i < MAX_INPUT_CHANNELS; i++) { - if ((*m_channels[i].m_param_name)() != pstring("")) + if ((*m_param_name[i])() != pstring("")) { - if (i != m_num_channels) - state().log().fatal("sound input numbering has to be sequential!"); - m_num_channels++; - m_channels[i].m_param = dynamic_cast<netlist::param_double_t *>(setup().find_param((*m_channels[i].m_param_name)(), true)); + if (i != m_num_channel) + netlist().log().fatal("sound input numbering has to be sequential!"); + m_num_channel++; + m_param[i] = dynamic_cast<netlist::param_double_t *>(setup().find_param((*m_param_name[i])(), true)); } } + return m_num_channel; } NETLIB_UPDATEI() { - for (int i=0; i<m_num_channels; i++) + for (int i=0; i<m_num_channel; i++) { - if (m_channels[i].m_buffer == nullptr) + if (m_buffer[i] == nullptr) break; // stop, called outside of stream_update - const nl_double v = m_channels[i].m_buffer[m_pos]; - m_channels[i].m_param->setTo(v * (*m_channels[i].m_param_mult)() + (*m_channels[i].m_param_offset)()); + const nl_double v = m_buffer[i][m_pos]; + m_param[i]->setTo(v * (*m_param_mult[i])() + (*m_param_offset[i])()); } m_pos++; m_Q.net().toggle_and_push_to_queue(m_inc); @@ -430,25 +400,19 @@ public: m_pos = 0; } - struct channel - { - netlist::pool_owned_ptr<netlist::param_str_t> m_param_name; - netlist::param_double_t *m_param; - stream_sample_t *m_buffer; - netlist::pool_owned_ptr<netlist::param_double_t> m_param_mult; - netlist::pool_owned_ptr<netlist::param_double_t> m_param_offset; - }; - channel m_channels[MAX_INPUT_CHANNELS]; + std::unique_ptr<netlist::param_str_t> m_param_name[MAX_INPUT_CHANNELS]; + netlist::param_double_t *m_param[MAX_INPUT_CHANNELS]; + stream_sample_t *m_buffer[MAX_INPUT_CHANNELS]; + std::unique_ptr<netlist::param_double_t> m_param_mult[MAX_INPUT_CHANNELS]; + std::unique_ptr<netlist::param_double_t> m_param_offset[MAX_INPUT_CHANNELS]; netlist::netlist_time m_inc; - int num_channels() { return m_num_channels; } - private: netlist::logic_input_t m_feedback; netlist::logic_output_t m_Q; int m_pos; - int m_num_channels; + int m_num_channel; }; @@ -467,25 +431,26 @@ private: netlist::setup_t &netlist_mame_device::setup() { - return m_netlist->nlstate().setup(); + return m_netlist->setup(); } -void netlist_mame_device::register_memregion_source(netlist::nlparse_t &setup, device_t &dev, const char *name) +void netlist_mame_device::register_memregion_source(netlist::setup_t &setup, const char *name) { - setup.register_source(plib::make_unique<netlist_source_memregion_t>(dev, pstring(name))); + setup.register_source(plib::make_unique_base<netlist::source_t, netlist_source_memregion_t>(setup, pstring(name, pstring::UTF8))); } void netlist_mame_analog_input_device::write(const double val) { - m_value_for_device_timer = val * m_mult + m_offset; - if (m_value_for_device_timer != (*m_param)()) - synchronize(0, 0, &m_value_for_device_timer); -} - -void netlist_mame_analog_input_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - update_to_current_time(); - m_param->setTo(*((double *) ptr)); + if (is_sound_device()) + { + update_to_current_time(); + m_param->setTo(val * m_mult + m_offset); + } + else + { + // FIXME: use device timer .... + m_param->setTo(val * m_mult + m_offset); + } } void netlist_mame_int_input_device::write(const uint32_t val) @@ -504,13 +469,15 @@ void netlist_mame_logic_input_device::write(const uint32_t val) void netlist_mame_int_input_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { - update_to_current_time(); + if (is_sound_device()) + update_to_current_time(); m_param->setTo(param); } void netlist_mame_logic_input_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { - update_to_current_time(); + if (is_sound_device()) + update_to_current_time(); m_param->setTo(param); } @@ -533,7 +500,7 @@ void netlist_mame_cpu_device::state_string_export(const device_state_entry &entr if (entry.index() & 1) str = string_format("%10.6f", *((double *)entry.dataptr())); else - str = string_format("%d", *((netlist::netlist_sig_t *)entry.dataptr())); + str = string_format("%d", *((netlist_sig_t *)entry.dataptr())); } } @@ -561,7 +528,7 @@ netlist_mame_analog_input_device::netlist_mame_analog_input_device(const machine void netlist_mame_analog_input_device::device_start() { LOGDEVCALLS("start\n"); - netlist::param_t *p = this->nl_owner().setup().find_param(pstring(m_param_name)); + netlist::param_t *p = this->nl_owner().setup().find_param(pstring(m_param_name, pstring::UTF8)); m_param = dynamic_cast<netlist::param_double_t *>(p); if (m_param == nullptr) { @@ -593,17 +560,16 @@ void netlist_mame_analog_output_device::set_params(const char *in_name, output_d m_delegate = std::move(adelegate); } -void netlist_mame_analog_output_device::custom_netlist_additions(netlist::netlist_state_t &nlstate) +void netlist_mame_analog_output_device::custom_netlist_additions(netlist::setup_t &setup) { - const pstring pin(m_in); + const pstring pin(m_in, pstring::UTF8); pstring dname = pstring("OUT_") + pin; - pstring dfqn = nlstate.setup().build_fqn(dname); m_delegate.bind_relative_to(owner()->machine().root_device()); - auto dev = netlist::pool().make_poolptr<NETLIB_NAME(analog_callback)>(nlstate, dfqn); + plib::owned_ptr<netlist::device_t> dev = plib::owned_ptr<netlist::device_t>::Create<NETLIB_NAME(analog_callback)>(setup.netlist(), setup.build_fqn(dname)); static_cast<NETLIB_NAME(analog_callback) *>(dev.get())->register_callback(std::move(m_delegate)); - nlstate.add_dev(dfqn, std::move(dev)); - nlstate.setup().register_link(dname + ".IN", pin); + setup.netlist().register_dev(std::move(dev)); + setup.register_link(dname + ".IN", pin); } void netlist_mame_analog_output_device::device_start() @@ -629,18 +595,16 @@ void netlist_mame_logic_output_device::set_params(const char *in_name, output_de m_delegate = std::move(adelegate); } -void netlist_mame_logic_output_device::custom_netlist_additions(netlist::netlist_state_t &nlstate) +void netlist_mame_logic_output_device::custom_netlist_additions(netlist::setup_t &setup) { - pstring pin(m_in); + pstring pin(m_in, pstring::UTF8); pstring dname = "OUT_" + pin; - pstring dfqn = nlstate.setup().build_fqn(dname); - m_delegate.bind_relative_to(owner()->machine().root_device()); - auto dev = netlist::pool().make_poolptr<NETLIB_NAME(logic_callback)>(nlstate, dfqn); + plib::owned_ptr<netlist::device_t> dev = plib::owned_ptr<netlist::device_t>::Create<NETLIB_NAME(logic_callback)>(setup.netlist(), setup.build_fqn(dname)); static_cast<NETLIB_NAME(logic_callback) *>(dev.get())->register_callback(std::move(m_delegate)); - nlstate.add_dev(dfqn, std::move(dev)); - nlstate.setup().register_link(dname + ".IN", pin); + setup.netlist().register_dev(std::move(dev)); + setup.register_link(dname + ".IN", pin); } void netlist_mame_logic_output_device::device_start() @@ -674,7 +638,7 @@ void netlist_mame_int_input_device::set_params(const char *param_name, const uin void netlist_mame_int_input_device::device_start() { LOGDEVCALLS("start\n"); - netlist::param_t *p = downcast<netlist_mame_device *>(this->owner())->setup().find_param(pstring(m_param_name)); + netlist::param_t *p = downcast<netlist_mame_device *>(this->owner())->setup().find_param(pstring(m_param_name, pstring::UTF8)); m_param = dynamic_cast<netlist::param_int_t *>(p); if (m_param == nullptr) { @@ -705,7 +669,7 @@ void netlist_mame_logic_input_device::set_params(const char *param_name, const u void netlist_mame_logic_input_device::device_start() { LOGDEVCALLS("start\n"); - netlist::param_t *p = downcast<netlist_mame_device *>(this->owner())->setup().find_param(pstring(m_param_name)); + netlist::param_t *p = downcast<netlist_mame_device *>(this->owner())->setup().find_param(pstring(m_param_name, pstring::UTF8)); m_param = dynamic_cast<netlist::param_logic_t *>(p); if (m_param == nullptr) { @@ -736,7 +700,7 @@ void netlist_mame_ram_pointer_device::set_params(const char *param_name) void netlist_mame_ram_pointer_device::device_start() { LOGDEVCALLS("start\n"); - netlist::param_t *p = downcast<netlist_mame_device *>(this->owner())->setup().find_param(pstring(m_param_name)); + netlist::param_t *p = downcast<netlist_mame_device *>(this->owner())->setup().find_param(pstring(m_param_name, pstring::UTF8)); m_param = dynamic_cast<netlist::param_ptr_t *>(p); if (m_param == nullptr) { @@ -769,17 +733,17 @@ void netlist_mame_stream_input_device::device_start() LOGDEVCALLS("start\n"); } -void netlist_mame_stream_input_device::custom_netlist_additions(netlist::netlist_state_t &nlstate) +void netlist_mame_stream_input_device::custom_netlist_additions(netlist::setup_t &setup) { - if (!nlstate.setup().device_exists("STREAM_INPUT")) - nlstate.setup().register_dev("NETDEV_SOUND_IN", "STREAM_INPUT"); + if (!setup.device_exists("STREAM_INPUT")) + setup.register_dev("NETDEV_SOUND_IN", "STREAM_INPUT"); pstring sparam = plib::pfmt("STREAM_INPUT.CHAN{1}")(m_channel); - nlstate.setup().register_param(sparam, pstring(m_param_name)); + setup.register_param(sparam, pstring(m_param_name, pstring::UTF8)); sparam = plib::pfmt("STREAM_INPUT.MULT{1}")(m_channel); - nlstate.setup().register_param(sparam, m_mult); + setup.register_param(sparam, m_mult); sparam = plib::pfmt("STREAM_INPUT.OFFSET{1}")(m_channel); - nlstate.setup().register_param(sparam, m_offset); + setup.register_param(sparam, m_offset); } // ---------------------------------------------------------------------------------------- @@ -805,18 +769,18 @@ void netlist_mame_stream_output_device::device_start() LOGDEVCALLS("start\n"); } -void netlist_mame_stream_output_device::custom_netlist_additions(netlist::netlist_state_t &nlstate) +void netlist_mame_stream_output_device::custom_netlist_additions(netlist::setup_t &setup) { //NETLIB_NAME(sound_out) *snd_out; pstring sname = plib::pfmt("STREAM_OUT_{1}")(m_channel); //snd_out = dynamic_cast<NETLIB_NAME(sound_out) *>(setup.register_dev("nld_sound_out", sname)); - nlstate.setup().register_dev("NETDEV_SOUND_OUT", sname); + setup.register_dev("NETDEV_SOUND_OUT", sname); - nlstate.setup().register_param(sname + ".CHAN" , m_channel); - nlstate.setup().register_param(sname + ".MULT", m_mult); - nlstate.setup().register_param(sname + ".OFFSET", m_offset); - nlstate.setup().register_link(sname + ".IN", pstring(m_out_name)); + setup.register_param(sname + ".CHAN" , m_channel); + setup.register_param(sname + ".MULT", m_mult); + setup.register_param(sname + ".OFFSET", m_offset); + setup.register_link(sname + ".IN", pstring(m_out_name, pstring::UTF8)); } @@ -833,6 +797,7 @@ netlist_mame_device::netlist_mame_device(const machine_config &mconfig, device_t : device_t(mconfig, type, tag, owner, clock) , m_icount(0) , m_old(netlist::netlist_time::zero()) + , m_netlist(nullptr) , m_setup_func(nullptr) { } @@ -842,6 +807,12 @@ netlist_mame_device::~netlist_mame_device() LOGDEVCALLS("~netlist_mame_device\n"); } +void netlist_mame_device::set_constructor(void (*setup_func)(netlist::setup_t &)) +{ + if (LOG_DEV_CALLS) logerror("set_constructor\n"); + m_setup_func = setup_func; +} + void netlist_mame_device::device_config_complete() { LOGDEVCALLS("device_config_complete %s\n", this->mconfig().gamedrv().name); @@ -859,7 +830,7 @@ void netlist_mame_device::device_start() //printf("clock is %d\n", clock()); - m_netlist = netlist::pool().make_poolptr<netlist_mame_t>(*this, "netlist"); + m_netlist = global_alloc(netlist_mame_t(*this, "netlist")); // register additional devices @@ -872,12 +843,12 @@ void netlist_mame_device::device_start() if( sdev != nullptr ) { LOGDEVCALLS("Preparse subdevice %s/%s\n", d.name(), d.shortname()); - sdev->pre_parse_action(m_netlist->nlstate()); + sdev->pre_parse_action(setup()); } } /* add default data provider for roms */ - setup().register_source(plib::make_unique<netlist_data_memregions_t>(*this)); + setup().register_source(plib::make_unique_base<netlist::source_t, netlist_data_memregions_t>(setup())); m_setup_func(setup()); @@ -888,15 +859,15 @@ void netlist_mame_device::device_start() if( sdev != nullptr ) { LOGDEVCALLS("Found subdevice %s/%s\n", d.name(), d.shortname()); - sdev->custom_netlist_additions(m_netlist->nlstate()); + sdev->custom_netlist_additions(setup()); } } - setup().prepare_to_run(); + netlist().start(); - netlist().nlstate().save(*this, m_rem, this->name(), "m_rem"); - netlist().nlstate().save(*this, m_div, this->name(), "m_div"); - netlist().nlstate().save(*this, m_old, this->name(), "m_old"); + netlist().save(*this, m_rem, "m_rem"); + netlist().save(*this, m_div, "m_div"); + netlist().save(*this, m_old, "m_old"); save_state(); @@ -925,26 +896,29 @@ void netlist_mame_device::device_stop() { LOGDEVCALLS("device_stop\n"); netlist().stop(); + + global_free(m_netlist); + m_netlist = nullptr; } ATTR_COLD void netlist_mame_device::device_post_load() { LOGDEVCALLS("device_post_load\n"); - netlist().run_state_manager().post_load(); - netlist().nlstate().rebuild_lists(); + netlist().state().post_load(); + netlist().rebuild_lists(); } ATTR_COLD void netlist_mame_device::device_pre_save() { LOGDEVCALLS("device_pre_save\n"); - netlist().run_state_manager().pre_save(); + netlist().state().pre_save(); } -void netlist_mame_device::update_icount(netlist::netlist_time time) +void netlist_mame_device::update_time_x() { - const netlist::netlist_time newt(time); + const netlist::netlist_time newt(netlist().time()); const netlist::netlist_time delta(newt - m_old + m_rem); const uint64_t d = delta / m_div; m_old = newt; @@ -960,7 +934,7 @@ void netlist_mame_device::check_mame_abort_slice() ATTR_COLD void netlist_mame_device::save_state() { - for (auto const & s : netlist().run_state_manager().save_list()) + for (auto const & s : netlist().state().save_list()) { netlist().log().debug("saving state for {1}\n", s->m_name.c_str()); if (s->m_dt.is_float) @@ -1023,18 +997,17 @@ void netlist_mame_cpu_device::device_start() state_add(STATE_GENPC, "GENPC", m_genPC).noshow(); state_add(STATE_GENPCBASE, "CURPC", m_genPC).noshow(); - int index = 0; - for (auto &n : netlist().nlstate().nets()) + for (int i=0; i < netlist().m_nets.size(); i++) { + netlist::detail::net_t *n = netlist().m_nets[i].get(); if (n->is_logic()) { - state_add(index, n->name().c_str(), *(downcast<netlist::logic_net_t &>(*n).Q_state_ptr())); + state_add(i*2, n->name().c_str(), *downcast<netlist::logic_net_t *>(n)->Q_state_ptr()); } else { - state_add(index, n->name().c_str(), *(downcast<netlist::analog_net_t &>(*n).Q_Analog_state_ptr())); + state_add(i*2+1, n->name().c_str(), *downcast<netlist::analog_net_t *>(n)->Q_Analog_state_ptr()); } - index++; } // set our instruction counter @@ -1059,8 +1032,10 @@ ATTR_COLD uint64_t netlist_mame_cpu_device::execute_cycles_to_clocks(uint64_t cy ATTR_HOT void netlist_mame_cpu_device::execute_run() { + bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0); + // debugging //m_ppc = m_pc; // copy PC to previous PC - if (debugger_enabled()) + if (check_debugger) { while (m_icount > 0) { @@ -1068,13 +1043,13 @@ ATTR_HOT void netlist_mame_cpu_device::execute_run() m_genPC &= 255; debugger_instruction_hook(m_genPC); netlist().process_queue(m_div); - update_icount(netlist().time()); + update_time_x(); } } else { netlist().process_queue(m_div * m_icount); - update_icount(netlist().time()); + update_time_x(); } } @@ -1114,8 +1089,11 @@ offs_t netlist_disassembler::disassemble(std::ostream &stream, offs_t pc, const netlist_mame_sound_device::netlist_mame_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : netlist_mame_device(mconfig, NETLIST_SOUND, tag, owner, clock) , device_sound_interface(mconfig, *this) + , m_out{nullptr} , m_in(nullptr) , m_stream(nullptr) + , m_num_inputs(0) + , m_num_outputs(0) { } @@ -1127,45 +1105,44 @@ void netlist_mame_sound_device::device_start() // Configure outputs - std::vector<nld_sound_out *> outdevs = netlist().nlstate().get_device_list<nld_sound_out>(); + std::vector<nld_sound_out *> outdevs = netlist().get_device_list<nld_sound_out>(); if (outdevs.size() == 0) fatalerror("No output devices"); - //m_num_outputs = outdevs.size(); + m_num_outputs = outdevs.size(); /* resort channels */ - for (auto &outdev : outdevs) + for (int i=0; i < MAX_OUT; i++) m_out[i] = nullptr; + for (int i=0; i < m_num_outputs; i++) { - int chan = outdev->m_channel(); + int chan = outdevs[i]->m_channel(); - netlist().log().verbose("Output %s on channel %d", outdev->name(), chan); + netlist().log().verbose("Output %d on channel %d", i, chan); - if (chan < 0 || chan >= outdevs.size()) + if (chan < 0 || chan >= MAX_OUT || chan >= outdevs.size()) fatalerror("illegal channel number"); - m_out[chan] = outdev; - m_out[chan]->m_sample_time = netlist::netlist_time::from_hz(clock()); + m_out[chan] = outdevs[i]; + m_out[chan]->m_sample = netlist::netlist_time::from_hz(clock()); m_out[chan]->m_buffer = nullptr; - m_out[chan]->m_bufsize = 0; } // Configure inputs - // FIXME: The limitation to one input device seems artificial. - // We should allow multiple devices with one channel each. + m_num_inputs = 0; m_in = nullptr; - std::vector<nld_sound_in *> indevs = netlist().nlstate().get_device_list<nld_sound_in>(); + std::vector<nld_sound_in *> indevs = netlist().get_device_list<nld_sound_in>(); if (indevs.size() > 1) fatalerror("A maximum of one input device is allowed!"); if (indevs.size() == 1) { m_in = indevs[0]; - m_in->resolve(); + m_num_inputs = m_in->resolve(); m_in->m_inc = netlist::netlist_time::from_hz(clock()); } /* initialize the stream(s) */ - m_stream = machine().sound().stream_alloc(*this, m_in ? m_in->num_channels() : 0, m_out.size(), clock()); + m_stream = machine().sound().stream_alloc(*this, m_num_inputs, m_num_outputs, clock()); } @@ -1178,21 +1155,17 @@ void netlist_mame_sound_device::nl_register_devices() void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { - - for (auto &e : m_out) + for (int i=0; i < m_num_outputs; i++) { - e.second->m_buffer = outputs[e.first]; - e.second->m_bufsize = samples; + m_out[i]->m_buffer = outputs[i]; } + if (m_num_inputs) + m_in->buffer_reset(); - if (m_in) + for (int i=0; i < m_num_inputs; i++) { - m_in->buffer_reset(); - for (int i=0; i < m_in->num_channels(); i++) - { - m_in->m_channels[i].m_buffer = inputs[i]; - } + m_in->m_buffer[i] = inputs[i]; } netlist::netlist_time cur(netlist().time()); @@ -1201,9 +1174,9 @@ void netlist_mame_sound_device::sound_stream_update(sound_stream &stream, stream cur += (m_div * samples); - for (auto &e : m_out) + for (int i=0; i < m_num_outputs; i++) { - e.second->sound_update_fill(samples); - e.second->buffer_reset(cur); + m_out[i]->sound_update(cur); + m_out[i]->buffer_reset(cur); } } diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h index 639223d2842..36bdcb0c415 100644 --- a/src/devices/machine/netlist.h +++ b/src/devices/machine/netlist.h @@ -11,19 +11,16 @@ #ifndef MAME_MACHINE_NETLIST_H #define MAME_MACHINE_NETLIST_H -#include <functional> - -#include "../../lib/netlist/nltypes.h" +#include "netlist/nl_time.h" class nld_sound_out; class nld_sound_in; namespace netlist { class setup_t; - class netlist_state_t; - class nlparse_t; - template <typename T> - class param_num_t; + class param_double_t; + class param_int_t; + class param_logic_t; class param_ptr_t; } @@ -34,9 +31,6 @@ namespace netlist { #define MCFG_NETLIST_SETUP(_setup) \ downcast<netlist_mame_device &>(*device).set_constructor(NETLIST_NAME(_setup)); -#define MCFG_NETLIST_SETUP_MEMBER(_obj, _setup) \ - downcast<netlist_mame_device &>(*device).set_constructor(_obj, _setup); - #define MCFG_NETLIST_ANALOG_INPUT(_basetag, _tag, _name) \ MCFG_DEVICE_ADD(_basetag ":" _tag, NETLIST_ANALOG_INPUT, 0) \ downcast<netlist_mame_analog_input_device &>(*device).set_name(_name); @@ -85,10 +79,9 @@ namespace netlist { #define NETLIST_ANALOG_PORT_CHANGED(_base, _tag) \ PORT_CHANGED_MEMBER(_base ":" _tag, netlist_mame_analog_input_device, input_changed, 0) -/* This macro can only be called from device member */ #define MEMREGION_SOURCE(_name) \ - netlist_mame_device::register_memregion_source(setup, *this, _name); + netlist_mame_device::register_memregion_source(setup, _name); #define NETDEV_ANALOG_CALLBACK_MEMBER(_name) \ void _name(const double data, const attotime &time) @@ -106,32 +99,21 @@ class netlist_mame_device : public device_t { public: class netlist_mame_t; - class netlist_mame_callbacks_t; - - using func_type = std::function<void(netlist::nlparse_t &)>; // construction/destruction netlist_mame_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); virtual ~netlist_mame_device(); - void set_constructor(void (*setup_func)(netlist::nlparse_t &)) - { - m_setup_func = func_type(setup_func); - } - - template <typename T, typename F> - void set_constructor(T *obj, F && f) - { - m_setup_func = std::move(std::bind(std::forward<F>(f), obj, std::placeholders::_1)); - } + void set_constructor(void (*setup_func)(netlist::setup_t &)); ATTR_HOT inline netlist::setup_t &setup(); ATTR_HOT inline netlist_mame_t &netlist() { return *m_netlist; } - ATTR_HOT void update_icount(netlist::netlist_time time); + ATTR_HOT inline const netlist::netlist_time last_time_update() { return m_old; } + ATTR_HOT void update_time_x(); ATTR_HOT void check_mame_abort_slice(); - static void register_memregion_source(netlist::nlparse_t &setup, device_t &dev, const char *name); + static void register_memregion_source(netlist::setup_t &setup, const char *name); int m_icount; @@ -160,9 +142,9 @@ private: netlist::netlist_time m_rem; netlist::netlist_time m_old; - netlist::pool_owned_ptr<netlist_mame_t> m_netlist; + netlist_mame_t * m_netlist; - func_type m_setup_func; + void (*m_setup_func)(netlist::setup_t &); }; // ---------------------------------------------------------------------------------------- @@ -249,9 +231,13 @@ protected: virtual void device_start() override; private: - std::map<int, nld_sound_out *> m_out; + static constexpr int MAX_OUT = 10; + nld_sound_out *m_out[MAX_OUT]; nld_sound_in *m_in; sound_stream *m_stream; + int m_num_inputs; + int m_num_outputs; + }; // ---------------------------------------------------------------------------------------- @@ -269,16 +255,14 @@ public: { } - virtual void custom_netlist_additions(netlist::netlist_state_t &nlstate) { } - virtual void pre_parse_action(netlist::netlist_state_t &nlstate) { } + virtual void custom_netlist_additions(netlist::setup_t &setup) { } + virtual void pre_parse_action(netlist::setup_t &setup) { } inline netlist_mame_device &nl_owner() const { return *m_owner; } - inline void update_to_current_time() - { - if (m_sound != nullptr) - m_sound->get_stream()->update(); - } + inline bool is_sound_device() const { return bool(m_sound); } + + inline void update_to_current_time() { m_sound->get_stream()->update(); } void set_mult_offset(const double mult, const double offset); @@ -322,13 +306,11 @@ public: protected: // device-level overrides virtual void device_start() override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; private: - netlist::param_num_t<double> *m_param; + netlist::param_double_t *m_param; bool m_auto_port; const char *m_param_name; - double m_value_for_device_timer; }; // ---------------------------------------------------------------------------------------- @@ -348,7 +330,7 @@ public: protected: // device-level overrides virtual void device_start() override; - virtual void custom_netlist_additions(netlist::netlist_state_t &nlstate) override; + virtual void custom_netlist_additions(netlist::setup_t &setup) override; private: const char *m_in; @@ -380,7 +362,7 @@ public: protected: // device-level overrides virtual void device_start() override; - virtual void custom_netlist_additions(netlist::netlist_state_t &nlstate) override; + virtual void custom_netlist_additions(netlist::setup_t &setup) override; private: const char *m_in; @@ -420,7 +402,7 @@ protected: virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; private: - netlist::param_num_t<int> *m_param; + netlist::param_int_t *m_param; uint32_t m_mask; uint32_t m_shift; const char *m_param_name; @@ -459,7 +441,7 @@ protected: virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; private: - netlist::param_num_t<bool> *m_param; + netlist::param_logic_t *m_param; uint32_t m_shift; const char *m_param_name; }; @@ -509,7 +491,7 @@ public: protected: // device-level overrides virtual void device_start() override; - virtual void custom_netlist_additions(netlist::netlist_state_t &nlstate) override; + virtual void custom_netlist_additions(netlist::setup_t &setup) override; private: uint32_t m_channel; const char *m_param_name; @@ -535,7 +517,7 @@ public: protected: // device-level overrides virtual void device_start() override; - virtual void custom_netlist_additions(netlist::netlist_state_t &nlstate) override; + virtual void custom_netlist_additions(netlist::setup_t &setup) override; private: uint32_t m_channel; diff --git a/src/devices/machine/nmc9306.h b/src/devices/machine/nmc9306.h index 07aa6b36db0..097742685aa 100644 --- a/src/devices/machine/nmc9306.h +++ b/src/devices/machine/nmc9306.h @@ -19,6 +19,17 @@ #pragma once + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_NMC9306_ADD(tag) \ + MCFG_DEVICE_ADD((tag), NMC9306, 0) + + + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** diff --git a/src/devices/machine/nsc810.cpp b/src/devices/machine/nsc810.cpp index 96a13e7b696..bf06c34d9dc 100644 --- a/src/devices/machine/nsc810.cpp +++ b/src/devices/machine/nsc810.cpp @@ -118,7 +118,7 @@ void nsc810_device::device_timer(emu_timer &timer, device_timer_id id, int param } } -uint8_t nsc810_device::read(offs_t offset) +READ8_MEMBER(nsc810_device::read) { uint8_t res = 0xff; @@ -191,7 +191,7 @@ uint8_t nsc810_device::read(offs_t offset) return res; } -void nsc810_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(nsc810_device::write) { uint32_t rate; diff --git a/src/devices/machine/nsc810.h b/src/devices/machine/nsc810.h index 520591208f7..bebeb8f82a6 100644 --- a/src/devices/machine/nsc810.h +++ b/src/devices/machine/nsc810.h @@ -16,38 +16,24 @@ class nsc810_device : public device_t { public: // construction/destruction - nsc810_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t clk0, uint32_t clk1) - : nsc810_device(mconfig, tag, owner, clock) - { - set_timer0_clock(clk0); - set_timer1_clock(clk1); - } - - nsc810_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const XTAL &clk0, const XTAL &clk1) - : nsc810_device(mconfig, tag, owner, clock) - { - set_timer0_clock(clk0.value()); - set_timer1_clock(clk1.value()); - } - nsc810_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - auto portA_read_callback() { return m_portA_r.bind(); } - auto portB_read_callback() { return m_portB_r.bind(); } - auto portC_read_callback() { return m_portC_r.bind(); } - auto portA_write_callback() { return m_portA_w.bind(); } - auto portB_write_callback() { return m_portB_w.bind(); } - auto portC_write_callback() { return m_portC_w.bind(); } - auto timer0_callback() { return m_timer0_out.bind(); } - auto timer1_callback() { return m_timer1_out.bind(); } + template <class Object> devcb_base &set_portA_read_callback(Object &&cb) { return m_portA_r.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_portB_read_callback(Object &&cb) { return m_portB_r.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_portC_read_callback(Object &&cb) { return m_portC_r.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_portA_write_callback(Object &&cb) { return m_portA_w.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_portB_write_callback(Object &&cb) { return m_portB_w.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_portC_write_callback(Object &&cb) { return m_portC_w.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_timer0_callback(Object &&cb) { return m_timer0_out.set_callback(std::forward<Object>(cb)); } + template <class Object> devcb_base &set_timer1_callback(Object &&cb) { return m_timer1_out.set_callback(std::forward<Object>(cb)); } void set_timer0_clock(uint32_t clk) { m_timer0_clock = clk; } void set_timer0_clock(const XTAL &clk) { set_timer0_clock(clk.value()); } void set_timer1_clock(uint32_t clk) { m_timer1_clock = clk; } void set_timer1_clock(const XTAL &clk) { set_timer1_clock(clk.value()); } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); protected: virtual void device_start() override; @@ -116,6 +102,35 @@ private: }; }; +#define MCFG_NSC810_ADD(_tag, _t0clk, _t1clk) \ + MCFG_DEVICE_ADD(_tag, NSC810, 0) \ + downcast<nsc810_device *>(device)->set_timer0_clock(_t0clk); \ + downcast<nsc810_device *>(device)->set_timer1_clock(_t1clk); + +#define MCFG_NSC810_PORTA_READ(_read) \ + downcast<nsc810_device &>(*device).set_portA_read_callback(DEVCB_##_read); + +#define MCFG_NSC810_PORTB_READ(_read) \ + downcast<nsc810_device &>(*device).set_portB_read_callback(DEVCB_##_read); + +#define MCFG_NSC810_PORTC_READ(_read) \ + downcast<nsc810_device &>(*device).set_portC_read_callback(DEVCB_##_read); + +#define MCFG_NSC810_PORTA_WRITE(_write) \ + downcast<nsc810_device &>(*device).set_portA_write_callback(DEVCB_##_write); + +#define MCFG_NSC810_PORTB_WRITE(_write) \ + downcast<nsc810_device &>(*device).set_portB_write_callback(DEVCB_##_write); + +#define MCFG_NSC810_PORTC_WRITE(_write) \ + downcast<nsc810_device &>(*device).set_portC_write_callback(DEVCB_##_write); + +#define MCFG_NSC810_TIMER0_OUT(_write) \ + downcast<nsc810_device &>(*device).set_timer0_callback(DEVCB_##_write); + +#define MCFG_NSC810_TIMER1_OUT(_write) \ + downcast<nsc810_device &>(*device).set_timer1_callback(DEVCB_##_write); + // device type definition DECLARE_DEVICE_TYPE(NSC810, nsc810_device) diff --git a/src/devices/machine/nscsi_bus.cpp b/src/devices/machine/nscsi_bus.cpp index ef3c0dd9f9a..328dd7239bd 100644 --- a/src/devices/machine/nscsi_bus.cpp +++ b/src/devices/machine/nscsi_bus.cpp @@ -3,15 +3,13 @@ #include "emu.h" #include "nscsi_bus.h" -#define LOG_GENERAL (1U << 0) -#define LOG_UNSUPPORTED (1U << 1) -#define LOG_STATE (1U << 2) -#define LOG_CONTROL (1U << 3) -#define LOG_DATA (1U << 4) -#define LOG_DATA_SENT (1U << 5) +#define LOG_GENERAL (1U << 0) +#define LOG_STATE (1U << 1) +#define LOG_CONTROL (1U << 2) +#define LOG_DATA (1U << 3) //#define VERBOSE (LOG_GENERAL | LOG_STATE | LOG_CONTROL | LOG_DATA) -#define VERBOSE (LOG_UNSUPPORTED | LOG_DATA_SENT) +#define VERBOSE 0 #include "logmacro.h" @@ -442,7 +440,7 @@ void nscsi_full_device::step(bool timeout) break; } - if(scsi_command_done(scsi_cmdbuf[0], data_buffer_pos)) { + if(command_done()) { scsi_cmdsize = data_buffer_pos; scsi_bus->ctrl_wait(scsi_refid, 0, S_ACK); scsi_command(); @@ -509,17 +507,18 @@ void nscsi_full_device::target_send_buffer_byte() target_send_byte(scsi_get_data(data_buffer_id, data_buffer_pos++)); } -bool nscsi_full_device::scsi_command_done(uint8_t command, uint8_t length) +bool nscsi_full_device::command_done() { - if(!length) + if(!data_buffer_pos) return false; - switch(command >> 5) { - case 0: return length == 6; - case 1: return length == 10; - case 2: return length == 10; + uint8_t h = scsi_cmdbuf[0]; + switch(h >> 5) { + case 0: return data_buffer_pos == 6; + case 1: return data_buffer_pos == 10; + case 2: return data_buffer_pos == 10; case 3: return true; case 4: return true; - case 5: return length == 12; + case 5: return data_buffer_pos == 12; case 6: return true; case 7: return true; } @@ -563,17 +562,6 @@ void nscsi_full_device::scsi_status_complete(uint8_t st) void nscsi_full_device::scsi_data_in(int buf, int size) { - if((VERBOSE & LOG_DATA_SENT) && buf == 0) { - std::string dt = ""; - int sz = size; - if(sz > 50) - sz = 50; - for(int i=0; i<sz; i++) - dt += util::string_format(" %02x", scsi_cmdbuf[i]); - if(size > sz) - dt += " ..."; - LOGMASKED(LOG_DATA_SENT, "Sending data (%d)%s\n", size, dt); - } control *c; c = buf_control_push(); c->action = BC_DATA_IN; @@ -595,28 +583,31 @@ void nscsi_full_device::sense(bool deferred, uint8_t key, uint8_t asc, uint8_t a memset(scsi_sense_buffer, 0, sizeof(scsi_sense_buffer)); scsi_sense_buffer[0] = deferred ? 0x71 : 0x70; scsi_sense_buffer[2] = key; - scsi_sense_buffer[7] = sizeof(scsi_sense_buffer) - 8; scsi_sense_buffer[12] = asc; scsi_sense_buffer[13] = ascq; } void nscsi_full_device::scsi_unknown_command() { - std::string txt = util::string_format("Unhandled command %s (%d):", command_names[scsi_cmdbuf[0]], scsi_cmdsize); + LOG("Unhandled command %s", command_names[scsi_cmdbuf[0]]); for(int i=0; i != scsi_cmdsize; i++) - txt += util::string_format(" %02x", scsi_cmdbuf[i]); - LOGMASKED(LOG_UNSUPPORTED, "%s\n", txt); + logerror(" %02x", scsi_cmdbuf[i]); + logerror("\n"); scsi_status_complete(SS_CHECK_CONDITION); - sense(false, SK_ILLEGAL_REQUEST); + sense(false, 5); } void nscsi_full_device::scsi_command() { switch(scsi_cmdbuf[0]) { case SC_REQUEST_SENSE: - LOG("command REQUEST SENSE alloc=%d\n", scsi_cmdbuf[4]); - scsi_data_in(SBUF_SENSE, scsi_cmdbuf[4] ? std::min(scsi_cmdbuf[4], u8(sizeof(scsi_sense_buffer))) : 4); + LOG("command REQUEST SENSE\n"); + /* + * Targets shall be capable of returning eighteen bytes of data in + * response to a REQUEST SENSE command. + */ + scsi_data_in(SBUF_SENSE, 18); scsi_status_complete(SS_GOOD); break; default: @@ -632,10 +623,10 @@ void nscsi_full_device::scsi_message() return; } - std::string txt = "Unknown message"; + LOG("Unknown message"); for(int i=0; i != scsi_cmdsize; i++) - txt += util::string_format(" %02x", scsi_cmdbuf[i]); - LOGMASKED(LOG_UNSUPPORTED, "%s\n", txt); + logerror(" %02x", scsi_cmdbuf[i]); + logerror("\n"); } int nscsi_full_device::get_lun(int def) @@ -649,7 +640,9 @@ int nscsi_full_device::get_lun(int def) void nscsi_full_device::bad_lun() { scsi_status_complete(SS_CHECK_CONDITION); - sense(false, SK_ILLEGAL_REQUEST, SK_ASC_LOGICAL_UNIT_NOT_SUPPORTED); + + // key:illegal request, asc:logical unit not supported + sense(false, 5, 0x25); } // Arbitration delay (2.4us) diff --git a/src/devices/machine/nscsi_bus.h b/src/devices/machine/nscsi_bus.h index 244eda94fe8..5e7d7dcecab 100644 --- a/src/devices/machine/nscsi_bus.h +++ b/src/devices/machine/nscsi_bus.h @@ -6,12 +6,19 @@ #pragma once +#define MCFG_NSCSI_BUS_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, NSCSI_BUS, 0) + +#define MCFG_NSCSI_ADD(_tag, _slot_intf, _def_slot, _fixed) \ + MCFG_DEVICE_ADD(_tag, NSCSI_CONNECTOR, 0) \ + MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _fixed) + class nscsi_device; class nscsi_bus_device : public device_t { public: - nscsi_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + nscsi_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); void ctrl_w(int refid, uint32_t lines, uint32_t mask); void data_w(int refid, uint32_t lines); @@ -42,19 +49,10 @@ private: }; class nscsi_connector: public device_t, - public device_slot_interface + public device_slot_interface { public: - template <typename T> - nscsi_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed = false) - : nscsi_connector(mconfig, tag, owner, 0) - { - option_reset(); - opts(*this); - set_default_option(dflt); - set_fixed(fixed); - } - nscsi_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + nscsi_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); virtual ~nscsi_connector(); nscsi_device *get_device(); @@ -169,9 +167,7 @@ protected: // SCSI addtional sense code qualifiers enum { - SK_ASC_INVALID_FIELD_IN_CDB = 0x24, - SK_ASC_LOGICAL_UNIT_NOT_SUPPORTED = 0x25, - SK_ASC_MEDIUM_NOT_PRESENT = 0x3a + SK_ASC_MEDIUM_NOT_PRESENT = 0x3a }; // SCSI commands @@ -308,7 +304,6 @@ protected: virtual void scsi_message(); virtual void scsi_command(); - virtual bool scsi_command_done(uint8_t command, uint8_t length); void scsi_unknown_command(); void scsi_status_complete(uint8_t st); @@ -449,6 +444,7 @@ private: void target_recv_byte(); void target_send_byte(uint8_t val); void target_send_buffer_byte(); + bool command_done(); }; diff --git a/src/devices/machine/nscsi_cb.h b/src/devices/machine/nscsi_cb.h index 575e8f19298..b5156935a98 100644 --- a/src/devices/machine/nscsi_cb.h +++ b/src/devices/machine/nscsi_cb.h @@ -8,20 +8,48 @@ #include "machine/nscsi_bus.h" +#define MCFG_NSCSICB_RST_HANDLER(_line) \ + downcast<nscsi_callback_device *>(device)->set_rst_callback(DEVCB_##_line); + +#define MCFG_NSCSICB_ATN_HANDLER(_line) \ + downcast<nscsi_callback_device *>(device)->set_atn_callback(DEVCB_##_line); + +#define MCFG_NSCSICB_ACK_HANDLER(_line) \ + downcast<nscsi_callback_device *>(device)->set_ack_callback(DEVCB_##_line); + +#define MCFG_NSCSICB_REQ_HANDLER(_line) \ + downcast<nscsi_callback_device *>(device)->set_req_callback(DEVCB_##_line); + +#define MCFG_NSCSICB_MSG_HANDLER(_line) \ + downcast<nscsi_callback_device *>(device)->set_msg_callback(DEVCB_##_line); + +#define MCFG_NSCSICB_IO_HANDLER(_line) \ + downcast<nscsi_callback_device *>(device)->set_io_callback(DEVCB_##_line); + +#define MCFG_NSCSICB_CD_HANDLER(_line) \ + downcast<nscsi_callback_device *>(device)->set_cd_callback(DEVCB_##_line); + +#define MCFG_NSCSICB_SEL_HANDLER(_line) \ + downcast<nscsi_callback_device *>(device)->set_sel_callback(DEVCB_##_line); + +#define MCFG_NSCSICB_BSY_HANDLER(_line) \ + downcast<nscsi_callback_device *>(device)->set_bsy_callback(DEVCB_##_line); + + class nscsi_callback_device : public nscsi_device { public: nscsi_callback_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - auto rst_callback() { return m_write_rst.bind(); } - auto atn_callback() { return m_write_atn.bind(); } - auto ack_callback() { return m_write_ack.bind(); } - auto req_callback() { return m_write_req.bind(); } - auto msg_callback() { return m_write_msg.bind(); } - auto io_callback() { return m_write_io.bind(); } - auto cd_callback() { return m_write_cd.bind(); } - auto sel_callback() { return m_write_sel.bind(); } - auto bsy_callback() { return m_write_bsy.bind(); } + template <class Line> devcb_base &set_rst_callback(Line &&cb) { return m_write_rst.set_callback(std::forward<Line>(cb)); } + template <class Line> devcb_base &set_atn_callback(Line &&cb) { return m_write_atn.set_callback(std::forward<Line>(cb)); } + template <class Line> devcb_base &set_ack_callback(Line &&cb) { return m_write_ack.set_callback(std::forward<Line>(cb)); } + template <class Line> devcb_base &set_req_callback(Line &&cb) { return m_write_req.set_callback(std::forward<Line>(cb)); } + template <class Line> devcb_base &set_msg_callback(Line &&cb) { return m_write_msg.set_callback(std::forward<Line>(cb)); } + template <class Line> devcb_base &set_io_callback(Line &&cb) { return m_write_io.set_callback(std::forward<Line>(cb)); } + template <class Line> devcb_base &set_cd_callback(Line &&cb) { return m_write_cd.set_callback(std::forward<Line>(cb)); } + template <class Line> devcb_base &set_sel_callback(Line &&cb) { return m_write_sel.set_callback(std::forward<Line>(cb)); } + template <class Line> devcb_base &set_bsy_callback(Line &&cb) { return m_write_bsy.set_callback(std::forward<Line>(cb)); } virtual void scsi_ctrl_changed() override; diff --git a/src/devices/machine/nscsi_cd.cpp b/src/devices/machine/nscsi_cd.cpp index 0446c600e9f..fc1898eecd5 100644 --- a/src/devices/machine/nscsi_cd.cpp +++ b/src/devices/machine/nscsi_cd.cpp @@ -7,7 +7,6 @@ #include "logmacro.h" DEFINE_DEVICE_TYPE(NSCSI_CDROM, nscsi_cdrom_device, "scsi_cdrom", "SCSI CD-ROM") -DEFINE_DEVICE_TYPE(NSCSI_CDROM_SGI, nscsi_cdrom_sgi_device, "scsi_cdrom_sgi", "SCSI CD-ROM SGI") DEFINE_DEVICE_TYPE(NSCSI_RRD45, nscsi_dec_rrd45_device, "nrrd45", "RRD45 CD-ROM (New)") DEFINE_DEVICE_TYPE(NSCSI_XM3301, nscsi_toshiba_xm3301_device, "nxm3301", "XM-3301TA CD-ROM (New)") DEFINE_DEVICE_TYPE(NSCSI_XM5301SUN, nscsi_toshiba_xm5301_sun_device, "nxm5301sun", "XM-5301B Sun 4x CD-ROM (New)") @@ -20,11 +19,6 @@ nscsi_cdrom_device::nscsi_cdrom_device(const machine_config &mconfig, const char { } -nscsi_cdrom_sgi_device::nscsi_cdrom_sgi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - nscsi_cdrom_device(mconfig, NSCSI_CDROM_SGI, tag, owner, "Sony", "CDU-76S", "1.0", 0x00, 0x05) -{ -} - nscsi_dec_rrd45_device::nscsi_dec_rrd45_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : nscsi_cdrom_device(mconfig, NSCSI_RRD45, tag, owner, "DEC ", "RRD45 (C) DEC ", "0436", 0x98, 0x02) { @@ -82,19 +76,10 @@ void nscsi_cdrom_device::device_reset() cur_sector = -1; } -void nscsi_cdrom_device::device_add_mconfig(machine_config &config) -{ - CDROM(config, image).set_interface("cdrom"); -} - -int nscsi_cdrom_device::to_msf(int frame) -{ - int m = frame / (75 * 60); - int s = (frame / 75) % 60; - int f = frame % 75; - - return (m << 16) | (s << 8) | f; -} +MACHINE_CONFIG_START(nscsi_cdrom_device::device_add_mconfig) + MCFG_CDROM_ADD("image") + MCFG_CDROM_INTERFACE("cdrom") +MACHINE_CONFIG_END void nscsi_cdrom_device::set_block_size(u32 block_size) { @@ -208,16 +193,21 @@ void nscsi_cdrom_device::scsi_command() * is returned with sense data ILLEGAL REQUEST and LOGICAL UNIT NOT * SUPPORTED. */ + if(lun) { + bad_lun(); + return; + } + int page = scsi_cmdbuf[2]; int size = scsi_cmdbuf[4]; switch(page) { case 0: std::fill_n(scsi_cmdbuf, 36, 0); - if (lun != 0) - scsi_cmdbuf[0] = 0x7f; - else - scsi_cmdbuf[0] = 0x05; // device is present, device is CD/DVD (MMC-3) + // vendor and product information must be padded with spaces + std::fill_n(&scsi_cmdbuf[8], 28, 0x20); + + scsi_cmdbuf[0] = 0x05; // device is present, device is CD/DVD (MMC-3) scsi_cmdbuf[1] = 0x80; // media is removable scsi_cmdbuf[2] = compliance; // device complies with SPC-3 standard scsi_cmdbuf[3] = 0x02; // response data format = SPC-3 standard @@ -226,12 +216,6 @@ void nscsi_cdrom_device::scsi_command() strncpy((char *)&scsi_cmdbuf[8], manufacturer, 8); strncpy((char *)&scsi_cmdbuf[16], product, 16); strncpy((char *)&scsi_cmdbuf[32], revision, 4); - - // vendor and product information must be padded with spaces - for(int i = 8; i < 36; i++) - if(scsi_cmdbuf[i] == 0) - scsi_cmdbuf[i] = 0x20; - if(size > 36) size = 36; scsi_data_in(SBUF_MAIN, size); @@ -257,48 +241,6 @@ void nscsi_cdrom_device::scsi_command() scsi_status_complete(SS_GOOD); break; - case SC_RECIEVE_DIAG_RES: { - LOG("command RECIEVE DIAGNOSTICS RESULTS"); - int size = (scsi_cmdbuf[3] << 8) | scsi_cmdbuf[4]; - int pos = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 6; - scsi_cmdbuf[pos++] = 0; // ROM is OK - scsi_cmdbuf[pos++] = 0; // RAM is OK - scsi_cmdbuf[pos++] = 0; // Data buffer is OK - scsi_cmdbuf[pos++] = 0; // Interface is OK - scsi_cmdbuf[pos++] = 0; - if(size > pos) - size = pos; - scsi_data_in(0, size); - scsi_status_complete(SS_GOOD); - break; - } - - case SC_SEND_DIAGNOSTICS: { - LOG("command SEND DIAGNOSTICS"); - int size = (scsi_cmdbuf[3] << 8) | scsi_cmdbuf[4]; - if(scsi_cmdbuf[1] & 4) { - // Self-test - scsi_status_complete(SS_GOOD); - break; - } - int pos = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 6; - scsi_cmdbuf[pos++] = 0; // ROM is OK - scsi_cmdbuf[pos++] = 0; // RAM is OK - scsi_cmdbuf[pos++] = 0; // Data buffer is OK - scsi_cmdbuf[pos++] = 0; // Interface is OK - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - if(size > pos) - size = pos; - scsi_data_in(0, size); - scsi_status_complete(SS_GOOD); - break; - } - case SC_READ_CAPACITY: { if(!cdrom) { return_no_cd(); @@ -308,7 +250,7 @@ void nscsi_cdrom_device::scsi_command() LOG("command READ CAPACITY\n"); // get the last used block on the disc - const u32 temp = cdrom_get_track_start(cdrom, 0xaa) * (bytes_per_sector / bytes_per_block) - 1; + const uint32_t temp = cdrom_get_track_start(cdrom, 0xaa) * (bytes_per_sector / bytes_per_block) - 1; scsi_cmdbuf[0] = (temp>>24) & 0xff; scsi_cmdbuf[1] = (temp>>16) & 0xff; @@ -325,15 +267,16 @@ void nscsi_cdrom_device::scsi_command() } case SC_READ_10: - lba = (scsi_cmdbuf[2]<<24) | (scsi_cmdbuf[3]<<16) | (scsi_cmdbuf[4]<<8) | scsi_cmdbuf[5]; - blocks = (scsi_cmdbuf[7] << 8) | scsi_cmdbuf[8]; - - LOG("command READ EXTENDED start=%08x blocks=%04x\n", lba, blocks); if(!cdrom) { return_no_cd(); break; } + lba = (scsi_cmdbuf[2]<<24) | (scsi_cmdbuf[3]<<16) | (scsi_cmdbuf[4]<<8) | scsi_cmdbuf[5]; + blocks = (scsi_cmdbuf[7] << 8) | scsi_cmdbuf[8]; + + LOG("command READ EXTENDED start=%08x blocks=%04x\n", lba, blocks); + scsi_data_in(2, blocks*bytes_per_block); scsi_status_complete(SS_GOOD); break; @@ -354,7 +297,7 @@ void nscsi_cdrom_device::scsi_command() scsi_cmdbuf[pos++] = 0x80; // WP, cache // get the last used block on the disc - const u32 temp = cdrom_get_track_start(cdrom, 0xaa) * (bytes_per_sector / bytes_per_block) - 1; + const uint32_t temp = cdrom_get_track_start(cdrom, 0xaa) * (bytes_per_sector / bytes_per_block) - 1; scsi_cmdbuf[pos++] = 0x08; // Block descriptor length scsi_cmdbuf[pos++] = 0x00; // density code @@ -366,11 +309,10 @@ void nscsi_cdrom_device::scsi_command() scsi_cmdbuf[pos++] = (bytes_per_block>>8)&0xff; scsi_cmdbuf[pos++] = (bytes_per_block & 0xff); - bool fail = false; int pmax = page == 0x3f ? 0x3e : page; int pmin = page == 0x3f ? 0x00 : page; - for(int p=pmax; p >= pmin; p--) { - switch(p) { + for(int page=pmax; page >= pmin; page--) { + switch(page) { case 0x00: // Vendor specific (does not require page format) scsi_cmdbuf[pos++] = 0x80; // PS, page id scsi_cmdbuf[pos++] = 0x02; // Page length @@ -398,10 +340,7 @@ void nscsi_cdrom_device::scsi_command() break; default: - if (page != 0x3f) { - LOG("mode sense page %02x unhandled\n", p); - fail = true; - } + LOG("mode sense page %02x unhandled\n", page); break; } } @@ -409,13 +348,8 @@ void nscsi_cdrom_device::scsi_command() if(pos > size) pos = size; - if (!fail) { - scsi_data_in(0, pos); - scsi_status_complete(SS_GOOD); - } else { - scsi_status_complete(SS_CHECK_CONDITION); - sense(false, SK_ILLEGAL_REQUEST, SK_ASC_INVALID_FIELD_IN_CDB); - } + scsi_data_in(0, pos); + scsi_status_complete(SS_GOOD); break; } @@ -425,186 +359,10 @@ void nscsi_cdrom_device::scsi_command() scsi_status_complete(SS_GOOD); break; - case SC_READ_TOC_PMA_ATIP: { - /* - Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out. - That makes sense in terms of how real-world CDs are referred to, but - our internal routines for tracks use "0" as track 1. That probably - should be fixed... - */ - static const char *const format_names[16] = { - "TOC", - "Session info", - "Full TOC", - "PMA", - "ATIP" - "Reserved 5", - "Reserved 6", - "Reserved 7", - "Reserved 8", - "Reserved 9", - "Reserved 10", - "Reserved 11", - "Reserved 12", - "Reserved 13", - "Reserved 14", - "Reserved 15" - }; - - bool msf = (scsi_cmdbuf[1] & 0x2) != 0; - u16 size = (scsi_cmdbuf[7] << 7) | scsi_cmdbuf[8]; - u8 format = scsi_cmdbuf[2] & 15; - - /// SFF8020 legacy format field (see T10/1836-D Revision 2g page 643) - if(!format) - format = (scsi_cmdbuf[9] >> 6) & 3; - - LOG("command READ TOC PMA ATIP, format %s msf=%d size=%d\n", format_names[format], msf, size); - - int pos = 0; - switch (format) { - case 0: { - int start_track = scsi_cmdbuf[6]; - int end_track = cdrom_get_last_track(cdrom); - - int tracks; - if(start_track == 0) - tracks = end_track + 1; - else if(start_track <= end_track) - tracks = (end_track - start_track) + 2; - else if(start_track <= 0xaa) - tracks = 1; - else - tracks = 0; - - int len = 2 + (tracks * 8); - - // the returned TOC DATA LENGTH must be the full amount, - // regardless of how much we're able to pass back due to size - scsi_cmdbuf[pos++] = (len>>8) & 0xff; - scsi_cmdbuf[pos++] = (len & 0xff); - scsi_cmdbuf[pos++] = 1; - scsi_cmdbuf[pos++] = cdrom_get_last_track(cdrom); - - if (start_track == 0) - start_track = 1; - - for(int i = 0; i < tracks; i++) { - int track = start_track + i; - int cdrom_track = track - 1; - if(i == tracks-1) { - track = 0xaa; - cdrom_track = 0xaa; - } - - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = cdrom_get_adr_control(cdrom, cdrom_track); - scsi_cmdbuf[pos++] = track; - scsi_cmdbuf[pos++] = 0; - - u32 tstart = cdrom_get_track_start(cdrom, cdrom_track); - - if(msf) - tstart = to_msf(tstart+150); - - scsi_cmdbuf[pos++] = (tstart>>24) & 0xff; - scsi_cmdbuf[pos++] = (tstart>>16) & 0xff; - scsi_cmdbuf[pos++] = (tstart>>8) & 0xff; - scsi_cmdbuf[pos++] = (tstart & 0xff); - } - break; - } - - case 1: { - int len = 2 + (8 * 1); - - scsi_cmdbuf[pos++] = (len>>8) & 0xff; - scsi_cmdbuf[pos++] = (len & 0xff); - scsi_cmdbuf[pos++] = 1; - scsi_cmdbuf[pos++] = 1; - - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = cdrom_get_adr_control(cdrom, 0); - scsi_cmdbuf[pos++] = 1; - scsi_cmdbuf[pos++] = 0; - - u32 tstart = cdrom_get_track_start(cdrom, 0); - - if (msf) - tstart = to_msf(tstart+150); - - scsi_cmdbuf[pos++] = (tstart>>24) & 0xff; - scsi_cmdbuf[pos++] = (tstart>>16) & 0xff; - scsi_cmdbuf[pos++] = (tstart>>8) & 0xff; - scsi_cmdbuf[pos++] = (tstart & 0xff); - break; - } - - default: - LOG("Unhandled format %d\n", format_names[format]); - break; - } - - if(pos) { - if(pos > size) - pos = size; - - scsi_data_in(0, pos); - scsi_status_complete(SS_GOOD); - } else { - // report unit attention condition - scsi_status_complete(SS_CHECK_CONDITION); - sense(false, SK_ILLEGAL_REQUEST); - break; - } - break; - } - default: - nscsi_full_device::scsi_command(); - break; - } -} - -enum sgi_scsi_command_e : uint8_t { - /* - * The SGI supplied CD-ROM drives (and possibly those from some other vendors) - * identify themselves as hard disk drives at poweron, and after SCSI bus resets, - * until issued a vendor specific command (0xc9). This is done because older - * systems would otherwise be unable to boot and load miniroots from CD, due to - * their design (they attempted to protect the user from booting from - * "ridiculous" devices, long before CD-ROM drives existed). The SGI drives are - * sent a command to "revert" to CD-ROM inquiry information during boot if on - * a SCSI bus handled by the PROM, but not all possible buses are handled by all - * PROMs; additionally, a SCSI bus reset causes the CD-ROM drives to revert to - * the poweron default, and this could happen before the hardware inventory code - * in the kernel runs, if there are SCSI problems. - */ - SGI_HD2CDROM = 0xc9, -}; - -void nscsi_cdrom_sgi_device::scsi_command() -{ - switch (scsi_cmdbuf[0]) { - case SGI_HD2CDROM: - LOG("command SGI_HD2CDROM"); - // No need to do anything (yet). Just acknowledge the command. - scsi_status_complete(SS_GOOD); - break; + logerror("unhandled command %02x\n", scsi_cmdbuf[0]); - default: - nscsi_cdrom_device::scsi_command(); + nscsi_full_device::scsi_command(); break; } } - -bool nscsi_cdrom_sgi_device::scsi_command_done(uint8_t command, uint8_t length) -{ - switch (command) { - case SGI_HD2CDROM: - return length == 10; - - default: - return nscsi_full_device::scsi_command_done(command, length); - } -} diff --git a/src/devices/machine/nscsi_cd.h b/src/devices/machine/nscsi_cd.h index 48097cea42f..f3ce871c70a 100644 --- a/src/devices/machine/nscsi_cd.h +++ b/src/devices/machine/nscsi_cd.h @@ -54,17 +54,6 @@ private: uint8_t compliance; void return_no_cd(); - static int to_msf(int frame); -}; - -class nscsi_cdrom_sgi_device : public nscsi_cdrom_device -{ -public: - nscsi_cdrom_sgi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); - -protected: - virtual void scsi_command() override; - virtual bool scsi_command_done(uint8_t command, uint8_t length) override; }; class nscsi_dec_rrd45_device : public nscsi_cdrom_device @@ -104,7 +93,6 @@ public: }; DECLARE_DEVICE_TYPE(NSCSI_CDROM, nscsi_cdrom_device) -DECLARE_DEVICE_TYPE(NSCSI_CDROM_SGI, nscsi_cdrom_sgi_device) DECLARE_DEVICE_TYPE(NSCSI_RRD45, nscsi_dec_rrd45_device) DECLARE_DEVICE_TYPE(NSCSI_XM3301, nscsi_toshiba_xm3301_device) DECLARE_DEVICE_TYPE(NSCSI_XM5301SUN, nscsi_toshiba_xm5301_sun_device) diff --git a/src/devices/machine/nscsi_hd.cpp b/src/devices/machine/nscsi_hd.cpp index 6684942c9d6..c83a2c17ef9 100644 --- a/src/devices/machine/nscsi_hd.cpp +++ b/src/devices/machine/nscsi_hd.cpp @@ -20,7 +20,7 @@ nscsi_harddisk_device::nscsi_harddisk_device(const machine_config &mconfig, cons } nscsi_harddisk_device::nscsi_harddisk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - nscsi_full_device(mconfig, type, tag, owner, clock), image(*this, "image"), harddisk(nullptr), lba(0), cur_lba(0), blocks(0), bytes_per_sector(0) + nscsi_full_device(mconfig, type, tag, owner, clock), harddisk(nullptr), lba(0), cur_lba(0), blocks(0), bytes_per_sector(0) { } @@ -37,7 +37,8 @@ void nscsi_harddisk_device::device_start() void nscsi_harddisk_device::device_reset() { nscsi_full_device::device_reset(); - harddisk = image->get_hard_disk_file(); + harddisk_image_device *hd = subdevice<harddisk_image_device>("image"); + harddisk = hd->get_hard_disk_file(); if(!harddisk) { scsi_id = -1; bytes_per_sector = 0; @@ -45,17 +46,18 @@ void nscsi_harddisk_device::device_reset() const hard_disk_info *hdinfo = hard_disk_get_info(harddisk); bytes_per_sector = hdinfo->sectorbytes; - chd_file *chd = image->get_chd_file(); + chd_file *chd = hd->get_chd_file(); if(chd != nullptr) chd->read_metadata(HARD_DISK_IDENT_METADATA_TAG, 0, m_inquiry_data); } cur_lba = -1; } -void nscsi_harddisk_device::device_add_mconfig(machine_config &config) -{ - HARDDISK(config, image).set_interface("scsi_hdd"); -} +MACHINE_CONFIG_START(nscsi_harddisk_device::device_add_mconfig) + MCFG_HARDDISK_ADD("image") + MCFG_HARDDISK_INTERFACE("scsi_hdd") +MACHINE_CONFIG_END + uint8_t nscsi_harddisk_device::scsi_get_data(int id, int pos) { @@ -90,9 +92,9 @@ void nscsi_harddisk_device::scsi_put_data(int id, int pos, uint8_t data) int offset = pos % bytes_per_sector; block[offset] = data; - cur_lba = lba + pos / bytes_per_sector; + int clba = lba + pos / bytes_per_sector; if(offset == bytes_per_sector-1) { - if(!hard_disk_write(harddisk, cur_lba, block)) + if(!hard_disk_write(harddisk, clba, block)) LOG("HD WRITE ERROR !\n"); } } @@ -166,8 +168,8 @@ void nscsi_harddisk_device::scsi_command() // Apple HD SC setup utility needs to see this strcpy((char *)&scsi_cmdbuf[8], " SEAGATE"); - strcpy((char *)&scsi_cmdbuf[16], " ST225N"); - strcpy((char *)&scsi_cmdbuf[32], "1.00"); + strcpy((char *)&scsi_cmdbuf[15], " ST225N"); + strcpy((char *)&scsi_cmdbuf[31], "1.00"); scsi_cmdbuf[36] = 0x00; // # of extents high scsi_cmdbuf[37] = 0x08; // # of extents low scsi_cmdbuf[38] = 0x00; // group 0 commands 0-1f @@ -228,10 +230,8 @@ void nscsi_harddisk_device::scsi_command() int pmax = page == 0x3f ? 0x3e : page; int pmin = page == 0x3f ? 0x00 : page; - - bool fail = false; - for(int p=pmax; p >= pmin; p--) { - switch(p) { + for(int page=pmax; page >= pmin; page--) { + switch(page) { case 0x00: // Unit attention parameters page (weird) scsi_cmdbuf[pos++] = 0x80; // PS, page id scsi_cmdbuf[pos++] = 0x02; // Page length @@ -239,40 +239,6 @@ void nscsi_harddisk_device::scsi_command() scsi_cmdbuf[pos++] = 0x00; // Double meh break; - case 0x01: // read-write error recovery page - scsi_cmdbuf[pos++] = 0x01; // !PS, page id - scsi_cmdbuf[pos++] = 0x0a; // page length - scsi_cmdbuf[pos++] = 0; // various bits - scsi_cmdbuf[pos++] = 0; // read retry count - scsi_cmdbuf[pos++] = 0; // correction span - scsi_cmdbuf[pos++] = 0; // head offset count - scsi_cmdbuf[pos++] = 0; // data strobe offset count - scsi_cmdbuf[pos++] = 0; // reserved - scsi_cmdbuf[pos++] = 0; // write retry count - scsi_cmdbuf[pos++] = 0; // reserved - scsi_cmdbuf[pos++] = 0; // recovery time limit (msb) - scsi_cmdbuf[pos++] = 0; // recovery time limit (lsb) - break; - - case 0x02: // disconnect-reconnect page - scsi_cmdbuf[pos++] = 0x02; // !PS, page id - scsi_cmdbuf[pos++] = 0x0e; // page length - scsi_cmdbuf[pos++] = 0; // buffer full ratio - scsi_cmdbuf[pos++] = 0; // buffer empty ratio - scsi_cmdbuf[pos++] = 0; // bus inactivity limit (msb) - scsi_cmdbuf[pos++] = 0; // bus inactivity limit (lsb) - scsi_cmdbuf[pos++] = 0; // disconnect time limit (msb) - scsi_cmdbuf[pos++] = 0; // disconnect time limit (lsb) - scsi_cmdbuf[pos++] = 0; // connect time limit (msb) - scsi_cmdbuf[pos++] = 0; // connect time limit (lsb) - scsi_cmdbuf[pos++] = 0; // maximum burst size (msb) - scsi_cmdbuf[pos++] = 0; // maximum burst size (lsb) - scsi_cmdbuf[pos++] = 0; // reserved - scsi_cmdbuf[pos++] = 0; // reserved - scsi_cmdbuf[pos++] = 0; // reserved - scsi_cmdbuf[pos++] = 0; // reserved - break; - case 0x03: { // Format parameters page scsi_cmdbuf[pos++] = 0x83; // PS, page id scsi_cmdbuf[pos++] = 0x16; // Page length @@ -329,21 +295,6 @@ void nscsi_harddisk_device::scsi_command() break; } - case 0x08: // caching page - scsi_cmdbuf[pos++] = 0x08; // !PS, page id - scsi_cmdbuf[pos++] = 0x0a; // page length - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - break; - case 0x30: { // Apple firmware ID page scsi_cmdbuf[pos++] = 0xb0; // cPS, page id scsi_cmdbuf[pos++] = 0x16; // Page length @@ -373,25 +324,16 @@ void nscsi_harddisk_device::scsi_command() } default: - if (page != 0x3f) { - LOG("mode sense page %02x unhandled\n", page); - fail = true; - } + LOG("mode sense page %02x unhandled\n", page); break; } } + scsi_cmdbuf[0] = pos; + if(pos > size) + pos = size; - if (!fail) { - scsi_cmdbuf[0] = pos; - if (pos > size) - pos = size; - - scsi_data_in(0, pos); - scsi_status_complete(SS_GOOD); - } else { - scsi_status_complete(SS_CHECK_CONDITION); - sense(false, SK_ILLEGAL_REQUEST, SK_ASC_INVALID_FIELD_IN_CDB); - } + scsi_data_in(0, pos); + scsi_status_complete(SS_GOOD); break; } @@ -400,48 +342,6 @@ void nscsi_harddisk_device::scsi_command() scsi_status_complete(SS_GOOD); break; - case SC_RECIEVE_DIAG_RES: { - LOG("command RECIEVE DIAGNOSTICS RESULTS"); - int size = (scsi_cmdbuf[3] << 8) | scsi_cmdbuf[4]; - int pos = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 6; - scsi_cmdbuf[pos++] = 0; // ROM is OK - scsi_cmdbuf[pos++] = 0; // RAM is OK - scsi_cmdbuf[pos++] = 0; // Data buffer is OK - scsi_cmdbuf[pos++] = 0; // Interface is OK - scsi_cmdbuf[pos++] = 0; - if(size > pos) - size = pos; - scsi_data_in(0, size); - scsi_status_complete(SS_GOOD); - break; - } - - case SC_SEND_DIAGNOSTICS: { - LOG("command SEND DIAGNOSTICS"); - int size = (scsi_cmdbuf[3] << 8) | scsi_cmdbuf[4]; - if(scsi_cmdbuf[1] & 4) { - // Self-test - scsi_status_complete(SS_GOOD); - break; - } - int pos = 0; - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 6; - scsi_cmdbuf[pos++] = 0; // ROM is OK - scsi_cmdbuf[pos++] = 0; // RAM is OK - scsi_cmdbuf[pos++] = 0; // Data buffer is OK - scsi_cmdbuf[pos++] = 0; // Interface is OK - scsi_cmdbuf[pos++] = 0; - scsi_cmdbuf[pos++] = 0; - if(size > pos) - size = pos; - scsi_data_in(0, size); - scsi_status_complete(SS_GOOD); - break; - } - case SC_READ_CAPACITY: { LOG("command READ CAPACITY\n"); @@ -503,11 +403,6 @@ void nscsi_harddisk_device::scsi_command() scsi_status_complete(SS_GOOD); break; - case SC_MODE_SELECT_6: - LOG("command MODE SELECT\n"); - scsi_status_complete(SS_GOOD); - break; - default: LOG("command %02x ***UNKNOWN***\n", scsi_cmdbuf[0]); nscsi_full_device::scsi_command(); diff --git a/src/devices/machine/nscsi_hd.h b/src/devices/machine/nscsi_hd.h index 5ddbf3e8519..19dfe55c0e5 100644 --- a/src/devices/machine/nscsi_hd.h +++ b/src/devices/machine/nscsi_hd.h @@ -6,7 +6,7 @@ #pragma once #include "machine/nscsi_bus.h" -#include "imagedev/harddriv.h" +#include "harddisk.h" class nscsi_harddisk_device : public nscsi_full_device { @@ -24,7 +24,6 @@ protected: virtual uint8_t scsi_get_data(int id, int pos) override; virtual void scsi_put_data(int buf, int offset, uint8_t data) override; - required_device<harddisk_image_device> image; uint8_t block[512]; hard_disk_file *harddisk; int lba, cur_lba, blocks; diff --git a/src/devices/machine/output_latch.h b/src/devices/machine/output_latch.h index 2498be7f63f..c915b4c7207 100644 --- a/src/devices/machine/output_latch.h +++ b/src/devices/machine/output_latch.h @@ -6,11 +6,36 @@ #pragma once +#define MCFG_OUTPUT_LATCH_BIT0_HANDLER(_devcb) \ + downcast<output_latch_device &>(*device).set_bit_handler<0>(DEVCB_##_devcb); + +#define MCFG_OUTPUT_LATCH_BIT1_HANDLER(_devcb) \ + downcast<output_latch_device &>(*device).set_bit_handler<1>(DEVCB_##_devcb); + +#define MCFG_OUTPUT_LATCH_BIT2_HANDLER(_devcb) \ + downcast<output_latch_device &>(*device).set_bit_handler<2>(DEVCB_##_devcb); + +#define MCFG_OUTPUT_LATCH_BIT3_HANDLER(_devcb) \ + downcast<output_latch_device &>(*device).set_bit_handler<3>(DEVCB_##_devcb); + +#define MCFG_OUTPUT_LATCH_BIT4_HANDLER(_devcb) \ + downcast<output_latch_device &>(*device).set_bit_handler<4>(DEVCB_##_devcb); + +#define MCFG_OUTPUT_LATCH_BIT5_HANDLER(_devcb) \ + downcast<output_latch_device &>(*device).set_bit_handler<5>(DEVCB_##_devcb); + +#define MCFG_OUTPUT_LATCH_BIT6_HANDLER(_devcb) \ + downcast<output_latch_device &>(*device).set_bit_handler<6>(DEVCB_##_devcb); + +#define MCFG_OUTPUT_LATCH_BIT7_HANDLER(_devcb) \ + downcast<output_latch_device &>(*device).set_bit_handler<7>(DEVCB_##_devcb); + class output_latch_device : public device_t { public: output_latch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + template <unsigned Bit, class Object> devcb_base &set_bit_handler(Object &&cb) { return m_bit_handlers[Bit].set_callback(std::forward<Object>(cb)); } template <unsigned Bit> auto bit_handler() { return m_bit_handlers[Bit].bind(); } void write(uint8_t data); diff --git a/src/devices/machine/pc_fdc.cpp b/src/devices/machine/pc_fdc.cpp index 8f48da0f505..601c4c813c5 100644 --- a/src/devices/machine/pc_fdc.cpp +++ b/src/devices/machine/pc_fdc.cpp @@ -157,7 +157,7 @@ uint8_t pc_fdc_family_device::do_dir_r() WRITE8_MEMBER( pc_fdc_xt_device::dor_fifo_w) { - fdc->fifo_w(data); + fdc->fifo_w(space, 0, data, mem_mask); dor_w(space, 0, data, mem_mask); } diff --git a/src/devices/machine/pc_lpt.cpp b/src/devices/machine/pc_lpt.cpp index 0d43fbc6eeb..b0f97871e87 100644 --- a/src/devices/machine/pc_lpt.cpp +++ b/src/devices/machine/pc_lpt.cpp @@ -46,8 +46,7 @@ void pc_lpt_device::device_reset() m_cent_ctrl_out->write(m_control); } -void pc_lpt_device::device_add_mconfig(machine_config &config) -{ +MACHINE_CONFIG_START(pc_lpt_device::device_add_mconfig) centronics_device ¢ronics(CENTRONICS(config, "centronics", centronics_devices, "printer")); centronics.set_data_input_buffer(m_cent_data_in); centronics.fault_handler().set(m_cent_status_in, FUNC(input_buffer_device::write_bit3)); @@ -65,8 +64,7 @@ void pc_lpt_device::device_add_mconfig(machine_config &config) INPUT_BUFFER(config, m_cent_ctrl_in); INPUT_BUFFER(config, m_cent_status_in); - OUTPUT_LATCH(config, m_cent_data_out); - centronics.set_output_latch(*m_cent_data_out); + MCFG_CENTRONICS_OUTPUT_LATCH_ADD("cent_data_out", "centronics") OUTPUT_LATCH(config, m_cent_ctrl_out); m_cent_ctrl_out->bit_handler<0>().set("centronics", FUNC(centronics_device::write_strobe)); @@ -74,7 +72,7 @@ void pc_lpt_device::device_add_mconfig(machine_config &config) m_cent_ctrl_out->bit_handler<2>().set("centronics", FUNC(centronics_device::write_init)); m_cent_ctrl_out->bit_handler<3>().set("centronics", FUNC(centronics_device::write_select_in)); m_cent_ctrl_out->bit_handler<4>().set(FUNC(pc_lpt_device::write_irq_enabled)); -} +MACHINE_CONFIG_END READ8_MEMBER( pc_lpt_device::data_r ) diff --git a/src/devices/machine/pckeybrd.h b/src/devices/machine/pckeybrd.h index 42a443226f5..7ee6c5c2c14 100644 --- a/src/devices/machine/pckeybrd.h +++ b/src/devices/machine/pckeybrd.h @@ -20,11 +20,12 @@ class pc_keyboard_device : public device_t { public: - pc_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + pc_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); DECLARE_READ8_MEMBER(read); DECLARE_WRITE_LINE_MEMBER(enable); + template <class Object> devcb_base &set_keypress_callback(Object &&cb) { return m_out_keypress_func.set_callback(std::forward<Object>(cb)); } auto keypress() { return m_out_keypress_func.bind(); } enum class KEYBOARD_TYPE @@ -76,13 +77,7 @@ private: class at_keyboard_device : public pc_keyboard_device { public: - at_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, KEYBOARD_TYPE type, int default_set) - : at_keyboard_device(mconfig, tag, owner, 0) - { - set_type(type, default_set); - } - - at_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + at_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); DECLARE_WRITE8_MEMBER( write ); @@ -119,4 +114,18 @@ INPUT_PORTS_EXTERN( at_keyboard ); DECLARE_DEVICE_TYPE(PC_KEYB, pc_keyboard_device) DECLARE_DEVICE_TYPE(AT_KEYB, at_keyboard_device) +#define MCFG_PC_KEYB_ADD(_tag, _cb) \ + MCFG_DEVICE_ADD(_tag, PC_KEYB, 0) \ + downcast<pc_keyboard_device &>(*device).set_keypress_callback(DEVCB_##_cb); + +#define MCFG_AT_KEYB_ADD(_tag, _def_set, _cb) \ + MCFG_DEVICE_ADD(_tag, AT_KEYB, 0) \ + downcast<at_keyboard_device &>(*device).set_type(pc_keyboard_device::KEYBOARD_TYPE::AT, _def_set); \ + downcast<pc_keyboard_device &>(*device).set_keypress_callback(DEVCB_##_cb); + +#define MCFG_AT_MF2_KEYB_ADD(_tag, _def_set, _cb) \ + MCFG_DEVICE_ADD(_tag, AT_KEYB, 0) \ + downcast<at_keyboard_device &>(*device).set_type(pc_keyboard_device::KEYBOARD_TYPE_MF2, _def_set); \ + downcast<pc_keyboard_device &>(*device).set_keypress_callback(DEVCB_##_cb); + #endif // MAME_MACHINE_PCKEYBRD_H diff --git a/src/devices/machine/pdc.cpp b/src/devices/machine/pdc.cpp index 20b0c627dc5..99964762548 100644 --- a/src/devices/machine/pdc.cpp +++ b/src/devices/machine/pdc.cpp @@ -261,7 +261,7 @@ void pdc_device::device_add_mconfig(machine_config &config) Z80(config, m_pdccpu, XTAL(10'000'000) / 2); m_pdccpu->set_addrmap(AS_PROGRAM, &pdc_device::pdc_mem); m_pdccpu->set_addrmap(AS_IO, &pdc_device::pdc_io); - //config.m_perfect_cpu_quantum = subtag(M6502_TAG); + //MCFG_QUANTUM_PERFECT_CPU(M6502_TAG) /* Floppy Disk Controller - uPD765a - NEC D765AC-2 */ UPD765A(config, m_fdc, 4'000'000, true, true); @@ -279,7 +279,6 @@ void pdc_device::device_add_mconfig(machine_config &config) m_dma8237->out_eop_callback().set(FUNC(pdc_device::i8237_eop_w)); m_dma8237->in_memr_callback().set(FUNC(pdc_device::i8237_dma_mem_r)); m_dma8237->out_memw_callback().set(FUNC(pdc_device::i8237_dma_mem_w)); - //m_dma8237->out_dack_callback<0>().set(m_fdc, FUNC(upd765a_device::dack_w)); m_dma8237->in_ior_callback<0>().set(FUNC(pdc_device::i8237_fdc_dma_r)); m_dma8237->out_iow_callback<0>().set(FUNC(pdc_device::i8237_fdc_dma_w)); m_dma8237->in_ior_callback<1>().set(FUNC(pdc_device::m68k_dma_r)); diff --git a/src/devices/machine/pic8259.h b/src/devices/machine/pic8259.h index 298ef1debea..0b85efd9ac1 100644 --- a/src/devices/machine/pic8259.h +++ b/src/devices/machine/pic8259.h @@ -31,7 +31,7 @@ class pic8259_device : public device_t { public: - pic8259_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + pic8259_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); auto out_int_callback() { return m_out_int_func.bind(); } // Interrupt request output to CPU or master 8259 (active high) auto in_sp_callback() { return m_in_sp_func.bind(); } // Slave program select (VCC = master; GND = slave; pin becomes EN output in buffered mode) @@ -118,7 +118,7 @@ private: class v5x_icu_device : public pic8259_device { public: - v5x_icu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + v5x_icu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); protected: virtual bool is_x86() const override { return true; } diff --git a/src/devices/machine/pit8253.cpp b/src/devices/machine/pit8253.cpp index 7d52572ba89..6e6f86e5b0e 100644 --- a/src/devices/machine/pit8253.cpp +++ b/src/devices/machine/pit8253.cpp @@ -74,12 +74,11 @@ fe2010_pit_device::fe2010_pit_device(const machine_config &mconfig, const char * // device_add_mconfig - add device configuration //------------------------------------------------- -void pit8253_device::device_add_mconfig(machine_config &config) -{ - PIT_COUNTER(config, "counter0", 0); - PIT_COUNTER(config, "counter1", 0); - PIT_COUNTER(config, "counter2", 0); -} +MACHINE_CONFIG_START(pit8253_device::device_add_mconfig) + MCFG_DEVICE_ADD("counter0", PIT_COUNTER, 0) + MCFG_DEVICE_ADD("counter1", PIT_COUNTER, 0) + MCFG_DEVICE_ADD("counter2", PIT_COUNTER, 0) +MACHINE_CONFIG_END //------------------------------------------------- diff --git a/src/devices/machine/pit8253.h b/src/devices/machine/pit8253.h index 77f0bf552f9..eebee4edbb3 100644 --- a/src/devices/machine/pit8253.h +++ b/src/devices/machine/pit8253.h @@ -104,7 +104,7 @@ class pit8253_device : public device_t public: // construction/destruction - pit8253_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + pit8253_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // configuration helpers template <unsigned N> void set_clk(double clk) { m_clk[N] = clk; } @@ -157,7 +157,7 @@ DECLARE_DEVICE_TYPE(PIT8253, pit8253_device) class pit8254_device : public pit8253_device { public: - pit8254_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + pit8254_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); protected: virtual void readback_command(uint8_t data) override; @@ -168,7 +168,7 @@ DECLARE_DEVICE_TYPE(PIT8254, pit8254_device) class fe2010_pit_device : public pit8253_device { public: - fe2010_pit_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + fe2010_pit_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; DECLARE_DEVICE_TYPE(FE2010_PIT, fe2010_pit_device) diff --git a/src/devices/machine/pla.h b/src/devices/machine/pla.h index b614a968b36..7e4672b7860 100644 --- a/src/devices/machine/pla.h +++ b/src/devices/machine/pla.h @@ -11,6 +11,24 @@ #pragma once +///************************************************************************* +// INTERFACE CONFIGURATION MACROS +///************************************************************************* + +#define MCFG_PLA_ADD(tag, inputs, outputs, terms) \ + MCFG_DEVICE_ADD((tag), PLA, 0) \ + downcast<pla_device &>(*device).set_num_inputs((inputs)); \ + downcast<pla_device &>(*device).set_num_outputs((outputs)); \ + downcast<pla_device &>(*device).set_num_terms((terms)); + +#define MCFG_PLA_INPUTMASK(mask) \ + downcast<pla_device &>(*device).set_inputmask((mask)); + +#define MCFG_PLA_FILEFORMAT(format) \ + downcast<pla_device &>(*device).set_format((pla_device::FMT::format)); + + +// macros for known (and used) devices // 82S100, 82S101, PLS100, PLS101 // 16x48x8 PLA, 28-pin: @@ -30,7 +48,8 @@ F4 13 | | 16 F2 GND 14 |_____________| 15 F3 */ - +#define MCFG_PLS100_ADD(tag) \ + MCFG_DEVICE_ADD((tag), PLS100) ///************************************************************************* // TYPE DEFINITIONS diff --git a/src/devices/machine/pxa255.cpp b/src/devices/machine/pxa255.cpp index 5a65f1542ae..0e96fec2b27 100644 --- a/src/devices/machine/pxa255.cpp +++ b/src/devices/machine/pxa255.cpp @@ -1222,20 +1222,20 @@ uint32_t pxa255_periphs_device::screen_update(screen_device &screen, bitmap_rgb3 return 0; } -void pxa255_periphs_device::device_add_mconfig(machine_config &config) -{ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); - screen.set_size(1024, 1024); - screen.set_visarea(0, 295, 0, 479); - screen.set_screen_update(FUNC(pxa255_periphs_device::screen_update)); - - PALETTE(config, m_palette).set_entries(256); +MACHINE_CONFIG_START(pxa255_periphs_device::device_add_mconfig) + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_REFRESH_RATE(60) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) + MCFG_SCREEN_SIZE(1024, 1024) + MCFG_SCREEN_VISIBLE_AREA(0, 295, 0, 479) + MCFG_SCREEN_UPDATE_DEVICE(DEVICE_SELF, pxa255_periphs_device, screen_update) + MCFG_PALETTE_ADD(m_palette, 256) SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); - DMADAC(config, m_dmadac[0]).add_route(ALL_OUTPUTS, "lspeaker", 1.0); - DMADAC(config, m_dmadac[1]).add_route(ALL_OUTPUTS, "rspeaker", 1.0); -} + MCFG_DEVICE_ADD(m_dmadac[0], DMADAC) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0) + MCFG_DEVICE_ADD(m_dmadac[1], DMADAC) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0) +MACHINE_CONFIG_END diff --git a/src/devices/machine/rtc65271.cpp b/src/devices/machine/rtc65271.cpp index 9ccc83997bf..f44cc8255fc 100644 --- a/src/devices/machine/rtc65271.cpp +++ b/src/devices/machine/rtc65271.cpp @@ -346,12 +346,12 @@ uint8_t rtc65271_device::read(int xramsel, offs_t offset) return reply; } -uint8_t rtc65271_device::rtc_r(offs_t offset) +READ8_MEMBER( rtc65271_device::rtc_r ) { return read(0, offset ); } -uint8_t rtc65271_device::xram_r(offs_t offset) +READ8_MEMBER( rtc65271_device::xram_r ) { return read(1, offset ); } @@ -436,12 +436,12 @@ void rtc65271_device::write(int xramsel, offs_t offset, uint8_t data) } } -void rtc65271_device::rtc_w(offs_t offset, uint8_t data) +WRITE8_MEMBER( rtc65271_device::rtc_w ) { write(0, offset, data ); } -void rtc65271_device::xram_w(offs_t offset, uint8_t data) +WRITE8_MEMBER( rtc65271_device::xram_w ) { write(1, offset, data ); } diff --git a/src/devices/machine/rtc65271.h b/src/devices/machine/rtc65271.h index 1a69b518839..65ee8233675 100644 --- a/src/devices/machine/rtc65271.h +++ b/src/devices/machine/rtc65271.h @@ -21,10 +21,10 @@ public: auto interrupt_cb() { return m_interrupt_cb.bind(); } - uint8_t rtc_r(offs_t offset); - uint8_t xram_r(offs_t offset); - void rtc_w(offs_t offset, uint8_t data); - void xram_w(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( rtc_r ); + DECLARE_READ8_MEMBER( xram_r ); + DECLARE_WRITE8_MEMBER( rtc_w ); + DECLARE_WRITE8_MEMBER( xram_w ); protected: // device-level overrides diff --git a/src/devices/machine/scc2698b.cpp b/src/devices/machine/scc2698b.cpp index 8a362e26d45..1f6c537f52d 100644 --- a/src/devices/machine/scc2698b.cpp +++ b/src/devices/machine/scc2698b.cpp @@ -768,8 +768,7 @@ attotime scc2698b_device::generate_baudrate(int block, int tx, int table_index) -void scc2698b_device::device_add_mconfig(machine_config &config) -{ +MACHINE_CONFIG_START(scc2698b_device::device_add_mconfig) for (required_device<scc2698b_channel> &channel : m_channel) SCC2698B_CHANNEL(config, channel, 0); -} +MACHINE_CONFIG_END diff --git a/src/devices/machine/scnxx562.cpp b/src/devices/machine/scnxx562.cpp index c3bfbfacc5d..9ccf996782c 100644 --- a/src/devices/machine/scnxx562.cpp +++ b/src/devices/machine/scnxx562.cpp @@ -126,11 +126,10 @@ DEFINE_DEVICE_TYPE(DUSCC68C562, duscc68c562_device, "duscc68c562", "Philips //------------------------------------------------- // device_add_mconfig - add device configuration //------------------------------------------------- -void duscc_device::device_add_mconfig(machine_config &config) -{ - DUSCC_CHANNEL(config, CHANA_TAG, 0); - DUSCC_CHANNEL(config, CHANB_TAG, 0); -} +MACHINE_CONFIG_START(duscc_device::device_add_mconfig) + MCFG_DEVICE_ADD(CHANA_TAG, DUSCC_CHANNEL, 0) + MCFG_DEVICE_ADD(CHANB_TAG, DUSCC_CHANNEL, 0) +MACHINE_CONFIG_END //************************************************************************** // LIVE DEVICE diff --git a/src/devices/machine/sis85c496.cpp b/src/devices/machine/sis85c496.cpp index 87b01edf2e6..186c4894b8d 100644 --- a/src/devices/machine/sis85c496.cpp +++ b/src/devices/machine/sis85c496.cpp @@ -45,8 +45,7 @@ void sis85c496_host_device::internal_io_map(address_map &map) map(0x00e0, 0x00ef).noprw(); } -void sis85c496_host_device::device_add_mconfig(machine_config &config) -{ +MACHINE_CONFIG_START(sis85c496_host_device::device_add_mconfig) PIT8254(config, m_pit8254, 0); m_pit8254->set_clk<0>(4772720/4); // heartbeat IRQ m_pit8254->out_handler<0>().set(FUNC(sis85c496_host_device::at_pit8254_out0_changed)); @@ -104,10 +103,10 @@ void sis85c496_host_device::device_add_mconfig(machine_config &config) m_keybc->kbd_clk().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb)); m_keybc->kbd_data().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb)); - PC_KBDC(config, m_pc_kbdc, 0); - m_pc_kbdc->out_clock_cb().set("keybc", FUNC(at_keyboard_controller_device::kbd_clk_w)); - m_pc_kbdc->out_data_cb().set("keybc", FUNC(at_keyboard_controller_device::kbd_data_w)); - PC_KBDC_SLOT(config, "kbd", pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL).set_pc_kbdc_slot(subdevice("pc_kbdc")); + MCFG_DEVICE_ADD("pc_kbdc", PC_KBDC, 0) + MCFG_PC_KBDC_OUT_CLOCK_CB(WRITELINE("keybc", at_keyboard_controller_device, kbd_clk_w)) + MCFG_PC_KBDC_OUT_DATA_CB(WRITELINE("keybc", at_keyboard_controller_device, kbd_data_w)) + MCFG_PC_KBDC_SLOT_ADD("pc_kbdc", "kbd", pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL) DS12885(config, m_ds12885); m_ds12885->irq().set(m_pic8259_slave, FUNC(pic8259_device::ir0_w)); @@ -116,7 +115,7 @@ void sis85c496_host_device::device_add_mconfig(machine_config &config) /* sound hardware */ SPEAKER(config, "mono").front_center(); SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50); -} +MACHINE_CONFIG_END sis85c496_host_device::sis85c496_host_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) @@ -493,8 +492,6 @@ WRITE_LINE_MEMBER( sis85c496_host_device::at_dma8237_out_eop ) void sis85c496_host_device::pc_select_dma_channel(int channel, bool state) { - //m_isabus->dack_line_w(channel, state); - if(!state) { m_dma_channel = channel; //if(m_cur_eop) @@ -544,19 +541,19 @@ WRITE8_MEMBER( sis85c496_host_device::at_portb_w ) READ8_MEMBER( sis85c496_host_device::at_dma8237_2_r ) { - return m_dma8237_2->read( offset / 2); + return m_dma8237_2->read( space, offset / 2); } WRITE8_MEMBER( sis85c496_host_device::at_dma8237_2_w ) { - m_dma8237_2->write( offset / 2, data); + m_dma8237_2->write( space, offset / 2, data); } READ8_MEMBER( sis85c496_host_device::at_keybc_r ) { switch (offset) { - case 0: return m_keybc->data_r(); + case 0: return m_keybc->data_r(space, 0); case 1: return at_portb_r(space, 0); } @@ -567,7 +564,7 @@ WRITE8_MEMBER( sis85c496_host_device::at_keybc_w ) { switch (offset) { - case 0: m_keybc->data_w(data); break; + case 0: m_keybc->data_w(space, 0, data); break; case 1: at_portb_w(space, 0, data); break; } } @@ -578,10 +575,10 @@ WRITE8_MEMBER( sis85c496_host_device::write_rtc ) if (offset==0) { m_nmi_enabled = BIT(data,7); //m_isabus->set_nmi_state((m_nmi_enabled==0) && (m_channel_check==0)); - m_ds12885->write(0,data); + m_ds12885->write(space,0,data); } else { - m_ds12885->write(offset,data); + m_ds12885->write(space,offset,data); } } diff --git a/src/devices/machine/smc91c9x.cpp b/src/devices/machine/smc91c9x.cpp index 359a69eefdb..e081c2c6a17 100644 --- a/src/devices/machine/smc91c9x.cpp +++ b/src/devices/machine/smc91c9x.cpp @@ -4,29 +4,92 @@ SMC91C9X ethernet controller implementation - by Aaron Giles, Ted Green + by Aaron Giles, Jean-François DEL NERO -***************************************************************************/ +*************************************************************************** + + Notes: + * Connected mode working + +**************************************************************************/ #include "emu.h" #include "smc91c9x.h" -#include <sstream> -#include <iomanip> +// Needed for netdev_count??? +#include "osdnet.h" + /*************************************************************************** DEBUGGING ***************************************************************************/ -#define LOG_GENERAL (1U << 0) -#define LOG_PACKETS (1U << 1) -#define LOG_TX (1U << 2) -#define LOG_RX (1U << 3) -#define LOG_FILTER (1U << 4) -//#define VERBOSE (LOG_GENERAL | LOG_PACKETS | LOG_TX | LOG_RX | LOG_FILTER) +//#define VERBOSE 1 #include "logmacro.h" #define DISPLAY_STATS (0) + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +/* Ethernet registers - bank 0 */ +#define EREG_TCR (0*8 + 0) +#define EREG_EPH_STATUS (0*8 + 1) +#define EREG_RCR (0*8 + 2) +#define EREG_COUNTER (0*8 + 3) +#define EREG_MIR (0*8 + 4) +#define EREG_MCR (0*8 + 5) +#define EREG_BANK (0*8 + 7) + +/* Ethernet registers - bank 1 */ +#define EREG_CONFIG (1*8 + 0) +#define EREG_BASE (1*8 + 1) +#define EREG_IA0_1 (1*8 + 2) +#define EREG_IA2_3 (1*8 + 3) +#define EREG_IA4_5 (1*8 + 4) +#define EREG_GENERAL_PURP (1*8 + 5) +#define EREG_CONTROL (1*8 + 6) + +/* Ethernet registers - bank 2 */ +#define EREG_MMU_COMMAND (2*8 + 0) +#define EREG_PNR_ARR (2*8 + 1) +#define EREG_FIFO_PORTS (2*8 + 2) +#define EREG_POINTER (2*8 + 3) +#define EREG_DATA_0 (2*8 + 4) +#define EREG_DATA_1 (2*8 + 5) +#define EREG_INTERRUPT (2*8 + 6) + +/* Ethernet registers - bank 3 */ +#define EREG_MT0_1 (3*8 + 0) +#define EREG_MT2_3 (3*8 + 1) +#define EREG_MT4_5 (3*8 + 2) +#define EREG_MT6_7 (3*8 + 3) +#define EREG_MGMT (3*8 + 4) +#define EREG_REVISION (3*8 + 5) +#define EREG_ERCV (3*8 + 6) + +/* Ethernet MMU commands */ +#define ECMD_NOP 0 +#define ECMD_ALLOCATE 2 +#define ECMD_RESET_MMU 4 +#define ECMD_REMOVE_TOPFRAME_RX 6 +#define ECMD_REMOVE_TOPFRAME_TX 7 +#define ECMD_REMOVE_RELEASE_TOPFRAME_RX 8 +#define ECMD_RELEASE_PACKET 10 +#define ECMD_ENQUEUE_PACKET 12 +#define ECMD_RESET_FIFOS 14 + +/* Ethernet interrupt bits */ +#define EINT_RCV 0x01 +#define EINT_TX 0x02 +#define EINT_TX_EMPTY 0x04 +#define EINT_ALLOC 0x08 +#define EINT_RX_OVRN 0x10 +#define EINT_EPH 0x20 +#define EINT_ERCV 0x40 + /* Ethernet register names */ static const char *const ethernet_regname[64] = { @@ -44,93 +107,73 @@ static const char *const ethernet_regname[64] = DEVICE INTERFACE ***************************************************************************/ -DEFINE_DEVICE_TYPE(SMC91C94, smc91c94_device, "smc91c94", "SMC91C94 Ethernet Controller") - -smc91c94_device::smc91c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : smc91c9x_device(mconfig, SMC91C94, tag, owner, clock, dev_type::SMC91C94) -{ - m_num_ebuf = 18; -} - -DEFINE_DEVICE_TYPE(SMC91C96, smc91c96_device, "smc91c96", "SMC91C96 Ethernet Controller") - -smc91c96_device::smc91c96_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : smc91c9x_device(mconfig, SMC91C96, tag, owner, clock, dev_type::SMC91C96) -{ - m_num_ebuf = 24; -} - -smc91c9x_device::smc91c9x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, dev_type device_type) +smc91c9x_device::smc91c9x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) , device_network_interface(mconfig, *this, 10.0f) - , m_device_type(device_type) - , m_num_ebuf(16) , m_irq_handler(*this) , m_link_unconnected(false) { } -const u8 smc91c9x_device::ETH_BROADCAST[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -const u8 smc91c9x_device::WMS_OUI[] = { 0x00, 0xA0, 0xAF }; - //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void smc91c9x_device::device_start() { - // Allocate main buffer - m_buffer = std::make_unique<u8[]>(ETHER_BUFFER_SIZE * m_num_ebuf); - // TX timer - m_tx_poll = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(smc91c9x_device::tx_poll), this)); + m_tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(smc91c9x_device::send_frame), this)); m_irq_handler.resolve_safe(); - // These registers don't get cleared on reset - m_reg[B1_CONFIG] = 0x0030; m_regmask[B1_CONFIG] = 0x17c6; - m_reg[B1_BASE] = 0x1866; m_regmask[B1_BASE] = 0xfffe; - - m_reg[B1_IA0_1] = 0x0000; m_regmask[B1_IA0_1] = 0xffff; - m_reg[B1_IA2_3] = 0x0000; m_regmask[B1_IA2_3] = 0xffff; - m_reg[B1_IA4_5] = 0x0000; m_regmask[B1_IA4_5] = 0xffff; - - // Revision is set based on chip type - m_regmask[B3_REVISION] = 0x0000; - if (m_device_type == dev_type::SMC91C94) - m_reg[B3_REVISION] = 0x3345; - else if (m_device_type == dev_type::SMC91C96) - m_reg[B3_REVISION] = 0x3346; - else - fatalerror("device_start: Unknown device type\n"); - /* register ide states */ save_item(NAME(m_reg)); save_item(NAME(m_regmask)); save_item(NAME(m_irq_state)); - save_pointer(NAME(m_buffer), ETHER_BUFFER_SIZE * m_num_ebuf); + save_item(NAME(m_buffer)); save_item(NAME(m_sent)); save_item(NAME(m_recd)); save_item(NAME(m_alloc_rx)); save_item(NAME(m_alloc_tx)); - save_item(NAME(m_tx_active)); - save_item(NAME(m_rx_active)); - save_item(NAME(m_tx_retry_count)); - save_item(NAME(m_rx_hash)); - save_item(NAME(m_loopback_result)); - - // Circular FIFOs - save_item(NAME(m_queued_tx)); - save_item(NAME(m_queued_tx_h)); - save_item(NAME(m_queued_tx_t)); - save_item(NAME(m_completed_tx)); - save_item(NAME(m_completed_tx_h)); - save_item(NAME(m_completed_tx_t)); - save_item(NAME(m_completed_rx)); - save_item(NAME(m_completed_rx_h)); - save_item(NAME(m_completed_rx_t)); + // Save vector data for proper save state restoration + save_item(NAME(m_comp_rx_data)); + save_item(NAME(m_comp_tx_data)); + save_item(NAME(m_trans_tx_data)); + // Save vector sizes for proper save state restoration + save_item(NAME(m_comp_tx_size)); + save_item(NAME(m_comp_rx_size)); + save_item(NAME(m_trans_tx_size)); +} + +// Save state presave to save vector sizes +void smc91c9x_device::device_pre_save() +{ + m_comp_tx_size = m_comp_tx.size(); + m_comp_rx_size = m_comp_rx.size(); + m_trans_tx_size = m_trans_tx.size(); + memcpy(m_comp_rx_data, m_comp_rx.data(), m_comp_rx_size * sizeof(u32)); + memcpy(m_comp_tx_data, m_comp_tx.data(), m_comp_tx_size * sizeof(u32)); + memcpy(m_trans_tx_data, m_trans_tx.data(), m_trans_tx_size * sizeof(u32)); + + //osd_printf_info("Save: comp_tx: %d comp_rx: %d trans_tx: %d\n", m_comp_tx_size, m_comp_rx_size, m_trans_tx_size); + //if (m_comp_tx_size) + // osd_printf_info("comp_tx packet: %d\n", m_comp_tx.front()); } +// Save state preload to restore vector sizes +void smc91c9x_device::device_post_load() +{ + m_comp_tx.resize(m_comp_tx_size); + m_comp_rx.resize(m_comp_rx_size); + m_trans_tx.resize(m_trans_tx_size); + memcpy(m_comp_rx.data(), m_comp_rx_data, m_comp_rx_size * sizeof(u32)); + memcpy(m_comp_tx.data(), m_comp_tx_data, m_comp_tx_size * sizeof(u32)); + memcpy(m_trans_tx.data(), m_trans_tx_data, m_trans_tx_size * sizeof(u32)); + + //osd_printf_info("Restore: comp_tx: %d comp_rx: %d trans_tx: %d\n", m_comp_tx_size, m_comp_rx_size, m_trans_tx_size); + //if (m_comp_tx_size) + // osd_printf_info("comp_tx size: %lu comp_tx packet: %d array_data: %d\n", m_comp_tx.size(), m_comp_tx.front(), m_comp_tx_data[0]); +} //------------------------------------------------- // device_reset - device-specific reset @@ -138,43 +181,75 @@ void smc91c9x_device::device_start() void smc91c9x_device::device_reset() { + std::fill(std::begin(m_reg), std::end(m_reg), 0); + + std::fill(std::begin(m_regmask), std::end(m_regmask), 0); + m_irq_state = 0; m_sent = 0; m_recd = 0; - m_tx_active = 0; - m_rx_active = 0; - m_tx_retry_count = 0; - - m_reg[B0_TCR] = 0x0000; m_regmask[B0_TCR] = 0x3d87; - m_reg[B0_EPH_STATUS] = 0x0000; m_regmask[B0_EPH_STATUS] = 0x0000; - m_reg[B0_RCR] = 0x0000; m_regmask[B0_RCR] = 0xc307; - m_reg[B0_COUNTER] = 0x0000; m_regmask[B0_COUNTER] = 0x0000; - m_reg[B0_MIR] = 0x1212; m_regmask[B0_MIR] = 0x0000; - m_reg[B0_MCR] = 0x3300; m_regmask[B0_MCR] = 0x00ff; - m_reg[B0_BANK] = 0x3300; m_regmask[B0_BANK] = 0x0007; - - m_reg[B1_GENERAL_PURP] = 0x0000; m_regmask[B1_GENERAL_PURP] = 0xffff; - m_reg[B1_CONTROL] = 0x0100; m_regmask[B1_CONTROL] = 0x68e7; - - m_reg[B2_MMU_COMMAND] = 0x0000; m_regmask[B2_MMU_COMMAND] = 0x00e7; - m_reg[B2_PNR_ARR] = 0x8000; m_regmask[B2_PNR_ARR] = 0x00ff; - m_reg[B2_FIFO_PORTS] = 0x8080; m_regmask[B2_FIFO_PORTS] = 0x0000; - m_reg[B2_POINTER] = 0x0000; m_regmask[B2_POINTER] = 0xf7ff; - m_reg[B2_DATA_0] = 0x0000; m_regmask[B2_DATA_0] = 0xffff; - m_reg[B2_DATA_1] = 0x0000; m_regmask[B2_DATA_1] = 0xffff; - m_reg[B2_INTERRUPT] = 0x0004; m_regmask[B2_INTERRUPT] = 0x7f00; - - m_reg[B3_MT0_1] = 0x0000; m_regmask[B3_MT0_1] = 0xffff; - m_reg[B3_MT2_3] = 0x0000; m_regmask[B3_MT2_3] = 0xffff; - m_reg[B3_MT4_5] = 0x0000; m_regmask[B3_MT4_5] = 0xffff; - m_reg[B3_MT6_7] = 0x0000; m_regmask[B3_MT6_7] = 0xffff; - m_reg[B3_MGMT] = 0x3030; m_regmask[B3_MGMT] = 0x0f0f; - - m_reg[B3_ERCV] = 0x331f; m_regmask[B3_ERCV] = 0x009f; + m_reg[EREG_TCR] = 0x0000; m_regmask[EREG_TCR] = 0x3d87; + m_reg[EREG_EPH_STATUS] = 0x0000; m_regmask[EREG_EPH_STATUS] = 0x0000; + m_reg[EREG_RCR] = 0x0000; m_regmask[EREG_RCR] = 0xc307; + m_reg[EREG_COUNTER] = 0x0000; m_regmask[EREG_COUNTER] = 0x0000; + m_reg[EREG_MIR] = 0x1212; m_regmask[EREG_MIR] = 0x0000; + m_reg[EREG_MCR] = 0x3300; m_regmask[EREG_MCR] = 0x00ff; + m_reg[EREG_BANK] = 0x3300; m_regmask[EREG_BANK] = 0x0007; + + m_reg[EREG_CONFIG] = 0x0030; m_regmask[EREG_CONFIG] = 0x17c6; + m_reg[EREG_BASE] = 0x1866; m_regmask[EREG_BASE] = 0xfffe; + + // Default MAC + m_reg[EREG_IA0_1] = 0x1300; m_regmask[EREG_IA0_1] = 0xffff; + m_reg[EREG_IA2_3] = 0x12F7; m_regmask[EREG_IA2_3] = 0xffff; + m_reg[EREG_IA4_5] = 0x5634; m_regmask[EREG_IA4_5] = 0xffff; + + m_reg[EREG_GENERAL_PURP] = 0x0000; m_regmask[EREG_GENERAL_PURP] = 0xffff; + m_reg[EREG_CONTROL] = 0x0100; m_regmask[EREG_CONTROL] = 0x68e7; + + m_reg[EREG_MMU_COMMAND] = 0x0000; m_regmask[EREG_MMU_COMMAND] = 0x00e7; + m_reg[EREG_PNR_ARR] = 0x8000; m_regmask[EREG_PNR_ARR] = 0x00ff; + m_reg[EREG_FIFO_PORTS] = 0x8080; m_regmask[EREG_FIFO_PORTS] = 0x0000; + m_reg[EREG_POINTER] = 0x0000; m_regmask[EREG_POINTER] = 0xf7ff; + m_reg[EREG_DATA_0] = 0x0000; m_regmask[EREG_DATA_0] = 0xffff; + m_reg[EREG_DATA_1] = 0x0000; m_regmask[EREG_DATA_1] = 0xffff; + m_reg[EREG_INTERRUPT] = 0x0004; m_regmask[EREG_INTERRUPT] = 0x7f00; + + m_reg[EREG_MT0_1] = 0x0000; m_regmask[EREG_MT0_1] = 0xffff; + m_reg[EREG_MT2_3] = 0x0000; m_regmask[EREG_MT2_3] = 0xffff; + m_reg[EREG_MT4_5] = 0x0000; m_regmask[EREG_MT4_5] = 0xffff; + m_reg[EREG_MT6_7] = 0x0000; m_regmask[EREG_MT6_7] = 0xffff; + m_reg[EREG_MGMT] = 0x3030; m_regmask[EREG_MGMT] = 0x0f0f; + // TODO: Revision should be set based on chip type + m_reg[EREG_REVISION] = 0x3345; m_regmask[EREG_REVISION] = 0x0000; + m_reg[EREG_ERCV] = 0x331f; m_regmask[EREG_ERCV] = 0x009f; update_ethernet_irq(); + m_tx_timer->reset(); + + // Setup real network if enabled + m_network_available = false; + if (netdev_count()) { + m_network_available = true; + osd_list_network_adapters(); + unsigned char const *const mac = (const unsigned char *)get_mac(); + if (VERBOSE & LOG_GENERAL) + { + logerror("MAC : "); + for (int i = 0; i < ETHERNET_ADDR_SIZE; i++) + logerror("%.2X", mac[i]); + + logerror("\n"); + } + + set_promisc(true); + // Interface MAC + m_reg[EREG_IA0_1] = mac[0] | (mac[1] << 8); + m_reg[EREG_IA2_3] = mac[2] | (mac[3] << 8); + m_reg[EREG_IA4_5] = mac[4] | (mac[5] << 8); + } // Reset MMU mmu_reset(); @@ -186,36 +261,39 @@ void smc91c9x_device::mmu_reset() m_alloc_rx = 0; m_alloc_tx = 0; - // Reset fifos. - reset_tx_fifos(); - reset_completed_rx(); + // Flush fifos. + clear_tx_fifo(); + clear_rx_fifo(); update_ethernet_irq(); } -void smc91c9x_device::reset_tx_fifos() +DEFINE_DEVICE_TYPE(SMC91C94, smc91c94_device, "smc91c94", "SMC91C94 Ethernet Controller") + +smc91c94_device::smc91c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : smc91c9x_device(mconfig, SMC91C94, tag, owner, clock) +{ +} + +DEFINE_DEVICE_TYPE(SMC91C96, smc91c96_device, "smc91c96", "SMC91C96 Ethernet Controller") + +smc91c96_device::smc91c96_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : smc91c9x_device(mconfig, SMC91C96, tag, owner, clock) { - // Disable transmit timer - m_tx_poll->enable(false); - // Reset transmit queue - reset_queued_tx(); - // Reset completion FIFOs - reset_completed_tx(); } bool smc91c9x_device::alloc_req(const int tx, int &packet_num) { u32 curr_alloc = m_alloc_rx | m_alloc_tx; - for (int index = 0; index < m_num_ebuf; index++) - { - if (!(curr_alloc & (1 << index))) - { + for (int index = 0; index < ETHER_BUFFERS; index++) { + if (!(curr_alloc & (1 << index))) { packet_num = index; - if (tx) + if (tx) { m_alloc_tx |= 1 << index; - else + } else { m_alloc_rx |= 1 << index; + } return true; } } @@ -226,8 +304,7 @@ bool smc91c9x_device::alloc_req(const int tx, int &packet_num) void smc91c9x_device::alloc_release(const int packet_num) { int clear_mask = ~(1 << packet_num); - if (!((m_alloc_tx | m_alloc_rx) & (1 << packet_num))) - { + if (!((m_alloc_tx | m_alloc_rx) & (1 << packet_num))) { logerror("alloc_release: Trying to release a non-allocated packet. packet_num: %02x alloc_tx: %04x alloc_rx: %04x\n", packet_num, m_alloc_tx, m_alloc_rx); } @@ -235,448 +312,338 @@ void smc91c9x_device::alloc_release(const int packet_num) m_alloc_rx &= clear_mask; } -/*************************************************************************** - INTERNAL HELPERS -***************************************************************************/ - -/*------------------------------------------------- - update_ethernet_irq - update the IRQ state --------------------------------------------------*/ - -void smc91c9x_device::update_ethernet_irq() +void smc91c9x_device::clear_tx_fifo() { - // Check tx completion fifo empty - if (empty_completed_tx()) - m_reg[B2_INTERRUPT] &= ~EINT_TX; - else - m_reg[B2_INTERRUPT] |= EINT_TX; + // Clear transmit timer + m_tx_timer->reset(); + // Reset transmit queue + m_trans_tx.clear(); + // Reset completion FIFOs + m_comp_tx.clear(); +} - // Check rx completion fifo empty - if (empty_completed_rx()) - m_reg[B2_INTERRUPT] &= ~EINT_RCV; - else - m_reg[B2_INTERRUPT] |= EINT_RCV; +void smc91c9x_device::clear_rx_fifo() +{ + // Clear recieve FIFO + m_comp_rx.clear(); +} - uint8_t const mask = m_reg[B2_INTERRUPT] >> 8; - uint8_t const state = m_reg[B2_INTERRUPT] & 0xff; +int smc91c9x_device::is_broadcast(const uint8_t *mac_address) +{ + int i; + i = 0; - /* update the IRQ state */ - uint8_t new_state = mask & state; - if (m_irq_state ^ new_state) + while(mac_address[i] == 0xFF) { - LOG("update_ethernet_irq: old: %02x new: %02x\n", m_irq_state, new_state); - m_irq_state = new_state; - m_irq_handler(m_irq_state ? ASSERT_LINE : CLEAR_LINE); + i++; } -} + if ( i == 6 ) + return 1; -/*------------------------------------------------- - update_stats - draw statistics --------------------------------------------------*/ - -void smc91c9x_device::update_stats() -{ - if ( DISPLAY_STATS ) - popmessage("Sent:%d Rec'd:%d", m_sent, m_recd); + return 0; } -/*------------------------------------------------- -dump_bytes - Print packet bytes --------------------------------------------------*/ -void smc91c9x_device::dump_bytes(u8 *buf, int length) +int smc91c9x_device::ethernet_packet_is_for_me(const uint8_t *mac_address) { - if (VERBOSE & LOG_PACKETS) - { - std::stringstream ss_bytes; - ss_bytes << std::hex << std::setfill('0'); - for (int i = 0; i < length; i++) - { - ss_bytes << std::setw(2) << (int) buf[i]; - // Send newline every 16 bytes and at the end - if ((i & 0xf) == 0xf || i == length - 1) - { - LOGMASKED(LOG_PACKETS, "%s\n", ss_bytes.str()); - ss_bytes.str(""); - } - else - ss_bytes << " "; - } - } -} + // tcpdump -i eth0 -q ether host 08:00:1e:01:ae:a5 or ether broadcast or ether dst 09:00:1e:00:00:00 or ether dst 09:00:1e:00:00:01 + // wireshark filter: eth.addr eq 08:00:1e:01:ae:a5 or eth.dst eq ff:ff:ff:ff:ff:ff or eth.dst eq 09:00:1e:00:00:00 or eth.dst eq 09:00:1e:00:00:01 -/*------------------------------------------------- -address_filter - Filter the received packet --------------------------------------------------*/ + int i; -int smc91c9x_device::address_filter(u8 *buf) -{ - if (m_reg[B0_RCR] & PRMS) - { - // TODO: 91C94 doesn't receive it's own transmisson when not in full duplex - LOGMASKED(LOG_FILTER, "address_filter accepted (promiscuous mode)\n"); - return ADDR_UNICAST; - } - else if (buf[0] & 1) + LOG("\n"); + + if (VERBOSE & LOG_GENERAL) { - // broadcast - if (!memcmp(ETH_BROADCAST, buf, 6)) + for ( i = 0 ; i < ETHERNET_ADDR_SIZE ; i++ ) { - LOGMASKED(LOG_FILTER, "address_filter accepted (broadcast) %02x-%02x-%02x-%02x-%02x-%02x\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); - - return ADDR_BROADCAST; + logerror("%.2X", ((u8 *)&m_reg[EREG_IA0_1])[i]); } - - // multicast - /* - * Multicast address matching is performed by computing the fcs crc of - * the destination address, and then using the upper 6 bits as an index - * into the 64-bit logical address filter. - */ - // Check for all multicast bit - if (m_reg[B0_RCR] & ALMUL) - return ADDR_MULTICAST; - - u32 const crc = util::crc32_creator::simple(buf, 6); - // The hash is based on the top 6 MSBs of the CRC - // The CRC needs to be inverted and reflected - m_rx_hash = 0x0; - for (int i = 0; i < 6; i++) - m_rx_hash |= (((~crc) >> i) & 1) << (5 - i); - u64 multicast_addr = *(u64*)&m_reg[B3_MT0_1]; - if (BIT(multicast_addr, m_rx_hash)) + logerror("="); + for ( i = 0 ; i < ETHERNET_ADDR_SIZE ; i++ ) { - LOGMASKED(LOG_FILTER, "address_filter accepted (multicast address match) %02x-%02x-%02x-%02x-%02x-%02x\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); - - return ADDR_MULTICAST; + logerror("%.2X",mac_address[i]); } - LOGMASKED(LOG_FILTER, "address_filter rejected multicast %02x-%02x-%02x-%02x-%02x-%02x crc: %08x hash: %02x multi: %16ullx\n", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], crc, m_rx_hash, *(u64*)&m_reg[B3_MT0_1]); + logerror("?"); } - else - { - // unicast - if (!memcmp(&m_reg[B1_IA0_1], buf, 6)) - { - LOGMASKED(LOG_FILTER, "address_filter accepted (physical address match)\n"); - return ADDR_UNICAST; - } + // skip Ethernet broadcast packets if RECV_BROAD is not set + if (is_broadcast(mac_address)) + { + LOG(" -- Broadcast rx\n"); + return 2; } - return ADDR_NOMATCH; -} -/*------------------------------------------------- -recv_start_cb - Start receiving packet - A return value of 0 will stop rx processing in dinetwork device - Any other value will be sent to the recv_complete_cb --------------------------------------------------*/ - -int smc91c9x_device::recv_start_cb(u8 *buf, int length) -{ - // check internal loopback - if (m_reg[B0_TCR] & (EPH_LOOP | LOOP)) + if (memcmp(mac_address, &m_reg[EREG_IA0_1], ETHERNET_ADDR_SIZE) == 0) { - LOGMASKED(LOG_RX, "receive internal loopback mode, external packet discarded\n"); - - return 0; + LOG(" -- Address Match\n"); + return 1; } - // discard bad length packets - if (length < 64 || length > 256*6 - 6) - { - LOGMASKED(LOG_RX, "received bad length packet length %d discarded\n", length); + LOG(" -- Not Matching\n"); - return 0; - } + return 0; +} - // discard packets not from WMS - if (memcmp(WMS_OUI, &buf[6], 3)) - { - LOGMASKED(LOG_RX, "received non-WMS packet OUI: %02x:%02x:%02x length %d discarded\n", buf[6], buf[7], buf[8], length); +/*************************************************************************** + recv_cb - receive callback - receive and process an ethernet packet + ***************************************************************************/ - return 0; - } +void smc91c9x_device::recv_cb(uint8_t *data, int length) +{ + LOG("recv_cb : %d/0x%x\n",length,length); - // Check for active transmission - if (m_tx_active) - { - // TODO: Update collision counters - LOGMASKED(LOG_RX, "transmit active COLLISION, rx packet length %d discarded\n", length); + int const isforme = ethernet_packet_is_for_me( data ); - return 0; + if (isforme==1 && (length >= ETHERNET_ADDR_SIZE) && (VERBOSE & LOG_GENERAL)) + { + logerror("RX: "); + for (int i = 0; i < ETHERNET_ADDR_SIZE; i++) + logerror("%.2X", data[i]); - } + logerror(" "); - return receive(buf, length); -} + for (int i = 0; i < length-ETHERNET_ADDR_SIZE; i++) + logerror("%.2X", data[ETHERNET_ADDR_SIZE + i]); -/*------------------------------------------------- -receive - Receive data into buffer - Returns the buffer packet number + 1 if successful --------------------------------------------------*/ + logerror(" - IsForMe %d - %d/0x%x bytes\n", isforme, length, length); + } -int smc91c9x_device::receive(u8 *buf, int length) -{ - // check receiver enabled - if (!(m_reg[B0_RCR] & RXEN)) + if ( (length < ETHERNET_ADDR_SIZE || !isforme) && !(m_reg[EREG_RCR] & 0x0102) ) { - LOGMASKED(LOG_RX, "receive disabled, external packet discarded\n"); + LOG("\n"); - return -1; + // skip packet + return; } - // address filter - int filter = address_filter(buf); - if (filter == ADDR_NOMATCH) - return -1; - - LOGMASKED(LOG_RX, "receive packet length %d\n", length); - dump_bytes(buf, length); + /* signal a receive */ // Try to request a packet number int packet_num; - if (!alloc_req(0, packet_num)) - { - logerror("recv_cb: Couldn't allocate memory for receive packet\n"); - return -2; + if (!alloc_req(0, packet_num)) { + logerror("recv_cb: Couldn't allocate a receive packet\n"); + return; } - m_rx_active = 1; + /* compute the packet length */ - // build up the packet - uint8_t *const packet = &m_buffer[packet_num * ETHER_BUFFER_SIZE]; + if ( ( length < ( ETHER_BUFFER_SIZE - ( 2+2+2 ) ) ) ) + { + uint8_t *const packet = &m_buffer[ packet_num * ETHER_BUFFER_SIZE]; - // Strip CRC - if (m_reg[B0_RCR] & STRIP_CRC) - length -= 4; + int dst = 0; - // Copy received payload - memcpy(&packet[4], buf, length); + // build up the packet - // Status word - u16 *rx_status = (u16*)&packet[0]; - *rx_status = 0x0000; + // Status word + packet[dst++] = 0x00; - // set the broadcast flag - if (filter == ADDR_BROADCAST) - *rx_status |= BRODCAST; + // set the broadcast flag + if ( isforme == 2 ) + packet[dst++] |= 0x40; + else + packet[dst++] = 0x00; - // set the multicast flag and hash - if (filter == ADDR_MULTICAST) - { - *rx_status |= (m_rx_hash << 1) | MULTCAST; - } + //bytes count + packet[dst++] = 0x00; + packet[dst++] = 0x00; - // Calculate buffer length and set control byte - u16 buf_length; + memcpy(&packet[dst], data, length ); + dst += length; - if (length & 1) - { - // ODD Frame - *rx_status |= ODDFRM; - packet[length + 4] = EBUF_RX_ALWAYS | EBUF_ODD; // Control - buf_length = length + 5; - } - else - { - packet[length + 4] = 0x00; // Pad - packet[length + 5] = EBUF_RX_ALWAYS; // Control - buf_length = length + 6; - } + if ( dst & 1 ) + { + // ODD Frame + packet[dst++] = 0x40 | 0x20; // Control + } + else + { + packet[dst++] = 0x00; // Pad + packet[dst++] = 0x40 | 0x00; // Control + } - // Set buffer length word - *(u16*)&packet[2] = buf_length; + //dst += 2; - return packet_num + 1; -} + dst &= 0x7FF; -/*------------------------------------------------- -recv_complete_cb - End of receive --------------------------------------------------*/ + packet[2] = (dst&0xFF); + packet[3] = (dst) >> 8; -void smc91c9x_device::recv_complete_cb(int result) -{ - if (result > 0) - { // Push packet number to rx completion fifo - push_completed_rx(result - 1); + m_comp_rx.push_back(packet_num); } - // Couldn't allocate memory - else if (result == -2) + else { - m_reg[B2_INTERRUPT] |= EINT_ALLOC; + LOG("Rejected ! Fifo Full ?"); } update_ethernet_irq(); - m_rx_active = 0; + LOG("\n"); } +/*************************************************************************** + INTERNAL HELPERS +***************************************************************************/ + /*------------------------------------------------- - tx_poll - Starts transmit + update_ethernet_irq - update the IRQ state -------------------------------------------------*/ -TIMER_CALLBACK_MEMBER(smc91c9x_device::tx_poll) +void smc91c9x_device::update_ethernet_irq() { - // Check for active RX and delay if necessary - if (m_rx_active) - { - // TODO: Implement correct CSMA/CD algorithm - m_tx_poll->adjust(attotime::from_usec(40)); - m_tx_retry_count++; - LOGMASKED(LOG_TX, "tx_poll: Delaying TX due to active RX retry_count = %d\n", m_tx_retry_count); - } - // Check if TX is enabled and packet is queued - else if ((m_reg[B0_TCR] & TXENA) && !empty_queued_tx()) - { - // Reset retry count - m_tx_retry_count = 0; + // Check tx completion fifo empty + if (m_comp_tx.empty()) + m_reg[EREG_INTERRUPT] &= ~EINT_TX; + else + m_reg[EREG_INTERRUPT] |= EINT_TX; - // Get the packet number from the transmit fifo - const int packet_num = curr_queued_tx(); - uint8_t *const tx_buffer = &m_buffer[packet_num * ETHER_BUFFER_SIZE]; + // Check rx completion fifo empty + if (m_comp_rx.empty()) + m_reg[EREG_INTERRUPT] &= ~EINT_RCV; + else + m_reg[EREG_INTERRUPT] |= EINT_RCV; - // Get the length and control fields from buffer - u16 length = (*(u16*)&tx_buffer[2]) & 0x7ff; - const u8 control = tx_buffer[length - 1]; + uint8_t const mask = m_reg[EREG_INTERRUPT] >> 8; + uint8_t const state = m_reg[EREG_INTERRUPT] & 0xff; - // Remove [pad], control - if (control & EBUF_ODD) - length -= 1; - else - length -= 2; - // Add padding up to CRC area - // take into account status & length removal (-4) and crc addtion (+4) - while (length < 64 + 4 - 4 && (m_reg[B0_TCR] & PAD_EN)) - tx_buffer[length++] = 0x00; + /* update the IRQ state */ + uint8_t new_state = mask & state; + if (m_irq_state ^ new_state) + { + LOG("update_ethernet_irq: old: %02x new: %02x\n", m_irq_state, new_state); + m_irq_state = new_state; + m_irq_handler(m_irq_state ? ASSERT_LINE : CLEAR_LINE); + } +} - // Add CRC - // TODO: Calculate CRC - if (1 && ((control & EBUF_CRC) || !(m_reg[B0_TCR] & NOCRC))) - { - tx_buffer[length++] = 0x11; - tx_buffer[length++] = 0x22; - tx_buffer[length++] = 0x33; - tx_buffer[length++] = 0x44; - } - // Remove status, length - length -= 4; +/*------------------------------------------------- + update_stats - draw statistics +-------------------------------------------------*/ - // Reset the EPH register */ - m_reg[B0_EPH_STATUS] &= LINK_OK; +void smc91c9x_device::update_stats() +{ + if ( DISPLAY_STATS ) + popmessage("Sent:%d Rec'd:%d", m_sent, m_recd); +} - // Send the frame - m_tx_active = 1; - m_tx_poll->enable(false); - LOGMASKED(LOG_TX, "Start sending packet %d length = %d time: %s\n", packet_num, length, machine().scheduler().time().as_string()); - dump_bytes(&tx_buffer[4], length); +/*------------------------------------------------- + send_frame - push a frame to the interface +-------------------------------------------------*/ - // Write loopback data and save result - if (m_reg[B0_TCR] & (EPH_LOOP | LOOP | FDUPLX)) - m_loopback_result = receive(&tx_buffer[4], length); - else - m_loopback_result = 0; +TIMER_CALLBACK_MEMBER(smc91c9x_device::send_frame) +{ + // Get the packet number from the transmit fifo + const int packet_num = m_trans_tx.front(); + uint8_t *const tx_buffer = &m_buffer[packet_num * ETHER_BUFFER_SIZE]; - // Local loopback isn't sent to cable - //if ((m_reg[B0_TCR] & (EPH_LOOP | LOOP) || (get_interface() < 0 && (m_reg[B0_TCR] & FDUPLX)))) - if (m_reg[B0_TCR] & (EPH_LOOP | LOOP)) - send_complete_cb(length); - else - send(&tx_buffer[4], length); + // Pop the transmit fifo + m_trans_tx.erase(m_trans_tx.begin()); - } -} + /* update the EPH register */ + m_reg[EREG_EPH_STATUS] = 0x0001; -/*------------------------------------------------- -send_complete_cb - Called after transmit complete --------------------------------------------------*/ + if (is_broadcast(&tx_buffer[4])) + m_reg[EREG_EPH_STATUS] |= 0x0040; + + // Check tx completion fifo empty + if (m_trans_tx.empty()) + m_reg[EREG_INTERRUPT] |= EINT_TX_EMPTY; -void smc91c9x_device::send_complete_cb(int result) -{ m_sent++; + update_stats(); - // Pop the packet number from the transmit fifo - const int packet_num = pop_queued_tx(); - uint8_t *const tx_buffer = &m_buffer[packet_num * ETHER_BUFFER_SIZE]; + int buffer_len = ((tx_buffer[3] << 8) | tx_buffer[2]) & 0x7ff; + // Remove status, length, [pad], control + if (tx_buffer[buffer_len - 1] & 0x20) + buffer_len -= 5; + else + buffer_len -= 6; + // Add padding + if (buffer_len < 64 && (m_reg[EREG_TCR] & 0x0080)) { + while (buffer_len < 64) + tx_buffer[4 + buffer_len++] = 0x00; + } + if (VERBOSE & LOG_GENERAL) + { + logerror("TX: "); + for (int i = 0; i < ETHERNET_ADDR_SIZE; i++) + logerror("%.2X", tx_buffer[4 + i]); - LOGMASKED(LOG_TX, "End sending packet %d result = %d time: %s\n", packet_num, result, machine().scheduler().time().as_string()); + logerror(" "); - /* update the EPH register */ - m_reg[B0_EPH_STATUS] |= TX_SUC; + for (int i = ETHERNET_ADDR_SIZE; i < buffer_len; i++) + logerror("%.2X", tx_buffer[4 + i]); - // Set LINK_OK in status - if (0 && !(m_reg[B0_EPH_STATUS] & LINK_OK)) - { - m_reg[B0_EPH_STATUS] |= LINK_OK; - // Set a ethernet phy status interrupt - m_reg[B2_INTERRUPT] |= EINT_EPH; + logerror("--- %d/0x%x bytes\n", buffer_len, buffer_len); } - // Set Tx broadcast flag - if (!memcmp(ETH_BROADCAST, &tx_buffer[4], 6)) - m_reg[B0_EPH_STATUS] |= LTX_BRD; + if (buffer_len > 4) + { + if (m_link_unconnected) + { + // Set lost carrier + if (m_reg[EREG_TCR] & 0x0400) + { + m_reg[EREG_EPH_STATUS] |= 0x400; + // Clear Tx Enable on error + m_reg[EREG_TCR] &= ~0x1; + } - // Check tx queued fifo empty - if (empty_queued_tx()) - m_reg[B2_INTERRUPT] |= EINT_TX_EMPTY; + // Set signal quality error + if (m_reg[EREG_TCR] & 0x1000) + { + m_reg[EREG_EPH_STATUS] |= 0x20; + // Clear Tx Enable on error + m_reg[EREG_TCR] &= ~0x1; + } - // Set no-transmission flags - if (m_link_unconnected) - { - //m_reg[B0_EPH_STATUS] &= ~LINK_OK; - //m_reg[B0_EPH_STATUS] &= ~TX_SUC; + // Set a ethernet phy status interrupt + m_reg[EREG_INTERRUPT] |= EINT_EPH; - // Set lost carrier - if (m_reg[B0_TCR] & MON_CSN) - { - m_reg[B0_EPH_STATUS] |= LOST_CARR; - // Clear Tx Enable on error - m_reg[B0_TCR] &= ~TXENA; + // TODO: Is it necessary to clear FIFOs on error? + // Flush fifos. + //clear_tx_fifo(); + //clear_rx_fifo(); } - - // Set signal quality error - if (m_reg[B0_TCR] & STP_SQET) + else { - m_reg[B0_EPH_STATUS] |= SQET; - // Clear Tx Enable on error - m_reg[B0_TCR] &= ~TXENA; - } + // Send the frame + if (!send(&tx_buffer[4], buffer_len)) + { + // FIXME: failed to send the Ethernet packet + //logerror("failed to send Ethernet packet\n"); + //LOG(this,("read_command_port(): !!! failed to send Ethernet packet")); + } - // Set a ethernet phy status interrupt - m_reg[B2_INTERRUPT] |= EINT_EPH; + // Loopback if loopback is set or fduplx is set + // TODO: Figure out correct size + // TODO: Check for addtional filter options for FDUPLX mode + if ((m_reg[EREG_TCR] & 0x2002) || (m_network_available && (m_reg[EREG_TCR] & 0x0800))) + recv_cb(&tx_buffer[4], buffer_len); + } } - // Update status in the transmit word - *(u16*)&tx_buffer[0] = m_reg[B0_EPH_STATUS]; + tx_buffer[0] = m_reg[EREG_EPH_STATUS]; + tx_buffer[1] = m_reg[EREG_EPH_STATUS] >> 8; // Push the packet number onto the tx completion fifo - push_completed_tx(packet_num); + m_comp_tx.push_back(packet_num); update_ethernet_irq(); - // Loopback if loopback is set or fduplx is set - if (m_loopback_result) - { - //int rx_result = receive(&tx_buffer[4], result); - recv_complete_cb(m_loopback_result); + // If there is more packets to transmit then set the tx timer + if ((m_reg[EREG_TCR] & 0x1) && !m_trans_tx.empty()) { + // Shortest packet (64 bytes @ 10Mbps = 50us) + m_tx_timer->adjust(attotime::from_usec(50)); } - - // If there is more packets to transmit then start the tx polling - if ((m_reg[B0_TCR] & TXENA) && !empty_queued_tx()) - { - m_tx_poll->adjust(attotime::from_usec(10)); - } - - m_tx_active = 0; } /*------------------------------------------------- @@ -695,48 +662,53 @@ void smc91c9x_device::process_command(uint16_t data) LOG(" ALLOCATE MEMORY FOR TX (%d)", (data & 7)); { int packet_num; - if (alloc_req(1, packet_num)) - { + if (alloc_req(1, packet_num)) { LOG(" packet_num = %02x\n", (packet_num)); // Set ARR register - m_reg[B2_PNR_ARR] &= ~0xff00; - m_reg[B2_PNR_ARR] |= packet_num << 8; - m_reg[B2_INTERRUPT] |= EINT_ALLOC; + m_reg[EREG_PNR_ARR] &= ~0xff00; + m_reg[EREG_PNR_ARR] |= packet_num << 8; + m_reg[EREG_INTERRUPT] |= EINT_ALLOC; update_ethernet_irq(); } - else - { + else { logerror("ECMD_ALLOCATE: Couldn't allocate TX memory\n"); } } break; case ECMD_RESET_MMU: + /* + 0100 + - RESET MMU TO INITIAL STATE - + Frees all memory allocations, clears relevant + interrupts, resets packet FIFO pointers. + */ + LOG(" RESET MMU\n"); mmu_reset(); break; case ECMD_REMOVE_TOPFRAME_TX: LOG(" REMOVE FRAME FROM TX FIFO\n"); - if (empty_completed_tx()) + if (m_comp_tx.empty()) logerror("process_command: Trying to remove entry from empty tx completion fifo\n"); else - pop_completed_tx(); + m_comp_tx.erase(m_comp_tx.begin()); break; case ECMD_REMOVE_RELEASE_TOPFRAME_RX: - LOG(" REMOVE AND RELEASE FRAME FROM RX FIFO (PACK_NUM=%d)\n", curr_completed_rx()); + LOG(" REMOVE AND RELEASE FRAME FROM RX FIFO (PACK_NUM=%d)\n", m_comp_rx.front()); // Release memory allocation - alloc_release(curr_completed_rx()); + alloc_release(m_comp_rx.front()); // Fall through case ECMD_REMOVE_TOPFRAME_RX: LOG(" REMOVE FRAME FROM RX FIFO\n"); // remove entry from rx completion queue - if (empty_completed_rx()) + if (m_comp_rx.empty()) logerror("process_command: Trying to remove entry from empty rx completion fifo\n"); else - pop_completed_rx(); + m_comp_rx.erase(m_comp_rx.begin()); update_ethernet_irq(); m_recd++; @@ -745,7 +717,7 @@ void smc91c9x_device::process_command(uint16_t data) case ECMD_RELEASE_PACKET: { - const int packet_number = m_reg[B2_PNR_ARR] & 0xff; + const int packet_number = m_reg[EREG_PNR_ARR] & 0xff; alloc_release(packet_number); LOG(" RELEASE SPECIFIC PACKET %d\n", packet_number); } @@ -754,31 +726,33 @@ void smc91c9x_device::process_command(uint16_t data) case ECMD_ENQUEUE_PACKET: LOG(" ENQUEUE TX PACKET "); - if (m_reg[B0_TCR] & TXENA) + if (m_reg[EREG_TCR] & 0x0001) // TX EN ? { - const int packet_number = m_reg[B2_PNR_ARR] & 0xff; + const int packet_number = m_reg[EREG_PNR_ARR] & 0xff; LOG("(PACKET_NUM=%d)\n", packet_number); // Push packet number to tx transmit fifo - push_queued_tx(packet_number); - // Start timer to send frame if not already transmitting - if (!m_tx_active && !m_tx_poll->enabled()) - { - m_tx_poll->adjust(attotime::from_usec(10)); - LOG("Start polling time: %s\n", machine().scheduler().time().as_string()); - } + m_trans_tx.push_back(packet_number); + // Calculate transmit time + //uint8_t *const tx_buffer = &m_buffer[packet_number * ETHER_BUFFER_SIZE]; + //int buffer_len = ((tx_buffer[3] << 8) | tx_buffer[2]) & 0x7ff; + //buffer_len -= 6; + //int usec = ((buffer_len * 8) / 10) + 1; + // Shortest packet (64 bytes @ 10Mbps = 50us) + m_tx_timer->adjust(attotime::from_usec(50)); } break; case ECMD_RESET_FIFOS: LOG(" RESET TX FIFOS\n"); // Flush fifos. - reset_tx_fifos(); + clear_tx_fifo(); break; } // Set Busy (clear on next read) - m_reg[B2_MMU_COMMAND] |= 0x0001; - + m_reg[EREG_MMU_COMMAND] |= 0x0001; + //LOG("process_command: TxQ: %d TxComp: %d RxComp: %d TxAlloc: %04x RxAlloc: %04x\n", + // m_trans_tx.size(), m_comp_tx.size(), m_comp_rx.size(), m_alloc_tx, m_alloc_rx); } @@ -797,60 +771,60 @@ READ16_MEMBER( smc91c9x_device::read ) /* determine the effective register */ offset %= 8; - if ( offset != B0_BANK ) - offset += 8 * (m_reg[B0_BANK] & 7); + if ( offset != EREG_BANK ) + offset += 8 * (m_reg[EREG_BANK] & 7); result = m_reg[offset]; switch (offset) { - case B2_MMU_COMMAND: + case EREG_MMU_COMMAND: // Clear busy - m_reg[B2_MMU_COMMAND] &= ~0x0001; + m_reg[EREG_MMU_COMMAND] &= ~0x0001; break; - case B2_PNR_ARR: + case EREG_PNR_ARR: if ( ACCESSING_BITS_8_15 ) { - m_reg[B2_INTERRUPT] &= ~EINT_ALLOC; + m_reg[EREG_INTERRUPT] &= ~EINT_ALLOC; update_ethernet_irq(); } break; - case B2_FIFO_PORTS: + case EREG_FIFO_PORTS: result = 0; - if (!empty_completed_tx()) - result |= curr_completed_tx(); + if (!m_comp_tx.empty()) + result |= m_comp_tx.front(); else result |= 0x80; - if (!empty_completed_rx()) - result |= curr_completed_rx() << 8; + if (!m_comp_rx.empty()) + result |= m_comp_rx.front() << 8; else result |= 0x80 << 8; break; - case B2_DATA_0: /* data register */ - case B2_DATA_1: /* data register */ + case EREG_DATA_0: /* data register */ + case EREG_DATA_1: /* data register */ { uint8_t *buffer; - int addr = m_reg[B2_POINTER] & 0x7ff; + int addr = m_reg[EREG_POINTER] & 0x7ff; - if ( m_reg[B2_POINTER] & 0x8000 ) - buffer = &m_buffer[curr_completed_rx() * ETHER_BUFFER_SIZE]; + if ( m_reg[EREG_POINTER] & 0x8000 ) + buffer = &m_buffer[m_comp_rx.front() * ETHER_BUFFER_SIZE]; else - buffer = &m_buffer[(m_reg[B2_PNR_ARR] & 0x1f) * ETHER_BUFFER_SIZE];; + buffer = &m_buffer[(m_reg[EREG_PNR_ARR] & 0x1f) * ETHER_BUFFER_SIZE];; result = buffer[addr++]; if ( ACCESSING_BITS_8_15 ) result |= buffer[addr++] << 8; - if ( m_reg[B2_POINTER] & 0x4000 ) - m_reg[B2_POINTER] = (m_reg[B2_POINTER] & ~0x7ff) | (addr & 0x7ff); + if ( m_reg[EREG_POINTER] & 0x4000 ) + m_reg[EREG_POINTER] = (m_reg[EREG_POINTER] & ~0x7ff) | (addr & 0x7ff); break; } } - if (offset != B0_BANK) + if (offset != EREG_BANK) LOG("%s:smc91c9x_r(%s) = %04X & %04X\n", machine().describe_context(), ethernet_regname[offset], result, mem_mask); return result; } @@ -864,12 +838,12 @@ WRITE16_MEMBER( smc91c9x_device::write ) { /* determine the effective register */ offset %= 8; - if (offset != B0_BANK) - offset += 8 * (m_reg[B0_BANK] & 7); + if (offset != EREG_BANK) + offset += 8 * (m_reg[EREG_BANK] & 7); /* update the data generically */ - if (offset != B0_BANK && offset < sizeof(m_reg)) + if (offset != EREG_BANK && offset < sizeof(m_reg)) LOG("%s:smc91c9x_w(%s) = [%04X]<-%04X & (%04X & %04X)\n", machine().describe_context(), ethernet_regname[offset], offset, data, mem_mask , m_regmask[offset]); mem_mask &= m_regmask[offset]; @@ -878,62 +852,49 @@ WRITE16_MEMBER( smc91c9x_device::write ) /* handle it */ switch (offset) { - case B0_TCR: /* transmit control register */ + case EREG_TCR: /* transmit control register */ // Setting Tx Enable clears some status and interrupts - if ( data & TXENA ) - { - if (m_reg[B0_EPH_STATUS] & (LOST_CARR | SQET | LATCOL | E16COL)) - { - m_reg[B0_EPH_STATUS] &= ~(LOST_CARR | SQET | LATCOL | E16COL); - m_reg[B2_INTERRUPT] &= ~EINT_EPH; - update_ethernet_irq(); - } - } - if (VERBOSE & LOG_GENERAL) - { - if (data & FDSE) LOG(" FDSE\n"); - if (data & EPH_LOOP) LOG(" EPH LOOP\n"); - if (data & STP_SQET) LOG(" STP SQET\n"); - if (data & FDUPLX) LOG(" FDUPLX\n"); - if (data & MON_CSN) LOG(" MON_CSN\n"); - if (data & NOCRC) LOG(" NOCRC\n"); - if (data & PAD_EN) LOG(" PAD_EN\n"); - if (data & FORCOL) LOG(" FORCOL\n"); - if (data & LOOP) LOG(" LOOP\n"); - if (data & TXENA) LOG(" TXENA\n"); + if ( data & 0x1 ) { + m_reg[EREG_EPH_STATUS] &= ~0x420; + m_reg[EREG_INTERRUPT] &= ~EINT_EPH; + update_ethernet_irq(); } + + if (data & 0x2000) LOG(" EPH LOOP\n"); + if (data & 0x1000) LOG(" STP SQET\n"); + if (data & 0x0800) LOG(" FDUPLX\n"); + if (data & 0x0400) LOG(" MON_CSN\n"); + if (data & 0x0100) LOG(" NOCRC\n"); + if (data & 0x0080) LOG(" PAD_EN\n"); + if (data & 0x0004) LOG(" FORCOL\n"); + if (data & 0x0002) LOG(" LOOP\n"); + if (data & 0x0001) LOG(" TXENA\n"); break; - case B0_RCR: /* receive control register */ + case EREG_RCR: /* receive control register */ - if ( data & SOFT_RST) + if ( data & 0x8000 ) { - reset(); + clear_rx_fifo(); + clear_tx_fifo(); } - if ( !(data & RXEN) ) - { - reset_completed_rx(); - } - if (data & RXEN) + if ( !(data & 0x0100) ) { - // Set LINK_OK in status - m_reg[B0_EPH_STATUS] |= LINK_OK; + clear_rx_fifo(); } - if (VERBOSE & LOG_GENERAL) - { - if (data & SOFT_RST) LOG(" SOFT RST\n"); - if (data & FILT_CAR) LOG(" FILT_CAR\n"); - if (data & STRIP_CRC) LOG(" STRIP CRC\n"); - if (data & RXEN) LOG(" RXEN\n"); - if (data & ALMUL) LOG(" ALMUL\n"); - if (data & PRMS) LOG(" PRMS\n"); - if (data & RX_ABORT) LOG(" RX_ABORT\n"); - } + if (data & 0x8000) reset(); + if (data & 0x8000) LOG(" SOFT RST\n"); + if (data & 0x4000) LOG(" FILT_CAR\n"); + if (data & 0x0200) LOG(" STRIP CRC\n"); + if (data & 0x0100) LOG(" RXEN\n"); + if (data & 0x0004) LOG(" ALMUL\n"); + if (data & 0x0002) LOG(" PRMS\n"); + if (data & 0x0001) LOG(" RX_ABORT\n"); break; - case B1_CONFIG: /* configuration register */ + case EREG_CONFIG: /* configuration register */ if (data & 0x1000) LOG(" NO WAIT\n"); if (data & 0x0400) LOG(" FULL STEP\n"); if (data & 0x0200) LOG(" SET SQLCH\n"); @@ -944,86 +905,64 @@ WRITE16_MEMBER( smc91c9x_device::write ) if (data & 0x0002) LOG(" INT SEL0\n"); break; - case B1_BASE: /* base address register */ + case EREG_BASE: /* base address register */ LOG(" base = $%04X\n", (data & 0xe000) | ((data & 0x1f00) >> 3)); LOG(" romsize = %d\n", ((data & 0xc0) >> 6)); LOG(" romaddr = $%05X\n", ((data & 0x3e) << 13)); break; - case B1_IA4_5: - set_promisc(m_reg[B0_RCR] & PRMS); - set_mac((char *)&m_reg[B1_IA0_1]); - - break; - - case B1_CONTROL: /* control register */ - // Clearing LE_EN clears interrupt from LINK_OK status change - if (!(data & LE_ENABLE)) - { - m_reg[B2_INTERRUPT] &= ~EINT_EPH; - update_ethernet_irq(); - } - if (0 && (data & LE_ENABLE)) - { - if (m_reg[B0_EPH_STATUS] & LINK_OK) - { - m_reg[B0_EPH_STATUS] &= ~(LINK_OK); - m_reg[B2_INTERRUPT] &= ~EINT_EPH; - update_ethernet_irq(); - } - } - if (VERBOSE & LOG_GENERAL) - { - if (data & RCV_BAD) LOG(" RCV_BAD\n"); - if (data & PWRDN) LOG(" PWRDN\n"); - if (data & WAKEUP_EN) LOG(" WAKEUP ENABLE\n"); - if (data & AUTO_RELEASE) LOG(" AUTO RELEASE\n"); - if (data & LE_ENABLE) LOG(" LE ENABLE\n"); - if (data & CR_ENABLE) LOG(" CR ENABLE\n"); - if (data & TE_ENABLE) LOG(" TE ENABLE\n"); - if (data & EEPROM_SEL) LOG(" EEPROM SELECT\n"); - if (data & RELOAD) LOG(" RELOAD\n"); - if (data & STORE) LOG(" STORE\n"); - } + case EREG_CONTROL: /* control register */ + if (data & 0x4000) LOG(" RCV_BAD\n"); + if (data & 0x2000) LOG(" PWRDN\n"); + if (data & 0x0800) LOG(" AUTO RELEASE\n"); + if (data & 0x0080) LOG(" LE ENABLE\n"); + if (data & 0x0040) LOG(" CR ENABLE\n"); + if (data & 0x0020) LOG(" TE ENABLE\n"); + if (data & 0x0004) LOG(" EEPROM SELECT\n"); + if (data & 0x0002) LOG(" RELOAD\n"); + if (data & 0x0001) LOG(" STORE\n"); break; - case B2_MMU_COMMAND: /* command register */ + case EREG_MMU_COMMAND: /* command register */ process_command(data); break; - case B2_DATA_0: /* data register */ - case B2_DATA_1: /* data register */ + case EREG_DATA_0: /* data register */ + case EREG_DATA_1: /* data register */ { uint8_t *buffer; - int addr = m_reg[B2_POINTER] & PTR; + int addr = m_reg[EREG_POINTER] & 0x7ff; - if (m_reg[B2_POINTER] & RCV) - buffer = &m_buffer[curr_completed_rx() * ETHER_BUFFER_SIZE]; + if (m_reg[EREG_POINTER] & 0x8000) + buffer = &m_buffer[m_comp_rx.front() * ETHER_BUFFER_SIZE]; else - buffer = &m_buffer[(m_reg[B2_PNR_ARR] & 0x1f) * ETHER_BUFFER_SIZE];; + buffer = &m_buffer[(m_reg[EREG_PNR_ARR] & 0x1f) * ETHER_BUFFER_SIZE];; + // TODO: Should be checking if incr is set buffer[addr++] = data; if ( ACCESSING_BITS_8_15 ) buffer[addr++] = data >> 8; - if ( m_reg[B2_POINTER] & AUTO_INCR) - m_reg[B2_POINTER] = (m_reg[B2_POINTER] & ~PTR) | (addr & PTR); + if ( m_reg[EREG_POINTER] & 0x4000 ) + m_reg[EREG_POINTER] = (m_reg[EREG_POINTER] & ~0x7ff) | (addr & 0x7ff); break; } - case B2_INTERRUPT: + case EREG_INTERRUPT: // Pop tx fifo packet from completion fifo if clear tx int is set - if (m_reg[B2_INTERRUPT] & data & EINT_TX) - { - if (empty_completed_tx()) + if (m_reg[EREG_INTERRUPT] & data & EINT_TX) { + if (m_comp_tx.empty()) { logerror("write: Trying to remove an entry from empty tx completion fifo\n"); - else - { - LOG("Removing tx completion packet_num = %d\n", curr_completed_tx()); - pop_completed_tx(); } + else { + LOG("Removing tx completion packet_num = %d\n", m_comp_tx.front()); + m_comp_tx.erase(m_comp_tx.begin()); + } + } + // Clear TX_EMPTY interrupt if clear tx empty bit is set + if (m_reg[EREG_INTERRUPT] & data & EINT_TX_EMPTY) { + m_reg[EREG_INTERRUPT] &= ~EINT_TX_EMPTY; } - // Clear interrupts - m_reg[B2_INTERRUPT] &= ~(data & (EINT_ERCV | EINT_RX_OVRN | EINT_TX_EMPTY | EINT_TX)); + m_reg[EREG_INTERRUPT] &= ~(data & 0x56); update_ethernet_irq(); break; } diff --git a/src/devices/machine/smc91c9x.h b/src/devices/machine/smc91c9x.h index b84f6070ef7..79fb52fcd0d 100644 --- a/src/devices/machine/smc91c9x.h +++ b/src/devices/machine/smc91c9x.h @@ -4,15 +4,13 @@ SMC91C9X ethernet controller implementation - by Aaron Giles, Ted Green + by Aaron Giles, Jean-François DEL NERO **************************************************************************/ #ifndef MAME_MACHINE_SMC91C9X_H #define MAME_MACHINE_SMC91C9X_H -#pragma once - /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ @@ -24,206 +22,39 @@ public: DECLARE_READ16_MEMBER( read ); DECLARE_WRITE16_MEMBER( write ); + TIMER_CALLBACK_MEMBER(send_frame); + virtual void recv_cb(uint8_t *data, int length) override; void set_link_connected(bool connected) { m_link_unconnected = !connected; }; protected: - enum class dev_type { - SMC91C94, - SMC91C96 - }; - - smc91c9x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, dev_type device_type); + smc91c9x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); // device-level overrides virtual void device_start() override; virtual void device_reset() override; - // device_network_interface overrides - virtual void send_complete_cb(int result) override; - virtual int recv_start_cb(u8 *buf, int length) override; - virtual void recv_complete_cb(int result) override; - - void dump_bytes(u8 *buf, int length); - int address_filter(u8 *buf); - int receive(u8 *buf, int length); - - TIMER_CALLBACK_MEMBER(tx_poll); - - const dev_type m_device_type; - unsigned m_num_ebuf; + virtual void device_pre_save(void) override; + virtual void device_post_load(void) override; private: - // Ethernet registers - bank 0 - enum bank0_addr : u8 { - B0_TCR = (0 * 8 + 0), - B0_EPH_STATUS = (0 * 8 + 1), - B0_RCR = (0 * 8 + 2), - B0_COUNTER = (0 * 8 + 3), - B0_MIR = (0 * 8 + 4), - B0_MCR = (0 * 8 + 5), - B0_BANK = (0 * 8 + 7) - }; - - // Ethernet registers - bank 1 - enum bank1_addr : u8 { - B1_CONFIG = (1 * 8 + 0), - B1_BASE = (1 * 8 + 1), - B1_IA0_1 = (1 * 8 + 2), - B1_IA2_3 = (1 * 8 + 3), - B1_IA4_5 = (1 * 8 + 4), - B1_GENERAL_PURP = (1 * 8 + 5), - B1_CONTROL = (1 * 8 + 6) - }; - - // Ethernet registers - bank 2 - enum bank2_addr : u8 { - B2_MMU_COMMAND = (2 * 8 + 0), - B2_PNR_ARR = (2 * 8 + 1), - B2_FIFO_PORTS = (2 * 8 + 2), - B2_POINTER = (2 * 8 + 3), - B2_DATA_0 = (2 * 8 + 4), - B2_DATA_1 = (2 * 8 + 5), - B2_INTERRUPT = (2 * 8 + 6) - }; - - // Ethernet registers - bank 3 - enum bank3_addr : u8 { - B3_MT0_1 = (3 * 8 + 0), - B3_MT2_3 = (3 * 8 + 1), - B3_MT4_5 = (3 * 8 + 2), - B3_MT6_7 = (3 * 8 + 3), - B3_MGMT = (3 * 8 + 4), - B3_REVISION = (3 * 8 + 5), - B3_ERCV = (3 * 8 + 6) - }; - - // Ethernet MMU commands - enum mmu_cmd : u8 { - ECMD_NOP = 0, - ECMD_ALLOCATE = 2, - ECMD_RESET_MMU = 4, - ECMD_REMOVE_TOPFRAME_RX = 6, - ECMD_REMOVE_TOPFRAME_TX = 7, - ECMD_REMOVE_RELEASE_TOPFRAME_RX = 8, - ECMD_RELEASE_PACKET = 10, - ECMD_ENQUEUE_PACKET = 12, - ECMD_RESET_FIFOS = 14 - }; - - // Ethernet interrupt bits - enum eint_def : u8 { - EINT_RCV = 0x01, - EINT_TX = 0x02, - EINT_TX_EMPTY = 0x04, - EINT_ALLOC = 0x08, - EINT_RX_OVRN = 0x10, - EINT_EPH = 0x20, - EINT_ERCV = 0x40, // 91c92 only - EINT_TX_IDLE = 0x80 // 91c94 only - }; - - // Address filter return codes - enum addr_filter_def : int { - ADDR_NOMATCH = 0, - ADDR_UNICAST = 1, - ADDR_BROADCAST = 2, - ADDR_MULTICAST = 3 - }; - - // Rx/Tx control bits - enum control_mask : u8 { - EBUF_RX_ALWAYS = 0x40, // Always set on receive buffer control byte - EBUF_ODD = 0x20, // Odd number of data payload bytes - EBUF_CRC = 0x10 // Tx add CRC - }; - - // Receive buffer status - enum rx_status_mask : u16 { - ALGNERR = 0x8000, - BRODCAST = 0x4000, - BADCRC = 0x2000, - ODDFRM = 0x1000, - TOOLNG = 0x0800, // Received fram is longer than 1518 bytes on cable - TOOSHORT = 0x0400, // Received fram is shorter than 64 bytes on cable - HASHVALUE = 0x007e, - MULTCAST = 0x0001 - }; - - // EPH Status bits - enum eph_mask : u16 { - LINK_OK = 0x4000, // State of link integrity test - CTR_ROL = 0x1000, // Counter roll Over - EXC_DEF = 0x0800, // Excessive deferral - LOST_CARR = 0x0400, // Lost carrier sense - LATCOL = 0x0200, // Late collisions detected - WAKEUP = 0x0100, // Magic packet received - TX_DEFER = 0x0080, // Transmit deferred - LTX_BRD = 0x0040, // Last transmit frame was a broadcast - SQET = 0x0020, // Signal Quality Error Test - E16COL = 0x0010, // 16 collisions reached - LTX_MULT = 0x0008, // Last transmit frame was a multicast - MULCOL = 0x0004, // Multiple collisions detected - SNGLCOL = 0x0002, // Single collision detected - TX_SUC = 0x0001 // Last transmit frame was successful - }; - - // CTR register bits - enum ctr_mask : u16 { - RCV_BAD = 0x4000, // Receive bad CRC packets - PWRDN = 0x2000, // Power down ethernet - WAKEUP_EN = 0x1000, // Enable magic packet wakeup - AUTO_RELEASE = 0x0800, // Release transmit packets on good transmission - LE_ENABLE = 0x0080, // Link Error enable - CR_ENABLE = 0x0040, // Counter Roll over enable - TE_ENABLE = 0x0020, // Transmit Error enable - EEPROM_SEL = 0x0004, // EEPROM address - RELOAD = 0x0002, // Reload config from EEPROM - STORE = 0x0001 // Store config to EEPROM - }; - - // Transmit Control Register bits - enum tcr_mask : u16 { - FDSE = 0x8000, - EPH_LOOP = 0x2000, - STP_SQET = 0x1000, - FDUPLX = 0x0800, - MON_CSN = 0x0400, - NOCRC = 0x0100, - PAD_EN = 0x0080, - FORCOL = 0x0004, - LOOP = 0x0002, - TXENA = 0x0001 - }; - - // Receive Control Register bits - enum rcr_mask : u16 { - SOFT_RST = 0x8000, - FILT_CAR = 0x4000, - STRIP_CRC = 0x0200, - RXEN = 0x0100, - ALMUL = 0x0004, - PRMS = 0x0002, - RX_ABORT = 0x0001 - }; - - // Pointer Register bits - enum pointer_mask : u16 { - RCV = 0x8000, - AUTO_INCR = 0x4000, - READ = 0x2000, - PTR = 0x07ff - }; - - static constexpr unsigned ETHER_BUFFER_SIZE = 256 * 6; - static const u8 ETH_BROADCAST[]; - static const u8 WMS_OUI[]; + static constexpr unsigned ETHER_BUFFER_SIZE = 2048; + // TODO: 96 device is larger + static constexpr unsigned ETHER_BUFFERS = 16; + static constexpr unsigned ETHERNET_ADDR_SIZE = 6; - // mmu + // external network is present + bool m_network_available; + // mmu // The bits in these vectors indicate a packet has been allocated u32 m_alloc_rx, m_alloc_tx; - + std::vector<u32> m_comp_tx, m_comp_rx; + // Fifo for allocated (queued) transmit packets + std::vector<u32> m_trans_tx; + // Save vector data and sizes for proper save state restoration + u32 m_comp_tx_data[ETHER_BUFFERS], m_comp_rx_data[ETHER_BUFFERS], m_trans_tx_data[ETHER_BUFFERS]; + u32 m_comp_tx_size, m_comp_rx_size, m_trans_tx_size; // Requests a packet allocation and returns true // and sets the packet number if successful bool alloc_req(const int tx, int &packet_num); @@ -246,56 +77,23 @@ private: uint8_t m_irq_state; // Main memory - std::unique_ptr<u8[]> m_buffer; + uint8_t m_buffer[ETHER_BUFFER_SIZE * ETHER_BUFFERS]; /* counters */ uint32_t m_sent; uint32_t m_recd; - emu_timer* m_tx_poll; + emu_timer* m_tx_timer; - int m_tx_active; - int m_rx_active; - int m_tx_retry_count; - u8 m_rx_hash; - u8 m_loopback_result; + int ethernet_packet_is_for_me(const uint8_t *mac_address); + int is_broadcast(const uint8_t *mac_address); void update_ethernet_irq(); void update_stats(); void process_command(uint16_t data); - void reset_tx_fifos(); - - // TODO: Make circular fifo a separate device - // Simple circular FIFO, power of 2 size, no over/under run checking - static constexpr unsigned FIFO_SIZE = 1 << 5; - - // FIFO for allocated (queued) transmit packets - u8 m_queued_tx[FIFO_SIZE]; - int m_queued_tx_h, m_queued_tx_t; - void reset_queued_tx() { m_queued_tx_t = m_queued_tx_h = 0; }; - void push_queued_tx(const u8 &data) { m_queued_tx[m_queued_tx_h++] = data; m_queued_tx_h &= FIFO_SIZE - 1; }; - u8 pop_queued_tx() { u8 val = m_queued_tx[m_queued_tx_t++]; m_queued_tx_t &= FIFO_SIZE - 1; return val; }; - bool empty_queued_tx() const { return m_queued_tx_h == m_queued_tx_t; }; - u8 curr_queued_tx() const { return m_queued_tx[m_queued_tx_t]; }; - - // FIFO for completed transmit packets - u8 m_completed_tx[FIFO_SIZE]; - int m_completed_tx_h, m_completed_tx_t; - void reset_completed_tx() { m_completed_tx_t = m_completed_tx_h = 0; }; - void push_completed_tx(const u8 &data) { m_completed_tx[m_completed_tx_h++] = data; m_completed_tx_h &= FIFO_SIZE - 1; }; - u8 pop_completed_tx() { u8 val = m_completed_tx[m_completed_tx_t++]; m_completed_tx_t &= FIFO_SIZE - 1; return val; }; - bool empty_completed_tx() const { return m_completed_tx_h == m_completed_tx_t; }; - u8 curr_completed_tx() const { return m_completed_tx[m_completed_tx_t]; }; - - // FIFO for completed receive packets - u8 m_completed_rx[FIFO_SIZE]; - int m_completed_rx_h, m_completed_rx_t; - void reset_completed_rx() { m_completed_rx_t = m_completed_rx_h = 0; }; - void push_completed_rx(const u8 &data) { m_completed_rx[m_completed_rx_h++] = data; m_completed_rx_h &= FIFO_SIZE - 1; }; - u8 pop_completed_rx() { u8 val = m_completed_rx[m_completed_rx_t++]; m_completed_rx_t &= FIFO_SIZE - 1; return val; }; - bool empty_completed_rx() const { return m_completed_rx_h == m_completed_rx_t; }; - u8 curr_completed_rx() const { return m_completed_rx[m_completed_rx_t]; }; + void clear_tx_fifo(); + void clear_rx_fifo(); }; diff --git a/src/devices/machine/smpc.cpp b/src/devices/machine/smpc.cpp index c62e65e1703..042fc06d590 100644 --- a/src/devices/machine/smpc.cpp +++ b/src/devices/machine/smpc.cpp @@ -205,7 +205,7 @@ void smpc_hle_device::smpc_regs(address_map &map) smpc_hle_device::smpc_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SMPC_HLE, tag, owner, clock), device_memory_interface(mconfig, *this), - m_space_config("regs", ENDIANNESS_LITTLE, 8, 7, 0, address_map_constructor(FUNC(smpc_hle_device::smpc_regs), this)), + m_space_config("regs", ENDIANNESS_LITTLE, 8, 7, 0, address_map_constructor(), address_map_constructor(FUNC(smpc_hle_device::smpc_regs), this)), m_mini_nvram(*this, "smem"), m_mshres(*this), m_mshnmi(*this), diff --git a/src/devices/machine/sonydriv.h b/src/devices/machine/sonydriv.h index 322db3f3342..b6e4358eadb 100644 --- a/src/devices/machine/sonydriv.h +++ b/src/devices/machine/sonydriv.h @@ -58,4 +58,22 @@ protected: // device type definition DECLARE_DEVICE_TYPE(FLOPPY_SONY, sonydriv_floppy_image_device) +#define MCFG_LEGACY_FLOPPY_SONY_2_DRIVES_ADD(_config) \ + MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY_SONY, 0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) \ + MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY_SONY, 0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) + +#define MCFG_LEGACY_FLOPPY_SONY_2_DRIVES_ADDITIONAL_ADD(_config) \ + MCFG_DEVICE_ADD(FLOPPY_2, FLOPPY_SONY, 0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) \ + MCFG_DEVICE_ADD(FLOPPY_3, FLOPPY_SONY, 0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) + +#define MCFG_LEGACY_FLOPPY_SONY_2_DRIVES_MODIFY(_config) \ + MCFG_DEVICE_MODIFY(FLOPPY_0) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) \ + MCFG_DEVICE_MODIFY(FLOPPY_1) \ + MCFG_LEGACY_FLOPPY_CONFIG(_config) + #endif // MAME_MACHINE_SONYDRIV_H diff --git a/src/devices/machine/spg110.cpp b/src/devices/machine/spg110.cpp deleted file mode 100644 index 9f9256f4b27..00000000000 --- a/src/devices/machine/spg110.cpp +++ /dev/null @@ -1,669 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood -/***************************************************************************** - - SunPlus SPG110-series SoC peripheral emulation - - 0032xx looks like it could be the same as 003dxx on spg2xx - but the video seems to have differences, and data - is fetched from private buffers filled by DMA instead of - main space? tile attributes different? palette format different - -**********************************************************************/ - -#include "emu.h" -#include "spg110.h" - -DEFINE_DEVICE_TYPE(SPG110, spg110_device, "spg110", "SPG110 System-on-a-Chip") - -spg110_device::spg110_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock) - , device_memory_interface(mconfig, *this) - , m_space_config("spg110", ENDIANNESS_BIG, 16, 32, 0, address_map_constructor(FUNC(spg110_device::map_video), this)) - , m_cpu(*this, finder_base::DUMMY_TAG) - , m_screen(*this, finder_base::DUMMY_TAG) - , m_palette(*this, "palette") - , m_gfxdecode(*this, "gfxdecode") - , m_palram(*this, "palram") - , m_spg_io(*this, "spg_io") - , m_porta_out(*this) - , m_portb_out(*this) - , m_portc_out(*this) - , m_porta_in(*this) - , m_portb_in(*this) - , m_portc_in(*this) - , m_adc_in{{*this}, {*this}} - , m_chip_sel(*this) -{ -} - -template<spg110_device::flipx_t FlipX> -void spg110_device::blit(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t attr, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile) -{ - address_space &space = m_cpu->space(AS_PROGRAM); - - int32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); - int32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); - - uint32_t yflipmask = attr & TILE_Y_FLIP ? h - 1 : 0; - - uint32_t nc = ((attr & 0x0003) + 1) << 1; - - uint32_t palette_offset = (attr & 0x0f00) >> 4; - - palette_offset >>= nc; - palette_offset <<= nc; - - uint32_t bits_per_row = nc * w / 16; - uint32_t words_per_tile = bits_per_row * h; - uint32_t m = bitmap_addr + words_per_tile * tile + bits_per_row * (line ^ yflipmask); - uint32_t bits = 0; - uint32_t nbits = 0; - uint32_t y = line; - - int yy = (yoff + y) & 0x1ff; - if (yy >= 0x01c0) - yy -= 0x0200; - - if (yy > 240 || yy < 0) - return; - - int y_index = yy * 320; - - for (int32_t x = FlipX ? (w - 1) : 0; FlipX ? x >= 0 : x < w; FlipX ? x-- : x++) - { - int xx = xoff + x; - - bits <<= nc; - - if (nbits < nc) - { - uint16_t b = space.read_word(m++ & 0x3fffff); - //b = (b << 8) | (b >> 8); - bits |= b << (nc - nbits); - nbits += 16; - } - nbits -= nc; - - uint32_t pal = palette_offset + (bits >> 16); - bits &= 0xffff; - - xx &= 0x01ff; - if (xx >= 0x01c0) - xx -= 0x0200; - - if (xx >= 0 && xx < 320) - { - // TODO, this is completely wrong for this palette system - int pix_index = xx + y_index; - uint16_t rawpal = m_palram[pal]; - const pen_t *pens = m_palette->pens(); - uint32_t paldata = pens[pal]; - - if (!(rawpal & 0x8000)) - { - m_screenbuf[pix_index] = paldata; - } - } - } -} - -void spg110_device::blit_page(const rectangle &cliprect, uint32_t scanline, int depth, uint32_t bitmap_addr, uint16_t *regs) -{ - uint32_t xscroll = regs[0]; - uint32_t yscroll = regs[1]; - uint32_t attr = regs[2]; - uint32_t ctrl = regs[3]; - uint32_t tilemap = regs[4]; - uint32_t palette_map = regs[5]; - address_space &space2 = this->space(0); - - if (!(ctrl & PAGE_ENABLE_MASK)) - { - return; - } - - if (((attr & PAGE_DEPTH_FLAG_MASK) >> PAGE_DEPTH_FLAG_SHIFT) != depth) - { - return; - } - - uint32_t tile_h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); - uint32_t tile_w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); - - uint32_t tile_count_x = 512 / tile_w; - - uint32_t bitmap_y = (scanline + yscroll) & 0xff; - uint32_t y0 = bitmap_y / tile_h; - uint32_t tile_scanline = bitmap_y % tile_h; - uint32_t tile_address = tile_count_x * y0; - - for (uint32_t x0 = 0; x0 < tile_count_x; x0++, tile_address++) - { - uint32_t yy = ((tile_h * y0 - yscroll + 0x10) & 0xff) - 0x10; - uint32_t xx = (tile_w * x0 - xscroll) & 0x1ff; - uint16_t tile = (ctrl & PAGE_WALLPAPER_MASK) ? space2.read_word(tilemap*2) : space2.read_word((tilemap + tile_address)*2); - uint16_t palette = 0; - - if (!tile) - continue; - - palette = space2.read_word(palette_map + tile_address / 2); - if (x0 & 1) - palette = (palette & 0xff00) >> 8; - else - palette = (palette & 0x00ff); - - - bool flip_x = 0;//(tileattr & TILE_X_FLIP); - - if (flip_x) - blit<FlipXOn>(cliprect, tile_scanline, xx, yy, attr, ctrl, bitmap_addr, tile); - else - blit<FlipXOff>(cliprect, tile_scanline, xx, yy, attr, ctrl, bitmap_addr, tile); - - } -} - - -/* correct, 4bpp gfxs */ -static const gfx_layout charlayout = -{ - 8,8, - RGN_FRAC(1,1), - 4, - { STEP4(0,1) }, - { 0*4,1*4,2*4,3*4,4*4,5*4,6*4,7*4 }, - { STEP8(0,4*8) }, - 8*8*4 -}; - -static const gfx_layout charlayout6 = -{ - 8,8, - RGN_FRAC(1,1), - 6, - { 0,1,2,3,4,5 }, - { STEP8(0,6) }, - { STEP8(0,6*8) }, - 8*8*6 -}; - -static const gfx_layout char16layout = -{ - 16,16, - RGN_FRAC(1,1), - 4, - { STEP4(0,1) }, - { 0*4,1*4,2*4,3*4,4*4,5*4,6*4,7*4, 8*4,9*4,10*4,11*4,12*4,13*4,14*4,15*4 }, - { STEP16(0,4*16) }, - 16*16*4 -}; - -static const gfx_layout char32layout = -{ - 32,32, - RGN_FRAC(1,1), - 4, - { STEP4(0,1) }, - { STEP32(0,4) }, - { STEP32(0,4*32) }, - 32*32*4 -}; - - - -static GFXDECODE_START( gfx ) - GFXDECODE_ENTRY( ":maincpu", 0, charlayout, 0, 16 ) - GFXDECODE_ENTRY( ":maincpu", 0, char16layout, 0, 16 ) - GFXDECODE_ENTRY( ":maincpu", 0, char32layout, 0, 16 ) - GFXDECODE_ENTRY( ":maincpu", 0, charlayout6, 0, 16 ) // correct for lots of the tiles inc. startup text -GFXDECODE_END - -void spg110_device::configure_spg_io(spg2xx_io_device* io) -{ - io->porta_in().set(FUNC(spg110_device::porta_r)); - io->portb_in().set(FUNC(spg110_device::portb_r)); - io->portc_in().set(FUNC(spg110_device::portc_r)); - io->porta_out().set(FUNC(spg110_device::porta_w)); - io->portb_out().set(FUNC(spg110_device::portb_w)); - io->portc_out().set(FUNC(spg110_device::portc_w)); - io->adc_in<0>().set(FUNC(spg110_device::adc_r<0>)); - io->adc_in<1>().set(FUNC(spg110_device::adc_r<1>)); - io->chip_select().set(FUNC(spg110_device::cs_w)); -// io->pal_read_callback().set(FUNC(spg110_device::get_pal_r)); -// io->write_timer_irq_callback().set(FUNC(spg110_device::timerirq_w)); -// io->write_uart_adc_irq_callback().set(FUNC(spg110_device::uartirq_w)); -// io->write_external_irq_callback().set(FUNC(spg110_device::extirq_w)); -// io->write_ffrq_tmr1_irq_callback().set(FUNC(spg110_device::ffreq1_w)); -// io->write_ffrq_tmr2_irq_callback().set(FUNC(spg110_device::ffreq2_w)); -} - -void spg110_device::device_add_mconfig(machine_config &config) -{ -// PALETTE(config, m_palette).set_format(palette_device::xRGB_555, 0x100); -// PALETTE(config, m_palette).set_format(palette_device::RGB_565, 0x100); -// PALETTE(config, m_palette).set_format(palette_device::IRGB_4444, 0x100); -// PALETTE(config, m_palette).set_format(palette_device::RGBI_4444, 0x100); -// PALETTE(config, m_palette).set_format(palette_device::xRGB_555, 0x100); - PALETTE(config, m_palette, palette_device::BLACK, 256); - - GFXDECODE(config, m_gfxdecode, m_palette, gfx); - - SPG24X_IO(config, m_spg_io, DERIVED_CLOCK(1, 1), m_cpu, m_screen); - configure_spg_io(m_spg_io); - -} - - -device_memory_interface::space_config_vector spg110_device::memory_space_config() const -{ - return space_config_vector { - std::make_pair(0, &m_space_config) - }; -} - -spg110_device::spg110_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : spg110_device(mconfig, SPG110, tag, owner, clock) -{ -} - -// irq source or similar? -READ16_MEMBER(spg110_device::spg110_2063_r) -{ - // checks for bits 0x20 and 0x08 in the IRQ function (all IRQs point to the same place) - return 0x0008; -} - -WRITE16_MEMBER(spg110_device::spg110_2063_w) -{ - // writes 0x28, probably clears the IRQ / IRQ sources? 0x63 is the same offset for this in spg2xx but bits used seem to be different - m_cpu->set_state_unsynced(UNSP_IRQ0_LINE, CLEAR_LINE); -} - - -WRITE16_MEMBER(spg110_device::spg110_201c_w) { } -WRITE16_MEMBER(spg110_device::spg110_2020_w) { } -WRITE16_MEMBER(spg110_device::spg110_2042_w) { } -WRITE16_MEMBER(spg110_device::spg110_2031_w) { } -WRITE16_MEMBER(spg110_device::spg110_2032_w) { } -WRITE16_MEMBER(spg110_device::spg110_2033_w) { } -WRITE16_MEMBER(spg110_device::spg110_2034_w) { } -WRITE16_MEMBER(spg110_device::spg110_2035_w) { } -WRITE16_MEMBER(spg110_device::spg110_2036_w) { COMBINE_DATA(&m_2036_scroll); } -WRITE16_MEMBER(spg110_device::spg110_2039_w) { } -WRITE16_MEMBER(spg110_device::spg110_2037_w) { } -WRITE16_MEMBER(spg110_device::spg110_203c_w) { } -WRITE16_MEMBER(spg110_device::spg110_203d_w) { } -WRITE16_MEMBER(spg110_device::spg110_2045_w) { } - - -WRITE16_MEMBER(spg110_device::spg110_2028_w) { } -WRITE16_MEMBER(spg110_device::spg110_2029_w) { } - -READ16_MEMBER(spg110_device::spg110_2028_r) { return 0x0000; } -READ16_MEMBER(spg110_device::spg110_2029_r) { return 0x0000; } - - -WRITE16_MEMBER(spg110_device::spg110_2050_w) { } -WRITE16_MEMBER(spg110_device::spg110_2051_w) { } -WRITE16_MEMBER(spg110_device::spg110_2052_w) { } -WRITE16_MEMBER(spg110_device::spg110_2053_w) { } -WRITE16_MEMBER(spg110_device::spg110_2054_w) { } -WRITE16_MEMBER(spg110_device::spg110_2055_w) { } -WRITE16_MEMBER(spg110_device::spg110_2056_w) { } -WRITE16_MEMBER(spg110_device::spg110_2057_w) { } -WRITE16_MEMBER(spg110_device::spg110_2058_w) { } -WRITE16_MEMBER(spg110_device::spg110_2059_w) { } -WRITE16_MEMBER(spg110_device::spg110_205a_w) { } -WRITE16_MEMBER(spg110_device::spg110_205b_w) { } -WRITE16_MEMBER(spg110_device::spg110_205c_w) { } -WRITE16_MEMBER(spg110_device::spg110_205d_w) { } -WRITE16_MEMBER(spg110_device::spg110_205e_w) { } -WRITE16_MEMBER(spg110_device::spg110_205f_w) { } - -WRITE16_MEMBER(spg110_device::dma_unk_2061_w) { COMBINE_DATA(&m_dma_unk_2061); } -WRITE16_MEMBER(spg110_device::dma_dst_step_w) { COMBINE_DATA(&m_dma_dst_step); } -WRITE16_MEMBER(spg110_device::dma_unk_2067_w) { COMBINE_DATA(&m_dma_unk_2067); } -WRITE16_MEMBER(spg110_device::dma_src_step_w) { COMBINE_DATA(&m_dma_src_step); } - -WRITE16_MEMBER(spg110_device::dma_dst_w) { COMBINE_DATA(&m_dma_dst); } -WRITE16_MEMBER(spg110_device::dma_src_w) { COMBINE_DATA(&m_dma_src); } - -WRITE16_MEMBER(spg110_device::dma_len_trigger_w) -{ - int length = data & 0x1fff; - - // this is presumably a counter that underflows to 0x1fff, because that's what the wait loop waits for? - logerror("%s: (trigger len) %04x with values (unk) %04x (dststep) %04x (unk) %04x (src step) %04x | (dst) %04x (src) %04x\n", machine().describe_context(), data, m_dma_unk_2061, m_dma_dst_step, m_dma_unk_2067, m_dma_src_step, m_dma_dst, m_dma_src); - - if ((m_dma_unk_2061!=0x0000) || (m_dma_unk_2067 != 0x0000)) - fatalerror("unknown DMA params are not zero!\n"); - - int source = m_dma_src; - int dest = m_dma_dst; - - for (int i = 0; i < length; i++) - { - address_space &mem = m_cpu->space(AS_PROGRAM); - uint16_t val = mem.read_word(source); - - this->space(0).write_word(dest * 2, val, 0xffff); - - source+=m_dma_src_step; - dest+=m_dma_dst_step; - } -} - -READ16_MEMBER(spg110_device::dma_len_status_r) -{ - return 0x1fff; // DMA related? -} - -READ16_MEMBER(spg110_device::spg110_2037_r) { return 0x0000; } -READ16_MEMBER(spg110_device::spg110_2042_r) { return 0x0000; } - - -WRITE16_MEMBER(spg110_device::spg110_3100_w) { } -WRITE16_MEMBER(spg110_device::spg110_3101_w) { } -WRITE16_MEMBER(spg110_device::spg110_3102_w) { } -WRITE16_MEMBER(spg110_device::spg110_3104_w) { } -WRITE16_MEMBER(spg110_device::spg110_3105_w) { } -WRITE16_MEMBER(spg110_device::spg110_3106_w) { } -WRITE16_MEMBER(spg110_device::spg110_3107_w) { } -WRITE16_MEMBER(spg110_device::spg110_3108_w) { } -WRITE16_MEMBER(spg110_device::spg110_3109_w) { } -WRITE16_MEMBER(spg110_device::spg110_310b_w) { } -WRITE16_MEMBER(spg110_device::spg110_310c_w) { } -WRITE16_MEMBER(spg110_device::spg110_310d_w) { } - -READ16_MEMBER(spg110_device::spg110_310f_r) { return 0x0000; } - -READ16_MEMBER(spg110_device::tmap0_regs_r) { return tmap0_regs[offset]; } -READ16_MEMBER(spg110_device::tmap1_regs_r) { return tmap1_regs[offset]; } - -void spg110_device::tilemap_write_regs(int which, uint16_t* regs, int regno, uint16_t data) -{ - switch (regno) - { - case 0x0: // Page X scroll - logerror("video_w: Page %d X Scroll = %04x\n", which, data & 0x01ff); - regs[regno] = data & 0x01ff; - break; - - case 0x1: // Page Y scroll - logerror("video_w: Page %d Y Scroll = %04x\n", which, data & 0x00ff); - regs[regno] = data & 0x00ff; - break; - - case 0x2: // Page Attributes - // 'depth' (aka z value) can't be depth here as it is on spg2xx, or the scores in attract will be behind the table, it really seems to be per attribute bit instead - - logerror("video_w: Page %d Attributes = %04x (Depth:%d, Palette:%d, VSize:%d, HSize:%d, FlipY:%d, FlipX:%d, BPP:%d)\n", which, data - , (data >> 12) & 3, (data >> 8) & 15, 8 << ((data >> 6) & 3), 8 << ((data >> 4) & 3), BIT(data, 3), BIT(data, 2), 2 * ((data & 3) + 1)); - regs[regno] = data; - break; - - case 0x3: // Page Control - logerror("video_w: Page %d Control = %04x (Blend:%d, HiColor:%d, RowScroll:%d, Enable:%d, Wallpaper:%d, RegSet:%d, Bitmap:%d)\n", which, data - , BIT(data, 8), BIT(data, 7), BIT(data, 4), BIT(data, 3), BIT(data, 2), BIT(data, 1), BIT(data, 0)); - regs[regno] = data; - break; - - case 0x4: // Page Tile Address - logerror("video_w: Page %d Tile Address = %04x\n", which, data); - regs[regno] = data; - break; - - case 0x5: // Page Attribute Address - logerror("video_w: Page %d Attribute Address = %04x\n", which, data); - regs[regno] = data; - break; - } -} - - -WRITE16_MEMBER(spg110_device::tmap0_regs_w) -{ - tilemap_write_regs(0, tmap0_regs,offset,data); -} - - -WRITE16_MEMBER(spg110_device::tmap1_regs_w) -{ - tilemap_write_regs(1, tmap1_regs,offset,data); -} - -void spg110_device::map(address_map &map) -{ - map(0x000000, 0x000fff).ram(); - - - // vregs are at 2000? - map(0x002010, 0x002015).rw(FUNC(spg110_device::tmap0_regs_r), FUNC(spg110_device::tmap0_regs_w)); - map(0x002016, 0x00201b).rw(FUNC(spg110_device::tmap1_regs_r), FUNC(spg110_device::tmap1_regs_w)); - - map(0x00201c, 0x00201c).w(FUNC(spg110_device::spg110_201c_w)); - - map(0x002020, 0x002020).w(FUNC(spg110_device::spg110_2020_w)); - - map(0x002028, 0x002028).rw(FUNC(spg110_device::spg110_2028_r), FUNC(spg110_device::spg110_2028_w)); - map(0x002029, 0x002029).rw(FUNC(spg110_device::spg110_2029_r), FUNC(spg110_device::spg110_2029_w)); - - map(0x002031, 0x002031).w(FUNC(spg110_device::spg110_2031_w)); // sometimes 14a? - map(0x002032, 0x002032).w(FUNC(spg110_device::spg110_2032_w)); // always 14a? - map(0x002033, 0x002033).w(FUNC(spg110_device::spg110_2033_w)); - map(0x002034, 0x002034).w(FUNC(spg110_device::spg110_2034_w)); - map(0x002035, 0x002035).w(FUNC(spg110_device::spg110_2035_w)); - map(0x002036, 0x002036).w(FUNC(spg110_device::spg110_2036_w)); // possible scroll register? - map(0x002037, 0x002037).rw(FUNC(spg110_device::spg110_2037_r), FUNC(spg110_device::spg110_2037_w)); - - map(0x002039, 0x002039).w(FUNC(spg110_device::spg110_2039_w)); - - map(0x00203c, 0x00203c).w(FUNC(spg110_device::spg110_203c_w)); - - map(0x00203d, 0x00203d).w(FUNC(spg110_device::spg110_203d_w)); // possible scroll register? - - map(0x002042, 0x002042).rw(FUNC(spg110_device::spg110_2042_r),FUNC(spg110_device::spg110_2042_w)); - - map(0x002045, 0x002045).w(FUNC(spg110_device::spg110_2045_w)); - - // seems to be 16 entries for.. something? - map(0x002050, 0x002050).w(FUNC(spg110_device::spg110_2050_w)); - map(0x002051, 0x002051).w(FUNC(spg110_device::spg110_2051_w)); - map(0x002052, 0x002052).w(FUNC(spg110_device::spg110_2052_w)); - map(0x002053, 0x002053).w(FUNC(spg110_device::spg110_2053_w)); - map(0x002054, 0x002054).w(FUNC(spg110_device::spg110_2054_w)); - map(0x002055, 0x002055).w(FUNC(spg110_device::spg110_2055_w)); - map(0x002056, 0x002056).w(FUNC(spg110_device::spg110_2056_w)); - map(0x002057, 0x002057).w(FUNC(spg110_device::spg110_2057_w)); - map(0x002058, 0x002058).w(FUNC(spg110_device::spg110_2058_w)); - map(0x002059, 0x002059).w(FUNC(spg110_device::spg110_2059_w)); - map(0x00205a, 0x00205a).w(FUNC(spg110_device::spg110_205a_w)); - map(0x00205b, 0x00205b).w(FUNC(spg110_device::spg110_205b_w)); - map(0x00205c, 0x00205c).w(FUNC(spg110_device::spg110_205c_w)); - map(0x00205d, 0x00205d).w(FUNC(spg110_device::spg110_205d_w)); - map(0x00205e, 0x00205e).w(FUNC(spg110_device::spg110_205e_w)); - map(0x00205f, 0x00205f).w(FUNC(spg110_device::spg110_205f_w)); - - //map(0x002010, 0x00205f).ram(); - - // everything (dma? and interrupt flag?!) - map(0x002060, 0x002060).w(FUNC(spg110_device::dma_dst_w)); - map(0x002061, 0x002061).w(FUNC(spg110_device::dma_unk_2061_w)); - map(0x002062, 0x002062).rw(FUNC(spg110_device::dma_len_status_r),FUNC(spg110_device::dma_len_trigger_w)); - map(0x002063, 0x002063).rw(FUNC(spg110_device::spg110_2063_r),FUNC(spg110_device::spg110_2063_w)); // this looks like interrupt stuff and is checked in the irq like an irq source, but why in the middle of what otherwise look like some kind of DMA? - map(0x002064, 0x002064).w(FUNC(spg110_device::dma_dst_step_w)); - map(0x002066, 0x002066).w(FUNC(spg110_device::dma_src_w)); - map(0x002067, 0x002067).w(FUNC(spg110_device::dma_unk_2067_w)); - map(0x002068, 0x002068).w(FUNC(spg110_device::dma_src_step_w)); - - map(0x002200, 0x0022ff).ram(); // looks like per-pen brightness or similar? strange because palette isn't memory mapped here - - map(0x003000, 0x00307f).ram(); // sound registers? seems to be 8 long entries, only uses up to 0x7f? - map(0x003080, 0x0030ff).ram(); - - map(0x003100, 0x003100).w(FUNC(spg110_device::spg110_3100_w)); - map(0x003101, 0x003101).w(FUNC(spg110_device::spg110_3101_w)); - map(0x003102, 0x003102).w(FUNC(spg110_device::spg110_3102_w)); - - map(0x003104, 0x003104).w(FUNC(spg110_device::spg110_3104_w)); - map(0x003105, 0x003105).w(FUNC(spg110_device::spg110_3105_w)); - map(0x003106, 0x003106).w(FUNC(spg110_device::spg110_3106_w)); - map(0x003107, 0x003107).w(FUNC(spg110_device::spg110_3107_w)); - map(0x003108, 0x003108).w(FUNC(spg110_device::spg110_3108_w)); - map(0x003109, 0x003109).w(FUNC(spg110_device::spg110_3109_w)); - - map(0x00310b, 0x00310b).w(FUNC(spg110_device::spg110_310b_w)); - map(0x00310c, 0x00310c).w(FUNC(spg110_device::spg110_310c_w)); - map(0x00310d, 0x00310d).w(FUNC(spg110_device::spg110_310d_w)); - - map(0x00310f, 0x00310f).r(FUNC(spg110_device::spg110_310f_r)); - - // 0032xx looks like it could be the same as 003d00 on spg2xx - map(0x003200, 0x00322f).rw(m_spg_io, FUNC(spg2xx_io_device::io_r), FUNC(spg2xx_io_device::io_w)); -} - -// this seems to be a different, non-cpu mapped space only accessible via the DMA? -void spg110_device::map_video(address_map &map) -{ - // are these addresses hardcoded, or can they move (in which case tilemap system isn't really suitable) - map(0x00000, 0x03fff).ram(); // 2fff? - - map(0x04000, 0x04fff).ram(); // seems to be 3 blocks, almost certainly spritelist - -// map(0x08000, 0x081ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); // probably? format unknown tho - map(0x08000, 0x081ff).ram().share("palram"); -} - - -/* -TIMER_CALLBACK_MEMBER(spg110_device::test_timer) -{ - // -} -*/ - - - -void spg110_device::device_start() -{ -// m_test_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg110_device::test_timer), this)); - save_item(NAME(m_dma_src_step)); - save_item(NAME(m_dma_dst_step)); - save_item(NAME(m_dma_unk_2061)); - save_item(NAME(m_dma_unk_2067)); - save_item(NAME(m_dma_dst)); - save_item(NAME(m_dma_src)); - save_item(NAME(m_bg_scrollx)); - save_item(NAME(m_bg_scrolly)); - save_item(NAME(m_2036_scroll)); - - m_porta_out.resolve_safe(); - m_portb_out.resolve_safe(); - m_portc_out.resolve_safe(); - m_porta_in.resolve_safe(0); - m_portb_in.resolve_safe(0); - m_portc_in.resolve_safe(0); - m_adc_in[0].resolve_safe(0x0fff); - m_adc_in[1].resolve_safe(0x0fff); - m_chip_sel.resolve_safe(); - -} - -void spg110_device::device_reset() -{ - m_dma_src_step = 0; - m_dma_dst_step = 0; - m_dma_unk_2061 = 0; - m_dma_unk_2067 = 0; - m_dma_dst = 0; - m_dma_src = 0; - m_bg_scrollx = 0; - m_bg_scrolly = 0; - m_2036_scroll = 0; -} - -double spg110_device::hue2rgb(double p, double q, double t) -{ - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1 / 6.0f) return p + (q - p) * 6 * t; - if (t < 1 / 2.0f) return q; - if (t < 2 / 3.0f) return p + (q - p) * (2 / 3.0f - t) * 6; - return p; -} - -uint32_t spg110_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - // Palette, this is still wrong! - int offs = 0; - for (int index = 0;index < 256; index++) - { - uint16_t dat = m_palram[offs++]; - - // llll lsss sshh hhhh - int l_raw = (dat & 0xf800) >> 11; - int sl_raw = (dat & 0x07c0) >> 6; - int h_raw = (dat & 0x003f) >> 0; - - double l = (double)l_raw / 31.0f; - double s = (double)sl_raw / 31.0f; - double h = (double)h_raw / 47.0f; - - double r, g, b; - - if (s == 0) { - r = g = b = l; // greyscale - } else { - double q = l < 0.5f ? l * (1 + s) : l + s - l * s; - double p = 2 * l - q; - r = hue2rgb(p, q, h + 1/3.0f); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1/3.0f); - } - - int r_real = r * 255.0f; - int g_real = g * 255.0f; - int b_real = b * 255.0f; - - m_palette->set_pen_color(index, r_real, g_real, b_real); - } - - memset(&m_screenbuf[320 * cliprect.min_y], 0, 4 * 320 * ((cliprect.max_y - cliprect.min_y) + 1)); - - const uint32_t page1_addr = 0;//0x40 * m_video_regs[0x20]; - const uint32_t page2_addr = 0;//0x40 * m_video_regs[0x21]; - uint16_t *page1_regs = tmap0_regs; - uint16_t *page2_regs = tmap1_regs; - - for (uint32_t scanline = (uint32_t)cliprect.min_y; scanline <= (uint32_t)cliprect.max_y; scanline++) - { - for (int i = 0; i < 4; i++) - { - blit_page(cliprect, scanline, i, page2_addr, page2_regs); - blit_page(cliprect, scanline, i, page1_addr, page1_regs); - //blit_sprites(cliprect, scanline, i); - } - } - - for (int y = cliprect.min_y; y <= cliprect.max_y; y++) - { - uint32_t *dest = &bitmap.pix32(y, cliprect.min_x); - uint32_t *src = &m_screenbuf[cliprect.min_x + 320 * y]; - memcpy(dest, src, sizeof(uint32_t) * ((cliprect.max_x - cliprect.min_x) + 1)); - } - - return 0; -} - -WRITE_LINE_MEMBER(spg110_device::vblank) -{ - if (!state) - { - m_cpu->set_state_unsynced(UNSP_IRQ0_LINE, ASSERT_LINE); - // m_test_timer->adjust(attotime::from_usec(100), 0); - } - - return; -} diff --git a/src/devices/machine/spg110.h b/src/devices/machine/spg110.h deleted file mode 100644 index 64464e1ba9d..00000000000 --- a/src/devices/machine/spg110.h +++ /dev/null @@ -1,220 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:David Haywood - -#ifndef MAME_MACHINE_SPG110_H -#define MAME_MACHINE_SPG110_H - -#pragma once - -//#include "spg2xx.h" -#include "cpu/unsp/unsp.h" -#include "emupal.h" -#include "spg2xx_io.h" - - -class spg110_device : public device_t, public device_memory_interface - -{ -public: - spg110_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - spg110_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - template <typename T, typename U> - spg110_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, U &&screen_tag) - : spg110_device(mconfig, tag, owner, clock) - { - m_cpu.set_tag(std::forward<T>(cpu_tag)); - m_screen.set_tag(std::forward<U>(screen_tag)); - } - - void map(address_map &map); - void map_video(address_map &map); - - double hue2rgb(double p, double q, double t); - uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(vblank); - - auto porta_out() { return m_porta_out.bind(); } - auto portb_out() { return m_portb_out.bind(); } - auto portc_out() { return m_portc_out.bind(); } - auto porta_in() { return m_porta_in.bind(); } - auto portb_in() { return m_portb_in.bind(); } - auto portc_in() { return m_portc_in.bind(); } - - template <size_t Line> auto adc_in() { return m_adc_in[Line].bind(); } - - auto chip_select() { return m_chip_sel.bind(); } - -protected: - virtual void device_start() override; - virtual void device_reset() override; - - virtual void device_add_mconfig(machine_config &config) override; - - virtual space_config_vector memory_space_config() const override; - - address_space_config m_space_config; - -private: - enum - { - PAGE_ENABLE_MASK = 0x0008, - PAGE_WALLPAPER_MASK = 0x0004, - - PAGE_DEPTH_FLAG_MASK = 0x3000, - PAGE_DEPTH_FLAG_SHIFT = 12, - PAGE_TILE_HEIGHT_MASK = 0x00c0, - PAGE_TILE_HEIGHT_SHIFT = 6, - PAGE_TILE_WIDTH_MASK = 0x0030, - PAGE_TILE_WIDTH_SHIFT = 4, - - TILE_X_FLIP = 0x0004, - TILE_Y_FLIP = 0x0008 - }; - - enum flipx_t : bool - { - FlipXOff = false, - FlipXOn = true - }; - - required_device<unsp_device> m_cpu; - required_device<screen_device> m_screen; - required_device<palette_device> m_palette; - required_device<gfxdecode_device> m_gfxdecode; - required_shared_ptr<uint16_t> m_palram; - required_device<spg2xx_io_device> m_spg_io; - - //TIMER_CALLBACK_MEMBER(test_timer); - //emu_timer *m_test_timer; - - - DECLARE_WRITE16_MEMBER(spg110_201c_w); - DECLARE_WRITE16_MEMBER(spg110_2020_w); - - DECLARE_WRITE16_MEMBER(spg110_2028_w); - DECLARE_WRITE16_MEMBER(spg110_2029_w); - - DECLARE_READ16_MEMBER(spg110_2028_r); - DECLARE_READ16_MEMBER(spg110_2029_r); - - DECLARE_WRITE16_MEMBER(spg110_2031_w); - DECLARE_WRITE16_MEMBER(spg110_2032_w); - DECLARE_WRITE16_MEMBER(spg110_2033_w); - DECLARE_WRITE16_MEMBER(spg110_2034_w); - DECLARE_WRITE16_MEMBER(spg110_2035_w); - DECLARE_WRITE16_MEMBER(spg110_2036_w); - DECLARE_WRITE16_MEMBER(spg110_2037_w); - DECLARE_WRITE16_MEMBER(spg110_2039_w); - - DECLARE_WRITE16_MEMBER(spg110_203c_w); - DECLARE_WRITE16_MEMBER(spg110_203d_w); - - DECLARE_WRITE16_MEMBER(spg110_2042_w); - - DECLARE_WRITE16_MEMBER(spg110_2045_w); - - DECLARE_WRITE16_MEMBER(spg110_2050_w); - DECLARE_WRITE16_MEMBER(spg110_2051_w); - DECLARE_WRITE16_MEMBER(spg110_2052_w); - DECLARE_WRITE16_MEMBER(spg110_2053_w); - DECLARE_WRITE16_MEMBER(spg110_2054_w); - DECLARE_WRITE16_MEMBER(spg110_2055_w); - DECLARE_WRITE16_MEMBER(spg110_2056_w); - DECLARE_WRITE16_MEMBER(spg110_2057_w); - DECLARE_WRITE16_MEMBER(spg110_2058_w); - DECLARE_WRITE16_MEMBER(spg110_2059_w); - DECLARE_WRITE16_MEMBER(spg110_205a_w); - DECLARE_WRITE16_MEMBER(spg110_205b_w); - DECLARE_WRITE16_MEMBER(spg110_205c_w); - DECLARE_WRITE16_MEMBER(spg110_205d_w); - DECLARE_WRITE16_MEMBER(spg110_205e_w); - DECLARE_WRITE16_MEMBER(spg110_205f_w); - - - DECLARE_READ16_MEMBER(spg110_2037_r); - DECLARE_READ16_MEMBER(spg110_2042_r); - - DECLARE_WRITE16_MEMBER(dma_dst_w); - DECLARE_WRITE16_MEMBER(dma_unk_2061_w); - DECLARE_WRITE16_MEMBER(dma_len_trigger_w); - DECLARE_WRITE16_MEMBER(spg110_2063_w); - DECLARE_WRITE16_MEMBER(dma_dst_step_w); - DECLARE_WRITE16_MEMBER(dma_src_w); - DECLARE_WRITE16_MEMBER(dma_unk_2067_w); - DECLARE_WRITE16_MEMBER(dma_src_step_w); - - DECLARE_READ16_MEMBER(dma_len_status_r); - DECLARE_READ16_MEMBER(spg110_2063_r); - - DECLARE_WRITE16_MEMBER(spg110_3100_w); - - DECLARE_WRITE16_MEMBER(spg110_3101_w); - DECLARE_WRITE16_MEMBER(spg110_3102_w); - DECLARE_WRITE16_MEMBER(spg110_3104_w); - DECLARE_WRITE16_MEMBER(spg110_3105_w); - DECLARE_WRITE16_MEMBER(spg110_3106_w); - DECLARE_WRITE16_MEMBER(spg110_3107_w); - DECLARE_WRITE16_MEMBER(spg110_3108_w); - DECLARE_WRITE16_MEMBER(spg110_3109_w); - - DECLARE_WRITE16_MEMBER(spg110_310b_w); - DECLARE_WRITE16_MEMBER(spg110_310c_w); - DECLARE_WRITE16_MEMBER(spg110_310d_w); - - DECLARE_READ16_MEMBER(spg110_310f_r); - - DECLARE_READ16_MEMBER(tmap0_regs_r); - DECLARE_READ16_MEMBER(tmap1_regs_r); - DECLARE_WRITE16_MEMBER(tmap0_regs_w); - DECLARE_WRITE16_MEMBER(tmap1_regs_w); - - uint16_t tmap0_regs[0x6]; - uint16_t tmap1_regs[0x6]; - - uint16_t m_dma_src_step; - uint16_t m_dma_dst_step; - uint16_t m_dma_unk_2061; - uint16_t m_dma_unk_2067; - - uint16_t m_dma_dst; - uint16_t m_dma_src; - - uint16_t m_bg_scrollx; - uint16_t m_bg_scrolly; - uint16_t m_2036_scroll; - - void tilemap_write_regs(int which, uint16_t* regs, int regno, uint16_t data); - - template<flipx_t FlipX> - void blit(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t attr, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile); - void blit_page(const rectangle &cliprect, uint32_t scanline, int depth, uint32_t bitmap_addr, uint16_t *regs); - uint32_t m_screenbuf[320 * 240]; - - devcb_write16 m_porta_out; - devcb_write16 m_portb_out; - devcb_write16 m_portc_out; - devcb_read16 m_porta_in; - devcb_read16 m_portb_in; - devcb_read16 m_portc_in; - - devcb_read16 m_adc_in[2]; - - devcb_write8 m_chip_sel; - - DECLARE_READ16_MEMBER(porta_r) { return m_porta_in(); }; - DECLARE_READ16_MEMBER(portb_r) { return m_portb_in(); }; - DECLARE_READ16_MEMBER(portc_r) { return m_portc_in(); }; - DECLARE_WRITE16_MEMBER(porta_w) { m_porta_out(offset, data, mem_mask); }; - DECLARE_WRITE16_MEMBER(portb_w) { m_portb_out(offset, data, mem_mask); }; - DECLARE_WRITE16_MEMBER(portc_w) { m_portc_out(offset, data, mem_mask); }; - template <size_t Line> DECLARE_READ16_MEMBER(adc_r) { return m_adc_in[Line](); }; - DECLARE_WRITE8_MEMBER(cs_w) { m_chip_sel(offset, data, mem_mask); }; - DECLARE_READ16_MEMBER(get_pal_r) { return 0; /*m_pal_flag;*/ }; - void configure_spg_io(spg2xx_io_device* io); - -}; - -DECLARE_DEVICE_TYPE(SPG110, spg110_device) - -#endif // MAME_MACHINE_SPG110_H diff --git a/src/devices/machine/spg2xx.cpp b/src/devices/machine/spg2xx.cpp index 3a3a22abac3..a325346558d 100644 --- a/src/devices/machine/spg2xx.cpp +++ b/src/devices/machine/spg2xx.cpp @@ -17,38 +17,57 @@ DEFINE_DEVICE_TYPE(SPG24X, spg24x_device, "spg24x", "SPG240-series System-on-a-Chip") DEFINE_DEVICE_TYPE(SPG28X, spg28x_device, "spg28x", "SPG280-series System-on-a-Chip") +#define LOG_IO_READS (1U << 1) +#define LOG_IO_WRITES (1U << 2) #define LOG_UNKNOWN_IO (1U << 3) #define LOG_IRQS (1U << 4) #define LOG_VLINES (1U << 5) +#define LOG_GPIO (1U << 6) +#define LOG_UART (1U << 7) +#define LOG_I2C (1U << 8) #define LOG_DMA (1U << 9) +#define LOG_SEGMENT (1U << 10) +#define LOG_WATCHDOG (1U << 11) +#define LOG_TIMERS (1U << 12) +#define LOG_SPU_READS (1U << 13) +#define LOG_SPU_WRITES (1U << 14) +#define LOG_UNKNOWN_SPU (1U << 15) +#define LOG_CHANNEL_READS (1U << 16) +#define LOG_CHANNEL_WRITES (1U << 17) +#define LOG_ENVELOPES (1U << 18) +#define LOG_SAMPLES (1U << 19) +#define LOG_RAMPDOWN (1U << 20) +#define LOG_BEAT (1U << 21) #define LOG_PPU_READS (1U << 22) #define LOG_PPU_WRITES (1U << 23) #define LOG_UNKNOWN_PPU (1U << 24) -#define LOG_IO (LOG_IRQS | LOG_DMA | LOG_UNKNOWN_IO) +#define LOG_IO (LOG_IO_READS | LOG_IO_WRITES | LOG_IRQS | LOG_GPIO | LOG_UART | LOG_I2C | LOG_DMA | LOG_TIMERS | LOG_UNKNOWN_IO) +#define LOG_CHANNELS (LOG_CHANNEL_READS | LOG_CHANNEL_WRITES) +#define LOG_SPU (LOG_SPU_READS | LOG_SPU_WRITES | LOG_UNKNOWN_SPU | LOG_CHANNEL_READS | LOG_CHANNEL_WRITES \ + | LOG_ENVELOPES | LOG_SAMPLES | LOG_RAMPDOWN | LOG_BEAT) #define LOG_PPU (LOG_PPU_READS | LOG_PPU_WRITES | LOG_UNKNOWN_PPU) -#define LOG_ALL (LOG_IO | LOG_PPU | LOG_VLINES ) +#define LOG_ALL (LOG_IO | LOG_SPU | LOG_PPU | LOG_VLINES | LOG_SEGMENT) -#define VERBOSE (0) +#define VERBOSE (LOG_UART | LOG_UNKNOWN_IO) #include "logmacro.h" #define SPG_DEBUG_VIDEO (0) +#define SPG_DEBUG_AUDIO (0) +#define IO_IRQ_ENABLE m_io_regs[0x21] +#define IO_IRQ_STATUS m_io_regs[0x22] #define VIDEO_IRQ_ENABLE m_video_regs[0x62] #define VIDEO_IRQ_STATUS m_video_regs[0x63] spg2xx_device::spg2xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) - , device_mixer_interface(mconfig, *this, 2) - , m_spg_audio(*this, "spgaudio") - , m_spg_io(*this, "spgio") - , m_rowscrolloffset(15) + , device_sound_interface(mconfig, *this) , m_porta_out(*this) , m_portb_out(*this) , m_portc_out(*this) , m_porta_in(*this) , m_portb_in(*this) , m_portc_in(*this) - , m_adc_in{{*this}, {*this}} , m_eeprom_w(*this) , m_eeprom_r(*this) , m_uart_tx(*this) @@ -78,234 +97,212 @@ void spg2xx_device::map(address_map &map) map(0x002900, 0x002aff).ram().share("scrollram"); map(0x002b00, 0x002bff).ram().share("paletteram"); map(0x002c00, 0x002fff).ram().share("spriteram"); - map(0x003000, 0x0031ff).rw(m_spg_audio, FUNC(spg2xx_audio_device::audio_r), FUNC(spg2xx_audio_device::audio_w)); - map(0x003200, 0x0033ff).rw(m_spg_audio, FUNC(spg2xx_audio_device::audio_phase_r), FUNC(spg2xx_audio_device::audio_phase_w)); - map(0x003400, 0x0037ff).rw(m_spg_audio, FUNC(spg2xx_audio_device::audio_ctrl_r), FUNC(spg2xx_audio_device::audio_ctrl_w)); - map(0x003d00, 0x003d2f).rw(m_spg_io, FUNC(spg2xx_io_device::io_r), FUNC(spg2xx_io_device::io_w)); - map(0x003d30, 0x003dff).rw(m_spg_io, FUNC(spg2xx_io_device::io_extended_r), FUNC(spg2xx_io_device::io_extended_w)); - map(0x003e00, 0x003e03).rw(FUNC(spg2xx_device::dma_r), FUNC(spg2xx_device::dma_w)); + map(0x003000, 0x0037ff).rw(FUNC(spg2xx_device::audio_r), FUNC(spg2xx_device::audio_w)); + map(0x003d00, 0x003eff).rw(FUNC(spg2xx_device::io_r), FUNC(spg2xx_device::io_w)); } void spg2xx_device::device_start() { - for (uint8_t i = 0; i < 32; i++) - { - m_rgb5_to_rgb8[i] = (i << 3) | (i >> 2); - } - for (uint16_t i = 0; i < 0x8000; i++) - { - m_rgb555_to_rgb888[i] = (m_rgb5_to_rgb8[(i >> 10) & 0x1f] << 16) | - (m_rgb5_to_rgb8[(i >> 5) & 0x1f] << 8) | - (m_rgb5_to_rgb8[(i >> 0) & 0x1f] << 0); - } m_porta_out.resolve_safe(); m_portb_out.resolve_safe(); m_portc_out.resolve_safe(); m_porta_in.resolve_safe(0); m_portb_in.resolve_safe(0); m_portc_in.resolve_safe(0); - m_adc_in[0].resolve_safe(0x0fff); - m_adc_in[1].resolve_safe(0x0fff); m_eeprom_w.resolve_safe(); m_eeprom_r.resolve_safe(0); m_uart_tx.resolve_safe(); m_chip_sel.resolve_safe(); + m_tmb1 = timer_alloc(TIMER_TMB1); + m_tmb2 = timer_alloc(TIMER_TMB2); + m_tmb1->adjust(attotime::never); + m_tmb2->adjust(attotime::never); + m_screenpos_timer = timer_alloc(TIMER_SCREENPOS); m_screenpos_timer->adjust(attotime::never); - save_item(NAME(m_hide_page0)); - save_item(NAME(m_hide_page1)); - save_item(NAME(m_hide_sprites)); - save_item(NAME(m_debug_sprites)); - save_item(NAME(m_debug_blit)); - save_item(NAME(m_debug_palette)); - save_item(NAME(m_sprite_index_to_debug)); + m_audio_beat = timer_alloc(TIMER_BEAT); + m_audio_beat->adjust(attotime::never); - save_item(NAME(m_dma_regs)); + m_stream = stream_alloc(0, 2, 44100); - save_item(NAME(m_video_regs)); - save_item(NAME(m_sprite_limit)); - save_item(NAME(m_pal_flag)); + m_channel_debug = -1; } void spg2xx_device::device_reset() { + memset(m_audio_regs, 0, 0x800 * sizeof(uint16_t)); + memset(m_sample_shift, 0, 16); + memset(m_sample_count, 0, sizeof(uint32_t) * 16); + memset(m_sample_addr, 0, sizeof(uint32_t) * 16); + memset(m_channel_rate, 0, sizeof(double) * 16); + memset(m_channel_rate_accum, 0, sizeof(double) * 16); + memset(m_rampdown_frame, 0, sizeof(uint32_t) * 16); + memset(m_envclk_frame, 4, sizeof(uint32_t) * 16); + memset(m_envelope_addr, 0, sizeof(uint32_t) * 16); + memset(m_video_regs, 0, 0x100 * sizeof(uint16_t)); - memset(m_dma_regs, 0, 0x4 * sizeof(uint16_t)); + memset(m_io_regs, 0, 0x200 * sizeof(uint16_t)); + + m_io_regs[0x23] = 0x0028; + m_uart_rx_available = false; + memset(m_uart_rx_fifo, 0, ARRAY_LENGTH(m_uart_rx_fifo)); + m_uart_rx_fifo_start = 0; + m_uart_rx_fifo_end = 0; + m_uart_rx_fifo_count = 0; m_video_regs[0x36] = 0xffff; m_video_regs[0x37] = 0xffff; m_video_regs[0x3c] = 0x0020; - m_video_regs[0x42] = 0x0001; m_hide_page0 = false; m_hide_page1 = false; m_hide_sprites = false; m_debug_sprites = false; m_debug_blit = false; - m_debug_palette = false; m_sprite_index_to_debug = 0; -} + m_debug_samples = false; + m_debug_rates = false; + m_audio_curr_beat_base_count = 0; -WRITE_LINE_MEMBER(spg2xx_device::audioirq_w) -{ - m_cpu->set_state_unsynced(UNSP_IRQ4_LINE, state); -} + m_audio_regs[AUDIO_CHANNEL_REPEAT] = 0x3f; + m_audio_regs[AUDIO_CHANNEL_ENV_MODE] = 0x3f; -WRITE_LINE_MEMBER(spg2xx_device::timerirq_w) -{ - m_cpu->set_state_unsynced(UNSP_IRQ2_LINE, state); + m_audio_beat->adjust(attotime::from_ticks(4, 281250), 0, attotime::from_ticks(4, 281250)); } -WRITE_LINE_MEMBER(spg2xx_device::uartirq_w) -{ - m_cpu->set_state_unsynced(UNSP_IRQ3_LINE, state); -} -WRITE_LINE_MEMBER(spg2xx_device::extirq_w) -{ - m_cpu->set_state_unsynced(UNSP_IRQ5_LINE, state); -} +/************************* +* Video Hardware * +*************************/ -WRITE_LINE_MEMBER(spg2xx_device::ffreq1_w) +inline uint8_t spg2xx_device::expand_rgb5_to_rgb8(uint8_t val) { - m_cpu->set_state_unsynced(UNSP_IRQ6_LINE, state); + uint8_t temp = val & 0x1f; + return (temp << 3) | (temp >> 2); } -WRITE_LINE_MEMBER(spg2xx_device::ffreq2_w) +// Perform a lerp between a and b +inline uint8_t spg2xx_device::mix_channel(uint8_t bottom, uint8_t top) { - m_cpu->set_state_unsynced(UNSP_IRQ7_LINE, state); + uint8_t alpha = (m_video_regs[0x2a] & 3) << 6; + return ((256 - alpha) * bottom + alpha * top) >> 8; } - - -READ16_MEMBER(spg2xx_device::space_r) +void spg2xx_device::mix_pixel(uint32_t offset, uint16_t rgb) { - address_space &cpuspace = m_cpu->space(AS_PROGRAM); - return cpuspace.read_word(offset); + m_screenbuf[offset].r = mix_channel(m_screenbuf[offset].r, expand_rgb5_to_rgb8(rgb >> 10)); + m_screenbuf[offset].g = mix_channel(m_screenbuf[offset].g, expand_rgb5_to_rgb8(rgb >> 5)); + m_screenbuf[offset].b = mix_channel(m_screenbuf[offset].b, expand_rgb5_to_rgb8(rgb)); } -/************************* -* Video Hardware * -*************************/ - -// Perform a lerp between a and b -inline uint8_t spg2xx_device::mix_channel(uint8_t bottom, uint8_t top) +void spg2xx_device::set_pixel(uint32_t offset, uint16_t rgb) { - uint8_t alpha = (m_video_regs[0x2a] & 3) << 6; - return ((256 - alpha) * bottom + alpha * top) >> 8; + m_screenbuf[offset].r = expand_rgb5_to_rgb8(rgb >> 10); + m_screenbuf[offset].g = expand_rgb5_to_rgb8(rgb >> 5); + m_screenbuf[offset].b = expand_rgb5_to_rgb8(rgb); } -template<spg2xx_device::blend_enable_t Blend, spg2xx_device::rowscroll_enable_t RowScroll, spg2xx_device::flipx_t FlipX> -void spg2xx_device::blit(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t attr, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile) +void spg2xx_device::blit(const rectangle &cliprect, uint32_t xoff, uint32_t yoff, uint32_t attr, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile) { address_space &space = m_cpu->space(AS_PROGRAM); - int32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); - int32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); + uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); + uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); uint32_t yflipmask = attr & TILE_Y_FLIP ? h - 1 : 0; + uint32_t xflipmask = attr & TILE_X_FLIP ? w - 1 : 0; uint32_t nc = ((attr & 0x0003) + 1) << 1; uint32_t palette_offset = (attr & 0x0f00) >> 4; - if (SPG_DEBUG_VIDEO && m_debug_blit) + if (m_debug_blit && SPG_DEBUG_VIDEO) { - printf("s:%d line:%d xy:%08x,%08x attr:%08x ctrl:%08x bitmap_addr:%08x tile:%04x\n", cliprect.min_x, line, xoff, yoff, attr, ctrl, bitmap_addr, tile); - printf("hw:%d,%d f:%d,%d yfm:%d ncols:%d pobs:%02x ", w, h, (attr & TILE_X_FLIP) ? 1 : 0, (attr & TILE_Y_FLIP) ? 1 : 0, yflipmask, nc, palette_offset); + printf("xy:%08x,%08x attr:%08x ctrl:%08x bitmap_addr:%08x tile:%04x\n", xoff, yoff, attr, ctrl, bitmap_addr, tile); + printf("hw:%d,%d f:%d,%d fm:%d,%d ncols:%d pobs:%02x ", w, h, (attr & TILE_X_FLIP) ? 1 : 0, (attr & TILE_Y_FLIP) ? 1 : 0, xflipmask, yflipmask, nc, palette_offset); } palette_offset >>= nc; palette_offset <<= nc; - if (SPG_DEBUG_VIDEO && m_debug_blit) + if (m_debug_blit && SPG_DEBUG_VIDEO) { printf("poas:%02x\n", palette_offset); } - uint32_t bits_per_row = nc * w / 16; - uint32_t words_per_tile = bits_per_row * h; - uint32_t m = bitmap_addr + words_per_tile * tile + bits_per_row * (line ^ yflipmask); + uint32_t m = bitmap_addr + nc * w*h / 16 * tile; uint32_t bits = 0; uint32_t nbits = 0; - uint32_t y = line; - - int yy = (yoff + y) & 0x1ff; - if (yy >= 0x01c0) - yy -= 0x0200; - if (yy > 240 || yy < 0) - return; - - if (SPG_DEBUG_VIDEO && m_debug_blit) - printf("%3d:\n", yy); - - int y_index = yy * 320; - - for (int32_t x = FlipX ? (w - 1) : 0; FlipX ? x >= 0 : x < w; FlipX ? x-- : x++) + for (uint32_t y = 0; y < h; y++) { - int xx = xoff + x; + int yy = (yoff + (y ^ yflipmask)) & 0x1ff; + if (yy >= 0x01c0) + yy -= 0x0200; - bits <<= nc; - if (SPG_DEBUG_VIDEO && m_debug_blit) - printf(" %08x:%d ", bits, nbits); - if (nbits < nc) - { - uint16_t b = space.read_word(m++ & 0x3fffff); - b = (b << 8) | (b >> 8); - bits |= b << (nc - nbits); - nbits += 16; - if (SPG_DEBUG_VIDEO && m_debug_blit) - printf("(%04x:%08x:%d) ", b, bits, nbits); - } - nbits -= nc; + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("%3d:\n", yy); - uint32_t pal = palette_offset + (bits >> 16); - if (SPG_DEBUG_VIDEO && m_debug_blit) - printf("%02x:%02x:%04x ", bits >> 16, pal, bits & 0xffff); - bits &= 0xffff; + for (uint32_t x = 0; x < w; x++) + { + int xx = xoff + (x ^ xflipmask); - if (RowScroll) - xx -= (int16_t)m_scrollram[(yy + m_rowscrolloffset) & 0x1ff]; + bits <<= nc; + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf(" %08x:%d ", bits, nbits); + if (nbits < nc) + { + uint16_t b = space.read_word(m++ & 0x3fffff); + b = (b << 8) | (b >> 8); + bits |= b << (nc - nbits); + nbits += 16; + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("(%04x:%08x:%d) ", b, bits, nbits); + } + nbits -= nc; - xx &= 0x01ff; - if (xx >= 0x01c0) - xx -= 0x0200; + uint32_t pal = palette_offset + (bits >> 16); + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("%02x:%02x:%04x ", bits >> 16, pal, bits & 0xffff); + bits &= 0xffff; - if (xx >= 0 && xx < 320) - { - int pix_index = xx + y_index; + if ((ctrl & 0x0010) && yy < 240) + xx -= (int16_t)m_scrollram[yy + 15]; - uint16_t rgb = m_paletteram[pal]; - if (SPG_DEBUG_VIDEO && m_debug_blit) - printf("rgb:%04x ", rgb); + xx &= 0x01ff; + if (xx >= 0x01c0) + xx -= 0x0200; - if (!(rgb & 0x8000)) + if (xx >= 0 && xx < 320 && yy >= 0 && yy < 240) { - if (Blend) + uint16_t rgb = m_paletteram[pal]; + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("rgb:%04x ", rgb); + if (!(rgb & 0x8000)) { - if (SPG_DEBUG_VIDEO && m_debug_blit) - printf("M\n"); - m_screenbuf[pix_index] = (mix_channel((uint8_t)(m_screenbuf[pix_index] >> 16), m_rgb5_to_rgb8[(rgb >> 10) & 0x1f]) << 16) | - (mix_channel((uint8_t)(m_screenbuf[pix_index] >> 8), m_rgb5_to_rgb8[(rgb >> 5) & 0x1f]) << 8) | - (mix_channel((uint8_t)(m_screenbuf[pix_index] >> 0), m_rgb5_to_rgb8[rgb & 0x1f])); + if (attr & 0x4000 || ctrl & 0x0100) + { + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("M\n"); + mix_pixel(xx + 320 * yy, rgb); + } + else + { + if (m_debug_blit && SPG_DEBUG_VIDEO) + printf("S\n"); + set_pixel(xx + 320 * yy, rgb); + } } - else + else if (m_debug_blit && SPG_DEBUG_VIDEO) { - if (SPG_DEBUG_VIDEO && m_debug_blit) - printf("S\n"); - m_screenbuf[pix_index] = m_rgb555_to_rgb888[rgb]; + printf("X\n"); } } - else if (SPG_DEBUG_VIDEO && m_debug_blit) - { - printf("X\n"); - } } } } -void spg2xx_device::blit_page(const rectangle &cliprect, uint32_t scanline, int depth, uint32_t bitmap_addr, uint16_t *regs) +void spg2xx_device::blit_page(const rectangle &cliprect, int depth, uint32_t bitmap_addr, uint16_t *regs) { uint32_t xscroll = regs[0]; uint32_t yscroll = regs[1]; @@ -325,98 +322,62 @@ void spg2xx_device::blit_page(const rectangle &cliprect, uint32_t scanline, int return; } - uint32_t tile_h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); - uint32_t tile_w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); - - uint32_t tile_count_x = 512 / tile_w; + uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); + uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); - uint32_t bitmap_y = (scanline + yscroll) & 0xff; - uint32_t y0 = bitmap_y / tile_h; - uint32_t tile_scanline = bitmap_y % tile_h; - uint32_t tile_address = tile_count_x * y0; - if (SPG_DEBUG_VIDEO && machine().input().code_pressed(KEYCODE_H)) - printf("s:%3d | baddr:%08x | yscr:%3d | bity:%3d | y0:%2d | ts:%2d\n", scanline, bitmap_addr, yscroll, bitmap_y, y0, tile_scanline); + uint32_t hn = 256 / h; + uint32_t wn = 512 / w; - if (SPG_DEBUG_VIDEO && machine().input().code_pressed(KEYCODE_EQUALS)) - m_debug_blit = true; - for (uint32_t x0 = 0; x0 < tile_count_x; x0++, tile_address++) + for (uint32_t y0 = 0; y0 < hn; y0++) { - uint32_t yy = ((tile_h * y0 - yscroll + 0x10) & 0xff) - 0x10; - uint32_t xx = (tile_w * x0 - xscroll) & 0x1ff; - uint16_t tile = (ctrl & PAGE_WALLPAPER_MASK) ? space.read_word(tilemap) : space.read_word(tilemap + tile_address); - uint16_t palette = 0; + for (uint32_t x0 = 0; x0 < wn; x0++) + { + uint16_t tile = (ctrl & PAGE_WALLPAPER_MASK) ? space.read_word(tilemap) : space.read_word(tilemap + x0 + wn * y0); + uint16_t palette = 0; + uint32_t xx, yy; - if (!tile) - continue; + if (!tile) + { + continue; + } - palette = (ctrl & PAGE_WALLPAPER_MASK) ? space.read_word(palette_map) : space.read_word(palette_map + tile_address / 2); - if (x0 & 1) - palette >>= 8; + palette = space.read_word(palette_map + (x0 + wn * y0) / 2); + if (x0 & 1) + { + palette >>= 8; + } - uint32_t tileattr = attr; - uint32_t tilectrl = ctrl; - if ((ctrl & 2) == 0) - { // -(1) bld(1) flip(2) pal(4) - tileattr &= ~0x000c; - tileattr |= (palette >> 2) & 0x000c; // flip + uint32_t tileattr = attr; + uint32_t tilectrl = ctrl; + if ((ctrl & 2) == 0) + { // -(1) bld(1) flip(2) pal(4) + tileattr &= ~0x000c; + tileattr |= (palette >> 2) & 0x000c; // flip - tileattr &= ~0x0f00; - tileattr |= (palette << 8) & 0x0f00; // palette + tileattr &= ~0x0f00; + tileattr |= (palette << 8) & 0x0f00; // palette - tilectrl &= ~0x0100; - tilectrl |= (palette << 2) & 0x0100; // blend - } + tilectrl &= ~0x0100; + tilectrl |= (palette << 2) & 0x0100; // blend + } - bool blend = (tileattr & 0x4000 || tilectrl & 0x0100); - bool row_scroll = (tilectrl & 0x0010); - bool flip_x = (tileattr & TILE_X_FLIP); + yy = ((h*y0 - yscroll + 0x10) & 0xff) - 0x10; + xx = (w*x0 - xscroll) & 0x1ff; - if (blend) - { - if (row_scroll) - { - if (flip_x) - blit<BlendOn, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, tileattr, tilectrl, bitmap_addr, tile); - else - blit<BlendOn, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, tileattr, tilectrl, bitmap_addr, tile); - } - else - { - if (flip_x) - blit<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, tileattr, tilectrl, bitmap_addr, tile); - else - blit<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, tileattr, tilectrl, bitmap_addr, tile); - } - } - else - { - if (row_scroll) - { - if (flip_x) - blit<BlendOff, RowScrollOn, FlipXOn>(cliprect, tile_scanline, xx, yy, tileattr, tilectrl, bitmap_addr, tile); - else - blit<BlendOff, RowScrollOn, FlipXOff>(cliprect, tile_scanline, xx, yy, tileattr, tilectrl, bitmap_addr, tile); - } - else - { - if (flip_x) - blit<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_scanline, xx, yy, tileattr, tilectrl, bitmap_addr, tile); - else - blit<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_scanline, xx, yy, tileattr, tilectrl, bitmap_addr, tile); - } + blit(cliprect, xx, yy, tileattr, tilectrl, bitmap_addr, tile); } } - if (SPG_DEBUG_VIDEO && machine().input().code_pressed(KEYCODE_EQUALS)) - m_debug_blit = false; } -void spg2xx_device::blit_sprite(const rectangle &cliprect, uint32_t scanline, int depth, uint32_t base_addr) +void spg2xx_device::blit_sprite(const rectangle &cliprect, int depth, uint32_t base_addr) { + address_space &space = m_cpu->space(AS_PROGRAM); uint32_t bitmap_addr = 0x40 * m_video_regs[0x22]; - uint16_t tile = m_spriteram[base_addr + 0]; - int16_t x = m_spriteram[base_addr + 1]; - int16_t y = m_spriteram[base_addr + 2]; - uint16_t attr = m_spriteram[base_addr + 3]; + + uint16_t tile = space.read_word(base_addr + 0); + int16_t x = space.read_word(base_addr + 1); + int16_t y = space.read_word(base_addr + 2); + uint16_t attr = space.read_word(base_addr + 3); if (!tile) { @@ -428,68 +389,32 @@ void spg2xx_device::blit_sprite(const rectangle &cliprect, uint32_t scanline, in return; } - const uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); - const uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); - if (!(m_video_regs[0x42] & SPRITE_COORD_TL_MASK)) { - x = (160 + x) - w / 2; - y = (120 - y) - (h / 2) + 8; - } + x = 160 + x; + y = 120 - y; - x &= 0x01ff; - y &= 0x01ff; + uint32_t h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); + uint32_t w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); - uint32_t tile_line = ((scanline - y) + 0x200) % h; - int16_t test_y = (y + tile_line) & 0x1ff; - if (test_y >= 0x01c0) - test_y -= 0x0200; - - if (test_y != scanline) - { - return; + x -= (w / 2); + y -= (h / 2) - 8; } - bool blend = (attr & 0x4000); - bool flip_x = (attr & TILE_X_FLIP); + x &= 0x01ff; + y &= 0x01ff; #if SPG_DEBUG_VIDEO if (m_debug_sprites && machine().input().code_pressed(KEYCODE_MINUS)) m_debug_blit = true; - if (blend) - { - if (flip_x) - blit<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, attr, 0, bitmap_addr, tile); - else - blit<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, attr, 0, bitmap_addr, tile); - } - else - { - if (flip_x) - blit<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, attr, 0, bitmap_addr, tile); - else - blit<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, attr, 0, bitmap_addr, tile); - } + blit(cliprect, x, y, attr, 0, bitmap_addr, tile); m_debug_blit = false; #else - if (blend) - { - if (flip_x) - blit<BlendOn, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, attr, 0, bitmap_addr, tile); - else - blit<BlendOn, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, attr, 0, bitmap_addr, tile); - } - else - { - if (flip_x) - blit<BlendOff, RowScrollOff, FlipXOn>(cliprect, tile_line, x, y, attr, 0, bitmap_addr, tile); - else - blit<BlendOff, RowScrollOff, FlipXOff>(cliprect, tile_line, x, y, attr, 0, bitmap_addr, tile); - } + blit(cliprect, x, y, attr, 0, bitmap_addr, tile); #endif } -void spg2xx_device::blit_sprites(const rectangle &cliprect, uint32_t scanline, int depth) +void spg2xx_device::blit_sprites(const rectangle &cliprect, int depth) { if (!(m_video_regs[0x42] & SPRITE_ENABLE_MASK)) { @@ -502,13 +427,13 @@ void spg2xx_device::blit_sprites(const rectangle &cliprect, uint32_t scanline, i #endif for (uint32_t n = 0; n < m_sprite_limit; n++) { - blit_sprite(cliprect, scanline, depth, 4 * n); + blit_sprite(cliprect, depth, 0x2c00 + 4 * n); } #if SPG_DEBUG_VIDEO } else { - blit_sprite(cliprect, scanline, depth, 4 * m_sprite_index_to_debug); + blit_sprite(cliprect, depth, 0x2c00 + 4 * m_sprite_index_to_debug); } #endif } @@ -522,13 +447,12 @@ void spg2xx_device::apply_saturation(const rectangle &cliprect) const float sat_adjust = (0xff - (m_video_regs[0x3c] & 0x00ff)) / (float)(0xff - 0x20); for (int y = cliprect.min_y; y <= cliprect.max_y; y++) { - uint32_t *src = &m_screenbuf[cliprect.min_x + 320 * y]; + rgbtriad_t *src = &m_screenbuf[cliprect.min_x + 320 * y]; for (int x = cliprect.min_x; x <= cliprect.max_x; x++) { - const uint32_t src_rgb = *src; - const float src_r = (uint8_t)(src_rgb >> 16) * s_u8_to_float; - const float src_g = (uint8_t)(src_rgb >> 8) * s_u8_to_float; - const float src_b = (uint8_t)(src_rgb >> 0) * s_u8_to_float; + const float src_r = src->r * s_u8_to_float; + const float src_g = src->g * s_u8_to_float; + const float src_b = src->b * s_u8_to_float; const float luma = src_r * s_gray_r + src_g * s_gray_g + src_b * s_gray_b; const float adjusted_r = luma + (src_r - luma) * sat_adjust; const float adjusted_g = luma + (src_g - luma) * sat_adjust; @@ -536,55 +460,50 @@ void spg2xx_device::apply_saturation(const rectangle &cliprect) const int integer_r = (int)floor(adjusted_r * 255.0f); const int integer_g = (int)floor(adjusted_g * 255.0f); const int integer_b = (int)floor(adjusted_b * 255.0f); - *src++ = (integer_r > 255 ? 0xff0000 : (integer_r < 0 ? 0 : ((uint8_t)integer_r << 16))) | - (integer_g > 255 ? 0x00ff00 : (integer_g < 0 ? 0 : ((uint8_t)integer_g << 8))) | - (integer_b > 255 ? 0x0000ff : (integer_b < 0 ? 0 : (uint8_t)integer_b)); + src->r = integer_r > 255 ? 255 : (integer_r < 0 ? 0 : (uint8_t)integer_r); + src->g = integer_g > 255 ? 255 : (integer_g < 0 ? 0 : (uint8_t)integer_g); + src->b = integer_b > 255 ? 255 : (integer_b < 0 ? 0 : (uint8_t)integer_b); + src++; } } } void spg2xx_device::apply_fade(const rectangle &cliprect) { - const uint16_t fade_offset = m_video_regs[0x30]; + const uint16_t fade_offset = m_video_regs[0x30] << 1; for (int y = cliprect.min_y; y <= cliprect.max_y; y++) { - uint32_t *src = &m_screenbuf[cliprect.min_x + 320 * y]; + rgbtriad_t *src = &m_screenbuf[cliprect.min_x + 320 * y]; for (int x = cliprect.min_x; x <= cliprect.max_x; x++) { - const uint32_t src_rgb = *src; - const uint8_t src_r = (src_rgb >> 16) & 0xff; - const uint8_t src_g = (src_rgb >> 8) & 0xff; - const uint8_t src_b = (src_rgb >> 0) & 0xff; - const uint8_t r = src_r - fade_offset; - const uint8_t g = src_g - fade_offset; - const uint8_t b = src_b - fade_offset; - *src++ = (r > src_r ? 0 : (r << 16)) | - (g > src_g ? 0 : (g << 8)) | - (b > src_b ? 0 : (b << 0)); + const uint16_t r = (uint16_t)src->r - fade_offset; + const uint16_t g = (uint16_t)src->g - fade_offset; + const uint16_t b = (uint16_t)src->b - fade_offset; + src->r = (r > src->r ? 0 : r); + src->g = (g > src->g ? 0 : g); + src->b = (b > src->b ? 0 : b); + src++; } } } uint32_t spg2xx_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { - memset(&m_screenbuf[320 * cliprect.min_y], 0, 4 * 320 * ((cliprect.max_y - cliprect.min_y) + 1)); + memset(&m_screenbuf[320 * cliprect.min_y], 0, 3 * 320 * ((cliprect.max_y - cliprect.min_y) + 1)); const uint32_t page1_addr = 0x40 * m_video_regs[0x20]; const uint32_t page2_addr = 0x40 * m_video_regs[0x21]; uint16_t *page1_regs = m_video_regs + 0x10; uint16_t *page2_regs = m_video_regs + 0x16; - for (uint32_t scanline = (uint32_t)cliprect.min_y; scanline <= (uint32_t)cliprect.max_y; scanline++) + for (int i = 0; i < 4; i++) { - for (int i = 0; i < 4; i++) - { - if (!SPG_DEBUG_VIDEO || !m_hide_page0) - blit_page(cliprect, scanline, i, page1_addr, page1_regs); - if (!SPG_DEBUG_VIDEO || !m_hide_page1) - blit_page(cliprect, scanline, i, page2_addr, page2_regs); - if (!SPG_DEBUG_VIDEO || !m_hide_sprites) - blit_sprites(cliprect, scanline, i); - } + if (!m_hide_page0) + blit_page(cliprect, i, page1_addr, page1_regs); + if (!m_hide_page1) + blit_page(cliprect, i, page2_addr, page2_regs); + if (!m_hide_sprites) + blit_sprites(cliprect, i); } if ((m_video_regs[0x3c] & 0x00ff) != 0x0020) @@ -597,30 +516,15 @@ uint32_t spg2xx_device::screen_update(screen_device &screen, bitmap_rgb32 &bitma apply_fade(cliprect); } + bitmap.fill(0, cliprect); for (int y = cliprect.min_y; y <= cliprect.max_y; y++) { uint32_t *dest = &bitmap.pix32(y, cliprect.min_x); - uint32_t *src = &m_screenbuf[cliprect.min_x + 320 * y]; - memcpy(dest, src, sizeof(uint32_t) * ((cliprect.max_x - cliprect.min_x) + 1)); - } - - if (SPG_DEBUG_VIDEO && m_debug_palette) - { - for (int y = cliprect.min_y; y <= cliprect.max_y && y < 128; y++) + rgbtriad_t *src = &m_screenbuf[cliprect.min_x + 320 * y]; + for (int x = cliprect.min_x; x <= cliprect.max_x; x++) { - const uint16_t high_nybble = (y / 8) << 4; - uint32_t *dest = &bitmap.pix32(y, cliprect.min_x); - for (int x = cliprect.min_x; x <= cliprect.max_x && x < 256; x++) - { - const uint16_t low_nybble = x / 16; - const uint16_t palette_entry = high_nybble | low_nybble; - const uint16_t color = m_paletteram[palette_entry]; - if (!(color & 0x8000)) - { - *dest = m_rgb555_to_rgb888[color & 0x7fff]; - } - dest++; - } + *dest++ = (src->r << 16) | (src->g << 8) | src->b; + src++; } } @@ -632,22 +536,15 @@ void spg2xx_device::do_sprite_dma(uint32_t len) address_space &mem = m_cpu->space(AS_PROGRAM); uint32_t src = m_video_regs[0x70] & 0x3fff; - uint32_t dst = m_video_regs[0x71]; + uint32_t dst = (m_video_regs[0x71] & 0x3ff) + 0x2c00; for (uint32_t j = 0; j < len; j++) { - m_spriteram[(dst + j) & 0x3ff] = mem.read_word(src + j); + mem.write_word(dst + j, mem.read_word(src + j)); } m_video_regs[0x72] = 0; - if (VIDEO_IRQ_ENABLE & 4) - { - const uint16_t old = VIDEO_IRQ_STATUS; - VIDEO_IRQ_STATUS |= 4; - const uint16_t changed = old ^ (VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS); - if (changed) - check_video_irq(); - } + VIDEO_IRQ_STATUS |= 4; } READ16_MEMBER(spg2xx_device::video_r) @@ -841,12 +738,9 @@ WRITE16_MEMBER(spg2xx_device::video_w) break; case 0x72: // Sprite DMA Length - { LOGMASKED(LOG_DMA, "video_w: Sprite DMA Length = %04x\n", data & 0x03ff); - uint16_t length = data & 0x3ff; - do_sprite_dma(length ? length : 0x400); + do_sprite_dma(data & 0x3ff); break; - } default: LOGMASKED(LOG_UNKNOWN_PPU, "video_w: Unknown register %04x = %04x\n", 0x2800 + offset, data); @@ -858,12 +752,7 @@ WRITE16_MEMBER(spg2xx_device::video_w) WRITE_LINE_MEMBER(spg2xx_device::vblank) { if (!state) - { - VIDEO_IRQ_STATUS &= ~1; - LOGMASKED(LOG_IRQS, "Setting video IRQ status to %04x\n", VIDEO_IRQ_STATUS); - check_video_irq(); return; - } #if SPG_DEBUG_VIDEO if (machine().input().code_pressed_once(KEYCODE_5)) @@ -878,22 +767,38 @@ WRITE_LINE_MEMBER(spg2xx_device::vblank) m_sprite_index_to_debug--; if (machine().input().code_pressed_once(KEYCODE_0)) m_sprite_index_to_debug++; - if (machine().input().code_pressed_once(KEYCODE_L)) - m_debug_palette = !m_debug_palette; #endif - if (VIDEO_IRQ_ENABLE & 1) +#if SPG_DEBUG_AUDIO + if (machine().input().code_pressed_once(KEYCODE_3)) + m_debug_samples = !m_debug_samples; + if (machine().input().code_pressed_once(KEYCODE_4)) + m_debug_rates = !m_debug_rates; + if (machine().input().code_pressed_once(KEYCODE_1)) { - VIDEO_IRQ_STATUS |= 1; - LOGMASKED(LOG_IRQS, "Setting video IRQ status to %04x\n", VIDEO_IRQ_STATUS); - check_video_irq(); + m_channel_debug--; + if (m_channel_debug < -1) + m_channel_debug = 15; } + if (machine().input().code_pressed_once(KEYCODE_2)) + { + m_channel_debug++; + if (m_channel_debug == 16) + m_channel_debug = -1; + } +#endif + + const uint16_t old = VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS; + VIDEO_IRQ_STATUS |= 1; + LOGMASKED(LOG_IRQS, "Setting video IRQ status to %04x\n", VIDEO_IRQ_STATUS); + const uint16_t changed = old ^ (VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS); + if (changed) + check_video_irq(); } void spg2xx_device::check_video_irq() { - LOGMASKED(LOG_IRQS, "%ssserting IRQ0 (%04x, %04x)\n", (VIDEO_IRQ_STATUS & VIDEO_IRQ_ENABLE) ? "A" : "Dea", VIDEO_IRQ_STATUS, VIDEO_IRQ_ENABLE); - m_cpu->set_state_unsynced(UNSP_IRQ0_LINE, (VIDEO_IRQ_STATUS & VIDEO_IRQ_ENABLE) ? ASSERT_LINE : CLEAR_LINE); + m_cpu->set_input_line(UNSP_IRQ0_LINE, (VIDEO_IRQ_STATUS & VIDEO_IRQ_ENABLE) ? ASSERT_LINE : CLEAR_LINE); } @@ -901,66 +806,588 @@ void spg2xx_device::check_video_irq() * Machine Hardware * *************************/ -READ16_MEMBER(spg2xx_device::dma_r) +void spg2xx_device::uart_rx(uint8_t data) { - uint16_t val = m_dma_regs[offset]; + if (!m_uart_rx_available) + { + if (BIT(m_io_regs[0x30], 6)) + { + m_io_regs[0x36] = data; + if (BIT(m_io_regs[0x30], 0)) + { + IO_IRQ_STATUS |= 0x0100; + check_irqs(0x0100); + } + m_uart_rx_available = true; + } + } + else if (m_uart_rx_fifo_count == ARRAY_LENGTH(m_uart_rx_fifo)) + { + m_io_regs[0x37] |= 0x4000; + } + else + { + m_uart_rx_fifo[m_uart_rx_fifo_end] = data; + m_uart_rx_fifo_end = (m_uart_rx_fifo_end + 1) % ARRAY_LENGTH(m_uart_rx_fifo); + m_uart_rx_fifo_count++; + } +} + +READ16_MEMBER(spg2xx_device::io_r) +{ + static const char *const gpioregs[] = { "GPIO Data Port", "GPIO Buffer Port", "GPIO Direction Port", "GPIO Attribute Port", "GPIO IRQ/Latch Port" }; + static const char gpioports[] = { 'A', 'B', 'C' }; + + uint16_t val = m_io_regs[offset]; + switch (offset) { + case 0x01: case 0x06: case 0x0b: // GPIO Data Port A/B/C + do_gpio(offset); + LOGMASKED(LOG_GPIO, "io_r: %s %c = %04x\n", gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], m_io_regs[offset]); + val = m_io_regs[offset]; + break; + + case 0x02: case 0x03: case 0x04: case 0x05: + case 0x07: case 0x08: case 0x09: case 0x0a: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: // Other GPIO regs + LOGMASKED(LOG_GPIO, "io_r: %s %c = %04x\n", gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], m_io_regs[offset]); + break; + + case 0x10: // Timebase Control + LOGMASKED(LOG_IO_READS, "io_r: Timebase Control = %04x\n", val); + break; - case 0x000: // DMA Source (L) - LOGMASKED(LOG_DMA, "dma_r: DMA Source (lo) = %04x\n", val); + case 0x1c: // Video line counter + val = m_screen->vpos(); + LOGMASKED(LOG_VLINES, "io_r: Video Line = %04x\n", val); break; - case 0x001: // DMA Source (H) - LOGMASKED(LOG_DMA, "dma_r: DMA Source (hi) = %04x\n", val); + case 0x20: // System Control + LOGMASKED(LOG_IO_READS, "io_r: System Control = %04x\n", val); break; - case 0x002: // DMA Length - LOGMASKED(LOG_DMA, "dma_r: DMA Length = %04x\n", 0); + case 0x21: // IRQ Control + LOGMASKED(LOG_IRQS, "io_r: I/O IRQ Control = %04x\n", val); + break; + + case 0x22: // IRQ Status + LOGMASKED(LOG_IRQS, "io_r: I/O IRQ Status = %04x\n", val); + break; + + case 0x23: // External Memory Control + LOGMASKED(LOG_IO_READS, "io_r: Ext. Memory Control = %04x\n", val); + break; + + case 0x25: // ADC Control + LOGMASKED(LOG_IO_READS, "io_r: ADC Control = %04x\n", val); + break; + + case 0x27: // ADC Data + m_io_regs[0x27] = 0; + LOGMASKED(LOG_IO_READS, "io_r: ADC Data = %04x\n", val); + break; + + case 0x29: // Wakeup Source + LOGMASKED(LOG_IO_READS, "io_r: Wakeup Source = %04x\n", val); + break; + + case 0x2b: + LOGMASKED(LOG_IO_READS, "io_r: NTSC/PAL = %04x\n", m_pal_flag); + return m_pal_flag; + + case 0x2c: case 0x2d: // PRNG 0/1 + val = machine().rand() & 0x0000ffff; + LOGMASKED(LOG_IO_READS, "io_r: PRNG %d = %04x\n", offset - 0x2c, val); + break; + + case 0x2e: // FIQ Source Select + LOGMASKED(LOG_IRQS, "io_r: FIQ Source Select = %04x\n", val); + break; + + case 0x2f: // Data Segment + val = m_cpu->state_int(UNSP_SR) >> 10; + LOGMASKED(LOG_SEGMENT, "io_r: Data Segment = %04x\n", val); + break; + + case 0x31: // UART Status + val |= (m_uart_rx_available ? 0x81 : 0); + LOGMASKED(LOG_UART, "io_r: UART Status = %04x\n", val); + break; + + case 0x36: // UART RX Data + if (m_uart_rx_available) + { + if (m_uart_rx_fifo_count) + { + m_io_regs[0x36] = m_uart_rx_fifo[m_uart_rx_fifo_start]; + m_uart_rx_fifo_start = (m_uart_rx_fifo_start + 1) % ARRAY_LENGTH(m_uart_rx_fifo); + m_uart_rx_fifo_count--; + } + else + { + m_uart_rx_available = false; + } + } + else + { + m_io_regs[0x37] |= 0x2000; + } + LOGMASKED(LOG_UART, "%s: io_r: UART Rx Data = %04x\n", machine().describe_context(), val); + break; + + case 0x37: // UART Rx FIFO Control + val &= ~0x0070; + val |= (m_uart_rx_available ? 7 : 0) << 4; + LOGMASKED(LOG_UART, "io_r: UART Rx FIFO Control = %04x\n", val); + break; + + case 0x59: // I2C Status + LOGMASKED(LOG_I2C, "io_r: I2C Status = %04x\n", val); + break; + + case 0x5e: // I2C Data In + LOGMASKED(LOG_I2C, "io_r: I2C Data In = %04x\n", val); + break; + + case 0x100: // DMA Source (L) + LOGMASKED(LOG_DMA, "io_r: DMA Source (lo) = %04x\n", val); + break; + + case 0x101: // DMA Source (H) + LOGMASKED(LOG_DMA, "io_r: DMA Source (hi) = %04x\n", val); + break; + + case 0x102: // DMA Length + LOGMASKED(LOG_DMA, "io_r: DMA Length = %04x\n", 0); val = 0; break; - case 0x003: // DMA Destination - LOGMASKED(LOG_DMA, "dma_r: DMA Dest = %04x\n", val); + case 0x103: // DMA Destination + LOGMASKED(LOG_DMA, "io_r: DMA Dest = %04x\n", val); break; default: - LOGMASKED(LOG_UNKNOWN_IO, "dma_r: Unknown register %04x\n", 0x3d00 + offset); + LOGMASKED(LOG_UNKNOWN_IO, "io_r: Unknown register %04x\n", 0x3d00 + offset); break; } return val; } +void spg2xx_device::update_porta_special_modes() +{ + static const char* const s_pa_special[4][16] = + { + // Input, Special 0 + // Input, Special 1 + // Output, Special 0 + // Output, Special 1 + + { "LP", "ExtClk2", "ExtClk1", "-", "SDA", "SlvRDY", "-", "-", "SPICLK", "-", "RxD", "SPISSB", "-", "-", "-", "-" }, + { "-", "-", "-", "SCK", "-", "SWS", "-", "-", "-", "-", "-", "-", "IRQ2B", "-", "-", "IRQ1B" }, + { "-", "-", "-", "SCK", "SDA", "SWS", "-", "-", "SPICLK", "TxD", "-", "SPISSB", "TAPWM", "TM1", "TBPWM", "TM2" }, + { "CSB3", "CSB2", "CSB1", "SCK", "SDA", "VSYNC", "HSYNC", "SYSCLK3", "SPICLK", "TxD", "SWS", "SPISSB", "-", "VSYNC", "HSYNC", "CSYNC" }, + }; + for (int bit = 15; bit >= 0; bit--) + { + if (!BIT(m_io_regs[0x05], bit)) + continue; + uint8_t type = (BIT(m_io_regs[0x03], bit) << 1) | BIT(m_io_regs[0x00], 0); + LOGMASKED(LOG_GPIO, " Bit %2d: %s\n", bit, s_pa_special[type][bit]); + } +} + +void spg2xx_device::update_portb_special_modes() +{ + static const char* const s_pb_special[4][8] = + { + // Input, Special 0 + // Input, Special 1 + // Output, Special 0 + // Output, Special 1 + + { "-", "-", "-", "-", "-", "-", "SDA", "SlvRDY" }, + { "-", "-", "-", "-", "-", "-", "SDA", "SlvRDY" }, + { "VSYNC", "HSYNC", "CSYNC", "-", "-", "SCK", "SDA", "SWS" }, + { "CSB3", "CSB2", "CSB1", "TBPWM", "TM2", "-", "-", "SYSCLK2" }, + }; + for (int bit = 7; bit >= 0; bit--) + { + if (!BIT(m_io_regs[0x0a], bit)) + continue; + uint8_t type = (BIT(m_io_regs[0x08], bit) << 1) | BIT(m_io_regs[0x00], 1); + LOGMASKED(LOG_GPIO, " Bit %2d: %s\n", bit, s_pb_special[type][bit]); + } +} -WRITE16_MEMBER(spg2xx_device::dma_w) +WRITE16_MEMBER(spg2xx_device::io_w) { + static const char *const gpioregs[] = { "GPIO Data Port", "GPIO Buffer Port", "GPIO Direction Port", "GPIO Attribute Port", "GPIO IRQ/Latch Port" }; + static const char gpioports[3] = { 'A', 'B', 'C' }; + switch (offset) { - case 0x000: // DMA Source (lo) - LOGMASKED(LOG_DMA, "dma_w: DMA Source (lo) = %04x\n", data); - m_dma_regs[offset] = data; + case 0x00: // GPIO special function select + { + LOGMASKED(LOG_GPIO, "io_w: GPIO Configuration = %04x (IOBWake:%d, IOAWake:%d, IOBSpecSel:%d, IOASpecSel:%d)\n", data + , BIT(data, 4), BIT(data, 3), BIT(data, 1), BIT(data, 0)); + const uint16_t old = m_io_regs[offset]; + m_io_regs[offset] = data; + const uint16_t changed = old ^ data; + if (BIT(changed, 0)) + update_porta_special_modes(); + if (BIT(changed, 1)) + update_portb_special_modes(); break; + } - case 0x001: // DMA Source (hi) - LOGMASKED(LOG_DMA, "dma_w: DMA Source (hi) = %04x\n", data); - m_dma_regs[offset] = data; + case 0x01: case 0x06: case 0x0b: // GPIO data, port A/B/C + offset++; + // Intentional fallthrough - we redirect data register writes to the buffer register. + + case 0x02: case 0x04: // Port A + case 0x07: case 0x09: // Port B + case 0x0c: case 0x0d: case 0x0e: case 0x0f: // Port C + LOGMASKED(LOG_GPIO, "io_w: %s %c = %04x\n", gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], data); + m_io_regs[offset] = data; + do_gpio(offset); + break; + + case 0x03: // Port A Direction + LOGMASKED(LOG_GPIO, "io_w: GPIO Direction Port A = %04x\n", data); + m_io_regs[offset] = data; + update_porta_special_modes(); + do_gpio(offset); break; - case 0x002: // DMA Length - LOGMASKED(LOG_DMA, "dma_w: DMA Length = %04x\n", data); - if (!(data & 0xc000)) // jak_dora writes 0xffff here which ends up trashing registers etc. why? such writes can't be valid - do_cpu_dma(data); + case 0x08: // Port B Direction + LOGMASKED(LOG_GPIO, "io_w: GPIO Direction Port B = %04x\n", data); + m_io_regs[offset] = data; + update_portb_special_modes(); + do_gpio(offset); break; - case 0x003: // DMA Destination - LOGMASKED(LOG_DMA, "dma_w: DMA Dest = %04x\n", data); - m_dma_regs[offset] = data; + case 0x05: // Port A Special + LOGMASKED(LOG_GPIO, "io_w: Port A Special Function Select: %04x\n", data); + m_io_regs[offset] = data; + update_porta_special_modes(); + break; + + case 0x0a: // Port B Special + LOGMASKED(LOG_GPIO, "io_w: Port B Special Function Select: %04x\n", data); + m_io_regs[offset] = data; + update_portb_special_modes(); + break; + + case 0x10: // Timebase Control + { + static const char* const s_tmb1_sel[2][4] = + { + { "8Hz", "16Hz", "32Hz", "64Hz" }, + { "12kHz", "24kHz", "40kHz", "40kHz" } + }; + static const char* const s_tmb2_sel[2][4] = + { + { "128Hz", "256Hz", "512Hz", "1024Hz" }, + { "105kHz", "210kHz", "420kHz", "840kHz" } + }; + static const uint32_t s_tmb1_freq[2][4] = + { + { 8, 16, 32, 64 }, + { 12000, 24000, 40000, 40000 } + }; + static const uint32_t s_tmb2_freq[2][4] = + { + { 128, 256, 512, 1024 }, + { 105000, 210000, 420000, 840000 } + }; + LOGMASKED(LOG_IO_WRITES, "io_w: Timebase Control = %04x (Source:%s, TMB2:%s, TMB1:%s)\n", data, + BIT(data, 4) ? "27MHz" : "32768Hz", s_tmb2_sel[BIT(data, 4)][(data >> 2) & 3], s_tmb1_sel[BIT(data, 4)][data & 3]); + const uint16_t old = m_io_regs[offset]; + m_io_regs[offset] = data; + const uint16_t changed = old ^ m_io_regs[offset]; + if (changed & 0x001f) + { + const uint8_t hifreq = BIT(data, 4); + if (changed & 0x0013) + { + const uint32_t freq = s_tmb1_freq[hifreq][data & 3]; + m_tmb1->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq)); + } + if (changed & 0x001c) + { + const uint32_t freq = s_tmb2_freq[hifreq][(data >> 2) & 3]; + m_tmb2->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq)); + } + } + break; + } + + case 0x11: // Timebase Clear + LOGMASKED(LOG_IO_WRITES, "io_w: Timebase Clear = %04x\n", data); + break; + + case 0x20: // System Control + { + static const char* const s_sysclk[4] = { "13.5MHz", "27MHz", "27MHz NoICE", "54MHz" }; + static const char* const s_lvd_voltage[4] = { "2.7V", "2.9V", "3.1V", "3.3V" }; + static const char* const s_weak_strong[2] = { "Weak", "Strong" }; + LOGMASKED(LOG_IO_WRITES, "io_w: System Control = %04x (Watchdog:%d, Sleep:%d, SysClk:%s, SysClkInv:%d, LVROutEn:%d, LVREn:%d\n" + , data, BIT(data, 15), BIT(data, 14), s_sysclk[(data >> 12) & 3], BIT(data, 11), BIT(data, 9), BIT(data, 8)); + LOGMASKED(LOG_IO_WRITES, " LVDEn:%d, LVDVoltSel:%s, 32kHzDisable:%d, StrWkMode:%s, VDACDisable:%d, ADACDisable:%d, ADACOutDisable:%d)\n" + , BIT(data, 7), s_lvd_voltage[(data >> 5) & 3], BIT(data, 4), s_weak_strong[BIT(data, 3)], BIT(data, 2), BIT(data, 1), BIT(data, 0)); + m_io_regs[offset] = data; + break; + } + + case 0x21: // IRQ Enable + { + LOGMASKED(LOG_IRQS, "io_w: IRQ Enable = %04x\n", data); + const uint16_t old = IO_IRQ_ENABLE & IO_IRQ_STATUS; + m_io_regs[offset] = data; + const uint16_t changed = old ^ (IO_IRQ_ENABLE & IO_IRQ_STATUS); + if (changed) + check_irqs(changed); + break; + } + + case 0x22: // IRQ Acknowledge + { + LOGMASKED(LOG_IRQS, "io_w: IRQ Acknowledge = %04x\n", data); + const uint16_t old = IO_IRQ_STATUS; + IO_IRQ_STATUS &= ~data; + const uint16_t changed = old ^ (IO_IRQ_ENABLE & IO_IRQ_STATUS); + if (changed) + check_irqs(changed); + break; + } + + case 0x23: // External Memory Control + { + static const char* const s_bus_arb[8] = + { + "Forbidden", "Forbidden", "Forbidden", "Forbidden", "Forbidden", "1:SPU/2:PPU/3:CPU", "Forbidden", "1:PPU/2:SPU/3:CPU" + }; + static const char* const s_addr_decode[4] = + { + "ROMCSB: 4000-3fffff, CSB1: ---, CSB2: ---, CSB3: ---", + "ROMCSB: 4000-1fffff, CSB1: 200000-3fffff, CSB2: ---, CSB3: ---", + "ROMCSB: 4000-0fffff, CSB1: 100000-1fffff, CSB2: 200000-2fffff, CSB3: 300000-3fffff", + "ROMCSB: 4000-0fffff, CSB1: 100000-1fffff, CSB2: 200000-2fffff, CSB3: 300000-3fffff" + }; + static const char* const s_ram_decode[16] = + { + "None", "None", "None", "None", "None", "None", "None", "None", + "4KW, 3ff000-3fffff\n", + "8KW, 3fe000-3fffff\n", + "16KW, 3fc000-3fffff\n", + "32KW, 3f8000-3fffff\n", + "64KW, 3f0000-3fffff\n", + "128KW, 3e0000-3fffff\n", + "256KW, 3c0000-3fffff\n", + "512KW, 380000-3fffff\n" + }; + LOGMASKED(LOG_IO_WRITES, "io_w: Ext. Memory Control (not yet implemented) = %04x:\n", data); + LOGMASKED(LOG_IO_WRITES, " WaitStates:%d, BusArbPrio:%s\n", (data >> 1) & 3, s_bus_arb[(data >> 3) & 7]); + LOGMASKED(LOG_IO_WRITES, " ROMAddrDecode:%s\n", s_addr_decode[(data >> 6) & 3]); + LOGMASKED(LOG_IO_WRITES, " RAMAddrDecode:%s\n", s_ram_decode[(data >> 8) & 15]); + m_chip_sel((data >> 6) & 3); + m_io_regs[offset] = data; + break; + } + + case 0x24: // Watchdog + LOGMASKED(LOG_WATCHDOG, "io_w: Watchdog Pet = %04x\n", data); + break; + + case 0x25: // ADC Control + { + LOGMASKED(LOG_IO_WRITES, "io_w: ADC Control = %04x\n", data); + //const uint16_t changed = m_io_regs[offset] ^ data; + m_io_regs[offset] = data; + //if (BIT(changed, 12) && BIT(data, 12) && !BIT(m_io_regs[offset], 1)) + { + //m_io_regs[0x27] = 0x80ff; + //const uint16_t old = IO_IRQ_STATUS; + //IO_IRQ_STATUS |= 0x2000; + //const uint16_t changed = IO_IRQ_STATUS ^ old; + //if (changed) + //check_irqs(changed); + } + break; + } + + case 0x28: // Sleep Mode + LOGMASKED(LOG_IO_WRITES, "io_w: Sleep Mode (%s enter value) = %04x\n", data == 0xaa55 ? "valid" : "invalid", data); + m_io_regs[offset] = data; + break; + + case 0x29: // Wakeup Source + { + m_io_regs[offset] = data; + static const char* const s_sources[8] = + { + "TMB1", "TMB2", "2Hz", "4Hz", "1024Hz", "2048Hz", "4096Hz", "Key" + }; + + LOGMASKED(LOG_IO_WRITES, "io_w: Wakeup Source = %04x:\n", data); + bool comma = false; + char buf[1024]; + int char_idx = 0; + for (int i = 7; i >= 0; i--) + { + if (BIT(data, i)) + { + char_idx += sprintf(&buf[char_idx], "%s%s", comma ? ", " : "", s_sources[i]); + comma = true; + } + } + buf[char_idx] = 0; + LOGMASKED(LOG_IO_WRITES, " %s\n", buf); + break; + } + + case 0x2e: // FIQ Source Select + { + static const char* const s_fiq_select[8] = + { + "PPU", "SPU Channel", "Timer A", "Timer B", "UART/SPI", "External", "Reserved", "None" + }; + LOGMASKED(LOG_IRQS, "io_w: FIQ Source Select (not yet implemented) = %04x, %s\n", data, s_fiq_select[data & 7]); + m_io_regs[offset] = data; + break; + } + + case 0x2f: // Data Segment + { + uint16_t ds = m_cpu->state_int(UNSP_SR); + m_cpu->set_state_int(UNSP_SR, (ds & 0x03ff) | ((data & 0x3f) << 10)); + LOGMASKED(LOG_SEGMENT, "io_w: Data Segment = %04x\n", data); + break; + } + + case 0x30: // UART Control + { + static const char* const s_9th_bit[4] = { "0", "1", "Odd", "Even" }; + LOGMASKED(LOG_UART, "io_w: UART Control = %04x (TxEn:%d, RxEn:%d, Bits:%d, MultiProc:%d, 9thBit:%s, TxIntEn:%d, RxIntEn:%d\n", data + , BIT(data, 7), BIT(data, 6), BIT(data, 5) ? 9 : 8, BIT(data, 4), s_9th_bit[(data >> 2) & 3], BIT(data, 1), BIT(data, 0)); + const uint16_t changed = m_io_regs[offset] ^ data; + m_io_regs[offset] = data; + if (!BIT(data, 6)) + { + m_uart_rx_available = false; + m_io_regs[0x36] = 0; + } + if (BIT(changed, 7) && BIT(data, 7)) + { + m_io_regs[0x31] |= 0x0002; + } + break; + } + + case 0x31: // UART Status + LOGMASKED(LOG_UART, "io_w: UART Status = %04x\n", data); + m_io_regs[offset] &= ~data; + break; + + case 0x33: // UART Baud Rate (low byte) + case 0x34: // UART Baud Rate (high byte) + { + m_io_regs[offset] = data; + const uint32_t divisor = 16 * (0x10000 - ((m_io_regs[0x34] << 8) | m_io_regs[0x33])); + LOGMASKED(LOG_UART, "io_w: UART Baud Rate (%s byte): Baud rate = %d\n", offset == 0x33 ? "low" : "high", 27000000 / divisor); + break; + } + + case 0x35: // UART TX Data + LOGMASKED(LOG_UART, "io_w: UART Tx Data = %02x\n", data & 0x00ff); + m_io_regs[offset] = data; + m_uart_tx((uint8_t)data); + m_io_regs[0x31] |= 2; + break; + + case 0x36: // UART RX Data + LOGMASKED(LOG_UART, "io_w: UART Rx Data (read-only) = %04x\n", data); + break; + + case 0x37: // UART Rx FIFO Control + LOGMASKED(LOG_UART, "io_w: UART Rx FIFO Control = %04x (Reset:%d, Overrun:%d, Underrun:%d, Count:%d, Threshold:%d)\n", data + , BIT(data, 15), BIT(data, 14), BIT(data, 13), (data >> 4) & 7, data & 7); + if (data & 0x8000) + { + m_uart_rx_available = false; + m_io_regs[0x36] = 0; + } + m_io_regs[offset] &= ~data & 0x6000; + m_io_regs[offset] &= ~0x0007; + m_io_regs[offset] |= data & 0x0007; + break; + + case 0x58: // I2C Command + LOGMASKED(LOG_I2C, "io_w: I2C Command = %04x\n", data); + m_io_regs[offset] = data; + do_i2c(); + break; + + case 0x59: // I2C Status / Acknowledge + LOGMASKED(LOG_I2C, "io_w: I2C Acknowledge = %04x\n", data); + m_io_regs[offset] &= ~data; + break; + + case 0x5a: // I2C Access Mode + LOGMASKED(LOG_I2C, "io_w: I2C Access Mode = %04x\n", data); + m_io_regs[offset] = data; + break; + + case 0x5b: // I2C Device Address + LOGMASKED(LOG_I2C, "io_w: I2C Device Address = %04x\n", data); + m_io_regs[offset] = data; + break; + + case 0x5c: // I2C Sub-Address + LOGMASKED(LOG_I2C, "io_w: I2C Sub-Address = %04x\n", data); + m_io_regs[offset] = data; + break; + + case 0x5d: // I2C Data Out + LOGMASKED(LOG_I2C, "io_w: I2C Data Out = %04x\n", data); + m_io_regs[offset] = data; + break; + + case 0x5e: // I2C Data In + LOGMASKED(LOG_I2C, "io_w: I2C Data In = %04x\n", data); + m_io_regs[offset] = data; + break; + + case 0x5f: // I2C Controller Mode + LOGMASKED(LOG_I2C, "io_w: I2C Controller Mode = %04x\n", data); + m_io_regs[offset] = data; + break; + + case 0x100: // DMA Source (lo) + LOGMASKED(LOG_DMA, "io_w: DMA Source (lo) = %04x\n", data); + m_io_regs[offset] = data; + break; + + case 0x101: // DMA Source (hi) + LOGMASKED(LOG_DMA, "io_w: DMA Source (hi) = %04x\n", data); + m_io_regs[offset] = data; + break; + + case 0x103: // DMA Destination + LOGMASKED(LOG_DMA, "io_w: DMA Dest = %04x\n", data); + m_io_regs[offset] = data; + break; + + case 0x102: // DMA Length + LOGMASKED(LOG_DMA, "io_w: DMA Length = %04x\n", data); + do_cpu_dma(data); break; default: - LOGMASKED(LOG_UNKNOWN_IO, "dma_w: Unknown register %04x = %04x\n", 0x3d00 + offset, data); - m_dma_regs[offset] = data; + LOGMASKED(LOG_UNKNOWN_IO, "io_w: Unknown register %04x = %04x\n", 0x3d00 + offset, data); + m_io_regs[offset] = data; break; } } @@ -969,29 +1396,145 @@ void spg2xx_device::device_timer(emu_timer &timer, device_timer_id id, int param { switch (id) { + case TIMER_TMB1: + { + LOGMASKED(LOG_TIMERS, "TMB1 elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 1, IO_IRQ_ENABLE); + IO_IRQ_STATUS |= 1; + check_irqs(0x0001); + break; + } + + case TIMER_TMB2: + { + LOGMASKED(LOG_TIMERS, "TMB2 elapsed, setting IRQ Status bit 1 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 2, IO_IRQ_ENABLE); + IO_IRQ_STATUS |= 2; + check_irqs(0x0002); + break; + } + case TIMER_SCREENPOS: { - if (VIDEO_IRQ_ENABLE & 2) + const uint16_t old = VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS; + VIDEO_IRQ_STATUS |= 2; + const uint16_t changed = old ^ (VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS); + if (changed) { - VIDEO_IRQ_STATUS |= 2; check_video_irq(); } m_screen->update_partial(m_screen->vpos()); + break; + } - // fire again, jak_dbz pinball needs this - m_screenpos_timer->adjust(m_screen->time_until_pos(m_video_regs[0x36], m_video_regs[0x37] << 1)); + case TIMER_BEAT: + { + audio_frame_tick(); break; } } } +void spg2xx_device::check_irqs(const uint16_t changed) +{ + // { + // m_cpu->set_input_line(UNSP_IRQ1_LINE, ASSERT_LINE); + // } + + if (changed & 0x0c00) // Timer A, Timer B IRQ + { + LOGMASKED(LOG_IRQS, "%ssserting IRQ2 (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b)); + m_cpu->set_input_line(UNSP_IRQ2_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE); + } + + if (changed & 0x2100) // UART, ADC IRQ + { + LOGMASKED(LOG_IRQS, "%ssserting IRQ3 (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b)); + m_cpu->set_input_line(UNSP_IRQ3_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100) ? ASSERT_LINE : CLEAR_LINE); + } + + if (changed & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) // Beat IRQ + { + if ((m_audio_regs[AUDIO_BEAT_COUNT] & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) == (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) + { + LOGMASKED(LOG_BEAT, "Asserting beat IRQ\n"); + m_cpu->set_input_line(UNSP_IRQ4_LINE, ASSERT_LINE); + } + else + { + LOGMASKED(LOG_BEAT, "Clearing beat IRQ\n"); + m_cpu->set_input_line(UNSP_IRQ4_LINE, CLEAR_LINE); + } + } + + if (changed & 0x1200) // External IRQ + { + LOGMASKED(LOG_IRQS, "%ssserting IRQ5 (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b)); + m_cpu->set_input_line(UNSP_IRQ5_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? ASSERT_LINE : CLEAR_LINE); + } + + if (changed & 0x0070) // 1024Hz, 2048Hz, 4096Hz IRQ + { + LOGMASKED(LOG_IRQS, "%ssserting IRQ6 (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b)); + m_cpu->set_input_line(UNSP_IRQ6_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE); + } + + if (changed & 0x008b) // TMB1, TMB2, 4Hz, key change IRQ + { + LOGMASKED(LOG_IRQS, "%ssserting IRQ7 (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b)); + m_cpu->set_input_line(UNSP_IRQ7_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? ASSERT_LINE : CLEAR_LINE); + } +} + +void spg2xx_device::do_gpio(uint32_t offset) +{ + uint32_t index = (offset - 1) / 5; + uint16_t buffer = m_io_regs[5 * index + 2]; + uint16_t dir = m_io_regs[5 * index + 3]; + uint16_t attr = m_io_regs[5 * index + 4]; + uint16_t special = m_io_regs[5 * index + 5]; + + uint16_t push = dir; + uint16_t pull = (~dir) & (~attr); + uint16_t what = (buffer & (push | pull)); + what ^= (dir & ~attr); + what &= ~special; + + switch (index) + { + case 0: + m_porta_out(0, what, push &~ special); + what = (what & ~pull) | (m_porta_in(0, pull &~ special) & pull); + break; + case 1: + m_portb_out(0, what, push &~ special); + what = (what & ~pull) | (m_portb_in(0, pull &~ special) & pull); + break; + case 2: + m_portc_out(0, what, push &~ special); + what = (what & ~pull) | (m_portc_in(0, pull &~ special) & pull); + break; + } + + m_io_regs[5 * index + 1] = what; +} + +void spg2xx_device::do_i2c() +{ + const uint16_t addr = ((m_io_regs[0x5b] & 0x06) << 7) | (uint8_t)m_io_regs[0x5c]; + + if (m_io_regs[0x58] & 0x40) // Serial EEPROM read + m_io_regs[0x5e] = m_eeprom_r(addr); + else + m_eeprom_w(addr, m_io_regs[0x5d]); + + m_io_regs[0x59] |= 1; +} void spg2xx_device::do_cpu_dma(uint32_t len) { address_space &mem = m_cpu->space(AS_PROGRAM); - uint32_t src = ((m_dma_regs[0x001] & 0x3f) << 16) | m_dma_regs[0x000]; - uint32_t dst = m_dma_regs[0x003] & 0x3fff; + uint32_t src = ((m_io_regs[0x101] & 0x3f) << 16) | m_io_regs[0x100]; + uint32_t dst = m_io_regs[0x103] & 0x3fff; for (uint32_t j = 0; j < len; j++) { @@ -999,56 +1542,1128 @@ void spg2xx_device::do_cpu_dma(uint32_t len) } src += len; - m_dma_regs[0x000] = (uint16_t)src; - m_dma_regs[0x001] = (src >> 16) & 0x3f; - m_dma_regs[0x002] = 0; - m_dma_regs[0x003] = (dst + len) & 0x3fff; + m_io_regs[0x100] = (uint16_t)src; + m_io_regs[0x101] = (src >> 16) & 0x3f; + m_io_regs[0x102] = 0; + m_io_regs[0x103] = (dst + len) & 0x3fff; +} + +/*********************** +* Audio Hardware * +***********************/ + +READ16_MEMBER(spg2xx_device::audio_r) +{ + const uint16_t channel = (offset & 0x00f0) >> 4; + uint16_t data = m_audio_regs[offset]; + + if (offset >= 0x400) + { + switch (offset) + { + case AUDIO_CHANNEL_ENABLE: + LOGMASKED(LOG_SPU_READS, "audio_r: Channel Enable: %04x\n", data); + break; + + case AUDIO_MAIN_VOLUME: + LOGMASKED(LOG_SPU_READS, "audio_r: Main Volume: %04x\n", data); + break; + + case AUDIO_CHANNEL_FIQ_ENABLE: + LOGMASKED(LOG_SPU_READS | LOG_IRQS, "audio_r: Channel FIQ Enable: %04x\n", data); + break; + + case AUDIO_CHANNEL_FIQ_STATUS: + LOGMASKED(LOG_SPU_READS | LOG_IRQS, "audio_r: Channel FIQ Acknowledge: %04x\n", data); + break; + + case AUDIO_BEAT_BASE_COUNT: + LOGMASKED(LOG_SPU_READS | LOG_BEAT, "audio_r: Beat Base Count: %04x\n", data); + break; + + case AUDIO_BEAT_COUNT: + LOGMASKED(LOG_SPU_READS | LOG_BEAT, "audio_r: Beat Count: %04x\n", data); + break; + + case AUDIO_ENVCLK0: + case AUDIO_ENVCLK1: + LOGMASKED(LOG_SPU_READS | LOG_ENVELOPES, "audio_r: Envelope Interval %d (lo): %04x\n", offset == AUDIO_ENVCLK0 ? 0 : 1, data); + break; + + case AUDIO_ENVCLK0_HIGH: + case AUDIO_ENVCLK1_HIGH: + LOGMASKED(LOG_SPU_READS | LOG_ENVELOPES, "audio_r: Envelope Interval %d (hi): %04x\n", offset == AUDIO_ENVCLK0_HIGH ? 0 : 1, data); + break; + + case AUDIO_ENV_RAMP_DOWN: + LOGMASKED(LOG_SPU_READS | LOG_RAMPDOWN, "audio_r: Envelope Fast Ramp Down: %04x\n", data); + break; + + case AUDIO_CHANNEL_STOP: + LOGMASKED(LOG_SPU_READS, "audio_r: Channel Stop Status: %04x\n", data); + break; + + case AUDIO_CHANNEL_ZERO_CROSS: + LOGMASKED(LOG_SPU_READS, "audio_r: Channel Zero-Cross Enable: %04x\n", data); + break; + + case AUDIO_CONTROL: + LOGMASKED(LOG_SPU_READS, "audio_r: Control: %04x\n", data); + break; + + case AUDIO_COMPRESS_CTRL: + LOGMASKED(LOG_SPU_READS, "audio_r: Compressor Control: %04x\n", data); + break; + + case AUDIO_CHANNEL_STATUS: + LOGMASKED(LOG_SPU_READS, "audio_r: Channel Status: %04x\n", data); + break; + + case AUDIO_WAVE_IN_L: + LOGMASKED(LOG_SPU_READS, "audio_r: Wave In (L) / FIFO Write Data: %04x\n", data); + break; + + case AUDIO_WAVE_IN_R: + LOGMASKED(LOG_SPU_READS, "audio_r: Wave In (R) / Software Channel FIFO IRQ Control: %04x\n", data); + break; + + case AUDIO_WAVE_OUT_L: + LOGMASKED(LOG_SPU_READS, "audio_r: Wave Out (L): %04x\n", data); + break; + + case AUDIO_WAVE_OUT_R: + LOGMASKED(LOG_SPU_READS, "audio_r: Wave Out (R): %04x\n", data); + break; + + case AUDIO_CHANNEL_REPEAT: + LOGMASKED(LOG_SPU_READS, "audio_r: Channel Repeat Enable: %04x\n", data); + break; + + case AUDIO_CHANNEL_ENV_MODE: + LOGMASKED(LOG_SPU_READS | LOG_ENVELOPES, "audio_r: Channel Envelope Enable: %04x\n", data); + break; + + case AUDIO_CHANNEL_TONE_RELEASE: + LOGMASKED(LOG_SPU_READS, "audio_r: Channel Tone Release Enable: %04x\n", data); + break; + + case AUDIO_CHANNEL_ENV_IRQ: + LOGMASKED(LOG_SPU_READS | LOG_IRQS, "audio_r: Channel Envelope IRQ Status: %04x\n", data); + break; + + case AUDIO_CHANNEL_PITCH_BEND: + LOGMASKED(LOG_SPU_READS, "audio_r: Channel Pitch Bend Enable: %04x\n", data); + break; + + case AUDIO_SOFT_PHASE: + LOGMASKED(LOG_SPU_READS, "audio_r: Software Channel Phase: %04x\n", data); + break; + + case AUDIO_ATTACK_RELEASE: + LOGMASKED(LOG_SPU_READS, "audio_r: Attack/Release Time Control: %04x\n", data); + break; + + case AUDIO_EQ_CUTOFF10: + LOGMASKED(LOG_SPU_READS, "audio_r: EQ Cutoff Frequency 0/1: %04x\n", data); + break; + + case AUDIO_EQ_CUTOFF32: + LOGMASKED(LOG_SPU_READS, "audio_r: EQ Cutoff Frequency 2/3: %04x\n", data); + break; + + case AUDIO_EQ_GAIN10: + LOGMASKED(LOG_SPU_READS, "audio_r: EQ Cutoff Gain 0/1: %04x\n", data); + break; + + case AUDIO_EQ_GAIN32: + LOGMASKED(LOG_SPU_READS, "audio_r: EQ Cutoff Gain 2/3: %04x\n", data); + break; + + default: + LOGMASKED(LOG_UNKNOWN_SPU, "audio_r: Unknown register %04x = %04x\n", 0x3000 + offset, data); + break; + } + } + else if (channel < 16) + { + switch (offset & AUDIO_CHAN_OFFSET_MASK) + { + case AUDIO_WAVE_ADDR: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Wave Addr (lo): %04x\n", channel, data); + break; + + case AUDIO_MODE: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Mode: %04x (ADPCM:%d, 16M:%d, TONE:%d, LADDR_HI:%04x, WADDR_HI:%04x)\n", channel, data, + get_adpcm_bit(channel), get_16bit_bit(channel), get_tone_mode(channel), get_loop_addr_high(channel), get_wave_addr_high(channel)); + break; + + case AUDIO_LOOP_ADDR: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Loop Addr: %04x\n", channel, data); + break; + + case AUDIO_PAN_VOL: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Pan/Vol: %04x (PAN:%02x, VOL:%02x)\n", channel, data, + get_pan(channel), get_volume(channel)); + break; + + case AUDIO_ENVELOPE0: + LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope0: %04x (RPTPER:%d, TARGET:%02x, SIGN:%d, INC:%02x)\n", channel, data, + get_repeat_period_bit(channel), get_envelope_target(channel), get_envelope_sign_bit(channel), get_envelope_inc(channel)); + break; + + case AUDIO_ENVELOPE_DATA: + LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope Data: %04x (CNT:%d, EDD:%02x)\n", channel, data, + get_envelope_count(channel), get_edd(channel)); + break; + + case AUDIO_ENVELOPE1: + LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope1 Data: %04x (RPTCNT:%02x, RPT:%d, LOAD:%02x)\n", channel, data, + get_envelope_repeat_count(channel), get_envelope_repeat_bit(channel), get_envelope_load(channel)); + break; + + case AUDIO_ENVELOPE_ADDR_HIGH: + LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope Addr (hi): %04x (IRQADDR:%03x, IRQEN:%d, EADDR_HI:%02x)\n", channel, data, + get_audio_irq_addr(channel), get_audio_irq_enable_bit(channel), get_envelope_addr_high(channel)); + break; + + case AUDIO_ENVELOPE_ADDR: + LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope Addr (lo): %04x \n", channel, data); + break; + + case AUDIO_WAVE_DATA_PREV: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Wave Data Prev: %04x \n", channel, data); + break; + + case AUDIO_ENVELOPE_LOOP_CTRL: + LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope Loop Ctrl: %04x (RDOFFS:%02x, EAOFFS:%03x)\n", channel, data, + get_rampdown_offset(channel), get_envelope_eaoffset(channel)); + break; + + case AUDIO_WAVE_DATA: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Wave Data: %04x\n", channel, data); + break; + + case AUDIO_ADPCM_SEL: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: ADPCM Sel: %04x (ADPCM36:%d, POINTNUM:%02x\n", channel, data, + get_adpcm36_bit(channel), get_point_number(channel)); + break; + + case AUDIO_PHASE_HIGH: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Phase High: %04x\n", channel, data); + break; + + case AUDIO_PHASE_ACCUM_HIGH: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Phase Accum High: %04x\n", channel, data); + break; + + case AUDIO_TARGET_PHASE_HIGH: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Target Phase High: %04x\n", channel, data); + break; + + case AUDIO_RAMP_DOWN_CLOCK: + LOGMASKED(LOG_CHANNEL_READS | LOG_RAMPDOWN, "audio_r: Channel %d: Rampdown Clock: %04x\n", channel, data); + break; + + case AUDIO_PHASE: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Phase: %04x\n", channel, data); + break; + + case AUDIO_PHASE_ACCUM: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Phase Accum: %04x\n", channel, data); + break; + + case AUDIO_TARGET_PHASE: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Target Phase: %04x\n", channel, data); + break; + + case AUDIO_PHASE_CTRL: + LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Phase Ctrl: %04x (TIMESTEP:%d, SIGN:%d, OFFSET:%03x\n", channel, data, + get_phase_time_step(channel), get_phase_sign_bit(channel), get_phase_offset(channel)); + break; + + default: + LOGMASKED(LOG_UNKNOWN_SPU, "audio_r: Unknown register %04x\n", 0x3000 + offset); + break; + } + } + else if (channel >= 16) + { + LOGMASKED(LOG_UNKNOWN_SPU, "audio_r: Trying to read from channel %d\n", channel); + } + return data; } -void spg2xx_device::configure_spg_io(spg2xx_io_device* io) +WRITE16_MEMBER(spg2xx_device::audio_w) { - io->porta_in().set(FUNC(spg2xx_device::porta_r)); - io->portb_in().set(FUNC(spg2xx_device::portb_r)); - io->portc_in().set(FUNC(spg2xx_device::portc_r)); - io->porta_out().set(FUNC(spg2xx_device::porta_w)); - io->portb_out().set(FUNC(spg2xx_device::portb_w)); - io->portc_out().set(FUNC(spg2xx_device::portc_w)); - io->adc_in<0>().set(FUNC(spg2xx_device::adc_r<0>)); - io->adc_in<1>().set(FUNC(spg2xx_device::adc_r<1>)); - io->eeprom_w().set(FUNC(spg2xx_device::eepromx_w)); - io->eeprom_r().set(FUNC(spg2xx_device::eepromx_r)); - io->uart_tx().set(FUNC(spg2xx_device::tx_w)); - io->chip_select().set(FUNC(spg2xx_device::cs_w)); - io->pal_read_callback().set(FUNC(spg2xx_device::get_pal_r)); - io->write_timer_irq_callback().set(FUNC(spg2xx_device::timerirq_w)); - io->write_uart_adc_irq_callback().set(FUNC(spg2xx_device::uartirq_w)); - io->write_external_irq_callback().set(FUNC(spg2xx_device::extirq_w)); - io->write_ffrq_tmr1_irq_callback().set(FUNC(spg2xx_device::ffreq1_w)); - io->write_ffrq_tmr2_irq_callback().set(FUNC(spg2xx_device::ffreq2_w)); + const uint16_t channel = (offset & 0x00f0) >> 4; + + if (offset >= 0x400) + { + switch (offset) + { + case AUDIO_CHANNEL_ENABLE: + { + LOGMASKED(LOG_SPU_WRITES, "audio_w: Channel Enable: %04x\n", data); + const uint16_t changed = m_audio_regs[AUDIO_CHANNEL_ENABLE] ^ data; + for (uint32_t channel_bit = 0; channel_bit < 16; channel_bit++) + { + const uint16_t mask = 1 << channel_bit; + if (!(changed & mask)) + continue; + + if (data & mask) + { + if (!(m_audio_regs[AUDIO_CHANNEL_STATUS] & mask)) + { + LOGMASKED(LOG_SPU_WRITES, "Enabling channel %d\n", channel_bit); + m_audio_regs[offset] |= mask; + if (!(m_audio_regs[AUDIO_CHANNEL_STOP] & mask)) + { + LOGMASKED(LOG_SPU_WRITES, "Stop not set, starting playback on channel %d, mask %04x\n", channel_bit, mask); + m_audio_regs[AUDIO_CHANNEL_STATUS] |= mask; + m_sample_addr[channel_bit] = get_wave_addr(channel_bit); + m_envelope_addr[channel_bit] = get_envelope_addr(channel_bit); + set_envelope_count(channel, get_envelope_load(channel)); + } + m_adpcm[channel_bit].reset(); + m_sample_shift[channel_bit] = 0; + m_sample_count[channel_bit] = 0; + } + } + else + { + m_audio_regs[offset] &= ~mask; + m_audio_regs[AUDIO_CHANNEL_STATUS] &= ~mask; + m_audio_regs[AUDIO_CHANNEL_STOP] |= mask; + m_audio_regs[AUDIO_CHANNEL_TONE_RELEASE] &= ~mask; + } + } + break; + } + + case AUDIO_MAIN_VOLUME: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Main Volume: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_MAIN_VOLUME_MASK; + break; + + case AUDIO_CHANNEL_FIQ_ENABLE: + LOGMASKED(LOG_SPU_WRITES | LOG_IRQS, "audio_w: Channel FIQ Enable: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_CHANNEL_FIQ_ENABLE_MASK; + break; + + case AUDIO_CHANNEL_FIQ_STATUS: + LOGMASKED(LOG_SPU_WRITES | LOG_IRQS, "audio_w: Channel FIQ Acknowledge: %04x\n", data); + m_audio_regs[offset] &= ~(data & AUDIO_CHANNEL_FIQ_STATUS_MASK); + break; + + case AUDIO_BEAT_BASE_COUNT: + LOGMASKED(LOG_SPU_WRITES | LOG_BEAT, "audio_w: Beat Base Count: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_BEAT_BASE_COUNT_MASK; + m_audio_curr_beat_base_count = m_audio_regs[offset]; + break; + + case AUDIO_BEAT_COUNT: + { + LOGMASKED(LOG_SPU_WRITES | LOG_BEAT, "audio_w: Beat Count: %04x\n", data); + const uint16_t old = m_audio_regs[offset]; + m_audio_regs[offset] &= ~(data & AUDIO_BIS_MASK); + m_audio_regs[offset] &= AUDIO_BIS_MASK; + m_audio_regs[offset] |= data & ~AUDIO_BIS_MASK; + const uint16_t changed = old ^ m_audio_regs[offset]; + if (data == 0xc000 && m_audio_regs[offset]) + { + } + if (changed & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) + { + LOGMASKED(LOG_BEAT, "BIS mask changed, updating IRQ\n"); + check_irqs(changed & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)); + } + break; + } + + case AUDIO_ENVCLK0: + case AUDIO_ENVCLK1: + { + LOGMASKED(LOG_SPU_WRITES | LOG_ENVELOPES, "audio_w: Envelope Interval %d (lo): %04x\n", offset == AUDIO_ENVCLK0 ? 0 : 1, data); + const uint16_t old = m_audio_regs[offset]; + m_audio_regs[offset] = data; + const uint16_t changed = old ^ m_audio_regs[offset]; + + if (!changed) + break; + + const uint8_t channel_offset = offset == AUDIO_ENVCLK0 ? 0 : 8; + for (uint8_t channel_bit = 0; channel_bit < 4; channel_bit++) + { + const uint8_t shift = channel_bit << 2; + const uint16_t mask = 0x0f << shift; + if (changed & mask) + { + m_envclk_frame[channel_bit + channel_offset] = get_envclk_frame_count(channel_bit + channel_offset); + } + } + break; + } + + case AUDIO_ENVCLK0_HIGH: + case AUDIO_ENVCLK1_HIGH: + { + LOGMASKED(LOG_SPU_WRITES | LOG_ENVELOPES, "audio_w: Envelope Interval %d (hi): %04x\n", offset == AUDIO_ENVCLK0_HIGH ? 0 : 1, data); + const uint16_t old = m_audio_regs[offset]; + m_audio_regs[offset] = data; + const uint16_t changed = old ^ m_audio_regs[offset]; + if (!changed) + break; + + const uint8_t channel_offset = offset == AUDIO_ENVCLK0_HIGH ? 0 : 8; + for (uint8_t channel_bit = 0; channel_bit < 4; channel_bit++) + { + const uint8_t shift = channel_bit << 2; + const uint16_t mask = 0x0f << shift; + if (changed & mask) + { + m_envclk_frame[channel_bit + channel_offset + 4] = get_envclk_frame_count(channel_bit + channel_offset); + } + } + break; + } + + case AUDIO_ENV_RAMP_DOWN: + { + LOGMASKED(LOG_SPU_WRITES | LOG_RAMPDOWN, "audio_w: Envelope Fast Ramp Down: %04x\n", data); + const uint16_t old = m_audio_regs[offset]; + m_audio_regs[offset] = data & AUDIO_ENV_RAMP_DOWN_MASK; + const uint16_t changed = old ^ m_audio_regs[offset]; + if (!changed) + break; + + for (uint32_t channel_bit = 0; channel_bit < 16; channel_bit++) + { + const uint16_t mask = 1 << channel_bit; + if ((changed & mask) && (data & mask)) + { + m_rampdown_frame[channel_bit] = get_rampdown_frame_count(channel_bit); + LOGMASKED(LOG_RAMPDOWN, "Preparing to ramp down channel %d in %d ticks\n", channel_bit, m_rampdown_frame[channel_bit] / 13); + } + } + break; + } + + case AUDIO_CHANNEL_STOP: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Channel Stop Status: %04x\n", data); + m_audio_regs[offset] &= ~data; + m_audio_regs[AUDIO_CHANNEL_ENABLE] &= ~data; + break; + + case AUDIO_CHANNEL_ZERO_CROSS: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Channel Zero-Cross Enable: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_CHANNEL_ZERO_CROSS_MASK; + break; + + case AUDIO_CONTROL: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Control: %04x (SOFTCH:%d, COMPEN:%d, NOHIGH:%d, NOINT:%d, EQEN:%d\n", data + , (data & AUDIO_CONTROL_SOFTCH_MASK) ? 1 : 0 + , (data & AUDIO_CONTROL_COMPEN_MASK) ? 1 : 0 + , (data & AUDIO_CONTROL_NOHIGH_MASK) ? 1 : 0 + , (data & AUDIO_CONTROL_NOINT_MASK) ? 1 : 0 + , (data & AUDIO_CONTROL_EQEN_MASK) ? 1 : 0); + m_audio_regs[offset] = data & AUDIO_CONTROL_MASK; + break; + + case AUDIO_COMPRESS_CTRL: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Compressor Control: %04x\n", data); + m_audio_regs[offset] = data; + break; + + case AUDIO_CHANNEL_STATUS: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Channel Status (read-only): %04x\n", data); + break; + + case AUDIO_WAVE_IN_L: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Wave In (L) / FIFO Write Data: %04x\n", data); + m_audio_regs[offset] = data; + break; + + case AUDIO_WAVE_IN_R: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Wave In (R) / Software Channel FIFO IRQ Control: %04x\n", data); + m_audio_regs[offset] = data; + break; + + case AUDIO_WAVE_OUT_L: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Wave Out (L): %04x\n", data); + m_audio_regs[offset] = data; + break; + + case AUDIO_WAVE_OUT_R: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Wave Out (R): %04x\n", data); + m_audio_regs[offset] = data; + break; + + case AUDIO_CHANNEL_REPEAT: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Channel Repeat Enable: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_CHANNEL_REPEAT_MASK; + break; + + case AUDIO_CHANNEL_ENV_MODE: + LOGMASKED(LOG_SPU_WRITES | LOG_ENVELOPES, "audio_w: Channel Envelope Enable: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_CHANNEL_ENV_MODE_MASK; + break; + + case AUDIO_CHANNEL_TONE_RELEASE: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Channel Tone Release Enable: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_CHANNEL_TONE_RELEASE_MASK; + break; + + case AUDIO_CHANNEL_ENV_IRQ: + LOGMASKED(LOG_SPU_WRITES | LOG_ENVELOPES | LOG_IRQS, "audio_w: Channel Envelope IRQ Acknowledge: %04x\n", data); + m_audio_regs[offset] &= ~data & AUDIO_CHANNEL_ENV_IRQ_MASK; + break; + + case AUDIO_CHANNEL_PITCH_BEND: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Channel Pitch Bend Enable: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_CHANNEL_PITCH_BEND_MASK; + break; + + case AUDIO_SOFT_PHASE: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Software Channel Phase: %04x\n", data); + m_audio_regs[offset] = data; + break; + + case AUDIO_ATTACK_RELEASE: + LOGMASKED(LOG_SPU_WRITES, "audio_w: Attack/Release Time Control: %04x\n", data); + m_audio_regs[offset] = data; + break; + + case AUDIO_EQ_CUTOFF10: + LOGMASKED(LOG_SPU_WRITES, "audio_w: EQ Cutoff Frequency 0/1: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_EQ_CUTOFF10_MASK; + break; + + case AUDIO_EQ_CUTOFF32: + LOGMASKED(LOG_SPU_WRITES, "audio_w: EQ Cutoff Frequency 2/3: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_EQ_CUTOFF32_MASK; + break; + + case AUDIO_EQ_GAIN10: + LOGMASKED(LOG_SPU_WRITES, "audio_w: EQ Cutoff Gain 0/1: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_EQ_GAIN10_MASK; + break; + + case AUDIO_EQ_GAIN32: + LOGMASKED(LOG_SPU_WRITES, "audio_w: EQ Cutoff Gain 2/3: %04x\n", data); + m_audio_regs[offset] = data & AUDIO_EQ_GAIN32_MASK; + break; + + default: + m_audio_regs[offset] = data; + LOGMASKED(LOG_UNKNOWN_SPU, "audio_w: Unknown register %04x = %04x\n", 0x3000 + offset, data); + break; + } + } + else if (channel < 16) + { + switch (offset & AUDIO_CHAN_OFFSET_MASK) + { + case AUDIO_WAVE_ADDR: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Wave Addr (lo): %04x\n", channel, data); + break; + + case AUDIO_MODE: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Mode: %04x (ADPCM:%d, 16M:%d, TONE:%d, LADDR_HI:%04x, WADDR_HI:%04x)\n", channel, data, + get_adpcm_bit(channel), get_16bit_bit(channel), get_tone_mode(channel), get_loop_addr_high(channel), get_wave_addr_high(channel)); + break; + + case AUDIO_LOOP_ADDR: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Loop Addr: %04x\n", channel, data); + break; + + case AUDIO_PAN_VOL: + m_audio_regs[offset] = data & AUDIO_PAN_VOL_MASK; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Pan/Vol: %04x (PAN:%02x, VOL:%02x)\n", channel, data, + get_pan(channel), get_volume(channel)); + break; + + case AUDIO_ENVELOPE0: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope0: %04x (RPTPER:%d, TARGET:%02x, SIGN:%d, INC:%02x)\n", channel, data, + get_repeat_period_bit(channel), get_envelope_target(channel), get_envelope_sign_bit(channel), get_envelope_inc(channel)); + break; + + case AUDIO_ENVELOPE_DATA: + m_audio_regs[offset] = data & AUDIO_ENVELOPE_DATA_MASK; + LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope Data: %04x (CNT:%d, EDD:%02x)\n", channel, data, + get_envelope_count(channel), get_edd(channel)); + break; + + case AUDIO_ENVELOPE1: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope1 Data: %04x (RPTCNT:%02x, RPT:%d, LOAD:%02x)\n", channel, data, + get_envelope_repeat_count(channel), get_envelope_repeat_bit(channel), get_envelope_load(channel)); + break; + + case AUDIO_ENVELOPE_ADDR_HIGH: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope Addr (hi): %04x (IRQADDR:%03x, IRQEN:%d, EADDR_HI:%02x)\n", channel, data, + get_audio_irq_addr(channel), get_audio_irq_enable_bit(channel), get_envelope_addr_high(channel)); + break; + + case AUDIO_ENVELOPE_ADDR: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope Addr (lo): %04x\n", channel, data); + break; + + case AUDIO_WAVE_DATA_PREV: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Wave Data Prev: %04x \n", channel, data); + break; + + case AUDIO_ENVELOPE_LOOP_CTRL: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope Loop Ctrl: %04x (RDOFFS:%02x, EAOFFS:%03x)\n", channel, data, + get_rampdown_offset(channel), get_envelope_eaoffset(channel)); + break; + + case AUDIO_WAVE_DATA: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Wave Data: %04x\n", channel, data); + break; + + case AUDIO_ADPCM_SEL: + m_audio_regs[offset] = data & AUDIO_ADPCM_SEL_MASK; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: ADPCM Sel: %04x (ADPCM36:%d, POINTNUM:%02x\n", channel, data, + get_adpcm36_bit(channel), get_point_number(channel)); + break; + + case AUDIO_PHASE_HIGH: + m_audio_regs[offset] = data & AUDIO_PHASE_HIGH_MASK; + m_channel_rate[channel] = ((double)get_phase(channel) * 140625.0 * 2.0) / (double)(1 << 19); + m_channel_rate_accum[channel] = 0.0; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Phase High: %04x (rate: %f)\n", channel, data, m_channel_rate[channel]); + break; + + case AUDIO_PHASE_ACCUM_HIGH: + m_audio_regs[offset] = data & AUDIO_PHASE_ACCUM_HIGH_MASK; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Phase Accum High: %04x\n", channel, data); + break; + + case AUDIO_TARGET_PHASE_HIGH: + m_audio_regs[offset] = data & AUDIO_TARGET_PHASE_HIGH_MASK; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Target Phase High: %04x\n", channel, data); + break; + + case AUDIO_RAMP_DOWN_CLOCK: + m_audio_regs[offset] = data & AUDIO_RAMP_DOWN_CLOCK_MASK; + LOGMASKED(LOG_CHANNEL_WRITES | LOG_RAMPDOWN, "audio_w: Channel %d: Rampdown Clock: %04x\n", channel, data); + break; + + case AUDIO_PHASE: + m_audio_regs[offset] = data; + m_channel_rate[channel] = ((double)get_phase(channel) * 140625.0 * 2.0) / (double)(1 << 19); + m_channel_rate_accum[channel] = 0.0; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Phase: %04x (rate: %f)\n", channel, data, m_channel_rate[channel]); + break; + + case AUDIO_PHASE_ACCUM: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Phase Accum: %04x\n", channel, data); + break; + + case AUDIO_TARGET_PHASE: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Target Phase: %04x\n", channel, data); + break; + + case AUDIO_PHASE_CTRL: + m_audio_regs[offset] = data; + LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Phase Ctrl: %04x (TIMESTEP:%d, SIGN:%d, OFFSET:%03x\n", channel, data, + get_phase_time_step(channel), get_phase_sign_bit(channel), get_phase_offset(channel)); + break; + + default: + m_audio_regs[offset] = data; + LOGMASKED(LOG_UNKNOWN_SPU, "audio_w: Unknown register %04x = %04x\n", 0x3000 + offset, data); + break; + } + } + else if (channel >= 16) + { + LOGMASKED(LOG_UNKNOWN_SPU, "audio_w: Trying to write to channel %d: %04x = %04x\n", channel, 0x3000 + offset, data); + } + else + { + m_audio_regs[offset] = data; + } +} + +void spg2xx_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +{ + stream_sample_t *out_l = outputs[0]; + stream_sample_t *out_r = outputs[1]; + address_space &space = m_cpu->space(AS_PROGRAM); + + for (int i = 0; i < samples; i++) + { + int32_t left_total = 0; + int32_t right_total = 0; + int32_t active_count = 0; + + for (uint32_t ch_index = 0; ch_index < 16; ch_index++) + { + if (!get_channel_status(ch_index)) + { + continue; + } + + if (SPG_DEBUG_AUDIO && m_debug_rates) + printf("%f:%f ", m_channel_rate[ch_index], m_channel_rate_accum[ch_index]); + bool playing = advance_channel(space, ch_index); + if (playing) + { + int32_t sample = (int16_t)(m_audio_regs[(ch_index << 4) | AUDIO_WAVE_DATA] ^ 0x8000); + if (!(m_audio_regs[AUDIO_CONTROL] & AUDIO_CONTROL_NOINT_MASK)) + { + int32_t prev_sample = (int16_t)(m_audio_regs[(ch_index << 4) | AUDIO_WAVE_DATA_PREV] ^ 0x8000); + int16_t lerp_factor = (int16_t)((m_channel_rate_accum[ch_index] / 44100.0) * 256.0); + prev_sample = (prev_sample * (0x100 - lerp_factor)) >> 8; + sample = (sample * lerp_factor) >> 8; + sample += prev_sample; + } + + sample = (sample * (int16_t)get_edd(ch_index)) >> 7; + + active_count++; + + int32_t vol = get_volume(ch_index); + int32_t pan = get_pan(ch_index); + + int32_t pan_left, pan_right; + if (pan < 0x40) + { + pan_left = 0x7f * vol; + pan_right = pan * 2 * vol; + } + else + { + pan_left = (0x7f - pan) * 2 * vol; + pan_right = 0x7f * vol; + } + + left_total += ((int16_t)sample * (int16_t)pan_left) >> 14; + right_total += ((int16_t)sample * (int16_t)pan_right) >> 14; + } + } + + if (active_count) + { + left_total /= active_count; + right_total /= active_count; + *out_l++ = (left_total * (int16_t)m_audio_regs[AUDIO_MAIN_VOLUME]) >> 7; + *out_r++ = (right_total * (int16_t)m_audio_regs[AUDIO_MAIN_VOLUME]) >> 7; + } + else + { + *out_l++ = 0; + *out_r++ = 0; + } + } +} + +inline void spg2xx_device::stop_channel(const uint32_t channel) +{ + // TODO: IRQs + m_audio_regs[AUDIO_CHANNEL_ENABLE] &= ~(1 << channel); + m_audio_regs[AUDIO_CHANNEL_STATUS] &= ~(1 << channel); + m_audio_regs[AUDIO_CHANNEL_STOP] |= (1 << channel); + m_audio_regs[(channel << 4) | AUDIO_MODE] &= ~AUDIO_ADPCM_MASK; + m_audio_regs[AUDIO_CHANNEL_TONE_RELEASE] &= ~(1 << channel); +} + +bool spg2xx_device::advance_channel(address_space &space, const uint32_t channel) +{ + m_channel_rate_accum[channel] += m_channel_rate[channel]; + uint32_t samples_to_advance = 0; + while (m_channel_rate_accum[channel] >= 44100.0) + { + m_channel_rate_accum[channel] -= 44100.0; + samples_to_advance++; + } + + if (!samples_to_advance) + return true; + + bool playing = true; + + if (get_adpcm_bit(channel)) + { + // ADPCM mode + for (uint32_t sample = 0; sample < samples_to_advance && playing; sample++) + { + playing = fetch_sample(space, channel); + if (playing) + { + m_sample_shift[channel] += 4; + if (m_sample_shift[channel] == 16) + { + m_sample_shift[channel] = 0; + m_sample_addr[channel]++; + } + } + } + } + else if (get_16bit_bit(channel)) + { + // 16-bit mode + for (uint32_t sample = 0; sample < samples_to_advance && playing; sample++) + { + playing = fetch_sample(space, channel); + if (playing) + m_sample_addr[channel]++; + } + } + else + { + // 8-bit mode + for (uint32_t sample = 0; sample < samples_to_advance && playing; sample++) + { + playing = fetch_sample(space, channel); + if (playing) + { + m_sample_shift[channel] += 8; + if (m_sample_shift[channel] == 16) + { + m_sample_shift[channel] = 0; + m_sample_addr[channel]++; + } + } + } + } + + return playing; +} + +bool spg2xx_device::fetch_sample(address_space &space, const uint32_t channel) +{ + const uint32_t channel_mask = channel << 4; + m_audio_regs[channel_mask | AUDIO_WAVE_DATA_PREV] = m_audio_regs[channel_mask | AUDIO_WAVE_DATA]; + + const uint32_t wave_data_reg = channel_mask | AUDIO_WAVE_DATA; + const uint16_t tone_mode = get_tone_mode(channel); + const uint16_t raw_sample = tone_mode ? space.read_word(m_sample_addr[channel]) : m_audio_regs[wave_data_reg]; + + m_audio_regs[wave_data_reg] = raw_sample; + + if (get_adpcm_bit(channel)) + { + // ADPCM mode + m_audio_regs[wave_data_reg] >>= m_sample_shift[channel]; + m_audio_regs[wave_data_reg] = (uint16_t)(m_adpcm[channel].clock((uint8_t)(m_audio_regs[wave_data_reg] & 0x000f)) * 7) ^ 0x8000; + if (tone_mode != 0 && raw_sample == 0xffff) + { + if (tone_mode == AUDIO_TONE_MODE_HW_ONESHOT) + { + LOGMASKED(LOG_SAMPLES, "ADPCM stopped after %d samples\n", m_sample_count[channel]); + m_sample_count[channel] = 0; + stop_channel(channel); + return false; + } + else + { + LOGMASKED(LOG_SAMPLES, "ADPCM looping after %d samples\n", m_sample_count[channel]); + m_sample_count[channel] = 0; + loop_channel(channel); + } + } + m_sample_count[channel]++; + } + else if (get_16bit_bit(channel)) + { + // 16-bit mode + if (tone_mode != 0 && raw_sample == 0xffff) + { + if (tone_mode == AUDIO_TONE_MODE_HW_ONESHOT) + { + LOGMASKED(LOG_SAMPLES, "16-bit PCM stopped after %d samples\n", m_sample_count[channel]); + m_sample_count[channel] = 0; + stop_channel(channel); + return false; + } + else + { + LOGMASKED(LOG_SAMPLES, "16-bit PCM looping after %d samples\n", m_sample_count[channel]); + m_sample_count[channel] = 0; + loop_channel(channel); + } + } + m_sample_count[channel]++; + } + else + { + // 8-bit mode + if (tone_mode != 0) + { + if (m_sample_shift[channel]) + m_audio_regs[wave_data_reg] <<= 8; + else + m_audio_regs[wave_data_reg] &= 0xff00; + + if (m_audio_regs[wave_data_reg] == 0xff00) + { + if (tone_mode == AUDIO_TONE_MODE_HW_ONESHOT) + { + LOGMASKED(LOG_SAMPLES, "8-bit PCM stopped after %d samples\n", m_sample_count[channel]); + m_sample_count[channel] = 0; + stop_channel(channel); + return false; + } + else + { + LOGMASKED(LOG_SAMPLES, "8-bit PCM looping after %d samples\n", m_sample_count[channel]); + m_sample_count[channel] = 0; + loop_channel(channel); + } + } + } + m_sample_count[channel]++; + } + + return true; } -void spg24x_device::device_add_mconfig(machine_config &config) +inline void spg2xx_device::loop_channel(const uint32_t channel) { - SPG2XX_AUDIO(config, m_spg_audio, DERIVED_CLOCK(1, 1)); - m_spg_audio->write_irq_callback().set(FUNC(spg24x_device::audioirq_w)); - m_spg_audio->space_read_callback().set(FUNC(spg24x_device::space_r)); + m_sample_addr[channel] = get_loop_addr(channel); + m_sample_shift[channel] = 0; +} - m_spg_audio->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0); - m_spg_audio->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1); +void spg2xx_device::audio_frame_tick() +{ + audio_beat_tick(); - SPG24X_IO(config, m_spg_io, DERIVED_CLOCK(1, 1), m_cpu, m_screen); - configure_spg_io(m_spg_io); + address_space &space = m_cpu->space(AS_PROGRAM); + bool any_changed = false; + for (uint32_t channel = 0; channel < 16; channel++) + { + const uint16_t mask = (1 << channel); + if (!(m_audio_regs[AUDIO_CHANNEL_STATUS] & mask)) + { + continue; + } + + if (m_audio_regs[AUDIO_ENV_RAMP_DOWN] & mask) + { + m_rampdown_frame[channel]--; + if (m_rampdown_frame[channel] == 0) + { + LOGMASKED(LOG_RAMPDOWN, "Ticking rampdown for channel %d\n", channel); + audio_rampdown_tick(channel); + any_changed = true; + } + continue; + } + + if (!(m_audio_regs[AUDIO_CHANNEL_ENV_MODE] & mask)) + { + m_envclk_frame[channel]--; + if (m_envclk_frame[channel] == 0) + { + LOGMASKED(LOG_ENVELOPES, "Ticking envelope for channel %d\n", channel); + any_changed = audio_envelope_tick(space, channel) || any_changed; + m_envclk_frame[channel] = get_envclk_frame_count(channel); + } + } + } + + if (any_changed) + { + m_stream->update(); + } } -void spg28x_device::device_add_mconfig(machine_config &config) +void spg2xx_device::audio_beat_tick() { - SPG2XX_AUDIO(config, m_spg_audio, DERIVED_CLOCK(1, 1)); - m_spg_audio->write_irq_callback().set(FUNC(spg28x_device::audioirq_w)); - m_spg_audio->space_read_callback().set(FUNC(spg28x_device::space_r)); + if (m_audio_curr_beat_base_count == 0) + { + LOGMASKED(LOG_BEAT, "Beat base count elapsed, reloading with %d\n", m_audio_regs[AUDIO_BEAT_BASE_COUNT]); + m_audio_curr_beat_base_count = m_audio_regs[AUDIO_BEAT_BASE_COUNT]; + + uint16_t beat_count = m_audio_regs[AUDIO_BEAT_COUNT] & AUDIO_BEAT_COUNT_MASK; + if (beat_count == 0) + { + if (m_audio_regs[AUDIO_BEAT_COUNT] & AUDIO_BIE_MASK) + { + LOGMASKED(LOG_BEAT, "Beat count elapsed, setting Status bit and checking IRQs\n"); + m_audio_regs[AUDIO_BEAT_COUNT] |= AUDIO_BIS_MASK; + check_irqs(AUDIO_BIS_MASK); + } + else + { + LOGMASKED(LOG_BEAT, "Beat count elapsed but IRQ not enabled\n"); + } + } + else + { + beat_count--; + m_audio_regs[AUDIO_BEAT_COUNT] = (m_audio_regs[AUDIO_BEAT_COUNT] & ~AUDIO_BEAT_COUNT_MASK) | beat_count; + } + } + else + { + m_audio_curr_beat_base_count--; + } +} - m_spg_audio->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0); - m_spg_audio->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1); +void spg2xx_device::audio_rampdown_tick(const uint32_t channel) +{ + const uint8_t old_edd = get_edd(channel); + uint8_t new_edd = old_edd - get_rampdown_offset(channel); + if (new_edd > old_edd) + new_edd = 0; - SPG28X_IO(config, m_spg_io, DERIVED_CLOCK(1, 1), m_cpu, m_screen); - configure_spg_io(m_spg_io); + if (new_edd) + { + LOGMASKED(LOG_RAMPDOWN, "Channel %d preparing for next rampdown step (%02x)\n", channel, new_edd); + const uint16_t channel_mask = channel << 4; + m_audio_regs[channel_mask | AUDIO_ENVELOPE_DATA] &= ~AUDIO_EDD_MASK; + m_audio_regs[channel_mask | AUDIO_ENVELOPE_DATA] |= new_edd & AUDIO_EDD_MASK; + m_rampdown_frame[channel] = get_rampdown_frame_count(channel); + } + else + { + LOGMASKED(LOG_RAMPDOWN, "Stopping channel %d due to rampdown\n", channel); + const uint16_t channel_mask = 1 << channel; + m_audio_regs[AUDIO_CHANNEL_ENABLE] &= ~channel_mask; + m_audio_regs[AUDIO_CHANNEL_STATUS] &= ~channel_mask; + m_audio_regs[AUDIO_CHANNEL_STOP] |= channel_mask; + m_audio_regs[AUDIO_ENV_RAMP_DOWN] &= ~channel_mask; + m_audio_regs[AUDIO_CHANNEL_TONE_RELEASE] &= ~channel_mask; + } +} + +const uint32_t spg2xx_device::s_rampdown_frame_counts[8] = +{ + 13*4, 13*16, 13*64, 13*256, 13*1024, 13*4096, 13*8192, 13*8192 +}; + +uint32_t spg2xx_device::get_rampdown_frame_count(const uint32_t channel) +{ + return s_rampdown_frame_counts[get_rampdown_clock(channel)]; +} + +const uint32_t spg2xx_device::s_envclk_frame_counts[16] = +{ + 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 8192, 8192, 8192, 8192 +}; + +uint32_t spg2xx_device::get_envclk_frame_count(const uint32_t channel) +{ + return s_envclk_frame_counts[get_envelope_clock(channel)]; +} + +uint32_t spg2xx_device::get_envelope_clock(const offs_t channel) const +{ + if (channel < 4) + return (m_audio_regs[AUDIO_ENVCLK0] >> (channel << 2)) & 0x000f; + else if (channel < 8) + return (m_audio_regs[AUDIO_ENVCLK0_HIGH] >> ((channel - 4) << 2)) & 0x000f; + else if (channel < 12) + return (m_audio_regs[AUDIO_ENVCLK1] >> ((channel - 8) << 2)) & 0x000f; + else + return (m_audio_regs[AUDIO_ENVCLK1_HIGH] >> ((channel - 12) << 2)) & 0x000f; +} + +bool spg2xx_device::audio_envelope_tick(address_space &space, const uint32_t channel) +{ + const uint16_t channel_mask = channel << 4; + uint16_t new_count = get_envelope_count(channel); + const uint16_t curr_edd = get_edd(channel); + LOGMASKED(LOG_ENVELOPES, "envelope %d tick, count is %04x, curr edd is %04x\n", channel, new_count, curr_edd); + bool edd_changed = false; + if (new_count == 0) + { + const uint16_t target = get_envelope_target(channel); + uint16_t new_edd = curr_edd; + const uint16_t inc = get_envelope_inc(channel); + + if (new_edd != target) + { + if (get_envelope_sign_bit(channel)) + { + new_edd -= inc; + LOGMASKED(LOG_ENVELOPES, "Envelope %d new EDD-: %04x (%04x), dec %04x\n", channel, new_edd, target, inc); + if (new_edd > curr_edd) + new_edd = 0; + else if (new_edd < target) + new_edd = target; + + if (new_edd == 0) + { + LOGMASKED(LOG_ENVELOPES, "Envelope %d at 0, stopping channel\n", channel); + stop_channel(channel); + return true; + } + } + else + { + new_edd += inc; + LOGMASKED(LOG_ENVELOPES, "Envelope %d new EDD+: %04x\n", channel, new_edd); + if (new_edd >= target) + new_edd = target; + } + } + + if (new_edd == target) + { + LOGMASKED(LOG_ENVELOPES, "Envelope %d at target %04x\n", channel, target); + new_edd = target; + + if (get_envelope_repeat_bit(channel)) + { + const uint16_t repeat_count = get_envelope_repeat_count(channel) - 1; + LOGMASKED(LOG_ENVELOPES, "Repeating envelope, new repeat count %d\n", repeat_count); + if (repeat_count == 0) + { + m_audio_regs[channel_mask | AUDIO_ENVELOPE0] = space.read_word(m_envelope_addr[channel]); + m_audio_regs[channel_mask | AUDIO_ENVELOPE1] = space.read_word(m_envelope_addr[channel] + 1); + m_audio_regs[channel_mask | AUDIO_ENVELOPE_LOOP_CTRL] = space.read_word(m_envelope_addr[channel] + 2); + m_envelope_addr[channel] = get_envelope_addr(channel) + get_envelope_eaoffset(channel); + LOGMASKED(LOG_ENVELOPES, "Envelope data after repeat: %04x %04x %04x (%08x)\n", m_audio_regs[channel_mask | AUDIO_ENVELOPE0], m_audio_regs[channel_mask | AUDIO_ENVELOPE1], m_audio_regs[channel_mask | AUDIO_ENVELOPE_LOOP_CTRL], m_envelope_addr[channel]); + } + else + { + set_envelope_repeat_count(channel, repeat_count); + } + } + else + { + LOGMASKED(LOG_ENVELOPES, "Fetching envelope for channel %d from %08x\n", channel, m_envelope_addr[channel]); + m_audio_regs[channel_mask | AUDIO_ENVELOPE0] = space.read_word(m_envelope_addr[channel]); + m_audio_regs[channel_mask | AUDIO_ENVELOPE1] = space.read_word(m_envelope_addr[channel] + 1); + LOGMASKED(LOG_ENVELOPES, "Fetched envelopes %04x %04x\n", m_audio_regs[channel_mask | AUDIO_ENVELOPE0], m_audio_regs[channel_mask | AUDIO_ENVELOPE1]); + m_envelope_addr[channel] += 2; + } + new_count = get_envelope_load(channel); + set_envelope_count(channel, new_count); + } + else + { + LOGMASKED(LOG_ENVELOPES, "Envelope %d not yet at target %04x (%04x)\n", channel, target, new_edd); + new_count = get_envelope_load(channel); + set_envelope_count(channel, new_count); + } + LOGMASKED(LOG_ENVELOPES, "Envelope %d new count %04x\n", channel, new_count); + + set_edd(channel, new_edd); + edd_changed = true; + LOGMASKED(LOG_ENVELOPES, "Setting channel %d edd to %04x, register is %04x\n", channel, new_edd, m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA]); + } + else + { + new_count--; + set_envelope_count(channel, new_count); + } + LOGMASKED(LOG_ENVELOPES, "envelope %d post-tick, count is now %04x, register is %04x\n", channel, new_count, m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA]); + return edd_changed; } diff --git a/src/devices/machine/spg2xx.h b/src/devices/machine/spg2xx.h index 859620d9f66..0573daef7ac 100644 --- a/src/devices/machine/spg2xx.h +++ b/src/devices/machine/spg2xx.h @@ -27,6 +27,12 @@ ND - unknown - Wireless Air 60 ND - Likely many more + Also on this hardware: + + name PCB ID ROM width TSOP pads ROM size SEEPROM die markings + Radica Play TV Football 2 L7278 x16 48 not dumped no Sunplus + Dream Life ? x16 48 not dumped no Sunplus + **********************************************************************/ #ifndef MAME_MACHINE_SPG2XX_H @@ -35,17 +41,15 @@ #pragma once #include "cpu/unsp/unsp.h" -#include "spg2xx_audio.h" -#include "spg2xx_io.h" +#include "sound/okiadpcm.h" #include "screen.h" -class spg2xx_device : public device_t, public device_mixer_interface +class spg2xx_device : public device_t, public device_sound_interface { public: spg2xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); void set_pal(bool pal) { m_pal_flag = pal ? 1 : 0; } - void set_rowscroll_offset(int offset) { m_rowscrolloffset = offset; } void map(address_map &map); @@ -56,8 +60,6 @@ public: auto portb_in() { return m_portb_in.bind(); } auto portc_in() { return m_portc_in.bind(); } - template <size_t Line> auto adc_in() { return m_adc_in[Line].bind(); } - auto eeprom_w() { return m_eeprom_w.bind(); } auto eeprom_r() { return m_eeprom_r.bind(); } @@ -65,22 +67,21 @@ public: auto chip_select() { return m_chip_sel.bind(); } + void uart_rx(uint8_t data); + uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); DECLARE_WRITE_LINE_MEMBER(vblank); - required_device<spg2xx_audio_device> m_spg_audio; - required_device<spg2xx_io_device> m_spg_io; - - void extint_w(int channel, bool state) { m_spg_io->extint_w(channel, state); }; - void uart_rx(uint8_t data) { m_spg_io->uart_rx(data); }; - protected: - spg2xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint32_t sprite_limit) + spg2xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const size_t sprite_limit) : spg2xx_device(mconfig, type, tag, owner, clock) { m_sprite_limit = sprite_limit; } + // sound stream update overrides + virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override; + enum { PAGE_ENABLE_MASK = 0x0008, @@ -99,82 +100,370 @@ protected: TILE_Y_FLIP = 0x0008 }; - DECLARE_READ16_MEMBER(video_r); - DECLARE_WRITE16_MEMBER(video_w); + void audio_frame_tick(); + void audio_beat_tick(); + void audio_rampdown_tick(const uint32_t channel); + bool audio_envelope_tick(address_space &space, const uint32_t channel); + inline uint32_t get_rampdown_frame_count(const uint32_t channel); + inline uint32_t get_envclk_frame_count(const uint32_t channel); + + // Audio getters + bool get_channel_enable(const offs_t channel) const { return m_audio_regs[AUDIO_CHANNEL_ENABLE] & (1 << channel); } + bool get_channel_status(const offs_t channel) const { return m_audio_regs[AUDIO_CHANNEL_STATUS] & (1 << channel); } + bool get_manual_envelope_enable(const offs_t channel) const { return m_audio_regs[AUDIO_CHANNEL_ENV_MODE] & (1 << channel); } + bool get_auto_envelope_enable(const offs_t channel) const { return !get_manual_envelope_enable(channel); } + uint32_t get_envelope_clock(const offs_t channel) const; + + // Audio Mode getters + uint16_t get_wave_addr_high(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_WADDR_HIGH_MASK; } + uint16_t get_loop_addr_high(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_LADDR_HIGH_MASK) >> AUDIO_LADDR_HIGH_SHIFT; } + uint16_t get_tone_mode(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_TONE_MODE_MASK) >> AUDIO_TONE_MODE_SHIFT; } + uint16_t get_16bit_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_16M_MASK) ? 1 : 0; } + uint16_t get_adpcm_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_ADPCM_MASK) ? 1 : 0; } + + // Audio Pan getters + uint16_t get_volume(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_PAN_VOL] & AUDIO_VOLUME_MASK; } + uint16_t get_pan(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_PAN_VOL] & AUDIO_PAN_MASK) >> AUDIO_PAN_SHIFT; } + + // Audio Envelope0 Data getters + uint16_t get_envelope_inc(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_ENVELOPE0] & AUDIO_ENVELOPE_INC_MASK; } + uint16_t get_envelope_sign_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE0] & AUDIO_ENVELOPE_SIGN_MASK) ? 1 : 0; } + uint16_t get_envelope_target(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE0] & AUDIO_ENVELOPE_TARGET_MASK) >> AUDIO_ENVELOPE_TARGET_SHIFT; } + uint16_t get_repeat_period_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE0] & AUDIO_ENVELOPE_REPEAT_PERIOD_MASK) ? 1 : 0; } + + // Audio Envelope Data getters + uint16_t get_edd(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA] & AUDIO_EDD_MASK; } + uint16_t get_envelope_count(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA] & AUDIO_ENVELOPE_COUNT_MASK) >> AUDIO_ENVELOPE_COUNT_SHIFT; } + void set_edd(const offs_t channel, uint8_t edd) { m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA] = (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA] & ~AUDIO_EDD_MASK) | edd; } + void set_envelope_count(const offs_t channel, uint16_t count) { m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA] = get_edd(channel) | (count << AUDIO_ENVELOPE_COUNT_SHIFT); } + + // Audio Envelope1 Data getters + uint16_t get_envelope_load(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_ENVELOPE1] & AUDIO_ENVELOPE_LOAD_MASK; } + uint16_t get_envelope_repeat_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE1] & AUDIO_ENVELOPE_RPT_MASK) ? 1 : 0; } + uint16_t get_envelope_repeat_count(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE1] & AUDIO_ENVELOPE_RPCNT_MASK) >> AUDIO_ENVELOPE_RPCNT_SHIFT; } + inline void set_envelope_repeat_count(const offs_t channel, const uint16_t count) { m_audio_regs[(channel << 4) | AUDIO_ENVELOPE1] = (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE1] & ~AUDIO_ENVELOPE_RPCNT_MASK) | ((count << AUDIO_ENVELOPE_RPCNT_SHIFT) & AUDIO_ENVELOPE_RPCNT_MASK); } + + // Audio Envelope Address getters + uint16_t get_envelope_addr_high(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_ADDR_HIGH] & AUDIO_EADDR_HIGH_MASK; } + uint16_t get_audio_irq_enable_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_ADDR_HIGH] & AUDIO_IRQ_EN_MASK) ? 1 : 0; } + uint16_t get_audio_irq_addr(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_ADDR_HIGH] & AUDIO_IRQ_ADDR_MASK) >> AUDIO_IRQ_ADDR_SHIFT; } + + // Audio Envelope Loop getters + uint16_t get_envelope_eaoffset(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_LOOP_CTRL] & AUDIO_EAOFFSET_MASK; } + uint16_t get_rampdown_offset(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_LOOP_CTRL] & AUDIO_RAMPDOWN_OFFSET_MASK) >> AUDIO_RAMPDOWN_OFFSET_SHIFT; } + void set_envelope_eaoffset(const offs_t channel, uint16_t eaoffset) { m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_LOOP_CTRL] = (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_LOOP_CTRL] & ~AUDIO_RAMPDOWN_OFFSET_MASK) | (eaoffset & AUDIO_EAOFFSET_MASK); } + + // Audio ADPCM getters + uint16_t get_point_number(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ADPCM_SEL] & AUDIO_POINT_NUMBER_MASK) >> AUDIO_POINT_NUMBER_SHIFT; } + uint16_t get_adpcm36_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ADPCM_SEL] & AUDIO_ADPCM36_MASK) ? 1 : 0; } + + // Audio high-word getters + uint16_t get_phase_high(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_PHASE_HIGH] & AUDIO_PHASE_HIGH_MASK; } + uint16_t get_phase_accum_high(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_PHASE_ACCUM_HIGH] & AUDIO_PHASE_ACCUM_HIGH_MASK; } + uint16_t get_target_phase_high(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_TARGET_PHASE_HIGH] & AUDIO_TARGET_PHASE_HIGH_MASK; } + uint16_t get_rampdown_clock(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_RAMP_DOWN_CLOCK] & AUDIO_RAMP_DOWN_CLOCK_MASK; } + + // Audio ADPCM getters + uint16_t get_phase_offset(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_PHASE_CTRL] & AUDIO_PHASE_OFFSET_MASK; } + uint16_t get_phase_sign_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_PHASE_CTRL] & AUDIO_PHASE_SIGN_MASK) >> AUDIO_PHASE_SIGN_SHIFT; } + uint16_t get_phase_time_step(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_PHASE_CTRL] & AUDIO_PHASE_TIME_STEP_MASK) >> AUDIO_PHASE_TIME_STEP_SHIFT; } + + // Audio combined getters + uint32_t get_phase(const offs_t channel) const { return ((uint32_t)get_phase_high(channel) << 16) | m_audio_regs[(channel << 4) | AUDIO_PHASE]; } + uint32_t get_phase_accum(const offs_t channel) const { return ((uint32_t)get_phase_accum_high(channel) << 16) | m_audio_regs[(channel << 4) | AUDIO_PHASE_ACCUM]; } + uint32_t get_target_phase(const offs_t channel) const { return ((uint32_t)get_target_phase_high(channel) << 16) | m_audio_regs[(channel << 4) | AUDIO_TARGET_PHASE]; } + uint32_t get_wave_addr(const offs_t channel) const { return ((uint32_t)get_wave_addr_high(channel) << 16) | m_audio_regs[(channel << 4) | AUDIO_WAVE_ADDR]; } + uint32_t get_loop_addr(const offs_t channel) const { return ((uint32_t)get_loop_addr_high(channel) << 16) | m_audio_regs[(channel << 4) | AUDIO_LOOP_ADDR]; } + uint32_t get_envelope_addr(const offs_t channel) const { return ((uint32_t)get_envelope_addr_high(channel) << 16) | m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_ADDR]; } + + enum + { + AUDIO_WAVE_ADDR = 0x000, + + AUDIO_MODE = 0x001, + AUDIO_WADDR_HIGH_MASK = 0x003f, + AUDIO_LADDR_HIGH_MASK = 0x0fc0, + AUDIO_LADDR_HIGH_SHIFT = 6, + AUDIO_TONE_MODE_MASK = 0x3000, + AUDIO_TONE_MODE_SHIFT = 12, + AUDIO_TONE_MODE_SW = 0, + AUDIO_TONE_MODE_HW_ONESHOT = 1, + AUDIO_TONE_MODE_HW_LOOP = 2, + AUDIO_16M_MASK = 0x4000, + AUDIO_ADPCM_MASK = 0x8000, + + AUDIO_LOOP_ADDR = 0x002, + + AUDIO_PAN_VOL = 0x003, + AUDIO_PAN_VOL_MASK = 0x7f7f, + AUDIO_VOLUME_MASK = 0x007f, + AUDIO_PAN_MASK = 0x7f00, + AUDIO_PAN_SHIFT = 8, + + AUDIO_ENVELOPE0 = 0x004, + AUDIO_ENVELOPE_INC_MASK = 0x007f, + AUDIO_ENVELOPE_SIGN_MASK = 0x0080, + AUDIO_ENVELOPE_TARGET_MASK = 0x7f00, + AUDIO_ENVELOPE_TARGET_SHIFT = 8, + AUDIO_ENVELOPE_REPEAT_PERIOD_MASK = 0x8000, + + AUDIO_ENVELOPE_DATA = 0x005, + AUDIO_ENVELOPE_DATA_MASK = 0xff7f, + AUDIO_EDD_MASK = 0x007f, + AUDIO_ENVELOPE_COUNT_MASK = 0xff00, + AUDIO_ENVELOPE_COUNT_SHIFT = 8, + + AUDIO_ENVELOPE1 = 0x006, + AUDIO_ENVELOPE_LOAD_MASK = 0x00ff, + AUDIO_ENVELOPE_RPT_MASK = 0x0100, + AUDIO_ENVELOPE_RPCNT_MASK = 0xfe00, + AUDIO_ENVELOPE_RPCNT_SHIFT = 9, + + AUDIO_ENVELOPE_ADDR_HIGH = 0x007, + AUDIO_EADDR_HIGH_MASK = 0x003f, + AUDIO_IRQ_EN_MASK = 0x0040, + AUDIO_IRQ_ADDR_MASK = 0xff80, + AUDIO_IRQ_ADDR_SHIFT = 7, + + AUDIO_ENVELOPE_ADDR = 0x008, + AUDIO_WAVE_DATA_PREV = 0x009, + + AUDIO_ENVELOPE_LOOP_CTRL = 0x00a, + AUDIO_EAOFFSET_MASK = 0x01ff, + AUDIO_RAMPDOWN_OFFSET_MASK = 0xfe00, + AUDIO_RAMPDOWN_OFFSET_SHIFT = 9, + + AUDIO_WAVE_DATA = 0x00b, + + AUDIO_ADPCM_SEL = 0x00d, + AUDIO_ADPCM_SEL_MASK = 0xfe00, + AUDIO_POINT_NUMBER_MASK = 0x7e00, + AUDIO_POINT_NUMBER_SHIFT = 9, + AUDIO_ADPCM36_MASK = 0x8000, + + AUDIO_PHASE_HIGH = 0x200, + AUDIO_PHASE_HIGH_MASK = 0x0007, + + AUDIO_PHASE_ACCUM_HIGH = 0x201, + AUDIO_PHASE_ACCUM_HIGH_MASK = 0x0007, + + AUDIO_TARGET_PHASE_HIGH = 0x202, + AUDIO_TARGET_PHASE_HIGH_MASK= 0x0007, + + AUDIO_RAMP_DOWN_CLOCK = 0x203, + AUDIO_RAMP_DOWN_CLOCK_MASK = 0x0007, + + AUDIO_PHASE = 0x204, + AUDIO_PHASE_ACCUM = 0x205, + AUDIO_TARGET_PHASE = 0x206, + + AUDIO_PHASE_CTRL = 0x207, + AUDIO_PHASE_OFFSET_MASK = 0x0fff, + AUDIO_PHASE_SIGN_MASK = 0x1000, + AUDIO_PHASE_SIGN_SHIFT = 12, + AUDIO_PHASE_TIME_STEP_MASK = 0xe000, + AUDIO_PHASE_TIME_STEP_SHIFT = 13, + + AUDIO_CHAN_OFFSET_MASK = 0xf0f, + + AUDIO_CHANNEL_ENABLE = 0x400, + AUDIO_CHANNEL_ENABLE_MASK = 0xffff, + + AUDIO_MAIN_VOLUME = 0x401, + AUDIO_MAIN_VOLUME_MASK = 0x007f, + + AUDIO_CHANNEL_FIQ_ENABLE = 0x402, + AUDIO_CHANNEL_FIQ_ENABLE_MASK = 0xffff, + + AUDIO_CHANNEL_FIQ_STATUS = 0x403, + AUDIO_CHANNEL_FIQ_STATUS_MASK = 0xffff, + + AUDIO_BEAT_BASE_COUNT = 0x404, + AUDIO_BEAT_BASE_COUNT_MASK = 0x07ff, + + AUDIO_BEAT_COUNT = 0x405, + AUDIO_BEAT_COUNT_MASK = 0x3fff, + AUDIO_BIS_MASK = 0x4000, + AUDIO_BIE_MASK = 0x8000, + + AUDIO_ENVCLK0 = 0x406, + + AUDIO_ENVCLK0_HIGH = 0x407, + AUDIO_ENVCLK0_HIGH_MASK = 0xffff, + + AUDIO_ENVCLK1 = 0x408, + + AUDIO_ENVCLK1_HIGH = 0x409, + AUDIO_ENVCLK1_HIGH_MASK = 0xffff, + + AUDIO_ENV_RAMP_DOWN = 0x40a, + AUDIO_ENV_RAMP_DOWN_MASK = 0xffff, + + AUDIO_CHANNEL_STOP = 0x40b, + AUDIO_CHANNEL_STOP_MASK = 0xffff, + + AUDIO_CHANNEL_ZERO_CROSS = 0x40c, + AUDIO_CHANNEL_ZERO_CROSS_MASK = 0xffff, + + AUDIO_CONTROL = 0x40d, + AUDIO_CONTROL_MASK = 0x9fe8, + AUDIO_CONTROL_SATURATE_MASK = 0x8000, + AUDIO_CONTROL_SOFTCH_MASK = 0x1000, + AUDIO_CONTROL_COMPEN_MASK = 0x0800, + AUDIO_CONTROL_NOHIGH_MASK = 0x0400, + AUDIO_CONTROL_NOINT_MASK = 0x0200, + AUDIO_CONTROL_EQEN_MASK = 0x0100, + AUDIO_CONTROL_VOLSEL_MASK = 0x00c0, + AUDIO_CONTROL_VOLSEL_SHIFT = 6, + AUDIO_CONTROL_FOF_MASK = 0x0020, + AUDIO_CONTROL_INIT_MASK = 0x0008, + + AUDIO_COMPRESS_CTRL = 0x40e, + AUDIO_COMPRESS_CTRL_PEAK_MASK = 0x8000, + AUDIO_COMPRESS_CTRL_THRESHOLD_MASK = 0x7f00, + AUDIO_COMPRESS_CTRL_THRESHOLD_SHIFT = 8, + AUDIO_COMPRESS_CTRL_ATTSCALE_MASK = 0x00c0, + AUDIO_COMPRESS_CTRL_ATTSCALE_SHIFT = 6, + AUDIO_COMPRESS_CTRL_RELSCALE_MASK = 0x0030, + AUDIO_COMPRESS_CTRL_RELSCALE_SHIFT = 4, + AUDIO_COMPRESS_CTRL_DISZC_MASK = 0x0008, + AUDIO_COMPRESS_CTRL_RATIO_MASK = 0x0007, + + AUDIO_CHANNEL_STATUS = 0x40f, + AUDIO_CHANNEL_STATUS_MASK = 0xffff, + + AUDIO_WAVE_IN_L = 0x410, + + AUDIO_WAVE_IN_R = 0x411, + AUDIO_SOFTIRQ_MASK = 0x8000, + AUDIO_SOFTIRQ_EN_MASK = 0x4000, + AUDIO_SOFT_PHASE_HIGH_MASK = 0x0070, + AUDIO_SOFT_PHASE_HIGH_SHIFT = 4, + AUDIO_FIFO_IRQ_THRESHOLD_MASK = 0x000f, + + AUDIO_WAVE_OUT_L = 0x412, + AUDIO_WAVE_OUT_R = 0x413, + + AUDIO_CHANNEL_REPEAT = 0x414, + AUDIO_CHANNEL_REPEAT_MASK = 0xffff, + + AUDIO_CHANNEL_ENV_MODE = 0x415, + AUDIO_CHANNEL_ENV_MODE_MASK = 0xffff, + + AUDIO_CHANNEL_TONE_RELEASE = 0x416, + AUDIO_CHANNEL_TONE_RELEASE_MASK = 0xffff, + + AUDIO_CHANNEL_ENV_IRQ = 0x417, + AUDIO_CHANNEL_ENV_IRQ_MASK = 0xffff, + + AUDIO_CHANNEL_PITCH_BEND = 0x418, + AUDIO_CHANNEL_PITCH_BEND_MASK = 0xffff, + + AUDIO_SOFT_PHASE = 0x419, - DECLARE_READ16_MEMBER(dma_r); - DECLARE_WRITE16_MEMBER(dma_w); + AUDIO_ATTACK_RELEASE = 0x41a, + AUDIO_RELEASE_TIME_MASK = 0x00ff, + AUDIO_ATTACK_TIME_MASK = 0xff00, + AUDIO_ATTACK_TIME_SHIFT = 8, - DECLARE_WRITE_LINE_MEMBER(audioirq_w); - DECLARE_WRITE_LINE_MEMBER(timerirq_w); - DECLARE_WRITE_LINE_MEMBER(uartirq_w); - DECLARE_WRITE_LINE_MEMBER(extirq_w); - DECLARE_WRITE_LINE_MEMBER(ffreq1_w); - DECLARE_WRITE_LINE_MEMBER(ffreq2_w); + AUDIO_EQ_CUTOFF10 = 0x41b, + AUDIO_EQ_CUTOFF10_MASK = 0x7f7f, - DECLARE_READ16_MEMBER(space_r); + AUDIO_EQ_CUTOFF32 = 0x41c, + AUDIO_EQ_CUTOFF32_MASK = 0x7f7f, + AUDIO_EQ_GAIN10 = 0x41d, + AUDIO_EQ_GAIN10_MASK = 0x7f7f, + + AUDIO_EQ_GAIN32 = 0x41e, + AUDIO_EQ_GAIN32_MASK = 0x7f7f + }; + + DECLARE_READ16_MEMBER(video_r); + DECLARE_WRITE16_MEMBER(video_w); + DECLARE_READ16_MEMBER(audio_r); + DECLARE_WRITE16_MEMBER(audio_w); + DECLARE_READ16_MEMBER(io_r); + DECLARE_WRITE16_MEMBER(io_w); + + void check_irqs(const uint16_t changed); inline void check_video_irq(); void spg2xx_map(address_map &map); + static const device_timer_id TIMER_TMB1 = 0; + static const device_timer_id TIMER_TMB2 = 1; static const device_timer_id TIMER_SCREENPOS = 2; - + static const device_timer_id TIMER_BEAT = 3; virtual void device_start() override; virtual void device_reset() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + void update_porta_special_modes(); + void update_portb_special_modes(); + void do_gpio(uint32_t offset); + + void do_i2c(); void do_cpu_dma(uint32_t len); void do_sprite_dma(uint32_t len); - enum blend_enable_t : bool - { - BlendOff = false, - BlendOn = true - }; - - enum rowscroll_enable_t : bool - { - RowScrollOff = false, - RowScrollOn = true - }; - - enum flipx_t : bool - { - FlipXOff = false, - FlipXOn = true - }; - void apply_saturation(const rectangle &cliprect); void apply_fade(const rectangle &cliprect); + void blit(const rectangle &cliprect, uint32_t xoff, uint32_t yoff, uint32_t attr, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile); + void blit_page(const rectangle &cliprect, int depth, uint32_t bitmap_addr, uint16_t *regs); + void blit_sprite(const rectangle &cliprect, int depth, uint32_t base_addr); + void blit_sprites(const rectangle &cliprect, int depth); - template<blend_enable_t Blend, rowscroll_enable_t RowScroll, flipx_t FlipX> - void blit(const rectangle &cliprect, uint32_t line, uint32_t xoff, uint32_t yoff, uint32_t attr, uint32_t ctrl, uint32_t bitmap_addr, uint16_t tile); - void blit_page(const rectangle &cliprect, uint32_t scanline, int depth, uint32_t bitmap_addr, uint16_t *regs); - void blit_sprite(const rectangle &cliprect, uint32_t scanline, int depth, uint32_t base_addr); - void blit_sprites(const rectangle &cliprect, uint32_t scanline, int depth); - + uint8_t expand_rgb5_to_rgb8(uint8_t val); uint8_t mix_channel(uint8_t a, uint8_t b); + void mix_pixel(uint32_t offset, uint16_t rgb); + void set_pixel(uint32_t offset, uint16_t rgb); + + void stop_channel(const uint32_t channel); + bool advance_channel(address_space &space, const uint32_t channel); + bool fetch_sample(address_space &space, const uint32_t channel); + void loop_channel(const uint32_t channel); + + struct rgbtriad_t + { + uint8_t r, g, b; + }; - uint32_t m_screenbuf[320 * 240]; - uint8_t m_rgb5_to_rgb8[32]; - uint32_t m_rgb555_to_rgb888[0x8000]; + rgbtriad_t m_screenbuf[320 * 240]; bool m_hide_page0; bool m_hide_page1; bool m_hide_sprites; bool m_debug_sprites; bool m_debug_blit; - bool m_debug_palette; uint8_t m_sprite_index_to_debug; - uint16_t m_dma_regs[0x4]; + bool m_debug_samples; + bool m_debug_rates; + + uint16_t m_audio_regs[0x800]; + uint8_t m_sample_shift[16]; + uint32_t m_sample_count[16]; + uint32_t m_sample_addr[16]; + double m_channel_rate[16]; + double m_channel_rate_accum[16]; + uint32_t m_rampdown_frame[16]; + uint32_t m_envclk_frame[16]; + uint32_t m_envelope_addr[16]; + int m_channel_debug; + uint16_t m_audio_curr_beat_base_count; + + uint16_t m_io_regs[0x200]; + uint8_t m_uart_rx_fifo[8]; + uint8_t m_uart_rx_fifo_start; + uint8_t m_uart_rx_fifo_end; + uint8_t m_uart_rx_fifo_count; + bool m_uart_rx_available; uint16_t m_video_regs[0x100]; - uint32_t m_sprite_limit; - int m_rowscrolloffset; // auto racing in 'zone60' minigames needs this to be 15, the JAKKS games (Star Wars Revenge of the sith - Gunship Battle, Wheel of Fortune, Namco Ms. Pac-Man 5-in-1 Pole Position) need it to be 0, where does it come from? + size_t m_sprite_limit; uint16_t m_pal_flag; devcb_write16 m_porta_out; @@ -184,8 +473,6 @@ protected: devcb_read16 m_portb_in; devcb_read16 m_portc_in; - devcb_read16 m_adc_in[2]; - devcb_write8 m_eeprom_w; devcb_read8 m_eeprom_r; @@ -193,7 +480,13 @@ protected: devcb_write8 m_chip_sel; + emu_timer *m_tmb1; + emu_timer *m_tmb2; emu_timer *m_screenpos_timer; + emu_timer *m_audio_beat; + + sound_stream *m_stream; + oki_adpcm_state m_adpcm[16]; required_device<unsp_device> m_cpu; required_device<screen_device> m_screen; @@ -201,23 +494,8 @@ protected: required_shared_ptr<uint16_t> m_paletteram; required_shared_ptr<uint16_t> m_spriteram; - void configure_spg_io(spg2xx_io_device* io); - - DECLARE_READ16_MEMBER(porta_r) { return m_porta_in(); }; - DECLARE_READ16_MEMBER(portb_r) { return m_portb_in(); }; - DECLARE_READ16_MEMBER(portc_r) { return m_portc_in(); }; - DECLARE_WRITE16_MEMBER(porta_w) { m_porta_out(offset, data, mem_mask); }; - DECLARE_WRITE16_MEMBER(portb_w) { m_portb_out(offset, data, mem_mask); }; - DECLARE_WRITE16_MEMBER(portc_w) { m_portc_out(offset, data, mem_mask); }; - template <size_t Line> DECLARE_READ16_MEMBER(adc_r) { return m_adc_in[Line](); }; - - DECLARE_WRITE8_MEMBER(eepromx_w) { m_eeprom_w(offset, data, mem_mask); }; - DECLARE_READ8_MEMBER(eepromx_r) { return m_eeprom_r(); }; - - DECLARE_WRITE8_MEMBER(tx_w) { m_uart_tx(offset, data, mem_mask); }; - DECLARE_WRITE8_MEMBER(cs_w) { m_chip_sel(offset, data, mem_mask); }; - DECLARE_READ16_MEMBER(get_pal_r) { return m_pal_flag; }; - + static const uint32_t s_rampdown_frame_counts[8]; + static const uint32_t s_envclk_frame_counts[16]; }; class spg24x_device : public spg2xx_device @@ -232,9 +510,6 @@ public: } spg24x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_add_mconfig(machine_config &config) override; - }; class spg28x_device : public spg2xx_device @@ -249,9 +524,6 @@ public: } spg28x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_add_mconfig(machine_config &config) override; - }; DECLARE_DEVICE_TYPE(SPG24X, spg24x_device) diff --git a/src/devices/machine/spg2xx_audio.cpp b/src/devices/machine/spg2xx_audio.cpp deleted file mode 100644 index a09eb907694..00000000000 --- a/src/devices/machine/spg2xx_audio.cpp +++ /dev/null @@ -1,1258 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/***************************************************************************** - - SunPlus SPG2xx-series SoC peripheral emulation (Audio) - -**********************************************************************/ - -#include "emu.h" -#include "spg2xx_audio.h" - -DEFINE_DEVICE_TYPE(SPG2XX_AUDIO, spg2xx_audio_device, "spg2xx", "SPG2xx-series System-on-a-Chip Audio") - -#define LOG_SPU_READS (1U << 0) -#define LOG_SPU_WRITES (1U << 1) -#define LOG_UNKNOWN_SPU (1U << 2) -#define LOG_CHANNEL_READS (1U << 3) -#define LOG_CHANNEL_WRITES (1U << 4) -#define LOG_ENVELOPES (1U << 5) -#define LOG_SAMPLES (1U << 6) -#define LOG_RAMPDOWN (1U << 7) -#define LOG_BEAT (1U << 8) - -#define LOG_ALL (LOG_SPU_READS | LOG_SPU_WRITES | LOG_UNKNOWN_SPU | LOG_CHANNEL_READS | LOG_CHANNEL_WRITES \ - | LOG_ENVELOPES | LOG_SAMPLES | LOG_RAMPDOWN | LOG_BEAT) - -#define VERBOSE (0) -#include "logmacro.h" - -#define SPG_DEBUG_AUDIO (0) - - -spg2xx_audio_device::spg2xx_audio_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock) - , device_sound_interface(mconfig, *this) - , m_space_read_cb(*this) - , m_irq_cb(*this) -{ -} - -spg2xx_audio_device::spg2xx_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : spg2xx_audio_device(mconfig, SPG2XX_AUDIO, tag, owner, clock) -{ -} - - -void spg2xx_audio_device::device_start() -{ - m_audio_beat = timer_alloc(TIMER_BEAT); - m_audio_beat->adjust(attotime::never); - - m_stream = stream_alloc(0, 2, 281250/4); - - m_channel_debug = -1; - - save_item(NAME(m_debug_samples)); - save_item(NAME(m_debug_rates)); - - save_item(NAME(m_audio_regs)); - save_item(NAME(m_audio_phase_regs)); - save_item(NAME(m_audio_ctrl_regs)); - - save_item(NAME(m_sample_shift)); - save_item(NAME(m_sample_count)); - save_item(NAME(m_sample_addr)); - save_item(NAME(m_channel_rate)); - save_item(NAME(m_channel_rate_accum)); - save_item(NAME(m_rampdown_frame)); - save_item(NAME(m_envclk_frame)); - save_item(NAME(m_envelope_addr)); - save_item(NAME(m_channel_debug)); - save_item(NAME(m_audio_curr_beat_base_count)); - - - for (int i = 0; i < 16; i++) - { - save_item(NAME(m_adpcm[i].m_signal), i); - save_item(NAME(m_adpcm[i].m_step), i); - } - - m_space_read_cb.resolve_safe(0); - m_irq_cb.resolve(); -} - -void spg2xx_audio_device::device_reset() -{ - memset(m_audio_regs, 0, 0x200 * sizeof(uint16_t)); - memset(m_audio_phase_regs, 0, 0x200 * sizeof(uint16_t)); - memset(m_audio_ctrl_regs, 0, 0x400 * sizeof(uint16_t)); - - memset(m_sample_shift, 0, 16); - memset(m_sample_count, 0, sizeof(uint32_t) * 16); - memset(m_sample_addr, 0, sizeof(uint32_t) * 16); - memset(m_channel_rate, 0, sizeof(double) * 16); - memset(m_channel_rate_accum, 0, sizeof(double) * 16); - memset(m_rampdown_frame, 0, sizeof(uint32_t) * 16); - memset(m_envclk_frame, 4, sizeof(uint32_t) * 16); - memset(m_envelope_addr, 0, sizeof(uint32_t) * 16); - - m_debug_samples = false; - m_debug_rates = false; - m_audio_curr_beat_base_count = 0; - - m_audio_ctrl_regs[AUDIO_CHANNEL_REPEAT] = 0x3f; - m_audio_ctrl_regs[AUDIO_CHANNEL_ENV_MODE] = 0x3f; - - m_audio_beat->adjust(attotime::from_ticks(4, 281250), 0, attotime::from_ticks(4, 281250)); -} - - -void spg2xx_audio_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch (id) - { - case TIMER_BEAT: - audio_beat_tick(); - break; - } -} - -/*********************** -* Audio Hardware * -***********************/ -void spg2xx_audio_device::check_irqs(const uint16_t changed) -{ - if (changed & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) // Beat IRQ - { - if ((m_audio_ctrl_regs[AUDIO_BEAT_COUNT] & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) == (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) - { - LOGMASKED(LOG_BEAT, "Asserting beat IRQ\n"); - m_irq_cb(true); - } - else - { - LOGMASKED(LOG_BEAT, "Clearing beat IRQ\n"); - m_irq_cb(false); - } - } -} - -READ16_MEMBER(spg2xx_audio_device::audio_ctrl_r) -{ - uint16_t data = m_audio_ctrl_regs[offset]; - - switch (offset) - { - case AUDIO_CHANNEL_ENABLE: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Channel Enable: %04x\n", data); - break; - - case AUDIO_MAIN_VOLUME: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Main Volume: %04x\n", data); - break; - - case AUDIO_CHANNEL_FIQ_ENABLE: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Channel FIQ Enable: %04x\n", data); - break; - - case AUDIO_CHANNEL_FIQ_STATUS: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Channel FIQ Acknowledge: %04x\n", data); - break; - - case AUDIO_BEAT_BASE_COUNT: - LOGMASKED(LOG_SPU_READS | LOG_BEAT, "audio_ctrl_r: Beat Base Count: %04x\n", data); - break; - - case AUDIO_BEAT_COUNT: - LOGMASKED(LOG_SPU_READS | LOG_BEAT, "audio_ctrl_r: Beat Count: %04x\n", data); - break; - - case AUDIO_ENVCLK0: - case AUDIO_ENVCLK1: - LOGMASKED(LOG_SPU_READS | LOG_ENVELOPES, "audio_ctrl_r: Envelope Interval %d (lo): %04x\n", offset == AUDIO_ENVCLK0 ? 0 : 1, data); - break; - - case AUDIO_ENVCLK0_HIGH: - case AUDIO_ENVCLK1_HIGH: - LOGMASKED(LOG_SPU_READS | LOG_ENVELOPES, "audio_ctrl_r: Envelope Interval %d (hi): %04x\n", offset == AUDIO_ENVCLK0_HIGH ? 0 : 1, data); - break; - - case AUDIO_ENV_RAMP_DOWN: - LOGMASKED(LOG_SPU_READS | LOG_RAMPDOWN, "audio_ctrl_r: Envelope Fast Ramp Down: %04x\n", data); - break; - - case AUDIO_CHANNEL_STOP: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Channel Stop Status: %04x\n", data); - break; - - case AUDIO_CHANNEL_ZERO_CROSS: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Channel Zero-Cross Enable: %04x\n", data); - break; - - case AUDIO_CONTROL: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Control: %04x\n", data); - break; - - case AUDIO_COMPRESS_CTRL: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Compressor Control: %04x\n", data); - break; - - case AUDIO_CHANNEL_STATUS: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Channel Status: %04x\n", data); - break; - - case AUDIO_WAVE_IN_L: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Wave In (L) / FIFO Write Data: %04x\n", data); - break; - - case AUDIO_WAVE_IN_R: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Wave In (R) / Software Channel FIFO IRQ Control: %04x\n", data); - break; - - case AUDIO_WAVE_OUT_L: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Wave Out (L): %04x\n", data); - break; - - case AUDIO_WAVE_OUT_R: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Wave Out (R): %04x\n", data); - break; - - case AUDIO_CHANNEL_REPEAT: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Channel Repeat Enable: %04x\n", data); - break; - - case AUDIO_CHANNEL_ENV_MODE: - LOGMASKED(LOG_SPU_READS | LOG_ENVELOPES, "audio_ctrl_r: Channel Envelope Enable: %04x\n", data); - break; - - case AUDIO_CHANNEL_TONE_RELEASE: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Channel Tone Release Enable: %04x\n", data); - break; - - case AUDIO_CHANNEL_ENV_IRQ: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Channel Envelope IRQ Status: %04x\n", data); - break; - - case AUDIO_CHANNEL_PITCH_BEND: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Channel Pitch Bend Enable: %04x\n", data); - break; - - case AUDIO_SOFT_PHASE: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Software Channel Phase: %04x\n", data); - break; - - case AUDIO_ATTACK_RELEASE: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: Attack/Release Time Control: %04x\n", data); - break; - - case AUDIO_EQ_CUTOFF10: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: EQ Cutoff Frequency 0/1: %04x\n", data); - break; - - case AUDIO_EQ_CUTOFF32: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: EQ Cutoff Frequency 2/3: %04x\n", data); - break; - - case AUDIO_EQ_GAIN10: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: EQ Cutoff Gain 0/1: %04x\n", data); - break; - - case AUDIO_EQ_GAIN32: - LOGMASKED(LOG_SPU_READS, "audio_ctrl_r: EQ Cutoff Gain 2/3: %04x\n", data); - break; - - default: - LOGMASKED(LOG_UNKNOWN_SPU, "audio_ctrl_r: Unknown register %04x = %04x\n", 0x3000 + offset, data); - break; - } - - return data; -} - -READ16_MEMBER(spg2xx_audio_device::audio_r) -{ - const uint16_t channel = (offset & 0x00f0) >> 4; - uint16_t data = m_audio_regs[offset]; - - - switch (offset & AUDIO_CHAN_OFFSET_MASK) - { - case AUDIO_WAVE_ADDR: - LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Wave Addr (lo): %04x\n", channel, data); - break; - - case AUDIO_MODE: - LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Mode: %04x (ADPCM:%d, 16M:%d, TONE:%d, LADDR_HI:%04x, WADDR_HI:%04x)\n", channel, data, - get_adpcm_bit(channel), get_16bit_bit(channel), get_tone_mode(channel), get_loop_addr_high(channel), get_wave_addr_high(channel)); - break; - - case AUDIO_LOOP_ADDR: - LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Loop Addr: %04x\n", channel, data); - break; - - case AUDIO_PAN_VOL: - LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Pan/Vol: %04x (PAN:%02x, VOL:%02x)\n", channel, data, - get_pan(channel), get_volume(channel)); - break; - - case AUDIO_ENVELOPE0: - LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope0: %04x (RPTPER:%d, TARGET:%02x, SIGN:%d, INC:%02x)\n", channel, data, - get_repeat_period_bit(channel), get_envelope_target(channel), get_envelope_sign_bit(channel), get_envelope_inc(channel)); - break; - - case AUDIO_ENVELOPE_DATA: - LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope Data: %04x (CNT:%d, EDD:%02x)\n", channel, data, - get_envelope_count(channel), get_edd(channel)); - break; - - case AUDIO_ENVELOPE1: - LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope1 Data: %04x (RPTCNT:%02x, RPT:%d, LOAD:%02x)\n", channel, data, - get_envelope_repeat_count(channel), get_envelope_repeat_bit(channel), get_envelope_load(channel)); - break; - - case AUDIO_ENVELOPE_ADDR_HIGH: - LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope Addr (hi): %04x (IRQADDR:%03x, IRQEN:%d, EADDR_HI:%02x)\n", channel, data, - get_audio_irq_addr(channel), get_audio_irq_enable_bit(channel), get_envelope_addr_high(channel)); - break; - - case AUDIO_ENVELOPE_ADDR: - LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope Addr (lo): %04x \n", channel, data); - break; - - case AUDIO_WAVE_DATA_PREV: - LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Wave Data Prev: %04x \n", channel, data); - break; - - case AUDIO_ENVELOPE_LOOP_CTRL: - LOGMASKED(LOG_CHANNEL_READS | LOG_ENVELOPES, "audio_r: Channel %d: Envelope Loop Ctrl: %04x (RDOFFS:%02x, EAOFFS:%03x)\n", channel, data, - get_rampdown_offset(channel), get_envelope_eaoffset(channel)); - break; - - case AUDIO_WAVE_DATA: - LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: Wave Data: %04x\n", channel, data); - break; - - case AUDIO_ADPCM_SEL: - LOGMASKED(LOG_CHANNEL_READS, "audio_r: Channel %d: ADPCM Sel: %04x (ADPCM36:%d, POINTNUM:%02x\n", channel, data, - get_adpcm36_bit(channel), get_point_number(channel)); - break; - - default: - LOGMASKED(LOG_UNKNOWN_SPU, "audio_r: Unknown register %04x\n", 0x3000 + offset); - break; - - } - - return data; -} - - -READ16_MEMBER(spg2xx_audio_device::audio_phase_r) -{ - const uint16_t channel = (offset & 0x00f0) >> 4; - uint16_t data = m_audio_phase_regs[offset]; - - switch (offset & AUDIO_CHAN_OFFSET_MASK) - { - case AUDIO_PHASE_HIGH: - LOGMASKED(LOG_CHANNEL_READS, "audio_phase_r: Channel %d: Phase High: %04x\n", channel, data); - break; - - case AUDIO_PHASE_ACCUM_HIGH: - LOGMASKED(LOG_CHANNEL_READS, "audio_phase_r: Channel %d: Phase Accum High: %04x\n", channel, data); - break; - - case AUDIO_TARGET_PHASE_HIGH: - LOGMASKED(LOG_CHANNEL_READS, "audio_phase_r: Channel %d: Target Phase High: %04x\n", channel, data); - break; - - case AUDIO_RAMP_DOWN_CLOCK: - LOGMASKED(LOG_CHANNEL_READS | LOG_RAMPDOWN, "audio_phase_r: Channel %d: Rampdown Clock: %04x\n", channel, data); - break; - - case AUDIO_PHASE: - LOGMASKED(LOG_CHANNEL_READS, "audio_phase_r: Channel %d: Phase: %04x\n", channel, data); - break; - - case AUDIO_PHASE_ACCUM: - LOGMASKED(LOG_CHANNEL_READS, "audio_phase_r: Channel %d: Phase Accum: %04x\n", channel, data); - break; - - case AUDIO_TARGET_PHASE: - LOGMASKED(LOG_CHANNEL_READS, "audio_phase_r: Channel %d: Target Phase: %04x\n", channel, data); - break; - - case AUDIO_PHASE_CTRL: - LOGMASKED(LOG_CHANNEL_READS, "audio_phase_r: Channel %d: Phase Ctrl: %04x (TIMESTEP:%d, SIGN:%d, OFFSET:%03x\n", channel, data, - get_phase_time_step(channel), get_phase_sign_bit(channel), get_phase_offset(channel)); - break; - - default: - LOGMASKED(LOG_UNKNOWN_SPU, "audio_phase_r: Unknown register %04x\n", 0x3000 + offset); - break; - } - - return data; -} - -WRITE16_MEMBER(spg2xx_audio_device::audio_ctrl_w) -{ - switch (offset) - { - case AUDIO_CHANNEL_ENABLE: - { - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel Enable: %04x\n", data); - const uint16_t changed = m_audio_ctrl_regs[AUDIO_CHANNEL_ENABLE] ^ data; - for (uint32_t channel_bit = 0; channel_bit < 16; channel_bit++) - { - const uint16_t mask = 1 << channel_bit; - if (!(changed & mask)) - continue; - - if (data & mask) - { - if (!(m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] & mask)) - { - LOGMASKED(LOG_SPU_WRITES, "Enabling channel %d\n", channel_bit); - m_audio_ctrl_regs[offset] |= mask; - if (!(m_audio_ctrl_regs[AUDIO_CHANNEL_STOP] & mask)) - { - LOGMASKED(LOG_SPU_WRITES, "Stop not set, starting playback on channel %d, mask %04x\n", channel_bit, mask); - m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] |= mask; - m_sample_addr[channel_bit] = get_wave_addr(channel_bit); - m_envelope_addr[channel_bit] = get_envelope_addr(channel_bit); - set_envelope_count(channel_bit, get_envelope_load(channel_bit)); - } - m_adpcm[channel_bit].reset(); - m_sample_shift[channel_bit] = 0; - m_sample_count[channel_bit] = 0; - } - } - else - { - stop_channel(channel_bit); - //m_audio_ctrl_regs[offset] &= ~mask; - //m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] &= ~mask; - //m_audio_ctrl_regs[AUDIO_CHANNEL_STOP] |= mask; - //m_audio_ctrl_regs[AUDIO_CHANNEL_TONE_RELEASE] &= ~mask; - } - } - break; - } - - case AUDIO_MAIN_VOLUME: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Main Volume: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_MAIN_VOLUME_MASK; - break; - - case AUDIO_CHANNEL_FIQ_ENABLE: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel FIQ Enable: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_CHANNEL_FIQ_ENABLE_MASK; - break; - - case AUDIO_CHANNEL_FIQ_STATUS: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel FIQ Acknowledge: %04x\n", data); - m_audio_ctrl_regs[offset] &= ~(data & AUDIO_CHANNEL_FIQ_STATUS_MASK); - break; - - case AUDIO_BEAT_BASE_COUNT: - LOGMASKED(LOG_SPU_WRITES | LOG_BEAT, "audio_ctrl_w: Beat Base Count: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_BEAT_BASE_COUNT_MASK; - m_audio_curr_beat_base_count = m_audio_ctrl_regs[offset]; - break; - - case AUDIO_BEAT_COUNT: - { - LOGMASKED(LOG_SPU_WRITES | LOG_BEAT, "audio_ctrl_w: Beat Count: %04x\n", data); - const uint16_t old = m_audio_ctrl_regs[offset]; - m_audio_ctrl_regs[offset] &= ~(data & AUDIO_BIS_MASK); - m_audio_ctrl_regs[offset] &= AUDIO_BIS_MASK; - m_audio_ctrl_regs[offset] |= data & ~AUDIO_BIS_MASK; - const uint16_t changed = old ^ m_audio_ctrl_regs[offset]; - if (changed & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) - { - LOGMASKED(LOG_BEAT, "BIS mask changed, updating IRQ\n"); - check_irqs(changed & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)); - } - break; - } - - case AUDIO_ENVCLK0: - case AUDIO_ENVCLK1: - { - LOGMASKED(LOG_SPU_WRITES | LOG_ENVELOPES, "audio_ctrl_w: Envelope Interval %d (lo): %04x\n", offset == AUDIO_ENVCLK0 ? 0 : 1, data); - const uint16_t old = m_audio_ctrl_regs[offset]; - m_audio_ctrl_regs[offset] = data; - const uint16_t changed = old ^ m_audio_ctrl_regs[offset]; - - if (!changed) - break; - - const uint8_t channel_offset = offset == AUDIO_ENVCLK0 ? 0 : 8; - for (uint8_t channel_bit = 0; channel_bit < 4; channel_bit++) - { - const uint8_t shift = channel_bit << 2; - const uint16_t mask = 0x0f << shift; - if (changed & mask) - { - m_envclk_frame[channel_bit + channel_offset] = get_envclk_frame_count(channel_bit + channel_offset); - } - } - break; - } - - case AUDIO_ENVCLK0_HIGH: - case AUDIO_ENVCLK1_HIGH: - { - LOGMASKED(LOG_SPU_WRITES | LOG_ENVELOPES, "audio_ctrl_w: Envelope Interval %d (hi): %04x\n", offset == AUDIO_ENVCLK0_HIGH ? 0 : 1, data); - const uint16_t old = m_audio_ctrl_regs[offset]; - m_audio_ctrl_regs[offset] = data; - const uint16_t changed = old ^ m_audio_ctrl_regs[offset]; - if (!changed) - break; - - const uint8_t channel_offset = offset == AUDIO_ENVCLK0_HIGH ? 0 : 8; - for (uint8_t channel_bit = 0; channel_bit < 4; channel_bit++) - { - const uint8_t shift = channel_bit << 2; - const uint16_t mask = 0x0f << shift; - if (changed & mask) - { - m_envclk_frame[channel_bit + channel_offset + 4] = get_envclk_frame_count(channel_bit + channel_offset); - } - } - break; - } - - case AUDIO_ENV_RAMP_DOWN: - { - LOGMASKED(LOG_SPU_WRITES | LOG_RAMPDOWN, "audio_ctrl_w: Envelope Fast Ramp Down: %04x\n", data); - const uint16_t old = m_audio_ctrl_regs[offset]; - m_audio_ctrl_regs[offset] = (data & AUDIO_ENV_RAMP_DOWN_MASK) & m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS]; - const uint16_t changed = old ^ m_audio_ctrl_regs[offset]; - if (!changed) - break; - - for (uint32_t channel_bit = 0; channel_bit < 16; channel_bit++) - { - const uint16_t mask = 1 << channel_bit; - if ((changed & mask) && (data & mask)) - { - m_rampdown_frame[channel_bit] = get_rampdown_frame_count(channel_bit); - LOGMASKED(LOG_RAMPDOWN, "Preparing to ramp down channel %d in %d ticks\n", channel_bit, m_rampdown_frame[channel_bit] / 13); - } - } - break; - } - - case AUDIO_CHANNEL_STOP: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel Stop Status: %04x\n", data); - m_audio_ctrl_regs[offset] &= ~data; - break; - - case AUDIO_CHANNEL_ZERO_CROSS: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel Zero-Cross Enable: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_CHANNEL_ZERO_CROSS_MASK; - break; - - case AUDIO_CONTROL: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Control: %04x (SOFTCH:%d, COMPEN:%d, NOHIGH:%d, NOINT:%d, EQEN:%d, VOLSEL:%d)\n", data - , (data & AUDIO_CONTROL_SOFTCH_MASK) ? 1 : 0 - , (data & AUDIO_CONTROL_COMPEN_MASK) ? 1 : 0 - , (data & AUDIO_CONTROL_NOHIGH_MASK) ? 1 : 0 - , (data & AUDIO_CONTROL_NOINT_MASK) ? 1 : 0 - , (data & AUDIO_CONTROL_EQEN_MASK) ? 1 : 0 - , (data & AUDIO_CONTROL_VOLSEL_MASK) >> AUDIO_CONTROL_VOLSEL_SHIFT); - m_audio_ctrl_regs[offset] = data & AUDIO_CONTROL_MASK; - break; - - case AUDIO_COMPRESS_CTRL: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Compressor Control: %04x\n", data); - m_audio_ctrl_regs[offset] = data; - break; - - case AUDIO_CHANNEL_STATUS: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel Status (read-only): %04x\n", data); - break; - - case AUDIO_WAVE_IN_L: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Wave In (L) / FIFO Write Data: %04x\n", data); - m_audio_ctrl_regs[offset] = data; - break; - - case AUDIO_WAVE_IN_R: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Wave In (R) / Software Channel FIFO IRQ Control: %04x\n", data); - m_audio_ctrl_regs[offset] = data; - break; - - case AUDIO_WAVE_OUT_L: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Wave Out (L): %04x\n", data); - m_audio_ctrl_regs[offset] = data; - break; - - case AUDIO_WAVE_OUT_R: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Wave Out (R): %04x\n", data); - m_audio_ctrl_regs[offset] = data; - break; - - case AUDIO_CHANNEL_REPEAT: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel Repeat Enable: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_CHANNEL_REPEAT_MASK; - break; - - case AUDIO_CHANNEL_ENV_MODE: - LOGMASKED(LOG_SPU_WRITES | LOG_ENVELOPES, "audio_ctrl_w: Channel Envelope Enable: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_CHANNEL_ENV_MODE_MASK; - break; - - case AUDIO_CHANNEL_TONE_RELEASE: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel Tone Release Enable: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_CHANNEL_TONE_RELEASE_MASK; - break; - - case AUDIO_CHANNEL_ENV_IRQ: - LOGMASKED(LOG_SPU_WRITES | LOG_ENVELOPES, "audio_ctrl_w: Channel Envelope IRQ Acknowledge: %04x\n", data); - m_audio_ctrl_regs[offset] &= ~data & AUDIO_CHANNEL_ENV_IRQ_MASK; - break; - - case AUDIO_CHANNEL_PITCH_BEND: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Channel Pitch Bend Enable: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_CHANNEL_PITCH_BEND_MASK; - break; - - case AUDIO_SOFT_PHASE: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Software Channel Phase: %04x\n", data); - m_audio_ctrl_regs[offset] = data; - break; - - case AUDIO_ATTACK_RELEASE: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: Attack/Release Time Control: %04x\n", data); - m_audio_ctrl_regs[offset] = data; - break; - - case AUDIO_EQ_CUTOFF10: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: EQ Cutoff Frequency 0/1: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_EQ_CUTOFF10_MASK; - break; - - case AUDIO_EQ_CUTOFF32: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: EQ Cutoff Frequency 2/3: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_EQ_CUTOFF32_MASK; - break; - - case AUDIO_EQ_GAIN10: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: EQ Cutoff Gain 0/1: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_EQ_GAIN10_MASK; - break; - - case AUDIO_EQ_GAIN32: - LOGMASKED(LOG_SPU_WRITES, "audio_ctrl_w: EQ Cutoff Gain 2/3: %04x\n", data); - m_audio_ctrl_regs[offset] = data & AUDIO_EQ_GAIN32_MASK; - break; - - default: - m_audio_ctrl_regs[offset] = data; - LOGMASKED(LOG_UNKNOWN_SPU, "audio_ctrl_w: Unknown register %04x = %04x\n", 0x3000 + offset, data); - break; - } -} - -WRITE16_MEMBER(spg2xx_audio_device::audio_phase_w) -{ - const uint16_t channel = (offset & 0x00f0) >> 4; - - switch (offset & AUDIO_CHAN_OFFSET_MASK) - { - case AUDIO_PHASE_HIGH: - m_audio_phase_regs[offset] = data & AUDIO_PHASE_HIGH_MASK; - m_channel_rate[channel] = ((double)get_phase(channel) * 140625.0 * 2.0) / (double)(1 << 19); - m_channel_rate_accum[channel] = 0.0; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_phase_w: Channel %d: Phase High: %04x (rate: %f)\n", channel, data, m_channel_rate[channel]); - break; - - case AUDIO_PHASE_ACCUM_HIGH: - m_audio_phase_regs[offset] = data & AUDIO_PHASE_ACCUM_HIGH_MASK; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_phase_w: Channel %d: Phase Accum High: %04x\n", channel, data); - break; - - case AUDIO_TARGET_PHASE_HIGH: - m_audio_phase_regs[offset] = data & AUDIO_TARGET_PHASE_HIGH_MASK; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_phase_w: Channel %d: Target Phase High: %04x\n", channel, data); - break; - - case AUDIO_RAMP_DOWN_CLOCK: - m_audio_phase_regs[offset] = data & AUDIO_RAMP_DOWN_CLOCK_MASK; - LOGMASKED(LOG_CHANNEL_WRITES | LOG_RAMPDOWN, "audio_phase_w: Channel %d: Rampdown Clock: %04x\n", channel, data); - break; - - case AUDIO_PHASE: - m_audio_phase_regs[offset] = data; - m_channel_rate[channel] = ((double)get_phase(channel) * 140625.0 * 2.0) / (double)(1 << 19); - m_channel_rate_accum[channel] = 0.0; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_phase_w: Channel %d: Phase: %04x (rate: %f)\n", channel, data, m_channel_rate[channel]); - break; - - case AUDIO_PHASE_ACCUM: - m_audio_phase_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_phase_w: Channel %d: Phase Accum: %04x\n", channel, data); - break; - - case AUDIO_TARGET_PHASE: - m_audio_phase_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_phase_w: Channel %d: Target Phase: %04x\n", channel, data); - break; - - case AUDIO_PHASE_CTRL: - m_audio_phase_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_phase_w: Channel %d: Phase Ctrl: %04x (TIMESTEP:%d, SIGN:%d, OFFSET:%03x\n", channel, data, - get_phase_time_step(channel), get_phase_sign_bit(channel), get_phase_offset(channel)); - break; - - default: - m_audio_phase_regs[offset] = data; - LOGMASKED(LOG_UNKNOWN_SPU, "audio_phase_w: Unknown register %04x = %04x\n", 0x3000 + offset, data); - break; - } -} - - -WRITE16_MEMBER(spg2xx_audio_device::audio_w) -{ - const uint16_t channel = (offset & 0x00f0) >> 4; - - switch (offset & AUDIO_CHAN_OFFSET_MASK) - { - case AUDIO_WAVE_ADDR: - m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Wave Addr (lo): %04x\n", channel, data); - break; - - case AUDIO_MODE: - m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Mode: %04x (ADPCM:%d, 16M:%d, TONE:%d, LADDR_HI:%04x, WADDR_HI:%04x)\n", channel, data, - get_adpcm_bit(channel), get_16bit_bit(channel), get_tone_mode(channel), get_loop_addr_high(channel), get_wave_addr_high(channel)); - break; - - case AUDIO_LOOP_ADDR: - m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Loop Addr: %04x\n", channel, data); - break; - - case AUDIO_PAN_VOL: - m_audio_regs[offset] = data & AUDIO_PAN_VOL_MASK; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Pan/Vol: %04x (PAN:%02x, VOL:%02x)\n", channel, data, - get_pan(channel), get_volume(channel)); - break; - - case AUDIO_ENVELOPE0: - m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope0: %04x (RPTPER:%d, TARGET:%02x, SIGN:%d, INC:%02x)\n", channel, data, - get_repeat_period_bit(channel), get_envelope_target(channel), get_envelope_sign_bit(channel), get_envelope_inc(channel)); - break; - - case AUDIO_ENVELOPE_DATA: - m_audio_regs[offset] = data & AUDIO_ENVELOPE_DATA_MASK; - LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope Data: %04x (CNT:%d, EDD:%02x)\n", channel, data, - get_envelope_count(channel), get_edd(channel)); - break; - - case AUDIO_ENVELOPE1: - m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope1 Data: %04x (RPTCNT:%02x, RPT:%d, LOAD:%02x)\n", channel, data, - get_envelope_repeat_count(channel), get_envelope_repeat_bit(channel), get_envelope_load(channel)); - break; - - case AUDIO_ENVELOPE_ADDR_HIGH: - m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope Addr (hi): %04x (IRQADDR:%03x, IRQEN:%d, EADDR_HI:%02x)\n", channel, data, - get_audio_irq_addr(channel), get_audio_irq_enable_bit(channel), get_envelope_addr_high(channel)); - break; - - case AUDIO_ENVELOPE_ADDR: - m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope Addr (lo): %04x\n", channel, data); - break; - - case AUDIO_WAVE_DATA_PREV: - m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Wave Data Prev: %04x \n", channel, data); - break; - - case AUDIO_ENVELOPE_LOOP_CTRL: - m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES | LOG_ENVELOPES, "audio_w: Channel %d: Envelope Loop Ctrl: %04x (RDOFFS:%02x, EAOFFS:%03x)\n", channel, data, - get_rampdown_offset(channel), get_envelope_eaoffset(channel)); - break; - - case AUDIO_WAVE_DATA: - m_audio_regs[offset] = data; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: Wave Data: %04x\n", channel, data); - break; - - case AUDIO_ADPCM_SEL: - m_audio_regs[offset] = data & AUDIO_ADPCM_SEL_MASK; - LOGMASKED(LOG_CHANNEL_WRITES, "audio_w: Channel %d: ADPCM Sel: %04x (ADPCM36:%d, POINTNUM:%02x\n", channel, data, - get_adpcm36_bit(channel), get_point_number(channel)); - break; - - default: - m_audio_regs[offset] = data; - LOGMASKED(LOG_UNKNOWN_SPU, "audio_w: Unknown register %04x = %04x\n", 0x3000 + offset, data); - break; - - } -} - -void spg2xx_audio_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) -{ - stream_sample_t *out_l = outputs[0]; - stream_sample_t *out_r = outputs[1]; - - for (int i = 0; i < samples; i++) - { - int32_t left_total = 0; - int32_t right_total = 0; - - for (uint32_t channel = 0; channel < 16; channel++) - { - if (!get_channel_status(channel)) - { - continue; - } - - if (SPG_DEBUG_AUDIO && m_debug_rates) - printf("%f:%f ", m_channel_rate[channel], m_channel_rate_accum[channel]); - bool playing = advance_channel(channel); - if (playing) - { - int32_t sample = (int16_t)(m_audio_regs[(channel << 4) | AUDIO_WAVE_DATA] ^ 0x8000); - if (!(m_audio_ctrl_regs[AUDIO_CONTROL] & AUDIO_CONTROL_NOINT_MASK)) - { - int32_t prev_sample = (int16_t)(m_audio_regs[(channel << 4) | AUDIO_WAVE_DATA_PREV] ^ 0x8000); - int16_t lerp_factor = (int16_t)((m_channel_rate_accum[channel] / 70312.5) * 256.0); - prev_sample = (prev_sample * (0x100 - lerp_factor)) >> 8; - sample = (sample * lerp_factor) >> 8; - sample += prev_sample; - } - - sample = (sample * (int32_t)get_edd(channel)) >> 7; - - int32_t vol = get_volume(channel); - int32_t pan = get_pan(channel); - - int32_t pan_left, pan_right; - if (pan < 0x40) - { - pan_left = 0x7f * vol; - pan_right = pan * 2 * vol; - } - else - { - pan_left = (0x7f - pan) * 2 * vol; - pan_right = 0x7f * vol; - } - - left_total += ((int16_t)sample * (int16_t)pan_left) >> 14; - right_total += ((int16_t)sample * (int16_t)pan_right) >> 14; - - const uint16_t mask = (1 << channel); - if (m_audio_ctrl_regs[AUDIO_ENV_RAMP_DOWN] & mask) - { - if (m_rampdown_frame[channel] == 0) - { - LOGMASKED(LOG_RAMPDOWN, "Ticking rampdown for channel %d\n", channel); - audio_rampdown_tick(channel); - } - m_rampdown_frame[channel]--; - } - else if (!(m_audio_ctrl_regs[AUDIO_CHANNEL_ENV_MODE] & mask)) - { - if (m_envclk_frame[channel] == 0) - { - LOGMASKED(LOG_ENVELOPES, "Ticking envelope for channel %d\n", channel); - audio_envelope_tick(channel); - m_envclk_frame[channel] = get_envclk_frame_count(channel); - } - m_envclk_frame[channel]--; - } - } - } - - switch (get_vol_sel()) - { - case 0: // 1/16 - left_total >>= 4; - right_total >>= 4; - break; - case 1: // 1/4 - case 2: // 1 - case 3: // 2 // Both x1 and x2 clip like mad even with only 6 voices. Hack it for now. - left_total >>= 2; - right_total >>= 2; - break; - } - *out_l++ = (left_total * (int16_t)m_audio_ctrl_regs[AUDIO_MAIN_VOLUME]) >> 7; - *out_r++ = (right_total * (int16_t)m_audio_ctrl_regs[AUDIO_MAIN_VOLUME]) >> 7; - } -} - -inline void spg2xx_audio_device::stop_channel(const uint32_t channel) -{ - // TODO: IRQs - m_audio_ctrl_regs[AUDIO_CHANNEL_ENABLE] &= ~(1 << channel); - m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] &= ~(1 << channel); - m_audio_regs[(channel << 4) | AUDIO_MODE] &= ~AUDIO_ADPCM_MASK; - m_audio_ctrl_regs[AUDIO_CHANNEL_TONE_RELEASE] &= ~(1 << channel); - m_audio_ctrl_regs[AUDIO_ENV_RAMP_DOWN] &= ~(1 << channel); -} - -bool spg2xx_audio_device::advance_channel(const uint32_t channel) -{ - m_channel_rate_accum[channel] += m_channel_rate[channel]; - uint32_t samples_to_advance = 0; - while (m_channel_rate_accum[channel] >= 70312.5) - { - m_channel_rate_accum[channel] -= 70312.5; - samples_to_advance++; - } - - if (!samples_to_advance) - return true; - - bool playing = true; - - for (uint32_t sample = 0; sample < samples_to_advance; sample++) - { - playing = fetch_sample(channel); - if (!playing) - break; - - if (get_adpcm_bit(channel)) - { - // ADPCM mode - m_sample_shift[channel] += 4; - if (m_sample_shift[channel] >= 16) - { - m_sample_shift[channel] = 0; - m_sample_addr[channel]++; - } - } - else if (get_16bit_bit(channel)) - { - // 16-bit mode - m_sample_addr[channel]++; - } - else - { - // 8-bit mode - m_sample_shift[channel] += 8; - if (m_sample_shift[channel] >= 16) - { - m_sample_shift[channel] = 0; - m_sample_addr[channel]++; - } - } - } - - return playing; -} - -uint16_t spg2xx_audio_device::read_space(offs_t offset) -{ - return m_space_read_cb(offset); -} - -bool spg2xx_audio_device::fetch_sample(const uint32_t channel) -{ - const uint32_t channel_mask = channel << 4; - m_audio_regs[channel_mask | AUDIO_WAVE_DATA_PREV] = m_audio_regs[channel_mask | AUDIO_WAVE_DATA]; - - const uint32_t wave_data_reg = channel_mask | AUDIO_WAVE_DATA; - const uint16_t tone_mode = get_tone_mode(channel); - uint16_t raw_sample = tone_mode ? read_space(m_sample_addr[channel]) : m_audio_regs[wave_data_reg]; - - LOGMASKED(LOG_SAMPLES, "Channel %d: Raw sample %04x\n", channel, raw_sample); - - if (get_adpcm_bit(channel)) - { - // ADPCM mode - if (tone_mode != 0 && raw_sample == 0xffff) - { - if (tone_mode == AUDIO_TONE_MODE_HW_ONESHOT) - { - LOGMASKED(LOG_SAMPLES, "ADPCM stopped after %d samples\n", m_sample_count[channel]); - m_sample_count[channel] = 0; - stop_channel(channel); - return false; - } - else - { - LOGMASKED(LOG_SAMPLES, "ADPCM looping after %d samples\n", m_sample_count[channel]); - m_sample_count[channel] = 0; - loop_channel(channel); - m_audio_regs[(channel << 4) | AUDIO_MODE] &= ~AUDIO_ADPCM_MASK; - } - } - else - { - m_audio_regs[wave_data_reg] = raw_sample; - m_audio_regs[wave_data_reg] >>= m_sample_shift[channel]; - const uint8_t adpcm_sample = (uint8_t)(m_audio_regs[wave_data_reg] & 0x000f); - m_audio_regs[wave_data_reg] = (uint16_t)(m_adpcm[channel].clock(adpcm_sample) << 4) ^ 0x8000; - } - m_sample_count[channel]++; - } - else if (get_16bit_bit(channel)) - { - // 16-bit mode - if (tone_mode != 0 && raw_sample == 0xffff) - { - if (tone_mode == AUDIO_TONE_MODE_HW_ONESHOT) - { - LOGMASKED(LOG_SAMPLES, "16-bit PCM stopped after %d samples\n", m_sample_count[channel]); - m_sample_count[channel] = 0; - stop_channel(channel); - return false; - } - else - { - LOGMASKED(LOG_SAMPLES, "16-bit PCM looping after %d samples\n", m_sample_count[channel]); - m_sample_count[channel] = 0; - loop_channel(channel); - } - } - else - { - m_audio_regs[wave_data_reg] = raw_sample; - } - m_sample_count[channel]++; - } - else - { - // 8-bit mode - LOGMASKED(LOG_SAMPLES, "Channel %d: Processing as 8-bit sample, tone_mode is %d, sample_shift is %d\n", channel, tone_mode, m_sample_shift[channel]); - if (tone_mode != 0) - { - if (m_sample_shift[channel]) - raw_sample &= 0xff00; - else - raw_sample <<= 8; - raw_sample |= raw_sample >> 8; - - if (raw_sample == 0xffff) - { - if (tone_mode == AUDIO_TONE_MODE_HW_ONESHOT) - { - LOGMASKED(LOG_SAMPLES, "Channel %d: 8-bit PCM stopped after %d samples\n", channel, m_sample_count[channel]); - m_sample_count[channel] = 0; - stop_channel(channel); - return false; - } - else - { - LOGMASKED(LOG_SAMPLES, "Channel %d: 8-bit PCM looping after %d samples\n", channel, m_sample_count[channel]); - m_sample_count[channel] = 0; - loop_channel(channel); - } - } - else - { - m_audio_regs[wave_data_reg] = raw_sample; - } - } - m_sample_count[channel]++; - } - - return true; -} - -inline void spg2xx_audio_device::loop_channel(const uint32_t channel) -{ - m_sample_addr[channel] = get_loop_addr(channel); - m_sample_shift[channel] = 0; - LOGMASKED(LOG_SAMPLES, "Channel %d: Looping to address %08x\n", channel, m_sample_addr[channel]); -} - -void spg2xx_audio_device::audio_beat_tick() -{ - if (m_audio_curr_beat_base_count == 0) - { - LOGMASKED(LOG_BEAT, "Beat base count elapsed, reloading with %d\n", m_audio_ctrl_regs[AUDIO_BEAT_BASE_COUNT]); - m_audio_curr_beat_base_count = m_audio_ctrl_regs[AUDIO_BEAT_BASE_COUNT]; - - uint16_t beat_count = m_audio_ctrl_regs[AUDIO_BEAT_COUNT] & AUDIO_BEAT_COUNT_MASK; - if (beat_count == 0) - { - if (m_audio_ctrl_regs[AUDIO_BEAT_COUNT] & AUDIO_BIE_MASK) - { - LOGMASKED(LOG_BEAT, "Beat count elapsed, setting Status bit and checking IRQs\n"); - m_audio_ctrl_regs[AUDIO_BEAT_COUNT] |= AUDIO_BIS_MASK; - check_irqs(AUDIO_BIS_MASK); - } - else - { - LOGMASKED(LOG_BEAT, "Beat count elapsed but IRQ not enabled\n"); - } - } - else - { - beat_count--; - m_audio_ctrl_regs[AUDIO_BEAT_COUNT] = (m_audio_ctrl_regs[AUDIO_BEAT_COUNT] & ~AUDIO_BEAT_COUNT_MASK) | beat_count; - } - } - m_audio_curr_beat_base_count--; -} - -void spg2xx_audio_device::audio_rampdown_tick(const uint32_t channel) -{ - const uint8_t old_edd = get_edd(channel); - uint8_t new_edd = old_edd - get_rampdown_offset(channel); - if (new_edd > old_edd) - new_edd = 0; - - if (new_edd) - { - LOGMASKED(LOG_RAMPDOWN, "Channel %d preparing for next rampdown step (%02x)\n", channel, new_edd); - const uint16_t channel_mask = channel << 4; - m_audio_regs[channel_mask | AUDIO_ENVELOPE_DATA] &= ~AUDIO_EDD_MASK; - m_audio_regs[channel_mask | AUDIO_ENVELOPE_DATA] |= new_edd & AUDIO_EDD_MASK; - m_rampdown_frame[channel] = get_rampdown_frame_count(channel); - } - else - { - LOGMASKED(LOG_RAMPDOWN, "Stopping channel %d due to rampdown\n", channel); - const uint16_t channel_mask = 1 << channel; - m_audio_ctrl_regs[AUDIO_CHANNEL_ENABLE] &= ~channel_mask; - m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] &= ~channel_mask; - m_audio_ctrl_regs[AUDIO_CHANNEL_STOP] |= channel_mask; - m_audio_ctrl_regs[AUDIO_ENV_RAMP_DOWN] &= ~channel_mask; - m_audio_ctrl_regs[AUDIO_CHANNEL_TONE_RELEASE] &= ~channel_mask; - } -} - -const uint32_t spg2xx_audio_device::s_rampdown_frame_counts[8] = -{ - 13*4, 13*16, 13*64, 13*256, 13*1024, 13*4096, 13*8192, 13*8192 -}; - -uint32_t spg2xx_audio_device::get_rampdown_frame_count(const uint32_t channel) -{ - return s_rampdown_frame_counts[get_rampdown_clock(channel)]; -} - -const uint32_t spg2xx_audio_device::s_envclk_frame_counts[16] = -{ - 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 8192, 8192, 8192, 8192 -}; - -uint32_t spg2xx_audio_device::get_envclk_frame_count(const uint32_t channel) -{ - return s_envclk_frame_counts[get_envelope_clock(channel)]; -} - -uint32_t spg2xx_audio_device::get_envelope_clock(const offs_t channel) const -{ - if (channel < 4) - return (m_audio_ctrl_regs[AUDIO_ENVCLK0] >> (channel << 2)) & 0x000f; - else if (channel < 8) - return (m_audio_ctrl_regs[AUDIO_ENVCLK0_HIGH] >> ((channel - 4) << 2)) & 0x000f; - else if (channel < 12) - return (m_audio_ctrl_regs[AUDIO_ENVCLK1] >> ((channel - 8) << 2)) & 0x000f; - else - return (m_audio_ctrl_regs[AUDIO_ENVCLK1_HIGH] >> ((channel - 12) << 2)) & 0x000f; -} - -bool spg2xx_audio_device::audio_envelope_tick(const uint32_t channel) -{ - const uint16_t channel_mask = channel << 4; - uint16_t new_count = get_envelope_count(channel); - const uint16_t curr_edd = get_edd(channel); - LOGMASKED(LOG_ENVELOPES, "envelope %d tick, count is %04x, curr edd is %04x\n", channel, new_count, curr_edd); - bool edd_changed = false; - if (new_count == 0) - { - const uint16_t target = get_envelope_target(channel); - uint16_t new_edd = curr_edd; - const uint16_t inc = get_envelope_inc(channel); - - if (new_edd != target) - { - if (get_envelope_sign_bit(channel)) - { - new_edd -= inc; - LOGMASKED(LOG_ENVELOPES, "Envelope %d new EDD-: %04x (%04x), dec %04x\n", channel, new_edd, target, inc); - if (new_edd > curr_edd) - new_edd = 0; - else if (new_edd < target) - new_edd = target; - - if (new_edd == 0) - { - LOGMASKED(LOG_ENVELOPES, "Envelope %d at 0, stopping channel\n", channel); - stop_channel(channel); - return true; - } - } - else - { - new_edd += inc; - LOGMASKED(LOG_ENVELOPES, "Envelope %d new EDD+: %04x (%04x), inc %04x\n", channel, new_edd, target, inc); - if (new_edd >= target) - new_edd = target; - } - } - - if (new_edd == target) - { - LOGMASKED(LOG_ENVELOPES, "Envelope %d at target %04x\n", channel, target); - new_edd = target; - - if (get_envelope_repeat_bit(channel)) - { - const uint16_t repeat_count = get_envelope_repeat_count(channel) - 1; - LOGMASKED(LOG_ENVELOPES, "Repeating envelope, new repeat count %d\n", repeat_count); - if (repeat_count == 0) - { - m_audio_regs[channel_mask | AUDIO_ENVELOPE0] = read_space(m_envelope_addr[channel]); - m_audio_regs[channel_mask | AUDIO_ENVELOPE1] = read_space(m_envelope_addr[channel] + 1); - m_audio_regs[channel_mask | AUDIO_ENVELOPE_LOOP_CTRL] = read_space(m_envelope_addr[channel] + 2); - m_envelope_addr[channel] = get_envelope_addr(channel) + get_envelope_eaoffset(channel); - LOGMASKED(LOG_ENVELOPES, "Envelope data after repeat: %04x %04x %04x (%08x)\n", m_audio_regs[channel_mask | AUDIO_ENVELOPE0], m_audio_regs[channel_mask | AUDIO_ENVELOPE1], m_audio_regs[channel_mask | AUDIO_ENVELOPE_LOOP_CTRL], m_envelope_addr[channel]); - } - else - { - set_envelope_repeat_count(channel, repeat_count); - } - } - else - { - LOGMASKED(LOG_ENVELOPES, "Fetching envelope for channel %d from %08x\n", channel, m_envelope_addr[channel]); - m_audio_regs[channel_mask | AUDIO_ENVELOPE0] = read_space(m_envelope_addr[channel]); - m_audio_regs[channel_mask | AUDIO_ENVELOPE1] = read_space(m_envelope_addr[channel] + 1); - LOGMASKED(LOG_ENVELOPES, "Fetched envelopes %04x %04x\n", m_audio_regs[channel_mask | AUDIO_ENVELOPE0], m_audio_regs[channel_mask | AUDIO_ENVELOPE1]); - m_envelope_addr[channel] += 2; - } - new_count = get_envelope_load(channel); - set_envelope_count(channel, new_count); - } - else - { - LOGMASKED(LOG_ENVELOPES, "Envelope %d not yet at target %04x (%04x)\n", channel, target, new_edd); - new_count = get_envelope_load(channel); - set_envelope_count(channel, new_count); - } - LOGMASKED(LOG_ENVELOPES, "Envelope %d new count %04x\n", channel, new_count); - - set_edd(channel, new_edd); - edd_changed = true; - LOGMASKED(LOG_ENVELOPES, "Setting channel %d edd to %04x, register is %04x\n", channel, new_edd, m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA]); - } - else - { - new_count--; - set_envelope_count(channel, new_count); - } - LOGMASKED(LOG_ENVELOPES, "envelope %d post-tick, count is now %04x, register is %04x\n", channel, new_count, m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA]); - return edd_changed; -} diff --git a/src/devices/machine/spg2xx_audio.h b/src/devices/machine/spg2xx_audio.h deleted file mode 100644 index 22f5108e405..00000000000 --- a/src/devices/machine/spg2xx_audio.h +++ /dev/null @@ -1,372 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/***************************************************************************** - - SunPlus SPG2xx-series SoC peripheral emulation (Audio) - -**********************************************************************/ - -#ifndef MAME_MACHINE_SPG2XX_AUDIO_H -#define MAME_MACHINE_SPG2XX_AUDIO_H - -#pragma once - -#include "sound/okiadpcm.h" -#include "cpu/unsp/unsp.h" - -class spg2xx_audio_device : public device_t, public device_sound_interface -{ -public: - spg2xx_audio_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - spg2xx_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - auto space_read_callback() { return m_space_read_cb.bind(); } - auto write_irq_callback() { return m_irq_cb.bind(); } - - DECLARE_READ16_MEMBER(audio_r); - DECLARE_WRITE16_MEMBER(audio_w); - DECLARE_READ16_MEMBER(audio_ctrl_r); - DECLARE_WRITE16_MEMBER(audio_ctrl_w); - DECLARE_READ16_MEMBER(audio_phase_r); - DECLARE_WRITE16_MEMBER(audio_phase_w); - -protected: - // sound stream update overrides - virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override; - - void audio_beat_tick(); - void audio_rampdown_tick(const uint32_t channel); - bool audio_envelope_tick(const uint32_t channel); - inline uint32_t get_rampdown_frame_count(const uint32_t channel); - inline uint32_t get_envclk_frame_count(const uint32_t channel); - - // Audio getters - bool get_channel_enable(const offs_t channel) const { return m_audio_ctrl_regs[AUDIO_CHANNEL_ENABLE] & (1 << channel); } - bool get_channel_status(const offs_t channel) const { return m_audio_ctrl_regs[AUDIO_CHANNEL_STATUS] & (1 << channel); } - bool get_manual_envelope_enable(const offs_t channel) const { return m_audio_ctrl_regs[AUDIO_CHANNEL_ENV_MODE] & (1 << channel); } - bool get_auto_envelope_enable(const offs_t channel) const { return !get_manual_envelope_enable(channel); } - uint32_t get_envelope_clock(const offs_t channel) const; - uint16_t get_vol_sel() const { return (m_audio_ctrl_regs[AUDIO_CONTROL] & AUDIO_CONTROL_VOLSEL_MASK) >> AUDIO_CONTROL_VOLSEL_SHIFT; } - - // Audio Mode getters - uint16_t get_wave_addr_high(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_WADDR_HIGH_MASK; } - uint16_t get_loop_addr_high(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_LADDR_HIGH_MASK) >> AUDIO_LADDR_HIGH_SHIFT; } - uint16_t get_tone_mode(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_TONE_MODE_MASK) >> AUDIO_TONE_MODE_SHIFT; } - uint16_t get_16bit_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_16M_MASK) ? 1 : 0; } - uint16_t get_adpcm_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_MODE] & AUDIO_ADPCM_MASK) ? 1 : 0; } - - // Audio Pan getters - uint16_t get_volume(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_PAN_VOL] & AUDIO_VOLUME_MASK; } - uint16_t get_pan(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_PAN_VOL] & AUDIO_PAN_MASK) >> AUDIO_PAN_SHIFT; } - - // Audio Envelope0 Data getters - uint16_t get_envelope_inc(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_ENVELOPE0] & AUDIO_ENVELOPE_INC_MASK; } - uint16_t get_envelope_sign_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE0] & AUDIO_ENVELOPE_SIGN_MASK) ? 1 : 0; } - uint16_t get_envelope_target(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE0] & AUDIO_ENVELOPE_TARGET_MASK) >> AUDIO_ENVELOPE_TARGET_SHIFT; } - uint16_t get_repeat_period_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE0] & AUDIO_ENVELOPE_REPEAT_PERIOD_MASK) ? 1 : 0; } - - // Audio Envelope Data getters - uint16_t get_edd(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA] & AUDIO_EDD_MASK; } - uint16_t get_envelope_count(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA] & AUDIO_ENVELOPE_COUNT_MASK) >> AUDIO_ENVELOPE_COUNT_SHIFT; } - void set_edd(const offs_t channel, uint8_t edd) { m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA] = (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA] & ~AUDIO_EDD_MASK) | edd; } - void set_envelope_count(const offs_t channel, uint16_t count) { m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA] = get_edd(channel) | (count << AUDIO_ENVELOPE_COUNT_SHIFT); } - - // Audio Envelope1 Data getters - uint16_t get_envelope_load(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_ENVELOPE1] & AUDIO_ENVELOPE_LOAD_MASK; } - uint16_t get_envelope_repeat_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE1] & AUDIO_ENVELOPE_RPT_MASK) ? 1 : 0; } - uint16_t get_envelope_repeat_count(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE1] & AUDIO_ENVELOPE_RPCNT_MASK) >> AUDIO_ENVELOPE_RPCNT_SHIFT; } - inline void set_envelope_repeat_count(const offs_t channel, const uint16_t count) { m_audio_regs[(channel << 4) | AUDIO_ENVELOPE1] = (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE1] & ~AUDIO_ENVELOPE_RPCNT_MASK) | ((count << AUDIO_ENVELOPE_RPCNT_SHIFT) & AUDIO_ENVELOPE_RPCNT_MASK); } - - // Audio Envelope Address getters - uint16_t get_envelope_addr_high(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_ADDR_HIGH] & AUDIO_EADDR_HIGH_MASK; } - uint16_t get_audio_irq_enable_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_ADDR_HIGH] & AUDIO_IRQ_EN_MASK) ? 1 : 0; } - uint16_t get_audio_irq_addr(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_ADDR_HIGH] & AUDIO_IRQ_ADDR_MASK) >> AUDIO_IRQ_ADDR_SHIFT; } - - // Audio Envelope Loop getters - uint16_t get_envelope_eaoffset(const offs_t channel) const { return m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_LOOP_CTRL] & AUDIO_EAOFFSET_MASK; } - uint16_t get_rampdown_offset(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_LOOP_CTRL] & AUDIO_RAMPDOWN_OFFSET_MASK) >> AUDIO_RAMPDOWN_OFFSET_SHIFT; } - void set_envelope_eaoffset(const offs_t channel, uint16_t eaoffset) { m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_LOOP_CTRL] = (m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_LOOP_CTRL] & ~AUDIO_RAMPDOWN_OFFSET_MASK) | (eaoffset & AUDIO_EAOFFSET_MASK); } - - // Audio ADPCM getters - uint16_t get_point_number(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ADPCM_SEL] & AUDIO_POINT_NUMBER_MASK) >> AUDIO_POINT_NUMBER_SHIFT; } - uint16_t get_adpcm36_bit(const offs_t channel) const { return (m_audio_regs[(channel << 4) | AUDIO_ADPCM_SEL] & AUDIO_ADPCM36_MASK) ? 1 : 0; } - - // Audio high-word getters - uint16_t get_phase_high(const offs_t channel) const { return m_audio_phase_regs[(channel << 4) | AUDIO_PHASE_HIGH] & AUDIO_PHASE_HIGH_MASK; } - uint16_t get_phase_accum_high(const offs_t channel) const { return m_audio_phase_regs[(channel << 4) | AUDIO_PHASE_ACCUM_HIGH] & AUDIO_PHASE_ACCUM_HIGH_MASK; } - uint16_t get_target_phase_high(const offs_t channel) const { return m_audio_phase_regs[(channel << 4) | AUDIO_TARGET_PHASE_HIGH] & AUDIO_TARGET_PHASE_HIGH_MASK; } - uint16_t get_rampdown_clock(const offs_t channel) const { return m_audio_phase_regs[(channel << 4) | AUDIO_RAMP_DOWN_CLOCK] & AUDIO_RAMP_DOWN_CLOCK_MASK; } - - // Audio ADPCM getters - uint16_t get_phase_offset(const offs_t channel) const { return m_audio_phase_regs[(channel << 4) | AUDIO_PHASE_CTRL] & AUDIO_PHASE_OFFSET_MASK; } - uint16_t get_phase_sign_bit(const offs_t channel) const { return (m_audio_phase_regs[(channel << 4) | AUDIO_PHASE_CTRL] & AUDIO_PHASE_SIGN_MASK) >> AUDIO_PHASE_SIGN_SHIFT; } - uint16_t get_phase_time_step(const offs_t channel) const { return (m_audio_phase_regs[(channel << 4) | AUDIO_PHASE_CTRL] & AUDIO_PHASE_TIME_STEP_MASK) >> AUDIO_PHASE_TIME_STEP_SHIFT; } - - // Audio combined getters - uint32_t get_phase(const offs_t channel) const { return ((uint32_t)get_phase_high(channel) << 16) | m_audio_phase_regs[(channel << 4) | AUDIO_PHASE]; } - uint32_t get_phase_accum(const offs_t channel) const { return ((uint32_t)get_phase_accum_high(channel) << 16) | m_audio_phase_regs[(channel << 4) | AUDIO_PHASE_ACCUM]; } - uint32_t get_target_phase(const offs_t channel) const { return ((uint32_t)get_target_phase_high(channel) << 16) | m_audio_phase_regs[(channel << 4) | AUDIO_TARGET_PHASE]; } - - uint32_t get_wave_addr(const offs_t channel) const { return ((uint32_t)get_wave_addr_high(channel) << 16) | m_audio_regs[(channel << 4) | AUDIO_WAVE_ADDR]; } - uint32_t get_loop_addr(const offs_t channel) const { return ((uint32_t)get_loop_addr_high(channel) << 16) | m_audio_regs[(channel << 4) | AUDIO_LOOP_ADDR]; } - uint32_t get_envelope_addr(const offs_t channel) const { return ((uint32_t)get_envelope_addr_high(channel) << 16) | m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_ADDR]; } - - enum // at audio write offset 0x000 in spg2xx - { - AUDIO_WAVE_ADDR = 0x000, - - AUDIO_MODE = 0x001, - AUDIO_WADDR_HIGH_MASK = 0x003f, - AUDIO_LADDR_HIGH_MASK = 0x0fc0, - AUDIO_LADDR_HIGH_SHIFT = 6, - AUDIO_TONE_MODE_MASK = 0x3000, - AUDIO_TONE_MODE_SHIFT = 12, - AUDIO_TONE_MODE_SW = 0, - AUDIO_TONE_MODE_HW_ONESHOT = 1, - AUDIO_TONE_MODE_HW_LOOP = 2, - AUDIO_16M_MASK = 0x4000, - AUDIO_ADPCM_MASK = 0x8000, - - AUDIO_LOOP_ADDR = 0x002, - - AUDIO_PAN_VOL = 0x003, - AUDIO_PAN_VOL_MASK = 0x7f7f, - AUDIO_VOLUME_MASK = 0x007f, - AUDIO_PAN_MASK = 0x7f00, - AUDIO_PAN_SHIFT = 8, - - AUDIO_ENVELOPE0 = 0x004, - AUDIO_ENVELOPE_INC_MASK = 0x007f, - AUDIO_ENVELOPE_SIGN_MASK = 0x0080, - AUDIO_ENVELOPE_TARGET_MASK = 0x7f00, - AUDIO_ENVELOPE_TARGET_SHIFT = 8, - AUDIO_ENVELOPE_REPEAT_PERIOD_MASK = 0x8000, - - AUDIO_ENVELOPE_DATA = 0x005, - AUDIO_ENVELOPE_DATA_MASK = 0xff7f, - AUDIO_EDD_MASK = 0x007f, - AUDIO_ENVELOPE_COUNT_MASK = 0xff00, - AUDIO_ENVELOPE_COUNT_SHIFT = 8, - - AUDIO_ENVELOPE1 = 0x006, - AUDIO_ENVELOPE_LOAD_MASK = 0x00ff, - AUDIO_ENVELOPE_RPT_MASK = 0x0100, - AUDIO_ENVELOPE_RPCNT_MASK = 0xfe00, - AUDIO_ENVELOPE_RPCNT_SHIFT = 9, - - AUDIO_ENVELOPE_ADDR_HIGH = 0x007, - AUDIO_EADDR_HIGH_MASK = 0x003f, - AUDIO_IRQ_EN_MASK = 0x0040, - AUDIO_IRQ_ADDR_MASK = 0xff80, - AUDIO_IRQ_ADDR_SHIFT = 7, - - AUDIO_ENVELOPE_ADDR = 0x008, - AUDIO_WAVE_DATA_PREV = 0x009, - - AUDIO_ENVELOPE_LOOP_CTRL = 0x00a, - AUDIO_EAOFFSET_MASK = 0x01ff, - AUDIO_RAMPDOWN_OFFSET_MASK = 0xfe00, - AUDIO_RAMPDOWN_OFFSET_SHIFT = 9, - - AUDIO_WAVE_DATA = 0x00b, - - AUDIO_ADPCM_SEL = 0x00d, - AUDIO_ADPCM_SEL_MASK = 0xfe00, - AUDIO_POINT_NUMBER_MASK = 0x7e00, - AUDIO_POINT_NUMBER_SHIFT = 9, - AUDIO_ADPCM36_MASK = 0x8000, - }; - - enum // at audio write offset 0x200 in spg2xx - { - AUDIO_PHASE_HIGH = 0x000, - AUDIO_PHASE_HIGH_MASK = 0x0007, - - AUDIO_PHASE_ACCUM_HIGH = 0x001, - AUDIO_PHASE_ACCUM_HIGH_MASK = 0x0007, - - AUDIO_TARGET_PHASE_HIGH = 0x002, - AUDIO_TARGET_PHASE_HIGH_MASK= 0x0007, - - AUDIO_RAMP_DOWN_CLOCK = 0x003, - AUDIO_RAMP_DOWN_CLOCK_MASK = 0x0007, - - AUDIO_PHASE = 0x004, - AUDIO_PHASE_ACCUM = 0x005, - AUDIO_TARGET_PHASE = 0x006, - - AUDIO_PHASE_CTRL = 0x007, - AUDIO_PHASE_OFFSET_MASK = 0x0fff, - AUDIO_PHASE_SIGN_MASK = 0x1000, - AUDIO_PHASE_SIGN_SHIFT = 12, - AUDIO_PHASE_TIME_STEP_MASK = 0xe000, - AUDIO_PHASE_TIME_STEP_SHIFT = 13, - - AUDIO_CHAN_OFFSET_MASK = 0xf0f, - }; - - enum // at audio write offset 0x400 in spg2xx - { - - AUDIO_CHANNEL_ENABLE = 0x000, - AUDIO_CHANNEL_ENABLE_MASK = 0xffff, - - AUDIO_MAIN_VOLUME = 0x001, - AUDIO_MAIN_VOLUME_MASK = 0x007f, - - AUDIO_CHANNEL_FIQ_ENABLE = 0x002, - AUDIO_CHANNEL_FIQ_ENABLE_MASK = 0xffff, - - AUDIO_CHANNEL_FIQ_STATUS = 0x003, - AUDIO_CHANNEL_FIQ_STATUS_MASK = 0xffff, - - AUDIO_BEAT_BASE_COUNT = 0x004, - AUDIO_BEAT_BASE_COUNT_MASK = 0x07ff, - - AUDIO_BEAT_COUNT = 0x005, - AUDIO_BEAT_COUNT_MASK = 0x3fff, - AUDIO_BIS_MASK = 0x4000, - AUDIO_BIE_MASK = 0x8000, - - AUDIO_ENVCLK0 = 0x006, - - AUDIO_ENVCLK0_HIGH = 0x007, - AUDIO_ENVCLK0_HIGH_MASK = 0xffff, - - AUDIO_ENVCLK1 = 0x008, - - AUDIO_ENVCLK1_HIGH = 0x009, - AUDIO_ENVCLK1_HIGH_MASK = 0xffff, - - AUDIO_ENV_RAMP_DOWN = 0x00a, - AUDIO_ENV_RAMP_DOWN_MASK = 0xffff, - - AUDIO_CHANNEL_STOP = 0x00b, - AUDIO_CHANNEL_STOP_MASK = 0xffff, - - AUDIO_CHANNEL_ZERO_CROSS = 0x00c, - AUDIO_CHANNEL_ZERO_CROSS_MASK = 0xffff, - - AUDIO_CONTROL = 0x00d, - AUDIO_CONTROL_MASK = 0x9fe8, - AUDIO_CONTROL_SATURATE_MASK = 0x8000, - AUDIO_CONTROL_SOFTCH_MASK = 0x1000, - AUDIO_CONTROL_COMPEN_MASK = 0x0800, - AUDIO_CONTROL_NOHIGH_MASK = 0x0400, - AUDIO_CONTROL_NOINT_MASK = 0x0200, - AUDIO_CONTROL_EQEN_MASK = 0x0100, - AUDIO_CONTROL_VOLSEL_MASK = 0x00c0, - AUDIO_CONTROL_VOLSEL_SHIFT = 6, - AUDIO_CONTROL_FOF_MASK = 0x0020, - AUDIO_CONTROL_INIT_MASK = 0x0008, - - AUDIO_COMPRESS_CTRL = 0x00e, - AUDIO_COMPRESS_CTRL_PEAK_MASK = 0x8000, - AUDIO_COMPRESS_CTRL_THRESHOLD_MASK = 0x7f00, - AUDIO_COMPRESS_CTRL_THRESHOLD_SHIFT = 8, - AUDIO_COMPRESS_CTRL_ATTSCALE_MASK = 0x00c0, - AUDIO_COMPRESS_CTRL_ATTSCALE_SHIFT = 6, - AUDIO_COMPRESS_CTRL_RELSCALE_MASK = 0x0030, - AUDIO_COMPRESS_CTRL_RELSCALE_SHIFT = 4, - AUDIO_COMPRESS_CTRL_DISZC_MASK = 0x0008, - AUDIO_COMPRESS_CTRL_RATIO_MASK = 0x0007, - - AUDIO_CHANNEL_STATUS = 0x00f, - AUDIO_CHANNEL_STATUS_MASK = 0xffff, - - AUDIO_WAVE_IN_L = 0x010, - - AUDIO_WAVE_IN_R = 0x011, - AUDIO_SOFTIRQ_MASK = 0x8000, - AUDIO_SOFTIRQ_EN_MASK = 0x4000, - AUDIO_SOFT_PHASE_HIGH_MASK = 0x0070, - AUDIO_SOFT_PHASE_HIGH_SHIFT = 4, - AUDIO_FIFO_IRQ_THRESHOLD_MASK = 0x000f, - - AUDIO_WAVE_OUT_L = 0x012, - AUDIO_WAVE_OUT_R = 0x013, - - AUDIO_CHANNEL_REPEAT = 0x014, - AUDIO_CHANNEL_REPEAT_MASK = 0xffff, - - AUDIO_CHANNEL_ENV_MODE = 0x015, - AUDIO_CHANNEL_ENV_MODE_MASK = 0xffff, - - AUDIO_CHANNEL_TONE_RELEASE = 0x016, - AUDIO_CHANNEL_TONE_RELEASE_MASK = 0xffff, - - AUDIO_CHANNEL_ENV_IRQ = 0x017, - AUDIO_CHANNEL_ENV_IRQ_MASK = 0xffff, - - AUDIO_CHANNEL_PITCH_BEND = 0x018, - AUDIO_CHANNEL_PITCH_BEND_MASK = 0xffff, - - AUDIO_SOFT_PHASE = 0x019, - - AUDIO_ATTACK_RELEASE = 0x01a, - AUDIO_RELEASE_TIME_MASK = 0x00ff, - AUDIO_ATTACK_TIME_MASK = 0xff00, - AUDIO_ATTACK_TIME_SHIFT = 8, - - AUDIO_EQ_CUTOFF10 = 0x01b, - AUDIO_EQ_CUTOFF10_MASK = 0x7f7f, - - AUDIO_EQ_CUTOFF32 = 0x01c, - AUDIO_EQ_CUTOFF32_MASK = 0x7f7f, - - AUDIO_EQ_GAIN10 = 0x01d, - AUDIO_EQ_GAIN10_MASK = 0x7f7f, - - AUDIO_EQ_GAIN32 = 0x01e, - AUDIO_EQ_GAIN32_MASK = 0x7f7f - }; - - static const device_timer_id TIMER_BEAT = 3; - void check_irqs(const uint16_t changed); - - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - - uint16_t read_space(offs_t offset); - - void stop_channel(const uint32_t channel); - bool advance_channel(const uint32_t channel); - bool fetch_sample(const uint32_t channel); - void loop_channel(const uint32_t channel); - - - bool m_debug_samples; - bool m_debug_rates; - - uint16_t m_audio_regs[0x200]; - uint16_t m_audio_phase_regs[0x200]; - uint16_t m_audio_ctrl_regs[0x400]; - uint8_t m_sample_shift[16]; - uint32_t m_sample_count[16]; - uint32_t m_sample_addr[16]; - double m_channel_rate[16]; - double m_channel_rate_accum[16]; - uint32_t m_rampdown_frame[16]; - uint32_t m_envclk_frame[16]; - uint32_t m_envelope_addr[16]; - int m_channel_debug; - uint16_t m_audio_curr_beat_base_count; - - emu_timer *m_audio_beat; - - sound_stream *m_stream; - oki_adpcm_state m_adpcm[16]; - - static const uint32_t s_rampdown_frame_counts[8]; - static const uint32_t s_envclk_frame_counts[16]; - -private: - devcb_read16 m_space_read_cb; - devcb_write_line m_irq_cb; - -}; - -DECLARE_DEVICE_TYPE(SPG2XX_AUDIO, spg2xx_audio_device) - -#endif // MAME_MACHINE_SPG2XX_AUDIO_H diff --git a/src/devices/machine/spg2xx_io.cpp b/src/devices/machine/spg2xx_io.cpp deleted file mode 100644 index 404087f6a7f..00000000000 --- a/src/devices/machine/spg2xx_io.cpp +++ /dev/null @@ -1,1313 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz - -/* this is used by the SPG110, SPG24x and SPG28x - basic I/O behavior is definitely the same on the SPG110 but - the rest needs verifying */ - -#include "emu.h" -#include "spg2xx_io.h" - -DEFINE_DEVICE_TYPE(SPG24X_IO, spg24x_io_device, "spg24x_io", "SPG240-series System-on-a-Chip I/O") -DEFINE_DEVICE_TYPE(SPG28X_IO, spg28x_io_device, "spg28x_io", "SPG280-series System-on-a-Chip I/O") - -#define LOG_IO_READS (1U << 1) -#define LOG_IO_WRITES (1U << 2) -#define LOG_UNKNOWN_IO (1U << 3) -#define LOG_IRQS (1U << 4) -#define LOG_VLINES (1U << 5) -#define LOG_GPIO (1U << 6) -#define LOG_UART (1U << 7) -#define LOG_I2C (1U << 8) -#define LOG_SEGMENT (1U << 10) -#define LOG_WATCHDOG (1U << 11) -#define LOG_TIMERS (1U << 12) -#define LOG_FIQ (1U << 25) -#define LOG_SIO (1U << 26) -#define LOG_EXT_MEM (1U << 27) -#define LOG_EXTINT (1U << 28) -#define LOG_IO (LOG_IO_READS | LOG_IO_WRITES | LOG_IRQS | LOG_GPIO | LOG_UART | LOG_I2C | LOG_TIMERS | LOG_EXTINT | LOG_UNKNOWN_IO) -#define LOG_ALL (LOG_IO | LOG_VLINES | LOG_SEGMENT | LOG_FIQ) - -#define VERBOSE (0) -#include "logmacro.h" - - -#define IO_IRQ_ENABLE m_io_regs[0x21] -#define IO_IRQ_STATUS m_io_regs[0x22] - -spg2xx_io_device::spg2xx_io_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock) - , m_porta_out(*this) - , m_portb_out(*this) - , m_portc_out(*this) - , m_porta_in(*this) - , m_portb_in(*this) - , m_portc_in(*this) - , m_adc_in{{*this}, {*this}} - , m_eeprom_w(*this) - , m_eeprom_r(*this) - , m_uart_tx(*this) - , m_chip_sel(*this) - , m_cpu(*this, finder_base::DUMMY_TAG) - , m_screen(*this, finder_base::DUMMY_TAG) - , m_pal_read_cb(*this) - , m_timer_irq_cb(*this) - , m_uart_adc_irq_cb(*this) - , m_external_irq_cb(*this) - , m_ffreq_tmr1_irq_cb(*this) - , m_ffreq_tmr2_irq_cb(*this) -{ -} - -spg24x_io_device::spg24x_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : spg2xx_io_device(mconfig, SPG24X_IO, tag, owner, clock, 256) -{ -} - -spg28x_io_device::spg28x_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : spg2xx_io_device(mconfig, SPG28X_IO, tag, owner, clock, 64) -{ -} - - -void spg2xx_io_device::device_start() -{ - m_porta_out.resolve_safe(); - m_portb_out.resolve_safe(); - m_portc_out.resolve_safe(); - m_porta_in.resolve_safe(0); - m_portb_in.resolve_safe(0); - m_portc_in.resolve_safe(0); - m_adc_in[0].resolve_safe(0x0fff); - m_adc_in[1].resolve_safe(0x0fff); - m_eeprom_w.resolve_safe(); - m_eeprom_r.resolve_safe(0); - m_uart_tx.resolve_safe(); - m_chip_sel.resolve_safe(); - m_pal_read_cb.resolve_safe(0); - - m_timer_irq_cb.resolve(); - m_uart_adc_irq_cb.resolve(); - m_external_irq_cb.resolve(); - m_ffreq_tmr1_irq_cb.resolve(); - m_ffreq_tmr2_irq_cb.resolve(); - - m_tmb1 = timer_alloc(TIMER_TMB1); - m_tmb2 = timer_alloc(TIMER_TMB2); - m_tmb1->adjust(attotime::never); - m_tmb2->adjust(attotime::never); - - m_uart_tx_timer = timer_alloc(TIMER_UART_TX); - m_uart_tx_timer->adjust(attotime::never); - - m_uart_rx_timer = timer_alloc(TIMER_UART_RX); - m_uart_rx_timer->adjust(attotime::never); - - m_4khz_timer = timer_alloc(TIMER_4KHZ); - m_4khz_timer->adjust(attotime::never); - - m_timer_src_ab = timer_alloc(TIMER_SRC_AB); - m_timer_src_ab->adjust(attotime::never); - - m_timer_src_c = timer_alloc(TIMER_SRC_C); - m_timer_src_c->adjust(attotime::never); - - save_item(NAME(m_timer_a_preload)); - save_item(NAME(m_timer_b_preload)); - save_item(NAME(m_timer_b_divisor)); - save_item(NAME(m_timer_b_tick_rate)); - - save_item(NAME(m_io_regs)); - - save_item(NAME(m_extint)); - - save_item(NAME(m_2khz_divider)); - save_item(NAME(m_1khz_divider)); - save_item(NAME(m_4hz_divider)); - - save_item(NAME(m_uart_baud_rate)); - -} - -void spg2xx_io_device::device_reset() -{ - memset(m_io_regs, 0, 0x100 * sizeof(uint16_t)); - - m_timer_a_preload = 0; - m_timer_b_preload = 0; - m_timer_b_divisor = 0; - m_timer_b_tick_rate = 0; - - m_io_regs[0x23] = 0x0028; - m_io_regs[0x2c] = 0x1418; - m_io_regs[0x2d] = 0x1658; - - m_uart_rx_available = false; - memset(m_uart_rx_fifo, 0, ARRAY_LENGTH(m_uart_rx_fifo)); - m_uart_rx_fifo_start = 0; - m_uart_rx_fifo_end = 0; - m_uart_rx_fifo_count = 0; - m_uart_tx_irq = false; - m_uart_rx_irq = false; - - memset(m_extint, 0, sizeof(bool) * 2); - - m_4khz_timer->adjust(attotime::from_hz(4096), 0, attotime::from_hz(4096)); - - m_2khz_divider = 0; - m_1khz_divider = 0; - m_4hz_divider = 0; -} - -/************************* -* Machine Hardware * -*************************/ - -void spg2xx_io_device::uart_rx(uint8_t data) -{ - LOGMASKED(LOG_UART, "uart_rx: Pulling %02x into receive FIFO\n", data); - if (BIT(m_io_regs[0x30], 6)) - { - m_uart_rx_fifo[m_uart_rx_fifo_end] = data; - m_uart_rx_fifo_end = (m_uart_rx_fifo_end + 1) % ARRAY_LENGTH(m_uart_rx_fifo); - m_uart_rx_fifo_count++; - if (m_uart_rx_timer->remaining() == attotime::never) - m_uart_rx_timer->adjust(attotime::from_ticks(BIT(m_io_regs[0x30], 5) ? 11 : 10, m_uart_baud_rate)); - } -} - -READ16_MEMBER(spg2xx_io_device::io_r) -{ - static const char *const gpioregs[] = { "GPIO Data Port", "GPIO Buffer Port", "GPIO Direction Port", "GPIO Attribute Port", "GPIO IRQ/Latch Port" }; - static const char gpioports[] = { 'A', 'B', 'C' }; - - uint16_t val = m_io_regs[offset]; - - switch (offset) - { - case 0x01: case 0x06: case 0x0b: // GPIO Data Port A/B/C - do_gpio(offset, false); - LOGMASKED(LOG_GPIO, "%s: io_r: %s %c = %04x\n", machine().describe_context(), gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], m_io_regs[offset]); - val = m_io_regs[offset]; - break; - - case 0x02: case 0x03: case 0x04: case 0x05: - case 0x07: case 0x08: case 0x09: case 0x0a: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: // Other GPIO regs - LOGMASKED(LOG_GPIO, "%s: io_r: %s %c = %04x\n", machine().describe_context(), gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], m_io_regs[offset]); - break; - - case 0x10: // Timebase Control - LOGMASKED(LOG_IO_READS, "io_r: Timebase Control = %04x\n", val); - break; - - case 0x12: // Timer A Data - LOGMASKED(LOG_IO_WRITES, "io_r: Timer A Data = %04x\n", val); - break; - - case 0x1c: // Video line counter - val = m_screen->vpos(); - LOGMASKED(LOG_VLINES, "io_r: Video Line = %04x\n", val); - break; - - case 0x20: // System Control - LOGMASKED(LOG_IO_READS, "io_r: System Control = %04x\n", val); - break; - - case 0x21: // IRQ Control - LOGMASKED(LOG_IRQS, "%s: io_r: I/O IRQ Control = %04x\n", machine().describe_context(), val); - break; - - case 0x22: // IRQ Status - LOGMASKED(LOG_IRQS, "%s: io_r: I/O IRQ Status = %04x\n", machine().describe_context(), val); - break; - - case 0x23: // External Memory Control - LOGMASKED(LOG_IO_READS, "%s: io_r: Ext. Memory Control = %04x\n", machine().describe_context(), val); - break; - - case 0x25: // ADC Control - LOGMASKED(LOG_IO_READS, "io_r: ADC Control = %04x\n", val); - break; - - case 0x27: // ADC Data - { - m_io_regs[0x27] = 0; - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS &= ~0x2000; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - check_irqs(changed); - LOGMASKED(LOG_IO_READS, "%s: io_r: ADC Data = %04x\n", machine().describe_context(), val); - break; - } - - case 0x29: // Wakeup Source - LOGMASKED(LOG_IO_READS, "io_r: Wakeup Source = %04x\n", val); - break; - - case 0x2b: - { - uint16_t pal = m_pal_read_cb(); - LOGMASKED(LOG_IO_READS, "io_r: NTSC/PAL = %04x\n", pal); - return pal; - } - - case 0x2c: // PRNG 0 - { - const uint16_t value = m_io_regs[0x2c]; - m_io_regs[0x2c] = ((value << 1) | (BIT(value, 14) ^ BIT(value, 13))) & 0x7fff; - return value; - } - - case 0x2d: // PRNG 1 - { - const uint16_t value = m_io_regs[0x2d]; - m_io_regs[0x2d] = ((value << 1) | (BIT(value, 14) ^ BIT(value, 13))) & 0x7fff; - return value; - } - - case 0x2e: // FIQ Source Select - LOGMASKED(LOG_FIQ, "io_r: FIQ Source Select = %04x\n", val); - break; - - case 0x2f: // Data Segment - val = m_cpu->get_ds(); - LOGMASKED(LOG_SEGMENT, "io_r: Data Segment = %04x\n", val); - break; - - default: - LOGMASKED(LOG_UNKNOWN_IO, "io_r: Unknown register %04x\n", 0x3d00 + offset); - break; - } - - return val; -} - -READ16_MEMBER(spg2xx_io_device::io_extended_r) -{ - // this set of registers might only be on the 24x not the 11x - - offset += 0x30; - - uint16_t val = m_io_regs[offset]; - - switch (offset) - { - case 0x30: // UART Control - LOGMASKED(LOG_UART, "%s: io_r: UART Control = %04x\n", machine().describe_context(), val); - break; - - case 0x31: // UART Status - //LOGMASKED(LOG_UART, "%s: io_r: UART Status = %04x\n", machine().describe_context(), val); - break; - - case 0x36: // UART RX Data - if (m_uart_rx_available) - { - m_io_regs[0x31] &= ~0x0081; - LOGMASKED(LOG_UART, "UART Rx data is available, clearing bits\n"); - if (m_uart_rx_fifo_count) - { - LOGMASKED(LOG_UART, "Remaining count %d, value %02x\n", m_uart_rx_fifo_count, m_uart_rx_fifo[m_uart_rx_fifo_start]); - m_io_regs[0x36] = m_uart_rx_fifo[m_uart_rx_fifo_start]; - val = m_io_regs[0x36]; - m_uart_rx_fifo_start = (m_uart_rx_fifo_start + 1) % ARRAY_LENGTH(m_uart_rx_fifo); - m_uart_rx_fifo_count--; - - if (m_uart_rx_fifo_count == 0) - { - m_uart_rx_available = false; - } - else - { - LOGMASKED(LOG_UART, "Remaining count %d, setting up timer\n", m_uart_rx_fifo_count); - //uart_receive_tick(); - if (m_uart_rx_timer->remaining() == attotime::never) - m_uart_rx_timer->adjust(attotime::from_ticks(BIT(m_io_regs[0x30], 5) ? 11 : 10, m_uart_baud_rate)); - } - } - else - { - m_uart_rx_available = false; - } - } - else - { - m_io_regs[0x37] |= 0x2000; - } - LOGMASKED(LOG_UART, "%s: io_r: UART Rx Data = %04x\n", machine().describe_context(), val); - break; - - case 0x37: // UART Rx FIFO Control - val &= ~0x0070; - val |= (m_uart_rx_available ? 7 : 0) << 4; - LOGMASKED(LOG_UART, "io_r: UART Rx FIFO Control = %04x\n", machine().describe_context(), val); - break; - - case 0x51: // unknown, polled by ClickStart cartridges ( clikstrt ) - return 0x8000; - - case 0x59: // I2C Status - LOGMASKED(LOG_I2C, "io_r: I2C Status = %04x\n", val); - break; - - case 0x5e: // I2C Data In - LOGMASKED(LOG_I2C, "io_r: I2C Data In = %04x\n", val); - break; - - default: - LOGMASKED(LOG_UNKNOWN_IO, "io_r: Unknown register %04x\n", 0x3d00 + offset); - break; - } - - return val; -} - -void spg2xx_io_device::update_porta_special_modes() -{ - static const char* const s_pa_special[4][16] = - { - // Input, Special 0 - // Input, Special 1 - // Output, Special 0 - // Output, Special 1 - - { "LP", "ExtClk2", "ExtClk1", "-", "SDA", "SlvRDY", "-", "-", "SPICLK", "-", "RxD", "SPISSB", "-", "-", "-", "-" }, - { "-", "-", "-", "SCK", "-", "SWS", "-", "-", "-", "-", "-", "-", "IRQ2B", "-", "-", "IRQ1B" }, - { "-", "-", "-", "SCK", "SDA", "SWS", "-", "-", "SPICLK", "TxD", "-", "SPISSB", "TAPWM", "TM1", "TBPWM", "TM2" }, - { "CSB3", "CSB2", "CSB1", "SCK", "SDA", "VSYNC", "HSYNC", "SYSCLK3", "SPICLK", "TxD", "SWS", "SPISSB", "-", "VSYNC", "HSYNC", "CSYNC" }, - }; - for (int bit = 15; bit >= 0; bit--) - { - if (!BIT(m_io_regs[0x05], bit)) - continue; - uint8_t type = (BIT(m_io_regs[0x03], bit) << 1) | BIT(m_io_regs[0x00], 0); - LOGMASKED(LOG_GPIO, " Bit %2d: %s\n", bit, s_pa_special[type][bit]); - } -} - -void spg2xx_io_device::update_portb_special_modes() -{ - static const char* const s_pb_special[4][8] = - { - // Input, Special 0 - // Input, Special 1 - // Output, Special 0 - // Output, Special 1 - - { "-", "-", "-", "-", "-", "-", "SDA", "SlvRDY" }, - { "-", "-", "-", "-", "-", "-", "SDA", "SlvRDY" }, - { "VSYNC", "HSYNC", "CSYNC", "-", "-", "SCK", "SDA", "SWS" }, - { "CSB3", "CSB2", "CSB1", "TBPWM", "TM2", "-", "-", "SYSCLK2" }, - }; - for (int bit = 7; bit >= 0; bit--) - { - if (!BIT(m_io_regs[0x0a], bit)) - continue; - uint8_t type = (BIT(m_io_regs[0x08], bit) << 1) | BIT(m_io_regs[0x00], 1); - LOGMASKED(LOG_GPIO, " Bit %2d: %s\n", bit, s_pb_special[type][bit]); - } -} - -void spg2xx_io_device::update_timer_b_rate() -{ - switch (m_io_regs[0x17] & 7) - { - case 0: - case 1: - case 5: - case 6: - case 7: - m_timer_src_c->adjust(attotime::never); - break; - case 2: - m_timer_src_c->adjust(attotime::from_hz(32768), 0, attotime::from_hz(32768)); - break; - case 3: - m_timer_src_c->adjust(attotime::from_hz(8192), 0, attotime::from_hz(8192)); - break; - case 4: - m_timer_src_c->adjust(attotime::from_hz(4096), 0, attotime::from_hz(4096)); - break; - } -} - -void spg2xx_io_device::update_timer_ab_src() -{ - if (m_timer_b_tick_rate == 0) - return; - - m_timer_b_divisor++; - if (m_timer_b_divisor >= m_timer_b_tick_rate) - { - m_timer_b_divisor = 0; - increment_timer_a(); - } -} - -void spg2xx_io_device::increment_timer_a() -{ - m_io_regs[0x12]++; - if (m_io_regs[0x12] == 0) - { - m_io_regs[0x12] = m_timer_a_preload; - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS |= 0x0800; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - { - //printf("Timer A overflow\n"); - check_irqs(0x0800); - } - } -} - -void spg2xx_io_device::update_timer_c_src() -{ - m_io_regs[0x16]++; - if (m_io_regs[0x16] == 0) - { - m_io_regs[0x16] = m_timer_b_preload; - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS |= 0x0400; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - { - printf("Timer B overflow\n"); - check_irqs(0x0400); - } - } -} - - -WRITE16_MEMBER(spg28x_io_device::io_extended_w) -{ - offset += 0x30; - - if (offset == 0x33) - { - m_io_regs[offset] = data; - m_uart_baud_rate = 27000000 / (0x10000 - m_io_regs[0x33]); - LOGMASKED(LOG_UART, "%s: io_w: UART Baud Rate scaler = %04x (%d baud)\n", machine().describe_context(), data, m_uart_baud_rate); - } - else - { - spg2xx_io_device::io_extended_w(space, offset-0x30, data, mem_mask); - } -} - -WRITE16_MEMBER(spg2xx_io_device::io_w) -{ - static const char *const gpioregs[] = { "GPIO Data Port", "GPIO Buffer Port", "GPIO Direction Port", "GPIO Attribute Port", "GPIO IRQ/Latch Port" }; - static const char gpioports[3] = { 'A', 'B', 'C' }; - - switch (offset) - { - case 0x00: // GPIO special function select - { - LOGMASKED(LOG_GPIO, "%s: io_w: GPIO Configuration = %04x (IOBWake:%d, IOAWake:%d, IOBSpecSel:%d, IOASpecSel:%d)\n", machine().describe_context(), data - , BIT(data, 4), BIT(data, 3), BIT(data, 1), BIT(data, 0)); - const uint16_t old = m_io_regs[offset]; - m_io_regs[offset] = data; - const uint16_t changed = old ^ data; - if (BIT(changed, 0)) - update_porta_special_modes(); - if (BIT(changed, 1)) - update_portb_special_modes(); - break; - } - - case 0x01: case 0x06: case 0x0b: // GPIO data, port A/B/C - offset++; - // Intentional fallthrough - we redirect data register writes to the buffer register. - - case 0x02: case 0x04: // Port A - case 0x07: case 0x09: // Port B - case 0x0c: case 0x0d: case 0x0e: case 0x0f: // Port C - LOGMASKED(LOG_GPIO, "%s: io_w: %s %c = %04x\n", machine().describe_context(), gpioregs[(offset - 1) % 5], gpioports[(offset - 1) / 5], data); - m_io_regs[offset] = data; - do_gpio(offset, true); - break; - - case 0x03: // Port A Direction - LOGMASKED(LOG_GPIO, "%s: io_w: GPIO Direction Port A = %04x\n", machine().describe_context(), data); - m_io_regs[offset] = data; - update_porta_special_modes(); - do_gpio(offset, true); - break; - - case 0x08: // Port B Direction - LOGMASKED(LOG_GPIO, "%s: io_w: GPIO Direction Port B = %04x\n", machine().describe_context(), data); - m_io_regs[offset] = data; - update_portb_special_modes(); - do_gpio(offset, true); - break; - - case 0x05: // Port A Special - LOGMASKED(LOG_GPIO, "%s: io_w: Port A Special Function Select: %04x\n", machine().describe_context(), data); - m_io_regs[offset] = data; - update_porta_special_modes(); - break; - - case 0x0a: // Port B Special - LOGMASKED(LOG_GPIO, "%s: io_w: Port B Special Function Select: %04x\n", machine().describe_context(), data); - m_io_regs[offset] = data; - update_portb_special_modes(); - break; - - case 0x10: // Timebase Control - { - static const char* const s_tmb1_sel[2][4] = - { - { "8Hz", "16Hz", "32Hz", "64Hz" }, - { "12kHz", "24kHz", "40kHz", "40kHz" } - }; - static const char* const s_tmb2_sel[2][4] = - { - { "128Hz", "256Hz", "512Hz", "1024Hz" }, - { "105kHz", "210kHz", "420kHz", "840kHz" } - }; - static const uint32_t s_tmb1_freq[2][4] = - { - { 8, 16, 32, 64 }, - { 12000, 24000, 40000, 40000 } - }; - static const uint32_t s_tmb2_freq[2][4] = - { - { 128, 256, 512, 1024 }, - { 105000, 210000, 420000, 840000 } - }; - LOGMASKED(LOG_TIMERS, "io_w: Timebase Control = %04x (Source:%s, TMB2:%s, TMB1:%s)\n", data, - BIT(data, 4) ? "27MHz" : "32768Hz", s_tmb2_sel[BIT(data, 4)][(data >> 2) & 3], s_tmb1_sel[BIT(data, 4)][data & 3]); - m_io_regs[offset] = data; - const uint8_t hifreq = BIT(data, 4); - const uint32_t tmb1freq = s_tmb1_freq[hifreq][data & 3]; - m_tmb1->adjust(attotime::from_hz(tmb1freq), 0, attotime::from_hz(tmb1freq)); - const uint32_t tmb2freq = s_tmb2_freq[hifreq][(data >> 2) & 3]; - m_tmb2->adjust(attotime::from_hz(tmb2freq), 0, attotime::from_hz(tmb2freq)); - break; - } - - case 0x11: // Timebase Clear - LOGMASKED(LOG_TIMERS, "io_w: Timebase Clear = %04x\n", data); - break; - - case 0x12: // Timer A Data - LOGMASKED(LOG_TIMERS, "io_w: Timer A Data = %04x\n", data); - m_io_regs[offset] = data; - m_timer_a_preload = data; - break; - - case 0x13: // Timer A Control - { - static const char* const s_source_a[8] = { "0", "0", "32768Hz", "8192Hz", "4096Hz", "1", "0", "ExtClk1" }; - static const char* const s_source_b[8] = { "2048Hz", "1024Hz", "256Hz", "TMB1", "4Hz", "2Hz", "1", "ExtClk2" }; - LOGMASKED(LOG_TIMERS, "io_w: Timer A Control = %04x (Source A:%s, Source B:%s)\n", data, - s_source_a[data & 7], s_source_b[(data >> 3) & 7]); - m_io_regs[offset] = data; - int timer_a_rate = 0; - switch (data & 7) - { - case 0: - case 1: - case 5: - case 6: - case 7: - m_timer_src_ab->adjust(attotime::never); - break; - case 2: - m_timer_src_ab->adjust(attotime::from_hz(32768), 0, attotime::from_hz(32768)); - timer_a_rate = 32768; - break; - case 3: - m_timer_src_ab->adjust(attotime::from_hz(8192), 0, attotime::from_hz(8192)); - timer_a_rate = 8192; - break; - case 4: - m_timer_src_ab->adjust(attotime::from_hz(4096), 0, attotime::from_hz(4096)); - timer_a_rate = 4096; - break; - } - switch ((data >> 3) & 7) - { - case 0: - m_timer_b_tick_rate = timer_a_rate / 2048; - break; - case 1: - m_timer_b_tick_rate = timer_a_rate / 1024; - break; - case 2: - m_timer_b_tick_rate = timer_a_rate / 256; - break; - case 3: - m_timer_b_tick_rate = 0; - break; - case 4: - m_timer_b_tick_rate = timer_a_rate / 4; - break; - case 5: - m_timer_b_tick_rate = timer_a_rate / 2; - break; - case 6: - m_timer_b_tick_rate = 1; - break; - case 7: - m_timer_b_tick_rate = 0; - break; - } - break; - } - - case 0x15: // Timer A IRQ Clear - { - LOGMASKED(LOG_TIMERS, "io_w: Timer A IRQ Clear\n"); - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS &= ~0x0800; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - check_irqs(0x0800); - break; - } - - case 0x16: // Timer B Data - LOGMASKED(LOG_TIMERS, "io_w: Timer B Data = %04x\n", data); - m_io_regs[offset] = data; - m_timer_b_preload = data; - break; - - case 0x17: // Timer B Control - { - static const char* const s_source_c[8] = { "0", "0", "32768Hz", "8192Hz", "4096Hz", "1", "0", "ExtClk1" }; - LOGMASKED(LOG_TIMERS, "io_w: Timer B Control = %04x (Source C:%s)\n", data, s_source_c[data & 7]); - m_io_regs[offset] = data; - if (m_io_regs[0x18] == 1) - { - update_timer_b_rate(); - } - break; - } - - case 0x18: // Timer B Enable - { - LOGMASKED(LOG_TIMERS, "io_w: Timer B Enable = %04x\n", data); - m_io_regs[offset] = data & 1; - if (data & 1) - { - update_timer_b_rate(); - } - else - { - m_timer_src_c->adjust(attotime::never); - } - break; - } - - case 0x19: // Timer B IRQ Clear - { - LOGMASKED(LOG_TIMERS, "io_w: Timer B IRQ Clear\n"); - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS &= ~0x0400; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - check_irqs(0x0400); - break; - } - - case 0x20: // System Control - { - static const char* const s_sysclk[4] = { "13.5MHz", "27MHz", "27MHz NoICE", "54MHz" }; - static const char* const s_lvd_voltage[4] = { "2.7V", "2.9V", "3.1V", "3.3V" }; - static const char* const s_weak_strong[2] = { "Weak", "Strong" }; - LOGMASKED(LOG_IO_WRITES, "io_w: System Control = %04x (Watchdog:%d, Sleep:%d, SysClk:%s, SysClkInv:%d, LVROutEn:%d, LVREn:%d\n" - , data, BIT(data, 15), BIT(data, 14), s_sysclk[(data >> 12) & 3], BIT(data, 11), BIT(data, 9), BIT(data, 8)); - LOGMASKED(LOG_IO_WRITES, " LVDEn:%d, LVDVoltSel:%s, 32kHzDisable:%d, StrWkMode:%s, VDACDisable:%d, ADACDisable:%d, ADACOutDisable:%d)\n" - , BIT(data, 7), s_lvd_voltage[(data >> 5) & 3], BIT(data, 4), s_weak_strong[BIT(data, 3)], BIT(data, 2), BIT(data, 1), BIT(data, 0)); - m_io_regs[offset] = data; - break; - } - - case 0x21: // IRQ Enable - { - LOGMASKED(LOG_IRQS, "io_w: IRQ Enable = %04x\n", data); - const uint16_t old = IO_IRQ_ENABLE; - m_io_regs[offset] = data; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - check_irqs(changed); - break; - } - - case 0x22: // IRQ Acknowledge - { - LOGMASKED(LOG_IRQS, "io_w: IRQ Acknowledge = %04x\n", data); - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS &= ~data; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (m_uart_rx_irq || m_uart_tx_irq) - { - LOGMASKED(LOG_IRQS | LOG_UART, "Re-setting UART IRQ due to still-unacknowledged Rx or Tx.\n"); - IO_IRQ_STATUS |= 0x0100; - } - if (changed) - check_irqs(changed); - break; - } - - case 0x23: // External Memory Control - { - static const char* const s_bus_arb[8] = - { - "Forbidden", "Forbidden", "Forbidden", "Forbidden", "Forbidden", "1:SPU/2:PPU/3:CPU", "Forbidden", "1:PPU/2:SPU/3:CPU" - }; - static const char* const s_addr_decode[4] = - { - "ROMCSB: 4000-3fffff, CSB1: ---, CSB2: ---, CSB3: ---", - "ROMCSB: 4000-1fffff, CSB1: 200000-3fffff, CSB2: ---, CSB3: ---", - "ROMCSB: 4000-0fffff, CSB1: 100000-1fffff, CSB2: 200000-2fffff, CSB3: 300000-3fffff", - "ROMCSB: 4000-0fffff, CSB1: 100000-1fffff, CSB2: 200000-2fffff, CSB3: 300000-3fffff" - }; - static const char* const s_ram_decode[16] = - { - "None", "None", "None", "None", "None", "None", "None", "None", - "4KW, 3ff000-3fffff\n", - "8KW, 3fe000-3fffff\n", - "16KW, 3fc000-3fffff\n", - "32KW, 3f8000-3fffff\n", - "64KW, 3f0000-3fffff\n", - "128KW, 3e0000-3fffff\n", - "256KW, 3c0000-3fffff\n", - "512KW, 380000-3fffff\n" - }; - LOGMASKED(LOG_EXT_MEM, "io_w: Ext. Memory Control (not yet implemented) = %04x:\n", data); - LOGMASKED(LOG_EXT_MEM, " WaitStates:%d, BusArbPrio:%s\n", (data >> 1) & 3, s_bus_arb[(data >> 3) & 7]); - LOGMASKED(LOG_EXT_MEM, " ROMAddrDecode:%s\n", s_addr_decode[(data >> 6) & 3]); - LOGMASKED(LOG_EXT_MEM, " RAMAddrDecode:%s\n", s_ram_decode[(data >> 8) & 15]); - m_chip_sel((data >> 6) & 3); - m_io_regs[offset] = data; - break; - } - - case 0x24: // Watchdog - LOGMASKED(LOG_WATCHDOG, "io_w: Watchdog Pet = %04x\n", data); - break; - - case 0x25: // ADC Control - { - LOGMASKED(LOG_IO_WRITES, "%s: io_w: ADC Control = %04x\n", machine().describe_context(), data); - m_io_regs[offset] = data & ~0x1000; - if (BIT(data, 0)) - { - m_io_regs[0x27] = 0x8000 | (m_adc_in[BIT(data, 5)]() & 0x7fff); - m_io_regs[0x25] |= 0x2000; - } - if (BIT(data, 12) && !BIT(m_io_regs[offset], 1)) - { - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS |= 0x2000; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - { - check_irqs(changed); - } - } - break; - } - - case 0x28: // Sleep Mode - LOGMASKED(LOG_IO_WRITES, "io_w: Sleep Mode (%s enter value) = %04x\n", data == 0xaa55 ? "valid" : "invalid", data); - m_io_regs[offset] = data; - break; - - case 0x29: // Wakeup Source - { - m_io_regs[offset] = data; - static const char* const s_sources[8] = - { - "TMB1", "TMB2", "2Hz", "4Hz", "1024Hz", "2048Hz", "4096Hz", "Key" - }; - - LOGMASKED(LOG_IO_WRITES, "io_w: Wakeup Source = %04x:\n", data); - bool comma = false; - char buf[1024]; - int char_idx = 0; - for (int i = 7; i >= 0; i--) - { - if (BIT(data, i)) - { - char_idx += sprintf(&buf[char_idx], "%s%s", comma ? ", " : "", s_sources[i]); - comma = true; - } - } - buf[char_idx] = 0; - LOGMASKED(LOG_IO_WRITES, " %s\n", buf); - break; - } - - case 0x2c: // PRNG 0 seed - LOGMASKED(LOG_IO_WRITES, "io_w: PRNG 0 seed = %04x\n", data & 0x7fff); - m_io_regs[offset] = data & 0x7fff; - break; - - case 0x2d: // PRNG 1 seed - LOGMASKED(LOG_IO_WRITES, "io_w: PRNG 1 seed = %04x\n", data & 0x7fff); - m_io_regs[offset] = data & 0x7fff; - break; - - case 0x2e: // FIQ Source Select - { - static const char* const s_fiq_select[8] = - { - "PPU", "SPU Channel", "Timer A", "Timer B", "UART/SPI", "External", "Reserved", "None" - }; - LOGMASKED(LOG_FIQ, "io_w: FIQ Source Select (not yet implemented) = %04x, %s\n", data, s_fiq_select[data & 7]); - m_io_regs[offset] = data; - break; - } - - case 0x2f: // Data Segment - m_cpu->set_ds(data & 0x3f); - LOGMASKED(LOG_SEGMENT, "io_w: Data Segment = %04x\n", data); - break; - - default: - LOGMASKED(LOG_UNKNOWN_IO, "io_w: Unknown register %04x = %04x\n", 0x3d00 + offset, data); - m_io_regs[offset] = data; - break; - } -} - - - - -WRITE16_MEMBER(spg2xx_io_device::io_extended_w) -{ - // this set of registers might only be on the 24x not the 11x - - offset += 0x30; - - switch (offset) - { - - case 0x30: // UART Control - { - static const char* const s_9th_bit[4] = { "0", "1", "Odd", "Even" }; - LOGMASKED(LOG_UART, "%s: io_w: UART Control = %04x (TxEn:%d, RxEn:%d, Bits:%d, MultiProc:%d, 9thBit:%s, TxIntEn:%d, RxIntEn:%d\n", - machine().describe_context(), data, BIT(data, 7), BIT(data, 6), BIT(data, 5) ? 9 : 8, BIT(data, 4), s_9th_bit[(data >> 2) & 3], - BIT(data, 1), BIT(data, 0)); - const uint16_t changed = m_io_regs[offset] ^ data; - m_io_regs[offset] = data; - if (!BIT(data, 6)) - { - m_uart_rx_available = false; - m_io_regs[0x36] = 0; - } - if (BIT(changed, 7)) - { - if (BIT(data, 7)) - { - m_io_regs[0x31] |= 0x0002; - } - else - { - m_io_regs[0x31] &= ~0x0042; - m_uart_tx_timer->adjust(attotime::never); - } - } - break; - } - - case 0x31: // UART Status - LOGMASKED(LOG_UART, "%s: io_w: UART Status = %04x\n", machine().describe_context(), data); - if (BIT(data, 0)) - { - m_io_regs[0x31] &= ~1; - m_uart_rx_irq = false; - } - if (BIT(data, 1)) - { - m_io_regs[0x31] &= ~2; - m_uart_tx_irq = false; - } - if (!m_uart_rx_irq && !m_uart_tx_irq) - { - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS &= ~0x0100; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - check_irqs(0x0100); - } - break; - - case 0x33: // UART Baud Rate (low byte) - case 0x34: // UART Baud Rate (high byte) - { - m_io_regs[offset] = data; - const uint32_t divisor = 16 * (0x10000 - ((m_io_regs[0x34] << 8) | m_io_regs[0x33])); - LOGMASKED(LOG_UART, "%s: io_w: UART Baud Rate (%s byte): Baud rate = %d\n", offset == 0x33 ? "low" : "high", machine().describe_context(), 27000000 / divisor); - m_uart_baud_rate = 27000000 / divisor; - break; - } - - case 0x35: // UART TX Data - LOGMASKED(LOG_UART, "%s: io_w: UART Tx Data = %02x\n", machine().describe_context(), data & 0x00ff); - m_io_regs[offset] = data; - if (BIT(m_io_regs[0x30], 7)) - { - LOGMASKED(LOG_UART, "io_w: UART Tx: Clearing ready bit, setting busy bit, setting up timer\n"); - m_uart_tx_timer->adjust(attotime::from_ticks(BIT(m_io_regs[0x30], 5) ? 11 : 10, m_uart_baud_rate)); - m_io_regs[0x31] &= ~0x0002; - m_io_regs[0x31] |= 0x0040; - } - break; - - case 0x36: // UART RX Data - LOGMASKED(LOG_UART, "%s: io_w: UART Rx Data (read-only) = %04x\n", machine().describe_context(), data); - break; - - case 0x37: // UART Rx FIFO Control - LOGMASKED(LOG_UART, "%s: io_w: UART Rx FIFO Control = %04x (Reset:%d, Overrun:%d, Underrun:%d, Count:%d, Threshold:%d)\n", - machine().describe_context(), data, BIT(data, 15), BIT(data, 14), BIT(data, 13), (data >> 4) & 7, data & 7); - if (data & 0x8000) - { - m_uart_rx_available = false; - m_io_regs[0x36] = 0; - } - m_io_regs[offset] &= ~data & 0x6000; - m_io_regs[offset] &= ~0x0007; - m_io_regs[offset] |= data & 0x0007; - break; - - case 0x50: // SIO Setup - { - static const char* const s_addr_mode[4] = { "16-bit", "None", "8-bit", "24-bit" }; - static const char* const s_baud_rate[4] = { "/16", "/4", "/8", "/32" }; - LOGMASKED(LOG_SIO, "io_w: SIO Setup (not implemented) = %04x (DS301Ready:%d, Start:%d, Auto:%d, IRQEn:%d, Width:%d, Related:%d\n", data - , BIT(data, 11), BIT(data, 10), BIT(data, 9), BIT(data, 8), BIT(data, 7) ? 16 : 8, BIT(data, 6)); - LOGMASKED(LOG_SIO, " (Mode:%s, RWProtocol:%d, Rate:sysclk%s, AddrMode:%s)\n" - , BIT(data, 5), BIT(data, 4), s_baud_rate[(data >> 2) & 3], s_addr_mode[data & 3]); - break; - } - - case 0x52: // SIO Start Address (low) - LOGMASKED(LOG_SIO, "io_w: SIO Stat Address (low) (not implemented) = %04x\n", data); - break; - - case 0x53: // SIO Start Address (hi) - LOGMASKED(LOG_SIO, "io_w: SIO Stat Address (hi) (not implemented) = %04x\n", data); - break; - - case 0x54: // SIO Data - LOGMASKED(LOG_SIO, "io_w: SIO Data (not implemented) = %04x\n", data); - break; - - case 0x55: // SIO Automatic Transmit Count - LOGMASKED(LOG_SIO, "io_w: SIO Auto Transmit Count (not implemented) = %04x\n", data); - break; - - case 0x58: // I2C Command - LOGMASKED(LOG_I2C, "io_w: I2C Command = %04x\n", data); - m_io_regs[offset] = data; - do_i2c(); - break; - - case 0x59: // I2C Status / Acknowledge - LOGMASKED(LOG_I2C, "io_w: I2C Acknowledge = %04x\n", data); - m_io_regs[offset] &= ~data; - break; - - case 0x5a: // I2C Access Mode - LOGMASKED(LOG_I2C, "io_w: I2C Access Mode = %04x\n", data); - m_io_regs[offset] = data; - break; - - case 0x5b: // I2C Device Address - LOGMASKED(LOG_I2C, "io_w: I2C Device Address = %04x\n", data); - m_io_regs[offset] = data; - break; - - case 0x5c: // I2C Sub-Address - LOGMASKED(LOG_I2C, "io_w: I2C Sub-Address = %04x\n", data); - m_io_regs[offset] = data; - break; - - case 0x5d: // I2C Data Out - LOGMASKED(LOG_I2C, "io_w: I2C Data Out = %04x\n", data); - m_io_regs[offset] = data; - break; - - case 0x5e: // I2C Data In - LOGMASKED(LOG_I2C, "io_w: I2C Data In = %04x\n", data); - m_io_regs[offset] = data; - break; - - case 0x5f: // I2C Controller Mode - LOGMASKED(LOG_I2C, "io_w: I2C Controller Mode = %04x\n", data); - m_io_regs[offset] = data; - break; - - default: - LOGMASKED(LOG_UNKNOWN_IO, "io_w: Unknown register %04x = %04x\n", 0x3d00 + offset, data); - m_io_regs[offset] = data; - break; - } -} - -void spg2xx_io_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch (id) - { - case TIMER_TMB1: - { - LOGMASKED(LOG_TIMERS, "TMB1 elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 1, IO_IRQ_ENABLE); - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS |= 1; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - check_irqs(0x0001); - break; - } - - case TIMER_TMB2: - { - LOGMASKED(LOG_TIMERS, "TMB2 elapsed, setting IRQ Status bit 1 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 2, IO_IRQ_ENABLE); - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS |= 2; - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - check_irqs(0x0002); - break; - } - - case TIMER_UART_TX: - uart_transmit_tick(); - break; - - case TIMER_UART_RX: - uart_receive_tick(); - break; - - case TIMER_4KHZ: - system_timer_tick(); - break; - - case TIMER_SRC_AB: - update_timer_ab_src(); - break; - - case TIMER_SRC_C: - update_timer_c_src(); - break; - } -} - -void spg2xx_io_device::system_timer_tick() -{ - const uint16_t old = IO_IRQ_STATUS; - uint16_t check_mask = 0x0040; - IO_IRQ_STATUS |= 0x0040; - - m_2khz_divider++; - if (m_2khz_divider == 2) - { - m_2khz_divider = 0; - IO_IRQ_STATUS |= 0x0020; - check_mask |= 0x0020; - - m_1khz_divider++; - if (m_1khz_divider == 2) - { - m_1khz_divider = 0; - IO_IRQ_STATUS |= 0x0010; - check_mask |= 0x0010; - - m_4hz_divider++; - if (m_4hz_divider == 256) - { - m_4hz_divider = 0; - IO_IRQ_STATUS |= 0x0008; - check_mask |= 0x0008; - } - } - } - - const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); - if (changed) - check_irqs(check_mask); -} - -void spg2xx_io_device::uart_transmit_tick() -{ - LOGMASKED(LOG_UART, "uart_transmit_tick: Transmitting %02x, setting TxReady, clearing TxBusy\n", (uint8_t)m_io_regs[0x35]); - m_uart_tx((uint8_t)m_io_regs[0x35]); - m_io_regs[0x31] |= 0x0002; - m_io_regs[0x31] &= ~0x0040; - if (BIT(m_io_regs[0x30], 1)) - { - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS |= 0x0100; - m_uart_tx_irq = true; - LOGMASKED(LOG_UART, "uart_transmit_tick: Setting UART IRQ bit\n"); - if (IO_IRQ_STATUS != old) - { - LOGMASKED(LOG_UART, "uart_transmit_tick: Bit newly set, checking IRQs\n"); - check_irqs(0x0100); - } - } -} - -void spg2xx_io_device::uart_receive_tick() -{ - LOGMASKED(LOG_UART, "uart_receive_tick: Setting RBF and RxRDY\n"); - m_io_regs[0x31] |= 0x81; - m_uart_rx_available = true; - if (BIT(m_io_regs[0x30], 0)) - { - LOGMASKED(LOG_UART, "uart_receive_tick: RxIntEn is set, setting rx_irq to true and setting UART IRQ\n"); - m_uart_rx_irq = true; - IO_IRQ_STATUS |= 0x0100; - check_irqs(0x0100); - } -} - -void spg2xx_io_device::extint_w(int channel, bool state) -{ - LOGMASKED(LOG_EXTINT, "Setting extint channel %d to %s\n", channel, state ? "true" : "false"); - bool old = m_extint[channel]; - m_extint[channel] = state; - if (old != state) - { - check_extint_irq(channel); - } -} - -void spg2xx_io_device::check_extint_irq(int channel) -{ - LOGMASKED(LOG_EXTINT, "%sing extint %d interrupt\n", m_extint[channel] ? "rais" : "lower", channel + 1); - const uint16_t mask = (channel == 0) ? 0x0200 : 0x1000; - const uint16_t old_irq = IO_IRQ_STATUS; - if (m_extint[channel]) - IO_IRQ_STATUS |= mask; - else - IO_IRQ_STATUS &= ~mask; - - if (old_irq != IO_IRQ_STATUS) - { - LOGMASKED(LOG_EXTINT, "extint IRQ changed, so checking interrupts\n"); - check_irqs(mask); - } -} - -void spg2xx_io_device::check_irqs(const uint16_t changed) -{ - if (changed & 0x0c00) // Timer A, Timer B IRQ - { - LOGMASKED(LOG_TIMERS, "%ssserting IRQ2 (%04x, %04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00), changed); - m_timer_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE); - } - - if (changed & 0x2100) // UART, ADC IRQ - { - LOGMASKED(LOG_UART, "%ssserting IRQ3 (%04x, %04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100), changed); - m_uart_adc_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100) ? ASSERT_LINE : CLEAR_LINE); - } - - if (changed & 0x1200) // External IRQ - { - LOGMASKED(LOG_UART, "%ssserting IRQ5 (%04x, %04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200), changed); - m_external_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? ASSERT_LINE : CLEAR_LINE); - } - - if (changed & 0x0070) // 1024Hz, 2048Hz, 4096Hz IRQ - { - LOGMASKED(LOG_TIMERS, "%ssserting IRQ6 (%04x, %04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070), changed); //m_cpu->set_state_unsynced(UNSP_IRQ6_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE); - m_ffreq_tmr1_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE); - } - - if (changed & 0x008b) // TMB1, TMB2, 4Hz, key change IRQ - { - LOGMASKED(LOG_IRQS, "%ssserting IRQ7 (%04x, %04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b), changed); - m_ffreq_tmr2_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? ASSERT_LINE : CLEAR_LINE); - } -} - -uint16_t spg2xx_io_device::do_special_gpio(uint32_t index, uint16_t mask) -{ - uint16_t data = 0; - switch (index) - { - case 0: // Port A - if (mask & 0xe000) - { - const uint8_t csel = m_cpu->get_csb() & 0x0e; - data = (csel << 12) & mask; - } - break; - case 1: // Port B - // To do - break; - case 2: // Port C - // To do - break; - default: - // Can't happen - break; - } - return data; -} - -void spg2xx_io_device::do_gpio(uint32_t offset, bool write) -{ - uint32_t index = (offset - 1) / 5; - uint16_t buffer = m_io_regs[5 * index + 2]; - uint16_t dir = m_io_regs[5 * index + 3]; - uint16_t attr = m_io_regs[5 * index + 4]; - uint16_t special = m_io_regs[5 * index + 5]; - - uint16_t push = dir; - uint16_t pull = ~dir; - uint16_t what = (buffer & (push | pull)); - what ^= (dir & ~attr); - what &= ~special; - - switch (index) - { - case 0: - if (write) - m_porta_out(0, what, push &~ special); - what = (what & ~pull); - if (!write) - what |= m_porta_in(0, pull &~ special) & pull; - break; - case 1: - if (write) - m_portb_out(0, what, push &~ special); - what = (what & ~pull); - if (!write) - what |= m_portb_in(0, pull &~ special) & pull; - break; - case 2: - if (write) - m_portc_out(0, what, push &~ special); - what = (what & ~pull); - if (!write) - what |= m_portc_in(0, pull &~ special) & pull; - break; - } - - what |= do_special_gpio(index, special); - m_io_regs[5 * index + 1] = what; -} - -void spg2xx_io_device::do_i2c() -{ - const uint16_t addr = ((m_io_regs[0x5b] & 0x06) << 7) | (uint8_t)m_io_regs[0x5c]; - - if (m_io_regs[0x58] & 0x40) // Serial EEPROM read - m_io_regs[0x5e] = m_eeprom_r(addr); - else - m_eeprom_w(addr, m_io_regs[0x5d]); - - m_io_regs[0x59] |= 1; -} diff --git a/src/devices/machine/spg2xx_io.h b/src/devices/machine/spg2xx_io.h deleted file mode 100644 index d829915cbec..00000000000 --- a/src/devices/machine/spg2xx_io.h +++ /dev/null @@ -1,183 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz - -#ifndef MAME_MACHINE_SPG2XX_IO_H -#define MAME_MACHINE_SPG2XX_IO_H - -#pragma once - -#include "cpu/unsp/unsp.h" -#include "screen.h" - -class spg2xx_io_device : public device_t -{ -public: - spg2xx_io_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - auto porta_out() { return m_porta_out.bind(); } - auto portb_out() { return m_portb_out.bind(); } - auto portc_out() { return m_portc_out.bind(); } - auto porta_in() { return m_porta_in.bind(); } - auto portb_in() { return m_portb_in.bind(); } - auto portc_in() { return m_portc_in.bind(); } - - template <size_t Line> auto adc_in() { return m_adc_in[Line].bind(); } - - auto eeprom_w() { return m_eeprom_w.bind(); } - auto eeprom_r() { return m_eeprom_r.bind(); } - - auto uart_tx() { return m_uart_tx.bind(); } - - auto chip_select() { return m_chip_sel.bind(); } - - void uart_rx(uint8_t data); - - void extint_w(int channel, bool state); - - DECLARE_READ16_MEMBER(io_r); - DECLARE_WRITE16_MEMBER(io_w); - - virtual DECLARE_READ16_MEMBER(io_extended_r); - virtual DECLARE_WRITE16_MEMBER(io_extended_w); - - - auto pal_read_callback() { return m_pal_read_cb.bind(); }; - - auto write_timer_irq_callback() { return m_timer_irq_cb.bind(); }; - auto write_uart_adc_irq_callback() { return m_uart_adc_irq_cb.bind(); }; - auto write_external_irq_callback() { return m_external_irq_cb.bind(); }; - auto write_ffrq_tmr1_irq_callback() { return m_ffreq_tmr1_irq_cb.bind(); }; - auto write_ffrq_tmr2_irq_callback() { return m_ffreq_tmr2_irq_cb.bind(); }; - -protected: - spg2xx_io_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint32_t sprite_limit) - : spg2xx_io_device(mconfig, type, tag, owner, clock) - { - } - - void check_extint_irq(int channel); - void check_irqs(const uint16_t changed); - - static const device_timer_id TIMER_TMB1 = 0; - static const device_timer_id TIMER_TMB2 = 1; - - static const device_timer_id TIMER_UART_TX = 4; - static const device_timer_id TIMER_UART_RX = 5; - static const device_timer_id TIMER_4KHZ = 6; - static const device_timer_id TIMER_SRC_AB = 7; - static const device_timer_id TIMER_SRC_C = 8; - - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - - void update_porta_special_modes(); - void update_portb_special_modes(); - void do_gpio(uint32_t offset, bool write); - uint16_t do_special_gpio(uint32_t index, uint16_t mask); - - void update_timer_b_rate(); - void update_timer_ab_src(); - void update_timer_c_src(); - void increment_timer_a(); - - void uart_transmit_tick(); - void uart_receive_tick(); - - void system_timer_tick(); - - void do_i2c(); - - uint16_t m_io_regs[0x100]; - - uint8_t m_uart_rx_fifo[8]; - uint8_t m_uart_rx_fifo_start; - uint8_t m_uart_rx_fifo_end; - uint8_t m_uart_rx_fifo_count; - bool m_uart_rx_available; - bool m_uart_rx_irq; - bool m_uart_tx_irq; - - bool m_extint[2]; - - devcb_write16 m_porta_out; - devcb_write16 m_portb_out; - devcb_write16 m_portc_out; - devcb_read16 m_porta_in; - devcb_read16 m_portb_in; - devcb_read16 m_portc_in; - - devcb_read16 m_adc_in[2]; - - devcb_write8 m_eeprom_w; - devcb_read8 m_eeprom_r; - - devcb_write8 m_uart_tx; - - devcb_write8 m_chip_sel; - - uint16_t m_timer_a_preload; - uint16_t m_timer_b_preload; - uint16_t m_timer_b_divisor; - uint16_t m_timer_b_tick_rate; - - emu_timer *m_tmb1; - emu_timer *m_tmb2; - emu_timer *m_timer_src_ab; - emu_timer *m_timer_src_c; - - emu_timer *m_4khz_timer; - uint32_t m_2khz_divider; - uint32_t m_1khz_divider; - uint32_t m_4hz_divider; - - uint32_t m_uart_baud_rate; - emu_timer *m_uart_tx_timer; - emu_timer *m_uart_rx_timer; - - required_device<unsp_device> m_cpu; - required_device<screen_device> m_screen; - - devcb_read16 m_pal_read_cb; - - devcb_write_line m_timer_irq_cb; - devcb_write_line m_uart_adc_irq_cb; - devcb_write_line m_external_irq_cb; - devcb_write_line m_ffreq_tmr1_irq_cb; - devcb_write_line m_ffreq_tmr2_irq_cb; -}; - -class spg24x_io_device : public spg2xx_io_device -{ -public: - template <typename T, typename U> - spg24x_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, U &&screen_tag) - : spg24x_io_device(mconfig, tag, owner, clock) - { - m_cpu.set_tag(std::forward<T>(cpu_tag)); - m_screen.set_tag(std::forward<U>(screen_tag)); - } - - spg24x_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - -class spg28x_io_device : public spg2xx_io_device -{ -public: - template <typename T, typename U> - spg28x_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, U &&screen_tag) - : spg28x_io_device(mconfig, tag, owner, clock) - { - m_cpu.set_tag(std::forward<T>(cpu_tag)); - m_screen.set_tag(std::forward<U>(screen_tag)); - } - - spg28x_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual DECLARE_WRITE16_MEMBER(io_extended_w) override; -}; - -DECLARE_DEVICE_TYPE(SPG24X_IO, spg24x_io_device) -DECLARE_DEVICE_TYPE(SPG28X_IO, spg28x_io_device) - -#endif // MAME_MACHINE_SPG2XX_IO_H diff --git a/src/devices/machine/strata.cpp b/src/devices/machine/strata.cpp index df434adbd24..3f32b62739f 100644 --- a/src/devices/machine/strata.cpp +++ b/src/devices/machine/strata.cpp @@ -203,7 +203,7 @@ void strataflash_device::device_start() /* read a 8/16-bit word from FEEPROM */ -uint16_t strataflash_device::read8_16(offs_t offset, bus_width_t bus_width) +uint16_t strataflash_device::read8_16(address_space& space, offs_t offset, bus_width_t bus_width) { switch (bus_width) { @@ -393,7 +393,7 @@ uint16_t strataflash_device::read8_16(offs_t offset, bus_width_t bus_width) /* write a 8/16-bit word to FEEPROM */ -void strataflash_device::write8_16(offs_t offset, uint16_t data, bus_width_t bus_width) +void strataflash_device::write8_16(address_space& space, offs_t offset, uint16_t data, bus_width_t bus_width) { switch (bus_width) { @@ -634,31 +634,31 @@ void strataflash_device::write8_16(offs_t offset, uint16_t data, bus_width_t bus /* read a byte from FEEPROM */ -uint8_t strataflash_device::read8(offs_t offset) +READ8_MEMBER( strataflash_device::read8 ) { - return read8_16(offset, bw_8); + return read8_16(space, offset, bw_8); } /* Write a byte to FEEPROM */ -void strataflash_device::write8(offs_t offset, uint8_t data) +WRITE8_MEMBER( strataflash_device::write8 ) { - write8_16(offset, data, bw_8); + write8_16(space, offset, data, bw_8); } /* read a 16-bit word from FEEPROM */ -uint16_t strataflash_device::read16(offs_t offset) +READ16_MEMBER( strataflash_device::read16 ) { - return read8_16(offset, bw_16); + return read8_16(space, offset, bw_16); } /* Write a byte to FEEPROM */ -void strataflash_device::write16(offs_t offset, uint16_t data) +WRITE16_MEMBER( strataflash_device::write16 ) { - write8_16(offset, data, bw_16); + write8_16(space, offset, data, bw_16); } diff --git a/src/devices/machine/strata.h b/src/devices/machine/strata.h index 1a3acbbd9dd..26d8675f436 100644 --- a/src/devices/machine/strata.h +++ b/src/devices/machine/strata.h @@ -12,12 +12,12 @@ public: strataflash_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // 8-bit access - uint8_t read8(offs_t offset); - void write8(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read8 ); + DECLARE_WRITE8_MEMBER( write8 ); // 16-bit access - uint16_t read16(offs_t offset); - void write16(offs_t offset, uint16_t data); + DECLARE_READ16_MEMBER( read16 ); + DECLARE_WRITE16_MEMBER( write16 ); protected: // device-level overrides @@ -36,8 +36,8 @@ private: bw_16 }; - uint16_t read8_16(offs_t offset, bus_width_t bus_width); - void write8_16(offs_t offset, uint16_t data, bus_width_t bus_width); + uint16_t read8_16(address_space& space, offs_t offset, bus_width_t bus_width); + void write8_16(address_space& space, offs_t offset, uint16_t data, bus_width_t bus_width); enum fm_mode_t { diff --git a/src/devices/machine/stvcd.cpp b/src/devices/machine/stvcd.cpp index c4b7ada9b9f..09323a7deea 100644 --- a/src/devices/machine/stvcd.cpp +++ b/src/devices/machine/stvcd.cpp @@ -78,17 +78,17 @@ stvcd_device::stvcd_device(const machine_config &mconfig, const char *tag, devic { } -void stvcd_device::device_add_mconfig(machine_config &config) -{ - CDROM(config, "cdrom").set_interface("sat_cdrom"); +MACHINE_CONFIG_START(stvcd_device::device_add_mconfig) + MCFG_CDROM_ADD("cdrom") + MCFG_CDROM_INTERFACE("sat_cdrom") - TIMER(config, m_sector_timer).configure_generic(FUNC(stvcd_device::stv_sector_cb)); - TIMER(config, m_sh1_timer).configure_generic(FUNC(stvcd_device::stv_sh1_sim)); + MCFG_TIMER_DRIVER_ADD("sector_timer", stvcd_device, stv_sector_cb) + MCFG_TIMER_DRIVER_ADD("sh1_cmd", stvcd_device, stv_sh1_sim) - CDDA(config, m_cdda); - m_cdda->add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0); - m_cdda->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1); -} + MCFG_DEVICE_ADD("cdda", CDDA) + MCFG_MIXER_ROUTE(0, *this, 1.0, 0) + MCFG_MIXER_ROUTE(1, *this, 1.0, 1) +MACHINE_CONFIG_END void stvcd_device::device_start() { diff --git a/src/devices/machine/tc009xlvc.cpp b/src/devices/machine/tc009xlvc.cpp index a870dee98a6..4624e3fc79d 100644 --- a/src/devices/machine/tc009xlvc.cpp +++ b/src/devices/machine/tc009xlvc.cpp @@ -171,7 +171,7 @@ void tc0091lvc_device::tc0091lvc_map8(address_map &map) tc0091lvc_device::tc0091lvc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, TC0091LVC, tag, owner, clock) , device_memory_interface(mconfig, *this) - , m_space_config("tc0091lvc", ENDIANNESS_LITTLE, 8,20, 0, address_map_constructor(FUNC(tc0091lvc_device::tc0091lvc_map8), this)) + , m_space_config("tc0091lvc", ENDIANNESS_LITTLE, 8,20, 0, address_map_constructor(), address_map_constructor(FUNC(tc0091lvc_device::tc0091lvc_map8), this)) , m_gfxdecode(*this, finder_base::DUMMY_TAG) { } diff --git a/src/devices/machine/terminal.cpp b/src/devices/machine/terminal.cpp index c2e5c5be205..be9b501c687 100644 --- a/src/devices/machine/terminal.cpp +++ b/src/devices/machine/terminal.cpp @@ -326,22 +326,21 @@ void generic_terminal_device::kbd_put(u8 data) VIDEO HARDWARE ***************************************************************************/ -void generic_terminal_device::device_add_mconfig(machine_config &config) -{ - screen_device &screen(SCREEN(config, TERMINAL_SCREEN_TAG, SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(50); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ - screen.set_size(generic_terminal_device::TERMINAL_WIDTH*8, generic_terminal_device::TERMINAL_HEIGHT*10); - screen.set_visarea(0, generic_terminal_device::TERMINAL_WIDTH*8-1, 0, generic_terminal_device::TERMINAL_HEIGHT*10-1); - screen.set_screen_update(FUNC(generic_terminal_device::update)); +MACHINE_CONFIG_START(generic_terminal_device::device_add_mconfig) + MCFG_SCREEN_ADD(TERMINAL_SCREEN_TAG, RASTER) + MCFG_SCREEN_REFRESH_RATE(50) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ + MCFG_SCREEN_SIZE(generic_terminal_device::TERMINAL_WIDTH*8, generic_terminal_device::TERMINAL_HEIGHT*10) + MCFG_SCREEN_VISIBLE_AREA(0, generic_terminal_device::TERMINAL_WIDTH*8-1, 0, generic_terminal_device::TERMINAL_HEIGHT*10-1) + MCFG_SCREEN_UPDATE_DEVICE(DEVICE_SELF, generic_terminal_device, update) generic_keyboard_device &keyboard(GENERIC_KEYBOARD(config, KEYBOARD_TAG, 0)); keyboard.set_keyboard_callback(FUNC(generic_terminal_device::kbd_put)); SPEAKER(config, "bell").front_center(); - BEEP(config, m_beeper, 2'000); - m_beeper->add_route(ALL_OUTPUTS, "bell", 0.25); -} + MCFG_DEVICE_ADD("beeper", BEEP, 2'000) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "bell", 0.25) +MACHINE_CONFIG_END void generic_terminal_device::device_start() { diff --git a/src/devices/machine/terminal.h b/src/devices/machine/terminal.h index dab8bd40578..bf2f81c07f7 100644 --- a/src/devices/machine/terminal.h +++ b/src/devices/machine/terminal.h @@ -36,7 +36,7 @@ public: } void set_keyboard_callback(generic_keyboard_device::output_delegate callback) { m_keyboard_cb = callback; } - void write(u8 data) { term_write(data); } + DECLARE_WRITE8_MEMBER(write) { term_write(data); } void kbd_put(u8 data); diff --git a/src/devices/machine/ticket.h b/src/devices/machine/ticket.h index 7330ad3cb74..813e27b95c1 100644 --- a/src/devices/machine/ticket.h +++ b/src/devices/machine/ticket.h @@ -21,6 +21,22 @@ DECLARE_DEVICE_TYPE(TICKET_DISPENSER, ticket_dispenser_device) DECLARE_DEVICE_TYPE(HOPPER, hopper_device) + +//************************************************************************** +// DEVICE CONFIGURATION MACROS +//************************************************************************** + +// add/remove dispensers +#define MCFG_TICKET_DISPENSER_ADD(_tag, _period_in_msec, _motor_sense, _status_sense) \ + MCFG_DEVICE_ADD(_tag, TICKET_DISPENSER, 0) \ + downcast<ticket_dispenser_device &>(*device).set_period(_period_in_msec); \ + downcast<ticket_dispenser_device &>(*device).set_senses(_motor_sense, _status_sense, false); + +#define MCFG_HOPPER_ADD(_tag, _period_in_msec, _motor_sense, _status_sense) \ + MCFG_DEVICE_ADD(_tag, TICKET_DISPENSER, 0) \ + downcast<ticket_dispenser_device &>(*device).set_period(_period_in_msec); \ + downcast<ticket_dispenser_device &>(*device).set_senses(_motor_sense, _status_sense, true); + //************************************************************************** // CONSTANTS //************************************************************************** diff --git a/src/devices/machine/timekpr.cpp b/src/devices/machine/timekpr.cpp index f7cfed5451c..7dddede2c05 100644 --- a/src/devices/machine/timekpr.cpp +++ b/src/devices/machine/timekpr.cpp @@ -37,47 +37,53 @@ DEFINE_DEVICE_TYPE(MK48T12, mk48t12_device, "mk48t12", "MK48T12 Timekeeper") MACROS ***************************************************************************/ -#define MASK_SECONDS (0x7f) -#define MASK_MINUTES (0x7f) -#define MASK_HOURS (0x3f) -#define MASK_DAY (0x07) -#define MASK_DATE (0x3f) -#define MASK_MONTH (0x1f) -#define MASK_YEAR (0xff) -#define MASK_CENTURY (0xff) +#define MASK_SECONDS ( 0x7f ) +#define MASK_MINUTES ( 0x7f ) +#define MASK_HOURS ( 0x3f ) +#define MASK_DAY ( 0x07 ) +#define MASK_DATE ( 0x3f ) +#define MASK_MONTH ( 0x1f ) +#define MASK_YEAR ( 0xff ) +#define MASK_CENTURY ( 0xff ) -#define CONTROL_W (0x80) -#define CONTROL_R (0x40) -#define CONTROL_S (0x20) /* not emulated */ -#define CONTROL_CALIBRATION (0x1f) /* not emulated */ +#define CONTROL_W ( 0x80 ) +#define CONTROL_R ( 0x40 ) +#define CONTROL_S ( 0x20 ) /* not emulated */ +#define CONTROL_CALIBRATION ( 0x1f ) /* not emulated */ -#define SECONDS_ST (0x80) +#define SECONDS_ST ( 0x80 ) -#define DAY_FT (0x40) /* M48T37 - not emulated */ -#define DAY_CEB (0x20) /* M48T35/M48T58 */ -#define DAY_CB (0x10) /* M48T35/M48T58 */ +#define DAY_FT ( 0x40 ) /* M48T37 - not emulated */ +#define DAY_CEB ( 0x20 ) /* M48T35/M48T58 */ +#define DAY_CB ( 0x10 ) /* M48T35/M48T58 */ -#define DATE_BLE (0x80) /* M48T58: not emulated */ -#define DATE_BL (0x40) /* M48T58: not emulated */ +#define DATE_BLE ( 0x80 ) /* M48T58: not emulated */ +#define DATE_BL ( 0x40 ) /* M48T58: not emulated */ -#define FLAGS_BL (0x10) /* MK48T08/M48T37: not emulated */ -#define FLAGS_AF (0x40) /* M48T37: not emulated */ -#define FLAGS_WDF (0x80) /* M48T37 */ +#define FLAGS_BL ( 0x10 ) /* MK48T08/M48T37: not emulated */ +#define FLAGS_AF ( 0x40 ) /* M48T37: not emulated */ +#define FLAGS_WDF ( 0x80 ) /* M48T37 */ /*************************************************************************** INLINE FUNCTIONS ***************************************************************************/ -inline void counter_to_ram(u8 *data, s32 offset, u8 counter) +static void counter_to_ram( uint8_t *data, int offset, int counter ) { - if (offset >= 0) - data[offset] = counter; + if( offset >= 0 ) + { + data[ offset ] = counter; + } } -inline int counter_from_ram(u8 const *data, s32 offset, u8 unmap = 0) +static int counter_from_ram( uint8_t *data, int offset ) { - return (offset >= 0) ? data[offset] : unmap; + if( offset >= 0 ) + { + return data[ offset ]; + } + return 0; } //************************************************************************** @@ -88,7 +94,7 @@ inline int counter_from_ram(u8 const *data, s32 offset, u8 unmap = 0) // timekeeper_device_config - constructor //------------------------------------------------- -timekeeper_device::timekeeper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 size) +timekeeper_device::timekeeper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int size) : device_t(mconfig, type, tag, owner, clock) , device_nvram_interface(mconfig, *this) , m_reset_cb(*this) @@ -98,7 +104,7 @@ timekeeper_device::timekeeper_device(const machine_config &mconfig, device_type { } -m48t02_device::m48t02_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +m48t02_device::m48t02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, M48T02, tag, owner, clock, 0x800) { m_offset_watchdog = -1; @@ -114,7 +120,7 @@ m48t02_device::m48t02_device(const machine_config &mconfig, const char *tag, dev m_offset_flags = -1; } -m48t35_device::m48t35_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +m48t35_device::m48t35_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, M48T35, tag, owner, clock, 0x8000) { m_offset_watchdog = -1; @@ -130,7 +136,7 @@ m48t35_device::m48t35_device(const machine_config &mconfig, const char *tag, dev m_offset_flags = -1; } -m48t37_device::m48t37_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +m48t37_device::m48t37_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, M48T37, tag, owner, clock, 0x8000) { m_offset_watchdog = 0x7ff7; @@ -146,7 +152,7 @@ m48t37_device::m48t37_device(const machine_config &mconfig, const char *tag, dev m_offset_flags = 0x7ff0; } -m48t58_device::m48t58_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +m48t58_device::m48t58_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, M48T58, tag, owner, clock, 0x2000) { m_offset_watchdog = -1; @@ -162,7 +168,7 @@ m48t58_device::m48t58_device(const machine_config &mconfig, const char *tag, dev m_offset_flags = -1; } -mk48t08_device::mk48t08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +mk48t08_device::mk48t08_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, MK48T08, tag, owner, clock, 0x2000) { m_offset_watchdog = -1; @@ -178,7 +184,7 @@ mk48t08_device::mk48t08_device(const machine_config &mconfig, const char *tag, d m_offset_flags = 0x1ff0; } -mk48t12_device::mk48t12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +mk48t12_device::mk48t12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : timekeeper_device(mconfig, MK48T12, tag, owner, clock, 0x800) { m_offset_watchdog = -1; @@ -208,27 +214,27 @@ void timekeeper_device::device_start() machine().base_datetime(systime); m_control = 0; - m_seconds = time_helper::make_bcd(systime.local_time.second); - m_minutes = time_helper::make_bcd(systime.local_time.minute); - m_hours = time_helper::make_bcd(systime.local_time.hour); - m_day = time_helper::make_bcd(systime.local_time.weekday + 1); - m_date = time_helper::make_bcd(systime.local_time.mday); - m_month = time_helper::make_bcd(systime.local_time.month + 1); - m_year = time_helper::make_bcd(systime.local_time.year % 100); - m_century = time_helper::make_bcd(systime.local_time.year / 100); - m_data.resize(m_size); - - save_item(NAME(m_control)); - save_item(NAME(m_seconds)); - save_item(NAME(m_minutes)); - save_item(NAME(m_hours)); - save_item(NAME(m_day)); - save_item(NAME(m_date)); - save_item(NAME(m_month)); - save_item(NAME(m_year)); - save_item(NAME(m_century)); - save_item(NAME(m_data)); - save_item(NAME(m_watchdog_delay)); + m_seconds = time_helper::make_bcd( systime.local_time.second ); + m_minutes = time_helper::make_bcd( systime.local_time.minute ); + m_hours = time_helper::make_bcd( systime.local_time.hour ); + m_day = time_helper::make_bcd( systime.local_time.weekday + 1 ); + m_date = time_helper::make_bcd( systime.local_time.mday ); + m_month = time_helper::make_bcd( systime.local_time.month + 1 ); + m_year = time_helper::make_bcd( systime.local_time.year % 100 ); + m_century = time_helper::make_bcd( systime.local_time.year / 100 ); + m_data.resize( m_size ); + + save_item( NAME(m_control) ); + save_item( NAME(m_seconds) ); + save_item( NAME(m_minutes) ); + save_item( NAME(m_hours) ); + save_item( NAME(m_day) ); + save_item( NAME(m_date) ); + save_item( NAME(m_month) ); + save_item( NAME(m_year) ); + save_item( NAME(m_century) ); + save_item( NAME(m_data) ); + save_item( NAME(m_watchdog_delay)); emu_timer *timer = timer_alloc(); timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1)); @@ -248,98 +254,98 @@ void timekeeper_device::device_reset() { } void timekeeper_device::counters_to_ram() { - counter_to_ram(&m_data[0], m_offset_control, m_control); - counter_to_ram(&m_data[0], m_offset_seconds, m_seconds); - counter_to_ram(&m_data[0], m_offset_minutes, m_minutes); - counter_to_ram(&m_data[0], m_offset_hours, m_hours); - counter_to_ram(&m_data[0], m_offset_day, m_day); - counter_to_ram(&m_data[0], m_offset_date, m_date); - counter_to_ram(&m_data[0], m_offset_month, m_month); - counter_to_ram(&m_data[0], m_offset_year, m_year); - counter_to_ram(&m_data[0], m_offset_century, m_century); + counter_to_ram( &m_data[0], m_offset_control, m_control ); + counter_to_ram( &m_data[0], m_offset_seconds, m_seconds ); + counter_to_ram( &m_data[0], m_offset_minutes, m_minutes ); + counter_to_ram( &m_data[0], m_offset_hours, m_hours ); + counter_to_ram( &m_data[0], m_offset_day, m_day ); + counter_to_ram( &m_data[0], m_offset_date, m_date ); + counter_to_ram( &m_data[0], m_offset_month, m_month ); + counter_to_ram( &m_data[0], m_offset_year, m_year ); + counter_to_ram( &m_data[0], m_offset_century, m_century ); } void timekeeper_device::counters_from_ram() { - m_control = counter_from_ram(&m_data[0], m_offset_control); - m_seconds = counter_from_ram(&m_data[0], m_offset_seconds); - m_minutes = counter_from_ram(&m_data[0], m_offset_minutes); - m_hours = counter_from_ram(&m_data[0], m_offset_hours); - m_day = counter_from_ram(&m_data[0], m_offset_day); - m_date = counter_from_ram(&m_data[0], m_offset_date); - m_month = counter_from_ram(&m_data[0], m_offset_month); - m_year = counter_from_ram(&m_data[0], m_offset_year); - m_century = counter_from_ram(&m_data[0], m_offset_century); + m_control = counter_from_ram( &m_data[0], m_offset_control ); + m_seconds = counter_from_ram( &m_data[0], m_offset_seconds ); + m_minutes = counter_from_ram( &m_data[0], m_offset_minutes ); + m_hours = counter_from_ram( &m_data[0], m_offset_hours ); + m_day = counter_from_ram( &m_data[0], m_offset_day ); + m_date = counter_from_ram( &m_data[0], m_offset_date ); + m_month = counter_from_ram( &m_data[0], m_offset_month ); + m_year = counter_from_ram( &m_data[0], m_offset_year ); + m_century = counter_from_ram( &m_data[0], m_offset_century ); } void timekeeper_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { LOGMASKED(LOG_TICKS, "Tick\n"); - if ((m_seconds & SECONDS_ST) != 0 || - (m_control & CONTROL_W) != 0) + if( ( m_seconds & SECONDS_ST ) != 0 || + ( m_control & CONTROL_W ) != 0 ) { logerror("No Tick\n"); return; } - int carry = time_helper::inc_bcd(&m_seconds, MASK_SECONDS, 0x00, 0x59); - if (carry) + int carry = time_helper::inc_bcd( &m_seconds, MASK_SECONDS, 0x00, 0x59 ); + if( carry ) { - carry = time_helper::inc_bcd(&m_minutes, MASK_MINUTES, 0x00, 0x59); + carry = time_helper::inc_bcd( &m_minutes, MASK_MINUTES, 0x00, 0x59 ); } - if (carry) + if( carry ) { - carry = time_helper::inc_bcd(&m_hours, MASK_HOURS, 0x00, 0x23); + carry = time_helper::inc_bcd( &m_hours, MASK_HOURS, 0x00, 0x23 ); } - if (carry) + if( carry ) { - u8 maxdays; - static const u8 daysinmonth[] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 }; + uint8_t maxdays; + static const uint8_t daysinmonth[] = { 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31 }; - time_helper::inc_bcd(&m_day, MASK_DAY, 0x01, 0x07); + time_helper::inc_bcd( &m_day, MASK_DAY, 0x01, 0x07 ); - u8 month = time_helper::from_bcd(m_month); - u8 year = time_helper::from_bcd(m_year); + uint8_t month = time_helper::from_bcd( m_month ); + uint8_t year = time_helper::from_bcd( m_year ); - if (month == 2 && (year % 4) == 0) + if( month == 2 && ( year % 4 ) == 0 ) { maxdays = 0x29; } - else if (month >= 1 && month <= 12) + else if( month >= 1 && month <= 12 ) { - maxdays = daysinmonth[month - 1]; + maxdays = daysinmonth[ month - 1 ]; } else { maxdays = 0x31; } - carry = time_helper::inc_bcd(&m_date, MASK_DATE, 0x01, maxdays); + carry = time_helper::inc_bcd( &m_date, MASK_DATE, 0x01, maxdays ); } - if (carry) + if( carry ) { - carry = time_helper::inc_bcd(&m_month, MASK_MONTH, 0x01, 0x12); + carry = time_helper::inc_bcd( &m_month, MASK_MONTH, 0x01, 0x12 ); } - if (carry) + if( carry ) { - carry = time_helper::inc_bcd(&m_year, MASK_YEAR, 0x00, 0x99); + carry = time_helper::inc_bcd( &m_year, MASK_YEAR, 0x00, 0x99 ); } - if (carry) + if( carry ) { - carry = time_helper::inc_bcd(&m_century, MASK_CENTURY, 0x00, 0x99); + carry = time_helper::inc_bcd( &m_century, MASK_CENTURY, 0x00, 0x99 ); - if (type() == M48T35 || - type() == M48T58) + if( type() == M48T35 || + type() == M48T58 ) { - if ((m_day & DAY_CEB) != 0) + if( ( m_day & DAY_CEB ) != 0 ) { m_day ^= DAY_CB; } } } - if ((m_control & CONTROL_R) == 0) + if( ( m_control & CONTROL_R ) == 0 ) { counters_to_ram(); } @@ -350,59 +356,57 @@ TIMER_CALLBACK_MEMBER(timekeeper_device::watchdog_callback) // Set Flag m_data[m_offset_flags] |= FLAGS_WDF; // WDS (bit 7) selects callback - if (m_data[m_offset_watchdog] & 0x80) - { + if (m_data[m_offset_watchdog] & 0x80) { // Clear watchdog register m_data[m_offset_watchdog] = 0; m_reset_cb(ASSERT_LINE); } - else + else { m_irq_cb(ASSERT_LINE); - + } logerror("watchdog_callback: WD Control: %02x WD Flags: %02x\n", m_data[m_offset_watchdog], m_data[m_offset_flags]); } -void timekeeper_device::watchdog_write(u8 data) +WRITE8_MEMBER(timekeeper_device::watchdog_write) { - if ((m_data[m_offset_watchdog] & 0x7f) != 0) + if ((m_data[m_offset_watchdog] & 0x7f) != 0) { m_watchdog_timer->adjust(m_watchdog_delay); + } } -void timekeeper_device::write(offs_t offset, u8 data) +WRITE8_MEMBER( timekeeper_device::write ) { LOGMASKED(LOG_GENERAL, "timekeeper_device::write: %04x = %02x\n", offset, data); - if (offset == m_offset_control) + if( offset == m_offset_control ) { - if ((m_control & CONTROL_W) != 0 && - (data & CONTROL_W) == 0) + if( ( m_control & CONTROL_W ) != 0 && + ( data & CONTROL_W ) == 0 ) { counters_from_ram(); } - if ((m_control & CONTROL_R) != 0 && - (data & CONTROL_W) == 0) + if( ( m_control & CONTROL_R ) != 0 && + ( data & CONTROL_W ) == 0 ) { counters_to_ram(); } m_control = data; } - else if (offset == m_offset_day) + else if( offset == m_offset_day ) { - if (type() == M48T35 || - type() == M48T58) + if( type() == M48T35 || + type() == M48T58 ) { - m_day = (m_day & ~DAY_CEB) | (data & DAY_CEB); + m_day = ( m_day & ~DAY_CEB ) | ( data & DAY_CEB ); } } else if (offset == m_offset_watchdog && type() == M48T37) { - if ((data & 0x7f) == 0) - { + if ((data & 0x7f) == 0) { m_watchdog_timer->adjust(attotime::never); } - else - { + else { // Calculate the time unit m_watchdog_delay = attotime::from_usec(62500 << (2 * (data & 0x3))); // Adjust by multiplier @@ -412,17 +416,17 @@ void timekeeper_device::write(offs_t offset, u8 data) } } - m_data[offset] = data; + m_data[ offset ] = data; } -u8 timekeeper_device::read(offs_t offset) +READ8_MEMBER( timekeeper_device::read ) { - u8 result = m_data[offset]; - if (offset == m_offset_date && type() == M48T58) + uint8_t result = m_data[ offset ]; + if( offset == m_offset_date && type() == M48T58 ) { result &= ~DATE_BL; } - else if (offset == m_offset_flags && type() == M48T37) + else if( offset == m_offset_flags && type() == M48T37 ) { // Clear the watchdog flag m_data[m_offset_flags] &= ~FLAGS_WDF; @@ -443,15 +447,15 @@ void timekeeper_device::nvram_default() { if (m_default_data.found()) { - memcpy(&m_data[0], m_default_data, m_size); + memcpy( &m_data[0], m_default_data, m_size ); } else { - memset(&m_data[0], 0xff, m_data.size()); + memset( &m_data[0], 0xff, m_data.size()); } - if (m_offset_flags >= 0) - m_data[m_offset_flags] = 0; + if ( m_offset_flags >= 0 ) + m_data[ m_offset_flags ] = 0; counters_to_ram(); } @@ -463,7 +467,7 @@ void timekeeper_device::nvram_default() void timekeeper_device::nvram_read(emu_file &file) { - file.read(&m_data[0], m_size); + file.read( &m_data[0], m_size ); counters_to_ram(); } @@ -476,5 +480,5 @@ void timekeeper_device::nvram_read(emu_file &file) void timekeeper_device::nvram_write(emu_file &file) { - file.write(&m_data[0], m_size); + file.write( &m_data[0], m_size ); } diff --git a/src/devices/machine/timekpr.h b/src/devices/machine/timekpr.h index def60c02059..4742a1b1ae8 100644 --- a/src/devices/machine/timekpr.h +++ b/src/devices/machine/timekpr.h @@ -32,16 +32,16 @@ class timekeeper_device : public device_t, public device_nvram_interface { public: - void write(offs_t offset, u8 data); - u8 read(offs_t offset); - void watchdog_write(u8 data = 0); + DECLARE_WRITE8_MEMBER( write ); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER(watchdog_write); auto reset_cb() { return m_reset_cb.bind(); } auto irq_cb() { return m_irq_cb.bind(); } protected: // construction/destruction - timekeeper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 size); + timekeeper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int size); // device-level overrides virtual void device_start() override; @@ -62,70 +62,70 @@ private: void counters_from_ram(); // internal state - u8 m_control; - u8 m_seconds; - u8 m_minutes; - u8 m_hours; - u8 m_day; - u8 m_date; - u8 m_month; - u8 m_year; - u8 m_century; - - std::vector<u8> m_data; - optional_region_ptr<u8> m_default_data; + uint8_t m_control; + uint8_t m_seconds; + uint8_t m_minutes; + uint8_t m_hours; + uint8_t m_day; + uint8_t m_date; + uint8_t m_month; + uint8_t m_year; + uint8_t m_century; + + std::vector<uint8_t> m_data; + optional_region_ptr<uint8_t> m_default_data; emu_timer* m_watchdog_timer; attotime m_watchdog_delay; protected: - u32 const m_size; - s32 m_offset_watchdog; - s32 m_offset_control; - s32 m_offset_seconds; - s32 m_offset_minutes; - s32 m_offset_hours; - s32 m_offset_day; - s32 m_offset_date; - s32 m_offset_month; - s32 m_offset_year; - s32 m_offset_century; - s32 m_offset_flags; + int const m_size; + int m_offset_watchdog; + int m_offset_control; + int m_offset_seconds; + int m_offset_minutes; + int m_offset_hours; + int m_offset_day; + int m_offset_date; + int m_offset_month; + int m_offset_year; + int m_offset_century; + int m_offset_flags; }; class m48t02_device : public timekeeper_device { public: - m48t02_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + m48t02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); }; class m48t35_device : public timekeeper_device { public: - m48t35_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + m48t35_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); }; class m48t37_device : public timekeeper_device { public: - m48t37_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + m48t37_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); }; class m48t58_device : public timekeeper_device { public: - m48t58_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + m48t58_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); }; class mk48t08_device : public timekeeper_device { public: - mk48t08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + mk48t08_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); }; class mk48t12_device : public timekeeper_device { public: - mk48t12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + mk48t12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); }; // device type definition diff --git a/src/devices/machine/timer.h b/src/devices/machine/timer.h index 944db93c1e5..e27c8a8cc53 100644 --- a/src/devices/machine/timer.h +++ b/src/devices/machine/timer.h @@ -23,6 +23,44 @@ #define TIMER_DEVICE_CALLBACK_MEMBER(name) void name(timer_device &timer, void *ptr, s32 param) //************************************************************************** +// TIMER DEVICE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_TIMER_ADD_NONE(_tag) \ + MCFG_DEVICE_ADD(_tag, TIMER, 0) \ + downcast<timer_device &>(*device).configure_generic(timer_device::expired_delegate()); +#define MCFG_TIMER_DRIVER_ADD(_tag, _class, _callback) \ + MCFG_DEVICE_ADD(_tag, TIMER, 0) \ + downcast<timer_device &>(*device).configure_generic(timer_device::expired_delegate(&_class::_callback, #_class "::" #_callback, nullptr, (_class *)nullptr)); +#define MCFG_TIMER_DEVICE_ADD(_tag, _devtag, _class, _callback) \ + MCFG_DEVICE_ADD(_tag, TIMER, 0) \ + downcast<timer_device &>(*device).configure_generic(timer_device::expired_delegate(&_class::_callback, #_class "::" #_callback, _devtag, (_class *)nullptr)); +#define MCFG_TIMER_DRIVER_ADD_PERIODIC(_tag, _class, _callback, _period) \ + MCFG_DEVICE_ADD(_tag, TIMER, 0) \ + downcast<timer_device &>(*device).configure_periodic(timer_device::expired_delegate(&_class::_callback, #_class "::" #_callback, nullptr, (_class *)nullptr), _period); +#define MCFG_TIMER_DEVICE_ADD_PERIODIC(_tag, _devtag, _class, _callback, _period) \ + MCFG_DEVICE_ADD(_tag, TIMER, 0) \ + downcast<timer_device &>(*device).configure_periodic(timer_device::expired_delegate(&_class::_callback, #_class "::" #_callback, _devtag, (_class *)nullptr), _period); +#define MCFG_TIMER_DRIVER_ADD_SCANLINE(_tag, _class, _callback, _screen, _first_vpos, _increment) \ + MCFG_DEVICE_ADD(_tag, TIMER, 0) \ + downcast<timer_device &>(*device).configure_scanline(timer_device::expired_delegate(&_class::_callback, #_class "::" #_callback, nullptr, (_class *)nullptr), _screen, _first_vpos, _increment); +#define MCFG_TIMER_DEVICE_ADD_SCANLINE(_tag, _devtag, _class, _callback, _screen, _first_vpos, _increment) \ + MCFG_DEVICE_ADD(_tag, TIMER, 0) \ + downcast<timer_device &>(*device).configure_scanline(timer_device::expired_delegate(&_class::_callback, #_class "::" #_callback, _devtag, (_class *)nullptr), _screen, _first_vpos, _increment); +#define MCFG_TIMER_MODIFY(_tag) \ + MCFG_DEVICE_MODIFY(_tag) + +#define MCFG_TIMER_DRIVER_CALLBACK(_class, _callback) \ + downcast<timer_device &>(*device).set_callback(timer_device::expired_delegate(&_class::_callback, #_class "::" #_callback, nullptr, (_class *)nullptr)); +#define MCFG_TIMER_START_DELAY(_start_delay) \ + downcast<timer_device &>(*device).set_start_delay(_start_delay); +#define MCFG_TIMER_PARAM(_param) \ + downcast<timer_device &>(*device).config_param(_param); +#define MCFG_TIMER_PTR(_ptr) \ + downcast<timer_device &>(*device).set_ptr((void *)(_ptr)); + + +//************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -48,11 +86,6 @@ public: configure_generic(expired_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr))); } - template <class FunctionClass> void configure_generic(const char *devname, void (FunctionClass::*callback)(timer_device &, void *, s32), const char *name) - { - configure_generic(expired_delegate(callback, name, devname, static_cast<FunctionClass *>(nullptr))); - } - template <typename Object> void configure_periodic(Object &&cb, const attotime &period) { m_type = TIMER_TYPE_PERIODIC; @@ -65,12 +98,6 @@ public: configure_periodic(expired_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr)), period); } - template <class FunctionClass> void configure_periodic(const char *devname, void (FunctionClass::*callback)(timer_device &, void *, s32), - const char *name, const attotime &period) - { - configure_periodic(expired_delegate(callback, name, devname, static_cast<FunctionClass *>(nullptr)), period); - } - template <typename Object> void configure_scanline(Object &&cb, const char *screen, int first_vpos, int increment) { m_type = TIMER_TYPE_SCANLINE; @@ -111,18 +138,13 @@ public: // adjustments void reset() { adjust(attotime::never, 0, attotime::never); } - void adjust(const attotime &duration, s32 param = 0, const attotime &period = attotime::never) const - { - assert(m_type == TIMER_TYPE_GENERIC); - m_timer->adjust(duration, param, period); - } + void adjust(const attotime &duration, s32 param = 0, const attotime &period = attotime::never) const { assert(m_type == TIMER_TYPE_GENERIC); m_timer->adjust(duration, param, period); } // timing information attotime time_elapsed() const { return m_timer->elapsed(); } attotime time_left() const { return m_timer->remaining(); } attotime start_time() const { return m_timer->start(); } attotime fire_time() const { return m_timer->expire(); } - attotime period() const { return m_timer ? m_timer->period() : m_period; } private: // device-level overrides @@ -141,7 +163,7 @@ private: // configuration data timer_type m_type; // type of timer - expired_delegate m_callback; // the timer's callback function + expired_delegate m_callback; // the timer's callback function void * m_ptr; // the pointer parameter passed to the timer callback // periodic timers only diff --git a/src/devices/machine/tmp68301.cpp b/src/devices/machine/tmp68301.cpp index 1eea072c64a..2add964e4e5 100644 --- a/src/devices/machine/tmp68301.cpp +++ b/src/devices/machine/tmp68301.cpp @@ -23,8 +23,7 @@ DEFINE_DEVICE_TYPE(TMP68301, tmp68301_device, "tmp68301", "Toshiba TMP68301") void tmp68301_device::tmp68301_regs(address_map &map) { - map(0x000, 0x3ff).rw(FUNC(tmp68301_device::regs_r), FUNC(tmp68301_device::regs_w)); - +// AM_RANGE(0x000,0x3ff) AM_RAM map(0x080, 0x093).rw(FUNC(tmp68301_device::icr_r), FUNC(tmp68301_device::icr_w)).umask16(0x00ff); map(0x094, 0x095).rw(FUNC(tmp68301_device::imr_r), FUNC(tmp68301_device::imr_w)); @@ -135,7 +134,9 @@ WRITE8_MEMBER(tmp68301_device::icr_w) } tmp68301_device::tmp68301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : m68000_device(mconfig, TMP68301, tag, owner, clock), + : device_t(mconfig, TMP68301, tag, owner, clock), + device_memory_interface(mconfig, *this), + m_cpu(*this, finder_base::DUMMY_TAG), m_in_parallel_cb(*this), m_out_parallel_cb(*this), m_ipl(0), @@ -144,7 +145,8 @@ tmp68301_device::tmp68301_device(const machine_config &mconfig, const char *tag, m_iisr(0), m_scr(0), m_pdir(0), - m_pdr(0) + m_pdr(0), + m_space_config("regs", ENDIANNESS_LITTLE, 16, 10, 0, address_map_constructor(), address_map_constructor(FUNC(tmp68301_device::tmp68301_regs), this)) { memset(m_regs, 0, sizeof(m_regs)); memset(m_icr, 0, sizeof(m_icr)); @@ -157,17 +159,13 @@ tmp68301_device::tmp68301_device(const machine_config &mconfig, const char *tag, void tmp68301_device::device_start() { - m68000_device::device_start(); - - for (int i = 0; i < 3; i++) + int i; + for (i = 0; i < 3; i++) m_tmp68301_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(tmp68301_device::timer_callback), this)); m_in_parallel_cb.resolve_safe(0); m_out_parallel_cb.resolve_safe(); - m_program->install_device(0xfffc00, 0xffffff, *this, &tmp68301_device::tmp68301_regs); - m_int_ack_callback = device_irq_acknowledge_delegate(FUNC(tmp68301_device::irq_callback), this); - save_item(NAME(m_regs)); save_item(NAME(m_icr)); save_item(NAME(m_ipl)); @@ -185,8 +183,6 @@ void tmp68301_device::device_start() void tmp68301_device::device_reset() { - m68000_device::device_reset(); - m_ipr = 0; m_iisr = 0; m_imr = 0x7f7; // mask all irqs @@ -194,10 +190,40 @@ void tmp68301_device::device_reset() update_ipl(); } +//------------------------------------------------- +// memory_space_config - return a description of +// any address spaces owned by this device +//------------------------------------------------- + +device_memory_interface::space_config_vector tmp68301_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(0, &m_space_config) + }; +} + //************************************************************************** // INLINE HELPERS //************************************************************************** +//------------------------------------------------- +// read_byte - read a byte at the given address +//------------------------------------------------- + +inline uint16_t tmp68301_device::read_word(offs_t address) +{ + return space(0).read_word(address << 1); +} + +//------------------------------------------------- +// write_byte - write a byte at the given address +//------------------------------------------------- + +inline void tmp68301_device::write_word(offs_t address, uint16_t data) +{ + space(0).write_word(address << 1, data); +} + IRQ_CALLBACK_MEMBER(tmp68301_device::irq_callback) { uint8_t IVNR = m_regs[0x9a/2] & 0xe0; // Interrupt Vector Number Register (IVNR) @@ -286,7 +312,7 @@ void tmp68301_device::update_timer(int i) { int scale = (TCR & 0x3c00)>>10; // P4..1 if (scale > 8) scale = 8; - duration = attotime::from_hz(unscaled_clock()) * ((1 << scale) * max); + duration = attotime::from_hz(m_cpu->unscaled_clock()) * ((1 << scale) * max); } break; } @@ -317,9 +343,9 @@ void tmp68301_device::update_ipl() if (new_ipl != m_ipl) { if (m_ipl != 0) - set_input_line(m_ipl, CLEAR_LINE); + m_cpu->set_input_line(m_ipl, CLEAR_LINE); if (new_ipl != 0) - set_input_line(new_ipl, ASSERT_LINE); + m_cpu->set_input_line(new_ipl, ASSERT_LINE); m_ipl = new_ipl; } @@ -340,16 +366,18 @@ uint8_t tmp68301_device::serial_interrupt_cause(int channel) READ16_MEMBER( tmp68301_device::regs_r ) { - return m_regs[offset]; + return read_word(offset); } WRITE16_MEMBER( tmp68301_device::regs_w ) { COMBINE_DATA(&m_regs[offset]); + write_word(offset,m_regs[offset]); + if (!ACCESSING_BITS_0_7) return; -// logerror("CPU #0 PC %06X: TMP68301 Reg %04X<-%04X & %04X\n", >pc(),offset*2,data,mem_mask^0xffff); +// logerror("CPU #0 PC %06X: TMP68301 Reg %04X<-%04X & %04X\n", m_cpu->pc(),offset*2,data,mem_mask^0xffff); switch( offset * 2 ) { diff --git a/src/devices/machine/tmp68301.h b/src/devices/machine/tmp68301.h index c350b9b0be6..e019387802b 100644 --- a/src/devices/machine/tmp68301.h +++ b/src/devices/machine/tmp68301.h @@ -16,19 +16,27 @@ -class tmp68301_device : public m68000_device +class tmp68301_device : public device_t, + public device_memory_interface { public: tmp68301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template <typename T> void set_cputag(T &&tag) { m_cpu.set_tag(std::forward<T>(tag)); } // FIXME: M68000 ought to be a parent class, not an external object auto in_parallel_callback() { return m_in_parallel_cb.bind(); } auto out_parallel_callback() { return m_out_parallel_cb.bind(); } + // Hardware Registers + DECLARE_READ16_MEMBER( regs_r ); + DECLARE_WRITE16_MEMBER( regs_w ); + // Interrupts void external_interrupt_0(); void external_interrupt_1(); void external_interrupt_2(); + IRQ_CALLBACK_MEMBER(irq_callback); + private: DECLARE_READ16_MEMBER(imr_r); DECLARE_WRITE16_MEMBER(imr_w); @@ -45,18 +53,13 @@ private: DECLARE_READ8_MEMBER(icr_r); DECLARE_WRITE8_MEMBER(icr_w); - // Hardware Registers - DECLARE_READ16_MEMBER( regs_r ); - DECLARE_WRITE16_MEMBER( regs_w ); - void tmp68301_regs(address_map &map); - IRQ_CALLBACK_MEMBER(irq_callback); - protected: // device-level overrides virtual void device_start() override; virtual void device_reset() override; + virtual space_config_vector memory_space_config() const override; private: TIMER_CALLBACK_MEMBER(timer_callback); @@ -75,6 +78,11 @@ private: static constexpr uint16_t TIMER1_IRQ = 1 << 9; static constexpr uint16_t TIMER2_IRQ = 1 << 10; + inline uint16_t read_word(offs_t address); + inline void write_word(offs_t address, uint16_t data); + + required_device<m68000_base_device> m_cpu; + devcb_read16 m_in_parallel_cb; devcb_write16 m_out_parallel_cb; @@ -92,6 +100,8 @@ private: uint16_t m_pdir; uint16_t m_pdr; uint8_t m_icr[10]; + + const address_space_config m_space_config; }; DECLARE_DEVICE_TYPE(TMP68301, tmp68301_device) diff --git a/src/devices/machine/tms5501.cpp b/src/devices/machine/tms5501.cpp index d067497567a..f7581a30a72 100644 --- a/src/devices/machine/tms5501.cpp +++ b/src/devices/machine/tms5501.cpp @@ -263,9 +263,6 @@ READ8_MEMBER( tms5501_device::rst_r ) READ8_MEMBER( tms5501_device::sta_r ) { - if(is_transmit_register_empty()) - m_sta |= STA_XBE; - uint8_t data = m_sta; m_sta &= ~STA_OE; diff --git a/src/devices/machine/tms9901.cpp b/src/devices/machine/tms9901.cpp index 4e7341feb61..5282dd6f9f5 100644 --- a/src/devices/machine/tms9901.cpp +++ b/src/devices/machine/tms9901.cpp @@ -53,16 +53,6 @@ Pins: (This is mostly obvious, but it implies that you cannot trigger an interrupt by setting the output state of a pin, which is not SO obvious.) -Clock mode: - The "clock mode" is entered by setting bit 0 to 1. This means that the - clock register becomes accessible to changes and inspection. The clock - itself runs in the interrupt mode. Accordingly, the typical setup - involves first setting bit 0 to 1, then loading some or all of the - clock register bits, and then switching to interrupt mode again. From then - on, INT3 is asserted whenever the clock reaches 0, and is cleared by - writing 0 or 1 to bit 3. The clock can only be stopped by setting the - register to 0 or by a reset. - Interrupt handling: After each clock cycle, TMS9901 latches the state of INT1*-INT15* (except pins which are set as output pins). If the clock is enabled, it replaces @@ -115,9 +105,6 @@ MZ: According to the description in MZ: Turned to class (January 2012) -MZ: Added a synchronous clock input (Phi line) as an alternative to the - emu_timer. - TODO: Tests on a real machine - Set an interrupt input (e.g. keyboard for Geneve), trigger RST2*, check whether interrupt mask has been reset @@ -137,23 +124,24 @@ TODO: Tests on a real machine #include <math.h> -#define LOG_GENERAL (1U << 0) -#define LOG_PINS (1U << 1) -#define LOG_CONFIG (1U << 2) -#define LOG_MODE (1U << 3) -#define LOG_INT (1U << 4) -#define LOG_DECVALUE (1U << 5) +#define LOG_GENERAL (1U << 0) +#define LOG_PINS (1U << 1) +#define LOG_CLOCK (1U << 2) +#define LOG_MODE (1U << 3) -#define VERBOSE ( 0 ) +//#define VERBOSE (LOG_PINS | LOG_CLOCK | LOG_MODE) #include "logmacro.h" +#define LOGPINS(...) LOGMASKED(LOG_PINS, __VA_ARGS__) +#define LOGCLOCK(...) LOGMASKED(LOG_CLOCK, __VA_ARGS__) +#define LOGMODE(...) LOGMASKED(LOG_MODE, __VA_ARGS__) + + /* Constructor */ tms9901_device::tms9901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, TMS9901, tag, owner, clock), - m_clock_active(false), - m_clockdiv(0), m_read_block(*this), m_write_p{{*this},{*this},{*this},{*this},{*this},{*this},{*this},{*this},{*this},{*this},{*this},{*this},{*this},{*this},{*this},{*this}}, m_interrupt(*this) @@ -174,12 +162,12 @@ void tms9901_device::field_interrupts() // if timer is enabled, INT3 pin is overridden by timer if (m_timer_int_pending) { - LOGMASKED(LOG_INT, "INT3 (timer) asserted\n"); + LOGCLOCK("timer fires\n"); current_ints |= INT3; } else { - LOGMASKED(LOG_INT, "INT3 (timer) cleared\n"); + LOGCLOCK("timer clear\n"); current_ints &= ~INT3; } } @@ -209,7 +197,6 @@ void tms9901_device::field_interrupts() current_ints >>= 1; /* try next bit */ level++; } - LOGMASKED(LOG_INT, "Triggering interrupt, level %d\n", level); m_int_pending = true; if (!m_interrupt.isnull()) m_interrupt(level, 1, 0xff); // the offset carries the IC0-3 level @@ -250,11 +237,11 @@ void tms9901_device::timer_reload() if (m_clock_register != 0) { /* reset clock interval */ m_decrementer_value = m_clock_register; - m_clock_active = true; + m_decrementer->enable(true); } else { /* clock interval == 0 -> no timer */ - m_clock_active = false; + m_decrementer->enable(false); } } @@ -275,13 +262,13 @@ void tms9901_device::timer_reload() bit 16-31: current status of the P0-P15 pins (quits timer mode, too...) */ -uint8_t tms9901_device::read(offs_t offset) +READ8_MEMBER( tms9901_device::read ) { int answer = 0; - offset &= 0x01f; + offset &= 0x003; - switch (offset >> 3) + switch (offset) { case 0: if (m_clock_mode) @@ -304,7 +291,7 @@ uint8_t tms9901_device::read(offs_t offset) // Set those bits here answer |= (m_pio_output_mirror & m_pio_direction_mirror) & 0xFF; } - LOGMASKED(LOG_PINS, "Input on lines INT7..CB = %02x\n", answer); + LOGPINS("input on lines INT7..CB = %02x\n", answer); break; case 1: if (m_clock_mode) @@ -324,7 +311,7 @@ uint8_t tms9901_device::read(offs_t offset) answer &= ~(m_pio_direction_mirror >> 8); answer |= (m_pio_output_mirror & m_pio_direction_mirror) >> 8; } - LOGMASKED(LOG_PINS, "Input on lines INT15..INT8 = %02x\n", answer); + LOGPINS("input on lines INT15..INT8 = %02x\n", answer); break; case 2: /* exit timer mode */ @@ -338,7 +325,7 @@ uint8_t tms9901_device::read(offs_t offset) answer &= ~m_pio_direction; answer |= (m_pio_output & m_pio_direction) & 0xFF; - LOGMASKED(LOG_PINS, "Input on lines P7..P0 = %02x\n", answer); + LOGPINS("input on lines P7..P0 = %02x\n", answer); break; case 3: @@ -351,12 +338,12 @@ uint8_t tms9901_device::read(offs_t offset) answer &= ~(m_pio_direction >> 8); answer |= (m_pio_output & m_pio_direction) >> 8; - LOGMASKED(LOG_PINS, "Input on lines P15..P8 = %02x\n", answer); + LOGPINS("input on lines P15..P8 = %02x\n", answer); break; } - return BIT(answer, offset & 7); + return answer; } /* @@ -372,7 +359,7 @@ uint8_t tms9901_device::read(offs_t offset) bit 16-31: set output state of P0-P15 (and set them as output pin) (quit timer mode, too...) */ -void tms9901_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER ( tms9901_device::write ) { data &= 1; /* clear extra bits */ offset &= 0x01F; @@ -380,7 +367,7 @@ void tms9901_device::write(offs_t offset, uint8_t data) if (offset >= 0x10) { int pin = offset & 0x0F; - LOGMASKED(LOG_PINS, "Output on P%d = %d\n", pin, data); + LOGPINS("output on P%d = %d\n", pin, data); int bit = (1 << pin); @@ -421,20 +408,18 @@ void tms9901_device::write(offs_t offset, uint8_t data) { // Switch to interrupt mode; quit clock mode m_clock_mode = false; - LOGMASKED(LOG_MODE, "Enter interrupt mode\n"); + LOGMODE("int mode\n"); } else { m_clock_mode = true; - LOGMASKED(LOG_MODE, "Enter clock mode\n"); + LOGMODE("clock mode\n"); // we are switching to clock mode: latch the current value of // the decrementer register if (m_clock_register != 0) m_clock_read_register = m_decrementer_value; else m_clock_read_register = 0; /* timer inactive... */ - - LOGMASKED(LOG_CONFIG, "Clock setting = %d\n", m_clock_read_register); } } else if (offset == 0x0f) @@ -452,7 +437,7 @@ void tms9901_device::write(offs_t offset, uint8_t data) // Spec is not clear on whether the mask bits are also reset by RST2* // TODO: Check on a real machine. (I'd guess from the text they are not touched) m_enabled_ints = 0; - LOGMASKED(LOG_MODE, "Soft reset (RST2*)\n"); + LOGMODE("Soft reset (RST2*)\n"); } } else @@ -462,7 +447,7 @@ void tms9901_device::write(offs_t offset, uint8_t data) else m_enabled_ints &= ~0x4000; /* unset bit */ - LOGMASKED(LOG_CONFIG, "Enabled interrupts = %04x\n", m_enabled_ints); + LOGMODE("interrupts = %04x\n", m_enabled_ints); field_interrupts(); /* changed interrupt state */ } } @@ -484,7 +469,7 @@ void tms9901_device::write(offs_t offset, uint8_t data) m_clock_register &= ~bit; /* clear bit */ /* reset clock timer (page 8) */ - LOGMASKED(LOG_CONFIG, "Clock register = %04x\n", m_clock_register); + LOGCLOCK("clock register = %04x\n", m_clock_register); timer_reload(); } else @@ -499,7 +484,7 @@ void tms9901_device::write(offs_t offset, uint8_t data) if (offset == 3) m_timer_int_pending = false; /* SBO 3 clears pending timer interrupt (??) */ - LOGMASKED(LOG_CONFIG, "Enabled interrupts = %04x\n", m_enabled_ints); + LOGMODE("enabled interrupts = %04x\n"); field_interrupts(); /* changed interrupt state */ } } @@ -515,20 +500,10 @@ void tms9901_device::device_timer(emu_timer &timer, device_timer_id id, int para { if (id==DECREMENTER) // we have only that one { - clock_in(ASSERT_LINE); - clock_in(CLEAR_LINE); - } -} - -void tms9901_device::clock_in(line_state clk) -{ - if (m_clock_active && clk == ASSERT_LINE) - { m_decrementer_value--; - LOGMASKED(LOG_DECVALUE, "Decrementer = %d\n", m_decrementer_value); + LOGCLOCK("decrementer = %d\n", m_decrementer_value); if (m_decrementer_value<=0) { - LOGMASKED(LOG_INT, "Timer expired\n"); m_timer_int_pending = true; // decrementer interrupt requested field_interrupts(); m_decrementer_value = m_clock_register; @@ -536,21 +511,6 @@ void tms9901_device::clock_in(line_state clk) } } -/* - Synchronous clock input. This may be used for systems which have - a CLK line controlled by the CPU, like the TMS99xx systems. - In that case, clock is set to 0. -*/ -WRITE_LINE_MEMBER( tms9901_device::phi_line ) -{ - // Divider by 64 - if (state==ASSERT_LINE) - m_clockdiv = (m_clockdiv+1) % 0x40; - - if (m_clockdiv==0) - clock_in((line_state)state); -} - /*------------------------------------------------- device_stop - device-specific stop -------------------------------------------------*/ @@ -605,12 +565,9 @@ void tms9901_device::do_reset() void tms9901_device::device_start() { - // Allow for using asynchronous and synchronous clocks - if (clock() != 0) - { - m_decrementer = timer_alloc(DECREMENTER); - m_decrementer->adjust(attotime::from_hz(clock() / 64.), 0, attotime::from_hz(clock() / 64.)); - } + m_decrementer = timer_alloc(DECREMENTER); + m_decrementer->adjust(attotime::from_hz(clock() / 64.), 0, attotime::from_hz(clock() / 64.)); + m_decrementer->enable(false); m_read_block.resolve(); for (auto &cb : m_write_p) diff --git a/src/devices/machine/tms9901.h b/src/devices/machine/tms9901.h index eda01f253ad..86a2c6852e3 100644 --- a/src/devices/machine/tms9901.h +++ b/src/devices/machine/tms9901.h @@ -60,11 +60,8 @@ public: DECLARE_WRITE_LINE_MEMBER( rst1_line ); - // Synchronous clock input - DECLARE_WRITE_LINE_MEMBER( phi_line ); - - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); auto p_out_cb(int n) { return m_write_p[n].bind(); } auto read_cb() { return m_read_block.bind(); } @@ -86,9 +83,6 @@ private: // Common method for device_reset and rst1_line void do_reset(); - // Common clock handling - void clock_in(line_state clk); - // State of the INT1-INT15 lines (must be inverted when queried) // Note that the levels must also be delivered when reading the pins, which // may require to latch the int levels. @@ -99,9 +93,6 @@ private: bool m_int_pending; // status of the int* pin (connected to TMS9900) bool m_timer_int_pending; // timer int pending (overrides int3 pin if timer enabled) - bool m_clock_active; - int m_clockdiv; // Clock divider counter (for synchronous clock) - // PIO registers int m_pio_direction; // direction register for PIO @@ -119,7 +110,7 @@ private: // true = clock mode (read/write clock interval) bool m_clock_mode; - // Timer, used to emulate the decrementer register + // MESS timer, used to emulate the decrementer register emu_timer *m_decrementer; // clock interval, loaded in decrementer when it reaches 0. diff --git a/src/devices/machine/tms9902.cpp b/src/devices/machine/tms9902.cpp index 813372f6f22..93e48cf03a2 100644 --- a/src/devices/machine/tms9902.cpp +++ b/src/devices/machine/tms9902.cpp @@ -478,109 +478,48 @@ void tms9902_device::initiate_transmit() bit 13-15: not emulated, normally used for diagnostics bit 16: RBINT (RBRL&RIENB) */ -uint8_t tms9902_device::cruread(offs_t offset) +READ8_MEMBER( tms9902_device::cruread ) { uint8_t answer = 0; - switch (offset & 31) - { - case 31: - answer = m_INT; - break; - - case 30: - answer = (m_LDCTRL || m_LDIR || m_LRDR || m_LXDR || m_BRKON); - break; - - case 29: - answer = m_DSCH; - break; - - case 28: - answer = m_CTSin; - break; - - case 27: - answer = m_DSRin; - break; - - case 26: - answer = m_RTSout; - break; - - case 25: - answer = m_TIMELP; - break; - - case 24: - answer = m_TIMERR; - break; - - case 23: - answer = m_XSRE; - break; - - case 22: - answer = m_XBRE; - break; + offset &= 0x0003; - case 21: - answer = m_RBRL; - break; - - case 20: - answer = (m_DSCH && m_DSCENB); - break; - - case 19: - answer = (m_TIMELP && m_TIMENB); - break; - - case 17: - answer = (m_XBRE && m_XBIENB); - break; - - case 16: - answer = (m_RBRL && m_RIENB); - break; - - case 15: - answer = m_RIN; - break; - - case 14: - answer = m_RSBD; - break; - - case 13: - answer = m_RFBD; - break; - - case 12: - answer = m_RFER; - break; - - case 11: - answer = m_ROVER; + switch (offset) + { + case 3: // Bits 31-24 + if (m_INT) answer |= 0x80; + if (m_LDCTRL || m_LDIR || m_LRDR || m_LXDR || m_BRKON) answer |= 0x40; + if (m_DSCH) answer |= 0x20; + if (m_CTSin) answer |= 0x10; + if (m_DSRin) answer |= 0x08; + if (m_RTSout) answer |= 0x04; + if (m_TIMELP) answer |= 0x02; + if (m_TIMERR) answer |= 0x01; break; - case 10: - answer = m_RPER; + case 2: // Bits 23-16 + if (m_XSRE) answer |= 0x80; + if (m_XBRE) answer |= 0x40; + if (m_RBRL) answer |= 0x20; + if (m_DSCH && m_DSCENB) answer |= 0x10; + if (m_TIMELP && m_TIMENB) answer |= 0x08; + if (m_XBRE && m_XBIENB) answer |= 0x02; + if (m_RBRL && m_RIENB) answer |= 0x01; break; - case 9: - answer = (m_RPER || m_RFER || m_ROVER); + case 1: // Bits 15-8 + if (m_RIN) answer |= 0x80; + if (m_RSBD) answer |= 0x40; + if (m_RFBD) answer |= 0x20; + if (m_RFER) answer |= 0x10; + if (m_ROVER) answer |= 0x08; + if (m_RPER) answer |= 0x04; + if (m_RPER || m_RFER || m_ROVER) answer |= 0x02; break; - case 7: - case 6: - case 5: - case 4: - case 3: - case 2: - case 1: - case 0: - answer = BIT(m_RBR, offset & 31); + case 0: // Bits 7-0 + LOGCRU("Reading received byte = %02x\n", m_RBR); + answer = m_RBR; break; } if (VERBOSE & LOG_DETAIL) LOGCRU("Reading flag bits %d - %d = %02x\n", ((offset+1)*8-1), offset*8, answer); @@ -658,7 +597,7 @@ void tms9902_device::reset_uart() /* TMS9902 CRU write */ -void tms9902_device::cruwrite(offs_t offset, uint8_t data) +WRITE8_MEMBER( tms9902_device::cruwrite ) { data &= 1; /* clear extra bits */ diff --git a/src/devices/machine/tms9902.h b/src/devices/machine/tms9902.h index 3d203c59709..1f96e2ffc17 100644 --- a/src/devices/machine/tms9902.h +++ b/src/devices/machine/tms9902.h @@ -69,8 +69,8 @@ public: int get_config_value(); - uint8_t cruread(offs_t offset); - void cruwrite(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( cruread ); + DECLARE_WRITE8_MEMBER( cruwrite ); protected: virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; diff --git a/src/devices/machine/tms9914.cpp b/src/devices/machine/tms9914.cpp index eef06895493..00fedd5db0c 100644 --- a/src/devices/machine/tms9914.cpp +++ b/src/devices/machine/tms9914.cpp @@ -241,7 +241,7 @@ WRITE_LINE_MEMBER(tms9914_device::ren_w) } // Register I/O -void tms9914_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(tms9914_device::reg8_w) { LOG_REG("W %u=%02x\n" , offset , data); @@ -323,7 +323,7 @@ void tms9914_device::write(offs_t offset, uint8_t data) } } -uint8_t tms9914_device::read(offs_t offset) +READ8_MEMBER(tms9914_device::reg8_r) { uint8_t res; diff --git a/src/devices/machine/tms9914.h b/src/devices/machine/tms9914.h index 9fda5aa2ebb..14df9d80647 100644 --- a/src/devices/machine/tms9914.h +++ b/src/devices/machine/tms9914.h @@ -83,9 +83,8 @@ public: DECLARE_WRITE_LINE_MEMBER(atn_w); DECLARE_WRITE_LINE_MEMBER(ren_w); - // Register access - void write(offs_t offset, uint8_t data); - uint8_t read(offs_t offset); + DECLARE_WRITE8_MEMBER(reg8_w); + DECLARE_READ8_MEMBER(reg8_r); // CONT output: true when 9914 is current controller-in-charge DECLARE_READ_LINE_MEMBER(cont_r); diff --git a/src/devices/machine/tube.cpp b/src/devices/machine/tube.cpp index a53c05ac38c..aac084a3158 100644 --- a/src/devices/machine/tube.cpp +++ b/src/devices/machine/tube.cpp @@ -79,7 +79,7 @@ void tube_device::update_interrupts() m_drq_handler(!BIT(m_r1stat, 4) && ((m_hp3pos > BIT(m_r1stat, 4)) || (m_ph3pos == 0)) ? ASSERT_LINE : CLEAR_LINE); } -uint8_t tube_device::host_r(offs_t offset) +READ8_MEMBER(tube_device::host_r) { uint8_t data = 0xfe; @@ -143,7 +143,7 @@ uint8_t tube_device::host_r(offs_t offset) return data; } -void tube_device::host_w(offs_t offset, uint8_t data) +WRITE8_MEMBER(tube_device::host_w) { switch (offset & 0x07) { @@ -197,7 +197,7 @@ void tube_device::host_w(offs_t offset, uint8_t data) update_interrupts(); } -uint8_t tube_device::parasite_r(offs_t offset) +READ8_MEMBER(tube_device::parasite_r) { uint8_t data = 0x00; @@ -265,7 +265,7 @@ uint8_t tube_device::parasite_r(offs_t offset) return data; } -void tube_device::parasite_w(offs_t offset, uint8_t data) +WRITE8_MEMBER(tube_device::parasite_w) { switch (offset & 0x07) { diff --git a/src/devices/machine/tube.h b/src/devices/machine/tube.h index 384cf29b8d9..c8d94b1c7a7 100644 --- a/src/devices/machine/tube.h +++ b/src/devices/machine/tube.h @@ -32,10 +32,10 @@ public: auto pirq_handler() { return m_pirq_handler.bind(); } auto drq_handler() { return m_drq_handler.bind(); } - uint8_t host_r(offs_t offset); - void host_w(offs_t offset, uint8_t data); - uint8_t parasite_r(offs_t offset); - void parasite_w(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(host_r); + DECLARE_WRITE8_MEMBER(host_w); + DECLARE_READ8_MEMBER(parasite_r); + DECLARE_WRITE8_MEMBER(parasite_w); protected: // device-level overrides diff --git a/src/devices/machine/upd7002.cpp b/src/devices/machine/upd7002.cpp index b00d44066e5..69b9bb262ee 100644 --- a/src/devices/machine/upd7002.cpp +++ b/src/devices/machine/upd7002.cpp @@ -59,7 +59,7 @@ void upd7002_device::device_reset() *****************************************************************************/ -READ_LINE_MEMBER( upd7002_device::eoc_r ) +READ8_MEMBER( upd7002_device::eoc_r ) { return (m_status>>7)&0x01; } @@ -94,7 +94,7 @@ void upd7002_device::device_timer(emu_timer &timer, device_timer_id id, int para } -uint8_t upd7002_device::read(offs_t offset) +READ8_MEMBER( upd7002_device::read ) { switch(offset&0x03) { @@ -112,7 +112,7 @@ uint8_t upd7002_device::read(offs_t offset) -void upd7002_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER( upd7002_device::write ) { /* logerror("write to uPD7002 $%02X = $%02X\n",offset,data); */ diff --git a/src/devices/machine/upd7002.h b/src/devices/machine/upd7002.h index 2a68774d435..5b62d13dc34 100644 --- a/src/devices/machine/upd7002.h +++ b/src/devices/machine/upd7002.h @@ -30,9 +30,9 @@ public: template <typename... T> void set_get_analogue_callback(T &&... args) { m_get_analogue_cb = get_analogue_delegate(std::forward<T>(args)...); } template <typename... T> void set_eoc_callback(T &&... args) { m_eoc_cb = eoc_delegate(std::forward<T>(args)...); } - DECLARE_READ_LINE_MEMBER(eoc_r); - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(eoc_r); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); protected: // device-level overrides diff --git a/src/devices/machine/upd765.cpp b/src/devices/machine/upd765.cpp index 64b844dd222..bfbf277449b 100644 --- a/src/devices/machine/upd765.cpp +++ b/src/devices/machine/upd765.cpp @@ -18,7 +18,6 @@ #define LOG_MATCH (1U << 10) // Sector matching #define LOG_STATE (1U << 11) // State machine #define LOG_LIVE (1U << 12) // Live states -#define LOG_DONE (1U << 13) // Command done #define VERBOSE (LOG_GENERAL | LOG_WARN ) @@ -39,7 +38,6 @@ #define LOGMATCH(...) LOGMASKED(LOG_MATCH, __VA_ARGS__) #define LOGSTATE(...) LOGMASKED(LOG_STATE, __VA_ARGS__) #define LOGLIVE(...) LOGMASKED(LOG_LIVE, __VA_ARGS__) -#define LOGDONE(...) LOGMASKED(LOG_DONE, __VA_ARGS__) DEFINE_DEVICE_TYPE(UPD765A, upd765a_device, "upd765a", "NEC uPD765A FDC") DEFINE_DEVICE_TYPE(UPD765B, upd765b_device, "upd765b", "NEC uPD765B FDC") @@ -168,9 +166,7 @@ upd765_family_device::upd765_family_device(const machine_config &mconfig, device pc_fdc_interface(mconfig, type, tag, owner, clock), intrq_cb(*this), drq_cb(*this), - hdl_cb(*this), - idx_cb(*this), - us_cb(*this) + hdl_cb(*this) { ready_polled = true; ready_connected = true; @@ -195,20 +191,15 @@ void upd765_family_device::set_mode(int _mode) mode = _mode; } -void upd765_family_device::device_resolve_objects() -{ - intrq_cb.resolve_safe(); - drq_cb.resolve_safe(); - hdl_cb.resolve_safe(); - idx_cb.resolve_safe(); - us_cb.resolve_safe(); -} - void upd765_family_device::device_start() { save_item(NAME(motorcfg)); save_item(NAME(selected_drive)); + intrq_cb.resolve_safe(); + drq_cb.resolve_safe(); + hdl_cb.resolve_safe(); + for(int i=0; i != 4; i++) { char name[2]; flopi[i].tm = timer_alloc(i); @@ -336,7 +327,6 @@ void upd765_family_device::set_ds(int fid) for(floppy_info &fi : flopi) if(fi.dev) fi.dev->ds_w(fid); - us_cb(fid); // record selected drive selected_drive = fid; @@ -351,11 +341,9 @@ void upd765_family_device::set_floppy(floppy_image_device *flop) } if(flop) flop->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&upd765_family_device::index_callback, this)); - else - idx_cb(0); } -uint8_t upd765_family_device::sra_r() +READ8_MEMBER(upd765_family_device::sra_r) { uint8_t sra = 0; int fid = dor & 3; @@ -378,17 +366,17 @@ uint8_t upd765_family_device::sra_r() return sra; } -uint8_t upd765_family_device::srb_r() +READ8_MEMBER(upd765_family_device::srb_r) { return 0; } -uint8_t upd765_family_device::dor_r() +READ8_MEMBER(upd765_family_device::dor_r) { return dor; } -void upd765_family_device::dor_w(uint8_t data) +WRITE8_MEMBER(upd765_family_device::dor_w) { LOGREGS("dor = %02x\n", data); uint8_t diff = dor ^ data; @@ -404,16 +392,21 @@ void upd765_family_device::dor_w(uint8_t data) check_irq(); } -uint8_t upd765_family_device::tdr_r() +READ8_MEMBER(upd765_family_device::tdr_r) { return 0; } -void upd765_family_device::tdr_w(uint8_t data) +WRITE8_MEMBER(upd765_family_device::tdr_w) +{ +} + +READ8_MEMBER(upd765_family_device::msr_r) { + return read_msr(); } -uint8_t upd765_family_device::msr_r() +uint8_t upd765_family_device::read_msr() { uint32_t msr = 0; switch(main_phase) { @@ -444,7 +437,7 @@ uint8_t upd765_family_device::msr_r() } msr |= get_drive_busy(); - if(data_irq && !machine().side_effects_disabled()) { + if(data_irq) { data_irq = false; check_irq(); } @@ -452,7 +445,7 @@ uint8_t upd765_family_device::msr_r() return msr; } -void upd765_family_device::dsr_w(uint8_t data) +WRITE8_MEMBER(upd765_family_device::dsr_w) { LOGREGS("dsr_w %02x (%s)\n", data, machine().describe_context()); if(data & 0x80) @@ -466,43 +459,39 @@ void upd765_family_device::set_rate(int rate) cur_rate = rate; } -uint8_t upd765_family_device::fifo_r() +uint8_t upd765_family_device::read_fifo() { uint8_t r = 0xff; switch(main_phase) { case PHASE_EXEC: - if(machine().side_effects_disabled()) - return fifo[0]; if(internal_drq) return fifo_pop(false); - LOGFIFO("fifo_r in phase %d\n", main_phase); + LOGFIFO("read_fifo in phase %d\n", main_phase); break; case PHASE_RESULT: r = result[0]; - if(!machine().side_effects_disabled()) { - result_pos--; - memmove(result, result+1, result_pos); - if(!result_pos) - main_phase = PHASE_CMD; - else if(result_pos == 1) { - // clear drive busy bit after the first sense interrupt status result byte is read - for(floppy_info &fi : flopi) - if((fi.main_state == RECALIBRATE || fi.main_state == SEEK) && fi.sub_state == IDLE && fi.st0_filled == false) - fi.main_state = IDLE; - clr_drive_busy(); - } + result_pos--; + memmove(result, result+1, result_pos); + if(!result_pos) + main_phase = PHASE_CMD; + else if(result_pos == 1) { + // clear drive busy bit after the first sense interrupt status result byte is read + for(floppy_info &fi : flopi) + if((fi.main_state == RECALIBRATE || fi.main_state == SEEK) && fi.sub_state == IDLE && fi.st0_filled == false) + fi.main_state = IDLE; + clr_drive_busy(); } break; default: - LOGFIFO("fifo_r in phase %d\n", main_phase); + LOGFIFO("read_fifo in phase %d\n", main_phase); break; } return r; } -void upd765_family_device::fifo_w(uint8_t data) +void upd765_family_device::write_fifo(uint8_t data) { switch(main_phase) { case PHASE_CMD: { @@ -528,11 +517,11 @@ void upd765_family_device::fifo_w(uint8_t data) fifo_push(data, false); return; } - LOGFIFO("fifo_w in phase %d\n", main_phase); + LOGFIFO("write_fifo in phase %d\n", main_phase); break; default: - LOGFIFO("fifo_w in phase %d\n", main_phase); + LOGFIFO("write_fifo in phase %d\n", main_phase); break; } } @@ -545,7 +534,12 @@ uint8_t upd765_family_device::do_dir_r() return 0x00; } -void upd765_family_device::ccr_w(uint8_t data) +READ8_MEMBER(upd765_family_device::dir_r) +{ + return do_dir_r(); +} + +WRITE8_MEMBER(upd765_family_device::ccr_w) { dsr = (dsr & 0xfc) | (data & 3); cur_rate = rates[data & 3]; @@ -647,10 +641,18 @@ void upd765_family_device::fifo_expect(int size, bool write) enable_transfer(); } +READ8_MEMBER(upd765_family_device::mdma_r) +{ + return dma_r(); +} + +WRITE8_MEMBER(upd765_family_device::mdma_w) +{ + dma_w(data); +} + uint8_t upd765_family_device::dma_r() { - if(machine().side_effects_disabled()) - return fifo[0]; return fifo_pop(false); } @@ -1472,7 +1474,7 @@ void upd765_family_device::execute_command(int cmd) void upd765_family_device::command_end(floppy_info &fi, bool data_completion) { - LOGDONE("command done (%s) - %s\n", data_completion ? "data" : "seek", results()); + LOGCOMMAND("command done (%s) - %s\n", data_completion ? "data" : "seek", results()); fi.main_state = fi.sub_state = IDLE; if(data_completion) data_irq = true; @@ -1744,16 +1746,7 @@ void upd765_family_device::read_data_continue(floppy_info &fi) fi.sub_state = COMMAND_DONE; break; } - // MZ: This st1 handling ensures that both HX5102 floppy and the - // Speedlock protection scheme are properly working. - // a) HX5102 requires that the ND flag not be set when no address - // marks could be found on the track at all (particularly due to - // wrong density) - // b) Speedlock requires the ND flag be set when there are valid - // sectors on the track, but the desired sector is missing, also - // when it has no valid address marks st1 &= ~ST1_MA; - st1 |= ST1_ND; if(!sector_matches()) { if(cur_live.idbuf[0] != command[2]) { if(cur_live.idbuf[0] == 0xff) @@ -1765,7 +1758,6 @@ void upd765_family_device::read_data_continue(floppy_info &fi) live_start(fi, SEARCH_ADDRESS_MARK_HEADER); return; } - st1 &= ~ST1_ND; LOGRW("reading sector %02x %02x %02x %02x\n", cur_live.idbuf[0], cur_live.idbuf[1], @@ -1784,6 +1776,11 @@ void upd765_family_device::read_data_continue(floppy_info &fi) case SCAN_ID_FAILED: LOGSTATE("SCAN_ID_FAILED\n"); fi.st0 |= ST0_FAIL; + // MZ: The HX5102 does not correctly detect a FM/MFM mismatch + // when the ND bit is set, because in the firmware the ND bit wins + // against MA, and thus concludes that the format is correct + // but the sector is missing. + // st1 |= ST1_ND; fi.sub_state = COMMAND_DONE; break; @@ -1855,7 +1852,7 @@ void upd765_family_device::write_data_start(floppy_info &fi) fi.main_state = WRITE_DATA; fi.sub_state = HEAD_LOAD; mfm = command[0] & 0x40; - LOGCOMMAND("command write%s data%s%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n", + LOGRW("command write%s data%s%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n", command[0] & 0x08 ? " deleted" : "", command[0] & 0x80 ? " mt" : "", command[0] & 0x40 ? " mfm" : "", @@ -1923,11 +1920,6 @@ void upd765_family_device::write_data_continue(floppy_info &fi) break; } st1 &= ~ST1_MA; - LOGRW("writing sector %02x %02x %02x %02x\n", - cur_live.idbuf[0], - cur_live.idbuf[1], - cur_live.idbuf[2], - cur_live.idbuf[3]); sector_size = calc_sector_size(cur_live.idbuf[3]); fifo_expect(sector_size, true); fi.sub_state = SECTOR_WRITTEN; @@ -2000,7 +1992,7 @@ void upd765_family_device::read_track_start(floppy_info &fi) mfm = command[0] & 0x40; sectors_read = 0; - LOGCOMMAND("command read track%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n", + LOGRW("command read track%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n", command[0] & 0x40 ? " mfm" : "", command[0], command[1], @@ -2292,9 +2284,6 @@ void upd765_family_device::read_id_start(floppy_info &fi) return; } - for(int i=0; i<4; i++) - cur_live.idbuf[i] = command[i+2]; - read_id_continue(fi); } @@ -2327,7 +2316,8 @@ void upd765_family_device::read_id_continue(floppy_info &fi) case SCAN_ID_FAILED: LOGSTATE("SCAN_ID_FAILED\n"); fi.st0 |= ST0_FAIL; - st1 |= ST1_ND|ST1_MA; + // st1 |= ST1_ND|ST1_MA; + st1 = ST1_MA; fi.sub_state = COMMAND_DONE; break; @@ -2453,7 +2443,6 @@ void upd765_family_device::index_callback(floppy_image_device *floppy, int state if(fi.live) live_sync(); fi.index = state; - idx_cb(state); if(!state) { general_continue(fi); @@ -2966,7 +2955,7 @@ void mcs3201_device::device_start() m_input_handler.resolve_safe(0); } -uint8_t mcs3201_device::input_r() +READ8_MEMBER( mcs3201_device::input_r ) { return m_input_handler(); } @@ -2986,7 +2975,7 @@ void tc8566af_device::device_start() save_item(NAME(m_cr1)); } -void tc8566af_device::cr1_w(uint8_t data) +WRITE8_MEMBER(tc8566af_device::cr1_w) { m_cr1 = data; @@ -2996,7 +2985,7 @@ void tc8566af_device::cr1_w(uint8_t data) } } -void upd72065_device::auxcmd_w(uint8_t data) +WRITE8_MEMBER(upd72065_device::auxcmd_w) { switch(data) { case 0x36: // reset diff --git a/src/devices/machine/upd765.h b/src/devices/machine/upd765.h index 0a40e4f4b53..dd2e30ce78a 100644 --- a/src/devices/machine/upd765.h +++ b/src/devices/machine/upd765.h @@ -45,29 +45,34 @@ public: auto intrq_wr_callback() { return intrq_cb.bind(); } auto drq_wr_callback() { return drq_cb.bind(); } auto hdl_wr_callback() { return hdl_cb.bind(); } - auto us_wr_callback() { return us_cb.bind(); } - auto idx_wr_callback() { return idx_cb.bind(); } virtual void map(address_map &map) override = 0; - uint8_t sra_r(); - uint8_t srb_r(); - uint8_t dor_r(); - void dor_w(uint8_t data); - uint8_t tdr_r(); - void tdr_w(uint8_t data); - uint8_t msr_r(); - void dsr_w(uint8_t data); - uint8_t fifo_r(); - void fifo_w(uint8_t data); - uint8_t dir_r() { return do_dir_r(); } - void ccr_w(uint8_t data); + DECLARE_READ8_MEMBER (sra_r); + DECLARE_READ8_MEMBER (srb_r); + DECLARE_READ8_MEMBER (dor_r); + DECLARE_WRITE8_MEMBER(dor_w); + DECLARE_READ8_MEMBER (tdr_r); + DECLARE_WRITE8_MEMBER(tdr_w); + uint8_t read_msr(); + DECLARE_READ8_MEMBER (msr_r); + DECLARE_WRITE8_MEMBER(dsr_w); + uint8_t read_fifo(); + void write_fifo(uint8_t data); + DECLARE_READ8_MEMBER (fifo_r) { return read_fifo(); } + DECLARE_WRITE8_MEMBER(fifo_w) { write_fifo(data); } + DECLARE_READ8_MEMBER (dir_r); + DECLARE_WRITE8_MEMBER(ccr_w); virtual uint8_t do_dir_r() override; uint8_t dma_r() override; void dma_w(uint8_t data) override; + // Same as the previous ones, but as memory-mappable members + DECLARE_READ8_MEMBER(mdma_r); + DECLARE_WRITE8_MEMBER(mdma_w); + bool get_irq() const; bool get_drq() const; void tc_w(bool val) override; @@ -86,7 +91,6 @@ public: protected: upd765_family_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - virtual void device_resolve_objects() override; virtual void device_start() override; virtual void device_reset() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; @@ -265,8 +269,7 @@ protected: int main_phase; live_info cur_live, checkpoint_live; - devcb_write_line intrq_cb, drq_cb, hdl_cb, idx_cb; - devcb_write8 us_cb; + devcb_write_line intrq_cb, drq_cb, hdl_cb; bool cur_irq, other_irq, data_irq, drq, internal_drq, tc, tc_done, locked, mfm, scan_done; floppy_info flopi[4]; @@ -470,7 +473,7 @@ public: upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); virtual void map(address_map &map) override; - void auxcmd_w(uint8_t data); + DECLARE_WRITE8_MEMBER(auxcmd_w); }; class n82077aa_device : public upd765_family_device { @@ -521,7 +524,7 @@ public: auto input_handler() { return m_input_handler.bind(); } virtual void map(address_map &map) override; - uint8_t input_r(); + DECLARE_READ8_MEMBER( input_r ); protected: virtual void device_start() override; @@ -536,7 +539,7 @@ public: virtual void map(address_map &map) override; - void cr1_w(uint8_t data); + DECLARE_WRITE8_MEMBER(cr1_w); protected: virtual void device_start() override; diff --git a/src/devices/machine/wd1010.cpp b/src/devices/machine/wd1010.cpp deleted file mode 100644 index 16442934352..00000000000 --- a/src/devices/machine/wd1010.cpp +++ /dev/null @@ -1,583 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Dirk Best -/*************************************************************************** - - Western Digital WD1010-05 Winchester Disk Controller - -***************************************************************************/ - -#include "emu.h" -#include "wd1010.h" - -//#define LOG_GENERAL (1U << 0) -#define LOG_CMD (1U << 1) -#define LOG_INT (1U << 2) -#define LOG_SEEK (1U << 3) -#define LOG_REGS (1U << 4) -#define LOG_DATA (1U << 5) - -//#define VERBOSE (LOG_CMD | LOG_INT | LOG_SEEK | LOG_REGS | LOG_DATA) -//#define LOG_OUTPUT_STREAM std::cout - -#include "logmacro.h" - -#define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__) -#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__) -#define LOGSEEK(...) LOGMASKED(LOG_SEEK, __VA_ARGS__) -#define LOGREGS(...) LOGMASKED(LOG_REGS, __VA_ARGS__) -#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__) - - -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -DEFINE_DEVICE_TYPE(WD1010, wd1010_device, "wd1010", "Western Digital WD1010-05") - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// wd1010_device - constructor -//------------------------------------------------- - -wd1010_device::wd1010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, WD1010, tag, owner, clock), - m_out_intrq_cb(*this), - m_out_bcr_cb(*this), - m_in_data_cb(*this), - m_out_data_cb(*this), - m_intrq(0), - m_brdy(0), - m_stepping_rate(0x00), - m_command(0x00), - m_error(0x00), - m_precomp(0x00), - m_sector_count(0x00), - m_sector_number(0x00), - m_cylinder(0x0000), - m_sdh(0x00), - m_status(0x00) -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void wd1010_device::device_start() -{ - // get connected drives - for (int i = 0; i < 4; i++) - { - char name[2]; - name[0] = '0' + i; - name[1] = 0; - m_drives[i].drive = subdevice<harddisk_image_device>(name); - m_drives[i].head = 0; - m_drives[i].cylinder = 0; - m_drives[i].sector = 0; - } - - // resolve callbacks - m_out_intrq_cb.resolve_safe(); - m_out_bcr_cb.resolve_safe(); - m_in_data_cb.resolve_safe(0); - m_out_data_cb.resolve_safe(); - - // allocate timer - m_seek_timer = timer_alloc(TIMER_SEEK); - m_data_timer = timer_alloc(TIMER_DATA); - - // register for save states - save_item(NAME(m_intrq)); - save_item(NAME(m_brdy)); - save_item(NAME(m_stepping_rate)); - save_item(NAME(m_command)); - save_item(NAME(m_error)); - save_item(NAME(m_precomp)); - save_item(NAME(m_sector_count)); - save_item(NAME(m_sector_number)); - save_item(NAME(m_cylinder)); - save_item(NAME(m_sdh)); - save_item(NAME(m_status)); -} - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void wd1010_device::device_reset() -{ -} - -//------------------------------------------------- -// device_timer - device-specific timer -//------------------------------------------------- - -void wd1010_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr) -{ - switch (tid) - { - case TIMER_SEEK: - - if ((m_command >> 4) != CMD_SCAN_ID) - { - LOGSEEK("Seek complete\n"); - m_drives[drive()].cylinder = param; - m_status |= STATUS_SC; - } - - switch (m_command >> 4) - { - case CMD_RESTORE: - cmd_restore(); - break; - - case CMD_SEEK: - cmd_seek(); - break; - - case CMD_READ_SECTOR: - cmd_read_sector(); - break; - - case CMD_WRITE_SECTOR: - case CMD_WRITE_FORMAT: - cmd_write_sector(); - break; - - case CMD_SCAN_ID: - cmd_scan_id(); - break; - } - - break; - - case TIMER_DATA: - - // check if data is ready or continue waiting - if (m_brdy) - cmd_write_sector(); - else - m_data_timer->adjust(attotime::from_usec(35)); - - break; - } -} - -//------------------------------------------------- -// set_error - set error and adjust status -//------------------------------------------------- - -void wd1010_device::set_error(int error) -{ - if (error) - { - m_error |= error; - m_status |= STATUS_ERR; - } - else - { - m_error = 0; - m_status &= ~STATUS_ERR; - } -} - -//------------------------------------------------- -// set_intrq - set interrupt status -//------------------------------------------------- - -void wd1010_device::set_intrq(int state) -{ - if (m_intrq == 0 && state == 1) - { - LOGINT("INT 1\n"); - m_intrq = 1; - m_out_intrq_cb(1); - } - else if (m_intrq == 1 && state == 0) - { - LOGINT("INT 0\n"); - m_intrq = 0; - m_out_intrq_cb(0); - } -} - -//------------------------------------------------- -// get_stepping_rate - calculate stepping rate -//------------------------------------------------- - -attotime wd1010_device::get_stepping_rate() -{ - if (m_stepping_rate) - return attotime::from_usec(500 * m_stepping_rate); - else - return attotime::from_usec(35); -} - -//------------------------------------------------- -// start_command - executed at the start of every command -//------------------------------------------------- - -void wd1010_device::start_command() -{ - // now busy and command in progress, clear error - m_status |= STATUS_BSY; - m_status |= STATUS_CIP; - set_error(0); - - switch (m_command >> 4) - { - case CMD_RESTORE: - m_stepping_rate = m_command & 0x0f; - LOGCMD("RESTORE\n"); - break; - case CMD_READ_SECTOR: - LOGCMD("READ SECTOR\n"); - break; - case CMD_WRITE_SECTOR: - LOGCMD("WRITE SECTOR\n"); - break; - case CMD_SCAN_ID: - LOGCMD("SCAN ID\n"); - break; - case CMD_WRITE_FORMAT: - LOGCMD("WRITE FORMAT ID\n"); - break; - case CMD_SEEK: - m_stepping_rate = m_command & 0x0f; - LOGCMD("SEEK\n"); - break; - } -} - -//------------------------------------------------- -// end_command - executed at end of every command -//------------------------------------------------- - -void wd1010_device::end_command() -{ - m_out_bcr_cb(1); - m_out_bcr_cb(0); - - m_status &= ~(STATUS_BSY | STATUS_CIP); - - set_intrq(1); -} - -//------------------------------------------------- -// get_lbasector - translate to lba -//------------------------------------------------- - -int wd1010_device::get_lbasector() -{ - hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file(); - hard_disk_info *info = hard_disk_get_info(file); - int lbasector; - - lbasector = m_cylinder; - lbasector *= info->heads; - lbasector += head(); - lbasector *= info->sectors; - lbasector += m_sector_number; - - return lbasector; -} - - -//************************************************************************** -// INTERFACE -//************************************************************************** - -WRITE_LINE_MEMBER( wd1010_device::drdy_w ) -{ - if (state) - m_status |= STATUS_RDY; - else - m_status &= ~STATUS_RDY; -} - -WRITE_LINE_MEMBER( wd1010_device::brdy_w ) -{ - m_brdy = state; -} - -READ8_MEMBER( wd1010_device::read ) -{ - // if the controller is busy all reads return the status register - if (m_status & STATUS_BSY) - { - LOG("Read while busy, return STATUS: %02x\n", m_status); - return m_status; - } - - switch (offset & 0x07) - { - case 0: - LOGREGS("RD INVALID\n"); - return 0; - - case 1: - LOGREGS("RD ERROR: %02x\n", m_error); - return m_error; - - case 2: - LOGREGS("RD SECTOR COUNT: %02x\n", m_sector_count); - return m_sector_count; - - case 3: - LOGREGS("RD SECTOR NUMBER: %02x\n", m_sector_number); - return m_sector_number; - - case 4: - LOGREGS("RD CYLINDER L: %02x\n", m_cylinder & 0xff); - return m_cylinder & 0xff; - - case 5: - LOGREGS("RD CYLINDER H: %02x\n", m_cylinder >> 8); - return m_cylinder >> 8; - - case 6: - LOGREGS("RD SDH: %02x\n", m_sdh); - return m_sdh; - - case 7: - LOGREGS("RD STATUS: %02x\n", m_status); - - // reading the status register clears the interrupt - set_intrq(0); - - return m_status; - } - - // should never get here - return 0xff; -} - -WRITE8_MEMBER( wd1010_device::write ) -{ - switch (offset & 0x07) - { - case 0: - LOGREGS("WR INVALID: %02x\n", data); - break; - - case 1: - LOGREGS("WR PRECOMP: %02x\n", data); - m_precomp = data; - break; - - case 2: - LOGREGS("WR SECTOR COUNT: %02x\n", data); - m_sector_count = data; - break; - - case 3: - LOGREGS("WR SECTOR NUMBER: %02x\n", data); - m_sector_number = data; - break; - - case 4: - LOGREGS("WR CYLINDER L: %02x\n", data); - m_cylinder = (m_cylinder & 0xff00) | (data << 0); - break; - - case 5: - LOGREGS("WR CYLINDER H: %02x\n", data); - m_cylinder = (m_cylinder & 0x00ff) | (data << 8); - break; - - case 6: - LOGREGS("WR SDH: %02x\n", data); - m_sdh = data; - break; - - case 7: - // writes to the command register are ignored when a command is in progress - if (m_status & STATUS_CIP) - return; - - // writing the command register clears the interrupt - set_intrq(0); - - // check drive status - if (!(m_status & STATUS_RDY)) - { - // selected drive not ready - LOG("--> Drive not ready, aborting\n"); - - set_error(ERR_AC); - end_command(); - } - else - { - m_command = data; - - start_command(); - - // all other command imply a seek - if ((m_command >> 4) != CMD_SCAN_ID) - m_status &= ~STATUS_SC; - - int amount = 0; - int target = 0; - - switch (m_command >> 4) - { - case CMD_RESTORE: - amount = m_drives[drive()].cylinder; - target = 0; - break; - - case CMD_SEEK: - case CMD_READ_SECTOR: - case CMD_WRITE_SECTOR: - case CMD_WRITE_FORMAT: - amount = abs(m_drives[drive()].cylinder - m_cylinder); - target = m_cylinder; - break; - } - - if ((m_command >> 4) != CMD_SCAN_ID) - LOGSEEK("Seeking %d cylinders to %d\n", amount, target); - - m_seek_timer->adjust(get_stepping_rate() * amount, target); - } - - break; - } -} - - -//************************************************************************** -// IMPLEMENTATION -//************************************************************************** - -void wd1010_device::cmd_restore() -{ - LOGCMD("--> RESTORE done\n"); - end_command(); -} - -void wd1010_device::cmd_read_sector() -{ - hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file(); - hard_disk_info *info = hard_disk_get_info(file); - - m_out_bcr_cb(1); - m_out_bcr_cb(0); - - // verify that we can read - if (head() > info->heads) - { - // out of range - LOG("--> Head out of range, aborting\n"); - - set_error(ERR_AC); - end_command(); - } - else - { - uint8_t buffer[512]; - - while (m_sector_count > 0) - { - LOGDATA("--> Transferring sector to buffer (lba = %08x)\n", get_lbasector()); - - hard_disk_read(file, get_lbasector(), buffer); - - for (int i = 0; i < 512; i++) - m_out_data_cb(buffer[i]); - - m_out_bcr_cb(1); - m_out_bcr_cb(0); - - // save last read head and sector number - m_drives[drive()].head = head(); - m_drives[drive()].sector = m_sector_number; - - if (BIT(m_command, 2)) - { - m_sector_number++; - m_sector_count--; - } - else - break; - } - - end_command(); - } -} - -void wd1010_device::cmd_write_sector() -{ - if (!(m_status & STATUS_DRQ)) - { - LOGDATA("Setting DATA REQUEST\n"); - m_status |= STATUS_DRQ; - m_data_timer->adjust(attotime::from_usec(35)); - return; - } - - if (m_brdy == 0) - { - m_data_timer->adjust(attotime::from_usec(35)); - return; - } - - LOGDATA("Clearing DATA REQUEST\n"); - m_status &= ~STATUS_DRQ; - - hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file(); - uint8_t buffer[512]; - - while (m_sector_count > 0) - { - if ((m_command >> 4) == CMD_WRITE_FORMAT) - { - // we ignore the format specification and fill everything with 0xe5 - std::fill(std::begin(buffer), std::end(buffer), 0xe5); - } - else - { - // get data for sector from buffer chip - for (int i = 0; i < 512; i++) - buffer[i] = m_in_data_cb(); - } - - hard_disk_write(file, get_lbasector(), buffer); - - // save last read head and sector number - m_drives[drive()].head = head(); - m_drives[drive()].sector = m_sector_number; - - if (BIT(m_command, 2)) - { - m_sector_number++; - m_sector_count--; - } - else - break; - } - - end_command(); -} - -void wd1010_device::cmd_scan_id() -{ - // update head, sector size, sector number and cylinder - m_sdh = (m_sdh & 0xf8) | (m_drives[drive()].head & 0x07); - m_sector_number = m_drives[drive()].sector; - m_cylinder = m_drives[drive()].cylinder; - - end_command(); -} - -void wd1010_device::cmd_seek() -{ - LOGCMD("--> SEEK done\n"); - end_command(); -} diff --git a/src/devices/machine/wd1010.h b/src/devices/machine/wd1010.h deleted file mode 100644 index b5db9975693..00000000000 --- a/src/devices/machine/wd1010.h +++ /dev/null @@ -1,143 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Dirk Best -/*************************************************************************** - - Western Digital WD1010-05 Winchester Disk Controller - -***************************************************************************/ - -#ifndef MAME_MACHINE_WD1010_H -#define MAME_MACHINE_WD1010_H - -#pragma once - -#include "imagedev/harddriv.h" - - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> wd1010_device - -class wd1010_device : public device_t -{ -public: - // construction/destruction - wd1010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - auto out_intrq_callback() { return m_out_intrq_cb.bind(); } - auto out_bcr_callback() { return m_out_bcr_cb.bind(); } - auto in_data_callback() { return m_in_data_cb.bind(); } - auto out_data_callback() { return m_out_data_cb.bind(); } - - DECLARE_READ8_MEMBER(read); - DECLARE_WRITE8_MEMBER(write); - - DECLARE_WRITE_LINE_MEMBER(drdy_w); - DECLARE_WRITE_LINE_MEMBER(brdy_w); - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - -private: - enum - { - STATUS_ERR = 0x01, // error - STATUS_CIP = 0x02, // command in progress - STATUS_RSV = 0x04, // reserved - STATUS_DRQ = 0x08, // data request - STATUS_SC = 0x10, // seek complete - STATUS_WF = 0x20, // write fault - STATUS_RDY = 0x40, // drive ready - STATUS_BSY = 0x80 // controller busy - }; - - enum - { - ERR_DM = 0x01, // data address mark not found - ERR_TK = 0x02, // track zero error - ERR_AC = 0x04, // aborted command - ERR_RSV1 = 0x08, // reserved, forced to 0 - ERR_ID = 0x10, // id not found - ERR_RSV2 = 0x20, // reserved, forced to 0 - ERR_CRC = 0x40, // crc error - ERR_BB = 0x80 // bad block - }; - - enum - { - CMD_RESTORE = 1, - CMD_READ_SECTOR = 2, - CMD_WRITE_SECTOR = 3, - CMD_SCAN_ID = 4, - CMD_WRITE_FORMAT = 5, - CMD_SEEK = 7 - }; - - enum - { - TIMER_SEEK, - TIMER_DATA - }; - - void set_error(int error); - void set_intrq(int state); - attotime get_stepping_rate(); - void start_command(); - void end_command(); - int get_lbasector(); - - // extract values from sdh - int head() { return (m_sdh >> 0) & 0x07; } - int drive() { return (m_sdh >> 3) & 0x03; } - int sector_size() - { - const int S[4] = { 256, 512, 1024, 128 }; - return S[(m_sdh >> 5) & 0x03]; - } - - void cmd_restore(); - void cmd_read_sector(); - void cmd_write_sector(); - void cmd_scan_id(); - void cmd_seek(); - - devcb_write_line m_out_intrq_cb; - devcb_write_line m_out_bcr_cb; - devcb_read8 m_in_data_cb; - devcb_write8 m_out_data_cb; - - struct - { - harddisk_image_device *drive; - uint8_t head; - uint16_t cylinder; - uint8_t sector; - } m_drives[4]; - - emu_timer *m_seek_timer; - emu_timer *m_data_timer; - - int m_intrq; - int m_brdy; - uint8_t m_stepping_rate; - uint8_t m_command; - - // task file registers - uint8_t m_error; - uint8_t m_precomp; - uint8_t m_sector_count; - uint8_t m_sector_number; - uint16_t m_cylinder; - uint8_t m_sdh; - uint8_t m_status; -}; - -// device type definition -DECLARE_DEVICE_TYPE(WD1010, wd1010_device) - -#endif // MAME_MACHINE_WD1010_H diff --git a/src/devices/machine/wd11c00_17.cpp b/src/devices/machine/wd11c00_17.cpp index b0d58034f6d..499601c943f 100644 --- a/src/devices/machine/wd11c00_17.cpp +++ b/src/devices/machine/wd11c00_17.cpp @@ -301,15 +301,6 @@ WRITE8_MEMBER( wd11c00_17_device::io_w ) //------------------------------------------------- -// dack3_w - -//------------------------------------------------- - -WRITE_LINE_MEMBER(wd11c00_17_device::dack3_w) -{ -} - - -//------------------------------------------------- // dack_r - //------------------------------------------------- diff --git a/src/devices/machine/wd11c00_17.h b/src/devices/machine/wd11c00_17.h index 0b375f61e67..e109c548202 100644 --- a/src/devices/machine/wd11c00_17.h +++ b/src/devices/machine/wd11c00_17.h @@ -39,7 +39,6 @@ public: DECLARE_READ8_MEMBER( io_r ); DECLARE_WRITE8_MEMBER( io_w ); - DECLARE_WRITE_LINE_MEMBER( dack3_w ); uint8_t dack_r(); void dack_w(uint8_t data); diff --git a/src/devices/machine/wd2010.cpp b/src/devices/machine/wd2010.cpp index 95bb4803107..c25aa538df3 100644 --- a/src/devices/machine/wd2010.cpp +++ b/src/devices/machine/wd2010.cpp @@ -28,11 +28,11 @@ UNIMPLEMENTED FEATURES : the intended instruction flow. Some loops were omitted! USAGE: tie WF (write fault) to ground if not needed: - in_wf_callback().set_constant(0) + MCFG_WD2010_IN_WF_CB(GND) Other signals should be set to VCC if not serviced: - in_drdy_callback().set_constant(1) // DRIVE READY = VCC - in_sc_callback().set_constant(1) // SEEK COMPLETE = VCC + MCFG_WD2010_IN_DRDY_CB(VCC) // DRIVE READY = VCC + MCFG_WD2010_IN_SC_CB(VCC) // SEEK COMPLETE = VCC **********************************************************************/ #include "emu.h" @@ -233,7 +233,7 @@ void wd2010_device::device_reset() // read - //------------------------------------------------- -uint8_t wd2010_device::read(offs_t offset) +READ8_MEMBER(wd2010_device::read) { uint8_t data; @@ -273,7 +273,7 @@ uint8_t wd2010_device::read(offs_t offset) // write - //------------------------------------------------- -void wd2010_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(wd2010_device::write) { m_task_file[offset] = data; diff --git a/src/devices/machine/wd2010.h b/src/devices/machine/wd2010.h index 1617f886ed6..fdfc2c4462c 100644 --- a/src/devices/machine/wd2010.h +++ b/src/devices/machine/wd2010.h @@ -40,8 +40,8 @@ public: auto in_tk000_callback() { return m_in_tk000_cb.bind(); } auto in_sc_callback() { return m_in_sc_cb.bind(); } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); void buffer_ready(bool state); diff --git a/src/devices/machine/wd33c93.cpp b/src/devices/machine/wd33c93.cpp new file mode 100644 index 00000000000..fcbb45957af --- /dev/null +++ b/src/devices/machine/wd33c93.cpp @@ -0,0 +1,984 @@ +// license:BSD-3-Clause +// copyright-holders:ElSemi, R. Belmont, Ryan Holtz +/* + * wd33c93.c + * + * WD/AMD 33c93 SCSI controller, as seen in + * early PCs, some MSX add-ons, NEC PC-88, and SGI + * Indigo, Indigo2, and Indy systems. + * + * References: + * WD 33c93 manual + * NetBSD 33c93 driver + * + */ + +#include "emu.h" +#include "wd33c93.h" + +#define LOG_READS (1 << 0) +#define LOG_WRITES (1 << 1) +#define LOG_COMMANDS (1 << 2) +#define LOG_ERRORS (1 << 3) +#define LOG_MISC (1 << 4) +#define LOG_REGS (LOG_READS | LOG_WRITES) +#define LOG_ALL (LOG_REGS | LOG_COMMANDS | LOG_ERRORS | LOG_MISC) + +#define VERBOSE (0) +#include "logmacro.h" + + +/* WD commands */ +#define WD_CMD_RESET 0x00 +#define WD_CMD_ABORT 0x01 +#define WD_CMD_ASSERT_ATN 0x02 +#define WD_CMD_NEGATE_ACK 0x03 +#define WD_CMD_DISCONNECT 0x04 +#define WD_CMD_RESELECT 0x05 +#define WD_CMD_SEL_ATN 0x06 +#define WD_CMD_SEL 0x07 +#define WD_CMD_SEL_ATN_XFER 0x08 +#define WD_CMD_SEL_XFER 0x09 +#define WD_CMD_RESEL_RECEIVE 0x0a +#define WD_CMD_RESEL_SEND 0x0b +#define WD_CMD_WAIT_SEL_RECEIVE 0x0c +#define WD_CMD_SSCC 0x0d +#define WD_CMD_SND_DISC 0x0e +#define WD_CMD_SET_IDI 0x0f +#define WD_CMD_RCV_CMD 0x10 +#define WD_CMD_RCV_DATA 0x11 +#define WD_CMD_RCV_MSG_OUT 0x12 +#define WD_CMD_RCV 0x13 +#define WD_CMD_SND_STATUS 0x14 +#define WD_CMD_SND_DATA 0x15 +#define WD_CMD_SND_MSG_IN 0x16 +#define WD_CMD_SND 0x17 +#define WD_CMD_TRANS_ADDR 0x18 +#define WD_CMD_XFER_PAD 0x19 +#define WD_CMD_TRANS_INFO 0x20 +#define WD_CMD_TRANSFER_PAD 0x21 +#define WD_CMD_SBT_MODE 0x80 + +/* ASR register */ +#define ASR_INT 0x80 +#define ASR_LCI 0x40 +#define ASR_BSY 0x20 +#define ASR_CIP 0x10 +#define ASR_PE 0x02 +#define ASR_DBR 0x01 + +/* SCSI Bus Phases */ +#define PHS_DATA_OUT 0x00 +#define PHS_DATA_IN 0x01 +#define PHS_COMMAND 0x02 +#define PHS_STATUS 0x03 +#define PHS_MESS_OUT 0x06 +#define PHS_MESS_IN 0x07 + +/* Command Status Register definitions */ + + /* reset state interrupts */ +#define CSR_RESET 0x00 +#define CSR_RESET_AF 0x01 + + /* successful completion interrupts */ +#define CSR_RESELECT 0x10 +#define CSR_SELECT 0x11 +#define CSR_SEL_XFER_DONE 0x16 +#define CSR_XFER_DONE 0x18 + + /* paused or aborted interrupts */ +#define CSR_MSGIN 0x20 +#define CSR_SDP 0x21 +#define CSR_SEL_ABORT 0x22 +#define CSR_RESEL_ABORT 0x25 +#define CSR_RESEL_ABORT_AM 0x27 +#define CSR_ABORT 0x28 + + /* terminated interrupts */ +#define CSR_INVALID 0x40 +#define CSR_UNEXP_DISC 0x41 +#define CSR_TIMEOUT 0x42 +#define CSR_PARITY 0x43 +#define CSR_PARITY_ATN 0x44 +#define CSR_BAD_STATUS 0x45 +#define CSR_UNEXP 0x48 + + /* service required interrupts */ +#define CSR_RESEL 0x80 +#define CSR_RESEL_AM 0x81 +#define CSR_DISC 0x85 +#define CSR_SRV_REQ 0x88 + + /* Own ID/CDB Size register */ +#define OWNID_EAF 0x08 +#define OWNID_EHP 0x10 +#define OWNID_RAF 0x20 +#define OWNID_FS_8 0x00 +#define OWNID_FS_12 0x40 +#define OWNID_FS_16 0x80 + + /* Control register */ +#define CTRL_HSP 0x01 +#define CTRL_HA 0x02 +#define CTRL_IDI 0x04 +#define CTRL_EDI 0x08 +#define CTRL_HHP 0x10 +#define CTRL_POLLED 0x00 +#define CTRL_BURST 0x20 +#define CTRL_BUS 0x40 +#define CTRL_DMA 0x80 + + /* Synchronous Transfer Register */ +#define STR_FSS 0x80 + + /* Destination ID register */ +#define DSTID_DPD 0x40 +#define DATA_OUT_DIR 0 +#define DATA_IN_DIR 1 +#define DSTID_SCC 0x80 + + /* Source ID register */ +#define SRCID_MASK 0x07 +#define SRCID_SIV 0x08 +#define SRCID_DSP 0x20 +#define SRCID_ES 0x40 +#define SRCID_ER 0x80 + +/* convernience functions */ +uint8_t wd33c93_device::getunit() +{ + /* return the destination unit id */ + return m_regs[WD_DESTINATION_ID] & SRCID_MASK; +} + +void wd33c93_device::set_xfer_count( int count ) +{ + /* set the count */ + m_regs[WD_TRANSFER_COUNT_LSB] = count & 0xff; + m_regs[WD_TRANSFER_COUNT] = (count >> 8) & 0xff; + m_regs[WD_TRANSFER_COUNT_MSB] = (count >> 16) & 0xff; +} + +int wd33c93_device::get_xfer_count() +{ + /* get the count */ + int count = m_regs[WD_TRANSFER_COUNT_MSB]; + + count <<= 8; + count |= m_regs[WD_TRANSFER_COUNT]; + count <<= 8; + count |= m_regs[WD_TRANSFER_COUNT_LSB]; + + return count; +} + +void wd33c93_device::complete_immediate(int status) +{ + /* reset our timer */ + m_cmd_timer->reset(); + + /* set the new status */ + m_regs[WD_SCSI_STATUS] = status & 0xff; + + /* set interrupt pending */ + m_regs[WD_AUXILIARY_STATUS] |= ASR_INT; + + /* check for error conditions */ + if (get_xfer_count() > 0) + { + /* set data buffer ready */ + m_regs[WD_AUXILIARY_STATUS] |= ASR_DBR; + } + else + { + /* clear data buffer ready */ + m_regs[WD_AUXILIARY_STATUS] &= ~ASR_DBR; + } + + /* clear command in progress and bus busy */ + m_regs[WD_AUXILIARY_STATUS] &= ~(ASR_CIP | ASR_BSY); + + /* if we have a callback, call it */ + if (!m_irq_cb.isnull()) + { + m_irq_cb(1); + } +} + +void wd33c93_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr) +{ + switch (tid) + { + case 0: + complete_immediate(param); + break; + + case 1: + complete_immediate(CSR_SRV_REQ | m_busphase); + break; + + case 2: + m_regs[WD_AUXILIARY_STATUS] &= ~ASR_CIP; + break; + } +} + +void wd33c93_device::complete_cmd(uint8_t status) +{ + /* fire off a timer to complete the command */ + m_cmd_timer->adjust(attotime::from_usec(1), status); +} + +/* command handlers */ +void wd33c93_device::unimplemented_cmd() +{ + LOGMASKED(LOG_COMMANDS | LOG_ERRORS, "%s: Unimplemented SCSI controller command: %02x\n", machine().describe_context(), m_regs[WD_COMMAND]); + + /* complete the command */ + complete_cmd(CSR_INVALID); +} + +void wd33c93_device::invalid_cmd() +{ + LOGMASKED(LOG_COMMANDS | LOG_ERRORS, "%s: Invalid SCSI controller command: %02x\n", machine().describe_context(), m_regs[WD_COMMAND]); + + /* complete the command */ + complete_cmd(CSR_INVALID); +} + +void wd33c93_device::reset_cmd() +{ + int advanced = 0; + + /* see if it wants us to reset with advanced features */ + if (m_regs[WD_OWN_ID] & OWNID_EAF) + { + advanced = 1; + } + + /* clear out all registers */ + memset(m_regs, 0, sizeof(m_regs)); + + /* complete the command */ + complete_cmd(advanced ? CSR_RESET_AF : CSR_RESET); +} + +void wd33c93_device::abort_cmd() +{ + /* complete the command */ + complete_cmd(CSR_ABORT); +} + +void wd33c93_device::disconnect_cmd() +{ + /* complete the command */ + m_regs[WD_AUXILIARY_STATUS] &= ~(ASR_CIP | ASR_BSY); +} + +void wd33c93_device::select_cmd() +{ + uint8_t unit = getunit(); + uint8_t newstatus; + + /* see if we can select that device */ + if (select(unit)) + { + /* device is available - signal selection done */ + newstatus = CSR_SELECT; + + /* determine the next bus phase depending on the command */ + if ((m_regs[WD_COMMAND] & 0x7f) == WD_CMD_SEL_ATN) + { + /* /ATN asserted during select: Move to Message Out Phase to read identify */ + m_busphase = PHS_MESS_OUT; + } + else + { + /* No /ATN asserted: Move to Command Phase */ + m_busphase = PHS_COMMAND; + } + + /* queue up a service request out in the future */ + m_service_req_timer->adjust( attotime::from_usec(50) ); + } + else + { + /* device is not available */ + newstatus = CSR_TIMEOUT; + } + + /* complete the command */ + complete_cmd(newstatus); +} + +void wd33c93_device::selectxfer_cmd() +{ + uint8_t unit = getunit(); + uint8_t newstatus; + + /* see if we can select that device */ + if (select(unit)) + { + if (m_regs[WD_COMMAND_PHASE] < 0x45) + { + /* device is available */ + + /* do the request */ + send_command(&m_regs[WD_CDB_1], 12); + int phase = get_phase(); + + /* set transfer count */ + if (get_xfer_count() > TEMP_INPUT_LEN) + { + LOGMASKED(LOG_ERRORS, "WD33C93: Transfer count too big. Please increase TEMP_INPUT_LEN (size=%d)\n", get_xfer_count()); + set_xfer_count(TEMP_INPUT_LEN); + } + + switch (phase) + { + case SCSI_PHASE_DATAIN: + m_read_pending = true; + break; + } + } + + if (m_read_pending) + { + int len = TEMP_INPUT_LEN; + + if (get_xfer_count() < len) + len = get_xfer_count(); + + memset(&m_temp_input[0], 0, TEMP_INPUT_LEN); + read_data(&m_temp_input[0], len); + m_temp_input_pos = 0; + m_read_pending = false; + } + + m_regs[WD_TARGET_LUN] = 0; + m_regs[WD_CONTROL] |= CTRL_EDI; + m_regs[WD_COMMAND_PHASE] = 0x60; + + /* signal transfer ready */ + newstatus = CSR_SEL_XFER_DONE; + + /* if allowed disconnect, queue a service request */ + if (m_identify & 0x40) + { + /* queue disconnect message in */ + m_busphase = PHS_MESS_IN; + + /* queue up a service request out in the future */ + m_service_req_timer->adjust(attotime::from_usec(50)); + } + } + else + { + /* device is not available */ + newstatus = CSR_TIMEOUT; + + set_xfer_count(0); + } + + /* complete the command */ + complete_cmd(newstatus); +} + +void wd33c93_device::negate_ack() +{ + LOGMASKED(LOG_MISC, "WD33C93: ACK Negated\n"); + + /* complete the command */ + m_regs[WD_AUXILIARY_STATUS] &= ~(ASR_CIP | ASR_BSY); +} + +void wd33c93_device::xferinfo_cmd() +{ + /* make the buffer available right away */ + m_regs[WD_AUXILIARY_STATUS] |= ASR_DBR; + m_regs[WD_AUXILIARY_STATUS] |= ASR_CIP; + + /* the command will be completed once the data is transferred */ + m_deassert_cip_timer->adjust(attotime::from_msec(1)); +} + +/* Handle pending commands */ +void wd33c93_device::dispatch_command() +{ + /* get the command */ + uint8_t cmd = m_regs[WD_COMMAND] & 0x7f; + + switch (cmd) + { + case WD_CMD_RESET: + LOGMASKED(LOG_COMMANDS, "WD33C93: %s - Reset Command\n", machine().describe_context()); + reset_cmd(); + break; + + case WD_CMD_ABORT: + LOGMASKED(LOG_COMMANDS, "WD33C93: %s - Abort Command\n", machine().describe_context()); + abort_cmd(); + break; + + case WD_CMD_NEGATE_ACK: + LOGMASKED(LOG_COMMANDS, "WD33C93: %s - Negate ACK Command\n", machine().describe_context()); + negate_ack(); + break; + + case WD_CMD_DISCONNECT: + LOGMASKED(LOG_COMMANDS, "WD33C93: %s - Disconnect Command\n", machine().describe_context()); + disconnect_cmd(); + break; + + case WD_CMD_SEL_ATN: + case WD_CMD_SEL: + LOGMASKED(LOG_COMMANDS, "WD33C93: %s - Select %sCommand\n", machine().describe_context(), cmd == WD_CMD_SEL_ATN ? "w/ ATN " : ""); + select_cmd(); + break; + + case WD_CMD_SEL_ATN_XFER: + case WD_CMD_SEL_XFER: + LOGMASKED(LOG_COMMANDS, "WD33C93: %s - Select %sand Xfer Command\n", machine().describe_context(), cmd == WD_CMD_SEL_ATN ? "w/ ATN " : ""); + selectxfer_cmd(); + break; + + case WD_CMD_TRANS_INFO: + LOGMASKED(LOG_COMMANDS, "WD33C93: %s - Transfer Info Command\n", machine().describe_context()); + xferinfo_cmd(); + break; + + case WD_CMD_ASSERT_ATN: + case WD_CMD_RESELECT: + case WD_CMD_RESEL_RECEIVE: + case WD_CMD_RESEL_SEND: + case WD_CMD_WAIT_SEL_RECEIVE: + case WD_CMD_SSCC: + case WD_CMD_SND_DISC: + case WD_CMD_SET_IDI: + case WD_CMD_RCV_CMD: + case WD_CMD_RCV_DATA: + case WD_CMD_RCV_MSG_OUT: + case WD_CMD_RCV: + case WD_CMD_SND_STATUS: + case WD_CMD_SND_DATA: + case WD_CMD_SND_MSG_IN: + case WD_CMD_SND: + case WD_CMD_TRANS_ADDR: + case WD_CMD_XFER_PAD: + case WD_CMD_TRANSFER_PAD: + unimplemented_cmd(); + break; + + default: + invalid_cmd(); + break; + } +} + +WRITE8_MEMBER(wd33c93_device::write) +{ + switch (offset) + { + case 0: + { + /* update register select */ + m_sasr = data & 0x1f; + } + break; + + case 1: + { + /* update the register */ + if (m_sasr != WD_SCSI_STATUS && m_sasr <= WD_QUEUE_TAG) + { + m_regs[m_sasr] = data; + } + + switch (m_sasr) + { + case WD_OWN_ID: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Own ID Register (CDB Size) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CONTROL: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Control Register = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_TIMEOUT_PERIOD: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Timeout Period Register = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_1: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Total Sectors Register (CDB1) = %02x\n", machine().describe_context(), m_sasr, data); + m_regs[WD_COMMAND_PHASE] = 0; + break; + case WD_CDB_2: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Total Heads Register (CDB2) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_3: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Total Cylinders Register MSB (CDB3) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_4: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Total Cylinders Register LSB (CDB4) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_5: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Logical Address Register MSB (CDB5) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_6: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Logical Address Register 2nd (CDB6) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_7: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Logical Address Register 3rd (CDB7) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_8: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Logical Address Register LSB (CDB8) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_9: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Sector Number Register (CDB9) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_10: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Head Number Register (CDB10) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_11: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Cylinder Number Register MSB (CDB11) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_CDB_12: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Cylinder Number Register LSB (CDB12) = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_TARGET_LUN: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Target LUN Register = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_COMMAND_PHASE: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Command Phase Register = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_SYNCHRONOUS_TRANSFER: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Synchronous Transfer Register = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_TRANSFER_COUNT_MSB: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Transfer Count Register MSB = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_TRANSFER_COUNT: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Transfer Count Register 2nd = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_TRANSFER_COUNT_LSB: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Transfer Count Register LSB = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_DESTINATION_ID: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Destination ID Register = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_SOURCE_ID: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Source ID Register = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_SCSI_STATUS: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, SCSI Status Register (read-only!) = %02x (ignored)\n", machine().describe_context(), m_sasr, data); + break; + case WD_COMMAND: + /* if we receive a command, schedule to process it */ + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Command Register = %02x - unit %d\n", machine().describe_context(), m_sasr, data, getunit()); + + /* signal we're processing it */ + m_regs[WD_AUXILIARY_STATUS] |= ASR_CIP; + + /* process the command */ + dispatch_command(); + break; + case WD_DATA: + { + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Data Register = %02x\n", machine().describe_context(), m_sasr, data); + + /* if data was written, and we have a count, send to device */ + int count = get_xfer_count(); + + if (m_regs[WD_COMMAND] & 0x80) + count = 1; + + if (count-- > 0) + { + /* write to FIFO */ + if (m_fifo_pos < FIFO_SIZE) + { + m_fifo[m_fifo_pos++] = data; + } + + /* update count */ + set_xfer_count(count); + + /* if we're done with the write, see where we're at */ + if (count == 0) + { + m_regs[WD_AUXILIARY_STATUS] |= ASR_INT; + m_regs[WD_AUXILIARY_STATUS] &= ~ASR_DBR; + + switch (m_busphase) + { + case PHS_MESS_OUT: + { + /* reset fifo */ + m_fifo_pos = 0; + + /* Message out phase. Data is probably SCSI Identify. Move to command phase. */ + m_busphase = PHS_COMMAND; + + m_identify = m_fifo[0]; + } + break; + + case PHS_COMMAND: + { + /* Execute the command. Depending on the command, we'll move to data in or out */ + send_command(&m_fifo[0], 12); + int xfercount = get_length(); + int phase = get_phase(); + + /* reset fifo */ + m_fifo_pos = 0; + + /* set the new count */ + set_xfer_count(xfercount); + + switch (phase) + { + case SCSI_PHASE_STATUS: + m_busphase = PHS_STATUS; + break; + + case SCSI_PHASE_DATAIN: + m_busphase = PHS_DATA_IN; + m_read_pending = true; + break; + + case SCSI_PHASE_DATAOUT: + m_busphase = PHS_DATA_OUT; + break; + } + } + break; + + case PHS_DATA_OUT: + { + /* write data out to device */ + write_data(m_fifo, m_fifo_pos); + + /* reset fifo */ + m_fifo_pos = 0; + + /* move to status phase */ + m_busphase = PHS_STATUS; + } + break; + } + + /* complete the command */ + complete_immediate(CSR_XFER_DONE | m_busphase); + } + } + else + { + LOGMASKED(LOG_MISC | LOG_ERRORS, "WD33C93: Sending data to device with transfer count = 0!. Ignoring...\n"); + } + break; + } + case WD_QUEUE_TAG: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Queue Tag Register = %02x\n", machine().describe_context(), m_sasr, data); + break; + case WD_AUXILIARY_STATUS: + LOGMASKED(LOG_WRITES, "WD33C93: %s - Write Register %02x, Auxiliary Status Register (read-only!) = %02x (ignored)\n", machine().describe_context(), m_sasr, data); + break; + default: + LOGMASKED(LOG_WRITES | LOG_ERRORS, "WD33C93: %s - Write Register %02x, Unknown = %02x (ignored)\n", machine().describe_context(), m_sasr, data); + break; + } + + /* auto-increment register select if not on special registers */ + if (m_sasr != WD_COMMAND && m_sasr != WD_DATA && m_sasr != WD_AUXILIARY_STATUS) + { + m_sasr = (m_sasr + 1) & 0x1f; + } + } + break; + + default: + { + LOGMASKED(LOG_ERRORS, "WD33C93: Write to invalid offset %d (data=%02x)\n", offset, data); + } + break; + } +} + +READ8_MEMBER(wd33c93_device::read) +{ + switch (offset) + { + case 0: + /* read aux status */ + return m_regs[WD_AUXILIARY_STATUS]; + + case 1: + { + switch (m_sasr) + { + case WD_OWN_ID: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Own ID Register (CDB Size) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CONTROL: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Control Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_TIMEOUT_PERIOD: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Timeout Period Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_1: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Total Sectors Register (CDB1) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + m_regs[WD_COMMAND_PHASE] = 0; + break; + case WD_CDB_2: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Total Heads Register (CDB2) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_3: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Total Cylinders Register MSB (CDB3) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_4: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Total Cylinders Register LSB (CDB4) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_5: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Logical Address Register MSB (CDB5) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_6: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Logical Address Register 2nd (CDB6) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_7: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Logical Address Register 3rd (CDB7) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_8: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Logical Address Register LSB (CDB8) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_9: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Sector Number Register (CDB9) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_10: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Head Number Register (CDB10) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_11: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Cylinder Number Register MSB (CDB11) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_CDB_12: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Cylinder Number Register LSB (CDB12) (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_TARGET_LUN: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Target LUN Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_COMMAND_PHASE: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Command Phase Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_SYNCHRONOUS_TRANSFER: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Synchronous Transfer Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_TRANSFER_COUNT_MSB: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Transfer Count Register MSB (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_TRANSFER_COUNT: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Transfer Count Register 2nd (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_TRANSFER_COUNT_LSB: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Transfer Count Register LSB (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_DESTINATION_ID: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Destination ID Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_SOURCE_ID: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Source ID Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_SCSI_STATUS: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, SCSI Status Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + m_regs[WD_AUXILIARY_STATUS] &= ~ASR_INT; + + /* if reading status, clear irq flag */ + if (!m_irq_cb.isnull()) + { + m_irq_cb(0); + } + break; + case WD_COMMAND: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Command Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_DATA: + { + /* we're going to be doing synchronous reads */ + + /* get the transfer count */ + int count = get_xfer_count(); + + /* initialize the return value */ + m_regs[WD_DATA] = 0; + + if (count <= 0 && m_busphase == PHS_MESS_IN) + { + /* move to disconnect */ + complete_cmd(CSR_DISC); + } + else if (count == 1 && m_busphase == PHS_STATUS) + { + /* update the count */ + set_xfer_count(0); + + /* move to message in phase */ + m_busphase = PHS_MESS_IN; + + /* complete the command */ + complete_cmd(CSR_XFER_DONE | m_busphase); + } + else if (count-- > 0) /* make sure we still have data to send */ + { + if (m_read_pending) + { + int len = TEMP_INPUT_LEN; + + if ((count + 1) < len ) + len = count + 1; + read_data(&m_temp_input[0], len); + m_temp_input_pos = 0; + m_read_pending = false; + } + + m_regs[WD_AUXILIARY_STATUS] &= ~ASR_INT; + + /* read in one byte */ + if (m_temp_input_pos < TEMP_INPUT_LEN) + m_regs[WD_DATA] = m_temp_input[m_temp_input_pos++]; + + /* update the count */ + set_xfer_count(count); + + /* transfer finished, see where we're at */ + if (count == 0) + { + if (m_regs[WD_COMMAND_PHASE] != 0x60) + { + /* move to status phase */ + m_busphase = PHS_STATUS; + + /* complete the command */ + complete_cmd(CSR_XFER_DONE | m_busphase); + } + else + { + m_regs[WD_AUXILIARY_STATUS] |= ASR_INT; + m_regs[WD_AUXILIARY_STATUS] &= ~ASR_DBR; + } + } + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Data Register (%02x)\n", machine().describe_context(), WD_DATA, m_regs[WD_DATA]); + } + break; + } + case WD_QUEUE_TAG: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Queue Tag Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + case WD_AUXILIARY_STATUS: + LOGMASKED(LOG_READS, "WD33C93: %s - Read Register %02x, Auxiliary Status Register (%02x)\n", machine().describe_context(), m_sasr, m_regs[m_sasr]); + break; + default: + LOGMASKED(LOG_READS | LOG_ERRORS, "WD33C93: %s - Read Register %02x, Unknown\n", machine().describe_context(), m_sasr); + break; + } + + /* get the register value */ + uint8_t ret = 0xff; + if (m_sasr == WD_AUXILIARY_STATUS || m_sasr <= WD_QUEUE_TAG) + ret = m_regs[m_sasr]; + + /* auto-increment register select if not on special registers */ + if (m_sasr != WD_COMMAND && m_sasr != WD_DATA && m_sasr != WD_AUXILIARY_STATUS) + { + m_sasr = (m_sasr + 1) & 0x1f; + } + + return ret; + } + + default: + LOGMASKED(LOG_READS | LOG_ERRORS, "WD33C93: Read from invalid offset %d\n", offset); + break; + } + + return 0; +} + +wd33c93_device::wd33c93_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + legacy_scsi_host_adapter(mconfig, WD33C93, tag, owner, clock), + m_irq_cb(*this) +{ +} + +void wd33c93_device::device_start() +{ + legacy_scsi_host_adapter::device_start(); + + memset(m_regs, 0, sizeof(m_regs)); + memset(m_fifo, 0, sizeof(m_fifo)); + memset(m_temp_input, 0, sizeof(m_temp_input)); + + m_sasr = 0; + m_fifo_pos = 0; + m_temp_input_pos = 0; + m_busphase = 0; + m_identify = 0; + m_read_pending = 0; + + m_irq_cb.resolve(); + + /* allocate a timer for commands */ + m_cmd_timer = timer_alloc(0); + m_service_req_timer = timer_alloc(1); + m_deassert_cip_timer = timer_alloc(2); + + save_item(NAME(m_sasr)); + save_item(NAME(m_regs)); + save_item(NAME(m_fifo)); + save_item(NAME(m_fifo_pos)); + save_item(NAME(m_temp_input)); + save_item(NAME(m_temp_input_pos)); + save_item(NAME(m_busphase)); + save_item(NAME(m_identify)); + save_item(NAME(m_read_pending)); +} + +int wd33c93_device::dma_read_data(int bytes, uint8_t *data) +{ + int len = bytes; + + if (len >= get_xfer_count()) + len = get_xfer_count(); + + if (len == 0) + return 0; + + if ((m_temp_input_pos + len) >= TEMP_INPUT_LEN) + { + LOGMASKED(LOG_ERRORS, "Reading past end of buffer, increase TEMP_INPUT_LEN size\n"); + len = TEMP_INPUT_LEN - len; + } + + assert(len); + + memcpy(data, &m_temp_input[m_temp_input_pos], len); + + m_temp_input_pos += len; + set_xfer_count(get_xfer_count() - len); + return len; +} + +void wd33c93_device::dma_write_data(int bytes, uint8_t *data) +{ + write_data(data, bytes); +} + +void wd33c93_device::clear_dma() +{ + /* indicate DMA completed by clearing the transfer count */ + set_xfer_count(0); + m_regs[WD_AUXILIARY_STATUS] &= ~ASR_DBR; +} + +int wd33c93_device::get_dma_count() +{ + return get_xfer_count(); +} + +DEFINE_DEVICE_TYPE(WD33C93, wd33c93_device, "wd33c93", "Western Digital WD33C93 SCSI") diff --git a/src/devices/machine/wd33c93.h b/src/devices/machine/wd33c93.h new file mode 100644 index 00000000000..b4a883afca4 --- /dev/null +++ b/src/devices/machine/wd33c93.h @@ -0,0 +1,112 @@ +// license:BSD-3-Clause +// copyright-holders:ElSemi, R. Belmont, Ryan Holtz +/* + * wd33c93.h + * + */ + +#ifndef MAME_MACHINE_WD33C93_H +#define MAME_MACHINE_WD33C93_H + +#pragma once + +#include "legscsi.h" + +class wd33c93_device : public legacy_scsi_host_adapter +{ +public: + // construction/destruction + wd33c93_device(const machine_config &mconfig, const char *tag, device_t *owner) + : wd33c93_device(mconfig, tag, owner, (uint32_t)0) + { + } + + wd33c93_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto irq_cb() { return m_irq_cb.bind(); } + + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); + + int dma_read_data(int bytes, uint8_t *data); + void dma_write_data(int bytes, uint8_t *data); + void clear_dma(); + int get_dma_count(); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + +private: + // wd register names + enum + { + WD_OWN_ID = 0x00, + WD_CONTROL = 0x01, + WD_TIMEOUT_PERIOD = 0x02, + WD_CDB_1 = 0x03, + WD_CDB_2 = 0x04, + WD_CDB_3 = 0x05, + WD_CDB_4 = 0x06, + WD_CDB_5 = 0x07, + WD_CDB_6 = 0x08, + WD_CDB_7 = 0x09, + WD_CDB_8 = 0x0a, + WD_CDB_9 = 0x0b, + WD_CDB_10 = 0x0c, + WD_CDB_11 = 0x0d, + WD_CDB_12 = 0x0e, + WD_TARGET_LUN = 0x0f, + WD_COMMAND_PHASE = 0x10, + WD_SYNCHRONOUS_TRANSFER = 0x11, + WD_TRANSFER_COUNT_MSB = 0x12, + WD_TRANSFER_COUNT = 0x13, + WD_TRANSFER_COUNT_LSB = 0x14, + WD_DESTINATION_ID = 0x15, + WD_SOURCE_ID = 0x16, + WD_SCSI_STATUS = 0x17, + WD_COMMAND = 0x18, + WD_DATA = 0x19, + WD_QUEUE_TAG = 0x1a, + WD_AUXILIARY_STATUS = 0x1f + }; + + static constexpr int TEMP_INPUT_LEN = 262144; + static constexpr int FIFO_SIZE = 12; + + uint8_t getunit(); + void set_xfer_count(int count); + int get_xfer_count(); + void complete_immediate(int status); + void complete_cmd(uint8_t status); + void unimplemented_cmd(); + void invalid_cmd(); + void reset_cmd(); + void abort_cmd(); + void disconnect_cmd(); + void select_cmd(); + void selectxfer_cmd(); + void negate_ack(); + void xferinfo_cmd(); + void dispatch_command(); + + uint8_t m_sasr; + uint8_t m_regs[WD_AUXILIARY_STATUS+1]; + uint8_t m_fifo[FIFO_SIZE]; + int m_fifo_pos; + uint8_t m_temp_input[TEMP_INPUT_LEN]; + int m_temp_input_pos; + uint8_t m_busphase; + uint8_t m_identify; + bool m_read_pending; + emu_timer *m_cmd_timer; + emu_timer *m_service_req_timer; + emu_timer *m_deassert_cip_timer; + devcb_write_line m_irq_cb; /* irq callback */ +}; + +// device type definition +DECLARE_DEVICE_TYPE(WD33C93, wd33c93_device) + +#endif // MAME_MACHINE_WD33C93_H diff --git a/src/devices/machine/wd33c9x.cpp b/src/devices/machine/wd33c9x.cpp index d425a9249b9..2ef063ad449 100644 --- a/src/devices/machine/wd33c9x.cpp +++ b/src/devices/machine/wd33c9x.cpp @@ -29,7 +29,8 @@ #define LOG_REGS (LOG_READS | LOG_WRITES) #define LOG_ALL (LOG_REGS | LOG_COMMANDS | LOG_ERRORS | LOG_MISC | LOG_LINES | LOG_STATE | LOG_STEP) -#define VERBOSE (0) +#define VERBOSE (LOG_COMMANDS | LOG_ERRORS | LOG_STATE) +#define LOG_OUTPUT_FUNC printf #include "logmacro.h" enum register_addresses_e : uint8_t { @@ -278,27 +279,6 @@ enum : uint16_t { INIT_CPT_RECV_BYTE_NACK }; -const char *const wd33c9x_base_device::state_names[] = { - "-", - "IDLE", - "FINISHED", - "DISC_SEL_ARBITRATION", - "INIT_MSG_WAIT_REQ", - "INIT_XFR", - "INIT_XFR_SEND_PAD_WAIT_REQ", - "INIT_XFR_SEND_PAD", - "INIT_XFR_RECV_PAD_WAIT_REQ", - "INIT_XFR_RECV_PAD", - "INIT_XFR_RECV_BYTE_ACK", - "INIT_XFR_RECV_BYTE_NACK", - "INIT_XFR_FUNCTION_COMPLETE", - "INIT_XFR_BUS_COMPLETE", - "INIT_XFR_WAIT_REQ", - "INIT_CPT_RECV_BYTE_ACK", - "INIT_CPT_RECV_WAIT_REQ", - "INIT_CPT_RECV_BYTE_NACK", -}; - enum : uint16_t { // Arbitration ARB_WAIT_BUS_FREE = 1, @@ -319,24 +299,6 @@ enum : uint16_t { RECV_WAIT_REQ_0 }; -const char *const wd33c9x_base_device::substate_names[] = { - "-", - "ARB_WAIT_BUS_FREE", - "ARB_CHECK_FREE", - "ARB_EXAMINE_BUS", - "ARB_ASSERT_SEL", - "ARB_SET_DEST", - "ARB_RELEASE_BUSY", - "ARB_TIMEOUT_BUSY", - "ARB_TIMEOUT_ABORT", - "ARB_DESKEW_WAIT", - "SEND_WAIT_SETTLE", - "SEND_WAIT_REQ_0", - "RECV_WAIT_REQ_1", - "RECV_WAIT_SETTLE", - "RECV_WAIT_REQ_0", -}; - enum : uint16_t { STATE_MASK = 0x00ff, SUB_SHIFT = 8, @@ -348,8 +310,8 @@ enum : uint16_t { // LIVE DEVICE //************************************************************************** -DEFINE_DEVICE_TYPE(WD33C92, wd33c92_device, "wd33c92", "Western Digital WD33C92 SCSI Controller") -DEFINE_DEVICE_TYPE(WD33C93, wd33c93_device, "wd33c93", "Western Digital WD33C93 SCSI Controller") +DEFINE_DEVICE_TYPE(WD33C92, wd33c92_device, "wd33c92", "Western Digital WD33C92 SCSI Controller") +DEFINE_DEVICE_TYPE(WD33C93N, wd33c93n_device, "wd33c93", "Western Digital WD33C93 SCSI Controller") DEFINE_DEVICE_TYPE(WD33C93A, wd33c93a_device, "wd33c93a", "Western Digital WD33C93A SCSI Controller") DEFINE_DEVICE_TYPE(WD33C93B, wd33c93b_device, "wd33c93b", "Western Digital WD33C93B SCSI Controller") @@ -362,10 +324,10 @@ wd33c9x_base_device::wd33c9x_base_device(const machine_config &mconfig, device_t , m_addr{ 0 } , m_regs{ 0 } , m_command_length{ 0 } - , m_last_message{ 0 } , m_scsi_state{ IDLE } , m_mode{ MODE_D } , m_xfr_phase{ 0 } + , m_step_count{ 0 } , m_transfer_count{ 0 } , m_data_fifo{ 0 } , m_data_fifo_pos{ 0 } @@ -393,10 +355,10 @@ void wd33c9x_base_device::device_start() save_item(NAME(m_addr)); save_item(NAME(m_regs)); save_item(NAME(m_command_length)); - save_item(NAME(m_last_message)); save_item(NAME(m_mode)); save_item(NAME(m_scsi_state)); save_item(NAME(m_xfr_phase)); + save_item(NAME(m_step_count)); save_item(NAME(m_transfer_count)); save_item(NAME(m_data_fifo)); save_item(NAME(m_data_fifo_pos)); @@ -422,10 +384,10 @@ void wd33c9x_base_device::device_reset() m_regs[reg] = (QUEUE_TAG <= reg && reg <= INVALID_1E) ? 0xff : 0; } m_command_length = 0; - m_last_message = 0; set_scsi_state(IDLE); m_mode = MODE_D; m_xfr_phase = 0; + m_step_count = 0; m_transfer_count = 0; data_fifo_reset(); irq_fifo_reset(); @@ -470,10 +432,10 @@ void wd33c9x_base_device::scsi_ctrl_changed() // dir_r //------------------------------------------------- -uint8_t wd33c9x_base_device::dir_r(offs_t offset) +READ8_MEMBER(wd33c9x_base_device::dir_r) { m_addr = offset & REGS_MASK; - return indir_reg_r(); + return indir_reg_r(space, 0, mem_mask); } @@ -481,10 +443,10 @@ uint8_t wd33c9x_base_device::dir_r(offs_t offset) // dir_w //------------------------------------------------- -void wd33c9x_base_device::dir_w(offs_t offset, uint8_t data) +WRITE8_MEMBER(wd33c9x_base_device::dir_w) { m_addr = offset & REGS_MASK; - indir_reg_w(data); + indir_reg_w(space, 0, data, mem_mask); } @@ -492,15 +454,15 @@ void wd33c9x_base_device::dir_w(offs_t offset, uint8_t data) // indir_r //------------------------------------------------- -uint8_t wd33c9x_base_device::indir_r(offs_t offset) +READ8_MEMBER(wd33c9x_base_device::indir_r) { switch (offset) { case 0: - return indir_addr_r(); + return indir_addr_r(space, 0, mem_mask); case 1: - return indir_reg_r(); + return indir_reg_r(space, 0, mem_mask); default: - LOGMASKED(LOG_READS | LOG_ERRORS, "Read from invalid offset %d\n", offset); + LOGMASKED(LOG_READS | LOG_ERRORS, "%s: Read from invalid offset %d\n", shortname(), offset); break; } return 0; @@ -511,17 +473,17 @@ uint8_t wd33c9x_base_device::indir_r(offs_t offset) // indir_w //------------------------------------------------- -void wd33c9x_base_device::indir_w(offs_t offset, uint8_t data) +WRITE8_MEMBER(wd33c9x_base_device::indir_w) { switch (offset) { case 0: - indir_addr_w(data); + indir_addr_w(space, 0, data, mem_mask); break; case 1: - indir_reg_w(data); + indir_reg_w(space, 0, data, mem_mask); break; default: - LOGMASKED(LOG_WRITES | LOG_ERRORS, "Write to invalid offset %d (data=%02x)\n", offset, data); + LOGMASKED(LOG_WRITES | LOG_ERRORS, "%s: Write to invalid offset %d (data=%02x)\n", shortname(), offset, data); break; } } @@ -531,10 +493,13 @@ void wd33c9x_base_device::indir_w(offs_t offset, uint8_t data) // indir_addr_r //------------------------------------------------- -uint8_t wd33c9x_base_device::indir_addr_r() +READ8_MEMBER(wd33c9x_base_device::indir_addr_r) { - // Trick to push the interrupt flag after the fifo is empty to help cps3 - return m_regs[AUXILIARY_STATUS] & 0x01 ? m_regs[AUXILIARY_STATUS] & 0x7f : m_regs[AUXILIARY_STATUS]; + if (offset != 0) { + fatalerror("%s: Read from invalid address offset %d\n", shortname(), offset); + } + step(false); + return m_regs[AUXILIARY_STATUS]; } @@ -542,8 +507,11 @@ uint8_t wd33c9x_base_device::indir_addr_r() // indir_addr_w //------------------------------------------------- -void wd33c9x_base_device::indir_addr_w(uint8_t data) +WRITE8_MEMBER(wd33c9x_base_device::indir_addr_w) { + if (offset != 0) { + fatalerror("%s: Write to invalid address offset %d (data=%02x)\n", shortname(), offset, data); + } m_addr = data & REGS_MASK; } @@ -552,11 +520,15 @@ void wd33c9x_base_device::indir_addr_w(uint8_t data) // indir_reg_r //------------------------------------------------- -uint8_t wd33c9x_base_device::indir_reg_r() +READ8_MEMBER(wd33c9x_base_device::indir_reg_r) { + if (offset != 0) { + fatalerror("%s: Read from invalid indirect register offset %d\n", shortname(), offset); + } + uint8_t ret; switch (m_addr) { - case DATA: { + case DATA: if (!(m_regs[AUXILIARY_STATUS] & AUXILIARY_STATUS_DBR)) { // The processor, except in one case, should only // access the Data Register when the DBR bit in the @@ -567,14 +539,9 @@ uint8_t wd33c9x_base_device::indir_reg_r() // Data Register. fatalerror("%s: The host should never access the data register without DBR set.\n", shortname()); } - bool was_full = data_fifo_full(); ret = data_fifo_pop(); - if (data_fifo_empty()) - m_regs[AUXILIARY_STATUS] &= ~AUXILIARY_STATUS_DBR; - if (was_full) - step(false); + m_regs[AUXILIARY_STATUS] &= ~AUXILIARY_STATUS_DBR; break; - } default: if (m_addr == OWN_ID) { @@ -604,8 +571,12 @@ uint8_t wd33c9x_base_device::indir_reg_r() // indir_reg_w //------------------------------------------------- -void wd33c9x_base_device::indir_reg_w(uint8_t data) +WRITE8_MEMBER(wd33c9x_base_device::indir_reg_w) { + if (offset != 0) { + fatalerror("%s: Write to invalid indirect register offset %d (data=%02x)\n", shortname(), offset, data); + } + switch (m_addr) { case SCSI_STATUS: case QUEUE_TAG: // Only for 92/93 and 93A @@ -614,7 +585,7 @@ void wd33c9x_base_device::indir_reg_w(uint8_t data) case INVALID_1D: case INVALID_1E: case AUXILIARY_STATUS: - LOGMASKED(LOG_WRITES | LOG_ERRORS, "Write to read-only register address %d (data=%02x)\n", m_addr, data); + LOGMASKED(LOG_WRITES | LOG_ERRORS, "%s: Write to read-only register address %d (data=%02x)\n", shortname(), m_addr, data); break; case COMMAND: { @@ -666,7 +637,7 @@ void wd33c9x_base_device::indir_reg_w(uint8_t data) WRITE_LINE_MEMBER(wd33c9x_base_device::reset_w) { if (state) { - LOGMASKED(LOG_LINES, "Reset via MR line\n"); + LOGMASKED(LOG_LINES, "%s: Reset via MR line\n", shortname()); device_reset(); } } @@ -724,7 +695,7 @@ void wd33c9x_base_device::start_command() switch (cc) { case COMMAND_CC_RESET: - LOGMASKED(LOG_COMMANDS, "Reset Command\n"); + LOGMASKED(LOG_COMMANDS, "%s: Reset Command\n", shortname()); scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); m_regs[OWN_ID] = m_command_length; @@ -738,18 +709,17 @@ void wd33c9x_base_device::start_command() set_scsi_state(FINISHED); irq_fifo_push((m_regs[OWN_ID] & OWN_ID_EAF) ? SCSI_STATUS_RESET_EAF : SCSI_STATUS_RESET); scsi_id = (m_regs[OWN_ID] & OWN_ID_SCSI_ID); - step(false); break; case COMMAND_CC_ABORT: - LOGMASKED(LOG_COMMANDS, "Abort Command\n"); + LOGMASKED(LOG_COMMANDS, "%s: Abort Command\n", shortname()); set_scsi_state(FINISHED); // FIXME irq_fifo_push((m_regs[OWN_ID] & OWN_ID_EAF) ? SCSI_STATUS_RESET_EAF : SCSI_STATUS_RESET); break; case COMMAND_CC_ASSERT_ATN: - LOGMASKED(LOG_COMMANDS, "Assert ATN Command\n"); + LOGMASKED(LOG_COMMANDS, "%s: Assert ATN Command\n", shortname()); if (m_mode != MODE_I) { fatalerror("%s: ASSERT_ATN command only valid in the Initiator state.", shortname()); } @@ -757,7 +727,7 @@ void wd33c9x_base_device::start_command() return; case COMMAND_CC_NEGATE_ACK: - LOGMASKED(LOG_COMMANDS, "Negate ACK Command\n"); + LOGMASKED(LOG_COMMANDS, "%s: Negate ACK Command\n", shortname()); // FIXME - This is causing problems, so ignore for now. //if (m_mode != MODE_I) { // fatalerror("NEGATE_ACK command only valid in the Initiator state."); @@ -766,27 +736,26 @@ void wd33c9x_base_device::start_command() return; case COMMAND_CC_DISCONNECT: - LOGMASKED(LOG_COMMANDS, "Disconnect Command\n"); + LOGMASKED(LOG_COMMANDS, "%s: Disconnect Command\n", shortname()); scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); m_mode = MODE_D; - set_scsi_state(IDLE); - m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY); + set_scsi_state(FINISHED); + irq_fifo_push(SCSI_STATUS_DISCONNECT); break; case COMMAND_CC_SELECT: case COMMAND_CC_SELECT_ATN: - LOGMASKED(LOG_COMMANDS, "%s Command\n", select_strings[cc - COMMAND_CC_SELECT_ATN]); + LOGMASKED(LOG_COMMANDS, "%s: %s Command\n", shortname(), select_strings[cc - COMMAND_CC_SELECT_ATN]); if (m_mode != MODE_D) { fatalerror("Select commands only valid in the Disconnected state."); } set_scsi_state((ARB_WAIT_BUS_FREE << SUB_SHIFT) | DISC_SEL_ARBITRATION); - step(false); break; case COMMAND_CC_SELECT_TRANSFER: case COMMAND_CC_SELECT_ATN_TRANSFER: - LOGMASKED(LOG_COMMANDS, "%s Command\n", select_strings[cc - COMMAND_CC_SELECT_ATN]); + LOGMASKED(LOG_COMMANDS, "%s: %s Command\n", shortname(), select_strings[cc - COMMAND_CC_SELECT_ATN]); if (m_mode == MODE_D) { set_scsi_state((ARB_WAIT_BUS_FREE << SUB_SHIFT) | DISC_SEL_ARBITRATION); m_regs[COMMAND_PHASE] = COMMAND_PHASE_ZERO; @@ -799,11 +768,10 @@ void wd33c9x_base_device::start_command() } set_command_length(cc); load_transfer_count(); - step(false); break; case COMMAND_CC_TRANSFER_INFO: - LOGMASKED(LOG_COMMANDS, "Transfer Info Command\n"); + LOGMASKED(LOG_COMMANDS, "%s: Transfer Info Command\n", shortname()); if (m_mode != MODE_I) { fatalerror("%s: TRANSFER_INFO command only valid in the Initiator state.", shortname()); } @@ -819,6 +787,8 @@ void wd33c9x_base_device::start_command() fatalerror("%s: Unimplemented command: 0x%02x", shortname(), cc); break; } + + delay(1); } @@ -840,533 +810,563 @@ static const char * phase_strings[8] = { void wd33c9x_base_device::step(bool timeout) { + if (++m_step_count > 1) { + return; + } + const uint8_t cc = (m_regs[COMMAND] & COMMAND_CC); const bool sat = (cc == COMMAND_CC_SELECT_TRANSFER || cc == COMMAND_CC_SELECT_ATN_TRANSFER); - const uint32_t ctrl = scsi_bus->ctrl_r(); - const uint32_t data = scsi_bus->data_r(); - - LOGMASKED(LOG_STEP, - "%s: step - PHASE:%s BSY:%x SEL:%x REQ:%x ACK:%x ATN:%x RST:%x DATA:%02x (%s.%s) %s\n", - shortname(), - phase_strings[ctrl & S_PHASE_MASK], - (ctrl & S_BSY) ? 1 : 0, - (ctrl & S_SEL) ? 1 : 0, - (ctrl & S_REQ) ? 1 : 0, - (ctrl & S_ACK) ? 1 : 0, - (ctrl & S_ATN) ? 1 : 0, - (ctrl & S_RST) ? 1 : 0, - data, - state_names[m_scsi_state & STATE_MASK], substate_names[m_scsi_state >> SUB_SHIFT], - (timeout) ? "timeout" : "change" - ); - - if (m_mode == MODE_I) { - if (ctrl & S_BSY) { - if (ctrl & S_REQ) { - uint8_t xfr_phase = (ctrl & S_PHASE_MASK); - switch (m_scsi_state) { - case DISC_SEL_ARBITRATION: - m_xfr_phase = xfr_phase; - break; + uint32_t cycles = 0; + do { + const uint32_t ctrl = scsi_bus->ctrl_r(); + const uint32_t data = scsi_bus->data_r(); + + m_step_count = 1; + + LOGMASKED(LOG_STEP, + "%s: step - PHASE:%s BSY:%x SEL:%x REQ:%x ACK:%x ATN:%x RST:%x DATA:%x (%d.%d) %s\n", + shortname(), + phase_strings[ctrl & S_PHASE_MASK], + (ctrl & S_BSY) ? 1 : 0, + (ctrl & S_SEL) ? 1 : 0, + (ctrl & S_REQ) ? 1 : 0, + (ctrl & S_ACK) ? 1 : 0, + (ctrl & S_ATN) ? 1 : 0, + (ctrl & S_RST) ? 1 : 0, + data, + m_scsi_state & STATE_MASK, m_scsi_state >> SUB_SHIFT, + (timeout) ? "timeout" : "change" + ); - case INIT_XFR_WAIT_REQ: - break; + if (m_mode == MODE_I) { + if (ctrl & S_BSY) { + if (ctrl & S_REQ) { + uint8_t xfr_phase = (ctrl & S_PHASE_MASK); + switch (m_scsi_state) { + case DISC_SEL_ARBITRATION: + m_xfr_phase = xfr_phase; + break; - default: - if (m_xfr_phase != xfr_phase) { - fatalerror("%s: Unexpected phase change during state.\n", shortname()); + case INIT_XFR_WAIT_REQ: + break; + + default: + if (m_xfr_phase != xfr_phase) { + fatalerror("%s: Unexpected phase change during state.\n", shortname()); + } + break; } - break; } } - } else { - LOGMASKED(LOG_STATE, "Target disconnected\n"); - if (sat) { - switch (m_regs[COMMAND_PHASE]) { - case COMMAND_PHASE_DISCONNECT_MESSAGE: - set_scsi_state(FINISHED); - m_regs[COMMAND_PHASE] = COMMAND_PHASE_DISCONNECTED; - break; - - case COMMAND_PHASE_COMMAND_COMPLETE: - if (m_regs[CONTROL] & CONTROL_EDI) { + else { + LOGMASKED(LOG_STATE, "%s: Target disconnected\n", shortname()); + if (sat) { + switch (m_regs[COMMAND_PHASE]) { + case COMMAND_PHASE_DISCONNECT_MESSAGE: set_scsi_state(FINISHED); - irq_fifo_push(SCSI_STATUS_SELECT_TRANSFER_SUCCESS); - } else { - // Makes very little sense, but the previous code did it and warzard seems to need it - XXX - m_regs[CONTROL] |= CONTROL_EDI; - } - break; + m_regs[COMMAND_PHASE] = COMMAND_PHASE_DISCONNECTED; + break; - default: - fatalerror("%s: Unhandled command phase during Select-and-Transfer disconnect.\n", shortname()); - break; + case COMMAND_PHASE_COMMAND_COMPLETE: + if (m_regs[CONTROL] & CONTROL_EDI) { + set_scsi_state(FINISHED); + irq_fifo_push(SCSI_STATUS_SELECT_TRANSFER_SUCCESS); + } + break; + + default: + fatalerror("%s: Unhandled command phase during Select-and-Transfer disconnect.\n", shortname()); + break; + } } - } else { - set_scsi_state(FINISHED); - irq_fifo_push(SCSI_STATUS_DISCONNECT); + else { + set_scsi_state(FINISHED); + irq_fifo_push(SCSI_STATUS_DISCONNECT); + } + m_mode = MODE_D; + scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); + scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); + continue; } - m_mode = MODE_D; - scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); - scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); } - } - switch (m_scsi_state & SUB_MASK ? m_scsi_state & SUB_MASK : m_scsi_state & STATE_MASK) { - case IDLE: - break; + switch (m_scsi_state & SUB_MASK ? m_scsi_state & SUB_MASK : m_scsi_state & STATE_MASK) { + case IDLE: + break; - case FINISHED: - set_scsi_state(IDLE); - m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY); - update_irq(); - break; + case FINISHED: + set_scsi_state(IDLE); + m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY); + update_irq(); + break; - case ARB_WAIT_BUS_FREE << SUB_SHIFT: - if (!(ctrl & (S_BSY | S_SEL))) { - set_scsi_state_sub(ARB_CHECK_FREE); - delay(1); - } - break; + case ARB_WAIT_BUS_FREE << SUB_SHIFT: + if (timeout) { + if (!(ctrl & (S_BSY | S_SEL))) { + set_scsi_state_sub(ARB_CHECK_FREE); + } + cycles = 1; + } + break; - case ARB_CHECK_FREE << SUB_SHIFT: - if (ctrl & (S_BSY | S_SEL)) { - set_scsi_state_sub(ARB_CHECK_FREE); + case ARB_CHECK_FREE << SUB_SHIFT: + if (timeout) { + uint8_t next_state; + if (ctrl & (S_BSY | S_SEL)) { + next_state = ARB_WAIT_BUS_FREE; + cycles = 1; + } + else { + scsi_bus->data_w(scsi_refid, 1 << scsi_id); + scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); + next_state = ARB_EXAMINE_BUS; + cycles = 1; + } + set_scsi_state_sub(next_state); + } break; - } - if (timeout) { - scsi_bus->data_w(scsi_refid, 1 << scsi_id); - scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); - set_scsi_state_sub(ARB_EXAMINE_BUS); - delay(1); - } - break; - case ARB_EXAMINE_BUS << SUB_SHIFT: - if (timeout) { - if (ctrl & S_SEL) { - scsi_bus->ctrl_w(scsi_refid, 0, S_BSY); - scsi_bus->data_w(scsi_refid, 0); - set_scsi_state_sub(ARB_WAIT_BUS_FREE); - } else { - int win; - for (win = 7; win >=0 && !(data & (1 << win)); win--); - if (win == scsi_id) { - scsi_bus->ctrl_w(scsi_refid, S_SEL, S_SEL); - set_scsi_state_sub(ARB_ASSERT_SEL); - delay(1); - } else { + case ARB_EXAMINE_BUS << SUB_SHIFT: + if (timeout) { + if (ctrl & S_SEL) { + scsi_bus->ctrl_w(scsi_refid, 0, S_BSY); scsi_bus->data_w(scsi_refid, 0); - scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); - set_scsi_state_sub(ARB_CHECK_FREE); + set_scsi_state_sub(ARB_WAIT_BUS_FREE); } + else { + int win; + for (win = 7; win >=0 && !(data & (1 << win)); win--) {}; + if (win == scsi_id) { + scsi_bus->ctrl_w(scsi_refid, S_SEL, S_SEL); + set_scsi_state_sub(ARB_ASSERT_SEL); + } + else { + scsi_bus->data_w(scsi_refid, 0); + scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); + } + } + cycles = 1; } - } - break; + break; - case ARB_ASSERT_SEL << SUB_SHIFT: - if (timeout) { - scsi_bus->data_w(scsi_refid, (1 << scsi_id) | (1 << (m_regs[DESTINATION_ID] & DESTINATION_ID_DI))); - set_scsi_state_sub(ARB_SET_DEST); - delay(1); - } - break; + case ARB_ASSERT_SEL << SUB_SHIFT: + if (timeout) { + scsi_bus->data_w(scsi_refid, (1 << scsi_id) | (1 << (m_regs[DESTINATION_ID] & DESTINATION_ID_DI))); + set_scsi_state_sub(ARB_SET_DEST); + cycles = 1; + } + break; - case ARB_SET_DEST << SUB_SHIFT: - if (timeout) { - scsi_bus->ctrl_w(scsi_refid, (cc == COMMAND_CC_SELECT_ATN || cc == COMMAND_CC_SELECT_ATN_TRANSFER) ? S_ATN : 0, S_ATN | S_BSY); - set_scsi_state_sub(ARB_RELEASE_BUSY); - delay(1); - } - break; + case ARB_SET_DEST << SUB_SHIFT: + if (timeout) { + scsi_bus->ctrl_w(scsi_refid, (cc == COMMAND_CC_SELECT_ATN || cc == COMMAND_CC_SELECT_ATN_TRANSFER) ? S_ATN : 0, S_ATN | S_BSY); + set_scsi_state_sub(ARB_RELEASE_BUSY); + cycles = 1; + } + break; - case ARB_RELEASE_BUSY << SUB_SHIFT: - if (timeout) { - if (ctrl & S_BSY) { - set_scsi_state_sub(ARB_DESKEW_WAIT); - if (cc == COMMAND_CC_RESELECT) { - scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); + case ARB_RELEASE_BUSY << SUB_SHIFT: + if (timeout) { + if (ctrl & S_BSY) { + set_scsi_state_sub(ARB_DESKEW_WAIT); + if (cc == COMMAND_CC_RESELECT) { + scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); + } + cycles = 1; + } + else { + set_scsi_state_sub(ARB_TIMEOUT_BUSY); + cycles = 1; } - delay(1); - } else { - set_scsi_state_sub(ARB_TIMEOUT_BUSY); - delay(1); // Should be the select timeout... } - } - break; - - case ARB_DESKEW_WAIT << SUB_SHIFT: - if (timeout) { - scsi_bus->data_w(scsi_refid, 0); - scsi_bus->ctrl_w(scsi_refid, 0, S_SEL); - m_mode = (cc == COMMAND_CC_RESELECT) ? MODE_T : MODE_I; - set_scsi_state_sub(0); - step(true); - } - break; + break; - case ARB_TIMEOUT_BUSY << SUB_SHIFT: - if (timeout) { - scsi_bus->data_w(scsi_refid, 0); - set_scsi_state_sub(ARB_TIMEOUT_ABORT); - delay(1000); - } else if (ctrl & S_BSY) { - set_scsi_state_sub(ARB_DESKEW_WAIT); - if (cc == COMMAND_CC_RESELECT) { - scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); + case ARB_DESKEW_WAIT << SUB_SHIFT: + if (timeout) { + scsi_bus->data_w(scsi_refid, 0); + scsi_bus->ctrl_w(scsi_refid, 0, S_SEL); + m_mode = (cc == COMMAND_CC_RESELECT) ? MODE_T : MODE_I; + set_scsi_state_sub(0); + ++m_step_count; } - delay(1); - } - break; + break; - case ARB_TIMEOUT_ABORT << SUB_SHIFT: - if (timeout) { - if (ctrl & S_BSY) { + case ARB_TIMEOUT_BUSY << SUB_SHIFT: + if (timeout) { + scsi_bus->data_w(scsi_refid, 0); + set_scsi_state_sub(ARB_TIMEOUT_ABORT); + cycles = 1000; + } + else if (ctrl & S_BSY) { set_scsi_state_sub(ARB_DESKEW_WAIT); if (cc == COMMAND_CC_RESELECT) { scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); } - delay(1); - } else { - scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); - scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); - m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY); - m_mode = MODE_D; - set_scsi_state(IDLE); - irq_fifo_push(SCSI_STATUS_SELECTION_TIMEOUT); - update_irq(); + cycles = 1; } - } - break; + break; - case SEND_WAIT_SETTLE << SUB_SHIFT: - if (timeout) { - set_scsi_state_sub(SEND_WAIT_REQ_0); - step(false); - } - break; + case ARB_TIMEOUT_ABORT << SUB_SHIFT: + if (timeout) { + if (ctrl & S_BSY) { + set_scsi_state_sub(ARB_DESKEW_WAIT); + if (cc == COMMAND_CC_RESELECT) { + scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); + } + cycles = 1; + } + else { + scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); + scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); + m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY); + m_mode = MODE_D; + set_scsi_state(IDLE); + irq_fifo_push(SCSI_STATUS_SELECTION_TIMEOUT); + update_irq(); + } + } + break; - case SEND_WAIT_REQ_0 << SUB_SHIFT: - if (!(ctrl & S_REQ)) { - set_scsi_state_sub(0); - scsi_bus->data_w(scsi_refid, 0); - scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); - if (sat) { - switch (m_xfr_phase) { - case S_PHASE_COMMAND: - ++m_regs[COMMAND_PHASE]; - break; + case SEND_WAIT_SETTLE << SUB_SHIFT: + if (timeout) { + set_scsi_state_sub(SEND_WAIT_REQ_0); + ++m_step_count; + } + break; + + case SEND_WAIT_REQ_0 << SUB_SHIFT: + if (!(ctrl & S_REQ)) { + set_scsi_state_sub(0); + scsi_bus->data_w(scsi_refid, 0); + scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); + if (sat) { + switch (m_xfr_phase) { + case S_PHASE_COMMAND: + ++m_regs[COMMAND_PHASE]; + break; + } } + ++m_step_count; } - step(false); - } - break; + break; - case RECV_WAIT_REQ_1 << SUB_SHIFT: - if (ctrl & S_REQ) { - set_scsi_state_sub(RECV_WAIT_SETTLE); - delay(1); - } - break; + case RECV_WAIT_REQ_1 << SUB_SHIFT: + if (ctrl & S_REQ) { + set_scsi_state_sub(RECV_WAIT_SETTLE); + cycles = 1; + } + break; - case RECV_WAIT_SETTLE << SUB_SHIFT: - if (timeout) { - if (sat) { - switch (m_xfr_phase) { - case S_PHASE_DATA_IN: + case RECV_WAIT_SETTLE << SUB_SHIFT: + if (timeout) { + if (sat) { + switch (m_xfr_phase) { + case S_PHASE_DATA_IN: + data_fifo_push(data); + if ((m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) { + set_drq(); + } + else { + decrement_transfer_count(); + m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; + } + break; + + case S_PHASE_STATUS: + m_regs[TARGET_LUN] = data; + m_regs[COMMAND_PHASE] = COMMAND_PHASE_STATUS_RECEIVED; + break; + + case S_PHASE_MSG_IN: + data_fifo_push(data); + break; + + default: + fatalerror("%s: Unexpected phase in RECV_WAIT_SETTLE.\n", shortname()); + break; + } + } + else { data_fifo_push(data); - if ((m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) { + if (m_xfr_phase == S_PHASE_DATA_IN && (m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) { set_drq(); - } else { + } + else { decrement_transfer_count(); m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; } - break; - - case S_PHASE_STATUS: - m_regs[TARGET_LUN] = data; - m_regs[COMMAND_PHASE] = COMMAND_PHASE_STATUS_RECEIVED; - break; - - case S_PHASE_MSG_IN: - m_last_message = data; - break; - - default: - fatalerror("%s: Unexpected phase in RECV_WAIT_SETTLE.\n", shortname()); - break; - } - } else { - data_fifo_push(data); - if (m_xfr_phase == S_PHASE_DATA_IN && (m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) { - set_drq(); - } else { - decrement_transfer_count(); - m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; } + set_scsi_state_sub(RECV_WAIT_REQ_0); + scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); + ++m_step_count; } - set_scsi_state_sub(RECV_WAIT_REQ_0); - scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); - step(false); - } - break; - - case RECV_WAIT_REQ_0 << SUB_SHIFT: - if (!(ctrl & S_REQ)) { - set_scsi_state_sub(0); - step(false); - } - break; + break; - case DISC_SEL_ARBITRATION: - scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); - if (cc == COMMAND_CC_SELECT || cc == COMMAND_CC_SELECT_ATN) { - set_scsi_state(FINISHED); - irq_fifo_push(SCSI_STATUS_SELECT_SUCCESS); - if (ctrl & S_REQ) { - irq_fifo_push(SCSI_STATUS_REQ | m_xfr_phase); + case RECV_WAIT_REQ_0 << SUB_SHIFT: + if (!(ctrl & S_REQ)) { + set_scsi_state_sub(0); + ++m_step_count; } - } else { - if(cc == COMMAND_CC_SELECT_TRANSFER) { - m_regs[COMMAND_PHASE] = COMMAND_PHASE_CP_BYTES_0; - std::string cmd; - for (uint8_t i = 0; i < m_command_length; ++i) { - const uint8_t command_byte = m_regs[CDB_1 + i]; - cmd += util::string_format(" %02x", command_byte); - data_fifo_push(command_byte); + break; + + case DISC_SEL_ARBITRATION: + scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); + if (cc == COMMAND_CC_SELECT || cc == COMMAND_CC_SELECT_ATN) { + set_scsi_state(FINISHED); + irq_fifo_push(SCSI_STATUS_SELECT_SUCCESS); + if (ctrl & S_REQ) { + irq_fifo_push(SCSI_STATUS_REQ | m_xfr_phase); } - LOGMASKED(LOG_COMMANDS, "Sending command:%s (%d)\n", cmd, m_transfer_count); - } else + } + else { + set_scsi_state(INIT_XFR); m_regs[COMMAND_PHASE] = COMMAND_PHASE_SELECTED; - set_scsi_state(INIT_XFR); - } - step(false); - break; + } + ++m_step_count; + break; - case INIT_XFR: - if (ctrl & S_REQ) { - switch (m_xfr_phase) { - case S_PHASE_DATA_OUT: - if ((m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) { - if(!data_fifo_full() && m_transfer_count > 0) - set_drq(); - } - if (!data_fifo_empty()) { - set_scsi_state(INIT_XFR_WAIT_REQ); - delay(send_byte()); - } else if ((m_regs[CONTROL] & CONTROL_DM) == CONTROL_DM_POLLED) { - m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; - } - break; + case INIT_XFR: + if (ctrl & S_REQ) { + switch (m_xfr_phase) { + case S_PHASE_DATA_OUT: + if ((m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) { + while (!data_fifo_full() && m_transfer_count > 0) { + set_drq(); + } + } + if (!data_fifo_empty()) { + set_scsi_state(INIT_XFR_WAIT_REQ); + cycles = send_byte(); + } + else if ((m_regs[CONTROL] & CONTROL_DM) == CONTROL_DM_POLLED) { + m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; + } + break; - case S_PHASE_COMMAND: - if (!data_fifo_empty()) { - uint32_t mask; - if (sat) { - mask = 0; - } else { + case S_PHASE_COMMAND: + if (!data_fifo_empty()) { + uint32_t mask; + if (sat) { + mask = 0; + } + else { + m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; + mask = (m_transfer_count == 0 && m_data_fifo_size == 1) ? S_ATN : 0; + } + set_scsi_state(INIT_XFR_WAIT_REQ); + cycles = send_byte(0, mask); + } + else if (!sat) { m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; - mask = (m_transfer_count == 0 && m_data_fifo_size == 1) ? S_ATN : 0; } - set_scsi_state(INIT_XFR_WAIT_REQ); - delay(send_byte(0, mask)); - } else if (!sat) { - m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; - } - break; + break; - case S_PHASE_MSG_OUT: - if (sat) { - data_fifo_push(get_msg_out()); - } - if (!data_fifo_empty()) { - uint32_t mask; + case S_PHASE_MSG_OUT: if (sat) { - mask = S_ATN; - } else { + data_fifo_push(get_msg_out()); + } + if (!data_fifo_empty()) { + uint32_t mask; + if (sat) { + mask = S_ATN; + } + else { + m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; + mask = (m_transfer_count == 0 && m_data_fifo_size == 1) ? S_ATN : 0; + } + set_scsi_state(INIT_XFR_WAIT_REQ); + cycles = send_byte(0, mask); + } + else if (!sat) { m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; - mask = (m_transfer_count == 0 && m_data_fifo_size == 1) ? S_ATN : 0; } - set_scsi_state(INIT_XFR_WAIT_REQ); - delay(send_byte(0, mask)); - } else if (!sat) { - m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; - } - break; + break; - case S_PHASE_DATA_IN: - case S_PHASE_STATUS: - case S_PHASE_MSG_IN: - if (!data_fifo_full()) { - // if it's the last message byte, ACK remains asserted, terminate with function_complete() - //state = (m_xfr_phase == S_PHASE_MSG_IN && (!dma_command || tcounter == 1)) ? INIT_XFR_RECV_BYTE_NACK : INIT_XFR_RECV_BYTE_ACK; - scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); - set_scsi_state((RECV_WAIT_REQ_1 << SUB_SHIFT) | INIT_XFR_RECV_BYTE_ACK); - step(false); - } - break; + case S_PHASE_DATA_IN: + case S_PHASE_STATUS: + case S_PHASE_MSG_IN: + if (!data_fifo_full()) { + // if it's the last message byte, ACK remains asserted, terminate with function_complete() + //state = (m_xfr_phase == S_PHASE_MSG_IN && (!dma_command || tcounter == 1)) ? INIT_XFR_RECV_BYTE_NACK : INIT_XFR_RECV_BYTE_ACK; + scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); + set_scsi_state((RECV_WAIT_REQ_1 << SUB_SHIFT) | INIT_XFR_RECV_BYTE_ACK); + if (ctrl & S_REQ) { + ++m_step_count; + } + } + break; - default: - fatalerror("%s: Invalid phase during INIT_XFR.\n", shortname()); - break; + default: + fatalerror("%s: Invalid phase during INIT_XFR.\n", shortname()); + break; + } } - } - break; + break; - case INIT_XFR_WAIT_REQ: - if (ctrl & S_REQ) { - uint16_t next_state = m_scsi_state; + case INIT_XFR_WAIT_REQ: + if (ctrl & S_REQ) { + uint16_t next_state = m_scsi_state; - const uint8_t xfr_phase = (ctrl & S_PHASE_MASK); + const uint8_t xfr_phase = (ctrl & S_PHASE_MASK); - switch ((m_xfr_phase << 3) | xfr_phase) { - case ((S_PHASE_MSG_OUT << 3) | S_PHASE_MSG_OUT): - case ((S_PHASE_COMMAND << 3) | S_PHASE_COMMAND): - case ((S_PHASE_MSG_IN << 3) | S_PHASE_MSG_IN): - next_state = INIT_XFR; - break; + switch ((m_xfr_phase << 3) | xfr_phase) { + case ((S_PHASE_MSG_OUT << 3) | S_PHASE_MSG_OUT): + case ((S_PHASE_COMMAND << 3) | S_PHASE_COMMAND): + case ((S_PHASE_MSG_IN << 3) | S_PHASE_MSG_IN): + next_state = INIT_XFR; + break; - case ((S_PHASE_DATA_IN << 3) | S_PHASE_DATA_IN): - case ((S_PHASE_DATA_OUT << 3) | S_PHASE_DATA_OUT): - if (sat || cc == COMMAND_CC_TRANSFER_INFO) { - if (m_transfer_count > 0 || (m_xfr_phase == S_PHASE_DATA_OUT && !data_fifo_empty())) { - next_state = INIT_XFR; + case ((S_PHASE_DATA_IN << 3) | S_PHASE_DATA_IN): + case ((S_PHASE_DATA_OUT << 3) | S_PHASE_DATA_OUT): + if (sat || cc == COMMAND_CC_TRANSFER_INFO) { + if (m_transfer_count > 0 || (m_xfr_phase == S_PHASE_DATA_OUT && !data_fifo_empty())) { + next_state = INIT_XFR; + } + else { + next_state = FINISHED; + uint8_t scsi_status; + if (sat) { + m_regs[COMMAND_PHASE] = COMMAND_PHASE_TRANSFER_COUNT; + scsi_status = SCSI_STATUS_UNEXPECTED_PHASE; + } + else { + scsi_status = SCSI_STATUS_TRANSFER_SUCCESS; + } + irq_fifo_push(scsi_status | m_xfr_phase); + } } else { + fatalerror("%s: Unhandled command in data phase.\n", shortname()); next_state = FINISHED; - uint8_t scsi_status; - if (sat) { - m_regs[COMMAND_PHASE] = COMMAND_PHASE_TRANSFER_COUNT; - scsi_status = SCSI_STATUS_UNEXPECTED_PHASE; - } - else { - scsi_status = SCSI_STATUS_TRANSFER_SUCCESS; + } + break; + + case ((S_PHASE_MSG_OUT << 3) | S_PHASE_COMMAND): + case ((S_PHASE_COMMAND << 3) | S_PHASE_DATA_OUT): + case ((S_PHASE_COMMAND << 3) | S_PHASE_DATA_IN): + case ((S_PHASE_COMMAND << 3) | S_PHASE_STATUS): + case ((S_PHASE_COMMAND << 3) | S_PHASE_MSG_IN): + case ((S_PHASE_DATA_OUT << 3) | S_PHASE_STATUS): + case ((S_PHASE_DATA_IN << 3) | S_PHASE_STATUS): + case ((S_PHASE_STATUS << 3) | S_PHASE_MSG_IN): + if (!(m_xfr_phase & 1) && !data_fifo_empty()) { + fatalerror("%s: Data FIFO is not empty on phase transition.\n", shortname()); + } + + if (sat) { + switch (xfr_phase) { + case S_PHASE_MSG_OUT: + next_state = INIT_XFR; + break; + + case S_PHASE_COMMAND: + next_state = INIT_XFR; + m_regs[COMMAND_PHASE] = COMMAND_PHASE_CP_BYTES_0; + LOGMASKED(LOG_COMMANDS, "%s: Sending Command:", shortname()); + for (uint8_t i = 0; i < m_command_length; ++i) { + const uint8_t command_byte = m_regs[CDB_1 + i]; + LOGMASKED(LOG_COMMANDS, " %02x", command_byte); + data_fifo_push(command_byte); + } + LOGMASKED(LOG_COMMANDS, " (%d)\n", m_transfer_count); + break; + + case S_PHASE_DATA_OUT: + case S_PHASE_DATA_IN: + next_state = INIT_XFR; + break; + + case S_PHASE_STATUS: + next_state = INIT_XFR; + m_regs[COMMAND_PHASE] = COMMAND_PHASE_RECEIVE_STATUS; + break; + + case S_PHASE_MSG_IN: + next_state = INIT_XFR; + break; + + default: + fatalerror("%s: Unhandled phase in Select-w/Atn-and-Transfer.\n", shortname()); + next_state = FINISHED; + break; } - irq_fifo_push(scsi_status | m_xfr_phase); } - } - else { - fatalerror("%s: Unhandled command in data phase.\n", shortname()); + else if (cc == COMMAND_CC_TRANSFER_INFO) { + next_state = FINISHED; + irq_fifo_push(SCSI_STATUS_TRANSFER_SUCCESS | xfr_phase); + } + else { + fatalerror("%s: Unhandled command in data phase.\n", shortname()); + next_state = FINISHED; + } + break; + + default: + fatalerror("%s: Unhandled phase transition in INIT_XFR_WAIT_REQ.\n", shortname()); next_state = FINISHED; + break; } - break; - case ((S_PHASE_MSG_OUT << 3) | S_PHASE_COMMAND): - case ((S_PHASE_COMMAND << 3) | S_PHASE_DATA_OUT): - case ((S_PHASE_COMMAND << 3) | S_PHASE_DATA_IN): - case ((S_PHASE_COMMAND << 3) | S_PHASE_STATUS): - case ((S_PHASE_COMMAND << 3) | S_PHASE_MSG_IN): - case ((S_PHASE_DATA_OUT << 3) | S_PHASE_STATUS): - case ((S_PHASE_DATA_IN << 3) | S_PHASE_STATUS): - case ((S_PHASE_STATUS << 3) | S_PHASE_MSG_IN): - if (!(m_xfr_phase & 1) && !data_fifo_empty()) { - fatalerror("%s: Data FIFO is not empty on phase transition.\n", shortname()); + if (next_state != m_scsi_state) { + set_scsi_state(next_state); + ++m_step_count; + m_xfr_phase = xfr_phase; } + } + break; - if (sat) { - switch (xfr_phase) { - case S_PHASE_MSG_OUT: - next_state = INIT_XFR; - break; - - case S_PHASE_COMMAND: { - next_state = INIT_XFR; - m_regs[COMMAND_PHASE] = COMMAND_PHASE_CP_BYTES_0; - std::string cmd; - for (uint8_t i = 0; i < m_command_length; ++i) { - const uint8_t command_byte = m_regs[CDB_1 + i]; - cmd += util::string_format(" %02x", command_byte); - data_fifo_push(command_byte); - } - LOGMASKED(LOG_COMMANDS, "Sending command:%s (%d)\n", cmd, m_transfer_count); + case INIT_XFR_RECV_BYTE_ACK: + if (sat && m_xfr_phase == S_PHASE_MSG_IN) { + const uint8_t msg = data_fifo_pop(); + if (m_regs[COMMAND_PHASE] <= COMMAND_PHASE_CP_BYTES_C) { + switch (msg) { + case SM_SAVE_DATA_PTR: + set_scsi_state(FINISHED); + irq_fifo_push(SCSI_STATUS_SAVE_DATA_POINTERS); + m_regs[COMMAND_PHASE] = COMMAND_PHASE_SAVE_DATA_POINTER; break; - } - case S_PHASE_DATA_OUT: - case S_PHASE_DATA_IN: - next_state = INIT_XFR; + case SM_DISCONNECT: + m_regs[COMMAND_PHASE] = COMMAND_PHASE_DISCONNECT_MESSAGE; break; - case S_PHASE_STATUS: - next_state = INIT_XFR; - m_regs[COMMAND_PHASE] = COMMAND_PHASE_RECEIVE_STATUS; + default: + fatalerror("%s: Unhandled MSG_IN.\n", shortname()); break; - - case S_PHASE_MSG_IN: - next_state = INIT_XFR; + } + } + else if (m_regs[COMMAND_PHASE] < COMMAND_PHASE_COMMAND_COMPLETE) { + switch (msg) { + case SM_COMMAND_COMPLETE: + set_scsi_state(FINISHED); + irq_fifo_push(SCSI_STATUS_SELECT_TRANSFER_SUCCESS); + m_regs[COMMAND_PHASE] = COMMAND_PHASE_COMMAND_COMPLETE; break; - default: - fatalerror("%s: Unhandled phase in Select-w/Atn-and-Transfer.\n", shortname()); - next_state = FINISHED; + fatalerror("%s: Unhandled MSG_IN.\n", shortname()); break; } } - else if (cc == COMMAND_CC_TRANSFER_INFO) { - next_state = FINISHED; - irq_fifo_push(SCSI_STATUS_TRANSFER_SUCCESS | xfr_phase); - } - else { - fatalerror("%s: Unhandled command in data phase.\n", shortname()); - next_state = FINISHED; - } - break; - - default: - fatalerror("%s: Unhandled phase transition in INIT_XFR_WAIT_REQ.\n", shortname()); - next_state = FINISHED; - break; } - - if (next_state != m_scsi_state) { - set_scsi_state(next_state); - m_xfr_phase = xfr_phase; - step(false); + else { + set_scsi_state(INIT_XFR_WAIT_REQ); } - } - break; + scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); + ++m_step_count; + break; - case INIT_XFR_RECV_BYTE_ACK: - if (sat && m_xfr_phase == S_PHASE_MSG_IN) { - if (m_regs[COMMAND_PHASE] <= COMMAND_PHASE_CP_BYTES_C) { - switch (m_last_message) { - case SM_SAVE_DATA_PTR: - set_scsi_state(FINISHED); - irq_fifo_push(SCSI_STATUS_SAVE_DATA_POINTERS); - m_regs[COMMAND_PHASE] = COMMAND_PHASE_SAVE_DATA_POINTER; - break; + default: + fatalerror("%s: Unhandled state in step.\n", shortname()); + break; + } - case SM_DISCONNECT: - m_regs[COMMAND_PHASE] = COMMAND_PHASE_DISCONNECT_MESSAGE; - break; + timeout = false; - default: - fatalerror("%s: Unhandled MSG_IN %02x.\n", shortname(), m_last_message); - break; - } - } else if (m_regs[COMMAND_PHASE] < COMMAND_PHASE_COMMAND_COMPLETE) { - switch (m_last_message) { - case SM_COMMAND_COMPLETE: - set_scsi_state(FINISHED); - irq_fifo_push(SCSI_STATUS_SELECT_TRANSFER_SUCCESS); - m_regs[COMMAND_PHASE] = COMMAND_PHASE_COMMAND_COMPLETE; - break; - default: - fatalerror("%s: Unhandled MSG_IN %02x.\n", shortname(), m_last_message); - break; - } - } - } else { - set_scsi_state(INIT_XFR_WAIT_REQ); - } - scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); - step(false); - break; + } while (--m_step_count); - default: - fatalerror("%s: Unhandled state in step.\n", shortname()); - break; + if (cycles) { + delay(cycles); } } @@ -1390,7 +1390,7 @@ void wd33c9x_base_device::load_transfer_count() m_transfer_count = 1; } } - LOGMASKED(LOG_COMMANDS, "Transfer Count %d bytes\n", m_transfer_count); + LOGMASKED(LOG_COMMANDS, "%s: Transfer Count %d bytes\n", shortname(), m_transfer_count); } @@ -1499,9 +1499,7 @@ uint32_t wd33c9x_base_device::send_byte(const uint32_t value, const uint32_t mas void wd33c9x_base_device::set_scsi_state(uint16_t state) { - LOGMASKED(LOG_STEP, "SCSI state change: %s.%s to %s.%s\n", - state_names[m_scsi_state & STATE_MASK], substate_names[m_scsi_state >> SUB_SHIFT], - state_names[state & STATE_MASK], substate_names[state >> SUB_SHIFT]); + LOGMASKED(LOG_STEP, "%s: SCSI state change: %x to %x\n", shortname(), m_scsi_state, state); m_scsi_state = state; } @@ -1590,7 +1588,7 @@ void wd33c9x_base_device::update_irq() { if (m_regs[AUXILIARY_STATUS] & AUXILIARY_STATUS_INT) { m_regs[AUXILIARY_STATUS] &= ~AUXILIARY_STATUS_INT; - LOGMASKED(LOG_LINES, "Clearing IRQ\n"); + LOGMASKED(LOG_LINES, "%s: Clearing IRQ\n", shortname()); m_irq_cb(CLEAR_LINE); } if (!irq_fifo_empty()) { @@ -1614,7 +1612,7 @@ void wd33c9x_base_device::update_irq() } } - LOGMASKED(LOG_LINES, "Asserting IRQ - SCSI Status (%02x)\n", m_regs[SCSI_STATUS]); + LOGMASKED(LOG_LINES, "%s: Asserting IRQ - SCSI Status (%02x)\n", shortname(), m_regs[SCSI_STATUS]); m_irq_cb(ASSERT_LINE); } } @@ -1627,7 +1625,7 @@ void wd33c9x_base_device::update_irq() void wd33c9x_base_device::set_drq() { if (!m_drq_state) { - LOGMASKED(LOG_LINES, "Asserting DRQ\n"); + LOGMASKED(LOG_LINES, "%s: Asserting DRQ\n", shortname()); m_drq_state = true; m_drq_cb(ASSERT_LINE); } @@ -1641,7 +1639,7 @@ void wd33c9x_base_device::set_drq() void wd33c9x_base_device::clear_drq() { if (m_drq_state) { - LOGMASKED(LOG_LINES, "Clearing DRQ\n"); + LOGMASKED(LOG_LINES, "%s: Clearing DRQ\n", shortname()); m_drq_state = false; m_drq_cb(CLEAR_LINE); } @@ -1680,13 +1678,15 @@ bool wd33c9x_base_device::set_command_length(const uint8_t cc) if (eaf && (cc == COMMAND_CC_SELECT_TRANSFER || cc == COMMAND_CC_SELECT_ATN_TRANSFER)) { m_command_length &= OWN_ID_CDB_SIZE; ret = true; - } else if (eaf && cc == COMMAND_CC_WAIT_SELECT_RECEIVE_DATA) { + } + else if (eaf && cc == COMMAND_CC_WAIT_SELECT_RECEIVE_DATA) { m_command_length = 6; m_regs[COMMAND_PHASE] = COMMAND_PHASE_CP_BYTES_1; irq_fifo_push(SCSI_STATUS_NEED_COMMAND_SIZE); update_irq(); ret = false; - } else { + } + else { switch (m_regs[CDB_1] >> 5) { default: case 0: m_command_length = 6; break; @@ -1695,7 +1695,7 @@ bool wd33c9x_base_device::set_command_length(const uint8_t cc) } ret = true; } - LOGMASKED(LOG_COMMANDS, "SCSI Command Length %d bytes\n", m_command_length); + LOGMASKED(LOG_COMMANDS, "%s: SCSI Command Length %d bytes\n", shortname(), m_command_length); return ret; } @@ -1715,8 +1715,8 @@ wd33c92_device::wd33c92_device(const machine_config &mconfig, const char *tag, d { } -wd33c93_device::wd33c93_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : wd33c9x_base_device(mconfig, WD33C93, tag, owner, clock) +wd33c93n_device::wd33c93n_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : wd33c9x_base_device(mconfig, WD33C93N, tag, owner, clock) { } diff --git a/src/devices/machine/wd33c9x.h b/src/devices/machine/wd33c9x.h index 65e97852e00..d5f3b5a5da4 100644 --- a/src/devices/machine/wd33c9x.h +++ b/src/devices/machine/wd33c9x.h @@ -18,18 +18,18 @@ public: auto drq_cb() { return m_drq_cb.bind(); } // Direct Addressing Interface - uint8_t dir_r(offs_t offset); - void dir_w(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(dir_r); + DECLARE_WRITE8_MEMBER(dir_w); // Indirect Addressing Interface - uint8_t indir_r(offs_t offset); - void indir_w(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(indir_r); + DECLARE_WRITE8_MEMBER(indir_w); // Alternative Indirect Addressing Interface - uint8_t indir_addr_r(); - void indir_addr_w(uint8_t data); - uint8_t indir_reg_r(); - void indir_reg_w(uint8_t data); + DECLARE_READ8_MEMBER(indir_addr_r); + DECLARE_WRITE8_MEMBER(indir_addr_w); + DECLARE_READ8_MEMBER(indir_reg_r); + DECLARE_WRITE8_MEMBER(indir_reg_w); // Master Reset (MR) Interface DECLARE_WRITE_LINE_MEMBER(reset_w); @@ -48,14 +48,11 @@ protected: virtual void scsi_ctrl_changed() override; private: - static const char *const state_names[]; - static const char *const substate_names[]; static constexpr uint8_t NUM_REGS = 0x20; static constexpr uint8_t REGS_MASK = NUM_REGS - 1; uint8_t m_addr; uint8_t m_regs[NUM_REGS]; uint8_t m_command_length; - uint8_t m_last_message; void start_command(); @@ -65,6 +62,7 @@ private: uint16_t m_scsi_state; uint8_t m_mode; uint8_t m_xfr_phase; + uint8_t m_step_count; void load_transfer_count(); bool decrement_transfer_count(); @@ -119,15 +117,15 @@ public: wd33c92_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; -class wd33c93_device : public wd33c9x_base_device +class wd33c93n_device : public wd33c9x_base_device { public: - wd33c93_device(const machine_config &mconfig, const char *tag, device_t *owner) - : wd33c93_device(mconfig, tag, owner, 0) + wd33c93n_device(const machine_config &mconfig, const char *tag, device_t *owner) + : wd33c93n_device(mconfig, tag, owner, 0) { } - wd33c93_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + wd33c93n_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; class wd33c93a_device : public wd33c9x_base_device @@ -153,8 +151,8 @@ public: }; -DECLARE_DEVICE_TYPE(WD33C92, wd33c92_device) -DECLARE_DEVICE_TYPE(WD33C93, wd33c93_device) +DECLARE_DEVICE_TYPE(WD33C92, wd33c92_device) +DECLARE_DEVICE_TYPE(WD33C93N, wd33c93n_device) DECLARE_DEVICE_TYPE(WD33C93A, wd33c93a_device) DECLARE_DEVICE_TYPE(WD33C93B, wd33c93b_device) diff --git a/src/devices/machine/wd7600.cpp b/src/devices/machine/wd7600.cpp index 373c371cb5f..9c018fede8e 100644 --- a/src/devices/machine/wd7600.cpp +++ b/src/devices/machine/wd7600.cpp @@ -159,46 +159,46 @@ void wd7600_device::device_start() if (m_space_io->data_width() == 16) { // FIXME: are all these address ranges correct? - m_space_io->install_readwrite_handler(0x0000, 0x000f, read8sm_delegate(FUNC(am9517a_device::read), &(*m_dma1)), write8sm_delegate(FUNC(am9517a_device::write), &(*m_dma1)), 0xffff); + m_space_io->install_readwrite_handler(0x0000, 0x000f, read8_delegate(FUNC(am9517a_device::read), &(*m_dma1)), write8_delegate(FUNC(am9517a_device::write), &(*m_dma1)), 0xffff); m_space_io->install_readwrite_handler(0x0020, 0x003f, read8sm_delegate(FUNC(pic8259_device::read), &(*m_pic1)), write8sm_delegate(FUNC(pic8259_device::write), &(*m_pic1)), 0xffff); m_space_io->install_readwrite_handler(0x0040, 0x0043, read8sm_delegate(FUNC(pit8254_device::read), &(*m_ctc)), write8sm_delegate(FUNC(pit8254_device::write), &(*m_ctc)), 0xffff); - m_space_io->install_readwrite_handler(0x0060, 0x0061, read8smo_delegate(FUNC(wd7600_device::keyb_data_r), this), write8smo_delegate(FUNC(wd7600_device::keyb_data_w), this), 0x00ff); - m_space_io->install_readwrite_handler(0x0060, 0x0061, read8smo_delegate(FUNC(wd7600_device::portb_r), this), write8smo_delegate(FUNC(wd7600_device::portb_w), this), 0xff00); - m_space_io->install_readwrite_handler(0x0064, 0x0065, read8smo_delegate(FUNC(wd7600_device::keyb_status_r), this), write8smo_delegate(FUNC(wd7600_device::keyb_cmd_w), this), 0x00ff); - m_space_io->install_readwrite_handler(0x0070, 0x007f, read8sm_delegate(FUNC(mc146818_device::read), &(*m_rtc)), write8sm_delegate(FUNC(wd7600_device::rtc_w), this), 0xffff); - m_space_io->install_readwrite_handler(0x0080, 0x008f, read8sm_delegate(FUNC(wd7600_device::dma_page_r), this), write8sm_delegate(FUNC(wd7600_device::dma_page_w), this), 0xffff); - m_space_io->install_readwrite_handler(0x0092, 0x0093, read8smo_delegate(FUNC(wd7600_device::a20_reset_r), this), write8smo_delegate(FUNC(wd7600_device::a20_reset_w), this), 0x00ff); + m_space_io->install_readwrite_handler(0x0060, 0x0061, read8_delegate(FUNC(wd7600_device::keyb_data_r), this), write8_delegate(FUNC(wd7600_device::keyb_data_w), this), 0x00ff); + m_space_io->install_readwrite_handler(0x0060, 0x0061, read8_delegate(FUNC(wd7600_device::portb_r), this), write8_delegate(FUNC(wd7600_device::portb_w), this), 0xff00); + m_space_io->install_readwrite_handler(0x0064, 0x0065, read8_delegate(FUNC(wd7600_device::keyb_status_r), this), write8_delegate(FUNC(wd7600_device::keyb_cmd_w), this), 0x00ff); + m_space_io->install_readwrite_handler(0x0070, 0x007f, read8_delegate(FUNC(mc146818_device::read), &(*m_rtc)), write8_delegate(FUNC(wd7600_device::rtc_w), this), 0xffff); + m_space_io->install_readwrite_handler(0x0080, 0x008f, read8_delegate(FUNC(wd7600_device::dma_page_r), this), write8_delegate(FUNC(wd7600_device::dma_page_w), this), 0xffff); + m_space_io->install_readwrite_handler(0x0092, 0x0093, read8_delegate(FUNC(wd7600_device::a20_reset_r), this), write8_delegate(FUNC(wd7600_device::a20_reset_w), this), 0x00ff); m_space_io->install_readwrite_handler(0x00a0, 0x00a3, read8sm_delegate(FUNC(pic8259_device::read), &(*m_pic2)), write8sm_delegate(FUNC(pic8259_device::write), &(*m_pic2)), 0xffff); - m_space_io->install_readwrite_handler(0x00c0, 0x00df, read8sm_delegate(FUNC(am9517a_device::read), &(*m_dma2)), write8sm_delegate(FUNC(am9517a_device::write), &(*m_dma2)), 0x00ff); - m_space_io->install_readwrite_handler(0x2072, 0x2073, read16smo_delegate(FUNC(wd7600_device::refresh_r), this), write16smo_delegate(FUNC(wd7600_device::refresh_w), this)); - m_space_io->install_readwrite_handler(0x2872, 0x2873, read16smo_delegate(FUNC(wd7600_device::chipsel_r), this), write16smo_delegate(FUNC(wd7600_device::chipsel_w), this)); - m_space_io->install_readwrite_handler(0x3872, 0x3873, read16smo_delegate(FUNC(wd7600_device::mem_ctrl_r), this), write16smo_delegate(FUNC(wd7600_device::mem_ctrl_w), this)); - m_space_io->install_readwrite_handler(0x4872, 0x4873, read16s_delegate(FUNC(wd7600_device::bank_01_start_r), this), write16s_delegate(FUNC(wd7600_device::bank_01_start_w), this)); - m_space_io->install_readwrite_handler(0x5072, 0x5073, read16s_delegate(FUNC(wd7600_device::bank_23_start_r), this), write16s_delegate(FUNC(wd7600_device::bank_23_start_w), this)); - m_space_io->install_readwrite_handler(0x5872, 0x5873, read16smo_delegate(FUNC(wd7600_device::split_addr_r), this), write16smo_delegate(FUNC(wd7600_device::split_addr_w), this)); - m_space_io->install_readwrite_handler(0x9872, 0x9873, read16smo_delegate(FUNC(wd7600_device::diag_r), this), write16smo_delegate(FUNC(wd7600_device::diag_w), this)); + m_space_io->install_readwrite_handler(0x00c0, 0x00df, read8_delegate(FUNC(am9517a_device::read), &(*m_dma2)), write8_delegate(FUNC(am9517a_device::write), &(*m_dma2)), 0x00ff); + m_space_io->install_readwrite_handler(0x2072, 0x2073, read16_delegate(FUNC(wd7600_device::refresh_r), this), write16_delegate(FUNC(wd7600_device::refresh_w), this)); + m_space_io->install_readwrite_handler(0x2872, 0x2873, read16_delegate(FUNC(wd7600_device::chipsel_r), this), write16_delegate(FUNC(wd7600_device::chipsel_w), this)); + m_space_io->install_readwrite_handler(0x3872, 0x3873, read16_delegate(FUNC(wd7600_device::mem_ctrl_r), this), write16_delegate(FUNC(wd7600_device::mem_ctrl_w), this)); + m_space_io->install_readwrite_handler(0x4872, 0x4873, read16_delegate(FUNC(wd7600_device::bank_01_start_r), this), write16_delegate(FUNC(wd7600_device::bank_01_start_w), this)); + m_space_io->install_readwrite_handler(0x5072, 0x5073, read16_delegate(FUNC(wd7600_device::bank_23_start_r), this), write16_delegate(FUNC(wd7600_device::bank_23_start_w), this)); + m_space_io->install_readwrite_handler(0x5872, 0x5873, read16_delegate(FUNC(wd7600_device::split_addr_r), this), write16_delegate(FUNC(wd7600_device::split_addr_w), this)); + m_space_io->install_readwrite_handler(0x9872, 0x9873, read16_delegate(FUNC(wd7600_device::diag_r), this), write16_delegate(FUNC(wd7600_device::diag_w), this)); } else { assert(m_space_io->data_width() == 32); - m_space_io->install_readwrite_handler(0x0000, 0x000f, read8sm_delegate(FUNC(am9517a_device::read), &(*m_dma1)), write8sm_delegate(FUNC(am9517a_device::write), &(*m_dma1)), 0xffffffff); + m_space_io->install_readwrite_handler(0x0000, 0x000f, read8_delegate(FUNC(am9517a_device::read), &(*m_dma1)), write8_delegate(FUNC(am9517a_device::write), &(*m_dma1)), 0xffffffff); m_space_io->install_readwrite_handler(0x0020, 0x003f, read8sm_delegate(FUNC(pic8259_device::read), &(*m_pic1)), write8sm_delegate(FUNC(pic8259_device::write), &(*m_pic1)), 0x0000ffff); m_space_io->install_readwrite_handler(0x0040, 0x0043, read8sm_delegate(FUNC(pit8254_device::read), &(*m_ctc)), write8sm_delegate(FUNC(pit8254_device::write), &(*m_ctc)), 0xffffffff); - m_space_io->install_readwrite_handler(0x0060, 0x0063, read8smo_delegate(FUNC(wd7600_device::keyb_data_r), this), write8smo_delegate(FUNC(wd7600_device::keyb_data_w), this), 0x000000ff); - m_space_io->install_readwrite_handler(0x0060, 0x0063, read8smo_delegate(FUNC(wd7600_device::portb_r), this), write8smo_delegate(FUNC(wd7600_device::portb_w), this), 0x0000ff00); - m_space_io->install_readwrite_handler(0x0064, 0x0067, read8smo_delegate(FUNC(wd7600_device::keyb_status_r), this), write8smo_delegate(FUNC(wd7600_device::keyb_cmd_w), this), 0x000000ff); - m_space_io->install_readwrite_handler(0x0070, 0x007f, read8sm_delegate(FUNC(mc146818_device::read), &(*m_rtc)), write8sm_delegate(FUNC(wd7600_device::rtc_w), this), 0x0000ffff); - m_space_io->install_readwrite_handler(0x0080, 0x008f, read8sm_delegate(FUNC(wd7600_device::dma_page_r), this), write8sm_delegate(FUNC(wd7600_device::dma_page_w), this), 0xffffffff); - m_space_io->install_readwrite_handler(0x0090, 0x0093, read8smo_delegate(FUNC(wd7600_device::a20_reset_r), this), write8smo_delegate(FUNC(wd7600_device::a20_reset_w), this), 0x00ff0000); + m_space_io->install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(wd7600_device::keyb_data_r), this), write8_delegate(FUNC(wd7600_device::keyb_data_w), this), 0x000000ff); + m_space_io->install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(wd7600_device::portb_r), this), write8_delegate(FUNC(wd7600_device::portb_w), this), 0x0000ff00); + m_space_io->install_readwrite_handler(0x0064, 0x0067, read8_delegate(FUNC(wd7600_device::keyb_status_r), this), write8_delegate(FUNC(wd7600_device::keyb_cmd_w), this), 0x000000ff); + m_space_io->install_readwrite_handler(0x0070, 0x007f, read8_delegate(FUNC(mc146818_device::read), &(*m_rtc)), write8_delegate(FUNC(wd7600_device::rtc_w), this), 0x0000ffff); + m_space_io->install_readwrite_handler(0x0080, 0x008f, read8_delegate(FUNC(wd7600_device::dma_page_r), this), write8_delegate(FUNC(wd7600_device::dma_page_w), this), 0xffffffff); + m_space_io->install_readwrite_handler(0x0090, 0x0093, read8_delegate(FUNC(wd7600_device::a20_reset_r), this), write8_delegate(FUNC(wd7600_device::a20_reset_w), this), 0x00ff0000); m_space_io->install_readwrite_handler(0x00a0, 0x00a3, read8sm_delegate(FUNC(pic8259_device::read), &(*m_pic2)), write8sm_delegate(FUNC(pic8259_device::write), &(*m_pic2)), 0x0000ffff); - m_space_io->install_readwrite_handler(0x00c0, 0x00df, read8sm_delegate(FUNC(am9517a_device::read), &(*m_dma2)), write8sm_delegate(FUNC(am9517a_device::write), &(*m_dma2)), 0x00ff00ff); - m_space_io->install_readwrite_handler(0x2070, 0x2073, read16smo_delegate(FUNC(wd7600_device::refresh_r), this), write16smo_delegate(FUNC(wd7600_device::refresh_w), this), 0xffff0000); - m_space_io->install_readwrite_handler(0x2870, 0x2873, read16smo_delegate(FUNC(wd7600_device::chipsel_r), this), write16smo_delegate(FUNC(wd7600_device::chipsel_w), this), 0xffff0000); - m_space_io->install_readwrite_handler(0x3870, 0x3873, read16smo_delegate(FUNC(wd7600_device::mem_ctrl_r), this), write16smo_delegate(FUNC(wd7600_device::mem_ctrl_w), this), 0xffff0000); - m_space_io->install_readwrite_handler(0x4870, 0x4873, read16s_delegate(FUNC(wd7600_device::bank_01_start_r), this), write16s_delegate(FUNC(wd7600_device::bank_01_start_w), this), 0xffff0000); - m_space_io->install_readwrite_handler(0x5070, 0x5073, read16s_delegate(FUNC(wd7600_device::bank_23_start_r), this), write16s_delegate(FUNC(wd7600_device::bank_23_start_w), this), 0xffff0000); - m_space_io->install_readwrite_handler(0x5870, 0x5873, read16smo_delegate(FUNC(wd7600_device::split_addr_r), this), write16smo_delegate(FUNC(wd7600_device::split_addr_w), this), 0xffff0000); - m_space_io->install_readwrite_handler(0x9870, 0x9873, read16smo_delegate(FUNC(wd7600_device::diag_r), this), write16smo_delegate(FUNC(wd7600_device::diag_w), this), 0xffff0000); + m_space_io->install_readwrite_handler(0x00c0, 0x00df, read8_delegate(FUNC(am9517a_device::read), &(*m_dma2)), write8_delegate(FUNC(am9517a_device::write), &(*m_dma2)), 0x00ff00ff); + m_space_io->install_readwrite_handler(0x2070, 0x2073, read16_delegate(FUNC(wd7600_device::refresh_r), this), write16_delegate(FUNC(wd7600_device::refresh_w), this), 0xffff0000); + m_space_io->install_readwrite_handler(0x2870, 0x2873, read16_delegate(FUNC(wd7600_device::chipsel_r), this), write16_delegate(FUNC(wd7600_device::chipsel_w), this), 0xffff0000); + m_space_io->install_readwrite_handler(0x3870, 0x3873, read16_delegate(FUNC(wd7600_device::mem_ctrl_r), this), write16_delegate(FUNC(wd7600_device::mem_ctrl_w), this), 0xffff0000); + m_space_io->install_readwrite_handler(0x4870, 0x4873, read16_delegate(FUNC(wd7600_device::bank_01_start_r), this), write16_delegate(FUNC(wd7600_device::bank_01_start_w), this), 0xffff0000); + m_space_io->install_readwrite_handler(0x5070, 0x5073, read16_delegate(FUNC(wd7600_device::bank_23_start_r), this), write16_delegate(FUNC(wd7600_device::bank_23_start_w), this), 0xffff0000); + m_space_io->install_readwrite_handler(0x5870, 0x5873, read16_delegate(FUNC(wd7600_device::split_addr_r), this), write16_delegate(FUNC(wd7600_device::split_addr_w), this), 0xffff0000); + m_space_io->install_readwrite_handler(0x9870, 0x9873, read16_delegate(FUNC(wd7600_device::diag_r), this), write16_delegate(FUNC(wd7600_device::diag_w), this), 0xffff0000); } } @@ -255,7 +255,7 @@ void wd7600_device::keyboard_gatea20(int state) a20m(); } -void wd7600_device::rtc_w(offs_t offset, uint8_t data) +WRITE8_MEMBER( wd7600_device::rtc_w ) { if (offset == 0) { @@ -263,10 +263,10 @@ void wd7600_device::rtc_w(offs_t offset, uint8_t data) data &= 0x7f; } - m_rtc->write(offset, data); + m_rtc->write(space, offset, data); } -uint8_t wd7600_device::pic1_slave_ack_r(offs_t offset) +READ8_MEMBER( wd7600_device::pic1_slave_ack_r ) { if (offset == 2) // IRQ 2 return m_pic2->acknowledge(); @@ -288,36 +288,36 @@ WRITE_LINE_MEMBER( wd7600_device::ctc_out2_w ) } // Keyboard -void wd7600_device::keyb_data_w(uint8_t data) +WRITE8_MEMBER( wd7600_device::keyb_data_w ) { // LOG("WD7600: keyboard data write %02x\n", data); - m_keybc->data_w(data); + m_keybc->data_w(space,0,data); } -uint8_t wd7600_device::keyb_data_r() +READ8_MEMBER( wd7600_device::keyb_data_r ) { - uint8_t ret = m_keybc->data_r(); + uint8_t ret = m_keybc->data_r(space,0); // LOG("WD7600: keyboard data read %02x\n", ret); return ret; } -void wd7600_device::keyb_cmd_w(uint8_t data) +WRITE8_MEMBER( wd7600_device::keyb_cmd_w ) { // LOG("WD7600: keyboard command %02x\n", data); - m_keybc->command_w(data); + m_keybc->command_w(space,0,data); } -uint8_t wd7600_device::keyb_status_r() +READ8_MEMBER( wd7600_device::keyb_status_r ) { - return m_keybc->status_r(); + return m_keybc->status_r(space,0); } -uint8_t wd7600_device::portb_r() +READ8_MEMBER( wd7600_device::portb_r ) { return m_portb; } -void wd7600_device::portb_w(uint8_t data) +WRITE8_MEMBER( wd7600_device::portb_w ) { m_portb = (m_portb & 0xf0) | (data & 0x0f); @@ -352,7 +352,7 @@ offs_t wd7600_device::page_offset() return 0xff0000; } -uint8_t wd7600_device::dma_read_byte(offs_t offset) +READ8_MEMBER( wd7600_device::dma_read_byte ) { if (m_dma_channel == -1) return 0xff; @@ -360,7 +360,7 @@ uint8_t wd7600_device::dma_read_byte(offs_t offset) return m_space->read_byte(page_offset() + offset); } -void wd7600_device::dma_write_byte(offs_t offset, uint8_t data) +WRITE8_MEMBER( wd7600_device::dma_write_byte ) { if (m_dma_channel == -1) return; @@ -368,7 +368,7 @@ void wd7600_device::dma_write_byte(offs_t offset, uint8_t data) m_space->write_byte(page_offset() + offset, data); } -uint8_t wd7600_device::dma_read_word(offs_t offset) +READ8_MEMBER( wd7600_device::dma_read_word ) { if (m_dma_channel == -1) return 0xff; @@ -379,7 +379,7 @@ uint8_t wd7600_device::dma_read_word(offs_t offset) return result; } -void wd7600_device::dma_write_word(offs_t offset, uint8_t data) +WRITE8_MEMBER( wd7600_device::dma_write_word ) { if (m_dma_channel == -1) return; @@ -401,8 +401,6 @@ WRITE_LINE_MEMBER( wd7600_device::dma1_eop_w ) void wd7600_device::set_dma_channel(int channel, bool state) { - //m_write_dack(channel, state); - if (!state) { m_dma_channel = channel; @@ -440,7 +438,7 @@ WRITE_LINE_MEMBER( wd7600_device::kbrst_w ) m_kbrst = state; } -void wd7600_device::a20_reset_w(uint8_t data) +WRITE8_MEMBER( wd7600_device::a20_reset_w ) { m_alt_a20 = BIT(data,1); a20m(); @@ -453,7 +451,7 @@ void wd7600_device::a20_reset_w(uint8_t data) } } -uint8_t wd7600_device::a20_reset_r() +READ8_MEMBER( wd7600_device::a20_reset_r ) { uint8_t ret = 0; if(m_alt_a20) @@ -462,12 +460,12 @@ uint8_t wd7600_device::a20_reset_r() } // port 0x2072 - Refresh Control, and serial/parallel port address select -uint16_t wd7600_device::refresh_r() +READ16_MEMBER(wd7600_device::refresh_r) { return m_refresh_ctrl; } -void wd7600_device::refresh_w(uint16_t data) +WRITE16_MEMBER(wd7600_device::refresh_w) { // TODO: select serial/parallel I/O port location m_refresh_ctrl = data; @@ -475,36 +473,36 @@ void wd7600_device::refresh_w(uint16_t data) } // port 0x2872 - chip select -uint16_t wd7600_device::chipsel_r() +READ16_MEMBER(wd7600_device::chipsel_r) { return m_chip_sel; } -void wd7600_device::chipsel_w(uint16_t data) +WRITE16_MEMBER(wd7600_device::chipsel_w) { m_chip_sel = data; LOG("WD7600: Chip Select write %04x\n", data); } // port 0x3872 - Memory Control -uint16_t wd7600_device::mem_ctrl_r() +READ16_MEMBER(wd7600_device::mem_ctrl_r) { return m_memory_ctrl; } -void wd7600_device::mem_ctrl_w(uint16_t data) +WRITE16_MEMBER(wd7600_device::mem_ctrl_w) { m_memory_ctrl = data; LOG("WD7600: Memory Control write %04x\n", data); } // port 0x4872 - Bank 0 and 1 start address -uint16_t wd7600_device::bank_01_start_r(offs_t offset, uint16_t mem_mask) +READ16_MEMBER(wd7600_device::bank_01_start_r) { return (m_bank_start[1] << 8) | m_bank_start[0]; } -void wd7600_device::bank_01_start_w(offs_t offset, uint16_t data, uint16_t mem_mask) +WRITE16_MEMBER(wd7600_device::bank_01_start_w) { if(ACCESSING_BITS_0_7) { @@ -519,12 +517,12 @@ void wd7600_device::bank_01_start_w(offs_t offset, uint16_t data, uint16_t mem_m } // port 0x5072 - Bank 2 and 3 start address -uint16_t wd7600_device::bank_23_start_r(offs_t offset, uint16_t mem_mask) +READ16_MEMBER(wd7600_device::bank_23_start_r) { return (m_bank_start[3] << 8) | m_bank_start[2]; } -void wd7600_device::bank_23_start_w(offs_t offset, uint16_t data, uint16_t mem_mask) +WRITE16_MEMBER(wd7600_device::bank_23_start_w) { if(ACCESSING_BITS_0_7) { @@ -539,24 +537,24 @@ void wd7600_device::bank_23_start_w(offs_t offset, uint16_t data, uint16_t mem_m } // port 0x5872 - split starting address (used for BIOS shadowing) -uint16_t wd7600_device::split_addr_r() +READ16_MEMBER(wd7600_device::split_addr_r) { return m_split_start; } -void wd7600_device::split_addr_w(uint16_t data) +WRITE16_MEMBER(wd7600_device::split_addr_w) { m_split_start = data; LOG("WD7600: Split start address write %04x\n", data); } // port 0x9872 - Diagnostic -uint16_t wd7600_device::diag_r() +READ16_MEMBER(wd7600_device::diag_r) { return m_diagnostic | 0xe080; } -void wd7600_device::diag_w(uint16_t data) +WRITE16_MEMBER(wd7600_device::diag_w) { m_diagnostic = data; LOG("WD7600: Diagnostic write %04x\n", data); diff --git a/src/devices/machine/wd7600.h b/src/devices/machine/wd7600.h index 43ddb00b038..8f40ed3116f 100644 --- a/src/devices/machine/wd7600.h +++ b/src/devices/machine/wd7600.h @@ -75,20 +75,20 @@ public: DECLARE_WRITE_LINE_MEMBER( gatea20_w ); DECLARE_WRITE_LINE_MEMBER( kbrst_w ); - uint16_t refresh_r(); - void refresh_w(uint16_t data); - uint16_t chipsel_r(); - void chipsel_w(uint16_t data); - uint16_t mem_ctrl_r(); - void mem_ctrl_w(uint16_t data); - uint16_t bank_01_start_r(offs_t offset, uint16_t mem_mask); - void bank_01_start_w(offs_t offset, uint16_t data, uint16_t mem_mask); - uint16_t bank_23_start_r(offs_t offset, uint16_t mem_mask); - void bank_23_start_w(offs_t offset, uint16_t data, uint16_t mem_mask); - uint16_t split_addr_r(); - void split_addr_w(uint16_t data); - uint16_t diag_r(); - void diag_w(uint16_t data); + DECLARE_READ16_MEMBER(refresh_r); + DECLARE_WRITE16_MEMBER(refresh_w); + DECLARE_READ16_MEMBER(chipsel_r); + DECLARE_WRITE16_MEMBER(chipsel_w); + DECLARE_READ16_MEMBER(mem_ctrl_r); + DECLARE_WRITE16_MEMBER(mem_ctrl_w); + DECLARE_READ16_MEMBER(bank_01_start_r); + DECLARE_WRITE16_MEMBER(bank_01_start_w); + DECLARE_READ16_MEMBER(bank_23_start_r); + DECLARE_WRITE16_MEMBER(bank_23_start_w); + DECLARE_READ16_MEMBER(split_addr_r); + DECLARE_WRITE16_MEMBER(split_addr_w); + DECLARE_READ16_MEMBER(diag_r); + DECLARE_WRITE16_MEMBER(diag_w); IRQ_CALLBACK_MEMBER(intack_cb) { return m_pic1->acknowledge(); } @@ -101,39 +101,39 @@ protected: private: DECLARE_WRITE_LINE_MEMBER( pic1_int_w ) { m_write_intr(state); } - uint8_t pic1_slave_ack_r(offs_t offset); + DECLARE_READ8_MEMBER( pic1_slave_ack_r ); DECLARE_WRITE_LINE_MEMBER( ctc_out1_w ); DECLARE_WRITE_LINE_MEMBER( ctc_out2_w ); - void rtc_w(offs_t offset, uint8_t data); - void keyb_cmd_w(uint8_t data); - void keyb_data_w(uint8_t data); - uint8_t keyb_data_r(); - uint8_t keyb_status_r(); - void a20_reset_w(uint8_t data); - uint8_t a20_reset_r(); - uint8_t portb_r(); - void portb_w(uint8_t data); - void dma_page_w(offs_t offset, uint8_t data) { m_dma_page[offset & 0x0f] = data; } - uint8_t dma_page_r(offs_t offset) { return m_dma_page[offset & 0x0f]; } - uint8_t dma_read_byte(offs_t offset); - void dma_write_byte(offs_t offset, uint8_t data); - uint8_t dma_read_word(offs_t offset); - void dma_write_word(offs_t offset, uint8_t data); + DECLARE_WRITE8_MEMBER( rtc_w ); + DECLARE_WRITE8_MEMBER( keyb_cmd_w ); + DECLARE_WRITE8_MEMBER( keyb_data_w ); + DECLARE_READ8_MEMBER( keyb_data_r ); + DECLARE_READ8_MEMBER( keyb_status_r ); + DECLARE_WRITE8_MEMBER( a20_reset_w ); + DECLARE_READ8_MEMBER( a20_reset_r ); + DECLARE_READ8_MEMBER( portb_r ); + DECLARE_WRITE8_MEMBER( portb_w ); + DECLARE_WRITE8_MEMBER( dma_page_w ) { m_dma_page[offset & 0x0f] = data; } + DECLARE_READ8_MEMBER( dma_page_r ) { return m_dma_page[offset & 0x0f]; } + DECLARE_READ8_MEMBER( dma_read_byte ); + DECLARE_WRITE8_MEMBER( dma_write_byte ); + DECLARE_READ8_MEMBER( dma_read_word ); + DECLARE_WRITE8_MEMBER( dma_write_word ); DECLARE_WRITE_LINE_MEMBER( dma1_eop_w ); - uint8_t dma1_ior0_r() { return m_read_ior(0); } - uint8_t dma1_ior1_r() { return m_read_ior(1); } - uint8_t dma1_ior2_r() { return m_read_ior(2); } - uint8_t dma1_ior3_r() { return m_read_ior(3); } - uint8_t dma2_ior1_r() { uint16_t result = m_read_ior(5); m_dma_high_byte = result >> 8; return result; } - uint8_t dma2_ior2_r() { uint16_t result = m_read_ior(6); m_dma_high_byte = result >> 8; return result; } - uint8_t dma2_ior3_r() { uint16_t result = m_read_ior(7); m_dma_high_byte = result >> 8; return result; } - void dma1_iow0_w(uint8_t data) { m_write_iow(0, data, 0xffff); } - void dma1_iow1_w(uint8_t data) { m_write_iow(1, data, 0xffff); } - void dma1_iow2_w(uint8_t data) { m_write_iow(2, data, 0xffff); } - void dma1_iow3_w(uint8_t data) { m_write_iow(3, data, 0xffff); } - void dma2_iow1_w(uint8_t data) { m_write_iow(5, (m_dma_high_byte << 8) | data, 0xffff); } - void dma2_iow2_w(uint8_t data) { m_write_iow(6, (m_dma_high_byte << 8) | data, 0xffff); } - void dma2_iow3_w(uint8_t data) { m_write_iow(7, (m_dma_high_byte << 8) | data, 0xffff); } + DECLARE_READ8_MEMBER( dma1_ior0_r ) { return m_read_ior(0); } + DECLARE_READ8_MEMBER( dma1_ior1_r ) { return m_read_ior(1); } + DECLARE_READ8_MEMBER( dma1_ior2_r ) { return m_read_ior(2); } + DECLARE_READ8_MEMBER( dma1_ior3_r ) { return m_read_ior(3); } + DECLARE_READ8_MEMBER( dma2_ior1_r ) { uint16_t result = m_read_ior(5); m_dma_high_byte = result >> 8; return result; } + DECLARE_READ8_MEMBER( dma2_ior2_r ) { uint16_t result = m_read_ior(6); m_dma_high_byte = result >> 8; return result; } + DECLARE_READ8_MEMBER( dma2_ior3_r ) { uint16_t result = m_read_ior(7); m_dma_high_byte = result >> 8; return result; } + DECLARE_WRITE8_MEMBER( dma1_iow0_w ) { m_write_iow(0, data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma1_iow1_w ) { m_write_iow(1, data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma1_iow2_w ) { m_write_iow(2, data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma1_iow3_w ) { m_write_iow(3, data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma2_iow1_w ) { m_write_iow(5, (m_dma_high_byte << 8) | data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma2_iow2_w ) { m_write_iow(6, (m_dma_high_byte << 8) | data, 0xffff); } + DECLARE_WRITE8_MEMBER( dma2_iow3_w ) { m_write_iow(7, (m_dma_high_byte << 8) | data, 0xffff); } DECLARE_WRITE_LINE_MEMBER( dma1_dack0_w ) { set_dma_channel(0, state); } DECLARE_WRITE_LINE_MEMBER( dma1_dack1_w ) { set_dma_channel(1, state); } DECLARE_WRITE_LINE_MEMBER( dma1_dack2_w ) { set_dma_channel(2, state); } diff --git a/src/devices/machine/x2201.cpp b/src/devices/machine/x2201.cpp index 90d731b7e3e..ec252d1b8dd 100644 --- a/src/devices/machine/x2201.cpp +++ b/src/devices/machine/x2201.cpp @@ -128,6 +128,17 @@ u8 x2201_device::read(offs_t offset) //------------------------------------------------- +// read_byte - read 8 bits of data from RAM +// (FIXME: remove once CRU reads are 1-bit) +//------------------------------------------------- + +u8 x2201_device::read_byte(offs_t offset) +{ + return m_ram[offset & 127]; +} + + +//------------------------------------------------- // write - write one bit of data to RAM //------------------------------------------------- diff --git a/src/devices/machine/x2201.h b/src/devices/machine/x2201.h index 1d873850df1..670c69b349c 100644 --- a/src/devices/machine/x2201.h +++ b/src/devices/machine/x2201.h @@ -38,6 +38,7 @@ public: // read/write handlers u8 read(offs_t offset); + u8 read_byte(offs_t offset); // hack void write(offs_t offset, u8 data); // control lines diff --git a/src/devices/machine/xc1700e.cpp b/src/devices/machine/xc1700e.cpp deleted file mode 100644 index fe056664b07..00000000000 --- a/src/devices/machine/xc1700e.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Patrick Mackinlay - -/* - * An implementation of the Xilinx XC1700E family of serial configuration PROM - * devices, including: - * - * Part Capacity Variants - * -------- --------- ---------------- - * XC1736E 36,288 - * XC1765E 65,536 XC1765EL - * XC17128E 131,072 XC17128EL - * XC17256E 262,144 XC17256EL - * XC17512L 524,288 - * XC1701 1,048,576 XC1701L, XQ1701L - * XC1702L 2,097,152 - * XC1704L 4,194,304 - * - * The input C̅E̅ and CLK lines have not been explicitly implemented; these are - * assumed to be asserted as expected before/during data read. The effect of - * C̅E̅O̅ can be obtained by connecting the cascade_r callback to the data_r of - * the cascaded device and resetting all devices when needed. - * - * This implementation assumes the input data is stored least-significant bit - * first; i.e. the first bit read out of the device is held in the LSB of the - * first byte of the memory region. This convention matches at least one - * dumping device tested. - * - * Sources: - * - * http://www.xilinx.com/support/documentation/data_sheets/ds027.pdf - * - */ - -#include "emu.h" -#include "xc1700e.h" - -#define VERBOSE 0 -#include "logmacro.h" - -DEFINE_DEVICE_TYPE(XC1736E, xc1736e_device, "xc1736e", "Xilinx 36,288 bit Serial PROM") -DEFINE_DEVICE_TYPE(XC1765E, xc1765e_device, "xc1765e", "Xilinx 65,536 bit Serial PROM") -DEFINE_DEVICE_TYPE(XC17128E, xc17128e_device, "xc17128e", "Xilinx 131,072 bit Serial PROM") -DEFINE_DEVICE_TYPE(XC17256E, xc17256e_device, "xc17256e", "Xilinx 262,144 bit Serial PROM") -DEFINE_DEVICE_TYPE(XC17512L, xc17512l_device, "xc17512l", "Xilinx 524,288 bit Serial PROM") -DEFINE_DEVICE_TYPE(XC1701, xc1701_device, "xc1701", "Xilinx 1,048,576 bit Serial PROM") -DEFINE_DEVICE_TYPE(XC1702L, xc1702l_device, "xc1702l", "Xilinx 2,097,152 bit Serial PROM") -DEFINE_DEVICE_TYPE(XC1704L, xc1704l_device, "xc1704l", "Xilinx 4,194,304 bit Serial PROM") - -base_xc1700e_device::base_xc1700e_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 capacity) - : device_t(mconfig, type, tag, owner, clock) - , m_capacity(capacity) - , m_region(*this, DEVICE_SELF) - , m_cascade_cb(*this) - , m_reset(true) - , m_address(0) -{ -} - -void base_xc1700e_device::device_start() -{ - m_cascade_cb.resolve_safe(1); - - save_item(NAME(m_reset)); - save_item(NAME(m_address)); -} - -void base_xc1700e_device::reset_w(int state) -{ - if (state) - m_address = 0; - - m_reset = bool(state); -} - -int base_xc1700e_device::data_r() -{ - if (m_reset) - return 1; - - if (m_address < m_capacity) - { - int const data = BIT(m_region->as_u8(m_address >> 3), m_address & 7); - - m_address++; - - return data; - } - else - return m_cascade_cb(); -} diff --git a/src/devices/machine/xc1700e.h b/src/devices/machine/xc1700e.h deleted file mode 100644 index 42a191c73ce..00000000000 --- a/src/devices/machine/xc1700e.h +++ /dev/null @@ -1,118 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Patrick Mackinlay - -#ifndef MAME_MACHINE_XC1700E_H -#define MAME_MACHINE_XC1700E_H - -#pragma once - -class base_xc1700e_device : public device_t -{ -public: - // configuration - auto cascade_r() { return m_cascade_cb.bind(); } - - // input/output lines - void reset_w(int state); - int data_r(); - -protected: - base_xc1700e_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 capacity); - - // device_t overrides - virtual void device_start() override; - -private: - // device configuration - const u32 m_capacity; - required_memory_region m_region; - - devcb_read_line m_cascade_cb; - - // device state - bool m_reset; - unsigned m_address; -}; - -DECLARE_DEVICE_TYPE(XC1736E, xc1736e_device) -DECLARE_DEVICE_TYPE(XC1765E, xc1765e_device) -DECLARE_DEVICE_TYPE(XC17128E, xc17128e_device) -DECLARE_DEVICE_TYPE(XC17256E, xc17256e_device) -DECLARE_DEVICE_TYPE(XC17512L, xc17512l_device) -DECLARE_DEVICE_TYPE(XC1701, xc1701_device) -DECLARE_DEVICE_TYPE(XC1702L, xc1702l_device) -DECLARE_DEVICE_TYPE(XC1704L, xc1704l_device) - -class xc1736e_device : public base_xc1700e_device -{ -public: - xc1736e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0) - : base_xc1700e_device(mconfig, XC1736E, tag, owner, clock, 36'288UL) - { - } -}; - -class xc1765e_device : public base_xc1700e_device -{ -public: - xc1765e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0) - : base_xc1700e_device(mconfig, XC1765E, tag, owner, clock, 65'536UL) - { - } -}; - -class xc17128e_device : public base_xc1700e_device -{ -public: - xc17128e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0) - : base_xc1700e_device(mconfig, XC17128E, tag, owner, clock, 131'072UL) - { - } -}; - -class xc17256e_device : public base_xc1700e_device -{ -public: - xc17256e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0) - : base_xc1700e_device(mconfig, XC17256E, tag, owner, clock, 262'144UL) - { - } -}; - -class xc17512l_device : public base_xc1700e_device -{ -public: - xc17512l_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0) - : base_xc1700e_device(mconfig, XC17512L, tag, owner, clock, 524'288UL) - { - } -}; - -class xc1701_device : public base_xc1700e_device -{ -public: - xc1701_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0) - : base_xc1700e_device(mconfig, XC1701, tag, owner, clock, 1'048'576UL) - { - } -}; - -class xc1702l_device : public base_xc1700e_device -{ -public: - xc1702l_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0) - : base_xc1700e_device(mconfig, XC1702L, tag, owner, clock, 2'097'152UL) - { - } -}; - -class xc1704l_device : public base_xc1700e_device -{ -public: - xc1704l_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0) - : base_xc1700e_device(mconfig, XC1704L, tag, owner, clock, 4'194'304UL) - { - } -}; - -#endif // MAME_MACHINE_XC1700E_H diff --git a/src/devices/machine/ym2148.cpp b/src/devices/machine/ym2148.cpp index 04a3e53e97e..10eb9c9e6c9 100644 --- a/src/devices/machine/ym2148.cpp +++ b/src/devices/machine/ym2148.cpp @@ -143,7 +143,7 @@ void ym2148_device::device_timer(emu_timer &timer, device_timer_id id, int param } -uint8_t ym2148_device::read(offs_t offset) +READ8_MEMBER(ym2148_device::read) { switch (offset & 7) { @@ -165,7 +165,7 @@ uint8_t ym2148_device::read(offs_t offset) } -void ym2148_device::write(offs_t offset, uint8_t data) +WRITE8_MEMBER(ym2148_device::write) { switch (offset & 7) { diff --git a/src/devices/machine/ym2148.h b/src/devices/machine/ym2148.h index 3cb13bf2058..7f5f45d7066 100644 --- a/src/devices/machine/ym2148.h +++ b/src/devices/machine/ym2148.h @@ -31,8 +31,8 @@ public: auto port_read_handler() { return m_port_read_handler.bind(); } auto irq_handler() { return m_irq_handler.bind(); } - uint8_t read(offs_t offset); - void write(offs_t offset, uint8_t data); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); DECLARE_WRITE_LINE_MEMBER(write_rxd); uint8_t get_irq_vector(); diff --git a/src/devices/machine/z80scc.cpp b/src/devices/machine/z80scc.cpp index b44be5c5873..711d58b8b49 100644 --- a/src/devices/machine/z80scc.cpp +++ b/src/devices/machine/z80scc.cpp @@ -84,9 +84,9 @@ baud rate: -- in the unlikely case of T == 0, pretend T = 1. - If the required wr11 bits are set: -- let's say M = wr4 D7,D6 if 1,1 M = 64; if 1,0 M = 32; if 0,1 M = 16 else M = 1 --- so, the required device clock = 2*T*B*M. +-- so, the required clock on the MCFG_DEVICE_ADD line = 2*T*B*M. - If the required wr11 bits are not set: --- call: configure_channels(X, 0, Y, 0), where X = channel-A-baud * T, +-- add a line: MCFG_Z80SCC_OFFSETS(X, 0, Y, 0), where X = channel-A-baud * T, and Y = channel-B-baud * T. ***************************************************************************/ @@ -436,7 +436,6 @@ z80scc_device::z80scc_device(const machine_config &mconfig, device_type type, co m_out_rxdrq_cb{ { *this }, { *this } }, m_out_txdrq_cb{ { *this }, { *this } }, m_out_int_cb(*this), - m_out_int_state(CLEAR_LINE), m_variant(variant), m_wr0_ptrbits(0), m_cputag(nullptr) @@ -518,7 +517,6 @@ void z80scc_device::device_start() LOG("%s", FUNCNAME); // state saving - save_item(NAME(m_out_int_state)); save_item(NAME(m_int_state)); save_item(NAME(m_int_source)); save_item(NAME(m_wr9)); @@ -683,12 +681,8 @@ void z80scc_device::z80daisy_irq_reti() void z80scc_device::check_interrupts() { int state = (z80daisy_irq_state() & Z80_DAISY_INT) ? ASSERT_LINE : CLEAR_LINE; - if (m_out_int_state != state) - { - m_out_int_state = state; - LOGINT("%s\n", FUNCNAME); - m_out_int_cb(state); - } + LOGINT("%s %s \n",tag(), FUNCNAME); + m_out_int_cb(state); } diff --git a/src/devices/machine/z80scc.h b/src/devices/machine/z80scc.h index 3e8812707dc..e2cad9e660b 100644 --- a/src/devices/machine/z80scc.h +++ b/src/devices/machine/z80scc.h @@ -467,7 +467,6 @@ protected: devcb_write_line m_out_int_cb; - int m_out_int_state; int m_int_state[6]; // interrupt state int m_int_source[6]; // interrupt source diff --git a/src/devices/machine/z80sio.cpp b/src/devices/machine/z80sio.cpp index 8337aeafdf6..82997875f46 100644 --- a/src/devices/machine/z80sio.cpp +++ b/src/devices/machine/z80sio.cpp @@ -242,17 +242,15 @@ DEFINE_DEVICE_TYPE(UPD7201_NEW, upd7201_new_device, "upd7201_new", "NEC uP //------------------------------------------------- // device_add_mconfig - add device configuration //------------------------------------------------- -void z80sio_device::device_add_mconfig(machine_config &config) -{ - Z80SIO_CHANNEL(config, CHANA_TAG, 0); - Z80SIO_CHANNEL(config, CHANB_TAG, 0); -} - -void i8274_new_device::device_add_mconfig(machine_config &config) -{ - I8274_CHANNEL(config, CHANA_TAG, 0); - I8274_CHANNEL(config, CHANB_TAG, 0); -} +MACHINE_CONFIG_START(z80sio_device::device_add_mconfig) + MCFG_DEVICE_ADD(CHANA_TAG, Z80SIO_CHANNEL, 0) + MCFG_DEVICE_ADD(CHANB_TAG, Z80SIO_CHANNEL, 0) +MACHINE_CONFIG_END + +MACHINE_CONFIG_START(i8274_new_device::device_add_mconfig) + MCFG_DEVICE_ADD(CHANA_TAG, I8274_CHANNEL, 0) + MCFG_DEVICE_ADD(CHANB_TAG, I8274_CHANNEL, 0) +MACHINE_CONFIG_END //************************************************************************** |