virtual std::string initialstate()
		{
			return STRING_WITH_NULLS(
				"\x11SubZero Game File" "\x00\x00\x00\x00" "\x02\x00\x03\x00" "\x00\x00"
				"\x01"
			)
			+ makePalette()
			+ makeTileFlags()
			+ std::string(10, '\0')
			// Actors
			+ STRING_WITH_NULLS(
				"\x01\x00"
				"\x01" "\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
			)
			+ std::string(112, '\0')
			// BG/FG
			+ STRING_WITH_NULLS(
				"\x04\x00" "\x04\x00"
				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"

				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"
			);
		}
		void addTests()
		{
			this->test_map2d::addTests();

			// c00: Initial state
			this->isInstance(MapType::DefinitelyYes, this->initialstate());

			// c01: Too short
			this->isInstance(MapType::DefinitelyNo, STRING_WITH_NULLS(
				"\x11SubZero Game File"
			));

			// c02: Bad signature
			this->isInstance(MapType::DefinitelyNo, STRING_WITH_NULLS(
				"\x11SubZero Lame File" "\x00\x00\x00\x00" "\x02\x00\x03\x00" "\x00\x00"
				"\x00"
			)
			+ makePalette()
			+ makeTileFlags()
			+ std::string(10, '\0')
			+ STRING_WITH_NULLS(
				"\x01\x00"
				"\x01" "\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
			)
			+ std::string(112, '\0')
			+ STRING_WITH_NULLS(
				"\x04\x00" "\x04\x00"
				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"

				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"
			));

			// c03: Palette out of range
			this->isInstance(MapType::DefinitelyNo, STRING_WITH_NULLS(
				"\x11SubZero Game File" "\x00\x00\x00\x00" "\x02\x00\x03\x00" "\x00\x00"
				"\x00"
				"\x41\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
			)
			+ std::string(768 - 16, '\0')
			+ makeTileFlags()
			+ STRING_WITH_NULLS(
				"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
				"\x01\x00"
				"\x01" "\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
			)
			+ std::string(112, '\0')
			+ STRING_WITH_NULLS(
				"\x04\x00" "\x04\x00"
				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"

				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"
			));

			// c04: Flags out of range
			this->isInstance(MapType::DefinitelyNo, STRING_WITH_NULLS(
				"\x11SubZero Game File" "\x00\x00\x00\x00" "\x02\x00\x03\x00" "\x00\x00"
				"\x00"
			)
			+ makePalette()
			+ STRING_WITH_NULLS(
				"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
			)
			+ std::string(256 - 16, '\0')
			+ STRING_WITH_NULLS(
				"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
				"\x01\x00"
				"\x01" "\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
			)
			+ std::string(112, '\0')
			+ STRING_WITH_NULLS(
				"\x04\x00" "\x04\x00"
				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"

				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"
			));

			// c05: Actor data runs past EOF
			this->isInstance(MapType::DefinitelyNo, STRING_WITH_NULLS(
				"\x11SubZero Game File" "\x00\x00\x00\x00" "\x02\x00\x03\x00" "\x00\x00"
				"\x00"
			)
			+ makePalette()
			+ makeTileFlags()
			+ std::string(10, '\0')
			+ STRING_WITH_NULLS(
				"\x00\x20"
				"\x01" "\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
			)
			+ std::string(112, '\0')
			+ STRING_WITH_NULLS(
				"\x04\x00" "\x04\x00"
				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"

				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"
			));

			std::string tooShort = STRING_WITH_NULLS(
				"\x11SubZero Game File" "\x00\x00\x00\x00" "\x02\x00\x03\x00" "\x00\x00"
				"\x00"
			)
			+ makePalette()
			+ makeTileFlags()
			+ std::string(10, '\0')
			+ STRING_WITH_NULLS(
				"\x01\x00"
				"\x01" "\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
			)
			+ std::string(112, '\0')
			+ STRING_WITH_NULLS(
				"\x04\x00" "\x04\x00"
				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"

				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f"
			);

			// c06a: BG or FG layer cut short
			this->isInstance(MapType::DefinitelyNo, tooShort);

			// c06b: Prev test plus one byte works
			this->isInstance(MapType::DefinitelyYes, tooShort + std::string(1, '\0'));

			// Attribute 00: Parallax
			this->changeAttribute(0, 0, STRING_WITH_NULLS(
				"\x11SubZero Game File" "\x00\x00\x00\x00" "\x02\x00\x03\x00" "\x00\x00"
				"\x00"
			)
			+ makePalette()
			+ makeTileFlags()
			+ std::string(10, '\0')
			// Actors
			+ STRING_WITH_NULLS(
				"\x01\x00"
				"\x01" "\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
			)
			+ std::string(112, '\0')
			// BG/FG
			+ STRING_WITH_NULLS(
				"\x04\x00" "\x04\x00"
				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"

				"\x01\x02\x03\x04"
				"\x05\x06\x07\x08"
				"\x09\x0a\x0b\x0c"
				"\x0d\x0e\x0f\x00"
			));
		}
