ZSNES has an (almost) fixed savestate format; everything is basically a struct:
http://www.romhacking.net/documents/170/http://www.romhacking.net/documents/190/http://www.romhacking.net/documents/171/ (SPC)
(these docs are really just copied from the source code)
IIRC after the fixed parts comes a variable-sized block if the game uses a coprocessor, and at the end there's a 64x56 bitmap that contains the savestate preview picture. There are almost certainly some ROM hackers who prefer this fixed format because the savestates can be edited in a hex editor.
SNES9x uses GZIP compression by default (I think you can disable it though with some menu option). After decompression you can see that the data is arranged in various blocks, each of which has a header with ID (signature) and length in bytes. So if you have a tool (like vSNES) that understands this basic file format structure, you can load savestates from future emulator releases and just ignore the unknown blocks. (I think I used the source code to find out the structure of each block.)
vSNES can also load SNESGT and Super Sleuth (now
kindred) savestates, but I don't remember the formats. Super Sleuth also has preview pictures.
bsnes savestates, as far as I know, are created by every system component dumping its state into the savestate file, and loading it from the file again upon savestate loading. Just like with ZSNES' coprocessor block, the only way to know what's inside is to basically recreate the emulator.
Each format is fundamentally incompatible with the others, either by file format structure or because some data is missing / represented differently. vSNES can load a savestate in one format and save it in another, but that's only useful for other savestate tools that understand only a certain format and use only specific parts (like VRAM).
For your own format you would at least need a signature and a version field (unless you want to encode that in the file names). Named blocks with a known structure are good for other tools. (You could also wrap
every variable in a block.) You could even use flat INI files, or
INI files that encode a hierarchy in the section names. Or XML files.