Abput "register" and "volatile" directives

Hello,

I'm going trough some XGCC demos.

I think I'm getting the point, but I wonder why sometime pointers are defined as volatile, other times as registers, other times both or neither of them.

For example pointer to Genesis's control and data registers.

Code:
uint *pw

pw = (address of register)

*pw = (data to write)

This does a 32 bits write??

ulong *pw (this would do a 64 bit write)

ushort *pw (this would do a 16 bit write)

uchar *pw (this would do an 8 bit write)

Right??

and one last thing about VBlank... you're suppose to refresh VRAM during VBlank periods. In ASM you can measure that easily, but in C, you don't really know how much time is going to take your refreshing routine. I got problems with Master System because my routine took more time than a VBlank period. How can you handle this in C for Genesis??

Thank you.
 
Originally posted by patroclus02@Fri, 2006-02-17 @ 05:47 AM

and one last thing about VBlank... you're suppose to refresh VRAM during VBlank periods. In ASM you can measure that easily, but in C, you don't really know how much time is going to take your refreshing routine. I got problems with Master System because my routine took more time than a VBlank period. How can you handle this in C for Genesis??

Thank you.

[post=144456]Quoted post[/post]​


i disable the interrupts while in vblank

it's not a real solution since, in fact, it's because you bad coded the vblank :(

the first thing is to know what to do in the vblank and what out of the vlank

last time, I moded x times my code because of this (too long, in, out...)
 
But if you disable interrupts you are not solving the problem. Even with no interrupts, VBlank will finish and the active display period will start again, and thus a real system could get severe graphics corruption. The only solution is do all inside VBlank, or turn the display off while refreshing, as far as I know
 
I wonder why sometime pointers are defined as volatile, other times as registers, other times both or neither of them.
"volatile" is hard to define exactly, but it more or less is a message to the compiler saying "you don't understand what this does, so don't try to optimize it". For example if you had a chunk of code like this:

Code:
*someregister = data1;

*someregister = data2;
The optimizer might say "Hey! Nothing reads this "someregister" variable between those two writes, so I can just get rid of the first write! I'm so smart!". Of course, you don't want it to do this with registers, because both writes do indeed affect the underlying hardware (probably), so you declare the register "volatile". The "register" keyword is a suggestion to the compiler that the variable should be kept in a CPU register instead of in memory. How seriously that suggestion is taken is up to the compiler. Pointers can be register variables, but register variables cannot have pointers to them (because they have no memory address).

This does a 32 bits write??

ulong *pw (this would do a 64 bit write)

ushort *pw (this would do a 16 bit write)

uchar *pw (this would do an 8 bit write)

Right??
Not necessarily. From the comp.lang.c FAQ:

It's often incorrectly assumed that C's types are defined to have certain, exact sizes. In fact, what's guaranteed is that:

type char can hold values up to 127;

types short int and int can hold values up to 32,767; and

type long int can hold values up to 2,147,483,647.

In particular, it's almost certain that "long int" is 32-bit on Genesis; the standard 64-bit type is "long long int" and is only defined in C99. "int" is probably 16-bit if it's being used to declare registers.
 
But then... what would be the difference between "char" and "short"

If "int" is 16 bits, "short" should be 8 bits, and "char" also 8 bits.

But in PC, short is 16 bits and char 8 bits. char is suppose to be half of short. This is confusing, as you need to know very well if you are writing 16 bits or 32 bits to a register, as VRAM access is 32 bit command
 
Originally posted by patroclus02@Fri, 2006-02-17 @ 07:01 PM

But then... what would be the difference between "char" and "short"

If "int" is 16 bits, "short" should be 8 bits, and "char" also 8 bits.
Short can't be less than 16 bits wide (in a standard-conforming compiler anyway). If int is only 16 bits wide, then short must also be 16 bits wide, as short cannot be wider than int.

But in PC, short is 16 bits and char 8 bits. char is suppose to be half of short.
There is no specified relation between char and short. In fact, since a char is supposed to be capable one character of the local character set you could well have a 16-bit or wider char. You can't make any assumptions about types beyond what is specified in the language standard.

This is confusing, as you need to know very well if you are writing 16 bits or 32 bits to a register, as VRAM access is 32 bit command
Know your compiler, know your system.
 
Ok, the volatile and register directives are clear to me. But, for those that develop for Genesis using C.. they must know what a shor, char, int and long stand for...

writing to VRAM needs to be done in word of 16 bits, and the first write of 32 bits, except for registers. So, an absolute control over write lenght is required.

Someone knows??
 
There is a standard C include file called limits.h. Amongst other things it defines a number of macros that indicate the largest values you can store in the standard integer types. UCHAR_MAX, USHRT_MAX, UINT_MAX and ULONG_MAX should tell you what you need.

And again, there is no "C for Megadrive" standard - depending on what compiler you use, types can and will have different sizes.
 
It would probably be best to read your compiler docs and/or the assembly output to see what it's doing and then use a suitable set of typedefs in case you ever want to compile with something else. If you really want "absolute control" over a read/write, you could do it with an asm function/macro (depending on which is more suitable for your compiler), but that would likely be less portable than the typedefs.
 
Back
Top