From 2181d363cdabbac6de93f95d943708ff2983026f Mon Sep 17 00:00:00 2001 From: "R. Belmont" Date: Sat, 4 Feb 2012 23:57:03 +0000 Subject: [PATCH] Model 1: add skeleton device for Z80 version of the MPEG sound board. No playback, just running the Z80. [R. Belmont] --- .gitattributes | 2 + src/mame/audio/dsbz80.c | 246 +++++++++++++++++++++++++++++++++++++ src/mame/audio/dsbz80.h | 57 +++++++++ src/mame/drivers/model1.c | 23 ++-- src/mame/includes/model1.h | 12 +- src/mame/mame.mak | 4 + 6 files changed, 335 insertions(+), 9 deletions(-) create mode 100644 src/mame/audio/dsbz80.c create mode 100644 src/mame/audio/dsbz80.h diff --git a/.gitattributes b/.gitattributes index 7d2cfcea0ac..b5cb40f22cf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/src/mame/audio/dsbz80.c b/src/mame/audio/dsbz80.c new file mode 100644 index 00000000000..f7cfbb5b287 --- /dev/null +++ b/src/mame/audio/dsbz80.c @@ -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; + + +//------------------------------------------------- +// 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; +} diff --git a/src/mame/audio/dsbz80.h b/src/mame/audio/dsbz80.h new file mode 100644 index 00000000000..bd42c721ddf --- /dev/null +++ b/src/mame/audio/dsbz80.h @@ -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 m_ourcpu; + optional_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__ */ diff --git a/src/mame/drivers/model1.c b/src/mame/drivers/model1.c index d4eec80d09c..4edf13e8405 100644 --- a/src/mame/drivers/model1.c +++ b/src/mame/drivers/model1.c @@ -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,12 +1337,12 @@ 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_LOAD( "epr-16471.bin", 0x000000, 0x020000, CRC(f4ee84a4) SHA1(f12b214e6f195b0e5f49ba9f41d8e54bfcea9acc) ) + 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_LOAD( "mpr-16514.bin", 0x000000, 0x200000, CRC(3175b0be) SHA1(63649d053c8c17ce1746d16d0cc8202be20c302f) ) - ROM_LOAD( "mpr-16515.bin", 0x000000, 0x200000, CRC(3114d748) SHA1(9ef090623cdd2a1d06b5d1bc4b9a07ab4eff5b76) ) + 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) ) ROM_REGION32_LE( 0xc00000, "user1", 0 ) /* TGP model roms */ ROM_LOAD32_WORD( "mpr-16476.26", 0x000000, 0x200000, CRC(d48609ae) SHA1(8c8686a5c9ca4837447a7f70ed194e2f1882b66d) ) @@ -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 ) diff --git a/src/mame/includes/model1.h b/src/mame/includes/model1.h index e14e9c335ac..eb15cba0c49 100644 --- a/src/mame/includes/model1.h +++ b/src/mame/includes/model1.h @@ -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 m_maincpu; // V60 + required_device m_audiocpu; // sound 68000 + optional_device m_dsbz80; // Digital Sound Board struct view *m_view; struct point *m_pointdb; diff --git a/src/mame/mame.mak b/src/mame/mame.mak index e636fe59180..cbe5c4d04b7 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -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