NOGDUS $1670.00 has been donated to NOGDUS!
September 23, 2017, 12:44:45 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1]   Go Down
  Print  
Author Topic: DS homebrew - Nice Dev Environment  (Read 5686 times)
0 Members and 1 Guest are viewing this topic.
Richard Marks
Administrator
Offline Offline

Respect: 3425
« on: January 12, 2010, 09:23:15 PM »

Welcome to the second tutorial on DS homebrew development.
I hope that you have read the first tutorial, if not, go do that now and I'll wait.
Bear with me as I am still writing the content for this series.

In this tutorial, I am going to show you how I setup my development environment.

You will need Code::Blocks, Wine (not the drink!), and to write a couple bash scripts.

I'm running Code::Blocks 8.02. You should be able to find it in your repo.
I've got the latest version of Wine installed.

OK, now here is what we are going to do:

Create a UserTemplate for Code::Blocks to easily jump into DS development.
Create a bash script that will run our build .nds rom image in the no$gba (aka no cash) emulator in Wine for us from within Code::Blocks.

First lets go start creating the bash script.

I keep all my bash scripts in a directory called bin in my home directory.

Create a file called ngba-runner in that directory, and give it executable permissions.
The contents of the file are shown below.
Code:
#!/bin/sh
NDSPLAYER=$DEVKITPRO/PAlib/emulators/no\$gba/ngba.exe
wine $NDSPLAYER $1

Now, go into the /devkitpro/PAlib/emulators/no$gba/ directory and copy the file NO$GBA.EXE to ngba.exe
I do this to make it easier to type.

OK, thats all for the script.

Lets go add the new tool to Code::Blocks now.

Start Code::Blocks and go to Tools->Configure Tools...Click on Add
See the attached screenshot to view the configuration details.

OK. Now, lets assign an easy keyboard shortcut to the tool.
go to Settings -> Editor -> Keyboard shortcuts.

Find the new tool in the menu, then assign a keyboard shortcut to it.
I used Ctrl-Shift-F5 for mine.

Alright, that is all for that.
Now, we have some work to do. lets create the new user template.

Go into the directory .codeblocks/ in your home directory.
If you don't see a directory called UserTemplates then create it, otherwise go in that directory.

Create a directory called something useful like "New DS Game".
In this directory, you will add a bunch of stuff.

To start with, we will add the Code::Blocks project file.
We are going to write it manually. ..Well I am. You're likely going to copy/paste my text. Roll Eyes

Create a file named New-DS-Game.cbp and save it in the directory you just made.
The contents of the file are shown below.
Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="New DS Game" />
<Option makefile="CBMakefile" />
<Option makefile_is_custom="1" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="devkitARM">
<Option output="New DS Game" prefix_auto="0" extension_auto="0" />
<Option working_dir="build/" />
<Option object_output="objects/" />
<Option type="0" />
<Option compiler="gcc" />
</Target>
</Build>
<Unit filename="include/game.h" />
<Unit filename="source/main.cpp" />
<Unit filename="source/game.cpp" />
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>

I'm not going to explain it, as its not important to know.
You just create the project file and let Code::Blocks use it. Cool

Now, we need to create another file. The Code::Blocks Makefile. name it CBMakefile and put inside it:
Code:
all: devkitARM

devkitARM:
make

cleandevkitARM:
make clean

This makefile really will simply call our DS Makefile, which we will create next.
Its named Makefile and its contents are shown below.
Yes, this is the same Makefile that comes with PAlib's project template.
I'm using their Makefile, but all the rest of the code to follow is my own.
Code:
#---------------------------------------------------------------------------------
# PAlib Project Makefile by Scognito, Tom, crash and fincs
#---------------------------------------------------------------------------------

#---------------------------------------------------------------------------------
# Please uncomment (i.e. delete the '#') only one "ARM7_SELECTED" line. If unsure,
# leave it as is (with ARM7_MP3 uncommented).
#---------------------------------------------------------------------------------

ARM7_SELECTED := ARM7_MP3
#ARM7_SELECTED := ARM7_MP3_DSWIFI
#ARM7_SELECTED := ARM7_MAXMOD_DSWIFI

#---------------------------------------------------------------------------------
# If you're using EFS uncomment "USE_EFS = YES" here.
#---------------------------------------------------------------------------------

#USE_EFS = YES

#---------------------------------------------------------------------------------
# Be sure to change these default banner TEXTs. This is the name your project will
# display in the DS menu (including some flash cards). Create a custom logo.bmp
# icon for your project too!
#---------------------------------------------------------------------------------

