summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/8080bw.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/8080bw.cpp')
-rw-r--r--src/mame/drivers/8080bw.cpp434
1 files changed, 434 insertions, 0 deletions
diff --git a/src/mame/drivers/8080bw.cpp b/src/mame/drivers/8080bw.cpp
index 73d06ff1c8f..94271d0c5f7 100644
--- a/src/mame/drivers/8080bw.cpp
+++ b/src/mame/drivers/8080bw.cpp
@@ -3560,6 +3560,423 @@ void _8080bw_state::init_invmulti()
+/*******************************************************/
+/* */
+/* Cane (Model Racing) */
+/* */
+/*******************************************************/
+/***********************************************************************************************************************************
+ This game was never released by Model Racing to the public.
+
+ The assembler source files for this game where extracted from the original floppy disks used by the former Model Racing developer
+ Adolfo Melilli (adolfo@melilli.com).
+ Those disks where retrieved by Alessandro Bolgia (xadhoom76@gmail.com) and Lorenzo Fongaro (lorenzo.fongaro@virgilio.it) and
+ dumped by Piero Andreini (pieroandreini@gmail.com) using KryoFlux hardware and software.
+ Subsequently Jean Paul Piccato (j2pguard-spam@yahoo.com) mounted the images and compiled the source files, managed to set up a
+ romset and wrote a mame driver that aims to reproduce in the most faithful way the work of Melilli at Model Racing in late '70s.
+
+ The game driver is not based on hardware inspection and is solely derived from assumptions I've made looking at the assembler
+ code and comments written into the source files of the game. Several of those hypothesis came following the directions of
+ previous yet contemporary Model Racing works (Eg: Claybuster) and where confirmed by Melilli himself.
+
+ Being unreleased this games has not an official name, thus the name used in the source files was used instead.
+
+***********************************************************************************************************************************/
+void cane_state::machine_start()
+{
+ mw8080bw_state::machine_start();
+}
+
+void cane_state::cane_map(address_map &map)
+{
+ map(0x0000, 0x1fff).rom().nopw();
+ map(0x2000, 0x3fff).ram().share("main_ram");
+}
+
+void cane_state::cane_io_map(address_map &map)
+{
+/*********************************************************************************************************************************
+ -----------
+ I/O mapping
+ -----------
+ out:
+ $00 - Unknown - Not yet emulated
+ $01 - Hardware shift register - Shift count
+ $02 - Hardware shift register - Shift data
+ $03 - Audio sub-system - D0->sx0, D1->sx1, D2->sx2, D3->sx3, D4->sx4, D5-D7 unused
+ sx0 mute/unmute all
+ sx1,sx2,sx3 routed to 76477 mixer select
+ sx4 routed to 555 one-shot trigger
+ $04 - Reset watchdog timer
+ $05 - Audio TOS
+
+ in:
+ $01 - CPO / coin input port
+ $03 - Hardware shift register - Shift result
+
+=================================================================================================================
+------------
+-- OUT 0 --
+Source file: CANE1.ED - Referred only once in code, in the "rifle routine" (ROUTINE FUCILE)
+
+ > ;ROUTINE FUCILE
+ > CALL SPARO
+ > OUT 0
+
+------------
+-- OUT 1 --
+Source files: CANE2.ED, MIRINO.ED
+
+ Defined in CANE2.ED
+
+ > PRMTR EQU 1
+
+ and referred multiple times in CANE2.ED and MIRINO.ED. Eg:
+
+ > ;PER RISPETTARE POS ORIZZONT. UCCELLO
+ > LXI D,TPADEL
+ > XRA A
+ > OUT PRMTR
+
+------------
+-- OUT 2 --
+Source files: CANE1.ED, CANE2.ED, MIRINO.ED
+
+ Defined in CANE2.ED
+
+ > DATO EQU 2
+
+ and referred multiple times in CANE1.ED and MIRINO.ED. Eg:
+
+ > ZANZ: XRA A
+ > OUT DATO
+
+------------
+-- OUT 3 --
+Source file: CANE2.ED
+
+ The access to port 3 is mediated by the routines SETP3 and RESP3 defined in CANE2.ED
+ SETP3 -- Port 3 = Port 3 | A
+
+ > SETP3:
+ > ;SETTA I BITS CONTEN IN REG A NELLA PORTA 3
+
+ RESP3 -- Port 3 = Port 3 & A
+
+ > RESP3:
+ > ;IL CONTRARIO DI SETP3
+
+ and referred multiple times in CANE2.ED. Eg:
+
+ > ;SPENGO IL VOLO UCCELLI
+ > MVI A,0FEH
+ > CALL SETP3
+
+------------
+-- OUT 4 --
+Source file: CANE1.ED, CANE2.ED
+
+ Called directly in CANE1.ED
+
+ > INT8:
+ > OUT 4
+ > ;PER LAUTORESET
+
+ Also defined in CANE2.ED
+
+ > RESET EQU 4
+
+ and called multiple times in CANE1.ED and CANE2.ED. Eg:
+
+ > DELAY3: OUT RESET
+
+------------
+-- OUT 5 --
+Source file: CANE2.ED, TOS.ED
+
+TOS sound
+D0-D7 is pushed into a LS273 (Octal D-type Flip-Flop) and it's value is used to preload the starting value of
+two, cascaded, LS161 (Synchronous 4-Bit Counters).
+The counters drive a J-K Flip-Flop generating a square wave signal drived in frequency by the preloaded value.
+
+ > CANONE:
+ > ;AZZITTO IL TOS:
+ > MVI A,255 ; A = 255 ; TIMER spento
+ > OUT 5 ; OUT 5
+
+The musical note is defined in a library source file TOS.ED and referred later by the source files, eg. in CANE2.ED:
+ > CARICA: DB RE,FA,FA,FA,FA,PAU
+ > DB RE,FA,FA,FA,FA,PAU
+ > DB RE,FA,PAU,RE,FA,PAU
+ > DB RE,FA,FA,FA,FA,PAU
+ > DB FINALE
+ > TABSTR: NOP
+ > LULUP: DB DO,RE,MI,FA,SOL,LA,SI,DO2
+ > DB FINALE
+
+ > CIPCIP: DB 220,215,210,205,200,FINALE
+
+ The notes are defined in TOS.ed:
+ > ; SI PARTE DA UNA FREQUENZA DI CLOCK DI 1 MHZ CIRCA,QUESTA FREQUENZA DIVISA)
+ > ; PER UNA SERIE DI PARAMETRI ATTRAVERSO DEI DIVISORI PROGRAMMABILI FORNISCE
+ > ; ALL'USCITA DI QUESTI I DODICI SEMITONI DELLA SCALA CROMATICA
+
+ Name - Counter - Aprox. frequency
+ DO 16 - 1000/(255-16) = 4.18 KHz
+ DOD 30 - 1000/(255-30) = 4.44 KHz
+ RE 43 - 1000/(255-43) = 4.72 KHz
+ RED 55 - 1000/(255-55) = 5 KHz
+ MI 66 - 1000/(255-66) = 5.29 KHz
+ FA 77 - 1000/(255-77) = 5.62 KHz
+ FAD 87 - 1000/(255-87) = 5.95 KHz
+ SOL 96 - 1000/(255-96) = 6.29 KHz
+ SOLD 105 - 1000/(255-105) = 6.67 KHz
+ LA 114 - 1000/(255-114) = 7.09 KHz
+ LAD 122 - 1000/(255-122) = 7.52 KHz
+ SI 129 - 1000/(255-129) = 7.94 KHz
+
+ DO2 136 - 1000/(255-136) = 8.4 KHz
+ DOD2 143 - 1000/(255-143) = 8.93 KHz
+ RE2 149.5 - 1000/(255-150) = 9.52 KHz
+ RED2 155.5 - 1000/(255-156) = 10.1 KHz
+ MI2 161 - 1000/(255-161) = 10.64 KHz
+ FA2 166.5 - 1000/(255-167) = 11.36 KHz
+ FAD2 171.5 - 1000/(255-172) = 12.05 KHz
+ SOL2 176 - 1000/(255-176) = 12.66 KHz
+ SOLD2 180.5 - 1000/(255-181) = 13.51 KHz
+ LA2 185 - 1000/(255-185) = 14.29 KHz
+ LAD2 189 - 1000/(255-189) = 15.15 KHz
+ SI2 192.5 - 1000/(255-193) = 16.13 KHz
+
+ Pause code:
+ PAU EQU 255
+
+ End of note sequence:
+ FINALE EQU 254
+
+------------
+-- IN 1 --
+Source file: CANE2.ED
+
+ Defined in CANE2.ED
+ > PORTAM EQU 1 ;E' LA PORTA DI INPUT DI TUTTI I PULSANTI
+
+------------
+-- IN 3 --
+Source file: CANE1.ED, CANE2.ED
+ Defined in CANE2.ED
+
+ > PRONTO EQU 3
+
+ and referred in CANE1.ED
+
+ > OUT LOW DATO
+ > IN LOW PRONTO
+
+**********************************************************************************************************************************/
+ map(0x00, 0x00).w(FUNC(cane_state::cane_unknown_port0_w));
+
+ map(0x01, 0x01).portr("IN1").w(m_mb14241, FUNC(mb14241_device::shift_count_w));
+ map(0x02, 0x02).w(m_mb14241, FUNC(mb14241_device::shift_data_w));
+ map(0x03, 0x03).r(m_mb14241, FUNC(mb14241_device::shift_result_r)).w("soundboard", FUNC(cane_audio_device::cane_sh_port_1_w));
+
+ map(0x04, 0x04).w(m_watchdog, FUNC(watchdog_timer_device::reset_w));
+
+ map(0x05, 0x05).w("soundboard", FUNC(cane_audio_device::cane_music_w));
+}
+
+static INPUT_PORTS_START( cane )
+/* Source file: CANE2.ED, MIRINO.ED
+ Port definition:
+ > PORTAM EQU 1 ;E' LA PORTA DI INPUT DI TUTTI I PULSANTI
+
+ Bit values:
+ CANE2.ED
+ > DITO EQU 80H ;BIT DEL PULSANTE DI SPARO DEL FUCILE
+
+ MIRINO.ED
+ > UPPMIR EQU 20H ;BIT PER MIRINO IN ALTO
+ > LOWMIR EQU 40H ;BASSO
+ > RIGMIR EQU 8H ;DESTRA
+ > LEFMIR EQU 10H ;SINISTRA
+
+ Joystick reading routine:
+ MIRINO.ED
+ > ;ORA LEGGO LA PORTA DELLA CLOCHE
+ > IN LOW PORTAM
+ > MOV B,A
+ > ;A QUESTO PUNTO AGGIORNO LE COORDINATE X E Y A SECONDA DELLO STATO DEI BIT
+ > ;DELLA CLOCHE (ATTIVI BASSI)
+ > ANI LOWMIR
+ > CZ MIRLOW
+ > MOV A,B
+ > ANI UPPMIR
+ > CZ MIRUPP
+ > MOV A,B
+ > ANI LEFMIR
+ > CZ MIRLEF
+ > MOV A,B
+ > ANI RIGMIR
+ > CZ MIRRIG
+
+ Shot reading routine:
+ CANE2.ED
+ > ;QUI CI VADO SE NESSUNO PREME IL PULSANTE E STO ASPETTANDO UNO SPARO
+ > ;TEST GRILLETTO
+ > IN PORTAM
+ > ANI DITO
+
+ Coin reading routine;
+ CANE1.ED
+ > ;ACCREDITA
+ > SAR9A: IN 1
+ > ANI 4
+
+ Start game: (Verificare con debug $3C2)
+ CANE1.ED
+ > IN 1
+ > ANI 8
+ > JNZ FONTI
+
+*/
+
+PORT_START("IN1")
+// PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_NOTUSED )
+// PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_NOTUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN1 )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_IMPULSE(2)
+INPUT_PORTS_END
+
+void cane_state::cane(machine_config &config)
+{
+ mw8080bw_root(config);
+
+ // Basic machine hardware
+ I8080(config.replace(), m_maincpu, 1996800); /* 19.968MHz / 10 */
+ m_maincpu->set_addrmap(AS_PROGRAM, &cane_state::cane_map);
+ m_maincpu->set_addrmap(AS_IO, &cane_state::cane_io_map);
+ m_maincpu->set_irq_acknowledge_callback(FUNC(cane_state::interrupt_vector));
+
+ WATCHDOG_TIMER(config, m_watchdog).set_vblank_count("screen", 255);
+
+ // add shifter
+ MB14241(config, m_mb14241);
+
+ // audio hardware
+ CANE_AUDIO(config, "soundboard");
+}
+
+void cane_state::cane_unknown_port0_w(u8 data)
+{
+ logerror("Unmapped io memory write to 00 = 00 %u\n", data);
+}
+
+/*******************************************************/
+/* */
+/* Model Racing "Orbite" */
+/* */
+/*******************************************************/
+/***********************************************************************************************************************************
+ This game was never completed and released by Model Racing to the public.
+ It's in a nearly incomplete form (eg: doesn't have any sound or score routine in the code) and it's barely playable.
+
+ The assembler source files for this game where extracted from the original floppy disks used by the former Model Racing developer
+ Adolfo Melilli (adolfo@melilli.com).
+ Those disks where retrieved by Alessandro Bolgia (xadhoom76@gmail.com) and Lorenzo Fongaro (lorenzo.fongaro@virgilio.it) and
+ dumped by Piero Andreini (pieroandreini@gmail.com) using KryoFlux hardware and software.
+ Subsequently Jean Paul Piccato (j2pguard-spam@yahoo.com) mounted the images and compiled the source files, managed to set up a
+ romset and wrote a mame driver that aims to reproduce in the most faithful way the work of Melilli at Model Racing in late '70s.
+
+ The game driver is not based on hardware inspection and is solely derived from assumptions I've made looking at the assembler
+ code and comments written into the source files of the game. Several of those hypothesis came following the directions of
+ previous yet contemporary Model Racing works (Eg: Claybuster) and where confirmed by Melilli himself.
+
+ Being unreleased this games has not an official name, thus the name used in the source files was used instead.
+
+***********************************************************************************************************************************/
+
+u8 orbite_state::orbite_scattered_colorram_r(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED u8 mem_mask)
+{
+ return m_scattered_colorram[(offset & 0x1f) | ((offset & 0x1f80) >> 2)];
+}
+
+
+void orbite_state::orbite_scattered_colorram_w(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED u8 data, ATTR_UNUSED u8 mem_mask)
+{
+ m_scattered_colorram[(offset & 0x1f) | ((offset & 0x1f80) >> 2)] = data;
+}
+
+
+void orbite_state::orbite_map(address_map &map)
+{
+// map(0x0000, 0x1fff).rom();
+ map(0x0000, 0x07ff).rom();
+ map(0x0800, 0x1fff).rom();
+ map(0x2000, 0x3fff).ram().share("main_ram");
+ map(0xc000, 0xdfff).rw(FUNC(orbite_state::orbite_scattered_colorram_r), FUNC(orbite_state::orbite_scattered_colorram_w));
+}
+
+
+void orbite_state::orbite_io_map(address_map &map)
+{
+ map(0x06, 0x06).w(m_watchdog, FUNC(watchdog_timer_device::reset_w));
+
+ // Ports verified on sources
+ map(0x08, 0x08).r(m_mb14241, FUNC(mb14241_device::shift_result_r));
+ map(0x20, 0x20).w(m_mb14241, FUNC(mb14241_device::shift_count_w));
+ map(0x40, 0x40).w(m_mb14241, FUNC(mb14241_device::shift_data_w));
+
+ map(0x66, 0x66).portr("IN0");
+ map(0x76, 0x76).portr("IN1");
+ map(0x7A, 0x7A).portr("IN2");
+}
+
+
+static INPUT_PORTS_START( orbite )
+ PORT_START("IN0")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_2WAY
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("IN1")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_2WAY
+
+ PORT_START("IN2") // port 2
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 )
+INPUT_PORTS_END
+
+
+void orbite_state::machine_start()
+{
+ m_scattered_colorram = std::make_unique<uint8_t []>(0x800);
+ save_pointer(&m_scattered_colorram[0], "m_scattered_colorram", 0x800);
+ mw8080bw_state::machine_start();
+}
+
+void orbite_state::orbite(machine_config &config)
+{
+ mw8080bw_root(config);
+
+ // basic machine hardware
+ I8080(config.replace(), m_maincpu, 1996800); /* 19.968MHz / 10 */
+ m_maincpu->set_addrmap(AS_PROGRAM, &orbite_state::orbite_map);
+ m_maincpu->set_addrmap(AS_IO, &orbite_state::orbite_io_map);
+ m_maincpu->set_irq_acknowledge_callback(FUNC(orbite_state::interrupt_vector));
+
+ WATCHDOG_TIMER(config, m_watchdog).set_vblank_count("screen", 255);
+
+ // add shifter
+ MB14241(config, m_mb14241);
+
+ // video hardware
+ m_screen->set_screen_update(FUNC(orbite_state::screen_update_orbite));
+
+ PALETTE(config, m_palette, palette_device::RGB_3BIT);
+}
+
/**************************************************************************************************************/
ROM_START( searthin )
@@ -5175,6 +5592,20 @@ ROM_START( attackfc )
ROM_LOAD( "39a.bin", 0x1c00, 0x0400, CRC(f538cf08) SHA1(4a375a41ab5d9f0d9f9a2ebef4c448038c139204) )
ROM_END
+ROM_START( cane )
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD( "mrcane.71", 0x0000, 0x0800, CRC(47de691e) SHA1(8ed359774489ccf6023819b0d604b5a6d94b9f98) )
+ ROM_LOAD( "mrcane.70", 0x0800, 0x0800, CRC(3f3ee3b9) SHA1(ef45cf76697bbe037c680021ffa663856f2972d0) )
+ ROM_LOAD( "mrcane.69", 0x1000, 0x0800, CRC(d1fd883f) SHA1(30572ac7052d4898e458ad3130cc05f153427a64) )
+ ROM_LOAD( "mrcane.62", 0x1800, 0x0800, CRC(0d37cc00) SHA1(02f136b499cca35c70a6aaae475c516d91392e36) )
+ROM_END
+
+ROM_START( orbite )
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD( "mrxx.71", 0x0000, 0x0800, CRC(78cf0c8a) SHA1(0bda9352c35e2ac175bd5ce6ee42e94247f5149a) )
+ ROM_LOAD( "mrxx.70", 0x0800, 0x0800, CRC(2914a5c4) SHA1(ac38c3a1c537ab22301bede0013db0d485012237) )
+ ROM_LOAD( "mrxx.69", 0x1000, 0x0800, CRC(46a8468b) SHA1(bf5dfed67fa4986994b8a74971e094bbff57c873) )
+ROM_END
// year rom parent machine inp class init monitor ...
@@ -5327,3 +5758,6 @@ GAME( 2002, invmultis3a, invmulti, invmulti, invmulti, _8080bw_state, init_in
GAME( 2002, invmultis2a, invmulti, invmulti, invmulti, _8080bw_state, init_invmulti, ROT270, "hack (Braze Technologies)", "Space Invaders Multigame (S0.82A)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
GAME( 2002, invmultis1a, invmulti, invmulti, invmulti, _8080bw_state, init_invmulti, ROT270, "hack (Braze Technologies)", "Space Invaders Multigame (S0.81A)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
GAME( 2002, invmultip, invmulti, invmulti, invmulti, _8080bw_state, init_invmulti, ROT270, "hack (Braze Technologies)", "Space Invaders Multigame (prototype)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
+
+GAME(1979?, cane, 0, cane, cane, cane_state, empty_init, ROT0, "Model Racing", "Cane", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND)
+GAME(1979?, orbite, 0, orbite, orbite, orbite_state, empty_init, ROT270, "Model Racing", "Orbite", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND_HW)