summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commit8b8643c108e83ea238b405a0a6077abc8d0f3298 (patch)
tree625409e10ceecf00acebbf5d10ae8ce2baa95db0
parent0b66c6d21c319fb20203302079e9b49169c956a4 (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.cpp262
-rw-r--r--src/devices/bus/hp_dio/hp98544.h83
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