diff --git a/src/core.h b/src/core.h index b8f7799..19e3cfe 100644 --- a/src/core.h +++ b/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 @@ -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" diff --git a/src/gapi/gu.h b/src/gapi/gu.h index 76d1441..1574ceb 100644 --- a/src/gapi/gu.h +++ b/src/gapi/gu.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() { diff --git a/src/gapi/sw.h b/src/gapi/sw.h new file mode 100644 index 0000000..da95837 --- /dev/null +++ b/src/gapi/sw.h @@ -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 diff --git a/src/inventory.h b/src/inventory.h index 8469621..e178e39 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -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 diff --git a/src/level.h b/src/level.h index d06e51f..eb9a563 100644 --- a/src/level.h +++ b/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 } diff --git a/src/mesh.h b/src/mesh.h index 975b620..23224a0 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -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(); diff --git a/src/platform/bittboy/build.sh b/src/platform/bittboy/build.sh new file mode 100644 index 0000000..e92ab4b --- /dev/null +++ b/src/platform/bittboy/build.sh @@ -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 diff --git a/src/platform/bittboy/main.cpp b/src/platform/bittboy/main.cpp new file mode 100644 index 0000000..c7172eb --- /dev/null +++ b/src/platform/bittboy/main.cpp @@ -0,0 +1,102 @@ +#include +#include +#include + +#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; +} diff --git a/src/platform/win/OpenLara.vcxproj b/src/platform/win/OpenLara.vcxproj index 528511c..3961acf 100644 --- a/src/platform/win/OpenLara.vcxproj +++ b/src/platform/win/OpenLara.vcxproj @@ -177,6 +177,7 @@ + diff --git a/src/platform/win/OpenLara.vcxproj.filters b/src/platform/win/OpenLara.vcxproj.filters index de46a49..1ee0dc1 100644 --- a/src/platform/win/OpenLara.vcxproj.filters +++ b/src/platform/win/OpenLara.vcxproj.filters @@ -101,6 +101,9 @@ gapi + + gapi + lang diff --git a/src/platform/win/main.cpp b/src/platform/win/main.cpp index ab3ee1f..047318b 100644 --- a/src/platform/win/main.cpp +++ b/src/platform/win/main.cpp @@ -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; diff --git a/src/texture.h b/src/texture.h index 8127f72..42934ac 100644 --- a/src/texture.h +++ b/src/texture.h @@ -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];