add driver and soundcustom for asteroids and asteroids deluxe

This commit is contained in:
dinkc64 2018-08-12 03:25:18 +00:00
parent b3c497f81b
commit 6302fa344b
4 changed files with 1285 additions and 2 deletions

View File

@ -44,7 +44,7 @@ drvsrc = d_dodonpachi.o d_donpachi.o d_esprade.o d_feversos.o d_gaia.o d_guwang
d_batrider.o d_batsugun.o d_battleg.o d_bbakraid.o d_dogyuun.o d_enmadaio.o d_fixeight.o d_ghox.o d_kbash.o d_kbash2.o d_mahoudai.o d_pipibibs.o d_shippumd.o d_slapfght.o \
d_snowbro2.o d_tekipaki.o d_toaplan1.o d_truxton2.o d_vfive.o d_wardner.o \
\
d_4enraya.o d_1942.o d_1943.o d_aeroboto.o d_alinvade.o d_alpha68k.o d_alpha68k1.o d_alpha68k2.o d_ambush.o d_amspdwy.o d_arabian.o d_armedf.o d_atetris.o d_aztarac.o d_bagman.o \
d_4enraya.o d_1942.o d_1943.o d_aeroboto.o d_alinvade.o d_alpha68k.o d_alpha68k1.o d_alpha68k2.o d_ambush.o d_amspdwy.o d_arabian.o d_armedf.o d_asteroids.o d_atetris.o d_aztarac.o d_bagman.o \
d_baraduke.o d_bbusters.o d_battlane.o d_beaminv.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_brkthru.o d_cabal.o \
d_calorie.o d_canyon.o d_capbowl.o d_carjmbre.o d_cclimber.o d_cheekyms.o d_chinagat.o d_citycon.o d_cloak.o d_clshroad.o d_commando.o d_cop01.o d_copsnrob.o d_cybertnk.o \
d_dacholer.o d_dday.o d_ddayjlc.o d_ddragon.o d_djboy.o d_dkong.o d_docastle.o d_dogfgt.o d_dorachan.o d_dribling.o d_drmicro.o d_dynduke.o d_efdt.o d_epos.o d_espial.o d_exedexes.o d_fantland.o \
@ -95,7 +95,7 @@ depobj = burn.o burn_gun.o burn_led.o burn_shift.o burn_memory.o burn_pal.o bur
mermaid.o namco_c45.o namcoio.o pandora.o resnet.o seibusnd.o sknsspr.o slapstic.o st0020.o t5182.o timekpr.o tms34061.o v3021.o vdc.o tms9928a.o \
watchdog.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 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_ymf278b.o c6280.o dac.o es5506.o es8712.o flower.o flt_rc.o fm.o fmopl.o ym2612.o gaelco.o hc55516.o ics2115.o iremga20.o \
k005289.o k007232.o k051649.o k053260.o k054539.o msm5205.o msm5232.o msm6295.o namco_snd.o c140.o nes_apu.o tms5110.o tms5220.o tms36xx.o phoenixsound.o \
pleiadssound.o pokey.o rf5c68.o saa1099.o samples.o segapcm.o sn76477.o sn76496.o upd7759.o vlm5030.o wiping.o x1010.o ym2151.o ym2413.o \

View File

