From 5dfa023808a3b37f8093052357c46b886a854025 Mon Sep 17 00:00:00 2001 From: Frodevan <32438575+Frodevan@users.noreply.github.com> Date: Sat, 6 Jun 2020 17:26:12 +0200 Subject: Graphics emulation for Tiki-100 redone to be accurate down to whole scanlines. Also fixed a small inacuracy in the keyboard. (#6785) --- src/mame/drivers/tiki100.cpp | 151 +++++++++++++++++++++++-------------------- src/mame/includes/tiki100.h | 8 ++- 2 files changed, 86 insertions(+), 73 deletions(-) diff --git a/src/mame/drivers/tiki100.cpp b/src/mame/drivers/tiki100.cpp index df53c4d54e9..122063589ed 100644 --- a/src/mame/drivers/tiki100.cpp +++ b/src/mame/drivers/tiki100.cpp @@ -1,12 +1,18 @@ // license:BSD-3-Clause -// copyright-holders:Curt Coder +// copyright-holders:Curt Coder, Frode van der Meeren /*************************************************************************** Tiki 100 12/05/2009 Skeleton driver. - http://www.djupdal.org/tiki/ + Most of the driver is written by Curt Coder. + + 2020-06-02: + Screen-drawing redone by Frode van der Meeren. + There is still some work that needs to get this + even more accurate, but it's mostly down to + triggering update at the right times. ****************************************************************************/ @@ -14,7 +20,6 @@ TODO: - - palette RAM should be written during HBLANK - winchester hard disk - analog/digital I/O - light pen @@ -185,13 +190,13 @@ READ8_MEMBER( tiki100_state::keyboard_r ) { uint8_t data = 0xff; - if (m_keylatch < 12) + if (m_keylatch < 13) { data = m_y[m_keylatch]->read(); } m_keylatch++; - if (m_keylatch == 12) m_keylatch = 0; + if (m_keylatch == 16) m_keylatch = 0; // Column selected by a 4-bit counter return data; } @@ -219,14 +224,6 @@ WRITE8_MEMBER( tiki100_state::video_mode_w ) */ m_mode = data; - - if (BIT(data, 7)) - { - int color = data & 0x0f; - uint8_t colordata = ~m_palette_val; - - m_palette->set_pen_color(color, pal3bit(colordata >> 5), pal3bit(colordata >> 2), pal2bit(colordata >> 0)); - } } WRITE8_MEMBER( tiki100_state::palette_w ) @@ -258,7 +255,7 @@ WRITE8_MEMBER( tiki100_state::system_w ) 0 DRIS0 drive select 0 1 DRIS1 drive select 1 2 _ROME enable ROM at 0000-3fff - 3 VIRE enable video RAM at 0000-7fff + 3 VIRE enable video RAM at 0000-7fff or 4000-bfff 4 SDEN single density select (0=DD, 1=SD) 5 _LMP0 GRAFIKK key led 6 MOTON floppy motor @@ -323,7 +320,10 @@ static INPUT_PORTS_START( tiki100 ) 10 | + (num) | - (num) | * (num) | 7 (num) | 8 (num) | 9 (num) | % (num) | = (num) | 11 | 4 (num) | 5 (num) | 6 (num) | HTAB | 1 (num) | 0 (num) | . (num) | | 12 | HJEM | H?YRE | 2 (num) | 3 (num) | ENTER | | | | + 13 | | | | | | | | | ----+---------+---------+---------+---------+---------+---------+---------+---------+ + + Unused bits may return some fixed values, an undocumented system call will read and return them. */ PORT_START("Y1") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) @@ -445,6 +445,16 @@ static INPUT_PORTS_START( tiki100 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_START("Y13") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_START("ST") PORT_CONFNAME( 0x01, 0x01, "DART TxCA") PORT_CONFSETTING( 0x00, "BAR0" ) @@ -453,71 +463,69 @@ INPUT_PORTS_END /* Video */ -uint32_t tiki100_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +TIMER_DEVICE_CALLBACK_MEMBER( tiki100_state::scanline_start ) { - const rgb_t *palette = m_palette->palette()->entry_list_raw(); - uint16_t addr = (m_scroll << 7); - int sx, y, pixel, mode = (m_mode >> 4) & 0x03; - - for (y = 0; y < 256; y++) - { - for (sx = 0; sx < 128; sx++) - { - uint8_t data = m_video_ram[addr & TIKI100_VIDEORAM_MASK]; + // TODO: Optional assertion of VSYNC on one of the PIO-pins, as used by some demos + //int scanline = param; - switch (mode) - { - case 0: - for (pixel = 0; pixel < 8; pixel++) - { - int x = (sx * 8) + pixel; + // TODO: use TIMER to trigger this every 16-pixel chunk (20MHz/16) instead of once at the end of the scanline + m_screen->update_now(); - bitmap.pix32(y, x) = palette[0]; - } - break; + // This point is by the end of a line. Changes in palette are applied here. + if (BIT(m_mode, 7)) + { + int color = m_mode & 0x0f; + uint8_t colordata = ~m_palette_val; - case 1: /* 1024x256x2 */ - for (pixel = 0; pixel < 8; pixel++) - { - int x = (sx * 8) + pixel; - int color = BIT(data, 0); + m_palette->set_pen_color(color, pal3bit(colordata >> 5), pal3bit(colordata >> 2), pal2bit(colordata >> 0)); + } +} - bitmap.pix32(y, x) = palette[color]; +uint32_t tiki100_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + // + // Emulates the pixel-shifter and row/column counters from a + // starting point on screen to an ending point on screen. + // + // For the most accurate results, this should be run once for + // every 16-pixel chunk, but per the spring of 2020 there is + // only one demo that require this degree of accuracy. + // + // - data >>= 1; - } - break; + const rgb_t *palette = m_palette->palette()->entry_list_raw(); - case 2: /* 512x256x4 */ - for (pixel = 0; pixel < 4; pixel++) + for (int vaddr = cliprect.min_y; vaddr <= cliprect.max_y; vaddr++) + { + // This is at the start of a line + int haddr = (cliprect.min_x>>4); + int haddr_end = (cliprect.max_x>>4); + for (; haddr <= haddr_end; haddr++) + { + // This is at the start of a 16-dot cluster. Changes in m_scroll and m_video_ram come into effect here. + uint16_t addr = ((vaddr+m_scroll)<<7) | (haddr<<1); + uint16_t data = (m_video_ram[(addr+1) & TIKI100_VIDEORAM_MASK]<<8) | m_video_ram[addr & TIKI100_VIDEORAM_MASK]; + for(int dot = 0; dot < 16; dot++) + { + // This is at the start of a dot. Changes in m_mode are applied at this point. + int mode = (m_mode >> 4) & 0x03; + if((mode == 1) || (!(dot&0x01) && mode == 2) || (!(dot&0x03) && mode == 3)) { - int x = (sx * 8) + (pixel * 2); - int color = data & 0x03; - - bitmap.pix32(y, x) = palette[color]; - bitmap.pix32(y, x + 1) = palette[color]; - - data >>= 2; + // This is the point when a pixel is latched from the dot-shifter. + // + // For the sake of readability: + // mode == 0: keep the old pixel + // mode == 1: latch new pixel once per dot + // mode == 2: latch new pixel once per 2 dots + // mode == 3: latch new pixel once per 4 dots + // + m_current_pixel = data&0x0F; } - break; + bitmap.pix32(vaddr, (haddr<<4) + dot) = palette[m_current_pixel&0x0F]; - case 3: /* 256x256x16 */ - for (pixel = 0; pixel < 2; pixel++) - { - int x = (sx * 8) + (pixel * 4); - int color = data & 0x0f; - - bitmap.pix32(y, x) = palette[color]; - bitmap.pix32(y, x + 1) = palette[color]; - bitmap.pix32(y, x + 2) = palette[color]; - bitmap.pix32(y, x + 3) = palette[color]; - - data >>= 4; - } - break; + // This will run the dot-shifter and add the TEST-pattern to the upper bits (usually hidden by palette). + data = (data>>1)|((haddr&0x02)<<14); } - - addr++; } } @@ -709,9 +717,10 @@ void tiki100_state::tiki100(machine_config &config) m_maincpu->set_daisy_config(tiki100_daisy_chain); /* video hardware */ - screen_device &screen(SCREEN(config, SCREEN_TAG, SCREEN_TYPE_RASTER)); - screen.set_raw(20_MHz_XTAL, 1280, 0, 1024, 312, 0, 256); - screen.set_screen_update(FUNC(tiki100_state::screen_update)); + TIMER(config, "scantimer").configure_scanline(FUNC(tiki100_state::scanline_start), "screen", 0, 1); + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_raw(20_MHz_XTAL, 1280, 0, 1024, 312, 0, 256); + m_screen->set_screen_update(FUNC(tiki100_state::screen_update)); PALETTE(config, m_palette).set_entries(16); TIKI100_BUS(config, m_exp, 0); diff --git a/src/mame/includes/tiki100.h b/src/mame/includes/tiki100.h index acf96781504..9a6f350a0b9 100644 --- a/src/mame/includes/tiki100.h +++ b/src/mame/includes/tiki100.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Curt Coder +// copyright-holders:Curt Coder, Frode van der Meeren #ifndef MAME_INCLUDES_TIKI100_H #define MAME_INCLUDES_TIKI100_H @@ -46,6 +46,7 @@ class tiki100_state : public driver_device public: tiki100_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), + m_screen(*this, "screen"), m_maincpu(*this, Z80_TAG), m_ctc(*this, Z80CTC_TAG), m_fdc(*this, FD1797_TAG), @@ -95,6 +96,7 @@ private: TIMER_DEVICE_CALLBACK_MEMBER( ctc_tick ); TIMER_DEVICE_CALLBACK_MEMBER( tape_tick ); + TIMER_DEVICE_CALLBACK_MEMBER( scanline_start ); DECLARE_WRITE_LINE_MEMBER(write_centronics_ack); DECLARE_WRITE_LINE_MEMBER(write_centronics_busy); @@ -108,6 +110,7 @@ private: virtual void machine_start() override; virtual void machine_reset() override; + required_device m_screen; required_device m_maincpu; required_device m_ctc; required_device m_fdc; @@ -123,7 +126,7 @@ private: required_memory_region m_rom; required_memory_region m_prom; optional_shared_ptr m_video_ram; - required_ioport_array<12> m_y; + required_ioport_array<13> m_y; required_ioport m_st_io; required_device m_palette; output_finder<2> m_leds; @@ -144,6 +147,7 @@ private: uint8_t m_scroll; uint8_t m_mode; uint8_t m_palette_val; + uint8_t m_current_pixel; // keyboard state int m_keylatch; -- cgit v1.2.3