From 8ef3dd279fd62cda60c26bfa85d44ad4716e057e Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Mon, 17 Jul 2023 15:15:30 +0700 Subject: sgi/light: pass power-on diagnostics --- src/mame/sgi/indigo.cpp | 9 +- src/mame/sgi/light.cpp | 480 +++++++++++++++++++----------------------------- src/mame/sgi/light.h | 185 ++++++++++++++----- 3 files changed, 334 insertions(+), 340 deletions(-) diff --git a/src/mame/sgi/indigo.cpp b/src/mame/sgi/indigo.cpp index b97d08db259..53d239bd434 100644 --- a/src/mame/sgi/indigo.cpp +++ b/src/mame/sgi/indigo.cpp @@ -20,6 +20,7 @@ #include "cpu/mips/mips1.h" #include "cpu/mips/r4000.h" #include "machine/eepromser.h" + #include "hpc1.h" #include "mc.h" #include "light.h" @@ -42,7 +43,7 @@ public: : driver_device(mconfig, type, tag) , m_hpc(*this, "hpc") , m_eeprom(*this, "eeprom") - , m_light(*this, "lg1") + , m_gfx(*this, "lg1") { } @@ -62,7 +63,7 @@ protected: required_device m_hpc; required_device m_eeprom; std::unique_ptr m_dsp_ram; - required_device m_light; + required_device m_gfx; address_space *m_space = nullptr; }; @@ -145,7 +146,7 @@ void indigo_state::dsp_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask) void indigo_state::indigo_map(address_map &map) { - map(0x1f3f0000, 0x1f3fffff).rw(m_light, FUNC(light_video_device::entry_r), FUNC(light_video_device::entry_w)); + map(0x1f3f0000, 0x1f3f7fff).m(m_gfx, FUNC(sgi_lg1_device::map)); 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)); @@ -169,7 +170,7 @@ INPUT_PORTS_END void indigo_state::indigo_base(machine_config &config) { - LIGHT_VIDEO(config, m_light); + SGI_LG1(config, m_gfx); EEPROM_93C56_16BIT(config, m_eeprom); } diff --git a/src/mame/sgi/light.cpp b/src/mame/sgi/light.cpp index c0fd7cc7b53..96ac802c175 100644 --- a/src/mame/sgi/light.cpp +++ b/src/mame/sgi/light.cpp @@ -5,45 +5,33 @@ entry level graphics in the Indigo and IRIS Crimson. */ +/* + * TODO: + * - devicify rex + * - slotify + * - later board revisions and LG2X2 dual-head variant + * + * WIP: + * - passes power-on diagnostic tests + * - usable for firmware graphic output + * - fails badly for IRIX graphic output + */ + #include "emu.h" #include "light.h" -#include "screen.h" #define LOG_REX (1U << 1) -#define LOG_ALL (LOG_REX) -#define VERBOSE (0) +//#define VERBOSE (LOG_GENERAL|LOG_REX) #include "logmacro.h" +static constexpr uint32_t x_res = 1024; +static constexpr uint32_t y_res = 768; + 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, @@ -54,328 +42,240 @@ enum 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") - +DEFINE_DEVICE_TYPE(SGI_LG1, sgi_lg1_device, "sgi_lg1", "SGI LG1") -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") +sgi_lg1_device::sgi_lg1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) + : device_t(mconfig, SGI_LG1, tag, owner, clock) + , m_vc1(*this, "vc1") + , m_lut1(*this, "lut1") + , m_screen(*this, "screen") { } +void sgi_lg1_device::device_add_mconfig(machine_config &config) +{ + SGI_VC1(config, m_vc1, 64_MHz_XTAL); + + // TODO: does LUT1 differ from Bt479? + BT479(config, m_lut1, 64_MHz_XTAL); -//------------------------------------------------- -// device_add_mconfig - device-specific machine configuration -//------------------------------------------------- + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + // TODO: video timing from VC1 + m_screen->set_raw(1024 * 768 * 60, 1024, 0, 1024, 768, 0, 768); + m_screen->set_screen_update(FUNC(sgi_lg1_device::screen_update)); +} -void light_video_device::device_add_mconfig(machine_config &config) +void sgi_lg1_device::device_start() { - 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); + m_vram = std::make_unique(0x10'0000); // 8xTC524256BJ-10 262,144x4 multiport dram + + save_pointer(NAME(m_vram), 0x10'0000); } +void sgi_lg1_device::device_reset() +{ +} -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- +void sgi_lg1_device::map(address_map &map) +{ + map(0x0000, 0x0003).select(0x0800).rw(FUNC(sgi_lg1_device::command_r), FUNC(sgi_lg1_device::command_w)); + map(0x0004, 0x0007).select(0x0800).rw(FUNC(sgi_lg1_device::aux1_r), FUNC(sgi_lg1_device::aux1_w)); + map(0x0008, 0x000b).select(0x0800).rw(FUNC(sgi_lg1_device::xstate_r), FUNC(sgi_lg1_device::xstate_w)); + map(0x000c, 0x000f).select(0x0800).rw(FUNC(sgi_lg1_device::xstarti_r), FUNC(sgi_lg1_device::xstarti_w)); + map(0x0010, 0x0013).select(0x0800).rw(FUNC(sgi_lg1_device::xstartf_r), FUNC(sgi_lg1_device::xstartf_w)); + map(0x0014, 0x0017).select(0x0800).rw(FUNC(sgi_lg1_device::xstart_r), FUNC(sgi_lg1_device::xstart_w)); + map(0x0018, 0x001b).select(0x0800).rw(FUNC(sgi_lg1_device::xendf_r), FUNC(sgi_lg1_device::xendf_w)); + map(0x001c, 0x001f).select(0x0800).rw(FUNC(sgi_lg1_device::ystarti_r), FUNC(sgi_lg1_device::ystarti_w)); + map(0x0020, 0x0023).select(0x0800).rw(FUNC(sgi_lg1_device::ystartf_r), FUNC(sgi_lg1_device::ystartf_w)); + map(0x0024, 0x0027).select(0x0800).rw(FUNC(sgi_lg1_device::ystart_r), FUNC(sgi_lg1_device::ystart_w)); + map(0x0028, 0x002b).select(0x0800).rw(FUNC(sgi_lg1_device::yendf_r), FUNC(sgi_lg1_device::yendf_w)); + map(0x002c, 0x002f).select(0x0800).rw(FUNC(sgi_lg1_device::xsave_r), FUNC(sgi_lg1_device::xsave_w)); + map(0x0030, 0x0033).select(0x0800).rw(FUNC(sgi_lg1_device::minorslope_r), FUNC(sgi_lg1_device::minorslope_w)); + map(0x0034, 0x0037).select(0x0800).rw(FUNC(sgi_lg1_device::xymove_r), FUNC(sgi_lg1_device::xymove_w)); + map(0x0038, 0x003b).select(0x0800).rw(FUNC(sgi_lg1_device::colori_r<0>), FUNC(sgi_lg1_device::colori_w<0>)); + map(0x003c, 0x003f).select(0x0800).rw(FUNC(sgi_lg1_device::colorf_r<0>), FUNC(sgi_lg1_device::colorf_w<0>)); + map(0x0040, 0x0043).select(0x0800).rw(FUNC(sgi_lg1_device::colori_r<1>), FUNC(sgi_lg1_device::colori_w<1>)); + map(0x0044, 0x0047).select(0x0800).rw(FUNC(sgi_lg1_device::colorf_r<1>), FUNC(sgi_lg1_device::colorf_w<1>)); + map(0x0048, 0x004b).select(0x0800).rw(FUNC(sgi_lg1_device::colori_r<2>), FUNC(sgi_lg1_device::colori_w<2>)); + map(0x004c, 0x004f).select(0x0800).rw(FUNC(sgi_lg1_device::colorf_r<2>), FUNC(sgi_lg1_device::colorf_w<2>)); + map(0x0050, 0x0053).select(0x0800).rw(FUNC(sgi_lg1_device::slopecolor_r<0>), FUNC(sgi_lg1_device::slopecolor_w<0>)); + map(0x0054, 0x0057).select(0x0800).rw(FUNC(sgi_lg1_device::slopecolor_r<1>), FUNC(sgi_lg1_device::slopecolor_w<1>)); + map(0x0058, 0x005b).select(0x0800).rw(FUNC(sgi_lg1_device::slopecolor_r<2>), FUNC(sgi_lg1_device::slopecolor_w<2>)); + map(0x005c, 0x005f).select(0x0800).rw(FUNC(sgi_lg1_device::colorback_r), FUNC(sgi_lg1_device::colorback_w)); + map(0x0060, 0x0063).select(0x0800).rw(FUNC(sgi_lg1_device::zpattern_r), FUNC(sgi_lg1_device::zpattern_w)); + map(0x0064, 0x0067).select(0x0800).rw(FUNC(sgi_lg1_device::lspattern_r), FUNC(sgi_lg1_device::lspattern_w)); + map(0x0068, 0x006b).select(0x0800).rw(FUNC(sgi_lg1_device::lsmode_r), FUNC(sgi_lg1_device::lsmode_w)); + map(0x006c, 0x006f).select(0x0800).rw(FUNC(sgi_lg1_device::aweight_r), FUNC(sgi_lg1_device::aweight_w)); + map(0x0070, 0x0073).select(0x0800).rw(FUNC(sgi_lg1_device::rwaux1_r), FUNC(sgi_lg1_device::rwaux1_w)); + map(0x0074, 0x0077).select(0x0800).rw(FUNC(sgi_lg1_device::rwaux2_r), FUNC(sgi_lg1_device::rwaux2_w)); + map(0x0078, 0x007b).select(0x0800).rw(FUNC(sgi_lg1_device::rwmask_r), FUNC(sgi_lg1_device::rwmask_w)); + map(0x007c, 0x007f).select(0x0800).rw(FUNC(sgi_lg1_device::smask_r<0>), FUNC(sgi_lg1_device::smask_w<0>)); + map(0x0080, 0x0083).select(0x0800).rw(FUNC(sgi_lg1_device::smask_r<1>), FUNC(sgi_lg1_device::smask_w<1>)); + map(0x0084, 0x0087).select(0x0800).rw(FUNC(sgi_lg1_device::xendi_r), FUNC(sgi_lg1_device::xendi_w)); + map(0x0088, 0x008b).select(0x0800).rw(FUNC(sgi_lg1_device::yendi_r), FUNC(sgi_lg1_device::yendi_w)); + + // configuration registers + map(0x4790, 0x4793).select(0x0800).rw(FUNC(sgi_lg1_device::smask_r<2>), FUNC(sgi_lg1_device::smask_w<2>)); + map(0x4794, 0x4797).select(0x0800).rw(FUNC(sgi_lg1_device::smask_r<3>), FUNC(sgi_lg1_device::smask_w<3>)); + map(0x4798, 0x479b).select(0x0800).rw(FUNC(sgi_lg1_device::smask_r<4>), FUNC(sgi_lg1_device::smask_w<4>)); + map(0x479c, 0x479f).select(0x0800).rw(FUNC(sgi_lg1_device::smask_r<5>), FUNC(sgi_lg1_device::smask_w<5>)); + map(0x47a0, 0x47a3).select(0x0800).rw(FUNC(sgi_lg1_device::smask_r<6>), FUNC(sgi_lg1_device::smask_w<6>)); + map(0x47a4, 0x47a7).select(0x0800).rw(FUNC(sgi_lg1_device::smask_r<7>), FUNC(sgi_lg1_device::smask_w<7>)); + map(0x47a8, 0x47ab).select(0x0800).rw(FUNC(sgi_lg1_device::aux2_r), FUNC(sgi_lg1_device::aux2_w)); + + map(0x47d8, 0x47db).select(0x0800).rw(FUNC(sgi_lg1_device::diagvram_r), FUNC(sgi_lg1_device::diagvram_w)); + map(0x47dc, 0x47df).select(0x0800).rw(FUNC(sgi_lg1_device::diagcid_r), FUNC(sgi_lg1_device::diagcid_w)); + + map(0x47e4, 0x47e7).select(0x0800).rw(FUNC(sgi_lg1_device::wclock_r), FUNC(sgi_lg1_device::wclock_w)); + map(0x47e8, 0x47eb).select(0x0800).rw(FUNC(sgi_lg1_device::dac_r), FUNC(sgi_lg1_device::dac_w)); + map(0x47ec, 0x47ef).select(0x0800).rw(FUNC(sgi_lg1_device::configsel_r), FUNC(sgi_lg1_device::configsel_w)); + map(0x47f0, 0x47f3).select(0x0800).rw(FUNC(sgi_lg1_device::vc1_r), FUNC(sgi_lg1_device::vc1_w)); + map(0x47f4, 0x47f7).select(0x0800).rw(FUNC(sgi_lg1_device::togglectxt_r), FUNC(sgi_lg1_device::togglectxt_w)); + map(0x47f8, 0x47fb).select(0x0800).rw(FUNC(sgi_lg1_device::configmode_r), FUNC(sgi_lg1_device::configmode_w)); + map(0x47fc, 0x47ff).select(0x0800).rw(FUNC(sgi_lg1_device::xywin_r), FUNC(sgi_lg1_device::xywin_w)); +} -void light_video_device::device_start() +u32 sgi_lg1_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect) { - 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); + u8 const *src = &m_vram[0]; + + for (unsigned y = screen.visible_area().min_y; y <= screen.visible_area().max_y; y++) + for (unsigned x = screen.visible_area().min_x; x <= screen.visible_area().max_x; x++) + bitmap.pix(y, x) = m_lut1->palette_lookup(*src++); + + return 0; } -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- +void sgi_lg1_device::minorslope_w(u32 data) +{ + if (BIT(data, 31)) + data = ~(data & 0x8000'ffffU) + 1; + + m_minorslope = data & 0x1'ffffU; +} -void light_video_device::device_reset() +template void sgi_lg1_device::slopecolor_w(u32 data) { - memset(&m_lg1, 0, sizeof(lg1_t)); - memset(&m_framebuffer[0], 0, x_res*y_res); + if (BIT(data, 31)) + data = ~(data & 0x800f'ffffU) + 1; + + m_slopecolor[Color] = ((data & 0x0008'0000U) << 1) | (data & 0x001f'ffffU); } -uint32_t light_video_device::screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect) +/* + * This logic assumes that there is an 8 bit latch used to interface to the + * LUT1 and VC1. The GO signal controls whether the latch is read or written + * by the host or by the addressed device. + */ + +u32 sgi_lg1_device::dac_r(offs_t offset) { - rgb_t const *const pens = m_palette->palette()->entry_list_raw(); - uint8_t const *src = &m_framebuffer[0]; - for (uint32_t y = 0; y < y_res; y++) { - uint32_t *dst = &bitmap.pix(y); - for (uint32_t x = 0; x < x_res; x++) { - *dst++ = pens[*src++]; - } - } - return 0; + if (offset & 0x200) + m_data = m_lut1->read(m_configsel); + + return m_data; } -uint32_t light_video_device::entry_r(offs_t offset, uint32_t mem_mask) +void sgi_lg1_device::dac_w(offs_t offset, u32 data) { - 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; + if (offset & 0x200) + m_lut1->write(m_configsel, m_data); + else + m_data = data; } -void light_video_device::entry_w(offs_t offset, uint32_t data, uint32_t mem_mask) +u32 sgi_lg1_device::vc1_r(offs_t offset) { - bool go = (offset >= REX15_PAGE1_GO/4) || (offset >= REX15_PAGE0_GO/4 && offset < REX15_PAGE1_SET/4); + if (offset & 0x200) + m_data = m_vc1->read(m_configsel); - 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 ColorBackI 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; - } + return m_data; +} + +void sgi_lg1_device::vc1_w(offs_t offset, u32 data) +{ + if (offset & 0x200) + m_vc1->write(m_configsel, m_data); + else + m_data = data; } -void light_video_device::do_rex_command() +void sgi_lg1_device::do_rex_command() { - if (m_lg1.m_command == 0) + if (m_command == 0) { return; } - if (m_lg1.m_command == 0x30080329) + if (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); + bool xycontinue = (m_command & REX15_OP_FLAG_XYCONTINUE); + bool copy = (m_command & REX15_OP_FLAG_LOGICSRC); + const uint32_t start_x = xycontinue ? m_xcurri : xstarti_r(); + const uint32_t start_y = xycontinue ? m_ycurri : ystarti_r(); + + const uint32_t src_start_x = start_x + (m_xymove >> 16); + const uint32_t src_start_y = start_y + u16(m_xymove); + + LOGMASKED(LOG_REX, "command %08x: Block copy from %d,%d-%d,%d inclusive.\n", m_command, start_x, start_y, xendi_r(), yendi_r()); 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]; + for (uint32_t y = start_y, src_y = src_start_y; y <= yendi_r(); y++, src_y++) + for (uint32_t x = start_x, src_x = src_start_x; x <= xendi_r(); x++, src_x++) + m_vram[y*x_res + x] = m_vram[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; + for (uint32_t y = start_y; y <= yendi_r(); y++) + for (uint32_t x = start_x; x <= xendi_r(); x++) + m_vram[y*x_res + x] = colori_r<0>(); } } - else if (m_lg1.m_command == 0x30000329) + else if (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++) + bool xycontinue = (m_command & REX15_OP_FLAG_XYCONTINUE); + uint32_t start_x = xycontinue ? m_xcurri : xstarti_r(); + uint32_t start_y = xycontinue ? m_ycurri : ystarti_r(); + + LOGMASKED(LOG_REX, "command %08x: Block draw from %d,%d-%d,%d inclusive.\n", m_command, start_x, start_y, xendi_r(), yendi_r()); + for (uint32_t y = start_y; y <= yendi_r(); y++) { - for (uint32_t x = start_x; x <= end_x; x++) + for (uint32_t x = start_x; x <= xendi_r(); x++) { - m_framebuffer[y*x_res + x] = m_lg1.m_color_red_i; + m_vram[y*x_res + x] = colori_r<0>(); } } } - else if (m_lg1.m_command == 0x300005a1 || - m_lg1.m_command == 0x300005a9 || - m_lg1.m_command == 0x300005b9) + else if (m_command == 0x300005a1 || + m_command == 0x300005a9 || + 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++) + bool xycontinue = (m_command & REX15_OP_FLAG_XYCONTINUE); + uint32_t start_x = xycontinue ? m_xcurri : xstarti_r(); + uint32_t start_y = xycontinue ? m_ycurri : ystarti_r(); + + LOGMASKED(LOG_REX, "command %08x: Pattern draw from %d-%d at %d\n", m_command, start_x, xendi_r(), start_y); + for (uint32_t x = start_x; x <= xendi_r() && x < (start_x + 32); x++) { - if (BIT(m_lg1.m_z_pattern, 31 - (x - start_x))) + if (BIT(m_zpattern, 31 - (x - start_x))) { - m_framebuffer[start_y*x_res + x] = m_lg1.m_color_red_i; + m_vram[start_y*x_res + x] = colori_r<0>(); } - m_lg1.m_x_curr_i++; + m_xcurri++; } - if (m_lg1.m_command & REX15_OP_FLAG_BLOCK) + if (m_command & REX15_OP_FLAG_BLOCK) { - if (m_lg1.m_x_curr_i > m_lg1.m_x_end_i) + if (m_xcurri > xendi_r()) { - m_lg1.m_y_curr_i--; - m_lg1.m_x_curr_i = m_lg1.m_x_start_i; + m_ycurri--; + m_xcurri = xstarti_r(); } } } else { - LOGMASKED(LOG_REX, "%s: Unknown LG1 command: %08x\n", machine().describe_context(), m_lg1.m_command); + LOGMASKED(LOG_REX, "%s: unknown command: %08x\n", machine().describe_context(), m_command); } } diff --git a/src/mame/sgi/light.h b/src/mame/sgi/light.h index 1a17c52225f..65f825c477e 100644 --- a/src/mame/sgi/light.h +++ b/src/mame/sgi/light.h @@ -10,66 +10,159 @@ #pragma once -#include "emupal.h" +#include "video/bt47x.h" +#include "vc1.h" -class light_video_device : public device_t +#include "screen.h" + +class sgi_lg1_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); + auto write_vblank() { return m_screen.lookup()->screen_vblank(); } - uint32_t screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect); + sgi_lg1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0); - uint32_t entry_r(offs_t offset, uint32_t mem_mask = ~0); - void entry_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - - static constexpr uint32_t x_res = 1024; - static constexpr uint32_t y_res = 768; + void map(address_map &map); protected: + // device_t implementation void device_add_mconfig(machine_config &config) override; virtual void device_start() override; virtual void device_reset() override; -private: + u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect); + void do_rex_command(); - struct lg1_t - { - uint32_t m_config_sel = 0; - uint32_t m_write_addr = 0; - uint32_t m_control = 0; - - uint32_t m_command = 0; - uint32_t m_x_start_i = 0; - uint32_t m_y_start_i = 0; - uint32_t m_xy_move = 0; - uint32_t m_color_red_i = 0; - uint32_t m_color_green_i = 0; - uint32_t m_color_blue_i = 0; - uint32_t m_color_back = 0; - uint32_t m_z_pattern = 0; - uint32_t m_x_end_i = 0; - uint32_t m_y_end_i = 0; - uint32_t m_x_curr_i = 0; - uint32_t m_y_curr_i = 0; - - uint8_t m_palette_idx = 0; - uint8_t m_palette_channel = 0; - 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; -}; + // rex register read handlers + u32 command_r(offs_t offset) { if (offset & 0x0200) do_rex_command(); return m_command; } + u32 aux1_r() { return m_aux1; } + u32 xstate_r() { return m_xstate; } + u32 xstart_r() { return m_xstart; } + u32 xstarti_r() { return m_xstart >> 15; } + u32 xstartf_r() { return m_xstart >> 4; } + u32 xendf_r() { return m_xend >> 4; } + u32 ystarti_r() { return m_ystart >> 15; } + u32 ystartf_r() { return m_ystart >> 4; } + u32 ystart_r() { return m_ystart; } + u32 yendf_r() { return m_yend >> 4; } + u32 xsave_r() { return m_xsave; } + u32 minorslope_r() { return m_minorslope; } + u32 xymove_r() { return m_xymove; } + template u32 colori_r() { return m_color[Color] >> 11; } + template u32 colorf_r() { return m_color[Color]; } + template u32 slopecolor_r() { return m_slopecolor[Color]; } + u32 colorback_r() { return m_colorback; } + u32 zpattern_r() { return m_zpattern; } + u32 lspattern_r() { return m_lspattern; } + u32 lsmode_r() { return m_lsmode; } + u32 aweight_r() { return m_aweight; } + u32 rwaux1_r() { return m_rwaux1; } + u32 rwaux2_r() { return m_rwaux2; } + u32 rwmask_r() { return m_rwmask; } + u32 xendi_r() { return m_xend >> 15; } + u32 yendi_r() { return m_yend >> 15; } + + // rex register write handlers + void command_w(offs_t offset, u32 data) { m_command = data; if (offset & 0x0200) do_rex_command(); } + void aux1_w(u32 data) { m_aux1 = data & 0x03ffU; } + void xstate_w(u32 data) { m_xstate = data; } + void xstarti_w(u32 data) { m_xstart = (data & 0x0fffU) << 15; m_xcurri = data & 0x0fffU; } + void xstartf_w(u32 data) { m_xstart = (data & 0x007fffffU) << 4; m_xcurri = (data >> 11) & 0x0fffU; } + void xstart_w(u32 data) { m_xstart = data & 0x07ffffffU; } + void xendf_w(u32 data) { m_xend = (data & 0x007ff800U) << 4; } + void ystarti_w(u32 data) { m_ystart = (data & 0x0fffU) << 15; m_ycurri = data & 0x0fffU; } + void ystartf_w(u32 data) { m_ystart = (data & 0x007fffffU) << 4; m_ycurri = (data >> 11) & 0x0fffU; } + void ystart_w(u32 data) { m_ystart = data & 0x07ffffffU; } + void yendf_w(u32 data) { m_yend = (data & 0x007ff800U) << 4; } + void xsave_w(u32 data) { m_xsave = data & 0x0fffU; } + void minorslope_w(u32 data); + void xymove_w(offs_t offset, u32 data) { m_xymove = data; if (offset & 0x0200) do_rex_command(); } + template void colori_w(offs_t offset, u32 data) { m_color[Color] = (data & 0xffU) << 11; if (offset & 0x0200) do_rex_command(); } + template void colorf_w(u32 data) { m_color[Color] = data & 0x000fffffU; } + template void slopecolor_w(u32 data); + void colorback_w(u32 data) { m_colorback = data & 0xffU; } + void zpattern_w(offs_t offset, u32 data) { m_zpattern = data; if (offset & 0x0200) do_rex_command(); } + void lspattern_w(u32 data) { m_lspattern = data; } + void lsmode_w(u32 data) { m_lsmode = data & 0x000fffffU; } + void aweight_w(u32 data) { m_aweight = data; } + void rwaux1_w(u32 data) { m_rwaux1 = data; } + void rwaux2_w(u32 data) { m_rwaux2 = data; } + void rwmask_w(u32 data) { m_rwmask = data & 0xffffU; } + void xendi_w(offs_t offset, u32 data) { m_xend = (data & 0x0fffU) << 15; } + void yendi_w(offs_t offset, u32 data) { m_yend = (data & 0x0fffU) << 15; } + + // configuration register read handlers + template u32 smask_r() { return m_smask[Index]; } + u32 aux2_r() { return m_aux2; } + u32 diagvram_r() { return m_diagvram; } + u32 diagcid_r() { return m_diagcid; } + u32 wclock_r() { return m_configsel == 4 ? 0 : m_wclock; } // board revision? + u32 dac_r(offs_t offset); + u32 configsel_r() { return m_configsel; } + u32 vc1_r(offs_t offset); + u32 togglectxt_r() { return m_togglectxt; } + u32 configmode_r() { return m_configmode; } + u32 xywin_r() { return m_xywin; } + + // configuration register write handlers + template void smask_w(u32 data) { m_smask[Index] = data & 0x03ff03ffU; } + void aux2_w(u32 data) { m_aux2 = data & 0x7fffffffU; } + void diagvram_w(u32 data) { m_diagvram = data; } + void diagcid_w(u32 data) { m_diagcid = data; } + void wclock_w(u32 data) { m_wclock = data & 0xffU; } + void dac_w(offs_t offset, u32 data); + void configsel_w(u32 data) { m_configsel = data & 7; } + void vc1_w(offs_t offset, u32 data); + void togglectxt_w(u32 data) { m_togglectxt = data; } + void configmode_w(u32 data) { m_configmode = data; } + void xywin_w(u32 data) { m_xywin = data & 0x0fff0fffU; } -DECLARE_DEVICE_TYPE(LIGHT_VIDEO, light_video_device) +private: + required_device m_vc1; + required_device m_lut1; + required_device m_screen; + std::unique_ptr m_vram; + + // rex registers + u32 m_command; + u32 m_aux1; + u32 m_xstate; + u32 m_xstart; + u32 m_ystart; + u32 m_xymove; + u32 m_color[3]; + u32 m_slopecolor[3]; + u32 m_colorback; + u32 m_zpattern; + u32 m_lspattern; + u32 m_lsmode; + u32 m_aweight; + u32 m_rwaux1; + u32 m_rwaux2; + u32 m_rwmask; + u32 m_xend; + u32 m_yend; + u32 m_xsave; + u32 m_minorslope; + + // configuration registers + u32 m_smask[8]; + u32 m_aux2; + u32 m_diagvram; + u32 m_diagcid; + u32 m_wclock; + u32 m_configsel; + u32 m_togglectxt; + u32 m_configmode; + u32 m_xywin; + + // other state + u32 m_xcurri; + u32 m_ycurri; + u8 m_data; +}; +DECLARE_DEVICE_TYPE(SGI_LG1, sgi_lg1_device) #endif // MAME_SGI_LIGHT_H -- cgit v1.2.3