From 2f5b793344ddcf599dc5b68ae2faa070cca3381a Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Fri, 31 Mar 2023 04:34:55 +1100 Subject: [PATCH] osborne/osborne1.cpp: Use a memory view to simplify bank 1/2 selection. --- src/mame/osborne/osborne1.cpp | 732 +++++++++++++++++++++++++++++++- src/mame/osborne/osborne1.h | 222 ---------- src/mame/osborne/osborne1_m.cpp | 558 ------------------------ 3 files changed, 717 insertions(+), 795 deletions(-) delete mode 100644 src/mame/osborne/osborne1.h delete mode 100644 src/mame/osborne/osborne1_m.cpp diff --git a/src/mame/osborne/osborne1.cpp b/src/mame/osborne/osborne1.cpp index beb077055b2..d58e473e124 100644 --- a/src/mame/osborne/osborne1.cpp +++ b/src/mame/osborne/osborne1.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Wilbert Pol,Vas Crabb +// copyright-holders:Wilbert Pol, Vas Crabb /*************************************************************************** Osborne-1 driver file @@ -40,6 +40,11 @@ used, and the value on the data bus is completley ignored. Selecting between bank 1 and bank 2 is also affected by M1 and IRQACK conditions using a set of three flipflops. +There are three IRQ sources: +- IRQ0 = IRQ from the serial ACIA +- IRQ1 = IRQA from the video PIA +- IRQ2 = IRQA from the IEEE488 PIA + The serial speed configuration implements wiring changes recommended in the Osborne 1 Technical Manual. There's no way for software to read the selected baud rates, so it will always call the low speed "300" and the high @@ -89,37 +94,734 @@ TODO: ***************************************************************************/ #include "emu.h" -#include "osborne1.h" +#include "bus/ieee488/ieee488.h" #include "bus/rs232/rs232.h" -#include "speaker.h" +#include "cpu/z80/z80.h" + +#include "imagedev/floppy.h" + +#include "machine/6821pia.h" +#include "machine/6850acia.h" +#include "machine/wd_fdc.h" + +#include "sound/spkrdev.h" + +#include "video/mc6845.h" + +#include "emupal.h" +#include "screen.h" #include "softlist_dev.h" +#include "speaker.h" +#include "tilemap.h" +namespace { + static constexpr XTAL MAIN_CLOCK = 15.9744_MHz_XTAL; +class osborne1_state : public driver_device +{ +public: + osborne1_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_rom_view(*this, "bank_0000"), + m_vram(*this, "vram", 0x2000, ENDIANNESS_LITTLE), + m_screen(*this, "screen"), + m_maincpu(*this, "maincpu"), + 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), + m_floppy0(*this, "mb8877:0"), + m_floppy1(*this, "mb8877:1"), + m_keyb_row(*this, { "ROW0", "ROW1", "ROW3", "ROW4", "ROW5", "ROW2", "ROW6", "ROW7" }), + m_btn_reset(*this, "RESET"), + m_cnf(*this, "CNF"), + m_bank_fxxx(*this, "bank_fxxx"), + m_p_chargen(*this, "chargen"), + m_video_timer(nullptr), + m_tilemap(nullptr), + m_acia_rxc_txc_timer(nullptr) + { + } + + void osborne1(machine_config &config); + + 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); + + u8 bank2_2xxx_3xxx_r(offs_t offset); + void bank2_2xxx_3xxx_w(offs_t offset, u8 data); + void videoram_w(offs_t offset, u8 data); + u8 opcode_r(offs_t offset); + void bankswitch_w(offs_t offset, u8 data); + 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); + + memory_view m_rom_view; + memory_share_creator m_vram; + required_device m_screen; + required_device m_maincpu; + required_device m_pia0; + required_device m_pia1; + +private: + u8 ieee_pia_pb_r(); + void ieee_pia_pb_w(u8 data); + DECLARE_WRITE_LINE_MEMBER(ieee_pia_irq_a_func); + + void video_pia_port_a_w(u8 data); + void video_pia_port_b_w(u8 data); + DECLARE_WRITE_LINE_MEMBER(video_pia_out_cb2_dummy); + DECLARE_WRITE_LINE_MEMBER(video_pia_irq_a_func); + + DECLARE_WRITE_LINE_MEMBER(serial_acia_irq_func); + + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + TIMER_CALLBACK_MEMBER(video_callback); + TIMER_CALLBACK_MEMBER(acia_rxc_txc_callback); + + TILE_GET_INFO_MEMBER(get_tile_info); + + bool set_rom_mode(u8 value); + bool set_bit_9(u8 value); + void update_irq(); + void update_acia_rxc_txc(); + + required_device m_gfxdecode; + required_device m_speaker; + required_device m_acia; + required_device m_fdc; + required_device m_ieee; + required_device m_floppy0; + required_device m_floppy1; + + // user inputs + required_ioport_array<8> m_keyb_row; + required_ioport m_btn_reset; + + // fake inputs for hardware configuration and things that need rewiring + required_ioport m_cnf; + + // pieces of memory + required_memory_bank m_bank_fxxx; + required_region_ptr m_p_chargen; + + // configuration (reloaded on reset) + u8 m_acia_rxc_txc_div; + u8 m_acia_rxc_txc_p_low; + u8 m_acia_rxc_txc_p_high; + + // bank switch control bits + u8 m_ub4a_q; + u8 m_ub6a_q; + u8 m_rom_mode; + u8 m_bit_9; + + // onboard video state + u8 m_scroll_x; + u8 m_scroll_y; + u8 m_beep_state; + emu_timer *m_video_timer; + tilemap_t *m_tilemap; + + // serial state + u8 m_acia_irq_state; + u8 m_acia_rxc_txc_state; + emu_timer *m_acia_rxc_txc_timer; + + memory_access<16, 0, 0, ENDIANNESS_LITTLE>::cache 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); + + u8 bank2_2xxx_3xxx_r(offs_t offset); + void bank2_2xxx_3xxx_w(offs_t offset, u8 data); + +private: + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + // SCREEN-PAC registers + u8 m_resolution = 0; + u8 m_hc_left = 0; +}; + + +class osborne1nv_state : public osborne1_state +{ +public: + osborne1nv_state(const machine_config &mconfig, device_type type, const char *tag) : + osborne1_state(mconfig, type, tag), + m_palette(*this, "palette"), + m_p_nuevo(*this, "nuevo") + { + } + + void osborne1nv(machine_config &config); + +private: + void osborne1nv_io(address_map &map); + + MC6845_UPDATE_ROW(crtc_update_row); + MC6845_ON_UPDATE_ADDR_CHANGED(crtc_update_addr_changed); + + required_device m_palette; + required_region_ptr m_p_nuevo; +}; + + +u8 osborne1_state::bank2_2xxx_3xxx_r(offs_t offset) +{ + // Since each peripheral only checks two bits, many addresses will + // result in multiple peripherals attempting to drive the bus. This is + // simulated by ANDing all the values together. + u8 data = 0xff; + if ((offset & 0x900) == 0x100) // Floppy + data &= m_fdc->read(offset & 0x03); + if ((offset & 0x900) == 0x900) // IEEE488 PIA + data &= m_pia0->read(offset & 0x03); + if ((offset & 0xa00) == 0x200) // Keyboard + { + for (unsigned b = 0; 8 > b; ++b) + { + if (BIT(offset, b)) + data &= m_keyb_row[b]->read(); + } + } + if ((offset & 0xa00) == 0xa00) // Serial + { + data &= m_acia->read(offset & 0x01); + } + if ((offset & 0xc00) == 0xc00) // Video PIA + data &= m_pia1->read(offset & 0x03); + return data; +} + +void osborne1_state::bank2_2xxx_3xxx_w(offs_t offset, u8 data) +{ + // Handle writes to the I/O area + if ((offset & 0x900) == 0x100) // Floppy + m_fdc->write(offset & 0x03, data); + if ((offset & 0x900) == 0x900) // IEEE488 PIA + m_pia0->write(offset & 0x03, data); + if ((offset & 0xa00) == 0xa00) // Serial + m_acia->write(offset & 0x01, data); + if ((offset & 0xc00) == 0xc00) // Video PIA + m_pia1->write(offset & 0x03, data); +} + +u8 osborne1sp_state::bank2_2xxx_3xxx_r(offs_t offset) +{ + u8 data = osborne1_state::bank2_2xxx_3xxx_r(offset); + + if ((offset & 0xc00) == 0x400) // SCREEN-PAC + data &= 0xfb; + + return data; +} + +void osborne1sp_state::bank2_2xxx_3xxx_w(offs_t offset, u8 data) +{ + osborne1_state::bank2_2xxx_3xxx_w(offset, data); + + if ((offset & 0xc00) == 0x400) // SCREEN-PAC + { + m_resolution = BIT(data, 0); + m_hc_left = BIT(~data, 1); + } +} + +void osborne1_state::videoram_w(offs_t offset, u8 data) +{ + // Attribute RAM is only one bit wide - low seven bits are discarded and read back high + if (m_bit_9) + data |= 0x7f; + else + m_tilemap->mark_tile_dirty(offset); + reinterpret_cast(m_bank_fxxx->base())[offset] = data; +} + +u8 osborne1_state::opcode_r(offs_t offset) +{ + if (!machine().side_effects_disabled()) + { + // Update the flipflops that control bank selection and NMI + u8 const new_ub6a_q = (m_btn_reset->read() & 0x80) ? 1 : 0; + if (!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_mem_cache.read_byte(offset); +} + +void osborne1_state::bankswitch_w(offs_t offset, u8 data) +{ + switch (offset) + { + case 0x00: + if (set_rom_mode(1)) + m_ub4a_q = m_ub6a_q; + break; + case 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: + set_bit_9(1); + break; + case 0x03: + set_bit_9(0); + break; + } +} + +WRITE_LINE_MEMBER( osborne1_state::irqack_w ) +{ + // Update the flipflops that control bank selection and NMI + 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); +} + + +u8 osborne1_state::ieee_pia_pb_r() +{ + /* + bit description + + 0 + 1 + 2 + 3 EOI + 4 + 5 DAV + 6 NDAC + 7 NRFD + */ + u8 data = 0; + + data |= m_ieee->eoi_r() << 3; + data |= m_ieee->dav_r() << 5; + data |= m_ieee->ndac_r() << 6; + data |= m_ieee->nrfd_r() << 7; + + return data; +} + +void osborne1_state::ieee_pia_pb_w(u8 data) +{ + /* + bit description + + 0 0 = DATAn as output, 1 = DATAn as input + 1 0 = NDAC/NRFD as output, 1 = NDAC/NRFD as input; also gates SRQ + 2 0 = EOI/DAV as output, 1 = EOI/DAV as input + 3 EOI + 4 ATN + 5 DAV + 6 NDAC + 7 NRFD + */ + m_ieee->host_eoi_w(BIT(data, 3)); + m_ieee->host_atn_w(BIT(data, 4)); + m_ieee->host_dav_w(BIT(data, 5)); + m_ieee->host_ndac_w(BIT(data, 6)); + m_ieee->host_nrfd_w(BIT(data, 7)); +} + +WRITE_LINE_MEMBER( osborne1_state::ieee_pia_irq_a_func ) +{ + update_irq(); +} + + +void osborne1_state::video_pia_port_a_w(u8 data) +{ + m_scroll_x = data >> 1; + + m_fdc->dden_w(BIT(data, 0)); +} + +void osborne1_state::video_pia_port_b_w(u8 data) +{ + m_speaker->level_w((BIT(data, 5) && m_beep_state) ? 1 : 0); + + if (BIT(data, 6)) + { + m_fdc->set_floppy(m_floppy0->get_device()); + m_floppy0->get_device()->mon_w(0); + } + else if (BIT(data, 7)) + { + m_fdc->set_floppy(m_floppy1->get_device()); + m_floppy1->get_device()->mon_w(0); + } + else + { + m_fdc->set_floppy(nullptr); + } +} + +WRITE_LINE_MEMBER( osborne1_state::video_pia_out_cb2_dummy ) +{ +} + +WRITE_LINE_MEMBER( osborne1_state::video_pia_irq_a_func ) +{ + update_irq(); +} + + +WRITE_LINE_MEMBER( osborne1_state::serial_acia_irq_func ) +{ + m_acia_irq_state = state; + update_irq(); +} + + +INPUT_CHANGED_MEMBER( osborne1_state::reset_key ) +{ + // This key affects NMI + if (!m_ub6a_q) + m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE); +} + + +void osborne1_state::machine_start() +{ + m_bank_fxxx->configure_entries(0, 2, &m_vram[0], 0x1000); + + m_video_timer = timer_alloc(FUNC(osborne1_state::video_callback), this); + m_tilemap = &machine().tilemap().create( + *m_gfxdecode, + tilemap_get_info_delegate(*this, FUNC(osborne1_state::get_tile_info)), TILEMAP_SCAN_ROWS, + 8, 10, 128, 32); + + m_acia_rxc_txc_timer = timer_alloc(FUNC(osborne1_state::acia_rxc_txc_callback), this); + + m_maincpu->space(AS_PROGRAM).cache(m_mem_cache); + + 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)); + + save_item(NAME(m_ub4a_q)); + save_item(NAME(m_ub6a_q)); + save_item(NAME(m_rom_mode)); + save_item(NAME(m_bit_9)); + + save_item(NAME(m_scroll_x)); + save_item(NAME(m_scroll_y)); + save_item(NAME(m_beep_state)); + + save_item(NAME(m_acia_irq_state)); + save_item(NAME(m_acia_rxc_txc_state)); +} + +void osborne1_state::machine_reset() +{ + // Refresh configuration + 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 0x01: + m_acia_rxc_txc_div = 16; + m_acia_rxc_txc_p_low = 9; + m_acia_rxc_txc_p_high = 15; + break; + case 0x02: + m_acia_rxc_txc_div = 16; + m_acia_rxc_txc_p_low = 5; + m_acia_rxc_txc_p_high = 8; + break; + case 0x03: + m_acia_rxc_txc_div = 8; + m_acia_rxc_txc_p_low = 5; + m_acia_rxc_txc_p_high = 8; + break; + } + + // Initialise memory configuration + m_rom_mode = 0; + m_bit_9 = 1; + set_rom_mode(1); + set_bit_9(0); + + // Reset serial state + m_acia_irq_state = 0; + m_acia_rxc_txc_state = 0; + update_acia_rxc_txc(); + + // The low bits of attribute RAM are not physically present and hence always read high + for (unsigned i = 0; i < 0x1000; i++) + m_vram[0x1000 + i] |= 0x7f; +} + +void osborne1_state::video_start() +{ + 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 +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 + u8 const ra(y % 10); + uint16_t *p(&bitmap.pix(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)); + u8 const chr(m_vram[offs]); + u8 const clr((m_vram[0x1000 + offs] & 0x80) ? 2 : 1); + + u8 const gfx(((chr & 0x80) && (ra == 9)) ? 0xff : m_p_chargen[(ra << 7) | (chr & 0x7f)]); + + // Display a scanline of a character + for (unsigned b = 0; 8 > b; ++b) + { + uint16_t const pixel(BIT(gfx, 7 - b) ? clr : 0); + for (unsigned i = 0; Scale > i; ++i) + *p++ = pixel; + } + } + } +} + +// 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) +{ + 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()); + u8 const ra(y % 10); + + // 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((m_beep_state && BIT(m_pia1->b_output(), 5)) ? 1 : 0); + + int const next((y - ra) + ((ra < 4) ? 4 : (ra < 8) ? 8 : 14)); + m_video_timer->adjust(m_screen->time_until_pos((m_screen->height() > next) ? next : 0, 0)); +} + +TIMER_CALLBACK_MEMBER(osborne1_state::acia_rxc_txc_callback) +{ + m_acia_rxc_txc_state = m_acia_rxc_txc_state ? 0 : 1; + update_acia_rxc_txc(); +} + + +TILE_GET_INFO_MEMBER(osborne1_state::get_tile_info) +{ + // The gfxdecode and tilemap aren't actually used for drawing, they just look nice in the graphics viewer + tileinfo.set(0, m_vram[tile_index] & 0x7f, 0, 0); +} + + +bool osborne1_state::set_rom_mode(u8 value) +{ + if (value != m_rom_mode) + { + m_rom_mode = value; + if (m_rom_mode) + m_rom_view.select(0); + else + m_rom_view.disable(); + return true; + } + else + { + return false; + } +} + +bool osborne1_state::set_bit_9(u8 value) +{ + if (value != m_bit_9) + { + m_bit_9 = value; + m_bank_fxxx->set_entry(m_bit_9); + return true; + } + else + { + return false; + } +} + +void osborne1_state::update_irq() +{ + if (m_pia0->irq_a_state()) + m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xf0); // Z80 + else if (m_pia1->irq_a_state()) + m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xf8); // Z80 + else if (m_acia_irq_state) + m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xfc); // Z80 + else + m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, CLEAR_LINE, 0xfe); // Z80 +} + +void osborne1_state::update_acia_rxc_txc() +{ + m_acia->write_rxc(m_acia_rxc_txc_state); + m_acia->write_txc(m_acia_rxc_txc_state); + attoseconds_t const dividend = (ATTOSECONDS_PER_SECOND / 100) * (m_acia_rxc_txc_state ? m_acia_rxc_txc_p_high : m_acia_rxc_txc_p_low); + attoseconds_t const divisor = (15974400 / 100) / m_acia_rxc_txc_div; + m_acia_rxc_txc_timer->adjust(attotime(0, dividend / divisor)); +} + + +MC6845_UPDATE_ROW(osborne1nv_state::crtc_update_row) +{ + rgb_t const *const palette = m_palette->palette()->entry_list_raw(); + uint16_t const base = (ma >> 1) & 0xf80; + uint32_t *p = &bitmap.pix(y); + for (u8 x = 0; x < x_count; ++x) + { + uint16_t const offset = base | ((ma + x) & 0x7f); + u8 const chr = m_vram[offset]; + u8 const clr = BIT(m_vram[0x1000 | offset], 7) ? 2 : 1; + + u8 const gfx = ((chr & 0x80) && (ra == 9)) ? 0xff : m_p_nuevo[(ra << 7) | (chr & 0x7f)]; + + for (unsigned bit = 0; 8 > bit; ++bit) + *p++ = palette[BIT(gfx, 7 - bit) ? clr : 0]; + } +} + +MC6845_ON_UPDATE_ADDR_CHANGED(osborne1nv_state::crtc_update_addr_changed) +{ +} + + void osborne1_state::osborne1_mem(address_map &map) { - map(0x0000, 0x0FFF).bankr(m_bank_0xxx).w(FUNC(osborne1_state::bank_0xxx_w)); - map(0x1000, 0x1FFF).bankr(m_bank_1xxx).w(FUNC(osborne1_state::bank_1xxx_w)); - map(0x2000, 0x3FFF).rw(FUNC(osborne1_state::bank_2xxx_3xxx_r), FUNC(osborne1_state::bank_2xxx_3xxx_w)); - map(0x4000, 0xEFFF).ram(); // FIXME: shouldn't this also read/write the RAM in the RAM device? - map(0xF000, 0xFFFF).bankr(m_bank_fxxx).w(FUNC(osborne1_state::videoram_w)); + map(0x0000, 0xefff).ram(); + map(0xf000, 0xffff).bankr(m_bank_fxxx).w(FUNC(osborne1_state::videoram_w)); + + map(0x0000, 0x3fff).view(m_rom_view); + m_rom_view[0](0x0000, 0x0fff).mirror(0x1000).rom().region("maincpu", 0).unmapw(); + m_rom_view[0](0x2000, 0x2fff).mirror(0x1000).rw(FUNC(osborne1_state::bank2_2xxx_3xxx_r), FUNC(osborne1_state::bank2_2xxx_3xxx_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)); + m_rom_view[0](0x2000, 0x2fff).mirror(0x1000).rw(FUNC(osborne1sp_state::bank2_2xxx_3xxx_r), FUNC(osborne1sp_state::bank2_2xxx_3xxx_w)); } void osborne1_state::osborne1_op(address_map &map) { - map(0x0000, 0xFFFF).r(FUNC(osborne1_state::opcode_r)); + map(0x0000, 0xffff).r(FUNC(osborne1_state::opcode_r)); } @@ -226,10 +928,10 @@ static INPUT_PORTS_START( osborne1 ) PORT_START("RESET") PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F12) PORT_NAME("RESET") PORT_CHANGED_MEMBER(DEVICE_SELF, osborne1_state, reset_key, 0) - PORT_BIT(0x7F, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x7f, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("CNF") - PORT_BIT(0xFC, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0xfc, IP_ACTIVE_LOW, IPT_UNUSED) PORT_CONFNAME(0x03, 0x00, "Serial Speed") PORT_CONFSETTING(0x00, "300/1200") PORT_CONFSETTING(0x01, "600/2400") @@ -332,9 +1034,6 @@ void osborne1_state::osborne1_base(machine_config &config) FLOPPY_CONNECTOR(config, m_floppy0, osborne1_floppies, "525ssdd", floppy_image_device::default_mfm_floppy_formats); FLOPPY_CONNECTOR(config, m_floppy1, osborne1_floppies, "525ssdd", floppy_image_device::default_mfm_floppy_formats); - // internal ram - RAM(config, m_ram).set_default_size("68K"); // 64kB main RAM and 4kbit video attribute RAM - SOFTWARE_LIST(config, "flop_list").set_original("osborne1"); } @@ -423,6 +1122,9 @@ ROM_START( osborne1nv ) ROM_LOAD( "character_generator_6-29-84.14", 0x0000, 0x800, CRC(6c1eab0d) SHA1(b04459d377a70abc9155a5486003cb795342c801) ) ROM_END +} // anonymous namespace + + // 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 ) diff --git a/src/mame/osborne/osborne1.h b/src/mame/osborne/osborne1.h deleted file mode 100644 index 10184bdd6eb..00000000000 --- a/src/mame/osborne/osborne1.h +++ /dev/null @@ -1,222 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Wilbert Pol,Vas Crabb -/***************************************************************************** - * - * includes/osborne1.h - * - ****************************************************************************/ -#ifndef MAME_OSBORNE_OSBORNE1_H -#define MAME_OSBORNE_OSBORNE1_H - -#pragma once - -#include "bus/ieee488/ieee488.h" - -#include "cpu/z80/z80.h" - -#include "imagedev/floppy.h" - -#include "machine/6821pia.h" -#include "machine/6850acia.h" -#include "machine/ram.h" -#include "machine/wd_fdc.h" - -#include "sound/spkrdev.h" - -#include "video/mc6845.h" - -#include "emupal.h" -#include "screen.h" -#include "tilemap.h" - - -class osborne1_state : public driver_device -{ -public: - osborne1_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_ram(*this, RAM_TAG), - m_screen(*this, "screen"), - m_maincpu(*this, "maincpu"), - 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), - m_floppy0(*this, "mb8877:0"), - m_floppy1(*this, "mb8877:1"), - m_keyb_row(*this, { "ROW0", "ROW1", "ROW3", "ROW4", "ROW5", "ROW2", "ROW6", "ROW7" }), - m_btn_reset(*this, "RESET"), - m_cnf(*this, "CNF"), - m_region_maincpu(*this, "maincpu"), - m_bank_0xxx(*this, "bank_0xxx"), - m_bank_1xxx(*this, "bank_1xxx"), - m_bank_fxxx(*this, "bank_fxxx"), - m_p_chargen(*this, "chargen"), - m_video_timer(nullptr), - m_tilemap(nullptr), - m_acia_rxc_txc_timer(nullptr) - { - } - - void osborne1(machine_config &config); - - 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 bank_0xxx_w(offs_t offset, u8 data); - void bank_1xxx_w(offs_t offset, u8 data); - u8 bank_2xxx_3xxx_r(offs_t offset); - void bank_2xxx_3xxx_w(offs_t offset, u8 data); - void videoram_w(offs_t offset, u8 data); - u8 opcode_r(offs_t offset); - void bankswitch_w(offs_t offset, u8 data); - 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: - u8 ieee_pia_pb_r(); - void ieee_pia_pb_w(u8 data); - DECLARE_WRITE_LINE_MEMBER(ieee_pia_irq_a_func); - - void video_pia_port_a_w(u8 data); - void video_pia_port_b_w(u8 data); - DECLARE_WRITE_LINE_MEMBER(video_pia_out_cb2_dummy); - DECLARE_WRITE_LINE_MEMBER(video_pia_irq_a_func); - - DECLARE_WRITE_LINE_MEMBER(serial_acia_irq_func); - - u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - - required_device m_gfxdecode; - required_device m_speaker; - required_device m_acia; - required_device m_fdc; - required_device m_ieee; - required_device m_floppy0; - required_device m_floppy1; - - TIMER_CALLBACK_MEMBER(video_callback); - TIMER_CALLBACK_MEMBER(acia_rxc_txc_callback); - - TILE_GET_INFO_MEMBER(get_tile_info); - - bool set_rom_mode(u8 value); - bool set_bit_9(u8 value); - void update_irq(); - void update_acia_rxc_txc(); - - // user inputs - required_ioport_array<8> m_keyb_row; - required_ioport m_btn_reset; - - // fake inputs for hardware configuration and things that need rewiring - required_ioport m_cnf; - - // pieces of memory - required_memory_region m_region_maincpu; - required_memory_bank m_bank_0xxx; - required_memory_bank m_bank_1xxx; - required_memory_bank m_bank_fxxx; - required_region_ptr m_p_chargen; - - // configuration (reloaded on reset) - u8 m_acia_rxc_txc_div; - u8 m_acia_rxc_txc_p_low; - u8 m_acia_rxc_txc_p_high; - - // bank switch control bits - u8 m_ub4a_q; - u8 m_ub6a_q; - u8 m_rom_mode; - u8 m_bit_9; - - // onboard video state - u8 m_scroll_x; - u8 m_scroll_y; - u8 m_beep_state; - emu_timer *m_video_timer; - tilemap_t *m_tilemap; - - // serial state - u8 m_acia_irq_state; - u8 m_acia_rxc_txc_state; - emu_timer *m_acia_rxc_txc_timer; - - memory_access<16, 0, 0, ENDIANNESS_LITTLE>::cache 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); - - u8 bank_2xxx_3xxx_r(offs_t offset); - void bank_2xxx_3xxx_w(offs_t offset, u8 data); - -private: - u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - - // SCREEN-PAC registers - u8 m_resolution = 0; - u8 m_hc_left = 0; -}; - - -class osborne1nv_state : public osborne1_state -{ -public: - osborne1nv_state(const machine_config &mconfig, device_type type, const char *tag) : - osborne1_state(mconfig, type, tag), - m_palette(*this, "palette"), - m_p_nuevo(*this, "nuevo") - { - } - - void osborne1nv(machine_config &config); - -private: - void osborne1nv_io(address_map &map); - - MC6845_UPDATE_ROW(crtc_update_row); - MC6845_ON_UPDATE_ADDR_CHANGED(crtc_update_addr_changed); - - required_device m_palette; - required_region_ptr m_p_nuevo; -}; - -#endif // MAME_OSBORNE_OSBORNE1_H diff --git a/src/mame/osborne/osborne1_m.cpp b/src/mame/osborne/osborne1_m.cpp deleted file mode 100644 index fe3bc0cc819..00000000000 --- a/src/mame/osborne/osborne1_m.cpp +++ /dev/null @@ -1,558 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Wilbert Pol,Vas Crabb -/*************************************************************************** - -There are three IRQ sources: -- IRQ0 = IRQ from the serial ACIA -- IRQ1 = IRQA from the video PIA -- IRQ2 = IRQA from the IEEE488 PIA - -***************************************************************************/ - -#include "emu.h" -#include "osborne1.h" - - -void osborne1_state::bank_0xxx_w(offs_t offset, u8 data) -{ - if (!rom_mode()) - m_ram->pointer()[offset] = data; -} - -void osborne1_state::bank_1xxx_w(offs_t offset, u8 data) -{ - if (!rom_mode()) - m_ram->pointer()[0x1000 + offset] = data; -} - -u8 osborne1_state::bank_2xxx_3xxx_r(offs_t offset) -{ - if (!rom_mode()) - return m_ram->pointer()[0x2000 + offset]; - - // Since each peripheral only checks two bits, many addresses will - // result in multiple peripherals attempting to drive the bus. This is - // simulated by ANDing all the values together. - u8 data = 0xFF; - if ((offset & 0x900) == 0x100) // Floppy - data &= m_fdc->read(offset & 0x03); - if ((offset & 0x900) == 0x900) // IEEE488 PIA - data &= m_pia0->read(offset & 0x03); - if ((offset & 0xA00) == 0x200) // Keyboard - { - for (unsigned b = 0; 8 > b; ++b) - { - if (BIT(offset, b)) - data &= m_keyb_row[b]->read(); - } - } - if ((offset & 0xA00) == 0xA00) // Serial - { - data &= m_acia->read(offset & 0x01); - } - if ((offset & 0xC00) == 0xC00) // Video PIA - data &= m_pia1->read(offset & 0x03); - return data; -} - -void osborne1_state::bank_2xxx_3xxx_w(offs_t offset, u8 data) -{ - if (!rom_mode()) - { - m_ram->pointer()[0x2000 + offset] = data; - } - else - { - // Handle writes to the I/O area - if ((offset & 0x900) == 0x100) // Floppy - m_fdc->write(offset & 0x03, data); - if ((offset & 0x900) == 0x900) // IEEE488 PIA - m_pia0->write(offset & 0x03, data); - if ((offset & 0xA00) == 0xA00) // Serial - { - m_acia->write(offset & 0x01, data); - } - if ((offset & 0xC00) == 0xC00) // Video PIA - m_pia1->write(offset & 0x03, data); - } -} - -u8 osborne1sp_state::bank_2xxx_3xxx_r(offs_t offset) -{ - u8 data = osborne1_state::bank_2xxx_3xxx_r(offset); - if (!rom_mode()) - return data; - - if ((offset & 0xC00) == 0x400) // SCREEN-PAC - { - data &= 0xFB; - } - return data; -} - -void osborne1sp_state::bank_2xxx_3xxx_w(offs_t offset, u8 data) -{ - osborne1_state::bank_2xxx_3xxx_w(offset, data); - - if (rom_mode()) - { - if ((offset & 0xC00) == 0x400) // SCREEN-PAC - { - m_resolution = BIT(data, 0); - m_hc_left = BIT(~data, 1); - } - } -} - -void osborne1_state::videoram_w(offs_t offset, u8 data) -{ - // Attribute RAM is only one bit wide - low seven bits are discarded and read back high - if (m_bit_9) - data |= 0x7F; - else - m_tilemap->mark_tile_dirty(offset); - reinterpret_cast(m_bank_fxxx->base())[offset] = data; -} - -u8 osborne1_state::opcode_r(offs_t offset) -{ - if (!machine().side_effects_disabled()) - { - // Update the flipflops that control bank selection and NMI - u8 const new_ub6a_q = (m_btn_reset->read() & 0x80) ? 1 : 0; - if (!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_mem_cache.read_byte(offset); -} - -void osborne1_state::bankswitch_w(offs_t offset, u8 data) -{ - switch (offset) - { - case 0x00: - if (set_rom_mode(1)) - m_ub4a_q = m_ub6a_q; - break; - case 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: - set_bit_9(1); - break; - case 0x03: - set_bit_9(0); - break; - } -} - -WRITE_LINE_MEMBER( osborne1_state::irqack_w ) -{ - // Update the flipflops that control bank selection and NMI - 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); -} - - -u8 osborne1_state::ieee_pia_pb_r() -{ - /* - bit description - - 0 - 1 - 2 - 3 EOI - 4 - 5 DAV - 6 NDAC - 7 NRFD - */ - u8 data = 0; - - data |= m_ieee->eoi_r() << 3; - data |= m_ieee->dav_r() << 5; - data |= m_ieee->ndac_r() << 6; - data |= m_ieee->nrfd_r() << 7; - - return data; -} - -void osborne1_state::ieee_pia_pb_w(u8 data) -{ - /* - bit description - - 0 0 = DATAn as output, 1 = DATAn as input - 1 0 = NDAC/NRFD as output, 1 = NDAC/NRFD as input; also gates SRQ - 2 0 = EOI/DAV as output, 1 = EOI/DAV as input - 3 EOI - 4 ATN - 5 DAV - 6 NDAC - 7 NRFD - */ - m_ieee->host_eoi_w(BIT(data, 3)); - m_ieee->host_atn_w(BIT(data, 4)); - m_ieee->host_dav_w(BIT(data, 5)); - m_ieee->host_ndac_w(BIT(data, 6)); - m_ieee->host_nrfd_w(BIT(data, 7)); -} - -WRITE_LINE_MEMBER( osborne1_state::ieee_pia_irq_a_func ) -{ - update_irq(); -} - - -void osborne1_state::video_pia_port_a_w(u8 data) -{ - m_scroll_x = data >> 1; - - m_fdc->dden_w(BIT(data, 0)); -} - -void osborne1_state::video_pia_port_b_w(u8 data) -{ - m_speaker->level_w((BIT(data, 5) && m_beep_state) ? 1 : 0); - - if (BIT(data, 6)) - { - m_fdc->set_floppy(m_floppy0->get_device()); - m_floppy0->get_device()->mon_w(0); - } - else if (BIT(data, 7)) - { - m_fdc->set_floppy(m_floppy1->get_device()); - m_floppy1->get_device()->mon_w(0); - } - else - { - m_fdc->set_floppy(nullptr); - } -} - -WRITE_LINE_MEMBER( osborne1_state::video_pia_out_cb2_dummy ) -{ -} - -WRITE_LINE_MEMBER( osborne1_state::video_pia_irq_a_func ) -{ - update_irq(); -} - - -WRITE_LINE_MEMBER( osborne1_state::serial_acia_irq_func ) -{ - m_acia_irq_state = state; - update_irq(); -} - - -INPUT_CHANGED_MEMBER( osborne1_state::reset_key ) -{ - // This key affects NMI - if (!m_ub6a_q) - m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE); -} - - -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); - m_bank_1xxx->configure_entries(0, 1, m_ram->pointer() + 0x1000, 0); - m_bank_1xxx->configure_entries(1, 1, m_region_maincpu->base(), 0); - m_bank_fxxx->configure_entries(0, 1, m_ram->pointer() + 0xF000, 0); - m_bank_fxxx->configure_entries(1, 1, m_ram->pointer() + 0x10000, 0); - - m_video_timer = timer_alloc(FUNC(osborne1_state::video_callback), this); - m_tilemap = &machine().tilemap().create( - *m_gfxdecode, - tilemap_get_info_delegate(*this, FUNC(osborne1_state::get_tile_info)), TILEMAP_SCAN_ROWS, - 8, 10, 128, 32); - - m_acia_rxc_txc_timer = timer_alloc(FUNC(osborne1_state::acia_rxc_txc_callback), this); - - m_maincpu->space(AS_PROGRAM).cache(m_mem_cache); - - 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)); - - save_item(NAME(m_ub4a_q)); - save_item(NAME(m_ub6a_q)); - save_item(NAME(m_rom_mode)); - save_item(NAME(m_bit_9)); - - save_item(NAME(m_scroll_x)); - save_item(NAME(m_scroll_y)); - save_item(NAME(m_beep_state)); - - save_item(NAME(m_acia_irq_state)); - save_item(NAME(m_acia_rxc_txc_state)); -} - -void osborne1_state::machine_reset() -{ - // Refresh configuration - 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 0x01: - m_acia_rxc_txc_div = 16; - m_acia_rxc_txc_p_low = 9; - m_acia_rxc_txc_p_high = 15; - break; - case 0x02: - m_acia_rxc_txc_div = 16; - m_acia_rxc_txc_p_low = 5; - m_acia_rxc_txc_p_high = 8; - break; - case 0x03: - m_acia_rxc_txc_div = 8; - m_acia_rxc_txc_p_low = 5; - m_acia_rxc_txc_p_high = 8; - break; - } - - // Initialise memory configuration - m_rom_mode = 0; - m_bit_9 = 1; - set_rom_mode(1); - set_bit_9(0); - - // Reset serial state - m_acia_irq_state = 0; - m_acia_rxc_txc_state = 0; - update_acia_rxc_txc(); - - // 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; -} - -void osborne1_state::video_start() -{ - 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 -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 - u8 const ra(y % 10); - uint16_t *p(&bitmap.pix(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)); - u8 const chr(m_ram->pointer()[0xF000 + offs]); - u8 const clr((m_ram->pointer()[0x10000 + offs] & 0x80) ? 2 : 1); - - u8 const gfx(((chr & 0x80) && (ra == 9)) ? 0xFF : m_p_chargen[(ra << 7) | (chr & 0x7F)]); - - // Display a scanline of a character - for (unsigned b = 0; 8 > b; ++b) - { - uint16_t const pixel(BIT(gfx, 7 - b) ? clr : 0); - for (unsigned i = 0; Scale > i; ++i) - *p++ = pixel; - } - } - } -} - -// 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()); - u8 const ra(y % 10); - - // 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((m_beep_state && BIT(m_pia1->b_output(), 5)) ? 1 : 0); - - int const next((y - ra) + ((ra < 4) ? 4 : (ra < 8) ? 8 : 14)); - m_video_timer->adjust(m_screen->time_until_pos((m_screen->height() > next) ? next : 0, 0)); -} - -TIMER_CALLBACK_MEMBER(osborne1_state::acia_rxc_txc_callback) -{ - m_acia_rxc_txc_state = m_acia_rxc_txc_state ? 0 : 1; - update_acia_rxc_txc(); -} - - -TILE_GET_INFO_MEMBER(osborne1_state::get_tile_info) -{ - // The gfxdecode and tilemap aren't actually used for drawing, they just look nice in the F4 GFX viewer - tileinfo.set(0, m_ram->pointer()[0xF000 | tile_index] & 0x7F, 0, 0); -} - - -bool osborne1_state::set_rom_mode(u8 value) -{ - if (value != m_rom_mode) - { - m_rom_mode = value; - m_bank_0xxx->set_entry(m_rom_mode); - m_bank_1xxx->set_entry(m_rom_mode); - return true; - } - else - { - return false; - } -} - -bool osborne1_state::set_bit_9(u8 value) -{ - if (value != m_bit_9) - { - m_bit_9 = value; - m_bank_fxxx->set_entry(m_bit_9); - return true; - } - else - { - return false; - } -} - -void osborne1_state::update_irq() -{ - if (m_pia0->irq_a_state()) - m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xF0); // Z80 - else if (m_pia1->irq_a_state()) - m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xF8); // Z80 - else if (m_acia_irq_state) - m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, 0xFC); // Z80 - else - m_maincpu->set_input_line_and_vector(INPUT_LINE_IRQ0, CLEAR_LINE, 0xFE); // Z80 -} - -void osborne1_state::update_acia_rxc_txc() -{ - m_acia->write_rxc(m_acia_rxc_txc_state); - m_acia->write_txc(m_acia_rxc_txc_state); - attoseconds_t const dividend = (ATTOSECONDS_PER_SECOND / 100) * (m_acia_rxc_txc_state ? m_acia_rxc_txc_p_high : m_acia_rxc_txc_p_low); - attoseconds_t const divisor = (15974400 / 100) / m_acia_rxc_txc_div; - m_acia_rxc_txc_timer->adjust(attotime(0, dividend / divisor)); -} - - -MC6845_UPDATE_ROW(osborne1nv_state::crtc_update_row) -{ - rgb_t const *const palette = m_palette->palette()->entry_list_raw(); - uint16_t const base = (ma >> 1) & 0xF80; - uint32_t *p = &bitmap.pix(y); - for (u8 x = 0; x < x_count; ++x) - { - uint16_t const offset = base | ((ma + x) & 0x7F); - u8 const chr = m_ram->pointer()[0xF000 | offset]; - u8 const clr = BIT(m_ram->pointer()[0x10000 | offset], 7) ? 2 : 1; - - u8 const gfx = ((chr & 0x80) && (ra == 9)) ? 0xFF : m_p_nuevo[(ra << 7) | (chr & 0x7F)]; - - for (unsigned bit = 0; 8 > bit; ++bit) - *p++ = palette[BIT(gfx, 7 - bit) ? clr : 0]; - } -} - -MC6845_ON_UPDATE_ADDR_CHANGED(osborne1nv_state::crtc_update_addr_changed) -{ -}