1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-30 00:10:09 +02:00

software rasterizer (triangles, quads, textured, color palette, lightmap)

This commit is contained in:
XProger
2019-10-05 07:21:16 +03:00
parent c62ed6e29d
commit fb962ec7b9
14 changed files with 592 additions and 381 deletions

View File

@@ -870,7 +870,7 @@ struct WaterCache {
game->setupBinding();
// merge visible rooms for all items
int roomsList[256];
RoomDesc roomsList[256];
int roomsCount = 0;
for (int i = 0; i < level->roomsCount; i++)

View File

@@ -6,9 +6,6 @@
#include "controller.h"
#include "character.h"
#define CAM_OFFSET_COMBAT (2048.0f + 512.0f)
#define CAM_OFFSET_LOOK (512.0f)
#define CAM_SPEED_FOLLOW 12
#define CAM_SPEED_COMBAT 8
@@ -21,6 +18,14 @@
#define CAM_OFFSET_FOLLOW (1024.0f + 512.0f)
#endif
#ifdef _OS_BITTBOY
#define CAM_OFFSET_COMBAT CAM_OFFSET_FOLLOW
#else
#define CAM_OFFSET_COMBAT (2048.0f + 512.0f)
#endif
#define CAM_OFFSET_LOOK (512.0f)
#define CAM_FOLLOW_ANGLE 0.0f
#define CAM_LOOK_ANGLE_XMAX ( 55.0f * DEG2RAD)
#define CAM_LOOK_ANGLE_XMIN (-75.0f * DEG2RAD)

View File

@@ -46,6 +46,14 @@ struct ICamera {
}
};
struct RoomDesc {
int32 index;
vec4 portal;
RoomDesc() {}
RoomDesc(int32 index, const vec4 &portal) : index(index), portal(portal) {}
};
struct IGame {
virtual ~IGame() {}
virtual void loadLevel(TR::LevelID id) {}
@@ -68,11 +76,11 @@ struct IGame {
virtual void setShader(Core::Pass pass, Shader::Type type, bool underwater = false, bool alphaTest = false) {}
virtual void setRoomParams(int roomIndex, Shader::Type type, float diffuse, float ambient, float specular, float alpha, bool alphaTest = false) {}
virtual void setupBinding() {}
virtual void getVisibleRooms(int *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) {}
virtual void getVisibleRooms(RoomDesc *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) {}
virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0, Core::Pass pass = Core::passAmbient) {}
virtual void renderModelFull(int modelIndex, bool underwater, Basis *joints) {}
virtual void renderCompose(int roomIndex) {}
virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, int *roomsList = NULL) {}
virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, RoomDesc *roomsList = NULL) {}
virtual void renderGame(bool showUI, bool invBG) {}
virtual void setEffect(Controller *controller, TR::Effect::Type effect) {}

View File

