summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2022-06-24 06:56:27 +1000
committer Vas Crabb <vas@vastheman.com>2022-06-24 07:05:48 +1000
commitaf97d42dd31cdd7da154108562bb9d08043757b5 (patch)
treecc73e8e44dd26fb21b9f648c83579ba1320a8179 /src/devices
parente50b51fe7810715e5002a0ab41bbe6dd1db5420d (diff)
bus/nubus: More Mac video card improvements.
Started implementing the Macintosh Display Card CRTC. It gives correct resolutions, although refresh rates are incorrect. Added machine configuration settings allowing several monitors to be selected. Implemented the Macintosh Display Card's packed RGB mode. The base/stride in RGB mode make more sense with this implemented. Cleaned up the code for the SuperMac Spectrum cards, and fixed the garbage at the bottom of the screen on the Spectrum/8. Put a layout with views for common monitor aspect ratios in a place where cards can use it. This is especially useful for the NuBus cards that can support portrait monitors.
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/bus/nubus/nubus.cpp11
-rw-r--r--src/devices/bus/nubus/nubus.h2
-rw-r--r--src/devices/bus/nubus/nubus_48gc.cpp496
-rw-r--r--src/devices/bus/nubus/nubus_48gc.h55
-rw-r--r--src/devices/bus/nubus/nubus_spec8.cpp62
-rw-r--r--src/devices/bus/nubus/nubus_specpdq.cpp198
-rw-r--r--src/devices/bus/nubus/nubus_specpdq.h15
-rw-r--r--src/devices/bus/nubus/supermac.cpp7
-rw-r--r--src/devices/bus/nubus/supermac.h10
9 files changed, 606 insertions, 250 deletions
diff --git a/src/devices/bus/nubus/nubus.cpp b/src/devices/bus/nubus/nubus.cpp
index 4cf28122207..4f712861714 100644
--- a/src/devices/bus/nubus/nubus.cpp
+++ b/src/devices/bus/nubus/nubus.cpp
@@ -193,6 +193,12 @@ void nubus_device::install_bank(offs_t start, offs_t end, void *data)
m_space->install_ram(start, end, data);
}
+void nubus_device::install_view(offs_t start, offs_t end, memory_view &view)
+{
+// printf("install_view: %s @ %x->%x\n", tag, start, end);
+ m_space->install_view(start, end, view);
+}
+
void nubus_device::set_irq_line(int slot, int state)
{
switch (slot)
@@ -284,6 +290,11 @@ void device_nubus_card_interface::install_bank(offs_t start, offs_t end, void *d
nubus().install_bank(start, end, data);
}
+void device_nubus_card_interface::install_view(offs_t start, offs_t end, memory_view &view)
+{
+ nubus().install_view(start, end, view);
+}
+
void device_nubus_card_interface::install_declaration_rom(const char *romregion, bool mirror_all_mb, bool reverse_rom)
{
bool inverted = false;
diff --git a/src/devices/bus/nubus/nubus.h b/src/devices/bus/nubus/nubus.h
index cc9a434d205..198f5b115eb 100644
--- a/src/devices/bus/nubus/nubus.h
+++ b/src/devices/bus/nubus/nubus.h
@@ -38,6 +38,7 @@ public:
// helper functions for card devices
void install_declaration_rom(const char *romregion, bool mirror_all_mb = false, bool reverse_rom = false);
void install_bank(offs_t start, offs_t end, void *data);
+ void install_view(offs_t start, offs_t end, memory_view &view);
uint32_t get_slotspace() { return 0xf0000000 | (m_slot<<24); }
uint32_t get_super_slotspace() { return m_slot<<28; }
@@ -126,6 +127,7 @@ public:
void install_readonly_device(offs_t start, offs_t end, read32_delegate rhandler, uint32_t mask=0xffffffff);
void install_writeonly_device(offs_t start, offs_t end, write32_delegate whandler, uint32_t mask=0xffffffff);
void install_bank(offs_t start, offs_t end, void *data);
+ void install_view(offs_t start, offs_t end, memory_view &view);
void set_irq_line(int slot, int state);
DECLARE_WRITE_LINE_MEMBER( irq9_w );
diff --git a/src/devices/bus/nubus/nubus_48gc.cpp b/src/devices/bus/nubus/nubus_48gc.cpp
index 3b6896e578d..fefaf8ad35d 100644
--- a/src/devices/bus/nubus/nubus_48gc.cpp
+++ b/src/devices/bus/nubus/nubus_48gc.cpp
@@ -1,15 +1,29 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont, Vas Crabb
/***************************************************************************
Apple 4*8 Graphics Card (model 630-0400) emulation
Apple 8*24 Graphics Card emulation (cards have the same framebuffer chip
w/different ROMs and RAMDACs, apparently)
+ TODO:
+ * Proper clock generation to calculate frame rate - it's pretty easy to
+ find where it's writing PLL parameters.
+ * Work out why some monitors need magic multiply or divide by two to
+ get the right RAMDAC clock - inferring it from the reference clock
+ modulus is definitely wrong.
+ * When a monochrome monitor is connected, it sends the intensity to the
+ blue channel - maybe detect this and map blue channel to white?
+ * The 8•24 card uses a strange off-white palette with some monitors,
+ including the 21" and 16" RGB displays.
+ * Interlaced modes.
+
***************************************************************************/
#include "emu.h"
#include "nubus_48gc.h"
+
+#include "layout/generic.h"
#include "screen.h"
#include <algorithm>
@@ -18,11 +32,38 @@
#include "logmacro.h"
-#define VRAM_SIZE (0x200000) // 2 megs, maxed out
+#define VRAM_SIZE (0x20'0000) // 2 megs, maxed out
-#define GC48_SCREEN_NAME "48gc_screen"
+#define GC48_SCREEN_NAME "screen"
#define GC48_ROM_REGION "48gc_rom"
+
+static INPUT_PORTS_START( 48gc )
+ PORT_START("MONITOR")
+ PORT_CONFNAME(0x07, 0x06, u8"Attached monitor")
+ PORT_CONFSETTING( 0x00, u8"Macintosh Two-Page Monitor (1152\u00d7870)")
+ PORT_CONFSETTING( 0x01, u8"Macintosh Portrait Display (B&W 15\" 640\u00d7870)")
+ PORT_CONFSETTING( 0x02, u8"Macintosh RGB Display (12\" 512\u00d7384)")
+ PORT_CONFSETTING( 0x03, u8"Macintosh Two-Page Monitor (B&W 21\" 1152\u00d7870)")
+ //PORT_CONFSETTING( 0x04, u8"NTSC Monitor") requires implementing interlace modes
+ PORT_CONFSETTING( 0x05, u8"Macintosh Portrait Display (640\u00d7870)")
+ PORT_CONFSETTING( 0x06, u8"Macintosh Hi-Res Display (12-14\" 640\u00d7480)")
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( 824gc )
+ PORT_START("MONITOR")
+ PORT_CONFNAME(0x07, 0x06, u8"Attached monitor")
+ PORT_CONFSETTING( 0x00, u8"Mac 21\" Color Display (1152\u00d7870)")
+ PORT_CONFSETTING( 0x01, u8"Mac Portrait Display (B&W 15\" 640\u00d7870)")
+ PORT_CONFSETTING( 0x02, u8"Mac RGB Display (12\" 512\u00d7384)")
+ PORT_CONFSETTING( 0x03, u8"Mac Two-Page Display (B&W 21\" 1152\u00d7870)")
+ //PORT_CONFSETTING( 0x04, u8"NTSC Monitor") requires implementing interlace modes
+ PORT_CONFSETTING( 0x05, u8"Mac 16\" Color Display (832\u00d7624)")
+ PORT_CONFSETTING( 0x06, u8"Mac Hi-Res Display (12-14\" 640\u00d7480)")
+INPUT_PORTS_END
+
+
ROM_START( gc48 )
ROM_REGION(0x8000, GC48_ROM_REGION, 0)
ROM_LOAD( "3410801.bin", 0x0000, 0x8000, CRC(e283da91) SHA1(4ae21d6d7bbaa6fc7aa301bee2b791ed33b1dcf9) )
@@ -47,6 +88,8 @@ DEFINE_DEVICE_TYPE(NUBUS_824GC, nubus_824gc_device, "nb_824gc", "Apple Macintosh
void jmfb_device::device_add_mconfig(machine_config &config)
{
+ config.set_default_layout(layout_monitors);
+
screen_device &screen(SCREEN(config, GC48_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(jmfb_device::screen_update));
screen.set_raw(25175000, 800, 0, 640, 525, 0, 480);
@@ -60,7 +103,7 @@ void jmfb_device::device_add_mconfig(machine_config &config)
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *jmfb_device::device_rom_region() const
+const tiny_rom_entry *nubus_48gc_device::device_rom_region() const
{
return ROM_NAME( gc48 );
}
@@ -71,6 +114,20 @@ const tiny_rom_entry *nubus_824gc_device::device_rom_region() const
}
//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nubus_48gc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( 48gc );
+}
+
+ioport_constructor nubus_824gc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( 824gc );
+}
+
+//-------------------------------------------------
// palette_entries - entries in color palette
//-------------------------------------------------
@@ -88,26 +145,27 @@ uint32_t jmfb_device::palette_entries() const
// jmfb_device - constructor
//-------------------------------------------------
-jmfb_device::jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is824) :
+jmfb_device::jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock),
device_nubus_card_interface(mconfig, *this),
device_video_interface(mconfig, *this),
device_palette_interface(mconfig, *this),
- m_timer(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_stride(0), m_base(0),
- m_count(0), m_clutoffs(0),
- m_xres(0), m_yres(0),
- m_is824(is824)
+ m_monitor(*this, "MONITOR"),
+ m_vram_view(*this, "vram"),
+ m_timer(nullptr),
+ m_vbl_disable(0), m_toggle(0), m_stride(0), m_base(0),
+ m_count(0), m_clutoffs(0), m_mode(0)
{
set_screen(*this, GC48_SCREEN_NAME);
}
nubus_48gc_device::nubus_48gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- jmfb_device(mconfig, NUBUS_48GC, tag, owner, clock, false)
+ jmfb_device(mconfig, NUBUS_48GC, tag, owner, clock)
{
}
nubus_824gc_device::nubus_824gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- jmfb_device(mconfig, NUBUS_824GC, tag, owner, clock, true)
+ jmfb_device(mconfig, NUBUS_824GC, tag, owner, clock)
{
}
@@ -117,20 +175,67 @@ nubus_824gc_device::nubus_824gc_device(const machine_config &mconfig, const char
void jmfb_device::device_start()
{
- uint32_t slotspace;
-
install_declaration_rom(GC48_ROM_REGION);
- slotspace = get_slotspace();
+ uint32_t const slotspace = get_slotspace();
-// printf("[JMFB %p] slotspace = %x\n", this, slotspace);
+ LOG("[JMFB %p] slotspace = %x\n", this, slotspace);
m_vram.resize(VRAM_SIZE / sizeof(uint32_t));
- install_bank(slotspace, slotspace+VRAM_SIZE-1, &m_vram[0]);
-
- nubus().install_device(slotspace+0x200000, slotspace+0x2003ff, read32s_delegate(*this, FUNC(jmfb_device::mac_48gc_r)), write32s_delegate(*this, FUNC(jmfb_device::mac_48gc_w)));
+ install_view(
+ slotspace, slotspace + VRAM_SIZE - 1,
+ m_vram_view);
+ m_vram_view[0].install_ram(
+ slotspace, slotspace + VRAM_SIZE - 1,
+ &m_vram[0]);
+ m_vram_view[1].install_readwrite_handler(
+ slotspace, slotspace + VRAM_SIZE - 1,
+ read32s_delegate(*this, FUNC(jmfb_device::rgb_unpack)), write32s_delegate(*this, FUNC(jmfb_device::rgb_pack)));
+ m_vram_view.select(0);
m_timer = timer_alloc(FUNC(jmfb_device::vbl_tick), this);
+
+ save_item(NAME(m_vram));
+ save_item(NAME(m_vbl_disable));
+ save_item(NAME(m_toggle));
+ save_item(NAME(m_stride));
+ save_item(NAME(m_base));
+ save_item(NAME(m_registers));
+ save_item(NAME(m_preload));
+ save_item(NAME(m_colors));
+ save_item(NAME(m_count));
+ save_item(NAME(m_clutoffs));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_hactive));
+ save_item(NAME(m_hbporch));
+ save_item(NAME(m_hsync));
+ save_item(NAME(m_hfporch));
+ save_item(NAME(m_vactive));
+ save_item(NAME(m_vbporch));
+ save_item(NAME(m_vsync));
+ save_item(NAME(m_vfporch));
+ save_item(NAME(m_modulus));
+ save_item(NAME(m_pdiv));
+}
+
+void nubus_48gc_device::device_start()
+{
+ jmfb_device::device_start();
+
+ uint32_t const slotspace = get_slotspace();
+ nubus().install_device(
+ slotspace + 0x200000, slotspace + 0x2003ff,
+ read32s_delegate(*this, FUNC(nubus_48gc_device::jmfb_r)), write32s_delegate(*this, FUNC(nubus_48gc_device::mac_48gc_w)));
+}
+
+void nubus_824gc_device::device_start()
+{
+ jmfb_device::device_start();
+
+ uint32_t const slotspace = get_slotspace();
+ nubus().install_device(
+ slotspace + 0x200000, slotspace + 0x2003ff,
+ read32s_delegate(*this, FUNC(nubus_824gc_device::jmfb_r)), write32s_delegate(*this, FUNC(nubus_824gc_device::mac_824gc_w)));
}
//-------------------------------------------------
@@ -139,18 +244,30 @@ void jmfb_device::device_start()
void jmfb_device::device_reset()
{
+ m_vram_view.select(0);
+
+ std::fill(m_vram.begin(), m_vram.end(), 0);
+ m_vbl_disable = 1;
m_toggle = 0;
+ m_stride = 80 / 4;
+ m_base = 0;
+ m_preload = 256 - 8;
+
m_clutoffs = 0;
m_count = 0;
- m_vbl_disable = 1;
- m_stride = 80/4;
- m_base = 0;
- m_xres = 640;
- m_yres = 480;
m_mode = 0;
- std::fill(m_vram.begin(), m_vram.end(), 0);
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
+ m_hactive = 286;
+ m_hbporch = 22;
+ m_hsync = 30;
+ m_hfporch = 18;
+
+ m_vactive = 1740;
+ m_vbporch = 78;
+ m_vsync = 6;
+ m_vfporch = 6;
+ m_modulus = 19;
+ m_pdiv = 1;
}
/***************************************************************************
@@ -171,17 +288,19 @@ TIMER_CALLBACK_MEMBER(jmfb_device::vbl_tick)
uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]) + (m_base << 5);
+ auto const screenbase = util::big_endian_cast<uint8_t const>(&m_vram[0]) + (m_base << 5);
+ int const xres = screen.visible_area().right();
switch (m_mode)
{
case 0: // 1bpp
- for (int y = 0; y < m_yres; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
+ auto const rowbase = screenbase + (y * m_stride * 4);
uint32_t *scanline = &bitmap.pix(y);
- for (int x = 0; x < m_xres/8; x++)
+ for (int x = 0; x <= xres/8; x++)
{
- uint8_t const pixels = vram8[(y * m_stride * 4) + x];
+ uint8_t const pixels = rowbase[x];
*scanline++ = pen_color(BIT(pixels, 7));
*scanline++ = pen_color(BIT(pixels, 6));
@@ -196,12 +315,13 @@ uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
break;
case 1: // 2bpp
- for (int y = 0; y < m_yres; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
+ auto const rowbase = screenbase + (y * m_stride * 4);
uint32_t *scanline = &bitmap.pix(y);
- for (int x = 0; x < m_xres/4; x++)
+ for (int x = 0; x <= xres/4; x++)
{
- uint8_t const pixels = vram8[(y * m_stride * 4) + x];
+ uint8_t const pixels = rowbase[x];
*scanline++ = pen_color(BIT(pixels, 6, 2));
*scanline++ = pen_color(BIT(pixels, 4, 2));
@@ -212,12 +332,13 @@ uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
break;
case 2: // 4 bpp
- for (int y = 0; y < m_yres; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
+ auto const rowbase = screenbase + (y * m_stride * 4);
uint32_t *scanline = &bitmap.pix(y);
- for (int x = 0; x < m_xres/2; x++)
+ for (int x = 0; x <= xres/2; x++)
{
- uint8_t const pixels = vram8[(y * m_stride * 4) + x];
+ uint8_t const pixels = rowbase[x];
*scanline++ = pen_color(BIT(pixels, 4, 4));
*scanline++ = pen_color(BIT(pixels, 0, 4));
@@ -226,24 +347,26 @@ uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
break;
case 3: // 8 bpp
- for (int y = 0; y < m_yres; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
+ auto const rowbase = screenbase + (y * m_stride * 4);
uint32_t *scanline = &bitmap.pix(y);
- for (int x = 0; x < m_xres; x++)
+ for (int x = 0; x <= xres; x++)
{
- uint8_t const pixels = vram8[(y * m_stride * 4) + x];
- *scanline++ = pen_color(pixels);
+ *scanline++ = pen_color(rowbase[x]);
}
}
break;
case 4: // 24 bpp
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
- uint32_t const base = (m_base * 8 / 3) << 3;
- uint32_t const stride = m_stride * 8 / 3;
- for (int y = 0; y < m_yres; y++)
+ auto source = util::big_endian_cast<uint8_t const>(&m_vram[0]) + (m_base << 6) + (y * m_stride * 8);
+ uint32_t *scanline = &bitmap.pix(y);
+ for (int x = 0; x <= xres; x++)
{
- std::copy_n(&m_vram[base + (y * stride)], m_xres, &bitmap.pix(y));
+ *scanline++ = rgb_t(source[0], source[1], source[2]);
+ source += 3;
}
}
break;
@@ -252,12 +375,100 @@ uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
return 0;
}
-void jmfb_device::mac_48gc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+void jmfb_device::update_crtc()
+{
+ int const vtotal = (m_vactive + m_vbporch + m_vsync + m_vfporch) / 2;
+ int const height = m_vactive / 2;
+ if (vtotal && height)
+ {
+ int scale = 0;
+ switch (m_modulus) // FIXME: hacky - I'm missing something
+ {
+ case 15:
+ scale = -1;
+ break;
+ case 21:
+ scale = 0;
+ break;
+ case 19:
+ case 22:
+ scale = 1;
+ break;
+ default:
+ throw emu_fatalerror("%s: Unknown clock modulus %d\n", tag(), m_modulus);
+ }
+ int const divider = 256 - unsigned(m_preload);
+ int htotal = ((m_hactive + m_hbporch + m_hsync + m_hfporch + 8) << (m_pdiv + scale)) / divider;
+ int width = ((m_hactive + 2) << (m_pdiv + scale)) / divider;
+ switch (m_mode)
+ {
+ case 0: // 1bpp:
+ htotal <<= 3;
+ width <<= 3;
+ break;
+ case 1: // 2bpp:
+ htotal <<= 2;
+ width <<= 2;
+ break;
+ case 2: // 4bpp:
+ htotal <<= 1;
+ width <<= 1;
+ break;
+ case 3: // 8bpp:
+ break;
+ case 4: // 24bpp:
+ htotal >>= 2;
+ width >>= 2;
+ break;
+ }
+ rectangle const active(0, width - 1, 0, height - 1);
+ screen().configure(
+ htotal, vtotal,
+ active,
+ HZ_TO_ATTOSECONDS(75)); // FIXME: not correct in any sense
+
+ // TODO: work out how this is configured
+ m_timer->adjust(screen().time_until_pos(height - 1, 0), 0);
+ }
+}
+
+uint32_t jmfb_device::jmfb_r(offs_t offset, uint32_t mem_mask)
+{
+// printf("%s 48gc_r: @ %x, mask %08x\n", machine().describe_context().c_str(), offset, mem_mask);
+
+ switch (offset)
+ {
+ case 0x000/4:
+ return m_monitor->read() << 9;
+
+ case 0x1c0/4:
+ m_toggle ^= 0xffffffff;
+ return m_toggle;
+ }
+
+ return 0;
+}
+
+void jmfb_device::jmfb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
COMBINE_DATA(&m_registers[offset & 0xff]);
switch (offset)
{
+ case 0x000/4: // control
+ LOG("%s: %04x to control\n", machine().describe_context(), data);
+ if (BIT(data, 7))
+ {
+ m_vram_view.select(BIT(data, 2)); // packed RGB mode
+ }
+ break;
+
+ case 0x004/4:
+ LOG("%s: %02x to preload\n", machine().describe_context(), data);
+ m_preload = data;
+ update_crtc();
+ break;
+
case 0x008/4: // base
LOG("%s: %x to base\n", machine().describe_context(), data);
m_base = data;
@@ -269,91 +480,170 @@ void jmfb_device::mac_48gc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
m_stride = data;
break;
- case 0x200/4: // DAC control
- LOG("%s: %08x to DAC control\n", machine().describe_context(), data);
- if (m_is824)
- {
- m_clutoffs = data & 0xff;
- }
- else
- {
- m_clutoffs = data >> 24;
- }
- m_count = 0;
+ case 0x10c/4: // active pixel cells - 2
+ LOG("%s: %d-2 to active cells\n", machine().describe_context(), data + 2);
+ m_hactive = data;
+ update_crtc();
break;
- case 0x204/4: // DAC data
- if (m_is824)
- {
- m_colors[m_count++] = data & 0xff;
- }
- else
- {
- m_colors[m_count++] = data >> 24;
- }
+ case 0x110/4: // horizontal back porch
+ LOG("%s: %d to horizontal back porch\n", machine().describe_context(), data + 2);
+ m_hbporch = data;
+ update_crtc();
+ break;
- if (m_count == 3)
- {
- LOG("%s: RAMDAC: color %d = %02x %02x %02x\n", machine().describe_context(), m_clutoffs, m_colors[0], m_colors[1], m_colors[2]);
- set_pen_color(m_clutoffs, rgb_t(m_colors[0], m_colors[1], m_colors[2]));
- m_clutoffs++;
- m_count = 0;
- }
+ case 0x114/4: // horizontal sync pulse
+ LOG("%s: %d-2 to horizontal sync pulse\n", machine().describe_context(), data + 2);
+ m_hsync = data;
+ update_crtc();
break;
- case 0x208/4: // mode control
- m_mode = (data>>3)&3;
- if (m_mode == 3) // this can be 8 or 24 bpp
- {
- // check pixel format for 24bpp
- if (m_is824)
- {
- if (data & 2)
- {
- m_mode = 4; // 24bpp
- }
- }
- else
- {
- if (((data>>5)&3) == 0)
- {
- m_mode = 4; // 24bpp
- }
- }
- }
-// printf("%02x to mode (m_mode = %d)\n", data, m_mode);
+ case 0x118/4: // horizontal front porch
+ LOG("%s: %d-2 to horizontal front porch\n", machine().describe_context(), data + 2);
+ m_hfporch = data;
+ update_crtc();
+ break;
+
+ case 0x124/4: // active lines * 2
+ LOG("%s: %d*2 to active lines\n", machine().describe_context(), data / 2);
+ m_vactive = data;
+ update_crtc();
+ break;
+
+ case 0x128/4: // vertical back porch * 2
+ LOG("%s: %d*2 to vertical back porch\n", machine().describe_context(), data / 2);
+ m_vbporch = data;
+ update_crtc();
+ break;
+
+ case 0x12c/4: // vertical sync width * 2
+ LOG("%s: %d*2 to vertical sync pulse width\n", machine().describe_context(), data / 2);
+ m_vsync = data;
+ update_crtc();
+ break;
+
+ case 0x130/4: // vertical front porch * 2
+ LOG("%s: %d*2 to vertical front porch\n", machine().describe_context(), data / 2);
+ m_vfporch = data;
+ update_crtc();
break;
- case 0x13c/4: // bit 1 = VBL disable (1=no interrupts)
+ case 0x13c/4: // bit 1 = VBL disable (1=no interrupts)
m_vbl_disable = (data & 2) ? 1 : 0;
break;
- case 0x148/4: // write 1 here to clear interrupt
+ case 0x148/4: // write 1 here to clear interrupt
if (data == 1)
{
lower_slot_irq();
}
break;
+ case 0x310/4:
+ case 0x314/4:
+ case 0x318/4:
+ m_modulus &= ~(0x0f << ((offset & 3) * 4));
+ m_modulus |= (data & 0x0f) << ((offset & 3) * 4);
+ LOG("%s: %d to modulus\n", machine().describe_context(), m_modulus);
+ if (offset == 0x318/4) // avoid bad intermediate values
+ update_crtc();
+ break;
+
+ case 0x324/4:
+ LOG("%s: 1<<%d to pixel cell divider\n", machine().describe_context(), data);
+ m_pdiv = data;
+ update_crtc();
+ break;
+
default:
break;
}
}
-uint32_t jmfb_device::mac_48gc_r(offs_t offset, uint32_t mem_mask)
+void nubus_48gc_device::mac_48gc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
-// printf("%s 48gc_r: @ %x, mask %08x\n", machine().describe_context().c_str(), offset, mem_mask);
+ switch (offset)
+ {
+ case 0x200/4: // DAC control
+ dac_ctrl_w(data >> 24);
+ break;
+
+ case 0x204/4: // DAC data
+ dac_data_w(data >> 24);
+ break;
+
+ case 0x208/4: // mode control
+ mode_w(data, !((data >> 5) & 0x3));
+ break;
+ default:
+ jmfb_w(offset, data, mem_mask);
+ }
+}
+
+void nubus_824gc_device::mac_824gc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
switch (offset)
{
- case 0:
- return 0x0c00; // sense 13" RGB for now
-// return 0x0000; // sense "RGB Kong" monitor
+ case 0x200/4: // DAC control
+ dac_ctrl_w(data & 0xff);
+ break;
- case 0x1c0/4:
- m_toggle ^= 0xffffffff;
- return m_toggle;
+ case 0x204/4: // DAC data
+ dac_data_w(data & 0xff);
+ break;
+
+ case 0x208/4: // mode control
+ mode_w(data, BIT(data, 1));
+ break;
+
+ default:
+ jmfb_w(offset, data, mem_mask);
+ }
+}
+
+void jmfb_device::dac_ctrl_w(uint8_t data)
+{
+ LOG("%s: %02x to DAC control\n", machine().describe_context(), data);
+ m_clutoffs = data;
+ m_count = 0;
+}
+
+void jmfb_device::dac_data_w(uint8_t data)
+{
+ m_colors[m_count++] = data;
+
+ if (m_count == 3)
+ {
+ LOG("%s: RAMDAC: color %d = %02x %02x %02x\n", machine().describe_context(), m_clutoffs, m_colors[0], m_colors[1], m_colors[2]);
+ set_pen_color(m_clutoffs, rgb_t(m_colors[0], m_colors[1], m_colors[2]));
+ m_clutoffs++;
+ m_count = 0;
}
+}
- return 0;
+void jmfb_device::mode_w(uint32_t data, bool rgb)
+{
+ m_mode = (data >> 3) & 0x3;
+ if ((m_mode == 3) & rgb) // mode 3 can be 8 or 24 bpp
+ m_mode = 4;
+ LOG("%s: %02x to mode (m_mode = %d)\n", machine().describe_context(), data, m_mode);
+ update_crtc();
+}
+
+uint32_t jmfb_device::rgb_unpack(offs_t offset, uint32_t mem_mask)
+{
+ auto const color = util::big_endian_cast<uint8_t const>(&m_vram[0]) + (offset * 3);
+ return (uint32_t(color[0]) << 16) | (uint32_t(color[1]) << 8) | uint32_t(color[2]);
+}
+
+void jmfb_device::rgb_pack(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ auto const color = util::big_endian_cast<uint8_t>(&m_vram[0]) + (offset * 3);
+ if (ACCESSING_BITS_16_23)
+ color[0] = uint8_t(data >> 16);
+ if (ACCESSING_BITS_8_15)
+ color[1] = uint8_t(data >> 8);
+ if (ACCESSING_BITS_0_7)
+ color[2] = uint8_t(data);
}
diff --git a/src/devices/bus/nubus/nubus_48gc.h b/src/devices/bus/nubus/nubus_48gc.h
index 78cf5f6d90e..8f69e115d4e 100644
--- a/src/devices/bus/nubus/nubus_48gc.h
+++ b/src/devices/bus/nubus/nubus_48gc.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont, Vas Crabb
#ifndef MAME_BUS_NUBUS_NUBUS_48GC_H
#define MAME_BUS_NUBUS_NUBUS_48GC_H
@@ -21,7 +21,7 @@ class jmfb_device :
{
protected:
// construction/destruction
- jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is824);
+ jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
@@ -29,40 +29,75 @@ protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
// palette implementation
uint32_t palette_entries() const override;
TIMER_CALLBACK_MEMBER(vbl_tick);
-private:
- uint32_t mac_48gc_r(offs_t offset, uint32_t mem_mask = ~0);
- void mac_48gc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t jmfb_r(offs_t offset, uint32_t mem_mask = ~0);
+ void jmfb_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ void dac_ctrl_w(uint8_t data);
+ void dac_data_w(uint8_t data);
+ void mode_w(uint32_t data, bool rgb);
+private:
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ void update_crtc();
+
+ uint32_t rgb_unpack(offs_t offset, uint32_t mem_mask = ~0);
+ void rgb_pack(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ required_ioport m_monitor;
+ memory_view m_vram_view;
emu_timer *m_timer;
std::vector<uint32_t> m_vram;
- uint32_t m_mode, m_vbl_disable, m_toggle, m_stride, m_base;
- uint32_t m_colors[3], m_count, m_clutoffs;
+ uint32_t m_vbl_disable, m_toggle, m_stride, m_base;
uint32_t m_registers[0x100];
- int m_xres, m_yres;
- const bool m_is824;
+ uint8_t m_preload;
+
+ uint8_t m_colors[3], m_count, m_clutoffs, m_mode;
+
+ uint16_t m_hactive, m_hbporch, m_hsync, m_hfporch;
+ uint16_t m_vactive, m_vbporch, m_vsync, m_vfporch;
+ uint16_t m_modulus;
+ uint8_t m_pdiv;
};
class nubus_48gc_device : public jmfb_device
{
public:
nubus_48gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ void mac_48gc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
};
class nubus_824gc_device : public jmfb_device
{
public:
nubus_824gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ void mac_824gc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
};
// device type definition
diff --git a/src/devices/bus/nubus/nubus_spec8.cpp b/src/devices/bus/nubus/nubus_spec8.cpp
index 1135a3bd442..ee3549a2572 100644
--- a/src/devices/bus/nubus/nubus_spec8.cpp
+++ b/src/devices/bus/nubus/nubus_spec8.cpp
@@ -21,17 +21,34 @@
Configuration settings, you need to zap the PRAM before it will be
recognised properly.
+ Set breakpoint at 0x2d1e on Mac II with Ver. 1.3 card in slot 9 to catch
+ user oscillator measurement. See the measured value in D0.b when
+ PC = 0x2d6c.
+
+ Expected:
+ 2- 5 57.28 MHz
+ 6-19 bad
+ 20-22 14.32 MHz
+ 23-24 15.67 MHz
+ 25-27 17.73 MHz
+ 27- bad
+
+ Measured:
+ 14.32 MHz 20
+ 15.67 MHz 23
+ 17.73 MHz 26
+ 57.28 MHz 5
+
TODO:
* Having no oscillator installed at Y1 is not emulated.
* Interlaced modes are not understood.
- * There are lines of garbage at the bottom of the screen in some high-
- resolution modes (bottom of the virtual desktop if virtual desktop is
- enabled).
***************************************************************************/
#include "emu.h"
#include "nubus_spec8.h"
+
+#include "layout/generic.h"
#include "screen.h"
#include <algorithm>
@@ -40,10 +57,10 @@
#include "logmacro.h"
-#define SPEC8S3_SCREEN_NAME "spec8s3_screen"
+#define SPEC8S3_SCREEN_NAME "screen"
#define SPEC8S3_ROM_REGION "spec8s3_rom"
-#define VRAM_SIZE (0xc0000) // 768k of VRAM for 1024x768 @ 8 bit
+#define VRAM_SIZE (0x10'0000) // 1M of VRAM for 1024x768 @ 8 bit
static INPUT_PORTS_START( spec8s3 )
@@ -79,9 +96,12 @@ DEFINE_DEVICE_TYPE(NUBUS_SPEC8S3, nubus_spec8s3_device, "nb_sp8s3", "SuperMac Sp
void nubus_spec8s3_device::device_add_mconfig(machine_config &config)
{
+ config.set_default_layout(layout_monitors);
+
screen_device &screen(SCREEN(config, SPEC8S3_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(nubus_spec8s3_device::screen_update));
screen.set_raw(80.000_MHz_XTAL, 332*4, 64*4, 320*4, 804, 33, 801);
+ screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
}
//-------------------------------------------------
@@ -496,38 +516,10 @@ uint32_t nubus_spec8s3_device::spec8s3_r(offs_t offset, uint32_t mem_mask)
case 0x382c:
case 0x382e:
{
- /*
- * Set breakpoint at 0x2d1e on Mac II with Ver. 1.3 card in
- * slot 9 to catch user oscillator measurement. See the
- * measured value in D0.b when PC = 0x2d6c.
- *
- * Expected:
- * 2- 5 57.28 MHz
- * 6-19 bad
- * 20-22 14.32 MHz
- * 23-24 15.67 MHz
- * 25-27 17.73 MHz
- * 27- bad
- *
- * Measured:
- * 14.32 MHz 20
- * 15.67 MHz 23
- * 17.73 MHz 26
- * 57.28 MHz 5
- */
- int vpos;
+ // hack for interlace modes because screen_device doesn't support them
+ int vpos = screen().vpos();
if (m_interlace)
- {
- // hack for interlace modes because screen_device doesn't support them
- vpos = screen().vpos() - (m_crtc.v_sync() * 2);
- if (vpos >= (m_crtc.v_total() * 2))
- vpos -= m_crtc.v_total() * 2;
vpos /= 2;
- }
- else
- {
- vpos = m_crtc.v_pos(screen());
- }
return ~((vpos >> (BIT(offset, 1) ? 8 : 0)) & 0xff);
}
diff --git a/src/devices/bus/nubus/nubus_specpdq.cpp b/src/devices/bus/nubus/nubus_specpdq.cpp
index 651d7b19023..62c1aec9e29 100644
--- a/src/devices/bus/nubus/nubus_specpdq.cpp
+++ b/src/devices/bus/nubus/nubus_specpdq.cpp
@@ -21,10 +21,18 @@
There is 256 bytes of pattern RAM arranged as 32 pixels horizontally by
8 vertically.
+ TODO:
+ * Having no alternate oscillator installed is not emulated.
+ * Work out how active line length is configured.
+ * Alternate oscillator calibration is currently failing. Fixing this
+ probably requires a complete cycle-accurate Mac II.
+
***************************************************************************/
#include "emu.h"
#include "nubus_specpdq.h"
+
+#include "layout/generic.h"
#include "screen.h"
#include <algorithm>
@@ -33,10 +41,10 @@
#include "logmacro.h"
-#define SPECPDQ_SCREEN_NAME "specpdq_screen"
+#define SPECPDQ_SCREEN_NAME "screen"
#define SPECPDQ_ROM_REGION "specpdq_rom"
-#define VRAM_SIZE (0x400000)
+#define VRAM_SIZE (0x40'0000)
static INPUT_PORTS_START( specpdq )
@@ -65,9 +73,12 @@ DEFINE_DEVICE_TYPE(NUBUS_SPECPDQ, nubus_specpdq_device, "nb_spdq", "SuperMac Spe
void nubus_specpdq_device::device_add_mconfig(machine_config &config)
{
+ config.set_default_layout(layout_monitors);
+
screen_device &screen(SCREEN(config, SPECPDQ_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(nubus_specpdq_device::screen_update));
screen.set_raw(100.000_MHz_XTAL, 1'456, 108, 1'260, 915, 39, 909);
+ screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
}
//-------------------------------------------------
@@ -118,9 +129,7 @@ nubus_specpdq_device::nubus_specpdq_device(const machine_config &mconfig, device
device_palette_interface(mconfig, *this),
m_userosc(*this, "USEROSC"),
m_timer(nullptr),
- m_mode(0), m_vbl_disable(0),
- m_count(0), m_clutoffs(0),
- m_width(0), m_height(0), m_patofsx(0), m_patofsy(0), m_vram_addr(0), m_vram_src(0)
+ m_mode(0)
{
set_screen(*this, SPECPDQ_SCREEN_NAME);
}
@@ -155,14 +164,14 @@ void nubus_specpdq_device::device_start()
save_item(NAME(m_vint));
save_item(NAME(m_hdelay));
save_item(NAME(m_osc));
+ save_item(NAME(m_blit_stride));
+ save_item(NAME(m_blit_src));
+ save_item(NAME(m_blit_dst));
+ save_item(NAME(m_blit_width));
+ save_item(NAME(m_blit_height));
+ save_item(NAME(m_blit_patoffs));
+ save_item(NAME(m_blit_pat));
save_item(NAME(m_7xxxxx_regs));
- save_item(NAME(m_width));
- save_item(NAME(m_height));
- save_item(NAME(m_patofsx));
- save_item(NAME(m_patofsy));
- save_item(NAME(m_vram_addr));
- save_item(NAME(m_vram_src));
- save_item(NAME(m_pattern));
}
//-------------------------------------------------
@@ -180,18 +189,21 @@ void nubus_specpdq_device::device_reset()
std::fill(std::begin(m_colors), std::end(m_colors), 0);
m_count = 0;
m_clutoffs = 0;
- m_stride = 512 / 4;
+
+ m_stride = 0;
m_vint = 0;
m_hdelay = 0;
m_osc = 0;
+ m_blit_stride = 0;
+ m_blit_src = 0;
+ m_blit_dst = 0;
+ m_blit_width = 0;
+ m_blit_height = 0;
+ m_blit_patoffs = 0;
+ std::fill(std::begin(m_blit_pat), std::end(m_blit_pat), 0);
+
std::fill(std::begin(m_7xxxxx_regs), std::end(m_7xxxxx_regs), 0);
- m_width = 0;
- m_height = 0;
- m_patofsx = 0;
- m_patofsy = 0;
- m_vram_addr = 0;
- m_vram_src = 0;
}
@@ -202,10 +214,7 @@ TIMER_CALLBACK_MEMBER(nubus_specpdq_device::vbl_tick)
raise_slot_irq();
}
- m_timer->adjust(
- screen().time_until_pos(
- m_vint + m_crtc.v_start() - 1,
- m_crtc.h_total(16) - m_crtc.h_sync(16)));
+ m_timer->adjust(screen().time_until_pos(m_vint));
}
/***************************************************************************
@@ -272,10 +281,7 @@ void nubus_specpdq_device::update_crtc()
active,
m_crtc.frame_time(16, oscillator));
- m_timer->adjust(
- screen().time_until_pos(
- m_vint + m_crtc.v_start() - 1,
- m_crtc.h_total(16) - m_crtc.h_sync(16)));
+ m_timer->adjust(screen().time_until_pos(m_vint + m_crtc.v_start() - 1));
}
}
@@ -410,7 +416,7 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
else if ((offset >= 0x181000) && (offset <= 0x18103f))
{
// 256 pixels worth at 8 bpp
- m_pattern[offset & 0x3f] = ~data;
+ m_blit_pat[offset & 0x3f] = ~data;
}
else switch (offset)
{
@@ -424,7 +430,6 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
case 0xc0054:
case 0xc0056:
- // same value written here and to c007a:c0078
m_stride &= BIT(offset, 1) ? 0x00ff : 0xff00;
m_stride |= (~data & 0xff000000) >> (BIT(offset, 1) ? 16 : 24);
LOG("%s: %u to stride\n", machine().describe_context(), m_stride);
@@ -451,6 +456,13 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
update_crtc();
break;
+ case 0xc0078:
+ case 0xc007a:
+ m_blit_stride &= BIT(offset, 1) ? 0x00ff : 0xff00;
+ m_blit_stride |= (~data & 0xff000000) >> (BIT(offset, 1) ? 16 : 24);
+ LOG("%s: %u to blitter stride\n", machine().describe_context(), m_blit_stride);
+ break;
+
case 0x120000: // DAC address
LOG("%s: %08x to DAC control\n", machine().describe_context(), data);
m_clutoffs = ~data & 0xff;
@@ -496,7 +508,6 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
m_shiftreg.write_control(*this, data);
break;
- // blitter control
case 0x182006:
data = ~data;
LOG("%08x (%d) to blitter ctrl 1 %s rectangle\n", data, data, machine().describe_context());
@@ -505,55 +516,18 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
case 0x182007:
data = ~data;
LOG("%s: %08x to blitter command\n", machine().describe_context(), data);
-
- if (data == 2)
- {
- // fill rectangle
- auto const source = util::big_endian_cast<uint8_t const>(m_pattern);
- auto dest = util::big_endian_cast<uint8_t>(&m_vram[0]) + m_vram_addr;
- uint32_t const patofsx = (m_vram_addr & 0x3) + m_patofsx;
- LOG("Fill rectangle with %02x %02x %02x %02x, adr %x (%d, %d) width %d height %d delta %d %d\n", source[0], source[1], source[2], source[3], m_vram_addr, m_vram_addr % 1152, m_vram_addr / 1152, m_width, m_height, m_patofsx, m_patofsy);
- for (int y = 0; y <= m_height; y++)
- {
- for (int x = 0; x < m_width; x++)
- {
- dest[x] = source[(((m_patofsy + y) & 0x7) << 5) + ((patofsx + x) & 0x1f)];
- }
- dest += m_stride * 4;
- }
- }
- else if (data == 0x100)
- {
- LOG("Copy rectangle forwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n", m_width, m_height, m_vram_addr, m_vram_addr % 1152, m_vram_addr / 1152, m_vram_src, m_vram_src % 1152, m_vram_src / 1152);
- auto source = util::big_endian_cast<uint8_t const>(&m_vram[0]) + m_vram_src;
- auto dest = util::big_endian_cast<uint8_t>(&m_vram[0]) + m_vram_addr;
- for (int y = 0; y <= m_height; y++)
- {
- for (int x = 0; x < m_width; x++)
- {
- dest[x] = source[x];
- }
- source += m_stride * 4;
- dest += m_stride * 4;
- }
- }
- else if (data == 0x101)
- {
- LOG("Copy rectangle backwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n", m_width, m_height, m_vram_addr, m_vram_addr % 1152, m_vram_addr / 1152, m_vram_src, m_vram_src % 1152, m_vram_src / 1152);
- auto source = util::big_endian_cast<uint8_t const>(&m_vram[0]) + m_vram_src;
- auto dest = util::big_endian_cast<uint8_t>(&m_vram[0]) + m_vram_addr;
- for (int y = 0; y <= m_height; y++)
- {
- for (int x = 0; x < m_width; x++)
- {
- dest[-x] = source[-x];
- }
- source -= m_stride * 4;
- dest -= m_stride * 4;
- }
- }
- else
+ switch (data)
{
+ case 0x002:
+ blitter_pattern_fill();
+ break;
+ case 0x100:
+ blitter_copy_forward();
+ break;
+ case 0x101:
+ blitter_copy_backward();
+ break;
+ default:
logerror("Unknown blitter command %08x\n", data);
}
break;
@@ -561,32 +535,31 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
case 0x182008:
data = ~data;
LOG("%s: %08x (%d) to blitter ctrl 2 rectangle\n", machine().describe_context(), data, data);
- m_patofsx = BIT(data, 0, 3);
- m_patofsy = BIT(data, 3, 3);
+ m_blit_patoffs = (data >> 3) & 0x1fff;
break;
case 0x182009:
data = ~data;
LOG("%s: %08x to blitter destination\n", machine().describe_context(), data);
- m_vram_addr = data >> 2;
+ m_blit_dst = (data >> 2) & 0x3fffff;
break;
case 0x18200a:
data = ~data;
LOG("%s: %08x to blitter source\n", machine().describe_context(), data);
- m_vram_src = data >> 2;
+ m_blit_src = (data >> 2) & 0x3fffff;
break;
case 0x18200b:
data = ~data;
LOG("%s: %08x (%d) to blitter height\n", machine().describe_context(), data, data);
- m_height = data & 0xffff;
+ m_blit_height = data;
break;
case 0x18200e:
data = ~data;
LOG("%s: %08x (%d) to blitter width\n", machine().describe_context(), data, data);
- m_width = data;
+ m_blit_width = data;
break;
default:
@@ -614,7 +587,7 @@ uint32_t nubus_specpdq_device::specpdq_r(offs_t offset, uint32_t mem_mask)
* 57.28 MHz 1 detected as 55.00 MHz
* 64.00 MHz 9 detected as 57.28 MHz
*/
- return ~((u32(m_crtc.v_pos(screen())) << (BIT(offset, 1) ? 16 : 24)) & 0xff000000);
+ return ~((u32(screen().vpos()) << (BIT(offset, 1) ? 16 : 24)) & 0xff000000);
}
if (offset >= 0xc0000 && offset < 0x100000)
@@ -635,3 +608,58 @@ uint32_t nubus_specpdq_device::vram_r(offs_t offset, uint32_t mem_mask)
{
return ~m_vram[offset];
}
+
+void nubus_specpdq_device::blitter_pattern_fill()
+{
+ auto const source = util::big_endian_cast<uint8_t const>(m_blit_pat);
+ auto const dest = util::big_endian_cast<uint8_t>(&m_vram[0]);
+ uint32_t const patofsx = m_blit_dst & 0x3;
+ uint32_t const stride = m_blit_stride * 4;
+ LOG("Fill rectangle with %02x %02x %02x %02x, adr %x (%d, %d) width %d height %d delta %d\n",
+ source[0], source[1], source[2], source[3],
+ m_blit_dst, m_blit_dst % (m_blit_stride * 4), m_blit_dst / (m_blit_stride * 4),
+ m_blit_width, m_blit_height, m_blit_patoffs);
+ for (int y = 0; y <= m_blit_height; y++)
+ {
+ for (int x = 0; x < m_blit_width; x++)
+ {
+ dest[(m_blit_dst + (y * stride) + x) & (VRAM_SIZE - 1)] = source[(((m_blit_patoffs + y) & 0x7) << 5) | ((patofsx + x) & 0x1f)];
+ }
+ }
+}
+
+void nubus_specpdq_device::blitter_copy_forward()
+{
+ LOG("Copy rectangle forwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n",
+ m_blit_width, m_blit_height,
+ m_blit_dst, m_blit_dst % (m_blit_stride * 4), m_blit_dst / (m_blit_stride * 4),
+ m_blit_src, m_blit_src % (m_blit_stride * 4), m_blit_src / (m_blit_stride * 4));
+ auto const source = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+ auto const dest = util::big_endian_cast<uint8_t>(&m_vram[0]);
+ uint32_t const stride = m_blit_stride * 4;
+ for (int y = 0; y <= m_blit_height; y++)
+ {
+ for (int x = 0; x < m_blit_width; x++)
+ {
+ dest[(m_blit_dst + (y * stride) + x) & (VRAM_SIZE - 1)] = source[(m_blit_src + (y * stride) + x) & (VRAM_SIZE - 1)];
+ }
+ }
+}
+
+void nubus_specpdq_device::blitter_copy_backward()
+{
+ LOG("Copy rectangle backwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n",
+ m_blit_width, m_blit_height,
+ m_blit_dst, m_blit_dst % (m_blit_stride * 4), m_blit_dst / (m_blit_stride * 4),
+ m_blit_src, m_blit_src % (m_blit_stride * 4), m_blit_src / (m_blit_stride * 4));
+ auto const source = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+ auto const dest = util::big_endian_cast<uint8_t>(&m_vram[0]);
+ uint32_t const stride = m_blit_stride * 4;
+ for (int y = 0; y <= m_blit_height; y++)
+ {
+ for (int x = 0; x < m_blit_width; x++)
+ {
+ dest[(m_blit_dst - (y * stride) - x) & (VRAM_SIZE - 1)] = source[(m_blit_src - (y * stride) - x) & (VRAM_SIZE - 1)];
+ }
+ }
+}
diff --git a/src/devices/bus/nubus/nubus_specpdq.h b/src/devices/bus/nubus/nubus_specpdq.h
index 53c3b9feb30..62b24c062b5 100644
--- a/src/devices/bus/nubus/nubus_specpdq.h
+++ b/src/devices/bus/nubus/nubus_specpdq.h
@@ -46,6 +46,10 @@ private:
uint32_t vram_r(offs_t offset, uint32_t mem_mask = ~0);
void vram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ void blitter_pattern_fill();
+ void blitter_copy_forward();
+ void blitter_copy_backward();
+
void update_crtc();
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
@@ -65,10 +69,13 @@ private:
uint8_t m_hdelay;
uint8_t m_osc;
- uint32_t m_7xxxxx_regs[0x100000/4];
- uint32_t m_width, m_height, m_patofsx, m_patofsy;
- uint32_t m_vram_addr, m_vram_src;
- uint32_t m_pattern[64];
+ uint16_t m_blit_stride;
+ uint32_t m_blit_src, m_blit_dst;
+ uint32_t m_blit_width, m_blit_height;
+ uint8_t m_blit_patoffs;
+ uint32_t m_blit_pat[64];
+
+ uint32_t m_7xxxxx_regs[0x100000 / 4];
};
diff --git a/src/devices/bus/nubus/supermac.cpp b/src/devices/bus/nubus/supermac.cpp
index af7ba20e9c1..c8f00e81003 100644
--- a/src/devices/bus/nubus/supermac.cpp
+++ b/src/devices/bus/nubus/supermac.cpp
@@ -131,13 +131,6 @@ bool supermac_spec_crtc::valid(device_t &device) const
}
-int supermac_spec_crtc::v_pos(screen_device const &screen) const
-{
- int const vpos = screen.vpos() + m_vsync + 1;
- return (vpos <= m_vtotal) ? vpos : (vpos - m_vtotal - 1);
-}
-
-
void supermac_spec_shift_reg::register_save(device_t &device)
{
device.save_item(NAME(m_shift_data));
diff --git a/src/devices/bus/nubus/supermac.h b/src/devices/bus/nubus/supermac.h
index d656eb6c4af..9fb4c93f326 100644
--- a/src/devices/bus/nubus/supermac.h
+++ b/src/devices/bus/nubus/supermac.h
@@ -24,9 +24,9 @@ public:
uint32_t h_active(uint32_t scale) const noexcept
{ return (m_hend - m_hstart) * scale; }
uint32_t h_start(uint32_t scale) const noexcept
- { return (m_hstart - m_hsync) * scale; }
+ { return (m_hstart + 1) * scale; }
uint32_t h_end(uint32_t scale) const noexcept
- { return (m_hend - m_hsync) * scale; }
+ { return (m_hend + 1) * scale; }
uint16_t v_sync() const noexcept
{ return m_vsync + 1; }
@@ -35,15 +35,13 @@ public:
uint32_t v_active() const noexcept
{ return (m_vend - m_vstart); }
uint16_t v_start() const noexcept
- { return m_vstart - m_vsync; }
+ { return m_vstart + 1; }
uint16_t v_end() const noexcept
- { return m_vend - m_vsync; }
+ { return m_vend + 1; }
attoseconds_t frame_time(uint32_t scale, XTAL const &osc) const noexcept
{ return attotime::from_ticks((m_htotal + 1) * (m_vtotal + 1) * scale, osc).attoseconds(); }
- int v_pos(screen_device const &screen) const;
-
private:
uint16_t m_hsync, m_hstart, m_hend, m_htotal;
uint16_t m_vsync, m_vstart, m_vend, m_vtotal;