/***************************************************************************
Radius Full Page Display card for the Mac SE, assy # 632-0022-A1
EPROMs are marked
"(c) 1991 Radius TPD/FPD-ASIC U6 297-0204-A V 4.1 256K" and "U7" with
all other text the same.
The SE PDS does not auto-configure like NuBus; cards have to snoop the 68k
address bus and claim spots the motherboard logic doesn't want.
This card claims these address ranges:
770000-77000F: Bt9014 RAMDAC
C00000-C0FFFF: EPROM
C10000 : read to ack vblank IRQ 2 (returns bit 7 = 0 for vblank active)
C20000 : read to enable vblank IRQ 2
C40000-C7FFFF: 256k VRAM
F80000-F8FFFF: EPROM mirror (the SE ROM looks for signatures and jump tables in this region)
TODO:
* suppress SE built-in screen (it stops working after OS boot with this card installed) & make our screen 3:4
* investigate if there's also a two-page display mode as the rom labels imply; 256K is
far too much for just 1024x880 but would fit double that nicely.
* later ROM versions provide System 7 compatibility; our current dump is good only
up to 6.0.8. (We have 4.1; the last version is 4.4).
***************************************************************************/
#include "emu.h"
#include "video/pds_tpdfpd.h"
#include "cpu/m68000/m68000.h"
#define SEDISPLAY_SCREEN_NAME "fpd_screen"
#define SEDISPLAY_ROM_REGION "fpd_rom"
#define VRAM_SIZE (256*1024) // PCB has a jumper for 1MByte; may require different EPROMs
MACHINE_CONFIG_FRAGMENT( sedisplay )
MCFG_SCREEN_ADD( SEDISPLAY_SCREEN_NAME, RASTER)
MCFG_SCREEN_UPDATE_DEVICE(DEVICE_SELF, macpds_sedisplay_device, screen_update)
MCFG_SCREEN_SIZE(1280, 960)
MCFG_SCREEN_REFRESH_RATE(70)
MCFG_SCREEN_VISIBLE_AREA(0, 640-1, 0, 870-1)
MACHINE_CONFIG_END
ROM_START( sedisplay )
ROM_REGION(0x10000, SEDISPLAY_ROM_REGION, ROMREGION_16BIT|ROMREGION_BE)
ROM_LOAD16_BYTE( "tfd_fpd-asic_u6_297-0205-a_v4_1", 0x0000, 0x8000, CRC(fd363f45) SHA1(3c4c596654647ee6ce1880de329aa675d298dc26) )
ROM_LOAD16_BYTE( "tfd_fpd-asic_u7_297-0205-a_v4_1", 0x0001, 0x8000, CRC(5872451a) SHA1(4673d9f341766c49ff1264b7819916e28a20518f) )
ROM_END
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
const device_type PDS_SEDISPLAY = &device_creator<macpds_sedisplay_device>;
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor macpds_sedisplay_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( sedisplay );
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const rom_entry *macpds_sedisplay_device::device_rom_region() const
{
return ROM_NAME( sedisplay );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// macpds_sedisplay_device - constructor
//-------------------------------------------------
macpds_sedisplay_device::macpds_sedisplay_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, PDS_SEDISPLAY, "Radius SE Full Page Display", tag, owner, clock, "pds_sefp", __FILE__),
device_video_interface(mconfig, *this),
device_macpds_card_interface(mconfig, *this),
m_assembled_tag(tag, ":", SEDISPLAY_SCREEN_NAME)
{
m_screen_tag = m_assembled_tag;
}
macpds_sedisplay_device::macpds_sedisplay_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
device_t(mconfig, type, name, tag, owner, clock, shortname, source),
device_video_interface(mconfig, *this),
device_macpds_card_interface(mconfig, *this),
m_assembled_tag(tag, ":", SEDISPLAY_SCREEN_NAME)
{
m_screen_tag = m_assembled_tag;
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void macpds_sedisplay_device::device_start()
{
set_macpds_device();
install_rom(this, SEDISPLAY_ROM_REGION, 0xc00000);
install_rom(this, SEDISPLAY_ROM_REGION, 0xf80000);
m_vram = auto_alloc_array(machine(), UINT8, VRAM_SIZE);
static const char bankname[] = { "radpds_ram" };
m_macpds->install_bank(0xc40000, 0xc40000+VRAM_SIZE-1, 0, 0, bankname, m_vram);
m_macpds->install_device(0x770000, 0x77000f, read16_delegate(FUNC(macpds_sedisplay_device::ramdac_r), this), write16_delegate(FUNC(macpds_sedisplay_device::ramdac_w), this));
m_macpds->install_device(0xc10000, 0xc2ffff, read16_delegate(FUNC(macpds_sedisplay_device::sedisplay_r), this), write16_delegate(FUNC(macpds_sedisplay_device::sedisplay_w), this));
m_timer = timer_alloc(0, NULL);
m_timer->adjust(m_screen->time_until_pos(879, 0), 0);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void macpds_sedisplay_device::device_reset()
{
m_count = 0;
m_clutoffs = 0;
m_vbl_disable = 1;
memset(m_vram, 0, VRAM_SIZE);
memset(m_palette, 0, sizeof(m_palette));
m_palette[0] = MAKE_RGB(0, 0, 0);
m_palette[1] = MAKE_RGB(255, 255, 255);
}
void macpds_sedisplay_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
{
if (!m_vbl_disable)
{
m_macpds->set_irq_line(M68K_IRQ_2, ASSERT_LINE);
}
m_timer->adjust(m_screen->time_until_pos(879, 0), 0);
}
/***************************************************************************
CB264 section
***************************************************************************/
UINT32 macpds_sedisplay_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
UINT32 *scanline;
int x, y;
UINT8 pixels, *vram;
vram = m_vram;
for (y = 0; y < 870; y++)
{
scanline = &bitmap.pix32(y);
for (x = 0; x < 640/8; x++)
{
pixels = vram[(y * (1024/8)) + (x^1)];
*scanline++ = m_palette[((pixels>>7)&0x1)^1];
*scanline++ = m_palette[((pixels>>6)&0x1)^1];
*scanline++ = m_palette[((pixels>>5)&0x1)^1];
*scanline++ = m_palette[((pixels>>4)&0x1)^1];
*scanline++ = m_palette[((pixels>>3)&0x1)^1];
*scanline++ = m_palette[((pixels>>2)&0x1)^1];
*scanline++ = m_palette[((pixels>>1)&0x1)^1];
*scanline++ = m_palette[(pixels&1)^1];
}
}
return 0;
}
WRITE16_MEMBER( macpds_sedisplay_device::sedisplay_w )
{
}
READ16_MEMBER( macpds_sedisplay_device::sedisplay_r )
{
if (offset == 0) // ack vbl
{
m_macpds->set_irq_line(M68K_IRQ_2, CLEAR_LINE);
}
else if (offset == 0x8000) // enable vbl
{
m_vbl_disable = 0;
}
return 0;
}
WRITE16_MEMBER( macpds_sedisplay_device::ramdac_w )
{
switch (offset)
{
case 4:
m_clutoffs = data>>8;
break;
case 5:
m_colors[m_count++] = data>>4; // they only fill in the lower nibble
if (m_count == 3)
{ // only the green channel drives the output
m_palette[m_clutoffs] = MAKE_RGB(m_colors[1], m_colors[1], m_colors[1]);
m_clutoffs++;
m_count = 0;
}
break;
default:
// printf("RAMDAC: %x to %x (mask %04x)\n", data, offset, mem_mask);
break;
}
}
READ16_MEMBER( macpds_sedisplay_device::ramdac_r )
{
return 0;
}