gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > Timer Routine - Anyone?

#160229 - zodiacdagreat - Sat Jul 12, 2008 10:25 am

Um, can someone make me a ASM timer routine for gba that does this - A count down timer, which starts at (User Defined Time - Minutes/Secs) when it reaches 0, it'll set a variable to a certain value. Will the game freeze when the routine is running? Cause I need one that doesn't freeze the game while counting down.

#160230 - silent_code - Sat Jul 12, 2008 10:30 am

You should take a look at timer interrupts. ;^)
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.

#160244 - Miked0801 - Sat Jul 12, 2008 7:41 pm

Again why asm? If asm, define 4 bytes in memory and set it to user defined minutes * 3600 + user defined seconds * 60. Decrement once per vblank. At 0, set your other variable in vblank. The same code in C is 4 lines or so long.

#160251 - sgeos - Sat Jul 12, 2008 9:19 pm

In this day and age, nobody hand codes assembler unless they really need to.
I would write this in C, see what the compiler does with it and then hand optimize it from there if you really need to.
I would probably use something like this:
Code:
#define TRUE    1
#define FALSE   0
#define FRAMES_PER_SECOND       60
#define FRAMES_PER_MINUTE       3600

// Max time is 18 minutes, 12 seconds, 15 frames
void initializeCountDownAndSetInt
(
        int *           pActive_Ptr,
        unsigned int *  pTimer_Ptr,
        int             pMinutes,
        int             pSeconds,
        int             pFrames
)
{
        *pActive_Ptr = TRUE;
        *pTimer_Ptr = pFrames +
                FRAMES_PER_SECOND * pSeconds +
                FRAMES_PER_MINUTE * pMinutes;
}

void countDownAndSetInt
(
        int *           pActive_Ptr,
        unsigned int *  pTimer_Ptr,
        int *           pTarget_Ptr,
        int             pTargetValue
)
{
        if ( FALSE == *pActive_Ptr )
                return;

        if ( 0 < *pTimer_Ptr )
        {
                (*pTimer_Ptr)--;
        }
        else
        {
                *pActive_Ptr = FALSE;
                *pTarget_Ptr = pTargetValue;
        }
}


For what it's worth, this is the PC side scaffolding code I used to test the timer code:
Code:
#include <stdio.h>

// never do this in production code (I was too lazy to create a header)
#include "timer.c"
// end never do this

// Max time is 18 minutes, 12 seconds, 15 frames
#define MINUTES 1
#define SECONDS 2
#define FRAMES  15
#define PRESET  FALSE
#define POSTSET TRUE

void display_status(int pActive, int pTimer, int pTarget)
{
        if (pActive)
                printf("running @ 0x%04X; target -> %d\n", pTimer, pTarget);
        else
                printf("stopped @ 0x%04X; target -> %d\n", pTimer, pTarget);
}

int main(void)
{
        // These need to live somewhere...
        int             active;
        unsigned int    timer;
        int             target = PRESET;

        // Initialize like this...
        initializeCountDownAndSetInt(&active, &timer, MINUTES, SECONDS, FRAMES);

        // Make sure everything went as planned...
        display_status(active, timer, target);

        // Dummy game loop for testing...
        while (active)
        {
                // Call like this...
                countDownAndSetInt(&active, &timer, &target, POSTSET);

                // Keep tabs on progress...
                display_status(active, timer, target);
        }

        // Make sure the timer has stopped...
        target = PRESET;
        int i;
        for (i = 0; i < 3; i++)
        {
                countDownAndSetInt(&active, &timer, &target, POSTSET);
                display_status(active, timer, target);
        }
        return 0;
}

Of course, all of this could be done with structs or even objects if you prefer C++ as a design language.

If your goal is to learn ASM, I suspect there are some ASM tutorials out there, but I have not looked in ages.

-Brendan

EDIT: I botched the max time. The ceiling is so high there is no need to worry about it. Related to that, the test display routine should really say 0x%08X instead of 0x%04X. None of this breaks the code posted.

#161363 - zodiacdagreat - Fri Aug 01, 2008 11:15 pm

Quote:
#define TRUE 1
#define FALSE 0
#define FRAMES_PER_SECOND 60
#define FRAMES_PER_MINUTE 3600

// Max time is 18 minutes, 12 seconds, 15 frames
void initializeCountDownAndSetInt
(
int * pActive_Ptr,
unsigned int * pTimer_Ptr,
int pMinutes,
int pSeconds,
int pFrames
)
{
*pActive_Ptr = TRUE;
*pTimer_Ptr = pFrames +
FRAMES_PER_SECOND * pSeconds +
FRAMES_PER_MINUTE * pMinutes;
}

void countDownAndSetInt
(
int * pActive_Ptr,
unsigned int * pTimer_Ptr,
int * pTarget_Ptr,
int pTargetValue
)
{
if ( FALSE == *pActive_Ptr )
return;

if ( 0 < *pTimer_Ptr )
{
(*pTimer_Ptr)--;
}
else
{
*pActive_Ptr = FALSE;
*pTarget_Ptr = pTargetValue;
}
}

Finally its been so long - it took me quite a while to understand at least to a extent. Um, I have one more request, could you make a same code like this, making it do this:

-Countdowntime of 3mins
-When countdown is done, 0x2022000 is 1
-and make this timer routine invisible like it doesn't freeze the game.

So, with these two , I can compare the differences and make my own. Please help.