diff options
author | Andree Buschmann <AndreeBuschmann@t-online.de> | 2011-08-07 20:01:04 +0000 |
---|---|---|
committer | Andree Buschmann <AndreeBuschmann@t-online.de> | 2011-08-07 20:01:04 +0000 |
commit | acb0917556fc33681c1df5a530cf754193e67705 (patch) | |
tree | 052a47097009a210e4aed9c207bd6aa4828cc000 /apps/codecs/libgme/nes_fds_apu.h | |
parent | 93c6f1329a5691a8be158cefe15641bd1daf9ef8 (diff) | |
download | rockbox-acb0917556fc33681c1df5a530cf754193e67705.tar.gz rockbox-acb0917556fc33681c1df5a530cf754193e67705.zip |
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
Diffstat (limited to 'apps/codecs/libgme/nes_fds_apu.h')
-rw-r--r-- | apps/codecs/libgme/nes_fds_apu.h | 116 |
1 files changed, 116 insertions, 0 deletions
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 @@ | |||
1 | // NES FDS sound chip emulator | ||
2 | |||
3 | // Game_Music_Emu 0.6-pre | ||
4 | #ifndef NES_FDS_APU_H | ||
5 | #define NES_FDS_APU_H | ||
6 | |||
7 | #include "blargg_common.h" | ||
8 | #include "blip_buffer.h" | ||
9 | |||
10 | enum { lfo_base_tempo = 8 }; | ||
11 | enum { fds_osc_count = 1 }; | ||
12 | |||
13 | enum { fds_io_addr = 0x4040 }; | ||
14 | enum { fds_io_size = 0x53 }; | ||
15 | |||
16 | enum { fds_wave_size = 0x40 }; | ||
17 | enum { fds_master_vol_max = 10 }; | ||
18 | enum { fds_vol_max = 0x20 }; | ||
19 | enum { fds_wave_sample_max = 0x3F }; | ||
20 | |||
21 | struct Nes_Fds_Apu { | ||
22 | unsigned char regs_ [fds_io_size];// last written value to registers | ||
23 | int lfo_tempo; // normally 8; adjusted by set_tempo() | ||
24 | |||
25 | int env_delay; | ||
26 | int env_speed; | ||
27 | int env_gain; | ||
28 | |||
29 | int sweep_delay; | ||
30 | int sweep_speed; | ||
31 | int sweep_gain; | ||
32 | |||
33 | int wave_pos; | ||
34 | int last_amp; | ||
35 | blip_time_t wave_fract; | ||
36 | |||
37 | int mod_fract; | ||
38 | int mod_pos; | ||
39 | int mod_write_pos; | ||
40 | unsigned char mod_wave [fds_wave_size]; | ||
41 | |||
42 | // synthesis | ||
43 | blip_time_t last_time; | ||
44 | struct Blip_Buffer* output_; | ||
45 | struct Blip_Synth synth; | ||
46 | }; | ||
47 | |||
48 | // init | ||
49 | void Fds_init( struct Nes_Fds_Apu* this ); | ||
50 | // setup | ||
51 | void Fds_set_tempo( struct Nes_Fds_Apu* this, double t ); | ||
52 | |||
53 | // emulation | ||
54 | void Fds_reset( struct Nes_Fds_Apu* this ); | ||
55 | |||
56 | static inline void Fds_volume( struct Nes_Fds_Apu* this, double v ) | ||
57 | { | ||
58 | Synth_volume( &this->synth, 0.14 / fds_master_vol_max / fds_vol_max / fds_wave_sample_max * v ); | ||
59 | } | ||
60 | |||
61 | static inline void Fds_set_output( struct Nes_Fds_Apu* this, int i, struct Blip_Buffer* b ) | ||
62 | { | ||
63 | #if defined(ROCKBOX) | ||
64 | (void) i; | ||
65 | #endif | ||
66 | |||
67 | assert( (unsigned) i < fds_osc_count ); | ||
68 | this->output_ = b; | ||
69 | } | ||
70 | |||
71 | void Fds_run_until( struct Nes_Fds_Apu* this, blip_time_t ) ICODE_ATTR; | ||
72 | static inline void Fds_end_frame( struct Nes_Fds_Apu* this, blip_time_t end_time ) | ||
73 | { | ||
74 | if ( end_time > this->last_time ) | ||
75 | Fds_run_until( this, end_time ); | ||
76 | this->last_time -= end_time; | ||
77 | assert( this->last_time >= 0 ); | ||
78 | } | ||
79 | |||
80 | void Fds_write_( struct Nes_Fds_Apu* this, unsigned addr, int data ) ICODE_ATTR; | ||
81 | static inline void Fds_write( struct Nes_Fds_Apu* this, blip_time_t time, unsigned addr, int data ) | ||
82 | { | ||
83 | Fds_run_until( this, time ); | ||
84 | Fds_write_( this, addr, data ); | ||
85 | } | ||
86 | |||
87 | static inline int Fds_read( struct Nes_Fds_Apu* this, blip_time_t time, unsigned addr ) | ||
88 | { | ||
89 | Fds_run_until( this, time ); | ||
90 | |||
91 | int result = 0xFF; | ||
92 | switch ( addr ) | ||
93 | { | ||
94 | case 0x4090: | ||
95 | result = this->env_gain; | ||
96 | break; | ||
97 | |||
98 | case 0x4092: | ||
99 | result = this->sweep_gain; | ||
100 | break; | ||
101 | |||
102 | default: | ||
103 | { | ||
104 | unsigned i = addr - fds_io_addr; | ||
105 | if ( i < fds_wave_size ) | ||
106 | result = this->regs_ [i]; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | return result | 0x40; | ||
111 | } | ||
112 | |||
113 | // allow access to registers by absolute address (i.e. 0x4080) | ||
114 | static inline unsigned char* regs_nes( struct Nes_Fds_Apu* this, unsigned addr ) { return &this->regs_ [addr - fds_io_addr]; } | ||
115 | |||
116 | #endif | ||