Crash when saving twice (pretty urgent)

I just ported Blocky World to the newest PokittoLib, and I noticed that when I save twice without restarting the game, the game crashes. Was there a change to how saving works that is causing this? I didn’t change any of the saving code, and I even just copied the code over to the new simulator from the old one again, so I’m sure I didn’t mess up any code.

Also, how can I fix it? I don’t really like the prospect of my game crashing every time I save twice in one session.

EDIT: For reference, I’m saving using fileOpen, fileSetPosition, filePutChar, and fileClose. I’m loading using all those as well, except for filePutChar, which is replaced by fileGetChar.

ANOTHER EDIT: I just did my first major optimization for the game to make it run on hardware, and this bug is preventing me from actually creating a world, since I’m using multiple saving functions. I need this to be fixed, otherwise I can’t continue working on the game. I did some tests, and I think it’s a problem with the simulator, as nothing has changed in PokittoDisk.cpp since the previous version.

On hardware or sim?

1 Like

Simulator. I think it’ll work on HW, but I don’t want to have to load the game onto my Pokitto whenever I try to test the game…

Also, I just tried using fileWriteBytes, and it crashes using that too.

Could you paste the file reading/writing code you’re trying to run here?

1 Like

I know it’s not the reading code, since I can load a world as many times as I want. However, here’s the writing code:

void saveCurrentWorld(char saveFile) {
    if (saveFile == 0) {
        fileOpen("sf0.txt",FILE_MODE_READWRITE);
    } else if (saveFile == 1) {
        fileOpen("sf1.txt",FILE_MODE_READWRITE);
    } else if (saveFile == 2) {
        fileOpen("sf2.txt",FILE_MODE_READWRITE);
    }
    fileSetPosition(0);
    fileWriteChar(1);
    fileSetPosition(1);
    fileWriteChar((char)(playerX/16));
    fileSetPosition(2);
    fileWriteChar((char)(playerY/16));
    fileSetPosition(3);
    fileWriteChar(currentWorld);
    for (char y = 0; y < 14; y++) {
        for (char x = 0; x < 14; x++) {
            fileSetPosition((int)(y*14+x+4));
            filePutChar(world.getBlockAbsolute(playerBX + (int)(x-7), playerBY + (int)(y-7)));
        }
    }
    for (char y = 0; y < 100; y++) {
        for (char x = 0; x < 120; x++) {
            switch (currentWorld) {
            case 0 :
                fileSetPosition(((y*120)+x)+200);
                break;
            case 1 :
                fileSetPosition(((y*120)+x)+12200);
                break;
            case 2 :
                fileSetPosition(((y*120)+x)+24200);
                break;
            case 3 :
                fileSetPosition(((y*120)+x)+36200);
                break;
            }
            fileWriteChar(world.getBlockAbsolute((int)x, (int)y));
        }
    }
    for (char y = 0; y < 100; y++) {
        for (char x = 0; x < 120; x++) {
            switch (currentWorld) {
            case 0 :
                fileSetPosition(((y*120)+x)+48200);
                break;
            case 1 :
                fileSetPosition(((y*120)+x)+60200);
                break;
            case 2 :
                fileSetPosition(((y*120)+x)+72200);
                break;
            case 3 :
                fileSetPosition(((y*120)+x)+84200);
                break;
            }
            fileWriteChar(world.getGroundBlock((int)x, (int)y));
        }
    }
    fileClose();
    //if (saveFO.is_open()) {
    //}
    /*for (char w=0; w<4; w++) {
        for (char y=0; y<100; y++) {
            for (char x=0; x<120; x++) {

            }
        }
    }*/
}

I’m 90% sure you don’t have to call fileSetPosition every time, the file position will advance itself after every write.
Also are you sure fileWriteChar exists?

I can’t seem to find it listed:

1 Like

Oops, forgot to put the code here. It’s a custom function:

