Welcome! Log In Create A New Profile

Advanced

Saving and Loading Problem

Posted by Arikado 
Re: Saving and Loading Problem
January 29, 2009 11:59AM
Note: watch out for endian issues when dealing with fileformats and integers!
Re: Saving and Loading Problem
January 29, 2009 12:02PM
In my understanding you don't have to worry about it as long as you writing and reading the data on the same plattform.

please correct me if i'm wrong.
Re: Saving and Loading Problem
January 29, 2009 04:38PM
True, but platforms tends to change quite suddenly without you being prepared. It's not that unreasonable to want a level editor on the pc instead.
Re: Saving and Loading Problem
January 29, 2009 08:19PM
Alright, I got it working. Here's the final version of the code:

                FILE *pattern;

               void SavePattern(){
	
	pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","wb");
	
	fwrite(brickx, 1, sizeof(brickx)*30, pattern);
	fwrite(bricky, 1, sizeof(bricky)*30, pattern);
	
	fclose(pattern);
	
	}
	
	void LoadPattern(){
	
	pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","rb");

	fread(brickx, 1, sizeof(brickx)*30, pattern);
	fread(bricky, 1, sizeof(bricky)*30, pattern);
	
	fclose(pattern);
	
	}

Thank you very much Tantric and Koopa. I couldn't have accomplished this without your help. Thanks to you, WiiBreaker now has a working, fully functional level editor. I'll be sure to mention you in the thank you section on the readme and on the wiki. Once again, thank you very much. :)
Re: Saving and Loading Problem
January 30, 2009 12:16AM
On a slightly unrelated note; When I open up the pattern file in notepad all I get is garbage characters. So I created a tool for the wii to display the values of the bricks one by one on the television screen:

int brickx[30]; //X values for the bricks
	int bricky[30]; //Y values for the bricks
	
	int brickweareon = 0;
	
	GameWindow gwd;
	
	ftImage print(640, 480);
	
	Sprite Text;
	
	FILE *pattern;
	
	void LoadPattern();//Load Pattern into level editor
	
	void LoadPattern(){
	
	pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","rb");

	fread(brickx, 1, sizeof(brickx)*30, pattern);
	fread(bricky, 1, sizeof(bricky)*30, pattern);
	
	fclose(pattern);
	
	}

    int main(int argc, char **argv){

	
	fatInitDefault();//Initialize the front SD for loading images
	
	gwd.InitVideo();
	
	WPAD_Init(); //Initialize the Wiimote
	
	WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);//Allows us to use the Wiimote pointer
	
	print.setFont(font_ttf, font_ttf_size);
	print.setSize(32);
	Text.SetPosition(100, 50);
    Text.SetImage(&print);
	print.setColor(Color::Color(0,255,255));
	
	LoadPattern();
	
	for(;;)
	{
		WPAD_ScanPads();
		
		print.printf("Brick: %d\n", brickweareon);
		print.printf("X: %d\n", brickx[brickweareon]);
		print.printf("Y: %d\n", bricky[brickweareon]);
			
		print.flush();
			
		Text.Draw();
			
		print.clear();
			
		print.reset();
		
		if(WPAD_ButtonsDown(WPAD_CHAN_0)&WPAD_BUTTON_A)
		brickweareon++;
		
		if((WPAD_ButtonsDown(WPAD_CHAN_0)&WPAD_BUTTON_HOME) || (WPAD_ButtonsDown(WPAD_CHAN_0)&WPAD_CLASSIC_BUTTON_HOME))
		break;	
		
		if(brickweareon > 29)
		brickweareon = 0;
		
		gwd.Flush();
		
	   }
	   return 0;
     }

Anyways, it works for about ten seconds, displaying the values of brick 0 on the screen in a nice pretty blue color. Then the wiimote unsyncs and I get a code dump. Any ideas?
Re: Saving and Loading Problem
January 30, 2009 07:46AM
If you want a program for your pc(lin/win/mac), say it, I'll analize your code and make a reader(/editor?).
Re: Saving and Loading Problem
January 30, 2009 11:52AM
Hey Arikado,

there are still some flaws in your loading/saving routines. Make sure you understand the meaning of the parameters to fwrite/fread.

The parameters for fwrite are:
ptr
Pointer to the array of elements to be written, --- obviously your array brickx
size
Size in bytes of each element to be written. --- you are storing integers in the array, so size in bytes of one element is sizeof(int), or simple 4 bytes
count
Number of elements, each one with a size of size bytes. - you have 30 elements in your array
stream
Pointer to a FILE object that specifies an output stream. -- well your file descriptor: pattern


