// license:BSD-3-Clause // copyright-holders:Patrick Mackinlay /* * Silicon Graphics Multiplexed Multimode Graphics Processor (XMAP2). */ #include "emu.h" #include "sgi_xmap2.h" #define LOG_GENERAL (1U << 0) //#define VERBOSE (LOG_GENERAL) #include "logmacro.h" DEFINE_DEVICE_TYPE(SGI_XMAP2, sgi_xmap2_device, "sgi_xmap2", "SGI XMAP2") sgi_xmap2_device::sgi_xmap2_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, SGI_XMAP2, tag, owner, clock) , device_palette_interface(mconfig, *this) , m_options_port(*this, "^options") , m_map_select(false) { } void sgi_xmap2_device::device_start() { // save state save_item(NAME(m_addr)); save_item(NAME(m_color)); save_item(NAME(m_overlay)); save_item(NAME(m_mode)); save_item(NAME(m_wid_aux)); save_item(NAME(m_map_select)); } void sgi_xmap2_device::device_reset() { m_options = m_options_port->read(); } u8 sgi_xmap2_device::reg_r(offs_t offset) { switch (offset) { case 0: // nop break; case 1: // blue data if (m_addr & 0x1000) return m_color[m_map_select ? m_addr : (m_addr & 0xfff)].b(); else if (m_addr < 0x10) return m_overlay[m_addr].b(); break; case 2: // green data if (m_addr & 0x1000) return m_color[m_map_select ? m_addr : (m_addr & 0xfff)].g(); else if (m_addr < 0x10) return m_overlay[m_addr].g(); break; case 3: // red data if (m_addr & 0x1000) return m_color[m_map_select ? m_addr : (m_addr & 0xfff)].r(); else if (m_addr < 0x10) return m_overlay[m_addr].r(); break; case 4: // increment address // TODO: should reading increment the address register? //m_addr = (m_addr + 1) & 0x1fff; LOG("read address increment\n"); break; case 5: // other data if (m_addr < 0x20) { u16 const mode = m_mode[(m_addr >> 1) & 0xf]; return BIT(m_addr, 0) ? (mode >> 8) : u8(mode); } else if (m_addr == 0x20) return m_wid_aux; else if (m_addr == 0x21) return m_options; else logerror("read unknown address 0x%04x\n", m_addr); break; case 6: // address msb return m_addr >> 8; case 7: // address lsb return u8(m_addr); } return 0; } void sgi_xmap2_device::reg_w(offs_t offset, u8 data) { switch (offset) { case 0: // nop break; case 1: // blue data if (m_addr & 0x1000) { unsigned const index = m_map_select ? m_addr : (m_addr & 0xfff); m_color[index].set_b(data); set_pen_blue_level(index & 0xfff, data); } else if (m_addr < 0x10) { m_overlay[m_addr].set_b(data); set_pen_blue_level(0x1000 + m_addr, data); } break; case 2: // green data if (m_addr & 0x1000) { unsigned const index = m_map_select ? m_addr : (m_addr & 0xfff); m_color[index].set_g(data); set_pen_green_level(index & 0xfff, data); } else if (m_addr < 0x10) { m_overlay[m_addr].set_g(data); set_pen_green_level(0x1000 + m_addr, data); } break; case 3: // red data if (m_addr & 0x1000) { unsigned const index = m_map_select ? m_addr : (m_addr & 0xfff); m_color[index].set_r(data); set_pen_red_level(index & 0xfff, data); } else if (m_addr < 0x10) { m_overlay[m_addr].set_r(data); set_pen_red_level(0x1000 + m_addr, data); } break; case 4: // increment address m_addr = (m_addr + 1) & 0x1fff; break; case 5: // other data if (m_addr < 0x20) { u16 &mode = m_mode[(m_addr >> 1) & 0xf]; if (BIT(m_addr, 0)) mode = (u16(data & 0x3f) << 8) | (mode & 0x00ff); else mode = (mode & 0x3f00) | data; } else if (m_addr == 0x20) m_wid_aux = BIT(data, 0); else logerror("write unknown address 0x%04x\n", m_addr); break; case 6: // address msb m_addr = u16((data & 0x1f) << 8) | (m_addr & 0x00ff); break; case 7: // address lsb m_addr = (m_addr & 0x1f00) | data; break; } } void sgi_xmap2_device::map_select_w(int state) { if (m_map_select ^ bool(state)) { m_map_select = bool(state); // update mame palette unsigned const base = m_map_select ? 4096 : 0; for (unsigned i = 0; i < 4096; i++) set_pen_color(i, m_color[base + i]); } }