Make Osborne 1 behave more like the schematics

This commit is contained in:
Vas Crabb 2015-10-28 03:13:31 +11:00
parent dc02861e5c
commit 212b262e44
3 changed files with 51 additions and 75 deletions

View File

@ -10,28 +10,35 @@ Bank 1 simply consists of 64KB of RAM. The upper 4KB is used for the lower 8
bit of video RAM entries.
Bank 2 holds the BIOS ROM and I/O area. Only addresses 0000-3FFF are used
by bank 2. Bank 2 is divided as follows:
3000-3FFF Unused
by bank 2 (4000-FFFF mirrors bank 1). Bank 2 is divided as follows:
3000-3FFF Nominally unused but acts as mirror of 2000-2FFF
2C00-2C03 Video PIA
2A00-2A01 Serial interface
2900-2903 488 PIA
2400-2400 SCREEN-PAC (if present)
2201-2280 Keyboard
2100-2103 Floppy
1000-1FFF Unused
1000-1FFF Nominally unused but acts as read mirror of BIOS ROM
0000-0FFF BIOS ROM
The logic is actually quite sloppy, and will cause bus fighting under many
circumstances since it doesn't actually check all four bits, just that two
are in the desired state.
Bank 3 has the ninth bit needed to complete the full Video RAM. These bits
are stored at F000-FFFF. Only the highest bit is used.
On bootup bank 2 is active.
The actual banking is done through I/O ports 00-03.
00 - Have both bank 2 and bank 1 active. This seems to be the power up default.
01 - Only have bank 1 active.
02 - Have both bank 2 and bank 3 active. (Not 100% sure, also bank 1 from 4000-EFFF?)
03 - Have both bank 2 and bank 1 active.
Banking is controlled by writes to I/O space. Only two low address bits are
used, and the value on the data bus is completley ignored.
00 - Activate bank 2 (also triggered by CPU reset)
01 - Activate bank 1
02 - Set BIT 9 signal (map bank 3 into F000-FFFF)
03 - Clear BIT 9 signal (map bank 1/2 into F000-FFFF)
TODO:
- Implement serial port
- Verify frequency of the beep/audio alarm.
***************************************************************************/
@ -45,17 +52,16 @@ 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, 0x2FFF ) AM_READWRITE( osborne1_2000_r, osborne1_2000_w )
AM_RANGE( 0x3000, 0x3FFF ) AM_READ_BANK("bank3") AM_WRITE( osborne1_3000_w )
AM_RANGE( 0x2000, 0x3FFF ) AM_READWRITE( osborne1_2000_r, osborne1_2000_w )
AM_RANGE( 0x4000, 0xEFFF ) AM_RAM
AM_RANGE( 0xF000, 0xFFFF ) AM_READ_BANK("bank4") AM_WRITE( osborne1_videoram_w )
AM_RANGE( 0xF000, 0xFFFF ) AM_READ_BANK("bank3") AM_WRITE( osborne1_videoram_w )
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, 0x03 ) AM_WRITE( osborne1_bankswitch_w )
AM_RANGE( 0x00, 0xff ) AM_WRITE( osborne1_bankswitch_w )
ADDRESS_MAP_END

View File

@ -51,7 +51,6 @@ public:
m_bank1(*this, "bank1"),
m_bank2(*this, "bank2"),
m_bank3(*this, "bank3"),
m_bank4(*this, "bank4"),
m_region_maincpu(*this, "maincpu") { }
virtual void video_start();
@ -74,7 +73,6 @@ public:
DECLARE_WRITE8_MEMBER(osborne1_1000_w);
DECLARE_READ8_MEMBER(osborne1_2000_r);
DECLARE_WRITE8_MEMBER(osborne1_2000_w);
DECLARE_WRITE8_MEMBER(osborne1_3000_w);
DECLARE_WRITE8_MEMBER(osborne1_videoram_w);
DECLARE_WRITE8_MEMBER(osborne1_bankswitch_w);
DECLARE_WRITE_LINE_MEMBER(ieee_pia_irq_a_func);
@ -87,9 +85,7 @@ public:
DECLARE_DIRECT_UPDATE_MEMBER(osborne1_opbase);
bool m_bank2_enabled;
bool m_bank3_enabled;
UINT8 *m_bank4_ptr;
UINT8 *m_empty_4K;
UINT8 m_bit_9;
/* IRQ states */
bool m_pia_0_irq_state;
bool m_pia_1_irq_state;
@ -123,7 +119,6 @@ protected:
required_memory_bank m_bank1;
required_memory_bank m_bank2;
required_memory_bank m_bank3;
required_memory_bank m_bank4;
required_memory_region m_region_maincpu;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);

View File

