• Welcome to SCdev.org. Please log in.

Welcome to the new SCdev forums!

graphic conversion

Started by ferroptic, August 10, 2006, 11:40:19 PM

Previous topic - Next topic

ferroptic

dear sweet mother of..

I never thought it'd be so hard to get a straight answer on what seems to be one of the most basic facets of homebrew development - sprite creation.

Since this is by far the most helpful ds dev forum I've been to, I figured I'd ask around here. I've looked at Patater's award-winning tutorial, and on his site, and learned that using .c includes of graphics that should be binaries with nice clean .h files is very very bad and everyone apparently laughs at you. Okay, I don't like being laughed at.

However, I can't seem to find any simple run through on how to convert graphics from any common form that I'm used to (and I freaking make my living in computer graphics) to the .bin and .h I'm supposed to end up with, lest my code be derided as "bad form."

I can make gfx2gba spit me out a .c and a .pal, but nothing seems to happen when I use the .c with hConvert, and I'm not even sure if that's the intended input format. Patater's intro guide says it "can convert the output from gfx2gba to a compatible format for use with the Nintendo DS" - great, but apparently I'm retarding up somewhere before that.

Anyone have a good system for this? An example gfx2gba command line that produces an output hconvert is happy with, and therefore nets me a file I can include properly? Or a site detailing how to do this that I somehow haven't found?

I'm sorry to ask like 9000 demanding questions there, but I'm a little frazzled. PALib seems to have a nice conversion utility, but then it seems to be including .c files as graphics, which I've been assured is bad juju, by sites that then don't give me any indication of what steps to take to do it the right way, which leads me to look for a nice alternative, and Oh hey PALib has a nice utility...

You see where this got me.

Thanks for any help, and I'm frustrated at my own ineptitude, not angry at any of the people who've provided the tools and tutorials that got me this far-

omaemad

I wouldnt use gfx2gba, its a standard answer by many on the forums and its just plain bad advice, you can have the liberty of using .pcx(palletted though) straight on your ds with no conversions, look at the complex 2d demo(in ds examples devkit pro) it loads the ballls from pcx files and turns them into sprites
man fears time but time fears the pyramid"


omaemad

Thats a texture converter =p

Sprites have to be tiled to work under most modes so i still recomends looking at the example i mentioned , no conversion required at all .
man fears time but time fears the pyramid"

ferroptic

Thanks om -

I'd looked at the complex 2d example, even switched out the graphic in it as an experiment because that ball has such a nasty white halo. My problem with it was that that program ran slow as hell on my real hardware. Is this because of the plasma stuff on the top screen, or even an intentional slow frame advance rate? I didn't look too carefully at that part of the code, so maybe I should do that.

Bouncing a sprite off the sides of the screen is part of what I want to accomplish, so if the complex2d example is good code for that and will run quickly with tweaking i'll definitely go the PCX route.

Still, the overwhelming majority of people seem to be using preconverted bins, and I'd have no idea how to use an animation going the PCX route, so I have to assume someone can explain a way...

omaemad

Its the plasma on the top screen thats slowing things down, its running in framebuffer mode, and each pixels needs to be processed each frame, as for the reason why people are using gfx2gba is.... i dont know i use jpegs for backgrounds(non tiled) while others use tiled bg's for backgrounds that were originally bitmaps rather than tiled levels, this makes the backgrounds look crappy as they are dithered to only 256 colours rather than 16bit and after all that they take up more space !.

its just a waste of ram as jpeg/pcx give allot better compresssion and are easier to use with gbfs (no .h 2 bin needed).

as for animations it would be the same code as the gba2gfx animation code its the loading thats diffrent

(ps i havent worked with animated sprtes before so i cant comment anymore)
man fears time but time fears the pyramid"

bitblt

Quote from: "ferroptic"
I've looked at Patater's award-winning tutorial, and on his site, and learned that using .c includes of graphics that should be binaries with nice clean .h files is very very bad and everyone apparently laughs at you. Okay, I don't like being laughed at.

However, I can't seem to find any simple run through on how to convert graphics from any common form that I'm used to (and I freaking make my living in computer graphics) to the .bin and .h I'm supposed to end up with, lest my code be derided as "bad form."

