basic PS2 instancing

This commit is contained in:
aap
2015-07-12 22:57:05 +02:00
parent e9f638db05
commit d832570142
10 changed files with 1186 additions and 504 deletions

View File

@@ -1,492 +1,493 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"
#include "rwobjects.h"
using namespace std;
namespace rw {
//
// TexDictionary
//
TexDictionary *currentTexDictionary;
TexDictionary::TexDictionary(void)
{
this->first = NULL;
}
void
TexDictionary::add(Texture *tex)
{
tex->next = this->first;
this->first = tex;
}
Texture*
TexDictionary::find(const char *name)
{
for(Texture *tex = this->first; tex; tex = tex->next)
if(strncmp(tex->name, name, 32) == 0)
return tex;
return NULL;
}
//
// Texture
//
Texture::Texture(void)
{
memset(this->name, 0, 32);
memset(this->mask, 0, 32);
this->filterAddressing = (WRAP << 12) | (WRAP << 8) | NEAREST;
this->raster = NULL;
this->refCount = 1;
this->next = NULL;
this->constructPlugins();
}
Texture::~Texture(void)
{
this->destructPlugins();
}
void
Texture::decRef(void)
{
this->refCount--;
if(this->refCount)
delete this;
}
// TODO: do this properly, pretty ugly right now
Texture*
Texture::read(const char *name, const char *mask)
{
(void)mask;
Raster *raster = NULL;
Texture *tex;
if(currentTexDictionary && (tex = currentTexDictionary->find(name)))
return tex;
tex = new Texture;
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);
delete img;
}
tex->raster = raster;
if(currentTexDictionary)
currentTexDictionary->add(tex);
return tex;
}
Texture*
Texture::streamRead(Stream *stream)
{
uint32 length;
char name[32], mask[32];
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
uint32 filterAddressing = stream->readU16();
// TODO: what is this? (mipmap? i think)
stream->seek(2);
assert(findChunk(stream, ID_STRING, &length, NULL));
stream->read(name, length);
assert(findChunk(stream, ID_STRING, &length, NULL));
stream->read(mask, length);
Texture *tex = Texture::read(name, mask);
tex->refCount++;
tex->filterAddressing = filterAddressing;
tex->streamReadPlugins(stream);
return tex;
}
bool
Texture::streamWrite(Stream *stream)
{
int size;
writeChunkHeader(stream, ID_TEXTURE, this->streamGetSize());
writeChunkHeader(stream, ID_STRUCT, 4);
stream->writeU32(this->filterAddressing);
// TODO: length can't be > 32
size = strlen(this->name)+4 & ~3;
writeChunkHeader(stream, ID_STRING, size);
stream->write(this->name, size);
size = strlen(this->mask)+4 & ~3;
writeChunkHeader(stream, ID_STRING, size);
stream->write(this->mask, size);
this->streamWritePlugins(stream);
return true;
}
uint32
Texture::streamGetSize(void)
{
uint32 size = 0;
size += 12 + 4;
size += 12 + 12;
size += strlen(this->name)+4 & ~3;
size += strlen(this->mask)+4 & ~3;
size += 12 + this->streamGetPluginSize();
return size;
}
//
// Image
//
Image::Image(int32 width, int32 height, int32 depth)
{
this->flags = 0;
this->width = width;
this->height = height;
this->depth = depth;
this->stride = 0;
this->pixels = NULL;
this->palette = NULL;
}
Image::~Image(void)
{
this->free();
}
void
Image::allocate(void)
{
if(this->pixels == NULL){
this->stride = this->width*(this->depth==4 ? 1 : this->depth/8);
this->pixels = new uint8[this->stride*this->height];
this->flags |= 1;
}
if(this->palette == NULL){
if(this->depth == 4 || this->depth == 8)
this->palette = new uint8[(this->depth==4? 16 : 256)*4];
this->flags |= 2;
}
}
void
Image::free(void)
{
if(this->flags&1)
delete[] this->pixels;
if(this->flags&2)
delete[] this->palette;
}
void
Image::setPixels(uint8 *pixels)
{
this->pixels = pixels;
this->flags |= 1;
}
void
Image::setPalette(uint8 *palette)
{
this->palette = palette;
this->flags |= 2;
}
static char *searchPaths = NULL;
int numSearchPaths = 0;
void
Image::setSearchPath(const char *path)
{
char *p, *end;
::free(searchPaths);
numSearchPaths = 0;
if(path)
searchPaths = p = strdup(path);
else{
searchPaths = NULL;
return;
}
while(p && *p){
end = strchr(p, ';');
if(end)
*end++ = '\0';
numSearchPaths++;
p = end;
}
}
void
Image::printSearchPath(void)
{
char *p = searchPaths;
for(int i = 0; i < numSearchPaths; i++){
printf("%s\n", p);
p += strlen(p) + 1;
}
}
char*
Image::getFilename(const char *name)
{
FILE *f;
char *s, *p = searchPaths;
int len = strlen(name)+1;
if(numSearchPaths == 0){
f = fopen(name, "r");
if(f){
fclose(f);
printf("found %s\n", name);
return strdup(name);
}
return NULL;
}else
for(int i = 0; i < numSearchPaths; i++){
s = (char*)malloc(strlen(p)+len);
strcpy(s, p);
strcat(s, name);
f = fopen(s, "r");
if(f){
fclose(f);
printf("found %s\n", name);
return s;
}
::free(s);
p += strlen(p) + 1;
}
return NULL;
}
//
// TGA I/O
//
#ifndef RW_PS2
#pragma pack(push)
#pragma pack(1)
#define PACKED_STRUCT
#else
#define PACKED_STRUCT __attribute__((__packed__))
#endif
struct PACKED_STRUCT TGAHeader
{
int8 IDlen;
int8 colorMapType;
int8 imageType;
int16 colorMapOrigin;
int16 colorMapLength;
int8 colorMapDepth;
int16 xOrigin, yOrigin;
int16 width, height;
uint8 depth;
uint8 descriptor;
};
#ifndef RW_PS2
#pragma pack(push)
#endif
Image*
readTGA(const char *afilename)
{
TGAHeader header;
Image *image;
char *filename;
int depth = 0, palDepth = 0;
filename = Image::getFilename(afilename);
if(filename == NULL)
return NULL;
uint32 length;
uint8 *data = getFileContents(filename, &length);
assert(data != NULL);
free(filename);
StreamMemory file;
file.open(data, length);
file.read(&header, sizeof(header));
assert(header.imageType == 1 || header.imageType == 2);
file.seek(header.IDlen);
if(header.colorMapType){
assert(header.colorMapOrigin == 0);
depth = (header.colorMapLength <= 16) ? 4 : 8;
palDepth = header.colorMapDepth;
assert(palDepth == 24 || palDepth == 32);
}else{
depth = header.depth;
assert(depth == 24 || depth == 32);
}
image = new Image(header.width, header.height, depth);
image->allocate();
uint8 *palette = header.colorMapType ? image->palette : NULL;
uint8 (*color)[4] = NULL;
if(palette){
int maxlen = depth == 4 ? 16 : 256;
color = (uint8(*)[4])palette;
int i;
for(i = 0; i < header.colorMapLength; i++){
color[i][2] = file.readU8();
color[i][1] = file.readU8();
color[i][0] = file.readU8();
color[i][3] = 0xFF;
if(palDepth == 32)
color[i][3] = file.readU8();
}
for(; i < maxlen; i++){
color[i][0] = color[i][1] = color[i][2] = 0;
color[i][3] = 0xFF;
}
}
uint8 *pixels = image->pixels;
if(!(header.descriptor & 0x20))
pixels += (image->height-1)*image->stride;
for(int y = 0; y < image->height; y++){
uint8 *line = pixels;
for(int x = 0; x < image->width; x++){
if(palette)
*line++ = file.readU8();
else{
line[2] = file.readU8();
line[1] = file.readU8();
line[0] = file.readU8();
line += 3;
if(depth == 32)
*line++ = file.readU8();
}
}
pixels += (header.descriptor&0x20) ?
image->stride : -image->stride;
}
file.close();
delete[] data;
return image;
}
void
writeTGA(Image *image, const char *filename)
{
TGAHeader header;
StreamFile file;
assert(file.open(filename, "wb"));
header.IDlen = 0;
header.imageType = image->palette != NULL ? 1 : 2;
header.colorMapType = image->palette != NULL;
header.colorMapOrigin = 0;
header.colorMapLength = image->depth == 4 ? 16 :
image->depth == 8 ? 256 : 0;
header.colorMapDepth = image->palette ? 32 : 0;
header.xOrigin = 0;
header.yOrigin = 0;
header.width = image->width;
header.height = image->height;
header.depth = image->depth == 4 ? 8 : image->depth;
header.descriptor = 0x20 | (image->depth == 32 ? 8 : 0);
file.write(&header, sizeof(header));
uint8 *pixels = image->pixels;
uint8 *palette = header.colorMapType ? image->palette : NULL;
uint8 (*color)[4] = (uint8(*)[4])palette;;
if(palette)
for(int i = 0; i < header.colorMapLength; i++){
file.writeU8(color[i][2]);
file.writeU8(color[i][1]);
file.writeU8(color[i][0]);
file.writeU8(color[i][3]);
}
for(int y = 0; y < image->height; y++){
uint8 *line = pixels;
for(int x = 0; x < image->width; x++){
if(palette)
file.writeU8(*line++);
else{
file.writeU8(line[2]);
file.writeU8(line[1]);
file.writeU8(line[0]);
line += 3;
if(image->depth == 32)
file.writeU8(*line++);
}
}
pixels += image->stride;
}
file.close();
}
//
// Raster
//
Raster::Raster(void)
{
this->type = 0;
this->width = this->height = this->depth = this->stride = 0;
this->format = 0;
this->texels = this->palette = NULL;
this->constructPlugins();
}
Raster::~Raster(void)
{
this->destructPlugins();
delete[] this->texels;
delete[] this->palette;
}
Raster*
Raster::createFromImage(Image *image)
{
Raster *raster = new Raster;
raster->type = 4;
raster->width = image->width;
raster->stride = image->stride;
raster->height = image->height;
raster->depth = image->depth;
raster->texels = raster->palette = NULL;
if(raster->depth == 32)
raster->format = Raster::C8888;
else if(raster->depth == 24)
raster->format = Raster::C888;
else if(raster->depth == 16)
raster->format = Raster::C1555;
else if(raster->depth == 8)
raster->format = Raster::PAL8 | Raster::C8888;
else if(raster->depth == 4)
raster->format = Raster::PAL4 | Raster::C8888;
else{
delete raster;
return NULL;
}
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);
}
return raster;
}
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <new>
#include "rwbase.h"
#include "rwplugin.h"
#include "rwpipeline.h"
#include "rwobjects.h"
using namespace std;
namespace rw {
//
// TexDictionary
//
TexDictionary *currentTexDictionary;
TexDictionary::TexDictionary(void)
{
this->first = NULL;
}
void
TexDictionary::add(Texture *tex)
{
tex->next = this->first;
this->first = tex;
}
Texture*
TexDictionary::find(const char *name)
{
for(Texture *tex = this->first; tex; tex = tex->next)
if(strncmp(tex->name, name, 32) == 0)
return tex;
return NULL;
}
//
// Texture
//
Texture::Texture(void)
{
memset(this->name, 0, 32);
memset(this->mask, 0, 32);
this->filterAddressing = (WRAP << 12) | (WRAP << 8) | NEAREST;
this->raster = NULL;
this->refCount = 1;
this->next = NULL;
this->constructPlugins();
}
Texture::~Texture(void)
{
this->destructPlugins();
}
void
Texture::decRef(void)
{
this->refCount--;
if(this->refCount)
delete this;
}
// TODO: do this properly, pretty ugly right now
Texture*
Texture::read(const char *name, const char *mask)
{
(void)mask;
Raster *raster = NULL;
Texture *tex;
if(currentTexDictionary && (tex = currentTexDictionary->find(name)))
return tex;
tex = new Texture;
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);
delete img;
}
tex->raster = raster;
if(currentTexDictionary)
currentTexDictionary->add(tex);
return tex;
}
Texture*
Texture::streamRead(Stream *stream)
{
uint32 length;
char name[32], mask[32];
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
uint32 filterAddressing = stream->readU16();
// TODO: what is this? (mipmap? i think)
stream->seek(2);
assert(findChunk(stream, ID_STRING, &length, NULL));
stream->read(name, length);
assert(findChunk(stream, ID_STRING, &length, NULL));
stream->read(mask, length);
Texture *tex = Texture::read(name, mask);
tex->refCount++;
tex->filterAddressing = filterAddressing;
tex->streamReadPlugins(stream);
return tex;
}
bool
Texture::streamWrite(Stream *stream)
{
int size;
writeChunkHeader(stream, ID_TEXTURE, this->streamGetSize());
writeChunkHeader(stream, ID_STRUCT, 4);
stream->writeU32(this->filterAddressing);
// TODO: length can't be > 32
size = strlen(this->name)+4 & ~3;
writeChunkHeader(stream, ID_STRING, size);
stream->write(this->name, size);
size = strlen(this->mask)+4 & ~3;
writeChunkHeader(stream, ID_STRING, size);
stream->write(this->mask, size);
this->streamWritePlugins(stream);
return true;
}
uint32
Texture::streamGetSize(void)
{
uint32 size = 0;
size += 12 + 4;
size += 12 + 12;
size += strlen(this->name)+4 & ~3;
size += strlen(this->mask)+4 & ~3;
size += 12 + this->streamGetPluginSize();
return size;
}
//
// Image
//
Image::Image(int32 width, int32 height, int32 depth)
{
this->flags = 0;
this->width = width;
this->height = height;
this->depth = depth;
this->stride = 0;
this->pixels = NULL;
this->palette = NULL;
}
Image::~Image(void)
{
this->free();
}
void
Image::allocate(void)
{
if(this->pixels == NULL){
this->stride = this->width*(this->depth==4 ? 1 : this->depth/8);
this->pixels = new uint8[this->stride*this->height];
this->flags |= 1;
}
if(this->palette == NULL){
if(this->depth == 4 || this->depth == 8)
this->palette = new uint8[(this->depth==4? 16 : 256)*4];
this->flags |= 2;
}
}
void
Image::free(void)
{
if(this->flags&1)
delete[] this->pixels;
if(this->flags&2)
delete[] this->palette;
}
void
Image::setPixels(uint8 *pixels)
{
this->pixels = pixels;
this->flags |= 1;
}
void
Image::setPalette(uint8 *palette)
{
this->palette = palette;
this->flags |= 2;
}
static char *searchPaths = NULL;
int numSearchPaths = 0;
void
Image::setSearchPath(const char *path)
{
char *p, *end;
::free(searchPaths);
numSearchPaths = 0;
if(path)
searchPaths = p = strdup(path);
else{
searchPaths = NULL;
return;
}
while(p && *p){
end = strchr(p, ';');
if(end)
*end++ = '\0';
numSearchPaths++;
p = end;
}
}
void
Image::printSearchPath(void)
{
char *p = searchPaths;
for(int i = 0; i < numSearchPaths; i++){
printf("%s\n", p);
p += strlen(p) + 1;
}
}
char*
Image::getFilename(const char *name)
{
FILE *f;
char *s, *p = searchPaths;
int len = strlen(name)+1;
if(numSearchPaths == 0){
f = fopen(name, "r");
if(f){
fclose(f);
printf("found %s\n", name);
return strdup(name);
}
return NULL;
}else
for(int i = 0; i < numSearchPaths; i++){
s = (char*)malloc(strlen(p)+len);
strcpy(s, p);
strcat(s, name);
f = fopen(s, "r");
if(f){
fclose(f);
printf("found %s\n", name);
return s;
}
::free(s);
p += strlen(p) + 1;
}
return NULL;
}
//
// TGA I/O
//
// TODO: fuck pakced structs
#ifndef RW_PS2
#pragma pack(push)
#pragma pack(1)
#define PACKED_STRUCT
#else
#define PACKED_STRUCT __attribute__((__packed__))
#endif
struct PACKED_STRUCT TGAHeader
{
int8 IDlen;
int8 colorMapType;
int8 imageType;
int16 colorMapOrigin;
int16 colorMapLength;
int8 colorMapDepth;
int16 xOrigin, yOrigin;
int16 width, height;
uint8 depth;
uint8 descriptor;
};
#ifndef RW_PS2
#pragma pack(push)
#endif
Image*
readTGA(const char *afilename)
{
TGAHeader header;
Image *image;
char *filename;
int depth = 0, palDepth = 0;
filename = Image::getFilename(afilename);
if(filename == NULL)
return NULL;
uint32 length;
uint8 *data = getFileContents(filename, &length);
assert(data != NULL);
free(filename);
StreamMemory file;
file.open(data, length);
file.read(&header, sizeof(header));
assert(header.imageType == 1 || header.imageType == 2);
file.seek(header.IDlen);
if(header.colorMapType){
assert(header.colorMapOrigin == 0);
depth = (header.colorMapLength <= 16) ? 4 : 8;
palDepth = header.colorMapDepth;
assert(palDepth == 24 || palDepth == 32);
}else{
depth = header.depth;
assert(depth == 24 || depth == 32);
}
image = new Image(header.width, header.height, depth);
image->allocate();
uint8 *palette = header.colorMapType ? image->palette : NULL;
uint8 (*color)[4] = NULL;
if(palette){
int maxlen = depth == 4 ? 16 : 256;
color = (uint8(*)[4])palette;
int i;
for(i = 0; i < header.colorMapLength; i++){
color[i][2] = file.readU8();
color[i][1] = file.readU8();
color[i][0] = file.readU8();
color[i][3] = 0xFF;
if(palDepth == 32)
color[i][3] = file.readU8();
}
for(; i < maxlen; i++){
color[i][0] = color[i][1] = color[i][2] = 0;
color[i][3] = 0xFF;
}
}
uint8 *pixels = image->pixels;
if(!(header.descriptor & 0x20))
pixels += (image->height-1)*image->stride;
for(int y = 0; y < image->height; y++){
uint8 *line = pixels;
for(int x = 0; x < image->width; x++){
if(palette)
*line++ = file.readU8();
else{
line[2] = file.readU8();
line[1] = file.readU8();
line[0] = file.readU8();
line += 3;
if(depth == 32)
*line++ = file.readU8();
}
}
pixels += (header.descriptor&0x20) ?
image->stride : -image->stride;
}
file.close();
delete[] data;
return image;
}
void
writeTGA(Image *image, const char *filename)
{
TGAHeader header;
StreamFile file;
assert(file.open(filename, "wb"));
header.IDlen = 0;
header.imageType = image->palette != NULL ? 1 : 2;
header.colorMapType = image->palette != NULL;
header.colorMapOrigin = 0;
header.colorMapLength = image->depth == 4 ? 16 :
image->depth == 8 ? 256 : 0;
header.colorMapDepth = image->palette ? 32 : 0;
header.xOrigin = 0;
header.yOrigin = 0;
header.width = image->width;
header.height = image->height;
header.depth = image->depth == 4 ? 8 : image->depth;
header.descriptor = 0x20 | (image->depth == 32 ? 8 : 0);
file.write(&header, sizeof(header));
uint8 *pixels = image->pixels;
uint8 *palette = header.colorMapType ? image->palette : NULL;
uint8 (*color)[4] = (uint8(*)[4])palette;;
if(palette)
for(int i = 0; i < header.colorMapLength; i++){
file.writeU8(color[i][2]);
file.writeU8(color[i][1]);
file.writeU8(color[i][0]);
file.writeU8(color[i][3]);
}
for(int y = 0; y < image->height; y++){
uint8 *line = pixels;
for(int x = 0; x < image->width; x++){
if(palette)
file.writeU8(*line++);
else{
file.writeU8(line[2]);
file.writeU8(line[1]);
file.writeU8(line[0]);
line += 3;
if(image->depth == 32)
file.writeU8(*line++);
}
}
pixels += image->stride;
}
file.close();
}
//
// Raster
//
Raster::Raster(void)
{
this->type = 0;
this->width = this->height = this->depth = this->stride = 0;
this->format = 0;
this->texels = this->palette = NULL;
this->constructPlugins();
}
Raster::~Raster(void)
{
this->destructPlugins();
delete[] this->texels;
delete[] this->palette;
}
Raster*
Raster::createFromImage(Image *image)
{
Raster *raster = new Raster;
raster->type = 4;
raster->width = image->width;
raster->stride = image->stride;
raster->height = image->height;
raster->depth = image->depth;
raster->texels = raster->palette = NULL;
if(raster->depth == 32)
raster->format = Raster::C8888;
else if(raster->depth == 24)
raster->format = Raster::C888;
else if(raster->depth == 16)
raster->format = Raster::C1555;
else if(raster->depth == 8)
raster->format = Raster::PAL8 | Raster::C8888;
else if(raster->depth == 4)
raster->format = Raster::PAL4 | Raster::C8888;
else{
delete raster;
return NULL;
}
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);
}
return raster;
}
}