Example #3
0
static void 
addEntryToIcon(MS_Ico       const MSIconData, 
               const char * const xorPpmFname,
               const char * const andPgmFname,
               bool         const trueTransparent) {

    IC_Entry entry;
    FILE * xorfile;
    pixel ** xorPPMarray;
    gray ** andPGMarray;
    ICON_bmp xorBitmap;
    ICON_bmp andBitmap;
    int rows, cols;
    int bpp, colors;
    int entry_cols;
    IC_Palette palette;
    colorhash_table  xorCht;
    colorhash_table  andCht; 
    const char * error;
   
    pixval xorMaxval;
    gray andMaxval;

    MALLOCVAR_NOFAIL(entry);

   /*
    * Read the xor PPM.
    */
    xorfile = pm_openr(xorPpmFname);
    xorPPMarray = ppm_readppm(xorfile, &cols, &rows, &xorMaxval);
    pm_close(xorfile);
    /*
    * Since the entry uses 1 byte to hold the width and height of the icon, the
    * image can't be more than 256 x 256.
    */
    if (rows > 255 || cols > 255) {
        pm_error("Max size for a icon is 255 x 255 (1 byte fields).  "
                 "%s is %d x %d", xorPpmFname, cols, rows);
    }
   
    if (verbose) pm_message("read PPM: %dw x %dh, maxval = %d", 
                            cols, rows, xorMaxval);

    makePalette(xorPPMarray, cols, rows, xorMaxval, 
                &palette, &xorCht, &colors, &error);

    if (error)
        pm_error("Unable to make palette for '%s'.  %s", xorPpmFname, error);
   /*
    * All the icons I found seemed to pad the palette to the max entries
    * for that bitdepth.
    * 
    * The spec indicates this isn't neccessary, but I'll follow this behaviour
    * just in case.
    */
    if (colors < 3) {
        bpp = 1;
        entry_cols = 2;
    } else if (colors < 17) {
        bpp = 4;
        entry_cols = 16;
    } else {
        bpp = 8;
        entry_cols = 256;
    }

    getOrFakeAndMap(andPgmFname, cols, rows,
                    &andPGMarray, &andMaxval, &andCht, &error);
    if (error)
        pm_error("Error in and map for '%s'.  %s", xorPpmFname, error);

    if (andPGMarray && trueTransparent)
        blackenTransparentAreas(xorPPMarray, cols, rows, 
                                andPGMarray, andMaxval);

    xorBitmap = createBitmap(bpp, xorPPMarray, cols, rows, xorCht);
    andBitmap = createAndBitmap(andPGMarray, cols, rows, andMaxval);
    /*
     * Fill in the entry data fields.
    */
    entry->width         = cols;
    entry->height        = rows;
    entry->color_count   = entry_cols;
    entry->reserved      = 0;
    entry->planes        = 1;
    /* 
    * all the icons I looked at ignored this value...
    */
    entry->bitcount      = bpp;
    entry->ih            = createInfoHeader(entry, xorBitmap, andBitmap);
    entry->colors        = palette->colors;
    overflow2(4, entry->color_count);
    overflow_add(xorBitmap->size, andBitmap->size);
    overflow_add(xorBitmap->size + andBitmap->size, 40);
    overflow_add(xorBitmap->size + andBitmap->size + 40, 4 * entry->color_count);
    entry->size_in_bytes = 
        xorBitmap->size + andBitmap->size + 40 + (4 * entry->color_count);
    if (verbose) 
        pm_message("entry->size_in_bytes = %d + %d + %d = %d",
                   xorBitmap->size ,andBitmap->size, 
                   40, entry->size_in_bytes );
    /*
    * We don't know the offset ATM, set to 0 for now.
    * Have to calculate this at the end.
    */
    entry->file_offset   = 0;
    entry->xorBitmapOut  = xorBitmap->data;
    entry->andBitmapOut  = andBitmap->data;
    entry->xBytesXor     = xorBitmap->xBytes;
    entry->xBytesAnd     = andBitmap->xBytes;  
    /*
    * Add the entry to the entries array.
    */
    overflow_add(MSIconData->count,1);
    MSIconData->count++;
    /* 
    * Perhaps I should use something that allocs a decent amount at start...
    */
    MSIconData->entries = 
        realloc2 (MSIconData->entries, MSIconData->count * sizeof(IC_Entry *));
    MSIconData->entries[MSIconData->count-1] = entry;
}