Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) Qt CreatorUbuntuNDS 'Hello World' using Qt Creator under Ubuntu for NDS

 

A Hello World program for NDS, using Qt Creator under Ubuntu is not simple. This page actually shows how to cross-compile a 'Hello World' Qt Creator project from Ubuntu to NDS?

 

 

The tool ndsmake allows to cross-compile directly from Qt Creator under Ubuntu to NDS.

 

 

 

 

 

Prerequisites

 

devkitpro needs to be installed in /opt/devkitpro. Follow the steps described by [1]. For the Qt Creator project to compile, also install the libnds source code (the libnds-src-1.4.7 tarball).

 

 

 

 

 

Folder structure

 

I have used the following folder structure (as in the downloadable project above):

 

 

 

 

 

main.cpp

 

A Hello World program for NDS additionally needs to call 'consoleDemoInit' from the libnds library and end in a waiting loop: if the program reaches the end of main, it terminates.

 

#include <nds.h>
#include <iostream>

int main()
{
  //consoleDemoInit is obligatory
  consoleDemoInit();

  std::cout << "Hello NDS\n";

  //Infinite waiting
  while (1) {}
}

 

 

 

 

 

Project file

 

A valid Qt Creator project file is practical for development. It will result in an unknown OS's executable.

 

#-------------------------------------------------
#
# Project created by QtCreator 2010-10-07T22:25:11
#
#-------------------------------------------------
INCLUDEPATH += /opt/devkitpro/libnds-1.4.7/include
INCLUDEPATH += /opt/devkitpro/libnds-src-1.4.7/include/nds
INCLUDEPATH += /opt/devkitpro/devkitARM/arm-eabi/include
LIBS += -L/opt/devkitpro/libnds-1.4.7/lib -lnds9
LIBS += -L/opt/devkitpro/devkitARM/arm-eabi/lib -lstdc++
DEFINES += ARM9
TARGET = CppHelloWorldQtCreatorUbuntuNds
CONFIG   += console
CONFIG -= qt
CONFIG   -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
QMAKE_CC = /opt/devkitpro/devkitARM/bin/arm-eabi-g++
QMAKE_CXX = /opt/devkitpro/devkitARM/bin/arm-eabi-g++
QMAKE_LINK = /opt/devkitpro/devkitARM/bin/arm-eabi-g++
QMAKE_LFLAGS = -T/opt/devkitpro/devkitARM/arm-eabi/lib/ds_arm9.ld

 

 

 

 

 

Makefile

 

The Makefile generated by Qt Creator will not result in a valid .nds file. This is a correct Makefile:

 

#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------

ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif

include $(DEVKITARM)/ds_rules

#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := $(shell basename $(CURDIR))
BUILD := build
SOURCES := gfx source data  
INCLUDES := include build /opt/devkitpro/libnds-1.4.7/include

#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -mthumb -mthumb-interwork

CFLAGS := -g -Wall -O2\
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
-ffast-math \
$(ARCH)

CFLAGS += $(INCLUDE) -DARM9
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions

ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -mno-fpu -Wl,-Map,$(notdir $*.map)

#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lnds9


#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(LIBNDS)

#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------

export OUTPUT := $(CURDIR)/$(TARGET)

export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)

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)))

#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

export OFILES := $(BINFILES:.bin=.o) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)

export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)

export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)

.PHONY: $(BUILD) clean

#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile

#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds $(TARGET).ds.gba


#---------------------------------------------------------------------------------
else

DEPENDS := $(OFILES:.o=.d)

#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).nds : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)

#---------------------------------------------------------------------------------
%.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
$(bin2o)


-include $(DEPENDS)

#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

 

 

 

 

 

make

 

Qt Creator does not generate a valid executable. Using a terminal, navigate to the folder with the important makefile. Then call make:

 

make

 

This hopefully results in the following success output:

 