Patater has done some fine work and I voted for him in the scdev.org tutorial contest which I helped sponsor.  Well done Patater!

I think omaemad’s suggestion is a good one.  If you study the DevKitPro 2D example Complex_2D you will find working with PCX files can be very convenient.  The Complex_2D example only runs slow because it’s processing every pixel of every frame for the plasma demo.

However, regarding this debate about linking with raw data binaries is better coding practice than including data encoded in C files is unfounded.  Both techniques are perfectly acceptable practice and will produce the exact same nds executable.  The only real difference is that C files have to be compiled and linked, where as raw data binaries need only to be linked.

If you really want to impress people with your homebrew programming skills then you shouldn’t use either technique.  The most efficient way to work with images and other data is to load them into RAM as needed from SD/CF media using the FAT libraries. This is similar to how commercial games will stream data into RAM from a game ROM.  There is only 4MB of internal RAM available for both code and data so linking images into your nds executable is wasteful.  In fact streaming data into RAM is required when a game has more content than will fit into the 4MB of DS RAM.


ferroptic: I'm going to explain some things you may already know, but I think this is good information for others having trouble working with gfx2gba.exe and graphic conversion.


If you are going to be working with images on the DS it is a prerequisite to understand how images are encoded in VRAM.  There are two ways to encode images, 8 bit mode and 16 bit mode.  The 8 bit mode is also referred to as 256 color mode.

In 8 bit mode an image is encoded as an array of bytes (unsigned char or u8 ) with an associated palette of colors encoded as an array of 256 words (unsigned short or u16 ). Each pixel (byte) in an image is an index into a 256 color (word) palette. So a full screen image for the DS in 8 bit mode would be 256*192*8 = 393216 bits, plus a color palette of 256*16 = 4096 bits, for a total of 397312 bits.  I will explain why the number of bits is important next.

In 16 bit mode an image is encoded without an associated color pallet. In 16 bit mode an image is encoded as a single array of words (unsigned short or u16 ).  Each pixel (word) in an image is a unique color value of 65535 possibilities (32768 RGB values with an alpha bit).  So a full screen image for the DS in 16 bit mode would be 256*192*16 = 786432 bits. You will notice a 16 bit image uses almost twice as many bits as the same dimension 8 bit image.

Color values are encoded the same way for 16 bit mode pixels as for 8 bit mode pallets.  Colors are encoded in 16 bit ARGB format as 1+5+5+5 or ABBBBBGGGGGRRRRR. It’s important to note that in 16 bit mode the most significant bit of each color value is used as an alpha bit (transparency), so if this bit is not set (1) the pixel will not be visible.  It should also be noted that when combining 8 bit mode and 16 bit mode images on both top and bottom screens, including independent backgrounds and sprite color pallets (not to mention 3D modes), it’s possible for the DS to display a total of 260,000 unique colors.

Now to keep this post from getting too long I will not go into the details of explaining how to load a PCX image into RAM using the FAT libraries.  Instead I will explain how to effectively link images into your project using the gfx2gba tool.  I want to point out that when linking images into your project it is more efficient to link 8 bit images because they require less room (fewer bits). Keep in mind that your entire nds executable, including linked data, must load into 4MB of DS RAM.

To convert a 256 color bitmap image into C files using gfx2gba.exe . . .

gfx2gba.exe -x -fsrc *.bmp

Using a 256x192 image.bmp as a hypothetical example gfx2gba will output  . . .

image.pal.c
image.raw.c

After we add these files to our project we can include them in our code like this . . .

#include "image.raw.c"
#include "image.pal.c"

If you study these files you will see that image data and palette data are defined something like this . . .

const unsigned short image_Palette[256] = {  0xC0DE, 0xC0DE, 0xC0DE, . . . };
const unsigned char image_Bitmap[49152] = { 0xC0DE, 0xC0DE, 0xC0DE, . . . };

( (256*16)+(49152*8 ) = 397312 bits )

With the DevKitPro 2D (8 bit mode) example 256_color_bmp we can display our image on the screen by replacing . . .

dmaCopy(drunkenlogo_bin, BG_GFX, 256*256);
dmaCopy(palette_bin, BG_PALETTE, 256*2);

with . . .

