diff options
Diffstat (limited to 'src/mame/video/mac.c')
-rw-r--r-- | src/mame/video/mac.c | 1257 |
1 files changed, 1257 insertions, 0 deletions
diff --git a/src/mame/video/mac.c b/src/mame/video/mac.c new file mode 100644 index 00000000000..289c62feb57 --- /dev/null +++ b/src/mame/video/mac.c @@ -0,0 +1,1257 @@ +// license:BSD-3-Clause +// copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont +/*************************************************************************** + + video/mac.c + + Macintosh video hardware + + Emulates the video hardware for compact Macintosh series (original + Macintosh (128k, 512k, 512ke), Macintosh Plus, Macintosh SE, Macintosh + Classic) + + Also emulates on-board video for systems with the + RBV, V8, Eagle, Sonora, and DAFB chips. + + ---------------------------------------------------------------------- + Monitor sense codes + + Apple assigns 3 pins for monitor IDs. These allow 8 possible codes: + + 000 - color 2-Page Display (21") + 001 - monochrome Full Page display (15") + 010 - color 512x384 (12") + 011 - monochrome 2 Page display (21") + 100 - NTSC + 101 - color Full Page display (15") + 110 - High-Resolution Color (13" 640x480) or use "type 6" extended codes + 111 - No monitor connected or use "type 7" extended codes + + For extended codes, you drive one of the 3 pins at a time and read the 2 + undriven pins. See http://support.apple.com/kb/TA21618?viewlocale=en_US + for details. + +Extended codes: + + Sense 2 Low Sense 1 Low Sense 0 Low + 1 & 0 2 & 0 2 & 1 + +Multiple Scan 14" 00 00 11 +Multiple Scan 16" 00 10 11 +Multiple Scan 21" 10 00 11 +PAL Encoder 00 00 00 +NTSC Encoder 01 01 00 +VGA/Super VGA 01 01 11 +RGB 16" 10 11 01 +PAL Monitor 11 00 00 +RGB 19" 11 10 10 +Radius color TPD 11 00 01 (TPD = Two Page Display) +Radius mono TPD 11 01 00 +Apple TPD 11 01 01 +Apple color FPD 01 11 10 (FPD = Full Page Display) + +***************************************************************************/ + + +#include "emu.h" +#include "sound/asc.h" +#include "includes/mac.h" +#include "machine/ram.h" + +PALETTE_INIT_MEMBER(mac_state,mac) +{ + palette.set_pen_color(0, 0xff, 0xff, 0xff); + palette.set_pen_color(1, 0x00, 0x00, 0x00); +} + +// 4-level grayscale +PALETTE_INIT_MEMBER(mac_state,macgsc) +{ + palette.set_pen_color(0, 0xff, 0xff, 0xff); + palette.set_pen_color(1, 0x7f, 0x7f, 0x7f); + palette.set_pen_color(2, 0x3f, 0x3f, 0x3f); + palette.set_pen_color(3, 0x00, 0x00, 0x00); +} + +VIDEO_START_MEMBER(mac_state,mac) +{ +} + +#define MAC_MAIN_SCREEN_BUF_OFFSET 0x5900 +#define MAC_ALT_SCREEN_BUF_OFFSET 0xD900 + +UINT32 mac_state::screen_update_mac(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + UINT32 video_base; + const UINT16 *video_ram; + UINT16 word; + UINT16 *line; + int y, x, b; + + video_base = m_ram->size() - (m_screen_buffer ? MAC_MAIN_SCREEN_BUF_OFFSET : MAC_ALT_SCREEN_BUF_OFFSET); + video_ram = (const UINT16 *) (m_ram->pointer() + video_base); + + for (y = 0; y < MAC_V_VIS; y++) + { + line = &bitmap.pix16(y); + + for (x = 0; x < MAC_H_VIS; x += 16) + { + word = *(video_ram++); + for (b = 0; b < 16; b++) + { + line[x + b] = (word >> (15 - b)) & 0x0001; + } + } + } + return 0; +} + +UINT32 mac_state::screen_update_macse30(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + UINT32 video_base; + const UINT16 *video_ram; + UINT16 word; + UINT16 *line; + int y, x, b; + + video_base = m_screen_buffer ? 0x8000 : 0; + video_base += (MAC_H_VIS/8); + video_ram = (const UINT16 *) &m_vram[video_base/4]; + + for (y = 0; y < MAC_V_VIS; y++) + { + line = &bitmap.pix16(y); + + for (x = 0; x < MAC_H_VIS; x += 16) + { + word = video_ram[((y * MAC_H_VIS)/16) + ((x/16)^1)]; + for (b = 0; b < 16; b++) + { + line[x + b] = (word >> (15 - b)) & 0x0001; + } + } + } + return 0; +} + +UINT32 mac_state::screen_update_macprtb(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + const UINT16 *video_ram; + UINT16 word; + UINT16 *line; + int y, x, b; + + video_ram = (const UINT16 *) m_vram16.target(); + + for (y = 0; y < 400; y++) + { + line = &bitmap.pix16(y); + + for (x = 0; x < 640; x += 16) + { + word = video_ram[((y * 640)/16) + ((x/16))]; + for (b = 0; b < 16; b++) + { + line[x + b] = (word >> (15 - b)) & 0x0001; + } + } + } + return 0; +} + +UINT32 mac_state::screen_update_macpb140(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + const UINT16 *video_ram; + UINT16 word; + UINT16 *line; + int y, x, b; + + video_ram = (const UINT16 *) m_vram.target(); + + for (y = 0; y < 400; y++) + { + line = &bitmap.pix16(y); + + for (x = 0; x < 640; x += 16) + { + word = video_ram[((y * 640)/16) + ((x/16)^1)]; + for (b = 0; b < 16; b++) + { + line[x + b] = (word >> (15 - b)) & 0x0001; + } + } + } + return 0; +} + +UINT32 mac_state::screen_update_macpb160(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + UINT16 *line; + int y, x; + UINT8 pixels; + UINT8 *vram8 = (UINT8 *)m_vram.target(); + + for (y = 0; y < 400; y++) + { + line = &bitmap.pix16(y); + + for (x = 0; x < 640/4; x++) + { + pixels = vram8[(y * 160) + (BYTE4_XOR_BE(x))]; + + *line++ = ((pixels>>6)&3); + *line++ = ((pixels>>4)&3); + *line++ = ((pixels>>2)&3); + *line++ = (pixels&3); + + } + } + return 0; +} + +// IIci/IIsi RAM-Based Video (RBV) and children: V8, Eagle, Spice, VASP, Sonora + +VIDEO_START_MEMBER(mac_state,macrbv) +{ +} + +VIDEO_RESET_MEMBER(mac_state,maceagle) +{ + m_rbv_montype = 32; + m_rbv_palette[0xfe] = 0xffffff; + m_rbv_palette[0xff] = 0; +} + +VIDEO_RESET_MEMBER(mac_state,macrbv) +{ + rectangle visarea; + int htotal, vtotal; + double framerate; + int view; + + memset(m_rbv_regs, 0, sizeof(m_rbv_regs)); + + m_rbv_count = 0; + m_rbv_clutoffs = 0; + m_rbv_immed10wr = 0; + + m_rbv_regs[2] = 0x7f; + m_rbv_regs[3] = 0; + + m_rbv_type = RBV_TYPE_RBV; + + visarea.min_x = 0; + visarea.min_y = 0; + view = 0; + if (m_montype) + { + m_rbv_montype = m_montype->read(); + } + else + { + m_rbv_montype = 2; + } + switch (m_rbv_montype) + { + case 1: // 15" portrait display + visarea.max_x = 640-1; + visarea.max_y = 870-1; + htotal = 832; + vtotal = 918; + framerate = 75.0; + view = 1; + break; + + case 2: // 12" RGB + visarea.max_x = 512-1; + visarea.max_y = 384-1; + htotal = 640; + vtotal = 407; + framerate = 60.15; + break; + + case 6: // 13" RGB + default: + visarea.max_x = 640-1; + visarea.max_y = 480-1; + htotal = 800; + vtotal = 525; + framerate = 59.94; + break; + } + +// printf("RBV reset: monitor is %dx%d @ %f Hz\n", visarea.max_x+1, visarea.max_y+1, framerate); + machine().first_screen()->configure(htotal, vtotal, visarea, HZ_TO_ATTOSECONDS(framerate)); + render_target *target = machine().render().first_target(); + target->set_view(view); +} + +VIDEO_RESET_MEMBER(mac_state,macsonora) +{ + rectangle visarea; + int htotal, vtotal; + double framerate; + int view = 0; + + memset(m_rbv_regs, 0, sizeof(m_rbv_regs)); + + m_rbv_count = 0; + m_rbv_clutoffs = 0; + m_rbv_immed10wr = 0; + + m_rbv_regs[2] = 0x7f; + m_rbv_regs[3] = 0; + + m_rbv_type = RBV_TYPE_SONORA; + + visarea.min_x = 0; + visarea.min_y = 0; + + m_rbv_montype = m_montype ? m_montype->read() : 2; + switch (m_rbv_montype) + { + case 1: // 15" portrait display + visarea.max_x = 640-1; + visarea.max_y = 870-1; + htotal = 832; + vtotal = 918; + framerate = 75.0; + view = 1; + break; + + case 2: // 12" RGB + visarea.max_x = 512-1; + visarea.max_y = 384-1; + htotal = 640; + vtotal = 407; + framerate = 60.15; + break; + + case 6: // 13" RGB + default: + visarea.max_x = 640-1; + visarea.max_y = 480-1; + htotal = 800; + vtotal = 525; + framerate = 59.94; + break; + } + +// printf("Sonora reset: monitor is %dx%d @ %f Hz\n", visarea.max_x+1, visarea.max_y+1, framerate); + machine().first_screen()->configure(htotal, vtotal, visarea, HZ_TO_ATTOSECONDS(framerate)); + render_target *target = machine().render().first_target(); + target->set_view(view); +} + +VIDEO_START_MEMBER(mac_state,macsonora) +{ + memset(m_rbv_regs, 0, sizeof(m_rbv_regs)); + + m_rbv_count = 0; + m_rbv_clutoffs = 0; + m_rbv_immed10wr = 0; + + m_rbv_regs[2] = 0x7f; + m_rbv_regs[3] = 0; + m_rbv_regs[4] = 0x6; + m_rbv_regs[5] = 0x3; + + m_sonora_vctl[0] = 0x9f; + m_sonora_vctl[1] = 0; + m_sonora_vctl[2] = 0; + + m_rbv_type = RBV_TYPE_SONORA; +} + +VIDEO_START_MEMBER(mac_state,macv8) +{ + memset(m_rbv_regs, 0, sizeof(m_rbv_regs)); + + m_rbv_count = 0; + m_rbv_clutoffs = 0; + m_rbv_immed10wr = 0; + + m_rbv_regs[0] = 0x4f; + m_rbv_regs[1] = 0x06; + m_rbv_regs[2] = 0x7f; + + m_rbv_type = RBV_TYPE_V8; +} + +UINT32 mac_state::screen_update_macrbv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + UINT32 *scanline; + int x, y, hres, vres; + UINT8 *vram8 = (UINT8 *)m_ram->pointer(); + + switch (m_rbv_montype) + { + case 32: // classic II built-in display + hres = MAC_H_VIS; + vres = MAC_V_VIS; + vram8 += 0x1f9a80; // Classic II apparently doesn't use VRAM? + break; + + case 1: // 15" portrait display + hres = 640; + vres = 870; + break; + + case 2: // 12" RGB + hres = 512; + vres = 384; + break; + + case 6: // 13" RGB + default: + hres = 640; + vres = 480; + break; + } + + switch (m_rbv_regs[0x10] & 7) + { + case 0: // 1bpp + { + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < hres; x+=8) + { + pixels = vram8[(y * (hres/8)) + ((x/8)^3)]; + + *scanline++ = m_rbv_palette[0xfe|(pixels>>7)]; + *scanline++ = m_rbv_palette[0xfe|((pixels>>6)&1)]; + *scanline++ = m_rbv_palette[0xfe|((pixels>>5)&1)]; + *scanline++ = m_rbv_palette[0xfe|((pixels>>4)&1)]; + *scanline++ = m_rbv_palette[0xfe|((pixels>>3)&1)]; + *scanline++ = m_rbv_palette[0xfe|((pixels>>2)&1)]; + *scanline++ = m_rbv_palette[0xfe|((pixels>>1)&1)]; + *scanline++ = m_rbv_palette[0xfe|(pixels&1)]; + } + } + } + break; + + case 1: // 2bpp + { + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < hres/4; x++) + { + pixels = vram8[(y * (hres/4)) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[0xfc|((pixels>>6)&3)]; + *scanline++ = m_rbv_palette[0xfc|((pixels>>4)&3)]; + *scanline++ = m_rbv_palette[0xfc|((pixels>>2)&3)]; + *scanline++ = m_rbv_palette[0xfc|(pixels&3)]; + } + } + } + break; + + case 2: // 4bpp + { + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < hres/2; x++) + { + pixels = vram8[(y * (hres/2)) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[0xf0|(pixels>>4)]; + *scanline++ = m_rbv_palette[0xf0|(pixels&0xf)]; + } + } + } + break; + + case 3: // 8bpp + { + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < hres; x++) + { + pixels = vram8[(y * hres) + (BYTE4_XOR_BE(x))]; + *scanline++ = m_rbv_palette[pixels]; + } + } + } + } + + return 0; +} + +UINT32 mac_state::screen_update_macrbvvram(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + UINT32 *scanline; + int x, y, hres, vres; + + switch (m_rbv_montype) + { + case 1: // 15" portrait display + hres = 640; + vres = 870; + break; + + case 2: // 12" RGB + hres = 512; + vres = 384; + break; + + case 6: // 13" RGB + default: + hres = 640; + vres = 480; + break; + } + + switch (m_rbv_regs[0x10] & 7) + { + case 0: // 1bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < hres; x+=8) + { + pixels = vram8[(y * 0x400) + ((x/8)^3)]; + + *scanline++ = m_rbv_palette[0x7f|(pixels&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<1)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<2)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<3)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<4)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<5)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<6)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<7)&0x80)]; + } + } + } + break; + + case 1: // 2bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < hres/4; x++) + { + pixels = vram8[(y * (hres/4)) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[0xfc|((pixels>>6)&3)]; + *scanline++ = m_rbv_palette[0xfc|((pixels>>4)&3)]; + *scanline++ = m_rbv_palette[0xfc|((pixels>>2)&3)]; + *scanline++ = m_rbv_palette[0xfc|(pixels&3)]; + } + } + } + break; + + case 2: // 4bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < hres/2; x++) + { + pixels = vram8[(y * (hres/2)) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[0xf0|(pixels>>4)]; + *scanline++ = m_rbv_palette[0xf0|(pixels&0xf)]; + } + } + } + break; + + case 3: // 8bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < hres; x++) + { + pixels = vram8[(y * 2048) + (BYTE4_XOR_BE(x))]; + *scanline++ = m_rbv_palette[pixels]; + } + } + } + } + + return 0; +} + +UINT32 mac_state::screen_update_macv8(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + UINT32 *scanline; + int x, y, hres, vres; + + switch (m_rbv_montype) + { + case 1: // 15" portrait display + hres = 640; + vres = 870; + break; + + case 2: // 12" RGB + hres = 512; + vres = 384; + break; + + case 6: // 13" RGB + default: + hres = 640; + vres = 480; + break; + } + + switch (m_rbv_regs[0x10] & 7) + { + case 0: // 1bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < hres; x+=8) + { + pixels = vram8[(y * 1024) + ((x/8)^3)]; + + *scanline++ = m_rbv_palette[0x7f|(pixels&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<1)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<2)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<3)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<4)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<5)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<6)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<7)&0x80)]; + } + } + } + break; + + case 1: // 2bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < hres/4; x++) + { + pixels = vram8[(y * 1024) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[0x3f|(pixels&0xc0)]; + *scanline++ = m_rbv_palette[0x3f|((pixels<<2)&0xc0)]; + *scanline++ = m_rbv_palette[0x3f|((pixels<<4)&0xc0)]; + *scanline++ = m_rbv_palette[0x3f|((pixels<<6)&0xc0)]; + } + } + } + break; + + case 2: // 4bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < hres/2; x++) + { + pixels = vram8[(y * 1024) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[(pixels&0xf0) | 0xf]; + *scanline++ = m_rbv_palette[((pixels&0x0f)<<4) | 0xf]; + } + } + } + break; + + case 3: // 8bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < hres; x++) + { + pixels = vram8[(y * 1024) + (BYTE4_XOR_BE(x))]; + *scanline++ = m_rbv_palette[pixels]; + } + } + } + break; + } + + return 0; +} + +UINT32 mac_state::screen_update_macsonora(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + UINT32 *scanline; + int x, y, hres, vres, stride; + + switch (m_rbv_montype) + { + case 1: // 15" portrait display + stride = hres = 640; + vres = 870; + break; + + case 2: // 12" RGB + stride = hres = 512; + vres = 384; + break; + + case 6: // 13" RGB + default: + stride = hres = 640; + vres = 480; + break; + } + + // forced blank? + if (m_sonora_vctl[0] & 0x80) + { + return 0; + } + + switch (m_sonora_vctl[1] & 7) + { + case 0: // 1bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < hres; x+=8) + { + pixels = vram8[(y * (stride/8)) + ((x/8)^3)]; + + *scanline++ = m_rbv_palette[0x7f|(pixels&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<1)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<2)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<3)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<4)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<5)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<6)&0x80)]; + *scanline++ = m_rbv_palette[0x7f|((pixels<<7)&0x80)]; + } + } + } + break; + + case 1: // 2bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < hres/4; x++) + { + pixels = vram8[(y * (stride/4)) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[0x3f|(pixels&0xc0)]; + *scanline++ = m_rbv_palette[0x3f|((pixels<<2)&0xc0)]; + *scanline++ = m_rbv_palette[0x3f|((pixels<<4)&0xc0)]; + *scanline++ = m_rbv_palette[0x3f|((pixels<<6)&0xc0)]; + } + } + } + break; + + case 2: // 4bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < hres/2; x++) + { + pixels = vram8[(y * (stride/2)) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[(pixels&0xf0) | 0xf]; + *scanline++ = m_rbv_palette[((pixels&0x0f)<<4) | 0xf]; + } + } + } + break; + + case 3: // 8bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < hres; x++) + { + pixels = vram8[(y * stride) + (BYTE4_XOR_BE(x))]; + *scanline++ = m_rbv_palette[pixels]; + } + } + } + break; + + case 4: // 16bpp + { + UINT16 *vram16 = (UINT16 *)m_vram.target(); + UINT16 pixels; + + for (y = 0; y < vres; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < hres; x++) + { + pixels = vram16[(y * stride) + (x^1)]; + *scanline++ = rgb_t(((pixels>>10) & 0x1f)<<3, ((pixels>>5) & 0x1f)<<3, (pixels & 0x1f)<<3); + } + } + } + break; + } + + return 0; +} + +// DAFB: video for Quadra 700/900 + +void mac_state::dafb_recalc_ints() +{ + if (m_dafb_int_status != 0) + { + nubus_slot_interrupt(0xf, ASSERT_LINE); + } + else + { + nubus_slot_interrupt(0xf, CLEAR_LINE); + } +} + +TIMER_CALLBACK_MEMBER(mac_state::dafb_vbl_tick) +{ + m_dafb_int_status |= 1; + dafb_recalc_ints(); + + m_vbl_timer->adjust(m_screen->time_until_pos(480, 0), 0); +} + +TIMER_CALLBACK_MEMBER(mac_state::dafb_cursor_tick) +{ + m_dafb_int_status |= 4; + dafb_recalc_ints(); + + m_cursor_timer->adjust(m_screen->time_until_pos(m_cursor_line, 0), 0); +} + +VIDEO_START_MEMBER(mac_state,macdafb) +{ + m_vbl_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mac_state::dafb_vbl_tick),this)); + m_cursor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mac_state::dafb_cursor_tick),this)); + + m_vbl_timer->adjust(attotime::never); + m_cursor_timer->adjust(attotime::never); +} + +VIDEO_RESET_MEMBER(mac_state,macdafb) +{ + m_rbv_count = 0; + m_rbv_clutoffs = 0; + m_rbv_montype = 6; + m_rbv_vbltime = 0; + m_dafb_int_status = 0; + m_rbv_type = RBV_TYPE_DAFB; + m_dafb_mode = 0; + m_dafb_base = 0x1000; + m_dafb_stride = 256*4; + + memset(m_rbv_palette, 0, sizeof(m_rbv_palette)); +} + +READ32_MEMBER(mac_state::dafb_r) +{ +// if (offset != 0x108/4) printf("DAFB: Read @ %x (mask %x PC=%x)\n", offset*4, mem_mask, m_maincpu->pc()); + + switch (offset<<2) + { + case 0x1c: // inverse of monitor sense + return 7; // 21" color 2-page + + case 0x24: // SCSI 539x #1 status + return m_dafb_scsi1_drq<<9; + + case 0x28: // SCSI 539x #2 status + return m_dafb_scsi2_drq<<9; + + case 0x108: // IRQ/VBL status + return m_dafb_int_status; + + case 0x10c: // clear cursor scanline int + m_dafb_int_status &= ~4; + dafb_recalc_ints(); + break; + + case 0x114: // clear VBL int + m_dafb_int_status &= ~1; + dafb_recalc_ints(); + break; + } + return 0; +} + +WRITE32_MEMBER(mac_state::dafb_w) +{ +// if (offset != 0x10c/4) printf("DAFB: Write %08x @ %x (mask %x PC=%x)\n", data, offset*4, mem_mask, m_maincpu->pc()); + + switch (offset<<2) + { + case 0: // bits 20-9 of base + m_dafb_base &= 0x1ff; + m_dafb_base |= (data & 0xffff) << 9; +// printf("DAFB baseH: %x\n", m_dafb_base); + break; + + case 4: // bits 8-5 of base + m_dafb_base &= ~0x1ff; + m_dafb_base |= (data & 0xf) << 5; +// printf("DAFB baseL: %x\n", m_dafb_base); + break; + + case 8: + m_dafb_stride = data<<2; // stride in DWORDs +// printf("DAFB stride: %x %x\n", m_dafb_stride, data); + break; + + case 0x104: + if (data & 1) // VBL enable + { + m_vbl_timer->adjust(m_screen->time_until_pos(480, 0), 0); + } + else + { + m_vbl_timer->adjust(attotime::never); + m_dafb_int_status &= ~1; + dafb_recalc_ints(); + } + + if (data & 2) // aux scanline interrupt enable + { + fatalerror("DAFB: Aux scanline interrupt enable not supported!\n"); + } + + if (data & 4) // cursor scanline interrupt enable + { + m_cursor_timer->adjust(m_screen->time_until_pos(m_cursor_line, 0), 0); + } + else + { + m_cursor_timer->adjust(attotime::never); + m_dafb_int_status &= ~4; + dafb_recalc_ints(); + } + break; + + case 0x10c: // clear cursor scanline int + m_dafb_int_status &= ~4; + dafb_recalc_ints(); + break; + + case 0x114: // clear VBL int + m_dafb_int_status &= ~1; + dafb_recalc_ints(); + break; + } +} + +READ32_MEMBER(mac_state::dafb_dac_r) +{ +// printf("DAFB: Read DAC @ %x (mask %x PC=%x)\n", offset*4, mem_mask, m_maincpu->pc()); + + return 0; +} + +WRITE32_MEMBER(mac_state::dafb_dac_w) +{ +// if ((offset > 0) && (offset != 0x10/4)) printf("DAFB: Write %08x to DAC @ %x (mask %x PC=%x)\n", data, offset*4, mem_mask, m_maincpu->pc()); + + switch (offset<<2) + { + case 0: + m_rbv_clutoffs = data & 0xff; + m_rbv_count = 0; + break; + + case 0x10: + m_rbv_colors[m_rbv_count++] = data&0xff; + + if (m_rbv_count == 3) + { + m_palette->set_pen_color(m_rbv_clutoffs, rgb_t(m_rbv_colors[0], m_rbv_colors[1], m_rbv_colors[2])); + m_rbv_palette[m_rbv_clutoffs] = rgb_t(m_rbv_colors[0], m_rbv_colors[1], m_rbv_colors[2]); + m_rbv_clutoffs++; + m_rbv_count = 0; + } + break; + + case 0x20: + printf("%x to DAFB mode\n", data); + switch (data & 0x9f) + { + case 0x80: + m_dafb_mode = 0; // 1bpp + break; + + case 0x88: + m_dafb_mode = 1; // 2bpp + break; + + case 0x90: + m_dafb_mode = 2; // 4bpp + break; + + case 0x98: + m_dafb_mode = 3; // 8bpp + break; + + case 0x9c: + m_dafb_mode = 4; // 24bpp + break; + } + break; + } +} + +UINT32 mac_state::screen_update_macdafb(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + UINT32 *scanline; + int x, y; + + switch (m_dafb_mode) + { + case 0: // 1bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + vram8 += m_dafb_base; + + for (y = 0; y < 870; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < 1152; x+=8) + { + pixels = vram8[(y * m_dafb_stride) + ((x/8)^3)]; + + *scanline++ = m_rbv_palette[(pixels>>7)&1]; + *scanline++ = m_rbv_palette[(pixels>>6)&1]; + *scanline++ = m_rbv_palette[(pixels>>5)&1]; + *scanline++ = m_rbv_palette[(pixels>>4)&1]; + *scanline++ = m_rbv_palette[(pixels>>3)&1]; + *scanline++ = m_rbv_palette[(pixels>>2)&1]; + *scanline++ = m_rbv_palette[(pixels>>1)&1]; + *scanline++ = m_rbv_palette[(pixels&1)]; + } + } + } + break; + + case 1: // 2bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + vram8 += m_dafb_base; + + for (y = 0; y < 870; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < 1152/4; x++) + { + pixels = vram8[(y * m_dafb_stride) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[((pixels>>6)&3)]; + *scanline++ = m_rbv_palette[((pixels>>4)&3)]; + *scanline++ = m_rbv_palette[((pixels>>2)&3)]; + *scanline++ = m_rbv_palette[(pixels&3)]; + } + } + } + break; + + case 2: // 4bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + vram8 += m_dafb_base; + + for (y = 0; y < 870; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < 1152/2; x++) + { + pixels = vram8[(y * m_dafb_stride) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[(pixels>>4)]; + *scanline++ = m_rbv_palette[(pixels&0xf)]; + } + } + } + break; + + case 3: // 8bpp + { + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + vram8 += m_dafb_base; + + for (y = 0; y < 870; y++) + { + scanline = &bitmap.pix32(y); + + for (x = 0; x < 1152; x++) + { + pixels = vram8[(y * m_dafb_stride) + (BYTE4_XOR_BE(x))]; + *scanline++ = m_rbv_palette[pixels]; + } + } + } + break; + + case 4: // 24 bpp + for (y = 0; y < 480; y++) + { + UINT32 *base; + + scanline = &bitmap.pix32(y); + base = (UINT32 *)&m_vram[(y * (m_dafb_stride/4)) + (m_dafb_base/4)]; + for (x = 0; x < 640; x++) + { + *scanline++ = *base++; + } + } + break; + } + + return 0; +} + +UINT32 mac_state::screen_update_macpbwd(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)/* Color PowerBooks using an off-the-shelf WD video chipset */ +{ + UINT32 *scanline; + int x, y; + UINT8 *vram8 = (UINT8 *)m_vram.target(); + UINT8 pixels; + +// vram8 += 0x40000; + + for (y = 0; y < 480; y++) + { + scanline = &bitmap.pix32(y); + for (x = 0; x < 640; x++) + { + pixels = vram8[(y * 640) + (BYTE4_XOR_BE(x))]; + *scanline++ = m_rbv_palette[pixels]; + } + } + + return 0; +} + +READ32_MEMBER(mac_state::macwd_r) +{ + switch (offset) + { + case 0xf6: + if (m_screen->vblank()) + { + return 0xffffffff; + } + else + { + return 0; + } + + default: +// printf("macwd_r: @ %x, mask %08x (PC=%x)\n", offset, mem_mask, m_maincpu->pc()); + break; + } + return 0; +} + +WRITE32_MEMBER(mac_state::macwd_w) +{ + switch (offset) + { + case 0xf2: + if (mem_mask == 0xff000000) // DAC control + { + m_rbv_clutoffs = data>>24; + m_rbv_count = 0; + } + else if (mem_mask == 0x00ff0000) // DAC data + { + m_rbv_colors[m_rbv_count++] = (data>>16)&0xff; + if (m_rbv_count == 3) + { +// printf("RAMDAC: color %d = %02x %02x %02x\n", m_rbv_clutoffs, m_rbv_colors[0], m_rbv_colors[1], m_rbv_colors[2]); + m_rbv_palette[m_rbv_clutoffs] = rgb_t(m_rbv_colors[0], m_rbv_colors[1], m_rbv_colors[2]); + m_rbv_clutoffs++; + m_rbv_count = 0; + } + } + else + { + printf("macwd: Unknown DAC write, data %08x, mask %08x\n", data, mem_mask); + } + break; + + default: +// printf("macwd_w: %x @ %x, mask %08x (PC=%x)\n", data, offset, mem_mask, m_maincpu->pc()); + break; + } +} |