ti99_2: Emulate the expansion port and a 32K expansion module.

This commit is contained in:
Michael Zapf 2020-06-21 15:17:25 +02:00
parent 4c0cfc7860
commit dc91091959
3 changed files with 176 additions and 7 deletions

View File

@ -7,7 +7,12 @@
This component implements the custom video controller and interface chip
from the TI-99/2 console.
Also, we emulate the expansion port at the backside of the console; there
are no known expansions except for a RAM expansion that is mentioned
in the specifications.
May 2018
June 2020
***************************************************************************/
@ -20,8 +25,9 @@
#define LOG_HEXBUS (1U<<4) // Hexbus logging
#define LOG_BANK (1U<<5) // Change ROM banks
#define LOG_KEYBOARD (1U<<6) // Keyboard operation
#define LOG_EXPRAM (1U<<7) // Expansion RAM
#define VERBOSE ( LOG_WARN )
#define VERBOSE ( LOG_GENERAL | LOG_WARN )
#include "logmacro.h"
@ -128,6 +134,8 @@ DEFINE_DEVICE_TYPE_NS(VIDEO99232, bus::ti99::internal, video992_32_device, "vide
DEFINE_DEVICE_TYPE_NS(IO99224, bus::ti99::internal, io992_24_device, "io992_24", "TI-99/2 I/O controller 24K version")
DEFINE_DEVICE_TYPE_NS(IO99232, bus::ti99::internal, io992_32_device, "io992_32", "TI-99/2 I/O controller 32K version")
DEFINE_DEVICE_TYPE_NS(TI992_EXPPORT, bus::ti99::internal, ti992_expport_device, "ti992_expport", "TI-99/2 Expansion Port")
DEFINE_DEVICE_TYPE_NS(TI992_RAM32K, bus::ti99::internal, ti992_expram_device, "ti992_ram32k", "TI-99/2 RAM Expansion 32K")
namespace bus { namespace ti99 { namespace internal {
@ -596,6 +604,82 @@ ioport_constructor io992_device::device_input_ports() const
return INPUT_PORTS_NAME( keys992 );
}
/********************************************************************
Expansion port
********************************************************************/
ti992_expport_device::ti992_expport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TI992_EXPPORT, tag, owner, clock),
device_slot_interface(mconfig, *this),
m_connected(nullptr)
{
}
void ti992_expport_device::readz(offs_t offset, uint8_t *value)
{
if (m_connected != nullptr)
m_connected->readz(offset, value);
}
void ti992_expport_device::write(offs_t offset, uint8_t data)
{
if (m_connected != nullptr)
m_connected->write(offset, data);
}
void ti992_expport_device::device_config_complete()
{
m_connected = static_cast<ti992_expport_attached_device*>(subdevices().first());
}
/*
32K Expansion cartridge
Maps at 6000 - DFFF
This is the only known expansion device
*/
ti992_expram_device::ti992_expram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
ti992_expport_attached_device(mconfig, TI992_RAM32K, tag, owner, clock),
m_ram(*this, "ram32k")
{
}
void ti992_expram_device::readz(offs_t offset, uint8_t *value)
{
// 000 -> 100 100 -> 000
// 001 -> 101 101 -> 001
// 010 -> 110 110 -> 010
// 011 -> 011 111 -> 111
offs_t address = offset;
if ((offset & 0x6000) != 0x6000) address ^= 0x8000;
if ((address & 0x8000)==0)
{
*value = m_ram->read(address);
LOGMASKED(LOG_EXPRAM, "expram %04x -> %02x\n", offset, *value);
}
}
void ti992_expram_device::write(offs_t offset, uint8_t value)
{
offs_t address = offset;
if ((offset & 0x6000) != 0x6000) address ^= 0x8000;
if ((address & 0x8000)==0)
{
m_ram->write(address, value);
LOGMASKED(LOG_EXPRAM, "expram %04x <- %02x\n", offset, value);
}
}
void ti992_expram_device::device_add_mconfig(machine_config &config)
{
RAM(config, m_ram, 0);
m_ram->set_default_size("32k");
m_ram->set_default_value(0);
}
} } }
void ti992_expport_options(device_slot_interface &device)
{
device.option_add("ram32k", TI992_RAM32K);
}

View File

@ -21,6 +21,7 @@
#include "screen.h"
#include "bus/hexbus/hexbus.h"
#include "imagedev/cassette.h"
#include "machine/ram.h"
#define TI992_CASSETTE "cassette"
#define TI992_VDC_TAG "vdc"
@ -149,11 +150,87 @@ public:
io992_32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
/********************************************************************
Expansion port
This is modeled after the ioport connector of the TI-99/4A
However, since there are basically no expansion cards available,
and only the memory expansion was described in the specs, we
only include the necessary connections.
********************************************************************/
#define TI992_EXPPORT_TAG "expport"
class ti992_expport_attached_device : public device_t
{
public:
ti992_expport_attached_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock)
{ }
// Methods called from the console
virtual void readz(offs_t offset, uint8_t *value) { }
virtual void write(offs_t offset, uint8_t data) { }
};
class ti992_expport_device : public device_t, public device_slot_interface
{
friend class expport_attached_device;
public:
template <typename U>
ti992_expport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, U &&opts, const char *dflt)
: ti992_expport_device(mconfig, tag, owner, clock)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
ti992_expport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// Methods called from the console
// More methods should be added, once we can find further 99/2 cartridges
void readz(offs_t offset, uint8_t *value);
void write(offs_t offset, uint8_t data);
protected:
void device_start() override { };
void device_config_complete() override;
private:
ti992_expport_attached_device* m_connected;
};
// RAM expansion
class ti992_expram_device : public ti992_expport_attached_device
{
public:
ti992_expram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
private:
void device_start() override {};
void device_add_mconfig(machine_config &config) override;
required_device<ram_device> m_ram;
};
} } } // end namespace bus::ti99::internal
DECLARE_DEVICE_TYPE_NS(TI992_EXPPORT, bus::ti99::internal, ti992_expport_device)
void ti992_expport_options(device_slot_interface &device);
DECLARE_DEVICE_TYPE_NS(VIDEO99224, bus::ti99::internal, video992_24_device)
DECLARE_DEVICE_TYPE_NS(VIDEO99232, bus::ti99::internal, video992_32_device)
DECLARE_DEVICE_TYPE_NS(IO99224, bus::ti99::internal, io992_24_device)
DECLARE_DEVICE_TYPE_NS(IO99232, bus::ti99::internal, io992_32_device)
DECLARE_DEVICE_TYPE_NS(TI992_RAM32K, bus::ti99::internal, ti992_expram_device)
#endif // MAME_BUS_TI99_INTERNAL_992BOARD_H

View File

@ -193,6 +193,7 @@ public:
m_io992(*this, TI992_IO_TAG),
m_cassette(*this, TI992_CASSETTE),
m_ram(*this, TI992_RAM_TAG),
m_expport(*this, TI992_EXPPORT_TAG),
m_otherbank(false),
m_rom(nullptr),
m_ram_start(0xf000),
@ -230,6 +231,8 @@ private:
required_device<cassette_image_device> m_cassette;
required_device<ram_device> m_ram;
required_device<bus::ti99::internal::ti992_expport_device> m_expport;
bool m_otherbank;
uint8_t* m_rom;
@ -322,6 +325,7 @@ void ti99_2_state::intflag_write(offs_t offset, uint8_t data)
*/
uint8_t ti99_2_state::mem_read(offs_t offset)
{
uint8_t value = 0;
if (m_maincpu->is_onchip(offset)) return m_maincpu->debug_read_onchip_memory(offset&0xff);
int page = offset >> 12;
@ -329,22 +333,23 @@ uint8_t ti99_2_state::mem_read(offs_t offset)
if (page>=0 && page<4)
{
// ROM, unbanked
return m_rom[offset];
value = m_rom[offset];
}
if (page>=4 && page<6)
{
// ROM, banked on 32K version
if (m_otherbank) offset = (offset & 0x1fff) | 0x10000;
return m_rom[offset];
value = m_rom[offset];
}
if ((page >= m_first_ram_page) && (page < 15))
{
return m_ram->pointer()[offset - m_ram_start];
value = m_ram->pointer()[offset - m_ram_start];
}
LOGMASKED(LOG_WARN, "Unmapped read access at %04x\n", offset);
return 0;
m_expport->readz(offset, &value);
return value;
}
void ti99_2_state::mem_write(offs_t offset, uint8_t data)
@ -370,7 +375,7 @@ void ti99_2_state::mem_write(offs_t offset, uint8_t data)
return;
}
LOGMASKED(LOG_WARN, "Unmapped write access at %04x\n", offset);
m_expport->write(offset, data);
}
/*
@ -470,6 +475,9 @@ void ti99_2_state::ti99_2(machine_config& config)
// Hexbus
HEXBUS(config, TI992_HEXBUS_TAG, 0, hexbus_options, nullptr);
// Expansion port (backside)
TI992_EXPPORT(config, m_expport, 0, ti992_expport_options, nullptr);
}
/*