gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > Tonc tutorial #define question - why?

#131403 - ShannonB - Fri Jun 15, 2007 5:03 am

Ok, going through the Tonc tutorials: http://www.coranac.com/tonc/text/first.htm

(Brilliant tutorial by the way, just going through the math section and I actually understand stuff I never thought I'd get that quickly)

Anyway, he makes a #define to point to the Display control register, which I get.


#define REG_DISPCNT *((volatile u32*)(MEM_IO+0x0000))

He previously #define MEM_IO as the address for the display control register.

#define MEM_IO 0x04000000

What I DON'T get, is why he adds 0x0000 to the memory address.

It might be something really simple such as me not having all the math basics of Hexadecimal down, or maybe I don't get pointers properly, but I just can't figure out why and what it does. Can anyone explain?
_________________
"Do you know what the chain of command is? It's the chain I get and beat you with until you understand who's in rutting command here!" -Jayne Cobb

#131406 - chishm - Fri Jun 15, 2007 5:11 am

0x04000000 is the base address of the GBA's registers. Adding 0x0000 doesn't accomplish anything when the code is compiled, but it lets the reader/programmer know that the register has an offset of 0 relative to the register base address.
_________________
http://chishm.drunkencoders.com
http://dldi.drunkencoders.com

#131408 - ShannonB - Fri Jun 15, 2007 6:14 am

Ok, so it's just Good Programming Practice(tm)?

When would the number NOT be zero? Could you give an example with any of the GBA registers?
_________________
"Do you know what the chain of command is? It's the chain I get and beat you with until you understand who's in rutting command here!" -Jayne Cobb

#131409 - chishm - Fri Jun 15, 2007 6:50 am

REG_DISPSTAT should be *((volatile u16*)MEM_IO + 0x0004), since it is a 16 bit register at 0x04000004 (register base address + 4). You can find all the known registers in the IO map of GBAtek.
_________________
http://chishm.drunkencoders.com
http://dldi.drunkencoders.com

#131410 - ShannonB - Fri Jun 15, 2007 6:57 am

Aah ok, perfect. I'm used to previous examples bit shifting the values into the correct position. Looking at it, it seems to have the same effect of bit-shifting the setting into the correct bits in the register.

This, once you understood it, should be a lot easier to read and to use.

Thanks muchly for your help. If I'm off in my understanding though please let me know.
_________________
"Do you know what the chain of command is? It's the chain I get and beat you with until you understand who's in rutting command here!" -Jayne Cobb

#131421 - Lick - Fri Jun 15, 2007 11:44 am

Sometimes people refer to a specifications document while coding, especially when it's necessary to deal with many registers. It's then easier to "follow the documents notation".
For example, the documented memory is MEM_IO [0x04000000], and its sections are notated by offset [0x????], not by absolute address [0x0400????]. It's then easier to "copy from the document" if you simply use offsets as well.

I'm not sure if Cearn (TONC) did it because of this reason though.
_________________
http://licklick.wordpress.com

#131445 - Cearn - Fri Jun 15, 2007 6:35 pm

ShannonB wrote:
Anyway, he makes a #define to point to the Display control register, which I get.
Code:
#define REG_DISPCNT *((volatile u32*)(MEM_IO+0x0000))


He previously #define MEM_IO as the address for the display control register.
Code:
#define MEM_IO      0x04000000

What I DON'T get, is why he adds 0x0000 to the memory address.

Because I can :P

It's partially what Lick said: all the IO-registers are in the same section of memory; by using a base #define + offset strategy, you can highlight the relations. Also, I find things with many zeros harder to read and easier to mis-type. Compare 0x400004 and 0x4000004. They look much the same, but the former has one zero too few. With a base+offset, you can minimize such mistakes. This is also why Tonc uses something like 0400:0000 for addresses: it's easier to read.

Adding 0x0000 is just for alignment with the rest of the register #defines, really. One of the many optimizations that compilers do is 'constant folding', which can take constant expressions ( like "1+2*3/4-5<<6", but also "DCNT_MODE3 | DCNT_BG2" ), calculate them at compile-time and put that in the binary. Constant arithmetic expressions don't cost anything and can make code clearer, which is always nice. It's still mostly just a matter of preference though.