mirror of
https://github.com/holub/mame
synced 2025-07-05 18:08:04 +03:00
New GROM implementation (TMC0430)
This commit is contained in:
parent
ee6684ac85
commit
ac3d3e5e41
@ -21,71 +21,71 @@
|
|||||||
MO = Mode. 1=address counter access, 0=data access
|
MO = Mode. 1=address counter access, 0=data access
|
||||||
GS* = GROM select. 0=select, 1=deselect
|
GS* = GROM select. 0=select, 1=deselect
|
||||||
|
|
||||||
GROMs are slow ROM devices, which are interfaced via a 8-bit data bus,
|
GROMs are slow ROM devices, which are interfaced via a 8-bit data bus,
|
||||||
and which include an internal address pointer which is incremented
|
and which include an internal address pointer which is incremented
|
||||||
after each read. This implies that accesses are faster when reading
|
after each read. This implies that accesses are faster when reading
|
||||||
consecutive bytes, although the address pointer can be read and written at any time.
|
consecutive bytes, although the address pointer can be read and written at any time.
|
||||||
|
|
||||||
GROMs are generally used to store programs written in GPL (Graphic Programming
|
GROMs are generally used to store programs written in GPL (Graphic Programming
|
||||||
Language): a proprietary, interpreted language from Texas Instruments which
|
Language): a proprietary, interpreted language from Texas Instruments which
|
||||||
is the machine language in some kind of virtual machine that is running
|
is the machine language in some kind of virtual machine that is running
|
||||||
inside the TI-99/4, TI-99/4A, and TI-99/8 computers.
|
inside the TI-99/4, TI-99/4A, and TI-99/8 computers.
|
||||||
|
|
||||||
Communication with GROM is done by writing and reading data over the
|
Communication with GROM is done by writing and reading data over the
|
||||||
AD0-AD7 lines. The M line determines whether the circuit will input or
|
AD0-AD7 lines. The M line determines whether the circuit will input or
|
||||||
output data over the bus. For GROMs, writing data is only done for setting
|
output data over the bus. For GROMs, writing data is only done for setting
|
||||||
the internal address register. The MO line must be asserted for accessing
|
the internal address register. The MO line must be asserted for accessing
|
||||||
this address register; otherwise data from the memory banks can be read.
|
this address register; otherwise data from the memory banks can be read.
|
||||||
Clearing MO and M means writing data, and although so-called GRAMs were
|
Clearing MO and M means writing data, and although so-called GRAMs were
|
||||||
mentioned by Texas Instruments in the specifications and manuals, they
|
mentioned by Texas Instruments in the specifications and manuals, they
|
||||||
were never seen. GROMs ignore this setting.
|
were never seen. GROMs ignore this setting.
|
||||||
|
|
||||||
Setting the address is done by writing two bytes to the circuit with
|
Setting the address is done by writing two bytes to the circuit with
|
||||||
M=0 and MO=1. In real systems, these lines are usually controlled by
|
M=0 and MO=1. In real systems, these lines are usually controlled by
|
||||||
address bus lines, which maps the circuit into the memory space at specific
|
address bus lines, which maps the circuit into the memory space at specific
|
||||||
addresses.
|
addresses.
|
||||||
|
|
||||||
The GROM address counter is 13 bits long (8 KiB), and judging from its
|
The GROM address counter is 13 bits long (8 KiB), and judging from its
|
||||||
behavior, the memory is organized as three banks of 2 KiB each:
|
behavior, the memory is organized as three banks of 2 KiB each:
|
||||||
|
|
||||||
00 -> Bank 0
|
00 -> Bank 0
|
||||||
01 -> Bank 1
|
01 -> Bank 1
|
||||||
10 -> Bank 2
|
10 -> Bank 2
|
||||||
11 -> Bank 1 OR Bank 2
|
11 -> Bank 1 OR Bank 2
|
||||||
|
|
||||||
The fourth 2 KiB block seems to be a logical OR of the contents of
|
The fourth 2 KiB block seems to be a logical OR of the contents of
|
||||||
bank 1 and 2. This means that one GROM delivers a maximum of 6 KiB of data.
|
bank 1 and 2. This means that one GROM delivers a maximum of 6 KiB of data.
|
||||||
Nevertheless, the address counter advances into the forbidden bank, and
|
Nevertheless, the address counter advances into the forbidden bank, and
|
||||||
wraps at its end to bank 0.
|
wraps at its end to bank 0.
|
||||||
|
|
||||||
8 GROMs can be used to cover a whole 16-bit address space, but only
|
8 GROMs can be used to cover a whole 16-bit address space, but only
|
||||||
48 KiB of memory can be used. Each GROM has a burnt-in 3 bit identifier
|
48 KiB of memory can be used. Each GROM has a burnt-in 3 bit identifier
|
||||||
which allows us to put 8 GROMs in parallel, each one answering only
|
which allows us to put 8 GROMs in parallel, each one answering only
|
||||||
when its area is currently selected.
|
when its area is currently selected.
|
||||||
|
|
||||||
The address that is loaded into the address register contains two parts:
|
The address that is loaded into the address register contains two parts:
|
||||||
|
|
||||||
[ I I I A A A A A A A A A A A A A ]
|
[ I I I A A A A A A A A A A A A A ]
|
||||||
|
|
||||||
The I bits indicate which GROM to use. They are latched inside every GROM,
|
The I bits indicate which GROM to use. They are latched inside every GROM,
|
||||||
and when the address is read from the register, they are delivered as the
|
and when the address is read from the register, they are delivered as the
|
||||||
most significant three address bits.
|
most significant three address bits.
|
||||||
|
|
||||||
All GROMs are wired in parallel, and only the circuits whose ID matches the
|
All GROMs are wired in parallel, and only the circuits whose ID matches the
|
||||||
prefix actually delivers the data to the outside. Apart from that, all
|
prefix actually delivers the data to the outside. Apart from that, all
|
||||||
GROMs perform the same internal operations. This means that each one of
|
GROMs perform the same internal operations. This means that each one of
|
||||||
them holds the same address value and delivers it on request.
|
them holds the same address value and delivers it on request.
|
||||||
|
|
||||||
Timing. GROMs have a CPU-bound operation phase and a non-CPU-bound operation
|
Timing. GROMs have a CPU-bound operation phase and a non-CPU-bound operation
|
||||||
phase. After being selected, the READY line is immediately lowered, and
|
phase. After being selected, the READY line is immediately lowered, and
|
||||||
it raises as soon as the data is ready for access. After that, a prefetch
|
it raises as soon as the data is ready for access. After that, a prefetch
|
||||||
is done to get the next data byte from the memory banks, advancing the
|
is done to get the next data byte from the memory banks, advancing the
|
||||||
address counter. This prefetch is also done when loading the address.
|
address counter. This prefetch is also done when loading the address.
|
||||||
Hence, reading the address register will always deliver a value increased
|
Hence, reading the address register will always deliver a value increased
|
||||||
by one.
|
by one.
|
||||||
|
|
||||||
[1] Michael L. Bunyard: Hardware Manual for the Texas Instruments 99/4A Home Computer, section 2.5
|
[1] Michael L. Bunyard: Hardware Manual for the Texas Instruments 99/4A Home Computer, section 2.5
|
||||||
|
|
||||||
Michael Zapf, August 2010
|
Michael Zapf, August 2010
|
||||||
January 2012: rewritten as class
|
January 2012: rewritten as class
|
||||||
|
|
||||||
@ -104,54 +104,54 @@
|
|||||||
Constructor.
|
Constructor.
|
||||||
*/
|
*/
|
||||||
tmc0430_device::tmc0430_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
tmc0430_device::tmc0430_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
: device_t(mconfig, TMC0430, "TMC0430 device (GROM)", tag, owner, clock, "grom", __FILE__),
|
: device_t(mconfig, TMC0430, "TMC0430 device (GROM)", tag, owner, clock, "grom", __FILE__),
|
||||||
m_gromready(*this),
|
m_gromready(*this),
|
||||||
m_current_clock_level(CLEAR_LINE),
|
m_current_clock_level(CLEAR_LINE),
|
||||||
m_current_ident(0),
|
m_current_ident(0),
|
||||||
m_phase(0),
|
m_phase(0),
|
||||||
m_address_mode(false),
|
m_address_mode(false),
|
||||||
m_read_mode(false),
|
m_read_mode(false),
|
||||||
m_selected(false),
|
m_selected(false),
|
||||||
m_address_lowbyte(false),
|
m_address_lowbyte(false),
|
||||||
m_regionname(nullptr),
|
m_regionname(nullptr),
|
||||||
m_ident(0),
|
m_ident(0),
|
||||||
m_address(0),
|
m_address(0),
|
||||||
m_buffer(0),
|
m_buffer(0),
|
||||||
m_memptr(nullptr)
|
m_memptr(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// Select lines. We have three lines for the direction, the mode, and
|
// Select lines. We have three lines for the direction, the mode, and
|
||||||
// the selection. You can call one function for each of them, but it is
|
// the selection. You can call one function for each of them, but it is
|
||||||
// recommended to use the combined set_lines function, in particular when
|
// recommended to use the combined set_lines function, in particular when
|
||||||
// there are lots of GROMs (see, for example, TI-99/8)
|
// there are lots of GROMs (see, for example, TI-99/8)
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Direction. When ASSERTed, GROM is set to be read by CPU.
|
Direction. When ASSERTed, GROM is set to be read by CPU.
|
||||||
*/
|
*/
|
||||||
WRITE_LINE_MEMBER( tmc0430_device::m_line )
|
WRITE_LINE_MEMBER( tmc0430_device::m_line )
|
||||||
{
|
{
|
||||||
m_read_mode = (state==ASSERT_LINE);
|
m_read_mode = (state==ASSERT_LINE);
|
||||||
if (TRACE_LINE) logerror("GROM %d dir %s\n", m_ident>>13, m_read_mode? "READ" : "WRITE");
|
if (TRACE_LINE) logerror("GROM %d dir %s\n", m_ident>>13, m_read_mode? "READ" : "WRITE");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mode. When ASSERTed, the address counter will be accessed (read or write).
|
Mode. When ASSERTed, the address counter will be accessed (read or write).
|
||||||
*/
|
*/
|
||||||
WRITE_LINE_MEMBER( tmc0430_device::mo_line )
|
WRITE_LINE_MEMBER( tmc0430_device::mo_line )
|
||||||
{
|
{
|
||||||
m_address_mode = (state==ASSERT_LINE);
|
m_address_mode = (state==ASSERT_LINE);
|
||||||
if (TRACE_LINE) logerror("GROM %d mode %s\n", m_ident>>13, m_address_mode? "ADDR" : "DATA");
|
if (TRACE_LINE) logerror("GROM %d mode %s\n", m_ident>>13, m_address_mode? "ADDR" : "DATA");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Select. When ASSERTed, the read/write operation is started.
|
Select. When ASSERTed, the read/write operation is started.
|
||||||
*/
|
*/
|
||||||
WRITE_LINE_MEMBER( tmc0430_device::gsq_line )
|
WRITE_LINE_MEMBER( tmc0430_device::gsq_line )
|
||||||
{
|
{
|
||||||
if (state==ASSERT_LINE && !m_selected) // check for edge
|
if (state==ASSERT_LINE && !m_selected) // check for edge
|
||||||
{
|
{
|
||||||
if (TRACE_READY) logerror("GROM %d selected, pulling down READY\n", m_ident>>13);
|
if (TRACE_READY) logerror("GROM %d selected, pulling down READY\n", m_ident>>13);
|
||||||
m_gromready(CLEAR_LINE);
|
m_gromready(CLEAR_LINE);
|
||||||
@ -161,20 +161,20 @@ WRITE_LINE_MEMBER( tmc0430_device::gsq_line )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Combined select lines. Avoids separate calls to the chip.
|
Combined select lines. Avoids separate calls to the chip.
|
||||||
Address:
|
Address:
|
||||||
0 -> MO=0, M=0
|
0 -> MO=0, M=0
|
||||||
1 -> MO=0, M=1
|
1 -> MO=0, M=1
|
||||||
2 -> MO=1, M=0
|
2 -> MO=1, M=0
|
||||||
3 -> MO=1, M=1
|
3 -> MO=1, M=1
|
||||||
Data: gsq line (ASSERT, CLEAR)
|
Data: gsq line (ASSERT, CLEAR)
|
||||||
*/
|
*/
|
||||||
WRITE8_MEMBER( tmc0430_device::set_lines )
|
WRITE8_MEMBER( tmc0430_device::set_lines )
|
||||||
{
|
{
|
||||||
m_read_mode = ((offset & GROM_M_LINE)!=0);
|
m_read_mode = ((offset & GROM_M_LINE)!=0);
|
||||||
m_address_mode = ((offset & GROM_MO_LINE)!=0);
|
m_address_mode = ((offset & GROM_MO_LINE)!=0);
|
||||||
|
|
||||||
if (data!=CLEAR_LINE && !m_selected) // check for edge
|
if (data!=CLEAR_LINE && !m_selected) // check for edge
|
||||||
{
|
{
|
||||||
if (TRACE_READY) logerror("GROM %d selected, pulling down READY\n", m_ident>>13);
|
if (TRACE_READY) logerror("GROM %d selected, pulling down READY\n", m_ident>>13);
|
||||||
m_gromready(CLEAR_LINE);
|
m_gromready(CLEAR_LINE);
|
||||||
@ -184,20 +184,20 @@ WRITE8_MEMBER( tmc0430_device::set_lines )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Clock in.
|
Clock in.
|
||||||
|
|
||||||
Note about the GREADY line:
|
Note about the GREADY line:
|
||||||
Inside the TI-99/4A console, the GREADY outputs of all GROMs are directly
|
Inside the TI-99/4A console, the GREADY outputs of all GROMs are directly
|
||||||
connected in parallel and pulled up. This implies that the GROMs are
|
connected in parallel and pulled up. This implies that the GROMs are
|
||||||
open-drain outputs pulling down. There are two options:
|
open-drain outputs pulling down. There are two options:
|
||||||
- Only the currently addressed GROM pulls down the line; all others keep
|
- Only the currently addressed GROM pulls down the line; all others keep
|
||||||
their output open.
|
their output open.
|
||||||
- All GROMs act strictly in parallel. In the case that some circuits are
|
- All GROMs act strictly in parallel. In the case that some circuits are
|
||||||
slightly out of sync, the GREADY line goes up when the last circuit releases
|
slightly out of sync, the GREADY line goes up when the last circuit releases
|
||||||
the line.
|
the line.
|
||||||
|
|
||||||
For the emulation we may assume that all GROMs at the same clock line
|
For the emulation we may assume that all GROMs at the same clock line
|
||||||
raise their outputs synchronously.
|
raise their outputs synchronously.
|
||||||
*/
|
*/
|
||||||
WRITE_LINE_MEMBER( tmc0430_device::gclock_in )
|
WRITE_LINE_MEMBER( tmc0430_device::gclock_in )
|
||||||
{
|
{
|
||||||
@ -212,29 +212,29 @@ WRITE_LINE_MEMBER( tmc0430_device::gclock_in )
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (TRACE_CLOCK) logerror("GROMCLK in, phase=%d, m_add=%d\n", m_phase, m_address);
|
if (TRACE_CLOCK) logerror("GROMCLK in, phase=%d, m_add=%d\n", m_phase, m_address);
|
||||||
|
|
||||||
switch (m_phase)
|
switch (m_phase)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// Get the next value into the buffer
|
// Get the next value into the buffer
|
||||||
// 000b b000 0000 0000
|
// 000b b000 0000 0000
|
||||||
baddr = m_address & 0x07ff;
|
baddr = m_address & 0x07ff;
|
||||||
bank = (m_address & 0x1800)>>11;
|
bank = (m_address & 0x1800)>>11;
|
||||||
|
|
||||||
// This is a theory how the behavior of the GROM can be explained
|
// This is a theory how the behavior of the GROM can be explained
|
||||||
// We don't have decapped GROMs (yet)
|
// We don't have decapped GROMs (yet)
|
||||||
m_buffer = 0;
|
m_buffer = 0;
|
||||||
if (bank == 0) m_buffer |= m_memptr[baddr];
|
if (bank == 0) m_buffer |= m_memptr[baddr];
|
||||||
if (bank & 1) m_buffer |= m_memptr[baddr | 0x0800];
|
if (bank & 1) m_buffer |= m_memptr[baddr | 0x0800];
|
||||||
if (bank & 2) m_buffer |= m_memptr[baddr | 0x1000];
|
if (bank & 2) m_buffer |= m_memptr[baddr | 0x1000];
|
||||||
|
|
||||||
if (TRACE_ADDRESS) logerror("G>%04x\n", m_address);
|
if (TRACE_ADDRESS) logerror("G>%04x\n", m_address);
|
||||||
if (TRACE_DETAIL) logerror("GROM %d preload %04x (bank %d) -> %02x\n", m_ident>>13, m_address, bank, m_buffer);
|
if (TRACE_DETAIL) logerror("GROM %d preload %04x (bank %d) -> %02x\n", m_ident>>13, m_address, bank, m_buffer);
|
||||||
m_phase = 3;
|
m_phase = 3;
|
||||||
break;
|
break;
|
||||||
case 2: // Do nothing if other ident
|
case 2: // Do nothing if other ident
|
||||||
m_phase = 3;
|
m_phase = 3;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
@ -245,7 +245,7 @@ WRITE_LINE_MEMBER( tmc0430_device::gclock_in )
|
|||||||
// In read mode, READY must have already been raised; in write mode, the ready line is still low
|
// In read mode, READY must have already been raised; in write mode, the ready line is still low
|
||||||
m_phase = m_read_mode? 0 : 7;
|
m_phase = m_read_mode? 0 : 7;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: // Starting here when the chip is selected
|
case 4: // Starting here when the chip is selected
|
||||||
m_phase = 5;
|
m_phase = 5;
|
||||||
break;
|
break;
|
||||||
@ -266,19 +266,19 @@ WRITE_LINE_MEMBER( tmc0430_device::gclock_in )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read operation. For MO=Address, delivers the address register (and destroys its contents).
|
Read operation. For MO=Address, delivers the address register (and destroys its contents).
|
||||||
For MO=Data, delivers the byte inside the buffer and prefetches the next one.
|
For MO=Data, delivers the byte inside the buffer and prefetches the next one.
|
||||||
*/
|
*/
|
||||||
READ8Z_MEMBER( tmc0430_device::readz )
|
READ8Z_MEMBER( tmc0430_device::readz )
|
||||||
{
|
{
|
||||||
if (!m_selected) return;
|
if (!m_selected) return;
|
||||||
|
|
||||||
if (m_address_mode)
|
if (m_address_mode)
|
||||||
{
|
{
|
||||||
// Address reading is destructive
|
// Address reading is destructive
|
||||||
*value = (m_address & 0xff00)>>8;
|
*value = (m_address & 0xff00)>>8;
|
||||||
UINT8 lsb = (m_address & 0x00ff);
|
UINT8 lsb = (m_address & 0x00ff);
|
||||||
m_address = (lsb << 8) | lsb; // see [1], section 2.5.3
|
m_address = (lsb << 8) | lsb; // see [1], section 2.5.3
|
||||||
if (TRACE_DETAIL) logerror("GROM %d return address %02x\n", m_ident>>13, *value);
|
if (TRACE_DETAIL) logerror("GROM %d return address %02x\n", m_ident>>13, *value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -289,7 +289,7 @@ READ8Z_MEMBER( tmc0430_device::readz )
|
|||||||
*value = m_buffer;
|
*value = m_buffer;
|
||||||
m_phase = 1;
|
m_phase = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_phase = 2;
|
m_phase = 2;
|
||||||
}
|
}
|
||||||
@ -298,13 +298,13 @@ READ8Z_MEMBER( tmc0430_device::readz )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Write operation. For MO=Address, shifts value in the address register
|
Write operation. For MO=Address, shifts value in the address register
|
||||||
by 8 bits and copies the new value into the low byte. After every two
|
by 8 bits and copies the new value into the low byte. After every two
|
||||||
write operations, prefetches the byte from the new location. For MO=Data,
|
write operations, prefetches the byte from the new location. For MO=Data,
|
||||||
do nothing, because GRAMs were never seen in the wild.
|
do nothing, because GRAMs were never seen in the wild.
|
||||||
|
|
||||||
This operation occurs in parallel to phase 4. The real GROM will pick up
|
This operation occurs in parallel to phase 4. The real GROM will pick up
|
||||||
the value from the data bus some phases later.
|
the value from the data bus some phases later.
|
||||||
*/
|
*/
|
||||||
WRITE8_MEMBER( tmc0430_device::write )
|
WRITE8_MEMBER( tmc0430_device::write )
|
||||||
{
|
{
|
||||||
@ -312,19 +312,19 @@ WRITE8_MEMBER( tmc0430_device::write )
|
|||||||
|
|
||||||
if (m_address_mode)
|
if (m_address_mode)
|
||||||
{
|
{
|
||||||
m_address = ((m_address << 8) | data); // [1], section 2.5.7
|
m_address = ((m_address << 8) | data); // [1], section 2.5.7
|
||||||
m_current_ident = m_address & 0xe000;
|
m_current_ident = m_address & 0xe000;
|
||||||
if (TRACE_DETAIL) logerror("GROM %d new address %04x (%s)\n", m_ident>>13, m_address, m_address_lowbyte? "complete" : "incomplete");
|
if (TRACE_DETAIL) logerror("GROM %d new address %04x (%s)\n", m_ident>>13, m_address, m_address_lowbyte? "complete" : "incomplete");
|
||||||
// Toggle the lowbyte flag
|
// Toggle the lowbyte flag
|
||||||
m_address_lowbyte = !m_address_lowbyte;
|
m_address_lowbyte = !m_address_lowbyte;
|
||||||
|
|
||||||
if (!m_address_lowbyte)
|
if (!m_address_lowbyte)
|
||||||
{
|
{
|
||||||
// Do a prefetch if addressed, else increase your address
|
// Do a prefetch if addressed, else increase your address
|
||||||
m_phase = (m_current_ident == m_ident)? 1 : 2;
|
m_phase = (m_current_ident == m_ident)? 1 : 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Check the duration of the access. In sum, both write accesses show correct timing,
|
// TODO: Check the duration of the access. In sum, both write accesses show correct timing,
|
||||||
// but in this implementation, the first one (!m_address_lowbyte) is slower (phase=4-5-6-7-0) while the
|
// but in this implementation, the first one (!m_address_lowbyte) is slower (phase=4-5-6-7-0) while the
|
||||||
// second is faster (phase=1-3-7-0 or 1-3-0)
|
// second is faster (phase=1-3-7-0 or 1-3-0)
|
||||||
|
@ -35,60 +35,60 @@ public:
|
|||||||
|
|
||||||
DECLARE_READ8Z_MEMBER(readz);
|
DECLARE_READ8Z_MEMBER(readz);
|
||||||
DECLARE_WRITE8_MEMBER(write);
|
DECLARE_WRITE8_MEMBER(write);
|
||||||
|
|
||||||
DECLARE_WRITE_LINE_MEMBER(m_line);
|
DECLARE_WRITE_LINE_MEMBER(m_line);
|
||||||
DECLARE_WRITE_LINE_MEMBER(mo_line);
|
DECLARE_WRITE_LINE_MEMBER(mo_line);
|
||||||
DECLARE_WRITE_LINE_MEMBER(gsq_line);
|
DECLARE_WRITE_LINE_MEMBER(gsq_line);
|
||||||
|
|
||||||
DECLARE_WRITE_LINE_MEMBER(gclock_in);
|
DECLARE_WRITE_LINE_MEMBER(gclock_in);
|
||||||
|
|
||||||
DECLARE_WRITE8_MEMBER( set_lines );
|
DECLARE_WRITE8_MEMBER( set_lines );
|
||||||
|
|
||||||
static void set_region_and_ident(device_t &device, const char *regionname, int offset, int ident)
|
static void set_region_and_ident(device_t &device, const char *regionname, int offset, int ident)
|
||||||
{
|
{
|
||||||
downcast<tmc0430_device &>(device).m_regionname = regionname;
|
downcast<tmc0430_device &>(device).m_regionname = regionname;
|
||||||
downcast<tmc0430_device &>(device).m_offset = offset;
|
downcast<tmc0430_device &>(device).m_offset = offset;
|
||||||
downcast<tmc0430_device &>(device).m_ident = ident<<13;
|
downcast<tmc0430_device &>(device).m_ident = ident<<13;
|
||||||
}
|
}
|
||||||
|
|
||||||
int debug_get_address();
|
int debug_get_address();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void device_start(void) override;
|
void device_start(void) override;
|
||||||
void device_reset(void) override;
|
void device_reset(void) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Ready callback. This line is usually connected to the READY pin of the CPU.
|
// Ready callback. This line is usually connected to the READY pin of the CPU.
|
||||||
devcb_write_line m_gromready;
|
devcb_write_line m_gromready;
|
||||||
|
|
||||||
// Clock line level
|
// Clock line level
|
||||||
line_state m_current_clock_level;
|
line_state m_current_clock_level;
|
||||||
|
|
||||||
// Currently active GROM ident
|
// Currently active GROM ident
|
||||||
int m_current_ident;
|
int m_current_ident;
|
||||||
|
|
||||||
// Phase of the state machine
|
// Phase of the state machine
|
||||||
int m_phase;
|
int m_phase;
|
||||||
|
|
||||||
// Address or data mode?
|
// Address or data mode?
|
||||||
bool m_address_mode;
|
bool m_address_mode;
|
||||||
|
|
||||||
// Reading or writing?
|
// Reading or writing?
|
||||||
bool m_read_mode;
|
bool m_read_mode;
|
||||||
|
|
||||||
// Selected?
|
// Selected?
|
||||||
bool m_selected;
|
bool m_selected;
|
||||||
|
|
||||||
// Toggle for address loading
|
// Toggle for address loading
|
||||||
bool m_address_lowbyte;
|
bool m_address_lowbyte;
|
||||||
|
|
||||||
// Region name
|
// Region name
|
||||||
const char* m_regionname;
|
const char* m_regionname;
|
||||||
|
|
||||||
// Offset in the region. We cannot rely on the ident because the GROMs
|
// Offset in the region. We cannot rely on the ident because the GROMs
|
||||||
// in the cartridges begin with ident 3, but start at the beginning of their region.
|
// in the cartridges begin with ident 3, but start at the beginning of their region.
|
||||||
int m_offset;
|
int m_offset;
|
||||||
|
|
||||||
// Identification of this GROM (0-7 <<13)
|
// Identification of this GROM (0-7 <<13)
|
||||||
int m_ident;
|
int m_ident;
|
||||||
|
|
||||||
@ -107,5 +107,5 @@ private:
|
|||||||
MCFG_DEVICE_ADD(_tag, TMC0430, 0) \
|
MCFG_DEVICE_ADD(_tag, TMC0430, 0) \
|
||||||
tmc0430_device::set_region_and_ident(*device, _region, _offset, _ident); \
|
tmc0430_device::set_region_and_ident(*device, _region, _offset, _ident); \
|
||||||
tmc0430_device::set_ready_wr_callback(*device, DEVCB_##_ready);
|
tmc0430_device::set_ready_wr_callback(*device, DEVCB_##_ready);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user