blargg_err_t Sgc_Core::load_( Data_Reader& dr ) { RETURN_ERR( Sgc_Impl::load_( dr ) ); if ( sega_mapping() && fm_apu_.supported() ) RETURN_ERR( fm_apu_.init( clock_rate(), clock_rate() / 72 ) ); set_tempo( 1.0 ); return blargg_ok; }
blargg_err_t Sgc_Impl::start_track( int track ) { memset( ram .begin(), 0, ram .size() ); memset( ram2.begin(), 0, ram2.size() ); memset( vectors.begin(), 0xFF, vectors.size() ); cpu.reset( unmapped_write.begin(), rom.unmapped() ); if ( sega_mapping() ) { vectors_addr = 0x10000 - Sgc_Cpu::page_size; idle_addr = vectors_addr; for ( int i = 1; i < 8; ++i ) { vectors [i*8 + 0] = 0xC3; // JP addr vectors [i*8 + 1] = header_.rst_addrs [i*2 + 0]; vectors [i*8 + 2] = header_.rst_addrs [i*2 + 1]; } cpu.map_mem( 0xC000, 0x2000, ram.begin() ); cpu.map_mem( vectors_addr, cpu.page_size, unmapped_write.begin(), vectors.begin() ); bank2 = NULL; for ( int i = 0; i < 4; ++i ) cpu_write( 0xFFFC + i, header_.mapping [i] ); } else { if ( !coleco_bios ) return BLARGG_ERR( BLARGG_ERR_CALLER, "Coleco BIOS not set" ); vectors_addr = 0; cpu.map_mem( 0, 0x2000, unmapped_write.begin(), coleco_bios ); for ( int i = 0; i < 8; ++i ) cpu.map_mem( 0x6000 + i*0x400, 0x400, ram.begin() ); idle_addr = 0x2000; cpu.map_mem( 0x2000, cpu.page_size, unmapped_write.begin(), vectors.begin() ); for ( int i = 0; i < 0x8000 / bank_size; ++i ) { int addr = 0x8000 + i*bank_size; cpu.map_mem( addr, bank_size, unmapped_write.begin(), rom.at_addr( addr ) ); } } cpu.r.sp = get_le16( header_.stack_ptr ); cpu.r.b.a = track; next_play = play_period; jsr( header_.init_addr ); return blargg_ok; }
blargg_err_t Sgc_Core::end_frame( time_t t ) { RETURN_ERR( Sgc_Impl::end_frame( t ) ); apu_.end_frame( t ); if ( sega_mapping() && fm_accessed ) { if ( fm_apu_.supported() ) fm_apu_.end_frame( t ); else set_warning( "FM sound not supported" ); } return blargg_ok; }
blargg_err_t Sgc_Core::start_track( int t ) { if ( sega_mapping() ) { apu_.reset(); fm_apu_.reset(); fm_accessed = false; } else { apu_.reset( 0x0003, 15 ); } return Sgc_Impl::start_track( t ); }
void Sgc_Core::cpu_out( time_t time, addr_t addr, int data ) { int port = addr & 0xFF; if ( sega_mapping() ) { switch ( port ) { case 0x06: apu_.write_ggstereo( time, data ); return; case 0x7E: case 0x7F: apu_.write_data( time, data ); dprintf( "$7E<-%02X\n", data ); return; case 0xF0: fm_accessed = true; if ( fm_apu_.supported() ) fm_apu_.write_addr( data );//, dprintf( "$F0<-%02X\n", data ); return; case 0xF1: fm_accessed = true; if ( fm_apu_.supported() ) fm_apu_.write_data( time, data );//, dprintf( "$F1<-%02X\n", data ); return; } } else if ( port >= 0xE0 ) { apu_.write_data( time, data ); return; } Sgc_Impl::cpu_out( time, addr, data ); }
blargg_err_t Sgc_Impl::load_( Data_Reader& in ) { RETURN_ERR( rom.load( in, header_.size, &header_, 0 ) ); if ( !header_.valid_tag() ) return blargg_err_file_type; if ( header_.vers != 1 ) set_warning( "Unknown file version" ); if ( header_.system > 2 ) set_warning( "Unknown system" ); addr_t load_addr = get_le16( header_.load_addr ); if ( load_addr < 0x400 ) set_warning( "Invalid load address" ); rom.set_addr( load_addr ); play_period = clock_rate() / 60; if ( sega_mapping() ) { RETURN_ERR( ram.resize( 0x2000 + Sgc_Cpu::page_padding ) ); RETURN_ERR( ram2.resize( bank_size + Sgc_Cpu::page_padding ) ); } else { RETURN_ERR( ram.resize( 0x400 + Sgc_Cpu::page_padding ) ); } RETURN_ERR( vectors.resize( Sgc_Cpu::page_size + Sgc_Cpu::page_padding ) ); // TODO: doesn't need to be larger than page size, if we do mapping calls right RETURN_ERR( unmapped_write.resize( bank_size ) ); return blargg_ok; }