various changes

This commit is contained in:
aap 2016-02-06 18:11:31 +01:00
parent 6d56a23dd1
commit ef58d76bc0
22 changed files with 890 additions and 2236 deletions

View File

@ -10,31 +10,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dumprwtree", "tools\dumprwt
{30552BB0-3B19-49A4-ABF4-87CF68AF9E38} = {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dffwrite", "tools\dffwrite\dffwrite.vcxproj", "{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}"
ProjectSection(ProjectDependencies) = postProject
{30552BB0-3B19-49A4-ABF4-87CF68AF9E38} = {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "insttest", "tools\insttest\insttest.vcxproj", "{2592ED29-F258-4949-AB45-7B873BF697F7}"
ProjectSection(ProjectDependencies) = postProject
{30552BB0-3B19-49A4-ABF4-87CF68AF9E38} = {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d3d9", "tools\d3d9\d3d9.vcxproj", "{E5D477C8-4CAF-43BF-B7E3-6689503D469F}"
ProjectSection(ProjectDependencies) = postProject
{30552BB0-3B19-49A4-ABF4-87CF68AF9E38} = {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "txdwrite", "tools\txdwrite\txdwrite.vcxproj", "{403C35A9-6D06-4261-B305-9ED000F00136}"
ProjectSection(ProjectDependencies) = postProject
{30552BB0-3B19-49A4-ABF4-87CF68AF9E38} = {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsltest", "tools\rsltest\rsltest.vcxproj", "{27ECE916-900F-49B2-8E9F-95E6B347E161}"
ProjectSection(ProjectDependencies) = postProject
{30552BB0-3B19-49A4-ABF4-87CF68AF9E38} = {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - null|Win32 = Debug - null|Win32
@ -66,53 +41,6 @@ Global
{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|Win32.ActiveCfg = Release|Win32
{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|Win32.Build.0 = Release|Win32
{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|x64.ActiveCfg = Release|x64
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|Win32.Build.0 = Debug - null|Win32
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|x64.ActiveCfg = Debug - null|x64
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug|Win32.ActiveCfg = Debug|Win32
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug|x64.ActiveCfg = Debug|x64
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug|x64.Build.0 = Debug|x64
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|Win32.ActiveCfg = Release|Win32
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|Win32.Build.0 = Release|Win32
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|x64.ActiveCfg = Release|x64
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|Win32.Build.0 = Debug - null|Win32
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|x64.ActiveCfg = Debug - null|x64
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|x64.Build.0 = Debug - null|x64
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|Win32.ActiveCfg = Debug|Win32
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|x64.ActiveCfg = Debug|x64
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|x64.Build.0 = Debug|x64
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.ActiveCfg = Release|Win32
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.Build.0 = Release|Win32
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.ActiveCfg = Release|x64
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.Build.0 = Release|x64
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|x64.ActiveCfg = Debug - null|x64
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|Win32.ActiveCfg = Debug|Win32
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|Win32.Build.0 = Debug|Win32
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|x64.ActiveCfg = Debug|x64
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|x64.Build.0 = Debug|x64
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|Win32.ActiveCfg = Release|Win32
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|Win32.Build.0 = Release|Win32
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|x64.ActiveCfg = Release|x64
{403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
{403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|Win32.Build.0 = Debug - null|Win32
{403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|x64.ActiveCfg = Debug - null|x64
{403C35A9-6D06-4261-B305-9ED000F00136}.Debug|Win32.ActiveCfg = Debug|Win32
{403C35A9-6D06-4261-B305-9ED000F00136}.Debug|x64.ActiveCfg = Debug|x64
{403C35A9-6D06-4261-B305-9ED000F00136}.Debug|x64.Build.0 = Debug|x64
{403C35A9-6D06-4261-B305-9ED000F00136}.Release|Win32.ActiveCfg = Release|Win32
{403C35A9-6D06-4261-B305-9ED000F00136}.Release|Win32.Build.0 = Release|Win32
{403C35A9-6D06-4261-B305-9ED000F00136}.Release|x64.ActiveCfg = Release|x64
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|Win32.Build.0 = Debug - null|Win32
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|x64.ActiveCfg = Debug - null|Win32
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug|Win32.ActiveCfg = Debug - null|Win32
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug|Win32.Build.0 = Debug - null|Win32
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug|x64.ActiveCfg = Debug - null|Win32
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Release|Win32.ActiveCfg = Release|Win32
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Release|Win32.Build.0 = Release|Win32
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -115,6 +115,7 @@
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;RW_D3D9;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -192,17 +193,16 @@
<ClCompile Include="src\d3d8.cpp" />
<ClCompile Include="src\d3d9.cpp" />
<ClCompile Include="src\geometry.cpp" />
<ClCompile Include="src\gtaplg.cpp" />
<ClCompile Include="src\image.cpp" />
<ClCompile Include="src\ogl.cpp" />
<ClCompile Include="src\pipeline.cpp" />
<ClCompile Include="src\plugins.cpp" />
<ClCompile Include="src\ps2.cpp" />
<ClCompile Include="src\ps2raster.cpp" />
<ClCompile Include="src\rwbase.cpp" />
<ClCompile Include="src\xbox.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\gtaplg.h" />
<ClInclude Include="src\rwbase.h" />
<ClInclude Include="src\rwd3d.h" />
<ClInclude Include="src\rwd3d8.h" />

View File

@ -3,8 +3,6 @@
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"

View File

@ -4,8 +4,6 @@
#include <cassert>
#include <cmath>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"

View File

@ -416,6 +416,82 @@ D3dRaster::getNumLevels(Raster*)
#endif
}
void
D3dRaster::fromImage(Raster *raster, Image *image)
{
int32 format;
if(image->depth == 32)
format = Raster::C8888;
else if(image->depth == 24)
format = Raster::C888;
else if(image->depth == 16)
format = Raster::C1555;
else if(image->depth == 8)
format = Raster::PAL8 | Raster::C8888;
else if(image->depth == 4)
format = Raster::PAL4 | Raster::C8888;
else
return;
format |= 4;
raster->type = format & 0x7;
raster->flags = format & 0xF8;
raster->format = format & 0xFF00;
this->create(raster);
uint8 *in, *out;
int pallength = 0;
if(raster->format & Raster::PAL4)
pallength = 16;
else if(raster->format & Raster::PAL8)
pallength = 256;
if(pallength){
in = image->palette;
out = (uint8*)this->palette;
for(int32 i = 0; i < pallength; i++){
out[0] = in[2];
out[1] = in[1];
out[2] = in[0];
out[3] = in[3];
in += 4;
out += 4;
}
}
in = image->pixels;
out = raster->lock(0);
if(pallength)
memcpy(out, in, raster->width*raster->height);
else
for(int32 y = 0; y < image->height; y++)
for(int32 x = 0; x < image->width; x++)
switch(raster->format & 0xF00){
case Raster::C8888:
out[0] = in[2];
out[1] = in[1];
out[2] = in[0];
out[3] = in[3];
in += 4;
out += 4;
break;
case Raster::C888:
out[0] = in[2];
out[1] = in[1];
out[2] = in[0];
out[3] = 0xFF;
in += 3;
out += 4;
break;
case Raster::C1555:
out[0] = in[0];
out[1] = in[1];
in += 2;
out += 2;
break;
}
raster->unlock(0);
}
int32
getLevelSize(Raster *raster, int32 level)
{

View File

@ -3,8 +3,6 @@
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"

View File

@ -3,8 +3,6 @@
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"

View File

@ -4,8 +4,6 @@
#include <cassert>
#include <cmath>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,139 +0,0 @@
namespace rw {
int32 findPlatform(Clump *c);
void switchPipes(Clump *c, int32 platform);
};
namespace gta {
using namespace rw;
enum
{
ID_EXTRANORMALS = 0x253f2f2,
ID_PIPELINE = 0x253f2f3,
ID_SPECMAT = 0x253f2f6,
ID_2DEFFECT = 0x253f2f8, // geometry
ID_EXTRAVERTCOLORS = 0x253f2f9,
ID_COLLISION = 0x253f2fa, // clump
ID_ENVMAT = 0x253f2fc,
ID_BREAKABLE = 0x253f2fd,
ID_NODENAME = 0x253f2fe
};
void attachPlugins(void);
// Node name
extern int32 nodeNameOffset;
void registerNodeNamePlugin(void);
char *getNodeName(Frame *f);
// Breakable model
struct Breakable
{
uint32 position;
uint32 numVertices;
uint32 numFaces;
uint32 numMaterials;
float32 *vertices;
float32 *texCoords;
uint8 *colors;
uint16 *faces;
uint16 *matIDs;
char (*texNames)[32];
char (*maskNames)[32];
float32 (*surfaceProps)[3];
};
extern int32 breakableOffset;
void registerBreakableModelPlugin(void);
// Extra normals (only on Xbox)
extern int32 extraNormalsOffset;
void registerExtraNormalsPlugin(void);
// Extra vert colors (not on Xbox)
struct ExtraVertColors
{
uint8 *nightColors;
uint8 *dayColors;
float balance;
};
extern int32 extraVertColorOffset;
void allocateExtraVertColors(Geometry *g);
void registerExtraVertColorPlugin(void);
// Environment mat
struct EnvMat
{
int8 scaleX, scaleY;
int8 transScaleX, transScaleY;
int8 shininess;
Texture *texture;
};
extern int32 envMatOffset;
// Specular mat
struct SpecMat
{
float specularity;
Texture *texture;
};
extern int32 specMatOffset;
void registerEnvSpecPlugin(void);
// Pipeline
// 0x53F2009A CCustomCarEnvMapPipeline
//
// PC & Mobile:
// 0x53F20098 CCustomBuildingDNPipeline
// 0x53F2009C CCustomBuildingPipeline
//
// Xbox
// 0x53F2009E building !N !EN
// 0x53F20096 building N !EN
// 0x53F200A0 building !N EN (also env) non-DN custom instanceCB!
// 0x53F200A2 building N EN (also env) DN custom instanceCB!
extern int32 pipelineOffset;
void registerPipelinePlugin(void);
uint32 getPipelineID(Atomic *atomic);
void setPipelineID(Atomic *atomic, uint32 id);
// 2dEffect
extern int32 twodEffectOffset;
void register2dEffectPlugin(void);
// Collision
extern int32 collisionOffset;
void registerCollisionPlugin(void);
// PDS pipes
struct SaVert : ps2::Vertex {
float32 w[4];
uint8 i[4];
float32 t1[2];
uint8 c1[4];
};
void insertSAVertex(Geometry *geo, int32 i, uint32 mask, SaVert *v);
int32 findSAVertex(Geometry *g, uint32 flags[], uint32 mask, SaVert *v);
void registerPDSPipes(void);
}

View File

@ -3,8 +3,6 @@
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"
@ -104,6 +102,8 @@ TexDictionary::streamGetSize(void)
// Texture
//
bool32 loadTextures;
Texture*
Texture::create(Raster *raster)
{
@ -149,19 +149,22 @@ Texture::read(const char *name, const char *mask)
tex = Texture::create(NULL);
strncpy(tex->name, name, 32);
strncpy(tex->mask, mask, 32);
// char *n = (char*)malloc(strlen(name) + 5);
// strcpy(n, name);
// strcat(n, ".tga");
// Image *img = readTGA(n);
// free(n);
// if(img){
// //raster = Raster::createFromImage(img);
// raster = new Raster(0, 0, 0, 0x80);
// img->destroy();
// }else
Image *img = NULL;
if(loadTextures){
char *n = (char*)malloc(strlen(name) + 5);
strcpy(n, name);
strcat(n, ".tga");
img = readTGA(n);
free(n);
if(img){
raster = Raster::createFromImage(img);
img->destroy();
}else
raster = Raster::create(0, 0, 0, 0x80);
}else
raster = Raster::create(0, 0, 0, 0x80);
tex->raster = raster;
if(currentTexDictionary /*&& img*/)
if(currentTexDictionary)
currentTexDictionary->add(tex);
return tex;
}
@ -184,9 +187,9 @@ Texture::streamRead(Stream *stream)
stream->read(mask, length);
Texture *tex = Texture::read(name, mask);
tex->refCount++;
if(tex->refCount == 1)
tex->filterAddressing = filterAddressing;
tex->refCount++; // TODO: RW doesn't do this, why?
tex->streamReadPlugins(stream);
@ -640,36 +643,15 @@ Raster::calculateNumLevels(int32 width, int32 height)
return n;
}
// BAD BAD BAD BAD
Raster*
Raster::createFromImage(Image *image)
{
assert(0 && "cannot create raster from image");
int32 format;
// TODO: make that into a function
if(image->depth == 32)
format = Raster::C8888;
else if(image->depth == 24)
format = Raster::C888;
else if(image->depth == 16)
format = Raster::C1555;
else if(image->depth == 8)
format = Raster::PAL8 | Raster::C8888;
else if(image->depth == 4)
format = Raster::PAL4 | Raster::C8888;
else
return NULL;
Raster *raster = Raster::create(image->width, image->height,
image->depth, format | 4 | 0x80);
raster->stride = image->stride;
raster->texels = new uint8[raster->stride*raster->height];
memcpy(raster->texels, image->pixels, raster->stride*raster->height);
if(image->palette){
int size = raster->depth == 4 ? 16 : 256;
raster->palette = new uint8[size*4];
memcpy(raster->palette, image->palette, size*4);
}
image->depth, 4 | 0x80);
int32 offset = nativeOffsets[raster->platform];
assert(offset != 0 && "unimplemented raster platform");
NativeRaster *nr = PLUGINOFFSET(NativeRaster, raster, offset);
nr->fromImage(raster, image);
return raster;
}

View File

@ -3,8 +3,6 @@
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"

View File

@ -3,8 +3,6 @@
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"

View File

@ -3,8 +3,6 @@
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"
@ -913,7 +911,16 @@ MatFX::setEffects(uint32 type)
}
}
int32
uint32
MatFX::getEffects(Material *m)
{
MatFX *fx = *PLUGINOFFSET(MatFX*, m, matFXGlobals.materialOffset);
if(fx)
return fx->type;
return 0;
}
uint32
MatFX::getEffectIndex(uint32 type)
{
for(int i = 0; i < 2; i++)

View File

@ -3,16 +3,12 @@
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"
#include "rwobjects.h"
#include "rwps2.h"
using namespace std;
namespace rw {
namespace ps2 {
@ -282,6 +278,34 @@ instanceUV(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
return p;
}
uint32*
instanceUV2(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
{
uint16 j;
uint32 *d0 = (uint32*)g->texCoords[0];
uint32 *d1 = (uint32*)g->texCoords[1];
for(uint32 i = idx; i < idx+n; i++){
j = m->indices[i];
if(g->numTexCoordSets > 0){
*p++ = d0[j*2+0];
*p++ = d0[j*2+1];
}else{
*p++ = 0;
*p++ = 0;
}
if(g->numTexCoordSets > 1){
*p++ = d1[j*2+0];
*p++ = d1[j*2+1];
}else{
*p++ = 0;
*p++ = 0;
}
}
while((uintptr)p % 0x10)
*p++ = 0;
return p;
}
uint32*
instanceRGBA(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
{
@ -338,15 +362,18 @@ MatPipeline::dump(void)
if(this->platform != PLATFORM_PS2)
return;
PipeAttribute *a;
printf("%x %x\n", this->pluginID, this->pluginData);
for(uint i = 0; i < nelem(this->attribs); i++){
a = this->attribs[i];
if(a)
printf("%d %s: %x\n", i, a->name, a->attrib);
}
printf("stride: %x\n", this->inputStride);
printf("vertcount: %x\n", this->vifOffset/this->inputStride);
printf("triSCount: %x\n", this->triStripCount);
printf("triLCount: %x\n", this->triListCount);
printf("vifOffset: %x\n", this->vifOffset);
printf("\n");
}
void
@ -506,20 +533,16 @@ MatPipeline::instance(Geometry *g, InstanceData *inst, Mesh *m)
*p++ = (a->attrib&0xFF004000)
| 0x8000 | nverts << 16 | i; // UNPACK
switch(i){
case 0:
if(a == &attribXYZ)
p = instanceXYZ(p, g, m, idx, nverts);
break;
case 1:
else if(a == &attribUV)
p = instanceUV(p, g, m, idx, nverts);
break;
case 2:
else if(a == &attribUV2)
p = instanceUV2(p, g, m, idx, nverts);
else if(a == &attribRGBA)
p = instanceRGBA(p, g, m, idx, nverts);
break;
case 3:
p = instanceNormal(p,g, m, idx, nverts);
break;
}
else if(a == &attribNormal)
p = instanceNormal(p, g, m, idx, nverts);
}
idx += g->meshHeader->flags == 1
? im.batchVertCount-2 : im.batchVertCount;
@ -726,6 +749,7 @@ findVertex(Geometry *g, uint32 flags[], uint32 mask, Vertex *v)
{
float32 *verts = g->morphTargets[0].vertices;
float32 *tex = g->texCoords[0];
float32 *tex1 = g->texCoords[1];
float32 *norms = g->morphTargets[0].normals;
uint8 *cols = g->colors;
@ -742,10 +766,14 @@ findVertex(Geometry *g, uint32 flags[], uint32 mask, Vertex *v)
if(mask & flags[i] & 0x1000 &&
!(tex[0] == v->t[0] && tex[1] == v->t[1]))
goto cont;
if(mask & flags[i] & 0x2000 &&
!(tex1[0] == v->t1[0] && tex1[1] == v->t1[1]))
goto cont;
return i;
cont:
verts += 3;
tex += 2;
tex1 += 2;
norms += 3;
cols += 4;
}
@ -763,10 +791,12 @@ insertVertex(Geometry *geo, int32 i, uint32 mask, Vertex *v)
memcpy(&geo->colors[i*4], v->c, 4);
if(mask & 0x1000)
memcpy(&geo->texCoords[0][i*2], v->t, 8);
if(mask & 0x2000)
memcpy(&geo->texCoords[1][i*2], v->t1, 8);
}
void
defaultUninstanceCB(MatPipeline*, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[])
defaultUninstanceCB(MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[])
{
float32 *verts = (float32*)data[AT_XYZ];
float32 *texcoords = (float32*)data[AT_UV];
@ -777,8 +807,9 @@ defaultUninstanceCB(MatPipeline*, Geometry *geo, uint32 flags[], Mesh *mesh, uin
mask |= 0x10;
if(geo->geoflags & Geometry::PRELIT)
mask |= 0x100;
if(geo->numTexCoordSets > 0)
mask |= 0x1000;
for(int32 i = 0; i < geo->numTexCoordSets; i++)
mask |= 0x1000 << i;
int numUV = pipe->attribs[AT_UV] == &attribUV2 ? 2 : 1;
Vertex v;
for(uint32 i = 0; i < mesh->numIndices; i++){
@ -793,6 +824,8 @@ defaultUninstanceCB(MatPipeline*, Geometry *geo, uint32 flags[], Mesh *mesh, uin
memcpy(&v.c, colors, 4);
if(mask & 0x1000)
memcpy(&v.t, texcoords, 8);
if(mask & 0x2000)
memcpy(&v.t1, texcoords+2, 8);
int32 idx = findVertex(geo, flags, mask, &v);
if(idx < 0)
@ -801,7 +834,7 @@ defaultUninstanceCB(MatPipeline*, Geometry *geo, uint32 flags[], Mesh *mesh, uin
flags[idx] = mask;
insertVertex(geo, idx, mask, &v);
verts += 3;
texcoords += 2;
texcoords += 2*numUV;
colors += 4;
norms += 3;
}
@ -1315,6 +1348,7 @@ static void
atomicPDSRights(void *object, int32, int32, uint32 data)
{
Atomic *a = (Atomic*)object;
//printf("atm pds: %x\n", data);
a->pipeline = (ObjPipeline*)getPDSPipe(data);
}
@ -1322,6 +1356,7 @@ static void
materialPDSRights(void *object, int32, int32, uint32 data)
{
Material *m = (Material*)object;
//printf("mat pds: %x\n", data);
m->pipeline = (ObjPipeline*)getPDSPipe(data);
}
@ -1338,6 +1373,73 @@ registerPDSPlugin(int32 n)
Material::setStreamRightsCallback(ID_PDS, materialPDSRights);
}
void
registerPluginPDSPipes(void)
{
// Skin
MatPipeline *pipe = new MatPipeline(PLATFORM_PS2);
pipe->pluginID = ID_PDS;
pipe->pluginData = 0x11001; // rwPDS_G3_Generic_GrpMatPipeID
pipe->attribs[AT_XYZ] = &attribXYZ;
pipe->attribs[AT_UV] = &attribUV;
pipe->attribs[AT_RGBA] = &attribRGBA;
pipe->attribs[AT_NORMAL] = &attribNormal;
pipe->attribs[AT_NORMAL+1] = &attribWeights;
uint32 vertCount = MatPipeline::getVertCount(VU_Lights-0x100, 5, 3, 2);
pipe->setTriBufferSizes(5, vertCount);
pipe->vifOffset = pipe->inputStride*vertCount;
pipe->instanceCB = skinInstanceCB;
pipe->uninstanceCB = skinUninstanceCB;
pipe->preUninstCB = skinPreCB;
pipe->postUninstCB = skinPostCB;
registerPDSPipe(pipe);
ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2);
opipe->pluginID = ID_PDS;
opipe->pluginData = 0x11002; // rwPDS_G3_Skin_GrpAtmPipeID
opipe->groupPipeline = pipe;
registerPDSPipe(opipe);
// MatFX UV1
pipe = new MatPipeline(PLATFORM_PS2);
pipe->pluginID = ID_PDS;
pipe->pluginData = 0x1100b; // rwPDS_G3_MatfxUV1_GrpMatPipeID
pipe->attribs[AT_XYZ] = &attribXYZ;
pipe->attribs[AT_UV] = &attribUV;
pipe->attribs[AT_RGBA] = &attribRGBA;
pipe->attribs[AT_NORMAL] = &attribNormal;
vertCount = MatPipeline::getVertCount(0x3C5, 4, 3, 3);
pipe->setTriBufferSizes(4, vertCount);
pipe->vifOffset = pipe->inputStride*vertCount;
pipe->uninstanceCB = defaultUninstanceCB;
registerPDSPipe(pipe);
opipe = new ObjPipeline(PLATFORM_PS2);
opipe->pluginID = ID_PDS;
opipe->pluginData = 0x1100d; // rwPDS_G3_MatfxUV1_GrpAtmPipeID
opipe->groupPipeline = pipe;
registerPDSPipe(opipe);
// MatFX UV2
pipe = new MatPipeline(PLATFORM_PS2);
pipe->pluginID = ID_PDS;
pipe->pluginData = 0x1100c; // rwPDS_G3_MatfxUV2_GrpMatPipeID
pipe->attribs[AT_XYZ] = &attribXYZ;
pipe->attribs[AT_UV] = &attribUV2;
pipe->attribs[AT_RGBA] = &attribRGBA;
pipe->attribs[AT_NORMAL] = &attribNormal;
vertCount = MatPipeline::getVertCount(0x3C5, 4, 3, 3);
pipe->setTriBufferSizes(4, vertCount);
pipe->vifOffset = pipe->inputStride*vertCount;
pipe->uninstanceCB = defaultUninstanceCB;
registerPDSPipe(pipe);
opipe = new ObjPipeline(PLATFORM_PS2);
opipe->pluginID = ID_PDS;
opipe->pluginData = 0x1100e; // rwPDS_G3_MatfxUV2_GrpAtmPipeID
opipe->groupPipeline = pipe;
registerPDSPipe(opipe);
}
// misc stuff
@ -1406,555 +1508,5 @@ sizedebug(InstanceData *inst)
}
}
// Raster
int32 nativeRasterOffset;
#define MAXLEVEL(r) ((r)->tex1[1]>>18 & 0x3F)
#define SETMAXLEVEL(r, l) ((r)->tex1[1] = (r)->tex1[1]&~0xFF0000 | l<<18)
#define SETKL(r, val) ((r)->tex1[1] = (r)->tex1[1]&~0xFFFF | (uint16)(val))
static bool32 noNewStyleRasters;
// i don't really understand this, stolen from RW
static void
ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh)
{
*minh = 1;
switch(psm){
case 0x00:
case 0x30:
*minw = 2; // 32 bit
break;
case 0x02:
case 0x0A:
case 0x32:
case 0x3A:
*minw = 4; // 16 bit
break;
case 0x01:
case 0x13:
case 0x14:
case 0x1B:
case 0x24:
case 0x2C:
case 0x31:
*minw = 8; // everything else
break;
}
if(flags & 0x2 && psm == 0x13){ // PSMT8
*minw = 16;
*minh = 4;
}
if(flags & 0x4 && psm == 0x14){ // PSMT4
*minw = 32;
*minh = 4;
}
}
void
Ps2Raster::create(Raster *raster)
{
int32 pageWidth, pageHeight;
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
//printf("%x %x %x %x\n", raster->format, raster->flags, raster->type, noNewStyleRasters);
assert(raster->type == 4); // Texture
switch(raster->depth){
case 4:
pageWidth = 128;
pageHeight = 128;
break;
case 8:
pageWidth = 128;
pageHeight = 64;
break;
case 16:
pageWidth = 64;
pageHeight = 64;
break;
case 32:
pageWidth = 64;
pageHeight = 32;
break;
default:
assert(0 && "unsupported depth");
}
int32 logw = 0, logh = 0;
int32 s;
for(s = 1; s < raster->width; s *= 2)
logw++;
for(s = 1; s < raster->height; s *= 2)
logh++;
SETKL(ras, 0xFC0);
//printf("%d %d %d %d\n", raster->width, logw, raster->height, logh);
ras->tex0[0] |= (raster->width < pageWidth ? pageWidth : raster->width)/64 << 14;
ras->tex0[0] |= logw << 26;
ras->tex0[0] |= logh << 30;
ras->tex0[1] |= logh >> 2;
int32 paletteWidth, paletteHeight, paletteDepth;
int32 palettePagewidth, palettePageheight;
if(raster->format & (Raster::PAL4 | Raster::PAL8))
switch(raster->format & 0xF00){
case Raster::C1555:
ras->tex0[1] |= 0xA << 19; // PSMCT16S
paletteDepth = 2;
palettePagewidth = palettePageheight = 64;
break;
case Raster::C8888:
// PSMCT32
paletteDepth = 4;
palettePagewidth = 64;
palettePageheight = 32;
break;
default:
assert(0 && "unsupported palette format\n");
}
if(raster->format & Raster::PAL4){
ras->tex0[0] |= 0x14 << 20; // PSMT4
ras->tex0[1] |= 1<<29 | 1<<2; // CLD 1, TCC RGBA
paletteWidth = 8;
paletteHeight = 2;
}else if(raster->format & Raster::PAL8){
ras->tex0[0] |= 0x13 << 20; // PSMT8
ras->tex0[1] |= 1<<29 | 1<<2; // CLD 1, TCC RGBA
paletteWidth = paletteHeight = 16;
}else{
paletteWidth = 0;
paletteHeight = 0;
paletteDepth = 0;
palettePagewidth = 0;
palettePageheight = 0;
switch(raster->format & 0xF00){
case Raster::C1555:
ras->tex0[0] |= 0xA << 20; // PSMCT16S
ras->tex0[1] |= 1 << 2; // TCC RGBA
break;
case Raster::C8888:
// PSMCT32
ras->tex0[1] |= 1 << 2; // TCC RGBA
break;
case Raster::C888:
ras->tex0[0] |= 1 << 20; // PSMCT24
break;
default:
assert(0 && "unsupported raster format\n");
}
}
raster->stride = raster->width*raster->depth/8;
if(raster->format & Raster::MIPMAP){
assert(0);
}else{
ras->texelSize = raster->stride*raster->depth+0xF & ~0xF;
ras->paletteSize = paletteWidth*paletteHeight*paletteDepth;
ras->miptbp1[0] |= 1<<14; // TBW1
ras->miptbp1[1] |= 1<<2 | 1<<22; // TBW2,3
ras->miptbp2[0] |= 1<<14; // TBW4
ras->miptbp2[1] |= 1<<2 | 1<<22; // TBW5,6
SETMAXLEVEL(ras, 0);
int32 nPagW = (raster->width + pageWidth-1)/pageWidth;
int32 nPagH = (raster->height + pageHeight-1)/pageHeight;
ras->gsSize = (nPagW*nPagH*0x800)&~0x7FF;
if(ras->paletteSize){
// BITBLTBUF DBP
if(pageWidth*nPagW > raster->width ||
pageHeight*nPagH > raster->height)
ras->tex1[0] = (ras->gsSize >> 6) - 4;
else{
ras->tex1[0] = ras->gsSize >> 6;
}
nPagW = (paletteWidth + palettePagewidth-1)/palettePagewidth;
nPagH = (paletteHeight + palettePageheight-1)/palettePageheight;
ras->gsSize += (nPagW*nPagH*0x800)&~0x7FF;
}else
ras->tex1[0] = 0;
}
// allocate data and fill with GIF packets
ras->texelSize = ras->texelSize+0xF & ~0xF;
int32 numLevels = MAXLEVEL(ras)+1;
if(noNewStyleRasters ||
(raster->width*raster->height*raster->depth & ~0x7F) >= 0x3FFF80){
assert(0);
}else{
ras->flags |= 1; // include GIF packets
int32 psm = ras->tex0[0]>>20 & 0x3F;
//int32 cpsm = ras->tex0[1]>>19 & 0x3F;
if(psm == 0x13){ // PSMT8
ras->flags |= 2;
// TODO: stuff
}
if(psm == 0x14){ // PSMT4
// swizzle flag probably depends on version :/
if(rw::version > 0x31000)
ras->flags |= 4;
// TODO: stuff
}
ras->texelSize = 0x50*numLevels; // GIF packets
int32 minW, minH;
ps2MinSize(psm, ras->flags, &minW, &minH);
int32 w = raster->width;
int32 h = raster->height;
int32 mipw, miph;
int32 n = numLevels;
while(n--){
mipw = w < minW ? minW : w;
miph = h < minH ? minH : h;
ras->texelSize += mipw*miph*raster->depth/8+0xF & ~0xF;
w /= 2;
h /= 2;
}
if(ras->paletteSize){
if(rw::version > 0x31000 && paletteHeight == 2)
paletteHeight = 3;
ras->paletteSize = 0x50 +
paletteDepth*paletteWidth*paletteHeight;
}
// TODO: allocate space for more DMA packets
ras->dataSize = ras->paletteSize+ras->texelSize;
uint8 *data = new uint8[ras->dataSize];
assert(data);
ras->data = data;
raster->texels = data + 0x50;
if(ras->paletteSize)
raster->palette = data + ras->texelSize + 0x50;
uint32 *p = (uint32*)data;
w = raster->width;
h = raster->height;
for(n = 0; n < numLevels; n++){
mipw = w < minW ? minW : w;
miph = h < minH ? minH : h;
// GIF tag
*p++ = 3; // NLOOP = 3
*p++ = 0x10000000; // NREG = 1
*p++ = 0xE; // A+D
*p++ = 0;
// TRXPOS
*p++ = 0; // TODO
*p++ = 0; // TODO
*p++ = 0x51;
*p++ = 0;
// TRXREG
if(ras->flags & 2 && psm == 0x13 ||
ras->flags & 4 && psm == 0x14){
*p++ = mipw/2;
*p++ = miph/2;
}else{
*p++ = mipw;
*p++ = miph;
}
*p++ = 0x52;
*p++ = 0;
// TRXDIR
*p++ = 0; // host -> local
*p++ = 0;
*p++ = 0x53;
*p++ = 0;
// GIF tag
uint32 sz = mipw*miph*raster->depth/8 + 0xF >> 4;
*p++ = sz;
*p++ = 0x08000000; // IMAGE
*p++ = 0;
*p++ = 0;
p += sz*4;
w /= 2;
h /= 2;
}
if(ras->paletteSize){
p = (uint32*)(raster->palette - 0x50);
// GIF tag
*p++ = 3; // NLOOP = 3
*p++ = 0x10000000; // NREG = 1
*p++ = 0xE; // A+D
*p++ = 0;
// TRXPOS
*p++ = 0; // TODO
*p++ = 0; // TODO
*p++ = 0x51;
*p++ = 0;
// TRXREG
*p++ = paletteWidth;
*p++ = paletteHeight;
*p++ = 0x52;
*p++ = 0;
// TRXDIR
*p++ = 0; // host -> local
*p++ = 0;
*p++ = 0x53;
*p++ = 0;
// GIF tag
uint32 sz = paletteSize - 0x50 + 0xF >> 4;
*p++ = sz;
*p++ = 0x08000000; // IMAGE
*p++ = 0;
*p++ = 0;
}
}
}
uint8*
Ps2Raster::lock(Raster *raster, int32 level)
{
// TODO
(void)raster;
(void)level;
return NULL;
}
void
Ps2Raster::unlock(Raster *raster, int32 level)
{
// TODO
(void)raster;
(void)level;
}
int32
Ps2Raster::getNumLevels(Raster *raster)
{
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
if(raster->texels == NULL) return 0;
if(raster->format & Raster::MIPMAP)
return MAXLEVEL(ras)+1;
return 1;
}
static void*
createNativeRaster(void *object, int32 offset, int32)
{
Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, object, offset);
new (raster) Ps2Raster;
raster->tex0[0] = 0;
raster->tex0[1] = 0;
raster->tex1[0] = 0;
raster->tex1[1] = 0;
raster->miptbp1[0] = 0;
raster->miptbp1[1] = 0;
raster->miptbp2[0] = 0;
raster->miptbp2[1] = 0;
raster->texelSize = 0;
raster->paletteSize = 0;
raster->gsSize = 0;
raster->flags = 0;
SETKL(raster, 0xFC0);
raster->dataSize = 0;
raster->data = NULL;
return object;
}
static void*
destroyNativeRaster(void *object, int32 offset, int32)
{
// TODO
(void)offset;
return object;
}
static void*
copyNativeRaster(void *dst, void *src, int32 offset, int32)
{
Ps2Raster *dstraster = PLUGINOFFSET(Ps2Raster, dst, offset);
Ps2Raster *srcraster = PLUGINOFFSET(Ps2Raster, src, offset);
*dstraster = *srcraster;
return dst;
}
static void
readMipmap(Stream *stream, int32, void *object, int32 offset, int32)
{
uint16 val = stream->readI32();
Texture *tex = (Texture*)object;
if(tex->raster == NULL)
return;
Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, tex->raster, offset);
SETKL(raster, val);
}
static void
writeMipmap(Stream *stream, int32, void *object, int32 offset, int32)
{
Texture *tex = (Texture*)object;
assert(tex->raster);
Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, tex->raster, offset);
stream->writeI32(raster->tex1[1]&0xFFFF);
}
static int32
getSizeMipmap(void*, int32, int32)
{
return rw::platform == PLATFORM_PS2 ? 4 : 0;
}
void
registerNativeRaster(void)
{
nativeRasterOffset = Raster::registerPlugin(sizeof(Ps2Raster),
0x12340000 | PLATFORM_PS2,
createNativeRaster,
destroyNativeRaster,
copyNativeRaster);
Raster::nativeOffsets[PLATFORM_PS2] = nativeRasterOffset;
Texture::registerPlugin(0, ID_SKYMIPMAP, NULL, NULL, NULL);
Texture::registerPluginStream(ID_SKYMIPMAP, readMipmap, writeMipmap, getSizeMipmap);
}
struct StreamRasterExt
{
int32 width;
int32 height;
int32 depth;
uint16 rasterFormat;
int16 type;
uint32 tex0[2];
uint32 tex1[2];
uint32 miptbp1[2];
uint32 miptbp2[2];
uint32 texelSize;
uint32 paletteSize;
uint32 gsSize;
uint32 mipmapVal;
};
Texture*
readNativeTexture(Stream *stream)
{
uint32 length, oldversion, version;
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
assert(stream->readU32() == 0x00325350); // 'PS2\0'
Texture *tex = Texture::create(NULL);
// Texture
tex->filterAddressing = stream->readU32();
assert(findChunk(stream, ID_STRING, &length, NULL));
stream->read(tex->name, length);
assert(findChunk(stream, ID_STRING, &length, NULL));
stream->read(tex->mask, length);
// Raster
StreamRasterExt streamExt;
oldversion = rw::version;
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
assert(findChunk(stream, ID_STRUCT, NULL, &version));
stream->read(&streamExt, 0x40);
Raster *raster;
noNewStyleRasters = streamExt.type < 2;
rw::version = version;
raster = Raster::create(streamExt.width, streamExt.height,
streamExt.depth, streamExt.rasterFormat,
PLATFORM_PS2);
noNewStyleRasters = 0;
rw::version = oldversion;
tex->raster = raster;
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
//printf("%08X%08X %08X%08X %08X%08X %08X%08X\n",
// ras->tex0[1], ras->tex0[0], ras->tex1[1], ras->tex1[0],
// ras->miptbp1[0], ras->miptbp1[1], ras->miptbp2[0], ras->miptbp2[1]);
ras->tex0[0] = streamExt.tex0[0];
ras->tex0[1] = streamExt.tex0[1];
ras->tex1[0] = streamExt.tex1[0];
ras->tex1[1] = ras->tex1[1]&~0xFF0000 | streamExt.tex1[1]<<16 & 0xFF0000;
ras->miptbp1[0] = streamExt.miptbp1[0];
ras->miptbp1[1] = streamExt.miptbp1[1];
ras->miptbp2[0] = streamExt.miptbp2[0];
ras->miptbp2[1] = streamExt.miptbp2[1];
ras->texelSize = streamExt.texelSize;
ras->paletteSize = streamExt.paletteSize;
ras->gsSize = streamExt.gsSize;
SETKL(ras, streamExt.mipmapVal);
//printf("%08X%08X %08X%08X %08X%08X %08X%08X\n",
// ras->tex0[1], ras->tex0[0], ras->tex1[1], ras->tex1[0],
// ras->miptbp1[0], ras->miptbp1[1], ras->miptbp2[0], ras->miptbp2[1]);
assert(findChunk(stream, ID_STRUCT, &length, NULL));
if(streamExt.type < 2){
stream->read(raster->texels, length);
}else{
stream->read(raster->texels-0x50, ras->texelSize);
stream->read(raster->palette-0x50, ras->paletteSize);
}
tex->streamReadPlugins(stream);
return tex;
}
void
writeNativeTexture(Texture *tex, Stream *stream)
{
Raster *raster = tex->raster;
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
int32 chunksize = getSizeNativeTexture(tex);
writeChunkHeader(stream, ID_TEXTURENATIVE, chunksize);
writeChunkHeader(stream, ID_STRUCT, 8);
stream->writeU32(FOURCC_PS2);
stream->writeU32(tex->filterAddressing);
int32 len = strlen(tex->name)+4 & ~3;
writeChunkHeader(stream, ID_STRING, len);
stream->write(tex->name, len);
len = strlen(tex->mask)+4 & ~3;
writeChunkHeader(stream, ID_STRING, len);
stream->write(tex->mask, len);
int32 sz = ras->texelSize + ras->paletteSize;
writeChunkHeader(stream, ID_STRUCT, 12 + 64 + 12 + sz);
writeChunkHeader(stream, ID_STRUCT, 64);
StreamRasterExt streamExt;
streamExt.width = raster->width;
streamExt.height = raster->height;
streamExt.depth = raster->depth;
streamExt.rasterFormat = raster->format | raster->type;
streamExt.type = 0;
if(ras->flags == 2 && raster->depth == 8)
streamExt.type = 1;
if(ras->flags & 1)
streamExt.type = 2;
streamExt.tex0[0] = ras->tex0[0];
streamExt.tex0[1] = ras->tex0[1];
streamExt.tex1[0] = ras->tex1[0];
streamExt.tex1[1] = ras->tex1[1]>>16 & 0xFF;
streamExt.miptbp1[0] = ras->miptbp1[0];
streamExt.miptbp1[1] = ras->miptbp1[1];
streamExt.miptbp2[0] = ras->miptbp2[0];
streamExt.miptbp2[1] = ras->miptbp2[1];
streamExt.texelSize = ras->texelSize;
streamExt.paletteSize = ras->paletteSize;
streamExt.gsSize = ras->gsSize;
streamExt.mipmapVal = ras->tex1[1]&0xFFFF;
stream->write(&streamExt, 64);
writeChunkHeader(stream, ID_STRUCT, sz);
if(streamExt.type < 2){
stream->write(raster->texels, sz);
}else{
stream->write(raster->texels-0x50, ras->texelSize);
stream->write(raster->palette-0x50, ras->paletteSize);
}
tex->streamWritePlugins(stream);
}
uint32
getSizeNativeTexture(Texture *tex)
{
uint32 size = 12 + 8;
size += 12 + strlen(tex->name)+4 & ~3;
size += 12 + strlen(tex->mask)+4 & ~3;
size += 12 + 12 + 64 + 12;
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, tex->raster, nativeRasterOffset);
size += ras->texelSize + ras->paletteSize;
size += 12 + tex->streamGetPluginSize();
return size;
}
}
}

636
src/ps2raster.cpp Normal file
View File

@ -0,0 +1,636 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"
#include "rwobjects.h"
#include "rwps2.h"
#define max(a, b) ((a) > (b) ? (a) : (b))
namespace rw {
namespace ps2 {
int32 nativeRasterOffset;
#define MAXLEVEL(r) ((r)->tex1[1]>>18 & 0x3F)
#define SETMAXLEVEL(r, l) ((r)->tex1[1] = (r)->tex1[1]&~0xFF0000 | l<<18)
#define SETKL(r, val) ((r)->tex1[1] = (r)->tex1[1]&~0xFFFF | (uint16)(val))
static bool32 noNewStyleRasters;
// i don't really understand this, stolen from RW
static void
ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh)
{
*minh = 1;
switch(psm){
case 0x00:
case 0x30:
*minw = 2; // 32 bit
break;
case 0x02:
case 0x0A:
case 0x32:
case 0x3A:
*minw = 4; // 16 bit
break;
case 0x01:
case 0x13:
case 0x14:
case 0x1B:
case 0x24:
case 0x2C:
case 0x31:
*minw = 8; // everything else
break;
}
if(flags & 0x2 && psm == 0x13){ // PSMT8
*minw = 16;
*minh = 4;
}
if(flags & 0x4 && psm == 0x14){ // PSMT4
*minw = 32;
*minh = 4;
}
}
struct dword
{
uint32 lo;
uint32 hi;
};
#define ALIGN64(x) ((x) + 0x3F & ~0x3F)
void
Ps2Raster::create(Raster *raster)
{
uint64 bufferWidth[7], bufferBase[7];
int32 pageWidth, pageHeight;
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
//printf("%x %x %x %x\n", raster->format, raster->flags, raster->type, noNewStyleRasters);
assert(raster->type == 4); // Texture
switch(raster->depth){
case 4:
pageWidth = 128;
pageHeight = 128;
break;
case 8:
pageWidth = 128;
pageHeight = 64;
break;
case 16:
pageWidth = 64;
pageHeight = 64;
break;
case 32:
pageWidth = 64;
pageHeight = 32;
break;
default:
assert(0 && "unsupported depth");
}
int32 logw = 0, logh = 0;
int32 s;
for(s = 1; s < raster->width; s *= 2)
logw++;
for(s = 1; s < raster->height; s *= 2)
logh++;
SETKL(ras, 0xFC0);
//printf("%d %d %d %d\n", raster->width, logw, raster->height, logh);
ras->tex0[0] |= (raster->width < pageWidth ? pageWidth : raster->width)/64 << 14;
ras->tex0[0] |= logw << 26;
ras->tex0[0] |= logh << 30;
ras->tex0[1] |= logh >> 2;
int32 paletteWidth, paletteHeight, paletteDepth;
int32 palettePagewidth, palettePageheight;
if(raster->format & (Raster::PAL4 | Raster::PAL8))
switch(raster->format & 0xF00){
case Raster::C1555:
ras->tex0[1] |= 0xA << 19; // PSMCT16S
paletteDepth = 2;
palettePagewidth = palettePageheight = 64;
break;
case Raster::C8888:
// PSMCT32
paletteDepth = 4;
palettePagewidth = 64;
palettePageheight = 32;
break;
default:
assert(0 && "unsupported palette format\n");
}
if(raster->format & Raster::PAL4){
ras->tex0[0] |= 0x14 << 20; // PSMT4
ras->tex0[1] |= 1<<29 | 1<<2; // CLD 1, TCC RGBA
paletteWidth = 8;
paletteHeight = 2;
}else if(raster->format & Raster::PAL8){
ras->tex0[0] |= 0x13 << 20; // PSMT8
ras->tex0[1] |= 1<<29 | 1<<2; // CLD 1, TCC RGBA
paletteWidth = paletteHeight = 16;
}else{
paletteWidth = 0;
paletteHeight = 0;
paletteDepth = 0;
palettePagewidth = 0;
palettePageheight = 0;
switch(raster->format & 0xF00){
case Raster::C1555:
ras->tex0[0] |= 0xA << 20; // PSMCT16S
ras->tex0[1] |= 1 << 2; // TCC RGBA
break;
case Raster::C8888:
// PSMCT32
ras->tex0[1] |= 1 << 2; // TCC RGBA
break;
case Raster::C888:
ras->tex0[0] |= 1 << 20; // PSMCT24
break;
default:
assert(0 && "unsupported raster format\n");
}
}
for(int i = 0; i < 7; i++){
bufferWidth[i] = 1;
bufferBase[i] = 0;
}
int32 mipw, miph;
int32 n;
int32 nPagW, nPagH;
int32 w = raster->width;
int32 h = raster->height;
int32 d = raster->depth;
raster->stride = w*d/8;
if(raster->format & Raster::MIPMAP){
static uint32 blockOffset32_24_8[8] = { 0, 2, 2, 8, 8, 10, 10, 32 };
static uint32 blockOffset16_4[8] = { 0, 1, 4, 5, 16, 17, 20, 21 };
static uint32 blockOffset16S[8] = { 0, 1, 8, 9, 4, 5, 12, 13 };
uint64 lastBufferWidth;
mipw = w;
miph = h;
lastBufferWidth = max(pageWidth, w)/64;
ras->texelSize = 0;
int32 gsoffset = 0;
int32 gsaddress = 0;
for(n = 0; n < 7; n++){
if(w >= 8 && h >= 8 && (mipw < 8 || miph < 8))
break;
ras->texelSize += ALIGN64(mipw*miph*d/8);
bufferWidth[n] = max(pageWidth, mipw)/64;
if(bufferWidth[n] != lastBufferWidth){
nPagW = ((w >> n-1) + pageWidth-1)/pageWidth;
nPagH = ((h >> n-1) + pageHeight-1)/pageHeight;
gsaddress = (gsoffset + nPagW*nPagH*0x800) & ~0x7FF;
}
lastBufferWidth = bufferWidth[n];
gsaddress = ALIGN64(gsaddress);
uint32 b = gsaddress/256 & 7;
switch(ras->tex0[0]>>20 & 0x3F){
case 0: case 1: case 0x13:
b = blockOffset32_24_8[b];
break;
case 2: case 0x14:
b = blockOffset16_4[b];
break;
case 0xA:
b = blockOffset16S[b];
break;
default:
// can't happen
break;
}
bufferBase[n] = b + (gsaddress>>11 << 5);
int32 stride = bufferWidth[n]/64*d/8;
gsaddress = ALIGN64(miph*stride/4 + gsoffset);
mipw /= 2;
miph /= 2;
}
assert(0);
}else{
ras->texelSize = raster->stride*raster->height+0xF & ~0xF;
ras->paletteSize = paletteWidth*paletteHeight*paletteDepth;
ras->miptbp1[0] |= 1<<14; // TBW1
ras->miptbp1[1] |= 1<<2 | 1<<22; // TBW2,3
ras->miptbp2[0] |= 1<<14; // TBW4
ras->miptbp2[1] |= 1<<2 | 1<<22; // TBW5,6
SETMAXLEVEL(ras, 0);
nPagW = (raster->width + pageWidth-1)/pageWidth;
nPagH = (raster->height + pageHeight-1)/pageHeight;
bufferBase[0] = 0;
bufferWidth[0] = nPagW * (pageWidth >> 6);
ras->gsSize = (nPagW*nPagH*0x800)&~0x7FF;
if(ras->paletteSize){
// BITBLTBUF DBP
if(pageWidth*nPagW > raster->width ||
pageHeight*nPagH > raster->height)
ras->tex1[0] = (ras->gsSize >> 6) - 4;
else{
ras->tex1[0] = ras->gsSize >> 6;
}
nPagW = (paletteWidth + palettePagewidth-1)/palettePagewidth;
nPagH = (paletteHeight + palettePageheight-1)/palettePageheight;
ras->gsSize += (nPagW*nPagH*0x800)&~0x7FF;
}else
ras->tex1[0] = 0;
}
// allocate data and fill with GIF packets
ras->texelSize = ras->texelSize+0xF & ~0xF;
int32 numLevels = MAXLEVEL(ras)+1;
if(noNewStyleRasters ||
(raster->width*raster->height*raster->depth & ~0x7F) >= 0x3FFF80){
assert(0);
}else{
ras->flags |= 1; // include GIF packets
int32 psm = ras->tex0[0]>>20 & 0x3F;
//int32 cpsm = ras->tex0[1]>>19 & 0x3F;
if(psm == 0x13){ // PSMT8
ras->flags |= 2;
// TODO: stuff
}
if(psm == 0x14){ // PSMT4
// swizzle flag probably depends on version :/
if(rw::version > 0x31000)
ras->flags |= 4;
// TODO: stuff
}
ras->texelSize = 0x50*numLevels; // GIF packets
int32 minW, minH;
ps2MinSize(psm, ras->flags, &minW, &minH);
w = raster->width;
h = raster->height;
n = numLevels;
while(n--){
mipw = w < minW ? minW : w;
miph = h < minH ? minH : h;
ras->texelSize += mipw*miph*raster->depth/8+0xF & ~0xF;
w /= 2;
h /= 2;
}
if(ras->paletteSize){
if(rw::version > 0x31000 && paletteHeight == 2)
paletteHeight = 3;
ras->paletteSize = 0x50 +
paletteDepth*paletteWidth*paletteHeight;
}
// TODO: allocate space for more DMA packets
ras->dataSize = ras->paletteSize+ras->texelSize;
uint8 *data = new uint8[ras->dataSize];
assert(data);
ras->data = data;
raster->texels = data + 0x50;
if(ras->paletteSize)
raster->palette = data + ras->texelSize + 0x50;
uint32 *p = (uint32*)data;
w = raster->width;
h = raster->height;
for(n = 0; n < numLevels; n++){
mipw = w < minW ? minW : w;
miph = h < minH ? minH : h;
// GIF tag
*p++ = 3; // NLOOP = 3
*p++ = 0x10000000; // NREG = 1
*p++ = 0xE; // A+D
*p++ = 0;
// TRXPOS
*p++ = 0; // TODO
*p++ = 0; // TODO
*p++ = 0x51;
*p++ = 0;
// TRXREG
if(ras->flags & 2 && psm == 0x13 ||
ras->flags & 4 && psm == 0x14){
*p++ = mipw/2;
*p++ = miph/2;
}else{
*p++ = mipw;
*p++ = miph;
}
*p++ = 0x52;
*p++ = 0;
// TRXDIR
*p++ = 0; // host -> local
*p++ = 0;
*p++ = 0x53;
*p++ = 0;
// GIF tag
uint32 sz = mipw*miph*raster->depth/8 + 0xF >> 4;
*p++ = sz;
*p++ = 0x08000000; // IMAGE
*p++ = 0;
*p++ = 0;
p += sz*4;
w /= 2;
h /= 2;
}
if(ras->paletteSize){
p = (uint32*)(raster->palette - 0x50);
// GIF tag
*p++ = 3; // NLOOP = 3
*p++ = 0x10000000; // NREG = 1
*p++ = 0xE; // A+D
*p++ = 0;
// TRXPOS
*p++ = 0; // TODO
*p++ = 0; // TODO
*p++ = 0x51;
*p++ = 0;
// TRXREG
*p++ = paletteWidth;
*p++ = paletteHeight;
*p++ = 0x52;
*p++ = 0;
// TRXDIR
*p++ = 0; // host -> local
*p++ = 0;
*p++ = 0x53;
*p++ = 0;
// GIF tag
uint32 sz = paletteSize - 0x50 + 0xF >> 4;
*p++ = sz;
*p++ = 0x08000000; // IMAGE
*p++ = 0;
*p++ = 0;
}
}
}
uint8*
Ps2Raster::lock(Raster *raster, int32 level)
{
// TODO
(void)raster;
(void)level;
return NULL;
}
void
Ps2Raster::unlock(Raster *raster, int32 level)
{
// TODO
(void)raster;
(void)level;
}
int32
Ps2Raster::getNumLevels(Raster *raster)
{
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
if(raster->texels == NULL) return 0;
if(raster->format & Raster::MIPMAP)
return MAXLEVEL(ras)+1;
return 1;
}
static void*
createNativeRaster(void *object, int32 offset, int32)
{
Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, object, offset);
new (raster) Ps2Raster;
raster->tex0[0] = 0;
raster->tex0[1] = 0;
raster->tex1[0] = 0;
raster->tex1[1] = 0;
raster->miptbp1[0] = 0;
raster->miptbp1[1] = 0;
raster->miptbp2[0] = 0;
raster->miptbp2[1] = 0;
raster->texelSize = 0;
raster->paletteSize = 0;
raster->gsSize = 0;
raster->flags = 0;
SETKL(raster, 0xFC0);
raster->dataSize = 0;
raster->data = NULL;
return object;
}
static void*
destroyNativeRaster(void *object, int32 offset, int32)
{
// TODO
(void)offset;
return object;
}
static void*
copyNativeRaster(void *dst, void *src, int32 offset, int32)
{
Ps2Raster *dstraster = PLUGINOFFSET(Ps2Raster, dst, offset);
Ps2Raster *srcraster = PLUGINOFFSET(Ps2Raster, src, offset);
*dstraster = *srcraster;
return dst;
}
static void
readMipmap(Stream *stream, int32, void *object, int32 offset, int32)
{
uint16 val = stream->readI32();
Texture *tex = (Texture*)object;
if(tex->raster == NULL)
return;
Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, tex->raster, offset);
SETKL(raster, val);
}
static void
writeMipmap(Stream *stream, int32, void *object, int32 offset, int32)
{
Texture *tex = (Texture*)object;
assert(tex->raster);
Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, tex->raster, offset);
stream->writeI32(raster->tex1[1]&0xFFFF);
}
static int32
getSizeMipmap(void*, int32, int32)
{
return rw::platform == PLATFORM_PS2 ? 4 : 0;
}
void
registerNativeRaster(void)
{
nativeRasterOffset = Raster::registerPlugin(sizeof(Ps2Raster),
0x12340000 | PLATFORM_PS2,
createNativeRaster,
destroyNativeRaster,
copyNativeRaster);
Raster::nativeOffsets[PLATFORM_PS2] = nativeRasterOffset;
Texture::registerPlugin(0, ID_SKYMIPMAP, NULL, NULL, NULL);
Texture::registerPluginStream(ID_SKYMIPMAP, readMipmap, writeMipmap, getSizeMipmap);
}
struct StreamRasterExt
{
int32 width;
int32 height;
int32 depth;
uint16 rasterFormat;
int16 type;
uint32 tex0[2];
uint32 tex1[2];
uint32 miptbp1[2];
uint32 miptbp2[2];
uint32 texelSize;
uint32 paletteSize;
uint32 gsSize;
uint32 mipmapVal;
};
Texture*
readNativeTexture(Stream *stream)
{
uint32 length, oldversion, version;
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
assert(stream->readU32() == 0x00325350); // 'PS2\0'
Texture *tex = Texture::create(NULL);
// Texture
tex->filterAddressing = stream->readU32();
assert(findChunk(stream, ID_STRING, &length, NULL));
stream->read(tex->name, length);
assert(findChunk(stream, ID_STRING, &length, NULL));
stream->read(tex->mask, length);
// Raster
StreamRasterExt streamExt;
oldversion = rw::version;
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
assert(findChunk(stream, ID_STRUCT, NULL, &version));
stream->read(&streamExt, 0x40);
Raster *raster;
noNewStyleRasters = streamExt.type < 2;
rw::version = version;
raster = Raster::create(streamExt.width, streamExt.height,
streamExt.depth, streamExt.rasterFormat,
PLATFORM_PS2);
noNewStyleRasters = 0;
rw::version = oldversion;
tex->raster = raster;
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
//printf("%08X%08X %08X%08X %08X%08X %08X%08X\n",
// ras->tex0[1], ras->tex0[0], ras->tex1[1], ras->tex1[0],
// ras->miptbp1[0], ras->miptbp1[1], ras->miptbp2[0], ras->miptbp2[1]);
ras->tex0[0] = streamExt.tex0[0];
ras->tex0[1] = streamExt.tex0[1];
ras->tex1[0] = streamExt.tex1[0];
ras->tex1[1] = ras->tex1[1]&~0xFF0000 | streamExt.tex1[1]<<16 & 0xFF0000;
ras->miptbp1[0] = streamExt.miptbp1[0];
ras->miptbp1[1] = streamExt.miptbp1[1];
ras->miptbp2[0] = streamExt.miptbp2[0];
ras->miptbp2[1] = streamExt.miptbp2[1];
ras->texelSize = streamExt.texelSize;
ras->paletteSize = streamExt.paletteSize;
ras->gsSize = streamExt.gsSize;
SETKL(ras, streamExt.mipmapVal);
//printf("%08X%08X %08X%08X %08X%08X %08X%08X\n",
// ras->tex0[1], ras->tex0[0], ras->tex1[1], ras->tex1[0],
// ras->miptbp1[0], ras->miptbp1[1], ras->miptbp2[0], ras->miptbp2[1]);
assert(findChunk(stream, ID_STRUCT, &length, NULL));
if(streamExt.type < 2){
stream->read(raster->texels, length);
}else{
stream->read(raster->texels-0x50, ras->texelSize);
stream->read(raster->palette-0x50, ras->paletteSize);
}
tex->streamReadPlugins(stream);
return tex;
}
void
writeNativeTexture(Texture *tex, Stream *stream)
{
Raster *raster = tex->raster;
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset);
int32 chunksize = getSizeNativeTexture(tex);
writeChunkHeader(stream, ID_TEXTURENATIVE, chunksize);
writeChunkHeader(stream, ID_STRUCT, 8);
stream->writeU32(FOURCC_PS2);
stream->writeU32(tex->filterAddressing);
int32 len = strlen(tex->name)+4 & ~3;
writeChunkHeader(stream, ID_STRING, len);
stream->write(tex->name, len);
len = strlen(tex->mask)+4 & ~3;
writeChunkHeader(stream, ID_STRING, len);
stream->write(tex->mask, len);
int32 sz = ras->texelSize + ras->paletteSize;
writeChunkHeader(stream, ID_STRUCT, 12 + 64 + 12 + sz);
writeChunkHeader(stream, ID_STRUCT, 64);
StreamRasterExt streamExt;
streamExt.width = raster->width;
streamExt.height = raster->height;
streamExt.depth = raster->depth;
streamExt.rasterFormat = raster->format | raster->type;
streamExt.type = 0;
if(ras->flags == 2 && raster->depth == 8)
streamExt.type = 1;
if(ras->flags & 1)
streamExt.type = 2;
streamExt.tex0[0] = ras->tex0[0];
streamExt.tex0[1] = ras->tex0[1];
streamExt.tex1[0] = ras->tex1[0];
streamExt.tex1[1] = ras->tex1[1]>>16 & 0xFF;
streamExt.miptbp1[0] = ras->miptbp1[0];
streamExt.miptbp1[1] = ras->miptbp1[1];
streamExt.miptbp2[0] = ras->miptbp2[0];
streamExt.miptbp2[1] = ras->miptbp2[1];
streamExt.texelSize = ras->texelSize;
streamExt.paletteSize = ras->paletteSize;
streamExt.gsSize = ras->gsSize;
streamExt.mipmapVal = ras->tex1[1]&0xFFFF;
stream->write(&streamExt, 64);
writeChunkHeader(stream, ID_STRUCT, sz);
if(streamExt.type < 2){
stream->write(raster->texels, sz);
}else{
stream->write(raster->texels-0x50, ras->texelSize);
stream->write(raster->palette-0x50, ras->paletteSize);
}
tex->streamWritePlugins(stream);
}
uint32
getSizeNativeTexture(Texture *tex)
{
uint32 size = 12 + 8;
size += 12 + strlen(tex->name)+4 & ~3;
size += 12 + strlen(tex->mask)+4 & ~3;
size += 12 + 12 + 64 + 12;
Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, tex->raster, nativeRasterOffset);
size += ras->texelSize + ras->paletteSize;
size += 12 + tex->streamGetPluginSize();
return size;
}
}
}

