diff --git a/.gitattributes b/.gitattributes index 194cb7e316b..f842c3a6b6f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3275,6 +3275,7 @@ src/mame/drivers/rainbow.c svneol=native#text/plain src/mame/drivers/rallyx.c svneol=native#text/plain src/mame/drivers/rampart.c svneol=native#text/plain src/mame/drivers/rastan.c svneol=native#text/plain +src/mame/drivers/rastersp.c svneol=native#text/plain src/mame/drivers/rbmk.c svneol=native#text/plain src/mame/drivers/rcorsair.c svneol=native#text/plain src/mame/drivers/re900.c svneol=native#text/plain diff --git a/src/mame/drivers/rastersp.c b/src/mame/drivers/rastersp.c new file mode 100644 index 00000000000..67cc92a53fb --- /dev/null +++ b/src/mame/drivers/rastersp.c @@ -0,0 +1,954 @@ +/*************************************************************************** + + Bell-Fruit/ATD RasterSpeed hardware + + driver by Phil Bennett + + Games supported: + * Rise of the Robots (prototype) + + ROMs wanted: + * Zool (prototype) + * Football Crazy (need HDD/CD image) + +****************************************************************************/ + +#include "emu.h" +#include "cpu/i386/i386.h" +#include "cpu/tms32031/tms32031.h" +#include "machine/53c7xx.h" +#include "machine/mc146818.h" +#include "machine/nscsi_hd.h" +#include "sound/dac.h" + + +/************************************* + * + * Defines + * + *************************************/ + +#define SOUND_CLOCK XTAL_12_288MHz +#define PLL_CLOCK XTAL_14_31818MHz +#define NVRAM_SIZE 0x8000 + +#define USE_SPEEDUP_HACK 1 + + +/************************************* + * + * Driver class + * + *************************************/ + +static IRQ_CALLBACK( irq_callback ); + +class rastersp_state : public driver_device +{ +public: + rastersp_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_dsp(*this, "dsp"), + m_dram(*this, "dram"), + m_dac_l(*this, "dac_l"), + m_dac_r(*this, "dac_r"), + m_tms_timer1(*this, "tms_timer1"), + m_tms_tx_timer(*this, "tms_tx_timer") + {} + + #define VIDEO_ADDR_MASK 0x3fffffff + + enum tms_regs + { + DMA_GLOBAL_CTL = 0x00, + DMA_SOURCE_ADDR = 0x04, + DMA_DEST_ADDR = 0x06, + DMA_TRANSFER_COUNT = 0x08, + + TIMER0_GLOBAL_CTL = 0x20, + TIMER0_COUNTER = 0x24, + TIMER0_PERIOD = 0x28, + + TIMER1_GLOBAL_CTL = 0x30, + TIMER1_COUNTER = 0x34, + TIMER1_PERIOD = 0x38, + + SPORT_GLOBAL_CTL = 0x40, + SPORT_TX_CTL = 0x42, + SPORT_RX_CTL = 0x43, + SPORT_TIMER_CTL = 0x44, + SPORT_TIMER_COUNTER = 0x45, + SPORT_TIMER_PERIOD = 0x46, + SPORT_DATA_TX = 0x48, + SPORT_DATA_RX = 0x4c, + }; + + enum irq_status + { + IRQ_RTC = 1, + IRQ_UART = 2, + IRQ_DSP = 4, + IRQ_VBLANK = 5, + IRQ_SCSI = 7, + }; + + required_device m_maincpu; + required_device m_dsp; + required_shared_ptr m_dram; + required_device m_dac_l; + required_device m_dac_r; + required_device m_tms_timer1; + required_device m_tms_tx_timer; + + DECLARE_WRITE32_MEMBER(cyrix_cache_w); + DECLARE_READ8_MEMBER(nvram_r); + DECLARE_WRITE8_MEMBER(nvram_w); + DECLARE_WRITE32_MEMBER(port1_w); + DECLARE_WRITE32_MEMBER(port2_w); + DECLARE_WRITE32_MEMBER(port3_w); + DECLARE_WRITE32_MEMBER(dpylist_w); + DECLARE_READ32_MEMBER(tms32031_control_r); + DECLARE_WRITE32_MEMBER(tms32031_control_w); + DECLARE_WRITE32_MEMBER(dsp_unk_w); + DECLARE_WRITE32_MEMBER(dsp_ctrl_w); + DECLARE_WRITE32_MEMBER(dsp_486_int_w); + DECLARE_READ32_MEMBER(dsp_speedup_r); + DECLARE_WRITE32_MEMBER(dsp_speedup_w); + DECLARE_WRITE_LINE_MEMBER(scsi_irq); + + TIMER_DEVICE_CALLBACK_MEMBER(tms_timer1); + TIMER_DEVICE_CALLBACK_MEMBER(tms_tx_timer); + INTERRUPT_GEN_MEMBER(vblank_irq); + + UINT8 *m_nvram8; + UINT8 m_io_reg; + UINT8 m_irq_status; + UINT32 m_dpyaddr; + UINT16 *m_palette; + UINT32 m_speedup_count; + UINT32 m_tms_io_regs[0x80]; + + UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void update_irq(UINT32 which, UINT32 state); + void upload_palette(UINT32 word1, UINT32 word2); + +protected: + // driver_device overrides + virtual void machine_reset(); + virtual void machine_start(); + virtual void video_start(); +}; + + + +/************************************* + * + * Initialisation + * + *************************************/ + +void rastersp_state::machine_start() +{ + machine().device("maincpu")->execute().set_irq_acknowledge_callback(irq_callback); + + m_nvram8 = auto_alloc_array(machine(), UINT8, NVRAM_SIZE); + + m_palette = auto_alloc_array(machine(), UINT16, 0x8000); + + machine().root_device().membank("bank1")->set_base(m_dram); + machine().root_device().membank("bank2")->set_base(&m_dram[0x10000/4]); + machine().root_device().membank("bank3")->set_base(&m_dram[0x300000/4]); + +#if USE_SPEEDUP_HACK + machine().device("dsp")->memory().space(AS_PROGRAM).install_read_handler(0x809923, 0x809923, read32_delegate(FUNC(rastersp_state::dsp_speedup_r), this)); + machine().device("dsp")->memory().space(AS_PROGRAM).install_write_handler(0x809923, 0x809923, write32_delegate(FUNC(rastersp_state::dsp_speedup_w), this)); +#endif +} + + +void rastersp_state::machine_reset() +{ + m_irq_status = 0; + m_dpyaddr = 0; + + // Halt the 486 on reset - the DSP will release it from reset + m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + + // Set IRQ1 line to cause DSP to boot from 0x400000 + m_dsp->set_input_line(TMS3203X_IRQ1, ASSERT_LINE); + m_dsp->set_input_line(TMS3203X_IRQ1, CLEAR_LINE); + + // Reset DSP internal registers + m_tms_io_regs[SPORT_GLOBAL_CTL] = 0; +} + + + +/************************************* + * + * Video hardware + * + *************************************/ + +void rastersp_state::video_start() +{ + +} + + +WRITE32_MEMBER( rastersp_state::dpylist_w ) +{ + m_dpyaddr = data; + +} + + +void rastersp_state::upload_palette(UINT32 word1, UINT32 word2) +{ + if (word1 & 3) + fatalerror("Unalligned palette address! (%x, %x)\n", word1, word2); + + UINT32 addr = word1 >> 8; + UINT32 entries = (word2 >> 16) & 0x1ff; + UINT32 index = ((word2 >> 12) & 0x1f) * 256; + + // The third byte of each entry in RAM appears to contain an index + // but appears to be discared when written to palette RAM + while (entries--) + { + UINT32 data = m_dram[addr / 4]; + m_palette[index++] = data & 0xffff; + addr += 4; + } +} + + +/******************************************************************************* + + Display list register: + + ..xxxxxx xxxxxxxx xxxxxxxx ........ Display list base (DWORD granularity) + ........ ........ ........ xxxxxxxx ? (number of entries? Only seems to be valid for basic stuff) + + Display list format: + +[0] ..xxxxxx xxxxxxxx xxxxxxxx ........ Source address (4MB mask?) + +Palette update: (8d000400) +[1] 1....... ........ ........ ........ ? + ...0.... ........ ........ ........ 0 for palette upload? + ....11.. ........ ........ ........ ? + .......x xxxxxxxx ........ ........ Entry count + ........ ........ .....1.. ........ ? (Usually 1) + +Pixel data: (94040100) +[2] 1....... ........ ........ ........ ? + ...1.... ........ ........ ........ 1 for video update? + .....1.. ........ ........ ........ ? + .......x xxxxxxxx ........ ........ Pixel count + ........ ........ xxxx.... ........ Palette + ........ ........ ....xxxx xxxxxxxx Scale (4.8 signed fixed point) + +Unknown: (D4000100) - Present at start of a list +[3] 1....... ........ ........ ......... + .1...... ........ ........ ......... ? + ..1..... ........ ........ ......... + .....1.. ........ ........ ......... ? + ........ ........ .......1 ......... ? + + + TODO: I'm not sure about bit 28. When creating the display list if it's 0, + 0x1000 is added to the source address. + +*******************************************************************************/ + +UINT32 rastersp_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + if (m_dpyaddr == 0) + { + bitmap.fill(get_black_pen(machine()), cliprect); + return 0; + } + + UINT32 dpladdr = (m_dpyaddr & ~0xff) >> 6; + + if ((m_dpyaddr & 0xff) != 0xb2 && (m_dpyaddr & 0xff) != 0xf2) + logerror("Unusual display list data: %x\n", m_dpyaddr); + + int y = cliprect.min_y; + int x = cliprect.min_x; + UINT16 *bmpptr = &bitmap.pix16(cliprect.min_y, cliprect.min_x); + + while (y <= cliprect.max_y) + { + UINT32 word1 = m_dram[dpladdr/4]; + + if (word1 & 0x80000000) + { + // TODO: What does this signify? + dpladdr += 4; + } + else + { + UINT32 word2 = m_dram[(dpladdr + 4)/4]; + + dpladdr += 8; + + if (word2 & 0x10000000) + { + if ((word2 & 0xfe000000) != 0x94000000) + logerror("Unusual display list entry: %x %x\n", word1, word2); + + UINT32 srcaddr = word1 >> 8; + UINT32 pixels = (word2 >> 16) & 0x1ff; + UINT32 palbase = (word2 >> 4) & 0xf00; + + UINT16* palptr = &m_palette[palbase]; + UINT8* srcptr = reinterpret_cast(&m_dram[0]); + + UINT32 acc = srcaddr << 8; + + INT32 incr = word2 & 0xfff; + + // Sign extend for our convenience + incr |= ~((incr & 0x800) - 1) & ~0xff; + + // TODO: Assumes 8-bit palettized mode - the hardware also supports 16-bit direct + while (y <= cliprect.max_y && pixels) + { + while (x <= cliprect.max_x && pixels) + { + *bmpptr++ = palptr[srcptr[BYTE_XOR_LE(acc >> 8)]]; + acc = (acc + incr) & VIDEO_ADDR_MASK; + + --pixels; + ++x; + } + + // Advance to the next scanline + if (x > cliprect.max_x) + { + x = cliprect.min_x; + ++y; + } + } + } + else + { + if ((word2 & 0x0c000000) != 0x0c000000) + logerror("Unknown palette upload: %.8x %.8x\n", word1, word2); + + upload_palette(word1, word2); + } + } + } + + return 0; +} + + + +/************************************* + * + * Interrupt handling + * + *************************************/ + +static IRQ_CALLBACK( irq_callback ) +{ + rastersp_state *state = device->machine().driver_data(); + + UINT8 vector = 0; + + if (state->m_irq_status & (1 << rastersp_state::IRQ_SCSI)) + { + vector = 11; + } + else if (state->m_irq_status & (1 << rastersp_state::IRQ_DSP)) + { + state->update_irq(rastersp_state::IRQ_DSP, CLEAR_LINE); + vector = 12; + } + else if (state->m_irq_status & (1 << rastersp_state::IRQ_VBLANK)) + { + state->update_irq(rastersp_state::IRQ_VBLANK, CLEAR_LINE); + vector = 13; + } + else + { + fatalerror("Unknown x86 IRQ (m_irq_status = %x)", state->m_irq_status); + } + + return vector; +} + + +void rastersp_state::update_irq(UINT32 which, UINT32 state) +{ + UINT32 mask = 1 << which; + + if (state) + m_irq_status |= mask; + else + m_irq_status &= ~mask; + + m_maincpu->set_input_line(0, m_irq_status ? HOLD_LINE : CLEAR_LINE); +} + + +WRITE_LINE_MEMBER( rastersp_state::scsi_irq ) +{ + update_irq(IRQ_SCSI, state); +} + + +INTERRUPT_GEN_MEMBER( rastersp_state::vblank_irq ) +{ + update_irq(IRQ_VBLANK, ASSERT_LINE); +} + + + +/************************************* + * + * 486 I/O + * + *************************************/ + +WRITE32_MEMBER( rastersp_state::port1_w ) +{ + // x... .... - LED? + // ..x. .... - DSP IRQ2 line + // .... ..xx - LEDs? + + if (data & 0x20) + { + m_dsp->set_input_line(TMS3203X_IRQ2, ASSERT_LINE); + m_dsp->set_input_line(TMS3203X_IRQ2, CLEAR_LINE); + } +} + + +WRITE32_MEMBER( rastersp_state::port2_w ) +{ + // .x.. .... - X9313WP /INC + // ..x. .... - X9313WP U/#D +} + + +WRITE32_MEMBER( rastersp_state:: port3_w ) +{ + // xxxx xxxx - 8 LED cluster? +} + + + +/************************************* + * + * NVRAM + * + *************************************/ + +static NVRAM_HANDLER( rastersp ) +{ + rastersp_state *state = machine.driver_data(); + + if (read_or_write) + { + file->write(state->m_nvram8, NVRAM_SIZE); + } + else if (file) + { + file->read(state->m_nvram8, NVRAM_SIZE); + } + else + { + memcpy(state->m_nvram8, machine.root_device().memregion("nvram")->base(), NVRAM_SIZE); + } +} + + +WRITE8_MEMBER( rastersp_state::nvram_w ) +{ + offset *= 4; + + if ((offset & 0xc000) || !(offset & 0x2000)) + { + logerror("Unmapped NVRAM write to offset: %x", offset); + } + + offset &= ~0x2000; + + UINT32 addr = ((offset & 0x00f0000) >> 5) | ((offset & 0x1fff) / 4); + + m_nvram8[addr] = data & 0xff; +} + + +READ8_MEMBER( rastersp_state::nvram_r ) +{ + offset *= 4; + + if ((offset & 0xc000) || !(offset & 0x2000)) + { + logerror("Unmapped NVRAM read from offset: %x", offset); + } + + offset &= ~0x2000; + + UINT32 addr = ((offset & 0x00f0000) >> 5) | ((offset & 0x1fff) / 4); + + return m_nvram8[addr]; +} + + +WRITE32_MEMBER( rastersp_state::cyrix_cache_w ) +{ + // TODO? +} + + + +/************************************* + * + * DSP + * + *************************************/ + +TIMER_DEVICE_CALLBACK_MEMBER( rastersp_state::tms_tx_timer ) +{ + // Is the transmit shifter full? + if (m_tms_io_regs[SPORT_GLOBAL_CTL] & (1 << 3)) + { + UINT32 data = m_tms_io_regs[SPORT_DATA_TX]; + + INT16 ldata = data & 0xffff; + INT16 rdata = data >> 16; + + m_dac_l->write_signed16(0x8000 + ldata); + m_dac_r->write_signed16(0x8000 + rdata); + } + + // Set XSREMPTY + m_tms_io_regs[SPORT_GLOBAL_CTL] &= ~(1 << 3); + + // Set XRDY + m_tms_io_regs[SPORT_GLOBAL_CTL] |= (1 << 1); + + // Signal a transmit interrupt + if (m_tms_io_regs[SPORT_GLOBAL_CTL] & (1 << 23)) + { + m_dsp->set_input_line(TMS3203X_XINT0, ASSERT_LINE); + m_dsp->set_input_line(TMS3203X_XINT0, CLEAR_LINE); + } +} + + +TIMER_DEVICE_CALLBACK_MEMBER( rastersp_state::tms_timer1 ) +{ + +} + + +READ32_MEMBER( rastersp_state::tms32031_control_r ) +{ + UINT32 val = m_tms_io_regs[offset]; + + switch (offset) + { + case TIMER1_COUNTER: + { + attotime elapsed = m_tms_timer1->time_elapsed(); + val = m_tms_io_regs[TIMER1_PERIOD] - (elapsed.as_ticks(m_dsp->clock() / 2 / 2)); + + break; + } + default: + { + logerror("TMS32031: Unhandled I/O read: %x\n", offset); + } + } + + return val; +} + + +WRITE32_MEMBER( rastersp_state::tms32031_control_w ) +{ + UINT32 old = m_tms_io_regs[offset]; + + m_tms_io_regs[offset] = data; + + switch (offset) + { + case TIMER1_GLOBAL_CTL: + { + // Calculate the DSP clocks + attotime period = attotime::from_hz(m_dsp->clock() / 2 / 2); + + period *= m_tms_io_regs[TIMER1_PERIOD]; + + m_tms_timer1->adjust(period, 0, period); + + break; + } + case SPORT_GLOBAL_CTL: + { + if (!(data & (1 << 26))) + { + // Reset transmitter + m_tms_tx_timer->adjust(attotime::never); + } + else if (!(old & (1 << 26)) && (data & (1 << 26))) + { + // Sample rate is 24KHz + attotime period = attotime::from_hz(SOUND_CLOCK / 512); + + // Set XRDY + m_tms_io_regs[SPORT_GLOBAL_CTL] |= (1 << 1); + + // Set XSREMPTY + m_tms_io_regs[SPORT_GLOBAL_CTL] &= ~(1 << 3); + + // Run transmitter + m_tms_tx_timer->adjust(period, 0, period); + } + + break; + } + case SPORT_DATA_TX: + { + // Clear XRDY + m_tms_io_regs[SPORT_GLOBAL_CTL] &= ~(1 << 1); + + // Clear XSREMPTY + m_tms_io_regs[SPORT_GLOBAL_CTL] |= (1 << 3); + + break; + } + default: + { + logerror("TMS32031: Unhandled I/O write: %x %x\n", offset, data); + } + } +} + + +WRITE32_MEMBER( rastersp_state::dsp_unk_w ) +{ + // TODO: Looks like a debug port? +} + + +WRITE32_MEMBER( rastersp_state::dsp_486_int_w ) +{ + + update_irq(IRQ_DSP, ASSERT_LINE); +} + + +WRITE32_MEMBER( rastersp_state::dsp_ctrl_w ) +{ + // x... .... LED? + // .xx. .... 486 reset control? + + m_maincpu->set_input_line(INPUT_LINE_RESET, (data & 0x60) == 0x60 ? CLEAR_LINE : ASSERT_LINE); +} + + +WRITE32_MEMBER( rastersp_state::dsp_speedup_w ) +{ + // 809e90 48fd, 48d5 + if (space.device().safe_pc() == 0x809c23) + { + INT32 cycles_left = space.device().execute().cycles_remaining(); + data += cycles_left / 6; + space.device().execute().spin(); + } + + m_speedup_count = data; +} + + +READ32_MEMBER( rastersp_state::dsp_speedup_r ) +{ + return m_speedup_count; +} + + +/************************************* + * + * Memory maps + * + *************************************/ + +static ADDRESS_MAP_START( cpu_map, AS_PROGRAM, 32, rastersp_state ) + AM_RANGE(0x00000000, 0x003fffff) AM_RAM AM_SHARE("dram") + AM_RANGE(0x01000000, 0x010bffff) AM_NOP // External ROM + AM_RANGE(0x010c0000, 0x010cffff) AM_ROM AM_REGION("bios", 0) + AM_RANGE(0x02200800, 0x02200803) AM_WRITENOP // ? + AM_RANGE(0x02208000, 0x02208fff) AM_DEVREADWRITE("scsibus:7:ncr53c700", ncr53c7xx_device, read, write) + AM_RANGE(0x0220e000, 0x0220e003) AM_WRITE(dpylist_w) + AM_RANGE(0x02200000, 0x022fffff) AM_READWRITE8(nvram_r, nvram_w, 0x000000ff) + AM_RANGE(0xfff00000, 0xffffffff) AM_RAMBANK("bank3") +ADDRESS_MAP_END + +static ADDRESS_MAP_START( io_map, AS_IO, 32, rastersp_state ) + AM_RANGE(0x0020, 0x0023) AM_WRITE(cyrix_cache_w) + AM_RANGE(0x1000, 0x1003) AM_READ_PORT("P1") AM_WRITE(port1_w) + AM_RANGE(0x1004, 0x1007) AM_READ_PORT("P2") AM_WRITE(port2_w) + AM_RANGE(0x1008, 0x100b) AM_READ_PORT("COMMON") AM_WRITE(port3_w) + AM_RANGE(0x100c, 0x100f) AM_READ_PORT("DSW2") + AM_RANGE(0x1010, 0x1013) AM_READ_PORT("DSW1") + AM_RANGE(0x1014, 0x1017) AM_READ_PORT("EXTRA") + AM_RANGE(0x4000, 0x4007) AM_DEVREADWRITE8("rtc", mc146818_device, read, write, 0x000000ff) + AM_RANGE(0x6008, 0x600b) AM_READNOP AM_WRITENOP // RS232 +ADDRESS_MAP_END + + +static ADDRESS_MAP_START( dsp_map, AS_PROGRAM, 32, rastersp_state ) + AM_RANGE(0x000000, 0x0fffff) AM_RAMBANK("bank1") + AM_RANGE(0x400000, 0x40ffff) AM_ROM AM_REGION("dspboot", 0) + AM_RANGE(0x808000, 0x80807f) AM_READWRITE(tms32031_control_r, tms32031_control_w) + AM_RANGE(0x880402, 0x880402) AM_WRITE(dsp_unk_w) + AM_RANGE(0x883c00, 0x883c00) AM_WRITE(dsp_486_int_w) + AM_RANGE(0xc00000, 0xc03fff) AM_RAMBANK("bank2") + AM_RANGE(0xc80000, 0xc80000) AM_WRITE(dsp_ctrl_w) + AM_RANGE(0xfc0000, 0xffffff) AM_RAMBANK("bank3") +ADDRESS_MAP_END + + + +/************************************* + * + * Inputs + * + *************************************/ + +static INPUT_PORTS_START( rotr ) + PORT_START("P1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) + + PORT_START("P2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) + + PORT_START("COMMON") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START2 ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_TILT ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("EXTRA") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(1) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(2) + + PORT_START("DSW1") + PORT_DIPNAME( 0x01, 0x01, "Setup Disk" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) + + PORT_DIPNAME( 0x02, 0x00, DEF_STR( Service_Mode ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + + PORT_DIPNAME( 0x3c, 0x00, "Load PROG" ) + PORT_DIPSETTING( 0x00, "0" ) + PORT_DIPSETTING( 0x04, "1" ) + PORT_DIPSETTING( 0x08, "2" ) + PORT_DIPSETTING( 0x0c, "3" ) + PORT_DIPSETTING( 0x10, "4" ) + PORT_DIPSETTING( 0x14, "5" ) + PORT_DIPSETTING( 0x18, "6" ) + PORT_DIPSETTING( 0x1c, "7" ) + PORT_DIPSETTING( 0x20, "8" ) + PORT_DIPSETTING( 0x24, "9" ) + PORT_DIPSETTING( 0x28, "A" ) + PORT_DIPSETTING( 0x2c, "B" ) + PORT_DIPSETTING( 0x30, "C" ) + PORT_DIPSETTING( 0x34, "D" ) + PORT_DIPSETTING( 0x38, "E" ) + PORT_DIPSETTING( 0x3c, "F" ) + + PORT_DIPNAME( 0x40, 0x00, "Reserved" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x40, DEF_STR( On ) ) + + PORT_DIPNAME( 0x80, 0x00, "Enable Cache" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) + + PORT_START("DSW2") + PORT_DIPNAME( 0x01, 0x00, "Debug Screen" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) + + PORT_DIPNAME( 0x0e, 0x00, "FPGA File Source" ) + PORT_DIPSETTING( 0x00, "Serial PROMs" ) + PORT_DIPSETTING( 0x0e, "Cable" ) + + PORT_DIPNAME( 0x70, 0x50, "Clock speed" ) + PORT_DIPSETTING( 0x00, "4" ) + PORT_DIPSETTING( 0x10, "8" ) + PORT_DIPSETTING( 0x20, "16" ) + PORT_DIPSETTING( 0x30, "20" ) + PORT_DIPSETTING( 0x40, "25" ) + PORT_DIPSETTING( 0x50, "33" ) + PORT_DIPSETTING( 0x60, "40" ) + PORT_DIPSETTING( 0x70, "50" ) + + PORT_DIPNAME( 0x80, 0x00, "SCSI bus terminated" ) + PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) + PORT_DIPSETTING( 0x80, DEF_STR( No ) ) +INPUT_PORTS_END + + + +/************************************* + * + * SCSI + * + *************************************/ + +static UINT32 ncr53c700_r(running_machine &machine, bool io, offs_t addr) +{ + return machine.device("maincpu")->memory().space(io ? AS_IO : AS_PROGRAM).read_dword(addr); +} + +static void ncr53c700_w(running_machine &machine, bool io, offs_t addr, UINT32 data, UINT32 mem_mask) +{ + machine.device("maincpu")->memory().space(io ? AS_IO : AS_PROGRAM).write_dword(addr, data, mem_mask); +} + +static const struct NCR53C7XXinterface ncr53c700_intf = +{ + DEVCB_DRIVER_LINE_MEMBER(rastersp_state, scsi_irq), + &ncr53c700_r, + &ncr53c700_w, +}; + +static SLOT_INTERFACE_START( rastersp_scsi_devices ) + SLOT_INTERFACE("harddisk", NSCSI_HARDDISK) + SLOT_INTERFACE_INTERNAL("ncr53c700", NCR53C7XX) +SLOT_INTERFACE_END + + + +/************************************* + * + * TMS32031 + * + *************************************/ + +static const tms3203x_config tms_config = +{ + true // Boot-loader mode +}; + + + +/************************************* + * + * Machine driver + * + *************************************/ + +static MACHINE_CONFIG_START( rastersp, rastersp_state ) + MCFG_CPU_ADD("maincpu", I486, 33330000) + MCFG_CPU_PROGRAM_MAP(cpu_map) + MCFG_CPU_IO_MAP(io_map) + MCFG_CPU_VBLANK_INT_DRIVER("screen", rastersp_state, vblank_irq) + + MCFG_CPU_ADD("dsp", TMS32031, 33330000) + MCFG_TMS3203X_CONFIG(tms_config) + MCFG_CPU_PROGRAM_MAP(dsp_map) + + /* Devices */ + MCFG_TIMER_DRIVER_ADD("tms_timer1", rastersp_state, tms_timer1) + MCFG_TIMER_DRIVER_ADD("tms_tx_timer", rastersp_state, tms_tx_timer) + MCFG_MC146818_ADD("rtc", MC146818_STANDARD) + MCFG_NVRAM_HANDLER(rastersp) + + MCFG_NSCSI_BUS_ADD("scsibus") + MCFG_NSCSI_ADD("scsibus:0", rastersp_scsi_devices, "harddisk", 0, 0, 0, true) + MCFG_NSCSI_ADD("scsibus:7", rastersp_scsi_devices, "ncr53c700", 0, &ncr53c700_intf, 66000000, true) + + /* Video */ + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_SIZE(320, 240) + MCFG_SCREEN_VISIBLE_AREA(0, 320-1, 0, 240-1) + MCFG_SCREEN_UPDATE_DRIVER(rastersp_state, screen_update) + MCFG_SCREEN_REFRESH_RATE(50) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ + + MCFG_PALETTE_INIT(RRRRR_GGGGGG_BBBBB) + MCFG_PALETTE_LENGTH(65536) + + /* Sound */ + MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") + + MCFG_DAC_ADD("dac_l") + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0) + MCFG_DAC_ADD("dac_r") + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0) +MACHINE_CONFIG_END + + + +/************************************* + * + * ROM definitions + * + *************************************/ + +ROM_START( rotr ) + ROM_REGION(0x100000, "bios", 0) + ROM_LOAD( "rasterspeed2.1_bootrom4.u10", 0x00000, 0x10000, CRC(6da142d1) SHA1(e2dbd479034677726fc26fd1ba85c4458d89286c) ) + + ROM_REGION(0x1000000, "dspboot", 0) + ROM_LOAD32_BYTE( "rasterspeed2.1_bootrom4.u10", 0x00000, 0x10000, CRC(6da142d1) SHA1(e2dbd479034677726fc26fd1ba85c4458d89286c) ) + + ROM_REGION(0x8000, "proms", 0) /* Xilinx FPGA PROMs */ + ROM_LOAD( "17128dpc.u72", 0x0000, 0x4000, CRC(5ddf6ee3) SHA1(f3d15b649b5641374a9e14877cea84ba9c57ef3c) ) + ROM_LOAD( "17128dpc.u73", 0x2000, 0x4000, CRC(9e274cea) SHA1(e974cad4e4b965bf2c9df7d3d0b4eec64629eeb0) ) + + ROM_REGION(0x8000, "nvram", 0) /* Default NVRAM */ + ROM_LOAD( "rotr.nv", 0x0000, 0x8000, CRC(62543517) SHA1(a4bf3431cdab956839bb155c4a8c140d30e5c7ec) ) + + DISK_REGION( "scsibus:0:harddisk" ) + DISK_IMAGE( "rotr", 0, SHA1(d67d7feb52d8c7ba1d2a190a40d97e84871f2d80) ) +ROM_END + + + +/************************************* + * + * Game drivers + * + *************************************/ + +GAME( 1994, rotr, 0, rastersp, rotr, driver_device, 0, ROT0, "BFM/Mirage", "Rise of the Robots (prototype)", 0 ) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 46d3ef23601..8d2754cf6ed 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -13491,6 +13491,9 @@ sc1goldw sc1druby sc1drubya +// RasterSpeed +rotr // 1994 + // Scorpion 2 / 3 sc2brkfs // The Big Breakfast diff --git a/src/mame/mame.mak b/src/mame/mame.mak index 7f6c38a8e31..34df416182e 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -550,6 +550,7 @@ $(MAMEOBJ)/bfm.a: \ $(DRIVERS)/bfmsys85.o \ $(MACHINE)/sec.o \ $(MACHINE)/bfm_bd1.o $(MACHINE)/bfm_bda.o $(VIDEO)/bfm_dm01.o \ + $(DRIVERS)/rastersp.o \ $(MAMEOBJ)/bmc.a: \ $(DRIVERS)/bmcbowl.o \