summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/spchrom.c
diff options
context:
space:
mode:
author smf- <smf-@users.noreply.github.com>2013-05-14 10:21:05 +0000
committer smf- <smf-@users.noreply.github.com>2013-05-14 10:21:05 +0000
commitd700c1f372a451a08cd7737be70372efdbdb1fa8 (patch)
treeeecbe8dfb684f585736c17c902e9b84cb00abef5 /src/emu/machine/spchrom.c
parent25cb3c0cdaaaffeee62bd8e5528a9c9ecfc48219 (diff)
modernised TMS5220 [smf]
Diffstat (limited to 'src/emu/machine/spchrom.c')
-rw-r--r--src/emu/machine/spchrom.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/emu/machine/spchrom.c b/src/emu/machine/spchrom.c
new file mode 100644
index 00000000000..27f1960e172
--- /dev/null
+++ b/src/emu/machine/spchrom.c
@@ -0,0 +1,115 @@
+/*
+ spchroms.c - This is an emulator for "typical" speech ROMs from TI, as used by TI99/4(a).
+
+ In order to support its speech processor, TI designed some ROMs with a 1-bit data bus
+ and 4-bit address bus (multiplexed 5 times to provide a 18-bit address).
+ A fairly complete description of such a ROM (tms6100) is found in the tms5220 datasheet.
+
+ One notable thing is that the address is a byte address (*NOT* a bit address).
+
+ This file is designed to be interfaced with the tms5220 core.
+ Interfacing it with the tms5110 would make sense, too.
+*/
+
+#include "emu.h"
+#include "spchrom.h"
+
+#define TMS5220_ADDRESS_MASK 0x3FFFFUL /* 18-bit mask for tms5220 address */
+
+// device type definition
+const device_type SPEECHROM = &device_creator<speechrom_device>;
+
+speechrom_device::speechrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, SPEECHROM, "SPEECHROM", tag, owner, clock),
+ m_speechROMaddr(0),
+ m_load_pointer(0),
+ m_ROM_bits_count(0)
+{
+}
+
+/*
+ Read 'count' bits serially from speech ROM
+*/
+int speechrom_device::read(int count)
+{
+ int val;
+
+ if (m_load_pointer)
+ { /* first read after load address is ignored */
+ m_load_pointer = 0;
+ count--;
+ }
+
+ if (m_speechROMaddr < m_speechROMlen)
+ if (count < m_ROM_bits_count)
+ {
+ m_ROM_bits_count -= count;
+ val = (m_speechrom_data[m_speechROMaddr] >> m_ROM_bits_count) & (0xFF >> (8 - count));
+ }
+ else
+ {
+ val = ((int) m_speechrom_data[m_speechROMaddr]) << 8;
+
+ m_speechROMaddr = (m_speechROMaddr + 1) & TMS5220_ADDRESS_MASK;
+
+ if (m_speechROMaddr < m_speechROMlen)
+ val |= m_speechrom_data[m_speechROMaddr];
+
+ m_ROM_bits_count += 8 - count;
+
+ val = (val >> m_ROM_bits_count) & (0xFF >> (8 - count));
+ }
+ else
+ val = 0;
+
+ return val;
+}
+
+/*
+ Write an address nibble to speech ROM
+*/
+void speechrom_device::load_address(int data)
+{
+ /* tms5220 data sheet says that if we load only one 4-bit nibble, it won't work.
+ This code does not care about this. */
+ m_speechROMaddr = ( (m_speechROMaddr & ~(0xf << m_load_pointer))
+ | (((unsigned long) (data & 0xf)) << m_load_pointer) ) & TMS5220_ADDRESS_MASK;
+ m_load_pointer += 4;
+ m_ROM_bits_count = 8;
+}
+
+/*
+ Perform a read and branch command
+*/
+void speechrom_device::read_and_branch()
+{
+ /* tms5220 data sheet says that if more than one speech ROM (tms6100) is present,
+ there is a bus contention. This code does not care about this. */
+ if (m_speechROMaddr < m_speechROMlen-1)
+ m_speechROMaddr = (m_speechROMaddr & 0x3c000UL)
+ | (((((unsigned long) m_speechrom_data[m_speechROMaddr]) << 8)
+ | m_speechrom_data[m_speechROMaddr+1]) & 0x3fffUL);
+ else if (m_speechROMaddr == m_speechROMlen-1)
+ m_speechROMaddr = (m_speechROMaddr & 0x3c000UL)
+ | ((((unsigned long) m_speechrom_data[m_speechROMaddr]) << 8) & 0x3fffUL);
+ else
+ m_speechROMaddr = (m_speechROMaddr & 0x3c000UL);
+
+ m_ROM_bits_count = 8;
+}
+
+void speechrom_device::device_start()
+{
+ memory_region *region = memregion(tag());
+ if (region == NULL)
+ {
+ throw emu_fatalerror("No region for device '%s'\n", tag());
+ }
+
+ m_speechrom_data = region->base();
+ m_speechROMlen = region->bytes();
+
+ save_item(NAME(m_speechROMaddr));
+ save_item(NAME(m_load_pointer));
+ save_item(NAME(m_ROM_bits_count));
+}