/* ** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) ** ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of version 2 of the GNU Library General ** Public License as published by the Free Software Foundation. ** ** This program 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 ** Library General Public License for more details. To obtain a ** copy of the GNU Library General Public License, write to the Free ** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ** ** Any permitted reproduction of these routines, in whole or in part, ** must bear this legend. ** ** ** nes_apu.h ** ** NES APU emulation header file ** $Id$ */ #ifndef _NES_APU_H_ #define _NES_APU_H_ #ifdef __GNUC__ #define INLINE static inline #elif defined(WIN32) #define INLINE static __inline #else #define INLINE static #endif /* define this for realtime generated noise */ #define REALTIME_NOISE #define APU_WRA0 0x4000 #define APU_WRA1 0x4001 #define APU_WRA2 0x4002 #define APU_WRA3 0x4003 #define APU_WRB0 0x4004 #define APU_WRB1 0x4005 #define APU_WRB2 0x4006 #define APU_WRB3 0x4007 #define APU_WRC0 0x4008 #define APU_WRC2 0x400A #define APU_WRC3 0x400B #define APU_WRD0 0x400C #define APU_WRD2 0x400E #define APU_WRD3 0x400F #define APU_WRE0 0x4010 #define APU_WRE1 0x4011 #define APU_WRE2 0x4012 #define APU_WRE3 0x4013 #define APU_OAMDMA 0x4014 #define APU_SMASK 0x4015 #define APU_JOY0 0x4016 #define APU_JOY1 0x4017 /* length of generated noise */ #define APU_NOISE_32K 0x7FFF #define APU_NOISE_93 93 #define APU_BASEFREQ (NES_MASTER_CLOCK / 12) /* to/from 16.16 fixed point */ #define APU_TO_FIXED(x) ((x) << 16) #define APU_FROM_FIXED(x) ((x) >> 16) /* channel structures */ /* As much data as possible is precalculated, ** to keep the sample processing as lean as possible */ typedef struct rectangle_s { uint8 regs[4]; boolean enabled; int32 phaseacc; int32 freq; int32 output_vol; boolean fixed_envelope; boolean holdnote; uint8 volume; int32 sweep_phase; int32 sweep_delay; boolean sweep_on; uint8 sweep_shifts; uint8 sweep_length; boolean sweep_inc; int32 freq_limit; int32 env_phase; int32 env_delay; uint8 env_vol; int vbl_length; uint8 adder; int duty_flip; } rectangle_t; /* enum { COUNTMODE_LOAD, COUNTMODE_COUNT }; */ typedef struct triangle_s { uint8 regs[3]; boolean enabled; int32 freq; int32 phaseacc; int32 output_vol; uint8 adder; boolean holdnote; boolean counter_started; /* quasi-hack */ int write_latency; /* boolean countmode; */ int vbl_length; int linear_length; } triangle_t; typedef struct noise_s { uint8 regs[3]; boolean enabled; int32 freq; int32 phaseacc; int32 output_vol; int32 env_phase; int32 env_delay; uint8 env_vol; boolean fixed_envelope; boolean holdnote; uint8 volume; int vbl_length; #ifdef REALTIME_NOISE uint8 xor_tap; #else boolean short_sample; int cur_pos; #endif /* REALTIME_NOISE */ } noise_t; typedef struct dmc_s { uint8 regs[4]; /* bodge for timestamp queue */ boolean enabled; int32 freq; int32 phaseacc; int32 output_vol; uint32 address; uint32 cached_addr; int dma_length; int cached_dmalength; uint8 cur_byte; boolean looping; boolean irq_gen; boolean irq_occurred; } dmc_t; enum { APU_FILTER_NONE, APU_FILTER_LOWPASS, APU_FILTER_WEIGHTED }; typedef struct { uint32 min_range, max_range; uint8 (*read_func)(uint32 address); } apu_memread; typedef struct { uint32 min_range, max_range; void (*write_func)(uint32 address, uint8 value); } apu_memwrite; /* external sound chip stuff */ typedef struct apuext_s { void (*init)(void); void (*shutdown)(void); void (*reset)(void); int32 (*process)(void); apu_memread *mem_read; apu_memwrite *mem_write; } apuext_t; /* APU queue structure */ #define APUQUEUE_SIZE 4096 #define APUQUEUE_MASK (APUQUEUE_SIZE - 1) /* apu ring buffer member */ typedef struct apudata_s { uint32 timestamp, address; uint8 value; } apudata_t; typedef struct apu_s { rectangle_t rectangle[2]; triangle_t triangle; noise_t noise; dmc_t dmc; uint8 enable_reg; apudata_t queue[APUQUEUE_SIZE]; int q_head, q_tail; uint32 elapsed_cycles; void *buffer; /* pointer to output buffer */ int num_samples; int mix_enable; /* $$$ben : should improve emulation */ int filter_type; int32 cycle_rate; int sample_rate; int sample_bits; int refresh_rate; void (*process)(uint8 *buffer, int num_samples); /* $$$ ben : last error string */ const char * errstr; /* external sound chip */ apuext_t *ext; } apu_t; #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* Function prototypes */ extern apu_t *apu_create(int sample_rate, int refresh_rate, int sample_bits, boolean stereo); extern void apu_destroy(apu_t *apu); extern int apu_setext(apu_t *apu, apuext_t *ext); extern int apu_setfilter(int filter_type); extern void apu_process(uint8 *buffer, int num_samples); extern void apu_reset(void); extern int apu_setchan(int chan, boolean enabled); extern int32 apu_getcyclerate(void); extern apu_t *apu_getcontext(void); extern uint8 apu_read(uint32 address); extern void apu_write(uint32 address, uint8 value); /* for visualization */ extern void apu_getpcmdata(void **data, int *num_samples, int *sample_bits); /* FIXME: added while importing for GStreamer */ void apu_setcontext(apu_t *src_apu); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* _NES_APU_H_ */ /* ** $Log$ ** Revision 1.3 2008/04/09 13:43:51 thaytan ** * gst/nsf/nes_apu.c: (apu_process): ** * gst/nsf/nes_apu.h: ** Don't do void pointer arithmetic - it's a gcc extension. ** ** Revision 1.2 2008-03-25 15:56:12 slomo ** Patch by: Andreas Henriksson ** * gst/nsf/Makefile.am: ** * gst/nsf/dis6502.h: ** * gst/nsf/fds_snd.c: ** * gst/nsf/fds_snd.h: ** * gst/nsf/fmopl.c: ** * gst/nsf/fmopl.h: ** * gst/nsf/gstnsf.c: ** * gst/nsf/log.c: ** * gst/nsf/log.h: ** * gst/nsf/memguard.c: ** * gst/nsf/memguard.h: ** * gst/nsf/mmc5_snd.c: ** * gst/nsf/mmc5_snd.h: ** * gst/nsf/nes6502.c: ** * gst/nsf/nes6502.h: ** * gst/nsf/nes_apu.c: ** * gst/nsf/nes_apu.h: ** * gst/nsf/nsf.c: ** * gst/nsf/nsf.h: ** * gst/nsf/osd.h: ** * gst/nsf/types.h: ** * gst/nsf/vrc7_snd.c: ** * gst/nsf/vrc7_snd.h: ** * gst/nsf/vrcvisnd.c: ** * gst/nsf/vrcvisnd.h: ** Update our internal nosefart to nosefart-2.7-mls to fix segfaults ** on some files. Fixes bug #498237. ** Remove some // comments, fix some compiler warnings and use pow() ** instead of a slow, selfmade implementation. ** ** Revision 1.2 2003/04/09 14:50:32 ben ** Clean NSF api. ** ** Revision 1.1 2003/04/08 20:53:01 ben ** Adding more files... ** ** Revision 1.12 2000/07/04 04:54:48 matt ** minor changes that helped with MAME ** ** Revision 1.11 2000/07/03 02:18:53 matt ** much better external module exporting ** ** Revision 1.10 2000/06/26 05:00:37 matt ** cleanups ** ** Revision 1.9 2000/06/23 03:29:28 matt ** cleaned up external sound inteface ** ** Revision 1.8 2000/06/20 04:06:16 matt ** migrated external sound definition to apu module ** ** Revision 1.7 2000/06/20 00:07:35 matt ** added convenience members to apu_t struct ** ** Revision 1.6 2000/06/09 16:49:02 matt ** removed all floating point from sound generation ** ** Revision 1.5 2000/06/09 15:12:28 matt ** initial revision ** */