Homebrew [HOMEBREW] 3DS Paint [UPDATE][2.0][NEW]

AlbertoSONIC

Pasta Team Member
OP
Member
Joined
Jun 27, 2014
Messages
927
Trophies
0
Age
52
Website
www.albertosonic.com
XP
1,396
Country
Italy
3DS Paint

Today i introduce you to my latest 3DS Homebrew: 3DS Paint! With this app you can draw anything you want, with 7 colors and an eraser! You can also save your drawing to the SDCARD! (.bmp image output) You can find some instructions on the 3DS's top screen!


How to install:

You can install this app in many ways. As a Gateway's 3ds file, as a .cia file, it's also ready for SSSPwn! You can find files below!


Screenshots:

f364840c6ac78e4b1484538e46c01ac7.jpg


MAIN SCREEN:
6f2cd68282ea0b889f7104128e6fb175.jpg


ABOUT POPUP:
f05dabc95f966ce99d3e3389eb8ddbae.jpg


DEBUG POPUP:
327f92711b7fbb8770e99ae10b1da179.jpg


PAINT SCREEN:
cae24542cb90bedbe228cb75757b454a.jpg


CLEAR SCREEN POPUP:
700374b16b0e4cdb9b17ddf68d84fbae.jpg


EXIT POPUP:
fa499fcfcd86e1ec51fac5cc7331b25b.jpg


DRAWING SAVED!!
fbd016f6d14d0cc8c336ecf4939a4143.jpg


HERE'S THE SAVED DRAWING:
https://www.dropbox.com/s/mssno9rkp13vy4p/3dspaint_drawing_01342922.bmp?dl=0


Bugs:

- There's a small undrawable corner around the the touchscreen.


Downloads:

Precompiled Files, ready to install: Link
Github Repo: Link


ChangeLog:

New 2.0 update brings:
- Whole app rewritten
- Now it exit without crashing, fully working on both NINJHAX and GATEWAY
- Much smoother (30fps)
- Debug features
- A main menu!
- Now you can save your drawings to SDCARD (.bmp image output)!
- HUGE performance improvement

- Less load for 3DS's ARM11 cpu
- Developed and built with latest CTRULIB
- New icon!
- Now using an UI framework!
- "Pop" sound when changing color! (Only for ninjhax users)
- New font!
- Screen Flickering fixed!
. Huge bugfix!

Credits:

Relys
filfat
Bond697
Screenshot feature (needed for saving) taken from BlargSnes
 
Last edited by AlbertoSONIC,

Relys

^(Software | Hardware) Exploit? Development.$
Member
Joined
Jan 5, 2007
Messages
878
Trophies
1
XP
1,239
Country
United States
Very nice. Clean example. Well documented. :)

One thing I would recommend is using camelCase (https://en.wikipedia.org/wiki/CamelCase) for function names with the first word lowercase.

Code:
int fooBar() //camel case.
{
    int someNumber=0; //Same idea for variables.
    return someNumber;
}

It really helps the readability and most C/C++ developers conform to this in their coding style standard (just look at ctrulib for example).
 

AlbertoSONIC

Pasta Team Member
OP
Member
Joined
Jun 27, 2014
Messages
927
Trophies
0
Age
52
Website
www.albertosonic.com
XP
1,396
Country
Italy
Very nice. Clean example. Well documented. :)

