strcpy(blog_title, witty_saying)
//what a dirty hack

Sep/09

29

Brewing the Nintendo DS from the comfort of the home, Part 2

Well my first version of the dice roller has turned out to be very easy to produce. I initially wanted to stay away from any graphics code and devkitPro provides a good avenue for that in the form of a console that supports ANSI escape codes. A built-in on-screen keyboard can be used for user input and access to the SLOT-1 device’s filesystem is accessible through the standard C I/O functions (fopen, getc etc.).

Here’s a basic overview of the code:

main.c

int main(int argc, char ** argv) 
{
    PROGRAM_STATE pState = MENU;
    touchPosition touch;
    consoleDemoInit();
    filesystem_init();

consoleDemoInit() is a libnds function that initialises the DS’ displays for console only display. filesystem_init() calls the libndsfat function fatInitDefault() to initialise the filesystem and if successful reads from a config file on the SLOT-1 device.

    for(;;)
    {
        //update input state
        scanKeys();
        touchRead(&touch);
 
        switch (pState)
        {
        case MENU:
            menu_draw();
            switch(menu_handleinput(&touch))
            {
            case 0:
                pState = CONFIG;
                break;
            case 1:
                pState = ROLLER;
                break;
            }
            break;
 
        case CONFIG:
            config_draw();
            if (config_handleinput(&touch) == -1)
                pState = MENU;
            break;
 
        case ROLLER:
            roller_draw();
            if (roller_handleinput(&touch) == -1)
                pState = MENU;
            break;
        }
        swiWaitForVBlank();
        consoleClear();
    }
    return 0;
}

The second part of the main function is the program loop. It is a simple state machine that has three states, a main menu, a configuration menu and the roller itself.
The first couple of function calls each loop are to libnds functions that update the user input state, scanKeys() for button presses and touchRead(&touch) for the touchscreen’s currently pressed coordinates. Each state then has a draw function and a handleInput function.

Finally there are another couple of calls to libnds. The first (swiWaitForVBlank()) blocks the program until the VBlank interrupt is triggered indicating that the screen has finished drawing. The second (consoleClear()) clears the console with an ANSI escape sequence.

menu.c

void menu_draw(void)
{
    int i;
    iprintf("\x1b[2;2H");
    iprintf("Welcome to DS Dice Roller\n");

This is the menu drawing function. iprintf is used rather than printf to avoid any inadvertent formatting of floats. The “\x1b[” string is the ANSI control sequence indicator and is followed by the row and the column of the desired position of the cursor.

int menu_handleinput(touchPosition * touch)
{
    int keys = keysDown();

keysDown() is a libnds function that returns an integer that is a bitwise OR of the current buttons pressed by the user. It is masked off to find the status of the buttons.

config.c

void config_numberinput(int * n, int max, Keyboard ** k)
{
    int key;
    if (!*k)
    {
        *k = keyboardDemoInit();
    }
    if (!(*k)->visible)
        keyboardShow();
 
    key = keyboardUpdate();
    if (key == '\b')
        *n /= 10;
 
    if (key >= '0' && key <= '9')
    {
        *n *= 10;
        *n += key - '0';
        if (*n > max) *n = max;
    }
 
    if (key == '\n')
    {
        keyboardHide();
        if (filesystemInitialised)
        {
            char buf[8];
            int n;
            FILE * f = fopen("diceconfig.bin", "wb");
            n = snprintf(buf, 8, "%d\n%d", num_sides, num_dice);
            if (n > 8) n = 8;
            if (f != NULL)
            {
                fwrite(buf, 1, n, f);
                fclose(f);
            }
        }
        cState = CONFIG_SELECTION;
    }
}

The only other interesting function. keyboardDemoInit() is called once to initialise the default on-screen keyboard. keyboardShow() displays the keyboard and keyboardUpdate() returns the ASCII character that represents the key pressed. As you can see, writing the results to storage is a simple matter of calling the appropriate C I/O functions.

Next on the schedule is the interesting part, actually rendering something other than text on the screen.

Up to date source code for the project can be cloned from the project site on Github or if you don’t use Git, can be downloaded from here.

·

No comments yet.

Leave a Reply

>>

Theme Design by devolux.nh2.me

 

September 2009
M T W T F S S
« Jul    
 123456
78910111213
14151617181920
21222324252627
282930