decstation: Emulated accelerated quasi-blitter enough to get a working console [R. Belmont]

This commit is contained in:
arbee 2018-09-08 12:05:10 -04:00
parent a24d9ab6ae
commit 809a58d21d

View File

@ -4,10 +4,10 @@
decstation.cpp: MIPS-based DECstation family decstation.cpp: MIPS-based DECstation family
WANTED: all boot ROM dumps except 5000/133, all TURBOchannel card ROM dumps WANTED: boot ROM dumps for KN02CA/KN04CA (MAXine) systems.
NOTE: after all the spew of failing tests (it really wants a VT102 terminal), NOTE: after all the spew of failing tests, press 'q' at the MORE prompt and
press 'q' at the MORE prompt and wait a few seconds for the PROM monitor to appear. wait a few seconds for the PROM monitor to appear.
Type 'ls' for a list of commands (this is a very UNIX-flavored PROM monitor). Type 'ls' for a list of commands (this is a very UNIX-flavored PROM monitor).
Machine types: Machine types:
@ -19,9 +19,9 @@
Ethernet: AMD7990 "LANCE" controller Ethernet: AMD7990 "LANCE" controller
Monochrome or color video on-board Monochrome or color video on-board
PMIN/KN01: PMIN/KN01:
Cheaper PMAX, 12.5 MHz R2000, same as PMAX Cheaper PMAX, 12.5 MHz R2000, othersame as PMAX
Personal DECstation 5000/xx (MAXine/KN02BA): Personal DECstation 5000/xx (MAXine/KN02CA for R3000, KN04CA? for R4000)
20, 25, or 33 MHz R3000 or 100 MHz R4000 20, 25, or 33 MHz R3000 or 100 MHz R4000
40 MiB max RAM 40 MiB max RAM
Serial: DEC "DZ" quad-UART for keyboard/mouse, SCC8530 for modem/printer Serial: DEC "DZ" quad-UART for keyboard/mouse, SCC8530 for modem/printer
@ -31,7 +31,7 @@
Color 1024x768 8bpp video on-board Color 1024x768 8bpp video on-board
2 TURBOchannel slots 2 TURBOchannel slots
DECstation 5000/1xx: (3MIN/KN02DA): DECstation 5000/1xx: (3MIN/KN02BA, KN04BA? for R4000):
20, 25, or 33 MHz R3000 or 100 MHz R4000 20, 25, or 33 MHz R3000 or 100 MHz R4000
128 MiB max RAM 128 MiB max RAM
Serial: 2x SCC8530 Serial: 2x SCC8530
@ -47,7 +47,7 @@
SCSI: NCR53C94 SCSI: NCR53C94
Ethernet: AMD7990 "LANCE" controllor Ethernet: AMD7990 "LANCE" controllor
DECstation 5000/240, 5000/261 (3MAX+/KN03) DECstation 5000/240 (3MAX+/KN03AA), 5000/260 (3MAX+/KN05)
40 MHz R3400, or 120 MHz R4400. 40 MHz R3400, or 120 MHz R4400.
480 MiB max RAM 480 MiB max RAM
Serial: 2x SCC8530 Serial: 2x SCC8530
@ -58,6 +58,7 @@
#include "emu.h" #include "emu.h"
#include "cpu/mips/r3000.h" #include "cpu/mips/r3000.h"
#include "cpu/mips/mips3.h"
#include "machine/decioga.h" #include "machine/decioga.h"
#include "machine/mc146818.h" #include "machine/mc146818.h"
#include "machine/z80scc.h" #include "machine/z80scc.h"
@ -65,7 +66,10 @@
#include "machine/nscsi_bus.h" #include "machine/nscsi_bus.h"
#include "machine/nscsi_cd.h" #include "machine/nscsi_cd.h"
#include "machine/nscsi_hd.h" #include "machine/nscsi_hd.h"
#include "machine/dec_lk201.h"
#include "bus/rs232/rs232.h" #include "bus/rs232/rs232.h"
#include "screen.h"
#include "video/bt459.h"
class decstation_state : public driver_device class decstation_state : public driver_device
{ {
@ -73,14 +77,18 @@ public:
decstation_state(const machine_config &mconfig, device_type type, const char *tag) decstation_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) , : driver_device(mconfig, type, tag) ,
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
m_screen(*this, "screen"),
m_lk201(*this, "lk201"),
m_ioga(*this, "ioga"), m_ioga(*this, "ioga"),
m_rtc(*this, "rtc"), m_rtc(*this, "rtc"),
m_scc0(*this, "scc0"), m_scc0(*this, "scc0"),
m_scc1(*this, "scc1"), m_scc1(*this, "scc1"),
m_asc(*this, "scsibus:7:asc") m_asc(*this, "scsibus:7:asc"),
m_vrom(*this, "gfx"),
m_bt459(*this, "bt459")
{ } { }
void kn02da(machine_config &config); void kn02ba(machine_config &config);
void init_decstation(); void init_decstation();
@ -95,65 +103,101 @@ protected:
private: private:
virtual void machine_start() override; virtual void machine_start() override;
virtual void machine_reset() override; virtual void machine_reset() override;
virtual void video_start() override;
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
required_device<cpu_device> m_maincpu; required_device<cpu_device> m_maincpu;
required_device<screen_device> m_screen;
required_device<lk201_device> m_lk201;
required_device<dec_ioga_device> m_ioga; required_device<dec_ioga_device> m_ioga;
required_device<mc146818_device> m_rtc; required_device<mc146818_device> m_rtc;
required_device<z80scc_device> m_scc0, m_scc1; required_device<z80scc_device> m_scc0, m_scc1;
required_device<ncr53c94_device> m_asc; required_device<ncr53c94_device> m_asc;
required_memory_region m_vrom;
required_device<bt459_device> m_bt459;
void decstation_map(address_map &map); void threemin_map(address_map &map);
uint8_t *m_vrom_ptr;
uint32_t m_vram[0x200000/4];
uint32_t m_sfb[0x80];
int m_copy_src;
}; };
/*************************************************************************** /***************************************************************************
VIDEO HARDWARE VIDEO HARDWARE
***************************************************************************/ ***************************************************************************/
void decstation_state::video_start()
{
}
uint32_t decstation_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
m_bt459->screen_update(screen, bitmap, cliprect, (uint8_t *)&m_vram[0]);
return 0;
}
/*
0x100000 copy register 0
0x100004 copy register 1
0x100008 copy register 2
0x10000C copy register 3
0x100010 copy register 4
0x100014 copy register 5
0x100018 copy register 6
0x10001C copy register 7
0x100020 foreground register
0x100024 background register
0x100028 plane mask
0x10002C pixel mask
0x100030 cxt mode
0x100034 boolean operation
0x100038 pixel shift
0x10003C line address
0x100040 bresh 1
0x100044 bresh 2
0x100048 bresh 3
0x10004C bresh continue
0x100050 deep register
0x100054 start register
0x100058 Clear Interrupt
0x10005C reserved 2
0x100060 refresh count
0x100064 video horiz
0x100068 video vertical
0x10006C refresh base
0x100070 video valid
0x100074 Interrupt Enable
*/
#define MODE_SIMPLE 0
#define MODE_OPAQUESTIPPLE 1
#define MODE_OPAQUELINE 2
#define MODE_TRANSPARENTSTIPPLE 5
#define MODE_TRANSPARENTLINE 6
#define MODE_COPY 7
READ32_MEMBER(decstation_state::cfb_r) READ32_MEMBER(decstation_state::cfb_r)
{ {
static const char fwver[8] = "V5.3a ";
static const char fwvendor[8] = "DEC ";
static const char fwmodule[8] = "PMAG-BA";
static const char fwtype[8] = "TCF0 ";
static const char fwinfo[8] = "CX - D8";
uint32_t addr = offset << 2; uint32_t addr = offset << 2;
logerror("cfb_r: reading at %x\n", addr); // logerror("cfb_r: reading at %x\n", addr);
// attempt to fake the ROM ID bytes of a PMAG-BA if (addr < 0x800000)
// color framebuffer card. doesn't work for unknown reasons.
if ((addr >= 0x3c0400) && (addr < 0x3c0420))
{ {
return fwver[(addr>>2)&0x7]; return m_vrom_ptr[addr>>2] & 0xff;
}
if ((addr >= 0x3c0420) && (addr < 0x3c0440))
{
return fwvendor[(addr>>2)&0x7];
}
if ((addr >= 0x3c0440) && (addr < 0x3c0460))
{
return fwmodule[(addr>>2)&0x7];
}
if ((addr >= 0x3c0460) && (addr < 0x3c0480))
{
return fwtype[(addr>>2)&0x7];
}
if ((addr >= 0x3c0480) && (addr < 0x3c04a0))
{
return fwinfo[(addr>>2)&0x7];
} }
switch (addr) if ((addr >= 0x100000) && (addr < 0x100200))
{ {
case 0x3c03e0: return 1; // ROM width return m_sfb[offset-(0x100000/4)];
case 0x3c03e4: return 4; // ROM stride }
case 0x3c03e8: return 1; // ROM size in 8 KiB units
case 0x3c03ec: return 1; // card address space in 4 MiB units if ((addr >= 0x200000) && (addr < 0x400000))
case 0x3c03f0: return 0x55555555; // TURBOchannel ID bytes {
case 0x3c03f4: return 0x00000000; return m_vram[offset-(0x200000/4)];
case 0x3c03f8: return 0xaaaaaaaa;
case 0x3c03fc: return 0xffffffff;
case 0x3c0470: return 0; // does card support parity?
} }
return 0xffffffff; return 0xffffffff;
@ -161,7 +205,93 @@ READ32_MEMBER(decstation_state::cfb_r)
WRITE32_MEMBER(decstation_state::cfb_w) WRITE32_MEMBER(decstation_state::cfb_w)
{ {
logerror("cfb: %08x (mask %08x) @ %x\n", data, mem_mask, offset); uint32_t addr = offset << 2;
if ((addr >= 0x100000) && (addr < 0x100200))
{
//printf("SFB: %08x (mask %08x) @ %x\n", data, mem_mask, offset<<2);
COMBINE_DATA(&m_sfb[offset-(0x100000/4)]);
if ((addr == 0x100030) && (data = 7))
{
m_copy_src = 1;
}
return;
}
if ((addr >= 0x1c0000) && (addr < 0x200000))
{
//printf("Bt459: %08x (mask %08x) @ %x\n", data, mem_mask, offset<<2);
return;
}
if ((addr >= 0x200000) && (addr < 0x400000))
{
//printf("FB: %08x (mask %08x) @ %x\n", data, mem_mask, offset<<2);
switch (m_sfb[0x30/4])
{
case MODE_SIMPLE: // simple
COMBINE_DATA(&m_vram[offset-(0x200000/4)]);
break;
case MODE_TRANSPARENTSTIPPLE:
{
uint8_t *pVRAM = (uint8_t *)&m_vram[offset-(0x200000/4)];
uint8_t fgs[4];
fgs[0] = m_sfb[0x20/4] >> 24;
fgs[1] = (m_sfb[0x20/4] >> 16) & 0xff;
fgs[2] = (m_sfb[0x20/4] >> 8) & 0xff;
fgs[3] = m_sfb[0x20/4] & 0xff;
for (int x = 0; x < 32; x++)
{
if (data & (1<<(31-x)))
{
pVRAM[x] = fgs[x & 3];
}
}
}
break;
case MODE_COPY:
{
uint8_t *pVRAM = (uint8_t *)&m_vram[offset-(0x200000/4)];
uint8_t *pBuffer = (uint8_t *)&m_sfb[0]; // first 8 32-bit regs are the copy buffer
if (m_copy_src)
{
m_copy_src = 0;
for (int x = 0; x < 32; x++)
{
if (data & (1<<(31-x)))
{
pBuffer[x] = pVRAM[x];
}
}
}
else
{
m_copy_src = 1;
for (int x = 0; x < 32; x++)
{
if (data & (1<<(31-x)))
{
pVRAM[x] = pBuffer[x];
}
}
}
}
break;
default:
logerror("SFB: Unsupported VRAM write %08x (mask %08x) at %08x in mode %x\n", data, mem_mask, offset<<2, m_sfb[0x30/4]);
break;
}
return;
}
} }
/*************************************************************************** /***************************************************************************
@ -170,20 +300,26 @@ WRITE32_MEMBER(decstation_state::cfb_w)
void decstation_state::machine_start() void decstation_state::machine_start()
{ {
m_vrom_ptr = m_vrom->base();
save_item(NAME(m_vram));
save_item(NAME(m_sfb));
save_item(NAME(m_copy_src));
} }
void decstation_state::machine_reset() void decstation_state::machine_reset()
{ {
m_copy_src = 1;
} }
/*************************************************************************** /***************************************************************************
ADDRESS MAPS ADDRESS MAPS
***************************************************************************/ ***************************************************************************/
void decstation_state::decstation_map(address_map &map) void decstation_state::threemin_map(address_map &map)
{ {
map(0x00000000, 0x07ffffff).ram(); // full 128 MB map(0x00000000, 0x07ffffff).ram(); // full 128 MB
map(0x10000000, 0x103cffff).rw(FUNC(decstation_state::cfb_r), FUNC(decstation_state::cfb_w)); map(0x10000000, 0x13ffffff).rw(FUNC(decstation_state::cfb_r), FUNC(decstation_state::cfb_w));
map(0x101c0000, 0x101c000f).m("bt459", FUNC(bt459_device::map)).umask32(0x000000ff);
map(0x1c000000, 0x1c07ffff).m(m_ioga, FUNC(dec_ioga_device::map)); map(0x1c000000, 0x1c07ffff).m(m_ioga, FUNC(dec_ioga_device::map));
map(0x1c100000, 0x1c100003).rw(m_scc0, FUNC(z80scc_device::ca_r), FUNC(z80scc_device::ca_w)).umask32(0x0000ff00); map(0x1c100000, 0x1c100003).rw(m_scc0, FUNC(z80scc_device::ca_r), FUNC(z80scc_device::ca_w)).umask32(0x0000ff00);
map(0x1c100004, 0x1c100007).rw(m_scc0, FUNC(z80scc_device::da_r), FUNC(z80scc_device::da_w)).umask32(0x0000ff00); map(0x1c100004, 0x1c100007).rw(m_scc0, FUNC(z80scc_device::da_r), FUNC(z80scc_device::da_w)).umask32(0x0000ff00);
@ -216,13 +352,19 @@ static void dec_scsi_devices(device_slot_interface &device)
device.option_add_internal("asc", NCR53C94); device.option_add_internal("asc", NCR53C94);
} }
MACHINE_CONFIG_START(decstation_state::kn02da) MACHINE_CONFIG_START(decstation_state::kn02ba)
MCFG_DEVICE_ADD( "maincpu", R3041, 33000000 ) // FIXME: Should be R3000A MCFG_DEVICE_ADD( "maincpu", R3041, 33000000 ) // FIXME: Should be R3000A
MCFG_R3000_ENDIANNESS(ENDIANNESS_LITTLE) MCFG_R3000_ENDIANNESS(ENDIANNESS_LITTLE)
MCFG_R3000_BRCOND0_INPUT(READLINE(*this, decstation_state, brcond0_r)) MCFG_R3000_BRCOND0_INPUT(READLINE(*this, decstation_state, brcond0_r))
MCFG_DEVICE_PROGRAM_MAP( decstation_map ) MCFG_DEVICE_PROGRAM_MAP( threemin_map )
MCFG_DEVICE_ADD("ioga", DECSTATION_IOGA, XTAL(12'500'000)) SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(130000000, 1704, 32, (1280+32), 1064, 3, (1024+3));
m_screen->set_screen_update(FUNC(decstation_state::screen_update));
BT459(config, m_bt459, 83'020'800);
DECSTATION_IOGA(config, m_ioga, XTAL(12'500'000));
MC146818(config, m_rtc, XTAL(32'768)); MC146818(config, m_rtc, XTAL(32'768));
m_rtc->irq().set("ioga", FUNC(dec_ioga_device::rtc_irq_w)); m_rtc->irq().set("ioga", FUNC(dec_ioga_device::rtc_irq_w));
@ -230,21 +372,25 @@ MACHINE_CONFIG_START(decstation_state::kn02da)
SCC85C30(config, m_scc0, XTAL(14'745'600)/2); SCC85C30(config, m_scc0, XTAL(14'745'600)/2);
//m_scc0->out_int_callback().set("ioga", FUNC(dec_ioga_device::scc0_irq_w)); //m_scc0->out_int_callback().set("ioga", FUNC(dec_ioga_device::scc0_irq_w));
m_scc0->out_txda_callback().set("rs232a", FUNC(rs232_port_device::write_txd));
m_scc0->out_txdb_callback().set("rs232b", FUNC(rs232_port_device::write_txd));
SCC85C30(config, m_scc1, XTAL(14'745'600)/2); SCC85C30(config, m_scc1, XTAL(14'745'600)/2);
//m_scc1->out_int_callback().set("ioga", FUNC(dec_ioga_device::scc1_irq_w)); //m_scc1->out_int_callback().set("ioga", FUNC(dec_ioga_device::scc1_irq_w));
m_scc1->out_txda_callback().set("rs232a", FUNC(rs232_port_device::write_txd)); m_scc1->out_txdb_callback().set("lk201", FUNC(lk201_device::rx_w));
m_scc1->out_txdb_callback().set("rs232b", FUNC(rs232_port_device::write_txd));
MCFG_DEVICE_ADD("rs232a", RS232_PORT, default_rs232_devices, "terminal") MCFG_DEVICE_ADD("lk201", LK201, 0)
MCFG_RS232_RXD_HANDLER(WRITELINE("scc1", z80scc_device, rxa_w)) MCFG_LK201_TX_HANDLER(WRITELINE("scc1", z80scc_device, rxb_w))
MCFG_RS232_DCD_HANDLER(WRITELINE("scc1", z80scc_device, dcda_w))
MCFG_RS232_CTS_HANDLER(WRITELINE("scc1", z80scc_device, ctsa_w)) MCFG_DEVICE_ADD("rs232a", RS232_PORT, default_rs232_devices, nullptr)
MCFG_RS232_RXD_HANDLER(WRITELINE("scc0", z80scc_device, rxa_w))
MCFG_RS232_DCD_HANDLER(WRITELINE("scc0", z80scc_device, dcda_w))
MCFG_RS232_CTS_HANDLER(WRITELINE("scc0", z80scc_device, ctsa_w))
MCFG_DEVICE_ADD("rs232b", RS232_PORT, default_rs232_devices, nullptr) MCFG_DEVICE_ADD("rs232b", RS232_PORT, default_rs232_devices, nullptr)
MCFG_RS232_RXD_HANDLER(WRITELINE("scc1", z80scc_device, rxb_w)) MCFG_RS232_RXD_HANDLER(WRITELINE("scc0", z80scc_device, rxb_w))
MCFG_RS232_DCD_HANDLER(WRITELINE("scc1", z80scc_device, dcdb_w)) MCFG_RS232_DCD_HANDLER(WRITELINE("scc0", z80scc_device, dcdb_w))
MCFG_RS232_CTS_HANDLER(WRITELINE("scc1", z80scc_device, ctsb_w)) MCFG_RS232_CTS_HANDLER(WRITELINE("scc0", z80scc_device, ctsb_w))
MCFG_NSCSI_BUS_ADD("scsibus") MCFG_NSCSI_BUS_ADD("scsibus")
MCFG_NSCSI_ADD("scsibus:0", dec_scsi_devices, "harddisk", false) MCFG_NSCSI_ADD("scsibus:0", dec_scsi_devices, "harddisk", false)
@ -275,8 +421,12 @@ void decstation_state::init_decstation()
ROM_START( ds5k133 ) ROM_START( ds5k133 )
ROM_REGION32_LE( 0x40000, "user1", 0 ) ROM_REGION32_LE( 0x40000, "user1", 0 )
// 5.7j sx
ROM_LOAD( "ds5000-133_005eb.bin", 0x000000, 0x040000, CRC(76a91d29) SHA1(140fcdb4fd2327daf764a35006d05fabfbee8da6) ) ROM_LOAD( "ds5000-133_005eb.bin", 0x000000, 0x040000, CRC(76a91d29) SHA1(140fcdb4fd2327daf764a35006d05fabfbee8da6) )
ROM_REGION32_LE( 0x20000, "gfx", 0 )
ROM_LOAD( "pmagb-ba-rom.img", 0x000000, 0x020000, CRC(91f40ab0) SHA1(a39ce6ed52697a513f0fb2300a1a6cf9e2eabe33) )
ROM_END ROM_END
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1992, ds5k133, 0, 0, kn02da, decstation, decstation_state, init_decstation, "Digital Equipment Corporation", "DECstation 5000/133", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) COMP( 1992, ds5k133, 0, 0, kn02ba, decstation, decstation_state, init_decstation, "Digital Equipment Corporation", "DECstation 5000/133", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )