mirror of
https://gitlab.com/shinovon/re3-symbian.git
synced 2026-05-23 01:57:21 +03:00
Initial commit
This commit is contained in:
commit
77cdaaf97e
827 changed files with 418745 additions and 0 deletions
678
vendor/librw/src/d3d/d3d8.cpp
vendored
Normal file
678
vendor/librw/src/d3d/d3d8.cpp
vendored
Normal file
|
|
@ -0,0 +1,678 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define WITH_D3D
|
||||
#include "../rwbase.h"
|
||||
#include "../rwerror.h"
|
||||
#include "../rwplg.h"
|
||||
#include "../rwpipeline.h"
|
||||
#include "../rwobjects.h"
|
||||
#include "../rwengine.h"
|
||||
#include "rwd3d.h"
|
||||
#include "rwd3d8.h"
|
||||
|
||||
#include "rwd3dimpl.h"
|
||||
|
||||
#define PLUGIN_ID 2
|
||||
|
||||
namespace rw {
|
||||
namespace d3d8 {
|
||||
using namespace d3d;
|
||||
|
||||
static void*
|
||||
driverOpen(void *o, int32, int32)
|
||||
{
|
||||
engine->driver[PLATFORM_D3D8]->defaultPipeline = makeDefaultPipeline();
|
||||
|
||||
engine->driver[PLATFORM_D3D8]->rasterNativeOffset = nativeRasterOffset;
|
||||
engine->driver[PLATFORM_D3D8]->rasterCreate = rasterCreate;
|
||||
engine->driver[PLATFORM_D3D8]->rasterLock = rasterLock;
|
||||
engine->driver[PLATFORM_D3D8]->rasterUnlock = rasterUnlock;
|
||||
engine->driver[PLATFORM_D3D8]->rasterNumLevels = rasterNumLevels;
|
||||
engine->driver[PLATFORM_D3D8]->imageFindRasterFormat = imageFindRasterFormat;
|
||||
engine->driver[PLATFORM_D3D8]->rasterFromImage = rasterFromImage;
|
||||
engine->driver[PLATFORM_D3D8]->rasterToImage = rasterToImage;
|
||||
return o;
|
||||
}
|
||||
|
||||
static void*
|
||||
driverClose(void *o, int32, int32)
|
||||
{
|
||||
return o;
|
||||
}
|
||||
|
||||
void
|
||||
registerPlatformPlugins(void)
|
||||
{
|
||||
Driver::registerPlugin(PLATFORM_D3D8, 0, PLATFORM_D3D8,
|
||||
driverOpen, driverClose);
|
||||
// shared between D3D8 and 9
|
||||
if(nativeRasterOffset == 0)
|
||||
registerNativeRaster();
|
||||
}
|
||||
|
||||
uint32
|
||||
makeFVFDeclaration(uint32 flags, int32 numTex)
|
||||
{
|
||||
uint32 fvf = 0x2;
|
||||
if(flags & Geometry::NORMALS)
|
||||
fvf |= 0x10;
|
||||
if(flags & Geometry::PRELIT)
|
||||
fvf |= 0x40;
|
||||
fvf |= numTex << 8;
|
||||
return fvf;
|
||||
}
|
||||
|
||||
int32
|
||||
getStride(uint32 flags, int32 numTex)
|
||||
{
|
||||
int32 stride = 12;
|
||||
if(flags & Geometry::NORMALS)
|
||||
stride += 12;;
|
||||
if(flags & Geometry::PRELIT)
|
||||
stride += 4;
|
||||
stride += numTex*8;
|
||||
return stride;
|
||||
}
|
||||
|
||||
void*
|
||||
destroyNativeData(void *object, int32, int32)
|
||||
{
|
||||
Geometry *geometry = (Geometry*)object;
|
||||
if(geometry->instData == nil ||
|
||||
geometry->instData->platform != PLATFORM_D3D8)
|
||||
return object;
|
||||
InstanceDataHeader *header =
|
||||
(InstanceDataHeader*)geometry->instData;
|
||||
geometry->instData = nil;
|
||||
InstanceData *inst = header->inst;
|
||||
for(uint32 i = 0; i < header->numMeshes; i++){
|
||||
destroyIndexBuffer(inst->indexBuffer);
|
||||
destroyVertexBuffer(inst->vertexBuffer);
|
||||
inst++;
|
||||
}
|
||||
rwFree(header->inst);
|
||||
rwFree(header);
|
||||
return object;
|
||||
}
|
||||
|
||||
Stream*
|
||||
readNativeData(Stream *stream, int32, void *object, int32, int32)
|
||||
{
|
||||
ASSERTLITTLE;
|
||||
Geometry *geometry = (Geometry*)object;
|
||||
uint32 platform;
|
||||
if(!findChunk(stream, ID_STRUCT, nil, nil)){
|
||||
RWERROR((ERR_CHUNK, "STRUCT"));
|
||||
return nil;
|
||||
}
|
||||
platform = stream->readU32();
|
||||
if(platform != PLATFORM_D3D8){
|
||||
RWERROR((ERR_PLATFORM, platform));
|
||||
return nil;
|
||||
}
|
||||
InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
|
||||
geometry->instData = header;
|
||||
header->platform = PLATFORM_D3D8;
|
||||
|
||||
int32 size = stream->readI32();
|
||||
uint8 *data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_GEOMETRY);
|
||||
stream->read8(data, size);
|
||||
uint8 *p = data;
|
||||
header->serialNumber = *(uint16*)p; p += 2;
|
||||
header->numMeshes = *(uint16*)p; p += 2;
|
||||
header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
|
||||
|
||||
InstanceData *inst = header->inst;
|
||||
for(uint32 i = 0; i < header->numMeshes; i++){
|
||||
inst->minVert = *(uint32*)p; p += 4;
|
||||
inst->stride = *(uint32*)p; p += 4;
|
||||
inst->numVertices = *(uint32*)p; p += 4;
|
||||
inst->numIndices = *(uint32*)p; p += 4;
|
||||
uint32 matid = *(uint32*)p; p += 4;
|
||||
inst->material = geometry->matList.materials[matid];
|
||||
inst->vertexShader = *(uint32*)p; p += 4;
|
||||
inst->primType = *(uint32*)p; p += 4;
|
||||
inst->indexBuffer = nil; p += 4;
|
||||
inst->vertexBuffer = nil; p += 4;
|
||||
inst->baseIndex = 0; p += 4;
|
||||
inst->vertexAlpha = *p++;
|
||||
inst->managed = 0; p++;
|
||||
inst->remapped = 0; p++; // TODO: really unused? and what's that anyway?
|
||||
inst++;
|
||||
}
|
||||
rwFree(data);
|
||||
|
||||
inst = header->inst;
|
||||
for(uint32 i = 0; i < header->numMeshes; i++){
|
||||
assert(inst->indexBuffer == nil);
|
||||
inst->indexBuffer = createIndexBuffer(inst->numIndices*2, false);
|
||||
uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
|
||||
stream->read8(indices, 2*inst->numIndices);
|
||||
unlockIndices(inst->indexBuffer);
|
||||
|
||||
inst->managed = 1;
|
||||
assert(inst->vertexBuffer == nil);
|
||||
inst->vertexBuffer = createVertexBuffer(inst->stride*inst->numVertices, 0, false);
|
||||
uint8 *verts = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
|
||||
stream->read8(verts, inst->stride*inst->numVertices);
|
||||
unlockVertices(inst->vertexBuffer);
|
||||
|
||||
inst++;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
Stream*
|
||||
writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
|
||||
{
|
||||
ASSERTLITTLE;
|
||||
Geometry *geometry = (Geometry*)object;
|
||||
writeChunkHeader(stream, ID_STRUCT, len-12);
|
||||
if(geometry->instData == nil ||
|
||||
geometry->instData->platform != PLATFORM_D3D8)
|
||||
return stream;
|
||||
stream->writeU32(PLATFORM_D3D8);
|
||||
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
|
||||
|
||||
int32 size = 4 + geometry->meshHeader->numMeshes*0x2C;
|
||||
uint8 *data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_GEOMETRY);
|
||||
stream->writeI32(size);
|
||||
uint8 *p = data;
|
||||
*(uint16*)p = header->serialNumber; p += 2;
|
||||
*(uint16*)p = header->numMeshes; p += 2;
|
||||
|
||||
InstanceData *inst = header->inst;
|
||||
for(uint32 i = 0; i < header->numMeshes; i++){
|
||||
*(uint32*)p = inst->minVert; p += 4;
|
||||
*(uint32*)p = inst->stride; p += 4;
|
||||
*(uint32*)p = inst->numVertices; p += 4;
|
||||
*(uint32*)p = inst->numIndices; p += 4;
|
||||
int32 matid = geometry->matList.findIndex(inst->material);
|
||||
*(int32*)p = matid; p += 4;
|
||||
*(uint32*)p = inst->vertexShader; p += 4;
|
||||
*(uint32*)p = inst->primType; p += 4;
|
||||
*(uint32*)p = 0; p += 4; // index buffer
|
||||
*(uint32*)p = 0; p += 4; // vertex buffer
|
||||
*(uint32*)p = inst->baseIndex; p += 4;
|
||||
*p++ = inst->vertexAlpha;
|
||||
*p++ = inst->managed;
|
||||
*p++ = inst->remapped;
|
||||
inst++;
|
||||
}
|
||||
stream->write8(data, size);
|
||||
rwFree(data);
|
||||
|
||||
inst = header->inst;
|
||||
for(uint32 i = 0; i < header->numMeshes; i++){
|
||||
uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
|
||||
stream->write8(indices, 2*inst->numIndices);
|
||||
unlockIndices(inst->indexBuffer);
|
||||
|
||||
uint8 *verts = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
|
||||
stream->write8(verts, inst->stride*inst->numVertices);
|
||||
unlockVertices(inst->vertexBuffer);
|
||||
inst++;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
int32
|
||||
getSizeNativeData(void *object, int32, int32)
|
||||
{
|
||||
Geometry *geometry = (Geometry*)object;
|
||||
if(geometry->instData == nil ||
|
||||
geometry->instData->platform != PLATFORM_D3D8)
|
||||
return 0;
|
||||
|
||||
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
|
||||
InstanceData *inst = header->inst;
|
||||
int32 size = 12 + 4 + 4 + 4 + header->numMeshes*0x2C;
|
||||
for(int32 i = 0; i < header->numMeshes; i++){
|
||||
size += inst->numIndices*2 + inst->numVertices*inst->stride;
|
||||
inst++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void
|
||||
registerNativeDataPlugin(void)
|
||||
{
|
||||
Geometry::registerPlugin(0, ID_NATIVEDATA,
|
||||
nil, destroyNativeData, nil);
|
||||
Geometry::registerPluginStream(ID_NATIVEDATA,
|
||||
readNativeData,
|
||||
writeNativeData,
|
||||
getSizeNativeData);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
|
||||
{
|
||||
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
|
||||
Geometry *geo = atomic->geometry;
|
||||
// TODO: allow for REINSTANCE
|
||||
if(geo->instData)
|
||||
return;
|
||||
InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
|
||||
MeshHeader *meshh = geo->meshHeader;
|
||||
geo->instData = header;
|
||||
header->platform = PLATFORM_D3D8;
|
||||
|
||||
header->serialNumber = meshh->serialNum;
|
||||
header->numMeshes = meshh->numMeshes;
|
||||
header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
|
||||
|
||||
InstanceData *inst = header->inst;
|
||||
Mesh *mesh = meshh->getMeshes();
|
||||
for(uint32 i = 0; i < header->numMeshes; i++){
|
||||
findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
|
||||
&inst->minVert, &inst->numVertices);
|
||||
inst->numIndices = mesh->numIndices;
|
||||
inst->material = mesh->material;
|
||||
inst->vertexShader = 0;
|
||||
inst->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
|
||||
inst->vertexBuffer = nil;
|
||||
inst->baseIndex = 0; // (maybe) not used by us
|
||||
inst->vertexAlpha = 0;
|
||||
inst->managed = 0;
|
||||
inst->remapped = 0;
|
||||
|
||||
inst->indexBuffer = createIndexBuffer(inst->numIndices*2, false);
|
||||
uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
|
||||
if(inst->minVert == 0)
|
||||
memcpy(indices, mesh->indices, inst->numIndices*2);
|
||||
else
|
||||
for(int32 j = 0; j < inst->numIndices; j++)
|
||||
indices[j] = mesh->indices[j] - inst->minVert;
|
||||
unlockIndices(inst->indexBuffer);
|
||||
|
||||
pipe->instanceCB(geo, inst);
|
||||
mesh++;
|
||||
inst++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
|
||||
{
|
||||
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
|
||||
Geometry *geo = atomic->geometry;
|
||||
if((geo->flags & Geometry::NATIVE) == 0)
|
||||
return;
|
||||
assert(geo->instData != nil);
|
||||
assert(geo->instData->platform == PLATFORM_D3D8);
|
||||
geo->numTriangles = geo->meshHeader->guessNumTriangles();
|
||||
geo->allocateData();
|
||||
geo->allocateMeshes(geo->meshHeader->numMeshes, geo->meshHeader->totalIndices, 0);
|
||||
|
||||
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
|
||||
InstanceData *inst = header->inst;
|
||||
Mesh *mesh = geo->meshHeader->getMeshes();
|
||||
for(uint32 i = 0; i < header->numMeshes; i++){
|
||||
uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0);
|
||||
if(inst->minVert == 0)
|
||||
memcpy(mesh->indices, indices, inst->numIndices*2);
|
||||
else
|
||||
for(int32 j = 0; j < inst->numIndices; j++)
|
||||
mesh->indices[j] = indices[j] + inst->minVert;
|
||||
unlockIndices(inst->indexBuffer);
|
||||
|
||||
pipe->uninstanceCB(geo, inst);
|
||||
mesh++;
|
||||
inst++;
|
||||
}
|
||||
geo->generateTriangles();
|
||||
geo->flags &= ~Geometry::NATIVE;
|
||||
destroyNativeData(geo, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
render(rw::ObjPipeline *rwpipe, Atomic *atomic)
|
||||
{
|
||||
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
|
||||
Geometry *geo = atomic->geometry;
|
||||
// TODO: allow for REINSTANCE
|
||||
if(geo->instData == nil)
|
||||
pipe->instance(atomic);
|
||||
assert(geo->instData != nil);
|
||||
assert(geo->instData->platform == PLATFORM_D3D8);
|
||||
if(pipe->renderCB)
|
||||
pipe->renderCB(atomic, (InstanceDataHeader*)geo->instData);
|
||||
}
|
||||
|
||||
void
|
||||
ObjPipeline::init(void)
|
||||
{
|
||||
this->rw::ObjPipeline::init(PLATFORM_D3D8);
|
||||
this->impl.instance = d3d8::instance;
|
||||
this->impl.uninstance = d3d8::uninstance;
|
||||
this->impl.render = d3d8::render;
|
||||
this->instanceCB = nil;
|
||||
this->uninstanceCB = nil;
|
||||
this->renderCB = nil;
|
||||
}
|
||||
|
||||
ObjPipeline*
|
||||
ObjPipeline::create(void)
|
||||
{
|
||||
ObjPipeline *pipe = rwNewT(ObjPipeline, 1, MEMDUR_GLOBAL);
|
||||
pipe->init();
|
||||
return pipe;
|
||||
}
|
||||
|
||||
void
|
||||
defaultInstanceCB(Geometry *geo, InstanceData *inst)
|
||||
{
|
||||
inst->vertexShader = makeFVFDeclaration(geo->flags, geo->numTexCoordSets);
|
||||
inst->stride = getStride(geo->flags, geo->numTexCoordSets);
|
||||
|
||||
assert(inst->vertexBuffer == nil);
|
||||
inst->vertexBuffer = createVertexBuffer(inst->numVertices*inst->stride,
|
||||
inst->vertexShader, false);
|
||||
inst->managed = 1;
|
||||
|
||||
uint8 *dst = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
|
||||
instV3d(VERT_FLOAT3, dst,
|
||||
&geo->morphTargets[0].vertices[inst->minVert],
|
||||
inst->numVertices, inst->stride);
|
||||
dst += 12;
|
||||
|
||||
if(geo->flags & Geometry::NORMALS){
|
||||
instV3d(VERT_FLOAT3, dst,
|
||||
&geo->morphTargets[0].normals[inst->minVert],
|
||||
inst->numVertices, inst->stride);
|
||||
dst += 12;
|
||||
}
|
||||
|
||||
inst->vertexAlpha = 0;
|
||||
if(geo->flags & Geometry::PRELIT){
|
||||
inst->vertexAlpha = instColor(VERT_ARGB, dst, &geo->colors[inst->minVert],
|
||||
inst->numVertices, inst->stride);
|
||||
dst += 4;
|
||||
}
|
||||
|
||||
for(int32 i = 0; i < geo->numTexCoordSets; i++){
|
||||
instTexCoords(VERT_FLOAT2, dst, &geo->texCoords[i][inst->minVert],
|
||||
inst->numVertices, inst->stride);
|
||||
dst += 8;
|
||||
}
|
||||
unlockVertices(inst->vertexBuffer);
|
||||
}
|
||||
|
||||
void
|
||||
defaultUninstanceCB(Geometry *geo, InstanceData *inst)
|
||||
{
|
||||
uint8 *src = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
|
||||
uninstV3d(VERT_FLOAT3,
|
||||
&geo->morphTargets[0].vertices[inst->minVert],
|
||||
src, inst->numVertices, inst->stride);
|
||||
src += 12;
|
||||
|
||||
if(geo->flags & Geometry::NORMALS){
|
||||
uninstV3d(VERT_FLOAT3,
|
||||
&geo->morphTargets[0].normals[inst->minVert],
|
||||
src, inst->numVertices, inst->stride);
|
||||
src += 12;
|
||||
}
|
||||
|
||||
inst->vertexAlpha = 0;
|
||||
if(geo->flags & Geometry::PRELIT){
|
||||
uninstColor(VERT_ARGB, &geo->colors[inst->minVert], src,
|
||||
inst->numVertices, inst->stride);
|
||||
src += 4;
|
||||
}
|
||||
|
||||
for(int32 i = 0; i < geo->numTexCoordSets; i++){
|
||||
uninstTexCoords(VERT_FLOAT2, &geo->texCoords[i][inst->minVert], src,
|
||||
inst->numVertices, inst->stride);
|
||||
src += 8;
|
||||
}
|
||||
unlockVertices(inst->vertexBuffer);
|
||||
}
|
||||
|
||||
ObjPipeline*
|
||||
makeDefaultPipeline(void)
|
||||
{
|
||||
ObjPipeline *pipe = ObjPipeline::create();
|
||||
pipe->instanceCB = defaultInstanceCB;
|
||||
pipe->uninstanceCB = defaultUninstanceCB;
|
||||
pipe->renderCB = defaultRenderCB;
|
||||
return pipe;
|
||||
}
|
||||
|
||||
// Native Texture and Raster
|
||||
|
||||
// only handles 4 and 8 bit textures right now
|
||||
Raster*
|
||||
readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format, int32 numLevels)
|
||||
{
|
||||
uint8 palette[256*4];
|
||||
int32 pallen = 0;
|
||||
uint8 *data = nil;
|
||||
|
||||
Image *img = Image::create(width, height, 32);
|
||||
img->allocate();
|
||||
|
||||
if(format & Raster::PAL4){
|
||||
pallen = 16;
|
||||
stream->read8(palette, 4*32);
|
||||
}else if(format & Raster::PAL8){
|
||||
pallen = 256;
|
||||
stream->read8(palette, 4*256);
|
||||
}
|
||||
if(!Raster::formatHasAlpha(format))
|
||||
for(int32 i = 0; i < pallen; i++)
|
||||
palette[i*4+3] = 0xFF;
|
||||
|
||||
Raster *ras = nil;
|
||||
|
||||
for(int i = 0; i < numLevels; i++){
|
||||
uint32 size = stream->readU32();
|
||||
|
||||
// don't read levels that don't exist
|
||||
if(ras && i >= ras->getNumLevels()){
|
||||
stream->seek(size);
|
||||
continue;
|
||||
}
|
||||
|
||||
// one allocation is enough, first level is largest
|
||||
if(data == nil)
|
||||
data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_IMAGE);
|
||||
stream->read8(data, size);
|
||||
|
||||
if(ras){
|
||||
ras->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
|
||||
img->width = ras->width;
|
||||
img->height = ras->height;
|
||||
img->stride = img->width*img->bpp;
|
||||
}
|
||||
|
||||
if(format & (Raster::PAL4 | Raster::PAL8)){
|
||||
uint8 *idx = data;
|
||||
uint8 *pixels = img->pixels;
|
||||
for(int y = 0; y < img->height; y++){
|
||||
uint8 *line = pixels;
|
||||
for(int x = 0; x < img->width; x++){
|
||||
line[0] = palette[*idx*4+0];
|
||||
line[1] = palette[*idx*4+1];
|
||||
line[2] = palette[*idx*4+2];
|
||||
if(img->bpp > 3)
|
||||
line[3] = palette[*idx*4+3];
|
||||
line += img->bpp;
|
||||
idx++;
|
||||
}
|
||||
pixels += img->stride;
|
||||
}
|
||||
}
|
||||
|
||||
if(ras == nil){
|
||||
// Important to have filled the image with data
|
||||
int32 newformat;
|
||||
Raster::imageFindRasterFormat(img, format&7, &width, &height, &depth, &newformat);
|
||||
newformat |= format & (Raster::MIPMAP | Raster::AUTOMIPMAP);
|
||||
ras = Raster::create(width, height, depth, newformat);
|
||||
ras->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
|
||||
}
|
||||
|
||||
ras->setFromImage(img);
|
||||
ras->unlock(i);
|
||||
}
|
||||
|
||||
rwFree(data);
|
||||
img->destroy();
|
||||
return ras;
|
||||
}
|
||||
|
||||
Texture*
|
||||
readNativeTexture(Stream *stream)
|
||||
{
|
||||
uint32 platform;
|
||||
if(!findChunk(stream, ID_STRUCT, nil, nil)){
|
||||
RWERROR((ERR_CHUNK, "STRUCT"));
|
||||
return nil;
|
||||
}
|
||||
platform = stream->readU32();
|
||||
if(platform != PLATFORM_D3D8){
|
||||
RWERROR((ERR_PLATFORM, platform));
|
||||
return nil;
|
||||
}
|
||||
Texture *tex = Texture::create(nil);
|
||||
if(tex == nil)
|
||||
return nil;
|
||||
|
||||
// Texture
|
||||
tex->filterAddressing = stream->readU32();
|
||||
stream->read8(tex->name, 32);
|
||||
stream->read8(tex->mask, 32);
|
||||
|
||||
// Raster
|
||||
uint32 format = stream->readU32();
|
||||
bool32 hasAlpha = stream->readI32();
|
||||
int32 width = stream->readU16();
|
||||
int32 height = stream->readU16();
|
||||
int32 depth = stream->readU8();
|
||||
int32 numLevels = stream->readU8();
|
||||
int32 type = stream->readU8();
|
||||
int32 compression = stream->readU8();
|
||||
|
||||
int32 pallength = 0;
|
||||
if(format & Raster::PAL4 || format & Raster::PAL8){
|
||||
pallength = format & Raster::PAL4 ? 32 : 256;
|
||||
if(!d3d::isP8supported){
|
||||
tex->raster = readAsImage(stream, width, height, depth, format|type, numLevels);
|
||||
return tex;
|
||||
}
|
||||
}
|
||||
|
||||
Raster *raster;
|
||||
D3dRaster *ras;
|
||||
if(compression){
|
||||
raster = Raster::create(width, height, depth, format | type | Raster::DONTALLOCATE, PLATFORM_D3D8);
|
||||
ras = GETD3DRASTEREXT(raster);
|
||||
allocateDXT(raster, compression, numLevels, hasAlpha);
|
||||
ras->customFormat = 1;
|
||||
}else{
|
||||
raster = Raster::create(width, height, depth, format | type, PLATFORM_D3D8);
|
||||
ras = GETD3DRASTEREXT(raster);
|
||||
}
|
||||
tex->raster = raster;
|
||||
|
||||
// TODO: check if format supported and convert if necessary
|
||||
|
||||
if(pallength != 0)
|
||||
stream->read8(ras->palette, 4*pallength);
|
||||
|
||||
uint32 size;
|
||||
uint8 *data;
|
||||
for(int32 i = 0; i < numLevels; i++){
|
||||
size = stream->readU32();
|
||||
if(i < raster->getNumLevels()){
|
||||
data = raster->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
|
||||
stream->read8(data, size);
|
||||
raster->unlock(i);
|
||||
}else
|
||||
stream->seek(size);
|
||||
}
|
||||
return tex;
|
||||
}
|
||||
|
||||
void
|
||||
writeNativeTexture(Texture *tex, Stream *stream)
|
||||
{
|
||||
int32 chunksize = getSizeNativeTexture(tex);
|
||||
writeChunkHeader(stream, ID_STRUCT, chunksize-12);
|
||||
stream->writeU32(PLATFORM_D3D8);
|
||||
|
||||
// Texture
|
||||
stream->writeU32(tex->filterAddressing);
|
||||
stream->write8(tex->name, 32);
|
||||
stream->write8(tex->mask, 32);
|
||||
|
||||
// Raster
|
||||
Raster *raster = tex->raster;
|
||||
D3dRaster *ras = GETD3DRASTEREXT(raster);
|
||||
int32 numLevels = raster->getNumLevels();
|
||||
stream->writeI32(raster->format);
|
||||
stream->writeI32(ras->hasAlpha);
|
||||
stream->writeU16(raster->width);
|
||||
stream->writeU16(raster->height);
|
||||
stream->writeU8(raster->depth);
|
||||
stream->writeU8(numLevels);
|
||||
stream->writeU8(raster->type);
|
||||
int32 compression = 0;
|
||||
if(ras->format)
|
||||
switch(ras->format){
|
||||
case 0x31545844: // DXT1
|
||||
compression = 1;
|
||||
break;
|
||||
case 0x32545844: // DXT2
|
||||
compression = 2;
|
||||
break;
|
||||
case 0x33545844: // DXT3
|
||||
compression = 3;
|
||||
break;
|
||||
case 0x34545844: // DXT4
|
||||
compression = 4;
|
||||
break;
|
||||
case 0x35545844: // DXT5
|
||||
compression = 5;
|
||||
break;
|
||||
}
|
||||
stream->writeU8(compression);
|
||||
|
||||
if(raster->format & Raster::PAL4)
|
||||
stream->write8(ras->palette, 4*32);
|
||||
else if(raster->format & Raster::PAL8)
|
||||
stream->write8(ras->palette, 4*256);
|
||||
|
||||
uint32 size;
|
||||
uint8 *data;
|
||||
for(int32 i = 0; i < numLevels; i++){
|
||||
size = getLevelSize(raster, i);
|
||||
stream->writeU32(size);
|
||||
data = raster->lock(i, Raster::LOCKREAD);
|
||||
stream->write8(data, size);
|
||||
raster->unlock(i);
|
||||
}
|
||||
}
|
||||
|
||||
uint32
|
||||
getSizeNativeTexture(Texture *tex)
|
||||
{
|
||||
uint32 size = 12 + 72 + 16;
|
||||
int32 levels = tex->raster->getNumLevels();
|
||||
if(tex->raster->format & Raster::PAL4)
|
||||
size += 4*32;
|
||||
else if(tex->raster->format & Raster::PAL8)
|
||||
size += 4*256;
|
||||
for(int32 i = 0; i < levels; i++)
|
||||
size += 4 + getLevelSize(tex->raster, i);
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue