Model 1: add skeleton device for Z80 version of the MPEG sound board. No playback, just running the Z80. [R. Belmont]

This commit is contained in:
R. Belmont 2012-02-04 23:57:03 +00:00
parent f7ac4ce982
commit 2181d363cd
6 changed files with 335 additions and 9 deletions

2
.gitattributes vendored
View File

@ -1817,6 +1817,8 @@ src/mame/audio/decobsmt.h svneol=native#text/plain
src/mame/audio/depthch.c svneol=native#text/plain
src/mame/audio/dkong.c svneol=native#text/plain
src/mame/audio/dragrace.c svneol=native#text/plain
src/mame/audio/dsbz80.c svneol=native#text/plain
src/mame/audio/dsbz80.h svneol=native#text/plain
src/mame/audio/exidy.c svneol=native#text/plain
src/mame/audio/exidy.h svneol=native#text/plain
src/mame/audio/exidy440.c svneol=native#text/plain

246
src/mame/audio/dsbz80.c Normal file
View File

@ -0,0 +1,246 @@
/***************************************************************************
Sega Z80 Digital Sound Board
used for Model 1/2/3
***************************************************************************/
#define ADDRESS_MAP_MODERN
#include "emu.h"
#include "audio/dsbz80.h"
#define Z80_TAG "mpegcpu"
#define YMZ770_TAG "ymz770"
static ADDRESS_MAP_START( dsbz80_map, AS_PROGRAM, 8, dsbz80_device )
AM_RANGE(0x0000, 0x7fff) AM_ROM AM_REGION(":mpegcpu", 0)
AM_RANGE(0x8000, 0xffff) AM_RAM
ADDRESS_MAP_END
static ADDRESS_MAP_START( dsbz80io_map, AS_IO, 8, dsbz80_device )
AM_RANGE(0xe0, 0xe0) AM_MIRROR(0xff00) AM_WRITE(mpeg_trigger_w)
AM_RANGE(0xe2, 0xe4) AM_MIRROR(0xff00) AM_READWRITE(mpeg_pos_r, mpeg_start_w)
AM_RANGE(0xe5, 0xe7) AM_MIRROR(0xff00) AM_WRITE(mpeg_end_w)
AM_RANGE(0xe8, 0xe8) AM_MIRROR(0xff00) AM_WRITE(mpeg_volume_w)
AM_RANGE(0xe9, 0xe9) AM_MIRROR(0xff00) AM_WRITE(mpeg_stereo_w)
AM_RANGE(0xf0, 0xf0) AM_MIRROR(0xff00) AM_READ(latch_r)
AM_RANGE(0xf1, 0xf1) AM_MIRROR(0xff00) AM_READ(status_r)
ADDRESS_MAP_END
MACHINE_CONFIG_FRAGMENT( dsbz80 )
MCFG_CPU_ADD(Z80_TAG, Z80, 1000000) /* unknown clock, but probably pretty slow considering the z80 does like nothing */
MCFG_CPU_PROGRAM_MAP(dsbz80_map)
MCFG_CPU_IO_MAP(dsbz80io_map)
#if 0
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_YMZ770_ADD(YMZ770_TAG, 8000000) /* clock ignored for this */
MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
#endif
MACHINE_CONFIG_END
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
const device_type DSBZ80 = &device_creator<dsbz80_device>;
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor dsbz80_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( dsbz80 );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// dsbz80_device - constructor
//-------------------------------------------------
dsbz80_device::dsbz80_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, DSBZ80, "Sega Z80-based Digital Sound Board", tag, owner, clock),
m_ourcpu(*this, Z80_TAG),
m_ymz770(*this, YMZ770_TAG)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void dsbz80_device::device_start()
{
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void dsbz80_device::device_reset()
{
m_dsb_latch = 0;
status = 1;
start = end = 0;
}
WRITE8_MEMBER(dsbz80_device::latch_w)
{
device_set_input_line(m_ourcpu, INPUT_LINE_IRQ0, ASSERT_LINE);
m_dsb_latch = data;
status |= 2;
// printf("%02x to DSB latch\n", data);
}
READ8_MEMBER(dsbz80_device::latch_r)
{
device_set_input_line(m_ourcpu, INPUT_LINE_IRQ0, CLEAR_LINE);
// printf("DSB Z80 read %02x\n", m_dsb_latch);
status &= ~2;
return m_dsb_latch;
}
WRITE8_MEMBER(dsbz80_device::mpeg_trigger_w)
{
mp_state = data;
if (data == 0) // stop
{
// MPEG_Stop_Playing();
// printf("MPEG stop\n");
}
else if (data == 1) // play without loop
{
// MPEG_Set_Loop(NULL, 0);
// MPEG_Play_Memory(ROM + mp_start, mp_end-mp_start);
// printf("MPEG start, one-shot from %x\n", mp_start);
}
else if (data == 2) // play with loop
{
// MPEG_Play_Memory(ROM + mp_start, mp_end-mp_start);
// printf("MPEG start, loop from %x\n", mp_start);
}
}
READ8_MEMBER(dsbz80_device::mpeg_pos_r)
{
int mp_prg = 0; //MPEG_Get_Progress(); // returns the byte offset currently playing
mp_prg += mp_start;
switch (offset)
{
case 0:
return (mp_prg>>16)&0xff;
break;
case 1:
return (mp_prg>>8)&0xff;
break;
case 2:
return mp_prg&0xff;
break;
}
return 0;
}
/* NOTE: writes to the start and end while playback is already in progress
get latched. When the current stream ends, the MPEG hardware starts playing
immediately from the latched start and end position. In this way, the Z80
enforces looping where appropriate and multi-part songs in other cases
(song #16 is a good example)
*/
WRITE8_MEMBER(dsbz80_device::mpeg_start_w)
{
switch (offset)
{
case 0:
start &= 0x00ffff;
start |= (int)data<<16;
break;
case 1:
start &= 0xff00ff;
start |= (int)data<<8;
break;
case 2:
start &= 0xffff00;
start |= data;
if (mp_state == 0)
{
mp_start = start;
}
else
{
lp_start = start;
// SWA: if loop end is zero, it means "keep previous end marker"
if (lp_end == 0)
{
// MPEG_Set_Loop(ROM + lp_start, mp_end-lp_start);
}
else
{
// MPEG_Set_Loop(ROM + lp_start, lp_end-lp_start);
}
}
break;
}
}
WRITE8_MEMBER(dsbz80_device::mpeg_end_w)
{
switch (offset)
{
case 0:
end &= 0x00ffff;
end |= (int)data<<16;
break;
case 1:
end &= 0xff00ff;
end |= (int)data<<8;
break;
case 2:
end &= 0xffff00;
end |= data;
if (mp_state == 0)
{
mp_end = end;
}
else
{
lp_end = end;
// MPEG_Set_Loop(ROM + lp_start, lp_end-lp_start);
}
break;
}
}
WRITE8_MEMBER(dsbz80_device::mpeg_volume_w)
{
mp_vol = 0x7f - data;
}
WRITE8_MEMBER(dsbz80_device::mpeg_stereo_w)
{
mp_pan = data & 3;
}
READ8_MEMBER(dsbz80_device::status_r)
{
// bit 0 = ??? (must be 1 for most games)
// bit 1 = command is pending (used by SWA instead of IRQ)
// other bits = ???
// SWA requires that status & 0x38 = 0 or else it loops endlessly...
return status;
}

57
src/mame/audio/dsbz80.h Normal file
View File

@ -0,0 +1,57 @@
#pragma once
#ifndef __DSBZ80_H__
#define __DSBZ80_H__
#include "emu.h"
#include "cpu/z80/z80.h"
#include "sound/ymz770.h"
#define DSBZ80_TAG "dsbz80"
#define MCFG_DSBZ80_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, DSBZ80, 0)
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class dsbz80_device : public device_t
{
public:
// construction/destruction
dsbz80_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// optional information overrides
virtual machine_config_constructor device_mconfig_additions() const;
DECLARE_WRITE8_MEMBER(latch_w);
required_device<cpu_device> m_ourcpu;
optional_device<ymz770_device> m_ymz770;
DECLARE_WRITE8_MEMBER(mpeg_trigger_w);
DECLARE_WRITE8_MEMBER(mpeg_start_w);
DECLARE_WRITE8_MEMBER(mpeg_end_w);
DECLARE_WRITE8_MEMBER(mpeg_volume_w);
DECLARE_WRITE8_MEMBER(mpeg_stereo_w);
DECLARE_READ8_MEMBER(mpeg_pos_r);
DECLARE_READ8_MEMBER(latch_r);
DECLARE_READ8_MEMBER(status_r);
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
private:
UINT8 m_dsb_latch;
UINT32 mp_start, mp_end, mp_vol, mp_pan, mp_state, lp_start, lp_end, start, end;
int status;
};
// device type definition
extern const device_type DSBZ80;
#endif /* __DSBZ80_H__ */

View File

@ -634,8 +634,6 @@ Notes:
#include "machine/nvram.h"
#include "includes/model1.h"
static READ16_HANDLER( io_r )
{
static const char *const analognames[] = { "AN0", "AN1", "AN2", "AN3", "AN4", "AN5", "AN6", "AN7" };
@ -860,6 +858,11 @@ static WRITE16_HANDLER( snd_latch_to_68k_w )
state->m_fifo_wptr++;
if (state->m_fifo_wptr >= ARRAY_LENGTH(state->m_to_68k)) state->m_fifo_wptr = 0;
if (state->m_dsbz80 != NULL)
{
state->m_dsbz80->latch_w(*space, 0, data);
}
// signal the 68000 that there's data waiting
cputag_set_input_line(space->machine(), "audiocpu", 2, HOLD_LINE);
// give the 68k time to reply
@ -1334,10 +1337,10 @@ ROM_START( swa )
ROM_LOAD( "mpr-16484.bin", 0x000000, 0x200000, CRC(9d4c334d) SHA1(8b4d903f14559fed425d225bb23ccfe8da23cbd3) )
ROM_LOAD( "mpr-16485.bin", 0x200000, 0x200000, CRC(95aadcad) SHA1(4276db655db9834692c3843eb96a3e3a89cb7252) )
ROM_REGION( 0x20000, "cpu2", 0 ) /* Z80 DSB code */
ROM_REGION( 0x20000, "mpegcpu", 0 ) /* Z80 DSB code */
ROM_LOAD( "epr-16471.bin", 0x000000, 0x020000, CRC(f4ee84a4) SHA1(f12b214e6f195b0e5f49ba9f41d8e54bfcea9acc) )
ROM_REGION( 0x400000, "mpeg", 0 ) /* DSB MPEG data */
ROM_REGION( 0x400000, "ymz770", 0 ) /* DSB MPEG data */
ROM_LOAD( "mpr-16514.bin", 0x000000, 0x200000, CRC(3175b0be) SHA1(63649d053c8c17ce1746d16d0cc8202be20c302f) )
ROM_LOAD( "mpr-16515.bin", 0x000000, 0x200000, CRC(3114d748) SHA1(9ef090623cdd2a1d06b5d1bc4b9a07ab4eff5b76) )
@ -1543,6 +1546,10 @@ static MACHINE_CONFIG_START( model1, model1_state )
MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED(swa, model1)
MCFG_DSBZ80_ADD(DSBZ80_TAG)
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( model1_vr, model1_state )
MCFG_CPU_ADD("maincpu", V60, 16000000)
MCFG_CPU_PROGRAM_MAP(model1_vr_mem)
@ -1591,7 +1598,7 @@ MACHINE_CONFIG_END
GAME( 1993, vf, 0, model1, vf, 0, ROT0, "Sega", "Virtua Fighter", GAME_IMPERFECT_GRAPHICS )
GAME( 1992, vr, 0, model1_vr, vr, 0, ROT0, "Sega", "Virtua Racing", GAME_IMPERFECT_GRAPHICS )
GAME( 1993, vformula, vr, model1_vr, vr, 0, ROT0, "Sega", "Virtua Formula", GAME_IMPERFECT_GRAPHICS )
GAME( 1993, swa, 0, model1, swa, 0, ROT0, "Sega", "Star Wars Arcade", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND )
GAME( 1993, swa, 0, swa, swa, 0, ROT0, "Sega", "Star Wars Arcade", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND )
GAME( 1994, wingwar, 0, model1, wingwar, 0, ROT0, "Sega", "Wing War (World)", GAME_NOT_WORKING )
GAME( 1994, wingwaru, wingwar, model1, wingwar, 0, ROT0, "Sega", "Wing War (US)", GAME_NOT_WORKING )
GAME( 1994, wingwarj, wingwar, model1, wingwar, 0, ROT0, "Sega", "Wing War (Japan)", GAME_NOT_WORKING )

View File

@ -1,3 +1,5 @@
#include "audio/dsbz80.h"
typedef void (*tgp_func)(running_machine &machine);
enum {FIFO_SIZE = 256};
@ -7,7 +9,15 @@ class model1_state : public driver_device
{
public:
model1_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) { }
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_audiocpu(*this, "maincpu"),
m_dsbz80(*this, DSBZ80_TAG)
{ }
required_device<cpu_device> m_maincpu; // V60
required_device<cpu_device> m_audiocpu; // sound 68000
optional_device<dsbz80_device> m_dsbz80; // Digital Sound Board
struct view *m_view;
struct point *m_pointdb;

View File

@ -1198,6 +1198,7 @@ $(MAMEOBJ)/sega.a: \
$(DRIVERS)/megaplay.o \
$(DRIVERS)/megatech.o \
$(DRIVERS)/model1.o $(MACHINE)/model1.o $(VIDEO)/model1.o \
$(AUDIO)/dsbz80.o \
$(DRIVERS)/model2.o $(VIDEO)/model2.o \
$(DRIVERS)/model3.o $(VIDEO)/model3.o $(MACHINE)/model3.o \
$(DRIVERS)/naomi.o $(MACHINE)/dc.o $(VIDEO)/dc.o $(MACHINE)/naomi.o \
@ -2174,6 +2175,9 @@ $(MACHINE)/nes_mmc.o: $(MAMESRC)/machine/nes_ines.c \
$(MAMESRC)/machine/nes_unif.c
$(VIDEO)/jaguar.o: $(MAMESRC)/video/jagobj.c \
$(MAMESRC)/video/jagblit.c
$(DRIVERS)/model1.o: $(MAMESRC)/includes/model1.h $(MAMESRC)/audio/dsbz80.h
$(VIDEO)/model1.o: $(MAMESRC)/includes/model1.h $(MAMESRC)/audio/dsbz80.h
$(MACHINE)/model1.o: $(MAMESRC)/includes/model1.h $(MAMESRC)/audio/dsbz80.h
$(VIDEO)/model2.o: $(MAMESRC)/video/model2rd.c
$(VIDEO)/model3.o: $(MAMESRC)/video/m3raster.c
$(VIDEO)/n64.o: $(MAMESRC)/video/rdpfiltr.c