diff --git a/src/devices/bus/ti99x/998board.cpp b/src/devices/bus/ti99x/998board.cpp index 89d7224fc98..d99c509f08a 100644 --- a/src/devices/bus/ti99x/998board.cpp +++ b/src/devices/bus/ti99x/998board.cpp @@ -137,7 +137,16 @@ mainboard8_device::mainboard8_device(const machine_config &mconfig, const char * m_vaquerro(*this, VAQUERRO_TAG), m_mofetta(*this, MOFETTA_TAG), m_amigo(*this, AMIGO_TAG), - m_oso(*this, OSO_TAG) + m_oso(*this, OSO_TAG), + m_video(*owner, VDP_TAG), // subdevice of main class + m_sound(*owner, TISOUNDCHIP_TAG), + m_speech(*owner, SPEECHSYN_TAG), + m_gromport(*owner, GROMPORT_TAG), + m_peb(*owner, PERIBOX_TAG), + m_sgrom_idle(true), + m_tsgrom_idle(true), + m_p8grom_idle(true), + m_p3grom_idle(true) { } @@ -252,17 +261,33 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in ) if (gromclk != m_gromclk) // when it changed, propagate to the GROMs { m_gromclk = gromclk; - for (int i=0; i < 8; i++) + + // Get some more performance. We only propagate the clock line to + // those GROMs that are not idle. + // Yields about 25% in bench (hoped for more, but well) + if (!m_sgrom_idle) { - if (i < 3) - { - m_sgrom[i]->gclock_in(gromclk); - m_p3grom[i]->gclock_in(gromclk); - } - m_tsgrom[i]->gclock_in(gromclk); - m_p8grom[i]->gclock_in(gromclk); + for (int i=0; i < 3; i++) m_sgrom[i]->gclock_in(gromclk); + m_gromport->gclock_in(gromclk); + m_sgrom_idle = m_sgrom[0]->idle(); + } + + if (!m_tsgrom_idle) + { + for (int i=0; i < 8; i++) m_tsgrom[i]->gclock_in(gromclk); + m_tsgrom_idle = m_tsgrom[0]->idle(); + } + if (!m_p8grom_idle) + { + for (int i=0; i < 8; i++) m_p8grom[i]->gclock_in(gromclk); + m_p8grom_idle = m_p8grom[0]->idle(); + } + + if (!m_p3grom_idle) + { + for (int i=0; i < 3; i++) m_p3grom[i]->gclock_in(gromclk); + m_p3grom_idle = m_p3grom[0]->idle(); } - m_gromport->gclock_in(gromclk); } // Check video for writing @@ -338,16 +363,23 @@ void mainboard8_device::select_groms() int lines = (m_dbin_level==ASSERT_LINE)? GROM_M_LINE : 0; if (m_A14_set) lines |= GROM_MO_LINE; + if (select & SGMSEL) m_sgrom_idle = false; + if (select & TSGSEL) m_tsgrom_idle = false; + if (select & P8GSEL) m_p8grom_idle = false; + if (select & P3GSEL) m_p3grom_idle = false; + + for (int i=0; i < 3; i++) + m_sgrom[i]->set_lines(*m_space, lines, select & SGMSEL); + for (int i=0; i < 8; i++) - { - if (i < 3) - { - m_sgrom[i]->set_lines(*m_space, lines, select & SGMSEL); - m_p3grom[i]->set_lines(*m_space, lines, select & P3GSEL); - } m_tsgrom[i]->set_lines(*m_space, lines, select & TSGSEL); + + for (int i=0; i < 8; i++) m_p8grom[i]->set_lines(*m_space, lines, select & P8GSEL); - } + + for (int i=0; i < 3; i++) + m_p3grom[i]->set_lines(*m_space, lines, select & P3GSEL); + // Write to the cartridge port. The GROMs on cartridges are accesses as system GROMs if (select & SGMSEL) m_gromport->romgq_line(CLEAR_LINE); m_gromport->set_gromlines(*m_space, lines, select & SGMSEL); @@ -476,6 +508,7 @@ READ8_MEMBER( mainboard8_device::read ) switch (m_vaquerro->gromcs_out()) { case SGMSEL: + m_sgrom_idle = false; for (int i=0; i < 3; i++) { m_sgrom[i]->readz(space, 0, &value); @@ -486,6 +519,7 @@ READ8_MEMBER( mainboard8_device::read ) goto readdone; case TSGSEL: + m_tsgrom_idle = false; for (int i=0; i < 8; i++) { m_tsgrom[i]->readz(space, 0, &value); @@ -495,6 +529,7 @@ READ8_MEMBER( mainboard8_device::read ) goto readdone; case P8GSEL: + m_p8grom_idle = false; for (int i=0; i < 8; i++) { m_p8grom[i]->readz(space, 0, &value); @@ -504,6 +539,7 @@ READ8_MEMBER( mainboard8_device::read ) goto readdone; case P3GSEL: + m_p3grom_idle = false; for (int i=0; i < 3; i++) { m_p3grom[i]->readz(space, 0, &value); @@ -751,21 +787,6 @@ void mainboard8_device::device_start() m_p8grom[i] = downcast(machine().device(glib2[i])); } - // Link to speech synthesizer - m_speech = downcast(machine().device(SPEECHSYN_TAG)); - - // Link to sound chip - m_sound = downcast(machine().device(TISOUNDCHIP_TAG)); - - // Link to video - m_video = downcast(machine().device(VDP_TAG)); - - // Link to cartridge port - m_gromport = downcast(machine().device(GROMPORT_TAG)); - - // Link to PEB - m_peb = downcast(machine().device(PERIBOX_TAG)); - // Configure RAM and AMIGO m_sram = std::make_unique(SRAM_SIZE); m_dram = std::make_unique(DRAM_SIZE); diff --git a/src/devices/bus/ti99x/998board.h b/src/devices/bus/ti99x/998board.h index e0ed6b397fa..a743f61d44b 100644 --- a/src/devices/bus/ti99x/998board.h +++ b/src/devices/bus/ti99x/998board.h @@ -505,18 +505,16 @@ private: required_device m_amigo; required_device m_oso; + // More devices + required_device m_video; + required_device m_sound; + required_device m_speech; + required_device m_gromport; + required_device m_peb; + // Debugging line_state m_last_ready; - // Video processor - tms9118_device* m_video; - - // Sound generator - sn76496_base_device* m_sound; - - // Speech processor - cd2501ecd_device* m_speech; - // System GROM library tmc0430_device* m_sgrom[3]; @@ -529,11 +527,11 @@ private: // Pascal 3 GROM library tmc0430_device* m_p3grom[3]; - // Gromport (cartridge port) - gromport_device* m_gromport; - - // Peripheral box - peribox_device* m_peb; + // Idle flags for GROMs + bool m_sgrom_idle; + bool m_tsgrom_idle; + bool m_p8grom_idle; + bool m_p3grom_idle; // Memory std::unique_ptr m_sram; diff --git a/src/devices/bus/ti99x/datamux.cpp b/src/devices/bus/ti99x/datamux.cpp index 1df66bc5c1e..470814b4d9a 100644 --- a/src/devices/bus/ti99x/datamux.cpp +++ b/src/devices/bus/ti99x/datamux.cpp @@ -87,7 +87,8 @@ ti99_datamux_device::ti99_datamux_device(const machine_config &mconfig, const ch m_ram16b(nullptr), m_use32k(false), m_base32k(0), - m_console_groms_present(false) + m_console_groms_present(false), + m_grom_idle(true) { } #define TRACE_READY 0 @@ -119,6 +120,7 @@ void ti99_datamux_device::read_all(address_space& space, UINT16 addr, UINT8 *val } // GROMport (GROMs) m_gromport->readz(space, addr, value); + m_grom_idle = false; } // Video @@ -149,6 +151,7 @@ void ti99_datamux_device::write_all(address_space& space, UINT16 addr, UINT8 val } // GROMport m_gromport->write(space, addr, value); + m_grom_idle = false; } // Cartridge port and sound @@ -190,6 +193,8 @@ void ti99_datamux_device::setaddress_all(address_space& space, UINT16 addr) if (a14==ASSERT_LINE) lines |= 2; line_state select = isgrom? ASSERT_LINE : CLEAR_LINE; + if (select) m_grom_idle = false; + if (m_console_groms_present) for (int i=0; i < 3; i++) m_grom[i]->set_lines(space, lines, select); @@ -519,14 +524,23 @@ WRITE_LINE_MEMBER( ti99_datamux_device::ready_line ) ready_join(); } +/* Called from VDP via console. */ WRITE_LINE_MEMBER( ti99_datamux_device::gromclk_in ) { + // Don't propagate the clock in idle phase + if (m_grom_idle) return; + // Propagate to the GROMs if (m_console_groms_present) { for (int i=0; i < 3; i++) m_grom[i]->gclock_in(state); + m_grom_idle = m_grom[0]->idle(); } m_gromport->gclock_in(state); + + // Only ask the gromport when we don't have GROMs in the console + if (!m_console_groms_present) + m_grom_idle = m_gromport->is_grom_idle(); } /*************************************************************************** diff --git a/src/devices/bus/ti99x/datamux.h b/src/devices/bus/ti99x/datamux.h index 27908d403c6..f95bb67de23 100644 --- a/src/devices/bus/ti99x/datamux.h +++ b/src/devices/bus/ti99x/datamux.h @@ -126,6 +126,9 @@ private: // Console GROMs are available (the HSGPL expects them to be removed) bool m_console_groms_present; + + // GROMs are idle, no need to propagate the clock + bool m_grom_idle; }; /******************************************************************************/ diff --git a/src/devices/bus/ti99x/gromport.cpp b/src/devices/bus/ti99x/gromport.cpp index b0539a7ad8f..cb2b2f869ca 100644 --- a/src/devices/bus/ti99x/gromport.cpp +++ b/src/devices/bus/ti99x/gromport.cpp @@ -234,6 +234,18 @@ void gromport_device::cartridge_inserted() } } +/* + Find out whether the GROMs in the cartridge are idle. In that case, + cut the clock line. +*/ +bool gromport_device::is_grom_idle() +{ + if (m_connector != nullptr) + return m_connector->is_grom_idle(); + else + return false; +} + void gromport_device::device_config_complete() { m_connector = static_cast(subdevices().first()); @@ -347,6 +359,14 @@ WRITE_LINE_MEMBER(single_conn_device::gclock_in) m_cartridge->gclock_in(state); } +/* + Check whether the GROMs are idle. +*/ +bool single_conn_device::is_grom_idle() +{ + return m_cartridge->is_grom_idle(); +} + void single_conn_device::device_start() { m_cartridge = static_cast(subdevices().first()); @@ -619,6 +639,22 @@ WRITE8_MEMBER(multi_conn_device::cruwrite) } } +/* + Check whether the GROMs are idle. Just ask the currently + active cartridge. +*/ +bool multi_conn_device::is_grom_idle() +{ + /* Sanity check. Higher slots are always empty. */ + if (m_active_slot >= NUMBER_OF_CARTRIDGE_SLOTS) + return false; + + if (m_cartridge[m_active_slot] != nullptr) + return m_cartridge[m_active_slot]->is_grom_idle(); + + return false; +} + void multi_conn_device::device_start() { m_next_free_slot = 0; @@ -818,6 +854,14 @@ WRITE_LINE_MEMBER(gkracker_device::gclock_in) if (m_cartridge != nullptr) m_cartridge->gclock_in(state); } +/* + Check whether the GROMs are idle. +*/ +bool gkracker_device::is_grom_idle() +{ + return (m_cartridge != nullptr)? m_cartridge->is_grom_idle() : false; +} + READ8Z_MEMBER(gkracker_device::readz) { if (m_grom_selected) @@ -1466,6 +1510,11 @@ WRITE_LINE_MEMBER(ti99_cartridge_device::gclock_in) if (m_pcb != nullptr) m_pcb->gclock_in(state); } +bool ti99_cartridge_device::is_grom_idle() +{ + return (m_pcb != nullptr)? m_pcb->is_grom_idle() : false; +} + void ti99_cartridge_device::device_config_complete() { update_names(); @@ -1527,6 +1576,7 @@ const device_type TI99CART = &device_creator; ti99_cartridge_pcb::ti99_cartridge_pcb() : m_cart(nullptr), + m_grom_idle(false), m_grom_size(0), m_rom_size(0), m_ram_size(0), @@ -1629,13 +1679,25 @@ WRITE_LINE_MEMBER( ti99_cartridge_pcb::romgq_line ) WRITE8_MEMBER(ti99_cartridge_pcb::set_gromlines) { for (auto& elem : m_grom) - if (elem != nullptr) elem->set_lines(space, offset, data); + { + if (elem != nullptr) + { + elem->set_lines(space, offset, data); + if (data==ASSERT_LINE) m_grom_idle = false; + } + } } WRITE_LINE_MEMBER(ti99_cartridge_pcb::gclock_in) { for (auto& elem : m_grom) - if (elem != nullptr) elem->gclock_in(state); + { + if (elem != nullptr) + { + elem->gclock_in(state); + m_grom_idle = elem->idle(); + } + } } diff --git a/src/devices/bus/ti99x/gromport.h b/src/devices/bus/ti99x/gromport.h index d21497d9d55..694ffb04f3d 100644 --- a/src/devices/bus/ti99x/gromport.h +++ b/src/devices/bus/ti99x/gromport.h @@ -42,6 +42,7 @@ public: template static devcb_base &static_set_reset_callback(device_t &device, _Object object) { return downcast(device).m_console_reset.set_callback(object); } void cartridge_inserted(); + bool is_grom_idle(); protected: virtual void device_start() override; @@ -100,6 +101,7 @@ public: bool is_available() { return m_pcb != nullptr; } void set_slot(int i); + bool is_grom_idle(); protected: virtual void device_start() override { }; @@ -159,8 +161,7 @@ public: virtual void insert(int index, ti99_cartridge_device* cart) { m_gromport->cartridge_inserted(); }; virtual void remove(int index) { }; - // UINT16 grom_base(); - // UINT16 grom_mask(); + virtual bool is_grom_idle() =0; protected: ti99_cartridge_connector_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); @@ -186,6 +187,8 @@ public: DECLARE_WRITE8_MEMBER(set_gromlines) override; DECLARE_WRITE_LINE_MEMBER(gclock_in) override; + bool is_grom_idle(); + protected: virtual void device_start() override; virtual void device_reset() override; @@ -221,6 +224,8 @@ public: void remove(int index) override; DECLARE_INPUT_CHANGED_MEMBER( switch_changed ); + bool is_grom_idle(); + protected: virtual void device_start() override; virtual void device_reset() override; @@ -258,6 +263,9 @@ public: void remove(int index) override; DECLARE_INPUT_CHANGED_MEMBER( gk_changed ); + // We may have a cartridge plugged into the GK + bool is_grom_idle(); + protected: virtual void device_start() override; virtual void device_reset() override; @@ -317,9 +325,11 @@ protected: void set_cartridge(ti99_cartridge_device *cart); const char* tag() { return m_tag; } void set_tag(const char* tag) { m_tag = tag; } + bool is_grom_idle() { return m_grom_idle; } ti99_cartridge_device* m_cart; tmc0430_device* m_grom[5]; + bool m_grom_idle; int m_grom_size; int m_rom_size; int m_ram_size; diff --git a/src/devices/machine/tmc0430.cpp b/src/devices/machine/tmc0430.cpp index 31fe699347e..7a5e2b39c3d 100644 --- a/src/devices/machine/tmc0430.cpp +++ b/src/devices/machine/tmc0430.cpp @@ -211,7 +211,7 @@ WRITE_LINE_MEMBER( tmc0430_device::gclock_in ) if ((m_current_clock_level==CLEAR_LINE) || (oldlevel==ASSERT_LINE)) return; - if (TRACE_CLOCK) logerror("GROMCLK in, phase=%d, m_add=%d\n", m_phase, m_address); + if (TRACE_CLOCK) logerror("GROMCLK in, phase=%d, m_add=%04x\n", m_phase, m_address); switch (m_phase) { diff --git a/src/devices/machine/tmc0430.h b/src/devices/machine/tmc0430.h index 6dcf44c3ec0..615dfb9063d 100644 --- a/src/devices/machine/tmc0430.h +++ b/src/devices/machine/tmc0430.h @@ -53,6 +53,9 @@ public: int debug_get_address(); + // Allow for checking the state of the GROM so we can turn off the clock + bool idle() { return m_phase == 0; } + protected: void device_start(void) override; void device_reset(void) override;