int Hes_Emu::cpu_read_( hes_addr_t addr ) { hes_time_t time = this->time(); addr &= page_size - 1; switch ( addr ) { case 0x0000: if ( irq.vdp > time ) return 0; irq.vdp = future_hes_time; run_until( time ); irq_changed(); return 0x20; case 0x0002: case 0x0003: debug_printf( "VDP read not supported: %d\n", addr ); return 0; case 0x0C01: //return timer.enabled; // TODO: remove? case 0x0C00: run_until( time ); debug_printf( "Timer count read\n" ); return (unsigned) (timer.count - 1) / timer_base; case 0x1402: return irq.disables; case 0x1403: { int status = 0; if ( irq.timer <= time ) status |= timer_mask; if ( irq.vdp <= time ) status |= vdp_mask; return status; } #ifndef NDEBUG case 0x1000: // I/O port case 0x180C: // CD-ROM case 0x180D: break; default: debug_printf( "unmapped read $%04X\n", addr ); #endif } return unmapped; }
int Opl_Apu::read( blip_time_t time, int port ) { run_until( time ); switch (type_) { case type_opll: case type_msxmusic: case type_smsfmunit: case type_vrc7: return ym2413_read( opl, port ); case type_opl: return ym3526_read( opl, port ); case type_msxaudio: { int ret = y8950_read( opl, port ); /*unsigned char temp [2] = { port + 0x80, ret }; fwrite( &temp, 1, 2, logfile );*/ return ret; } case type_opl2: return ym3812_read( opl, port ); } return 0; }
void Opl_Apu::write_data( blip_time_t time, int data ) { run_until( time ); switch (type_) { case type_opll: case type_msxmusic: case type_smsfmunit: case type_vrc7: ym2413_write( opl, 0, addr ); ym2413_write( opl, 1, data ); break; case type_opl: ym3526_write( opl, 0, addr ); ym3526_write( opl, 1, data ); break; case type_msxaudio: /*if ( addr >= 7 && addr <= 7 + 11 ) { unsigned char temp [2] = { addr - 7, data }; fwrite( &temp, 1, 2, logfile ); }*/ y8950_write( opl, 0, addr ); y8950_write( opl, 1, data ); break; case type_opl2: ym3812_write( opl, 0, addr ); ym3812_write( opl, 1, data ); break; } }
blargg_err_t Hes_Emu::run_clocks( blip_time_t& duration_, int ) { blip_time_t const duration = duration_; // cache if ( cpu::run( duration ) ) set_warning( "Emulation error (illegal instruction)" ); check( time() >= duration ); //check( time() - duration < 20 ); // Txx instruction could cause going way over run_until( duration ); // end time frame timer.last_time -= duration; vdp.next_vbl -= duration; #if GME_FRAME_HOOK_DEFINED last_frame_hook -= duration; #endif cpu::end_frame( duration ); ::adjust_time( irq.timer, duration ); ::adjust_time( irq.vdp, duration ); apu.end_frame( duration ); return 0; }
void Sms_Fm_Apu::write_data( blip_time_t time, int data ) { if ( time > next_time ) run_until( time ); apu.write( addr, data ); }
int Hes_Apu_Adpcm::read_data( blip_time_t time, int addr ) { if ( time > last_time ) run_until( time ); switch ( addr & 15 ) { case 10: return state.pcmbuf [state.readptr++]; case 11: return state.port [11] & ~1; case 12: if (!state.playflag) { state.port [12] |= 1; state.port [12] &= ~8; } else { state.port [12] &= ~1; state.port [12] |= 8; } return state.port [12]; case 13: return state.port [13]; } return 0xFF; }
void Hes_Emu::cpu_write_vdp( int addr, int data ) { switch ( addr ) { case 0: vdp.latch = data & 0x1F; break; case 2: if ( vdp.latch == 5 ) { if ( data & 0x04 ) set_warning( "Scanline interrupt unsupported" ); run_until( time() ); vdp.control = data; irq_changed(); } else { debug_printf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data ); } break; case 3: debug_printf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data ); break; } }
void Nes_Vrc6_Apu::end_frame( nes_time_t time ) { if ( time > last_time ) run_until( time ); assert( last_time >= time ); last_time -= time; }
void Nes_Vrc6_Apu::write_osc( nes_time_t time, int osc_index, int reg, int data ) { require( (unsigned) osc_index < osc_count ); require( (unsigned) reg < reg_count ); run_until( time ); oscs [osc_index].regs [reg] = data; }
void Opl_Apu::end_frame( blip_time_t time ) { run_until( time ); next_time -= time; if ( output_ ) output_->set_modified(); }
virtual void end_frame( nes_time_t end_time ) { if ( end_time > last_time ) run_until( end_time ); last_time -= end_time; sound.end_frame( end_time ); }
void Hes_Apu_Adpcm::end_frame( blip_time_t end_time ) { run_until( end_time ); last_time -= end_time; next_timer -= (double)end_time; check( last_time >= 0 ); if ( output ) output->set_modified(); }
void Sms_Fm_Apu::end_frame( blip_time_t time ) { if ( time > next_time ) run_until( time ); next_time -= time; assert( next_time >= 0 ); if ( output_ ) output_->set_modified(); }
void Nes_Vrc7_Apu::write_data( blip_time_t time, int data ) { int type = (addr >> 4) - 1; int chan = addr & 15; if ( (unsigned) type < 3 && chan < osc_count ) oscs [chan].regs [type] = data; if ( time > next_time ) run_until( time ); ym2413_write( opll, 0, addr ); ym2413_write( opll, 1, data ); }
void Nes_Vrc7_Apu::write_data( blip_time_t time, int data ) { int type = (addr >> 4) - 1; int chan = addr & 15; if ( (unsigned) type < 3 && chan < osc_count ) oscs [chan].regs [type] = data; if ( addr < 0x08 ) inst [addr] = data; if ( time > next_time ) run_until( time ); OPLL_writeIO( (OPLL *) opll, 0, addr ); OPLL_writeIO( (OPLL *) opll, 1, data ); }
void Nsf_Impl::end_frame( time_t end ) { if ( time() < end ) run_until( end ); cpu.adjust_time( -end ); // Localize to new time frame next_play -= end; check( next_play >= 0 ); if ( next_play < 0 ) next_play = 0; apu.end_frame( end ); }
void Nes_Vrc7_Apu::end_frame( blip_time_t time ) { if ( time > next_time ) run_until( time ); next_time -= time; assert( next_time >= 0 ); for ( int i = osc_count; --i >= 0; ) { Blip_Buffer* output = oscs [i].output; if ( output ) output->set_modified(); } }
void Mapper_Fme7::write_irq( nes_time_t time, int index, int data ) { run_until( time ); switch ( index ) { case 0x0D: irq_mode = data; irq_pending = false; irq_changed(); break; case 0x0E: irq_count = (irq_count & 0xFF00) | data; break; case 0x0F: irq_count = data << 8 | (irq_count & 0xFF); break; } }
void Hes_Apu_Adpcm::write_data( blip_time_t time, int addr, int data ) { if ( time > last_time ) run_until( time ); data &= 0xFF; state.port[ addr & 15 ] = data; switch ( addr & 15 ) { case 8: state.addr &= 0xFF00; state.addr |= data; break; case 9: state.addr &= 0xFF; state.addr |= data << 8; break; case 10: state.pcmbuf[ state.writeptr++ ] = data; state.playlength ++; break; case 11: dprintf("ADPCM DMA 0x%02X", data); break; case 13: if ( data & 0x80 ) { state.addr = 0; state.freq = 0; state.writeptr = 0; state.readptr = 0; state.playflag = 0; state.repeatflag = 0; state.length = 0; state.volume = 0xFF; } if ( ( data & 3 ) == 3 ) { state.writeptr = state.addr; } if ( data & 8 ) { state.readptr = state.addr ? state.addr - 1 : state.addr; } if ( data & 0x10 ) { state.length = state.addr; } state.repeatflag = data & 0x20; state.playflag = data & 0x40; if ( state.playflag ) { state.playptr = state.readptr; state.playlength = state.length + 1; state.playedsamplecount = 0; state.ad_sample = 0; state.ad_low_nibble = false; } break; case 14: state.freq = 7159091 / ( 32000 / ( 16 - ( data & 15 ) ) ); break; case 15: switch ( data & 15 ) { case 0: case 8: case 12: state.fadetimer = -100; state.fadecount = state.fadetimer; break; case 10: state.fadetimer = 5000; state.fadecount = state.fadetimer; break; case 14: state.fadetimer = 1500; state.fadecount = state.fadetimer; break; } break; } }
void Hes_Emu::cpu_write_( hes_addr_t addr, int data ) { if ( unsigned (addr - apu.start_addr) <= apu.end_addr - apu.start_addr ) { GME_APU_HOOK( this, addr - apu.start_addr, data ); // avoid going way past end when a long block xfer is writing to I/O space hes_time_t t = min( time(), end_time() + 8 ); apu.write_data( t, addr, data ); return; } hes_time_t time = this->time(); switch ( addr ) { case 0x0000: case 0x0002: case 0x0003: cpu_write_vdp( addr, data ); return; case 0x0C00: { run_until( time ); timer.raw_load = (data & 0x7F) + 1; recalc_timer_load(); timer.count = timer.load; break; } case 0x0C01: data &= 1; if ( timer.enabled == data ) return; run_until( time ); timer.enabled = data; if ( data ) timer.count = timer.load; break; case 0x1402: run_until( time ); irq.disables = data; if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values debug_printf( "Int mask: $%02X\n", data ); break; case 0x1403: run_until( time ); if ( timer.enabled ) timer.count = timer.load; timer.fired = false; break; #ifndef NDEBUG case 0x1000: // I/O port case 0x0402: // palette case 0x0403: case 0x0404: case 0x0405: return; default: debug_printf( "unmapped write $%04X <- $%02X\n", addr, data ); return; #endif } irq_changed(); }