so writing should be
fwrite(brickx, sizeof(int), 30, pattern);

On your notepad issue: fwrite writes binary data, so you can't view it with an ordinary text editor. You can use an hex editor to view the data.
Re: Saving and Loading Problem
January 30, 2009 02:20PM
@Dykam
Yes, please. For Windows Vista. Editing is not neseccary because I only need to read the files to transfer their data into one of the modes of play. Thanks a ton in advance.


@Koopa
Believe it or not Koopa, I actually tried your method and I experienced loaded coordinates that were even farther off than the original coordinates than when I posted this topic.
Re: Saving and Loading Problem
January 30, 2009 03:11PM
@Arikado:as Koopa said, you have to fully understand how the fwrite/fead functions work before throwing some random code out


Quote
http://www.cplusplus.com/reference/clibrary/cstdio/fread.html
Parameters

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

ptr
Pointer to a block of memory with a minimum size of (size*count) bytes.
size
Size in bytes of each element to be read.
count
Number of elements, each one with a size of size bytes.
stream
Pointer to a FILE object that specifies an input stream.

you are experimenting crash in the last version you posted because you try to read/write outside the allocated memory (you are actually reading 30*30*4 bytes instead of 30*4 bytes) which generally lead to corrupted memory and unexpected behavior or DSI exception.


if you do something like this, for loading:

FILE *pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","rb");
if (pattern)
{
  fread(&brickx[0], sizeof(brickx), 1, pattern);
  fread(&bricky[0], sizeof(bricky), 1, pattern);
  fclose(pattern);
}

and this, for saving function:

FILE *pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","wb");
if (pattern)
{
  fwrite(&brickx[0], sizeof(brickx), 1, pattern);
  fwrite(&bricky[0], sizeof(bricky), 1, pattern);
  fclose(pattern);
}

