From 0658d35ee84c5cc7520f85951a9aae798e105580 Mon Sep 17 00:00:00 2001 From: Mirko Date: Thu, 11 Jun 2020 15:57:55 +0200 Subject: new machines marked as working ----------------------------- Super Motor (prototype) [Mirko Buffoni, Roberto Fresca, Retromaniacs, recreativas.org] --- src/mame/drivers/smotor.cpp | 478 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 478 insertions(+) create mode 100644 src/mame/drivers/smotor.cpp diff --git a/src/mame/drivers/smotor.cpp b/src/mame/drivers/smotor.cpp new file mode 100644 index 00000000000..a6f30360666 --- /dev/null +++ b/src/mame/drivers/smotor.cpp @@ -0,0 +1,478 @@ +// license:BSD-3-Clause +// copyright-holders: Roberto Fresca, Mirko Buffoni +/******************************************************************** + + Super Motor (prototype) + 19??, Duintronic. + + Driver by Roberto Fresca and Mirko Buffoni. + + +********************************************************************* + + Seems to be a prototype, since there are some issues. + You can choose motorcycle <-> car game throug a DIP switch. + + Also there are four difficult modes: + + - Easy: You only have slow trucks in the game, and gas cans on + the road that extend 10 seconds the game time. + + - Normal: You have trucks and cars on the street. Also gas cans. + + - Medium: You have trucks and cars on the street, but no gas cans. + Trucks and cars can stop. + + - Hard: You have trucks and cars on the street, but no gas cans. + Trucks and cars can stop. Seems a bit harder. + + Maybe the easy option was meant for kids cabs. + + + Duintronic, the manufacturer, is a Spanish company from Barcelona, + created by someone from Ampetronic, and finally adquired by one of + the Tecfri CEOs. The only arcade game known released by them was + Buccanneers, running in IREM Vigilante hardware. + + +********************************************************************* + + Hardware specs... + + It's a dedicated PCB that has etched the Duintronic logo. + + + 1x Z80 @ 5MHz. (stickered: S.P.V. -BR BRI NC) + 1x YM2413 @ 2.5 MHz. + + 1x NEC D446C-2, 2K x 8 SRAM. (near CPU) + 1x NEC D4016C–2 SRAM 32K x 8 SRAM. (VRAM?) + + 4x 27C512 ROM. + 3x N82S129N bipolar PROMs. + + 1x LM324N low-power quad op amp. (audio amp) + + 3x GAL16V8-20. (marked 1, 2, 3) + + 1x 5.000 MHz. crystal. + 1x 20.00 MHz. crystal. + + 2x 8 DIP switches banks. + + 1x (2x28) JAMMA edge connector. + + +*********************************************************************/ + + +#include "emu.h" +#include "cpu/z80/z80.h" +#include "video/resnet.h" +#include "sound/ym2413.h" +#include "emupal.h" +#include "screen.h" +#include "speaker.h" +#include "tilemap.h" + +#define FIRST_CLOCK XTAL(5'000'000) +#define SECOND_CLOCK XTAL(20'000'000) +#define CPU_CLOCK (FIRST_CLOCK) // verified 5 MHz. +#define SND_CLOCK (SECOND_CLOCK / 8) // verified 2.5 MHz. + + +class smotor_state : public driver_device +{ +public: + smotor_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_ym2413(*this, "ymsnd"), + m_gfxdecode(*this, "gfxdecode"), + m_palette(*this, "palette"), + m_videoreg(*this, "videoreg"), + m_videoram(*this, "videoram") + { } + + void smotor(machine_config &config); + +private: + required_device m_maincpu; + required_device m_ym2413; + required_device m_gfxdecode; + required_device m_palette; + + required_shared_ptr m_videoreg; + required_shared_ptr m_videoram; + + tilemap_t *m_bg_tilemap; + tilemap_t *m_fg_tilemap; + + DECLARE_WRITE8_MEMBER(videoram_w); + DECLARE_WRITE8_MEMBER(cpu_io_videoreg_w); + + TILE_GET_INFO_MEMBER(get_fg_tile_info); + TILE_GET_INFO_MEMBER(get_bg_tile_info); + + virtual void machine_start() override; + virtual void video_start() override; + + void smotor_palette(palette_device &palette) const; + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void smotor_cpu_map(address_map &map); + void smotor_cpu_io(address_map &map); +}; + + +/********************************************* +* Video Hardware * +*********************************************/ + +WRITE8_MEMBER(smotor_state::videoram_w) +{ + m_videoram[offset] = data; + m_fg_tilemap->mark_tile_dirty(offset/2); +} + + +TILE_GET_INFO_MEMBER(smotor_state::get_fg_tile_info) +{ + tile_index *= 2; + + int attr = m_videoram[tile_index + 1]; + int code = m_videoram[tile_index] | ((attr & 0x0f) << 8); + int color = (attr) >> 4; + tileinfo.set(0, code, color, 0); +} + + +TILE_GET_INFO_MEMBER(smotor_state::get_bg_tile_info) +{ + uint8_t *tilerom = memregion("bgmap")->base(); + + tile_index *= 2; + + int data = tilerom[tile_index]; + int attr = tilerom[tile_index + 1]; + int code = (data | ((attr & 0x07) << 8)) + 0x800; + int color = attr >> 4; + + tileinfo.set(0, code, color, 0); +} + +void smotor_state::video_start() +{ + m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(smotor_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32); + m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(smotor_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 1024); + m_bg_tilemap->set_scroll_rows(32); + m_fg_tilemap->set_transparent_pen(0); +} + +uint32_t smotor_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + if (BIT(m_videoreg[0],0)) { + m_bg_tilemap->set_scrolly((m_videoreg[3] + (m_videoreg[5] << 8))); + m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); + } else { + bitmap.fill(rgb_t::black(), cliprect); + } + + m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0); + return 0; +} + +/*************************************************************************** + + Convert the color PROMs into a more useable format. + + There are three 256x4 palette PROMs (one per gun). + The palette PROMs are connected to the RGB output this way: + + bit 3 -- 220 ohm resistor -- RED/GREEN/BLUE + -- 680 ohm resistor -- RED/GREEN/BLUE + -- 1.0kohm resistor -- RED/GREEN/BLUE + bit 0 -- 2.2kohm resistor -- RED/GREEN/BLUE + +***************************************************************************/ + +void smotor_state::smotor_palette(palette_device &palette) const +{ + uint8_t const *const color_prom = memregion("proms")->base(); + static constexpr int resistances[4] = { 2200, 1000, 680, 220 }; + + // compute the color output resistor weights + double rweights[4], gweights[4], bweights[4]; + compute_resistor_weights(0, 255, -1.0, + 4, &resistances[0], rweights, 330, 0, + 4, &resistances[0], gweights, 330, 0, + 4, &resistances[0], bweights, 330, 0); + + // initialize the palette with these colors + for (int i = 0; i < palette.entries(); i++) + { + int bit0, bit1, bit2, bit3; + + // red component + bit0 = BIT(color_prom[i], 0); + bit1 = BIT(color_prom[i], 1); + bit2 = BIT(color_prom[i], 2); + bit3 = BIT(color_prom[i], 3); + int const r = combine_weights(rweights, bit0, bit1, bit2, bit3); + + // green component + bit0 = BIT(color_prom[i+0x100], 0); + bit1 = BIT(color_prom[i+0x100], 1); + bit2 = BIT(color_prom[i+0x100], 2); + bit3 = BIT(color_prom[i+0x100], 3); + int const g = combine_weights(gweights, bit0, bit1, bit2, bit3); + + // blue component + bit0 = BIT(color_prom[i+0x200], 0); + bit1 = BIT(color_prom[i+0x200], 1); + bit2 = BIT(color_prom[i+0x200], 2); + bit3 = BIT(color_prom[i+0x200], 3); + int const b = combine_weights(bweights, bit0, bit1, bit2, bit3); + + palette.set_pen_color(i, rgb_t(r, g, b)); + } +} + + +/********************************************* +* Memory Map Information * +*********************************************/ + +void smotor_state::smotor_cpu_map(address_map &map) +{ + map(0x0000, 0xbfff).rom(); + map(0xf000, 0xf7ff).ram().w(FUNC(smotor_state::videoram_w)).share("videoram"); + map(0xf800, 0xffff).ram(); +} + +void smotor_state::smotor_cpu_io(address_map &map) +{ + map.global_mask(0xff); + map(0x00, 0x00).portr("IN0"); + map(0x01, 0x01).portr("DSW1"); + + map(0x00, 0x01).w("ymsnd", FUNC(ym2413_device::write)); + + map(0x02, 0x02).portr("DSW2"); + + map(0x02, 0x07).w(FUNC(smotor_state::cpu_io_videoreg_w)).share("videoreg"); + +/* + 00: RW ; port_r / ym2413_w #1 + 01: RW ; dsw1_r / ym2413_w #2 + 02: RW ; dsw2_r / bg_enable_w, coin counters (values written: 0x30 [boot], 0x20 [attract], 0x11 [ingame]) + 04: W ; / ??? (values written: 0x00) + 05: W ; / LSB Scrolly + 06: W ; / BG offset reset (values written: 0xff) + 07: W ; / MSB Scrolly +*/ + +} + +WRITE8_MEMBER(smotor_state::cpu_io_videoreg_w) +{ + switch (offset) { + + case 0x00: + m_videoreg[offset] = data; + m_ym2413->set_output_gain(ALL_OUTPUTS, BIT(data, 4) ? 1.0f : 0.0f); + if ((BIT(data, 0)) & (BIT(data, 2))) // coin lock + coin a, used for init. + break; + machine().bookkeeping().coin_lockout_global_w(BIT(data, 0)); // coin lock. + machine().bookkeeping().coin_counter_w(1, BIT(data, 1)); // coin b counter. + machine().bookkeeping().coin_counter_w(0, BIT(data, 2)); // coin a counter. + break; + + case 0x02: + case 0x03: + m_videoreg[3] = data; + break; + case 0x04: + case 0x05: + m_videoreg[5] = data; + break; + default: + logerror("OUT[%02x] = %02X\n", offset + 2, data); + } +} + + +/********************************************* +* Input Ports * +*********************************************/ + +static INPUT_PORTS_START( smotor ) + PORT_START("IN0") + 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_JOYSTICK_LEFT ) PORT_2WAY + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_2WAY + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) + + PORT_START("DSW1") + PORT_DIPNAME( 0x0f, 0x0f, DEF_STR( Coin_A ) ) PORT_DIPLOCATION("SW1:1,2,3,4") + PORT_DIPSETTING( 0x0f, DEF_STR( 1C_1C ) ) + PORT_DIPSETTING( 0x0e, DEF_STR( 1C_2C ) ) + PORT_DIPSETTING( 0x0d, DEF_STR( 1C_3C ) ) + PORT_DIPSETTING( 0x0c, DEF_STR( 1C_4C ) ) + PORT_DIPSETTING( 0x0b, DEF_STR( 1C_5C ) ) + PORT_DIPSETTING( 0x0a, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0x09, DEF_STR( 2C_3C ) ) + PORT_DIPSETTING( 0x08, DEF_STR( 2C_5C ) ) + PORT_DIPSETTING( 0x07, DEF_STR( 3C_1C ) ) + PORT_DIPSETTING( 0x06, DEF_STR( 3C_2C ) ) + PORT_DIPSETTING( 0x05, DEF_STR( 3C_5C ) ) + PORT_DIPSETTING( 0x04, DEF_STR( 4C_1C ) ) + PORT_DIPSETTING( 0x03, DEF_STR( 4C_3C ) ) + PORT_DIPSETTING( 0x02, DEF_STR( 4C_5C ) ) + PORT_DIPSETTING( 0x01, DEF_STR( 5C_1C ) ) + PORT_DIPSETTING( 0x00, DEF_STR( 5C_2C ) ) + PORT_DIPNAME( 0xf0, 0xf0, DEF_STR( Coin_B ) ) PORT_DIPLOCATION("SW1:5,6,7,8") + PORT_DIPSETTING( 0xf0, DEF_STR( 1C_1C ) ) + PORT_DIPSETTING( 0xe0, DEF_STR( 1C_2C ) ) + PORT_DIPSETTING( 0xd0, DEF_STR( 1C_3C ) ) + PORT_DIPSETTING( 0xc0, DEF_STR( 1C_4C ) ) + PORT_DIPSETTING( 0xb0, DEF_STR( 1C_5C ) ) + PORT_DIPSETTING( 0xa0, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0x90, DEF_STR( 2C_3C ) ) + PORT_DIPSETTING( 0x80, DEF_STR( 2C_5C ) ) + PORT_DIPSETTING( 0x70, DEF_STR( 3C_1C ) ) + PORT_DIPSETTING( 0x60, DEF_STR( 3C_2C ) ) + PORT_DIPSETTING( 0x50, DEF_STR( 3C_5C ) ) + PORT_DIPSETTING( 0x40, DEF_STR( 4C_1C ) ) + PORT_DIPSETTING( 0x30, DEF_STR( 4C_3C ) ) + PORT_DIPSETTING( 0x20, DEF_STR( 4C_5C ) ) + PORT_DIPSETTING( 0x10, DEF_STR( 5C_1C ) ) + PORT_DIPSETTING( 0x00, DEF_STR( 5C_2C ) ) + + PORT_START("DSW2") + PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:1") + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x06, 0x04, DEF_STR( Difficult ) ) PORT_DIPLOCATION("SW2:2,3") + PORT_DIPSETTING( 0x06, "Easy (with gas cans, only trucks)" ) + PORT_DIPSETTING( 0x04, "Normal (with gas cans, trucks and cars)" ) + PORT_DIPSETTING( 0x02, "Medium (no gas cans, both trucks and cars)" ) + PORT_DIPSETTING( 0x00, "Hard (no gas cans, both trucks and cars)" ) + PORT_DIPNAME( 0x18, 0x18, DEF_STR( Game_Time ) ) PORT_DIPLOCATION("SW2:4,5") + PORT_DIPSETTING( 0x18, "1:00" ) + PORT_DIPSETTING( 0x10, "1:20" ) + PORT_DIPSETTING( 0x08, "1:40" ) + PORT_DIPSETTING( 0x00, "2:00" ) + PORT_DIPNAME( 0x20, 0x20, "Cycle / Car" ) PORT_DIPLOCATION("SW2:6") + PORT_DIPSETTING( 0x20, "Cycle" ) + PORT_DIPSETTING( 0x00, "Car" ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unused ) ) PORT_DIPLOCATION("SW2:7") + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unused ) ) PORT_DIPLOCATION("SW2:8") + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) +INPUT_PORTS_END + + +/********************************************* +* Graphics Layouts * +*********************************************/ + +static const gfx_layout tiles8x8_layout = +{ + 8, 8, + 0x1000, + 4, + { 0, 2, 4, 6 }, + { 1, 0, 9, 8, 17, 16, 25, 24 }, + { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 }, + 32 * 8 +}; + + +/************************************************** +* Graphics Decode Information * +**************************************************/ + +static GFXDECODE_START( gfx_smotor ) + GFXDECODE_ENTRY( "gfx1", 0, tiles8x8_layout, 0, 16 ) +GFXDECODE_END + + + +/********************************************* +* Machine Start & Reset * +*********************************************/ + +void smotor_state::machine_start() +{ +} + + +/********************************************* +* Machine Config * +*********************************************/ + +void smotor_state::smotor(machine_config &config) +{ + // basic machine hardware + Z80(config, m_maincpu, CPU_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &smotor_state::smotor_cpu_map); + m_maincpu->set_addrmap(AS_IO, &smotor_state::smotor_cpu_io); + m_maincpu->set_vblank_int("screen", FUNC(smotor_state::irq0_line_hold)); + + // video hardware + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); + screen.set_refresh_hz(60); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); + screen.set_size(256, 256); + screen.set_visarea(0*8, 32*8-1, 0*8, 32*8-1); + screen.set_screen_update(FUNC(smotor_state::screen_update)); + screen.set_palette(m_palette); + + GFXDECODE(config, m_gfxdecode, m_palette, gfx_smotor); + PALETTE(config, m_palette, FUNC(smotor_state::smotor_palette), 256); // 256 static colors + + // sound hardware + SPEAKER(config, "speaker").front_center(); + YM2413(config, "ymsnd", SND_CLOCK).add_route(ALL_OUTPUTS, "speaker", 2.0); +} + + +/********************************************* +* ROM Load * +*********************************************/ + +ROM_START( smotor ) + ROM_REGION( 0x10000, "maincpu", 0 ) + ROM_LOAD( "2_27c512.d4", 0x00000, 0x10000, CRC(82ca877d) SHA1(fc11c793c25865ebd3d5199c61ce14c535e0d2a8) ) + + ROM_REGION( 0x20000, "gfx1", 0 ) + ROM_LOAD( "1_27c512.a2", 0x00000, 0x10000, CRC(f12cb8bb) SHA1(0aaa7040b3bdba01e823212550cc0f990eee02e8) ) + ROM_LOAD( "4_27c512.i1", 0x10000, 0x10000, CRC(4c82a10b) SHA1(215354f37f6c13378aca85c96c209610f774711a) ) + + ROM_REGION( 0x10000, "bgmap", 0 ) + ROM_LOAD( "3_27c512.g3", 0x00000, 0x10000, CRC(0f67d74b) SHA1(90bb8884f95c883fa3d95e97fba2c0420668dab3) ) + + ROM_REGION( 0x300, "proms", 0 ) + ROM_LOAD( "82s129.l4", 0x000, 0x100, CRC(cd06515a) SHA1(589961f0438b889d20223d8139992dc8bf35b935) ) // R + ROM_LOAD( "82s129.j4", 0x100, 0x100, CRC(26472e34) SHA1(c08f61911135cf1fe847a109f25de7f32646f5ec) ) // G + ROM_LOAD( "82s129.k4", 0x200, 0x100, CRC(b4cffc3b) SHA1(1536ea938f1dc8e506ad98ae6810279e83fe9192) ) // B + + ROM_REGION( 0x0600, "plds", 0 ) + ROM_LOAD( "1_gal16v8.a3", 0x0000, 0x0117, NO_DUMP ) // device is dead + ROM_LOAD( "2_gal16v8.k3", 0x0000, 0x0117, NO_DUMP ) // device is dead + ROM_LOAD( "3_gal16v8.l2", 0x0000, 0x0117, NO_DUMP ) // device is dead +ROM_END + + +/********************************************* +* Game Drivers * +*********************************************/ + +// YEAR NAME PARENT MACHINE INPUT CLASS INIT ROT COMPANY FULLNAME FLAGS +GAME( 19??, smotor, 0, smotor, smotor, smotor_state, empty_init, ROT0, "Duintronic", "Super Motor (prototype)", 0 ) -- cgit v1.2.3