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.

Coding > Modify Program to use memcpy and memset

#65193 - jake2431 - Sat Dec 31, 2005 6:20 am

Hi, I am reading Programming the "Nintendo Game Boy Advance" and one of the challenges is to modify the following code to use memset and memcopy(from string.h).

Code:
#define MULTIBOOT int __gba_multiboot;
MULTIBOOT

//add support for rand function
#include <stdlib.h>

//declare the function prototype
void DrawPixel3(int, int, unsigned short);
void DrawBox3(int,int,int,int, unsigned short);

//declare some defines for the video mode
#define REG_DISPCNT *(unsigned long*)0x4000000
#define MODE_3 0x3
#define BG2_ENABLE 0x400

//changes the video mode
#define SetMode(mode) REG_DISPCNT = (mode)

//packs three values into a 15-bit color
#define RGB(r,g,b) ((r) + (g<<5) + (b<<10))

//create a pointer to the video buffer
unsigned short *videoBuffer = (unsigned short*)0x6000000;

int main(void)
{
    int x1;
    int y1;
    int x2;
    int y2;
    unsigned short color;
   
    SetMode(MODE_3 | BG2_ENABLE);
   
    while(1)
    {
        x1 = rand() % 240;
        y1 = rand() % 160;
        x2 = x1 + rand() % 60;
        y2 = y1 + rand() % 60;
        color = RGB(rand()%31, rand()%31, rand()%31);
       
        DrawBox3(x1,y1,x2,y2, color);
    }
    return 0;
}

void DrawPixel3(int x, int y, unsigned short color)
{
    videoBuffer[y * 240 + x] = color;
}

void DrawBox3(int left, int top, int right, int bottom, unsigned short color)
{
    int x;
    int y;

    for(y = top; y<bottom; y++)
        for(x = left; x < right; x++)
            DrawPixel3(x,y,color);
}


I am having trouble seeing exactly how to do this. If you have the pdf version of this book it is challenge 2 on page 196. Could someone show me how this is done and maybe explain it a little bit?

Thanks
-Jake

#65196 - Dwedit - Sat Dec 31, 2005 7:42 am

This is a poor example, since you can't use memset on 16 bit data. But here is a replacement of DrawBox3 that uses memcpy to copy the previous row drawn.

Code:

const int screen_width = 240; //hardcoded numbers = headaches when you change them, so make them constants

void DrawBox3(int left, int top, int right, int bottom, unsigned short color)
{
    unsigned short *on_video;
    int x;
    int y;
    int width=right-left;
    int height=top-bottom;

    if (height<=0) return;
    //address in video memory = base + y*screen_width + x
    on_video = videobuffer + top * screen_width + left;
   
    //draw first row manually
    for (x = 0; x < width; x++)
    {
        on_video[x]=color;
    }

    for (y = 1; y < height; y++)
    {
        //copy previous rows
        on_video+=screen_width;
        memcpy(on_video,on_video-screen_width,width*sizeof(unsigned short));
    }
}

_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."

#65208 - Cearn - Sat Dec 31, 2005 4:39 pm

Unfortunately, that might not work either, partially for the same reasons.

The reason memset doesn't work is because the input is always in bytes, so it'd never work for 16 or 32 bit data anyway. In principle this wouldn't matter for memcpy because data is just data, except for that little problem concerning VRAM and byte copies. The exception to this is when the copy can be optimised, which is possible when a) then size is over 16 bytes (and possibly a multiple of 4, can't remember right now) and b) the source and destination addresses are word aligned. Which for a general mode 3 plotter won't be the case.

Your best bet would be to create your own 16 and 32 bit versions of memset/memcpy, or nick someone elses. Or use DMA.

#65210 - jake2431 - Sat Dec 31, 2005 7:10 pm

Oh, okay. Thanks guys for your help. I think I will just continue reading the book for now and maybe come back to it later since it is not something that is going to really help right now.

Also, though, in the book he taught me how to write a few functions that would display hard coded text of his design. This was interesting and will most definetly help in the development of games. However, the third challenge on the same page as mentioned above was to make this text count how many randomly placed objects were being displayed on the screen. Now, my first idea was to put a variable++ in the loop that displayed the random objects along with our Print function and use ("%d", variable++); to diplay the number of objects(like with the stdio.h heder file). But with the arguments "Print(int,int,char *,unsigned short) //unsigned short being the color" I don't see how to accomplish this. Any idea? If you need to see the entire DisplayText code just let me know.

#65223 - tepples - Sun Jan 01, 2006 2:21 am

Look up sprintf to see what it does.

[commercial break]

Now you know what sprintf(char *, const char *, ...) does. But on the GBA, it's called something different: siprintf(). The 'i' means integer-only so that you don't bring in the large, slow floating-point arithmetic library.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.