mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
Revert "nes_vt: APU improvements (#4476)"
This reverts commit 6d3238ead8
.
This commit is contained in:
parent
a93943e002
commit
e55e20c79e
@ -642,7 +642,6 @@ end
|
||||
---------------------------------------------------
|
||||
-- Nintendo custom sound chips
|
||||
--@src/devices/sound/nes_apu.h,SOUNDS["NES_APU"] = true
|
||||
--@src/devices/sound/nes_vt_apu.h,SOUNDS["NES_APU"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (SOUNDS["NES_APU"]~=null) then
|
||||
@ -650,8 +649,6 @@ if (SOUNDS["NES_APU"]~=null) then
|
||||
MAME_DIR .. "src/devices/sound/nes_apu.cpp",
|
||||
MAME_DIR .. "src/devices/sound/nes_apu.h",
|
||||
MAME_DIR .. "src/devices/sound/nes_defs.h",
|
||||
MAME_DIR .. "src/devices/sound/nes_vt_apu.cpp",
|
||||
MAME_DIR .. "src/devices/sound/nes_vt_apu.h"
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -101,18 +101,13 @@ static void create_noise(u8 *buf, const int bits, int size)
|
||||
DEFINE_DEVICE_TYPE(NES_APU, nesapu_device, "nesapu", "N2A03 APU")
|
||||
|
||||
nesapu_device::nesapu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: nesapu_device(mconfig, tag, NES_APU, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
nesapu_device::nesapu_device(const machine_config &mconfig, const char *tag, device_type type, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
: device_t(mconfig, NES_APU, tag, owner, clock)
|
||||
, device_sound_interface(mconfig, *this)
|
||||
, m_mem_read_cb(*this)
|
||||
, m_irq_handler(*this)
|
||||
, m_samps_per_sync(0)
|
||||
, m_buffer_size(0)
|
||||
, m_stream(nullptr)
|
||||
, m_irq_handler(*this)
|
||||
, m_mem_read_cb(*this)
|
||||
{
|
||||
for (auto & elem : m_noise_lut)
|
||||
{
|
||||
@ -170,7 +165,14 @@ void nesapu_device::calculate_rates()
|
||||
|
||||
void nesapu_device::device_start()
|
||||
{
|
||||
apu_init();
|
||||
// resolve callbacks
|
||||
m_irq_handler.resolve_safe();
|
||||
m_mem_read_cb.resolve_safe(0x00);
|
||||
|
||||
create_noise(m_noise_lut, 13, apu_t::NOISE_LONG);
|
||||
|
||||
calculate_rates();
|
||||
|
||||
/* register for save */
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
@ -228,18 +230,6 @@ void nesapu_device::device_start()
|
||||
#endif
|
||||
}
|
||||
|
||||
void nesapu_device::apu_init()
|
||||
{
|
||||
// resolve callbacks
|
||||
m_irq_handler.resolve_safe();
|
||||
m_mem_read_cb.resolve_safe(0x00);
|
||||
|
||||
create_noise(m_noise_lut, 13, apu_t::NOISE_LONG);
|
||||
|
||||
calculate_rates();
|
||||
}
|
||||
|
||||
|
||||
/* TODO: sound channels should *ALL* have DC volume decay */
|
||||
|
||||
/* OUTPUT SQUARE WAVE SAMPLE (VALUES FROM -16 to +15) */
|
||||
|
@ -54,33 +54,16 @@ public:
|
||||
virtual void device_reset() override;
|
||||
virtual void device_clock_changed() override;
|
||||
|
||||
virtual u8 read(offs_t offset);
|
||||
virtual void write(offs_t offset, u8 data);
|
||||
u8 read(offs_t offset);
|
||||
void write(offs_t offset, u8 data);
|
||||
|
||||
protected:
|
||||
nesapu_device(const machine_config &mconfig, const char *tag, device_type type, device_t *owner, u32 clock);
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
|
||||
// sound stream update overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
|
||||
|
||||
void apu_init();
|
||||
void calculate_rates();
|
||||
void create_syncs(unsigned long sps);
|
||||
s8 apu_square(apu_t::square_t *chan);
|
||||
s8 apu_triangle(apu_t::triangle_t *chan);
|
||||
s8 apu_noise(apu_t::noise_t *chan);
|
||||
s8 apu_dpcm(apu_t::dpcm_t *chan);
|
||||
|
||||
inline void apu_regwrite(int address, u8 value);
|
||||
inline u8 apu_read(int address);
|
||||
inline void apu_write(int address, u8 value);
|
||||
|
||||
devcb_read8 m_mem_read_cb;
|
||||
devcb_write_line m_irq_handler;
|
||||
|
||||
private:
|
||||
/* GLOBAL CONSTANTS */
|
||||
static constexpr unsigned SYNCS_MAX1 = 0x20;
|
||||
@ -95,7 +78,16 @@ private:
|
||||
u32 m_sync_times1[SYNCS_MAX1]; /* Samples per sync table */
|
||||
u32 m_sync_times2[SYNCS_MAX2]; /* Samples per sync table */
|
||||
sound_stream *m_stream;
|
||||
devcb_write_line m_irq_handler;
|
||||
devcb_read8 m_mem_read_cb;
|
||||
|
||||
void calculate_rates();
|
||||
void create_syncs(unsigned long sps);
|
||||
s8 apu_square(apu_t::square_t *chan);
|
||||
s8 apu_triangle(apu_t::triangle_t *chan);
|
||||
s8 apu_noise(apu_t::noise_t *chan);
|
||||
s8 apu_dpcm(apu_t::dpcm_t *chan);
|
||||
inline void apu_regwrite(int address, u8 value);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(NES_APU, nesapu_device)
|
||||
|
@ -1,289 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Shah
|
||||
/*****************************************************************************
|
||||
|
||||
MAME/MESS VTxx APU CORE
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "nes_vt_apu.h"
|
||||
|
||||
#define VTXX_NTSC_XTAL XTAL(21'477'272)
|
||||
#define VTXX_NTSC_APU_CLOCK (VTXX_NTSC_XTAL/12)
|
||||
|
||||
DEFINE_DEVICE_TYPE(NES_VT_APU, nesapu_vt_device, "nesapu_vt", "VTxx APU")
|
||||
DEFINE_DEVICE_TYPE(NES_VT_APU_SLAVE, nesapu_vt_slave_device, "nesapu_vt_slave", "VTxx APU (slave)")
|
||||
|
||||
nesapu_vt_device::nesapu_vt_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: nesapu_device(mconfig, tag, NES_VT_APU, owner, clock),
|
||||
m_xop2(*this, "nesapu_vt_slave"),
|
||||
m_rom_read_cb(*this)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void nesapu_vt_device::device_start()
|
||||
{
|
||||
apu_init();
|
||||
m_rom_read_cb.resolve_safe(0x00);
|
||||
|
||||
if(!m_xop2->started())
|
||||
throw device_missing_dependencies();
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
save_item(NAME(m_apu_vt.vt33_pcm[i].address), i);
|
||||
save_item(NAME(m_apu_vt.vt33_pcm[i].volume), i);
|
||||
save_item(NAME(m_apu_vt.vt33_pcm[i].enabled), i);
|
||||
save_item(NAME(m_apu_vt.vt33_pcm[i].playing), i);
|
||||
save_item(NAME(m_apu_vt.vt33_pcm[i].phaseacc), i);
|
||||
save_item(NAME(m_apu_vt.vt33_pcm[i].curr), i);
|
||||
}
|
||||
|
||||
save_item(NAME(m_apu_vt.vt03_pcm.phaseacc));
|
||||
save_item(NAME(m_apu_vt.vt03_pcm.regs));
|
||||
save_item(NAME(m_apu_vt.vt03_pcm.address));
|
||||
save_item(NAME(m_apu_vt.vt03_pcm.length));
|
||||
save_item(NAME(m_apu_vt.vt03_pcm.remaining_bytes));
|
||||
save_item(NAME(m_apu_vt.vt03_pcm.enabled));
|
||||
save_item(NAME(m_apu_vt.vt03_pcm.irq_occurred));
|
||||
save_item(NAME(m_apu_vt.vt03_pcm.vol));
|
||||
|
||||
save_item(NAME(m_apu_vt.extra_regs));
|
||||
save_item(NAME(m_apu_vt.vt3x_sel_channel));
|
||||
save_item(NAME(m_apu_vt.use_vt03_pcm));
|
||||
save_item(NAME(m_apu_vt.use_vt3x_pcm));
|
||||
|
||||
}
|
||||
|
||||
nesapu_vt_slave_device::nesapu_vt_slave_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: nesapu_device(mconfig, tag, NES_VT_APU_SLAVE, owner, clock)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void nesapu_vt_slave_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
//TODO: any tweaks needed here:
|
||||
nesapu_device::sound_stream_update(stream, inputs, outputs, samples);
|
||||
}
|
||||
|
||||
void nesapu_vt_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
std::unique_ptr<stream_sample_t[]> pbuf = std::make_unique<stream_sample_t[]>(samples);
|
||||
std::unique_ptr<stream_sample_t[]> sbuf = std::make_unique<stream_sample_t[]>(samples);
|
||||
|
||||
stream_sample_t *pptr = pbuf.get(), *sptr = sbuf.get();
|
||||
|
||||
// Dual legacy sound generators
|
||||
nesapu_device::sound_stream_update(stream, inputs, &pptr, samples);
|
||||
m_xop2->sound_stream_update(stream, inputs, &sptr, samples);
|
||||
|
||||
int accum;
|
||||
memset( outputs[0], 0, samples*sizeof(*outputs[0]) );
|
||||
|
||||
for(int i = 0; i < samples; i++)
|
||||
{
|
||||
accum = 0;
|
||||
accum += pbuf[i] >> 8;
|
||||
accum += sbuf[i] >> 8; //TODO: mixing between generators?
|
||||
accum += vt03_pcm(&m_apu_vt.vt03_pcm);
|
||||
accum += vt3x_pcm(&(m_apu_vt.vt33_pcm[0]));
|
||||
accum += vt3x_pcm(&(m_apu_vt.vt33_pcm[1]));
|
||||
|
||||
/* 8-bit clamps */
|
||||
if (accum > 127)
|
||||
accum = 127;
|
||||
else if (accum < -128)
|
||||
accum = -128;
|
||||
|
||||
*(outputs[0]++)=accum<<8;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
s8 nesapu_vt_device::vt03_pcm(apu_vt_t::vt03_pcm_t *ch) {
|
||||
if (ch->enabled) {
|
||||
int freq = dpcm_clocks[ch->regs[0] & 0x0F];
|
||||
ch->phaseacc -= 4;
|
||||
while (ch->phaseacc < 0 && ch->enabled)
|
||||
{
|
||||
ch->phaseacc += freq;
|
||||
u8 data = u8(m_mem_read_cb(ch->address));
|
||||
logerror("pcm fetch %04x %d\n", ch->address, int(data));
|
||||
ch->vol = data;
|
||||
ch->address++;
|
||||
ch->remaining_bytes--;
|
||||
if (ch->remaining_bytes == 0)
|
||||
{
|
||||
if (ch->regs[0] & 0x80)
|
||||
{
|
||||
ch->irq_occurred = true;
|
||||
m_irq_handler(true);
|
||||
}
|
||||
if (ch->regs[0] & 0x40)
|
||||
reset_vt03_pcm(ch);
|
||||
else
|
||||
ch->enabled = false;
|
||||
}
|
||||
}
|
||||
return ch->vol - 128;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
s8 nesapu_vt_device::vt3x_pcm(apu_vt_t::vt3x_pcm_t *ch) {
|
||||
if (ch->enabled && ch->playing) {
|
||||
const int freq = 0x6F;
|
||||
ch->phaseacc -= 4;
|
||||
while (ch->phaseacc < 0)
|
||||
{
|
||||
ch->phaseacc += freq;
|
||||
u8 sample = m_rom_read_cb(ch->address);
|
||||
// logerror("pcm fetch %06x %d\n", ch->address, int(sample));
|
||||
if (sample == 0xFF) {
|
||||
ch->playing = false;
|
||||
ch->enabled = false;
|
||||
} else {
|
||||
ch->address++;
|
||||
ch->curr = s8((s8(sample - 128) * u16(ch->volume)) / 128);
|
||||
// logerror("scaled %d\n", int(ch->curr));
|
||||
}
|
||||
}
|
||||
return ch->curr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nesapu_vt_device::reset_vt03_pcm(apu_vt_t::vt03_pcm_t *ch) {
|
||||
// logerror("reset vt03 pwm\n");
|
||||
ch->address = ((~m_apu_vt.extra_regs[0]) & 0x03) << 14 | m_apu_vt.vt03_pcm.regs[2] << 6;
|
||||
ch->remaining_bytes = m_apu_vt.vt03_pcm.regs[3] << 4;
|
||||
ch->length = m_apu_vt.vt03_pcm.regs[3] << 4;
|
||||
ch->enabled = true;
|
||||
ch->irq_occurred = true;
|
||||
}
|
||||
|
||||
void nesapu_vt_device::vt_apu_write(uint8_t address, uint8_t data) {
|
||||
|
||||
if(address == 0x35 && !m_apu_vt.use_vt3x_pcm)
|
||||
{
|
||||
//When VT3x PCM disabled, 4035 controls XOP2
|
||||
m_xop2->write(0x15, data & 0x0F);
|
||||
m_apu_vt.extra_regs[0x05] = data;
|
||||
} else if (address >= 0x10 && address <= 0x13) {
|
||||
m_apu_vt.vt03_pcm.regs[address - 0x10] = data;
|
||||
if (address == 0x10) {
|
||||
m_apu_vt.vt03_pcm.irq_occurred = false;
|
||||
m_irq_handler(false);
|
||||
}
|
||||
if (m_apu_vt.use_vt3x_pcm && (address == 0x12) && !m_apu_vt.vt33_pcm[m_apu_vt.vt3x_sel_channel].enabled) {
|
||||
m_apu_vt.vt33_pcm[m_apu_vt.vt3x_sel_channel].address &= ~(0xFF << 6);
|
||||
m_apu_vt.vt33_pcm[m_apu_vt.vt3x_sel_channel].address |= (data << 6);
|
||||
}
|
||||
} else if(address >= 0x30 && address <= 0x36) {
|
||||
if (address == 0x30) {
|
||||
m_apu_vt.use_vt03_pcm = (data & 0x10) != 0;
|
||||
} else if (address == 0x33) {
|
||||
m_apu_vt.use_vt3x_pcm = (data & 0x80);
|
||||
m_apu_vt.vt33_pcm[0].enabled = (data & 0x10);
|
||||
m_apu_vt.vt33_pcm[1].enabled = (data & 0x08);
|
||||
} else if (address == 0x31) {
|
||||
m_apu_vt.vt3x_sel_channel = 0;
|
||||
m_apu_vt.vt33_pcm[0].volume = data;
|
||||
} else if (address == 0x32) {
|
||||
m_apu_vt.vt3x_sel_channel = 1;
|
||||
m_apu_vt.vt33_pcm[1].volume = data;
|
||||
} else if (address == 0x35 && !m_apu_vt.vt33_pcm[m_apu_vt.vt3x_sel_channel].enabled) {
|
||||
m_apu_vt.vt33_pcm[m_apu_vt.vt3x_sel_channel].address &= ~(0x7F << 14);
|
||||
m_apu_vt.vt33_pcm[m_apu_vt.vt3x_sel_channel].address |= ((data & 0x7F) << 14);
|
||||
} else if (address == 0x36 && !m_apu_vt.vt33_pcm[m_apu_vt.vt3x_sel_channel].enabled) {
|
||||
m_apu_vt.vt33_pcm[m_apu_vt.vt3x_sel_channel].address &= ~(0xFF << 21);
|
||||
m_apu_vt.vt33_pcm[m_apu_vt.vt3x_sel_channel].address |= (data << 21);
|
||||
m_apu_vt.vt33_pcm[m_apu_vt.vt3x_sel_channel].playing = true;
|
||||
}
|
||||
|
||||
m_apu_vt.extra_regs[address - 0x30] = data;
|
||||
} else if (address == 0x15) {
|
||||
uint8_t nes_val = data;
|
||||
if(m_apu_vt.use_vt03_pcm || m_apu_vt.use_vt3x_pcm)
|
||||
{
|
||||
if (m_apu_vt.use_vt03_pcm) {
|
||||
if (nes_val & 0x10)
|
||||
reset_vt03_pcm(&m_apu_vt.vt03_pcm);
|
||||
else
|
||||
m_apu_vt.vt03_pcm.enabled = false;
|
||||
}
|
||||
|
||||
nes_val &= 0x0F;
|
||||
}
|
||||
nesapu_device::write(0x15, nes_val);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t nesapu_vt_device::vt_apu_read(uint8_t address) {
|
||||
|
||||
if(address >= 0x30 && address <= 0x36)
|
||||
{
|
||||
return m_apu_vt.extra_regs[address - 0x30];
|
||||
} else if (address >= 0x10 && address <= 0x13) {
|
||||
return m_apu_vt.vt03_pcm.regs[address - 0x10];
|
||||
} else if (address == 0x15) {
|
||||
uint8_t base = nesapu_device::read(0x15);
|
||||
if(m_apu_vt.use_vt03_pcm)
|
||||
{
|
||||
base &= 0x4F;
|
||||
base |= (m_apu_vt.vt03_pcm.enabled << 4);
|
||||
base |= m_apu_vt.vt03_pcm.irq_occurred ? 0x80 : 0x00;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
|
||||
|
||||
u8 nesapu_vt_device::read(offs_t address)
|
||||
{
|
||||
// logerror("nesapu_vt read %04x\n", 0x4000 + address);
|
||||
if (address <= 0x0F) {
|
||||
return nesapu_device::read(address);
|
||||
} else if (address >= 0x10 && address <= 0x13) {
|
||||
if(!m_apu_vt.use_vt03_pcm)
|
||||
return nesapu_device::read(address);
|
||||
else
|
||||
return vt_apu_read(address);
|
||||
} else if (address >= 0x20 && address <= 0x2F) {
|
||||
return m_xop2->read(address - 0x20);
|
||||
} else if (address == 0x15 || (address >= 0x30 && address <= 0x36)) {
|
||||
return vt_apu_read(address);
|
||||
} else {
|
||||
logerror("nesapu_vt read %04x\n", 0x4000 + address);
|
||||
return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
void nesapu_vt_device::write(offs_t address, u8 value)
|
||||
{
|
||||
// logerror("nesapu_vt write %04x %02x\n", 0x4000 + address, value);
|
||||
if (address <= 0x0F) {
|
||||
nesapu_device::write(address, value);
|
||||
} else if (address >= 0x10 && address <= 0x13) {
|
||||
//PCM registers affect both new and legacy APU
|
||||
if (m_apu_vt.use_vt03_pcm || m_apu_vt.use_vt3x_pcm)
|
||||
vt_apu_write(address, value);
|
||||
else
|
||||
nesapu_device::write(address, value);
|
||||
} else if (address >= 0x20 && address <= 0x2F) {
|
||||
m_xop2->write(address - 0x20, value);
|
||||
} else if (address == 0x15 || (address >= 0x30 && address <= 0x36)) {
|
||||
vt_apu_write(address, value);
|
||||
} else {
|
||||
logerror("nesapu_vt write %04x %02x\n", 0x4000 + address, value);
|
||||
}
|
||||
}
|
||||
|
||||
MACHINE_CONFIG_START(nesapu_vt_device::device_add_mconfig)
|
||||
MCFG_DEVICE_ADD("nesapu_vt_slave", NES_VT_APU_SLAVE, VTXX_NTSC_APU_CLOCK)
|
||||
MACHINE_CONFIG_END
|
@ -1,140 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Shah
|
||||
/*****************************************************************************
|
||||
|
||||
MAME/MESS VTxx APU CORE
|
||||
|
||||
This core emulates the audio functionality of the V.R. Technology VTxx series
|
||||
of "enhanced NES" system on chips.
|
||||
|
||||
The VTxx APU is effectively two NES APUs with added PCM functionality.
|
||||
|
||||
APU 1 ("XOP1"), is a full-featured NES APU mapped at 0x4000-0x4013, and has
|
||||
full NES functionality plus a new PCM mode in addition to NES-style DPCM,
|
||||
with controls for that at 0x4030 and 0x4031.
|
||||
|
||||
APU2 ("XOP2"), has all functions except DPCM/PCM and is mapped at
|
||||
0x4020-0x402F.
|
||||
|
||||
Newer devices, from the VT09 (?) onwards add new banking registers for PCM,
|
||||
seperate from the CPU's PRG banking registers, located at 0x4125, 0x4126 (high
|
||||
address bank) and 0x4127, 0x4128 (relative high address bank).
|
||||
|
||||
Even newer devices from the VT33 (??) onwards have a new two-channel PCM mode,
|
||||
limited info known. Possible map below, credit to NewRisingSun for reverse
|
||||
engineering this.
|
||||
0x4031,
|
||||
0x4032: select channel 1 or 2 respectively and set volume
|
||||
0x4033: bit 7: global enable, bit 4: ch1 enable, bit3: ch2 enable
|
||||
0x4012: set start address bits 13..6 of selected channel
|
||||
0x4035: set start address bits 20..14 of selected channel
|
||||
0x4036: set start address bits 24..21 of selected channel, and start playing
|
||||
Playback seems to be stopped by a 0xFF sample.
|
||||
This mode will be called enhanced PCM for lack of a better name
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef MAME_SOUND_NES_VT_APU_H
|
||||
#define MAME_SOUND_NES_VT_APU_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nes_apu.h"
|
||||
|
||||
struct apu_vt_t {
|
||||
struct vt03_pcm_t
|
||||
{
|
||||
vt03_pcm_t()
|
||||
{
|
||||
for (auto & elem : regs)
|
||||
elem = 0;
|
||||
}
|
||||
|
||||
float phaseacc = 0.0;
|
||||
uint8_t regs[4];
|
||||
uint32_t address = 0;
|
||||
uint32_t length = 0;
|
||||
uint32_t remaining_bytes = 0;
|
||||
bool enabled = false, irq_occurred = false;
|
||||
uint8_t vol = 0;
|
||||
};
|
||||
|
||||
struct vt3x_pcm_t
|
||||
{
|
||||
vt3x_pcm_t()
|
||||
{
|
||||
for (auto & elem : regs)
|
||||
elem = 0;
|
||||
}
|
||||
|
||||
uint8_t rate = 0;
|
||||
float phaseacc = 0.0;
|
||||
uint32_t address = 0;
|
||||
uint8_t volume = 0;
|
||||
bool enabled = false, playing = false;
|
||||
uint8_t regs[4];
|
||||
int8_t curr = 0;
|
||||
};
|
||||
|
||||
uint8_t extra_regs[7]; //4030 .. 4037
|
||||
|
||||
apu_vt_t()
|
||||
{
|
||||
for (auto & elem : extra_regs)
|
||||
elem = 0;
|
||||
}
|
||||
|
||||
|
||||
int vt3x_sel_channel = 0;
|
||||
vt03_pcm_t vt03_pcm;
|
||||
vt3x_pcm_t vt33_pcm[2];
|
||||
bool use_vt03_pcm = false, use_vt3x_pcm = false;
|
||||
};
|
||||
|
||||
// This represents the "slave APU", which is modified to disable DPCM
|
||||
class nesapu_vt_slave_device : public nesapu_device
|
||||
{
|
||||
public:
|
||||
nesapu_vt_slave_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
|
||||
};
|
||||
|
||||
class nesapu_vt_device : public nesapu_device
|
||||
{
|
||||
public:
|
||||
nesapu_vt_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
template <class Object> devcb_base &set_rom_read_callback(Object &&cb) { return m_rom_read_cb.set_callback(std::forward<Object>(cb)); }
|
||||
auto rom_read() { return m_rom_read_cb.bind(); }
|
||||
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
|
||||
|
||||
virtual u8 read(offs_t offset) override;
|
||||
virtual void write(offs_t offset, u8 data) override;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void device_start() override;
|
||||
|
||||
|
||||
uint8_t vt_apu_read(uint8_t address);
|
||||
void vt_apu_write(uint8_t address, uint8_t data);
|
||||
void vt_apu_regwrite(uint8_t address, uint8_t data);
|
||||
|
||||
apu_vt_t m_apu_vt;
|
||||
|
||||
required_device<nesapu_vt_slave_device> m_xop2;
|
||||
|
||||
s8 vt03_pcm(apu_vt_t::vt03_pcm_t *ch);
|
||||
s8 vt3x_pcm(apu_vt_t::vt3x_pcm_t *ch);
|
||||
void reset_vt03_pcm(apu_vt_t::vt03_pcm_t *ch);
|
||||
void start_vt3x_pcm(apu_vt_t::vt3x_pcm_t *ch);
|
||||
private:
|
||||
devcb_read8 m_rom_read_cb;
|
||||
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(NES_VT_APU, nesapu_vt_device)
|
||||
DECLARE_DEVICE_TYPE(NES_VT_APU_SLAVE, nesapu_vt_slave_device)
|
||||
|
||||
#endif // MAME_SOUND_NES_VT_APU_H
|
@ -74,7 +74,6 @@
|
||||
#include "machine/bankdev.h"
|
||||
#include "video/ppu2c0x_vt.h"
|
||||
#include "machine/m6502_vtscr.h"
|
||||
#include "sound/nes_vt_apu.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
|
||||
@ -127,7 +126,6 @@ private:
|
||||
/* APU handling */
|
||||
DECLARE_WRITE_LINE_MEMBER(apu_irq);
|
||||
DECLARE_READ8_MEMBER(apu_read_mem);
|
||||
DECLARE_READ8_MEMBER(apu_read_rom);
|
||||
DECLARE_READ8_MEMBER(psg1_4014_r);
|
||||
DECLARE_READ8_MEMBER(psg1_4015_r);
|
||||
DECLARE_WRITE8_MEMBER(psg1_4015_w);
|
||||
@ -235,7 +233,7 @@ private:
|
||||
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<ppu_vt03_device> m_ppu;
|
||||
required_device<nesapu_vt_device> m_apu;
|
||||
required_device<nesapu_device> m_apu;
|
||||
required_device<address_map_bank_device> m_prg;
|
||||
required_memory_bank m_prgbank0;
|
||||
required_memory_bank m_prgbank1;
|
||||
@ -1166,7 +1164,7 @@ void nes_vt_state::nes_vt_map(address_map &map)
|
||||
map(0x0000, 0x07ff).ram();
|
||||
map(0x2000, 0x3fff).mask(0x001F).rw(m_ppu, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); /* PPU registers */
|
||||
|
||||
map(0x4000, 0x4036).rw(m_apu, FUNC(nesapu_vt_device::read), FUNC(nesapu_vt_device::write));
|
||||
map(0x4000, 0x4013).rw(m_apu, FUNC(nesapu_device::read), FUNC(nesapu_device::write));
|
||||
map(0x4014, 0x4014).r(FUNC(nes_vt_state::psg1_4014_r)).w(FUNC(nes_vt_state::nes_vh_sprite_dma_w));
|
||||
map(0x4015, 0x4015).rw(FUNC(nes_vt_state::psg1_4015_r), FUNC(nes_vt_state::psg1_4015_w)); /* PSG status / first control register */
|
||||
map(0x4016, 0x4016).rw(FUNC(nes_vt_state::nes_in0_r), FUNC(nes_vt_state::nes_in0_w));
|
||||
@ -1234,7 +1232,7 @@ void nes_vt_state::nes_vt_hh_map(address_map &map)
|
||||
map(0x0000, 0x1fff).mask(0x0fff).ram();
|
||||
map(0x2000, 0x3fff).rw(m_ppu, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); /* PPU registers */
|
||||
|
||||
map(0x4000, 0x4036).rw(m_apu, FUNC(nesapu_vt_device::read), FUNC(nesapu_vt_device::write));
|
||||
map(0x4000, 0x4013).rw(m_apu, FUNC(nesapu_device::read), FUNC(nesapu_device::write));
|
||||
map(0x4015, 0x4015).rw(FUNC(nes_vt_state::psg1_4015_r), FUNC(nes_vt_state::psg1_4015_w)); /* PSG status / first control register */
|
||||
map(0x4016, 0x4016).rw(FUNC(nes_vt_state::nes_in0_r), FUNC(nes_vt_state::nes_in0_w));
|
||||
map(0x4017, 0x4017).r(FUNC(nes_vt_state::nes_in1_r)).w(FUNC(nes_vt_state::psg1_4017_w));
|
||||
@ -1258,7 +1256,7 @@ void nes_vt_state::nes_vt_dg_map(address_map &map)
|
||||
map(0x0000, 0x1fff).ram();
|
||||
map(0x2000, 0x3fff).rw(m_ppu, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); /* PPU registers */
|
||||
|
||||
map(0x4000, 0x4036).rw(m_apu, FUNC(nesapu_vt_device::read), FUNC(nesapu_vt_device::write));
|
||||
map(0x4000, 0x4013).rw(m_apu, FUNC(nesapu_device::read), FUNC(nesapu_device::write));
|
||||
map(0x4015, 0x4015).rw(FUNC(nes_vt_state::psg1_4015_r), FUNC(nes_vt_state::psg1_4015_w)); /* PSG status / first control register */
|
||||
map(0x4016, 0x4016).rw(FUNC(nes_vt_state::nes_in0_r), FUNC(nes_vt_state::nes_in0_w));
|
||||
map(0x4017, 0x4017).r(FUNC(nes_vt_state::nes_in1_r)).w(FUNC(nes_vt_state::psg1_4017_w));
|
||||
@ -1307,17 +1305,12 @@ void nes_vt_state::prg_map(address_map &map)
|
||||
|
||||
WRITE_LINE_MEMBER(nes_vt_state::apu_irq)
|
||||
{
|
||||
m_maincpu->set_input_line(N2A03_APU_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
|
||||
// set_input_line(N2A03_APU_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
READ8_MEMBER(nes_vt_state::apu_read_mem)
|
||||
{
|
||||
return m_maincpu->space(AS_PROGRAM).read_byte(offset);
|
||||
}
|
||||
|
||||
READ8_MEMBER(nes_vt_state::apu_read_rom)
|
||||
{
|
||||
return m_prgrom[offset & (m_romsize - 1)];
|
||||
return 0x00;//mintf->program->read_byte(offset);
|
||||
}
|
||||
|
||||
/* not strictly needed, but helps us see where things are in ROM to aid with figuring out banking schemes*/
|
||||
@ -1390,10 +1383,9 @@ void nes_vt_state::nes_vt_base(machine_config &config)
|
||||
than just using 2 APUs as registers in the 2nd one affect the PCM channel mode but the
|
||||
DMA control still comes from the 1st, but in the new mode, sound always outputs via the
|
||||
2nd. Probably need to split the APU into interface and sound gen logic. */
|
||||
NES_VT_APU(config, m_apu, NTSC_APU_CLOCK);
|
||||
NES_APU(config, m_apu, NTSC_APU_CLOCK);
|
||||
m_apu->irq().set(FUNC(nes_vt_state::apu_irq));
|
||||
m_apu->mem_read().set(FUNC(nes_vt_state::apu_read_mem));
|
||||
m_apu->rom_read().set(FUNC(nes_vt_state::apu_read_rom));
|
||||
m_apu->add_route(ALL_OUTPUTS, "mono", 0.50);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user