http://www.staredit.net/wiki/index.php/Scenario.chk#SectionsInvalid sections can exist and will be ignored. While Size is unsigned, it can safely be a negative value to read a chunk earlier in the file. This allows for "section stacking", allowing smaller sections to be placed inside of larger ones or duplicate triggers or units to take less space in the file.
So how can Size be negative if it's unsigned?
None.
I assume the wiki means that so long as it's a u32, the addition overflow arithmetic is the same as if it were a s32, personally I just made it signed.
bool Scenario::ParseScenario(buffer &chk)
{
caching = false;
u32 chkSize = chk.size();
u32 position = 0,
nextPosition = 0;
bool parsing = true;
do
{
if ( position + 8 < chkSize ) // Valid section header
{
if ( ParseSection(chk, position, nextPosition) )
position = nextPosition;
else // Severe data handling issue or out of memory
return false;
}
else if ( position < chkSize ) // Partial section header
{
tailLength = (u8)(chkSize - position);
if ( !chk.getArray<u8>(tailData, position, tailLength) )
return false;
mapIsProtected = true;
parsing = false;
}
else if ( position > chkSize ) // Oversized finish
{
mapIsProtected = true;
parsing = false;
}
else // Natural finish (position == chkSize)
parsing = false;
} while ( parsing );
// Pre-cache mergings/corrections
correctMTXM();
// Cache sections
CacheSections();
caching = true;
return true;
}
bool Scenario::ParseSection(buffer &chk, u32 position, u32 &nextPosition)
{
u32 sectionId = 0;
s32 sectionSize = 0;
if ( chk.get<u32>(sectionId, position) && // Get sectionId/title
chk.get<s32>(sectionSize, position + 4) ) // Get section size
{
nextPosition = position + 8 + sectionSize;
}
else
return false; // Unexpected read faliure
if ( sectionSize >= 0 ) // Normal section
{
auto newSection = AddSection(sectionId);
return nextPosition >= position + 8 && // Check for addition overflow
(nextPosition > chk.size() || // Check for oversized
sectionSize == 0 || // Check for empty section
newSection->extract(chk, position+8, sectionSize)); // Move data to this section
}
else if ( sectionSize < 0 ) // Jump section
{
return nextPosition < position + 8 && // Check for addition underflow
nextPosition != 0; // Check for loop (right now it just checks for position to zero)
}
return true; // sectionSize == 0
}
TheNitesWhoSay - Clan Aura -
githubReached the top of StarCraft theory crafting 2:12 AM CST, August 2nd, 2014.
jjf28 is right, since signed and unsigned is only a way how we interpret the number. If we're working with unsigned numbers then we consider overflow an error. If we say numbers are signed then we utilize overflow mechanics to make a subtraction operation out of summation and don't consider overflow an error.
In this particular case, since 32bit address space is assumed, we can individually address up to 2^32 bytes = 4GiB memory. If you're trying to shift forward more than there are bytes left from current position to the end of the address space overflow wraps it up and actually gets us back in address space.
That way, if our current (0-based) position is CP (which points at the byte just after the section header) and you shift SZ bytes forward, where SZ >= 4 GiB - CP, then next position NP is SZ - (4 GiB - CP) which is CP - NP = 4GiB - SZ bytes backward. The latter is in turn a number -SZ written in two's complement form.
jjf28, thank you for the nice piece of code! The check for addition underflow is smart, I probably wouldn't have thought about this little nuisance. Actually this question arouse in good time, because I was going to play with chk format on my own and write a parser. May I use the provided code as a start point?
Some.
All of Chkdraft is under the MIT license so feel free to use it however, so long as you're not copy-pasting and claiming the code was your original work.
I wrote all of "Mapping Core" to be possible to quickly copy-paste into new projects (as I've done with lotsa my little apps like TrigCount) but you ofc can use the code however you wish
The code was from
this file in particular.
TheNitesWhoSay - Clan Aura -
githubReached the top of StarCraft theory crafting 2:12 AM CST, August 2nd, 2014.
Thanks! That will be very useful to me! I just realized there might be weird loops due to backwards reference... uh oh. I wonder if jump sections are really used anywhere besides map protection.
Some.
me and farty used jump sections for compressing things like dEUPs; otherwise I think it's just for protection
TheNitesWhoSay - Clan Aura -
githubReached the top of StarCraft theory crafting 2:12 AM CST, August 2nd, 2014.
I was actually going to write a Chk library
I wanted to translate some Korean maps that are protected, but can't do so with conventional map editors.
None.