Tutorial  Updated

DS Programming for Newbies!

3Lwpv.png

Table of Contents:

Introductory Chapters:
  1. Preparing the environment
  2. Variables!
  3. Functions!
  4. Operators in C
  5. Conditions - if/else Statements and switches
  6. Looping - for() and while() Loops
  7. Containers of Variables - Arrays and Structures
Introduction to DS Hardware:
  1. RAM and VRAM
  2. OAM and 2D Sprites
Practical use of libnds:
  1. Input: Keys and the Touchscreen
Practical Use of NightFox Lib:
  1. NightFox Lib Integration
  2. 2D MODE-0 Part 1 - Tiled Backgrounds
  3. 2D MODE-0 Part 2 - Tiled Sprites
Excercises:
  1. Your first program!
  2. MODE-0 Tiled Backgrounds Example
  3. MODE-0 Tiled Sprites Example
  4. Our very first game: Tic Tac Toe!
Additional Utilities:
  1. GRIT


:download: PDF Version maintained by CannonFoddr available on FileTrip HERE!

:download: PDF Version maintained by Pomegrenade GBAtemp Mirror HERE!




Preface


Hello and welcome! If you are reading this then it’s likely that you’re interested in getting to know more about programming for the Nintendo DS! If you are not, then you likely took the wrong turn, but let’s not get into that. Let’s also start with establishing one important thing – as the title suggests, this is a “From Zero to Hero” guide. If you are an experienced programmer then it is likely that you will not benefit from it much, if at all. It is going to introduce the very basics to users who have never even seen a compiler before and never coded in their life – stuff that you probably already know and aren’t interested in anymore. You are however still welcome as this is my first tutorial and will likely require a certain degree of proof-reading, plus, you may of course have useful suggestions! Keep in mind the target audience though, I’m doing my best not to introduce complicated concepts early on. If you’re not an experienced programmer or never programmed at all, this is a great place to start!

I’ve seen many guides approaching this subject – some were more helpful, some were rather vague, but there is one thing that was common in all of them, and it became apparent to me that something has to be done about it. The guides I’ve seen so-far are dedicated to users who are familiar with programming and only require an introduction to the DS environment, none of them are actually “tutorials” from the ground up. Does this mean that a non-experienced user simply cannot program for the DS or should not begin his adventure with programming on this exact platform? No, it does not! In fact, the DS is likely the easiest platform to program for when it comes to consoles – libnds is really not that hard to wrap your mind around and there are numerous libraries out there that facilitate programming for it even further. You probably want to ask: “If it’s so easy, why do You think it requires some sort of an explanation? The libraries are well-documented, do you expect the readers to be dill-wits who can’t follow simple examples?” and the answer to that is “No, in fact, I do believe that everybody is capable of programming, however one has to learn and acquire some basic programming habits and have some practice in C to be successful at it” and this is exactly the main goal of this tutorial. Depending on the interest shown by users and my workload at Uni this may or may not be a full-featured guide, however I promise that I will at least try to keep it up-to-date and expand upon it from time to time.

Now that the purpose is established, let’s move on to the juicy parts! I hope you will enjoy learning together and in case of any questions or suggestions, do write! Dear readers, keep in mind that the first few tutorials will be an incredibly rapid course in C, applicable to any type of programming, not just for the DS! We won’t be compiling much until this material is covered and thoroughly understood! So… Let’s get it on!
 
Last edited by Foxi4,

ExplodingGoose123

Member
Newcomer
Joined
Aug 11, 2020
Messages
9
Trophies
0
Age
20
XP
61
Country
Netherlands
I am quite new to this, and i am looking for the right software to edit sprites and backgrounds. I managed to find some online tools like pixilart and piskel and converted it with GIMP, but when i converted the image, some brown colors where gone or turned black. Is there some (free) software where you can set your own resolution, set 8-bit colors and save it as .bmp?

Great toturial btw, very fun if you have a nintendo and some motivation left!
Will there be another lesson (For example CMaps)?;)
 

Foxi4

Endless Trash
OP
Global Moderator
Joined
Sep 13, 2009
Messages
30,818
Trophies
3
Location
Gaming Grotto
XP
29,788
Country
Poland
I am quite new to this, and i am looking for the right software to edit sprites and backgrounds. I managed to find some online tools like pixilart and piskel and converted it with GIMP, but when i converted the image, some brown colors where gone or turned black. Is there some (free) software where you can set your own resolution, set 8-bit colors and save it as .bmp?

