Implemented SCAN cooker

This commit is contained in:
Aruki
2019-01-30 13:48:05 -07:00
parent e6702d09e8
commit 1e997dac46
9 changed files with 206 additions and 18 deletions

View File

@@ -4,6 +4,7 @@
#include "CAreaCooker.h"
#include "CModelCooker.h"
#include "CPoiToWorldCooker.h"
#include "CScanCooker.h"
#include "CStringCooker.h"
#include "CWorldCooker.h"
@@ -25,6 +26,7 @@ public:
{
case EResourceType::Area: return CAreaCooker::CookMREA((CGameArea*) pRes, rOutput);
case EResourceType::Model: return CModelCooker::CookCMDL((CModel*) pRes, rOutput);
case EResourceType::Scan: return CScanCooker::CookSCAN((CScan*) pRes, rOutput);
case EResourceType::StaticGeometryMap: return CPoiToWorldCooker::CookEGMC((CPoiToWorld*) pRes, rOutput);
case EResourceType::StringTable: return CStringCooker::CookSTRG((CStringTable*) pRes, rOutput);
case EResourceType::Tweaks: return CTweakCooker::CookCTWK((CTweakData*) pRes, rOutput);

View File

@@ -0,0 +1,63 @@
#include "CScanCooker.h"
#include "Core/Resource/Cooker/CScriptCooker.h"
#include "Core/GameProject/DependencyListBuilders.h"
bool CScanCooker::CookSCAN(CScan* pScan, IOutputStream& SCAN)
{
// File header
if (pScan->Game() <= EGame::Prime)
{
// We currently do not support cooking for the MP1 demo build
ASSERT( pScan->Game() != EGame::PrimeDemo );
SCAN.WriteLong( 5 ); // Version number; must be 5
SCAN.WriteLong( 0x0BADBEEF ); // SCAN magic
CStructRef ScanProperties = pScan->ScanData();
CScriptCooker Cooker(pScan->Game());
Cooker.WriteProperty(SCAN, ScanProperties.Property(), ScanProperties.DataPointer(), true);
}
else
{
SCAN.WriteFourCC( FOURCC('SCAN') ); // SCAN magic
SCAN.WriteLong( 2 ); // Version number; must be 2
SCAN.WriteByte( 1 ); // Layer version number; must be 1
SCAN.WriteLong( 1 ); // Instance count
// Scans in MP2/3 are saved with the script object data format
// Write a dummy script object header here
SCAN.WriteLong( FOURCC('SNFO') ); // ScannableObjectInfo object ID
uint ScanInstanceSizeOffset = SCAN.Tell();
SCAN.WriteShort( 0 ); // Object size
SCAN.WriteLong( 0 ); // Instance ID
SCAN.WriteShort( 0 ); // Link count
CStructRef ScanProperties = pScan->ScanData();
CScriptCooker Cooker(pScan->Game());
Cooker.WriteProperty(SCAN, ScanProperties.Property(), ScanProperties.DataPointer(), false);
uint ScanInstanceEnd = SCAN.Tell();
uint ScanInstanceSize = ScanInstanceEnd - ScanInstanceSizeOffset - 2;
SCAN.GoTo(ScanInstanceSizeOffset);
SCAN.WriteShort( (uint16) ScanInstanceSize );
SCAN.GoTo(ScanInstanceEnd);
// Write dependency list
// @todo this output may not be 100% correct. Some dependencies seem to be conditionally excluded in base game.
// This may cause some assets to be unnecessarily loaded into memory ingame.
std::vector<CAssetID> Dependencies;
CAssetDependencyListBuilder Builder(pScan->Entry());
Builder.BuildDependencyList(Dependencies);
SCAN.WriteLong(Dependencies.size());
for (const CAssetID& kID : Dependencies)
{
CResourceEntry* pEntry = pScan->Entry()->ResourceStore()->FindEntry(kID);
ASSERT( pEntry != nullptr );
pEntry->CookedExtension().Write(SCAN);
kID.Write(SCAN);
}
}
return true;
}

View File

@@ -0,0 +1,15 @@
#ifndef CSCANCOOKER_H
#define CSCANCOOKER_H
#include "Core/Resource/Scan/CScan.h"
/** Cooker class for writing game-compatible SCAN assets */
class CScanCooker
{
CScanCooker() {}
public:
static bool CookSCAN(CScan* pScan, IOutputStream& SCAN);
};
#endif // CSCANCOOKER_H