TEXT1 := PAlib Project
TEXT2 := Change this text
TEXT3 := for your project!

#---------------------------------------------------------------------------------
# TARGET is the name of the file to output
# BUILD is the directory where object files and intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
# AUDIO is a list of directories containing audio files for use with Maxmod
# RELEASEPATH is the output directory (Optional)
#---------------------------------------------------------------------------------

TARGET      := $(shell basename $(CURDIR))
BUILD       := build
SOURCES     := source data gfx/bin
INCLUDES    := include build data gfx
AUDIO       := audio
RELEASEPATH :=

#---------------------------------------------------------------------------------
# If you need to change other parts of the make process, see the PA_Makefile:
#---------------------------------------------------------------------------------

MAKEFILE_VER := ver1

include $(DEVKITPRO)/PAlib/lib/PA_Makefile

OK, now create the following directories:

source
include
gfx

create the file game.h and save it in the include directory you just created.
create the files main.cpp and game.cpp and save them in the source directory you just created.

open your favorite graphics package, and make a developer logo screen that is 256x192 and save it in the gfx directory that you just created with the name devlogoscreen.png.

Next we will write the code for those source files that we saved.
Logged

Richard Marks
Administrator
Offline Offline

Respect: 3425
« Reply #1 on: January 13, 2010, 01:52:16 AM »

Open the .cbp file that we created using Code::Blocks so that we can finish writing this user template.

Open the game.h file into the C::B editor, and lets start writing.