Great toturial btw, very fun if you have a nintendo and some motivation left!
Will there be another lesson (For example CMaps)?;)
Your problem is transparencies. The first colour in the pallete is always the transparent one, so wherever it was used on the picture will seem see-through, exposing the pitch black void underneath. :P

In regards to collision maps, it's very simple logic - create a background that represents your map boundaries, then hide it underneath the visible layer. Once done, create a routine that checks the colours of the pixels on that background. There's a function in Nightfox that does just that if you look at the documentation, but let's say that we want to know how it works. Say your sprite is 8 pixels by 8 pixels, so if pixel 2,3 (dead center of the bottom of the sprite touches colour 0,0,0 (black) then your sprite is standing on the ground. You can do that any number of times and program responses to any colour. :)
 

ExplodingGoose123

Member
Newcomer
Joined
Aug 11, 2020
Messages
9
Trophies
0
Age
20
XP
61
Country
Netherlands
Thanks for the fast reply and help Foxi4.

Your problem is transparencies. The first colour in the pallete is always the transparent one, so wherever it was used on the picture will seem see-through, exposing the pitch black void underneath. :P
I thought the only color that was transparent was magenta (255, 0, 255)... Guess i have to change my drawings than.

In regards to collision maps, it's very simple logic - create a background that represents your map boundaries, then hide it underneath the visible layer. Once done, create a routine that checks the colours of the pixels on that background. There's a function in Nightfox that does just that if you look at the documentation, but let's say that we want to know how it works. Say your sprite is 8 pixels by 8 pixels, so if pixel 2,3 (dead center of the bottom of the sprite touches colour 0,0,0 (black) then your sprite is standing on the ground. You can do that any number of times and program responses to any colour. :)
Thanks a lot!, no more tons of if/elses for me:rofl2:.

One more last thing... Is there a way to let things move in gimp?(So for example i can create a sprite in piskel, and convert it to a moving .bmp in GIMP). I tried to convert it into a .png, so i could edit it in GIMP, but it seems like i lose my animations than. Changing the batch files so it converts a .gif instead of a .bmp also doesn't seem to work.
 

Foxi4

Endless Trash
OP
Global Moderator
Joined
Sep 13, 2009
Messages
30,818
Trophies
3
Location
Gaming Grotto
XP
29,788
Country
Poland
Thanks for the fast reply and help Foxi4.


I thought the only color that was transparent was magenta (255, 0, 255)... Guess i have to change my drawings than.


Thanks a lot!, no more tons of if/elses for me:rofl2:.

One more last thing... Is there a way to let things move in gimp?(So for example i can create a sprite in piskel, and convert it to a moving .bmp in GIMP). I tried to convert it into a .png, so i could edit it in GIMP, but it seems like i lose my animations than. Changing the batch files so it converts a .gif instead of a .bmp also doesn't seem to work.
You need to make a sprite strip. Make it the width of the sprite and the height of however many frames you have. There's an example of an animated sprite in the Tic Tac Toe code, you just need to adjust the animation to your needs. If it makes it easier, you can create an animated gif and convert that into a strip, there was an app that did just that, but the name escapes me right now. You'll have to do some Googling for a converter or manually strap frames together into a strip.

As for the transparency issue, you don't necessarily need to change the drawing, you just need to change the first colour of the palette to something that's not anywhere else in the picture - magenta is a common choice, but it can be anything. You can manually edit the palette in GIMP.
 

ExplodingGoose123

Member
Newcomer
Joined
Aug 11, 2020
Messages
9
Trophies
0
Age
20
XP
61
Country
Netherlands
You need to make a sprite strip. Make it the width of the sprite and the height of however many frames you have. There's an example of an animated sprite in the Tic Tac Toe code, you just need to adjust the animation to your needs. If it makes it easier, you can create an animated gif and convert that into a strip, there was an app that did just that, but the name escapes me right now. You'll have to do some Googling for a converter or manually strap frames together into a strip.

As for the transparency issue, you don't necessarily need to change the drawing, you just need to change the first colour of the palette to something that's not anywhere else in the picture - magenta is a common choice, but it can be anything. You can manually edit the palette in GIMP.

Thank you a lot! You are really some kind of genius.
 

ExplodingGoose123

Member
Newcomer
Joined
Aug 11, 2020
Messages
9
Trophies
0
Age
20
XP
61
Country
Netherlands
Sorry for the spam, but i am having trouble again...
you just need to change the first colour of the palette to something that's not anywhere else in the picture
I tried to change the first color of the pallete in GIMP to magenta, but that doesn't seem to do anything, the blur is still there(When i try to convert the image to a .bmp it gives an error and says that there isn't a alfachannel, and it will make one, but i don't know if this is the problem). I tried to edit the .pal file that comes with the .img file after converting, but the file seems corrupted, i can't open it with any software i tried, so i tried looking for the example you provided. In the .nds file aren't any animations, but i could see some magenta blur around the circles and crosses. I am using No$Gba, as you recommended earlier, but maybe it could be something else?

