diff options
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 |
commit | c9eff96eecddde0eda302408f8b93132a1ea6832 (patch) | |
tree | 4225ff797082274456edfae626b8195589b2a59e /src/mess/drivers/pcfx.c | |
parent | bfc765ae40f3bb8fc00027fd0770dcb3651840c5 (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.c | 202 |
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) |