Post

NDS Programming (Part 3)

NDS Programming (Part 3)

3.1 Development Environment

The best choice for NDS development is Nintendo’s official development kit — excellent, with complete development and debugging tools (I’ve never seen one). But it’s expensive and not for sale to just anyone — you need a good relationship with Nintendo. So common people can’t get it unless they join Konami, Namco, etc. The dev tools URL is http://www.warioworld.com.

If you can’t be an imperial guard, be a folk hero. A group of skilled people abroad built their own DIY development environment. They call themselves Homebrew. This environment is called devkitPro. All our development work below uses devkitPro.

devkitPro supports multiple game consoles — not just NDS, but also GBA, PSP, NGC, and GP32. Some use MIPS, some PowerPC — beyond our scope. We’ll focus on NDS.

3.2 Installing and Configuring the Development Environment

devkitPro is a SourceForge.net project. Get the latest from SourceForge at http://sourceforge.net/projects/devkitpro. A Google search should turn up many links.

devkitPro is fully open source. You can download source code for almost all libraries and tools from SourceForge. If you’re a programmer who wants to understand every detail (like me), reading devkitPro’s code is a good choice. Like other open source projects, the NDS documentation in devkitPro is pathetically minimal. To learn how to write programs and use library functions, there’s basically one approach — read the code.

Download an exe file named something like devkitProUpdater-1.2.7.exe. This isn’t directly an installer, but it handles online installation of the latest devkitPro. If your internet isn’t slow and your hard drive isn’t small, select all options — that’s my style. Install it on the root directory, e.g., D:\devkitPro.

After installation, configure three environment variables: DEVKITARM (point to devkitARM directory), DEVKITPRO (point to devkitpro root). Important: these paths must use Unix-style paths — use “/” not “". D drive should be written as “/d/” not “D:”. Also set the PATH to include the compiler and other tool directories. You can set environment variables via “My Computer” → Properties, but I prefer writing a batch script to set them without affecting the whole system.

My batch script:

@echo off REM REM Written by Jason He; Set up NDS development environment REM 4/19/2006 REM REM set environment set DEVKITARM=/D/devkitPro/devkitARM set DEVKITPRO=/D/devkitPro REM set path set PATH=%PATH%D:\devkitPro\devkitARM\arm-elf\bin;D:\devkitpro\devkitarm\bin;D:\devkitpro\msys\bin; cd /d D:\devkitPro\examples\nds\ echo Welcome to enter NDS development world!

Save this as nds.bat. Then create a shortcut pointing to: %SystemRoot%\system32\cmd.exe /K D:\devkitPro\nds.bat. Double-click to open the development environment.

3.3 Compiling the NDS Hello World

Before writing our own program, let’s compile and run devkitPro’s built-in example. In the command-line environment, cd to D:\devkitPro\examples\nds\Graphics\2D\hello_world. Just type make and compilation begins. After completion, the hello_world directory will contain several new files — the most important being hello_world.nds. If you’ve used a flash cart, you know .nds files are ROM files that NDS can run.

3.4 Running Hello World

If you have an NDS + flash cart, just copy the file to the flash cart and run it like any other NDS game. On my Super Card SD, it runs directly without conversion.

If you have an NDS but no flash cart, there’s a software called WifiMe that can download hello_world.nds from PC to NDS via WiFi. But it requires high-end PC WiFi hardware. I haven’t tried WifiMe, so I won’t detail it.

If you don’t even have an NDS, you can still run it with an NDS emulator. Since NDS hardware is complex, current emulators are primitive — can’t run commercial games, but fine for example code.

A promising emulator is ideas, still being updated. There’s also ensata (leaked Nintendo internal emulator), but it’s no longer updated. Several other emulators exist — choose as you like.

We can develop and debug our own games this way.

3.5 Code Analysis

3.5.1 Hello World Directory Structure

Now that Hello World runs on NDS, let’s look at the code to understand how it works.

Directory structure after make (I’ve added explanations):

hello_world.arm9 // Compiled output, ARM binary hello_world.elf // ELF format binary hello_world.nds // Executable NDS ROM Makefile // Build script build/ // Build output, temporary files hello_world.map // Map file main.d // Dependency file main.o // Object file include/ // Header files (empty) source/ main.cpp // Source file

Before make, only two files existed: makefile and main.cpp. To create a new project, you just need these two. You can copy the arm9 or combined template from D:\devkitPro\examples\nds\templates\.

3.5.2 main.cpp

The main.cpp code is short — no assembly. It consists of several sections:

Section 1: Header includes

#include <nds.h> #include <nds/arm9/console.h> #include <stdio.h>

Section 2: Global variable and Vblank()

volatile int frame = 0; void Vblank() { frame++; }

Section 3: main() function

int main(void) { touchPosition touchXY; irqInit(); irqSet(IRQ_VBLANK, Vblank); irqEnable(IRQ_VBLANK); videoSetMode(0); videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE); vramSetBankC(VRAM_C_SUB_BG); SUB_BG0_CR = BG_MAP_BASE(31); BG_PALETTE_SUB[255] = RGB15(31,31,31); consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16); iprintf(" Hello DS dev'rs\n"); iprintf(" www.devkitpro.org\n"); iprintf(" www.drunkencoders.com"); while(1) { swiWaitForVBlank(); touchXY = touchReadXY(); iprintf("\x1b[10;0HFrame = %d", frame); iprintf("\x1b[16;0HTouch x = %04X, %04X\n", touchXY.x, touchXY.px); iprintf("Touch y = %04X, %04X\n", touchXY.y, touchXY.py); } return 0; }

Try modifying the code and recompiling. Homework: the default text is white — can you change the color?

3.5.3 Makefile

The makefile automates compilation. make.exe reads it and decides how to build the system. Because of makefile, just type make and the system builds automatically.

Due to Windows programmers being “spoiled” by IDEs, makefiles often intimidate. If you’re afraid of makefiles, Google some tutorials.

This makefile is a template. For new projects, just modify a few macros. Key parts:

include $(DEVKITARM)/ds_rules TARGET := $(shell basename $(CURDIR)) BUILD := build SOURCES := gfx source data INCLUDES := include build LIBS := -lnds9 CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) BINFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.bin)))

With this, we know which files to compile, which libraries to link, and the output name. When creating a new project, just modify these settings.

This post is licensed under CC BY 4.0 by the author.