Also, where does the magic happen from the strip to animation? Like where is the strip (.png/.jpg) coming into a animation? The batch files are kind of a grey area for me, so i figured that must be the place, but i am not so sure now, and i don't want to run into more problems.:lol:
 
Last edited by ExplodingGoose123,

Foxi4

Endless Trash
OP
Global Moderator
Joined
Sep 13, 2009
Messages
30,818
Trophies
3
Location
Gaming Grotto
XP
29,788
Country
Poland
Sorry for the spam, but i am having trouble again...

I tried to change the first color of the pallete in GIMP to magenta, but that doesn't seem to do anything, the blur is still there(When i try to convert the image to a .bmp it gives an error and says that there isn't a alfachannel, and it will make one, but i don't know if this is the problem). I tried to edit the .pal file that comes with the .img file after converting, but the file seems corrupted, i can't open it with any software i tried, so i tried looking for the example you provided. In the .nds file aren't any animations, but i could see some magenta blur around the circles and crosses. I am using No$Gba, as you recommended earlier, but maybe it could be something else?

Also, where does the magic happen from the strip to animation? Like where is the strip (.png/.jpg) coming into a animation? The batch files are kind of a grey area for me, so i figured that must be the place, but i am not so sure now, and i don't want to run into more problems.:lol:
That's more a matter of me being lazy than the console's fault - if you get any artifacting during resizing or if you use colour blending, you'll end up with uneven transparencies, like I did. This is why sprites normally use some kind of a border to separate the sprite from the transparent background.

As for the animation, that happens on the console itself. Imagine that it's a strip of film, with frames from 0 downwards, that scrolls across the screen. You only have a viewing angle of one frame at a time, so you create the illusion of motion as the "film" scrolls.

Hope that helps. :)
 

ExplodingGoose123

Member
Newcomer
Joined
Aug 11, 2020
Messages
9
Trophies
0
Age
20
XP
61
Country
Netherlands
That's more a matter of me being lazy than the console's fault - if you get any artifacting during resizing or if you use colour blending, you'll end up with uneven transparencies, like I did. This is why sprites normally use some kind of a border to separate the sprite from the transparent background.

I don't use any random sites to make my pixelart, so that is one convert-step less, drawing now in GIMP. I don't get any alfa-channel-errors anymore. I created a border as you recommended, but the blur is still there. But when i open the batch file Convert_Sprites, i get a message at the start with "Shared palette name:" I just filled it with "dino" because that is the name i recall in my code, but i know now the palette is way more important than i thought, so maybe i am doing something wrong in here? I don't add a palette anywhere, so that could be a problem, but the batch file does make a .pal file, so i thought that it would be fine.

As for the animation, that happens on the console itself. Imagine that it's a strip of film, with frames from 0 downwards, that scrolls across the screen. You only have a viewing angle of one frame at a time, so you create the illusion of motion as the "film" scrolls.

Hope that helps. :)

Yes, this helps a lot, i know now i don't have to worry about any extra software, thanks a lot!:D
 

Foxi4

Endless Trash
OP
Global Moderator
Joined
Sep 13, 2009
Messages
30,818
Trophies
3
Location
Gaming Grotto
XP
29,788
Country
Poland
I don't use any random sites to make my pixelart, so that is one convert-step less, drawing now in GIMP. I don't get any alfa-channel-errors anymore. I created a border as you recommended, but the blur is still there. But when i open the batch file Convert_Sprites, i get a message at the start with "Shared palette name:" I just filled it with "dino" because that is the name i recall in my code, but i know now the palette is way more important than i thought, so maybe i am doing something wrong in here? I don't add a palette anywhere, so that could be a problem, but the batch file does make a .pal file, so i thought that it would be fine.

Yes, this helps a lot, i know now i don't have to worry about any extra software, thanks a lot!:D
Any chance you could post a screenshot from an emulator or something that would let me diagnose the problem?
 

ExplodingGoose123

