Homebrew Draw pixels code

ground

Well-Known Member
OP
Member
Joined
Mar 22, 2007
Messages
907
Trophies
0
XP
597
Country
Netherlands
hello,

I wanted to create some homebrew for a while now, so i started learning c(++). Now I am at the point where I understand most of it, and i got a good working menu(and the 3ds).

But now i wanted to draw a single pixel on the 3ds bottom screen, and the troubles start, as both the location and color are off. I am using the following code(which i found on several homebrew apps).

void drawpixel(int i)
{
u8* screen;
screen = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
char r= 0xff;
char g= 0x00;
char b = 0x00;
int height = 240;
u32 v = (height-1-i+i*height)*3;
screen[v] = b;
screen[v + 1] = g;
screen[v + 2] = r;
}
(I know this code can be much shorter, but i wrote a lot out as i try to solve this problem.

i call this function with a for loop, so it should draw a diagonal line in the screen (starting at 1,1). But Here is where it is getting weird, The first diagonal line starts at 1,1, is yellow. the second line starts halfway down the y as and is blue, the third line starts at a quarter of the x as and is blue too (all lines stop halfway at the x as).

can someone explain what I am missing here(my guess is at the screen getframebuffer, but i cant get what).

thanks in advance.
 

Cyan

GBATemp's lurking knight
Former Staff
Joined
Oct 27, 2002
Messages
23,749
Trophies
4
Age
46
Location
Engine room, learning
XP
15,662
Country
France
If the color is wrong it means you are a byte off.
BBGGRR BBGGRR
0000FF 0000FF what you want
00FFFF 00FFFF what you get (yellow)(doesn't make sense, even if it was shifted you should have 2 bytes at 0x00)
FF0000 FF0000 what you get (blue)

and your position seems wrong:
To make a diagonal, shouldn't it be:
(i*height-height+i) ?

sorry if all this is wrong, just thought about it for 2 mins

edit:
ah, your diagonal is probably not in the same direction I thought, so it's fine.
your code seems good to me.
 
  • Like
Reactions: ground

quarz

New Member
Newbie
Joined
Sep 13, 2009
Messages
4
Trophies
0
XP
135
Country
Gambia, The
Hey there! I'm also just starting to write homebrew for 3DS and i used an old example that doesn't work with newer versions of ctrulib. It was a problem with the initialzation of the framebuffers.

I guess you are using gfxInit(some format, some format, bool) in your main() function. Unless you need that format you should use gfxInitDefault() instead.

Your code works on my end, so your problem should be the format of your framebuffers.
 

ground

Well-Known Member
OP
Member
Joined
Mar 22, 2007
Messages
907
Trophies
0
XP
597
Country
Netherlands
Could you send a screenshot/picture of the result you get, plus the loop that is supposed to draw the line?
sure:
strange.jpg

and the loop(copied the most important functions in case you want to look at it):
void clearrow(int row)
{
for (i = 0; i < 51; i = i + 1)
printf("\x1b[%d;%dH ", i, row);
}

void startselector(int value)
{
menu[0] = menu[0] + value;
if (menu[0] >= 4)
menu[0] = 0;
if (menu[0] <= -1)
menu[0] = 3;
}

void drawpixel(int i)
{
char r = 0xff;
char g = 0x00;
char b = 0x00;
int height = 240;
u32 v = (height-1-i+i*height)*3;
screen[v] = b;
screen[v + 1] = g;
screen[v + 2] = r;
}

void start_single(void)
{
int i;
for (i = 0; i < 100; i = i + 1)
drawpixel(i);
}

void start(void)
{
menu[0] = 0;
menu[1] = 1;
hidScanInput();
kDown = hidKeysDown();
enum Menu{
single=0,multi=1,highscores=2,exit=3
};
drawpicture(0);
printf("\x1b[10;3HSingle Player");
printf("\x1b[12;3HMulti Player");
printf("\x1b[14;3HHighscores");
printf("\x1b[16;3HExit");
printf("\x1b[29;20HVersion: %s",version);
while (true)
{
hidScanInput();
kDown = hidKeysDown();

if (kDown&KEY_DDOWN)
startselector(+1);
if (kDown&KEY_DUP)
startselector(-1);
if (kDown&KEY_A)
{
if (menu[0] == single)
start_single();
if (menu[0] == multi)
start_multi();
if (menu[0] == highscores)
start_highscores();
if (menu[0] == exit)
break;
}
printf("\x1b[18;3H%d %d", menu[0], menu[1]);
if (menu[1] != menu[0])
{
clearrow(1);
if (menu[0] == single)
printf("\x1b[10;1HX ");
if (menu[0] == multi)
printf("\x1b[12;1HX ");
if (menu[0] == highscores)
printf("\x1b[14;1HX ");
if (menu[0] == exit)
printf("\x1b[16;1HX ");
}
if (kDown & KEY_START) break;
menu[1] = menu[0];

}
}]
If the color is wrong it means you are a byte off.
BGRBGR
00F00F what you want
0FF0FF what you get (yellow)(doesn't make sense, even if it was shifted you should have 2 bytes at 0x00)
F00F00 what you get (blue)

and your position seems wrong:
To make a diagonal, shouldn't it be:
(i*height-height+i) ?

sorry if all this is wrong, just thought about it for 2 mins

edit:
ah, your diagonal is probably not in the same direction I thought, so it's fine.
your code seems good to me.
yeah, well you could be right, as i still try to picture the "formula"in my head. i can see why it is heigh-1(so it is all on the screen, and the heigh*width*3 is to find the correct location of the pixel in memory, as it is laid out "flat") en why the *3 is there (for each pixel 1, but if it is RGBRGB shouldn't it be *6?).
 

Cyan

GBATemp's lurking knight
Former Staff
Joined
Oct 27, 2002
Messages
23,749
Trophies
4
Age
46
Location
Engine room, learning
XP
15,662
Country
France
no, it's BBGGRR BBGGRR
I just shortened the code to BGR because I was easier to see the "FF" position, I'll edit my message to prevent confusion.
it's *3 for 3 bytes per pixels

the lines shouldn't be dotted.
You have spaces between each colored pixels like if it's printing 1/3 pixels.
maybe you mixed width and height?

is there a "bottom right" buffer? does that exists?
it looks to me you overflow the left buffer and it continues writing to the second buffer.
but the two buffers are maybe separated by a byte, so the color get shifted.


try removing the "*3" (it shouldn't work, just curious to see the result)
 
  • Like
Reactions: ground

Technicmaster0

Well-Known Member
Member
Joined
Oct 22, 2011
Messages
4,420
Trophies
2
Website
www.flashkarten.tk
XP
3,553
Country
Gambia, The
is there a "bottom right" buffer? does that exists?
it looks to me you overflow the left buffer and it continues writing to the second buffer.
but the two buffers are maybe separated by a byte, so the color get shifted.
No. The bottomscreen uses the left buffer as well.

Maybe you are in the wrong RGB mode: both, the draw and the initialization must be in RGB8 or RGB565.
 

ll0rT

Well-Known Member
Member
Joined
Dec 15, 2014
Messages
137
Trophies
0
Age
28
XP
361
Country
You can use:
Code:
void setPixel(u8 *fb, u16 x, u16 y, u8 red, u8 green, u8 blue) {
    fb[3 * (240 - y + (x - 1) * 240)] = blue;
    fb[3 * (240 - y + (x - 1) * 240) + 1] = green;
    fb[3 * (240 - y + (x - 1) * 240) + 2] = red;
}

setPixel(bottomFb, 1, 1, 255, 0, 0); draws a red pixel on top-left corner.
setPixel(bottomFb, 320, 240, 255, 255, 255); draws a white pixel on bottom-right corner.
You can use it for top screen as well if you use top screen's framebuffer in first argument.
 
  • Like
Reactions: ground and Cyan

ground

Well-Known Member
OP
Member
Joined
Mar 22, 2007
Messages
907
Trophies
0
XP
597
Country
Netherlands
You can use:
Code:
void setPixel(u8 *fb, u16 x, u16 y, u8 red, u8 green, u8 blue) {
    fb[3 * (240 - y + (x - 1) * 240)] = blue;
    fb[3 * (240 - y + (x - 1) * 240) + 1] = green;
    fb[3 * (240 - y + (x - 1) * 240) + 2] = red;
}

setPixel(bottomFb, 1, 1, 255, 0, 0); draws a red pixel on top-left corner.
setPixel(bottomFb, 320, 240, 255, 255, 255); draws a white pixel on bottom-right corner.
You can use it for top screen as well if you use top screen's framebuffer in first argument.
thanks for your reply, but colors and locations are still off(in the same way).
could there be somethign wrong witht his code:
gfxInitDefault();
u8* screen;
screen = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
 

ll0rT

Well-Known Member
Member
Joined
Dec 15, 2014
Messages
137
Trophies
0
Age
28
XP
361
Country
thanks for your reply, but colors and locations are still off(in the same way).
could there be somethign wrong witht his code:

There is nothing wrong in that code. The problem might be printf.
Did you use this code?
Code:
consoleInit(GFX_BOTTOM, NULL);
This will make all bottom screen pixel drawings inaccurate and I don't know how to fix this. Use one screen to print texts and other screen to draw pixels.
 
  • Like
Reactions: ground

ground

Well-Known Member
OP
Member
Joined
Mar 22, 2007
Messages
907
Trophies
0
XP
597
Country
Netherlands
There is nothing wrong in that code. The problem might be printf.
Did you use this code?
Code:
consoleInit(GFX_BOTTOM, NULL);
This will make all bottom screen pixel drawings inaccurate and I don't know how to fix this. Use one screen to print texts and other screen to draw pixels.
Yes i used consoleinit(GFX_BOTTOM,NULL), otherwise nothing shows up;
I also used printf a lot. And i want to draw pixels to clear some text out, but not everything, so i guess i am going to "space"that out. that works well but it seems inconvenient.
 

Technicmaster0

Well-Known Member
Member
Joined
Oct 22, 2011
Messages
4,420
Trophies
2
Website
www.flashkarten.tk
XP
3,553
Country
Gambia, The
Yes i used consoleinit(GFX_BOTTOM,NULL), otherwise nothing shows up;
I also used printf a lot. And i want to draw pixels to clear some text out, but not everything, so i guess i am going to "space"that out. that works well but it seems inconvenient.
That's the issue. The "printf" command uses RGB565 while your setPixel method uses RGB8. You need another setPixel command to use both at the same time. Try the following:
Code:
//This works only in RGB565 mode
void drawPixel(u32 x, u32 y, u32 color, u8 *fbAdr)
{
	int idx = (x * 240) + (239 - y);
 
	((u16*)fbAdr)[idx] = (u16)color;
}
But that opens another problem: the colors you use with this must be in RGB565 format, not RGB8. You can use the following method to convert the colors from RGB8 to RGB565 (the method is integrated into ctrulib):
Code:
RGB8_to_565(r,g,b)
 
  • Like
Reactions: ll0rT and ground

ground

Well-Known Member
OP
Member
Joined
Mar 22, 2007
Messages
907
Trophies
0
XP
597
Country
Netherlands
That's the issue. The "printf" command uses RGB565 while your setPixel method uses RGB8. You need another setPixel command to use both at the same time. Try the following:
Code:
//This works only in RGB565 mode
void drawPixel(u32 x, u32 y, u32 color, u8 *fbAdr)
{
int idx = (x * 240) + (239 - y);
 
((u16*)fbAdr)[idx] = (u16)color;
}
But that opens another problem: the colors you use with this must be in RGB565 format, not RGB8. You can use the following method to convert the colors from RGB8 to RGB565 (the method is integrated into ctrulib):
Code:
RGB8_to_565(r,g,b)
yup, this did the trick:D thank you.

the code what i have now:
void drawpixel(u8* screen, u32 x,u32 y,u8 r,u8 g, u8 b)
{
u32 color = RGB8_to_565(r, g, b);
int idx = (x * 240) + (239 - y);
((u16*)screen)[idx] = (u16)color;
}
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • BakerMan @ BakerMan:
    i just want a wizard to stick his wand (whether literal or figurative is up to interpretation, either way it's either freaky or sus, or both i guess) up my ass
  • BigOnYa @ BigOnYa:
    I'm making Texas sheet cake for first time today, my Nieghbor brought us some few weeks ago and damn that's good, so I got her recipe and gonna try it today.
  • BakerMan @ BakerMan:
    mmm, sounds good
  • BigOnYa @ BigOnYa:
    Its not a brownie, and its not a cake, so what is it- Texas sheet cake.
  • BigOnYa @ BigOnYa:
    I tried making chocolate lava cakes the other day in cupcake pan, what a mess, my lava exploded out of the cakes everywhere while baking, was still ok tho, just no lava inside.
  • BigOnYa @ BigOnYa:
    We had our grandkids over yesterday and I got a small above ground swimming pool I filled for them to play in. Well today I woke to find 3 ducks swimming around in it. Don't mind really but they are annoyingly loud, quack quack. Gotta drain it today. Guess what were having for dinner, lol.
    +1
  • BakerMan @ BakerMan:
    lol
  • AncientBoi @ AncientBoi:
    BBQ'd 🦆
    +1
  • BakerMan @ BakerMan:
    also i'm sorry your molten lava cakes failed
    +2
  • BakerMan @ BakerMan:
    just looked up a pic of texas sheet cake, and it looks delicious
    +1
  • AncientBoi @ AncientBoi:
    🌋 Science Project?
  • BakerMan @ BakerMan:
    i think i might need to try making lava cakes for the 4th of july fr
    +2
  • BigOnYa @ BigOnYa:
    I used butter instead of vegetable oil, and think that's why they squirted out during baking, who knows
  • BakerMan @ BakerMan:
    yeah i think oil is the right call
    +1
  • BakerMan @ BakerMan:
    plus if you're making brownies or lava cakes for people with dairy allergies, you should use oil instead of butter anyway
    +2
  • ZeroT21 @ ZeroT21:
    @BakerMan Make me a space cake plz
  • BigOnYa @ BigOnYa:
    I make rum cake for 4th July every year, I make it a week prior and then soak it in rum in the fridge all week. I flip the cake each day, and add little more rum, it soaks it up everyday, so good.
    +2
  • BakerMan @ BakerMan:
    sorry, idk what you mean by a space cake, and even if i did, i'm not really taking requests right now, because otherwise people will get mad at me for taking a request but not making a birthday cake for @Xdqwerty (i'm sorry for that btw bro)
  • ZeroT21 @ ZeroT21:
    @BakerMan lies, you just want to smoke it

    :rofl2:
    +1
  • ZeroT21 @ ZeroT21:
    Guess all the food in my fridge can knock out a cow or two
  • ZeroT21 @ ZeroT21:
    I should visit Florida again, miss the alligator barbecues
  • BigOnYa @ BigOnYa:
    Me and wifey was deciding on our next vacation, so I hung up a map on the wall, and give her a dart and said, wherever you hit, we will go. She threw the dart and it missed the map completely and fell into a trash can below on floor. So I said "ok Florida it is."
  • BakerMan @ BakerMan:
    @ZeroT21 ohhh a pot cake?
    +1
  • SylverReZ @ SylverReZ:
    Gimme some of dat
    SylverReZ @ SylverReZ: Gimme some of dat