From 70739e354ec0ec89dad28ac67d2c9189e6a74b83 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 9 Aug 2017 10:57:32 +0200 Subject: [PATCH 1/8] worked on engine and d3ddriver --- premake5.lua | 10 +- src/base.err | 6 + src/camera.cpp | 17 +- src/clump.cpp | 2 +- src/d3d/d3d.cpp | 10 +- src/d3d/d3d8.cpp | 36 ++-- src/d3d/d3d8render.cpp | 18 +- src/d3d/d3d9.cpp | 22 +-- src/d3d/d3d9render.cpp | 22 ++- src/d3d/d3ddriver.cpp | 339 ++++++++++++++++++++++++++++++++-- src/d3d/d3drender.cpp | 70 +++++++ src/d3d/rwd3d.h | 15 +- src/d3d/xbox.cpp | 16 +- src/d3d/xboxplugins.cpp | 2 +- src/engine.cpp | 150 +++++++++++---- src/geoplg.cpp | 1 + src/gl/gl3.cpp | 14 +- src/gl/gl3driver.cpp | 175 ++++++++++++++---- src/gl/gl3render.cpp | 5 +- src/gl/gl3shader.cpp | 6 +- src/gl/rwgl3.h | 18 +- src/gl/shaders/im2d.frag | 2 +- src/gl/shaders/im2d_gl3.inc | 2 +- src/gl/shaders/matfx_env.frag | 2 +- src/gl/shaders/matfx_gl3.inc | 2 +- src/gl/shaders/simple.frag | 2 +- src/gl/shaders/simple_gl3.inc | 2 +- src/gl/wdgl.cpp | 2 +- src/hanim.cpp | 1 + src/image.cpp | 12 +- src/ps2/ps2.cpp | 14 +- src/ps2/ps2raster.cpp | 4 +- src/ps2/ps2skin.cpp | 2 +- src/rwengine.h | 86 ++++++--- src/rwerror.h | 2 +- src/rwobjects.h | 1 + 36 files changed, 869 insertions(+), 221 deletions(-) create mode 100644 src/d3d/d3drender.cpp diff --git a/premake5.lua b/premake5.lua index 591ab10..b1934e6 100755 --- a/premake5.lua +++ b/premake5.lua @@ -1,3 +1,6 @@ +GLEWdir = "C:/Users/aap/src/glew-2.1.0" +GLFW64dir = "C:/Users/aap/src/glfw-3.2.1.bin.WIN64" + workspace "librw" location "build" language "C++" @@ -41,8 +44,13 @@ workspace "librw" filter { "platforms:linux*" } system "linux" + filter { "platforms:win*gl3" } + defines { "GLEW_STATIC" } + includedirs { path.join(GLEWdir, "include") } + includedirs { path.join(GLFW64dir, "include") } + filter "action:vs*" - buildoptions { "/wd4996" } + buildoptions { "/wd4996", "/wd4244" } filter {} diff --git a/src/base.err b/src/base.err index 52df5b2..a02a9c0 100644 --- a/src/base.err +++ b/src/base.err @@ -10,3 +10,9 @@ ECODE(ERR_VERSION, "Unsupported version %X") ECODE(ERR_PLATFORM, "Unsupported platform %d") +ECODE(ERR_ENGINEINIT, + "Engine could not be initialized") +ECODE(ERR_ENGINEOPEN, + "Engine could not be opened") +ECODE(ERR_ENGINESTART, + "Engine could not be started") diff --git a/src/camera.cpp b/src/camera.cpp index 1477596..76e68a3 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -17,13 +17,13 @@ defaultBeginUpdateCB(Camera *cam) { engine->currentCamera = cam; Frame::syncDirty(); - engine->beginUpdate(cam); + engine->device.beginUpdate(cam); } void defaultEndUpdateCB(Camera *cam) { - engine->endUpdate(cam); + engine->device.endUpdate(cam); } static void @@ -315,7 +315,14 @@ Camera::destroy(void) void Camera::clear(RGBA *col, uint32 mode) { - engine->clearCamera(this, col, mode); + engine->device.clearCamera(this, col, mode); +} + +void +Camera::showRaster(void) +{ + // TODO: camera raster + engine->device.showRaster(nil); } void @@ -323,8 +330,8 @@ calczShiftScale(Camera *cam) { float32 n = cam->nearPlane; float32 f = cam->farPlane; - float32 N = engine->zNear; - float32 F = engine->zFar; + float32 N = engine->device.zNear; + float32 F = engine->device.zFar; // RW does this N += (F - N)/10000.0f; F -= (F - N)/10000.0f; diff --git a/src/clump.cpp b/src/clump.cpp index 2c33f79..17efa3d 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -523,7 +523,7 @@ Atomic::getPipeline(void) { return this->pipeline ? this->pipeline : - driver[platform]->defaultPipeline; + engine->driver[platform]->defaultPipeline; } void diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index 8e8e6ae..49d7b5e 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -15,9 +15,7 @@ namespace d3d { bool32 isP8supported = 1; -#ifdef RW_D3D9 -IDirect3DDevice9 *device = nil; -#else +#ifndef RW_D3D9 #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ ((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) | \ ((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 )) @@ -186,7 +184,7 @@ createIndexBuffer(uint32 length) { #ifdef RW_D3D9 IDirect3DIndexBuffer9 *ibuf; - device->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0); + d3ddevice->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0); return ibuf; #else return new uint8[length]; @@ -227,7 +225,7 @@ createVertexBuffer(uint32 length, uint32 fvf, int32 pool) { #ifdef RW_D3D9 IDirect3DVertexBuffer9 *vbuf; - device->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, fvf, (D3DPOOL)pool, &vbuf, 0); + d3ddevice->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, fvf, (D3DPOOL)pool, &vbuf, 0); return vbuf; #else (void)fvf; @@ -270,7 +268,7 @@ createTexture(int32 width, int32 height, int32 numlevels, uint32 format) { #ifdef RW_D3D9 IDirect3DTexture9 *tex; - device->CreateTexture(width, height, numlevels, 0, + d3ddevice->CreateTexture(width, height, numlevels, 0, (D3DFORMAT)format, D3DPOOL_MANAGED, &tex, nil); return tex; #else diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index cccf81f..454ff90 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -23,15 +23,15 @@ using namespace d3d; void* driverOpen(void *o, int32, int32) { - driver[PLATFORM_D3D8]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_D3D8]->defaultPipeline = makeDefaultPipeline(); - driver[PLATFORM_D3D8]->rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_D3D8]->rasterCreate = rasterCreate; - driver[PLATFORM_D3D8]->rasterLock = rasterLock; - driver[PLATFORM_D3D8]->rasterUnlock = rasterUnlock; - driver[PLATFORM_D3D8]->rasterNumLevels = rasterNumLevels; - driver[PLATFORM_D3D8]->rasterFromImage = rasterFromImage; - driver[PLATFORM_D3D8]->rasterToImage = rasterToImage; + engine->driver[PLATFORM_D3D8]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_D3D8]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_D3D8]->rasterLock = rasterLock; + engine->driver[PLATFORM_D3D8]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_D3D8]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_D3D8]->rasterFromImage = rasterFromImage; + engine->driver[PLATFORM_D3D8]->rasterToImage = rasterToImage; return o; } @@ -102,7 +102,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) Geometry *geometry = (Geometry*)object; uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); @@ -359,26 +359,26 @@ defaultInstanceCB(Geometry *geo, InstanceData *inst) uint8 *dst = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); instV3d(VERT_FLOAT3, dst, - &geo->morphTargets[0].vertices[3*inst->minVert], + &geo->morphTargets[0].vertices[inst->minVert], inst->numVertices, inst->stride); dst += 12; if(geo->flags & Geometry::NORMALS){ instV3d(VERT_FLOAT3, dst, - &geo->morphTargets[0].normals[3*inst->minVert], + &geo->morphTargets[0].normals[inst->minVert], inst->numVertices, inst->stride); dst += 12; } inst->vertexAlpha = 0; if(geo->flags & Geometry::PRELIT){ - inst->vertexAlpha = instColor(VERT_ARGB, dst, &geo->colors[4*inst->minVert], + inst->vertexAlpha = instColor(VERT_ARGB, dst, &geo->colors[inst->minVert], inst->numVertices, inst->stride); dst += 4; } for(int32 i = 0; i < geo->numTexCoordSets; i++){ - instTexCoords(VERT_FLOAT2, dst, &geo->texCoords[i][2*inst->minVert], + instTexCoords(VERT_FLOAT2, dst, &geo->texCoords[i][inst->minVert], inst->numVertices, inst->stride); dst += 8; } @@ -390,26 +390,26 @@ defaultUninstanceCB(Geometry *geo, InstanceData *inst) { uint8 *src = lockVertices(inst->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK); uninstV3d(VERT_FLOAT3, - &geo->morphTargets[0].vertices[3*inst->minVert], + &geo->morphTargets[0].vertices[inst->minVert], src, inst->numVertices, inst->stride); src += 12; if(geo->flags & Geometry::NORMALS){ uninstV3d(VERT_FLOAT3, - &geo->morphTargets[0].normals[3*inst->minVert], + &geo->morphTargets[0].normals[inst->minVert], src, inst->numVertices, inst->stride); src += 12; } inst->vertexAlpha = 0; if(geo->flags & Geometry::PRELIT){ - uninstColor(VERT_ARGB, &geo->colors[4*inst->minVert], src, + uninstColor(VERT_ARGB, &geo->colors[inst->minVert], src, inst->numVertices, inst->stride); src += 4; } for(int32 i = 0; i < geo->numTexCoordSets; i++){ - uninstTexCoords(VERT_FLOAT2, &geo->texCoords[i][2*inst->minVert], src, + uninstTexCoords(VERT_FLOAT2, &geo->texCoords[i][inst->minVert], src, inst->numVertices, inst->stride); src += 8; } @@ -481,7 +481,7 @@ readNativeTexture(Stream *stream) { uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/d3d/d3d8render.cpp b/src/d3d/d3d8render.cpp index 8330529..c5aed73 100644 --- a/src/d3d/d3d8render.cpp +++ b/src/d3d/d3d8render.cpp @@ -7,6 +7,7 @@ #include "../rwplg.h" #include "../rwpipeline.h" #include "../rwobjects.h" +#include "../rwengine.h" #include "rwd3d.h" #include "rwd3d8.h" @@ -23,28 +24,31 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) { RawMatrix world; + d3d::lightingCB(); + Geometry *geo = atomic->geometry; + d3d::setRenderState(D3DRS_LIGHTING, !!(geo->flags & rw::Geometry::LIGHT)); + Frame *f = atomic->getFrame(); convMatrix(&world, f->getLTM()); - device->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world); + d3ddevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world); InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ d3d::setTexture(0, inst->material->texture); d3d::setMaterial(inst->material); - d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40)); d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL); if(geo->flags & Geometry::PRELIT) d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1); - device->SetFVF(inst->vertexShader); - device->SetStreamSource(0, (IDirect3DVertexBuffer9*)inst->vertexBuffer, 0, inst->stride); - device->SetIndices((IDirect3DIndexBuffer9*)inst->indexBuffer); + d3ddevice->SetFVF(inst->vertexShader); + d3ddevice->SetStreamSource(0, (IDirect3DVertexBuffer9*)inst->vertexBuffer, 0, inst->stride); + d3ddevice->SetIndices((IDirect3DIndexBuffer9*)inst->indexBuffer); uint32 numPrim = inst->primType == D3DPT_TRIANGLESTRIP ? inst->numIndices-2 : inst->numIndices/3; d3d::flushCache(); - device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)inst->primType, inst->baseIndex, - 0, inst->numVertices, 0, numPrim); + d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)inst->primType, inst->baseIndex, + 0, inst->numVertices, 0, numPrim); inst++; } } diff --git a/src/d3d/d3d9.cpp b/src/d3d/d3d9.cpp index 8ce74ee..a772b0c 100644 --- a/src/d3d/d3d9.cpp +++ b/src/d3d/d3d9.cpp @@ -31,15 +31,15 @@ static VertexElement _d3ddec_end = {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0}; void* driverOpen(void *o, int32, int32) { - driver[PLATFORM_D3D9]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_D3D9]->defaultPipeline = makeDefaultPipeline(); - driver[PLATFORM_D3D9]->rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_D3D9]->rasterCreate = rasterCreate; - driver[PLATFORM_D3D9]->rasterLock = rasterLock; - driver[PLATFORM_D3D9]->rasterUnlock = rasterUnlock; - driver[PLATFORM_D3D9]->rasterNumLevels = rasterNumLevels; - driver[PLATFORM_D3D9]->rasterFromImage = rasterFromImage; - driver[PLATFORM_D3D9]->rasterToImage = rasterToImage; + engine->driver[PLATFORM_D3D9]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_D3D9]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_D3D9]->rasterLock = rasterLock; + engine->driver[PLATFORM_D3D9]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_D3D9]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_D3D9]->rasterFromImage = rasterFromImage; + engine->driver[PLATFORM_D3D9]->rasterToImage = rasterToImage; return o; } @@ -64,7 +64,7 @@ createVertexDeclaration(VertexElement *elements) { #ifdef RW_D3D9 IDirect3DVertexDeclaration9 *decl = 0; - device->CreateVertexDeclaration((D3DVERTEXELEMENT9*)elements, &decl); + d3ddevice->CreateVertexDeclaration((D3DVERTEXELEMENT9*)elements, &decl); return decl; #else int n = 0; @@ -122,7 +122,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) Geometry *geometry = (Geometry*)object; uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); @@ -592,7 +592,7 @@ readNativeTexture(Stream *stream) { uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/d3d/d3d9render.cpp b/src/d3d/d3d9render.cpp index 44672a5..96dc440 100644 --- a/src/d3d/d3d9render.cpp +++ b/src/d3d/d3d9render.cpp @@ -7,6 +7,7 @@ #include "../rwplg.h" #include "../rwpipeline.h" #include "../rwobjects.h" +#include "../rwengine.h" #include "rwd3d.h" #include "rwd3d9.h" @@ -23,29 +24,32 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) { RawMatrix world; + d3d::lightingCB(); + Geometry *geo = atomic->geometry; + d3d::setRenderState(D3DRS_LIGHTING, !!(geo->flags & rw::Geometry::LIGHT)); + Frame *f = atomic->getFrame(); convMatrix(&world, f->getLTM()); - device->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world); + d3ddevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world); - device->SetStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer, - 0, header->vertexStream[0].stride); - device->SetIndices((IDirect3DIndexBuffer9*)header->indexBuffer); - device->SetVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration); + d3ddevice->SetStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer, + 0, header->vertexStream[0].stride); + d3ddevice->SetIndices((IDirect3DIndexBuffer9*)header->indexBuffer); + d3ddevice->SetVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration); InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ d3d::setTexture(0, inst->material->texture); d3d::setMaterial(inst->material); - d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40)); d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL); if(geo->flags & Geometry::PRELIT) d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1); d3d::flushCache(); - device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex, - 0, inst->numVertices, - inst->startIndex, inst->numPrimitives); + d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex, + 0, inst->numVertices, + inst->startIndex, inst->numPrimitives); inst++; } } diff --git a/src/d3d/d3ddriver.cpp b/src/d3d/d3ddriver.cpp index 12cf481..d420914 100644 --- a/src/d3d/d3ddriver.cpp +++ b/src/d3d/d3ddriver.cpp @@ -5,16 +5,31 @@ #include "../rwbase.h" #include "../rwplg.h" +#include "../rwerror.h" #include "../rwpipeline.h" #include "../rwobjects.h" #include "../rwengine.h" #include "rwd3d.h" +#define PLUGIN_ID 0 + namespace rw { namespace d3d { #ifdef RW_D3D9 +// cached RW render states +static bool32 vertexAlpha; +static bool32 textureAlpha; +static uint32 srcblend, destblend; +static uint32 zwrite; +static uint32 ztest; +static uint32 fogenable; +static RGBA fogcolor; +static uint32 alphafunc; +static uint32 alpharef; + + #define MAXNUMSTATES D3DRS_BLENDOPALPHA #define MAXNUMSTAGES 8 #define MAXNUMTEXSTATES D3DTSS_CONSTANT @@ -41,10 +56,13 @@ static uint32 d3dTextureStageStates[MAXNUMSTATES][MAXNUMSTAGES]; static uint32 d3dSamplerStates[MAXNUMSAMPLERSTATES][MAXNUMSTAGES]; +// TODO: not only rasters, make a struct static Raster *d3dRaster[MAXNUMSTAGES]; static D3DMATERIAL9 d3dmaterial; +// D3D render state + void setRenderState(uint32 state, uint32 value) { @@ -81,7 +99,7 @@ flushCache(void) v = stateCache[s].value; stateCache[s].dirty = 0; if(d3dStates[s] != v){ - device->SetRenderState((D3DRENDERSTATETYPE)s, v); + d3ddevice->SetRenderState((D3DRENDERSTATETYPE)s, v); d3dStates[s] = v; } } @@ -92,7 +110,7 @@ flushCache(void) v = textureStageStateCache[t][s].value; textureStageStateCache[t][s].dirty = 0; if(d3dTextureStageStates[t][s] != v){ - device->SetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, v); + d3ddevice->SetTextureStageState(s, (D3DTEXTURESTAGESTATETYPE)t, v); d3dTextureStageStates[t][s] = v; } } @@ -103,22 +121,154 @@ void setSamplerState(uint32 stage, uint32 type, uint32 value) { if(d3dSamplerStates[type][stage] != value){ - device->SetSamplerState(stage, (D3DSAMPLERSTATETYPE)type, value); + d3ddevice->SetSamplerState(stage, (D3DSAMPLERSTATETYPE)type, value); d3dSamplerStates[type][stage] = value; } } +// RW render state + +static void +setVertexAlpha(bool32 enable) +{ + if(vertexAlpha != enable){ + if(!textureAlpha){ + setRenderState(D3DRS_ALPHABLENDENABLE, enable); + setRenderState(D3DRS_ALPHATESTENABLE, enable); + } + vertexAlpha = enable; + } +} + +static uint32 blendMap[] = { + D3DBLEND_ZERO, + D3DBLEND_ONE, + D3DBLEND_SRCCOLOR, + D3DBLEND_INVSRCCOLOR, + D3DBLEND_SRCALPHA, + D3DBLEND_INVSRCALPHA, + D3DBLEND_DESTALPHA, + D3DBLEND_INVDESTALPHA, + D3DBLEND_DESTCOLOR, + D3DBLEND_INVDESTCOLOR, + D3DBLEND_SRCALPHASAT +}; + +uint32 alphafuncMap[] = { + D3DCMP_ALWAYS, + D3DCMP_GREATEREQUAL, + D3DCMP_LESS +}; + +static void +setRwRenderState(int32 state, uint32 value) +{ + uint32 bval = value ? TRUE : FALSE; + switch(state){ + case VERTEXALPHA: + setVertexAlpha(bval); + break; + case SRCBLEND: + if(srcblend != value){ + srcblend = value; + setRenderState(D3DRS_SRCBLEND, blendMap[value]); + } + break; + case DESTBLEND: + if(destblend != value){ + destblend = value; + setRenderState(D3DRS_DESTBLEND, blendMap[value]); + } + break; + case ZTESTENABLE: + if(ztest != bval){ + ztest = bval; + setRenderState(D3DRS_ZENABLE, ztest); + } + break; + case ZWRITEENABLE: + if(zwrite != bval){ + zwrite = bval; + setRenderState(D3DRS_ZWRITEENABLE, zwrite); + } + break; + case FOGENABLE: + if(fogenable != bval){ + fogenable = bval; + setRenderState(D3DRS_FOGENABLE, fogenable); + }; + break; + case FOGCOLOR:{ + RGBA c = *(RGBA*)&value; + if(!equal(fogcolor, c)){ + fogcolor = c; + setRenderState(D3DRS_FOGCOLOR, D3DCOLOR_RGBA(c.red, c.green, c.blue, c.alpha)); + }} break; + case ALPHATESTFUNC: + if(alphafunc != value){ + alphafunc = value; + setRenderState(D3DRS_ALPHAFUNC, alphafuncMap[alphafunc]); + } + break; + case ALPHATESTREF: + if(alpharef != value){ + alpharef = value; + setRenderState(D3DRS_ALPHAREF, alpharef); + } + break; + } +} + +static uint32 +getRwRenderState(int32 state) +{ + switch(state){ + case VERTEXALPHA: + return vertexAlpha; + case SRCBLEND: + return srcblend; + case DESTBLEND: + return destblend; + case ZTESTENABLE: + return ztest; + case ZWRITEENABLE: + return zwrite; + case FOGENABLE: + return fogenable; + case FOGCOLOR: + return *(uint32*)&fogcolor; + case ALPHATESTFUNC: + return alphafunc; + case ALPHATESTREF: + return alpharef; + } + return 0; +} + void setRasterStage(uint32 stage, Raster *raster) { + bool32 alpha; D3dRaster *d3draster = nil; if(raster != d3dRaster[stage]){ d3dRaster[stage] = raster; if(raster){ d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); - device->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture); - }else - device->SetTexture(stage, nil); + d3ddevice->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture); + alpha = d3draster->hasAlpha; + }else{ + d3ddevice->SetTexture(stage, nil); + alpha = 0; + } + if(stage == 0){ + if(textureAlpha != alpha){ + textureAlpha = alpha; + if(!vertexAlpha){ + setRenderState(D3DRS_ALPHABLENDENABLE, alpha); + setRenderState(D3DRS_ALPHATESTENABLE, alpha); + } + } + } } } @@ -173,19 +323,19 @@ setMaterial(Material *mat) d3dmaterial.Ambient.g != mat9.Ambient.g || d3dmaterial.Ambient.b != mat9.Ambient.b || d3dmaterial.Ambient.a != mat9.Ambient.a){ - device->SetMaterial(&mat9); + d3ddevice->SetMaterial(&mat9); d3dmaterial = mat9; } } -void +static void beginUpdate(Camera *cam) { float view[16], proj[16]; // View Matrix Matrix inv; - Matrix::invertOrthonormal(&inv, cam->getFrame()->getLTM()); + Matrix::invert(&inv, cam->getFrame()->getLTM()); // Since we're looking into positive Z, // flip X to ge a left handed view space. view[0] = -inv.right.x; @@ -204,7 +354,7 @@ beginUpdate(Camera *cam) view[13] = inv.pos.y; view[14] = inv.pos.z; view[15] = 1.0f; - device->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view); + d3ddevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)view); // Projection Matrix float32 invwx = 1.0f/cam->viewWindow.x; @@ -237,15 +387,176 @@ beginUpdate(Camera *cam) proj[15] = 1.0f; } proj[14] = -cam->nearPlane*proj[10]; - device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj); + d3ddevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)proj); + + // TODO: figure out where this is really done + setRenderState(D3DRS_FOGSTART, *(uint32*)&cam->fogPlane); + setRenderState(D3DRS_FOGEND, *(uint32*)&cam->farPlane); + + // TODO: figure out when to call this + d3ddevice->BeginScene(); } -void -initializeRender(void) +static void +endUpdate(Camera *cam) { - engine->beginUpdate = beginUpdate; + // TODO: figure out when to call this + d3ddevice->EndScene(); } +static void +clearCamera(Camera *cam, RGBA *col, uint32 mode) +{ + int flags = 0; + if(mode & Camera::CLEARIMAGE) + mode |= D3DCLEAR_TARGET; + if(mode & Camera::CLEARZ) + mode |= D3DCLEAR_ZBUFFER; + D3DCOLOR c = D3DCOLOR_RGBA(col->red, col->green, col->blue, col->alpha); + d3ddevice->Clear(0, 0, mode, c, 1.0f, 0); +} + +static void +showRaster(Raster *raster) +{ + // TODO: do this properly! + d3ddevice->Present(nil, nil, 0, nil); +} + +// taken from Frank Luna's d3d9 book +static int +startD3D(EngineStartParams *params) +{ + HWND win = params->window; + bool windowed = true; + + HRESULT hr = 0; + IDirect3D9 *d3d9 = 0; + d3d9 = Direct3DCreate9(D3D_SDK_VERSION); + if(!d3d9){ + RWERROR((ERR_GENERAL, "Direct3DCreate9() failed")); + return 0; + } + + D3DCAPS9 caps; + d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); + int vp = 0; + if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) + vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; + else + vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; + + RECT rect; + GetClientRect(win, &rect); + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + + D3DPRESENT_PARAMETERS d3dpp; + d3dpp.BackBufferWidth = width; + d3dpp.BackBufferHeight = height; + d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; + d3dpp.BackBufferCount = 1; + d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; + d3dpp.MultiSampleQuality = 0; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.hDeviceWindow = win; + d3dpp.Windowed = windowed; + d3dpp.EnableAutoDepthStencil = true; + d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; + d3dpp.Flags = 0; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + + IDirect3DDevice9 *dev; + hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, win, + vp, &d3dpp, &dev); + if(FAILED(hr)){ + // try again using a 16-bit depth buffer + d3dpp.AutoDepthStencilFormat = D3DFMT_D16; + + hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + win, vp, &d3dpp, &dev); + + if(FAILED(hr)){ + RWERROR((ERR_GENERAL, "CreateDevice() failed")); + d3d9->Release(); + return 0; + } + } + d3d9->Release(); + d3d::d3ddevice = dev; + return 1; +} + +static int +stopD3D(void) +{ + d3d::d3ddevice->Release(); + d3d::d3ddevice = nil; + return 1; +} + +static int +initD3D(void) +{ + // TODO: do some real stuff here + + d3ddevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); + alphafunc = ALPHAGREATEREQUAL; + d3ddevice->SetRenderState(D3DRS_ALPHAREF, 10); + alpharef = 10; + + d3ddevice->SetRenderState(D3DRS_FOGENABLE, FALSE); + fogenable = 0; + d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR); + // TODO: more fog stuff + + d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + + d3ddevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + srcblend = BLENDSRCALPHA; + d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + destblend = BLENDINVSRCALPHA; + d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 0); + vertexAlpha = 0; + textureAlpha = 0; + + setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); +// setTextureStageState(0, D3DTSS_CONSTANT, 0xFFFFFFFF); +// setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); +// setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CONSTANT); +// setTextureStageState(0, D3DTSS_COLOROP, D3DTA_CONSTANT); + + return 1; +} + +static int +deviceSystem(DeviceReq req, void *arg0) +{ + switch(req){ + case DEVICESTART: + return startD3D((EngineStartParams*)arg0); + case DEVICEINIT: + return initD3D(); + case DEVICESTOP: + return stopD3D(); + } + return 1; +} + +Device renderdevice = { + 0.0f, 1.0f, + d3d::beginUpdate, + d3d::endUpdate, + d3d::clearCamera, + d3d::showRaster, + d3d::setRwRenderState, + d3d::getRwRenderState, + null::im2DRenderIndexedPrimitive, + d3d::deviceSystem, +}; + #endif } } diff --git a/src/d3d/d3drender.cpp b/src/d3d/d3drender.cpp new file mode 100644 index 0000000..828b4ce --- /dev/null +++ b/src/d3d/d3drender.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "rwd3d.h" + +namespace rw { +namespace d3d { + +#ifdef RW_D3D9 +IDirect3DDevice9 *d3ddevice = nil; + +#define MAX_LIGHTS 8 + +void +lightingCB(void) +{ + World *world; + RGBAf ambLight = { 0.0, 0.0, 0.0, 1.0 }; + RGBA amb; + D3DLIGHT9 light; + light.Type = D3DLIGHT_DIRECTIONAL; + //light.Diffuse = { 0.8f, 0.8f, 0.8f, 1.0f }; + light.Specular = { 0.0f, 0.0f, 0.0f, 0.0f }; + light.Ambient = { 0.0f, 0.0f, 0.0f, 0.0f }; + light.Position = { 0.0f, 0.0f, 0.0f }; + //light.Direction = { 0.0f, 0.0f, -1.0f }; + light.Range = 0.0f; + light.Falloff = 0.0f; + light.Attenuation0 = 0.0f; + light.Attenuation1 = 0.0f; + light.Attenuation2 = 0.0f; + light.Theta = 0.0f; + light.Phi = 0.0f; + int n = 0; + + world = (World*)engine->currentWorld; + // only unpositioned lights right now + FORLIST(lnk, world->directionalLights){ + Light *l = Light::fromWorld(lnk); + if(l->getType() == Light::DIRECTIONAL){ + if(n >= MAX_LIGHTS) + continue; + light.Diffuse = *(D3DCOLORVALUE*)&l->color; + light.Direction = *(D3DVECTOR*)&l->getFrame()->getLTM()->at; + d3ddevice->SetLight(n, &light); + d3ddevice->LightEnable(n, TRUE); + n++; + }else if(l->getType() == Light::AMBIENT){ + ambLight.red += l->color.red; + ambLight.green += l->color.green; + ambLight.blue += l->color.blue; + } + } + for(; n < MAX_LIGHTS; n++) + d3ddevice->LightEnable(n, FALSE); + convColor(&amb, &ambLight); + d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_RGBA(amb.red, amb.green, amb.blue, amb.alpha)); +} + +#endif + +} +} diff --git a/src/d3d/rwd3d.h b/src/d3d/rwd3d.h index bc0014b..836d8d3 100644 --- a/src/d3d/rwd3d.h +++ b/src/d3d/rwd3d.h @@ -4,14 +4,23 @@ #endif namespace rw { -namespace d3d { -void initializeRender(void); +#ifdef RW_D3D9 +struct EngineStartParams +{ + HWND window; +}; +#endif + +namespace d3d { extern bool32 isP8supported; #ifdef RW_D3D9 -extern IDirect3DDevice9 *device; +extern IDirect3DDevice9 *d3ddevice; +extern Device renderdevice; + +void lightingCB(void); #else enum { D3DLOCK_NOSYSLOCK = 0, // ignored diff --git a/src/d3d/xbox.cpp b/src/d3d/xbox.cpp index 406c40f..5adb2c9 100644 --- a/src/d3d/xbox.cpp +++ b/src/d3d/xbox.cpp @@ -21,13 +21,13 @@ namespace xbox { void* driverOpen(void *o, int32, int32) { - driver[PLATFORM_XBOX]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_XBOX]->defaultPipeline = makeDefaultPipeline(); - driver[PLATFORM_XBOX]->rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_XBOX]->rasterCreate = rasterCreate; - driver[PLATFORM_XBOX]->rasterLock = rasterLock; - driver[PLATFORM_XBOX]->rasterUnlock = rasterUnlock; - driver[PLATFORM_XBOX]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_XBOX]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_XBOX]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_XBOX]->rasterLock = rasterLock; + engine->driver[PLATFORM_XBOX]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_XBOX]->rasterNumLevels = rasterNumLevels; // TODO: from image return o; @@ -71,7 +71,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) uint32 vers; uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, &vers)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); @@ -622,7 +622,7 @@ readNativeTexture(Stream *stream) { uint32 vers, platform; if(!findChunk(stream, ID_STRUCT, nil, &vers)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/d3d/xboxplugins.cpp b/src/d3d/xboxplugins.cpp index 2561b8f..8dc6eca 100644 --- a/src/d3d/xboxplugins.cpp +++ b/src/d3d/xboxplugins.cpp @@ -35,7 +35,7 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset) Geometry *geometry = (Geometry*)object; uint32 vers, platform; if(!findChunk(stream, ID_STRUCT, nil, &vers)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/engine.cpp b/src/engine.cpp index 833277e..5b78309 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -3,6 +3,7 @@ #include #include "rwbase.h" +#include "rwerror.h" #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" @@ -15,22 +16,55 @@ #include "gl/rwgl3.h" #include "gl/rwwdgl.h" +#define PLUGIN_ID 0 + namespace rw { Engine *engine; -Driver *driver[NUM_PLATFORMS]; +PluginList Driver::s_plglist[NUM_PLATFORMS]; +Engine::State Engine::state = Dead; -void +// This function mainly registers engine plugins +// RW initializes memory related things here too and +// uses more plugins +// TODO: do this^ ? +bool32 Engine::init(void) { - engine = new Engine; - PluginList init = { sizeof(Driver), sizeof(Driver), nil, nil }; + if(engine || Engine::state != Dead){ + RWERROR((ERR_ENGINEINIT)); + return 0; + } + PluginList init = { sizeof(Driver), sizeof(Driver), nil, nil }; for(uint i = 0; i < NUM_PLATFORMS; i++) Driver::s_plglist[i] = init; - Frame::dirtyList.init(); + // Register plugins + // TODO: these are wrong + ps2::initializePlatform(); + xbox::initializePlatform(); + d3d8::initializePlatform(); + d3d9::initializePlatform(); + wdgl::initializePlatform(); + gl3::initializePlatform(); + Engine::state = Initialized; + return 1; +} + +// This is where RW allocates the engine and e.g. opens d3d +// TODO: this will take an argument with device specific data (HWND &c.) +bool32 +Engine::open(void) +{ + if(engine || Engine::state != Initialized){ + RWERROR((ERR_ENGINEOPEN)); + return 0; + } + + // Allocate engine + engine = (Engine*)malloc(sizeof(Engine)); engine->currentCamera = nil; engine->currentWorld = nil; engine->currentTexDictionary = nil; @@ -38,45 +72,66 @@ Engine::init(void) engine->loadTextures = 1; engine->makeDummies = 1; - engine->beginUpdate = null::beginUpdate; - engine->endUpdate = null::endUpdate; - engine->clearCamera = null::clearCamera; - engine->setRenderState = null::setRenderState; - engine->getRenderState = null::getRenderState; - engine->im2DRenderIndexedPrimitive = null::im2DRenderIndexedPrimitive; - engine->zNear = 0.0f; // random values - engine->zFar = 1.0f; + // Initialize device + // Device and possibly OS specific! +#ifdef RW_GL3 + engine->device = gl3::renderdevice; +#elif RW_D3D9 + engine->device = d3d::renderdevice; +#else + engine->device = null::renderdevice; +#endif - ps2::initializePlatform(); - xbox::initializePlatform(); - d3d8::initializePlatform(); - d3d9::initializePlatform(); - wdgl::initializePlatform(); - gl3::initializePlatform(); + // TODO: open device; create d3d object/get video mode + + // TODO: init driver functions + ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL); + for(uint i = 0; i < NUM_PLATFORMS; i++){ + rw::engine->driver[i] = (Driver*)malloc(Driver::s_plglist[i].size); + + engine->driver[i]->defaultPipeline = defpipe; + + engine->driver[i]->rasterCreate = null::rasterCreate; + engine->driver[i]->rasterLock = null::rasterLock; + engine->driver[i]->rasterUnlock = null::rasterUnlock; + engine->driver[i]->rasterNumLevels = null::rasterNumLevels; + engine->driver[i]->rasterFromImage = null::rasterFromImage; + engine->driver[i]->rasterToImage = null::rasterToImage; + } + + Engine::state = Opened; + return 1; } -PluginList Driver::s_plglist[NUM_PLATFORMS]; +// This is where RW creates the actual rendering device +// ans calls the engine plugin ctors +bool32 +Engine::start(EngineStartParams *p) +{ + if(engine == nil || Engine::state != Opened){ + RWERROR((ERR_ENGINESTART)); + return 0; + } + + // Start device + engine->device.system(DEVICESTART, (void*)p); + engine->device.system(DEVICEINIT, nil); + + // TODO: construct engine plugins + Frame::dirtyList.init(); + for(uint i = 0; i < NUM_PLATFORMS; i++) + Driver::s_plglist[i].construct(rw::engine->driver[i]); + + // TODO: finalize device start + + Engine::state = Started; + return 1; +} void -Driver::open(void) +Engine::stop(void) { - ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL); - - for(uint i = 0; i < NUM_PLATFORMS; i++){ - rw::driver[i] = (Driver*)malloc(s_plglist[i].size); - - driver[i]->defaultPipeline = defpipe; - - driver[i]->rasterCreate = null::rasterCreate; - driver[i]->rasterLock = null::rasterLock; - driver[i]->rasterUnlock = null::rasterUnlock; - driver[i]->rasterNumLevels = null::rasterNumLevels; - driver[i]->rasterFromImage = null::rasterFromImage; - driver[i]->rasterToImage = null::rasterToImage; - - - s_plglist[i].construct(rw::driver[i]); - } + engine->device.system(DEVICESTOP, nil); } namespace null { @@ -84,6 +139,7 @@ namespace null { void beginUpdate(Camera*) { } void endUpdate(Camera*) { } void clearCamera(Camera*,RGBA*,uint32) { } +void showRaster(Raster*) { } void setRenderState(int32, uint32) { } uint32 getRenderState(int32) { return 0; } @@ -129,5 +185,23 @@ rasterToImage(Raster*) return nil; } +int +devicesystem(DeviceReq req, void *arg0) +{ + return 1; +} + +Device renderdevice = { + 0.0f, 1.0f, + null::beginUpdate, + null::endUpdate, + null::clearCamera, + null::showRaster, + null::setRenderState, + null::getRenderState, + null::im2DRenderIndexedPrimitive, + null::devicesystem +}; + } } diff --git a/src/geoplg.cpp b/src/geoplg.cpp index 36a164b..821735f 100644 --- a/src/geoplg.cpp +++ b/src/geoplg.cpp @@ -8,6 +8,7 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwengine.h" #include "rwanim.h" #include "rwplugins.h" #include "ps2/rwps2.h" diff --git a/src/gl/gl3.cpp b/src/gl/gl3.cpp index eaf7b5d..d4d8f1f 100644 --- a/src/gl/gl3.cpp +++ b/src/gl/gl3.cpp @@ -26,14 +26,14 @@ void* driverOpen(void *o, int32, int32) { #ifdef RW_OPENGL - driver[PLATFORM_GL3]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_GL3]->defaultPipeline = makeDefaultPipeline(); #endif - driver[PLATFORM_GL3]->rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_GL3]->rasterCreate = rasterCreate; - driver[PLATFORM_GL3]->rasterLock = rasterLock; - driver[PLATFORM_GL3]->rasterUnlock = rasterUnlock; - driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels; - driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage; + engine->driver[PLATFORM_GL3]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_GL3]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_GL3]->rasterLock = rasterLock; + engine->driver[PLATFORM_GL3]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_GL3]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_GL3]->rasterFromImage = rasterFromImage; return o; } diff --git a/src/gl/gl3driver.cpp b/src/gl/gl3driver.cpp index d3695db..4060eee 100644 --- a/src/gl/gl3driver.cpp +++ b/src/gl/gl3driver.cpp @@ -10,10 +10,13 @@ #include "../rwengine.h" #ifdef RW_OPENGL #include +#include #include "rwgl3.h" #include "rwgl3shader.h" #include "rwgl3impl.h" +#define PLUGIN_ID 0 + namespace rw { namespace gl3 { @@ -77,7 +80,9 @@ static uint32 srcblend, destblend; static uint32 zwrite; static uint32 ztest; -uint32 blendMap[] = { +static int32 activeTexture; + +static uint32 blendMap[] = { GL_ZERO, GL_ONE, GL_SRC_COLOR, @@ -91,18 +96,26 @@ uint32 blendMap[] = { GL_SRC_ALPHA_SATURATE, }; -void +static void +setVertexAlpha(bool32 enable) +{ + if(vertexAlpha != enable){ + vertexAlpha = enable; + if(!textureAlpha){ + if(enable) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + } + } +} + +static void setRenderState(int32 state, uint32 value) { switch(state){ case VERTEXALPHA: - if(vertexAlpha != value){ - vertexAlpha = value; - if(vertexAlpha) - glEnable(GL_BLEND); - else if(!textureAlpha) - glDisable(GL_BLEND); - } + setVertexAlpha(value); break; case SRCBLEND: if(srcblend != value){ @@ -158,7 +171,7 @@ setRenderState(int32 state, uint32 value) } } -uint32 +static uint32 getRenderState(int32 state) { RGBA rgba; @@ -182,15 +195,15 @@ getRenderState(int32 state) case ALPHATESTFUNC: return uniformState.alphaFunc; case ALPHATESTREF: - return uniformState.alphaRef*255.0f; + return (uint32)(uniformState.alphaRef*255.0f); } return 0; } -void +static void resetRenderState(void) { - uniformState.alphaFunc = ALPHAGREATERTHAN; + uniformState.alphaFunc = ALPHAGREATEREQUAL; uniformState.alphaRef = 10.0f/255.0f; uniformState.fogEnable = 0; uniformState.fogStart = 0.0f; @@ -254,7 +267,7 @@ setLight(int32 n, Light *light) l->direction = m->at; } // light has position - l->w = light->getType() >= Light::POINT ? 1.0f : 0.0; + l->w = light->getType() >= Light::POINT ? 1.0f : 0.0f; l->color = light->color; l->radius = light->radius; l->minusCosAngle = light->minusCosAngle; @@ -275,11 +288,20 @@ setViewMatrix(float32 *mat) sceneDirty = 1; } +static void +setActiveTexture(int32 n) +{ + if(activeTexture != n){ + activeTexture = n; + glActiveTexture(n); + } +} + void setTexture(int32 n, Texture *tex) { bool32 alpha; - glActiveTexture(GL_TEXTURE0+n); + setActiveTexture(GL_TEXTURE0+n); if(tex == nil || tex->raster->platform != PLATFORM_GL3 || tex->raster->width == 0){ glBindTexture(GL_TEXTURE_2D, whitetex); @@ -291,12 +313,16 @@ setTexture(int32 n, Texture *tex) alpha = natras->hasAlpha; } - if(textureAlpha != alpha){ - textureAlpha = alpha; - if(textureAlpha) - glEnable(GL_BLEND); - else if(!vertexAlpha) - glDisable(GL_BLEND); + if(n == 0){ + if(alpha != textureAlpha){ + textureAlpha = alpha; + if(!vertexAlpha){ + if(alpha) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + } + } } } @@ -323,7 +349,7 @@ flushCache(void) } } -void +static void clearCamera(Camera *cam, RGBA *col, uint32 mode) { RGBAf colf; @@ -339,7 +365,16 @@ clearCamera(Camera *cam, RGBA *col, uint32 mode) glClear(mask); } -void +static GLFWwindow *glfwwindow; + +static void +showRaster(Raster *raster) +{ + // TODO: do this properly! + glfwSwapBuffers(glfwwindow); +} + +static void beginUpdate(Camera *cam) { float view[16], proj[16]; @@ -410,17 +445,62 @@ beginUpdate(Camera *cam) } } -void -initializeRender(void) +static int +startGLFW(EngineStartParams *startparams) { - engine->beginUpdate = beginUpdate; - engine->clearCamera = clearCamera; - engine->setRenderState = setRenderState; - engine->getRenderState = getRenderState; - engine->im2DRenderIndexedPrimitive = im2DRenderIndexedPrimitive; - engine->zNear = -1.0f; - engine->zFar = 1.0f; + GLenum status; + GLFWwindow *win; + /* Init GLFW */ + if(!glfwInit()){ + RWERROR((ERR_GENERAL, "glfwInit() failed")); + return 0; + } + glfwWindowHint(GLFW_SAMPLES, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + win = glfwCreateWindow(startparams->width, startparams->height, startparams->windowtitle, 0, 0); + if(win == nil){ + RWERROR((ERR_GENERAL, "glfwCreateWindow() failed")); + glfwTerminate(); + return 0; + } + glfwMakeContextCurrent(win); + + /* Init GLEW */ + glewExperimental = GL_TRUE; + status = glewInit(); + if(status != GLEW_OK){ + RWERROR((ERR_GENERAL, glewGetErrorString(status))); + glfwDestroyWindow(win); + glfwTerminate(); + return 0; + } + if(!GLEW_VERSION_3_3){ + RWERROR((ERR_GENERAL, "OpenGL 3.3 needed")); + glfwDestroyWindow(win); + glfwTerminate(); + return 0; + } + glfwwindow = win; + *startparams->window = win; + return 1; +} + +static int +stopGLFW(void) +{ + glfwDestroyWindow(glfwwindow); + glfwTerminate(); + return 1; +} + +static int +initOpenGL(void) +{ #include "shaders/simple_gl3.inc" simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src); @@ -438,7 +518,6 @@ initializeRender(void) GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - glGenBuffers(1, &ubo_scene); glBindBuffer(GL_UNIFORM_BUFFER, ubo_scene); glBindBufferBase(GL_UNIFORM_BUFFER, gl3::findBlock("Scene"), ubo_scene); @@ -446,7 +525,6 @@ initializeRender(void) GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - glGenBuffers(1, &ubo_object); glBindBuffer(GL_UNIFORM_BUFFER, ubo_object); glBindBufferBase(GL_UNIFORM_BUFFER, gl3::findBlock("Object"), ubo_object); @@ -454,7 +532,6 @@ initializeRender(void) GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - byte whitepixel[4] = {0xFF, 0xFF, 0xFF, 0xFF}; glGenTextures(1, &whitetex); glBindTexture(GL_TEXTURE_2D, whitetex); @@ -464,7 +541,35 @@ initializeRender(void) 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitepixel); im2DInit(); + return 1; } + +static int +deviceSystem(DeviceReq req, void *arg0) +{ + switch(req){ + case DEVICESTART: + return startGLFW((EngineStartParams*)arg0); + case DEVICEINIT: + return initOpenGL(); + case DEVICESTOP: + return stopGLFW(); + } + return 1; +} + +Device renderdevice = { + -1.0f, 1.0f, + gl3::beginUpdate, + null::endUpdate, + gl3::clearCamera, + gl3::showRaster, + gl3::setRenderState, + gl3::getRenderState, + gl3::im2DRenderIndexedPrimitive, + gl3::deviceSystem +}; + } } diff --git a/src/gl/gl3render.cpp b/src/gl/gl3render.cpp index 90783b7..fd345a7 100644 --- a/src/gl/gl3render.cpp +++ b/src/gl/gl3render.cpp @@ -43,7 +43,7 @@ void lightingCB(void) { World *world; - RGBAf ambLight = (RGBAf){0.0, 0.0, 0.0, 1.0}; + RGBAf ambLight = { 0.0, 0.0, 0.0, 1.0 }; int n = 0; world = (World*)engine->currentWorld; @@ -84,9 +84,6 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) InstanceData *inst = header->inst; int32 n = header->numMeshes; -// rw::setRenderState(ALPHATESTFUNC, 1); -// rw::setRenderState(ALPHATESTREF, 50); - simpleShader->use(); while(n--){ diff --git a/src/gl/gl3shader.cpp b/src/gl/gl3shader.cpp index be879a0..fa16bb8 100644 --- a/src/gl/gl3shader.cpp +++ b/src/gl/gl3shader.cpp @@ -189,8 +189,10 @@ Shader::fromFiles(const char *vspath, const char *fspath) void Shader::use(void) { - glUseProgram(this->program); - currentShader = this; + if(currentShader != this){ + glUseProgram(this->program); + currentShader = this; + } } } diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 0a51e9a..313ea6d 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -1,8 +1,24 @@ +#ifdef RW_GL3 +#include +#include +#endif + namespace rw { + +#ifdef RW_GL3 +struct EngineStartParams +{ + GLFWwindow **window; + int width, height; + const char *windowtitle; +}; +#endif + namespace gl3 { void initializePlatform(void); -void initializeRender(void); + +extern Device renderdevice; // arguments to glVertexAttribPointer basically struct AttribDesc diff --git a/src/gl/shaders/im2d.frag b/src/gl/shaders/im2d.frag index b40c2f9..91bfc3e 100644 --- a/src/gl/shaders/im2d.frag +++ b/src/gl/shaders/im2d.frag @@ -10,6 +10,6 @@ out vec4 color; void main(void) { - color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y)); + color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y)); } diff --git a/src/gl/shaders/im2d_gl3.inc b/src/gl/shaders/im2d_gl3.inc index 23af07c..6230350 100644 --- a/src/gl/shaders/im2d_gl3.inc +++ b/src/gl/shaders/im2d_gl3.inc @@ -36,7 +36,7 @@ const char *im2d_frag_src = "void\n" "main(void)\n" "{\n" -" color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y));\n" +" color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y));\n" "}\n" ; diff --git a/src/gl/shaders/matfx_env.frag b/src/gl/shaders/matfx_env.frag index 5c9522d..ed90362 100644 --- a/src/gl/shaders/matfx_env.frag +++ b/src/gl/shaders/matfx_env.frag @@ -17,7 +17,7 @@ out vec4 color; void main(void) { - color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y)); + color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y)); switch(u_alphaTest){ default: case 0: break; diff --git a/src/gl/shaders/matfx_gl3.inc b/src/gl/shaders/matfx_gl3.inc index 3a8f5f5..8b65b64 100644 --- a/src/gl/shaders/matfx_gl3.inc +++ b/src/gl/shaders/matfx_gl3.inc @@ -78,7 +78,7 @@ const char *matfx_env_frag_src = "void\n" "main(void)\n" "{\n" -" color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y));\n" +" color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y));\n" " switch(u_alphaTest){\n" " default:\n" " case 0: break;\n" diff --git a/src/gl/shaders/simple.frag b/src/gl/shaders/simple.frag index 11b2939..770d62b 100644 --- a/src/gl/shaders/simple.frag +++ b/src/gl/shaders/simple.frag @@ -22,7 +22,7 @@ out vec4 color; void main(void) { - color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y)); + color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y)); if(u_fogEnable != 0) color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog); switch(u_alphaTest){ diff --git a/src/gl/shaders/simple_gl3.inc b/src/gl/shaders/simple_gl3.inc index 6d0e614..76a21f8 100644 --- a/src/gl/shaders/simple_gl3.inc +++ b/src/gl/shaders/simple_gl3.inc @@ -95,7 +95,7 @@ const char *simple_frag_src = "void\n" "main(void)\n" "{\n" -" color = v_color*texture2D(tex, vec2(v_tex0.x, v_tex0.y));\n" +" color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y));\n" " if(u_fogEnable != 0)\n" " color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" " switch(u_alphaTest){\n" diff --git a/src/gl/wdgl.cpp b/src/gl/wdgl.cpp index 60029ef..123c7d5 100644 --- a/src/gl/wdgl.cpp +++ b/src/gl/wdgl.cpp @@ -25,7 +25,7 @@ namespace wdgl { void* driverOpen(void *o, int32, int32) { - driver[PLATFORM_WDGL]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_WDGL]->defaultPipeline = makeDefaultPipeline(); return o; } diff --git a/src/hanim.cpp b/src/hanim.cpp index 32b824c..d2daf6e 100644 --- a/src/hanim.cpp +++ b/src/hanim.cpp @@ -8,6 +8,7 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwengine.h" #include "rwanim.h" #include "rwplugins.h" #include "ps2/rwps2.h" diff --git a/src/image.cpp b/src/image.cpp index fd97f49..06a7ef3 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -917,7 +917,7 @@ Raster::create(int32 width, int32 height, int32 depth, int32 format, int32 platf s_plglist.construct(raster); // printf("%d %d %d %d\n", raster->type, raster->width, raster->height, raster->depth); - driver[raster->platform]->rasterCreate(raster); + engine->driver[raster->platform]->rasterCreate(raster); return raster; } @@ -933,19 +933,19 @@ Raster::destroy(void) uint8* Raster::lock(int32 level) { - return driver[this->platform]->rasterLock(this, level); + return engine->driver[this->platform]->rasterLock(this, level); } void Raster::unlock(int32 level) { - driver[this->platform]->rasterUnlock(this, level); + engine->driver[this->platform]->rasterUnlock(this, level); } int32 Raster::getNumLevels(void) { - return driver[this->platform]->rasterNumLevels(this); + return engine->driver[this->platform]->rasterNumLevels(this); } int32 @@ -964,14 +964,14 @@ Raster::createFromImage(Image *image, int32 platform) Raster *raster = Raster::create(image->width, image->height, image->depth, TEXTURE | DONTALLOCATE, platform); - driver[raster->platform]->rasterFromImage(raster, image); + engine->driver[raster->platform]->rasterFromImage(raster, image); return raster; } Image* Raster::toImage(void) { - return driver[this->platform]->rasterToImage(this); + return engine->driver[this->platform]->rasterToImage(this); } } diff --git a/src/ps2/ps2.cpp b/src/ps2/ps2.cpp index ec29a1c..b4a22f6 100644 --- a/src/ps2/ps2.cpp +++ b/src/ps2/ps2.cpp @@ -24,13 +24,13 @@ namespace ps2 { void* driverOpen(void *o, int32, int32) { - driver[PLATFORM_PS2]->defaultPipeline = makeDefaultPipeline(); + engine->driver[PLATFORM_PS2]->defaultPipeline = makeDefaultPipeline(); - driver[PLATFORM_PS2]->rasterNativeOffset = nativeRasterOffset; - driver[PLATFORM_PS2]->rasterCreate = rasterCreate; - driver[PLATFORM_PS2]->rasterLock = rasterLock; - driver[PLATFORM_PS2]->rasterUnlock = rasterUnlock; - driver[PLATFORM_PS2]->rasterNumLevels = rasterNumLevels; + engine->driver[PLATFORM_PS2]->rasterNativeOffset = nativeRasterOffset; + engine->driver[PLATFORM_PS2]->rasterCreate = rasterCreate; + engine->driver[PLATFORM_PS2]->rasterLock = rasterLock; + engine->driver[PLATFORM_PS2]->rasterUnlock = rasterUnlock; + engine->driver[PLATFORM_PS2]->rasterNumLevels = rasterNumLevels; return o; } @@ -73,7 +73,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) Geometry *geometry = (Geometry*)object; uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/ps2/ps2raster.cpp b/src/ps2/ps2raster.cpp index 363e45b..e69c057 100644 --- a/src/ps2/ps2raster.cpp +++ b/src/ps2/ps2raster.cpp @@ -559,7 +559,7 @@ registerNativeRaster(void) void printTEX0(uint64 tex0) { - printf("%016lX ", tex0); + printf("%016llX ", tex0); uint32 tbp0 = tex0 & 0x3FFF; tex0 >>= 14; uint32 tbw = tex0 & 0x3F; tex0 >>= 6; uint32 psm = tex0 & 0x3F; tex0 >>= 6; @@ -579,7 +579,7 @@ printTEX0(uint64 tex0) void printTEX1(uint64 tex1) { - printf("%016lX ", tex1); + printf("%016llX ", tex1); uint32 lcm = tex1 & 0x1; tex1 >>= 2; uint32 mxl = tex1 & 0x7; tex1 >>= 3; uint32 mmag = tex1 & 0x1; tex1 >>= 1; diff --git a/src/ps2/ps2skin.cpp b/src/ps2/ps2skin.cpp index f605fa3..36609b4 100644 --- a/src/ps2/ps2skin.cpp +++ b/src/ps2/ps2skin.cpp @@ -74,7 +74,7 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset) Geometry *geometry = (Geometry*)object; uint32 platform; if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")) + RWERROR((ERR_CHUNK, "STRUCT")); return nil; } platform = stream->readU32(); diff --git a/src/rwengine.h b/src/rwengine.h index aa88f9a..1428c1e 100644 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -22,9 +22,9 @@ enum RenderState enum AlphaTestFunc { - ALPHANEVER = 0, - ALPHALESS, - ALPHAGREATERTHAN + ALPHAALWAYS = 0, + ALPHAGREATEREQUAL, + ALPHALESS }; enum BlendFunction @@ -43,37 +43,35 @@ enum BlendFunction // TODO: add more perhaps }; -// This is for platform independent things and the render device (of which -// there can only ever be one). -// TODO: move more stuff into this -struct Engine +enum DeviceReq { - void *currentCamera; - void *currentWorld; - Texture *imtexture; + // Device/Context creation + DEVICESTART, + // Device initialization before Engine/Driver plugins are opened + DEVICEINIT, + // Device/Context shutdown + DEVICESTOP, +}; - TexDictionary *currentTexDictionary; - bool32 loadTextures; // load textures from files - bool32 makeDummies; // create dummy textures to store just names +typedef int DeviceSystem(DeviceReq req, void *arg0); - - // Device +// This is for the render device, we only have one +struct Device +{ float32 zNear, zFar; void (*beginUpdate)(Camera*); void (*endUpdate)(Camera*); void (*clearCamera)(Camera*, RGBA *col, uint32 mode); + void (*showRaster)(Raster *raster); void (*setRenderState)(int32 state, uint32 value); uint32 (*getRenderState)(int32 state); void (*im2DRenderIndexedPrimitive)(PrimitiveType, void*, int32, void*, int32); - - static void init(void); + DeviceSystem *system; }; -extern Engine *engine; - -// This is for platform driver implementations which have to be available -// regardless of the render device. +// This is for platform-dependent but portable things +// so the engine has one for every platform struct Driver { ObjPipeline *defaultPipeline; @@ -87,7 +85,6 @@ struct Driver Image *(*rasterToImage)(Raster*); static PluginList s_plglist[NUM_PLATFORMS]; - static void open(void); static int32 registerPlugin(int32 platform, int32 size, uint32 id, Constructor ctor, Destructor dtor){ return s_plglist[platform].registerPlugin(size, id, @@ -95,14 +92,47 @@ struct Driver } }; -extern Driver *driver[NUM_PLATFORMS]; -#define DRIVER driver[rw::platform] +struct EngineStartParams; + +// This is for platform independent things +// TODO: move more stuff into this +// TODO: make this have plugins and allocate in Engine::open +struct Engine +{ + enum State { + Dead = 0, + Initialized, + Opened, + Started + }; + void *currentCamera; + void *currentWorld; + Texture *imtexture; + + TexDictionary *currentTexDictionary; + // load textures from files + bool32 loadTextures; + // create dummy textures to store just names + bool32 makeDummies; + // Dynamically allocated because of plugins + Driver *driver[NUM_PLATFORMS]; + Device device; + + static State state; + + static bool32 init(void); + static bool32 open(void); + static bool32 start(EngineStartParams*); + static void stop(void); +}; + +extern Engine *engine; inline void SetRenderState(int32 state, uint32 value){ - engine->setRenderState(state, value); } + engine->device.setRenderState(state, value); } inline uint32 GetRenderState(int32 state){ - return engine->getRenderState(state); } + return engine->device.getRenderState(state); } namespace null { void beginUpdate(Camera*); @@ -121,6 +151,10 @@ namespace null { void im2DRenderIndexedPrimitive(PrimitiveType, void*, int32, void*, int32); + + int deviceSystem(DeviceReq req); + + extern Device renderdevice; } } diff --git a/src/rwerror.h b/src/rwerror.h index e382e89..937cc0e 100644 --- a/src/rwerror.h +++ b/src/rwerror.h @@ -20,6 +20,6 @@ char *dbgsprint(int32 code, ...); fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \ fprintf(stderr, "%s\n", rw::dbgsprint ecode); \ rw::setError(&_e); \ -}while(0); +}while(0) } diff --git a/src/rwobjects.h b/src/rwobjects.h index 19f2dd1..5bbf75b 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -612,6 +612,7 @@ struct Camera : PluginBase void beginUpdate(void) { this->beginUpdateCB(this); } void endUpdate(void) { this->endUpdateCB(this); } void clear(RGBA *col, uint32 mode); + void showRaster(void); void setNearPlane(float32); void setFarPlane(float32); int32 frustumTestSphere(Sphere *s); From 497796e55042df945585e1392e63efea678983ee Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 10 Aug 2017 00:42:33 +0200 Subject: [PATCH 2/8] wrote basic skeleton; clumpview --- premake5.lua | 45 ++++++++ rw.h | 3 - skeleton/glfw.cpp | 184 +++++++++++++++++++++++++++++++ skeleton/skeleton.cpp | 57 ++++++++++ skeleton/skeleton.h | 91 ++++++++++++++++ skeleton/win.cpp | 217 +++++++++++++++++++++++++++++++++++++ src/base.cpp | 20 ++++ src/engine.cpp | 10 ++ src/frame.cpp | 7 ++ src/rwbase.h | 1 + src/rwengine.h | 2 + src/rwobjects.h | 3 +- tools/clumpview/camera.cpp | 134 +++++++++++++++++++++++ tools/clumpview/camera.h | 26 +++++ tools/clumpview/main.cpp | 181 +++++++++++++++++++++++++++++++ tools/clumpview/teapot.dff | Bin 0 -> 42796 bytes 16 files changed, 977 insertions(+), 4 deletions(-) create mode 100644 skeleton/glfw.cpp create mode 100644 skeleton/skeleton.cpp create mode 100644 skeleton/skeleton.h create mode 100644 skeleton/win.cpp create mode 100644 tools/clumpview/camera.cpp create mode 100644 tools/clumpview/camera.h create mode 100644 tools/clumpview/main.cpp create mode 100644 tools/clumpview/teapot.dff diff --git a/premake5.lua b/premake5.lua index b1934e6..984fcab 100755 --- a/premake5.lua +++ b/premake5.lua @@ -71,3 +71,48 @@ project "dumprwtree" includedirs { "." } libdirs { Libdir } links { "librw" } + +function findlibs() + filter { "platforms:linux*gl3" } + links { "GL", "GLEW", "glfw" } + filter { "platforms:win*gl3" } + defines { "GLEW_STATIC" } + filter { "platforms:win-amd64-gl3" } + libdirs { path.join(GLEWdir, "lib/Release/x64") } + libdirs { path.join(GLFW64dir, "lib-vc2015") } + filter { "platforms:win-x86-gl3" } + libdirs { path.join(GLEWdir, "lib/Release/Win32") } + filter { "platforms:win*gl3" } + links { "glew32s", "glfw3", "opengl32" } + filter { "platforms:*d3d9" } + links { "d3d9", "Xinput9_1_0" } + filter {} +end + +function skeleton() + files { "skeleton/*.cpp", "skeleton/*.h" } + includedirs { "skeleton" } +end + +function skeltool(dir) + targetdir (Bindir) + files { path.join("tools", dir, "*.cpp"), + path.join("tools", dir, "*.h") } + vpaths { + {["src"] = { path.join("tools", dir, "*") }}, + {["skeleton"] = { "skeleton/*" }}, + } + skeleton() + debugdir ( path.join("tools", dir) ) + includedirs { "." } + libdirs { Libdir } + links { "librw" } + findlibs() +end + +project "clumpview" + kind "WindowedApp" + characterset ("MBCS") + skeltool("clumpview") + flags { "WinMain" } + removeplatforms { "*null" } diff --git a/rw.h b/rw.h index 8638793..af7d6eb 100644 --- a/rw.h +++ b/rw.h @@ -15,9 +15,6 @@ #include "src/d3d/rwd3d.h" #include "src/d3d/rwd3d8.h" #include "src/d3d/rwd3d9.h" -#ifdef RW_OPENGL -#include -#endif #include "src/gl/rwwdgl.h" #include "src/gl/rwgl3.h" #include "src/gl/rwgl3shader.h" diff --git a/skeleton/glfw.cpp b/skeleton/glfw.cpp new file mode 100644 index 0000000..5690a04 --- /dev/null +++ b/skeleton/glfw.cpp @@ -0,0 +1,184 @@ +#include +#include +#include "skeleton.h" + +using namespace sk; +using namespace rw; + +#ifdef RW_OPENGL + +GLFWwindow *window; +int keymap[GLFW_KEY_LAST+1]; + +static void +initkeymap(void) +{ + int i; + for(i = 0; i < GLFW_KEY_LAST+1; i++) + keymap[i] = KEY_NULL; + keymap[GLFW_KEY_SPACE] = ' '; + keymap[GLFW_KEY_APOSTROPHE] = '\''; + keymap[GLFW_KEY_COMMA] = ','; + keymap[GLFW_KEY_MINUS] = '-'; + keymap[GLFW_KEY_PERIOD] = '.'; + keymap[GLFW_KEY_SLASH] = '/'; + keymap[GLFW_KEY_0] = '0'; + keymap[GLFW_KEY_1] = '1'; + keymap[GLFW_KEY_2] = '2'; + keymap[GLFW_KEY_3] = '3'; + keymap[GLFW_KEY_4] = '4'; + keymap[GLFW_KEY_5] = '5'; + keymap[GLFW_KEY_6] = '6'; + keymap[GLFW_KEY_7] = '7'; + keymap[GLFW_KEY_8] = '8'; + keymap[GLFW_KEY_9] = '9'; + keymap[GLFW_KEY_SEMICOLON] = ';'; + keymap[GLFW_KEY_EQUAL] = '='; + keymap[GLFW_KEY_A] = 'A'; + keymap[GLFW_KEY_B] = 'B'; + keymap[GLFW_KEY_C] = 'C'; + keymap[GLFW_KEY_D] = 'D'; + keymap[GLFW_KEY_E] = 'E'; + keymap[GLFW_KEY_F] = 'F'; + keymap[GLFW_KEY_G] = 'G'; + keymap[GLFW_KEY_H] = 'H'; + keymap[GLFW_KEY_I] = 'I'; + keymap[GLFW_KEY_J] = 'J'; + keymap[GLFW_KEY_K] = 'K'; + keymap[GLFW_KEY_L] = 'L'; + keymap[GLFW_KEY_M] = 'M'; + keymap[GLFW_KEY_N] = 'N'; + keymap[GLFW_KEY_O] = 'O'; + keymap[GLFW_KEY_P] = 'P'; + keymap[GLFW_KEY_Q] = 'Q'; + keymap[GLFW_KEY_R] = 'R'; + keymap[GLFW_KEY_S] = 'S'; + keymap[GLFW_KEY_T] = 'T'; + keymap[GLFW_KEY_U] = 'U'; + keymap[GLFW_KEY_V] = 'V'; + keymap[GLFW_KEY_W] = 'W'; + keymap[GLFW_KEY_X] = 'X'; + keymap[GLFW_KEY_Y] = 'Y'; + keymap[GLFW_KEY_Z] = 'Z'; + keymap[GLFW_KEY_LEFT_BRACKET] = '['; + keymap[GLFW_KEY_BACKSLASH] = '\\'; + keymap[GLFW_KEY_RIGHT_BRACKET] = ']'; + keymap[GLFW_KEY_GRAVE_ACCENT] = '`'; + keymap[GLFW_KEY_ESCAPE] = KEY_ESC; + keymap[GLFW_KEY_ENTER] = KEY_ENTER; + keymap[GLFW_KEY_TAB] = KEY_TAB; + keymap[GLFW_KEY_BACKSPACE] = KEY_BACKSP; + keymap[GLFW_KEY_INSERT] = KEY_INS; + keymap[GLFW_KEY_DELETE] = KEY_DEL; + keymap[GLFW_KEY_RIGHT] = KEY_RIGHT; + keymap[GLFW_KEY_LEFT] = KEY_LEFT; + keymap[GLFW_KEY_DOWN] = KEY_DOWN; + keymap[GLFW_KEY_UP] = KEY_UP; + keymap[GLFW_KEY_PAGE_UP] = KEY_PGUP; + keymap[GLFW_KEY_PAGE_DOWN] = KEY_PGDN; + keymap[GLFW_KEY_HOME] = KEY_HOME; + keymap[GLFW_KEY_END] = KEY_END; + keymap[GLFW_KEY_CAPS_LOCK] = KEY_CAPSLK; + keymap[GLFW_KEY_SCROLL_LOCK] = KEY_NULL; + keymap[GLFW_KEY_NUM_LOCK] = KEY_NULL; + keymap[GLFW_KEY_PRINT_SCREEN] = KEY_NULL; + keymap[GLFW_KEY_PAUSE] = KEY_NULL; + + keymap[GLFW_KEY_F1] = KEY_F1; + keymap[GLFW_KEY_F2] = KEY_F2; + keymap[GLFW_KEY_F3] = KEY_F3; + keymap[GLFW_KEY_F4] = KEY_F4; + keymap[GLFW_KEY_F5] = KEY_F5; + keymap[GLFW_KEY_F6] = KEY_F6; + keymap[GLFW_KEY_F7] = KEY_F7; + keymap[GLFW_KEY_F8] = KEY_F8; + keymap[GLFW_KEY_F9] = KEY_F9; + keymap[GLFW_KEY_F10] = KEY_F10; + keymap[GLFW_KEY_F11] = KEY_F11; + keymap[GLFW_KEY_F12] = KEY_F12; + keymap[GLFW_KEY_F13] = KEY_NULL; + keymap[GLFW_KEY_F14] = KEY_NULL; + keymap[GLFW_KEY_F15] = KEY_NULL; + keymap[GLFW_KEY_F16] = KEY_NULL; + keymap[GLFW_KEY_F17] = KEY_NULL; + keymap[GLFW_KEY_F18] = KEY_NULL; + keymap[GLFW_KEY_F19] = KEY_NULL; + keymap[GLFW_KEY_F20] = KEY_NULL; + keymap[GLFW_KEY_F21] = KEY_NULL; + keymap[GLFW_KEY_F22] = KEY_NULL; + keymap[GLFW_KEY_F23] = KEY_NULL; + keymap[GLFW_KEY_F24] = KEY_NULL; + keymap[GLFW_KEY_F25] = KEY_NULL; + keymap[GLFW_KEY_KP_0] = KEY_NULL; + keymap[GLFW_KEY_KP_1] = KEY_NULL; + keymap[GLFW_KEY_KP_2] = KEY_NULL; + keymap[GLFW_KEY_KP_3] = KEY_NULL; + keymap[GLFW_KEY_KP_4] = KEY_NULL; + keymap[GLFW_KEY_KP_5] = KEY_NULL; + keymap[GLFW_KEY_KP_6] = KEY_NULL; + keymap[GLFW_KEY_KP_7] = KEY_NULL; + keymap[GLFW_KEY_KP_8] = KEY_NULL; + keymap[GLFW_KEY_KP_9] = KEY_NULL; + keymap[GLFW_KEY_KP_DECIMAL] = KEY_NULL; + keymap[GLFW_KEY_KP_DIVIDE] = KEY_NULL; + keymap[GLFW_KEY_KP_MULTIPLY] = KEY_NULL; + keymap[GLFW_KEY_KP_SUBTRACT] = KEY_NULL; + keymap[GLFW_KEY_KP_ADD] = KEY_NULL; + keymap[GLFW_KEY_KP_ENTER] = KEY_NULL; + keymap[GLFW_KEY_KP_EQUAL] = KEY_NULL; + keymap[GLFW_KEY_LEFT_SHIFT] = KEY_LSHIFT; + keymap[GLFW_KEY_LEFT_CONTROL] = KEY_LCTRL; + keymap[GLFW_KEY_LEFT_ALT] = KEY_LALT; + keymap[GLFW_KEY_LEFT_SUPER] = KEY_NULL; + keymap[GLFW_KEY_RIGHT_SHIFT] = KEY_RSHIFT; + keymap[GLFW_KEY_RIGHT_CONTROL] = KEY_RCTRL; + keymap[GLFW_KEY_RIGHT_ALT] = KEY_RALT; + keymap[GLFW_KEY_RIGHT_SUPER] = KEY_NULL; + keymap[GLFW_KEY_MENU] = KEY_NULL; +} + +static void KeyUp(int key) { EventHandler(KEYUP, &key); } +static void KeyDown(int key) { EventHandler(KEYDOWN, &key); } + +static void +keypress(GLFWwindow *window, int key, int scancode, int action, int mods) +{ + if(key >= 0 && key <= GLFW_KEY_LAST){ + if(action == GLFW_RELEASE) KeyUp(keymap[key]); + else if(action == GLFW_PRESS) KeyDown(keymap[key]); + else if(action == GLFW_REPEAT) KeyDown(keymap[key]); + } +} + +int +main(int argc, char *argv[]) +{ + EventHandler(INITIALIZE, nil); + + engineStartParams.width = sk::globals.width; + engineStartParams.height = sk::globals.height; + engineStartParams.windowtitle = sk::globals.windowtitle; + engineStartParams.window = &window; + + if(EventHandler(RWINITIALIZE, nil) == EVENTERROR) + return 0; + + initkeymap(); + glfwSetKeyCallback(window, keypress); + + float lastTime = glfwGetTime()*1000; + while(!sk::globals.quit && !glfwWindowShouldClose(window)){ + float currTime = glfwGetTime()*1000; + float timeDelta = (currTime - lastTime)*0.001f; + glfwPollEvents(); + + EventHandler(IDLE, &timeDelta); + + lastTime = currTime; + } + + EventHandler(RWTERMINATE, nil); + + return 0; +} +#endif diff --git a/skeleton/skeleton.cpp b/skeleton/skeleton.cpp new file mode 100644 index 0000000..d0bdb55 --- /dev/null +++ b/skeleton/skeleton.cpp @@ -0,0 +1,57 @@ +#include +#include "skeleton.h" + +namespace sk { + +Globals globals; + +bool +InitRW(void) +{ + if(!rw::Engine::init()) + return false; + if(AppEventHandler(sk::PLUGINATTACH, nil) == EVENTERROR) + return false; + if(!rw::Engine::open()) + return false; + if(!rw::Engine::start(&engineStartParams)) + return false; + rw::engine->loadTextures = 1; + + rw::TexDictionary::setCurrent(rw::TexDictionary::create()); + rw::Image::setSearchPath("."); + return true; +} + +void +TerminateRW(void) +{ + // TODO: delete all tex dicts + rw::Engine::stop(); + rw::Engine::close(); + rw::Engine::term(); +} + +EventStatus +EventHandler(Event e, void *param) +{ + EventStatus s; + s = AppEventHandler(e, param); + if(e == QUIT){ + globals.quit = 1; + return EVENTPROCESSED; + } + if(s == EVENTNOTPROCESSED) + switch(e){ + case RWINITIALIZE: + return InitRW() ? EVENTPROCESSED : EVENTERROR; + case RWTERMINATE: + TerminateRW(); + return EVENTPROCESSED; + default: + break; + } + return s; +} + +} diff --git a/skeleton/skeleton.h b/skeleton/skeleton.h new file mode 100644 index 0000000..dc049d7 --- /dev/null +++ b/skeleton/skeleton.h @@ -0,0 +1,91 @@ +extern rw::EngineStartParams engineStartParams; + +namespace sk { + +using namespace rw; + +// same as RW skeleton +enum Key +{ + // ascii... + + KEY_ESC = 128, + + KEY_F1 = 129, + KEY_F2 = 130, + KEY_F3 = 131, + KEY_F4 = 132, + KEY_F5 = 133, + KEY_F6 = 134, + KEY_F7 = 135, + KEY_F8 = 136, + KEY_F9 = 137, + KEY_F10 = 138, + KEY_F11 = 139, + KEY_F12 = 140, + + KEY_INS = 141, + KEY_DEL = 142, + KEY_HOME = 143, + KEY_END = 144, + KEY_PGUP = 145, + KEY_PGDN = 146, + + KEY_UP = 147, + KEY_DOWN = 148, + KEY_LEFT = 149, + KEY_RIGHT = 150, + + // some stuff ommitted + + KEY_BACKSP = 168, + KEY_TAB = 169, + KEY_CAPSLK = 170, + KEY_ENTER = 171, + KEY_LSHIFT = 172, + KEY_RSHIFT = 173, + KEY_LCTRL = 174, + KEY_RCTRL = 175, + KEY_LALT = 176, + KEY_RALT = 177, + + KEY_NULL, // unused + KEY_NUMKEYS, +}; + +enum EventStatus +{ + EVENTERROR, + EVENTPROCESSED, + EVENTNOTPROCESSED +}; + +enum Event +{ + INITIALIZE, + RWINITIALIZE, + RWTERMINATE, + SELECTDEVICE, + PLUGINATTACH, + KEYDOWN, + KEYUP, + IDLE, + QUIT +}; + +struct Globals +{ + const char *windowtitle; + int32 width; + int32 height; + bool32 quit; +}; +extern Globals globals; + +bool InitRW(void); +void TerminateRW(void); +EventStatus EventHandler(Event e, void *param); + +} + +sk::EventStatus AppEventHandler(sk::Event e, void *param); diff --git a/skeleton/win.cpp b/skeleton/win.cpp new file mode 100644 index 0000000..b8cc034 --- /dev/null +++ b/skeleton/win.cpp @@ -0,0 +1,217 @@ +#include +#include +#include "skeleton.h" + +using namespace sk; +using namespace rw; + +#ifdef RW_D3D9 + +static int keymap[256]; +static void +initkeymap(void) +{ + int i; + for(i = 0; i < 256; i++) + keymap[i] = KEY_NULL; + keymap[VK_SPACE] = ' '; + keymap[VK_OEM_7] = '\''; + keymap[VK_OEM_COMMA] = ','; + keymap[VK_OEM_MINUS] = '-'; + keymap[VK_OEM_PERIOD] = '.'; + keymap[VK_OEM_2] = '/'; + for(i = '0'; i <= '9'; i++) + keymap[i] = i; + keymap[VK_OEM_1] = ';'; + keymap[VK_OEM_NEC_EQUAL] = '='; + for(i = 'A'; i <= 'Z'; i++) + keymap[i] = i; + keymap[VK_OEM_4] = '['; + keymap[VK_OEM_5] = '\\'; + keymap[VK_OEM_6] = ']'; + keymap[VK_OEM_3] = '`'; + keymap[VK_ESCAPE] = KEY_ESC; + keymap[VK_RETURN] = KEY_ENTER; + keymap[VK_TAB] = KEY_TAB; + keymap[VK_BACK] = KEY_BACKSP; + keymap[VK_INSERT] = KEY_INS; + keymap[VK_DELETE] = KEY_DEL; + keymap[VK_RIGHT] = KEY_RIGHT; + keymap[VK_LEFT] = KEY_LEFT; + keymap[VK_DOWN] = KEY_DOWN; + keymap[VK_UP] = KEY_UP; + keymap[VK_PRIOR] = KEY_PGUP; + keymap[VK_NEXT] = KEY_PGDN; + keymap[VK_HOME] = KEY_HOME; + keymap[VK_END] = KEY_END; + keymap[VK_MODECHANGE] = KEY_CAPSLK; + for(i = VK_F1; i <= VK_F24; i++) + keymap[i] = i-VK_F1+KEY_F1; + keymap[VK_LSHIFT] = KEY_LSHIFT; + keymap[VK_LCONTROL] = KEY_LCTRL; + keymap[VK_LMENU] = KEY_LALT; + keymap[VK_RSHIFT] = KEY_RSHIFT; + keymap[VK_RCONTROL] = KEY_RCTRL; + keymap[VK_RMENU] = KEY_RALT; +} +bool running; + +static void KeyUp(int key) { EventHandler(KEYUP, &key); } +static void KeyDown(int key) { EventHandler(KEYDOWN, &key); } + +LRESULT CALLBACK +WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg){ + case WM_DESTROY: + PostQuitMessage(0); + break; + + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + if(wParam == VK_MENU){ + if(GetKeyState(VK_LMENU) & 0x8000) KeyDown(keymap[VK_LMENU]); + if(GetKeyState(VK_RMENU) & 0x8000) KeyDown(keymap[VK_RMENU]); + }else if(wParam == VK_CONTROL){ + if(GetKeyState(VK_LCONTROL) & 0x8000) KeyDown(keymap[VK_LCONTROL]); + if(GetKeyState(VK_RCONTROL) & 0x8000) KeyDown(keymap[VK_RCONTROL]); + }else if(wParam == VK_SHIFT){ + if(GetKeyState(VK_LSHIFT) & 0x8000) KeyDown(keymap[VK_LSHIFT]); + if(GetKeyState(VK_RSHIFT) & 0x8000) KeyDown(keymap[VK_RSHIFT]); + }else + KeyDown(keymap[wParam]); + break; + + case WM_SYSKEYUP: + case WM_KEYUP: + if(wParam == VK_MENU){ + if((GetKeyState(VK_LMENU) & 0x8000) == 0) KeyUp(keymap[VK_LMENU]); + if((GetKeyState(VK_RMENU) & 0x8000) == 0) KeyUp(keymap[VK_RMENU]); + }else if(wParam == VK_CONTROL){ + if((GetKeyState(VK_LCONTROL) & 0x8000) == 0) KeyUp(keymap[VK_LCONTROL]); + if((GetKeyState(VK_RCONTROL) & 0x8000) == 0) KeyUp(keymap[VK_RCONTROL]); + }else if(wParam == VK_SHIFT){ + if((GetKeyState(VK_LSHIFT) & 0x8000) == 0) KeyUp(keymap[VK_LSHIFT]); + if((GetKeyState(VK_RSHIFT) & 0x8000) == 0) KeyUp(keymap[VK_RSHIFT]); + }else + KeyUp(keymap[wParam]); + break; + + case WM_CLOSE: + DestroyWindow(hwnd); + break; + + case WM_QUIT: + running = false; + break; + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +HWND +MakeWindow(HINSTANCE instance, int width, int height, const char *title) +{ + WNDCLASS wc; + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = instance; + wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = 0; + wc.lpszClassName = "librwD3D9"; + if(!RegisterClass(&wc)){ + MessageBox(0, "RegisterClass() - FAILED", 0, 0); + return 0; + } + + HWND win; + win = CreateWindow("librwD3D9", title, + WS_BORDER | WS_CAPTION | WS_SYSMENU | + WS_MINIMIZEBOX | WS_MAXIMIZEBOX, + 0, 0, width, height, 0, 0, instance, 0); + if(!win){ + MessageBox(0, "CreateWindow() - FAILED", 0, 0); + return 0; + } + ShowWindow(win, SW_SHOW); + UpdateWindow(win); + return win; +} + +void +pollEvents(void) +{ + MSG msg; + while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){ + if(msg.message == WM_QUIT){ + running = false; + break; + }else{ + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + +int WINAPI +WinMain(HINSTANCE instance, HINSTANCE, + PSTR cmdLine, int showCmd) +{ + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + + EventHandler(INITIALIZE, nil); + + HWND win = MakeWindow(instance, + sk::globals.width, sk::globals.height, + sk::globals.windowtitle); + if(win == 0){ + MessageBox(0, "MakeWindow() - FAILED", 0, 0); + return 0; + } + engineStartParams.window = win; + initkeymap(); + + if(EventHandler(RWINITIALIZE, nil) == EVENTERROR) + return 0; + + float lastTime = (float)GetTickCount(); + running = true; + while(pollEvents(), !globals.quit){ + float currTime = (float)GetTickCount(); + float timeDelta = (currTime - lastTime)*0.001f; + + EventHandler(IDLE, &timeDelta); + + lastTime = currTime; + } + + EventHandler(RWTERMINATE, nil); + + return 0; +} +#endif + +#ifdef RW_OPENGL +int main(int argc, char *argv[]); + +int WINAPI +WinMain(HINSTANCE instance, HINSTANCE, + PSTR cmdLine, int showCmd) +{ + char *argv[1] = { + "clumpview", + }; + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + + return main(1, argv); +} +#endif diff --git a/src/base.cpp b/src/base.cpp index 7ac5f11..98a1678 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -301,6 +301,26 @@ Matrix::scale(V3d *scale, CombineOp op) return this; } +Matrix* +Matrix::transform(Matrix *mat, CombineOp op) +{ + Matrix tmp; + switch(op){ + case COMBINEREPLACE: + *this = *mat; + break; + case COMBINEPRECONCAT: + mult(&tmp, mat, this); + *this = tmp; + break; + case COMBINEPOSTCONCAT: + mult(&tmp, this, mat); + *this = tmp; + break; + } + return this; +} + void Matrix::lookAt(const V3d &dir, const V3d &up) { diff --git a/src/engine.cpp b/src/engine.cpp index 5b78309..d9d5043 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -128,6 +128,16 @@ Engine::start(EngineStartParams *p) return 1; } +void +Engine::term(void) +{ +} + +void +Engine::close(void) +{ +} + void Engine::stop(void) { diff --git a/src/frame.cpp b/src/frame.cpp index d868039..80fbe41 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -269,6 +269,13 @@ Frame::scale(V3d *scl, CombineOp op) updateObjects(); } +void +Frame::transform(Matrix *mat, CombineOp op) +{ + this->matrix.transform(mat, op); + updateObjects(); +} + void Frame::updateObjects(void) { diff --git a/src/rwbase.h b/src/rwbase.h index 7955006..7497601 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -231,6 +231,7 @@ struct Matrix Matrix *rotate(const Quat &q, CombineOp op); Matrix *translate(V3d *translation, CombineOp op); Matrix *scale(V3d *scl, CombineOp op); + Matrix *transform(Matrix *mat, CombineOp op); void lookAt(const V3d &dir, const V3d &up); // helper functions. consider private diff --git a/src/rwengine.h b/src/rwengine.h index 1428c1e..a1c835c 100644 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -123,6 +123,8 @@ struct Engine static bool32 init(void); static bool32 open(void); static bool32 start(EngineStartParams*); + static void term(void); + static void close(void); static void stop(void); }; diff --git a/src/rwobjects.h b/src/rwobjects.h index 5bbf75b..d38373a 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -125,7 +125,8 @@ struct Frame : PluginBase Matrix *getLTM(void); void rotate(V3d *axis, float32 angle, CombineOp op); void translate(V3d *trans, CombineOp op); - void scale(V3d *trans, CombineOp op); + void scale(V3d *scale, CombineOp op); + void transform(Matrix *mat, CombineOp op); void updateObjects(void); diff --git a/tools/clumpview/camera.cpp b/tools/clumpview/camera.cpp new file mode 100644 index 0000000..27185aa --- /dev/null +++ b/tools/clumpview/camera.cpp @@ -0,0 +1,134 @@ +#include +#include + +#include + +#define PI 3.14159265359f +#include "camera.h" + +using rw::Quat; +using rw::V3d; + +void +Camera::update(void) +{ + if(m_rwcam){ + m_rwcam->nearPlane = m_near; + m_rwcam->farPlane = m_far; + m_rwcam->setFOV(m_fov, m_aspectRatio); + + rw::Frame *f = m_rwcam->getFrame(); + if(f){ + V3d forward = normalize(sub(m_target, m_position)); + V3d left = normalize(cross(m_up, forward)); + V3d nup = cross(forward, left); + f->matrix.right = left; // lol + f->matrix.up = nup; + f->matrix.at = forward; + f->matrix.pos = m_position; + f->matrix.optimize(); + f->updateObjects(); + } + } +} + +void +Camera::setTarget(V3d target) +{ + m_position = sub(m_position, sub(m_target, target)); + m_target = target; +} + +float +Camera::getHeading(void) +{ + V3d dir = sub(m_target, m_position); + float a = atan2(dir.y, dir.x)-PI/2.0f; + return m_localup.z < 0.0f ? a-PI : a; +} + +void +Camera::turn(float yaw, float pitch) +{ + V3d dir = sub(m_target, m_position); + Quat r = Quat::rotation(yaw, rw::makeV3d(0.0f, 0.0f, 1.0f)); + dir = rotate(dir, r); + m_localup = rotate(m_localup, r); + + V3d right = normalize(cross(dir, m_localup)); + r = Quat::rotation(pitch, right); + dir = rotate(dir, r); + m_localup = normalize(cross(right, dir)); + if(m_localup.z >= 0.0) m_up.z = 1.0; + else m_up.z = -1.0f; + + m_target = add(m_position, dir); +} + +void +Camera::orbit(float yaw, float pitch) +{ + V3d dir = sub(m_target, m_position); + Quat r = Quat::rotation(yaw, rw::makeV3d(0.0f, 0.0f, 1.0f)); + dir = rotate(dir, r); + m_localup = rotate(m_localup, r); + + V3d right = normalize(cross(dir, m_localup)); + r = Quat::rotation(-pitch, right); + dir = rotate(dir, r); + m_localup = normalize(cross(right, dir)); + if(m_localup.z >= 0.0) m_up.z = 1.0; + else m_up.z = -1.0f; + + m_position = sub(m_target, dir); +} + +void +Camera::dolly(float dist) +{ + V3d dir = setlength(sub(m_target, m_position), dist); + m_position = add(m_position, dir); + m_target = add(m_target, dir); +} + +void +Camera::zoom(float dist) +{ + V3d dir = sub(m_target, m_position); + float curdist = length(dir); + if(dist >= curdist) + dist = curdist-0.01f; + dir = setlength(dir, dist); + m_position = add(m_position, dir); +} + +void +Camera::pan(float x, float y) +{ + V3d dir = normalize(sub(m_target, m_position)); + V3d right = normalize(cross(dir, m_up)); + V3d localup = normalize(cross(right, dir)); + dir = add(scale(right, x), scale(localup, y)); + m_position = add(m_position, dir); + m_target = add(m_target, dir); +} + +float +Camera::distanceTo(V3d v) +{ + return length(sub(m_position, v)); +} + +Camera::Camera() +{ + m_position.set(0.0f, 6.0f, 0.0f); + m_target.set(0.0f, 0.0f, 0.0f); + m_up.set(0.0f, 0.0f, 1.0f); + m_localup = m_up; + m_fov = 70.0f; + m_aspectRatio = 1.0f; + m_near = 0.1f; + m_far = 100.0f; + m_rwcam = NULL; +} + diff --git a/tools/clumpview/camera.h b/tools/clumpview/camera.h new file mode 100644 index 0000000..8a0315d --- /dev/null +++ b/tools/clumpview/camera.h @@ -0,0 +1,26 @@ +class Camera +{ +public: + rw::Camera *m_rwcam; + rw::V3d m_position; + rw::V3d m_target; + rw::V3d m_up; + rw::V3d m_localup; + + float m_fov, m_aspectRatio; + float m_near, m_far; + + + void setTarget(rw::V3d target); + float getHeading(void); + + void turn(float yaw, float pitch); + void orbit(float yaw, float pitch); + void dolly(float dist); + void zoom(float dist); + void pan(float x, float y); + + void update(void); + float distanceTo(rw::V3d v); + Camera(void); +}; diff --git a/tools/clumpview/main.cpp b/tools/clumpview/main.cpp new file mode 100644 index 0000000..124534d --- /dev/null +++ b/tools/clumpview/main.cpp @@ -0,0 +1,181 @@ +#include +#include +#include "camera.h" +#include + +rw::V3d zero = { 0.0f, 0.0f, 0.0f }; +Camera *camera; +rw::Clump *clump; +rw::World *world; +rw::EngineStartParams engineStartParams; + +void +Init(void) +{ + sk::globals.windowtitle = "Clump viewer"; + sk::globals.width = 640; + sk::globals.height = 480; + sk::globals.quit = 0; +} + +bool +attachPlugins(void) +{ + rw::ps2::registerPDSPlugin(40); + rw::ps2::registerPluginPDSPipes(); + + rw::registerMeshPlugin(); + rw::registerNativeDataPlugin(); + rw::registerAtomicRightsPlugin(); + rw::registerMaterialRightsPlugin(); + rw::xbox::registerVertexFormatPlugin(); + rw::registerSkinPlugin(); + rw::registerHAnimPlugin(); + rw::registerMatFXPlugin(); + rw::registerUVAnimPlugin(); + rw::ps2::registerADCPlugin(); + return true; +} + +bool +InitRW(void) +{ +// rw::platform = rw::PLATFORM_D3D8; + if(!sk::InitRW()) + return false; + + char *filename = "teapot.dff"; + rw::StreamFile in; + if(in.open(filename, "rb") == NULL){ + printf("couldn't open file\n"); + return false; + } + rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL); + clump = rw::Clump::streamRead(&in); + assert(clump); + in.close(); + + clump->getFrame()->translate(&zero, rw::COMBINEREPLACE); + + FORLIST(lnk, clump->atomics){ + rw::Atomic *a = rw::Atomic::fromClump(lnk); + if(a->pipeline && a->pipeline->platform != rw::platform) + a->pipeline = NULL; + } + + + world = rw::World::create(); + + rw::Light *ambient = rw::Light::create(rw::Light::AMBIENT); + ambient->setColor(0.2f, 0.2f, 0.2f); + world->addLight(ambient); + + rw::V3d xaxis = { 1.0f, 0.0f, 0.0f }; + rw::Light *direct = rw::Light::create(rw::Light::DIRECTIONAL); + direct->setColor(0.8f, 0.8f, 0.8f); + direct->setFrame(rw::Frame::create()); + direct->getFrame()->rotate(&xaxis, 180.0f, rw::COMBINEREPLACE); + world->addLight(direct); + + camera = new Camera; + camera->m_rwcam = rw::Camera::create(); + camera->m_rwcam->setFrame(rw::Frame::create()); + camera->m_aspectRatio = 640.0f/480.0f; + camera->m_near = 0.1f; + camera->m_far = 450.0f; + camera->m_target.set(0.0f, 0.0f, 0.0f); + camera->m_position.set(0.0f, -10.0f, 0.0f); +// camera->setPosition(Vec3(0.0f, 5.0f, 0.0f)); +// camera->setPosition(Vec3(0.0f, -70.0f, 0.0f)); +// camera->setPosition(Vec3(0.0f, -1.0f, 3.0f)); + camera->update(); + + world->addCamera(camera->m_rwcam); + + return true; +} + +void +Draw(float timeDelta) +{ + static rw::RGBA clearcol = { 0x80, 0x80, 0x80, 0xFF }; + camera->m_rwcam->clear(&clearcol, rw::Camera::CLEARIMAGE|rw::Camera::CLEARZ); + camera->update(); + camera->m_rwcam->beginUpdate(); + + clump->render(); + + camera->m_rwcam->endUpdate(); + camera->m_rwcam->showRaster(); +} + + +void +KeyUp(int key) +{ +} + +void +KeyDown(int key) +{ + switch(key){ + case 'W': + camera->orbit(0.0f, 0.1f); + break; + case 'S': + camera->orbit(0.0f, -0.1f); + break; + case 'A': + camera->orbit(-0.1f, 0.0f); + break; + case 'D': + camera->orbit(0.1f, 0.0f); + break; + case sk::KEY_UP: + camera->turn(0.0f, 0.1f); + break; + case sk::KEY_DOWN: + camera->turn(0.0f, -0.1f); + break; + case sk::KEY_LEFT: + camera->turn(0.1f, 0.0f); + break; + case sk::KEY_RIGHT: + camera->turn(-0.1f, 0.0f); + break; + case 'R': + camera->zoom(0.1f); + break; + case 'F': + camera->zoom(-0.1f); + break; + case sk::KEY_ESC: + sk::globals.quit = 1; + break; + } +} + +sk::EventStatus +AppEventHandler(sk::Event e, void *param) +{ + using namespace sk; + switch(e){ + case INITIALIZE: + Init(); + return EVENTPROCESSED; + case RWINITIALIZE: + return ::InitRW() ? EVENTPROCESSED : EVENTERROR; + case PLUGINATTACH: + return attachPlugins() ? EVENTPROCESSED : EVENTERROR; + case KEYDOWN: + KeyDown(*(int*)param); + return EVENTPROCESSED; + case KEYUP: + KeyUp(*(int*)param); + return EVENTPROCESSED; + case IDLE: + Draw(*(float*)param); + return EVENTPROCESSED; + } + return sk::EVENTNOTPROCESSED; +} diff --git a/tools/clumpview/teapot.dff b/tools/clumpview/teapot.dff new file mode 100644 index 0000000000000000000000000000000000000000..7a65176c0659c246a447047757cf984498180b97 GIT binary patch literal 42796 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 literal 0 HcmV?d00001 From f7988a5fcc86bdf349713d6dc8d0fa5c5c936075 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 10 Aug 2017 14:43:52 +0200 Subject: [PATCH 3/8] got rid of PluginBase inhertiance because ps2 gcc complained about non-POD types --- src/camera.cpp | 2 ++ src/clump.cpp | 3 +++ src/frame.cpp | 1 + src/geometry.cpp | 3 +++ src/image.cpp | 4 ++++ src/light.cpp | 2 ++ src/rwobjects.h | 33 ++++++++++++++++++++++----------- src/rwplg.h | 37 ++++++++++++++++--------------------- src/world.cpp | 2 ++ 9 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/camera.cpp b/src/camera.cpp index 76e68a3..966c43d 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -12,6 +12,8 @@ namespace rw { +PluginList Camera::s_plglist = { sizeof(Camera), sizeof(Camera), nil, nil }; + void defaultBeginUpdateCB(Camera *cam) { diff --git a/src/clump.cpp b/src/clump.cpp index 17efa3d..258d737 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -13,6 +13,9 @@ namespace rw { +PluginList Clump::s_plglist = { sizeof(Clump), sizeof(Clump), nil, nil }; +PluginList Atomic::s_plglist = { sizeof(Atomic), sizeof(Atomic), nil, nil }; + // // Clump // diff --git a/src/frame.cpp b/src/frame.cpp index 80fbe41..ff635d2 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -12,6 +12,7 @@ namespace rw { LinkList Frame::dirtyList; +PluginList Frame::s_plglist = { sizeof(Frame), sizeof(Frame), nil, nil }; Frame* Frame::create(void) diff --git a/src/geometry.cpp b/src/geometry.cpp index 2ee044d..44dcfc4 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -14,6 +14,9 @@ namespace rw { +PluginList Geometry::s_plglist = { sizeof(Geometry), sizeof(Geometry), nil, nil }; +PluginList Material::s_plglist = { sizeof(Material), sizeof(Material), nil, nil }; + SurfaceProperties defaultSurfaceProps = { 1.0f, 1.0f, 1.0f }; Geometry* diff --git a/src/image.cpp b/src/image.cpp index 06a7ef3..244ff77 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -24,6 +24,10 @@ namespace rw { +PluginList TexDictionary::s_plglist = { sizeof(TexDictionary), sizeof(TexDictionary), nil, nil }; +PluginList Texture::s_plglist = { sizeof(Texture), sizeof(Texture), nil, nil }; +PluginList Raster::s_plglist = { sizeof(Raster), sizeof(Raster), nil, nil }; + // // TexDictionary // diff --git a/src/light.cpp b/src/light.cpp index 55eeba0..21ced14 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -11,6 +11,8 @@ namespace rw { +PluginList Light::s_plglist = { sizeof(Light), sizeof(Light), nil, nil }; + static void lightSync(ObjectWithFrame*) { diff --git a/src/rwobjects.h b/src/rwobjects.h index d38373a..e18fa70 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -82,8 +82,9 @@ struct Object } }; -struct Frame : PluginBase +struct Frame { + PLUGINBASE typedef Frame *(*Callback)(Frame *f, void *data); enum { ID = 0 }; enum { // private flags @@ -215,8 +216,9 @@ struct RasterLevels } levels[1]; // 0 is illegal :/ }; -struct Raster : PluginBase +struct Raster { + PLUGINBASE int32 platform; int32 type; // hardly used @@ -268,8 +270,9 @@ struct Raster : PluginBase struct TexDictionary; -struct Texture : PluginBase +struct Texture { + PLUGINBASE Raster *raster; TexDictionary *dict; LLLink inDict; @@ -317,8 +320,9 @@ struct SurfaceProperties float32 diffuse; }; -struct Material : PluginBase +struct Material { + PLUGINBASE Texture *texture; RGBA color; SurfaceProperties surfaceProps; @@ -391,8 +395,9 @@ struct MaterialList uint32 streamGetSize(void); }; -struct Geometry : PluginBase +struct Geometry { + PLUGINBASE enum { ID = 8 }; Object object; uint32 flags; @@ -453,8 +458,9 @@ void registerNativeDataPlugin(void); struct Clump; struct World; -struct Atomic : PluginBase +struct Atomic { + PLUGINBASE typedef void (*RenderCB)(Atomic *atomic); enum { ID = 1 }; enum { @@ -509,8 +515,9 @@ struct Atomic : PluginBase void registerAtomicRightsPlugin(void); -struct Light : PluginBase +struct Light { + PLUGINBASE enum { ID = 3 }; ObjectWithFrame object; float32 radius; @@ -568,8 +575,9 @@ struct FrustumPlane uint8 closestZ; }; -struct Camera : PluginBase +struct Camera { + PLUGINBASE enum { ID = 4 }; enum { PERSPECTIVE = 1, PARALLEL }; enum { CLEARIMAGE = 0x1, CLEARZ = 0x2}; @@ -625,8 +633,9 @@ struct Camera : PluginBase void setFOV(float32 fov, float32 ratio); }; -struct Clump : PluginBase +struct Clump { + PLUGINBASE enum { ID = 2 }; Object object; LinkList atomics; @@ -664,8 +673,9 @@ struct Clump : PluginBase }; // A bit of a stub right now -struct World : PluginBase +struct World { + PLUGINBASE enum { ID = 7 }; Object object; LinkList lights; // these have positions (type >= 0x80) @@ -676,8 +686,9 @@ struct World : PluginBase void addCamera(Camera *cam); }; -struct TexDictionary : PluginBase +struct TexDictionary { + PLUGINBASE enum { ID = 6 }; Object object; LinkList textures; diff --git a/src/rwplg.h b/src/rwplg.h index 9dc082b..38a1bee 100644 --- a/src/rwplg.h +++ b/src/rwplg.h @@ -49,27 +49,22 @@ struct PluginList int32 getPluginOffset(uint32 id); }; -template -struct PluginBase -{ - static PluginList s_plglist; +#define PLUGINBASE \ + static PluginList s_plglist; \ + static int32 registerPlugin(int32 size, uint32 id, Constructor ctor, \ + Destructor dtor, CopyConstructor copy){ \ + return s_plglist.registerPlugin(size, id, ctor, dtor, copy); \ + } \ + static int32 registerPluginStream(uint32 id, StreamRead read, \ + StreamWrite write, StreamGetSize getSize){ \ + return s_plglist.registerStream(id, read, write, getSize); \ + } \ + static int32 setStreamRightsCallback(uint32 id, RightsCallback cb){ \ + return s_plglist.setStreamRightsCallback(id, cb); \ + } \ + static int32 getPluginOffset(uint32 id){ \ + return s_plglist.getPluginOffset(id); \ + } - static int32 registerPlugin(int32 size, uint32 id, Constructor ctor, - Destructor dtor, CopyConstructor copy){ - return s_plglist.registerPlugin(size, id, ctor, dtor, copy); - } - static int32 registerPluginStream(uint32 id, StreamRead read, - StreamWrite write, StreamGetSize getSize){ - return s_plglist.registerStream(id, read, write, getSize); - } - static int32 setStreamRightsCallback(uint32 id, RightsCallback cb){ - return s_plglist.setStreamRightsCallback(id, cb); - } - static int32 getPluginOffset(uint32 id){ - return s_plglist.getPluginOffset(id); - } -}; -template -PluginList PluginBase::s_plglist = { sizeof(T), sizeof(T), nil, nil }; } diff --git a/src/world.cpp b/src/world.cpp index f63c618..41bad9e 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -13,6 +13,8 @@ namespace rw { +PluginList World::s_plglist = { sizeof(World), sizeof(World), nil, nil }; + World* World::create(void) { From e5c2a66bd5be9739c21c63f39f0bd11b0b40407a Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 10 Aug 2017 14:47:28 +0200 Subject: [PATCH 4/8] fixed some syntax errors --- src/base.cpp | 6 +++--- src/geometry.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/base.cpp b/src/base.cpp index 98a1678..b4d71ce 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -477,9 +477,9 @@ Matrix::orthogonalError(void) float32 Matrix::identityError(void) { - V3d r { right.x-1.0f, right.y, right.z }; - V3d u { up.x, up.y-1.0f, up.z }; - V3d a { at.x, at.y, at.z-1.0f }; + V3d r = { right.x-1.0f, right.y, right.z }; + V3d u = { up.x, up.y-1.0f, up.z }; + V3d a = { at.x, at.y, at.z-1.0f }; return dot(r,r) + dot(u,u) + dot(a,a) + dot(pos,pos); } diff --git a/src/geometry.cpp b/src/geometry.cpp index 44dcfc4..b8f1791 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -291,8 +291,8 @@ Geometry::calculateBoundingSphere(void) { for(int32 i = 0; i < this->numMorphTargets; i++){ MorphTarget *m = &this->morphTargets[i]; - V3d min { 1000000.0f, 1000000.0f, 1000000.0f }; - V3d max { -1000000.0f, -1000000.0f, -1000000.0f }; + V3d min = { 1000000.0f, 1000000.0f, 1000000.0f }; + V3d max = { -1000000.0f, -1000000.0f, -1000000.0f }; V3d *v = m->vertices; for(int32 j = 0; j < this->numVertices; j++){ if(v->x > max.x) max.x = v->x; From aec8c202c64afe288d001d4c9fea0123d03861ed Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 12 Aug 2017 10:25:25 +0200 Subject: [PATCH 5/8] starting work on ps2 driver --- premake5.lua | 36 +- src/base.cpp | 17 +- src/camera.cpp | 56 +- src/d3d/{d3ddriver.cpp => d3ddevice.cpp} | 0 src/engine.cpp | 8 +- src/gl/{gl3driver.cpp => gl3device.cpp} | 0 src/matfx.cpp | 2 +- src/pipeline.cpp | 1 - src/ps2/pds.cpp | 1 + src/ps2/ps2.cpp | 47 +- src/ps2/ps2device.cpp | 41 ++ src/ps2/rwps2.h | 20 +- src/rwengine.h | 3 +- src/rwobjects.h | 3 + src/rwplugins.h | 2 +- src/world.cpp | 7 +- tools/ps2test/gs.h | 437 +++++++++++++++ tools/ps2test/main.cpp | 656 +++++++++++++++++++++++ tools/ps2test/mem.h | 95 ++++ tools/ps2test/ps2.h | 23 + tools/ps2test/vu/defaultpipe.dsm | 128 +++++ tools/ps2test/vu/light.vu | 94 ++++ tools/ps2test/vu/skinpipe.dsm | 129 +++++ tools/ps2test/vu/vu.dsm | 98 ++++ 24 files changed, 1843 insertions(+), 61 deletions(-) mode change 100644 => 100755 src/base.cpp mode change 100644 => 100755 src/camera.cpp rename src/d3d/{d3ddriver.cpp => d3ddevice.cpp} (100%) mode change 100644 => 100755 mode change 100644 => 100755 src/engine.cpp rename src/gl/{gl3driver.cpp => gl3device.cpp} (100%) mode change 100644 => 100755 mode change 100644 => 100755 src/matfx.cpp mode change 100644 => 100755 src/pipeline.cpp mode change 100644 => 100755 src/ps2/pds.cpp mode change 100644 => 100755 src/ps2/ps2.cpp create mode 100755 src/ps2/ps2device.cpp mode change 100644 => 100755 src/ps2/rwps2.h mode change 100644 => 100755 src/rwengine.h mode change 100644 => 100755 src/rwobjects.h mode change 100644 => 100755 src/rwplugins.h mode change 100644 => 100755 src/world.cpp create mode 100755 tools/ps2test/gs.h create mode 100755 tools/ps2test/main.cpp create mode 100755 tools/ps2test/mem.h create mode 100755 tools/ps2test/ps2.h create mode 100755 tools/ps2test/vu/defaultpipe.dsm create mode 100755 tools/ps2test/vu/light.vu create mode 100755 tools/ps2test/vu/skinpipe.dsm create mode 100755 tools/ps2test/vu/vu.dsm diff --git a/premake5.lua b/premake5.lua index 984fcab..4708dbb 100755 --- a/premake5.lua +++ b/premake5.lua @@ -12,8 +12,8 @@ workspace "librw" "win-amd64-null", "win-amd64-gl3", "win-amd64-d3d9" } filter { "system:linux" } platforms { "linux-x86-null", "linux-x86-gl3", - "linux-amd64-null", "linux-amd64-gl3" } - -- TODO: ps2 + "linux-amd64-null", "linux-amd64-gl3", + "ps2" } filter {} filter "configurations:Debug" @@ -31,8 +31,12 @@ workspace "librw" defines { "RW_GL3" } filter { "platforms:*d3d9" } defines { "RW_D3D9" } - filter { "platforms:*ps2" } + filter { "platforms:ps2" } defines { "RW_PS2" } + toolset "gcc" + gccprefix 'ee-' + buildoptions { "-nostdlib", "-fno-common" } + includedirs { "$(PS2SDK)/ee/include", "$(PS2SDK)/common/include" } filter { "platforms:*amd64*" } architecture "x86_64" @@ -110,9 +114,35 @@ function skeltool(dir) findlibs() end +function vucode() + filter "files:**.dsm" + buildcommands { + 'cpp "%{file.relpath}" | dvp-as -o "%{cfg.objdir}/%{file.basename}.o"' + } + buildoutputs { '%{cfg.objdir}/%{file.basename}.o' } + filter {} +end + project "clumpview" kind "WindowedApp" characterset ("MBCS") skeltool("clumpview") flags { "WinMain" } removeplatforms { "*null" } + +project "ps2test" + kind "ConsoleApp" + targetdir (Bindir) + vucode() + removeplatforms { "*gl3", "*d3d9", "*null" } + targetextension '.elf' + includedirs { "." } + files { "tools/ps2test/*.cpp", + "tools/ps2test/vu/*.dsm", + "tools/ps2test/*.h" } + linkoptions '$(PS2SDK)/ee/startup/crt0.o' + linkoptions { '-mno-crt0', "-T$(PS2SDK)/ee/startup/linkfile" } + libdirs { "$(PS2SDK)/ee/lib" } + links { "librw" } + -- "c -lc" is a hack because we need -lc twice for some reason + links { "c -lc", "kernel", "mf" } diff --git a/src/base.cpp b/src/base.cpp old mode 100644 new mode 100755 index b4d71ce..bd263d8 --- a/src/base.cpp +++ b/src/base.cpp @@ -261,6 +261,7 @@ Matrix::translate(V3d *translation, CombineOp op) Matrix tmp; Matrix trans = identMat; trans.pos = *translation; + trans.flags &= ~IDENTITY; switch(op){ case COMBINEREPLACE: *this = trans; @@ -483,22 +484,6 @@ Matrix::identityError(void) return dot(r,r) + dot(u,u) + dot(a,a) + dot(pos,pos); } -#if 0 - -bool32 -Matrix::isIdentity(void) -{ - return matrixIsIdentity((float32*)this); -} - -void -Matrix::transpose(Matrix *m1, Matrix *m2) -{ - matrixTranspose((float32*)m1, (float32*)m2); -} - -#endif - #define PSEP_C '/' #define PSEP_S "/" #ifndef _WIN32 diff --git a/src/camera.cpp b/src/camera.cpp old mode 100644 new mode 100755 index 966c43d..363c35f --- a/src/camera.cpp +++ b/src/camera.cpp @@ -184,7 +184,21 @@ cameraSync(ObjectWithFrame *obj) * and to clip space are handled by separate matrices there. * On these platforms the two matrices are built in the platform's * beginUpdate function. - * On the PS2 the 1/2 translation/shear is removed again on the VU1. + * On the PS2 the z- and w-rows are the same and the + * 1/2 translation/shear is removed again on the VU1 by + * subtracting the w-row/2 from the x- and y-rows. + * + * perspective: + * 1/2w 0 ox/2w -ox/2w + * 0 -1/2h -oy/2h oy/2h + * 0 0 1 0 + * 0 0 1 0 + * + * parallel: + * 1/2w 0 ox/2w -ox/2w + * 0 -1/2h -oy/2h oy/2h + * 0 0 1 0 + * 0 0 0 1 * * RW builds this matrix directly without using explicit * inversion and matrix multiplication. @@ -193,8 +207,8 @@ cameraSync(ObjectWithFrame *obj) Camera *cam = (Camera*)obj; Matrix inv, proj; Matrix::invertOrthonormal(&inv, cam->getFrame()->getLTM()); - float32 xscl = 2.0f/cam->viewWindow.x; - float32 yscl = 2.0f/cam->viewWindow.y; + float32 xscl = 1.0f/(2.0f*cam->viewWindow.x); + float32 yscl = 1.0f/(2.0f*cam->viewWindow.y); proj.flags = 0; proj.right.x = xscl; @@ -351,6 +365,8 @@ Camera::setNearPlane(float32 near) { this->nearPlane = near; calczShiftScale(this); + if(this->getFrame()) + this->getFrame()->updateObjects(); } void @@ -358,6 +374,32 @@ Camera::setFarPlane(float32 far) { this->farPlane = far; calczShiftScale(this); + if(this->getFrame()) + this->getFrame()->updateObjects(); +} + +void +Camera::setViewWindow(const V2d *window) +{ + this->viewWindow = *window; + if(this->getFrame()) + this->getFrame()->updateObjects(); +} + +void +Camera::setViewOffset(const V2d *offset) +{ + this->viewOffset = *offset; + if(this->getFrame()) + this->getFrame()->updateObjects(); +} + +void +Camera::setProjection(int32 proj) +{ + this->projection = proj; + if(this->getFrame()) + this->getFrame()->updateObjects(); } int32 @@ -433,10 +475,12 @@ Camera::streamGetSize(void) void Camera::setFOV(float32 fov, float32 ratio) { + V2d v; float32 a = tan(fov*3.14159f/360.0f); - this->viewWindow.x = a; - this->viewWindow.y = a/ratio; - this->viewOffset.set(0.0f, 0.0f); + v.set(a, a/ratio); + this->setViewWindow(&v); + v.set(0.0f, 0.0f); + this->setViewOffset(&v); } } diff --git a/src/d3d/d3ddriver.cpp b/src/d3d/d3ddevice.cpp old mode 100644 new mode 100755 similarity index 100% rename from src/d3d/d3ddriver.cpp rename to src/d3d/d3ddevice.cpp diff --git a/src/engine.cpp b/src/engine.cpp old mode 100644 new mode 100755 index d9d5043..0b7b53a --- a/src/engine.cpp +++ b/src/engine.cpp @@ -74,7 +74,9 @@ Engine::open(void) // Initialize device // Device and possibly OS specific! -#ifdef RW_GL3 +#ifdef RW_PS2 + engine->device = ps2::renderdevice; +#elif RW_GL3 engine->device = gl3::renderdevice; #elif RW_D3D9 engine->device = d3d::renderdevice; @@ -196,7 +198,7 @@ rasterToImage(Raster*) } int -devicesystem(DeviceReq req, void *arg0) +deviceSystem(DeviceReq req, void *arg0) { return 1; } @@ -210,7 +212,7 @@ Device renderdevice = { null::setRenderState, null::getRenderState, null::im2DRenderIndexedPrimitive, - null::devicesystem + null::deviceSystem }; } diff --git a/src/gl/gl3driver.cpp b/src/gl/gl3device.cpp old mode 100644 new mode 100755 similarity index 100% rename from src/gl/gl3driver.cpp rename to src/gl/gl3device.cpp diff --git a/src/matfx.cpp b/src/matfx.cpp old mode 100644 new mode 100755 index 777c065..70bea42 --- a/src/matfx.cpp +++ b/src/matfx.cpp @@ -145,7 +145,7 @@ MatFX::get(Material *m) return *PLUGINOFFSET(MatFX*, m, matFXGlobals.materialOffset); } -uint32 +int32 MatFX::getEffectIndex(uint32 type) { for(int i = 0; i < 2; i++) diff --git a/src/pipeline.cpp b/src/pipeline.cpp old mode 100644 new mode 100755 index 0cd936b..dfe1c75 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -7,7 +7,6 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" -#include "ps2/rwps2.h" #define COLOR_ARGB(a,r,g,b) \ ((uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) diff --git a/src/ps2/pds.cpp b/src/ps2/pds.cpp old mode 100644 new mode 100755 index 449a2f4..53d977d --- a/src/ps2/pds.cpp +++ b/src/ps2/pds.cpp @@ -7,6 +7,7 @@ #include "../rwplg.h" #include "../rwpipeline.h" #include "../rwobjects.h" +#include "../rwengine.h" #include "../rwanim.h" #include "../rwplugins.h" #include "rwps2.h" diff --git a/src/ps2/ps2.cpp b/src/ps2/ps2.cpp old mode 100644 new mode 100755 index b4a22f6..bd444b3 --- a/src/ps2/ps2.cpp +++ b/src/ps2/ps2.cpp @@ -92,7 +92,6 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) uint32 buf[2]; stream->read(buf, 8); instance->dataSize = buf[0]; - instance->arePointersFixed = buf[1]; // TODO: force alignment instance->data = new uint8[instance->dataSize]; #ifdef RW_PS2 @@ -100,6 +99,10 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) assert(a % 0x10 == 0); #endif stream->read(instance->data, instance->dataSize); +#ifdef RW_PS2 + if(!buf[1]) + fixDmaOffsets(instance); +#endif instance->material = geometry->meshHeader->mesh[i].material; // sizedebug(instance); } @@ -118,13 +121,15 @@ writeNativeData(Stream *stream, int32 len, void *object, int32, int32) InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; for(uint32 i = 0; i < header->numMeshes; i++){ InstanceData *instance = &header->instanceMeshes[i]; - if(instance->arePointersFixed == 2) - unfixDmaOffsets(instance); uint32 buf[2]; buf[0] = instance->dataSize; - buf[1] = instance->arePointersFixed; + buf[1] = unfixDmaOffsets(instance); stream->write(buf, 8); stream->write(instance->data, instance->dataSize); +#ifdef RW_PS2 + if(!buf[1]) + fixDmaOffsets(instance); +#endif } return stream; } @@ -157,13 +162,11 @@ registerNativeDataPlugin(void) getSizeNativeData); } +// Patch DMA ref ADDR fields to point to the actual data. #ifdef RW_PS2 void fixDmaOffsets(InstanceData *inst) { - if(inst->arePointersFixed) - return; - uint32 base = (uint32)inst->data; uint32 *tag = (uint32*)inst->data; for(;;){ @@ -184,7 +187,6 @@ fixDmaOffsets(InstanceData *inst) // DMAret case 0x60000000: // we're done - inst->arePointersFixed = 2; return; default: @@ -195,15 +197,17 @@ fixDmaOffsets(InstanceData *inst) } #endif -void +// Patch DMA ref ADDR fields to qword offsets and return whether +// no ref tags were found. +// Only under RW_PS2 are the addresses actually patched but we need +// the return value for streaming out. +bool32 unfixDmaOffsets(InstanceData *inst) { - (void)inst; + bool32 norefs = 1; #ifdef RW_PS2 - if(inst->arePointersFixed != 2) - return; - uint32 base = (uint32)inst->data; +#endif uint32 *tag = (uint32*)inst->data; for(;;){ switch(tag[0]&0x70000000){ @@ -215,23 +219,23 @@ unfixDmaOffsets(InstanceData *inst) // DMAref case 0x30000000: + norefs = 0; // unfix address and jump to next +#ifdef RW_PS2 tag[1] = (tag[1] - base)>>4; +#endif tag += 4; break; // DMAret case 0x60000000: - // we're done - inst->arePointersFixed = 0; - return; + return norefs; default: fprintf(stderr, "error: unknown DMAtag %X\n", tag[0]); - return; + return norefs; } } -#endif } // Pipeline @@ -586,7 +590,6 @@ MatPipeline::instance(Geometry *g, InstanceData *inst, Mesh *m) InstMeshInfo im = getInstMeshInfo(this, g, m); inst->dataSize = (im.size+im.size2)<<4; - inst->arePointersFixed = im.numBrokenAttribs == 0; // TODO: force alignment inst->data = new uint8[inst->dataSize]; @@ -685,6 +688,8 @@ MatPipeline::instance(Geometry *g, InstanceData *inst, Mesh *m) if(this->instanceCB) this->instanceCB(this, g, m, datap); + if(im.numBrokenAttribs) + fixDmaOffsets(inst); } uint8* @@ -766,6 +771,7 @@ objInstance(rw::ObjPipeline *rwpipe, Atomic *atomic) geo->flags |= Geometry::NATIVE; } +/* static void printVertCounts(InstanceData *inst, int flag) { @@ -794,6 +800,7 @@ printVertCounts(InstanceData *inst, int flag) } } } +*/ static void objUninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) @@ -1241,6 +1248,7 @@ registerADCPlugin(void) } // misc stuff +/* void printDMA(InstanceData *inst) @@ -1300,6 +1308,7 @@ sizedebug(InstanceData *inst) } } } +*/ } } diff --git a/src/ps2/ps2device.cpp b/src/ps2/ps2device.cpp new file mode 100755 index 0000000..f40a9b6 --- /dev/null +++ b/src/ps2/ps2device.cpp @@ -0,0 +1,41 @@ +#ifdef RW_PS2 + +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwerror.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "../rwanim.h" +#include "../rwplugins.h" +#include "rwps2.h" +#include "rwps2plg.h" + +#include "rwps2impl.h" + +#define PLUGIN_ID 2 + +namespace rw { +namespace ps2 { + +Device renderdevice = { + 16777215.0f, 0.0f, + null::beginUpdate, + null::endUpdate, + null::clearCamera, + null::showRaster, + null::setRenderState, + null::getRenderState, + null::im2DRenderIndexedPrimitive, + null::deviceSystem +}; + +} +} + +#endif diff --git a/src/ps2/rwps2.h b/src/ps2/rwps2.h old mode 100644 new mode 100755 index 9a2d930..57f7efc --- a/src/ps2/rwps2.h +++ b/src/ps2/rwps2.h @@ -1,15 +1,19 @@ namespace rw { + +#ifdef RW_PS2 +struct EngineStartParams +{ +}; +#endif + namespace ps2 { void initializePlatform(void); +extern Device renderdevice; + struct InstanceData { - // 0 - addresses in ref tags need fixing - // 1 - no ref tags, so no fixing - // set by the program: - // 2 - ref tags are fixed, need to unfix before stream write - uint32 arePointersFixed; uint32 dataSize; uint8 *data; Material *material; @@ -57,10 +61,8 @@ void registerNativeDataPlugin(void); void printDMA(InstanceData *inst); void sizedebug(InstanceData *inst); -// only RW_PS2 -void fixDmaOffsets(InstanceData *inst); -void unfixDmaOffsets(InstanceData *inst); -// +void fixDmaOffsets(InstanceData *inst); // only RW_PS2 +int32 unfixDmaOffsets(InstanceData *inst); struct PipeAttribute { diff --git a/src/rwengine.h b/src/rwengine.h old mode 100644 new mode 100755 index a1c835c..dd8352d --- a/src/rwengine.h +++ b/src/rwengine.h @@ -140,6 +140,7 @@ namespace null { void beginUpdate(Camera*); void endUpdate(Camera*); void clearCamera(Camera*, RGBA *col, uint32 mode); + void showRaster(Raster*); void setRenderState(int32 state, uint32 value); uint32 getRenderState(int32 state); @@ -154,7 +155,7 @@ namespace null { void im2DRenderIndexedPrimitive(PrimitiveType, void*, int32, void*, int32); - int deviceSystem(DeviceReq req); + int deviceSystem(DeviceReq req, void*); extern Device renderdevice; } diff --git a/src/rwobjects.h b/src/rwobjects.h old mode 100644 new mode 100755 index e18fa70..421a823 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -624,6 +624,9 @@ struct Camera void showRaster(void); void setNearPlane(float32); void setFarPlane(float32); + void setViewWindow(const V2d *window); + void setViewOffset(const V2d *offset); + void setProjection(int32 proj); int32 frustumTestSphere(Sphere *s); static Camera *streamRead(Stream *stream); bool streamWrite(Stream *stream); diff --git a/src/rwplugins.h b/src/rwplugins.h old mode 100644 new mode 100755 index 111c19d..d0edf9f --- a/src/rwplugins.h +++ b/src/rwplugins.h @@ -130,7 +130,7 @@ struct MatFX static void setEffects(Material *m, uint32 flags); static uint32 getEffects(Material *m); static MatFX *get(Material *m); - uint32 getEffectIndex(uint32 type); + int32 getEffectIndex(uint32 type); void setBumpTexture(Texture *t); void setBumpCoefficient(float32 coef); void setEnvTexture(Texture *t); diff --git a/src/world.cpp b/src/world.cpp old mode 100644 new mode 100755 index 41bad9e..d17def9 --- a/src/world.cpp +++ b/src/world.cpp @@ -35,14 +35,19 @@ World::addLight(Light *light) light->world = this; if(light->getType() < Light::POINT){ this->directionalLights.append(&light->inWorld); - }else + }else{ this->lights.append(&light->inWorld); + if(light->getFrame()) + light->getFrame()->updateObjects(); + } } void World::addCamera(Camera *cam) { cam->world = this; + if(cam->getFrame()) + cam->getFrame()->updateObjects(); } } diff --git a/tools/ps2test/gs.h b/tools/ps2test/gs.h new file mode 100755 index 0000000..361ad8c --- /dev/null +++ b/tools/ps2test/gs.h @@ -0,0 +1,437 @@ +#define GS_NONINTERLACED 0 +#define GS_INTERLACED 1 + +#define GS_NTSC 2 +#define GS_PAL 3 +#define GS_VESA1A 0x1a +#define GS_VESA1B 0x1b +#define GS_VESA1C 0x1c +#define GS_VESA1D 0x1d +#define GS_VESA2A 0x2a +#define GS_VESA2B 0x2b +#define GS_VESA2C 0x2c +#define GS_VESA2D 0x2d +#define GS_VESA2E 0x2e +#define GS_VESA3B 0x3b +#define GS_VESA3C 0x3c +#define GS_VESA3D 0x3d +#define GS_VESA3E 0x3e +#define GS_VESA4A 0x4a +#define GS_VESA4B 0x4b +#define GS_DTV480P 0x50 + +#define GS_FIELD 0 +#define GS_FRAME 1 + +#define GS_PSMCT32 0 +#define GS_PSMCT24 1 +#define GS_PSMCT16 2 +#define GS_PSMCT16S 10 +#define GS_PS_GPU24 18 + +#define GS_PSMZ32 0 +#define GS_PSMZ24 1 +#define GS_PSMZ16 2 +#define GS_PSMZ16S 10 + +#define GS_ZTST_NEVER 0 +#define GS_ZTST_ALWAYS 1 +#define GS_ZTST_GREATER 2 +#define GS_ZTST_GEQUAL 3 + +#define GS_PRIM_POINT 0 +#define GS_PRIM_LINE 1 +#define GS_PRIM_LINE_STRIP 2 +#define GS_PRIM_TRI 3 +#define GS_PRIM_TRI_STRIP 4 +#define GS_PRIM_TRI_FAN 5 +#define GS_PRIM_SPRITE 6 +#define GS_PRIM_NO_SPEC 7 +#define GS_IIP_FLAT 0 +#define GS_IIP_GOURAUD 1 + +/* GS general purpose registers */ + +#define GS_PRIM 0x00 +#define GS_RGBAQ 0x01 +#define GS_ST 0x02 +#define GS_UV 0x03 +#define GS_XYZF2 0x04 +#define GS_XYZ2 0x05 +#define GS_TEX0_1 0x06 +#define GS_TEX0_2 0x07 +#define GS_CLAMP_1 0x08 +#define GS_CLAMP_2 0x09 +#define GS_FOG 0x0a +#define GS_XYZF3 0x0c +#define GS_XYZ3 0x0d +#define GS_TEX1_1 0x14 +#define GS_TEX1_2 0x15 +#define GS_TEX2_1 0x16 +#define GS_TEX2_2 0x17 +#define GS_XYOFFSET_1 0x18 +#define GS_XYOFFSET_2 0x19 +#define GS_PRMODECONT 0x1a +#define GS_PRMODE 0x1b +#define GS_TEXCLUT 0x1c +#define GS_SCANMSK 0x22 +#define GS_MIPTBP1_1 0x34 +#define GS_MIPTBP1_2 0x35 +#define GS_MIPTBP2_1 0x36 +#define GS_MIPTBP2_2 0x37 +#define GS_TEXA 0x3b +#define GS_FOGCOL 0x3d +#define GS_TEXFLUSH 0x3f +#define GS_SCISSOR_1 0x40 +#define GS_SCISSOR_2 0x41 +#define GS_ALPHA_1 0x42 +#define GS_ALPHA_2 0x43 +#define GS_DIMX 0x44 +#define GS_DTHE 0x45 +#define GS_COLCLAMP 0x46 +#define GS_TEST_1 0x47 +#define GS_TEST_2 0x48 +#define GS_PABE 0x49 +#define GS_FBA_1 0x4a +#define GS_FBA_2 0x4b +#define GS_FRAME_1 0x4c +#define GS_FRAME_2 0x4d +#define GS_ZBUF_1 0x4e +#define GS_ZBUF_2 0x4f +#define GS_BITBLTBUF 0x50 +#define GS_TRXPOS 0x51 +#define GS_TRXREG 0x52 +#define GS_TRXDIR 0x53 +#define GS_HWREG 0x54 +#define GS_SIGNAL 0x60 +#define GS_FINISH 0x61 +#define GS_LABEL 0x62 + +typedef union +{ + struct { + uint64 EN1 : 1; + uint64 EN2 : 1; + uint64 CRTMD : 3; + uint64 MMOD : 1; + uint64 AMOD : 1; + uint64 SLBG : 1; + uint64 ALP : 8; + } f; + uint64 d; +} GsPmode; + +#define GS_MAKE_PMODE(EN1,EN2,MMOD,AMOD,SLBG,ALP) \ + (BIT64(EN1,0) | BIT64(EN2,1) | BIT64(1,2) | \ + BIT64(MMOD,5) | BIT64(AMOD,6) | BIT64(SLBG,7) | BIT64(ALP,8)) + +typedef union +{ + struct { + uint64 INT : 1; + uint64 FFMD : 1; + uint64 DPMS : 2; + } f; + uint64 d; +} GsSmode2; + +#define GS_MAKE_SMODE2(INT,FFMD,DPMS) \ + (BIT64(INT,0) | BIT64(FFMD,1) | BIT64(DPMS,2)) + +typedef union +{ + struct { + uint64 FBP : 9; + uint64 FBW : 6; + uint64 PSM : 5; + uint64 : 12; + uint64 DBX : 11; + uint64 DBY : 11; + } f; + uint64 d; +} GsDispfb; + +#define GS_MAKE_DISPFB(FBP,FBW,PSM,DBX,DBY) \ + (BIT64(FBP,0) | BIT64(FBW,9) | BIT64(PSM,15) | \ + BIT64(DBX,32) | BIT64(DBY,43)) + +typedef union +{ + struct { + uint64 DX : 12; + uint64 DY : 11; + uint64 MAGH : 4; + uint64 MAGV : 2; + uint64 : 3; + uint64 DW : 12; + uint64 DH : 11; + } f; + uint64 d; +} GsDisplay; + +#define GS_MAKE_DISPLAY(DX,DY,MAGH,MAGV,DW,DH) \ + (BIT64(DX,0) | BIT64(DY,12) | BIT64(MAGH,23) | \ + BIT64(MAGV,27) | BIT64(DW,32) | BIT64(DH,44)) + +typedef union +{ + struct { + uint64 EXBP : 14; + uint64 EXBW : 6; + uint64 FBIN : 2; + uint64 WFFMD : 1; + uint64 EMODA : 2; + uint64 EMODC : 2; + uint64 : 5; + uint64 WDX : 11; + uint64 WDY : 11; + } f; + uint64 d; +} GsExtbuf; + +#define GS_MAKE_EXTBUF(EXBP,EXBW,FBIN,WFFMD,EMODA,EMODC,WDX,WDY) \ + (BIT64(EXBP,0) | BIT64(EXBW,14) | BIT64(FBIN,20) | \ + BIT64(WFFMD,22) | BIT64(EMODA,23) | BIT64(EMODC,25) | \ + BIT64(WDX,32) | BIT64(WDY,43)) + +typedef union +{ + struct { + uint64 SX : 12; + uint64 SY : 11; + uint64 SMPH : 4; + uint64 SMPV : 2; + uint64 : 3; + uint64 WW : 12; + uint64 WH : 11; + } f; + uint64 d; +} GsExtdata; + +#define GS_MAKE_EXTDATA(SX,SY,SMPH,SMPV,WW,WH) \ + (BIT64(SX,0) | BIT64(SY,12) | BIT64(SMPH,23) | \ + BIT64(SMPV,27) | BIT64(WW,32) | BIT64(WH,44)) + +typedef union +{ + struct { + uint64 WRITE : 1; + } f; + uint64 d; +} GsExtwrite; + +typedef union +{ + struct { + uint64 R : 8; + uint64 G : 8; + uint64 B : 8; + } f; + uint64 d; +} GsBgcolor; + +#define GS_MAKE_BGCOLOR(R,G,B) \ + (BIT64(R,0) | BIT64(G,8) | BIT64(B,16)) + +typedef union +{ + struct { + uint64 SIGNAL : 1; + uint64 FINISH : 1; + uint64 HSINT : 1; + uint64 VSINT : 1; + uint64 EDWINT : 1; + uint64 : 3; + uint64 FLUSH : 1; + uint64 RESET : 1; + uint64 : 2; + uint64 NFIELD : 1; + uint64 FIELD : 1; + uint64 FIFO : 2; + uint64 REV : 8; + uint64 ID : 8; + } f; + uint64 d; +} GsCsr; + +#define GS_CSR_SIGNAL_O 0 +#define GS_CSR_FINISH_O 1 +#define GS_CSR_HSINT_O 2 +#define GS_CSR_VSINT_O 3 +#define GS_CSR_EDWINT_O 4 +#define GS_CSR_FLUSH_O 8 +#define GS_CSR_RESET_O 9 +#define GS_CSR_NFIELD_O 12 +#define GS_CSR_FIELD_O 13 +#define GS_CSR_FIFO_O 14 +#define GS_CSR_REV_O 16 +#define GS_CSR_ID_O 24 + +typedef union +{ + struct { + uint64 : 8; + uint64 SIGMSK : 1; + uint64 FINISHMSK : 1; + uint64 HSMSKMSK : 1; + uint64 VSMSKMSK : 1; + uint64 EDWMSKMSK : 1; + } f; + uint64 d; +} GsImr; + +typedef union +{ + struct { + uint64 DIR : 1; + } f; + uint64 d; +} GsBusdir; + +typedef union +{ + struct { + uint64 SIGID : 32; + uint64 LBLID : 32; + } f; + uint64 d; +} GsSiglblid; + + +typedef union +{ + struct { + uint64 FBP : 9; + uint64 : 7; + uint64 FBW : 6; + uint64 : 2; + uint64 PSM : 6; + uint64 : 2; + uint64 FBMSK : 32; + } f; + uint64 d; +} GsFrame; + +#define GS_MAKE_FRAME(FBP,FBW,PSM,FBMASK) \ + (BIT64(FBP,0) | BIT64(FBW,16) | BIT64(PSM,24) | BIT64(FBMASK,32)) + +typedef union +{ + struct { + uint64 ZBP : 9; + uint64 : 15; + uint64 PSM : 4; + uint64 : 4; + uint64 ZMSDK : 1; + } f; + uint64 d; +} GsZbuf; + +#define GS_MAKE_ZBUF(ZBP,PSM,ZMSK) \ + (BIT64(ZBP,0) | BIT64(PSM,24) | BIT64(ZMSK,32)) + +typedef union +{ + struct { + uint64 OFX : 16; + uint64 : 16; + uint64 OFY : 16; + } f; + uint64 d; +} GsXyOffset; + +#define GS_MAKE_XYOFFSET(OFX,OFY) \ + (BIT64(OFX,0) | BIT64(OFY,32)) + +typedef union +{ + struct { + uint64 SCAX0 : 11; + uint64 : 5; + uint64 SCAX1 : 11; + uint64 : 5; + uint64 SCAY0 : 11; + uint64 : 5; + uint64 SCAY1 : 11; + } f; + uint64 d; +} GsScissor; + +#define GS_MAKE_SCISSOR(SCAX0,SCAX1,SCAY0,SCAY1) \ + (BIT64(SCAX0,0) | BIT64(SCAX1,16) | BIT64(SCAY0,32) | BIT64(SCAY1,48)) + +#define GS_MAKE_TEST(ATE,ATST,AREF,AFAIL,DATE,DATM,ZTE,ZTST) \ + (BIT64(ATE,0) | BIT64(ATST,1) | BIT64(AREF,4) | BIT64(AFAIL,12) | \ + BIT64(DATE,14) | BIT64(DATM,15) | BIT64(ZTE,16) | BIT64(ZTST,17)) + +#define GS_MAKE_PRIM(PRIM,IIP,TME,FGE,ABE,AA1,FST,CTXT,FIX) \ + (BIT64(PRIM,0) | BIT64(IIP,3) | BIT64(TME,4) | BIT64(FGE,5) | \ + BIT64(ABE,6) | BIT64(AA1,7) | BIT64(FST,8) | BIT64(CTXT,9) | BIT64(FIX,10)) + +#define GS_MAKE_RGBAQ(R,G,B,A,Q) \ + (BIT64(R,0) | BIT64(G,8) | BIT64(B,16) | BIT64(A,24) | BIT64(Q,32)) + +#define GS_MAKE_XYZ(X,Y,Z) \ + (BIT64(X,0) | BIT64(Y,16) | BIT64(Z,32)) + +#define GIF_PACKED 0 +#define GIF_REGLIST 1 +#define GIF_IMAGE 2 + +#define GIF_MAKE_TAG(NLOOP,EOP,PRE,PRIM,FLG,NREG) \ + (BIT64(NLOOP,0) | BIT64(EOP,15) | BIT64(PRE,46) | \ + BIT64(PRIM,47) | BIT64(FLG,58) | BIT64(NREG,60)) + +/* This is global and not tied to a user context because + * it is set up by kernel functions and not really changed + * afterwards. */ +typedef struct GsCrtState GsCrtState; +struct GsCrtState +{ + short inter, mode, ff; +}; +extern GsCrtState gsCrtState; + +typedef struct GsDispCtx GsDispCtx; +struct GsDispCtx +{ + // two circuits + GsPmode pmode; + GsDispfb dispfb1; + GsDispfb dispfb2; + GsDisplay display1; + GsDisplay display2; + GsBgcolor bgcolor; +}; + +typedef struct GsDrawCtx GsDrawCtx; +struct GsDrawCtx +{ + //two contexts + uint128 gifTag; + GsFrame frame1; + uint64 ad_frame1; + GsFrame frame2; + uint64 ad_frame2; + GsZbuf zbuf1; + uint64 ad_zbuf1; + GsZbuf zbuf2; + uint64 ad_zbuf2; + GsXyOffset xyoffset1; + uint64 ad_xyoffset1; + GsXyOffset xyoffset2; + uint64 ad_xyoffset2; + GsScissor scissor1; + uint64 ad_scissor1; + GsScissor scissor2; + uint64 ad_scissor2; +}; + +typedef struct GsCtx GsCtx; +struct GsCtx +{ + // display context; two buffers + GsDispCtx disp[2]; + // draw context; two buffers + GsDrawCtx draw[2]; +}; diff --git a/tools/ps2test/main.cpp b/tools/ps2test/main.cpp new file mode 100755 index 0000000..5ca95ff --- /dev/null +++ b/tools/ps2test/main.cpp @@ -0,0 +1,656 @@ +#include +#include + +#include +using rw::uint8; +using rw::uint16; +using rw::uint32; +using rw::uint64; +using rw::int8; +using rw::int16; +using rw::int32; +using rw::int64; +using rw::bool32; +using rw::float32; +typedef uint8 uchar; +typedef uint16 ushort; +typedef uint32 uint; + +#define WIDTH 640 +#define HEIGHT 448 + +#include "ps2.h" + +// getting undefined references otherwise :/ +int *__errno() { return &errno; } + +// NONINTERLACED and FRAME have half of the FIELD vertical resolution! +// NONINTERLACED has half the vertical units + +uint128 packetbuf[128]; +uint128 chainbuf[128]; + +int frames; + +void +printquad(uint128 p) +{ + uint64 *lp; + lp = (uint64*)&p; + printf("%016lx %016lx\n", lp[1], lp[0]); +} + +struct DmaChannel { + uint32 chcr; uint32 pad0[3]; + uint32 madr; uint32 pad1[3]; + uint32 qwc; uint32 pad2[3]; + uint32 tadr; uint32 pad3[3]; + uint32 asr0; uint32 pad4[3]; + uint32 asr1; uint32 pad5[3]; + uint32 pad6[8]; + uint32 sadr; +}; + +static struct DmaChannel *dmaChannels[] = { + (struct DmaChannel *) &D0_CHCR, + (struct DmaChannel *) &D1_CHCR, + (struct DmaChannel *) &D2_CHCR, + (struct DmaChannel *) &D3_CHCR, + (struct DmaChannel *) &D4_CHCR, + (struct DmaChannel *) &D5_CHCR, + (struct DmaChannel *) &D6_CHCR, + (struct DmaChannel *) &D7_CHCR, + (struct DmaChannel *) &D8_CHCR, + (struct DmaChannel *) &D9_CHCR +}; + +void +dmaReset(void) +{ + /* don't clear the SIF channels */ + int doclear[] = { 1, 1, 1, 1, 1, 0, 0, 0, 1, 1 }; + int i; + + D_CTRL = 0; + for(i = 0; i < 10; i++) + if(doclear[i]){ + dmaChannels[i]->chcr = 0; + dmaChannels[i]->madr = 0; + dmaChannels[i]->qwc = 0; + dmaChannels[i]->tadr = 0; + dmaChannels[i]->asr0 = 0; + dmaChannels[i]->asr1 = 0; + dmaChannels[i]->sadr = 0; + } + D_CTRL = 1; +} + +void +waitDMA(volatile uint32 *chcr) +{ + while(*chcr & (1<<8)); +} + +void +qwcpy(uint128 *dst, uint128 *src, int n) +{ + while(n--) *dst++ = *src++; +} + +void +toGIF(void *src, int n) +{ + FlushCache(0); + D2_QWC = n; + D2_MADR = (uint32)src; + D2_CHCR = 1<<8; + waitDMA(&D2_CHCR); +} + +void +toGIFchain(void *src) +{ + FlushCache(0); + D2_QWC = 0; + D2_TADR = (uint32)src & 0x0FFFFFFF; + D2_CHCR = 1<<0 | 1<<2 | 1<<6 | 1<<8; + waitDMA(&D2_CHCR); +} + +void +toVIF1chain(void *src) +{ + FlushCache(0); + D1_QWC = 0; + D1_TADR = (uint32)src & 0x0FFFFFFF; + D1_CHCR = 1<<0 | 1<<2 | 1<<6 | 1<<8; + waitDMA(&D1_CHCR); +} + + +GsCrtState gsCrtState; + +int psmsizemap[64] = { + 4, // GS_PSMCT32 + 4, // GS_PSMCT24 + 2, // GS_PSMCT16 + 0, 0, 0, 0, 0, 0, 0, + 2, // GS_PSMCT16S + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, // GS_PSMZ32 + 4, // GS_PSMZ24 + 2, // GS_PSMZ16 + 2, // GS_PSMZ16S + 0, 0, 0, 0, 0 +}; + +void +GsResetCrt(uchar inter, uchar mode, uchar ff) +{ + gsCrtState.inter = inter; + gsCrtState.mode = mode; + gsCrtState.ff = ff; + GS_CSR = 1 << GS_CSR_RESET_O; + __asm__("sync.p; nop"); + GsPutIMR(0xff00); + SetGsCrt(gsCrtState.inter, gsCrtState.mode, gsCrtState.ff); +} + +uint gsAllocPtr = 0; + +void +GsInitDispCtx(GsDispCtx *disp, int width, int height, int psm) +{ + int magh, magv; + int dx, dy; + int dw, dh; + + dx = gsCrtState.mode == GS_NTSC ? 636 : 656; + dy = gsCrtState.mode == GS_NTSC ? 25 : 36; + magh = 2560/width - 1; + magv = 0; + dw = 2560-1; + dh = height-1; + + if(gsCrtState.inter == GS_INTERLACED){ + dy *= 2; + if(gsCrtState.ff == GS_FRAME) + dh = (dh+1)*2-1; + } + + disp->pmode.d = GS_MAKE_PMODE(0, 1, 1, 1, 0, 0x00); + disp->bgcolor.d = 0x404040; + disp->dispfb1.d = 0; + disp->dispfb2.d = GS_MAKE_DISPFB(0, width/64, psm, 0, 0); + disp->display1.d = 0; + disp->display2.d = GS_MAKE_DISPLAY(dx, dy, magh, magv, dw, dh); +} + +void +GsPutDispCtx(GsDispCtx *disp) +{ + GS_PMODE = disp->pmode.d; + GS_DISPFB1 = disp->dispfb1.d; + GS_DISPLAY1 = disp->display1.d; + GS_DISPFB2 = disp->dispfb2.d; + GS_DISPLAY2 = disp->display2.d; + GS_BGCOLOR = disp->bgcolor.d; +} + +void +GsInitDrawCtx(GsDrawCtx *draw, int width, int height, int psm, int zpsm) +{ + MAKE128(draw->gifTag, 0xe, + GIF_MAKE_TAG(8, 1, 0, 0, GIF_PACKED, 1)); + draw->frame1.d = GS_MAKE_FRAME(0, width/64, psm, 0); + draw->ad_frame1 = GS_FRAME_1; + draw->frame2.d = draw->frame1.d; + draw->ad_frame2 = GS_FRAME_2; + draw->zbuf1.d = GS_MAKE_ZBUF(0, zpsm, 0); + draw->ad_zbuf1 = GS_ZBUF_1; + draw->zbuf2.d = draw->zbuf1.d; + draw->ad_zbuf2 = GS_ZBUF_2; + draw->xyoffset1.d = GS_MAKE_XYOFFSET(2048<<4, 2048<<4); + draw->ad_xyoffset1 = GS_XYOFFSET_1; + draw->xyoffset2.d = draw->xyoffset1.d; + draw->ad_xyoffset2 = GS_XYOFFSET_2; + draw->scissor1.d = GS_MAKE_SCISSOR(0, width-1, 0, height-1); + draw->ad_scissor1 = GS_SCISSOR_1; + draw->scissor2.d = draw->scissor1.d; + draw->ad_scissor2 = GS_SCISSOR_2; +} + +void +GsPutDrawCtx(GsDrawCtx *draw) +{ + printquad(*(uint128*)&draw->frame1); + toGIF(draw, 9); +} + +void +GsInitCtx(GsCtx *ctx, int width, int height, int psm, int zpsm) +{ + uint fbsz, zbsz; + uint fbp, zbp; + fbsz = (width*height*psmsizemap[psm] + 2047)/2048; + zbsz = (width*height*psmsizemap[0x30|zpsm] + 2047)/2048; + gsAllocPtr = 2*fbsz + zbsz; + fbp = fbsz; + zbp = fbsz*2; + + GsInitDispCtx(&ctx->disp[0], width, height, psm); + GsInitDispCtx(&ctx->disp[1], width, height, psm); + GsInitDrawCtx(&ctx->draw[0], width, height, psm, zpsm); + GsInitDrawCtx(&ctx->draw[1], width, height, psm, zpsm); + ctx->disp[1].dispfb2.f.FBP = fbp/4; + ctx->draw[0].frame1.f.FBP = fbp/4; + ctx->draw[0].frame2.f.FBP = fbp/4; + ctx->draw[0].zbuf1.f.ZBP = zbp/4; + ctx->draw[0].zbuf2.f.ZBP = zbp/4; + ctx->draw[1].zbuf1.f.ZBP = zbp/4; + ctx->draw[1].zbuf2.f.ZBP = zbp/4; +} + +void +initrender(void) +{ + uint128 *p, tmp; + p = packetbuf; + MAKE128(tmp, 0xe, GIF_MAKE_TAG(2, 1, 0, 0, GIF_PACKED, 1)); + *p++ = tmp; + MAKE128(tmp, GS_PRMODECONT, 1); + *p++ = tmp; + MAKE128(tmp, GS_COLCLAMP, 1); + *p++ = tmp; + toGIF(packetbuf, 3); +} + +void +clearscreen(int r, int g, int b) +{ + int x, y; + uint128 *p, tmp; + p = packetbuf; + + x = (2048 + 640)<<4; + y = (2048 + 448)<<4; + + MAKE128(tmp, 0xe, GIF_MAKE_TAG(5, 1, 0, 0, GIF_PACKED, 1)); + *p++ = tmp; + MAKE128(tmp, GS_TEST_1, GS_MAKE_TEST(0, 0, 0, 0, 0, 0, 1, 1)); + *p++ = tmp; + MAKE128(tmp, GS_PRIM, GS_MAKE_PRIM(GS_PRIM_SPRITE,0,0,0,0,0,0,0,0)); + *p++ = tmp; + MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(r, g, b, 0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(2048<<4, 2048<<4, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x, y, 0)); + *p++ = tmp; + toGIF(packetbuf, 6); +} + +void +drawtest(void) +{ + int x0, x1, x2, x3; + int y0, y1, y2; + uint128 *p, tmp; + int n; + + x0 = 2048<<4; + x1 = (2048 + 210)<<4; + x2 = (2048 + 430)<<4; + x3 = (2048 + 640)<<4; + y0 = 2048<<4; + y1 = (2048 + 224)<<4; + y2 = (2048 + 448)<<4; + + n = 2 + 3*7; + p = packetbuf; + MAKEQ(tmp, 0x70000000 | n+1, 0, 0, 0); + *p++ = tmp; + MAKE128(tmp, 0xe, GIF_MAKE_TAG(n, 1, 0, 0, GIF_PACKED, 1)); + *p++ = tmp; + MAKE128(tmp, GS_TEST_1, GS_MAKE_TEST(0, 0, 0, 0, 0, 0, 1, 1)); + *p++ = tmp; + MAKE128(tmp, GS_PRIM, GS_MAKE_PRIM(GS_PRIM_SPRITE,0,0,0,0,0,0,0,0)); + *p++ = tmp; + MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(255, 0, 0, 0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x0, y0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x1, y1, 0)); + *p++ = tmp; + MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(0, 255, 0, 0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x1, y0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x2, y1, 0)); + *p++ = tmp; + MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(0, 0, 255, 0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x2, y0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x3, y1, 0)); + *p++ = tmp; + MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(0, 255, 255, 0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x0, y1, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x1, y2, 0)); + *p++ = tmp; + MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(255, 0, 255, 0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x1, y1, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x2, y2, 0)); + *p++ = tmp; + MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(255, 255, 0, 0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x2, y1, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x3, y2, 0)); + *p++ = tmp; + MAKE128(tmp, GS_RGBAQ, GS_MAKE_RGBAQ(255, 255, 255, 0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ((2048+20)<<4, y0, 0)); + *p++ = tmp; + MAKE128(tmp, GS_XYZ2, GS_MAKE_XYZ(x3, (2048+20)<<4, 0)); + *p++ = tmp; + toGIFchain(packetbuf); +} + +void +drawtri(void) +{ + uint128 *p, tmp; + uint32 *ip; + int nverts, n; + + nverts = 3; + n = 2*nverts; + p = packetbuf; + MAKEQ(tmp, 0x70000000 | n+1, 0, 0, 0); + *p++ = tmp; + MAKE128(tmp, (0x5<<4) | 0x1, + GIF_MAKE_TAG(nverts, 1, 1, GS_MAKE_PRIM(GS_PRIM_TRI, 1, 0, 0, 0, 0, 0, 0, 0), GIF_PACKED, 2)); + *p++ = tmp; + MAKEQ(tmp, 255, 0, 0, 0); + *p++ = tmp; + MAKEQ(tmp, (2048+85)<<4, (2048+70)<<4, 0, 0); + *p++ = tmp; + MAKEQ(tmp, 0, 255, 0, 0); + *p++ = tmp; + MAKEQ(tmp, (2048+260)<<4, (2048+200)<<4, 0, 0); + *p++ = tmp; + MAKEQ(tmp, 0, 0, 255, 0); + *p++ = tmp; + MAKEQ(tmp, (2048+180)<<4, (2048+350)<<4, 0, 0); + *p++ = tmp; + toGIFchain(packetbuf); +} + + +rw::Matrix projMat, viewMat, worldMat; + +extern uint32 MyDmaPacket[]; +extern rw::RawMatrix vuMat; +extern rw::RawMatrix vuLightMat; +extern float vuXYZScale[]; +extern float vuXYZOffset[]; +extern float vuOffset[]; +extern uint64 vuGIFtag[]; +extern float vuMatcolor[]; +extern float vuSurfProps[]; +extern float vuAmbLight[]; +extern uint32 vuGeometry[]; +extern uint32 mpgCall[]; +extern uint32 textureCall[]; +extern uint32 geometryCall[]; +extern uint32 defaultPipe[]; +extern uint32 skinPipe[]; + +rw::World *world; +rw::Camera *camera; + +void +printMatrix(rw::Matrix *m) +{ + rw::V3d *x = &m->right; + rw::V3d *y = &m->up; + rw::V3d *z = &m->at; + rw::V3d *w = &m->pos; + printf( + "[ [ %8.4f, %8.4f, %8.4f, %8.4f ]\n" + " [ %8.4f, %8.4f, %8.4f, %8.4f ]\n" + " [ %8.4f, %8.4f, %8.4f, %8.4f ]\n" + " [ %8.4f, %8.4f, %8.4f, %8.4f ] ]\n" + " %08x == flags\n", + x->x, y->x, z->x, w->x, + x->y, y->y, z->y, w->y, + x->z, y->z, z->z, w->z, + 0.0f, 0.0f, 0.0f, 1.0f, + m->flags); +} + + +void +drawAtomic(rw::Atomic *atomic) +{ + using namespace rw; + + int i; + Geometry *geo; + Matrix *vp; + + printf("view matrix\n"); + printMatrix(&camera->viewMatrix); + printf("camera matrix\n"); + printMatrix(camera->getFrame()->getLTM()); + printf("atomic ltm\n"); + printMatrix(atomic->getFrame()->getLTM()); + +/* + RpAtomicPS2AllGetMeshHeaderMeshCache(atomic, ps2AllPipeData); + RpAtomicPS2AllGatherObjMetrics(atomic); + RpAtomicPS2AllMorphSetup(atomic, ps2AllPipeData); + RpAtomicPS2AllObjInstanceTest(atomic, ps2AllPipeData); + RpAtomicPS2AllClear(atomic); + RpAtomicPS2AllTransformSetup(atomic, transform); + RpAtomicPS2AllFrustumTest(atomic, &inFrustum); + RpAtomicPS2AllPrimTypeTransTypeSetup(ps2AllPipeData, inFrustum); + RpAtomicPS2AllMatModulateSetup(atomic, ps2AllPipeData); + RpAtomicPS2AllLightingSetup(ps2AllPipeData); +*/ + + // Transform Setup + Matrix::mult((Matrix*)&vuMat, atomic->getFrame()->getLTM(), &camera->viewMatrix); + vuMat.rightw = vuMat.right.z; + vuMat.upw = vuMat.up.z; + vuMat.atw = vuMat.at.z; + vuMat.posw = vuMat.pos.z; + + *(Matrix*)&vuLightMat = *atomic->getFrame()->getLTM(); + vuLightMat.rightw = 0.0f; + vuLightMat.upw = 0.0f; + vuLightMat.atw = 0.0f; + vuLightMat.posw = 1.0f; + + geo = atomic->geometry; + if(!(geo->flags & Geometry::NATIVE)){ + printf("not instanced!\n"); + return; + } + + vuAmbLight[0] = 80; + vuAmbLight[1] = 80; + vuAmbLight[2] = 80; + vuAmbLight[3] = 0; + + assert(geo->instData != NULL); + rw::ps2::InstanceDataHeader *instData = + (rw::ps2::InstanceDataHeader*)geo->instData; + rw::MeshHeader *meshHeader = geo->meshHeader; + rw::Mesh *mesh; + for(i = 0; i < instData->numMeshes; i++){ + geometryCall[1] = (uint32)instData->instanceMeshes[i].data; + vuMatcolor[0] = 1.0f; + vuMatcolor[1] = 1.0f; + vuMatcolor[2] = 1.0f; + vuMatcolor[3] = 1.0f; + + vuGIFtag[0] = GIF_MAKE_TAG(0, 1, 1, GS_MAKE_PRIM(GS_PRIM_TRI_STRIP,1,0,0,0,0,0,0,0), GIF_PACKED, 3); + vuGIFtag[1] = 0x412; + + geometryCall[3] = 0x020000DC; + mpgCall[1] = (uint32)skinPipe; +// geometryCall[3] = 0x02000114; +// mpgCall[1] = (uint32)defaultPipe; + toVIF1chain(MyDmaPacket); + } +} + +void +beginCamera(void) +{ + uint128 *p, tmp; + p = packetbuf; + MAKE128(tmp, 0xe, GIF_MAKE_TAG(2, 1, 0, 0, GIF_PACKED, 1)); + *p++ = tmp; + MAKE128(tmp, GS_XYOFFSET_1, GS_MAKE_XYOFFSET(2048-WIDTH/2 <<4, 2048-HEIGHT/2 <<4)); + *p++ = tmp; + MAKE128(tmp, GS_TEST_1, GS_MAKE_TEST(0, 0, 0, 0, 0, 0, 1, 2)); + *p++ = tmp; + toGIF(packetbuf, 3); + vuXYZScale[0] = WIDTH; + vuXYZScale[1] = HEIGHT; + vuXYZScale[2] = camera->zScale; + vuXYZScale[3] = 0.0f; + vuXYZOffset[0] = 2048.0f; + vuXYZOffset[1] = 2048.0f; + vuXYZOffset[2] = camera->zShift; + vuXYZOffset[3] = 0.0f; +} + +rw::EngineStartParams engineStartParams; + +void +pluginattach(void) +{ + rw::ps2::registerPDSPlugin(40); + rw::ps2::registerPluginPDSPipes(); + + rw::registerMeshPlugin(); + rw::registerNativeDataPlugin(); + rw::registerAtomicRightsPlugin(); + rw::registerMaterialRightsPlugin(); + rw::xbox::registerVertexFormatPlugin(); + rw::registerSkinPlugin(); + rw::registerHAnimPlugin(); + rw::registerMatFXPlugin(); + rw::registerUVAnimPlugin(); + rw::ps2::registerADCPlugin(); +} + +bool32 +initrw(void) +{ + rw::version = 0x34000; + rw::platform = rw::PLATFORM_PS2; + if(!rw::Engine::init()) + return 0; + pluginattach(); + if(!rw::Engine::open()) + return 0; + if(!rw::Engine::start(&engineStartParams)) + return 0; + rw::engine->loadTextures = 0; + + rw::TexDictionary::setCurrent(rw::TexDictionary::create()); + rw::Image::setSearchPath("."); + + world = rw::World::create(); + camera = rw::Camera::create(); + camera->setFrame(rw::Frame::create()); + rw::V3d t = { 0.0f, 0.0f, -4.0f }; +// rw::V3d t = { 0.0f, 0.0f, -40.0f }; + camera->getFrame()->translate(&t, rw::COMBINEPOSTCONCAT); + rw::V3d axis = { 0.0f, 1.0f, 0.0f }; + camera->getFrame()->rotate(&axis, 40.0f, rw::COMBINEPOSTCONCAT); + camera->setNearPlane(0.1f); + camera->setFarPlane(450.0f); + camera->setFOV(60.0f, 4.0f/3.0f); + world->addCamera(camera); + return 1; +} + +int +vsynch(int id) +{ + frames++; + ExitHandler(); + return 0; +} + +int +main() +{ + FlushCache(0); + if(!initrw()){ + printf("init failed!\n"); + for(;;); + } + + rw::uint32 len; + rw::uint8 *data = rw::getFileContents("host:player.DFF", &len); +// rw::uint8 *data = rw::getFileContents("host:od_newscafe_dy.dff", &len); + rw::StreamMemory in; + in.open(data, len); + rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL); + rw::Clump *clump = rw::Clump::streamRead(&in); + in.close(); + delete[] data; + + GsCtx gsCtx; + + dmaReset(); + +// GsResetCrt(GS_NONINTERLACED, GS_NTSC, 0); +// GsInitCtx(&gsCtx, 640, 224, GS_PSMCT32, GS_PSMZ32); + +// GsResetCrt(GS_INTERLACED, GS_NTSC, GS_FRAME); +// GsInitCtx(&gsCtx, 640, 224, GS_PSMCT32, GS_PSMZ32); + + GsResetCrt(GS_INTERLACED, GS_NTSC, GS_FIELD); + GsInitCtx(&gsCtx, WIDTH, HEIGHT, GS_PSMCT32, GS_PSMZ32); + + initrender(); + + AddIntcHandler(2, vsynch, 0); + EnableIntc(2); + + GsPutDrawCtx(&gsCtx.draw[0]); + GsPutDispCtx(&gsCtx.disp[1]); + // PCSX2 needs a delay for some reason + { int i; for(i = 0; i < 1000000; i++); } + clearscreen(0, 0, 0); + drawtest(); + drawtri(); + + vuOffset[0] = 0.0f; + vuOffset[1] = 0.0f; + + camera->beginUpdate(); + beginCamera(); + FORLIST(lnk, clump->atomics) + drawAtomic(rw::Atomic::fromClump(lnk)); + camera->endUpdate(); + + printf("hello %p\n", clump); + for(;;); +// printf(""); + return 0; +} diff --git a/tools/ps2test/mem.h b/tools/ps2test/mem.h new file mode 100755 index 0000000..088c1d4 --- /dev/null +++ b/tools/ps2test/mem.h @@ -0,0 +1,95 @@ +/* FIFOs */ +#define VIF0_FIFO (*(volatile uint128*)0x10004000) +#define VIF1_FIFO (*(volatile uint128*)0x10005000) +#define GIF_FIFO (*(volatile uint128*)0x10006000) +#define IPU_out_FIFO (*(volatile uint128*)0x10007000) +#define IPU_in_FIFO (*(volatile uint128*)0x10007010) + +/* DMA channels */ +// to VIF0 +#define D0_CHCR (*(volatile uint32*)0x10008000) +#define D0_MADR (*(volatile uint32*)0x10008010) +#define D0_QWC (*(volatile uint32*)0x10008020) +#define D0_TADR (*(volatile uint32*)0x10008030) +#define D0_ASR0 (*(volatile uint32*)0x10008040) +#define D0_ASR1 (*(volatile uint32*)0x10008050) +// VIF1 +#define D1_CHCR (*(volatile uint32*)0x10009000) +#define D1_MADR (*(volatile uint32*)0x10009010) +#define D1_QWC (*(volatile uint32*)0x10009020) +#define D1_TADR (*(volatile uint32*)0x10009030) +#define D1_ASR0 (*(volatile uint32*)0x10009040) +#define D1_ASR1 (*(volatile uint32*)0x10009050) +// to GIF +#define D2_CHCR (*(volatile uint32*)0x1000a000) +#define D2_MADR (*(volatile uint32*)0x1000a010) +#define D2_QWC (*(volatile uint32*)0x1000a020) +#define D2_TADR (*(volatile uint32*)0x1000a030) +#define D2_ASR0 (*(volatile uint32*)0x1000a040) +#define D2_ASR1 (*(volatile uint32*)0x1000a050) +// fromIPU +#define D3_CHCR (*(volatile uint32*)0x1000b000) +#define D3_MADR (*(volatile uint32*)0x1000b010) +#define D3_QWC (*(volatile uint32*)0x1000b020) +// toIPU +#define D4_CHCR (*(volatile uint32*)0x1000b400) +#define D4_MADR (*(volatile uint32*)0x1000b410) +#define D4_QWC (*(volatile uint32*)0x1000b420) +#define D4_TADR (*(volatile uint32*)0x1000b430) +// from SIF0 +#define D5_CHCR (*(volatile uint32*)0x1000c000) +#define D5_MADR (*(volatile uint32*)0x1000c010) +#define D5_QWC (*(volatile uint32*)0x1000c020) +// to SIF1 +#define D6_CHCR (*(volatile uint32*)0x1000c400) +#define D6_MADR (*(volatile uint32*)0x1000c410) +#define D6_QWC (*(volatile uint32*)0x1000c420) +#define D6_TADR (*(volatile uint32*)0x1000c430) +// SIF2 +#define D7_CHCR (*(volatile uint32*)0x1000c800) +#define D7_MADR (*(volatile uint32*)0x1000c810) +#define D7_QWC (*(volatile uint32*)0x1000c820) +// fromSPR +#define D8_CHCR (*(volatile uint32*)0x1000d000) +#define D8_MADR (*(volatile uint32*)0x1000d010) +#define D8_QWC (*(volatile uint32*)0x1000d020) +#define D8_SADR (*(volatile uint32*)0x1000d080) +// toSPR +#define D9_CHCR (*(volatile uint32*)0x1000d400) +#define D9_MADR (*(volatile uint32*)0x1000d410) +#define D9_QWC (*(volatile uint32*)0x1000d420) +#define D9_TADR (*(volatile uint32*)0x1000d430) +#define D9_SADR (*(volatile uint32*)0x1000d480) + +/* DMA controller */ +#define D_CTRL (*(volatile uint32*)0x1000e000) +#define D_STAT (*(volatile uint32*)0x1000e010) +#define D_PCR (*(volatile uint32*)0x1000e020) +#define D_SQWC (*(volatile uint32*)0x1000e030) +#define D_RBSR (*(volatile uint32*)0x1000e040) +#define D_RBOR (*(volatile uint32*)0x1000e050) +#define D_STADR (*(volatile uint32*)0x1000e060) +#define D_ENABLER (*(volatile uint32*)0x1000f520) +#define D_ENABLEW (*(volatile uint32*)0x1000f590) + + +/* GS privileged registers */ +#define GS_PMODE (*(volatile uint64*)0x12000000) +#define GS_SMODE1 (*(volatile uint64*)0x12000010) +#define GS_SMODE2 (*(volatile uint64*)0x12000020) +#define GS_SRFSH (*(volatile uint64*)0x12000030) +#define GS_SYNCH1 (*(volatile uint64*)0x12000040) +#define GS_SYNCH2 (*(volatile uint64*)0x12000050) +#define GS_SYNCV (*(volatile uint64*)0x12000060) +#define GS_DISPFB1 (*(volatile uint64*)0x12000070) +#define GS_DISPLAY1 (*(volatile uint64*)0x12000080) +#define GS_DISPFB2 (*(volatile uint64*)0x12000090) +#define GS_DISPLAY2 (*(volatile uint64*)0x120000a0) +#define GS_EXTBUF (*(volatile uint64*)0x120000b0) +#define GS_EXTDATA (*(volatile uint64*)0x120000c0) +#define GS_EXTWRITE (*(volatile uint64*)0x120000d0) +#define GS_BGCOLOR (*(volatile uint64*)0x120000e0) +#define GS_CSR (*(volatile uint64*)0x12001000) +#define GS_IMR (*(volatile uint64*)0x12001010) +#define GS_BUSDIR (*(volatile uint64*)0x12001040) +#define GS_SIGLBLID (*(volatile uint64*)0x12001080) diff --git a/tools/ps2test/ps2.h b/tools/ps2test/ps2.h new file mode 100755 index 0000000..86122da --- /dev/null +++ b/tools/ps2test/ps2.h @@ -0,0 +1,23 @@ +#include + +typedef int quad __attribute__((mode(TI))); +typedef int int128 __attribute__((mode(TI))); +typedef unsigned int uquad __attribute__((mode(TI))); +typedef unsigned int uint128 __attribute__((mode(TI))); + +#define MAKE128(RES,MSB,LSB) \ + __asm__ ( "pcpyld %0, %1, %2" : "=r" (RES) : "r" ((uint64)MSB), "r" ((uint64)LSB)) +#define UINT64(LOW,HIGH) ((uint64)HIGH<<32 | (uint64)LOW) +#define MAKEQ(RES,W0,W1,W2,W3) MAKE128(RES,UINT64(W2,W3),UINT64(W0,W1)) + +#define BIT64(v,s) ((uint64)(v) << (s)) + +#include "mem.h" +#include "gs.h" + +extern uint128 packetbuf[128]; + +void waitDMA(volatile uint32 *chcr); +void toGIF(void *src, int n); + +void drawcube(void); diff --git a/tools/ps2test/vu/defaultpipe.dsm b/tools/ps2test/vu/defaultpipe.dsm new file mode 100755 index 0000000..bc971bf --- /dev/null +++ b/tools/ps2test/vu/defaultpipe.dsm @@ -0,0 +1,128 @@ +.global defaultPipe + +.equ vertexTop, 0x3d0 +.equ numInAttribs, 4 +.equ numOutAttribs, 3 +.equ numOutBuf, 2 +.equ vertCount, ((vertexTop-numOutBuf)/(numInAttribs*2+numOutAttribs*numOutBuf)) +.equ offset, (vertCount*numInAttribs) +.equ outBuf1, (2*offset) +.equ outSize, ((vertexTop-outBuf1-2)/2) +.equ outBuf2, (outBuf1+outSize) + +.equ lightMat, 0x3d0 +.equ lightDir, 0x3d4 +.equ matrix, 0x3f0 +.equ XYZScale, 0x3f7 +.equ XYZOffset, 0x3f8 +.equ gifTag, 0x3fa +.equ matColor, 0x3fb +.equ ambientLight, 0x3fd + +/* This is the the projection matrix we start with: + * 1/2w 0 ox/2w + 1/2 -ox/2w + * 0 -1/2h -oy/2h + 1/2 oy/2h + * 0 0 1 0 + * 0 0 1 0 + * To get rid of the +1/2 in the combined matrix we + * subtract the z-row/2 from the x- and y-rows. + * + * The z-row is then set to [0 0 0 1] such that multiplication + * by XYZscale gives [0 0 0 zScale]. After perspective division + * and addition of XYZoffset we then get zScale/w + zShift for z. + * + * XYZScale scales xy to the resolution and z by zScale. + * XYZOffset translates xy to the GS coordinate system (where + * [2048, 2048] is the center of the frame buffer) and add zShift to z. + */ + +; constant: +; VF28-VF31 transformation matrix +; VF25 XYZ offset + + +.balign 16,0 +defaultPipe: +DMAret * +MPG 0, * +.vu +Start: + SUB.z VF28, VF28, VF28 LOI 0.5 ; right.z = 0 + SUB.z VF29, VF29, VF29 LQ VF28, matrix(VI00) ; up.z = 0 - load matrix + SUB.z VF30, VF30, VF30 LQ VF29, matrix+1(VI00) ; at.z = 0 - load matrix + ADDw.z VF31, VF00, VF00 LQ VF30, matrix+2(VI00) ; at.z = 1 - load matrix + NOP LQ VF31, matrix+3(VI00) ; - load matrix + MULi.w VF20, VF28, I LQ.xyz VF01, XYZScale(VI00) ; fix matrix - load scale + MULi.w VF21, VF29, I NOP ; fix matrix + MULi.w VF22, VF30, I NOP ; fix matrix + MULi.w VF23, VF31, I NOP ; fix matrix + SUBw.xy VF28, VF28, VF20 NOP ; fix matrix + SUBw.xy VF29, VF29, VF21 NOP ; fix matrix + SUBw.xy VF30, VF30, VF22 NOP ; fix matrix + SUBw.xy VF31, VF31, VF23 NOP ; fix matrix + MUL.xy VF28, VF28, VF01 LQ.xyz VF25, XYZOffset(VI00) ; scale matrix + MUL.xy VF29, VF29, VF01 IADDIU VI12, VI00, outBuf1 ; scale matrix + MUL.xy VF30, VF30, VF01 IADDIU VI13, VI00, outBuf2 ; scale matrix + MUL.xyz VF31, VF31, VF01 NOP ; scale matrix +Cnt: + NOP XTOP VI02 ; input pointer + NOP LQ VF01, gifTag(VI00) + NOP XITOP VI01 ; vertex count + NOP IADDIU VI05, VI00, 0x4000 + NOP IADD VI05, VI05, VI05 + NOP IOR VI05, VI05, VI01 + NOP SQ VF01, 0(VI12) + NOP ISW.x VI05, 0(VI12) + NOP IADDIU VI03, VI12, 1 ; output pointer + NOP LQ VF18, lightMat(VI00) + NOP LQ VF19, lightMat+1(VI00) + NOP LQ VF20, lightMat+2(VI00) + +Loop: + NOP LQI VF01, (VI02++) ; vertex + NOP LQI VF02, (VI02++) ; UV + NOP LQI VF03, (VI02++) ; color + NOP LQI VF04, (VI02++) ; normal + + MULAw.xyzw ACC, VF31, VF00w NOP ; transform vertex + MADDAx.xyw ACC, VF28, VF01x NOP + MADDAy.xyw ACC, VF29, VF01y NOP + MADDz.xyzw VF01, VF30, VF01z NOP + ITOF0 VF03, VF03 NOP + ITOF0[I] VF04, VF04 LOI 0.0078125 ; - normal scale + NOP NOP + NOP DIV Q, VF00w, VF01w + NOP WAITQ + MULq VF01, VF01, Q NOP ; perspective division + MULi VF04, VF04, I NOP ; scale normal + NOP MR32.z VF02, VF00 + NOP NOP + SUB.w VF01, VF01, VF01 NOP + MULAx.xyz ACC, VF18, VF04x NOP ; transform normal + MADDAy.xyz ACC, VF19, VF04y NOP + MADDz.xyz VF04, VF20, VF04z NOP + ADD.xyz VF01, VF01, VF25 NOP + MULq VF02, VF02, Q NOP + NOP NOP + FTOI0 VF03, VF03 NOP + FTOI4 VF01, VF01 NOP + NOP SQ VF04, -2(VI02) ; store normal + NOP IADDI VI01, VI01, -1 + NOP SQI VF02, (VI03++) ; STQ + NOP SQI VF03, (VI03++) ; color + NOP SQI VF01, (VI03++) ; vertex + NOP IBNE VI01, VI00, Loop + NOP NOP + +#include "light.vu" + + NOP XGKICK VI12 + NOP IADD VI15,VI00,VI12 + NOP IADD VI12,VI00,VI13 + NOP[E] IADD VI13,VI00,VI15 + NOP NOP + NOP B Cnt + NOP NOP + +.EndMPG +.EndDmaData diff --git a/tools/ps2test/vu/light.vu b/tools/ps2test/vu/light.vu new file mode 100755 index 0000000..cd941d6 --- /dev/null +++ b/tools/ps2test/vu/light.vu @@ -0,0 +1,94 @@ +; Ambient light: + NOP LQ VF26, ambientLight(VI00) + NOP XITOP VI01 + NOP IADDIU VI03, VI12, 2 +Ambloop: + NOP LQ VF03, 0(VI03) ; output color + NOP NOP + NOP NOP + NOP NOP + ITOF0 VF03, VF03 NOP + NOP NOP + NOP NOP + NOP NOP + ADD VF03, VF03, VF26 NOP + NOP NOP + NOP NOP + NOP NOP + FTOI0 VF03, VF03 NOP + NOP IADDI VI01, VI01, -1 + NOP IADDIU VI03, VI03, numOutAttribs + NOP IBNE VI01, VI00, Ambloop + NOP SQ VF03, -numOutAttribs(VI03) +; end amblight + +; Direct Light + NOP LQ VF26, lightDir(VI00) + NOP XITOP VI01 + NOP XTOP VI02 + NOP IADDIU VI03, VI12, 2 + SUB.xyz VF26, VF00, VF26 NOP +Dirloop: + NOP LQ VF01, 3(VI02); ; normal + NOP LQ VF02, 0(VI03); ; output color + NOP NOP + NOP NOP + MUL VF03, VF01, VF26 NOP + ITOF0 VF02, VF02 NOP + NOP NOP + NOP NOP + ADDy.x VF03, VF03, VF03y NOP + NOP NOP + NOP NOP + NOP NOP + ADDz.x VF03, VF03, VF03z NOP + NOP NOP + NOP NOP + NOP NOP + MAX.x VF03, VF00, VF03 NOP ; clamp to 0 + NOP[I] LOI 255 + NOP NOP + NOP NOP + MULi.x VF03, VF03, I NOP + NOP NOP + NOP NOP + NOP NOP + ADDx.xyz VF02, VF02, VF03x NOP + NOP NOP + NOP NOP + NOP NOP + FTOI0 VF02, VF02 NOP + NOP IADDI VI01, VI01, -1 + NOP IADDIU VI02, VI02, numInAttribs + NOP IADDIU VI03, VI03, numOutAttribs + NOP IBNE VI01, VI00, Dirloop + NOP SQ VF02, -numOutAttribs(VI03) +; end dirlight + +; Material color and clamp + NOP LQ VF27, matColor(VI00) + NOP XITOP VI01 + NOP IADDIU VI03, VI12, 2 +Colorloop: + NOP LQ VF03, 0(VI03) + NOP NOP + NOP NOP + NOP NOP + ITOF0 VF03, VF03 NOP + NOP NOP + NOP NOP + NOP NOP +;; MUL VF03, VF03, VF27 NOP + NOP[I] LOI 255 + NOP NOP + NOP NOP + MINIi VF03, VF03, I NOP + NOP NOP + NOP NOP + NOP NOP + FTOI0 VF03, VF03 NOP + NOP IADDI VI01, VI01, -1 + NOP IADDIU VI03, VI03, numOutAttribs + NOP IBNE VI01, VI00, Colorloop + NOP SQ VF03, -numOutAttribs(VI03) +; end material color diff --git a/tools/ps2test/vu/skinpipe.dsm b/tools/ps2test/vu/skinpipe.dsm new file mode 100755 index 0000000..a3a8122 --- /dev/null +++ b/tools/ps2test/vu/skinpipe.dsm @@ -0,0 +1,129 @@ +.global skinPipe + +.equ vertexTop, 0x2d0 +.equ numInAttribs, 5 +.equ numOutAttribs, 3 +.equ numOutBuf, 2 +.equ vertCount, ((vertexTop-numOutBuf)/(numInAttribs*2+numOutAttribs*numOutBuf)) +.equ offset, (vertCount*numInAttribs) +.equ outBuf1, (2*offset) +.equ outSize, ((vertexTop-outBuf1-2)/2) +.equ outBuf2, (outBuf1+outSize) + +.equ lightMat, 0x3d0 +.equ lightDir, 0x3d4 +.equ matrix, 0x3f0 +.equ XYZScale, 0x3f7 +.equ XYZOffset, 0x3f8 +.equ gifTag, 0x3fa +.equ matColor, 0x3fb +.equ ambientLight, 0x3fd + +/* This is the the projection matrix we start with: + * 1/2w 0 ox/2w + 1/2 -ox/2w + * 0 -1/2h -oy/2h + 1/2 oy/2h + * 0 0 1 0 + * 0 0 1 0 + * To get rid of the +1/2 in the combined matrix we + * subtract the z-row/2 from the x- and y-rows. + * + * The z-row is then set to [0 0 0 1] such that multiplication + * by XYZscale gives [0 0 0 zScale]. After perspective division + * and addition of XYZoffset we then get zScale/w + zShift for z. + * + * XYZScale scales xy to the resolution and z by zScale. + * XYZOffset translates xy to the GS coordinate system (where + * [2048, 2048] is the center of the frame buffer) and add zShift to z. + */ + +; constant: +; VF28-VF31 transformation matrix +; VF25 XYZ offset + + +.balign 16,0 +skinPipe: +DMAret * +MPG 0, * +.vu +Start: + SUB.z VF28, VF28, VF28 LOI 0.5 ; right.z = 0 + SUB.z VF29, VF29, VF29 LQ VF28, matrix(VI00) ; up.z = 0 - load matrix + SUB.z VF30, VF30, VF30 LQ VF29, matrix+1(VI00) ; at.z = 0 - load matrix + ADDw.z VF31, VF00, VF00 LQ VF30, matrix+2(VI00) ; at.z = 1 - load matrix + NOP LQ VF31, matrix+3(VI00) ; - load matrix + MULi.w VF20, VF28, I LQ.xyz VF01, XYZScale(VI00) ; fix matrix - load scale + MULi.w VF21, VF29, I NOP ; fix matrix + MULi.w VF22, VF30, I NOP ; fix matrix + MULi.w VF23, VF31, I NOP ; fix matrix + SUBw.xy VF28, VF28, VF20 NOP ; fix matrix + SUBw.xy VF29, VF29, VF21 NOP ; fix matrix + SUBw.xy VF30, VF30, VF22 NOP ; fix matrix + SUBw.xy VF31, VF31, VF23 NOP ; fix matrix + MUL.xy VF28, VF28, VF01 LQ.xyz VF25, XYZOffset(VI00) ; scale matrix + MUL.xy VF29, VF29, VF01 IADDIU VI12, VI00, outBuf1 ; scale matrix + MUL.xy VF30, VF30, VF01 IADDIU VI13, VI00, outBuf2 ; scale matrix + MUL.xyz VF31, VF31, VF01 NOP ; scale matrix +Cnt: + NOP XTOP VI02 ; input pointer + NOP LQ VF01, gifTag(VI00) + NOP XITOP VI01 ; vertex count + NOP IADDIU VI05, VI00, 0x4000 + NOP IADD VI05, VI05, VI05 + NOP IOR VI05, VI05, VI01 + NOP SQ VF01, 0(VI12) + NOP ISW.x VI05, 0(VI12) + NOP IADDIU VI03, VI12, 1 ; output pointer + NOP LQ VF18, lightMat(VI00) + NOP LQ VF19, lightMat+1(VI00) + NOP LQ VF20, lightMat+2(VI00) + +Loop: + NOP LQI VF01, (VI02++) ; vertex + NOP LQI VF02, (VI02++) ; UV + NOP LQI VF03, (VI02++) ; color + NOP LQI VF04, (VI02++) ; normal + NOP IADDIU VI02, VI02, 1 ; skip weights + + MULAw.xyzw ACC, VF31, VF00w NOP ; transform vertex + MADDAx.xyw ACC, VF28, VF01x NOP + MADDAy.xyw ACC, VF29, VF01y NOP + MADDz.xyzw VF01, VF30, VF01z NOP + ITOF0 VF03, VF03 NOP + ITOF0[I] VF04, VF04 LOI 0.0078125 ; - normal scale + NOP NOP + NOP DIV Q, VF00w, VF01w + NOP WAITQ + MULq VF01, VF01, Q NOP ; perspective division + MULi VF04, VF04, I NOP ; scale normal + NOP MR32.z VF02, VF00 + NOP NOP + SUB.w VF01, VF01, VF01 NOP + MULAx.xyz ACC, VF18, VF04x NOP ; transform normal + MADDAy.xyz ACC, VF19, VF04y NOP + MADDz.xyz VF04, VF20, VF04z NOP + ADD.xyz VF01, VF01, VF25 NOP + MULq VF02, VF02, Q NOP + NOP NOP + FTOI0 VF03, VF03 NOP + FTOI4 VF01, VF01 NOP + NOP SQ VF04, -2(VI02) ; store normal + NOP IADDI VI01, VI01, -1 + NOP SQI VF02, (VI03++) ; STQ + NOP SQI VF03, (VI03++) ; color + NOP SQI VF01, (VI03++) ; vertex + NOP IBNE VI01, VI00, Loop + NOP NOP + +#include "light.vu" + + NOP XGKICK VI12 + NOP IADD VI15,VI00,VI12 + NOP IADD VI12,VI00,VI13 + NOP[E] IADD VI13,VI00,VI15 + NOP NOP + NOP B Cnt + NOP NOP + +.EndMPG +.EndDmaData diff --git a/tools/ps2test/vu/vu.dsm b/tools/ps2test/vu/vu.dsm new file mode 100755 index 0000000..58c10d6 --- /dev/null +++ b/tools/ps2test/vu/vu.dsm @@ -0,0 +1,98 @@ +.data +.global MyDmaPacket +.global vuLightMat +.global vuMat +.global vuXYZScale +.global vuXYZOffset +.global vuOffset +.global vuGIFtag +.global vuMatcolor +.global vuSurfProps +.global vuAmbLight +.global mpgCall +.global textureCall +.global geometryCall + +.align 4 + +MyDmaPacket: +DMAcnt * +.EndDmaData + +mpgCall: +DMAcall *, 0 ;vuProg +.EndDmaData + +/* +#define vuSDLightOffset 0x3d0 +#define vuSDBlockLow 0x3c3 +#define vuSDBlockHigh 0x3f0 +#define vuSDmat0 vuSDBlockHigh +#define vuSDmat1 vuSDBlockHigh+1 +#define vuSDmat2 vuSDBlockHigh+2 +#define vuSDmat3 vuSDBlockHigh+3 +#define vuSDnearClip vuSDBlockHigh+4 +#define vuSDfarClip vuSDBlockHigh+5 +#define vuSDxMaxyMax vuSDBlockHigh+6 +#define vuSDcamWcamHzScale vuSDBlockHigh+7 +#define vuSDoffXoffYzShift vuSDBlockHigh+8 +#define vuSDrealOffset vuSDBlockHigh+9 +#define vuSDgifTag vuSDBlockHigh+10 +#define vuSDcolScale vuSDBlockHigh+11 +#define vuSDsurfProps vuSDBlockHigh+12 +#define vuSDpingPongAddr vuSDBlockHigh+13 +#define vuSDpingPongCount vuSDBlockHigh+14 +#define vuSDClipvec1 vuSDBlockHigh+13 +#define vuSDClipvec2 vuSDBlockHigh+14 +#define vuSDVUSwitch vuSDBlockHigh+15 +*/ + +DMAcnt * + UNPACK 4, 4, V4_32, 0x3d0, * +vuLightMat: + .float 1.0, 0.0, 0.0, 0.0 + .float 0.0, 1.0, 0.0, 0.0 + .float 0.0, 0.0, 1.0, 0.0 + .float 0.0, 0.0, 0.0, 1.0 +lightDir: + .float 0.5, -0.5, -0.70710, 0.0 + .EndUnpack + + UNPACK 4, 4, V4_32, 0x3f0, * +vuMat: + .float 0.0, 0.0, 0.0, 0.0 + .float 0.0, 0.0, 0.0, 0.0 + .float 0.0, 0.0, 0.0, 0.0 + .float 0.0, 0.0, 0.0, 0.0 + .EndUnpack + + UNPACK 4, 4, V4_32, 0x3f7, * +vuXYZScale: + .float 0.0, 0.0, 0.0, 0.0 +vuXYZOffset: + .float 0.0, 0.0, 0.0, 0.0 +vuOffset: + .float 0.0, 0.0, 0.0, 0.0 +vuGIFtag: + .int 0x00008000, 0x3005C000, 0x0000000412, 0x00000000 +vuMatcolor: + .float 1.0, 1.0, 1.0, 0.5 +vuSurfProps: + .float 1.0, 1.0, 1.0, 1.0 +vuAmbLight: + .float 0, 0, 0, 0 + .EndUnpack +.EndDmaData + +;;textureCall: +;;DMAcall *, 0 +;;.EndDmaData + +geometryCall: +DMAcall *, 0 ;vuGeometry + BASE 0 + OFFSET 0x0 +.EndDmaData + +DMAend + From 7280647085ee42ee033bab54972d0f7be93fa1b8 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 12 Aug 2017 21:24:19 +0200 Subject: [PATCH 6/8] work on ps2test --- tools/ps2test/main.cpp | 274 ++++++++++++++++++++----------- tools/ps2test/ps2.h | 4 +- tools/ps2test/vu/defaultpipe.dsm | 45 +---- tools/ps2test/vu/light.vu | 158 +++++++++--------- tools/ps2test/vu/setup_persp.vu | 39 +++++ tools/ps2test/vu/skinpipe.dsm | 45 +---- tools/ps2test/vu/vu.dsm | 98 ----------- 7 files changed, 311 insertions(+), 352 deletions(-) create mode 100755 tools/ps2test/vu/setup_persp.vu delete mode 100755 tools/ps2test/vu/vu.dsm diff --git a/tools/ps2test/main.cpp b/tools/ps2test/main.cpp index 5ca95ff..330400a 100755 --- a/tools/ps2test/main.cpp +++ b/tools/ps2test/main.cpp @@ -28,7 +28,20 @@ int *__errno() { return &errno; } // NONINTERLACED has half the vertical units uint128 packetbuf[128]; -uint128 chainbuf[128]; +uint128 vuXYZScale; +uint128 vuXYZOffset; +extern uint32 geometryCall[]; +extern uint32 skinPipe[]; + +uint128 *curVifPtr; +uint128 lightpacket[128]; +int32 numLightQ; + + + +rw::World *world; +rw::Camera *camera; + int frames; @@ -40,6 +53,22 @@ printquad(uint128 p) printf("%016lx %016lx\n", lp[1], lp[0]); } +void +printquad4(uint128 p) +{ + uint32 *lp; + lp = (uint32*)&p; + printf("%08x %08x %08x %08x\n", lp[0], lp[1], lp[2], lp[3]); +} + +void +dump4(uint128 *p, int n) +{ +printf("data at %p\n", p); + while(n--) + printquad4(*p++); +} + struct DmaChannel { uint32 chcr; uint32 pad0[3]; uint32 madr; uint32 pad1[3]; @@ -393,29 +422,6 @@ drawtri(void) toGIFchain(packetbuf); } - -rw::Matrix projMat, viewMat, worldMat; - -extern uint32 MyDmaPacket[]; -extern rw::RawMatrix vuMat; -extern rw::RawMatrix vuLightMat; -extern float vuXYZScale[]; -extern float vuXYZOffset[]; -extern float vuOffset[]; -extern uint64 vuGIFtag[]; -extern float vuMatcolor[]; -extern float vuSurfProps[]; -extern float vuAmbLight[]; -extern uint32 vuGeometry[]; -extern uint32 mpgCall[]; -extern uint32 textureCall[]; -extern uint32 geometryCall[]; -extern uint32 defaultPipe[]; -extern uint32 skinPipe[]; - -rw::World *world; -rw::Camera *camera; - void printMatrix(rw::Matrix *m) { @@ -436,59 +442,120 @@ printMatrix(rw::Matrix *m) m->flags); } +// This is not proper data, just for testing +void +setupLight(rw::Atomic *atomic) +{ + using namespace rw; + Matrix *lightmat; + float32 *lp; + + numLightQ = 0; + lp = (float32*)lightpacket; + + // TODO: this is the wrong matrix. we actually want to + // transform the light, not all normals. + lightmat = atomic->getFrame()->getLTM(); + *lp++ = lightmat->right.x; + *lp++ = lightmat->right.y; + *lp++ = lightmat->right.z; + *lp++ = 0.0f; + *lp++ = lightmat->up.x; + *lp++ = lightmat->up.y; + *lp++ = lightmat->up.z; + *lp++ = 0.0f; + *lp++ = lightmat->at.x; + *lp++ = lightmat->at.y; + *lp++ = lightmat->at.z; + *lp++ = 0.0f; + *lp++ = lightmat->pos.x; + *lp++ = lightmat->pos.y; + *lp++ = lightmat->pos.z; + *lp++ = 1.0f; + // TODO: make a proper light block + // ambient + *lp++ = 80.0f; + *lp++ = 80.0f; + *lp++ = 80.0f; + *lp++ = 0.0f; + // directional + *lp++ = 0.5f; + *lp++ = -0.5f; + *lp++ = -0.7071f; + *lp++ = 0.0f; + numLightQ = 6; +} + +void +setupTransform(rw::Atomic *atomic, rw::Matrix *trans) +{ + rw::Matrix::mult(trans, atomic->getFrame()->getLTM(), &camera->viewMatrix); +} + +enum { + DMAcnt = 0x10000000, + DMAref = 0x30000000, + DMAcall = 0x50000000, + DMAret = 0x60000000, + DMAend = 0x70000000, + + V4_32 = 0x6C +}; + +#define UNPACK(type, nq, offset) ((type)<<24 | (nq)<<16 | (offset)) +#define STCYCL(WL,CL) (0x01000000 | (WL)<<8 | (CL)) void drawAtomic(rw::Atomic *atomic) { using namespace rw; - int i; + Matrix trans; Geometry *geo; - Matrix *vp; - - printf("view matrix\n"); - printMatrix(&camera->viewMatrix); - printf("camera matrix\n"); - printMatrix(camera->getFrame()->getLTM()); - printf("atomic ltm\n"); - printMatrix(atomic->getFrame()->getLTM()); - -/* - RpAtomicPS2AllGetMeshHeaderMeshCache(atomic, ps2AllPipeData); - RpAtomicPS2AllGatherObjMetrics(atomic); - RpAtomicPS2AllMorphSetup(atomic, ps2AllPipeData); - RpAtomicPS2AllObjInstanceTest(atomic, ps2AllPipeData); - RpAtomicPS2AllClear(atomic); - RpAtomicPS2AllTransformSetup(atomic, transform); - RpAtomicPS2AllFrustumTest(atomic, &inFrustum); - RpAtomicPS2AllPrimTypeTransTypeSetup(ps2AllPipeData, inFrustum); - RpAtomicPS2AllMatModulateSetup(atomic, ps2AllPipeData); - RpAtomicPS2AllLightingSetup(ps2AllPipeData); -*/ - - // Transform Setup - Matrix::mult((Matrix*)&vuMat, atomic->getFrame()->getLTM(), &camera->viewMatrix); - vuMat.rightw = vuMat.right.z; - vuMat.upw = vuMat.up.z; - vuMat.atw = vuMat.at.z; - vuMat.posw = vuMat.pos.z; - - *(Matrix*)&vuLightMat = *atomic->getFrame()->getLTM(); - vuLightMat.rightw = 0.0f; - vuLightMat.upw = 0.0f; - vuLightMat.atw = 0.0f; - vuLightMat.posw = 1.0f; + ps2::ObjPipeline *pipe; + ps2::MatPipeline *matpipe; + Material *material; + uint128 tmp, *lp; + uint32 *vec; + RGBAf color; + int i; geo = atomic->geometry; - if(!(geo->flags & Geometry::NATIVE)){ - printf("not instanced!\n"); + pipe = (ps2::ObjPipeline*)atomic->getPipeline(); + if(pipe->platform != PLATFORM_PS2) return; - } - vuAmbLight[0] = 80; - vuAmbLight[1] = 80; - vuAmbLight[2] = 80; - vuAmbLight[3] = 0; + setupLight(atomic); + setupTransform(atomic, &trans); + + curVifPtr = packetbuf; + // upload lights + MAKEQ(tmp, DMAcnt | numLightQ+8, 0, STCYCL(4,4), UNPACK(V4_32, numLightQ, 0x3d0)); + *curVifPtr++ = tmp; + for(lp = lightpacket; numLightQ--;) + *curVifPtr++ = *lp++; + + // upload transformation matrix + MAKEQ(tmp, 0, 0, STCYCL(4,4), UNPACK(V4_32, 4, 0x3f0)); + *curVifPtr++ = tmp; + vec = (uint32*)&trans.right; + MAKEQ(tmp, vec[0], vec[1], vec[2], vec[2]); + *curVifPtr++ = tmp; + vec = (uint32*)&trans.up; + MAKEQ(tmp, vec[0], vec[1], vec[2], vec[2]); + *curVifPtr++ = tmp; + vec = (uint32*)&trans.at; + MAKEQ(tmp, vec[0], vec[1], vec[2], vec[2]); + *curVifPtr++ = tmp; + vec = (uint32*)&trans.pos; + MAKEQ(tmp, vec[0], vec[1], vec[2], vec[2]); + *curVifPtr++ = tmp; + + // upload camera/screen info + MAKEQ(tmp, 0, 0, STCYCL(4,4), UNPACK(V4_32, 2, 0x3f7)); + *curVifPtr++ = tmp; + *curVifPtr++ = vuXYZScale; + *curVifPtr++ = vuXYZOffset; assert(geo->instData != NULL); rw::ps2::InstanceDataHeader *instData = @@ -496,27 +563,49 @@ drawAtomic(rw::Atomic *atomic) rw::MeshHeader *meshHeader = geo->meshHeader; rw::Mesh *mesh; for(i = 0; i < instData->numMeshes; i++){ - geometryCall[1] = (uint32)instData->instanceMeshes[i].data; - vuMatcolor[0] = 1.0f; - vuMatcolor[1] = 1.0f; - vuMatcolor[2] = 1.0f; - vuMatcolor[3] = 1.0f; + material = instData->instanceMeshes[i].material; + matpipe = pipe->groupPipeline; + if(matpipe == nil) + matpipe = (ps2::MatPipeline*)material->pipeline; + if(matpipe == nil) + matpipe = ps2::defaultMatPipe; - vuGIFtag[0] = GIF_MAKE_TAG(0, 1, 1, GS_MAKE_PRIM(GS_PRIM_TRI_STRIP,1,0,0,0,0,0,0,0), GIF_PACKED, 3); - vuGIFtag[1] = 0x412; - - geometryCall[3] = 0x020000DC; - mpgCall[1] = (uint32)skinPipe; -// geometryCall[3] = 0x02000114; -// mpgCall[1] = (uint32)defaultPipe; - toVIF1chain(MyDmaPacket); + // call vu code + MAKEQ(tmp, DMAcall, (uint32)skinPipe, 0, 0); + *curVifPtr++ = tmp; + // unpack GIF tag, material color, surface properties + MAKEQ(tmp, DMAcnt | 3, 0, STCYCL(4,4), UNPACK(V4_32, 3, 0x3fa)); + *curVifPtr++ = tmp; + MAKE128(tmp, 0x412, + GIF_MAKE_TAG(0, 1, 1, GS_MAKE_PRIM(GS_PRIM_TRI_STRIP,1,0,0,0,0,0,0,0), GIF_PACKED, 3)); + *curVifPtr++ = tmp; + convColor(&color, &material->color); + color.alpha *= 128.0f/255.0f; + MAKEQ(tmp, *(uint32*)&color.red, *(uint32*)&color.green, + *(uint32*)&color.blue, *(uint32*)&color.alpha); + *curVifPtr++ = tmp; + MAKEQ(tmp, *(uint32*)&material->surfaceProps.ambient, + *(uint32*)&material->surfaceProps.specular, + *(uint32*)&material->surfaceProps.diffuse, + 0.0f); // extra + *curVifPtr++ = tmp; + // call geometry + MAKEQ(tmp, DMAcall, (uint32)instData->instanceMeshes[i].data, 0x03000000, 0x02000000 | matpipe->vifOffset); + *curVifPtr++ = tmp; } + MAKEQ(tmp, DMAend, 0, 0, 0); + *curVifPtr++ = tmp; + for(lp = packetbuf; lp < curVifPtr; lp++) + printquad4(*lp); + toVIF1chain(packetbuf); } void beginCamera(void) { uint128 *p, tmp; + float32 *f; + p = packetbuf; MAKE128(tmp, 0xe, GIF_MAKE_TAG(2, 1, 0, 0, GIF_PACKED, 1)); *p++ = tmp; @@ -525,14 +614,16 @@ beginCamera(void) MAKE128(tmp, GS_TEST_1, GS_MAKE_TEST(0, 0, 0, 0, 0, 0, 1, 2)); *p++ = tmp; toGIF(packetbuf, 3); - vuXYZScale[0] = WIDTH; - vuXYZScale[1] = HEIGHT; - vuXYZScale[2] = camera->zScale; - vuXYZScale[3] = 0.0f; - vuXYZOffset[0] = 2048.0f; - vuXYZOffset[1] = 2048.0f; - vuXYZOffset[2] = camera->zShift; - vuXYZOffset[3] = 0.0f; + f = (float32*)&vuXYZScale; + f[0] = WIDTH; + f[1] = HEIGHT; + f[2] = camera->zScale; + f[3] = 0.0f; + f = (float32*)&vuXYZOffset; + f[0] = 2048.0f; + f[1] = 2048.0f; + f[2] = camera->zShift; + f[3] = 0.0f; } rw::EngineStartParams engineStartParams; @@ -636,12 +727,9 @@ main() GsPutDispCtx(&gsCtx.disp[1]); // PCSX2 needs a delay for some reason { int i; for(i = 0; i < 1000000; i++); } - clearscreen(0, 0, 0); - drawtest(); - drawtri(); - - vuOffset[0] = 0.0f; - vuOffset[1] = 0.0f; + clearscreen(0x80, 0x80, 0x80); +// drawtest(); +// drawtri(); camera->beginUpdate(); beginCamera(); diff --git a/tools/ps2test/ps2.h b/tools/ps2test/ps2.h index 86122da..ced015a 100755 --- a/tools/ps2test/ps2.h +++ b/tools/ps2test/ps2.h @@ -7,10 +7,10 @@ typedef unsigned int uint128 __attribute__((mode(TI))); #define MAKE128(RES,MSB,LSB) \ __asm__ ( "pcpyld %0, %1, %2" : "=r" (RES) : "r" ((uint64)MSB), "r" ((uint64)LSB)) -#define UINT64(LOW,HIGH) ((uint64)HIGH<<32 | (uint64)LOW) +#define UINT64(LOW,HIGH) (((uint64)HIGH)<<32 | ((uint64)LOW)) #define MAKEQ(RES,W0,W1,W2,W3) MAKE128(RES,UINT64(W2,W3),UINT64(W0,W1)) -#define BIT64(v,s) ((uint64)(v) << (s)) +#define BIT64(v,s) (((uint64)(v)) << (s)) #include "mem.h" #include "gs.h" diff --git a/tools/ps2test/vu/defaultpipe.dsm b/tools/ps2test/vu/defaultpipe.dsm index bc971bf..ae3fa39 100755 --- a/tools/ps2test/vu/defaultpipe.dsm +++ b/tools/ps2test/vu/defaultpipe.dsm @@ -11,34 +11,15 @@ .equ outBuf2, (outBuf1+outSize) .equ lightMat, 0x3d0 -.equ lightDir, 0x3d4 +.equ ambientLight, 0x3d4 +.equ lightDir, 0x3d5 + .equ matrix, 0x3f0 .equ XYZScale, 0x3f7 .equ XYZOffset, 0x3f8 .equ gifTag, 0x3fa .equ matColor, 0x3fb -.equ ambientLight, 0x3fd - -/* This is the the projection matrix we start with: - * 1/2w 0 ox/2w + 1/2 -ox/2w - * 0 -1/2h -oy/2h + 1/2 oy/2h - * 0 0 1 0 - * 0 0 1 0 - * To get rid of the +1/2 in the combined matrix we - * subtract the z-row/2 from the x- and y-rows. - * - * The z-row is then set to [0 0 0 1] such that multiplication - * by XYZscale gives [0 0 0 zScale]. After perspective division - * and addition of XYZoffset we then get zScale/w + zShift for z. - * - * XYZScale scales xy to the resolution and z by zScale. - * XYZOffset translates xy to the GS coordinate system (where - * [2048, 2048] is the center of the frame buffer) and add zShift to z. - */ - -; constant: -; VF28-VF31 transformation matrix -; VF25 XYZ offset +.equ surfProps, 0x3fc .balign 16,0 @@ -47,23 +28,7 @@ DMAret * MPG 0, * .vu Start: - SUB.z VF28, VF28, VF28 LOI 0.5 ; right.z = 0 - SUB.z VF29, VF29, VF29 LQ VF28, matrix(VI00) ; up.z = 0 - load matrix - SUB.z VF30, VF30, VF30 LQ VF29, matrix+1(VI00) ; at.z = 0 - load matrix - ADDw.z VF31, VF00, VF00 LQ VF30, matrix+2(VI00) ; at.z = 1 - load matrix - NOP LQ VF31, matrix+3(VI00) ; - load matrix - MULi.w VF20, VF28, I LQ.xyz VF01, XYZScale(VI00) ; fix matrix - load scale - MULi.w VF21, VF29, I NOP ; fix matrix - MULi.w VF22, VF30, I NOP ; fix matrix - MULi.w VF23, VF31, I NOP ; fix matrix - SUBw.xy VF28, VF28, VF20 NOP ; fix matrix - SUBw.xy VF29, VF29, VF21 NOP ; fix matrix - SUBw.xy VF30, VF30, VF22 NOP ; fix matrix - SUBw.xy VF31, VF31, VF23 NOP ; fix matrix - MUL.xy VF28, VF28, VF01 LQ.xyz VF25, XYZOffset(VI00) ; scale matrix - MUL.xy VF29, VF29, VF01 IADDIU VI12, VI00, outBuf1 ; scale matrix - MUL.xy VF30, VF30, VF01 IADDIU VI13, VI00, outBuf2 ; scale matrix - MUL.xyz VF31, VF31, VF01 NOP ; scale matrix +#include "setup_persp.vu" Cnt: NOP XTOP VI02 ; input pointer NOP LQ VF01, gifTag(VI00) diff --git a/tools/ps2test/vu/light.vu b/tools/ps2test/vu/light.vu index cd941d6..8f7a31c 100755 --- a/tools/ps2test/vu/light.vu +++ b/tools/ps2test/vu/light.vu @@ -1,94 +1,94 @@ ; Ambient light: - NOP LQ VF26, ambientLight(VI00) - NOP XITOP VI01 - NOP IADDIU VI03, VI12, 2 + NOP LQ VF26, ambientLight(VI00) + NOP XITOP VI01 + NOP IADDIU VI03, VI12, 2 Ambloop: - NOP LQ VF03, 0(VI03) ; output color - NOP NOP - NOP NOP - NOP NOP - ITOF0 VF03, VF03 NOP - NOP NOP - NOP NOP - NOP NOP - ADD VF03, VF03, VF26 NOP - NOP NOP - NOP NOP - NOP NOP - FTOI0 VF03, VF03 NOP - NOP IADDI VI01, VI01, -1 - NOP IADDIU VI03, VI03, numOutAttribs - NOP IBNE VI01, VI00, Ambloop - NOP SQ VF03, -numOutAttribs(VI03) + NOP LQ VF03, 0(VI03) ; output color + NOP NOP + NOP NOP + NOP NOP + ITOF0 VF03, VF03 NOP + NOP NOP + NOP NOP + NOP NOP + ADD.xyz VF03, VF03, VF26 NOP + NOP NOP + NOP NOP + NOP NOP + FTOI0 VF03, VF03 NOP + NOP IADDI VI01, VI01, -1 + NOP IADDIU VI03, VI03, numOutAttribs + NOP IBNE VI01, VI00, Ambloop + NOP SQ VF03, -numOutAttribs(VI03) ; end amblight ; Direct Light - NOP LQ VF26, lightDir(VI00) - NOP XITOP VI01 - NOP XTOP VI02 - NOP IADDIU VI03, VI12, 2 + NOP LQ VF26, lightDir(VI00) + NOP XITOP VI01 + NOP XTOP VI02 + NOP IADDIU VI03, VI12, 2 SUB.xyz VF26, VF00, VF26 NOP Dirloop: - NOP LQ VF01, 3(VI02); ; normal - NOP LQ VF02, 0(VI03); ; output color - NOP NOP - NOP NOP - MUL VF03, VF01, VF26 NOP - ITOF0 VF02, VF02 NOP - NOP NOP - NOP NOP + NOP LQ VF01, 3(VI02); ; normal + NOP LQ VF02, 0(VI03); ; output color + NOP NOP + NOP NOP + MUL VF03, VF01, VF26 NOP + ITOF0 VF02, VF02 NOP + NOP NOP + NOP NOP ADDy.x VF03, VF03, VF03y NOP - NOP NOP - NOP NOP - NOP NOP + NOP NOP + NOP NOP + NOP NOP ADDz.x VF03, VF03, VF03z NOP - NOP NOP - NOP NOP - NOP NOP - MAX.x VF03, VF00, VF03 NOP ; clamp to 0 - NOP[I] LOI 255 - NOP NOP - NOP NOP - MULi.x VF03, VF03, I NOP - NOP NOP - NOP NOP - NOP NOP + NOP NOP + NOP NOP + NOP NOP + MAX.x VF03, VF00, VF03 NOP ; clamp to 0 + NOP[I] LOI 255 + NOP NOP + NOP NOP + MULi.x VF03, VF03, I NOP + NOP NOP + NOP NOP + NOP NOP ADDx.xyz VF02, VF02, VF03x NOP - NOP NOP - NOP NOP - NOP NOP - FTOI0 VF02, VF02 NOP - NOP IADDI VI01, VI01, -1 - NOP IADDIU VI02, VI02, numInAttribs - NOP IADDIU VI03, VI03, numOutAttribs - NOP IBNE VI01, VI00, Dirloop - NOP SQ VF02, -numOutAttribs(VI03) + NOP NOP + NOP NOP + NOP NOP + FTOI0 VF02, VF02 NOP + NOP IADDI VI01, VI01, -1 + NOP IADDIU VI02, VI02, numInAttribs + NOP IADDIU VI03, VI03, numOutAttribs + NOP IBNE VI01, VI00, Dirloop + NOP SQ VF02, -numOutAttribs(VI03) ; end dirlight ; Material color and clamp - NOP LQ VF27, matColor(VI00) - NOP XITOP VI01 - NOP IADDIU VI03, VI12, 2 + NOP LQ VF27, matColor(VI00) + NOP XITOP VI01 + NOP IADDIU VI03, VI12, 2 Colorloop: - NOP LQ VF03, 0(VI03) - NOP NOP - NOP NOP - NOP NOP - ITOF0 VF03, VF03 NOP - NOP NOP - NOP NOP - NOP NOP -;; MUL VF03, VF03, VF27 NOP - NOP[I] LOI 255 - NOP NOP - NOP NOP - MINIi VF03, VF03, I NOP - NOP NOP - NOP NOP - NOP NOP - FTOI0 VF03, VF03 NOP - NOP IADDI VI01, VI01, -1 - NOP IADDIU VI03, VI03, numOutAttribs - NOP IBNE VI01, VI00, Colorloop - NOP SQ VF03, -numOutAttribs(VI03) + NOP LQ VF03, 0(VI03) + NOP NOP + NOP NOP + NOP NOP + ITOF0 VF03, VF03 NOP + NOP NOP + NOP NOP + NOP NOP + MUL VF03, VF03, VF27 NOP + NOP[I] LOI 255 + NOP NOP + NOP NOP + MINIi VF03, VF03, I NOP + NOP NOP + NOP NOP + NOP NOP + FTOI0 VF03, VF03 NOP + NOP IADDI VI01, VI01, -1 + NOP IADDIU VI03, VI03, numOutAttribs + NOP IBNE VI01, VI00, Colorloop + NOP SQ VF03, -numOutAttribs(VI03) ; end material color diff --git a/tools/ps2test/vu/setup_persp.vu b/tools/ps2test/vu/setup_persp.vu new file mode 100755 index 0000000..b9ea42f --- /dev/null +++ b/tools/ps2test/vu/setup_persp.vu @@ -0,0 +1,39 @@ +/* This is the the projection matrix we start with: + * 1/2w 0 ox/2w + 1/2 -ox/2w + * 0 -1/2h -oy/2h + 1/2 oy/2h + * 0 0 1 0 + * 0 0 1 0 + * To get rid of the +1/2 in the combined matrix we + * subtract the z-row/2 from the x- and y-rows. + * + * The z-row is then set to [0 0 0 1] such that multiplication + * by XYZscale gives [0 0 0 zScale]. After perspective division + * and addition of XYZoffset we then get zScale/w + zShift for z. + * + * XYZScale scales xy to the resolution and z by zScale. + * XYZOffset translates xy to the GS coordinate system (where + * [2048, 2048] is the center of the frame buffer) and add zShift to z. + */ + +; constant: +; VF28-VF31 transformation matrix +; VF25 XYZ offset + + + SUB.z VF28, VF28, VF28 LOI 0.5 ; right.z = 0 + SUB.z VF29, VF29, VF29 LQ VF28, matrix(VI00) ; up.z = 0 - load matrix + SUB.z VF30, VF30, VF30 LQ VF29, matrix+1(VI00) ; at.z = 0 - load matrix + ADDw.z VF31, VF00, VF00 LQ VF30, matrix+2(VI00) ; at.z = 1 - load matrix + NOP LQ VF31, matrix+3(VI00) ; - load matrix + MULi.w VF20, VF28, I LQ.xyz VF01, XYZScale(VI00) ; fix matrix - load scale + MULi.w VF21, VF29, I NOP ; fix matrix + MULi.w VF22, VF30, I NOP ; fix matrix + MULi.w VF23, VF31, I NOP ; fix matrix + SUBw.xy VF28, VF28, VF20 NOP ; fix matrix + SUBw.xy VF29, VF29, VF21 NOP ; fix matrix + SUBw.xy VF30, VF30, VF22 NOP ; fix matrix + SUBw.xy VF31, VF31, VF23 NOP ; fix matrix + MUL.xy VF28, VF28, VF01 LQ.xyz VF25, XYZOffset(VI00) ; scale matrix + MUL.xy VF29, VF29, VF01 IADDIU VI12, VI00, outBuf1 ; scale matrix + MUL.xy VF30, VF30, VF01 IADDIU VI13, VI00, outBuf2 ; scale matrix + MUL.xyz VF31, VF31, VF01 NOP ; scale matrix diff --git a/tools/ps2test/vu/skinpipe.dsm b/tools/ps2test/vu/skinpipe.dsm index a3a8122..18536cd 100755 --- a/tools/ps2test/vu/skinpipe.dsm +++ b/tools/ps2test/vu/skinpipe.dsm @@ -11,34 +11,15 @@ .equ outBuf2, (outBuf1+outSize) .equ lightMat, 0x3d0 -.equ lightDir, 0x3d4 +.equ ambientLight, 0x3d4 +.equ lightDir, 0x3d5 + .equ matrix, 0x3f0 .equ XYZScale, 0x3f7 .equ XYZOffset, 0x3f8 .equ gifTag, 0x3fa .equ matColor, 0x3fb -.equ ambientLight, 0x3fd - -/* This is the the projection matrix we start with: - * 1/2w 0 ox/2w + 1/2 -ox/2w - * 0 -1/2h -oy/2h + 1/2 oy/2h - * 0 0 1 0 - * 0 0 1 0 - * To get rid of the +1/2 in the combined matrix we - * subtract the z-row/2 from the x- and y-rows. - * - * The z-row is then set to [0 0 0 1] such that multiplication - * by XYZscale gives [0 0 0 zScale]. After perspective division - * and addition of XYZoffset we then get zScale/w + zShift for z. - * - * XYZScale scales xy to the resolution and z by zScale. - * XYZOffset translates xy to the GS coordinate system (where - * [2048, 2048] is the center of the frame buffer) and add zShift to z. - */ - -; constant: -; VF28-VF31 transformation matrix -; VF25 XYZ offset +.equ surfProps, 0x3fc .balign 16,0 @@ -47,23 +28,7 @@ DMAret * MPG 0, * .vu Start: - SUB.z VF28, VF28, VF28 LOI 0.5 ; right.z = 0 - SUB.z VF29, VF29, VF29 LQ VF28, matrix(VI00) ; up.z = 0 - load matrix - SUB.z VF30, VF30, VF30 LQ VF29, matrix+1(VI00) ; at.z = 0 - load matrix - ADDw.z VF31, VF00, VF00 LQ VF30, matrix+2(VI00) ; at.z = 1 - load matrix - NOP LQ VF31, matrix+3(VI00) ; - load matrix - MULi.w VF20, VF28, I LQ.xyz VF01, XYZScale(VI00) ; fix matrix - load scale - MULi.w VF21, VF29, I NOP ; fix matrix - MULi.w VF22, VF30, I NOP ; fix matrix - MULi.w VF23, VF31, I NOP ; fix matrix - SUBw.xy VF28, VF28, VF20 NOP ; fix matrix - SUBw.xy VF29, VF29, VF21 NOP ; fix matrix - SUBw.xy VF30, VF30, VF22 NOP ; fix matrix - SUBw.xy VF31, VF31, VF23 NOP ; fix matrix - MUL.xy VF28, VF28, VF01 LQ.xyz VF25, XYZOffset(VI00) ; scale matrix - MUL.xy VF29, VF29, VF01 IADDIU VI12, VI00, outBuf1 ; scale matrix - MUL.xy VF30, VF30, VF01 IADDIU VI13, VI00, outBuf2 ; scale matrix - MUL.xyz VF31, VF31, VF01 NOP ; scale matrix +#include "setup_persp.vu" Cnt: NOP XTOP VI02 ; input pointer NOP LQ VF01, gifTag(VI00) diff --git a/tools/ps2test/vu/vu.dsm b/tools/ps2test/vu/vu.dsm deleted file mode 100755 index 58c10d6..0000000 --- a/tools/ps2test/vu/vu.dsm +++ /dev/null @@ -1,98 +0,0 @@ -.data -.global MyDmaPacket -.global vuLightMat -.global vuMat -.global vuXYZScale -.global vuXYZOffset -.global vuOffset -.global vuGIFtag -.global vuMatcolor -.global vuSurfProps -.global vuAmbLight -.global mpgCall -.global textureCall -.global geometryCall - -.align 4 - -MyDmaPacket: -DMAcnt * -.EndDmaData - -mpgCall: -DMAcall *, 0 ;vuProg -.EndDmaData - -/* -#define vuSDLightOffset 0x3d0 -#define vuSDBlockLow 0x3c3 -#define vuSDBlockHigh 0x3f0 -#define vuSDmat0 vuSDBlockHigh -#define vuSDmat1 vuSDBlockHigh+1 -#define vuSDmat2 vuSDBlockHigh+2 -#define vuSDmat3 vuSDBlockHigh+3 -#define vuSDnearClip vuSDBlockHigh+4 -#define vuSDfarClip vuSDBlockHigh+5 -#define vuSDxMaxyMax vuSDBlockHigh+6 -#define vuSDcamWcamHzScale vuSDBlockHigh+7 -#define vuSDoffXoffYzShift vuSDBlockHigh+8 -#define vuSDrealOffset vuSDBlockHigh+9 -#define vuSDgifTag vuSDBlockHigh+10 -#define vuSDcolScale vuSDBlockHigh+11 -#define vuSDsurfProps vuSDBlockHigh+12 -#define vuSDpingPongAddr vuSDBlockHigh+13 -#define vuSDpingPongCount vuSDBlockHigh+14 -#define vuSDClipvec1 vuSDBlockHigh+13 -#define vuSDClipvec2 vuSDBlockHigh+14 -#define vuSDVUSwitch vuSDBlockHigh+15 -*/ - -DMAcnt * - UNPACK 4, 4, V4_32, 0x3d0, * -vuLightMat: - .float 1.0, 0.0, 0.0, 0.0 - .float 0.0, 1.0, 0.0, 0.0 - .float 0.0, 0.0, 1.0, 0.0 - .float 0.0, 0.0, 0.0, 1.0 -lightDir: - .float 0.5, -0.5, -0.70710, 0.0 - .EndUnpack - - UNPACK 4, 4, V4_32, 0x3f0, * -vuMat: - .float 0.0, 0.0, 0.0, 0.0 - .float 0.0, 0.0, 0.0, 0.0 - .float 0.0, 0.0, 0.0, 0.0 - .float 0.0, 0.0, 0.0, 0.0 - .EndUnpack - - UNPACK 4, 4, V4_32, 0x3f7, * -vuXYZScale: - .float 0.0, 0.0, 0.0, 0.0 -vuXYZOffset: - .float 0.0, 0.0, 0.0, 0.0 -vuOffset: - .float 0.0, 0.0, 0.0, 0.0 -vuGIFtag: - .int 0x00008000, 0x3005C000, 0x0000000412, 0x00000000 -vuMatcolor: - .float 1.0, 1.0, 1.0, 0.5 -vuSurfProps: - .float 1.0, 1.0, 1.0, 1.0 -vuAmbLight: - .float 0, 0, 0, 0 - .EndUnpack -.EndDmaData - -;;textureCall: -;;DMAcall *, 0 -;;.EndDmaData - -geometryCall: -DMAcall *, 0 ;vuGeometry - BASE 0 - OFFSET 0x0 -.EndDmaData - -DMAend - From 75435b89348e720bde0b30360a5dbc05f7324d25 Mon Sep 17 00:00:00 2001 From: aap Date: Fri, 18 Aug 2017 19:28:01 +0200 Subject: [PATCH 7/8] mipmap allocation for ps2 rasters --- premake5.lua | 9 + src/base.err | 2 + src/image.cpp | 1 + src/ps2/ps2.cpp | 2 + src/ps2/ps2raster.cpp | 1116 +++++++++++++++++++++++++++++++++-------- src/ps2/rwps2.h | 15 +- src/rwobjects.h | 6 +- 7 files changed, 946 insertions(+), 205 deletions(-) diff --git a/premake5.lua b/premake5.lua index 4708dbb..1074856 100755 --- a/premake5.lua +++ b/premake5.lua @@ -146,3 +146,12 @@ project "ps2test" links { "librw" } -- "c -lc" is a hack because we need -lc twice for some reason links { "c -lc", "kernel", "mf" } + +project "ps2rastertest" + kind "ConsoleApp" + targetdir (Bindir) + removeplatforms { "*gl3", "*d3d9" } + files { "tools/ps2rastertest/*.cpp" } + includedirs { "." } + libdirs { Libdir } + links { "librw" } diff --git a/src/base.err b/src/base.err index a02a9c0..5e06a86 100644 --- a/src/base.err +++ b/src/base.err @@ -16,3 +16,5 @@ ECODE(ERR_ENGINEOPEN, "Engine could not be opened") ECODE(ERR_ENGINESTART, "Engine could not be started") +ECODE(ERR_INVRASTER, + "Invalid raster format") diff --git a/src/image.cpp b/src/image.cpp index 244ff77..45599b1 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -908,6 +908,7 @@ Image::getFilename(const char *name) Raster* Raster::create(int32 width, int32 height, int32 depth, int32 format, int32 platform) { + // TODO: pass arguments through to the driver and create the raster there Raster *raster = (Raster*)malloc(s_plglist.size); assert(raster != nil); raster->platform = platform ? platform : rw::platform; diff --git a/src/ps2/ps2.cpp b/src/ps2/ps2.cpp index bd444b3..1407532 100755 --- a/src/ps2/ps2.cpp +++ b/src/ps2/ps2.cpp @@ -688,8 +688,10 @@ MatPipeline::instance(Geometry *g, InstanceData *inst, Mesh *m) if(this->instanceCB) this->instanceCB(this, g, m, datap); +#ifdef RW_PS2 if(im.numBrokenAttribs) fixDmaOffsets(inst); +#endif } uint8* diff --git a/src/ps2/ps2raster.cpp b/src/ps2/ps2raster.cpp index e69c057..2a9e9fb 100644 --- a/src/ps2/ps2raster.cpp +++ b/src/ps2/ps2raster.cpp @@ -13,6 +13,7 @@ #define PLUGIN_ID 0 +#define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) namespace rw { @@ -23,29 +24,45 @@ int32 nativeRasterOffset; #define MAXLEVEL(r) ((r)->tex1low >> 2) static bool32 noNewStyleRasters; +enum Psm { + PSMCT32 = 0x0, + PSMCT24 = 0x1, + PSMCT16 = 0x2, + PSMCT16S = 0xA, + PSMT8 = 0x13, + PSMT4 = 0x14, + PSMT8H = 0x1B, + PSMT4HL = 0x24, + PSMT4HH = 0x2C, + PSMZ32 = 0x30, + PSMZ24 = 0x31, + PSMZ16 = 0x32, + PSMZ16S = 0x3A, +}; + // 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: + case PSMCT32: + case PSMZ32: *minw = 2; // 32 bit break; - case 0x02: - case 0x0A: - case 0x32: - case 0x3A: + case PSMCT16: + case PSMCT16S: + case PSMZ16: + case PSMZ16S: *minw = 4; // 16 bit break; - case 0x01: - case 0x13: - case 0x14: - case 0x1B: - case 0x24: - case 0x2C: - case 0x31: + case PSMCT24: + case PSMT8: + case PSMT4: + case PSMT8H: + case PSMT4HL: + case PSMT4HH: + case PSMZ24: *minw = 8; // everything else break; } @@ -61,18 +78,7 @@ ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh) #define ALIGN16(x) ((x) + 0xF & ~0xF) #define ALIGN64(x) ((x) + 0x3F & ~0x3F) - -enum Psm { - PSMCT32 = 0x0, - PSMCT24 = 0x1, - PSMCT16 = 0x2, - PSMCT16S = 0xA, - PSMT8 = 0x13, - PSMT4 = 0x14, - PSMT8H = 0x1B, - PSMT4HL = 0x24, - PSMT4HH = 0x2C, -}; +#define NSIZE(dim,pagedim) (((dim) + (pagedim)-1)/(pagedim)) void* mallocalign(size_t size, int32 alignment) @@ -95,106 +101,754 @@ freealign(void *p) free(pp); } -void -rasterCreate(Raster *raster) +// TODO: these depend on video mode, set in deviceSystem! +int32 cameraFormat = Raster::C8888; +int32 cameraDepth = 32; +int32 cameraZDepth = 16; + +int32 defaultMipMapKL = 0xFC0; +int32 maxMipLevels = 7; + +int32 +getRasterFormat(Raster *raster) { + int32 palformat, pixelformat, mipmapflags; + pixelformat = raster->format & 0xF00; + palformat = raster->format & 0x6000; + mipmapflags = raster->format & 0x9000; + switch(raster->type){ + case Raster::ZBUFFER: + if(palformat || mipmapflags){ + RWERROR((ERR_INVRASTER)); + return 0; + } + if(raster->depth && raster->depth != cameraZDepth){ + RWERROR((ERR_INVRASTER)); + return 0; + } + raster->depth = cameraZDepth; + if(pixelformat){ + if(raster->depth == 16 && pixelformat != Raster::D16 || + raster->depth == 32 && pixelformat != Raster::D32){ + RWERROR((ERR_INVRASTER)); + return 0; + } + } + pixelformat = raster->depth == 16 ? Raster::D16 : Raster::D32; + raster->format = pixelformat; + break; + case Raster::CAMERA: + if(palformat || mipmapflags){ + RWERROR((ERR_INVRASTER)); + return 0; + } + if(raster->depth && raster->depth != cameraDepth){ + RWERROR((ERR_INVRASTER)); + return 0; + } + raster->depth = cameraDepth; + if(pixelformat && pixelformat != cameraFormat){ + RWERROR((ERR_INVRASTER)); + return 0; + } + pixelformat = cameraFormat; + raster->format = pixelformat; + break; + case Raster::NORMAL: + case Raster::CAMERATEXTURE: + if(palformat || mipmapflags){ + RWERROR((ERR_INVRASTER)); + return 0; + } + /* fallthrough */ + case Raster::TEXTURE: + // Find raster format by depth if none was given + if(pixelformat == 0) + switch(raster->depth){ + case 4: + pixelformat = Raster::C1555; + palformat = Raster::PAL4; + break; + case 8: + pixelformat = Raster::C1555; + palformat = Raster::PAL8; + break; + case 24: + pixelformat = Raster::C888; + palformat = 0; + break; + case 32: + pixelformat = Raster::C8888; + palformat = 0; + break; + default: + pixelformat = Raster::C1555; + palformat = 0; + break; + } + raster->format = pixelformat | palformat | mipmapflags; + // Sanity check raster format and depth; set depth if none given + if(palformat){ + if(palformat == Raster::PAL8){ + if(raster->depth && raster->depth != 8){ + RWERROR((ERR_INVRASTER)); + return 0; + } + raster->depth = 8; + if(pixelformat != Raster::C1555 && pixelformat != Raster::C8888){ + RWERROR((ERR_INVRASTER)); + return 0; + } + }else if(palformat == Raster::PAL4){ + if(raster->depth && raster->depth != 4){ + RWERROR((ERR_INVRASTER)); + return 0; + } + raster->depth = 4; + if(pixelformat != Raster::C1555 && pixelformat != Raster::C8888){ + RWERROR((ERR_INVRASTER)); + return 0; + } + }else{ + RWERROR((ERR_INVRASTER)); + return 0; + } + }else if(pixelformat == Raster::C1555){ + if(raster->depth && raster->depth != 16){ + RWERROR((ERR_INVRASTER)); + return 0; + } + raster->depth = 16; + }else if(pixelformat == Raster::C8888){ + if(raster->depth && raster->depth != 32){ + RWERROR((ERR_INVRASTER)); + return 0; + } + raster->depth = 32; + }else if(pixelformat == Raster::C888){ + if(raster->depth && raster->depth != 24){ + RWERROR((ERR_INVRASTER)); + return 0; + } + raster->depth = 24; + }else{ + RWERROR((ERR_INVRASTER)); + return 0; + } + break; + default: + RWERROR((ERR_INVRASTER)); + return 0; + } + return 1; +} + +/* + * Memory units: + * Column: 64 bytes (single cycle access) + * Block: 256 bytes, 64 words, 4 columns. texture base pointers + * Page: 8 kbytes, 2 kwords, 128 columns, 32 blocks. frame buffer base pointers + * entire memory: 4 mbytes, 64k columns, 16k blocks, 512 pages + * + * PSMT4: 128x128 pixels, 4x8 blocks per page, 32x16 pixels per block + * PSMT8: 128x64 pixels, 8x4 blocks per page, 16x16 pixels per block + * PSMCT16(S): 64x64 pixels, 4x8 blocks per page, 16x8 pixels per block + * PSMCT24: 64x32 pixels, 8x4 blocks per page, 8x8 pixels per block + * PSMCT32: 64x32 pixels, 8x4 blocks per page, 8x8 pixels per block + * + * Layout of blocks in page: + * + * PSMCT24, PSMCT32, PSMT8 + * +----+----+----+----+----+----+----+----+ + * | 0 | 1 | 4 | 5 | 16 | 17 | 20 | 21 | + * +----+----+----+----+----+----+----+----+ + * | 2 | 3 | 6 | 7 | 18 | 19 | 22 | 23 | + * +----+----+----+----+----+----+----+----+ + * | 8 | 9 | 12 | 13 | 24 | 25 | 28 | 29 | + * +----+----+----+----+----+----+----+----+ + * | 10 | 11 | 14 | 15 | 26 | 27 | 30 | 31 | + * +----+----+----+----+----+----+----+----+ + * + * PSMCT16, PSMT4 + * +----+----+----+----+ + * | 0 | 2 | 8 | 10 | + * +----+----+----+----+ + * | 1 | 3 | 9 | 11 | + * +----+----+----+----+ + * | 4 | 6 | 12 | 14 | + * +----+----+----+----+ + * | 5 | 7 | 13 | 15 | + * +----+----+----+----+ + * | 16 | 18 | 24 | 26 | + * +----+----+----+----+ + * | 17 | 19 | 25 | 27 | + * +----+----+----+----+ + * | 20 | 22 | 28 | 30 | + * +----+----+----+----+ + * | 21 | 23 | 29 | 31 | + * +----+----+----+----+ + * + * PSMCT16S + * +----+----+----+----+ + * | 0 | 2 | 16 | 18 | + * +----+----+----+----+ + * | 1 | 3 | 17 | 19 | + * +----+----+----+----+ + * | 8 | 10 | 24 | 26 | + * +----+----+----+----+ + * | 9 | 11 | 25 | 27 | + * +----+----+----+----+ + * | 4 | 6 | 20 | 22 | + * +----+----+----+----+ + * | 5 | 7 | 21 | 23 | + * +----+----+----+----+ + * | 12 | 14 | 28 | 30 | + * +----+----+----+----+ + * | 13 | 15 | 29 | 31 | + * +----+----+----+----+ + * + */ + +static uint8 blockmap_PSMCT32[32] = { + 0, 1, 4, 5, 16, 17, 20, 21, + 2, 3, 6, 7, 18, 19, 22, 23, + 8, 9, 12, 13, 24, 25, 28, 29, + 10, 11, 14, 15, 26, 27, 30, 31, +}; +static uint8 blockmap_PSMCT16[32] = { + 0, 2, 8, 10, + 1, 3, 9, 11, + 4, 6, 12, 14, + 5, 7, 13, 15, + 16, 18, 24, 26, + 17, 19, 25, 27, + 20, 22, 28, 30, + 21, 23, 29, 31, +}; +static uint8 blockmap_PSMCT16S[32] = { + 0, 2, 16, 18, + 1, 3, 17, 19, + 8, 10, 24, 26, + 9, 11, 25, 27, + 4, 6, 20, 22, + 5, 7, 21, 23, + 12, 14, 28, 30, + 13, 15, 29, 31, +}; +static uint8 blockmap_PSMZ32[32] = { + 24, 25, 28, 29, 8, 9, 12, 13, + 26, 27, 30, 31, 10, 11, 14, 15, + 16, 17, 20, 21, 0, 1, 4, 5, + 18, 19, 22, 23, 2, 3, 6, 7, +}; +static uint8 blockmap_PSMZ16[32] = { + 24, 26, 16, 18, + 25, 27, 17, 19, + 28, 30, 20, 22, + 29, 31, 21, 23, + 8, 10, 0, 2, + 9, 11, 1, 3, + 12, 14, 4, 6, + 13, 15, 5, 7, +}; +static uint8 blockmap_PSMZ16S[32] = { + 24, 26, 8, 10, + 25, 27, 9, 11, + 16, 18, 0, 2, + 17, 19, 1, 3, + 28, 30, 12, 14, + 29, 31, 13, 15, + 20, 22, 4, 6, + 21, 23, 5, 7, +}; + +/* Suffixes used: + * _Px - pixels + * _W - width units (pixels/64) + * _B - blocks + * _P - pages + */ + +/* Layout mipmaps and palette in GS memory */ +static void +calcOffsets(int32 width_Px, int32 height_Px, int32 psm, uint64 *bufferBase_B, uint64 *bufferWidth_W, uint32 *trxpos, uint32 *totalSize, uint32 *paletteBase) +{ + int32 pageWidth_Px, pageHeight_Px; + int32 blockWidth_Px, blockHeight_Px; + int32 mindim_Px; + int32 nlevels; + int32 n; + int32 mipw_Px, miph_Px; + int32 lastmipw_Px, lastmiph_Px; + uint32 bufferHeight_P[8]; + uint32 bufferPage_B[8]; // address of page in which the level is allocated + uint32 xoff_Px, yoff_Px; // x/y offset the last level starts at + // Whenever we allocate horizontally inside a page, + // keep track of the region below it on this stack. + uint32 sp; + uint32 xoffstack_Px[8]; // actually unused... + uint32 widthstack_Px[8]; + uint32 heightstack_Px[8]; + uint32 basestack_B[8]; + int32 flag; + + switch(psm){ + case PSMCT32: + case PSMCT24: + case PSMT8H: + case PSMT4HL: + case PSMT4HH: + case PSMZ32: + case PSMZ24: + pageWidth_Px = 64; + pageHeight_Px = 32; + blockWidth_Px = 8; + blockHeight_Px = 8; + break; + case PSMT8: + pageWidth_Px = 128; + pageHeight_Px = 64; + blockWidth_Px = 16; + blockHeight_Px = 16; + break; + case PSMT4: + pageWidth_Px = 128; + pageHeight_Px = 128; + blockWidth_Px = 32; + blockHeight_Px = 16; + break; + case PSMCT16: + case PSMCT16S: + case PSMZ16: + case PSMZ16S: + default: + pageWidth_Px = 64; + pageHeight_Px = 64; + blockWidth_Px = 16; + blockHeight_Px = 8; + break; + } + + mindim_Px = min(width_Px, height_Px); + for(nlevels = 1; mindim_Px > 8; nlevels++){ + if(nlevels >= maxMipLevels) + break; + mindim_Px /= 2; + } + +#define PAGEWIDTH_B (pageWidth_Px/blockWidth_Px) // number of horizontal blocks per page +#define NBLKX(dim) (NSIZE((dim), blockWidth_Px)) +#define NBLKY(dim) (NSIZE((dim), blockHeight_Px)) +#define NPGX(dim) (NSIZE((dim), pageWidth_Px)) +#define NPGY(dim) (NSIZE((dim), pageHeight_Px)) +#define REALWIDTH(w) (max((w), blockWidth_Px)) +#define REALHEIGHT(w) (max((w), blockHeight_Px)) + + bufferBase_B[0] = 0; + bufferWidth_W[0] = NPGX(width_Px)*pageWidth_Px/64; + bufferHeight_P[0] = NPGY(height_Px); + bufferPage_B[0] = 0; + lastmipw_Px = width_Px; + lastmiph_Px = height_Px; + sp = 0; + xoff_Px = 0; + yoff_Px = 0; + flag = 0; + // Calculate info for all mipmap levels. + // mipwidth/height are actually the dimensions of level n-1! + // This code was reversed from RW and is rather complicated... + // partially because it's not clear what the assumptions are, + // can width/height be non-powers of 2? + for(n = 1; n < nlevels; n++){ + mipw_Px = lastmipw_Px/2; + miph_Px = lastmiph_Px/2; + if(lastmipw_Px >= pageWidth_Px){ + if(lastmiph_Px >= pageHeight_Px){ + // CASE 0 + // We allocate full pages + // This is the only place bufferWidth can change. Similarly bufferBase_2, which is related + bufferBase_B[n] = bufferBase_B[n-1] + (lastmipw_Px/blockWidth_Px)*(lastmiph_Px/blockHeight_Px); + bufferPage_B[n] = bufferBase_B[n]; + bufferWidth_W[n] = NPGX(mipw_Px)*pageWidth_Px/64; + bufferHeight_P[n] = NPGY(miph_Px); + xoff_Px = 0; + yoff_Px = 0; + }else{ + // CASE 1 + // Allocate vertically in the current page + bufferPage_B[n] = bufferPage_B[n-1]; + bufferHeight_P[n] = bufferHeight_P[n-1]; + bufferWidth_W[n] = bufferWidth_W[n-1]; + // How do we know pageHeight - yoff - REALHEIGHT(lastmiph) >= miph? + // And how is this condition ever false? + // Assuming lastmipw >= pageWidth for any number of levels, lastmiph must be pageHeight/2 + // or lower to reach this code. No dimension is lower than 8. Then consequent mipmaps + // will have heights halved but even with PSMT4 we will only (vertically) fill the + // page with the last mipmap and not go beyond... + if(REALHEIGHT(lastmiph_Px) + yoff_Px < pageHeight_Px){ + // CASE 2 + yoff_Px += REALHEIGHT(lastmiph_Px); + bufferBase_B[n] = bufferBase_B[n-1] + + PAGEWIDTH_B * NBLKY(lastmiph_Px) * + bufferWidth_W[n]*64/pageWidth_Px; // number of horizontal pages for level + }else{ + // CASE 3 + // Can this happen? + xoff_Px += REALWIDTH(lastmipw_Px); + bufferBase_B[n] = bufferBase_B[n-1] + NBLKX(lastmipw_Px); + } + } + }else if(lastmiph_Px >= pageHeight_Px){ + // CASE 4 + // Allocate horizontally + bufferPage_B[n] = bufferPage_B[n-1]; + bufferHeight_P[n] = bufferHeight_P[n-1]; + bufferWidth_W[n] = bufferWidth_W[n-1]; + if(REALWIDTH(lastmipw_Px) + xoff_Px < pageWidth_Px){ + // CASE 5 + xoffstack_Px[sp] = xoff_Px; // unused... + heightstack_Px[sp] = REALHEIGHT(lastmiph_Px); + widthstack_Px[sp] = REALWIDTH(lastmipw_Px); + basestack_B[sp] = bufferBase_B[n-1] + NBLKY(lastmiph_Px) * PAGEWIDTH_B; + sp++; + xoff_Px += REALWIDTH(lastmipw_Px); + bufferBase_B[n] = bufferBase_B[n-1] + NBLKX(lastmipw_Px); + }else if(sp){ + // CASE 7 + bufferBase_B[n] = basestack_B[sp-1]; + if(REALWIDTH(mipw_Px) < widthstack_Px[sp-1]){ + // CASE 9 + basestack_B[sp-1] += NBLKX(mipw_Px); + widthstack_Px[sp-1] -= REALWIDTH(mipw_Px); + }else if(REALHEIGHT(miph_Px) < heightstack_Px[sp-1]){ + // CASE 8 + basestack_B[sp-1] += NBLKY(miph_Px) * PAGEWIDTH_B; + heightstack_Px[sp-1] -= REALHEIGHT(miph_Px); + }else{ + // CASE 10 + sp--; + } + flag = 1; + }else{ + // CASE 6 + yoff_Px += REALHEIGHT(lastmiph_Px); + bufferBase_B[n] = bufferBase_B[n-1] + PAGEWIDTH_B*NBLKY(lastmiph_Px); + } + }else{ + // CASE 11 + bufferHeight_P[n] = bufferHeight_P[n-1]; + bufferPage_B[n] = bufferPage_B[n-1]; + bufferWidth_W[n] = bufferWidth_W[n-1]; + if(REALWIDTH(lastmipw_Px) + xoff_Px < bufferWidth_W[n-1]*64){ + // CASE 12 + xoffstack_Px[sp] = xoff_Px; // unused... + widthstack_Px[sp] = REALWIDTH(lastmipw_Px); + heightstack_Px[sp] = REALHEIGHT(lastmiph_Px); + basestack_B[sp] = bufferBase_B[n-1] + PAGEWIDTH_B * NBLKY(lastmiph_Px); + sp++; + xoff_Px += REALWIDTH(lastmipw_Px); + bufferBase_B[n] = bufferBase_B[n-1] + NBLKX(lastmipw_Px); + }else if(REALHEIGHT(lastmiph_Px) + yoff_Px < pageHeight_Px*bufferHeight_P[n] && flag == 0){ + // CASE 13 + bufferBase_B[n] = bufferBase_B[n-1] + PAGEWIDTH_B * NBLKY(lastmiph_Px); + yoff_Px += blockHeight_Px ? lastmiph_Px : 0; // how exactly can blockHeight be 0?? This looks wrong... + flag = n; + }else{ + // CASE 14 + bufferBase_B[n] = basestack_B[sp-1]; + if(REALWIDTH(mipw_Px) < widthstack_Px[sp-1]){ + // CASE 15 + basestack_B[sp-1] += NBLKX(mipw_Px); + widthstack_Px[sp-1] -= REALWIDTH(mipw_Px); + }else if(REALHEIGHT(miph_Px) < heightstack_Px[sp-1]){ + // CASE 16 + basestack_B[sp-1] += PAGEWIDTH_B * NBLKY(miph_Px); + heightstack_Px[sp-1] -= REALHEIGHT(miph_Px); + }else{ + // CASE 17 + sp--; + } + } + } + lastmipw_Px = mipw_Px; + lastmiph_Px = miph_Px; + } + + // Calculate position of palette. + uint32 paletteBase_B = 0; + uint64 bufwidth_Px = bufferWidth_W[nlevels-1]*64; + uint64 bufheight_Px = bufferHeight_P[nlevels-1]*pageHeight_Px; + // != means > really + if(bufwidth_Px != lastmipw_Px || bufheight_Px != lastmiph_Px){ + if(psm == PSMT8){ + // 2x2 blocks at the end of the page (even for PSMCT16S) + paletteBase_B = bufferPage_B[nlevels-1] + + ((bufwidth_Px/pageWidth_Px)*bufferHeight_P[nlevels-1] << 5) // total number of blocks + - (bufheight_Px/pageWidth_Px) * PAGEWIDTH_B // one block up + - 2; // two blocks left + }else if(psm == PSMT4){ + // One block at the end of the page + paletteBase_B = bufferPage_B[nlevels-1] + + ((bufwidth_Px/pageWidth_Px) * bufferHeight_P[nlevels-1] << 5) + - 1; + } + }else{ + if(psm == PSMT8 || psm == PSMT4){ + paletteBase_B = bufferPage_B[nlevels-1] + + (bufwidth_Px/blockWidth_Px) * (bufheight_Px/blockHeight_Px); + } + } + + uint32 bufwidth_W = bufferWidth_W[0]; + uint32 bufpage_B = bufferPage_B[0]; + uint32 pixeloff; + for(n = 0; n < nlevels; n++){ + // Calculate TRXPOS register + // Start of buffer on current page (x in pixels, y in blocks) + pixeloff = (bufferBase_B[n] - bufpage_B) * blockWidth_Px; + // y coordinate of first pixel + yoff_Px = (pixeloff / (bufwidth_W*64)) * blockHeight_Px; + // x coordinate of first pixel + xoff_Px = pixeloff % (bufwidth_W*64); + if(bufferWidth_W[n] == bufwidth_W && + // Not quite sure what's the meaning of this. + // SSAY is 11 bits, but so is SSAX and it is not checked? + yoff_Px < 0x800){ + trxpos[n] = yoff_Px<<16 | xoff_Px; + }else{ + bufwidth_W = bufferWidth_W[n]; + bufpage_B = bufferPage_B[n]; + trxpos[n] = 0; + } + + // If using more than one page we have to swizzle rows inside page rows + if(bufwidth_W*64 / pageWidth_Px > 1){ + uint32 bufpagestride_B = bufwidth_W*64 * 32 / pageWidth_Px; // one row of pages + uint32 bufwidth_B = bufwidth_W*64 / blockWidth_Px; // one row of blocks + // To illustrate assume: + // - 8x4 block pages + // - texture is 4 pages wide + // Then the lower bits of an input block address look like: RRRPPCC + // where the C bits are the block's column inside a page + // the P bits are the block's page horizontally + // the R bits are the block's row in a row of pages + // We want to swap P and R: PPRRRCC + bufferBase_B[n] = + (bufferBase_B[n] & ~(bufpagestride_B - PAGEWIDTH_B)) // mask out R and P + | ((bufferBase_B[n] & (bufwidth_B - PAGEWIDTH_B)) * (bufpagestride_B/bufwidth_B)) // extract P and shift left + | ((bufferBase_B[n] & (bufpagestride_B - bufwidth_B)) / (bufwidth_B/PAGEWIDTH_B)); // extract R and shift right + } + + // Always have to swizzle blocks inside pages. We use a lookup, RW does bit operations + switch(psm){ + case PSMCT32: + case PSMCT24: + case PSMT8: + case PSMT8H: + case PSMT4HL: + case PSMT4HH: + // ABCDE -> CADBE + bufferBase_B[n] = bufferBase_B[n]&~0x1F | (uint64)blockmap_PSMCT32[bufferBase_B[n]&0x1F]; + break; + case PSMT4: + case PSMCT16: + // ABCDE -> ADBEC + bufferBase_B[n] = bufferBase_B[n]&~0x1F | (uint64)blockmap_PSMCT16[bufferBase_B[n]&0x1F]; + break; + case PSMCT16S: + // ABCDE -> DBAEC + bufferBase_B[n] = bufferBase_B[n]&~0x1F | (uint64)blockmap_PSMCT16S[bufferBase_B[n]&0x1F]; + break; + case PSMZ32: + case PSMZ24: + // ABCDE -> ~C~ADBE + bufferBase_B[n] = bufferBase_B[n]&~0x1F | (uint64)blockmap_PSMZ32[bufferBase_B[n]&0x1F]; + break; + case PSMZ16: + // ABCDE -> ~A~DBEC + bufferBase_B[n] = bufferBase_B[n]&~0x1F | (uint64)blockmap_PSMZ16[bufferBase_B[n]&0x1F]; + break; + case PSMZ16S: + // ABCDE -> ~D~BAEC + bufferBase_B[n] = bufferBase_B[n]&~0x1F | (uint64)blockmap_PSMZ16S[bufferBase_B[n]&0x1F]; + break; + default: break; + } + } + + // Same dance as above, with the palette + if(bufwidth_W*64 / pageWidth_Px > 1){ + uint32 bufpagestride_B = bufwidth_W*64 * 32 / pageWidth_Px; // one row of pages + uint32 bufwidth_B = bufwidth_W*64 / blockWidth_Px; // one row of blocks + paletteBase_B = + (paletteBase_B & ~(bufpagestride_B - PAGEWIDTH_B)) // mask out R and P + | ((paletteBase_B & (bufwidth_B - PAGEWIDTH_B)) * (bufpagestride_B/bufwidth_B)) // extract P and shift left + | ((paletteBase_B & (bufpagestride_B - bufwidth_B)) / (bufwidth_B/PAGEWIDTH_B)); // extract R and shift right + } + switch(psm){ + case PSMCT32: + case PSMCT24: + case PSMT8: + case PSMT8H: + case PSMT4HL: + case PSMT4HH: + paletteBase_B = paletteBase_B&~0x1F | (uint64)blockmap_PSMCT32[paletteBase_B&0x1F]; + break; + case PSMT4: + case PSMCT16: + paletteBase_B = paletteBase_B&~0x1F | (uint64)blockmap_PSMCT16[paletteBase_B&0x1F]; + break; + case PSMCT16S: + paletteBase_B = paletteBase_B&~0x1F | (uint64)blockmap_PSMCT16S[paletteBase_B&0x1F]; + break; + case PSMZ32: + case PSMZ24: + paletteBase_B = paletteBase_B&~0x1F | (uint64)blockmap_PSMZ32[paletteBase_B&0x1F]; + break; + case PSMZ16: + paletteBase_B = paletteBase_B&~0x1F | (uint64)blockmap_PSMZ16[paletteBase_B&0x1F]; + break; + case PSMZ16S: + paletteBase_B = paletteBase_B&~0x1F | (uint64)blockmap_PSMZ16S[paletteBase_B&0x1F]; + break; + default: break; + } + *paletteBase = paletteBase_B; + *totalSize = bufferPage_B[nlevels-1] + // start of last buffer` + bufferWidth_W[nlevels-1]*64/blockWidth_Px * // number of horizontal blocks in last level + pageHeight_Px*bufferHeight_P[nlevels-1]/blockHeight_Px; // number of vertical blocks in last level + *totalSize *= 64; // to words + +#undef BLKSTRIDE +#undef NBLKX +#undef NBLKY +#undef NPGX +#undef NPGY +#undef REALWIDTH +#undef REALHEIGHT +} + +static void +createTexRaster(Raster *raster) +{ + // We use a map for fast lookup, even for impossible depths + static int32 pageWidths[32] = { + 128, 128, 128, 128, + 128, 128, 128, 128, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }; + static int32 pageHeights[32] = { + 128, 128, 128, 128, + 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + }; enum { TCC_RGBA = 1 << 2, CLD_1 = 1 << 29, - }; - uint64 bufferWidth[7], bufferBase[7]; - int32 pageWidth, pageHeight; - Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset); + WD2BLK = 64, // words per block + WD2PG = 2048, // words per page + }; + int32 pixelformat, palformat; + // TEX0 fields (not all) + int64 tbw = 0; // texture buffer width, texels/64 + int64 psm = 0; // pixel storage mode + int64 tw = 0; // texture width exponent, width = 2^tw + int64 th = 0; // texture height exponent, height = 2^th + int64 tcc = 0; // texture color component, 0 = rgb, 1 = rgba + int64 cpsm = 0; // CLUT pixel storage mode + int64 cld = 0; // CLUT buffer load control + + uint64 bufferWidth[7]; // in number of pixels / 64 + uint64 bufferBase[7]; // block address + uint32 trxpos[8]; + int32 width, height, depth; + int32 pageWidth, pageHeight; + int32 paletteWidth, paletteHeight, paletteDepth; + int32 palettePagewidth, palettePageheight; + + + Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset); + pixelformat = raster->format & 0xF00; + palformat = raster->format & 0x6000; + width = raster->width; + height = raster->height; + depth = raster->depth; + + + // RW doesn't seem to check this, hm... if(raster->flags & Raster::DONTALLOCATE) return; //printf("%x %x %x %x\n", raster->format, raster->flags, raster->type, noNewStyleRasters); - assert(raster->type == Raster::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; + pageWidth = pageWidths[depth-1]; + pageHeight = pageHeights[depth-1]; + int32 s; - for(s = 1; s < raster->width; s *= 2) - logw++; - for(s = 1; s < raster->height; s *= 2) - logh++; - ras->kl = 0xFC0; + tw = 0; + for(s = 1; s < width; s *= 2) + tw++; + th = 0; + for(s = 1; s < height; s *= 2) + th++; + ras->kl = defaultMipMapKL; + // unk2[0] = 1 //printf("%d %d %d %d\n", raster->width, logw, raster->height, logh); // round up to page width, set TBW, TW, TH - 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; + tbw = max(width,pageWidth)/64; // set PSM, TCC, CLD, CPSM and figure out palette format - int32 paletteWidth, paletteHeight, paletteDepth; - int32 palettePagewidth, palettePageheight; - if(raster->format & (Raster::PAL4 | Raster::PAL8)) - switch(raster->format & 0xF00){ - case Raster::C1555: - ras->tex0[1] |= PSMCT16S << 19; + if(palformat){ + if(palformat == Raster::PAL8){ + psm = PSMT8; + paletteWidth = 16; + paletteHeight = 16; + }else if(palformat == Raster::PAL4){ + psm = PSMT4; + paletteWidth = 8; + paletteHeight = 2; + }else{ + // can't happen, sanity check in getRasterFormat + return; + } + tcc = 1; // RGBA + cld = 1; + if(pixelformat == Raster::C1555){ paletteDepth = 2; - palettePagewidth = palettePageheight = 64; - break; - case Raster::C8888: - ras->tex0[1] |= PSMCT32 << 19; + cpsm = PSMCT16S; + palettePagewidth = 64; + palettePageheight = 64; + }else if(pixelformat == Raster::C8888){ paletteDepth = 4; + cpsm = PSMCT32; palettePagewidth = 64; palettePageheight = 32; - break; - default: - assert(0 && "unsupported palette format\n"); - } - if(raster->format & Raster::PAL4){ - ras->tex0[0] |= PSMT4 << 20; - ras->tex0[1] |= CLD_1 | TCC_RGBA; - paletteWidth = 8; - paletteHeight = 2; - }else if(raster->format & Raster::PAL8){ - ras->tex0[0] |= PSMT8 << 20; - ras->tex0[1] |= CLD_1 | TCC_RGBA; - paletteWidth = paletteHeight = 16; + }else + // can't happen, sanity check in getRasterFormat + return; }else{ paletteWidth = 0; paletteHeight = 0; paletteDepth = 0; palettePagewidth = 0; palettePageheight = 0; - switch(raster->format & 0xF00){ - case Raster::C1555: - ras->tex0[0] |= PSMCT16S << 20; - ras->tex0[1] |= TCC_RGBA; - break; - case Raster::C8888: - ras->tex0[0] |= PSMCT32 << 20; - ras->tex0[1] |= TCC_RGBA; - break; - case Raster::C888: - ras->tex0[0] |= PSMCT24 << 20; - break; - default: - assert(0 && "unsupported raster format\n"); - } + if(pixelformat == Raster::C8888){ + psm = PSMCT32; + tcc = 1; // RGBA + }else if(pixelformat == Raster::C888){ + psm = PSMCT24; + tcc = 0; // RGB + }else if(pixelformat == Raster::C1555){ + psm = PSMCT16S; + tcc = 1; // RGBA + }else + // can't happen, sanity check in getRasterFormat + return; } for(int i = 0; i < 7; i++){ @@ -203,120 +857,164 @@ rasterCreate(Raster *raster) } int32 mipw, miph; + int32 w, h; int32 n; int32 nPagW, nPagH; - int32 w = raster->width; - int32 h = raster->height; - int32 d = raster->depth; - raster->stride = w*d/8; + raster->stride = width*depth/8; if(raster->format & Raster::MIPMAP){ + // NOTE: much of this code seems to be totally useless. + // calcOffsets overwrites what we calculate here. I wonder + // why this code even is in RW. Maybe it's older code that used + // the GS' automatic base pointer calculation? + + // see the left columns in the maps above 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)) + mipw = width; + miph = height; + lastBufferWidth = max(pageWidth, width)/64; + ras->pixelSize = 0; + int32 lastaddress = 0; // word address + int32 nextaddress = 0; // word address + int32 stride; // in bytes + for(n = 0; mipw != 0 && miph != 0 && n < maxMipLevels; n++){ + if(width >= 8 && height >= 8 && (mipw < 8 || miph < 8)) break; - ras->texelSize += ALIGN64(mipw*miph*d/8); + ras->pixelSize += ALIGN64(mipw*miph*depth/8); bufferWidth[n] = max(pageWidth, mipw)/64; + stride = bufferWidth[n]*64*depth/8; + // If buffer width changes, align next address to page if(bufferWidth[n] != lastBufferWidth){ - nPagW = ((w >> n-1) + pageWidth-1)/pageWidth; - nPagH = ((h >> n-1) + pageHeight-1)/pageHeight; - gsaddress = (gsoffset + nPagW*nPagH*0x800) & ~0x7FF; + nPagW = ((width >> n-1) + pageWidth-1)/pageWidth; + nPagH = ((height >> n-1) + pageHeight-1)/pageHeight; + nextaddress = (lastaddress + nPagW*nPagH*WD2PG) & ~(WD2PG-1); } lastBufferWidth = bufferWidth[n]; - gsaddress = ALIGN64(gsaddress); - uint32 b = gsaddress/256 & 7; - switch(ras->tex0[0]>>20 & 0x3F){ - case 0: case 1: case 0x13: + nextaddress = ALIGN64(nextaddress); // this should already be the case... + uint32 b = nextaddress>>(11-3) & 7; // upper three bits of block-in-page address + switch(psm){ + case PSMCT32: + case PSMCT24: + case PSMT8: b = blockOffset32_24_8[b]; break; - case 2: case 0x14: + case PSMCT16: + case PSMT4: b = blockOffset16_4[b]; break; - case 0xA: + case PSMCT16S: 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); + // shift to page address, then to block address and add offset inside page + bufferBase[n] = b + (nextaddress>>11 << 5); + + lastaddress = nextaddress; + nextaddress = ALIGN64(miph*stride/4 + lastaddress); mipw /= 2; miph /= 2; } - assert(0); + + // Do the real work here + uint32 paletteBase; + uint32 totalSize; + calcOffsets(width, height, psm, bufferBase, bufferWidth, trxpos, &totalSize, &paletteBase); + + ras->paletteSize = paletteWidth*paletteHeight*paletteDepth; + ras->miptbp1 = + bufferWidth[1]<<14 | (bufferBase[1] & 0x3FFF)<<0 + | bufferWidth[2]<<34 | (bufferBase[2] & 0x3FFF)<<20 + | bufferWidth[3]<<54 | (bufferBase[3] & 0x3FFF)<<40; + ras->miptbp2 = + bufferWidth[4]<<14 | (bufferBase[4] & 0x3FFF)<<0 + | bufferWidth[5]<<34 | (bufferBase[5] & 0x3FFF)<<20 + | bufferWidth[6]<<54 | (bufferBase[6] & 0x3FFF)<<40; + ras->tex1low = (n-1)<<2; + ras->totalSize = totalSize; + if(ras->paletteSize){ + ras->paletteBase = paletteBase; + if(ras->paletteBase*64 == ras->totalSize) + ras->totalSize += WD2PG; + }else + ras->paletteBase = 0; }else{ // No mipmaps - ras->texelSize = ALIGN16(raster->stride*raster->height); + ras->pixelSize = ALIGN16(raster->stride*raster->height); 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 + ras->miptbp1 = 1<<54 | 1<<34 | 1<<14; + ras->miptbp2 = 1<<54 | 1<<34 | 1<<14; ras->tex1low = 0; // one mipmap level // find out number of pages needed - nPagW = (raster->width + pageWidth-1)/pageWidth; - nPagH = (raster->height + pageHeight-1)/pageHeight; + nPagW = (width + pageWidth-1)/pageWidth; + nPagH = (height + pageHeight-1)/pageHeight; // calculate buffer width in units of pixels/64 bufferBase[0] = 0; bufferWidth[0] = nPagW*pageWidth / 64; // calculate whole buffer size in words - ras->gsSize = nPagW*nPagH*0x800; + ras->totalSize = nPagW*nPagH*WD2PG; // calculate palette offset on GS in units of words/64 if(ras->paletteSize){ - // Maximum palette size will be 256 words. + // Maximum palette size is 256 words. // If there is still room, use it! - // TODO: find out why this check works - if(pageWidth*nPagW > raster->width || - pageHeight*nPagH > raster->height) - ras->paletteOffset = (ras->gsSize - 256)/ 64; + // If dimensions don't fill a page, we have at least + // half a page left, enough for any palette + if(pageWidth*nPagW > width || + pageHeight*nPagH > height) + ras->paletteBase = (ras->totalSize - 256) / WD2BLK; else{ // Otherwise allocate more space... - ras->paletteOffset = ras->gsSize / 64; - // ...using the same calculation as above + ras->paletteBase = ras->totalSize / WD2BLK; + // ...using the same calculation as above. + // WHY? we never need more than one page! nPagW = (paletteWidth + palettePagewidth-1)/palettePagewidth; nPagH = (paletteHeight + palettePageheight-1)/palettePageheight; - ras->gsSize += nPagW*nPagH*0x800; + ras->totalSize += nPagW*nPagH*WD2PG; } }else - ras->paletteOffset = 0; + ras->paletteBase = 0; } + ras->tex0 = tbw << 14 | + psm << 20 | + tw << 26 | + th << 30 | + tcc << 34 | + cpsm << 51 | + 0 << 55 | // csm0 + 0 << 56 | // entry offset + cld << 61; + + // allocate data and fill with GIF packets - ras->texelSize = ALIGN16(ras->texelSize); + ras->pixelSize = ALIGN16(ras->pixelSize); int32 numLevels = MAXLEVEL(ras)+1; // No GIF packet because we either don't want it (pre 0x310 rasters) // or the data wouldn't fit into a DMA packet if(noNewStyleRasters || (raster->width*raster->height*raster->depth/8/0x10) >= 0x7FFF){ - ras->dataSize = ras->paletteSize+ras->texelSize; + ras->dataSize = ras->paletteSize+ras->pixelSize; uint8 *data = (uint8*)mallocalign(ras->dataSize, 0x40); ras->data = data; raster->texels = data; if(ras->paletteSize) - raster->palette = data + ras->texelSize; + raster->palette = data + ras->pixelSize; if(raster->depth == 8) ras->flags |= Ps2Raster::SWIZZLED8; }else{ ras->flags |= Ps2Raster::HASGIFPACKETS; - int32 psm = ras->tex0[0]>>20 & 0x3F; //int32 cpsm = ras->tex0[1]>>19 & 0x3F; if(psm == PSMT8){ ras->flags |= Ps2Raster::SWIZZLED8; @@ -329,7 +1027,7 @@ rasterCreate(Raster *raster) ras->flags |= Ps2Raster::SWIZZLED4; // TODO: crazy stuff } - ras->texelSize = 0x50*numLevels; // GIF packets + ras->pixelSize = 0x50*numLevels; // GIF packets int32 minW, minH; ps2MinSize(psm, ras->flags, &minW, &minH); w = raster->width; @@ -338,7 +1036,7 @@ rasterCreate(Raster *raster) while(n--){ mipw = w < minW ? minW : w; miph = h < minH ? minH : h; - ras->texelSize += ALIGN16(mipw*miph*raster->depth/8); + ras->pixelSize += ALIGN16(mipw*miph*raster->depth/8); w /= 2; h /= 2; } @@ -354,13 +1052,13 @@ rasterCreate(Raster *raster) // GIF tag A+D // BITBLTBUF // DMAref(pixel data) [NOP, DIRECT] - ras->dataSize = ras->paletteSize+ras->texelSize; + ras->dataSize = ras->paletteSize+ras->pixelSize; uint8 *data = (uint8*)mallocalign(ras->dataSize, 0x40); assert(data); ras->data = data; raster->texels = data + 0x50; if(ras->paletteSize) - raster->palette = data + ras->texelSize + 0x50; + raster->palette = data + ras->pixelSize + 0x50; uint32 *p = (uint32*)data; w = raster->width; h = raster->height; @@ -446,6 +1144,44 @@ rasterCreate(Raster *raster) } } +void +rasterCreate(Raster *raster) +{ + if(!getRasterFormat(raster)) + return; + + // init raster + if(raster->width == 0 || raster->height == 0){ + raster->flags = Raster::DONTALLOCATE; + raster->stride = 0; + return; + } + + switch(raster->type){ + case Raster::NORMAL: + // TODO + break; + case Raster::ZBUFFER: + // TODO. only RW_PS2 + // get info from video mode + raster->flags = Raster::DONTALLOCATE; + break; + case Raster::CAMERA: + // TODO. only RW_PS2 + // get info from video mode + raster->flags = Raster::DONTALLOCATE; + break; + case Raster::TEXTURE: + createTexRaster(raster); + break; + case Raster::CAMERATEXTURE: + // TODO. only RW_PS2 + // check wdith/height and fall through to texture + break; + } + +} + uint8* rasterLock(Raster *raster, int32 level) { @@ -477,19 +1213,16 @@ static void* createNativeRaster(void *object, int32 offset, int32) { Ps2Raster *raster = PLUGINOFFSET(Ps2Raster, object, offset); - raster->tex0[0] = 0; - raster->tex0[1] = 0; - raster->paletteOffset = 0; + raster->tex0 = 0; + raster->paletteBase = 0; raster->kl = 0xFC0; raster->tex1low = 0; raster->unk2 = 0; - raster->miptbp1[0] = 0; - raster->miptbp1[1] = 0; - raster->miptbp2[0] = 0; - raster->miptbp2[1] = 0; - raster->texelSize = 0; + raster->miptbp1 = 0; + raster->miptbp2 = 0; + raster->pixelSize = 0; raster->paletteSize = 0; - raster->gsSize = 0; + raster->totalSize = 0; raster->flags = 0; raster->dataSize = 0; @@ -644,14 +1377,14 @@ struct StreamRasterExt int32 depth; uint16 rasterFormat; int16 type; - uint32 tex0[2]; + uint64 tex0; uint32 paletteOffset; uint32 tex1low; - uint32 miptbp1[2]; - uint32 miptbp2[2]; - uint32 texelSize; + uint64 miptbp1; + uint64 miptbp2; + uint32 pixelSize; uint32 paletteSize; - uint32 gsSize; + uint32 totalSize; uint32 mipmapVal; }; @@ -700,23 +1433,20 @@ readNativeTexture(Stream *stream) goto fail; } stream->read(&streamExt, 0x40); -printf("%X %X %X %X %X %08X%08X %X %X %08X%08X %08X%08X %X %X %X %X\n", +printf("%X %X %X %X %X %016llX %X %X %016llX %016llX %X %X %X %X\n", streamExt.width, streamExt.height, streamExt.depth, streamExt.rasterFormat, streamExt.type, -streamExt.tex0[1], -streamExt.tex0[0], +streamExt.tex0, streamExt.paletteOffset, streamExt.tex1low, -streamExt.miptbp1[1], -streamExt.miptbp1[0], -streamExt.miptbp2[1], -streamExt.miptbp2[0], -streamExt.texelSize, +streamExt.miptbp1, +streamExt.miptbp2, +streamExt.pixelSize, streamExt.paletteSize, -streamExt.gsSize, +streamExt.totalSize, streamExt.mipmapVal); noNewStyleRasters = streamExt.type < 2; @@ -737,17 +1467,14 @@ streamExt.mipmapVal); calcTEX1(raster, &tex1, tex->filterAddressing & 0xF); // printTEX1(tex1); - natras->tex0[0] = streamExt.tex0[0]; - natras->tex0[1] = streamExt.tex0[1]; - natras->paletteOffset = streamExt.paletteOffset; + natras->tex0 = streamExt.tex0; + natras->paletteBase = streamExt.paletteOffset; natras->tex1low = streamExt.tex1low; - natras->miptbp1[0] = streamExt.miptbp1[0]; - natras->miptbp1[1] = streamExt.miptbp1[1]; - natras->miptbp2[0] = streamExt.miptbp2[0]; - natras->miptbp2[1] = streamExt.miptbp2[1]; - natras->texelSize = streamExt.texelSize; + natras->miptbp1 = streamExt.miptbp1; + natras->miptbp2 = streamExt.miptbp2; + natras->pixelSize = streamExt.pixelSize; natras->paletteSize = streamExt.paletteSize; - natras->gsSize = streamExt.gsSize; + natras->totalSize = streamExt.totalSize; natras->kl = streamExt.mipmapVal; //printf("%X %X\n", natras->paletteOffset, natras->tex1low); // printf("%08X%08X %08X%08X %08X%08X\n", @@ -764,7 +1491,7 @@ streamExt.mipmapVal); if(streamExt.type < 2){ stream->read(raster->texels, length); }else{ - stream->read(raster->texels-0x50, natras->texelSize); + stream->read(raster->texels-0x50, natras->pixelSize); stream->read(raster->palette-0x50, natras->paletteSize); } //printf("\n"); @@ -790,7 +1517,7 @@ writeNativeTexture(Texture *tex, Stream *stream) writeChunkHeader(stream, ID_STRING, len); stream->write(tex->mask, len); - int32 sz = ras->texelSize + ras->paletteSize; + int32 sz = ras->pixelSize + ras->paletteSize; writeChunkHeader(stream, ID_STRUCT, 12 + 64 + 12 + sz); writeChunkHeader(stream, ID_STRUCT, 64); StreamRasterExt streamExt; @@ -803,17 +1530,14 @@ writeNativeTexture(Texture *tex, Stream *stream) streamExt.type = 1; if(ras->flags & Ps2Raster::HASGIFPACKETS) streamExt.type = 2; - streamExt.tex0[0] = ras->tex0[0]; - streamExt.tex0[1] = ras->tex0[1]; - streamExt.paletteOffset = ras->paletteOffset; + streamExt.tex0 = ras->tex0; + streamExt.paletteOffset = ras->paletteBase; streamExt.tex1low = ras->tex1low; - 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.miptbp1 = ras->miptbp1; + streamExt.miptbp2 = ras->miptbp2; + streamExt.pixelSize = ras->pixelSize; streamExt.paletteSize = ras->paletteSize; - streamExt.gsSize = ras->gsSize; + streamExt.totalSize = ras->totalSize; streamExt.mipmapVal = ras->kl; stream->write(&streamExt, 64); @@ -821,7 +1545,7 @@ writeNativeTexture(Texture *tex, Stream *stream) if(streamExt.type < 2){ stream->write(raster->texels, sz); }else{ - stream->write(raster->texels-0x50, ras->texelSize); + stream->write(raster->texels-0x50, ras->pixelSize); stream->write(raster->palette-0x50, ras->paletteSize); } } @@ -835,7 +1559,7 @@ getSizeNativeTexture(Texture *tex) size += 12; size += 12 + 64; Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, tex->raster, nativeRasterOffset); - size += 12 + ras->texelSize + ras->paletteSize; + size += 12 + ras->pixelSize + ras->paletteSize; return size; } diff --git a/src/ps2/rwps2.h b/src/ps2/rwps2.h index 57f7efc..ca75940 100755 --- a/src/ps2/rwps2.h +++ b/src/ps2/rwps2.h @@ -188,17 +188,16 @@ struct Ps2Raster SWIZZLED4 = 0x4, }; - uint32 tex0[2]; - uint32 paletteOffset; // from beginning of GS data; - // in words/64 + uint64 tex0; + uint32 paletteBase; // block address from beginning of GS data (words/64) uint16 kl; uint8 tex1low; // MXL and LCM of TEX1 uint8 unk2; - uint32 miptbp1[2]; - uint32 miptbp2[2]; - uint32 texelSize; - uint32 paletteSize; - uint32 gsSize; + uint64 miptbp1; + uint64 miptbp2; + uint32 pixelSize; // in bytes + uint32 paletteSize; // in bytes + uint32 totalSize; // total size of texture on GS in words int8 flags; uint8 *data; //tmp diff --git a/src/rwobjects.h b/src/rwobjects.h index 421a823..0a4c336 100755 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -221,13 +221,17 @@ struct Raster PLUGINBASE int32 platform; - int32 type; // hardly used + // TODO: use bytes + int32 type; int32 flags; int32 format; int32 width, height, depth; int32 stride; uint8 *texels; uint8 *palette; + // TODO: + // original pixels, width, height, stride (used for locking) + // parent raster and offset static Raster *create(int32 width, int32 height, int32 depth, int32 format, int32 platform = 0); From 8e277cbe9cadd3d082dbbf0a4cc64a56ec9448b5 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 19 Aug 2017 23:09:45 +0200 Subject: [PATCH 8/8] ps2 raster creation basically done --- src/gl/wdgl.cpp | 2 +- src/image.cpp | 2 +- src/ps2/ps2raster.cpp | 320 +++++++++++++++++++++++++++++++----------- src/ps2/rwps2.h | 15 +- src/rwobjects.h | 8 +- 5 files changed, 261 insertions(+), 86 deletions(-) diff --git a/src/gl/wdgl.cpp b/src/gl/wdgl.cpp index 123c7d5..cd4def3 100644 --- a/src/gl/wdgl.cpp +++ b/src/gl/wdgl.cpp @@ -820,7 +820,7 @@ Texture::upload(void) switch(r->format & 0xF00){ case Raster::C8888: glTexImage2D(GL_TEXTURE_2D, 0, 4, r->width, r->height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, r->texels); + 0, GL_RGBA, GL_UNSIGNED_BYTE, r->pixels); break; default: printf("unsupported raster format: %x\n", r->format); diff --git a/src/image.cpp b/src/image.cpp index 45599b1..e32606e 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -918,7 +918,7 @@ Raster::create(int32 width, int32 height, int32 depth, int32 format, int32 platf raster->width = width; raster->height = height; raster->depth = depth; - raster->texels = raster->palette = nil; + raster->pixels = raster->palette = nil; s_plglist.construct(raster); // printf("%d %d %d %d\n", raster->type, raster->width, raster->height, raster->depth); diff --git a/src/ps2/ps2raster.cpp b/src/ps2/ps2raster.cpp index 2a9e9fb..292e7a8 100644 --- a/src/ps2/ps2raster.cpp +++ b/src/ps2/ps2raster.cpp @@ -42,7 +42,7 @@ enum Psm { // i don't really understand this, stolen from RW static void -ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh) +transferMinSize(int32 psm, int32 flags, int32 *minw, int32 *minh) { *minh = 1; switch(psm){ @@ -66,16 +66,17 @@ ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh) *minw = 8; // everything else break; } - if(flags & 0x2 && psm == 0x13){ // PSMT8 + if(flags & 0x2 && psm == PSMT8){ *minw = 16; *minh = 4; } - if(flags & 0x4 && psm == 0x14){ // PSMT4 + if(flags & 0x4 && psm == PSMT4){ *minw = 32; *minh = 4; } } +#define ALIGN(x,a) ((x) + (a)-1 & ~((a)-1)) #define ALIGN16(x) ((x) + 0xF & ~0xF) #define ALIGN64(x) ((x) + 0x3F & ~0x3F) #define NSIZE(dim,pagedim) (((dim) + (pagedim)-1)/(pagedim)) @@ -310,56 +311,73 @@ getRasterFormat(Raster *raster) */ static uint8 blockmap_PSMCT32[32] = { - 0, 1, 4, 5, 16, 17, 20, 21, - 2, 3, 6, 7, 18, 19, 22, 23, - 8, 9, 12, 13, 24, 25, 28, 29, - 10, 11, 14, 15, 26, 27, 30, 31, + 0, 1, 4, 5, 16, 17, 20, 21, + 2, 3, 6, 7, 18, 19, 22, 23, + 8, 9, 12, 13, 24, 25, 28, 29, + 10, 11, 14, 15, 26, 27, 30, 31, }; static uint8 blockmap_PSMCT16[32] = { - 0, 2, 8, 10, - 1, 3, 9, 11, - 4, 6, 12, 14, - 5, 7, 13, 15, - 16, 18, 24, 26, - 17, 19, 25, 27, - 20, 22, 28, 30, - 21, 23, 29, 31, + 0, 2, 8, 10, + 1, 3, 9, 11, + 4, 6, 12, 14, + 5, 7, 13, 15, + 16, 18, 24, 26, + 17, 19, 25, 27, + 20, 22, 28, 30, + 21, 23, 29, 31, }; static uint8 blockmap_PSMCT16S[32] = { - 0, 2, 16, 18, - 1, 3, 17, 19, - 8, 10, 24, 26, - 9, 11, 25, 27, - 4, 6, 20, 22, - 5, 7, 21, 23, - 12, 14, 28, 30, - 13, 15, 29, 31, + 0, 2, 16, 18, + 1, 3, 17, 19, + 8, 10, 24, 26, + 9, 11, 25, 27, + 4, 6, 20, 22, + 5, 7, 21, 23, + 12, 14, 28, 30, + 13, 15, 29, 31, }; static uint8 blockmap_PSMZ32[32] = { - 24, 25, 28, 29, 8, 9, 12, 13, - 26, 27, 30, 31, 10, 11, 14, 15, - 16, 17, 20, 21, 0, 1, 4, 5, - 18, 19, 22, 23, 2, 3, 6, 7, + 24, 25, 28, 29, 8, 9, 12, 13, + 26, 27, 30, 31, 10, 11, 14, 15, + 16, 17, 20, 21, 0, 1, 4, 5, + 18, 19, 22, 23, 2, 3, 6, 7, }; static uint8 blockmap_PSMZ16[32] = { - 24, 26, 16, 18, - 25, 27, 17, 19, - 28, 30, 20, 22, - 29, 31, 21, 23, - 8, 10, 0, 2, - 9, 11, 1, 3, - 12, 14, 4, 6, - 13, 15, 5, 7, + 24, 26, 16, 18, + 25, 27, 17, 19, + 28, 30, 20, 22, + 29, 31, 21, 23, + 8, 10, 0, 2, + 9, 11, 1, 3, + 12, 14, 4, 6, + 13, 15, 5, 7, }; static uint8 blockmap_PSMZ16S[32] = { - 24, 26, 8, 10, - 25, 27, 9, 11, - 16, 18, 0, 2, - 17, 19, 1, 3, - 28, 30, 12, 14, - 29, 31, 13, 15, - 20, 22, 4, 6, - 21, 23, 5, 7, + 24, 26, 8, 10, + 25, 27, 9, 11, + 16, 18, 0, 2, + 17, 19, 1, 3, + 28, 30, 12, 14, + 29, 31, 13, 15, + 20, 22, 4, 6, + 21, 23, 5, 7, +}; + +static uint8 blockmaprev_PSMCT32[32] = { + 0, 1, 8, 9, 2, 3, 10, 11, + 16, 17, 24, 25, 18, 19, 26, 27, + 4, 5, 12, 13, 6, 7, 14, 15, + 20, 21, 28, 29, 22, 23, 30, 31, +}; +static uint8 blockmaprev_PSMCT16[32] = { + 0, 4, 1, 5, + 8, 12, 9, 13, + 2, 6, 3, 7, + 10, 14, 11, 15, + 16, 20, 17, 21, + 24, 28, 25, 29, + 18, 22, 19, 23, + 26, 30, 27, 31, }; /* Suffixes used: @@ -603,7 +621,7 @@ calcOffsets(int32 width_Px, int32 height_Px, int32 psm, uint64 *bufferBase_B, ui uint32 bufpage_B = bufferPage_B[0]; uint32 pixeloff; for(n = 0; n < nlevels; n++){ - // Calculate TRXPOS register + // Calculate TRXPOS register (DSAX and DSAY, shifted up later) // Start of buffer on current page (x in pixels, y in blocks) pixeloff = (bufferBase_B[n] - bufpage_B) * blockWidth_Px; // y coordinate of first pixel @@ -612,7 +630,7 @@ calcOffsets(int32 width_Px, int32 height_Px, int32 psm, uint64 *bufferBase_B, ui xoff_Px = pixeloff % (bufwidth_W*64); if(bufferWidth_W[n] == bufwidth_W && // Not quite sure what's the meaning of this. - // SSAY is 11 bits, but so is SSAX and it is not checked? + // DSAY is 11 bits, but so is DSAX and it is not checked? yoff_Px < 0x800){ trxpos[n] = yoff_Px<<16 | xoff_Px; }else{ @@ -765,7 +783,7 @@ createTexRaster(Raster *raster) uint64 bufferWidth[7]; // in number of pixels / 64 uint64 bufferBase[7]; // block address - uint32 trxpos[8]; + uint32 trxpos_hi[8]; int32 width, height, depth; int32 pageWidth, pageHeight; int32 paletteWidth, paletteHeight, paletteDepth; @@ -926,7 +944,7 @@ createTexRaster(Raster *raster) // Do the real work here uint32 paletteBase; uint32 totalSize; - calcOffsets(width, height, psm, bufferBase, bufferWidth, trxpos, &totalSize, &paletteBase); + calcOffsets(width, height, psm, bufferBase, bufferWidth, trxpos_hi, &totalSize, &paletteBase); ras->paletteSize = paletteWidth*paletteHeight*paletteDepth; ras->miptbp1 = @@ -1007,35 +1025,63 @@ createTexRaster(Raster *raster) (raster->width*raster->height*raster->depth/8/0x10) >= 0x7FFF){ ras->dataSize = ras->paletteSize+ras->pixelSize; uint8 *data = (uint8*)mallocalign(ras->dataSize, 0x40); + assert(data); ras->data = data; - raster->texels = data; + raster->pixels = data; if(ras->paletteSize) raster->palette = data + ras->pixelSize; if(raster->depth == 8) ras->flags |= Ps2Raster::SWIZZLED8; }else{ - ras->flags |= Ps2Raster::HASGIFPACKETS; - //int32 cpsm = ras->tex0[1]>>19 & 0x3F; + ras->flags |= Ps2Raster::NEWSTYLE; + uint64 paltrxpos = 0; + uint32 dsax = trxpos_hi[numLevels-1] & 0x7FF; + uint32 dsay = trxpos_hi[numLevels-1]>>16 & 0x7FF; + // Set swizzle flags and calculate TRXPOS for palette if(psm == PSMT8){ ras->flags |= Ps2Raster::SWIZZLED8; - // TODO: crazy stuff + if(cpsm == PSMCT32 && bufferWidth[numLevels-1] == 2){ // one page + // unswizzle the starting block of the last buffer and palette + uint32 bufbase_B = bufferBase[numLevels-1]&~0x1F | (uint64)blockmaprev_PSMCT32[bufferBase[numLevels-1]&0x1F]; + uint32 palbase_B = ras->paletteBase&~0x1F | (uint64)blockmaprev_PSMCT32[ras->paletteBase&0x1F]; + // find start of page of last level (16,16 are PSMT8 block dimensions) + uint32 page_B = bufbase_B - 8*(dsay/16) - dsax/16; + // find palette DSAX/Y (in PSMCT32!) + dsay = (palbase_B - page_B)/8 * 8; // block/blocksPerPageX * blockHeight + dsax = (palbase_B - page_B)*8 % 64; // block*blockWidth % pageWidth + if(dsay < 0x800) + paltrxpos = dsay<<16 | dsax; + } } if(psm == PSMT4){ - // swizzle flag probably depends on version :/ + // swizzle flag depends on version :/ // but which version? .... - if(rw::version > 0x31000) + if(rw::version > 0x31000){ ras->flags |= Ps2Raster::SWIZZLED4; - // TODO: crazy stuff + // Where can this come from? if anything we're using PSMCT16S + if(cpsm == PSMCT16){ + // unswizzle the starting block of the last buffer and palette + uint32 bufbase_B = bufferBase[numLevels-1]&~0x1F | (uint64)blockmaprev_PSMCT16[bufferBase[numLevels-1]&0x1F]; + uint32 palbase_B = ras->paletteBase&~0x1F | (uint64)blockmaprev_PSMCT16[ras->paletteBase&0x1F]; + // find start of page of last level (32,16 are PSMT4 block dimensions) + uint32 page_B = bufbase_B - 4*(dsay/32) - dsax/16; + // find palette DSAX/Y (in PSMCT16!) + dsay = (palbase_B - page_B)/4 * 8; // block/blocksPerPageX * blockHeight + dsax = (palbase_B - page_B)*16 % 128; // block*blockWidth % pageWidth + if(dsay < 0x800) + paltrxpos = dsay<<16 | dsax; + } + } } ras->pixelSize = 0x50*numLevels; // GIF packets int32 minW, minH; - ps2MinSize(psm, ras->flags, &minW, &minH); + transferMinSize(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; + mipw = max(w, minW); + miph = max(h, minH); ras->pixelSize += ALIGN16(mipw*miph*raster->depth/8); w /= 2; h /= 2; @@ -1046,25 +1092,44 @@ createTexRaster(Raster *raster) ras->paletteSize = 0x50 + paletteDepth*paletteWidth*paletteHeight; } - // TODO: allocate space for more DMA packets - // every upload as 4 qwords: + // One transfer per buffer width, 4 qwords: // DMAcnt(2) [NOP, DIRECT] // GIF tag A+D // BITBLTBUF // DMAref(pixel data) [NOP, DIRECT] - ras->dataSize = ras->paletteSize+ras->pixelSize; + uint32 extrasize = 0x10; // PixelPtr + int32 numTransfers = 0; + for(n = 0; n < numLevels; n++) + if(trxpos_hi[n] == 0){ + extrasize += 0x40; + numTransfers++; + } + if(ras->paletteSize){ + extrasize += 0x40; + numTransfers++; + } + // What happens here? + if(ras->paletteSize && paltrxpos == 0) + ras->dataSize = ALIGN(ras->pixelSize,128) + ALIGN(ras->paletteSize,64) + extrasize + 0x70; + else + ras->dataSize = ALIGN(ras->paletteSize+ras->pixelSize,64) + extrasize + 0x70; uint8 *data = (uint8*)mallocalign(ras->dataSize, 0x40); + uint32 *xferchain = (uint32*)(data + 0x10); assert(data); ras->data = data; - raster->texels = data + 0x50; + Ps2Raster::PixelPtr *pp = (Ps2Raster::PixelPtr*)data; + pp->numTransfers = numTransfers; + pp->numTotalTransfers = numTransfers; + pp->pixels = (uint8*)ALIGN((uintptr)data + extrasize, 128); + raster->pixels = (uint8*)pp; if(ras->paletteSize) - raster->palette = data + ras->pixelSize + 0x50; - uint32 *p = (uint32*)data; + raster->palette = pp->pixels + ALIGN(ras->pixelSize, 128) + 0x50; + uint32 *p = (uint32*)pp->pixels; w = raster->width; h = raster->height; for(n = 0; n < numLevels; n++){ - mipw = w < minW ? minW : w; - miph = h < minH ? minH : h; + mipw = max(w, minW); + miph = max(h, minH); // GIF tag *p++ = 3; // NLOOP = 3 @@ -1073,8 +1138,14 @@ createTexRaster(Raster *raster) *p++ = 0; // TRXPOS - *p++ = 0; // TODO - *p++ = 0; // TODO + if(ras->flags & Ps2Raster::SWIZZLED8 && psm == PSMT8 || + ras->flags & Ps2Raster::SWIZZLED4 && psm == PSMT4){ + *p++ = 0; // SSAX/Y is always 0 + *p++ = (trxpos_hi[n] & ~0x10001)/2; // divide both DSAX/Y by 2 + }else{ + *p++ = 0; + *p++ = trxpos_hi[n]; + } *p++ = 0x51; *p++ = 0; @@ -1097,18 +1168,62 @@ createTexRaster(Raster *raster) *p++ = 0; // GIF tag - uint32 sz = mipw*miph*raster->depth/8 + 0xF >> 4; - *p++ = sz; + uint32 sz = ALIGN16(mipw*miph*raster->depth/8)/16; + *p++ = sz & 0x7FFF; *p++ = 0x08000000; // IMAGE *p++ = 0; *p++ = 0; + if(trxpos_hi[n] == 0){ + // Add a transfer, see above for layout + + *xferchain++ = 0x10000002; // DMAcnt, 2 qwords + *xferchain++ = 0; + *xferchain++ = 0; // VIF nop + *xferchain++ = 0x50000002; // VIF DIRECT 2 qwords + + // GIF tag + *xferchain++ = 1; // NLOOP = 1 + *xferchain++ = 0x10000000; // NREG = 1 + *xferchain++ = 0xE; // A+D + *xferchain++ = 0; + + // BITBLTBUF + if(ras->flags & Ps2Raster::SWIZZLED8 && psm == PSMT8){ + // PSMT8 is swizzled to PSMCT32 and dimensions are halved + *xferchain++ = PSMCT32<<24 | bufferWidth[n]/2<<16; // src buffer + *xferchain++ = PSMCT32<<24 | bufferWidth[n]/2<<16 | bufferBase[n]; // dst buffer + }else if(ras->flags & Ps2Raster::SWIZZLED4 && psm == PSMT4){ + // PSMT4 is swizzled to PSMCT16 and dimensions are halved + *xferchain++ = PSMCT16<<24 | bufferWidth[n]/2<<16; // src buffer + *xferchain++ = PSMCT16<<24 | bufferWidth[n]/2<<16 | bufferBase[n]; // dst buffer + }else{ + *xferchain++ = psm<<24 | bufferWidth[n]<<16; // src buffer + *xferchain++ = psm<<24 | bufferWidth[n]<<16 | bufferBase[n]; // dst buffer + } + *xferchain++ = 0x50; + *xferchain++ = 0; + + *xferchain++ = 0x30000000 | sz+5; // DMAref + // this obviously only works with 32 bit pointers, but it's only needed on the PS2 anyway + *xferchain++ = (uint32)(uintptr)p - 0x50; + *xferchain++ = 0; // VIF nop + *xferchain++ = 0x50000000 | sz+5; // VIF DIRECT 2 qwords + }else{ + // Add to existing transfer + xferchain[-4] = 0x30000000 | (xferchain[-4]&0xFFFF) + sz+5; // last DMAref + xferchain[-1] = 0x50000000 | (xferchain[-1]&0xFFFF) + sz+5; // last DIRECT + } + p += sz*4; w /= 2; h /= 2; } if(ras->paletteSize){ + // huh? + if(paltrxpos) + raster->palette = (uint8*)p + 0x50; p = (uint32*)(raster->palette - 0x50); // GIF tag *p++ = 3; // NLOOP = 3 @@ -1117,8 +1232,8 @@ createTexRaster(Raster *raster) *p++ = 0; // TRXPOS - *p++ = 0; // TODO - *p++ = 0; // TODO + *(uint64*)p = paltrxpos; + p += 2; *p++ = 0x51; *p++ = 0; @@ -1135,13 +1250,54 @@ createTexRaster(Raster *raster) *p++ = 0; // GIF tag - uint32 sz = ras->paletteSize - 0x50 + 0xF >> 4; - *p++ = sz; + uint32 sz = ALIGN16(ras->paletteSize - 0x50)/16; + *p++ = sz & 0x7FFF; *p++ = 0x08000000; // IMAGE *p++ = 0; *p++ = 0; + + // Transfer + *xferchain++ = 0x10000002; // DMAcnt, 2 qwords + *xferchain++ = 0; + *xferchain++ = 0; // VIF nop + *xferchain++ = 0x50000002; // VIF DIRECT 2 qwords + + // GIF tag + *xferchain++ = 1; // NLOOP = 1 + *xferchain++ = 0x10000000; // NREG = 1 + *xferchain++ = 0xE; // A+D + *xferchain++ = 0; + + // BITBLTBUF + if(paltrxpos == 0){ + *xferchain++ = cpsm<<24 | 1<<16; // src buffer + *xferchain++ = cpsm<<24 | 1<<16 | ras->paletteBase; // dst buffer + *xferchain++ = 0x50; + *xferchain++ = 0; + }else{ + // copy last pixel bitbltbuf...if uploading palette separately it's still the same buffer + xferchain[0] = xferchain[-16]; + xferchain[1] = xferchain[-15]; + xferchain[2] = xferchain[-14]; + xferchain[3] = xferchain[-13]; + // Add to last transfer + xferchain[-16] = 0x30000000 | (xferchain[-16]&0xFFFF) + sz+5; // last DMAref + xferchain[-13] = 0x50000000 | (xferchain[-13]&0xFFFF) + sz+5; // last DIRECT + xferchain += 4; + pp->numTransfers--; + } + + *xferchain++ = 0x30000000 | sz+5; // DMAref + // this obviously only works with 32 bit pointers, but it's only needed on the PS2 anyway + *xferchain++ = (uint32)(uintptr)p - 0x50; + *xferchain++ = 0; // VIF nop + *xferchain++ = 0x50000000 | sz+5; // VIF DIRECT 2 qwords } } + raster->originalPixels = raster->pixels; + raster->originalStride = raster->stride; + if(ras->flags & Ps2Raster::NEWSTYLE) + raster->pixels = ((Ps2Raster::PixelPtr*)raster->pixels)->pixels + 0x50; } void @@ -1151,9 +1307,15 @@ rasterCreate(Raster *raster) return; // init raster + raster->pixels = nil; + raster->palette = nil; + raster->originalWidth = raster->width; + raster->originalHeight = raster->height; + raster->originalPixels = raster->pixels; if(raster->width == 0 || raster->height == 0){ raster->flags = Raster::DONTALLOCATE; raster->stride = 0; + raster->originalStride = 0; return; } @@ -1203,7 +1365,7 @@ int32 rasterNumLevels(Raster *raster) { Ps2Raster *ras = PLUGINOFFSET(Ps2Raster, raster, nativeRasterOffset); - if(raster->texels == nil) return 0; + if(raster->pixels == nil) return 0; if(raster->format & Raster::MIPMAP) return MAXLEVEL(ras)+1; return 1; @@ -1489,9 +1651,9 @@ streamExt.mipmapVal); goto fail; } if(streamExt.type < 2){ - stream->read(raster->texels, length); + stream->read(raster->pixels, length); }else{ - stream->read(raster->texels-0x50, natras->pixelSize); + stream->read(((Ps2Raster::PixelPtr*)raster->originalPixels)->pixels, natras->pixelSize); stream->read(raster->palette-0x50, natras->paletteSize); } //printf("\n"); @@ -1528,7 +1690,7 @@ writeNativeTexture(Texture *tex, Stream *stream) streamExt.type = 0; if(ras->flags == Ps2Raster::SWIZZLED8 && raster->depth == 8) streamExt.type = 1; - if(ras->flags & Ps2Raster::HASGIFPACKETS) + if(ras->flags & Ps2Raster::NEWSTYLE) streamExt.type = 2; streamExt.tex0 = ras->tex0; streamExt.paletteOffset = ras->paletteBase; @@ -1543,9 +1705,9 @@ writeNativeTexture(Texture *tex, Stream *stream) writeChunkHeader(stream, ID_STRUCT, sz); if(streamExt.type < 2){ - stream->write(raster->texels, sz); + stream->write(raster->pixels, sz); }else{ - stream->write(raster->texels-0x50, ras->pixelSize); + stream->write(((Ps2Raster::PixelPtr*)raster->originalPixels)->pixels, ras->pixelSize); stream->write(raster->palette-0x50, ras->paletteSize); } } diff --git a/src/ps2/rwps2.h b/src/ps2/rwps2.h index ca75940..f98f4a2 100755 --- a/src/ps2/rwps2.h +++ b/src/ps2/rwps2.h @@ -183,9 +183,18 @@ void registerPluginPDSPipes(void); struct Ps2Raster { enum Flags { - HASGIFPACKETS = 0x1, - SWIZZLED8 = 0x2, - SWIZZLED4 = 0x4, + NEWSTYLE = 0x1, // has GIF tags and transfer DMA chain + SWIZZLED8 = 0x2, + SWIZZLED4 = 0x4, + }; + struct PixelPtr { + // RW has pixels as second element but we don't want this struct + // to be longer than 16 bytes + uint8 *pixels; + // palette can be allocated in last level, in that case numTransfers is + // one less than numTotalTransfers. + int32 numTransfers; + int32 numTotalTransfers; }; uint64 tex0; diff --git a/src/rwobjects.h b/src/rwobjects.h index 0a4c336..afd1846 100755 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -227,10 +227,14 @@ struct Raster int32 format; int32 width, height, depth; int32 stride; - uint8 *texels; + uint8 *pixels; uint8 *palette; + uint8 *originalPixels; + // TODO: use them (for locking mainly) + int32 originalWidth; + int32 originalHeight; + int32 originalStride; // TODO: - // original pixels, width, height, stride (used for locking) // parent raster and offset static Raster *create(int32 width, int32 height, int32 depth,