From 6d9304d96a77dd2beb9dfa14203e37b71d5df319 Mon Sep 17 00:00:00 2001 From: XProger Date: Sun, 27 Dec 2020 18:00:36 +0300 Subject: [PATCH] TI-Nspire port --- src/core.h | 8 ++- src/format.h | 9 ++- src/gameflow.h | 4 +- src/gapi/sw.h | 23 ++++-- src/objects.h | 14 ++-- src/platform/tns/Makefile | 49 +++++++++++++ src/platform/tns/main.cpp | 145 ++++++++++++++++++++++++++++++++++++++ src/sound.h | 25 ++++--- src/ui.h | 2 +- src/utils.h | 12 ++-- src/video.h | 20 ++++++ 11 files changed, 278 insertions(+), 33 deletions(-) create mode 100644 src/platform/tns/Makefile create mode 100644 src/platform/tns/main.cpp diff --git a/src/core.h b/src/core.h index f0d52fa..603f8c1 100644 --- a/src/core.h +++ b/src/core.h @@ -150,9 +150,15 @@ #elif _X360 #define _OS_X360 1 // TODO +#elif __NDLESS__ + #define _OS_TNS 1 + #define _GAPI_SW 1 + #include + + #undef OS_PTHREAD_MT #endif -#ifndef _OS_PSP +#if !defined(_OS_PSP) && !defined(_OS_TNS) #define USE_INFLATE #endif diff --git a/src/format.h b/src/format.h index 7a1448d..e1160d5 100644 --- a/src/format.h +++ b/src/format.h @@ -3233,7 +3233,9 @@ namespace TR { case VER_TR2_PSX : loadTR2_PSX (stream); break; case VER_TR3_PC : loadTR3_PC (stream); break; case VER_TR3_PSX : loadTR3_PSX (stream); break; + #ifdef USE_INFLATE case VER_TR4_PC : loadTR4_PC (stream); break; + #endif case VER_TR4_PSX : loadTR4_PSX (stream); break; case VER_TR4_SDC : loadTR4_SDC (stream); break; case VER_TR5_PC : loadTR5_PC (stream); break; @@ -3609,6 +3611,7 @@ namespace TR { readCameraFrames(stream); } + #ifdef USE_INFLATE void loadTR4_PC (Stream &stream) { uint16 roomTilesCount, objTilesCount, bumpTilesCount; uint32 sizeD, sizeC, sizeR; @@ -3686,6 +3689,7 @@ namespace TR { soundDataSize += sizeC; } } + #endif void loadTR4_PSX (Stream &stream) { @@ -5895,10 +5899,13 @@ namespace TR { break; } case VER_TR3_PSX : { + mesh.tCount = 0; + mesh.rCount = 0; + mesh.fCount = 0; + if (!mesh.vCount) { mesh.vertices = NULL; mesh.faces = NULL; - mesh.tCount = mesh.rCount = mesh.fCount = 0; break; } diff --git a/src/gameflow.h b/src/gameflow.h index 4b63918..b631469 100644 --- a/src/gameflow.h +++ b/src/gameflow.h @@ -1087,7 +1087,7 @@ namespace TR { id == LVL_TR2_CUT_4 || id == LVL_TR2_XIAN || id == LVL_TR2_HOUSE) { char buf[64]; strcpy(buf, LEVEL_INFO[id].name); - String::toLower(buf); + StrUtils::toLower(buf); sprintf(dst, "DATA/%s.TR2", buf); } else if (id == LVL_TR2_TITLE) { sprintf(dst, "DATA/%s.tr2", LEVEL_INFO[id].name); @@ -1098,7 +1098,7 @@ namespace TR { } if (Stream::existsContent(dst)) break; strcpy(dst, LEVEL_INFO[id].name); - String::toLower(dst); + StrUtils::toLower(dst); strcat(dst, ".TR2"); break; } diff --git a/src/gapi/sw.h b/src/gapi/sw.h index b15c681..8957373 100644 --- a/src/gapi/sw.h +++ b/src/gapi/sw.h @@ -7,12 +7,14 @@ #define PROFILE_LABEL(id, name, label) #define PROFILE_TIMING(time) -#ifdef _OS_LINUX +//#define DITHER_FILTER + +#if defined(_OS_LINUX) || defined(_OS_TNS) #define COLOR_16 #endif #ifdef COLOR_16 - #ifdef _OS_LINUX + #if defined(_OS_LINUX) || defined(_OS_TNS) #define COLOR_FMT_565 #define CONV_COLOR(r,g,b) (((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)) #else @@ -290,7 +292,7 @@ namespace GAPI { } if (depth) { - memset(swDepth, 0xFF, Core::width * Core::height * sizeof(DepthSW)); + //memset(swDepth, 0xFF, Core::width * Core::height * sizeof(DepthSW)); } } @@ -396,18 +398,25 @@ namespace GAPI { int32 i = y * Core::width; + #ifdef DITHER_FILTER const int *dithY = uvDither + ((y & 1) * 4); + #endif for (int x = i + x1; x < i + x2; x++) { S.z += dS.z; DepthSW z = DepthSW(uint32(S.z) >> 16); - if (swDepth[x] >= z) { + {//if (swDepth[x] >= z) { + #ifdef DITHER_FILTER const int *dithX = dithY + (x & 1); uint32 u = uint32(S.u + dithX[0]) >> 16; uint32 v = uint32(S.v + dithX[2]) >> 16; + #else + uint32 u = uint32(S.u) >> 16; + uint32 v = uint32(S.v) >> 16; + #endif uint8 index = curTile->index[(v << 8) + u]; @@ -415,7 +424,7 @@ namespace GAPI { index = swLightmap[((S.l >> (16 + 3)) << 8) + index]; swColor[x] = swPalette[index]; - swDepth[x] = z; + //swDepth[x] = z; } } @@ -580,8 +589,8 @@ namespace GAPI { } void applyLighting(VertexSW &result, const Vertex &vertex, float depth) { - vec3 coord = vec3(vertex.coord); - vec3 normal = vec3(vertex.normal).normal(); + vec3 coord = vec3(float(vertex.coord.x), float(vertex.coord.y), float(vertex.coord.z)); + vec3 normal = vec3(float(vertex.normal.x), float(vertex.normal.y), float(vertex.normal.z)).normal(); float lighting = 0.0f; for (int i = 0; i < lightsCount; i++) { LightSW &light = lightsRel[i]; diff --git a/src/objects.h b/src/objects.h index 1c86287..ce631f1 100644 --- a/src/objects.h +++ b/src/objects.h @@ -153,9 +153,9 @@ struct Flame : Sprite { Controller *owner; int32 jointIndex; - float sleep; + float sleepTime; - Flame(IGame *game, int entity) : Sprite(game, entity, false, Sprite::FRAME_ANIMATED), owner(NULL), jointIndex(0), sleep(0.0f) { + Flame(IGame *game, int entity) : Sprite(game, entity, false, Sprite::FRAME_ANIMATED), owner(NULL), jointIndex(0), sleepTime(0.0f) { time = randf() * 3.0f; activate(); } @@ -186,15 +186,15 @@ struct Flame : Sprite { lara->hit(FLAME_BURN_DAMAGE * Core::deltaTime, this); } else if (lara->health > 0.0f) { - if (sleep > 0.0f) - sleep = max(0.0f, sleep - Core::deltaTime); + if (sleepTime > 0.0f) + sleepTime = max(0.0f, sleepTime - Core::deltaTime); - if (sleep == 0.0f && !lara->burn && lara->collide(Sphere(pos, 600.0f))) { + if (sleepTime == 0.0f && !lara->burn && lara->collide(Sphere(pos, 600.0f))) { lara->hit(FLAME_HEAT_DAMAGE * Core::deltaTime, this); if (lara->collide(Sphere(pos, 300.0f))) { Flame::add(game, lara, 0); - sleep = 3.0f; // stay inactive for 3 seconds + sleepTime = 3.0f; // stay inactive for 3 seconds } } } @@ -1838,4 +1838,4 @@ struct Bullet : Controller { } }; -#endif \ No newline at end of file +#endif diff --git a/src/platform/tns/Makefile b/src/platform/tns/Makefile new file mode 100644 index 0000000..b4b9d14 --- /dev/null +++ b/src/platform/tns/Makefile @@ -0,0 +1,49 @@ +DEBUG = FALSE + +GCC = nspire-gcc +AS = nspire-as +GXX = nspire-g++ +LD = nspire-ld +GENZEHN = genzehn + +GCCFLAGS = -marm -march=armv5te -mtune=arm926ej-s -std=c++11 -flto -fomit-frame-pointer -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -D__NDLESS__ -I../../ +LDFLAGS = -Wl,--gc-sections -Wl,--as-needed -flto -Wno-alloc-size-larger-than +ZEHNFLAGS = --name "OpenLara" + +ifeq ($(DEBUG),FALSE) + GCCFLAGS += -Ofast +else + GCCFLAGS += -O0 -g +endif + +OBJS = $(patsubst %.c, %.o, $(shell find . -name \*.c)) +OBJS += $(patsubst %.cpp, %.o, $(shell find . -name \*.cpp)) +OBJS += $(patsubst %.S, %.o, $(shell find . -name \*.S)) +EXE = OpenLara +DISTDIR = . +vpath %.tns $(DISTDIR) +vpath %.elf $(DISTDIR) + +all: $(EXE).prg.tns + +%.o: %.c + $(GCC) $(GCCFLAGS) -c $< + +%.o: %.cpp + $(GXX) $(GCCFLAGS) -c $< + +%.o: %.S + $(AS) -c $< + +$(EXE).elf: $(OBJS) + mkdir -p $(DISTDIR) + $(LD) $^ -o $(DISTDIR)/$@ $(LDFLAGS) + +$(EXE).tns: $(EXE).elf + $(GENZEHN) --input $(DISTDIR)/$^ --output $(DISTDIR)/$@ $(ZEHNFLAGS) + +$(EXE).prg.tns: $(EXE).tns + make-prg $(DISTDIR)/$^ $(DISTDIR)/$@ + +clean: + rm -f *.o $(DISTDIR)/$(EXE).tns $(DISTDIR)/$(EXE).elf $(DISTDIR)/$(EXE).prg.tns diff --git a/src/platform/tns/main.cpp b/src/platform/tns/main.cpp new file mode 100644 index 0000000..04c0e2f --- /dev/null +++ b/src/platform/tns/main.cpp @@ -0,0 +1,145 @@ +#include + +#include + +// multi-threading (no sound - no problem) +void* osMutexInit() { return NULL; } +void osMutexFree(void *obj) {} +void osMutexLock(void *obj) {} +void osMutexUnlock(void *obj) {} + + +// timing +unsigned int osTime; +volatile unsigned int *timerBUS; +volatile unsigned int *timerCLK; +volatile unsigned int *timerCTR; +volatile unsigned int *timerDIV; + +void timerInit() +{ + timerBUS = (unsigned int*)0x900B0018; + timerCLK = (unsigned int*)0x900C0004; + timerCTR = (unsigned int*)0x900C0008; + timerDIV = (unsigned int*)0x900C0080; + + *timerBUS &= ~(1 << 11); + *timerDIV = 0x0A; + *timerCTR = 0x82; + + osTime = *timerCLK; +} + +int osGetTimeMS() +{ + return (osTime - *timerCLK) / 33; +} + + +// input +touchpad_info_t* touchInfo; +touchpad_report_t touchReport; + +void touchInit() +{ + touchInfo = is_touchpad ? touchpad_getinfo() : NULL; +} + +bool osJoyReady(int index) +{ + return (index == 0); +} + +void osJoyVibrate(int index, float L, float R) {} + +void joyUpdate() +{ + Input::setJoyPos(0, jkL, vec2(0.0f, 0.0f)); + Input::setJoyPos(0, jkR, vec2(0.0f, 0.0f)); + Input::setJoyPos(0, jkLT, vec2(0.0f, 0.0f)); + Input::setJoyPos(0, jkRT, vec2(0.0f, 0.0f)); + + if (touchInfo) + { + touchpad_scan(&touchReport); + if (touchReport.contact) + { + float tx = float(touchReport.x) / float(touchInfo->width) * 2.0f - 1.0f; + float ty = float(touchReport.y) / float(touchInfo->height) * 2.0f - 1.0f; + Input::setJoyPos(0, jkL, vec2(tx, -ty)); + } + } + + Input::setJoyDown(0, jkA, isKeyPressed(KEY_NSPIRE_2)); + Input::setJoyDown(0, jkB, isKeyPressed(KEY_NSPIRE_3)); + Input::setJoyDown(0, jkX, isKeyPressed(KEY_NSPIRE_5)); + Input::setJoyDown(0, jkY, isKeyPressed(KEY_NSPIRE_6)); + Input::setJoyDown(0, jkLB, isKeyPressed(KEY_NSPIRE_7)); + Input::setJoyDown(0, jkRB, isKeyPressed(KEY_NSPIRE_9)); + Input::setJoyDown(0, jkL, false); + Input::setJoyDown(0, jkR, false); + Input::setJoyDown(0, jkStart, isKeyPressed(KEY_NSPIRE_ENTER)); + Input::setJoyDown(0, jkSelect, isKeyPressed(KEY_NSPIRE_MENU)); + + Input::setJoyDown(0, jkUp, isKeyPressed(KEY_NSPIRE_UP) || isKeyPressed(KEY_NSPIRE_LEFTUP) || isKeyPressed(KEY_NSPIRE_UPRIGHT)); + Input::setJoyDown(0, jkDown, isKeyPressed(KEY_NSPIRE_DOWN) || isKeyPressed(KEY_NSPIRE_RIGHTDOWN) || isKeyPressed(KEY_NSPIRE_DOWNLEFT)); + Input::setJoyDown(0, jkLeft, isKeyPressed(KEY_NSPIRE_LEFT) || isKeyPressed(KEY_NSPIRE_LEFTUP) || isKeyPressed(KEY_NSPIRE_DOWNLEFT)); + Input::setJoyDown(0, jkRight, isKeyPressed(KEY_NSPIRE_RIGHT) || isKeyPressed(KEY_NSPIRE_RIGHTDOWN) || isKeyPressed(KEY_NSPIRE_UPRIGHT)); +} + +unsigned short* osPalette() +{ + return (unsigned short*)0xC0000200; +} + +int main(void) +{ + if (!has_colors) + return 0; + + lcd_init(SCR_320x240_565); + + timerInit(); + touchInit(); + + contentDir[0] = saveDir[0] = cacheDir[0] = 0; + + strcpy(contentDir, "/documents/Games/OpenLara/"); + strcpy(saveDir, contentDir); + strcpy(cacheDir, contentDir); + + Stream::addPack("content.tns"); + + Core::width = SCREEN_WIDTH; + Core::height = SCREEN_HEIGHT; + + GAPI::swColor = new GAPI::ColorSW[SCREEN_WIDTH * SCREEN_HEIGHT]; + GAPI::resize(); + + Sound::channelsCount = 0; + + Game::init("DATA/LEVEL1.PHD"); + + while (!Core::isQuit) + { + joyUpdate(); + + if (Game::update()) + { + Game::render(); + + lcd_blit(GAPI::swColor, SCR_320x240_565); + } + + if (isKeyPressed(KEY_NSPIRE_ESC)) + { + Core::quit(); + } + } + + delete[] GAPI::swColor; + + //Game::deinit(); + + return 0; +} diff --git a/src/sound.h b/src/sound.h index 29e9c7e..558d8ae 100644 --- a/src/sound.h +++ b/src/sound.h @@ -1,15 +1,20 @@ #ifndef H_SOUND #define H_SOUND -#define DECODE_ADPCM -#define DECODE_IMA -#define DECODE_VAG -#define DECODE_XA +#ifdef _OS_TNS + #define NO_SOUND +#endif -#define DECODE_OGG +#ifndef NO_SOUND + #define DECODE_ADPCM + #define DECODE_IMA + #define DECODE_VAG + #define DECODE_XA + #define DECODE_OGG -#if !defined(_OS_PSP) && !defined(_OS_WEB) && !defined(_OS_PSV) && !defined(_OS_3DS) && !defined(_OS_XBOX) && !defined(_OS_XB1) - #define DECODE_MP3 + #if !defined(_OS_PSP) && !defined(_OS_WEB) && !defined(_OS_PSV) && !defined(_OS_3DS) && !defined(_OS_XBOX) && !defined(_OS_XB1) + #define DECODE_MP3 + #endif #endif #include "utils.h" @@ -846,7 +851,8 @@ namespace Sound { Sample(Stream *stream, const vec3 *pos, float volume, float pitch, int flags, int id) : uniquePtr(pos), decoder(NULL), volume(volume), volumeTarget(volume), volumeDelta(0.0f), pitch(pitch), flags(flags), id(id) { this->pos = pos ? *pos : vec3(0.0f); - + + #ifndef NO_SOUND uint32 fourcc; stream->read(fourcc); if (fourcc == FOURCC("RIFF")) { // wav @@ -898,6 +904,7 @@ namespace Sound { decoder = new VAG(stream); #endif } + #endif if (!decoder) delete stream; @@ -1171,6 +1178,7 @@ namespace Sound { } Sample* play(Stream *stream, const vec3 *pos = NULL, float volume = 1.0f, float pitch = 0.0f, int flags = 0, int id = - 1) { + #ifndef NO_SOUND OS_LOCK(lock); ASSERT(pitch >= 0.0f); @@ -1207,6 +1215,7 @@ namespace Sound { LOG("! no free channels\n"); } + #endif delete stream; return NULL; } diff --git a/src/ui.h b/src/ui.h index 5d08e04..f521d78 100644 --- a/src/ui.h +++ b/src/ui.h @@ -9,7 +9,7 @@ #define SUBTITLES_SPEED 0.1f #define TEXT_LINE_HEIGHT 18 -#ifdef _OS_PSV +#if defined(_OS_PSV) || defined(_OS_TNS) #define UI_SHOW_FPS #endif diff --git a/src/utils.h b/src/utils.h index bff2d02..df41744 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1532,7 +1532,7 @@ struct CLUT { ColorCLUT color[16]; }; -namespace String { +namespace StrUtils { void toLower(char *str) { if (!str) return; @@ -1868,7 +1868,7 @@ private: public: Stream(const char *name, const void *data, int size, Callback *callback = NULL, void *userData = NULL) : callback(callback), userData(userData), f(NULL), data((char*)data), name(NULL), size(size), pos(0), buffer(NULL) { - this->name = String::copy(name); + this->name = StrUtils::copy(name); } Stream(const char *name, Callback *callback = NULL, void *userData = NULL) : callback(callback), userData(userData), f(NULL), data(NULL), name(NULL), size(-1), pos(0), buffer(NULL), buffering(true), baseOffset(0) { @@ -1912,13 +1912,13 @@ public: fpos = 0; bufferIndex = -1; - this->name = String::copy(name); + this->name = StrUtils::copy(name); if (callback) callback(this, userData); return; } } - this->name = String::copy(name); + this->name = StrUtils::copy(name); #ifdef _OS_3DS /* TODO if (callback) { @@ -1964,14 +1964,14 @@ public: break; } - int32 len = utf16_to_utf8((uint8*)buf + pathLen, entry.name, String::length(entry.name)); + int32 len = utf16_to_utf8((uint8*)buf + pathLen, entry.name, StrUtils::length(entry.name)); buf[pathLen + len] = 0; if (entry.attributes & FS_ATTRIBUTE_DIRECTORY) { strcat(buf, "/"); readDirectory(archive, buf); } else { - fileList.push(String::copy(buf)); + fileList.push(StrUtils::copy(buf)); } } diff --git a/src/video.h b/src/video.h index 2aa3b51..552fcb7 100644 --- a/src/video.h +++ b/src/video.h @@ -5,6 +5,10 @@ #include "texture.h" #include "sound.h" +#ifdef _OS_TNS + #define NO_VIDEO +#endif + struct AC_ENTRY { uint8 code; uint8 skip; @@ -264,6 +268,9 @@ struct Video { nextChunk(0, 0); + #ifdef NO_SOUND + audioDecoder = NULL; + #else if (sfmt == 1) audioDecoder = new Sound::PCM(NULL, channels, rate, 0x7FFFFF, bps); // TR2 else if (sfmt == 101) { @@ -272,6 +279,7 @@ struct Video { else audioDecoder = new Sound::IMA(NULL, channels, rate); // TR3 } + #endif } virtual ~Escape() { @@ -678,6 +686,9 @@ struct Video { } virtual int decode(Sound::Frame *frames, int count) { + #ifdef NO_VIDEO + return 0; + #else if (!audioDecoder) return 0; if (bps != 4 && abs(curAudioChunk - curVideoChunk) > 1) { // sync with video chunk, doesn't work for IMA @@ -718,6 +729,7 @@ struct Video { } return count; + #endif } }; @@ -838,7 +850,11 @@ struct Video { channels = 2; freq = 37800; + #ifdef NO_SOUND + audioDecoder = NULL; + #else audioDecoder = new Sound::XA(NULL); + #endif } virtual ~STR() { @@ -1077,6 +1093,9 @@ struct Video { } virtual int decode(Sound::Frame *frames, int count) { + #ifdef NO_VIDEO + return 0; + #else if (!audioDecoder) return 0; Sound::XA *xa = (Sound::XA*)audioDecoder; @@ -1104,6 +1123,7 @@ struct Video { } return count; + #endif } };