mirror of
https://github.com/holub/mame
synced 2025-06-30 16:00:01 +03:00
osborne1.cpp:
* Move drawing to scanline update function and get rid of intermediate bitmap * Connect VBLANK input to PIA in machine configuration * Use the screen parameters set by the BIOS in machine configuration for osborne1nv * Turned SCREEN-PAC variant into a separate machine as it's a major hardware modification * Got back some performance by adding a memory access cache
This commit is contained in:
parent
9f2b31a9d8
commit
be7476e81b
@ -109,6 +109,13 @@ void osborne1_state::osborne1_mem(address_map &map)
|
||||
map(0xF000, 0xFFFF).bankr(m_bank_fxxx).w(FUNC(osborne1_state::videoram_w));
|
||||
}
|
||||
|
||||
void osborne1sp_state::osborne1sp_mem(address_map &map)
|
||||
{
|
||||
osborne1_mem(map);
|
||||
|
||||
map(0x2000, 0x3FFF).rw(FUNC(osborne1sp_state::bank_2xxx_3xxx_r), FUNC(osborne1sp_state::bank_2xxx_3xxx_w));
|
||||
}
|
||||
|
||||
|
||||
void osborne1_state::osborne1_op(address_map &map)
|
||||
{
|
||||
@ -228,15 +235,12 @@ static INPUT_PORTS_START( osborne1 )
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
|
||||
PORT_START("CNF")
|
||||
PORT_BIT(0xF8, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
PORT_CONFNAME(0x06, 0x00, "Serial Speed")
|
||||
PORT_BIT(0xFC, IP_ACTIVE_LOW, IPT_UNUSED)
|
||||
PORT_CONFNAME(0x03, 0x00, "Serial Speed")
|
||||
PORT_CONFSETTING(0x00, "300/1200")
|
||||
PORT_CONFSETTING(0x02, "600/2400")
|
||||
PORT_CONFSETTING(0x04, "1200/4800")
|
||||
PORT_CONFSETTING(0x06, "2400/9600")
|
||||
PORT_CONFNAME(0x01, 0x00, "Video Output")
|
||||
PORT_CONFSETTING(0x00, "Standard")
|
||||
PORT_CONFSETTING(0x01, "SCREEN-PAC")
|
||||
PORT_CONFSETTING(0x01, "600/2400")
|
||||
PORT_CONFSETTING(0x02, "1200/4800")
|
||||
PORT_CONFSETTING(0x03, "2400/9600")
|
||||
INPUT_PORTS_END
|
||||
|
||||
INPUT_PORTS_START( osborne1nv )
|
||||
@ -283,7 +287,7 @@ static GFXDECODE_START( gfx_osborne1 )
|
||||
GFXDECODE_END
|
||||
|
||||
|
||||
void osborne1_state::osborne1(machine_config &config)
|
||||
void osborne1_state::osborne1_base(machine_config &config)
|
||||
{
|
||||
Z80(config, m_maincpu, MAIN_CLOCK/4);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &osborne1_state::osborne1_mem);
|
||||
@ -292,9 +296,6 @@ void osborne1_state::osborne1(machine_config &config)
|
||||
m_maincpu->irqack_cb().set(FUNC(osborne1_state::irqack_w));
|
||||
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER, rgb_t::green());
|
||||
m_screen->set_screen_update(FUNC(osborne1_state::screen_update));
|
||||
m_screen->set_raw(MAIN_CLOCK, 1024, 0, 104*8, 260, 0, 24*10);
|
||||
m_screen->set_palette("palette");
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, "palette", gfx_osborne1);
|
||||
PALETTE(config, "palette", palette_device::MONOCHROME_HIGHLIGHT);
|
||||
@ -343,15 +344,41 @@ void osborne1_state::osborne1(machine_config &config)
|
||||
SOFTWARE_LIST(config, "flop_list").set_original("osborne1");
|
||||
}
|
||||
|
||||
void osborne1_state::osborne1(machine_config &config)
|
||||
{
|
||||
osborne1_base(config);
|
||||
|
||||
m_screen->set_screen_update(FUNC(osborne1_state::screen_update));
|
||||
m_screen->set_raw(MAIN_CLOCK / 2, 512, 0, 52 * 8, 260, 0, 24 * 10);
|
||||
m_screen->screen_vblank().set(m_pia1, FUNC(pia6821_device::ca1_w));
|
||||
m_screen->set_palette("palette");
|
||||
m_screen->set_video_attributes(VIDEO_UPDATE_SCANLINE | VIDEO_ALWAYS_UPDATE);
|
||||
}
|
||||
|
||||
void osborne1sp_state::osborne1sp(machine_config &config)
|
||||
{
|
||||
osborne1_base(config);
|
||||
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &osborne1sp_state::osborne1sp_mem);
|
||||
|
||||
m_screen->set_screen_update(FUNC(osborne1sp_state::screen_update));
|
||||
m_screen->set_raw(MAIN_CLOCK, 1024, 0, 104 * 8, 260, 0, 24 * 10);
|
||||
m_screen->screen_vblank().set(m_pia1, FUNC(pia6821_device::ca1_w));
|
||||
m_screen->set_palette("palette");
|
||||
m_screen->set_video_attributes(VIDEO_UPDATE_SCANLINE | VIDEO_ALWAYS_UPDATE);
|
||||
}
|
||||
|
||||
void osborne1nv_state::osborne1nv(machine_config &config)
|
||||
{
|
||||
osborne1(config);
|
||||
osborne1_base(config);
|
||||
|
||||
m_maincpu->set_addrmap(AS_IO, &osborne1nv_state::osborne1nv_io);
|
||||
|
||||
m_screen->set_no_palette();
|
||||
m_screen->set_screen_update("crtc", FUNC(mc6845_device::screen_update));
|
||||
m_screen->set_raw(12.288_MHz_XTAL, (96 + 1) * 8, 0, 80 * 8, ((25 + 1) * 10) + 4, 0, 24 * 10);
|
||||
m_screen->screen_vblank().set(m_pia1, FUNC(pia6821_device::ca1_w)); // FIXME: AFAICT the PIA gets this from the (vestigial) onboard video circuitry
|
||||
|
||||
sy6545_1_device &crtc(SY6545_1(config, "crtc", XTAL(12'288'000)/8));
|
||||
sy6545_1_device &crtc(SY6545_1(config, "crtc", 12.288_MHz_XTAL / 8));
|
||||
crtc.set_screen(m_screen);
|
||||
crtc.set_show_border_area(false);
|
||||
crtc.set_char_width(8);
|
||||
@ -389,6 +416,8 @@ ROM_START( osborne1 )
|
||||
ROMX_LOAD( "7a3007-00.ud15", 0x0000, 0x800, CRC(6c1eab0d) SHA1(b04459d377a70abc9155a5486003cb795342c801), ROM_BIOS(6) )
|
||||
ROM_END
|
||||
|
||||
#define rom_osborne1sp rom_osborne1
|
||||
|
||||
ROM_START( osborne1nv )
|
||||
ROM_REGION(0x1000, "maincpu", 0)
|
||||
ROM_LOAD( "monrom-rev1.51-12.ud11", 0x0000, 0x1000, CRC(298da402) SHA1(7fedd070936ccfe98f96d6e0ac71689666da79cb) )
|
||||
@ -400,6 +429,7 @@ ROM_START( osborne1nv )
|
||||
ROM_LOAD( "character_generator_6-29-84.14", 0x0000, 0x800, CRC(6c1eab0d) SHA1(b04459d377a70abc9155a5486003cb795342c801) )
|
||||
ROM_END
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1981, osborne1, 0, 0, osborne1, osborne1, osborne1_state, init_osborne1, "Osborne", "Osborne-1", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1984, osborne1nv, osborne1, 0, osborne1nv, osborne1nv, osborne1nv_state, init_osborne1, "Osborne/Nuevo", "Osborne-1 (Nuevo Video)", MACHINE_SUPPORTS_SAVE )
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1981, osborne1, 0, 0, osborne1, osborne1, osborne1_state, empty_init, "Osborne", "Osborne-1", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1983, osborne1sp, osborne1, 0, osborne1sp, osborne1, osborne1sp_state, empty_init, "Osborne", "Osborne-1 with SCREEN-PAC", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1984, osborne1nv, osborne1, 0, osborne1nv, osborne1nv, osborne1nv_state, empty_init, "Osborne/Nuevo", "Osborne-1 (Nuevo Video)", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -5,7 +5,6 @@
|
||||
* includes/osborne1.h
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef MAME_INCLUDES_OSBORNE1_H
|
||||
#define MAME_INCLUDES_OSBORNE1_H
|
||||
|
||||
@ -39,10 +38,10 @@ public:
|
||||
m_ram(*this, RAM_TAG),
|
||||
m_screen(*this, "screen"),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_speaker(*this, "speaker"),
|
||||
m_pia0(*this, "pia_0"),
|
||||
m_pia1(*this, "pia_1"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_speaker(*this, "speaker"),
|
||||
m_acia(*this, "acia"),
|
||||
m_fdc(*this, "mb8877"),
|
||||
m_ieee(*this, IEEE488_TAG),
|
||||
@ -58,27 +57,27 @@ public:
|
||||
m_p_chargen(*this, "chargen"),
|
||||
m_video_timer(nullptr),
|
||||
m_tilemap(nullptr),
|
||||
m_acia_rxc_txc_timer(nullptr)
|
||||
m_acia_rxc_txc_timer(nullptr),
|
||||
m_mem_cache(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void osborne1(machine_config &config);
|
||||
|
||||
void init_osborne1();
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(reset_key);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
void osborne1_base(machine_config &config);
|
||||
|
||||
void osborne1_mem(address_map &map);
|
||||
void osborne1_op(address_map &map);
|
||||
void osborne1_io(address_map &map);
|
||||
void osborne1nv_io(address_map &map);
|
||||
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<z80_device> m_maincpu;
|
||||
|
||||
private:
|
||||
DECLARE_WRITE8_MEMBER(bank_0xxx_w);
|
||||
DECLARE_WRITE8_MEMBER(bank_1xxx_w);
|
||||
DECLARE_READ8_MEMBER(bank_2xxx_3xxx_r);
|
||||
@ -88,6 +87,18 @@ private:
|
||||
DECLARE_WRITE8_MEMBER(bankswitch_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(irqack_w);
|
||||
|
||||
bool rom_mode() const { return 0 != m_rom_mode; }
|
||||
u8 scroll_x() const { return m_scroll_x; }
|
||||
|
||||
template <int Width, unsigned Scale> void draw_rows(uint16_t col, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<z80_device> m_maincpu;
|
||||
required_device<pia6821_device> m_pia0;
|
||||
required_device<pia6821_device> m_pia1;
|
||||
|
||||
private:
|
||||
DECLARE_READ8_MEMBER(ieee_pia_pb_r);
|
||||
DECLARE_WRITE8_MEMBER(ieee_pia_pb_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ieee_pia_irq_a_func);
|
||||
@ -103,18 +114,12 @@ private:
|
||||
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<speaker_sound_device> m_speaker;
|
||||
required_device<pia6821_device> m_pia0;
|
||||
required_device<pia6821_device> m_pia1;
|
||||
required_device<acia6850_device> m_acia;
|
||||
required_device<mb8877_device> m_fdc;
|
||||
required_device<ieee488_device> m_ieee;
|
||||
required_device<floppy_connector> m_floppy0;
|
||||
required_device<floppy_connector> m_floppy1;
|
||||
|
||||
void osborne1_mem(address_map &map);
|
||||
void osborne1_op(address_map &map);
|
||||
void osborne1_io(address_map &map);
|
||||
|
||||
TIMER_CALLBACK_MEMBER(video_callback);
|
||||
TIMER_CALLBACK_MEMBER(acia_rxc_txc_callback);
|
||||
|
||||
@ -140,7 +145,6 @@ private:
|
||||
required_region_ptr<u8> m_p_chargen;
|
||||
|
||||
// configuration (reloaded on reset)
|
||||
u8 m_screen_pac;
|
||||
u8 m_acia_rxc_txc_div;
|
||||
u8 m_acia_rxc_txc_p_low;
|
||||
u8 m_acia_rxc_txc_p_high;
|
||||
@ -156,17 +160,42 @@ private:
|
||||
u8 m_scroll_y;
|
||||
u8 m_beep_state;
|
||||
emu_timer *m_video_timer;
|
||||
bitmap_ind16 m_bitmap;
|
||||
tilemap_t *m_tilemap;
|
||||
|
||||
// SCREEN-PAC registers
|
||||
u8 m_resolution;
|
||||
u8 m_hc_left;
|
||||
|
||||
// serial state
|
||||
u8 m_acia_irq_state;
|
||||
u8 m_acia_rxc_txc_state;
|
||||
emu_timer *m_acia_rxc_txc_timer;
|
||||
|
||||
memory_access_cache<0, 0, ENDIANNESS_LITTLE> *m_mem_cache;
|
||||
};
|
||||
|
||||
|
||||
class osborne1sp_state : public osborne1_state
|
||||
{
|
||||
public:
|
||||
osborne1sp_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
osborne1_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
|
||||
void osborne1sp(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void osborne1sp_mem(address_map &map);
|
||||
|
||||
DECLARE_READ8_MEMBER(bank_2xxx_3xxx_r);
|
||||
DECLARE_WRITE8_MEMBER(bank_2xxx_3xxx_w);
|
||||
|
||||
private:
|
||||
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
// SCREEN-PAC registers
|
||||
u8 m_resolution;
|
||||
u8 m_hc_left;
|
||||
};
|
||||
|
||||
|
||||
|
@ -15,19 +15,19 @@ There are three IRQ sources:
|
||||
|
||||
WRITE8_MEMBER( osborne1_state::bank_0xxx_w )
|
||||
{
|
||||
if (!m_rom_mode)
|
||||
if (!rom_mode())
|
||||
m_ram->pointer()[offset] = data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( osborne1_state::bank_1xxx_w )
|
||||
{
|
||||
if (!m_rom_mode)
|
||||
if (!rom_mode())
|
||||
m_ram->pointer()[0x1000 + offset] = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER( osborne1_state::bank_2xxx_3xxx_r )
|
||||
{
|
||||
if (!m_rom_mode)
|
||||
if (!rom_mode())
|
||||
return m_ram->pointer()[0x2000 + offset];
|
||||
|
||||
// Since each peripheral only checks two bits, many addresses will
|
||||
@ -53,10 +53,6 @@ READ8_MEMBER( osborne1_state::bank_2xxx_3xxx_r )
|
||||
{
|
||||
data &= m_acia->read(offset & 0x01);
|
||||
}
|
||||
if ((offset & 0xC00) == 0x400) // SCREEN-PAC
|
||||
{
|
||||
if (m_screen_pac) data &= 0xFB;
|
||||
}
|
||||
if ((offset & 0xC00) == 0xC00) // Video PIA
|
||||
data &= m_pia1->read(offset & 0x03);
|
||||
return data;
|
||||
@ -64,7 +60,7 @@ READ8_MEMBER( osborne1_state::bank_2xxx_3xxx_r )
|
||||
|
||||
WRITE8_MEMBER( osborne1_state::bank_2xxx_3xxx_w )
|
||||
{
|
||||
if (!m_rom_mode)
|
||||
if (!rom_mode())
|
||||
{
|
||||
m_ram->pointer()[0x2000 + offset] = data;
|
||||
}
|
||||
@ -79,16 +75,38 @@ WRITE8_MEMBER( osborne1_state::bank_2xxx_3xxx_w )
|
||||
{
|
||||
m_acia->write(offset & 0x01, data);
|
||||
}
|
||||
if ((offset & 0xC00) == 0x400) // SCREEN-PAC
|
||||
{
|
||||
m_resolution = data & 0x01;
|
||||
m_hc_left = (data & 0x02) ? 0 : 1;
|
||||
}
|
||||
if ((offset & 0xC00) == 0xC00) // Video PIA
|
||||
m_pia1->write(offset & 0x03, data);
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER( osborne1sp_state::bank_2xxx_3xxx_r )
|
||||
{
|
||||
uint8_t data = osborne1_state::bank_2xxx_3xxx_r(space, offset, mem_mask);
|
||||
if (!rom_mode())
|
||||
return data;
|
||||
|
||||
if ((offset & 0xC00) == 0x400) // SCREEN-PAC
|
||||
{
|
||||
data &= 0xFB;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( osborne1sp_state::bank_2xxx_3xxx_w )
|
||||
{
|
||||
osborne1_state::bank_2xxx_3xxx_w(space, offset, data, mem_mask);
|
||||
|
||||
if (rom_mode())
|
||||
{
|
||||
if ((offset & 0xC00) == 0x400) // SCREEN-PAC
|
||||
{
|
||||
m_resolution = BIT(data, 0);
|
||||
m_hc_left = BIT(~data, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( osborne1_state::videoram_w )
|
||||
{
|
||||
// Attribute RAM is only one bit wide - low seven bits are discarded and read back high
|
||||
@ -105,7 +123,7 @@ READ8_MEMBER( osborne1_state::opcode_r )
|
||||
{
|
||||
// Update the flipflops that control bank selection and NMI
|
||||
uint8_t const new_ub6a_q = (m_btn_reset->read() & 0x80) ? 1 : 0;
|
||||
if (!m_rom_mode)
|
||||
if (!rom_mode())
|
||||
{
|
||||
set_rom_mode(m_ub4a_q ? 0 : 1);
|
||||
m_ub4a_q = m_ub6a_q;
|
||||
@ -115,7 +133,7 @@ READ8_MEMBER( osborne1_state::opcode_r )
|
||||
}
|
||||
|
||||
// Now that's sorted out we can call the normal read handler
|
||||
return m_maincpu->space(AS_PROGRAM).read_byte(offset);
|
||||
return m_mem_cache->read_byte(offset);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( osborne1_state::bankswitch_w )
|
||||
@ -144,7 +162,8 @@ WRITE8_MEMBER( osborne1_state::bankswitch_w )
|
||||
WRITE_LINE_MEMBER( osborne1_state::irqack_w )
|
||||
{
|
||||
// Update the flipflops that control bank selection and NMI
|
||||
if (!m_rom_mode) set_rom_mode(m_ub4a_q ? 0 : 1);
|
||||
if (!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);
|
||||
@ -254,7 +273,7 @@ INPUT_CHANGED_MEMBER( osborne1_state::reset_key )
|
||||
}
|
||||
|
||||
|
||||
void osborne1_state::init_osborne1()
|
||||
void osborne1_state::machine_start()
|
||||
{
|
||||
m_bank_0xxx->configure_entries(0, 1, m_ram->pointer(), 0);
|
||||
m_bank_0xxx->configure_entries(1, 1, m_region_maincpu->base(), 0);
|
||||
@ -271,7 +290,8 @@ void osborne1_state::init_osborne1()
|
||||
|
||||
m_acia_rxc_txc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(osborne1_state::acia_rxc_txc_callback), this));
|
||||
|
||||
save_item(NAME(m_screen_pac));
|
||||
m_mem_cache = m_maincpu->space(AS_PROGRAM).cache<0, 0, ENDIANNESS_LITTLE>();
|
||||
|
||||
save_item(NAME(m_acia_rxc_txc_div));
|
||||
save_item(NAME(m_acia_rxc_txc_p_low));
|
||||
save_item(NAME(m_acia_rxc_txc_p_high));
|
||||
@ -285,9 +305,6 @@ void osborne1_state::init_osborne1()
|
||||
save_item(NAME(m_scroll_y));
|
||||
save_item(NAME(m_beep_state));
|
||||
|
||||
save_item(NAME(m_resolution));
|
||||
save_item(NAME(m_hc_left));
|
||||
|
||||
save_item(NAME(m_acia_irq_state));
|
||||
save_item(NAME(m_acia_rxc_txc_state));
|
||||
}
|
||||
@ -295,25 +312,24 @@ void osborne1_state::init_osborne1()
|
||||
void osborne1_state::machine_reset()
|
||||
{
|
||||
// Refresh configuration
|
||||
m_screen_pac = 0 != (m_cnf->read() & 0x01);
|
||||
switch (m_cnf->read() & 0x06)
|
||||
switch (m_cnf->read() & 0x03)
|
||||
{
|
||||
case 0x00:
|
||||
m_acia_rxc_txc_div = 16;
|
||||
m_acia_rxc_txc_p_low = 23;
|
||||
m_acia_rxc_txc_p_high = 29;
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x01:
|
||||
m_acia_rxc_txc_div = 16;
|
||||
m_acia_rxc_txc_p_low = 9;
|
||||
m_acia_rxc_txc_p_high = 15;
|
||||
break;
|
||||
case 0x04:
|
||||
case 0x02:
|
||||
m_acia_rxc_txc_div = 16;
|
||||
m_acia_rxc_txc_p_low = 5;
|
||||
m_acia_rxc_txc_p_high = 8;
|
||||
break;
|
||||
case 0x06:
|
||||
case 0x03:
|
||||
m_acia_rxc_txc_div = 8;
|
||||
m_acia_rxc_txc_p_low = 5;
|
||||
m_acia_rxc_txc_p_high = 8;
|
||||
@ -331,10 +347,6 @@ void osborne1_state::machine_reset()
|
||||
m_acia_rxc_txc_state = 0;
|
||||
update_acia_rxc_txc();
|
||||
|
||||
// Reset video hardware
|
||||
m_resolution = 0;
|
||||
m_hc_left = 1;
|
||||
|
||||
// The low bits of attribute RAM are not physically present and hence always read high
|
||||
for (unsigned i = 0; i < 0x1000; i++)
|
||||
m_ram->pointer()[0x10000 + i] |= 0x7F;
|
||||
@ -342,13 +354,110 @@ void osborne1_state::machine_reset()
|
||||
|
||||
void osborne1_state::video_start()
|
||||
{
|
||||
m_screen->register_screen_bitmap(m_bitmap);
|
||||
m_video_timer->adjust(m_screen->time_until_pos(1, 0));
|
||||
}
|
||||
|
||||
void osborne1sp_state::machine_start()
|
||||
{
|
||||
osborne1_state::machine_start();
|
||||
|
||||
save_item(NAME(m_resolution));
|
||||
save_item(NAME(m_hc_left));
|
||||
}
|
||||
|
||||
void osborne1sp_state::machine_reset()
|
||||
{
|
||||
osborne1_state::machine_reset();
|
||||
|
||||
// Reset video hardware
|
||||
m_resolution = 0;
|
||||
m_hc_left = 1;
|
||||
}
|
||||
|
||||
template <int Width, unsigned Scale>
|
||||
inline void osborne1_state::draw_rows(uint16_t col, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
for (int y = cliprect.min_y; cliprect.max_y >= y; ++y)
|
||||
{
|
||||
// Vertical scroll is latched at the start of the visible area
|
||||
if (0 == y)
|
||||
m_scroll_y = m_pia1->b_output() & 0x1F;
|
||||
|
||||
// Draw a line of the display
|
||||
uint8_t const ra(y % 10);
|
||||
uint16_t *p(&bitmap.pix16(y));
|
||||
uint16_t const row(((m_scroll_y + (y / 10)) << 7) & 0x0F80);
|
||||
|
||||
for (uint16_t x = 0; Width > x; ++x)
|
||||
{
|
||||
uint16_t const offs(row | ((col + x) & 0x7F));
|
||||
uint8_t const chr(m_ram->pointer()[0xF000 + offs]);
|
||||
uint8_t const clr((m_ram->pointer()[0x10000 + offs] & 0x80) ? 2 : 1);
|
||||
|
||||
uint8_t const gfx(((chr & 0x80) && (ra == 9)) ? 0xFF : m_p_chargen[(ra << 7) | (chr & 0x7F)]);
|
||||
|
||||
// Display a scanline of a character
|
||||
for (unsigned i = 0; Scale > i; ++i) *p++ = BIT(gfx, 7) ? clr : 0;
|
||||
for (unsigned i = 0; Scale > i; ++i) *p++ = BIT(gfx, 6) ? clr : 0;
|
||||
for (unsigned i = 0; Scale > i; ++i) *p++ = BIT(gfx, 5) ? clr : 0;
|
||||
for (unsigned i = 0; Scale > i; ++i) *p++ = BIT(gfx, 4) ? clr : 0;
|
||||
for (unsigned i = 0; Scale > i; ++i) *p++ = BIT(gfx, 3) ? clr : 0;
|
||||
for (unsigned i = 0; Scale > i; ++i) *p++ = BIT(gfx, 2) ? clr : 0;
|
||||
for (unsigned i = 0; Scale > i; ++i) *p++ = BIT(gfx, 1) ? clr : 0;
|
||||
for (unsigned i = 0; Scale > i; ++i) *p++ = BIT(gfx, 0) ? clr : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The derivation of the initial column is not obvious. The 7-bit
|
||||
// column counter is preloaded near the beginning of the horizontal
|
||||
// blank period. The initial column is offset by the number of
|
||||
// character clock periods in the horizontal blank period minus one
|
||||
// because it latches the value before it's displayed. Using the
|
||||
// standard video display, there are 12 character clock periods in
|
||||
// the horizontal blank period, so subtracting 1 gives 0x0B. Using
|
||||
// the SCREEN-PAC's high-resolution mode, the character clock is
|
||||
// twice the frequency giving 24 character clock periods in the
|
||||
// horizontal blanking period, so subtracting 1 gives 0x17. Using
|
||||
// the standard video display, the column counter is preloaded with
|
||||
// the high 7 bits of the value from PIA1 PORTB. The SCREEN-PAC
|
||||
// takes the two high bits of this value, but sets the low five bits
|
||||
// to a fixed value of 1 or 9 depending on the value of the HC-LEFT
|
||||
// signal (set by bit 1 of the value written to 0x2400). Of course
|
||||
// it depends on the value wrapping around to zero when it counts
|
||||
// past 0x7F.
|
||||
|
||||
uint32_t osborne1_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
|
||||
draw_rows<52, 1>(scroll_x() + 0x0B, bitmap, cliprect);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t osborne1sp_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
// The derivation of the initial column is not obvious. The 7-bit
|
||||
// column counter is preloaded near the beginning of the horizontal
|
||||
// blank period. The initial column is offset by the number of
|
||||
// character clock periods in the horizontal blank period minus one
|
||||
// because it latches the value before it's displayed. Using the
|
||||
// standard video display, there are 12 character clock periods in
|
||||
// the horizontal blank period, so subtracting 1 gives 0x0B. Using
|
||||
// the SCREEN-PAC's high-resolution mode, the character clock is
|
||||
// twice the frequency giving 24 character clock periods in the
|
||||
// horizontal blanking period, so subtracting 1 gives 0x17. Using
|
||||
// the standard video display, the column counter is preloaded with
|
||||
// the high 7 bits of the value from PIA1 PORTB. The SCREEN-PAC
|
||||
// takes the two high bits of this value, but sets the low five bits
|
||||
// to a fixed value of 1 or 9 depending on the value of the HC-LEFT
|
||||
// signal (set by bit 1 of the value written to 0x2400). Of course
|
||||
// it depends on the value wrapping around to zero when it counts
|
||||
// past 0x7F.
|
||||
if (m_resolution)
|
||||
draw_rows<104, 1>((scroll_x() & 0x60) + (m_hc_left ? 0x09 : 0x01) + 0x17, bitmap, cliprect);
|
||||
else
|
||||
draw_rows<52, 2>(scroll_x() + 0x0B, bitmap, cliprect);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -359,71 +468,6 @@ TIMER_CALLBACK_MEMBER(osborne1_state::video_callback)
|
||||
uint8_t const ra = y % 10;
|
||||
uint8_t const port_b = m_pia1->b_output();
|
||||
|
||||
// Check for start/end of visible area and clear/set CA1 on video PIA
|
||||
if (y == 0)
|
||||
{
|
||||
m_scroll_y = port_b & 0x1F;
|
||||
m_pia1->ca1_w(0);
|
||||
}
|
||||
else if (y == 240)
|
||||
{
|
||||
m_pia1->ca1_w(1);
|
||||
}
|
||||
|
||||
if (y < 240)
|
||||
{
|
||||
// Draw a line of the display
|
||||
uint16_t *p = &m_bitmap.pix16(y);
|
||||
bool const hires = m_screen_pac & m_resolution;
|
||||
uint16_t const row = ((m_scroll_y + (y / 10)) << 7) & 0xF80;
|
||||
|
||||
// The derivation of the initial column is not obvious. The 7-bit
|
||||
// column counter is preloaded near the beginning of the horizontal
|
||||
// blank period. The initial column is offset by the number of
|
||||
// character clock periods in the horizontal blank period minus one
|
||||
// because it latches the value before it's displayed. Using the
|
||||
// standard video display, there are 12 character clock periods in
|
||||
// the horizontal blank period, so subtracting 1 gives 0x0B. Using
|
||||
// the SCREEN-PAC's high-resolution mode, the character clock is
|
||||
// twice the frequency giving 24 character clock periods in the
|
||||
// horizontal blanking period, so subtracting 1 gives 0x17. Using
|
||||
// the standard video display, the column counter is preloaded with
|
||||
// the high 7 bits of the value from PIA1 PORTB. The SCREEN-PAC
|
||||
// takes the two high bits of this value, but sets the low five bits
|
||||
// to a fixed value of 1 or 9 depending on the value of the HC-LEFT
|
||||
// signal (set by bit 1 of the value written to 0x2400). Of course
|
||||
// it depends on the value wrapping around to zero when it counts
|
||||
// past 0x7F.
|
||||
uint16_t const col = hires ? ((m_scroll_x & 0x60) + (m_hc_left ? 0x09 : 0x01) + 0x17) : (m_scroll_x + 0x0B);
|
||||
|
||||
for (uint16_t x = 0; x < (hires ? 104 : 52); x++)
|
||||
{
|
||||
uint16_t const offs = row | ((col + x) & 0x7F);
|
||||
uint8_t const chr = m_ram->pointer()[0xF000 + offs];
|
||||
uint8_t const clr = (m_ram->pointer()[0x10000 + offs] & 0x80) ? 2 : 1;
|
||||
|
||||
uint8_t const gfx = ((chr & 0x80) && (ra == 9)) ? 0xFF : m_p_chargen[(ra << 7) | (chr & 0x7F)];
|
||||
|
||||
// Display a scanline of a character
|
||||
*p++ = BIT(gfx, 7) ? clr : 0;
|
||||
if (!hires) { p[0] = p[-1]; p++; }
|
||||
*p++ = BIT(gfx, 6) ? clr : 0;
|
||||
if (!hires) { p[0] = p[-1]; p++; }
|
||||
*p++ = BIT(gfx, 5) ? clr : 0;
|
||||
if (!hires) { p[0] = p[-1]; p++; }
|
||||
*p++ = BIT(gfx, 4) ? clr : 0;
|
||||
if (!hires) { p[0] = p[-1]; p++; }
|
||||
*p++ = BIT(gfx, 3) ? clr : 0;
|
||||
if (!hires) { p[0] = p[-1]; p++; }
|
||||
*p++ = BIT(gfx, 2) ? clr : 0;
|
||||
if (!hires) { p[0] = p[-1]; p++; }
|
||||
*p++ = BIT(gfx, 1) ? clr : 0;
|
||||
if (!hires) { p[0] = p[-1]; p++; }
|
||||
*p++ = BIT(gfx, 0) ? clr : 0;
|
||||
if (!hires) { p[0] = p[-1]; p++; }
|
||||
}
|
||||
}
|
||||
|
||||
// The beeper is gated so it's active four out of every ten scanlines
|
||||
m_beep_state = (ra & 0x04) ? 1 : 0;
|
||||
m_speaker->level_w((BIT(port_b, 5) && m_beep_state) ? 1 : 0);
|
||||
|
@ -31617,6 +31617,7 @@ osbexec // 1982 Osborne Executive
|
||||
@source:osborne1.cpp
|
||||
osborne1 // 1981 Osborne-1
|
||||
osborne1nv // 1984 Osborne-1 (Nuevo Video)
|
||||
osborne1sp // 1983 Osborne-1 with SCREEN-PAC
|
||||
|
||||
@source:osi.cpp
|
||||
c1p //
|
||||
|
Loading…
Reference in New Issue
Block a user