From acb0917556fc33681c1df5a530cf754193e67705 Mon Sep 17 00:00:00 2001 From: Andree Buschmann Date: Sun, 7 Aug 2011 20:01:04 +0000 Subject: Submit initial patch from FS#12176. Adds support for several new game music formats (AY, GBS, HES, KSS, SGC, VGM and VGZ) and replaces the current NSF and NSFE with a new implementation based on a port of the Game Music Emu library 'GME'. This first submit does not cover the full functionality provided by the author's original patch: Coleco-SGV is not supported, some GME-specific m3u-support has been removed and IRAM is not used yet. Further changes are very likely to follow this submit. Thanks to Mauricio Garrido. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30264 a1c6a512-1295-4272-9138-f99709370657 --- apps/codecs/libgme/nes_fds_apu.h | 116 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 apps/codecs/libgme/nes_fds_apu.h (limited to 'apps/codecs/libgme/nes_fds_apu.h') diff --git a/apps/codecs/libgme/nes_fds_apu.h b/apps/codecs/libgme/nes_fds_apu.h new file mode 100644 index 0000000000..1360e443db --- /dev/null +++ b/apps/codecs/libgme/nes_fds_apu.h @@ -0,0 +1,116 @@ +// NES FDS sound chip emulator + +// Game_Music_Emu 0.6-pre +#ifndef NES_FDS_APU_H +#define NES_FDS_APU_H + +#include "blargg_common.h" +#include "blip_buffer.h" + +enum { lfo_base_tempo = 8 }; +enum { fds_osc_count = 1 }; + +enum { fds_io_addr = 0x4040 }; +enum { fds_io_size = 0x53 }; + +enum { fds_wave_size = 0x40 }; +enum { fds_master_vol_max = 10 }; +enum { fds_vol_max = 0x20 }; +enum { fds_wave_sample_max = 0x3F }; + +struct Nes_Fds_Apu { + unsigned char regs_ [fds_io_size];// last written value to registers + int lfo_tempo; // normally 8; adjusted by set_tempo() + + int env_delay; + int env_speed; + int env_gain; + + int sweep_delay; + int sweep_speed; + int sweep_gain; + + int wave_pos; + int last_amp; + blip_time_t wave_fract; + + int mod_fract; + int mod_pos; + int mod_write_pos; + unsigned char mod_wave [fds_wave_size]; + + // synthesis + blip_time_t last_time; + struct Blip_Buffer* output_; + struct Blip_Synth synth; +}; + +// init +void Fds_init( struct Nes_Fds_Apu* this ); +// setup +void Fds_set_tempo( struct Nes_Fds_Apu* this, double t ); + +// emulation +void Fds_reset( struct Nes_Fds_Apu* this ); + +static inline void Fds_volume( struct Nes_Fds_Apu* this, double v ) +{ + Synth_volume( &this->synth, 0.14 / fds_master_vol_max / fds_vol_max / fds_wave_sample_max * v ); +} + +static inline void Fds_set_output( struct Nes_Fds_Apu* this, int i, struct Blip_Buffer* b ) +{ +#if defined(ROCKBOX) + (void) i; +#endif + + assert( (unsigned) i < fds_osc_count ); + this->output_ = b; +} + +void Fds_run_until( struct Nes_Fds_Apu* this, blip_time_t ) ICODE_ATTR; +static inline void Fds_end_frame( struct Nes_Fds_Apu* this, blip_time_t end_time ) +{ + if ( end_time > this->last_time ) + Fds_run_until( this, end_time ); + this->last_time -= end_time; + assert( this->last_time >= 0 ); +} + +void Fds_write_( struct Nes_Fds_Apu* this, unsigned addr, int data ) ICODE_ATTR; +static inline void Fds_write( struct Nes_Fds_Apu* this, blip_time_t time, unsigned addr, int data ) +{ + Fds_run_until( this, time ); + Fds_write_( this, addr, data ); +} + +static inline int Fds_read( struct Nes_Fds_Apu* this, blip_time_t time, unsigned addr ) +{ + Fds_run_until( this, time ); + + int result = 0xFF; + switch ( addr ) + { + case 0x4090: + result = this->env_gain; + break; + + case 0x4092: + result = this->sweep_gain; + break; + + default: + { + unsigned i = addr - fds_io_addr; + if ( i < fds_wave_size ) + result = this->regs_ [i]; + } + } + + return result | 0x40; +} + +// allow access to registers by absolute address (i.e. 0x4080) +static inline unsigned char* regs_nes( struct Nes_Fds_Apu* this, unsigned addr ) { return &this->regs_ [addr - fds_io_addr]; } + +#endif -- cgit v1.2.3