mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 06:42:08 +00:00
GME update with bug-fixes
- True fix for infinite loops [please verify!] - True fix for KSS silence - Fix for HES distorted and unstable/random tempo
This commit is contained in:
parent
7d73616fda
commit
1a070d12a1
7 changed files with 318 additions and 287 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
|||
// Game_Music_Emu 0.6.0. http://www.slack.net/~ant/
|
||||
// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
|
||||
|
||||
/*
|
||||
Last validated with zexall 2006.11.14 2:19 PM
|
||||
|
@ -162,11 +162,6 @@ static byte const ed_dd_timing [0x100] = {
|
|||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
|
||||
// even on x86, using short and unsigned char was slower
|
||||
typedef int fint16;
|
||||
typedef unsigned fuint16;
|
||||
typedef unsigned fuint8;
|
||||
|
||||
bool Kss_Cpu::run( cpu_time_t end_time )
|
||||
{
|
||||
set_end_time( end_time );
|
||||
|
@ -183,10 +178,10 @@ bool Kss_Cpu::run( cpu_time_t end_time )
|
|||
rg = this->r.b;
|
||||
|
||||
cpu_time_t s_time = s.time;
|
||||
fuint16 pc = r.pc;
|
||||
fuint16 sp = r.sp;
|
||||
fuint16 ix = r.ix; // TODO: keep in memory for direct access?
|
||||
fuint16 iy = r.iy;
|
||||
uint_fast32_t pc = r.pc;
|
||||
uint_fast32_t sp = r.sp;
|
||||
uint_fast32_t ix = r.ix; // TODO: keep in memory for direct access?
|
||||
uint_fast32_t iy = r.iy;
|
||||
int flags = r.b.flags;
|
||||
|
||||
goto loop;
|
||||
|
@ -208,7 +203,7 @@ loop:
|
|||
uint8_t const* instr = s.read [pc >> page_shift];
|
||||
#define GET_ADDR() GET_LE16( instr )
|
||||
|
||||
fuint8 opcode;
|
||||
uint_fast8_t opcode;
|
||||
|
||||
// TODO: eliminate this special case
|
||||
#if BLARGG_NONPORTABLE
|
||||
|
@ -241,7 +236,7 @@ loop:
|
|||
11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
|
||||
};
|
||||
|
||||
fuint16 data;
|
||||
uint_fast16_t data;
|
||||
data = base_timing [opcode];
|
||||
if ( (s_time += data) >= 0 )
|
||||
goto possibly_out_of_time;
|
||||
|
@ -297,7 +292,7 @@ possibly_out_of_time:
|
|||
goto loop;
|
||||
|
||||
case 0x3A:{// LD A,(addr)
|
||||
fuint16 addr = GET_ADDR();
|
||||
uint_fast16_t addr = GET_ADDR();
|
||||
pc += 2;
|
||||
rg.a = READ( addr );
|
||||
goto loop;
|
||||
|
@ -385,7 +380,7 @@ possibly_out_of_time:
|
|||
|
||||
case 0xCD:{// CALL addr
|
||||
call_taken:
|
||||
fuint16 addr = pc + 2;
|
||||
uint_fast16_t addr = pc + 2;
|
||||
pc = GET_ADDR();
|
||||
sp = uint16_t (sp - 2);
|
||||
WRITE_WORD( sp, addr );
|
||||
|
@ -501,7 +496,7 @@ possibly_out_of_time:
|
|||
add_hl_data: {
|
||||
blargg_ulong sum = rp.hl + data;
|
||||
data ^= rp.hl;
|
||||
rp.hl = (uint16_t)sum;
|
||||
rp.hl = sum;
|
||||
flags = (flags & (S80 | Z40 | V04)) |
|
||||
(sum >> 16) |
|
||||
(sum >> 8 & (F20 | F08)) |
|
||||
|
@ -691,21 +686,21 @@ possibly_out_of_time:
|
|||
goto loop;
|
||||
|
||||
case 0x2A:{// LD HL,(addr)
|
||||
fuint16 addr = GET_ADDR();
|
||||
uint_fast16_t addr = GET_ADDR();
|
||||
pc += 2;
|
||||
rp.hl = READ_WORD( addr );
|
||||
goto loop;
|
||||
}
|
||||
|
||||
case 0x32:{// LD (addr),A
|
||||
fuint16 addr = GET_ADDR();
|
||||
uint_fast16_t addr = GET_ADDR();
|
||||
pc += 2;
|
||||
WRITE( addr, rg.a );
|
||||
goto loop;
|
||||
}
|
||||
|
||||
case 0x22:{// LD (addr),HL
|
||||
fuint16 addr = GET_ADDR();
|
||||
uint_fast16_t addr = GET_ADDR();
|
||||
pc += 2;
|
||||
WRITE_WORD( addr, rp.hl );
|
||||
goto loop;
|
||||
|
@ -728,7 +723,7 @@ possibly_out_of_time:
|
|||
// Rotate
|
||||
|
||||
case 0x07:{// RLCA
|
||||
fuint16 temp = rg.a;
|
||||
uint_fast16_t temp = rg.a;
|
||||
temp = (temp << 1) | (temp >> 7);
|
||||
flags = (flags & (S80 | Z40 | P04)) |
|
||||
(temp & (F20 | F08 | C01));
|
||||
|
@ -737,7 +732,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
case 0x0F:{// RRCA
|
||||
fuint16 temp = rg.a;
|
||||
uint_fast16_t temp = rg.a;
|
||||
flags = (flags & (S80 | Z40 | P04)) |
|
||||
(temp & C01);
|
||||
temp = (temp << 7) | (temp >> 1);
|
||||
|
@ -756,7 +751,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
case 0x1F:{// RRA
|
||||
fuint16 temp = (flags << 7) | (rg.a >> 1);
|
||||
uint_fast16_t temp = (flags << 7) | (rg.a >> 1);
|
||||
flags = (flags & (S80 | Z40 | P04)) |
|
||||
(temp & (F20 | F08)) |
|
||||
(rg.a & C01);
|
||||
|
@ -766,7 +761,7 @@ possibly_out_of_time:
|
|||
|
||||
// Misc
|
||||
case 0x2F:{// CPL
|
||||
fuint16 temp = ~rg.a;
|
||||
uint_fast16_t temp = ~rg.a;
|
||||
flags = (flags & (S80 | Z40 | P04 | C01)) |
|
||||
(temp & (F20 | F08)) |
|
||||
(H10 | N02);
|
||||
|
@ -792,21 +787,21 @@ possibly_out_of_time:
|
|||
goto loop;
|
||||
|
||||
case 0xE3:{// EX (SP),HL
|
||||
fuint16 temp = READ_WORD( sp );
|
||||
uint_fast16_t temp = READ_WORD( sp );
|
||||
WRITE_WORD( sp, rp.hl );
|
||||
rp.hl = temp;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
case 0xEB:{// EX DE,HL
|
||||
fuint16 temp = rp.hl;
|
||||
uint_fast16_t temp = rp.hl;
|
||||
rp.hl = rp.de;
|
||||
rp.de = temp;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
case 0xD9:{// EXX DE,HL
|
||||
fuint16 temp = r.alt.w.bc;
|
||||
uint_fast16_t temp = r.alt.w.bc;
|
||||
r.alt.w.bc = rp.bc;
|
||||
rp.bc = temp;
|
||||
|
||||
|
@ -847,7 +842,7 @@ possibly_out_of_time:
|
|||
// Rotate left
|
||||
|
||||
#define RLC( read, write ) {\
|
||||
fuint8 result = read;\
|
||||
uint_fast8_t result = read;\
|
||||
result = uint8_t (result << 1) | (result >> 7);\
|
||||
flags = SZ28P( result ) | (result & C01);\
|
||||
write;\
|
||||
|
@ -866,7 +861,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
#define RL( read, write ) {\
|
||||
fuint16 result = (read << 1) | (flags & C01);\
|
||||
uint_fast16_t result = (read << 1) | (flags & C01);\
|
||||
flags = SZ28PC( result );\
|
||||
write;\
|
||||
goto loop;\
|
||||
|
@ -884,7 +879,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
#define SLA( read, add, write ) {\
|
||||
fuint16 result = (read << 1) | add;\
|
||||
uint_fast16_t result = (read << 1) | add;\
|
||||
flags = SZ28PC( result );\
|
||||
write;\
|
||||
goto loop;\
|
||||
|
@ -915,7 +910,7 @@ possibly_out_of_time:
|
|||
// Rotate right
|
||||
|
||||
#define RRC( read, write ) {\
|
||||
fuint8 result = read;\
|
||||
uint_fast8_t result = read;\
|
||||
flags = result & C01;\
|
||||
result = uint8_t (result << 7) | (result >> 1);\
|
||||
flags |= SZ28P( result );\
|
||||
|
@ -935,8 +930,8 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
#define RR( read, write ) {\
|
||||
fuint8 result = read;\
|
||||
fuint8 temp = result & C01;\
|
||||
uint_fast8_t result = read;\
|
||||
uint_fast8_t temp = result & C01;\
|
||||
result = uint8_t (flags << 7) | (result >> 1);\
|
||||
flags = SZ28P( result ) | temp;\
|
||||
write;\
|
||||
|
@ -955,7 +950,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
#define SRA( read, write ) {\
|
||||
fuint8 result = read;\
|
||||
uint_fast8_t result = read;\
|
||||
flags = result & C01;\
|
||||
result = (result & 0x80) | (result >> 1);\
|
||||
flags |= SZ28P( result );\
|
||||
|
@ -975,7 +970,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
#define SRL( read, write ) {\
|
||||
fuint8 result = read;\
|
||||
uint_fast8_t result = read;\
|
||||
flags = result & C01;\
|
||||
result >>= 1;\
|
||||
flags |= SZ28P( result );\
|
||||
|
@ -1083,7 +1078,7 @@ possibly_out_of_time:
|
|||
blargg_ulong sum = temp + (flags & C01);
|
||||
flags = ~data >> 2 & N02;
|
||||
if ( flags )
|
||||
sum = (blargg_ulong)-(blargg_long)sum;
|
||||
sum = -sum;
|
||||
sum += rp.hl;
|
||||
temp ^= rp.hl;
|
||||
temp ^= sum;
|
||||
|
@ -1091,7 +1086,7 @@ possibly_out_of_time:
|
|||
(temp >> 8 & H10) |
|
||||
(sum >> 8 & (S80 | F20 | F08)) |
|
||||
((temp - -0x8000) >> 14 & V04);
|
||||
rp.hl = (uint16_t)sum;
|
||||
rp.hl = sum;
|
||||
if ( (uint16_t) sum )
|
||||
goto loop;
|
||||
flags |= Z40;
|
||||
|
@ -1119,7 +1114,7 @@ possibly_out_of_time:
|
|||
case 0x43: // LD (ADDR),BC
|
||||
case 0x53: // LD (ADDR),DE
|
||||
temp = R16( data, 4, 0x43 );
|
||||
fuint16 addr = GET_ADDR();
|
||||
uint_fast16_t addr = GET_ADDR();
|
||||
pc += 2;
|
||||
WRITE_WORD( addr, temp );
|
||||
goto loop;
|
||||
|
@ -1127,21 +1122,21 @@ possibly_out_of_time:
|
|||
|
||||
case 0x4B: // LD BC,(ADDR)
|
||||
case 0x5B:{// LD DE,(ADDR)
|
||||
fuint16 addr = GET_ADDR();
|
||||
uint_fast16_t addr = GET_ADDR();
|
||||
pc += 2;
|
||||
R16( data, 4, 0x4B ) = READ_WORD( addr );
|
||||
goto loop;
|
||||
}
|
||||
|
||||
case 0x7B:{// LD SP,(ADDR)
|
||||
fuint16 addr = GET_ADDR();
|
||||
uint_fast16_t addr = GET_ADDR();
|
||||
pc += 2;
|
||||
sp = READ_WORD( addr );
|
||||
goto loop;
|
||||
}
|
||||
|
||||
case 0x67:{// RRD
|
||||
fuint8 temp = READ( rp.hl );
|
||||
uint_fast8_t temp = READ( rp.hl );
|
||||
WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
|
||||
temp = (rg.a & 0xF0) | (temp & 0x0F);
|
||||
flags = (flags & C01) | SZ28P( temp );
|
||||
|
@ -1150,7 +1145,7 @@ possibly_out_of_time:
|
|||
}
|
||||
|
||||
case 0x6F:{// RLD
|
||||
fuint8 temp = READ( rp.hl );
|
||||
uint_fast8_t temp = READ( rp.hl );
|
||||
WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
|
||||
temp = (rg.a & 0xF0) | (temp >> 4);
|
||||
flags = (flags & C01) | SZ28P( temp );
|
||||
|
@ -1174,7 +1169,7 @@ possibly_out_of_time:
|
|||
case 0xA1: // CPI
|
||||
case 0xB1: // CPIR
|
||||
inc = +1;
|
||||
fuint16 addr = rp.hl;
|
||||
uint_fast16_t addr = rp.hl;
|
||||
rp.hl = addr + inc;
|
||||
int temp = READ( addr );
|
||||
|
||||
|
@ -1207,7 +1202,7 @@ possibly_out_of_time:
|
|||
case 0xA0: // LDI
|
||||
case 0xB0: // LDIR
|
||||
inc = +1;
|
||||
fuint16 addr = rp.hl;
|
||||
uint_fast16_t addr = rp.hl;
|
||||
rp.hl = addr + inc;
|
||||
int temp = READ( addr );
|
||||
|
||||
|
@ -1239,7 +1234,7 @@ possibly_out_of_time:
|
|||
case 0xA3: // OUTI
|
||||
case 0xB3: // OTIR
|
||||
inc = +1;
|
||||
fuint16 addr = rp.hl;
|
||||
uint_fast16_t addr = rp.hl;
|
||||
rp.hl = addr + inc;
|
||||
int temp = READ( addr );
|
||||
|
||||
|
@ -1265,7 +1260,7 @@ possibly_out_of_time:
|
|||
case 0xB2: // INIR
|
||||
inc = +1;
|
||||
|
||||
fuint16 addr = rp.hl;
|
||||
uint_fast16_t addr = rp.hl;
|
||||
rp.hl = addr + inc;
|
||||
|
||||
int temp = IN( rp.bc );
|
||||
|
@ -1330,7 +1325,7 @@ possibly_out_of_time:
|
|||
|
||||
//////////////////////////////////////// DD/FD prefix
|
||||
{
|
||||
fuint16 ixy;
|
||||
uint_fast16_t ixy;
|
||||
case 0xDD:
|
||||
ixy = ix;
|
||||
goto ix_prefix;
|
||||
|
@ -1526,7 +1521,7 @@ possibly_out_of_time:
|
|||
goto loop;
|
||||
|
||||
case 0x22:{// LD (ADDR),IXY
|
||||
fuint16 addr = GET_ADDR();
|
||||
uint_fast16_t addr = GET_ADDR();
|
||||
pc += 2;
|
||||
WRITE_WORD( addr, ixy );
|
||||
goto loop;
|
||||
|
@ -1538,7 +1533,7 @@ possibly_out_of_time:
|
|||
goto set_ixy;
|
||||
|
||||
case 0x2A:{// LD IXY,(addr)
|
||||
fuint16 addr = GET_ADDR();
|
||||
uint_fast16_t addr = GET_ADDR();
|
||||
ixy = READ_WORD( addr );
|
||||
pc += 2;
|
||||
goto set_ixy;
|
||||
|
@ -1562,7 +1557,7 @@ possibly_out_of_time:
|
|||
case 0x3E: goto srl_data_addr; // SRL (IXY)
|
||||
|
||||
CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
|
||||
fuint8 temp = READ( data );
|
||||
uint_fast8_t temp = READ( data );
|
||||
int masked = temp & 1 << (data2 >> 3 & 7);
|
||||
flags = (flags & C01) | H10 |
|
||||
(masked & S80) |
|
||||
|
@ -1664,7 +1659,7 @@ possibly_out_of_time:
|
|||
goto loop;
|
||||
|
||||
case 0xE3:{// EX (SP),IXY
|
||||
fuint16 temp = READ_WORD( sp );
|
||||
uint_fast16_t temp = READ_WORD( sp );
|
||||
WRITE_WORD( sp, ixy );
|
||||
ixy = temp;
|
||||
goto set_ixy;
|
||||
|
|
|
@ -64,6 +64,8 @@ Music_Emu::Music_Emu()
|
|||
equalizer_.treble = -1.0;
|
||||
equalizer_.bass = 60;
|
||||
|
||||
emu_autoload_playback_limit_ = true;
|
||||
|
||||
static const char* const names [] = {
|
||||
"Voice 1", "Voice 2", "Voice 3", "Voice 4",
|
||||
"Voice 5", "Voice 6", "Voice 7", "Voice 8"
|
||||
|
@ -187,6 +189,16 @@ void Music_Emu::end_track_if_error( blargg_err_t err )
|
|||
}
|
||||
}
|
||||
|
||||
bool Music_Emu::autoload_playback_limit() const
|
||||
{
|
||||
return emu_autoload_playback_limit_;
|
||||
}
|
||||
|
||||
void Music_Emu::set_autoload_playback_limit( bool do_autoload_limit )
|
||||
{
|
||||
emu_autoload_playback_limit_ = do_autoload_limit;
|
||||
}
|
||||
|
||||
// Tell/Seek
|
||||
|
||||
blargg_long Music_Emu::msec_to_samples( blargg_long msec ) const
|
||||
|
|
|
@ -13,7 +13,7 @@ public:
|
|||
|
||||
// Set output sample rate. Must be called only once before loading file.
|
||||
blargg_err_t set_sample_rate( long sample_rate );
|
||||
|
||||
|
||||
// specifies if all 8 voices get rendered to their own stereo channel
|
||||
// default implementation of Music_Emu always returns not supported error (i.e. no multichannel support by default)
|
||||
// derived emus must override this if they support multichannel rendering
|
||||
|
@ -40,8 +40,8 @@ public:
|
|||
|
||||
// Names of voices
|
||||
const char** voice_names() const;
|
||||
|
||||
bool multi_channel() const;
|
||||
|
||||
bool multi_channel() const;
|
||||
|
||||
// Track status/control
|
||||
|
||||
|
@ -67,6 +67,13 @@ public:
|
|||
// true. Fade time can be changed while track is playing.
|
||||
void set_fade( long start_msec, long length_msec = 8000 );
|
||||
|
||||
// Controls whether or not to automatically load and obey track length
|
||||
// metadata for supported emulators.
|
||||
//
|
||||
// @since 0.6.2.
|
||||
bool autoload_playback_limit() const;
|
||||
void set_autoload_playback_limit( bool do_autoload_limit );
|
||||
|
||||
// Disable automatic end-of-track detection and skipping of silence at beginning
|
||||
void ignore_silence( bool disable = true );
|
||||
|
||||
|
@ -134,7 +141,7 @@ protected:
|
|||
double gain() const { return gain_; }
|
||||
double tempo() const { return tempo_; }
|
||||
void remute_voices();
|
||||
blargg_err_t set_multi_channel_( bool is_enabled );
|
||||
blargg_err_t set_multi_channel_( bool is_enabled );
|
||||
|
||||
virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0;
|
||||
virtual void set_equalizer_( equalizer_t const& ) { }
|
||||
|
@ -158,10 +165,10 @@ private:
|
|||
double tempo_;
|
||||
double gain_;
|
||||
bool multi_channel_;
|
||||
|
||||
|
||||
// returns the number of output channels, i.e. usually 2 for stereo, unlesss multi_channel_ == true
|
||||
int out_channels() const { return this->multi_channel() ? 2*8 : 2; }
|
||||
|
||||
|
||||
long sample_rate_;
|
||||
blargg_long msec_to_samples( blargg_long msec ) const;
|
||||
|
||||
|
@ -170,6 +177,7 @@ private:
|
|||
blargg_long out_time; // number of samples played since start of track
|
||||
blargg_long emu_time; // number of samples emulator has generated since start of track
|
||||
bool emu_track_ended_; // emulator has reached end of track
|
||||
bool emu_autoload_playback_limit_; // whether to load and obey track length by default
|
||||
volatile bool track_ended_;
|
||||
void clear_track_vars();
|
||||
void end_track_if_error( blargg_err_t );
|
||||
|
|
|
@ -299,6 +299,12 @@ blargg_err_t Spc_Emu::start_track_( int track )
|
|||
RETURN_ERR( apu.load_spc( file_data, file_size ) );
|
||||
filter.set_gain( (int) (gain() * SPC_Filter::gain_unit) );
|
||||
apu.clear_echo();
|
||||
track_info_t spc_info;
|
||||
RETURN_ERR( track_info_( &spc_info, track ) );
|
||||
|
||||
// Set a default track length, need a non-zero fadeout
|
||||
if ( autoload_playback_limit() && ( spc_info.length > 0 ) )
|
||||
set_fade ( spc_info.length, 50 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,10 +103,10 @@ BLARGG_EXPORT gme_type_t gme_identify_extension( const char* extension_ )
|
|||
char const* end = strrchr( extension_, '.' );
|
||||
if ( end )
|
||||
extension_ = end + 1;
|
||||
|
||||
|
||||
char extension [6];
|
||||
to_uppercase( extension_, sizeof extension, extension );
|
||||
|
||||
|
||||
for ( gme_type_t const* types = gme_type_list(); *types; types++ )
|
||||
if ( !strcmp( extension, (*types)->extension_ ) )
|
||||
return *types;
|
||||
|
@ -133,30 +133,30 @@ BLARGG_EXPORT gme_err_t gme_identify_file( const char* path, gme_type_t* type_ou
|
|||
RETURN_ERR( in.read( header, sizeof header ) );
|
||||
*type_out = gme_identify_extension( gme_identify_header( header ) );
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLARGG_EXPORT gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate )
|
||||
{
|
||||
require( (data || !size) && out );
|
||||
*out = 0;
|
||||
|
||||
|
||||
gme_type_t file_type = 0;
|
||||
if ( size >= 4 )
|
||||
file_type = gme_identify_extension( gme_identify_header( data ) );
|
||||
if ( !file_type )
|
||||
return gme_wrong_file_type;
|
||||
|
||||
|
||||
Music_Emu* emu = gme_new_emu( file_type, sample_rate );
|
||||
CHECK_ALLOC( emu );
|
||||
|
||||
|
||||
gme_err_t err = gme_load_data( emu, data, size );
|
||||
|
||||
|
||||
if ( err )
|
||||
delete emu;
|
||||
else
|
||||
*out = emu;
|
||||
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -164,13 +164,13 @@ BLARGG_EXPORT gme_err_t gme_open_file( const char* path, Music_Emu** out, int sa
|
|||
{
|
||||
require( path && out );
|
||||
*out = 0;
|
||||
|
||||
|
||||
GME_FILE_READER in;
|
||||
RETURN_ERR( in.open( path ) );
|
||||
|
||||
|
||||
char header [4];
|
||||
int header_size = 0;
|
||||
|
||||
|
||||
gme_type_t file_type = gme_identify_extension( path );
|
||||
if ( !file_type )
|
||||
{
|
||||
|
@ -180,23 +180,33 @@ BLARGG_EXPORT gme_err_t gme_open_file( const char* path, Music_Emu** out, int sa
|
|||
}
|
||||
if ( !file_type )
|
||||
return gme_wrong_file_type;
|
||||
|
||||
|
||||
Music_Emu* emu = gme_new_emu( file_type, sample_rate );
|
||||
CHECK_ALLOC( emu );
|
||||
|
||||
|
||||
// optimization: avoids seeking/re-reading header
|
||||
Remaining_Reader rem( header, header_size, &in );
|
||||
gme_err_t err = emu->load( rem );
|
||||
in.close();
|
||||
|
||||
|
||||
if ( err )
|
||||
delete emu;
|
||||
else
|
||||
*out = emu;
|
||||
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
BLARGG_EXPORT void gme_set_autoload_playback_limit( Music_Emu *emu, int do_autoload_limit )
|
||||
{
|
||||
emu->set_autoload_playback_limit( do_autoload_limit != 0 );
|
||||
}
|
||||
|
||||
BLARGG_EXPORT int gme_autoload_playback_limit( Music_Emu *const emu )
|
||||
{
|
||||
return emu->autoload_playback_limit();
|
||||
}
|
||||
|
||||
// Used to implement gme_new_emu and gme_new_emu_multi_channel
|
||||
Music_Emu* gme_internal_new_emu_( gme_type_t type, int rate, bool multi_channel )
|
||||
{
|
||||
|
@ -204,7 +214,7 @@ Music_Emu* gme_internal_new_emu_( gme_type_t type, int rate, bool multi_channel
|
|||
{
|
||||
if ( rate == gme_info_only )
|
||||
return type->new_info();
|
||||
|
||||
|
||||
Music_Emu* me = type->new_emu();
|
||||
if ( me )
|
||||
{
|
||||
|
@ -224,7 +234,7 @@ Music_Emu* gme_internal_new_emu_( gme_type_t type, int rate, bool multi_channel
|
|||
if ( me->effects_buffer )
|
||||
me->set_buffer( me->effects_buffer );
|
||||
}
|
||||
|
||||
|
||||
if ( !(type->flags_ & 1) || me->effects_buffer )
|
||||
#endif
|
||||
{
|
||||
|
@ -276,30 +286,30 @@ BLARGG_EXPORT int gme_track_count( Music_Emu const* me ) { return me->track_coun
|
|||
struct gme_info_t_ : gme_info_t
|
||||
{
|
||||
track_info_t info;
|
||||
|
||||
|
||||
BLARGG_DISABLE_NOTHROW
|
||||
};
|
||||
|
||||
BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track )
|
||||
{
|
||||
*out = NULL;
|
||||
|
||||
|
||||
gme_info_t_* info = BLARGG_NEW gme_info_t_;
|
||||
CHECK_ALLOC( info );
|
||||
|
||||
|
||||
gme_err_t err = me->track_info( &info->info, track );
|
||||
if ( err )
|
||||
{
|
||||
gme_free_info( info );
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
#define COPY(name) info->name = info->info.name;
|
||||
|
||||
|
||||
COPY( length );
|
||||
COPY( intro_length );
|
||||
COPY( loop_length );
|
||||
|
||||
|
||||
info->i4 = -1;
|
||||
info->i5 = -1;
|
||||
info->i6 = -1;
|
||||
|
@ -312,7 +322,7 @@ BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, i
|
|||
info->i13 = -1;
|
||||
info->i14 = -1;
|
||||
info->i15 = -1;
|
||||
|
||||
|
||||
info->s7 = "";
|
||||
info->s8 = "";
|
||||
info->s9 = "";
|
||||
|
@ -322,7 +332,7 @@ BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, i
|
|||
info->s13 = "";
|
||||
info->s14 = "";
|
||||
info->s15 = "";
|
||||
|
||||
|
||||
COPY( system );
|
||||
COPY( game );
|
||||
COPY( song );
|
||||
|
@ -330,9 +340,9 @@ BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, i
|
|||
COPY( copyright );
|
||||
COPY( comment );
|
||||
COPY( dumper );
|
||||
|
||||
|
||||
#undef COPY
|
||||
|
||||
|
||||
info->play_length = info->length;
|
||||
if ( info->play_length <= 0 )
|
||||
{
|
||||
|
@ -340,9 +350,9 @@ BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, i
|
|||
if ( info->play_length <= 0 )
|
||||
info->play_length = 150 * 1000; // 2.5 minutes
|
||||
}
|
||||
|
||||
|
||||
*out = info;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ MusInfo *GME_OpenSong(FileReader &reader, const char *fmt)
|
|||
return nullptr;
|
||||
}
|
||||
gme_set_stereo_depth(emu, clamp(*gme_stereodepth, 0.f, 1.f));
|
||||
gme_set_fade(emu, -1); // Enable infinite loop
|
||||
return new GMESong(emu, sample_rate);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue