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; } }
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 Hes_Emu::cpu_done() { check( time() >= end_time() || (!(r.status & i_flag_mask) && time() >= irq_time()) ); if ( !(r.status & i_flag_mask) ) { hes_time_t present = time(); if ( irq.timer <= present && !(irq.disables & timer_mask) ) { timer.fired = true; irq.timer = future_hes_time; irq_changed(); // overkill, but not worth writing custom code #if GME_FRAME_HOOK_DEFINED { unsigned const threshold = period_60hz / 30; unsigned long elapsed = present - last_frame_hook; if ( elapsed - period_60hz + threshold / 2 < threshold ) { last_frame_hook = present; GME_FRAME_HOOK( this ); } } #endif return 0x0A; } if ( irq.vdp <= present && !(irq.disables & vdp_mask) ) { // work around for bugs with music not acknowledging VDP //run_until( present ); //irq.vdp = future_hes_time; //irq_changed(); #if GME_FRAME_HOOK_DEFINED last_frame_hook = present; GME_FRAME_HOOK( this ); #endif return 0x08; } } return 0; }
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_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(); }