2006/10/05

Subtleties of Console Development

I've been trying to write my own sprite management code as a sort of exercise in C++ as well as the DS. I was having trouble getting things displayed correctly and thrashed back and forth changing one thing and then another, writing directly to memory rather than using DMA, etc. etc. etc. trying to figure out what was wrong. I'm a pretty careless programmer, so I assumed that it was either my mistake or the result of developing on an only partially documented system. Not having figured out a good way to do debugging obviously doesn't help either.

And, I finally figured it out. It was in code I wasn't even looking at; apparently I was trying to do something the system hadn't been initialized to do.

You can pass a number of flags to videoSetMode() when you are initializing the display, and apparently DISPLAY_SPR_1D_BMP is necessary in order to display 16-bit, non-palettized sprites. It seems obvious given that the ATTR0_BMP flag must be set in the sprite's OAM entry, but I didn't even know I should be looking for it.

Further, apparently you can't mix ATTR0_BMP and non-BMP sprites. At least, I can't get both to display at the same time. Perhaps I need another flag....

2006/10/02

Lua, Lua... Oh no! Me gotta go

Been messing around with Lua a bit the last few days. Can't remember how I came across it but it's performance against other languages (1, 2) made me decide to give it a serious look. Particularly given how well it did against the dark lord Perl and my personal favorite, Python. Found several other things where people remarked how easy it was to embed in C/C++ programs so I figured it was worth the time.

Downloaded the 5.1.1 source from www.lua.org and had it compiled under cygwin in a matter of seconds without any problems. Found a decent selection of tutorials, and an online version of Programming in Lua but found they were a bit thin when it came to embedding Lua in C. Thought I hit the jackpot with this writeup at debian.org but was amazed to find out that it no longer worked despite being less than a year old.

After an hour or two of (re-)reading the sources above, looking at header files, etc. I was able to figure out enough to get a demo working. It's pretty slick. You can write a C program like:

#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
int
main( int argc, char ** argv ){
int value = 1;

// Initialize Lua
lua_State *L = lua_open();

// Load various Lua libraries
luaopen_base( L );
luaopen_table( L );
//luaopen_io( L ); // Not sure why but I get a PANIC if i try to load this
luaopen_string( L );
luaopen_math( L );

luaL_loadfile( L, "3.lua");
lua_pcall( L, 0, 0, 0 ); // Have to parse it once or getglobal() will fail

printf( "C: value is %d\n", value );

lua_getglobal( L, "test" );
lua_pushnumber( L, value );
lua_pcall( L, 1, 1, 0); // 1 argument, 1 result
value = (int)lua_tonumber( L, -1 ); // Lua arrays are 1-indexed /boggle

printf( "C: value is %d\n", value );

// Cleanup
lua_close( L );

return 0;
}


And then you create a script called 3.lua like:
function test (x)
return (x + 1)
end


And your output should be:
C: value is 1
C: value is 2


Pretty slick. Doesn't make the C program terribly huge, either. The luaopen_*() functions load libraries which naturally increase the size of executable. The plain C executable was about 8k, with the four libraries above about 130k, or with just "base" alone it was 114k. OK, OK, so the executable is about 12x larger... it's still neat seeing as how you now have full access to a fairly powerful scripting engine without having to recompile.

I'm positive I can put this to good use in at least one of my projects. Why do I mention it here? Saw a bunch of comments about it being used for scripting, etc. in various video games.... good stuff.

2006/09/27

Sprites, Tiles and Their Unholy Union in Sprite Memory

There are several demos both packaged with devkitpro and in various tutorials that use sprites, but they almost all involve drawing one sprite (possibly multiple times) on screen. As I started trying to add to the demos, I found that I was having trouble drawing more than two sprites.

Several examples setup sprite OAM (Object Attribute Memory) as follows:
int spriteID = 0; // the sprite id
int spriteX = 0; // X position
int spriteY = 0; // Y position
sprites[0].attribute[0] = ATTR0_COLOR_16 | ATTR0_SQUARE | spriteX;
sprites[0].attribute[1] = ATTR1_SIZE_16 | spriteY;
sprites[0].attribute[2] = spriteID;


ATTR0_COLOR_16 specifies 16 color mode, ATTR0_SQUARE says the sprite is square (heigth = width), ATTR1_SIZE_16 makes the sprite 16x16.

And then sprite data is written like:
/* size of sprite in words (word is 16 bits) = 16 * 16 / 4
* 16-color mode = 4 bits per pixel (2 pixels per byte, or 4 per word)
* 16 pixel by 16 pixel sprite, 4 pixels per word = 16 * 16 / 4 bytes
*/
int size = 64;
int pali = 2; // Palette index
for( int i = 0; i < size; i++ ){
SPRITE_GFX[ spriteID * size + i] = (pali << 12) | (pali << 8) | (pali << 4) | pali;
}


