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 > problem

#29994 - ThUg4LiFe - Sat Nov 27, 2004 10:17 am

Code:
#include <stdio.h>
#include <stdlib.h>

void main()
{
  char* pPermanentMem = (char)malloc(5);

  *(pPermanentMem+0) = 0xF0;
  *(pPermanentMem+1) = 0x00;
  *(pPermanentMem+2) = 0x04;
  *(pPermanentMem+3) = 0xFF;
  *(pPermanentMem+4) = 0x01;

  printf("\npPermanentMem = %X%X%X%X%X", *(pPermanentMem+0), *(pPermanentMem+1), *(pPermanentMem+2),
                                       *(pPermanentMem+3), *(pPermanentMem+4));
  printf("\nIt Should Be F00004FF01");

return;
}


it there a reason that this code (it originally didnt have the printf() statements) crashed the command prompt window? maybe its something obvious and im not seeing it

#29995 - jma - Sat Nov 27, 2004 10:24 am

This:
Code:
char* pPermanentMem = (char)malloc(5);

Should be:
Code:
char* pPermanentMem = (char*)malloc(5);

Jeff
_________________
massung@gmail.com
http://www.retrobyte.org

#29996 - ThUg4LiFe - Sat Nov 27, 2004 10:41 am

ah.. that is one change i made...

i think it wouldnt compile until i cast the memory to "pointer to char" instead of "char".. but once i changed it and it compiled, and i executed the file - it crashed cmd

#30025 - sajiimori - Sat Nov 27, 2004 7:36 pm

With that change it should run fine. However, the output won't be what you expect for 2 reasons.

