/** * lädt eine ACT-File in ein ArchivInfo. * * @param[in] file Dateiname der ACT-File * @param[out] items ArchivInfo-Struktur, welche gefüllt wird * * @return Null bei Erfolg, ein Wert ungleich Null bei Fehler * * @author FloSoft * @author OLiver */ int libsiedler2::loader::LoadACT(const std::string& file, ArchivInfo& items) { long size; if(file.empty()) return 1; // Datei zum lesen öffnen boost::scoped_ptr<FILE> act(fopen(file.c_str(), "rb")); // hat das geklappt? if(!act) return 2; fseek(act.get(), 0, SEEK_END); size = ftell(act.get()); fseek(act.get(), 0, SEEK_SET); // sind es 256*3 Bytes, also somit 8bit-RGB? if(size != 256*3) return 3; ArchivItem_Palette* palette = (ArchivItem_Palette*)getAllocator().create(BOBTYPE_PALETTE); if(palette->load(act.get(), false) != 0){ delete palette; return 4; } // einlesen items.clear(); items.push(palette); // Alles OK return 0; }
/** * lädt eine Sounddatei in ein ArchivInfo. (midi, xmidi, wave) * * @param[in] file Dateiname der Sounddatei * @param[out] items ArchivInfo-Struktur, welche gefüllt wird * * @return Null bei Erfolg, ein Wert ungleich Null bei Fehler */ int libsiedler2::loader::LoadSND(const std::string& file, ArchivInfo& items) { if(file.empty()) return 1; // Datei zum lesen öffnen boost::iostreams::mapped_file_source mmapFile; try{ mmapFile.open(bfs::path(file)); } catch(std::exception& e){ std::cerr << "Could not open '" << file << "': " << e.what() << std::endl; return 2; } typedef boost::iostreams::stream<boost::iostreams::mapped_file_source> MMStream; MMStream snd(mmapFile); // hat das geklappt? if(!snd) return 2; baseArchivItem_Sound* sound = baseArchivItem_Sound::findSubType(snd); if(!sound) return 3; size_t size = getIStreamSize(snd); if(sound->load(snd, static_cast<unsigned>(size)) != 0) return 4; items.clear(); items.push(sound); return 0; }
/** * lädt eine BOB-File in ein ArchivInfo. * * @param[in] file Dateiname der BOB-File * @param[out] items ArchivInfo-Struktur, welche gefüllt wird * * @return Null bei Erfolg, ein Wert ungleich Null bei Fehler */ int libsiedler2::loader::LoadBOB(const std::string& file, const ArchivItem_Palette* palette, ArchivInfo& items) { unsigned int header; if(file.empty() || palette == NULL) return 1; // Datei zum lesen öffnen boost::iostreams::mapped_file_source mmapFile; try { mmapFile.open(bfs::path(file)); } catch(std::exception& e) { std::cerr << "Could not open '" << file << "': " << e.what() << std::endl; return 2; } typedef boost::iostreams::stream<boost::iostreams::mapped_file_source> MMStream; MMStream mmapStream(mmapFile); libendian::EndianIStream<false, MMStream& > bob(mmapStream); // hat das geklappt? if(!bob) return 2; // Header einlesen bob >> header; // ist es eine BOB-File? (Header 0xF601F501) if(header != 0x01F501F6) return 4; ArchivItem_Bob* item = dynamic_cast<ArchivItem_Bob*>(getAllocator().create(BOBTYPE_BOB)); boost::filesystem::path filePath(file); if(filePath.has_filename()) item->setName(filePath.filename().string()); if(item->load(bob.getStream(), palette) != 0) { delete item; return 5; } // Item alloziieren und zuweisen items.clear(); items.push(item); return 0; }
/** * lädt eine GER/ENG-File in ein ArchivInfo. * * @param[in] file Dateiname der GER/ENG-File * @param[out] items ArchivInfo-Struktur, welche gefüllt wird * @param[in] conversion Soll ggf. OEM-Charset in ANSI umgewandelt werden? * * @return Null bei Erfolg, ein Wert ungleich Null bei Fehler * * @bug Keine Erkennung ob Plain-Text oder "Irgendwas". */ int libsiedler2::loader::LoadTXT(const std::string& file, ArchivInfo& items, bool conversion) { short header; if(file.empty()) return 1; // Datei zum lesen öffnen boost::iostreams::mapped_file_source mmapFile; try{ mmapFile.open(bfs::path(file)); }catch(std::exception& e){ std::cerr << "Could not open '" << file << "': " << e.what() << std::endl; return 2; } typedef boost::iostreams::stream<boost::iostreams::mapped_file_source> MMStream; MMStream mmapStream(mmapFile); libendian::EndianIStream<false, MMStream& > fs(mmapStream); // hat das geklappt? if(!fs) return 2; size_t length = getIStreamSize(fs.getStream()); assert(length < std::numeric_limits<unsigned>::max()); // Header einlesen fs >> header; items.clear(); // ist es eine TXT-File? (Header 0xE7FD) if( header != (short)0xFDE7 ) { // den Header zurückspringen fs.setPositionRel(-2); ArchivItem_Text* item = (ArchivItem_Text*)getAllocator().create(BOBTYPE_TEXT); item->load(fs.getStream(), conversion); items.push(item); } else { // "archiviert" unsigned short count, unknown; unsigned int size; fs >> count; fs >> unknown; fs >> size; if(size == 0) size = static_cast<unsigned>(length); else size += 10; std::vector<unsigned> starts(count); // Starts einlesen for(unsigned short x = 0; x < count; ++x) { uint32_t s; fs >> s; if(s != 0) starts[x] = s + 10; } // Daten einlesen, zwecks Längenbestimmung size_t pos = fs.getPosition(); size_t rest = size - pos; std::vector<char> buffer(rest + 1); buffer.resize(rest); fs >> buffer; buffer.push_back(0); for(unsigned short x = 0; x < count; ++x) { unsigned i = starts[x]; if(i != 0) { // An Start springen fs.setPosition(i); // einlesen ArchivItem_Text* item = (ArchivItem_Text*)getAllocator().create(BOBTYPE_TEXT); assert(i >= pos); item->load(fs.getStream(), conversion, (unsigned int)strlen(&buffer[i - pos]) + 1); items.push(item); } else items.push(NULL); } } // alles ok return 0; }
/** * lädt eine BBM-File in ein ArchivInfo. * * @param[in] file Dateiname der BBM-File * @param[out] items ArchivInfo-Struktur, welche gefüllt wird * * @return Null bei Erfolg, ein Wert ungleich Null bei Fehler * * @author FloSoft * @author OLiver */ int libsiedler2::loader::LoadBBM(const std::string& file, ArchivInfo& items) { char header[4], pbm[4]; unsigned int chunk; unsigned int i = 0; if(file.empty()) return 1; // Datei zum lesen öffnen boost::scoped_ptr<FILE> bbm(fopen(file.c_str(), "rb")); // hat das geklappt? if(!bbm) return 2; long size = getFileLength(bbm.get()); // Header einlesen if(libendian::le_read_c(header, 4, bbm.get()) != 4) return 3; // ist es eine BBM-File? (Header "FORM") if(strncmp(header, "FORM", 4) != 0) return 4; // Länge einlesen unsigned length; if(libendian::le_read_ui(&length, bbm.get()) != 0) return 5; // Typ einlesen if(libendian::le_read_c(pbm, 4, bbm.get()) != 4) return 6; // ist es eine BBM-File? (Typ "PBM ") if(strncmp(pbm, "PBM ", 4) != 0) return 7; // Chunks einlesen while(!feof(bbm.get()) && ftell(bbm.get()) < size) { // Chunk-Typ einlesen if(libendian::be_read_ui(&chunk, bbm.get()) != 0) return 8; switch(chunk) { case 0x434D4150: // "CMAP" { // Länge einlesen if(libendian::be_read_ui(&length, bbm.get()) != 0) return 9; // Bei ungerader Zahl aufrunden if(length & 1) ++length; // Ist Länge wirklich so groß wie Farbtabelle? if(length != 256 * 3) return 10; // Daten von Item auswerten ArchivItem_Palette* palette = (ArchivItem_Palette*)getAllocator().create(BOBTYPE_PALETTE); items.push(palette); size_t namePos = file.find_last_of('/'); if(namePos != std::string::npos) { std::stringstream rName; rName << file.substr(namePos+1) << "(" << i << ")"; palette->setName(rName.str()); } // Farbpalette lesen Color colors[256]; if(libendian::le_read_uc(&colors[0].r, sizeof(colors), bbm.get()) != sizeof(colors)) return 10; // Farbpalette zuweisen for(unsigned int k = 0; k < 256; ++k) palette->set(k, colors[k]); ++i; } break; default: { // Länge einlesen if(libendian::be_read_ui(&length, bbm.get()) != 0) return 12; // Bei ungerader Zahl aufrunden if(length & 1) ++length; if(length > 0) { boost::scoped_array<unsigned char> buffer(new unsigned char[length]); // überspringen if(libendian::le_read_uc(buffer.get(), length, bbm.get()) != (int)length) return 13; } } break; } } if(items.size() == 0) return 14; // alles ok return 0; }