mirror of
https://github.com/aap/librw.git
synced 2024-11-25 13:15:43 +00:00
various changes
This commit is contained in:
parent
6d56a23dd1
commit
ef58d76bc0
72
librw.sln
72
librw.sln
@ -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
|
||||
|
@ -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" />
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "rwbase.h"
|
||||
#include "rwplugin.h"
|
||||
#include "rwpipeline.h"
|
||||
|
@ -4,8 +4,6 @@
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "rwbase.h"
|
||||
#include "rwplugin.h"
|
||||
#include "rwpipeline.h"
|
||||
|
76
src/d3d.cpp
76
src/d3d.cpp
@ -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)
|
||||
{
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "rwbase.h"
|
||||
#include "rwplugin.h"
|
||||
#include "rwpipeline.h"
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "rwbase.h"
|
||||
#include "rwplugin.h"
|
||||
#include "rwpipeline.h"
|
||||
|
@ -4,8 +4,6 @@
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "rwbase.h"
|
||||
#include "rwplugin.h"
|
||||
#include "rwpipeline.h"
|
||||
|
1378
src/gtaplg.cpp
1378
src/gtaplg.cpp
File diff suppressed because it is too large
Load Diff
139
src/gtaplg.h
139
src/gtaplg.h
@ -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);
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "rwbase.h"
|
||||
#include "rwplugin.h"
|
||||
#include "rwpipeline.h"
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "rwbase.h"
|
||||
#include "rwplugin.h"
|
||||
#include "rwpipeline.h"
|
||||
|
@ -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++)
|
||||
|
690
src/ps2.cpp
690
src/ps2.cpp
@ -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
636
src/ps2raster.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -3,8 +3,6 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "rwbase.h"
|
||||
#include "rwplugin.h"
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
10
src/rwps2.h
10
src/rwps2.h
@ -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
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <new>
|
||||
|
||||
#include <rw.h>
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <new>
|
||||
|
||||
#include <rw.h>
|
||||
#include <args.h>
|
||||
|
Loading…
Reference in New Issue
Block a user