One thing I would recommend is using camelCase (https://en.wikipedia.org/wiki/CamelCase) for function names with the first word lowercase.

Code:
int fooBar() //camel case.
{
    int someNumber=0; //Same idea for variables.
    return someNumber;
}

It really helps the readability and most C/C++ developers conform to this in their coding style standard (just look at ctrulib for example).
So, printbottombackgnd() should be printBottomBackgnd()?
 
  • Like
Reactions: Relys

filfat

CTO @ Nordcom Group Inc.
Member
Joined
Nov 24, 2012
Messages
1,261
Trophies
1
Location
Gothenburg, Sweden
Website
www.sweetsideofsweden.com
XP
1,749
Country
Sweden

Relys

^(Software | Hardware) Exploit? Development.$
Member
Joined
Jan 5, 2007
Messages
878
Trophies
1
XP
1,239
Country
United States
Here's an example of loading an image from the sd card to the screen: https://github.com/smealum/ctrulib/blob/master/examples/sdmc/source/main.c


Here I am attempting to reverse that process to write framebuffer to allocated buffer in memory and then write to file on sd card.
Code:
    fsInit(); //needed for filesystem stuff
    u8* buffer;
    u64 size;
    u32 bytesWritten;
    Handle fileHandle;
    //setup SDMC archive
    FS_archive sdmcArchive=(FS_archive){ARCH_SDMC, (FS_path){PATH_EMPTY, 1, (u8*)""}};
    //create file path struct (note : FS_makePath actually only supports PATH_CHAR, it will change in the future)
    FS_path filePath=FS_makePath(PATH_CHAR, "/test.bin");
 
    //open file
    Result ret=FSUSER_OpenFileDirectly(NULL, &fileHandle, sdmcArchive, filePath, FS_OPEN_CREATE, FS_ATTRIBUTE_NONE); //RELYS: Changed FS_OPEN_READ to FS_OPEN_CREATE. Not sure if FS_ATTRIBUTE_NONE needs to be changed to FS_ATTRIBUTE_ARCHIVE
    //check for errors : exit if there is one
    if(ret)goto exit;
 
    //get screen size
    size=320*240*3; // RELYS: x resolution * y resolution * 3 colors per pixel
 
    //allocate a buffer on linear heap (could just be a malloc fwiw)
    buffer=linearAlloc(size);
    if(!buffer)goto exit;
 
    //copy lower screen to buffer
    memcpy(buffer,gfxGetFramebuffer(GFX_BOTTOM, GFX_BOTTOM, NULL, NULL), size);
 
    //Write contents
    ret=FSFILE_Write(fileHandle, &bytesWritten, 0x0, buffer,FS_WRITE_FLUSH); //RELYS: Not sure if we want to use FS_WRITE_FLUSH or FS_WRITE_NOFLUSH
    if(ret || size!=bytesWritten)goto exit;
 
    //close the file because we like being nice and tidy
    ret=FSFILE_Close(fileHandle);
    if(ret)goto exit;
 
    //cleanup and return
    //returning from main() returns to hbmenu when run under ninjhax
    exit:
    //closing all handles is super important
    svcCloseHandle(fileHandle);

I also noticed in the example that they use this for rendering. Maybe we should be using gfxSwappBuffersGPU and gspWaitForEvent???

Code:
        renderEffect();
        //wait & swap
        gfxSwapBuffersGpu();
        gspWaitForEvent(GSPEVENT_VBlank0, false);
 

AlbertoSONIC

Pasta Team Member
OP
Member
Joined
Jun 27, 2014
Messages
927
Trophies
0
Age
52
Website
www.albertosonic.com
XP
1,396
Country
Italy
https://github.com/smealum/ctrulib/blob/master/examples/sdmc/source/main.c

Code:
    fsInit(); //needed for filesystem stuff
    [FONT=Consolas][COLOR=#333333]u8* buffer;[/COLOR][/FONT]
    u64 size;
    u32 bytesWritten;
    Handle fileHandle;
    //setup SDMC archive
    FS_archive sdmcArchive=(FS_archive){ARCH_SDMC, (FS_path){PATH_EMPTY, 1, (u8*)""}};
    //create file path struct (note : FS_makePath actually only supports PATH_CHAR, it will change in the future)
    FS_path filePath=FS_makePath(PATH_CHAR, "/test.bin");
 
    //open file
    Result ret=FSUSER_OpenFileDirectly(NULL, &fileHandle, sdmcArchive, filePath, FS_OPEN_CREATE, FS_ATTRIBUTE_NONE); //RELYS: Changed FS_OPEN_READ to FS_OPEN_CREATE. Not sure if FS_ATTRIBUTE_NONE needs to be changed to FS_ATTRIBUTE_ARCHIVE
    //check for errors : exit if there is one
    if(ret)goto exit;
 
    //get screen size
    size=320*240*3; // RELYS: x resolution * y resolution * 3 colors per pixel
 
    //allocate a buffer on linear heap (could just be a malloc fwiw)
    buffer=linearAlloc(size);
    if(!buffer)goto exit;
 
    //copy lower screen to buffer
    memcpy(buffer,gfxGetFramebuffer(GFX_BOTTOM, GFX_BOTTOM, NULL, NULL), size);
 
    //Write contents
    ret=FSFILE_Write(fileHandle, &bytesWritten, 0x0, buffer,FS_WRITE_FLUSH); //RELYS: Not sure if we want to use FS_WRITE_FLUSH or FS_WRITE_NOFLUSH
    if(ret || size!=bytesWritten)goto exit;
 
    //close the file because we like being nice and tidy
    ret=FSFILE_Close(fileHandle);
    if(ret)goto exit;
 
    //cleanup and return
    //returning from main() returns to hbmenu when run under ninjhax
    exit:
    //closing all handles is super important
    svcCloseHandle(fileHandle);

I also noticed in the example that they use this for rendering. Maybe we should be using gfxSwappBuffersGPU and gspWaitForEvent???

Code:
        renderEffect();
        //wait & swap
        gfxSwapBuffersGpu();
        gspWaitForEvent(GSPEVENT_VBlank0, false);

I noticed it too! May be usefull...
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    AncientBoi @ AncientBoi: Imma make quesadillas for lunch :D +2