Ejemplo n.º 1
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".
 *
 *  @author FloSoft
 */
int libsiedler2::loader::LoadTXT(const char* file, ArchivInfo* items, bool conversion)
{
    FILE* txt;
    short header;
    long length;

    if(file == NULL || items == NULL)
        return 1;

    // Datei zum lesen öffnen
    txt = fopen(file, "rb");

    // hat das geklappt?
    if(txt == NULL)
        return 2;

    // Länge bestimmen
    fseek(txt, 0, SEEK_END);
    length = ftell(txt);
    fseek(txt, 0, SEEK_SET);

    // Header einlesen
    if(libendian::be_read_s(&header, txt) != 0)
        return 3;

    // ist es eine TXT-File? (Header 0xE7FD)
    if( header != (short)0xE7FD )
    {
        // den Header zurückspringen
        fseek(txt, -2, SEEK_CUR);

        // Plain-Text
        items->alloc(1);

        ArchivItem_Text* item = (ArchivItem_Text*)(*allocator)(BOBTYPE_TEXT, 0, NULL);
        item->load(txt, conversion);

        // Item erzeugen
        items->set(0, item);
    }
    else
    {
        // "archiviert"
        unsigned short count, unknown;
        unsigned int size;

        if(libendian::le_read_us(&count, txt) != 0)
            return 4;

        if(libendian::le_read_us(&unknown, txt) != 0)
            return 5;

        if(libendian::le_read_ui(&size, txt) != 0)
            return 6;

        if(size == 0)
            size = length;
        else
            size += 10;

        // Anzahl alloziieren
        items->alloc(count);

        int* starts = new int[count];
        memset(starts, 0, sizeof(int)*count);

        // Starts einlesen
        for(unsigned short x = 0; x < count; ++x)
        {
            int s;
            if(libendian::le_read_i(&s, txt) != 0)
                return 7;

            if(s != 0)
                starts[x] = s + 10;
        }

        // Daten einlesen, zwecks Längenbestimmung
        unsigned int pos = ftell(txt);
        unsigned int rest = size - pos;
        char* buffer = new char[rest + 1];
        if(libendian::le_read_c(buffer, rest, txt) != (int)rest)
            return 8;

        for(unsigned short x = 0; x < count; ++x)
        {
            int i = starts[x];

            if(i != 0)
            {
                // An Start springen
                fseek(txt, i, SEEK_SET);

                // einlesen
                ArchivItem_Text* item = (ArchivItem_Text*)(*allocator)(BOBTYPE_TEXT, 0, NULL);
                item->load(txt, conversion, (unsigned int)strlen(&buffer[i - pos]));

                items->set(x, item);
            }
            else
                items->set(x, (ArchivItem_Text*)(*allocator)(BOBTYPE_TEXT, 0, NULL));
        }
        delete[] buffer;
        delete[] starts;
    }

    // alles ok
    return 0;
}
Ejemplo n.º 2
0
/**
 *  lädt eine spezifizierten Bobtype aus einer Datei in ein ArchivItem.
 *
 *  @param[in]  bobtype Typ des Items
 *  @param[in]  file    Filehandle auf die auszulesende Datei
 *  @param[in]  palette Grundpalette
 *  @param[out] item    ArchivItem-Struktur, welche gefüllt wird
 *
 *  @return Null bei Erfolg, ein Wert ungleich Null bei Fehler
 */
int libsiedler2::loader::LoadType(BOBTYPES bobtype, std::istream& file, const ArchivItem_Palette* palette, ArchivItem*& item)
{
    if(!file)
        return 1;

    try{
        switch(bobtype)
        {
            case BOBTYPE_SOUND: // WAVs, MIDIs
            {
                libendian::LittleEndianIStreamRef fs(file);
                unsigned int length;
                fs >> length;

                baseArchivItem_Sound* nitem = baseArchivItem_Sound::findSubType(file);
                if(!nitem || nitem->load(file, length) != 0){
                    delete nitem;
                    return 5;
                }
                item = nitem;
            } break;
            case BOBTYPE_BITMAP_RLE: // RLE komprimiertes Bitmap
            {
                baseArchivItem_Bitmap_RLE* nitem = dynamic_cast<baseArchivItem_Bitmap_RLE*>(getAllocator().create(BOBTYPE_BITMAP_RLE));
                if(nitem->load(file, palette) != 0){
                    delete nitem;
                    return 6;
                }
                item = nitem;
            } break;
            case BOBTYPE_FONT: // Font
            {
                ArchivItem_Font* nitem = dynamic_cast<ArchivItem_Font*>(getAllocator().create(BOBTYPE_FONT));
                if(nitem->load(file, palette) != 0){
                    delete nitem;
                    return 7;
                }
                item = nitem;
            } break;
            case BOBTYPE_BITMAP_PLAYER: // Bitmap mit spezifischer Spielerfarbe
            {
                ArchivItem_Bitmap_Player* nitem = dynamic_cast<ArchivItem_Bitmap_Player*>(getAllocator().create(BOBTYPE_BITMAP_PLAYER));
                if(nitem->load(file, palette) != 0){
                    delete nitem;
                    return 8;
                }
                item = nitem;
            } break;
            case BOBTYPE_PALETTE: // Palette
            {
                ArchivItem_Palette* nitem =  dynamic_cast<ArchivItem_Palette*>(getAllocator().create(BOBTYPE_PALETTE));
                if(nitem->load(file) != 0){
                    delete nitem;
                    return 9;
                }
                item = nitem;
            } break;
            case BOBTYPE_BOB: // Bobfile
            {
                ArchivItem_Bob* nitem = dynamic_cast<ArchivItem_Bob*>(getAllocator().create(BOBTYPE_BOB));
                if(nitem->load(file, palette) != 0){
                    delete nitem;
                    return 10;
                }
                item = nitem;
            } break;
            case BOBTYPE_BITMAP_SHADOW: // Schatten
            {
                baseArchivItem_Bitmap_Shadow* nitem = dynamic_cast<baseArchivItem_Bitmap_Shadow*>(getAllocator().create(BOBTYPE_BITMAP_SHADOW));
                if(nitem->load(file, palette) != 0){
                    delete nitem;
                    return 11;
                }
                item = nitem;
            } break;
            case BOBTYPE_MAP: // Mapfile
            {
                ArchivItem_Map* nitem = dynamic_cast<ArchivItem_Map*>(getAllocator().create(BOBTYPE_MAP));
                if(nitem->load(file, false) != 0){
                    delete nitem;
                    return 12;
                }
                item = nitem;
            } break;
            case BOBTYPE_TEXT: // Textfile
            {
                ArchivItem_Text* nitem =  dynamic_cast<ArchivItem_Text*>(getAllocator().create(BOBTYPE_TEXT));
                if(nitem->load(file) != 0){
                    delete nitem;
                    return 13;
                }
                item = nitem;
            } break;
            case BOBTYPE_BITMAP_RAW: // unkomprimiertes Bitmap
            {
                baseArchivItem_Bitmap_Raw* nitem = dynamic_cast<baseArchivItem_Bitmap_Raw*>(getAllocator().create(BOBTYPE_BITMAP_RAW));
                if(nitem->load(file, palette) != 0){
                    delete nitem;
                    return 14;
                }
                item = nitem;
            } break;
            case BOBTYPE_NONE:
                item = NULL;
                break;
            default:
                item = NULL;
                return 42;
        }

        if(item != NULL)
            item->setBobType(bobtype);
    }catch(std::runtime_error&){
        // Mostly error on reading (e.g. unexpected end of file)
        return 999;
    }

    return 0;
}
Ejemplo n.º 3
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;
}