Add topcat asic (#3558)

* add topcat template

HP topcat was an ASIC used on HP900/300 graphics cards.

Signed-off-by: Sven Schnelle <svens@stackframe.org>

* hook up topcat asic to HP98544

Signed-off-by: Sven Schnelle <svens@stackframe.org>

* topcat: add basic configuration macros for fb planes, height and width

Signed-off-by: Sven Schnelle <svens@stackframe.org>

* hp98544: move logic to topcat video driver

Preparation to support multi plane graphic cards
like the HP98543/98545/98547.

Signed-off-by: Sven Schnelle <svens@stackframe.org>

* xtal: add 35.904MHz XTAL
This commit is contained in:
Sven Schnelle 2018-05-11 23:17:55 +02:00 committed by R. Belmont
parent 718b23d773
commit e6b55ad7a6
6 changed files with 478 additions and 359 deletions

View File

@ -1069,3 +1069,14 @@ if (VIDEOS["BT45X"]~=null) then
MAME_DIR .. "src/devices/video/bt45x.h",
}
end
--------------------------------------------------
--
--@src/devices/video/topcat.h,VIDEOS["TOPCAT"] = true
--------------------------------------------------
if (VIDEOS["TOPCAT"]~=null) then
files {
MAME_DIR .. "src/devices/video/topcat.cpp",
MAME_DIR .. "src/devices/video/topcat.h",
}
end

View File

@ -15,8 +15,6 @@
#define HP98544_SCREEN_NAME "98544_screen"
#define HP98544_ROM_REGION "98544_rom"
#define VRAM_SIZE (0x100000)
ROM_START( hp98544 )
ROM_REGION( 0x2000, HP98544_ROM_REGION, 0 )
ROM_LOAD( "98544_1818-1999.bin", 0x000000, 0x002000, CRC(8c7d6480) SHA1(d2bcfd39452c38bc652df39f84c7041cfdf6bd51) )
@ -39,6 +37,11 @@ MACHINE_CONFIG_START(dio16_98544_device::device_add_mconfig)
MCFG_SCREEN_SIZE(1024,768)
MCFG_SCREEN_VISIBLE_AREA(0, 1024-1, 0, 768-1)
MCFG_SCREEN_REFRESH_RATE(70)
MCFG_DEVICE_ADD("topcat", TOPCAT, XTAL(35904000))
MCFG_TOPCAT_FB_WIDTH(1024)
MCFG_TOPCAT_FB_HEIGHT(768)
MCFG_TOPCAT_PLANES(1)
MACHINE_CONFIG_END
//-------------------------------------------------
@ -65,7 +68,8 @@ dio16_98544_device::dio16_98544_device(const machine_config &mconfig, const char
dio16_98544_device::dio16_98544_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock),
device_dio16_card_interface(mconfig, *this)
device_dio16_card_interface(mconfig, *this),
m_topcat(*this, "topcat")
{
}
@ -80,7 +84,6 @@ void dio16_98544_device::device_start()
m_rom = device().machine().root_device().memregion(this->subtag(HP98544_ROM_REGION).c_str())->base();
m_vram.resize(VRAM_SIZE);
m_dio->install_memory(
0x200000, 0x2fffff,
read16_delegate(FUNC(dio16_98544_device::vram_r), this),
@ -93,8 +96,6 @@ void dio16_98544_device::device_start()
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));
}
//-------------------------------------------------
@ -103,49 +104,16 @@ void dio16_98544_device::device_start()
void dio16_98544_device::device_reset()
{
memset(&m_vram[0], 0, VRAM_SIZE);
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)
{
return m_vram[offset];
return m_topcat->vram_r(space, offset, mem_mask);
}
WRITE16_MEMBER(dio16_98544_device::vram_w)
{
// execute_rule(data, (replacement_rule_t)m_pixel_replacement_rule, &data);
COMBINE_DATA(&m_vram[offset]);
m_topcat->vram_w(space, offset, data, mem_mask);
}
READ16_MEMBER(dio16_98544_device::rom_r)
@ -158,249 +126,17 @@ WRITE16_MEMBER(dio16_98544_device::rom_w)
{
}
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;
}
return m_topcat->ctrl_w(space, offset, data);
}
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;
return m_topcat->ctrl_r(space, offset);
}
uint32_t dio16_98544_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
uint32_t *scanline;
int x, y;
uint32_t pixels;
for (y = 0; y < 768; y++)
{
scanline = &bitmap.pix32(y);
for (x = 0; x < 1024/2; x++)
{
pixels = m_vram[(y * 512) + x];
*scanline++ = m_palette[(pixels>>8) & 1];
*scanline++ = m_palette[(pixels & 1)];
}
}
return 0;
return m_topcat->screen_update(screen, bitmap, cliprect);
}