@ -0,0 +1,698 @@
// FB Alpha 1942 driver module
// Based on MAME driver by Brad Oliver, Bernd Wiebelt, Allard van der Bas
// todo:
// add clones
// add lunar lander hw?
#include "tiles_generic.h"
#include "m6502_intf.h"
#include "watchdog.h"
#include "bitswap.h"
#include "avgdvg.h"
#include "vector.h"
#include "pokey.h"
#include "asteroids.h"
#include "earom.h"
static UINT8 *AllMem;
static UINT8 *MemEnd;
static UINT8 *AllRam;
static UINT8 *RamEnd;
static UINT8 *DrvM6502ROM;
static UINT8 *DrvDgvPROM;
static UINT8 *DrvM6502RAM;
static UINT8 *DrvVectorRAM;
static UINT32 *DrvPalette;
static UINT8 DrvRecalc;
static UINT8 bankdata;
static UINT8 DrvJoy1[8];
static UINT8 DrvJoy2[8];
static UINT8 DrvDips[2];
static UINT8 DrvInputs[2];
static UINT8 DrvReset;
static INT32 avgdone = 0; // already ran avgdvg this frame.
static INT32 avgOK = 0; // ok to run avgdvg?
static INT32 astdelux = 0;
static struct BurnInputInfo AsteroidInputList[] = {
{"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" },
{"P1 Start", BIT_DIGITAL, DrvJoy2 + 3, "p1 start" },
{"P1 Left", BIT_DIGITAL, DrvJoy2 + 7, "p1 left" },
{"P1 Right", BIT_DIGITAL, DrvJoy2 + 6, "p1 right" },
{"P1 Fire", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" },
{"P1 Thrust", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" },
{"P1 Hyperspace", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 3" },
{"Reset", BIT_DIGITAL, &DrvReset, "reset" },
{"Diag Step", BIT_DIGITAL, DrvJoy1 + 5, "service2" },
{"Service", BIT_DIGITAL, DrvJoy1 + 7, "service" },
{"Tilt", BIT_DIGITAL, DrvJoy1 + 6, "tilt" },
{"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
};
STDINPUTINFO(Asteroid)
static struct BurnInputInfo AstdeluxInputList[] = {
{"P1 Coin", BIT_DIGITAL, DrvJoy2 + 0, "p1 coin" },
{"P1 Start", BIT_DIGITAL, DrvJoy2 + 3, "p1 start" },
{"P1 Left", BIT_DIGITAL, DrvJoy2 + 7, "p1 left" },
{"P1 Right", BIT_DIGITAL, DrvJoy2 + 6, "p1 right" },
{"P1 Fire", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" },
{"P1 Thrust", BIT_DIGITAL, DrvJoy2 + 5, "p1 fire 2" },
{"P1 Sheild", BIT_DIGITAL, DrvJoy1 + 3, "p1 fire 3" },
{"Reset", BIT_DIGITAL, &DrvReset, "reset" },
{"Diag Step", BIT_DIGITAL, DrvJoy1 + 5, "service2" },
{"Service", BIT_DIGITAL, DrvJoy1 + 7, "service" },
{"Tilt", BIT_DIGITAL, DrvJoy1 + 6, "tilt" },
{"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
{"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" }, // astdelux
};
STDINPUTINFO(Astdelux)
static struct BurnDIPInfo AsteroidDIPList[]=
{
{0x0b, 0xff, 0xff, 0x84, NULL },
{0 , 0xfe, 0 , 4, "Language" },
{0x0b, 0x01, 0x03, 0x00, "English" },
{0x0b, 0x01, 0x03, 0x01, "German" },
{0x0b, 0x01, 0x03, 0x02, "French" },
{0x0b, 0x01, 0x03, 0x03, "Spanish" },
{0 , 0xfe, 0 , 2, "Lives" },
{0x0b, 0x01, 0x04, 0x04, "3" },
{0x0b, 0x01, 0x04, 0x00, "4" },
#if 0
{0 , 0xfe, 0 , 2, "Center Mech" },
{0x0b, 0x01, 0x08, 0x00, "X 1" },
{0x0b, 0x01, 0x08, 0x08, "X 2" },
{0 , 0xfe, 0 , 4, "Right Mech" },
{0x0b, 0x01, 0x30, 0x00, "X 1" },
{0x0b, 0x01, 0x30, 0x10, "X 4" },
{0x0b, 0x01, 0x30, 0x20, "X 5" },
{0x0b, 0x01, 0x30, 0x30, "X 6" },
#endif
{0 , 0xfe, 0 , 4, "Coinage" },
{0x0b, 0x01, 0xc0, 0xc0, "2 Coins 1 Credits" },
{0x0b, 0x01, 0xc0, 0x80, "1 Coin 1 Credits" },
{0x0b, 0x01, 0xc0, 0x40, "1 Coin 2 Credits" },
{0x0b, 0x01, 0xc0, 0x00, "Free Play" },
};
STDDIPINFO(Asteroid)
static struct BurnDIPInfo AstdeluxDIPList[]=
{
{0x0b, 0xff, 0xff, 0x00, NULL },
{0x0c, 0xff, 0xff, 0xfd, NULL },
{0 , 0xfe, 0 , 4, "Language" },
{0x0b, 0x01, 0x03, 0x00, "English" },
{0x0b, 0x01, 0x03, 0x01, "German" },
{0x0b, 0x01, 0x03, 0x02, "French" },
{0x0b, 0x01, 0x03, 0x03, "Spanish" },
{0 , 0xfe, 0 , 4, "Lives" },
{0x0b, 0x01, 0x0c, 0x00, "2-4" },
{0x0b, 0x01, 0x0c, 0x04, "3-5" },
{0x0b, 0x01, 0x0c, 0x08, "4-6" },
{0x0b, 0x01, 0x0c, 0x0c, "5-7" },
{0 , 0xfe, 0 , 2, "Minimum Plays" },
{0x0b, 0x01, 0x10, 0x00, "1" },
{0x0b, 0x01, 0x10, 0x10, "2" },
{0 , 0xfe, 0 , 2, "Difficulty" },
{0x0b, 0x01, 0x20, 0x00, "Hard" },
{0x0b, 0x01, 0x20, 0x20, "Easy" },
{0 , 0xfe, 0 , 4, "Bonus Life" },
{0x0b, 0x01, 0xc0, 0x00, "10000" },
{0x0b, 0x01, 0xc0, 0x40, "12000" },
{0x0b, 0x01, 0xc0, 0x80, "15000" },
{0x0b, 0x01, 0xc0, 0xc0, "None" },
{0 , 0xfe, 0 , 4, "Coinage" },
{0x0c, 0x01, 0x03, 0x00, "2 Coins 1 Credits" },
{0x0c, 0x01, 0x03, 0x01, "1 Coin 1 Credits" },
{0x0c, 0x01, 0x03, 0x02, "1 Coin 2 Credits" },
{0x0c, 0x01, 0x03, 0x03, "Free Play" },
{0 , 0xfe, 0 , 4, "Right Coin" },
{0x0c, 0x01, 0x0c, 0x00, "X 6" },
{0x0c, 0x01, 0x0c, 0x04, "X 5" },
{0x0c, 0x01, 0x0c, 0x08, "X 4" },
{0x0c, 0x01, 0x0c, 0x0c, "X 1" },
{0 , 0xfe, 0 , 2, "Center Coin" },
{0x0c, 0x01, 0x10, 0x00, "X 2" },
{0x0c, 0x01, 0x10, 0x10, "X 1" },
{0 , 0xfe, 0 , 5, "Bonus Coins" },
{0x0c, 0x01, 0xe0, 0x60, "1 Coin Each 5 Coins" },
{0x0c, 0x01, 0xe0, 0x80, "2 Coins Each 4 Coins" },
{0x0c, 0x01, 0xe0, 0xa0, "1 Coin Each 4 Coins" },
{0x0c, 0x01, 0xe0, 0xc0, "1 Coin Each 2 Coins" },
{0x0c, 0x01, 0xe0, 0xe0, "None" },
};
STDDIPINFO(Astdelux)
static void bankswitch(INT32 data)
{
bankdata = data;
INT32 bank = (astdelux) ? (data >> 7) & 1 : (data >> 2) & 1;
if (bank == 0) { // tih... timmy??
M6502MapMemory(DrvM6502RAM + 0x200, 0x0200, 0x02ff, MAP_RAM);
M6502MapMemory(DrvM6502RAM + 0x300, 0x0300, 0x03ff, MAP_RAM);
} else {
M6502MapMemory(DrvM6502RAM + 0x300, 0x0200, 0x02ff, MAP_RAM);
M6502MapMemory(DrvM6502RAM + 0x200, 0x0300, 0x03ff, MAP_RAM);
}
}
static void asteroid_write(UINT16 address, UINT8 data)
{
switch (address)
{
case 0x3000:
avgdvg_go();
avgdone = 1;
avgOK = 1;
return;
case 0x3200:
bankswitch(data);
return;
case 0x3400:
BurnWatchogWrite();
return;
case 0x3600:
asteroid_explode_w(data);
return;
case 0x3a00:
asteroid_thump_w(data);
return;
case 0x3c00:
case 0x3c01:
case 0x3c02:
case 0x3c03:
case 0x3c04:
case 0x3c05:
asteroid_sounds_w(address&7, data);
return;
case 0x3e00:
// noise_reset_w
return;
}
}
static void astdelux_write(UINT16 address, UINT8 data)
{
if (address >= 0x2c00 && address <= 0x2c0f) {
pokey1_w(address & 0x0f, data);
return;
}
if (address >= 0x3200 && address <= 0x323f) {
earom_write(address & 0x3f, data);
return;
}
switch (address)
{
case 0x3000:
avgdvg_go();
avgdone = 1;
avgOK = 1;
return;
case 0x3c04:
bankswitch(data);
return;
case 0x3400:
BurnWatchogWrite();
return;
case 0x3600:
asteroid_explode_w(data);
return;
case 0x3a00:
earom_ctrl_write(address, data);
return;
case 0x3c03:
astdelux_sounds_w(data);
return;
case 0x3e00:
// noise_reset_w
return;
}
}
static UINT8 asteroid_read(UINT16 address)
{
switch (address & ~7)
{
case 0x2000:
{
UINT8 ret = (DrvInputs[0] & ~0x06);
ret |= ((M6502TotalCycles() & 0x100) ? 0x02 : 0);
ret |= (avgdvg_done() ? 0x00 : 0x04);
return (ret & (1 << (address & 7))) ? 0x80 : 0x7f;
}
case 0x2400:
return (DrvInputs[1] & (1 << (address & 7))) ? 0x80 : 0x7f;
}
switch (address & ~3)
{
case 0x2800:
return 0xfc | ((DrvDips[0] >> ((~address & 3) * 2)) & 3);;
}
return 0;
}
static UINT8 astdelux_read(UINT16 address)
{
if (address >= 0x2c00 && address <= 0x2c0f) {
return pokey1_r(address & 0x0f);
}
if (address >= 0x2c40 && address <= 0x2c7f) {
return earom_read(address);
}
switch (address & ~7)
{
case 0x2000:
{
UINT8 ret = (DrvInputs[0] & ~0x06);
ret |= ((M6502TotalCycles() & 0x100) ? 0x02 : 0);
ret |= (avgdvg_done() ? 0x00 : 0x04);
return (ret & (1 << (address & 7))) ? 0x80 : 0x7f;
}
case 0x2400:
return (DrvInputs[1] & (1 << (address & 7))) ? 0x80 : 0x7f;
}
switch (address & ~3)
{
case 0x2800:
return 0xfc | ((DrvDips[0] >> ((~address & 3) * 2)) & 3);;
}
return 0;
}
static INT32 allpot_read(INT32 offset)
{
return DrvDips[1];
}
static INT32 DrvDoReset(INT32 clear_mem)
{
if (clear_mem) {
memset (AllRam, 0, RamEnd - AllRam);
}
M6502Open(0);
bankswitch(0);
M6502Reset();
M6502Close();
BurnWatchdogReset();
vector_reset();
avgdvg_reset();
earom_reset();
avgdone = 0;
avgOK = 0;
return 0;
}
static INT32 MemIndex()
{
UINT8 *Next; Next = AllMem;
DrvM6502ROM = Next; Next += 0x010000;
DrvDgvPROM = Next; Next += 0x000100;
DrvPalette = (UINT32*)Next; Next += 0x2 * 256 * sizeof(UINT32);
AllRam = Next;
DrvM6502RAM = Next; Next += 0x000800;
RamEnd = Next;
MemEnd = Next;
DrvVectorRAM = DrvM6502ROM + 0x4000;
return 0;
}
static INT32 DrvInit()
{
AllMem = NULL;
MemIndex();
INT32 nLen = MemEnd - (UINT8 *)0;
if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
memset(AllMem, 0, nLen);
MemIndex();
{
if (BurnLoadRom(DrvM6502ROM + 0x6800, 0, 1)) return 1;
if (BurnLoadRom(DrvM6502ROM + 0x7000, 1, 1)) return 1;
if (BurnLoadRom(DrvM6502ROM + 0x7800, 2, 1)) return 1;
if (BurnLoadRom(DrvM6502ROM + 0x5000, 3, 1)) return 1;
if (BurnLoadRom(DrvDgvPROM + 0x0000, 4, 1)) return 1;
}
if (DrvVectorRAM != DrvM6502ROM+0x4000) bprintf(0, _T("VectorRAM not hooked up right.\n"));
M6502Init(0, TYPE_M6502);
M6502Open(0);
M6502SetAddressMask(0x7fff);
M6502MapMemory(DrvM6502RAM, 0x0000, 0x01ff, MAP_RAM);
bankswitch(0); // 0x0200, 0x03ff
M6502MapMemory(DrvVectorRAM, 0x4000, 0x47ff, MAP_RAM);
M6502MapMemory(DrvM6502ROM + 0x5000, 0x5000, 0x57ff, MAP_ROM);
M6502MapMemory(DrvM6502ROM + 0x6800, 0x6800, 0x7fff, MAP_ROM);
M6502SetWriteHandler(asteroid_write);
M6502SetReadHandler(asteroid_read);
M6502Close();
BurnWatchdogInit(DrvDoReset, 180);
vector_init();
vector_set_scale(1044, 788);
vector_set_offsets(11, 119);
dvg_asteroids_start(DrvVectorRAM);
asteroid_sound_init();
DrvDoReset(1);
return 0;
}
static INT32 AstdeluxInit()
{
AllMem = NULL;
MemIndex();
INT32 nLen = MemEnd - (UINT8 *)0;
if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
memset(AllMem, 0, nLen);
MemIndex();
{
if (BurnLoadRom(DrvM6502ROM + 0x6000, 0, 1)) return 1;
if (BurnLoadRom(DrvM6502ROM + 0x6800, 1, 1)) return 1;
if (BurnLoadRom(DrvM6502ROM + 0x7000, 2, 1)) return 1;
if (BurnLoadRom(DrvM6502ROM + 0x7800, 3, 1)) return 1;
if (BurnLoadRom(DrvM6502ROM + 0x4800, 4, 1)) return 1;
if (BurnLoadRom(DrvM6502ROM + 0x5000, 5, 1)) return 1;
if (BurnLoadRom(DrvDgvPROM + 0x0000, 6, 1)) return 1;
}
if (DrvVectorRAM != DrvM6502ROM+0x4000) bprintf(0, _T("VectorRAM not hooked up right.\n"));
M6502Init(0, TYPE_M6502);
M6502Open(0);
M6502SetAddressMask(0x7fff);
M6502MapMemory(DrvM6502RAM, 0x0000, 0x01ff, MAP_RAM);
bankswitch(0); // 0x0200, 0x03ff
M6502MapMemory(DrvVectorRAM, 0x4000, 0x47ff, MAP_RAM);
M6502MapMemory(DrvM6502ROM + 0x4800, 0x4800, 0x57ff, MAP_ROM); // Vector ROM
M6502MapMemory(DrvM6502ROM + 0x6000, 0x6000, 0x7fff, MAP_ROM); // Main ROM
M6502SetWriteHandler(astdelux_write);
M6502SetReadHandler(astdelux_read);
M6502Close();
BurnWatchdogInit(DrvDoReset, 180);
vector_init();
vector_set_scale(1044, 788);
vector_set_offsets(11, 119);
dvg_asteroids_start(DrvVectorRAM);
asteroid_sound_init();
astdelux = 1;
earom_init();
PokeyInit(12096000/8, 1, 2.40, 1);
PokeySetTotalCyclesCB(M6502TotalCycles);
PokeyAllPotCallback(0, allpot_read);
DrvDoReset(1);
return 0;
}
static INT32 DrvExit()
{
M6502Exit();
vector_exit();
asteroid_sound_exit();
BurnFree(AllMem);
if (astdelux) {
earom_exit();
PokeyExit();
}
astdelux = 0;
return 0;
}
static void DrvPaletteInit()
{
UINT32 colors[2] = { 0x000000, 0xffffff };
for (INT32 i = 0; i < 0x2; i++) // color
{
for (INT32 j = 0; j < 256; j++) // intensity
{
int r = (colors[i] >> 16) & 0xff;
int g = (colors[i] >> 8) & 0xff;
int b = (colors[i] >> 0) & 0xff;
r = (r * j) / 255;
g = (g * j) / 255;
b = (b * j) / 255;
DrvPalette[i * 256 + j] = (r << 16) | (g << 8) | b; // must be 32bit palette! -dink (see vector.cpp)
}
}
}
static INT32 DrvDraw()
{
if (DrvRecalc) {
DrvPaletteInit();
DrvRecalc = 0;
}
DrvPaletteInit();
if (avgdone == 0 && avgOK) avgdvg_go(); // only if we didn't update this frame
draw_vector(DrvPalette);
return 0;
}
static INT32 DrvFrame()
{
BurnWatchdogUpdate();
if (DrvReset) {
DrvDoReset(1);
}
{
memset (DrvInputs, 0, 2);
for (INT32 i = 0; i < 8; i++) {
DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
}
}
INT32 nInterleave = 256; // nmi is 4x per frame!
INT32 nCyclesTotal = (1512000 * 100) / 6152; // 61.5234375 hz
INT32 nCyclesDone = 0;
INT32 nSoundBufferPos = 0;
avgdone = 0;
M6502Open(0);
for (INT32 i = 0; i < nInterleave; i++)
{
nCyclesDone += M6502Run(nCyclesTotal / nInterleave);
if ((i % 64) == 63 && (DrvInputs[0] & 0x80) == 0)
M6502SetIRQLine(0x20, CPU_IRQSTATUS_AUTO);
// Render Sound Segment
if (pBurnSoundOut && i&1) {
INT32 nSegmentLength = nBurnSoundLen / (nInterleave/2);
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
if (astdelux)
astdelux_sound_update(pSoundBuf, nSegmentLength);
else
asteroid_sound_update(pSoundBuf, nSegmentLength);
nSoundBufferPos += nSegmentLength;
}
}
M6502Close();
// Make sure the buffer is entirely filled.
if (pBurnSoundOut) {
INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
if (nSegmentLength) {
if (astdelux)
astdelux_sound_update(pSoundBuf, nSegmentLength);
else
asteroid_sound_update(pSoundBuf, nSegmentLength);
}
if (astdelux)
pokey_update(0, pBurnSoundOut, nBurnSoundLen);
}
if (pBurnDraw) {
DrvDraw();
}
return 0;
}
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
{
struct BurnArea ba;
if (pnMin) {
*pnMin = 0x029722;
}
if (nAction & ACB_VOLATILE) {
memset(&ba, 0, sizeof(ba));
ba.Data = AllRam;
ba.nLen = RamEnd - AllRam;
ba.szName = "All Ram";
BurnAcb(&ba);
memset(&ba, 0, sizeof(ba));
ba.Data = DrvVectorRAM;
ba.nLen = 0x1000;
ba.szName = "Vector Ram";
BurnAcb(&ba);
M6502Scan(nAction);
BurnWatchdogScan(nAction);
if (astdelux)
pokey_scan(nAction, pnMin);
}
if (astdelux)
earom_scan(nAction, pnMin); // here.
return 0;
}
// Asteroids (rev 4)
static struct BurnRomInfo asteroidRomDesc[] = {
{ "035145-04e.ef2", 0x0800, 0xb503eaf7, 1 | BRF_PRG | BRF_ESS }, // 0 M6502 Code
{ "035144-04e.h2", 0x0800, 0x25233192, 1 | BRF_PRG | BRF_ESS }, // 1
{ "035143-02.j2", 0x0800, 0x312caa02, 1 | BRF_PRG | BRF_ESS }, // 2
{ "035127-02.np3", 0x0800, 0x8b71fd9e, 1 | BRF_PRG | BRF_ESS }, // 3 Vector ROM
{ "034602-01.c8", 0x0100, 0x97953db8, 2 | BRF_GRA }, // 4 DVG PROM
};
STD_ROM_PICK(asteroid)
STD_ROM_FN(asteroid)
struct BurnDriver BurnDrvAsteroid = {
"asteroid", NULL, NULL, NULL, "1979",
"Asteroids (rev 4)\0", NULL, "Atari", "Miscellaneous",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0,
NULL, asteroidRomInfo, asteroidRomName, NULL, NULL, AsteroidInputInfo, AsteroidDIPInfo,
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 2 * 256,
600, 500, 4, 3
};
// Asteroids Deluxe (rev 3)
static struct BurnRomInfo astdeluxRomDesc[] = {
{ "036430-02.d1", 0x0800, 0xa4d7a525, 1 | BRF_PRG | BRF_ESS }, // 0 M6502 Code
{ "036431-02.ef1", 0x0800, 0xd4004aae, 1 | BRF_PRG | BRF_ESS }, // 1
{ "036432-02.fh1", 0x0800, 0x6d720c41, 1 | BRF_PRG | BRF_ESS }, // 2
{ "036433-03.j1", 0x0800, 0x0dcc0be6, 1 | BRF_PRG | BRF_ESS }, // 3
{ "036800-02.r2", 0x0800, 0xbb8cabe1, 1 | BRF_PRG | BRF_ESS }, // 4 Vector ROM
{ "036799-01.np2", 0x0800, 0x7d511572, 1 | BRF_PRG | BRF_ESS }, // 5 Vector ROM 2/2
{ "034602-01.c8", 0x0100, 0x97953db8, 2 | BRF_GRA }, // 6 DVG PROM
};
STD_ROM_PICK(astdelux)
STD_ROM_FN(astdelux)
struct BurnDriver BurnDrvAstdelux = {
"astdelux", NULL, NULL, NULL, "1980",
"Asteroids Deluxe (rev 3)\0", NULL, "Atari", "Miscellaneous",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0,
NULL, astdeluxRomInfo, astdeluxRomName, NULL, NULL, AstdeluxInputInfo, AstdeluxDIPInfo,
AstdeluxInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 2 * 256,
600, 500, 4, 3
};

575
src/burn/snd/asteroids.cpp Normal file
View File

@ -0,0 +1,575 @@
/*****************************************************************************
*
* A (partially wrong) try to emulate Asteroid's analog sound
* It's getting better but is still imperfect :/
* If you have ideas, corrections, suggestions contact Juergen
* Buchmueller <pullmoll@t-online.de>
*
* Known issues (TODO):
* - find out if/why the samples are 'damped', I don't see no
* low pass filter in the sound output, but the samples sound
* like there should be one. Maybe in the amplifier..
* - better (accurate) way to emulate the low pass on the thrust sound?
* - verify the thump_frequency calculation. It's only an approximation now
* - the nastiest piece of the circuit is the saucer sound IMO
* the circuits are almost equal, but there are some strange looking
* things like the direct coupled op-amps and transistors and I can't
* calculate the true resistance and thus voltage at the control
* input (5) of the NE555s.
* - saucer sound is not easy either and the calculations might be off, still.
*
*****************************************************************************/
#include <math.h>
#include "burnint.h"
#include "asteroids.h"
#define VMAX 32767
#define VMIN 0
#define SAUCEREN 0
#define SAUCRFIREEN 1
#define SAUCERSEL 2
#define THRUSTEN 3
#define SHIPFIREEN 4
#define LIFEEN 5
#define EXPITCH0 (1<<6)
#define EXPITCH1 (1<<7)
#define EXPAUDSHIFT 2
#define EXPAUDMASK (0x0f<<EXPAUDSHIFT)
#define NE555_T1(Ra,Rb,C) (VMAX*2/3/(0.639*((Ra)+(Rb))*(C)))
#define NE555_T2(Ra,Rb,C) (VMAX*2/3/(0.639*(Rb)*(C)))
#define NE555_F(Ra,Rb,C) (1.44/(((Ra)+2*(Rb))*(C)))
static INT32 explosion_latch;
static INT32 thump_latch;
static INT32 sound_latch[8];
static INT32 polynome;
static INT32 thump_frequency;
static INT16 *discharge; // look up table
static INT16 vol_explosion[16]; // look up table
#define EXP(charge,n) (charge ? 0x7fff - discharge[0x7fff-n] : discharge[n])
#define INLINE static inline
struct asteroid_sound {
INT32 explosion_counter;
INT32 explosion_sample_counter;
INT32 explosion_out;
INT32 thrust_counter;
INT32 thrust_out;
INT32 thrust_amp;
INT32 thump_counter;
INT32 thump_out;
INT32 saucer_vco, saucer_vco_charge, saucer_vco_counter;
INT32 saucer_out, saucer_counter;
INT32 saucerfire_vco, saucerfire_vco_counter;
INT32 saucerfire_amp, saucerfire_amp_counter;
INT32 saucerfire_out, saucerfire_counter;
INT32 shipfire_vco, shipfire_vco_counter;
INT32 shipfire_amp, shipfire_amp_counter;
INT32 shipfire_out, shipfire_counter;
INT32 life_counter, life_out;
};
static asteroid_sound asound;
INLINE INT32 explosion(INT32 samplerate)
{
//static INT32 counter, sample_counter;
//static INT32 out;
asound.explosion_counter -= 12000;
while( asound.explosion_counter <= 0 )
{
asound.explosion_counter += samplerate;
if( ((polynome & 0x4000) == 0) == ((polynome & 0x0040) == 0) )
polynome = (polynome << 1) | 1;
else
polynome <<= 1;
if( ++asound.explosion_sample_counter == 16 )
{
asound.explosion_sample_counter = 0;
if( explosion_latch & EXPITCH0 )
asound.explosion_sample_counter |= 2 + 8;
else
asound.explosion_sample_counter |= 4;
if( explosion_latch & EXPITCH1 )
asound.explosion_sample_counter |= 1 + 8;
}
/* ripple count output is high? */
if( asound.explosion_sample_counter == 15 )
asound.explosion_out = polynome & 1;
}
if( asound.explosion_out )
return vol_explosion[(explosion_latch & EXPAUDMASK) >> EXPAUDSHIFT];
return 0;
}
INLINE INT32 thrust(INT32 samplerate)
{
//static INT32 counter, out, amp;
if( sound_latch[THRUSTEN] )
{
/* SHPSND filter */
asound.thrust_counter -= 110;
while( asound.thrust_counter <= 0 )
{
asound.thrust_counter += samplerate;
asound.thrust_out = polynome & 1;
}
if( asound.thrust_out )
{
if( asound.thrust_amp < VMAX )
asound.thrust_amp += (VMAX - asound.thrust_amp) * 32768 / 32 / samplerate + 1;
}
else
{
if( asound.thrust_amp > VMIN )
asound.thrust_amp -= asound.thrust_amp * 32768 / 32 / samplerate + 1;
}
return asound.thrust_amp;
} else {
// decay thrust amp for no clicks -dink
asound.thrust_amp *= (double)0.997;
return asound.thrust_amp;
}
return 0;
}
INLINE INT32 thump(INT32 samplerate)
{
//static INT32 counter, out;
if( thump_latch & 0x10 )
{
asound.thump_counter -= thump_frequency;
while( asound.thump_counter <= 0 )
{
asound.thump_counter += samplerate;
asound.thump_out ^= 1;
}
if( asound.thump_out )
return VMAX;
}
return 0;
}
INLINE INT32 saucer(INT32 samplerate)
{
//static INT32 vco, vco_charge, vco_counter; asound.saucer_
//static INT32 out, counter;
double v5;
/* saucer sound enabled ? */
if( sound_latch[SAUCEREN] )
{
/* NE555 setup as astable multivibrator:
* C = 10u, Ra = 5.6k, Rb = 10k
* or, with /SAUCERSEL being low:
* C = 10u, Ra = 5.6k, Rb = 6k (10k parallel with 15k)
*/
if( asound.saucer_vco_charge )
{
if( sound_latch[SAUCERSEL] )
asound.saucer_vco_counter -= NE555_T1(5600,10000,10e-6);
else
asound.saucer_vco_counter -= NE555_T1(5600,6000,10e-6);
if( asound.saucer_vco_counter <= 0 )
{
INT32 steps = (-asound.saucer_vco_counter / samplerate) + 1;
asound.saucer_vco_counter += steps * samplerate;
if( (asound.saucer_vco += steps) >= VMAX*2/3 )
{
asound.saucer_vco = VMAX*2/3;
asound.saucer_vco_charge = 0;
}
}
}
else
{
if( sound_latch[SAUCERSEL] )
asound.saucer_vco_counter -= NE555_T2(5600,10000,10e-6);
else
asound.saucer_vco_counter -= NE555_T2(5600,6000,10e-6);
if( asound.saucer_vco_counter <= 0 )
{
INT32 steps = (-asound.saucer_vco_counter / samplerate) + 1;
asound.saucer_vco_counter += steps * samplerate;
if( (asound.saucer_vco -= steps) <= VMAX*1/3 )
{
asound.saucer_vco = VMIN*1/3;
asound.saucer_vco_charge = 1;
}
}
}
/*
* NE566 voltage controlled oscillator
* Co = 0.047u, Ro = 10k
* to = 2.4 * (Vcc - V5) / (Ro * Co * Vcc)
*/
if( sound_latch[SAUCERSEL] )
v5 = 12.0 - 1.66 - 5.0 * EXP(asound.saucer_vco_charge,asound.saucer_vco) / 32768;
else
v5 = 11.3 - 1.66 - 5.0 * EXP(asound.saucer_vco_charge,asound.saucer_vco) / 32768;
asound.saucer_counter -= floor(2.4 * (12.0 - v5) / (10000 * 0.047e-6 * 12.0));
while( asound.saucer_counter <= 0 )
{
asound.saucer_counter += samplerate;
asound.saucer_out ^= 1;
}
if( asound.saucer_out )
return VMAX;
}
return 0;
}
INLINE INT32 saucerfire(INT32 samplerate)
{
//static INT32 vco, vco_counter;
//static INT32 amp, amp_counter;
//static INT32 out, counter;
if( sound_latch[SAUCRFIREEN] )
{
if( asound.saucerfire_vco < VMAX*12/5 )
{
/* charge C38 (10u) through R54 (10K) from 5V to 12V */
#define C38_CHARGE_TIME (VMAX)
asound.saucerfire_vco_counter -= C38_CHARGE_TIME;
while( asound.saucerfire_vco_counter <= 0 )
{
asound.saucerfire_vco_counter += samplerate;
if( ++asound.saucerfire_vco == VMAX*12/5 )
break;
}
}
if( asound.saucerfire_amp > VMIN )
{
/* discharge C39 (10u) through R58 (10K) and diode CR6,
* but only during the time the output of the NE555 is low.
*/
if( asound.saucerfire_out )
{
#define C39_DISCHARGE_TIME (int)(VMAX)
asound.saucerfire_amp_counter -= C39_DISCHARGE_TIME;
while( asound.saucerfire_amp_counter <= 0 )
{
asound.saucerfire_amp_counter += samplerate;
if( --asound.saucerfire_amp == VMIN )
break;
}
}
}
if( asound.saucerfire_out )
{
/* C35 = 1u, Ra = 3.3k, Rb = 680
* discharge = 0.693 * 680 * 1e-6 = 4.7124e-4 -> 2122 Hz
*/
asound.saucerfire_counter -= 2122;
if( asound.saucerfire_counter <= 0 )
{
INT32 n = -asound.saucerfire_counter / samplerate + 1;
asound.saucerfire_counter += n * samplerate;
asound.saucerfire_out = 0;
}
}
else
{
/* C35 = 1u, Ra = 3.3k, Rb = 680
* charge 0.693 * (3300+680) * 1e-6 = 2.75814e-3 -> 363Hz
*/
asound.saucerfire_counter -= 363 * 2 * (VMAX*12/5-asound.saucerfire_vco) / 32768;
if( asound.saucerfire_counter <= 0 )
{
INT32 n = -asound.saucerfire_counter / samplerate + 1;
asound.saucerfire_counter += n * samplerate;
asound.saucerfire_out = 1;
}
}
if( asound.saucerfire_out )
return asound.saucerfire_amp;
}
else
{
/* charge C38 and C39 */
asound.saucerfire_amp = VMAX;
asound.saucerfire_vco = VMAX;
}
return 0;
}
INLINE INT32 shipfire(INT32 samplerate)
{
//static INT32 vco, vco_counter;
//static INT32 amp, amp_counter;
//static INT32 out, counter;
if( sound_latch[SHIPFIREEN] )
{
if( asound.shipfire_vco < VMAX*12/5 )
{
/* charge C47 (1u) through R52 (33K) and Q3 from 5V to 12V */
#define C47_CHARGE_TIME (VMAX * 3)
asound.shipfire_vco_counter -= C47_CHARGE_TIME;
while( asound.shipfire_vco_counter <= 0 )
{
asound.shipfire_vco_counter += samplerate;
if( ++asound.shipfire_vco == VMAX*12/5 )
break;
}
}
if( asound.shipfire_amp > VMIN )
{
/* discharge C48 (10u) through R66 (2.7K) and CR8,
* but only while the output of theNE555 is low.
*/
if( asound.shipfire_out )
{
#define C48_DISCHARGE_TIME (VMAX * 3)
asound.shipfire_amp_counter -= C48_DISCHARGE_TIME;
while( asound.shipfire_amp_counter <= 0 )
{
asound.shipfire_amp_counter += samplerate;
if( --asound.shipfire_amp == VMIN )
break;
}
}
}
if( asound.shipfire_out )
{
/* C50 = 1u, Ra = 3.3k, Rb = 680
* discharge = 0.693 * 680 * 1e-6 = 4.7124e-4 -> 2122 Hz
*/
asound.shipfire_counter -= 2122;
if( asound.shipfire_counter <= 0 )
{
INT32 n = -asound.shipfire_counter / samplerate + 1;
asound.shipfire_counter += n * samplerate;
asound.shipfire_out = 0;
}
}
else
{
/* C50 = 1u, Ra = R65 (3.3k), Rb = R61 (680)
* charge = 0.693 * (3300+680) * 1e-6) = 2.75814e-3 -> 363Hz
*/
asound.shipfire_counter -= 363 * 2 * (VMAX*12/5-asound.shipfire_vco) / 32768;
if( asound.shipfire_counter <= 0 )
{
INT32 n = -asound.shipfire_counter / samplerate + 1;
asound.shipfire_counter += n * samplerate;
asound.shipfire_out = 1;
}
}
if( asound.shipfire_out )
return asound.shipfire_amp;
}
else
{
/* charge C47 and C48 */
asound.shipfire_amp = VMAX;
asound.shipfire_vco = VMAX;
}
return 0;
}
INLINE INT32 life(INT32 samplerate)
{
//static INT32 asound.life_counter, out;
if( sound_latch[LIFEEN] )
{
asound.life_counter -= 3000;
while( asound.life_counter <= 0 )
{
asound.life_counter += samplerate;
asound.life_out ^= 1;
}
if( asound.life_out )
return VMAX;
}
return 0;
}
void asteroid_sound_update(INT16 *buffer, INT32 length)
{
INT32 samplerate = nBurnSoundRate;
while( length-- > 0 )
{
INT32 sum = 0;
sum += explosion(samplerate) / 7;
sum += thrust(samplerate) / 7;
sum += thump(samplerate) / 7;
sum += saucer(samplerate) / 7;
sum += saucerfire(samplerate) / 7;
sum += shipfire(samplerate) / 7;
sum += life(samplerate) / 7;
*buffer++ = sum;
*buffer++ = sum;
}
}
static void explosion_init(void)
{
for( INT32 i = 0; i < 16; i++ )
{
/* r0 = open, r1 = open */
double r0 = 1.0/1e12, r1 = 1.0/1e12;
/* R14 */
if( i & 1 )
r1 += 1.0/47000;
else
r0 += 1.0/47000;
/* R15 */
if( i & 2 )
r1 += 1.0/22000;
else
r0 += 1.0/22000;
/* R16 */
if( i & 4 )
r1 += 1.0/12000;
else
r0 += 1.0/12000;
/* R17 */
if( i & 8 )
r1 += 1.0/5600;
else
r0 += 1.0/5600;
r0 = 1.0/r0;
r1 = 1.0/r1;
vol_explosion[i] = VMAX * r0 / (r0 + r1);
}
}
void asteroid_sound_init()
{
discharge = (INT16 *)BurnMalloc(32768 * sizeof(INT16));
if( !discharge ) {
bprintf(0, _T("Unable to allocate 64k ram for Asteroids sound custom.. crashing soon!\n"));
return;
}
for( INT32 i = 0; i < 0x8000; i++ )
discharge[0x7fff-i] = (INT16) (0x7fff/exp(1.0*i/4096));
/* initialize explosion volume lookup table */
explosion_init();
return;
}
void asteroid_sound_exit()
{
if( discharge )
BurnFree(discharge);
discharge = NULL;
}
void asteroid_sound_reset()
{
explosion_latch = 0;
thump_latch = 0;
memset(sound_latch, 0, sizeof(sound_latch));
polynome = 0;
thump_frequency = 0;
memset(&asound, 0, sizeof(asound));
}
void asteroid_explode_w(UINT8 data)
{
if( data == explosion_latch )
return;
explosion_latch = data;
}
void asteroid_thump_w(UINT8 data)
{
double r0 = 1/47000, r1 = 1/1e12;
if( data == thump_latch )
return;
thump_latch = data;
if( thump_latch & 1 )
r1 += 1.0/220000;
else
r0 += 1.0/220000;
if( thump_latch & 2 )
r1 += 1.0/100000;
else
r0 += 1.0/100000;
if( thump_latch & 4 )
r1 += 1.0/47000;
else
r0 += 1.0/47000;
if( thump_latch & 8 )
r1 += 1.0/22000;
else
r0 += 1.0/22000;
/* NE555 setup as voltage controlled astable multivibrator
* C = 0.22u, Ra = 22k...???, Rb = 18k
* frequency = 1.44 / ((22k + 2*18k) * 0.22n) = 56Hz .. huh?
*/
thump_frequency = 56 + 56 * r0 / (r0 + r1);
}
void asteroid_sounds_w(UINT16 offset, UINT8 data)
{
data &= 0x80;
if( data == sound_latch[offset] )
return;
sound_latch[offset] = data;
}
void astdelux_sound_update(INT16 *buffer, INT32 length)
{
INT32 samplerate = nBurnSoundRate;
while( length-- > 0)
{
INT32 sum = 0;
sum += explosion(samplerate) / 2;
sum += thrust(samplerate) / 2;
*buffer++ = sum;
*buffer++ = sum;
}
}
void astdelux_sounds_w(UINT8 data)
{
data = data & 0x80;
if( data == sound_latch[THRUSTEN] )
return;
sound_latch[THRUSTEN] = data;
}

10
src/burn/snd/asteroids.h Normal file
View File

@ -0,0 +1,10 @@
void asteroid_sound_init();
void asteroid_sound_exit();
void asteroid_sound_reset();
void asteroid_sound_update(INT16 *buffer, INT32 length);
void asteroid_explode_w(UINT8 data);
void asteroid_thump_w(UINT8 data);
void asteroid_sounds_w(UINT16 offset, UINT8 data);
void astdelux_sound_update(INT16 *buffer, INT32 length);
void astdelux_sounds_w(UINT8 data);