Basically I'm redeveloping an NES emulator and improving on the old one I wrote by adding accurate cycle timing. So basically, from all the docs and nes.wikis I've read, each scanline that is fired lasts for exactly 113.666666666667 cpu cycles, which is basically 341 ppu cycles divided by 3 since ppu cycles are 3 times faster than cpu cycles. Now with that said, that would mean for every cpu cycle, it cycles through 3 pixels. To get through each cycle of 113.666666666667 which is 113 of them per scanline, that would mean that each cpu cycle moves at a rate of 1.00589970501475 cycles, which is derived from 113.666666666667 / 113. Cpu cycles are fired from 6502 instructions. Some instructions have 2 to 7 cpu cycles, and some cycles are even added when it exceeds a page boundary. At the moment, I have it coded to where each 6502 instruction called goes through a do loop cycling through each cycle until it exceeds the number of cycles they are capable of. For example, if ADC Absolute is called, which as 4 cycles, it will do like so:
Code: Select all
void MOS6502::Fire_Opcode(byte opcode) {
switch(opcode){
....
Case ADC_ABSOLUTE: cpu.instruction.ADC.Absolute(cpu.address); break;
....
}
}
void MOS6502::Execute() {
while (true) {
if (cpu.paused == false) {
opcode = Read_Memory(Registers::pc);
Fire_Opcode(opcode);
ppu.Fire_Scanline();
}
}
}
void PPU::Fire_Scanline() {
ushort temp_scanline_cycle = 0;
do {
temp_scanline_cycle++;
scanline_cycle += ppu.NTSC_CPU_CYCLE_SPEED_FOR_SCANLINE;
ppu_cycle_position += (ppu.NTSC_CPU_CYCLE_SPEED_FOR_SCANLINE * 3.0);
if (scanline_cycle > cpu.NTSC_CPU_CYCLES_PER_SCANLINE) {
// Render scanline here
ppu_cycle_position = 0.0;
scanline_cycle = static_cast<double>(static_cast<int>(scanline_cycle) % static_cast<int>(cpu.NTSC_CPU_CYCLES_PER_SCANLINE)); // Loop it back to the beginning
scanline++; // Add a scanline
}
if (scanline > ppu.NTSC_TOTAL_PICTURE_HEIGHT) {
scanline = 0;
ppu.cycles = 0;
scanline_cycle = 0.0000000000;
}
} while (!(temp_scanline_cycle >= cpu.cycle_list[opcode]));
}
1 of 4
2 of 4
3 of 4
4 of 4
Then it exits the do loop and fires the next 6502 instruction over, and over, until ultimately, it reaches the end of the scanline.
Now on to the question and my point. Most of the time the cpu cycles end up over exceeding the scanline and carry over to the next scanline. But somehow I feel this is wrong:
Scanline 0:
1 of 4 at cpu cycle 112
2 of 4 at cpu cycle 113
Scanline 1:
3 of 4 at cpu cycle 1
4 of 4 at cpu cycle 2
fire next instruction
1 of 2 at cpu cycle 3
2 of 2 at cpu cycle 4
....
....
If the cycles surpass a scanline or even a frame, do they get reset or carry over. Thanks in advance.
