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)
This commit is contained in:
Vas Crabb 2015-10-29 21:42:50 +11:00
parent 66768b1039
commit 314b8c650a
3 changed files with 246 additions and 363 deletions

View File

@ -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)

View File

@ -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<floppy_image_device> m_floppy0;
required_device<floppy_image_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_ */

View File

@ -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<UINT8 *>(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<UINT8 *>(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<osborne1_daisy_device>;
//**************************************************************************
// 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<osborne1_state>();
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<osborne1_state>();
/* 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);
}