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:
Vitaly Novichkov 2019-08-18 03:19:28 +03:00 committed by alexey.lysiuk
parent 7d73616fda
commit 1a070d12a1
7 changed files with 318 additions and 287 deletions

View file

@ -94,14 +94,14 @@ bool Hes_Cpu::run( hes_time_t end_time )
state_t s = this->state_;
this->state = &s;
// even on x86, using s.time in place of s_time was slower
int16_t s_time = s.time;
blargg_long s_time = s.time;
// registers
uint16_t pc = r.pc;
uint8_t a = r.a;
uint8_t x = r.x;
uint8_t y = r.y;
uint16_t sp;
uint_fast16_t pc = r.pc;
uint_fast8_t a = r.a;
uint_fast8_t x = r.x;
uint_fast8_t y = r.y;
uint_fast16_t sp;
SET_SP( r.sp );
#define IS_NEG (nz & 0x8080)
@ -120,11 +120,11 @@ bool Hes_Cpu::run( hes_time_t end_time )
nz |= ~in & st_z;\
} while ( 0 )
uint8_t status;
uint16_t c; // carry set if (c & 0x100) != 0
uint16_t nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
uint_fast8_t status;
uint_fast16_t c; // carry set if (c & 0x100) != 0
uint_fast16_t nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
{
uint8_t temp = r.status;
uint_fast8_t temp = r.status;
SET_STATUS( temp );
}
@ -153,7 +153,7 @@ loop:
check( (unsigned) x < 0x100 );
uint8_t const* instr = s.code_map [pc >> page_shift];
uint8_t opcode;
uint_fast8_t opcode;
// TODO: eliminate this special case
#if BLARGG_NONPORTABLE
@ -187,7 +187,7 @@ loop:
4,7,7,17,2,4,6,7,2,5,4,2,2,5,7,6 // F
}; // 0x00 was 8
uint16_t data;
uint_fast16_t data;
data = clock_table [opcode];
if ( (s_time += data) >= 0 )
goto possibly_out_of_time;
@ -224,7 +224,7 @@ possibly_out_of_time:
// TODO: more efficient way to handle negative branch that wraps PC around
#define BRANCH( cond )\
{\
int16_t offset = (int8_t) data;\
int_fast16_t offset = (int8_t) data;\
pc++;\
if ( !(cond) ) goto branch_not_taken;\
pc = uint16_t (pc + offset);\
@ -277,7 +277,7 @@ possibly_out_of_time:
case 0xCF:
case 0xDF:
case 0xEF: {
uint16_t t = 0x101 * READ_LOW( data );
uint_fast16_t t = 0x101 * READ_LOW( data );
t ^= 0xFF;
pc++;
data = GET_MSB();
@ -305,7 +305,7 @@ possibly_out_of_time:
goto branch_taken;
case 0x20: { // JSR
uint16_t temp = pc + 1;
uint_fast16_t temp = pc + 1;
pc = GET_ADDR();
WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
sp = (sp - 2) | 0x100;
@ -326,7 +326,7 @@ possibly_out_of_time:
case 0xBD:{// LDA abs,X
PAGE_CROSS_PENALTY( data + x );
uint16_t addr = GET_ADDR() + x;
uint_fast16_t addr = GET_ADDR() + x;
pc += 2;
CPU_READ_FAST( this, addr, TIME, nz );
a = nz;
@ -334,7 +334,7 @@ possibly_out_of_time:
}
case 0x9D:{// STA abs,X
uint16_t addr = GET_ADDR() + x;
uint_fast16_t addr = GET_ADDR() + x;
pc += 2;
CPU_WRITE_FAST( this, addr, a, TIME );
goto loop;
@ -348,7 +348,7 @@ possibly_out_of_time:
goto loop;
case 0xAE:{// LDX abs
uint16_t addr = GET_ADDR();
uint_fast16_t addr = GET_ADDR();
pc += 2;
CPU_READ_FAST( this, addr, TIME, nz );
x = nz;
@ -363,7 +363,7 @@ possibly_out_of_time:
// Load/store
{
uint16_t addr;
uint_fast16_t addr;
case 0x91: // STA (ind),Y
addr = 0x100 * READ_LOW( uint8_t (data + 1) );
addr += READ_LOW( data ) + y;
@ -389,7 +389,7 @@ possibly_out_of_time:
}
{
uint16_t addr;
uint_fast16_t addr;
case 0xA1: // LDA (ind,X)
data = uint8_t (data + x);
case 0xB2: // LDA (ind)
@ -419,7 +419,7 @@ possibly_out_of_time:
case 0xBE:{// LDX abs,y
PAGE_CROSS_PENALTY( data + y );
uint16_t addr = GET_ADDR() + y;
uint_fast16_t addr = GET_ADDR() + y;
pc += 2;
FLUSH_TIME();
x = nz = READ( addr );
@ -443,7 +443,7 @@ possibly_out_of_time:
case 0x3C: // BIT abs,x
data += x;
case 0x2C:{// BIT abs
uint16_t addr;
uint_fast16_t addr;
ADD_PAGE( addr );
FLUSH_TIME();
nz = READ( addr );
@ -466,7 +466,7 @@ possibly_out_of_time:
goto loop;
{
uint16_t addr;
uint_fast16_t addr;
case 0xB3: // TST abs,x
addr = GET_MSB() + x;
@ -499,7 +499,7 @@ possibly_out_of_time:
goto loop;
{
uint16_t addr;
uint_fast16_t addr;
case 0x0C: // TSB abs
case 0x1C: // TRB abs
addr = GET_ADDR();
@ -604,7 +604,7 @@ possibly_out_of_time:
data += x;
PAGE_CROSS_PENALTY( data );
case 0xAC:{// LDY abs
uint16_t addr = data + 0x100 * GET_MSB();
uint_fast16_t addr = data + 0x100 * GET_MSB();
pc += 2;
FLUSH_TIME();
y = nz = READ( addr );
@ -613,7 +613,7 @@ possibly_out_of_time:
}
{
uint8_t temp;
uint_fast8_t temp;
case 0x8C: // STY abs
temp = y;
goto store_abs;
@ -621,7 +621,7 @@ possibly_out_of_time:
case 0x8E: // STX abs
temp = x;
store_abs:
uint16_t addr = GET_ADDR();
uint_fast16_t addr = GET_ADDR();
pc += 2;
FLUSH_TIME();
WRITE( addr, temp );
@ -632,7 +632,7 @@ possibly_out_of_time:
// Compare
case 0xEC:{// CPX abs
uint16_t addr = GET_ADDR();
uint_fast16_t addr = GET_ADDR();
pc++;
FLUSH_TIME();
data = READ( addr );
@ -651,7 +651,7 @@ possibly_out_of_time:
goto loop;
case 0xCC:{// CPY abs
uint16_t addr = GET_ADDR();
uint_fast16_t addr = GET_ADDR();
pc++;
FLUSH_TIME();
data = READ( addr );
@ -678,7 +678,7 @@ possibly_out_of_time:
data = 0x100 * READ_LOW( uint8_t (data + 1) ) + READ_LOW( data );\
goto ptr##op;\
case op + 0x0C:{/* (ind),y */\
uint16_t temp = READ_LOW( data ) + y;\
uint_fast16_t temp = READ_LOW( data ) + y;\
PAGE_CROSS_PENALTY( temp );\
data = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
goto ptr##op;\
@ -736,8 +736,8 @@ possibly_out_of_time:
adc_imm: {
if ( status & st_d )
debug_printf( "Decimal mode not supported\n" );
int16_t carry = c >> 8 & 1;
int16_t ov = (a ^ 0x80) + carry + (int8_t) data; // sign-extend
int_fast16_t carry = c >> 8 & 1;
int_fast16_t ov = (a ^ 0x80) + carry + (int8_t) data; // sign-extend
status &= ~st_v;
status |= ov >> 2 & 0x40;
c = nz = a + data + carry;
@ -765,7 +765,7 @@ possibly_out_of_time:
case 0x2A: { // ROL A
nz = a << 1;
int16_t temp = c >> 8 & 1;
int_fast16_t temp = c >> 8 & 1;
c = nz;
nz |= temp;
a = (uint8_t) nz;
@ -871,7 +871,7 @@ possibly_out_of_time:
case 0xD6: // DEC zp,x
data = uint8_t (data + x);
case 0xC6: // DEC zp
nz = (uint16_t) -1;
nz = (unsigned) -1;
add_nz_zp:
nz += READ_LOW( data );
write_nz_zp:
@ -896,7 +896,7 @@ possibly_out_of_time:
case 0xCE: // DEC abs
data = GET_ADDR();
dec_ptr:
nz = (uint16_t) -1;
nz = (unsigned) -1;
inc_common:
FLUSH_TIME();
nz += READ( data );
@ -936,7 +936,7 @@ possibly_out_of_time:
goto loop;
#define SWAP_REGS( r1, r2 ) {\
uint8_t t = r1;\
uint_fast8_t t = r1;\
r1 = r2;\
r2 = t;\
goto loop;\
@ -978,7 +978,7 @@ possibly_out_of_time:
goto loop;
case 0x40:{// RTI
uint8_t temp = READ_LOW( sp );
uint_fast8_t temp = READ_LOW( sp );
pc = READ_LOW( 0x100 | (sp - 0xFF) );
pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
sp = (sp - 0xFD) | 0x100;
@ -1012,8 +1012,8 @@ possibly_out_of_time:
goto loop;
case 0x28:{// PLP
uint8_t temp = POP();
uint8_t changed = status ^ temp;
uint_fast8_t temp = POP();
uint_fast8_t changed = status ^ temp;
SET_STATUS( temp );
if ( !(changed & st_i) )
goto loop; // I flag didn't change
@ -1024,7 +1024,7 @@ possibly_out_of_time:
#undef POP
case 0x08: { // PHP
uint8_t temp;
uint_fast8_t temp;
CALC_STATUS( temp );
PUSH( temp | st_b );
goto loop;
@ -1033,7 +1033,7 @@ possibly_out_of_time:
// Flags
case 0x38: // SEC
c = (uint16_t) ~0;
c = (unsigned) ~0;
goto loop;
case 0x18: // CLC
@ -1101,7 +1101,7 @@ possibly_out_of_time:
// Special
case 0x53:{// TAM
uint8_t const bits = data; // avoid using data across function call
uint_fast8_t const bits = data; // avoid using data across function call
pc++;
for ( int i = 0; i < 8; i++ )
if ( bits & (1 << i) )
@ -1125,7 +1125,7 @@ possibly_out_of_time:
case 0x03: // ST0
case 0x13: // ST1
case 0x23:{// ST2
uint16_t addr = opcode >> 4;
uint_fast16_t addr = opcode >> 4;
if ( addr )
addr++;
pc++;
@ -1147,7 +1147,7 @@ possibly_out_of_time:
goto loop;
case 0xF4: { // SET
//uint16_t operand = GET_MSB();
//fuint16 operand = GET_MSB();
debug_printf( "SET not handled\n" );
//switch ( data )
//{
@ -1159,10 +1159,10 @@ possibly_out_of_time:
// Block transfer
{
uint16_t in_alt;
int16_t in_inc;
uint16_t out_alt;
int16_t out_inc;
uint_fast16_t in_alt;
int_fast16_t in_inc;
uint_fast16_t out_alt;
int_fast16_t out_inc;
case 0xE3: // TIA
in_alt = 0;
@ -1193,8 +1193,8 @@ possibly_out_of_time:
in_alt = 0;
out_alt = 0;
bxfer:
uint16_t in = GET_LE16( instr + 0 );
uint16_t out = GET_LE16( instr + 2 );
uint_fast16_t in = GET_LE16( instr + 0 );
uint_fast16_t out = GET_LE16( instr + 2 );
int count = GET_LE16( instr + 4 );
if ( !count )
count = 0x10000;
@ -1206,7 +1206,7 @@ possibly_out_of_time:
do
{
// TODO: reads from $0800-$1400 in I/O page return 0 and don't access I/O
uint8_t t = READ( in );
uint_fast8_t t = READ( in );
in += in_inc;
in &= 0xFFFF;
s.time += 6;
@ -1246,7 +1246,7 @@ interrupt:
pc = GET_LE16( &READ_PROG( 0xFFF0 ) + result_ );
sp = (sp - 3) | 0x100;
uint8_t temp;
uint_fast8_t temp;
CALC_STATUS( temp );
if ( result_ == 6 )
temp |= st_b;
@ -1283,7 +1283,7 @@ out_of_time:
r.y = y;
{
uint8_t temp;
uint_fast8_t temp;
CALC_STATUS( temp );
r.status = temp;
}
@ -1293,4 +1293,3 @@ out_of_time:
return illegal_encountered;
}

View file

@ -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;

View file

@ -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

View file

@ -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 );
@ -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 );

View file

@ -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;
}

View file

@ -197,6 +197,16 @@ BLARGG_EXPORT gme_err_t gme_open_file( const char* path, Music_Emu** out, int sa
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 )
{

View file

@ -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);
}