mirror of
https://github.com/holub/mame
synced 2025-04-23 08:49:55 +03:00
4dpi: refactoring (nw)
* added dip switches for graphics hardware * devicified xmap2 * overlay/underlay support
This commit is contained in:
parent
1b016d02dc
commit
4cfde79a28
@ -3216,6 +3216,8 @@ files {
|
||||
MAME_DIR .. "src/mame/video/sgi_ge5.h",
|
||||
MAME_DIR .. "src/mame/video/sgi_re2.cpp",
|
||||
MAME_DIR .. "src/mame/video/sgi_re2.h",
|
||||
MAME_DIR .. "src/mame/video/sgi_xmap2.cpp",
|
||||
MAME_DIR .. "src/mame/video/sgi_xmap2.h",
|
||||
}
|
||||
|
||||
createMESSProjects(_target, _subtarget, "sharp")
|
||||
|
@ -31,7 +31,7 @@
|
||||
* - https://github.com/NetBSD/src/tree/trunk/sys/arch/sgimips/
|
||||
*
|
||||
* TODO:
|
||||
* - graphics, audio, printer
|
||||
* - audio, printer
|
||||
* - devicify ioc1 and ctl1
|
||||
*
|
||||
* Status:
|
||||
|
@ -38,10 +38,10 @@
|
||||
*
|
||||
* TODO:
|
||||
* - host dma
|
||||
* - refactor display subsystem
|
||||
* - display registers
|
||||
* - save state
|
||||
* - slotify (SGI, MCA, ISA)
|
||||
* - separate raster and display systems?
|
||||
*/
|
||||
/*
|
||||
* Irix 4.0.5 IDE WIP
|
||||
@ -71,8 +71,9 @@ DEFINE_DEVICE_TYPE(SGI_GR1, sgi_gr1_device, "sgi_gr1", "SGI GR1 Graphics")
|
||||
sgi_gr1_device::sgi_gr1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, SGI_GR1, tag, owner, clock)
|
||||
, m_screen(*this, "screen")
|
||||
, m_re(*this, "re2")
|
||||
, m_ge(*this, "ge5")
|
||||
, m_re(*this, "re2")
|
||||
, m_xmap(*this, "xmap%u", 0U)
|
||||
, m_cursor(*this, "cursor%u", 0U)
|
||||
, m_ramdac(*this, "ramdac%u", 0U)
|
||||
, m_vblank_cb(*this)
|
||||
@ -80,18 +81,33 @@ sgi_gr1_device::sgi_gr1_device(machine_config const &mconfig, char const *tag, d
|
||||
{
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START(sgi_gr1)
|
||||
PORT_START("options")
|
||||
PORT_DIPNAME(0x08, 0x08, "Turbo")
|
||||
PORT_DIPSETTING(0x00, DEF_STR(Yes))
|
||||
PORT_DIPSETTING(0x08, DEF_STR(No))
|
||||
PORT_DIPNAME(0x10, 0x00, "Z Buffer")
|
||||
PORT_DIPSETTING(0x00, DEF_STR(Yes))
|
||||
PORT_DIPSETTING(0x10, DEF_STR(No))
|
||||
INPUT_PORTS_END
|
||||
|
||||
void sgi_gr1_device::map(address_map &map)
|
||||
{
|
||||
// TODO: bank based on mar_msb
|
||||
|
||||
map(0x0000, 0x03ff).rw(m_ge, FUNC(sgi_ge5_device::code_r), FUNC(sgi_ge5_device::code_w));
|
||||
|
||||
map(0x0400, 0x041f).rw(FUNC(sgi_gr1_device::xmap2_r<0>), FUNC(sgi_gr1_device::xmap2_w<0>)).umask32(0x000000ff);
|
||||
map(0x0420, 0x043f).rw(FUNC(sgi_gr1_device::xmap2_r<1>), FUNC(sgi_gr1_device::xmap2_w<1>)).umask32(0x000000ff);
|
||||
map(0x0440, 0x045f).rw(FUNC(sgi_gr1_device::xmap2_r<2>), FUNC(sgi_gr1_device::xmap2_w<2>)).umask32(0x000000ff);
|
||||
map(0x0460, 0x047f).rw(FUNC(sgi_gr1_device::xmap2_r<3>), FUNC(sgi_gr1_device::xmap2_w<3>)).umask32(0x000000ff);
|
||||
map(0x0480, 0x049f).rw(FUNC(sgi_gr1_device::xmap2_r<4>), FUNC(sgi_gr1_device::xmap2_w<4>)).umask32(0x000000ff);
|
||||
map(0x04a0, 0x04bf).w(FUNC(sgi_gr1_device::xmap2_bc_w)).umask32(0x000000ff);
|
||||
map(0x0400, 0x041f).rw(m_xmap[0], FUNC(sgi_xmap2_device::reg_r), FUNC(sgi_xmap2_device::reg_w)).umask32(0x000000ff);
|
||||
map(0x0420, 0x043f).rw(m_xmap[1], FUNC(sgi_xmap2_device::reg_r), FUNC(sgi_xmap2_device::reg_w)).umask32(0x000000ff);
|
||||
map(0x0440, 0x045f).rw(m_xmap[2], FUNC(sgi_xmap2_device::reg_r), FUNC(sgi_xmap2_device::reg_w)).umask32(0x000000ff);
|
||||
map(0x0460, 0x047f).rw(m_xmap[3], FUNC(sgi_xmap2_device::reg_r), FUNC(sgi_xmap2_device::reg_w)).umask32(0x000000ff);
|
||||
map(0x0480, 0x049f).rw(m_xmap[4], FUNC(sgi_xmap2_device::reg_r), FUNC(sgi_xmap2_device::reg_w)).umask32(0x000000ff);
|
||||
map(0x04a0, 0x04bf).lw8("xmap_broadcast",
|
||||
[this](offs_t offset, u8 data)
|
||||
{
|
||||
for (sgi_xmap2_device *xmap : m_xmap)
|
||||
xmap->reg_w(offset, data);
|
||||
}).umask32(0x000000ff);
|
||||
|
||||
map(0x04c0, 0x04c3).rw(FUNC(sgi_gr1_device::dr1_r), FUNC(sgi_gr1_device::dr1_w)).umask32(0xff000000);
|
||||
map(0x04e0, 0x04e3).rw(FUNC(sgi_gr1_device::dr0_r), FUNC(sgi_gr1_device::dr0_w)).umask32(0xff000000);
|
||||
@ -143,38 +159,39 @@ void sgi_gr1_device::device_add_mconfig(machine_config &config)
|
||||
*/
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
||||
m_screen->set_raw(pixel_clock, 1680, 246, 246 + 1280, 1065, 39, 39 + 1024);
|
||||
m_screen->set_screen_update(FUNC(sgi_gr1_device::screen_update));
|
||||
m_screen->set_screen_update(m_re.finder_tag(), FUNC(sgi_re2_device::screen_update));
|
||||
m_screen->screen_vblank().set([this](int state) { m_vblank_cb(state); });
|
||||
|
||||
|
||||
SGI_GE5(config, m_ge, 10_MHz_XTAL);
|
||||
m_ge->fifo_empty().set([this]() { return int(m_fifo.empty()); });
|
||||
m_ge->fifo_read().set(FUNC(sgi_gr1_device::ge_fifo_r));
|
||||
m_ge->re_r().set(m_re, FUNC(sgi_re2_device::reg_r));
|
||||
m_ge->re_w().set(m_re, FUNC(sgi_re2_device::reg_w));
|
||||
|
||||
BT431(config, m_cursor[0], pixel_clock / 5);
|
||||
BT431(config, m_cursor[1], pixel_clock / 5);
|
||||
|
||||
SGI_RE2(config, m_re, 0);
|
||||
m_re->out_rdy().set(m_ge, FUNC(sgi_ge5_device::re_rdy_w));
|
||||
m_re->out_drq().set(m_ge, FUNC(sgi_ge5_device::re_drq_w));
|
||||
m_re->vram_r().set(
|
||||
[this](offs_t offset)
|
||||
{
|
||||
return m_vram[offset];
|
||||
});
|
||||
m_re->vram_w().set(
|
||||
[this](offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_vram[offset]);
|
||||
});
|
||||
|
||||
SGI_XMAP2(config, m_xmap[0], pixel_clock / 5);
|
||||
SGI_XMAP2(config, m_xmap[1], pixel_clock / 5);
|
||||
SGI_XMAP2(config, m_xmap[2], pixel_clock / 5);
|
||||
SGI_XMAP2(config, m_xmap[3], pixel_clock / 5);
|
||||
SGI_XMAP2(config, m_xmap[4], pixel_clock / 5);
|
||||
|
||||
BT431(config, m_cursor[0], pixel_clock / 5);
|
||||
BT431(config, m_cursor[1], pixel_clock / 5);
|
||||
|
||||
BT457(config, m_ramdac[0], pixel_clock);
|
||||
BT457(config, m_ramdac[1], pixel_clock);
|
||||
BT457(config, m_ramdac[2], pixel_clock);
|
||||
}
|
||||
|
||||
|
||||
ioport_constructor sgi_gr1_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(sgi_gr1);
|
||||
}
|
||||
|
||||
void sgi_gr1_device::device_start()
|
||||
{
|
||||
m_vblank_cb.resolve_safe();
|
||||
@ -182,9 +199,6 @@ void sgi_gr1_device::device_start()
|
||||
|
||||
//save_item(NAME());
|
||||
|
||||
m_vram = std::make_unique<u32[]>(1280 * 1024);
|
||||
m_dram = std::make_unique<u32[]>(1280 * 1024);
|
||||
|
||||
m_reset = true;
|
||||
}
|
||||
|
||||
@ -199,83 +213,14 @@ void sgi_gr1_device::device_reset()
|
||||
m_fifo.clear();
|
||||
}
|
||||
|
||||
u32 sgi_gr1_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect)
|
||||
void sgi_gr1_device::dr4_w(u8 data)
|
||||
{
|
||||
// TODO: underlay
|
||||
LOG("dr4_w 0x%02x\n", data);
|
||||
|
||||
// TODO: variable topscan row and column
|
||||
for (unsigned screen_y = screen.visible_area().min_y, mem_y = 1023; screen_y <= screen.visible_area().max_y; screen_y++, mem_y--)
|
||||
for (unsigned screen_x = screen.visible_area().min_x, mem_x = 0; screen_x <= screen.visible_area().max_x; screen_x++, mem_x++)
|
||||
{
|
||||
unsigned const offset = (mem_y * 0x500) + mem_x;
|
||||
unsigned const bank = mem_x % 5;
|
||||
m_dr4 = (m_dr4 & ~DR4_WM) | (data & DR4_WM);
|
||||
|
||||
u32 const data = m_vram[offset];
|
||||
u8 const overlay = (m_cursor[0]->cur_r(screen_x, screen_y) ? 1 : 0) | (m_cursor[1]->cur_r(screen_x, screen_y) ? 2 : 0);
|
||||
u16 const mode = m_xmap2[bank].mode[data >> 28];
|
||||
|
||||
switch (mode & 0x07)
|
||||
{
|
||||
case 0: // 8 bit ci single buffer
|
||||
{
|
||||
u16 const ci = BIT(mode, 9) ? (mode & 0x0f00) | u8(data) : u8(data);
|
||||
rgb_t const cm = m_xmap2[bank].color[(m_dr4 & DR4_MS) ? ci | 0x1000 : ci];
|
||||
|
||||
bitmap.pix(screen_y, screen_x) = rgb_t(
|
||||
m_ramdac[0]->lookup(cm.r(), overlay),
|
||||
m_ramdac[1]->lookup(cm.g(), overlay),
|
||||
m_ramdac[2]->lookup(cm.b(), overlay));
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // 4 bit ci double buffer
|
||||
{
|
||||
u8 const fb = BIT(mode, 3) ? u8(data) >> 4 : data & 0x0f;
|
||||
u16 const ci = BIT(mode, 9) ? (mode & 0x0f00) | fb : fb;
|
||||
rgb_t const cm = m_xmap2[bank].color[(m_dr4 & DR4_MS) ? ci | 0x1000 : ci];
|
||||
|
||||
bitmap.pix(screen_y, screen_x) = rgb_t(
|
||||
m_ramdac[0]->lookup(cm.r(), overlay),
|
||||
m_ramdac[1]->lookup(cm.g(), overlay),
|
||||
m_ramdac[2]->lookup(cm.b(), overlay));
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // 12 bit ci double buffer
|
||||
{
|
||||
u8 const fb = u16(BIT(mode, 3) ? data >> 12 : data) & 0x0fff;
|
||||
u16 const ci = BIT(mode, 9) ? (mode & 0x0f00) | (fb & 0xff) : fb;
|
||||
rgb_t const cm = m_xmap2[bank].color[(m_dr4 & DR4_MS) ? ci | 0x1000 : ci];
|
||||
|
||||
bitmap.pix(screen_y, screen_x) = rgb_t(
|
||||
m_ramdac[0]->lookup(cm.r(), overlay),
|
||||
m_ramdac[1]->lookup(cm.g(), overlay),
|
||||
m_ramdac[2]->lookup(cm.b(), overlay));
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // 24 bit rgb single buffer
|
||||
bitmap.pix(screen_y, screen_x) = rgb_t(
|
||||
m_ramdac[0]->lookup(u8(data >> 0), overlay),
|
||||
m_ramdac[1]->lookup(u8(data >> 8), overlay),
|
||||
m_ramdac[2]->lookup(u8(data >> 16), overlay));
|
||||
break;
|
||||
|
||||
case 5: // 12 bit rgb double buffer
|
||||
bitmap.pix(screen_y, screen_x) = BIT(mode, 3) ?
|
||||
rgb_t(
|
||||
m_ramdac[0]->lookup((u8(data >> 0) & 0xf0) | (u8(data >> 4) & 0x0f), overlay),
|
||||
m_ramdac[1]->lookup((u8(data >> 8) & 0xf0) | (u8(data >> 12) & 0x0f), overlay),
|
||||
m_ramdac[2]->lookup((u8(data >> 16) & 0xf0) | (u8(data >> 20) & 0x0f), overlay)) :
|
||||
rgb_t(
|
||||
m_ramdac[0]->lookup((u8(data << 4) & 0xf0) | (u8(data >> 0) & 0x0f), overlay),
|
||||
m_ramdac[1]->lookup((u8(data >> 4) & 0xf0) | (u8(data >> 8) & 0x0f), overlay),
|
||||
m_ramdac[2]->lookup((u8(data >> 12) & 0xf0) | (u8(data >> 16) & 0x0f), overlay));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
for (sgi_xmap2_device *xmap : m_xmap)
|
||||
xmap->map_select_w(m_dr4 & DR4_MS);
|
||||
}
|
||||
|
||||
u64 sgi_gr1_device::ge_fifo_r()
|
||||
@ -324,120 +269,3 @@ void sgi_gr1_device::reset_w(int state)
|
||||
|
||||
m_reset = !state;
|
||||
}
|
||||
|
||||
template <unsigned Channel> u8 sgi_gr1_device::xmap2_r(offs_t offset)
|
||||
{
|
||||
xmap2 const x = m_xmap2[Channel];
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // nop
|
||||
break;
|
||||
|
||||
case 1: // blue data
|
||||
if (x.addr & 0x1000)
|
||||
return x.color[(m_dr4 & DR4_MS) ? x.addr : (x.addr & 0xfff)].b();
|
||||
else if (x.addr < 0x10)
|
||||
return x.overlay[x.addr].b();
|
||||
break;
|
||||
|
||||
case 2: // green data
|
||||
if (x.addr & 0x1000)
|
||||
return x.color[(m_dr4 & DR4_MS) ? x.addr : (x.addr & 0xfff)].g();
|
||||
else if (x.addr < 0x10)
|
||||
return x.overlay[x.addr].g();
|
||||
break;
|
||||
|
||||
case 3: // red data
|
||||
if (x.addr & 0x1000)
|
||||
return x.color[(m_dr4 & DR4_MS) ? x.addr : (x.addr & 0xfff)].r();
|
||||
else if (x.addr < 0x10)
|
||||
return x.overlay[x.addr].r();
|
||||
break;
|
||||
|
||||
case 4: // increment address
|
||||
// TODO: should reading increment the address register?
|
||||
//x.addr = (x.addr + 1) & 0x1fff;
|
||||
LOG("read address increment\n");
|
||||
break;
|
||||
|
||||
case 5: // other data
|
||||
if (x.addr < 0x20)
|
||||
{
|
||||
u16 const mode = x.mode[(x.addr >> 1) & 0xf];
|
||||
|
||||
return BIT(x.addr, 0) ? (mode >> 8) : u8(mode);
|
||||
}
|
||||
else if (x.addr == 0x20)
|
||||
return x.wid_aux;
|
||||
else if (x.addr == 0x21)
|
||||
return 0x0; // 0x08==no turbo option, 0x10==no z buffer
|
||||
break;
|
||||
|
||||
case 6: // address msb
|
||||
return x.addr >> 8;
|
||||
|
||||
case 7: // address lsb
|
||||
return u8(x.addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <unsigned Channel> void sgi_gr1_device::xmap2_w(offs_t offset, u8 data)
|
||||
{
|
||||
xmap2 &x = m_xmap2[Channel];
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // nop
|
||||
break;
|
||||
|
||||
case 1: // blue data
|
||||
if (x.addr & 0x1000)
|
||||
x.color[(m_dr4 & DR4_MS) ? x.addr : (x.addr & 0xfff)].set_b(data);
|
||||
else if (x.addr < 0x10)
|
||||
x.overlay[x.addr].set_b(data);
|
||||
break;
|
||||
|
||||
case 2: // green data
|
||||
if (x.addr & 0x1000)
|
||||
x.color[(m_dr4 & DR4_MS) ? x.addr : (x.addr & 0xfff)].set_g(data);
|
||||
else if (x.addr < 0x10)
|
||||
x.overlay[x.addr].set_g(data);
|
||||
break;
|
||||
|
||||
case 3: // red data
|
||||
if (x.addr & 0x1000)
|
||||
x.color[(m_dr4 & DR4_MS) ? x.addr : (x.addr & 0xfff)].set_r(data);
|
||||
else if (x.addr < 0x10)
|
||||
x.overlay[x.addr].set_r(data);
|
||||
break;
|
||||
|
||||
case 4: // increment address
|
||||
x.addr = (x.addr + 1) & 0x1fff;
|
||||
break;
|
||||
|
||||
case 5: // other data
|
||||
if (x.addr < 0x20)
|
||||
{
|
||||
u16 &mode = x.mode[(x.addr >> 1) & 0xf];
|
||||
|
||||
if (BIT(x.addr, 0))
|
||||
mode = (u16(data & 0x3f) << 8) | (mode & 0x00ff);
|
||||
else
|
||||
mode = (mode & 0x3f00) | data;
|
||||
}
|
||||
else if (x.addr == 0x20)
|
||||
x.wid_aux = BIT(data, 0);
|
||||
break;
|
||||
|
||||
case 6: // address msb
|
||||
x.addr = u16((data & 0x1f) << 8) | (x.addr & 0x00ff);
|
||||
break;
|
||||
|
||||
case 7: // address lsb
|
||||
x.addr = (x.addr & 0x1f00) | data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "screen.h"
|
||||
#include "video/sgi_ge5.h"
|
||||
#include "video/sgi_re2.h"
|
||||
#include "video/sgi_xmap2.h"
|
||||
#include "video/bt45x.h"
|
||||
#include "video/bt431.h"
|
||||
|
||||
@ -31,12 +32,11 @@ public:
|
||||
|
||||
protected:
|
||||
// device_t overrides
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect);
|
||||
|
||||
u8 dr0_r() { return m_dr0; }
|
||||
u8 dr1_r() { return m_dr1; }
|
||||
u8 dr2_r() { return m_dr2; }
|
||||
@ -46,27 +46,17 @@ protected:
|
||||
void dr1_w(u8 data) { m_dr1 = (m_dr1 & ~DR1_WM) | (data & DR1_WM); m_ge->cwen_w(BIT(data, 1)); }
|
||||
void dr2_w(u8 data) { m_dr2 = (m_dr2 & ~DR2_WM) | (data & DR2_WM); }
|
||||
void dr3_w(u8 data) { m_dr3 = (m_dr3 & ~DR3_WM) | (data & DR3_WM); }
|
||||
void dr4_w(u8 data) { m_dr4 = (m_dr4 & ~DR4_WM) | (data & DR4_WM); }
|
||||
void dr4_w(u8 data);
|
||||
|
||||
u64 ge_fifo_r();
|
||||
u32 fifo_r() { return u32(ge_fifo_r()); }
|
||||
void fifo_w(offs_t offset, u32 data, u32 mem_mask);
|
||||
|
||||
template <unsigned Channel> u8 xmap2_r(offs_t offset);
|
||||
template <unsigned Channel> void xmap2_w(offs_t offset, u8 data);
|
||||
void xmap2_bc_w(offs_t offset, u8 data)
|
||||
{
|
||||
xmap2_w<0>(offset, data);
|
||||
xmap2_w<1>(offset, data);
|
||||
xmap2_w<2>(offset, data);
|
||||
xmap2_w<3>(offset, data);
|
||||
xmap2_w<4>(offset, data);
|
||||
}
|
||||
|
||||
private:
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<sgi_re2_device> m_re;
|
||||
required_device<sgi_ge5_device> m_ge;
|
||||
required_device<sgi_re2_device> m_re;
|
||||
required_device_array<sgi_xmap2_device, 5> m_xmap;
|
||||
required_device_array<bt431_device, 2> m_cursor;
|
||||
required_device_array<bt457_device, 3> m_ramdac;
|
||||
|
||||
@ -137,19 +127,6 @@ private:
|
||||
|
||||
util::fifo<u64, 512> m_fifo;
|
||||
|
||||
std::unique_ptr<u32[]> m_vram;
|
||||
std::unique_ptr<u32[]> m_dram;
|
||||
|
||||
struct xmap2
|
||||
{
|
||||
u16 addr;
|
||||
rgb_t color[8192];
|
||||
rgb_t overlay[16];
|
||||
u16 mode[16];
|
||||
bool wid_aux;
|
||||
}
|
||||
m_xmap2[5];
|
||||
|
||||
bool m_reset;
|
||||
};
|
||||
|
||||
|
@ -51,10 +51,12 @@ DEFINE_DEVICE_TYPE(SGI_RE2, sgi_re2_device, "sgi_re2", "SGI Raster Engine 2")
|
||||
|
||||
sgi_re2_device::sgi_re2_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, SGI_RE2, tag, owner, clock)
|
||||
, m_xmap(*this, "^xmap%u", 0U)
|
||||
, m_cursor(*this, "^cursor%u", 0U)
|
||||
, m_ramdac(*this, "^ramdac%u", 0U)
|
||||
, m_options_port(*this, "^options")
|
||||
, m_rdy_cb(*this)
|
||||
, m_drq_cb(*this)
|
||||
, m_vram_r(*this)
|
||||
, m_vram_w(*this)
|
||||
, m_rdy(false)
|
||||
, m_drq(false)
|
||||
{
|
||||
@ -65,8 +67,8 @@ void sgi_re2_device::device_start()
|
||||
m_rdy_cb.resolve();
|
||||
m_drq_cb.resolve();
|
||||
|
||||
m_vram_r.resolve();
|
||||
m_vram_w.resolve();
|
||||
m_vram = std::make_unique<u32[]>(1280 * 1024);
|
||||
m_dram = std::make_unique<u32[]>(1280 * 1024);
|
||||
|
||||
// save state
|
||||
for (unsigned i = 0; i < ARRAY_LENGTH(m_reg); i++)
|
||||
@ -81,6 +83,10 @@ void sgi_re2_device::device_start()
|
||||
|
||||
void sgi_re2_device::device_reset()
|
||||
{
|
||||
u8 const options = m_options_port->read();
|
||||
m_vram_mask = 0xffffffffU;
|
||||
m_dram_mask = (options & 0x10) ? 0xffffffff : 0;
|
||||
|
||||
m_state = IDLE;
|
||||
m_ir_pending = false;
|
||||
|
||||
@ -281,12 +287,12 @@ void sgi_re2_device::draw_shaded_span()
|
||||
{
|
||||
/*
|
||||
* raster operation logic:
|
||||
*
|
||||
u32 const result =
|
||||
(m_func[0] & src & dst) +
|
||||
(m_func[1] & src & ~dst) +
|
||||
(m_func[2] & ~src & dst) +
|
||||
(m_func[3] & ~src & ~dst);
|
||||
*
|
||||
u32 const result =
|
||||
(m_func[0] & src & dst) +
|
||||
(m_func[1] & src & ~dst) +
|
||||
(m_func[2] & ~src & dst) +
|
||||
(m_func[3] & ~src & ~dst);
|
||||
*/
|
||||
|
||||
u32 const mask = (m_reg[REG_AUXMASK] << 24) | m_reg[REG_PIXMASK];
|
||||
@ -307,7 +313,7 @@ void sgi_re2_device::draw_shaded_span()
|
||||
{
|
||||
u32 const color = (m_r >> 11) << 0 | (m_g >> 11) << 8 | (m_b >> 11) << 16;
|
||||
|
||||
m_vram_w(offset, aux | color, mask);
|
||||
vram_w(offset, aux | color, mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -332,7 +338,7 @@ void sgi_re2_device::draw_flat_span(unsigned const n)
|
||||
{
|
||||
u32 const color = (m_r >> 11) << 0 | (m_g >> 11) << 8 | (m_b >> 11) << 16;
|
||||
|
||||
m_vram_w(offset + i, aux | color, mask);
|
||||
vram_w(offset + i, aux | color, mask);
|
||||
}
|
||||
|
||||
if ((i % n) == 0)
|
||||
@ -360,7 +366,7 @@ void sgi_re2_device::read_buffer()
|
||||
switch (m_reg[REG_RWMODE])
|
||||
{
|
||||
case RWMODE_FB_P:
|
||||
m_reg[REG_RWDATA] = m_vram_r((m_y >> 14) * 0x500 + (m_x >> 14));
|
||||
m_reg[REG_RWDATA] = m_vram[(m_y >> 14) * 0x500 + (m_x >> 14)];
|
||||
break;
|
||||
}
|
||||
|
||||
@ -401,7 +407,7 @@ void sgi_re2_device::write_buffer()
|
||||
switch (m_reg[REG_RWMODE])
|
||||
{
|
||||
case RWMODE_UAUX:
|
||||
m_vram_w(offset, data << 24, (m_reg[REG_AUXMASK] & (m_nopup ? 0xf : 0xc)) << 24);
|
||||
vram_w(offset, data << 24, (m_reg[REG_AUXMASK] & (m_nopup ? 0xf : 0xc)) << 24);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -439,9 +445,10 @@ bool sgi_re2_device::wid(unsigned const ir, offs_t const offset)
|
||||
if ((ir == IR_TOPLINE || ir == IR_BOTLINE) && !m_reg[REG_ENABLWID])
|
||||
return true;
|
||||
|
||||
unsigned const wid = m_vram_r(offset) >> 28;
|
||||
unsigned const wid = m_vram[offset] >> 28;
|
||||
|
||||
if (m_reg[REG_FBOPTION])
|
||||
// 2 or 4 wid bitplanes?
|
||||
if (m_reg[REG_FBOPTION] & 1)
|
||||
{
|
||||
if (BIT(m_reg[REG_DEPTHFN], 3))
|
||||
return (wid & 0xe) == (m_reg[REG_CURWID] & 0xe);
|
||||
@ -461,3 +468,76 @@ bool sgi_re2_device::pattern(unsigned const x, unsigned const n) const
|
||||
|
||||
return BIT(m_pat, 31 - index);
|
||||
}
|
||||
|
||||
u32 sgi_re2_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect)
|
||||
{
|
||||
// TODO: variable topscan row and column
|
||||
for (unsigned screen_y = screen.visible_area().min_y, mem_y = 1023; screen_y <= screen.visible_area().max_y; screen_y++, mem_y--)
|
||||
for (unsigned screen_x = screen.visible_area().min_x, mem_x = 0; screen_x <= screen.visible_area().max_x; screen_x++, mem_x++)
|
||||
{
|
||||
unsigned const channel = mem_x % 5;
|
||||
u32 const data = m_vram[(mem_y * 0x500) + mem_x];
|
||||
u16 const mode = m_xmap[channel]->mode_r(data >> 28);
|
||||
|
||||
// default is 24 bit rgb single buffered
|
||||
rgb_t color = rgb_t(data >> 0, data >> 8, data >> 16);
|
||||
|
||||
// check overlay or underlay
|
||||
if (((data >> 20) & mode & sgi_xmap2_device::MODE_OE) || ((mode & sgi_xmap2_device::MODE_UE) && !(data & 0x00ffffffU)))
|
||||
color = m_xmap[channel]->overlay_r(data >> 24);
|
||||
else
|
||||
switch (mode & sgi_xmap2_device::MODE_DM)
|
||||
{
|
||||
case 0: // 8 bit indexed single buffered
|
||||
{
|
||||
u16 const index = BIT(mode, sgi_xmap2_device::BIT_ME) ? ((mode & sgi_xmap2_device::MODE_MC) >> 2) | u8(data) : u8(data);
|
||||
|
||||
color = m_xmap[channel]->pen_color(index);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // 4 bit indexed double buffered
|
||||
{
|
||||
u8 const buffer = BIT(mode, sgi_xmap2_device::BIT_BS) ? u8(data) >> 4 : data & 0x0f;
|
||||
u16 const index = BIT(mode, sgi_xmap2_device::BIT_ME) ? ((mode & sgi_xmap2_device::MODE_MC) >> 2) | buffer : buffer;
|
||||
|
||||
color = m_xmap[channel]->pen_color(index);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // 12 bit indexed double buffered
|
||||
{
|
||||
u16 const buffer = u16(BIT(mode, sgi_xmap2_device::BIT_BS) ? data >> 12 : data) & 0x0fff;
|
||||
u16 const index = BIT(mode, sgi_xmap2_device::BIT_ME) ? ((mode & sgi_xmap2_device::MODE_MC) >> 2) | (buffer & 0xff) : buffer;
|
||||
|
||||
color = m_xmap[channel]->pen_color(index);
|
||||
}
|
||||
break;
|
||||
|
||||
case 5: // 12 bit rgb double buffered
|
||||
color = BIT(mode, sgi_xmap2_device::BIT_BS) ?
|
||||
rgb_t(
|
||||
((data >> 0x00) & 0xf0) | ((data >> 0x04) & 0x0f),
|
||||
((data >> 0x08) & 0xf0) | ((data >> 0x0c) & 0x0f),
|
||||
((data >> 0x10) & 0xf0) | ((data >> 0x14) & 0x0f)) :
|
||||
rgb_t(
|
||||
((data << 0x04) & 0xf0) | ((data >> 0x00) & 0x0f),
|
||||
((data >> 0x04) & 0xf0) | ((data >> 0x08) & 0x0f),
|
||||
((data >> 0x0c) & 0xf0) | ((data >> 0x10) & 0x0f));
|
||||
break;
|
||||
}
|
||||
|
||||
// read the cursor devices
|
||||
u8 const cursor =
|
||||
(m_cursor[0]->cur_r(screen_x, screen_y) ? 1 : 0) |
|
||||
(m_cursor[1]->cur_r(screen_x, screen_y) ? 2 : 0);
|
||||
|
||||
// apply the gamma ramp and output the pixel
|
||||
bitmap.pix(screen_y, screen_x) = rgb_t(
|
||||
m_ramdac[0]->lookup(color.r(), cursor),
|
||||
m_ramdac[1]->lookup(color.g(), cursor),
|
||||
m_ramdac[2]->lookup(color.b(), cursor));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,6 +6,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "video/sgi_xmap2.h"
|
||||
#include "video/bt45x.h"
|
||||
#include "video/bt431.h"
|
||||
#include "screen.h"
|
||||
|
||||
class sgi_re2_device : public device_t
|
||||
{
|
||||
public:
|
||||
@ -14,13 +19,12 @@ public:
|
||||
auto out_rdy() { return m_rdy_cb.bind(); }
|
||||
auto out_drq() { return m_drq_cb.bind(); }
|
||||
|
||||
auto vram_r() { return m_vram_r.bind(); }
|
||||
auto vram_w() { return m_vram_w.bind(); }
|
||||
|
||||
// device_t overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect);
|
||||
|
||||
enum re_register : unsigned
|
||||
{
|
||||
// buffered registers (write only unless noted)
|
||||
@ -149,13 +153,17 @@ protected:
|
||||
|
||||
void increment();
|
||||
|
||||
void vram_w(offs_t const offset, u32 const data, u32 const mem_mask) { m_vram[offset] = (m_vram[offset] & ~mem_mask) | (data & mem_mask & m_vram_mask); }
|
||||
|
||||
private:
|
||||
required_device_array<sgi_xmap2_device, 5> m_xmap;
|
||||
required_device_array<bt431_device, 2> m_cursor;
|
||||
required_device_array<bt457_device, 3> m_ramdac;
|
||||
required_ioport m_options_port;
|
||||
|
||||
devcb_write_line m_rdy_cb;
|
||||
devcb_write_line m_drq_cb;
|
||||
|
||||
devcb_read32 m_vram_r;
|
||||
devcb_write32 m_vram_w;
|
||||
|
||||
// state machine
|
||||
emu_timer *m_step;
|
||||
enum re_state : unsigned
|
||||
@ -202,6 +210,11 @@ private:
|
||||
unsigned m_ir;
|
||||
|
||||
rectangle m_clip;
|
||||
|
||||
std::unique_ptr<u32[]> m_vram;
|
||||
std::unique_ptr<u32[]> m_dram;
|
||||
u32 m_vram_mask;
|
||||
u32 m_dram_mask;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SGI_RE2, sgi_re2_device)
|
||||
|
190
src/mame/video/sgi_xmap2.cpp
Normal file
190
src/mame/video/sgi_xmap2.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
// 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;
|
||||
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);
|
||||
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]);
|
||||
}
|
||||
}
|
60
src/mame/video/sgi_xmap2.h
Normal file
60
src/mame/video/sgi_xmap2.h
Normal file
@ -0,0 +1,60 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#ifndef MAME_VIDEO_SGI_XMAP2_H
|
||||
#define MAME_VIDEO_SGI_XMAP2_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class sgi_xmap2_device
|
||||
: public device_t
|
||||
, public device_palette_interface
|
||||
{
|
||||
public:
|
||||
sgi_xmap2_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
// device_t overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_palette_interface overrides
|
||||
virtual u32 palette_entries() const override { return 4096 + 16; }
|
||||
|
||||
u8 reg_r(offs_t offset);
|
||||
void reg_w(offs_t offset, u8 data);
|
||||
|
||||
void map_select_w(int state);
|
||||
|
||||
u16 mode_r(unsigned const index) const { return m_mode[index]; }
|
||||
rgb_t overlay_r(u8 data) const { return m_wid_aux ? m_overlay[data & 0x3] : m_overlay[data & 0xf]; }
|
||||
|
||||
enum mode_mask : u16
|
||||
{
|
||||
MODE_MC = 0x3c00, // multimap constant
|
||||
MODE_ME = 0x0200, // multimap enable
|
||||
MODE_UE = 0x0100, // underlay enable
|
||||
MODE_OE = 0x00f0, // overlay enable
|
||||
MODE_BS = 0x0008, // buffer select
|
||||
MODE_DM = 0x0007, // display mode
|
||||
};
|
||||
enum mode_bits : unsigned
|
||||
{
|
||||
BIT_ME = 9, // multimap enable
|
||||
BIT_UE = 8, // underlay enable
|
||||
BIT_BS = 3, // buffer select
|
||||
};
|
||||
private:
|
||||
required_ioport m_options_port;
|
||||
|
||||
u16 m_addr;
|
||||
rgb_t m_color[8192];
|
||||
rgb_t m_overlay[16];
|
||||
u16 m_mode[16];
|
||||
bool m_wid_aux;
|
||||
bool m_map_select;
|
||||
u8 m_options;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SGI_XMAP2, sgi_xmap2_device)
|
||||
|
||||
#endif // MAME_VIDEO_SGI_XMAP2_H
|
Loading…
Reference in New Issue
Block a user