#476 - staringmonkey - Wed Jan 08, 2003 1:30 am
Hey all,
For anybody who wants to hit me with the "where the hell have you been, we never talk to you anymore" style questions, you can go ahead, but thats not the reason for this post. :)
Normally I'd post my problems on the Yahoo group, but I thought I'd give these handy dandy new message boards a spin.
Heres the situation:
Basically, I've run out of IWRAM and I don't know why. But let me start at the beginning. The last few coding sessions I've had I've been having variables return incorrectly, AKA the values in the variables are fine within the function, but when returned and stored in a variable the value is corrupted. I thought that I was just doing something stupid so I took some time off from that and did some optimization stuff, but yesterday when I went back to work on it I started having the same problem. I didn't know what could be causing it other than some sort of memory bug so I just checked the address of one of my most recently initialized variables to see where it was in memory and it was at 0x3007d73, right on the trailing edge of IWRAM! I can more or less put together the pieces on whats going on here, but I don't understand where my RAM could have gone. All my game data is in ROM and my game variables are in EXRAM (granted the pointers to them are in IWRAM, but thats not much). According to my .map file my last global is being placed at 0x030007a8, not even 2K into RAM. So the only things in memory are code, 2K of globals, and local variables... that can't account for 32K worth of RAM. I don't understand what the rest of my memory is being used for.
For the sake of experimentation (the way I usually find solutions to bugs) I tried declaring a variable right at the beginning of my first function to see where it was getting put. Address check: 0x3007ef4. So basically I'm missing the vast majority of IWRAM... I won't claim to having ever been an expert on low-level memory management, but never-the-less I've never seen anything like this.
Any ideas what the hell is going on? BTW, this is for a professional project with an upcoming deadline, so time is severely NOT on my side.
Thanks in advance,
staringmonkey
#483 - ampz - Wed Jan 08, 2003 1:53 am
That's your stack.
The stack is usually placed at the end of the memory area.
Local variables goes onto the stack you know.
#485 - staringmonkey - Wed Jan 08, 2003 2:14 am
Ampz:
Ahhhhhhhh (sigh of understanding). I didn't know the stack was placed at the end of memory. Well that makes sense. Tid-bit of knowledge that I did not know. So then my problem may not be a memory issue after all. Then why are my functions returning incorrect values...?
I guess I'll go tinker with this code some more... maybe it was something stupid I was doing after all... :)
Thanks,
staringmonkey
#487 - Touchstone - Wed Jan 08, 2003 2:21 am
If you have the official devkit hardware you can use the debugger to single-step each assembly instruction and that way follow your data from one function to the next more closely than by single-stepping each C line. If you don't have the debug hardware on the other hand you're .. how should I put this .. on your own.
_________________
You can't beat our meat
#488 - theSparko - Wed Jan 08, 2003 2:34 am
I am a total Noob to GBA development, but I know some programming and I thought this sounded like a bug that might deal with passing by value or reference.
Y'know:
Code: |
void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
return;
}
|
Now if you check the value of x and y they're still their original values because C is pass by value. So the function gets the values of x and y not a reference to their addresses.
Anyway, I'm sure you probably already thought of this, but I thought I'd throw it out there anyway just cause I like to help people.
Helpfully,
theSparko
#506 - tom - Wed Jan 08, 2003 7:47 am
staringmonkey wrote: |
So then my problem may not be a memory issue after all. Then why are my functions returning incorrect values...?
staringmonkey |
post one of these functions. perhaps you're returning addresses of local variables on the stack ?
#507 - staringmonkey - Wed Jan 08, 2003 7:50 am
Hey guys,
TouchStone: No I don't have official dev-hardware, not yet anyway.
theSparko: Not quite what I was asking for, but thanks for trying to be helpful. :)
Normally I wouldn't post code, but this is an extenuating (sp?) circumstance:
Code: |
///////////////////////////////Output////////////////////////////////////////
u8 Output(u8 screenMem, u16 font, u8 palette, u8 startX, u8 startY, u8 maxX, u8 maxY, char *originalString, ...)
{
//Local variables
u16 i = 0; //Looping variable
u8 x = 0; //X Column
u8 y = 0; //Y Row
char outputString[(strlen(originalString) + 32)]; //String with variables
u16 length = 0; //Array length
u16 currentLetter = 0; //Current letter
u16 *destination = 0; //Target memory
u16 findSpace = 0; //Used to find last space before line-end
//Cocanate variables into this string
va_list arguments; //Get arguments list
va_start(arguments, originalString); //Start
vsprintf(outputString, originalString, arguments); //Copy arguments
va_end(arguments); //End
//Get the target memory
destination = GET_SCREEN_MEM(screenMem);
//Get the length of the string
length = strlen(outputString);
//Starting cursor position
x = startX;
y = startY;
//Output the text
for(currentLetter = 0; currentLetter < length; currentLetter++)
{
//This letter is a carriage return
if(outputString[currentLetter] == TEXT_CR)
{
//Next line
x = startX;
y++;
//Next letter
continue;
}
//If past the end of this line
if(x >= maxX)
{
//Start at currentLetter
findSpace = currentLetter;
//Search string
while(outputString[findSpace] != TEXT_SPACE)
{
//Backwords from current point
findSpace--;
//No spaces found in the sentence
if(findSpace <= 0)
{
//Just start writing on the next line with this letter
findSpace = currentLetter - 1;
break;
}
}
//Move forward from the found space
for(i = findSpace + 1; i < currentLetter; i++)
{
//Erase this letter
destination[(y * 32) + (x - (currentLetter - i))] = 0;
}
//Beginning of next line
x = startX;
y++;
//Move back in the string (just past the space) and start writing again
currentLetter = findSpace + 1;
//Past maximum length
if(y >= maxY)
{
//Quit writing
return (y + 1);
}
}
//Output the current letter
destination[(y * 32) + (x)] = ((font + (outputString[currentLetter] - 32)) | (palette<<12));
//Next space
x++;
}
//Return next open line
return (y + 1);
}
|
When I pass call this function as:
Code: |
currentLine = Output(8, bg_font_graphics, bg_font_palette, DIALOGUE_WINDOW_LEFT + 3, currentLine, DIALOGUE_WINDOW_RIGHT, 32, "%s", message->responses[3]);
|
Where message->responses[3] = "1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0"
The thing returns 53... incorrect.
Strangeness #1: If I change message->responses[3] to "1234...etc" (no spaces) it works fine.
Strangeness #2: If I check the value of y immediately prior to returning, it is 11.
!I AM SO CONFUSED!
Thanks again,
staringmonkey
#513 - Quirky - Wed Jan 08, 2003 9:26 am
Does this work then?
char outputString[(strlen(originalString) + 32)]; //String with variables
because I can't imagine it'd compile - the copiler doesn't know the size of outputString at compile time... Anyway that's by the by, when you do this:
vsprintf(outputString, originalString, arguments)
"arguments" is longer than 32, which is the extra space you've alloted in your char buffer, isn't it? That could explain why it works with "1234567890" but not "1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0". Any behaviour after this step is undefined. Have you tried setting
char outputString[200];
or something really big that will definitely hold all the chars? I'm probably way off though...
#515 - tom - Wed Jan 08, 2003 9:48 am
Quirky wrote: |
Does this work then?
char outputString[(strlen(originalString) + 32)]; //String with variables
|
this is certainly one of the problems. the size of a variable on the stack must be a constant value, determinable at compile time. i wonder why this even compiles. vc++ refuses to compile that (which is correct behaviour)
i'd try something like that:
char *outputString = (char*)malloc(strlen(originalString)+32);
don't forget to free up the allocated memory at the end of the function.
or use a large enough string, as Quirky suggested, although that is of course not very safe =)
#516 - staringmonkey - Wed Jan 08, 2003 10:01 am
Hey,
Yep, you guys are right. I just made this discovery myself, albeit in a far more roundabout way then you guys did. (Lets just say it involved lots of futzing with how the string was passed.)
Stupid, stupid mistake... oh well... I guess sometimes you have to learn the hard way. Not that I'll look at it that way in two weeks when my first milestone is due. :)
Thanks again,
The ever-so-humbled staringmonkey
#518 - ampz - Wed Jan 08, 2003 10:23 am
Actually, an local array CAN be of variable size. This is a C99(I think) feature that GCC supports. (however, not all compilers do support it)