Exemple #1
0
/********************************************************************
*	 ConvertTMPQShunt
********************************************************************/
void ConvertTMPQShunt(void *shunt)
{
	TMPQShunt * theShunt = (TMPQShunt *)shunt;

	theShunt->dwID = SwapULong(theShunt->dwID);
	theShunt->dwUnknown = SwapULong(theShunt->dwUnknown);
	theShunt->dwHeaderPos = SwapULong(theShunt->dwHeaderPos);
}
Exemple #2
0
/********************************************************************
*	 ConvertTMPQUserData
********************************************************************/
void ConvertTMPQUserData(void *userData)
{
	TMPQUserData * theData = (TMPQUserData *)userData;

	theData->dwID = SwapULong(theData->dwID);
	theData->cbUserDataSize = SwapULong(theData->cbUserDataSize);
	theData->dwHeaderOffs = SwapULong(theData->dwHeaderOffs);
	theData->cbUserDataHeader = SwapULong(theData->cbUserDataHeader);
}
Exemple #3
0
/********************************************************************
*	 ConvertTMPQHeader
********************************************************************/
void ConvertTMPQHeader(void *header)
{
	TMPQHeader2 * theHeader = (TMPQHeader2 *)header;
	
	theHeader->dwID = SwapULong(theHeader->dwID);
	theHeader->dwHeaderSize = SwapULong(theHeader->dwHeaderSize);
	theHeader->dwArchiveSize = SwapULong(theHeader->dwArchiveSize);
	theHeader->wFormatVersion = SwapUShort(theHeader->wFormatVersion);
	theHeader->wBlockSize = SwapUShort(theHeader->wBlockSize);
	theHeader->dwHashTablePos = SwapULong(theHeader->dwHashTablePos);
	theHeader->dwBlockTablePos = SwapULong(theHeader->dwBlockTablePos);
	theHeader->dwHashTableSize = SwapULong(theHeader->dwHashTableSize);
	theHeader->dwBlockTableSize = SwapULong(theHeader->dwBlockTableSize);

	if(theHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
	{
		DWORD dwTemp = theHeader->ExtBlockTablePos.LowPart;
		theHeader->ExtBlockTablePos.LowPart = theHeader->ExtBlockTablePos.HighPart;
		theHeader->ExtBlockTablePos.HighPart = dwTemp;
		theHeader->ExtBlockTablePos.LowPart = SwapULong(theHeader->ExtBlockTablePos.LowPart);
		theHeader->ExtBlockTablePos.HighPart = SwapULong(theHeader->ExtBlockTablePos.HighPart);
		theHeader->wHashTablePosHigh = SwapUShort(theHeader->wHashTablePosHigh);
		theHeader->wBlockTablePosHigh = SwapUShort(theHeader->wBlockTablePosHigh);
	}
}
Exemple #4
0
//
// ACS_countOpSizeACS0
//
// Some instructions require special handling to find next index.
//
static uint32_t ACS_countOpSizeACS0(acs0_tracer_t *tracer, uint32_t index,
                                    uint32_t opSize, const acs0_opdata_t *opdata)
{
   switch(opdata->op)
   {
   case ACS0_OP_LINESPEC1_IMM_BYTE:
   case ACS0_OP_LINESPEC2_IMM_BYTE:
   case ACS0_OP_LINESPEC3_IMM_BYTE:
   case ACS0_OP_LINESPEC4_IMM_BYTE:
   case ACS0_OP_LINESPEC5_IMM_BYTE:
   case ACS0_OP_GET_IMM_BYTE:
   case ACS0_OP_GET2_IMM_BYTE:
   case ACS0_OP_GET3_IMM_BYTE:
   case ACS0_OP_GET4_IMM_BYTE:
   case ACS0_OP_GET5_IMM_BYTE:
   case ACS0_OP_DELAY_IMM_BYTE:
   case ACS0_OP_RANDOM_IMM_BYTE:
      return opSize + opdata->args;

   case ACS0_OP_GETARR_IMM_BYTE:
      // Need room for the byte count.
      if(index + opSize > tracer->lumpLength - 4) return opSize;

      return opSize + 1 + tracer->data[index + opSize];

   case ACS0_OP_BRANCH_CASETABLE:
      // Set opSize to the op plus alignment.
      opSize = ((index + opSize + 3) & ~3) - index;

      // Need room for the case count.
      if(index + opSize > tracer->lumpLength - 4) return opSize;

      // Read the number of cases.
      return opSize + (SwapULong(*(uint32_t *)(tracer->data + index + opSize)) * 8) + 4;

   case ACS0_OP_CALLFUNC:
      return opSize + (tracer->compressed ? 3 : 8);

   default:
      return opSize + opdata->args * (tracer->compressed && opdata->compressed ? 1 : 4);
   }
}
Exemple #5
0
//
// ACS_LoadScriptACS0
//
void ACS_LoadScriptACS0(ACSVM *vm, WadDirectory *dir, int lump, byte *data)
{
   uint32_t lumpAvail; // Used in bounds checking.
   uint32_t lumpLength = dir->lumpLength(lump);
   int32_t *rover;
   uint32_t tableIndex;

   // Header + table index + script count + string count = 16 bytes.
   if (lumpLength < 16) return;
   lumpAvail = lumpLength - 16;

   rover = (int32_t *)data + 1;

   // Find script table.
   tableIndex = SwapLong(*rover);

   // Aha, but there might really be an ACSE header here!
   if(tableIndex >= 8 && tableIndex <= lumpLength)
   {
      uint32_t fakeHeader = SwapULong(*(uint32_t *)(data + tableIndex - 4));

      if(fakeHeader == ACS_CHUNKID('A', 'C', 'S', 'E'))
      {
         ACS_LoadScriptACSE(vm, dir, lump, data, tableIndex - 8);
         return;
      }
      else if(fakeHeader == ACS_CHUNKID('A', 'C', 'S', 'e'))
      {
         ACS_LoadScriptACSe(vm, dir, lump, data, tableIndex - 8);
         return;
      }
   }

   // At the index there must be at least the script count and string count.
   // Subtracting from lumpLength instead of adding to tableIndex in case the
   // latter would cause an overflow.
   if (tableIndex > lumpLength - 8) return;

   rover = (int32_t *)(data + tableIndex);

   // Read script count.
   vm->numScripts = SwapLong(*rover++);

   // Verify that there is enough space for the given number of scripts.
   if (vm->numScripts * 12 > lumpAvail) return;
   lumpAvail -= vm->numScripts * 12;

   // Also verify that the string count will be inside the lump.
   if (tableIndex + 8 > lumpLength - (vm->numScripts * 12)) return;
   tableIndex += 8 + (vm->numScripts * 12);

   // Read scripts.
   vm->scripts = estructalloctag(ACSScript, vm->numScripts, PU_LEVEL);

   for(ACSScript *itr = vm->scripts, *end = itr + vm->numScripts; itr != end; ++itr)
   {
      itr->number    = SwapLong(*rover++);
      itr->codeIndex = SwapLong(*rover++);
      itr->numArgs   = SwapLong(*rover++);

      itr->numVars   = ACS_NUM_LOCALVARS;
      itr->vm        = vm;

      if(itr->number >= 1000)
      {
         itr->type = ACS_STYPE_OPEN;
         itr->number -= 1000;
      }
      else
         itr->type = ACS_STYPE_CLOSED;
   }

   // Read string count.
   vm->numStrings = SwapLong(*rover++);

   // Again, verify that there is enough space for the table first.
   if (vm->numStrings * 4 > lumpAvail) return;
   lumpAvail -= vm->numStrings * 4;

   // This time, just verify the end of the table is in bounds.
   if (tableIndex > lumpLength - (vm->numStrings * 4)) return;

   // Read strings.
   vm->strings = (uint32_t *)Z_Malloc(vm->numStrings * sizeof(uint32_t), PU_LEVEL, NULL);

   for(uint32_t *itr = vm->strings, *end = itr + vm->numStrings; itr != end; ++itr)
   {
      tableIndex = SwapLong(*rover++);

      if (tableIndex < lumpLength)
         *itr = ACS_LoadStringACS0(data + tableIndex, data + lumpLength);
      else
         *itr = ACS_LoadStringACS0(data + lumpLength, data + lumpLength);
   }

   // The first part of the global string table must match VM-0 for compatibility.
   if(vm->id == 0 && ACSVM::GlobalNumStrings < vm->numStrings)
      vm->addStrings();

   // Read code.
   ACS_LoadScriptCodeACS0(vm, data, lumpLength, false);

   vm->loaded = true;
}
Exemple #6
0
//
// ACS_traceScriptACS0
//
static void ACS_traceScriptACS0(acs0_tracer_t *tracer, uint32_t index)
{
   uint32_t indexNext, opSize;
   int32_t op;
   acs0_opdata_t const *opdata;

   for(;;)
   {
      // Read next instruction from file.
      op = ACS_readOpACS0(tracer, &opSize, index);

      // Invalid opcode terminates tracer.
      if(op >= ACS0_OPMAX || op < 0)
      {
         // But flag it so that a KILL gets generated by the translator.
         ACS_touchScriptACS0(tracer->codeTouched + index, tracer->codeTouched + index + opSize);
         ++tracer->vm->numCode;
         return;
      }

      opdata = &ACS0opdata[op];

      // Calculate next index.
      indexNext = index + ACS_countOpSizeACS0(tracer, index, opSize, opdata);

      // Leaving the bounds of the lump also terminates the tracer.
      if(indexNext > tracer->lumpLength) return;

      // If already touched this instruction, stop tracing.
      if(ACS_touchScriptACS0(tracer->codeTouched + index, tracer->codeTouched + indexNext))
         return;

      // Determine how many internal codes this counts for.
      switch(op)
      {
      case ACS0_OP_LINESPEC1_IMM:
      case ACS0_OP_LINESPEC2_IMM:
      case ACS0_OP_LINESPEC3_IMM:
      case ACS0_OP_LINESPEC4_IMM:
      case ACS0_OP_LINESPEC5_IMM:
      case ACS0_OP_LINESPEC1_IMM_BYTE:
      case ACS0_OP_LINESPEC2_IMM_BYTE:
      case ACS0_OP_LINESPEC3_IMM_BYTE:
      case ACS0_OP_LINESPEC4_IMM_BYTE:
      case ACS0_OP_LINESPEC5_IMM_BYTE:
      case ACS0_OP_GET2_IMM_BYTE:
      case ACS0_OP_GET3_IMM_BYTE:
      case ACS0_OP_GET4_IMM_BYTE:
      case ACS0_OP_GET5_IMM_BYTE:
         tracer->vm->numCode += opdata->args + 2;
         break;

      case ACS0_OP_GETARR_IMM_BYTE:
         tracer->vm->numCode += *(tracer->data + index + opSize) + 2;
         break;

      case ACS0_OP_ACTIVATORHEALTH:
      case ACS0_OP_ACTIVATORARMOR:
      case ACS0_OP_ACTIVATORFRAGS:
      case ACS0_OP_BRANCH_RETURNVOID:
      case ACS0_OP_PLAYERNUMBER:
      case ACS0_OP_ACTIVATORTID:
      case ACS0_OP_SIGILPIECES:
         tracer->vm->numCode += opdata->opdata->args + 1 + 2; // GET_IMM 0
         break;

      case ACS0_OP_GAMETYPE_ONEFLAGCTF:
         tracer->vm->numCode += 2; // GET_IMM
         break;
      case ACS0_OP_GAMETYPE_SINGLEPLAYER:
         tracer->vm->numCode += 4; // GAMETYPE + GET_IMM + CMP_EQ
         break;

      case ACS0_OP_BRANCH_CALLDISCARD:
         tracer->vm->numCode += opdata->opdata->args + 1 + 1; // DROP
         break;

      case ACS0_OP_BRANCH_CASETABLE:
         tracer->vm->numCode += 2;
         // More alignment stuff. (Wow, that's a mouthfull.)
         tracer->vm->numCode += SwapULong(*(uint32_t *)(((uintptr_t)tracer->data + index + opSize + 3) & ~3)) * 2;
         break;

      case ACS0_OP_CALLFUNC:
         if(tracer->compressed)
         {
            uint8_t  argc = tracer->data[index + opSize];
            uint16_t func = SwapUShort(*(uint16_t *)(tracer->data + index + opSize + 1));
            tracer->vm->numCode += ACS_traceFuncACS0(func, argc);
         }
         else
         {
            uint32_t argc = SwapULong(*(uint32_t *)(tracer->data + index + opSize + 0));
            uint32_t func = SwapULong(*(uint32_t *)(tracer->data + index + opSize + 4));
            tracer->vm->numCode += ACS_traceFuncACS0(func, argc);
         }
         break;

      default:
         // Translation to CALLFUNC.
         if(opdata->opdata->op == ACS_OP_CALLFUNC_IMM)
         {
            // Adds the func and argc arguments.
            tracer->vm->numCode += opdata->args + 1 + 2;
            break;
         }

         // Direct translation.
#ifdef RANGECHECK
         // This should never happen.
         if(opdata->opdata->args == -1)
            I_Error("Unknown translation for opcode. opcode %i", (int)op);
#endif

         tracer->vm->numCode += opdata->opdata->args + 1;
         break;
      }

      // Advance the index past the instruction.
      switch(op)
      {
      case ACS0_OP_SCRIPT_TERMINATE:
      case ACS0_OP_BRANCH_RETURN:
      case ACS0_OP_BRANCH_RETURNVOID:
         return;

      case ACS0_OP_BRANCH_IMM:
         ++tracer->jumpCount;
         index = SwapLong(*(int32_t *)(tracer->data + index + opSize));
         continue;

      case ACS0_OP_BRANCH_NOTZERO:
      case ACS0_OP_BRANCH_ZERO:
         ++tracer->jumpCount;
         ACS_traceScriptACS0(tracer, SwapLong(*(int32_t *)(tracer->data + index + opSize)));
         break;

      case ACS0_OP_BRANCH_CASE:
         ++tracer->jumpCount;
         ACS_traceScriptACS0(tracer, SwapLong(*(int32_t *)(tracer->data + index + opSize + 4)));
         break;

      case ACS0_OP_BRANCH_CASETABLE:
         {
            uint32_t jumps, *rover;

            rover = (uint32_t *)(tracer->data + index + opSize);
            // And alignment again.
            rover = (uint32_t *)(((uintptr_t)rover + 3) & ~3);
            jumps = SwapULong(*rover++);

            tracer->jumpCount += jumps;

            // Trace all of the jump targets.
            // Start by incrementing rover to point to address.
            for(++rover; jumps--; rover += 2)
               ACS_traceScriptACS0(tracer, SwapULong(*rover));
         }
         break;
      }

      index = indexNext;
   }
}