wesleyjohnson
Member
Posts: 486
Registered: 04-09 |
That all is interesting. Just to save everyone from downloading DoomLegacy (ha ha), it follows here. Just for reference, or to make commenting on it more accurate. Inserted underlines because this post engine keeps removing the indenting, and it collapses all other multiple spaces to one space.
Notice:
1. The problem is in the blockmap offset table, which gives indexes into the actual blockmap lists.
2. There are protections to keep it disabled for most level maps.
3. The protections arbitrarily uses 0x1000, which could be tightened up to 0x0020 or smaller and still work.
4. How well this succeeds with overly large compressed blockmaps (with offsets that exceed 0xf000), is dependent on whether the shared lists are within 0x1000 of each other and do not occur across the bme increment. I expect compression to reduce the blockmap table to smaller than 0xf000 (keeping it valid), and thus reduce the chance of another Europe.wad problem.
Partial Listing from reading of blockmap, in p_setup.c
firstlist = 4 + (bmapwidth*bmapheight);
lastlist = count - 1;
// read blockmap index array
for (i=4 ; i<firstlist ; i++) // for all entries in wad offset index
{
_ uint32_t bme = LE_SWAP16(wadblockmaplump[i]); // offset
_ // upon overflow, the bme will wrap to low values
_ if ( (bme < firstlist) // too small to be valid
_ && (bme < 0x1000) && (prev_bme > 0xf000)) // wrapped
_ {
_ _ // first or repeated overflow
_ _ overflow_corr += 0x00010000;
_ _ fprintf( stderr,"Correct blockmap offset[%i...] overflow by adding 0x%X\n",
_ _ i, overflow_corr );
_ }
_ prev_bme = bme; // uncorrected
_ // correct for overflow, or else try without correction
_ if ( overflow_corr )
_ {
_ _ uint32_t bmec = bme + overflow_corr;
_ _ // First entry of list is 0, but high odds of hitting one randomly.
_ _ // Check for valid blockmap offset, and offset overflow
_ _ if ( bmec <= lastlist
_ _ && wadblockmaplump[bmec] == 0 // valid start list
_ _ && ((bmec - blockmaphead[i-1]) < 1000)) // reasonably close sequentially
_ _ {
_ _ _ bme = bmec;
_ _ }
_ }
_ if ( bme > lastlist )
_ _ I_Error("Blockmap offset[%i]= %i, exceeds bounds.\n", i, bme);
_ if ( bme < firstlist
_ _ || wadblockmaplump[bme] != 0 ) // not start list
_ _ I_Error("Bad blockmap offset[%i]= %i.\n", i, bme);
_ blockmaphead[i] = bme;
}
// read blockmap lists
for (i=firstlist ; i<count ; i++) // for all list entries in wad blockmap
{
_ // killough 3/1/98
_ // keep -1 (0xffff), but other values are unsigned
_ uint16_t bme = LE_SWAP16(wadblockmaplump[i]);
_ blockmaphead[i] = (bme == 0xffff)? ((uint32_t) -1) : ((uint32_t) bme);
}
Last edited by wesleyjohnson on 06-30-11 at 05:00
|