mirror of
https://github.com/holub/mame
synced 2025-07-01 16:19:38 +03:00
Split S-SMP and S-DSP implement in snes_snd.cpp (#6417)
* Split S-SMP and S-DSP implement in snes_snd.cpp both convert memory handler into device_memory_interface, Internalize ROM region of S-SMP s_smp.cpp : Use callback for S-DSP interface, Split internal and external memory space snes.cpp : Convert WRAM into shared_ptr * s_dsp.cpp : Reduce #define macros
This commit is contained in:
parent
7b060ff044
commit
6aef7adadd
@ -4269,6 +4269,18 @@ if (MACHINES["I3002"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/s_smp.h,MACHINES["S_SMP"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["S_SMP"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/s_smp.cpp",
|
||||
MAME_DIR .. "src/devices/machine/s_smp.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/cxd1185.h,MACHINES["CXD1185"] = true
|
||||
|
@ -1566,6 +1566,18 @@ if (SOUNDS["VGMVIZ"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/sound/s_dsp.h,SOUNDS["S_DSP"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (SOUNDS["S_DSP"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/sound/s_dsp.cpp",
|
||||
MAME_DIR .. "src/devices/sound/s_dsp.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/sound/ks0164.h,SOUNDS["KS0164"] = true
|
||||
|
@ -279,6 +279,7 @@ SOUNDS["MM5837"] = true
|
||||
--SOUNDS["DAVE"] = true
|
||||
SOUNDS["LC7535"] = true
|
||||
--SOUNDS["UPD934G"] = true
|
||||
SOUNDS["S_DSP"] = true
|
||||
SOUNDS["KS0164"] = true
|
||||
|
||||
--------------------------------------------------
|
||||
@ -595,6 +596,7 @@ MACHINES["RSTBUF"] = true
|
||||
MACHINES["RTC4543"] = true
|
||||
MACHINES["RTC65271"] = true
|
||||
MACHINES["RTC9701"] = true
|
||||
MACHINES["S_SMP"] = true
|
||||
MACHINES["S2636"] = true
|
||||
MACHINES["S3520CF"] = true
|
||||
MACHINES["S3C24XX"] = true
|
||||
@ -3099,8 +3101,6 @@ files {
|
||||
MAME_DIR .. "src/mame/video/n8080.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/nss.cpp",
|
||||
MAME_DIR .. "src/mame/machine/snes.cpp",
|
||||
MAME_DIR .. "src/mame/audio/snes_snd.cpp",
|
||||
MAME_DIR .. "src/mame/audio/snes_snd.h",
|
||||
MAME_DIR .. "src/mame/drivers/playch10.cpp",
|
||||
MAME_DIR .. "src/mame/includes/playch10.h",
|
||||
MAME_DIR .. "src/mame/machine/playch10.cpp",
|
||||
|
@ -302,6 +302,7 @@ SOUNDS["IOPSPU"] = true
|
||||
SOUNDS["SWP00"] = true
|
||||
SOUNDS["SWP20"] = true
|
||||
SOUNDS["SWP30"] = true
|
||||
SOUNDS["S_DSP"] = true
|
||||
SOUNDS["ROLANDPCM"] = true
|
||||
|
||||
--------------------------------------------------
|
||||
@ -617,6 +618,7 @@ MACHINES["RSTBUF"] = true
|
||||
MACHINES["RTC4543"] = true
|
||||
MACHINES["RTC65271"] = true
|
||||
MACHINES["RTC9701"] = true
|
||||
MACHINES["S_SMP"] = true
|
||||
--MACHINES["S2636"] = true
|
||||
MACHINES["S3520CF"] = true
|
||||
MACHINES["S3C24XX"] = true
|
||||
@ -1419,8 +1421,6 @@ files {
|
||||
MAME_DIR .. "src/mame/machine/kabuki.h",
|
||||
MAME_DIR .. "src/mame/video/pk8000.cpp",
|
||||
MAME_DIR .. "src/mame/machine/snes.cpp",
|
||||
MAME_DIR .. "src/mame/audio/snes_snd.cpp",
|
||||
MAME_DIR .. "src/mame/audio/snes_snd.h",
|
||||
MAME_DIR .. "src/mame/machine/n64.cpp",
|
||||
MAME_DIR .. "src/mame/video/n64.cpp",
|
||||
MAME_DIR .. "src/mame/video/n64types.h",
|
||||
|
@ -222,8 +222,13 @@ DEFINE_DEVICE_TYPE(SPC700, spc700_device, "spc700", "Sony SPC700")
|
||||
|
||||
|
||||
spc700_device::spc700_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: cpu_device(mconfig, SPC700, tag, owner, clock)
|
||||
, m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0)
|
||||
: spc700_device(mconfig, SPC700, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
spc700_device::spc700_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map)
|
||||
: cpu_device(mconfig, type, tag, owner, clock)
|
||||
, m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, internal_map)
|
||||
, m_a(0)
|
||||
, m_x(0)
|
||||
, m_y(0)
|
||||
|
@ -13,6 +13,9 @@ public:
|
||||
spc700_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
protected:
|
||||
// construction/destruction
|
||||
spc700_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map = address_map_constructor());
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
@ -36,9 +39,8 @@ protected:
|
||||
// device_disasm_interface overrides
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
|
||||
private:
|
||||
address_space_config m_program_config;
|
||||
|
||||
private:
|
||||
uint32_t m_a; /* Accumulator */
|
||||
uint32_t m_x; /* Index Register X */
|
||||
uint32_t m_y; /* Index Register Y */
|
||||
|
321
src/devices/machine/s_smp.cpp
Normal file
321
src/devices/machine/s_smp.cpp
Normal file
@ -0,0 +1,321 @@
|
||||
// license:LGPL-2.1+
|
||||
// copyright-holders:R. Belmont, Brad Martin
|
||||
/***************************************************************************
|
||||
|
||||
s_smp.cpp
|
||||
|
||||
File to handle the S-SMP emulation used in Nintendo Super NES.
|
||||
|
||||
By R. Belmont, adapted from OpenSPC 0.3.99 by Brad Martin with permission.
|
||||
Thanks to Brad and also to Charles Bilyu? of SNeESe.
|
||||
|
||||
OpenSPC's license terms (the LGPL) follow:
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright Brad Martin.
|
||||
|
||||
OpenSPC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenSPC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "s_smp.h"
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS AND MACROS
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
// Nintendo/Sony S-SMP internal ROM region
|
||||
ROM_START( s_smp )
|
||||
ROM_REGION( 0x40, "sound_ipl", 0 ) /* IPL ROM */
|
||||
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
||||
ROM_END
|
||||
|
||||
|
||||
void s_smp_device::internal_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x00ef).lrw8(
|
||||
[this](offs_t offset) -> u8 { return data_read_byte(offset); }, "data_r",
|
||||
[this](offs_t offset, u8 data) { data_write_byte(offset, data); }, "data_w");
|
||||
map(0x00f0, 0x00ff).rw(FUNC(s_smp_device::io_r), FUNC(s_smp_device::io_w));
|
||||
map(0x0100, 0xffff).lrw8(
|
||||
[this](offs_t offset) -> u8 { return data_read_byte(offset + 0x100); }, "data_100_r",
|
||||
[this](offs_t offset, u8 data) { data_write_byte(offset + 0x100, data); }, "data_100_w");
|
||||
}
|
||||
|
||||
|
||||
DEFINE_DEVICE_TYPE(S_SMP, s_smp_device, "s_smp", "Nintendo/Sony S-SMP")
|
||||
|
||||
|
||||
s_smp_device::s_smp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: spc700_device(mconfig, S_SMP, tag, owner, clock, address_map_constructor(FUNC(s_smp_device::internal_map), this))
|
||||
, m_data_config("data", ENDIANNESS_LITTLE, 8, 16)
|
||||
, m_ipl_region(*this, "sound_ipl")
|
||||
, m_dsp_io_r_cb(*this)
|
||||
, m_dsp_io_w_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// rom_region - return a pointer to the device's
|
||||
// internal ROM region
|
||||
//-------------------------------------------------
|
||||
|
||||
const tiny_rom_entry *s_smp_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME( s_smp );
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void s_smp_device::device_start()
|
||||
{
|
||||
m_dsp_io_r_cb.resolve_safe(0);
|
||||
m_dsp_io_w_cb.resolve_safe();
|
||||
|
||||
m_data = &space(AS_DATA);
|
||||
// Find our direct access
|
||||
m_dcache = m_data->cache<0, 0, ENDIANNESS_LITTLE>();
|
||||
|
||||
m_tick_timer = timer_alloc(TIMER_TICK_ID);
|
||||
|
||||
save_item(NAME(m_timer_enabled));
|
||||
save_item(NAME(m_subcounter));
|
||||
save_item(NAME(m_counter));
|
||||
save_item(NAME(m_port_in));
|
||||
save_item(NAME(m_port_out));
|
||||
save_item(NAME(m_test));
|
||||
save_item(NAME(m_ctrl));
|
||||
save_item(NAME(m_counter_reg));
|
||||
|
||||
save_item(NAME(m_TnDIV));
|
||||
spc700_device::device_start();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void s_smp_device::device_reset()
|
||||
{
|
||||
int i;
|
||||
/* default to ROM visible */
|
||||
m_ctrl = 0x80;
|
||||
|
||||
/* Sort out the ports */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
m_port_in[i] = 0;
|
||||
m_port_out[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
m_timer_enabled[i] = false;
|
||||
m_TnDIV[i] = 256;
|
||||
m_counter[i] = 0;
|
||||
m_subcounter[i] = 0;
|
||||
}
|
||||
|
||||
attotime period = attotime::from_ticks(32, clock());
|
||||
m_tick_timer->adjust(period, 0, period);
|
||||
spc700_device::device_reset();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_clock_changed - called if the clock
|
||||
// changes
|
||||
//-------------------------------------------------
|
||||
|
||||
void s_smp_device::device_clock_changed()
|
||||
{
|
||||
attotime period = attotime::from_ticks(32, clock());
|
||||
m_tick_timer->adjust(period, 0, period);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// memory_space_config - return a description of
|
||||
// any address spaces owned by this device
|
||||
//-------------------------------------------------
|
||||
|
||||
device_memory_interface::space_config_vector s_smp_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector{
|
||||
std::make_pair(AS_PROGRAM, &m_program_config),
|
||||
std::make_pair(AS_DATA, &m_data_config)
|
||||
};
|
||||
}
|
||||
|
||||
inline void s_smp_device::update_timer_tick(u8 which)
|
||||
{
|
||||
if (m_timer_enabled[which] == false)
|
||||
return;
|
||||
|
||||
m_subcounter[which]++;
|
||||
|
||||
// if timer channel is 0 or 1 we update at 64000/8
|
||||
if (m_subcounter[which] >= 8 || which == 2)
|
||||
{
|
||||
m_subcounter[which] = 0;
|
||||
m_counter[which]++;
|
||||
if (m_counter[which] >= m_TnDIV[which] ) // minus =
|
||||
{
|
||||
m_counter[which] = 0;
|
||||
m_counter_reg[which]++;
|
||||
m_counter_reg[which] &= 0x0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void s_smp_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
if (id != TIMER_TICK_ID)
|
||||
throw emu_fatalerror("Unknown id in s_smp_device::device_timer");
|
||||
|
||||
for (int ch = 0; ch < 3; ch++)
|
||||
update_timer_tick(ch);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
IMPLEMENTATION
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/***************************
|
||||
I/O for S-SMP
|
||||
***************************/
|
||||
|
||||
u8 s_smp_device::io_r(offs_t offset)
|
||||
{
|
||||
switch (offset) /* Offset is from 0x00f0 */
|
||||
{
|
||||
case 0x0: //FIXME: Super Bomberman PBW reads from there, is it really write-only?
|
||||
return 0;
|
||||
case 0x1:
|
||||
return 0; //Super Kick Boxing reads port 1 and wants it to be zero.
|
||||
case 0x2: /* Register address */
|
||||
case 0x3: /* Register data */
|
||||
return m_dsp_io_r_cb(offset - 0x2);
|
||||
case 0x4: /* Port 0 */
|
||||
case 0x5: /* Port 1 */
|
||||
case 0x6: /* Port 2 */
|
||||
case 0x7: /* Port 3 */
|
||||
// osd_printf_debug("%s SPC: rd %02x @ %d\n", machine().describe_context(), m_port_in[offset - 4], offset - 4);
|
||||
return m_port_in[offset - 4];
|
||||
case 0x8: //normal RAM, can be read even if the ram disabled flag ($f0 bit 1) is active
|
||||
case 0x9:
|
||||
return data_read_byte(0xf0 + offset);
|
||||
case 0xa: /* Timer 0 */
|
||||
case 0xb: /* Timer 1 */
|
||||
case 0xc: /* Timer 2 */
|
||||
break;
|
||||
case 0xd: /* Counter 0 */
|
||||
case 0xe: /* Counter 1 */
|
||||
case 0xf: /* Counter 2 */
|
||||
{
|
||||
u8 value = m_counter_reg[offset - 0xd] & 0x0f;
|
||||
if (!machine().side_effects_disabled())
|
||||
m_counter_reg[offset - 0xd] = 0;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void s_smp_device::io_w(offs_t offset, u8 data)
|
||||
{
|
||||
switch (offset) /* Offset is from 0x00f0 */
|
||||
{
|
||||
case 0x0:
|
||||
m_test = data;
|
||||
logerror("Warning: write to SOUND TEST register with data %02x!\n", data);
|
||||
break;
|
||||
case 0x1: /* Control */
|
||||
m_ctrl = data;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (BIT(data, i) && m_timer_enabled[i] == false)
|
||||
{
|
||||
m_subcounter[i] = 0;
|
||||
m_counter[i] = 0;
|
||||
m_counter_reg[i] = 0;
|
||||
}
|
||||
|
||||
m_timer_enabled[i] = BIT(data, i);
|
||||
//m_timer[i]->enable(m_timer_enabled[i]);
|
||||
}
|
||||
|
||||
if (BIT(data, 4))
|
||||
{
|
||||
m_port_in[0] = 0;
|
||||
m_port_in[1] = 0;
|
||||
}
|
||||
|
||||
if (BIT(data, 5))
|
||||
{
|
||||
m_port_in[2] = 0;
|
||||
m_port_in[3] = 0;
|
||||
}
|
||||
|
||||
/* bit 7 = IPL ROM enable */
|
||||
break;
|
||||
case 0x2: /* Register address */
|
||||
case 0x3: /* Register data - 0x80-0xff is a read-only mirror of 0x00-0x7f */
|
||||
m_dsp_io_w_cb(offset - 0x2, data);
|
||||
break;
|
||||
case 0x4: /* Port 0 */
|
||||
case 0x5: /* Port 1 */
|
||||
case 0x6: /* Port 2 */
|
||||
case 0x7: /* Port 3 */
|
||||
// osd_printf_debug("%s SPC: %02x to APU @ %d\n", machine().describe_context(), data, offset & 3);
|
||||
m_port_out[offset - 4] = data;
|
||||
// Unneeded, we already run at perfect_interleave
|
||||
// machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(20));
|
||||
break;
|
||||
case 0xa: /* Timer 0 */
|
||||
case 0xb: /* Timer 1 */
|
||||
case 0xc: /* Timer 2 */
|
||||
// if 0 then TnDiv is divided by 256, otherwise it's divided by 1 to 255
|
||||
if (data == 0)
|
||||
m_TnDIV[offset - 0xa] = 256;
|
||||
else
|
||||
m_TnDIV[offset - 0xa] = data;
|
||||
break;
|
||||
case 0xd: /* Counter 0 */
|
||||
case 0xe: /* Counter 1 */
|
||||
case 0xf: /* Counter 2 */
|
||||
return;
|
||||
}
|
||||
|
||||
data_write_byte(0xf0 + offset, data);
|
||||
}
|
||||
|
||||
|
||||
u8 s_smp_device::spc_port_out_r(offs_t offset)
|
||||
{
|
||||
assert(offset < 4);
|
||||
|
||||
return m_port_out[offset];
|
||||
}
|
||||
|
||||
void s_smp_device::spc_port_in_w(offs_t offset, u8 data)
|
||||
{
|
||||
assert(offset < 4);
|
||||
|
||||
m_port_in[offset] = data;
|
||||
}
|
90
src/devices/machine/s_smp.h
Normal file
90
src/devices/machine/s_smp.h
Normal file
@ -0,0 +1,90 @@
|
||||
// license:LGPL-2.1+
|
||||
// copyright-holders:R. Belmont, Brad Martin
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Nintendo/Sony S-SMP emulation
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef MAME_MACHINE_S_SMP_H
|
||||
#define MAME_MACHINE_S_SMP_H
|
||||
|
||||
#include "cpu/spc700/spc700.h"
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
class s_smp_device : public spc700_device
|
||||
{
|
||||
public:
|
||||
s_smp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
auto dsp_io_read_callback() { return m_dsp_io_r_cb.bind(); }
|
||||
auto dsp_io_write_callback() { return m_dsp_io_w_cb.bind(); }
|
||||
|
||||
u8 spc_port_out_r(offs_t offset);
|
||||
void spc_port_in_w(offs_t offset, u8 data);
|
||||
|
||||
protected:
|
||||
tiny_rom_entry const *device_rom_region() const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_clock_changed() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
// device_memory_interface configuration
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
address_space_config m_data_config;
|
||||
|
||||
private:
|
||||
address_space *m_data;
|
||||
memory_access_cache<0, 0, ENDIANNESS_LITTLE> *m_dcache;
|
||||
inline u8 data_read_byte(offs_t a)
|
||||
{
|
||||
/* IPL ROM enabled */
|
||||
if (a >= 0xffc0 && m_ctrl & 0x80)
|
||||
return m_ipl_region[a & 0x3f];
|
||||
|
||||
return m_dcache->read_byte(a);
|
||||
}
|
||||
inline void data_write_byte(offs_t a, u8 d) { m_data->write_byte(a, d); }
|
||||
|
||||
required_region_ptr<u8> m_ipl_region; /* SPC top 64 bytes */
|
||||
|
||||
u8 io_r(offs_t offset);
|
||||
void io_w(offs_t offset, u8 data);
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_TICK_ID = 1
|
||||
};
|
||||
/* timers */
|
||||
emu_timer *m_tick_timer;
|
||||
bool m_timer_enabled[3];
|
||||
u16 m_counter[3];
|
||||
u8 m_subcounter[3];
|
||||
inline void update_timer_tick(u8 which);
|
||||
|
||||
/* IO ports */
|
||||
u8 m_port_in[4]; /* SPC input ports */
|
||||
u8 m_port_out[4]; /* SPC output ports */
|
||||
|
||||
u16 m_TnDIV[3]; /**< Timer N Divider */
|
||||
|
||||
// registers
|
||||
u8 m_test;
|
||||
u8 m_ctrl;
|
||||
u8 m_counter_reg[3];
|
||||
|
||||
devcb_read8 m_dsp_io_r_cb;
|
||||
devcb_write8 m_dsp_io_w_cb;
|
||||
|
||||
void internal_map(address_map &map);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(S_SMP, s_smp_device)
|
||||
|
||||
|
||||
#endif // MAME_MACHINE_S_SMP_H
|
@ -2,9 +2,9 @@
|
||||
// copyright-holders:R. Belmont, Brad Martin
|
||||
/***************************************************************************
|
||||
|
||||
snes_snd.cpp
|
||||
s_dsp.cpp
|
||||
|
||||
File to handle the sound emulation of the Nintendo Super NES.
|
||||
File to handle the S-DSP emulation used in Nintendo Super NES.
|
||||
|
||||
By R. Belmont, adapted from OpenSPC 0.3.99 by Brad Martin with permission.
|
||||
Thanks to Brad and also to Charles Bilyu? of SNeESe.
|
||||
@ -28,7 +28,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "audio/snes_snd.h"
|
||||
#include "s_dsp.h"
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS AND MACROS
|
||||
@ -135,72 +135,42 @@ static const int ENVCNT[0x20]
|
||||
};
|
||||
|
||||
|
||||
/* Make reading the ADSR code easier */
|
||||
#define SL( v ) (m_dsp_regs[((v) << 4) + 6] >> 5) /* Returns SUSTAIN level */
|
||||
#define SR( v ) (m_dsp_regs[((v) << 4) + 6] & 0x1f) /* Returns SUSTAIN rate */
|
||||
|
||||
/* Handle endianness */
|
||||
#define LEtoME16( x ) little_endianize_int16(x)
|
||||
#define MEtoLE16( x ) little_endianize_int16(x)
|
||||
|
||||
ALLOW_SAVE_TYPE(snes_sound_device::env_state_t32);
|
||||
ALLOW_SAVE_TYPE(s_dsp_device::env_state_t32);
|
||||
|
||||
|
||||
DEFINE_DEVICE_TYPE(SNES_SOUND, snes_sound_device, "snes_sound", "SNES Custom DSP (SPC700)")
|
||||
DEFINE_DEVICE_TYPE(S_DSP, s_dsp_device, "s_dsp", "Nintendo/Sony S-DSP")
|
||||
|
||||
snes_sound_device::snes_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, SNES_SOUND, tag, owner, clock)
|
||||
|
||||
s_dsp_device::s_dsp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, S_DSP, tag, owner, clock)
|
||||
, device_sound_interface(mconfig, *this)
|
||||
, device_memory_interface(mconfig, *this)
|
||||
, m_data_config("data", ENDIANNESS_LITTLE, 8, 16)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void snes_sound_device::device_start()
|
||||
void s_dsp_device::device_start()
|
||||
{
|
||||
m_data = &space(0);
|
||||
// Find our direct access
|
||||
m_cache = m_data->cache<0, 0, ENDIANNESS_LITTLE>();
|
||||
|
||||
m_channel = machine().sound().stream_alloc(*this, 0, 2, clock() / 64);
|
||||
|
||||
m_ram = make_unique_clear<u8[]>(SNES_SPCRAM_SIZE);
|
||||
|
||||
/* put IPL image at the top of RAM */
|
||||
memcpy(m_ipl_region, machine().root_device().memregion("sound_ipl")->base(), 64);
|
||||
|
||||
m_tick_timer = timer_alloc(TIMER_TICK_ID);
|
||||
|
||||
state_register();
|
||||
save_pointer(NAME(m_ram), SNES_SPCRAM_SIZE);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void snes_sound_device::device_reset()
|
||||
void s_dsp_device::device_reset()
|
||||
{
|
||||
int i;
|
||||
/* default to ROM visible */
|
||||
m_ram[0xf1] = 0x80;
|
||||
|
||||
/* Sort out the ports */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
m_port_in[i] = 0;
|
||||
m_port_out[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
m_timer_enabled[i] = false;
|
||||
m_TnDIV[i] = 256;
|
||||
m_counter[i] = 0;
|
||||
m_subcounter[i] = 0;
|
||||
}
|
||||
|
||||
attotime period = attotime::from_ticks(32, clock());
|
||||
m_tick_timer->adjust(period, 0, period);
|
||||
|
||||
dsp_reset();
|
||||
}
|
||||
|
||||
@ -209,41 +179,19 @@ void snes_sound_device::device_reset()
|
||||
// changes
|
||||
//-------------------------------------------------
|
||||
|
||||
void snes_sound_device::device_clock_changed()
|
||||
void s_dsp_device::device_clock_changed()
|
||||
{
|
||||
m_channel->set_sample_rate(clock() / 64);
|
||||
attotime period = attotime::from_ticks(32, clock());
|
||||
m_tick_timer->adjust(period, 0, period);
|
||||
}
|
||||
|
||||
inline void snes_sound_device::update_timer_tick(u8 which)
|
||||
//-------------------------------------------------
|
||||
// memory_space_config - return a description of
|
||||
// any address spaces owned by this device
|
||||
//-------------------------------------------------
|
||||
|
||||
device_memory_interface::space_config_vector s_dsp_device::memory_space_config() const
|
||||
{
|
||||
if (m_timer_enabled[which] == false)
|
||||
return;
|
||||
|
||||
m_subcounter[which]++;
|
||||
|
||||
// if timer channel is 0 or 1 we update at 64000/8
|
||||
if (m_subcounter[which] >= 8 || which == 2)
|
||||
{
|
||||
m_subcounter[which] = 0;
|
||||
m_counter[which]++;
|
||||
if (m_counter[which] >= m_TnDIV[which] ) // minus =
|
||||
{
|
||||
m_counter[which] = 0;
|
||||
m_ram[0xfd + which]++;
|
||||
m_ram[0xfd + which] &= 0x0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void snes_sound_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
if (id != TIMER_TICK_ID)
|
||||
throw emu_fatalerror("Unknown id in snes_sound_device::device_timer");
|
||||
|
||||
for (int ch = 0; ch < 3; ch++)
|
||||
update_timer_tick(ch);
|
||||
return space_config_vector{ std::make_pair(0, &m_data_config) };
|
||||
}
|
||||
|
||||
|
||||
@ -258,7 +206,7 @@ void snes_sound_device::device_timer(emu_timer &timer, device_timer_id id, int p
|
||||
Reset emulated DSP
|
||||
-------------------------------------------------*/
|
||||
|
||||
void snes_sound_device::dsp_reset()
|
||||
void s_dsp_device::dsp_reset()
|
||||
{
|
||||
#ifdef MAME_DEBUG
|
||||
logerror("dsp_reset\n");
|
||||
@ -295,19 +243,18 @@ void snes_sound_device::dsp_reset()
|
||||
to mix audio into
|
||||
-------------------------------------------------*/
|
||||
|
||||
void snes_sound_device::dsp_update( s16 *sound_ptr )
|
||||
void s_dsp_device::dsp_update( s16 *sound_ptr )
|
||||
{
|
||||
int V;
|
||||
|
||||
int envx;
|
||||
int m;
|
||||
src_dir_type * sd;
|
||||
int v;
|
||||
int vl;
|
||||
voice_state_type * vp;
|
||||
int vr;
|
||||
|
||||
sd = (src_dir_type *) &m_ram[(int) m_dsp_regs[0x5d] << 8];
|
||||
const u16 sd = m_dsp_regs[0x5d];
|
||||
|
||||
/* Check for reset */
|
||||
if (m_dsp_regs[0x6c] & 0x80)
|
||||
@ -355,9 +302,11 @@ void snes_sound_device::dsp_update( s16 *sound_ptr )
|
||||
/* Voice was keyed on */
|
||||
m_keys |= m;
|
||||
m_keyed_on |= m;
|
||||
#ifdef DBG_KEY
|
||||
vl = m_dsp_regs[(v << 4) + 4];
|
||||
vp->samp_id = *( u32 * )&sd[vl];
|
||||
vp->mem_ptr = LEtoME16(sd[vl].vptr);
|
||||
#endif
|
||||
vp->samp_id = (vptr(sd, V) << 16) | lptr(sd, V);
|
||||
vp->mem_ptr = vptr(sd, V);
|
||||
|
||||
#ifdef DBG_KEY
|
||||
logerror("Keying on voice %d, samp=0x%04X (0x%02X)\n", v, vp->mem_ptr, vl);
|
||||
@ -409,7 +358,7 @@ void snes_sound_device::dsp_update( s16 *sound_ptr )
|
||||
continue;
|
||||
}
|
||||
|
||||
vp->pitch = LEtoME16(*((u16 *)&m_dsp_regs[V + 2])) & 0x3fff;
|
||||
vp->pitch = pitch(V);
|
||||
|
||||
#ifndef NO_PMOD
|
||||
/* Pitch mod uses OUTX from last voice for this one. Luckily we haven't
|
||||
@ -445,7 +394,7 @@ void snes_sound_device::dsp_update( s16 *sound_ptr )
|
||||
m_dsp_regs[0x7c] |= m;
|
||||
if (vp->end & 2)
|
||||
{
|
||||
vp->mem_ptr = LEtoME16(sd[m_dsp_regs[V + 4]].lptr);
|
||||
vp->mem_ptr = lptr(sd, V);
|
||||
|
||||
#ifdef DBG_BRR
|
||||
logerror("BRR looping to 0x%04X\n", vp->mem_ptr);
|
||||
@ -472,7 +421,7 @@ void snes_sound_device::dsp_update( s16 *sound_ptr )
|
||||
}
|
||||
|
||||
vp->header_cnt = 8;
|
||||
vl = (u8)m_ram[vp->mem_ptr++];
|
||||
vl = (u8)read_byte(vp->mem_ptr++);
|
||||
vp->range = vl >> 4;
|
||||
vp->end = vl & 3;
|
||||
vp->filter = (vl & 12) >> 2;
|
||||
@ -485,13 +434,13 @@ void snes_sound_device::dsp_update( s16 *sound_ptr )
|
||||
if (vp->half == 0)
|
||||
{
|
||||
vp->half = 1;
|
||||
outx = ((s8)m_ram[vp->mem_ptr]) >> 4;
|
||||
outx = ((s8)read_byte(vp->mem_ptr)) >> 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp->half = 0;
|
||||
/* Funkiness to get 4-bit signed to carry through */
|
||||
outx = (s8)(m_ram[vp->mem_ptr++] << 4);
|
||||
outx = (s8)(read_byte(vp->mem_ptr++) << 4);
|
||||
outx >>= 4;
|
||||
vp->header_cnt--;
|
||||
}
|
||||
@ -644,8 +593,8 @@ void snes_sound_device::dsp_update( s16 *sound_ptr )
|
||||
#endif
|
||||
|
||||
int echo_base = ((m_dsp_regs[0x6d] << 8) + m_echo_ptr) & 0xffff;
|
||||
m_fir_lbuf[m_fir_ptr] = (s16)LEtoME16(*(u16 *)&m_ram[echo_base]);
|
||||
m_fir_rbuf[m_fir_ptr] = (s16)LEtoME16(*(u16 *)&m_ram[echo_base + sizeof(s16)]);
|
||||
m_fir_lbuf[m_fir_ptr] = (s16)read_word(echo_base);
|
||||
m_fir_rbuf[m_fir_ptr] = (s16)read_word(echo_base + sizeof(s16));
|
||||
|
||||
/* Now, evaluate the FIR filter, and add the results into the final output. */
|
||||
vl = m_fir_lbuf[m_fir_ptr] * (s8)m_dsp_regs[0x7f];
|
||||
@ -709,8 +658,8 @@ void snes_sound_device::dsp_update( s16 *sound_ptr )
|
||||
logerror("Echo: Writing %04X,%04X at location %04X\n", (u16)echol, (u16)echor, echo_base);
|
||||
#endif
|
||||
|
||||
*(u16 *)&m_ram[echo_base] = MEtoLE16((u16)echol);
|
||||
*(u16 *)&m_ram[echo_base + sizeof(s16)] = MEtoLE16((u16)echor);
|
||||
write_word(echo_base, (u16)echol);
|
||||
write_word(echo_base + sizeof(s16), (u16)echor);
|
||||
}
|
||||
|
||||
m_echo_ptr += 2 * sizeof(s16);
|
||||
@ -766,7 +715,7 @@ void snes_sound_device::dsp_update( s16 *sound_ptr )
|
||||
to process envelope for.
|
||||
-------------------------------------------------*/
|
||||
|
||||
int snes_sound_device::advance_envelope( int v )
|
||||
int s_dsp_device::advance_envelope( int v )
|
||||
{
|
||||
int t;
|
||||
|
||||
@ -1010,11 +959,11 @@ int snes_sound_device::advance_envelope( int v )
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
spc700_set_volume - sets SPC700 volume level
|
||||
set_volume - sets S-DSP volume level
|
||||
for both speakers, used for fade in/out effects
|
||||
-------------------------------------------------*/
|
||||
|
||||
void snes_sound_device::set_volume(int volume)
|
||||
void s_dsp_device::set_volume(int volume)
|
||||
{
|
||||
m_channel->set_output_gain(0, volume / 100.0);
|
||||
m_channel->set_output_gain(1, volume / 100.0);
|
||||
@ -1025,183 +974,56 @@ void snes_sound_device::set_volume(int volume)
|
||||
I/O for DSP
|
||||
***************************/
|
||||
|
||||
u8 snes_sound_device::dsp_io_r(offs_t offset)
|
||||
u8 s_dsp_device::dsp_io_r(offs_t offset)
|
||||
{
|
||||
m_channel->update();
|
||||
|
||||
#ifdef NO_ENVX
|
||||
if (8 == (m_ram[0xf2] & 0x0f))
|
||||
m_dsp_regs[m_ram[0xf2]] = 0;
|
||||
if (!machine().side_effects_disabled())
|
||||
if (8 == (m_dsp_addr & 0x0f))
|
||||
m_dsp_regs[m_dsp_addr] = 0;
|
||||
#endif
|
||||
|
||||
/* All reads simply return the contents of the addressed register. */
|
||||
return m_dsp_regs[offset & 0x7f];
|
||||
if (offset & 1)
|
||||
return m_dsp_regs[m_dsp_addr & 0x7f];
|
||||
|
||||
return m_dsp_addr;
|
||||
}
|
||||
|
||||
void snes_sound_device::dsp_io_w(offs_t offset, u8 data)
|
||||
void s_dsp_device::dsp_io_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_channel->update();
|
||||
|
||||
if (offset == 0x7c)
|
||||
if (offset & 1)
|
||||
{
|
||||
/* Writes to register 0x7c (ENDX) clear ALL bits no matter which value is written */
|
||||
m_dsp_regs[offset] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All other writes store the value in the addressed register as expected. */
|
||||
m_dsp_regs[offset] = data;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************
|
||||
I/O for SPC700
|
||||
***************************/
|
||||
|
||||
u8 snes_sound_device::spc_io_r(offs_t offset)
|
||||
{
|
||||
switch (offset) /* Offset is from 0x00f0 */
|
||||
{
|
||||
case 0x0: //FIXME: Super Bomberman PBW reads from there, is it really write-only?
|
||||
return 0;
|
||||
case 0x1:
|
||||
return 0; //Super Kick Boxing reads port 1 and wants it to be zero.
|
||||
case 0x2: /* Register address */
|
||||
return m_ram[0xf2];
|
||||
case 0x3: /* Register data */
|
||||
return dsp_io_r(m_ram[0xf2]);
|
||||
case 0x4: /* Port 0 */
|
||||
case 0x5: /* Port 1 */
|
||||
case 0x6: /* Port 2 */
|
||||
case 0x7: /* Port 3 */
|
||||
// osd_printf_debug("%s SPC: rd %02x @ %d\n", machine().describe_context(), m_port_in[offset - 4], offset - 4);
|
||||
return m_port_in[offset - 4];
|
||||
case 0x8: //normal RAM, can be read even if the ram disabled flag ($f0 bit 1) is active
|
||||
case 0x9:
|
||||
return m_ram[0xf0 + offset];
|
||||
case 0xa: /* Timer 0 */
|
||||
case 0xb: /* Timer 1 */
|
||||
case 0xc: /* Timer 2 */
|
||||
break;
|
||||
case 0xd: /* Counter 0 */
|
||||
case 0xe: /* Counter 1 */
|
||||
case 0xf: /* Counter 2 */
|
||||
if (!(m_dsp_addr & 0x80))
|
||||
{
|
||||
u8 value = m_ram[0xf0 + offset] & 0x0f;
|
||||
m_ram[0xf0 + offset] = 0;
|
||||
return value;
|
||||
offset = m_dsp_addr & 0x7f;
|
||||
if (offset == 0x7c)
|
||||
{
|
||||
/* Writes to register 0x7c (ENDX) clear ALL bits no matter which value is written */
|
||||
m_dsp_regs[offset & 0x7f] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All other writes store the value in the addressed register as expected. */
|
||||
m_dsp_regs[offset & 0x7f] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
else
|
||||
m_dsp_addr = data;
|
||||
}
|
||||
|
||||
void snes_sound_device::spc_io_w(offs_t offset, u8 data)
|
||||
{
|
||||
switch (offset) /* Offset is from 0x00f0 */
|
||||
{
|
||||
case 0x0:
|
||||
logerror("Warning: write to SOUND TEST register with data %02x!\n", data);
|
||||
break;
|
||||
case 0x1: /* Control */
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (BIT(data, i) && m_timer_enabled[i] == false)
|
||||
{
|
||||
m_subcounter[i] = 0;
|
||||
m_counter[i] = 0;
|
||||
m_ram[0xfd + i] = 0;
|
||||
}
|
||||
|
||||
m_timer_enabled[i] = BIT(data, i);
|
||||
//m_timer[i]->enable(m_timer_enabled[i]);
|
||||
}
|
||||
|
||||
if (BIT(data, 4))
|
||||
{
|
||||
m_port_in[0] = 0;
|
||||
m_port_in[1] = 0;
|
||||
}
|
||||
|
||||
if (BIT(data, 5))
|
||||
{
|
||||
m_port_in[2] = 0;
|
||||
m_port_in[3] = 0;
|
||||
}
|
||||
|
||||
/* bit 7 = IPL ROM enable */
|
||||
break;
|
||||
case 0x2: /* Register address */
|
||||
break;
|
||||
case 0x3: /* Register data - 0x80-0xff is a read-only mirror of 0x00-0x7f */
|
||||
if (!(m_ram[0xf2] & 0x80))
|
||||
dsp_io_w(m_ram[0xf2] & 0x7f, data);
|
||||
break;
|
||||
case 0x4: /* Port 0 */
|
||||
case 0x5: /* Port 1 */
|
||||
case 0x6: /* Port 2 */
|
||||
case 0x7: /* Port 3 */
|
||||
// osd_printf_debug("%s SPC: %02x to APU @ %d\n", machine().describe_context(), data, offset & 3);
|
||||
m_port_out[offset - 4] = data;
|
||||
// Unneeded, we already run at perfect_interleave
|
||||
// machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(20));
|
||||
break;
|
||||
case 0xa: /* Timer 0 */
|
||||
case 0xb: /* Timer 1 */
|
||||
case 0xc: /* Timer 2 */
|
||||
// if 0 then TnDiv is divided by 256, otherwise it's divided by 1 to 255
|
||||
if (data == 0)
|
||||
m_TnDIV[offset - 0xa] = 256;
|
||||
else
|
||||
m_TnDIV[offset - 0xa] = data;
|
||||
break;
|
||||
case 0xd: /* Counter 0 */
|
||||
case 0xe: /* Counter 1 */
|
||||
case 0xf: /* Counter 2 */
|
||||
return;
|
||||
}
|
||||
|
||||
m_ram[0xf0 + offset] = data;
|
||||
}
|
||||
|
||||
u8 snes_sound_device::spc_ram_r(offs_t offset)
|
||||
{
|
||||
/* IPL ROM enabled */
|
||||
if (offset >= 0xffc0 && m_ram[0xf1] & 0x80)
|
||||
return m_ipl_region[offset & 0x3f];
|
||||
|
||||
return m_ram[offset];
|
||||
}
|
||||
|
||||
void snes_sound_device::spc_ram_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_ram[offset] = data;
|
||||
}
|
||||
|
||||
|
||||
u8 snes_sound_device::spc_port_out(offs_t offset)
|
||||
{
|
||||
assert(offset < 4);
|
||||
|
||||
return m_port_out[offset];
|
||||
}
|
||||
|
||||
void snes_sound_device::spc_port_in(offs_t offset, u8 data)
|
||||
{
|
||||
assert(offset < 4);
|
||||
|
||||
m_port_in[offset] = data;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
DEVICE INTERFACE
|
||||
*****************************************************************************/
|
||||
|
||||
void snes_sound_device::state_register()
|
||||
void s_dsp_device::state_register()
|
||||
{
|
||||
save_item(NAME(m_dsp_addr));
|
||||
save_item(NAME(m_dsp_regs));
|
||||
save_item(NAME(m_ipl_region));
|
||||
|
||||
save_item(NAME(m_keyed_on));
|
||||
save_item(NAME(m_keys));
|
||||
@ -1216,14 +1038,6 @@ void snes_sound_device::state_register()
|
||||
save_item(NAME(m_echo_ptr));
|
||||
#endif
|
||||
|
||||
save_item(NAME(m_timer_enabled));
|
||||
save_item(NAME(m_subcounter));
|
||||
save_item(NAME(m_counter));
|
||||
save_item(NAME(m_port_in));
|
||||
save_item(NAME(m_port_out));
|
||||
|
||||
save_item(NAME(m_TnDIV));
|
||||
|
||||
for (int v = 0; v < 8; v++)
|
||||
{
|
||||
save_item(NAME(m_voice_state[v].mem_ptr), v);
|
||||
@ -1250,7 +1064,7 @@ void snes_sound_device::state_register()
|
||||
// sound_stream_update - handle a stream update
|
||||
//-------------------------------------------------
|
||||
|
||||
void snes_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
void s_dsp_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
s16 mix[2];
|
||||
|
@ -2,33 +2,26 @@
|
||||
// copyright-holders:R. Belmont, Brad Martin
|
||||
/*****************************************************************************
|
||||
*
|
||||
* audio/snes_snd.h
|
||||
* Nintendo/Sony S-DSP emulation
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef MAME_AUDIO_SNES_SND_H
|
||||
#define MAME_AUDIO_SNES_SND_H
|
||||
|
||||
#ifndef MAME_SOUND_S_DSP_H
|
||||
#define MAME_SOUND_S_DSP_H
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
class snes_sound_device : public device_t, public device_sound_interface
|
||||
class s_dsp_device : public device_t, public device_sound_interface, public device_memory_interface
|
||||
{
|
||||
public:
|
||||
snes_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
s_dsp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
void set_volume(int volume);
|
||||
|
||||
u8 spc_io_r(offs_t offset);
|
||||
u8 spc_ram_r(offs_t offset);
|
||||
u8 spc_port_out(offs_t offset);
|
||||
void spc_io_w(offs_t offset, u8 data);
|
||||
void spc_ram_w(offs_t offset, u8 data);
|
||||
void spc_port_in(offs_t offset, u8 data);
|
||||
|
||||
// u8 *spc_get_ram() { return m_ram; }
|
||||
u8 dsp_io_r(offs_t offset);
|
||||
void dsp_io_w(offs_t offset, u8 data);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
@ -38,9 +31,20 @@ protected:
|
||||
|
||||
// sound stream update overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
// device_memory_interface configuration
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
address_space_config m_data_config;
|
||||
|
||||
private:
|
||||
address_space *m_data;
|
||||
memory_access_cache<0, 0, ENDIANNESS_LITTLE> *m_cache;
|
||||
inline u8 read_byte(offs_t a) { return m_cache->read_byte(a); }
|
||||
inline u16 read_word(offs_t a) { return read_byte(a) | (read_byte(a + 1) << 8); }
|
||||
inline void write_byte(offs_t a, u8 d) { m_data->write_byte(a, d); }
|
||||
inline void write_word(offs_t a, u16 d) { write_byte(a, d & 0xff); write_byte(a + 1, (d >> 8) & 0xff); }
|
||||
|
||||
enum class env_state_t32 : u8
|
||||
{
|
||||
ATTACK,
|
||||
@ -49,8 +53,6 @@ private:
|
||||
RELEASE
|
||||
};
|
||||
|
||||
static constexpr unsigned SNES_SPCRAM_SIZE = 0x10000;
|
||||
|
||||
struct voice_state_type /* Voice state type */
|
||||
{
|
||||
u16 mem_ptr; /* Sample data memory pointer */
|
||||
@ -72,25 +74,23 @@ private:
|
||||
s16 sampbuf[4]; /* Buffer for Gaussian interp */
|
||||
};
|
||||
|
||||
struct src_dir_type /* Source directory entry */
|
||||
{
|
||||
u16 vptr; /* Ptr to start of sample data */
|
||||
u16 lptr; /* Loop pointer in sample data */
|
||||
};
|
||||
inline u16 vptr(u8 sd, u8 v) { return read_word((sd << 8) + (m_dsp_regs[v + 4] << 2)); } /* Ptr to start of sample data */
|
||||
inline u16 lptr(u8 sd, u8 v) { return read_word((sd << 8) + (m_dsp_regs[v + 4] << 2) + 2); } /* Loop pointer in sample data */
|
||||
inline u16 pitch(u8 v) { (m_dsp_regs[v + 2] | (m_dsp_regs[v + 3] << 8)) & 0x3fff; }
|
||||
|
||||
/* Make reading the ADSR code easier */
|
||||
inline u8 SL(u8 v) { return m_dsp_regs[(v << 4) + 6] >> 5; } /* Returns SUSTAIN level */
|
||||
inline u8 SR(u8 v) { return m_dsp_regs[(v << 4) + 6] & 0x1f; } /* Returns SUSTAIN rate */
|
||||
|
||||
u8 dsp_io_r(offs_t offset);
|
||||
void dsp_io_w(offs_t offset, u8 data);
|
||||
// TIMER_CALLBACK_MEMBER(spc_timer);
|
||||
void dsp_reset();
|
||||
void dsp_update(s16 *sound_ptr);
|
||||
int advance_envelope(int v);
|
||||
void state_register();
|
||||
|
||||
// internal state
|
||||
std::unique_ptr<u8[]> m_ram;
|
||||
sound_stream *m_channel;
|
||||
u8 m_dsp_addr;
|
||||
u8 m_dsp_regs[256]; /* DSP registers */
|
||||
u8 m_ipl_region[64]; /* SPC top 64 bytes */
|
||||
|
||||
int m_keyed_on;
|
||||
int m_keys; /* 8-bits for 8 voices */
|
||||
@ -108,25 +108,9 @@ private:
|
||||
int m_echo_ptr;
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_TICK_ID = 1
|
||||
};
|
||||
/* timers */
|
||||
emu_timer *m_tick_timer;
|
||||
bool m_timer_enabled[3];
|
||||
u16 m_counter[3];
|
||||
u8 m_subcounter[3];
|
||||
inline void update_timer_tick(u8 which);
|
||||
|
||||
/* IO ports */
|
||||
u8 m_port_in[4]; /* SPC input ports */
|
||||
u8 m_port_out[4]; /* SPC output ports */
|
||||
|
||||
u16 m_TnDIV[3]; /**< Timer N Divider */
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SNES_SOUND, snes_sound_device)
|
||||
DECLARE_DEVICE_TYPE(S_DSP, s_dsp_device)
|
||||
|
||||
|
||||
#endif // MAME_AUDIO_SNES_SND_H
|
||||
#endif // MAME_SOUND_S_DSP_H
|
@ -353,12 +353,10 @@ private:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
DECLARE_WRITE_LINE_MEMBER(nss_vblank_irq);
|
||||
DECLARE_READ8_MEMBER(spc_ram_100_r);
|
||||
DECLARE_WRITE8_MEMBER(spc_ram_100_w);
|
||||
void bios_io_map(address_map &map);
|
||||
void bios_map(address_map &map);
|
||||
void snes_map(address_map &map);
|
||||
void spc_mem(address_map &map);
|
||||
void spc_map(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
@ -374,25 +372,13 @@ uint32_t nss_state::screen_update( screen_device &screen, bitmap_rgb32 &bitmap,
|
||||
void nss_state::snes_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x7dffff).rw(FUNC(nss_state::snes_r_bank1), FUNC(nss_state::snes_w_bank1));
|
||||
map(0x7e0000, 0x7fffff).ram(); /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
||||
map(0x7e0000, 0x7fffff).ram().share("wram"); /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
||||
map(0x800000, 0xffffff).rw(FUNC(nss_state::snes_r_bank2), FUNC(nss_state::snes_w_bank2)); /* Mirror and ROM */
|
||||
}
|
||||
|
||||
READ8_MEMBER(nss_state::spc_ram_100_r)
|
||||
void nss_state::spc_map(address_map &map)
|
||||
{
|
||||
return m_spc700->spc_ram_r(offset + 0x100);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(nss_state::spc_ram_100_w)
|
||||
{
|
||||
m_spc700->spc_ram_w(offset + 0x100, data);
|
||||
}
|
||||
|
||||
void nss_state::spc_mem(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x00ef).rw(m_spc700, FUNC(snes_sound_device::spc_ram_r), FUNC(snes_sound_device::spc_ram_w)); /* lower 32k ram */
|
||||
map(0x00f0, 0x00ff).rw(m_spc700, FUNC(snes_sound_device::spc_io_r), FUNC(snes_sound_device::spc_io_w)); /* spc io */
|
||||
map(0x0100, 0xffff).rw(FUNC(nss_state::spc_ram_100_r), FUNC(nss_state::spc_ram_100_w));
|
||||
map(0x0000, 0xffff).ram().share("aram");
|
||||
}
|
||||
|
||||
/* NSS specific */
|
||||
@ -577,7 +563,7 @@ WRITE8_MEMBER(nss_state::port_01_w)
|
||||
---- ---x Maybe SNES CPU/PPU reset? (0=Reset, 1=Run)
|
||||
*/
|
||||
m_input_disabled = BIT(data, 7) ^ 1;
|
||||
m_spc700->set_volume((data & 0x20) ? 0.0 : 100.0);
|
||||
m_s_dsp->set_volume((data & 0x20) ? 0.0 : 100.0);
|
||||
|
||||
m_cart_sel = (data & 0xc) >> 2;
|
||||
|
||||
@ -587,7 +573,7 @@ WRITE8_MEMBER(nss_state::port_01_w)
|
||||
m_soundcpu->set_input_line(INPUT_LINE_RESET, (data & 1) ? CLEAR_LINE : ASSERT_LINE);
|
||||
/* also reset the device */
|
||||
if (!(data & 1))
|
||||
m_spc700->reset();
|
||||
m_s_dsp->reset();
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(nss_state::port_02_w)
|
||||
@ -839,8 +825,10 @@ void nss_state::nss(machine_config &config)
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &nss_state::snes_map);
|
||||
|
||||
// runs at 24.576 MHz / 12 = 2.048 MHz
|
||||
SPC700(config, m_soundcpu, XTAL(24'576'000) / 12);
|
||||
m_soundcpu->set_addrmap(AS_PROGRAM, &nss_state::spc_mem);
|
||||
S_SMP(config, m_soundcpu, XTAL(24'576'000) / 12);
|
||||
m_soundcpu->set_addrmap(AS_DATA, &nss_state::spc_map);
|
||||
m_soundcpu->dsp_io_read_callback().set(m_s_dsp, FUNC(s_dsp_device::dsp_io_r));
|
||||
m_soundcpu->dsp_io_write_callback().set(m_s_dsp, FUNC(s_dsp_device::dsp_io_w));
|
||||
|
||||
config.set_perfect_quantum(m_maincpu);
|
||||
|
||||
@ -857,9 +845,11 @@ void nss_state::nss(machine_config &config)
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
SNES_SOUND(config, m_spc700, XTAL(24'576'000) / 12);
|
||||
m_spc700->add_route(0, "lspeaker", 1.00);
|
||||
m_spc700->add_route(1, "rspeaker", 1.00);
|
||||
|
||||
S_DSP(config, m_s_dsp, XTAL(24'576'000) / 12);
|
||||
m_s_dsp->set_addrmap(0, &nss_state::spc_map);
|
||||
m_s_dsp->add_route(0, "lspeaker", 1.00);
|
||||
m_s_dsp->add_route(1, "rspeaker", 1.00);
|
||||
|
||||
/* video hardware */
|
||||
/* TODO: the screen should actually superimpose, but for the time being let's just separate outputs */
|
||||
@ -892,8 +882,6 @@ void nss_state::nss(machine_config &config)
|
||||
***************************************************************************/
|
||||
|
||||
#define NSS_BIOS \
|
||||
ROM_REGION(0x100, "sound_ipl", 0) /* IPL ROM */ \
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) \
|
||||
ROM_REGION(0x8000, "bios", 0) /* Bios CPU */ \
|
||||
ROM_SYSTEM_BIOS( 0, "single", "Nintendo Super System (Single Cart BIOS)" ) \
|
||||
ROMX_LOAD("nss-ic14.02.ic14", 0x00000, 0x8000, CRC(e06cb58f) SHA1(62f507e91a2797919a78d627af53f029c7d81477), ROM_BIOS(0) ) /* bios */ \
|
||||
|
@ -155,12 +155,10 @@ private:
|
||||
DECLARE_WRITE8_MEMBER( snes_map_1_w );
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
DECLARE_READ8_MEMBER(spc_ram_100_r);
|
||||
DECLARE_WRITE8_MEMBER(spc_ram_100_w);
|
||||
void sfcbox_io(address_map &map);
|
||||
void sfcbox_map(address_map &map);
|
||||
void snes_map(address_map &map);
|
||||
void spc_mem(address_map &map);
|
||||
void spc_map(address_map &map);
|
||||
};
|
||||
|
||||
uint32_t sfcbox_state::screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect )
|
||||
@ -172,25 +170,13 @@ uint32_t sfcbox_state::screen_update( screen_device &screen, bitmap_rgb32 &bitma
|
||||
void sfcbox_state::snes_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x7dffff).rw(FUNC(sfcbox_state::snes_r_bank1), FUNC(sfcbox_state::snes_w_bank1));
|
||||
map(0x7e0000, 0x7fffff).ram(); /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
||||
map(0x7e0000, 0x7fffff).ram().share("wram"); /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
||||
map(0x800000, 0xffffff).rw(FUNC(sfcbox_state::snes_r_bank2), FUNC(sfcbox_state::snes_w_bank2)); /* Mirror and ROM */
|
||||
}
|
||||
|
||||
READ8_MEMBER(sfcbox_state::spc_ram_100_r)
|
||||
void sfcbox_state::spc_map(address_map &map)
|
||||
{
|
||||
return m_spc700->spc_ram_r(offset + 0x100);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(sfcbox_state::spc_ram_100_w)
|
||||
{
|
||||
m_spc700->spc_ram_w(offset + 0x100, data);
|
||||
}
|
||||
|
||||
void sfcbox_state::spc_mem(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x00ef).rw(m_spc700, FUNC(snes_sound_device::spc_ram_r), FUNC(snes_sound_device::spc_ram_w)); /* lower 32k ram */
|
||||
map(0x00f0, 0x00ff).rw(m_spc700, FUNC(snes_sound_device::spc_io_r), FUNC(snes_sound_device::spc_io_w)); /* spc io */
|
||||
map(0x0100, 0xffff).rw(FUNC(sfcbox_state::spc_ram_100_r), FUNC(sfcbox_state::spc_ram_100_w));
|
||||
map(0x0000, 0xffff).ram().share("aram");
|
||||
}
|
||||
|
||||
void sfcbox_state::sfcbox_map(address_map &map)
|
||||
@ -463,8 +449,10 @@ void sfcbox_state::sfcbox(machine_config &config)
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &sfcbox_state::snes_map);
|
||||
|
||||
// runs at 24.576 MHz / 12 = 2.048 MHz
|
||||
SPC700(config, m_soundcpu, XTAL(24'576'000) / 12);
|
||||
m_soundcpu->set_addrmap(AS_PROGRAM, &sfcbox_state::spc_mem);
|
||||
S_SMP(config, m_soundcpu, XTAL(24'576'000) / 12);
|
||||
m_soundcpu->set_addrmap(AS_DATA, &sfcbox_state::spc_map);
|
||||
m_soundcpu->dsp_io_read_callback().set(m_s_dsp, FUNC(s_dsp_device::dsp_io_r));
|
||||
m_soundcpu->dsp_io_write_callback().set(m_s_dsp, FUNC(s_dsp_device::dsp_io_w));
|
||||
|
||||
config.set_perfect_quantum(m_maincpu);
|
||||
|
||||
@ -479,9 +467,11 @@ void sfcbox_state::sfcbox(machine_config &config)
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
SNES_SOUND(config, m_spc700, XTAL(24'576'000) / 12);
|
||||
m_spc700->add_route(0, "lspeaker", 1.00);
|
||||
m_spc700->add_route(1, "rspeaker", 1.00);
|
||||
|
||||
S_DSP(config, m_s_dsp, XTAL(24'576'000) / 12);
|
||||
m_s_dsp->set_addrmap(0, &sfcbox_state::spc_map);
|
||||
m_s_dsp->add_route(0, "lspeaker", 1.00);
|
||||
m_s_dsp->add_route(1, "rspeaker", 1.00);
|
||||
|
||||
/* video hardware */
|
||||
/* TODO: the screen should actually superimpose, but for the time being let's just separate outputs */
|
||||
@ -516,8 +506,6 @@ void sfcbox_state::sfcbox(machine_config &config)
|
||||
|
||||
#define SFCBOX_BIOS \
|
||||
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 ) \
|
||||
ROM_REGION( 0x100, "sound_ipl", 0 ) \
|
||||
ROM_LOAD( "spc700.rom", 0x00, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) \
|
||||
ROM_REGION( 0x10000, "krom", 0 ) \
|
||||
ROM_LOAD( "krom1.ic1", 0x00000, 0x10000, CRC(c9010002) SHA1(f4c74086a83b728b1c1af3a021a60efa80eff5a4) ) \
|
||||
ROM_REGION( 0x100000, "user3", 0 ) \
|
||||
|
@ -28,9 +28,7 @@
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/snes.h"
|
||||
#include "audio/snes_snd.h"
|
||||
|
||||
#include "cpu/spc700/spc700.h"
|
||||
#include "machine/snescx4.h"
|
||||
|
||||
#include "bus/snes/snes_slot.h"
|
||||
@ -92,9 +90,6 @@ private:
|
||||
DECLARE_READ8_MEMBER( pfest94_lo_r );
|
||||
DECLARE_WRITE8_MEMBER( pfest94_lo_w );
|
||||
|
||||
DECLARE_READ8_MEMBER( spc_ram_100_r );
|
||||
DECLARE_WRITE8_MEMBER( spc_ram_100_w );
|
||||
|
||||
// input related
|
||||
SNESCTRL_ONSCREEN_CB(onscreen_cb);
|
||||
SNESCTRL_GUNLATCH_CB(gun_latch_cb);
|
||||
@ -122,18 +117,6 @@ private:
|
||||
*
|
||||
*************************************/
|
||||
|
||||
// SPC access
|
||||
|
||||
READ8_MEMBER(snes_console_state::spc_ram_100_r )
|
||||
{
|
||||
return m_spc700->spc_ram_r(offset + 0x100);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(snes_console_state::spc_ram_100_w )
|
||||
{
|
||||
m_spc700->spc_ram_w(offset + 0x100, data);
|
||||
}
|
||||
|
||||
// Memory access for the various types of carts
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
@ -165,7 +148,7 @@ READ8_MEMBER( snes_console_state::snes20_hi_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
return snes_r_io(space, address);
|
||||
else if (address < 0x8000)
|
||||
@ -225,7 +208,7 @@ WRITE8_MEMBER( snes_console_state::snes20_hi_w )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000)
|
||||
snes_w_io(space, address, data);
|
||||
}
|
||||
@ -260,7 +243,7 @@ READ8_MEMBER( snes_console_state::snes20_lo_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
return snes_r_io(space, address);
|
||||
else if (address < 0x8000)
|
||||
@ -321,7 +304,7 @@ READ8_MEMBER( snes_console_state::snes21_lo_r )
|
||||
if (offset < 0x400000 && address < 0x8000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
return snes_r_io(space, address);
|
||||
else
|
||||
@ -354,7 +337,7 @@ WRITE8_MEMBER( snes_console_state::snes21_lo_w )
|
||||
if (offset < 0x400000 && address < 0x8000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000)
|
||||
snes_w_io(space, address, data);
|
||||
else
|
||||
@ -383,7 +366,7 @@ READ8_MEMBER( snes_console_state::snes21_hi_r )
|
||||
if (offset < 0x400000 && address < 0x8000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
return snes_r_io(space, address);
|
||||
else
|
||||
@ -416,7 +399,7 @@ WRITE8_MEMBER( snes_console_state::snes21_hi_w )
|
||||
if (offset < 0x400000 && address < 0x8000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000)
|
||||
snes_w_io(space, address, data);
|
||||
else
|
||||
@ -449,7 +432,7 @@ READ8_MEMBER( snes_console_state::snessfx_hi_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x3000 && address < 0x3300)
|
||||
@ -475,7 +458,7 @@ READ8_MEMBER( snes_console_state::snessfx_lo_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x3000 && address < 0x3300)
|
||||
@ -500,7 +483,7 @@ WRITE8_MEMBER( snes_console_state::snessfx_hi_w )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x3000 && address < 0x3300)
|
||||
@ -531,7 +514,7 @@ READ8_MEMBER( snes_console_state::snessa1_hi_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x2200 && address < 0x2400)
|
||||
@ -557,7 +540,7 @@ READ8_MEMBER( snes_console_state::snessa1_lo_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x2200 && address < 0x2400)
|
||||
@ -584,7 +567,7 @@ WRITE8_MEMBER( snes_console_state::snessa1_hi_w )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x2200 && address < 0x2400)
|
||||
@ -618,7 +601,7 @@ READ8_MEMBER( snes_console_state::snes7110_hi_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
uint16_t limit = (m_cartslot->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
|
||||
@ -647,7 +630,7 @@ READ8_MEMBER( snes_console_state::snes7110_lo_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
uint16_t limit = (m_cartslot->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
|
||||
@ -683,7 +666,7 @@ WRITE8_MEMBER( snes_console_state::snes7110_lo_w )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
uint16_t limit = (m_cartslot->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
|
||||
@ -716,7 +699,7 @@ READ8_MEMBER( snes_console_state::snessdd1_lo_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x4800 && address < 0x4808)
|
||||
@ -754,7 +737,7 @@ WRITE8_MEMBER( snes_console_state::snessdd1_hi_w )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x4300 && address < 0x4380)
|
||||
@ -786,7 +769,7 @@ READ8_MEMBER( snes_console_state::snesbsx_hi_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x2188 && address < 0x21a0)
|
||||
@ -814,7 +797,7 @@ WRITE8_MEMBER( snes_console_state::snesbsx_hi_w )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x2188 && address < 0x21a0)
|
||||
@ -847,7 +830,7 @@ READ8_MEMBER( snes_console_state::snesbsx_lo_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
{
|
||||
if (address >= 0x2188 && address < 0x21a0)
|
||||
@ -886,7 +869,7 @@ READ8_MEMBER( snes_console_state::snessgb_hi_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
return snes_r_io(space, address);
|
||||
else if (address < 0x8000)
|
||||
@ -911,7 +894,7 @@ WRITE8_MEMBER( snes_console_state::snessgb_hi_w )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000)
|
||||
snes_w_io(space, address, data);
|
||||
else if (address < 0x8000)
|
||||
@ -935,7 +918,7 @@ READ8_MEMBER( snes_console_state::pfest94_hi_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
return snes_r_io(space, address);
|
||||
else if (address < 0x8000)
|
||||
@ -961,7 +944,7 @@ WRITE8_MEMBER( snes_console_state::pfest94_hi_w )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
space.write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000)
|
||||
snes_w_io(space, address, data);
|
||||
else if (address < 0x8000)
|
||||
@ -983,7 +966,7 @@ READ8_MEMBER( snes_console_state::pfest94_lo_r )
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000)
|
||||
return space.read_byte(0x7e0000 + address);
|
||||
return m_wram[address];
|
||||
else if (address < 0x6000)
|
||||
return snes_r_io(space, address);
|
||||
else if (address < 0x8000)
|
||||
@ -1018,15 +1001,13 @@ WRITE8_MEMBER( snes_console_state::pfest94_lo_w )
|
||||
void snes_console_state::snes_map(address_map &map)
|
||||
{
|
||||
// map(0x000000, 0x7dffff).rw(FUNC(snes_console_state::snes20_lo_r), FUNC(snes_console_state::snes20_lo_w));
|
||||
map(0x7e0000, 0x7fffff).ram(); /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
||||
map(0x7e0000, 0x7fffff).ram().share("wram"); /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
||||
// map(0x800000, 0xffffff).rw(FUNC(snes_console_state::snes20_hi_r), FUNC(snes_console_state::snes20_hi_w));
|
||||
}
|
||||
|
||||
void snes_console_state::spc_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x00ef).rw(m_spc700, FUNC(snes_sound_device::spc_ram_r), FUNC(snes_sound_device::spc_ram_w)); /* lower 32k ram */
|
||||
map(0x00f0, 0x00ff).rw(m_spc700, FUNC(snes_sound_device::spc_io_r), FUNC(snes_sound_device::spc_io_w)); /* spc io */
|
||||
map(0x0100, 0xffff).rw(FUNC(snes_console_state::spc_ram_100_r), FUNC(snes_console_state::spc_ram_100_w));
|
||||
map(0x0000, 0xffff).ram().share("aram");
|
||||
}
|
||||
|
||||
|
||||
@ -1340,8 +1321,10 @@ void snes_console_state::snes(machine_config &config)
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &snes_console_state::snes_map);
|
||||
|
||||
// runs at 24.576 MHz / 12 = 2.048 MHz
|
||||
SPC700(config, m_soundcpu, XTAL(24'576'000) / 12);
|
||||
m_soundcpu->set_addrmap(AS_PROGRAM, &snes_console_state::spc_map);
|
||||
S_SMP(config, m_soundcpu, XTAL(24'576'000) / 12);
|
||||
m_soundcpu->set_addrmap(AS_DATA, &snes_console_state::spc_map);
|
||||
m_soundcpu->dsp_io_read_callback().set(m_s_dsp, FUNC(s_dsp_device::dsp_io_r));
|
||||
m_soundcpu->dsp_io_write_callback().set(m_s_dsp, FUNC(s_dsp_device::dsp_io_w));
|
||||
|
||||
//config.set_maximum_quantum(attotime::from_hz(48000));
|
||||
config.set_perfect_quantum(m_maincpu);
|
||||
@ -1365,9 +1348,11 @@ void snes_console_state::snes(machine_config &config)
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
SNES_SOUND(config, m_spc700, XTAL(24'576'000) / 12);
|
||||
m_spc700->add_route(0, "lspeaker", 1.00);
|
||||
m_spc700->add_route(1, "rspeaker", 1.00);
|
||||
|
||||
S_DSP(config, m_s_dsp, XTAL(24'576'000) / 12);
|
||||
m_s_dsp->set_addrmap(0, &snes_console_state::spc_map);
|
||||
m_s_dsp->add_route(0, "lspeaker", 1.00);
|
||||
m_s_dsp->add_route(1, "rspeaker", 1.00);
|
||||
|
||||
SNS_CART_SLOT(config, m_cartslot, MCLK_NTSC, snes_cart, nullptr);
|
||||
m_cartslot->irq_callback().set_inputline(m_maincpu, G65816_LINE_IRQ);
|
||||
@ -1399,9 +1384,6 @@ void snes_console_state::snespal(machine_config &config)
|
||||
|
||||
ROM_START( snes )
|
||||
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
|
||||
|
||||
ROM_REGION( 0x100, "sound_ipl", 0 ) /* IPL ROM */
|
||||
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
||||
ROM_END
|
||||
|
||||
#define rom_snespal rom_snes
|
||||
|
@ -192,12 +192,10 @@ private:
|
||||
DECLARE_READ8_MEMBER(snesb_dsw1_r);
|
||||
DECLARE_READ8_MEMBER(snesb_dsw2_r);
|
||||
DECLARE_READ8_MEMBER(snesb_coin_r);
|
||||
DECLARE_READ8_MEMBER(spc_ram_100_r);
|
||||
DECLARE_WRITE8_MEMBER(spc_ram_100_w);
|
||||
DECLARE_MACHINE_RESET(ffight2b);
|
||||
void mcu_io_map(address_map &map);
|
||||
void snesb_map(address_map &map);
|
||||
void spc_mem(address_map &map);
|
||||
void spc_map(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
@ -332,25 +330,13 @@ READ8_MEMBER(snesb_state::snesb_coin_r)
|
||||
void snesb_state::snesb_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x7dffff).rw(FUNC(snesb_state::snes_r_bank1), FUNC(snesb_state::snes_w_bank1));
|
||||
map(0x7e0000, 0x7fffff).ram(); /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
||||
map(0x7e0000, 0x7fffff).ram().share("wram"); /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
||||
map(0x800000, 0xffffff).rw(FUNC(snesb_state::snes_r_bank2), FUNC(snesb_state::snes_w_bank2)); /* Mirror and ROM */
|
||||
}
|
||||
|
||||
READ8_MEMBER(snesb_state::spc_ram_100_r)
|
||||
void snesb_state::spc_map(address_map &map)
|
||||
{
|
||||
return m_spc700->spc_ram_r(offset + 0x100);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(snesb_state::spc_ram_100_w)
|
||||
{
|
||||
m_spc700->spc_ram_w(offset + 0x100, data);
|
||||
}
|
||||
|
||||
void snesb_state::spc_mem(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x00ef).rw(m_spc700, FUNC(snes_sound_device::spc_ram_r), FUNC(snes_sound_device::spc_ram_w)); /* lower 32k ram */
|
||||
map(0x00f0, 0x00ff).rw(m_spc700, FUNC(snes_sound_device::spc_io_r), FUNC(snes_sound_device::spc_io_w)); /* spc io */
|
||||
map(0x0100, 0xffff).rw(FUNC(snesb_state::spc_ram_100_r), FUNC(snesb_state::spc_ram_100_w));
|
||||
map(0x0000, 0xffff).ram().share("aram");
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START( snes_common )
|
||||
@ -821,8 +807,10 @@ void snesb_state::kinstb(machine_config &config)
|
||||
|
||||
/* audio CPU */
|
||||
// runs at 24.576 MHz / 12 = 2.048 MHz
|
||||
SPC700(config, m_soundcpu, XTAL(24'576'000) / 12);
|
||||
m_soundcpu->set_addrmap(AS_PROGRAM, &snesb_state::spc_mem);
|
||||
S_SMP(config, m_soundcpu, XTAL(24'576'000) / 12);
|
||||
m_soundcpu->set_addrmap(AS_DATA, &snesb_state::spc_map);
|
||||
m_soundcpu->dsp_io_read_callback().set(m_s_dsp, FUNC(s_dsp_device::dsp_io_r));
|
||||
m_soundcpu->dsp_io_write_callback().set(m_s_dsp, FUNC(s_dsp_device::dsp_io_w));
|
||||
|
||||
config.set_perfect_quantum(m_maincpu);
|
||||
|
||||
@ -839,9 +827,11 @@ void snesb_state::kinstb(machine_config &config)
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
SNES_SOUND(config, m_spc700, XTAL(24'576'000) / 12);
|
||||
m_spc700->add_route(0, "lspeaker", 1.00);
|
||||
m_spc700->add_route(1, "rspeaker", 1.00);
|
||||
|
||||
S_DSP(config, m_s_dsp, XTAL(24'576'000) / 12);
|
||||
m_s_dsp->set_addrmap(0, &snesb_state::spc_map);
|
||||
m_s_dsp->add_route(0, "lspeaker", 1.00);
|
||||
m_s_dsp->add_route(1, "rspeaker", 1.00);
|
||||
}
|
||||
|
||||
MACHINE_RESET_MEMBER( snesb_state, ffight2b )
|
||||
@ -1371,9 +1361,6 @@ ROM_START( kinstb )
|
||||
ROM_LOAD( "3.u16", 0x200000, 0x100000, CRC(7a40f7dd) SHA1(cebe632e8d2d68d0619077cc1e931af73c9a723b) )
|
||||
ROM_LOAD( "4.u17", 0x300000, 0x100000, CRC(3d7564c1) SHA1(392b513991897668d5dd469ac84a34f785895774) )
|
||||
|
||||
ROM_REGION(0x100, "sound_ipl", 0)
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )
|
||||
|
||||
ROM_REGION(0x800, "user6", ROMREGION_ERASEFF)
|
||||
ROM_END
|
||||
|
||||
@ -1413,9 +1400,6 @@ ROM_START( ffight2b )
|
||||
ROM_CONTINUE( 0x078000, 0x008000 )
|
||||
ROM_LOAD( "ff2_1.u8", 0x100000, 0x040000, CRC(ea315ac1) SHA1(a85de091882d35bc77dc99677511828ff7c20350) )
|
||||
|
||||
ROM_REGION(0x100, "sound_ipl", 0)
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )
|
||||
|
||||
ROM_REGION(0x800, "user6", ROMREGION_ERASEFF)
|
||||
ROM_END
|
||||
|
||||
@ -1425,9 +1409,6 @@ ROM_START( iron )
|
||||
ROM_LOAD( "5.c10.bin", 0x080000, 0x080000, CRC(0c3a0b5b) SHA1(1e8ab860689137e0e94731f1af2cfc561492b5bd) )
|
||||
ROM_LOAD( "4.c11.bin", 0x100000, 0x040000, CRC(2aa417c7) SHA1(24b375e5bbd4be5dcd31b63ea98fbbadd53d543e) )
|
||||
|
||||
ROM_REGION(0x100, "sound_ipl", 0)
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )
|
||||
|
||||
ROM_REGION(0x800, "user6", ROMREGION_ERASEFF)
|
||||
ROM_END
|
||||
|
||||
@ -1438,18 +1419,12 @@ ROM_START( denseib )
|
||||
ROM_LOAD( "dj.u16", 0x100000, 0x0080000, CRC(7cb71fd7) SHA1(7673e9dcaabe804e2d637e67eabca1683dad4245) )
|
||||
ROM_LOAD( "dj.u17", 0x180000, 0x0080000, CRC(de29dd89) SHA1(441aefbc7ee64515ee66431ef504e76dc8dc5ca3) )
|
||||
|
||||
ROM_REGION(0x100, "sound_ipl", 0)
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )
|
||||
|
||||
ROM_REGION(0x800, "user6", ROMREGION_ERASEFF)
|
||||
ROM_END
|
||||
|
||||
ROM_START( denseib2 )
|
||||
ROM_REGION( 0x200000, "user3", ROMREGION_ERASEFF )
|
||||
|
||||
ROM_REGION(0x100, "sound_ipl", 0)
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )
|
||||
|
||||
ROM_REGION(0x800, "user6", ROMREGION_ERASEFF)
|
||||
|
||||
ROM_REGION( 0x200000, "user7", 0 )
|
||||
@ -1462,9 +1437,6 @@ ROM_END
|
||||
ROM_START( sblast2b )
|
||||
ROM_REGION( 0x180000, "user3", ROMREGION_ERASEFF )
|
||||
|
||||
ROM_REGION(0x100, "sound_ipl", 0)
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )
|
||||
|
||||
ROM_REGION(0x800, "user6", ROMREGION_ERASEFF)
|
||||
|
||||
ROM_REGION( 0x180000, "user7", 0 )
|
||||
@ -1511,18 +1483,12 @@ ROM_START( legendsb )
|
||||
ROM_CONTINUE( 0x0f0000, 0x008000 )
|
||||
ROM_CONTINUE( 0x078000, 0x008000 )
|
||||
|
||||
ROM_REGION(0x100, "sound_ipl", 0)
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )
|
||||
|
||||
ROM_REGION(0x800, "user6", ROMREGION_ERASEFF)
|
||||
ROM_END
|
||||
|
||||
ROM_START( endless )
|
||||
ROM_REGION( 0x200000, "user3", ROMREGION_ERASEFF )
|
||||
|
||||
ROM_REGION(0x100, "sound_ipl", 0)
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )
|
||||
|
||||
ROM_REGION(0x800, "user6", ROMREGION_ERASEFF)
|
||||
|
||||
ROM_REGION( 0x200000, "user7", 0 )
|
||||
@ -1535,9 +1501,6 @@ ROM_END
|
||||
ROM_START( rushbets )
|
||||
ROM_REGION( 0x200000, "user3", ROMREGION_ERASEFF )
|
||||
|
||||
ROM_REGION(0x100, "sound_ipl", 0)
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )
|
||||
|
||||
ROM_REGION(0x800, "user6", ROMREGION_ERASEFF)
|
||||
|
||||
ROM_REGION( 0x200000, "user7", 0 )
|
||||
@ -1550,9 +1513,6 @@ ROM_END
|
||||
ROM_START( venom )
|
||||
ROM_REGION( 0x300000, "user3", ROMREGION_ERASEFF )
|
||||
|
||||
ROM_REGION(0x100, "sound_ipl", 0)
|
||||
ROM_LOAD("spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) )
|
||||
|
||||
ROM_REGION(0x800, "user6", ROMREGION_ERASEFF)
|
||||
|
||||
ROM_REGION( 0x300000, "user7", 0 )
|
||||
|
@ -4,9 +4,9 @@
|
||||
#ifndef MAME_INCLUDES_SNES_H
|
||||
#define MAME_INCLUDES_SNES_H
|
||||
|
||||
#include "cpu/spc700/spc700.h"
|
||||
#include "cpu/g65816/g65816.h"
|
||||
#include "audio/snes_snd.h"
|
||||
#include "machine/s_smp.h"
|
||||
#include "sound/s_dsp.h"
|
||||
#include "video/snes_ppu.h"
|
||||
#include "screen.h"
|
||||
|
||||
@ -303,9 +303,10 @@ public:
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_soundcpu(*this, "soundcpu"),
|
||||
m_spc700(*this, "spc700"),
|
||||
m_s_dsp(*this, "s_dsp"),
|
||||
m_ppu(*this, "ppu"),
|
||||
m_screen(*this, "screen")
|
||||
m_screen(*this, "screen"),
|
||||
m_wram(*this, "wram")
|
||||
{ }
|
||||
|
||||
void init_snes();
|
||||
@ -316,6 +317,11 @@ public:
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_NMI_TICK,
|
||||
@ -385,11 +391,13 @@ protected:
|
||||
|
||||
/* devices */
|
||||
required_device<_5a22_device> m_maincpu;
|
||||
required_device<spc700_device> m_soundcpu;
|
||||
required_device<snes_sound_device> m_spc700;
|
||||
required_device<s_smp_device> m_soundcpu;
|
||||
required_device<s_dsp_device> m_s_dsp;
|
||||
required_device<snes_ppu_device> m_ppu;
|
||||
required_device<screen_device> m_screen;
|
||||
|
||||
required_shared_ptr<u8> m_wram;
|
||||
|
||||
inline int dma_abus_valid(uint32_t address);
|
||||
inline uint8_t abus_read(address_space &space, uint32_t abus);
|
||||
inline void dma_transfer(address_space &space, uint8_t dma, uint32_t abus, uint16_t bbus);
|
||||
@ -432,10 +440,6 @@ protected:
|
||||
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(load_snes_cart);
|
||||
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(load_sufami_cart);
|
||||
void snes_init_timers();
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
};
|
||||
|
||||
/* Special chips, checked at init and used in memory handlers */
|
||||
|
@ -390,7 +390,7 @@ READ8_MEMBER( snes_state::snes_r_io )
|
||||
// APU is mirrored from 2140 to 217f
|
||||
if (offset >= APU00 && offset < WMDATA)
|
||||
{
|
||||
return m_spc700->spc_port_out(offset & 0x3);
|
||||
return m_soundcpu->spc_port_out_r(offset & 0x3);
|
||||
}
|
||||
|
||||
// DMA accesses are from 4300 to 437f
|
||||
@ -404,7 +404,7 @@ READ8_MEMBER( snes_state::snes_r_io )
|
||||
switch (offset) // offset is from 0x000000
|
||||
{
|
||||
case WMDATA: /* Data to read from WRAM */
|
||||
value = m_maincpu->space(AS_PROGRAM).read_byte(0x7e0000 + m_wram_address++);
|
||||
value = m_wram[m_wram_address++];
|
||||
m_wram_address &= 0x1ffff;
|
||||
return value;
|
||||
|
||||
@ -480,7 +480,7 @@ WRITE8_MEMBER( snes_state::snes_w_io )
|
||||
if (offset >= APU00 && offset < WMDATA)
|
||||
{
|
||||
// printf("816: %02x to APU @ %d (PC=%06x)\n", data, offset & 3,m_maincpu->pc());
|
||||
m_spc700->spc_port_in(offset & 0x3, data);
|
||||
m_soundcpu->spc_port_in_w(offset & 0x3, data);
|
||||
machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(20));
|
||||
return;
|
||||
}
|
||||
@ -496,7 +496,7 @@ WRITE8_MEMBER( snes_state::snes_w_io )
|
||||
switch (offset)
|
||||
{
|
||||
case WMDATA: /* Data to write to WRAM */
|
||||
m_maincpu->space(AS_PROGRAM).write_byte(0x7e0000 + m_wram_address++, data );
|
||||
m_wram[m_wram_address++] = data;
|
||||
m_wram_address &= 0x1ffff;
|
||||
return;
|
||||
case WMADDL: /* Address to read/write to wram (low) */
|
||||
@ -720,7 +720,7 @@ READ8_MEMBER(snes_state::snes_r_bank1)
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000) /* Mirror of Low RAM */
|
||||
value = m_maincpu->space(AS_PROGRAM).read_byte(0x7e0000 + address);
|
||||
value = m_wram[address];
|
||||
else if (address < 0x6000) /* I/O */
|
||||
value = snes_r_io(space, address);
|
||||
else if (address < 0x8000)
|
||||
@ -831,7 +831,7 @@ WRITE8_MEMBER(snes_state::snes_w_bank1)
|
||||
if (offset < 0x400000)
|
||||
{
|
||||
if (address < 0x2000) /* Mirror of Low RAM */
|
||||
m_maincpu->space(AS_PROGRAM).write_byte(0x7e0000 + address, data);
|
||||
m_wram[address] = data;
|
||||
else if (address < 0x6000) /* I/O */
|
||||
snes_w_io(space, address, data);
|
||||
else if (address < 0x8000)
|
||||
@ -1034,14 +1034,14 @@ void snes_state::snes_init_timers()
|
||||
|
||||
void snes_state::snes_init_ram()
|
||||
{
|
||||
address_space &cpu0space = m_maincpu->space(AS_PROGRAM);
|
||||
int i;
|
||||
|
||||
/* Init work RAM - 0x55 isn't exactly right but it's close */
|
||||
/* make sure it happens to the 65816 (CPU 0) */
|
||||
for (i = 0; i < (128*1024); i++)
|
||||
const size_t size = m_wram.bytes();
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
cpu0space.write_byte(0x7e0000 + i, 0x55);
|
||||
m_wram[i] = 0x55;
|
||||
}
|
||||
|
||||
/* Inititialize registers/variables */
|
||||
|
Loading…
Reference in New Issue
Block a user