This just fills the entire sprite area with whatever color is defined at index 2 of the palette.

What was confusing me was the representation of sprites as tiles, how they are stored in sprite memory, the allocation of sprite IDs, and the way that sprite OAM uses sprite memory. If you are unclear on the meaning of tiles, check out Patater's tutorial.

Basically, tiles are 8 pixel by 8 pixel images, and all sprites are made up of them. What's important to understand here is that the sprite IDs reference the location of tiles in memory. If a sprite is larger than 8x8 then it uses more than one tile and covers a range of tile/sprite IDs. This means that two 16x16 sprites (each 4 tiles) stored in adjacent memory can't be allocated ID 0 and ID 1. The two images will overlap since the 16x16 sprite at ID 0 is defined as tiles 0 to 3, and the 16x16 sprite at ID 1 is defined as tiles 1 to 4.

You have to keep in mind the size of one pixel in memory and the dimensions of the sprite both when storing pixel data in sprite memory, and when allocating sprite IDs in sprite OAM.

In the example above (two 16-color 16x16 sprites):

  1. The first sprite is assigned ID 0 (8x8 tiles 0 to 3) and is stored in 128 bytes (16pix * 16pix / 2 pixels-per-byte) of sprite memory starting at index 0.

  2. The second sprite should be assigned ID 4 (8x8 tiles 4 to 7) and is stored in 128 bytes of sprite memory starting at index 128 + 1 (right after the first sprite).



NOTE: In the code above I offset by 64 rather than 128 because we are using word-aligned (16 bit) rather than byte-aligned (8 bit) addressing since SPRITE_GFX is an array of 16-bit values.

2006/09/15

PassMes, M3s, and GBAMPs, oh my!

Odds are, if you've been interested in running homebrew code on the Nintendo DS, you were probably more than a little lost/confused initially (if you ever got it figured out). There *is* an active community out there, but most of the information is spread out across different bulletin boards, in different threads, often containing more than a little incorrect and/or outdated information, and using terminology/abbreviations you're probably not yet familiar with. Maybe I'm just the kind of person that really likes to have a good grasp of what I'm doing and what all my options are rather than running with "just do X" as posted by some_random_guy023.

Far and away the best write up I've come across is the Running Homebrew wiki entry at DSLinux. It does a nice job of presenting the various requirements and what your options are, the between them such as in which circumstances you can use them and what the pros/cons are, as well as providing links (via Pocketheaven) to specific products/manufacturers.

Check it out and save yourself a lot of headache/irritation.

2006/09/13

Virtual Desktop Environments for Windows XP

Anyone that has experience with a *nix (and possibly other non-Microsoft OSes) environment is probably frequently annoyed with XPs lack of virtual desktops. After you've been working for a while, or work on several different projects simultaneously, it doesn't take long to end up in task bar hell. Alt-tab and friends are rendered nigh completely useless.

I got fed up with this in the course of my DS programming and decided to seek out a virtual desktop environment add-on for XP. I should first point out that my standard of comparison is IceWM, a light-weight, configurable window manager with hotkeys for pretty much everything. If you're not familiar with IceWM, don't worry, the idea is to have a very simple, responsive virtual desktop environment that is easy to navigate with shortcuts. Further, I use a laptop with a second monitor, so dual-head support is really key. Finally, it needs to be free. There are probably pretty good programs that you can pay for, but poor students like me can't eat and pay for each and every little piece of software we use.

Spoiler alert!!!!


I ended up deciding on Virtual Dimension as it provided pretty much everything I was looking for. Features:

  • Small- memory usage comes in around 6.4MB.

  • Shortcuts for all the things I was looking for: move a window to different desktop, and move to different desktop.

  • Fast switching between desktops.

  • Supports a variable number of desktops and configurable layout of them.

  • Easily to understand/configure/use.

  • No strange behavior with a second monitor.

It even has some features I didn't expect/require but appreciate:

  • Support for a shortcut to maximize the height of the current window (this is awesome and loved it in IceWM yet so few window managers actually support it).

  • Lets you set the transparency of windows.

  • Configurable preview window for all desktops: auto-hide, transparency, always on top, etc. This is actually really slick and I like it more and more as I continue using it.

  • Non-intrusive, configurable indicator of the desktop you just switched to (WindowMaker-esque).

  • Can right-click title bars to access VD functionality.

  • Is open source so I can always add a feature myself if nobody else does.

  • Per-desktop wallpaper and switch-to hotkeys.

  • Can minimize windows to the systray and sticky them to all desktops.

