diff options
Diffstat (limited to 'apps/codecs/libgme/kss_emu.h')
-rw-r--r-- | apps/codecs/libgme/kss_emu.h | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/apps/codecs/libgme/kss_emu.h b/apps/codecs/libgme/kss_emu.h new file mode 100644 index 0000000000..81db2ae708 --- /dev/null +++ b/apps/codecs/libgme/kss_emu.h | |||
@@ -0,0 +1,228 @@ | |||
1 | // MSX computer KSS music file emulator | ||
2 | |||
3 | // Game_Music_Emu 0.5.5 | ||
4 | #ifndef KSS_EMU_H | ||
5 | #define KSS_EMU_H | ||
6 | |||
7 | #include "gme.h" | ||
8 | #include "blargg_common.h" | ||
9 | |||
10 | #include "rom_data.h" | ||
11 | #include "multi_buffer.h" | ||
12 | |||
13 | #include "kss_scc_apu.h" | ||
14 | #include "z80_cpu.h" | ||
15 | #include "sms_apu.h" | ||
16 | #include "ay_apu.h" | ||
17 | #include "opl_apu.h" | ||
18 | #include "m3u_playlist.h" | ||
19 | |||
20 | typedef short sample_t; | ||
21 | typedef int kss_time_t; | ||
22 | typedef int kss_addr_t; | ||
23 | typedef struct Z80_Cpu Kss_Cpu; | ||
24 | |||
25 | // Sound chip flags | ||
26 | enum { | ||
27 | sms_psg_flag = 1 << 0, | ||
28 | sms_fm_flag = 1 << 1, | ||
29 | msx_psg_flag = 1 << 2, | ||
30 | msx_scc_flag = 1 << 3, | ||
31 | msx_music_flag = 1 << 4, | ||
32 | msx_audio_flag = 1 << 5 | ||
33 | }; | ||
34 | |||
35 | enum { idle_addr = 0xFFFF }; | ||
36 | enum { scc_enabled_true = 0xC000 }; | ||
37 | enum { mem_size = 0x10000 }; | ||
38 | enum { buf_size = 2048 }; | ||
39 | |||
40 | // KSS file header | ||
41 | enum { header_size = 0x20 }; | ||
42 | enum { header_base_size = 0x10 }; | ||
43 | enum { header_ext_size = header_size - header_base_size }; | ||
44 | |||
45 | struct header_t | ||
46 | { | ||
47 | byte tag [4]; | ||
48 | byte load_addr [2]; | ||
49 | byte load_size [2]; | ||
50 | byte init_addr [2]; | ||
51 | byte play_addr [2]; | ||
52 | byte first_bank; | ||
53 | byte bank_mode; | ||
54 | byte extra_header; | ||
55 | byte device_flags; | ||
56 | |||
57 | // KSSX extended data, if extra_header==0x10 | ||
58 | byte data_size [4]; | ||
59 | byte unused [4]; | ||
60 | byte first_track [2]; | ||
61 | byte last_track [2]; // if no extended data, we set this to 0xFF | ||
62 | byte psg_vol; | ||
63 | byte scc_vol; | ||
64 | byte msx_music_vol; | ||
65 | byte msx_audio_vol; | ||
66 | }; | ||
67 | |||
68 | struct sms_t { | ||
69 | struct Sms_Apu psg; | ||
70 | struct Opl_Apu fm; | ||
71 | }; | ||
72 | |||
73 | struct msx_t { | ||
74 | struct Ay_Apu psg; | ||
75 | struct Scc_Apu scc; | ||
76 | struct Opl_Apu music; | ||
77 | struct Opl_Apu audio; | ||
78 | }; | ||
79 | |||
80 | struct Kss_Emu { | ||
81 | struct header_t header; | ||
82 | |||
83 | int chip_flags; | ||
84 | bool scc_accessed; | ||
85 | bool gain_updated; | ||
86 | |||
87 | int track_count; | ||
88 | |||
89 | unsigned scc_enabled; // 0 or 0xC000 | ||
90 | int bank_count; | ||
91 | |||
92 | blip_time_t play_period; | ||
93 | blip_time_t next_play; | ||
94 | int ay_latch; | ||
95 | |||
96 | // general | ||
97 | int max_initial_silence; | ||
98 | int voice_count; | ||
99 | int mute_mask_; | ||
100 | double tempo; | ||
101 | double gain; | ||
102 | |||
103 | long sample_rate; | ||
104 | |||
105 | // track-specific | ||
106 | int current_track; | ||
107 | blargg_long out_time; // number of samples played since start of track | ||
108 | blargg_long emu_time; // number of samples emulator has generated since start of track | ||
109 | bool emu_track_ended_; // emulator has reached end of track | ||
110 | volatile bool track_ended; | ||
111 | |||
112 | // fading | ||
113 | blargg_long fade_start; | ||
114 | int fade_step; | ||
115 | |||
116 | // silence detection | ||
117 | int silence_lookahead; // speed to run emulator when looking ahead for silence | ||
118 | bool ignore_silence; | ||
119 | long silence_time; // number of samples where most recent silence began | ||
120 | long silence_count; // number of samples of silence to play before using buf | ||
121 | long buf_remain; // number of samples left in silence buffer | ||
122 | |||
123 | struct Stereo_Buffer stereo_buffer; // NULL if using custom buffer | ||
124 | long clock_rate_; | ||
125 | unsigned buf_changed_count; | ||
126 | |||
127 | // M3u Playlist | ||
128 | struct M3u_Playlist m3u; | ||
129 | |||
130 | // large items | ||
131 | sample_t buf [buf_size]; | ||
132 | |||
133 | struct sms_t sms; | ||
134 | struct msx_t msx; | ||
135 | |||
136 | Kss_Cpu cpu; | ||
137 | struct Rom_Data rom; | ||
138 | |||
139 | byte unmapped_read [0x100]; | ||
140 | byte unmapped_write [page_size]; | ||
141 | byte ram [mem_size + cpu_padding]; | ||
142 | }; | ||
143 | |||
144 | // Basic functionality (see Gme_File.h for file loading/track info functions) | ||
145 | |||
146 | void Kss_init( struct Kss_Emu* this ); | ||
147 | blargg_err_t Kss_load_mem( struct Kss_Emu* this, const void* data, long size ); | ||
148 | blargg_err_t end_frame( struct Kss_Emu* this, kss_time_t ); | ||
149 | |||
150 | // Set output sample rate. Must be called only once before loading file. | ||
151 | blargg_err_t Kss_set_sample_rate( struct Kss_Emu* this, long sample_rate ); | ||
152 | |||
153 | // Start a track, where 0 is the first track. Also clears warning string. | ||
154 | blargg_err_t Kss_start_track( struct Kss_Emu* this, int track ); | ||
155 | |||
156 | // Generate 'count' samples info 'buf'. Output is in stereo. Any emulation | ||
157 | // errors set warning string, and major errors also end track. | ||
158 | blargg_err_t Kss_play( struct Kss_Emu* this, long count, sample_t* buf ) ICODE_ATTR; | ||
159 | |||
160 | // Track status/control | ||
161 | |||
162 | // Number of milliseconds (1000 msec = 1 second) played since beginning of track | ||
163 | long Track_tell( struct Kss_Emu* this ); | ||
164 | |||
165 | // Seek to new time in track. Seeking backwards or far forward can take a while. | ||
166 | blargg_err_t Track_seek( struct Kss_Emu* this, long msec ); | ||
167 | |||
168 | // Skip n samples | ||
169 | blargg_err_t Track_skip( struct Kss_Emu* this, long n ); | ||
170 | |||
171 | // Set start time and length of track fade out. Once fade ends track_ended() returns | ||
172 | // true. Fade time can be changed while track is playing. | ||
173 | void Track_set_fade( struct Kss_Emu* this, long start_msec, long length_msec ); | ||
174 | |||
175 | // Get track length in milliseconds | ||
176 | static inline long Track_get_length( struct Kss_Emu* this, int n ) | ||
177 | { | ||
178 | long length = 0; | ||
179 | |||
180 | if ( (this->m3u.size > 0) && (n < this->m3u.size) ) { | ||
181 | struct entry_t* entry = &this->m3u.entries [n]; | ||
182 | length = entry->length; | ||
183 | } | ||
184 | |||
185 | if ( length <= 0 ) | ||
186 | length = 120 * 1000; /* 2 minutes */ | ||
187 | |||
188 | return length; | ||
189 | } | ||
190 | |||
191 | // Sound customization | ||
192 | |||
193 | // Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed. | ||
194 | // Track length as returned by track_info() assumes a tempo of 1.0. | ||
195 | void Sound_set_tempo( struct Kss_Emu* this, double t ); | ||
196 | |||
197 | // Mute/unmute voice i, where voice 0 is first voice | ||
198 | void Sound_mute_voice( struct Kss_Emu* this, int index, bool mute ); | ||
199 | |||
200 | // Set muting state of all voices at once using a bit mask, where -1 mutes them all, | ||
201 | // 0 unmutes them all, 0x01 mutes just the first voice, etc. | ||
202 | void Sound_mute_voices( struct Kss_Emu* this, int mask ); | ||
203 | |||
204 | // Change overall output amplitude, where 1.0 results in minimal clamping. | ||
205 | // Must be called before set_sample_rate(). | ||
206 | static inline void Sound_set_gain( struct Kss_Emu* this, double g ) | ||
207 | { | ||
208 | assert( !this->sample_rate ); // you must set gain before setting sample rate | ||
209 | this->gain = g; | ||
210 | } | ||
211 | |||
212 | // Emulation (You shouldn't touch these | ||
213 | void cpu_write( struct Kss_Emu* this, kss_addr_t, int ) ICODE_ATTR; | ||
214 | int cpu_in( struct Kss_Emu* this, kss_time_t, kss_addr_t ) ICODE_ATTR; | ||
215 | void cpu_out( struct Kss_Emu* this, kss_time_t, kss_addr_t, int ) ICODE_ATTR; | ||
216 | |||
217 | void cpu_write_( struct Kss_Emu* this, kss_addr_t addr, int data ) ICODE_ATTR; | ||
218 | bool run_cpu( struct Kss_Emu* this, kss_time_t end ) ICODE_ATTR; | ||
219 | void jsr( struct Kss_Emu* this, byte const addr [] ) ICODE_ATTR; | ||
220 | |||
221 | static inline int sms_psg_enabled( struct Kss_Emu* this ) { return this->chip_flags & sms_psg_flag; } | ||
222 | static inline int sms_fm_enabled( struct Kss_Emu* this ) { return this->chip_flags & sms_fm_flag; } | ||
223 | static inline int msx_psg_enabled( struct Kss_Emu* this ) { return this->chip_flags & msx_psg_flag; } | ||
224 | static inline int msx_scc_enabled( struct Kss_Emu* this ) { return this->chip_flags & msx_scc_flag; } | ||
225 | static inline int msx_music_enabled( struct Kss_Emu* this ) { return this->chip_flags & msx_music_flag;} | ||
226 | static inline int msx_audio_enabled( struct Kss_Emu* this ) { return this->chip_flags & msx_audio_flag;} | ||
227 | |||
228 | #endif | ||