Draw pixels code

Discussion in '3DS - Homebrew Development and Emulators' started by ground, May 24, 2015.

  1. ground
    OP

    ground GBAtemp Advanced Fan

    Member
    909
    281
    Mar 22, 2007
    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).

    (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.
     
  2. MRJPGames

    MRJPGames Pretty great guy

    Member
    1,090
    708
    Aug 17, 2013
    Netherlands
    The Netherlands
    Could you send a screenshot/picture of the result you get, plus the loop that is supposed to draw the line?
     
    ground likes this.
  3. Cyan

    Cyan GBATemp's lurking knight

    Global Moderator
    17,696
    8,299
    Oct 27, 2002
    France
    Engine room, learning
    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.
     
    ground likes this.
  4. quarz

    quarz Newbie

    Newcomer
    4
    0
    Sep 13, 2009
    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.
     
  5. ground
    OP

    ground GBAtemp Advanced Fan

    Member
    909
    281
    Mar 22, 2007
    Netherlands
    sure:
    and the loop(copied the most important functions in case you want to look at it):
    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?).
     
  6. Cyan

    Cyan GBATemp's lurking knight

    Global Moderator
    17,696
    8,299
    Oct 27, 2002
    France
    Engine room, learning
    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)
     
    ground likes this.
  7. Technicmaster0

    Technicmaster0 GBAtemp Psycho!

    Member
    3,007
    613
    Oct 22, 2011
    Gambia, The
    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.
     
  8. ll0rT

    ll0rT GBAtemp Regular

    Member
    134
    109
    Dec 15, 2014
    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.
     
    ground and Cyan like this.
  9. ground
    OP

    ground GBAtemp Advanced Fan

    Member
    909
    281
    Mar 22, 2007
    Netherlands
    thanks for your reply, but colors and locations are still off(in the same way).
    could there be somethign wrong witht his code:
     
  10. ll0rT

    ll0rT GBAtemp Regular

    Member
    134
    109
    Dec 15, 2014
    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.
     
    ground likes this.
  11. ground
    OP

    ground GBAtemp Advanced Fan

    Member
    909
    281
    Mar 22, 2007
    Netherlands
    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.
     
  12. Technicmaster0

    Technicmaster0 GBAtemp Psycho!

    Member
    3,007
    613
    Oct 22, 2011
    Gambia, The
    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)
     
    ll0rT and ground like this.
  13. ground
    OP

    ground GBAtemp Advanced Fan

    Member
    909
    281
    Mar 22, 2007
    Netherlands
    yup, this did the trick:D thank you.

    the code what i have now: