Exemple #1
0
/**
 *  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;
}
Exemple #2
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;
}
Exemple #4
0
/**
 *  Kopierfunktion von @p ArchivInfo.
 *
 *  @param[in] to     Zielposition
 *  @param[in] from   Quellposition
 *  @param[in] count  Anzahl
 *  @param[in] source Quelle
 *
 *  @author FloSoft
 */
void ArchivInfo::copy(size_t to, size_t from, size_t count, const ArchivInfo& source)
{
    if(to + count > size())
        data.resize(to + count);

    for(size_t f = from; f < from + count; ++to, ++f)
        setC(to, *source.get(f));
}
Exemple #5
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;
}
Exemple #6
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;
}
Exemple #7
0
void unpack(const string& directory, const ArchivInfo& lst, const ArchivItem_Palette* palette)
{
    CreateDirectoryA(directory.c_str(), NULL);

    for(unsigned int i = 0; i < lst.getCount(); ++i)
    {
        const ArchivItem* item = lst.get(i);

        bool changed = false;
        stringstream newfile;
        newfile << directory << "\\" << i << ".";

        if(!item)
        {
            /*newfile << "empty";

            FILE *n = fopen(newfile.str().c_str(), "wb");
            if(n)
                fclose(n);*/
            continue;
        }
        switch(item->getBobType())
        {
        case BOBTYPE_SOUND: // WAVs, MIDIs
        {
            unsigned short subtype = SOUNDTYPE_NONE;

            const ArchivItem_Sound* i = dynamic_cast<const ArchivItem_Sound*>(item);
            if(item)
                subtype = i->getType();

            switch(subtype)
            {
            case SOUNDTYPE_NONE:
            {
            } break;
            case SOUNDTYPE_MIDI: // MIDI
            {
            } break;
            case SOUNDTYPE_WAVE: // WAV
            {
                newfile << "wav";

                cout << "extracting " << newfile.str() << ": ";

                const ArchivItem_Sound_Wave* wave = dynamic_cast<const ArchivItem_Sound_Wave*>(item);
                FILE* fwave = fopen(newfile.str().c_str(), "wb");
                if(fwave && wave && wave->write(fwave, false) == 0)
                {
                    fclose(fwave);
                    cout << "done" << endl;
                }
                else
                    cout << "failed" << endl;
            }
            break;
            case SOUNDTYPE_XMIDI: // XMIDI
            {
            } break;
            case SOUNDTYPE_OTHER: // Andere
            {
            } break;
            }
        }
        break;
        case BOBTYPE_FONT: // Font
        {
            cout << "extracting " << newfile.str() << ": ";

            const ArchivItem_Font* font = dynamic_cast<const ArchivItem_Font*>(item);

            newfile << "dx" << (short)font->getDx() << ".dy" << (short)font->getDy() << ".";
            newfile << "fon";

            unpack(newfile.str(), *font, palette);
        }
        break;
        case BOBTYPE_PALETTE: // Palette
        {
            ArchivInfo items;
            items.pushC(item);
            newfile << "bbm";

            cout << "extracting " << newfile.str() << ": ";

            if(WriteBBM(newfile.str().c_str(), &items) != 0)
                cout << "failed" << endl;
            else
                cout << "done" << endl;
        }
        break;
        case BOBTYPE_BOB: // Bobfiles
        {
            const ArchivItem_Bob* bob = dynamic_cast<const ArchivItem_Bob*>(item);
            unpack(directory, bob, palette);
        }
        break;
        case BOBTYPE_MAP: // Mapfiles
        {
        } break;
        case BOBTYPE_TEXT: // Text
        {
        } break;
        case BOBTYPE_RAW: // Raw-Item
        {
        } break;
        case BOBTYPE_MAP_HEADER: // Mapheader-Item
        {
        } break;
        case BOBTYPE_BITMAP_RLE: // RLE komprimiertes Bitmap
        {
            if(!changed)
            {
                newfile << "rle.";
                changed = true;
            }
        }
        case BOBTYPE_BITMAP_PLAYER: // Bitmap mit spezifischer Spielerfarbe
        {
            if(!changed)
            {
                newfile << "player.";
                changed = true;
            }
        }
        case BOBTYPE_BITMAP_SHADOW: // Schatten
        {
            if(!changed)
            {
                newfile << "shadow.";
                changed = true;
            }
        }
        case BOBTYPE_BITMAP_RAW: // unkomprimiertes Bitmap
        {
            const ArchivItem_Bitmap* bitmap = dynamic_cast<const ArchivItem_Bitmap*>(item);
            ArchivInfo items;
            items.pushC(bitmap);
            newfile << "nx" << bitmap->getNx() << ".ny" << bitmap->getNy() << ".";
            newfile << "bmp";

            cout << "extracting " << newfile.str() << ": ";

            if(WriteBMP(newfile.str().c_str(), palette, &items) != 0)
                cout << "failed" << endl;
            else
                cout << "done" << endl;
        }
        break;
        }
    }
}