diff options
author | Sven Schnelle <sven.schnelle@lancom.de> | 2018-04-13 21:55:42 +0200 |
---|---|---|
committer | Sven Schnelle <sven.schnelle@lancom.de> | 2018-04-15 20:25:51 +0200 |
commit | 8b8643c108e83ea238b405a0a6077abc8d0f3298 (patch) | |
tree | 625409e10ceecf00acebbf5d10ae8ce2baa95db0 | |
parent | 0b66c6d21c319fb20203302079e9b49169c956a4 (diff) |
Add basic window move support to hp98544 framebuffer
HP Basic (and probably other OS') use the window mover to place letters
on the screen by moving them from non-visible memory to the screen. Add
basic support for that so that we have some output from HP basic. It also
implements cursor control.
Signed-off-by: Sven Schnelle <svens@stackframe.org>
-rw-r--r-- | src/devices/bus/hp_dio/hp98544.cpp | 262 | ||||
-rw-r--r-- | src/devices/bus/hp_dio/hp98544.h | 83 |
2 files changed, 341 insertions, 4 deletions
diff --git a/src/devices/bus/hp_dio/hp98544.cpp b/src/devices/bus/hp_dio/hp98544.cpp index 96b464a9f86..c0b2b8177b7 100644 --- a/src/devices/bus/hp_dio/hp98544.cpp +++ b/src/devices/bus/hp_dio/hp98544.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:R. Belmont +// copyright-holders:R. Belmont, Sven Schnelle /*************************************************************************** HP98544 high-resolution monochrome board @@ -85,6 +85,10 @@ void dio16_98544_device::device_start() write16_delegate(FUNC(dio16_98544_device::vram_w), this)); m_dio->install_memory(0x560000, 0x563fff, read16_delegate(FUNC(dio16_98544_device::rom_r), this), write16_delegate(FUNC(dio16_98544_device::rom_w), this)); + m_dio->install_memory(0x564000, 0x567fff, read16_delegate(FUNC(dio16_98544_device::ctrl_r), this), + write16_delegate(FUNC(dio16_98544_device::ctrl_w), this)); + m_cursor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dio16_98544_device::cursor_callback),this)); + m_cursor_timer->adjust(attotime::from_hz(3)); } //------------------------------------------------- @@ -97,6 +101,34 @@ void dio16_98544_device::device_reset() m_palette[1] = rgb_t(255, 255, 255); m_palette[0] = rgb_t(0, 0, 0); + m_pixel_replacement_rule = TOPCAT_REPLACE_RULE_SRC; +} + +TIMER_CALLBACK_MEMBER(dio16_98544_device::cursor_callback) +{ + m_cursor_timer->adjust(attotime::from_hz(5)); + m_cursor_state ^= true; + + if (m_cursor_ctrl & 0x02) { + for(int i = 0; i < m_cursor_width; i++) { + m_vram[(m_cursor_y_pos * 512) + (m_cursor_x_pos + i)/2] = m_cursor_state ? 0xffff : 0; + m_vram[((m_cursor_y_pos-1) * 512) + (m_cursor_x_pos + i)/2] = m_cursor_state ? 0xffff : 0; + m_vram[((m_cursor_y_pos-2) * 512) + (m_cursor_x_pos + i)/2] = m_cursor_state ? 0xffff : 0; + } + } +} + +void dio16_98544_device::update_cursor(int x, int y, uint8_t ctrl, uint8_t width) +{ + for(int i = 0; i < m_cursor_width; i++) { + m_vram[(m_cursor_y_pos * 512) + (m_cursor_x_pos + i)/2] = 0; + m_vram[((m_cursor_y_pos-1) * 512) + (m_cursor_x_pos + i)/2] = 0; + m_vram[((m_cursor_y_pos-2) * 512) + (m_cursor_x_pos + i)/2] = 0; + } + m_cursor_x_pos = x; + m_cursor_y_pos = y; + m_cursor_ctrl = ctrl; + m_cursor_width = width; } READ16_MEMBER(dio16_98544_device::vram_r) @@ -106,6 +138,7 @@ READ16_MEMBER(dio16_98544_device::vram_r) WRITE16_MEMBER(dio16_98544_device::vram_w) { +// execute_rule(data, (replacement_rule_t)m_pixel_replacement_rule, &data); COMBINE_DATA(&m_vram[offset]); } @@ -117,9 +150,234 @@ READ16_MEMBER(dio16_98544_device::rom_r) // the video chip registers live here, so these writes are valid WRITE16_MEMBER(dio16_98544_device::rom_w) { - printf("rom_w: %02x at %x (mask %04x)\n", data, offset, mem_mask); } +void dio16_98544_device::execute_rule(uint16_t src, replacement_rule_t rule, uint16_t *dst) +{ + switch(rule & 0x0f) { + case TOPCAT_REPLACE_RULE_CLEAR: + *dst = 0; + break; + case TOPCAT_REPLACE_RULE_SRC_AND_DST: + *dst &= src; + break; + case TOPCAT_REPLACE_RULE_SRC_AND_NOT_DST: + *dst = ~(*dst) & src; + break; + case TOPCAT_REPLACE_RULE_SRC: + *dst = src; + break; + case TOPCAT_REPLACE_RULE_NOT_SRC_AND_DST: + *dst &= ~src; + break; + case TOPCAT_REPLACE_RULE_NOP: + break; + case TOPCAT_REPLACE_RULE_SRC_XOR_DST: + *dst ^= src; + break; + case TOPCAT_REPLACE_RULE_SRC_OR_DST: + *dst |= src; + break; + case TOPCAT_REPLACE_RULE_NOT_SRC_AND_NOT_DST: + *dst = ~(*dst) & ~src; + break; + case TOPCAT_REPLACE_RULE_NOT_SRC_XOR_DST: + *dst ^= ~src; + break; + case TOPCAT_REPLACE_RULE_NOT_DST: + *dst ^= 0xffff; + break; + case TOPCAT_REPLACE_RULE_SRC_OR_NOT_DST: + *dst = src | ~(*dst); + break; + case TOPCAT_REPLACE_RULE_NOT_SRC: + *dst = ~src; + break; + case TOPCAT_REPLACE_RULE_NOT_SRC_OR_DST: + *dst = ~src | *dst; + break; + case TOPCAT_REPLACE_RULE_NOT_SRC_OR_NOT_DST: + *dst = ~src | ~(*dst); + break; + case TOPCAT_REPLACE_RULE_SET: + *dst = 0xffff; + break; + + } +} + +void dio16_98544_device::window_move(void) +{ + for(int line = 0; line < m_block_mover_pixel_height; line++) { + for(int column = 0; column < m_block_mover_pixel_width; column++) { + uint16_t sdata = m_vram[((m_source_y_pixel + line) * 1024 + (m_source_x_pixel + column))/2]; + uint16_t *ddata = &m_vram[((m_dst_y_pixel + line) * 1024 + (m_dst_x_pixel + column))/2]; + execute_rule(sdata, (replacement_rule_t)((m_move_replacement_rule >> 4) & 0x0f), ddata); + execute_rule(sdata, (replacement_rule_t)(m_move_replacement_rule & 0x0f), ddata); + } + } +} + +WRITE16_MEMBER(dio16_98544_device::ctrl_w) +{ + if (mem_mask == 0xff00) + data >>= 8; + + if (mem_mask == 0x00ff) { + logerror("%s: write ignored\n", __FUNCTION__); + return; + } + + switch(offset) { + case TOPCAT_REG_VBLANK: + m_vblank = data & 0xff; + break; + case TOPCAT_REG_WMOVE_ACTIVE: + break; + case TOPCAT_REG_VERT_RETRACE_INTRQ: + m_vert_retrace_intrq = data; + break; + case TOPCAT_REG_WMOVE_INTRQ: + m_wmove_intrq = data; + break; + case TOPCAT_REG_DISPLAY_PLANE_ENABLE: + m_display_enable_planes = data; + break; + case TOPCAT_REG_DISPLAY_WRITE_ENABLE_PLANE: + m_write_enable_plane = data; + break; + case TOPCAT_REG_DISPLAY_READ_ENABLE_PLANE: + m_read_enable_plane = data; + break; + case TOPCAT_REG_FB_WRITE_ENABLE: + m_fb_write_enable = data; + break; + case TOPCAT_REG_START_WMOVE: + window_move(); + break; + case TOPCAT_REG_ENABLE_BLINK_PLANES: + logerror("ENABLE_BLINK_PLANES: %04x\n", data); + m_enable_blink_planes = data; + break; + case TOPCAT_REG_ENABLE_ALT_FRAME: + logerror("ENABLE_ALT_PLANE: %04x\n", data); + m_enable_alt_frame = data; + break; + case TOPCAT_REG_PIXEL_REPLACE_RULE: + logerror("PIXEL RR: data %04X mask %04X\n", data, mem_mask); + m_pixel_replacement_rule = data; + break; + case TOPCAT_REG_MOVE_REPLACE_RULE: + logerror("MOVE RR: data %04X mask %04X\n", data, mem_mask); + m_move_replacement_rule = data; + break; + case TOPCAT_REG_SOURCE_X_PIXEL: + m_source_x_pixel = data; + break; + case TOPCAT_REG_SOURCE_Y_PIXEL: + m_source_y_pixel = data; + break; + case TOPCAT_REG_DST_X_PIXEL: + m_dst_x_pixel = data; + break; + case TOPCAT_REG_DST_Y_PIXEL: + m_dst_y_pixel = data; + break; + case TOPCAT_REG_BLOCK_MOVER_PIXEL_WIDTH: + m_block_mover_pixel_width = data; + break; + case TOPCAT_REG_BLOCK_MOVER_PIXEL_HEIGHT: + m_block_mover_pixel_height = data; + break; + case TOPCAT_REG_CURSOR_CNTL: + update_cursor(m_cursor_x_pos, m_cursor_y_pos, data, m_cursor_width); + break; + case TOPCAT_REG_CURSOR_X_POS: + update_cursor(data, m_cursor_y_pos, m_cursor_ctrl, m_cursor_width); + break; + case TOPCAT_REG_CURSOR_Y_POS: + update_cursor(m_cursor_x_pos, data, m_cursor_ctrl, m_cursor_width); + break; + case TOPCAT_REG_CURSOR_WIDTH: + update_cursor(m_cursor_x_pos, m_cursor_y_pos, m_cursor_ctrl, data); + break; + default: + logerror("unknown register: %02X = %04x\n", offset, data, mem_mask); + break; + } +} + +READ16_MEMBER(dio16_98544_device::ctrl_r) +{ + uint16_t ret = 0xffff; + + switch(offset) { + case TOPCAT_REG_VBLANK: + ret = m_vblank; + break; + case TOPCAT_REG_WMOVE_ACTIVE: + ret = m_wmove_active; + break; + case TOPCAT_REG_VERT_RETRACE_INTRQ: + ret = m_vert_retrace_intrq; + break; + case TOPCAT_REG_WMOVE_INTRQ: + ret = m_wmove_intrq; + break; + case TOPCAT_REG_DISPLAY_PLANE_ENABLE: + ret = m_display_enable_planes; + break; + case TOPCAT_REG_DISPLAY_WRITE_ENABLE_PLANE: + ret = m_write_enable_plane; + break; + case TOPCAT_REG_DISPLAY_READ_ENABLE_PLANE: + ret = m_read_enable_plane; + break; + case TOPCAT_REG_FB_WRITE_ENABLE: + ret = m_fb_write_enable; + break; + case TOPCAT_REG_START_WMOVE: + ret = 0; + break; + case TOPCAT_REG_ENABLE_BLINK_PLANES: + ret = m_enable_blink_planes; + break; + case TOPCAT_REG_ENABLE_ALT_FRAME: + ret = m_enable_alt_frame; + break; + case TOPCAT_REG_CURSOR_CNTL: + ret = m_cursor_ctrl; + break; + case TOPCAT_REG_PIXEL_REPLACE_RULE: + ret = m_pixel_replacement_rule; + break; + case TOPCAT_REG_MOVE_REPLACE_RULE: + ret = m_move_replacement_rule; + break; + case TOPCAT_REG_SOURCE_X_PIXEL: + ret = m_source_x_pixel; + break; + case TOPCAT_REG_SOURCE_Y_PIXEL: + ret = m_source_y_pixel; + break; + case TOPCAT_REG_DST_X_PIXEL: + ret = m_dst_x_pixel; + break; + case TOPCAT_REG_DST_Y_PIXEL: + ret = m_dst_y_pixel; + break; + case TOPCAT_REG_BLOCK_MOVER_PIXEL_WIDTH: + ret = m_block_mover_pixel_width; + break; + case TOPCAT_REG_BLOCK_MOVER_PIXEL_HEIGHT: + ret = m_block_mover_pixel_height; + break; + default: + logerror("unknown register read %02x\n", offset); + break; + } + return ret; +} uint32_t dio16_98544_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { uint32_t *scanline; diff --git a/src/devices/bus/hp_dio/hp98544.h b/src/devices/bus/hp_dio/hp98544.h index 499d305573b..fef92c868d3 100644 --- a/src/devices/bus/hp_dio/hp98544.h +++ b/src/devices/bus/hp_dio/hp98544.h @@ -26,8 +26,12 @@ public: DECLARE_WRITE16_MEMBER(vram_w); DECLARE_READ16_MEMBER(rom_r); DECLARE_WRITE16_MEMBER(rom_w); + DECLARE_READ16_MEMBER(ctrl_r); + DECLARE_WRITE16_MEMBER(ctrl_w); -protected: + TIMER_CALLBACK_MEMBER(cursor_callback); + + protected: dio16_98544_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); // device-level overrides @@ -38,12 +42,87 @@ protected: virtual void device_add_mconfig(machine_config &config) override; virtual const tiny_rom_entry *device_rom_region() const override; + typedef enum { + TOPCAT_REPLACE_RULE_CLEAR, /* 0 */ + TOPCAT_REPLACE_RULE_SRC_AND_DST, + TOPCAT_REPLACE_RULE_SRC_AND_NOT_DST, + TOPCAT_REPLACE_RULE_SRC, + TOPCAT_REPLACE_RULE_NOT_SRC_AND_DST, + TOPCAT_REPLACE_RULE_NOP, + TOPCAT_REPLACE_RULE_SRC_XOR_DST, + TOPCAT_REPLACE_RULE_SRC_OR_DST, + TOPCAT_REPLACE_RULE_NOT_SRC_AND_NOT_DST, + TOPCAT_REPLACE_RULE_NOT_SRC_XOR_DST, + TOPCAT_REPLACE_RULE_NOT_DST, + TOPCAT_REPLACE_RULE_SRC_OR_NOT_DST, + TOPCAT_REPLACE_RULE_NOT_SRC, + TOPCAT_REPLACE_RULE_NOT_SRC_OR_DST, + TOPCAT_REPLACE_RULE_NOT_SRC_OR_NOT_DST, + TOPCAT_REPLACE_RULE_SET, + } replacement_rule_t; + private: - uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + enum topcat_reg { + TOPCAT_REG_VBLANK=0x20, + TOPCAT_REG_WMOVE_ACTIVE=0x22, + TOPCAT_REG_VERT_RETRACE_INTRQ=0x24, + TOPCAT_REG_WMOVE_INTRQ=0x26, + TOPCAT_REG_DISPLAY_PLANE_ENABLE=0x40, + TOPCAT_REG_DISPLAY_WRITE_ENABLE_PLANE=0x44, + TOPCAT_REG_DISPLAY_READ_ENABLE_PLANE=0x46, + TOPCAT_REG_FB_WRITE_ENABLE=0x48, + TOPCAT_REG_START_WMOVE=0x4e, + TOPCAT_REG_ENABLE_BLINK_PLANES=0x50, + TOPCAT_REG_ENABLE_ALT_FRAME=0x54, + TOPCAT_REG_CURSOR_CNTL=0x56, + TOPCAT_REG_PIXEL_REPLACE_RULE=0x75, + TOPCAT_REG_MOVE_REPLACE_RULE=0x77, + TOPCAT_REG_SOURCE_X_PIXEL=0x79, + TOPCAT_REG_SOURCE_Y_PIXEL=0x7b, + TOPCAT_REG_DST_X_PIXEL=0x7d, + TOPCAT_REG_DST_Y_PIXEL=0x7f, + TOPCAT_REG_BLOCK_MOVER_PIXEL_WIDTH=0x81, + TOPCAT_REG_BLOCK_MOVER_PIXEL_HEIGHT=0x83, + TOPCAT_REG_CURSOR_X_POS=0x85, + TOPCAT_REG_CURSOR_Y_POS=0x87, + TOPCAT_REG_CURSOR_WIDTH=0x89, + }; + + void window_move(void); + void execute_rule(uint16_t src, replacement_rule_t rule, uint16_t *dst); + uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + void update_cursor(int x, int y, uint8_t ctrl, uint8_t width); std::vector<uint16_t> m_vram; uint32_t m_palette[2]; uint8_t *m_rom; + + uint8_t m_vblank; + uint8_t m_wmove_active; + uint8_t m_vert_retrace_intrq; + uint8_t m_wmove_intrq; + uint8_t m_display_enable_planes; + uint8_t m_write_enable_plane; + uint8_t m_read_enable_plane; + uint8_t m_fb_write_enable; + uint8_t m_start_wmove; + uint8_t m_enable_blink_planes; + uint8_t m_enable_alt_frame; + uint8_t m_cursor_ctrl; + uint8_t m_move_replacement_rule; + uint8_t m_pixel_replacement_rule; + uint16_t m_source_x_pixel; + uint16_t m_source_y_pixel; + uint16_t m_dst_x_pixel; + uint16_t m_dst_y_pixel; + uint16_t m_block_mover_pixel_width; + uint16_t m_block_mover_pixel_height; + + emu_timer *m_cursor_timer; + bool m_cursor_state; + uint16_t m_cursor_x_pos; + uint16_t m_cursor_y_pos; + uint16_t m_cursor_width; }; // device type definition |