From c7aeff7d6d35e1478e015148b1d5dcc248e897be Mon Sep 17 00:00:00 2001 From: Michael Zapf Date: Tue, 19 Apr 2016 22:03:27 +0200 Subject: [PATCH] ti99: Again one indirection less; dropped the videowrp and moved the v9938 on the EVPC board. --- scripts/src/bus.lua | 2 - src/devices/bus/ti99_peb/evpc.cpp | 376 ++++++++----- src/devices/bus/ti99_peb/evpc.h | 36 +- src/devices/bus/ti99_peb/hsgpl.cpp | 80 +-- src/devices/bus/ti99_peb/peribox.cpp | 24 +- src/devices/bus/ti99_peb/peribox.h | 8 + src/devices/bus/ti99_peb/samsmem.cpp | 48 +- src/devices/bus/ti99_peb/samsmem.h | 11 +- src/devices/bus/ti99x/datamux.cpp | 35 +- src/devices/bus/ti99x/datamux.h | 3 +- src/devices/bus/ti99x/ti99defs.h | 39 +- src/devices/bus/ti99x/videowrp.cpp | 121 ----- src/devices/bus/ti99x/videowrp.h | 93 ---- src/mame/drivers/ti99_4p.cpp | 759 ++++++++++++++++----------- src/mame/drivers/ti99_4x.cpp | 107 +++- src/mame/drivers/ti99_8.cpp | 1 - 16 files changed, 968 insertions(+), 775 deletions(-) delete mode 100644 src/devices/bus/ti99x/videowrp.cpp delete mode 100644 src/devices/bus/ti99x/videowrp.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 9272b2384c2..78032cabff0 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2076,8 +2076,6 @@ if (BUSES["TI99X"]~=null) then MAME_DIR .. "src/devices/bus/ti99x/mecmouse.cpp", MAME_DIR .. "src/devices/bus/ti99x/mecmouse.h", MAME_DIR .. "src/devices/bus/ti99x/ti99defs.h", - MAME_DIR .. "src/devices/bus/ti99x/videowrp.cpp", - MAME_DIR .. "src/devices/bus/ti99x/videowrp.h", } end diff --git a/src/devices/bus/ti99_peb/evpc.cpp b/src/devices/bus/ti99_peb/evpc.cpp index 6945df0dcc6..1d56c00458f 100644 --- a/src/devices/bus/ti99_peb/evpc.cpp +++ b/src/devices/bus/ti99_peb/evpc.cpp @@ -1,39 +1,99 @@ // license:LGPL-2.1+ // copyright-holders:Michael Zapf /**************************************************************************** - SNUG Enhanced Video Processor Card (evpc) - based on v9938 (may also be equipped with v9958) - Can be used with TI-99/4A as an add-on card; internal VDP must be removed + SNUG Enhanced Video Processor Card (EVPC) + + This is an expansion card with an own v9938 video processor on board. + Later releases (EVPC2) can also be equipped with a v9958. + + The EVPC is intended to be used + 1. with the TI-99/4A console + 2. with the SGCPU + + For option 1, the console-internal VDP (TMS9928A) must be removed. This, + however, raises a problem, because the video interrupt must now be send + from the EVPC in the Peripheral Expansion Box to the console, but there is + no line in the PEB cable for this purpose. + + To solve this issue, a separate cable is led from the EVPC to the console + which delivers the video interrupt, and also the GROM clock which is also + lost due to the removal of the internal VDP. + + The SGCPU requires this card, as it does not offer any video processor. + In this configuration, the video interrupt cable is not required. + + Also, the SGCPU does not offer a socket for the sound chip of the TI + console, and accordingly, the EVPC also gives the sound chip a new home. + Thus we assume that in the TI console (option 1) the sound chip has + also been removed. + + Important note: The DSR (firmware) of the EVPC expects a memory expansion + to be present; otherwise, the configuration (using CALL EVPC) will crash. + There is no warning if the 32K expansion is not present. - The SGCPU ("TI-99/4P") only runs with EVPC. Michael Zapf - October 2010: Rewritten as device - February 2012: Rewritten as class - - FIXME: Locks up on startup when HFDC is present. This can be avoided - by using another controller (like bwg) or doing a soft reset. - *****************************************************************************/ #include "evpc.h" #define EVPC_CRU_BASE 0x1400 -#define VERBOSE 1 -#define LOG logerror + +#define TRACE_ADDRESS 0 +#define TRACE_CRU 0 +#define TRACE_MEM 0 #define NOVRAM_SIZE 256 snug_enhanced_video_device::snug_enhanced_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : ti_expansion_card_device(mconfig, TI99_EVPC, "SNUG Enhanced Video Processor Card", tag, owner, clock, "ti99_evpc", __FILE__), device_nvram_interface(mconfig, *this), - m_dsrrom(nullptr), - m_RAMEN(false), m_dsr_page(0), - m_novram(nullptr) + m_inDsrArea(false), + m_novram_accessed(false), + m_palette_accessed(false), + m_RAMEN(false), + m_dsrrom(nullptr), + m_novram(nullptr), + m_video(*this, VDP_TAG), + m_sound(*this, TISOUNDCHIP_TAG) { } +SETADDRESS_DBIN_MEMBER( snug_enhanced_video_device::setaddress_dbin ) +{ + // Do not allow setaddress for the debugger. It will mess up the + // setaddress/memory access pairs when the CPU enters wait states. + if (space.debugger_access()) return; + + if (TRACE_ADDRESS) logerror("set address %04x, %s\n", offset, (state==ASSERT_LINE)? "read" : "write"); + + m_address = offset; + bool reading = (state==ASSERT_LINE); + int offbase = (m_address & 0xfc01); + + // Sound + m_sound_accessed = ((m_address & 0xff01)==0x8400) && !reading; + + // Video space + // 8800 / 8802 / 8804 / 8806 + // 8c00 / 8c02 / 8c04 / 8c06 + // + // Bits 1000 1w00 0000 0xx0 + // Mask 1111 1000 0000 0001 + m_video_accessed = ((offbase==0x8800) && reading) || ((offbase==0x8c00) && !reading); + + // Read a byte in evpc DSR space + // 0x4000 - 0x5eff DSR (paged) + // 0x5f00 - 0x5fef NOVRAM + // 0x5ff0 - 0x5fff Palette + m_inDsrArea = ((m_address & 0xe000)==0x4000); + m_novram_accessed = ((m_address & 0xff00)==0x5f00); + m_palette_accessed = ((m_address & 0xfff0)==0x5ff0); + + // Note that we check the selection in reverse order so that the overlap is avoided +} + //------------------------------------------------- // nvram_default - called to initialize NVRAM to // its default state @@ -64,85 +124,80 @@ void snug_enhanced_video_device::nvram_write(emu_file &file) file.write(m_novram.get(), NOVRAM_SIZE); } - /* - Read a byte in evpc DSR space + Read a byte in evpc DSR space, NOVRAM, Palette, or video 0x4000 - 0x5eff DSR (paged) 0x5f00 - 0x5fef NOVRAM - 0x5ff0 - 0x5fff Palette + 0x5ff0 - 0x5fff Palette (5ff0, 5ff2, 5ff4, 5ff6) */ READ8Z_MEMBER(snug_enhanced_video_device::readz) { - if (m_selected) + if (m_selected && m_inDsrArea) { - if ((offset & m_select_mask)==m_select_value) + if (m_palette_accessed) { - if ((offset & 0x1ff0)==0x1ff0) // Palette control + switch (m_address & 0x000f) { - switch (offset & 0x000f) - { - case 0: - /* Palette Read Address Register */ - *value = m_palette.write_index; - break; + case 0: + // Palette Read Address Register + *value = m_palette.write_index; + break; - case 2: - /* Palette Read Color Value */ - if (m_palette.read) - { - switch (m_palette.state) - { - case 0: - *value = m_palette.color[m_palette.read_index].red; - break; - case 1: - *value = m_palette.color[m_palette.read_index].green; - break; - case 2: - *value = m_palette.color[m_palette.read_index].blue; - break; - } - m_palette.state++; - if (m_palette.state == 3) - { - m_palette.state = 0; - m_palette.read_index++; - } - } - break; - - case 4: - /* Palette Read Pixel Mask */ - *value = m_palette.mask; - break; - case 6: - /* Palette Read Address Register for Color Value */ - if (m_palette.read) - *value = 0; - else - *value = 3; - break; - } - } - else - { - if ((offset & 0x1f00)==0x1f00) + case 2: + // Palette Read Color Value + if (m_palette.read) { - if (m_RAMEN) // NOVRAM hides DSR + switch (m_palette.state) { - *value = m_novram[offset & 0x00ff]; + case 0: + *value = m_palette.color[m_palette.read_index].red; + break; + case 1: + *value = m_palette.color[m_palette.read_index].green; + break; + case 2: + *value = m_palette.color[m_palette.read_index].blue; + break; } - else // DSR + m_palette.state++; + if (m_palette.state == 3) { - *value = m_dsrrom[(offset&0x1fff) | (m_dsr_page<<13)]; + m_palette.state = 0; + m_palette.read_index++; } } + break; + + case 4: + // Palette Read Pixel Mask + *value = m_palette.mask; + break; + case 6: + // Palette Read Address Register for Color Value + if (m_palette.read) + *value = 0; else - { - *value = m_dsrrom[(offset&0x1fff) | (m_dsr_page<<13)]; - } + *value = 3; + break; } + return; } + + if (m_novram_accessed && m_RAMEN) + { + // NOVRAM + *value = m_novram[offset & 0x00ff]; + return; + } + + // DSR space + *value = m_dsrrom[(offset & 0x1fff) | (m_dsr_page<<13)]; + return; + } + + if (m_video_accessed) + { + *value = m_video->read(space, m_address>>1); } } @@ -150,82 +205,87 @@ READ8Z_MEMBER(snug_enhanced_video_device::readz) Write a byte in evpc DSR space 0x4000 - 0x5eff DSR (paged) 0x5f00 - 0x5fef NOVRAM - 0x5ff0 - 0x5fff Palette + 0x5ff0 - 0x5fff Palette (5ff8, 5ffa, 5ffc, 5ffe) */ WRITE8_MEMBER(snug_enhanced_video_device::write) { - if (m_selected) + if (m_selected && m_inDsrArea) { - if ((offset & m_select_mask)==m_select_value) + if (m_palette_accessed) { - if ((offset & 0x1ff0)==0x1ff0) + // Palette + if (TRACE_MEM) logerror("palette write %04x <- %02x\n", offset&0xffff, data); + switch (m_address & 0x000f) { - /* PALETTE */ - if (VERBOSE>5) LOG("palette write %04x <- %02x\n", offset&0xffff, data); - switch (offset & 0x000f) + case 0x08: + // Palette Write Address Register + if (TRACE_MEM) logerror("EVPC palette address write (for write access)\n"); + m_palette.write_index = data; + m_palette.state = 0; + m_palette.read = 0; + break; + + case 0x0a: + // Palette Write Color Value + if (TRACE_MEM) logerror("EVPC palette color write\n"); + if (!m_palette.read) { - case 0x08: - /* Palette Write Address Register */ - if (VERBOSE>5) LOG("EVPC palette address write (for write access)\n"); - m_palette.write_index = data; - m_palette.state = 0; - m_palette.read = 0; - break; - - case 0x0a: - /* Palette Write Color Value */ - if (VERBOSE>5) LOG("EVPC palette color write\n"); - if (!m_palette.read) + switch (m_palette.state) { - switch (m_palette.state) - { - case 0: - m_palette.color[m_palette.write_index].red = data; - break; - case 1: - m_palette.color[m_palette.write_index].green = data; - break; - case 2: - m_palette.color[m_palette.write_index].blue = data; - break; - } - m_palette.state++; - if (m_palette.state == 3) - { - m_palette.state = 0; - m_palette.write_index++; - } - //evpc_palette.dirty = 1; + case 0: + m_palette.color[m_palette.write_index].red = data; + break; + case 1: + m_palette.color[m_palette.write_index].green = data; + break; + case 2: + m_palette.color[m_palette.write_index].blue = data; + break; } - break; - - case 0x0c: - /* Palette Write Pixel Mask */ - if (VERBOSE>5) LOG("EVPC palette mask write\n"); - m_palette.mask = data; - break; - - case 0x0e: - /* Palette Write Address Register for Color Value */ - if (VERBOSE>5) LOG("EVPC palette address write (for read access)\n"); - m_palette.read_index = data; - m_palette.state = 0; - m_palette.read = 1; - break; - } - } - else - { - if ((offset & 0x1f00)==0x1f00) - { - if (m_RAMEN) + m_palette.state++; + if (m_palette.state == 3) { - // NOVRAM - m_novram[offset & 0x00ff] = data; + m_palette.state = 0; + m_palette.write_index++; } + //evpc_palette.dirty = 1; } + break; + + case 0x0c: + // Palette Write Pixel Mask + if (TRACE_MEM) logerror("EVPC palette mask write\n"); + m_palette.mask = data; + break; + + case 0x0e: + // Palette Write Address Register for Color Value + if (TRACE_MEM) logerror("EVPC palette address write (for read access)\n"); + m_palette.read_index = data; + m_palette.state = 0; + m_palette.read = 1; + break; + } + return; } + + if (m_novram_accessed && m_RAMEN) + { + // NOVRAM + m_novram[offset & 0x00ff] = data; + return; + } + } + + if (m_video_accessed) + { + m_video->write(space, m_address>>1, data); + } + + if (m_sound_accessed) + { + m_sound->write(space, 0, data); } } @@ -273,7 +333,7 @@ WRITE8_MEMBER(snug_enhanced_video_device::cruwrite) { case 0: m_selected = (data!=0); - if (VERBOSE>4) LOG("evpc: Map DSR = %d\n", m_selected); + if (TRACE_CRU) logerror("Map DSR = %d\n", m_selected); break; case 1: @@ -309,15 +369,23 @@ WRITE8_MEMBER(snug_enhanced_video_device::cruwrite) } } +/* + READY line for the sound chip +*/ +WRITE_LINE_MEMBER( snug_enhanced_video_device::ready_line ) +{ + m_slot->set_ready(state); +} + void snug_enhanced_video_device::device_start() { m_dsrrom = memregion(DSRROM)->base(); m_novram = std::make_unique(NOVRAM_SIZE); + m_console_conn = downcast(machine().device(EVPC_CONN_TAG)); } void snug_enhanced_video_device::device_reset() { - if (VERBOSE>5) LOG("evpc: reset\n"); m_select_mask = 0x7e000; m_select_value = 0x74000; m_dsr_page = 0; @@ -330,11 +398,36 @@ void snug_enhanced_video_device::device_stop() m_novram = nullptr; } +/* + This is the extra cable running from the EVPC card right into the TI console. + It delivers the VDP interrupt and the GROM clock. + + For the SGCPU, the signal is delivered by the LCP line. +*/ +WRITE_LINE_MEMBER( snug_enhanced_video_device::video_interrupt_in ) +{ + if (m_console_conn != nullptr) m_console_conn->vclock_line(state); + else m_slot->lcp_line(state); +} + ROM_START( ti99_evpc ) ROM_REGION(0x10000, DSRROM, 0) ROM_LOAD("evpcdsr.bin", 0, 0x10000, CRC(a062b75d) SHA1(6e8060f86e3bb9c36f244d88825e3fe237bfe9a9)) /* evpc DSR ROM */ ROM_END +MACHINE_CONFIG_FRAGMENT( ti99_evpc ) + // video hardware + MCFG_V9938_ADD(VDP_TAG, SCREEN_TAG, 0x20000, XTAL_21_4772MHz) /* typical 9938 clock, not verified */ + MCFG_V99X8_INTERRUPT_CALLBACK(WRITELINE(snug_enhanced_video_device, video_interrupt_in)) + MCFG_V99X8_SCREEN_ADD_NTSC(SCREEN_TAG, VDP_TAG, XTAL_21_4772MHz) + + // Sound hardware + MCFG_SPEAKER_STANDARD_MONO("sound_out") + MCFG_SOUND_ADD(TISOUNDCHIP_TAG, SN94624, 3579545/8) /* 3.579545 MHz */ + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "sound_out", 0.75) + MCFG_SN76496_READY_HANDLER( WRITELINE(snug_enhanced_video_device, ready_line) ) +MACHINE_CONFIG_END + /* Input ports for the EPVC */ @@ -370,4 +463,9 @@ ioport_constructor snug_enhanced_video_device::device_input_ports() const return INPUT_PORTS_NAME(ti99_evpc); } +machine_config_constructor snug_enhanced_video_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( ti99_evpc ); +} + const device_type TI99_EVPC = &device_creator; diff --git a/src/devices/bus/ti99_peb/evpc.h b/src/devices/bus/ti99_peb/evpc.h index 2b67fd272fc..f7423f6011d 100644 --- a/src/devices/bus/ti99_peb/evpc.h +++ b/src/devices/bus/ti99_peb/evpc.h @@ -17,6 +17,9 @@ #include "emu.h" #include "peribox.h" +#include "video/v9938.h" +#include "sound/sn76496.h" +#include "bus/ti99x/ti99defs.h" extern const device_type TI99_EVPC; @@ -35,28 +38,45 @@ public: snug_enhanced_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); DECLARE_READ8Z_MEMBER(readz) override; DECLARE_WRITE8_MEMBER(write) override; + DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) override; + + DECLARE_WRITE_LINE_MEMBER( ready_line ); DECLARE_READ8Z_MEMBER(crureadz) override; DECLARE_WRITE8_MEMBER(cruwrite) override; + DECLARE_WRITE_LINE_MEMBER( video_interrupt_in ); protected: - virtual void device_start(void) override; - virtual void device_reset(void) override; - virtual void device_stop(void) override; + void device_start(void) override; + void device_reset(void) override; + void device_stop(void) override; virtual const rom_entry *device_rom_region() const override; virtual ioport_constructor device_input_ports() const override; + machine_config_constructor device_mconfig_additions() const override; void nvram_default() override; void nvram_read(emu_file &file) override; void nvram_write(emu_file &file) override; private: - UINT8* m_dsrrom; - bool m_RAMEN; - int m_dsr_page; - std::unique_ptr m_novram; /* NOVRAM area */ - evpc_palette m_palette; + int m_address; + int m_dsr_page; + bool m_inDsrArea; + bool m_novram_accessed; + bool m_palette_accessed; + bool m_RAMEN; + bool m_sound_accessed; + bool m_video_accessed; + + UINT8* m_dsrrom; + + std::unique_ptr m_novram; // NOVRAM area + + evpc_palette m_palette; + required_device m_video; + required_device m_sound; + evpc_clock_connector* m_console_conn; }; #endif diff --git a/src/devices/bus/ti99_peb/hsgpl.cpp b/src/devices/bus/ti99_peb/hsgpl.cpp index 42ec9360ad3..77ea46fa971 100644 --- a/src/devices/bus/ti99_peb/hsgpl.cpp +++ b/src/devices/bus/ti99_peb/hsgpl.cpp @@ -127,6 +127,7 @@ #define TRACE_DSR 0 #define TRACE_BANKING 0 #define TRACE_CRU 0 +#define TRACE_ADDRESS 0 #define TRACE_READ 0 #define TRACE_WRITE 0 #define TRACE_IGNORE 0 @@ -165,7 +166,7 @@ WRITE8_MEMBER(snug_high_speed_gpl_device::cruwrite) { if (data != 0) { - if (TRACE_CRU) logerror("%s: Supercart cru setting %04x\n", tag(), offset); + if (TRACE_CRU) logerror("Supercart cru setting %04x\n", offset); m_current_bank = (offset-0x0802)>>2; } return; @@ -179,15 +180,15 @@ WRITE8_MEMBER(snug_high_speed_gpl_device::cruwrite) { case 0: m_dsr_enabled = (data != 0); - if (TRACE_CRU) logerror("%s: Set dsr_enabled=%x\n", tag(), data); + if (TRACE_CRU) logerror("Set dsr_enabled=%x\n", data); break; case 1: m_gram_enabled = (data != 0); - if (TRACE_CRU) logerror("%s: Set gram_enabled=%x\n", tag(), data); + if (TRACE_CRU) logerror("Set gram_enabled=%x\n", data); break; case 2: m_bank_inhibit = (data != 0); - if (TRACE_CRU) logerror("%s: Set bank_inhibit=%x\n", tag(), data); + if (TRACE_CRU) logerror("Set bank_inhibit=%x\n", data); break; case 3: case 4: @@ -199,34 +200,34 @@ WRITE8_MEMBER(snug_high_speed_gpl_device::cruwrite) m_dsr_page |= (1 << (bit-3)); else m_dsr_page &= ~(1 << (bit-3)); - if (TRACE_CRU) logerror("%s: Set dsr_page=%d\n", tag(), m_dsr_page); + if (TRACE_CRU) logerror("Set dsr_page=%d\n", m_dsr_page); break; case 9: m_card_enabled = data; - if (TRACE_CRU) logerror("%s: Set card_enabled=%x\n", tag(), data); + if (TRACE_CRU) logerror("Set card_enabled=%x\n", data); break; case 10: m_write_enabled = data; - if (TRACE_CRU) logerror("%s: Set write_enabled=%x\n", tag(), data); + if (TRACE_CRU) logerror("Set write_enabled=%x\n", data); break; case 11: m_supercart_enabled = data; // CHECK: Do we have to reset the bank? - if (TRACE_CRU) logerror("%s: Set supercart_enabled=%x\n", tag(), data); + if (TRACE_CRU) logerror("Set supercart_enabled=%x\n", data); break; case 12: m_led_on = data; - if (TRACE_CRU) logerror("%s: Set led_on=%x\n", tag(), data); + if (TRACE_CRU) logerror("Set led_on=%x\n", data); break; case 13: break; case 14: m_mbx_enabled = data; - if (TRACE_CRU) logerror("%s: Set mbx_enabled=%x\n", tag(), data); + if (TRACE_CRU) logerror("Set mbx_enabled=%x\n", data); break; case 15: m_ram_enabled = data; - if (TRACE_CRU) logerror("%s: Set ram_enabled=%x\n", tag(), data); + if (TRACE_CRU) logerror("Set ram_enabled=%x\n", data); break; } } @@ -279,7 +280,7 @@ void snug_high_speed_gpl_device::dsrspace_readz(address_space& space, offs_t off if (m_dsr_enabled) { *value = m_dsr_eeprom->read(space, (offset & 0x1fff) | (m_dsr_page<<13), mem_mask); - if (TRACE_READ) logerror("%s: read dsr %04x[%02x] -> %02x\n", tag(), offset, m_dsr_page, *value); + if (TRACE_READ) logerror("read dsr %04x[%02x] -> %02x\n", offset, m_dsr_page, *value); } } @@ -290,14 +291,14 @@ void snug_high_speed_gpl_device::cartspace_readz(address_space& space, offs_t of { if (!m_card_enabled || m_flash_mode) { - if (TRACE_IGNORE) logerror("%s: cartridge space read ignored (enable=%d, flash_mode=%d)\n", tag(), m_card_enabled, m_flash_mode); + if (TRACE_IGNORE) logerror("cartridge space read ignored (enable=%d, flash_mode=%d)\n", m_card_enabled, m_flash_mode); return; } if (m_module_bank < 16) { *value = m_rom6_eeprom->read(space, (offset & 0x1fff) | (m_current_bank<<13) | (m_current_grom_port<<15), mem_mask); - if (TRACE_READ) logerror("%s: cartridge space read %04x -> %02x\n", tag(), offset, *value); + if (TRACE_READ) logerror("cartridge space read %04x -> %02x\n", offset, *value); } else { @@ -307,7 +308,7 @@ void snug_high_speed_gpl_device::cartspace_readz(address_space& space, offs_t of } else { - logerror("%s: unknown 0x6000 port\n", tag()); + logerror("unknown 0x6000 port\n"); } } } @@ -356,7 +357,7 @@ void snug_high_speed_gpl_device::grom_readz(address_space& space, offs_t offset, { *value = m_gram_memory[m_grom_address | (port<<16)]; m_module_bank = port + 16; - if (TRACE_PORT) if (bNew) logerror("%s: GRAM read access at %04x (GRMENA=1) - switch to bank %d\n", tag(), offset & 0xffff, m_module_bank); + if (TRACE_PORT) if (bNew) logerror("GRAM read access at %04x (GRMENA=1) - switch to bank %d\n", offset & 0xffff, m_module_bank); } else { @@ -366,7 +367,7 @@ void snug_high_speed_gpl_device::grom_readz(address_space& space, offs_t offset, { *value = m_grom_a_eeprom->read(space, m_grom_address | (port<<16), mem_mask); m_module_bank = port; - if (TRACE_PORT) if (bNew) logerror("%s: GROM read access at %04x - switch to bank %d\n", tag(), offset & 0xffff, m_module_bank); + if (TRACE_PORT) if (bNew) logerror("GROM read access at %04x - switch to bank %d\n", offset & 0xffff, m_module_bank); } } else @@ -375,7 +376,7 @@ void snug_high_speed_gpl_device::grom_readz(address_space& space, offs_t offset, { *value = m_grom_b_eeprom->read(space, m_grom_address | ((port-8)<<16), mem_mask); m_module_bank = port; - if (TRACE_PORT) if (bNew) logerror("%s: GROM read access at %04x - switch to bank %d\n", tag(), offset & 0xffff, m_module_bank); + if (TRACE_PORT) if (bNew) logerror("GROM read access at %04x - switch to bank %d\n", offset & 0xffff, m_module_bank); } else { @@ -385,7 +386,7 @@ void snug_high_speed_gpl_device::grom_readz(address_space& space, offs_t offset, // DSR banks 0-63 (8 KiB per bank, 8 banks per port) *value = m_dsr_eeprom->read(space, m_grom_address | ((port-16)<<16), mem_mask); // Don't change the module port - if (TRACE_DSR) if (bNew) logerror("%s: read access to DSR bank %d-%d (%04x)\n", tag(), (port-16)<<3, ((port-16)<<3)+7, offset); + if (TRACE_DSR) if (bNew) logerror("read access to DSR bank %d-%d (%04x)\n", (port-16)<<3, ((port-16)<<3)+7, offset); } else { @@ -395,7 +396,7 @@ void snug_high_speed_gpl_device::grom_readz(address_space& space, offs_t offset, // Each ROM6 is available as 4 (sub)banks (switchable via 6000, 6002, 6004, 6006) // Accordingly, each port has two complete sets *value = m_rom6_eeprom->read(space, m_grom_address | ((port-24)<<16), mem_mask); - if (TRACE_PORT) if (bNew) logerror("%s: ROM6 read access for module bank %d-%d (%04x)\n", tag(), (port-24)<<1, ((port-24)<<1)+1, offset & 0xffff); + if (TRACE_PORT) if (bNew) logerror("ROM6 read access for module bank %d-%d (%04x)\n", (port-24)<<1, ((port-24)<<1)+1, offset & 0xffff); } else { @@ -404,7 +405,7 @@ void snug_high_speed_gpl_device::grom_readz(address_space& space, offs_t offset, { *value = m_gram_memory[m_grom_address | ((port-32)<<16)]; m_module_bank = port - 16; - if (TRACE_PORT) if (bNew) logerror("%s: GRAM read access at %04x - switch to bank %d\n", tag(), offset & 0xffff, m_module_bank); + if (TRACE_PORT) if (bNew) logerror("GRAM read access at %04x - switch to bank %d\n", offset & 0xffff, m_module_bank); } else { @@ -412,11 +413,11 @@ void snug_high_speed_gpl_device::grom_readz(address_space& space, offs_t offset, { // *value = m_ram6_memory[m_grom_address]; *value = m_ram6_memory[m_grom_address | ((port-48)<<16)]; - if (TRACE_PORT) if (bNew) logerror("%s: RAM read access at %04x\n", tag(), offset & 0xffff); + if (TRACE_PORT) if (bNew) logerror("RAM read access at %04x\n", offset & 0xffff); } else { - logerror("%s: Attempt to read from undefined port 0x%0x; ignored.\n", tag(), port); + logerror("Attempt to read from undefined port 0x%0x; ignored.\n", port); } } } @@ -427,6 +428,7 @@ void snug_high_speed_gpl_device::grom_readz(address_space& space, offs_t offset, } // The address auto-increment should be done even when the card is // offline + if (TRACE_ADDRESS) logerror("HSGPL GROM address %04x\n", m_grom_address); m_grom_address++; m_raddr_LSB = m_waddr_LSB = false; } @@ -439,19 +441,19 @@ void snug_high_speed_gpl_device::cartspace_write(address_space& space, offs_t of { if (!m_card_enabled || m_flash_mode) { - if (TRACE_IGNORE) logerror("%s: write ignored: card_enabled=%d, flash_mode=%d\n", tag(), m_card_enabled, m_flash_mode); + if (TRACE_IGNORE) logerror("write ignored: card_enabled=%d, flash_mode=%d\n", m_card_enabled, m_flash_mode); return; } - if (TRACE_WRITE) logerror("%s: cartridge space write %04x <- %02x\n", tag(), offset, data); + if (TRACE_WRITE) logerror("cartridge space write %04x <- %02x\n", offset, data); if (!m_bank_inhibit && (m_module_bank < 16)) { if ((offset & 1) == 0) { - if ((offset & 0x9ff0)!=0) logerror("%s: unplausible ROM6 write: %04x <- %02x\n", tag(), offset, data); + if ((offset & 0x9ff0)!=0) logerror("unplausible ROM6 write: %04x <- %02x\n", offset, data); m_current_bank = (offset>>1) & 3; - if (TRACE_BANKING) logerror("%s: select bank %d\n", tag(), m_current_bank); + if (TRACE_BANKING) logerror("select bank %d\n", m_current_bank); } return; /* right??? */ } @@ -459,7 +461,7 @@ void snug_high_speed_gpl_device::cartspace_write(address_space& space, offs_t of if ((m_mbx_enabled) && (offset==0x6ffe)) { /* MBX: mapper at 0x6ffe */ m_current_bank = data & 0x03; - if (TRACE_BANKING) logerror("%s: select bank MBX %d\n", tag(), m_current_bank); + if (TRACE_BANKING) logerror("select bank MBX %d\n", m_current_bank); return; } @@ -477,7 +479,7 @@ void snug_high_speed_gpl_device::cartspace_write(address_space& space, offs_t of // and !ram_enabled if (m_module_bank < 16) { - logerror("%s: invalid write %04x <- %02x\n", tag(), offset, data); + logerror("invalid write %04x <- %02x\n", offset, data); // feeprom is normally written to using GPL ports, and I don't know // whether writing through >6000 page is enabled /* @@ -493,7 +495,7 @@ void snug_high_speed_gpl_device::cartspace_write(address_space& space, offs_t of } else { - logerror("%s: unknown 0x6000 port\n", tag()); + logerror("unknown 0x6000 port\n"); } } } @@ -543,7 +545,7 @@ void snug_high_speed_gpl_device::grom_write(address_space& space, offs_t offset, { m_gram_memory[m_grom_address | (port<<16)] = data; m_module_bank = port + 16; - if (TRACE_PORT) if (bNew) logerror("%s: GRAM write access at %04x (GRMENA=1) - switch to bank %d\n", tag(), offset & 0xffff, port); + if (TRACE_PORT) if (bNew) logerror("GRAM write access at %04x (GRMENA=1) - switch to bank %d\n", offset & 0xffff, port); } else { @@ -551,7 +553,7 @@ void snug_high_speed_gpl_device::grom_write(address_space& space, offs_t offset, { m_grom_a_eeprom->write(space, m_grom_address | (port<<16), data, mem_mask); m_module_bank = port; - if (TRACE_PORT) if (bNew) logerror("%s: GROM write access at %04x - switch to bank %d\n", tag(), offset & 0xffff, port); + if (TRACE_PORT) if (bNew) logerror("GROM write access at %04x - switch to bank %d\n", offset & 0xffff, port); } else { @@ -559,21 +561,21 @@ void snug_high_speed_gpl_device::grom_write(address_space& space, offs_t offset, { m_grom_b_eeprom->write(space, m_grom_address | ((port-8)<<16), data, mem_mask); m_module_bank = port; - if (TRACE_PORT) if (bNew) logerror("%s: GROM write access at %04x - switch to bank %d\n", tag(), offset & 0xffff, port); + if (TRACE_PORT) if (bNew) logerror("GROM write access at %04x - switch to bank %d\n", offset & 0xffff, port); } else { if (port < 24) { m_dsr_eeprom->write(space, m_grom_address | ((port-16)<<16), data, mem_mask); - if (TRACE_DSR) if (bNew) logerror("%s: write access to DSR bank %d-%d (%04x)\n", tag(), (port-16)<<3, ((port-16)<<3)+7, offset); + if (TRACE_DSR) if (bNew) logerror("write access to DSR bank %d-%d (%04x)\n", (port-16)<<3, ((port-16)<<3)+7, offset); } else { if (port < 32) { m_rom6_eeprom->write(space, m_grom_address | ((port-24)<<16), data, mem_mask); - if (TRACE_PORT) if (bNew) logerror("%s: ROM6 write access for module bank %d-%d (%04x)\n", tag(), (port-24)<<1, ((port-24)<<1)+1,offset & 0xffff); + if (TRACE_PORT) if (bNew) logerror("ROM6 write access for module bank %d-%d (%04x)\n", (port-24)<<1, ((port-24)<<1)+1,offset & 0xffff); } else { @@ -581,7 +583,7 @@ void snug_high_speed_gpl_device::grom_write(address_space& space, offs_t offset, { m_gram_memory[m_grom_address | ((port-32)<<16)] = data; m_module_bank = port - 16; - if (TRACE_PORT) if (bNew) logerror("%s: GRAM write access at %04x - switch to bank %d\n", tag(), offset & 0xffff, m_module_bank); + if (TRACE_PORT) if (bNew) logerror("GRAM write access at %04x - switch to bank %d\n", offset & 0xffff, m_module_bank); } else { @@ -589,11 +591,11 @@ void snug_high_speed_gpl_device::grom_write(address_space& space, offs_t offset, { // m_ram6_memory[m_grom_address] = data; m_ram6_memory[m_grom_address | ((port-48)<<16)] = data; - if (TRACE_PORT) if (bNew) logerror("%s: RAM write access at %04x\n", tag(), offset & 0xffff); + if (TRACE_PORT) if (bNew) logerror("RAM write access at %04x\n", offset & 0xffff); } else { - logerror("%s: Attempt to write to undefined port; ignored.\n", tag()); + logerror("Attempt to write to undefined port; ignored.\n"); } } } @@ -619,7 +621,7 @@ void snug_high_speed_gpl_device::device_start() void snug_high_speed_gpl_device::device_reset() { - logerror("%s: reset\n", tag()); + logerror("reset\n"); m_dsr_enabled = false; m_gram_enabled = false; m_bank_inhibit = false; diff --git a/src/devices/bus/ti99_peb/peribox.cpp b/src/devices/bus/ti99_peb/peribox.cpp index 52274505533..a38e44ac2bb 100644 --- a/src/devices/bus/ti99_peb/peribox.cpp +++ b/src/devices/bus/ti99_peb/peribox.cpp @@ -220,7 +220,9 @@ peribox_device::peribox_device(const machine_config &mconfig, const char *tag, d : bus8z_device(mconfig, PERIBOX, "Peripheral expansion box", tag, owner, clock, "peribox", __FILE__), m_console_inta(*this), m_console_intb(*this), - m_datamux_ready(*this), m_inta_flag(0), m_intb_flag(0), m_ready_flag(0) + m_sgcpu_lcp(*this), + m_datamux_ready(*this), + m_inta_flag(0), m_intb_flag(0), m_lcp_flag(0), m_ready_flag(0) { for (int i=2; i <= 8; i++) m_slot[i] = nullptr; // The address prefix is actually created by the "Flex cable interface" @@ -235,6 +237,7 @@ peribox_device::peribox_device(const machine_config &mconfig, device_type type, : bus8z_device(mconfig, type, name, tag, owner, clock, shortname, source), m_console_inta(*this), m_console_intb(*this), + m_sgcpu_lcp(*this), m_datamux_ready(*this), m_inta_flag(0), m_intb_flag(0), m_ready_flag(0), m_address_prefix(0), m_msast(false), m_memen(false) { for (int i=2; i <= 8; i++) m_slot[i] = nullptr; @@ -378,6 +381,17 @@ void peribox_device::intb_join(int slot, int state) m_console_intb((m_intb_flag != 0)? ASSERT_LINE : CLEAR_LINE); } +void peribox_device::lcp_join(int slot, int state) +{ + if (TRACE_INT) logerror("%s: propagating LCP from slot %d to SGCPU: %d\n", tag(), slot, state); + if (state==ASSERT_LINE) + m_lcp_flag |= (1 << slot); + else + m_lcp_flag &= ~(1 << slot); + + m_sgcpu_lcp((m_lcp_flag != 0)? ASSERT_LINE : CLEAR_LINE); +} + /* When any device pulls down READY, READY goes down. */ @@ -405,6 +419,7 @@ void peribox_device::device_start(void) // Resolve the callback lines to the console m_console_inta.resolve(); m_console_intb.resolve(); + m_sgcpu_lcp.resolve(); m_datamux_ready.resolve(); if (TRACE_EMU) @@ -421,6 +436,7 @@ void peribox_device::device_config_complete() { m_inta_flag = 0; m_intb_flag = 0; + m_lcp_flag = 0; m_ready_flag = 0; } @@ -721,6 +737,12 @@ WRITE_LINE_MEMBER( peribox_slot_device::set_intb ) peb->intb_join(m_slotnumber, state); } +WRITE_LINE_MEMBER( peribox_slot_device::lcp_line ) +{ + peribox_device *peb = static_cast(owner()); + peb->lcp_join(m_slotnumber, state); +} + WRITE_LINE_MEMBER( peribox_slot_device::set_ready ) { peribox_device *peb = static_cast(owner()); diff --git a/src/devices/bus/ti99_peb/peribox.h b/src/devices/bus/ti99_peb/peribox.h index fa390cc2b88..47095f7d9ce 100644 --- a/src/devices/bus/ti99_peb/peribox.h +++ b/src/devices/bus/ti99_peb/peribox.h @@ -42,6 +42,7 @@ public: template static devcb_base &static_set_inta_callback(device_t &device, _Object object) { return downcast(device).m_console_inta.set_callback(object); } template static devcb_base &static_set_intb_callback(device_t &device, _Object object) { return downcast(device).m_console_intb.set_callback(object); } template static devcb_base &static_set_ready_callback(device_t &device, _Object object) { return downcast(device).m_datamux_ready.set_callback(object); } + template static devcb_base &static_set_lcp_callback(device_t &device, _Object object) { return downcast(device).m_sgcpu_lcp.set_callback(object); } // Next eight methods are called from the console DECLARE_READ8Z_MEMBER(readz) override; @@ -74,6 +75,7 @@ protected: // Next three methods call back the console devcb_write_line m_console_inta; // INTA line (Box to console) devcb_write_line m_console_intb; // INTB line + devcb_write_line m_sgcpu_lcp; // For EVPC with SGCPU only devcb_write_line m_datamux_ready; // READY line (to the datamux) void set_slot_loaded(int slot, peribox_slot_device* slotdev); @@ -83,10 +85,12 @@ protected: // if any one slot asserts the line, the joint line is asserted. void inta_join(int slot, int state); void intb_join(int slot, int state); + void lcp_join(int slot, int state); void ready_join(int slot, int state); int m_inta_flag; int m_intb_flag; + int m_lcp_flag; int m_ready_flag; // The TI-99/4(A) Flex Cable Interface (slot 1) pulls up the AMA/AMB/AMC lines to 1/1/1. @@ -173,6 +177,7 @@ public: // Called from the card (direction to box) DECLARE_WRITE_LINE_MEMBER( set_inta ); DECLARE_WRITE_LINE_MEMBER( set_intb ); + DECLARE_WRITE_LINE_MEMBER( lcp_line ); DECLARE_WRITE_LINE_MEMBER( set_ready ); DECLARE_READ8Z_MEMBER(crureadz); @@ -257,4 +262,7 @@ protected: #define MCFG_PERIBOX_READY_HANDLER( _ready ) \ devcb = &peribox_device::static_set_ready_callback( *device, DEVCB_##_ready ); +#define MCFG_PERIBOX_LCP_HANDLER( _lcp ) \ + devcb = &peribox_device::static_set_lcp_callback( *device, DEVCB_##_lcp ); + #endif /* __PBOX__ */ diff --git a/src/devices/bus/ti99_peb/samsmem.cpp b/src/devices/bus/ti99_peb/samsmem.cpp index 0ff3e27d928..51d912ce1b0 100644 --- a/src/devices/bus/ti99_peb/samsmem.cpp +++ b/src/devices/bus/ti99_peb/samsmem.cpp @@ -11,22 +11,26 @@ addresses at 4000, 4002, ..., 401e, which correspond to memory locations 0000-0fff, 1000-1fff, ..., f000-ffff. - Michael Zapf + According to a software distribution disk from the South West 99ers group, + the predecessor of this card was the Asgard Expanded Memory System (AEMS). + Although some documentation and software was available for it, it was never + built. Instead, a simpler memory card called the Asgard Memory System (AMS) + was built. The South West 99ers group built a better version of this card + called the Super AMS. Any documentation and software containing a reference + to the AEMS are applicable to either AMS or SAMS. - February 2012: Rewritten as class + Michael Zapf *****************************************************************************/ #include "samsmem.h" -#define RAMREGION "ram" #define SAMS_CRU_BASE 0x1e00 -#define VERBOSE 1 -#define LOG logerror - sams_memory_expansion_device::sams_memory_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) -: ti_expansion_card_device(mconfig, TI99_SAMSMEM, "SuperAMS memory expansion card", tag, owner, clock, "ti99_sams", __FILE__), m_ram(nullptr), m_map_mode(false), m_access_mapper(false) +: ti_expansion_card_device(mconfig, TI99_SAMSMEM, "SuperAMS memory expansion card", tag, owner, clock, "ti99_sams", __FILE__), + m_ram(*this, RAM_TAG), + m_map_mode(false), m_access_mapper(false) { } @@ -49,12 +53,12 @@ READ8Z_MEMBER(sams_memory_expansion_device::readz) if (!m_map_mode) { // transparent mode - *value = m_ram[offset & 0xffff]; + *value = m_ram->pointer()[offset & 0xffff]; } else { base = (m_mapper[(offset & 0xf000)>>12] << 12); - *value = m_ram[base | (offset & 0x0fff)]; + *value = m_ram->pointer()[base | (offset & 0x0fff)]; } } } @@ -73,12 +77,12 @@ WRITE8_MEMBER(sams_memory_expansion_device::write) if (!m_map_mode) { // transparent mode - m_ram[offset & 0xffff] = data; + m_ram->pointer()[offset & 0xffff] = data; } else { base = (m_mapper[(offset & 0xf000)>>12] << 12); - m_ram[base | (offset & 0x0fff)] = data; + m_ram->pointer()[base | (offset & 0x0fff)] = data; } } } @@ -97,37 +101,31 @@ WRITE8_MEMBER(sams_memory_expansion_device::cruwrite) { if ((offset & 0xff00)==SAMS_CRU_BASE) { - if (VERBOSE>7) LOG("cru address %04x = %02x\n", offset&0xffff, data); - if ((offset & 0x000e)==0) m_access_mapper = (data!=0); if ((offset & 0x000e)==2) m_map_mode = (data!=0); } } +MACHINE_CONFIG_FRAGMENT( sams_mem ) + MCFG_RAM_ADD(RAM_TAG) + MCFG_RAM_DEFAULT_SIZE("1M") +MACHINE_CONFIG_END -ROM_START( sams_card ) - ROM_REGION(0x100000, RAMREGION, 0) - ROM_FILL(0x0000, 0x100000, 0x00) -ROM_END +machine_config_constructor sams_memory_expansion_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( sams_mem ); +} void sams_memory_expansion_device::device_start() { - if (VERBOSE>5) LOG("SuperAMS: start\n"); - m_ram = memregion(RAMREGION)->base(); } void sams_memory_expansion_device::device_reset() { - if (VERBOSE>5) LOG("SuperAMS: reset\n"); // Resetting values m_map_mode = false; m_access_mapper = false; for (auto & elem : m_mapper) elem = 0; } -const rom_entry *sams_memory_expansion_device::device_rom_region() const -{ - return ROM_NAME( sams_card ); -} - const device_type TI99_SAMSMEM = &device_creator; diff --git a/src/devices/bus/ti99_peb/samsmem.h b/src/devices/bus/ti99_peb/samsmem.h index d5e1cb9b062..10c69c1d655 100644 --- a/src/devices/bus/ti99_peb/samsmem.h +++ b/src/devices/bus/ti99_peb/samsmem.h @@ -17,6 +17,7 @@ #include "emu.h" #include "peribox.h" +#include "machine/ram.h" extern const device_type TI99_SAMSMEM; @@ -30,13 +31,15 @@ public: DECLARE_READ8Z_MEMBER(crureadz) override; DECLARE_WRITE8_MEMBER(cruwrite) override; + machine_config_constructor device_mconfig_additions() const override; + protected: - virtual void device_start(void) override; - virtual void device_reset(void) override; - virtual const rom_entry *device_rom_region(void) const override; + void device_start(void) override; + void device_reset(void) override; private: - UINT8* m_ram; + // Console RAM + required_device m_ram; int m_mapper[16]; bool m_map_mode; bool m_access_mapper; diff --git a/src/devices/bus/ti99x/datamux.cpp b/src/devices/bus/ti99x/datamux.cpp index 034ecfe114d..6cb44af8f53 100644 --- a/src/devices/bus/ti99x/datamux.cpp +++ b/src/devices/bus/ti99x/datamux.cpp @@ -124,7 +124,18 @@ void ti99_datamux_device::read_all(address_space& space, UINT16 addr, UINT8 *val // Video if ((addr & 0xf801)==0x8800) { - m_video->readz(space, addr, value); + // Forward to VDP unless we have an EVPC + if (m_video != nullptr) + { + if ((addr & 2) != 0) + { // read VDP status + *value = m_video->register_read(space, 0); + } + else + { // read VDP RAM + *value = m_video->vram_read(space, 0); + } + } } } @@ -152,12 +163,28 @@ void ti99_datamux_device::write_all(address_space& space, UINT16 addr, UINT8 val // Cartridge port and sound if ((addr & 0xe000)==0x6000) m_gromport->write(space, addr, value); - if ((addr & 0xfc01)==0x8400) m_sound->write(space, 0, value); + + // Only if the sound chip has not been removed + if ((addr & 0xfc01)==0x8400) + { + if (m_sound != nullptr) m_sound->write(space, 0, value); + } // Video if ((addr & 0xf801)==0x8800) { - m_video->write(space, addr, value); + // Forward to VDP unless we have an EVPC + if (m_video != nullptr) + { + if ((addr & 2) != 0) + { // write VDP address/register + m_video->register_write(space, 0, value); + } + else + { // write VDP data + m_video->vram_write(space, 0, value); + } + } } // PEB gets all accesses @@ -560,7 +587,7 @@ void ti99_datamux_device::device_reset(void) void ti99_datamux_device::device_config_complete() { - m_video = downcast(owner()->subdevice(VIDEO_SYSTEM_TAG)); + m_video = downcast(owner()->subdevice(VDP_TAG)); m_sound = downcast(owner()->subdevice(TISOUNDCHIP_TAG)); m_gromport = downcast(owner()->subdevice(GROMPORT_TAG)); m_peb = downcast(owner()->subdevice(PERIBOX_TAG)); diff --git a/src/devices/bus/ti99x/datamux.h b/src/devices/bus/ti99x/datamux.h index 5b59ea7d134..27908d403c6 100644 --- a/src/devices/bus/ti99x/datamux.h +++ b/src/devices/bus/ti99x/datamux.h @@ -20,7 +20,6 @@ #include "bus/ti99_peb/peribox.h" #include "sound/sn76496.h" #include "video/tms9928a.h" -#include "bus/ti99x/videowrp.h" extern const device_type DATAMUX; @@ -56,7 +55,7 @@ protected: private: // Link to the video processor - bus8z_device* m_video; + tms9928a_device* m_video; // Link to the sound processor sn76496_base_device* m_sound; diff --git a/src/devices/bus/ti99x/ti99defs.h b/src/devices/bus/ti99x/ti99defs.h index 8d137e6599f..c8fd6eac587 100644 --- a/src/devices/bus/ti99x/ti99defs.h +++ b/src/devices/bus/ti99x/ti99defs.h @@ -18,7 +18,6 @@ #define TMS9901_TAG "tms9901" #define TIBOARD_TAG "ti_board" #define DATAMUX_TAG "datamux_16_8" -#define VIDEO_SYSTEM_TAG "video" #define SCREEN_TAG "screen" #define TISOUNDCHIP_TAG "soundchip" #define TISOUND_TAG "tisound" @@ -31,6 +30,8 @@ #define HANDSET_TAG "handset" #define JOYPORT_TAG "joyport" #define VDP_TAG "vdp" +#define EVPC_CONN_TAG "evpc_conn" + #define DSRROM "dsrrom" #define CONSOLEROM "consolerom" @@ -137,6 +138,42 @@ public: virtual DECLARE_SETADDRESS_DBIN_MEMBER( setaddress_dbin ) { }; }; +/**************************************************************************** + Connector from EVPC + We need this for the TI-99/4A console as well as for the SGCPU, so we have + to use callbacks +****************************************************************************/ +class ti99_4x_state; + +class evpc_clock_connector; + +const device_type EVPC_CONN = &device_creator; + +class evpc_clock_connector : public device_t +{ +public: + evpc_clock_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, EVPC_CONN, "EVPC clock connector", tag, owner, clock, "ti99_evpc_clock", __FILE__), + m_vdpint(*this) { }; + + template static devcb_base &static_set_vdpint_callback(device_t &device, _Object object) + { + return downcast(device).m_vdpint.set_callback(object); + } + + WRITE_LINE_MEMBER( vclock_line ) { m_vdpint(state); } + void device_start() override { m_vdpint.resolve(); } + +private: + // VDPINT line to the CPU + devcb_write_line m_vdpint; +}; + + +#define MCFG_ADD_EVPC_CONNECTOR( _tag, _vdpint ) \ + MCFG_DEVICE_ADD(_tag, EVPC_CONN, 0) \ + devcb = &evpc_clock_connector::static_set_vdpint_callback( *device, DEVCB_##_vdpint ); + /**************************************************************************** Constants ****************************************************************************/ diff --git a/src/devices/bus/ti99x/videowrp.cpp b/src/devices/bus/ti99x/videowrp.cpp deleted file mode 100644 index 4aa1935f226..00000000000 --- a/src/devices/bus/ti99x/videowrp.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Michael Zapf -/**************************************************************************** - - TI-99/4A Video subsystem - This device actually wraps the naked video chip implementation - - EVPC (Enhanced Video Processor Card) from SNUG - based on v9938 (may also be equipped with v9958) - Can be used with TI-99/4A as an add-on card; internal VDP must be removed - - The SGCPU ("TI-99/4P") only runs with EVPC - - Michael Zapf - -*****************************************************************************/ - -#include "emu.h" -#include "videowrp.h" - -/* - Constructors -*/ -ti_video_device::ti_video_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) -: bus8z_device(mconfig, type, name, tag, owner, clock, shortname, source), -m_tms9928a(nullptr) -{ -} - -ti_std_video_device::ti_std_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : ti_video_device(mconfig, TI99VIDEO, "TI99 STD Video subsystem", tag, owner, clock, "ti99_video", __FILE__) -{ -} - -ti_exp_video_device::ti_exp_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : ti_video_device(mconfig, V9938VIDEO, "TI99 EXP Video subsystem", tag, owner, clock, "v9938_video", __FILE__), - m_v9938(nullptr) -{ -} - -/*****************************************************************************/ -/* - Accessing TMS9928A (TI-99/4A) -*/ -READ8Z_MEMBER( ti_std_video_device::readz ) -{ - if (space.debugger_access()) return; - - if (offset & 2) - { /* read VDP status */ - *value = m_tms9928a->register_read(space, 0); - } - else - { /* read VDP RAM */ - *value = m_tms9928a->vram_read(space, 0); - } -} - -WRITE8_MEMBER( ti_std_video_device::write ) -{ - if (space.debugger_access()) return; - - if (offset & 2) - { /* write VDP address */ - m_tms9928a->register_write(space, 0, data); - } - else - { /* write VDP data */ - m_tms9928a->vram_write(space, 0, data); - } -} - -/*****************************************************************************/ - -/* - Accessing v9938 via 16 bit bus (SGCPU) -*/ -READ16_MEMBER( ti_exp_video_device::read16 ) -{ - if (space.debugger_access()) return 0; - return (int)(m_v9938->read(space, offset)<<8); -} - -WRITE16_MEMBER( ti_exp_video_device::write16 ) -{ - if (space.debugger_access()) return; - m_v9938->write(space, offset, (data>>8)&0xff); -} - - -/******************************************************************************/ - -/* - Accessing v9938 via 8 bit bus (EVPC) -*/ -READ8Z_MEMBER( ti_exp_video_device::readz ) -{ - if (space.debugger_access()) return; - *value = m_v9938->read(space, offset>>1); -} - -WRITE8_MEMBER( ti_exp_video_device::write ) -{ - if (space.debugger_access()) return; - m_v9938->write(space, offset>>1, data); -} - -void ti_video_device::device_start(void) -{ - m_tms9928a = static_cast(machine().device(VDP_TAG)); -} - -void ti_exp_video_device::device_start(void) -{ - m_v9938 = static_cast(machine().device(VDP_TAG)); -} - -/**************************************************************************/ - -const device_type TI99VIDEO = &device_creator; -const device_type V9938VIDEO = &device_creator; diff --git a/src/devices/bus/ti99x/videowrp.h b/src/devices/bus/ti99x/videowrp.h deleted file mode 100644 index 787f0e2d44f..00000000000 --- a/src/devices/bus/ti99x/videowrp.h +++ /dev/null @@ -1,93 +0,0 @@ -// license:LGPL-2.1+ -// copyright-holders:Michael Zapf -/**************************************************************************** - - TI-99/4A / EVPC Video subsystem - See videowrp.c for documentation - - Michael Zapf - October 2010 - January 2012: Rewritten as class - -*****************************************************************************/ - -#ifndef __TIVIDEO__ -#define __TIVIDEO__ - -#include "video/tms9928a.h" -#include "video/v9938.h" -#include "ti99defs.h" - -class ti_video_device : public bus8z_device -{ -public: - virtual void reset_vdp(int state) =0; - -protected: - tms9928a_device *m_tms9928a; - - /* Constructor */ - ti_video_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); - virtual void device_start(void) override; - virtual void device_reset(void) override { }; - virtual DECLARE_READ8Z_MEMBER(readz) override { }; - virtual DECLARE_WRITE8_MEMBER(write) override { }; -}; - -/* - Used in the TI-99/4A and TI-99/8 -*/ -class ti_std_video_device : public ti_video_device -{ -public: - ti_std_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - DECLARE_READ8Z_MEMBER(readz) override; - DECLARE_WRITE8_MEMBER(write) override; - void reset_vdp(int state) override { m_tms9928a->reset_line(state); } -}; - -/* - Used in the EVPC -*/ -class ti_exp_video_device : public ti_video_device -{ -public: - ti_exp_video_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - DECLARE_READ8Z_MEMBER(readz) override; - DECLARE_WRITE8_MEMBER(write) override; - DECLARE_READ16_MEMBER(read16); - DECLARE_WRITE16_MEMBER(write16); - void reset_vdp(int state) override { m_v9938->reset_line(state); } - -protected: - virtual void device_start(void) override; - -private: - v9938_device *m_v9938; -}; - -extern const device_type TI99VIDEO; -extern const device_type V9938VIDEO; - - -/****************************************************************************/ - -#define MCFG_TI_TMS991x_ADD_NTSC(_tag, _chip, _vsize, _class, _int, _gclk) \ - MCFG_DEVICE_ADD(_tag, TI99VIDEO, 0) \ - MCFG_DEVICE_ADD( VDP_TAG, _chip, XTAL_10_738635MHz / 2 ) \ - MCFG_TMS9928A_VRAM_SIZE(_vsize) \ - MCFG_TMS9928A_OUT_INT_LINE_CB(WRITELINE(_class,_int)) \ - MCFG_TMS9928A_OUT_GROMCLK_CB(WRITELINE(_class,_gclk)) \ - MCFG_TMS9928A_SCREEN_ADD_NTSC( SCREEN_TAG ) \ - MCFG_SCREEN_UPDATE_DEVICE( VDP_TAG, tms9928a_device, screen_update ) - -#define MCFG_TI_TMS991x_ADD_PAL(_tag, _chip, _vsize, _class, _int, _gclk) \ - MCFG_DEVICE_ADD(_tag, TI99VIDEO, 0) \ - MCFG_DEVICE_ADD( VDP_TAG, _chip, XTAL_10_738635MHz / 2 ) \ - MCFG_TMS9928A_VRAM_SIZE(_vsize) \ - MCFG_TMS9928A_OUT_INT_LINE_CB(WRITELINE(_class,_int)) \ - MCFG_TMS9928A_OUT_GROMCLK_CB(WRITELINE(_class,_gclk)) \ - MCFG_TMS9928A_SCREEN_ADD_PAL( SCREEN_TAG ) \ - MCFG_SCREEN_UPDATE_DEVICE( VDP_TAG, tms9928a_device, screen_update ) - -#endif /* __TIVIDEO__ */ diff --git a/src/mame/drivers/ti99_4p.cpp b/src/mame/drivers/ti99_4p.cpp index 4650d391c08..fb239868a8f 100644 --- a/src/mame/drivers/ti99_4p.cpp +++ b/src/mame/drivers/ti99_4p.cpp @@ -2,53 +2,126 @@ // copyright-holders:Michael Zapf /**************************************************************************** - SNUG SGCPU (a.k.a. 99/4p) system + SNUG Second Generation CPU (SGCPU, aka TI-99/4P) - This system is a reimplementation of the old ti99/4a console. It is known - both as the 99/4p ("peripheral box", since the system is a card to be - inserted in the peripheral box, instead of a self contained console), and - as the SGCPU ("Second Generation CPU", which was originally the name used - in TI documentation to refer to either (or both) TI99/5 and TI99/8 - projects). + This system is known both as the TI-99/4P ("Peripheral box", since the + system is a card to be inserted in the peripheral box, instead of a + self-contained console), and as the SGCPU ("Second Generation CPU", + which was originally the name used in TI documentation to refer to either + (or both) TI-99/5 and TI-99/8 projects). The SGCPU was designed and built by the SNUG (System 99 Users Group), namely by Michael Becker for the hardware part and Harald Glaab for the software part. It has no relationship with TI. - The card is architectured around a 16-bit bus (vs. an 8-bit bus in every - other TI99 system). It includes 64kb of ROM, including a GPL interpreter, - an internal DSR ROM which contains system-specific code, part of the TI - extended Basic interpreter, and up to 1Mbyte of RAM. It still includes a - 16-bit to 8-bit multiplexer in order to support extension cards designed - for TI99/4a, but it can support 16-bit cards, too. It does not include - GROMs, video or sound: instead, it relies on the HSGPL and EVPC cards to - do the job. + The card is a complete redesign of the original TI-99/4A mainboard to fit + on a peripheral card, thus replacing the console. It shows no original + circuits on its board; the concept is to cannibalize a TI-99/4A console, + moving its main circuits (TMS9900, TMS9901) into the sockets on this board. - IMPORTANT: The SGCPU card relies on a properly set up HSGPL flash memory - card; without, it will immediately lock up. It is impossible to set it up - from here (a bootstrap problem; you cannot start without the HSGPL). - The best chance is to start a ti99_4ev with a plugged-in HSGPL - and go through the setup process there. Copy the nvram files of the hsgpl into this - driver's nvram subdirectory. The contents will be directly usable for the SGCPU. + The sound chip is not plugged on the SGCPU but on the EVPC card which + provides the video processor for SGCPU card (see below). + + The card offers a PC-style keyboard interface which adapts the keyboard + to the matrix organisation expected by the operating system of the TI. + + All decoding and further features are implemented by a MACH chip, which + appears on many SNUG cards. + + On the card, most circuits are directly accessed by a 16-bit data bus, + which ensures a significant speed-up compared to the original console. Only + when accessing external devices via the PEB, a databus multiplexer comes into + play which is implemented in the same way as the one in the original console, + also contained in the MACH. + + The SGCPU offers a special connector at the back, containing the remaining + 8 data bus lines; by this feature, expansion cards can be connected at + full 16 bit width. Only the HRD16 card (not yet emulated), which is a + RAMDisk card, actually uses it. + + EPROM layout 64K + ---------------- + The memory region is shifted by 4000 in the EPROM address space + According to the designers, this is caused by the next-to most significant + address line (2^14) being locked to 1. This is done to allow for smaller + 24pin EPROM to be used. + + Area EPROM offset Mapped at + --------------------------------------- + ROM0 4000 (0100) 0000 + DSR C000 (1100) 4000 + ROM6A 6000 (0110) 6000 + ROM6B E000 (1110) 6000 + + System ROM + ---------- + The GPL interpreter is located in the EPROM as ROM0 (see above). The + SGCPU does not contain any GROM, which contain the actual TI operating + system and the BASIC interpreter. The GROMs are replaced by the HSGPL card. + + ==== CAUTION ====: This means that the HSGPL must be properly set up before + starting up the SGCPU. Otherwise, the emulation locks up immediately with a + BLACK SCREEN. + + In the real environment, the HSGPL has usually been set up on delivery. + In MESS we have to create a suitable HSGPL memory content. Best practice + is to start the TI-99/4A console with EVPC support (driver ti99_4ev) with + a plugged-in HSGPL and to go through the setup process there. + Finally, the nvram files of the HSGPL must be copied into this driver's nvram + subdirectory. The contents will be directly usable for the SGCPU. + + RAM: AEMS emulation + -------------------- + The Asgard Expanded Memory System is a peripheral card whose successor + (Super AMS) is available in MESS. The AEMS card is emulated inside the MACH + chip of the SGCPU. For more information see samsmem.cpp. + + The first four address lines are used to select one of 16 mapper values with + 8 bits each. Instead of these first 4 lines, the 8 bits are prepended to + the remaining address, yielding a 20 bit address space. + + The mapper values are mapped into the address space at 4000 by setting + CRU bit 1E00. Only the even addresses are used, so the first mapper byte is + at 4000, the second at 4002, the last one at 401E. + + The mapping mode can be turned on and off by the CRU bit at address 1E02. + When turned off, the address is passed through to the RAM circuits. + + Since the only RAM areas on the TI systems are at 2000-3FFF and A000-FFFF, + the typical usage is to use the AEMS as a 32K expansion in unmapped mode + (the remaining 32K of the address space is decoded earlier, and does not + affect the card), and to use it as paged memory in the 2000-3FFF and A000-FFFF + areas by setting the mapper appropriately. Mapper registers referring to + other memory areas have no effect. + + Video and sound + --------------- + The SGCPU relies on the EVPC or EVPC2 card to provide video capabilities. + This card (rel.1) is emulated in MESS and is based on the v9938 video + display processor. + In order to route the VDP interrupt to the SGCPU card, the previously + unused LCP* line in the Peripheral Expansion Box is used. + + The sound chip requires the video clock, and therefore it is moved from the + console to the EVPC card. + + Joystick and cassette + --------------------- + The card features a 25-pin connector at the back which contains the lines + for the joysticks and one cassette input/output. An adapter must be built + to be able to use the common cables. Michael Zapf - February 2012: Rewritten as class - *****************************************************************************/ #include "emu.h" #include "cpu/tms9900/tms9900.h" #include "sound/wave.h" -#include "sound/dac.h" -#include "sound/sn76496.h" #include "machine/tms9901.h" #include "imagedev/cassette.h" - -#include "bus/ti99x/videowrp.h" #include "bus/ti99x/joyport.h" - #include "bus/ti99_peb/peribox.h" #define TMS9901_TAG "tms9901" @@ -57,6 +130,9 @@ #define TRACE_ILLWRITE 0 #define TRACE_READY 0 #define TRACE_INT 0 +#define TRACE_ADDRESS 0 +#define TRACE_MEM 0 +#define TRACE_MUX 0 class ti99_4p_state : public driver_device { @@ -65,28 +141,28 @@ public: : driver_device(mconfig, type, tag), m_cpu(*this, "maincpu"), m_tms9901(*this, TMS9901_TAG), - m_sound(*this, TISOUNDCHIP_TAG), - m_video(*this, VIDEO_SYSTEM_TAG), m_cassette(*this, "cassette"), m_peribox(*this, PERIBOX_TAG), m_joyport(*this, JOYPORT_TAG) { } - DECLARE_WRITE_LINE_MEMBER( console_ready ); - DECLARE_WRITE_LINE_MEMBER( console_ready_dmux ); - + DECLARE_WRITE_LINE_MEMBER( ready_line ); DECLARE_WRITE_LINE_MEMBER( extint ); DECLARE_WRITE_LINE_MEMBER( notconnected ); DECLARE_READ8_MEMBER( interrupt_level ); + + DECLARE_SETOFFSET_MEMBER( setoffset ); DECLARE_READ16_MEMBER( memread ); DECLARE_WRITE16_MEMBER( memwrite ); + DECLARE_WRITE_LINE_MEMBER( dbin_in ); DECLARE_READ16_MEMBER( samsmem_read ); DECLARE_WRITE16_MEMBER( samsmem_write ); DECLARE_WRITE8_MEMBER(external_operation); DECLARE_WRITE_LINE_MEMBER( clock_out ); + DECLARE_WRITE_LINE_MEMBER( dbin_line ); - void clock_in(int clock); + void datamux_clock_in(int clock); // CRU (Communication Register Unit) handling DECLARE_READ8_MEMBER( cruread ); @@ -103,12 +179,10 @@ public: virtual void machine_start() override; DECLARE_MACHINE_RESET(ti99_4p); - DECLARE_WRITE_LINE_MEMBER(set_tms9901_INT2_from_v9938); + DECLARE_WRITE_LINE_MEMBER(video_interrupt_in); required_device m_cpu; required_device m_tms9901; - required_device m_sound; - required_device m_video; required_device m_cassette; required_device m_peribox; required_device m_joyport; @@ -116,15 +190,6 @@ public: // Pointer to ROM0 UINT16 *m_rom0; - // Pointer to DSR ROM - UINT16 *m_dsr; - - // Pointer to ROM6, first bank - UINT16 *m_rom6a; - - // Pointer to ROM6, second bank - UINT16 *m_rom6b; - // AMS RAM (1 Mib) std::vector m_ram; @@ -134,12 +199,14 @@ public: // First joystick. 6 for TI-99/4A int m_firstjoy; - // READY line - int m_ready_line, m_ready_line_dmux; - private: - DECLARE_READ16_MEMBER( datamux_read ); - DECLARE_WRITE16_MEMBER( datamux_write ); + + int decode_address(int address); + DECLARE_READ16_MEMBER( debugger_read ); + DECLARE_WRITE16_MEMBER( debugger_write ); + + void ready_join(); + void set_keyboard_column(int number, int data); int m_keyboard_column; @@ -163,6 +230,36 @@ private: // TRUE when mapper registers are accessible bool m_access_mapper; + // Value on address bus (after being set by setaddress) + int m_addr_buf; + + // Address decoding result + int m_decode; + + // Ready state of the databus multiplexer + bool m_muxready; + + // Incoming Ready level + line_state m_sysready; + + // Saves a pointer to the address space + address_space* m_spacep; + + // Internal DSR mapped in + bool m_internal_dsr_active; + + // Mapper visible in 4000 area + bool m_mapper_active; + + // ROM6 visible in 6000 + bool m_rom6_active; + + // Upper bank of ROM6 selected + bool m_rom6_upper; + + // State of the DBIN line + line_state m_dbin; + UINT8 m_lowbyte; UINT8 m_highbyte; UINT8 m_latch; @@ -170,6 +267,9 @@ private: // Mapper registers UINT8 m_mapper[16]; + // Pointer to EPROM + UINT16 *m_rom; + // Latch for 9901 INT2, INT1 lines int m_9901_int; void set_9901_int(int line, line_state state); @@ -178,8 +278,16 @@ private: }; +enum +{ + ROM0BASE = 0x4000, + DSRBASE = 0xc000, + ROM6LBASE = 0x6000, + ROM6UBASE = 0xe000 +}; + static ADDRESS_MAP_START(memmap, AS_PROGRAM, 16, ti99_4p_state) - AM_RANGE(0x0000, 0xffff) AM_READWRITE( memread, memwrite ) + AM_RANGE(0x0000, 0xffff) AM_READWRITE( memread, memwrite ) AM_SETOFFSET( setoffset ) ADDRESS_MAP_END static ADDRESS_MAP_START(cru_map, AS_IO, 8, ti99_4p_state) @@ -267,226 +375,309 @@ static INPUT_PORTS_START(ti99_4p) INPUT_PORTS_END +enum +{ + SGCPU_NONE = 0, + SGCPU_SYSROM, + SGCPU_RAM, + SGCPU_INTDSR, + SGCPU_MAPPER, + SGCPU_ROM6, + SGCPU_PADRAM, + SGCPU_PEB +}; + +int ti99_4p_state::decode_address(int address) +{ + int dec = SGCPU_NONE; + switch (address & 0xe000) + { + case 0x0000: + dec = SGCPU_SYSROM; + break; + case 0x2000: + case 0xa000: + case 0xc000: + case 0xe000: + dec = SGCPU_RAM; + break; + case 0x4000: + if (m_internal_dsr_active) dec = SGCPU_INTDSR; + else if (m_mapper_active) dec = SGCPU_MAPPER; + break; + case 0x6000: + if (m_rom6_active) dec = SGCPU_ROM6; + break; + case 0x8000: + if ((m_addr_buf & 0x1c00)==0x0000) dec = SGCPU_PADRAM; + break; + + default: + break; + } + return dec; +} + /* - Memory access + Called when the memory access starts by setting the address bus. From that + point on, we suspend the CPU until all operations are done. */ +SETOFFSET_MEMBER( ti99_4p_state::setoffset ) +{ + m_addr_buf = offset << 1; + m_waitcount = 0; + + if (TRACE_ADDRESS) logerror("set address %04x\n", m_addr_buf); + + m_decode = SGCPU_NONE; + m_muxready = true; + m_spacep = &space; + + m_decode = decode_address(m_addr_buf); + + if (m_decode == SGCPU_NONE) + { + // not found - pass on to PEB, 8 bit access with wait states as in TI-99/4A console + // PEB gets remaining accesses + // HSGPL, EVPC, other devices + m_decode = SGCPU_PEB; + m_waitcount = 5; + m_muxready = false; + m_peribox->memen_in(ASSERT_LINE); + m_peribox->setaddress_dbin(space, m_addr_buf+1, m_dbin); + } + + ready_join(); +} + READ16_MEMBER( ti99_4p_state::memread ) { - int addroff = offset << 1; - if (m_rom0 == nullptr) return 0; // premature access + int address = 0; + UINT8 hbyte = 0; - UINT16 zone = addroff & 0xe000; UINT16 value = 0; - if (zone==0x0000) + int addr_off8k = m_addr_buf & 0x1fff; + + // If we use the debugger, decode the address now (normally done in setaddress) + if (space.debugger_access()) { - // ROM0 - value = m_rom0[(addroff & 0x1fff)>>1]; - return value; - } - if (zone==0x2000 || zone==0xa000 || zone==0xc000 || zone==0xe000) - { - value = samsmem_read(space, offset, mem_mask); - return value; + m_addr_buf = offset << 1; + m_decode = decode_address(m_addr_buf); } - if (zone==0x4000) + switch (m_decode) { - if (m_internal_dsr) - { - value = m_dsr[(addroff & 0x1fff)>>1]; - return value; - } - else - { - if (m_access_mapper && ((addroff & 0xffe0)==0x4000)) - { - value = m_mapper[offset & 0x000f]<<8; - return value; - } - } + case SGCPU_SYSROM: + value = m_rom[(ROM0BASE | addr_off8k) >> 1]; + break; + + case SGCPU_RAM: + // Memory read. The AEMS emulation has two address areas: The memory is at locations + // 0x2000-0x3fff and 0xa000-0xffff, and the mapper area is at 0x4000-0x401e + // (only even addresses). + if (m_map_mode) + address = (m_mapper[(m_addr_buf & 0xf000)>>12] << 12) | (m_addr_buf & 0x0fff); + else // transparent mode + address = m_addr_buf; + + value = m_ram[address>>1]; + break; + + case SGCPU_INTDSR: + value = m_rom[(DSRBASE | addr_off8k)>>1]; + break; + + case SGCPU_MAPPER: + value = (m_mapper[m_addr_buf & 0x000f]<<8) & 0xff00; + break; + + case SGCPU_ROM6: + value = m_rom[((m_rom6_upper? ROM6UBASE : ROM6LBASE) | addr_off8k)>>1]; + break; + case SGCPU_PADRAM: + // Scratch pad RAM (16 bit) + // 8000 ... 83ff (1K, 4 times the size of the internal RAM of the TI-99/4A) + value = m_scratchpad[(m_addr_buf & 0x03ff)>>1]; + break; + + case SGCPU_PEB: + if (space.debugger_access()) return debugger_read(space, offset); + // The byte from the odd address has already been read into the latch + // Reading the even address now + m_peribox->readz(space, m_addr_buf, &hbyte); + m_peribox->memen_in(CLEAR_LINE); + if (TRACE_MEM) logerror("Read even byte from address %04x -> %02x\n", m_addr_buf, hbyte); + value = (hbyte<<8) | m_latch; } - if (zone==0x6000 && m_internal_rom6) - { - if (m_rom6_bank==0) - value = m_rom6a[(addroff & 0x1fff)>>1]; - else - value = m_rom6b[(addroff & 0x1fff)>>1]; - - return value; - } - - // Scratch pad RAM and sound - // speech is in peribox - // groms are in hsgpl in peribox - if (zone==0x8000) - { - if ((addroff & 0xfff0)==0x8400) // cannot read from sound - { - value = 0; - return value; - } - if ((addroff & 0xfc00)==0x8000) - { - value = m_scratchpad[(addroff & 0x03ff)>>1]; - return value; - } - // Video: 8800, 8802 - if ((addroff & 0xfffd)==0x8800) - { - value = m_video->read16(space, offset, mem_mask); - return value; - } - } - - // If we are here, check the peribox via the datamux - // catch-all for unmapped zones - value = datamux_read(space, offset, mem_mask); return value; } + WRITE16_MEMBER( ti99_4p_state::memwrite ) { -// m_cpu->adjust_icount(-4); + int address = 0; - int addroff = offset << 1; - UINT16 zone = addroff & 0xe000; - - if (zone==0x0000) + // If we use the debugger, decode the address now (normally done in setaddress) + if (space.debugger_access()) { - // ROM0 - if (TRACE_ILLWRITE) logerror("Ignoring ROM write access at %04x\n", addroff); - return; + m_addr_buf = offset << 1; + m_decode = decode_address(m_addr_buf); } - if (zone==0x2000 || zone==0xa000 || zone==0xc000 || zone==0xe000) + switch (m_decode) { - samsmem_write(space, offset, data, mem_mask); - return; - } + case SGCPU_SYSROM: + if (TRACE_ILLWRITE) logerror("Ignoring ROM write access at %04x\n", m_addr_buf); + break; - if (zone==0x4000) - { - if (m_internal_dsr) - { - if (TRACE_ILLWRITE) logerror("Ignoring DSR write access at %04x\n", addroff); - return; - } - else - { - if (m_access_mapper && ((addroff & 0xffe0)==0x4000)) - { - m_mapper[offset & 0x000f] = data; - return; - } - } - } + case SGCPU_RAM: + // see above + if (m_map_mode) + address = (m_mapper[(m_addr_buf & 0xf000)>>12] << 12) | (m_addr_buf & 0x0fff); + else // transparent mode + address = m_addr_buf; - if (zone==0x6000 && m_internal_rom6) - { - m_rom6_bank = offset & 0x0001; - return; - } + m_ram[address>>1] = data; + break; - // Scratch pad RAM and sound - // speech is in peribox - // groms are in hsgpl in peribox - if (zone==0x8000) - { - if ((addroff & 0xfff0)==0x8400) //sound write - { - m_sound->write(space, 0, (data >> 8) & 0xff); - return; - } - if ((addroff & 0xfc00)==0x8000) - { - m_scratchpad[(addroff & 0x03ff)>>1] = data; - return; - } - // Video: 8C00, 8C02 - if ((addroff & 0xfffd)==0x8c00) - { - m_video->write16(space, offset, data, mem_mask); - return; - } - } + case SGCPU_INTDSR: + if (TRACE_ILLWRITE) logerror("Ignoring DSR write access at %04x\n", m_addr_buf); + break; - // If we are here, check the peribox via the datamux - // catch-all for unmapped zones - datamux_write(space, offset, data, mem_mask); + case SGCPU_MAPPER: + m_mapper[(m_addr_buf>>1) & 0x000f] = data; // writing both bytes, but only the first is accepted + break; + + case SGCPU_ROM6: + // Writing to 6002 sets upper bank + m_rom6_upper = (m_addr_buf & 0x0002)!=0; + break; + + case SGCPU_PADRAM: + // Scratch pad RAM (16 bit) + // 8000 ... 83ff (1K, 4 times the size of the internal RAM of the TI-99/4A) + m_scratchpad[(m_addr_buf & 0x03ff)>>1] = data; + break; + + case SGCPU_PEB: + if (space.debugger_access()) { debugger_write(space, offset, data); return; } + + // Writing the even address now (addr) + // The databus multplexer puts the even value into the latch and outputs the odd value now. + m_latch = (data >> 8) & 0xff; + + // write odd byte + if (TRACE_MEM) logerror("datamux: write odd byte to address %04x <- %02x\n", m_addr_buf+1, data & 0xff); + m_peribox->write(space, m_addr_buf+1, data & 0xff); + m_peribox->memen_in(CLEAR_LINE); + } } -/*************************************************************************** - Internal datamux; similar to TI-99/4A. However, here we have just - one device, the peripheral box, so it is much simpler. -***************************************************************************/ +/* + Used when the debugger is reading values from PEB cards. +*/ +READ16_MEMBER( ti99_4p_state::debugger_read ) +{ + UINT8 lval = 0; + UINT8 hval = 0; + UINT16 addrb = offset << 1; + m_peribox->memen_in(ASSERT_LINE); + m_peribox->readz(space, addrb+1, &lval); + m_peribox->readz(space, addrb, &hval); + m_peribox->memen_in(CLEAR_LINE); + return ((hval << 8)&0xff00) | (lval & 0xff); +} + +/* + Used when the debugger is writing values to PEB cards. +*/ +WRITE16_MEMBER( ti99_4p_state::debugger_write ) +{ + int addrb = offset << 1; + m_peribox->memen_in(ASSERT_LINE); + m_peribox->write(space, addrb+1, data & 0xff); + m_peribox->write(space, addrb, (data>>8) & 0xff); + m_peribox->memen_in(CLEAR_LINE); +} + +/* + Data bus in (DBIN) line from the CPU. +*/ +WRITE_LINE_MEMBER( ti99_4p_state::dbin_line ) +{ + m_dbin = (line_state)state; +} /* The datamux is connected to the clock line in order to operate - the wait state counter. + the wait state counter and to read/write the bytes. */ -void ti99_4p_state::clock_in(int clock) +WRITE_LINE_MEMBER( ti99_4p_state::datamux_clock_in ) { - if (clock==ASSERT_LINE && m_waitcount!=0) + // return immediately if the datamux is currently inactive + if (m_waitcount>0) { - m_waitcount--; - if (m_waitcount==0) console_ready_dmux(ASSERT_LINE); + if (TRACE_MUX) logerror("datamux: wait count %d\n", m_waitcount); + if (m_sysready==CLEAR_LINE) + { + if (TRACE_MUX) logerror("datamux: stalled due to external READY=0\n"); + return; + } + + if (m_dbin==ASSERT_LINE) + { + // Reading + if (state==ASSERT_LINE) + { // raising edge + if (--m_waitcount==0) + { + m_muxready = true; + ready_join(); + } + if (m_waitcount==2) + { + // read odd byte + m_peribox->readz(*m_spacep, m_addr_buf+1, &m_latch); + m_peribox->memen_in(CLEAR_LINE); + + if (TRACE_MEM) logerror("datamux: read odd byte from address %04x -> %02x\n", m_addr_buf+1, m_latch); + + // do the setaddress for the even address + m_peribox->memen_in(ASSERT_LINE); + m_peribox->setaddress_dbin(*m_spacep, m_addr_buf, m_dbin); + } + } + } + else // write access + { + if (state==ASSERT_LINE) + { // raising edge + if (--m_waitcount==0) + { + m_muxready = true; + ready_join(); + } + } + else + { // falling edge + if (m_waitcount==2) + { + // do the setaddress for the even address + m_peribox->memen_in(ASSERT_LINE); + m_peribox->setaddress_dbin(*m_spacep, m_addr_buf, m_dbin); + + // write even byte + if (TRACE_MEM) logerror("datamux: write even byte to address %04x <- %02x\n", m_addr_buf, m_latch); + m_peribox->write(*m_spacep, m_addr_buf, m_latch); + m_peribox->memen_in(CLEAR_LINE); + } + } + } } } - -READ16_MEMBER( ti99_4p_state::datamux_read ) -{ - UINT8 hbyte = 0; - UINT16 addroff = (offset << 1); - - m_peribox->memen_in(ASSERT_LINE); - - m_peribox->readz(space, addroff+1, &m_latch, mem_mask); - m_lowbyte = m_latch; - - m_peribox->readz(space, addroff, &hbyte, mem_mask); - m_highbyte = hbyte; - - m_peribox->memen_in(CLEAR_LINE); - - // use the latch and the currently read byte and put it on the 16bit bus -// printf("read address = %04x, value = %04x, memmask = %4x\n", addroff, (hbyte<<8) | sgcpu->latch, mem_mask); - - // Insert four wait states and let CPU enter wait state - m_waitcount = 6; - console_ready_dmux(CLEAR_LINE); - - return (hbyte<<8) | m_latch ; -} - -/* - Write access. - TODO: use the 16-bit expansion in the box for suitable cards -*/ -WRITE16_MEMBER( ti99_4p_state::datamux_write ) -{ - UINT16 addroff = (offset << 1); -// printf("write address = %04x, value = %04x, memmask = %4x\n", addroff, data, mem_mask); - - // read more about the datamux in datamux.c - - // Write to the PEB - m_peribox->memen_in(ASSERT_LINE); - - m_peribox->write(space, addroff+1, data & 0xff); - - // Write to the PEB - m_peribox->write(space, addroff, (data>>8) & 0xff); - - m_peribox->memen_in(CLEAR_LINE); - - // Insert four wait states and let CPU enter wait state - m_waitcount = 6; - console_ready_dmux(CLEAR_LINE); -} - /*************************************************************************** CRU interface ***************************************************************************/ @@ -528,46 +719,6 @@ READ8_MEMBER( ti99_4p_state::cruread ) return value; } -/*************************************************************************** - AMS Memory implementation -***************************************************************************/ - -/* - Memory read. The SAMS card has two address areas: The memory is at locations - 0x2000-0x3fff and 0xa000-0xffff, and the mapper area is at 0x4000-0x401e - (only even addresses). -*/ -READ16_MEMBER( ti99_4p_state::samsmem_read ) -{ - UINT32 address = 0; - int addroff = offset << 1; - - // select memory expansion - if (m_map_mode) - address = (m_mapper[(addroff>>12) & 0x000f] << 12) + (addroff & 0x0fff); - else // transparent mode - address = addroff; - - return m_ram[address>>1]; -} - -/* - Memory write -*/ -WRITE16_MEMBER( ti99_4p_state::samsmem_write ) -{ - UINT32 address = 0; - int addroff = offset << 1; - - // select memory expansion - if (m_map_mode) - address = (m_mapper[(addroff>>12) & 0x000f] << 12) + (addroff & 0x0fff); - else // transparent mode - address = addroff; - - m_ram[address>>1] = data; -} - /*************************************************************************** Keyboard/tape control ****************************************************************************/ @@ -700,15 +851,11 @@ WRITE_LINE_MEMBER( ti99_4p_state::cassette_output ) ****************************************************************************/ /* - We may have lots of devices pulling down this line; so we should use a AND - gate to do it right. On the other hand, when READY is down, there is just - no chance to make another device pull down the same line; the CPU just - won't access any other device in this time. + Combine the external (sysready) and the own (muxready) READY states. */ -WRITE_LINE_MEMBER( ti99_4p_state::console_ready ) +void ti99_4p_state::ready_join() { - m_ready_line = state; - int combined = (m_ready_line == ASSERT_LINE && m_ready_line_dmux == ASSERT_LINE)? ASSERT_LINE : CLEAR_LINE; + int combined = (m_sysready == ASSERT_LINE && m_muxready)? ASSERT_LINE : CLEAR_LINE; if (TRACE_READY) { @@ -719,21 +866,17 @@ WRITE_LINE_MEMBER( ti99_4p_state::console_ready ) } /* - The exception of the above rule. Memory access over the datamux also operates - the READY line, and the datamux raises READY depending on the clock pulse. - So we must make sure this does not interfere. + Incoming READY line from other cards in the Peripheral Expansion Box. */ -WRITE_LINE_MEMBER( ti99_4p_state::console_ready_dmux ) +WRITE_LINE_MEMBER( ti99_4p_state::ready_line ) { - m_ready_line_dmux = state; - int combined = (m_ready_line == ASSERT_LINE && m_ready_line_dmux == ASSERT_LINE)? ASSERT_LINE : CLEAR_LINE; - if (TRACE_READY) { - if (m_ready_prev != combined) logerror("READY dmux level = %d\n", state); + if (state != m_sysready) logerror("READY line from PBox = %d\n", state); } - m_ready_prev = combined; - m_cpu->set_ready(combined); + m_sysready = (line_state)state; + // Also propagate to CPU via driver + ready_join(); } void ti99_4p_state::set_9901_int( int line, line_state state) @@ -760,7 +903,8 @@ WRITE_LINE_MEMBER( ti99_4p_state::notconnected ) */ WRITE_LINE_MEMBER( ti99_4p_state::clock_out ) { - clock_in(state); + datamux_clock_in(state); + m_peribox->clock_in(state); } WRITE8_MEMBER( ti99_4p_state::tms9901_interrupt ) @@ -781,7 +925,7 @@ READ8_MEMBER( ti99_4p_state::interrupt_level ) WRITE8_MEMBER( ti99_4p_state::external_operation ) { static const char* extop[8] = { "inv1", "inv2", "IDLE", "RSET", "inv3", "CKON", "CKOF", "LREX" }; - logerror("External operation %s not implemented on the SGCPU board\n", extop[offset]); + if (offset != IDLE_OP) logerror("External operation %s not implemented on the SGCPU board\n", extop[offset]); } /*****************************************************************************/ @@ -796,19 +940,16 @@ void ti99_4p_state::machine_start() m_firstjoy = 6; - m_ready_line = m_ready_line_dmux = ASSERT_LINE; + m_sysready = ASSERT_LINE; + m_muxready = true; - UINT16 *rom = (UINT16*)(memregion("maincpu")->base()); - m_rom0 = rom + 0x2000; - m_dsr = rom + 0x6000; - m_rom6a = rom + 0x3000; - m_rom6b = rom + 0x7000; + m_rom = (UINT16*)(memregion("maincpu")->base()); } /* set the state of int2 (called by the v9938) */ -WRITE_LINE_MEMBER(ti99_4p_state::set_tms9901_INT2_from_v9938) +WRITE_LINE_MEMBER(ti99_4p_state::video_interrupt_in) { set_9901_int(2, (line_state)state); } @@ -836,12 +977,7 @@ static MACHINE_CONFIG_START( ti99_4p_60hz, ti99_4p_state ) MCFG_TMS99xx_EXTOP_HANDLER( WRITE8(ti99_4p_state, external_operation) ) MCFG_TMS99xx_INTLEVEL_HANDLER( READ8(ti99_4p_state, interrupt_level) ) MCFG_TMS99xx_CLKOUT_HANDLER( WRITELINE(ti99_4p_state, clock_out) ) - - /* video hardware */ - MCFG_DEVICE_ADD(VIDEO_SYSTEM_TAG, V9938VIDEO, 0) - MCFG_V9938_ADD(VDP_TAG, SCREEN_TAG, 0x20000, XTAL_21_4772MHz) /* typical 9938 clock, not verified */ - MCFG_V99X8_INTERRUPT_CALLBACK(WRITELINE(ti99_4p_state, set_tms9901_INT2_from_v9938)) - MCFG_V99X8_SCREEN_ADD_NTSC(SCREEN_TAG, VDP_TAG, XTAL_21_4772MHz) + MCFG_TMS99xx_DBIN_HANDLER( WRITELINE(ti99_4p_state, dbin_line) ) // tms9901 MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000) @@ -858,13 +994,10 @@ static MACHINE_CONFIG_START( ti99_4p_60hz, ti99_4p_state ) MCFG_DEVICE_ADD( PERIBOX_TAG, PERIBOX_SG, 0) MCFG_PERIBOX_INTA_HANDLER( WRITELINE(ti99_4p_state, extint) ) MCFG_PERIBOX_INTB_HANDLER( WRITELINE(ti99_4p_state, notconnected) ) - MCFG_PERIBOX_READY_HANDLER( WRITELINE(ti99_4p_state, console_ready) ) + MCFG_PERIBOX_READY_HANDLER( WRITELINE(ti99_4p_state, ready_line) ) - // Sound hardware - MCFG_SPEAKER_STANDARD_MONO("sound_out") - MCFG_SOUND_ADD(TISOUNDCHIP_TAG, SN94624, 3579545/8) /* 3.579545 MHz */ - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "sound_out", 0.75) - MCFG_SN76496_READY_HANDLER( WRITELINE(ti99_4p_state, console_ready) ) + // The SGCPU actually makes use of this pin which was unused before + MCFG_PERIBOX_LCP_HANDLER( WRITELINE(ti99_4p_state, video_interrupt_in) ) // Cassette drives MCFG_SPEAKER_STANDARD_MONO("cass_out") @@ -887,4 +1020,4 @@ ROM_START(ti99_4p) ROM_END /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */ -COMP( 1996, ti99_4p, 0, 0, ti99_4p_60hz, ti99_4p, driver_device, 0, "System 99 Users Group", "SGCPU (a.k.a. 99/4P)" , 0 ) +COMP( 1996, ti99_4p, 0, 0, ti99_4p_60hz, ti99_4p, driver_device, 0, "System-99 User Group", "SGCPU (aka TI-99/4P)" , 0 ) diff --git a/src/mame/drivers/ti99_4x.cpp b/src/mame/drivers/ti99_4x.cpp index 898327f92a7..e487f149c3c 100644 --- a/src/mame/drivers/ti99_4x.cpp +++ b/src/mame/drivers/ti99_4x.cpp @@ -46,7 +46,7 @@ #include "machine/tms9901.h" #include "imagedev/cassette.h" -#include "bus/ti99x/videowrp.h" +#include "bus/ti99x/ti99defs.h" #include "bus/ti99x/datamux.h" #include "bus/ti99x/gromport.h" #include "bus/ti99x/joyport.h" @@ -73,7 +73,7 @@ public: m_peribox(*this, PERIBOX_TAG), m_joyport(*this, JOYPORT_TAG), m_datamux(*this, DATAMUX_TAG), - m_video(*this, VIDEO_SYSTEM_TAG), + m_video(*this, VDP_TAG), m_cassette1(*this, "cassette"), m_cassette2(*this, "cassette2") { } @@ -130,6 +130,7 @@ public: DECLARE_INPUT_CHANGED_MEMBER( load_interrupt ); // Used by EVPC + DECLARE_WRITE_LINE_MEMBER( video_interrupt_evpc_in ); void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; private: @@ -157,7 +158,7 @@ private: required_device m_peribox; required_device m_joyport; required_device m_datamux; - required_device m_video; + optional_device m_video; required_device m_cassette1; required_device m_cassette2; @@ -655,6 +656,13 @@ void ti99_4x_state::device_timer(emu_timer &timer, device_timer_id id, int param /*****************************************************************************/ +WRITE_LINE_MEMBER( ti99_4x_state::video_interrupt_evpc_in ) +{ + if (TRACE_INTERRUPTS) logerror("ti99_4x: VDP INT2 from EVPC on tms9901, level=%d\n", state); + m_int2 = (line_state)state; + m_tms9901->set_single_int(2, state); +} + /* set the state of TMS9901's INT2 (called by the tms9928 core) */ @@ -754,7 +762,7 @@ WRITE_LINE_MEMBER( ti99_4x_state::console_reset ) { logerror("ti99_4x: Console reset line = %d\n", state); m_cpu->set_input_line(INT_9900_RESET, state); - m_video->reset_vdp(state); + m_video->reset_line(state); } } @@ -770,6 +778,37 @@ WRITE_LINE_MEMBER( ti99_4x_state::notconnected ) if (TRACE_INTERRUPTS) logerror("ti99_4x: Setting a not connected line ... ignored\n"); } +#if 0 +/* + External clock connector. This is actually a separate cable lead going from + the EPVC in the PEB to a pin inside the console. This cable sends the + video interrupt from the v9938 on the EVPC into the console. + This workaround must be done on the real system because the peripheral + box and its connector were not designed to deliver a video interrupt signal. + This was fixed with the EVPC2 which uses the external interrupt EXTINT + with a special firmware (DSR). + + Emulation detail: We are using a separate device class in order to avoid + exposing the console class to the external class. +*/ +evpc_clock_connector::evpc_clock_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) +: device_t(mconfig, EVPC_CONN, "EVPC clock connector", tag, owner, clock, "ti99_evpc_clock", __FILE__) +{ +} + +void evpc_clock_connector::device_start() +{ + m_console = downcast(owner()); +} + +WRITE_LINE_MEMBER( evpc_clock_connector::vclock_line ) +{ + m_console->video_interrupt_in(state); +}; + +const device_type EVPC_CONN = &device_creator; +#endif + /****************************************************************************** Machine definitions ******************************************************************************/ @@ -863,14 +902,24 @@ MACHINE_CONFIG_END US version: 60 Hz, NTSC */ static MACHINE_CONFIG_DERIVED( ti99_4_60hz, ti99_4 ) - MCFG_TI_TMS991x_ADD_NTSC(VIDEO_SYSTEM_TAG, TMS9918, 0x4000, ti99_4x_state, video_interrupt_in, gromclk_in) + MCFG_DEVICE_ADD( VDP_TAG, TMS9918, XTAL_10_738635MHz / 2 ) \ + MCFG_TMS9928A_VRAM_SIZE(0x4000) \ + MCFG_TMS9928A_OUT_INT_LINE_CB(WRITELINE(ti99_4x_state, video_interrupt_in)) \ + MCFG_TMS9928A_OUT_GROMCLK_CB(WRITELINE(ti99_4x_state, gromclk_in)) \ + MCFG_TMS9928A_SCREEN_ADD_NTSC( SCREEN_TAG ) \ + MCFG_SCREEN_UPDATE_DEVICE( VDP_TAG, tms9928a_device, screen_update ) MACHINE_CONFIG_END /* European version: 50 Hz, PAL */ static MACHINE_CONFIG_DERIVED( ti99_4_50hz, ti99_4 ) - MCFG_TI_TMS991x_ADD_PAL(VIDEO_SYSTEM_TAG, TMS9929, 0x4000, ti99_4x_state, video_interrupt_in, gromclk_in) + MCFG_DEVICE_ADD( VDP_TAG, TMS9929, XTAL_10_738635MHz / 2 ) \ + MCFG_TMS9928A_VRAM_SIZE(0x4000) \ + MCFG_TMS9928A_OUT_INT_LINE_CB(WRITELINE(ti99_4x_state, video_interrupt_in)) \ + MCFG_TMS9928A_OUT_GROMCLK_CB(WRITELINE(ti99_4x_state, gromclk_in)) \ + MCFG_TMS9928A_SCREEN_ADD_PAL( SCREEN_TAG ) \ + MCFG_SCREEN_UPDATE_DEVICE( VDP_TAG, tms9928a_device, screen_update ) MACHINE_CONFIG_END /********************************************************************** @@ -961,14 +1010,24 @@ MACHINE_CONFIG_END US version: 60 Hz, NTSC */ static MACHINE_CONFIG_DERIVED( ti99_4a_60hz, ti99_4a ) - MCFG_TI_TMS991x_ADD_NTSC(VIDEO_SYSTEM_TAG, TMS9918A, 0x4000, ti99_4x_state, video_interrupt_in, gromclk_in) + MCFG_DEVICE_ADD( VDP_TAG, TMS9918A, XTAL_10_738635MHz / 2 ) \ + MCFG_TMS9928A_VRAM_SIZE(0x4000) \ + MCFG_TMS9928A_OUT_INT_LINE_CB(WRITELINE(ti99_4x_state, video_interrupt_in)) \ + MCFG_TMS9928A_OUT_GROMCLK_CB(WRITELINE(ti99_4x_state, gromclk_in)) \ + MCFG_TMS9928A_SCREEN_ADD_NTSC( SCREEN_TAG ) \ + MCFG_SCREEN_UPDATE_DEVICE( VDP_TAG, tms9928a_device, screen_update ) MACHINE_CONFIG_END /* European version: 50 Hz, PAL */ static MACHINE_CONFIG_DERIVED( ti99_4a_50hz, ti99_4a ) - MCFG_TI_TMS991x_ADD_PAL(VIDEO_SYSTEM_TAG, TMS9929A, 0x4000, ti99_4x_state, video_interrupt_in, gromclk_in) + MCFG_DEVICE_ADD( VDP_TAG, TMS9929A, XTAL_10_738635MHz / 2 ) \ + MCFG_TMS9928A_VRAM_SIZE(0x4000) \ + MCFG_TMS9928A_OUT_INT_LINE_CB(WRITELINE(ti99_4x_state, video_interrupt_in)) \ + MCFG_TMS9928A_OUT_GROMCLK_CB(WRITELINE(ti99_4x_state, gromclk_in)) \ + MCFG_TMS9928A_SCREEN_ADD_PAL( SCREEN_TAG ) \ + MCFG_SCREEN_UPDATE_DEVICE( VDP_TAG, tms9928a_device, screen_update ) MACHINE_CONFIG_END /************************************************************************ @@ -996,19 +1055,32 @@ MACHINE_CONFIG_END US version: 60 Hz, NTSC */ static MACHINE_CONFIG_DERIVED( ti99_4qi_60hz, ti99_4qi ) - MCFG_TI_TMS991x_ADD_NTSC(VIDEO_SYSTEM_TAG, TMS9918A, 0x4000, ti99_4x_state, video_interrupt_in, gromclk_in) + MCFG_DEVICE_ADD( VDP_TAG, TMS9918A, XTAL_10_738635MHz / 2 ) \ + MCFG_TMS9928A_VRAM_SIZE(0x4000) \ + MCFG_TMS9928A_OUT_INT_LINE_CB(WRITELINE(ti99_4x_state, video_interrupt_in)) \ + MCFG_TMS9928A_OUT_GROMCLK_CB(WRITELINE(ti99_4x_state, gromclk_in)) \ + MCFG_TMS9928A_SCREEN_ADD_NTSC( SCREEN_TAG ) \ + MCFG_SCREEN_UPDATE_DEVICE( VDP_TAG, tms9928a_device, screen_update ) MACHINE_CONFIG_END /* European version: 50 Hz, PAL */ static MACHINE_CONFIG_DERIVED( ti99_4qi_50hz, ti99_4qi ) - MCFG_TI_TMS991x_ADD_PAL(VIDEO_SYSTEM_TAG, TMS9929A, 0x4000, ti99_4x_state, video_interrupt_in, gromclk_in) + MCFG_DEVICE_ADD( VDP_TAG, TMS9929A, XTAL_10_738635MHz / 2 ) \ + MCFG_TMS9928A_VRAM_SIZE(0x4000) \ + MCFG_TMS9928A_OUT_INT_LINE_CB(WRITELINE(ti99_4x_state, video_interrupt_in)) \ + MCFG_TMS9928A_OUT_GROMCLK_CB(WRITELINE(ti99_4x_state, gromclk_in)) \ + MCFG_TMS9928A_SCREEN_ADD_PAL( SCREEN_TAG ) \ + MCFG_SCREEN_UPDATE_DEVICE( VDP_TAG, tms9928a_device, screen_update ) MACHINE_CONFIG_END /************************************************************************ TI-99/4A with 80-column support. Actually a separate expansion card (EVPC), replacing the console video processor. + + Note that the sound chip is also moved to this card, because the SGCPU, + which is intended to use the EVPC, does not have an own sound chip. *************************************************************************/ MACHINE_START_MEMBER(ti99_4x_state, ti99_4ev) @@ -1043,12 +1115,6 @@ static MACHINE_CONFIG_START( ti99_4ev_60hz, ti99_4x_state ) MCFG_MACHINE_START_OVERRIDE(ti99_4x_state, ti99_4ev ) MCFG_MACHINE_RESET_OVERRIDE(ti99_4x_state, ti99_4ev ) - /* video hardware */ - MCFG_DEVICE_ADD(VIDEO_SYSTEM_TAG, V9938VIDEO, 0) - MCFG_V9938_ADD(VDP_TAG, SCREEN_TAG, 0x20000, XTAL_21_4772MHz) /* typical 9938 clock, not verified */ - MCFG_V99X8_INTERRUPT_CALLBACK(WRITELINE(ti99_4x_state, video_interrupt_in)) - MCFG_V99X8_SCREEN_ADD_NTSC(SCREEN_TAG, VDP_TAG, XTAL_21_4772MHz) - /* Main board */ MCFG_DEVICE_ADD(TMS9901_TAG, TMS9901, 3000000) MCFG_TMS9901_READBLOCK_HANDLER( READ8(ti99_4x_state, read_by_9901) ) @@ -1068,6 +1134,9 @@ static MACHINE_CONFIG_START( ti99_4ev_60hz, ti99_4x_state ) MCFG_GROMPORT_READY_HANDLER( WRITELINE(ti99_4x_state, console_ready_cart) ) MCFG_GROMPORT_RESET_HANDLER( WRITELINE(ti99_4x_state, console_reset) ) + // EVPC connector + MCFG_ADD_EVPC_CONNECTOR( EVPC_CONN_TAG, WRITELINE( ti99_4x_state, video_interrupt_evpc_in ) ) + /* Software list */ MCFG_SOFTWARE_LIST_ADD("cart_list_ti99", "ti99_cart") @@ -1077,12 +1146,6 @@ static MACHINE_CONFIG_START( ti99_4ev_60hz, ti99_4x_state ) MCFG_PERIBOX_INTB_HANDLER( WRITELINE(ti99_4x_state, notconnected) ) MCFG_PERIBOX_READY_HANDLER( DEVWRITELINE(DATAMUX_TAG, ti99_datamux_device, ready_line) ) - // Sound hardware - MCFG_SPEAKER_STANDARD_MONO("sound_out") - MCFG_SOUND_ADD(TISOUNDCHIP_TAG, SN94624, 3579545/8) /* 3.579545 MHz */ - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "sound_out", 0.75) - MCFG_SN76496_READY_HANDLER( WRITELINE(ti99_4x_state, console_ready_sound) ) - /* Cassette drives */ MCFG_SPEAKER_STANDARD_MONO("cass_out") MCFG_CASSETTE_ADD( "cassette" ) diff --git a/src/mame/drivers/ti99_8.cpp b/src/mame/drivers/ti99_8.cpp index 9b661f71e82..91d71536929 100644 --- a/src/mame/drivers/ti99_8.cpp +++ b/src/mame/drivers/ti99_8.cpp @@ -182,7 +182,6 @@ Known Issues (MZ, 2010-11-07) #include "imagedev/cassette.h" #include "bus/ti99x/998board.h" -#include "bus/ti99x/videowrp.h" #include "bus/ti99x/gromport.h" #include "bus/ti99x/joyport.h"