From 4eb493759ecc227b53d00751410d8d93faea9a35 Mon Sep 17 00:00:00 2001 From: AJR Date: Wed, 1 May 2019 21:47:31 -0400 Subject: [PATCH] z100: Various improvements - Render video through CRTC instead of working around it by caching registers - Add cursor - Add video interrupt - Add 8253 timer and associated interrupt - Correct numerous clocks --- src/mame/drivers/z100.cpp | 213 ++++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 90 deletions(-) diff --git a/src/mame/drivers/z100.cpp b/src/mame/drivers/z100.cpp index ff837376bb8..28576325c6a 100644 --- a/src/mame/drivers/z100.cpp +++ b/src/mame/drivers/z100.cpp @@ -145,12 +145,15 @@ ZDIPSW EQU 0FFH ; Configuration dip switches #include "emu.h" #include "cpu/i86/i86.h" +#include "cpu/i8085/i8085.h" +#include "cpu/mcs48/mcs48.h" //#include "bus/rs232/rs232.h" //#include "bus/s100/s100.h" #include "imagedev/floppy.h" #include "machine/6821pia.h" #include "machine/input_merger.h" #include "machine/mc2661.h" +#include "machine/pit8253.h" #include "machine/pic8259.h" #include "machine/wd_fdc.h" #include "video/mc6845.h" @@ -184,22 +187,28 @@ private: virtual void machine_reset() override; virtual void video_start() override; + offs_t vram_map(offs_t offset) const; DECLARE_READ8_MEMBER(z100_vram_r); DECLARE_WRITE8_MEMBER(z100_vram_w); DECLARE_READ8_MEMBER(keyb_data_r); DECLARE_READ8_MEMBER(keyb_status_r); DECLARE_WRITE8_MEMBER(keyb_command_w); - DECLARE_WRITE8_MEMBER(z100_6845_address_w); - DECLARE_WRITE8_MEMBER(z100_6845_data_w); DECLARE_WRITE8_MEMBER(floppy_select_w); DECLARE_WRITE8_MEMBER(floppy_motor_w); + uint8_t tmr_status_r(); + void tmr_status_w(uint8_t data); + DECLARE_WRITE_LINE_MEMBER(timer_flipflop0_w); + DECLARE_WRITE_LINE_MEMBER(timer_flipflop1_w); + void sys_pia_A_w(uint8_t data); + DECLARE_WRITE_LINE_MEMBER(vidint_w); + DECLARE_READ8_MEMBER(get_slave_ack); DECLARE_WRITE8_MEMBER(video_pia_A_w); DECLARE_WRITE8_MEMBER(video_pia_B_w); DECLARE_WRITE_LINE_MEMBER(video_pia_CA2_w); DECLARE_WRITE_LINE_MEMBER(video_pia_CB2_w); - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + MC6845_UPDATE_ROW(update_row); void z100_io(address_map &map); void z100_mem(address_map &map); @@ -222,92 +231,71 @@ private: uint8_t m_display_mask; uint8_t m_flash; uint8_t m_clr_val; - uint8_t m_crtc_vreg[0x100]; - uint8_t m_crtc_index; - uint16_t m_start_addr; + uint8_t m_tmr_status; + uint8_t m_start_addr; + bool m_vidint_enable; floppy_image_device *m_floppy; }; -#define mc6845_h_char_total (m_crtc_vreg[0]) -#define mc6845_h_display (m_crtc_vreg[1]) -#define mc6845_h_sync_pos (m_crtc_vreg[2]) -#define mc6845_sync_width (m_crtc_vreg[3]) -#define mc6845_v_char_total (m_crtc_vreg[4]) -#define mc6845_v_total_adj (m_crtc_vreg[5]) -#define mc6845_v_display (m_crtc_vreg[6]) -#define mc6845_v_sync_pos (m_crtc_vreg[7]) -#define mc6845_mode_ctrl (m_crtc_vreg[8]) -#define mc6845_tile_height (m_crtc_vreg[9]+1) -#define mc6845_cursor_y_start (m_crtc_vreg[0x0a]) -#define mc6845_cursor_y_end (m_crtc_vreg[0x0b]) -#define mc6845_start_addr (((m_crtc_vreg[0x0c]<<8) & 0xff00) | (m_crtc_vreg[0x0d] & 0xff)) -#define mc6845_cursor_addr (((m_crtc_vreg[0x0e]<<8) & 0xff00) | (m_crtc_vreg[0x0f] & 0xff)) -#define mc6845_light_pen_addr (((m_crtc_vreg[0x10]<<8) & 0xff00) | (m_crtc_vreg[0x11] & 0xff)) -#define mc6845_update_addr (((m_crtc_vreg[0x12]<<8) & 0xff00) | (m_crtc_vreg[0x13] & 0xff)) - void z100_state::video_start() { m_gvram = make_unique_clear(0x30000); + + m_vidint_enable = false; } -uint32_t z100_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +MC6845_UPDATE_ROW(z100_state::update_row) { - int x,y,xi,yi; - int dot; - int i; + uint32_t *const pix = &bitmap.pix32(y); - bitmap.fill(0, cliprect); - - for(y=0;y> (7-xi)) & 1) << i; // b, r, g - - dot &= m_display_mask; - - /* overwrite */ - if(m_flash) - dot = m_display_mask; - - if(y*mc6845_tile_height+yi < 216 && x*8+xi < 640) /* TODO: safety check */ - bitmap.pix16(y*mc6845_tile_height+yi, x*8+xi) = m_palette->pen(dot); - } + dot = m_display_mask; } + else + { + for (int i = 0; i < 3; i++) + dot |= ((m_gvram[((x + ma) & 0xfff) << 4 | (ra & 0xf) | (0x10000*i)] >> (7-xi)) & 1) << i; // b, r, g + + if (x == cursor_x) + dot ^= 7; + + dot &= m_display_mask; + } + + pix[x*8+xi] = m_palette->pen(dot); } } +} - return 0; +offs_t z100_state::vram_map(offs_t offset) const +{ + // FIXME: part of this calculation is actually done through a ROM + return (offset & 0x30000) | ((((offset & 0x007f) << 4 | (offset & 0x0780) >> 7) + ((offset & 0xf800) >> 11) * 0x0500 + (uint16_t(m_start_addr) << 8)) & 0xffff); } READ8_MEMBER( z100_state::z100_vram_r ) { - return m_gvram[offset]; + return m_gvram[vram_map(offset)]; } WRITE8_MEMBER( z100_state::z100_vram_w ) { if(m_vram_enable) { - int i; - + offset = vram_map(offset); m_gvram[offset] = data; - for(i=0;i<3;i++) + for (int i = 0; i < 3; i++) { - if(m_gbank & (1 << i)) + if (BIT(m_gbank, i)) m_gvram[((offset) & 0xffff)+0x10000*i] = data; } } @@ -356,19 +344,6 @@ WRITE8_MEMBER( z100_state::keyb_command_w ) // ... } -WRITE8_MEMBER( z100_state::z100_6845_address_w ) -{ - data &= 0x1f; - m_crtc_index = data; - m_crtc->address_w(data); -} - -WRITE8_MEMBER( z100_state::z100_6845_data_w ) -{ - m_crtc_vreg[m_crtc_index] = data; - m_crtc->register_w(data); -} - // todo: side select? WRITE8_MEMBER( z100_state::floppy_select_w ) @@ -383,6 +358,49 @@ WRITE8_MEMBER( z100_state::floppy_motor_w ) m_floppy->mon_w(!BIT(data, 1)); } +uint8_t z100_state::tmr_status_r() +{ + return m_tmr_status; +} + +void z100_state::tmr_status_w(uint8_t data) +{ + m_tmr_status &= data & 3; + if (m_tmr_status == 0) + m_picm->ir2_w(0); +} + +WRITE_LINE_MEMBER(z100_state::timer_flipflop0_w) +{ + if (state) + { + m_tmr_status |= 1; + m_picm->ir2_w(1); + } +} + +WRITE_LINE_MEMBER(z100_state::timer_flipflop1_w) +{ + if (state) + { + m_tmr_status |= 2; + m_picm->ir2_w(1); + } +} + +void z100_state::sys_pia_A_w(uint8_t data) +{ + m_vidint_enable = BIT(data, 5); + if (!m_vidint_enable) + m_pia[1]->ca2_w(0); +} + +WRITE_LINE_MEMBER(z100_state::vidint_w) +{ + if (state && m_vidint_enable) + m_pia[1]->ca2_w(1); +} + void z100_state::z100_io(address_map &map) { map.unmap_value_high(); @@ -403,11 +421,11 @@ void z100_state::z100_io(address_map &map) // AM_RANGE (0xcd, 0xce) ET-100 CRT Controller // AM_RANGE (0xd4, 0xd7) ET-100 Trainer Parallel I/O map(0xd8, 0xdb).rw(m_pia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); //video board - map(0xdc, 0xdc).w(FUNC(z100_state::z100_6845_address_w)); - map(0xdd, 0xdd).w(FUNC(z100_state::z100_6845_data_w)); + map(0xdc, 0xdc).w(m_crtc, FUNC(mc6845_device::address_w)); + map(0xdd, 0xdd).w(m_crtc, FUNC(mc6845_device::register_w)); // AM_RANGE (0xde, 0xde) light pen map(0xe0, 0xe3).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); //main board -// AM_RANGE (0xe4, 0xe7) 8253 PIT + map(0xe4, 0xe7).rw("pit", FUNC(pit8253_device::read), FUNC(pit8253_device::write)); map(0xe8, 0xeb).rw(m_epci[0], FUNC(mc2661_device::read), FUNC(mc2661_device::write)); map(0xec, 0xef).rw(m_epci[1], FUNC(mc2661_device::read), FUNC(mc2661_device::write)); map(0xf0, 0xf1).rw(m_pics, FUNC(pic8259_device::read), FUNC(pic8259_device::write)); @@ -415,7 +433,7 @@ void z100_state::z100_io(address_map &map) map(0xf4, 0xf4).r(FUNC(z100_state::keyb_data_r)); // -> 8041 MCU map(0xf5, 0xf5).rw(FUNC(z100_state::keyb_status_r), FUNC(z100_state::keyb_command_w)); // AM_RANGE (0xf6, 0xf6) expansion ROM is present (bit 0, active low) -// AM_RANGE (0xfb, 0xfb) timer irq status + map(0xfb, 0xfb).rw(FUNC(z100_state::tmr_status_r), FUNC(z100_state::tmr_status_w)); // AM_RANGE (0xfc, 0xfc) memory latch // AM_RANGE (0xfd, 0xfd) Hi-address latch // AM_RANGE (0xfe, 0xfe) Processor swap port @@ -626,7 +644,7 @@ WRITE8_MEMBER( z100_state::video_pia_A_w ) WRITE8_MEMBER( z100_state::video_pia_B_w ) { - m_start_addr = data << 4; //<- TODO + m_start_addr = data; } /* clear screen */ @@ -667,46 +685,61 @@ static void z100_floppies(device_slot_interface &device) void z100_state::z100(machine_config &config) { /* basic machine hardware */ - I8088(config, m_maincpu, 14.318181_MHz_XTAL / 3); + I8088(config, m_maincpu, 15_MHz_XTAL / 3); // 5 MHz or 8 MHz depending on XTAL m_maincpu->set_addrmap(AS_PROGRAM, &z100_state::z100_mem); m_maincpu->set_addrmap(AS_IO, &z100_state::z100_io); m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb)); + I8085A(config, "cpu85", 10_MHz_XTAL).set_disable(); + + I8041(config, "upi", 6_MHz_XTAL).set_disable(); + /* video hardware */ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(50); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ - screen.set_size(640, 480); - screen.set_visarea(0, 640-1, 0, 480-1); - screen.set_screen_update(FUNC(z100_state::screen_update)); - screen.set_palette(m_palette); + screen.set_raw(14.112_MHz_XTAL, 912, 0, 640, 258, 0, 216); + screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update)); PALETTE(config, m_palette).set_entries(8); /* devices */ - MC6845(config, m_crtc, 14.318181_MHz_XTAL / 8); /* unknown clock, hand tuned to get ~50/~60 fps */ + MC6845(config, m_crtc, 14.112_MHz_XTAL / 8); // 68A45 m_crtc->set_screen("screen"); m_crtc->set_show_border_area(false); m_crtc->set_char_width(8); + m_crtc->set_update_row_callback(FUNC(z100_state::update_row), this); + m_crtc->out_vsync_callback().set(FUNC(z100_state::vidint_w)); - PIC8259(config, m_picm, 0); + PIC8259(config, m_picm); m_picm->out_int_callback().set_inputline(m_maincpu, 0); m_picm->in_sp_callback().set_constant(1); m_picm->read_slave_ack_callback().set(FUNC(z100_state::get_slave_ack)); - PIC8259(config, m_pics, 0); + PIC8259(config, m_pics); m_pics->out_int_callback().set(m_picm, FUNC(pic8259_device::ir3_w)); m_pics->in_sp_callback().set_constant(0); - PIA6821(config, m_pia[0], 0); + pit8253_device &pit(PIT8253(config, "pit")); + pit.set_clk<0>(4_MHz_XTAL / 16); + pit.out_handler<0>().set(FUNC(z100_state::timer_flipflop0_w)); + pit.out_handler<0>().append("pit", FUNC(pit8253_device::write_clk1)); + pit.set_clk<2>(4_MHz_XTAL / 16); + pit.out_handler<2>().set(FUNC(z100_state::timer_flipflop1_w)); + + PIA6821(config, m_pia[0]); m_pia[0]->writepa_handler().set(FUNC(z100_state::video_pia_A_w)); m_pia[0]->writepb_handler().set(FUNC(z100_state::video_pia_B_w)); m_pia[0]->ca2_handler().set(FUNC(z100_state::video_pia_CA2_w)); m_pia[0]->cb2_handler().set(FUNC(z100_state::video_pia_CB2_w)); - PIA6821(config, m_pia[1], 0); + PIA6821(config, m_pia[1]); + m_pia[1]->irqa_handler().set("keydspyint", FUNC(input_merger_device::in_w<1>)); + m_pia[1]->irqb_handler().set(m_picm, FUNC(pic8259_device::ir7_w)); + m_pia[1]->writepa_handler().set(FUNC(z100_state::sys_pia_A_w)); - FD1797(config, m_fdc, 1_MHz_XTAL); + input_merger_device &keydspyint(INPUT_MERGER_ANY_HIGH(config, "keydspyint")); + keydspyint.output_handler().set(m_picm, FUNC(pic8259_device::ir6_w)); + + FD1797(config, m_fdc, 4_MHz_XTAL / 4); FLOPPY_CONNECTOR(config, m_floppies[0], z100_floppies, "dd", floppy_image_device::default_floppy_formats); FLOPPY_CONNECTOR(config, m_floppies[1], z100_floppies, "dd", floppy_image_device::default_floppy_formats); @@ -733,8 +766,8 @@ ROM_START( z100 ) ROM_REGION( 0x4000, "ipl", ROMREGION_ERASEFF ) ROM_LOAD( "intel-d27128-1.bin", 0x0000, 0x4000, CRC(b21f0392) SHA1(69e492891cceb143a685315efe0752981a2d8143)) - ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF ) //8041 - ROM_LOAD( "mcu", 0x0000, 0x1000, NO_DUMP ) + ROM_REGION( 0x0400, "upi", ROMREGION_ERASEFF ) // 8041A keyboard controller + ROM_LOAD( "444-109.u284", 0x0000, 0x0400, NO_DUMP ) ROM_END void z100_state::driver_init()