Skip to content

Tracking state of DIV register #24

@msinger

Description

@msinger

Hi, after your amazing presentation on Friday, I asked you about the issues with tracking the value of the DIV register. If I recall correctly, the possible issues are:

  • You don't know which value DIV has when the first instruction of the game gets executed, because this is different for each Game Boy model and/or boot ROM version.
  • You might not be able to start tracking the DIV register from the very first clock tick after reset, where it will always start at zero, because you might not be quick enough in setting things up.
  • When the CPU is in HALT mode, the output of the 1 MiHz phi clock is disabled and you can't keep track of the time anymore.

I'm pretty sure the first two points can be solved. If you're really too slow, then this would require a hardware change. The HALT mode issue will be tricky.

When the Game Boy comes out of reset, it uses the DIV register (the full 16 bit, not only the 8 bit you get access to) to count to 0x8000. It counts with 1 MiHz, so it takes ~32 milliseconds to reach that value. When this value is reached, then the 1 MiHz phi clock that you see on the cartridge port starts ticking. Before that, the phi clock is held high, so you can't actually see the very first rising edge, because it is already "risen". The CPU will fetch the first instruction of the boot ROM two phi ticks after the 0x8000 was reached. Here are two GTKWave screenshots from a simulation of the DMG-CPU B chip, showing this scenario:

start_div16_after_reset
(DIV starts counting from 0, when low active reset signal is released. "clk" is the 4 MiHz crystal clock. "phi" is the 1 MiHz clock you see on the cartridge.)

start_cpu_after_div8000
(1 MiHz phi clock starts ticking after DIV reaches 0x8000 for the first time after reset. CPU fetches first instruction shortly after that. "afer" is the high active synchronous reset signal of the SM83 CPU core. "a" and "d" are the chip internal address and data buses, not visible on the cartridge port.)

So, when you start counting from the very first phi clock tick, you should know the exact value of the 16 bit DIV register as long as there is no HALT instruction used by the game. Register FF04 shows you bits 6-13 of those 16 bits (start counting from 0, not 1). When the game resets DIV by writing to 0xFF04, the whole 16 bits get reset to 0, not only bits 6-13. You should also be able to determine the Game Boy model / boot ROM by counting the number of ticks it takes until it reaches the first instruction of the game.

If you are really to slow after detecting that the Game Boy was switched on, and you are missing the first tick of the phi clock, you could address this in a new hardware revision. I saw that you used up all GPIOs already, so you would need to switch to a bigger microcontroller. You can buy yourself as much time as you need, by just driving the reset pin low. You can't do that with those somthing245 level shifters though. It needs to be done with an open drain output. It would also be beneficial to be able to read the reset line, because cartridges like the EverDrive or the Nintendo GB-memory cartridges that were only available in Japan are also pulling at the reset line to boot into the actual game after it was selected in the menu. I don't know if and how you are handling this right now. There is a transistor that is also used for bidirectionally level shifting I2C buses. It's the BSS138. I use it for the Game Boy reset line like this and it works good:
using_bss138

It's too bad that the HALT mode disables the phi clock on the cartridge port. The only solution I see there is to start a timer and measure the time from the HALT instruction until the phi clock is enabled again. The mechanism responsible for generating the 1 MiHz clock from the 4 MiHz is always running internally, only the output is disabled. This means, the timing grid for the 1 MiHz phi clock will be preserved. For example, if phi stops at the 4 MiHz clock tick number 12, it can only resume at clock ticks like 20 or 24 or 28, but not on ticks like 21 or 22, because they are not dividable by four. You could use this information to counter inaccuracies of your locally tracked time while the phi clock is disabled. I don't know how good this would work, but before I heard from you, I wasn't expecting that something like this GB interceptor would work at all. So what do I know...

I was wrong about the boot ROM not using DMA btw. The Game Boy Color boot ROM is using the HDMA. But I didn't understand why this is relevant or if you already talked about something else there.

If you are actually trying to implement accurate DIV tracking in the future, I could help you figuring out the details you need for that.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions