mirror of
https://github.com/libretro/FBNeo.git
synced 2024-11-23 17:09:43 +00:00
add driver and soundcustom for asteroids and asteroids deluxe
This commit is contained in:
parent
b3c497f81b
commit
6302fa344b
@ -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 \
|
||||
|
698
src/burn/drv/pre90s/d_asteroids.cpp
Normal file
698
src/burn/drv/pre90s/d_asteroids.cpp
Normal 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
575
src/burn/snd/asteroids.cpp
Normal 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
10
src/burn/snd/asteroids.h
Normal 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);
|
||||
|
Loading…
Reference in New Issue
Block a user