@@ -6,6 +6,8 @@
#endif
#include <stdio.h>
#include <memory.h>
#include <stdint.h>
#define OS_FILEIO_CACHE
#define OS_PTHREAD_MT
@@ -59,8 +61,9 @@
#define DYNGEOM_NO_VBO
#elif __BITTBOY__
#define _OS_LINUX 1
#define _GAPI_SW 1
#define _OS_BITTBOY 1
#define _OS_LINUX 1
#define _GAPI_SW 1
#elif __linux__
#define _OS_LINUX 1
#define _GAPI_GL 1
@@ -122,7 +125,7 @@
#ifdef FFP
#define SPLIT_BY_TILE
#if defined(_GAPI_GU) || defined(_GAPI_SW)
#if defined(_GAPI_GU)
#define SPLIT_BY_CLUT
#endif
#else
@@ -461,7 +464,7 @@ struct Edge {
struct Vertex {
short4 coord; // xyz - position, w - joint index (for entities only)
short4 normal; // xyz - vertex normal, w - unused
short4 normal; // xyz - vertex normal, w - quad(0) or triangle (1)
short4 texCoord; // xy - texture coordinates, zw - trapezoid warping
ubyte4 color; // for non-textured geometry
ubyte4 light; // xyz - color, w - use premultiplied alpha
@@ -1044,6 +1047,12 @@ namespace Core {
setViewport(Viewport(x, y, width, height));
}
void setViewport(const vec4 &vp, int width, int height) {
vec4 s = vec4(vp.x, -vp.w, vp.z, -vp.y);
s = (s * 0.5 + 0.5) * vec4(float(width), float(height), float(width), float(height));
setViewport(int(s.x), int(s.y), int(s.z) - int(s.x), int(s.w) - int(s.y));
}
void setCullMode(CullMode mode) {
renderState &= ~RS_CULL;
switch (mode) {

View File

@@ -1752,30 +1752,6 @@ namespace TR {
#define FACE4_SIZE (sizeof(uint16) + sizeof(uint16) * 4) // flags + vertices[4]
#define FACE3_SIZE (FACE4_SIZE - sizeof(uint16))
struct ColorIndex4 {
uint8 a:4, b:4;
};
struct Tile4 {
ColorIndex4 index[256 * 256 / 2];
};
struct Tile8 {
uint8 index[256 * 256];
};
struct Tile16 {
Color16 color[256 * 256];
};
struct Tile32 {
Color32 color[256 * 256]; // + 128 for mips data
};
struct CLUT {
Color16 color[16];
};
struct Room {
struct Info {
@@ -2986,6 +2962,7 @@ namespace TR {
int32 entitiesCount;
Entity *entities;
uint8 lightmap[32 * 256]; // color indices table for 32 shades
Color24 *palette;
Color32 *palette32;
@@ -2999,6 +2976,7 @@ namespace TR {
Tile32 *tiles32;
Tile32 *tilesMisc;
uint16 cameraFramesCount;
CameraFrame *cameraFrames;
@@ -3848,7 +3826,10 @@ namespace TR {
}
void readLightMap(Stream &stream) {
stream.seek(32 * 256); // unused
stream.raw(lightmap, 32 * 256);
for (int i = 0; i < 32; i++) {
lightmap[i * 256] = 0;
}
}
void readCameraFrames(Stream &stream) {
@@ -6443,7 +6424,12 @@ namespace TR {
Color32 getColor(int texture) const {
switch (version) {
case VER_TR1_SAT : return Color16((uint16)texture);
case VER_TR1_PC : return palette[texture & 0xFF];
case VER_TR1_PC :
#ifdef _GAPI_SW
return Color32(texture & 0xFF, 0, 0, 142);
#else
return palette[texture & 0xFF];
#endif
case VER_TR2_PC :
case VER_TR3_PC : return palette32[(texture >> 8) & 0xFF];
case VER_TR1_PSX :

View File

@@ -494,6 +494,7 @@ namespace GAPI {
void init(Core::Pass pass, int type, int *def, int defCount) {}
void deinit() {}
void bind() {}
void validate() {}
void setParam(UniformType uType, const vec4 &value, int count = 1) {}
void setParam(UniformType uType, const mat4 &value, int count = 1) {}
#else
@@ -1257,8 +1258,7 @@ namespace GAPI {
glScalef(1.0f / 32767.0f, 1.0f / 32767.0f, 1.0f / 32767.0f);
glClearColor(0, 0, 0, 0);
#endif
#else
char extHeader[256];
GLSL_HEADER_VERT[0] = GLSL_HEADER_FRAG[0] = extHeader[0] = 0;
if (_GL_OES_standard_derivatives) {
@@ -1322,6 +1322,7 @@ namespace GAPI {
#endif
ASSERT(strlen(GLSL_HEADER_VERT) < COUNT(GLSL_HEADER_VERT));
ASSERT(strlen(GLSL_HEADER_FRAG) < COUNT(GLSL_HEADER_FRAG));
#endif // FFP
}
void deinit() {

View File

@@ -11,6 +11,19 @@
#define COLOR_16
#endif
#ifdef COLOR_16
#ifdef _OS_LINUX
#define COLOR_FMT_565
#define CONV_COLOR(r,g,b) (((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3))
#else
#define COLOR_FMT_555
#define CONV_COLOR(r,g,b) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3))
#endif
#else
#define COLOR_FMT_888
#define CONV_COLOR(r,g,b) ((r << 16) | (g << 8) | b)
#endif
namespace GAPI {
using namespace Core;
@@ -24,6 +37,16 @@ namespace GAPI {
#endif
typedef uint16 DepthSW;
uint8 *swLightmap; // 32 * 256
ColorSW *swPalette;
ColorSW swPaletteColor[256];
ColorSW swPaletteWater[256];
ColorSW swPaletteGray[256];
uint8 swGradient[256];
Tile8 *curTile;
uint8 ambient;
// Shader
struct Shader {
void init(Pass pass, int type, int *def, int defCount) {}
@@ -71,17 +94,11 @@ namespace GAPI {
if (!this || (opt & OPT_PROXY)) return;
ASSERT(memory);
// sceGuTexMode(GU_PSM_8888, 0, 0, getSwizzle());
// sceGuTexImage(0, width, height, width, memory);
curTile = NULL;
}
void bindTileCLUT(void *tile, void *clut) {
ASSERT(tile);
ASSERT(clut);
// sceGuTexMode(GU_PSM_T4, 0, 0, getSwizzle());
// sceGuClutLoad(1, clut);
// sceGuTexImage(0, width, height, width, tile);
void bindTileIndices(Tile8 *tile) {
curTile = (Tile8*)tile;
}
void unbind(int sampler) {}
@@ -124,7 +141,7 @@ namespace GAPI {
if (indices) {
memcpy(iBuffer, indices, iCount * sizeof(indices[0]));
}
if (vertices) {
memcpy(vBuffer, vertices, vCount * sizeof(vertices[0]));
}
@@ -142,76 +159,81 @@ namespace GAPI {
ColorSW *swColor;
DepthSW *swDepth;
short4 swClipRect;
mat4 swMatrix;
vec4 swViewport;
mat4 swMatrix;
vec2 swScale;
struct VertexSW {
float w;
short2 coord;
ubyte4 color;
short2 uv;
DepthSW z;
int32 x, y, z, w;
int32 u, v, l;
inline VertexSW operator + (const VertexSW &p) const {
VertexSW ret;
ret.x = x + p.x;
ret.y = y;
ret.z = z + p.z;
ret.w = w + p.w;
ret.u = u + p.u;
ret.v = v + p.v;
ret.l = l + p.l;
return ret;
}
inline VertexSW operator - (const VertexSW &p) const {
VertexSW ret;
ret.x = x - p.x;
ret.y = y;
ret.z = z - p.z;
ret.w = w - p.w;
ret.u = u - p.u;
ret.v = v - p.v;
ret.l = l - p.l;
return ret;
}
inline VertexSW operator * (const int32 s) const {
VertexSW ret;
ret.x = x * s;
ret.y = y;
ret.z = z * s;
ret.w = w * s;
ret.u = u * s;
ret.v = v * s;
ret.l = l * s;
return ret;
}
inline VertexSW operator / (const int32 s) const {
VertexSW ret;
ret.x = x / s;
ret.y = y;
ret.z = z / s;
ret.w = w / s;
ret.u = u / s;
ret.v = v / s;
ret.l = l / s;
return ret;
}
};
VertexSW *swVertices;
int32 swVerticesCount;
Index *swIndices;
int32 swIndicesCount;
Array<VertexSW> swVertices;
Array<Index> swIndices;
Array<int32> swTriangles;
Array<int32> swQuads;
void init() {
LOG("Renderer : %s\n", "Software");
LOG("Version : %s\n", "0.1");
/*
sceGuEnable(GU_TEXTURE_2D);
sceGuDepthFunc(GU_LEQUAL);
sceGuDepthRange(0x0000, 0xFFFF);
sceGuClearDepth(0xFFFF);
sceGuShadeModel(GU_SMOOTH);
sceGuAlphaFunc(GU_GREATER, 127, 255);
int swizzle = GU_FALSE;
#ifdef TEX_SWIZZLE
swizzle = GU_TRUE;
#endif
sceGuClutMode(GU_PSM_5551, 0, 0xFF, 0);
sceGuTexMode(GU_PSM_T4, 0, 0, swizzle);
sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
sceGuTexScale(1.0f, 1.0f);
sceGuTexOffset(0.0f, 0.0f);
sceGuTexFilter(GU_LINEAR, GU_LINEAR);
//sceGuTexFilter(GU_NEAREST, GU_NEAREST);
sceGuEnable(GU_CLIP_PLANES);
const ScePspIMatrix4 dith =
{ {-4, 0, -3, 1},
{ 2, -2, 3, -1},
{-3, 1, -4, 0},
{ 3, -1, 2, -2} };
sceGuSetDither(&dith);
sceGuEnable(GU_DITHER);
sceGuAmbientColor(0xFFFFFFFF);
sceGuColor(0xFFFFFFFF);
sceGuClearColor(0x00000000);
sceGuColorMaterial(GU_AMBIENT | GU_DIFFUSE);
*/
swDepth = NULL;
swVertices = NULL;
swIndices = NULL;
swVerticesCount = 0;
swIndicesCount = 0;
swDepth = NULL;
}
void deinit() {
delete[] swDepth;
delete[] swVertices;
delete[] swIndices;
swVertices.clear();
swIndices.clear();
swTriangles.clear();
swQuads.clear();
}
void resize() {
@@ -220,7 +242,7 @@ namespace GAPI {
}
inline mat4::ProjRange getProjRange() {
return mat4::PROJ_NEG_POS;
return mat4::PROJ_ZERO_POS;
}
mat4 ortho(float l, float r, float b, float t, float znear, float zfar) {
@@ -239,20 +261,11 @@ namespace GAPI {
return true;
}
void endFrame() {
//
}
void endFrame() {}
void resetState() {}
void bindTarget(Texture *texture, int face) {
/*
if (!target)
sceGuDrawBufferList(GU_PSM_5650, GAPI::curBackBuffer, 512);
else
sceGuDrawBufferList(GU_PSM_5650, target->offset, target->width);
*/
}
void bindTarget(Texture *texture, int face) {}
void discardTarget(bool color, bool depth) {}
@@ -260,13 +273,11 @@ namespace GAPI {
void setVSync(bool enable) {}
void waitVBlank() {
//sceDisplayWaitVblankStart();
}
void waitVBlank() {}
void clear(bool color, bool depth) {
if (color) {
memset(swColor, 0, Core::width * Core::height * sizeof(ColorSW));
// memset(swColor, 0x00, Core::width * Core::height * sizeof(ColorSW));
}
if (depth) {
@@ -274,270 +285,387 @@ namespace GAPI {
}
}
void setClearColor(const vec4 &color) {
//
}
void setClearColor(const vec4 &color) {}
void setViewport(const Viewport &vp) {
//
swClipRect.x = vp.x;
swClipRect.y = vp.y;
swClipRect.z = vp.x + vp.width;
swClipRect.w = vp.y + vp.height;
}
void setDepthTest(bool enable) {
//
}
void setDepthTest(bool enable) {}
void setDepthWrite(bool enable) {
//
}
void setDepthWrite(bool enable) {}
void setColorWrite(bool r, bool g, bool b, bool a) {
//
}
void setColorWrite(bool r, bool g, bool b, bool a) {}
void setAlphaTest(bool enable) {
//
}
void setAlphaTest(bool enable) {}
void setCullMode(int rsMask) {
cullMode = rsMask;
//switch (rsMask) {
// case RS_CULL_BACK : sceGuFrontFace(GU_CCW); break;
// case RS_CULL_FRONT : sceGuFrontFace(GU_CW); break;
// default : sceGuDisable(GU_CULL_FACE); return;
//}
//sceGuEnable(GU_CULL_FACE);
}
void setCullMode(int rsMask) {}
void setBlendMode(int rsMask) {
blendMode = rsMask;
//switch (rsMask) {
// case RS_BLEND_ALPHA : sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); break;
// case RS_BLEND_ADD : sceGuBlendFunc(GU_ADD, GU_FIX, GU_FIX, 0xffffffff, 0xffffffff); break;
// case RS_BLEND_MULT : sceGuBlendFunc(GU_ADD, GU_DST_COLOR, GU_FIX, 0, 0); break;
// case RS_BLEND_PREMULT : sceGuBlendFunc(GU_ADD, GU_FIX, GU_ONE_MINUS_SRC_ALPHA, 0xffffffff, 0); break;
// default : sceGuDisable(GU_BLEND); return;
//}
//sceGuEnable(GU_BLEND);
}
void setBlendMode(int rsMask) {}
void setViewProj(const mat4 &mView, const mat4 &mProj) {
//
}
void setViewProj(const mat4 &mView, const mat4 &mProj) {}
void updateLights(vec4 *lightPos, vec4 *lightColor, int count) {
int lightsCount = 0;
ubyte4 amb;
amb.x = amb.y = amb.z = clamp(int(active.material.y * 255), 0, 255);
amb.w = 255;
/*
sceGuAmbient(*(uint32*)&amb);
ambient = clamp(int32(active.material.y * 255), 0, 255);
for (int i = 0; i < MAX_LIGHTS; i++) {
if (lightColor[i].w != 1.0f) {
sceGuEnable(GU_LIGHT0 + i);
lightsCount++;
} else {
sceGuDisable(GU_LIGHT0 + i);
continue;
}
ScePspFVector3 pos;
pos.x = lightPos[i].x;
pos.y = lightPos[i].y;
pos.z = lightPos[i].z;
sceGuLight(i, GU_POINTLIGHT, GU_DIFFUSE, &pos);
ubyte4 color;
color.x = clamp(int(lightColor[i].x * 255), 0, 255);
color.y = clamp(int(lightColor[i].y * 255), 0, 255);
color.z = clamp(int(lightColor[i].z * 255), 0, 255);
color.w = 255;
sceGuLightColor(i, GU_DIFFUSE, *(uint32*)&color);
sceGuLightAtt(i, 1.0f, 0.0f, lightColor[i].w * lightColor[i].w);
// TODO
}
if (lightsCount) {
sceGuEnable(GU_LIGHTING);
} else {
sceGuDisable(GU_LIGHTING);
}
*/
}
struct Edge {
float A, B, C;
Edge(const vec3 &a, const vec3 &b) {
A = a.y - b.y;
B = b.x - a.x;
C = -(A * (a.x + b.x) + B * (a.y + b.y)) * 0.5f;
}
float evaluate(float x, float y) const {
return A*x + B*y + C;
}
};
#define VERTEX_CACHE_MAX 4
Index vertexCache[2][VERTEX_CACHE_MAX];
void vcacheClear() {
memset(vertexCache, 0xFF, sizeof(vertexCache));
}
void vcacheSet(int in, int out) {
int i = in % VERTEX_CACHE_MAX;
vertexCache[0][i] = in;
vertexCache[1][i] = out;
bool checkBackface(const VertexSW *a, const VertexSW *b, const VertexSW *c) {
return ((b->x - a->x) >> 16) * (c->y - a->y) -
((c->x - a->x) >> 16) * (b->y - a->y) <= 0;
}
Index vcacheGet(int in) {
int i = in % VERTEX_CACHE_MAX;
if (vertexCache[0][i] == in) {
return vertexCache[1][i];
inline void sortVertices(VertexSW *&t, VertexSW *&m, VertexSW *&b) {
if (t->y > m->y) swap(t, m);
if (t->y > b->y) swap(t, b);
if (m->y > b->y) swap(m, b);
}
inline void sortVertices(VertexSW *&t, VertexSW *&m, VertexSW *&b, VertexSW *&o) {
if (t->y > m->y) swap(t, m);
if (o->y > b->y) swap(o, b);
if (t->y > o->y) swap(t, o);
if (m->y > b->y) swap(m, b);
if (m->y > o->y) swap(m, o);
}
inline void step(VertexSW &v, const VertexSW &d) {
//v.w += d.w;
v.u += d.u;
v.v += d.v;
v.l += d.l;
}
inline void step(VertexSW &v, const VertexSW &d, int32 count) {
//v.w += d.w * count;
v.u += d.u * count;
v.v += d.v * count;
v.l += d.l * count;
}
void drawLine(const VertexSW &L, const VertexSW &R, int32 y) {
int32 x1 = L.x >> 16;
int32 x2 = R.x >> 16;
int32 f = x2 - x1;
if (f == 0) return;
VertexSW dS = (R - L) / f;
VertexSW S = L;
if (x1 < swClipRect.x) {
x1 = swClipRect.x - x1;
S.z += dS.z * x1;
step(S, dS, x1);
x1 = Core::viewport.x;
}
return 0xFFFF;
}
void DrawLine(int x1, int x2, int y, DepthSW z, ColorSW color) {
if (x2 - x1 == 0) return;
if (x1 < 0) x1 = 0;
if (x2 > Core::width - 1) x2 = Core::width - 1;
if (x2 < x1) return;
if (x2 > swClipRect.z) x2 = swClipRect.z;
int32 i = y * Core::width;
for (int x = i + x1; x < i + x2; x++) {
S.z += dS.z;
DepthSW z = DepthSW(uint32(S.z) >> 16);
if (swDepth[x] >= z) {
swDepth[x] = z;
swColor[x] = color;
uint32 u = uint32(S.u) >> 16;
uint32 v = uint32(S.v) >> 16;
uint8 index = curTile->index[(v << 8) + u];
if (index != 0) {
index = swLightmap[((S.l >> (16 + 3)) << 8) + index];
swColor[x] = swPalette[index];
swDepth[x] = z;
}
}
step(S, dS);
}
}
void DrawTriangle(Index *indices) {
VertexSW a = swVertices[indices[0]];
VertexSW b = swVertices[indices[1]];
VertexSW c = swVertices[indices[2]];
void drawPart(const VertexSW &a, const VertexSW &b, const VertexSW &c, const VertexSW &d) {
VertexSW L, R, dL, dR;
int32 minY, maxY;
if (a.w < 0.0f || b.w < 0.0f || c.w < 0.0f) return;
int32 f = c.y - a.y;
dL = (c - a) / f;
dR = (d - b) / f;
short2 &ia = a.coord;
short2 &ib = b.coord;
short2 &ic = c.coord;
L = a;
R = b;
if ((ib.x - ia.x) * (ic.y - ia.y) -
(ib.y - ia.y) * (ic.x - ia.x) <= 0) return;
minY = a.y;
maxY = c.y;
DepthSW z = DepthSW((uint32(a.z) + uint32(b.z) + uint32(c.z)) / 3.0f); // 16-bit depth range
if (maxY < swClipRect.y || minY >= swClipRect.w) return;
if (a.coord.y > b.coord.y) swap(a, b);
if (a.coord.y > c.coord.y) swap(a, c);
if (b.coord.y > c.coord.y) swap(b, c);
if (minY < swClipRect.y) {
minY = swClipRect.y - minY;
L.x += dL.x * minY;
L.z += dL.z * minY;
R.x += dR.x * minY;
R.z += dR.z * minY;
step(L, dL, minY);
step(R, dR, minY);
minY = swClipRect.y;
}
ColorSW color = a.color.value;
if (maxY > swClipRect.w) maxY = swClipRect.w;
int16 minY = ia.y;
int16 maxY = ic.y;
if (minY < 0) minY = 0;
if (maxY > Core::height - 1) maxY = Core::height - 1;
if (minY > maxY) return;
for (int y = minY; y < maxY; y++) {
drawLine(L, R, y);
L.x += dL.x;
L.z += dL.z;
R.x += dR.x;
R.z += dR.z;
step(L, dL);
step(R, dR);
}
}
int16 midY = clamp(ib.y, minY, maxY);
void drawTriangle(Index *indices) {
/*
t
/\ <----- top triangle
m /__\/ n
\ /\
\ \ <-- bottom triangle
\ \
\\
\
b
*/
VertexSW _n;
VertexSW *t = swVertices + indices[0];
VertexSW *m = swVertices + indices[1];
VertexSW *b = swVertices + indices[2];
VertexSW *n = &_n;
int32 f = ((ic.x - ia.x) << 16) / (ic.y - ia.y);
if (t->w <= 0 || m->w <= 0 || b->w <= 0)
return;
if (ia.y != ib.y) {
int32 f1 = f;
int32 f2 = ((ib.x - ia.x) << 16) / (ib.y - ia.y);
int32 x1 = (ia.x << 16) + (minY - ia.y) * f1;
int32 x2 = (ia.x << 16) + (minY - ia.y) * f2;
if (checkBackface(t, m, b))
return;
if (f1 > f2) {
swap(x1, x2);
swap(f1, f2);
int32 cx1 = swClipRect.x << 16;
int32 cx2 = swClipRect.z << 16;
if (t->x < cx1 && m->x < cx1 && b->x < cx1)
return;
if (t->x > cx2 && m->x > cx2 && b->x > cx2)
return;
sortVertices(t, m, b);
if (b->y < swClipRect.y || t->y > swClipRect.w)
return;
*n = ((*b - *t) / (b->y - t->y) * (m->y - t->y)) + *t;
n->y = m->y;
if (m->x > n->x) {
swap(m, n);
}
if (m->y != t->y) drawPart(*t, *t, *m, *n);
if (m->y != b->y) drawPart(*m, *n, *b, *b);
}
void drawQuad(Index *indices) {
/*
t
/\ <----- top triangle
m /__\/ n
\ /\
\ \ <-- quad
p \/__\ o
/\ /
\/ <-- bottom triangle
b
*/
VertexSW _n;
VertexSW _p;
VertexSW *t = swVertices + indices[0];
VertexSW *m = swVertices + indices[1];
VertexSW *b = swVertices + indices[2];
VertexSW *o = swVertices + indices[3];
VertexSW *n = &_n;
VertexSW *p = &_p;
if (t->w <= 0 || m->w <= 0 || o->w <= 0 || b->w <= 0)
return;
if (checkBackface(t, m, b))
return;
int32 cx1 = swClipRect.x << 16;
int32 cx2 = swClipRect.z << 16;
if (t->x < cx1 && m->x < cx1 && o->x < cx1 && b->x < cx1)
return;
if (t->x > cx2 && m->x > cx2 && o->x > cx2 && b->x > cx2)
return;
sortVertices(t, m, b, o);
if (b->y < swClipRect.y || t->y > swClipRect.w)
return;
if (checkBackface(t, b, m) == checkBackface(t, b, o)) {
VertexSW d = (*b - *t) / (b->y - t->y);
*n = *t + d * (m->y - t->y);
*p = *t + d * (o->y - t->y);
n->y = m->y;
p->y = o->y;
} else {
if (o->y != t->y) {
*n = *t + ((*o - *t) / (o->y - t->y) * (m->y - t->y));
n->y = m->y;
}
for (int16 y = minY; y < midY; y++) {
DrawLine(x1 >> 16, x2 >> 16, y, z, color);
x1 += f1;
x2 += f2;
if (m->y != b->y) {
*p = *b + ((*m - *b) / (m->y - b->y) * (o->y - b->y));
p->y = o->y;
}
}
if (o->y != t->y && m->x > n->x) swap(m, n);
if (m->y != b->y && p->x > o->x) swap(p, o);
if (t->y != m->y) drawPart(*t, *t, *m, *n);
if (m->y != o->y) drawPart(*m, *n, *p, *o);
if (o->y != b->y) drawPart(*p, *o, *b, *b);
}
bool transform(const Index *indices, const Vertex *vertices, int iStart, int iCount, int vStart) {
swVertices.reset();
swIndices.reset();
swTriangles.reset();
swQuads.reset();
int vIndex = 0;
bool isTriangle = false;
bool colored = false;
for (int i = 0; i < iCount; i++) {
const Index index = indices[iStart + i];
const Vertex &vertex = vertices[vStart + index];
vIndex++;
if (vIndex == 1) {
isTriangle = vertex.normal.w == 1;
}
if (vertex.color.w == 142) {
colored = true;
}
if (!isTriangle && (vIndex == 4 || vIndex == 5)) { // loader splits quads to two triangles with indices 012[02]3, we ignore [02] to make it quad again!
continue;
}
vec4 c;
c = swMatrix * vec4(vertex.coord.x, vertex.coord.y, vertex.coord.z, 1.0f);
c.x /= c.w;
c.y /= c.w;
c.z /= c.w;
c.x = clamp(c.x, -16384.0f, 16384.0f);
c.y = clamp(c.y, -16384.0f, 16384.0f);
VertexSW result;
result.x = int32(c.x) << 16;
result.y = int32(c.y);
result.z = uint32(clamp(c.z, 0.0f, 1.0f) * 65535.0f) << 16;
result.w = int32(c.w);
if (colored) {
result.u = vertex.color.x << 16;
result.v = 0;
} else {
result.u = (vertex.texCoord.x << 16);// / result.w;
result.v = (vertex.texCoord.y << 16);// / result.w;
}
result.w = result.w << 16;
result.l = (255 - ((vertex.light.x * ambient) >> 8)) << 16;
swIndices.push(swVertices.push(result));
ASSERT(!(isTriangle && vIndex > 3));
if (isTriangle && vIndex == 3) {
swTriangles.push(swIndices.length - 3);
vIndex = 0;
} else if (vIndex == 6) {
swQuads.push(swIndices.length - 4);
vIndex = 0;
}
}
if (ib.y != ic.y) {
int32 f1 = f;
int32 f2 = ((ic.x - ib.x) << 16) / (ic.y - ib.y);
int32 x1 = (ia.x << 16) + (midY - ia.y) * f1;
int32 x2 = (ib.x << 16) + (midY - ib.y) * f2;
if (x1 > x2) {
swap(x1, x2);
swap(f1, f2);
}
for (int16 y = midY; y < maxY; y++) {
DrawLine(x1 >> 16, x2 >> 16, y, z, color);
x1 += f1;
x2 += f2;
}
}
return colored;
}
void DIP(Mesh *mesh, const MeshRange &range) {
swMatrix = mViewProj * mModel;
swViewport = vec4(float(Core::width / 2), float(Core::height / 2), 0, 0);
if (swVerticesCount < mesh->vCount) {
delete[] swVertices;
swVerticesCount = mesh->vCount;
swVertices = new VertexSW[swVerticesCount];
if (curTile == NULL) {
//uint32 *tex = (uint32*)Core::active.textures[0]->memory; // TODO
return;
}
if (swIndicesCount < mesh->iCount) {
delete[] swIndices;
swIndicesCount = mesh->iCount;
swIndices = new Index[swIndicesCount];
swMatrix.viewport(0.0f, (float)Core::height, (float)Core::width, -(float)Core::height, 0.0f, 1.0f);
swMatrix = swMatrix * mViewProj * mModel;
bool colored = transform(mesh->iBuffer, mesh->vBuffer, range.iStart, range.iCount, range.vStart);
Tile8 *oldTile = curTile;
if (colored) {
curTile = (Tile8*)swGradient;
}
vcacheClear();
uint32 vCount = 0;
for (int i = 0; i < range.iCount; i++) {
Index in = mesh->iBuffer[range.iStart + i];
Index out = vcacheGet(in);
if (out == 0xFFFF) {
out = vCount++;
VertexSW &result = swVertices[out];
Vertex &vertex = mesh->vBuffer[range.vStart + in];
vec4 c;
c = swMatrix * vec4(vertex.coord.x, vertex.coord.y, vertex.coord.z, 1.0f); \
c.x = clamp( swViewport.x * ( c.x / c.w + 1.0f), -16384.0f, 16384.0f); \
c.y = clamp( swViewport.y * (-c.y / c.w + 1.0f), -16384.0f, 16384.0f); \
c.z /= c.w;
result.w = c.w;
result.coord = short2( int16(c.x), int16(c.y) );
result.z = DepthSW(clamp(c.z, 0.0f, 1.0f) * 0xFFFF);
result.color = vertex.light;
vcacheSet(in, out);
}
swIndices[i] = out;
for (int i = 0; i < swQuads.length; i++) {
drawQuad(&swIndices[swQuads[i]]);
}
for (int i = 0; i < range.iCount; i += 3) {
DrawTriangle(swIndices + i);
for (int i = 0; i < swTriangles.length; i++) {
drawTriangle(&swIndices[swTriangles[i]]);
}
curTile = oldTile;
}
void initPalette(Color24 *palette, uint8 *lightmap) {
swLightmap = lightmap;
for (uint32 i = 0; i < 256; i++) {
const Color24 &p = palette[i];
swPaletteColor[i] = CONV_COLOR(p.r, p.g, p.b);
swPaletteWater[i] = CONV_COLOR((uint32(p.r) * 150) >> 8, (uint32(p.g) * 230) >> 8, (uint32(p.b) * 230) >> 8);
swPaletteGray[i] = CONV_COLOR((i * 57) >> 8, (i * 29) >> 8, (i * 112) >> 8);
swGradient[i] = i;
}
}
void setPalette(ColorSW *palette) {
swPalette = palette;
}
vec4 copyPixel(int x, int y) {

View File

@@ -157,7 +157,9 @@ static const OptionItem optSound[] = {
OptionItem( OptionItem::TYPE_PARAM, STR_EMPTY, SETTINGS( audio.sound ), 0xFFFF8000, 102, SND_MAX_VOLUME, true ),
OptionItem( OptionItem::TYPE_PARAM, STR_REVERBERATION, SETTINGS( audio.reverb ), STR_OFF, 0, 1 ),
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_SUBTITLES, SETTINGS( audio.subtitles ), STR_OFF, 0, 1 ),
#ifndef FFP
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_LANGUAGE, SETTINGS( audio.language ), STR_LANG_EN, 0, 10 ),
#endif
};
#if defined(_OS_CLOVER) || defined(_OS_PSC)
@@ -1836,7 +1838,7 @@ struct Inventory {
m.identity();
Core::setViewProj(m, m);
Core::mModel.identity();
Core::mModel.scale(vec3(1.0f / 32767.0f));
#else
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR || !background[0]) {
backTex = Core::blackTex; // black background

View File

@@ -565,6 +565,10 @@ struct Level : IGame {
setShader(Core::pass, type, (Core::pass == Core::passAmbient) ? false : room.flags.water, alphaTest);
#ifdef _GAPI_SW
GAPI::setPalette(room.flags.water ? GAPI::swPaletteWater : GAPI::swPaletteColor);
#endif
Core::setMaterial(material.x, material.y, material.z, material.w);
if (room.flags.water) {
@@ -598,6 +602,9 @@ struct Level : IGame {
}
virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0, Core::Pass pass = Core::passAmbient) {
#ifdef _GAPI_SW
return;
#endif
PROFILE_MARKER("ENVIRONMENT");
setupBinding();
float tmpEye = Core::eye;
@@ -1240,7 +1247,7 @@ struct Level : IGame {
#define ATLAS_PAGE_BARS 4096
#define ATLAS_PAGE_GLYPHS 8192
TR::Tile32 *tileData;
Tile32 *tileData;
uint8 *glyphsRU;
uint8 *glyphsJA;
uint8 *glyphsGR;
@@ -1451,7 +1458,7 @@ struct Level : IGame {
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++) {
TR::Tile8 &tile = level.tiles8[sprite.tile];
Tile8 &tile = level.tiles8[sprite.tile];
data[pos.x + x + (pos.y + y) * size.x] = level.getColor(tile.index[sprite.texCoord[0].x + x + (sprite.texCoord[0].y + y) * 256]);
}
@@ -1465,17 +1472,17 @@ struct Level : IGame {
void dumpKanji() {
Stream stream("DATA/KANJI.PSX");
int size = stream.readLE32() / 2;
TR::ColorIndex4 *buffer = new TR::ColorIndex4[size];
ColorIndex4 *buffer = new ColorIndex4[size];
stream.raw(buffer, size);
int width = 256;
int height = size / width * 2;
Color32 *image = new Color32[width * height];
TR::Tile4 *tile = (TR::Tile4*)buffer;
TR::CLUT &clut = level.cluts[level.spriteTextures[level.kanjiSprite].clut];
Tile4 *tile = (Tile4*)buffer;
CLUT &clut = level.cluts[level.spriteTextures[level.kanjiSprite].clut];
TR::ColorIndex4 *idx = buffer;
ColorIndex4 *idx = buffer;
Color32 *ptr = image;
for (int y = 0; y < height; y++) {
@@ -1585,7 +1592,7 @@ struct Level : IGame {
}
// get result texture
tileData = new TR::Tile32();
tileData = new Tile32();
atlasRooms = rAtlas->pack(true);
atlasObjects = oAtlas->pack(true);
@@ -1630,7 +1637,14 @@ struct Level : IGame {
#else
ASSERT(level.tilesCount);
#if defined(_GAPI_SW) || defined(_GAPI_GU)
#if defined(_GAPI_SW)
atlasRooms =
atlasObjects =
atlasSprites =
atlasGlyphs = new Texture(level.tiles8, level.tilesCount);
GAPI::initPalette(level.palette, level.lightmap);
GAPI::setPalette(GAPI::swPaletteColor);
#elif defined(_GAPI_GU)
atlasRooms =
atlasObjects =
atlasSprites =
@@ -1647,7 +1661,7 @@ struct Level : IGame {
short4 uv = t.getMinMax();
uv.z++;
uv.w++;
level.fillObjectTexture((TR::Tile32*)tiles[t.tile].data, uv, &t);
level.fillObjectTexture((Tile32*)tiles[t.tile].data, uv, &t);
}
for (int i = 0; i < level.spriteTexturesCount; i++) {
@@ -1655,7 +1669,7 @@ struct Level : IGame {
short4 uv = t.getMinMax();
uv.z++;
uv.w++;
level.fillObjectTexture((TR::Tile32*)tiles[t.tile].data, uv, &t);
level.fillObjectTexture((Tile32*)tiles[t.tile].data, uv, &t);
}
for (int i = 0; i < level.tilesCount; i++) {
@@ -1667,7 +1681,10 @@ struct Level : IGame {
}
}
atlas = new Texture(tiles, level.tilesCount);
atlasRooms =
atlasObjects =
atlasSprites =
atlasGlyphs = new Texture(tiles, level.tilesCount);
for (int i = 0; i < level.tilesCount; i++)
delete[] tiles[i].data;
@@ -1800,14 +1817,14 @@ struct Level : IGame {
Core::pass = pass;
}
void prepareRooms(int *roomsList, int roomsCount) {
void prepareRooms(RoomDesc *roomsList, int roomsCount) {
skyIsVisible = (level.version & TR::VER_TR1);
for (int i = 0; i < level.roomsCount; i++)
level.rooms[i].flags.visible = false;
for (int i = 0; i < roomsCount; i++) {
TR::Room &r = level.rooms[roomsList[i]];
TR::Room &r = level.rooms[roomsList[i].index];
skyIsVisible |= r.flags.sky;
r.flags.visible = true;
}
@@ -1829,7 +1846,7 @@ struct Level : IGame {
setMainLight(player);
}
void renderRooms(int *roomsList, int roomsCount, int transp) {
void renderRooms(RoomDesc *roomsList, int roomsCount, int transp) {
PROFILE_MARKER("ROOMS");
if (Core::pass == Core::passShadow)
@@ -1858,8 +1875,10 @@ struct Level : IGame {
atlasRooms->bind(sDiffuse);
Viewport vp = Core::viewport;
while (i != end) {
int roomIndex = roomsList[i];
int roomIndex = roomsList[i].index;
MeshBuilder::RoomRange &range = mesh->rooms[roomIndex];
if (!range.geometry[transp].count && !range.dynamic[transp].count) {
@@ -1867,6 +1886,10 @@ struct Level : IGame {
continue;
}
#ifdef _GAPI_SW
Core::setViewport(roomsList[i].portal, vp.width, vp.height);
#endif
const TR::Room &room = level.rooms[roomIndex];
vec3 center = room.getCenter();
@@ -1899,14 +1922,18 @@ struct Level : IGame {
#endif
for (int i = 0; i < roomsCount; i++) {
level.rooms[roomsList[i]].flags.visible = true;
int roomIndex = roomsList[i].index;
level.rooms[roomIndex].flags.visible = true;
int roomIndex = roomsList[i];
MeshBuilder::RoomRange &range = mesh->rooms[roomIndex];
if (!range.sprites.iCount)
continue;
#ifdef _GAPI_SW
Core::setViewport(roomsList[i].portal, vp.width, vp.height);
#endif
setRoomParams(roomIndex, Shader::SPRITE, 1.0f, 1.0f, 0.0f, 1.0f, true);
basis.pos = level.rooms[roomIndex].getOffset();
@@ -1916,6 +1943,7 @@ struct Level : IGame {
}
}
Core::setViewport(vp);
Core::setBlendMode(bmNone);
}
@@ -2259,10 +2287,7 @@ struct Level : IGame {
Core::setBlendMode(bmPremult);
renderEntitiesTransp(transp);
#ifdef FFP
Core::whiteTex->bind(0);
#endif
#ifndef FFP
Core::whiteTex->bind(sDiffuse);
Core::setBlendMode(bmMult);
for (int i = 0; i < level.entitiesCount; i++) {
@@ -2272,10 +2297,7 @@ struct Level : IGame {
controller->renderShadow(mesh);
}
Core::setBlendMode(bmNone);
#ifdef FFP
atlasRooms->bind(0);
#endif
#endif
}
if (transp == 2) {
@@ -2357,7 +2379,7 @@ struct Level : IGame {
return true;
}
virtual void getVisibleRooms(int *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) {
virtual void getVisibleRooms(RoomDesc *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) {
if (count > 16) {
//ASSERT(false);
return;
@@ -2370,7 +2392,7 @@ struct Level : IGame {
waterCache->setVisible(from, to);
room.flags.visible = true;
roomsList[roomsCount++] = to;
roomsList[roomsCount++] = RoomDesc(to, viewPort);
}
vec4 clipPort;
@@ -2385,7 +2407,7 @@ struct Level : IGame {
}
}
void renderOpaque(int *roomsList, int roomsCount) {
void renderOpaque(RoomDesc *roomsList, int roomsCount) {
renderRooms(roomsList, roomsCount, 0);
renderEntities(0);
if (Core::pass != Core::passShadow && skyIsVisible) {
@@ -2393,12 +2415,12 @@ struct Level : IGame {
}
}
void renderTransparent(int *roomsList, int roomsCount) {
void renderTransparent(RoomDesc *roomsList, int roomsCount) {
renderRooms(roomsList, roomsCount, 1);
renderEntities(1);
}
void renderAdditive(int *roomsList, int roomsCount) {
void renderAdditive(RoomDesc *roomsList, int roomsCount) {
vec4 oldFog = Core::fogParams;
Core::fogParams = FOG_BLACK; // don't apply fog for additive
renderRooms(roomsList, roomsCount, 2);
@@ -2406,13 +2428,13 @@ struct Level : IGame {
Core::fogParams = oldFog;
}
virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, int *roomsList = NULL) {
virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, RoomDesc *roomsList = NULL) {
PROFILE_MARKER("VIEW");
if (water && waterCache)
waterCache->reset();
int rList[256];
RoomDesc rList[256];
if (!roomsList) {
roomsList = rList;
@@ -2435,21 +2457,21 @@ struct Level : IGame {
// add other non-alternative rooms
for (int i = 0; i < level.roomsCount; i++)
if (!level.rooms[i].flags.visible)
roomsList[roomsCount++] = i;
roomsList[roomsCount++] = RoomDesc(i, vec4(-1.0f, -1.0f, 1.0f, 1.0f));
// refresh visible flag
for (int i = 0; i < level.roomsCount; i++)
level.rooms[i].flags.visible = false;
for (int i = 0; i < roomsCount; i++)
level.rooms[roomsList[i]].flags.visible = true;
level.rooms[roomsList[i].index].flags.visible = true;
} else
getVisibleRooms(roomsList, roomsCount, TR::NO_ROOM, roomIndex, vec4(-1.0f, -1.0f, 1.0f, 1.0f), water);
}
if (water && waterCache) {
for (int i = 0; i < roomsCount; i++)
waterCache->setVisible(roomsList[i]);
waterCache->setVisible(roomsList[i].index);
waterCache->renderReflection();
@@ -3153,6 +3175,10 @@ struct Level : IGame {
void renderUI() {
if (inventory->titleTimer > 1.0f || level.isTitle()) return;
#ifdef _GAPI_SW
GAPI::setPalette(GAPI::swPaletteColor);
#endif
Core::pushLights();
UI::begin(camera->aspect);

View File

@@ -70,7 +70,7 @@ struct Mesh : GAPI::Mesh {
TR::Room::Data::Vertex &v = d.vertices[f.vertices[k]];\
Vertex &rv = _vertices[vCount++];\
rv.coord = short4( v.pos.x, v.pos.y, v.pos.z, 0 );\
rv.normal = short4( f.normal.x, f.normal.y, f.normal.z, 0 );\
rv.normal = short4( f.normal.x, f.normal.y, f.normal.z, f.triangle ? 1 : 0 );\
rv.color = ubyte4( 255, 255, 255, 255 );\
rv.light = ubyte4( v.color.r, v.color.g, v.color.b, 255 );\
}
@@ -462,7 +462,7 @@ struct MeshBuilder {
shadowBlob.iCount = 8 * 3 * 3;
for (int i = 0; i < 9; i++) {
Vertex &v0 = vertices[vCount + i * 2 + 0];
v0.normal = short4( 0, -1, 0, 32767 );
v0.normal = short4( 0, -1, 0, 1 );
v0.texCoord = short4( whiteObject.texCoordAtlas[0].x, whiteObject.texCoordAtlas[0].y, 32767, 32767 );
v0.color = v0.light = ubyte4( 0, 0, 0, 0 );
@@ -538,7 +538,7 @@ struct MeshBuilder {
Vertex &v = vertices[vCount + i];
pos.rotate(cs);
v.coord = short4( short(pos.x), short(pos.y), 0, 1 );
v.normal = short4( 0, 0, 0, 32767 );
v.normal = short4( 0, 0, 0, 1 );
v.texCoord = short4( whiteSprite.texCoordAtlas[0].x, whiteSprite.texCoordAtlas[0].y, 32767, 32767 );
v.color = ubyte4( 255, 255, 255, 255 );
v.light = ubyte4( 255, 255, 255, 255 );
@@ -564,7 +564,7 @@ struct MeshBuilder {
for (int i = 0; i < COUNT(boxCoords); i++) {
Vertex &v = vertices[vCount++];
v.coord = boxCoords[i];
v.normal = short4(0, 0, 0, 32767);
v.normal = short4(0, 0, 0, 0);
v.texCoord = short4(0, 0, 0, 0);
v.color = ubyte4(255, 255, 255, 255);
v.light = ubyte4(255, 255, 255, 255);
@@ -1092,9 +1092,9 @@ struct MeshBuilder {
vertices[vCount].coord = transform(v.coord, joint, x, y, z, dir);
vec3 n = vec3(v.normal.x, v.normal.y, v.normal.z).normal() * 32767.0f;
v.normal = short4(short(n.x), short(n.y), short(n.z), 0);
v.normal = short4(short(n.x), short(n.y), short(n.z), f.triangle ? 1 : 0);
vertices[vCount].normal = rotate(v.normal, dir);
vertices[vCount].color = ubyte4( c.r, c.g, c.b, 255 );
vertices[vCount].color = ubyte4( c.r, c.g, c.b, c.a );
vertices[vCount].light = ubyte4( light.r, light.g, light.b, 255 );
vCount++;
@@ -1525,7 +1525,8 @@ struct MeshBuilder {
TR::Room::Data &d = level->rooms[roomIndex].data;
for (int j = 0; j < d.sCount; j++) {
TR::Room::Data::Sprite &f = d.sprites[j];
addDynSprite(f.texture, d.vertices[f.vertexIndex].pos, false, false, COLOR_WHITE, COLOR_WHITE);
TR::Room::Data::Vertex &v = d.vertices[f.vertexIndex];
addDynSprite(f.texture, d.vertices[f.vertexIndex].pos, false, false, v.color, v.color);
}
dynEnd();

View File

@@ -135,13 +135,13 @@
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FloatingPointModel>Strict</FloatingPointModel>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalOptions>/d2noftol3 %(AdditionalOptions)</AdditionalOptions>
<WholeProgramOptimization>true</WholeProgramOptimization>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>wcrt.lib;wsock32.lib;opengl32.lib;d3d11.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

View File

@@ -923,7 +923,7 @@ int main(int argc, char** argv) {
#else
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
int argc = (lpCmdLine && strlen(lpCmdLine)) ? 2 : 1;
char *argv[] = { "", lpCmdLine };
const char *argv[] = { "", lpCmdLine };
#endif
cacheDir[0] = saveDir[0] = contentDir[0] = 0;

View File

@@ -8,11 +8,17 @@ struct Texture : GAPI::Texture {
#ifdef SPLIT_BY_TILE
#if defined(_GAPI_SW) || defined(_GAPI_GU)
TR::Tile4 *tiles;
TR::CLUT *cluts;
#if defined(_GAPI_SW)
Tile8 *tiles;
Texture(TR::Tile4 *tiles, int tilesCount, TR::CLUT *cluts, int clutsCount) : GAPI::Texture(256, 256, 1, OPT_PROXY) {
Texture(Tile8 *tiles, int tilesCount) : GAPI::Texture(256, 256, 1, OPT_PROXY) {
this->tiles = tiles;
}
#elif defined(_GAPI_GU)
Tile4 *tiles;
CLUT *cluts;
Texture(Tile4 *tiles, int tilesCount, CLUT *cluts, int clutsCount) : GAPI::Texture(256, 256, 1, OPT_PROXY) {
#ifdef EDRAM_TEX
this->tiles = (TR::Tile4*)GAPI::allocEDRAM(tilesCount * sizeof(tiles[0]));
this->cluts = (TR::CLUT*)GAPI::allocEDRAM(clutsCount * sizeof(cluts[0]));
@@ -47,7 +53,9 @@ struct Texture : GAPI::Texture {
#endif
void bindTile(uint16 tile, uint16 clut) {
#if defined(_GAPI_SW) || defined(_GAPI_GU)
#if defined(_GAPI_SW)
bindTileIndices(tiles + tile);
#elif defined(_GAPI_GU)
bindTileCLUT(tiles + tile, cluts + clut);
#else
tiles[tile]->bind(0);

View File

@@ -737,6 +737,16 @@ struct mat4 {
frustum(range, -x - eyeX, x - eyeX, -y - eyeY, y - eyeY, znear, zfar, rotate90);
}
void viewport(float x, float y, float width, float height, float n, float f) {
identity();
e00 = width * 0.5f;
e11 = height * 0.5f;
e22 = (f - n) * 0.5f;
e23 = (f + n) * 0.5f;
e03 = x + e00;
e13 = y + e11;
}
mat4(const vec3 &from, const vec3 &at, const vec3 &up) {
vec3 r, u, d;
d = (from - at).normal();
@@ -1444,6 +1454,29 @@ union Color16 { // RGBA5551
operator Color32() const { return Color32((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2), -a); }
};
struct ColorIndex4 {
uint8 a:4, b:4;
};
struct Tile4 {
ColorIndex4 index[256 * 256 / 2];
};
struct Tile8 {
uint8 index[256 * 256];
};
struct Tile16 {
Color16 color[256 * 256];
};
struct Tile32 {
Color32 color[256 * 256]; // + 128 for mips data
};
struct CLUT {
Color16 color[16];
};
namespace String {
@@ -2053,8 +2086,12 @@ struct Array {
this->length = length;
}
void clear() {
void reset() {
length = 0;
}
void clear() {
reset();
free(items);
items = NULL;
}
@@ -2068,7 +2105,7 @@ struct Array {
return items[index];
};
operator T*() const { return items; };
inline operator T*() const { return items; };
};