Interesting. You mention Adam (Rosenfield, I suppose, maker of EVNEW) so I suppose you know about the EVNEW source code; let me also mention the fact the source code for the .bin to .rez converter included with Nova is available, too.
Anyway, a few notes. First, there are portability issues. WHY THE HECK DO YOU ASSUME A LITTLE ENDIAN HOST? It makes sense for your code to be able to compile on Macs as well (PowerPC Macs, admittedly), we may need to have to convert from .rez; even if there is no shortage of such converters it never harms to consider your code may be used somewhere else than the place you're currently using. Also, try to use explicit-sized integers, C99 defines int32_t and uint32_t, now I know that there are very few environments where int is 16 bits, but they do exist (short is less of a problem as it's always 16 bits, though I know some embedded environments where they don't care much about ISO conformance and have 8 bits shorts to save on space as much as possible, when the ISO standard mandates that shorts be at least 16 bits, and very few people on their right mind would make shorts longer than that). Of course, you cannot avoid some Visual C stupidities (_tmain? wtf?), but as long as they are contained they should be easier to fix, should they need to be.
Then, why name your source file with extension cpp? I only see standard C features (apart from a few Visual C-isms), you might as well rename it with extension c for it to be compiled as plain old C, to avoid a good deal of headaches, sometimes C++ can have surprising effects (say, name mangling and function overloading).
Also, it's only a matter of seconds to replace the hard-coded test.rez with argv(1) so that the name of the file is given on the command line.
I think I know where the 12 is coming from. I think it's because, just after having read IndexTyp.offset, you're already 12 bytes into the file, so you just have to fseek(file, indexTyp.offset, SEEK_CUR) to be at the beginning of the resource entries. It just so happens that it's the offset from the beginning of the file to the first 'e' of "resource.map", but if it was something else than resource.map it would no longer be the case, especially, substracting 1 from it to get the beginning of this string is not a good idea: this offset exists to easily get the beginning of the resource entries even if the string is something else (and especially, something else with a different length) than "resource.map".
I suppose you might wish to know the binary format of the various Nova resources, not just shďp. Unfortunately, the Holy Nova Bible doesn't document such low-level details, it doesn't indicate you which fields are 32 bits and where there is unused space, if any. However, this info is given in the ResEdit Nova templates, available in the Mac distribution of Nova (that you should be able to expand, since it's a .sit archive); this file is itself a resource file (I think you can user Burger's convertor to convert it to .rez if you prefer to rad such files) containing resources of type TMPL, whose ID does not matter (as long as they're different from each other) but whose resource name indicates which resource type they specify the format of. The format of the TMPL resource itself is simple, really:
List running to the end of the resource (no explicit count in the resource):
BYTE number of following chars
CHARs label of the field (used when editing the resource, it's also that way that you can relate them to the description given in the Bible)
(note: there is no padding to 256 or 255 or any NUL terminating byte or whatever, the following comes immediately after the last char of the label string)
CHAR(4) field type, a code made of four characters indicating the kind of field, its size, and how it should be edited.
Full documentation for the field types is available at (damn, Bernard's site seems to be down at the moment) and ResEdit Reference, in the chapter ResEdit Templates at page 79 (93 for the pdf doc). For instance, DWRD is just a two-byte integer, Cxxx is a C string that takes up xxx bytes (in hex), counting the terminating NUL. For instance, the template for bööm is:
So in Mehrunes' syntax, this would be:
By the way, it is indeed better all around to fill the structure one field by one field, instead of trying to fill it entirely at once, because besides byte swapping there are also issues of padding and stuff; however, I think you should byte swap each item of the struct just after you've read it; also, I don't think it's necessary to prefix every single struct item name with "ship", since you already know it's a ship structure and they are only valid within its context so there is no namespace collosion problem (but it's more a matter of personal taste).