mirror of
https://github.com/XProger/OpenLara.git
synced 2025-05-12 13:35:26 +02:00
BittBoy platform support; Software Renderer (WIP)
This commit is contained in:
parent
af4b6c1159
commit
c62ed6e29d
30
src/core.h
30
src/core.h
@ -16,6 +16,8 @@
|
||||
//#define _GAPI_D3D9 1
|
||||
//#define _GAPI_D3D11 1
|
||||
//#define _GAPI_VULKAN 1
|
||||
//#define _GAPI_SW 1
|
||||
|
||||
//#define _NAPI_SOCKET
|
||||
|
||||
#include <windows.h>
|
||||
@ -34,10 +36,10 @@
|
||||
#define VR_SUPPORT
|
||||
#elif __SDL2__
|
||||
#define _GAPI_GL 1
|
||||
#ifdef SDL2_GLES
|
||||
#define _GAPI_GLES 1
|
||||
#define DYNGEOM_NO_VBO
|
||||
#endif
|
||||
#ifdef SDL2_GLES
|
||||
#define _GAPI_GLES 1
|
||||
#define DYNGEOM_NO_VBO
|
||||
#endif
|
||||
#elif __RPI__
|
||||
#define _OS_RPI 1
|
||||
#define _GAPI_GL 1
|
||||
@ -56,6 +58,9 @@
|
||||
#define _GAPI_GLES 1
|
||||
|
||||
#define DYNGEOM_NO_VBO
|
||||
#elif __BITTBOY__
|
||||
#define _OS_LINUX 1
|
||||
#define _GAPI_SW 1
|
||||
#elif __linux__
|
||||
#define _OS_LINUX 1
|
||||
#define _GAPI_GL 1
|
||||
@ -86,7 +91,6 @@
|
||||
#define _OS_PSP 1
|
||||
#define _GAPI_GU 1
|
||||
|
||||
#define FFP
|
||||
#define TEX_SWIZZLE
|
||||
//#define EDRAM_MESH
|
||||
#define EDRAM_TEX
|
||||
@ -112,9 +116,13 @@
|
||||
#include "libs/tinf/tinf.h"
|
||||
#endif
|
||||
|
||||
#if defined(_GAPI_SW) || defined(_GAPI_GU)
|
||||
#define FFP
|
||||
#endif
|
||||
|
||||
#ifdef FFP
|
||||
#define SPLIT_BY_TILE
|
||||
#ifdef _OS_PSP
|
||||
#if defined(_GAPI_GU) || defined(_GAPI_SW)
|
||||
#define SPLIT_BY_CLUT
|
||||
#endif
|
||||
#else
|
||||
@ -263,7 +271,7 @@ namespace Core {
|
||||
}
|
||||
|
||||
void setLighting(Quality value) {
|
||||
#ifdef _OS_PSP
|
||||
#if defined(_GAPI_SW) || defined(_GAPI_GU)
|
||||
lighting = LOW;
|
||||
#else
|
||||
lighting = value;
|
||||
@ -271,7 +279,7 @@ namespace Core {
|
||||
}
|
||||
|
||||
void setShadows(Quality value) {
|
||||
#ifdef _OS_PSP
|
||||
#if defined(_GAPI_SW) || defined(_GAPI_GU)
|
||||
shadows = LOW;
|
||||
#else
|
||||
shadows = value;
|
||||
@ -279,7 +287,7 @@ namespace Core {
|
||||
}
|
||||
|
||||
void setWater(Quality value) {
|
||||
#ifdef _OS_PSP
|
||||
#if defined(_GAPI_SW) || defined(_GAPI_GU)
|
||||
water = LOW;
|
||||
#else
|
||||
if (value > LOW && !(support.texFloat || support.texHalf))
|
||||
@ -666,7 +674,9 @@ namespace Core {
|
||||
} stats;
|
||||
}
|
||||
|
||||
#ifdef _GAPI_GL
|
||||
#ifdef _GAPI_SW
|
||||
#include "gapi/sw.h"
|
||||
#elif _GAPI_GL
|
||||
#include "gapi/gl.h"
|
||||
#elif _GAPI_D3D9
|
||||
#include "gapi/d3d9.h"
|
||||
|
@ -330,6 +330,8 @@ namespace GAPI {
|
||||
|
||||
void discardTarget(bool color, bool depth) {}
|
||||
|
||||
void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) {}
|
||||
|
||||
void setVSync(bool enable) {}
|
||||
|
||||
void waitVBlank() {
|
||||
|
548
src/gapi/sw.h
Normal file
548
src/gapi/sw.h
Normal file
@ -0,0 +1,548 @@
|
||||
#ifndef H_GAPI_SW
|
||||
#define H_GAPI_SW
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#define PROFILE_MARKER(title)
|
||||
#define PROFILE_LABEL(id, name, label)
|
||||
#define PROFILE_TIMING(time)
|
||||
|
||||
#ifdef _OS_LINUX
|
||||
#define COLOR_16
|
||||
#endif
|
||||
|
||||
namespace GAPI {
|
||||
|
||||
using namespace Core;
|
||||
|
||||
typedef ::Vertex Vertex;
|
||||
|
||||
#ifdef COLOR_16
|
||||
typedef uint16 ColorSW;
|
||||
#else
|
||||
typedef uint32 ColorSW;
|
||||
#endif
|
||||
typedef uint16 DepthSW;
|
||||
|
||||
// Shader
|
||||
struct Shader {
|
||||
void init(Pass pass, int type, int *def, int defCount) {}
|
||||
void deinit() {}
|
||||
void bind() {}
|
||||
void setParam(UniformType uType, const vec4 &value, int count = 1) {}
|
||||
void setParam(UniformType uType, const mat4 &value, int count = 1) {}
|
||||
};
|
||||
|
||||
// Texture
|
||||
struct Texture {
|
||||
uint8 *memory;
|
||||
int width, height, origWidth, origHeight;
|
||||
TexFormat fmt;
|
||||
uint32 opt;
|
||||
|
||||
Texture(int width, int height, int depth, uint32 opt) : memory(0), width(width), height(height), origWidth(width), origHeight(height), fmt(FMT_RGBA), opt(opt) {}
|
||||
|
||||
void init(void *data) {
|
||||
ASSERT((opt & OPT_PROXY) == 0);
|
||||
|
||||
opt &= ~(OPT_CUBEMAP | OPT_MIPMAPS);
|
||||
|
||||
memory = new uint8[width * height * 4];
|
||||
if (data) {
|
||||
update(data);
|
||||
}
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
if (memory) {
|
||||
delete[] memory;
|
||||
}
|
||||
}
|
||||
|
||||
void generateMipMap() {}
|
||||
|
||||
void update(void *data) {
|
||||
memcpy(memory, data, width * height * 4);
|
||||
}
|
||||
|
||||
void bind(int sampler) {
|
||||
Core::active.textures[sampler] = this;
|
||||
|
||||
if (!this || (opt & OPT_PROXY)) return;
|
||||
ASSERT(memory);
|
||||
|
||||
// sceGuTexMode(GU_PSM_8888, 0, 0, getSwizzle());
|
||||
// sceGuTexImage(0, width, height, width, memory);
|
||||
}
|
||||
|
||||
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 unbind(int sampler) {}
|
||||
|
||||
void setFilterQuality(int value) {
|
||||
if (value > Settings::LOW)
|
||||
opt &= ~OPT_NEAREST;
|
||||
else
|
||||
opt |= OPT_NEAREST;
|
||||
}
|
||||
};
|
||||
|
||||
// Mesh
|
||||
struct Mesh {
|
||||
Index *iBuffer;
|
||||
GAPI::Vertex *vBuffer;
|
||||
|
||||
int iCount;
|
||||
int vCount;
|
||||
bool dynamic;
|
||||
|
||||
Mesh(bool dynamic) : iBuffer(NULL), vBuffer(NULL), dynamic(dynamic) {}
|
||||
|
||||
void init(Index *indices, int iCount, ::Vertex *vertices, int vCount, int aCount) {
|
||||
this->iCount = iCount;
|
||||
this->vCount = vCount;
|
||||
|
||||
iBuffer = new Index[iCount];
|
||||
vBuffer = new Vertex[vCount];
|
||||
|
||||
update(indices, iCount, vertices, vCount);
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
delete[] iBuffer;
|
||||
delete[] vBuffer;
|
||||
}
|
||||
|
||||
void update(Index *indices, int iCount, ::Vertex *vertices, int vCount) {
|
||||
if (indices) {
|
||||
memcpy(iBuffer, indices, iCount * sizeof(indices[0]));
|
||||
}
|
||||
|
||||
if (vertices) {
|
||||
memcpy(vBuffer, vertices, vCount * sizeof(vertices[0]));
|
||||
}
|
||||
}
|
||||
|
||||
void bind(const MeshRange &range) const {}
|
||||
|
||||
void initNextRange(MeshRange &range, int &aIndex) const {
|
||||
range.aIndex = -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int cullMode, blendMode;
|
||||
|
||||
ColorSW *swColor;
|
||||
DepthSW *swDepth;
|
||||
|
||||
mat4 swMatrix;
|
||||
vec4 swViewport;
|
||||
|
||||
struct VertexSW {
|
||||
float w;
|
||||
short2 coord;
|
||||
ubyte4 color;
|
||||
short2 uv;
|
||||
DepthSW z;
|
||||
};
|
||||
|
||||
VertexSW *swVertices;
|
||||
int32 swVerticesCount;
|
||||
|
||||
Index *swIndices;
|
||||
int32 swIndicesCount;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
delete[] swDepth;
|
||||
delete[] swVertices;
|
||||
delete[] swIndices;
|
||||
}
|
||||
|
||||
void resize() {
|
||||
delete[] swDepth;
|
||||
swDepth = new DepthSW[Core::width * Core::height];
|
||||
}
|
||||
|
||||
inline mat4::ProjRange getProjRange() {
|
||||
return mat4::PROJ_NEG_POS;
|
||||
}
|
||||
|
||||
mat4 ortho(float l, float r, float b, float t, float znear, float zfar) {
|
||||
mat4 m;
|
||||
m.ortho(getProjRange(), l, r, b, t, znear, zfar);
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) {
|
||||
mat4 m;
|
||||
m.perspective(getProjRange(), fov, aspect, znear, zfar, eye);
|
||||
return m;
|
||||
}
|
||||
|
||||
bool beginFrame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
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 discardTarget(bool color, bool depth) {}
|
||||
|
||||
void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) {}
|
||||
|
||||
void setVSync(bool enable) {}
|
||||
|
||||
void waitVBlank() {
|
||||
//sceDisplayWaitVblankStart();
|
||||
}
|
||||
|
||||
void clear(bool color, bool depth) {
|
||||
if (color) {
|
||||
memset(swColor, 0, Core::width * Core::height * sizeof(ColorSW));
|
||||
}
|
||||
|
||||
if (depth) {
|
||||
memset(swDepth, 0xFF, Core::width * Core::height * sizeof(DepthSW));
|
||||
}
|
||||
}
|
||||
|
||||
void setClearColor(const vec4 &color) {
|
||||
//
|
||||
}
|
||||
|
||||
void setViewport(const Viewport &vp) {
|
||||
//
|
||||
}
|
||||
|
||||
void setDepthTest(bool enable) {
|
||||
//
|
||||
}
|
||||
|
||||
void setDepthWrite(bool enable) {
|
||||
//
|
||||
}
|
||||
|
||||
void setColorWrite(bool r, bool g, bool b, bool a) {
|
||||
//
|
||||
}
|
||||
|
||||
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 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 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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Index vcacheGet(int in) {
|
||||
int i = in % VERTEX_CACHE_MAX;
|
||||
if (vertexCache[0][i] == in) {
|
||||
return vertexCache[1][i];
|
||||
}
|
||||
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;
|
||||
|
||||
int32 i = y * Core::width;
|
||||
|
||||
for (int x = i + x1; x < i + x2; x++) {
|
||||
if (swDepth[x] >= z) {
|
||||
swDepth[x] = z;
|
||||
swColor[x] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTriangle(Index *indices) {
|
||||
VertexSW a = swVertices[indices[0]];
|
||||
VertexSW b = swVertices[indices[1]];
|
||||
VertexSW c = swVertices[indices[2]];
|
||||
|
||||
if (a.w < 0.0f || b.w < 0.0f || c.w < 0.0f) return;
|
||||
|
||||
short2 &ia = a.coord;
|
||||
short2 &ib = b.coord;
|
||||
short2 &ic = c.coord;
|
||||
|
||||
if ((ib.x - ia.x) * (ic.y - ia.y) -
|
||||
(ib.y - ia.y) * (ic.x - ia.x) <= 0) return;
|
||||
|
||||
DepthSW z = DepthSW((uint32(a.z) + uint32(b.z) + uint32(c.z)) / 3.0f); // 16-bit depth range
|
||||
|
||||
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);
|
||||
|
||||
ColorSW color = a.color.value;
|
||||
|
||||
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;
|
||||
|
||||
int16 midY = clamp(ib.y, minY, maxY);
|
||||
|
||||
int32 f = ((ic.x - ia.x) << 16) / (ic.y - ia.y);
|
||||
|
||||
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 (f1 > f2) {
|
||||
swap(x1, x2);
|
||||
swap(f1, f2);
|
||||
}
|
||||
|
||||
for (int16 y = minY; y < midY; y++) {
|
||||
DrawLine(x1 >> 16, x2 >> 16, y, z, color);
|
||||
x1 += f1;
|
||||
x2 += f2;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 (swIndicesCount < mesh->iCount) {
|
||||
delete[] swIndices;
|
||||
swIndicesCount = mesh->iCount;
|
||||
swIndices = new Index[swIndicesCount];
|
||||
}
|
||||
|
||||
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 < range.iCount; i += 3) {
|
||||
DrawTriangle(swIndices + i);
|
||||
}
|
||||
}
|
||||
|
||||
vec4 copyPixel(int x, int y) {
|
||||
return vec4(0.0f); // TODO: read from framebuffer
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1425,11 +1425,11 @@ struct Inventory {
|
||||
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
|
||||
return;
|
||||
|
||||
#ifdef _OS_PSP
|
||||
#ifdef _GAPI_GU
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef _OS_3DS
|
||||
#ifdef _GAPI_C3D
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
23
src/level.h
23
src/level.h
@ -891,7 +891,7 @@ struct Level : IGame {
|
||||
level.simpleItems = Core::settings.detail.simple == 1;
|
||||
level.initModelIndices();
|
||||
|
||||
#ifdef _OS_PSP
|
||||
#ifdef _GAPI_GU
|
||||
GAPI::freeEDRAM();
|
||||
#endif
|
||||
nextLevel = TR::LVL_MAX;
|
||||
@ -994,9 +994,11 @@ struct Level : IGame {
|
||||
delete zoneCache;
|
||||
|
||||
delete atlasRooms;
|
||||
delete atlasObjects;
|
||||
delete atlasSprites;
|
||||
delete atlasGlyphs;
|
||||
#if !defined(_GAPI_SW) && !defined(_GAPI_GU)
|
||||
delete atlasObjects;
|
||||
delete atlasSprites;
|
||||
delete atlasGlyphs;
|
||||
#endif
|
||||
delete mesh;
|
||||
|
||||
Sound::stopAll();
|
||||
@ -1494,7 +1496,7 @@ struct Level : IGame {
|
||||
void initTextures() {
|
||||
#ifndef SPLIT_BY_TILE
|
||||
|
||||
#ifdef _OS_PSP
|
||||
#if defined(_GAPI_SW) || defined(_GAPI_GU)
|
||||
#error atlas packing is not allowed for this platform
|
||||
#endif
|
||||
|
||||
@ -1628,8 +1630,11 @@ struct Level : IGame {
|
||||
#else
|
||||
ASSERT(level.tilesCount);
|
||||
|
||||
#ifdef _OS_PSP
|
||||
atlas = new Texture(level.tiles4, level.tilesCount, level.cluts, level.clutsCount);
|
||||
#if defined(_GAPI_SW) || defined(_GAPI_GU)
|
||||
atlasRooms =
|
||||
atlasObjects =
|
||||
atlasSprites =
|
||||
atlasGlyphs = new Texture(level.tiles4, level.tilesCount, level.cluts, level.clutsCount);
|
||||
#else
|
||||
Texture::Tile *tiles = new Texture::Tile[level.tilesCount];
|
||||
for (int i = 0; i < level.tilesCount; i++) {
|
||||
@ -1669,6 +1674,7 @@ struct Level : IGame {
|
||||
delete[] tiles;
|
||||
#endif
|
||||
|
||||
#ifndef _GAPI_SW
|
||||
for (int i = 0; i < level.objectTexturesCount; i++) {
|
||||
TR::TextureInfo &t = level.objectTextures[i];
|
||||
|
||||
@ -1705,6 +1711,7 @@ struct Level : IGame {
|
||||
t.texCoord[1].y += 16;
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2267,7 +2274,7 @@ struct Level : IGame {
|
||||
Core::setBlendMode(bmNone);
|
||||
|
||||
#ifdef FFP
|
||||
atlas->bind(0);
|
||||
atlasRooms->bind(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1525,7 +1525,7 @@ 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, COLOR_WHITE, COLOR_WHITE);
|
||||
addDynSprite(f.texture, d.vertices[f.vertexIndex].pos, false, false, COLOR_WHITE, COLOR_WHITE);
|
||||
}
|
||||
|
||||
dynEnd();
|
||||
|
1
src/platform/bittboy/build.sh
Normal file
1
src/platform/bittboy/build.sh
Normal file
@ -0,0 +1 @@
|
||||
/opt/bittboy-toolchain/bin/arm-buildroot-linux-musleabi-g++ -std=c++11 -O3 -s -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -Wl,--gc-sections -D__BITTBOY__ -DNDEBUG -D_POSIX_THREADS -D_POSIX_READER_WRITER_LOCKS main.cpp ../../libs/stb_vorbis/stb_vorbis.c ../../libs/minimp3/minimp3.cpp ../../libs/tinf/tinflate.c -I../../ -o../../../bin/OpenLara -lm -lpthread -lSDL -lasound
|
102
src/platform/bittboy/main.cpp
Normal file
102
src/platform/bittboy/main.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include "game.h"
|
||||
|
||||
SDL_Surface *screen = NULL;
|
||||
|
||||
#define SCREEN_WIDTH (SCREEN_HEIGHT/3)*4
|
||||
#define SCREEN_HEIGHT 240
|
||||
#define BTN_B SDLK_SPACE
|
||||
#define BTN_A SDLK_LCTRL
|
||||
#define BTN_TA SDLK_LALT
|
||||
#define BTN_TB SDLK_LSHIFT
|
||||
#define BTN_START SDLK_RETURN
|
||||
#define BTN_SELECT SDLK_ESCAPE
|
||||
#define BTN_R SDLK_RCTRL
|
||||
#define BTN_UP SDLK_UP
|
||||
#define BTN_DOWN SDLK_DOWN
|
||||
#define BTN_LEFT SDLK_LEFT
|
||||
#define BTN_RIGHT SDLK_RIGHT
|
||||
|
||||
// timing
|
||||
unsigned int startTime;
|
||||
|
||||
int osGetTimeMS() {
|
||||
timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
return int((t.tv_sec - startTime) * 1000 + t.tv_usec / 1000);
|
||||
}
|
||||
|
||||
// input
|
||||
bool osJoyReady(int index) {
|
||||
return index == 0;
|
||||
}
|
||||
|
||||
void osJoyVibrate(int index, float L, float R) {
|
||||
//
|
||||
}
|
||||
|
||||
JoyKey getJoyKey(int key) {
|
||||
switch (key) {
|
||||
case BTN_B : return jkX;
|
||||
case BTN_A : return jkA;
|
||||
case BTN_TA : return jkRB;
|
||||
case BTN_TB : return jkY;
|
||||
case BTN_START : return jkStart;
|
||||
case BTN_SELECT : return jkSelect;
|
||||
case BTN_UP : return jkUp;
|
||||
case BTN_DOWN : return jkDown;
|
||||
case BTN_LEFT : return jkLeft;
|
||||
case BTN_RIGHT : return jkRight;
|
||||
default : return jkNone;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
|
||||
SDL_ShowCursor(0);
|
||||
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 16, SDL_SWSURFACE | SDL_NOFRAME);
|
||||
|
||||
timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
startTime = t.tv_sec;
|
||||
|
||||
Core::width = SCREEN_WIDTH;
|
||||
Core::height = SCREEN_HEIGHT;
|
||||
|
||||
Core::defLang = 0;
|
||||
|
||||
Game::init("/mnt/games/OpenLara/LEVEL2.PSX");
|
||||
|
||||
GAPI::resize();
|
||||
GAPI::swColor = (uint16*)screen->pixels;
|
||||
|
||||
bool isQuit = false;
|
||||
|
||||
while (!isQuit) {
|
||||
|
||||
SDL_Event event;
|
||||
if (SDL_PollEvent(&event)) {
|
||||
|
||||
if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
|
||||
Input::setJoyDown(0, getJoyKey(event.key.keysym.sym), event.type == SDL_KEYDOWN);
|
||||
}
|
||||
|
||||
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == BTN_R) {
|
||||
isQuit = true;
|
||||
}
|
||||
} else {
|
||||
if (Game::update()) {
|
||||
Game::render();
|
||||
SDL_Flip(screen);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Game::deinit();
|
||||
|
||||
return 0;
|
||||
}
|
@ -177,6 +177,7 @@
|
||||
<ClInclude Include="..\..\gapi\gl.h" />
|
||||
<ClInclude Include="..\..\gapi\gu.h" />
|
||||
<ClInclude Include="..\..\gapi\gxm.h" />
|
||||
<ClInclude Include="..\..\gapi\sw.h" />
|
||||
<ClInclude Include="..\..\gapi\vk.h" />
|
||||
<ClInclude Include="..\..\gltf.h" />
|
||||
<ClInclude Include="..\..\json.h" />
|
||||
|
@ -101,6 +101,9 @@
|
||||
<ClInclude Include="..\..\gapi\vk.h">
|
||||
<Filter>gapi</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\gapi\sw.h">
|
||||
<Filter>gapi</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\lang\gr.h">
|
||||
<Filter>lang</Filter>
|
||||
</ClInclude>
|
||||
|
@ -379,7 +379,31 @@ void sndInit(HWND hwnd) {
|
||||
|
||||
HWND hWnd;
|
||||
|
||||
#ifdef _GAPI_GL
|
||||
|
||||
#ifdef _GAPI_SW
|
||||
HDC hDC;
|
||||
|
||||
void ContextCreate() {
|
||||
hDC = GetDC(hWnd);
|
||||
}
|
||||
|
||||
void ContextDelete() {
|
||||
ReleaseDC(hWnd, hDC);
|
||||
delete[] GAPI::swColor;
|
||||
}
|
||||
|
||||
void ContextResize() {
|
||||
delete[] GAPI::swColor;
|
||||
GAPI::swColor = new GAPI::ColorSW[Core::width * Core::height];
|
||||
|
||||
GAPI::resize();
|
||||
}
|
||||
|
||||
void ContextSwap() {
|
||||
const BITMAPINFO bmi = { sizeof(BITMAPINFOHEADER), Core::width, -Core::height, 1, sizeof(GAPI::ColorSW) * 8, BI_RGB, 0, 0, 0, 0, 0 };
|
||||
SetDIBitsToDevice(hDC, 0, 0, Core::width, Core::height, 0, 0, 0, Core::height, GAPI::swColor, &bmi, 0);
|
||||
}
|
||||
#elif _GAPI_GL
|
||||
HDC hDC;
|
||||
HGLRC hRC;
|
||||
|
||||
|
@ -8,11 +8,11 @@ struct Texture : GAPI::Texture {
|
||||
|
||||
#ifdef SPLIT_BY_TILE
|
||||
|
||||
#ifdef _OS_PSP
|
||||
#if defined(_GAPI_SW) || defined(_GAPI_GU)
|
||||
TR::Tile4 *tiles;
|
||||
TR::CLUT *cluts;
|
||||
|
||||
Texture(TR::Tile4 *tiles, int tilesCount, TR::CLUT *cluts, int clutsCount) : GAPI::Texture(256, 256, OPT_PROXY) {
|
||||
Texture(TR::Tile4 *tiles, int tilesCount, TR::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]));
|
||||
@ -37,7 +37,7 @@ struct Texture : GAPI::Texture {
|
||||
uint32 *data;
|
||||
};
|
||||
|
||||
Texture(Tile *tiles, int tilesCount) : GAPI::Texture(256, 256, OPT_PROXY) {
|
||||
Texture(Tile *tiles, int tilesCount) : GAPI::Texture(256, 256, 1, OPT_PROXY) {
|
||||
memset(this->tiles, 0, sizeof(this->tiles));
|
||||
|
||||
ASSERT(tilesCount < COUNT(this->tiles));
|
||||
@ -47,7 +47,7 @@ struct Texture : GAPI::Texture {
|
||||
#endif
|
||||
|
||||
void bindTile(uint16 tile, uint16 clut) {
|
||||
#ifdef _OS_PSP
|
||||
#if defined(_GAPI_SW) || defined(_GAPI_GU)
|
||||
bindTileCLUT(tiles + tile, cluts + clut);
|
||||
#else
|
||||
tiles[tile]->bind(0);
|
||||
@ -68,7 +68,7 @@ struct Texture : GAPI::Texture {
|
||||
|
||||
Texture(int width, int height, int depth, TexFormat format, uint32 opt = 0, void *data = NULL) : GAPI::Texture(width, height, depth, opt) {
|
||||
#ifdef SPLIT_BY_TILE
|
||||
#ifndef _OS_PSP
|
||||
#if !defined(_GAPI_SW) && !defined(_GAPI_GU)
|
||||
memset(this->tiles, 0, sizeof(tiles));
|
||||
#endif
|
||||
#endif
|
||||
@ -123,7 +123,7 @@ struct Texture : GAPI::Texture {
|
||||
}
|
||||
|
||||
virtual ~Texture() {
|
||||
#ifndef _OS_PSP
|
||||
#if !defined(_GAPI_SW) && !defined(_GAPI_GU)
|
||||
#ifdef SPLIT_BY_TILE
|
||||
for (int i = 0; i < COUNT(tiles); i++)
|
||||
delete tiles[i];
|
||||
|
Loading…
x
Reference in New Issue
Block a user