Home New Tutorials Programs
1-R4DS Setup 2-Software Space Invaders
Old Tutorials DSEmu
1-Setup 4-Sound 7-FIFO
2-Framebuffer 5-SRAM 8-Interrupts
3-Keys 6-Filesystems 9-Microphone
10-Extended Rotation Background

Homebrew Nintendo DS Development Part 1

This tutorial was tested and works with the libraries installed by the devkitPro Updater 1.4.1 and Dualis dated 2006-05-3.

Having recently got a Nintendo DS I decided to try my hand at doing some development on it. This series of articles is intended to describe my understandings of Nintendo DS development and be a loose tutorial on using the various development tools.

Equipment and Software

To run self developed code on the DS you need to be able to somehow transfer the executable to the device. There are a few ways of doing this but the way I'm using is something called 'WifiMe'.

This involves running a program on a PC with a compatible PCMCIA or PCI 802.11g network card that appears to the DS as a 'DS Download Play' server.

On the DS you can then go to the 'DS Download Play' option and select the available program served up by the PC. This program will then run on the DS and cause a DS executable stored on a GBA Flash cartridge in the DS to execute.

So for the purposes of this tutorial I'll be using:

You can use any compatible wireless card, flash cartridge and development environment but the examples I'll be giving will be specific for my setup.

Setup

The instructions here are for a Windows based system. devkitPro is cross platform though and runs on Linux, MacOS X and Windows so installation of the system for the other operating systems is possible.

  1. Install the PCI Network card, WifiMe software and RT2560 driver as per the WifiMe tutorial. Make sure you don't install the drivers for the PCI Network card. You must install the custom developed RT2560 driver specific for the DS.
  2. Install the 'wmb.exe' program into a directory. Have a 'data' subdirectory off that. In that 'data' subdirectory have a 'wifime' subdirectory containing the 'WifiMe' files.
  3. Install the devkitPro development environment by running the devkitPro windows installer. This will download and install all necessary programs and libraries for you. It also sets up the required environment variables.

Test Setup

Download the file demo1.zip. This contains the sample application used in this tutorial. Unzip/Extract this file to a directory of your choice. Start an MSys shell by choosing the Start menu option 'devkitPro/MSys'. From within this shell change to the 'demo1' subdirectory that unzipping the file creates and run the command 'make'.

$ make
arm9_main.cpp
arm-eabi-g++ -MMD -MP -MF /c/repos/nds/demo1/build/arm9_main.d -g -Wall -O2 -mcp
u=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer -ffast-math -mthumb -mthumb-inte
rwork -I/c/repos/nds/demo1/include -I/c/repos/nds/demo1/build -I/c/devkitPro/lib
nds/include -I/c/devkitPro/libnds/include -I/c/repos/nds/demo1/build -DARM9 -fno
-rtti -fno-exceptions -c /c/repos/nds/demo1/source/arm9_main.cpp -o arm9_main.o
linking demo1.elf
built ... demo1.arm9
Nintendo DS rom tool 1.33 - Jan 28 2007 21:02:20
by Rafael Vuijk, Dave Murphy,  Alexei Karpenko
built ... demo1.nds

In the 'demo1' directory this will create some new files. The main one of interest is:

From the directory where you extracted 'wmb.exe', run the following command:

f:\wmb>wmb -data wifime

Nintendo DS - Wireless Multiboot Application - Version 1.3 BETA 4

(c) 2005 Tim Schuerewegen

Device Description = Ralink RT2560 Device
Device Hardware ID = PCI\VEN_1814&DEV_0201&SUBSYS_700A1799&REV_01
Device Location    = PCI bus 1, device 9, function 0
Driver Version     = 1.0.0.7

Loading "wifime"... ok

Press [x] to abort

Sending multiboot beacons & waiting for authentication

Using the software that came with the GBA Flash Card, copy the 'demo1.nds' file to it. It should be the only file on the card.

Insert the card into the DS and turn it on. Select 'DS Download Play'. The DS should find the 'WifiMe' download. Select this and confirm. The software will download and then the executable on the GBA Flash card will run.

Development Overview

The Nintendo DS has two CPU's. They are the ARM7 and ARM9. Both can be running code at the same time. A DS program is usually composed of an ARM7 executable, an ARM9 executable and various icons, bitmaps, resources, etc. These are combined into a single 'executable' using a tool called 'ndstool'. The resulting file is like a self contained filesystem. This produces the 'someprog.nds' file that can be run by the device.

Simple Demo Program

ARM7 Code

The first thing we need is the ARM7 code. The ARM7 is the only CPU that can be used for controlling the touchscreen. The 'libnds' library examples use some 'boilerplate' code for this that sets up an interrupt handler for the 'Vertical Blank Interrupt'. This is an interrupt that occurs on a regular basis to do with screen drawing.

Inside the interrupt handler, the 'boilerplate' code gets the value of the touchscreen parameters and stores them for the ARM9 code to retrieve. Remember that only the ARM7 can access the touchscreen so it needs to read it. But by storing it in an internal structure accessable by the ARM9 it enables that CPU to use the data.

devkitPro includes a default ARM7 program to handle basic tasks like interrupts, touchscreen, etc. Usually there is no need to write custom ARM7 code. By default the standard Makefile includes this default ARM7 program so there is no need for any ARM7 code to be written for this simple demo.

ARM9 Code

The ARM9 code is going to do the main work in this example. It will display a simple text message and output the X and Y coordinates obtained from the touch screen. The default ARM7 code obtains this information at regular intervals and stores it in a data structure we can access from the ARM9.

The ARM9 code is a single 'main' function. First the video mode is set up to use one of the Nintendo DS's screens. In this case, the touch screen. We also set up things to display text, the font colour, etc:

  // Use the touch screen for output
  videoSetMode(0);
  videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
  vramSetBankC(VRAM_C_SUB_BG);
  SUB_BG0_CR = BG_MAP_BASE(31);

  // Set the colour of the font to White.
  BG_PALETTE_SUB[255] = RGB15(31,31,31);

  consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);

From there the text is output and a loop is entered to display the touch screen data. The standard C 'printf' routine is used to output text to the Nintendo DS console screen and I use an ASCII escape sequence to position the cursor on the screen when I print the X and Y coordinates of the touch screen:

  printf("\n\n\tHello World!\n");
  while(1) {
    touchPosition touchXY = touchReadXY();

    printf("\x1b[10;0H");
    printf("Touch x = %d   \n", touchXY.px);
    printf("Touch y = %d   \n", touchXY.py);			
  }

This code, in 'arm9_main.cpp' is compiled by default rules in the makefile to generate ARM9 code.

Creating the DS Executable

Once run the Makefile compiles the ARM9 code. It then either compiles any ARM7 code provided, or uses the standard ARM7 code (as in this example). It then generates an executable which is the 'mini-filesystem' containing the code, files, bitmaps, icons and resources, etc. The tool that does this is 'ndstool'.

The 'ndstool' produces the file, 'demo1.nds', that will actually run on the hardware.

You can also run the 'demo1.nds' file in any DS emulator. A screenshot of the application running in an emulator is here. The full source code is available in demo1.zip and you can download the compiled demo1.nds file to test on an emulator and hardware respectively.

The complete Makefile is here and running 'make' inside the 'demo1' subdirectory should build all required files.

Conclusion

The Nintendo DS is a great system for homebrew development. It has a two screens, one being a touch screen, a microphone, 3D hardware, and Wifi. Hopefully I'll be exploring some more extensive examples in later articles. Any comments or suggestions are welcomed. See my contact details below.