void Nsf_Impl::write_bank( int bank, int data ) { // Find bank in ROM int offset = rom.mask_addr( data * bank_size ); if ( offset >= rom.size() ) special_event( "invalid bank" ); void const* rom_data = rom.at_addr( offset ); #if !NSF_EMU_APU_ONLY if ( bank < bank_count - fds_banks && fds_enabled() ) { // TODO: FDS bank switching is kind of hacky, might need to // treat ROM as RAM so changes won't get lost when switching. byte* out = sram(); if ( bank >= fds_banks ) { out = fdsram(); bank -= fds_banks; } memcpy( &out [bank * bank_size], rom_data, bank_size ); return; } #endif if ( bank >= fds_banks ) cpu.map_code( (bank + 6) * bank_size, bank_size, rom_data ); }
void Nsf_Impl::write_mem( addr_t addr, int data ) { (void) LOG_MEM( addr, "<", data ); int offset = addr - sram_addr; if ( (unsigned) offset < sram_size ) { sram() [offset] = data; } else { // after sram because CPU handles most low_ram accesses internally already int temp = addr & (low_ram_size-1); // also handles wrap-around if ( !(addr & 0xE000) ) { low_ram [temp] = data; } else { int bank = addr - banks_addr; if ( (unsigned) bank < bank_count ) { write_bank( bank, data ); } else if ( (unsigned) (addr - apu.io_addr) < apu.io_size ) { apu.write_register( time(), addr, data ); } else { #if !NSF_EMU_APU_ONLY // 0x8000-0xDFFF is writable int i = addr - 0x8000; if ( (unsigned) i < fdsram_size && fds_enabled() ) fdsram() [i] = data; else #endif cpu_write( addr, data ); } } } }
int sc_main(int argc, char *argv[]) { int i; sc_signal<bool> clk; sc_signal<sc_int<8> > addr; sc_signal_rv<16> data_in; sc_signal_rv<16> data_out; sc_signal<bool> write; sc_trace_file *my_trace_file; my_trace_file = sc_create_vcd_trace_file ("sram_trace"); sc_trace(my_trace_file, clk, "clk"); sc_trace(my_trace_file, addr, "addr"); sc_trace(my_trace_file, data_in, "data_in"); sc_trace(my_trace_file, data_out, "data_out"); sc_trace(my_trace_file, write, "write"); sram sram("Synchronous_RAM"); sram.clk(clk); sram.addr(addr); sram.data_in(data_in); sram.data_out(data_out); sram.write(write); addr=22 ; write = 1; data_in=34; next_cycle (clk); addr=23 ; write = 1; data_in=42; next_cycle(clk); next_cycle(clk); write = 0; addr=25 ; next_cycle(clk); write = 0; addr=22 ; next_cycle(clk); next_cycle(clk); for(i=0; i<17; i++) next_cycle(clk); sc_close_vcd_trace_file (my_trace_file); return EXIT_SUCCESS; }
void Nsf_Impl::map_memory() { // Map standard things cpu.reset( unmapped_code() ); cpu.map_code( 0, 0x2000, low_ram, low_ram_size ); // mirrored four times cpu.map_code( sram_addr, sram_size, sram() ); // Determine initial banks byte banks [bank_count]; static byte const zero_banks [sizeof header_.banks] = { 0 }; if ( memcmp( header_.banks, zero_banks, sizeof zero_banks ) ) { banks [0] = header_.banks [6]; banks [1] = header_.banks [7]; memcpy( banks + fds_banks, header_.banks, sizeof header_.banks ); } else { // No initial banks, so assign them based on load_addr int first_bank = (get_addr( header_.load_addr ) - sram_addr) / bank_size; unsigned total_banks = rom.size() / bank_size; for ( int i = bank_count; --i >= 0; ) { int bank = i - first_bank; if ( (unsigned) bank >= total_banks ) bank = 0; banks [i] = bank; } } // Map banks for ( int i = (fds_enabled() ? 0 : fds_banks); i < bank_count; ++i ) write_bank( i, banks [i] ); // Map FDS RAM if ( fds_enabled() ) cpu.map_code( rom_addr, fdsram_size, fdsram() ); }
blargg_err_t Nsf_Impl::start_track( int track ) { int speed_flags = 0; #if NSF_EMU_EXTRA_FLAGS speed_flags = header().speed_flags; #endif apu.reset( header().pal_only(), (speed_flags & 0x20) ? 0x3F : 0 ); apu.enable_w4011_( enable_w4011 ); apu.write_register( 0, 0x4015, 0x0F ); apu.write_register( 0, 0x4017, (speed_flags & 0x10) ? 0x80 : 0 ); // Clear memory memset( unmapped_code(), Nes_Cpu::halt_opcode, unmapped_size ); memset( low_ram, 0, low_ram_size ); memset( sram(), 0, sram_size ); map_memory(); // Arrange time of first call to play routine play_extra = 0; next_play = play_period; play_delay = initial_play_delay; saved_state.pc = idle_addr; // Setup for call to init routine cpu.r.a = track; cpu.r.x = header_.pal_only(); cpu.r.sp = 0xFF; jsr_then_stop( header_.init_addr ); if ( cpu.r.pc < get_addr( header_.load_addr ) ) set_warning( "Init address < load address" ); return blargg_ok; }