Member
Newcomer
Joined
Aug 11, 2020
Messages
9
Trophies
0
Age
20
XP
61
Country
Netherlands
Yes of course. In any case, it isn't great. I am not an artist, so the pixelart lookse horrible:ha:.
Error.png
You can see in the left bottom corner some black blur, that is where the dinosaur is supposed to be. It is a little bit confusing because the trees are also black (the converting didn't go well here either.)
result.png
This is my ugly dinosaur that should be in the left bottom corner. The first color is magenta, as used in the background. I tried it with a color that didn't exist in my picture too.(No animation, i started about a few hours ago with learning to make pixelart in GIMP.)
 
Last edited by ExplodingGoose123,

Foxi4

Endless Trash
OP
Global Moderator
Joined
Sep 13, 2009
Messages
30,818
Trophies
3
Location
Gaming Grotto
XP
29,788
Country
Poland
Yes of course. In any case, it isn't great. I am not an artist, so the pixelart lookse horrible:ha:.
View attachment 221788
You can see in the left bottom corner some black blur, that is where the dinosaur is supposed to be. It is a little bit confusing because the trees are also black (the converting didn't go well here either.)
View attachment 221790
This is my ugly dinosaur that should be in the left bottom corner. The first color is magenta, as used in the background. I tried it with a color that didn't exist in my picture too.(No animation, i started about a few hours ago with learning to make pixelart in GIMP.)
Ah, I understand. You're using the wrong palette for the dinosaur, that's my first guess. It seems to be using the wrong colors. Each sprite and background have their own transparency and the creator is making a joint palette, but that will give you grief if you're using a lot of colors at once. My suggestion would be to use a separate palette for each background layer and a palette for sprites, as opposed to using a single one. There are batch files available for that kind of processing, and NFlib does support loading multiple palettes, I believe you have four slots, but my memory of the library is hazy.
 

ExplodingGoose123

Member
Newcomer
Joined
Aug 11, 2020
Messages
9
Trophies
0
Age
20
XP
61
Country
Netherlands
sorry for the slow response, but thanks a lot! I have a feeling of getting finally close to what i want.:yay:
It works now too! The dinosaur yawning without sound in the background. Pretty useless, but still fun!
again, Thanks for all the help!
 
  • Like
Reactions: Foxi4

Foxi4

Endless Trash
OP
Global Moderator
Joined
Sep 13, 2009
Messages
30,818
Trophies
3
Location
Gaming Grotto
XP
29,788
Country
Poland
You're welcome! Sound effects should be easy to add, all you need is normal wave forms. I always use mono sounds since the DS speakers are craptastic anyway - saves you space.
 

ocai0

Member
Newcomer
Joined
Aug 22, 2020
Messages
6
Trophies
0
XP
71
Country
Brazil
Hi, so i'm having some trouble with the libnds. Basically the way my little code appears on real hardware is different from the emulator.
I'm using Desmume, an acekard (maybe the 2 because of the theme i use) and the TWilightMenu++ (basically nds-bootstrap) to run.
The results on the hardware doesn't change from the acekard to the nds-bootstrap, but it differs a lot from the emulation and what i expect.
The code makes two squares (16x16) and shows in on both screens.
IMG_6767.JPG
 
Last edited by ocai0,

Foxi4

Endless Trash
OP
Global Moderator
Joined
Sep 13, 2009
Messages
30,818
Trophies
3
Location
Gaming Grotto
XP
29,788
Country
Poland
Hi, so i'm having some trouble with the libnds. Basically the way my little code appears on real hardware is different from the emulator.
I'm using Desmume, an acekard (maybe the 2 because of the theme i use) and the TWilightMenu++ (basically nds-bootstrap) to run.
The results on the hardware doesn't change from the acekard to the nds-bootstrap, but it differs a lot from the emulation and what i expect.
The code makes two squares (16x16) and shows in on both screens.
View attachment 222461
Desmume is an emulator tailored for retail releases, it has a lot of trouble with accurately testing homebrew. My first suggestion is to test on No$GBA going forward, it's the recommended emulator due to its accuracy and extensive developer tools. I would also need to see a code snippet of some kind to give advice, without it I'm poking blindly.
 

ocai0

Member
Newcomer
Joined
Aug 22, 2020
Messages
6
Trophies
0
XP
71
Country
Brazil
Desmume is an emulator tailored for retail releases, it has a lot of trouble with accurately testing homebrew. My first suggestion is to test on No$GBA going forward, it's the recommended emulator due to its accuracy and extensive developer tools. I would also need to see a code snippet of some kind to give advice, without it I'm poking blindly.

Right, so here's the full code i've made.

Code:
#include <nds.h>
#include <stdio.h>
//---------------------------------------------------------------------------------
void createSquare(int x, int y, OamState *screen, u16 *graphics, u16 color);

bool isRunning = true;
touchPosition touch;

int upperScreenSquareX = (SCREEN_WIDTH/2) - 8;
int upperScreenSquareY = (SCREEN_HEIGHT/2) - 8;
int speedUpperSquare = 5, facingVectorX = 0, facingVectorY = 0;

int main(void) {

    u16 *upperScreen  = oamAllocateGfx(&oamMain, SpriteSize_16x16, SpriteColorFormat_Bmp);
    u16 *bottomScreen = oamAllocateGfx(&oamSub, SpriteSize_16x16, SpriteColorFormat_Bmp);
  
    //Inicializa a tela Superior [upperScreen]
    videoSetMode(MODE_0_2D);
    vramSetBankA(VRAM_A_MAIN_SPRITE);
    oamInit(&oamMain, SpriteMapping_1D_32, false);
  
    //Inicializa a tela Inferior [bottomScreen]
    videoSetModeSub(MODE_0_2D);
    vramSetBankD(VRAM_D_SUB_SPRITE);
  
    oamInit(&oamSub, SpriteMapping_1D_32, false);
  
    while(isRunning) {
        //Inicializa a leitura de input
        scanKeys();
        int held = keysHeld();
      
        //label: Bottom Screen
            //Realiza operações, usando o input
            if(held & KEY_TOUCH)                                             touchRead(&touch);
            if(!(held & KEY_TOUCH) && (touch.py < SCREEN_HEIGHT - 16))  touch.py += 1;
          
            //Deixa o quadrado dentro da tela, não o deixa sair da tela (age como borda)
            if(touch.py < 0)                                                      touch.py = 0;
            if(touch.py > SCREEN_HEIGHT - 16)                   touch.py = SCREEN_HEIGHT - 16;
            if(touch.px > SCREEN_WIDTH - 16)                     touch.px = SCREEN_WIDTH - 16;
            if(touch.px < 0)                                                       touch.px = 0;
        //EndLabel: Bottom Screen
        //Label: Upper Screen
            facingVectorX = 0;
            facingVectorY = 0;
          
            if(held & KEY_UP)                facingVectorY = -1;
            if(held & KEY_LEFT)             facingVectorX = -1;
            if(held & KEY_DOWN)         facingVectorY = 1;
            if(held & KEY_RIGHT)          facingVectorX = 1;
          
            upperScreenSquareX = upperScreenSquareX + (speedUpperSquare * facingVectorX);
            upperScreenSquareY = upperScreenSquareY + (speedUpperSquare * facingVectorY);
          
            if(upperScreenSquareX > SCREEN_WIDTH - 16)                     upperScreenSquareX = SCREEN_WIDTH - 16;
            if(upperScreenSquareX < 0)                                                       upperScreenSquareX =  0;
            if(upperScreenSquareY > SCREEN_HEIGHT - 16)                    upperScreenSquareY = SCREEN_HEIGHT - 16;
            if(upperScreenSquareY < 0)                                                       upperScreenSquareY = 0;
          
        //EndLabel: Upper Screen
      
        //Cria o quadrado
        createSquare(upperScreenSquareX , upperScreenSquareY, &oamMain, upperScreen, ARGB16(1, 31, 12, 12));
        createSquare(touch.px, touch.py, &oamSub, bottomScreen, ARGB16(1, 12, 31, 12));
      
        //Renderiza a tela
        swiWaitForVBlank();
      
        // Atualiza as telas
        oamUpdate(&oamMain);
        oamUpdate(&oamSub);
    }
    return 0;
}

void createSquare(int x, int y, OamState *screen, u16 *graphics, u16 color) {
    dmaFillHalfWords(color, graphics, 16*16*2);
    oamSet(screen,1,x, y, 0, 15, SpriteSize_16x16, SpriteColorFormat_Bmp, graphics, 0, false, false, false, false, false);
}

Wow, it got messy these spaces...
 
Last edited by ocai0,

Foxi4

Endless Trash
OP
Global Moderator
Joined
Sep 13, 2009
Messages
30,818
Trophies
3
Location
Gaming Grotto
XP
29,788
Country
Poland

ocai0

Member
Newcomer
Joined
Aug 22, 2020
Messages
6
Trophies
0
XP
71
Country
Brazil
On first glance nothing seems out of the ordinary besides your oamInit mapped for 32 sprites instead of the expected 128. I'm on mobile, so I can't compile, but have a look at this example - it seems to execute what you are trying to achieve, and might shed some light on your issue
When I have a moment, I'll test your code on my end.

I've compiled the example and i've got the same result

IMG_6770.JPG
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    Xdqwerty @ Xdqwerty: Ok I changed my mind KIDS, DO DRUGS