The drawbacks:
  • Not many configuration options for using the mouse to switch desktops. Can change desktops, but no way to get the mouse to warp to the opposite side of the neighboring desktop as if the mouse had intuitively moved to the adjoining edge.

There's a screenshot up at their website that shows what your desktop ends up looking like. Been using it for about a week now and have absolutely no complaints. Damn satisfied. If I had to guess, I'd be willing to bet the devs are all ex-*nix users.


I actually test-drove quite a few other environments that I feel like I would mention if you, like me, found that there are quite a few virtual desktop programs floating around and wondering whether they're worth bothering with.

Honorable mention:


These are the virtual desktop programs that were really quite good and I would consider using were it not for a problem or lack of some feature that was a deal breaker for me. If Virtual Dimension doesn't quite cut the mustard for you, you're probably best off looking at these first.

VirtuaWin


Homepage: http://virtuawin.sourceforge.net/
This is probably my second choice, and a very close one at that. I kept writing up draw-backs for it and then as I used it more and more I found out how to do the things I wanted. It's probably one of the most configurable (yet not overwhelmingly so) options here.

The Good:
  • Available hotkeys: switching to a particular desktop, cycling through desktops, making a window sticky.
  • Provides really excellent support for using the mouse to switch desktops: can alter the delay, whether or not the mouse cursor warps to the adjacent edge or stays on the same side of the screen, etc.
  • Desktop switching is very fast.
  • Small- 5.8MB
  • Has some kind of plug-in architecture.
  • Quite a lot of configuration options.
  • Can change the layout of screens and add/remove desktops.
The Bad:
  • Desktop cycling (being able to wrap around from the last desktop to the first) isn't enabled by default, you have to enable it from the "Expert" tab in "Setup".
  • No hotkey to move windows between desktops, would be nice to have a few more shortcuts (possible with a plug-in?).
  • When you move to another desktop dragging a window, rather than the window staying with the mouse it appears at the original location of the window in the new desktop.
  • No good "current desktop" indicator or desktop preview tool. It's in the systray which isn't visible if you have your task bar set to autohide.
The Ugly:
  • None?


Deskillusion


Homepage: http://www.unfate.f2g.net
(homepage seems to be down a lot so you can get it from download.com)
The Good:
  • Small- Just over 6MB of memory.
  • Fast- Desktop switches are real quick.
  • Unobtrusive indication of desktop you just switched to.
  • Configurable shortcuts to switch to other desktops.
  • Easy to add/remove virtual desktops.
  • Simple to setup/use.
  • No problems with multiple monitors.
  • Right-clicking a window title bar allows you to: send it to another desktop, or sticky it.
The Bad:
  • Too simple: lack of advanced configuration options, shortcuts.
  • No way to set shortcut to move a window to another desktop- have to right-click title bar.
The Ugly:
  • Occasionally some weirdness- windows appearing on more than one desktop, window order changing, etc.


SDesk


Homepage: http://www.nearestexit.com/sdesk/
This is actually different from the other programs as it doesn't create virtual desktops, it expands the size of the desktop beyond the size of the screen.

The Good:

  • Small- under 6MB
  • Fast- probably the fastest of them all since it doesn't actually create virtual desktops, it just expands the one you've got
  • Very cool usage of a second monitor: it your secondary monitor is positioned above your primary display then moving to a lower part of the desktop will move what was shown in the primary display up into the secondary display. Very intuitive.
  • An optional Unix-esque preview window
  • Shortcuts for pretty much everything- using either/both the keyboard or/and mouse

The Bad:
  • Not virtual desktops, so you still end up with all your tasks dumped onto one task bar.
  • More difficult to configure than some of the others.
  • Settings are peculiar when a second monitor is used that is a different resolution than the primary display- have to set the width to the resolution of the larger monitor in order to correctly move by the size of a desktop

The Ugly:
  • Nasty handling of a secondary display:
    • When the secondary display ends up showing a part of the desktop outside that controlled by SDesk, moving away and then moving back causes all the windows displayed on the secondary display to be reset.
    • If the secondary display uses a different resolution than the primary display then windows will also be repositioned when moving to different parts of the desktop.
  • No longer under development/maintained?- last updated in 2003...
I was completely in love with SDesk until I found how it handled a secondary monitor. It's functionality seems to clash with that used by Windows for dual-head support, especially if the two displays use a different resolution.

The Rest:


These are the virtual desktop programs that I just don't consider usable. You may find a real gem here depending on your needs/usage, but to each their own.

Virtual Desktop Toolbox


