• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Forum moderator applications are now open! Click here for details.
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Research: General GBA Graphics

Full Metal

C(++) Developer.
810
Posts
16
Years
Warning to you wise-cracks

In no way, am i saying this is 100% accurate; I'm human, and make mistakes. You've been warned, so no flaming, just point somethin out then SHUT UP. Anyways on to the juicy stuff (i decided to start making things look professionalerer the first time so...its a bit more organized than my other threads)





Simple stuff
Terminology

Bit: The absolute smallest storage unit of data, can only be 1 (set) or 0 (unset)
Byte: 8 bits; maximum value of 0xFF (255)
Short: 2 bytes (16 bits); maximum value of 0xFFFF (65,535)
Integer: 4 bytes (32 bits); maximum value of 0xFFFFFF (4,294,967,295)
Color: err..go back to kindergarten, what are you doing here?
Palette: usually 16 or 256 colors
GBA: OK SRSLY WTF R U DOIN HERE?! (jk XD)
The gba has a screen size of 240x160 pixels.
This has the capability of having 30x20 tiles on the screen at a time.
The gba is a 16-bit color system. Meaning all the colors you have available on a computer, are not available on the GBA.

Colors
How colors are stored in the GBA vram

As previously stated, GBA colors are 16 bits a piece. Believe it or not, 1 bit is actually wasted :O.
heres how a gba color looks
[wasted bit][5 bits: Red value][5 bits: Green Value][5 bits: Blue value]
since each of the RGB values are only 5 bits long, there is a maximum of 31 value possibilities to each. You will get the closest match to the actual color, by simply multiplying those values by 8. If you are a programmer, here's how to store colors in GBA format.
#define gba(r,g,b) ( r | g<<5 | b << 10 )
If you aren't, that is simple enough, you should be able to figure it out (again, bitwise logic is needed) << means to shift left X times. Reversing that is as simple as bitshifting to the right the respective amount of times and a little bit of AND'ing to remove the other bits from the remaining colors.
The BG Palette Memory Starts at 0x5000000 and the Sprite Palette Memory starts at: 0x5000200

Un-Compressed Graphics
The Easy Stuff...

The GBA has IO2 (that i know of) different storages of graphics. Compressed, or Uncompressed. Uncompressed graphics are easier to understand. If you are in 4BPP mode, the least amount of pixels you can have is 2.
[4 bits: pixel 2 index][4 bits: pixel 1 index]
What I mean by "index" is which color value on the palette will be used. Usually, 4BPP will be used with tilemaps, but there are other cases (like sprites)
please note that 4 bits restrains you to a value of 15, which is oddly convenient...
8BPP graphics are stored similarly
[8 bits (1 byte): pixel index]
This will allow you access to all 256 colors of either the BG palette, or the Sprite Palette.

GBA Video Modes
How the gba processes the graphics

The gba has different "modes" for graphics display. How the GBA knows which mode to use, is that it reads from the address 0x4000000. That is where the screen mode, and which bg's are enabled is stored. To set the appropriate mode you need to know some bitwise logic (google it if you don't already know it)
the hex values for the different bgs being enabled are:
BG0: 0x100
BG1: 0x200
BG2: 0x400
BG3: 0x800
If sprites are also enabled, you can treat them as a BG as well. They're enabled code is 0x1000
---<bg X enabled code> do that for each bg you are enabling.
OR <Mode, simply the mode number in hex>
Spoiler:

Putting it all together
Some assembly required