@ -24,7 +24,7 @@ be written to RAM if RAM was switched in.
WRITE8_MEMBER( osborne1_state::osborne1_0000_w )
{
/* Check whether regular RAM is enabled */
if ( ! m_bank2_enabled || ( m_in_irq_handler && m_bankswitch == RAMMODE ) )
if ( !m_bank2_enabled || ( m_in_irq_handler && m_bankswitch == RAMMODE) )
{
m_ram->pointer()[ offset ] = data;
}
@ -34,7 +34,7 @@ WRITE8_MEMBER( osborne1_state::osborne1_0000_w )
WRITE8_MEMBER( osborne1_state::osborne1_1000_w )
{
/* Check whether regular RAM is enabled */
if ( ! m_bank2_enabled || ( m_in_irq_handler && m_bankswitch == RAMMODE ) )
if ( !m_bank2_enabled || ( m_in_irq_handler && m_bankswitch == RAMMODE) )
{
m_ram->pointer()[ 0x1000 + offset ] = data;
}
@ -46,13 +46,16 @@ READ8_MEMBER( osborne1_state::osborne1_2000_r )
UINT8 data = 0xFF;
/* Check whether regular RAM is enabled */
if ( ! m_bank2_enabled )
if ( !m_bank2_enabled )
{
data = m_ram->pointer()[ 0x2000 + offset ];
}
else
{
switch( offset & 0x0F00 )
// 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 );
@ -79,12 +82,12 @@ READ8_MEMBER( osborne1_state::osborne1_2000_r )
if (m_screen_pac) data &= 0xFB;
break;
case 0x900: /* IEEE488 PIA */
data = m_pia0->read(space, offset & 0x03 );
data = m_pia0->read(space, offset & 0x03);
break;
case 0xA00: /* Serial */
break;
case 0xC00: /* Video PIA */
data = m_pia1->read(space, offset & 0x03 );
data = m_pia1->read(space, offset & 0x03);
break;
}
}
@ -95,45 +98,26 @@ READ8_MEMBER( osborne1_state::osborne1_2000_r )
WRITE8_MEMBER( osborne1_state::osborne1_2000_w )
{
/* Check whether regular RAM is enabled */
if ( ! m_bank2_enabled )
if ( !m_bank2_enabled || (m_in_irq_handler && m_bankswitch == RAMMODE) )
{
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 & 0x0F00 )
if ( 0x100 == (offset & 0x900) ) /* Floppy */
m_fdc->write(space, offset & 0x03, data);
if ( 0x400 == (offset & 0xC00) ) /* SCREEN-PAC */
{
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;
}
}
}
WRITE8_MEMBER( osborne1_state::osborne1_3000_w )
{
/* Check whether regular RAM is enabled */
if ( ! m_bank2_enabled || ( m_in_irq_handler && m_bankswitch == RAMMODE ) )
{
m_ram->pointer()[ 0x3000 + offset ] = data;
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 */
m_pia1->write(space, offset & 0x03, data);
}
}
@ -141,49 +125,43 @@ WRITE8_MEMBER( osborne1_state::osborne1_3000_w )
WRITE8_MEMBER( osborne1_state::osborne1_videoram_w )
{
/* Check whether the video attribute section is enabled */
if ( m_bank3_enabled )
if ( m_bit_9 )
data |= 0x7F;
m_bank4_ptr[offset] = data;
reinterpret_cast<UINT8 *>(m_bank3->base())[offset] = data;
}
WRITE8_MEMBER( osborne1_state::osborne1_bankswitch_w )
{
switch( offset )
switch ( offset & 0x03 )
{
case 0x00:
m_bank2_enabled = 1;
m_bank3_enabled = 0;
m_bankswitch = 0x00;
break;
case 0x01:
m_bank2_enabled = 0;
m_bank3_enabled = 0;
m_bankswitch = 0x01;
break;
case 0x02:
m_bank2_enabled = 1;
m_bank3_enabled = 1;
m_bit_9 = 1;
break;
case 0x03:
m_bank2_enabled = 1;
m_bank3_enabled = 0;
m_bit_9 = 0;
break;
}
if ( m_bank2_enabled )
{
m_bank1->set_base(m_region_maincpu->base() );
m_bank2->set_base(m_empty_4K );
m_bank3->set_base(m_empty_4K );
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() + 0x3000 );
m_bank1->set_base(m_ram->pointer());
m_bank2->set_base(m_ram->pointer() + 0x1000);
}
m_bank4_ptr = m_ram->pointer() + ( ( m_bank3_enabled ) ? 0x10000 : 0xF000 );
m_bank4->set_base(m_bank4_ptr );
m_bankswitch = offset;
m_bank3->set_base(m_ram->pointer() + (m_bit_9 ? 0x10000 : 0xF000));
m_in_irq_handler = 0;
}
@ -394,7 +372,7 @@ TIMER_CALLBACK_MEMBER(osborne1_state::osborne1_video_callback)
}
}
if ( (ra==2) || (ra== 6) )
if ( (ra==2) || (ra==6) )
{
m_beep->set_state( m_beep_state );
}
@ -436,9 +414,6 @@ void osborne1_state::machine_reset()
DRIVER_INIT_MEMBER(osborne1_state,osborne1)
{
m_empty_4K = auto_alloc_array(machine(), UINT8, 0x1000 );
memset( m_empty_4K, 0xFF, 0x1000 );
/* Configure the 6850 ACIA */
// acia6850_config( 0, &osborne1_6850_config );
m_video_timer = timer_alloc(TIMER_VIDEO);