diff options
Diffstat (limited to 'src/mame/zaccaria/laserbat_a.cpp')
-rw-r--r-- | src/mame/zaccaria/laserbat_a.cpp | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/src/mame/zaccaria/laserbat_a.cpp b/src/mame/zaccaria/laserbat_a.cpp new file mode 100644 index 00000000000..96e114c3dea --- /dev/null +++ b/src/mame/zaccaria/laserbat_a.cpp @@ -0,0 +1,326 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/* + Laser Battle / Lazarian (c) 1981 Zaccaria + Cat and Mouse (c) 1982 Zaccaria + + audio emulation by Vas Crabb +*/ + +#include "emu.h" +#include "laserbat.h" + + +uint8_t laserbat_state_base::rhsc_r() +{ + return m_rhsc; +} + +void laserbat_state_base::whsc_w(uint8_t data) +{ + m_whsc = data; +} + +void laserbat_state_base::csound1_w(uint8_t data) +{ + m_csound1 = data; +} + +void laserbat_state_base::csound2_w(uint8_t data) +{ + m_csound2 = data; +} + + +/* + The Laser Battle/Lazarian sound board has a SN76477 CSG, two TMS3615 + tone synthesisers, and a TDA1010 power amplifier. It receives + commands from the game board over a 16-bit unidirectional data bus. + The CPU cannot write all sixteen lines atomically, it writes to + lines 1-8 as one group and 9-16 as another group. + + The game board makes the audio output from the first S2636 PVI (5E) + available on a pin at the sound board interface connector, but it + isn't routed anywhere, so you won't hear it. + + The TMS3615 at 05 is clocked at 250kHz (4MHz crystal oscillator + divided by 16), and its divide-by-two output is used to clock the + TMS3615 at 04. This gives a base 16' note of C3. The combined 8' + or 16' outputs are selectable by jumper, allowing the board to be + switched between two octaves. There's no indication of which octave + would have been selected in the Lazarian manual. + + There's a filter network between the TMS3615 outputs and the power + amplifier with several parameters controllable from the game board. + + The audio output of the SN76477 isn't actually used. Rather, the + signal from before the output amplifier is taken and used to gate + distortion elements in the analog filter network. + + +-----+----------------------------------------------------------+ + | Bit | Function | + +-----+----------------------------------------------------------+ + | 1 | Multiplexed data bit 1 | + | 2 | Multiplexed data bit 2 | + | 3 | Multiplexed data bit 3 | + | 4 | Multiplexed data bit 4 | + | 5 | Multiplexed data bit 5 | + | 6 | Multiplexed data bit 6 | + | 7 | Multiplexed data bit 7 | + | 8 | Multiplexed data bit 8 | + | 9 | SN76477/distortion control (positive edge trigger) | + | 10 | High octave key 13 | + | 11 | Key/SLF resistor select A | + | 12 | Key/SLF resistor select B | + | 13 | Key/SLF resistor control | + | 14 | Gates 22k/10nF low-pass filter and one SN-driven effect | + | 15 | SN76477 VCO select (inverted) | + | 16 | TMS3615 reset | + +-----+----------------------------------------------------------+ + + +-------+----------+-----------------------------------+ + | 11-13 | SLF res. | Key select | + +-------+----------+-----------------------------------+ + | 0 | 27k | | + | 1 | 22k | | + | 2 | 22k | | + | 3 | 12k | | + | 4 | inf. | | + | 5 | inf. | Low octave 1-8 | + | 6 | inf. | Low octave 9-13, high octave 2-4 | + | 7 | inf. | High octave 5-12 | + +-------+----------+-----------------------------------+ + + When bit 13 is high, no SLF control resistor is connected to the + CSG. When bit 13 is low, bits 11 and 12 select between 27k, 22k and + 12k. + + When bit 13 is high, the clock input of a latch driving eight of + TMS3615 key inputs will be driven low, depending on bits 11 and 12. + These latches are positive edge triggered, and you have to beware of + glitches, so the safe way to set key inputs is: + * Ensure bit 13 is low + * Write desired key data pattern to CSOUND1 + * Write CSOUND2 setting bits 11 and 12 to select keys to set + * Write CSOUND2 setting bit 13 high + * Write CSOUND2 setting bit 13 low + * Write CSOUND2 setting bits 11 and 12 to select SLF resistor + + Note that the SLF resistor will necessarily thrash around during the + process of setting key data. It's a side-effect of the way control + lines are overloaded. + + The SN76477 control bits are defined as follows: + + +-----+---------------------------------------------------------+ + | Bit | Function | + +-----+---------------------------------------------------------+ + | 1 | Noise filter/VCO resistor select A | + | 2 | Noise filter/VCO resistor select B | + | 3 | Noise filter/VCO resistor select C | + | 4 | AB SOUND (connected to System Inhibit input) | + | 5 | VCO/NOISE (connected to Mixer Select B input) | + | 6 | DEGR (controls a distortion element in filter network) | + | 7 | FILT (gates 10nF capacitor across distortion elements) | + | 8 | A (controls a distortion element in filter network) | + +-----+---------------------------------------------------------+ + +*/ + +void laserbat_state::csound2_w(uint8_t data) +{ + // there are a bunch of edge-triggered things, so grab changes + uint8_t const diff = data ^ m_csound2; + + // SN76477 and distortion control + if (data & diff & 0x01) + { + switch (m_csound1 & 0x07) + { + case 0x00: + m_csg->noise_filter_res_w(RES_K(270)); // R30 + m_csg->vco_res_w(RES_K(47)); // R47 + break; + case 0x01: + m_csg->noise_filter_res_w(RES_K(220)); // R23 + m_csg->vco_res_w(RES_K(27)); // R40 + break; + case 0x02: + m_csg->noise_filter_res_w(RES_K(150)); // R24 + m_csg->vco_res_w(RES_K(22)); // R41 + break; + case 0x03: + m_csg->noise_filter_res_w(RES_K(120)); // R25 + m_csg->vco_res_w(RES_K(15)); // R42 + break; + case 0x04: + m_csg->noise_filter_res_w(RES_K(82)); // R29 + m_csg->vco_res_w(RES_K(12)); // R46 + break; + case 0x05: + m_csg->noise_filter_res_w(RES_K(68)); // R28 + m_csg->vco_res_w(RES_K(8.2)); // R45 + break; + case 0x06: + m_csg->noise_filter_res_w(RES_K(47)); // R27 + m_csg->vco_res_w(RES_K(6.8)); // R44 + break; + case 0x07: + m_csg->noise_filter_res_w(RES_K(33)); // R26 + m_csg->vco_res_w(RES_K(4.7)); // R43 + break; + } + m_csg->enable_w((m_csound1 & 0x08) ? 1 : 0); + m_csg->mixer_b_w((m_csound1 & 0x10) ? 1 : 0); + // TODO: DEGR/FILT/A + } + + // edge-triggered latches plus a dedicated bit for note control + m_keys = (m_keys & 0x00ffffff) | ((data & 0x02) ? 0x01000000 : 0x00000000); + if ((m_csound2 & 0x10) && (diff & 0x1c)) + { + switch (m_csound2 & 0x0c) + { + case 0x00: + break; + case 0x04: + m_keys = (m_keys & 0x01ffff00) | (unsigned(m_csound1) << 0); + break; + case 0x08: + m_keys = (m_keys & 0x01ff00ff) | (unsigned(m_csound1) << 8); + break; + case 0x0c: + m_keys = (m_keys & 0x0100ffff) | (unsigned(m_csound1) << 16); + break; + } + } + m_synth_low->enable_w((m_keys >> 0) & 0x01fff); + m_synth_high->enable_w((m_keys >> 12) & 0x01ffe); + + // bits 11-13 set the SLF control register directly + switch (data & 0x1c) + { + case 0x00: // R54 + m_csg->slf_res_w(RES_K(27)); + break; + case 0x04: // R53 + case 0x08: // R52 + m_csg->slf_res_w(RES_K(22)); + break; + case 0x0c: // R51 + m_csg->slf_res_w(RES_K(12)); + break; + default: // NC + m_csg->slf_res_w(RES_INF); + break; + } + + // TODO: BIT14 filter control + + // inverted VCO select + m_csg->vco_w((data & 0x40) ? 0 : 1); + + // TODO: BIT15 TMS reset + + // keep for detecting changes next time + m_csound2 = data; +} + + +/* + The Cat and Mouse sound board has a 6802 processor with three ROMs, + a 6821 PIA, two AY-3-8910 PSGs, and some other logic and analog + circuitry. Unfortunately we lack a schematic, so all knowledge of + this board is based on tracing the sound program, examining PCB + photos and cross-referencing with the schematic for the 1B11142 + board. + + The 6821 PIA is mapped at addresses $005C..$005F. The known PIA + signal assignments are as follows: + + +------+-----------------------+ + | PA0 | PSG1/PSG2 DA0 | + | PA1 | PSG1/PSG2 DA1 | + | PA2 | PSG1/PSG2 DA2 | + | PA3 | PSG1/PSG2 DA3 | + | PA4 | PSG1/PSG2 DA4 | + | PA5 | PSG1/PSG2 DA5 | + | PA6 | PSG1/PSG2 DA6 | + | PA7 | PSG1/PSG2 DA7 | + | PB0 | PSG1 BC1 | + | PB1 | PSG1 BDIR | + | PB2 | PSG2 BC1 | + | PB3 | PSG2 BDIR | + | CA1 | Host interface bit 6 | + | CB1 | periodic IRQ source | + | IRQA | 6802 NMI | + | IRQB | 6802 IRQ | + +------+-----------------------+ + + The program makes use of I/O port A on the first PSG as outputs. At + a guess, it could have the same function as it does on other + Zaccaria sound boards. + + The first PSG receives commands from the game board in the low five + bits of port B. Commands are processed on receiving an NMI. The + sound program always masks out the high three bits of the value so + they could be connected to anything on the board. + + The I/O ports on the second PSG don't appear to be used at all. + + The game board sends commands to the sound board over a 16-bit + unidirectional data bus. The CPU cannot write all sixteen lines + atomically, it write to lines 1-8 as one group and 9-16 as another + group. However only seven lines are actually connected to the sound + board: + + +-----+----------+-------------+ + | Bit | Name | Connection | + +-----+----------+-------------+ + | 1 | SOUND 0 | PSG1 IOB0 | + | 2 | SOUND 1 | PSG1 IOB1 | + | 3 | SOUND 2 | PSG1 IOB2 | + | 4 | SOUND 3 | PSG1 IOB3 | + | 5 | SOUND 4 | PSG1 IOB4 | + | 6 | SOUND 5 | PIA CA1 | + | 7 | | | + | 8 | | | + | 9 | | 14L A11 | + | 10 | | | + | 11 | | | + | 12 | | | + | 13 | | | + | 14 | | | + | 15 | | | + | 16 | RESET | Unknown | + +-----+----------+-------------+ + + Bit 9 is used to select the sprite ROM bank. There's a wire visible + on the component side of the PCB connecting it to the high address + bit (A11) of the sprite ROM at 14L. + + There could well be other connections on the sound board - these are + just what can be deduced by tracing the sound program. + + The game board makes the audio output from the first S2636 PVI + (5E) available on a pin at the sound board interface connector, but + it isn't routed anywhere. +*/ + +void catnmous_state::csound1_w(uint8_t data) +{ + m_audiopcb->sound_w(data); + + m_csound1 = data; +} + +void catnmous_state::csound2_w(uint8_t data) +{ + // the bottom bit is used for sprite banking, of all things + m_gfx2_base = uint16_t(BIT(data, 0)) << 11; + + // the top bit is called RESET on the wiring diagram + m_audiopcb->reset_w(BIT(data, 7)); + + m_csound2 = data; +} |