Page 1 of 1

Main Program Loop (design)

Posted: Fri May 20, 2011 4:57 pm
by Dr. Floppy
Okay, I've got a working title screen upon startup. Now it's time to go somewhere with it. The flowchart for Project Alpha dictates that there are only two ways out of the Title Screen, the main one being pressing Start to transition to Level Zero. Since Level Zero represents actual gameplay, the time has come to get serious about the Main Program Loop (which is currently just a frame counter).

After considering various approaches, I've drafted the following as my tentative blueprint:

1) Music/Sound Updates (tail-end of NMI)
2) Frame Counter Advance
3) Transition Check:

Are we transitioning? This will be determined by a zero-page status byte normally set to zero (null). #01 = Activate Transition, which JSR's to a special handling routine. #FF = Transition-in-progress, which JMP's to the upkeep handler part of that routine.

This will handle stuff like the Title Screen --> Level Zero fade-out/fade-in sequence, transitions to and from the status subscreen, transitions between levels and perhaps even transitions within them (horizontal area to vertical area, etc.).

4) Mode-Specific Branching

This is the one I'm most curious about, as it's either really right or really wrong. I figured that because not every part of the game is going to require the same checks & updates, it could be advantageous to have multiple versions of the MPL (with the branch point positioned after all of the "universal" stuff).

Branching is based on the current "macromode", of which I've determined six: title screen, active gameplay, subscreen, password screen, game over screen, ending/credits. (Ironically, the first thing I've got down for each branch is a check on controller input...)

These roads will all converge in the end, if only to experience the timeless delight of "A9-00-F0-FC".

Posted: Sat May 21, 2011 1:02 pm
by Ian A
Rather than branching, I have multiple main loops and a variable to select which one to use. Here's an example:

Code: Select all

TileMain:
       jsr DoSomeCrap
       jsr DoMoreCrap
       jmp WaitForNMI

GameMain:
       jsr DoSomeCrap
       jsr DoCompletelyDifferentCrap
       jmp WaitForNMI

WaitForNMI:
       ;; wait for nmi code
       jmp (mainloop)
There are some obvious disadvantages to this, and it may not work for you, but it is much easier for me to maintain and a million times easier for me to read.

YMMV

Posted: Sat May 21, 2011 4:29 pm
by tokumaru
I agree with the idea of multiple main loops (and even multiple NMIs) rather than only one loop with lots of branching.

In my game, I have a main loop for each part, and each part can activate a different NMI routine. The simpler parts use a basic NMI handler that just signals the start of VBlank, but the main engine needs a custom, much more complex routine.

Posted: Sat May 21, 2011 5:45 pm
by Dr. Floppy
tokumaru wrote:I agree with the idea of multiple main loops (and even multiple NMIs) rather than only one loop with lots of branching.

In my game, I have a main loop for each part, and each part can activate a different NMI routine. The simpler parts use a basic NMI handler that just signals the start of VBlank, but the main engine needs a custom, much more complex routine.
Perhaps I erred in my description; by "branching", I merely meant that the MPL jumps to whatever specialized loop is appropriate based upon the current macromode. (The actual command is $6C-18-00.) Conceptually, the design somewhat resembles the space lab from Metroid Fusion:

Image

To conserve space, I merely put all the universal stuff like music, frame counter & transition check (violet, gray & red disks) prior to the actual MPL branching point (green thing). From that point onward, it's all macromode-specific stuff (the six colored cylinders). At the end of each MPL will be a JMP command which will converge all six MPL's upon a singular location that loops upon itself until the NMI (as opposed to having half a dozen different self-looping commands scattered throughout the ROM).

The specialized NMI concept greatly intrigues me.

Posted: Sat May 21, 2011 5:53 pm
by 3gengames
If you hardcode all your routines, you'd better get it right the first time.

Posted: Sat May 21, 2011 10:34 pm
by Dr. Floppy
3gengames wrote:If you hardcode all your routines, you'd better get it right the first time.
I usually do. But just to be safe, I tend to work on one specific thing at a time. That way, I can better gauge what's going wrong (and where).

To wit, I just got the Socktopus up and moving around on my title screen demo. During testing, I decided I wanted to double his speed, so I updated the four movement commands. After this, one of his tentacles kept flying off at double the speed as everything else. A cursory analysis revealed that I'd forgotten to update a BPL-operand. That stray tentacle was actually moving correctly; it was everything else that was dragging, all because #F7 should've been #F4!

Posted: Sun May 22, 2011 11:45 am
by 3gengames
You need to get an assembler. :wink: Sorry, but you won't get very far without one.

Posted: Sun May 22, 2011 6:09 pm
by Dr. Floppy
3gengames wrote:You need to get an assembler. :wink: Sorry, but you won't get very far without one.
Then it's a foregone conclusion...

I don't suppose I get to participate in the betting pool over when the prophecy is fulfilled?

(And here I was looking forward to mapping everything out on my personal wiki!)

Posted: Mon May 23, 2011 3:57 pm
by Celius
For my game, I have a couple of main loops. But I access them all from a universal main loop:

MainLoop:
jmp ($xxxx)
LoopReturn:
inc LoopCount
lda vblCount
-
cmp vblCount
beq -
jmp MainLoop


I just stick whatever main loop address I want in RAM, and jump to that. Within my most frequently used main loop, I have one indirect jump like this which usually points to hardcoded routines for event handling.