there is absolutely no reason for you to get loaded values different from saved ones
Re: Saving and Loading Problem
January 30, 2009 03:16PM
Just to clarify, the code I posted before worked (not the tool the save and load functions in the post before that). However ekeeke, your functions are far better than mine and I see where I have gone wrong. Thank you for being so helpful :)
Re: Saving and Loading Problem
January 30, 2009 03:23PM
It worked because you probably simply tested the save/load functions consecutively, without doing anything else in between (that's way you saved data that was outside arrays memory but when you load the content o fthe file, you just ended up overwriting memory with the same values)

or you just get lucky

but believe me, writing 3600 bytes in a 120 bytes array only lead to one thing: memory corruption
Re: Saving and Loading Problem
January 30, 2009 03:32PM
I dont mean to continually post random bits of code, but changing to your method ekeeke doesnt appear to be working.

void SavePattern(){
	
   FILE *pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","wb");
    if (pattern){
    for(int i = 0; i < 30; i++){
    fwrite(&brickx, sizeof(brickx), 1, pattern);
    fwrite(&bricky, sizeof(bricky), 1, pattern);
    }
    fclose(pattern);
    }
	
  }
	
   void LoadPattern(){
	
   FILE *pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","rb");
    if (pattern) {
    for(int i = 0; i < 30; i++){
    fread(&brickx, sizeof(brickx), 1, pattern);
    fread(&bricky, sizeof(bricky), 1, pattern);
    }
    fclose(pattern);
    }
	
  }
EDIT: However it did fix my pattern tool.



Edited 2 time(s). Last edit at 01/30/2009 03:38PM by Arikado.
Re: Saving and Loading Problem
January 30, 2009 03:41PM
you mixed it up again.

it should either be:
void SavePattern(){
	
	FILE *pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","wb");
    if (pattern){
	for(int i = 0; i < 30; i++){
    fwrite(&brickx, sizeof(int), 1, pattern);
    fwrite(&bricky, sizeof(int), 1, pattern);
	}
    fclose(pattern);
    }
	
	}
	
	void LoadPattern(){
	
	FILE *pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","rb");
    if (pattern) {
	
	for(int i = 0; i < 30; i++){
    fread(&brickx, sizeof(int), 1, pattern);
    fread(&bricky, sizeof(int), 1, pattern);
    }
    fclose(pattern);
    }
	
	}


or

void SavePattern(){
	
	FILE *pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","wb");
    if (pattern){
	
    fwrite(&brickx[0], sizeof(brickx), 1, pattern);
    fwrite(&bricky[0], sizeof(bricky), 1, pattern);
	
    fclose(pattern);
    }
	
	}
	
	void LoadPattern(){
	
	FILE *pattern = fopen("sd:/apps/Wiibreaker/data/pattern1.pattern","rb");
    if (pattern) {
	
	
    fread(&brickx[0], sizeof(brickx), 1, pattern);
    fread(&bricky[0], sizeof(bricky), 1, pattern);

    fclose(pattern);
    }
	
	}

Re: Saving and Loading Problem
January 30, 2009 03:50PM
koopa, I tried both of your functions exactly as you posted them and they return or load values far different then the saved values.
Re: Saving and Loading Problem
January 30, 2009 04:03PM
lol, sorry but you put some random code again, can't you just copypaste what I gave you
don't want to sound rude but you should REALLY try first to understand what you are coding


first, there was no more "for" loop needed

and I didn't write

&brickx

but

&brickx[0]


see the difference ?
(same for bricky)

&brickx is a pointer INSIDE the brickx array, i being the offset
&brickx[0] is a pointer to the BEGINNING of the array

by doing what you did, you were writing 30x times the content of the file in brickx, at different offsets
and the result was that:
1/ you ended up overwriting all array values with brickx[0] value
2/ you are writing outside the allocate memory

which is now worst than before

hope this is more clear now

I'd avise you to learn C pointer as soon as possible, it is a little bit complicate first but would be very handy later



Edited 4 time(s). Last edit at 01/30/2009 04:15PM by ekeeke.
Re: Saving and Loading Problem
January 30, 2009 04:54PM
Alright ekeeke I did what you told me and it worked. Not only does it work, its a lot faster than it was before.

Sorry for my ignorance as I took brickx[0] a little to literally and assumed I would end up writing bricx[1], brickx[2], brickx[3]... You get the picture. So I attempted to use a for loop instead. I gave myself a little crash course in C pointers like you reccomended, and why everything works or doesnt work makes alot more sense to me.

Up until a couple days ago I didnt know FILE classes or fopen() even existed. I'd like to personally thank everyone who posted in this topic for getting me as far as you all did. Consequently, WiiBreaker now has a fully working level editor and I have a tool to read pattern files. Once again, thank you to everyone, I would not have gotten even a quarter of the way without all of your help.
Re: Saving and Loading Problem
January 30, 2009 06:25PM
If your are creating an editor on windows you will need to deal with endianess like henke37 mentioned. Here's a function that will help you out.


unsigned long swap2 (unsigned long number)
{
   return (((number&0x000000FF)<<24)+((number&0x0000FF00)<<8) + ((number&0x00FF0000)>>8)+((number&0xFF000000)>>24));
}


If you create the map on Win and load on Wii you will need to do this -
for(int i = 0; i < 30; i++){
    brickx = swap2 (brickx);
    bricky = swap2 (bricky);
}

Also don't forget that an int is 4 bytes on Windows. I think it's 4 bytes on the Wii also.
Re: Saving and Loading Problem
January 30, 2009 07:02PM
Quote
scanff
[...]
If you want to know, I'm going to develop the pc-pattern-viewer in dotNet/Mono, which has some simple endian features. C# is more simple compared to C(++).
Re: Saving and Loading Problem
January 30, 2009 11:36PM
If you want to maintain a human readable file format, so you can edit the file with any text editor, you can write integers to a file as a char array (string), and when you read them back, convert the string back to an integer using atoi.

To convert the integer to a string for saving, you would usually use itoa, but devkitPro/libogc do not include this function, as it is non standard, and the devs think it is useless! However, you can use sprintf instead.

/* NOT a working example, just a hint to get you started */

/* This will save each integer on a new line */
/* FILE *f is a stream you have opened elsewhere */
void write_int_to_file(int value, FILE *f) {
    char buffer[12]; /* You will need some memory to hold the string */
    sprintf(buffer, "%d\n", value); /* print the numerical representation of the int into the buffer */
    fputs(buffer, f); /* Write the buffer to the file stream */
}

/* This will return the integer value in the array */
int read_int_from_array(char *array) {
    return atoi(array);
}

void load_file() {
    /* Open the file stream here - I'll call it inFile */
    
    char buffer[12]; /* buffer to read each line of the file to */
    while (fgets(buffer, 12, inFile) != NULL) {
        int value = read_int_from_array(buffer);
        /* Do something with value */
    }
}



Edited 3 time(s). Last edit at 01/30/2009 11:41PM by DrTwox.
Re: Saving and Loading Problem
January 31, 2009 11:49AM
If you need to know exactly how long the string buffer needs to be, just bring out good old logarithms, log10(number)=number of digits. Just remember to account for the string terminator character too.
Sorry, only registered users may post in this forum.

Click here to login