Пример #1
0
int readChunk(chunk &outChunk, unsigned char *chunkData)
{
  outChunk.data       = chunkData;
  outChunk.magic      = getHword(chunkData,      CHUNK_MAGIC, true);
  outChunk.type       = getHword(chunkData,       CHUNK_TYPE, true); 
  outChunk.CID        =  getWord(chunkData,        CHUNK_CID, true);
  outChunk.entryCount =  getWord(chunkData, CHUNK_ENTRYCOUNT, true);
  outChunk.checksum   =  getWord(chunkData,   CHUNK_CHECKSUM, true);

  if (outChunk.type == 0)
  {
    unsigned long prevOffset = 0;
	  for (unsigned long count = 0; count < outChunk.entryCount; count++)
    {
      unsigned long offset      = getWord(chunkData, CHUNK_ENTRYOFFSETS+(count*4), true);
      outChunk.entryData[count] = &chunkData[offset];
	
	    outChunk.entrySize[count] = offset - prevOffset;
	    readEntry(outChunk.entries[count], outChunk.entryData[count]);
	    prevOffset = offset;
    }
  }
  
  return outChunk.type;
}
Пример #2
0
//sub_800260AC
void updateLevelMisc(unsigned char *headerMisc, unsigned long flags)
{
  //*(0x57970) = *(0x34520)
  var_57964 = var_57968 & 0xFFFFFF00;
  var_5796C = (getHword(headerMisc, 0x2C, true) << 8) | getHword(headerMisc, 0x2E, true);
  
  unsigned long zoneFlags = getWord(headerMisc, 0x1C, true);
  globals[0x1E] = zoneFlags; 
  
  if (flags & 4)
    flagUnknown = true;
}
Пример #3
0
void readCrashZoneEntity(unsigned char *zoneEntity, crash_zone_entity &crashZoneEntity)
{
  crashZoneEntity.reserved      = getWord(zoneEntity, 0, true);
  crashZoneEntity.initModeFlags = getHword(zoneEntity, 0x4, true);
  crashZoneEntity.group         = getHword(zoneEntity, 0x6, true);
  crashZoneEntity.ID            = getHword(zoneEntity, 0x8, true);
  crashZoneEntity.pathCount     = getHword(zoneEntity, 0xA, true);
  crashZoneEntity.initFlagsA    = getHword(zoneEntity, 0xC, true);
  crashZoneEntity.initFlagsB    = getHword(zoneEntity, 0xE, true);
  crashZoneEntity.initFlagsC    = getHword(zoneEntity, 0x10, true);
  crashZoneEntity.type          = zoneEntity[0x12];
  crashZoneEntity.subtype       = zoneEntity[0x13];
  
  crashZoneEntity.camPath = (crash_zone_entity::objectCamPathNode*)malloc(crashZoneEntity.pathCount * sizeof(crash_zone_entity::objectCamPathNode));
  for (int lp=0; lp<crashZoneEntity.pathCount; lp++)
  {
    crashZoneEntity.camPath[lp].camX = getHword(zoneEntity, 0x14+(lp*6), true);
    crashZoneEntity.camPath[lp].camY = getHword(zoneEntity, 0x16+(lp*6), true);
    crashZoneEntity.camPath[lp].camZ = getHword(zoneEntity, 0x18+(lp*6), true);
  }
}
Пример #4
0
void readCrashZoneSection(unsigned char *zoneSection, crash_zone_section &crashZoneSection)
{
  crashZoneSection.slst                 = getWord(zoneSection, 0, true);
  crashZoneSection.parentZone           = getWord(zoneSection, 4, true);
  crashZoneSection.neighborSectionCount = getWord(zoneSection, 8, true);
  
  for (int lp=0; lp<4; lp++)
  { 
    crash_zone_section::neighborSectionDescriptor *neighborSection = &crashZoneSection.neighborSection[lp];
    neighborSection->relation           = zoneSection[0xC+(lp*4)];
    neighborSection->neighborZoneIndex  = zoneSection[0xD+(lp*4)];
    neighborSection->sectionIndex       = zoneSection[0xE +(lp*4)];
    neighborSection->goal               = zoneSection[0xF+(lp*4)];
  }
  
  crashZoneSection.entranceIndex        = zoneSection[0x1C];
  crashZoneSection.exitIndex            = zoneSection[0x1D];
  crashZoneSection.length               = getHword(zoneSection, 0x1E, true);
  crashZoneSection.camMode              = getHword(zoneSection, 0x20, true);
  crashZoneSection.avgNodeDist          = getHword(zoneSection, 0x22, true);
  crashZoneSection.camZoom              = getHword(zoneSection, 0x24, true);
  crashZoneSection.unknownA             = getHword(zoneSection, 0x26, true);
  crashZoneSection.unknownB             = getHword(zoneSection, 0x28, true);
  crashZoneSection.unknownC             = getHword(zoneSection, 0x2A, true);
  crashZoneSection.pathDirectionX       = getHword(zoneSection, 0x2C, true);
  crashZoneSection.pathDirectionY       = getHword(zoneSection, 0x2E, true);
  crashZoneSection.pathDirectionZ       = getHword(zoneSection, 0x30, true);
  
  crashZoneSection.camPath = (crash_zone_section::sectionCamPathNode*)malloc(crashZoneSection.length * sizeof(crash_zone_section::sectionCamPathNode));
  for (int lp=0; lp<crashZoneSection.length; lp++)
  {
    crashZoneSection.camPath[lp].camX    = getHword(zoneSection, 0x32+(lp*12), true);
    crashZoneSection.camPath[lp].camY    = getHword(zoneSection, 0x34+(lp*12), true);
    crashZoneSection.camPath[lp].camZ    = getHword(zoneSection, 0x36+(lp*12), true);
    
    crashZoneSection.camPath[lp].camRotX = getHword(zoneSection, 0x38+(lp*12), true);
    crashZoneSection.camPath[lp].camRotY = getHword(zoneSection, 0x40+(lp*12), true);
    crashZoneSection.camPath[lp].camRotZ = getHword(zoneSection, 0x42+(lp*12), true);
  }
}
Пример #5
0
void readCrashZoneHeader(entry *zone, crash_zone_header &crashZoneHeader)
{
  unsigned char *zoneHeader = zone->itemData[0];
  
  crashZoneHeader.worldCount     = getWord(zoneHeader, 0, true);
  for (int lp=0; lp<8; lp++)                   
    crashZoneHeader.world[lp].world = getWord(zoneHeader, 4+(lp*0x40), true);
                                               
  crashZoneHeader.headerColCount = getWord(zoneHeader, 0x204, true);
  crashZoneHeader.sectionCount   = getWord(zoneHeader, 0x208, true);
  crashZoneHeader.entityCount    = getWord(zoneHeader, 0x20C, true);
                                               
  crashZoneHeader.neighborCount  = getWord(zoneHeader, 0x210, true);
  for (int lp=0; lp<8; lp++)                   
    crashZoneHeader.neighbor[lp] = getWord(zoneHeader, 0x214+(lp*4), true);
                                               
  crashZoneHeader.tpageCount     = getWord(zoneHeader, 0x234, true);
  crashZoneHeader.tchunkCount    = getWord(zoneHeader, 0x238, true);
                                               
  for (int lp=0; lp<8; lp++)                   
    crashZoneHeader.tpage[lp]    = getWord(zoneHeader, 0x23C+(lp*4), true);
    
  for (int lp=0; lp<32; lp++)
    crashZoneHeader.tchunk[lp]   = getWord(zoneHeader, 0x25C+(lp*4), true);
    
  crashZoneHeader.gameFlags      = getWord(zoneHeader, 0x2DC, true);
  crashZoneHeader.vramFillHeight = getWord(zoneHeader, 0x2E0, true);
  crashZoneHeader.unknownA       = getWord(zoneHeader, 0x2E4, true);
  crashZoneHeader.visibilityDepth= getWord(zoneHeader, 0x2E8, true);
  crashZoneHeader.unknownB       = getWord(zoneHeader, 0x2EC, true);
  crashZoneHeader.unknownC       = getWord(zoneHeader, 0x2F0, true);
  crashZoneHeader.unknownD       = getWord(zoneHeader, 0x2F4, true);
  crashZoneHeader.unknownE       = getWord(zoneHeader, 0x2F8, true);
  crashZoneHeader.flags          = getWord(zoneHeader, 0x2FC, true);
  crashZoneHeader.deathY         = getWord(zoneHeader, 0x300, true);  
  crashZoneHeader.unknownF       = getWord(zoneHeader, 0x304, true);
  crashZoneHeader.unknownG       = getWord(zoneHeader, 0x308, true);  
  crashZoneHeader.unknownH       = getWord(zoneHeader, 0x30C, true);
  
  crashZoneHeader.vramFillR      = zoneHeader[0x310];
  crashZoneHeader.vramFillG      = zoneHeader[0x311];
  crashZoneHeader.vramFillB      = zoneHeader[0x312];
  crashZoneHeader.unusedA        = zoneHeader[0x313];
  crashZoneHeader.farColorR      = zoneHeader[0x314];
  crashZoneHeader.farColorG      = zoneHeader[0x315];
  crashZoneHeader.farColorB      = zoneHeader[0x316];
  crashZoneHeader.unusedB        = zoneHeader[0x317];
  
  for (int lp=0; lp<9; lp++)
    crashZoneHeader.objectLightMatrix[lp] = getHword(zoneHeader, 0x318+(lp*2), true);
  
  for (int lp=0; lp<3; lp++)
    crashZoneHeader.objectBackColor[lp] = getHword(zoneHeader, 0x32A+(lp*2), true);
   
  for (int lp=0; lp<9; lp++)
    crashZoneHeader.objectColorMatrix[lp] = getHword(zoneHeader, 0x330+(lp*2), true);
   
  for (int lp=0; lp<3; lp++)
    crashZoneHeader.objectBackColorIntensity[lp] = getHword(zoneHeader, 0x342+(lp*2), true);
    
  for (int lp=0; lp<9; lp++)
    crashZoneHeader.playerLightMatrix[lp] = getHword(zoneHeader, 0x348+(lp*2), true);
  
  for (int lp=0; lp<3; lp++)
    crashZoneHeader.playerBackColor[lp] = getHword(zoneHeader, 0x35A+(lp*2), true);
   
  for (int lp=0; lp<9; lp++)
    crashZoneHeader.playerColorMatrix[lp] = getHword(zoneHeader, 0x360+(lp*2), true);
   
  for (int lp=0; lp<3; lp++)
    crashZoneHeader.playerBackColorIntensity[lp] = getHword(zoneHeader, 0x372+(lp*2), true);
}
Пример #6
0
//sub_80025A60(zone, section, progressV, flags)
void updateLevel(entry *zone, unsigned char *section, signed long progressV, unsigned long flags)
{
  //var_78 = zone
  //var_70 = section
  //var_68 = progressV
  //var_60 = flag

  if (!zone || !section) { return; }

  unsigned short sectionDepth  = getHword(section, 0x1E, true);
  unsigned short sectionDepthV = sectionDepth << 8;
  
  //restrict the progress value from the input if it does not lie in the section
  if (progressV < (sectionDepthV - 1))
  {
    if (progressV < 0)
      progressV = 0;
  }
  else
    progressV = (sectionDepthV - 1);

  unsigned char *zoneHeader    = zone->itemData[0];
  unsigned long zoneModelCount = getWord(zoneHeader, 0, true);
  
  unsigned long progress        =        progressV >> 8;
  unsigned long currentProgress = currentProgressV >> 8;
 
  //if the zone is not a blank area and contains models 
  if (zoneModelCount != 0)
  {
    if (zone == currentZone && section == currentSection && progress == currentProgress) 
    {
      //wouldn't they be the same though at this point?
      currentProgressV = progressV; 
    }
    //else there is a new zone, new zone section, or change in section progress
    else
    {
      /* we don't care about the display lists quite yet 
      although their format has been cracked...
      
      unsigned long slstEID = getWord(section, 0, true);

      changeProgress = abs((progressV - curProgressV) >> 8);

      if (section == curSection &&
          (progress >= changeProgress && (sectionDepth - (progress + 1)) >= changeProgress))
      {
        startItem = curProgress;
      }
      else
      {
        swap(gp[0x2C0], gp[0x304]);

        sectionCenter = sectionDepth / 2;

        if (progress < sectionCenter)
        {
          itemFirst = slst[0x10];

          gp[0x2BC] = sub_80029B0C(itemFirst, gp[0x2BC], gp[0x304], 1);

          startItem = 0;
        }
        else
        {
          itemLast = slst[0x10 + (sectionDepth*4)];

          gp[0x2BC] = sub_80029B0C(itemLast, gp[0x2BC], gp[0x304], 0);

          startItem = sectionDepth - 1;
        }
      }

      count     = progress - startItem;
      itemIndex = startItem;

      while (count != 0)
      {
        swap(gp[0x2C0], gp[0x304]);

        if (count < 0)
        {
          itemIndex--;
          count++;  
          flag = 0;
        }
        else //count is > 0
        {
          itemIndex++;
          count--;
          flag = 1;    
        }

        item = slst[0x10 + (itemIndex*4)];

        gp[0x2BC] = sub_80029B0C(itemLast, gp[0x2BC], gp[0x304], flag);
      }
      
      sub_80015458(section, 1);
      */
    }
  }
  
  //if the zone has no wgeo models OR there has been a change in zone, section, or progress
  if (zoneModelCount == 0 || 
      zone != currentZone || section != currentSection || progress != currentProgress)
  {
    if (currentZone != zone)
    {
      bool processPages = true;
      
      //*(0x61998) = 0;
      globals[0x43] = 0;
      
      //set by camera routine/camera mode
      //if (*(0x618D0) == 0x600)
      //  processPages = !(flags & 2);
        
      if (currentZone)
      {
        oldZoneHeader                = currentZone->itemData[0];
        unsigned char *newZoneHeader = zone->itemData[0];
        
        processPages = (flags & 2);  

        unsigned long oldNeighborCount = getWord(oldZoneHeader, 0x210, true);     //count of neighboring Zdat entrys? including itself?
        unsigned long newNeighborCount = getWord(newZoneHeader, 0x210, true); 

        for (int countA = 0; countA < oldNeighborCount; countA++)
        {
          //oldNeighborZone = EID_PROCESS(getWord(oldZoneHeader, 0x214+(countA*4), true));   //
          unsigned long EID       = getWord(oldZoneHeader, 0x214 + (countA*4), true);
          entry *oldNeighborZone  = crashSystemPage(EID);
          
          bool match = false;
          for (int countB = 0; countB < newNeighborCount; countB++)
          {
            //entry *newNeighborZone = EID_PROCESS(getWord(newZoneHeader, 0x214+(countB*4), true);
            EID                    = getWord(newZoneHeader, 0x214 + (countB*4), true);
            entry *newNeighborZone = crashSystemPage(EID);
          
            if (newNeighborZone == oldNeighborZone)
            {
              match = true;
              break;
            }
          }
    
          if (match) 
          {
            unsigned char *oldNeighbHeader = oldNeighborZone->itemData[0];
   
            //if zone is loaded then remove it from the system and reset bits
            unsigned long zoneFlags = getWord(oldNeighbHeader, 0x2DC, true);
            if (zoneFlags & 1)
            {
              //sub_8001D200(oldNeighborZone);  //remove it from the system
              setWord(oldNeighbHeader, 0x2DC, true, zoneFlags & 0xFFFFFFFC); //clear bits 1 & 2
            }
          }
        }
      }
          
      if ((flags & 1) == 0)
      {
        for (int count = 0; count < 0x130; count++)
          states[count] &= 0xFFFFFFF9;  //clear bit 2 & 3
      }
          
      currentZone      = zone;
      currentSection   = section;
      currentProgressV = progressV;    
      
      /* can't do any of the following yet; paging system not implemented 
      
      //texture page entry/chunk array routine (gets set up for load to appropriate slots?)
      if (section)
        sub_8001495C(&zoneHeader[0x234], 0);
      else
        sub_8001495C(0, 0);
   
      //load all zone tpage entries
      unsigned long texCount = getWord(zoneHeader, 0x234, true);
      for (int count = 0; count < texCount; count++)
      {
        unsigned long texEID = getWord(zoneHeader, 0x23C+(count*4), true);
        sub_80015118(texEID, 0, 1);
      }

      unsigned long CIDCount = getWord(zoneHeader, 0x238, true);
      for (int count = 0; count < CIDCount; count++)
      {
        unsigned long texCID = getWord(zoneHeader, 0x25C, true);
        sub_80014DD0(texCID, 0, 1, 0x6396347F);
      }

      if (processPages != 0)     //bit 2 from the flags if set
        sub_80013748();          //process ALL pages in the CID list

      */
      
      unsigned long neighborCount = getWord(zoneHeader, 0x210, true);
      
      unsigned char *neighborHeader;
      for (int count = 0; count < neighborCount; count++)
      {
        //neighborZone              = EID_PROCESS(neighborEID);    
        unsigned long EID       = getWord(zoneHeader, 0x214 + (count*4), true);
        entry *neighborZone     = crashSystemPage(EID);
                  
        neighborHeader = neighborZone->itemData[0];
        if ((getWord(neighborHeader, 0x2DC, true) & 1) == 0)  //if bit 1 not set
        {
          var_61A5C = 0;
          var_61A64 = 0;

          var_61A60 = 0x19000;

          setWord(neighborHeader, 0x2DC, true, getWord(neighborHeader, 0x2DC, true) | 3);  //set bits 1 & 2
        }             
        
        if (processPages)
          setWord(neighborHeader, 0x2DC, true, getWord(neighborHeader, 0x2DC, true) | 4);  //set bit 3
        else
          setWord(neighborHeader, 0x2DC, true, getWord(neighborHeader, 0x2DC, true) & 3); //clear bit 3
      }
          
      //use this function on the last neighbor
      updateLevelMisc(neighborHeader + 0x2E0, flags);
    } 
    else
    {
      currentZone      = zone;
      currentSection   = section;
      currentProgressV = progressV;
    }
  }
  
  camRotBefore.X = camera.rot.X;  //copy camera X rotation angle value before sub
  camRotBefore.Y = camera.rot.Y;  //copy camera Y rotation angle value before sub
  camRotBefore.Z = camera.rot.Z;  //copy camera Z rotation angle value before sub

  cameraCalculate(currentSection, -currentProgressV, &camera);  //adjust camera for current zone

  camRotAfter.X = camera.rot.X;   //copy camera X rotation angle value after sub
  camRotAfter.Y = camera.rot.Y;   //copy camera Y rotation angle value after sub
  camRotAfter.Z = camera.rot.Z;   //copy camera Z rotation angle value after sub

  var_5CFC0 = 0;
}
Пример #7
0
void zoneList::occupy(entry *zone)
{
  unsigned char *zoneHeader = zone->itemData[0];
  modelCount = getWord(zoneHeader, 0, true);  
  headerColCount = getWord(zoneHeader, 0x204, true);
  sectionCount = getWord(zoneHeader, 0x208, true);
  entityCount = getWord(zoneHeader, 0x20C, true);
  neighborCount = getWord(zoneHeader, 0x210, true);
  
  char zoneModelString[8][30];
  for (unsigned long lp=0; lp<modelCount; lp++)
  {
    unsigned long modelEID = getWord(zoneHeader, 4+(lp*0x40), true);
    getEIDstring(zoneModelString[lp], modelEID);
    
    unsigned long parentCID = nsd->lookupCID(modelEID);
    if (parentCID != -1)
    {
      chunk *parentChunk      = nsf->lookupChunk(parentCID);
      zoneModel[lp]           = lookupEntry(modelEID, parentChunk);
    }
    else
    {
      char temp[6];
      getEIDstring(temp, modelEID);
      sprintf(zoneModelString[lp], "BAD REF: %s", temp);
      
      zoneModel[lp] = 0;
    }
  }
  
  char zoneEntityString[20][10];
  for (unsigned long lp=0; lp<entityCount; lp++)
  {
    unsigned char *entity = zone->itemData[headerColCount+sectionCount+lp];
    
    unsigned short entityID = getHword(entity, 0x8, true);
    
    unsigned char codeIndex = entity[0x12];
    unsigned long entityCodeEID = nsd->levelEIDs[codeIndex];
    char entityCodeEIDString[6];
    getEIDstring(entityCodeEIDString, entityCodeEID);
    
    sprintf(zoneEntityString[lp], "%i: %s", entityID, entityCodeEIDString);
  }
  
  char zoneNeighborString[20][10];
  for (unsigned long lp=0; lp<neighborCount; lp++)
  {
    unsigned long neighborEID = getWord(zoneHeader, 0x214+(lp*4), true);
    getEIDstring(zoneNeighborString[lp], neighborEID);
    
    unsigned long parentCID = nsd->lookupCID(neighborEID);
    if (parentCID != -1)
    {
      chunk *parentChunk      = nsf->lookupChunk(parentCID);
      zoneNeighbor[lp]        = lookupEntry(neighborEID, parentChunk);
    }
    else
    {
      char temp[6];
      getEIDstring(temp, neighborEID);
      sprintf(zoneNeighborString[lp], "BAD REF: %s", temp);
      
      zoneNeighbor[lp] = 0;
    }
  }
  
  char zoneEIDString[6];
  getEIDstring(zoneEIDString, zone->EID);
  
  char zoneString[20];
  sprintf(zoneString, "Zone: %s", zoneEIDString);
  
  AddItemToTree(hwnd, zoneString, 1, 1);
  
  AddItemToTree(hwnd, "Models", 2, 0);
  for (unsigned long lp=0; lp<modelCount; lp++)    
    AddItemToTree(hwnd, zoneModelString[lp], 3, (lp << 8) | 3);
  
  AddItemToTree(hwnd, "Entities", 2, 0);
  for (unsigned long lp=0; lp<entityCount; lp++)
    AddItemToTree(hwnd, zoneEntityString[lp], 3, (lp << 8) | 5);
  
  AddItemToTree(hwnd, "Sections", 2, 0);
  for (unsigned long lp=0; lp<sectionCount; lp++)
  {
    char sectionString[20];
    sprintf(sectionString, "Section %i", lp);
    AddItemToTree(hwnd, sectionString, 3, 0);
    
    AddItemToTree(hwnd,            "Camera", 4, (lp << 8) | (0 << 3) | 4);
    AddItemToTree(hwnd, "Neighbor Sections", 4, (lp << 8) | (1 << 3) | 4);
  }
  
  AddItemToTree(hwnd, "Neighbor Zones", 2, 0);
  for (unsigned long lp=0; lp<neighborCount; lp++)
  {
    AddItemToTree(hwnd, zoneNeighborString[lp], 3, (lp << 8) | 2);
  }
  
  AddItemToTree(hwnd,          "Lighting properties", 2, (1 << 3) | 1);
  AddItemToTree(hwnd, "Shading/rendering properties", 2, (2 << 3) | 1); 
  AddItemToTree(hwnd,             "Collision octree", 2, (3 << 3) | 1);
}
Пример #8
0
void findNode(unsigned char *zoneCollisions, unsigned short node, cspace zoneSpace, cvector *vectA, cvector *vectB, unsigned short level)
{
  // we want to search the given 'node's -child- nodes
  unsigned short *childNodes;
  
  // if the given node a non-leaf node (has children)
  // or the given node is an empty node 
  // (i.e. refers to an non-occupied, non-solid, empty region of space)
  if ((node & 1) == 0)
  {
    // if the node is a non-leaf node
    if (node & 0xFFFF)
      childNodes = (unsigned short*) &zoneCollisions[node & 0xFFFF]; //it can be subdivided into its children
    else
      childNodes = 0;                              //else it can be subdivided no further
  }  
 
  // if the given node is a non-leaf node
  if (((node & 1) == 0) && (node & 0xFFFF))
  {
    // we'd like to determine the dimensions of its child nodes
    cspace childSpace;

	memset(&childSpace, 0, sizeof(cspace));

    // firstly, we'd like to determine the width, height, and depth

    // get the max levels/depths (number of recursive subdivisions) of the tree 
    // for each dimension
    unsigned short depthW = getHword(zoneCollisions, 0x1E, true);
    unsigned short depthH = getHword(zoneCollisions, 0x20, true);
    unsigned short depthD = getHword(zoneCollisions, 0x22, true);
    
    // if the current level does not exceed the maximum level for the X dimension
    if (level < depthW)               // then the node's corresponding space (zoneSpace) 
      childSpace.W = zoneSpace.W / 2; // can be subdivided (halved) further by width..
    else                              // otherwise, the node's space
      childSpace.W = zoneSpace.W;     // can not be subdivided further by width
    
    // if the current level does not exceed the maximum level for the Y dimension
    if (level < depthH)               // then the node's corresponding space (zoneSpace) 
      childSpace.H = zoneSpace.H / 2; // can also be subdivided (halved) further by height..
    else                              // otherwise, the node's space
      childSpace.H = zoneSpace.H;     // can not be subdivided further by height
     
    // if the current level does not exceed the maximum level for the Z dimension
    if (level < depthD)               // then the node's corresponding space (zoneSpace) 
      childSpace.D = zoneSpace.D / 2; // can also be subdivided (halved) further by depth..
    else                              // otherwise, the node's space
      childSpace.D = zoneSpace.D;     // can not be subdivided further by depth
     
    // then we determine the (location) x, y, and z of each of its child nodes
    unsigned long countX = 0;
    unsigned long countY = 0;
    unsigned long countZ = 0;
    unsigned short child = 0;
    do
    {
      if ((depthW == 0) && (countX > 0))
        break;
        
      do
      {
        if ((depthH == 0) && (countY > 0))
          break;
          
        do
        {
          if ((depthD == 0) && (countZ > 0))
            break;
                      
          childSpace.X = zoneSpace.X;
          if (countX != 0)
            childSpace.X += childSpace.W;
            
          childSpace.Y = zoneSpace.Y;
          if (countY != 0)
            childSpace.Y += childSpace.H;
            
          childSpace.Z = zoneSpace.Z;
          if (countZ != 0)
            childSpace.Z += childSpace.D;
              
          // if vectA lies within the current child node/subdivision
          if ((childSpace.X < vectA->X) && 
              (childSpace.Y < vectA->Y) && 
              (childSpace.Z < vectA->Z) &&
              ((childSpace.X + childSpace.W) > vectA->X) &&
              ((childSpace.Y + childSpace.H) > vectA->Y) &&
              ((childSpace.Z + childSpace.D) > vectA->Z))
          {
            unsigned long childNode = childNodes[child];
            
            findNode(zoneCollisions, childNode, childSpace, vectA, vectB, level+1);
		  }
          
          child++;
        } while (++countZ < 2);
      } while (++countY < 2);        
    } while (++countX < 2);
    
    return; //retval;
  }
  // else the given node is an empty node 
  // (i.e. refers to an non-occupied, non-solid, empty region of space)
  // we have to interpolate the ray one unit further than the closest face
  // that it intersects to get the location of the next potentially solid
  // node at its direction
  else if ((node & 1) == 0)
  { 
    signed long xval, yval, zval;
    
    // let R be a ray starting at origin A (vectA/pointA) 
    // and pointing in direction B (vectB)

    // R = A + Bt
    
    // (we can find each point on the ray R for each 
    // corresponding value of t)

    // we also know that, at this point, the origin point A is
    // within the box/space of the containing node
    
    // we want to find which of the containing node's faces 
    // that this ray will -first- intersect with (considering
    // this is collision testing, we typically desire that
    // the object on this ray path is stopped at the first 
    // intersection pt, such that it could not travel any
    // further to reach those inevitable points of 
    // intersection with faces further away)
    // then we can move the object at origin pt.A (vectA)
    // in the given direction B (vectB) exactly up to the 
    // closest face
    
    // since we know that the origin point A is within the box
    // space of the containing node, then based on the ray's 
    // direction B, right off the bat we can eliminate 3 of the 
    // 6 node/cube faces: those aligned with the respective x,
    // y, and z axes that are 'behind' the origin pt A, since
    // these could not possibly be reached at the ray's direction
    // thus we consider only the offsets (locations) of the 
    // 3 faces that the ray point towards, each in their
    // separate respective axis
    
    if (vectB->X <= 0)                    //if negative in the x direction
      xval = zoneSpace.X;                //we may hit the left of the node
    else                                  //else if positive 
      xval = zoneSpace.X + zoneSpace.W; //we may hit the right of the node
      
    if (vectB->Y <= 0)                    //if negative in the y direction
      yval = zoneSpace.Y;                //we may hit the top of the node
    else                                  //else if positive 
      yval = zoneSpace.Y + zoneSpace.H; //we may hit the bottom of the node
      
    if (vectB->Z <= 0)                    //if negative in the z direction
      zval = zoneSpace.Z;                //we may hit the back of the node
    else                                  //else if positive 
      zval = zoneSpace.Z + zoneSpace.D; //we may hit the front of the node
      
    // note that, given the offsets in the respective axes of
    // each face, we have the respective equations of their 
    // planes:
    //
    // X = xval
    // Y = yval
    // Z = zval
    //
    // then we can solve for t for where each 
    // component of the ray intersects the respective
    // axis aligned plane:
    //
    // R = A + Bt =
    // Rx = Ax + Bxt
    // Ry = Ay + Byt
    // Rz = Az + Bzt
    //
    // (we want to find t when the component R* is at
    //  the location/offset of the plane/face in axis '*';
    //  that is, what is t for when the ray intersects the
    //  face/plane at for each respective component)
    //
    // xval = Ax + Bxt
    // Bxt = xval - Ax
    // tX = (xval - Ax)/Bx
    //
    // similarly for y and z
    // tY = (yval - Ay)/By
    // tZ = (zval - Az)/Bz
    //
    // since for -larger- t, we get a *point* -further- along 
    // the rays path as a result, the -smallest- t from these 3 
    // calculations determines the -closest- *point* along the
    // rays path that is also a point on the respective -closest-
    // face; thus we determine the min:
    
    unsigned long min = 0x7FFFFFFF;
    if (vectB->X != 0)
    {
      long tX = CTCVC(xval - vectA->X)/vectB->X;
      
      if (tX < min)
        min = tX;
    }
    
    if (vectB->Y != 0)
    {
      long tY = CTCVC(yval - vectA->Y)/vectB->Y;
      
      if (tY < min)
        min = tY;
    }
    
    if (vectB->Z != 0)
    {
      long tZ = CTCVC(zval - vectA->Z)/vectB->Z;
      
      if (tZ < min)
        min = tZ;
    }
    
    // after the following line, min will refer to one point 
    // -further- than the point of the closest plane/edge of 
    // the node (this is to move vectA into the realm of an
    // adjacent, possibly solid node, at the specified dir. of 
    // vectB)
    
    min += CTCVC(1);  
                                        
    // now we move the object at given pt A (vectA) in 
    // direction B (vectB), i.e. along ray R, until it 
    // reaches one point further than the point on the closest 
    // face (plane) at t = min, 
    
    vectA->X += CTGVC(min * vectB->X);
    vectA->Y += CTGVC(min * vectB->Y);
    vectA->Z += CTGVC(min * vectB->Z);
    
    return;
  }
  // else the node is a leaf node, so we use its value
  else
  {
    // previously, we were within a non-solid node and after
    // travelling in the direction of the ray, we crossed over the
    // closest face; the crossing took place such that we are now
    // one unit outside of/away from that node and within the 
    // current, solid (adjacent) node. since we know we are within
    // a solid node, now we reverse trace, or trace the ray back 
    // in the opposite direction, to see which of the faces that 
    // was crossed (but now in terms of this node).
    
    // by vector subtraction:
    //
    // A - B = C
    //
    // we get point C, a point that approximates our previous
    // position within the non-solid node such that we can then
    // find the dist between that point and -now- the faces of the
    // solid cube we are within
    
    // 
  
  }
}
Пример #9
0
void collisionVectors(cvector *vectA, cvector *vectB)
{
  if ((vectB->X == 0) &&
      (vectB->Y == 0) &&
      (vectB->Z == 0))
    return;
  
  unsigned char *currentZoneHeader = currentZone->itemData[0];
  
  unsigned long retval = 0;
  
  do
  {
    // number of neighbor zones
    unsigned long neighborCount = getWord(currentZoneHeader, 0x210, true);
    
    // counter/iterator
    unsigned long count = 0;
    if (neighborCount > 0)
    {
      do
      {
        unsigned long neighborEID = getWord(currentZoneHeader, 0x214+(count*4), true);
        entry *neighborZone       = goolSystemPage(neighborEID);
        
        unsigned char *neighborCollisions = neighborZone->itemData[1];
        
        // get zone location and dimensions
        signed long zoneX   = getWord(neighborCollisions,    0, true) << 8;
        signed long zoneY   = getWord(neighborCollisions,    4, true) << 8;
        signed long zoneZ   = getWord(neighborCollisions,    8, true) << 8;
        unsigned long zoneW = getWord(neighborCollisions,  0xC, true) << 8;
        unsigned long zoneH = getWord(neighborCollisions, 0x10, true) << 8;
        unsigned long zoneD = getWord(neighborCollisions, 0x14, true) << 8;
        
        // if vector A lies within the zone
        if (vectA->X >= zoneX &&
            vectA->Y >= zoneY &&
            vectA->Z >= zoneZ &&
            vectA->X < (zoneX + zoneW) &&
            vectA->Y < (zoneY + zoneH) &&
            vectA->Z < (zoneZ + zoneD))
        {
          cspace zoneSpace;
          zoneSpace.xyz1.X = zoneX;
          zoneSpace.xyz1.Y = zoneY;
          zoneSpace.xyz1.Z = zoneZ;
          zoneSpace.xyz2.X = zoneX + zoneW;
          zoneSpace.xyz2.Y = zoneY + zoneH;
          zoneSpace.xyz2.Z = zoneZ + zoneD;
          
          unsigned short rootNode = getHword(neighborCollisions, 0x1E, true);
          unsigned short level    = 0;
          
          retval = findNode(neighborCollisions, rootNode, zoneSpace, vectA, vectB, level);

          break;
        }
      } while (count < neighborCount);
      
      if (count == neighborCount) { return; }
    }
  } while (!retval);

  return;
}  
Пример #10
0
void model_obj::loadVertices(entry *svtx, int frame, prim_alloc *prims)
{
  unsigned char *buffer = svtx->itemData[frame];
  
  //load the vertices/normals for this frame
  vertCount = getWord(buffer, 0, true);

  signed long offsetX = getWord(buffer, 0x8, true);
  signed long offsetY = getWord(buffer, 0xC, true);
  signed long offsetZ = getWord(buffer, 0x10, true);
  
  //**the game subtracts a default of 128 from the model coordinate offset  
  //(scaling here is also done to shift the sign to the appropriate position)
  signed short offsetXP = (signed short) ((offsetX - 128) * SCALE_OBJECT);
  signed short offsetYP = (signed short) ((offsetY - 128) * SCALE_OBJECT);
  signed short offsetZP = (signed short) ((offsetZ - 128) * SCALE_OBJECT);
 
  vertices  = prims->allocVertices(vertCount);
  normals   = prims->allocNormals(vertCount);
 
  #define SVTX_VERTICES 0x38
  
  for (int lp = 0; lp < vertCount; lp++)
  {
    unsigned long bufferOffset = lp * 6;
	
    //first grab AAZZYYXXCCBB values from binary model data
    unsigned long  CNXZYX  =  getWord(buffer, SVTX_VERTICES + bufferOffset, true);
    unsigned short CNZCNY  = getHword(buffer, SVTX_VERTICES + bufferOffset+4, true);
	
    //then separate appropriately, performing any additional scaling
    //like the game does before sending to the GTE
    unsigned short vertX = ((CNXZYX & 0x000000FF) >>  0) * SCALE_OBJECT;
    unsigned short vertY = ((CNXZYX & 0x0000FF00) >>  8) * SCALE_OBJECT;
    unsigned short vertZ = ((CNXZYX & 0x00FF0000) >> 16) * SCALE_OBJECT;
    
    signed char CNX = (CNXZYX & 0xFF000000) >> 24;
    signed char CNY = (CNZCNY & 0x00FF);
    signed char CNZ = (CNZCNY & 0xFF00) >> 8;

    //now calculate total vertex position
    signed short X = offsetXP + vertX;
    signed short Y = offsetYP + vertY;
    signed short Z = offsetZP + vertZ;
	
    //psx GTE reads these values as fixed point, gl as floats
    //do the appropriate conversions before storing so gl can interpret correctly
    vertices[lp].X = ((float)X * 8) / 0x1000;
    vertices[lp].Y = ((float)Y * 8) / 0x1000;
    vertices[lp].Z = ((float)Z * 8) / 0x1000;
   
    //pre-emptively sets the object to be drawn white if texture information is not found
    vertices[lp].Rf = 1.0;
    vertices[lp].Gf = 1.0;
    vertices[lp].Bf = 1.0;
	
    normals[lp].X = (float)CNX / (16);
    normals[lp].Y = (float)CNY / (16);
    normals[lp].Z = (float)CNZ / (16);
  }  
  
  //load the bound box for this frame
  signed long boundX1 = getWord(buffer, 0x14, true);
  signed long boundY1 = getWord(buffer, 0x18, true);
  signed long boundZ1 = getWord(buffer, 0x1C, true);
  
  signed long boundX2 = getWord(buffer, 0x20, true);
  signed long boundY2 = getWord(buffer, 0x24, true);
  signed long boundZ2 = getWord(buffer, 0x28, true);
  
  bound.P1.X = ((float)boundX1 * 8) / 0x1000;
  bound.P1.Y = ((float)boundY1 * 8) / 0x1000;
  bound.P1.Z = ((float)boundZ1 * 8) / 0x1000;
  
  bound.P2.X = ((float)boundX2 * 8) / 0x1000;
  bound.P2.Y = ((float)boundY2 * 8) / 0x1000;
  bound.P2.Z = ((float)boundZ2 * 8) / 0x1000;
}
Пример #11
0
void model_obj::loadPolygons(entry *tgeo, texture_buffer *texbuf, prim_alloc *prims)
{
  if (tgeo->itemData[0] == 0 || tgeo->itemSize[0] == 0) { return; }
  if (tgeo->itemData[1] == 0 || tgeo->itemSize[1] == 0) { return; }
  
  unsigned char *buffer       = tgeo->itemData[0];
  unsigned char *texInfoArray = tgeo->itemData[0] + 0x14;
  
  //or -are- these actually scale values?
  //where are these used in the assembly?
  unsigned long scaleX = getWord(buffer, 0x4, true);
  unsigned long scaleY = getWord(buffer, 0x8, true);
  unsigned long scaleZ = getWord(buffer, 0xC, true);
    
  polyCount    = getWord(buffer, 0, true);
  polyTexCount = 0;

  vertex *vertex_list = vertices;
  fvector *normal_list = normals;
  prims->preparepPolygons(vertices, normals, texcoords);
  
  vertex  *pVertex;
  fvector *pNormal;
  fpoint2 *pTexcoord;
    
  buffer = tgeo->itemData[1];
  for (int lp = 0; lp < polyCount; lp++)
  {
    unsigned long bufferOffset = lp * 8;

    unsigned short flagTex       = getHword(buffer, bufferOffset+6, true);
    unsigned short texInfoOffset = (flagTex & 0x7FFF);

    unsigned long texInfoA  = getWord(texInfoArray, texInfoOffset*4, true);
    bool textured           = (texInfoA >> 31) & 1;
   
    if (textured)
    {          
      prims->allocpPolygon(pVertex, pNormal, pTexcoord);  

      unsigned short aOffset = getHword(buffer, bufferOffset+0, true);
      unsigned short bOffset = getHword(buffer, bufferOffset+2, true);
      unsigned short cOffset = getHword(buffer, bufferOffset+4, true);

      pVertex[0] = vertex_list[(aOffset/6)];
      pVertex[1] = vertex_list[(bOffset/6)];
      pVertex[2] = vertex_list[(cOffset/6)];
      pNormal[0] = normal_list[(aOffset/6)];
      pNormal[1] = normal_list[(bOffset/6)];
      pNormal[2] = normal_list[(cOffset/6)];
      
      unsigned char modelFlag      = (flagTex & 0x8000) >> 15;
      unsigned short texInfoOffset = (flagTex & 0x7FFF);
    
      unsigned char semiTrans = (texInfoA >> 29) & 3;
           
      unsigned long texEID   = getWord(texInfoArray, (texInfoOffset*4)+4, true); 
      unsigned long texInfoB = getWord(texInfoArray, (texInfoOffset*4)+8, true);
	  
      unsigned short texCoordsOffset = ((texInfoB >> 22) & 0x3FF);
      unsigned short colorMode       = ((texInfoB >> 20) & 3);
      unsigned short section128      = ((texInfoB >> 18) & 3);
    
      //unsigned short offsetX = ((texInfoB >> 10) & 0xF8) >> colorMode;  //multiple of 4 or else, varies for cmode
      //unsigned short offsetY = (texInfoB & 0x1F) << 2; 
      unsigned short offsetX = ((texInfoB >> 13) & 0x1F);  
      unsigned short offsetY =         (texInfoB & 0x1F); 
        
      unsigned char clutIndex   = (texInfoB >> 6) & 0x7F;
      unsigned char clutPalette = (texInfoA >> 24) & 0xF;  
      
      textureEntry texEntry;
      texEntry.coords      = texCoordsOffset;
      texEntry.colorMode   = colorMode;
      texEntry.sect128     = section128;
      texEntry.offsetX     = offsetX;
      texEntry.offsetY     = offsetY;
      texEntry.clutIndex   = clutIndex;
      texEntry.clutPalette = clutPalette;
      texEntry.chunkIndex  = texbuf->getTextureChunk(texEID);
     
      texture *tex = texbuf->getTexture(&texEntry);
      
      pTexcoord[0] = tex->coords.A;
      pTexcoord[1] = tex->coords.B;
      pTexcoord[2] = tex->coords.C;

      polyTexCount++;
    }
  }  
    
  polyNonCount = 0;
  
  for (int lp = 0; lp < polyCount; lp++)
  {
    unsigned long bufferOffset = lp * 8;
    
    unsigned short flagTex       = getHword(buffer, bufferOffset+6, true);
    unsigned short texInfoOffset = (flagTex & 0x7FFF);
    
    unsigned long texInfoA = getWord(texInfoArray, texInfoOffset*4, true);
    bool textured          = (texInfoA >> 31) & 1;
   
    if (!textured)
    {          
      prims->allocpPolygon(pVertex, pNormal); 

      unsigned short aOffset = getHword(buffer, bufferOffset+0, true);
      unsigned short bOffset = getHword(buffer, bufferOffset+2, true);
      unsigned short cOffset = getHword(buffer, bufferOffset+4, true);
 
      pVertex[0] = vertex_list[(aOffset/6)];
      pVertex[1] = vertex_list[(bOffset/6)];
      pVertex[2] = vertex_list[(cOffset/6)];
      pNormal[0] = normal_list[(aOffset/6)];
      pNormal[1] = normal_list[(bOffset/6)];
      pNormal[2] = normal_list[(cOffset/6)];

      unsigned char R = (texInfoA >>  0) & 0xFF;
      unsigned char G = (texInfoA >>  8) & 0xFF;
      unsigned char B = (texInfoA >> 16) & 0xFF;
      
      pVertex[0].Rf = (float)R/256;
      pVertex[0].Gf = (float)G/256;
      pVertex[0].Bf = (float)B/256;
      pVertex[1].Rf = (float)R/256;
      pVertex[1].Gf = (float)G/256;
      pVertex[1].Bf = (float)B/256;
      pVertex[2].Rf = (float)R/256;
      pVertex[2].Gf = (float)G/256;
      pVertex[2].Bf = (float)B/256;      

      polyNonCount++;
    }
  }