To display a 240x160 256 colors image, heres what you need to do.
Store the palette in the ROM
Store the image in the ROM (using tilemoster or etc, so that it's uncompressed)
write a routine, and set the video mode to one appropriate for you (i reccomend mode 4) then add a that will enter a (i usually use C++, so try to bear with me on my terms like "loop") loop, writing the palette to the BG memory. Add another (separate) loop that will copy the bytes from your image offset into the appropriate BG memory (I challenge you to find that with nothing more than VBA, hint hint: check the "map viewer" ;) )
add another (separate) loop. Next write a script that will fade the screen to black/other color, and call your routine (smart asm hackers obviously can call the routine through other methods, but i'm not exactly a "smart" asm hacker...still learning basics...) and voila! u see a nice pretty picture :D
...don't ask me how to return to normal play. Perhaps you could add a "waitforkeypress" to your script, then fade to black (yes, again) then fade from black to normal play. Or maybe you could loop in your routine (after displaying loading palette and pixels) and when a button is pushed the script would continue, which you could just fade into normal play from there. I dont' know branching and whatnot yet, so I can't post an example routine right nao...maybe i still wont' to help inspire others who dont know how either...

Tiles and their maps
Not alot to say...

Well, theres not a lot to these, especially since we have NTME and Cyclone, and PTC (lol, theres' so many...)
simple.
A tile: 8x8 block of pixels
Tilemap: a series of shorts describing which tile goes where on the GBA screen
I'm not going to touch on how to load tilemaps, its' a bit much for me to type out at 11:23 pm...

Tile Insertion
almost a little rant

Ok, so you have this nice set of tiles you'd like to insert right?
But holy shiz! ITS FRIGGIN HUGE!
Have no fear, this tutorial is here!
What I see a lot of is people getting the mis-understanding that tiles you insert have to be as you see them in the map; this is a lie. First let me explain to you what a "block" and a "map" are.
Block: a 2x2 set of tiles, with two layers.
Map: a bunch of tiles, with movement permissions, and events.
Tileset: a bunch of blocks.

So rather than have a 16x16 tile pasted into your tileset, and wasting space (assuming they're identical) you can break it down into perfect 8x8 tiles ;)

How to do this?
well, you could just jump into sphere and convert it...but that could turn out disastrous.

First you need to gather all the tiles you want to insert, that share the same palette.

Open up paint, and paste all the tiles you want in there.
Fill the BG (your going to be indexing this, so be sure not to miss anything) with a transparent color (you want it to be completely unique, so using the paint default colors is perfectly exceptional. Ensure that the bottom-left pixel is the transparent color, and save as a un-indexed bitmap file.
Open up the saved file in irfanview, and index it into 16 colors. Save again (still bitmap format)


download and, maybe, install the GTK+ runtime, the tool "Full Metal Paletted" from here


once that's done, run the program. Click on the 4BPP bitmap option, and load the file from previous steps.
Then click on the save a-map palette button, and save the advance map palette. Open a-map, load your rom, go to a map with the right tileset and load block editor.

Choose the palette to replace, and load it from file (choose the file we saved in with palette editor).

Now comes the tile insertion part.
Open up each individual tile, and make sure it aligns with a pixel spot that, if added by one, is divisible by 8 (if the first pixel on the left is 0) and also make sure the same is true vertically. Save your image. Open up sphere, import->image to map and open the image we previously saved. Set the block size to 8x8 and click yes when it asks to remove duplicate tiles grab the tileset saved with sphere and save it. Open that up in paint, and copy it. Then go back to a-map, and save your tileset (with the palette you want to use). Open up your tileset with pain, paste your clipboard wherever it fits, and load the tileset again with amap. This is important, if you clicked "Write Palette Changes to ROM" then you'll have to load your palette again (from file) and then load your tileset, i'll explain why later. If you didn't click "Write Palette Changes to ROM" then you are good to go, load the tileset, and NOW click "write palette changes to ROM" and may begin block editing ;) read some other tile insertion tutorial to learn how to do that...
So why can't you click "write palette changes to ROM"?
Every tileset image is stored with a .pal file right next to it. The .pal file has all the colors used in your palette, which is how A-map knows which pixel to put where, without using indexed bitmaps. If you have a pixel on your bitmap, that is not in your .pal file, then your tileset, when loaded, will not load the colors right, unless by some unlikely chance, all the colors are divisible by 8 and less than 248. So...why can't we click that button? Because when you do, a-map looses the original colors, and converts them to colors that are GBA compatible (divisible by 8 and less than 248) so when you save the tileset, the colors in the .pal file will NOT match the colors of the content in your clipboard.
 
Last edited:

colcolstyles

Yours truly
1,588
Posts
15
Years
Okay. How about explaining how a hacker might utilize this information? For example, where in the RAM does it say what mode is currently being used? How would one switch between different modes? Frankly, I don't think that there would be many uses for any mode other than Mode 0 in a Pokémon hack but I'm sure somebody out there could think of something.

It's a nice start but I can't really think of any practical applications for this information. I think you'd be better off explaining the ins and outs of the VRAM and the registers involved with the various Backgrounds.
 

Full Metal

C(++) Developer.
810
Posts
16
Years
gyahh! I didn't realize i posted this :P thats why its so incomplete --sorry guys XD
thanks for the quick response though colcolstyles :)
will do what you suggested (i originally planned too...>_< silly post button)
*edit* howzat fur ya?
 
Last edited:

Giga Universe

Working on a tool.
121
Posts
16
Years
Shouldn't you have explained how to use the I/O register at 0x4000000 properly? All you gave were some hex values for enabling the modes. Shouldn't you at least link to something like GBATek that shows what the individual bits do? Like Here? Maybe explain it it more detail though, because some people might not understand that it works in binary or something.

EDIT: And aren't colours stored in the PALETTE RAM, not the VRAM? Theres a mistake in your tutorial saying it's VRAM (In the heading under colours)
 
Last edited:

Full Metal

C(++) Developer.
810
Posts
16
Years
well...i kinda considered it part of VRAM because you can change what's on the screen just by modifying that...
it told them how to use those codes ?
all they need to do is OR it with the bg's needed, and then write the value to memory
 

Giga Universe

Working on a tool.
121
Posts
16
Years
Well I'm going to attempt to work on some ASM today to get this working. Any ideas on how to get the routine to get pointers to the palette and image data?
 
Last edited:

colcolstyles

Yours truly
1,588
Posts
15
Years
er the palette data is at the very beginning of the vram if i remember right (0x500000)

No the VRAM is at 0x0600:0000. The Palette Memory is at 0x0500:0000 but it's completely separate from the VRAM. However, seeing how this is in a ROM Hacking forum, telling us where the palettes are stored is only a step towards hacking the palettes. You'll find very quickly that simply writing to the Palette Memory won't change the palettes. The reason why you can't is something that I think belongs in this tutorial. I'll let you figure it out.
 

Full Metal

C(++) Developer.
810
Posts
16
Years
mkay....
Spoiler:

That is a C example of loading and displaying an image in the GBA. Download gba dev kit advance, create a file named "beach.pcx" drag and drop onto a program called "pcxtogba", then compile the code. Ill edit this and first post with an asm routine (if i can do one that is...) in just a minute....
*edit*
well, thanks to foofatron's documentation, i've found out where i can write to to change the palettes. Now i have a question for ya; What causes the writes i make in memory viewer to get overwritten? Is it because that's not legal to do in GBA?or is it because FireRed is doing something. I've opened up the disassembler in VBA, and i find the almost offset of where the palette's that work are being referenced frequently, so I think that it may be firered's doing....but you seem to know, so i thought i would ask.
 
Last edited:

Giga Universe

Working on a tool.
121
Posts
16
Years
I originally thought the same thing, but that is wrong. In order to write to VRAM, PALETTE RAM or OAM, you need to request a "blank" (or force it). This can be done by writing a 1 to the 8th bit at 0x04000000. You'll have to turn it off again after you've finished the write. Also, I have (sorta) figured out how to use the BIOS function for uncompressing LZ77 compressed data. It allows you to write a source location, then an output location for the data, and then will automatically decompress it for you.
 

colcolstyles

Yours truly
1,588
Posts
15
Years
I originally thought the same thing, but that is wrong. In order to write to VRAM, PALETTE RAM or OAM, you need to request a "blank" (or force it). This can be done by writing a 1 to the 8th bit at 0x04000000. You'll have to turn it off again after you've finished the write. Also, I have (sorta) figured out how to use the BIOS function for uncompressing LZ77 compressed data. It allows you to write a source location, then an output location for the data, and then will automatically decompress it for you.

I wasn't aware of that and yet I've been able to write to the VRAM just fine. o_O
 

Darthatron

巨大なトロール。
1,152
Posts
18
Years
GBAtek said:
SWI 11h (GBA/NDS7/NDS9) - LZ77UnCompWram
SWI 12h (GBA/NDS7/NDS9) - LZ77UnCompVram (NDS: with Callback)
Expands LZ77-compressed data. The Wram function is faster, and writes in units of 8bits. For the Vram function the destination must be halfword aligned, data is written in units of 16bits.
If the size of the compressed data is not a multiple of 4, please adjust it as much as possible by padding with 0. Align the source address to a 4-Byte boundary.

Code:
  r0   Source address, pointing to data as such:
        Data header (32bit)
          Bit 0-3   Reserved
          Bit 4-7   Compressed type (must be 1 for LZ77)
          Bit 8-31  Size of decompressed data
        Repeat below. Each Flag Byte followed by eight Blocks.
        Flag data (8bit)
          Bit 0-7   Type Flags for next 8 Blocks, MSB first
        Block Type 0 - Uncompressed - Copy 1 Byte from Source to Dest
          Bit 0-7   One data byte to be copied to dest
        Block Type 1 - Compressed - Copy N+3 Bytes from Dest-Disp-1 to Dest
          Bit 0-3   Disp MSBs
          Bit 4-7   Number of bytes to copy (minus 3)
          Bit 8-15  Disp LSBs
  r1   Destination address
  r2  Callback parameter (NDS SWI 12h only, see Callback notes below)
  r3  Callback structure (NDS SWI 12h only, see Callback notes below)
http://nocash.emubase.de/gbatek.htm#biosdecompressionfunctions
I originally thought the same thing, but that is wrong. In order to write to VRAM, PALETTE RAM or OAM, you need to request a "blank" (or force it). This can be done by writing a 1 to the 8th bit at 0x04000000. You'll have to turn it off again after you've finished the write. Also, I have (sorta) figured out how to use the BIOS function for uncompressing LZ77 compressed data. It allows you to write a source location, then an output location for the data, and then will automatically decompress it for you.

I'm fairly sure that doesn't apply to VRAM. I write to that fine, all of the time.
 

Full Metal

C(++) Developer.
810
Posts
16
Years
I wasn't aware of that and yet I've been able to write to the VRAM just fine. o_O
he's definitely on to something
if you go to the 04 (multiple 0's)
you'll see a XX40 or XX80
when it's 04, that means you are able to edit the palette memory and what not.
if it's anything other than that, then you can't.
Atleast, that was my experience.
and happy day ^^: i finally used the "disassembler" with VBA.
 

Giga Universe

Working on a tool.
121
Posts
16
Years
I wasn't aware of that and yet I've been able to write to the VRAM just fine. o_O

http://nocash.emubase.de/gbatek.htm#biosdecompressionfunctions

I'm fairly sure that doesn't apply to VRAM. I write to that fine, all of the time.

Strange... In my asm routines attempting to display images, I did not get any success until I set that byte. Thanks for the link, I was already aware of that. What I meant was that I still hadn't had any success to display an Image, therefore I would not have any success with a compressed Image. However, that bit DOES enable extremely fast VRAM editing if I'm not mistaken. So even if its not required to be set, It should speed things up.
 
Back
Top