summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/drivers/pcfx.c
diff options
context:
space:
mode:
author Wilbert Pol <wilbert@jdg.info>2012-08-21 20:39:41 +0000
committer Wilbert Pol <wilbert@jdg.info>2012-08-21 20:39:41 +0000
commitc9eff96eecddde0eda302408f8b93132a1ea6832 (patch)
tree4225ff797082274456edfae626b8195589b2a59e /src/mess/drivers/pcfx.c
parentbfc765ae40f3bb8fc00027fd0770dcb3651840c5 (diff)
(MESS) pcfx.c: Started implementing the interrupt controller. The bios is now waiting to receive an irq from HuC6270-B (which is never gets). (nw)
Diffstat (limited to 'src/mess/drivers/pcfx.c')
-rw-r--r--src/mess/drivers/pcfx.c202
1 files changed, 197 insertions, 5 deletions
diff --git a/src/mess/drivers/pcfx.c b/src/mess/drivers/pcfx.c
index b9f4322acf8..313079a4125 100644
--- a/src/mess/drivers/pcfx.c
+++ b/src/mess/drivers/pcfx.c
@@ -17,11 +17,34 @@ class pcfx_state : public driver_device
{
public:
pcfx_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag) { }
+ : driver_device(mconfig, type, tag)
+ , m_maincpu(*this, "maincpu")
+ { }
+
+ required_device<cpu_device> m_maincpu;
virtual void machine_reset();
UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ // Interrupt controller (component unknown)
+ UINT16 m_irq_mask;
+ UINT16 m_irq_pending;
+ UINT8 m_irq_priority[8];
+
+ DECLARE_READ16_MEMBER( irq_read );
+ DECLARE_WRITE16_MEMBER( irq_write );
+ inline void check_irqs();
+ inline void set_irq_line(int line, int state);
+ DECLARE_WRITE_LINE_MEMBER( irq8_w );
+ DECLARE_WRITE_LINE_MEMBER( irq9_w );
+ DECLARE_WRITE_LINE_MEMBER( irq10_w );
+ DECLARE_WRITE_LINE_MEMBER( irq11_w );
+ DECLARE_WRITE_LINE_MEMBER( irq12_w );
+ DECLARE_WRITE_LINE_MEMBER( irq13_w );
+ DECLARE_WRITE_LINE_MEMBER( irq14_w );
+ DECLARE_WRITE_LINE_MEMBER( irq15_w );
+
};
@@ -44,7 +67,7 @@ static ADDRESS_MAP_START( pcfx_io, AS_IO, 32, pcfx_state )
AM_RANGE( 0x00000500, 0x000005FF ) AM_DEVREADWRITE8( "huc6270_b", huc6270_device, read, write, 0xff ) /* HuC6270-B */
AM_RANGE( 0x00000600, 0x000006FF ) AM_NOP /* HuC6272 */
AM_RANGE( 0x00000C80, 0x00000C83 ) AM_NOP
- AM_RANGE( 0x00000E00, 0x00000EFF ) AM_NOP
+ AM_RANGE( 0x00000E00, 0x00000EFF ) AM_READWRITE16( irq_read, irq_write, 0xffff ) /* Interrupt controller */
AM_RANGE( 0x00000F00, 0x00000FFF ) AM_NOP
AM_RANGE( 0x80500000, 0x805000FF ) AM_NOP /* HuC6273 */
ADDRESS_MAP_END
@@ -54,8 +77,172 @@ static INPUT_PORTS_START( pcfx )
INPUT_PORTS_END
-static WRITE_LINE_DEVICE_HANDLER( pcfx_irq_changed )
+READ16_MEMBER( pcfx_state::irq_read )
+{
+ UINT16 data = 0;
+
+ switch( offset )
+ {
+ // Interrupts pending
+ // Same bit order as mask
+ case 0x00/4:
+ data = m_irq_pending;
+ break;
+
+ // Interrupt mask
+ case 0x40/4:
+ data = m_irq_mask;
+ break;
+
+ // Interrupt priority 0
+ case 0x80/4:
+ data = m_irq_priority[4] | ( m_irq_priority[5] << 3 ) | ( m_irq_priority[6] << 6 ) | ( m_irq_priority[7] << 9 );
+ break;
+
+ // Interrupt priority 1
+ case 0xC0/4:
+ data = m_irq_priority[0] | ( m_irq_priority[1] << 3 ) | ( m_irq_priority[2] << 6 ) | ( m_irq_priority[3] << 9 );
+ break;
+ }
+
+ return data;
+}
+
+
+WRITE16_MEMBER( pcfx_state::irq_write )
+{
+ switch( offset )
+ {
+ // Interrupts pending
+ case 0x00/4:
+ logerror("irq_write: Attempt to write to irq pending register\n");
+ break;
+
+ // Interrupt mask
+ // --------x------- Mask interrupt level 8 (Unknown)
+ // ---------x------ Mask interrupt level 9 (Timer)
+ // ----------x----- Mask interrupt level 10 (Unknown)
+ // -----------x---- Mask interrupt level 11 (Pad)
+ // ------------x--- Mask interrupt level 12 (HuC6270-A)
+ // -------------x-- Mask interrupt level 13 (HuC6272)
+ // --------------x- Mask interrupt level 14 (HuC6270-B)
+ // ---------------x Mask interrupt level 15 (HuC6273)
+ // 0 - allow, 1 - ignore interrupt
+ case 0x40/4:
+ m_irq_mask = data;
+ check_irqs();
+ break;
+
+ // Interrupt priority 0
+ // ----xxx--------- Priority level interrupt 12
+ // -------xxx------ Priority level interrupt 13
+ // ----------xxx--- Priority level interrupt 14
+ // -------------xxx Priority level interrupt 15
+ case 0x80/4:
+ m_irq_priority[4] = ( data >> 0 ) & 0x07;
+ m_irq_priority[5] = ( data >> 3 ) & 0x07;
+ m_irq_priority[6] = ( data >> 6 ) & 0x07;
+ m_irq_priority[7] = ( data >> 9 ) & 0x07;
+ check_irqs();
+ break;
+
+ // Interrupt priority 1
+ // ----xxx--------- Priority level interrupt 8
+ // -------xxx------ Priority level interrupt 9
+ // ----------xxx--- Priority level interrupt 10
+ // -------------xxx Priority level interrupt 11
+ case 0xC0/4:
+ m_irq_priority[0] = ( data >> 0 ) & 0x07;
+ m_irq_priority[1] = ( data >> 3 ) & 0x07;
+ m_irq_priority[2] = ( data >> 6 ) & 0x07;
+ m_irq_priority[3] = ( data >> 9 ) & 0x07;
+ check_irqs();
+ break;
+ }
+}
+
+
+inline void pcfx_state::check_irqs()
+{
+ UINT16 active_irqs = m_irq_pending & ~m_irq_mask;
+ int highest_prio = -1;
+
+ for ( int i = 0; i < 8; i++ )
+ {
+ if ( active_irqs & 0x80 )
+ {
+ if ( m_irq_priority[i] >= highest_prio )
+ {
+ highest_prio = m_irq_priority[i];
+ }
+ }
+ active_irqs <<= 1;
+ }
+
+ if ( highest_prio >= 0 )
+ {
+ device_set_input_line( m_maincpu, 8 + highest_prio, ASSERT_LINE );
+ }
+ else
+ {
+ device_set_input_line( m_maincpu, 0, CLEAR_LINE );
+ }
+}
+
+
+inline void pcfx_state::set_irq_line(int line, int state)
+{
+ if ( state )
+ {
+printf("Setting irq line %d\n", line);
+ m_irq_pending |= ( 1 << ( 15 - line ) );
+ }
+ else
+ {
+printf("Clearing irq line %d\n", line);
+ m_irq_pending &= ~( 1 << ( 15 - line ) );
+ }
+ check_irqs();
+}
+
+WRITE_LINE_MEMBER( pcfx_state::irq8_w )
+{
+ set_irq_line(8, state);
+}
+
+WRITE_LINE_MEMBER( pcfx_state::irq9_w )
+{
+ set_irq_line(9, state);
+}
+
+WRITE_LINE_MEMBER( pcfx_state::irq10_w )
+{
+ set_irq_line(10, state);
+}
+
+WRITE_LINE_MEMBER( pcfx_state::irq11_w )
{
+ set_irq_line(11, state);
+}
+
+WRITE_LINE_MEMBER( pcfx_state::irq12_w )
+{
+ set_irq_line(12, state);
+}
+
+WRITE_LINE_MEMBER( pcfx_state::irq13_w )
+{
+ set_irq_line(13, state);
+}
+
+WRITE_LINE_MEMBER( pcfx_state::irq14_w )
+{
+ set_irq_line(14, state);
+}
+
+WRITE_LINE_MEMBER( pcfx_state::irq15_w )
+{
+ set_irq_line(15, state);
}
@@ -70,27 +257,32 @@ static const huc6261_interface pcfx_huc6261_config =
static const huc6270_interface pcfx_huc6270_a_config =
{
0x20000,
- DEVCB_LINE(pcfx_irq_changed),
+ DEVCB_DRIVER_LINE_MEMBER(pcfx_state, irq12_w)
};
static const huc6270_interface pcfx_huc6270_b_config =
{
0x20000,
- DEVCB_LINE(pcfx_irq_changed),
+ DEVCB_DRIVER_LINE_MEMBER(pcfx_state, irq14_w)
};
void pcfx_state::machine_reset()
{
membank( "bank1" )->set_base( memregion("user1")->base() );
+
+ m_irq_mask = 0xFF;
+ m_irq_pending = 0;
}
+
UINT32 pcfx_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
return 0;
}
+
static MACHINE_CONFIG_START( pcfx, pcfx_state )
MCFG_CPU_ADD( "maincpu", V810, XTAL_21_4772MHz )
MCFG_CPU_PROGRAM_MAP( pcfx_mem)