February 15th, 2015, 19:10
You'll probably have googled it by now, but just in case you haven't, breakpoints are essentially points in the code where you tell your program to stop once certain conditions are true. This allows you to halt the program and examine its current state. The most common forms of breakpoints for emulator debugging are ones that involve the PC. That is to say, whenever you set a PC breakpoint, the emulator will run normally until the PC = whatever value you want. This is very helpful since it allows you to potentially skip hundreds of instructions that are of no interest to you. With breakpoints, you wouldn't have to run your emulator instruction by instruction to reach every VBLANK, for example. Just tell it to stop whenever the PC == 0x40 and print the registers/other info you want, while ignoring the thousands of other instructions that happened in between. The point of this is to find out when you are getting weird results and then trace it backwards to the source. It's very much a game of hide and seek, really. Some bugs are pesky and obscure
Good luck by the way.
February 16th, 2015, 15:25
Ok, so I checked and it seems all roms have a jump instruction in PC = 0x40 and it seems its updating data from the registers 0xFF** and probably vRAM (there are many subrutine calls). I assume that whenever a vertical blank happens (i.e. every 17556 cycles approximately) a CALL 0x40 instruction will happen. This would be approximately 6000 instructions at an average of ~3 cycles/instruction. Hence, if I set a breakpoint there, I would need to debug this many instructions when I find mismatching register values.
Are my assumptions correct? If so, isn't there another way to go forward by, say only 500 instructions? It's easy to implement in my emulator, but it seems that BGB only stops at breakpoints defined by the PC. And I don't know if there is another address that happens more or less this often as an instruction.
- - - Updated - - -
Also, what is a good way to stop the dispatch loop? I am using scanf() but this makes the render and debug windows difficult to move and sometimes windows complains that the program is not answering. Is there any other simple way?
February 16th, 2015, 16:03
Here's what I would do. First, find out how many VBLANKs it takes for the issue to appear (if it happens after the first couple or VBLANKs that's great). You only need to check the VBLANK breakpoint and look at the registers. Once you have narrowed it down, i.e. the problem occurs between VBLANKs 5 and 6 for example, it's time to do some digging.
Ask yourself what it is you should be looking at. VRAM is a good target in your case. When does the game write to VRAM? Your black screen issue sounds like you're not writing to VRAM when you should, or you're writing incorrect values. BGB can break whenever it writes to memory areas you define; just go to Debug -> access breakpoints (format is xxxx-yyyy for the range, leave the value blank to catch any write). See where BGB hits this code and what happens in your emulator, then work your way back.
About stopping your emulator, I always used C++'s std::cin (for console input). It always halts the program until it receives input. Dunno if that's comparable to scanf() as I don't use a lot of C.
Last edited by Shonumi; February 17th, 2015 at 02:54.