blargg_err_t Classic_Emu::setup_buffer( long rate )
{
	change_clock_rate( rate );
	RETURN_ERR( buf->set_channel_count( voice_count() ) );
	set_equalizer( equalizer() );
	buf_changed_count = buf->channels_changed_count();
	return 0;
}
Exemple #2
0
blargg_err_t Classic_Emu::setup_buffer( int rate )
{
	change_clock_rate( rate );
	RETURN_ERR( buf->set_channel_count( voice_count(), voice_types ) );
	set_equalizer( equalizer() );
	buf_changed_count = buf->channels_changed_count();
	return (blargg_err_t)blargg_ok;
}
Exemple #3
0
void Ay_Emu::cpu_out_misc( cpu_time_t time, unsigned addr, int data )
{
	if ( !cpc_mode )
	{
		switch ( addr & 0xFEFF )
		{
		case 0xFEFD:
			spectrum_mode = true;
			apu_addr = data & 0x0F;
			return;
		
		case 0xBEFD:
			spectrum_mode = true;
			apu.write( time, apu_addr, data );
			return;
		}
	}
	
	if ( !spectrum_mode )
	{
		switch ( addr >> 8 )
		{
		case 0xF6:
			switch ( data & 0xC0 )
			{
			case 0xC0:
				apu_addr = cpc_latch & 0x0F;
				goto enable_cpc;
			
			case 0x80:
				apu.write( time, apu_addr, cpc_latch );
				goto enable_cpc;
			}
			break;
		
		case 0xF4:
			cpc_latch = data;
			goto enable_cpc;
		}
	}
	
	debug_printf( "Unmapped OUT: $%04X <- $%02X\n", addr, data );
	return;
	
enable_cpc:
	if ( !cpc_mode )
	{
		cpc_mode = true;
		change_clock_rate( cpc_clock );
		set_tempo( tempo() );
	}
}
Exemple #4
0
blargg_err_t Ay_Emu::start_track_( int track )
{
	RETURN_ERR( Classic_Emu::start_track_( track ) );
	
	memset( mem.ram + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
	memset( mem.ram + 0x0100, 0xFF, 0x4000 - 0x100 );
	memset( mem.ram + ram_start, 0x00, sizeof mem.ram - ram_start );
	memset( mem.padding1, 0xFF, sizeof mem.padding1 );
	memset( mem.ram + 0x10000, 0xFF, sizeof mem.ram - 0x10000 );
	
	// locate data blocks
	byte const* const data = get_data( file, file.tracks + track * 4 + 2, 14 );
	if ( !data ) return "File data missing";
	
	byte const* const more_data = get_data( file, data + 10, 6 );
	if ( !more_data ) return "File data missing";
	
	byte const* blocks = get_data( file, data + 12, 8 );
	if ( !blocks ) return "File data missing";
	
	// initial addresses
	cpu::reset( mem.ram );
	r.sp = get_be16( more_data );
	r.b.a = r.b.b = r.b.d = r.b.h = data [8];
	r.b.flags = r.b.c = r.b.e = r.b.l = data [9];
	r.alt.w = r.w;
	r.ix = r.iy = r.w.hl;
	
	unsigned addr = get_be16( blocks );
	if ( !addr ) return "File data missing";
	
	unsigned init = get_be16( more_data + 2 );
	if ( !init )
		init = addr;
	
	// copy blocks into memory
	do
	{
		blocks += 2;
		unsigned len = get_be16( blocks ); blocks += 2;
		if ( addr + len > 0x10000 )
		{
			set_warning( "Bad data block size" );
			len = 0x10000 - addr;
		}
		check( len );
		byte const* in = get_data( file, blocks, 0 ); blocks += 2;
		if ( len > blargg_ulong (file.end - in) )
		{
			set_warning( "Missing file data" );
			len = file.end - in;
		}
		//debug_printf( "addr: $%04X, len: $%04X\n", addr, len );
		if ( addr < ram_start && addr >= 0x400 ) // several tracks use low data
			debug_printf( "Block addr in ROM\n" );
		memcpy( mem.ram + addr, in, len );
		
		if ( file.end - blocks < 8 )
		{
			set_warning( "Missing file data" );
			break;
		}
	}
	while ( (addr = get_be16( blocks )) != 0 );
	
	// copy and configure driver
	static byte const passive [] = {
		0xF3,       // DI
		0xCD, 0, 0, // CALL init
		0xED, 0x5E, // LOOP: IM 2
		0xFB,       // EI
		0x76,       // HALT
		0x18, 0xFA  // JR LOOP
	};
	static byte const active [] = {
		0xF3,       // DI
		0xCD, 0, 0, // CALL init
		0xED, 0x56, // LOOP: IM 1
		0xFB,       // EI
		0x76,       // HALT
		0xCD, 0, 0, // CALL play
		0x18, 0xF7  // JR LOOP
	};
	memcpy( mem.ram, passive, sizeof passive );
	unsigned play_addr = get_be16( more_data + 4 );
	//debug_printf( "Play: $%04X\n", play_addr );
	if ( play_addr )
	{
		memcpy( mem.ram, active, sizeof active );
		mem.ram [ 9] = play_addr;
		mem.ram [10] = play_addr >> 8;
	}
	mem.ram [2] = init;
	mem.ram [3] = init >> 8;
	
	mem.ram [0x38] = 0xFB; // Put EI at interrupt vector (followed by RET)
	
	memcpy( mem.ram + 0x10000, mem.ram, 0x80 ); // some code wraps around (ugh)
	
	beeper_delta = int (apu.amp_range * 0.65);
	last_beeper = 0;
	apu.reset();
	next_play = play_period;
	
	// start at spectrum speed
	change_clock_rate( spectrum_clock );
	set_tempo( tempo() );
	
	spectrum_mode = false;
	cpc_mode      = false;
	cpc_latch     = 0;
	
	return 0;
}
Exemple #5
0
inline void Ay_Emu::enable_cpc()
{
    change_clock_rate( cpc_clock );
    set_tempo( tempo() );
}
Exemple #6
0
blargg_err_t Ay_Emu::start_track_( int track )
{
    RETURN_ERR( Classic_Emu::start_track_( track ) );

    byte* const mem = core.mem();

    memset( mem + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
    memset( mem + 0x0100, 0xFF, 0x4000 - 0x100 );
    memset( mem + core.ram_addr, 0x00, core.mem_size - core.ram_addr );

    // locate data blocks
    byte const* const data = get_data( file, file.tracks + track * 4 + 2, 14 );
    if ( !data )
        return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );

    byte const* const more_data = get_data( file, data + 10, 6 );
    if ( !more_data )
        return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );

    byte const* blocks = get_data( file, data + 12, 8 );
    if ( !blocks )
        return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );

    // initial addresses
    unsigned addr = get_be16( blocks );
    if ( !addr )
        return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );

    unsigned init = get_be16( more_data + 2 );
    if ( !init )
        init = addr;

    // copy blocks into memory
    do
    {
        blocks += 2;
        unsigned len = get_be16( blocks );
        blocks += 2;
        if ( addr + len > core.mem_size )
        {
            set_warning( "Bad data block size" );
            len = core.mem_size - addr;
        }
        check( len );
        byte const* in = get_data( file, blocks, 0 );
        blocks += 2;
        if ( len > (unsigned) (file.end - in) )
        {
            set_warning( "File data missing" );
            len = file.end - in;
        }
        //dprintf( "addr: $%04X, len: $%04X\n", addr, len );
        if ( addr < core.ram_addr && addr >= 0x400 ) // several tracks use low data
            dprintf( "Block addr in ROM\n" );
        memcpy( mem + addr, in, len );

        if ( file.end - blocks < 8 )
        {
            set_warning( "File data missing" );
            break;
        }
    }
    while ( (addr = get_be16( blocks )) != 0 );

    // copy and configure driver
    static byte const passive [] = {
        0xF3,       // DI
        0xCD, 0, 0, // CALL init
        0xED, 0x5E, // LOOP: IM 2
        0xFB,       // EI
        0x76,       // HALT
        0x18, 0xFA  // JR LOOP
    };
    static byte const active [] = {
        0xF3,       // DI
        0xCD, 0, 0, // CALL init
        0xED, 0x56, // LOOP: IM 1
        0xFB,       // EI
        0x76,       // HALT
        0xCD, 0, 0, // CALL play
        0x18, 0xF7  // JR LOOP
    };
    memcpy( mem, passive, sizeof passive );
    int const play_addr = get_be16( more_data + 4 );
    if ( play_addr )
    {
        memcpy( mem, active, sizeof active );
        mem [ 9] = play_addr;
        mem [10] = play_addr >> 8;
    }
    mem [2] = init;
    mem [3] = init >> 8;

    mem [0x38] = 0xFB; // Put EI at interrupt vector (followed by RET)

    // start at spectrum speed
    change_clock_rate( spectrum_clock );
    set_tempo( tempo() );

    Ay_Core::registers_t r = { };
    r.sp = get_be16( more_data );
    r.b.a     = r.b.b = r.b.d = r.b.h = data [8];
    r.b.flags = r.b.c = r.b.e = r.b.l = data [9];
    r.alt.w = r.w;
    r.ix = r.iy = r.w.hl;

    core.start_track( r, play_addr );

    return blargg_ok;
}