/*************************************************************************** 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; //------------------------------------------------- // 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; }