Just how common is it... (coding question)

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

Post Reply
powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Just how common is it... (coding question)

Post by powerofrecall » Wed Sep 18, 2013 2:43 am

Just how common is it for an MD game to do all of its processing in the vblank interrupt?

I am disassembling the Japanese version of Rocket Knight Adventures and (thanks to IDA and Exodus's active disassembly feature! Thanks Nemesis!) made good progress at separating code from data with the exception of a few jump tables and pre-calculated address register jumps that I'm working backwards to solve. That's neither here nor there, however.

You guys may well know some of this already but here's what I've picked apart that struck me as a little strange:
The main code path ends with:
0003C6 bra $3c6
It just spins here, all the game code is called from the vblank interrupt. Doesn't this have a HUGE execution time cost in terms of wasted cycles? Isn't there more available time outside of vblank?

The H-interrupt vector is a pointer into RAM, I'm guessing so it can quickly switch pointers for horizontal interrupt routines, the game does a lot of linescroll FX & mid frame palette stuff as you probably know. What is weird to me is so far I can't see any pointers at that RAM location (in Regen).

The entire code path is apparently based on a huge jump table with smaller tables sprouting from that. It looks well engineered from that perspective, I get the feeling they actually engineered the code flow rather than just sitting down and banging out a game. Konami seems pretty professional.

The game loads small bits of code into RAM and jumps to them. Most of the time from what I'm able to observe it just loads the RTS opcode in there and comes right back out of the code in RAM. The game appears to have reserved a small RAM bank just for code but don't quote me on that yet. Is there any real benefit to this? I know in theory you could self modify code but that seems kind of both difficult and not really necessary on the 68k.

To me (and I'm not as experienced in 68k as many of you guys I'm sure) a lot of the attempts at streamlining and optimization seem silly when they are intentionally avoiding doing any processing outside vblank. What do you guys think?

Charles MacDonald
Very interested
Posts: 292
Joined: Sat Apr 21, 2007 1:14 am

Re: Just how common is it... (coding question)

Post by Charles MacDonald » Wed Sep 18, 2013 3:23 am

It just spins here, all the game code is called from the vblank interrupt. Doesn't this have a HUGE execution time cost in terms of wasted cycles? Isn't there more available time outside of vblank?
The CPU isn't really restricted to processing within the V-Blank time (38 scanlines or so). Once the interrupt starts, it has a complete frame's worth of time before the next interrupt is triggered. That's the same amount of time if you were updating the game out of the main loop.

Consider that when the interrupt is processed the game does two things:

1. (Immediately after the interrupt) - Update video to reflect the game state that was calculated in the previous interrupt.
2. (After the video updates) - Start calculating the game state for the next interrupt.

Step #1 finishes within the V-Blank time (38 scanlines or so), step #2 has the remainder of the frame (224 scanlines) until the next interrupt to complete. Since Rocket Knight has slowdown, we know in some cases it needs more than a frame of time to process things and the next interrupt is not handled. So all the time available is being used and then some.

I think the advantage of this method is that when using a main loop to update your game, you never know if the main loop code is running during the active display or V-Blank. If you want to update the display state, you end up having to poll a flag in memory that the V-Blank interrupt routine sets, which just wastes time. Or you have to partition video data into an 'active' and 'next' list so you can update data like sprite lists or scroll registers without changing the current display in the main loop, and let the V-Blank routine swap those data elements and make the update to the video registers for the next frame.

With the V-Blank driven method, as soon as the interrupt triggers you know you are in V-Blank and can do all the critical off-screen updates first. Once that's done, you have all the time left until the next interrupt to do anything you want, like calculate the game state for the next frame. If you are out of things to do, just RTE and idle. This way there's no polling and waiting to get into V-Blank.

I've seen this method used in a lot of Sega arcade games so it seems common enough. It does make of the structure of the game code harder to follow because you end up using a lot of jump tables and function pointers which sounds like what you're seeing too.

powerofrecall
Very interested
Posts: 237
Joined: Fri Apr 17, 2009 7:35 pm
Location: USA

Re: Just how common is it... (coding question)

Post by powerofrecall » Wed Sep 18, 2013 7:18 am

Charles MacDonald wrote: The CPU isn't really restricted to processing within the V-Blank time (38 scanlines or so). Once the interrupt starts, it has a complete frame's worth of time before the next interrupt is triggered. That's the same amount of time if you were updating the game out of the main loop.
I have no idea why it never occurred to me, but this makes sense! It's just a structurally different way to go about the same thing. Like you said the jump tables make stuff a little harder to follow because it's almost like every vblank you are starting execution again from the "top" and solving that maze. I think what shocked me a bit was doing some traces and seeing how much time it was spending just spinning in a loop, but looking at it from this angle it was just idle time anyway. Makes sense.

I was also a little confused because I have done some disassembly of other games and seen them do the flag polling method, but the games I've seen it in were almost certainly written in C or some other higher level language (just guessing, but seeing function arguments passed on the stack rather than registers and poor address register usage make me think that).

I still think the rest of the RKA's weirdness/uniqueness is going to be fun to figure out. I'm really curious about the code-in-RAM thing, I don't know how common that is on genesis games. I'm still aiming for creating a more functional disassembly though. I'd love to have a re-buildable split-disassembly of RKA to tinker with!

tomaitheous
Very interested
Posts: 256
Joined: Tue Sep 11, 2007 9:10 pm

Post by tomaitheous » Sat Sep 21, 2013 2:03 pm

Some NES games are like this as well (I think the first SMB game is like this).

Post Reply