/gme/Vgm_Emu.cpp

http://game-music-emu.googlecode.com/ · C++ · 416 lines · 319 code · 75 blank · 22 comment · 49 complexity · 3e815abaed6c5a4563dc08baccadc0a8 MD5 · raw file

  1. // Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
  2. #include "Vgm_Emu.h"
  3. #include "blargg_endian.h"
  4. #include <string.h>
  5. #include <math.h>
  6. /* Copyright (C) 2003-2006 Shay Green. This module is free software; you
  7. can redistribute it and/or modify it under the terms of the GNU Lesser
  8. General Public License as published by the Free Software Foundation; either
  9. version 2.1 of the License, or (at your option) any later version. This
  10. module is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  13. details. You should have received a copy of the GNU Lesser General Public
  14. License along with this module; if not, write to the Free Software Foundation,
  15. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
  16. #include "blargg_source.h"
  17. double const fm_gain = 3.0; // FM emulators are internally quieter to avoid 16-bit overflow
  18. double const rolloff = 0.990;
  19. double const oversample_factor = 1.5;
  20. Vgm_Emu::Vgm_Emu()
  21. {
  22. disable_oversampling_ = false;
  23. psg_rate = 0;
  24. set_type( gme_vgm_type );
  25. static int const types [8] = {
  26. wave_type | 1, wave_type | 0, wave_type | 2, noise_type | 0
  27. };
  28. set_voice_types( types );
  29. set_silence_lookahead( 1 ); // tracks should already be trimmed
  30. static equalizer_t const eq = { -14.0, 80 };
  31. set_equalizer( eq );
  32. }
  33. Vgm_Emu::~Vgm_Emu() { }
  34. // Track info
  35. static byte const* skip_gd3_str( byte const* in, byte const* end )
  36. {
  37. while ( end - in >= 2 )
  38. {
  39. in += 2;
  40. if ( !(in [-2] | in [-1]) )
  41. break;
  42. }
  43. return in;
  44. }
  45. static byte const* get_gd3_str( byte const* in, byte const* end, char* field )
  46. {
  47. byte const* mid = skip_gd3_str( in, end );
  48. int len = (mid - in) / 2 - 1;
  49. if ( len > 0 )
  50. {
  51. len = min( len, (int) Gme_File::max_field_ );
  52. field [len] = 0;
  53. for ( int i = 0; i < len; i++ )
  54. field [i] = (in [i * 2 + 1] ? '?' : in [i * 2]); // TODO: convert to utf-8
  55. }
  56. return mid;
  57. }
  58. static byte const* get_gd3_pair( byte const* in, byte const* end, char* field )
  59. {
  60. return skip_gd3_str( get_gd3_str( in, end, field ), end );
  61. }
  62. static void parse_gd3( byte const* in, byte const* end, track_info_t* out )
  63. {
  64. in = get_gd3_pair( in, end, out->song );
  65. in = get_gd3_pair( in, end, out->game );
  66. in = get_gd3_pair( in, end, out->system );
  67. in = get_gd3_pair( in, end, out->author );
  68. in = get_gd3_str ( in, end, out->copyright );
  69. in = get_gd3_pair( in, end, out->dumper );
  70. in = get_gd3_str ( in, end, out->comment );
  71. }
  72. int const gd3_header_size = 12;
  73. static long check_gd3_header( byte const* h, long remain )
  74. {
  75. if ( remain < gd3_header_size ) return 0;
  76. if ( memcmp( h, "Gd3 ", 4 ) ) return 0;
  77. if ( get_le32( h + 4 ) >= 0x200 ) return 0;
  78. long gd3_size = get_le32( h + 8 );
  79. if ( gd3_size > remain - gd3_header_size ) return 0;
  80. return gd3_size;
  81. }
  82. byte const* Vgm_Emu::gd3_data( int* size ) const
  83. {
  84. if ( size )
  85. *size = 0;
  86. long gd3_offset = get_le32( header().gd3_offset ) - 0x2C;
  87. if ( gd3_offset < 0 )
  88. return 0;
  89. byte const* gd3 = data + header_size + gd3_offset;
  90. long gd3_size = check_gd3_header( gd3, data_end - gd3 );
  91. if ( !gd3_size )
  92. return 0;
  93. if ( size )
  94. *size = gd3_size + gd3_header_size;
  95. return gd3;
  96. }
  97. static void get_vgm_length( Vgm_Emu::header_t const& h, track_info_t* out )
  98. {
  99. long length = get_le32( h.track_duration ) * 10 / 441;
  100. if ( length > 0 )
  101. {
  102. long loop = get_le32( h.loop_duration );
  103. if ( loop > 0 && get_le32( h.loop_offset ) )
  104. {
  105. out->loop_length = loop * 10 / 441;
  106. out->intro_length = length - out->loop_length;
  107. }
  108. else
  109. {
  110. out->length = length; // 1000 / 44100 (VGM files used 44100 as timebase)
  111. out->intro_length = length; // make it clear that track is no longer than length
  112. out->loop_length = 0;
  113. }
  114. }
  115. }
  116. blargg_err_t Vgm_Emu::track_info_( track_info_t* out, int ) const
  117. {
  118. get_vgm_length( header(), out );
  119. int size;
  120. byte const* gd3 = gd3_data( &size );
  121. if ( gd3 )
  122. parse_gd3( gd3 + gd3_header_size, gd3 + size, out );
  123. return 0;
  124. }
  125. static blargg_err_t check_vgm_header( Vgm_Emu::header_t const& h )
  126. {
  127. if ( memcmp( h.tag, "Vgm ", 4 ) )
  128. return gme_wrong_file_type;
  129. return 0;
  130. }
  131. struct Vgm_File : Gme_Info_
  132. {
  133. Vgm_Emu::header_t h;
  134. blargg_vector<byte> gd3;
  135. Vgm_File() { set_type( gme_vgm_type ); }
  136. blargg_err_t load_( Data_Reader& in )
  137. {
  138. long file_size = in.remain();
  139. if ( file_size <= Vgm_Emu::header_size )
  140. return gme_wrong_file_type;
  141. RETURN_ERR( in.read( &h, Vgm_Emu::header_size ) );
  142. RETURN_ERR( check_vgm_header( h ) );
  143. long gd3_offset = get_le32( h.gd3_offset ) - 0x2C;
  144. long remain = file_size - Vgm_Emu::header_size - gd3_offset;
  145. byte gd3_h [gd3_header_size];
  146. if ( gd3_offset > 0 && remain >= gd3_header_size )
  147. {
  148. RETURN_ERR( in.skip( gd3_offset ) );
  149. RETURN_ERR( in.read( gd3_h, sizeof gd3_h ) );
  150. long gd3_size = check_gd3_header( gd3_h, remain );
  151. if ( gd3_size )
  152. {
  153. RETURN_ERR( gd3.resize( gd3_size ) );
  154. RETURN_ERR( in.read( gd3.begin(), gd3.size() ) );
  155. }
  156. }
  157. return 0;
  158. }
  159. blargg_err_t track_info_( track_info_t* out, int ) const
  160. {
  161. get_vgm_length( h, out );
  162. if ( gd3.size() )
  163. parse_gd3( gd3.begin(), gd3.end(), out );
  164. return 0;
  165. }
  166. };
  167. static Music_Emu* new_vgm_emu () { return BLARGG_NEW Vgm_Emu ; }
  168. static Music_Emu* new_vgm_file() { return BLARGG_NEW Vgm_File; }
  169. static gme_type_t_ const gme_vgm_type_ = { "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGM", 1 };
  170. gme_type_t const gme_vgm_type = &gme_vgm_type_;
  171. static gme_type_t_ const gme_vgz_type_ = { "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGZ", 1 };
  172. gme_type_t const gme_vgz_type = &gme_vgz_type_;
  173. // Setup
  174. void Vgm_Emu::set_tempo_( double t )
  175. {
  176. if ( psg_rate )
  177. {
  178. vgm_rate = (long) (44100 * t + 0.5);
  179. blip_time_factor = (long) floor( double (1L << blip_time_bits) / vgm_rate * psg_rate + 0.5 );
  180. //debug_printf( "blip_time_factor: %ld\n", blip_time_factor );
  181. //debug_printf( "vgm_rate: %ld\n", vgm_rate );
  182. // TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only)
  183. //blip_time_factor = (long) floor( double (1L << blip_time_bits) * psg_rate / 44100 / t + 0.5 );
  184. //vgm_rate = (long) floor( double (1L << blip_time_bits) * psg_rate / blip_time_factor + 0.5 );
  185. fm_time_factor = 2 + (long) floor( fm_rate * (1L << fm_time_bits) / vgm_rate + 0.5 );
  186. }
  187. }
  188. blargg_err_t Vgm_Emu::set_sample_rate_( long sample_rate )
  189. {
  190. RETURN_ERR( blip_buf.set_sample_rate( sample_rate, 1000 / 30 ) );
  191. return Classic_Emu::set_sample_rate_( sample_rate );
  192. }
  193. void Vgm_Emu::update_eq( blip_eq_t const& eq )
  194. {
  195. psg.treble_eq( eq );
  196. dac_synth.treble_eq( eq );
  197. }
  198. void Vgm_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
  199. {
  200. if ( i < psg.osc_count )
  201. psg.osc_output( i, c, l, r );
  202. }
  203. void Vgm_Emu::mute_voices_( int mask )
  204. {
  205. Classic_Emu::mute_voices_( mask );
  206. dac_synth.output( &blip_buf );
  207. if ( uses_fm )
  208. {
  209. psg.output( (mask & 0x80) ? 0 : &blip_buf );
  210. if ( ym2612.enabled() )
  211. {
  212. dac_synth.volume( (mask & 0x40) ? 0.0 : 0.1115 / 256 * fm_gain * gain() );
  213. ym2612.mute_voices( mask );
  214. }
  215. if ( ym2413.enabled() )
  216. {
  217. int m = mask & 0x3F;
  218. if ( mask & 0x20 )
  219. m |= 0x01E0; // channels 5-8
  220. if ( mask & 0x40 )
  221. m |= 0x3E00;
  222. ym2413.mute_voices( m );
  223. }
  224. }
  225. }
  226. blargg_err_t Vgm_Emu::load_mem_( byte const* new_data, long new_size )
  227. {
  228. assert( offsetof (header_t,unused2 [8]) == header_size );
  229. if ( new_size <= header_size )
  230. return gme_wrong_file_type;
  231. header_t const& h = *(header_t const*) new_data;
  232. RETURN_ERR( check_vgm_header( h ) );
  233. check( get_le32( h.version ) <= 0x150 );
  234. // psg rate
  235. psg_rate = get_le32( h.psg_rate );
  236. if ( !psg_rate )
  237. psg_rate = 3579545;
  238. blip_buf.clock_rate( psg_rate );
  239. data = new_data;
  240. data_end = new_data + new_size;
  241. // get loop
  242. loop_begin = data_end;
  243. if ( get_le32( h.loop_offset ) )
  244. loop_begin = &data [get_le32( h.loop_offset ) + offsetof (header_t,loop_offset)];
  245. set_voice_count( psg.osc_count );
  246. RETURN_ERR( setup_fm() );
  247. static const char* const fm_names [] = {
  248. "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
  249. };
  250. static const char* const psg_names [] = { "Square 1", "Square 2", "Square 3", "Noise" };
  251. set_voice_names( uses_fm ? fm_names : psg_names );
  252. // do after FM in case output buffer is changed
  253. return Classic_Emu::setup_buffer( psg_rate );
  254. }
  255. blargg_err_t Vgm_Emu::setup_fm()
  256. {
  257. long ym2612_rate = get_le32( header().ym2612_rate );
  258. long ym2413_rate = get_le32( header().ym2413_rate );
  259. if ( ym2413_rate && get_le32( header().version ) < 0x110 )
  260. update_fm_rates( &ym2413_rate, &ym2612_rate );
  261. uses_fm = false;
  262. fm_rate = blip_buf.sample_rate() * oversample_factor;
  263. if ( ym2612_rate )
  264. {
  265. uses_fm = true;
  266. if ( disable_oversampling_ )
  267. fm_rate = ym2612_rate / 144.0;
  268. Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() );
  269. RETURN_ERR( ym2612.set_rate( fm_rate, ym2612_rate ) );
  270. ym2612.enable( true );
  271. set_voice_count( 8 );
  272. }
  273. if ( !uses_fm && ym2413_rate )
  274. {
  275. uses_fm = true;
  276. if ( disable_oversampling_ )
  277. fm_rate = ym2413_rate / 72.0;
  278. Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() );
  279. int result = ym2413.set_rate( fm_rate, ym2413_rate );
  280. if ( result == 2 )
  281. return "YM2413 FM sound isn't supported";
  282. CHECK_ALLOC( !result );
  283. ym2413.enable( true );
  284. set_voice_count( 8 );
  285. }
  286. if ( uses_fm )
  287. {
  288. RETURN_ERR( Dual_Resampler::reset( blip_buf.length() * blip_buf.sample_rate() / 1000 ) );
  289. psg.volume( 0.135 * fm_gain * gain() );
  290. }
  291. else
  292. {
  293. ym2612.enable( false );
  294. ym2413.enable( false );
  295. psg.volume( gain() );
  296. }
  297. return 0;
  298. }
  299. // Emulation
  300. blargg_err_t Vgm_Emu::start_track_( int track )
  301. {
  302. RETURN_ERR( Classic_Emu::start_track_( track ) );
  303. psg.reset( get_le16( header().noise_feedback ), header().noise_width );
  304. dac_disabled = -1;
  305. pos = data + header_size;
  306. pcm_data = pos;
  307. pcm_pos = pos;
  308. dac_amp = -1;
  309. vgm_time = 0;
  310. if ( get_le32( header().version ) >= 0x150 )
  311. {
  312. long data_offset = get_le32( header().data_offset );
  313. check( data_offset );
  314. if ( data_offset )
  315. pos += data_offset + offsetof (header_t,data_offset) - 0x40;
  316. }
  317. if ( uses_fm )
  318. {
  319. if ( ym2413.enabled() )
  320. ym2413.reset();
  321. if ( ym2612.enabled() )
  322. ym2612.reset();
  323. fm_time_offset = 0;
  324. blip_buf.clear();
  325. Dual_Resampler::clear();
  326. }
  327. return 0;
  328. }
  329. blargg_err_t Vgm_Emu::run_clocks( blip_time_t& time_io, int msec )
  330. {
  331. time_io = run_commands( msec * vgm_rate / 1000 );
  332. psg.end_frame( time_io );
  333. return 0;
  334. }
  335. blargg_err_t Vgm_Emu::play_( long count, sample_t* out )
  336. {
  337. if ( !uses_fm )
  338. return Classic_Emu::play_( count, out );
  339. Dual_Resampler::dual_play( count, out, blip_buf );
  340. return 0;
  341. }