mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
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:
parent
66768b1039
commit
314b8c650a
@ -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)
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user