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.

Coding > low-level programming in GBA

#166993 - bollkalle - Wed Feb 25, 2009 5:50 pm

Hello!

I am very interested in low-level programming. I wonder if it's possible to program very low to GBA. For example: I write a register and put a value in it. And for everything in the program I will do this way. Is it easy or at least possible?

#166995 - gauauu - Wed Feb 25, 2009 6:32 pm

Yes, it's not only easy, it's a fairly normal way of doing things. Look at libgba -- they have most (if not all?) of the hardware registers #define'd to constants.

Using C and pointers, (or assembly, if that's your thing), you can easily read/write these registers.

#167006 - bollkalle - Thu Feb 26, 2009 7:16 am

OK! Thanks for the reply!

EDIT: Is it possible to write like this:

if (0x04000164 == 7)
{
0x04000166 = 5;
}

Or do I have to do something more?

#167008 - elhobbs - Thu Feb 26, 2009 2:42 pm

no, but close. you need to cast the address to a pointer of the correct size and dereference it. getting the size correct is important as well as marking it as volatile, which is why you are better off using the defines - plus it easier to understand when you come back to the code a week or even a day later.
here is an example from video.h in libnds
Code:
#define GFX_TEX_FORMAT        (*(vu32*) 0x040004A8)

and it is written t like so
Code:
GFX_TEX_FORMAT=0;

#167009 - bollkalle - Thu Feb 26, 2009 2:49 pm

But isn't it several bits in an address like this: 0x040004A8?

#167010 - elhobbs - Thu Feb 26, 2009 3:27 pm

bollkalle wrote:
But isn't it several bits in an address like this: 0x040004A8?
I am not really sure what you are asking. but, 0x040004A8 is a literal or just a number in C. until it is cast to a pointer the compiler can not use it. your statement is equivalent to 8=5.

the arm processors in the ds are byte addressable. so, each address points to a byte in memory. the memory regions that you refer to point at hardware registers. some of them are 8bit, 16bit, or 32bit wide. so they need to be cast to the correct pointer types so that they are written to correctly. using the defines shields you from doing this wrong.

#167011 - Cearn - Thu Feb 26, 2009 3:43 pm

bollkalle wrote:
But isn't it several bits in an address like this: 0x040004A8?
Not bits in the address; bits at the address. The address points to where you have to set the bits. To write to bits at some address, you have to do what elhobbs mentioned: create a pointer and then dereference it.

elhobbs wrote:
... hardware registers. some of them are 8bit, 16bit, or 32bit wide. so they need to be cast to the correct pointer types so that they are written to correctly.
This is not entirely true. You can access the hardware registers with any datatype, it's just that some datatypes are more useful than others.

For example, take the windowing registers. REG_WININ is defined as a 16-bit register with control bits for both window 0 and window 1. But you can also separate these into, say, byte-sized REG_WIN0CNT and REG_WIN1CNT, which are probably easier to use.

A contrasting example is REG_BGnX, which technically 32-bit, but sometimes also split into 16-bit REG_BGnX_L and REG_BGnX_H. In this case the split is rather pointless, but it would work.

#167013 - bollkalle - Thu Feb 26, 2009 4:25 pm

So if I have a register and want to put bits in it, I can do like this:

0100011011000101

Or what?

#167015 - elhobbs - Thu Feb 26, 2009 4:41 pm

bollkalle wrote:
So if I have a register and want to put bits in it, I can do like this:

0100011011000101

Or what?
I am not sure what you are asking.

yes, you can use binary values though I think you need to put a b in front (or something like that). however, hexidecimal is more common since it is more compact.

I am not sure how familiar you are with C programming, but it sounds like you may not be that familiar with it. Trying to learn C with low level register manipulation can be challenging. I think if you are asking this type of question then you should definitely be using the libnds defines or a higher level library.

#167016 - bollkalle - Thu Feb 26, 2009 4:48 pm

I do not program in C usual, but I have programmed in C++ pretty much.

Where can I learn about register manipulation?

#167018 - elhobbs - Thu Feb 26, 2009 5:28 pm

I do not think you need to read about register manipulation per say. I think you may want read up on pointers and casting data types. perhaps something on bitmasks as well. you should be able to find a wealth of information using your favorite search engine. you probably could learn quite a bit by looking at the source code for the examples that are provided with lidnds.

#167022 - Miked0801 - Thu Feb 26, 2009 6:21 pm

Have you ever worked with the following C/C++ ops?

|
&
^
~

As in:

Code:

foo = ((foo2 | foo3) & ~fooMask) ^ 0x01;


If you cannot explain in plain English what each step in the above is doing, then you need a refresher and the low-level GBA is beyond you for now.

#167023 - sgeos - Thu Feb 26, 2009 7:15 pm

Miked0801 wrote:
Code:
foo = ((foo2 | foo3) & ~fooMask) ^ 0x01;
If you cannot explain in plain English what each step in the above is doing,

This strikes me as an amazing interview question.

Here is the same thing, but it might be a little easier to explain if you are finding all the foos confusing. What is the final status of the unit? (flagNonFlyingMask consists of flagLand + flagSea).
Code:
unitFlags = ((flagAir | flagLand) & ~flagNonFlyingMask) ^ flagHidden;

#167045 - elyk1212 - Fri Feb 27, 2009 6:04 pm

bollkalle wrote:
So if I have a register and want to put bits in it, I can do like this:

0100011011000101

Or what?


In my opinion, representing the value hex is quite a bit more readable and also easier to not make mistakes in bit placement. But whatever works for you I guess.

Quote:

Code:

unitFlags = ((flagAir | flagLand) & ~flagNonFlyingMask) ^ flagHidden;



I wish my interviews had questions like that :P.

My last one, some guy that barely spoke english just started drawing logic gates on the board, in a huge mess, and at the end asked me what it did. Then I got some kind of weird ones like how to verify a toaster, and this was supposed to be an hour response?! Then some guy drew a machine that had a magnetic disc in the center, he showed polarity on each part of the disc, stated how fast it was spinning then wanted a description of what kind of circuit it would be equivalent to, given the wave forms that it produces. That was one weird interview... fun, but strange.

#167069 - Miked0801 - Sat Feb 28, 2009 5:25 am

Sounds like and M$ interview. Off the wall questions followed by some good ones.