//70224 clocks/frame // 456 clocks/scanline // 154 scanlines/frame #ifdef CPU_CPP #include "opcode.cpp" void CPU::add_clocks(unsigned clocks) { system.clocks_executed += clocks; if(system.sgb()) scheduler.exit(Scheduler::ExitReason::StepEvent); status.clock += clocks; if(status.clock >= 4 * 1024 * 1024) { status.clock -= 4 * 1024 * 1024; cartridge.mbc3.second(); } //4MHz / N(hz) - 1 = mask if((status.clock & 15) == 0) timer_262144hz(); if((status.clock & 63) == 0) timer_65536hz(); if((status.clock & 255) == 0) timer_16384hz(); if((status.clock & 511) == 0) timer_8192hz(); if((status.clock & 1023) == 0) timer_4096hz(); lcd.clock -= clocks * lcd.frequency; if(lcd.clock <= 0) co_switch(scheduler.active_thread = lcd.thread); apu.clock -= clocks * apu.frequency; if(apu.clock <= 0) co_switch(scheduler.active_thread = apu.thread); } void CPU::timer_262144hz() { if(status.timer_enable && status.timer_clock == 1) { if(++status.tima == 0) { status.tima = status.tma; interrupt_raise(Interrupt::Timer); } } } void CPU::timer_65536hz() { if(status.timer_enable && status.timer_clock == 2) { if(++status.tima == 0) { status.tima = status.tma; interrupt_raise(Interrupt::Timer); } } } void CPU::timer_16384hz() { if(status.timer_enable && status.timer_clock == 3) { if(++status.tima == 0) { status.tima = status.tma; interrupt_raise(Interrupt::Timer); } } status.div++; } void CPU::timer_8192hz() { if(status.serial_transfer && status.serial_clock) { if(--status.serial_bits == 0) { status.serial_transfer = 0; interrupt_raise(Interrupt::Serial); } } } void CPU::timer_4096hz() { if(status.timer_enable && status.timer_clock == 0) { if(++status.tima == 0) { status.tima = status.tma; interrupt_raise(Interrupt::Timer); } } } void CPU::hblank() { if(status.dma_mode == 1 && status.dma_length) { for(unsigned n = 0; n < 16; n++) { bus.write(status.dma_target++, bus.read(status.dma_source++)); add_clocks(4); } status.dma_length -= 16; } } #endif