#176082 - kcaze - Tue Apr 05, 2011 10:00 am
Hi all, I know I'm several years late to the scene (if there still is a gba development scene), but I've just started looking into gba programming. I haven't done embedded systems programming before but I can program in C fairly well. Could someone help answer the following list of questions?
1. Is there a utility similar to gfx2gba for linux? A google search didn't turn up any linux binary or source code so I'm guessing that gfx2gba isn't available for linux. If there isn't such a utility, I'm planning to write my own; so far I have a program that can convert gif files into a u16 array in a c source file. Is that the usual way of doing things?
2. How does audio work on the gba? I've seen Belogic's website and understand how to use direct sound, but I don't understand anything else about audio. Could someone give me a brief overview of how audio is stored (I think each byte or something corresponds to an amplitude?).
3. I've tried converting a 4 minute mp3 into a wav file and the resulting wav file was 50 mb. Obviously there's no way I can use that in my game. What other formats are there? I've heard of MODs: are they commonly used? Finally, is it feasible to have the gba decode mp3 files and play them on the fly in a game?
4. How does accessing cart ROM work? I've looked at GBATek which states that there are 3 waitstates, but each waitstate seems to only allow for 32 mb of ROM? I have a Mini SD Super Card SD flash cart and the SD itself is 1GB. How would I access data on the Mini SD Card?
5. I've already read about the different graphic modes and understand how to work with objects, tiles, and bitmap modes. Also, I've looked at DMA. Beyond this, I plan to look into how to use windows and interrupts. Is there anything else that's essential to understand for general gba programming?
6. Many people have recommended TONC and I do find the explanations extremely useful. However, the TONC library conflicts quite a bit with libgba doesn't it? Which should I use? I've been using libgba currently as it comes with devkitPro but I'm wondering if the TONC library was useful as well?
7 (last one, I promise :P). Is gbadev the only active gba development community? I know that drukencoders.com also seems active but the forum there appears dead. Also, I've been to the #gbadev channel on Blitzed and no one seems to go on there either. I know that it's quite late to be doing gba homebrew, considering that the 3DS is out as well now, but are there any other gba development communities?
#176083 - Ruben - Tue Apr 05, 2011 11:05 am
1) I'm not entirely sure about Linux (as most use Windows) so I can't help you there.
2) Sound/music is my fort? ^_^
Sound on the GBA is produced by either the hardware tone generators (they were there for compatibility with the Gameboy Color but stayed after the GBA audio-people started using it) or by using the 8-bit PCM.
Music on the GBA is usually stored as a form of sequenced data (whether it be a variant of Midi, MOD, S3M, IT, etc) while the audio data is usually stored as signed or unsigned 8-bit samples (I think MaxMod uses unsigned) as the data must be mixed in software.
3) ... Yeah, like I said before, using streamed music (ie, MP3, OGG, etc) is quite literally impossible to do on the GBA due to its VERY limited horsepower. Further, converting MP3 to a .wav will GREATLY increase the ROM size (which, IIRC, is limited to 32MB).
You'll usually want to use module formats (ie, MOD, S3M, XM, IT) or Midi (this is what official titles used). MaxMod supports all module formats (but not Midi).
4) I would give advice on this but since I'm not 100% sure, I won't ;)
5) For general programming, you'll also need to know how to read input and interpret that (ie, key taps, etc).
6) I can't comment on this matter as both are good libraries and I wouldn't recommend one over the other (though, IIRC, tonclib has an include specially made to be used with libgba)
7) There are plenty of other GBA-dev communities (even if they've mostly moved to the DS =P) out there that I know of, but I don't think we're allowed to directly mention them. =P
_________________
I'm 18 and have Asperger's, so if I don't get something at first, just bear with me. *nod*
#176084 - Quirky - Tue Apr 05, 2011 1:28 pm
1. I use grit - the "GBA Raster Image Transmogrifier" - it's shipped as part of devkitARM. The flags are different, but you can achieve all of the same results as with gfx2gba. Cearn may even add something you're missing, or you can patch the source yourself (I nagged him into adding -pS for shared palettes by sending him bad patches until he implemented it himself :-)).
4. Data location is handled by the devkitARM linkscript (IIRC) - if you declare data "const" then it goes in ROM and any accesses you make to it in C will read from ROM. i.e. if you say "const int myint = 3;" then do printf("%#x\n", &myint); the address will be in ROM (0x8000000 isn't it? It's been a while since I thought about this stuff)
5. Learning to work with emulators is important. Visual Boy Advance is very useful. You may have to compile it from source to get all the developer options, and I vaguely remember Ubuntu ships 1.8.0 that was a bit crashy when debugging. I had more luck with 1.7.2. The Windows version works with wine and is a great help for visualising VRAM. NO$GBA emulates "errors" more accurately - e.g. a sprite shows on VBA but not on hardware, then there's a good chance it'll be broken on NO$ too (because you have sprites disabled, or set to the wrong priority, or have the double scale set but not rotation, or....)
6. try keep your use of registers well controlled - don't sprinkle them liberally around all your code, it's easily done if you don't take care. That way you can swap from one library to another with less pain. Using libgba would also make porting to the DS easier (libnds and libgba share a lot of the same register names, there are just enough differences to keep you on your toes).
#176085 - kcaze - Tue Apr 05, 2011 1:42 pm
Grit looks perfect. It was actually pretty fun learning the GIF format though :P Plus, I learned about how LZW compression works. I've never done anything with compression before XD
I've read somewhere that MOD files are really limited. What I'm actually planning to do right now is to write a simple rhythm game so I'm hoping to be able to put songs with vocals into the game. Again, I'm pretty much clueless when it comes to audio, but MIDI files are out of the question since they are synthesized right? Unless somehow vocals can be synthesized too o_O
Also, I've been using VBA so far to test my programs and it seems sufficient for now although I had some headaches when copying palettes into VRAM. Apparently, using memcpy to copy it garbles the data somehow? Is it related to word assignment or something?
Anyways, thanks for the prompt replies!
#176086 - Ruben - Tue Apr 05, 2011 2:11 pm
MOD files are limited to four notes polyphony per song - taking into account that the minimum specs for General Midi is 32 notes, this is EXTREMELY limited. =P
IMO, you should use S3M files if you want strict control of your sound channels or XM/IT if you want instruments with envelopes.
As for vocals: XM/IT use built-in 'instruments' which are made up of sound samples you provide, so that's easily fixed.
With Midi, the sound banks differ from sound card to sound card, meaning that in the end, you'll have to provide your own samples, too, so adding vocals is just as easy, but you won't hear them unless you're testing the bank directly.
As for memcpy:
memcpy will try to copy the memory in the fastest way possible (it usually screws something up and fails in the latter, though =P).
VRAM can only accept 16 and 32-bit writes - 8-bit writes are considered 16-bit writes to both the upper and the lower bytes (ie, 00XX results in XXXX).
memcpy may screw up and use 8-bit copying if your data is not aligned or the angle of the moon against the sun isn't exactly 69.6969696969... degrees. =P
Usually, you'll want to use DMA to copy data as this is the fastest method (no loop overhead).
_________________
I'm 18 and have Asperger's, so if I don't get something at first, just bear with me. *nod*
#176087 - kcaze - Tue Apr 05, 2011 2:35 pm
@_@ Grah, all this stuff about sound banks and audio terminology is confusing. XD, I don't even play an instrument so there's probably a lot to learn. For now, I guess I'll stick with visuals :P
So far, I've only been array copying memory to vram ^^; I haven't really tried using DMA yet, so I'll write something quick to test it out.
EDIT:
So here's what I've written (I tried manually setting the DMA registers and using libgba's DMACOPY):
Code: |
#include <gba_dma.h>
#include <gba_video.h>
#include <gba_sprites.h>
#include "thomas.h"
void init_screen(void){
REG_DISPCNT = MODE_0 | OBJ_ON | OBJ_1D_MAP;
}
//---------------------------------------------------------------------------------
// Program entry point
//---------------------------------------------------------------------------------
int main(void) {
init_screen();
REG_DMA0SAD = thomasPal;
REG_DMA0DAD = OBJ_COLORS;
REG_DMA0CNT = (thomasPalLen >> 1) | DMA_DST_INC | DMA_SRC_INC | DMA16 | DMA_ENABLE;
DMA0COPY(thomasTiles, SPRITE_GFX, (thomasTilesLen >> 1) | DMA16);
OAM[0].attr0 = ATTR0_SQUARE;
OAM[0].attr1 = ATTR1_SIZE_64;
OAM[0].attr2 = OBJ_CHAR(0);
while(1);
//---------------------------------------------------------------------------------
}
|
Is this the general way to do things? Also, why isn't there a macro that lets you set all 3 attributes for the OAM at once? It seems like a lot of hassle to have to write 3 lines to set up one object.
#176089 - Ruben - Wed Apr 06, 2011 6:39 am
For DMA, you'll usually want to copy in 32-bits as this is faster (specially from ROM). Also, as long as the variable is unsigned, divisions are automatically turned into shifts. So...
Code: |
REG_DMA0SAD = thomasPal;
REG_DMA0DAD = OBJ_COLORS;
REG_DMA0CNT = (thomasPalLen / sizeof(u32)) | DMA_DST_INC | DMA_SRC_INC | DMA32 | DMA_ENABLE;
DMA0COPY(thomasTiles, SPRITE_GFX, (thomasTilesLen / sizeof(u32)) | DMA32); |
As for objects, you usually use a managing system so that you don't set the OAM variables directly but instead call functions to do stuff (ie, obj_SetPos, obj_Enable, etc).
EDIT:
Oh yeah: DMA0 is usually reserved for H-Blank stuff. DMA1 and DMA2 are usually reserved for sound so you most often use DMA3.
_________________
I'm 18 and have Asperger's, so if I don't get something at first, just bear with me. *nod*
#176092 - dantheman - Thu Apr 07, 2011 3:31 pm
For audio, if you *really* wanted to use streaming audio, Tepples's GBA GSM Player might be your best option. You're still not going to get very much music in there, but at least it's more compressed than WAVE. Downside is of course that it will take up more CPU time to decode (hence why MP3 is impossible - 16 MHz just simply isn't enough), and also porting the 7-year-old code might be a challenge.
Regarding #4, typically with the GBA you include all your assets within the *.gba file itself, and this *.gba file can be no more than 32 MB. On your Supercard, you'd find the *.gba file on your 1 GB card and then the Supercard will load it into its 32 MB of RAM and execute it directly from there. While technically DLDI is compatible with the GBA, and thus while you could theoretically directly access the SD card's filesystem from within GBA mode, this seems difficult and I would have no idea how it was done. I've only ever seen two programs that ever made use of this: chishm's savefile dumper program, and a test version of PocketNES by Dwedit that let you load roms from the SD card rather than building them in with the *.gba file to begin with.
It wasn't until the DS came along that it became common practice to access external files rather than including them in the binary.
#176095 - kcaze - Sat Apr 09, 2011 4:20 am
Thanks dantheman for the information about the cart information.
I've been trying to use H-Blank DMA Transfers to create a rainbow effect but the the rainbow lines only seem to flicker around randomly. Here's my code, could someone tell me what's wrong with it?
Code: |
#include <gba_video.h>
#include <gba_dma.h>
enum RAINBOW_COLORS {CLRED = 0x1F, CLGREEN = 0x1F0, CLBLUE = 0x7C00, CLPINK = 0x7C1F, CLYELLOW = 0x3FF, CLAQUA = 0x7FE0};
u16 colors[6] = {CLRED, CLYELLOW, CLGREEN, CLAQUA, CLBLUE, CLPINK};
void init_screen(void){
REG_DISPCNT = MODE_0;
}
void rainbow_effect(u16 *color_arr){
static u32 index = 0;
u32 ii = 0;
for (ii = 0; ii < 80; ii++){
color_arr[2*ii] = colors[(index + ii) % 6];
color_arr[2*ii+1] = colors[(index + ii) % 6];
}
index += 1;
}
//---------------------------------------------------------------------------------
// Program entry point
//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
init_screen();
u16 color_arr[160];
rainbow_effect(color_arr);
while (1){
while (REG_VCOUNT >= 160);
while (REG_VCOUNT < 160);
rainbow_effect(color_arr);
DMA0COPY(color_arr, BG_COLORS, 1 | DMA16 | DMA_DST_FIXED | DMA_HBLANK | DMA_REPEAT);
}
} |
#176096 - Dwedit - Sat Apr 09, 2011 6:54 am
In order to properly do HDMA effects:
Have a Vblank interrupt handler.
First thing the vblank handler should do is stop any HDMA effects currently running.
Your vblank handler should check a flag to see if we want to run the effect or not. You should set the flag when your data is ready, and clear the flag when you no longer want the effect.
Because HDMA only triggers after the first scanline has rendered, the vblank handler should manually perform the first write of the effect, and configure the HDMA to start with the second piece of data.
Then you start your HDMA effect as normal.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#176097 - kcaze - Sat Apr 09, 2011 9:20 am
Ah >.<, you had to clear the DMA each time? I looked at TONC's example and it didn't seem to clear the DMA, but everything works now :D
#176149 - sierra_madre - Tue Apr 19, 2011 8:46 am
This is really interesting, wish I'll also be able to kick off my gears and start learning about this.
_________________
Seize the day!
#176158 - kcaze - Fri Apr 22, 2011 11:23 am
Good luck! GBA programming's pretty fun so far ;P
By the way, I've been reading GBATek and the mention all these things about waitstates when accessing cartridge ROM. Do I need to know about any of that? I've tried simply accessing the ROM memory directly by casting it as a pointer and that seemed to work. So did using DMA to access it.
So I'm guessing either my emulator isn't that accurate or there's no need to deal with waitstates?
#176159 - gauauu - Fri Apr 22, 2011 3:04 pm
For most beginner-level development, you don't need to worry about it.
#176160 - Dwedit - Fri Apr 22, 2011 6:08 pm
Waitstates are automatic, it just means that it's slower to access cartridge ROM than internal ram. So if you need extra speed, copy code/data to IWRAM, or even Video RAM.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."