From 314b8c650ac8f2bcc9721ea267717b89a87a6dd0 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 29 Oct 2015 21:42:50 +1100 Subject: [PATCH] osborne1 improvements [Vas Crabb] * Bank low 16k according to schematics, passes memory test * Correct vectoring of IEEE488 interrupt * Implement RESET key (generates NMI, F12 by default) --- src/mame/drivers/osborne1.c | 73 +++--- src/mame/includes/osborne1.h | 109 ++++----- src/mame/machine/osborne1.c | 427 +++++++++++++---------------------- 3 files changed, 246 insertions(+), 363 deletions(-) diff --git a/src/mame/drivers/osborne1.c b/src/mame/drivers/osborne1.c index 9d5d5fcfb40..7b64b3ba7e0 100644 --- a/src/mame/drivers/osborne1.c +++ b/src/mame/drivers/osborne1.c @@ -37,10 +37,11 @@ used, and the value on the data bus is completley ignored. 02 - Set BIT 9 signal (map bank 3 into F000-FFFF) 03 - Clear BIT 9 signal (map bank 1/2 into F000-FFFF) +Selecting between bank 1 and bank 2 is also affected by M1 and IRQACK +conditions using a set of three flipflops. + TODO: - - Implement ROM/IO bank selection properly - Implement serial port - - Implement reset key (generates NMI and affects bank selection) - Verify frequency of the beep/audio alarm. ***************************************************************************/ @@ -52,29 +53,34 @@ TODO: static ADDRESS_MAP_START( osborne1_mem, AS_PROGRAM, 8, osborne1_state ) - AM_RANGE( 0x0000, 0x0FFF ) AM_READ_BANK("bank1") AM_WRITE( osborne1_0000_w ) - AM_RANGE( 0x1000, 0x1FFF ) AM_READ_BANK("bank2") AM_WRITE( osborne1_1000_w ) - AM_RANGE( 0x2000, 0x3FFF ) AM_READWRITE( osborne1_2000_r, osborne1_2000_w ) + AM_RANGE( 0x0000, 0x0FFF ) AM_READ_BANK("bank_0xxx") AM_WRITE(bank_0xxx_w) + AM_RANGE( 0x1000, 0x1FFF ) AM_READ_BANK("bank_1xxx") AM_WRITE(bank_1xxx_w) + AM_RANGE( 0x2000, 0x3FFF ) AM_READWRITE(bank_2xxx_3xxx_r, bank_2xxx_3xxx_w) AM_RANGE( 0x4000, 0xEFFF ) AM_RAM - AM_RANGE( 0xF000, 0xFFFF ) AM_READ_BANK("bank3") AM_WRITE( osborne1_videoram_w ) + AM_RANGE( 0xF000, 0xFFFF ) AM_READ_BANK("bank_fxxx") AM_WRITE(videoram_w) +ADDRESS_MAP_END + + +static ADDRESS_MAP_START( osborne1_op, AS_DECRYPTED_OPCODES, 8, osborne1_state ) + AM_RANGE( 0x0000, 0xFFFF ) AM_READ(opcode_r) ADDRESS_MAP_END static ADDRESS_MAP_START( osborne1_io, AS_IO, 8, osborne1_state ) ADDRESS_MAP_UNMAP_HIGH ADDRESS_MAP_GLOBAL_MASK(0xff) - AM_RANGE( 0x00, 0xff ) AM_WRITE( osborne1_bankswitch_w ) + AM_RANGE( 0x00, 0xff ) AM_WRITE(bankswitch_w) ADDRESS_MAP_END static INPUT_PORTS_START( osborne1 ) PORT_START("ROW0") - PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('[') PORT_CHAR(']') + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('[') PORT_CHAR(']') PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('\'') PORT_CHAR('"') PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) - PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t') PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) @@ -150,6 +156,16 @@ static INPUT_PORTS_START( osborne1 ) PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_START("RESET") + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RESET") PORT_CODE(KEYCODE_F12) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_START("CNF") PORT_CONFNAME(0x01, 0x00, "Video Output") PORT_CONFSETTING(0x00, "Standard") @@ -157,14 +173,6 @@ static INPUT_PORTS_START( osborne1 ) INPUT_PORTS_END -static const z80_daisy_config osborne1_daisy_chain[] = -{ -/* { osborne1_z80_reset, osborne1_z80_irq_state, osborne1_z80_irq_ack, osborne1_z80_irq_reti, 0 }, */ - { "osborne1_daisy" }, - { NULL } -}; - - /* * The Osborne-1 supports the following disc formats: * - Osborne single density: 40 tracks, 10 sectors per track, 256-byte sectors (100 KByte) @@ -176,37 +184,36 @@ static const z80_daisy_config osborne1_daisy_chain[] = */ static SLOT_INTERFACE_START( osborne1_floppies ) - SLOT_INTERFACE( "525sssd", FLOPPY_525_SSSD ) // Siemens FDD 100-5, custom Osborne electronics - SLOT_INTERFACE( "525ssdd", FLOPPY_525_SSDD ) // MPI 52(?), custom Osborne electronics + SLOT_INTERFACE("525sssd", FLOPPY_525_SSSD) // Siemens FDD 100-5, custom Osborne electronics + SLOT_INTERFACE("525ssdd", FLOPPY_525_SSDD) // MPI 52(?), custom Osborne electronics SLOT_INTERFACE_END /* F4 Character Displayer */ static const gfx_layout osborne1_charlayout = { - 8, 10, /* 8 x 10 characters */ - 128, /* 128 characters */ - 1, /* 1 bits per pixel */ - { 0 }, /* no bitplanes */ - /* x offsets */ + 8, 10, // 8 x 10 characters + 128, // 128 characters + 1, // 1 bits per pixel + { 0 }, // no bitplanes + // x offsets { 0, 1, 2, 3, 4, 5, 6, 7 }, - /* y offsets */ + // y offsets { 0*128*8, 1*128*8, 2*128*8, 3*128*8, 4*128*8, 5*128*8, 6*128*8, 7*128*8, 8*128*8, 9*128*8 }, - 8 /* every char takes 16 x 1 bytes */ + 8 // every char takes 16 x 1 bytes }; static GFXDECODE_START( osborne1 ) - GFXDECODE_ENTRY( "chargen", 0x0000, osborne1_charlayout, 0, 1 ) + GFXDECODE_ENTRY("chargen", 0x0000, osborne1_charlayout, 0, 1) GFXDECODE_END static MACHINE_CONFIG_START( osborne1, osborne1_state ) - MCFG_CPU_ADD( "maincpu", Z80, MAIN_CLOCK/4 ) - MCFG_CPU_PROGRAM_MAP( osborne1_mem) - MCFG_CPU_IO_MAP( osborne1_io) - MCFG_CPU_CONFIG( osborne1_daisy_chain ) - - MCFG_DEVICE_ADD( "osborne1_daisy", OSBORNE1_DAISY, 0 ) + MCFG_CPU_ADD("maincpu", Z80, MAIN_CLOCK/4) + MCFG_CPU_PROGRAM_MAP(osborne1_mem) + MCFG_CPU_DECRYPTED_OPCODES_MAP(osborne1_op) + MCFG_CPU_IO_MAP(osborne1_io) + MCFG_Z80_SET_IRQACK_CALLBACK(WRITELINE(osborne1_state, irqack_w)) MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_UPDATE_DRIVER(osborne1_state, screen_update) diff --git a/src/mame/includes/osborne1.h b/src/mame/includes/osborne1.h index 1dce651223f..1e69d0aded4 100644 --- a/src/mame/includes/osborne1.h +++ b/src/mame/includes/osborne1.h @@ -11,7 +11,6 @@ #include "emu.h" #include "cpu/z80/z80.h" -#include "cpu/z80/z80daisy.h" #include "sound/beep.h" #include "machine/6821pia.h" #include "machine/6850acia.h" @@ -39,18 +38,19 @@ public: m_ieee(*this, IEEE488_TAG), m_floppy0(*this, "mb8877:0:525ssdd"), m_floppy1(*this, "mb8877:1:525ssdd"), - m_row0(*this, "ROW0"), - m_row1(*this, "ROW1"), - m_row2(*this, "ROW2"), - m_row3(*this, "ROW3"), - m_row4(*this, "ROW4"), - m_row5(*this, "ROW5"), - m_row6(*this, "ROW6"), - m_row7(*this, "ROW7"), + m_keyb_row0(*this, "ROW0"), + m_keyb_row1(*this, "ROW1"), + m_keyb_row2(*this, "ROW2"), + m_keyb_row3(*this, "ROW3"), + m_keyb_row4(*this, "ROW4"), + m_keyb_row5(*this, "ROW5"), + m_keyb_row6(*this, "ROW6"), + m_keyb_row7(*this, "ROW7"), + m_btn_reset(*this, "RESET"), m_cnf(*this, "CNF"), - m_bank1(*this, "bank1"), - m_bank2(*this, "bank2"), - m_bank3(*this, "bank3"), + m_bank_0xxx(*this, "bank_0xxx"), + m_bank_1xxx(*this, "bank_1xxx"), + m_bank_fxxx(*this, "bank_fxxx"), m_region_maincpu(*this, "maincpu") { } virtual void video_start(); @@ -69,26 +69,24 @@ public: required_device m_floppy0; required_device m_floppy1; - DECLARE_WRITE8_MEMBER(osborne1_0000_w); - DECLARE_WRITE8_MEMBER(osborne1_1000_w); - DECLARE_READ8_MEMBER(osborne1_2000_r); - DECLARE_WRITE8_MEMBER(osborne1_2000_w); - DECLARE_WRITE8_MEMBER(osborne1_videoram_w); - DECLARE_WRITE8_MEMBER(osborne1_bankswitch_w); - DECLARE_WRITE_LINE_MEMBER(ieee_pia_irq_a_func); + DECLARE_WRITE8_MEMBER(bank_0xxx_w); + DECLARE_WRITE8_MEMBER(bank_1xxx_w); + DECLARE_READ8_MEMBER(bank_2xxx_3xxx_r); + DECLARE_WRITE8_MEMBER(bank_2xxx_3xxx_w); + DECLARE_WRITE8_MEMBER(videoram_w); + DECLARE_READ8_MEMBER(opcode_r); + DECLARE_WRITE8_MEMBER(bankswitch_w); + DECLARE_WRITE_LINE_MEMBER(irqack_w); + DECLARE_READ8_MEMBER(ieee_pia_pb_r); DECLARE_WRITE8_MEMBER(ieee_pia_pb_w); - DECLARE_WRITE_LINE_MEMBER(video_pia_out_cb2_dummy); + DECLARE_WRITE_LINE_MEMBER(ieee_pia_irq_a_func); + DECLARE_WRITE8_MEMBER(video_pia_port_a_w); DECLARE_WRITE8_MEMBER(video_pia_port_b_w); + DECLARE_WRITE_LINE_MEMBER(video_pia_out_cb2_dummy); DECLARE_WRITE_LINE_MEMBER(video_pia_irq_a_func); - DECLARE_DIRECT_UPDATE_MEMBER(osborne1_opbase); - bool m_bank2_enabled; - UINT8 m_bit_9; - /* IRQ states */ - bool m_pia_0_irq_state; - bool m_pia_1_irq_state; /* video related */ UINT8 m_screen_pac; UINT8 m_resolution; @@ -97,9 +95,6 @@ public: UINT8 m_new_start_y; emu_timer *m_video_timer; UINT8 *m_p_chargen; - /* bankswitch setting */ - UINT8 m_bankswitch; - bool m_in_irq_handler; bool m_beep_state; DECLARE_DRIVER_INIT(osborne1); virtual void machine_reset(); @@ -107,41 +102,35 @@ public: TIMER_CALLBACK_MEMBER(setup_osborne1); protected: - required_ioport m_row0; - required_ioport m_row1; - required_ioport m_row2; - required_ioport m_row3; - required_ioport m_row4; - required_ioport m_row5; - required_ioport m_row6; - required_ioport m_row7; + required_ioport m_keyb_row0; + required_ioport m_keyb_row1; + required_ioport m_keyb_row2; + required_ioport m_keyb_row3; + required_ioport m_keyb_row4; + required_ioport m_keyb_row5; + required_ioport m_keyb_row6; + required_ioport m_keyb_row7; + required_ioport m_btn_reset; + required_ioport m_cnf; - required_memory_bank m_bank1; - required_memory_bank m_bank2; - required_memory_bank m_bank3; + + required_memory_bank m_bank_0xxx; + required_memory_bank m_bank_1xxx; + required_memory_bank m_bank_fxxx; + required_memory_region m_region_maincpu; + // bank switch control bits + UINT8 m_ub4a_q; + UINT8 m_ub6a_q; + UINT8 m_rom_mode; + UINT8 m_bit_9; + + bool set_rom_mode(UINT8 value); + bool set_bit_9(UINT8 value); + void update_irq(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); }; - -// ======================> osborne1_daisy_device - -class osborne1_daisy_device : public device_t, - public device_z80daisy_interface -{ -public: - // construction/destruction - osborne1_daisy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - -private: - virtual void device_start(); - // z80daisy_interface overrides - virtual int z80daisy_irq_state(); - virtual int z80daisy_irq_ack(); - virtual void z80daisy_irq_reti(); -}; - -extern const device_type OSBORNE1_DAISY; - #endif /* OSBORNE1_H_ */ diff --git a/src/mame/machine/osborne1.c b/src/mame/machine/osborne1.c index ee24e3b5246..f9fc4b2f7fb 100644 --- a/src/mame/machine/osborne1.c +++ b/src/mame/machine/osborne1.c @@ -3,229 +3,150 @@ /*************************************************************************** There are three IRQ sources: -- IRQ0 +- IRQ0 = IRQ from the serial ACIA - IRQ1 = IRQA from the video PIA - IRQ2 = IRQA from the IEEE488 PIA -Interrupt handling on the Osborne-1 is a bit awkward. When an interrupt is -taken by the Z80 the ROMMODE is enabled on each fetch of an instruction -byte. During execution of an instruction the previous ROMMODE setting seems -to be used. Side effect of this is that when an interrupt is taken and the -stack pointer is pointing to 0000-3FFF then the return address will still -be written to RAM if RAM was switched in. - ***************************************************************************/ #include "includes/osborne1.h" -#define RAMMODE (0x01) - -WRITE8_MEMBER( osborne1_state::osborne1_0000_w ) +WRITE8_MEMBER( osborne1_state::bank_0xxx_w ) { - /* Check whether regular RAM is enabled */ - if ( !m_bank2_enabled || ( m_in_irq_handler && m_bankswitch == RAMMODE) ) - { - m_ram->pointer()[ offset ] = data; - } + if (!m_rom_mode) + m_ram->pointer()[offset] = data; } - -WRITE8_MEMBER( osborne1_state::osborne1_1000_w ) +WRITE8_MEMBER( osborne1_state::bank_1xxx_w ) { - /* Check whether regular RAM is enabled */ - if ( !m_bank2_enabled || ( m_in_irq_handler && m_bankswitch == RAMMODE) ) - { - m_ram->pointer()[ 0x1000 + offset ] = data; - } + if (!m_rom_mode) + m_ram->pointer()[0x1000 + offset] = data; } - -READ8_MEMBER( osborne1_state::osborne1_2000_r ) +READ8_MEMBER( osborne1_state::bank_2xxx_3xxx_r ) { + if (!m_rom_mode) + return m_ram->pointer()[0x2000 + offset]; + + // This isn't really accurate - bus fighting will occur for many values + // since each peripheral only checks two bits. We just return 0xFF for + // any undocumented address. UINT8 data = 0xFF; - - /* Check whether regular RAM is enabled */ - if ( !m_bank2_enabled ) + switch (offset & 0x0F00) { - data = m_ram->pointer()[ 0x2000 + offset ]; - } - else - { - // This isn't really accurate - bus fighting will occur for many values - // since each peripheral only checks two bits. We just return 0xFF for - // any undocumented address. - switch ( offset & 0x0F00 ) - { - case 0x100: /* Floppy */ - data = m_fdc->read( space, offset & 0x03 ); - break; - case 0x200: /* Keyboard */ - /* Row 0 */ - if ( offset & 0x01 ) data &= m_row0->read(); - /* Row 1 */ - if ( offset & 0x02 ) data &= m_row1->read(); - /* Row 2 */ - if ( offset & 0x04 ) data &= m_row3->read(); - /* Row 3 */ - if ( offset & 0x08 ) data &= m_row4->read(); - /* Row 4 */ - if ( offset & 0x10 ) data &= m_row5->read(); - /* Row 5 */ - if ( offset & 0x20 ) data &= m_row2->read(); - /* Row 6 */ - if ( offset & 0x40 ) data &= m_row6->read(); - /* Row 7 */ - if ( offset & 0x80 ) data &= m_row7->read(); - break; - case 0x400: /* SCREEN-PAC */ - if (m_screen_pac) data &= 0xFB; - break; - case 0x900: /* IEEE488 PIA */ - data = m_pia0->read(space, offset & 0x03); - break; - case 0xA00: /* Serial */ - break; - case 0xC00: /* Video PIA */ - data = m_pia1->read(space, offset & 0x03); - break; - } + case 0x100: /* Floppy */ + data = m_fdc->read(space, offset & 0x03); + break; + case 0x200: /* Keyboard */ + if (offset & 0x01) data &= m_keyb_row0->read(); + if (offset & 0x02) data &= m_keyb_row1->read(); + if (offset & 0x04) data &= m_keyb_row3->read(); + if (offset & 0x08) data &= m_keyb_row4->read(); + if (offset & 0x10) data &= m_keyb_row5->read(); + if (offset & 0x20) data &= m_keyb_row2->read(); + if (offset & 0x40) data &= m_keyb_row6->read(); + if (offset & 0x80) data &= m_keyb_row7->read(); + break; + case 0x400: /* SCREEN-PAC */ + if (m_screen_pac) data &= 0xFB; + break; + case 0x900: /* IEEE488 PIA */ + data = m_pia0->read(space, offset & 0x03); + break; + case 0xA00: /* Serial */ + break; + case 0xC00: /* Video PIA */ + data = m_pia1->read(space, offset & 0x03); + break; } return data; } - -WRITE8_MEMBER( osborne1_state::osborne1_2000_w ) +WRITE8_MEMBER( osborne1_state::bank_2xxx_3xxx_w ) { -#if 0 - /* Check whether regular RAM is enabled */ - if ( !m_bank2_enabled || (m_in_irq_handler && m_bankswitch == RAMMODE) ) + if (!m_rom_mode) { - m_ram->pointer()[ 0x2000 + offset ] = data; + m_ram->pointer()[0x2000 + offset] = data; } else { - /* Handle writes to the I/O area */ - if ( 0x100 == (offset & 0x900) ) /* Floppy */ + // Handle writes to the I/O area + if ((offset & 0x900) == 0x100) // Floppy m_fdc->write(space, offset & 0x03, data); - if ( 0x400 == (offset & 0xC00) ) /* SCREEN-PAC */ + if ((offset & 0x900) == 0x900) // IEEE488 PIA + m_pia0->write(space, offset & 0x03, data); + if ((offset & 0xA00) == 0xA00) // Serial + /* not implemented */; + if ((offset & 0xC00) == 0x400) // SCREEN-PAC { m_resolution = data & 0x01; m_hc_left = (data >> 1) & 0x01; } - if ( 0x900 == (offset & 0x900) ) /* IEEE488 PIA */ - m_pia0->write(space, offset & 0x03, data); - if ( 0xA00 == (offset & 0xA00) ) /* Serial */ - /* not implemented */; - if ( 0xC00 == (offset & 0xC00) ) /* Video PIA */ + if ((offset & 0xC00) == 0xC00) // Video PIA m_pia1->write(space, offset & 0x03, data); } -#else - // This code is a nasty hack that doesn't reflect hardware operation, - // but it gets us by while the bank selection implementation is inadequate - if ( ! m_bank2_enabled ) - { - m_ram->pointer()[ 0x2000 + offset ] = data; - } - else - { - if ( m_in_irq_handler && m_bankswitch == RAMMODE ) - { - m_ram->pointer()[ 0x2000 + offset ] = data; - } - /* Handle writes to the I/O area */ - switch( offset & 0x1F00 ) - { - case 0x100: /* Floppy */ - m_fdc->write(space, offset & 0x03, data); - break; - case 0x400: /* SCREEN-PAC */ - m_resolution = data & 0x01; - m_hc_left = (data >> 1) & 0x01; - break; - case 0x900: /* IEEE488 PIA */ - m_pia0->write(space, offset & 0x03, data ); - break; - case 0xA00: /* Serial */ - break; - case 0xC00: /* Video PIA */ - m_pia1->write(space, offset & 0x03, data ); - break; - } - } -#endif } - -WRITE8_MEMBER( osborne1_state::osborne1_videoram_w ) +WRITE8_MEMBER( osborne1_state::videoram_w ) { - /* Check whether the video attribute section is enabled */ - if ( m_bit_9 ) - data |= 0x7F; - - reinterpret_cast(m_bank3->base())[offset] = data; + // Attribute RAM is only one bit wide - low seven bits are discarded and read back high + if (m_bit_9) data |= 0x7F; + reinterpret_cast(m_bank_fxxx->base())[offset] = data; } - -WRITE8_MEMBER( osborne1_state::osborne1_bankswitch_w ) +READ8_MEMBER( osborne1_state::opcode_r ) { - switch ( offset & 0x03 ) + // Update the flipflops that control bank selection and NMI + UINT8 const new_ub6a_q = (m_btn_reset->read() & 0x80) ? 1 : 0; + if (!m_rom_mode) + { + set_rom_mode(m_ub4a_q ? 0 : 1); + m_ub4a_q = m_ub6a_q; + } + m_ub6a_q = new_ub6a_q; + m_maincpu->set_input_line(INPUT_LINE_NMI, m_ub6a_q ? CLEAR_LINE : ASSERT_LINE); + + // Now that's sorted out we can call the normal read handler + return m_maincpu->space(AS_PROGRAM).read_byte(offset); +} + +WRITE8_MEMBER( osborne1_state::bankswitch_w ) +{ + switch (offset & 0x03) { case 0x00: - m_bank2_enabled = 1; - m_bankswitch = 0x00; + if (set_rom_mode(1)) + m_ub4a_q = m_ub6a_q; break; case 0x01: - m_bank2_enabled = 0; - m_bankswitch = 0x01; + m_ub4a_q = 1; + m_ub6a_q = 1; + set_rom_mode(0); + m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); break; case 0x02: - m_bit_9 = 1; + set_bit_9(1); break; case 0x03: - m_bit_9 = 0; + set_bit_9(0); break; } - if ( m_bank2_enabled ) - { - m_bank1->set_base(m_region_maincpu->base()); - m_bank2->set_base(m_region_maincpu->base()); - } - else - { - m_bank1->set_base(m_ram->pointer()); - m_bank2->set_base(m_ram->pointer() + 0x1000); - } - m_bank3->set_base(m_ram->pointer() + (m_bit_9 ? 0x10000 : 0xF000)); - m_in_irq_handler = 0; } - -DIRECT_UPDATE_MEMBER(osborne1_state::osborne1_opbase) +WRITE_LINE_MEMBER( osborne1_state::irqack_w ) { - if ( ( address & 0xF000 ) == 0x2000 ) - { - if ( ! m_bank2_enabled ) - { - direct.explicit_configure(0x2000, 0x2fff, 0x0fff, m_ram->pointer() + 0x2000); - return ~0; - } - } - return address; -} - - -WRITE_LINE_MEMBER( osborne1_state::ieee_pia_irq_a_func ) -{ - m_pia_0_irq_state = state; - m_maincpu->set_input_line(0, ( m_pia_1_irq_state ) ? ASSERT_LINE : CLEAR_LINE); + // Update the flipflops that control bank selection and NMI + if (!m_rom_mode) set_rom_mode(m_ub4a_q ? 0 : 1); + m_ub4a_q = 0; + m_ub6a_q = (m_btn_reset->read() & 0x80) ? 1 : 0; + m_maincpu->set_input_line(INPUT_LINE_NMI, m_ub6a_q ? CLEAR_LINE : ASSERT_LINE); } READ8_MEMBER( osborne1_state::ieee_pia_pb_r ) { /* - bit description 0 @@ -236,9 +157,7 @@ READ8_MEMBER( osborne1_state::ieee_pia_pb_r ) 5 DAV 6 NDAC 7 NRFD - */ - UINT8 data = 0; data |= m_ieee->eoi_r() << 3; @@ -249,11 +168,9 @@ READ8_MEMBER( osborne1_state::ieee_pia_pb_r ) return data; } - WRITE8_MEMBER( osborne1_state::ieee_pia_pb_w ) { /* - bit description 0 @@ -264,9 +181,7 @@ WRITE8_MEMBER( osborne1_state::ieee_pia_pb_w ) 5 DAV 6 NDAC 7 NRFD - */ - m_ieee->eoi_w(BIT(data, 3)); m_ieee->atn_w(BIT(data, 4)); m_ieee->dav_w(BIT(data, 5)); @@ -274,12 +189,16 @@ WRITE8_MEMBER( osborne1_state::ieee_pia_pb_w ) m_ieee->nrfd_w(BIT(data, 7)); } +WRITE_LINE_MEMBER( osborne1_state::ieee_pia_irq_a_func ) +{ + update_irq(); +} + WRITE_LINE_MEMBER( osborne1_state::video_pia_out_cb2_dummy ) { } - WRITE8_MEMBER( osborne1_state::video_pia_port_a_w ) { m_fdc->dden_w(BIT(data, 0)); @@ -293,7 +212,6 @@ WRITE8_MEMBER( osborne1_state::video_pia_port_a_w ) //logerror("Video pia port a write: %02X, density set to %s\n", data, data & 1 ? "FM" : "MFM" ); } - WRITE8_MEMBER( osborne1_state::video_pia_port_b_w ) { m_new_start_y = data & 0x1F; @@ -317,11 +235,9 @@ WRITE8_MEMBER( osborne1_state::video_pia_port_b_w ) //logerror("Video pia port b write: %02X\n", data ); } - WRITE_LINE_MEMBER( osborne1_state::video_pia_irq_a_func ) { - m_pia_1_irq_state = state; - m_maincpu->set_input_line(0, ( m_pia_1_irq_state ) ? ASSERT_LINE : CLEAR_LINE); + update_irq(); } @@ -357,23 +273,18 @@ void osborne1_state::device_timer(emu_timer &timer, device_timer_id id, int para TIMER_CALLBACK_MEMBER(osborne1_state::osborne1_video_callback) { int const y = machine().first_screen()->vpos(); - UINT8 ra=0; + UINT8 ra = 0; - /* Check for start of frame */ - if ( y == 0 ) - { - /* Clear CA1 on video PIA */ + // Check for start/end of visible area and clear/set CA1 on video PIA + if (y == 0) m_pia1->ca1_w(0); - } - if ( y == 240 ) - { - /* Set CA1 on video PIA */ + else if (y == 240) m_pia1->ca1_w(1); - } - if ( y < 240 ) + + if (y < 240) { ra = y % 10; - /* Draw a line of the display */ + // Draw a line of the display bool const hires = m_screen_pac & m_resolution; UINT16 const row = (m_new_start_y + (y/10)) * 128 & 0xF80; UINT16 const col = (m_new_start_x & (hires ? 0x60 : 0x7F)) - ((hires && m_hc_left) ? 8 : 0); @@ -382,12 +293,12 @@ TIMER_CALLBACK_MEMBER(osborne1_state::osborne1_video_callback) for ( UINT16 x = 0; x < (hires ? 104 : 52); x++ ) { UINT16 offs = row | ((col + x) & 0x7F); - UINT8 const chr = m_ram->pointer()[ 0xF000 + offs ]; - UINT8 const dim = m_ram->pointer()[ 0x10000 + offs ] & 0x80; + UINT8 const chr = m_ram->pointer()[0xF000 + offs]; + UINT8 const dim = m_ram->pointer()[0x10000 + offs] & 0x80; - UINT8 const gfx = ((chr & 0x80) && (ra == 9)) ? 0xFF : m_p_chargen[ (ra << 7) | (chr & 0x7F) ]; + UINT8 const gfx = ((chr & 0x80) && (ra == 9)) ? 0xFF : m_p_chargen[(ra << 7) | (chr & 0x7F)]; - /* Display a scanline of a character */ + // Display a scanline of a character *p++ = BIT(gfx, 7) ? ( dim ? 2 : 1 ) : 0; if (!hires) { p[0] = p[-1]; p++; } *p++ = BIT(gfx, 6) ? ( dim ? 2 : 1 ) : 0; @@ -407,16 +318,16 @@ TIMER_CALLBACK_MEMBER(osborne1_state::osborne1_video_callback) } } - if ( (ra==2) || (ra==6) ) - { - m_beep->set_state( m_beep_state ); - } + if ((ra == 2) || (ra == 6)) + m_beep->set_state(m_beep_state); else - { - m_beep->set_state( 0 ); - } + m_beep->set_state(0); - m_video_timer->adjust(machine().first_screen()->time_until_pos(y + 1, 0 )); + // Check reset key if necessary - it affects NMI + if (!m_ub6a_q) + m_maincpu->set_input_line(INPUT_LINE_NMI, (m_btn_reset->read() && 0x80) ? CLEAR_LINE : ASSERT_LINE); + + m_video_timer->adjust(machine().first_screen()->time_until_pos(y + 1, 0)); } TIMER_CALLBACK_MEMBER(osborne1_state::setup_osborne1) @@ -428,22 +339,18 @@ TIMER_CALLBACK_MEMBER(osborne1_state::setup_osborne1) void osborne1_state::machine_reset() { - /* Initialize memory configuration */ - osborne1_bankswitch_w( m_maincpu->space(AS_IO), 0x00, 0 ); - - m_pia_0_irq_state = FALSE; - m_pia_1_irq_state = FALSE; - m_in_irq_handler = 0; + // Initialize memory configuration + m_rom_mode = 0; + m_bit_9 = 1; + set_rom_mode(1); + set_bit_9(0); m_screen_pac = 0 != (m_cnf->read() & 0x01); m_resolution = 0; m_hc_left = 0; m_p_chargen = memregion( "chargen" )->base(); - memset( m_ram->pointer() + 0x10000, 0xFF, 0x1000 ); - - address_space& space = m_maincpu->space(AS_PROGRAM); - space.set_direct_update_handler(direct_update_delegate(FUNC(osborne1_state::osborne1_opbase), this)); + memset(m_ram->pointer() + 0x10000, 0xFF, 0x1000); } @@ -452,7 +359,7 @@ DRIVER_INIT_MEMBER(osborne1_state,osborne1) /* Configure the 6850 ACIA */ // acia6850_config( 0, &osborne1_6850_config ); m_video_timer = timer_alloc(TIMER_VIDEO); - m_video_timer->adjust(machine().first_screen()->time_until_pos(1, 0 )); + m_video_timer->adjust(machine().first_screen()->time_until_pos(1, 0)); timer_set(attotime::zero, TIMER_SETUP); } @@ -463,77 +370,57 @@ void osborne1_state::video_start() machine().first_screen()->register_screen_bitmap(m_bitmap); } + UINT32 osborne1_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); return 0; } -/**************************************************************** - Osborne1 specific daisy chain code -****************************************************************/ -const device_type OSBORNE1_DAISY = &device_creator; - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// z80ctc_device - constructor -//------------------------------------------------- -osborne1_daisy_device::osborne1_daisy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, OSBORNE1_DAISY, "Osborne 1 daisy", tag, owner, clock, "osborne1_daisy", __FILE__), - device_z80daisy_interface(mconfig, *this) +bool osborne1_state::set_rom_mode(UINT8 value) { + if (value != m_rom_mode) + { + m_rom_mode = value; + if (m_rom_mode) + { + m_bank_0xxx->set_base(m_region_maincpu->base()); + m_bank_1xxx->set_base(m_region_maincpu->base()); + } + else + { + m_bank_0xxx->set_base(m_ram->pointer()); + m_bank_1xxx->set_base(m_ram->pointer() + 0x1000); + } + return true; + } + else + { + return false; + } } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void osborne1_daisy_device::device_start() +bool osborne1_state::set_bit_9(UINT8 value) { + if (value != m_bit_9) + { + m_bit_9 = value; + m_bank_fxxx->set_base(m_ram->pointer() + (m_bit_9 ? 0x10000 : 0xF000)); + return true; + } + else + { + return false; + } } -//************************************************************************** -// DAISY CHAIN INTERFACE -//************************************************************************** - -//------------------------------------------------- -// z80daisy_irq_state - return the overall IRQ -// state for this device -//------------------------------------------------- - -int osborne1_daisy_device::z80daisy_irq_state() -{ - osborne1_state *state = machine().driver_data(); - return ( state->m_pia_1_irq_state ? Z80_DAISY_INT : 0 ); -} - - -//------------------------------------------------- -// z80daisy_irq_ack - acknowledge an IRQ and -// return the appropriate vector -//------------------------------------------------- - -int osborne1_daisy_device::z80daisy_irq_ack() -{ - osborne1_state *state = machine().driver_data(); - /* Enable ROM and I/O when IRQ is acknowledged */ - UINT8 old_bankswitch = state->m_bankswitch; - - state->osborne1_bankswitch_w( state->m_maincpu->space(AS_IO), 0, 0 ); - state->m_bankswitch = old_bankswitch; - state->m_in_irq_handler = 1; - return 0xF8; -} - -//------------------------------------------------- -// z80daisy_irq_reti - clear the interrupt -// pending state to allow other interrupts through -//------------------------------------------------- - -void osborne1_daisy_device::z80daisy_irq_reti() +void osborne1_state::update_irq() { + if (m_pia0->irq_a_state()) + m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xF0); + else if (m_pia1->irq_a_state()) + m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xF8); + else + m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, CLEAR_LINE, 0xFE); }