#include "create_supernova.h" #include "gametext.h" #include "file.h" #include "po_parser.h" // HACK to allow building with the SDL backend on MinGW // see bug #1800764 "TOOLS: MinGW tools building broken" #ifdef main #undef main #endif // main // List of languages to look for. To add new languages you only need to change the array below // and add the supporting files: // - 640x480 bitmap picture for the newpaper named 'img1-##.pbm' and 'img2-##.pbm' // in pbm binary format (you can use gimp to generate those) // - strings in a po file named 'strings-##.po' that uses CP850 encoding const char *lang[] = { "en", NULL }; void writeImage(File& outputFile, const char *name, const char* language) { File imgFile; char fileName[16]; sprintf(fileName, "%s-%s.pbm", name, language); if (!imgFile.open(fileName, kFileReadMode)) { printf("Cannot find image '%s' for language '%s'. This image will be skipped.\n", name, language); return; } char str[256]; // Read header (and check we have a binary PBM file) imgFile.readString(str, 256); if (strcmp(str, "P4") != 0) { imgFile.close(); printf("File '%s' doesn't seem to be a binary pbm file! This image will be skipped.\n", fileName); return; } // Skip comments and then read and check size do { imgFile.readString(str, 256); } while (str[0] == '#'); int w = 0, h = 0; if (sscanf(str, "%d %d", &w, &h) != 2 || w != 640 || h != 480) { imgFile.close(); printf("Binary pbm file '%s' doesn't have the expected size (expected: 640x480, read: %dx%d). This image will be skipped.\n", fileName, w, h); return; } // Write block header in output file (4 bytes). // We convert the image name to upper case. for (int i = 0 ; i < 4 ; ++i) { if (name[i] >= 97 && name[i] <= 122) outputFile.writeByte(name[i] - 32); else outputFile.writeByte(name[i]); } // And write the language code on 4 bytes as well (padded with 0 if needed). int languageLength = strlen(language); for (int i = 0 ; i < 4 ; ++i) { if (i < languageLength) outputFile.writeByte(language[i]); else outputFile.writeByte(0); } // Write block size (640*480 / 8) outputFile.writeLong(38400); // Write all the bytes. We should have 38400 bytes (640 * 480 / 8) // However we need to invert the bits has the engine expects 1 for the background and 0 for the text (black) // but pbm uses 0 for white and 1 for black. for (int i = 0 ; i < 38400 ; ++i) { byte b = imgFile.readByte(); outputFile.writeByte(~b); } imgFile.close(); } void writeGermanStrings(File& outputFile) { // Write header and language outputFile.write("TEXT", 4); outputFile.write("de\0\0", 4); // Reserve the size for the block size, but we will write it at the end once we know what it is. uint32 blockSizePos = outputFile.pos(); uint32 blockSize = 0; outputFile.writeLong(blockSize); // Write all the strings const char **s = &gameText[0]; while (*s) { outputFile.writeString(*s); blockSize += strlen(*s) + 1; ++s; } // Now write the block size and then go back to the end of the file. outputFile.seek(blockSizePos, SEEK_SET); outputFile.writeLong(blockSize); outputFile.seek(0, SEEK_END); } void writeStrings(File& outputFile, const char* language) { char fileName[16]; sprintf(fileName, "strings-%s.po", language); PoMessageList* poList = parsePoFile(fileName); if (!poList) { printf("Cannot find strings file for language '%s'.\n", language); return; } // Write block header outputFile.write("TEXT", 4); // And write the language code on 4 bytes as well (padded with 0 if needed). int languageLength = strlen(language); for (int i = 0 ; i < 4 ; ++i) { if (i < languageLength) outputFile.writeByte(language[i]); else outputFile.writeByte(0); } // Reserve the size for the block size, but we will write it at the end once we know what it is. uint32 blockSizePos = outputFile.pos(); uint32 blockSize = 0; outputFile.writeLong(blockSize); // Write all the strings. // If a string is not translated we use the German one. const char **s = &gameText[0]; while (*s) { const char* translation = poList->findTranslation(*s); if (translation) { outputFile.writeString(translation); blockSize += strlen(translation) + 1; } else { outputFile.writeString(*s); blockSize += strlen(*s) + 1; } ++s; } delete poList; // Now write the block size and then go back to the end of the file. outputFile.seek(blockSizePos, SEEK_SET); outputFile.writeLong(blockSize); outputFile.seek(0, SEEK_END); } /** * Main method */ int main(int argc, char *argv[]) { File outputFile; if (!outputFile.open("supernova.dat", kFileWriteMode)) { printf("Cannot create file 'supernova.dat' in current directory.\n"); exit(0); } // The generated file is of the form: // 3 bytes: 'MSN' // 1 byte: version // -- data blocks // 4 bytes: header 'IMG1' and 'IMG2' for newspaper images (for file 1 and file 2 respectively), // 'TEXT' for strings // 4 bytes: language code ('en\0', 'de\0'- see common/language.cpp) // 4 bytes: block size n (uint32) // n bytes: data // --- // Header outputFile.write("MSN", 3); outputFile.writeByte(VERSION); // German strings writeGermanStrings(outputFile); // Other languages const char **l = &lang[0]; while(*l) { writeImage(outputFile, "img1", *l); writeImage(outputFile, "img2", *l); writeStrings(outputFile, *l); ++l; } outputFile.close(); return 0; }