How to get timings right?

Discussion of programming and development for the original Game Boy and Game Boy Color.
Post Reply
mnemonix84
Posts: 1
Joined: Thu Jun 16, 2022 5:54 am

How to get timings right?

Post by mnemonix84 »

Hello all,

I'm currently writing my first (Gameboy) emulator and have a few questions for you. At the moment I am trying to get the timings for the CPU instructions correct. I already assumed that they are correct. However, the blargg timing test for the CPU instructions tells me something different. Unfortunately I have no idea what the problem could be. The following tests ran successfully: blargg tests for all CPU instructions, mooneye timer and first memory timing tests. blargg's CPU timing test always gives me the following output:

Code: Select all

00:254-1 01:0-3 02:255-2 03:255-2 04:254-1 05:254-1 06:255-2 07:254-1 08:2-5 09:255-2 0A:255-2 0B:255-2 0C:254-1 ...

Instruction byte : Actual timing - Target timing
It seems like the timings are 3 M-cycles back (unsigned wrap-around)? Does anyone have any idea what this could be?

Attached are some other questions that came to me while writing the timer:

1. The Pan Docs documentation states that if there is a TIMA overflow, the TMA reload and also the interrupt request is delayed by 4 T-cycles. However, how does this behave when the overflow happens in the middle of an M-cycle? Is this then still 4 T-cycles? Or does this shorten and the TMA reload happens already at the beginning of the next M-cycle?

2. If a TMA reload happens in parallel to a CPU memory read access? Is this immediately visible to the CPU or only in the next M-cycle? This would conflict in my case, for example, because I normally handle this as follows:

Code: Select all

read_byte()
{
    read_byte_from_memory()
    cycle(4) // 4 T-cycles, timer, LCD/PPU, etc.
}
However, a test did not run with this. So I had to solve this in the following way, that the correct value is read from memory.

Code: Select all

read_byte()
{
    cycle(1)
    read_byte_from_memory()
    cycle(3)
}
3. How is this generally with visibilities of CPU write/read accesses with all the parallel subsystems? When does which subsystem see what within an M-cycle or T-cycle?

4. Do you guys have any other tips on how to get a Gameboy reasonably (doesn't have to be 100% perfect) cycle accurate?

Thanks in advance for your answers.
Post Reply