This was the most downloaded program from download.com. I figured its success was a sure sign of its suitability. I just couldn't see myself using it, however:
  • Way too big- the download weighs in at over 12MB. When you look at the others and see that they're generally under 1MB you can't help but hear the Sesame Street song "One of These Things is not Like the Others".
  • Way too big part 2- at runtime it consumes almost 18MB of memory... uh, yeah.
  • Bigger just isn't better:
    • Speed- was one of the slowest of all the programs I tested while switching desktops.
    • Configuration was over-complicated: I found myself hunting through menus trying to disable annoying things that are enabled by default, or enabling things I wanted.
  • Didn't seem to be any way to just move a window from one desktop to another.
  • It also seemed to randomly cause programs to crash at runtime or on exit.
In its defence it did provide some features that none of the other programs had: the ability to setup special "scenarios" for certain usage situations, and the ability to specify settings that are automatically applied to specific programs that run. It also provided several different tools for managing windows, displaying the desktops, etc.

I just found it too slow, complicated, annoying to be worth the trouble. I've never seen a virtual desktop tool that was so complicated that it needed wizards, and I think there's a good reason why.

Microdesk


Pretty slick looking tool that comes default with 10 desktops and a toolbar similar to that used by Microsoft's IME. Didn't really match my needs, however:
  • Bit on the heavy site- 9.4MB of memory.
  • Requires some kind of registration.
  • No simple/quick way to move windows from one desktop to another. Requires use of the "Application Manager".
  • Configuration/usage was a bit more complicated/non-intuitive than really necessary.
  • Not very refined:
    • Clicking "Options" pops up an error-like window before actually showing the options window.
    • Seemed to have some conflicts with the taskbar: sometimes I would switch desktops and the taskbar would be completely missing on one desktop while it wouldn't auto-hide on others.
It was the prettiest of the virtual desktop tools, however. They did a nice job working on neat effects and graphics for the UI, but their time would have been better spent making it more functional imho.

MultiDesk


  • I couldn't even figure out how to use it, honestly. It claimed to have created 10 virtual desktops, but I never found any way to actually switch to them.
  • Didn't seem to be any way to specify hotkeys of any kind.
Maybe this program is just too clever for me. But, it looks like it hasn't been updated since 2002, so I think it's just no longer usable on XP sp2.

Microsoft's Virtual Desktop Manager XP PowerToy


This is pretty simple and easy to use. You can specify a different wallpaper for each desktop, and shortcuts to move between them. Even provides a cool, preview of all four desktops and the ability to select the one you want to switch to.

Ultimately I decided against using it because:
  • No way to cycle backwards/forwards through the desktops, you can only move to a specific one.
  • No easy way to move a window to a different desktop.
  • Pretty slow desktop switches (I believe it was the slowest).
  • Forced to use 4, and only 4 virtual desktops.
Microsoft deserves credit for having the lightest-weight program out of all the ones I looked at: a tiny 3MB and change. Think this may be a first for the boys from Redmond.

PowerPro


It's actually a bit unfair to compare PowerPro to the other virtual desktop programs because it's actually quite a complex tool that just happens to also have the ability to do virtual desktops. It's really, really, really configurable and seems quite powerful, but it's virtual desktop functionality seemed more primitive because it's less specialized. It may, however, be possible to use the extensive scripting/toolbar creation functionality to improve it. I was unable to do so, though.

2006/09/07

New Design

Despite my whining in the last post I got things mostly setup the way I wanted. Switched out to starting with simpler, shorter template, and made all my changes offline in vi. Only took another iteration or two to actually get everything working.

It's not quite perfect, but it's close. Let's say 85%. Good enough that I'm going to use it until we get closer to, say... 95%. Need to make sure it isn't actually hard to read or something else equally dysfunctional.

Despite my artistic handicap, I even managed to come up with a logo and matching favicon. Go me!

2006/09/06

Blog Design Woes

Ever since the announcement that they got HTML editing setup and the new template language ready to go I've been thinking about doing a little redesign.

And, man, is it a pita. I've never been one for GUI design, honestly. Move this widget here. Push this thing over there. Wait, not yet. Do this thing a little more. Maybe that should be aligned the other way.

I swear you can do that stuff for hours. Throw colors in and I never actually get anything done since it never looks *quite* right. Their templating language is cool and all, but I find CSS in general to be extremely verbose. Couple that with the amount of processing they seem to do on the templates before it actually gets to your browser and its a bit annoying to figure out where a style is being applied. Not to mention a bit disorienting.

It doesn't really seem like downloading the template and editing it offline is really an option, either. If you try to display it, it just comes up with bits of a page. So, I've been using their online tools and it's been pretty slow going. Click on "Edit HTML" and muck around there, "Fonts and Colors" to set those, then to the other browser tab and refresh it to see what your page actually looks like.