dmaCopy(image_Palette, BG_PALETTE, 256*2);
dmaCopy(image_Bitmap, BG_GFX+(256*16), 256*192);

(Note that BG_GFX+(256*16) merely centers our 256x192 image inside the 8 bit 256x256 BG example)

With the DevKitPro 2D (16 bit mode) example 16bit_color_bmp we can display our image on the screen by replacing . . .

for(int i = 0; i < 256*256; i++)
   BG_GFX = ((u16*)drunkenlogo_bin) | BIT(15);

with . . .

for(int i = 0; i < 256*192; i++)
BG_GFX[i+(256*32)] = image_Palette[image_Bitmap]| BIT(15);

(Note that BG_GFX[i+(256*32)] merely centers our 256x192 image inside the 16 bit 256x256 BG example)

You will notice in this 16 bit mode example we must index color values for each pixel in our image as well as set bit 15 (alpha bit) so our image is visible.

Finally I will explain how to work with sprites using the gfx2gba.exe tool.  Using a 32x32 sprite.bmp as a hypothetical example gfx2gba will output  . . .

sprite.pal.c
sprite.raw.c

After we add these files to our project we can include them in our code like this . . .

#include "sprite.raw.c"
#include "sprite.pal.c"

With the DevKitPro 2D example Complex_2D we can display our sprite on the screen by replacing . . .

loadPCX((u8*)ball_pcx, &ball);

with . . .

ball.height = 32;
ball.width = 32;
ball.bpp = 8;
ball.palette = (short unsigned int*)sprite_Palette;
ball.data8 = (unsigned char *)sprite_Bitmap;

Of course you may find that simply linking with PCX files and using loadPCX is more convenient.

ferroptic

I've said it before, I'll say it again, bitblt for president.

After Om's post, I went ahead and dissected the complex2d code, and after a quick refresher on how to get my very expensive copy of Photoshop to do some PCX palette magic I used to do for doom wads with a 20kb piece of freeware, I got a sprite converted and imported into a rom with a transparent background and everything. Woohoo. This was shamelessly stealing the loadPCX code from the complex2d example, but hey, it worked.

Now, after getting all the math and most importantly the code practice blessing from bitblt, I'll be interested to try converting some nice tasty BMPs. I'd looked at the drunkencoders example for that that came with devkitpro, but it came packed with a bin, and in fact noted that that was the way to go in a comment, so I gave up looking there on how to do a simple sprite. I'd written an app that did some button press detection and touchscreen tracking, but it was just filling a sprite with a block of color, which is code I shamelessly stole from the sprite bitmap example that came with devkitpro. Now that colored box is replaced with a sprite I made myself- joy. When I get this crappy app a little more developed, I'll post it - I downloaded devkit for the first time Thursday, so this is already way past where I expected to be.

Bitblt: will the method outlined in your post convert an animated BMP into an animated sprite? Is that within gfx2gba's capabilites? I'm much more of a graphics guy than a coder, so I'd be loathe to have to manually animate sprites and do graphics swapouts via a function in order to get an animation going.

Vanit

Quote from: "ferroptic"my very expensive copy of Photoshop
... you can buy photoshop?  :shock:

ferroptic

Quote from: "Vanit"
Quote from: "ferroptic"my very expensive copy of Photoshop
... you can buy photoshop?  :shock:

If you work at a place that staffs software auditors, they manage to find a way.

bitblt

Quote from: "ferroptic"
Bitblt: will the method outlined in your post convert an animated BMP into an animated sprite? Is that within gfx2gba's capabilites? I'm much more of a graphics guy than a coder, so I'd be loathe to have to manually animate sprites and do graphics swapouts via a function in order to get an animation going.

It's past my bedtime so I'm not going to get into animating sprites at this time.  Hopefully the information provided will help get you started.

Quote from: "bitblt"Keep in mind that your entire nds executable, including linked data, must load into 4MB of DS RAM.

I just want to mention the fact that it is possible to append data to the end of your nds executable by using GBFS or some other embedded file system technique.

Quote from: "bitblt"
Of course you may find that simply linking with PCX files and using loadPCX is more convenient.

It's also worth pointing out that PCX files are compressed.  However, they still need to be expanded into RAM before they can be used.