// Copyright (C) 2012 Gaz Davidson // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h /*** This tool creates a .h file from a given input file by encoding it into a C string, allowing you to build your resources directly into your binaries, just like Irrlicht's built-in font. To distribute your app as a single executable file of minimal size: 1. Put all your resources into a single directory and add it to Irrlicht's filesystem as a folder through IFileSystem::addArchive. Develop and test your app as usual. 2. Open IrrCompileConfig.h and comment out all the options that your app does not use. This will reduce the size of the Irrlicht library considerably. * You should remove the D3D video drivers, because they rely on external DLLs. * You should keep either the TAR or ZIP archive loader, used in step 6. * If you remove the JPEG loader, you don't have to say you use JPEG code in your documentation. 3. Recompile Irrlicht as a static library, editing the IRR_STATIC_LIB line in IrrCompileConfig.h. The next time you compile your application it will take a while longer, but Irrlicht will be built into your binary. 4. TAR or ZIP your resource directory using your favourite archiving tool (ie 7zip). * If you chose ZIP but compiled without zlib, don't compress this archive or it won't open. 5. Run this tool to convert your resource file into a .h file, like so: FileToHeader res.zip > EmbeddedResources.h 6. Add the .h file to your project, create the embedded read file then mount as a ZIP or TAR archive instead of the folder, like so: io::IReadFile *f = io::createEmbeddedFile(device->getFileSystem(), "res.zip"); device->getFileSystem()->addFileArchive(f); archive->drop(); 7. Recompile your app. * If you use Microsoft's compiler, make sure your CRT (common run-time) is the static library version, otherwise you'll have a dependency on the CRT DLLs. Your binary should now be completely portable; you can distribute just the exe file. 8. Optional: Use UPX (upx.sf.net) to compress your binary. */ #include #include #include using namespace std; int main(int argc, char* argv[]) { if (argc < 2) { // print usage cerr << "You must to specify at least one input file" << endl; cerr << "usage: " << argv[0] << " [file2...]" << endl; cerr << "outputs a header file to stdout, so for example use"; return 1; } int i = 1; // write file header cout << "// File made by FileToHeader, part of the Irrlicht Engine" << endl << endl << "#ifndef _EMBEDDED_FILES_H_INCLUDED_" << endl << "#define _EMBEDDED_FILES_H_INCLUDED_" << endl << endl << "#include \"irrTypes.h\"" << endl << "#include \"IReadFile.h\"" << endl << "#include \"IFileSystem.h\"" << endl << endl << "namespace irr" << endl << "{" << endl << "namespace io" << endl << "{" << endl << endl << " const c8* EmbeddedFileData[] = " << endl << " {" << endl; // store sizes and file names stringstream sizes; stringstream names; sizes << "const u32 EmbeddedFileSizes[] = {"; names << "const c8* EmbeddedFileNames[] = {"; int fileCount = 0; // char to hex digit table, probably doesn't help for speed due to fstream. better than using sprintf though char hextable[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; while (i < argc) { // open and seek to end of file ifstream input; input.open(argv[i], ios::in | ios::binary | ios::ate); if (input.is_open()) { int size = input.tellg(); input.seekg(0, ios::beg); // read the file into RAM char *entireFile = new char[size]; input.read(entireFile, size); if (fileCount) { sizes << ", "; names << ", "; cout << "," << endl; } // save file size and name sizes << size; names << '"' << argv[i] << '"'; // write the file data cout << " \""; for (int count=0; count < size; ++count) { if (count && (count % 16) == 0) cout << "\"" << endl << " \""; cout << "\\x" << hextable[(entireFile[count] >> 4) & 0xF] << hextable[entireFile[count] & 0x0F]; } cout << "\""; delete [] entireFile; // input.close(); fileCount++; } else { cerr << "Failed to open file: " << argv[i] << endl; } ++i; } // close binary file list and write file metadata cout << endl << " , 0};" << endl << endl << " const u32 EmbeddedFileCount = " << fileCount << ";" << endl << " " << sizes.str() << "};" << endl << " " << names.str() << "};" << endl << endl; // write functions to create embedded IReadFiles cout << " IReadFile* createEmbeddedFile(IFileSystem *fs, u32 index)" << endl << " {" << endl << " if (EmbeddedFileCount < index)" << endl << " return 0;" << endl << endl << " return fs->createMemoryReadFile((void*)EmbeddedFileData[index], " << endl << " EmbeddedFileSizes[index], EmbeddedFileNames[index]);" << endl << " }" << endl << endl << " IReadFile* createEmbeddedFile(IFileSystem *fs, path filename)" << endl << " {" << endl << " for (u32 i=0; i < EmbeddedFileCount; ++i)" << endl << " if (filename == EmbeddedFileNames[i])" << endl << " return createEmbeddedFile(fs, i);" << endl << endl << " return 0;" << endl << " }" << endl << endl; // write footer cout << "} // namespace io" << endl << "} // namespace irr" << endl << endl << "#endif // _EMBEDDED_FILES_H_INCLUDED_" << endl; return 0; }