I realize I could just ignore the "Fonts and Colors" friendly variable definitions, but it seems really negligent for some reason. And, I realize "Fonts and Colors" has a preview pane, but it seems to just be a static image so you can't see hover changes etc. Plus, it's cramped way down at the bottom of the view.

Having to use their plain-text editing window instead of vi sure is a drag, too.

Hmm...

2006/09/04

DevKitPro Templated Build Directories

One thing worth mentioning that's part of the DevKitPro is the "templated" build directories for Nintendo DS projects. I figured I'd give them a brief explanation since they're kind of unique to DKP.

You'll find them in [DevKitPro root dir]/examples/nds/templates/.
There should be two sub-directories:
  • arm9/
  • combined/

arm9/ is the simpler of the two, but is for projects that only require an arm9 executable. combined/ is a bit more complicated but allows for easily creating programs that use both the arm7 and arm9.

I'll only talk about the combined/ directory because you can limit yourself to the arm9/ sub-directory if all you want to do is mess around with the arm9, AND you can continue using the same template you've gotten used to as you move on to more complex projects and actually need both processors. In any case, most things apply to both templates in one way or another, it's just that in the case of combined/ it may be found in a subdirectory.

Template Prep



First, what I did was copy the combined/ directory to a location where I can easily find it when doing DS programming. I then renamed it "template", but you can call it whatever you want. The basic idea is to be able to just make a copy and rename it for each project you want to start, and you'll have a nice build environment ready to go.

Next, I made some changes to the default template because there's some unnecessary junk there (afaic):

If you don't use Programmer's Notepad you can safely delete template.pnproj, template.pnps, and template.prj.

cd [template directory]
rm template.*


I honestly have no idea why this is included with DKP. Maybe they own stock in it or something.

Next, you're going to want to do a "make clean". At the time of this writing the template directories are being distributed already built. This can cause problems for you during the linking phase of your project if your directory structure isn't setup just like the developers:
make clean
Now create a "data" subdirectory in the arm7/ and/or arm9/ subdirectories and add them to the relevant Makefile's list of subdirectories:

# For arm9/
cd arm9
mkdir data

Edit arm9/'s Makefile from this:
BUILD  := build
SOURCES := source
INCLUDES := include
DATA :=

To this:
BUILD  := build
SOURCES := source
INCLUDES := include
DATA := data # Or whatever you called the subdirectory you created


Your template build directory is ready to go!

Template Usage



Creating new projects is as simple as:

  1. Copying your template directory

  2. Renaming it something that fits your project

  3. Adding files as shown below



[root]/
+- arm9/
+- source/ ; Put all source files (*.c, *.cpp, etc.) here
+- data/ ; Binary files (*.bin) go here
+- build/ ; Project will be built here. Also, *_bin.h files generated
; for your *.bin files will end up here.
+- arm7/ ; Basically same as arm9/ directory


Change to the [root] directory, run "make" to build everything, and you should have a nice *.nds file waiting for you to debug. =)

2006/09/03

Mapping touch-screen input to pixel values on the DS

Finally got some school stuff out of the way so I can get back to the important things in life.... like the Nintendo DS.

Been messing around with touch-screen input a bit. It was fairly easy to get a demo running, but when I started trying to drag something around I found out that the touch screen uses a different coordinate system from the display. Dug around a little bit and came up with:


#define SCREEN_WIDTH 256
#define SCREEN_HEIGHT 192

// those are pixel positions of the two points you click
// when calibrating
#define TOUCH_CNTRL_X1 (*(vu8*)0x027FFCDC)
#define TOUCH_CNTRL_Y1 (*(vu8*)0x027FFCDD)
#define TOUCH_CNTRL_X2 (*(vu8*)0x027FFCE2)
#define TOUCH_CNTRL_Y2 (*(vu8*)0x027FFCE3)

// those are the corresponding touchscreen values:
#define TOUCH_CAL_X1 (*(vu16*)0x027FFCD8)
#define TOUCH_CAL_Y1 (*(vu16*)0x027FFCDA)
#define TOUCH_CAL_X2 (*(vu16*)0x027FFCDE)
#define TOUCH_CAL_Y2 (*(vu16*)0x027FFCE0)

// linear mapping can be used to go from touchscreen position to
// pixel position

// precalculate some values
static int16 TOUCH_WIDTH = TOUCH_CAL_X2 - TOUCH_CAL_X1;
static int16 TOUCH_HEIGHT = TOUCH_CAL_Y2 - TOUCH_CAL_Y1;
static int16 CNTRL_WIDTH = TOUCH_CNTRL_X2 - TOUCH_CNTRL_X1;
static int16 CNTRL_HEIGHT = TOUCH_CNTRL_Y2 - TOUCH_CNTRL_Y1;