I am going to provide you with a simple C style (but I'm using C++ here) framework to quickly get started with writing a game.

Code:
// game.h
// Nintendo DS Homebrew Project

/*
  ****************************************************************************
  * Copyright (c) 2010, Richard Marks, CCPS Solutions,                       *
  * Undefined Aeon Software.                                                 *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
  * "Software"), to deal in the Software without restriction, including      *
  * without limitation the rights to use, copy, modify, merge, publish,      *
  * distribute, distribute with modifications, sub-license, and/or sell      *
  * copies of the Software, and to permit persons to whom the Software is    *
  * furnished to do so, subject to the following conditions:                 *
  *                                                                          *
  * The above copyright notice and this permission notice shall be included  *
  * in all copies or substantial portions of the Software.                   *
  *                                                                          *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  *
  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
  *                                                                          *
  * Except as contained in this notice, the name(s) of the above copyright   *
  * holders shall not be used in advertising or otherwise to promote the     *
  * sale, use or other dealings in this Software without prior written       *
  * authorization.                                                           *
  ****************************************************************************
*/

#ifndef __GAME_H__
#define __GAME_H__

// include the PAlib header
#include <PA9.h>

// include the STL vector header
#include <vector>

I am including a state engine that uses function pointers in this framework.
This gives our framework a very nice and easily extended system to work with.

First lets make a type definition for our function pointer.
I've decided to use only void functions with no arguments. This suits my design well.

Code:
////////////////////////////////////////////////////////////////////////////////
// TYPE DEFINITIONS AND DATA STRUCTURES
////////////////////////////////////////////////////////////////////////////////

typedef void (*VoidFunctionPointer)();

Now we can create function pointers easily without having to remember the sometimes cryptic syntax.
Next I am adding a wrapper structure that holds the function pointers that we need.
I am separating the game logic from the game rendering code to make it easier to follow.
So our wrapper has two function pointers.

Code:
////////////////////////////////////////////////////////////////////////////////

struct StateWrapper
{
VoidFunctionPointer updatefunction_;
VoidFunctionPointer renderfunction_;
};

////////////////////////////////////////////////////////////////////////////////

The state engine structure holds a vector of pointers to our state wrapper structure, and an instance of the state wrapper structure.
The vector will hold all available states, and the instance will be used to actually execute the current state functions. If this is confusing, don't worry, it will become clearer once you see how its used.

Code:
struct StateEngine
{
std::vector <StateWrapper*> stateregistry_;
StateWrapper state_;
};

////////////////////////////////////////////////////////////////////////////////

I call my next structure an Actor, where many would call it a Sprite, I think that Actor suits the purpose better.

Code:
struct Actor
{
// sprite ID
u8 id_;

// position
u16 x_;
u16 y_;

// size
u8 w_;
u8 h_;

// velocity
s32 dx_;
s32 dy_;

// add any extra member variables you might want to give your actors
};

////////////////////////////////////////////////////////////////////////////////

The next structure is empty as we have no variables for our little project template.
Later we will use this when I show you how to write a Pong clone game for the DS! Cheesy
We create the structure now, as its going to be needed for every project.
Might as well stick it in the template!

Code:
struct GameData
{
// add your variables for your game here
};

To make it easily readable to see which states we are switching to when we get to game.cpp
I am including a list of defines
The ordering of each is important, as you will learn later.

Code:

#define DEVELOPERLOGOSCREENSTATE 0
#define GAMESTARTUPSTATE 1
#define INGAMESTATE 2
#define PAUSEDSTATE 3
#define WINSTATE 4
#define LOSESTATE 5

// add any more states that you wish to have


Now, we will declare the function prototypes.
I'm not going to explain these right now.

Code:
////////////////////////////////////////////////////////////////////////////////
// FUNCTION PROTOTYPES
////////////////////////////////////////////////////////////////////////////////

// actor engine functions
extern Actor* create_actor(u8 x, u8 y, u8 w, u8 h, u8 dx = 0, u8 dy = 0);
extern void destroy_actor(Actor* actor);

// state engine functions
extern void reset_state_engine();
extern u8 register_state(VoidFunctionPointer updatefunction, VoidFunctionPointer renderfunction);
extern StateWrapper* get_state(u8 id);
extern void set_state(u8 id);

// game state functions
extern void update_developer_logo_screen();
extern void update_startup();
extern void update_ingame();
extern void update_paused();
extern void update_win();
extern void update_lose();

extern void render_developer_logo_screen();
extern void render_startup();
extern void render_ingame();
extern void render_paused();
extern void render_win();
extern void render_lose();

// add any more game state functions that you need

// game logic functions

extern void game_init();
extern void game_main();


The globals.
There are only a few of them, as we really do not need much more.
Anything else we need can go in the GameData structure, or we could add more in our projects.
But this is fine for our template.

Code:
////////////////////////////////////////////////////////////////////////////////
// GLOBALS
////////////////////////////////////////////////////////////////////////////////

// actor engine globals
extern u8 actorscreated;

// state engine globals
extern StateEngine stateengine;

// game globals
extern GameData globaldata;

#endif

OK, next I'll show you the game.cpp

Logged

Richard Marks
Administrator
Offline Offline

Respect: 3425
« Reply #2 on: January 14, 2010, 03:19:12 AM »

Alright, sorry for the delay. I was trying to find some answers to be able to explain my code better.
I already had it working, but I didn't know what I was doing really. Grin

Code:
// game.cpp
// Nintendo DS Homebrew Project

/*
  ****************************************************************************
  * Copyright (c) 2010, Richard Marks, CCPS Solutions,                       *
  * Undefined Aeon Software.                                                 *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
  * "Software"), to deal in the Software without restriction, including      *
  * without limitation the rights to use, copy, modify, merge, publish,      *
  * distribute, distribute with modifications, sub-license, and/or sell      *
  * copies of the Software, and to permit persons to whom the Software is    *
  * furnished to do so, subject to the following conditions:                 *
  *                                                                          *
  * The above copyright notice and this permission notice shall be included  *
  * in all copies or substantial portions of the Software.                   *
  *                                                                          *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  *
  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
  *                                                                          *
  * Except as contained in this notice, the name(s) of the above copyright   *
  * holders shall not be used in advertising or otherwise to promote the     *
  * sale, use or other dealings in this Software without prior written       *
  * authorization.                                                           *
  ****************************************************************************
*/

#include "game.h"
#include "all_gfx.h"


////////////////////////////////////////////////////////////////////////////////
// ACTOR ENGINE GLOBALS
////////////////////////////////////////////////////////////////////////////////

u8 actorscreated = 0;

////////////////////////////////////////////////////////////////////////////////
// STATE ENGINE GLOBALS
////////////////////////////////////////////////////////////////////////////////

StateEngine stateengine;

////////////////////////////////////////////////////////////////////////////////
// GAME GLOBALS
////////////////////////////////////////////////////////////////////////////////

GameData globaldata;


Everything above should be really easy to understand.
Except the all_gfx.h file that we #include ..but I will get to that after I finish showing you all the rest of the code.
Just make a mental note that that file is for the embedded graphics.

Next is the actor engine implementation. Its really basic. Just 2 functions. One for creating and one for deleting actors.

Code:

////////////////////////////////////////////////////////////////////////////////
// ACTOR ENGINE FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

Actor* create_actor(u8 x, u8 y, u8 w, u8 h, u8 dx, u8 dy)
{
Actor* actor = new Actor;

actor->id_ = actorscreated;
actor->x_ = x;
actor->y_ = y;
actor->w_ = w;
actor->h_ = h;
actor->dx_ = dx;
actor->dy_ = dy;

actorscreated++;
return actor;
}

////////////////////////////////////////////////////////////////////////////////

void destroy_actor(Actor* actor)
{
if (actor)
{
delete actor;
actor = 0;
actorscreated--;
}
}

The state engine is next, and consists of four functions. I'm too tired to explain them right now.
If you can't figure it out. Ask me later. Cheesy

Code:

////////////////////////////////////////////////////////////////////////////////
// STATE ENGINE FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

void reset_state_engine()
{
stateengine.state_.updatefunction_ = 0;
stateengine.state_.renderfunction_ = 0;

if (stateengine.stateregistry_.size())
{
std::vector <StateWrapper*>::iterator iter = stateengine.stateregistry_.begin();
while(iter != stateengine.stateregistry_.end())
{
if (*iter)
{
delete *iter;
stateengine.stateregistry_.erase(iter);
}
else
{
iter++;
}
}
}
}

////////////////////////////////////////////////////////////////////////////////

u8 register_state(VoidFunctionPointer updatefunction, VoidFunctionPointer renderfunction)
{
StateWrapper* state = new StateWrapper;

state->updatefunction_ = updatefunction;
state->renderfunction_ = renderfunction;

u8 id = stateengine.stateregistry_.size();
stateengine.stateregistry_.push_back(state);

return id;
}

////////////////////////////////////////////////////////////////////////////////

StateWrapper* get_state(u8 id)
{
if (id >= stateengine.stateregistry_.size())
{
return 0;
}

return stateengine.stateregistry_.at(id);
}

////////////////////////////////////////////////////////////////////////////////

void set_state(u8 id)
{
StateWrapper* wrapper = get_state(id);
if (!wrapper)
{
return;
}

stateengine.state_.updatefunction_ = wrapper->updatefunction_;
stateengine.state_.renderfunction_ = wrapper->renderfunction_;
}

Next we've got the update functions for each game state.

Code:

////////////////////////////////////////////////////////////////////////////////
// GAME STATE FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

void update_developer_logo_screen()
{
if (Pad.Newpress.A)
{
globaldata.beginfade_ = true;
}
}

////////////////////////////////////////////////////////////////////////////////

void update_startup()
{
// jump directly to the in-game state
set_state(INGAMESTATE);
}

////////////////////////////////////////////////////////////////////////////////

void update_ingame()
{
// pause the game if you press the start button
if (Pad.Newpress.Start)
{
PA_ClearTextBg(1);
set_state(PAUSEDSTATE);
}

// "win" if you press the A button
if (Pad.Newpress.A)
{
PA_ClearTextBg(1);
set_state(WINSTATE);
}

// "lose" if you press the B button
if (Pad.Newpress.B)
{
PA_ClearTextBg(1);
set_state(LOSESTATE);
}
}

////////////////////////////////////////////////////////////////////////////////

void update_paused()
{
// resume the game if you press the start button
if (Pad.Newpress.Start)
{
PA_ClearTextBg(1);
set_state(INGAMESTATE);
}
}

////////////////////////////////////////////////////////////////////////////////

void update_win()
{
// reset when the Select button is pressed
if (Pad.Newpress.Select)
{
PA_ClearTextBg(1);
PA_LoadBackground(0, 0, &devlogoscreen);
set_state(DEVELOPERLOGOSCREENSTATE);
}
}

////////////////////////////////////////////////////////////////////////////////

void update_lose()
{
// reset when the Select button is pressed
if (Pad.Newpress.Select)
{
PA_ClearTextBg(1);
PA_LoadBackground(0, 0, &devlogoscreen);
set_state(DEVELOPERLOGOSCREENSTATE);
}
}

I will have to explain all that another time, as I am fading fast. Its 2am.
Next are the rendering functions for all the game states.

Code:

////////////////////////////////////////////////////////////////////////////////

void render_developer_logo_screen()
{
PA_OutputSimpleText(1, 0, 0, "Press the A button.");

if (globaldata.beginfade_)
{
globaldata.beginfade_ = false;

// fade the screen to black
for (s16 brightness = 0; brightness >= -31; brightness--)
{
PA_SetBrightness(0, brightness);
// delay the fade by waiting for an extra frame
PA_WaitForVBL();
PA_WaitForVBL();
}

PA_ResetBgSysScreen(0);
PA_SetBrightness(0, 0);
PA_ClearTextBg(1);

// change to the next state
set_state(GAMESTARTUPSTATE);
}
}

////////////////////////////////////////////////////////////////////////////////

void render_startup()
{
}

////////////////////////////////////////////////////////////////////////////////

void render_ingame()
{
PA_OutputSimpleText(1, 0, 0, "The game is in play.");
PA_OutputSimpleText(1, 0, 2, "Press [Start] button to pause.");
PA_OutputSimpleText(1, 0, 4, "Press [A] button to \"win\".");
PA_OutputSimpleText(1, 0, 6, "Press [B] button to \"lose\".");
}

////////////////////////////////////////////////////////////////////////////////

void render_paused()
{
PA_OutputSimpleText(1, 0, 0, "The game is paused.");
PA_OutputSimpleText(1, 0, 2, "Press [Start] button to resume.");
}

////////////////////////////////////////////////////////////////////////////////

void render_win()
{
PA_OutputSimpleText(1, 0, 0, "The game has been won.");
PA_OutputSimpleText(1, 0, 2, "Press [Select] button to reset.");
}

////////////////////////////////////////////////////////////////////////////////

void render_lose()
{
PA_OutputSimpleText(1, 0, 0, "The game has been lost.");
PA_OutputSimpleText(1, 0, 2, "Press [Select] button to reset.");
}

Alright, heres the end of the game.cpp file.
The init and main game loop.

Code:

////////////////////////////////////////////////////////////////////////////////
// GAME LOGIC FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

void game_init()
{
// initialize PAlib
PA_Init();

// load the default font for top screen on bg #2
PA_LoadDefaultText(1, 2);

// load the developer logo screen into the bottom screen as bg #0
PA_LoadBackground(0, 0, &devlogoscreen);

// init the screen fader flag to false
globaldata.beginfade_ = false;
}

////////////////////////////////////////////////////////////////////////////////

void game_main()
{
bool running = true;
while(running)
{
stateengine.state_.updatefunction_();
stateengine.state_.renderfunction_();
PA_WaitForVBL();
}
}

Next I'll show the main.cpp source.

Code:
// main.cpp
// Nintendo DS Homebrew Project

/*
  ****************************************************************************
  * Copyright (c) 2010, Richard Marks, CCPS Solutions,                       *
  * Undefined Aeon Software.                                                 *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
  * "Software"), to deal in the Software without restriction, including      *
  * without limitation the rights to use, copy, modify, merge, publish,      *
  * distribute, distribute with modifications, sub-license, and/or sell      *
  * copies of the Software, and to permit persons to whom the Software is    *
  * furnished to do so, subject to the following conditions:                 *
  *                                                                          *
  * The above copyright notice and this permission notice shall be included  *
  * in all copies or substantial portions of the Software.                   *
  *                                                                          *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  *
  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
  *                                                                          *
  * Except as contained in this notice, the name(s) of the above copyright   *
  * holders shall not be used in advertising or otherwise to promote the     *
  * sale, use or other dealings in this Software without prior written       *
  * authorization.                                                           *
  ****************************************************************************
*/

#include "game.h"

int main()
{
// register the states into which the game can be placed
/* #0 */ register_state(&update_developer_logo_screen, &render_developer_logo_screen);
/* #1 */ register_state(&update_startup, &render_startup);
/* #2 */ register_state(&update_ingame, &render_ingame);
/* #3 */ register_state(&update_paused, &render_paused);
/* #4 */ register_state(&update_win, &render_win);
/* #5 */ register_state(&update_lose, &render_lose);

// set the startup game state
set_state(DEVELOPERLOGOSCREENSTATE);

// initialize the game
game_init();

// start the game
game_main();

return 0;
}

OK. One last thing before I head to bed.

In order to use the devlogoscreen.png that we made in the gfx directory, we have to use the PAGfx tool to convert the graphics into C source and .bin files that will be linked into the final .nds rom file.

You need to have Mono installed. Check your repositories for it.
Now, copy the file PAGfx.exe from this directory: /devkitpro/PAlib/tools/PAGfx/Mono/
and paste it into the gfx directory in your project template.

Now, you must create another text file in the gfx directory.
Name it PAGfx.ini and put in it the following text:
Code:
#TranspColor Magenta
 
#Sprites :

#Backgrounds :
devlogoscreen.png TileBg

#Textures :

Now, run the following command in your terminal from within the gfx directory:
Code:
$ mono PAGfx

and if all went well, you can now build your project and you should get an .nds rom!

Whew!
Sorry for the briefness, I'll explain everything in more detail another day.
Good night!
Logged

Tags:
Pages: [1]   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines
.: Theme by Richard Marks :.
Valid XHTML 1.0! Valid CSS!