Machines promotes to working:

--------
Future Flash [Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen, Tomasz Slanina]
Laser Base (set 1) [Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen, Tomasz Slanina]
Laser Base (set 2) [Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen, Tomasz Slanina]
This commit is contained in:
Tomasz Slanina 2017-01-21 22:07:17 +01:00
parent b500e53625
commit 70897a5e5b

View File

@ -1,22 +1,32 @@
// license:BSD-3-Clause
// copyright-holders:Tomasz Slanina
// copyright-holders: Tomasz Slanina, Morten Shearman Kirkegaard, Samuel Neves, Peter Wilhelmsen
/********************************************
Laser Base / Future Flash driver
IC marked as Z1 is probably protection device
mapped in memory region f800-fbff
(similar to the one used in Parallel Turn)
Reads form this device depends on previous
writes (adr, data), address and previous
operation (read or write).
Pinout is almost identical to 2716 - type EPROM,
except separated /RD and /WR signals and lacks
of /CS
Tomasz Slanina analog [at] op.pl
============================================
TODO:
- Video: weird palette changes, Laserbase colors, missing bg scrolling between stages (CRT address lines + m_hset ( or m_vset ?))
- Sound: sound related i/o writes ( out_w handler )
- Interrupts - NMI/Int timing is wrong, it's based on measures of broken PCB
TS 20.01.2017
There's incomplete schematics available. It's missing a couple of important elements (analog sound, interrupts).
PCB contains big analog sound section, currently only partially emulated ( timers + counters + xors + dacs). There's many capacitors,
resistors and few ICs, including:
7B LM2902N - Op Amps
4B LM2902N
2B LM2902N
1B LM2902N
6B LM1496N - Balanced Modulator-Demodulator
3B CA3080E - Op Amp
6C NE555P - Timer
4A NE555P - Timer
6A SN94560AN - ? a tone generator (similar to SN76477 ?)
3A MB84013B - Dual D flip-flop
2A MN3008 - 2048-stage long delay low noise BBD (reverb effect generator)
1C MB3712 - Power Amp.
DASM notes:
@ -53,127 +63,180 @@ expected: 43 FB CC 9A D4 23 6C 01 3E <- From ROM 4
#include "cpu/z80/z80.h"
#include "video/mc6845.h"
#include "machine/pit8253.h"
#include "sound/dac.h"
#include "sound/volt_reg.h"
class laserbas_state : public driver_device
{
public:
laserbas_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_protram(*this, "protram"),
m_maincpu(*this, "maincpu") { }
m_maincpu(*this, "maincpu"),
m_palette(*this, "palette"),
m_dac1(*this, "dac1"),
m_dac2(*this, "dac2"),
m_dac3(*this, "dac3"),
m_dac4(*this, "dac4"),
m_dac5(*this, "dac5"),
m_dac6(*this, "dac6")
{ }
/* misc */
int m_count;
int m_dac_data;
int m_counter[6];
int m_cnt_out[6];
int m_nmi;
/* video-related */
int m_vrambank;
uint8_t m_vram1[0x8000];
uint8_t m_vram2[0x8000];
uint8_t m_vram[0x10000];
int m_hset, m_vset;
int m_bset;
int m_scl;
bool m_flipscreen;
required_shared_ptr<uint8_t> m_protram;
uint16_t m_z1data[4];
void write_pit_out(int num, int state);
DECLARE_READ8_MEMBER(vram_r);
DECLARE_WRITE8_MEMBER(vram_w);
DECLARE_WRITE8_MEMBER(vrambank_w);
DECLARE_READ8_MEMBER(protram_r);
DECLARE_WRITE8_MEMBER(protram_w);
DECLARE_WRITE8_MEMBER(videoctrl_w);
DECLARE_READ8_MEMBER(z1_r);
DECLARE_READ8_MEMBER(track_lo_r);
DECLARE_READ8_MEMBER(track_hi_r);
DECLARE_WRITE8_MEMBER(out_w);
DECLARE_WRITE_LINE_MEMBER(pit_out_0_w);
DECLARE_WRITE_LINE_MEMBER(pit_out_1_w);
DECLARE_WRITE_LINE_MEMBER(pit_out_2_w);
DECLARE_WRITE_LINE_MEMBER(pit_out_3_w);
DECLARE_WRITE_LINE_MEMBER(pit_out_4_w);
DECLARE_WRITE_LINE_MEMBER(pit_out_5_w);
TIMER_DEVICE_CALLBACK_MEMBER(laserbas_scanline);
MC6845_UPDATE_ROW(crtc_update_row);
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void video_start() override;
uint32_t screen_update_laserbas(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
required_device<cpu_device> m_maincpu;
required_device<palette_device> m_palette;
required_device<dac_byte_interface> m_dac1;
required_device<dac_byte_interface> m_dac2;
required_device<dac_byte_interface> m_dac3;
required_device<dac_byte_interface> m_dac4;
required_device<dac_byte_interface> m_dac5;
required_device<dac_byte_interface> m_dac6;
};
void laserbas_state::video_start()
TIMER_DEVICE_CALLBACK_MEMBER( laserbas_state::laserbas_scanline )
{
save_item(NAME(m_vram1));
save_item(NAME(m_vram2));
save_item(NAME(m_flipscreen));
int scanline = param;
if(scanline == 0 || scanline == 135)
{
m_maincpu->set_input_line(0, HOLD_LINE );
}
if(scanline == 240 && m_nmi)
{
m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
}
}
uint32_t laserbas_state::screen_update_laserbas(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
MC6845_UPDATE_ROW( laserbas_state::crtc_update_row )
{
int x,y, x0,y0, x1,y1, delta;
int x, x_max, dx, pixaddr;
const rgb_t *palette = m_palette->palette()->entry_list_raw();
uint32_t *p = &bitmap.pix32(y);
if (m_flipscreen)
{
delta = -1;
x0 = 256-1; x1 = -1;
y0 = 256-1; y1 = -1;
y=0x100-y-1-0x20;
dx = -1;
x = 0x100-1;
x_max = -1;
}
else
{
delta = 1;
x0 = 0; x1 = 256;
y0 = 0; y1 = 256;
dx = 1;
x = 0;
x_max = 0x100;
}
int pixaddr = 0;
for (y = y0; y != y1; y += delta)
pixaddr=y<<8;
{
for (x = x0; x != x1; x += delta)
while ( x != x_max )
{
uint8_t p1 = m_vram1[pixaddr/2];
uint8_t p2 = m_vram2[pixaddr/2];
uint8_t mask = (pixaddr & 1) ? 0xf0 : 0x0f;
uint8_t shift = (pixaddr & 1) ? 4 : 0;
uint32_t offset = (pixaddr>>1)&0x7fff;
uint8_t p1 = m_vram[offset];
uint8_t p2 = m_vram[offset+0x8000]; // 0x10000 VRAM, two 4 bit layers 0x8000 bytes each
if (p2 & mask)
bitmap.pix16(y, x) = (p2 & mask) >> shift;
else
bitmap.pix16(y, x) = ((p1 & mask) >> shift) + 16;
uint8_t shift = (pixaddr & 1)?4:0; // two 4 bit pixels in one byte
p1 = (p1>>shift) & 0xf;
p2 = (p2>>shift) & 0xf;
pixaddr++;
p[x] = palette[p2?:(p1?(p1+16):m_bset)]; // layer 2 | layer 1 | bg pen
++pixaddr;
x += dx;
}
}
return 0;
}
READ8_MEMBER(laserbas_state::vram_r)
{
if(!m_vrambank)
return m_vram1[offset];
else
return m_vram2[offset];
return m_vram[offset+(m_vrambank?0x8000:0)];
}
WRITE8_MEMBER(laserbas_state::vram_w)
{
if(!m_vrambank)
m_vram1[offset] = data;
else
m_vram2[offset] = data;
m_vram[offset+(m_vrambank?0x8000:0)] = data;
}
#if 0
READ8_MEMBER(laserbas_state::read_unk)
WRITE8_MEMBER(laserbas_state::videoctrl_w)
{
m_count ^= 0x80;
return m_count | 0x7f;
}
#endif
WRITE8_MEMBER(laserbas_state::vrambank_w)
{
m_vrambank = data & 0x40;
m_flipscreen = !(data & 0x80);
if(!(offset&1))
{
m_vrambank = data & 0x40; // layer select
m_flipscreen = !(data & 0x80);
m_vset = (data>>3)&7; // inc-ed on interrupts ( 8 ints / frame ?)
m_hset = data&7;
}
else
{
data^=0xff;
m_bset = data>>4; // bg pen
m_scl = (data&8)>>3; // unknown
m_nmi=data&1; // nmi enable (not on schematics, traced)
}
}
READ8_MEMBER(laserbas_state::protram_r)
READ8_MEMBER(laserbas_state::z1_r)
{
uint8_t prot = m_protram[offset];
// prot = machine().rand();
// logerror("%s: Z1 read %03x = %02x\n", machine().describe_context(), offset, prot);
return prot;
}
uint8_t res = 0;
WRITE8_MEMBER(laserbas_state::protram_w)
{
// logerror("%s: Z1 write %03x = %02x\n", machine().describe_context(), offset, data);
m_protram[offset] = data;
m_z1data[0] = m_z1data[1];
m_z1data[1] = m_z1data[2];
m_z1data[2] = m_z1data[3];
m_z1data[3] = offset;
#define x(o) (1 & (m_z1data[o / 10] >> (o % 10)))
#define nx(o) (1 & ~(m_z1data[o / 10] >> (o % 10)))
#define MUX2(s, a, b) ((s) ? (a) : (b))
res =
MUX2(x(36) & x(33), x(31) ^ x(35), (nx(33) & (nx(20) | nx(36))) | (nx(36) & x(24))) << 7
| MUX2(x(36), MUX2(x(33), x(29), nx(23) | x(30)), x(33) & x(15)) << 6
| MUX2(x(36), nx(33) & x(27), x(32) | x(33)) << 5
| MUX2(x(36), MUX2(x(33), nx(24), nx(35)), MUX2(nx(33), x(4), MUX2(nx(26), x(5) & x(23), MUX2(x(23), x(19), nx(13) | x(20))))) << 4
| MUX2(x(36), x(33) & x(11), MUX2(x(33), x(25) | nx(31), x(24))) << 3
| MUX2(x(33), MUX2(x(36), x(28), x(20)), MUX2(x(36), nx(11), nx(39))) << 2
| MUX2(x(36), MUX2(x(23), MUX2(x(26), nx(18), nx(10)) | x(33), MUX2(x(26), x(1), x(29)) & nx(33)), MUX2(x(33), x(7), x(17))) << 1
| MUX2(x(33), MUX2(x(36), x(22), nx(26)), MUX2(x(36), x(14), x(21))) << 0
;
#undef MUX2
#undef nx
#undef x
return res;
}
READ8_MEMBER(laserbas_state::track_lo_r)
@ -181,29 +244,103 @@ READ8_MEMBER(laserbas_state::track_lo_r)
uint8_t dx = ioport("TRACK_X")->read();
uint8_t dy = ioport("TRACK_Y")->read();
if (dx & 0x10)
dx ^= 0x0f;
dx ^= 0xf;
if (dy & 0x10)
dy ^= 0x0f;
return (dx & 0x0f) | ((dy & 0x0f) << 4);
int data = (dx & 0x0f) | ((dy & 0x0f) << 4);
return data;
}
READ8_MEMBER(laserbas_state::track_hi_r)
{
return ((ioport("TRACK_X")->read() & 0x10) >> 4) | ((ioport("TRACK_Y")->read() & 0x10) >> 3);
int data = ((ioport("TRACK_X")->read() & 0x10) >> 4) | ((ioport("TRACK_Y")->read() & 0x10) >> 3);
return data;
}
WRITE8_MEMBER(laserbas_state::out_w)
{
static uint8_t out[4];
out[offset] = data;
// port 20: mask 01 = service1, mask 02 = pulsed (no delay) waiting for start1, mask 08 = coin2, mask 40 = coin1
popmessage("OUT 20: %02x %02x - %02x %02x", out[0], out[1], out[2], out[3]);
/* sound related , maybe also lamps */
}
void laserbas_state::machine_start()
{
save_item(NAME(m_vram));
save_item(NAME(m_flipscreen));
save_item(NAME(m_vrambank));
save_item(NAME(m_hset));
save_item(NAME(m_vset));
save_item(NAME(m_bset));
save_item(NAME(m_scl));
save_item(NAME(m_nmi));
save_item(NAME(m_dac_data));
save_item(NAME(m_counter));
save_item(NAME(m_cnt_out));
save_item(NAME(m_z1data));
}
void laserbas_state::machine_reset()
{
m_vrambank = 0;
m_flipscreen = false;
m_nmi=0;
m_bset = 0;
m_hset = 0;
m_vset = 0;
m_scl = 0;
}
void laserbas_state::write_pit_out(int num, int state)
{
state^=1; // 7404 (6G)
if((!state)& m_cnt_out[num]){ // 0->1 rising edge CLK
m_counter[num] = (m_counter[num]+1)&0x0f; // 4 bit counters 74393
}
int data =(state) | ((m_counter[num]&7)<<1); // combine output from 8253 with counter bits 0-3
data<<=4;
if(m_counter[num]&8) data^=0x0f; // counter bit 4 xors the data ( 7486 x 6)
switch(num){
case 0: m_dac1->write(data);break; // 4 resistor packs : 47k, 100k, 220k, 470k
case 1: m_dac2->write(data);break;
case 2: m_dac3->write(data);break;
case 3: m_dac4->write(data);break;
case 4: m_dac5->write(data);break;
case 5: m_dac6->write(data);break;
}
m_cnt_out[num]=state;
}
WRITE_LINE_MEMBER(laserbas_state::pit_out_0_w)
{
write_pit_out(0,state);
}
WRITE_LINE_MEMBER(laserbas_state::pit_out_1_w)
{
write_pit_out(1,state);
}
WRITE_LINE_MEMBER(laserbas_state::pit_out_2_w)
{
write_pit_out(2,state);
}
WRITE_LINE_MEMBER(laserbas_state::pit_out_3_w)
{
write_pit_out(3,state);
}
WRITE_LINE_MEMBER(laserbas_state::pit_out_4_w)
{
write_pit_out(4,state);
}
WRITE_LINE_MEMBER(laserbas_state::pit_out_5_w)
{
write_pit_out(5,state);
}
static ADDRESS_MAP_START( laserbas_memory, AS_PROGRAM, 8, laserbas_state )
AM_RANGE(0x0000, 0x3fff) AM_ROM
AM_RANGE(0x4000, 0xbfff) AM_READWRITE(vram_r, vram_w)
AM_RANGE(0xc000, 0xf7ff) AM_ROM
AM_RANGE(0xf800, 0xfbff) AM_READWRITE(protram_r, protram_w) AM_SHARE("protram") /* protection device */
AM_RANGE(0xc000, 0xf7ff) AM_ROM AM_WRITENOP
AM_RANGE(0xf800, 0xfbff) AM_READ(z1_r) AM_WRITENOP /* protection device */
AM_RANGE(0xfc00, 0xffff) AM_RAM
ADDRESS_MAP_END
@ -211,11 +348,11 @@ static ADDRESS_MAP_START( laserbas_io, AS_IO, 8, laserbas_state )
ADDRESS_MAP_GLOBAL_MASK(0xff)
AM_RANGE(0x00, 0x00) AM_DEVWRITE("crtc", mc6845_device, address_w)
AM_RANGE(0x01, 0x01) AM_DEVWRITE("crtc", mc6845_device, register_w)
AM_RANGE(0x10, 0x10) AM_WRITE(vrambank_w)
AM_RANGE(0x10, 0x11) AM_WRITE(videoctrl_w)
AM_RANGE(0x20, 0x20) AM_READ_PORT("DSW")
AM_RANGE(0x21, 0x21) AM_READ_PORT("INPUTS")
AM_RANGE(0x22, 0x22) AM_READ(track_hi_r)
AM_RANGE(0x23, 0x23) AM_READ(track_lo_r) // AM_WRITE(test_w)
AM_RANGE(0x23, 0x23) AM_READ(track_lo_r)
AM_RANGE(0x20, 0x23) AM_WRITE(out_w)
AM_RANGE(0x40, 0x43) AM_DEVREADWRITE("pit0", pit8253_device, read, write)
AM_RANGE(0x44, 0x47) AM_DEVREADWRITE("pit1", pit8253_device, read, write)
@ -234,8 +371,8 @@ static INPUT_PORTS_START( laserbas )
PORT_DIPSETTING( 0x04, "10k" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20)
PORT_DIPSETTING( 0x00, "30k" ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20)
PORT_DIPNAME( 0x08, 0x08, DEF_STR( Demo_Sounds ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20)
PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20)
PORT_DIPSETTING( 0x08, DEF_STR( On ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20)
PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20)
PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20)
PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_B ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20)
PORT_DIPSETTING( 0x10, DEF_STR( 3C_1C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20)
PORT_DIPSETTING( 0x20, DEF_STR( 2C_1C ) ) PORT_CONDITION("INPUTS", 0x20, EQUALS, 0x20)
@ -259,7 +396,7 @@ static INPUT_PORTS_START( laserbas )
PORT_START("INPUTS") // $21
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_PLAYER(2)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN2 )
@ -268,58 +405,67 @@ static INPUT_PORTS_START( laserbas )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SERVICE1 ) // service coin
PORT_START("TRACK_X")
PORT_BIT( 0x1f, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(10) PORT_KEYDELTA(1) PORT_RESET
PORT_BIT( 0x01f, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_RESET
PORT_START("TRACK_Y")
PORT_BIT( 0x1f, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(10) PORT_KEYDELTA(1) PORT_RESET PORT_REVERSE
PORT_BIT( 0x01f, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_RESET PORT_REVERSE
INPUT_PORTS_END
void laserbas_state::machine_start()
{
save_item(NAME(m_vrambank));
save_item(NAME(m_count));
}
void laserbas_state::machine_reset()
{
m_vrambank = 0;
m_flipscreen = false;
m_count = 0;
}
#define CLOCK 16680000
#define PIT_CLOCK (CLOCK/16) // 12 divider ?
static MACHINE_CONFIG_START( laserbas, laserbas_state )
MCFG_CPU_ADD("maincpu", Z80, 4000000)
MCFG_CPU_ADD("maincpu", Z80, CLOCK*4)
MCFG_CPU_PROGRAM_MAP(laserbas_memory)
MCFG_CPU_IO_MAP(laserbas_io)
MCFG_CPU_VBLANK_INT_DRIVER("screen", laserbas_state, irq0_line_hold)
// MCFG_TIMER_DRIVER_ADD_PERIODIC("nmi", laserbas_state, nmi_line_pulse, attotime::from_hz(60))
MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", laserbas_state, laserbas_scanline, "screen", 0, 1)
/* TODO: clocks aren't known */
MCFG_DEVICE_ADD("pit0", PIT8253, 0)
MCFG_PIT8253_CLK0(31250)
MCFG_PIT8253_CLK1(31250)
MCFG_PIT8253_CLK2(31250)
MCFG_PIT8253_CLK0(PIT_CLOCK)
MCFG_PIT8253_CLK1(PIT_CLOCK)
MCFG_PIT8253_CLK2(PIT_CLOCK)
MCFG_PIT8253_OUT0_HANDLER(WRITELINE(laserbas_state, pit_out_0_w))
MCFG_PIT8253_OUT1_HANDLER(WRITELINE(laserbas_state, pit_out_1_w))
MCFG_PIT8253_OUT2_HANDLER(WRITELINE(laserbas_state, pit_out_2_w))
MCFG_DEVICE_ADD("pit1", PIT8253, 0)
MCFG_PIT8253_CLK0(31250)
MCFG_PIT8253_CLK1(31250)
MCFG_PIT8253_CLK2(31250)
MCFG_PIT8253_CLK0(PIT_CLOCK)
MCFG_PIT8253_CLK1(PIT_CLOCK)
MCFG_PIT8253_CLK2(PIT_CLOCK)
MCFG_PIT8253_OUT0_HANDLER(WRITELINE(laserbas_state, pit_out_3_w))
MCFG_PIT8253_OUT1_HANDLER(WRITELINE(laserbas_state, pit_out_4_w))
MCFG_PIT8253_OUT2_HANDLER(WRITELINE(laserbas_state, pit_out_5_w))
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */)
MCFG_SCREEN_SIZE(32*8, 32*8)
MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 32*8-1)
MCFG_SCREEN_UPDATE_DRIVER(laserbas_state, screen_update_laserbas)
MCFG_SCREEN_PALETTE("palette")
MCFG_SCREEN_RAW_PARAMS(4000000, 256, 0, 256, 256, 0, 256) /* temporary, CRTC will configure screen */
MCFG_SCREEN_UPDATE_DEVICE("crtc", mc6845_device, screen_update)
MCFG_MC6845_ADD("crtc", H46505, "screen", 3000000/4) /* unknown clock, hand tuned to get ~60 fps */
MCFG_MC6845_SHOW_BORDER_AREA(false)
MCFG_MC6845_CHAR_WIDTH(8)
MCFG_MC6845_UPDATE_ROW_CB(laserbas_state, crtc_update_row)
MCFG_PALETTE_ADD("palette", 32)
MCFG_PALETTE_FORMAT(RRRGGGBB)
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("speaker")
MCFG_SOUND_ADD("dac1", DAC_4BIT_R2R, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.16)
MCFG_SOUND_ADD("dac2", DAC_4BIT_R2R, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.16)
MCFG_SOUND_ADD("dac3", DAC_4BIT_R2R, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.16)
MCFG_SOUND_ADD("dac4", DAC_4BIT_R2R, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.16)
MCFG_SOUND_ADD("dac5", DAC_4BIT_R2R, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.16)
MCFG_SOUND_ADD("dac6", DAC_4BIT_R2R, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.16)
MCFG_DEVICE_ADD("vref", VOLTAGE_REGULATOR, 0) MCFG_VOLTAGE_REGULATOR_OUTPUT(5.0)
MCFG_SOUND_ROUTE_EX(0, "dac1", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE_EX(0, "dac1", -1.0, DAC_VREF_NEG_INPUT)
MCFG_SOUND_ROUTE_EX(0, "dac2", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE_EX(0, "dac2", -1.0, DAC_VREF_NEG_INPUT)
MCFG_SOUND_ROUTE_EX(0, "dac3", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE_EX(0, "dac3", -1.0, DAC_VREF_NEG_INPUT)
MCFG_SOUND_ROUTE_EX(0, "dac4", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE_EX(0, "dac4", -1.0, DAC_VREF_NEG_INPUT)
MCFG_SOUND_ROUTE_EX(0, "dac5", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE_EX(0, "dac5", -1.0, DAC_VREF_NEG_INPUT)
MCFG_SOUND_ROUTE_EX(0, "dac6", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE_EX(0, "dac6", -1.0, DAC_VREF_NEG_INPUT)
MACHINE_CONFIG_END
/*
@ -410,6 +556,6 @@ ROM_START( futflash )
ROM_LOAD( "ff.8", 0xf000, 0x0800, CRC(623f558f) SHA1(be6c6565df658555f21c43a8c2459cf399794a84) )
ROM_END
GAME( 1981, laserbas, 0, laserbas, laserbas, driver_device, 0, ROT270, "Hoei (Amstar license)", "Laser Base (set 1)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
GAME( 1981, laserbasa,laserbas, laserbas, laserbas, driver_device, 0, ROT270, "Hoei (Amstar license)", "Laser Base (set 2)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
GAME( 1981, futflash, laserbas, laserbas, laserbas, driver_device, 0, ROT270, "Hoei", "Future Flash", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
GAME( 1980, futflash, 0, laserbas, laserbas, driver_device, 0, ROT270, "Hoei", "Future Flash", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
GAME( 1981, laserbas, futflash, laserbas, laserbas, driver_device, 0, ROT270, "Hoei (Amstar license)", "Laser Base (set 1)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )
GAME( 1981, laserbasa,futflash, laserbas, laserbas, driver_device, 0, ROT270, "Hoei (Amstar license)", "Laser Base (set 2)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE )