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/hes_emu.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/hes_emu.h')
-rw-r--r-- | apps/codecs/libgme/hes_emu.h | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/apps/codecs/libgme/hes_emu.h b/apps/codecs/libgme/hes_emu.h new file mode 100644 index 0000000000..18dbe0d506 --- /dev/null +++ b/apps/codecs/libgme/hes_emu.h | |||
@@ -0,0 +1,229 @@ | |||
1 | // TurboGrafx-16/PC Engine HES music file emulator | ||
2 | |||
3 | // Game_Music_Emu 0.5.2 | ||
4 | #ifndef HES_EMU_H | ||
5 | #define HES_EMU_H | ||
6 | |||
7 | #include "blargg_source.h" | ||
8 | |||
9 | #include "multi_buffer.h" | ||
10 | #include "rom_data.h" | ||
11 | #include "hes_apu.h" | ||
12 | #include "hes_apu_adpcm.h" | ||
13 | #include "hes_cpu.h" | ||
14 | #include "m3u_playlist.h" | ||
15 | |||
16 | typedef short sample_t; | ||
17 | |||
18 | enum { buf_size = 2048 }; | ||
19 | |||
20 | // HES file header | ||
21 | enum { header_size = 0x20 }; | ||
22 | struct header_t | ||
23 | { | ||
24 | byte tag [4]; | ||
25 | byte vers; | ||
26 | byte first_track; | ||
27 | byte init_addr [2]; | ||
28 | byte banks [8]; | ||
29 | byte data_tag [4]; | ||
30 | byte size [4]; | ||
31 | byte addr [4]; | ||
32 | byte unused [4]; | ||
33 | }; | ||
34 | |||
35 | |||
36 | struct timer_t { | ||
37 | hes_time_t last_time; | ||
38 | blargg_long count; | ||
39 | blargg_long load; | ||
40 | int raw_load; | ||
41 | byte enabled; | ||
42 | byte fired; | ||
43 | }; | ||
44 | |||
45 | struct vdp_t { | ||
46 | hes_time_t next_vbl; | ||
47 | byte latch; | ||
48 | byte control; | ||
49 | }; | ||
50 | |||
51 | struct irq_t { | ||
52 | hes_time_t timer; | ||
53 | hes_time_t vdp; | ||
54 | byte disables; | ||
55 | }; | ||
56 | |||
57 | |||
58 | struct Hes_Emu { | ||
59 | hes_time_t play_period; | ||
60 | hes_time_t last_frame_hook; | ||
61 | int timer_base; | ||
62 | |||
63 | struct timer_t timer; | ||
64 | struct vdp_t vdp; | ||
65 | struct irq_t irq; | ||
66 | |||
67 | // Sound | ||
68 | long clock_rate_; | ||
69 | long sample_rate_; | ||
70 | unsigned buf_changed_count; | ||
71 | int voice_count_; | ||
72 | double tempo_; | ||
73 | double gain_; | ||
74 | |||
75 | // track-specific | ||
76 | byte track_count; | ||
77 | volatile bool track_ended; | ||
78 | int current_track_; | ||
79 | blargg_long out_time; // number of samples played since start of track | ||
80 | blargg_long emu_time; // number of samples emulator has generated since start of track | ||
81 | bool emu_track_ended_; // emulator has reached end of track | ||
82 | |||
83 | // fading | ||
84 | blargg_long fade_start; | ||
85 | int fade_step; | ||
86 | |||
87 | // silence detection | ||
88 | // Disable automatic end-of-track detection and skipping of silence at beginning | ||
89 | bool ignore_silence; | ||
90 | |||
91 | int max_initial_silence; | ||
92 | int mute_mask_; | ||
93 | int silence_lookahead; // speed to run emulator when looking ahead for silence | ||
94 | long silence_time; // number of samples where most recent silence began | ||
95 | long silence_count; // number of samples of silence to play before using buf | ||
96 | long buf_remain; // number of samples left in silence buffer | ||
97 | |||
98 | // Larger files at the end | ||
99 | // Header for currently loaded file | ||
100 | struct header_t header; | ||
101 | |||
102 | // M3u Playlist | ||
103 | struct M3u_Playlist m3u; | ||
104 | |||
105 | // Hes Cpu | ||
106 | byte* write_pages [page_count + 1]; // 0 if unmapped or I/O space | ||
107 | struct Hes_Cpu cpu; | ||
108 | |||
109 | struct Hes_Apu apu; | ||
110 | struct Hes_Apu_Adpcm adpcm; | ||
111 | |||
112 | struct Stereo_Buffer stereo_buf; | ||
113 | sample_t buf [buf_size]; | ||
114 | |||
115 | // rom & ram | ||
116 | struct Rom_Data rom; | ||
117 | byte sgx [3 * page_size + cpu_padding]; | ||
118 | }; | ||
119 | |||
120 | |||
121 | // Basic functionality | ||
122 | // Initializes Hes_Emu structure | ||
123 | void Hes_init( struct Hes_Emu* this ); | ||
124 | |||
125 | // Stops (clear) Hes_Emu structure | ||
126 | void Hes_stop( struct Hes_Emu* this ); | ||
127 | |||
128 | // Loads a file from memory | ||
129 | blargg_err_t Hes_load( struct Hes_Emu* this, void* data, long size ); | ||
130 | |||
131 | // Set output sample rate. Must be called only once before loading file. | ||
132 | blargg_err_t Hes_set_sample_rate( struct Hes_Emu* this, long sample_rate ); | ||
133 | |||
134 | // Start a track, where 0 is the first track. Also clears warning string. | ||
135 | blargg_err_t Hes_start_track( struct Hes_Emu* this, int ); | ||
136 | |||
137 | // Generate 'count' samples info 'buf'. Output is in stereo. Any emulation | ||
138 | // errors set warning string, and major errors also end track. | ||
139 | blargg_err_t Hes_play( struct Hes_Emu* this, long count, sample_t* buf ) ICODE_ATTR; | ||
140 | |||
141 | // Track status/control | ||
142 | // Number of milliseconds (1000 msec = 1 second) played since ning of track | ||
143 | long Track_tell( struct Hes_Emu* this ); | ||
144 | |||
145 | // Seek to new time in track. Seeking backwards or far forward can take a while. | ||
146 | blargg_err_t Track_seek( struct Hes_Emu* this, long msec ); | ||
147 | |||
148 | // Skip n samples | ||
149 | blargg_err_t Track_skip( struct Hes_Emu* this, long n ); | ||
150 | |||
151 | // Set start time and length of track fade out. Once fade ends track_ended() returns | ||
152 | // true. Fade time can be changed while track is playing. | ||
153 | void Track_set_fade( struct Hes_Emu* this, long start_msec, long length_msec ); | ||
154 | |||
155 | // Get track length in milliseconds | ||
156 | static inline long Track_get_length( struct Hes_Emu* this, int n ) | ||
157 | { | ||
158 | long length = 120 * 1000; /* 2 minutes */ | ||
159 | if ( (this->m3u.size > 0) && (n < this->m3u.size) ) { | ||
160 | struct entry_t* entry = &this->m3u.entries [n]; | ||
161 | length = entry->length; | ||
162 | } | ||
163 | |||
164 | return length; | ||
165 | } | ||
166 | |||
167 | |||
168 | // Sound customization | ||
169 | // Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed. | ||
170 | // Track length as returned by track_info() assumes a tempo of 1.0. | ||
171 | void Sound_set_tempo( struct Hes_Emu* this, double ); | ||
172 | |||
173 | // Mute/unmute voice i, where voice 0 is first voice | ||
174 | void Sound_mute_voice( struct Hes_Emu* this, int index, bool mute ); | ||
175 | |||
176 | // Set muting state of all voices at once using a bit mask, where -1 mutes them all, | ||
177 | // 0 unmutes them all, 0x01 mutes just the first voice, etc. | ||
178 | void Sound_mute_voices( struct Hes_Emu* this, int mask ); | ||
179 | |||
180 | // Change overall output amplitude, where 1.0 results in minimal clamping. | ||
181 | // Must be called before set_sample_rate(). | ||
182 | static inline void Sound_set_gain( struct Hes_Emu* this, double g ) | ||
183 | { | ||
184 | assert( !this->sample_rate_ ); // you must set gain before setting sample rate | ||
185 | this->gain_ = g; | ||
186 | } | ||
187 | |||
188 | |||
189 | // Emulation (You shouldn't touch these) | ||
190 | |||
191 | int Cpu_read( struct Hes_Emu* this, hes_addr_t ) ICODE_ATTR; | ||
192 | void Cpu_write( struct Hes_Emu* this, hes_addr_t, int ) ICODE_ATTR; | ||
193 | void Cpu_write_vdp( struct Hes_Emu* this, int addr, int data ) ICODE_ATTR; | ||
194 | int Cpu_done( struct Hes_Emu* this ) ICODE_ATTR; | ||
195 | |||
196 | int Emu_cpu_read( struct Hes_Emu* this, hes_addr_t ) ICODE_ATTR; | ||
197 | void Emu_cpu_write( struct Hes_Emu* this, hes_addr_t, int data ) ICODE_ATTR; | ||
198 | |||
199 | static inline byte const* Emu_cpu_set_mmr( struct Hes_Emu* this, int page, int bank ) | ||
200 | { | ||
201 | this->write_pages [page] = 0; | ||
202 | if ( bank < 0x80 ) | ||
203 | return Rom_at_addr( &this->rom, bank * (blargg_long) page_size ); | ||
204 | |||
205 | byte* data = 0; | ||
206 | switch ( bank ) | ||
207 | { | ||
208 | case 0xF8: | ||
209 | data = this->cpu.ram; | ||
210 | break; | ||
211 | |||
212 | case 0xF9: | ||
213 | case 0xFA: | ||
214 | case 0xFB: | ||
215 | data = &this->sgx [(bank - 0xF9) * page_size]; | ||
216 | break; | ||
217 | |||
218 | default: | ||
219 | if ( bank != 0xFF ) { | ||
220 | dprintf( "Unmapped bank $%02X\n", bank ); | ||
221 | } | ||
222 | return this->rom.unmapped; | ||
223 | } | ||
224 | |||
225 | this->write_pages [page] = data; | ||
226 | return data; | ||
227 | } | ||
228 | |||
229 | #endif | ||