Tutorial  Updated

Switch Homebrew development

Switch Homebrew development

I've seen quite a lot questions about how to get into Homebrew development for the switch recently so I decided to share some information I would have found useful when I started.
This Guide is made on Windows 10. Refer to other resources for the installation process on other operating systems. After the setup is done, pretty much everything will be the same.

First of all, here's all the topics I'm going to cover in this Guide:
  • What do I need?
  • Setup and Installation
  • Tools
  • Examples and explanation
  • FAQ
If you find any errors, feel free to report them! So let's get started.



What do I need?Setup and InstallationToolsExamples and explanations


  1. First of all you'll need a Nintendo Switch with a way to get into RCM and some way to start up the custom loader (Hekate for example). There are many tutorials out there on how use those.

    Next, you'll need the following tools:
    • devkitPro : Make sure devkitA64 is selected during installation.
    • hb-menu : You need one of the latest commits to properly use nx-link later so you need to compile it from sources for now.
    • Atom : A nice and advanced text editor. You can use any other text editor you want but I recommend this one.
    • Cmder : An advanced console emulator for Windows. You can use the default Windows cmd but I recommend to switch to better one.
    • (Git : Version control tool. I recommend using it to share your progress and to open source your project so the community can benefit from it. It's not necessary though)
    • ASM/C/C++ knowledge : I'll try to explain everything as easy as possible but don't try getting into homebrew without any prior C programming experience.
    • A lot of patience : We don't have GDB yet so your only way to debug right now is via printf.

    Once you're sure you've got everything above you may continue to the next chapter.

  2. After you've installed devkitPro, Atom Cmder and hopefully git AND you're running the latest version of the hb-menu we can start with the setup process.
    First of all we need to correct the devkitPro environment variables. By default they get set to the paths used on Linux which won't work on Windows.
    To change them, press Win + Pause/Break and click on Advanced system settings in the window that pops up. Now you press on the Environment Variables... button.
    Now search in the System variables list for DEVKITARM, DEVKITPPC and DEVKITPRO. Change them to your devkitPro path. Now if it's not already there, add a DEVKITA64 variable and set the path to the devkitA64 folder path.
    After you're finished, it should look something like this:

    0uJYvpt.png

    Now find the PATH variable and add the path to the ../devkitPro/tools/bin directory to it.

    After this step you're basically done. You don't need any setup for Atom or Cmder. They just work out of the box.​

  3. For compilation and deployment we're going to use two things: make and nxlink. Both get installed by default together with devkitPro.

    If you use the attached template project, all you'll need to do is to type make. This will take care of the whole compilation part. To deploy your compiled project to the Switch now we use nxlink.

    First, enter the hbmenu on your Switch and press the Y Button. This brings you into the nxlink mode. The list of homebrews should disappear now. Now you can run the following command:

    nxlink -s -a 192.168.xxx.xxx out\<homebrew_name>.nro

    This nxlink command some arguments.
    • -s stands for server. It's used for debugging. With this option enabled, printf output can get redirected to our console.
    • -a stands for address. It's the IP address of the Switch. You can look it up either in your router settings or in the Switch settings.
    • out\<homebrew_name>.nro is the path to your homebrew executable. By default it gets built inside the /out folder.


  4. First of all, download the attached sample homebrew and load it up in Atom.
    There are a lot of great examples for many different things inside the /devkitPro/examples/switch folder. Read through those first if you want to start developing. You can also look at the source code of EdiZon, Checkpoint, the hbmenu or any other homebrew to find out how they did certain stuff. We're all a community and learn from each others :). For any other questions consult the official documentation of libnx. You may ask here in this thread as well but I can't promise to be able to help everybody.

    So, let's get started with the examples. More examples will come over time.

    Button detection & console outputGraphics output


    1. Code:
      #include <switch.h>
      #include <stdio.h>
      
      int main(int argc, char** argv) {
          u32 kdown = 0x00000000;
          u32 kdownOld = 0x00000000;
      
          gfxInitDefault();
          consoleInit(nullptr); //Init the console
      
          while(appletMainLoop()) {
              hidScanInput();    //Scan for input       
              kdown = hidKeysDown(CONTROLLER_P1_AUTO); //Read the currently pressed buttons and store that value into kdown
      
               //Edge detection. We don't want to print "Hello World" while A is pressed. We only want to print it once and then again on the next press
              if(kdown > kdownOld) {
                  if(kdown & KEY_A)
                      printf("Hello World\n"); //Prints to the console on screen
              }
      
              kdownOld = kdown;
               
              gfxFlushBuffers();   //Finish this frame
              gfxSwapBuffers();    //Display it on the screen
              gfxWaitForVsync();   //Wait till the last frame finished displaying before updating to avoid flickering
          }
          gfxExit();
          return 0;
      }

    2. Code:
      #include <switch.h>
      
      int main(int argc, char** argv) {
         u8 *framebuffer;
         u32 framebuffer_width;
         u32 framebuffer_height;
      
         gfxInitDefault();
         framebuffer = gfxGetFramebuffer(&framebuffer_width, &framebuffer_height);  //Gets the address of the framebuffer so we can draw to it
      
         while(appletMainLoop()) {
             //The framebuffer is layed out in RGBA8 format. We're coloring it entirely in Magenta (0xFF00FFFF)
              for(u16 x = 0; x < framebuffer_width; x++) {
                  for(u16 y = 0; y < framebuffer_height; y++) {
                       framebuffer[(x + y * framebuffer_width) * 4 + 0] = 0xFF;   //Red
                       framebuffer[(x + y * framebuffer_width) * 4 + 1] = 0x00;   //Green
                       framebuffer[(x + y * framebuffer_width) * 4 + 2] = 0xFF;   //Blue
                       framebuffer[(x + y * framebuffer_width) * 4 + 3] = 0xFF;   //Alpha
                  }
              }
            
              gfxFlushBuffers();   //Finish this frame
              gfxSwapBuffers();    //Display it on the screen
              gfxWaitForVsync();   //Wait till the last frame finished displaying before updating to avoid flickering
          }
      
          gfxExit();
      
         return 0;
      }
 

Attachments

  • HomebrewTemplate.zip
    156.3 KB · Views: 1,726
Last edited by WerWolv,

M7L7NK7

Well-Known Member
Member
Joined
Oct 16, 2017
Messages
3,892
Trophies
1
Website
youtube.com
XP
5,953
Country
Australia
Anyone got a basic hello world handy to see? Just to see how to write on the screen

And what's the basics if you're trying to port an open source game?
 

Manurocker95

Game Developer & Pokémon Master
Member
Joined
May 29, 2016
Messages
1,511
Trophies
0
Age
29
Location
Madrid
Website
manuelrodriguezmatesanz.com
XP
2,788
Country
Spain
Anyone got a basic hello world handy to see? Just to see how to write on the screen

And what's the basics if you're trying to port an open source game?

If you need to setup the environment too, check out my tutorial with Visual studio. If not, this tutorial shows you a simple hello world. The basis are coding knowledge and devkitpro setup.
 

M7L7NK7

Well-Known Member
Member
Joined
Oct 16, 2017
Messages
3,892
Trophies
1
Website
youtube.com
XP
5,953
Country
Australia
My experience so far is writing hello world (which I couldn't see, it would just exit straight away) and then making it loop which I assumed worked because it stayed on the black screen lol

Just linking to other files is what I need to tackle next
 

Manurocker95

Game Developer & Pokémon Master
Member
Joined
May 29, 2016
Messages
1,511
Trophies
0
Age
29
Location
Madrid
Website
manuelrodriguezmatesanz.com
XP
2,788
Country
Spain
My experience so far is writing hello world (which I couldn't see, it would just exit straight away) and then making it loop which I assumed worked because it stayed on the black screen lol

Just linking to other files is what I need to tackle next
Then you did not follow the steps because this tutorial shows a hello world by console print xF btw, check my setup tutorial after retrying this one again :)
 

Tonydaexpert

C++ Pleb, but with a Monado
Member
Joined
Jul 5, 2016
Messages
194
Trophies
0
XP
769
Country
United States
This is cool! I was just learning about SDL some time ago. I only have focused on C++ so I hope that is enough lol (I know C++ can do stuff from C) can't wait to make things on Switch.
 

Rempa

Member
Newcomer
Joined
Apr 27, 2018
Messages
5
Trophies
0
Age
23
Location
Chez moi
Website
www.youtube.com
XP
85
Country
France
When trying to compile the example, i get those errors, and i don't understant why. Are these functions dependent on something else than libnx ?

D:\Documents\Prog\Switch\Dev>make
main.cpp
aarch64-none-elf-g++ -MMD -MP -MF /d/Documents/Prog/Switch/Dev/build/main.d -g -Wall -O3 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -DVERSION_MAJOR=1 -DVERSION_MINOR=0 -DVERSION_MICRO=0 -I/d/Documents/Prog/Switch/Dev/include -I/D\devkitPro/portlibs/switch/include -ID:\devkitPro/libnx/include -I/d/Documents/Prog/Switch/Dev/build -D__SWITCH__ -fno-rtti -fno-exceptions -std=gnu++17 -c /d/Documents/Prog/Switch/Dev/source/main.cpp -o main.o
D:/Documents/Prog/Switch/Dev/source/main.cpp: In function 'int main(int, char**)':
D:/Documents/Prog/Switch/Dev/source/main.cpp:10:3: error: 'gfxInitDefault' was not declared in this scope
gfxInitDefault();
^~~~~~~~~~~~~~
D:/Documents/Prog/Switch/Dev/source/main.cpp:26:3: error: 'gfxExit' was not declared in this scope
gfxExit();
^~~~~~~
D:/Documents/Prog/Switch/Dev/source/main.cpp:26:3: note: suggested alternative: 'fsExit'
gfxExit();
^~~~~~~
fsExit
make[1]: *** [D:\devkitPro/devkitA64/base_rules:14: main.o] Error 1
make: *** [Makefile:160: build] Error 2
 

Adran_Marit

Walküre's Hacker
Member
Joined
Oct 3, 2015
Messages
3,781
Trophies
1
Location
42*South
XP
4,547
Country
Australia
When trying to compile the example, i get those errors, and i don't understant why. Are these functions dependent on something else than libnx ?

D:\Documents\Prog\Switch\Dev>make
main.cpp
aarch64-none-elf-g++ -MMD -MP -MF /d/Documents/Prog/Switch/Dev/build/main.d -g -Wall -O3 -ffunction-sections -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -DVERSION_MAJOR=1 -DVERSION_MINOR=0 -DVERSION_MICRO=0 -I/d/Documents/Prog/Switch/Dev/include -I/D\devkitPro/portlibs/switch/include -ID:\devkitPro/libnx/include -I/d/Documents/Prog/Switch/Dev/build -D__SWITCH__ -fno-rtti -fno-exceptions -std=gnu++17 -c /d/Documents/Prog/Switch/Dev/source/main.cpp -o main.o
D:/Documents/Prog/Switch/Dev/source/main.cpp: In function 'int main(int, char**)':
D:/Documents/Prog/Switch/Dev/source/main.cpp:10:3: error: 'gfxInitDefault' was not declared in this scope
gfxInitDefault();
^~~~~~~~~~~~~~
D:/Documents/Prog/Switch/Dev/source/main.cpp:26:3: error: 'gfxExit' was not declared in this scope
gfxExit();
^~~~~~~
D:/Documents/Prog/Switch/Dev/source/main.cpp:26:3: note: suggested alternative: 'fsExit'
gfxExit();
^~~~~~~
fsExit
make[1]: *** [D:\devkitPro/devkitA64/base_rules:14: main.o] Error 1
make: *** [Makefile:160: build] Error 2

the gfx functions that are erroring were present in a previous version of libnx, and were removed in 1.5 if i remember correctly
 
  • Like
Reactions: CosmoCortney

Muxi

Well-Known Member
Member
Joined
Jun 1, 2016
Messages
605
Trophies
0
Age
52
XP
2,110
Country
Germany
I'm having problems setting up devkitPro on Windows 10 and at the point where the devkitPro environment variables need to be corrected I can't get any further. DEVKITARM and DEVKITPPC are included in my list of system variables, but none of these folders are in my devkitPro folder. Also, I could not make a devkitA64 selection when installing devkitpro as described in the manual. I could only select the components. I only selected Switch Development there. Does anyone have a clue what I did wrong? Thanks in advance.
 
Last edited by Muxi,

Daniel_Bradbury

New Member
Newbie
Joined
Jul 25, 2019
Messages
2
Trophies
0
Age
19
Location
England, United Kingdom
XP
60
Country
United Kingdom
Getting this error:

[...]/main.cpp:11:3: error: 'gfxInitDefault' was not declared in this scope
11 | gfxInitDefault();
| ^~~~~~~~~~~~~~
[...]/main.cpp:27:3: error: 'gfxExit' was not declared in this scope; did you mean 'nfcExit'?
27 | gfxExit();
| ^~~~~~~

What is causing this? Am I missing something?
 

Manurocker95

Game Developer & Pokémon Master
Member
Joined
May 29, 2016
Messages
1,511
Trophies
0
Age
29
Location
Madrid
Website
manuelrodriguezmatesanz.com
XP
2,788
Country
Spain
Getting this error:

[...]/main.cpp:11:3: error: 'gfxInitDefault' was not declared in this scope
11 | gfxInitDefault();
| ^~~~~~~~~~~~~~
[...]/main.cpp:27:3: error: 'gfxExit' was not declared in this scope; did you mean 'nfcExit'?
27 | gfxExit();
| ^~~~~~~

What is causing this? Am I missing something?
stupid question but do you have latest devkitpro installed with switch dependencies?
 

Daniel_Bradbury

New Member
Newbie
Joined
Jul 25, 2019
Messages
2
Trophies
0
Age
19
Location
England, United Kingdom
XP
60
Country
United Kingdom
stupid question but do you have latest devkitpro installed with switch dependencies?
Yes, I installed everything that the guide said other than atom and cmder
I also set up the environment variables as said.

Edit 1:

the gfx functions that are erroring were present in a previous version of libnx, and were removed in 1.5 if i remember correctly
Ah. That's probably what the problem is

Edit 2:

Fixed it by just commenting out those lines

Edit 3:

The build works, but nothing is actually displayed to the screen, so I guess that didn't really help anything
 
Last edited by Daniel_Bradbury,

vaugerbird

Well-Known Member
Newcomer
Joined
Nov 1, 2020
Messages
47
Trophies
1
Location
West Coast
XP
948
Country
United States
Sorry for necro, but I'm constantly getting this error every time I run make on any tesla overlay. I could really use some help.


Error after running make on QuickNTP:
Code:
In file included from C:\devkitPro/libnx/include/switch.h:79,
                 from C:/Users/user/Downloads/QuickNTP-1.2.0/QuickNTP-1.2.0/libs/libtesla/include/tesla.hpp:22,
                 from C:/Users/user/Downloads/QuickNTP-1.2.0/QuickNTP-1.2.0/source/main.cpp:2:
C:\devkitPro/libnx/include/switch/services/hid.h:1756:17: note: declared here
 1756 | void DEPRECATED hidTouchRead(touchPosition *pos, u32 point_id); ///< \deprecated
      |                 ^~~~~~~~~~~~
make[1]: *** [C:\devkitPro/devkitA64/base_rules:14: main.o] Error 1
make: *** [Makefile:170: build] Error 2

Full console output: https://pastebin.com/vCt3Lj75


EDIT: I found what the problem was. tesla.hpp from libtesla has a syntax error at line 3468 and 3494, but I think it's above my skill level to fix it.

Code:
Code in question:             hidsysAcquireHomeButtonEventHandle(&shData->homeButtonPressEvent);

Error:
In file included from C:/Users/user/Documents/GitHub/NetTest-ovl/source/main.cpp:2:
C:/Users/user/Documents/GitHub/NetTest-ovl/libs/libtesla/include/tesla.hpp: In function 'void tsl::impl::homeButtonDetector(void*)':
C:/Users/user/Documents/GitHub/NetTest-ovl/libs/libtesla/include/tesla.hpp:3468:77: error: too few arguments to function 'Result hidsysAcquireHomeButtonEventHandle(Event*, bool)'
 3468 |             hidsysAcquireHomeButtonEventHandle(&shData->homeButtonPressEvent);
      |                                                                             ^

EDIT 2: Replaced the tesla.hpp in from the latest release with this one from GitHub, and it's compiling up to a point. Thankfully at this point it's only errors in my coding.
 
Last edited by vaugerbird,

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    K3Nv2 @ K3Nv2: You could probably run duals in this Gigabyte B550 AORUS ELITE V2 AMD Ryzen 5000 ATX Motherboard...