uint16_t bytesRead;
void fileWriteChar(char c)
{
    bytesRead = fileReadBytes(reinterpret_cast<uint8_t *>(&c), static_cast<uint16_t>(sizeof(c)));
}

I could be wrong, but FileWriteChar() doesn’t seem to write anything…

2 Likes

@catsfolly is right, that’s a read function in your write function.

Plus it doesn’t make sense to make a wrapper for reading/writing single chars, that’s what char fileGetChar(void) and void filePutChar(char) are for.

Oops, that might be the problem. I accidentally put fileReadBytes instead of fileWriteBytes

I’m not using filePutChar because that was previously crashing.

However, I just tried using filePutChar again, because I can’t figure out fileWriteBytes, and I removed most of the fileSetPosition calls because you were right that the position advances itself.

2 Likes

filePutChar shouldn’t be crashing.
It’s possible for it to not work if you try to write past the end of the file, so it’s best to check for errors with if(fileOk() != 0)

Come to think of it you opened in read/write mode so it makes sense that it would be crashing because of the combination of read and write operations interacting todo something odd.

Also remember that the save files must already be the size you need them to be, Pokitto Disk won’t increase the size of a file if you try to read/write more bytes than the file has available.


By the way, I had a quick go at simplifying your code.
I don’t know if it’ll work but I came up with this:

#include <cstdint>

constexpr const std::uint16_t MapHeight = 100;
constexpr const std::uint16_t MapWidth = 120;
constexpr const std::uint16_t MapSize = mapHeight * mapWidth;
constexpr const std::uint16_t MaxMaps = 4;
constexpr const std::uint16_t PlayerVisionHeight = 14;
constexpr const std::uint16_t PlayerVisionWidth = 14;
constexpr const std::uint16_t HalfPlayerVisionHeight = PlayerVisionHeight / 2;
constexpr const std::uint16_t HalfPlayerVisionWidth = PlayerVisionWidth / 2;


bool saveCurrentWorld(char saveFile) {
	pokInitSD();

	if (saveFile == 0) {
		fileOpen("sf0.txt",FILE_MODE_READWRITE);
	} else if (saveFile == 1) {
		fileOpen("sf1.txt",FILE_MODE_READWRITE);
	} else if (saveFile == 2) {
		fileOpen("sf2.txt",FILE_MODE_READWRITE);
	}
	
	if(fileOK() != 0) {
		// File hasn't opened properly,
		// handle this.
		return false;
	}
	
	fileWriteChar(1);
	fileWriteChar((char)(playerX/16));
	fileWriteChar((char)(playerY/16));
	fileWriteChar(currentWorld);
	
	// Save immediate area
	for (char y = 0; y < PlayerVisionHeight; ++y) {
		for (char x = 0; x < PlayerVisionWidth; ++x) {
			filePutChar(world.getBlockAbsolute(playerBX + (int)(x-7), playerBY + (int)(y - HalfPlayerVisionHeight)));
		}
	}
	
	const std::uint16_t currentWorldOffset = (mapSize * currentWorld);	
	const std::uint16_t endWorldBlockOffset = (mapSize * maxMaps);
	
	// Save blocks
	for (char y = 0; y < MapHeight; ++y) {
		for (char x = 0; x < MapWidth; ++x) {
			filePutChar(world.getBlockAbsolute((int)x, (int)y));
		}
	}	
	
	// Move to end of blocks zone
	fileSeekRelative(endWorldBlockOffset - currentWorldOffset);
	
	// Move to correct place
	fileSeekRelative(currentWorldOffset);
	
	// Save ground
	for (char y = 0; y < MapHeight; y++) {
		for (char x = 0; x < MapWidth; x++) {
			filePutChar(world.getGroundBlock((int)x, (int)y));
		}
	}
	
	if(fileOK() != 0) {
		// Some other error,
		// handle this.
		return false;
	}
	
	fileClose();
	return true;
}
2 Likes