View File

@ -3,8 +3,6 @@
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"

View File

@ -83,6 +83,7 @@ struct D3dRaster : NativeRaster
virtual uint8 *lock(Raster *raster, int32 level);
virtual void unlock(Raster *raster, int32 level);
virtual int32 getNumLevels(Raster *raster);
virtual void fromImage(Raster *raster, Image *img);
};
int32 getLevelSize(Raster *raster, int32 level);

View File

@ -51,7 +51,7 @@ struct LLLink
// Have to be careful since the link might be deleted.
#define FORLIST(_link, _list) \
for(LLLink *_next = NULL, *_link = (_list).link.next; \
for(rw::LLLink *_next = NULL, *_link = (_list).link.next; \
_next = (_link)->next, (_link) != (_list).end(); \
(_link) = _next)
@ -303,18 +303,22 @@ struct Raster : PluginBase<Raster>
};
};
#define IGNORERASTERIMP 1
extern bool32 loadTextures;
#define IGNORERASTERIMP 0
struct NativeRaster
{
virtual void create(Raster*)
{ assert(IGNORERASTERIMP && "unimplemented"); };
{ assert(IGNORERASTERIMP && "NativeRaster::create unimplemented"); };
virtual uint8 *lock(Raster*, int32)
{ assert(IGNORERASTERIMP && "unimplemented"); return NULL; };
{ assert(IGNORERASTERIMP && "NativeRaster::lock unimplemented"); return NULL; };
virtual void unlock(Raster*, int32)
{ assert(IGNORERASTERIMP && "unimplemented"); };
{ assert(IGNORERASTERIMP && "NativeRaster::unlock unimplemented"); };
virtual int32 getNumLevels(Raster*)
{ assert(IGNORERASTERIMP && "unimplemented"); return 0; };
{ assert(IGNORERASTERIMP && "NativeRaster::getNumLevels unimplemented"); return 0; };
virtual void fromImage(Raster*, Image *img)
{ assert(IGNORERASTERIMP && "NativeRaster::fromImage unimplemented"); };
};
struct TexDictionary;
@ -426,7 +430,8 @@ struct MatFX
uint32 type;
void setEffects(uint32 flags);
int32 getEffectIndex(uint32 type);
static uint32 getEffects(Material *m);
uint32 getEffectIndex(uint32 type);
void setBumpTexture(Texture *t);
void setBumpCoefficient(float32 coef);
void setEnvTexture(Texture *t);

