Exemplo n.º 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;
}
bool ArchivItem_BitmapBase::checkPalette(const ArchivItem_Palette& palette) const
{
    if(format_ == FORMAT_PALETTED)
        return true;
    for(unsigned y = 0; y < height_; y++)
    {
        for(unsigned x = 0; x < width_; x++)
        {
            ColorARGB clr = getARGBPixel(x, y);
            uint8_t dummyIdx;
            if(clr.getAlpha() != 0 && !palette.lookup(clr, dummyIdx))
                return false;
        }
    }
    return true;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
/**
 *  schreibt ein ArchivInfo in eine BBM-File.
 *
 *  @param[in] file    Dateiname der BBM-File
 *  @param[in] items   ArchivInfo-Struktur, von welcher gelesen wird
 *
 *  @return Null bei Erfolg, ein Wert ungleich Null bei Fehler
 *
 *  @author FloSoft
 */
int libsiedler2::loader::WriteBBM(const char* file, const ArchivInfo* items)
{
    FILE* bbm;
    char header[5] = "FORM", pbm[5] = "PBM ", cmap[5] = "CMAP";
    unsigned long count = 0;
    unsigned int length = 0;

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

    // Anzahl Paletten in ArchivInfo suchen
    for(unsigned long i = 0; i < items->getCount(); ++i)
    {
        if(!items->get(i))
            continue;
        if(items->get(i)->getBobType() == BOBTYPE_PALETTE)
            ++count;
    }

    // Datei zum schreiben öffnen
    bbm = fopen(file, "wb");

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

    // Header schreiben
    if(libendian::le_write_c(header, 4, bbm) != 4)
        return 3;

    // Länge schreiben
    length = 4 + count * (256 * 3 + 8);
    if(libendian::le_write_ui(length, bbm) != 0)
        return 4;

    // Typ schreiben
    if(libendian::le_write_c(pbm, 4, bbm) != 4)
        return 5;

    for(unsigned long i = 0; i < items->getCount(); ++i)
    {
        ArchivItem_Palette* palette = (ArchivItem_Palette*)items->get(i);
        if(palette->getBobType() == BOBTYPE_PALETTE)
        {
            // Chunk schreiben
            if(libendian::be_write_c(cmap, 4, bbm) != 4)
                return 6;

            // Länge schreiben
            length = 256 * 3;
            if(libendian::be_write_ui(length, bbm) != 0)
                return 7;

            // Farbpalette zuweisen
            unsigned char colors[256][3];
            for(unsigned int k = 0; k < 256; ++k)
                palette->get(k, &colors[k][0], &colors[k][1], &colors[k][2]);

            // Farbpalette schreiben
            if(libendian::le_write_uc(colors[0], 256 * 3, bbm) != 256 * 3)
                return 8;
        }
    }

    // Datei schliessen
    fclose(bbm);

    // alles ok
    return 0;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
/**
 *  lädt eine LBM-File in ein ArchivInfo.
 *
 *  @param[in]  file    Dateiname der LBM-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::LoadLBM(const char* file, ArchivInfo* items)
{
    FILE* lbm;
    char header[4], pbm[4];
    unsigned int chunk;
    unsigned int length;
    long size;

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

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

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

    fseek(lbm, 0, SEEK_END);
    size = ftell(lbm);
    fseek(lbm, 0, SEEK_SET);

    // Header einlesen
    if(libendian::le_read_c(header, 4, lbm) != 4)
        return 3;

    // ist es eine LBM-File? (Header "FORM")
    if(strncmp(header, "FORM", 4) != 0)
        return 4;

    // Länge einlesen
    if(libendian::le_read_ui(&length, lbm) != 0)
        return 5;

    // Typ einlesen
    if(libendian::le_read_c(pbm, 4, lbm) != 4)
        return 6;

    // ist es eine LBM-File? (Typ "PBM ")
    if(strncmp(pbm, "PBM ", 4) != 0)
        return 7;

    baseArchivItem_Bitmap* bitmap = dynamic_cast<baseArchivItem_Bitmap*>((*allocator)(BOBTYPE_BITMAP_RAW, 0, NULL));
    bitmap->setFormat(FORMAT_PALETTED);
    ArchivItem_Palette* palette = NULL;
    unsigned short compression;
    unsigned short width, height;
    unsigned short depth;

    // lbm has normally 2 items, palette (1) and image (0),
    // i'll change position of those items to be compatible with LoadBMP
    items->alloc(2);

    // Chunks einlesen
    while(!feof(lbm) && ftell(lbm) < size)
    {
        // Chunk-Typ einlesen
        if(libendian::be_read_ui(&chunk, lbm) != 0)
            return 8;

        switch(chunk)
        {
            case 0x424D4844: // "BHMD"
            {
                // Länge einlesen
                if(libendian::be_read_ui(&length, lbm) != 0)
                    return 9;

                // Bei ungerader Zahl aufrunden
                if(length & 1)
                    ++length;

                if(libendian::be_read_us(&width, lbm) != 0)
                    return 10;

                if(libendian::be_read_us(&height, lbm) != 0)
                    return 11;

                bitmap->setWidth(width);
                bitmap->setHeight(height);

                // Unbekannte Daten ( 4 Byte ) berspringen
                fseek(lbm, 4, SEEK_CUR);

                // Farbtiefe einlesen
                if(libendian::le_read_us(&depth, lbm) != 0)
                    return 12;

                // Nur 256 Farben und nicht mehr!
                if(depth != 8)
                    return 13;

                // Kompressionflag lesen
                if(libendian::le_read_us(&compression, lbm) != 0)
                    return 14;

                // Keine bekannte Kompressionsart?
                if(compression > 1)
                    return 15;

                length -= 12;

                // Rest überspringen
                fseek(lbm, length, SEEK_CUR);
            } break;
            case 0x434D4150: // "CMAP"
            {
                // Länge einlesen
                if(libendian::be_read_ui(&length, lbm) != 0)
                    return 16;

                // Bei ungerader Zahl aufrunden
                if(length & 1)
                    ++length;

                // Ist Länge wirklich so groß wie Farbtabelle?
                if(length != 256 * 3)
                    return 17;

                // Daten von Item auswerten
                palette = (ArchivItem_Palette*)(*allocator)(BOBTYPE_PALETTE, 0, NULL);
                items->set(1, palette);

                // Farbpalette lesen
                unsigned char colors[256][3];
                if(libendian::le_read_uc(colors[0], 256 * 3, lbm) != 256 * 3)
                    return 18;

                // Farbpalette zuweisen
                for(unsigned int k = 0; k < 256; ++k)
                    palette->set(k, colors[k][0], colors[k][1], colors[k][2]);
            } break;
            case 0x424F4459: // "BODY"
            {
                // Länge einlesen
                if(libendian::be_read_ui(&length, lbm) != 0)
                    return 19;

                // Bei ungerader Zahl aufrunden
                if(length & 1)
                    ++length;

                // haben wir eine Palette erhalten?
                if(palette == NULL)
                    return 20;

                bitmap->setPalette(palette);
                bitmap->tex_alloc();

                switch(compression)
                {
                    case 0: // unkomprimiert
                    {
                        /*assert(false);*/
                    } break;
                    case 1: // komprimiert (RLE?)
                    {
                        // Welcher Pixel ist dran?
                        unsigned short x = 0, y = 0;
                        unsigned char ctype;
                        unsigned char color;

                        // Solange einlesen, bis Block zuende bzw. Datei zuende ist
                        while(length >= 0 && !feof(lbm) && ftell(lbm) < size)
                        {
                            // Typ lesen
                            if(libendian::le_read_uc(&ctype, 1, lbm) != 1)
                                return 21;
                            --length;
                            if(length == 0)
                                continue;

                            if(ctype < 128) // unkomprimierte Pixel
                            {
                                unsigned short count = ctype + 1;

                                for(unsigned short i = 0; i < count; ++i)
                                {
                                    // Farbe auslesen
                                    if(libendian::le_read_uc(&color, 1, lbm) != 1)
                                        return 22;
                                    --length;

                                    bitmap->tex_setPixel(x++, y, color, palette);
                                    if(x >= width)
                                    {
                                        ++y;
                                        x = 0;
                                    }
                                }
                            }
                            else // komprimierte Pixel
                            {
                                unsigned short count = 0xFF - ctype + 2;

                                // Farbe auslesen
                                if(libendian::le_read_uc(&color, 1, lbm) != 1)
                                    return 23;
                                --length;

                                for(unsigned short i = 0; i < count; ++i)
                                {
                                    bitmap->tex_setPixel(x++, y, color, palette);
                                    if(x >= width)
                                    {
                                        ++y;
                                        x = 0;
                                    }
                                }
                            }
                        }
                    } break;
                }
                items->set(0, bitmap);
            } break;
            default:
            {
                // Länge einlesen
                if(libendian::be_read_ui(&length, lbm) != 0)
                    return 24;

                // Bei ungerader Zahl aufrunden
                if(length & 1)
                    ++length;

                // Rest überspringen
                fseek(lbm, length, SEEK_CUR);
            } break;
        }
    }

    if(items->getCount() == 0)
        return 25;

    // Datei schliessen
    fclose(lbm);

    return 0;
}