From be7476e81bafad3ec7b5c4f501fbd131bfdf1911 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Fri, 6 Dec 2019 21:43:12 +1100 Subject: 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 --- src/mame/drivers/osborne1.cpp | 66 ++++++++---- src/mame/includes/osborne1.h | 75 +++++++++----- src/mame/machine/osborne1.cpp | 230 +++++++++++++++++++++++++----------------- src/mame/mame.lst | 1 + 4 files changed, 238 insertions(+), 134 deletions(-) diff --git a/src/mame/drivers/osborne1.cpp b/src/mame/drivers/osborne1.cpp index afa933e8de6..9f9dcc46979 100644 --- a/src/mame/drivers/osborne1.cpp +++ b/src/mame/drivers/osborne1.cpp @@ -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 ) diff --git a/src/mame/includes/osborne1.h b/src/mame/includes/osborne1.h index c972e777e16..d3fc9e14a4b 100644 --- a/src/mame/includes/osborne1.h +++ b/src/mame/includes/osborne1.h @@ -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 osborne1nv_io(address_map &map); + void osborne1_base(machine_config &config); - required_device m_ram; - required_device m_screen; - required_device m_maincpu; + void osborne1_mem(address_map &map); + void osborne1_op(address_map &map); + void osborne1_io(address_map &map); + void osborne1nv_io(address_map &map); -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 void draw_rows(uint16_t col, bitmap_ind16 &bitmap, const rectangle &cliprect); + + required_device m_ram; + required_device m_screen; + required_device m_maincpu; + required_device m_pia0; + required_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 m_gfxdecode; required_device m_speaker; - required_device m_pia0; - required_device m_pia1; required_device m_acia; required_device m_fdc; required_device m_ieee; required_device m_floppy0; required_device 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 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; }; diff --git a/src/mame/machine/osborne1.cpp b/src/mame/machine/osborne1.cpp index 5fb5f7e669d..f76215ddbed 100644 --- a/src/mame/machine/osborne1.cpp +++ b/src/mame/machine/osborne1.cpp @@ -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,13 +75,35 @@ WRITE8_MEMBER( osborne1_state::bank_2xxx_3xxx_w ) { m_acia->write(offset & 0x01, data); } + 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 = data & 0x01; - m_hc_left = (data & 0x02) ? 0 : 1; + m_resolution = BIT(data, 0); + m_hc_left = BIT(~data, 1); } - if ((offset & 0xC00) == 0xC00) // Video PIA - m_pia1->write(offset & 0x03, data); } } @@ -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,87 +354,119 @@ 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)); } -uint32_t osborne1_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +void osborne1sp_state::machine_start() { - copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); - return 0; -} + osborne1_state::machine_start(); + save_item(NAME(m_resolution)); + save_item(NAME(m_hc_left)); +} -TIMER_CALLBACK_MEMBER(osborne1_state::video_callback) +void osborne1sp_state::machine_reset() { - int const y = m_screen->vpos(); - uint8_t const ra = y % 10; - uint8_t const port_b = m_pia1->b_output(); + osborne1_state::machine_reset(); - // 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); - } + // Reset video hardware + m_resolution = 0; + m_hc_left = 1; +} - if (y < 240) +template +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 - 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++) + 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; + 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)]; + 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++; } + 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) +{ + 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; +} + + +TIMER_CALLBACK_MEMBER(osborne1_state::video_callback) +{ + int const y = m_screen->vpos(); + uint8_t const ra = y % 10; + uint8_t const port_b = m_pia1->b_output(); // The beeper is gated so it's active four out of every ten scanlines m_beep_state = (ra & 0x04) ? 1 : 0; diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 0bfa18d1138..35d5c70a764 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -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 // -- cgit v1.2.3