diff options
author | janniz <j2pguard-spam@yahoo.com> | 2019-10-31 12:11:45 +0100 |
---|---|---|
committer | Vas Crabb <cuavas@users.noreply.github.com> | 2019-10-31 22:11:45 +1100 |
commit | f31b19f9c91a82d12f15959f03d0c7caf914c152 (patch) | |
tree | 78f7b2136c593403568eb784112d37b1094d12fe | |
parent | ba273549dd298adc55d786ea5d1d463874f24eda (diff) |
Added two new unreleased Model Racing games (#5813)
* Fixed LOG_WAV_ENABLED_ONLY (m_enable has to be checked only if LOG_WAV_ENABLED_ONLY is set)
Added log data to the right channel of the wave, accordingly to the definition declared in LOG_WAV_VALUE_R
* Fixed an error with tag() returning a ':' and generating a filename not valid in Windows environment
* Added Model Racing "Cane"
* Added Model Racing "Orbite"
* Replaced the char array with a std::string in sn76477_device::open_wav_file to override possible buffer overrun.
Minor cosmetic change in a boolean expression in sn76477_device::sound_stream_update
* Refactored "Cane" related code creating an audio device to encapsulate the audio system
Refactored "Cane" and "Orbite" creating their own classes
Other minor changes in indentation of the source code
-rw-r--r-- | src/devices/sound/sn76477.cpp | 38 | ||||
-rw-r--r-- | src/mame/audio/8080bw.cpp | 280 | ||||
-rw-r--r-- | src/mame/audio/8080bw.h | 44 | ||||
-rw-r--r-- | src/mame/drivers/8080bw.cpp | 434 | ||||
-rw-r--r-- | src/mame/includes/8080bw.h | 73 | ||||
-rw-r--r-- | src/mame/mame.lst | 2 | ||||
-rw-r--r-- | src/mame/video/8080bw.cpp | 25 |
7 files changed, 884 insertions, 12 deletions
diff --git a/src/devices/sound/sn76477.cpp b/src/devices/sound/sn76477.cpp index c259b3cb0ed..d24ab6a1bb6 100644 --- a/src/devices/sound/sn76477.cpp +++ b/src/devices/sound/sn76477.cpp @@ -892,9 +892,11 @@ void sn76477_device::log_complete_state() void sn76477_device::open_wav_file() { - char wav_file_name[30]; + std::string s = tag(); + std::replace(s.begin(), s.end(), ':', '_'); + + char const* wav_file_name = util::string_format(LOG_WAV_FILE_NAME, s).c_str(); - sprintf(wav_file_name, LOG_WAV_FILE_NAME, tag()); m_file = wav_open(wav_file_name, m_our_sample_rate, 2); LOG(1, "SN76477: Logging output: %s\n", wav_file_name); @@ -1996,7 +1998,7 @@ void sn76477_device::sound_stream_update(sound_stream &stream, stream_sample_t * */ *buffer++ = (((voltage_out - OUT_LOW_CLIP_THRESHOLD) / (OUT_CENTER_LEVEL_VOLTAGE - OUT_LOW_CLIP_THRESHOLD)) - 1) * 32767; - if (LOG_WAV && LOG_WAV_ENABLED_ONLY && !m_enable) + if (LOG_WAV && (!m_enable || !LOG_WAV_ENABLED_ONLY)) { int16_t log_data_l; int16_t log_data_r; @@ -2005,30 +2007,48 @@ void sn76477_device::sound_stream_update(sound_stream &stream, stream_sample_t * { case 0: log_data_l = LOG_WAV_GAIN_FACTOR * voltage_out; - log_data_r = LOG_WAV_GAIN_FACTOR * voltage_out; break; case 1: log_data_l = LOG_WAV_GAIN_FACTOR * m_enable; - log_data_r = LOG_WAV_GAIN_FACTOR * m_enable; break; case 2: log_data_l = LOG_WAV_GAIN_FACTOR * m_one_shot_cap_voltage; - log_data_r = LOG_WAV_GAIN_FACTOR * m_one_shot_cap_voltage; break; case 3: log_data_l = LOG_WAV_GAIN_FACTOR * m_attack_decay_cap_voltage; - log_data_r = LOG_WAV_GAIN_FACTOR * m_attack_decay_cap_voltage; break; case 4: log_data_l = LOG_WAV_GAIN_FACTOR * m_slf_cap_voltage; - log_data_r = LOG_WAV_GAIN_FACTOR * m_slf_cap_voltage; break; case 5: log_data_l = LOG_WAV_GAIN_FACTOR * m_vco_cap_voltage; - log_data_r = LOG_WAV_GAIN_FACTOR * m_vco_cap_voltage; break; case 6: log_data_l = LOG_WAV_GAIN_FACTOR * m_noise_filter_cap_voltage; + break; + } + + switch (LOG_WAV_VALUE_R) + { + case 0: + log_data_r = LOG_WAV_GAIN_FACTOR * voltage_out; + break; + case 1: + log_data_r = LOG_WAV_GAIN_FACTOR * m_enable; + break; + case 2: + log_data_r = LOG_WAV_GAIN_FACTOR * m_one_shot_cap_voltage; + break; + case 3: + log_data_r = LOG_WAV_GAIN_FACTOR * m_attack_decay_cap_voltage; + break; + case 4: + log_data_r = LOG_WAV_GAIN_FACTOR * m_slf_cap_voltage; + break; + case 5: + log_data_r = LOG_WAV_GAIN_FACTOR * m_vco_cap_voltage; + break; + case 6: log_data_r = LOG_WAV_GAIN_FACTOR * m_noise_filter_cap_voltage; break; } diff --git a/src/mame/audio/8080bw.cpp b/src/mame/audio/8080bw.cpp index 27fcb7add51..08beb52cf52 100644 --- a/src/mame/audio/8080bw.cpp +++ b/src/mame/audio/8080bw.cpp @@ -24,6 +24,13 @@ MACHINE_START_MEMBER(_8080bw_state,extra_8080bw_sh) save_item(NAME(m_port_3_last_extra)); } +/************************************* + * + * Device type globals + * + *************************************/ + +DEFINE_DEVICE_TYPE(CANE_AUDIO, cane_audio_device, "cane_audio", "Model Racing Cane Audio") /************************************* @@ -1397,3 +1404,276 @@ WRITE8_MEMBER( _8080bw_state::darthvdr_08_w ) m_port_1_last_extra = data; } + + +/*********************************************************/ +/* */ +/* Model Racing "Cane" (Slightly based on Claybuster hw) */ +/* */ +/*********************************************************/ +#define CANE_CLOCK (19968000.0) +#define CANE_H64 CANE_CLOCK /2 /2 /4 + +/* Nodes - Sound enable */ +#define CANE_SND_EN NODE_05 + +/* Nodes - Adjusters */ +#define CANE_VR1 NODE_07 // Gain for 76477 +#define CANE_VR2 NODE_08 // VR attached to the output of the TOS +#define CANE_VR3 NODE_09 // VR for SFX generated by the 555 + +/* Nodes - sn76477 Sounds */ +#define CANE_EXP_STREAM NODE_03 +#define CANE_EXP_SND NODE_11 + +/* Nodes - BGM */ +#define CANE_MUSIC_DATA NODE_06 +#define CANE_MUSIC_NOTE NODE_40 +#define CANE_MUSIC_NOTE_PF NODE_01 +#define CANE_MUSIC_SND NODE_12 + +/* Nodes - 555 sfx */ +#define CANE_76477_PIN6 NODE_13 +#define CANE_555_CLAMPED NODE_14 +#define CANE_555_ONESHOT NODE_15 +#define CANE_555_EN NODE_16 +#define CANE_TMP_SND NODE_17 +#define CANE_SFX_SND NODE_18 + +/* Node output */ +#define CANE_SOUND_OUT NODE_90 + +static INPUT_PORTS_START( cane_audio ) + PORT_START("VR1") + PORT_ADJUSTER( 80, "VR1 - SFX from 76477" ) + + PORT_START("VR2") + PORT_ADJUSTER( 90, "VR2 - TOS music" ) + + PORT_START("VR3") + PORT_ADJUSTER( 70, "VR3 - Shoot SFX from 555" ) +INPUT_PORTS_END + +cane_audio_device::cane_audio_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, CANE_AUDIO, tag, owner, clock), + m_cane_vco_timer(*this, "cane_vco_timer"), + m_sn(*this, "snsnd"), + m_discrete(*this, "discrete"), + m_cane_vco_rc_chargetime(INT_MAX) +{ +} + +void cane_audio_device::device_add_mconfig(machine_config &config) +{ + // provare a commentare + m_cane_vco_rc_chargetime = INT_MAX; + + TIMER(config, "cane_vco_timer").configure_periodic(FUNC(cane_vco_voltage_timer), attotime::from_hz(1000)); + + SPEAKER(config, "mono").front_center(); + + SN76477(config, m_sn); + // Amplitude res in the schematic is connected to a 470K potentiometer, so from the schematic is impossible to know the real res. + // This parameter drives the amp just before the audio output pin 13. + m_sn->set_amp_res(100+RES_K(20)); + m_sn->set_noise_params(RES_K(39), RES_K(1), CAP_P(1000)); + m_sn->set_decay_res(RES_M(1)); + m_sn->set_attack_params(CAP_U(1.0), RES_K(47)); + m_sn->set_feedback_res(RES_K(4.7)); + m_sn->set_vco_params(0, CAP_P(3300), RES_K(100)); + m_sn->set_pitch_voltage(5.0); + m_sn->set_slf_params(CAP_U(1.0), RES_K(33)); + m_sn->set_oneshot_params(CAP_U(10), RES_K(100)); + m_sn->set_vco_mode(0); + m_sn->set_mixer_params(0, 0, 0); + m_sn->set_envelope_params(1, 0); + m_sn->set_enable(0); + m_sn->add_route(0, "discrete", 1.0, 0); + + DISCRETE(config, m_discrete, cane_discrete); + m_discrete->add_route(ALL_OUTPUTS, "mono", 1.0); +} + +ioport_constructor cane_audio_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(cane_audio); +} + +void cane_audio_device::device_start() +{ +} + +void cane_audio_device::cane_sh_port_1_w(u8 data) +{ + /* + bit 0 - SX0 - Sound enable on mixer + bit 1 - SX1 - SN76477 - Mixer select C - pin 27 + bit 2 - SX2 - SN76477 - Mixer select A - pin 26 + bit 3 - SX3 - SN76477 - Mixer select B - pin 25 + bit 4 - SX4 - NE555 - Trigger (Step, high output level for 1.1*RC = 1.1*100K*0.47u = 51.7 ms) + */ + + m_discrete->write(CANE_SND_EN, data & 0x01); // BIT(data, 0) - bit 0 - SX0 - Sound enable on mixer + m_discrete->write(CANE_555_EN, data & 0x10); // BIT(data, 4) - bit 4 - SX4 - NE555 - Trigger + + // 76477 enable bit is connected to the select line of the out port 3 (inverted). + m_sn->enable_w(1); + m_sn->set_mixer_params(BIT(data, 2), BIT(data, 3), BIT(data, 1)); + + m_cane_vco_timer->adjust(attotime::zero, m_cane_vco_timer->param(), attotime::from_hz(1000)); + m_cane_vco_rc_chargetime = m_cane_vco_timer->start_time().as_double(); + + // Little hack... + // To be precise I should enable the 76477 every time the CPU reads or write to a port different from port 3 + // and disable it every time the CPU read/write from/to port 3. + // Actually this can not be done easily so I decided to enable it preemptively here after every port 3 access + m_sn->enable_w(0); +} + +void cane_audio_device::cane_music_w(u8 data) +{ + m_sn->enable_w(1); + m_discrete->write(CANE_MUSIC_DATA, data); +} + +void cane_audio_device::cane_76477_en_w(u8 data) +{ + m_sn->enable_w(0); +} + +void cane_audio_device::cane_76477_dis_w(u8 data) +{ + m_sn->enable_w(1); +} + +/*******************************************************************************************************************************************************/ +/* Cane discrete implementation, slightly based on Claybuster hw. */ +/* This implementation doesn't pretend to be accurate thus trying to be at least functionally similar. */ +/* */ +/* Port 1 - SX4 CANE_VR3 Port 1 - SX0 */ +/* | | | */ +/* CANE_555_EN | | */ +/* | | | */ +/* +------------------+ | | */ +/* | CANE_555_ONESHOT | | | */ +/* +------------------+ | | */ +/* | | | */ +/* v v | */ +/* sn76477 pin 6 +------------------+ +---+ +--------------+ +---+ +--------------+ | */ +/* CLAMP(0, 5V) ->| CANE_555_CLAMPED |->| * |->| CANE_TMP_SND |->| * |->| CANE_SFX_SND | CANE_SND_EN */ +/* (DISCRETE_NOISE) +------------------+ +---+ +--------------+ +---+ +--------------+ | */ +/* | | */ +/* CANE_VR1 | | */ +/* | | | */ +/* v v v */ +/* sn76477 output +-----------------+ +---+ +--------------+ +---+ +----------------+ */ +/* DISCRETE_INPUTX_STREAM ->| CANE_EXP_STREAM |->| * |->| CANE_EXP_SND |->| + |->| CANE_SOUND_OUT |->OUT */ +/* +-----------------+ +---+ +--------------+ +---+ +----------------+ */ +/* ^ */ +/* | */ +/* CANE_MUSIC_DATA +--------------------+ +-----------+ +-----------------+ +---+ +----------------+ */ +/* Port 5 data---DISCRETE_INPUT_DATA ->| CANE_MUSIC_NOTE_PF |->| CR_FILTER |->| CANE_MUSIC_NOTE |->| * |->| CANE_MUSIC_SND | */ +/* DISCRETE_NOTE +--------------------+ +-----------+ +-----------------+ +---+ +----------------+ */ +/* RES_K(10) ^ */ +/* CAP_U(0.1) | */ +/* CANE_VR2 */ +/* */ +/* */ +/*******************************************************************************************************************************************************/ +DISCRETE_SOUND_START(cane_discrete) + /************************************************/ + /* Input register mapping for cane */ + /************************************************/ + DISCRETE_INPUT_DATA (CANE_MUSIC_DATA) + + DISCRETE_INPUT_LOGIC (CANE_555_EN) + + // scale to 0-2.5V + DISCRETE_INPUTX_STREAM(CANE_EXP_STREAM, 0, 0.5, 0) + + DISCRETE_INPUT_LOGIC (CANE_SND_EN) + + /************************************************/ + /* Volume adjusters. */ + /* We will set them to adjust the realitive */ + /* gains. */ + /************************************************/ + DISCRETE_ADJUSTMENT(CANE_VR1, 0, 0.33*6, DISC_LINADJ, "VR1") // Gain for 76477 + DISCRETE_ADJUSTMENT(CANE_VR2, 0, 0.33*60000, DISC_LINADJ, "VR2") // VR attached to the output of the TOS + DISCRETE_ADJUSTMENT(CANE_VR3, 0, 0.33*60000, DISC_LINADJ, "VR3") // VR for SFX generated by the 555 + + /************************************************/ + /* From 555 */ + /************************************************/ + /* TODO: find real noise freq and amplitude */ + /* width was simulated with ltspice using Claybuster schematic as a source and it's value is about 51ms */ + DISCRETE_NOISE(CANE_76477_PIN6, + 1, /* ENAB */ + 1280, /* FREQ - Guessed */ + 1, /* AMP */ + 0) /* BIAS - fake AC is fine*/ + DISCRETE_CLAMP(CANE_555_CLAMPED, + CANE_76477_PIN6, /* input node */ + 0.0, /* minimum */ + 5.0) /* maximum */ + DISCRETE_ONESHOT(CANE_555_ONESHOT, + CANE_555_EN, /* trigger node */ + 1, /* amplitude node or static value */ + 0.05, /* width (in seconds) node or static value - 50 ms*/ + DISC_ONESHOT_FEDGE | DISC_ONESHOT_RETRIG) /* type of oneshot static value */ + + DISCRETE_MULTIPLY(CANE_TMP_SND, CANE_555_CLAMPED, CANE_555_ONESHOT) + DISCRETE_MULTIPLY(CANE_SFX_SND, CANE_TMP_SND, CANE_VR3) + +/***************************************************************************** +* +* Music Generator (TOS) +* +* Values for this section of the sound hardware where derived from comments +* in the source code and the analysis of TOS.ED sources. +* +* For further info look at the relevant comments reported into +* drivers/8080bw.cpp +* +******************************************************************************/ + DISCRETE_NOTE(CANE_MUSIC_NOTE_PF, 1, CANE_H64, CANE_MUSIC_DATA, 255, 1, DISC_CLK_IS_FREQ) + DISCRETE_CRFILTER(CANE_MUSIC_NOTE, CANE_MUSIC_NOTE_PF, RES_K(10), CAP_U(0.1)) // high pass filter + DISCRETE_MULTIPLY(CANE_MUSIC_SND, CANE_MUSIC_NOTE, CANE_VR2) + +/****************************************************************************** +* +* From 76477 output +* +******************************************************************************/ + DISCRETE_MULTIPLY(CANE_EXP_SND, CANE_EXP_STREAM, CANE_VR1) + +/****************************************************************************** +* +* Final Mixing and Output +* +******************************************************************************/ + DISCRETE_ADDER3(CANE_SOUND_OUT, CANE_SND_EN, CANE_SFX_SND, CANE_EXP_SND, CANE_MUSIC_SND) + DISCRETE_OUTPUT(CANE_SOUND_OUT, 1) + +//LOG +/* + DISCRETE_WAVLOG1(CANE_EXP_STREAM, 1) + DISCRETE_WAVLOG1(CANE_EXP_SND, 1) + DISCRETE_WAVLOG1(CANE_TMP_SND, 1) + DISCRETE_WAVLOG1(CANE_SFX_SND, 1) + DISCRETE_WAVLOG1(CANE_MUSIC_NOTE, 1) + DISCRETE_WAVLOG1(CANE_MUSIC_SND, 1) + DISCRETE_WAVLOG1(CANE_SOUND_OUT, 1) +*/ +DISCRETE_SOUND_END + +TIMER_DEVICE_CALLBACK_MEMBER(cane_audio_device::cane_vco_voltage_timer) +{ + double voltage; + voltage = 5 * (1 - exp(- (m_cane_vco_timer->fire_time().as_double() - m_cane_vco_rc_chargetime) / 47)); + + logerror("t = %d\n", m_cane_vco_timer->fire_time().as_double() - m_cane_vco_rc_chargetime); + logerror("vco_voltage = %d\n", voltage); + + m_sn->vco_voltage_w(voltage); +} diff --git a/src/mame/audio/8080bw.h b/src/mame/audio/8080bw.h new file mode 100644 index 00000000000..3bbe99c2ab4 --- /dev/null +++ b/src/mame/audio/8080bw.h @@ -0,0 +1,44 @@ +// license:BSD-3-Clause +/*************************************************************************** + + 8080-based black and white sound hardware + +****************************************************************************/ +#ifndef MAME_AUDIO_8080BW_H +#define MAME_AUDIO_8080BW_H + +#pragma once + +#include "machine/timer.h" +#include "sound/discrete.h" +#include "sound/samples.h" +#include "sound/sn76477.h" + +class cane_audio_device : public device_t +{ +public: + cane_audio_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0); + + void cane_sh_port_1_w(u8 data); + void cane_music_w(u8 data); + void cane_76477_en_w(u8 data); + void cane_76477_dis_w(u8 data); + +protected: + virtual void device_add_mconfig(machine_config &config) override; + virtual ioport_constructor device_input_ports() const override; + virtual void device_start() override; + +private: + TIMER_DEVICE_CALLBACK_MEMBER(cane_vco_voltage_timer); + + required_device<timer_device> m_cane_vco_timer; + required_device<sn76477_device> m_sn; + required_device<discrete_sound_device> m_discrete; + + double m_cane_vco_rc_chargetime; +}; + +DECLARE_DEVICE_TYPE(CANE_AUDIO, cane_audio_device) + +#endif // MAME_AUDIO_8080BW_H 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) diff --git a/src/mame/includes/8080bw.h b/src/mame/includes/8080bw.h index c2feda4b058..32693e39337 100644 --- a/src/mame/includes/8080bw.h +++ b/src/mame/includes/8080bw.h @@ -11,6 +11,7 @@ #pragma once +#include "audio/8080bw.h" #include "includes/mw8080bw.h" #include "machine/eepromser.h" @@ -89,7 +90,10 @@ public: DECLARE_INPUT_CHANGED_MEMBER(claybust_gun_trigger); DECLARE_READ_LINE_MEMBER(claybust_gun_on_r); -private: +protected: + void clear_extra_columns( bitmap_rgb32 &bitmap, int color ); + inline void set_8_pixels( bitmap_rgb32 &bitmap, uint8_t y, uint8_t x, uint8_t data, int fore_color, int back_color ); + /* devices/memory pointers */ optional_device<cpu_device> m_audiocpu; optional_device<timer_device> m_schaser_effect_555_timer; @@ -101,9 +105,11 @@ private: optional_device<palette_device> m_palette; optional_shared_ptr<uint8_t> m_colorram; +private: /* misc game specific */ optional_ioport m_gunx; optional_ioport m_guny; + uint8_t m_color_map; uint8_t m_screen_red; uint8_t m_fleet_step; @@ -226,8 +232,6 @@ private: void schaser_reinit_555_time_remain(); inline void set_pixel( bitmap_rgb32 &bitmap, uint8_t y, uint8_t x, int color ); - inline void set_8_pixels( bitmap_rgb32 &bitmap, uint8_t y, uint8_t x, uint8_t data, int fore_color, int back_color ); - void clear_extra_columns( bitmap_rgb32 &bitmap, int color ); void invaders_samples_audio(machine_config &config); @@ -281,4 +285,67 @@ DISCRETE_SOUND_EXTERN( indianbt_discrete ); DISCRETE_SOUND_EXTERN( polaris_discrete ); DISCRETE_SOUND_EXTERN( schaser_discrete ); +/*******************************************************/ +/* */ +/* Cane (Model Racing) */ +/* */ +/*******************************************************/ +class cane_state : public _8080bw_state +{ +public: + cane_state(machine_config const &mconfig, device_type type, char const *tag) : + _8080bw_state(mconfig, type, tag), + m_soundboard(*this, "soundboard") + { + } + + void cane(machine_config &config); + void cane_audio(machine_config &config); + +protected: + void cane_unknown_port0_w(u8 data); + +private: + virtual void machine_start() override; + + void cane_io_map(address_map &map); + void cane_map(address_map &map); + + required_device<cane_audio_device> m_soundboard; +}; + +DISCRETE_SOUND_EXTERN( cane_discrete ); + +/*******************************************************/ +/* */ +/* Model Racing "Orbite" */ +/* */ +/*******************************************************/ +class orbite_state : public _8080bw_state +{ +public: + orbite_state(machine_config const &mconfig, device_type type, char const *tag) : + _8080bw_state(mconfig, type, tag), + m_main_ram(*this, "main_ram") + { + } + + void orbite(machine_config &config); + +protected: + required_shared_ptr<uint8_t> m_main_ram; + std::unique_ptr<uint8_t[]> m_scattered_colorram; + + u8 orbite_scattered_colorram_r(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED u8 mem_mask = 0xff); + void orbite_scattered_colorram_w(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED u8 data, ATTR_UNUSED u8 mem_mask = 0xff); + +private: + virtual void machine_start() override; + + void orbite_io_map(address_map &map); + void orbite_map(address_map &map); + + u32 screen_update_orbite(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); +}; + #endif // MAME_INCLUDES_8080BW_H diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 086f608b0c4..24f23098f4c 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -126,6 +126,7 @@ alieninvp2 // bootleg astropal // (c) 19?? Sidam attackfc // (c) 1979? E.G.S. ballbomb // TN (c) 1980 Taito +cane // Model Racing claybust // (c) 1978 Model Racing cosmicin // bootleg cosmicm2 // Universal @@ -186,6 +187,7 @@ lupin3a // LP (c) 1980 Taito mlander // (c) 1980 Leisure Time Electronics moonbase // Taito moonbasea // Zeta - Nichibutsu +orbite // Model Racing ozmawars // Shin Nihon Kikaku (SNK) ozmawars2 // Shin Nihon Kikaku (SNK) ozmawarsmr // bootleg (Model Racing) diff --git a/src/mame/video/8080bw.cpp b/src/mame/video/8080bw.cpp index 2d84c4df351..f3df7201358 100644 --- a/src/mame/video/8080bw.cpp +++ b/src/mame/video/8080bw.cpp @@ -409,3 +409,28 @@ uint32_t _8080bw_state::screen_update_spacecom(screen_device &screen, bitmap_rgb return 0; } + +/*******************************************************/ +/* */ +/* Model Racing "Orbite" */ +/* */ +/*******************************************************/ +uint32_t orbite_state::screen_update_orbite(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + for (offs_t offs = 0; offs < m_main_ram.bytes(); offs++) + { + uint8_t back_color = 0; + + uint8_t y = offs >> 5; + uint8_t x = offs << 3; + + uint8_t data = m_main_ram[offs]; + uint8_t fore_color = m_scattered_colorram[(offs & 0x1f) | ((offs & 0x1f80) >> 2)] & 0x07; + + set_8_pixels(bitmap, y, x, data, fore_color, back_color); + } + + clear_extra_columns(bitmap, 0); + + return 0; +} |