summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/config.h2
-rw-r--r--src/render/Antennas.cpp139
-rw-r--r--src/render/Antennas.h25
-rw-r--r--src/rw.cpp1
4 files changed, 167 insertions, 0 deletions
diff --git a/src/config.h b/src/config.h
index ccd81023..94692fa0 100644
--- a/src/config.h
+++ b/src/config.h
@@ -50,4 +50,6 @@ enum Config {
NUMWEATHERS = 4,
NUMHOURS = 24,
+
+ NUMANTENNAS = 8,
};
diff --git a/src/render/Antennas.cpp b/src/render/Antennas.cpp
new file mode 100644
index 00000000..d564c196
--- /dev/null
+++ b/src/render/Antennas.cpp
@@ -0,0 +1,139 @@
+#include "common.h"
+#include "patcher.h"
+#include "Antennas.h"
+
+CAntenna CAntennas::aAntennas[NUMANTENNAS];
+
+void
+CAntennas::Init(void)
+{
+ int i;
+ for(i = 0; i < NUMANTENNAS; i++){
+ aAntennas[i].active = false;
+ aAntennas[i].updatedLastFrame = false;
+ }
+}
+
+// Free antennas that aren't used anymore
+void
+CAntennas::Update(void)
+{
+ int i;
+
+ for(i = 0; i < NUMANTENNAS; i++){
+ if(aAntennas[i].active && !aAntennas[i].updatedLastFrame)
+ aAntennas[i].active = false;
+ aAntennas[i].updatedLastFrame = false;
+ }
+}
+
+// Add a new one or update an old one
+void
+CAntennas::RegisterOne(uint32 id, CVector dir, CVector position, float length)
+{
+ int i, j;
+
+ for(i = 0; i < NUMANTENNAS; i++)
+ if(aAntennas[i].active && aAntennas[i].id == id)
+ break;
+
+ if(i >= NUMANTENNAS){
+ // not found, register new one
+
+ // find empty slot
+ for(i = 0; i < NUMANTENNAS; i++)
+ if(!aAntennas[i].active)
+ break;
+
+ // there is space
+ if(i < NUMANTENNAS){
+ aAntennas[i].active = true;
+ aAntennas[i].updatedLastFrame = true;
+ aAntennas[i].id = id;
+ aAntennas[i].segmentLength = length/6.0f;
+ for(j = 0; j < 6; j++){
+ aAntennas[i].pos[j] = position + dir*j*aAntennas[i].segmentLength;
+ aAntennas[i].speed[j] = CVector(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }else{
+ // found, update
+ aAntennas[i].Update(dir, position);
+ aAntennas[i].updatedLastFrame = true;
+ }
+}
+
+static RwIm3DVertex vertexbufferA[2];
+
+void
+CAntennas::Render(void)
+{
+ int i, j;
+
+ for(i = 0; i < NUMANTENNAS; i++){
+ if(!aAntennas[i].active)
+ continue;
+
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+
+ for(j = 0; j < 5; j++){
+ RwIm3DVertexSetRGBA(&vertexbufferA[0], 200, 200, 200, 100);
+ RwIm3DVertexSetPos(&vertexbufferA[0],
+ aAntennas[i].pos[j].x,
+ aAntennas[i].pos[j].y,
+ aAntennas[i].pos[j].z);
+ RwIm3DVertexSetRGBA(&vertexbufferA[1], 200, 200, 200, 100);
+ RwIm3DVertexSetPos(&vertexbufferA[1],
+ aAntennas[i].pos[j+1].x,
+ aAntennas[i].pos[j+1].y,
+ aAntennas[i].pos[j+1].z);
+
+ // LittleTest();
+ if(RwIm3DTransform(vertexbufferA, 2, nil, 0)){
+ RwIm3DRenderLine(0, 1);
+ RwIm3DEnd();
+ }
+ }
+ }
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+}
+
+void
+CAntenna::Update(CVector dir, CVector basepos)
+{
+ int i;
+
+ pos[0] = basepos;
+ pos[1] = basepos + dir*segmentLength;
+
+ for(i = 2; i < 6; i++){
+ CVector basedir = pos[i-1] - pos[i-2];
+ CVector newdir = pos[i] - pos[i-1] + // drag along
+ dir*0.1f + // also drag up a bit for stiffness
+ speed[i]; // and keep moving
+ newdir.Normalise();
+ newdir *= segmentLength;
+ CVector newpos = pos[i-1] + (basedir + newdir)/2.0f;
+ speed[i] = (newpos - pos[i])*0.9f;
+ pos[i] = newpos;
+ }
+}
+
+STARTPATCHES
+ InjectHook(0x4F64D0, &CAntennas::Init, PATCH_JUMP);
+ InjectHook(0x4F6550, &CAntennas::Update, PATCH_JUMP);
+ InjectHook(0x4F66C0, &CAntennas::RegisterOne, PATCH_JUMP);
+ InjectHook(0x4F6590, &CAntennas::Render, PATCH_JUMP);
+ InjectHook(0x4F6830, &CAntenna::Update, PATCH_JUMP);
+
+ // give to cheetah for testing
+// Patch<int>(0x535B50+1, 105);
+// Patch<float>(0x535B57+7, -0.84);
+// Patch<float>(0x535B74+7, 0.78);
+// Patch<float>(0x535B69+7, 0.24);
+ENDPATCHES
diff --git a/src/render/Antennas.h b/src/render/Antennas.h
new file mode 100644
index 00000000..47cb1dad
--- /dev/null
+++ b/src/render/Antennas.h
@@ -0,0 +1,25 @@
+#pragma once
+
+class CAntenna
+{
+public:
+ bool active;
+ bool updatedLastFrame;
+ uint32 id;
+ float segmentLength;
+ CVector pos[6];
+ CVector speed[6];
+
+ void Update(CVector dir, CVector pos);
+};
+
+class CAntennas
+{
+ // no need to use game's array
+ static CAntenna aAntennas[NUMANTENNAS];
+public:
+ static void Init(void);
+ static void Update(void);
+ static void RegisterOne(uint32 id, CVector dir, CVector position, float length);
+ static void Render(void);
+};
diff --git a/src/rw.cpp b/src/rw.cpp
index b0e838ac..d202b2ce 100644
--- a/src/rw.cpp
+++ b/src/rw.cpp
@@ -226,6 +226,7 @@ WRAPPER RwBool RwIm2DRenderIndexedPrimitive(RwPrimitiveType, RwIm2DVertex*, RwIn
WRAPPER RwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex *indices, RwInt32 numIndices) { EAXJMP(0x5B6820); }
WRAPPER void *RwIm3DTransform(RwIm3DVertex *pVerts, RwUInt32 numVerts, RwMatrix *ltm, RwUInt32 flags) { EAXJMP(0x5B6720); }
+WRAPPER RwBool RwIm3DRenderLine(RwInt32 vert1, RwInt32 vert2) { EAXJMP(0x5B6980); }
WRAPPER RwBool RwIm3DEnd(void) { EAXJMP(0x5B67F0); }
static uint32_t _rwObjectHasFrameSetFrame_A = AddressByVersion<uint32_t>(0x5BC950, 0x5BCC10, 0x5C1820, 0x660CC0, 0x660D10, 0x65FC70);