[Wiki]POP files

Introduction

POP files, or Pokitto Programs, are like bin files, but can contain a lot more information.

The easiest way to make a POP is with the mkpop tool. Simply drag-and-drop your bin, fill in the title/author/description fields, and optionally drag-and-drop icons and screenshots. If you don’t have icons, it’ll make an attempt at generating one based on the title. It’s good to have at least a screenshot of the title screen.

In total, 4 icons will be stored inside the POP: two small (24x24 4bpp, 24x24 16bpp) and two large (36x36 4bpp, 36x36 16bpp). Color conversion is done automatically using @Pharap’s palette:
image

Or, if you prefer hex values...
  0x181c20,
  0x4a5052,
  0xa4a19c,
  0xffffff,
  0x202c9c,
  0x5255ff,
  0x08a18b,
  0x39b2de,
  0x8b20ac,
  0xf691a4,
  0xa42010,
  0xff8518,
  0xffde39,
  0x734429,
  0x527d10,
  0x83ce18,
If you want to import it in the FemtoIDE image editor...

…here is the palette in Jasc pal format:
pop.pal (206 Bytes)


File Format

POP files are composed of a series of tags, their lengths and their data. There is no header, all tags are optional and can be in any order (though the mkpop tool puts smaller tags first). Unknown tags can be safely ignored and skipped.

With one exception, all tags have the following format:
[4 bytes tag Id] [4 bytes data length ] [ data bytes ]

The CODE tag does not have a data length. All bytes, including the tag id itself until the EOF, are considered the data.
All string tags have a data length and are zero terminated.

An enum with all the tags can be found here.

These are the currently defined tags:

  • 0 - PADDING: filler data used to align the following tag (currently unused)
  • 1 - INDEX: Data contains an index of following tags/offsets (currently unused)
  • 2 - OFFSETADDRESS: Used together with the CODE tag to define where that code should be located (default is zero)
  • 3 - CODECHUNK: Contains an offset address (4 bytes) followed by the code to load to that address.
  • 4 - ENTRYPOINT: Reserved
  • 5 - CRC: Intended to verify integrity of the game currently loaded in flash. (currently unused).
  • 6 - HAT: Intended to indicate required/compatible hats
  • 7 - LONGNAME: String. Name of the game without restrictions.
  • 8 - AUTHOR: String. Name of the author(s).
  • 9 - DESCRIPTION: String. Short description of the game.
  • 10 - IMG_36X36_4BPP: Large,16 color icon bitmap data
  • 11 - IMG_24X24_4BPP: Small, 16 color icon bitmap data
  • 12 - IMG_100X24_4BPP: Wide 16 color logo bitmap data (unused)
  • 13 - IMG_110X88_4BPP: Low-res 16-color screenshot (unused)
  • 14 - IMG_36X36_565: Large, High-color icon bitmap data
  • 15 - IMG_24X24_565: Small, High-color icon bitmap data
  • 16 - IMG_100X24_565: Wide, High-color logo bitmap data (unused)
  • 17 - IMG_110X88_565: Low-res High-color screenshot (unused)
  • 18 - IMG_220X176_565: High-res, High-color screenshot
  • 19 - IMG_200X80_4BPP: 16 color Kraken banner
  • 20 - IMG_200X80_565: High-color Kraken banner
  • 21 - VERSION: String that identifies the version of the game
  • 0x10008000 - CODE: Code that should be loaded into the OFFSETADDRESS. This tag has no size, it’s data is the remainder of the file so it should always be the last.

The mkpop tool currently emits the following tags:

  • LONGNAME
  • AUTHOR
  • DESCRIPTION
  • IMG_24X24_4BPP
  • IMG_24X24_565
  • IMG_36X36_4BPP
  • IMG_36X36_565
  • IMG_220X176_565 (for each screenshot)
  • CODE

Reading POP files

Here’s the basic idea, adapt to your specific use-case.

struct Tag {
	uint32_t id;
	uint32_t length;
};

Tag tag;

FILE *file = FS.fopen( fileName, "r" );

// While there are still tags to read...
while( FS.fread( &tag, sizeof(tag), 1, file ) != 0 ) {

	if( tag.id == tag you want ) {

		// Found the tag you're interested in.
		// Read the data to a buffer and do something with it.
		FS.fread( buffer, tag.length, 1, file );
		break;

	} else if( tag.id == TAG_CODE ) {

		// Need to stop reading tags here.
		break;

	} else { 

		// Unknown tag, skip the data to read the next one.
		FS.fseek( file, tag.length, SEEK_CUR );

	}

}

