Any idea what can cause "error: wrong file type: no header"?

A Kuroobi player on Discord is experiencing an error message saying "error: wrong file type: no header" when displaying the character selection screen.

The error occurs during the loading of the following image table:
sprite-character_select_character-table-240-240

Do anyone has an idea of what could be causing this error? Could it be due to file corruption? Or maybe a bug in my code?

I encountered an error for the exact same image before, but the error message was different (it was "Unknown uC-FS error 1414 when trying to load bitmap tables"), and it occurred because of memory saturation. This seems different here because the player gets this error right after launching the game.

I think I figured it out, strangest bug I've ever seen.

Chromeblast sent me the content of his data folder and it contained a file named sprite-character_select_character.pdt.

So it seems that the value of the constant with the path to the save file have been overridden by the path to an image table. Not sure why, maybe because of memory saturation?

When the game tried to save, it created a file with the name sprite-character_select_character.pdt.
Thus every subsequent load of the image table tried to read the new file located inside the data folder instead of the one inside the PDX.

Or maybe it’s a multi threading error?

@dave: is there a shared buffer between playdate->graphics->loadBitmapTable and playdate->file->open that is used to store the path to the file?

That would make sense: the game load online scores on the title screen. If the player press A before it has finished loading, there are chances that it will complete during the load of the character selection screen.
When the rankings are downloaded I write them to disk in the callback function. So it can occur at the same time as the load of a bitmap table.

Strictly speaking, there's no multi-threading since the Playdate's firmware is based on FreeRTOS and both the Playdate's MCUs don't support threads. There is indeed a shared buffer, however, since loadBitmapTable depends on sd_open and that uses a static 256-byte buffer to store the filename.

1 Like

Thank you! At least it explains why trying to open rankings.data leads to opening sprite-character_select_character.pdt.

I don’t think that mutex are available to use so I think that I can simply stop saving scores inside the fetch callback and only write everything to disk on exit/low power event.

I don't know exactly where the collision is, but SM's got the gist of it: The filesystem functions have some static buffers that don't like being used from multiple tasks. FreeRTOS doesn't have "threads" exactly, but it does have a pre-emptive task switching system that can pause one execution context and continue on another to share CPU between multiple contexts. (Don't ask me how that's different from a thread, I have no idea.) The bug here is that we're invoking your callback immediately from the wifi task instead of queuing it on the game task so that it runs between update cycles.

So yeah, writing in the fetch callback is no good until we fix that. If you do want to write the data to disk after receiving it you could set a flag that you then pick up in the update function.

Thanks to both of y'all for finding this bug!

2 Likes