From b5937ea0e8c9702cea998f7e522169dffa3f4545 Mon Sep 17 00:00:00 2001 From: tyfighter Date: Thu, 31 Jan 2019 09:58:08 -0600 Subject: Indigo: move LG1 "Light" graphics support out to its own device for future sharing --- scripts/target/mame/mess.lua | 2 + src/mame/drivers/indigo.cpp | 385 +------------------------------------------ src/mame/video/light.cpp | 381 ++++++++++++++++++++++++++++++++++++++++++ src/mame/video/light.h | 75 +++++++++ 4 files changed, 464 insertions(+), 379 deletions(-) create mode 100644 src/mame/video/light.cpp create mode 100644 src/mame/video/light.h diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 5cae6e3dc38..6e268930be3 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -3056,6 +3056,8 @@ files { MAME_DIR .. "src/mame/drivers/4dpi.cpp", MAME_DIR .. "src/mame/drivers/indigo.cpp", MAME_DIR .. "src/mame/drivers/indy_indigo2.cpp", + MAME_DIR .. "src/mame/video/light.cpp", + MAME_DIR .. "src/mame/video/light.h", MAME_DIR .. "src/mame/video/newport.cpp", MAME_DIR .. "src/mame/video/newport.h", MAME_DIR .. "src/mame/video/crime.cpp", diff --git a/src/mame/drivers/indigo.cpp b/src/mame/drivers/indigo.cpp index e58056fce37..f5ceae47718 100644 --- a/src/mame/drivers/indigo.cpp +++ b/src/mame/drivers/indigo.cpp @@ -22,17 +22,12 @@ #include "machine/eepromser.h" #include "machine/hpc1.h" #include "machine/sgi.h" -#include "emupal.h" -#include "screen.h" - -#define ENABLE_ENTRY_GFX (1) +#include "video/light.h" #define LOG_UNKNOWN (1 << 0) #define LOG_INT (1 << 1) #define LOG_DSP (1 << 2) -#define LOG_GFX (1 << 3) -#define LOG_GFX_CMD (1 << 4) -#define LOG_ALL (LOG_UNKNOWN | LOG_INT | LOG_DSP | LOG_GFX | LOG_GFX_CMD) +#define LOG_ALL (LOG_UNKNOWN | LOG_INT | LOG_DSP) #define VERBOSE (LOG_UNKNOWN) #include "logmacro.h" @@ -44,7 +39,7 @@ public: : driver_device(mconfig, type, tag) , m_hpc(*this, "hpc") , m_eeprom(*this, "eeprom") - , m_palette(*this, "palette") + , m_light(*this, "lg1") { } @@ -58,96 +53,14 @@ protected: DECLARE_WRITE32_MEMBER(int_w); DECLARE_READ32_MEMBER(dsp_ram_r); DECLARE_WRITE32_MEMBER(dsp_ram_w); - DECLARE_READ32_MEMBER(entry_r); - DECLARE_WRITE32_MEMBER(entry_w); - - void do_rex_command(); void indigo_map(address_map &map); - uint32_t screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect); - - enum - { - REX15_PAGE0_SET = 0x00000000, - REX15_PAGE0_GO = 0x00000800, - REX15_PAGE1_SET = 0x00004790, - REX15_PAGE1_GO = 0x00004f90, - - REX15_P0REG_COMMAND = 0x00000000, - REX15_P0REG_XSTARTI = 0x0000000c, - REX15_P0REG_YSTARTI = 0x0000001c, - REX15_P0REG_XYMOVE = 0x00000034, - REX15_P0REG_COLORREDI = 0x00000038, - REX15_P0REG_COLORGREENI = 0x00000040, - REX15_P0REG_COLORBLUEI = 0x00000048, - REX15_P0REG_COLORBACK = 0x0000005c, - REX15_P0REG_ZPATTERN = 0x00000060, - REX15_P0REG_XENDI = 0x00000084, - REX15_P0REG_YENDI = 0x00000088, - - REX15_P1REG_WCLOCKREV = 0x00000054, - REX15_P1REG_CFGDATA = 0x00000058, - REX15_P1REG_CFGSEL = 0x0000005c, - REX15_P1REG_VC1_ADDRDATA = 0x00000060, - REX15_P1REG_CFGMODE = 0x00000068, - REX15_P1REG_XYOFFSET = 0x0000006c, - - REX15_OP_NOP = 0x00000000, - REX15_OP_DRAW = 0x00000001, - - REX15_OP_FLAG_BLOCK = 0x00000008, - REX15_OP_FLAG_LENGTH32 = 0x00000010, - REX15_OP_FLAG_QUADMODE = 0x00000020, - REX15_OP_FLAG_XYCONTINUE = 0x00000080, - REX15_OP_FLAG_STOPONX = 0x00000100, - REX15_OP_FLAG_STOPONY = 0x00000200, - REX15_OP_FLAG_ENZPATTERN = 0x00000400, - REX15_OP_FLAG_LOGICSRC = 0x00080000, - REX15_OP_FLAG_ZOPAQUE = 0x00800000, - REX15_OP_FLAG_ZCONTINUE = 0x01000000, - - REX15_WRITE_ADDR = 0x00, - REX15_PALETTE_RAM = 0x01, - REX15_PIXEL_READ_MASK = 0x02, - REX15_CONTROL = 0x06 - }; - - struct lg1_t - { - uint32_t m_config_sel; - uint32_t m_write_addr; - uint32_t m_control; - - uint32_t m_command; - uint32_t m_x_start_i; - uint32_t m_y_start_i; - uint32_t m_xy_move; - uint32_t m_color_red_i; - uint32_t m_color_green_i; - uint32_t m_color_blue_i; - uint32_t m_color_back; - uint32_t m_z_pattern; - uint32_t m_x_end_i; - uint32_t m_y_end_i; - uint32_t m_x_curr_i; - uint32_t m_y_curr_i; - - uint8_t m_palette_idx; - uint8_t m_palette_channel; - uint8_t m_palette_entry[3]; - uint8_t m_pix_read_mask[256]; - }; - required_device m_hpc; required_device m_eeprom; - required_device m_palette; std::unique_ptr m_dsp_ram; - + required_device m_light; address_space *m_space; - - lg1_t m_lg1; - std::unique_ptr m_framebuffer; }; class indigo3k_state : public indigo_state @@ -195,37 +108,11 @@ protected: void indigo_state::machine_start() { m_dsp_ram = std::make_unique(0x8000); - m_framebuffer = std::make_unique(1024*768); - - save_item(NAME(m_lg1.m_config_sel)); - save_item(NAME(m_lg1.m_write_addr)); - save_item(NAME(m_lg1.m_control)); - save_item(NAME(m_lg1.m_command)); - save_item(NAME(m_lg1.m_x_start_i)); - save_item(NAME(m_lg1.m_y_start_i)); - save_item(NAME(m_lg1.m_xy_move)); - save_item(NAME(m_lg1.m_color_red_i)); - save_item(NAME(m_lg1.m_color_green_i)); - save_item(NAME(m_lg1.m_color_blue_i)); - save_item(NAME(m_lg1.m_color_back)); - save_item(NAME(m_lg1.m_z_pattern)); - save_item(NAME(m_lg1.m_x_end_i)); - save_item(NAME(m_lg1.m_y_end_i)); - save_item(NAME(m_lg1.m_x_curr_i)); - save_item(NAME(m_lg1.m_y_curr_i)); - save_item(NAME(m_lg1.m_palette_idx)); - save_item(NAME(m_lg1.m_palette_channel)); - save_item(NAME(m_lg1.m_palette_entry)); - save_item(NAME(m_lg1.m_pix_read_mask)); - save_pointer(NAME(&m_dsp_ram[0]), 0x8000); - save_pointer(NAME(&m_framebuffer[0]), 1024*768); } void indigo_state::machine_reset() { - memset(&m_lg1, 0, sizeof(lg1_t)); - memset(&m_framebuffer[0], 0, 1024*768); } void indigo4k_state::machine_reset() @@ -259,262 +146,10 @@ WRITE32_MEMBER(indigo_state::dsp_ram_w) m_dsp_ram[offset] = data; } -READ32_MEMBER(indigo_state::entry_r) -{ - uint32_t ret = 0; - switch (offset) - { - case REX15_PAGE0_GO/4: - LOGMASKED(LOG_GFX, "%s: LG1 Read: Status(?) (Go) %08x = %08x & %08x\n", machine().describe_context(), 0x1f3f0000 + offset*4, ret, mem_mask); - do_rex_command(); - break; - case 0x0014/4: - ret = 0x033c0000; - LOGMASKED(LOG_GFX, "%s: LG1 Read: Presence Detect(?) %08x = %08x & %08x\n", machine().describe_context(), 0x1f3f0000 + offset*4, ret, mem_mask); - break; - default: - LOGMASKED(LOG_GFX, "%s: Unknown LG1 Read: %08x = %08x & %08x\n", machine().describe_context(), 0x1f3f0000 + offset*4, ret, mem_mask); - break; - } - return ret; -} - -void indigo_state::do_rex_command() -{ - if (m_lg1.m_command == 0) - { - return; - } - if (m_lg1.m_command == 0x30080329) - { - bool xycontinue = (m_lg1.m_command & REX15_OP_FLAG_XYCONTINUE); - bool copy = (m_lg1.m_command & REX15_OP_FLAG_LOGICSRC); - const uint32_t start_x = xycontinue ? m_lg1.m_x_curr_i : m_lg1.m_x_start_i; - const uint32_t start_y = xycontinue ? m_lg1.m_y_curr_i : m_lg1.m_y_start_i; - const uint32_t end_x = m_lg1.m_x_end_i; - const uint32_t end_y = m_lg1.m_y_end_i; - const uint32_t src_start_x = start_x + (m_lg1.m_xy_move >> 16); - const uint32_t src_start_y = start_y + (uint16_t)m_lg1.m_xy_move;; - - LOGMASKED(LOG_GFX, "LG1: Command %08x: Block copy from %d,%d-%d,%d inclusive.\n", m_lg1.m_command, start_x, start_y, end_x, end_y); - if (copy) - { - for (uint32_t y = start_y, src_y = src_start_y; y <= end_y; y++, src_y++) - for (uint32_t x = start_x, src_x = src_start_x; x <= end_x; x++, src_x++) - m_framebuffer[y*1024 + x] = m_framebuffer[src_y*1024 + src_x]; - } - else - { - for (uint32_t y = start_y; y <= end_y; y++) - for (uint32_t x = start_x; x <= end_x; x++) - m_framebuffer[y*1024 + x] = m_lg1.m_color_red_i; - } - } - else if (m_lg1.m_command == 0x30000329) - { - bool xycontinue = (m_lg1.m_command & REX15_OP_FLAG_XYCONTINUE); - uint32_t start_x = xycontinue ? m_lg1.m_x_curr_i : m_lg1.m_x_start_i; - uint32_t start_y = xycontinue ? m_lg1.m_y_curr_i : m_lg1.m_y_start_i; - uint32_t end_x = m_lg1.m_x_end_i; - uint32_t end_y = m_lg1.m_y_end_i; - - LOGMASKED(LOG_GFX, "LG1: Command %08x: Block draw from %d,%d-%d,%d inclusive.\n", m_lg1.m_command, start_x, start_y, end_x, end_y); - for (uint32_t y = start_y; y <= end_y; y++) - { - for (uint32_t x = start_x; x <= end_x; x++) - { - m_framebuffer[y*1024 + x] = m_lg1.m_color_red_i; - } - } - } - else if (m_lg1.m_command == 0x300005a1 || - m_lg1.m_command == 0x300005a9 || - m_lg1.m_command == 0x300005b9) - { - bool xycontinue = (m_lg1.m_command & REX15_OP_FLAG_XYCONTINUE); - uint32_t start_x = xycontinue ? m_lg1.m_x_curr_i : m_lg1.m_x_start_i; - uint32_t start_y = xycontinue ? m_lg1.m_y_curr_i : m_lg1.m_y_start_i; - uint32_t end_x = m_lg1.m_x_end_i; - LOGMASKED(LOG_GFX, "LG1: Command %08x: Pattern draw from %d-%d at %d\n", m_lg1.m_command, start_x, end_x, start_y); - for (uint32_t x = start_x; x <= end_x && x < (start_x + 32); x++) - { - if (BIT(m_lg1.m_z_pattern, 31 - (x - start_x))) - { - m_framebuffer[start_y*1024 + x] = m_lg1.m_color_red_i; - } - m_lg1.m_x_curr_i++; - } - - if (m_lg1.m_command & REX15_OP_FLAG_BLOCK) - { - if (m_lg1.m_x_curr_i > m_lg1.m_x_end_i) - { - m_lg1.m_y_curr_i--; - m_lg1.m_x_curr_i = m_lg1.m_x_start_i; - } - } - } - else - { - LOGMASKED(LOG_GFX_CMD | LOG_UNKNOWN, "%s: Unknown LG1 command: %08x\n", machine().describe_context(), m_lg1.m_command); - } -} - -WRITE32_MEMBER(indigo_state::entry_w) -{ - bool go = (offset >= REX15_PAGE1_GO/4) || (offset >= REX15_PAGE0_GO/4 && offset < REX15_PAGE1_SET/4); - - switch (offset) - { - case (REX15_PAGE0_SET+REX15_P0REG_COMMAND)/4: - case (REX15_PAGE0_GO+REX15_P0REG_COMMAND)/4: - m_lg1.m_command = data; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 Command Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - if (go) - do_rex_command(); - break; - case (REX15_PAGE0_SET+REX15_P0REG_XSTARTI)/4: - case (REX15_PAGE0_GO+REX15_P0REG_XSTARTI)/4: - m_lg1.m_x_start_i = data; - m_lg1.m_x_curr_i = m_lg1.m_x_start_i; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 XStartI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - break; - case (REX15_PAGE0_SET+REX15_P0REG_YSTARTI)/4: - case (REX15_PAGE0_GO+REX15_P0REG_YSTARTI)/4: - m_lg1.m_y_start_i = data; - m_lg1.m_y_curr_i = m_lg1.m_y_start_i; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 YStartI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - break; - case (REX15_PAGE0_SET+REX15_P0REG_XYMOVE)/4: - case (REX15_PAGE0_GO+REX15_P0REG_XYMOVE)/4: - m_lg1.m_xy_move = data; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 XYMove Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - if (go) - do_rex_command(); - break; - case (REX15_PAGE0_SET+REX15_P0REG_COLORREDI)/4: - case (REX15_PAGE0_GO+REX15_P0REG_COLORREDI)/4: - m_lg1.m_color_red_i = data; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 ColorRedI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - break; - case (REX15_PAGE0_SET+REX15_P0REG_COLORGREENI)/4: - case (REX15_PAGE0_GO+REX15_P0REG_COLORGREENI)/4: - m_lg1.m_color_green_i = data; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 ColorGreenI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - break; - case (REX15_PAGE0_SET+REX15_P0REG_COLORBLUEI)/4: - case (REX15_PAGE0_GO+REX15_P0REG_COLORBLUEI)/4: - m_lg1.m_color_blue_i = data; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 ColorBlueI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - break; - case (REX15_PAGE0_SET+REX15_P0REG_COLORBACK)/4: - case (REX15_PAGE0_GO+REX15_P0REG_COLORBACK)/4: - m_lg1.m_color_back = data; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 ColorBlueI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - break; - case (REX15_PAGE0_SET+REX15_P0REG_ZPATTERN)/4: - case (REX15_PAGE0_GO+REX15_P0REG_ZPATTERN)/4: - m_lg1.m_z_pattern = data; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 ZPattern Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - if (go) - do_rex_command(); - break; - case (REX15_PAGE0_SET+REX15_P0REG_XENDI)/4: - case (REX15_PAGE0_GO+REX15_P0REG_XENDI)/4: - m_lg1.m_x_end_i = data; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 XEndI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - break; - case (REX15_PAGE0_SET+REX15_P0REG_YENDI)/4: - case (REX15_PAGE0_GO+REX15_P0REG_YENDI)/4: - m_lg1.m_y_end_i = data; - LOGMASKED(LOG_GFX, "%s: LG1 REX1.5 YEndI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); - break; - - case (REX15_PAGE1_SET+REX15_P1REG_CFGSEL)/4: - case (REX15_PAGE1_GO+REX15_P1REG_CFGSEL)/4: - m_lg1.m_config_sel = data; - switch (data) - { - case REX15_WRITE_ADDR: - LOGMASKED(LOG_GFX, "%s: LG1 ConfigSel Write = %08x (Write Addr)\n", machine().describe_context(), data); - break; - case REX15_PALETTE_RAM: - LOGMASKED(LOG_GFX, "%s: LG1 ConfigSel Write = %08x (Palette RAM)\n", machine().describe_context(), data); - break; - case REX15_CONTROL: - LOGMASKED(LOG_GFX, "%s: LG1 ConfigSel Write = %08x (Control)\n", machine().describe_context(), data); - break; - case REX15_PIXEL_READ_MASK: - LOGMASKED(LOG_GFX, "%s: LG1 ConfigSel Write = %08x (Pixel Read Mask)\n", machine().describe_context(), data); - break; - default: - LOGMASKED(LOG_GFX, "%s: LG1 ConfigSel Write = %08x (Unknown)\n", machine().describe_context(), data); - break; - } - break; - case (REX15_PAGE1_SET+REX15_P1REG_CFGDATA)/4: - case (REX15_PAGE1_GO+REX15_P1REG_CFGDATA)/4: - if (go) // Ignore 'Go' writes for now, unsure what they do - break; - switch (m_lg1.m_config_sel) - { - case REX15_WRITE_ADDR: - LOGMASKED(LOG_GFX, "%s: LG1 ConfigSel Write: Setting WriteAddr to %08x\n", machine().describe_context(), data); - m_lg1.m_write_addr = data; - if (m_lg1.m_control == 0xf) - { - LOGMASKED(LOG_GFX, "%s: LG1 about to set palette entry %02x\n", machine().describe_context(), (uint8_t)data); - m_lg1.m_palette_idx = (uint8_t)data; - m_lg1.m_palette_channel = 0; - } - break; - case REX15_PALETTE_RAM: - LOGMASKED(LOG_GFX, "%s: LG1 ConfigSel Write: Setting Palette RAM %02x entry %d to %02x\n", machine().describe_context(), - m_lg1.m_palette_idx, m_lg1.m_palette_channel, (uint8_t)data); - m_lg1.m_palette_entry[m_lg1.m_palette_channel++] = (uint8_t)data; - if (m_lg1.m_palette_channel == 3) - { - m_palette->set_pen_color(m_lg1.m_palette_idx, m_lg1.m_palette_entry[0], m_lg1.m_palette_entry[1], m_lg1.m_palette_entry[2]); - } - break; - case REX15_CONTROL: - LOGMASKED(LOG_GFX, "%s: LG1 ConfigSel Write: Setting Control to %08x\n", machine().describe_context(), data); - m_lg1.m_control = data; - break; - case REX15_PIXEL_READ_MASK: - LOGMASKED(LOG_GFX, "%s: LG1 ConfigSel Write = %08x (Pixel Read Mask, entry %02x)\n", machine().describe_context(), data, m_lg1.m_palette_idx); - m_lg1.m_pix_read_mask[m_lg1.m_palette_idx] = (uint8_t)data; - break; - default: - LOGMASKED(LOG_GFX, "%s: LG1 Unknown ConfigData Write = %08x\n", machine().describe_context(), data); - break; - } - break; - default: - LOGMASKED(LOG_GFX, "%s: Unknown LG1 Write: %08x = %08x & %08x\n", machine().describe_context(), 0x1f3f0000 + offset*4, data, mem_mask); - break; - } -} - -uint32_t indigo_state::screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - const rgb_t *pens = m_palette->palette()->entry_list_raw(); - - for (int y = 0; y < 768; y++) - { - uint32_t *dst = &bitmap.pix32(y); - uint8_t *src = &m_framebuffer[y*1024]; - for (int x = 0; x < 1024; x++) - { - *dst++ = pens[*src++]; - } - } - return 0; -} void indigo_state::indigo_map(address_map &map) { - map(0x1f3f0000, 0x1f3fffff).rw(FUNC(indigo_state::entry_r), FUNC(indigo_state::entry_w)); + map(0x1f3f0000, 0x1f3fffff).rw(m_light, FUNC(light_video_device::entry_r), FUNC(light_video_device::entry_w)); map(0x1fb80000, 0x1fb8ffff).rw(m_hpc, FUNC(hpc1_device::read), FUNC(hpc1_device::write)); map(0x1fbd9000, 0x1fbd903f).rw(FUNC(indigo_state::int_r), FUNC(indigo_state::int_w)); map(0x1fbe0000, 0x1fbfffff).rw(FUNC(indigo_state::dsp_ram_r), FUNC(indigo_state::dsp_ram_w)); @@ -559,15 +194,7 @@ INPUT_PORTS_END void indigo_state::indigo_base(machine_config &config) { - /* video hardware */ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ - screen.set_size(1024, 768); - screen.set_visarea(0, 1024-1, 0, 768-1); - screen.set_screen_update(FUNC(indigo_state::screen_update)); - - PALETTE(config, m_palette).set_entries(256); + LIGHT_VIDEO(config, m_light); EEPROM_93C56_16BIT(config, m_eeprom); } diff --git a/src/mame/video/light.cpp b/src/mame/video/light.cpp new file mode 100644 index 00000000000..719113a9447 --- /dev/null +++ b/src/mame/video/light.cpp @@ -0,0 +1,381 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz, Tyson Smith +/* + Silicon Graphics LG1 "Light" graphics board used as + entry level graphics in the Indigo and IRIS Crimson. +*/ + +#include "emu.h" +#include "video/light.h" +#include "screen.h" + +#define LOG_REX (1 << 0) +#define LOG_ALL (LOG_REX) + +#define VERBOSE (0) +#include "logmacro.h" + +enum +{ + REX15_PAGE0_SET = 0x00000000, + REX15_PAGE0_GO = 0x00000800, + REX15_PAGE1_SET = 0x00004790, + REX15_PAGE1_GO = 0x00004f90, + + REX15_P0REG_COMMAND = 0x00000000, + REX15_P0REG_XSTARTI = 0x0000000c, + REX15_P0REG_YSTARTI = 0x0000001c, + REX15_P0REG_XYMOVE = 0x00000034, + REX15_P0REG_COLORREDI = 0x00000038, + REX15_P0REG_COLORGREENI = 0x00000040, + REX15_P0REG_COLORBLUEI = 0x00000048, + REX15_P0REG_COLORBACK = 0x0000005c, + REX15_P0REG_ZPATTERN = 0x00000060, + REX15_P0REG_XENDI = 0x00000084, + REX15_P0REG_YENDI = 0x00000088, + + REX15_P1REG_WCLOCKREV = 0x00000054, + REX15_P1REG_CFGDATA = 0x00000058, + REX15_P1REG_CFGSEL = 0x0000005c, + REX15_P1REG_VC1_ADDRDATA = 0x00000060, + REX15_P1REG_CFGMODE = 0x00000068, + REX15_P1REG_XYOFFSET = 0x0000006c, + + REX15_OP_NOP = 0x00000000, + REX15_OP_DRAW = 0x00000001, + + REX15_OP_FLAG_BLOCK = 0x00000008, + REX15_OP_FLAG_LENGTH32 = 0x00000010, + REX15_OP_FLAG_QUADMODE = 0x00000020, + REX15_OP_FLAG_XYCONTINUE = 0x00000080, + REX15_OP_FLAG_STOPONX = 0x00000100, + REX15_OP_FLAG_STOPONY = 0x00000200, + REX15_OP_FLAG_ENZPATTERN = 0x00000400, + REX15_OP_FLAG_LOGICSRC = 0x00080000, + REX15_OP_FLAG_ZOPAQUE = 0x00800000, + REX15_OP_FLAG_ZCONTINUE = 0x01000000, + + REX15_WRITE_ADDR = 0x00, + REX15_PALETTE_RAM = 0x01, + REX15_PIXEL_READ_MASK = 0x02, + REX15_CONTROL = 0x06 +}; + +DEFINE_DEVICE_TYPE(LIGHT_VIDEO, light_video_device, "light_video", "SGI Light graphics board") + + +light_video_device::light_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, LIGHT_VIDEO, tag, owner, clock) + , m_palette(*this, "palette") +{ +} + + +//------------------------------------------------- +// device_add_mconfig - device-specific machine configuration +//------------------------------------------------- + +void light_video_device::device_add_mconfig(machine_config &config) +{ + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_refresh_hz(60); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ + screen.set_size(x_res, y_res); + screen.set_visarea(0, x_res-1, 0, y_res-1); + screen.set_screen_update(FUNC(light_video_device::screen_update)); + + PALETTE(config, m_palette).set_entries(256); +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void light_video_device::device_start() +{ + m_framebuffer = std::make_unique(x_res*y_res); + + save_item(NAME(m_lg1.m_config_sel)); + save_item(NAME(m_lg1.m_write_addr)); + save_item(NAME(m_lg1.m_control)); + save_item(NAME(m_lg1.m_command)); + save_item(NAME(m_lg1.m_x_start_i)); + save_item(NAME(m_lg1.m_y_start_i)); + save_item(NAME(m_lg1.m_xy_move)); + save_item(NAME(m_lg1.m_color_red_i)); + save_item(NAME(m_lg1.m_color_green_i)); + save_item(NAME(m_lg1.m_color_blue_i)); + save_item(NAME(m_lg1.m_color_back)); + save_item(NAME(m_lg1.m_z_pattern)); + save_item(NAME(m_lg1.m_x_end_i)); + save_item(NAME(m_lg1.m_y_end_i)); + save_item(NAME(m_lg1.m_x_curr_i)); + save_item(NAME(m_lg1.m_y_curr_i)); + save_item(NAME(m_lg1.m_palette_idx)); + save_item(NAME(m_lg1.m_palette_channel)); + save_item(NAME(m_lg1.m_palette_entry)); + save_item(NAME(m_lg1.m_pix_read_mask)); + + save_pointer(NAME(&m_framebuffer[0]), x_res*y_res); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void light_video_device::device_reset() +{ + memset(&m_lg1, 0, sizeof(lg1_t)); + memset(&m_framebuffer[0], 0, x_res*y_res); +} + +uint32_t light_video_device::screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + const rgb_t *pens = m_palette->palette()->entry_list_raw(); + const uint8_t *src = &m_framebuffer[0]; + for (uint32_t y = 0; y < y_res; y++) { + uint32_t *dst = &bitmap.pix32(y); + for (uint32_t x = 0; x < x_res; x++) { + *dst++ = pens[*src++]; + } + } + return 0; +} + +READ32_MEMBER(light_video_device::entry_r) +{ + uint32_t ret = 0; + switch (offset) + { + case REX15_PAGE0_GO/4: + LOGMASKED(LOG_REX, "%s: LG1 Read: Status(?) (Go) %08x = %08x & %08x\n", machine().describe_context(), 0x1f3f0000 + offset*4, ret, mem_mask); + do_rex_command(); + break; + case 0x0014/4: + ret = 0x033c0000; + LOGMASKED(LOG_REX, "%s: LG1 Read: Presence Detect(?) %08x = %08x & %08x\n", machine().describe_context(), 0x1f3f0000 + offset*4, ret, mem_mask); + break; + default: + LOGMASKED(LOG_REX, "%s: Unknown LG1 Read: %08x = %08x & %08x\n", machine().describe_context(), 0x1f3f0000 + offset*4, ret, mem_mask); + break; + } + return ret; +} + +WRITE32_MEMBER(light_video_device::entry_w) +{ + bool go = (offset >= REX15_PAGE1_GO/4) || (offset >= REX15_PAGE0_GO/4 && offset < REX15_PAGE1_SET/4); + + switch (offset) + { + case (REX15_PAGE0_SET+REX15_P0REG_COMMAND)/4: + case (REX15_PAGE0_GO+REX15_P0REG_COMMAND)/4: + m_lg1.m_command = data; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 Command Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + if (go) + do_rex_command(); + break; + case (REX15_PAGE0_SET+REX15_P0REG_XSTARTI)/4: + case (REX15_PAGE0_GO+REX15_P0REG_XSTARTI)/4: + m_lg1.m_x_start_i = data; + m_lg1.m_x_curr_i = m_lg1.m_x_start_i; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 XStartI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + break; + case (REX15_PAGE0_SET+REX15_P0REG_YSTARTI)/4: + case (REX15_PAGE0_GO+REX15_P0REG_YSTARTI)/4: + m_lg1.m_y_start_i = data; + m_lg1.m_y_curr_i = m_lg1.m_y_start_i; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 YStartI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + break; + case (REX15_PAGE0_SET+REX15_P0REG_XYMOVE)/4: + case (REX15_PAGE0_GO+REX15_P0REG_XYMOVE)/4: + m_lg1.m_xy_move = data; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 XYMove Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + if (go) + do_rex_command(); + break; + case (REX15_PAGE0_SET+REX15_P0REG_COLORREDI)/4: + case (REX15_PAGE0_GO+REX15_P0REG_COLORREDI)/4: + m_lg1.m_color_red_i = data; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 ColorRedI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + break; + case (REX15_PAGE0_SET+REX15_P0REG_COLORGREENI)/4: + case (REX15_PAGE0_GO+REX15_P0REG_COLORGREENI)/4: + m_lg1.m_color_green_i = data; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 ColorGreenI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + break; + case (REX15_PAGE0_SET+REX15_P0REG_COLORBLUEI)/4: + case (REX15_PAGE0_GO+REX15_P0REG_COLORBLUEI)/4: + m_lg1.m_color_blue_i = data; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 ColorBlueI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + break; + case (REX15_PAGE0_SET+REX15_P0REG_COLORBACK)/4: + case (REX15_PAGE0_GO+REX15_P0REG_COLORBACK)/4: + m_lg1.m_color_back = data; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 ColorBlueI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + break; + case (REX15_PAGE0_SET+REX15_P0REG_ZPATTERN)/4: + case (REX15_PAGE0_GO+REX15_P0REG_ZPATTERN)/4: + m_lg1.m_z_pattern = data; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 ZPattern Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + if (go) + do_rex_command(); + break; + case (REX15_PAGE0_SET+REX15_P0REG_XENDI)/4: + case (REX15_PAGE0_GO+REX15_P0REG_XENDI)/4: + m_lg1.m_x_end_i = data; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 XEndI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + break; + case (REX15_PAGE0_SET+REX15_P0REG_YENDI)/4: + case (REX15_PAGE0_GO+REX15_P0REG_YENDI)/4: + m_lg1.m_y_end_i = data; + LOGMASKED(LOG_REX, "%s: LG1 REX1.5 YEndI Write (%s) = %08x\n", machine().describe_context(), (offset & 0x200) ? "Go" : "Set", data); + break; + + case (REX15_PAGE1_SET+REX15_P1REG_CFGSEL)/4: + case (REX15_PAGE1_GO+REX15_P1REG_CFGSEL)/4: + m_lg1.m_config_sel = data; + switch (data) + { + case REX15_WRITE_ADDR: + LOGMASKED(LOG_REX, "%s: LG1 ConfigSel Write = %08x (Write Addr)\n", machine().describe_context(), data); + break; + case REX15_PALETTE_RAM: + LOGMASKED(LOG_REX, "%s: LG1 ConfigSel Write = %08x (Palette RAM)\n", machine().describe_context(), data); + break; + case REX15_CONTROL: + LOGMASKED(LOG_REX, "%s: LG1 ConfigSel Write = %08x (Control)\n", machine().describe_context(), data); + break; + case REX15_PIXEL_READ_MASK: + LOGMASKED(LOG_REX, "%s: LG1 ConfigSel Write = %08x (Pixel Read Mask)\n", machine().describe_context(), data); + break; + default: + LOGMASKED(LOG_REX, "%s: LG1 ConfigSel Write = %08x (Unknown)\n", machine().describe_context(), data); + break; + } + break; + case (REX15_PAGE1_SET+REX15_P1REG_CFGDATA)/4: + case (REX15_PAGE1_GO+REX15_P1REG_CFGDATA)/4: + if (go) // Ignore 'Go' writes for now, unsure what they do + break; + switch (m_lg1.m_config_sel) + { + case REX15_WRITE_ADDR: + LOGMASKED(LOG_REX, "%s: LG1 ConfigSel Write: Setting WriteAddr to %08x\n", machine().describe_context(), data); + m_lg1.m_write_addr = data; + if (m_lg1.m_control == 0xf) + { + LOGMASKED(LOG_REX, "%s: LG1 about to set palette entry %02x\n", machine().describe_context(), (uint8_t)data); + m_lg1.m_palette_idx = (uint8_t)data; + m_lg1.m_palette_channel = 0; + } + break; + case REX15_PALETTE_RAM: + LOGMASKED(LOG_REX, "%s: LG1 ConfigSel Write: Setting Palette RAM %02x entry %d to %02x\n", machine().describe_context(), + m_lg1.m_palette_idx, m_lg1.m_palette_channel, (uint8_t)data); + m_lg1.m_palette_entry[m_lg1.m_palette_channel++] = (uint8_t)data; + if (m_lg1.m_palette_channel == 3) + { + m_palette->set_pen_color(m_lg1.m_palette_idx, m_lg1.m_palette_entry[0], m_lg1.m_palette_entry[1], m_lg1.m_palette_entry[2]); + } + break; + case REX15_CONTROL: + LOGMASKED(LOG_REX, "%s: LG1 ConfigSel Write: Setting Control to %08x\n", machine().describe_context(), data); + m_lg1.m_control = data; + break; + case REX15_PIXEL_READ_MASK: + LOGMASKED(LOG_REX, "%s: LG1 ConfigSel Write = %08x (Pixel Read Mask, entry %02x)\n", machine().describe_context(), data, m_lg1.m_palette_idx); + m_lg1.m_pix_read_mask[m_lg1.m_palette_idx] = (uint8_t)data; + break; + default: + LOGMASKED(LOG_REX, "%s: LG1 Unknown ConfigData Write = %08x\n", machine().describe_context(), data); + break; + } + break; + default: + LOGMASKED(LOG_REX, "%s: Unknown LG1 Write: %08x = %08x & %08x\n", machine().describe_context(), 0x1f3f0000 + offset*4, data, mem_mask); + break; + } +} + +void light_video_device::do_rex_command() +{ + if (m_lg1.m_command == 0) + { + return; + } + if (m_lg1.m_command == 0x30080329) + { + bool xycontinue = (m_lg1.m_command & REX15_OP_FLAG_XYCONTINUE); + bool copy = (m_lg1.m_command & REX15_OP_FLAG_LOGICSRC); + const uint32_t start_x = xycontinue ? m_lg1.m_x_curr_i : m_lg1.m_x_start_i; + const uint32_t start_y = xycontinue ? m_lg1.m_y_curr_i : m_lg1.m_y_start_i; + const uint32_t end_x = m_lg1.m_x_end_i; + const uint32_t end_y = m_lg1.m_y_end_i; + const uint32_t src_start_x = start_x + (m_lg1.m_xy_move >> 16); + const uint32_t src_start_y = start_y + (uint16_t)m_lg1.m_xy_move;; + + LOGMASKED(LOG_REX, "LG1: Command %08x: Block copy from %d,%d-%d,%d inclusive.\n", m_lg1.m_command, start_x, start_y, end_x, end_y); + if (copy) + { + for (uint32_t y = start_y, src_y = src_start_y; y <= end_y; y++, src_y++) + for (uint32_t x = start_x, src_x = src_start_x; x <= end_x; x++, src_x++) + m_framebuffer[y*x_res + x] = m_framebuffer[src_y*x_res + src_x]; + } + else + { + for (uint32_t y = start_y; y <= end_y; y++) + for (uint32_t x = start_x; x <= end_x; x++) + m_framebuffer[y*x_res + x] = m_lg1.m_color_red_i; + } + } + else if (m_lg1.m_command == 0x30000329) + { + bool xycontinue = (m_lg1.m_command & REX15_OP_FLAG_XYCONTINUE); + uint32_t start_x = xycontinue ? m_lg1.m_x_curr_i : m_lg1.m_x_start_i; + uint32_t start_y = xycontinue ? m_lg1.m_y_curr_i : m_lg1.m_y_start_i; + uint32_t end_x = m_lg1.m_x_end_i; + uint32_t end_y = m_lg1.m_y_end_i; + + LOGMASKED(LOG_REX, "LG1: Command %08x: Block draw from %d,%d-%d,%d inclusive.\n", m_lg1.m_command, start_x, start_y, end_x, end_y); + for (uint32_t y = start_y; y <= end_y; y++) + { + for (uint32_t x = start_x; x <= end_x; x++) + { + m_framebuffer[y*x_res + x] = m_lg1.m_color_red_i; + } + } + } + else if (m_lg1.m_command == 0x300005a1 || + m_lg1.m_command == 0x300005a9 || + m_lg1.m_command == 0x300005b9) + { + bool xycontinue = (m_lg1.m_command & REX15_OP_FLAG_XYCONTINUE); + uint32_t start_x = xycontinue ? m_lg1.m_x_curr_i : m_lg1.m_x_start_i; + uint32_t start_y = xycontinue ? m_lg1.m_y_curr_i : m_lg1.m_y_start_i; + uint32_t end_x = m_lg1.m_x_end_i; + LOGMASKED(LOG_REX, "LG1: Command %08x: Pattern draw from %d-%d at %d\n", m_lg1.m_command, start_x, end_x, start_y); + for (uint32_t x = start_x; x <= end_x && x < (start_x + 32); x++) + { + if (BIT(m_lg1.m_z_pattern, 31 - (x - start_x))) + { + m_framebuffer[start_y*x_res + x] = m_lg1.m_color_red_i; + } + m_lg1.m_x_curr_i++; + } + + if (m_lg1.m_command & REX15_OP_FLAG_BLOCK) + { + if (m_lg1.m_x_curr_i > m_lg1.m_x_end_i) + { + m_lg1.m_y_curr_i--; + m_lg1.m_x_curr_i = m_lg1.m_x_start_i; + } + } + } + else + { + LOGMASKED(LOG_REX, "%s: Unknown LG1 command: %08x\n", machine().describe_context(), m_lg1.m_command); + } +} diff --git a/src/mame/video/light.h b/src/mame/video/light.h new file mode 100644 index 00000000000..ffc9932d02e --- /dev/null +++ b/src/mame/video/light.h @@ -0,0 +1,75 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz, Tyson Smith +/* + Silicon Graphics LG1 "Light" graphics board used as + entry level graphics in the Indigo and IRIS Crimson. +*/ + +#ifndef MAME_VIDEO_LIGHT_H +#define MAME_VIDEO_LIGHT_H + +#pragma once + +#include "emupal.h" + +class light_video_device : public device_t +{ +public: + light_video_device(const machine_config &mconfig, const char *tag, device_t *owner) + : light_video_device(mconfig, tag, owner, (uint32_t)0) + { + } + + light_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + uint32_t screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect); + + DECLARE_READ32_MEMBER(entry_r); + DECLARE_WRITE32_MEMBER(entry_w); + + static constexpr uint32_t x_res = 1024; + static constexpr uint32_t y_res = 768; + +protected: + void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void device_reset() override; + +private: + void do_rex_command(); + + struct lg1_t + { + uint32_t m_config_sel; + uint32_t m_write_addr; + uint32_t m_control; + + uint32_t m_command; + uint32_t m_x_start_i; + uint32_t m_y_start_i; + uint32_t m_xy_move; + uint32_t m_color_red_i; + uint32_t m_color_green_i; + uint32_t m_color_blue_i; + uint32_t m_color_back; + uint32_t m_z_pattern; + uint32_t m_x_end_i; + uint32_t m_y_end_i; + uint32_t m_x_curr_i; + uint32_t m_y_curr_i; + + uint8_t m_palette_idx; + uint8_t m_palette_channel; + uint8_t m_palette_entry[3]; + uint8_t m_pix_read_mask[256]; + }; + lg1_t m_lg1; + + required_device m_palette; + std::unique_ptr m_framebuffer; +}; + +DECLARE_DEVICE_TYPE(LIGHT_VIDEO, light_video_device) + + +#endif // MAME_VIDEO_LIGHT_H -- cgit v1.2.3