54
src/pipeline.cpp Normal file
View File

@@ -0,0 +1,54 @@
#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"
using namespace std;
namespace rw {
Pipeline::Pipeline(uint32 platform)
{
this->pluginID = 0;
this->pluginData = 0;
this->platform = platform;
for(int i = 0; i < 10; i++)
this->attribs[i] = NULL;
}
Pipeline::Pipeline(Pipeline *)
{
assert(0 && "Can't copy pipeline");
}
Pipeline::~Pipeline(void)
{
}
void
Pipeline::instance(Atomic *atomic)
{
fprintf(stderr, "This pipeline can't instance\n");
}
void
Pipeline::uninstance(Atomic *atomic)
{
fprintf(stderr, "This pipeline can't uninstance\n");
}
void
Pipeline::render(Atomic *atomic)
{
fprintf(stderr, "This pipeline can't render\n");
}
}

View File

@@ -554,7 +554,8 @@ registerSkinPlugin(void)
defpipe->pluginData = 1;
for(uint i = 0; i < nelem(matFXGlobals.pipelines); i++)
skinGlobals.pipelines[i] = defpipe;
skinGlobals.pipelines[platformIdx[PLATFORM_PS2]] =
ps2::makeSkinPipeline();
skinGlobals.offset = Geometry::registerPlugin(sizeof(Skin*), ID_SKIN,
createSkin,
@@ -883,6 +884,8 @@ registerMatFXPlugin(void)
defpipe->pluginData = 0;
for(uint i = 0; i < nelem(matFXGlobals.pipelines); i++)
matFXGlobals.pipelines[i] = defpipe;
matFXGlobals.pipelines[platformIdx[PLATFORM_PS2]] =
ps2::makeMatFXPipeline();
matFXGlobals.atomicOffset =
Atomic::registerPlugin(sizeof(int32), ID_MATFX,

View File

@@ -126,7 +126,7 @@ fixDmaOffsets(InstanceData *inst)
// DMAref
case 0x30000000:
// fix address and jump to next
tag[1] = base + tag[1]*0x10;
tag[1] = base + tag[1]<<4;
tag += 4;
break;
@@ -165,7 +165,7 @@ unfixDmaOffsets(InstanceData *inst)
// DMAref
case 0x30000000:
// unfix address and jump to next
tag[1] = (tag[1] - base)/0x10;
tag[1] = (tag[1] - base)>>4;
tag += 4;
break;
@@ -203,9 +203,8 @@ enum PS2Attribs {
enum PS2AttibTypes {
AT_XYZ = 0,
AT_UV = 1,
AT_UV2 = 2,
AT_RGBA = 3,
AT_NORMAL = 4
AT_RGBA = 2,
AT_NORMAL = 3
};
PipeAttribute attribXYZ = {
@@ -241,6 +240,301 @@ PipeAttribute attribWeights = {
Pipeline::Pipeline(uint32 platform)
: rw::Pipeline(platform) { }
static uint32
attribSize(uint32 unpack)
{
static uint32 size[] = { 32, 16, 8, 16 };
return ((unpack>>26 & 3)+1)*size[unpack>>24 & 3]/8;
}
#define QWC(x) (((x)+0xF)>>4)
static uint32
getBatchSize(Pipeline *pipe, uint32 vertCount)
{
PipeAttribute *a;
uint32 size = 1;
for(uint i = 0; i < nelem(pipe->attribs); i++)
if((a = pipe->attribs[i]) && (a->attrib & AT_RW) == 0){
size++;
size += QWC(vertCount*attribSize(a->attrib));
}
return size;
}
uint32*
instanceXYZ(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
{
uint16 j;
uint32 *d = (uint32*)g->morphTargets[0].vertices;
for(uint32 i = idx; i < idx+n; i++){
j = m->indices[i];
*p++ = d[j*3+0];
*p++ = d[j*3+1];
*p++ = d[j*3+2];
}
while((uintptr)p % 0x10)
*p++ = 0;
return p;
}
uint32*
instanceUV(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
{
uint16 j;
uint32 *d = (uint32*)g->texCoords[0];
if((g->geoflags & Geometry::TEXTURED) ||
(g->geoflags & Geometry::TEXTURED2))
for(uint32 i = idx; i < idx+n; i++){
j = m->indices[i];
*p++ = d[j*2+0];
*p++ = d[j*2+1];
}
else
for(uint32 i = idx; i < idx+n; i++){
*p++ = 0;
*p++ = 0;
}
while((uintptr)p % 0x10)
*p++ = 0;
return p;
}
uint32*
instanceRGBA(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
{
uint16 j;
uint32 *d = (uint32*)g->colors;
if((g->geoflags & Geometry::PRELIT))
for(uint32 i = idx; i < idx+n; i++){
j = m->indices[i];
*p++ = d[j];
}
else
for(uint32 i = idx; i < idx+n; i++)
*p++ = 0xFF000000;
while((uintptr)p % 0x10)
*p++ = 0;
return p;
}
uint32*
instanceNormal(uint32 *wp, Geometry *g, Mesh *m, uint32 idx, uint32 n)
{
uint16 j;
float *d = g->morphTargets[0].normals;
uint8 *p = (uint8*)wp;
if((g->geoflags & Geometry::NORMALS))
for(uint32 i = idx; i < idx+n; i++){
j = m->indices[i];
*p++ = d[j*3+0]*127.0f;
*p++ = d[j*3+1]*127.0f;
*p++ = d[j*3+2]*127.0f;
}
else
for(uint32 i = idx; i < idx+n; i++){
*p++ = 0;
*p++ = 0;
*p++ = 0;
}
while((uintptr)p % 0x10)
*p++ = 0;
return (uint32*)p;
}
uint32 markcnt = 0xf790;
static void
instanceMat(Pipeline *pipe, Geometry *g, InstanceData *inst, Mesh *m)
{
PipeAttribute *a;
uint32 numAttribs = 0;
uint32 numBrokenAttribs = 0;
for(uint i = 0; i < nelem(pipe->attribs); i++)
if(a = pipe->attribs[i])
if(a->attrib & AT_RW)
numBrokenAttribs++;
else
numAttribs++;
uint32 numBatches = 0;
uint32 totalVerts = 0;
uint32 batchVertCount, lastBatchVertCount;
if(g->meshHeader->flags == 1){ // tristrip
for(uint i = 0; i < m->numIndices; i += pipe->triStripCount-2){
numBatches++;
totalVerts += m->numIndices-i < pipe->triStripCount ?
m->numIndices-i : pipe->triStripCount;
}
batchVertCount = pipe->triStripCount;
lastBatchVertCount = totalVerts%pipe->triStripCount;
}else{ // trilist
numBatches = (m->numIndices+pipe->triListCount-1) /
pipe->triListCount;
totalVerts = m->numIndices;
batchVertCount = pipe->triListCount;
lastBatchVertCount = totalVerts%pipe->triListCount;
}
uint32 batchSize = getBatchSize(pipe, batchVertCount);
uint32 lastBatchSize = getBatchSize(pipe, lastBatchVertCount);
uint32 size = 0;
if(numBrokenAttribs == 0)
size = 1 + batchSize*(numBatches-1) + lastBatchSize;
else
size = 2*numBatches +
(1+batchSize)*(numBatches-1) + 1+lastBatchSize;
/* figure out size and addresses of broken out sections */
uint32 attribPos[nelem(pipe->attribs)];
uint32 size2 = 0;
for(uint i = 0; i < nelem(pipe->attribs); i++)
if((a = pipe->attribs[i]) && a->attrib & AT_RW){
attribPos[i] = size2 + size;
size2 += QWC(m->numIndices*attribSize(a->attrib));
}
/*
printf("attribs: %d %d\n", numAttribs, numBrokenAttribs);
printf("numIndices: %d\n", m->numIndices);
printf("%d %d, %x %x\n", numBatches, totalVerts,
batchVertCount, lastBatchVertCount);
printf("%x %x\n", batchSize, lastBatchSize);
printf("size: %x, %x\n", size, size2);
*/
inst->dataSize = (size+size2)<<4;
inst->arePointersFixed = numBrokenAttribs == 0;
// TODO: force alignment
inst->data = new uint8[inst->dataSize];
uint32 idx = 0;
uint32 *p = (uint32*)inst->data;
if(numBrokenAttribs == 0){
*p++ = 0x60000000 | size-1;
*p++ = 0;
*p++ = 0x11000000; // FLUSH
*p++ = 0x06000000; // MSKPATH3; SA: FLUSH
}
for(uint32 j = 0; j < numBatches; j++){
uint32 nverts, bsize;
if(j < numBatches-1){
bsize = batchSize;
nverts = batchVertCount;
}else{
bsize = lastBatchSize;
nverts = lastBatchVertCount;
}
for(uint i = 0; i < nelem(pipe->attribs); i++)
if((a = pipe->attribs[i]) && a->attrib & AT_RW){
uint32 atsz = attribSize(a->attrib);
*p++ = 0x30000000 | QWC(nverts*atsz);
*p++ = attribPos[i];
*p++ = 0x01000100 |
pipe->inputStride; // STCYCL
*p++ = (a->attrib&0xFF004000)
| 0x8000 | nverts << 16 | i; // UNPACK
*p++ = 0x10000000;
*p++ = 0x0;
*p++ = 0x0;
*p++ = 0x0;
attribPos[i] += g->meshHeader->flags == 1 ?
QWC((batchVertCount-2)*atsz) :
QWC(batchVertCount*atsz);
}
if(numBrokenAttribs){
*p++ = (j < numBatches-1 ? 0x10000000 : 0x60000000) |
bsize;
*p++ = 0x0;
*p++ = 0x0;
*p++ = 0x0;
}
for(uint i = 0; i < nelem(pipe->attribs); i++)
if((a = pipe->attribs[i]) && (a->attrib & AT_RW) == 0){
*p++ = 0x07000000 | markcnt++; // MARK (SA: NOP)
*p++ = 0x05000000; // STMOD
*p++ = 0x01000100 |
pipe->inputStride; // STCYCL
*p++ = (a->attrib&0xFF004000)
| 0x8000 | nverts << 16 | i; // UNPACK
// TODO: instance
switch(i){
case 0:
p = instanceXYZ(p, g, m, idx, nverts);
break;
case 1:
p = instanceUV(p, g, m, idx, nverts);
break;
case 2:
p = instanceRGBA(p, g, m, idx, nverts);
break;
case 3:
p = instanceNormal(p,g, m, idx, nverts);
break;
}
}
idx += g->meshHeader->flags == 1
? batchVertCount-2 : batchVertCount;
*p++ = 0x04000000 | nverts; // ITOP
*p++ = j == 0 ? 0x15000000 : 0x17000000;
if(j < numBatches-1){
*p++ = 0x0;
*p++ = 0x0;
}else{
*p++ = 0x11000000; // FLUSH
*p++ = 0x06000000; // MSKPATH3; SA: FLUSH
}
}
/*
FILE *f = fopen("out.bin", "w");
fwrite(inst->data, inst->dataSize, 1, f);
fclose(f);
*/
}
#undef QWC
void
Pipeline::instance(Atomic *atomic)
{
Geometry *geometry = atomic->geometry;
InstanceDataHeader *header = new InstanceDataHeader;
geometry->instData = header;
header->platform = PLATFORM_PS2;
assert(geometry->meshHeader != NULL);
header->numMeshes = geometry->meshHeader->numMeshes;
header->instanceMeshes = new InstanceData[header->numMeshes];
for(uint32 i = 0; i < header->numMeshes; i++){
Mesh *mesh = &geometry->meshHeader->mesh[i];
InstanceData *instance = &header->instanceMeshes[i];
// TODO: should depend on material pipeline
instanceMat(this, geometry, instance, mesh);
//printf("\n");
}
geometry->geoflags |= Geometry::NATIVE;
}
// Only a dummy right now
void
Pipeline::uninstance(Atomic *atomic)
{
Geometry *geometry = atomic->geometry;
assert(geometry->instData->platform == PLATFORM_PS2);
assert(geometry->instData != NULL);
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
for(uint32 i = 0; i < header->numMeshes; i++){
Mesh *mesh = &geometry->meshHeader->mesh[i];
InstanceData *instance = &header->instanceMeshes[i];
printf("numIndices: %d\n", mesh->numIndices);
printDMA(instance);
}
}
void
Pipeline::setTriBufferSizes(uint32 inputStride,
uint32 stripCount, uint32 listCount)
@@ -277,6 +571,8 @@ Pipeline*
makeSkinPipeline(void)
{
Pipeline *pipe = new Pipeline(PLATFORM_PS2);
pipe->pluginID = ID_SKIN;
pipe->pluginData = 1;
pipe->attribs[AT_XYZ] = &attribXYZ;
pipe->attribs[AT_UV] = &attribUV;
pipe->attribs[AT_RGBA] = &attribRGBA;
@@ -288,6 +584,24 @@ makeSkinPipeline(void)
return pipe;
}
Pipeline*
makeMatFXPipeline(void)
{
Pipeline *pipe = new Pipeline(PLATFORM_PS2);
pipe->pluginID = ID_MATFX;
pipe->pluginData = 0;
pipe->attribs[AT_XYZ] = &attribXYZ;
pipe->attribs[AT_UV] = &attribUV;
pipe->attribs[AT_RGBA] = &attribRGBA;
pipe->attribs[AT_NORMAL] = &attribNormal;
// TODO: not correct
uint32 vertCount = Pipeline::getVertCount(VU_Lights, 4, 3, 2);
pipe->setTriBufferSizes(4, vertCount, vertCount/3);
pipe->triStripCount = 0x38;
pipe->vifOffset = pipe->inputStride*vertCount;
return pipe;
}
void
dumpPipeline(rw::Pipeline *rwpipe)
{
@@ -454,6 +768,32 @@ registerADCPlugin(void)
// misc stuff
void
printDMA(InstanceData *inst)
{
uint32 *tag = (uint32*)inst->data;
for(;;){
switch(tag[0]&0x70000000){
// DMAcnt
case 0x10000000:
printf("%08x %08x\n", tag[0], tag[1]);
tag += (1+(tag[0]&0xFFFF))*4;
break;
// DMAref
case 0x30000000:
printf("%08x %08x\n", tag[0], tag[1]);
tag += 4;
break;
// DMAret
case 0x60000000:
printf("%08x %08x\n", tag[0], tag[1]);
return;
}
}
}
/* Function to specifically walk geometry chains */
void
walkDMA(InstanceData *inst, void (*f)(uint32 *data, int32 size))
@@ -471,7 +811,7 @@ walkDMA(InstanceData *inst, void (*f)(uint32 *data, int32 size))
break;
// DMAref
case 0x3000000:
case 0x30000000:
f(base + tag[1]*4, (tag[0]&0xFFFF)*4);
tag += 4;
break;

View File

@@ -18,7 +18,7 @@ int version = 0x36003;
int build = 0xFFFF;
#ifdef RW_PS2
int platform = PLATFORM_PS2;
#elseif RW_OPENGL
#elif RW_OPENGL
int platform = PLATFORM_OPENGL;
#else
int platform = PLATFORM_NULL;

27
src/rwpipeline.h Normal file
View File

@@ -0,0 +1,27 @@
namespace rw {
struct PipeAttribute
{
const char *name;
uint32 attrib;
};
struct Atomic;
struct Pipeline
{
uint32 pluginID;
uint32 pluginData;
uint32 platform;
PipeAttribute *attribs[10];
Pipeline(uint32 platform);
Pipeline(Pipeline *p);
~Pipeline(void);
virtual void instance(Atomic *atomic);
virtual void uninstance(Atomic *atomic);
virtual void render(Atomic *atomic);
};
}

View File

@@ -29,6 +29,7 @@ void writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
int32 getSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
void printDMA(InstanceData *inst);
void walkDMA(InstanceData *inst, void (*f)(uint32 *data, int32 size));
void sizedebug(InstanceData *inst);
@@ -49,12 +50,16 @@ struct Pipeline : rw::Pipeline
}
Pipeline(uint32 platform);
virtual void instance(Atomic *atomic);
virtual void uninstance(Atomic *atomic);
// virtual void render(Atomic *atomic);
void setTriBufferSizes(uint32 inputStride,
uint32 stripCount, uint32 listCount);
};
Pipeline *makeDefaultPipeline(void);
Pipeline *makeSkinPipeline(void);
Pipeline *makeMatFXPipeline(void);
void dumpPipeline(rw::Pipeline *pipe);
// Skin plugin