#ifdef CPU_CPP void CPU::queue_event(unsigned id) { switch(id) { case QueueEvent::DramRefresh: return add_clocks(40); case QueueEvent::HdmaRun: return hdma_run(); case QueueEvent::ControllerLatch: return ppu.latch_counters(); } } void CPU::last_cycle() { if(status.irq_lock) { status.irq_lock = false; return; } if(status.nmi_transition) { regs.wai = false; status.nmi_transition = false; status.nmi_pending = true; } if(status.irq_transition || regs.irq) { regs.wai = false; status.irq_transition = false; status.irq_pending = !regs.p.i; } } void CPU::add_clocks(unsigned clocks) { if(status.hirq_enabled) { if(status.virq_enabled) { unsigned cpu_time = vcounter() * 1364 + hcounter(); unsigned irq_time = status.vtime * 1364 + status.htime * 4; unsigned framelines = (system.region() == System::Region::NTSC ? 262 : 312) + field(); if(cpu_time > irq_time) irq_time += framelines * 1364; bool irq_valid = status.irq_valid; status.irq_valid = cpu_time <= irq_time && cpu_time + clocks > irq_time; if(!irq_valid && status.irq_valid) status.irq_line = true; } else { unsigned irq_time = status.htime * 4; if(hcounter() > irq_time) irq_time += 1364; bool irq_valid = status.irq_valid; status.irq_valid = hcounter() <= irq_time && hcounter() + clocks > irq_time; if(!irq_valid && status.irq_valid) status.irq_line = true; } if(status.irq_line) status.irq_transition = true; } else if(status.virq_enabled) { bool irq_valid = status.irq_valid; status.irq_valid = vcounter() == status.vtime; if(!irq_valid && status.irq_valid) status.irq_line = true; if(status.irq_line) status.irq_transition = true; } tick(clocks); queue.tick(clocks); step(clocks); } void CPU::scanline() { synchronize_smp(); synchronize_ppu(); synchronize_coprocessor(); system.scanline(); if(vcounter() == 0) hdma_init(); queue.enqueue(534, QueueEvent::DramRefresh); if(vcounter() <= (ppu.overscan() == false ? 224 : 239)) { queue.enqueue(1104 + 8, QueueEvent::HdmaRun); } if(vcounter() == input.latchy) { queue.enqueue(input.latchx, QueueEvent::ControllerLatch); } bool nmi_valid = status.nmi_valid; status.nmi_valid = vcounter() >= (ppu.overscan() == false ? 225 : 240); if(!nmi_valid && status.nmi_valid) { status.nmi_line = true; if(status.nmi_enabled) status.nmi_transition = true; } else if(nmi_valid && !status.nmi_valid) { status.nmi_line = false; } if(status.auto_joypad_poll_enabled && vcounter() == (ppu.overscan() == false ? 227 : 242)) { input.poll(); run_auto_joypad_poll(); } } void CPU::run_auto_joypad_poll() { uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0; for(unsigned i = 0; i < 16; i++) { uint8 port0 = input.port_read(0); uint8 port1 = input.port_read(1); joy1 |= (port0 & 1) ? (0x8000 >> i) : 0; joy2 |= (port1 & 1) ? (0x8000 >> i) : 0; joy3 |= (port0 & 2) ? (0x8000 >> i) : 0; joy4 |= (port1 & 2) ? (0x8000 >> i) : 0; } status.joy1l = joy1; status.joy1h = joy1 >> 8; status.joy2l = joy2; status.joy2h = joy2 >> 8; status.joy3l = joy3; status.joy3h = joy3 >> 8; status.joy4l = joy4; status.joy4h = joy4 >> 8; } #endif