View File

@ -96,6 +96,7 @@ public:
struct Vertex {
float32 p[3];
float32 t[2];
float32 t1[2];
uint8 c[4];
float32 n[3];
};
@ -155,10 +156,10 @@ void allocateADC(Geometry *geo);
// IDs used by SA
// n atomic material
// 1892 53f20080 53f20081 // ?
// 1 53f20080 53f2008d // triad_buddha01.dff
// 56430 53f20082 53f20083 // world
// 39 53f20082 53f2008f // reflective world
// 1892 53f20080 53f20081 // ? no night colors
// 1 53f20080 53f2008d // triad_buddha01.dff no night colors
// 56430 53f20082 53f20083 // world night colors
// 39 53f20082 53f2008f // reflective world night colors
// 6941 53f20084 53f20085 // vehicles
// 3423 53f20084 53f20087 // vehicles
// 4640 53f20084 53f2008b // vehicles
@ -167,6 +168,7 @@ void allocateADC(Geometry *geo);
Pipeline *getPDSPipe(uint32 data);
void registerPDSPipe(Pipeline *pipe);
void registerPDSPlugin(int32 n);
void registerPluginPDSPipes(void);
// Native Texture and Raster

View File

@ -2,7 +2,6 @@
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <new>
#include <rw.h>

View File

@ -2,7 +2,6 @@
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <new>
#include <rw.h>
#include <args.h>