The chars are going to become ints when they get passed in to printf due to the way variable-length argument lists work. After they become ints, chars with a 1 in the high bit (0xFF and 0xF0) will be bit-extended (to 0xFFFFFFFF and 0xFFFFFFF0 respectively). Declare the buffer as unsigned char* to keep the sign bit from being extended (so you'll get 0x000000FF and 0x000000F0).

Also, leading zeros will be dropped on values like 0x00, 0x04, and 0x01. To make printf pad output with leading zeros, use "%0nX", where "n" is how many digits you want to be printed (so you'd want "%02X" instead of just "%X").

#30084 - ThUg4LiFe - Sun Nov 28, 2004 3:56 am

sajiimori wrote:
With that change it should run fine. However, the output won't be what you expect for 2 reasons.

The chars are going to become ints when they get passed in to printf due to the way variable-length argument lists work. After they become ints, chars with a 1 in the high bit (0xFF and 0xF0) will be bit-extended (to 0xFFFFFFFF and 0xFFFFFFF0 respectively). Declare the buffer as unsigned char* to keep the sign bit from being extended (so you'll get 0x000000FF and 0x000000F0).

Also, leading zeros will be dropped on values like 0x00, 0x04, and 0x01. To make printf pad output with leading zeros, use "%0nX", where "n" is how many digits you want to be printed (so you'd want "%02X" instead of just "%X").


thanx for the help

in my code without that; the fact that they would appear with 8 hexadecimal digits with printf() wouldnt actually be the VALUES stored in memory would they? because a char is only 1 bit (2 hex digits), its just the way printf displays it, right?

#30090 - sajiimori - Sun Nov 28, 2004 4:41 am

If you convert a char to an int, the char will have its sign bit extended to fill the new high bits. That way a negative value will stay negative. Sign bit extension is the main difference between signed and unsigned types.

When you call printf, the compiler will upgrade your chars to ints because variable length argument lists require word-sized values. It's just a quirk of that particular feature.

So, the actual values that get pushed onto the stack as arguments are 32 bits in size (assuming 32 bit ints), but your original chars remain 8 bits.

#30114 - ThUg4LiFe - Sun Nov 28, 2004 1:14 pm

nice one

sajiimori wrote:
If you convert a char to an int, the char will have its sign bit extended to fill the new high bits. That way a negative value will stay negative. Sign bit extension is the main difference between signed and unsigned types.


yeah i read reading about that when i was going over bitwise operations in the book im learning from, but i never understood it until your earlier post

#30165 - ThUg4LiFe - Mon Nov 29, 2004 2:50 am

Code:

printf("\nenter a score to start with:\n");
scanf("%ld", &Practice1);
printf("\nenter number of points to add to it:\n");
scanf("%ld", &Practice2);

*(pPointsAndScore+1) = Practice1;
*(pPointsAndScore+0) = Practice2;

FAKELOOP:
///when a player's points are being added to the visual score each game loop///
   if ((*(pPointsAndScore+1) + (*(pPointsAndScore+0))) > 999999999)
     *(pPointsAndScore+0) = 999999999 - (*(pPointsAndScore+1));

   if ((*(pPointsAndScore+0) != 0) && (*(pPointsAndScore+1) != 999999999))
     {
        for (*pCounters = 8 ; *pCounters > 0 ; *pCounters--)
           {
             if (*(pPointsAndScore+0) / pow(10, *pCounters) == 0)
                continue;
             else
             {
                *(pPointsAndScore+1) += pow(10, *pCounters);
                *(pPointsAndScore+0) -= pow(10, *pCounters);
                printf("%9d :TOTAL SCORE\r", *(pPointsAndScore+1));
             }
             break;
           }
        if (*pCounters < 1)
        {
          (*(pPointsAndScore+1))++;
          (*(pPointsAndScore+0))--;
          printf("%9d :TOTAL SCORE\r", *(pPointsAndScore+1));
        }
     }

now = clock();
for ( ; clock() - now < 100 ; );

if (*(pPointsAndScore+0) != 0)
   goto FAKELOOP;

return;


sorry to have another problem but, im not sure why this isnt giving the result i expect. its just making a continous loop - and the output is not what i wanted at all, at first it was only incrementing the output by 1 each time, and now its just producing crazy results. i know its my fault and ive made a mistake somwhere - it was closer to what i wanted when it incremented 1 at a time - but now it just keeps incrememnting and then going to negative numbers, and not formatted witht the field width i want, and isnt actually using the first number entered as a starting point either now - its simply overwriting what it starts with, with junk numbers

#30172 - sajiimori - Mon Nov 29, 2004 4:05 am

Sorry, that code is too crazy to read.

Most importantly, write functions that do one thing, not many things. Split up your code until you have no more than 2 tabs in a row. Turn complicated expressions into well-named functions.

Don't use magic numbers.

Use a[i] instead of *(a+i). That operator is provided to make your code easier to read, so you may as well use it.

Pick a standard indentation style and stick to it. Line up your braces directly under the keyword (if, for, while, etc).

Don't use goto unless you have a really really good reason. Yours could be replaced with do-while.

pCounters doesn't need to be a pointer. Pointers are useful tools, but unnecessary use just puts more stress on the reader. Among other things, it forces the reader to think about how the pointer might move and who else might be sharing the same memory.

Combining 2 variables with different purposes into an array is pure obfuscation.

Post whole functions or programs with all the relevant declarations, not just floating function bodies.

Edit: here, let me get you started.
Code:
int readIntWithPrompt(char* prompt)
{
  int i;
  printf("%s: ", prompt);
  scanf("%ld", &i);
  return i;
}

int readStartScore()
{
  return readIntWithPrompt("enter a score to start with");
}

int readScoreIncrement()
{
  return readIntWithPrompt("enter number of points to add to it");
}

void whatDoesThisThingDoAnyway()
{
  int score = readStartScore();
  int increment = readScoreIncrement();

  do
  {
    /* simple body with no more nested braces */
  } while(increment > 0);
}

#30197 - ThUg4LiFe - Mon Nov 29, 2004 11:29 am

thanx for all that. it seems im struggling at the minute to get my programming and style right :-[

the idea was............. i wanted to test a code id written, so i added an ability to scan in two integers (one would be placed where the score from the game would be stored in memory, the second would be stored where points to be added to the score is going to be stored) and use this before the loop starts

then through each loop it will increment the "score" by the highest power of 10, up to a maximum of 8 (which equates to 100,000,000) but is not higher than the number of points to be added; and it would deduct the same figure from the number of points to be added

i also wanted to make it wait inbetween each loop for a short time, so i could see if it was working



initially, it just incremented the score by 1, until the number of points to be added = 0. which was close to what i wanted but it needed to start with the higher powers of 10 (up to 8 - depending on how high the numbers of points are to be added was)


also, once it found that there was less than 10 points to be added, in other words, ( points to be added / 10 to the power of 1 = 0 (as an integer) ) then it would know to use increments of 1s and use a different piece of code to finish off the rest of the points and get it down to 0 to exit the loop, (because if it used 10 to the power of 0, it would incrementing by 0 (unless my maths is wrong there!))

#30217 - tepples - Mon Nov 29, 2004 4:47 pm

pow() is floating-point, and floating-point is slow on GBA and on some PC models. If you want to convert an integer to a base 10 string, I'd suggest calling sprintf.

EDIT: clarify somewhere else FP is slow
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.


Last edited by tepples on Mon Nov 29, 2004 8:12 pm; edited 2 times in total

#30241 - sajiimori - Mon Nov 29, 2004 7:44 pm

His code isn't meant for GBA, hence the use of scanf.

#30262 - ThUg4LiFe - Mon Nov 29, 2004 10:44 pm

yes my code is for PC - at the moment

i havent really read much of the GBA specific tutorial yet, so im just practicing with standard C

#30481 - ThUg4LiFe - Wed Dec 01, 2004 4:56 pm

ive found the best thing to do is plan the entire program out as a flow diagram with only ever specific routes that it can take. its making it a lot easier to remember everything i wanted it to do and everything i already devised would be doing - because its easier to understand and write than unfinished code! and if i can plan the entire thing out like this it should then just be a straightforward conversion from the flow chart system to coding

#30513 - sajiimori - Wed Dec 01, 2004 7:39 pm

Yeah, diagrams are often easier to understand than finished code, let alone unfinished code.

With flowchars in particular though, be aware that they will tend to lead you to very procedural solutions, where you solve a problem by making a series of accumulated side-effects. These sorts of programs are easy to write, so most of my early code looks like that, but over the years I've come to greatly appreciate code that can be decomposed into parts that don't depend on the previous step. Such code is very easy to reason about, because you don't have to think about the current "state" to understand a piece of the program.

The most useful kind of diagram I've ever drawn is a dependancy graph, where each module is a node and arrows show what depends on what. It keeps my mind on the big picture, and tends to lead me toward very modular solutions with minimal interdependancies. If my graph is hard to draw due to lines crossing each other all over the place, I'm probably doing something wrong -- and not just with layout. ;)

#30767 - ThUg4LiFe - Sat Dec 04, 2004 1:42 pm

tepples wrote:
pow() is floating-point, and floating-point is slow on GBA and on some PC models. If you want to convert an integer to a base 10 string, I'd suggest calling sprintf.

EDIT: clarify somewhere else FP is slow


to bring this back up, how can i get around the problem with floating-point? i mean i need to use a function to calculate the result of something to the power of something else, how can i do it without using the floating-point pow()? its all integers anyway, i dont think my game would need to use decimal points at all

basically what i want to do is this:

if speed is 0, then the delay before increase is 0
if speed is 1, then the delay before increase is 1
if speed is 2, then the delay before increase is 1
if speed is 3, 4, 5, 6 or 7, then the delay before increase is "2 to the power of (speed - 2)"

simple enough, and things like this would be quicker if i can use a function, than specifying the exact calculation for each possibility - speed will actually be able to go up to 15 later in the game, and this would mean writing a calculation for each example.

i had the same problem where the earlier code was attempting to find "the highest power of 10, that is less than Points". id have to write a seperate expression for each power of 10


--------

secondly, im wondering about division because it also says to avoid this in the FAQ, so what is the best way around this when you need to divide something?

i can think of ways around it - but they seem so long-winded....that id imagine them being slower than division

#30772 - identitycrisisuk - Sat Dec 04, 2004 3:29 pm

If you're dealing with powers of 2 then you can left and right shift things. "2 to the power of (speed - 2)" is the same as 1<<(speed-2);

Off the top of my head, the simplest general purpose function for getting one number to the power of another would be based around a for loop, where the loop goes around to the power of itself times and each loop you multiply your number by itself.

Don't know that much about division really, I have a grand total of one in my code so far that I think is called once per frame. I'm guessing that when it's infrequent like that it doesn't cause much of a problem, it's more if you are doing it many times a frame, in a loop say.
_________________
Code:
CanIKickIt(YES_YOU_CAN);

#30774 - ThUg4LiFe - Sat Dec 04, 2004 4:22 pm

identitycrisisuk wrote:
If you're dealing with powers of 2 then you can left and right shift things. "2 to the power of (speed - 2)" is the same as 1<<(speed-2);

Off the top of my head, the simplest general purpose function for getting one number to the power of another would be based around a for loop, where the loop goes around to the power of itself times and each loop you multiply your number by itself.

Don't know that much about division really, I have a grand total of one in my code so far that I think is called once per frame. I'm guessing that when it's infrequent like that it doesn't cause much of a problem, it's more if you are doing it many times a frame, in a loop say.


that loop sounds like a good and simple solution (for doing a power operation)

and i was thinking that maybe there would be an easy way to deal with powers of 2, seeing as each bit is like increasing the power of 2. thanks for the help

division may not be a problem then if you can use it a small amount, i did have it used somewhere - but removed it because the expression i wrote was incorrect and it wasnt needed at all. however, i know i will need to use division for at least one thing each game loop

#30793 - sajiimori - Sat Dec 04, 2004 7:25 pm

There are many threads here about fixed-point math and fast divison.