FS.fclose(file);
10 Likes

Maybe you should add a section about why to use pop files instead of bin files for beginners (like myself/

1 Like

In order to satisfy the requirements for binary distribution under some licences, I suggest you include a LICENCE tag. This could be a String type.

2 Likes

The more beginner-oriented information will come at about the same time as the new gamedisk, I think. Things are still under development and might change.

Yes, that would be good. I’ve intended to add this tag since it was suggested in the Extensible Loader thread, but haven’t done so because the loader still doesn’t have a UI to show string tags yet.

Would it be possible to extend this to include addition game resources.
Music, sprites and other data?

It would, but loaders would need to store the name of the pop in eeprom.

Why would that be?

Users can put the pop file in a folder or change the name. Then the game wouldn’t be able to find its resources.

Thats already a problem with resource folders having to be on the top of the file structure

Yes, but people are less likely to rename resource folders, it’s more obvious that doing so would break things.

Dissociating the resource folder with the binary file seems to be a bad idea aswell. Would a type of dot file on the sd card be more convenient to figure out file pathing for both folders and pop files?

Or in a specially named file at the root of the SD card.
E.g. lastLoaded (or lastload or something if there’s file naming restrictions).


Storing data in a .pop file probably isn’t going to have any restrictions that storing the data in a separate file wouldn’t.

We’d probably be better off just agreeing on some kind of convention.
E.g. People agree to keep their game resources in /games/<userName>/<gameName>/.

We could even have a library to codify the convention.
E.g. getResourceFolder(char * buffer, std::size_t length, const char * userName, const char * gameName) (wrapped in a template that automagically fills in the array size of course).

The loaders could be less cluttered with folders, Multiple versions of a game with different resources would be possible as well.

While I’d prefer not to impose restrictions on how people organize their SD cards, anything would be better than forcing people to throw everything in the root of the card.

5 Likes

This is a out my knowledge, Is there any way to search for a file or folder?
Problem i see with both eeprom path and lastload file is wen you program over usb that will not update.
Smaller issues like swapping card or users re organizing files gives similar errors.

Pretty much every OS does it in one way or another.
Windows has its ‘System32’, ‘AppData’, documents, pictures, music, videos and user profile locations (most of those can be moved, but it’s awkward and requires messing with the registry),
Linux and OSX have their /bin, /boot, /home, /lib et cetera.

We could probably get away with just having a few top level folders for specific things.
E.g.

  • /games for games
  • /music for music not affiliated with games (e.g. for using the Pokitto as a music player)
  • /user for storing user-specific info
  • /tools for programs that aren’t games (like calculators)

And under each of those could be a directory with the name of a person/group responsible for creating said games/music/tools, and then the games/music/tools themselves.

E.g.

  • /games/<userName>/<gameName>.pop - a game executable
  • /games/<userName>/<gameName>/ - game resources
  • /music/<userName>/<musicName>.snd - a music file
  • /tools/<userName>/<toolName>.pop - a tool executable

Or the system could be turned on its head a bit…

E.g.

  • /<userName>/games/<gameName>.pop - a game executable
  • /<userName>/games/<gameName>/ - game resources
  • /<userName>/music/<musicName>.snd - a music file
  • /<userName>/tools/<toolName>.pop - a tool executable

I’m not sure what the merits of each approach are,
but I’m sure both have their pros and cons.

The problem with doing things as every other OS does is that here the majority of files are games (or are somehow associated with a game).
When you have a lot of games, finding one in a really long list becomes difficult.
Imagine an SD card with >1000 Gameboy bins all in the same folder.

I’m not sure that will always be the case though.
If it were then we wouldn’t need these fancy pseudo-OS loaders/facilities.

But if that is the case then perhaps the top layer should indeed be the creator rather than the type of ‘thing’?

Sounds like my Steam/SteamApps/common folder. :P

It does, but that’s not what most people use to start up their games. The steam client has a set of categories (Installed, Not Installed, etc) and also user-customizable categories for further organization (FPS, RPG, Indie, etc).

1 Like

The arduboy flash cart loader appears to divide games up by genre, probably based on the arduboy game repo. What if we could sort by the same set of genres as we have in the Pokitto games page, if that metadata were to be added to pop files?
Edit: Or perhaps we could divide the games into folders for each genre, if it’s too much to ask the loader to look through every pop file to sort them.