View File

@ -7,7 +7,7 @@
#pragma once
#include "hp_dio.h"
#include "video/topcat.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@ -29,8 +29,8 @@ public:
DECLARE_READ16_MEMBER(ctrl_r);
DECLARE_WRITE16_MEMBER(ctrl_w);
TIMER_CALLBACK_MEMBER(cursor_callback);
required_device<topcat_device> m_topcat;
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
protected:
dio16_98544_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@ -41,87 +41,8 @@ public:
// optional information overrides
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:
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_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

View File

@ -0,0 +1,324 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
#include "emu.h"
#include "topcat.h"
// define VERBOSE 1
#include "logmacro.h"
DEFINE_DEVICE_TYPE(TOPCAT, topcat_device, "topcat", "HP Topcat ASIC")
#define VRAM_SIZE (0x100000)
topcat_device::topcat_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
{
}
topcat_device::topcat_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: topcat_device(mconfig, TOPCAT, tag, owner, clock)
{
}
void topcat_device::device_start()
{
m_vram.resize(VRAM_SIZE);
m_cursor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(topcat_device::cursor_callback),this));
m_cursor_timer->adjust(attotime::from_hz(3));
}
void topcat_device::device_reset()
{
memset(&m_vram[0], 0, VRAM_SIZE);
m_palette[1] = rgb_t(255, 255, 255);
m_palette[0] = rgb_t(0, 0, 0);
m_pixel_replacement_rule = TOPCAT_REPLACE_RULE_SRC;
}
READ16_MEMBER(topcat_device::vram_r)
{
return m_vram[offset];
}
WRITE16_MEMBER(topcat_device::vram_w)
{
COMBINE_DATA(&m_vram[offset]);
}
TIMER_CALLBACK_MEMBER(topcat_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 topcat_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;
}
void topcat_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 topcat_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);
}
}
}
READ16_MEMBER(topcat_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);
return space.unmap();
}
return ret;
}
WRITE16_MEMBER(topcat_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;
}
}
uint32_t topcat_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
uint32_t *scanline;
int x, y;
uint32_t pixels;
for (y = 0; y < 768; y++)
{
scanline = &bitmap.pix32(y);
for (x = 0; x < 1024/2; x++)
{
pixels = m_vram[(y * 512) + x];
*scanline++ = m_palette[(pixels>>8) & 1];
*scanline++ = m_palette[(pixels & 1)];
}
}
return 0;
}

126
src/devices/video/topcat.h Normal file
View File

@ -0,0 +1,126 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
#ifndef MAME_VIDEO_TOPCAT_H_
#define MAME_VIDEO_TOPCAT_H_
#pragma once
#define MCFG_TOPCAT_FB_WIDTH(_pixels) \
downcast<topcat_device &>(*device).set_fb_width(_pixels);
#define MCFG_TOPCAT_FB_HEIGHT(_pixels) \
downcast<topcat_device &>(*device).set_fb_height(_pixels);
#define MCFG_TOPCAT_PLANES(_planes) \
downcast<topcat_device &>(*device).set_planes(_planes);
class topcat_device : public device_t
{
public:
topcat_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void set_fb_width(int _pixels) { m_fb_width = _pixels; }
void set_fb_height(int _pixels) { m_fb_height = _pixels; }
void set_planes(int _planes) { m_planes = _planes; }
TIMER_CALLBACK_MEMBER(cursor_callback);
DECLARE_READ16_MEMBER(vram_r);
DECLARE_WRITE16_MEMBER(vram_w);
DECLARE_READ16_MEMBER(ctrl_r);
DECLARE_WRITE16_MEMBER(ctrl_w);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
protected:
topcat_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void device_start() override;
virtual void device_reset() override;
private:
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;
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);
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_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_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;
int m_fb_width;
int m_fb_height;
int m_planes;
int m_plane_mask;
};
DECLARE_DEVICE_TYPE(TOPCAT, topcat_device)
#endif // MAME_VIDEO_TOPCAT_H_

View File

@ -301,6 +301,7 @@ const double XTAL::known_xtals[] = {
33'868'800, /* 33.8688_MHz_XTAL Usually used to drive 90's Yamaha OPL/FM chips with /2 divider */
34'000'000, /* 34_MHz_XTAL Gaelco PCBs */
34'291'712, /* 34.291712_MHz_XTAL Fairlight CMI master card */
35'904'000, /* 35.904_MHz_XTAL Used on HP98543 graphics board */
36'000'000, /* 36_MHz_XTAL Sega Model 1 video board */
38'769'220, /* 38.76922_MHz_XTAL Namco System 21 video board */
39'321'600, /* 39.3216_MHz_XTAL Sun 2/120 */