diff options
Diffstat (limited to 'plugins/gme/game-music-emu-0.6pre/gme/Nsf_Core.cpp')
-rw-r--r-- | plugins/gme/game-music-emu-0.6pre/gme/Nsf_Core.cpp | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/plugins/gme/game-music-emu-0.6pre/gme/Nsf_Core.cpp b/plugins/gme/game-music-emu-0.6pre/gme/Nsf_Core.cpp new file mode 100644 index 00000000..f0822250 --- /dev/null +++ b/plugins/gme/game-music-emu-0.6pre/gme/Nsf_Core.cpp @@ -0,0 +1,302 @@ +// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/ + +#include "Nsf_Core.h" + +#include "blargg_endian.h" + +#if !NSF_EMU_APU_ONLY + #include "Nes_Namco_Apu.h" + #include "Nes_Vrc6_Apu.h" + #include "Nes_Fme7_Apu.h" + #include "Nes_Fds_Apu.h" + #include "Nes_Mmc5_Apu.h" + #include "Nes_Vrc7_Apu.h" +#endif + +/* Copyright (C) 2003-2008 Shay Green. This module 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.1 of the License, or (at your option) any later version. This +module 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. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +Nsf_Core::Nsf_Core() +{ + fds = NULL; + fme7 = NULL; + mmc5 = NULL; + namco = NULL; + vrc6 = NULL; + vrc7 = NULL; +} + +Nsf_Core::~Nsf_Core() +{ + unload(); +} + +void Nsf_Core::unload() +{ +#if !NSF_EMU_APU_ONLY + delete fds; + fds = NULL; + + delete fme7; + fme7 = NULL; + + delete namco; + namco = NULL; + + delete mmc5; + mmc5 = NULL; + + delete vrc6; + vrc6 = NULL; + + delete vrc7; + vrc7 = NULL; +#endif + + Nsf_Impl::unload(); +} + +void Nsf_Core::set_tempo( double t ) +{ + set_play_period( (int) (header().play_period() / t) ); + nes_apu()->set_tempo( t ); +#if !NSF_EMU_APU_ONLY + if ( fds ) + fds->set_tempo( t ); +#endif +} + +blargg_err_t Nsf_Core::post_load() +{ + int chip_flags = header().chip_flags; + + #if !NSF_EMU_APU_ONLY + if ( chip_flags & header_t::fds_mask ) + CHECK_ALLOC( fds = BLARGG_NEW Nes_Fds_Apu ); + + if ( chip_flags & header_t::fme7_mask ) + CHECK_ALLOC( fme7 = BLARGG_NEW Nes_Fme7_Apu ); + + if ( chip_flags & header_t::mmc5_mask ) + CHECK_ALLOC( mmc5 = BLARGG_NEW Nes_Mmc5_Apu ); + + if ( chip_flags & header_t::namco_mask ) + CHECK_ALLOC( namco = BLARGG_NEW Nes_Namco_Apu ); + + if ( chip_flags & header_t::vrc6_mask ) + CHECK_ALLOC( vrc6 = BLARGG_NEW Nes_Vrc6_Apu ); + + if ( chip_flags & header_t::vrc7_mask ) + { + #if NSF_EMU_NO_VRC7 + chip_flags = ~chips_mask; // give warning rather than error + #else + CHECK_ALLOC( vrc7 = BLARGG_NEW Nes_Vrc7_Apu ); + RETURN_ERR( vrc7->init() ); + #endif + } + #endif + + set_tempo( 1.0 ); + + if ( chip_flags & ~chips_mask ) + set_warning( "Uses unsupported audio expansion hardware" ); + + return Nsf_Impl::post_load(); +} + +int Nsf_Core::cpu_read( addr_t addr ) +{ + #if !NSF_EMU_APU_ONLY + { + if ( addr == Nes_Namco_Apu::data_reg_addr && namco ) + return namco->read_data(); + + if ( (unsigned) (addr - Nes_Fds_Apu::io_addr) < Nes_Fds_Apu::io_size && fds ) + return fds->read( time(), addr ); + + int i = addr - 0x5C00; + if ( (unsigned) i < mmc5->exram_size && mmc5 ) + return mmc5->exram [i]; + + int m = addr - 0x5205; + if ( (unsigned) m < 2 && mmc5 ) + return (mmc5_mul [0] * mmc5_mul [1]) >> (m * 8) & 0xFF; + } + #endif + + return Nsf_Impl::cpu_read( addr ); +} + +int Nsf_Core::unmapped_read( addr_t addr ) +{ + switch ( addr ) + { + case 0x2002: + case 0x4016: + case 0x4017: + return addr >> 8; + } + + return Nsf_Impl::unmapped_read( addr ); +} + +void Nsf_Core::cpu_write( addr_t addr, int data ) +{ + #if !NSF_EMU_APU_ONLY + { + if ( (unsigned) (addr - fds->io_addr) < fds->io_size && fds ) + { + fds->write( time(), addr, data ); + return; + } + + if ( namco ) + { + if ( addr == namco->addr_reg_addr ) + { + namco->write_addr( data ); + return; + } + + if ( addr == namco->data_reg_addr ) + { + namco->write_data( time(), data ); + return; + } + } + + if ( vrc6 ) + { + int reg = addr & (vrc6->addr_step - 1); + int osc = (unsigned) (addr - vrc6->base_addr) / vrc6->addr_step; + if ( (unsigned) osc < vrc6->osc_count && (unsigned) reg < vrc6->reg_count ) + { + vrc6->write_osc( time(), osc, reg, data ); + return; + } + } + + if ( addr >= fme7->latch_addr && fme7 ) + { + switch ( addr & fme7->addr_mask ) + { + case Nes_Fme7_Apu::latch_addr: + fme7->write_latch( data ); + return; + + case Nes_Fme7_Apu::data_addr: + fme7->write_data( time(), data ); + return; + } + } + + if ( mmc5 ) + { + if ( (unsigned) (addr - mmc5->regs_addr) < mmc5->regs_size ) + { + mmc5->write_register( time(), addr, data ); + return; + } + + int m = addr - 0x5205; + if ( (unsigned) m < 2 ) + { + mmc5_mul [m] = data; + return; + } + + int i = addr - 0x5C00; + if ( (unsigned) i < mmc5->exram_size ) + { + mmc5->exram [i] = data; + return; + } + } + + if ( vrc7 ) + { + if ( addr == 0x9010 ) + { + vrc7->write_reg( data ); + return; + } + + if ( (unsigned) (addr - 0x9028) <= 0x08 ) + { + vrc7->write_data( time(), data ); + return; + } + } + } + #endif + + return Nsf_Impl::cpu_write( addr, data ); +} + +void Nsf_Core::unmapped_write( addr_t addr, int data ) +{ + switch ( addr ) + { + case 0x8000: // some write to $8000 and $8001 repeatedly + case 0x8001: + case 0x4800: // probably namco sound mistakenly turned on in MCK + case 0xF800: + case 0xFFF8: // memory mapper? + return; + } + + if ( mmc5 && addr == 0x5115 ) return; + + // FDS memory + if ( fds && (unsigned) (addr - 0x8000) < 0x6000 ) return; + + Nsf_Impl::unmapped_write( addr, data ); +} + +blargg_err_t Nsf_Core::start_track( int track ) +{ + #if !NSF_EMU_APU_ONLY + if ( mmc5 ) + { + mmc5_mul [0] = 0; + mmc5_mul [1] = 0; + memset( mmc5->exram, 0, mmc5->exram_size ); + } + #endif + + #if !NSF_EMU_APU_ONLY + if ( fds ) fds ->reset(); + if ( fme7 ) fme7 ->reset(); + if ( mmc5 ) mmc5 ->reset(); + if ( namco ) namco->reset(); + if ( vrc6 ) vrc6 ->reset(); + if ( vrc7 ) vrc7 ->reset(); + #endif + + return Nsf_Impl::start_track( track ); +} + +void Nsf_Core::end_frame( time_t end ) +{ + Nsf_Impl::end_frame( end ); + + #if !NSF_EMU_APU_ONLY + if ( fds ) fds ->end_frame( end ); + if ( fme7 ) fme7 ->end_frame( end ); + if ( mmc5 ) mmc5 ->end_frame( end ); + if ( namco ) namco->end_frame( end ); + if ( vrc6 ) vrc6 ->end_frame( end ); + if ( vrc7 ) vrc7 ->end_frame( end ); + #endif +} |