Staredit Network > Forums > General StarCraft > Topic: Unsigned negative values???
Unsigned negative values???
Jan 1 2017, 10:24 am
By: iCCup.xboi209  

Jan 1 2017, 10:24 am iCCup.xboi209 Post #1



http://www.staredit.net/wiki/index.php/Scenario.chk#Sections

Quote
Invalid 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?




Jan 1 2017, 2:40 pm jjf28 Post #2

Cartography Artisan

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.

Code
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
}




Rs_yes-im4real - Clan Aura - jjf28.net84.net

Reached the top of StarCraft theory crafting 2:12 AM CST, August 2nd, 2014.

Jan 1 2017, 5:29 pm Wormer Post #3



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.

Jan 1 2017, 5:45 pm jjf28 Post #4

Cartography Artisan

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.



Rs_yes-im4real - Clan Aura - jjf28.net84.net

Reached the top of StarCraft theory crafting 2:12 AM CST, August 2nd, 2014.

Jan 1 2017, 5:55 pm Wormer Post #5



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.

Jan 1 2017, 7:19 pm jjf28 Post #6

Cartography Artisan

me and farty used jump sections for compressing things like dEUPs; otherwise I think it's just for protection



Rs_yes-im4real - Clan Aura - jjf28.net84.net

Reached the top of StarCraft theory crafting 2:12 AM CST, August 2nd, 2014.

Jan 3 2017, 2:37 am iCCup.xboi209 Post #7



I was actually going to write a Chk library :massimo:
I wanted to translate some Korean maps that are protected, but can't do so with conventional map editors.




Jan 3 2017, 4:08 am trgk Post #8



1234 + 0xfffffffc = 1230



EUD

Options
  Back to forum
Please log in to reply to this topic or to report it.
Members in this topic: None.
[09:10 am]
Suicidal Insanity -- :P
[09:10 am]
Suicidal Insanity -- Not that I think that is a good idea
[09:10 am]
Suicidal Insanity -- then it is a real index
[09:10 am]
Suicidal Insanity -- jjf28
jjf28 shouted: Suicidal Insanity I can't have code saying xIndex for something that's 1-based, to me xIndex is always a 0-based array index specifically, anything else is an identifier ("Id", usually sequential) or key (hash or a fixed-byte abbreviation or something), those are my cues so I don't need to constantly refer to some documentation so I know what to code
I'm just saying have your function 'GetMapTitleStringIndex' return realValue - 1
[2019-3-18. : 1:45 am]
CaptainWill -- If anyone was considering Hypnospace Outlaw, I recommend it
[2019-3-18. : 1:41 am]
jjf28 -- I think the reason I had it so wrong was cause I could treat it as a 0-based index from section start (offsets actually start after first two bytes of numStrings) so I had my access simplified like that :P
[2019-3-18. : 1:08 am]
jjf28 -- Suicidal Insanity
Suicidal Insanity shouted: No you don't. you can just change all the getters that give you a stringID instead
I can't have code saying xIndex for something that's 1-based, to me xIndex is always a 0-based array index specifically, anything else is an identifier ("Id", usually sequential) or key (hash or a fixed-byte abbreviation or something), those are my cues so I don't need to constantly refer to some documentation so I know what to code
[2019-3-18. : 12:52 am]
O)FaRTy1billion[MM] -- 0 usually means no string or default string
[2019-3-17. : 9:58 pm]
Ultraviolet -- :wob:
[2019-3-17. : 9:51 pm]
Corbo -- hi
Please log in to shout.


Members Online: Roy, Kolokol