Files
PhysX4.1/physx/source/physxextensions/src/serialization/Binary/SnConvX_Output.cpp
2025-11-28 23:13:44 +05:30

493 lines
12 KiB
C++

//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#include "foundation/PxIO.h"
#include "foundation/PxErrorCallback.h"
#include "SnConvX.h"
#if PX_VC
#pragma warning(disable:4389) // signed/unsigned mismatch
#endif
using namespace physx;
void Sn::ConvX::setNullPtr(bool flag)
{
mNullPtr = flag;
}
void Sn::ConvX::setNoOutput(bool flag)
{
mNoOutput = flag;
}
bool Sn::ConvX::initOutput(PxOutputStream& targetStream)
{
mOutStream = &targetStream;
mOutputSize = 0;
mNullPtr = false;
mNoOutput = false;
const MetaData* srcMetaData = getBinaryMetaData(META_DATA_SRC);
PX_ASSERT(srcMetaData);
const MetaData* dstMetaData = getBinaryMetaData(META_DATA_DST);
PX_ASSERT(dstMetaData);
mSrcPtrSize = srcMetaData->getPtrSize();
mDstPtrSize = dstMetaData->getPtrSize();
PX_ASSERT(!srcMetaData->getFlip());
mMustFlip = dstMetaData->getFlip();
return true;
}
void Sn::ConvX::closeOutput()
{
mOutStream = NULL;
}
int Sn::ConvX::getCurrentOutputSize()
{
return mOutputSize;
}
void Sn::ConvX::output(short value)
{
if(mNoOutput)
return;
if(mMustFlip)
flip(value);
PX_ASSERT(mOutStream);
const size_t size = mOutStream->write(&value, 2);
PX_ASSERT(size==2);
mOutputSize += int(size);
}
void Sn::ConvX::output(int value)
{
if(mNoOutput)
return;
if(mMustFlip)
flip(value);
PX_ASSERT(mOutStream);
const size_t size = mOutStream->write(&value, 4);
PX_ASSERT(size==4);
mOutputSize += int(size);
}
//ntohll is a macro on apple yosemite
static PxU64 ntohll_internal(const PxU64 value)
{
union
{
PxU64 ull;
PxU8 c[8];
} x;
x.ull = value;
PxU8 c = 0;
c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c;
c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c;
c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c;
c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c;
return x.ull;
}
void Sn::ConvX::output(PxU64 value)
{
if(mNoOutput)
return;
if(mMustFlip)
// flip(value);
value = ntohll_internal(value);
PX_ASSERT(mOutStream);
const size_t size = mOutStream->write(&value, 8);
PX_ASSERT(size==8);
mOutputSize += int(size);
}
void Sn::ConvX::output(const char* buffer, int nbBytes)
{
if(mNoOutput)
return;
if(!nbBytes)
return;
PX_ASSERT(mOutStream);
const PxU32 size = mOutStream->write(buffer, PxU32(nbBytes));
PX_ASSERT(size== PxU32(nbBytes));
mOutputSize += int(size);
}
void Sn::ConvX::convert8(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
{
(void)dstEntry;
if(mNoOutput)
return;
PX_ASSERT(entry.mSize==1*entry.mCount);
PX_ASSERT(mOutStream);
PX_ASSERT(entry.mSize==dstEntry.mSize);
const PxU32 size = mOutStream->write(src, PxU32(entry.mSize));
PX_ASSERT(size== PxU32(entry.mSize));
mOutputSize += int(size);
}
// This is called to convert auto-generated "padding bytes" (or so we think).
// We use a special converter to check the input bytes and issue warnings when it doesn't look like padding
void Sn::ConvX::convertPad8(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
{
(void)dstEntry;
(void)src;
if(mNoOutput)
return;
PX_ASSERT(entry.mSize);
PX_ASSERT(entry.mSize==1*entry.mCount);
PX_ASSERT(mOutStream);
PX_ASSERT(entry.mSize==dstEntry.mSize);
// PT: we don't output the source data on purpose, to catch missing meta-data
// sschirm: changed that to 0xcd, so we can mark the output as "having marked pads"
const unsigned char b = 0xcd;
for(int i=0;i<entry.mSize;i++)
{
const size_t size = mOutStream->write(&b, 1);
(void)size;
}
mOutputSize += entry.mSize;
}
void Sn::ConvX::convert16(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
{
(void)dstEntry;
if(mNoOutput)
return;
PX_ASSERT(entry.mSize==int(sizeof(short)*entry.mCount));
PX_ASSERT(mOutStream);
PX_ASSERT(entry.mSize==dstEntry.mSize);
const short* data = reinterpret_cast<const short*>(src);
for(int i=0;i<entry.mCount;i++)
{
short value = *data++;
if(mMustFlip)
flip(value);
const size_t size = mOutStream->write(&value, sizeof(short));
PX_ASSERT(size==sizeof(short));
mOutputSize += int(size);
}
}
void Sn::ConvX::convert32(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
{
(void)dstEntry;
if(mNoOutput)
return;
PX_ASSERT(entry.mSize==int(sizeof(int)*entry.mCount));
PX_ASSERT(mOutStream);
PX_ASSERT(entry.mSize==dstEntry.mSize);
const int* data = reinterpret_cast<const int*>(src);
for(int i=0;i<entry.mCount;i++)
{
int value = *data++;
if(mMustFlip)
flip(value);
const size_t size = mOutStream->write(&value, sizeof(int));
PX_ASSERT(size==sizeof(int));
mOutputSize += int(size);
}
}
void Sn::ConvX::convert64(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
{
(void)dstEntry;
if(mNoOutput)
return;
PX_ASSERT(entry.mSize==int(sizeof(PxU64)*entry.mCount));
PX_ASSERT(mOutStream);
PX_ASSERT(entry.mSize==dstEntry.mSize);
const PxU64* data = reinterpret_cast<const PxU64*>(src);
for(int i=0;i<entry.mCount;i++)
{
PxU64 value = *data++;
if(mMustFlip)
value = ntohll_internal(value);
const size_t size = mOutStream->write(&value, sizeof(PxU64));
PX_ASSERT(size==sizeof(PxU64));
mOutputSize += int(size);
}
}
void Sn::ConvX::convertFloat(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
{
(void)dstEntry;
if(mNoOutput)
return;
PX_ASSERT(entry.mSize==int(sizeof(float)*entry.mCount));
PX_ASSERT(mOutStream);
PX_ASSERT(entry.mSize==dstEntry.mSize);
const float* data = reinterpret_cast<const float*>(src);
for(int i=0;i<entry.mCount;i++)
{
float value = *data++;
if(mMustFlip)
flip(value);
const size_t size = mOutStream->write(&value, sizeof(float));
PX_ASSERT(size==sizeof(float));
mOutputSize += int(size);
}
}
void Sn::ConvX::convertPtr(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
{
(void)dstEntry;
if(mNoOutput)
return;
PX_ASSERT(entry.mSize==mSrcPtrSize*entry.mCount);
PX_ASSERT(mOutStream);
char buffer[16];
for(int i=0;i<entry.mCount;i++)
{
PxU64 testValue=0;
// Src pointer can be 4 or 8 bytes so we can't use "void*" here
if(mSrcPtrSize==4)
{
PX_ASSERT(sizeof(PxU32)==4);
const PxU32* data = reinterpret_cast<const PxU32*>(src);
PxU32 value = *data++;
src = reinterpret_cast<const char*>(data);
if(mPointerActiveRemap)
{
PxU32 ref;
if(mPointerActiveRemap->getObjectRef(value, ref))
{
value = ref;
}
else if(value)
{
// all pointers not in the pointer remap table get set as 0x12345678, this also applies to PhysX name properties (mName)
value=0x12345678;
}
}
else
{
//we should only get here during convertReferenceTables to build up the pointer map
PxU32 ref;
if (mPointerRemap.getObjectRef(value, ref))
{
value = ref;
}
else if(value)
{
const PxU32 remappedRef = 0x80000000 | (mPointerRemapCounter++ +1);
mPointerRemap.setObjectRef(value, remappedRef);
value = remappedRef;
}
}
if(mMustFlip)
flip(value);
if(mNullPtr)
value = 0;
*reinterpret_cast<PxU32*>(buffer) = value;
}
else
{
PX_ASSERT(mSrcPtrSize==8);
PX_ASSERT(sizeof(PxU64)==8);
const PxU64* data = reinterpret_cast<const PxU64*>(src);
PxU64 value = *data++;
src = reinterpret_cast<const char*>(data);
if(mPointerActiveRemap)
{
PxU32 ref;
if(mPointerActiveRemap->getObjectRef(value, ref))
{
value = ref;
}
else if(value)
{
// all pointers not in the pointer remap table get set as 0x12345678, this also applies to PhysX name properties (mName)
value=0x12345678;
}
}
else
{
//we should only get here during convertReferenceTables to build up the pointer map
PxU32 ref;
if (mPointerRemap.getObjectRef(value, ref))
{
value = ref;
}
else if(value)
{
const PxU32 remappedRef = 0x80000000 | (mPointerRemapCounter++ +1);
mPointerRemap.setObjectRef(value, remappedRef);
value = remappedRef;
}
}
if(mNullPtr)
value = 0;
testValue = value;
*reinterpret_cast<PxU64*>(buffer) = value;
}
if(mSrcPtrSize==mDstPtrSize)
{
const size_t size = mOutStream->write(buffer, PxU32(mSrcPtrSize));
PX_ASSERT(size==PxU32(mSrcPtrSize));
mOutputSize += int(size);
}
else
{
if(mDstPtrSize>mSrcPtrSize)
{
// 32bit to 64bit
PX_ASSERT(mDstPtrSize==8);
PX_ASSERT(mSrcPtrSize==4);
// We need to output the lower 32bits first for PC. Might be different on a 64bit console....
// Output src ptr for the lower 32bits
const size_t size = mOutStream->write(buffer, PxU32(mSrcPtrSize));
PX_ASSERT(size==PxU32(mSrcPtrSize));
mOutputSize += int(size);
// Output zeros for the higher 32bits
const int zero = 0;
const size_t size0 = mOutStream->write(&zero, 4);
PX_ASSERT(size0==4);
mOutputSize += int(size0);
}
else
{
// 64bit to 32bit
PX_ASSERT(mSrcPtrSize==8);
PX_ASSERT(mDstPtrSize==4);
// Not sure how we can safely convert 64bit ptrs to 32bit... just drop the high 32 bits?!?
PxU32 ptr32 = *reinterpret_cast<PxU32*>(buffer);
(void)ptr32;
PxU32 ptr32b = PxU32(testValue);
(void)ptr32b;
if(mMustFlip)
flip(ptr32b);
// Output src ptr for the lower 32bits
const size_t size = mOutStream->write(&ptr32b, 4);
PX_ASSERT(size==4);
mOutputSize += int(size);
}
}
}
}
void Sn::ConvX::convertHandle16(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
{
(void)dstEntry;
if(mNoOutput)
return;
PX_ASSERT(strcmp(entry.mType, "PxU16") == 0);
PX_ASSERT(entry.mSize==dstEntry.mSize);
PX_ASSERT(mOutStream);
const PxU16* handles = reinterpret_cast<const PxU16*>(src);
for(int i=0;i<entry.mCount;i++)
{
PxU16 value = handles[i];
if (mHandle16ActiveRemap)
{
PxU16 ref;
bool isMapped = mHandle16ActiveRemap->getObjectRef(value, ref);
PX_UNUSED(isMapped);
PX_ASSERT(isMapped);
value = ref;
}
else
{
//we should only get here during convertReferenceTables to build up the pointer map
PxU16 ref;
if (mHandle16Remap.getObjectRef(value, ref))
{
value = ref;
}
else
{
const PxU16 remappedRef = mHandle16RemapCounter++;
mHandle16Remap.setObjectRef(value, remappedRef);
value = remappedRef;
}
}
if(mMustFlip)
flip(value);
const size_t size = mOutStream->write(&value, sizeof(PxU16));
PX_UNUSED(size);
PX_ASSERT(size==sizeof(PxU16));
mOutputSize += sizeof(PxU16);
}
}