From 63ff9648ed026d1e5905c717bb1de477a4fb984f Mon Sep 17 00:00:00 2001 From: fulivi Date: Tue, 7 Aug 2018 18:54:40 +0200 Subject: hp_ipc: lots of improvements to HP-1LL3 GPU --- src/devices/video/hp1ll3.cpp | 875 +++++++++++++++++++++++++++++-------------- src/devices/video/hp1ll3.h | 48 ++- src/mame/drivers/hp_ipc.cpp | 17 +- 3 files changed, 633 insertions(+), 307 deletions(-) diff --git a/src/devices/video/hp1ll3.cpp b/src/devices/video/hp1ll3.cpp index 380fc6aa250..136d8f0e27d 100644 --- a/src/devices/video/hp1ll3.cpp +++ b/src/devices/video/hp1ll3.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Sergey Svishchev +// copyright-holders:Sergey Svishchev, F. Ulivi /* HP 1LL3-0005 GPU emulation. @@ -47,12 +47,12 @@ * 0 -- no data * 1 -- write 1 word of data, then command * 2 -- write 2 words of data, then command - * 3 -- write command, then 12 words of data (= CONF only?) + * 3 -- write command, then 12 words of data (= CONF only) * 4 -- write 1 word of data, then command, then write X words of data, then write NOP * * (read) * - * 3 -- ??? + * 3 -- write command, then read 2 words of data (X & Y coordinates) * 4 -- write 1 word of data, then command, then read X words of data, then write NOP */ #define NOP 0 // type 0 @@ -62,39 +62,39 @@ #define WRMEM 7 // type 4, write GPU memory at offset, terminate by NOP #define RDMEM 8 // type 4, read GPU memory from offset, terminate by NOP #define WRSAD 9 // type 1, set screen area start address -#define WRORG 10 // type 1, set ??? +#define WRORG 10 // type 1, set raster start address #define WRDAD 11 // type 1, set data area start address (16x16 area fill, sprite and cursor) #define WRRR 12 // type 1, set replacement rule (rasterop) #define MOVEP 13 // type 2, move pointer -#define IMOVEP 14 +#define IMOVEP 14 // type 2, incremental move pointer #define DRAWP 15 // type 2, draw line -#define IDRAWP 16 -#define RDP 17 +#define IDRAWP 16 // type 2, incremental draw line +#define RDP 17 // type 3, read pointer position #define WRUDL 18 // type 1, set user-defined line pattern (16-bit) -#define WRWINSIZ 19 // type 2, set ??? -#define WRWINORG 20 // type 2, set ??? -#define COPY 21 // type 2 +#define WRWINSIZ 19 // type 2, set window size +#define WRWINORG 20 // type 2, set window origin +#define COPY 21 // type 2, block copy #define FILL 22 // type 1, fill area -#define FRAME 23 // type _, draw rectangle -#define SCROLUP 24 // type 2 -#define SCROLDN 25 // type 2 -#define SCROLLF 26 // type 2 -#define SCROLRT 27 // type 2 -#define RDWIN 28 // type 1 -#define WRWIN 29 // type 1 +#define FRAME 23 // type 0, draw rectangle +#define SCROLUP 24 // type 2, scroll up +#define SCROLDN 25 // type 2, scroll down +#define SCROLLF 26 // type 2, scroll left +#define SCROLRT 27 // type 2, scroll right +#define RDWIN 28 // type 4, read window raster +#define WRWIN 29 // type 4, write window raster #define RDWINPARM 30 -#define CR 31 -#define CRLFx 32 +#define CR 31 // type 0, carriage return +#define CRLFx 32 // type 0, CR + LF #define LABEL 36 // type 1, draw text -#define ENSP 38 // type 0, enable sprite +#define ENSP 38 // type 1, enable sprite #define DISSP 39 // type 0, disable sprite #define MOVESP 40 // type 2, move sprite -#define IMOVESP 41 -#define RDSP 42 -#define DRAWPX 43 // type _, draw single pixel +#define IMOVESP 41 // type 2, incremental move sprite +#define RDSP 42 // type 3, read sprite position +#define DRAWPX 43 // type 2, draw single pixel #define WRFAD 44 // type 1, set font area start address -#define ENCURS 45 // type 0 -#define DISCURS 46 // type 0 +#define ENCURS 45 // type 2, enable cursor +#define DISCURS 46 // type 0, disable cursor #define ID 63 @@ -126,8 +126,8 @@ #define RR_NAND 0xe #define RR_FORCE_ONE 0xf -#define WS 16 // bits in a word - +constexpr unsigned WS = 16; // bits in a word +constexpr uint16_t MSB_MASK = 0x8000; // Mask of MSB //************************************************************************** // MACROS / CONSTANTS @@ -145,10 +145,29 @@ } \ } while (0) - -// enough for 9807a and 9808a both. -#define HPGPU_VRAM_SIZE (16384 * 4) - +// This is the size for 9807. To be made configurable. +#define HPGPU_VRAM_SIZE 16384 + +// Index of words in configuration vector +constexpr unsigned CONF_HOR_0 = 0; // Horizontal timing, 1st word +constexpr unsigned CONF_HOR_1 = 1; // Horizontal timing, 2nd word +constexpr unsigned CONF_HOR_2 = 2; // Horizontal timing, 3rd word +constexpr unsigned CONF_HOR_3 = 3; // Horizontal timing, 4th word +constexpr unsigned CONF_VER_0 = 4; // Vertical timing, 1st word +constexpr unsigned CONF_VER_1 = 5; // Vertical timing, 2nd word +constexpr unsigned CONF_VER_2 = 6; // Vertical timing, 3rd word +constexpr unsigned CONF_VER_3 = 7; // Vertical timing, 4th word +constexpr unsigned CONF_WPL = 8; // Words per line +constexpr unsigned CONF_LINES = 9; // Lines +constexpr unsigned CONF_RAM_SIZE = 10; // RAM size (?) + +// Fields of hor/ver timing words +constexpr uint16_t HV_CNT_MASK = 0x3ff; // Mask of counter part +constexpr uint16_t HV_ZONE_MASK = 0xc000; // Mask of zone part +constexpr uint16_t HV_ZONE_0 = 0x0000; // Value for zone 0 +constexpr uint16_t HV_ZONE_1 = 0x4000; // Value for zone 1 +constexpr uint16_t HV_ZONE_2 = 0x8000; // Value for zone 2 +constexpr uint16_t HV_ZONE_3 = 0xc000; // Value for zone 3 //************************************************************************** // GLOBAL VARIABLES @@ -186,33 +205,32 @@ void hp1ll3_device::device_start() screen().register_screen_bitmap(m_bitmap); - m_cursor.allocate(16, 16); - m_sprite.allocate(16, 16); - - m_videoram = std::make_unique(HPGPU_VRAM_SIZE*2); // x2 size to make WRWIN/RDWIN easier + m_videoram = std::make_unique(HPGPU_VRAM_SIZE); + save_pointer(NAME(m_videoram) , HPGPU_VRAM_SIZE); + m_ram_addr_mask = 0x3fff; m_horiz_pix_total = visarea.max_x + 1; m_vert_pix_total = visarea.max_y + 1; } void hp1ll3_device::device_reset() { - m_input_ptr = m_command = 0; + m_io_ptr = m_command = 0; m_sad = m_fad = m_dad = m_org = m_rr = m_udl = 0; m_enable_video = m_enable_cursor = m_enable_sprite = m_busy = false; } - -inline void hp1ll3_device::point(int x, int y, int px) +uint16_t hp1ll3_device::get_pix_addr(uint16_t x , uint16_t y) const { - uint16_t offset = m_sad; + return m_org + y * m_conf[ CONF_WPL ] + x / WS; +} - offset += y*(m_horiz_pix_total/16) + (x >> 4); +inline void hp1ll3_device::point(int x, int y, bool pix, const uint16_t masks[]) +{ + uint16_t offset = get_pix_addr(x, y); + uint16_t pix_mask = MSB_MASK >> (x % WS); - if (px) - m_videoram[offset] |= (1 << (15-(x%16))); - else - m_videoram[offset] &= ~(1 << (15-(x%16))); + rmw_rop(offset, pix ? ~0 : 0, pix_mask, masks); } // Bresenham algorithm -- from ef9365.cpp @@ -226,6 +244,11 @@ void hp1ll3_device::line(int x1, int y1, int x2, int y2) int diago,horiz; unsigned char c1; + uint16_t rop_masks[ 4 ]; + get_rop_masks(m_rr, rop_masks); + + uint16_t udl_scan = MSB_MASK; + c1=0; incy=1; @@ -283,7 +306,11 @@ void hp1ll3_device::line(int x1, int y1, int x2, int y2) { do { - point(y,x,m_udl); + point(y,x,m_udl & udl_scan,rop_masks); + udl_scan >>= 1; + if (!udl_scan) { + udl_scan = MSB_MASK; + } if( e > 0 ) { @@ -303,7 +330,11 @@ void hp1ll3_device::line(int x1, int y1, int x2, int y2) { do { - point(x,y,m_udl); + point(x,y,m_udl & udl_scan,rop_masks); + udl_scan >>= 1; + if (!udl_scan) { + udl_scan = MSB_MASK; + } if( e > 0 ) { @@ -323,127 +354,289 @@ void hp1ll3_device::line(int x1, int y1, int x2, int y2) return; } -void hp1ll3_device::fill(int org_x, int org_y, int w, int h, int arg) +void hp1ll3_device::label(uint8_t chr, int width) { - uint16_t gfx, offset, mask, max_x = org_x + w; - - if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); - - for (int y = org_y; y < org_y + h; y++) { - gfx = m_videoram[m_dad + (0x10 * arg) + y%16]; - if (m_rr == RR_COPYINVERTED) gfx ^= 0xffff; - for (int x = org_x; x < max_x;) { - mask = 0xffff; - offset = m_sad + m_org + y * (m_horiz_pix_total/16) + (x >> 4); - - if (offset >= m_sad + (m_vert_pix_total * m_horiz_pix_total/WS)) - DBG_LOG(0,"HPGPU",("buffer overflow in FILL: %04x (%d, %d)\n", offset, 16*x, y)); - - // clipping - if (x == org_x) { - mask >>= (org_x % WS); - x += (WS - (org_x % WS)); - } else { - if ((max_x - x) < WS) { - mask &= ~((1 << (WS - (max_x % WS))) - 1); - } - x += WS; - } - m_videoram[offset] &= ~mask; - m_videoram[offset] |= gfx & mask; - } - } + draw_cursor_sprite(); - if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); + Rectangle clip = get_window(); + Rectangle dst{{ m_cursor_x , m_cursor_y } , { uint16_t(width) , m_fontheight }}; + bitblt(m_fontdata + chr * 16 , 16 , 16 , Point { 0 , 0 } , clip , dst , m_rr); + m_cursor_x += width; + draw_cursor_sprite(); } -// sprite drawing -- source is 16x16 px max, no window clipping -void hp1ll3_device::bitblt(int dstx, int dsty, uint16_t srcaddr, int width, int height, int op) +void hp1ll3_device::wr_video(uint16_t addr , uint16_t v) { - uint16_t gfx, offset, mask; - int max_x, max_y; + m_videoram[ addr & m_ram_addr_mask ] = v; +} - max_x = dstx + width; - if (max_x >= m_horiz_pix_total) - max_x = m_horiz_pix_total; +uint16_t hp1ll3_device::rd_video(uint16_t addr) const +{ + return m_videoram[ addr & m_ram_addr_mask ]; +} - max_y = dsty + height; - if (max_y >= m_vert_pix_total) - max_y = m_vert_pix_total; +void hp1ll3_device::get_rop_masks(uint16_t rop , uint16_t masks[]) +{ + masks[ 0 ] = BIT(rop , 0) ? ~0 : 0; + masks[ 1 ] = BIT(rop , 1) ? ~0 : 0; + masks[ 2 ] = BIT(rop , 2) ? ~0 : 0; + masks[ 3 ] = BIT(rop , 3) ? ~0 : 0; +} - for (int y = dsty; y < max_y; y++) { - mask = 0xffff; - gfx = m_videoram[srcaddr + y - dsty] & mask; - offset = m_sad + y * (m_horiz_pix_total/16) + (dstx >> 4); +uint16_t hp1ll3_device::apply_rop(uint16_t old_pix , uint16_t new_pix , uint16_t glob_mask , const uint16_t masks[]) +{ + uint16_t diff0 = old_pix & new_pix; + uint16_t diff1 = ~old_pix & new_pix; + uint16_t diff2 = old_pix & ~new_pix; + uint16_t diff3 = ~old_pix & ~new_pix; + + // The idea here is that ROP is forced to be "RR_OLD" for all zero bits in glob_mask + // so that the corresponding bits in new_pix are ignored + return + ((masks[ 0 ] | ~glob_mask) & diff0) | + (masks[ 1 ] & glob_mask & diff1) | + ((masks[ 2 ] | ~glob_mask) & diff2) | + (masks[ 3 ] & glob_mask & diff3); +} - if (offset >= m_sad + (m_vert_pix_total * m_horiz_pix_total/16)) - DBG_LOG(0,"HPGPU",("buffer overflow in bitblt: %04x (%d, %d)\n", offset, 16*dstx, y)); +void hp1ll3_device::rmw_rop(uint16_t addr , uint16_t new_pix , uint16_t glob_mask , const uint16_t masks[]) +{ + wr_video(addr , apply_rop(rd_video(addr), new_pix, glob_mask, masks)); +} - // are we crossing word boundary? - if (dstx % 16) { - if (op == RR_XOR) - { - m_videoram[offset ] ^= gfx >> (dstx % 16); - m_videoram[offset + 1] ^= gfx << (16 - (dstx % 16)); - } - } else { - if (op == RR_XOR) - { - m_videoram[offset] ^= (gfx & mask); - } +void hp1ll3_device::clip_coord(int size_1 , int& p1 , int origin_clip , int size_clip , int& origin_2 , int& size_2) const +{ + // origin_1 is implicitly 0 + int corner_2 = origin_2 + size_2; + // Clip origin_2 & p1 w.r.t. clip rectangle + int t = origin_2 - origin_clip; + if (t < 0) { + p1 -= t; + origin_2 = origin_clip; + } + // Clip size_2 w.r.t. clip rectangle + int corner_clip = origin_clip + size_clip; + if (corner_2 > corner_clip) { + size_2 = corner_clip - origin_2; + } + // Clip size_2 w.r.t. rectangle 1 (whose origin is 0,0) + t = p1 + size_2 - size_1; + if (t > 0) { + size_2 -= t; + } +} + +bool hp1ll3_device::bitblt(uint16_t src_base_addr , unsigned src_width , unsigned src_height , Point src_p , + const Rectangle& clip_rect , const Rectangle& dst_rect , uint16_t rop , bool use_m_org) +{ + DBG_LOG(3,0,("bitblt %04x,%u,%u,(%u,%u),(%u,%u,%u,%u),(%u,%u,%u,%u),%u\n" , src_base_addr , + src_width , + src_height , + src_p.x , + src_p.y , + clip_rect.origin.x , clip_rect.origin.y , clip_rect.size.x , clip_rect.size.y , + dst_rect.origin.x , dst_rect.origin.y , dst_rect.size.x , dst_rect.size.y , + rop)); + int src_x = src_p.x; + int dst_x = dst_rect.origin.x; + int dst_width = dst_rect.size.x; + int src_y = src_p.y; + int dst_y = dst_rect.origin.y; + int dst_height = dst_rect.size.y; + // Clip x-coordinates + clip_coord(src_width, src_x, clip_rect.origin.x, clip_rect.size.x, dst_x, dst_width); + // Clip y-coordinates + clip_coord(src_height, src_y, clip_rect.origin.y, clip_rect.size.y, dst_y, dst_height); + + DBG_LOG(3,0,("bitblt (%u,%u) (%u,%u,%u,%u)\n" , src_x , src_y , + dst_x , dst_y , dst_width , dst_height)); + if (dst_width <= 0 || dst_height <= 0) { + return false; + } + + unsigned dst_rounded_width = m_conf[ CONF_WPL ] * WS; + + // p1_pix & p2_pix point to a uniquely identified pixel in video RAM + unsigned p1_pix = unsigned(src_base_addr) * WS + src_x + src_width * src_y; + unsigned p2_pix = unsigned(use_m_org ? m_org : m_sad) * WS + dst_x + dst_rounded_width * dst_y; + + DBG_LOG(3,0,("bitblt p1_pix=%u p2_pix=%u\n" , p1_pix , p2_pix)); + uint16_t rop_masks[ 4 ]; + get_rop_masks(rop, rop_masks); + + if (p1_pix < p2_pix) { + // Move block going up (decrease y) + p1_pix += dst_height * src_width + dst_width - 1; + p2_pix += dst_height * dst_rounded_width + dst_width - 1; + DBG_LOG(3,0,("bitblt rev p1_pix=%u p2_pix=%u\n" , p1_pix , p2_pix)); + while (dst_height--) { + p1_pix -= src_width; + p2_pix -= dst_rounded_width; + rowbltneg(p1_pix , p2_pix , dst_width , rop_masks); + } + } else { + // Move block going down (increase y) + DBG_LOG(3,0,("bitblt fwd\n")); + while (dst_height--) { + rowbltpos(p1_pix , p2_pix , dst_width , rop_masks); + p1_pix += src_width; + p2_pix += dst_rounded_width; } } + + return true; } -void hp1ll3_device::label(uint8_t chr, int width) +void hp1ll3_device::rowbltpos(unsigned p1_pix , unsigned p2_pix , int width , const uint16_t masks[]) { - uint16_t x, gfx, bg = 0x3f, offset, font = m_fontdata + chr * 16; - int max_y = m_cursor_y + m_fontheight; + // p1_pix and p2_pix point to the leftmost pixel of the row + while (width > 0) { + unsigned p1_word = p1_pix / WS; + unsigned p1_bit = p1_pix % WS; + // Get src pixels and align to MSB + uint16_t new_pix = rd_video(p1_word) << p1_bit; + if (p1_bit) { + new_pix |= rd_video(p1_word + 1) >> (WS - p1_bit); + } + unsigned p2_word = p2_pix / WS; + unsigned p2_bit = p2_pix % WS; + uint16_t old_pix = rd_video(p2_word); + unsigned w = p2_bit + width; + uint16_t glob_mask = ~0; + if (p2_bit) { + // Left end + new_pix >>= p2_bit; + glob_mask >>= p2_bit; + } + if (w < WS) { + // Right end + glob_mask &= ~0 << (WS - w); + } + rmw_rop(p2_word, new_pix, glob_mask, masks); + DBG_LOG(3,0,("rowbltpos %04x %04x %04x>%04x %u %u %u\n" , old_pix , new_pix , glob_mask , rd_video(p2_word) , p1_pix , p2_pix , width)); + w = WS - p2_bit; + p1_pix += w; + p2_pix += w; + width -= w; + } +} - if (max_y >= m_window.org_y + m_window.height) - max_y = m_window.org_y + m_window.height - 1 - m_cursor_y; - else - max_y -= m_cursor_y; - - if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); - - for (int y = 0; y < max_y; y++) { - x = m_cursor_x; - offset = m_sad + (m_cursor_y + y) * (m_horiz_pix_total/16) + (x >> 4); - gfx = m_videoram[font + y] >> (16 - width); - - if (offset >= m_sad + (m_vert_pix_total * m_horiz_pix_total/16)) - DBG_LOG(0,"HPGPU",("buffer overflow in LABEL: %04x (%d, %d)\n", offset, 16*x, y)); - - // are we crossing word boundary? - if ((x % 16) > (16 - width)) { - if (m_rr == RR_COPYINVERTED) { - m_videoram[offset ] |= bg >> ((x % 16) - (16 - width)); - m_videoram[offset + 1] |= bg << (16 - ((x + width) % 16)); - } else { - m_videoram[offset ] &= ~(bg>> ((x % 16) - (16 - width))); - m_videoram[offset + 1] &= ~(bg<< (16 - ((x + width) % 16))); - } - m_videoram[offset ] ^= gfx >> ((x % 16) - (16 - width)); - m_videoram[offset + 1] ^= gfx << (16 - ((x + width) % 16)); - } else { - if (m_rr == RR_COPYINVERTED) { - m_videoram[offset ] |= bg << ((16 - width) - (x % 16)); - } else { - m_videoram[offset ] &= ~(bg<< ((16 - width) - (x % 16))); - } - m_videoram[offset ] ^= gfx << ((16 - width) - (x % 16)); +void hp1ll3_device::rowbltneg(unsigned p1_pix , unsigned p2_pix , int width , const uint16_t masks[]) +{ + // p1_pix and p2_pix point to the rightmost pixel of the row + while (width > 0) { + unsigned p1_word = p1_pix / WS; + unsigned p1_bit = p1_pix % WS; + // Get src pixels and align to LSB + uint16_t new_pix = rd_video(p1_word) >> (WS - 1 - p1_bit); + if (p1_bit != (WS - 1)) { + new_pix |= rd_video(p1_word - 1) << (p1_bit + 1); + } + unsigned p2_word = p2_pix / WS; + unsigned p2_bit = p2_pix % WS; + uint16_t old_pix = rd_video(p2_word); + int w = p2_bit - width; + uint16_t glob_mask = ~0; + if (p2_bit != (WS - 1)) { + // Right end + new_pix <<= (WS - 1 - p2_bit); + glob_mask <<= (WS - 1 - p2_bit); + } + if (w >= 0) { + // Left end + uint16_t tmp = ~0; + glob_mask &= tmp >> (w + 1); } + rmw_rop(p2_word, new_pix, glob_mask, masks); + DBG_LOG(3,0,("rowbltneg %04x %04x %04x>%04x %u %u %u\n" , old_pix , new_pix , glob_mask , rd_video(p2_word) , p1_pix , p2_pix , width)); + w = p2_bit + 1; + p1_pix -= w; + p2_pix -= w; + width -= w; } +} - m_cursor_x += width; - if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); +void hp1ll3_device::fill(const Rectangle& fill_rect , uint16_t pattern_no) +{ + uint16_t pattern_addr = get_pattern_addr(pattern_no); + + Point src_p{ 0 , 0 }; + // Align to 16x16 tiles in absolute coordinates + uint16_t start_x = fill_rect.origin.x & ~0xf; + Rectangle dst_rect{{ start_x , uint16_t(fill_rect.origin.y & ~0xf) } , { 16 , 16 }}; + + // Iterate over vertical span + while (bitblt(pattern_addr, 16, 16, src_p, fill_rect, dst_rect, m_rr)) { + // Iterate over horizontal span + do { + dst_rect.origin.x += 16; + } while (bitblt(pattern_addr, 16, 16, src_p, fill_rect, dst_rect, m_rr)); + dst_rect.origin.x = start_x; + dst_rect.origin.y += 16; + } +} + +uint16_t hp1ll3_device::get_pattern_addr(uint16_t pattern_no) const +{ + return m_dad + pattern_no * 16; +} + +void hp1ll3_device::draw_cursor() +{ + if (m_enable_cursor) { + Rectangle dst{{ uint16_t(m_cursor_x + m_cursor_offset) , m_cursor_y } , { 16 , 16 }}; + bitblt(get_pattern_addr(m_cursor_pattern), 16, 16, Point{ 0 , 0 }, get_screen(), dst, RR_XOR , false); + } +} + +void hp1ll3_device::draw_sprite() +{ + if (m_enable_sprite) { + Rectangle dst{{ m_sprite_x , m_sprite_y } , { 16 , 16 }}; + bitblt(get_pattern_addr(m_sprite_pattern), 16, 16, Point{ 0 , 0 }, get_screen(), dst, RR_XOR , false); + } +} + +void hp1ll3_device::draw_cursor_sprite() +{ + draw_cursor(); + draw_sprite(); +} + +void hp1ll3_device::set_pen_pos(Point p) +{ + if (p.x != m_cursor_x || p.y != m_cursor_y) { + draw_cursor(); + m_cursor_x = p.x; + m_cursor_y = p.y; + draw_cursor(); + } +} + +void hp1ll3_device::set_sprite_pos(Point p) +{ + if (p.x != m_sprite_x || p.y != m_sprite_y) { + draw_sprite(); + m_sprite_x = p.x; + m_sprite_y = p.y; + draw_sprite(); + } +} + +hp1ll3_device::Rectangle hp1ll3_device::get_window() const +{ + return Rectangle{{ m_window.org_x , m_window.org_y } , { m_window.width , m_window.height }}; } +hp1ll3_device::Rectangle hp1ll3_device::get_screen() const +{ + return Rectangle{{ 0 , 0 } , { uint16_t(m_horiz_pix_total) , uint16_t(m_vert_pix_total) }}; +} + +void hp1ll3_device::apply_conf() +{ + // TODO: +} uint32_t hp1ll3_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { @@ -456,7 +649,7 @@ uint32_t hp1ll3_device::screen_update(screen_device &screen, bitmap_ind16 &bitma } // XXX last line is not actually drawn on real hw - for (y = 0; y < m_vert_pix_total-1; y++) { + for (y = 0; y < m_vert_pix_total; y++) { offset = m_sad + y*(m_horiz_pix_total/16); p = &m_bitmap.pix16(y); @@ -507,41 +700,73 @@ READ8_MEMBER( hp1ll3_device::read ) { uint8_t data = 0; - switch (offset) - { - case 0: + if (offset == 0) { data = m_busy ? 1 : 0; data |= 2; data |= (screen().vblank() ? 8 : 0); - break; - - case 2: - switch (m_command) - { - case RDMEM: - if (m_memory_ptr < HPGPU_VRAM_SIZE*2) { - if (m_memory_ptr & 1) { - data = m_videoram[m_memory_ptr >> 1] & 0xff; - } else { - data = m_videoram[m_memory_ptr >> 1] >> 8; + } else { + if ((m_io_ptr & 1) == 0) { + switch (m_command) + { + case RDMEM: + m_io_word = rd_video(m_memory_ptr++); + break; + + case RDWIN: + { + uint16_t addr = get_pix_addr(m_rw_win_x , m_rw_win_y); + unsigned bit = m_rw_win_x % WS; + int width = m_window.width + m_window.org_x - m_rw_win_x; + if (width <= 0) { + m_command = NOP; + break; + } + unsigned w = std::min(WS , unsigned(width)); + + m_io_word = rd_video(addr) << bit; + if ((bit + w) > WS) { + m_io_word |= rd_video(addr + 1) >> (WS - bit); + } + m_io_word &= ~0 << (WS - w); + m_rw_win_x += w; + if (m_rw_win_x >= (m_window.width + m_window.org_x)) { + m_rw_win_x = m_window.org_x; + m_rw_win_y++; + if (m_rw_win_y >= (m_window.height + m_window.org_y)) { + m_command = NOP; + } + } + } + break; + + case RDP: + if (m_io_ptr == 0) { + m_io_word = m_cursor_x; + } else if (m_io_ptr == 2) { + m_io_word = m_cursor_y; + } + break; + + case RDSP: + if (m_io_ptr == 0) { + m_io_word = m_sprite_x; + } else if (m_io_ptr == 2) { + m_io_word = m_sprite_y; + } + break; + case ID: + /* + * 'diagb' ROM accepts either of these ID values + * 0x3003, 0x4004, 0x5005, 0x6006 + */ + m_io_word = 0x4004; + break; } - m_memory_ptr++; - } - break; - - /* - * 'diagb' ROM accepts either of these ID values - * 0x3003, 0x4004, 0x5005, 0x6006 - */ - case ID: - data = 0x40; - break; + data = uint8_t(m_io_word >> 8); + } else { + data = m_io_word & 0xff; } - break; - - case 3: - if (m_command == ID) data = 0x04; - break; + m_io_ptr++; } DBG_LOG(1,"HPGPU", ("R @ %d == %02x\n", offset, data)); @@ -558,68 +783,77 @@ WRITE8_MEMBER( hp1ll3_device::write ) { DBG_LOG(1,"HPGPU", ("W @ %d <- %02x\n", offset, data)); - switch (offset) - { - case 0: + if (offset == 0) { command(data); - break; - - case 2: - case 3: - switch (m_command) - { - case CONF: - if (m_conf_ptr < 2 * ARRAY_LENGTH(m_conf)) { - if (m_conf_ptr & 1) { - m_conf[m_conf_ptr >> 1] |= data; - DBG_LOG(1,"HPGPU",("CONF data word %d received: %04X\n", m_conf_ptr >> 1, m_conf[m_conf_ptr >> 1])); - } else { - m_conf[m_conf_ptr >> 1] = data << 8; - } - } else { - if (m_conf_ptr & 1) { - m_input[0] |= data; - DBG_LOG(1,"HPGPU",("unexpected CONF data word %d discarded: %04X\n", m_conf_ptr >> 1, m_input[0])); - } else { - m_input[0] = data << 8; - } - } - m_conf_ptr++; - break; - - case WRMEM: - if (m_memory_ptr < HPGPU_VRAM_SIZE*2) { - if (m_memory_ptr & 1) { - m_videoram[m_memory_ptr >> 1] |= data; - } else { - m_videoram[m_memory_ptr >> 1] = data << 8; + } else { + if ((m_io_ptr & 1) == 0) { + m_io_word = uint16_t(data) << 8; + } else { + m_io_word |= data; + switch (m_command) + { + case CONF: + m_conf[ m_io_ptr >> 1 ] = m_io_word; + DBG_LOG(1,"HPGPU",("CONF data word %d received: %04X\n", m_io_ptr >> 1, m_io_word)); + if ((m_io_ptr >> 1) == 10) { + apply_conf(); + m_io_ptr = -1; + m_command = NOP; + } + break; + + case WRMEM: + wr_video(m_memory_ptr++ , m_io_word); + break; + + case WRWIN: + { + uint16_t rop_masks[ 4 ]; + get_rop_masks(m_rr , rop_masks); + + uint16_t addr = get_pix_addr(m_rw_win_x , m_rw_win_y); + uint16_t glob_mask = ~0; + unsigned bit = m_rw_win_x % WS; + int width = m_window.width + m_window.org_x - m_rw_win_x; + if (width <= 0) { + m_command = NOP; + draw_cursor_sprite(); + } else { + unsigned w = std::min(WS , unsigned(width)); + + glob_mask >>= bit; + if ((bit + w) < WS) { + glob_mask &= ~0 << (WS - (bit + w)); + } + rmw_rop(addr , m_io_word >> bit , glob_mask , rop_masks); + DBG_LOG(3, 0, ("WRWIN (%u,%u) %d %04x %04x\n" , m_rw_win_x , m_rw_win_y , width , m_io_word >> bit , glob_mask)); + if ((bit + w) > WS) { + unsigned pad = WS - bit; + glob_mask = ~0 << (2 * WS - bit - w); + rmw_rop(addr + 1 , uint16_t(m_io_word << pad) , glob_mask , rop_masks); + DBG_LOG(3, 0, ("WRWIN %u %04x %04x\n" , pad , m_io_word << pad , glob_mask)); + } + m_rw_win_x += w; + if (m_rw_win_x >= (m_window.width + m_window.org_x)) { + m_rw_win_x = m_window.org_x; + m_rw_win_y++; + if (m_rw_win_y >= (m_window.height + m_window.org_y)) { + m_command = NOP; + draw_cursor_sprite(); + } + } + } + } + break; + + default: + if (m_io_ptr <= 4) { + m_input[ m_io_ptr / 2 ] = m_io_word; + } + DBG_LOG(2,"HPGPU",("wrote %02x at %d, input buffer is %04X %04X\n", data, m_io_ptr, m_input[0], m_input[1])); } - m_memory_ptr++; - } - break; - - default: - switch (m_input_ptr) - { - case 0: - m_input[0] = data << 8; - break; - - case 1: - m_input[0] |= data; - break; - - case 2: - m_input[1] = data << 8; - break; - - case 3: - m_input[1] |= data; - break; - } - DBG_LOG(2,"HPGPU",("wrote %02x at %d, input buffer is %04X %04X\n", data, m_input_ptr, m_input[0], m_input[1])); - m_input_ptr++; } + m_io_ptr++; } } @@ -638,11 +872,15 @@ void hp1ll3_device::command(int command) switch (m_command) { case RDMEM: - DBG_LOG(1,"HPGPU",("RDMEM of %d words at %04X complete\n", (m_memory_ptr >> 1) - m_input[0], m_input[0])); + DBG_LOG(1,"HPGPU",("RDMEM of %d words at %04X complete\n", m_memory_ptr - m_input[0], m_input[0])); break; case WRMEM: - DBG_LOG(1,"HPGPU",("WRMEM of %d words to %04X complete\n", (m_memory_ptr >> 1) - m_input[0], m_input[0])); + DBG_LOG(1,"HPGPU",("WRMEM of %d words to %04X complete\n", m_memory_ptr - m_input[0], m_input[0])); + break; + + case WRWIN: + draw_cursor_sprite(); break; } break; @@ -661,38 +899,23 @@ void hp1ll3_device::command(int command) case DISSP: DBG_LOG(2,"HPGPU",("command: DISSP [%d, 0x%x]\n", command, command)); - if (m_enable_sprite) { - bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); - m_enable_sprite = false; - } + draw_sprite(); + m_enable_sprite = false; break; case ENSP: DBG_LOG(2,"HPGPU",("command: ENSP [%d, 0x%x]\n", command, command)); - if (m_enable_sprite) { - bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); - } - bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); + draw_sprite(); + m_sprite_pattern = m_input[ 0 ]; m_enable_sprite = true; + draw_sprite(); DBG_LOG(1,"HPGPU",("enable sprite; cursor %d,%d sprite %d,%d\n", m_cursor_x, m_cursor_y, m_sprite_x, m_sprite_y)); break; case DISCURS: DBG_LOG(2,"HPGPU",("command: DISCURS [%d, 0x%x]\n", command, command)); - if (m_enable_cursor) { - bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - m_enable_cursor = false; - } - break; - - case ENCURS: - DBG_LOG(2,"HPGPU",("command: ENCURS [%d, 0x%x]\n", command, command)); - if (m_enable_cursor) { - bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - } - bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - m_enable_cursor = true; - DBG_LOG(1,"HPGPU",("enable cursor; cursor %d,%d sprite %d,%d\n", m_cursor_x, m_cursor_y, m_sprite_x, m_sprite_y)); + draw_cursor(); + m_enable_cursor = false; break; // type 1 commands -- 1 word of data expected in the buffer @@ -710,10 +933,10 @@ void hp1ll3_device::command(int command) // ?? used by diagnostic ROM case 6: - m_fontheight = m_videoram[m_fad]; - m_fontdata = m_fad + m_videoram[m_fad + 1] + 2; + m_fontheight = rd_video(m_fad); + m_fontdata = m_fad + rd_video(m_fad + 1) + 2; DBG_LOG(1,"HPGPU",("font data set: FAD %04X header %d bitmaps %04X height %d\n", - m_fad, m_videoram[m_fad + 1], m_fontdata, m_fontheight)); + m_fad, rd_video(m_fad + 1), m_fontdata, m_fontheight)); break; // start of data area @@ -731,7 +954,7 @@ void hp1ll3_device::command(int command) // set replacement rule (raster op) case WRRR: DBG_LOG(2,"HPGPU",("command: WRRR [%d, 0x%x] (0x%04x)\n", command, command, m_input[0])); - m_rr = m_input[0]; + m_rr = m_input[ 0 ]; break; // set user-defined line pattern @@ -743,9 +966,11 @@ void hp1ll3_device::command(int command) // area fill case FILL: DBG_LOG(2,"HPGPU",("command: FILL [%d, 0x%x] (0x%04x) from (%d,%d) size (%d,%d) rop 0x%x\n", - command, command, m_input[0], - m_window.org_x, m_window.org_y, m_window.width, m_window.height, m_rr)); - fill(m_window.org_x, m_window.org_y, m_window.width, m_window.height, m_input[0]); + command, command, m_input[0], + m_window.org_x, m_window.org_y, m_window.width, m_window.height, m_rr)); + draw_cursor_sprite(); + fill(get_window() , m_input[0]); + draw_cursor_sprite(); break; case LABEL: @@ -753,16 +978,37 @@ void hp1ll3_device::command(int command) (m_input[0]<32||m_input[0]>127) ? ' ' : m_input[0], m_cursor_x, m_cursor_y)); c = m_input[0] & 255; w = (c & 1) ? - (m_videoram[m_fad + 2 + (c>>1)] & 255) : - (m_videoram[m_fad + 2 + (c>>1)] >> 8); + (rd_video(m_fad + 2 + (c>>1)) & 255) : + (rd_video(m_fad + 2 + (c>>1)) >> 8); label(c, w); break; + // Write window + case WRWIN: + DBG_LOG(2,"HPGPU",("command: WRWIN [%d, 0x%x] offset=%u size(%d,%d)\n",command, command, m_input[0], m_window.width, m_window.height)); + // m_input[0] is offset (to be implemented) + m_rw_win_x = m_window.org_x; + m_rw_win_y = m_window.org_y; + draw_cursor_sprite(); + break; + + // Read window + case RDWIN: + DBG_LOG(2,"HPGPU",("command: RDWIN [%d, 0x%x] offset=%u\n",command, command, m_input[0])); + // m_input[0] is offset (to be implemented) + m_rw_win_x = m_window.org_x; + m_rw_win_y = m_window.org_y; + break; + // type 2 commands -- 2 words of data expected in the buffer case DRAWPX: - DBG_LOG(2,"HPGPU",("command: DRAWPX [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1])); - point(m_input[0], m_input[1],(m_rr != RR_COPYINVERTED)); + { + DBG_LOG(2,"HPGPU",("command: DRAWPX [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1])); + uint16_t rop_masks[ 4 ]; + get_rop_masks(m_rr , rop_masks); + point(m_input[0], m_input[1], true, rop_masks); + } break; // set window size @@ -779,34 +1025,80 @@ void hp1ll3_device::command(int command) m_window.org_y = m_input[1]; break; + // Copy + case COPY: + { + DBG_LOG(2,"HPGPU",("command: COPY [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1])); + draw_cursor_sprite(); + unsigned rounded_width = m_conf[ CONF_WPL ] * WS; + Rectangle dst_rect{{ m_input[ 0 ] , m_input[ 1 ] } , { m_window.width , m_window.height }}; + // COPY apparently doesn't clip anything + bitblt(m_org , rounded_width , 0xffff , Point{ m_window.org_x , m_window.org_y } , + Rectangle{{ 0 , 0 } , { uint16_t(rounded_width) , 0xffff }} , dst_rect , m_rr); + draw_cursor_sprite(); + } + break; + // move pointer absolute case MOVEP: DBG_LOG(2,"HPGPU",("command: MOVEP [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1])); - if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); - m_cursor_x = m_input[0]; - m_cursor_y = m_input[1]; + set_pen_pos(Point{ m_input[ 0 ] , m_input[ 1 ] }); m_saved_x = m_cursor_x; - if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); + break; + + // Scroll UP + case SCROLUP: + { + DBG_LOG(2,"HPGPU",("command: SCROLUP [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1])); + draw_cursor_sprite(); + Point src_p{ m_window.org_x , uint16_t(m_window.org_y + m_input[ 1 ]) }; + Rectangle dst_rect = get_window(); + dst_rect.size.y -= m_input[ 1 ]; + bitblt(m_org , m_horiz_pix_total , m_vert_pix_total , src_p , get_window() , dst_rect , m_rr); + dst_rect.origin.y += dst_rect.size.y; + dst_rect.size.y = m_input[ 1 ]; + fill(dst_rect , m_input[ 0 ]); + draw_cursor_sprite(); + } + break; + + // Scroll DOWN + case SCROLDN: + { + DBG_LOG(2,"HPGPU",("command: SCROLDN [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1])); + draw_cursor_sprite(); + Point src_p{ m_window.org_x , m_window.org_y }; + Rectangle dst_rect = get_window(); + dst_rect.origin.y += m_input[ 1 ]; + dst_rect.size.y -= m_input[ 1 ]; + bitblt(m_org , m_horiz_pix_total , m_vert_pix_total , src_p , get_window() , dst_rect , m_rr); + dst_rect.origin.y = m_window.org_y; + dst_rect.size.y = m_input[ 1 ]; + fill(dst_rect , m_input[ 0 ]); + draw_cursor_sprite(); + } + break; + + case ENCURS: + DBG_LOG(2,"HPGPU",("command: ENCURS [%d, 0x%x]\n", command, command)); + draw_cursor(); + m_cursor_pattern = m_input[ 0 ]; + m_cursor_offset = m_input[ 1 ]; + m_enable_cursor = true; + draw_cursor(); + DBG_LOG(1,"HPGPU",("enable cursor; cursor %d,%d sprite %d,%d\n", m_cursor_x, m_cursor_y, m_sprite_x, m_sprite_y)); break; // carriage return, line feed case CRLFx: DBG_LOG(2,"HPGPU",("command: CRLF [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1])); - if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); - m_cursor_x = m_saved_x; - m_cursor_y += m_fontheight; - if (m_enable_cursor) bitblt(m_cursor_x, m_cursor_y, m_dad, 16, 16, RR_XOR); - if (m_enable_sprite) bitblt(m_sprite_x, m_sprite_y, m_dad + 16, 16, 16, RR_XOR); + set_pen_pos(Point{ m_saved_x , uint16_t(m_cursor_y + m_fontheight) }); break; // move sprite absolute case MOVESP: DBG_LOG(2,"HPGPU",("command: MOVESP [%d, 0x%x] (%d, %d)\n", command, command, m_input[0], m_input[1])); - m_sprite_x = m_input[0]; - m_sprite_y = m_input[1]; + set_sprite_pos(Point{ m_input[ 0 ] , m_input[ 1 ] }); break; // draw to ... @@ -814,14 +1106,12 @@ void hp1ll3_device::command(int command) DBG_LOG(2,"HPGPU",("command: DRAWP [%d, 0x%x] (%d, %d) to (%d, %d)\n", command, command, m_cursor_x, m_cursor_y, m_input[0], m_input[1])); line(m_cursor_x, m_cursor_y, m_input[0], m_input[1]); - m_cursor_x = m_input[0]; - m_cursor_y = m_input[1]; + set_pen_pos(Point{ m_input[ 0 ] , m_input[ 1 ] }); break; // type 3 command -- CONF -- accept configuration parameters (11 words) case CONF: - m_conf_ptr = 0; break; // type 4 commands -- like type 1 plus data is read or written after command, terminated by NOP @@ -830,7 +1120,12 @@ void hp1ll3_device::command(int command) case WRMEM: DBG_LOG(2,"HPGPU",("command: %s [%d, 0x%x] (0x%04x)\n", command == RDMEM?"RDMEM":"WRMEM", command, command, m_input[0])); - m_memory_ptr = m_input[0] << 1; // memory is word-addressable + m_memory_ptr = m_input[0]; // memory is word-addressable + break; + + // type 3 read commands + case RDP: + case RDSP: break; default: @@ -838,6 +1133,6 @@ void hp1ll3_device::command(int command) break; } - m_input_ptr = 0; + m_io_ptr = 0; m_command = command; } diff --git a/src/devices/video/hp1ll3.h b/src/devices/video/hp1ll3.h index b8c9b45e007..2360b190af6 100644 --- a/src/devices/video/hp1ll3.h +++ b/src/devices/video/hp1ll3.h @@ -43,16 +43,43 @@ protected: virtual void device_reset() override; private: + struct Point { + uint16_t x , y; + }; + struct Rectangle { + Point origin; + Point size; + }; + void command(int command); - inline void point(int x, int y, int px); + uint16_t get_pix_addr(uint16_t x , uint16_t y) const; + inline void point(int x, int y, bool pix, const uint16_t masks[]); void label(uint8_t chr, int width); - void fill(int x, int y, int w, int h, int arg); void line(int x_from, int y_from, int x_to, int y_to); - void bitblt(int dstx, int dsty, uint16_t srcaddr, int width, int height, int op); - - uint16_t m_conf[12], m_input[2]; - int m_input_ptr, m_memory_ptr, m_conf_ptr; + void wr_video(uint16_t addr , uint16_t v); + uint16_t rd_video(uint16_t addr) const; + static void get_rop_masks(uint16_t rop , uint16_t masks[]); + static uint16_t apply_rop(uint16_t old_pix , uint16_t new_pix , uint16_t glob_mask , const uint16_t masks[]); + void rmw_rop(uint16_t addr , uint16_t new_pix , uint16_t glob_mask , const uint16_t masks[]); + void clip_coord(int size_1 , int& p1 , int origin_clip , int size_clip , int& origin_2 , int& size_2) const; + bool bitblt(uint16_t src_base_addr , unsigned src_width , unsigned src_height , Point src_p , + const Rectangle& clip_rect , const Rectangle& dst_rect , uint16_t rop , bool use_m_org = true); + void rowbltpos(unsigned p1_pix , unsigned p2_pix , int width , const uint16_t masks[]); + void rowbltneg(unsigned p1_pix , unsigned p2_pix , int width , const uint16_t masks[]); + void fill(const Rectangle& fill_rect , uint16_t pattern_no); + uint16_t get_pattern_addr(uint16_t pattern_no) const; + void draw_cursor(); + void draw_sprite(); + void draw_cursor_sprite(); + void set_pen_pos(Point p); + void set_sprite_pos(Point p); + Rectangle get_window() const; + Rectangle get_screen() const; + void apply_conf(); + + uint16_t m_conf[ 11 ] , m_input[2] , m_io_word; + int m_io_ptr, m_memory_ptr; int m_command, m_horiz_pix_total, m_vert_pix_total; uint16_t m_sad; @@ -64,15 +91,20 @@ private: bool m_enable_video, m_enable_cursor, m_enable_sprite; uint16_t m_cursor_x, m_cursor_y, m_saved_x; + uint16_t m_cursor_pattern; + uint16_t m_cursor_offset; uint16_t m_sprite_x, m_sprite_y; + uint16_t m_sprite_pattern; struct { - uint16_t width, height, org_x, org_y, width_w; + uint16_t width, height, org_x, org_y; } m_window; std::unique_ptr m_videoram; + uint16_t m_ram_addr_mask; + uint16_t m_rw_win_x , m_rw_win_y; bool m_busy; - bitmap_ind16 m_bitmap, m_cursor, m_sprite; + bitmap_ind16 m_bitmap; }; diff --git a/src/mame/drivers/hp_ipc.cpp b/src/mame/drivers/hp_ipc.cpp index fcbe52ff23f..522470c5d60 100644 --- a/src/mame/drivers/hp_ipc.cpp +++ b/src/mame/drivers/hp_ipc.cpp @@ -495,7 +495,7 @@ void hp_ipc_state::hp_ipc_mem_inner_base(address_map &map) map(0x0600000, 0x060FFFF).rw(FUNC(hp_ipc_state::mmu_r), FUNC(hp_ipc_state::mmu_w)); map(0x0610000, 0x0610007).rw(FUNC(hp_ipc_state::floppy_id_r), FUNC(hp_ipc_state::floppy_id_w)).umask16(0x00ff); map(0x0610008, 0x061000F).rw(m_fdc, FUNC(wd2797_device::read), FUNC(wd2797_device::write)).umask16(0x00ff); - map(0x0620000, 0x062000F).rw("gpu", FUNC(hp1ll3_device::read), FUNC(hp1ll3_device::write)).umask16(0x00ff); + map(0x0620000, 0x0620007).rw("gpu", FUNC(hp1ll3_device::read), FUNC(hp1ll3_device::write)).umask16(0x00ff); map(0x0630000, 0x063FFFF).mask(0xf).rw("hpib" , FUNC(tms9914_device::reg8_r) , FUNC(tms9914_device::reg8_w)).umask16(0x00ff); map(0x0640000, 0x064002F).rw("rtc", FUNC(mm58167_device::read), FUNC(mm58167_device::write)).umask16(0x00ff); map(0x0660000, 0x06600FF).rw("mlc", FUNC(hp_hil_mlc_device::read), FUNC(hp_hil_mlc_device::write)).umask16(0x00ff); // 'caravan', scrn/caravan.h @@ -738,9 +738,7 @@ MACHINE_CONFIG_START(hp_ipc_state::hp_ipc_base) MCFG_DEVICE_ADD("maincpu", M68000, 15.92_MHz_XTAL / 2) MCFG_DEVICE_PROGRAM_MAP(hp_ipc_mem_outer) - MCFG_HP1LL3_ADD("gpu") -// MCFG_HP1LL3_IRQ_CALLBACK(WRITELINE(*this, hp_ipc_state, irq_4)) - MCFG_VIDEO_SET_SCREEN("screen") + HP1LL3(config , "gpu" , 24_MHz_XTAL / 8).set_screen("screen"); // XXX actual clock is 1MHz; remove this workaround (and change 2000 to 100 in hp_ipc_dsk.cpp) // XXX when floppy code correctly handles 600 rpm drives. @@ -799,12 +797,13 @@ MACHINE_CONFIG_START(hp_ipc_state::hp_ipc) // horizontal time = 60 us (min) // ver.refresh period = ~300 us // ver.period = 16.7ms (~60 hz) - MCFG_SCREEN_ADD_MONOCHROME("screen", LCD, rgb_t::amber()) // actually a kind of EL display - MCFG_SCREEN_UPDATE_DEVICE("gpu", hp1ll3_device, screen_update) - MCFG_SCREEN_RAW_PARAMS(6_MHz_XTAL * 2, 720, 0, 512, 278, 0, 256) - MCFG_SCREEN_VBLANK_CALLBACK(WRITELINE("mlc", hp_hil_mlc_device, ap_w)) // XXX actually it's driven by 555 (U59) + SCREEN(config , m_screen , SCREEN_TYPE_LCD); + m_screen->set_color(rgb_t::amber()); // actually a kind of EL display + m_screen->set_screen_update("gpu" , FUNC(hp1ll3_device::screen_update)); + m_screen->set_raw(6_MHz_XTAL * 2 , 720 , 0 , 512 , 261 , 0 , 255); + m_screen->screen_vblank().set("mlc", FUNC(hp_hil_mlc_device::ap_w)); // XXX actually it's driven by 555 (U59) + m_screen->set_palette("palette"); - MCFG_SCREEN_PALETTE("palette") MCFG_PALETTE_ADD_MONOCHROME("palette") MACHINE_CONFIG_END -- cgit v1.2.3