// reading pixel position:
int16 x = (IPC->touchX - (int16) TOUCH_CAL_X1)
* CNTRL_WIDTH / TOUCH_WIDTH + (int16) TOUCH_CNTRL_X1;
int16 y = (IPC->touchY - (int16) TOUCH_CAL_Y1)
* CNTRL_HEIGHT / TOUCH_HEIGHT + (int16) TOUCH_CNTRL_Y1;


at NDSTech Wiki. The needed calibration values don't seem to be in ndslib so I think you need to define them yourself. Took around a minute of messing around to get a nice demo working where you could drag something around on screen just like you'd expect.

Something I did in my code that's worth pointing out is changing the calculations a bit to get rid of any extra operations (especially the division). Granted, I'm not sure how much the compiler can take care of, but it probably doesn't hurt.

First, if you separate the
IPC->touchX - (int16) TOUCH_CAL_X1
terms, the entire TOUCH_CAL_X1 component only needs to be calculated once.

Second, you can trade out the arbitrary divide for a shift by preforming the divide ahead of time and shifting the result to avoid using floating point. Then undoing the shift whenever you use the value. The numbers are small enough that you shouldn't have to worry about overflow when multiplying with a larger number... I think. i.e.


#define SHIFT 4
static u16 scale_value = (CNTRL_WIDTH << SHIFT) / TOUCH_WIDTH;
...
(IPC->touchX * scale_value) >> SHIFT ...


Gotta look into compiler optimizations and figure out whether the above is worth the trouble if you specify -O2, etc.

2006/08/25

Linking DS Code to Binary Image Data

Having to deal with sprite/texture/background data is a pretty common task in DS programming. The best way to do it is to strip any sort of header information and undo compression that is part of many graphics formats so you can just link the binary data along with your code. The problem is you have to know how to do this.

It looks like a lot of people convert the image to a header file and then #include it in their code. For small demos this really isn't a big deal, but it's kind of bad once you go beyond loading a single image. Why? Since the data is included by the pre-processor you have to recompile it along with your code EVERY time you make a change.

I figured out the tools well enough to get around this so I thought I'd share two different ways of doing this. Anyway, the two methods are:
  1. Image->Source->Binary
  2. Image->Binary
The end result is essentially the same, the process is just a little different.

Both require a program call gfx2gba from gbadev.org (NOTE: There are two versions of gfx2gba around, but you want v0.13. v1.03 is a similar but different program from a different author. I'm pretty sure you could use it I just won't talk about it here). This program can read various graphics file formats and extract the image data from them in various ways and seems to be an indespensible part of both GBA and DS development (yes, despite its name it is also useful in DS development because the two platforms have several similarities).

Image->Source->Binary


  1. Use gfx2gba to convert your image (bmp/pcx/tga/...) to a C source file. I will assume your image file is called image.bmp.

    gfx2gba -t8 -f src -o arm9/source image.bmp

    This converts image.bmp into a master.pal.c file containing the palette information and a image.raw.c file containing the image data arranged as 8x8 tiles. This would be used for sprites. For backgrounds you don't want tiling so you leave off "-t8".

    "-f src" specifies that the output type will be source (C) files.

    "-o arm9/source" specifies the output directory that the *.c files will be placed it. Set this to your source directory.

    gfx2gba has several other options so be sure to try running it without arguments or looking at the readme.txt file.


  2. Next, you want to make sure that this image data will be compiled as part of your build process (when you type "make"). You will either have to add it if you are using a custom Makefile, or place it in a directory that is searched for *.c files.


  3. Finally, you have to make the data accessible from your program. This is done by adding a declaration to your code so the compiler will let you use the arrays in the external object files. You will have a palette array called master_Palette in master.pal.c and an image array called image_Bitmap in image.raw.c. Putting the following code somewhere in your program source code will allow you to use them:

    extern const unsigned char image_Bitmap[];
    extern const unsigned short master_Palette[];

    Unfortunately, there doesn't seem to be a way to determine the size of the arrays at compile-time when you use this method. sizeof() gave me an error since they are arrays of unspecified size. You either have to include the dimension of the arrays from the generated source files:

    extern const unsigned char image_Bitmap[4096]; // Or whatever the size is
    extern const unsigned short master_Palette[256];

    OR, declare additional variables that hold them:

    unsigned int image_Bitmap_size = 4096; // Or whatever
    unsigned int master_Palette_size = 256;

    OR, add two other variables to the generated source files to store the size and then declare them as well:

    /* Add to the end of image.raw.c */
    const unsigned int image_Bitmap_size = sizeof( image_Bitmap );
    /* Add to the end of master.pal.c */
    const unsigned int master_Palette_size = sizeof( master_Palette );

    /* In your program source code */
    extern const unsigned int image_Bitmap_size;
    extern const unsigned int master_Palette_size;
    /* Don't forget the data array externs as well */

    I prefer the latter method because it is the most automatic of the three. If you ever change the image files you will have to regenerate the source and re-add the lines, but they're quite short and you probably won't be changing the images often.



