mirror of
https://github.com/holub/mame
synced 2025-04-25 17:56:43 +03:00
277 lines
9.2 KiB
C
277 lines
9.2 KiB
C
/* Hyper NeoGeo 64 Audio */
|
|
|
|
// uses a V53A ( == V33A with extra peripherals eg. DMA, Timers, MMU giving virtual 24-bit address space etc.)
|
|
|
|
/* The uploaded code shows that several different sound program revisions were used
|
|
|
|
sams64 (#)SNK R&D Center (R) NEO-GEO64 Sound Driver Ver 1.00a. (#)Copyright (C) SNK Corp. 1996-1997 All rights reserved
|
|
roadedge (#)SNK R&D Center (R) NEO-GEO64 Sound Driver Ver 1.10. (#)Copyright (C) SNK Corp. 1996-1997 All rights reserved
|
|
xrally (#)SNK R&D Center (R) HYPER NEOGEO64 Sound Driver Ver 1.10. (#)Copyright (C) SNK Corp. 1997,1998 All rights reserved
|
|
bbust2 (#)SNK R&D Center (R) HYPER NEOGEO64 Sound Driver Ver 1.11. (#)Copyright (C) SNK Corp. 1997,1998 All rights reserved
|
|
sams64_2 (#)SNK R&D Center (R) HYPER NEOGEO64 Sound Driver Ver 1.14. (#)Copyright (C) SNK Corp. 1997,1998 All rights reserved
|
|
fatfurwa (#)SNK R&D Center (R) HYPER NEOGEO64 Sound Driver Ver 1.14. (#)Copyright (C) SNK Corp. 1997,1998 All rights reserved
|
|
buriki (#)SNK R&D Center (R) HYPER NEOGEO64 Sound Driver Ver 1.15. (#)Copyright (C) SNK Corp. 1997,1998 All rights reserved
|
|
|
|
The earlier revisions appear to have 2 banks of code (there are vectors at the end of the 0x1e0000 block and the 0x1f0000 block)
|
|
|
|
Those first two revisions also spam the entire range of I/O ports with values several times on startup causing some unexpected
|
|
writes to the V53 internal registers. The important ones are reinitialized after this however, I'm guessing this is harmless
|
|
on real hardware, as the code flow seems to be correct.
|
|
|
|
data structures look very similar between all of them
|
|
|
|
*/
|
|
|
|
|
|
#include "includes/hng64.h"
|
|
|
|
// save the sound program?
|
|
#define DUMP_SOUNDPRG 0
|
|
|
|
// ----------------------------------------------
|
|
// MIPS side
|
|
// ----------------------------------------------
|
|
|
|
// if you actually map RAM here on the MIPS side then xrally will upload the actual sound program here and blank out the area where
|
|
// the program would usually be uploaded (and where all other games upload it) this seems to suggest that the area is unmapped on
|
|
// real hardware.
|
|
WRITE32_MEMBER(hng64_state::hng64_soundram2_w)
|
|
{
|
|
}
|
|
|
|
READ32_MEMBER(hng64_state::hng64_soundram2_r)
|
|
{
|
|
return 0x0000;
|
|
}
|
|
|
|
|
|
WRITE32_MEMBER(hng64_state::hng64_soundram_w)
|
|
{
|
|
//logerror("hng64_soundram_w %08x: %08x %08x\n", offset, data, mem_mask);
|
|
|
|
UINT32 mem_mask32 = mem_mask;
|
|
UINT32 data32 = data;
|
|
|
|
/* swap data around.. keep the v55 happy */
|
|
data = data32 >> 16;
|
|
data = FLIPENDIAN_INT16(data);
|
|
mem_mask = mem_mask32 >> 16;
|
|
mem_mask = FLIPENDIAN_INT16(mem_mask);
|
|
COMBINE_DATA(&m_soundram[offset * 2 + 0]);
|
|
|
|
data = data32 & 0xffff;
|
|
data = FLIPENDIAN_INT16(data);
|
|
mem_mask = mem_mask32 & 0xffff;
|
|
mem_mask = FLIPENDIAN_INT16(mem_mask);
|
|
COMBINE_DATA(&m_soundram[offset * 2 + 1]);
|
|
|
|
if (DUMP_SOUNDPRG)
|
|
{
|
|
if (offset==0x7ffff)
|
|
{
|
|
logerror("dumping sound program in m_soundram\n");
|
|
FILE *fp;
|
|
char filename[256];
|
|
sprintf(filename,"soundram_%s", space.machine().system().name);
|
|
fp=fopen(filename, "w+b");
|
|
if (fp)
|
|
{
|
|
fwrite((UINT8*)m_soundram, 0x80000*4, 1, fp);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
READ32_MEMBER(hng64_state::hng64_soundram_r)
|
|
{
|
|
UINT16 datalo = m_soundram[offset * 2 + 0];
|
|
UINT16 datahi = m_soundram[offset * 2 + 1];
|
|
|
|
return FLIPENDIAN_INT16(datahi) | (FLIPENDIAN_INT16(datalo) << 16);
|
|
}
|
|
|
|
WRITE32_MEMBER( hng64_state::hng64_soundcpu_enable_w )
|
|
{
|
|
if (mem_mask&0xffff0000)
|
|
{
|
|
int cmd = data >> 16;
|
|
// I guess it's only one of the bits, the commands are inverse of each other
|
|
if (cmd==0x55AA)
|
|
{
|
|
printf("soundcpu ON\n");
|
|
m_audiocpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
|
|
m_audiocpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
|
|
}
|
|
else if (cmd==0xAA55)
|
|
{
|
|
printf("soundcpu OFF\n");
|
|
m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
|
|
m_audiocpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
|
}
|
|
else
|
|
{
|
|
printf("unknown hng64_soundcpu_enable_w cmd %04x\n", cmd);
|
|
}
|
|
}
|
|
|
|
if (mem_mask&0x0000ffff)
|
|
{
|
|
printf("unknown hng64_soundcpu_enable_w %08x %08x\n", data, mem_mask);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------
|
|
// General
|
|
// ----------------------------------------------
|
|
|
|
|
|
void hng64_state::reset_sound()
|
|
{
|
|
UINT8 *RAM = (UINT8*)m_soundram;
|
|
membank("bank1")->set_base(&RAM[0x1f0000]); // allows us to boot
|
|
membank("bank2")->set_base(&RAM[0x1f0000]); // seems to be the right default for most games (initial area jumps to a DI here)
|
|
m_audiocpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
|
|
m_audiocpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
|
}
|
|
|
|
// ----------------------------------------------
|
|
// V53A side
|
|
// ----------------------------------------------
|
|
|
|
|
|
static ADDRESS_MAP_START( hng_sound_map, AS_PROGRAM, 16, hng64_state )
|
|
AM_RANGE(0x00000, 0x0ffff) AM_RAMBANK("bank2")
|
|
AM_RANGE(0x10000, 0x1ffff) AM_RAM // tmp, roadedge
|
|
AM_RANGE(0xf0000, 0xfffff) AM_RAMBANK("bank1")
|
|
ADDRESS_MAP_END
|
|
|
|
WRITE16_MEMBER(hng64_state::hng64_sound_port_0008_w)
|
|
{
|
|
// printf("hng64_sound_port_0008_w %04x %04x\n", data, mem_mask);
|
|
// seems to one or more of the DMARQ on the V53, writes here when it expects DMA channel 3 to transfer ~0x20 bytes just after startup
|
|
|
|
|
|
m_audiocpu->dreq3_w(data&1);
|
|
// m_audiocpu->hack_w(1);
|
|
|
|
}
|
|
|
|
WRITE16_MEMBER(hng64_state::hng64_sound_select_w)
|
|
{
|
|
// seems to write values in the format xxyy where yy is 0x00-0x1f and xx is oten 00/01/0a
|
|
// there are said to be 32 audio channels, so maybe the lower byte is the channel?
|
|
|
|
// printf("hng64_sound_select_w")
|
|
COMBINE_DATA(&m_audiochannel);
|
|
}
|
|
|
|
WRITE16_MEMBER(hng64_state::hng64_sound_data_02_w)
|
|
{
|
|
m_audiodat[m_audiochannel].dat[2] = data;
|
|
// printf("write port 0x0002 chansel %04x data %04x (%04x%04x%04x)\n", m_audiochannel, data, m_audiodat[m_audiochannel].dat[0], m_audiodat[m_audiochannel].dat[1], m_audiodat[m_audiochannel].dat[2]);
|
|
}
|
|
|
|
WRITE16_MEMBER(hng64_state::hng64_sound_data_04_w)
|
|
{
|
|
m_audiodat[m_audiochannel].dat[1] = data;
|
|
// printf("write port 0x0004 chansel %04x data %04x (%04x%04x%04x)\n", m_audiochannel, data, m_audiodat[m_audiochannel].dat[0], m_audiodat[m_audiochannel].dat[1], m_audiodat[m_audiochannel].dat[2]);
|
|
}
|
|
WRITE16_MEMBER(hng64_state::hng64_sound_data_06_w)
|
|
{
|
|
m_audiodat[m_audiochannel].dat[0] = data;
|
|
// printf("write port 0x0006 chansel %04x data %04x (%04x%04x%04x)\n", m_audiochannel, data, m_audiodat[m_audiochannel].dat[0], m_audiodat[m_audiochannel].dat[1], m_audiodat[m_audiochannel].dat[2]);
|
|
}
|
|
|
|
// but why not just use the V33/V53 XA mode??
|
|
WRITE16_MEMBER(hng64_state::hng64_sound_bank_w)
|
|
{
|
|
printf("%08x hng64_sound_bank_w? %02x %04x\n", space.device().safe_pc(), offset, data);
|
|
// buriki writes 0x3f to 0x200 before jumping to the low addresses..
|
|
// where it expects to find data from 0x1f0000
|
|
|
|
// the 2 early games don't do this.. maybe all banks actuallly default to that region tho?
|
|
// the sound code on those games seems buggier anyway.
|
|
}
|
|
|
|
WRITE16_MEMBER(hng64_state::hng64_sound_port_0102_w)
|
|
{
|
|
printf("hng64_port 0x0102 %04x\n", data);
|
|
}
|
|
|
|
WRITE16_MEMBER(hng64_state::hng64_sound_port_0080_w)
|
|
{
|
|
printf("hng64_port 0x0080 %04x\n", data);
|
|
}
|
|
|
|
static ADDRESS_MAP_START( hng_sound_io, AS_IO, 16, hng64_state )
|
|
AM_RANGE(0x0000, 0x0001) AM_WRITE( hng64_sound_select_w )
|
|
AM_RANGE(0x0002, 0x0003) AM_WRITE( hng64_sound_data_02_w )
|
|
AM_RANGE(0x0004, 0x0005) AM_WRITE( hng64_sound_data_04_w )
|
|
AM_RANGE(0x0006, 0x0007) AM_WRITE( hng64_sound_data_06_w )
|
|
AM_RANGE(0x0008, 0x0009) AM_WRITE( hng64_sound_port_0008_w )
|
|
// a 8 c used too?
|
|
|
|
AM_RANGE(0x0080, 0x0081) AM_WRITE( hng64_sound_port_0080_w )
|
|
|
|
AM_RANGE(0x0102, 0x0103) AM_WRITE( hng64_sound_port_0102_w )
|
|
|
|
AM_RANGE(0x0200, 0x021f) AM_WRITE( hng64_sound_bank_w ) // ??
|
|
|
|
ADDRESS_MAP_END
|
|
|
|
WRITE_LINE_MEMBER(hng64_state::dma_hreq_cb)
|
|
{
|
|
m_audiocpu->hack_w(1);
|
|
}
|
|
|
|
READ8_MEMBER(hng64_state::dma_memr_cb)
|
|
{
|
|
return m_audiocpu->space(AS_PROGRAM).read_byte(offset);;
|
|
}
|
|
|
|
WRITE8_MEMBER(hng64_state::dma_iow3_cb)
|
|
{
|
|
// currently it reads a block of 0x20 '0x00' values from a very specific block of RAM where there is a 0x20 space in the data and transfers them repeatedly, I assume
|
|
// this is some kind of buffer for the audio or DSP and eventually will be populated with other values...
|
|
// if this comes to life maybe something interesting is happening!
|
|
if (data!=0x00) printf("dma_iow3_cb %02x\n", data);
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(hng64_state::tcu_tm0_cb)
|
|
{
|
|
// this goes high once near startup
|
|
printf("tcu_tm0_cb %02x\n", state);
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(hng64_state::tcu_tm1_cb)
|
|
{
|
|
// these are very active, maybe they feed back into the v53 via one of the IRQ pins? TM2 toggles more rapidly than TM1
|
|
// printf("tcu_tm1_cb %02x\n", state);
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(hng64_state::tcu_tm2_cb)
|
|
{
|
|
// these are very active, maybe they feed back into the v53 via one of the IRQ pins? TM2 toggles more rapidly than TM1
|
|
// printf("tcu_tm2_cb %02x\n", state);
|
|
}
|
|
|
|
|
|
|
|
MACHINE_CONFIG_FRAGMENT( hng64_audio )
|
|
MCFG_CPU_ADD("audiocpu", V53A, 16000000) // V53A, 16? mhz!
|
|
MCFG_CPU_PROGRAM_MAP(hng_sound_map)
|
|
MCFG_CPU_IO_MAP(hng_sound_io)
|
|
MCFG_V53_DMAU_OUT_HREQ_CB(WRITELINE(hng64_state, dma_hreq_cb))
|
|
MCFG_V53_DMAU_IN_MEMR_CB(READ8(hng64_state, dma_memr_cb))
|
|
MCFG_V53_DMAU_OUT_IOW_3_CB(WRITE8(hng64_state,dma_iow3_cb))
|
|
|
|
MCFG_V53_TCU_OUT0_HANDLER(WRITELINE(hng64_state, tcu_tm0_cb))
|
|
MCFG_V53_TCU_OUT1_HANDLER(WRITELINE(hng64_state, tcu_tm1_cb))
|
|
MCFG_V53_TCU_OUT2_HANDLER(WRITELINE(hng64_state, tcu_tm2_cb))
|
|
|
|
MACHINE_CONFIG_END
|
|
|
|
|