diff options
author | 0kmg <9137159+0kmg@users.noreply.github.com> | 2022-09-03 10:02:59 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-04 04:02:59 +1000 |
commit | 2468371a075875e43b24e53a3ecbfe27a879d425 (patch) | |
tree | 5e21fcd3d9cd9e8dc6294b1b77bca406514f5995 | |
parent | 7a50a679c4f35d68022ff0d19d95f8865ef74848 (diff) |
sound/nes_apu.cpp: Added earliest hardware variant of 2A03 APU. (#10299)
Fixes several audio bugs with the noise channel in VS. System games, including:
* High-pitch sound in vsgshoe percussion track.
* Jet sounds in bnglngby.
* Number of tanks killed count screen in btlecity.
* nvs_platoon's bullet and enemies dying sounds are subtly changed.
It's estimated that these letterless CPU versions are in the first two
million or so Famicoms (about 10% of Famicoms sold). There are games
developed on the RP2A03 that have sound glitches on later, more common
Famicoms. For instance, the very last note in the game over melody in
Balloon Fight rings out with a loud buzz on later machines. The new
famicomo driver plays it as the developers must have intended.
New working clones
------------------
Nintendo Famicom (earlier, with RP2A03) [kmg]
-rw-r--r-- | src/devices/cpu/m6502/n2a03.cpp | 27 | ||||
-rw-r--r-- | src/devices/cpu/m6502/n2a03.h | 15 | ||||
-rw-r--r-- | src/devices/sound/nes_apu.cpp | 29 | ||||
-rw-r--r-- | src/devices/sound/nes_apu.h | 15 | ||||
-rw-r--r-- | src/devices/sound/nes_defs.h | 2 | ||||
-rw-r--r-- | src/mame/mame.lst | 1 | ||||
-rw-r--r-- | src/mame/nintendo/cham24.cpp | 2 | ||||
-rw-r--r-- | src/mame/nintendo/famibox.cpp | 2 | ||||
-rw-r--r-- | src/mame/nintendo/multigam.cpp | 2 | ||||
-rw-r--r-- | src/mame/nintendo/nes.cpp | 18 | ||||
-rw-r--r-- | src/mame/nintendo/nes.h | 1 | ||||
-rw-r--r-- | src/mame/nintendo/nes_arcade_bl.cpp | 2 | ||||
-rw-r--r-- | src/mame/nintendo/nes_clone.cpp | 4 | ||||
-rw-r--r-- | src/mame/nintendo/playch10.cpp | 2 | ||||
-rw-r--r-- | src/mame/virtual/vgmplay.cpp | 4 |
15 files changed, 102 insertions, 24 deletions
diff --git a/src/devices/cpu/m6502/n2a03.cpp b/src/devices/cpu/m6502/n2a03.cpp index e1731b62e75..f0914298659 100644 --- a/src/devices/cpu/m6502/n2a03.cpp +++ b/src/devices/cpu/m6502/n2a03.cpp @@ -13,7 +13,8 @@ #include "n2a03d.h" DEFINE_DEVICE_TYPE(N2A03_CORE, n2a03_core_device, "n2a03_core", "Ricoh N2A03 core") // needed for some VT systems with XOP instead of standard APU -DEFINE_DEVICE_TYPE(N2A03, n2a03_device, "n2a03", "Ricoh N2A03") +DEFINE_DEVICE_TYPE(N2A03, n2a03_device, "n2a03", "Ricoh N2A03") // earliest version, found in punchout, spnchout, dkong3, VS. systems, and some early Famicoms +DEFINE_DEVICE_TYPE(N2A03G, n2a03g_device, "n2a03g", "Ricoh N2A03G") // later revision, found in front-loader NES uint8_t n2a03_device::psg1_4014_r() { @@ -64,14 +65,24 @@ n2a03_core_device::n2a03_core_device(const machine_config &mconfig, const char * -n2a03_device::n2a03_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : n2a03_core_device(mconfig, N2A03, tag, owner, clock) +n2a03_device::n2a03_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : n2a03_core_device(mconfig, type, tag, owner, clock) , device_mixer_interface(mconfig, *this, 1) , m_apu(*this, "nesapu") { program_config.m_internal_map = address_map_constructor(FUNC(n2a03_device::n2a03_map), this); } +n2a03_device::n2a03_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : n2a03_device(mconfig, N2A03, tag, owner, clock) +{ +} + +n2a03g_device::n2a03g_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : n2a03_device(mconfig, N2A03G, tag, owner, clock) +{ +} + std::unique_ptr<util::disasm_interface> n2a03_core_device::create_disassembler() @@ -92,11 +103,19 @@ uint8_t n2a03_device::apu_read_mem(offs_t offset) void n2a03_device::device_add_mconfig(machine_config &config) { - NES_APU(config, m_apu, DERIVED_CLOCK(1,1)); + APU_2A03(config, m_apu, DERIVED_CLOCK(1,1)); m_apu->irq().set(FUNC(n2a03_device::apu_irq)); m_apu->mem_read().set(FUNC(n2a03_device::apu_read_mem)); m_apu->add_route(ALL_OUTPUTS, *this, 1.0, AUTO_ALLOC_INPUT, 0); } +void n2a03g_device::device_add_mconfig(machine_config &config) +{ + NES_APU(config, m_apu, DERIVED_CLOCK(1,1)); + m_apu->irq().set(FUNC(n2a03g_device::apu_irq)); + m_apu->mem_read().set(FUNC(n2a03g_device::apu_read_mem)); + m_apu->add_route(ALL_OUTPUTS, *this, 1.0, AUTO_ALLOC_INPUT, 0); +} + #include "cpu/m6502/n2a03.hxx" diff --git a/src/devices/cpu/m6502/n2a03.h b/src/devices/cpu/m6502/n2a03.h index 4232093c7a5..28b43233dcc 100644 --- a/src/devices/cpu/m6502/n2a03.h +++ b/src/devices/cpu/m6502/n2a03.h @@ -51,18 +51,26 @@ public: void psg1_4017_w(uint8_t data); void n2a03_map(address_map &map); + protected: + n2a03_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); required_device<nesapu_device> m_apu; virtual void device_add_mconfig(machine_config &config) override; -private: DECLARE_WRITE_LINE_MEMBER(apu_irq); uint8_t apu_read_mem(offs_t offset); - }; +class n2a03g_device : public n2a03_device +{ +public: + n2a03g_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void device_add_mconfig(machine_config &config) override; +}; /* These are the official XTAL values and clock rates used by Nintendo for manufacturing throughout the production of the 2A03. PALC_APU_CLOCK is @@ -82,6 +90,7 @@ enum { }; DECLARE_DEVICE_TYPE(N2A03_CORE, n2a03_core_device) -DECLARE_DEVICE_TYPE(N2A03, n2a03_device) +DECLARE_DEVICE_TYPE(N2A03, n2a03_device) +DECLARE_DEVICE_TYPE(N2A03G, n2a03g_device) #endif // MAME_CPU_M6502_N2A03_H diff --git a/src/devices/sound/nes_apu.cpp b/src/devices/sound/nes_apu.cpp index a7e8a3066f7..ee038128524 100644 --- a/src/devices/sound/nes_apu.cpp +++ b/src/devices/sound/nes_apu.cpp @@ -45,7 +45,8 @@ #include "emu.h" #include "nes_apu.h" -DEFINE_DEVICE_TYPE(NES_APU, nesapu_device, "nesapu", "N2A03 APU") +DEFINE_DEVICE_TYPE(NES_APU, nesapu_device, "nesapu", "N2A0X APU") +DEFINE_DEVICE_TYPE(APU_2A03, apu2a03_device, "apu2a03", "RP2A03 APU") nesapu_device::nesapu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, type, tag, owner, clock) @@ -63,6 +64,12 @@ nesapu_device::nesapu_device(const machine_config& mconfig, const char* tag, dev { } +apu2a03_device::apu2a03_device(const machine_config& mconfig, const char* tag, device_t* owner, u32 clock) + : nesapu_device(mconfig, APU_2A03, tag, owner, clock) +{ +} + + void nesapu_device::device_reset() { write(0x15, 0x00); @@ -177,7 +184,7 @@ void nesapu_device::device_start() save_item(NAME(m_APU.tri.output)); save_item(NAME(m_APU.noi.regs)); - save_item(NAME(m_APU.noi.seed)); + save_item(NAME(m_APU.noi.lfsr)); save_item(NAME(m_APU.noi.vbl_length)); save_item(NAME(m_APU.noi.phaseacc)); save_item(NAME(m_APU.noi.env_phase)); @@ -385,10 +392,10 @@ void nesapu_device::apu_noise(apu_t::noise_t *chan) while (chan->phaseacc < 0) { chan->phaseacc += freq; - chan->seed = (chan->seed >> 1) | ((BIT(chan->seed, 0) ^ BIT(chan->seed, (chan->regs[2] & 0x80) ? 6 : 1)) << 14); + update_lfsr(*chan); } - if (BIT(chan->seed, 0)) /* make it silence */ + if (BIT(chan->lfsr, 0)) /* silence channel */ { chan->output = 0; return; @@ -400,6 +407,18 @@ void nesapu_device::apu_noise(apu_t::noise_t *chan) chan->output = 0x0f - chan->env_vol; } +void nesapu_device::update_lfsr(apu_t::noise_t &chan) +{ + chan.lfsr |= (BIT(chan.lfsr, 0) ^ BIT(chan.lfsr, (chan.regs[2] & 0x80) ? 6 : 1)) << 15; + chan.lfsr >>= 1; +} + +void apu2a03_device::update_lfsr(apu_t::noise_t &chan) +{ + chan.lfsr |= (BIT(chan.lfsr, 0) ^ BIT(chan.lfsr, 1)) << 15; + chan.lfsr >>= 1; +} + /* RESET DPCM PARAMETERS */ static inline void apu_dpcmreset(apu_t::dpcm_t *chan) { @@ -609,7 +628,7 @@ void nesapu_device::write(offs_t offset, u8 value) break; case apu_t::IRQCTRL: - if(value & 0x80) + if (value & 0x80) m_APU.step_mode = 5; else m_APU.step_mode = 4; diff --git a/src/devices/sound/nes_apu.h b/src/devices/sound/nes_apu.h index bb694b79ffa..42a92be2b0e 100644 --- a/src/devices/sound/nes_apu.h +++ b/src/devices/sound/nes_apu.h @@ -64,6 +64,8 @@ protected: // sound stream update overrides virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; + virtual void update_lfsr(apu_t::noise_t &chan); + private: /* GLOBAL CONSTANTS */ static constexpr unsigned SYNCS_MAX1 = 0x20; @@ -92,6 +94,17 @@ private: void apu_dpcm(apu_t::dpcm_t *chan); }; -DECLARE_DEVICE_TYPE(NES_APU, nesapu_device) +class apu2a03_device : public nesapu_device +{ +public: + apu2a03_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + virtual void update_lfsr(apu_t::noise_t &chan) override; +}; + + +DECLARE_DEVICE_TYPE(NES_APU, nesapu_device) +DECLARE_DEVICE_TYPE(APU_2A03, apu2a03_device) #endif // MAME_SOUND_NES_APU_H diff --git a/src/devices/sound/nes_defs.h b/src/devices/sound/nes_defs.h index 1f4544b02c2..a9ee22bef92 100644 --- a/src/devices/sound/nes_defs.h +++ b/src/devices/sound/nes_defs.h @@ -86,7 +86,7 @@ struct apu_t } u8 regs[4]; /* regs[1] unused */ - u32 seed = 1; + u16 lfsr = 1; int vbl_length = 0; float phaseacc = 0.0; float env_phase = 0.0; diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 0b950eda7c4..a70d9fe06c7 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -33382,6 +33382,7 @@ dendy2 // Dendy Classic 2 (Russian import of IQ-502 fam sb486 // Subor/Xiao Ba Wang SB-486 drpcjr // Bung Doctor PC Jr famicom // Nintendo Family Computer (a.k.a. Famicom) +famicomo // Nintendo Family Computer (original with RP2A03) famitvc1 // Sharp My Computer Terebi C1 famitwin // Sharp Famicom Twin System fds // Nintendo Family Computer (a.k.a. Famicom) + Disk System add-on diff --git a/src/mame/nintendo/cham24.cpp b/src/mame/nintendo/cham24.cpp index ec66bfe6eba..8e197c98f59 100644 --- a/src/mame/nintendo/cham24.cpp +++ b/src/mame/nintendo/cham24.cpp @@ -250,7 +250,7 @@ void cham24_state::machine_reset() void cham24_state::cham24(machine_config &config) { /* basic machine hardware */ - N2A03(config, m_maincpu, NTSC_APU_CLOCK); + N2A03G(config, m_maincpu, NTSC_APU_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &cham24_state::cham24_map); /* video hardware */ diff --git a/src/mame/nintendo/famibox.cpp b/src/mame/nintendo/famibox.cpp index c3146538d9c..22bb956ba88 100644 --- a/src/mame/nintendo/famibox.cpp +++ b/src/mame/nintendo/famibox.cpp @@ -523,7 +523,7 @@ void famibox_state::machine_start() void famibox_state::famibox(machine_config &config) { // basic machine hardware - N2A03(config, m_maincpu, NTSC_APU_CLOCK); + N2A03G(config, m_maincpu, NTSC_APU_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &famibox_state::famibox_map); // video hardware diff --git a/src/mame/nintendo/multigam.cpp b/src/mame/nintendo/multigam.cpp index 3675da93132..5dc1d44bda6 100644 --- a/src/mame/nintendo/multigam.cpp +++ b/src/mame/nintendo/multigam.cpp @@ -1184,7 +1184,7 @@ MACHINE_START_MEMBER(multigam_state,supergm3) void multigam_state::multigam(machine_config &config) { /* basic machine hardware */ - N2A03(config, m_maincpu, NTSC_APU_CLOCK); + N2A03G(config, m_maincpu, NTSC_APU_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &multigam_state::multigam_map); /* video hardware */ diff --git a/src/mame/nintendo/nes.cpp b/src/mame/nintendo/nes.cpp index 0b8d01427c1..790a740af07 100644 --- a/src/mame/nintendo/nes.cpp +++ b/src/mame/nintendo/nes.cpp @@ -51,7 +51,7 @@ INPUT_PORTS_END void nes_state::nes(machine_config &config) { // basic machine hardware - n2a03_device &maincpu(N2A03(config, m_maincpu, NTSC_APU_CLOCK)); + n2a03_device &maincpu(N2A03G(config, m_maincpu, NTSC_APU_CLOCK)); maincpu.set_addrmap(AS_PROGRAM, &nes_state::nes_map); SCREEN(config, m_screen, SCREEN_TYPE_RASTER); @@ -121,6 +121,17 @@ void nes_state::famicom(machine_config &config) SOFTWARE_LIST(config, "cass_list").set_original("famicom_cass"); } +void nes_state::famicomo(machine_config &config) +{ + famicom(config); + + // basic machine hardware + n2a03_device &maincpu(N2A03(config.replace(), m_maincpu, NTSC_APU_CLOCK)); + maincpu.set_addrmap(AS_PROGRAM, &nes_state::nes_map); + + maincpu.add_route(ALL_OUTPUTS, "mono", 0.90); +} + void nes_state::nespalc(machine_config &config) { nespal(config); @@ -314,6 +325,10 @@ ROM_START( famicom ) ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 ) // Main RAM ROM_END +ROM_START( famicomo ) + ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASE00 ) // Main RAM +ROM_END + ROM_START( famitvc1 ) ROM_REGION( 0x2000, "canvas_prg", 0 ) ROM_LOAD( "ix0402ce.ic109", 0x0000, 0x2000, CRC(96456b13) SHA1(a4dcb3c4f2be5077f0d197e870a26414287ce189) ) // dump needs verified @@ -398,6 +413,7 @@ CONS( 198?, m82p, nes, 0, nespal, nes, nes_state, empty_init, // Famicom hardware CONS( 1983, famicom, 0, nes, famicom, famicom, nes_state, init_famicom, "Nintendo", "Famicom", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) +CONS( 1983, famicomo, famicom, 0, famicomo, famicom, nes_state, init_famicom, "Nintendo", "Famicom (earlier, with RP2A03)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) CONS( 1983, famitvc1, famicom, 0, famitvc1, famicom, nes_state, init_famicom, "Sharp", "My Computer Terebi C1", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // working but for unimplemented save/load in builtin cartridge, which causes system to hang CONS( 1986, fds, famicom, 0, fds, famicom, nes_state, init_famicom, "Nintendo", "Famicom (w/ Disk System add-on)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) CONS( 1986, famitwin, famicom, 0, famitwin, famicom, nes_state, init_famicom, "Sharp", "Famicom Twin", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/nintendo/nes.h b/src/mame/nintendo/nes.h index bf0be0b5d7d..f1c3ae6d452 100644 --- a/src/mame/nintendo/nes.h +++ b/src/mame/nintendo/nes.h @@ -85,6 +85,7 @@ public: void suborkbd(machine_config &config); void famipalc(machine_config &config); void famicom(machine_config &config); + void famicomo(machine_config &config); void famitvc1(machine_config &config); void famitwin(machine_config &config); void nespal(machine_config &config); diff --git a/src/mame/nintendo/nes_arcade_bl.cpp b/src/mame/nintendo/nes_arcade_bl.cpp index 346b64eb96d..71a4446ae28 100644 --- a/src/mame/nintendo/nes_arcade_bl.cpp +++ b/src/mame/nintendo/nes_arcade_bl.cpp @@ -116,7 +116,7 @@ INPUT_PORTS_END void nes_arcade_bl_state::smb3bl(machine_config &config) { - N2A03(config, m_maincpu, 3.579545_MHz_XTAL / 2); // TODO: verify divider + N2A03G(config, m_maincpu, 3.579545_MHz_XTAL / 2); // TODO: verify divider m_maincpu->set_addrmap(AS_PROGRAM, &nes_arcade_bl_state::nes_cpu_map); z80_device &timercpu(Z80(config, "timercpu", 3.579545_MHz_XTAL)); diff --git a/src/mame/nintendo/nes_clone.cpp b/src/mame/nintendo/nes_clone.cpp index 75975dc4a34..82cfb8ee90f 100644 --- a/src/mame/nintendo/nes_clone.cpp +++ b/src/mame/nintendo/nes_clone.cpp @@ -404,7 +404,7 @@ void nes_clone_state::machine_start() void nes_clone_state::nes_clone(machine_config &config) { /* basic machine hardware */ - N2A03(config, m_maincpu, NTSC_APU_CLOCK); + N2A03G(config, m_maincpu, NTSC_APU_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &nes_clone_state::nes_clone_map); /* video hardware */ @@ -427,7 +427,7 @@ void nes_clone_state::nes_clone(machine_config &config) void nes_clone_state::nes_clone_pal(machine_config &config) { /* basic machine hardware */ - N2A03(config, m_maincpu, PALC_APU_CLOCK); + N2A03G(config, m_maincpu, PALC_APU_CLOCK); m_maincpu->set_addrmap(AS_PROGRAM, &nes_clone_state::nes_clone_map); /* video hardware */ diff --git a/src/mame/nintendo/playch10.cpp b/src/mame/nintendo/playch10.cpp index 436c4905597..ed33534f2e7 100644 --- a/src/mame/nintendo/playch10.cpp +++ b/src/mame/nintendo/playch10.cpp @@ -1906,7 +1906,7 @@ void playch10_state::playch10(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &playch10_state::bios_map); m_maincpu->set_addrmap(AS_IO, &playch10_state::bios_io_map); - N2A03(config, m_cartcpu, NTSC_APU_CLOCK); + N2A03G(config, m_cartcpu, NTSC_APU_CLOCK); m_cartcpu->set_addrmap(AS_PROGRAM, &playch10_state::cart_map); ls259_device &outlatch1(LS259(config, "outlatch1")); // 7D diff --git a/src/mame/virtual/vgmplay.cpp b/src/mame/virtual/vgmplay.cpp index a7402341fb4..4c4032f9076 100644 --- a/src/mame/virtual/vgmplay.cpp +++ b/src/mame/virtual/vgmplay.cpp @@ -3845,13 +3845,13 @@ void vgmplay_state::vgmplay(machine_config &config) m_dmg[1]->add_route(0, m_mixer, 1, AUTO_ALLOC_INPUT, 0); m_dmg[1]->add_route(0, m_mixer, 1, AUTO_ALLOC_INPUT, 1); - N2A03(config, m_nescpu[0], 0); + N2A03G(config, m_nescpu[0], 0); m_nescpu[0]->set_addrmap(AS_PROGRAM, &vgmplay_state::nescpu_map<0>); m_nescpu[0]->set_disable(); m_nescpu[0]->add_route(ALL_OUTPUTS, m_mixer, 0.50, AUTO_ALLOC_INPUT, 0); m_nescpu[0]->add_route(ALL_OUTPUTS, m_mixer, 0.50, AUTO_ALLOC_INPUT, 1); - N2A03(config, m_nescpu[1], 0); + N2A03G(config, m_nescpu[1], 0); m_nescpu[1]->set_addrmap(AS_PROGRAM, &vgmplay_state::nescpu_map<1>); m_nescpu[1]->set_disable(); m_nescpu[1]->add_route(ALL_OUTPUTS, m_mixer, 0.50, AUTO_ALLOC_INPUT, 0); |