new driver: Bally Astrocade [iq_132, dink]

This commit is contained in:
dinkc64 2025-06-12 09:20:56 -04:00
parent 534610301c
commit d6d0416da6
4 changed files with 3107 additions and 2 deletions

View File

@ -58,7 +58,7 @@ drvsrc = d_akkaarrh.o d_arcadecl.o d_atarig1.o d_badlands.o d_batman.o d_blstro
d_shippumd.o d_slapfght.o d_snowbro2.o d_tekipaki.o d_toaplan1.o d_truxton2.o d_twincobr.o d_vfive.o d_wardner.o \
\
d_4enraya.o d_1942.o d_1943.o d_aeroboto.o d_akazukin.o d_alinvade.o d_alpha68k.o d_alpha68k1.o d_alpha68k2.o d_ambush.o d_amspdwy.o d_arabian.o d_argus.o d_armedf.o \
d_asteroids.o d_atetris.o d_aztarac.o d_bagman.o d_baraduke.o d_battlane.o d_battlex.o d_bbusters.o d_beaminv.o d_berzerk.o d_bionicc.o d_blktiger.o \
d_asteroids.o d_astrocde.o d_atetris.o d_aztarac.o d_bagman.o d_baraduke.o d_battlane.o d_battlex.o d_bbusters.o d_beaminv.o d_berzerk.o d_bionicc.o d_blktiger.o \
d_blockade.o d_blockout.o d_blueprnt.o d_bogeyman.o d_bombjack.o d_btime.o d_bwidow.o d_bzone.o d_cabal.o d_calorie.o d_canyon.o d_capbowl.o \
d_carjmbre.o d_ccastles.o d_cclimber.o d_cheekyms.o d_chinagat.o d_citycon.o d_cloak.o d_cloud9.o d_clshroad.o d_commando.o d_cop01.o d_copsnrob.o \
d_cybertnk.o d_dacholer.o d_darkmist.o d_dday.o d_ddayjlc.o d_ddragon.o d_deadang.o d_djboy.o d_dkong.o d_docastle.o d_dogfgt.o d_dorachan.o d_dribling.o d_drmicro.o \
@ -109,7 +109,7 @@ depobj = burn.o burn_bitmap.o burn_gun.o burn_led.o burn_shift.o burn_memory.o
namco_c45.o namcoio.o pandora.o pic8259.o pit8253.o poly.o qs1000.o resnet.o rtc9701.o seibucop.o seibusnd.o serflash.o sknsspr.o slapstic.o st0020.o t5182.o timekpr.o tlc34076.o tms34061.o v3021.o vdc.o \
tms9928a.o watchdog.o x2212.o \
\
asteroids.o ay8910.o burn_y8950.o burn_ym2151.o burn_ym2203.o burn_ym2413.o burn_ym2608.o burn_ym2610.o burn_ym2612.o burn_md2612.o \
asteroids.o astrocde_snd.o ay8910.o burn_y8950.o burn_ym2151.o burn_ym2203.o burn_ym2413.o burn_ym2608.o burn_ym2610.o burn_ym2612.o burn_md2612.o \
burn_ym3526.o burn_ym3812.o burn_ymf262.o burn_ymf271.o burn_ymf278b.o bzone.o c6280.o dac.o digitalk.o es5506.o es8712.o exidy440_snd.o flower.o flt_rc.o fm.o fmopl.o ym2612.o gaelco.o hc55516.o \
i5000.o ics2115.o iremga20.o k005289.o k007232.o k051649.o k053260.o k054539.o llander.o mpeg_audio.o msm5205.o msm5232.o msm6295.o multipcm.o namco_snd.o c140.o c352.o nes_apu.o \
t6w28.o tiamc1_snd.o tms5110.o tms5220.o tms36xx.o phoenixsound.o pleiadssound.o pokey.o redbaron.o rf5c68.o s14001a.o saa1099.o samples.o segapcm.o sn76477.o sn76496.o \

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,295 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles,Frank Palazzolo
/***********************************************************
Astrocade custom 'IO' chip sound chip driver
Aaron Giles
based on original work by Frank Palazzolo
************************************************************
Register Map
============
Register 0:
D7..D0: Master oscillator frequency
Register 1:
D7..D0: Tone generator A frequency
Register 2:
D7..D0: Tone generator B frequency
Register 3:
D7..D0: Tone generator C frequency
Register 4:
D7..D6: Vibrato speed
D5..D0: Vibrato depth
Register 5:
D5: Noise AM enable
D4: Mux source (0=vibrato, 1=noise)
D3..D0: Tone generator C volume
Register 6:
D7..D4: Tone generator B volume
D3..D0: Tone generator A volume
Register 7:
D7..D0: Noise volume
************************************************************
The device has active high(!) SO strobes triggered by
read accesses, which transfer data from the 8 SI lines
to the bus. Logically SO0-7 and SI0-7 ought to be hooked
up to the same input matrix, but this only appears to be
the case with the Astrocade home systems. The arcade
games instead channel the SI inputs through a quartet of
MC14539B (pin-compatible with 74153) CMOS multiplexers
and connect the SO strobes to unrelated outputs which
generally use the upper 8 address bits as data.
***********************************************************/
#include "burnint.h"
#include "bitswap.h"
#include "astrocde_snd.h"
#include "stream.h"
struct AstroReg {
UINT8 m_reg[8]; /* 8 control registers */
UINT8 m_master_count; /* current master oscillator count */
UINT16 m_vibrato_clock; /* current vibrato clock */
UINT8 m_noise_clock; /* current noise generator clock */
UINT16 m_noise_state; /* current noise LFSR state */
UINT8 m_a_count; /* current tone generator A count */
UINT8 m_a_state; /* current tone generator A state */
UINT8 m_b_count; /* current tone generator B count */
UINT8 m_b_state; /* current tone generator B state */
UINT8 m_c_count; /* current tone generator C count */
UINT8 m_c_state; /* current tone generator C state */
};
static UINT8 m_bitswap[256]; /* bitswap table */
static Stream stream[2]; // dink's stream
static AstroReg r[2];
static INT32 ndevs = 0;
static INT32 stream_id = 0;
static void sound_stream_update(INT16 **streams, INT32 samples);
void astrocde_snd_init(INT32 ndev, INT32 route)
{
if (ndev > 1) {
bprintf(PRINT_ERROR, _T("astrocde_snd: only 2 devices possible.\n"));
return;
}
ndevs = ndev;
stream[ndev].init((14318181)/2/4, nBurnSoundRate, 1, ndev, sound_stream_update);
stream[ndev].set_volume(1.00);
stream[ndev].set_route(route);
for (int i = 0; i < 256; i++)
m_bitswap[i] = BITSWAP08(i, 0,1,2,3,4,5,6,7);
}
void astrocde_snd_reset()
{
for (int i = 0; i <= ndevs; i++) {
bprintf(0, _T("resetting astrocde snd #%d\n"), i);
memset(&r[i], 0, sizeof(AstroReg));
}
}
void astrocde_snd_exit()
{
for (int i = 0; i <= ndevs; i++) {
stream[i].exit();
}
ndevs = 0;
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
#define d_min(a, b) (((a) < (b)) ? (a) : (b))
static void sound_stream_update(INT16 **streams, INT32 samples)
{
INT16 *dest = streams[0];
UINT16 noise_state;
UINT8 master_count;
UINT8 noise_clock;
/* load some locals */
master_count = r[stream_id].m_master_count;
noise_clock = r[stream_id].m_noise_clock;
noise_state = r[stream_id].m_noise_state;
/* loop over samples */
int samples_this_time;
// constexpr stream_buffer::sample_t sample_scale = 1.0f / 60.0f;
for (int sampindex = 0; sampindex < samples; sampindex += samples_this_time)
{
INT32 cursample = 0;
/* compute the number of cycles until the next master oscillator reset */
/* or until the next noise boundary */
samples_this_time = d_min(samples - sampindex, 256 - master_count);
samples_this_time = d_min(samples_this_time, 64 - noise_clock);
/* sum the output of the tone generators */
if (r[stream_id].m_a_state)
cursample += r[stream_id].m_reg[6] & 0x0f;
if (r[stream_id].m_b_state)
cursample += r[stream_id].m_reg[6] >> 4;
if (r[stream_id].m_c_state)
cursample += r[stream_id].m_reg[5] & 0x0f;
/* add in the noise if it is enabled, based on the top bit of the LFSR */
if ((r[stream_id].m_reg[5] & 0x20) && (noise_state & 0x4000))
cursample += r[stream_id].m_reg[7] >> 4;
/* scale to max and output */
cursample = cursample * 0x7fff / 60;
for (int i = 0; i < samples_this_time; i++)
*dest++ = cursample;
/* clock the noise; a 2-bit counter clocks a 4-bit counter which clocks the LFSR */
noise_clock += samples_this_time;
if (noise_clock >= 64)
{
/* update the noise state; this is a 15-bit LFSR with feedback from */
/* the XOR of the top two bits */
noise_state = (noise_state << 1) | (~((noise_state >> 14) ^ (noise_state >> 13)) & 1);
noise_clock -= 64;
/* the same clock also controls the vibrato clock, which is a 13-bit counter */
r[stream_id].m_vibrato_clock++;
}
/* clock the master oscillator; this is an 8-bit up counter */
master_count += samples_this_time;
if (master_count == 0)
{
/* reload based on mux value -- the value from the register is negative logic */
master_count = ~r[stream_id].m_reg[0];
/* mux value 0 means reload based on the vibrato control */
if ((r[stream_id].m_reg[5] & 0x10) == 0)
{
/* vibrato speed (register 4 bits 6-7) selects one of the top 4 bits */
/* of the 13-bit vibrato clock to use (0=highest freq, 3=lowest) */
if (!((r[stream_id].m_vibrato_clock >> (r[stream_id].m_reg[4] >> 6)) & 0x0200))
{
/* if the bit is clear, we add the vibrato volume to the counter */
master_count += r[stream_id].m_reg[4] & 0x3f;
}
}
/* mux value 1 means reload based on the noise control */
else
{
/* the top 8 bits of the noise LFSR are ANDed with the noise volume */
/* register and added to the count */
master_count += m_bitswap[(noise_state >> 7) & 0xff] & r[stream_id].m_reg[7];
}
/* clock tone A */
if (++r[stream_id].m_a_count == 0)
{
r[stream_id].m_a_state ^= 1;
r[stream_id].m_a_count = ~r[stream_id].m_reg[1];
}
/* clock tone B */
if (++r[stream_id].m_b_count == 0)
{
r[stream_id].m_b_state ^= 1;
r[stream_id].m_b_count = ~r[stream_id].m_reg[2];
}
/* clock tone C */
if (++r[stream_id].m_c_count == 0)
{
r[stream_id].m_c_state ^= 1;
r[stream_id].m_c_count = ~r[stream_id].m_reg[3];
}
}
}
/* put back the locals */
r[stream_id].m_master_count = master_count;
r[stream_id].m_noise_clock = noise_clock;
r[stream_id].m_noise_state = noise_state;
}
/*************************************
*
* Sound write accessors
*
*************************************/
void astrocde_snd_update(INT16 *output, INT32 samples_len)
{
if (samples_len != nBurnSoundLen) {
bprintf(0, _T("astrocde_snd_update(): once per frame, please!\n"));
return;
}
for (int i = 0; i <= ndevs; i++) {
stream_id = i;
stream[i].render(output, samples_len);
}
}
void astrocde_snd_set_buffered(INT32 (*pCPUCyclesCB)(), INT32 nCPUMhz)
{
for (int i = 0; i <= ndevs; i++) {
stream_id = i;
stream[i].set_buffered(pCPUCyclesCB, nCPUMhz);
}
}
void astrocde_snd_set_volume(double vol)
{
for (int i = 0; i <= ndevs; i++) {
stream[i].set_volume(vol);
}
}
void astrocde_snd_scan(INT32 nAction, INT32 *pnMin)
{
if (nAction & ACB_DRIVER_DATA) {
for (int i = 0; i <= ndevs; i++) {
SCAN_VAR(r[i]);
}
}
}
void astrocde_snd_write(INT32 dev, INT32 offset, UINT8 data)
{
if ((offset & 8) != 0)
offset = (offset >> 8) & 7;
else
offset &= 7;
/* update */
stream_id = dev;
stream[dev].update();
/* stash the new register value */
r[dev].m_reg[offset & 7] = data;
}

View File

@ -0,0 +1,8 @@
void astrocde_snd_init(INT32 ndev, INT32 route);
void astrocde_snd_reset();
void astrocde_snd_exit();
void astrocde_snd_scan(INT32 nAction, INT32 *pnMin);
void astrocde_snd_update(INT16 *output, INT32 samples_len);
void astrocde_snd_set_buffered(INT32 (*pCPUCyclesCB)(), INT32 nCPUMhz);
void astrocde_snd_set_volume(double vol);
void astrocde_snd_write(INT32 dev, INT32 offset, UINT8 data);