Now when you run "make" it will compile the image data source files once and then you won't have to compile them again. The compiled image data will be linked into the executatable (don't forget to tell the linker about them if necessary).

Personally, I don't really like this method because it requires some manual work. I like things to be as automated as possible so I don't screw something up when I forget to do some manual step. For this reason I prefer the second method.

Image->Binary



  1. First, extract the image data from the image file with gfx2gba (assuming an image file called image.bmp):
    gfx2gba -f raw -t8 -St.bin -pmaster.bin image.bmp

    Again, leave off "-t8" if you are working with a background rather than a sprite.

    "-f raw" for binary output is the default.

    "-St.bin" sets the extension of the image data to ".bin" instead of the default ".raw".

    "-pmaster.bin" sets the palette filename to "master.bin" instead of the default ("master.pal"). There is a "-Sp" option to set the palette extension similar to "-St", but it doesn't seem to work.

    This will generate two binary files: image.bin containing the image data, and master.bin containing the palette.

  2. Next, you need to make these files linkable. This requires a bit of "magic" as it's hard to see how the example programs do this.

    If you look at a Makefile for one of the example programs you will find the following rule way down at the bottom:

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

    Basically, it takes *.bin files and trys to make them *.bin.o files by calling "bin2o". Now, if you look in devKitPro/devKitARM/base_rules (a file that gets included in all the Makefiles) you will find:

    define bin2o
    bin2s $< | $(AS) $(ARCH) -o $(@) echo "extern const u8" `(echo $( `(echo $(> `(echo $(> `(echo $(

    What this basically does is convert a binary file to assembly language, assemble it so it can be linked to your program, then generates master_bin.h and image_bin.h files to be #include'd in your program source. They contain:

    /* In master_bin.h */
    extern const u8 master_bin_end[];
    extern const u8 master_bin[];
    extern const u32 master_bin_size;

    /* In image_bin.h */
    extern const u8 image_bin_end[];
    extern const u8 image_bin[];
    extern const u32 image_bin_size;


    The extern's from the first method all nice and automagically declared for you.



I've shown you 2 different approaches to getting away from header file #include'd data and moving to more professional linking of binary files. I prefer the latter method as it can be pretty much completely automated, but which method you use will largely depend on your needs.

This is not to say these are the only two methods, mind you. While trying to figure this all out I saw references to some program named "katie" and another called "bin2c" ("binary to C" I would assume) that sounded like they could likewise be used. I'll leave that to you. Also, I'm willing to bet that there's a plugin for The Gimp or some other graphics program that will do all of this.

2006/08/24

My bad, DevKitPro devs! orz

It looks like I jumped the gun a bit in yesterday's post when I complained about the ease of learning to use DevKitPro (DKP).

Got some sleep and woke up a lot less grumpy today so I thought I'd give it another shot. This time with a clear head.

I came across the PataterSoft tutorial and in the process of messing around with it I ended up going back through the "examples" directory of DKP. And, I must say.... they're really well commented, fully explained, easily understood examples. Maybe that's why all the tutorials have fallen into states of disrepair; they're unneeded. You just pick the directory you want and learn about what's in there- it's kind of like "Choose Your Own Adventure".

Really didn't take much to get a few easy examples going. I retract all the nasty things I said earlier and instead tip my hat in their general direction.

Hmmm.... the API has changed, eh?

In general, DevKitPro is a pretty nice software package. GBA, PSP, and (most importantly) DS development libraries all in one place. They even have a fancy updating tool that will keep your libraries up to date and add new ones (they recently added dswifi).

Biggest problem? Documentation... of course. Unless there's some guys that are really dedicated to working on it, the documentation for every project generally seems to limp along coughing and wheezing behind the coders. And, DevKitPro is no exception.

Don't they have a Wiki? Well... kinda. But its out of order.

Doxygen? Well... kinda. But its pretty obviously not complete.

In case you're wondering, there doesn't seem to be any documentation in the software directory- save for the PSP.

For this reason, tutorials are nice just to avoid the frustration of figuring things out. If you check out any other DS dev-related sites: NDS Homebrew, Drunken Coders, PataterSoft, etc. They all tend to link to the same tutortials- all of which are either quite outdated or incomplete.

Far and away the best is PALib. This is assuming you want to use PALib, that is.

I was using the highly regarded double.co.nz tutorials. But, they no longer work. I haven't looked into it very deeply yet, but when I tried to compile the very short programs there were several errors. devKitARM (part of devKitPro) seems to have changed since the tutorials were last updated.

Most notably:

  • The development tools all changed from arm-elf-* to arm-eabi-*

  • The DISP_SR symbol seems to have completely disappeared.


The first isn't really a bit deal. But it illustrates the a problem that may be more difficult to solve for a real beginner. I didn't really bother with it after than. I'll give it another go tonight when I get home.

Perhaps writing an up to date tutorial is something I should undertake. We'll see.

2006/08/21

DirectX Programming with Visual C++ 2005 Express Edition

At some point I feel like I should embrace the winner in graphics APIs for computer games and learn DirectX (seriously, this time). In some obvious attempt to entice me, Microsoft began offering the Visual C++ 2005 Express Edition for free.

I looked at how to get it setup for DirectX development and these are my notes. You obviously need it and the DirectX SDK to start with.


  1. Setup the Platform SDK as described here here.

  2. Start Visual C++

  3. File->New->Project

  4. For "Project type" select "Visual C++" or "Win32" and create a "Win32 Console Application".

  5. When the Win32 Application Wizard comes up, make sure you select "Windows applicaiton" for the "Application type", and "Empty project" from "Additional options".

  6. Project->Add New Item. Select "C++ File".

  7. Project->Properties. Configuration Properties->Linker->Input. Add necessary DirectX libraries (ddraw.lib, dxguid.lib, etc.) to "Additional Dependencies".

Out with OpenGL, in with DirectX

I'll admit, I was originally in the OpenGL camp. OpenGL + GLUT was just vastly easier than DirectX for those of us with no Windows programming experience (even with the "easy to use" application framework they introduced in DirectX 8 or 9). Plus, I was fortunate to use it in a graphics programming class I had as an undergrad.

However, as part of my renewed interest in game programming, the coming release of Vista and DirectX 10, and the apparent demise of OpenGL, I decided to give DirectX another shot. But that requires tools.

The DirectX SDK is easy enough. That's been freely available for some time. A compiler and other development tools... that's a different story. I'd known about Visual C++ Toolkit 2003 (now deprecated, free command-line tools) for sometime, but I didn't know that they'd gone another step further and introduced Visual C++ 2005 Express Edition. Basically the same thing, but now with an IDE to boot. Very sweet.

This actually got me to dust off my DirectX and WinAPI books and do a little Windows programming for the first time in quite a while.

Refactoring

Well, I knew it was bound to happen...

I went ahead and created the blog and decided on a name, and then I thought of a name I'd rather have the very next day. I figure, with the blog still in its infancy there's no harm in changing it at this point. So...

R.I.P. "Rendered Useless". Long live "Rendered Obsolete"!!!!

On the topic of blog content/maintenance/etc., we should be seeing a new design here shortly. There really isn't much to the Blogger templates, now I'm just busy mucking around with CSS. I'm a bit old-skool when it comes to web-design; I haven't done much since the heyday of HTML 2.0... yeah... I remember being all impressed when I got RealAudio meta-files figured out (are they even still around?). Anyway, stay tuned for that.

Also, in order to placate my insatiable whims for name changes, yet still amuse myself, I've decided to use a "sub-title" of sorts for the blog. Just something I can change from time to time, yet is essentially meaningless. What does this mean for you? Absolutely nothing. But, please think of it as being +1 to the "amusement" factor of the blog. Unexpected. Spontaneous. Random.

2006/08/20

Let them eat XNA!

Although hardly news anymore, Microsoft's annoucement of a free XNA Game Studio Express is well worth mentioning. At launch it will only allow for Windows development in C# with the XNA Framework (R.I.P. Managed DirectX), but they will eventually include support to build games for the Xbox 360.

How cool is that?

Granted, you have to join the XNA Creator's Club with a "value-added" price of $99 per year to develop *OR* even play someone else's games (via FAQ). But, that's still quite a bit cheaper and with less red tape than an official Wii developer's kit (hint: $2,500-$10,000).

Beta begins Aug. 30.

Hello world?

Should the first post of a blog about console development/game development/general programming have any other title?

I should think not.

Partially inspired by my "extra-curricular" interests as of late, my long-standing love for Mixi (a Japanese social networking site), and partially driven by news of Google's intent to update the extremely outdated and ghetto Blogger, we have a new blog. Hopefully it won't befall the same fate as my last ill-conceived and neglected blog.

My hope is that interest in one will help drive and sustain progress/motivation in the other.

I intend to try and keep this reasonably focused on the area of console development. Logically, it will on occasion expand into other areas such as general game development and programming.

I'll be looking into the templates, CSS, etc. in short order to try and make it look a little less generic.