the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 682 lines 19 kB view raw
1#include "stdafx.h" 2#include "FileHeader.h" 3 4//#define _DEBUG_FILE_HEADER 5 6FileHeader::FileHeader() 7{ 8 lastFile = NULL; 9 m_saveVersion = 0; 10 11 // New saves should have an original version set to the latest version. This will be overridden when we load a save 12 m_originalSaveVersion = SAVE_FILE_VERSION_NUMBER; 13 m_savePlatform = SAVE_FILE_PLATFORM_LOCAL; 14 m_saveEndian = m_localEndian; 15} 16 17FileHeader::~FileHeader() 18{ 19 for( unsigned int i = 0; i < fileTable.size(); ++i ) 20 { 21 delete fileTable[i]; 22 } 23} 24 25FileEntry *FileHeader::AddFile( const wstring &name, unsigned int length /* = 0 */ ) 26{ 27 assert( name.length() < 64 ); 28 29 wchar_t filename[64]; 30 memset( &filename, 0, sizeof( wchar_t ) * 64 ); 31 memcpy( &filename, name.c_str(), min( sizeof( wchar_t ) * 64, sizeof( wchar_t ) * name.length() ) ); 32 33 // Would a map be more efficient? Our file tables probably won't be very big so better to avoid hashing all the time? 34 // Does the file exist? 35 for( unsigned int i = 0; i < fileTable.size(); ++i ) 36 { 37 if( wcscmp( fileTable[i]->data.filename, filename ) == 0 ) 38 { 39 // If so, return it 40 return fileTable[i]; 41 } 42 } 43 44 // Else, add it to our file table 45 fileTable.push_back( new FileEntry( filename, length, GetStartOfNextData() ) ); 46 lastFile = fileTable[ fileTable.size() - 1 ]; 47 return lastFile; 48} 49 50void FileHeader::RemoveFile( FileEntry *file ) 51{ 52 if( file == NULL ) return; 53 54 AdjustStartOffsets(file, file->getFileSize(), true); 55 56 AUTO_VAR(it, find(fileTable.begin(), fileTable.end(),file)); 57 58 if( it < fileTable.end() ) 59 { 60 fileTable.erase( it ); 61 } 62 63#ifndef _CONTENT_PACKAGE 64 wprintf(L"Removed file %ls\n", file->data.filename); 65#endif 66 67 delete file; 68} 69 70void FileHeader::WriteHeader( LPVOID saveMem ) 71{ 72 unsigned int headerOffset = GetStartOfNextData(); 73 74 // 4J Changed for save version 2 to be the number of files rather than the size in bytes 75 unsigned int headerSize = (int)(fileTable.size()); 76 77 //DWORD numberOfBytesWritten = 0; 78 79 // Write the offset of the header 80 //assert(numberOfBytesWritten == 4); 81 int *begin = (int *)saveMem; 82#ifdef __PSVITA__ 83 VirtualCopyTo(begin, &headerOffset, sizeof(headerOffset)); 84#else 85 *begin = headerOffset; 86#endif 87 88 // Write the size of the header 89 //assert(numberOfBytesWritten == 4); 90#ifdef __PSVITA__ 91 VirtualCopyTo(begin + 1, &headerSize, sizeof(headerSize)); 92#else 93 *(begin + 1) = headerSize; 94#endif 95 96 short *versions = (short *)(begin + 2); 97 // Write the original version number 98#ifdef __PSVITA__ 99 VirtualCopyTo(versions, &m_originalSaveVersion, sizeof(m_originalSaveVersion)); 100#else 101 *versions = m_originalSaveVersion; 102#endif 103 104 // Write the version number 105 short versionNumber = SAVE_FILE_VERSION_NUMBER; 106 //assert(numberOfBytesWritten == 4); 107 //*(begin + 2) = versionNumber; 108#ifdef __PSVITA__ 109 VirtualCopyTo(versions + 1, &versionNumber, sizeof(versionNumber)); 110#else 111 *(versions + 1) = versionNumber; 112#endif 113 114#ifdef _DEBUG_FILE_HEADER 115 app.DebugPrintf("Write save file with original version: %d, and current version %d\n", m_originalSaveVersion, versionNumber); 116#endif 117 118 char *headerPosition = (char *)saveMem + headerOffset; 119 120#ifdef _DEBUG_FILE_HEADER 121 app.DebugPrintf("\n\nWrite file Header: Offset = %d, Size = %d\n", headerOffset, headerSize); 122#endif 123 124 // Write the header 125 for( unsigned int i = 0; i < fileTable.size(); ++i ) 126 { 127 //wprintf(L"File: %ls, Start = %d, Length = %d, End = %d\n", fileTable[i]->data.filename, fileTable[i]->data.startOffset, fileTable[i]->data.length, fileTable[i]->data.startOffset + fileTable[i]->data.length); 128#ifdef __PSVITA__ 129 VirtualCopyTo((void *)headerPosition, &fileTable[i]->data, sizeof(FileEntrySaveData)); 130#else 131 memcpy( (void *)headerPosition, &fileTable[i]->data, sizeof(FileEntrySaveData) ); 132#endif 133 //assert(numberOfBytesWritten == sizeof(FileEntrySaveData)); 134 headerPosition += sizeof(FileEntrySaveData); 135 } 136} 137 138void FileHeader::ReadHeader( LPVOID saveMem, ESavePlatform plat /*= SAVE_FILE_PLATFORM_LOCAL */ ) 139{ 140 unsigned int headerOffset; 141 unsigned int headerSize; 142 143 m_savePlatform = plat; 144 145 switch(m_savePlatform) 146 { 147 case SAVE_FILE_PLATFORM_X360: 148 case SAVE_FILE_PLATFORM_PS3: 149 m_saveEndian = BIGENDIAN; 150 break; 151 case SAVE_FILE_PLATFORM_XBONE: 152 case SAVE_FILE_PLATFORM_WIN64: 153 case SAVE_FILE_PLATFORM_PS4: 154 case SAVE_FILE_PLATFORM_PSVITA: 155 m_saveEndian = LITTLEENDIAN; 156 break; 157 default: 158 assert(0); 159 m_savePlatform = SAVE_FILE_PLATFORM_LOCAL; 160 m_saveEndian = m_localEndian; 161 break; 162 } 163 164 165 // Read the offset of the header 166 //assert(numberOfBytesRead == 4); 167 int *begin = (int *)saveMem; 168#ifdef __PSVITA__ 169 VirtualCopyFrom(&headerOffset, begin, sizeof(headerOffset)); 170#else 171 headerOffset = *begin; 172#endif 173 if(isSaveEndianDifferent()) System::ReverseULONG(&headerOffset); 174 175 // Read the size of the header 176 //assert(numberOfBytesRead == 4); 177#ifdef __PSVITA__ 178 VirtualCopyFrom(&headerSize, begin + 1, sizeof(headerSize)); 179#else 180 headerSize = *(begin + 1); 181#endif 182 if(isSaveEndianDifferent()) System::ReverseULONG(&headerSize); 183 184 185 short *versions = (short *)(begin + 2); 186 // Read the original save version number 187#ifdef __PSVITA__ 188 VirtualCopyFrom(&m_originalSaveVersion, versions, sizeof(m_originalSaveVersion)); 189#else 190 m_originalSaveVersion = *(versions); 191#endif 192 if(isSaveEndianDifferent()) System::ReverseSHORT(&m_originalSaveVersion); 193 194 // Read the save version number 195 //m_saveVersion = *(begin + 2); 196#ifdef __PSVITA__ 197 VirtualCopyFrom(&m_saveVersion, versions + 1, sizeof(m_saveVersion)); 198#else 199 m_saveVersion = *(versions + 1); 200#endif 201 if(isSaveEndianDifferent()) System::ReverseSHORT(&m_saveVersion); 202 203#ifdef _DEBUG_FILE_HEADER 204 app.DebugPrintf("Read save file with orignal version: %d, and current version %d\n", m_originalSaveVersion, m_saveVersion); 205 app.DebugPrintf("\n\nRead file Header: Offset = %d, Size = %d\n", headerOffset, headerSize); 206#endif 207 208 char *headerPosition = (char *)saveMem + headerOffset; 209 210 switch( m_saveVersion ) 211 { 212 //case SAVE_FILE_VERSION_NUMBER: 213 //case 8: // 4J Stu - SAVE_FILE_VERSION_NUMBER 2,3,4,5,6,7,8 are the same, but: 214 // : Bumped it to 3 in TU5 to force older builds (ie 0062) to generate a new world when trying to load new saves 215 // : Bumped it to 4 in TU9 to delete versions of The End that were generated in builds prior to TU9 216 // : Bumped it to 5 in TU9 to update the map data that was only using 1 bit to determine dimension 217 // : Bumped it to 6 for PS3 v1 to update map data mappings to use larger PlayerUID 218 // : Bumped it to 7 for Durango v1 to update map data mappings to use string based PlayerUID 219 // : Bumped it to 8 for Durango v1 when to save the chunks in a different compressed format 220 case SAVE_FILE_VERSION_CHUNK_INHABITED_TIME: 221 case SAVE_FILE_VERSION_COMPRESSED_CHUNK_STORAGE: 222 case SAVE_FILE_VERSION_DURANGO_CHANGE_MAP_DATA_MAPPING_SIZE: 223 case SAVE_FILE_VERSION_CHANGE_MAP_DATA_MAPPING_SIZE: 224 case SAVE_FILE_VERSION_MOVED_STRONGHOLD: 225 case SAVE_FILE_VERSION_NEW_END: 226 case SAVE_FILE_VERSION_POST_LAUNCH: 227 case SAVE_FILE_VERSION_LAUNCH: 228 { 229 // Changes for save file version 2: 230 // headerSize is now a count of elements rather than a count of bytes 231 // The FileEntrySaveData struct has a lastModifiedTime member 232 233 // Read the header 234 FileEntrySaveData *fesdHeaderPosition = (FileEntrySaveData *)headerPosition; 235 for(unsigned int i = 0; i < headerSize; ++i) 236 { 237 FileEntry *entry = new FileEntry(); 238 //assert(numberOfBytesRead == sizeof(FileEntrySaveData)); 239 240#ifdef __PSVITA__ 241 VirtualCopyFrom( &entry->data, fesdHeaderPosition, sizeof(FileEntrySaveData) ); 242#else 243 memcpy( &entry->data, fesdHeaderPosition, sizeof(FileEntrySaveData) ); 244#endif 245 246 if(isSaveEndianDifferent()) 247 { 248 // Reverse bytes 249 System::ReverseWCHARA(entry->data.filename,64); 250 System::ReverseULONG(&entry->data.length); 251 System::ReverseULONG(&entry->data.startOffset); 252 System::ReverseULONGLONG(&entry->data.lastModifiedTime); 253 } 254 255 256 entry->currentFilePointer = entry->data.startOffset; 257 lastFile = entry; 258 fileTable.push_back( entry ); 259#ifdef _DEBUG_FILE_HEADER 260 app.DebugPrintf("File: %ls, Start = %d, Length = %d, End = %d, Timestamp = %lld\n", entry->data.filename, entry->data.startOffset, entry->data.length, entry->data.startOffset + entry->data.length, entry->data.lastModifiedTime); 261#endif 262 263 fesdHeaderPosition++; 264 } 265 } 266 break; 267 268 // Legacy save versions, with updated code to convert the FileEntrySaveData to the latest version 269 // 4J Stu - At time of writing, the tutorial save is V1 so need to keep this for compatibility 270 case SAVE_FILE_VERSION_PRE_LAUNCH: 271 { 272 // Read the header 273 // We can then make headerPosition a FileEntrySaveData pointer and just increment by one up to the number 274 unsigned int i = 0; 275 while( i < headerSize ) 276 { 277 FileEntry *entry = new FileEntry(); 278 //assert(numberOfBytesRead == sizeof(FileEntrySaveData)); 279 280#ifdef __PSVITA__ 281 VirtualCopyFrom( &entry->data, headerPosition, sizeof(FileEntrySaveDataV1) ); 282#else 283 memcpy( &entry->data, headerPosition, sizeof(FileEntrySaveDataV1) ); 284#endif 285 286 entry->currentFilePointer = entry->data.startOffset; 287 lastFile = entry; 288 fileTable.push_back( entry ); 289#ifdef _DEBUG_FILE_HEADER 290 app.DebugPrintf("File: %ls, Start = %d, Length = %d, End = %d\n", entry->data.filename, entry->data.startOffset, entry->data.length, entry->data.startOffset + entry->data.length); 291#endif 292 293 i += sizeof(FileEntrySaveDataV1); 294 headerPosition += sizeof(FileEntrySaveDataV1); 295 } 296 } 297 break; 298 default: 299#ifndef _CONTENT_PACKAGE 300 app.DebugPrintf("********** Invalid save version %d\n",m_saveVersion); 301 __debugbreak(); 302#endif 303 break; 304 } 305} 306 307unsigned int FileHeader::GetStartOfNextData() 308{ 309 // The first 4 bytes is the location of the header (the header itself is at the end of the file) 310 // Then 4 bytes for the size of the header 311 // Then 2 bytes for the version number at which this save was first generated 312 // Then 2 bytes for the version number that the save should now be at 313 unsigned int totalBytesSoFar = SAVE_FILE_HEADER_SIZE; 314 for( unsigned int i = 0; i < fileTable.size(); ++i ) 315 { 316 if( fileTable[i]->getFileSize() > 0 ) 317 totalBytesSoFar += fileTable[i]->getFileSize(); 318 } 319 return totalBytesSoFar; 320} 321 322unsigned int FileHeader::GetFileSize() 323{ 324 return GetStartOfNextData() + ( sizeof(FileEntrySaveData) * (unsigned int)fileTable.size() ); 325} 326 327void FileHeader::AdjustStartOffsets(FileEntry *file, DWORD nNumberOfBytesToWrite, bool subtract /*= false*/) 328{ 329 bool found = false; 330 for( unsigned int i = 0; i < fileTable.size(); ++i ) 331 { 332 if( found == true ) 333 { 334 if(subtract) 335 { 336 fileTable[i]->data.startOffset -= nNumberOfBytesToWrite; 337 fileTable[i]->currentFilePointer -= nNumberOfBytesToWrite; 338 } 339 else 340 { 341 fileTable[i]->data.startOffset += nNumberOfBytesToWrite; 342 fileTable[i]->currentFilePointer += nNumberOfBytesToWrite; 343 } 344 } 345 else if( fileTable[i] == file ) 346 { 347 found = true; 348 } 349 } 350} 351 352bool FileHeader::fileExists( const wstring &name ) 353{ 354 for( unsigned int i = 0; i < fileTable.size(); ++i ) 355 { 356 if( wcscmp( fileTable[i]->data.filename, name.c_str() ) == 0 ) 357 { 358 // If so, return it 359 return true; 360 } 361 } 362 return false; 363} 364 365vector<FileEntry *> *FileHeader::getFilesWithPrefix(const wstring &prefix) 366{ 367 vector<FileEntry *> *files = NULL; 368 369 for( unsigned int i = 0; i < fileTable.size(); ++i ) 370 { 371 if( wcsncmp( fileTable[i]->data.filename, prefix.c_str(), prefix.size() ) == 0 ) 372 { 373 if( files == NULL ) 374 { 375 files = new vector<FileEntry *>(); 376 } 377 378 files->push_back(fileTable[i]); 379 } 380 } 381 382 return files; 383} 384 385#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) 386 387static bool isHexChar(wchar_t wc) 388{ 389 if(wc >= L'0' && wc <= L'9') 390 return true; 391 if(wc >= L'a' && wc <= L'f') 392 return true; 393 return false; 394} 395static bool isHexString(wchar_t* ws, int size) 396{ 397 for(int i=0;i<size;i++) 398 { 399 if(!isHexChar(ws[i])) 400 return false; 401 } 402 return true; 403} 404static bool isDecimalChar(wchar_t wc) 405{ 406 if(wc >= L'0' && wc <= L'9') 407 return true; 408 return false; 409} 410static bool isDecimalString(wchar_t* ws, int size) 411{ 412 for(int i=0;i<size;i++) 413 { 414 if(!isDecimalChar(ws[i])) 415 return false; 416 } 417 return true; 418} 419static wchar_t* findFilenameStart(wchar_t* str) 420{ 421 // find the last forward slash in the filename, and return the pointer to the following character 422 wchar_t* filenameStart= str; 423 int len = wcslen(str); 424 for(int i=0;i<len;i++) 425 if(str[i] == L'/') 426 filenameStart = &str[i+1]; 427 return filenameStart; 428} 429 430wstring FileHeader::getPlayerDataFilenameForLoad(const PlayerUID& pUID) 431{ 432 wstring retVal = L""; 433 vector<FileEntry*>* pFiles = getDatFilesWithOnlineID(pUID); 434 if(!pFiles) 435 { 436 // we didn't find a matching online dat file, so look for an offline version 437 pFiles = getDatFilesWithMacAndUserID(pUID); 438 } 439 if(!pFiles) 440 { 441 // and we didn't find an offline file, so check if we're the primary user, and grab the primary file if we are 442 if(pUID.isPrimaryUser()) 443 { 444 pFiles= getDatFilesWithPrimaryUser(); 445 } 446 } 447 if(pFiles) 448 { 449 // we've got something to load 450// assert(pFiles->size() == 1); 451 retVal = pFiles->at(0)->data.filename; 452 delete pFiles; 453 } 454 return retVal; 455} 456 457wstring FileHeader::getPlayerDataFilenameForSave(const PlayerUID& pUID) 458{ 459 // check if we're online first 460 if(pUID.isSignedIntoPSN() == false) 461 { 462 // OK, we're not online, see if we can find another data file with matching mac and userID 463 vector<FileEntry*>* pFiles = getDatFilesWithMacAndUserID(pUID); 464 if(pFiles) 465 { 466 // we've found a previous save, use the filename from it, as it might have the online part too 467// assert(pFiles->size() == 1); 468 wstring retVal = pFiles->at(0)->data.filename; 469 delete pFiles; 470 return retVal; 471 } 472 } 473 474 // we're either online, or we can't find a previous save, so use the standard filename 475 wstring retVal = pUID.toString() + L".dat"; 476 return retVal; 477} 478 479 480vector<FileEntry *> *FileHeader::getValidPlayerDatFiles() 481{ 482 vector<FileEntry *> *files = NULL; 483 484 // find filenames that match this pattern 485 // P_5e7ff8372ea9_00000004_Mark_4J 486 487 for( unsigned int i = 0; i < fileTable.size(); ++i ) 488 { 489 wchar_t* filenameOnly = findFilenameStart(fileTable[i]->data.filename); 490 491 int nameLen = wcslen(filenameOnly); 492 if(nameLen <= 4) 493 continue; 494 495 // make sure it's a ".dat" file 496 if( wcsncmp( &filenameOnly[nameLen-4], L".dat", 4 ) != 0 ) 497 continue; 498 // make sure we start with "P_" or "N_" 499 if( ( wcsncmp(&filenameOnly[0], L"P_", 2) != 0 ) && ( wcsncmp( &filenameOnly[0], L"N_", 2 ) != 0 ) ) 500 continue; 501 //check the next 12 chars are hex 502 if(!isHexString(&filenameOnly[2], 12)) 503 continue; 504 // make sure character 14 is '_' 505 if(filenameOnly[14] != L'_') 506 continue; 507 //check the next 8 chars are decimal 508 if(!isDecimalString(&filenameOnly[15], 8)) 509 continue; 510 511 // if we get here, it must be a valid filename 512 if( files == NULL ) 513 { 514 files = new vector<FileEntry *>(); 515 } 516 files->push_back(fileTable[i]); 517 } 518 519 return files; 520} 521 522 523 524vector<FileEntry *> *FileHeader::getDatFilesWithOnlineID(const PlayerUID& pUID) 525{ 526 if(pUID.isSignedIntoPSN() == false) 527 return NULL; 528 529 vector<FileEntry *>* datFiles = getValidPlayerDatFiles(); 530 if(datFiles == NULL) 531 return NULL; 532 533 // we're looking for the online name from the pUID in these types of filenames - 534 // P_5e7ff8372ea9_00000004_Mark_4J 535 wchar_t onlineIDW[64]; 536 mbstowcs(onlineIDW, pUID.getOnlineID(), 64); 537 538 vector<FileEntry *> *files = NULL; 539 int onlineIDSize = wcslen(onlineIDW); 540 if(onlineIDSize == 0) 541 return NULL; 542 543 wcscat(onlineIDW, L".dat"); 544 545#ifdef __ORBIS__ 546 onlineIDSize = wcslen(onlineIDW); 547#else 548 static const int onlineIDStart = 24; // 24 characters into the filename 549#endif 550 551 char tempStr[128]; 552 for( unsigned int i = 0; i < datFiles->size(); ++i ) 553 { 554 wchar_t* filenameOnly = findFilenameStart(datFiles->at(i)->data.filename); 555 wcstombs(tempStr,filenameOnly, 128); 556 app.DebugPrintf("file : %s\n", tempStr); 557 558#ifdef __ORBIS__ 559 int onlineIDStart = wcslen(filenameOnly) - onlineIDSize; 560 if(onlineIDStart > 0) 561#else 562 if(wcslen(filenameOnly) > onlineIDStart) 563#endif 564 { 565 if(wcsncmp(&filenameOnly[onlineIDStart], onlineIDW, onlineIDSize) == 0) 566 { 567 if( files == NULL ) 568 { 569 files = new vector<FileEntry *>(); 570 } 571 files->push_back(datFiles->at(i)); 572 } 573 } 574 } 575 delete datFiles; 576 577 if(files) sort(files->begin(), files->end(), FileEntry::newestFirst ); 578 return files; 579} 580 581vector<FileEntry *> *FileHeader::getDatFilesWithMacAndUserID(const PlayerUID& pUID) 582{ 583 584 vector<FileEntry *>* datFiles = getValidPlayerDatFiles(); 585 if(datFiles == NULL) 586 return NULL; 587 588 // we're looking for the mac address and userIDfrom the pUID in these types of filenames - 589 // P_5e7ff8372ea9_00000004_Mark_4J 590 std::wstring macStr = pUID.macAddressStr(); 591 std::wstring userStr = pUID.userIDStr(); 592 const wchar_t* pMacStr = macStr.c_str(); 593 const wchar_t* pUserStr = userStr.c_str(); 594 595 vector<FileEntry *> *files = NULL; 596 static const int macAddrStart = 2; // 2 characters into the filename 597 static const int userIDStart = 15; // 15 characters into the filename 598 599 char tempStr[128]; 600 for( unsigned int i = 0; i < datFiles->size(); ++i ) 601 { 602 wchar_t* filenameOnly = findFilenameStart(datFiles->at(i)->data.filename); 603 wcstombs(tempStr,filenameOnly, 128); 604 app.DebugPrintf("file : %s\n", tempStr); 605 606 // check the mac address matches 607 if(wcsncmp(&filenameOnly[macAddrStart], pMacStr, macStr.size()) == 0) 608 { 609 // check the userID matches 610 if(wcsncmp(&filenameOnly[userIDStart], pUserStr, userStr.size()) == 0) 611 { 612 if( files == NULL ) 613 { 614 files = new vector<FileEntry *>(); 615 } 616 files->push_back(datFiles->at(i)); 617 } 618 } 619 } 620 delete datFiles; 621 if(files) sort(files->begin(), files->end(), FileEntry::newestFirst ); 622 return files; 623} 624 625 626vector<FileEntry *> *FileHeader::getDatFilesWithPrimaryUser() 627{ 628 629 vector<FileEntry *>* datFiles = getValidPlayerDatFiles(); 630 if(datFiles == NULL) 631 return NULL; 632 633 // we're just looking for filenames starting with "P_" in these types of filenames - 634 // P_5e7ff8372ea9_00000004_Mark_4J 635 vector<FileEntry *> *files = NULL; 636 637 char tempStr[128]; 638 for( unsigned int i = 0; i < datFiles->size(); ++i ) 639 { 640 wchar_t* filenameOnly = findFilenameStart(datFiles->at(i)->data.filename); 641 wcstombs(tempStr,filenameOnly, 128); 642 app.DebugPrintf("file : %s\n", tempStr); 643 644 // check for "P_" prefix 645 if(wcsncmp(&filenameOnly[0], L"P_", 2) == 0) 646 { 647 if( files == NULL ) 648 { 649 files = new vector<FileEntry *>(); 650 } 651 files->push_back(datFiles->at(i)); 652 } 653 } 654 delete datFiles; 655 if(files) sort(files->begin(), files->end(), FileEntry::newestFirst ); 656 return files; 657} 658#endif // __PS3__ || __ORBIS__ 659 660ByteOrder FileHeader::getEndian( ESavePlatform plat ) 661{ 662 ByteOrder platEndian; 663 switch(plat) 664 { 665 case SAVE_FILE_PLATFORM_X360: 666 case SAVE_FILE_PLATFORM_PS3: 667 return BIGENDIAN; 668 break; 669 670 case SAVE_FILE_PLATFORM_NONE: 671 case SAVE_FILE_PLATFORM_XBONE: 672 case SAVE_FILE_PLATFORM_PS4: 673 case SAVE_FILE_PLATFORM_PSVITA: 674 case SAVE_FILE_PLATFORM_WIN64: 675 return LITTLEENDIAN; 676 break; 677 default: 678 assert(0); 679 break; 680 } 681 return LITTLEENDIAN; 682}