Nintendo DS rom tool 1.48 - Jul  7 2010
by Rafael Vuijk, Dave Murphy, Alexei Karpenko
built ... CppHelloWorldQtCreatorUbuntuNds.nds

 

 

 

 

 

Running the program

 

The generated NDS executable (CppHelloWorldQtCreatorUbuntuNds.nds) can be run in an NDS emulator or copied on an R4 (and other ways I do not know the details (and success) of, like WiFi-ing the code, or passing through a Gameboy Advanced)

 

Personally, I call the NDS emulator from command line:

 

desmume CppHelloWorldQtCreatorUbuntuNds.nds

 

 

 

 

 

References

 

  1. Devkitpro wiki 'Getting started/devkitARM'
     
    The first thing that you need to do is create a folder for the devkitPro toolchains. Start by opening a terminal - on OSX use the apple key + space, then type terminal. In the terminal window type the following command to create a new folder - all these commands are executed by pressing the return key. You'll need to create the initial folder with root privileges

    sudo mkdir -p /opt/devkitpro

    Once you've done that you can grant world access to the folder so you can extract the archives with normal privileges.

    sudo chmod 777 /opt/devkitpro

    When we're done the layout for your devkitPro folder should end up like this, each folder links to the appropriate sourceforge package.

    devkitpro
       |
       +-- devkitARM
       +-- examples
       |     |
       |     +-- gba
       |     +-- gp32
       |     +-- nds
       +-- libgba
       +-- libmirko
       +-- libnds

    Nothing else should be placed inside these folders unless otherwise instructed by the devkitPro toolchain maintainers. On Windows several of these folders are removed and replaced by the update system.

    The first package to install is the devkitARM tarball, obtained from the devkitARM link shown above. Download the appropriate tarball for your host platform - the files are named as devkitARM_<revision>-<processor>-<os>.tar.bz2. For OSX we provide universal binaries - devkitARM_<revision>-osx.tar.bz2.

    Once the file is downloaded then you need to extract it into the devkitpro folder

    cd /opt/devkitpro
    tar -xvjf <file you downloaded>

    Obviously replace <file you downloaded> with the name of the file obtained from sourceforge. On OSX you can simply drag & drop the downloaded file into the terminal window to get the file path.

    Now you need to obtain the support libraries for your target platform - we'll start with the Nintendo DS libraries.

    Download the latest binary of libnds then create a new folder and extract the tarball from the terminal window as before. Note: This is the file without "-src-" in the name.

    mkdir libnds
    cd libnds
    tar -xvjf <libnds tarball>

    Again, replace <libnds tarball> with the name of the file obtained from sourceforge. On OSX you can simply drag & drop the downloaded file into the terminal window to get the file path.

    Now download libfat-nds, this is the libfat-nds tarball and may not be in the release at the top of the list. You may need to expand the second section to find the appropriate file. This should be extracted to the same folder as the libnds tarball earlier.

    tar -xvjf <libfat-nds tarball>

    Download the dswifi tarball and extract in the same place.

    tar -xvjf <dswifi tarball>

    Download the maxmod tarball and extract in the same place.

    tar -xvjf <maxmod-nds tarball>

    Download the libfilesystem tarball and extract in the same place.

    tar -xvjf <libfilesystem tarball>

    Lastly you'll need the arm7 binary that handles the wifi, audio and touchscreen on the DS.

    Download the default arm7 tarball and extract, still inside the libnds folder.

    tar -xvjf <default arm7 tarball>

    Now all that remains for DS programming is the examples archive. Move back to the devkitpro folder and create an examples/nds folder.

    cd ..
    mkdir -p examples/nds
    cd examples/nds

    Grab the nds examples archive from sourceforge & extract it here.

    tar -xvjf <examples tarball>

    Add these variables in your execution environment, for instance, editing the .bashrc file located in your home folder:

    export DEVKITPRO=/opt/devkitpro
    export DEVKITARM=$DEVKITPRO/devkitARM

     

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict