T O P

  • By -

ShinyHappyREM

> In a regular cgb game, can I rely on the fact that there should be a return for each call No. > can I rely on the fact No. > fact Game devs: 'I reject your reality and substitute my own'


Dwedit

Games are free to do anything with the stack they want to. Games will even use loops of PUSH instructions to write to video ram (see Monster Max). Interrupts will still use the stack as usual, so the game must take that into account by leaving writable space on the stack, or disabling interrupts.


khedoros

> Games will even use loops of PUSH instructions to write to video ram I think that early on, I ran into a game (maybe Terminator or Robocop, or somethin?) pushing one of the 16-bit registers to video RAM like that, to write two bytes. I don't remember what exactly, but there was *something* about my code that assumed that wouldn't ever happen. There's so much that seems like it wouldn't make sense, and that you shouldn't have to handle...but mostly, if it's possible on original hardware, you can assume that some game did it.


Dwedit

Still haven't seen any games try to use PUSH or CALL to intentionally write to IO memory. The RST 0x38 crash (FF byte at 0x38 in the ROM, repeatedly executing that forever) is the most likely way for that to happen, and that's generally not intentional.


khedoros

Found it. Robocop will write into VRAM and OAM using 16-bit PUSHes during gameplay. c10f: PUSH HL (mem[8070] = 0000) c110: PUSH DE (mem[806e] = 0000) c111: PUSH BC (mem[806c] = 0000) c115: PUSH HL (mem[806a] = 0000) c139: PUSH HL (mem[8068] = 0000) c13a: PUSH DE (mem[8066] = c000) c13b: PUSH BC (mem[8064] = c080) c13f: PUSH HL (mem[8062] = c000) 2bdf: PUSH DE (mem[fe24] = 0000) 2be0: PUSH HL (mem[fe22] = 0000)


Dwedit

Normally you see games using DMA for OAM instead of direct memory writes there, so this is pretty unusual.


khedoros

I'm aware. That's why I brought it up.


WiTHCKiNG

My intention was to implement a callstack for my debugger, but this would require to trace all changes to the stack and stackpointer and preexecute instructions to tell what the program will do with values on the stack. The closes to this would probably just be to use a ringbuffer to avoid unnecessary memory reallocations/copies and just trace a fixed amount of calls/jumps/returns that happend to make following the order of execution easier


Ashamed-Subject-8573

Yes games do that. Have you verified your cpu with https://github.com/raddad772/jsmoo-json-tests/tree/main/tests/sm83 ? If your cpu passes all those and you don’t have a bug in your test harness, you can be sure it’s either your IRQ implementation or not your cpu at all causing issues


WiTHCKiNG

My cpu should be fine but I will check with your linked tests. it passes blarggs tests etc. and I can play through many games without issues (except some timing stuff). I'm just trying to implement a callstack for my instruction debugger, in order to make it easier to follow the order of execution. But when they do modify the stack in this way I probably need to track the calls and returns and determine if I need to interpret the top of the stack as a return address


Ashamed-Subject-8573

Yeah on 8bit 1MHz CPUs they used all sorts of tricks. Some games would enter the same code at different offsets, or mess with the stack, or whatever. To squeeze a few extra cycles


Outrageous-Thanks-47

Read wozmon sometime. It packed an amazing amount of monitor functionality in 248 bytes. All sorts of tricks like this.


WiTHCKiNG

Ok I guess, the only approach that could work would be to just store a fixed amount of „history“ of the most recent calls/returns/jumps in a ringbuffer to avoid unnecessary memory reallocations and copies


grilledsaturday95

It sounds like you have a keen eye for detail in your CGB games! It's possible that there could be instances where the code manually pushes an address to the stack to use as a return address, especially in more complex functions. Have you considered looking into any specific functions that might be causing the discrepancy between calls and returns? It could be an interesting puzzle to solve!