summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/AnimViewer.cpp10
-rw-r--r--src/core/Cam.cpp14
-rw-r--r--src/core/Camera.cpp36
-rw-r--r--src/core/Camera.h4
-rw-r--r--src/core/CdStream.cpp10
-rw-r--r--src/core/CdStreamPosix.cpp4
-rw-r--r--src/core/Collision.cpp3290
-rw-r--r--src/core/Collision.h254
-rw-r--r--src/core/ControllerConfig.cpp244
-rw-r--r--src/core/FileLoader.cpp40
-rw-r--r--src/core/Frontend.cpp1272
-rw-r--r--src/core/Frontend.h121
-rw-r--r--src/core/Frontend_PS2.cpp18
-rw-r--r--src/core/Frontend_PS2.h22
-rw-r--r--src/core/Game.cpp610
-rw-r--r--src/core/MenuScreens.cpp14
-rw-r--r--src/core/MenuScreensCustom.cpp878
-rw-r--r--src/core/Pad.cpp27
-rw-r--r--src/core/Pad.h3
-rw-r--r--src/core/Pools.cpp19
-rw-r--r--src/core/Streaming.cpp174
-rw-r--r--src/core/Streaming.h2
-rw-r--r--src/core/TempColModels.cpp297
-rw-r--r--src/core/TempColModels.h23
-rw-r--r--src/core/World.cpp52
-rw-r--r--src/core/ZoneCull.cpp1165
-rw-r--r--src/core/ZoneCull.h32
-rw-r--r--src/core/config.h107
-rw-r--r--src/core/main.cpp398
-rw-r--r--src/core/main.h4
-rw-r--r--src/core/re3.cpp511
-rw-r--r--src/core/templates.h28
-rw-r--r--src/core/vu0Collision.dsm21
-rw-r--r--src/core/vu0Collision_1.s610
-rw-r--r--src/core/vu0Collision_2.s191
35 files changed, 4352 insertions, 6153 deletions
diff --git a/src/core/AnimViewer.cpp b/src/core/AnimViewer.cpp
index c8d8cb56..b8354d93 100644
--- a/src/core/AnimViewer.cpp
+++ b/src/core/AnimViewer.cpp
@@ -49,7 +49,7 @@ CAnimViewer::Render(void) {
if (pTarget) {
#ifdef FIX_BUGS
#ifdef PED_SKIN
- if(pTarget->IsPed())
+ if(pTarget->IsPed() && IsClumpSkinned(pTarget->GetClump()))
((CPed*)pTarget)->UpdateRpHAnim();
#endif
#endif
@@ -100,6 +100,9 @@ CAnimViewer::Initialise(void) {
CRadar::Initialise();
CRadar::LoadTextures();
CVehicleModelInfo::LoadVehicleColours();
+#ifdef FIX_BUGS
+ CVehicleModelInfo::LoadEnvironmentMaps();
+#endif
CAnimManager::LoadAnimFiles();
CWorld::PlayerInFocus = 0;
CWeapon::InitialiseWeapons();
@@ -294,7 +297,12 @@ CAnimViewer::Update(void)
if (pTarget->IsVehicle() || pTarget->IsPed() || pTarget->IsObject()) {
((CPhysical*)pTarget)->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
}
+#ifdef FIX_BUGS
+ // so we don't end up in the water
+ pTarget->GetMatrix().GetPosition().z = 10.0f;
+#else
pTarget->GetMatrix().GetPosition().z = 0.0f;
+#endif
if (modelInfo->GetModelType() == MITYPE_PED) {
((CPed*)pTarget)->bKindaStayInSamePlace = true;
diff --git a/src/core/Cam.cpp b/src/core/Cam.cpp
index 3e016667..b20e6db3 100644
--- a/src/core/Cam.cpp
+++ b/src/core/Cam.cpp
@@ -263,9 +263,11 @@ CCam::Process(void)
case MODE_FIGHT_CAM_RUNABOUT:
Process_1rstPersonPedOnPC(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
+#ifdef GTA_SCENE_EDIT
case MODE_EDITOR:
Process_Editor(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);
break;
+#endif
default:
Source = CVector(0.0f, 0.0f, 0.0f);
Front = CVector(0.0f, 1.0f, 0.0f);
@@ -2570,7 +2572,7 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
ResetStatics = false;
}
-#ifndef GTA3_1_1_PATCH
+#if GTA_VERSION < GTA3_PC_11
((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(&HeadPos, PED_HEAD);
Source = HeadPos;
Source.z += 0.1f;
@@ -2605,7 +2607,7 @@ CCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)
if(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);
else if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
HeadPos.x = 0.0f;
HeadPos.y = 0.0f;
HeadPos.z = 0.0f;
@@ -3919,6 +3921,7 @@ CCam::Process_Debug(const CVector&, float, float, float)
}
#endif
+#ifdef GTA_SCENE_EDIT
void
CCam::Process_Editor(const CVector&, float, float, float)
{
@@ -3997,6 +4000,7 @@ CCam::Process_Editor(const CVector&, float, float, float)
sprintf(str, "Look@: %f, Look@: %f, Look@: %f ", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);
}
}
+#endif
void
CCam::Process_ModelView(const CVector &CameraTarget, float, float, float)
@@ -4010,6 +4014,12 @@ CCam::Process_ModelView(const CVector &CameraTarget, float, float, float)
Distance += CPad::GetPad(0)->GetLeftStickY()/1000.0f;
else
Distance += CPad::GetPad(0)->GetLeftStickY() * ((Distance - 10.0f)/20.0f + 1.0f) / 1000.0f;
+#ifdef IMPROVED_CAMERA
+ if(CPad::GetPad(0)->GetLeftMouse()){
+ Distance += DEGTORAD(CPad::GetPad(0)->GetMouseY()/2.0f);
+ Angle += DEGTORAD(CPad::GetPad(0)->GetMouseX()/2.0f);
+ }
+#endif
if(Distance < 1.5f)
Distance = 1.5f;
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 13d03213..4551e36f 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -74,7 +74,7 @@ bool bDidWeProcessAnyCinemaCam;
CCamera::CCamera(void)
{
-#if defined(GTA3_1_1_PATCH) || defined(FIX_BUGS)
+#if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS)
m_fMouseAccelHorzntl = 0.0025f;
m_fMouseAccelVertical = 0.003f;
#endif
@@ -88,15 +88,15 @@ CCamera::CCamera(float)
void
CCamera::Init(void)
{
-#if defined(GTA3_1_1_PATCH) || defined(FIX_BUGS)
+#if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS)
float fMouseAccelHorzntl = m_fMouseAccelHorzntl;
float fMouseAccelVertical = m_fMouseAccelVertical;
#endif
#ifdef PS2_MENU
- if ( !TheMemoryCard.m_bWantToLoad && !FrontEndMenuManager.m_bWantToRestart ) {
+ if ( !TheMemoryCard.m_bWantToLoad && !FrontEndMenuManager.m_bWantToRestart )
#endif
-
+ {
#ifdef FIX_BUGS
static const CCamera DummyCamera = CCamera(0.f);
*this = DummyCamera;
@@ -104,15 +104,13 @@ CCamera::Init(void)
memset(this, 0, sizeof(CCamera)); // getting rid of vtable, eh?
#endif
- #if defined(GTA3_1_1_PATCH) || defined(FIX_BUGS)
+ #if GTA_VERSION >= GTA3_PC_11 || defined(FIX_BUGS)
m_fMouseAccelHorzntl = fMouseAccelHorzntl;
m_fMouseAccelVertical = fMouseAccelVertical;
#endif
m_pRwCamera = nil;
-#ifdef PS2_MENU
}
-#endif
m_1rstPersonRunCloseToAWall = false;
m_fPositionAlongSpline = 0.0f;
@@ -123,7 +121,7 @@ CCamera::Init(void)
Cams[0].Mode = CCam::MODE_FOLLOWPED;
Cams[1].Mode = CCam::MODE_FOLLOWPED;
unknown = 0;
- m_bJustJumpedOutOf1stPersonBecauseOfTarget = false;
+ m_bUnknown = false;
ClearPlayerWeaponMode();
m_bInATunnelAndABigVehicle = false;
m_iModeObbeCamIsInForCar = OBBE_INVALID;
@@ -237,7 +235,7 @@ CCamera::Init(void)
m_uiTransitionState = 0;
m_uiTimeTransitionStart = 0;
m_bLookingAtPlayer = true;
-#if !defined(GTA3_1_1_PATCH) && !defined(FIX_BUGS)
+#if GTA_VERSION < GTA3_PC_11 && !defined(FIX_BUGS)
m_fMouseAccelHorzntl = 0.0025f;
m_fMouseAccelVertical = 0.003f;
#endif
@@ -715,14 +713,18 @@ CCamera::Process(void)
DistanceToWater = CWaterLevel::CalcDistanceToWater(GetPosition().x, GetPosition().y);
// LOD dist
- if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier())
- LODDistMultiplier = 70.0f/CDraw::GetFOV() * CDraw::GetAspectRatio()/(4.0f/3.0f);
- else
+ if(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier()){
+ LODDistMultiplier = 70.0f/CDraw::GetFOV();
+#ifndef FIX_BUGS
+ // makes no sense and gone in VC
+ LODDistMultiplier *= CDraw::GetAspectRatio()/(4.0f/3.0f);
+#endif
+ }else
LODDistMultiplier = 1.0f;
- // missing on PS2
+#if GTA_VERSION > GTA3_PS2_160
GenerationDistMultiplier = LODDistMultiplier;
LODDistMultiplier *= CRenderer::ms_lodDistScale;
- //
+#endif
// Keep track of speed
if(m_bJustInitalised || m_bJust_Switched){
@@ -1574,8 +1576,10 @@ CCamera::CamControl(void)
switchByJumpCut = true;
}
}
+#ifdef GTA_SCENE_EDIT
if(CSceneEdit::m_bEditOn)
ReqMode = CCam::MODE_EDITOR;
+#endif
if((m_uiTransitionState == 0 || switchByJumpCut) && ReqMode != Cams[ActiveCam].Mode){
if(switchByJumpCut){
@@ -3398,10 +3402,10 @@ CCamera::Fade(float timeout, int16 direction)
m_fTimeToFadeMusic = timeout;
m_uiFadeTimeStartedMusic = CTimer::GetTimeInMilliseconds();
// Not on PS2
- if(!m_bJustJumpedOutOf1stPersonBecauseOfTarget && m_iMusicFadingDirection == FADE_OUT){
+ if(!m_bUnknown && m_iMusicFadingDirection == FADE_OUT){
unknown++;
if(unknown >= 2){
- m_bJustJumpedOutOf1stPersonBecauseOfTarget = true;
+ m_bUnknown = true;
unknown = 0;
}else
m_bMoveCamToAvoidGeom = true;
diff --git a/src/core/Camera.h b/src/core/Camera.h
index dd78d952..ca1bd135 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -213,7 +213,9 @@ public:
void PrintMode(void);
void Process_Debug(const CVector&, float, float, float);
+#ifdef GTA_SCENE_EDIT
void Process_Editor(const CVector&, float, float, float);
+#endif
void Process_ModelView(const CVector &CameraTarget, float, float, float);
void Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float);
void Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float);
@@ -348,7 +350,7 @@ public:
bool m_bcutsceneFinished;
bool m_bCullZoneChecksOn;
bool m_bFirstPersonBeingUsed;
- bool m_bJustJumpedOutOf1stPersonBecauseOfTarget;
+ bool m_bUnknown;
bool m_bIdleOn;
bool m_bInATunnelAndABigVehicle;
bool m_bInitialNodeFound;
diff --git a/src/core/CdStream.cpp b/src/core/CdStream.cpp
index c11fb72a..f987dea5 100644
--- a/src/core/CdStream.cpp
+++ b/src/core/CdStream.cpp
@@ -5,6 +5,7 @@
#include "CdStream.h"
#include "rwcore.h"
#include "RwHelper.h"
+#include "MemoryMgr.h"
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
@@ -242,8 +243,15 @@ CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
else
return STREAM_SUCCESS;
}
-
+
+#ifdef BIG_IMG
+ LARGE_INTEGER liDistanceToMove;
+ liDistanceToMove.QuadPart = _GET_OFFSET(offset);
+ liDistanceToMove.QuadPart *= CDSTREAM_SECTOR_SIZE;
+ SetFilePointerEx(hImage, liDistanceToMove, nil, FILE_BEGIN);
+#else
SetFilePointer(hImage, _GET_OFFSET(offset) * CDSTREAM_SECTOR_SIZE, nil, FILE_BEGIN);
+#endif
DWORD NumberOfBytesRead;
diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp
index 5c8d1b16..0854d850 100644
--- a/src/core/CdStreamPosix.cpp
+++ b/src/core/CdStreamPosix.cpp
@@ -16,7 +16,7 @@
#include "CdStream.h"
#include "rwcore.h"
-#include "RwHelper.h"
+#include "MemoryMgr.h"
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
@@ -429,7 +429,7 @@ void *CdStreamThread(void *param)
ASSERT(pChannel->hFile >= 0);
ASSERT(pChannel->pBuffer != nil );
- lseek(pChannel->hFile, pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE, SEEK_SET);
+ lseek(pChannel->hFile, (size_t)pChannel->nSectorOffset * (size_t)CDSTREAM_SECTOR_SIZE, SEEK_SET);
if (read(pChannel->hFile, pChannel->pBuffer, pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE) == -1) {
// pChannel->nSectorsToRead == 0 at this point means we wanted to flush channel
// STREAM_WAITING is a little hack to make CStreaming not process this data
diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp
deleted file mode 100644
index d8603cd8..00000000
--- a/src/core/Collision.cpp
+++ /dev/null
@@ -1,3290 +0,0 @@
-#include "common.h"
-
-#include "VuVector.h"
-#include "main.h"
-#include "Lists.h"
-#include "Game.h"
-#include "Zones.h"
-#include "General.h"
-#include "ZoneCull.h"
-#include "World.h"
-#include "Entity.h"
-#include "Train.h"
-#include "Streaming.h"
-#include "Pad.h"
-#include "DMAudio.h"
-#include "Population.h"
-#include "FileLoader.h"
-#include "Replay.h"
-#include "CutsceneMgr.h"
-#include "RenderBuffer.h"
-#include "SurfaceTable.h"
-#include "Lines.h"
-#include "Collision.h"
-#include "Frontend.h"
-
-
-// TODO: where do these go?
-
-#ifdef VU_COLLISION
-
-struct VuTriangle
-{
- // Compressed int16 but unpacked
-#ifdef GTA_PS2
- uint128 v0;
- uint128 v1;
- uint128 v2;
- uint128 plane;
-#else
- int32 v0[4];
- int32 v1[4];
- int32 v2[4];
- int32 plane[4];
-#endif
-};
-
-#ifndef GTA_PS2
-static int16 vi01;
-static CVuVector vf01;
-static CVuVector vf02;
-static CVuVector vf03;
-
-CVuVector
-DistanceBetweenSphereAndLine(const CVuVector &center, const CVuVector &p0, const CVuVector &line)
-{
- // center VF12
- // p0 VF14
- // line VF15
- CVuVector ret; // VF16
- CVuVector p1 = p0+line;
- CVuVector dist0 = center - p0; // VF20
- CVuVector dist1 = center - p1; // VF25
- float lenSq = line.MagnitudeSqr(); // VF21
- float distSq0 = dist0.MagnitudeSqr(); // VF22
- float distSq1 = dist1.MagnitudeSqr();
- float dot = DotProduct(dist0, line); // VF23
- if(dot < 0.0f){
- // not above line, closest to p0
- ret = p0;
- ret.w = distSq0;
- return ret;
- }
- float t = dot/lenSq; // param of nearest point on infinite line
- if(t > 1.0f){
- // not above line, closest to p1
- ret = p1;
- ret.w = distSq1;
- return ret;
- }
- // closest to line
- ret = p0 + line*t;
- ret.w = (ret - center).MagnitudeSqr();
- return ret;
-}
-inline int SignFlags(const CVector &v)
-{
- int f = 0;
- if(v.x < 0.0f) f |= 1;
- if(v.y < 0.0f) f |= 2;
- if(v.z < 0.0f) f |= 4;
- return f;
-}
-#endif
-
-extern "C" void
-LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1,
- const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
- const CVuVector &plane)
-{
-#ifdef GTA_PS2
- __asm__ volatile (
- ".set noreorder\n"
- "lqc2 vf12, 0x0(%0)\n"
- "lqc2 vf13, 0x0(%1)\n"
- "lqc2 vf14, 0x0(%2)\n"
- "lqc2 vf15, 0x0(%3)\n"
- "lqc2 vf16, 0x0(%4)\n"
- "lqc2 vf17, 0x0(%5)\n"
- "vcallms Vu0LineToTriangleCollisionStart\n"
- ".set reorder\n"
- :
- : "r" (&p0), "r" (&p1), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
- );
-#else
- float dot0 = DotProduct(plane, p0);
- float dot1 = DotProduct(plane, p1);
- float dist0 = plane.w - dot0;
- float dist1 = plane.w - dot1;
-
- // if points are on the same side, no collision
- if(dist0 * dist1 > 0.0f){
- vi01 = 0;
- return;
- }
-
- CVuVector diff = p1 - p0;
- float t = dist0/(dot1 - dot0);
- CVuVector p = p0 + diff*t;
- p.w = 0.0f;
- vf01 = p;
- vf03.x = t;
-
- // Check if point is inside
- CVector cross1 = CrossProduct(p-v0, v1-v0);
- CVector cross2 = CrossProduct(p-v1, v2-v1);
- CVector cross3 = CrossProduct(p-v2, v0-v2);
- // Only check relevant directions
- int flagmask = 0;
- if(Abs(plane.x) > 0.5f) flagmask |= 1;
- if(Abs(plane.y) > 0.5f) flagmask |= 2;
- if(Abs(plane.z) > 0.5f) flagmask |= 4;
- int flags1 = SignFlags(cross1) & flagmask;
- int flags2 = SignFlags(cross2) & flagmask;
- int flags3 = SignFlags(cross3) & flagmask;
- // inside if on the same side of all edges
- if(flags1 != flags2 || flags1 != flags3){
- vi01 = 0;
- return;
- }
- vi01 = 1;
- vf02 = plane;
- return;
-#endif
-}
-
-extern "C" void
-LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri)
-{
-#ifdef GTA_PS2
- __asm__ volatile (
- ".set noreorder\n"
- "lqc2 vf12, 0x0(%0)\n"
- "lqc2 vf13, 0x0(%1)\n"
- "lqc2 vf14, 0x0(%2)\n"
- "lqc2 vf15, 0x10(%2)\n"
- "lqc2 vf16, 0x20(%2)\n"
- "lqc2 vf17, 0x30(%2)\n"
- "vcallms Vu0LineToTriangleCollisionCompressedStart\n"
- ".set reorder\n"
- :
- : "r" (&p0), "r" (&p1), "r" (&tri)
- );
-#else
- CVuVector v0, v1, v2, plane;
- v0.x = tri.v0[0]/128.0f;
- v0.y = tri.v0[1]/128.0f;
- v0.z = tri.v0[2]/128.0f;
- v0.w = tri.v0[3]/128.0f;
- v1.x = tri.v1[0]/128.0f;
- v1.y = tri.v1[1]/128.0f;
- v1.z = tri.v1[2]/128.0f;
- v1.w = tri.v1[3]/128.0f;
- v2.x = tri.v2[0]/128.0f;
- v2.y = tri.v2[1]/128.0f;
- v2.z = tri.v2[2]/128.0f;
- v2.w = tri.v2[3]/128.0f;
- plane.x = tri.plane[0]/4096.0f;
- plane.y = tri.plane[1]/4096.0f;
- plane.z = tri.plane[2]/4096.0f;
- plane.w = tri.plane[3]/128.0f;
- LineToTriangleCollision(p0, p1, v0, v1, v2, plane);
-#endif
-}
-
-extern "C" void
-SphereToTriangleCollision(const CVuVector &sph,
- const CVuVector &v0, const CVuVector &v1, const CVuVector &v2,
- const CVuVector &plane)
-{
-#ifdef GTA_PS2
- __asm__ volatile (
- ".set noreorder\n"
- "lqc2 vf12, 0x0(%0)\n"
- "lqc2 vf14, 0x0(%1)\n"
- "lqc2 vf15, 0x0(%2)\n"
- "lqc2 vf16, 0x0(%3)\n"
- "lqc2 vf17, 0x0(%4)\n"
- "vcallms Vu0SphereToTriangleCollisionStart\n"
- ".set reorder\n"
- :
- : "r" (&sph), "r" (&v0), "r" (&v1), "r" (&v2), "r" (&plane)
- );
-#else
- float planedist = DotProduct(plane, sph) - plane.w; // VF02
- if(Abs(planedist) > sph.w){
- vi01 = 0;
- return;
- }
- // point on plane
- CVuVector p = sph - planedist*plane;
- p.w = 0.0f;
- vf01 = p;
- planedist = Abs(planedist);
- // edges
- CVuVector v01 = v1 - v0;
- CVuVector v12 = v2 - v1;
- CVuVector v20 = v0 - v2;
- // VU code calculates normal again for some weird reason...
- // Check sides of point
- CVector cross1 = CrossProduct(p-v0, v01);
- CVector cross2 = CrossProduct(p-v1, v12);
- CVector cross3 = CrossProduct(p-v2, v20);
- // Only check relevant directions
- int flagmask = 0;
- if(Abs(plane.x) > 0.1f) flagmask |= 1;
- if(Abs(plane.y) > 0.1f) flagmask |= 2;
- if(Abs(plane.z) > 0.1f) flagmask |= 4;
- int nflags = SignFlags(plane) & flagmask;
- int flags1 = SignFlags(cross1) & flagmask;
- int flags2 = SignFlags(cross2) & flagmask;
- int flags3 = SignFlags(cross3) & flagmask;
- int testcase = 0;
- CVuVector closest(0.0f, 0.0f, 0.0f); // VF04
- if(flags1 == nflags){
- closest += v2;
- testcase++;
- }
- if(flags2 == nflags){
- closest += v0;
- testcase++;
- }
- if(flags3 == nflags){
- closest += v1;
- testcase++;
- }
- if(testcase == 3){
- // inside triangle - dist to plane already checked
- vf02 = plane;
- vf02.w = vf03.x = planedist;
- vi01 = 1;
- }else if(testcase == 1){
- // outside two sides - closest to point opposide inside edge
- vf01 = closest;
- vf02 = sph - closest;
- float distSq = vf02.MagnitudeSqr();
- vi01 = sph.w*sph.w > distSq;
- vf03.x = Sqrt(distSq);
- vf02 *= 1.0f/vf03.x;
- }else{
- // inside two sides - closest to third edge
- if(flags1 != nflags)
- closest = DistanceBetweenSphereAndLine(sph, v0, v01);
- else if(flags2 != nflags)
- closest = DistanceBetweenSphereAndLine(sph, v1, v12);
- else
- closest = DistanceBetweenSphereAndLine(sph, v2, v20);
- vi01 = sph.w*sph.w > closest.w;
- vf01 = closest;
- vf02 = sph - closest;
- vf03.x = Sqrt(closest.w);
- vf02 *= 1.0f/vf03.x;
- }
-#endif
-}
-
-extern "C" void
-SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri)
-{
-#ifdef GTA_PS2
- __asm__ volatile (
- ".set noreorder\n"
- "lqc2 vf12, 0x0(%0)\n"
- "lqc2 vf14, 0x0(%1)\n"
- "lqc2 vf15, 0x10(%1)\n"
- "lqc2 vf16, 0x20(%1)\n"
- "lqc2 vf17, 0x30(%1)\n"
- "vcallms Vu0SphereToTriangleCollisionCompressedStart\n"
- ".set reorder\n"
- :
- : "r" (&sph), "r" (&tri)
- );
-#else
- CVuVector v0, v1, v2, plane;
- v0.x = tri.v0[0]/128.0f;
- v0.y = tri.v0[1]/128.0f;
- v0.z = tri.v0[2]/128.0f;
- v0.w = tri.v0[3]/128.0f;
- v1.x = tri.v1[0]/128.0f;
- v1.y = tri.v1[1]/128.0f;
- v1.z = tri.v1[2]/128.0f;
- v1.w = tri.v1[3]/128.0f;
- v2.x = tri.v2[0]/128.0f;
- v2.y = tri.v2[1]/128.0f;
- v2.z = tri.v2[2]/128.0f;
- v2.w = tri.v2[3]/128.0f;
- plane.x = tri.plane[0]/4096.0f;
- plane.y = tri.plane[1]/4096.0f;
- plane.z = tri.plane[2]/4096.0f;
- plane.w = tri.plane[3]/128.0f;
- SphereToTriangleCollision(sph, v0, v1, v2, plane);
-#endif
-}
-
-inline int
-GetVUresult(void)
-{
-#ifdef GTA_PS2
- int ret;
- __asm__ volatile (
- "cfc2.i %0,vi01\n" // .i important! wait for VU0 to finish
- : "=r" (ret)
- );
- return ret;
-#else
- return vi01;
-#endif
-}
-
-inline int
-GetVUresult(CVuVector &point, CVuVector &normal, float &dist)
-{
-#ifdef GTA_PS2
- int ret;
- __asm__ volatile (
- "cfc2.i %0,vi01\n" // .i important! wait for VU0 to finish
- "sqc2 vf01,(%1)\n"
- "sqc2 vf02,(%2)\n"
- "qmfc2 $12,vf03\n"
- "sw $12,(%3)\n"
- : "=r" (ret)
- : "r" (&point), "r" (&normal), "r" (&dist)
- : "$12"
- );
- return ret;
-#else
- point = vf01;
- normal = vf02;
- dist = vf03.x;
- return vi01;
-#endif
-}
-
-#endif
-
-
-enum Direction
-{
- DIR_X_POS,
- DIR_X_NEG,
- DIR_Y_POS,
- DIR_Y_NEG,
- DIR_Z_POS,
- DIR_Z_NEG,
-};
-
-eLevelName CCollision::ms_collisionInMemory;
-CLinkList<CColModel*> CCollision::ms_colModelCache;
-
-void
-CCollision::Init(void)
-{
- ms_colModelCache.Init(NUMCOLCACHELINKS);
- ms_collisionInMemory = LEVEL_GENERIC;
-}
-
-void
-CCollision::Shutdown(void)
-{
- ms_colModelCache.Shutdown();
-}
-
-void
-CCollision::Update(void)
-{
- CVector playerCoors;
- playerCoors = FindPlayerCoors();
- eLevelName level = CTheZones::m_CurrLevel;
- bool forceLevelChange = false;
-
- if(CTimer::GetTimeInMilliseconds() < 2000 || CCutsceneMgr::IsCutsceneProcessing())
- return;
-
- // hardcode a level if there are no zones
- if(level == LEVEL_GENERIC){
- if(CGame::currLevel == LEVEL_INDUSTRIAL &&
- playerCoors.x < 400.0f){
- level = LEVEL_COMMERCIAL;
- forceLevelChange = true;
- }else if(CGame::currLevel == LEVEL_SUBURBAN &&
- playerCoors.x > -450.0f && playerCoors.y < -1400.0f){
- level = LEVEL_COMMERCIAL;
- forceLevelChange = true;
- }else{
- if(playerCoors.x > 800.0f){
- level = LEVEL_INDUSTRIAL;
- forceLevelChange = true;
- }else if(playerCoors.x < -800.0f){
- level = LEVEL_SUBURBAN;
- forceLevelChange = true;
- }
- }
- }
- if(level != LEVEL_GENERIC && level != CGame::currLevel)
- CGame::currLevel = level;
- if(ms_collisionInMemory != CGame::currLevel)
- LoadCollisionWhenINeedIt(forceLevelChange);
- CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
-}
-
-eLevelName
-GetCollisionInSectorList(CPtrList &list)
-{
- CPtrNode *node;
- CEntity *e;
- int level;
-
- for(node = list.first; node; node = node->next){
- e = (CEntity*)node->item;
- level = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel()->level;
- if(level != LEVEL_GENERIC)
- return (eLevelName)level;
- }
- return LEVEL_GENERIC;
-}
-
-// Get a level this sector is in based on collision models
-eLevelName
-GetCollisionInSector(CSector &sect)
-{
- int level;
-
- level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS]);
- if(level == LEVEL_GENERIC)
- level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);
- if(level == LEVEL_GENERIC)
- level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS]);
- if(level == LEVEL_GENERIC)
- level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS_OVERLAP]);
- if(level == LEVEL_GENERIC)
- level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES]);
- if(level == LEVEL_GENERIC)
- level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES_OVERLAP]);
- return (eLevelName)level;
-}
-
-void
-CCollision::LoadCollisionWhenINeedIt(bool forceChange)
-{
- eLevelName level, l;
- bool multipleLevels;
- CVector playerCoors;
- CVehicle *veh;
- CEntryInfoNode *ei;
- int sx, sy;
- int xmin, xmax, ymin, ymax;
- int x, y;
-
- level = LEVEL_GENERIC;
-
- playerCoors = FindPlayerCoors();
- sx = CWorld::GetSectorIndexX(playerCoors.x);
- sy = CWorld::GetSectorIndexY(playerCoors.y);
- multipleLevels = false;
-
- veh = FindPlayerVehicle();
- if(veh && veh->IsTrain()){
- if(((CTrain*)veh)->m_nDoorState != TRAIN_DOOR_OPEN)
- return;
- }else if(playerCoors.z < -4.0f && !CCullZones::DoINeedToLoadCollision())
- return;
-
- // Figure out whose level's collisions we're most likely to be interested in
- if(!forceChange){
- if(veh && veh->IsBoat()){
- // on water we expect to be between levels
- multipleLevels = true;
- }else{
- xmin = Max(sx - 1, 0);
- xmax = Min(sx + 1, NUMSECTORS_X-1);
- ymin = Max(sy - 1, 0);
- ymax = Min(sy + 1, NUMSECTORS_Y-1);
-
- for(x = xmin; x <= xmax; x++)
- for(y = ymin; y <= ymax; y++){
- l = GetCollisionInSector(*CWorld::GetSector(x, y));
- if(l != LEVEL_GENERIC){
- if(level == LEVEL_GENERIC)
- level = l;
- if(level != l)
- multipleLevels = true;
- }
- }
- }
-
- if(multipleLevels && veh && veh->IsBoat())
- for(ei = veh->m_entryInfoList.first; ei; ei = ei->next){
- level = GetCollisionInSector(*ei->sector);
- if(level != LEVEL_GENERIC)
- break;
- }
- }
-
- if (level == CGame::currLevel || forceChange) {
-#ifdef FIX_BUGS
- CTimer::Suspend();
-#else
- CTimer::Stop();
-#endif
- ISLAND_LOADING_IS(LOW)
- {
- DMAudio.SetEffectsFadeVol(0);
- CPad::StopPadsShaking();
- LoadCollisionScreen(CGame::currLevel);
- DMAudio.Service();
- }
-
- CPopulation::DealWithZoneChange(ms_collisionInMemory, CGame::currLevel, false);
-
- ISLAND_LOADING_ISNT(HIGH)
- {
- CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL);
- CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL);
- CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
- }
- ISLAND_LOADING_IS(LOW)
- {
- CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);
- CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);
- CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);
- CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
- CStreaming::RemoveUnusedModelsInLoadedList();
- CGame::TidyUpMemory(true, true);
- CFileLoader::LoadCollisionFromDatFile(CGame::currLevel);
- }
-
- ms_collisionInMemory = CGame::currLevel;
- CReplay::EmptyReplayBuffer();
- ISLAND_LOADING_IS(LOW)
- {
- if (CGame::currLevel != LEVEL_GENERIC)
- LoadSplash(GetLevelSplashScreen(CGame::currLevel));
- CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
- CStreaming::RemoveUnusedBuildings(CGame::currLevel);
- CStreaming::RequestBigBuildings(CGame::currLevel);
- }
-#ifdef NO_ISLAND_LOADING
- else if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_MEDIUM)
- CStreaming::RequestIslands(CGame::currLevel);
-#endif
- CStreaming::LoadAllRequestedModels(true);
-
- ISLAND_LOADING_IS(LOW)
- {
- CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
-
- CGame::TidyUpMemory(true, true);
- }
-#ifdef FIX_BUGS
- CTimer::Resume();
-#else
- CTimer::Update();
-#endif
- ISLAND_LOADING_IS(LOW)
- DMAudio.SetEffectsFadeVol(127);
- }
-}
-
-#ifdef NO_ISLAND_LOADING
-bool CCollision::bAlreadyLoaded = false;
-#endif
-void
-CCollision::SortOutCollisionAfterLoad(void)
-{
- if(ms_collisionInMemory == CGame::currLevel)
- return;
- ISLAND_LOADING_IS(LOW)
- CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
-
- if (CGame::currLevel != LEVEL_GENERIC) {
-#ifdef NO_ISLAND_LOADING
- if (CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) {
- if (bAlreadyLoaded) {
- ms_collisionInMemory = CGame::currLevel;
- return;
- }
- bAlreadyLoaded = true;
- CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL);
- CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL);
- CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN);
- } else
-#endif
- CFileLoader::LoadCollisionFromDatFile(CGame::currLevel);
- if(!CGame::playingIntro)
- LoadSplash(GetLevelSplashScreen(CGame::currLevel));
- }
- ms_collisionInMemory = CGame::currLevel;
- CGame::TidyUpMemory(true, false);
-}
-
-void
-CCollision::LoadCollisionScreen(eLevelName level)
-{
- static Const char *levelNames[4] = {
- "",
- "IND_ZON",
- "COM_ZON",
- "SUB_ZON"
- };
-
- // Why twice?
- LoadingIslandScreen(levelNames[level]);
- LoadingIslandScreen(levelNames[level]);
-}
-
-//
-// Test
-//
-
-
-bool
-CCollision::TestSphereSphere(const CColSphere &s1, const CColSphere &s2)
-{
- float d = s1.radius + s2.radius;
- return (s1.center - s2.center).MagnitudeSqr() < d*d;
-}
-
-bool
-CCollision::TestSphereBox(const CColSphere &sph, const CColBox &box)
-{
- if(sph.center.x + sph.radius < box.min.x) return false;
- if(sph.center.x - sph.radius > box.max.x) return false;
- if(sph.center.y + sph.radius < box.min.y) return false;
- if(sph.center.y - sph.radius > box.max.y) return false;
- if(sph.center.z + sph.radius < box.min.z) return false;
- if(sph.center.z - sph.radius > box.max.z) return false;
- return true;
-}
-
-bool
-CCollision::TestLineBox(const CColLine &line, const CColBox &box)
-{
- float t, x, y, z;
- // If either line point is in the box, we have a collision
- if(line.p0.x > box.min.x && line.p0.x < box.max.x &&
- line.p0.y > box.min.y && line.p0.y < box.max.y &&
- line.p0.z > box.min.z && line.p0.z < box.max.z)
- return true;
- if(line.p1.x > box.min.x && line.p1.x < box.max.x &&
- line.p1.y > box.min.y && line.p1.y < box.max.y &&
- line.p1.z > box.min.z && line.p1.z < box.max.z)
- return true;
-
- // check if points are on opposite sides of min x plane
- if((box.min.x - line.p1.x) * (box.min.x - line.p0.x) < 0.0f){
- // parameter along line where we intersect
- t = (box.min.x - line.p0.x) / (line.p1.x - line.p0.x);
- // y of intersection
- y = line.p0.y + (line.p1.y - line.p0.y)*t;
- if(y > box.min.y && y < box.max.y){
- // z of intersection
- z = line.p0.z + (line.p1.z - line.p0.z)*t;
- if(z > box.min.z && z < box.max.z)
- return true;
- }
- }
-
- // same test with max x plane
- if((line.p1.x - box.max.x) * (line.p0.x - box.max.x) < 0.0f){
- t = (line.p0.x - box.max.x) / (line.p0.x - line.p1.x);
- y = line.p0.y + (line.p1.y - line.p0.y)*t;
- if(y > box.min.y && y < box.max.y){
- z = line.p0.z + (line.p1.z - line.p0.z)*t;
- if(z > box.min.z && z < box.max.z)
- return true;
- }
- }
-
- // min y plne
- if((box.min.y - line.p0.y) * (box.min.y - line.p1.y) < 0.0f){
- t = (box.min.y - line.p0.y) / (line.p1.y - line.p0.y);
- x = line.p0.x + (line.p1.x - line.p0.x)*t;
- if(x > box.min.x && x < box.max.x){
- z = line.p0.z + (line.p1.z - line.p0.z)*t;
- if(z > box.min.z && z < box.max.z)
- return true;
- }
- }
-
- // max y plane
- if((line.p0.y - box.max.y) * (line.p1.y - box.max.y) < 0.0f){
- t = (line.p0.y - box.max.y) / (line.p0.y - line.p1.y);
- x = line.p0.x + (line.p1.x - line.p0.x)*t;
- if(x > box.min.x && x < box.max.x){
- z = line.p0.z + (line.p1.z - line.p0.z)*t;
- if(z > box.min.z && z < box.max.z)
- return true;
- }
- }
-
- // min z plne
- if((box.min.z - line.p0.z) * (box.min.z - line.p1.z) < 0.0f){
- t = (box.min.z - line.p0.z) / (line.p1.z - line.p0.z);
- x = line.p0.x + (line.p1.x - line.p0.x)*t;
- if(x > box.min.x && x < box.max.x){
- y = line.p0.y + (line.p1.y - line.p0.y)*t;
- if(y > box.min.y && y < box.max.y)
- return true;
- }
- }
-
- // max z plane
- if((line.p0.z - box.max.z) * (line.p1.z - box.max.z) < 0.0f){
- t = (line.p0.z - box.max.z) / (line.p0.z - line.p1.z);
- x = line.p0.x + (line.p1.x - line.p0.x)*t;
- if(x > box.min.x && x < box.max.x){
- y = line.p0.y + (line.p1.y - line.p0.y)*t;
- if(y > box.min.y && y < box.max.y)
- return true;
- }
- }
- return false;
-}
-
-bool
-CCollision::TestVerticalLineBox(const CColLine &line, const CColBox &box)
-{
- if(line.p0.x <= box.min.x) return false;
- if(line.p0.y <= box.min.y) return false;
- if(line.p0.x >= box.max.x) return false;
- if(line.p0.y >= box.max.y) return false;
- if(line.p0.z < line.p1.z){
- if(line.p0.z > box.max.z) return false;
- if(line.p1.z < box.min.z) return false;
- }else{
- if(line.p1.z > box.max.z) return false;
- if(line.p0.z < box.min.z) return false;
- }
- return true;
-}
-
-bool
-CCollision::TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane)
-{
-#ifdef VU_COLLISION
- // not used in favour of optimized loops
- VuTriangle vutri;
- verts[tri.a].Unpack(vutri.v0);
- verts[tri.b].Unpack(vutri.v1);
- verts[tri.c].Unpack(vutri.v2);
- plane.Unpack(vutri.plane);
-
- LineToTriangleCollisionCompressed(*(CVuVector*)&line.p0, *(CVuVector*)&line.p1, vutri);
-
- if(GetVUresult())
- return true;
- return false;
-#else
- float t;
- CVector normal;
- plane.GetNormal(normal);
-
- // if points are on the same side, no collision
- if(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f)
- return false;
-
- // intersection parameter on line
- t = -plane.CalcPoint(line.p0) / DotProduct(line.p1 - line.p0, normal);
- // find point of intersection
- CVector p = line.p0 + (line.p1-line.p0)*t;
-
- const CVector &va = verts[tri.a].Get();
- const CVector &vb = verts[tri.b].Get();
- const CVector &vc = verts[tri.c].Get();
- CVector2D vec1, vec2, vec3, vect;
-
- // We do the test in 2D. With the plane direction we
- // can figure out how to project the vectors.
- // normal = (c-a) x (b-a)
- switch(plane.dir){
- case DIR_X_POS:
- vec1.x = va.y; vec1.y = va.z;
- vec2.x = vc.y; vec2.y = vc.z;
- vec3.x = vb.y; vec3.y = vb.z;
- vect.x = p.y; vect.y = p.z;
- break;
- case DIR_X_NEG:
- vec1.x = va.y; vec1.y = va.z;
- vec2.x = vb.y; vec2.y = vb.z;
- vec3.x = vc.y; vec3.y = vc.z;
- vect.x = p.y; vect.y = p.z;
- break;
- case DIR_Y_POS:
- vec1.x = va.z; vec1.y = va.x;
- vec2.x = vc.z; vec2.y = vc.x;
- vec3.x = vb.z; vec3.y = vb.x;
- vect.x = p.z; vect.y = p.x;
- break;
- case DIR_Y_NEG:
- vec1.x = va.z; vec1.y = va.x;
- vec2.x = vb.z; vec2.y = vb.x;
- vec3.x = vc.z; vec3.y = vc.x;
- vect.x = p.z; vect.y = p.x;
- break;
- case DIR_Z_POS:
- vec1.x = va.x; vec1.y = va.y;
- vec2.x = vc.x; vec2.y = vc.y;
- vec3.x = vb.x; vec3.y = vb.y;
- vect.x = p.x; vect.y = p.y;
- break;
- case DIR_Z_NEG:
- vec1.x = va.x; vec1.y = va.y;
- vec2.x = vb.x; vec2.y = vb.y;
- vec3.x = vc.x; vec3.y = vc.y;
- vect.x = p.x; vect.y = p.y;
- break;
- default:
- assert(0);
- }
- // This is our triangle:
- // 3-------2
- // \ P /
- // \ /
- // \ /
- // 1
- // We can use the "2d cross product" to check on which side
- // a vector is of another. Test is true if point is inside of all edges.
- if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false;
- if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false;
- if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false;
- return true;
-#endif
-}
-
-// Test if line segment intersects with sphere.
-// If the first point is inside the sphere this test does not register a collision!
-// The code is reversed from the original code and rather ugly, see Process for a clear version.
-// TODO: actually rewrite this mess
-bool
-CCollision::TestLineSphere(const CColLine &line, const CColSphere &sph)
-{
- CVector v01 = line.p1 - line.p0; // vector from p0 to p1
- CVector v0c = sph.center - line.p0; // vector from p0 to center
- float linesq = v01.MagnitudeSqr();
- // I leave in the strange -2 factors even though they serve no real purpose
- float projline = -2.0f * DotProduct(v01, v0c); // project v0c onto line
- // Square of tangent from p0 multiplied by line length so we can compare with projline.
- // The length of the tangent would be this: Sqrt((c-p0)^2 - r^2).
- // Negative if p0 is inside the sphere! This breaks the test!
- float tansq = 4.0f * linesq *
- (sph.center.MagnitudeSqr() - 2.0f*DotProduct(sph.center, line.p0) + line.p0.MagnitudeSqr() - sph.radius*sph.radius);
- float diffsq = projline*projline - tansq;
- // if diffsq < 0 that means the line is a passant, so no intersection
- if(diffsq < 0.0f)
- return false;
- // projline (negative in GTA for some reason) is the point on the line
- // in the middle of the two intersection points (startin from p0).
- // Sqrt(diffsq) somehow works out to be the distance from that
- // midpoint to the intersection points.
- // So subtract that and get rid of the awkward scaling:
- float f = (-projline - Sqrt(diffsq)) / (2.0f*linesq);
- // f should now be in range [0, 1] for [p0, p1]
- return f >= 0.0f && f <= 1.0f;
-}
-
-bool
-CCollision::TestSphereTriangle(const CColSphere &sphere,
- const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane)
-{
-#ifdef VU_COLLISION
- // not used in favour of optimized loops
- VuTriangle vutri;
- verts[tri.a].Unpack(vutri.v0);
- verts[tri.b].Unpack(vutri.v1);
- verts[tri.c].Unpack(vutri.v2);
- plane.Unpack(vutri.plane);
-
- SphereToTriangleCollisionCompressed(*(CVuVector*)&sphere, vutri);
-
- if(GetVUresult())
- return true;
- return false;
-#else
- // If sphere and plane don't intersect, no collision
- float planedist = plane.CalcPoint(sphere.center);
- if(Abs(planedist) > sphere.radius)
- return false;
-
- const CVector &va = verts[tri.a].Get();
- const CVector &vb = verts[tri.b].Get();
- const CVector &vc = verts[tri.c].Get();
-
- // calculate two orthogonal basis vectors for the triangle
- CVector vec2 = vb - va;
- float len = vec2.Magnitude();
- vec2 = vec2 * (1.0f/len);
- CVector normal;
- plane.GetNormal(normal);
- CVector vec1 = CrossProduct(vec2, normal);
-
- // We know A has local coordinate [0,0] and B has [0,len].
- // Now calculate coordinates on triangle for these two vectors:
- CVector vac = vc - va;
- CVector vas = sphere.center - va;
- CVector2D b(0.0f, len);
- CVector2D c(DotProduct(vec1, vac), DotProduct(vec2, vac));
- CVector2D s(DotProduct(vec1, vas), DotProduct(vec2, vas));
-
- // The three triangle lines partition the space into 6 sectors,
- // find out in which the center lies.
- int insideAB = CrossProduct2D(s, b) >= 0.0f;
- int insideAC = CrossProduct2D(c, s) >= 0.0f;
- int insideBC = CrossProduct2D(s-b, c-b) >= 0.0f;
-
- int testcase = insideAB + insideAC + insideBC;
- float dist = 0.0f;
- switch(testcase){
- case 1:
- // closest to a vertex
- if(insideAB) dist = (sphere.center - vc).Magnitude();
- else if(insideAC) dist = (sphere.center - vb).Magnitude();
- else if(insideBC) dist = (sphere.center - va).Magnitude();
- else assert(0);
- break;
- case 2:
- // closest to an edge
- // looks like original game as DistToLine manually inlined
- if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center);
- else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center);
- else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center);
- else assert(0);
- break;
- case 3:
- // center is in triangle
- dist = Abs(planedist);
- break;
- default:
- assert(0);
- }
-
- return dist < sphere.radius;
-#endif
-}
-
-bool
-CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough)
-{
-#ifdef VU_COLLISION
- CMatrix matTransform;
- int i;
-
- // transform line to model space
- Invert(matrix, matTransform);
- CVuVector newline[2];
- TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2);
-
- // If we don't intersect with the bounding box, no chance on the rest
- if(!TestLineBox(*(CColLine*)newline, model.boundingBox))
- return false;
-
- for(i = 0; i < model.numSpheres; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
- if(TestLineSphere(*(CColLine*)newline, model.spheres[i]))
- return true;
- }
-
- for(i = 0; i < model.numBoxes; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
- if(TestLineBox(*(CColLine*)newline, model.boxes[i]))
- return true;
- }
-
- CalculateTrianglePlanes(&model);
- int lastTest = -1;
- VuTriangle vutri;
- for(i = 0; i < model.numTriangles; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
-
- CColTriangle *tri = &model.triangles[i];
- model.vertices[tri->a].Unpack(vutri.v0);
- model.vertices[tri->b].Unpack(vutri.v1);
- model.vertices[tri->c].Unpack(vutri.v2);
- model.trianglePlanes[i].Unpack(vutri.plane);
-
- LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
- lastTest = i;
- break;
- }
-#ifdef FIX_BUGS
- // no need to check first again
- i++;
-#endif
- for(; i < model.numTriangles; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
-
- CColTriangle *tri = &model.triangles[i];
- model.vertices[tri->a].Unpack(vutri.v0);
- model.vertices[tri->b].Unpack(vutri.v1);
- model.vertices[tri->c].Unpack(vutri.v2);
- model.trianglePlanes[i].Unpack(vutri.plane);
-
- if(GetVUresult())
- return true;
-
- LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
- lastTest = i;
-
- }
- if(lastTest != -1 && GetVUresult())
- return true;
-
- return false;
-#else
- static CMatrix matTransform;
- int i;
-
- // transform line to model space
- Invert(matrix, matTransform);
- CColLine newline(matTransform * line.p0, matTransform * line.p1);
-
- // If we don't intersect with the bounding box, no chance on the rest
- if(!TestLineBox(newline, model.boundingBox))
- return false;
-
- for(i = 0; i < model.numSpheres; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
- if(TestLineSphere(newline, model.spheres[i]))
- return true;
- }
-
- for(i = 0; i < model.numBoxes; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
- if(TestLineBox(newline, model.boxes[i]))
- return true;
- }
-
- CalculateTrianglePlanes(&model);
- for(i = 0; i < model.numTriangles; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
- if(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i]))
- return true;
- }
-
- return false;
-#endif
-}
-
-
-//
-// Process
-//
-
-// For Spheres mindist is the squared distance to its center
-// For Lines mindist is between [0,1]
-
-bool
-CCollision::ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq)
-{
- CVector dist = s1.center - s2.center;
- float d = dist.Magnitude() - s2.radius; // distance from s1's center to s2
- float depth = s1.radius - d; // sphere overlap
- if(d < 0.0f) d = 0.0f; // clamp to zero, i.e. if s1's center is inside s2
- // no collision if sphere is not close enough
- if(d*d < mindistsq && d < s1.radius){
- dist.Normalise();
- point.point = s1.center - dist*d;
- point.normal = dist;
-#ifndef VU_COLLISION
- point.surfaceA = s1.surface;
- point.pieceA = s1.piece;
- point.surfaceB = s2.surface;
- point.pieceB = s2.piece;
-#endif
- point.depth = depth;
- mindistsq = d*d; // collision radius
- return true;
- }
- return false;
-}
-
-bool
-CCollision::ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq)
-{
- CVector p;
- CVector dist;
-
- // GTA's code is too complicated, uses a huge 3x3x3 if statement
- // we can simplify the structure a lot
-
- // first make sure we have a collision at all
- if(sph.center.x + sph.radius < box.min.x) return false;
- if(sph.center.x - sph.radius > box.max.x) return false;
- if(sph.center.y + sph.radius < box.min.y) return false;
- if(sph.center.y - sph.radius > box.max.y) return false;
- if(sph.center.z + sph.radius < box.min.z) return false;
- if(sph.center.z - sph.radius > box.max.z) return false;
-
- // Now find out where the sphere center lies in relation to all the sides
- int xpos = sph.center.x < box.min.x ? 1 :
- sph.center.x > box.max.x ? 2 :
- 0;
- int ypos = sph.center.y < box.min.y ? 1 :
- sph.center.y > box.max.y ? 2 :
- 0;
- int zpos = sph.center.z < box.min.z ? 1 :
- sph.center.z > box.max.z ? 2 :
- 0;
-
- if(xpos == 0 && ypos == 0 && zpos == 0){
- // sphere is inside the box
- p = (box.min + box.max)*0.5f;
-
- dist = sph.center - p;
- float lensq = dist.MagnitudeSqr();
- if(lensq < mindistsq){
- point.normal = dist * (1.0f/Sqrt(lensq));
- point.point = sph.center - point.normal;
-#ifndef VU_COLLISION
- point.surfaceA = sph.surface;
- point.pieceA = sph.piece;
- point.surfaceB = box.surface;
- point.pieceB = box.piece;
-#endif
-
- // find absolute distance to the closer side in each dimension
- float dx = dist.x > 0.0f ?
- box.max.x - sph.center.x :
- sph.center.x - box.min.x;
- float dy = dist.y > 0.0f ?
- box.max.y - sph.center.y :
- sph.center.y - box.min.y;
- float dz = dist.z > 0.0f ?
- box.max.z - sph.center.z :
- sph.center.z - box.min.z;
- // collision depth is maximum of that:
- if(dx > dy && dx > dz)
- point.depth = dx;
- else if(dy > dz)
- point.depth = dy;
- else
- point.depth = dz;
- return true;
- }
- }else{
- // sphere is outside.
- // closest point on box:
- p.x = xpos == 1 ? box.min.x :
- xpos == 2 ? box.max.x :
- sph.center.x;
- p.y = ypos == 1 ? box.min.y :
- ypos == 2 ? box.max.y :
- sph.center.y;
- p.z = zpos == 1 ? box.min.z :
- zpos == 2 ? box.max.z :
- sph.center.z;
-
- dist = sph.center - p;
- float lensq = dist.MagnitudeSqr();
- if(lensq < mindistsq){
- float len = Sqrt(lensq);
- point.point = p;
- point.normal = dist * (1.0f/len);
-#ifndef VU_COLLISION
- point.surfaceA = sph.surface;
- point.pieceA = sph.piece;
- point.surfaceB = box.surface;
- point.pieceB = box.piece;
-#endif
- point.depth = sph.radius - len;
- mindistsq = lensq;
- return true;
- }
- }
- return false;
-}
-
-bool
-CCollision::ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist)
-{
- float mint, t, x, y, z;
- CVector normal;
- CVector p;
-
- mint = 1.0f;
- // check if points are on opposite sides of min x plane
- if((box.min.x - line.p1.x) * (box.min.x - line.p0.x) < 0.0f){
- // parameter along line where we intersect
- t = (box.min.x - line.p0.x) / (line.p1.x - line.p0.x);
- // y of intersection
- y = line.p0.y + (line.p1.y - line.p0.y)*t;
- if(y > box.min.y && y < box.max.y){
- // z of intersection
- z = line.p0.z + (line.p1.z - line.p0.z)*t;
- if(z > box.min.z && z < box.max.z)
- if(t < mint){
- mint = t;
- p = CVector(box.min.x, y, z);
- normal = CVector(-1.0f, 0.0f, 0.0f);
- }
- }
- }
-
- // max x plane
- if((line.p1.x - box.max.x) * (line.p0.x - box.max.x) < 0.0f){
- t = (line.p0.x - box.max.x) / (line.p0.x - line.p1.x);
- y = line.p0.y + (line.p1.y - line.p0.y)*t;
- if(y > box.min.y && y < box.max.y){
- z = line.p0.z + (line.p1.z - line.p0.z)*t;
- if(z > box.min.z && z < box.max.z)
- if(t < mint){
- mint = t;
- p = CVector(box.max.x, y, z);
- normal = CVector(1.0f, 0.0f, 0.0f);
- }
- }
- }
-
- // min y plne
- if((box.min.y - line.p0.y) * (box.min.y - line.p1.y) < 0.0f){
- t = (box.min.y - line.p0.y) / (line.p1.y - line.p0.y);
- x = line.p0.x + (line.p1.x - line.p0.x)*t;
- if(x > box.min.x && x < box.max.x){
- z = line.p0.z + (line.p1.z - line.p0.z)*t;
- if(z > box.min.z && z < box.max.z)
- if(t < mint){
- mint = t;
- p = CVector(x, box.min.y, z);
- normal = CVector(0.0f, -1.0f, 0.0f);
- }
- }
- }
-
- // max y plane
- if((line.p0.y - box.max.y) * (line.p1.y - box.max.y) < 0.0f){
- t = (line.p0.y - box.max.y) / (line.p0.y - line.p1.y);
- x = line.p0.x + (line.p1.x - line.p0.x)*t;
- if(x > box.min.x && x < box.max.x){
- z = line.p0.z + (line.p1.z - line.p0.z)*t;
- if(z > box.min.z && z < box.max.z)
- if(t < mint){
- mint = t;
- p = CVector(x, box.max.y, z);
- normal = CVector(0.0f, 1.0f, 0.0f);
- }
- }
- }
-
- // min z plne
- if((box.min.z - line.p0.z) * (box.min.z - line.p1.z) < 0.0f){
- t = (box.min.z - line.p0.z) / (line.p1.z - line.p0.z);
- x = line.p0.x + (line.p1.x - line.p0.x)*t;
- if(x > box.min.x && x < box.max.x){
- y = line.p0.y + (line.p1.y - line.p0.y)*t;
- if(y > box.min.y && y < box.max.y)
- if(t < mint){
- mint = t;
- p = CVector(x, y, box.min.z);
- normal = CVector(0.0f, 0.0f, -1.0f);
- }
- }
- }
-
- // max z plane
- if((line.p0.z - box.max.z) * (line.p1.z - box.max.z) < 0.0f){
- t = (line.p0.z - box.max.z) / (line.p0.z - line.p1.z);
- x = line.p0.x + (line.p1.x - line.p0.x)*t;
- if(x > box.min.x && x < box.max.x){
- y = line.p0.y + (line.p1.y - line.p0.y)*t;
- if(y > box.min.y && y < box.max.y)
- if(t < mint){
- mint = t;
- p = CVector(x, y, box.max.z);
- normal = CVector(0.0f, 0.0f, 1.0f);
- }
- }
- }
-
- if(mint >= mindist)
- return false;
-
- point.point = p;
- point.normal = normal;
-#ifndef VU_COLLISION
- point.surfaceA = 0;
- point.pieceA = 0;
- point.surfaceB = box.surface;
- point.pieceB = box.piece;
-#endif
- mindist = mint;
-
- return true;
-}
-
-// If line.p0 lies inside sphere, no collision is registered.
-bool
-CCollision::ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist)
-{
- CVector v01 = line.p1 - line.p0;
- CVector v0c = sphere.center - line.p0;
- float linesq = v01.MagnitudeSqr();
- // project v0c onto v01, scaled by |v01| this is the midpoint of the two intersections
- float projline = DotProduct(v01, v0c);
- // tangent of p0 to sphere, scaled by linesq just like projline^2
- float tansq = (v0c.MagnitudeSqr() - sphere.radius*sphere.radius) * linesq;
- // this works out to be the square of the distance between the midpoint and the intersections
- float diffsq = projline*projline - tansq;
- // no intersection
- if(diffsq < 0.0f)
- return false;
- // point of first intersection, in range [0,1] between p0 and p1
- float t = (projline - Sqrt(diffsq)) / linesq;
- // if not on line or beyond mindist, no intersection
- if(t < 0.0f || t > 1.0f || t >= mindist)
- return false;
- point.point = line.p0 + v01*t;
- point.normal = point.point - sphere.center;
- point.normal.Normalise();
-#ifndef VU_COLLISION
- point.surfaceA = 0;
- point.pieceA = 0;
- point.surfaceB = sphere.surface;
- point.pieceB = sphere.piece;
-#endif
- mindist = t;
- return true;
-}
-
-bool
-CCollision::ProcessVerticalLineTriangle(const CColLine &line,
- const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
- CColPoint &point, float &mindist, CStoredCollPoly *poly)
-{
-#ifdef VU_COLLISION
- // not used in favour of optimized loops
- bool res = ProcessLineTriangle(line, verts, tri, plane, point, mindist);
- if(res && poly){
- poly->verts[0] = verts[tri.a].Get();
- poly->verts[1] = verts[tri.b].Get();
- poly->verts[2] = verts[tri.c].Get();
- poly->valid = true;
- }
- return res;
-#else
- float t;
- CVector normal;
-
- const CVector &p0 = line.p0;
- const CVector &va = verts[tri.a].Get();
- const CVector &vb = verts[tri.b].Get();
- const CVector &vc = verts[tri.c].Get();
-
- // early out bound rect test
- if(p0.x < va.x && p0.x < vb.x && p0.x < vc.x) return false;
- if(p0.x > va.x && p0.x > vb.x && p0.x > vc.x) return false;
- if(p0.y < va.y && p0.y < vb.y && p0.y < vc.y) return false;
- if(p0.y > va.y && p0.y > vb.y && p0.y > vc.y) return false;
-
- plane.GetNormal(normal);
- // if points are on the same side, no collision
- if(plane.CalcPoint(p0) * plane.CalcPoint(line.p1) > 0.0f)
- return false;
-
- // intersection parameter on line
- float h = (line.p1 - p0).z;
- t = -plane.CalcPoint(p0) / (h * normal.z);
- // early out if we're beyond the mindist
- if(t >= mindist)
- return false;
- CVector p(p0.x, p0.y, p0.z + h*t);
-
- CVector2D vec1, vec2, vec3, vect;
- switch(plane.dir){
- case DIR_X_POS:
- vec1.x = va.y; vec1.y = va.z;
- vec2.x = vc.y; vec2.y = vc.z;
- vec3.x = vb.y; vec3.y = vb.z;
- vect.x = p.y; vect.y = p.z;
- break;
- case DIR_X_NEG:
- vec1.x = va.y; vec1.y = va.z;
- vec2.x = vb.y; vec2.y = vb.z;
- vec3.x = vc.y; vec3.y = vc.z;
- vect.x = p.y; vect.y = p.z;
- break;
- case DIR_Y_POS:
- vec1.x = va.z; vec1.y = va.x;
- vec2.x = vc.z; vec2.y = vc.x;
- vec3.x = vb.z; vec3.y = vb.x;
- vect.x = p.z; vect.y = p.x;
- break;
- case DIR_Y_NEG:
- vec1.x = va.z; vec1.y = va.x;
- vec2.x = vb.z; vec2.y = vb.x;
- vec3.x = vc.z; vec3.y = vc.x;
- vect.x = p.z; vect.y = p.x;
- break;
- case DIR_Z_POS:
- vec1.x = va.x; vec1.y = va.y;
- vec2.x = vc.x; vec2.y = vc.y;
- vec3.x = vb.x; vec3.y = vb.y;
- vect.x = p.x; vect.y = p.y;
- break;
- case DIR_Z_NEG:
- vec1.x = va.x; vec1.y = va.y;
- vec2.x = vb.x; vec2.y = vb.y;
- vec3.x = vc.x; vec3.y = vc.y;
- vect.x = p.x; vect.y = p.y;
- break;
- default:
- assert(0);
- }
- if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false;
- if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false;
- if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false;
- if(t >= mindist) return false;
- point.point = p;
- point.normal = normal;
- point.surfaceA = 0;
- point.pieceA = 0;
- point.surfaceB = tri.surface;
- point.pieceB = 0;
- if(poly){
- poly->verts[0] = va;
- poly->verts[1] = vb;
- poly->verts[2] = vc;
- poly->valid = true;
- }
- mindist = t;
- return true;
-#endif
-}
-
-bool
-CCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly)
-{
-#ifdef VU_COLLISION
- if(!poly->valid)
- return false;
-
- CVuVector p0 = pos;
- CVuVector p1 = pos;
- p1.z = z;
-
- CVector v01 = poly->verts[1] - poly->verts[0];
- CVector v02 = poly->verts[2] - poly->verts[0];
- CVuVector plane = CrossProduct(v02, v01);
- plane.Normalise();
- plane.w = DotProduct(plane, poly->verts[0]);
-
- LineToTriangleCollision(p0, p1, poly->verts[0], poly->verts[1], poly->verts[2], plane);
-
- CVuVector pnt;
- float dist;
- if(!GetVUresult(pnt, plane, dist))
-#ifdef FIX_BUGS
- // perhaps not needed but be safe
- return poly->valid = false;
-#else
- return false;
-#endif
- point.point = pnt;
- return true;
-#else
- float t;
-
- if(!poly->valid)
- return false;
-
- // maybe inlined?
- CColTrianglePlane plane;
- plane.Set(poly->verts[0], poly->verts[1], poly->verts[2]);
-
- const CVector &va = poly->verts[0];
- const CVector &vb = poly->verts[1];
- const CVector &vc = poly->verts[2];
- CVector p0 = pos;
- CVector p1(pos.x, pos.y, z);
-
- // The rest is pretty much CCollision::ProcessLineTriangle
-
- // if points are on the same side, no collision
- if(plane.CalcPoint(p0) * plane.CalcPoint(p1) > 0.0f)
- return poly->valid = false;
-
- // intersection parameter on line
- CVector normal;
- plane.GetNormal(normal);
- t = -plane.CalcPoint(p0) / DotProduct(p1 - p0, normal);
- // find point of intersection
- CVector p = p0 + (p1-p0)*t;
-
- CVector2D vec1, vec2, vec3, vect;
- switch(plane.dir){
- case DIR_X_POS:
- vec1.x = va.y; vec1.y = va.z;
- vec2.x = vc.y; vec2.y = vc.z;
- vec3.x = vb.y; vec3.y = vb.z;
- vect.x = p.y; vect.y = p.z;
- break;
- case DIR_X_NEG:
- vec1.x = va.y; vec1.y = va.z;
- vec2.x = vb.y; vec2.y = vb.z;
- vec3.x = vc.y; vec3.y = vc.z;
- vect.x = p.y; vect.y = p.z;
- break;
- case DIR_Y_POS:
- vec1.x = va.z; vec1.y = va.x;
- vec2.x = vc.z; vec2.y = vc.x;
- vec3.x = vb.z; vec3.y = vb.x;
- vect.x = p.z; vect.y = p.x;
- break;
- case DIR_Y_NEG:
- vec1.x = va.z; vec1.y = va.x;
- vec2.x = vb.z; vec2.y = vb.x;
- vec3.x = vc.z; vec3.y = vc.x;
- vect.x = p.z; vect.y = p.x;
- break;
- case DIR_Z_POS:
- vec1.x = va.x; vec1.y = va.y;
- vec2.x = vc.x; vec2.y = vc.y;
- vec3.x = vb.x; vec3.y = vb.y;
- vect.x = p.x; vect.y = p.y;
- break;
- case DIR_Z_NEG:
- vec1.x = va.x; vec1.y = va.y;
- vec2.x = vb.x; vec2.y = vb.y;
- vec3.x = vc.x; vec3.y = vc.y;
- vect.x = p.x; vect.y = p.y;
- break;
- default:
- assert(0);
- }
- if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return poly->valid = false;
- if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return poly->valid = false;
- if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return poly->valid = false;
- point.point = p;
- return poly->valid = true;
-#endif
-}
-
-bool
-CCollision::ProcessLineTriangle(const CColLine &line,
- const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
- CColPoint &point, float &mindist)
-{
-#ifdef VU_COLLISION
- // not used in favour of optimized loops
- VuTriangle vutri;
- verts[tri.a].Unpack(vutri.v0);
- verts[tri.b].Unpack(vutri.v1);
- verts[tri.c].Unpack(vutri.v2);
- plane.Unpack(vutri.plane);
-
- LineToTriangleCollisionCompressed(*(CVuVector*)&line.p0, *(CVuVector*)&line.p1, vutri);
-
- CVuVector pnt, normal;
- float dist;
- if(GetVUresult(pnt, normal, dist)){
- if(dist < mindist){
- point.point = pnt;
- point.normal = normal;
- mindist = dist;
- return true;
- }
- }
- return false;
-#else
- float t;
- CVector normal;
- plane.GetNormal(normal);
-
- // if points are on the same side, no collision
- if(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f)
- return false;
-
- // intersection parameter on line
- t = -plane.CalcPoint(line.p0) / DotProduct(line.p1 - line.p0, normal);
- // early out if we're beyond the mindist
- if(t >= mindist)
- return false;
- // find point of intersection
- CVector p = line.p0 + (line.p1-line.p0)*t;
-
- const CVector &va = verts[tri.a].Get();
- const CVector &vb = verts[tri.b].Get();
- const CVector &vc = verts[tri.c].Get();
- CVector2D vec1, vec2, vec3, vect;
-
- switch(plane.dir){
- case DIR_X_POS:
- vec1.x = va.y; vec1.y = va.z;
- vec2.x = vc.y; vec2.y = vc.z;
- vec3.x = vb.y; vec3.y = vb.z;
- vect.x = p.y; vect.y = p.z;
- break;
- case DIR_X_NEG:
- vec1.x = va.y; vec1.y = va.z;
- vec2.x = vb.y; vec2.y = vb.z;
- vec3.x = vc.y; vec3.y = vc.z;
- vect.x = p.y; vect.y = p.z;
- break;
- case DIR_Y_POS:
- vec1.x = va.z; vec1.y = va.x;
- vec2.x = vc.z; vec2.y = vc.x;
- vec3.x = vb.z; vec3.y = vb.x;
- vect.x = p.z; vect.y = p.x;
- break;
- case DIR_Y_NEG:
- vec1.x = va.z; vec1.y = va.x;
- vec2.x = vb.z; vec2.y = vb.x;
- vec3.x = vc.z; vec3.y = vc.x;
- vect.x = p.z; vect.y = p.x;
- break;
- case DIR_Z_POS:
- vec1.x = va.x; vec1.y = va.y;
- vec2.x = vc.x; vec2.y = vc.y;
- vec3.x = vb.x; vec3.y = vb.y;
- vect.x = p.x; vect.y = p.y;
- break;
- case DIR_Z_NEG:
- vec1.x = va.x; vec1.y = va.y;
- vec2.x = vb.x; vec2.y = vb.y;
- vec3.x = vc.x; vec3.y = vc.y;
- vect.x = p.x; vect.y = p.y;
- break;
- default:
- assert(0);
- }
- if(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false;
- if(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false;
- if(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false;
- if(t >= mindist) return false;
- point.point = p;
- point.normal = normal;
- point.surfaceA = 0;
- point.pieceA = 0;
- point.surfaceB = tri.surface;
- point.pieceB = 0;
- mindist = t;
- return true;
-#endif
-}
-
-bool
-CCollision::ProcessSphereTriangle(const CColSphere &sphere,
- const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,
- CColPoint &point, float &mindistsq)
-{
-#ifdef VU_COLLISION
- // not used in favour of optimized loops
- VuTriangle vutri;
- verts[tri.a].Unpack(vutri.v0);
- verts[tri.b].Unpack(vutri.v1);
- verts[tri.c].Unpack(vutri.v2);
- plane.Unpack(vutri.plane);
-
- SphereToTriangleCollisionCompressed(*(CVuVector*)&sphere, vutri);
-
- CVuVector pnt, normal;
- float dist;
- if(GetVUresult(pnt, normal, dist) && dist*dist < mindistsq){
- float depth = sphere.radius - dist;
- if(depth > point.depth){
- point.point = pnt;
- point.normal = normal;
- point.depth = depth;
- mindistsq = dist*dist;
- return true;
- }
- }
- return false;
-#else
- // If sphere and plane don't intersect, no collision
- float planedist = plane.CalcPoint(sphere.center);
- float distsq = planedist*planedist;
- if(Abs(planedist) > sphere.radius || distsq > mindistsq)
- return false;
-
- const CVector &va = verts[tri.a].Get();
- const CVector &vb = verts[tri.b].Get();
- const CVector &vc = verts[tri.c].Get();
-
- // calculate two orthogonal basis vectors for the triangle
- CVector normal;
- plane.GetNormal(normal);
- CVector vec2 = vb - va;
- float len = vec2.Magnitude();
- vec2 = vec2 * (1.0f/len);
- CVector vec1 = CrossProduct(vec2, normal);
-
- // We know A has local coordinate [0,0] and B has [0,len].
- // Now calculate coordinates on triangle for these two vectors:
- CVector vac = vc - va;
- CVector vas = sphere.center - va;
- CVector2D b(0.0f, len);
- CVector2D c(DotProduct(vec1, vac), DotProduct(vec2, vac));
- CVector2D s(DotProduct(vec1, vas), DotProduct(vec2, vas));
-
- // The three triangle lines partition the space into 6 sectors,
- // find out in which the center lies.
- int insideAB = CrossProduct2D(s, b) >= 0.0f;
- int insideAC = CrossProduct2D(c, s) >= 0.0f;
- int insideBC = CrossProduct2D(s-b, c-b) >= 0.0f;
-
- int testcase = insideAB + insideAC + insideBC;
- float dist = 0.0f;
- CVector p;
- switch(testcase){
- case 1:
- // closest to a vertex
- if(insideAB) p = vc;
- else if(insideAC) p = vb;
- else if(insideBC) p = va;
- else assert(0);
- dist = (sphere.center - p).Magnitude();
- break;
- case 2:
- // closest to an edge
- // looks like original game as DistToLine manually inlined
- if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center, p);
- else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center, p);
- else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center, p);
- else assert(0);
- break;
- case 3:
- // center is in triangle
- dist = Abs(planedist);
- p = sphere.center - normal*planedist;
- break;
- default:
- assert(0);
- }
-
- if(dist >= sphere.radius || dist*dist >= mindistsq)
- return false;
-
- point.point = p;
- point.normal = sphere.center - p;
- point.normal.Normalise();
-#ifndef VU_COLLISION
- point.surfaceA = sphere.surface;
- point.pieceA = sphere.piece;
- point.surfaceB = tri.surface;
- point.pieceB = 0;
-#endif
- point.depth = sphere.radius - dist;
- mindistsq = dist*dist;
- return true;
-#endif
-}
-
-bool
-CCollision::ProcessLineOfSight(const CColLine &line,
- const CMatrix &matrix, CColModel &model,
- CColPoint &point, float &mindist, bool ignoreSeeThrough)
-{
-#ifdef VU_COLLISION
- CMatrix matTransform;
- int i;
-
- // transform line to model space
- Invert(matrix, matTransform);
- CVuVector newline[2];
- TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2);
-
- if(mindist < 1.0f)
- newline[1] = newline[0] + (newline[1] - newline[0])*mindist;
-
- // If we don't intersect with the bounding box, no chance on the rest
- if(!TestLineBox(*(CColLine*)newline, model.boundingBox))
- return false;
-
- float coldist = 1.0f;
- for(i = 0; i < model.numSpheres; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
- if(ProcessLineSphere(*(CColLine*)newline, model.spheres[i], point, coldist))
- point.Set(0, 0, model.spheres[i].surface, model.spheres[i].piece);
- }
-
- for(i = 0; i < model.numBoxes; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
- if(ProcessLineBox(*(CColLine*)newline, model.boxes[i], point, coldist))
- point.Set(0, 0, model.boxes[i].surface, model.boxes[i].piece);
- }
-
- CalculateTrianglePlanes(&model);
- VuTriangle vutri;
- CColTriangle *lasttri = nil;
- for(i = 0; i < model.numTriangles; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
-
- CColTriangle *tri = &model.triangles[i];
- model.vertices[tri->a].Unpack(vutri.v0);
- model.vertices[tri->b].Unpack(vutri.v1);
- model.vertices[tri->c].Unpack(vutri.v2);
- model.trianglePlanes[i].Unpack(vutri.plane);
-
- LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
- lasttri = tri;
- break;
- }
-#ifdef FIX_BUGS
- // no need to check first again
- i++;
-#endif
- CVuVector pnt, normal;
- float dist;
- for(; i < model.numTriangles; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
-
- CColTriangle *tri = &model.triangles[i];
- model.vertices[tri->a].Unpack(vutri.v0);
- model.vertices[tri->b].Unpack(vutri.v1);
- model.vertices[tri->c].Unpack(vutri.v2);
- model.trianglePlanes[i].Unpack(vutri.plane);
-
- if(GetVUresult(pnt, normal, dist))
- if(dist < coldist){
- point.point = pnt;
- point.normal = normal;
- point.Set(0, 0, lasttri->surface, 0);
- coldist = dist;
- }
-
- LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
- lasttri = tri;
- }
- if(lasttri && GetVUresult(pnt, normal, dist))
- if(dist < coldist){
- point.point = pnt;
- point.normal = normal;
- point.Set(0, 0, lasttri->surface, 0);
- coldist = dist;
- }
-
-
- if(coldist < 1.0f){
- point.point = matrix * point.point;
- point.normal = Multiply3x3(matrix, point.normal);
- mindist *= coldist;
- return true;
- }
- return false;
-#else
- static CMatrix matTransform;
- int i;
-
- // transform line to model space
- Invert(matrix, matTransform);
- CColLine newline(matTransform * line.p0, matTransform * line.p1);
-
- // If we don't intersect with the bounding box, no chance on the rest
- if(!TestLineBox(newline, model.boundingBox))
- return false;
-
- float coldist = mindist;
- for(i = 0; i < model.numSpheres; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
- ProcessLineSphere(newline, model.spheres[i], point, coldist);
- }
-
- for(i = 0; i < model.numBoxes; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
- ProcessLineBox(newline, model.boxes[i], point, coldist);
- }
-
- CalculateTrianglePlanes(&model);
- for(i = 0; i < model.numTriangles; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
- ProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist);
- }
-
- if(coldist < mindist){
- point.point = matrix * point.point;
- point.normal = Multiply3x3(matrix, point.normal);
- mindist = coldist;
- return true;
- }
- return false;
-#endif
-}
-
-bool
-CCollision::ProcessVerticalLine(const CColLine &line,
- const CMatrix &matrix, CColModel &model,
- CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly)
-{
-#ifdef VU_COLLISION
- static CStoredCollPoly TempStoredPoly;
- CMatrix matTransform;
- int i;
-
- // transform line to model space
- Invert(matrix, matTransform);
- CVuVector newline[2];
- TransformPoints(newline, 2, matTransform, (RwV3d*)&line.p0, sizeof(CColLine)/2);
-
- if(mindist < 1.0f)
- newline[1] = newline[0] + (newline[1] - newline[0])*mindist;
-
- if(!TestLineBox(*(CColLine*)newline, model.boundingBox))
- return false;
-
- float coldist = 1.0f;
- for(i = 0; i < model.numSpheres; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
- if(ProcessLineSphere(*(CColLine*)newline, model.spheres[i], point, coldist))
- point.Set(0, 0, model.spheres[i].surface, model.spheres[i].piece);
- }
-
- for(i = 0; i < model.numBoxes; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
- if(ProcessLineBox(*(CColLine*)newline, model.boxes[i], point, coldist))
- point.Set(0, 0, model.boxes[i].surface, model.boxes[i].piece);
- }
-
- CalculateTrianglePlanes(&model);
- TempStoredPoly.valid = false;
- if(model.numTriangles){
- bool registeredCol;
- CColTriangle *lasttri = nil;
- VuTriangle vutri;
- for(i = 0; i < model.numTriangles; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
-
- CColTriangle *tri = &model.triangles[i];
- model.vertices[tri->a].Unpack(vutri.v0);
- model.vertices[tri->b].Unpack(vutri.v1);
- model.vertices[tri->c].Unpack(vutri.v2);
- model.trianglePlanes[i].Unpack(vutri.plane);
-
- LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
- lasttri = tri;
- break;
- }
-#ifdef FIX_BUGS
- // no need to check first again
- i++;
-#endif
- CVuVector pnt, normal;
- float dist;
- for(; i < model.numTriangles; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
-
- CColTriangle *tri = &model.triangles[i];
- model.vertices[tri->a].Unpack(vutri.v0);
- model.vertices[tri->b].Unpack(vutri.v1);
- model.vertices[tri->c].Unpack(vutri.v2);
- model.trianglePlanes[i].Unpack(vutri.plane);
-
- if(GetVUresult(pnt, normal, dist)){
- if(dist < coldist){
- point.point = pnt;
- point.normal = normal;
- point.Set(0, 0, lasttri->surface, 0);
- coldist = dist;
- registeredCol = true;
- }else
- registeredCol = false;
- }else
- registeredCol = false;
-
- if(registeredCol){
- TempStoredPoly.verts[0] = model.vertices[lasttri->a].Get();
- TempStoredPoly.verts[1] = model.vertices[lasttri->b].Get();
- TempStoredPoly.verts[2] = model.vertices[lasttri->c].Get();
- TempStoredPoly.valid = true;
- }
-
- LineToTriangleCollisionCompressed(newline[0], newline[1], vutri);
- lasttri = tri;
- }
- if(lasttri && GetVUresult(pnt, normal, dist)){
- if(dist < coldist){
- point.point = pnt;
- point.normal = normal;
- point.Set(0, 0, lasttri->surface, 0);
- coldist = dist;
- registeredCol = true;
- }else
- registeredCol = false;
- }else
- registeredCol = false;
-
- if(registeredCol){
- TempStoredPoly.verts[0] = model.vertices[lasttri->a].Get();
- TempStoredPoly.verts[1] = model.vertices[lasttri->b].Get();
- TempStoredPoly.verts[2] = model.vertices[lasttri->c].Get();
- TempStoredPoly.valid = true;
- }
- }
-
- if(coldist < 1.0f){
- point.point = matrix * point.point;
- point.normal = Multiply3x3(matrix, point.normal);
- if(TempStoredPoly.valid && poly){
- *poly = TempStoredPoly;
- poly->verts[0] = matrix * CVector(poly->verts[0]);
- poly->verts[1] = matrix * CVector(poly->verts[1]);
- poly->verts[2] = matrix * CVector(poly->verts[2]);
- }
- mindist *= coldist;
- return true;
- }
- return false;
-#else
- static CStoredCollPoly TempStoredPoly;
- int i;
-
- // transform line to model space
- // Why does the game seem to do this differently than above?
- CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1));
- newline.p1.x = newline.p0.x;
- newline.p1.y = newline.p0.y;
-
- if(!TestVerticalLineBox(newline, model.boundingBox))
- return false;
-
- float coldist = mindist;
- for(i = 0; i < model.numSpheres; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;
- ProcessLineSphere(newline, model.spheres[i], point, coldist);
- }
-
- for(i = 0; i < model.numBoxes; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;
- ProcessLineBox(newline, model.boxes[i], point, coldist);
- }
-
- CalculateTrianglePlanes(&model);
- TempStoredPoly.valid = false;
- for(i = 0; i < model.numTriangles; i++){
- if(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;
- ProcessVerticalLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly);
- }
-
- if(coldist < mindist){
- point.point = matrix * point.point;
- point.normal = Multiply3x3(matrix, point.normal);
- if(TempStoredPoly.valid && poly){
- *poly = TempStoredPoly;
- poly->verts[0] = matrix * poly->verts[0];
- poly->verts[1] = matrix * poly->verts[1];
- poly->verts[2] = matrix * poly->verts[2];
- }
- mindist = coldist;
- return true;
- }
- return false;
-#endif
-}
-
-enum {
- MAXNUMSPHERES = 128,
- MAXNUMBOXES = 32,
- MAXNUMLINES = 16,
- MAXNUMTRIS = 600
-};
-
-#ifdef VU_COLLISION
-#ifdef GTA_PS2
-#define SPR(off) ((uint8*)(0x70000000 + (off)))
-#else
-static uint8 fakeSPR[16*1024];
-#define SPR(off) ((uint8*)(fakeSPR + (off)))
-#endif
-#endif
-
-// This checks model A's spheres and lines against model B's spheres, boxes and triangles.
-// Returns the number of A's spheres that collide.
-// Returned ColPoints are in world space.
-// NB: only vehicles can have col models with lines, exactly 4, one for each wheel
-int32
-CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
- const CMatrix &matrixB, CColModel &modelB,
- CColPoint *spherepoints, CColPoint *linepoints, float *linedists)
-{
-#ifdef VU_COLLISION
- CVuVector *aSpheresA = (CVuVector*)SPR(0x0000);
- CVuVector *aSpheresB = (CVuVector*)SPR(0x0800);
- CVuVector *aLinesA = (CVuVector*)SPR(0x1000);
- int32 *aSphereIndicesA = (int32*)SPR(0x1200);
- int32 *aSphereIndicesB = (int32*)SPR(0x1400);
- int32 *aBoxIndicesB = (int32*)SPR(0x1600);
- int32 *aTriangleIndicesB = (int32*)SPR(0x1680);
- bool *aCollided = (bool*)SPR(0x1FE0);
- CMatrix &matAB = *(CMatrix*)SPR(0x1FF0);
- CMatrix &matBA = *(CMatrix*)SPR(0x2040);
- int i, j, k;
-
- // From model A space to model B space
- Invert(matrixB, matAB);
- matAB *= matrixA;
-
- CVuVector bsphereAB; // bounding sphere of A in B space
- TransformPoint(bsphereAB, matAB, *(RwV3d*)modelA.boundingSphere.center); // inlined
- bsphereAB.w = modelA.boundingSphere.radius;
- if(!TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boundingBox))
- return 0;
-
- // transform modelA's spheres and lines to B space
- TransformPoints(aSpheresA, modelA.numSpheres, matAB, (RwV3d*)&modelA.spheres->center, sizeof(CColSphere));
- for(i = 0; i < modelA.numSpheres; i++)
- aSpheresA[i].w = modelA.spheres[i].radius;
- TransformPoints(aLinesA, modelA.numLines*2, matAB, (RwV3d*)&modelA.lines->p0, sizeof(CColLine)/2);
-
- // Test them against model B's bounding volumes
- int numSpheresA = 0;
- for(i = 0; i < modelA.numSpheres; i++)
- if(TestSphereBox(*(CColSphere*)&aSpheresA[i], modelB.boundingBox))
- aSphereIndicesA[numSpheresA++] = i;
- // No collision
- if(numSpheresA == 0 && modelA.numLines == 0)
- return 0;
-
-
- // B to A space
- Invert(matrixA, matBA);
- matBA *= matrixB;
-
- // transform modelB's spheres to A space
- TransformPoints(aSpheresB, modelB.numSpheres, matBA, (RwV3d*)&modelB.spheres->center, sizeof(CColSphere));
- for(i = 0; i < modelB.numSpheres; i++)
- aSpheresB[i].w = modelB.spheres[i].radius;
-
- // Check model B against A's bounding volumes
- int numSpheresB = 0;
- int numBoxesB = 0;
- int numTrianglesB = 0;
- for(i = 0; i < modelB.numSpheres; i++)
- if(TestSphereBox(*(CColSphere*)&aSpheresB[i], modelA.boundingBox))
- aSphereIndicesB[numSpheresB++] = i;
- for(i = 0; i < modelB.numBoxes; i++)
- if(TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boxes[i]))
- aBoxIndicesB[numBoxesB++] = i;
- CalculateTrianglePlanes(&modelB);
- if(modelB.numTriangles){
- VuTriangle vutri;
- // process the first triangle
- CColTriangle *tri = &modelB.triangles[0];
- modelB.vertices[tri->a].Unpack(vutri.v0);
- modelB.vertices[tri->b].Unpack(vutri.v1);
- modelB.vertices[tri->c].Unpack(vutri.v2);
- modelB.trianglePlanes[0].Unpack(vutri.plane);
-
- SphereToTriangleCollisionCompressed(bsphereAB, vutri);
-
- for(i = 1; i < modelB.numTriangles; i++){
- // set up the next triangle while VU0 is running
- tri = &modelB.triangles[i];
- modelB.vertices[tri->a].Unpack(vutri.v0);
- modelB.vertices[tri->b].Unpack(vutri.v1);
- modelB.vertices[tri->c].Unpack(vutri.v2);
- modelB.trianglePlanes[i].Unpack(vutri.plane);
-
- // check previous result
- if(GetVUresult())
- aTriangleIndicesB[numTrianglesB++] = i-1;
-
- // kick off this one
- SphereToTriangleCollisionCompressed(bsphereAB, vutri);
- }
-
- // check last result
- if(GetVUresult())
- aTriangleIndicesB[numTrianglesB++] = i-1;
- }
- // No collision
- if(numSpheresB == 0 && numBoxesB == 0 && numTrianglesB == 0)
- return 0;
-
- // We now have the collision volumes in A and B that are worth processing.
-
- // Process A's spheres against B's collision volumes
- int numCollisions = 0;
- spherepoints[numCollisions].depth = -1.0f;
- for(i = 0; i < numSpheresA; i++){
- float coldist = 1.0e24f;
- bool hasCollided = false;
- CColSphere *sphA = &modelA.spheres[aSphereIndicesA[i]];
- CVuVector *vusphA = &aSpheresA[aSphereIndicesA[i]];
-
- for(j = 0; j < numSpheresB; j++)
- // This actually looks like something was inlined here
- if(ProcessSphereSphere(*(CColSphere*)vusphA, modelB.spheres[aSphereIndicesB[j]],
- spherepoints[numCollisions], coldist)){
- spherepoints[numCollisions].Set(
- sphA->surface, sphA->piece,
- modelB.spheres[aSphereIndicesB[j]].surface, modelB.spheres[aSphereIndicesB[j]].piece);
- hasCollided = true;
- }
- for(j = 0; j < numBoxesB; j++)
- if(ProcessSphereBox(*(CColSphere*)vusphA, modelB.boxes[aBoxIndicesB[j]],
- spherepoints[numCollisions], coldist)){
- spherepoints[numCollisions].Set(
- sphA->surface, sphA->piece,
- modelB.boxes[aBoxIndicesB[j]].surface, modelB.boxes[aBoxIndicesB[j]].piece);
- hasCollided = true;
- }
- if(numTrianglesB){
- CVuVector point, normal;
- float depth;
- bool registeredCol;
- CColTriangle *lasttri;
-
- VuTriangle vutri;
- // process the first triangle
- k = aTriangleIndicesB[0];
- CColTriangle *tri = &modelB.triangles[k];
- modelB.vertices[tri->a].Unpack(vutri.v0);
- modelB.vertices[tri->b].Unpack(vutri.v1);
- modelB.vertices[tri->c].Unpack(vutri.v2);
- modelB.trianglePlanes[k].Unpack(vutri.plane);
-
- SphereToTriangleCollisionCompressed(*vusphA, vutri);
- lasttri = tri;
-
- for(j = 1; j < numTrianglesB; j++){
- k = aTriangleIndicesB[j];
- // set up the next triangle while VU0 is running
- tri = &modelB.triangles[k];
- modelB.vertices[tri->a].Unpack(vutri.v0);
- modelB.vertices[tri->b].Unpack(vutri.v1);
- modelB.vertices[tri->c].Unpack(vutri.v2);
- modelB.trianglePlanes[k].Unpack(vutri.plane);
-
- // check previous result
- // TODO: this looks inlined but spherepoints[numCollisions] does not...
- if(GetVUresult(point, normal, depth)){
- depth = sphA->radius - depth;
- if(depth > spherepoints[numCollisions].depth){
- spherepoints[numCollisions].point = point;
- spherepoints[numCollisions].normal = normal;
- spherepoints[numCollisions].Set(depth,
- sphA->surface, sphA->piece, lasttri->surface, 0);
- registeredCol = true;
- }else
- registeredCol = false;
- }else
- registeredCol = false;
-
- if(registeredCol)
- hasCollided = true;
-
- // kick off this one
- SphereToTriangleCollisionCompressed(*vusphA, vutri);
- lasttri = tri;
- }
-
- // check last result
- // TODO: this looks inlined but spherepoints[numCollisions] does not...
- if(GetVUresult(point, normal, depth)){
- depth = sphA->radius - depth;
- if(depth > spherepoints[numCollisions].depth){
- spherepoints[numCollisions].point = point;
- spherepoints[numCollisions].normal = normal;
- spherepoints[numCollisions].Set(depth,
- sphA->surface, sphA->piece, lasttri->surface, 0);
- registeredCol = true;
- }else
- registeredCol = false;
- }else
- registeredCol = false;
-
- if(registeredCol)
- hasCollided = true;
- }
-
- if(hasCollided){
- numCollisions++;
- if(numCollisions == MAX_COLLISION_POINTS)
- break;
- spherepoints[numCollisions].depth = -1.0f;
- }
- }
- for(i = 0; i < numCollisions; i++){
- // TODO: both VU0 macros
- spherepoints[i].point = matrixB * spherepoints[i].point;
- spherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal);
- }
-
- // And the same thing for the lines in A
- for(i = 0; i < modelA.numLines; i++){
- aCollided[i] = false;
- CVuVector *lineA = &aLinesA[i*2];
-
- for(j = 0; j < numSpheresB; j++)
- if(ProcessLineSphere(*(CColLine*)lineA, modelB.spheres[aSphereIndicesB[j]],
- linepoints[i], linedists[i])){
- linepoints[i].Set(0, 0,
-#ifdef FIX_BUGS
- modelB.spheres[aSphereIndicesB[j]].surface, modelB.spheres[aSphereIndicesB[j]].piece);
-#else
- modelB.spheres[j].surface, modelB.spheres[j].piece);
-#endif
- aCollided[i] = true;
- }
- for(j = 0; j < numBoxesB; j++)
- if(ProcessLineBox(*(CColLine*)lineA, modelB.boxes[aBoxIndicesB[j]],
- linepoints[i], linedists[i])){
- linepoints[i].Set(0, 0,
- modelB.boxes[aBoxIndicesB[j]].surface, modelB.boxes[aBoxIndicesB[j]].piece);
- aCollided[i] = true;
- }
- if(numTrianglesB){
- CVuVector point, normal;
- float dist;
- bool registeredCol;
- CColTriangle *lasttri;
-
- VuTriangle vutri;
- // process the first triangle
- k = aTriangleIndicesB[0];
- CColTriangle *tri = &modelB.triangles[k];
- modelB.vertices[tri->a].Unpack(vutri.v0);
- modelB.vertices[tri->b].Unpack(vutri.v1);
- modelB.vertices[tri->c].Unpack(vutri.v2);
- modelB.trianglePlanes[k].Unpack(vutri.plane);
-
- LineToTriangleCollisionCompressed(lineA[0], lineA[1], vutri);
- lasttri = tri;
-
- for(j = 1; j < numTrianglesB; j++){
- k = aTriangleIndicesB[j];
- // set up the next triangle while VU0 is running
- CColTriangle *tri = &modelB.triangles[k];
- modelB.vertices[tri->a].Unpack(vutri.v0);
- modelB.vertices[tri->b].Unpack(vutri.v1);
- modelB.vertices[tri->c].Unpack(vutri.v2);
- modelB.trianglePlanes[k].Unpack(vutri.plane);
-
- // check previous result
- // TODO: this again somewhat looks inlined
- if(GetVUresult(point, normal, dist)){
- if(dist < linedists[i]){
- linepoints[i].point = point;
- linepoints[i].normal = normal;
- linedists[i] = dist;
- linepoints[i].Set(0, 0, lasttri->surface, 0);
- registeredCol = true;
- }else
- registeredCol = false;
- }else
- registeredCol = false;
-
- if(registeredCol)
- aCollided[i] = true;
-
- // kick of this one
- LineToTriangleCollisionCompressed(lineA[0], lineA[1], vutri);
- lasttri = tri;
- }
-
- // check last result
- if(GetVUresult(point, normal, dist)){
- if(dist < linedists[i]){
- linepoints[i].point = point;
- linepoints[i].normal = normal;
- linedists[i] = dist;
- linepoints[i].Set(0, 0, lasttri->surface, 0);
- registeredCol = true;
- }else
- registeredCol = false;
- }else
- registeredCol = false;
-
- if(registeredCol)
- aCollided[i] = true;
- }
-
- if(aCollided[i]){
- // TODO: both VU0 macros
- linepoints[i].point = matrixB * linepoints[i].point;
- linepoints[i].normal = Multiply3x3(matrixB, linepoints[i].normal);
- }
- }
-
- return numCollisions; // sphere collisions
-#else
- static int aSphereIndicesA[MAXNUMSPHERES];
- static int aLineIndicesA[MAXNUMLINES];
- static int aSphereIndicesB[MAXNUMSPHERES];
- static int aBoxIndicesB[MAXNUMBOXES];
- static int aTriangleIndicesB[MAXNUMTRIS];
- static bool aCollided[MAXNUMLINES];
- static CColSphere aSpheresA[MAXNUMSPHERES];
- static CColLine aLinesA[MAXNUMLINES];
- static CMatrix matAB, matBA;
- CColSphere s;
- int i, j;
-
- assert(modelA.numSpheres <= MAXNUMSPHERES);
- assert(modelA.numLines <= MAXNUMLINES);
-
- // From model A space to model B space
- Invert(matrixB, matAB);
- matAB *= matrixA;
-
- CColSphere bsphereAB; // bounding sphere of A in B space
- bsphereAB.Set(modelA.boundingSphere.radius, matAB * modelA.boundingSphere.center);
- if(!TestSphereBox(bsphereAB, modelB.boundingBox))
- return 0;
- // B to A space
- matBA = Invert(matrixA, matBA);
- matBA *= matrixB;
-
- // transform modelA's spheres and lines to B space
- for(i = 0; i < modelA.numSpheres; i++){
- CColSphere &s = modelA.spheres[i];
- aSpheresA[i].Set(s.radius, matAB * s.center, s.surface, s.piece);
- }
- for(i = 0; i < modelA.numLines; i++)
- aLinesA[i].Set(matAB * modelA.lines[i].p0, matAB * modelA.lines[i].p1);
-
- // Test them against model B's bounding volumes
- int numSpheresA = 0;
- int numLinesA = 0;
- for(i = 0; i < modelA.numSpheres; i++)
- if(TestSphereBox(aSpheresA[i], modelB.boundingBox))
- aSphereIndicesA[numSpheresA++] = i;
- // no actual check???
- for(i = 0; i < modelA.numLines; i++)
- aLineIndicesA[numLinesA++] = i;
- // No collision
- if(numSpheresA == 0 && numLinesA == 0)
- return 0;
-
- // Check model B against A's bounding volumes
- int numSpheresB = 0;
- int numBoxesB = 0;
- int numTrianglesB = 0;
- for(i = 0; i < modelB.numSpheres; i++){
- s.Set(modelB.spheres[i].radius, matBA * modelB.spheres[i].center);
- if(TestSphereBox(s, modelA.boundingBox))
- aSphereIndicesB[numSpheresB++] = i;
- }
- for(i = 0; i < modelB.numBoxes; i++)
- if(TestSphereBox(bsphereAB, modelB.boxes[i]))
- aBoxIndicesB[numBoxesB++] = i;
- CalculateTrianglePlanes(&modelB);
- for(i = 0; i < modelB.numTriangles; i++)
- if(TestSphereTriangle(bsphereAB, modelB.vertices, modelB.triangles[i], modelB.trianglePlanes[i]))
- aTriangleIndicesB[numTrianglesB++] = i;
- assert(numSpheresB <= MAXNUMSPHERES);
- assert(numBoxesB <= MAXNUMBOXES);
- assert(numTrianglesB <= MAXNUMTRIS);
- // No collision
- if(numSpheresB == 0 && numBoxesB == 0 && numTrianglesB == 0)
- return 0;
-
- // We now have the collision volumes in A and B that are worth processing.
-
- // Process A's spheres against B's collision volumes
- int numCollisions = 0;
- for(i = 0; i < numSpheresA; i++){
- float coldist = 1.0e24f;
- bool hasCollided = false;
-
- for(j = 0; j < numSpheresB; j++)
- hasCollided |= ProcessSphereSphere(
- aSpheresA[aSphereIndicesA[i]],
- modelB.spheres[aSphereIndicesB[j]],
- spherepoints[numCollisions], coldist);
- for(j = 0; j < numBoxesB; j++)
- hasCollided |= ProcessSphereBox(
- aSpheresA[aSphereIndicesA[i]],
- modelB.boxes[aBoxIndicesB[j]],
- spherepoints[numCollisions], coldist);
- for(j = 0; j < numTrianglesB; j++)
- hasCollided |= ProcessSphereTriangle(
- aSpheresA[aSphereIndicesA[i]],
- modelB.vertices,
- modelB.triangles[aTriangleIndicesB[j]],
- modelB.trianglePlanes[aTriangleIndicesB[j]],
- spherepoints[numCollisions], coldist);
-
- if(hasCollided)
- numCollisions++;
- }
- for(i = 0; i < numCollisions; i++){
- spherepoints[i].point = matrixB * spherepoints[i].point;
- spherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal);
- }
-
- // And the same thing for the lines in A
- for(i = 0; i < numLinesA; i++){
- aCollided[i] = false;
-
- for(j = 0; j < numSpheresB; j++)
- aCollided[i] |= ProcessLineSphere(
- aLinesA[aLineIndicesA[i]],
- modelB.spheres[aSphereIndicesB[j]],
- linepoints[aLineIndicesA[i]],
- linedists[aLineIndicesA[i]]);
- for(j = 0; j < numBoxesB; j++)
- aCollided[i] |= ProcessLineBox(
- aLinesA[aLineIndicesA[i]],
- modelB.boxes[aBoxIndicesB[j]],
- linepoints[aLineIndicesA[i]],
- linedists[aLineIndicesA[i]]);
- for(j = 0; j < numTrianglesB; j++)
- aCollided[i] |= ProcessLineTriangle(
- aLinesA[aLineIndicesA[i]],
- modelB.vertices,
- modelB.triangles[aTriangleIndicesB[j]],
- modelB.trianglePlanes[aTriangleIndicesB[j]],
- linepoints[aLineIndicesA[i]],
- linedists[aLineIndicesA[i]]);
- }
- for(i = 0; i < numLinesA; i++)
- if(aCollided[i]){
- j = aLineIndicesA[i];
- linepoints[j].point = matrixB * linepoints[j].point;
- linepoints[j].normal = Multiply3x3(matrixB, linepoints[j].normal);
- }
-
- return numCollisions; // sphere collisions
-#endif
-}
-
-
-//
-// Misc
-//
-
-float
-CCollision::DistToLine(const CVector *l0, const CVector *l1, const CVector *point)
-{
- float lensq = (*l1 - *l0).MagnitudeSqr();
- float dot = DotProduct(*point - *l0, *l1 - *l0);
- // Between 0 and len we're above the line.
- // if not, calculate distance to endpoint
- if(dot <= 0.0f)
- return (*point - *l0).Magnitude();
- if(dot >= lensq)
- return (*point - *l1).Magnitude();
- // distance to line
- return Sqrt((*point - *l0).MagnitudeSqr() - dot*dot/lensq);
-}
-
-// same as above but also return the point on the line
-float
-CCollision::DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest)
-{
- float lensq = (*l1 - *l0).MagnitudeSqr();
- float dot = DotProduct(*point - *l0, *l1 - *l0);
- // find out which point we're closest to
- if(dot <= 0.0f)
- closest = *l0;
- else if(dot >= lensq)
- closest = *l1;
- else
- closest = *l0 + (*l1 - *l0)*(dot/lensq);
- // this is the distance
- return (*point - closest).Magnitude();
-}
-
-void
-CCollision::CalculateTrianglePlanes(CColModel *model)
-{
- assert(model);
- if(model->numTriangles == 0)
- return;
-
- CLink<CColModel*> *lptr;
- if(model->trianglePlanes){
- // re-insert at front so it's not removed again soon
- lptr = model->GetLinkPtr();
- lptr->Remove();
- ms_colModelCache.head.Insert(lptr);
- }else{
- lptr = ms_colModelCache.Insert(model);
- if(lptr == nil){
- // make room if we have to, remove last in list
- lptr = ms_colModelCache.tail.prev;
- assert(lptr);
- assert(lptr->item);
- lptr->item->RemoveTrianglePlanes();
- ms_colModelCache.Remove(lptr);
- // now this cannot fail
- lptr = ms_colModelCache.Insert(model);
- assert(lptr);
- }
- model->CalculateTrianglePlanes();
- model->SetLinkPtr(lptr);
- }
-}
-
-void
-CCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel)
-{
- int i;
- CVector min, max;
- CVector verts[8];
- CVector c;
- float r;
-
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
-
- min = colModel.boundingBox.min;
- max = colModel.boundingBox.max;
-
- verts[0] = mat * CVector(min.x, min.y, min.z);
- verts[1] = mat * CVector(min.x, min.y, max.z);
- verts[2] = mat * CVector(min.x, max.y, min.z);
- verts[3] = mat * CVector(min.x, max.y, max.z);
- verts[4] = mat * CVector(max.x, min.y, min.z);
- verts[5] = mat * CVector(max.x, min.y, max.z);
- verts[6] = mat * CVector(max.x, max.y, min.z);
- verts[7] = mat * CVector(max.x, max.y, max.z);
-
- CLines::RenderLineWithClipping(
- verts[0].x, verts[0].y, verts[0].z,
- verts[1].x, verts[1].y, verts[1].z,
- 0xFF0000FF, 0xFF0000FF);
- CLines::RenderLineWithClipping(
- verts[1].x, verts[1].y, verts[1].z,
- verts[3].x, verts[3].y, verts[3].z,
- 0xFF0000FF, 0xFF0000FF);
- CLines::RenderLineWithClipping(
- verts[3].x, verts[3].y, verts[3].z,
- verts[2].x, verts[2].y, verts[2].z,
- 0xFF0000FF, 0xFF0000FF);
- CLines::RenderLineWithClipping(
- verts[2].x, verts[2].y, verts[2].z,
- verts[0].x, verts[0].y, verts[0].z,
- 0xFF0000FF, 0xFF0000FF);
-
- CLines::RenderLineWithClipping(
- verts[4].x, verts[4].y, verts[4].z,
- verts[5].x, verts[5].y, verts[5].z,
- 0xFF0000FF, 0xFF0000FF);
- CLines::RenderLineWithClipping(
- verts[5].x, verts[5].y, verts[5].z,
- verts[7].x, verts[7].y, verts[7].z,
- 0xFF0000FF, 0xFF0000FF);
- CLines::RenderLineWithClipping(
- verts[7].x, verts[7].y, verts[7].z,
- verts[6].x, verts[6].y, verts[6].z,
- 0xFF0000FF, 0xFF0000FF);
- CLines::RenderLineWithClipping(
- verts[6].x, verts[6].y, verts[6].z,
- verts[4].x, verts[4].y, verts[4].z,
- 0xFF0000FF, 0xFF0000FF);
-
- CLines::RenderLineWithClipping(
- verts[0].x, verts[0].y, verts[0].z,
- verts[4].x, verts[4].y, verts[4].z,
- 0xFF0000FF, 0xFF0000FF);
- CLines::RenderLineWithClipping(
- verts[1].x, verts[1].y, verts[1].z,
- verts[5].x, verts[5].y, verts[5].z,
- 0xFF0000FF, 0xFF0000FF);
- CLines::RenderLineWithClipping(
- verts[2].x, verts[2].y, verts[2].z,
- verts[6].x, verts[6].y, verts[6].z,
- 0xFF0000FF, 0xFF0000FF);
- CLines::RenderLineWithClipping(
- verts[3].x, verts[3].y, verts[3].z,
- verts[7].x, verts[7].y, verts[7].z,
- 0xFF0000FF, 0xFF0000FF);
-
- for(i = 0; i < colModel.numSpheres; i++){
- c = mat * colModel.spheres[i].center;
- r = colModel.spheres[i].radius;
-
- CLines::RenderLineWithClipping(
- c.x, c.y, c.z-r,
- c.x-r, c.y-r, c.z,
- 0xFF00FFFF, 0xFF00FFFF);
- CLines::RenderLineWithClipping(
- c.x, c.y, c.z-r,
- c.x-r, c.y+r, c.z,
- 0xFF00FFFF, 0xFF00FFFF);
- CLines::RenderLineWithClipping(
- c.x, c.y, c.z-r,
- c.x+r, c.y-r, c.z,
- 0xFF00FFFF, 0xFF00FFFF);
- CLines::RenderLineWithClipping(
- c.x, c.y, c.z-r,
- c.x+r, c.y+r, c.z,
- 0xFF00FFFF, 0xFF00FFFF);
- CLines::RenderLineWithClipping(
- c.x-r, c.y-r, c.z,
- c.x, c.y, c.z+r,
- 0xFF00FFFF, 0xFF00FFFF);
- CLines::RenderLineWithClipping(
- c.x-r, c.y+r, c.z,
- c.x, c.y, c.z+r,
- 0xFF00FFFF, 0xFF00FFFF);
- CLines::RenderLineWithClipping(
- c.x+r, c.y-r, c.z,
- c.x, c.y, c.z+r,
- 0xFF00FFFF, 0xFF00FFFF);
- CLines::RenderLineWithClipping(
- c.x+r, c.y+r, c.z,
- c.x, c.y, c.z+r,
- 0xFF00FFFF, 0xFF00FFFF);
- }
-
- for(i = 0; i < colModel.numLines; i++){
- verts[0] = colModel.lines[i].p0;
- verts[1] = colModel.lines[i].p1;
-
- verts[0] = mat * verts[0];
- verts[1] = mat * verts[1];
-
- CLines::RenderLineWithClipping(
- verts[0].x, verts[0].y, verts[0].z,
- verts[1].x, verts[1].y, verts[1].z,
- 0x00FFFFFF, 0x00FFFFFF);
- }
-
- for(i = 0; i < colModel.numBoxes; i++){
- min = colModel.boxes[i].min;
- max = colModel.boxes[i].max;
-
- verts[0] = mat * CVector(min.x, min.y, min.z);
- verts[1] = mat * CVector(min.x, min.y, max.z);
- verts[2] = mat * CVector(min.x, max.y, min.z);
- verts[3] = mat * CVector(min.x, max.y, max.z);
- verts[4] = mat * CVector(max.x, min.y, min.z);
- verts[5] = mat * CVector(max.x, min.y, max.z);
- verts[6] = mat * CVector(max.x, max.y, min.z);
- verts[7] = mat * CVector(max.x, max.y, max.z);
-
- CLines::RenderLineWithClipping(
- verts[0].x, verts[0].y, verts[0].z,
- verts[1].x, verts[1].y, verts[1].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
- CLines::RenderLineWithClipping(
- verts[1].x, verts[1].y, verts[1].z,
- verts[3].x, verts[3].y, verts[3].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
- CLines::RenderLineWithClipping(
- verts[3].x, verts[3].y, verts[3].z,
- verts[2].x, verts[2].y, verts[2].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
- CLines::RenderLineWithClipping(
- verts[2].x, verts[2].y, verts[2].z,
- verts[0].x, verts[0].y, verts[0].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
-
- CLines::RenderLineWithClipping(
- verts[4].x, verts[4].y, verts[4].z,
- verts[5].x, verts[5].y, verts[5].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
- CLines::RenderLineWithClipping(
- verts[5].x, verts[5].y, verts[5].z,
- verts[7].x, verts[7].y, verts[7].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
- CLines::RenderLineWithClipping(
- verts[7].x, verts[7].y, verts[7].z,
- verts[6].x, verts[6].y, verts[6].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
- CLines::RenderLineWithClipping(
- verts[6].x, verts[6].y, verts[6].z,
- verts[4].x, verts[4].y, verts[4].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
-
- CLines::RenderLineWithClipping(
- verts[0].x, verts[0].y, verts[0].z,
- verts[4].x, verts[4].y, verts[4].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
- CLines::RenderLineWithClipping(
- verts[1].x, verts[1].y, verts[1].z,
- verts[5].x, verts[5].y, verts[5].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
- CLines::RenderLineWithClipping(
- verts[2].x, verts[2].y, verts[2].z,
- verts[6].x, verts[6].y, verts[6].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
- CLines::RenderLineWithClipping(
- verts[3].x, verts[3].y, verts[3].z,
- verts[7].x, verts[7].y, verts[7].z,
- 0xFFFFFFFF, 0xFFFFFFFF);
- }
-
- for(i = 0; i < colModel.numTriangles; i++){
- colModel.GetTrianglePoint(verts[0], colModel.triangles[i].a);
- colModel.GetTrianglePoint(verts[1], colModel.triangles[i].b);
- colModel.GetTrianglePoint(verts[2], colModel.triangles[i].c);
- verts[0] = mat * verts[0];
- verts[1] = mat * verts[1];
- verts[2] = mat * verts[2];
- CLines::RenderLineWithClipping(
- verts[0].x, verts[0].y, verts[0].z,
- verts[1].x, verts[1].y, verts[1].z,
- 0x00FF00FF, 0x00FF00FF);
- CLines::RenderLineWithClipping(
- verts[0].x, verts[0].y, verts[0].z,
- verts[2].x, verts[2].y, verts[2].z,
- 0x00FF00FF, 0x00FF00FF);
- CLines::RenderLineWithClipping(
- verts[1].x, verts[1].y, verts[1].z,
- verts[2].x, verts[2].y, verts[2].z,
- 0x00FF00FF, 0x00FF00FF);
- }
-
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
-}
-
-void
-CCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id)
-{
- int i;
- int s;
- float f;
- CVector verts[8];
- CVector min, max;
- int r, g, b;
- RwImVertexIndex *iptr;
- RwIm3DVertex *vptr;
-
- RenderBuffer::ClearRenderBuffer();
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
-
- for(i = 0; i < colModel.numTriangles; i++){
- colModel.GetTrianglePoint(verts[0], colModel.triangles[i].a);
- colModel.GetTrianglePoint(verts[1], colModel.triangles[i].b);
- colModel.GetTrianglePoint(verts[2], colModel.triangles[i].c);
- verts[0] = mat * verts[0];
- verts[1] = mat * verts[1];
- verts[2] = mat * verts[2];
-
- // game doesn't do this
- r = 255;
- g = 128;
- b = 0;
-
- s = colModel.triangles[i].surface;
- f = (s & 0xF)/32.0f + 0.5f;
- switch(CSurfaceTable::GetAdhesionGroup(s)){
- case ADHESIVE_RUBBER:
- r = f * 255.0f;
- g = 0;
- b = 0;
- break;
- case ADHESIVE_HARD:
- r = f*255.0f;
- g = f*255.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_ROAD:
- r = f*128.0f;
- g = f*128.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_LOOSE:
- r = 0;
- g = f * 255.0f;
- b = 0;
- break;
- case ADHESIVE_WET:
- r = 0;
- g = 0;
- b = f * 255.0f;
- break;
- default:
- // this doesn't make much sense
- r *= f;
- g *= f;
- b *= f;
- }
-
- if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE ||
- s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE)
- if(CTimer::GetFrameCounter() & 1){
- r = 0;
- g = 0;
- b = 0;
- }
-
- if(s > SURFACE_METAL_GATE){
- r = CGeneral::GetRandomNumber();
- g = CGeneral::GetRandomNumber();
- b = CGeneral::GetRandomNumber();
- printf("Illegal surfacetype:%d on MI:%d\n", s, id);
- }
-
- RenderBuffer::StartStoring(6, 3, &iptr, &vptr);
- RwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255);
- RwIm3DVertexSetRGBA(&vptr[1], r, g, b, 255);
- RwIm3DVertexSetRGBA(&vptr[2], r, g, b, 255);
- RwIm3DVertexSetU(&vptr[0], 0.0f);
- RwIm3DVertexSetV(&vptr[0], 0.0f);
- RwIm3DVertexSetU(&vptr[1], 0.0f);
- RwIm3DVertexSetV(&vptr[1], 1.0f);
- RwIm3DVertexSetU(&vptr[2], 1.0f);
- RwIm3DVertexSetV(&vptr[2], 1.0f);
- RwIm3DVertexSetPos(&vptr[0], verts[0].x, verts[0].y, verts[0].z);
- RwIm3DVertexSetPos(&vptr[1], verts[1].x, verts[1].y, verts[1].z);
- RwIm3DVertexSetPos(&vptr[2], verts[2].x, verts[2].y, verts[2].z);
- iptr[0] = 0; iptr[1] = 1; iptr[2] = 2;
- iptr[3] = 0; iptr[4] = 2; iptr[5] = 1;
- RenderBuffer::StopStoring();
- }
-
- for(i = 0; i < colModel.numBoxes; i++){
- min = colModel.boxes[i].min;
- max = colModel.boxes[i].max;
-
- verts[0] = mat * CVector(min.x, min.y, min.z);
- verts[1] = mat * CVector(min.x, min.y, max.z);
- verts[2] = mat * CVector(min.x, max.y, min.z);
- verts[3] = mat * CVector(min.x, max.y, max.z);
- verts[4] = mat * CVector(max.x, min.y, min.z);
- verts[5] = mat * CVector(max.x, min.y, max.z);
- verts[6] = mat * CVector(max.x, max.y, min.z);
- verts[7] = mat * CVector(max.x, max.y, max.z);
-
- s = colModel.boxes[i].surface;
- f = (s & 0xF)/32.0f + 0.5f;
- switch(CSurfaceTable::GetAdhesionGroup(s)){
- case ADHESIVE_RUBBER:
- r = f * 255.0f;
- g = 0;
- b = 0;
- break;
- case ADHESIVE_HARD:
- r = f*255.0f;
- g = f*255.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_ROAD:
- r = f*128.0f;
- g = f*128.0f;
- b = f*128.0f;
- break;
- case ADHESIVE_LOOSE:
- r = 0;
- g = f * 255.0f;
- b = 0;
- break;
- case ADHESIVE_WET:
- r = 0;
- g = 0;
- b = f * 255.0f;
- break;
- default:
- // this doesn't make much sense
- r *= f;
- g *= f;
- b *= f;
- }
-
- if(s == SURFACE_TRANSPARENT_CLOTH || s == SURFACE_METAL_CHAIN_FENCE ||
- s == SURFACE_TRANSPARENT_STONE || s == SURFACE_SCAFFOLD_POLE)
- if(CTimer::GetFrameCounter() & 1){
- r = 0;
- g = 0;
- b = 0;
- }
-
- RenderBuffer::StartStoring(36, 8, &iptr, &vptr);
- RwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255);
- RwIm3DVertexSetRGBA(&vptr[1], r, g, b, 255);
- RwIm3DVertexSetRGBA(&vptr[2], r, g, b, 255);
- RwIm3DVertexSetRGBA(&vptr[3], r, g, b, 255);
- RwIm3DVertexSetRGBA(&vptr[4], r, g, b, 255);
- RwIm3DVertexSetRGBA(&vptr[5], r, g, b, 255);
- RwIm3DVertexSetRGBA(&vptr[6], r, g, b, 255);
- RwIm3DVertexSetRGBA(&vptr[7], r, g, b, 255);
- RwIm3DVertexSetU(&vptr[0], 0.0f);
- RwIm3DVertexSetV(&vptr[0], 0.0f);
- RwIm3DVertexSetU(&vptr[1], 0.0f);
- RwIm3DVertexSetV(&vptr[1], 1.0f);
- RwIm3DVertexSetU(&vptr[2], 1.0f);
- RwIm3DVertexSetV(&vptr[2], 1.0f);
- RwIm3DVertexSetU(&vptr[3], 0.0f);
- RwIm3DVertexSetV(&vptr[3], 0.0f);
- RwIm3DVertexSetU(&vptr[4], 0.0f);
- RwIm3DVertexSetV(&vptr[4], 1.0f);
- RwIm3DVertexSetU(&vptr[5], 1.0f);
- RwIm3DVertexSetV(&vptr[5], 1.0f);
- RwIm3DVertexSetU(&vptr[6], 0.0f);
- RwIm3DVertexSetV(&vptr[6], 1.0f);
- RwIm3DVertexSetU(&vptr[7], 1.0f);
- RwIm3DVertexSetV(&vptr[7], 1.0f);
- RwIm3DVertexSetPos(&vptr[0], verts[0].x, verts[0].y, verts[0].z);
- RwIm3DVertexSetPos(&vptr[1], verts[1].x, verts[1].y, verts[1].z);
- RwIm3DVertexSetPos(&vptr[2], verts[2].x, verts[2].y, verts[2].z);
- RwIm3DVertexSetPos(&vptr[3], verts[3].x, verts[3].y, verts[3].z);
- RwIm3DVertexSetPos(&vptr[4], verts[4].x, verts[4].y, verts[4].z);
- RwIm3DVertexSetPos(&vptr[5], verts[5].x, verts[5].y, verts[5].z);
- RwIm3DVertexSetPos(&vptr[6], verts[6].x, verts[6].y, verts[6].z);
- RwIm3DVertexSetPos(&vptr[7], verts[7].x, verts[7].y, verts[7].z);
- iptr[0] = 0; iptr[1] = 1; iptr[2] = 2;
- iptr[3] = 1; iptr[4] = 3; iptr[5] = 2;
- iptr[6] = 1; iptr[7] = 5; iptr[8] = 7;
- iptr[9] = 1; iptr[10] = 7; iptr[11] = 3;
- iptr[12] = 2; iptr[13] = 3; iptr[14] = 7;
- iptr[15] = 2; iptr[16] = 7; iptr[17] = 6;
- iptr[18] = 0; iptr[19] = 5; iptr[20] = 1;
- iptr[21] = 0; iptr[22] = 4; iptr[23] = 5;
- iptr[24] = 0; iptr[25] = 2; iptr[26] = 4;
- iptr[27] = 2; iptr[28] = 6; iptr[29] = 4;
- iptr[30] = 4; iptr[31] = 6; iptr[32] = 7;
- iptr[33] = 4; iptr[34] = 7; iptr[35] = 5;
- RenderBuffer::StopStoring();
- }
-
- RenderBuffer::RenderStuffInBuffer();
- RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
- RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
- RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
- RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
-}
-
-
-/*
- * ColModel code
- */
-
-void
-CColSphere::Set(float radius, const CVector &center, uint8 surf, uint8 piece)
-{
- this->radius = radius;
- this->center = center;
- this->surface = surf;
- this->piece = piece;
-}
-
-void
-CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece)
-{
- this->min = min;
- this->max = max;
- this->surface = surf;
- this->piece = piece;
-}
-
-void
-CColLine::Set(const CVector &p0, const CVector &p1)
-{
- this->p0 = p0;
- this->p1 = p1;
-}
-
-void
-CColTriangle::Set(const CompressedVector *, int a, int b, int c, uint8 surf, uint8 piece)
-{
- this->a = a;
- this->b = b;
- this->c = c;
- this->surface = surf;
-}
-
-#ifdef VU_COLLISION
-void
-CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
-{
- CVector norm = CrossProduct(vc-va, vb-va);
- norm.Normalise();
- float d = DotProduct(norm, va);
- normal.x = norm.x*4096.0f;
- normal.y = norm.y*4096.0f;
- normal.z = norm.z*4096.0f;
- dist = d*128.0f;
-}
-#else
-void
-CColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)
-{
- normal = CrossProduct(vc-va, vb-va);
- normal.Normalise();
- dist = DotProduct(normal, va);
- CVector an(Abs(normal.x), Abs(normal.y), Abs(normal.z));
- // find out largest component and its direction
- if(an.x > an.y && an.x > an.z)
- dir = normal.x < 0.0f ? DIR_X_NEG : DIR_X_POS;
- else if(an.y > an.z)
- dir = normal.y < 0.0f ? DIR_Y_NEG : DIR_Y_POS;
- else
- dir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS;
-}
-#endif
-
-CColModel::CColModel(void)
-{
- numSpheres = 0;
- spheres = nil;
- numLines = 0;
- lines = nil;
- numBoxes = 0;
- boxes = nil;
- numTriangles = 0;
- vertices = nil;
- triangles = nil;
- trianglePlanes = nil;
- level = CGame::currLevel;
- ownsCollisionVolumes = true;
-}
-
-CColModel::~CColModel(void)
-{
- RemoveCollisionVolumes();
- RemoveTrianglePlanes();
-}
-
-void
-CColModel::RemoveCollisionVolumes(void)
-{
- if(ownsCollisionVolumes){
- RwFree(spheres);
- RwFree(lines);
- RwFree(boxes);
- RwFree(vertices);
- RwFree(triangles);
- }
- numSpheres = 0;
- numLines = 0;
- numBoxes = 0;
- numTriangles = 0;
- spheres = nil;
- lines = nil;
- boxes = nil;
- vertices = nil;
- triangles = nil;
-}
-
-void
-CColModel::CalculateTrianglePlanes(void)
-{
- // HACK: allocate space for one more element to stuff the link pointer into
- trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1));
- for(int i = 0; i < numTriangles; i++)
- trianglePlanes[i].Set(vertices, triangles[i]);
-}
-
-void
-CColModel::RemoveTrianglePlanes(void)
-{
- RwFree(trianglePlanes);
- trianglePlanes = nil;
-}
-
-void
-CColModel::SetLinkPtr(CLink<CColModel*> *lptr)
-{
- assert(trianglePlanes);
- *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]) = lptr;
-}
-
-CLink<CColModel*>*
-CColModel::GetLinkPtr(void)
-{
- assert(trianglePlanes);
- return *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]);
-}
-
-void
-CColModel::GetTrianglePoint(CVector &v, int i) const
-{
- v = vertices[i].Get();
-}
-
-CColModel&
-CColModel::operator=(const CColModel &other)
-{
- int i;
- int numVerts;
-
- boundingSphere = other.boundingSphere;
- boundingBox = other.boundingBox;
-
- // copy spheres
- if(other.numSpheres){
- if(numSpheres != other.numSpheres){
- numSpheres = other.numSpheres;
- if(spheres)
- RwFree(spheres);
- spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere));
- }
- for(i = 0; i < numSpheres; i++)
- spheres[i] = other.spheres[i];
- }else{
- numSpheres = 0;
- if(spheres)
- RwFree(spheres);
- spheres = nil;
- }
-
- // copy lines
- if(other.numLines){
- if(numLines != other.numLines){
- numLines = other.numLines;
- if(lines)
- RwFree(lines);
- lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine));
- }
- for(i = 0; i < numLines; i++)
- lines[i] = other.lines[i];
- }else{
- numLines = 0;
- if(lines)
- RwFree(lines);
- lines = nil;
- }
-
- // copy boxes
- if(other.numBoxes){
- if(numBoxes != other.numBoxes){
- numBoxes = other.numBoxes;
- if(boxes)
- RwFree(boxes);
- boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox));
- }
- for(i = 0; i < numBoxes; i++)
- boxes[i] = other.boxes[i];
- }else{
- numBoxes = 0;
- if(boxes)
- RwFree(boxes);
- boxes = nil;
- }
-
- // copy mesh
- if(other.numTriangles){
- // copy vertices
- numVerts = 0;
- for(i = 0; i < other.numTriangles; i++){
- if(other.triangles[i].a > numVerts)
- numVerts = other.triangles[i].a;
- if(other.triangles[i].b > numVerts)
- numVerts = other.triangles[i].b;
- if(other.triangles[i].c > numVerts)
- numVerts = other.triangles[i].c;
- }
- numVerts++;
- if(vertices)
- RwFree(vertices);
- if(numVerts){
- vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
- for(i = 0; i < numVerts; i++)
- vertices[i] = other.vertices[i];
- }
-
- // copy triangles
- if(numTriangles != other.numTriangles){
- numTriangles = other.numTriangles;
- if(triangles)
- RwFree(triangles);
- triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
- }
- for(i = 0; i < numTriangles; i++)
- triangles[i] = other.triangles[i];
- }else{
- numTriangles = 0;
- if(triangles)
- RwFree(triangles);
- triangles = nil;
- if(vertices)
- RwFree(vertices);
- vertices = nil;
- }
- return *this;
-}
diff --git a/src/core/Collision.h b/src/core/Collision.h
deleted file mode 100644
index da94dd34..00000000
--- a/src/core/Collision.h
+++ /dev/null
@@ -1,254 +0,0 @@
-#pragma once
-
-#include "templates.h"
-#include "Game.h" // for eLevelName
-#ifdef VU_COLLISION
-#include "VuVector.h"
-#endif
-
-// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32.
-#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE)
-#define MAX_COLLISION_POINTS 64
-#else
-#define MAX_COLLISION_POINTS 32
-#endif
-
-struct CompressedVector
-{
-#ifdef COMPRESSED_COL_VECTORS
- int16 x, y, z;
- CVector Get(void) const { return CVector(x, y, z)/128.0f; };
- void Set(float x, float y, float z) { this->x = x*128.0f; this->y = y*128.0f; this->z = z*128.0f; };
-#ifdef GTA_PS2
- void Unpack(uint128 &qword) const {
- __asm__ volatile (
- "lh $8, 0(%1)\n"
- "lh $9, 2(%1)\n"
- "lh $10, 4(%1)\n"
- "pextlw $10, $8\n"
- "pextlw $2, $9, $10\n"
- "sq $2, %0\n"
- : "=m" (qword)
- : "r" (this)
- : "$8", "$9", "$10", "$2"
- );
- }
-#else
- void Unpack(int32 *qword) const {
- qword[0] = x;
- qword[1] = y;
- qword[2] = z;
- qword[3] = 0; // junk
- }
-#endif
-#else
- float x, y, z;
- CVector Get(void) const { return CVector(x, y, z); };
- void Set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; };
-#endif
-};
-
-struct CColSphere
-{
- // NB: this has to be compatible with a CVuVector
- CVector center;
- float radius;
- uint8 surface;
- uint8 piece;
-
- void Set(float radius, const CVector &center, uint8 surf, uint8 piece);
- void Set(float radius, const CVector &center) { this->center = center; this->radius = radius; }
-};
-
-struct CColBox
-{
- CVector min;
- CVector max;
- uint8 surface;
- uint8 piece;
-
- void Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece);
- CVector GetSize(void) { return max - min; }
-};
-
-struct CColLine
-{
- // NB: this has to be compatible with two CVuVectors
- CVector p0;
- int pad0;
- CVector p1;
- int pad1;
-
- CColLine(void) { };
- CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; };
- void Set(const CVector &p0, const CVector &p1);
-};
-
-struct CColTriangle
-{
- uint16 a;
- uint16 b;
- uint16 c;
- uint8 surface;
-
- void Set(const CompressedVector *v, int a, int b, int c, uint8 surf, uint8 piece);
-};
-
-struct CColTrianglePlane
-{
-#ifdef VU_COLLISION
- CompressedVector normal;
- int16 dist;
-
- void Set(const CVector &va, const CVector &vb, const CVector &vc);
- void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
- void GetNormal(CVector &n) const { n.x = normal.x/4096.0f; n.y = normal.y/4096.0f; n.z = normal.z/4096.0f; }
- float CalcPoint(const CVector &v) const { CVector n; GetNormal(n); return DotProduct(n, v) - dist/128.0f; };
-#ifdef GTA_PS2
- void Unpack(uint128 &qword) const {
- __asm__ volatile (
- "lh $8, 0(%1)\n"
- "lh $9, 2(%1)\n"
- "lh $10, 4(%1)\n"
- "lh $11, 6(%1)\n"
- "pextlw $10, $8\n"
- "pextlw $11, $9\n"
- "pextlw $2, $11, $10\n"
- "sq $2, %0\n"
- : "=m" (qword)
- : "r" (this)
- : "$8", "$9", "$10", "$11", "$2"
- );
- }
-#else
- void Unpack(int32 *qword) const {
- qword[0] = normal.x;
- qword[1] = normal.y;
- qword[2] = normal.z;
- qword[3] = dist;
- }
-#endif
-#else
- CVector normal;
- float dist;
- uint8 dir;
-
- void Set(const CVector &va, const CVector &vb, const CVector &vc);
- void Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }
- void GetNormal(CVector &n) const { n = normal; }
- float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
-#endif
-};
-
-struct CColPoint
-{
- CVector point;
- int pad1;
- // the surface normal on the surface of point
- CVector normal;
- int pad2;
- uint8 surfaceA;
- uint8 pieceA;
- uint8 surfaceB;
- uint8 pieceB;
- float depth;
-
- void Set(float depth, uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {
- this->depth = depth;
- this->surfaceA = surfA;
- this->pieceA = pieceA;
- this->surfaceB = surfB;
- this->pieceB = pieceB;
- }
- void Set(uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {
- this->surfaceA = surfA;
- this->pieceA = pieceA;
- this->surfaceB = surfB;
- this->pieceB = pieceB;
- }
-};
-
-struct CStoredCollPoly
-{
-#ifdef VU_COLLISION
- CVuVector verts[3];
-#else
- CVector verts[3];
-#endif
- bool valid;
-};
-
-struct CColModel
-{
- CColSphere boundingSphere;
- CColBox boundingBox;
- int16 numSpheres;
- int16 numLines;
- int16 numBoxes;
- int16 numTriangles;
- int32 level;
- bool ownsCollisionVolumes; // missing on PS2
- CColSphere *spheres;
- CColLine *lines;
- CColBox *boxes;
- CompressedVector *vertices;
- CColTriangle *triangles;
- CColTrianglePlane *trianglePlanes;
-
- CColModel(void);
- ~CColModel(void);
- void RemoveCollisionVolumes(void);
- void CalculateTrianglePlanes(void);
- void RemoveTrianglePlanes(void);
- CLink<CColModel*> *GetLinkPtr(void);
- void SetLinkPtr(CLink<CColModel*>*);
- void GetTrianglePoint(CVector &v, int i) const;
-
- CColModel& operator=(const CColModel& other);
-};
-
-class CCollision
-{
-public:
- static eLevelName ms_collisionInMemory;
- static CLinkList<CColModel*> ms_colModelCache;
-#ifdef NO_ISLAND_LOADING
- static bool bAlreadyLoaded;
-#endif
-
- static void Init(void);
- static void Shutdown(void);
- static void Update(void);
- static void LoadCollisionWhenINeedIt(bool changeLevel);
- static void SortOutCollisionAfterLoad(void);
- static void LoadCollisionScreen(eLevelName level);
- static void DrawColModel(const CMatrix &mat, const CColModel &colModel);
- static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
-
- static void CalculateTrianglePlanes(CColModel *model);
-
- // all these return true if there's a collision
- static bool TestSphereSphere(const CColSphere &s1, const CColSphere &s2);
- static bool TestSphereBox(const CColSphere &sph, const CColBox &box);
- static bool TestLineBox(const CColLine &line, const CColBox &box);
- static bool TestVerticalLineBox(const CColLine &line, const CColBox &box);
- static bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
- static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
- static bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
- static bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough);
-
- static bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq);
- static bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq);
- static bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist);
- static bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly);
- static bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist);
- static bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);
- static bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);
- static bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough);
- static bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, CStoredCollPoly *poly);
- static int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);
- static bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);
-
- static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point);
- static float DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest);
-};
diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp
index 576a58b1..cadba7f2 100644
--- a/src/core/ControllerConfig.cpp
+++ b/src/core/ControllerConfig.cpp
@@ -2316,8 +2316,252 @@ int32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction act
return num;
}
+#ifdef BIND_VEHICLE_FIREWEAPON
+#define VFB(b) b,
+#else
+#define VFB(b)
+#endif
+
+#define CONTROLLER_BUTTONS(T, O, X, Q, L1, L2, L3, R1, R2, R3, SELECT) \
+ {{ \
+ O, /* PED_FIREWEAPON */ \
+ R2, /* PED_CYCLE_WEAPON_RIGHT */ \
+ L2, /* PED_CYCLE_WEAPON_LEFT */ \
+ nil, /* GO_FORWARD */ \
+ nil, /* GO_BACK */ \
+ nil, /* GO_LEFT */ \
+ nil, /* GO_RIGHT */ \
+ Q, /* PED_SNIPER_ZOOM_IN */ \
+ X, /* PED_SNIPER_ZOOM_OUT */ \
+ T, /* VEHICLE_ENTER_EXIT */ \
+ SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \
+ Q, /* PED_JUMPING */ \
+ X, /* PED_SPRINT */ \
+ R3, /* PED_LOOKBEHIND */ \
+ VFB(O) /* VEHICLE_FIREWEAPON */ \
+ X, /* VEHICLE_ACCELERATE */ \
+ Q, /* VEHICLE_BRAKE */ \
+ L1, /* VEHICLE_CHANGE_RADIO_STATION */ \
+ L3, /* VEHICLE_HORN */ \
+ R3, /* TOGGLE_SUBMISSIONS */ \
+ R1, /* VEHICLE_HANDBRAKE */ \
+ nil, /* PED_1RST_PERSON_LOOK_LEFT */ \
+ nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \
+ L2, /* VEHICLE_LOOKLEFT */ \
+ R2, /* VEHICLE_LOOKRIGHT */ \
+ nil, /* VEHICLE_LOOKBEHIND */ \
+ nil, /* VEHICLE_TURRETLEFT */ \
+ nil, /* VEHICLE_TURRETRIGHT */ \
+ nil, /* VEHICLE_TURRETUP */ \
+ nil, /* VEHICLE_TURRETDOWN */ \
+ L2, /* PED_CYCLE_TARGET_LEFT */ \
+ R2, /* PED_CYCLE_TARGET_RIGHT */ \
+ L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
+ R1, /* PED_LOCK_TARGET */ \
+ nil, /* NETWORK_TALK */ \
+ nil, /* PED_1RST_PERSON_LOOK_UP */ \
+ nil, /* PED_1RST_PERSON_LOOK_DOWN */ \
+ nil, /* _CONTROLLERACTION_36 */ \
+ nil, /* TOGGLE_DPAD */ \
+ nil, /* SWITCH_DEBUG_CAM_ON */ \
+ nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
+ }, \
+ { \
+ O, /* PED_FIREWEAPON */ \
+ R2, /* PED_CYCLE_WEAPON_RIGHT */ \
+ L2, /* PED_CYCLE_WEAPON_LEFT */ \
+ nil, /* GO_FORWARD */ \
+ nil, /* GO_BACK */ \
+ nil, /* GO_LEFT */ \
+ nil, /* GO_RIGHT */ \
+ Q, /* PED_SNIPER_ZOOM_IN */ \
+ X, /* PED_SNIPER_ZOOM_OUT */ \
+ T, /* VEHICLE_ENTER_EXIT */ \
+ SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \
+ Q, /* PED_JUMPING */ \
+ X, /* PED_SPRINT */ \
+ R3, /* PED_LOOKBEHIND */ \
+ VFB(O) /* VEHICLE_FIREWEAPON */ \
+ X, /* VEHICLE_ACCELERATE */ \
+ Q, /* VEHICLE_BRAKE */ \
+ SELECT, /* VEHICLE_CHANGE_RADIO_STATION */ \
+ L1, /* VEHICLE_HORN */ \
+ R3, /* TOGGLE_SUBMISSIONS */ \
+ R1, /* VEHICLE_HANDBRAKE */ \
+ nil, /* PED_1RST_PERSON_LOOK_LEFT */ \
+ nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \
+ L2, /* VEHICLE_LOOKLEFT */ \
+ R2, /* VEHICLE_LOOKRIGHT */ \
+ nil, /* VEHICLE_LOOKBEHIND */ \
+ nil, /* VEHICLE_TURRETLEFT */ \
+ nil, /* VEHICLE_TURRETRIGHT */ \
+ nil, /* VEHICLE_TURRETUP */ \
+ nil, /* VEHICLE_TURRETDOWN */ \
+ L2, /* PED_CYCLE_TARGET_LEFT */ \
+ R2, /* PED_CYCLE_TARGET_RIGHT */ \
+ L1, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
+ R1, /* PED_LOCK_TARGET */ \
+ nil, /* NETWORK_TALK */ \
+ nil, /* PED_1RST_PERSON_LOOK_UP */ \
+ nil, /* PED_1RST_PERSON_LOOK_DOWN */ \
+ nil, /* _CONTROLLERACTION_36 */ \
+ nil, /* TOGGLE_DPAD */ \
+ nil, /* SWITCH_DEBUG_CAM_ON */ \
+ nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
+ }, \
+ { \
+ X, /* PED_FIREWEAPON */ \
+ R2, /* PED_CYCLE_WEAPON_RIGHT */ \
+ L2, /* PED_CYCLE_WEAPON_LEFT */ \
+ nil, /* GO_FORWARD */ \
+ nil, /* GO_BACK */ \
+ nil, /* GO_LEFT */ \
+ nil, /* GO_RIGHT */ \
+ T, /* PED_SNIPER_ZOOM_IN */ \
+ Q, /* PED_SNIPER_ZOOM_OUT */ \
+ L1, /* VEHICLE_ENTER_EXIT */ \
+ SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \
+ Q, /* PED_JUMPING */ \
+ O, /* PED_SPRINT */ \
+ R3, /* PED_LOOKBEHIND */ \
+ VFB(O) /* VEHICLE_FIREWEAPON */ \
+ X, /* VEHICLE_ACCELERATE */ \
+ Q, /* VEHICLE_BRAKE */ \
+ L3, /* VEHICLE_CHANGE_RADIO_STATION */ \
+ R1, /* VEHICLE_HORN */ \
+ R3, /* TOGGLE_SUBMISSIONS */ \
+ T, /* VEHICLE_HANDBRAKE */ \
+ nil, /* PED_1RST_PERSON_LOOK_LEFT */ \
+ nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \
+ L2, /* VEHICLE_LOOKLEFT */ \
+ R2, /* VEHICLE_LOOKRIGHT */ \
+ nil, /* VEHICLE_LOOKBEHIND */ \
+ nil, /* VEHICLE_TURRETLEFT */ \
+ nil, /* VEHICLE_TURRETRIGHT */ \
+ nil, /* VEHICLE_TURRETUP */ \
+ nil, /* VEHICLE_TURRETDOWN */ \
+ L2, /* PED_CYCLE_TARGET_LEFT */ \
+ R2, /* PED_CYCLE_TARGET_RIGHT */ \
+ T, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
+ R1, /* PED_LOCK_TARGET */ \
+ nil, /* NETWORK_TALK */ \
+ nil, /* PED_1RST_PERSON_LOOK_UP */ \
+ nil, /* PED_1RST_PERSON_LOOK_DOWN */ \
+ nil, /* _CONTROLLERACTION_36 */ \
+ nil, /* TOGGLE_DPAD */ \
+ nil, /* SWITCH_DEBUG_CAM_ON */ \
+ nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
+ }, \
+ { \
+ R1, /* PED_FIREWEAPON */ \
+ R2, /* PED_CYCLE_WEAPON_RIGHT */ \
+ L2, /* PED_CYCLE_WEAPON_LEFT */ \
+ nil, /* GO_FORWARD */ \
+ nil, /* GO_BACK */ \
+ nil, /* GO_LEFT */ \
+ nil, /* GO_RIGHT */ \
+ Q, /* PED_SNIPER_ZOOM_IN */ \
+ X, /* PED_SNIPER_ZOOM_OUT */ \
+ T, /* VEHICLE_ENTER_EXIT */ \
+ SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */ \
+ Q, /* PED_JUMPING */ \
+ X, /* PED_SPRINT */ \
+ R3, /* PED_LOOKBEHIND */ \
+ VFB(R1) /* VEHICLE_FIREWEAPON */ \
+ nil, /* VEHICLE_ACCELERATE */ \
+ nil, /* VEHICLE_BRAKE */ \
+ O, /* VEHICLE_CHANGE_RADIO_STATION */ \
+ L3, /* VEHICLE_HORN */ \
+ Q, /* TOGGLE_SUBMISSIONS */ \
+ L1, /* VEHICLE_HANDBRAKE */ \
+ nil, /* PED_1RST_PERSON_LOOK_LEFT */ \
+ nil, /* PED_1RST_PERSON_LOOK_RIGHT */ \
+ L2, /* VEHICLE_LOOKLEFT */ \
+ R2, /* VEHICLE_LOOKRIGHT */ \
+ nil, /* VEHICLE_LOOKBEHIND */ \
+ nil, /* VEHICLE_TURRETLEFT */ \
+ nil, /* VEHICLE_TURRETRIGHT */ \
+ nil, /* VEHICLE_TURRETUP */ \
+ nil, /* VEHICLE_TURRETDOWN */ \
+ L2, /* PED_CYCLE_TARGET_LEFT */ \
+ R2, /* PED_CYCLE_TARGET_RIGHT */ \
+ O, /* PED_CENTER_CAMERA_BEHIND_PLAYER */ \
+ L1, /* PED_LOCK_TARGET */ \
+ nil, /* NETWORK_TALK */ \
+ nil, /* PED_1RST_PERSON_LOOK_UP */ \
+ nil, /* PED_1RST_PERSON_LOOK_DOWN */ \
+ nil, /* _CONTROLLERACTION_36 */ \
+ nil, /* TOGGLE_DPAD */ \
+ nil, /* SWITCH_DEBUG_CAM_ON */ \
+ nil, /* TAKE_SCREEN_SHOT */ \
+ nil, /* SHOW_MOUSE_POINTER_TOGGLE */ \
+ }}
+
+
+const char *XboxButtons_noIcons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("Y", "B", "A", "X", "LB", "LT", "LS", "RB", "RT", "RS", "BACK");
+
+#ifdef BUTTON_ICONS
+const char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS("~T~", "~O~", "~X~", "~Q~", "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "BACK");
+#endif
+
+
+#if 0 // set 1 for ps2 fonts
+#define PS2_TRIANGLE "\""
+#define PS2_CIRCLE "|"
+#define PS2_CROSS "/"
+#define PS2_SQUARE "^"
+#elif defined(BUTTON_ICONS)
+#define PS2_TRIANGLE "~T~"
+#define PS2_CIRCLE "~O~"
+#define PS2_CROSS "~X~"
+#define PS2_SQUARE "~Q~"
+#else
+#define PS2_TRIANGLE "TRIANGLE"
+#define PS2_CIRCLE "CIRCLE"
+#define PS2_CROSS "CROSS"
+#define PS2_SQUARE "SQUARE"
+#endif
+
+const char *PlayStationButtons_noIcons[][MAX_CONTROLLERACTIONS] =
+ CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "L1", "L2", "L3", "R1", "R2", "R3", "SELECT");
+
+#ifdef BUTTON_ICONS
+const char *PlayStationButtons[][MAX_CONTROLLERACTIONS] =
+ CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, "~K~", "~M~", "~A~", "~J~", "~V~", "~C~", "SELECT");
+#endif
+
+#undef PS2_TRIANGLE
+#undef PS2_CIRCLE
+#undef PS2_CROSS
+#undef PS2_SQUARE
+
+#undef CONTROLLER_BUTTONS
+#undef VFB
+
void CControllerConfigManager::GetWideStringOfCommandKeys(uint16 action, wchar *text, uint16 leight)
{
+#ifdef DETECT_PAD_INPUT_SWITCH
+ if (CPad::GetPad(0)->IsAffectedByController) {
+ wchar wstr[16];
+
+ // TODO: INI and/or menu setting for Xbox/PS switch
+#ifdef BUTTON_ICONS
+ const char *(*Buttons)[MAX_CONTROLLERACTIONS] = CFont::ButtonsSlot != -1 ? XboxButtons : XboxButtons_noIcons;
+#else
+ const char *(*Buttons)[MAX_CONTROLLERACTIONS] = XboxButtons_noIcons;
+#endif
+
+ assert(Buttons[CPad::GetPad(0)->Mode][action] != nil); // we cannot use these
+ AsciiToUnicode(Buttons[CPad::GetPad(0)->Mode][action], wstr);
+
+ CMessages::WideStringCopy(text, wstr, leight);
+ return;
+ }
+#endif
+
int32 nums = GetNumOfSettingsForAction((e_ControllerAction)action);
int32 sets = 0;
diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp
index aadafc29..b9d475b8 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -11,7 +11,6 @@
#include "HandlingMgr.h"
#include "CarCtrl.h"
#include "PedType.h"
-#include "PedStats.h"
#include "AnimManager.h"
#include "Game.h"
#include "RwHelper.h"
@@ -25,6 +24,7 @@
#include "ZoneCull.h"
#include "CdStream.h"
#include "FileLoader.h"
+#include "MemoryHeap.h"
char CFileLoader::ms_line[256];
@@ -59,7 +59,13 @@ CFileLoader::LoadLevel(const char *filename)
savedTxd = RwTexDictionaryCreate();
RwTexDictionarySetCurrent(savedTxd);
}
+#if GTA_VERSION <= GTA3_PS2_160
+ CFileMgr::ChangeDir("\\DATA\\");
+ fd = CFileMgr::OpenFile(filename, "r");
+ CFileMgr::ChangeDir("\\");
+#else
fd = CFileMgr::OpenFile(filename, "r");
+#endif
assert(fd > 0);
for(line = LoadLine(fd); line; line = LoadLine(fd)){
@@ -72,11 +78,13 @@ CFileLoader::LoadLevel(const char *filename)
if(strncmp(line, "IMAGEPATH", 9) == 0){
RwImageSetPath(line + 10);
}else if(strncmp(line, "TEXDICTION", 10) == 0){
+ PUSH_MEMID(MEMID_TEXTURES);
strcpy(txdname, line+11);
LoadingScreenLoadingFile(txdname);
RwTexDictionary *txd = LoadTexDictionary(txdname);
AddTexDictionaries(savedTxd, txd);
RwTexDictionaryDestroy(txd);
+ POP_MEMID();
}else if(strncmp(line, "COLFILE", 7) == 0){
int level;
sscanf(line+8, "%d", &level);
@@ -95,12 +103,16 @@ CFileLoader::LoadLevel(const char *filename)
LoadObjectTypes(line + 4);
}else if(strncmp(line, "IPL", 3) == 0){
if(!objectsLoaded){
+ PUSH_MEMID(MEMID_DEF_MODELS);
CModelInfo::ConstructMloClumps();
+ POP_MEMID();
CObjectData::Initialise("DATA\\OBJECT.DAT");
objectsLoaded = true;
}
+ PUSH_MEMID(MEMID_WORLD);
LoadingScreenLoadingFile(line + 4);
LoadScene(line + 4);
+ POP_MEMID();
}else if(strncmp(line, "MAPZONE", 7) == 0){
LoadingScreenLoadingFile(line + 8);
LoadMapZones(line + 8);
@@ -189,6 +201,8 @@ CFileLoader::LoadCollisionFile(const char *filename)
CBaseModelInfo *mi;
ColHeader header;
+ PUSH_MEMID(MEMID_COLLISION);
+
debug("Loading collision file %s\n", filename);
fd = CFileMgr::OpenFile(filename, "rb");
@@ -212,6 +226,8 @@ CFileLoader::LoadCollisionFile(const char *filename)
}
CFileMgr::CloseFile(fd);
+
+ POP_MEMID();
}
void
@@ -233,6 +249,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
buf += 44;
if(model.numSpheres > 0){
model.spheres = (CColSphere*)RwMalloc(model.numSpheres*sizeof(CColSphere));
+ REGISTER_MEMPTR(&model.spheres);
for(i = 0; i < model.numSpheres; i++){
model.spheres[i].Set(*(float*)buf, *(CVector*)(buf+4), buf[16], buf[17]);
buf += 20;
@@ -244,6 +261,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
buf += 4;
if(model.numLines > 0){
model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine));
+ REGISTER_MEMPTR(&model.lines);
for(i = 0; i < model.numLines; i++){
model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12));
buf += 24;
@@ -255,6 +273,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
buf += 4;
if(model.numBoxes > 0){
model.boxes = (CColBox*)RwMalloc(model.numBoxes*sizeof(CColBox));
+ REGISTER_MEMPTR(&model.boxes);
for(i = 0; i < model.numBoxes; i++){
model.boxes[i].Set(*(CVector*)buf, *(CVector*)(buf+12), buf[24], buf[25]);
buf += 28;
@@ -266,6 +285,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
buf += 4;
if(numVertices > 0){
model.vertices = (CompressedVector*)RwMalloc(numVertices*sizeof(CompressedVector));
+ REGISTER_MEMPTR(&model.vertices);
for(i = 0; i < numVertices; i++){
model.vertices[i].Set(*(float*)buf, *(float*)(buf+4), *(float*)(buf+8));
if(Abs(*(float*)buf) >= 256.0f ||
@@ -281,6 +301,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
buf += 4;
if(model.numTriangles > 0){
model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle));
+ REGISTER_MEMPTR(&model.triangles);
for(i = 0; i < model.numTriangles; i++){
model.triangles[i].Set(model.vertices, *(int32*)buf, *(int32*)(buf+4), *(int32*)(buf+8), buf[12], buf[13]);
buf += 16;
@@ -332,6 +353,16 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data)
return atomic;
}
+#ifdef LIBRW
+void
+InitClump(RpClump *clump)
+{
+ RpClumpForAllAtomics(clump, ConvertPlatformAtomic, nil);
+}
+#else
+#define InitClump(clump)
+#endif
+
void
CFileLoader::LoadModelFile(const char *filename)
{
@@ -343,6 +374,7 @@ CFileLoader::LoadModelFile(const char *filename)
if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){
clump = RpClumpStreamRead(stream);
if(clump){
+ InitClump(clump);
RpClumpForAllAtomics(clump, FindRelatedModelInfoCB, clump);
RpClumpDestroy(clump);
}
@@ -368,6 +400,7 @@ CFileLoader::LoadClumpFile(const char *filename)
GetNameAndLOD(nodename, name, &n);
mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(name, nil);
if(mi){
+ InitClump(clump);
assert(mi->IsClump());
mi->SetClump(clump);
}else
@@ -393,6 +426,7 @@ CFileLoader::LoadClumpFile(RwStream *stream, uint32 id)
if (mi->GetModelType() == MITYPE_PED && id != 0 && RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) {
// Read LOD ped
clump = RpClumpStreamRead(stream);
+ InitClump(clump);
if(clump){
((CPedModelInfo*)mi)->SetLowDetailClump(clump);
RpClumpDestroy(clump);
@@ -423,6 +457,7 @@ CFileLoader::FinishLoadClumpFile(RwStream *stream, uint32 id)
clump = RpClumpGtaStreamRead2(stream);
if(clump){
+ InitClump(clump);
mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id);
mi->SetClump(clump);
return true;
@@ -443,6 +478,7 @@ CFileLoader::LoadAtomicFile(RwStream *stream, uint32 id)
clump = RpClumpStreamRead(stream);
if(clump == nil)
return false;
+ InitClump(clump);
gpRelatedModelInfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);
RpClumpForAllAtomics(clump, SetRelatedModelInfoCB, clump);
RpClumpDestroy(clump);
@@ -806,6 +842,8 @@ CFileLoader::LoadAtomicFile2Return(const char *filename)
stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);
if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
clump = RpClumpStreamRead(stream);
+ if(clump)
+ InitClump(clump);
RwStreamClose(stream, nil);
return clump;
}
diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp
index 89b5ba3d..5597b358 100644
--- a/src/core/Frontend.cpp
+++ b/src/core/Frontend.cpp
@@ -41,14 +41,7 @@
#define TIDY_UP_PBP // ProcessButtonPresses
#define MAX_VISIBLE_LIST_ROW 30
#define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result
-
-#ifdef USE_PRECISE_MEASUREMENT_CONVERTION
-#define MILES_IN_METER 0.000621371192f
-#define FEET_IN_METER 3.28084f
-#else
-#define MILES_IN_METER 0.00059880241f
-#define FEET_IN_METER 3.33f
-#endif
+#define SCROLLABLE_PAGES
#ifdef SCROLLABLE_STATS_PAGE
#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS)
@@ -56,6 +49,34 @@
#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS)
#endif
+#define hasNativeList(screen) (screen == MENUPAGE_MULTIPLAYER_FIND_GAME || screen == MENUPAGE_SKIN_SELECT \
+ || screen == MENUPAGE_KEYBOARD_CONTROLS)
+
+#ifdef SCROLLABLE_PAGES
+#define MAX_VISIBLE_OPTION 12
+#define MAX_VISIBLE_OPTION_ON_SCREEN (hasNativeList(m_nCurrScreen) ? MAX_VISIBLE_LIST_ROW : MAX_VISIBLE_OPTION)
+
+int GetOptionCount(int screen)
+{
+ int i = 0;
+ for (; i < NUM_MENUROWS && aScreens[screen].m_aEntries[i].m_Action != MENUACTION_NOTHING; i++);
+ return i;
+}
+
+#define SETUP_SCROLLING(screen) \
+ if (!hasNativeList(screen)) { \
+ m_nTotalListRow = GetOptionCount(screen); \
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION) { \
+ m_nSelectedListRow = 0; \
+ m_nFirstVisibleRowOnList = 0; \
+ m_nScrollbarTopMargin = 0; \
+ } \
+ }
+#else
+#define MAX_VISIBLE_OPTION_ON_SCREEN MAX_VISIBLE_LIST_ROW
+#define SETUP_SCROLLING(screen)
+#endif
+
#ifdef TRIANGLE_BACK_BUTTON
#define GetBackJustUp GetTriangleJustUp
#define GetBackJustDown GetTriangleJustDown
@@ -80,13 +101,40 @@ float CMenuManager::fMapCenterX;
BottomBarOption bbNames[8];
int bbTabCount = 0;
bool bottomBarActive = false;
-bool reverseAlpha = false;
int pendingScreen = -1;
int pendingOption = -1;
int curBottomBarOption = -1;
int hoveredBottomBarOption = -1;
#endif
+#ifdef CUTSCENE_BORDERS_SWITCH
+bool CMenuManager::m_PrefsCutsceneBorders = true;
+#endif
+
+#ifdef MULTISAMPLING
+int8 CMenuManager::m_nPrefsMSAALevel = 0;
+int8 CMenuManager::m_nDisplayMSAALevel = 0;
+#endif
+
+#ifdef NO_ISLAND_LOADING
+int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW;
+#endif
+
+// Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway)
+#ifdef PS2_LIKE_MENU
+const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255);
+#else
+const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color
+#endif
+
+#ifdef USE_PRECISE_MEASUREMENT_CONVERTION
+#define MILES_IN_METER 0.000621371192f
+#define FEET_IN_METER 3.28084f
+#else
+#define MILES_IN_METER 0.00059880241f
+#define FEET_IN_METER 3.33f
+#endif
+
int32 CMenuManager::OS_Language = LANG_ENGLISH;
int8 CMenuManager::m_PrefsUseVibration;
int8 CMenuManager::m_DisplayControllerOnFoot;
@@ -112,31 +160,11 @@ int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt;
int32 CMenuManager::m_PrefsMusicVolume = 102;
int32 CMenuManager::m_PrefsSfxVolume = 102;
-#ifdef CUTSCENE_BORDERS_SWITCH
-bool CMenuManager::m_PrefsCutsceneBorders = true;
-#endif
-
-#ifdef MULTISAMPLING
-int8 CMenuManager::m_nPrefsMSAALevel = 0;
-int8 CMenuManager::m_nDisplayMSAALevel = 0;
-#endif
-
-#ifdef NO_ISLAND_LOADING
-int8 CMenuManager::m_DisplayIslandLoading = ISLAND_LOADING_LOW;
-int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW;
-#endif
char CMenuManager::m_PrefsSkinFile[256] = DEFAULT_SKIN_NAME;
int32 CMenuManager::m_KeyPressedCode = -1;
-// Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway)
-#ifdef PS2_LIKE_MENU
-const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255);
-#else
-const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color
-#endif
-
float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE;
float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE;
@@ -254,35 +282,12 @@ const char* MenuFilenames[][2] = {
#define PAGE_NAME_X SCREEN_SCALE_FROM_RIGHT
#endif
-#ifdef PS2_LIKE_MENU
-#define ChangeScreen(screen, option, updateDelay, withReverseAlpha) \
- do { \
- if (reverseAlpha) { \
- m_nPrevScreen = m_nCurrScreen; \
- m_nCurrScreen = pendingScreen; \
- m_nCurrOption = pendingOption; \
- reverseAlpha = false; \
- if (updateDelay) \
- m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \
- } \
- if (withReverseAlpha && !m_bRenderGameInMenu) { \
- pendingOption = option; \
- pendingScreen = screen; \
- reverseAlpha = true; \
- } else { \
- m_nPrevScreen = m_nCurrScreen; \
- m_nCurrScreen = screen; \
- m_nCurrOption = option; \
- if (updateDelay) \
- m_nScreenChangeDelayTimer = CTimer::GetTimeInMillisecondsPauseMode(); \
- } \
- m_nMenuFadeAlpha = 255; \
- } while(0)
-#else
+// Seperate func. in VC
#define ChangeScreen(screen, option, updateDelay, clearAlpha) \
do { \
m_nPrevScreen = m_nCurrScreen; \
int newOpt = option; \
+ SETUP_SCROLLING(screen) \
m_nCurrScreen = screen; \
m_nCurrOption = newOpt; \
if(updateDelay) \
@@ -290,7 +295,6 @@ const char* MenuFilenames[][2] = {
if(clearAlpha) \
m_nMenuFadeAlpha = 0; \
} while(0)
-#endif
#define PREPARE_MENU_HEADER \
CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); \
@@ -341,8 +345,8 @@ CMenuManager::ScrollUpListByOne()
void
CMenuManager::ScrollDownListByOne()
{
- if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1) {
- if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) {
+ if (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1) {
+ if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) {
m_nSelectedListRow++;
m_nFirstVisibleRowOnList++;
m_nScrollbarTopMargin += SCROLLBAR_MAX_HEIGHT / m_nTotalListRow;
@@ -357,13 +361,13 @@ CMenuManager::ScrollDownListByOne()
void
CMenuManager::PageUpList(bool playSoundOnSuccess)
{
- if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) {
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) {
if (m_nFirstVisibleRowOnList > 0) {
if(playSoundOnSuccess)
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_LIST_ROW);
- m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW - 1);
+ m_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_OPTION_ON_SCREEN);
+ m_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1);
} else {
m_nFirstVisibleRowOnList = 0;
m_nSelectedListRow = 0;
@@ -375,15 +379,15 @@ CMenuManager::PageUpList(bool playSoundOnSuccess)
void
CMenuManager::PageDownList(bool playSoundOnSuccess)
{
- if (m_nTotalListRow > MAX_VISIBLE_LIST_ROW) {
- if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_LIST_ROW) {
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) {
+ if (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) {
if(playSoundOnSuccess)
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW, m_nTotalListRow - MAX_VISIBLE_LIST_ROW);
+ m_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN, m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN);
m_nSelectedListRow = Max(m_nSelectedListRow, m_nFirstVisibleRowOnList);
} else {
- m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW;
+ m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN;
m_nSelectedListRow = m_nTotalListRow - 1;
}
m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
@@ -434,30 +438,26 @@ CMenuManager::ThingsToDoBeforeGoingBack()
m_nTotalListRow = 0;
}
-#ifdef CUSTOM_FRONTEND_OPTIONS
- for (int i = 0; i < numCustomFrontendOptions; i++) {
- FrontendOption &option = customFrontendOptions[i];
- if (option.type != FEOPTION_REDIRECT && option.type != FEOPTION_GOBACK && m_nCurrScreen == option.screen) {
- if (option.returnPrevPageFunc)
- option.returnPrevPageFunc();
-
- if (m_nCurrOption == option.screenOptionOrder && (option.type == FEOPTION_DYNAMIC || option.type == FEOPTION_BUILTIN_ACTION))
- if(option.buttonPressFunc)
- option.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS);
-
- if (option.type == FEOPTION_SELECT && option.onlyApplyOnEnter && option.lastSavedValue != option.displayedValue)
- option.displayedValue = *option.value = option.lastSavedValue;
- }
+#ifdef SCROLLABLE_PAGES
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) {
+ m_nSelectedListRow = 0;
+ m_nFirstVisibleRowOnList = 0;
+ m_nScrollbarTopMargin = 0;
}
+#endif
- if (m_nCurrScreen > lastOgScreen) {
- for (int i = 0; i < numCustomFrontendScreens; i++) {
- FrontendScreen& screen = customFrontendScreens[i];
- if (m_nCurrScreen == screen.id && screen.returnPrevPageFunc) {
- screen.returnPrevPageFunc();
- break;
- }
- }
+#ifdef CUSTOM_FRONTEND_OPTIONS
+ CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];
+
+ if (option.m_Action == MENUACTION_CFO_DYNAMIC)
+ if(option.m_CFODynamic->buttonPressFunc)
+ option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS);
+
+ if (option.m_Action == MENUACTION_CFO_SELECT && option.m_CFOSelect->onlyApplyOnEnter && option.m_CFOSelect->lastSavedValue != option.m_CFOSelect->displayedValue)
+ option.m_CFOSelect->displayedValue = *option.m_CFO->value = option.m_CFOSelect->lastSavedValue;
+
+ if (aScreens[m_nCurrScreen].returnPrevPageFunc) {
+ aScreens[m_nCurrScreen].returnPrevPageFunc();
}
#endif
}
@@ -476,21 +476,248 @@ CMenuManager::GetPreviousPageOption()
prevPage = prevPage == MENUPAGE_NONE ? (!m_bGameNotLoaded ? MENUPAGE_PAUSE_MENU : MENUPAGE_START_MENU) : prevPage;
for (int i = 0; i < NUM_MENUROWS; i++) {
- if (aScreens[prevPage].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO) {
- FrontendOption &option = customFrontendOptions[aScreens[prevPage].m_aEntries[i].m_TargetMenu];
- if(option.type == FEOPTION_REDIRECT && option.to == m_nCurrScreen) {
+ if (aScreens[prevPage].m_aEntries[i].m_Action >= MENUACTION_NOTHING) { // CFO check
+ if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) {
return i;
}
- } else if (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) {
- return i;
}
}
-
- // Couldn't find current screen option on previous page, use default behaviour (maybe save-related screen?)
- return !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry[1] : aScreens[m_nCurrScreen].m_ParentEntry[0];
+
+ // This shouldn't happen
+ return 0;
#endif
}
+void
+CMenuManager::ProcessList(bool &goBack, bool &optionSelected)
+{
+ if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) {
+ m_nTotalListRow = m_nSkinsTotal;
+ }
+ if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) {
+ m_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 30 : 25;
+ if (m_nSelectedListRow > m_nTotalListRow)
+ m_nSelectedListRow = m_nTotalListRow - 1;
+ }
+
+#ifndef TIDY_UP_PBP
+ if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) {
+ m_bShowMouse = 0;
+ optionSelected = true;
+ }
+#endif
+ if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_535) {
+ if (m_nCurrExLayer == HOVEROPTION_LIST) {
+ m_nHoverOption = HOVEROPTION_NOT_HOVERING;
+ m_bWaitingForNewKeyBind = true;
+ m_bStartWaitingForKeyBind = true;
+ m_bKeyChangeNotProcessed = true;
+ pControlEdit = &m_KeyPressedCode;
+ }
+ } else {
+ field_535 = false;
+ }
+
+ static uint32 lastTimeClickedScrollButton = 0;
+
+ if (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) {
+ m_bPressedPgUpOnList = false;
+ m_bPressedPgDnOnList = false;
+ m_bPressedUpOnList = false;
+ m_bPressedDownOnList = false;
+ m_bPressedScrollButton = false;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ }
+
+ if (CPad::GetPad(0)->GetTabJustDown()) {
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ m_bShowMouse = false;
+ switch (m_nCurrExLayer) {
+ case HOVEROPTION_BACK:
+ default:
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ break;
+ case HOVEROPTION_LIST:
+ m_nCurrExLayer = HOVEROPTION_USESKIN;
+ break;
+ case HOVEROPTION_USESKIN:
+ m_nCurrExLayer = HOVEROPTION_BACK;
+ }
+ if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) {
+ m_nCurrExLayer = HOVEROPTION_BACK;
+ }
+ if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) {
+ m_nCurrExLayer = HOVEROPTION_BACK;
+ }
+ }
+
+ bool pressed = false;
+ if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) {
+ m_bShowMouse = false;
+ pressed = true;
+ } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) {
+ m_bShowMouse = true;
+ pressed = true;
+ }
+
+ // Up
+ if (pressed) {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ if (!m_bPressedUpOnList) {
+ m_bPressedUpOnList = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ ScrollUpListByOne();
+ }
+ } else {
+ m_bPressedUpOnList = false;
+ }
+
+ pressed = false;
+ if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) {
+ m_bShowMouse = false;
+ pressed = true;
+ } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) {
+ m_bShowMouse = true;
+ pressed = true;
+ }
+
+ // Down
+ if (pressed) {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ if (!m_bPressedDownOnList) {
+ m_bPressedDownOnList = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ ScrollDownListByOne();
+ }
+ } else {
+ m_bPressedDownOnList = false;
+ }
+
+ if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
+ if (!CPad::GetPad(0)->GetPageUp()) {
+ m_bPressedPgUpOnList = false;
+ } else {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ if (!m_bPressedPgUpOnList) {
+ m_bPressedPgUpOnList = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ m_bShowMouse = false;
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ PageUpList(false);
+ }
+ }
+ if (!CPad::GetPad(0)->GetPageDown()) {
+ m_bPressedPgDnOnList = false;
+ } else {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ if (!m_bPressedPgDnOnList) {
+ m_bPressedPgDnOnList = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ m_bShowMouse = false;
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ PageDownList(false);
+ }
+ }
+ if (CPad::GetPad(0)->GetHome()) {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ m_bShowMouse = false;
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) {
+ m_nFirstVisibleRowOnList = 0;
+ }
+ m_nSelectedListRow = 0;
+ m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
+ }
+ if (CPad::GetPad(0)->GetEnd()) {
+ m_nCurrExLayer = HOVEROPTION_LIST;
+ m_bShowMouse = false;
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
+ if (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) {
+ m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN;
+ }
+ m_nSelectedListRow = m_nTotalListRow - 1;
+ m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
+ }
+ }
+
+#ifndef TIDY_UP_PBP
+ if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) {
+ m_bShowMouse = false;
+ goBack = true;
+ }
+#endif
+
+ if (CPad::GetPad(0)->GetLeftMouseJustDown()) {
+ switch (m_nHoverOption) {
+ case HOVEROPTION_BACK:
+ goBack = true;
+ break;
+ case HOVEROPTION_PAGEUP:
+ PageUpList(true);
+ break;
+ case HOVEROPTION_PAGEDOWN:
+ PageDownList(true);
+ break;
+ case HOVEROPTION_USESKIN:
+ if (m_nSkinsTotal > 0) {
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);
+ m_pSelectedSkin = m_pSkinListHead.nextSkin;
+ strcpy(m_PrefsSkinFile, m_aSkinName);
+ CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);
+ SaveSettings();
+ }
+ }
+ }
+
+ if (CPad::GetPad(0)->GetLeftMouseJustDown()) {
+ switch (m_nHoverOption) {
+ case HOVEROPTION_OVER_SCROLL_UP:
+ m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP;
+ break;
+ case HOVEROPTION_OVER_SCROLL_DOWN:
+ m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN;
+ break;
+ case HOVEROPTION_LIST:
+ m_nHoverOption = HOVEROPTION_SKIN;
+ }
+ } else if ((CPad::GetPad(0)->GetLeftMouseJustUp())
+ && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) {
+ m_nHoverOption = HOVEROPTION_NOT_HOVERING;
+ }
+
+ if (!CPad::GetPad(0)->GetLeftMouse()) {
+ holdingScrollBar = false;
+ } else {
+ if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) {
+ holdingScrollBar = true;
+ // TODO: This part is a bit hard to reverse. Not much code tho
+ assert(0 && "Holding scrollbar isn't done yet");
+ } else {
+ switch (m_nHoverOption) {
+ case HOVEROPTION_OVER_SCROLL_UP:
+ case HOVEROPTION_CLICKED_SCROLL_UP:
+ if (!m_bPressedScrollButton) {
+ m_bPressedScrollButton = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ ScrollUpListByOne();
+ }
+ break;
+ case HOVEROPTION_OVER_SCROLL_DOWN:
+ case HOVEROPTION_CLICKED_SCROLL_DOWN:
+ if (!m_bPressedScrollButton) {
+ m_bPressedScrollButton = true;
+ lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
+ ScrollDownListByOne();
+ }
+ break;
+ default:
+ m_bPressedScrollButton = false;
+ }
+ }
+ }
+}
// ------ Functions not in the game/inlined ends
void
@@ -782,19 +1009,21 @@ CMenuManager::Draw()
CFont::SetCentreOff();
CFont::SetJustifyOn();
CFont::SetBackGroundOnlyTextOn();
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
+#ifdef DRAW_MENU_VERSION_TEXT
CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255)));
CFont::SetRightJustifyOn();
CFont::SetFontStyle(FONT_HEADING);
CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f));
- CFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
+ CFont::SetWrapx(SCREEN_WIDTH);
CFont::SetRightJustifyWrap(0.0f);
strcpy(gString, "V1.1");
AsciiToUnicode(gString, gUString);
CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString);
#endif
+#endif
CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN));
- CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH));
+ CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f));
switch (m_nCurrScreen) {
case MENUPAGE_STATS:
@@ -854,13 +1083,6 @@ CMenuManager::Draw()
str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);
break;
default:
-#ifdef CUSTOM_FRONTEND_OPTIONS
- if (aScreens[m_nCurrScreen].m_aEntries[0].m_SaveSlot == SAVESLOT_CFO) {
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[0].m_TargetMenu];
- str = (wchar*)option.leftText;
- }
- else
-#endif
str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);
break;
}
@@ -873,7 +1095,11 @@ CMenuManager::Draw()
#endif
}
+#ifdef ASPECT_RATIO_SCALE
CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));
+#else
+ CFont::SetCentreSize(SCREEN_WIDTH);
+#endif
#ifdef PS2_LIKE_MENU
bool itemsAreSelectable = !bottomBarActive;
@@ -959,30 +1185,22 @@ CMenuManager::Draw()
#endif
default:
#ifdef CUSTOM_FRONTEND_OPTIONS
- bool custom = m_nCurrScreen > lastOgScreen;
+ CCustomScreenLayout *custom = aScreens[m_nCurrScreen].layout;
if (custom) {
- for (int i = 0; i < numCustomFrontendScreens; i++) {
- FrontendScreen& screen = customFrontendScreens[i];
- if (m_nCurrScreen == screen.id) {
- columnWidth = screen.columnWidth;
- headerHeight = screen.headerHeight;
- lineHeight = screen.lineHeight;
- CFont::SetFontStyle(FONT_LOCALE(screen.font));
- CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = screen.fontScaleX), MENU_Y(MENU_TEXT_SIZE_Y = screen.fontScaleY));
- if (screen.alignment == FESCREEN_LEFT_ALIGN) {
- CFont::SetCentreOff();
- CFont::SetRightJustifyOff();
- } else if (screen.alignment == FESCREEN_RIGHT_ALIGN) {
- CFont::SetCentreOff();
- CFont::SetRightJustifyOn();
- } else {
- CFont::SetRightJustifyOff();
- CFont::SetCentreOn();
- }
- break;
- }
- if (i == numCustomFrontendScreens - 1)
- custom = false;
+ columnWidth = custom->columnWidth;
+ headerHeight = custom->headerHeight;
+ lineHeight = custom->lineHeight;
+ CFont::SetFontStyle(FONT_LOCALE(custom->font));
+ CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X = custom->fontScaleX), MENU_Y(MENU_TEXT_SIZE_Y = custom->fontScaleY));
+ if (custom->alignment == FESCREEN_LEFT_ALIGN) {
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOff();
+ } else if (custom->alignment == FESCREEN_RIGHT_ALIGN) {
+ CFont::SetCentreOff();
+ CFont::SetRightJustifyOn();
+ } else {
+ CFont::SetRightJustifyOff();
+ CFont::SetCentreOn();
}
}
if (!custom)
@@ -1043,13 +1261,24 @@ CMenuManager::Draw()
#endif
#ifdef CUSTOM_FRONTEND_OPTIONS
- static int lastOption = m_nCurrOption;
+ static int lastSelectedOpt = m_nCurrOption;
#endif
+#ifdef SCROLLABLE_PAGES
+ int firstOption = m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen) ? m_nFirstVisibleRowOnList : 0;
+ for (int i = firstOption; i < firstOption + MAX_VISIBLE_OPTION && i < NUM_MENUROWS; ++i) {
+#else
for (int i = 0; i < NUM_MENUROWS; ++i) {
+#endif
+
#ifdef CUSTOM_FRONTEND_OPTIONS
bool isOptionDisabled = false;
#endif
+ // Hide back button
+#ifdef PS2_LIKE_MENU
+ if ((i == NUM_MENUROWS - 1 || aScreens[m_nCurrScreen].m_aEntries[i+1].m_EntryName[0] == '\0') && strncmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "FEDS_TB", 8) == 0)
+ break;
+#endif
if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\0') {
wchar *rightText = nil;
wchar *leftText;
@@ -1066,28 +1295,22 @@ CMenuManager::Draw()
leftText = TheText.Get(gString);
}
} else {
-#ifdef CUSTOM_FRONTEND_OPTIONS
- if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO){
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu];
- leftText = (wchar*)option.leftText;
- } else
-#endif
leftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName);
}
#ifdef CUSTOM_FRONTEND_OPTIONS
- if (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot == SAVESLOT_CFO) {
- FrontendOption &option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu];
- if (option.type == FEOPTION_SELECT) {
- if (option.onlyApplyOnEnter){
+ if (aScreens[m_nCurrScreen].m_aEntries[i].m_Action < MENUACTION_NOTHING) { // CFO check
+ CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i];
+ if (option.m_Action == MENUACTION_CFO_SELECT) {
+ if (option.m_CFOSelect->onlyApplyOnEnter){
if (m_nCurrOption != i) {
- if (option.displayedValue != option.lastSavedValue)
+ if (option.m_CFOSelect->displayedValue != option.m_CFOSelect->lastSavedValue)
SetHelperText(3); // Restored original value
-// option.displayedValue = option.lastSavedValue = *option.value;
+// option.displayedValue = option.lastSavedValue = *option.m_CFO->value;
} else {
- if (option.displayedValue != *option.value)
+ if (option.m_CFOSelect->displayedValue != *option.m_CFO->value)
SetHelperText(1); // Enter to apply
else if (m_nHelperTextMsgId == 1)
ResetHelperText(); // Applied
@@ -1095,14 +1318,14 @@ CMenuManager::Draw()
}
}
- if (m_nCurrOption != lastOption && lastOption == i) {
- FrontendOption &oldOption = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[lastOption].m_TargetMenu];
- if (oldOption.type == FEOPTION_DYNAMIC || oldOption.type == FEOPTION_BUILTIN_ACTION)
- if(oldOption.buttonPressFunc)
- oldOption.buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS);
+ if (m_nCurrOption != lastSelectedOpt && lastSelectedOpt == i) {
+ CMenuScreenCustom::CMenuEntry &oldOption = aScreens[m_nCurrScreen].m_aEntries[lastSelectedOpt];
+ if (oldOption.m_Action == MENUACTION_CFO_DYNAMIC)
+ if(oldOption.m_CFODynamic->buttonPressFunc)
+ oldOption.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS);
- if (oldOption.onlyApplyOnEnter && oldOption.type == FEOPTION_SELECT)
- oldOption.displayedValue = oldOption.lastSavedValue = *oldOption.value;
+ if (oldOption.m_Action == MENUACTION_CFO_SELECT && oldOption.m_CFOSelect->onlyApplyOnEnter)
+ oldOption.m_CFOSelect->displayedValue = oldOption.m_CFOSelect->lastSavedValue = *oldOption.m_CFO->value;
}
}
#endif
@@ -1270,21 +1493,6 @@ CMenuManager::Draw()
AsciiToUnicode(_psGetVideoModeList()[m_nDisplayVideoMode], unicodeTemp);
rightText = unicodeTemp;
break;
-//#ifdef NO_ISLAND_LOADING
-// case MENUACTION_ISLANDLOADING:
-// switch (m_DisplayIslandLoading) {
-// case ISLAND_LOADING_LOW:
-// rightText = TheText.Get("FEM_LOW");
-// break;
-// case ISLAND_LOADING_MEDIUM:
-// rightText = TheText.Get("FEM_MED");
-// break;
-// case ISLAND_LOADING_HIGH:
-// rightText = TheText.Get("FEM_HIG");
-// break;
-// }
-// break;
-//#endif
case MENUACTION_AUDIOHW:
if (m_nPrefsAudio3DProviderIndex == -1)
rightText = TheText.Get("FEA_NAH");
@@ -1336,29 +1544,24 @@ CMenuManager::Draw()
rightText = TheText.Get(CVehicle::m_bDisableMouseSteering ? "FEM_OFF" : "FEM_ON");
break;
#ifdef CUSTOM_FRONTEND_OPTIONS
- case MENUACTION_TRIGGERFUNC:
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu];
- if (m_nCurrScreen == option.screen && i == option.screenOptionOrder) {
- if (option.type == FEOPTION_SELECT) {
- // To whom manipulate option.value of static options externally (like RestoreDef functions)
- if (*option.value != option.lastSavedValue)
- option.displayedValue = option.lastSavedValue = *option.value;
-
- if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0)
- option.displayedValue = 0;
-
- rightText = (wchar*)option.rightTexts[option.displayedValue];
-
- } else if (option.type == FEOPTION_DYNAMIC) {
- if (option.drawFunc) {
- rightText = option.drawFunc(&isOptionDisabled, m_nCurrOption == i);
- }
+ case MENUACTION_CFO_DYNAMIC:
+ case MENUACTION_CFO_SELECT:
+ CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i];
+ if (option.m_Action == MENUACTION_CFO_SELECT) {
+ // To whom manipulate option.m_CFO->value of static options externally (like RestoreDef functions)
+ if (*option.m_CFO->value != option.m_CFOSelect->lastSavedValue)
+ option.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *option.m_CFO->value;
+
+ if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0)
+ option.m_CFOSelect->displayedValue = 0;
+
+ rightText = TheText.Get(option.m_CFOSelect->rightTexts[option.m_CFOSelect->displayedValue]);
+
+ } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) {
+ if (option.m_CFODynamic->drawFunc) {
+ rightText = option.m_CFODynamic->drawFunc(&isOptionDisabled, m_nCurrOption == i);
}
- } else {
- debug("A- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, i, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[i].m_TargetMenu, option.screen, option.screenOptionOrder);
- assert(0 && "Custom frontend options is borked");
}
-
break;
#endif
}
@@ -1368,9 +1571,20 @@ CMenuManager::Draw()
int nextYToCheck = bitAboveNextItemY;
if (!foundTheHoveringItem) {
+#ifdef SCROLLABLE_PAGES
+ for (int rowToCheck = firstOption + (aScreens[m_nCurrScreen].m_aEntries[firstOption].m_Action == MENUACTION_LABEL); rowToCheck < firstOption + MAX_VISIBLE_OPTION && rowToCheck < NUM_MENUROWS; ++rowToCheck) {
+#else
for (int rowToCheck = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL; rowToCheck < NUM_MENUROWS; ++rowToCheck) {
+#endif
if(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING)
break;
+
+ // Hide back button
+#ifdef PS2_LIKE_MENU
+ if ((rowToCheck == NUM_MENUROWS - 1 || aScreens[m_nCurrScreen].m_aEntries[rowToCheck+1].m_EntryName[0] == '\0') &&
+ strncmp(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_EntryName, "FEDS_TB", 8) == 0)
+ break;
+#endif
int extraOffset = 0;
if (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_RADIO)
@@ -1469,12 +1683,6 @@ CMenuManager::Draw()
if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES") && m_nHelperTextMsgId == 1)
ResetHelperText();
}
-//#ifdef NO_ISLAND_LOADING
-// if (m_DisplayIslandLoading == m_PrefsIslandLoading) {
-// if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_ISL") && m_nHelperTextMsgId == 1)
-// ResetHelperText();
-// }
-//#endif
if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) {
if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH"))
SetHelperText(1);
@@ -1483,12 +1691,6 @@ CMenuManager::Draw()
if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FED_RES"))
SetHelperText(1);
}
-//#ifdef NO_ISLAND_LOADING
-// if (m_DisplayIslandLoading != m_PrefsIslandLoading) {
-// if (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEM_ISL"))
-// SetHelperText(1);
-// }
-//#endif
if (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) {
if (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEA_3DH") != 0
// To make assigning built-in actions to new custom options possible.
@@ -1535,6 +1737,12 @@ CMenuManager::Draw()
break;
}
+ // Needed after the bug fix in Font.cpp
+#ifdef FIX_BUGS
+ if (!CFont::Details.centre)
+ CFont::SetRightJustifyOff();
+#endif
+
// 60.0 is silly
nextYToUse += lineHeight * CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(60.0f), MENU_Y(nextYToUse), leftText);
@@ -1559,7 +1767,36 @@ CMenuManager::Draw()
}
#ifdef CUSTOM_FRONTEND_OPTIONS
- lastOption = m_nCurrOption;
+ lastSelectedOpt = m_nCurrOption;
+#endif
+
+#ifdef SCROLLABLE_PAGES
+ #define SCROLLBAR_BOTTOM_X 125.0f // only for background, scrollbar's itself is calculated
+ #define SCROLLBAR_RIGHT_X 36.0f
+ #define SCROLLBAR_WIDTH 9.5f
+ #define SCROLLBAR_TOP_X 64
+
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) {
+ // Scrollbar background
+ CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2), MENU_Y(SCROLLBAR_TOP_X),
+ MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2 - SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(SCROLLBAR_BOTTOM_X)), CRGBA(100, 100, 66, FadeIn(205)));
+
+ float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nTotalListRow / (float) MAX_VISIBLE_OPTION);
+ float scrollbarBottom, scrollbarTop;
+
+ scrollbarBottom = MENU_Y(SCROLLBAR_TOP_X - 8 + m_nScrollbarTopMargin + scrollbarHeight);
+ scrollbarTop = MENU_Y(SCROLLBAR_TOP_X + m_nScrollbarTopMargin);
+ // Scrollbar shadow
+ CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop,
+ MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 1 - SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)),
+ CRGBA(50, 50, 50, FadeIn(255)));
+
+ // Scrollbar
+ CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop,
+ MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - SCROLLBAR_WIDTH), scrollbarBottom),
+ CRGBA(235, 170, 50, FadeIn(255)));
+
+ }
#endif
switch (m_nCurrScreen) {
@@ -1573,13 +1810,9 @@ CMenuManager::Draw()
break;
#ifdef CUSTOM_FRONTEND_OPTIONS
default:
- if (m_nCurrScreen > lastOgScreen) {
- for (int i = 0; i < numCustomFrontendScreens; i++) {
- FrontendScreen& screen = customFrontendScreens[i];
- if (m_nCurrScreen == screen.id && screen.showLeftRightHelper) {
- DisplayHelperText();
- break;
- }
+ if (aScreens[m_nCurrScreen].layout) {
+ if (aScreens[m_nCurrScreen].layout->showLeftRightHelper) {
+ DisplayHelperText();
}
}
break;
@@ -2047,7 +2280,7 @@ CMenuManager::DrawControllerSetupScreen()
CFont::SetRightJustifyOff();
CFont::SetBackGroundOnlyTextOn();
CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN));
- CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH));
+ CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f));
PREPARE_MENU_HEADER
@@ -2236,27 +2469,28 @@ CMenuManager::DrawFrontEnd()
CFont::SetAlphaFade(255.0f);
#ifdef PS2_LIKE_MENU
+ #define setBbItem(a, b, c) strcpy(a.name, b); a.screenId = c;
if (m_nCurrScreen == MENUPAGE_NONE) {
if (m_bGameNotLoaded) {
if (bbTabCount != 6) {
- bbNames[0] = { "FEB_SAV",MENUPAGE_NEW_GAME };
- bbNames[1] = { "FEB_CON",MENUPAGE_CONTROLLER_PC };
- bbNames[2] = { "FEB_AUD",MENUPAGE_SOUND_SETTINGS };
- bbNames[3] = { "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS };
- bbNames[4] = { "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS };
- bbNames[5] = { "FESZ_QU",MENUPAGE_EXIT };
+ setBbItem(bbNames[0], "FEB_SAV",MENUPAGE_NEW_GAME)
+ setBbItem(bbNames[1], "FEB_CON",MENUPAGE_CONTROLLER_PC)
+ setBbItem(bbNames[2], "FEB_AUD",MENUPAGE_SOUND_SETTINGS)
+ setBbItem(bbNames[3], "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS)
+ setBbItem(bbNames[4], "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS)
+ setBbItem(bbNames[5], "FESZ_QU",MENUPAGE_EXIT)
bbTabCount = 6;
}
} else {
if (bbTabCount != 8) {
- bbNames[0] = { "FEB_STA",MENUPAGE_STATS };
- bbNames[1] = { "FEB_SAV",MENUPAGE_NEW_GAME };
- bbNames[2] = { "FEB_BRI",MENUPAGE_BRIEFS };
- bbNames[3] = { "FEB_CON",MENUPAGE_CONTROLLER_PC };
- bbNames[4] = { "FEB_AUD",MENUPAGE_SOUND_SETTINGS };
- bbNames[5] = { "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS };
- bbNames[6] = { "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS };
- bbNames[7] = { "FESZ_QU",MENUPAGE_EXIT };
+ setBbItem(bbNames[0], "FEB_STA",MENUPAGE_STATS)
+ setBbItem(bbNames[1], "FEB_SAV",MENUPAGE_NEW_GAME)
+ setBbItem(bbNames[2], "FEB_BRI",MENUPAGE_BRIEFS)
+ setBbItem(bbNames[3], "FEB_CON",MENUPAGE_CONTROLLER_PC)
+ setBbItem(bbNames[4], "FEB_AUD",MENUPAGE_SOUND_SETTINGS)
+ setBbItem(bbNames[5], "FEB_DIS",MENUPAGE_DISPLAY_SETTINGS)
+ setBbItem(bbNames[6], "FEB_LAN",MENUPAGE_LANGUAGE_SETTINGS)
+ setBbItem(bbNames[7], "FESZ_QU",MENUPAGE_EXIT)
bbTabCount = 8;
}
}
@@ -2264,6 +2498,7 @@ CMenuManager::DrawFrontEnd()
bottomBarActive = true;
curBottomBarOption = 0;
}
+ #undef setBbItem
#else
if (m_nCurrScreen == MENUPAGE_NONE) {
if (m_bGameNotLoaded) {
@@ -2354,7 +2589,7 @@ CMenuManager::DrawFrontEndNormal()
m_aFrontEndSprites[FE2_MAINPANEL_UR].Draw(CRect(SCREEN_WIDTH / 2, 0.0f, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT / 2), CRGBA(255, 255, 255, 255));
m_aFrontEndSprites[FE2_MAINPANEL_DL].Draw(CRect(MENU_X_LEFT_ALIGNED(0.0f), SCREEN_HEIGHT / 2, SCREEN_WIDTH / 2, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
m_aFrontEndSprites[FE2_MAINPANEL_DR].Draw(CRect(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, MENU_X_RIGHT_ALIGNED(0.0f), SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
-
+
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
eFrontendSprites currentSprite;
switch (m_nCurrScreen) {
@@ -2394,39 +2629,15 @@ CMenuManager::DrawFrontEndNormal()
break;
}
- m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha));
-
static float fadeAlpha = 0.0f;
- static int lastState = 0;
- // reverseAlpha = PS2 fading (wait for 255->0, then change screen)
if (m_nMenuFadeAlpha < 255) {
- if (lastState == 1 && !reverseAlpha)
- fadeAlpha = 0.f;
-
- if (m_nMenuFadeAlpha <= 0 && reverseAlpha) {
- reverseAlpha = false;
- ChangeScreen(pendingScreen, pendingOption, true, false);
- } else {
- // +20 per every 33 ms (1000.f/30.f - original frame limiter fps)
- if (!reverseAlpha)
- fadeAlpha += (frameTime) * 20.f / 33.f;
- else
- fadeAlpha = max(0.0f, fadeAlpha - (frameTime) * 30.f / 33.f);
-
- m_nMenuFadeAlpha = fadeAlpha;
- }
- lastState = 0;
+ if (m_nMenuFadeAlpha == 0 && fadeAlpha > 1.0f) fadeAlpha = 0.0f;
+
+ // +20 per every 33 ms (1000.f/30.f - original frame limiter fps)
+ fadeAlpha += (frameTime) * 20.f / 33.f;
+ m_nMenuFadeAlpha = fadeAlpha;
} else {
- if (lastState == 0) fadeAlpha = 255.f;
-
- if (reverseAlpha) {
- fadeAlpha -= (frameTime) * 30.f / 33.f;
-
- m_nMenuFadeAlpha = fadeAlpha;
- }
- lastState = 1;
-
// TODO: what is this? waiting mouse?
if(field_518 == 4){
if(m_nHoverOption == HOVEROPTION_3 || m_nHoverOption == HOVEROPTION_4 ||
@@ -2438,6 +2649,8 @@ CMenuManager::DrawFrontEndNormal()
}
}
+ m_aFrontEndSprites[currentSprite].Draw(CRect(MENU_X_LEFT_ALIGNED(50.0f), MENU_Y(50.0f), MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(95.0f)), CRGBA(255, 255, 255, m_nMenuFadeAlpha > 255 ? 255 : m_nMenuFadeAlpha));
+
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
@@ -2463,7 +2676,7 @@ CMenuManager::DrawFrontEndNormal()
CFont::SetJustifyOn();
CFont::SetRightJustifyOff();
CFont::SetBackGroundOnlyTextOn();
- CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(40.0f)); // 600.0f
+ CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); // 600.0f
CFont::SetColor(CRGBA(16, 16, 16, 255));
switch (m_nCurrScreen) {
@@ -2612,17 +2825,10 @@ CMenuManager::DrawFrontEndNormal()
break;
default:
#ifdef CUSTOM_FRONTEND_OPTIONS
- bool custom = m_nPrevScreen > lastOgScreen;
+ CCustomScreenLayout *custom = aScreens[m_nPrevScreen].layout;
if (custom) {
- for (int i = 0; i < numCustomFrontendScreens; i++) {
- FrontendScreen& screen = customFrontendScreens[i];
- if (m_nPrevScreen == screen.id) {
- previousSprite = screen.sprite;
- break;
- }
- if (i == numCustomFrontendScreens - 1)
- custom = false;
- }
+ previousSprite = custom->sprite;
+ break;
}
if (!custom)
#endif
@@ -2678,15 +2884,9 @@ CMenuManager::DrawFrontEndNormal()
break;
#ifdef CUSTOM_FRONTEND_OPTIONS
default:
- bool custom = m_nCurrScreen > lastOgScreen;
+ CCustomScreenLayout *custom = aScreens[m_nCurrScreen].layout;
if (custom) {
- for (int i = 0; i < numCustomFrontendScreens; i++) {
- FrontendScreen& screen = customFrontendScreens[i];
- if (m_nCurrScreen == screen.id) {
- currentSprite = screen.sprite;
- break;
- }
- }
+ previousSprite = custom->sprite;
}
break;
#endif
@@ -2794,7 +2994,7 @@ CMenuManager::DrawPlayerSetupScreen()
CFont::SetRightJustifyOff();
CFont::SetBackGroundOnlyTextOn();
CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN));
- CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH));
+ CFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN - 2.0f));
PREPARE_MENU_HEADER
@@ -2986,14 +3186,13 @@ CMenuManager::DrawPlayerSetupScreen()
CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(100, 100, 66, FadeIn(205)));
- // Scrollbar
- float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal * (float) MAX_VISIBLE_LIST_ROW;
+ float scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nSkinsTotal / (float) MAX_VISIBLE_LIST_ROW);
float scrollbarBottom, scrollbarTop;
if (m_nSkinsTotal <= MAX_VISIBLE_LIST_ROW) {
scrollbarBottom = SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 4.0f);
scrollbarTop = MENU_Y(PLAYERSETUP_LIST_BODY_TOP);
- // Shadow
+ // Scrollbar shadow
CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop,
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), CRGBA(50, 50, 50, FadeIn(255)));
} else {
@@ -3004,12 +3203,13 @@ CMenuManager::DrawPlayerSetupScreen()
scrollbarBottom = MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 4 + m_nScrollbarTopMargin + scrollbarHeight - SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal);
scrollbarTop = MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin);
#endif
- // Shadow
+ // Scrollbar shadow
CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop,
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)),
CRGBA(50, 50, 50, FadeIn(255)));
}
+ // Scrollbar
CSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop,
MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom),
CRGBA(235, 170, 50, FadeIn(255)));
@@ -3301,10 +3501,6 @@ CMenuManager::InitialiseChangedLanguageSettings()
default:
break;
}
-
-#ifdef CUSTOM_FRONTEND_OPTIONS
- CustomFrontendOptionsPopulate();
-#endif
}
}
@@ -3342,7 +3538,7 @@ CMenuManager::LoadAllTextures()
CTxdStore::LoadTxd(frontendTxdSlot, "MODELS/FRONTEND.TXD");
CTxdStore::AddRef(frontendTxdSlot);
CTxdStore::SetCurrentTxd(frontendTxdSlot);
-#ifndef GTA3_1_1_PATCH
+#if GTA_VERSION < GTA3_PC_11
CStreaming::IHaveUsedStreamingMemory();
CTimer::Update();
#endif
@@ -3372,7 +3568,7 @@ CMenuManager::LoadAllTextures()
m_aMapSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);
}
#endif
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
CStreaming::IHaveUsedStreamingMemory();
CTimer::Update();
#endif
@@ -3387,7 +3583,7 @@ CMenuManager::LoadSettings()
int fileHandle = CFileMgr::OpenFile("gta3.set", "r");
int32 prevLang = m_PrefsLanguage;
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
CMBlur::BlurOn = (_dwOperatingSystemVersion != OS_WIN98);
#else
CMBlur::BlurOn = true;
@@ -3494,6 +3690,9 @@ CMenuManager::LoadSettings()
strcpy(m_PrefsSkinFile, DEFAULT_SKIN_NAME);
strcpy(m_aSkinName, DEFAULT_SKIN_NAME);
}
+#ifdef LOAD_INI_SETTINGS
+ LoadINISettings(); // needs frontend options to be loaded
+#endif
}
void
@@ -3575,8 +3774,8 @@ CMenuManager::MessageScreen(const char *text)
CFont::SetPropOn();
CFont::SetJustifyOn();
CFont::SetBackGroundOnlyTextOn();
- CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); // not used
- CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); // not used
+ CFont::SetWrapx(SCREEN_WIDTH - StretchX(170.0f)); // unused
+ CFont::SetRightJustifyWrap(SCREEN_WIDTH - StretchX(170.0f)); // unused
CSprite2d::DrawRect(CRect(StretchX(120.0f), StretchY(150.0f), SCREEN_WIDTH - StretchX(120.0f), SCREEN_HEIGHT - StretchY(220.0f)), CRGBA(50, 50, 50, 210));
CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
CFont::SetCentreSize(SCREEN_SCALE_X(380.0f));
@@ -3670,7 +3869,7 @@ CMenuManager::PrintErrorMessage()
CFont::SetJustifyOn();
CFont::SetRightJustifyOff();
CFont::SetBackGroundOnlyTextOn();
- CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(40.0f));
+ CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(MENU_X_MARGIN));
#ifdef FIX_BUGS
CFont::PrintString(SCREEN_SCALE_X(50.0f), SCREEN_SCALE_Y(180.0f), TheText.Get(CPad::bDisplayNoControllerMessage ? "NOCONT" : "WRCONT"));
#else
@@ -3683,7 +3882,7 @@ void
CMenuManager::PrintStats()
{
int rowNum = ConstructStatLine(99999);
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
#endif
CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X * 0.7), MENU_Y(MENU_TEXT_SIZE_Y * 0.9)); // second mulipliers are double, idk why
@@ -3958,12 +4157,22 @@ CMenuManager::ProcessButtonPresses(void)
DoSettingsBeforeStartingAGame();
return;
}
+ if (glfwGetKey(PSGLOBAL(window), GLFW_KEY_D) == GLFW_PRESS) {
+ scriptToLoad = 2;
+ DoSettingsBeforeStartingAGame();
+ return;
+ }
#elif defined _WIN32
if (GetAsyncKeyState('R') & 0x8000) {
scriptToLoad = 1;
DoSettingsBeforeStartingAGame();
return;
}
+ if (GetAsyncKeyState('D') & 0x8000) {
+ scriptToLoad = 2;
+ DoSettingsBeforeStartingAGame();
+ return;
+ }
#endif
}
#endif
@@ -3982,235 +4191,10 @@ CMenuManager::ProcessButtonPresses(void)
if (m_nMousePosY < 0) m_nMousePosY = 0;
if (m_nMousePosY > SCREEN_HEIGHT) m_nMousePosY = SCREEN_HEIGHT;
- if (m_nCurrScreen == MENUPAGE_MULTIPLAYER_FIND_GAME || m_nCurrScreen == MENUPAGE_SKIN_SELECT
- || m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) {
-
- if (m_nCurrScreen == MENUPAGE_SKIN_SELECT) {
- m_nTotalListRow = m_nSkinsTotal;
- }
- if (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) {
- m_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 30 : 25;
- if (m_nSelectedListRow > m_nTotalListRow)
- m_nSelectedListRow = m_nTotalListRow - 1;
- }
-
-#ifndef TIDY_UP_PBP
- if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) {
- m_bShowMouse = 0;
- optionSelected = true;
- }
-#endif
- if (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_535) {
- if (m_nCurrExLayer == HOVEROPTION_LIST) {
- m_nHoverOption = HOVEROPTION_NOT_HOVERING;
- m_bWaitingForNewKeyBind = true;
- m_bStartWaitingForKeyBind = true;
- m_bKeyChangeNotProcessed = true;
- pControlEdit = &m_KeyPressedCode;
- }
- } else {
- field_535 = false;
- }
-
- static uint32 lastTimeClickedScrollButton = 0;
-
- if (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) {
- m_bPressedPgUpOnList = false;
- m_bPressedPgDnOnList = false;
- m_bPressedUpOnList = false;
- m_bPressedDownOnList = false;
- m_bPressedScrollButton = false;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- }
-
- if (CPad::GetPad(0)->GetTabJustDown()) {
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- m_bShowMouse = false;
- switch (m_nCurrExLayer) {
- case HOVEROPTION_BACK:
- default:
- m_nCurrExLayer = HOVEROPTION_LIST;
- break;
- case HOVEROPTION_LIST:
- m_nCurrExLayer = HOVEROPTION_USESKIN;
- break;
- case HOVEROPTION_USESKIN:
- m_nCurrExLayer = HOVEROPTION_BACK;
- }
- if (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) {
- m_nCurrExLayer = HOVEROPTION_BACK;
- }
- if ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) {
- m_nCurrExLayer = HOVEROPTION_BACK;
- }
- }
-
- bool pressed = false;
- if (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) {
- m_bShowMouse = false;
- pressed = true;
- } else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) {
- m_bShowMouse = true;
- pressed = true;
- }
-
- // Up
- if (pressed) {
- m_nCurrExLayer = HOVEROPTION_LIST;
- if (!m_bPressedUpOnList) {
- m_bPressedUpOnList = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- ScrollUpListByOne();
- }
- } else {
- m_bPressedUpOnList = false;
- }
-
- pressed = false;
- if (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) {
- m_bShowMouse = false;
- pressed = true;
- } else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) {
- m_bShowMouse = true;
- pressed = true;
- }
-
- // Down
- if (pressed) {
- m_nCurrExLayer = HOVEROPTION_LIST;
- if (!m_bPressedDownOnList) {
- m_bPressedDownOnList = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- ScrollDownListByOne();
- }
- } else {
- m_bPressedDownOnList = false;
- }
-
- if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
- if (!CPad::GetPad(0)->GetPageUp()) {
- m_bPressedPgUpOnList = false;
- } else {
- m_nCurrExLayer = HOVEROPTION_LIST;
- if (!m_bPressedPgUpOnList) {
- m_bPressedPgUpOnList = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- m_bShowMouse = false;
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- PageUpList(false);
- }
- }
- if (!CPad::GetPad(0)->GetPageDown()) {
- m_bPressedPgDnOnList = false;
- } else {
- m_nCurrExLayer = HOVEROPTION_LIST;
- if (!m_bPressedPgDnOnList) {
- m_bPressedPgDnOnList = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- m_bShowMouse = false;
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- PageDownList(false);
- }
- }
- if (CPad::GetPad(0)->GetHome()) {
- m_nCurrExLayer = HOVEROPTION_LIST;
- m_bShowMouse = false;
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- if (m_nTotalListRow >= MAX_VISIBLE_LIST_ROW) {
- m_nFirstVisibleRowOnList = 0;
- }
- m_nSelectedListRow = 0;
- m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
- }
- if (CPad::GetPad(0)->GetEnd()) {
- m_nCurrExLayer = HOVEROPTION_LIST;
- m_bShowMouse = false;
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
- if (m_nTotalListRow >= MAX_VISIBLE_LIST_ROW) {
- m_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_LIST_ROW;
- }
- m_nSelectedListRow = m_nTotalListRow - 1;
- m_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;
- }
- }
-
-#ifndef TIDY_UP_PBP
- if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) {
- m_bShowMouse = false;
- goBack = true;
- }
-#endif
-
- if (CPad::GetPad(0)->GetLeftMouseJustDown()) {
- switch (m_nHoverOption) {
- case HOVEROPTION_BACK:
- goBack = true;
- break;
- case HOVEROPTION_PAGEUP:
- PageUpList(true);
- break;
- case HOVEROPTION_PAGEDOWN:
- PageDownList(true);
- break;
- case HOVEROPTION_USESKIN:
- if (m_nSkinsTotal > 0) {
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);
- m_pSelectedSkin = m_pSkinListHead.nextSkin;
- strcpy(m_PrefsSkinFile, m_aSkinName);
- CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);
- SaveSettings();
- }
- }
- }
+ if (hasNativeList(m_nCurrScreen)) {
+ // Not split to seperate function in III as in VC, but we need it for scrollable pages :)
+ ProcessList(goBack, optionSelected);
- if (CPad::GetPad(0)->GetLeftMouseJustDown()) {
- switch (m_nHoverOption) {
- case HOVEROPTION_OVER_SCROLL_UP:
- m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP;
- break;
- case HOVEROPTION_OVER_SCROLL_DOWN:
- m_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN;
- break;
- case HOVEROPTION_LIST:
- m_nHoverOption = HOVEROPTION_SKIN;
- }
- } else if ((CPad::GetPad(0)->GetLeftMouseJustUp())
- && ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) {
- m_nHoverOption = HOVEROPTION_NOT_HOVERING;
- }
-
- if (!CPad::GetPad(0)->GetLeftMouse()) {
- holdingScrollBar = false;
- } else {
- if ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) {
- holdingScrollBar = true;
- // TODO: This part is a bit hard to reverse. Not much code tho
- assert(0 && "Holding scrollbar isn't done yet");
- } else {
- switch (m_nHoverOption) {
- case HOVEROPTION_OVER_SCROLL_UP:
- case HOVEROPTION_CLICKED_SCROLL_UP:
- if (!m_bPressedScrollButton) {
- m_bPressedScrollButton = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- ScrollUpListByOne();
- }
- break;
- case HOVEROPTION_OVER_SCROLL_DOWN:
- case HOVEROPTION_CLICKED_SCROLL_DOWN:
- if (!m_bPressedScrollButton) {
- m_bPressedScrollButton = true;
- lastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();
- ScrollDownListByOne();
- }
- break;
- default:
- m_bPressedScrollButton = false;
- }
- }
- }
} else if (isPlainTextScreen(m_nCurrScreen)) {
#ifndef TIDY_UP_PBP
if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown() || CPad::GetPad(0)->GetLeftMouseJustDown()) {
@@ -4449,7 +4433,7 @@ CMenuManager::ProcessButtonPresses(void)
TheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl;
SaveSettings();
break;
- }
+ }
#else
switch (m_nHoverOption) {
case HOVEROPTION_INCREASE_BRIGHTNESS:
@@ -4468,7 +4452,26 @@ CMenuManager::ProcessButtonPresses(void)
break;
}
#endif
- }
+ }
+
+#ifdef SCROLLABLE_PAGES
+ if (m_nTotalListRow > MAX_VISIBLE_OPTION) {
+ bool temp = false;
+
+ m_nSelectedListRow = m_nCurrOption;
+
+ // ignore detected back/select states, it's our screen's job
+ ProcessList(temp, temp);
+
+ // and ignore our screen's goUp/Down, now it's ProcessList's job
+ goUp = false;
+ goDown = false;
+ m_nCurrOption = m_nSelectedListRow;
+ }
+
+ // Prevent sound on scroll. Mouse wheel is now belongs to us!
+ if (!(m_nTotalListRow > MAX_VISIBLE_OPTION && (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustDown())))
+#endif
if (CPad::GetPad(0)->GetLeftMouseJustUp() || CPad::GetPad(0)->GetLeftJustUp() || CPad::GetPad(0)->GetRightJustUp()
|| CPad::GetPad(0)->GetDPadLeftJustUp() || CPad::GetPad(0)->GetDPadRightJustUp()
@@ -4483,6 +4486,7 @@ CMenuManager::ProcessButtonPresses(void)
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);
}
+
#ifndef TIDY_UP_PBP
if (CPad::GetPad(0)->GetBackJustDown()) {
if (m_nCurrScreen != MENUPAGE_START_MENU && m_nCurrScreen != MENUPAGE_PAUSE_MENU) {
@@ -4502,7 +4506,7 @@ CMenuManager::ProcessButtonPresses(void)
goBack = false;
}
#endif
- }
+ }
// Centralized enter/back (except some conditions)
#ifdef TIDY_UP_PBP
@@ -4555,16 +4559,10 @@ CMenuManager::ProcessButtonPresses(void)
if (bbNames[curBottomBarOption].screenId == MENUPAGE_SOUND_SETTINGS)
DMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1);
- // If there's a menu change with fade ongoing, finish it now
- if (reverseAlpha)
- m_nMenuFadeAlpha = 0;
return;
} else if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown()
|| CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) {
- if (reverseAlpha && m_nMenuFadeAlpha > 30)
- return;
-
m_bShowMouse = false;
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
curBottomBarOption = ((curBottomBarOption + bbTabCount) - 1) % bbTabCount;
@@ -4573,9 +4571,6 @@ CMenuManager::ProcessButtonPresses(void)
} else if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()
|| CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) {
- if (reverseAlpha && m_nMenuFadeAlpha > 30)
- return;
-
m_bShowMouse = false;
DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);
curBottomBarOption = ((curBottomBarOption + bbTabCount) + 1) % bbTabCount;
@@ -4606,6 +4601,12 @@ CMenuManager::ProcessButtonPresses(void)
}
}
+ // Hide back button
+#ifdef PS2_LIKE_MENU
+ if ((goUp || goDown) && m_nCurrScreen != MENUPAGE_MULTIPLAYER_FIND_GAME && strncmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, "FEDS_TB", 8) == 0)
+ m_nCurrOption = goUp ? m_nCurrOption - 1 : (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL);
+#endif
+
if (optionSelected) {
int option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action;
if ((option == MENUACTION_CHANGEMENU) || (option == MENUACTION_POPULATESLOTS_CHANGEMENU)) {
@@ -4879,45 +4880,6 @@ CMenuManager::ProcessButtonPresses(void)
SaveSettings();
}
break;
-//#ifdef NO_ISLAND_LOADING
-// case MENUACTION_ISLANDLOADING:
-// if (m_DisplayIslandLoading != m_PrefsIslandLoading) {
-// if (!m_bGameNotLoaded) {
-// if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) {
-// if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH)
-// CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC);
-// if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) {
-// if (CGame::currLevel != LEVEL_INDUSTRIAL)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL);
-// if (CGame::currLevel != LEVEL_COMMERCIAL)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL);
-// if (CGame::currLevel != LEVEL_SUBURBAN)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN);
-// CCollision::bAlreadyLoaded = true;
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CStreaming::RequestBigBuildings(CGame::currLevel);
-// } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) {
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CStreaming::RequestIslands(CGame::currLevel);
-// } else
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// } else { // low
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CCollision::bAlreadyLoaded = false;
-// CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
-// CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
-// CStreaming::RemoveUnusedBuildings(CGame::currLevel);
-// CStreaming::RequestIslands(CGame::currLevel);
-// }
-//
-// CStreaming::LoadAllRequestedModels(true);
-// } else
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// SetHelperText(0);
-// SaveSettings();
-// }
-// break;
-//#endif
case MENUACTION_AUDIOHW:
{
int selectedProvider = m_nPrefsAudio3DProviderIndex;
@@ -4974,7 +4936,7 @@ CMenuManager::ProcessButtonPresses(void)
m_PrefsUseWideScreen = false;
m_PrefsShowSubtitles = true;
m_nDisplayVideoMode = m_nPrefsVideoMode;
-#ifdef GTA3_1_1_PATCH
+#if GTA_VERSION >= GTA3_PC_11
if (_dwOperatingSystemVersion == OS_WIN98) {
CMBlur::BlurOn = false;
CMBlur::MotionBlurClose();
@@ -4992,40 +4954,6 @@ CMenuManager::ProcessButtonPresses(void)
RestoreDefGraphics(FEOPTION_ACTION_SELECT);
RestoreDefDisplay(FEOPTION_ACTION_SELECT);
#endif
-//#ifdef NO_ISLAND_LOADING
-// m_DisplayIslandLoading = ISLAND_LOADING_LOW;
-// if (!m_bGameNotLoaded) {
-// if (m_DisplayIslandLoading > ISLAND_LOADING_LOW) {
-// if (m_DisplayIslandLoading == ISLAND_LOADING_HIGH)
-// CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC);
-// if (m_PrefsIslandLoading == ISLAND_LOADING_LOW) {
-// if (CGame::currLevel != LEVEL_INDUSTRIAL)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL);
-// if (CGame::currLevel != LEVEL_COMMERCIAL)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL);
-// if (CGame::currLevel != LEVEL_SUBURBAN)
-// CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN);
-// CCollision::bAlreadyLoaded = true;
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CStreaming::RequestBigBuildings(CGame::currLevel);
-// } else if (m_PrefsIslandLoading == ISLAND_LOADING_HIGH) {
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CStreaming::RequestIslands(CGame::currLevel);
-// } else
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// } else { // low
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-// CCollision::bAlreadyLoaded = false;
-// CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
-// CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
-// CStreaming::RemoveUnusedBuildings(CGame::currLevel);
-// CStreaming::RequestIslands(CGame::currLevel);
-// }
-//
-// CStreaming::LoadAllRequestedModels(true);
-// } else
-// m_PrefsIslandLoading = m_DisplayIslandLoading;
-//#endif // NO_ISLAND_LOADING
SaveSettings();
} else if ((m_nCurrScreen != MENUPAGE_SKIN_SELECT_OLD) && (m_nCurrScreen == MENUPAGE_CONTROLLER_PC)) {
ControlsManager.MakeControllerActionsBlank();
@@ -5086,29 +5014,28 @@ CMenuManager::ProcessButtonPresses(void)
return;
#endif
#ifdef CUSTOM_FRONTEND_OPTIONS
- case MENUACTION_TRIGGERFUNC:
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu];
- if (m_nCurrScreen == option.screen && m_nCurrOption == option.screenOptionOrder) {
- if (option.type == FEOPTION_SELECT) {
- if (!option.onlyApplyOnEnter) {
- option.displayedValue++;
- if (option.displayedValue >= option.numRightTexts || option.displayedValue < 0)
- option.displayedValue = 0;
- }
- option.changeFunc(option.displayedValue);
- *option.value = option.lastSavedValue = option.displayedValue;
-
- } else if (option.type == FEOPTION_DYNAMIC) {
- if (option.buttonPressFunc)
- option.buttonPressFunc(FEOPTION_ACTION_SELECT);
- } else if (option.type == FEOPTION_REDIRECT) {
- ChangeScreen(option.to, option.option, true, option.fadeIn);
- } else if (option.type == FEOPTION_GOBACK) {
- goBack = true;
+ case MENUACTION_CFO_SELECT:
+ case MENUACTION_CFO_DYNAMIC:
+ CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];
+ if (option.m_Action == MENUACTION_CFO_SELECT) {
+ if (!option.m_CFOSelect->onlyApplyOnEnter) {
+ option.m_CFOSelect->displayedValue++;
+ if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0)
+ option.m_CFOSelect->displayedValue = 0;
}
- } else {
- debug("B- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder);
- assert(0 && "Custom frontend options are borked");
+ int8 oldValue = *option.m_CFO->value;
+
+ *option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue;
+
+ if (option.m_CFOSelect->save)
+ SaveSettings();
+
+ if (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc)
+ option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue);
+
+ } else if (option.m_Action == MENUACTION_CFO_DYNAMIC) {
+ if (option.m_CFODynamic->buttonPressFunc)
+ option.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_SELECT);
}
break;
@@ -5116,14 +5043,6 @@ CMenuManager::ProcessButtonPresses(void)
}
}
ProcessOnOffMenuOptions();
-#ifdef CUSTOM_FRONTEND_OPTIONS
- if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot == SAVESLOT_CFO) {
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu];
- if (option.type == FEOPTION_BUILTIN_ACTION && option.buttonPressFunc) {
- option.buttonPressFunc(FEOPTION_ACTION_SELECT);
- }
- }
-#endif
}
if (goBack) {
@@ -5213,23 +5132,27 @@ CMenuManager::ProcessButtonPresses(void)
if (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()) {
m_bShowMouse = false;
increase = true;
- } else if (CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
+ } else if (
+#ifdef SCROLLABLE_PAGES
+ !(m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) &&
+#endif
+ CPad::GetPad(0)->GetMouseWheelUpJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
increase = true;
CheckSliderMovement(1);
m_bShowMouse = true;
}
- if (!CPad::GetPad(0)->GetLeftJustDown() && !CPad::GetPad(0)->GetAnaloguePadLeft() && !CPad::GetPad(0)->GetDPadLeftJustDown()) {
- if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) {
- if (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
- decrease = true;
- CheckSliderMovement(-1);
- m_bShowMouse = true;
- }
- }
- } else {
+ if (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown()) {
m_bShowMouse = false;
decrease = true;
+ } else if (
+#ifdef SCROLLABLE_PAGES
+ !(m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen)) &&
+#endif
+ CPad::GetPad(0)->GetMouseWheelDownJustDown() && m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {
+ decrease = true;
+ CheckSliderMovement(-1);
+ m_bShowMouse = true;
}
if (increase)
@@ -5294,15 +5217,6 @@ CMenuManager::ProcessButtonPresses(void)
}
}
break;
-//#ifdef NO_ISLAND_LOADING
-// case MENUACTION_ISLANDLOADING:
-// m_DisplayIslandLoading += changeValueBy;
-// if (m_DisplayIslandLoading > ISLAND_LOADING_HIGH)
-// m_DisplayIslandLoading = ISLAND_LOADING_LOW;
-// else if (m_DisplayIslandLoading < ISLAND_LOADING_LOW)
-// m_DisplayIslandLoading = ISLAND_LOADING_HIGH;
-// break;
-//#endif
case MENUACTION_AUDIOHW:
if (m_nPrefsAudio3DProviderIndex != -1) {
m_nPrefsAudio3DProviderIndex += changeValueBy;
@@ -5326,32 +5240,34 @@ CMenuManager::ProcessButtonPresses(void)
SaveSettings();
break;
#ifdef CUSTOM_FRONTEND_OPTIONS
- case MENUACTION_TRIGGERFUNC:
- FrontendOption& option = customFrontendOptions[aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu];
- if (m_nCurrScreen == option.screen && m_nCurrOption == option.screenOptionOrder) {
- if (option.type == FEOPTION_SELECT) {
- if (changeValueBy > 0) {
- option.displayedValue++;
- if (option.displayedValue >= option.numRightTexts)
- option.displayedValue = 0;
- } else {
- option.displayedValue--;
- if (option.displayedValue < 0)
- option.displayedValue = option.numRightTexts - 1;
- }
- if (!option.onlyApplyOnEnter) {
- option.changeFunc(option.displayedValue);
- *option.value = option.lastSavedValue = option.displayedValue;
- }
- } else if (option.type == FEOPTION_DYNAMIC && option.buttonPressFunc) {
- option.buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT);
+ case MENUACTION_CFO_SELECT:
+ case MENUACTION_CFO_DYNAMIC:
+ CMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];
+ if (option.m_Action == MENUACTION_CFO_SELECT) {
+ if (changeValueBy > 0) {
+ option.m_CFOSelect->displayedValue++;
+ if (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts)
+ option.m_CFOSelect->displayedValue = 0;
+ } else {
+ option.m_CFOSelect->displayedValue--;
+ if (option.m_CFOSelect->displayedValue < 0)
+ option.m_CFOSelect->displayedValue = option.m_CFOSelect->numRightTexts - 1;
}
- DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);
- }
- else {
- debug("C- screen:%d option:%d - totalCo: %d, coId: %d, coScreen:%d, coOption:%d\n", m_nCurrScreen, m_nCurrOption, numCustomFrontendOptions, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu, option.screen, option.screenOptionOrder);
- assert(0 && "Custom frontend options are borked");
+ if (!option.m_CFOSelect->onlyApplyOnEnter) {
+ int8 oldValue = *option.m_CFO->value;
+
+ *option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue;
+
+ if (option.m_CFOSelect->save)
+ SaveSettings();
+
+ if (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc)
+ option.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue);
+ }
+ } else if (option.m_Action == MENUACTION_CFO_DYNAMIC && option.m_CFODynamic->buttonPressFunc) {
+ option.m_CFODynamic->buttonPressFunc(changeValueBy > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT);
}
+ DMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);
break;
#endif
@@ -5527,6 +5443,10 @@ CMenuManager::SetHelperText(int text)
void
CMenuManager::ShutdownJustMenu()
{
+ // In case we're windowed, keep mouse centered while in game. Done in main.cpp in other conditions.
+#if defined(RW_GL3) && defined(IMPROVED_VIDEOMODE)
+ glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+#endif
m_bMenuActive = false;
CTimer::EndUserPause();
}
@@ -5623,8 +5543,14 @@ CMenuManager::SwitchMenuOnAndOff()
gMusicPlaying = 0;
}
*/
- if (m_bMenuActive != menuWasActive)
+ if (m_bMenuActive != menuWasActive) {
m_bMenuStateChanged = true;
+
+ // In case we're windowed, keep mouse centered while in game. Done in main.cpp in other conditions.
+#if defined(RW_GL3) && defined(IMPROVED_VIDEOMODE)
+ glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, m_bMenuActive && m_nPrefsWindowed ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_DISABLED);
+#endif
+ }
m_bStartUpFrontEndRequested = false;
m_bShutDownFrontEndRequested = false;
@@ -5662,7 +5588,7 @@ CMenuManager::WaitForUserCD()
CSprite2d *splash;
char *splashscreen = nil;
-#if (!(defined RANDOMSPLASH) && !(defined GTA3_1_1_PATCH))
+#if (!(defined RANDOMSPLASH) && GTA_VERSION < GTA3_PC_11)
if (CGame::frenchGame || CGame::germanGame || !CGame::nastyGame)
splashscreen = "mainsc2";
else
diff --git a/src/core/Frontend.h b/src/core/Frontend.h
index 848148e7..21124fdb 100644
--- a/src/core/Frontend.h
+++ b/src/core/Frontend.h
@@ -18,7 +18,6 @@
#define MENU_X_MARGIN 40.0f
#define MENUACTION_POS_Y 60.0f
-#define MENUACTION_WIDTH 38.0f
#define MENUACTION_SCALE_MULT 0.9f
#define MENURADIO_ICON_SCALE 60.0f
@@ -156,9 +155,6 @@ enum eSaveSlot
SAVESLOT_7,
SAVESLOT_8,
SAVESLOT_LABEL = 36,
-#ifdef CUSTOM_FRONTEND_OPTIONS
- SAVESLOT_CFO
-#endif
};
#ifdef MENU_MAP
@@ -239,18 +235,31 @@ enum eMenuScreen
MENUPAGE_MOUSE_CONTROLS = 56,
MENUPAGE_MISSION_RETRY = 57,
#ifdef MENU_MAP
- MENUPAGE_MAP,
+ MENUPAGE_MAP = 58,
#endif
- MENUPAGE_UNK, // 58 in game. Map page is added above, because last screen in CMenuScreens should always be empty to make CFO work
#ifdef CUSTOM_FRONTEND_OPTIONS
- MENUPAGES = 65 // for some room to add more screen
+
+#ifdef GRAPHICS_MENU_OPTIONS
+ MENUPAGE_GRAPHICS_SETTINGS,
#else
- MENUPAGES
+ MENUPAGE_ADVANCED_DISPLAY_SETTINGS,
+#endif
+#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
+ MENUPAGE_DETECT_JOYSTICK,
#endif
+
+#endif
+ MENUPAGE_UNK, // originally 58. Custom screens are inserted above, because last screen in CMenuScreens should always be empty to make CFO work
+ MENUPAGES
+
};
enum eMenuAction
{
+#ifdef CUSTOM_FRONTEND_OPTIONS
+ MENUACTION_CFO_SELECT = -2,
+ MENUACTION_CFO_DYNAMIC = -1,
+#endif
MENUACTION_NOTHING,
MENUACTION_LABEL,
MENUACTION_CHANGEMENU,
@@ -370,12 +379,6 @@ enum eMenuAction
// MENUACTION_MIPMAPS,
// MENUACTION_TEXTURE_FILTERING,
//#endif
-//#ifdef NO_ISLAND_LOADING
-// MENUACTION_ISLANDLOADING,
-//#endif
-#ifdef CUSTOM_FRONTEND_OPTIONS
- MENUACTION_TRIGGERFUNC
-#endif
};
enum eCheckHover
@@ -458,6 +461,7 @@ struct BottomBarOption
int32 screenId;
};
+#ifndef CUSTOM_FRONTEND_OPTIONS
struct CMenuScreen
{
char m_ScreenName[8];
@@ -470,9 +474,91 @@ struct CMenuScreen
int32 m_Action; // eMenuAction
char m_EntryName[8];
int32 m_SaveSlot; // eSaveSlot
- int32 m_TargetMenu; // eMenuScreen // FrontendOption ID if it's a custom option
+ int32 m_TargetMenu; // eMenuScreen
} m_aEntries[NUM_MENUROWS];
};
+extern CMenuScreen aScreens[MENUPAGES];
+#else
+#include "frontendoption.h"
+struct CCustomScreenLayout {
+ eMenuSprites sprite;
+ int columnWidth;
+ int headerHeight;
+ int lineHeight;
+ int8 font;
+ int8 alignment;
+ bool showLeftRightHelper;
+ float fontScaleX;
+ float fontScaleY;
+};
+
+struct CCFO
+{
+ int8 *value;
+ const char *save;
+};
+
+struct CCFOSelect : CCFO
+{
+ char** rightTexts;
+ int8 numRightTexts;
+ bool onlyApplyOnEnter;
+ int8 displayedValue; // only if onlyApplyOnEnter enabled for now
+ int8 lastSavedValue; // only if onlyApplyOnEnter enabled
+ ChangeFunc changeFunc;
+
+ CCFOSelect() {};
+ CCFOSelect(int8* value, const char* save, const char** rightTexts, int8 numRightTexts, bool onlyApplyOnEnter, ChangeFunc changeFunc){
+ this->value = value;
+ if (value)
+ this->lastSavedValue = this->displayedValue = *value;
+
+ this->save = save;
+ this->rightTexts = (char**)rightTexts;
+ this->numRightTexts = numRightTexts;
+ this->onlyApplyOnEnter = onlyApplyOnEnter;
+ this->changeFunc = changeFunc;
+ }
+};
+
+struct CCFODynamic : CCFO
+{
+ DrawFunc drawFunc;
+ ButtonPressFunc buttonPressFunc;
+
+ CCFODynamic() {};
+ CCFODynamic(int8* value, const char* save, DrawFunc drawFunc, ButtonPressFunc buttonPressFunc){
+ this->value = value;
+ this->save = save;
+ this->drawFunc = drawFunc;
+ this->buttonPressFunc = buttonPressFunc;
+ }
+};
+
+struct CMenuScreenCustom
+{
+ char m_ScreenName[8];
+ int32 m_PreviousPage[2]; // eMenuScreen
+ CCustomScreenLayout *layout;
+ ReturnPrevPageFunc returnPrevPageFunc;
+
+ struct CMenuEntry
+ {
+ int32 m_Action; // eMenuAction - below zero is CFO
+ char m_EntryName[8];
+ struct {
+ union {
+ CCFO *m_CFO; // for initializing
+ CCFOSelect *m_CFOSelect;
+ CCFODynamic *m_CFODynamic;
+ };
+ int32 m_SaveSlot; // eSaveSlot
+ int32 m_TargetMenu; // eMenuScreen
+ };
+ } m_aEntries[NUM_MENUROWS];
+};
+extern CMenuScreenCustom aScreens[MENUPAGES];
+#endif
class CMenuManager
{
@@ -628,7 +714,6 @@ public:
ISLAND_LOADING_HIGH
};
- static int8 m_DisplayIslandLoading;
static int8 m_PrefsIslandLoading;
#define ISLAND_LOADING_IS(p) if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_##p)
@@ -696,6 +781,7 @@ public:
void PageUpList(bool);
void PageDownList(bool);
int8 GetPreviousPageOption();
+ void ProcessList(bool &goBack, bool &optionSelected);
};
#ifndef IMPROVED_VIDEOMODE
@@ -703,6 +789,5 @@ VALIDATE_SIZE(CMenuManager, 0x564);
#endif
extern CMenuManager FrontEndMenuManager;
-extern CMenuScreen aScreens[MENUPAGES];
-#endif \ No newline at end of file
+#endif
diff --git a/src/core/Frontend_PS2.cpp b/src/core/Frontend_PS2.cpp
index a76ac279..1cb944d1 100644
--- a/src/core/Frontend_PS2.cpp
+++ b/src/core/Frontend_PS2.cpp
@@ -22,7 +22,7 @@
#include "Game.h"
#include "World.h"
#include "PlayerInfo.h"
-#include "FrontendControls.h"
+#include "FrontEndControls.h"
#include "MemoryCard.h"
#define CRect_SZ(x, y, w, h) CRect(x, y, x+w, y+h)
@@ -203,20 +203,6 @@ static const char* FrontendFilenames[][2] =
{"fe_radio9", "" },
};
-#ifdef CUTSCENE_BORDERS_SWITCH
-bool CMenuManager::m_PrefsCutsceneBorders = true;
-#endif
-
-#ifdef MULTISAMPLING
-int8 CMenuManager::m_nPrefsMSAALevel = 0;
-int8 CMenuManager::m_nDisplayMSAALevel = 0;
-#endif
-
-#ifdef NO_ISLAND_LOADING
-int8 CMenuManager::m_DisplayIslandLoading = ISLAND_LOADING_LOW;
-int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW;
-#endif
-
int32 CMenuManager::m_PrefsSfxVolume = 102;
int32 CMenuManager::m_PrefsMusicVolume = 102;
int32 CMenuManager::m_PrefsBrightness = 256;
@@ -3044,4 +3030,4 @@ CMenuManager::FilterOutColorMarkersFromString(wchar *string, CRGBA &color)
*dst = '\0';
}
-#endif \ No newline at end of file
+#endif
diff --git a/src/core/Frontend_PS2.h b/src/core/Frontend_PS2.h
index c1e42291..4bab7df9 100644
--- a/src/core/Frontend_PS2.h
+++ b/src/core/Frontend_PS2.h
@@ -160,31 +160,9 @@ public:
static int32 m_PrefsLanguage;
static CONTRCONFIG m_PrefsControllerConfig;
static bool m_PrefsUseVibration;
-#ifdef NO_ISLAND_LOADING
- enum
- {
- ISLAND_LOADING_LOW = 0,
- ISLAND_LOADING_MEDIUM,
- ISLAND_LOADING_HIGH
- };
-
- static int8 m_DisplayIslandLoading;
- static int8 m_PrefsIslandLoading;
-#define ISLAND_LOADING_IS(p) if (CMenuManager::m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_##p)
-#define ISLAND_LOADING_ISNT(p) if (CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_##p)
-#else
#define ISLAND_LOADING_IS(p)
#define ISLAND_LOADING_ISNT(p)
-#endif
-#ifdef CUTSCENE_BORDERS_SWITCH
- static bool m_PrefsCutsceneBorders;
-#endif
-#ifdef MULTISAMPLING
- static int8 m_nPrefsMSAALevel;
- static int8 m_nDisplayMSAALevel;
-#endif
-
#ifdef GTA_PC
bool m_bQuitGameNoCD;
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index ef4800c5..33302653 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -86,10 +86,14 @@
#include "ZoneCull.h"
#include "Zones.h"
#include "debugmenu.h"
-#include "frontendoption.h"
#include "postfx.h"
#include "custompipes.h"
+#include "screendroplets.h"
#include "crossplatform.h"
+#include "MemoryHeap.h"
+#ifdef USE_TEXTURE_POOL
+#include "TexturePools.h"
+#endif
eLevelName CGame::currLevel;
bool CGame::bDemoMode = true;
@@ -129,7 +133,7 @@ void MessageScreen(char *msg)
CFont::SetFontStyle(FONT_BANK);
CFont::SetBackgroundOff();
- CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f // unused
+ CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f
CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f));
CFont::SetCentreOn();
CFont::SetCentreSize(SCREEN_SCALE_X(450.0f)); // 450.0f
@@ -172,19 +176,33 @@ CGame::InitialiseRenderWare(void)
#ifdef USE_TEXTURE_POOL
_TexturePoolsInitialise();
#endif
-
- CTxdStore::Initialise();
- CVisibilityPlugins::Initialise();
-
+
+#if GTA_VERSION > GTA3_PS2_160
+ CTxdStore::Initialise(); // in GameInit on ps2
+ CVisibilityPlugins::Initialise(); // in plugin attach on ps2
+#endif
+
+ //InitialiseScene(Scene); // PS2 only, only clears Scene.camera
+
+#ifdef GTA_PS2
+ RpSkySelectTrueTSClipper(TRUE);
+ RpSkySelectTrueTLClipper(TRUE);
+
+ // PS2ManagerApplyDirectionalLightingCB() uploads the GTA lights
+ // directly without going through RpWorld and all that
+ SetupPS2ManagerDefaultLightingCallback();
+ PreAllocateRwObjects();
+#endif
+
/* Create camera */
- Scene.camera = CameraCreate(RsGlobal.width, RsGlobal.height, TRUE);
+ Scene.camera = CameraCreate(SCREEN_WIDTH, SCREEN_HEIGHT, TRUE);
ASSERT(Scene.camera != nil);
if (!Scene.camera)
{
return (false);
}
- RwCameraSetFarClipPlane(Scene.camera, 2000.0f);
+ RwCameraSetFarClipPlane(Scene.camera, 2000.0f); // 250.0f on PS2 but who cares
RwCameraSetNearClipPlane(Scene.camera, 0.9f);
CameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
@@ -207,8 +225,12 @@ CGame::InitialiseRenderWare(void)
/* Add the camera to the world */
RpWorldAddCamera(Scene.world, Scene.camera);
LightsCreate(Scene.world);
-
- CreateDebugFont();
+
+#if GTA_VERSION > GTA3_PS2_160
+ CreateDebugFont(); // in GameInit on PS2
+#else
+ RwImageSetPath("textures");
+#endif
#ifdef LIBRW
#ifdef PS2_MATFX
@@ -224,14 +246,22 @@ CGame::InitialiseRenderWare(void)
ReplaceAtomicPipeCallback();
#endif // PS2_ALPHA_TEST
#endif // LIBRW
-
+
+
+#if GTA_VERSION > GTA3_PS2_160
+ // in GameInit on PS2
+ PUSH_MEMID(MEMID_TEXTURES);
CFont::Initialise();
CHud::Initialise();
+ POP_MEMID();
+#endif
+ // TODO: define
CPlayerSkin::Initialise();
return (true);
}
+// missing altogether on PS2
void CGame::ShutdownRenderWare(void)
{
CMBlur::MotionBlurClose();
@@ -241,7 +271,8 @@ void CGame::ShutdownRenderWare(void)
for ( int32 i = 0; i < NUMPLAYERS; i++ )
CWorld::Players[i].DeletePlayerSkin();
-
+
+ // TODO: define
CPlayerSkin::Shutdown();
DestroyDebugFont();
@@ -264,16 +295,19 @@ void CGame::ShutdownRenderWare(void)
#endif
}
+// missing altogether on PS2
bool CGame::InitialiseOnceAfterRW(void)
{
+#if GTA_VERSION > GTA3_PS2_160
TheText.Load();
- DMAudio.Initialise();
+ DMAudio.Initialise(); // before TheGame() on PS2
CTimer::Initialise();
CTempColModels::Initialise();
mod_HandlingManager.Initialise();
CSurfaceTable::Initialise("DATA\\SURFACE.DAT");
CPedStats::Initialise();
CTimeCycle::Initialise();
+#endif
if ( DMAudio.GetNum3DProvidersAvailable() == 0 )
FrontEndMenuManager.m_nPrefsAudio3DProviderIndex = -1;
@@ -314,19 +348,10 @@ bool CGame::InitialiseOnceAfterRW(void)
DMAudio.SetMusicFadeVol(127);
CWorld::Players[0].SetPlayerSkin(CMenuManager::m_PrefsSkinFile);
-#ifdef CUSTOM_FRONTEND_OPTIONS
- // Apparently this func. can be run multiple times at the start.
- if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0) {
- // needs stored language and TheText to be loaded, and last TheText reload is at the start of here
- CustomFrontendOptionsPopulate();
- }
-#endif
-#ifdef LOAD_INI_SETTINGS
- LoadINISettings(); // needs frontend options to be loaded
-#endif
return true;
}
+// missing altogether on PS2
void
CGame::FinalShutdown(void)
{
@@ -337,21 +362,40 @@ CGame::FinalShutdown(void)
bool CGame::Initialise(const char* datFile)
{
+#ifdef GTA_PS2
+ // TODO: upload VU0 collision code here
+#endif
+
+#if GTA_VERSION > GTA3_PS2_160
ResetLoadingScreenBar();
strcpy(aDatFile, datFile);
- CPools::Initialise();
+ CPools::Initialise(); // done in CWorld on PS2
+#endif
+
+#ifndef GTA_PS2
CIniFile::LoadIniFile();
+#endif
+
currLevel = LEVEL_INDUSTRIAL;
+
+ PUSH_MEMID(MEMID_TEXTURES);
LoadingScreen("Loading the Game", "Loading generic textures", GetRandomSplashScreen());
gameTxdSlot = CTxdStore::AddTxdSlot("generic");
CTxdStore::Create(gameTxdSlot);
CTxdStore::AddRef(gameTxdSlot);
+
LoadingScreen("Loading the Game", "Loading particles", nil);
int particleTxdSlot = CTxdStore::AddTxdSlot("particle");
CTxdStore::LoadTxd(particleTxdSlot, "MODELS/PARTICLE.TXD");
CTxdStore::AddRef(particleTxdSlot);
CTxdStore::SetCurrentTxd(gameTxdSlot);
LoadingScreen("Loading the Game", "Setup game variables", nil);
+ POP_MEMID();
+
+#ifdef GTA_PS2
+ CDma::SyncChannel(0, true);
+#endif
+
CGameLogic::InitAtStartOfGame();
CReferences::Init();
TheCamera.Init();
@@ -362,32 +406,72 @@ bool CGame::Initialise(const char* datFile)
CWeather::Init();
CCullZones::Init();
CCollision::Init();
-#ifdef PS2_MENU
+#ifdef PS2_MENU // TODO: is this the right define?
TheText.Load();
#endif
CTheZones::Init();
CUserDisplay::Init();
CMessages::Init();
+#if GTA_VERSION > GTA3_PS2_160
CMessages::ClearAllMessagesDisplayedByGame();
+#endif
CRecordDataForGame::Init();
CRestart::Initialise();
+
+ PUSH_MEMID(MEMID_WORLD);
CWorld::Initialise();
+ POP_MEMID();
+
+#if GTA_VERSION <= GTA3_PS2_160
+ mod_HandlingManager.Initialise();
+ CSurfaceTable::Initialise("DATA\\SURFACE.DAT");
+ CTempColModels::Initialise();
+#endif
+
+ PUSH_MEMID(MEMID_TEXTURES);
CParticle::Initialise();
-#ifdef PS2
+ POP_MEMID();
+
+#if GTA_VERSION <= GTA3_PS2_160
gStartX = -180.0f;
gStartY = 180.0f;
gStartZ = 14.0f;
#endif
+
+ PUSH_MEMID(MEMID_ANIMATION);
CAnimManager::Initialise();
CCutsceneMgr::Initialise();
+ POP_MEMID();
+
+ PUSH_MEMID(MEMID_CARS);
CCarCtrl::Init();
+ POP_MEMID();
+
+#if GTA_VERSION > GTA3_PS2_160
InitModelIndices();
+#endif
+
+ PUSH_MEMID(MEMID_DEF_MODELS);
CModelInfo::Initialise();
+#if GTA_VERSION <= GTA3_PS2_160
+ CPedStats::Initialise(); // InitialiseOnceAfterRW
+#else
+ // probably moved before LoadLevel for multiplayer maps?
CPickups::Init();
CTheCarGenerators::Init();
+#endif
+
+#ifndef GTA_PS2 // or GTA_VERSION?
CdStreamAddImage("MODELS\\GTA3.IMG");
+#endif
+
+#if GTA_VERSION > GTA3_PS2_160
CFileLoader::LoadLevel("DATA\\DEFAULT.DAT");
CFileLoader::LoadLevel(datFile);
+#else
+ CFileLoader::LoadLevel("GTA3.DAT");
+#endif
+
#ifdef EXTENDED_PIPELINES
// for generic fallback
CustomPipes::SetTxdFindCallback();
@@ -396,17 +480,30 @@ bool CGame::Initialise(const char* datFile)
CVehicleModelInfo::LoadVehicleColours();
CVehicleModelInfo::LoadEnvironmentMaps();
CTheZones::PostZoneCreation();
+ POP_MEMID();
+
+#if GTA_VERSION <= GTA3_PS2_160
+ TestModelIndices();
+#endif
LoadingScreen("Loading the Game", "Setup paths", GetRandomSplashScreen());
ThePaths.PreparePathData();
+#if GTA_VERSION > GTA3_PS2_160
for (int i = 0; i < NUMPLAYERS; i++)
CWorld::Players[i].Clear();
CWorld::Players[0].LoadPlayerSkin();
TestModelIndices();
+#endif
+
LoadingScreen("Loading the Game", "Setup water", nil);
CWaterLevel::Initialise("DATA\\WATER.DAT");
+#if GTA_VERSION <= GTA3_PS2_160
+ CTimeCycle::Initialise(); // InitialiseOnceAfterRW
+#else
TheConsole.Init();
+#endif
CDraw::SetFOV(120.0f);
CDraw::ms_fLODDistance = 500.0f;
+
LoadingScreen("Loading the Game", "Setup streaming", nil);
CStreaming::Init();
CStreaming::LoadInitialVehicles();
@@ -414,22 +511,37 @@ bool CGame::Initialise(const char* datFile)
CStreaming::RequestBigBuildings(LEVEL_GENERIC);
CStreaming::LoadAllRequestedModels(false);
printf("Streaming uses %zuK of its memory", CStreaming::ms_memoryUsed / 1024); // original modifier was %d
+
LoadingScreen("Loading the Game", "Load animations", GetRandomSplashScreen());
+ PUSH_MEMID(MEMID_ANIMATION);
CAnimManager::LoadAnimFiles();
+ POP_MEMID();
+
CPed::Initialise();
CRouteNode::Initialise();
CEventList::Initialise();
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::Initialise();
+#endif
LoadingScreen("Loading the Game", "Find big buildings", nil);
CRenderer::Init();
+
LoadingScreen("Loading the Game", "Setup game variables", nil);
CRadar::Initialise();
CRadar::LoadTextures();
CWeapon::InitialiseWeapons();
+
LoadingScreen("Loading the Game", "Setup traffic lights", nil);
CTrafficLights::ScanForLightsOnMap();
CRoadBlocks::Init();
+
LoadingScreen("Loading the Game", "Setup game variables", nil);
CPopulation::Initialise();
+#if GTA_VERSION <= GTA3_PS2_160
+ for (int i = 0; i < NUMPLAYERS; i++)
+ CWorld::Players[i].Clear();
+// CWorld::Players[0].LoadPlayerSkin(); // TODO: use a define for this
+#endif
CWorld::PlayerInFocus = 0;
CCoronas::Init();
CShadows::Init();
@@ -438,44 +550,74 @@ bool CGame::Initialise(const char* datFile)
CAntennas::Init();
CGlass::Init();
gPhoneInfo.Initialise();
+#ifdef GTA_SCENE_EDIT
CSceneEdit::Initialise();
+#endif
+
LoadingScreen("Loading the Game", "Load scripts", nil);
+ PUSH_MEMID(MEMID_SCRIPT);
CTheScripts::Init();
CGangs::Initialise();
+ POP_MEMID();
+
LoadingScreen("Loading the Game", "Setup game variables", nil);
+#if GTA_VERSION <= GTA3_PS2_160
+ CTimer::Initialise();
+#endif
CClock::Initialise(1000);
+#if GTA_VERSION <= GTA3_PS2_160
+ CTheCarGenerators::Init();
+#endif
CHeli::InitHelis();
CCranes::InitCranes();
CMovingThings::Init();
CDarkel::Init();
CStats::Init();
+#if GTA_VERSION <= GTA3_PS2_160
+ CPickups::Init();
+#endif
CPacManPickups::Init();
+#if GTA_VERSION <= GTA3_PS2_160
+ CGarages::Init();
+#endif
CRubbish::Init();
CClouds::Init();
+#if GTA_VERSION <= GTA3_PS2_160
+ CRemote::Init();
+#endif
CSpecialFX::Init();
CWaterCannons::Init();
CBridge::Init();
+#if GTA_VERSION > GTA3_PS2_160
CGarages::Init();
+#endif
+
LoadingScreen("Loading the Game", "Position dynamic objects", nil);
CWorld::RepositionCertainDynamicObjects();
+#if GTA_VERSION <= GTA3_PS2_160
+ CCullZones::ResolveVisibilities();
+#endif
+
LoadingScreen("Loading the Game", "Initialise vehicle paths", nil);
+#if GTA_VERSION > GTA3_PS2_160
CCullZones::ResolveVisibilities();
+#endif
CTrain::InitTrains();
CPlane::InitPlanes();
CCredits::Init();
CRecordDataForChase::Init();
CReplay::Init();
+
#ifdef PS2_MENU
if ( !TheMemoryCard.m_bWantToLoad )
- {
#endif
- LoadingScreen("Loading the Game", "Start script", nil);
- CTheScripts::StartTestScript();
- CTheScripts::Process();
- TheCamera.Process();
-#ifdef PS2_MENU
+ {
+ LoadingScreen("Loading the Game", "Start script", nil);
+ CTheScripts::StartTestScript();
+ CTheScripts::Process();
+ TheCamera.Process();
}
-#endif
+
LoadingScreen("Loading the Game", "Load scene", nil);
CModelInfo::RemoveColModelsFromOtherLevels(currLevel);
CCollision::ms_collisionInMemory = currLevel;
@@ -490,7 +632,7 @@ bool CGame::ShutDown(void)
CPlane::Shutdown();
CTrain::Shutdown();
CSpecialFX::Shutdown();
-#ifndef PS2
+#if GTA_VERSION > GTA3_PS2_160
CGarages::Shutdown();
#endif
CMovingThings::Shutdown();
@@ -531,7 +673,9 @@ bool CGame::ShutDown(void)
CSkidmarks::Shutdown();
CWeaponEffects::Shutdown();
CParticle::Shutdown();
+#if GTA_VERSION > GTA3_PS2_160
CPools::ShutDown();
+#endif
CTxdStore::RemoveTxdSlot(gameTxdSlot);
CdStreamRemoveImages();
return true;
@@ -542,13 +686,11 @@ void CGame::ReInitGameObjectVariables(void)
CGameLogic::InitAtStartOfGame();
#ifdef PS2_MENU
if ( !TheMemoryCard.m_bWantToLoad )
- {
#endif
- TheCamera.Init();
- TheCamera.SetRwCamera(Scene.camera);
-#ifdef PS2_MENU
+ {
+ TheCamera.Init();
+ TheCamera.SetRwCamera(Scene.camera);
}
-#endif
CDebug::DebugInitTextBuffer();
CWeather::Init();
CUserDisplay::Init();
@@ -557,7 +699,7 @@ void CGame::ReInitGameObjectVariables(void)
CWorld::bDoingCarCollisions = false;
CHud::ReInitialise();
CRadar::Initialise();
-#ifdef PS2
+#if GTA_VERSION <= GTA3_PS2_160
gStartX = -180.0f;
gStartY = 180.0f;
gStartZ = 14.0f;
@@ -570,6 +712,9 @@ void CGame::ReInitGameObjectVariables(void)
CStreaming::LoadAllRequestedModels(false);
CPed::Initialise();
CEventList::Initialise();
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::Initialise();
+#endif
CWeapon::InitialiseWeapons();
CPopulation::Initialise();
@@ -577,15 +722,19 @@ void CGame::ReInitGameObjectVariables(void)
CWorld::Players[i].Clear();
CWorld::PlayerInFocus = 0;
-#ifdef PS2
+#if GTA_VERSION <= GTA3_PS2_160
CWeaponEffects::Init();
CSkidmarks::Init();
#endif
CAntennas::Init();
CGlass::Init();
gPhoneInfo.Initialise();
+
+ PUSH_MEMID(MEMID_SCRIPT);
CTheScripts::Init();
CGangs::Initialise();
+ POP_MEMID();
+
CTimer::Initialise();
CClock::Initialise(1000);
CTheCarGenerators::Init();
@@ -596,7 +745,7 @@ void CGame::ReInitGameObjectVariables(void)
CPickups::Init();
CPacManPickups::Init();
CGarages::Init();
-#ifdef PS2
+#if GTA_VERSION <= GTA3_PS2_160
CClouds::Init();
CRemote::Init();
#endif
@@ -666,7 +815,7 @@ void CGame::ShutDownForRestart(void)
CRadar::RemoveRadarSections();
FrontEndMenuManager.UnloadTextures();
CParticleObject::RemoveAllParticleObjects();
-#ifndef PS2
+#if GTA_VERSION >= GTA3_PS2_160
CPedType::Shutdown();
CSpecialFX::Shutdown();
#endif
@@ -745,10 +894,10 @@ void CGame::InitialiseWhenRestarting(void)
//CFont::SetFontStyle(?);
CFont::SetBackgroundOff();
- CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f // unused
+ CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(160.0f)); // 480.0f
CFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f));
CFont::SetCentreOn();
- CFont::SetCentreSize(SCREEN_SCALE_X(480.0f)); // 480.0f
+ CFont::SetCentreSize(SCREEN_SCALE_X(480.0f));
CFont::SetJustifyOff();
CFont::SetColor(CRGBA(255, 255, 255, 255));
CFont::SetBackGroundOnlyTextOff();
@@ -811,7 +960,7 @@ void CGame::InitialiseWhenRestarting(void)
void CGame::Process(void)
{
CPad::UpdatePads();
-#ifdef GTA_PS2
+#ifdef USE_CUSTOM_ALLOCATOR
ProcessTidyUpMemory();
#endif
TheCamera.SetMotionBlurAlpha(0);
@@ -821,8 +970,12 @@ void CGame::Process(void)
DebugMenuProcess();
#endif
CCutsceneMgr::Update();
+
+ PUSH_MEMID(MEMID_FRONTEND);
if (!CCutsceneMgr::IsCutsceneProcessing() && !CTimer::GetIsCodePaused())
FrontEndMenuManager.Process();
+ POP_MEMID();
+
CStreaming::Update();
if (!CTimer::GetIsPaused())
{
@@ -835,7 +988,11 @@ void CGame::Process(void)
CPad::DoCheats();
CClock::Update();
CWeather::Update();
+
+ PUSH_MEMID(MEMID_SCRIPT);
CTheScripts::Process();
+ POP_MEMID();
+
CCollision::Update();
CTrain::UpdateTrains();
CPlane::UpdatePlanes();
@@ -844,7 +1001,9 @@ void CGame::Process(void)
CSkidmarks::Update();
CAntennas::Update();
CGlass::Update();
+#ifdef GTA_SCENE_EDIT
CSceneEdit::Update();
+#endif
CEventList::Update();
CParticle::Update();
gFireManager.Update();
@@ -859,7 +1018,11 @@ void CGame::Process(void)
CWaterCannons::Update();
CUserDisplay::Process();
CReplay::Update();
+
+ PUSH_MEMID(MEMID_WORLD);
CWorld::Process();
+ POP_MEMID();
+
gAccidentManager.Update();
CPacManPickups::Update();
CPickups::Update();
@@ -880,33 +1043,370 @@ void CGame::Process(void)
gPhoneInfo.Update();
if (!CReplay::IsPlayingBack())
{
+ PUSH_MEMID(MEMID_CARS);
CCarCtrl::GenerateRandomCars();
CRoadBlocks::GenerateRoadBlocks();
CCarCtrl::RemoveDistantCars();
+ POP_MEMID();
}
}
-#ifdef PS2
+#ifdef GTA_PS2
CMemCheck::DoTest();
#endif
}
-void CGame::DrasticTidyUpMemory(bool)
+#ifdef USE_CUSTOM_ALLOCATOR
+
+int32 gNumMemMoved;
+
+bool
+MoveMem(void **ptr)
+{
+ if(*ptr){
+ gNumMemMoved++;
+ void *newPtr = gMainHeap.MoveMemory(*ptr);
+ if(*ptr != newPtr){
+ *ptr = newPtr;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Some convenience structs
+struct SkyDataPrefix
+{
+ uint32 pktSize1;
+ uint32 data; // pointer to data as read from TXD
+ uint32 pktSize2;
+ uint32 unused;
+};
+
+struct DMAGIFUpload
+{
+ uint32 tag1_qwc, tag1_addr; // dmaref
+ uint32 nop1, vif_direct1;
+
+ uint32 giftag[4];
+ uint32 gs_bitbltbuf[4];
+
+ uint32 tag2_qwc, tag2_addr; // dmaref
+ uint32 nop2, vif_direct2;
+};
+
+// This is very scary. it depends on the exact memory layout of the DMA chains and whatnot
+RwTexture *
+MoveTextureMemoryCB(RwTexture *texture, void *pData)
+{
+#ifdef GTA_PS2
+ bool *pRet = (bool*)pData;
+ RwRaster *raster = RwTextureGetRaster(texture);
+ _SkyRasterExt *rasterExt = RASTEREXTFROMRASTER(raster);
+ if(raster->originalPixels == nil || // the raw data
+ raster->cpPixels == raster->originalPixels || // old format, can't handle it
+ rasterExt->dmaRefCount != 0 && rasterExt->dmaClrCount != 0)
+ return texture;
+
+ // this is the allocated pointer we will move
+ SkyDataPrefix *prefix = (SkyDataPrefix*)raster->originalPixels;
+ DMAGIFUpload *uploads = (DMAGIFUpload*)(prefix+1);
+
+ // We have 4qw for each upload,
+ // i.e. for each buffer width of mip levels,
+ // and the palette if there is one.
+ // NB: this code does NOT support mipmaps!
+ // so we assume two uploads (pixels and palette)
+ //
+ // each upload looks like this:
+ // (DMAcnt; NOP; VIF DIRECT(2))
+ // giftag (1, A+D)
+ // GS_BITBLTBUF
+ // (DMAref->pixel data; NOP; VIF DIRECT(5))
+ // the DMArefs are what we have to adjust
+ uintptr dataDiff, upload1Diff, upload2Diff, pixelDiff, paletteDiff;
+ dataDiff = prefix->data - (uintptr)raster->originalPixels;
+ upload1Diff = uploads[0].tag2_addr - (uintptr)raster->originalPixels;
+ if(raster->palette)
+ upload2Diff = uploads[1].tag2_addr - (uintptr)raster->originalPixels;
+ pixelDiff = (uintptr)raster->cpPixels - (uintptr)raster->originalPixels;
+ if(raster->palette)
+ paletteDiff = (uintptr)raster->palette - (uintptr)raster->originalPixels;
+ uint8 *newptr = (uint8*)gMainHeap.MoveMemory(raster->originalPixels);
+ if(newptr != raster->originalPixels){
+ // adjust everything
+ prefix->data = (uintptr)newptr + dataDiff;
+ uploads[0].tag2_addr = (uintptr)newptr + upload1Diff;
+ if(raster->palette)
+ uploads[1].tag2_addr = (uintptr)newptr + upload2Diff;
+ raster->originalPixels = newptr;
+ raster->cpPixels = newptr + pixelDiff;
+ if(raster->palette)
+ raster->palette = newptr + paletteDiff;
+
+ if(pRet){
+ *pRet = true;
+ return nil;
+ }
+ }
+#else
+ // nothing to do here really, everything should be in videomemory
+#endif
+ return texture;
+}
+
+bool
+MoveAtomicMemory(RpAtomic *atomic, bool onlyOne)
+{
+ RpGeometry *geo = RpAtomicGetGeometry(atomic);
+
+#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31
+ if(MoveMem((void**)&geo->triangles) && onlyOne)
+ return true;
+ if(MoveMem((void**)&geo->matList.materials) && onlyOne)
+ return true;
+ if(MoveMem((void**)&geo->preLitLum) && onlyOne)
+ return true;
+ if(MoveMem((void**)&geo->texCoords[0]) && onlyOne)
+ return true;
+ if(MoveMem((void**)&geo->texCoords[1]) && onlyOne)
+ return true;
+
+ // verts and normals of morph target are allocated together
+ int vertDiff;
+ if(geo->morphTarget->normals)
+ vertDiff = geo->morphTarget->normals - geo->morphTarget->verts;
+ if(MoveMem((void**)&geo->morphTarget->verts)){
+ if(geo->morphTarget->normals)
+ geo->morphTarget->normals = geo->morphTarget->verts + vertDiff;
+ if(onlyOne)
+ return true;
+ }
+
+ RpMeshHeader *oldmesh = geo->mesh;
+ if(MoveMem((void**)&geo->mesh)){
+ // index pointers are allocated together with meshes,
+ // have to relocate those too
+ RpMesh *mesh = (RpMesh*)(geo->mesh+1);
+ uintptr reloc = (uintptr)geo->mesh - (uintptr)oldmesh;
+ for(int i = 0; i < geo->mesh->numMeshes; i++)
+ mesh[i].indices = (RxVertexIndex*)((uintptr)mesh[i].indices + reloc);
+ if(onlyOne)
+ return true;
+ }
+#else
+ // we could do something in librw here
+#endif
+ return false;
+}
+
+bool
+MoveColModelMemory(CColModel &colModel, bool onlyOne)
+{
+#if GTA_VERSION >= GTA3_PS2_160
+ // hm...should probably only do this if ownsCollisionVolumes
+ // but it doesn't exist on PS2...
+ if(!colModel.ownsCollisionVolumes)
+ return false;
+#endif
+
+ if(MoveMem((void**)&colModel.spheres) && onlyOne)
+ return true;
+ if(MoveMem((void**)&colModel.lines) && onlyOne)
+ return true;
+ if(MoveMem((void**)&colModel.boxes) && onlyOne)
+ return true;
+ if(MoveMem((void**)&colModel.vertices) && onlyOne)
+ return true;
+ if(MoveMem((void**)&colModel.triangles) && onlyOne)
+ return true;
+ if(MoveMem((void**)&colModel.trianglePlanes) && onlyOne)
+ return true;
+ return false;
+}
+
+RpAtomic*
+MoveAtomicMemoryCB(RpAtomic *atomic, void *pData)
+{
+ bool *pRet = (bool*)pData;
+ if(pRet == nil)
+ MoveAtomicMemory(atomic, false);
+ else if(MoveAtomicMemory(atomic, true)){
+ *pRet = true;
+ return nil;
+ }
+ return atomic;
+}
+
+bool
+TidyUpModelInfo(CBaseModelInfo *modelInfo, bool onlyone)
{
-#ifdef PS2
- // meow
+ if(modelInfo->GetColModel() && modelInfo->DoesOwnColModel())
+ if(MoveColModelMemory(*modelInfo->GetColModel(), onlyone))
+ return true;
+
+ RwObject *rwobj = modelInfo->GetRwObject();
+ if(RwObjectGetType(rwobj) == rpATOMIC)
+ if(MoveAtomicMemory((RpAtomic*)rwobj, onlyone))
+ return true;
+ if(RwObjectGetType(rwobj) == rpCLUMP){
+ bool ret = false;
+ if(onlyone)
+ RpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, &ret);
+ else
+ RpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, nil);
+ if(ret)
+ return true;
+ }
+
+ if(modelInfo->GetModelType() == MITYPE_PED && ((CPedModelInfo*)modelInfo)->m_hitColModel)
+ if(MoveColModelMemory(*((CPedModelInfo*)modelInfo)->m_hitColModel, onlyone))
+ return true;
+
+ return false;
+}
+#endif
+
+void CGame::DrasticTidyUpMemory(bool flushDraw)
+{
+#ifdef USE_CUSTOM_ALLOCATOR
+ bool removedCol = false;
+
+ TidyUpMemory(true, flushDraw);
+
+ if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){
+ CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL);
+ CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL);
+ CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
+ TidyUpMemory(true, flushDraw);
+ }
+
+ if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){
+ CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC);
+ TidyUpMemory(true, flushDraw);
+ removedCol = true;
+ }
+
+ if(gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro){
+ CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);
+ CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);
+ CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);
+ TidyUpMemory(true, flushDraw);
+ }
+
+ if(removedCol){
+ // different on PS2
+ CFileLoader::LoadCollisionFromDatFile(CCollision::ms_collisionInMemory);
+ }
+
+ if(!playingIntro)
+ CStreaming::RequestBigBuildings(currLevel);
+
+ CStreaming::LoadAllRequestedModels(true);
#endif
}
-void CGame::TidyUpMemory(bool, bool)
+void CGame::TidyUpMemory(bool moveTextures, bool flushDraw)
{
-#ifdef PS2
- // meow
+#ifdef USE_CUSTOM_ALLOCATOR
+ printf("Largest free block before tidy %d\n", gMainHeap.GetLargestFreeBlock());
+
+ if(moveTextures){
+ if(flushDraw){
+#ifdef GTA_PS2
+ for(int i = 0; i < sweMaxFlips+1; i++){
+#else
+ for(int i = 0; i < 5; i++){ // probably more than needed
+#endif
+ RwCameraBeginUpdate(Scene.camera);
+ RwCameraEndUpdate(Scene.camera);
+ RwCameraShowRaster(Scene.camera, nil, 0);
+ }
+ }
+ int fontSlot = CTxdStore::FindTxdSlot("fonts");
+
+ for(int i = 0; i < TXDSTORESIZE; i++){
+ if(i == fontSlot ||
+ CTxdStore::GetSlot(i) == nil)
+ continue;
+ RwTexDictionary *txd = CTxdStore::GetSlot(i)->texDict;
+ if(txd)
+ RwTexDictionaryForAllTextures(txd, MoveTextureMemoryCB, nil);
+ }
+ }
+
+ // animations
+ for(int i = 0; i < NUMANIMATIONS; i++){
+ CAnimBlendHierarchy *anim = CAnimManager::GetAnimation(i);
+ if(anim == nil)
+ continue; // cannot happen
+ anim->MoveMemory();
+ }
+
+ // model info
+ for(int i = 0; i < MODELINFOSIZE; i++){
+ CBaseModelInfo *mi = CModelInfo::GetModelInfo(i);
+ if(mi == nil)
+ continue;
+ TidyUpModelInfo(mi, false);
+ }
+
+ printf("Largest free block after tidy %d\n", gMainHeap.GetLargestFreeBlock());
#endif
}
void CGame::ProcessTidyUpMemory(void)
{
-#ifdef PS2
- // meow
+#ifdef USE_CUSTOM_ALLOCATOR
+ static int32 modelIndex = 0;
+ static int32 animIndex = 0;
+ static int32 txdIndex = 0;
+ bool txdReturn = false;
+ RwTexDictionary *txd = nil;
+ gNumMemMoved = 0;
+
+ // model infos
+ for(int numCleanedUp = 0; numCleanedUp < 10; numCleanedUp++){
+ CBaseModelInfo *mi;
+ do{
+ mi = CModelInfo::GetModelInfo(modelIndex);
+ modelIndex++;
+ if(modelIndex >= MODELINFOSIZE)
+ modelIndex = 0;
+ }while(mi == nil);
+
+ if(TidyUpModelInfo(mi, true))
+ return;
+ }
+
+ // tex dicts
+ for(int numCleanedUp = 0; numCleanedUp < 3; numCleanedUp++){
+ if(gNumMemMoved > 80)
+ break;
+
+ do{
+#ifdef FIX_BUGS
+ txd = nil;
+#endif
+ if(CTxdStore::GetSlot(txdIndex))
+ txd = CTxdStore::GetSlot(txdIndex)->texDict;
+ txdIndex++;
+ if(txdIndex >= TXDSTORESIZE)
+ txdIndex = 0;
+ }while(txd == nil);
+
+ RwTexDictionaryForAllTextures(txd, MoveTextureMemoryCB, &txdReturn);
+ if(txdReturn)
+ return;
+ }
+
+ // animations
+ CAnimBlendHierarchy *anim;
+ do{
+ anim = CAnimManager::GetAnimation(animIndex);
+ animIndex++;
+ if(animIndex >= NUMANIMATIONS)
+ animIndex = 0;
+ }while(anim == nil); // always != nil
+ anim->MoveMemory(true);
#endif
}
diff --git a/src/core/MenuScreens.cpp b/src/core/MenuScreens.cpp
index 533fc755..9eff09e6 100644
--- a/src/core/MenuScreens.cpp
+++ b/src/core/MenuScreens.cpp
@@ -2,8 +2,10 @@
#include "Frontend.h"
#ifdef PC_MENU
-// If you want to add new options, please don't do that here and see CustomFrontendOptionsPopulate in re3.cpp.
+// Please don't touch this file, except for bug fixing or ports.
+// Check MenuScreensCustom.cpp
+#ifndef CUSTOM_FRONTEND_OPTIONS
CMenuScreen aScreens[MENUPAGES] = {
// MENUPAGE_NONE = 0
{ "", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0, },
@@ -390,6 +392,9 @@ CMenuScreen aScreens[MENUPAGES] = {
{ "FET_PAU", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
MENUACTION_RESUME, "FEM_RES", SAVESLOT_NONE, MENUPAGE_NONE,
MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
+#ifdef MENU_MAP
+ MENUACTION_CHANGEMENU, "FEG_MAP", SAVESLOT_NONE, MENUPAGE_MAP,
+#endif
MENUACTION_CHANGEMENU, "FEP_STA", SAVESLOT_NONE, MENUPAGE_STATS,
MENUACTION_CHANGEMENU, "FEP_BRI", SAVESLOT_NONE, MENUPAGE_BRIEFS,
MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS,
@@ -436,10 +441,10 @@ CMenuScreen aScreens[MENUPAGES] = {
#ifdef MENU_MAP
// MENUPAGE_MAP
- { "FEG_MAP", 1, MENUPAGE_NONE, MENUPAGE_NONE, 5, 2,
+ { "FEG_MAP", 1, MENUPAGE_NONE, MENUPAGE_NONE, 2, 2,
MENUACTION_UNK110, "", SAVESLOT_NONE, MENUPAGE_NONE, // to prevent cross/enter to go back
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
- },
+ },
#endif
// MENUPAGE_UNK
@@ -449,4 +454,5 @@ CMenuScreen aScreens[MENUPAGES] = {
};
-#endif \ No newline at end of file
+#endif
+#endif
diff --git a/src/core/MenuScreensCustom.cpp b/src/core/MenuScreensCustom.cpp
new file mode 100644
index 00000000..ae08f5f5
--- /dev/null
+++ b/src/core/MenuScreensCustom.cpp
@@ -0,0 +1,878 @@
+#include "common.h"
+#include "platform.h"
+#include "crossplatform.h"
+#include "Renderer.h"
+#include "Frontend.h"
+#include "Font.h"
+#include "Camera.h"
+#include "main.h"
+#include "MBlur.h"
+#include "postfx.h"
+#include "custompipes.h"
+#include "RwHelper.h"
+#include "Text.h"
+#include "Streaming.h"
+#include "FileLoader.h"
+#include "Collision.h"
+#include "ModelInfo.h"
+#include "Pad.h"
+
+// Menu screens array is at the bottom of the file.
+
+#ifdef PC_MENU
+
+#ifdef CUSTOM_FRONTEND_OPTIONS
+
+#ifdef IMPROVED_VIDEOMODE
+ #define VIDEOMODE_SELECTOR MENUACTION_CFO_SELECT, "FEM_SCF", { new CCFOSelect((int8*)&FrontEndMenuManager.m_nPrefsWindowed, nil, screenModes, 2, true, ScreenModeAfterChange) },
+#else
+ #define VIDEOMODE_SELECTOR
+#endif
+
+#ifdef MULTISAMPLING
+ #define MULTISAMPLING_SELECTOR MENUACTION_CFO_DYNAMIC, "FED_AAS", { new CCFODynamic((int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, "MultiSampling", MultiSamplingDraw, MultiSamplingButtonPress) },
+#else
+ #define MULTISAMPLING_SELECTOR
+#endif
+
+#ifdef CUTSCENE_BORDERS_SWITCH
+ #define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, "FEM_CSB", { new CCFOSelect((int8 *)&CMenuManager::m_PrefsCutsceneBorders, "CutsceneBorders", off_on, 2, false, nil) },
+#else
+ #define CUTSCENE_BORDERS_TOGGLE
+#endif
+
+#ifdef FREE_CAM
+ #define FREE_CAM_TOGGLE MENUACTION_CFO_SELECT, "FEC_FRC", { new CCFOSelect((int8*)&TheCamera.bFreeCam, "FreeCam", off_on, 2, false, nil) },
+#else
+ #define FREE_CAM_TOGGLE
+#endif
+
+#ifdef PS2_ALPHA_TEST
+ #define DUALPASS_SELECTOR MENUACTION_CFO_SELECT, "FEM_2PR", { new CCFOSelect((int8*)&gPS2alphaTest, "PS2AlphaTest", off_on, 2, false, nil) },
+#else
+ #define DUALPASS_SELECTOR
+#endif
+
+#ifdef NO_ISLAND_LOADING
+ #define ISLAND_LOADING_SELECTOR MENUACTION_CFO_SELECT, "FEM_ISL", { new CCFOSelect((int8*)&CMenuManager::m_PrefsIslandLoading, "IslandLoading", islandLoadingOpts, ARRAY_SIZE(islandLoadingOpts), true, IslandLoadingAfterChange) },
+#else
+ #define ISLAND_LOADING_SELECTOR
+#endif
+
+#ifdef EXTENDED_COLOURFILTER
+ #define POSTFX_SELECTORS \
+ MENUACTION_CFO_SELECT, "FED_CLF", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, "ColourFilter", filterNames, ARRAY_SIZE(filterNames), false, nil) }, \
+ MENUACTION_CFO_SELECT, "FED_MBL", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, "MotionBlur", off_on, 2, false, nil) },
+#else
+ #define POSTFX_SELECTORS
+#endif
+
+#ifdef EXTENDED_PIPELINES
+ #define PIPELINES_SELECTOR \
+ MENUACTION_CFO_SELECT, "FED_VPL", { new CCFOSelect((int8*)&CustomPipes::VehiclePipeSwitch, "VehiclePipeline", vehPipelineNames, ARRAY_SIZE(vehPipelineNames), false, nil) }, \
+ MENUACTION_CFO_SELECT, "FED_PRM", { new CCFOSelect((int8*)&CustomPipes::RimlightEnable, "NeoRimLight", off_on, 2, false, nil) }, \
+ MENUACTION_CFO_SELECT, "FED_WLM", { new CCFOSelect((int8*)&CustomPipes::LightmapEnable, "NeoLightMaps", off_on, 2, false, nil) }, \
+ MENUACTION_CFO_SELECT, "FED_RGL", { new CCFOSelect((int8*)&CustomPipes::GlossEnable, "NeoRoadGloss", off_on, 2, false, nil) },
+#else
+ #define PIPELINES_SELECTOR
+#endif
+
+#ifdef INVERT_LOOK_FOR_PAD
+ #define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, "FEC_IVP", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, "InvertPad", off_on, 2, false, nil) },
+#else
+ #define INVERT_PAD_SELECTOR
+#endif
+
+const char *filterNames[] = { "FEM_NON", "FEM_SIM", "FEM_NRM", "FEM_MOB" };
+const char *vehPipelineNames[] = { "FED_MFX", "FED_NEO" };
+const char *off_on[] = { "FEM_OFF", "FEM_ON" };
+
+void RestoreDefGraphics(int8 action) {
+ if (action != FEOPTION_ACTION_SELECT)
+ return;
+
+ #ifdef PS2_ALPHA_TEST
+ gPS2alphaTest = false;
+ #endif
+ #ifdef MULTISAMPLING
+ FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0;
+ #endif
+ #ifdef NO_ISLAND_LOADING
+ if (!FrontEndMenuManager.m_bGameNotLoaded) {
+ FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW;
+ CCollision::bAlreadyLoaded = false;
+ CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
+ CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
+ CStreaming::RemoveUnusedBuildings(CGame::currLevel);
+ CStreaming::RequestIslands(CGame::currLevel);
+ CStreaming::LoadAllRequestedModels(true);
+ } else
+ FrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW;
+ #endif
+ #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those
+ CMenuManager::m_PrefsFrameLimiter = true;
+ CMenuManager::m_PrefsVsyncDisp = true;
+ CMenuManager::m_PrefsVsync = true;
+ CMenuManager::m_PrefsUseWideScreen = false;
+ FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode;
+ #if GTA_VERSION >= GTA3_PC_11
+ if (_dwOperatingSystemVersion == OS_WIN98) {
+ CMBlur::BlurOn = false;
+ CMBlur::MotionBlurClose();
+ } else {
+ CMBlur::BlurOn = true;
+ CMBlur::MotionBlurOpen(Scene.camera);
+ }
+ #else
+ CMBlur::BlurOn = true;
+ #endif
+ FrontEndMenuManager.SaveSettings();
+ #endif
+}
+
+void RestoreDefDisplay(int8 action) {
+ if (action != FEOPTION_ACTION_SELECT)
+ return;
+
+ #ifdef CUTSCENE_BORDERS_SWITCH
+ CMenuManager::m_PrefsCutsceneBorders = true;
+ #endif
+ #ifdef FREE_CAM
+ TheCamera.bFreeCam = false;
+ #endif
+ #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those
+ CMenuManager::m_PrefsBrightness = 256;
+ CMenuManager::m_PrefsLOD = 1.2f;
+ CRenderer::ms_lodDistScale = 1.2f;
+ CMenuManager::m_PrefsShowSubtitles = true;
+ FrontEndMenuManager.SaveSettings();
+ #endif
+}
+
+#ifdef NO_ISLAND_LOADING
+const char *islandLoadingOpts[] = { "FEM_LOW", "FEM_MED", "FEM_HIG" };
+void IslandLoadingAfterChange(int8 before, int8 after) {
+ if (!FrontEndMenuManager.m_bGameNotLoaded) {
+ if (after > FrontEndMenuManager.ISLAND_LOADING_LOW) {
+ FrontEndMenuManager.m_PrefsIslandLoading = before; // calls below needs previous mode :shrug:
+
+ if (after == FrontEndMenuManager.ISLAND_LOADING_HIGH)
+ CStreaming::RemoveIslandsNotUsed(LEVEL_GENERIC);
+ if (before == FrontEndMenuManager.ISLAND_LOADING_LOW) {
+ if (CGame::currLevel != LEVEL_INDUSTRIAL)
+ CFileLoader::LoadCollisionFromDatFile(LEVEL_INDUSTRIAL);
+ if (CGame::currLevel != LEVEL_COMMERCIAL)
+ CFileLoader::LoadCollisionFromDatFile(LEVEL_COMMERCIAL);
+ if (CGame::currLevel != LEVEL_SUBURBAN)
+ CFileLoader::LoadCollisionFromDatFile(LEVEL_SUBURBAN);
+ CCollision::bAlreadyLoaded = true;
+ FrontEndMenuManager.m_PrefsIslandLoading = after;
+ CStreaming::RequestBigBuildings(CGame::currLevel);
+
+ } else if (before == FrontEndMenuManager.ISLAND_LOADING_HIGH) {
+ FrontEndMenuManager.m_PrefsIslandLoading = after;
+ CStreaming::RequestIslands(CGame::currLevel);
+ } else
+ FrontEndMenuManager.m_PrefsIslandLoading = after;
+
+ } else { // low
+ CCollision::bAlreadyLoaded = false;
+ CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
+ CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
+ CStreaming::RemoveUnusedBuildings(CGame::currLevel);
+ CStreaming::RequestIslands(CGame::currLevel);
+ }
+
+ CStreaming::LoadAllRequestedModels(true);
+ }
+
+ FrontEndMenuManager.SetHelperText(0);
+}
+#endif
+
+#ifdef MORE_LANGUAGES
+void LangPolSelect(int8 action)
+{
+ if (action == FEOPTION_ACTION_SELECT) {
+ FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_POLISH;
+ FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
+ FrontEndMenuManager.InitialiseChangedLanguageSettings();
+ FrontEndMenuManager.SaveSettings();
+ }
+}
+
+void LangRusSelect(int8 action)
+{
+ if (action == FEOPTION_ACTION_SELECT) {
+ FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_RUSSIAN;
+ FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
+ FrontEndMenuManager.InitialiseChangedLanguageSettings();
+ FrontEndMenuManager.SaveSettings();
+ }
+}
+
+void LangJapSelect(int8 action)
+{
+ if (action == FEOPTION_ACTION_SELECT) {
+ FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_JAPANESE;
+ FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
+ FrontEndMenuManager.InitialiseChangedLanguageSettings();
+ FrontEndMenuManager.SaveSettings();
+ }
+}
+#endif
+
+#ifndef MULTISAMPLING
+void GraphicsGoBack() {
+}
+#else
+void GraphicsGoBack() {
+ FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
+}
+
+void MultiSamplingButtonPress(int8 action) {
+ if (action == FEOPTION_ACTION_SELECT) {
+ if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
+ FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel;
+ _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode);
+ FrontEndMenuManager.SetHelperText(0);
+ FrontEndMenuManager.SaveSettings();
+ }
+ } else if (action == FEOPTION_ACTION_LEFT || action == FEOPTION_ACTION_RIGHT) {
+ if (FrontEndMenuManager.m_bGameNotLoaded) {
+ FrontEndMenuManager.m_nDisplayMSAALevel += (action == FEOPTION_ACTION_RIGHT ? 1 : -1);
+
+ int i = 0;
+ int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels();
+ while (maxAA != 1) {
+ i++;
+ maxAA >>= 1;
+ }
+
+ if (FrontEndMenuManager.m_nDisplayMSAALevel < 0)
+ FrontEndMenuManager.m_nDisplayMSAALevel = i;
+ else if (FrontEndMenuManager.m_nDisplayMSAALevel > i)
+ FrontEndMenuManager.m_nDisplayMSAALevel = 0;
+ }
+ } else if (action == FEOPTION_ACTION_FOCUSLOSS) {
+ if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
+ FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
+ FrontEndMenuManager.SetHelperText(3);
+ }
+ }
+}
+
+wchar* MultiSamplingDraw(bool *disabled, bool userHovering) {
+ static wchar unicodeTemp[64];
+ if (userHovering) {
+ if (FrontEndMenuManager.m_nDisplayMSAALevel == FrontEndMenuManager.m_nPrefsMSAALevel) {
+ if (FrontEndMenuManager.m_nHelperTextMsgId == 1) // Press enter to apply
+ FrontEndMenuManager.ResetHelperText();
+ } else {
+ FrontEndMenuManager.SetHelperText(1);
+ }
+ } else {
+ if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
+ FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
+ }
+ }
+
+ if (!FrontEndMenuManager.m_bGameNotLoaded)
+ *disabled = true;
+
+ switch (FrontEndMenuManager.m_nDisplayMSAALevel) {
+ case 0:
+ return TheText.Get("FEM_OFF");
+ default:
+ sprintf(gString, "%iX", 1 << (FrontEndMenuManager.m_nDisplayMSAALevel));
+ AsciiToUnicode(gString, unicodeTemp);
+ return unicodeTemp;
+ }
+}
+#endif
+
+#ifdef IMPROVED_VIDEOMODE
+const char* screenModes[] = { "FED_FLS", "FED_WND" };
+void ScreenModeAfterChange(int8 before, int8 after)
+{
+ _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); // apply same resolution
+ FrontEndMenuManager.SetHelperText(0);
+}
+
+#endif
+
+#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
+wchar selectedJoystickUnicode[128];
+
+wchar* DetectJoystickDraw(bool* disabled, bool userHovering) {
+ int numButtons;
+ int found = -1;
+ const char *joyname;
+ if (userHovering) {
+ for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) {
+ if ((joyname = glfwGetJoystickName(i))) {
+ const uint8* buttons = glfwGetJoystickButtons(i, &numButtons);
+ for (int j = 0; j < numButtons; j++) {
+ if (buttons[j]) {
+ found = i;
+ break;
+ }
+ }
+ if (found != -1)
+ break;
+ }
+ }
+
+ if (found != -1 && PSGLOBAL(joy1id) != found) {
+ if (PSGLOBAL(joy1id) != -1 && PSGLOBAL(joy1id) != found)
+ PSGLOBAL(joy2id) = PSGLOBAL(joy1id);
+ else
+ PSGLOBAL(joy2id) = -1;
+
+ strcpy(gSelectedJoystickName, joyname);
+ PSGLOBAL(joy1id) = found;
+ }
+ }
+ if (PSGLOBAL(joy1id) == -1)
+ AsciiToUnicode("Not found", selectedJoystickUnicode);
+ else
+ AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode);
+
+ return selectedJoystickUnicode;
+}
+#endif
+
+CMenuScreenCustom aScreens[MENUPAGES] = {
+ // MENUPAGE_NONE = 0
+ { "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil, },
+
+ // MENUPAGE_STATS = 1
+ { "FET_STA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_NEW_GAME = 2
+ { "FET_SGA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_CHANGEMENU, "FES_SNG", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD },
+ MENUACTION_POPULATESLOTS_CHANGEMENU, "GMLOAD", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT },
+ MENUACTION_POPULATESLOTS_CHANGEMENU, "FES_DGA", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_BRIEFS = 3
+ { "FET_BRE", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CONTROLLER_SETTINGS = 4
+ { "FET_CON", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_CTRLCONFIG, "FEC_CCF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
+ MENUACTION_CTRLDISPLAY, "FEC_CDP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
+ MENUACTION_CTRLVIBRATION, "FEC_VIB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_SOUND_SETTINGS = 5
+ { "FET_AUD", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_MUSICVOLUME, "FEA_MUS", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_SFXVOLUME, "FEA_SFX", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_AUDIOHW, "FEA_3DH", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_SPEAKERCONF, "FEA_SPK", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_DYNAMICACOUSTIC, "FET_DAM", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_RADIO, "FEA_RSS", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+#ifndef GRAPHICS_MENU_OPTIONS
+ // MENUPAGE_DISPLAY_SETTINGS = 6
+ { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_FRAMESYNC, "FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_FRAMELIMIT, "FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+#ifndef EXTENDED_COLOURFILTER
+ MENUACTION_TRAILS, "FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+#endif
+ MENUACTION_SUBTITLES, "FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_WIDESCREEN, "FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ VIDEOMODE_SELECTOR
+ MULTISAMPLING_SELECTOR
+ MENUACTION_CHANGEMENU, "FET_ADV", { nil, SAVESLOT_NONE, MENUPAGE_ADVANCED_DISPLAY_SETTINGS },
+ MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#else
+ // MENUPAGE_DISPLAY_SETTINGS = 6
+ { "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_BRIGHTNESS, "FED_BRI", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_DRAWDIST, "FEM_LOD", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ CUTSCENE_BORDERS_TOGGLE
+ FREE_CAM_TOGGLE
+ MENUACTION_SUBTITLES, "FED_SUB", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, RestoreDefDisplay) },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#endif
+
+ // MENUPAGE_LANGUAGE_SETTINGS = 7
+ { "FET_LAN", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_LANG_ENG, "FEL_ENG", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+ MENUACTION_LANG_FRE, "FEL_FRE", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+ MENUACTION_LANG_GER, "FEL_GER", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+ MENUACTION_LANG_ITA, "FEL_ITA", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+ MENUACTION_LANG_SPA, "FEL_SPA", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+#ifdef MORE_LANGUAGES
+ MENUACTION_CFO_DYNAMIC, "FEL_POL", { new CCFODynamic(nil, nil, nil, LangPolSelect) },
+ MENUACTION_CFO_DYNAMIC, "FEL_RUS", { new CCFODynamic(nil, nil, nil, LangRusSelect) },
+ MENUACTION_CFO_DYNAMIC, "FEL_JAP", { new CCFODynamic(nil, nil, nil, LangJapSelect) },
+#endif
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CHOOSE_LOAD_SLOT = 8
+ { "FET_LG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil,
+ MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+ MENUACTION_CHECKSAVE, "FEM_SL0", { nil, SAVESLOT_1, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL1", { nil, SAVESLOT_2, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL2", { nil, SAVESLOT_3, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL3", { nil, SAVESLOT_4, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL4", { nil, SAVESLOT_5, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL5", { nil, SAVESLOT_6, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL6", { nil, SAVESLOT_7, MENUPAGE_LOAD_SLOT_CONFIRM },
+ MENUACTION_CHECKSAVE, "FEM_SL7", { nil, SAVESLOT_8, MENUPAGE_LOAD_SLOT_CONFIRM },
+ },
+
+ // MENUPAGE_CHOOSE_DELETE_SLOT = 9
+ { "FET_DG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil,
+ MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+ MENUACTION_CHANGEMENU, "FEM_SL0", { nil, SAVESLOT_1, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL1", { nil, SAVESLOT_2, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL2", { nil, SAVESLOT_3, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL3", { nil, SAVESLOT_4, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL4", { nil, SAVESLOT_5, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL5", { nil, SAVESLOT_6, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL6", { nil, SAVESLOT_7, MENUPAGE_DELETE_SLOT_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL7", { nil, SAVESLOT_8, MENUPAGE_DELETE_SLOT_CONFIRM },
+ },
+
+ // MENUPAGE_NEW_GAME_RELOAD = 10
+ { "FET_NG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, nil, nil,
+ MENUACTION_LABEL, "FESZ_QR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+ MENUACTION_NEWGAME, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD },
+ },
+
+ // MENUPAGE_LOAD_SLOT_CONFIRM = 11
+ { "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, nil, nil,
+ MENUACTION_LABEL, "FESZ_QL", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT },
+ MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS },
+ },
+
+ // MENUPAGE_DELETE_SLOT_CONFIRM = 12
+ { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FESZ_QD", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT },
+ MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_DELETING },
+ },
+
+ // MENUPAGE_NO_MEMORY_CARD = 13
+ { "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ // hud adjustment page in mobile
+ },
+
+ // MENUPAGE_LOADING_IN_PROGRESS = 14
+ { "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FED_LDW", { nil, SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM },
+ },
+
+ // MENUPAGE_DELETING_IN_PROGRESS = 15
+ { "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FEDL_WR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_PS2_LOAD_FAILED = 16
+ { "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FES_LOE", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_DELETE_FAILED = 17
+ { "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FES_DEE", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT },
+ },
+
+ // MENUPAGE_DEBUG_MENU = 18
+ { "FED_DBG", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_RELOADIDE, "FED_RID", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_RELOADIPL, "FED_RIP", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SETDBGFLAG, "FED_DFL", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SWITCHBIGWHITEDEBUGLIGHT, "FED_DLS", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_PEDROADGROUPS, "FED_SPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CARROADGROUPS, "FED_SCR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_COLLISIONPOLYS, "FED_SCP", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_PARSEHEAP, "FED_PAH", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SHOWCULL, "FED_SCZ", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_DEBUGSTREAM, "FED_DSR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_MEMORY_CARD_DEBUG = 19
+ { "FEM_MCM", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_REGMEMCARD1, "FEM_RMC", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_TESTFORMATMEMCARD1, "FEM_TFM", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_TESTUNFORMATMEMCARD1, "FEM_TUM", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CREATEROOTDIR, "FEM_CRD", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CREATELOADICONS, "FEM_CLI", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_FILLWITHGUFF, "FEM_FFF", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SAVEONLYTHEGAME, "FEM_SOG", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SAVEGAME, "FEM_STG", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_SAVEGAMEUNDERGTA, "FEM_STS", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CREATECOPYPROTECTED, "FEM_CPD", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_MEMORY_CARD_TEST = 20
+ { "FEM_MC2", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_MAIN = 21
+ { "FET_MP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_PS2_SAVE_FAILED = 22
+ { "MCDNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_PS2_SAVE_FAILED_2 = 23
+ { "MCGNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // Unused in PC but anyway
+ // MENUPAGE_SAVE = 24
+#ifdef PS2_SAVE_DIALOG
+ { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_CHANGEMENU, "FESZ_SA", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
+ MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#else
+ { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FES_SCG", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_POPULATESLOTS_CHANGEMENU, "GMSAVE", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
+ MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#endif
+
+ // MENUPAGE_NO_MEMORY_CARD_2 = 25
+ { "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_CHANGEMENU, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CHOOSE_SAVE_SLOT = 26
+ { "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_RESUME_FROM_SAVEZONE, "FESZ_CA", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_SL1", { nil, SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL2", { nil, SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL3", { nil, SAVESLOT_3, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL4", { nil, SAVESLOT_4, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL5", { nil, SAVESLOT_5, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL6", { nil, SAVESLOT_6, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL7", { nil, SAVESLOT_7, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ MENUACTION_CHANGEMENU, "FEM_SL8", { nil, SAVESLOT_8, MENUPAGE_SAVE_OVERWRITE_CONFIRM },
+ },
+
+ // MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27
+ { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FESZ_QO", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS },
+ MENUACTION_CHANGEMENU, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
+ },
+
+ // MENUPAGE_MULTIPLAYER_MAP = 28
+ { "FET_MAP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_CONNECTION = 29
+ { "FET_CON", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_FIND_GAME = 30
+ { "FET_FG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_MODE = 31
+ { "FET_GT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_CREATE = 32
+ { "FET_HG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_MULTIPLAYER_START = 33
+ { "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_SKIN_SELECT_OLD = 34
+ { "FET_PS", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_CONTROLLER_PC = 35
+ { "FET_CTL", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_CTRLMETHOD, "FET_CME", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
+ MENUACTION_KEYBOARDCTRLS,"FET_RDK", { nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS },
+#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
+ MENUACTION_CHANGEMENU, "FEC_JOD", { nil, SAVESLOT_NONE, MENUPAGE_DETECT_JOYSTICK },
+#endif
+ MENUACTION_CHANGEMENU, "FET_AMS", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
+ MENUACTION_RESTOREDEF, "FET_DEF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CONTROLLER_PC_OLD1 = 36
+ { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+ MENUACTION_GETKEY, "FEC_PLB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_CWL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_CWR", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_LKT", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_PJP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_PSP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_TLF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_TRG", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_GETKEY, "FEC_CCM", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1 },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CONTROLLER_PC_OLD2 = 37
+ { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+
+ },
+
+ // MENUPAGE_CONTROLLER_PC_OLD3 = 38
+ { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+ MENUACTION_GETKEY, "FEC_LUP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
+ MENUACTION_GETKEY, "FEC_LDN", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
+ MENUACTION_GETKEY, "FEC_SMS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
+ MENUACTION_SHOWHEADBOB, "FEC_GSL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3 },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_CONTROLLER_PC_OLD4 = 39
+ { "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+
+ },
+
+ // MENUPAGE_CONTROLLER_DEBUG = 40
+ { "FEC_DBG", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+ MENUACTION_GETKEY, "FEC_TGD", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
+ MENUACTION_GETKEY, "FEC_TDO", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
+ MENUACTION_GETKEY, "FEC_TSS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
+ MENUACTION_GETKEY, "FEC_SMS", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_OPTIONS = 41
+ { "FET_OPT", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_CHANGEMENU, "FET_CTL", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
+ MENUACTION_LOADRADIO, "FET_AUD", { nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS },
+ MENUACTION_CHANGEMENU, "FET_DIS", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+#ifdef GRAPHICS_MENU_OPTIONS
+ MENUACTION_CHANGEMENU, "FET_GRA", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS },
+#endif
+ MENUACTION_CHANGEMENU, "FET_LAN", { nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS },
+ MENUACTION_PLAYERSETUP, "FET_PSU", { nil, SAVESLOT_NONE, MENUPAGE_SKIN_SELECT },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_EXIT = 42
+ { "FET_QG", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_LABEL, "FEQ_SRE", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_DONTCANCEL, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CANCELGAME, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_SAVING_IN_PROGRESS = 43
+ { "", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FES_WAR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_SAVE_SUCCESSFUL = 44
+ { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FES_SSC", { nil, SAVESLOT_LABEL, MENUPAGE_NONE },
+ MENUACTION_RESUME_FROM_SAVEZONE, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
+ },
+
+ // MENUPAGE_DELETING = 45
+ { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FED_DLW", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_DELETE_SUCCESS = 46
+ { "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,
+ MENUACTION_LABEL, "DEL_FNM", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT },
+ },
+
+ // MENUPAGE_SAVE_FAILED = 47
+ { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FEC_SVU", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEC_OKK", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT },
+ },
+
+ // MENUPAGE_LOAD_FAILED = 48
+ { "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FEC_SVU", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_LOAD_FAILED_2 = 49
+ { "FET_LG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,
+ MENUACTION_LABEL, "FEC_LUN", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT },
+ },
+
+ // MENUPAGE_FILTER_GAME = 50
+ { "FIL_FLT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+
+ },
+
+ // MENUPAGE_START_MENU = 51
+ { "FEM_MM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_CHANGEMENU, "FEN_STA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+ MENUACTION_CHANGEMENU, "FET_OPT", { nil, SAVESLOT_NONE, MENUPAGE_OPTIONS },
+ MENUACTION_CHANGEMENU, "FEM_QT", { nil, SAVESLOT_NONE, MENUPAGE_EXIT },
+ },
+
+ // MENUPAGE_PAUSE_MENU = 52
+ { "FET_PAU", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_RESUME, "FEM_RES", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEN_STA", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+#ifdef MENU_MAP
+ MENUACTION_CHANGEMENU, "FEG_MAP", { nil, SAVESLOT_NONE, MENUPAGE_MAP },
+#endif
+ MENUACTION_CHANGEMENU, "FEP_STA", { nil, SAVESLOT_NONE, MENUPAGE_STATS },
+ MENUACTION_CHANGEMENU, "FEP_BRI", { nil, SAVESLOT_NONE, MENUPAGE_BRIEFS },
+ MENUACTION_CHANGEMENU, "FET_OPT", { nil, SAVESLOT_NONE, MENUPAGE_OPTIONS },
+ MENUACTION_CHANGEMENU, "FEM_QT", { nil, SAVESLOT_NONE, MENUPAGE_EXIT },
+ },
+
+ // MENUPAGE_CHOOSE_MODE = 53
+ { "FEN_STA", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_CHANGEMENU, "FET_SP", { nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME },
+ MENUACTION_INITMP, "FET_MP", { nil, SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+
+ // MENUPAGE_SKIN_SELECT = 54
+ { "FET_PSU", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN },
+ },
+
+ // MENUPAGE_KEYBOARD_CONTROLS = 55
+ { "FET_STI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC },
+ },
+
+ // MENUPAGE_MOUSE_CONTROLS = 56
+ { "FET_MTI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
+ MENUACTION_MOUSESENS, "FEC_MSH", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
+ MENUACTION_INVVERT, "FEC_IVV", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
+ INVERT_PAD_SELECTOR
+ MENUACTION_MOUSESTEER, "FET_MST", { nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+ // MENUPAGE_MISSION_RETRY = 57
+#ifdef MISSION_REPLAY
+
+ { "M_FAIL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, nil, nil,
+ MENUACTION_LABEL, "FESZ_RM", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CHANGEMENU, "FEM_YES", { nil, SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS },
+ MENUACTION_REJECT_RETRY, "FEM_NO", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#else
+ { "", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ // mission failed, wanna restart page in mobile
+ },
+#endif
+
+#ifdef MENU_MAP
+ // MENUPAGE_MAP
+ { "FEG_MAP", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+ MENUACTION_UNK110, "", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, // to prevent cross/enter to go back
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#endif
+
+#ifdef GRAPHICS_MENU_OPTIONS
+ // MENUPAGE_GRAPHICS_SETTINGS
+ { "FET_GRA", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS,
+ new CCustomScreenLayout({MENUSPRITE_MAINMENU, 50, 0, 20, FONT_HEADING, FESCREEN_LEFT_ALIGN, true, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), GraphicsGoBack,
+
+ MENUACTION_SCREENRES, "FED_RES", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS },
+ MENUACTION_WIDESCREEN, "FED_WIS", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS },
+ VIDEOMODE_SELECTOR
+ MENUACTION_FRAMESYNC, "FEM_VSC", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MENUACTION_FRAMELIMIT, "FEM_FRM", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+ MULTISAMPLING_SELECTOR
+#ifdef EXTENDED_COLOURFILTER
+ POSTFX_SELECTORS
+#else
+ MENUACTION_TRAILS, "FED_TRA", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS },
+#endif
+#ifdef EXTENDED_PIPELINES
+ PIPELINES_SELECTOR
+#endif
+ ISLAND_LOADING_SELECTOR
+ DUALPASS_SELECTOR
+ MENUACTION_CFO_DYNAMIC, "FET_DEF", { new CCFODynamic(nil, nil, nil, RestoreDefGraphics) },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#else
+ // MENUPAGE_ADVANCED_DISPLAY_SETTINGS
+ { "FET_ADV", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS,
+ new CCustomScreenLayout({MENUSPRITE_MAINMENU, 50, 0, 20, FONT_HEADING, FESCREEN_LEFT_ALIGN, true, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), nil,
+
+ ISLAND_LOADING_SELECTOR
+ DUALPASS_SELECTOR
+ CUTSCENE_BORDERS_TOGGLE
+ FREE_CAM_TOGGLE
+#ifdef EXTENDED_COLOURFILTER
+ POSTFX_SELECTORS
+#endif
+#ifdef EXTENDED_PIPELINES
+ PIPELINES_SELECTOR
+#endif
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#endif
+
+#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
+ // MENUPAGE_DETECT_JOYSTICK
+ { "FEC_JOD", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC,
+ new CCustomScreenLayout({MENUSPRITE_MAINMENU, 40, 60, 20, FONT_BANK, FESCREEN_LEFT_ALIGN, false, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE}), nil,
+
+ MENUACTION_LABEL, "FEC_JPR", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ MENUACTION_CFO_DYNAMIC, "FEC_JDE", { new CCFODynamic(nil, nil, DetectJoystickDraw, nil) },
+ MENUACTION_CHANGEMENU, "FEDS_TB", { nil, SAVESLOT_NONE, MENUPAGE_NONE },
+ },
+#endif
+
+ // MENUPAGE_UNK
+ { "", MENUPAGE_NONE, MENUPAGE_NONE, nil, nil,
+
+ },
+
+};
+
+#endif
+#endif
diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp
index 0e2f06a6..b971f3ec 100644
--- a/src/core/Pad.cpp
+++ b/src/core/Pad.cpp
@@ -59,6 +59,9 @@ bool CPad::bDisplayNoControllerMessage;
bool CPad::bObsoleteControllerMessage;
bool CPad::bOldDisplayNoControllerMessage;
bool CPad::m_bMapPadOneToPadTwo;
+#ifdef INVERT_LOOK_FOR_PAD
+bool CPad::bInvertLook4Pad;
+#endif
#ifdef GTA_PS2
unsigned char act_direct[6];
unsigned char act_align[6];
@@ -934,7 +937,7 @@ void CPad::AddToPCCheatString(char c)
if ( !_CHEATCMP("GNIROOOOOB") )
SlowTimeCheat();
-#ifndef GTA3_1_1_PATCH
+#if GTA_VERSION < GTA3_PC_11
// "TURTOISE"
if ( !_CHEATCMP("ESIOTRUT") )
ArmourCheat();
@@ -1281,7 +1284,7 @@ void CPad::Update(int16 pad)
{
if ( ShakeDur )
{
- ShakeDur = Max(ShakeDur - CTimer::GetTimeStepInMilliseconds(), 0);
+ ShakeDur = Max(ShakeDur - (int32)CTimer::GetTimeStepInMilliseconds(), 0);
if ( ShakeDur == 0 )
{
@@ -2534,10 +2537,20 @@ int16 CPad::SniperModeLookLeftRight(void)
int16 CPad::SniperModeLookUpDown(void)
{
int16 axis = NewState.LeftStickY;
+ int16 dpad;
#ifdef FIX_BUGS
axis = -axis;
#endif
- int16 dpad = (NewState.DPadUp - NewState.DPadDown) / 2;
+#ifndef INVERT_LOOK_FOR_PAD
+ dpad = (NewState.DPadUp - NewState.DPadDown) / 2;
+#else
+ if (CPad::bInvertLook4Pad) {
+ axis = -axis;
+ dpad = (NewState.DPadDown - NewState.DPadUp) / 2;
+ } else {
+ dpad = (NewState.DPadUp - NewState.DPadDown) / 2;
+ }
+#endif
if ( Abs(axis) > Abs(dpad) )
return axis;
@@ -2567,6 +2580,10 @@ int16 CPad::LookAroundUpDown(void)
#ifdef FIX_BUGS
axis = -axis;
#endif
+#ifdef INVERT_LOOK_FOR_PAD
+ if (CPad::bInvertLook4Pad)
+ axis = -axis;
+#endif
if ( Abs(axis) > 85 && !GetLookBehindForPed() )
return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) )
@@ -2593,7 +2610,7 @@ void CPad::PrintErrorMessage(void)
CFont::SetScale(0.85f, 1.0f);
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
- CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));
+ CFont::SetCentreSize(SCREEN_SCALE_X(SCREEN_WIDTH - 20));
CFont::SetCentreOn();
CFont::SetPropOn();
CFont::SetColor(CRGBA(255, 255, 200, 200));
@@ -2610,7 +2627,7 @@ void CPad::PrintErrorMessage(void)
CFont::SetScale(0.85f, 1.0f);
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
- CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));
+ CFont::SetCentreSize(SCREEN_SCALE_X(SCREEN_WIDTH - 20));
CFont::SetCentreOn();
CFont::SetPropOn();
CFont::SetColor(CRGBA(255, 255, 200, 200));
diff --git a/src/core/Pad.h b/src/core/Pad.h
index 8c5d7ba3..20a676ef 100644
--- a/src/core/Pad.h
+++ b/src/core/Pad.h
@@ -170,6 +170,9 @@ public:
static bool bObsoleteControllerMessage;
static bool bOldDisplayNoControllerMessage;
static bool m_bMapPadOneToPadTwo;
+#ifdef INVERT_LOOK_FOR_PAD
+ static bool bInvertLook4Pad;
+#endif
static CKeyboardState OldKeyState;
static CKeyboardState NewKeyState;
diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp
index bd0814d0..79841c14 100644
--- a/src/core/Pools.cpp
+++ b/src/core/Pools.cpp
@@ -12,6 +12,7 @@
#include "Streaming.h"
#include "Wanted.h"
#include "World.h"
+#include "MemoryHeap.h"
CCPtrNodePool *CPools::ms_pPtrNodePool;
CEntryInfoNodePool *CPools::ms_pEntryInfoNodePool;
@@ -23,18 +24,36 @@ CObjectPool *CPools::ms_pObjectPool;
CDummyPool *CPools::ms_pDummyPool;
CAudioScriptObjectPool *CPools::ms_pAudioScriptObjectPool;
+#ifdef GTA_PS2 // or USE_CUSTOM_ALLOCATOR
+#define CHECKMEM(msg) CMemCheck::AllocateMemCheckBlock(msg)
+#else
+#define CHECKMEM(msg)
+#endif
+
void
CPools::Initialise(void)
{
+ PUSH_MEMID(MEMID_POOLS);
+ CHECKMEM("before pools");
ms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES);
+ CHECKMEM("after CPtrNodePool");
ms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS);
+ CHECKMEM("after CEntryInfoNodePool");
ms_pPedPool = new CPedPool(NUMPEDS);
+ CHECKMEM("after CPedPool");
ms_pVehiclePool = new CVehiclePool(NUMVEHICLES);
+ CHECKMEM("after CVehiclePool");
ms_pBuildingPool = new CBuildingPool(NUMBUILDINGS);
+ CHECKMEM("after CBuildingPool");
ms_pTreadablePool = new CTreadablePool(NUMTREADABLES);
+ CHECKMEM("after CTreadablePool");
ms_pObjectPool = new CObjectPool(NUMOBJECTS);
+ CHECKMEM("after CObjectPool");
ms_pDummyPool = new CDummyPool(NUMDUMMIES);
+ CHECKMEM("after CDummyPool");
ms_pAudioScriptObjectPool = new CAudioScriptObjectPool(NUMAUDIOSCRIPTOBJECTS);
+ CHECKMEM("after pools");
+ POP_MEMID();
}
void
diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp
index 3c5689fd..03b49fd6 100644
--- a/src/core/Streaming.cpp
+++ b/src/core/Streaming.cpp
@@ -33,6 +33,9 @@
#endif
#include "main.h"
#include "Frontend.h"
+#include "Font.h"
+#include "MemoryMgr.h"
+#include "MemoryHeap.h"
bool CStreaming::ms_disableStreaming;
bool CStreaming::ms_bLoadingBigModel;
@@ -289,6 +292,11 @@ CStreaming::Shutdown(void)
}
}
+#ifndef MASTER
+uint64 timeProcessingTXD;
+uint64 timeProcessingDFF;
+#endif
+
void
CStreaming::Update(void)
{
@@ -296,6 +304,11 @@ CStreaming::Update(void)
CStreamingInfo *si, *prev;
bool requestedSubway = false;
+#ifndef MASTER
+ timeProcessingTXD = 0;
+ timeProcessingDFF = 0;
+#endif
+
UpdateMemoryUsed();
if(ms_channelError != -1){
@@ -331,6 +344,14 @@ CStreaming::Update(void)
LoadRequestedModels();
+#ifndef MASTER
+ if (CPad::GetPad(1)->GetLeftShoulder1JustDown() && CPad::GetPad(1)->GetRightShoulder1() && CPad::GetPad(1)->GetRightShoulder2())
+ PrintStreamingBufferState();
+
+ // TODO: PrintRequestList
+ //if (CPad::GetPad(1)->GetLeftShoulder2JustDown() && CPad::GetPad(1)->GetRightShoulder1() && CPad::GetPad(1)->GetRightShoulder2())
+ // PrintRequestList();
+#endif
for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){
prev = si->m_prev;
@@ -390,6 +411,7 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
assert(sizeof(direntry) == 32);
while(CFileMgr::Read(fd, (char*)&direntry, sizeof(direntry))){
dot = strchr(direntry.name, '.');
+ assert(dot);
if(dot) *dot = '\0';
if(direntry.size > (uint32)ms_streamingBufferSize)
ms_streamingBufferSize = direntry.size;
@@ -436,6 +458,35 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
CFileMgr::CloseFile(fd);
}
+#ifdef USE_CUSTOM_ALLOCATOR
+RpAtomic*
+RegisterAtomicMemPtrsCB(RpAtomic *atomic, void *data)
+{
+#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31
+ // not quite sure what's going on here:
+ // gta3's RW 3.1 allocates separate memory for geometry data of RpGeometry.
+ // Is that a R* change? rpDefaultGeometryInstance also depends on it
+ RpGeometry *geo = RpAtomicGetGeometry(atomic);
+ if(geo->triangles)
+ REGISTER_MEMPTR(&geo->triangles);
+ if(geo->matList.materials)
+ REGISTER_MEMPTR(&geo->matList.materials);
+ if(geo->preLitLum)
+ REGISTER_MEMPTR(&geo->preLitLum);
+ if(geo->texCoords[0])
+ REGISTER_MEMPTR(&geo->texCoords[0]);
+ if(geo->texCoords[1])
+ REGISTER_MEMPTR(&geo->texCoords[1]);
+#else
+ // normally RpGeometry is allocated in one block (excluding morph targets)
+ // so we don't really have allocated pointers in the struct.
+ // NB: in librw we actually do it in two allocations (geometry itself and data)
+ // so we could conceivably come up with something here
+#endif
+ return atomic;
+}
+#endif
+
bool
CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
{
@@ -469,10 +520,14 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
// Set Txd to use
CTxdStore::AddRef(mi->GetTxdSlot());
- CTxdStore::SetCurrentTxd(mi->GetTxdSlot());
+ PUSH_MEMID(MEMID_STREAM_MODELS);
+ CTxdStore::SetCurrentTxd(mi->GetTxdSlot());
if(mi->IsSimple()){
success = CFileLoader::LoadAtomicFile(stream, streamId);
+#ifdef USE_CUSTOM_ALLOCATOR
+ RegisterAtomicMemPtrsCB(((CSimpleModelInfo*)mi)->m_atomics[0], nil);
+#endif
} else if (mi->GetModelType() == MITYPE_VEHICLE) {
// load vehicles in two parts
CModelInfo::GetModelInfo(streamId)->AddRef();
@@ -481,7 +536,12 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_STARTED;
}else{
success = CFileLoader::LoadClumpFile(stream, streamId);
+#ifdef USE_CUSTOM_ALLOCATOR
+ if(success)
+ RpClumpForAllAtomics((RpClump*)mi->GetRwObject(), RegisterAtomicMemPtrsCB, nil);
+#endif
}
+ POP_MEMID();
UpdateMemoryUsed();
// Txd no longer needed unless we only read part of the file
@@ -505,12 +565,14 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
return false;
}
+ PUSH_MEMID(MEMID_STREAM_TEXUTRES);
if(ms_bLoadingBigModel || cdsize > 200){
success = CTxdStore::StartLoadTxd(streamId - STREAM_OFFSET_TXD, stream);
if(success)
ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_STARTED;
}else
success = CTxdStore::LoadTxd(streamId - STREAM_OFFSET_TXD, stream);
+ POP_MEMID();
UpdateMemoryUsed();
if(!success){
@@ -560,7 +622,9 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
// Mark objects as loaded
if(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED){
ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;
+#ifndef USE_CUSTOM_ALLOCATOR
ms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE;
+#endif
}
endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();
@@ -600,31 +664,42 @@ CStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId)
if(streamId < STREAM_OFFSET_TXD){
// Model
mi = CModelInfo::GetModelInfo(streamId);
+ PUSH_MEMID(MEMID_STREAM_MODELS);
CTxdStore::SetCurrentTxd(mi->GetTxdSlot());
success = CFileLoader::FinishLoadClumpFile(stream, streamId);
- if(success)
+ if(success){
+#ifdef USE_CUSTOM_ALLOCATOR
+ RpClumpForAllAtomics((RpClump*)mi->GetRwObject(), RegisterAtomicMemPtrsCB, nil);
+#endif
success = AddToLoadedVehiclesList(streamId);
+ }
+ POP_MEMID();
mi->RemoveRef();
CTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot());
}else{
// Txd
CTxdStore::AddRef(streamId - STREAM_OFFSET_TXD);
+ PUSH_MEMID(MEMID_STREAM_TEXUTRES);
success = CTxdStore::FinishLoadTxd(streamId - STREAM_OFFSET_TXD, stream);
+ POP_MEMID();
CTxdStore::RemoveRefWithoutDelete(streamId - STREAM_OFFSET_TXD);
}
RwStreamClose(stream, &mem);
- ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;
+
+ ms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED; // only done if success on PS2
+#ifndef USE_CUSTOM_ALLOCATOR
ms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE;
+#endif
if(!success){
RemoveModel(streamId);
ReRequestModel(streamId);
- UpdateMemoryUsed();
+ UpdateMemoryUsed(); // directly after pop on PS2
return false;
}
- UpdateMemoryUsed();
+ UpdateMemoryUsed(); // directly after pop on PS2
endTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();
timeDiff = endTime - startTime;
@@ -741,7 +816,9 @@ CStreaming::RequestBigBuildings(eLevelName level)
b = CPools::GetBuildingPool()->GetSlot(i);
if(b && b->bIsBIGBuilding
#ifdef NO_ISLAND_LOADING
- && ((CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) || (b->m_level == level))
+ && (((CMenuManager::m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) && (b != pIslandLODindustEntity) && (b != pIslandLODcomIndEntity) &&
+ (b != pIslandLODcomSubEntity) && (b != pIslandLODsubIndEntity) && (b != pIslandLODsubComEntity)
+ ) || (b->m_level == level))
#else
&& b->m_level == level
#endif
@@ -855,7 +932,11 @@ CStreaming::RemoveModel(int32 id)
CModelInfo::GetModelInfo(id)->DeleteRwObject();
else
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
+#ifdef USE_CUSTOM_ALLOCATOR
+ UpdateMemoryUsed();
+#else
ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE;
+#endif
}
if(ms_aInfoForModel[id].m_next){
@@ -877,6 +958,9 @@ CStreaming::RemoveModel(int32 id)
RpClumpGtaCancelStream();
else
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
+#ifdef USE_CUSTOM_ALLOCATOR
+ UpdateMemoryUsed();
+#endif
}
ms_aInfoForModel[id].m_loadState = STREAMSTATE_NOTLOADED;
@@ -2041,19 +2125,25 @@ CStreaming::FlushRequestList(void)
void
CStreaming::ImGonnaUseStreamingMemory(void)
{
- // empty
+ PUSH_MEMID(MEMID_STREAM);
}
void
CStreaming::IHaveUsedStreamingMemory(void)
{
+ POP_MEMID();
UpdateMemoryUsed();
}
void
CStreaming::UpdateMemoryUsed(void)
{
- // empty
+#ifdef USE_CUSTOM_ALLOCATOR
+ ms_memoryUsed =
+ gMainHeap.GetMemoryUsed(MEMID_STREAM) +
+ gMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS) +
+ gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES);
+#endif
}
#define STREAM_DIST 80.0f
@@ -2633,3 +2723,71 @@ CStreaming::UpdateForAnimViewer(void)
CStreaming::RetryLoadFile(CStreaming::ms_channelError);
}
}
+
+
+void
+CStreaming::PrintStreamingBufferState()
+{
+ char str[128];
+ wchar wstr[128];
+ uint32 offset, size;
+
+ CTimer::Stop();
+ int i = 0;
+ while (i < NUMSTREAMINFO) {
+ while (true) {
+ int j = 0;
+ DoRWStuffStartOfFrame(50, 50, 50, 0, 0, 0, 255);
+ CPad::UpdatePads();
+ CSprite2d::InitPerFrame();
+ CFont::InitPerFrame();
+ DefinedState();
+
+ CRect unusedRect(0, 0, RsGlobal.maximumWidth, RsGlobal.maximumHeight);
+ CRGBA unusedColor(255, 255, 255, 255);
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::SetBackgroundOff();
+ CFont::SetWrapx(DEFAULT_SCREEN_WIDTH);
+ CFont::SetScale(0.5f, 0.75f);
+ CFont::SetCentreOff();
+ CFont::SetCentreSize(DEFAULT_SCREEN_WIDTH);
+ CFont::SetJustifyOff();
+ CFont::SetColor(CRGBA(200, 200, 200, 200));
+ CFont::SetBackGroundOnlyTextOff();
+ int modelIndex = i;
+ if (modelIndex < NUMSTREAMINFO) {
+ int y = 24;
+ for ( ; j < 34 && modelIndex < NUMSTREAMINFO; modelIndex++) {
+ CStreamingInfo *streamingInfo = &ms_aInfoForModel[modelIndex];
+ CBaseModelInfo *modelInfo = CModelInfo::GetModelInfo(modelIndex);
+ if (streamingInfo->m_loadState != STREAMSTATE_LOADED || !streamingInfo->GetCdPosnAndSize(offset, size))
+ continue;
+
+ if (modelIndex >= STREAM_OFFSET_TXD)
+ sprintf(str, "txd %s, refs %d, size %dK, flags 0x%x", CTxdStore::GetTxdName(modelIndex - STREAM_OFFSET_TXD),
+ CTxdStore::GetNumRefs(modelIndex - STREAM_OFFSET_TXD), 2 * size, streamingInfo->m_flags);
+ else
+ sprintf(str, "model %d,%s, refs%d, size%dK, flags%x", modelIndex, modelInfo->GetName(), modelInfo->GetNumRefs(), 2 * size,
+ streamingInfo->m_flags);
+ AsciiToUnicode(str, wstr);
+ CFont::PrintString(24.0f, y, wstr);
+ y += 12;
+ j++;
+ }
+ }
+
+ if (CPad::GetPad(1)->GetCrossJustDown())
+ i = modelIndex;
+
+ if (!CPad::GetPad(1)->GetTriangleJustDown())
+ break;
+
+ i = 0;
+ CFont::DrawFonts();
+ DoRWStuffEndOfFrame();
+ }
+ CFont::DrawFonts();
+ DoRWStuffEndOfFrame();
+ }
+ CTimer::Update();
+} \ No newline at end of file
diff --git a/src/core/Streaming.h b/src/core/Streaming.h
index 0b2ff124..ee9183a5 100644
--- a/src/core/Streaming.h
+++ b/src/core/Streaming.h
@@ -188,4 +188,6 @@ public:
static void MemoryCardLoad(uint8 *buffer, uint32 length);
static void UpdateForAnimViewer(void);
+
+ static void PrintStreamingBufferState();
};
diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp
deleted file mode 100644
index f6796909..00000000
--- a/src/core/TempColModels.cpp
+++ /dev/null
@@ -1,297 +0,0 @@
-#include "common.h"
-
-#include "TempColModels.h"
-#include "SurfaceTable.h"
-
-CColModel CTempColModels::ms_colModelPed1;
-CColModel CTempColModels::ms_colModelPed2;
-CColModel CTempColModels::ms_colModelBBox;
-CColModel CTempColModels::ms_colModelBumper1;
-CColModel CTempColModels::ms_colModelWheel1;
-CColModel CTempColModels::ms_colModelPanel1;
-CColModel CTempColModels::ms_colModelBodyPart2;
-CColModel CTempColModels::ms_colModelBodyPart1;
-CColModel CTempColModels::ms_colModelCutObj[5];
-CColModel CTempColModels::ms_colModelPedGroundHit;
-CColModel CTempColModels::ms_colModelBoot1;
-CColModel CTempColModels::ms_colModelDoor1;
-CColModel CTempColModels::ms_colModelBonnet1;
-
-
-CColSphere s_aPedSpheres[3];
-CColSphere s_aPed2Spheres[3];
-CColSphere s_aPedGSpheres[4];
-#ifdef FIX_BUGS
-CColSphere s_aDoorSpheres[3];
-#else
-CColSphere s_aDoorSpheres[4];
-#endif
-CColSphere s_aBumperSpheres[4];
-CColSphere s_aPanelSpheres[4];
-CColSphere s_aBonnetSpheres[4];
-CColSphere s_aBootSpheres[4];
-CColSphere s_aWheelSpheres[2];
-CColSphere s_aBodyPartSpheres1[2];
-CColSphere s_aBodyPartSpheres2[2];
-
-void
-CTempColModels::Initialise(void)
-{
-#define SET_COLMODEL_SPHERES(colmodel, sphrs)\
- colmodel.numSpheres = ARRAY_SIZE(sphrs);\
- colmodel.spheres = sphrs;\
- colmodel.level = LEVEL_GENERIC;\
- colmodel.ownsCollisionVolumes = false;\
-
- int i;
-
- ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0);
- ms_colModelBBox.level = LEVEL_GENERIC;
-
- for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) {
- ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0);
- ms_colModelCutObj[i].level = LEVEL_GENERIC;
- }
-
- // Ped Spheres
-
- for (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++)
- s_aPedSpheres[i].radius = 0.35f;
-
- s_aPedSpheres[0].center = CVector(0.0f, 0.0f, -0.25f);
- s_aPedSpheres[1].center = CVector(0.0f, 0.0f, 0.15f);
- s_aPedSpheres[2].center = CVector(0.0f, 0.0f, 0.55f);
-
-#ifdef FIX_BUGS
- for (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++) {
-#else
- for (i = 0; i < ARRAY_SIZE(s_aPedGSpheres); i++) {
-#endif
- s_aPedSpheres[i].surface = SURFACE_PED;
- s_aPedSpheres[i].piece = 0;
- }
-
- ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f), SURFACE_DEFAULT, 0);
- SET_COLMODEL_SPHERES(ms_colModelPed1, s_aPedSpheres);
-
- // Ped 2 Spheres
-
- s_aPed2Spheres[0].radius = 0.3f;
- s_aPed2Spheres[1].radius = 0.4f;
- s_aPed2Spheres[2].radius = 0.3f;
-
- s_aPed2Spheres[0].center = CVector(0.0f, 0.35f, -0.9f);
- s_aPed2Spheres[1].center = CVector(0.0f, 0.0f, -0.9f);
- s_aPed2Spheres[2].center = CVector(0.0f, -0.35f, -0.9f);
-
- for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) {
- s_aPed2Spheres[i].surface = SURFACE_PED;
- s_aPed2Spheres[i].piece = 0;
- }
-
- ms_colModelPed2.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelPed2.boundingBox.Set(CVector(-0.7f, -0.7f, -1.2f), CVector(0.7f, 0.7f, 0.0f), SURFACE_DEFAULT, 0);
-
- SET_COLMODEL_SPHERES(ms_colModelPed2, s_aPed2Spheres);
-
- // Ped ground collision
-
- s_aPedGSpheres[0].radius = 0.35f;
- s_aPedGSpheres[1].radius = 0.35f;
- s_aPedGSpheres[2].radius = 0.35f;
- s_aPedGSpheres[3].radius = 0.3f;
-
- s_aPedGSpheres[0].center = CVector(0.0f, -0.4f, -0.9f);
- s_aPedGSpheres[1].center = CVector(0.0f, -0.1f, -0.9f);
- s_aPedGSpheres[2].center = CVector(0.0f, 0.25f, -0.9f);
- s_aPedGSpheres[3].center = CVector(0.0f, 0.65f, -0.9f);
-
- s_aPedGSpheres[0].surface = SURFACE_PED;
- s_aPedGSpheres[1].surface = SURFACE_PED;
- s_aPedGSpheres[2].surface = SURFACE_PED;
- s_aPedGSpheres[3].surface = SURFACE_PED;
- s_aPedGSpheres[0].piece = 4;
- s_aPedGSpheres[1].piece = 1;
- s_aPedGSpheres[2].piece = 0;
- s_aPedGSpheres[3].piece = 6;
-
- ms_colModelPedGroundHit.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelPedGroundHit.boundingBox.Set(CVector(-0.4f, -1.0f, -1.25f), CVector(0.4f, 1.2f, -0.5f), SURFACE_DEFAULT, 0);
-
- SET_COLMODEL_SPHERES(ms_colModelPedGroundHit, s_aPedGSpheres);
-
- // Door Spheres
-
- s_aDoorSpheres[0].radius = 0.15f;
- s_aDoorSpheres[1].radius = 0.15f;
- s_aDoorSpheres[2].radius = 0.25f;
-
- s_aDoorSpheres[0].center = CVector(0.0f, -0.25f, -0.35f);
- s_aDoorSpheres[1].center = CVector(0.0f, -0.95f, -0.35f);
- s_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f);
-
-#ifdef FIX_BUGS
- for (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) {
-#else
- for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) {
-#endif
- s_aDoorSpheres[i].surface = SURFACE_CAR_PANEL;
- s_aDoorSpheres[i].piece = 0;
- }
-
- ms_colModelDoor1.boundingSphere.Set(1.5f, CVector(0.0f, -0.6f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelDoor1.boundingBox.Set(CVector(-0.3f, 0.0f, -0.6f), CVector(0.3f, -1.2f, 0.6f), SURFACE_DEFAULT, 0);
-
- SET_COLMODEL_SPHERES(ms_colModelDoor1, s_aDoorSpheres);
-
- // Bumper Spheres
-
- for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++)
- s_aBumperSpheres[i].radius = 0.15f;
-
- s_aBumperSpheres[0].center = CVector(0.85f, -0.05f, 0.0f);
- s_aBumperSpheres[1].center = CVector(0.4f, 0.05f, 0.0f);
- s_aBumperSpheres[2].center = CVector(-0.4f, 0.05f, 0.0f);
- s_aBumperSpheres[3].center = CVector(-0.85f, -0.05f, 0.0f);
-
- for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) {
- s_aBumperSpheres[i].surface = SURFACE_CAR_PANEL;
- s_aBumperSpheres[i].piece = 0;
- }
-
- ms_colModelBumper1.boundingSphere.Set(2.2f, CVector(0.0f, -0.6f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBumper1.boundingBox.Set(CVector(-1.2f, -0.3f, -0.2f), CVector(1.2f, 0.3f, 0.2f), SURFACE_DEFAULT, 0);
-
- SET_COLMODEL_SPHERES(ms_colModelBumper1, s_aBumperSpheres);
-
- // Panel Spheres
-
- for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++)
- s_aPanelSpheres[i].radius = 0.15f;
-
- s_aPanelSpheres[0].center = CVector(0.15f, 0.45f, 0.0f);
- s_aPanelSpheres[1].center = CVector(0.15f, -0.45f, 0.0f);
- s_aPanelSpheres[2].center = CVector(-0.15f, -0.45f, 0.0f);
- s_aPanelSpheres[3].center = CVector(-0.15f, 0.45f, 0.0f);
-
- for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) {
- s_aPanelSpheres[i].surface = SURFACE_CAR_PANEL;
- s_aPanelSpheres[i].piece = 0;
- }
-
- ms_colModelPanel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelPanel1.boundingBox.Set(CVector(-0.3f, -0.6f, -0.15f), CVector(0.3f, 0.6f, 0.15f), SURFACE_DEFAULT, 0);
-
- SET_COLMODEL_SPHERES(ms_colModelPanel1, s_aPanelSpheres);
-
- // Bonnet Spheres
-
- for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++)
- s_aBonnetSpheres[i].radius = 0.2f;
-
- s_aBonnetSpheres[0].center = CVector(-0.4f, 0.1f, 0.0f);
- s_aBonnetSpheres[1].center = CVector(-0.4f, 0.9f, 0.0f);
- s_aBonnetSpheres[2].center = CVector(0.4f, 0.1f, 0.0f);
- s_aBonnetSpheres[3].center = CVector(0.4f, 0.9f, 0.0f);
-
- for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) {
- s_aBonnetSpheres[i].surface = SURFACE_CAR_PANEL;
- s_aBonnetSpheres[i].piece = 0;
- }
-
- ms_colModelBonnet1.boundingSphere.Set(1.7f, CVector(0.0f, 0.5f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBonnet1.boundingBox.Set(CVector(-0.7f, -0.2f, -0.3f), CVector(0.7f, 1.2f, 0.3f), SURFACE_DEFAULT, 0);
-
- SET_COLMODEL_SPHERES(ms_colModelBonnet1, s_aBonnetSpheres);
-
- // Boot Spheres
-
- for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++)
- s_aBootSpheres[i].radius = 0.2f;
-
- s_aBootSpheres[0].center = CVector(-0.4f, -0.1f, 0.0f);
- s_aBootSpheres[1].center = CVector(-0.4f, -0.6f, 0.0f);
- s_aBootSpheres[2].center = CVector(0.4f, -0.1f, 0.0f);
- s_aBootSpheres[3].center = CVector(0.4f, -0.6f, 0.0f);
-
- for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {
- s_aBootSpheres[i].surface = SURFACE_CAR_PANEL;
- s_aBootSpheres[i].piece = 0;
- }
-
- ms_colModelBoot1.boundingSphere.Set(1.4f, CVector(0.0f, -0.4f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBoot1.boundingBox.Set(CVector(-0.7f, -0.9f, -0.3f), CVector(0.7f, 0.2f, 0.3f), SURFACE_DEFAULT, 0);
-
- SET_COLMODEL_SPHERES(ms_colModelBoot1, s_aBootSpheres);
-
- // Wheel Spheres
-
- s_aWheelSpheres[0].radius = 0.35f;
- s_aWheelSpheres[1].radius = 0.35f;
-
- s_aWheelSpheres[0].center = CVector(-0.3f, 0.0f, 0.0f);
- s_aWheelSpheres[1].center = CVector(0.3f, 0.0f, 0.0f);
-
-#ifdef FIX_BUGS
- for (i = 0; i < ARRAY_SIZE(s_aWheelSpheres); i++) {
-#else
- for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {
-#endif
- s_aWheelSpheres[i].surface = SURFACE_WHEELBASE;
- s_aWheelSpheres[i].piece = 0;
- }
-
- ms_colModelWheel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelWheel1.boundingBox.Set(CVector(-0.7f, -0.4f, -0.4f), CVector(0.7f, 0.4f, 0.4f), SURFACE_DEFAULT, 0);
-
- SET_COLMODEL_SPHERES(ms_colModelWheel1, s_aWheelSpheres);
-
- // Body Part Spheres 1
-
- s_aBodyPartSpheres1[0].radius = 0.2f;
- s_aBodyPartSpheres1[1].radius = 0.2f;
-
- s_aBodyPartSpheres1[0].center = CVector(0.0f, 0.0f, 0.0f);
- s_aBodyPartSpheres1[1].center = CVector(0.8f, 0.0f, 0.0f);
-
-#ifdef FIX_BUGS
- for (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres1); i++) {
-#else
- for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {
-#endif
- s_aBodyPartSpheres1[i].surface = SURFACE_PED;
- s_aBodyPartSpheres1[i].piece = 0;
- }
-
- ms_colModelBodyPart1.boundingSphere.Set(0.7f, CVector(0.4f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBodyPart1.boundingBox.Set(CVector(-0.3f, -0.3f, -0.3f), CVector(1.1f, 0.3f, 0.3f), SURFACE_DEFAULT, 0);
-
- SET_COLMODEL_SPHERES(ms_colModelBodyPart1, s_aBodyPartSpheres1);
-
- // Body Part Spheres 2
-
- s_aBodyPartSpheres2[0].radius = 0.15f;
- s_aBodyPartSpheres2[1].radius = 0.15f;
-
- s_aBodyPartSpheres2[0].center = CVector(0.0f, 0.0f, 0.0f);
- s_aBodyPartSpheres2[1].center = CVector(0.5f, 0.0f, 0.0f);
-
-#ifdef FIX_BUGS
- for (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres2); i++) {
-#else
- for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {
-#endif
- s_aBodyPartSpheres2[i].surface = SURFACE_PED;
- s_aBodyPartSpheres2[i].piece = 0;
- }
-
- ms_colModelBodyPart2.boundingSphere.Set(0.5f, CVector(0.25f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
- ms_colModelBodyPart2.boundingBox.Set(CVector(-0.2f, -0.2f, -0.2f), CVector(0.7f, 0.2f, 0.2f), SURFACE_DEFAULT, 0);
-
- SET_COLMODEL_SPHERES(ms_colModelBodyPart2, s_aBodyPartSpheres2);
-
-#undef SET_COLMODEL_SPHERES
-}
diff --git a/src/core/TempColModels.h b/src/core/TempColModels.h
deleted file mode 100644
index 3e1dd5e1..00000000
--- a/src/core/TempColModels.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-#include "Collision.h"
-
-class CTempColModels
-{
-public:
- static CColModel ms_colModelPed1;
- static CColModel ms_colModelPed2;
- static CColModel ms_colModelBBox;
- static CColModel ms_colModelBumper1;
- static CColModel ms_colModelWheel1;
- static CColModel ms_colModelPanel1;
- static CColModel ms_colModelBodyPart2;
- static CColModel ms_colModelBodyPart1;
- static CColModel ms_colModelCutObj[5];
- static CColModel ms_colModelPedGroundHit;
- static CColModel ms_colModelBoot1;
- static CColModel ms_colModelDoor1;
- static CColModel ms_colModelBonnet1;
-
- static void Initialise(void);
-};
diff --git a/src/core/World.cpp b/src/core/World.cpp
index d65d57dd..0bc564ff 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -53,6 +53,9 @@ bool CWorld::bIncludeCarTyres;
void
CWorld::Initialise()
{
+#if GTA_VERSION <= GTA3_PS2_160
+ CPools::Initialise();
+#endif
pIgnoreEntity = nil;
bDoingCarCollisions = false;
bSecondShift = false;
@@ -919,24 +922,24 @@ CEntity *
CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float radius, CEntity *entityToIgnore,
bool ignoreSomeObjects)
{
- static CColModel sphereCol;
-
- sphereCol.boundingSphere.center.x = 0.0f;
- sphereCol.boundingSphere.center.y = 0.0f;
- sphereCol.boundingSphere.center.z = 0.0f;
- sphereCol.boundingSphere.radius = radius;
- sphereCol.boundingBox.min.x = -radius;
- sphereCol.boundingBox.min.y = -radius;
- sphereCol.boundingBox.min.z = -radius;
- sphereCol.boundingBox.max.x = radius;
- sphereCol.boundingBox.max.y = radius;
- sphereCol.boundingBox.max.z = radius;
- sphereCol.numSpheres = 1;
- sphereCol.spheres = &sphereCol.boundingSphere;
- sphereCol.numLines = 0;
- sphereCol.numBoxes = 0;
- sphereCol.numTriangles = 0;
- sphereCol.ownsCollisionVolumes = false;
+ static CColModel OurColModel;
+
+ OurColModel.boundingSphere.center.x = 0.0f;
+ OurColModel.boundingSphere.center.y = 0.0f;
+ OurColModel.boundingSphere.center.z = 0.0f;
+ OurColModel.boundingSphere.radius = radius;
+ OurColModel.boundingBox.min.x = -radius;
+ OurColModel.boundingBox.min.y = -radius;
+ OurColModel.boundingBox.min.z = -radius;
+ OurColModel.boundingBox.max.x = radius;
+ OurColModel.boundingBox.max.y = radius;
+ OurColModel.boundingBox.max.z = radius;
+ OurColModel.numSpheres = 1;
+ OurColModel.spheres = &OurColModel.boundingSphere;
+ OurColModel.numLines = 0;
+ OurColModel.numBoxes = 0;
+ OurColModel.numTriangles = 0;
+ OurColModel.ownsCollisionVolumes = false;
CMatrix sphereMat;
sphereMat.SetTranslate(spherePos);
@@ -959,7 +962,7 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad
if(e->GetBoundRadius() + radius > distance) {
CColModel *eCol = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
int collidedSpheres =
- CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(), *eCol,
+ CCollision::ProcessColModels(sphereMat, OurColModel, e->GetMatrix(), *eCol,
gaTempSphereColPoints, nil, nil);
if(collidedSpheres != 0 ||
@@ -1735,10 +1738,12 @@ CWorld::ShutDown(void)
CWorld::Remove(pEntity);
delete pEntity;
}
+#ifndef FIX_BUGS
pSector->m_lists[ENTITYLIST_BUILDINGS].Flush();
pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();
pSector->m_lists[ENTITYLIST_DUMMIES].Flush();
pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();
+#endif
}
for(int32 i = 0; i < 4; i++) {
for(CPtrNode *pNode = GetBigBuildingList((eLevelName)i).first; pNode; pNode = pNode->next) {
@@ -1750,6 +1755,12 @@ CWorld::ShutDown(void)
}
for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) {
CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y);
+#ifdef FIX_BUGS
+ pSector->m_lists[ENTITYLIST_BUILDINGS].Flush();
+ pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();
+ pSector->m_lists[ENTITYLIST_DUMMIES].Flush();
+ pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();
+#endif
if(pSector->m_lists[ENTITYLIST_BUILDINGS].first) {
sprintf(gString, "Building list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y);
pSector->m_lists[ENTITYLIST_BUILDINGS].Flush();
@@ -1780,6 +1791,9 @@ CWorld::ShutDown(void)
}
}
ms_listMovingEntityPtrs.Flush();
+#if GTA_VERSION <= GTA3_PS2_160
+ CPools::Shutdown();
+#endif
}
void
diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp
index c376e11f..075a13bc 100644
--- a/src/core/ZoneCull.cpp
+++ b/src/core/ZoneCull.cpp
@@ -1,5 +1,6 @@
#include "common.h"
+#include "General.h"
#include "Building.h"
#include "Treadable.h"
#include "Train.h"
@@ -11,6 +12,9 @@
#include "ZoneCull.h"
#include "Zones.h"
+#include "Debug.h"
+#include "Renderer.h"
+
int32 CCullZones::NumCullZones;
CCullZone CCullZones::aZones[NUMCULLZONES];
int32 CCullZones::NumAttributeZones;
@@ -27,6 +31,8 @@ int32 CCullZones::EntityIndicesUsed;
bool CCullZones::bCurrentSubwayIsInvisible;
bool CCullZones::bCullZonesDisabled;
+#define NUMUNCOMPRESSED (6000)
+#define NUMTEMPINDICES (140000)
void
CCullZones::Init(void)
@@ -48,26 +54,6 @@ CCullZones::Init(void)
aPointersToBigBuildingsForTreadables[i] = -1;
}
-bool CCullZone::TestLine(CVector vec1, CVector vec2)
-{
- CColPoint colPoint;
- CEntity *entity;
-
- if (CWorld::ProcessLineOfSight(vec1, vec2, colPoint, entity, true, false, false, false, false, true, false))
- return true;
- if (CWorld::ProcessLineOfSight(CVector(vec1.x + 0.05f, vec1.y, vec1.z), CVector(vec2.x + 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
- return true;
- if (CWorld::ProcessLineOfSight(CVector(vec1.x - 0.05f, vec1.y, vec1.z), CVector(vec2.x - 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
- return true;
- if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y + 0.05f, vec1.z), CVector(vec2.x, vec2.y + 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
- return true;
- if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y - 0.05f, vec1.z), CVector(vec2.x, vec2.y - 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
- return true;
- if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z + 0.05f), CVector(vec2.x, vec2.y, vec2.z + 0.05f), colPoint, entity, true, false, false, false, false, true, false))
- return true;
- return CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z - 0.05f), CVector(vec2.x, vec2.y, vec2.z - 0.05f), colPoint, entity, true, false, false, false, false, true, false);
-}
-
uint16* pTempArrayIndices;
int TempEntityIndicesUsed;
@@ -89,19 +75,25 @@ CCullZones::ResolveVisibilities(void)
CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
CFileMgr::CloseFile(fd);
}else{
-#if 0
- // TODO: implement code from mobile to generate data here
+#ifndef MASTER
EntityIndicesUsed = 0;
BuildListForBigBuildings();
- pTempArrayIndices = new uint16[140000];
+ pTempArrayIndices = new uint16[NUMTEMPINDICES];
TempEntityIndicesUsed = 0;
- for (int i = 0; i < NumCullZones; i++) {
- DoVisibilityTestCullZone(i, true);
+// if(!LoadTempFile()) // not in final game
+ {
+ for (int i = 0; i < NumCullZones; i++) {
+//printf("testing zone %d (%d indices)\n", i, TempEntityIndicesUsed);
+ DoVisibilityTestCullZone(i, true);
+ }
+
+// SaveTempFile(); // not in final game
}
CompressIndicesArray();
delete[] pTempArrayIndices;
+ pTempArrayIndices = nil;
fd = CFileMgr::OpenFileForWriting("data\\cullzone.dat");
if (fd != 0) {
@@ -118,16 +110,53 @@ CCullZones::ResolveVisibilities(void)
}
}
+bool
+CCullZones::LoadTempFile(void)
+{
+ int fd = CFileMgr::OpenFile("cullzone.tmp");
+ if (fd != 0) {
+ CFileMgr::Read(fd, (char*)&NumCullZones, sizeof(NumCullZones));
+ CFileMgr::Read(fd, (char*)aZones, sizeof(aZones));
+ CFileMgr::Read(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones));
+ CFileMgr::Read(fd, (char*)&aAttributeZones, sizeof(aAttributeZones));
+ CFileMgr::Read(fd, (char*)pTempArrayIndices, NUMTEMPINDICES*sizeof(uint16));
+ CFileMgr::Read(fd, (char*)&TempEntityIndicesUsed, sizeof(TempEntityIndicesUsed));
+ CFileMgr::Read(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings));
+ CFileMgr::Read(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
+ CFileMgr::CloseFile(fd);
+ return true;
+ }
+ return false;
+}
+
+void
+CCullZones::SaveTempFile(void)
+{
+ int fd = CFileMgr::OpenFileForWriting("cullzone.tmp");
+ if (fd != 0) {
+ CFileMgr::Write(fd, (char*)&NumCullZones, sizeof(NumCullZones));
+ CFileMgr::Write(fd, (char*)aZones, sizeof(aZones));
+ CFileMgr::Write(fd, (char*)&NumAttributeZones, sizeof(NumAttributeZones));
+ CFileMgr::Write(fd, (char*)&aAttributeZones, sizeof(aAttributeZones));
+ CFileMgr::Write(fd, (char*)pTempArrayIndices, NUMTEMPINDICES*sizeof(uint16));
+ CFileMgr::Write(fd, (char*)&TempEntityIndicesUsed, sizeof(TempEntityIndicesUsed));
+ CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForBuildings, sizeof(aPointersToBigBuildingsForBuildings));
+ CFileMgr::Write(fd, (char*)&aPointersToBigBuildingsForTreadables, sizeof(aPointersToBigBuildingsForTreadables));
+ CFileMgr::CloseFile(fd);
+ }
+}
+
+
void
CCullZones::BuildListForBigBuildings()
{
for (int i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--) {
CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
if (building == nil || !building->bIsBIGBuilding) continue;
- CSimpleModelInfo *nonlod = (CSimpleModelInfo*)((CSimpleModelInfo *)CModelInfo::GetModelInfo(building->GetModelIndex()))->m_atomics[2];
+ CSimpleModelInfo *nonlod = ((CSimpleModelInfo *)CModelInfo::GetModelInfo(building->GetModelIndex()))->GetRelatedModel();
if (nonlod == nil) continue;
- for (int j = i; j >= 0; j--) {
+ for (int j = CPools::GetBuildingPool()->GetSize()-1; j >= 0; j--) {
CBuilding *building2 = CPools::GetBuildingPool()->GetSlot(j);
if (building2 == nil || building2->bIsBIGBuilding) continue;
if (CModelInfo::GetModelInfo(building2->GetModelIndex()) == nonlod) {
@@ -150,7 +179,7 @@ CCullZones::BuildListForBigBuildings()
}
void
-CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt)
+CCullZones::DoVisibilityTestCullZone(int zoneId, bool findIndices)
{
aZones[zoneId].m_groupIndexCount[0] = 0;
aZones[zoneId].m_groupIndexCount[1] = 0;
@@ -158,16 +187,17 @@ CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt)
aZones[zoneId].m_indexStart = TempEntityIndicesUsed;
aZones[zoneId].FindTestPoints();
- if (!doIt) return;
+ if (!findIndices) return;
for (int i = CPools::GetBuildingPool()->GetSize() - 1; i >= 0; i--) {
CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
if (building != nil && !building->bIsBIGBuilding && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForBuildings[i] != -1)) {
- CBuilding *building2 = nil;
+ CBuilding *LODbuilding = nil;
if (aPointersToBigBuildingsForBuildings[i] != -1)
- building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]);
+ LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForBuildings[i]);
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) {
+ if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, LODbuilding)) {
+ assert(TempEntityIndicesUsed < NUMTEMPINDICES);
pTempArrayIndices[TempEntityIndicesUsed++] = i;
aZones[zoneId].m_groupIndexCount[0]++;
}
@@ -175,13 +205,14 @@ CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt)
}
for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) {
- CTreadable* building = CPools::GetTreadablePool()->GetSlot(i);
+ CBuilding* building = CPools::GetTreadablePool()->GetSlot(i);
if (building != nil && aZones[zoneId].IsEntityCloseEnoughToZone(building, aPointersToBigBuildingsForTreadables[i] != -1)) {
- CTreadable* building2 = nil;
+ CBuilding *LODbuilding = nil;
if (aPointersToBigBuildingsForTreadables[i] != -1)
- building2 = CPools::GetTreadablePool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
+ LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, building2)) {
+ if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 10.0f, LODbuilding)) {
+ assert(TempEntityIndicesUsed < NUMTEMPINDICES);
pTempArrayIndices[TempEntityIndicesUsed++] = i;
aZones[zoneId].m_groupIndexCount[1]++;
}
@@ -189,23 +220,28 @@ CCullZones::DoVisibilityTestCullZone(int zoneId, bool doIt)
}
for (int i = CPools::GetTreadablePool()->GetSize() - 1; i >= 0; i--) {
- CTreadable *building = CPools::GetTreadablePool()->GetSlot(i);
- if (building != nil && aZones[zoneId].CalcDistToCullZoneSquared(building->GetPosition().x, building->GetPosition().y) < 40000.0f) {
+ CBuilding *building = CPools::GetTreadablePool()->GetSlot(i);
+ if (building != nil && aZones[zoneId].CalcDistToCullZoneSquared(building->GetPosition().x, building->GetPosition().y) < SQR(200.0f)) {
int start = aZones[zoneId].m_groupIndexCount[0] + aZones[zoneId].m_indexStart;
int end = aZones[zoneId].m_groupIndexCount[1] + start;
bool alreadyAdded = false;
for (int k = start; k < end; k++) {
+#ifdef FIX_BUGS
+ if (pTempArrayIndices[k] == i)
+#else
if (aIndices[k] == i)
+#endif
alreadyAdded = true;
}
if (!alreadyAdded) {
- CBuilding *building2 = nil;
+ CBuilding *LODbuilding = nil;
if (aPointersToBigBuildingsForTreadables[i] != -1)
- building2 = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
- if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, building2)) {
+ LODbuilding = CPools::GetBuildingPool()->GetSlot(aPointersToBigBuildingsForTreadables[i]);
+ if (!aZones[zoneId].TestEntityVisibilityFromCullZone(building, 0.0f, LODbuilding)) {
+ assert(TempEntityIndicesUsed < NUMTEMPINDICES);
pTempArrayIndices[TempEntityIndicesUsed++] = i;
aZones[zoneId].m_groupIndexCount[2]++;
}
@@ -353,7 +389,9 @@ CCullZones::AddCullZone(CVector const &position,
if((flag & ATTRZONE_NOTCULLZONE) == 0){
cull = &aZones[NumCullZones++];
v = position;
- // WTF is this?
+ // reposition start point to the start/end of the
+ // alley next to the big building in the industrial district.
+ // probably isn't analyzed correctly otherwise?s
if((v-CVector(1032.14f, -624.255f, 24.93f)).Magnitude() < 1.0f)
v = CVector(1061.7f, -613.0f, 19.0f);
if((v-CVector(1029.48f, -495.757f, 21.98f)).Magnitude() < 1.0f)
@@ -385,6 +423,208 @@ CCullZones::AddCullZone(CVector const &position,
}
}
+uint16 *pExtraArrayIndices;
+
+void
+CCullZones::CompressIndicesArray()
+{
+ uint16 set[3];
+
+ // These are used to hold the compressed groups in sets of 3
+ int numExtraIndices = 0;
+ pExtraArrayIndices = new uint16[NUMTEMPINDICES];
+
+ for(int numOccurrences = 6; numOccurrences > 1; numOccurrences--){
+ if(NumCullZones == 0)
+ break;
+
+//printf("checking occurrences %d\n", numOccurrences);
+ int attempt = 0;
+ while(attempt < 10000){
+ for(;;){
+ attempt++;
+
+ int zone = CGeneral::GetRandomNumber() % NumCullZones;
+ int group = CGeneral::GetRandomNumber() % 3;
+ if(!PickRandomSetForGroup(zone, group, set))
+ break;
+ if(!DoWeHaveMoreThanXOccurencesOfSet(numOccurrences, set))
+ break;
+
+ // add this set
+ attempt = 1;
+ int setId = numExtraIndices + NUMUNCOMPRESSED;
+ pExtraArrayIndices[numExtraIndices++] = set[0];
+ pExtraArrayIndices[numExtraIndices++] = set[1];
+ pExtraArrayIndices[numExtraIndices++] = set[2];
+ ReplaceSetForAllGroups(set, setId);
+ }
+ }
+ }
+
+ TidyUpAndMergeLists(pExtraArrayIndices, numExtraIndices);
+
+ delete[] pExtraArrayIndices;
+}
+
+// Get three random indices for this group of a zone
+bool
+CCullZones::PickRandomSetForGroup(int32 zone, int32 group, uint16 *set)
+{
+ int32 start;
+ int32 size;
+
+ aZones[zone].GetGroupStartAndSize(group, start, size);
+ if(size <= 0)
+ return false;
+
+ int numIndices = 0;
+ for(int i = 0; i < size; i++)
+ if(pTempArrayIndices[start + i] != 0xFFFF)
+ numIndices++;
+ if(numIndices < 3)
+ return false;
+
+ int first = CGeneral::GetRandomNumber() % (numIndices-2);
+
+ numIndices = 0;
+ int n = 0;
+ for(int i = 0; i < size; i++)
+ if(pTempArrayIndices[start + i] != 0xFFFF){
+ if(n++ < first) continue;
+
+ set[numIndices++] = pTempArrayIndices[start + i];
+ if(numIndices == 3)
+ break;
+ }
+ return true;
+}
+
+bool
+CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set)
+{
+ int32 curCount;
+ int32 start;
+ int32 size;
+
+ curCount = 0;
+ for (int i = 0; i < NumCullZones; i++) {
+ for (int group = 0; group < 3; group++) {
+ aZones[i].GetGroupStartAndSize(group, start, size);
+ if(size <= 0) continue;
+
+ // check if the set is a subset of the group
+ int n = 0;
+ for (int j = 0; j < size; j++) {
+ for (int k = 0; k < 3; k++) {
+ if (pTempArrayIndices[start+j] == set[k])
+ n++;
+ }
+ }
+ // yes it is
+ if(n == 3){
+ curCount++;
+ // check if we have seen this set often enough
+ if(curCount >= count)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void
+CCullZones::ReplaceSetForAllGroups(uint16 *set, uint16 setid)
+{
+ int32 start;
+ int32 size;
+
+ for(int i = 0; i < NumCullZones; i++)
+ for(int group = 0; group < 3; group++){
+ aZones[i].GetGroupStartAndSize(group, start, size);
+ if(size <= 0) continue;
+
+ // check if the set is a subset of the group
+ int n = 0;
+ for(int j = 0; j < size; j++){
+ for(int k = 0; k < 3; k++){
+ if(pTempArrayIndices[start+j] == set[k])
+ n++;
+ }
+ }
+
+ // yes it is, so replace it
+ if(n == 3){
+ bool insertedSet = false;
+ for(int j = 0; j < size; j++){
+ for(int k = 0; k < 3; k++){
+ // replace first element by set, invalidate others
+ if(pTempArrayIndices[start+j] == set[k]){
+ if(!insertedSet)
+ pTempArrayIndices[start+j] = setid;
+ else
+ pTempArrayIndices[start+j] = 0xFFFF;
+ insertedSet = true;
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+CCullZones::TidyUpAndMergeLists(uint16 *extraIndices, int32 numExtraIndices)
+{
+ int numTempIndices = 0;
+ for(int i = 0; i < TempEntityIndicesUsed; i++)
+ if(pTempArrayIndices[i] != 0xFFFF)
+ numTempIndices++;
+
+ // Fix up zone ranges such that there are no holes
+ for(int i = 0; i < NumCullZones; i++){
+ int j;
+ int start = 0;
+ for(j = 0; j < aZones[i].m_indexStart; j++)
+ if(pTempArrayIndices[j] != 0xFFFF)
+ start++;
+
+ aZones[i].m_indexStart = start;
+ aZones[i].m_numBuildings = 0;
+ aZones[i].m_numTreadablesPlus10m = 0;
+ aZones[i].m_numTreadables = 0;
+
+ for(int k = 0; k < aZones[i].m_groupIndexCount[0]; k++)
+ if(pTempArrayIndices[j++] != 0xFFFF)
+ aZones[i].m_numBuildings++;
+ for(int k = 0; k < aZones[i].m_groupIndexCount[1]; k++)
+ if(pTempArrayIndices[j++] != 0xFFFF)
+ aZones[i].m_numTreadablesPlus10m++;
+ for(int k = 0; k < aZones[i].m_groupIndexCount[2]; k++)
+ if(pTempArrayIndices[j++] != 0xFFFF)
+ aZones[i].m_numTreadables++;
+ }
+
+ // Now copy the actually used indices
+ EntityIndicesUsed = 0;
+ for(int i = 0; i < TempEntityIndicesUsed; i++)
+ if(pTempArrayIndices[i] != 0xFFFF){
+ assert(EntityIndicesUsed < NUMZONEINDICES);
+ if(pTempArrayIndices[i] < NUMUNCOMPRESSED)
+ aIndices[EntityIndicesUsed++] = pTempArrayIndices[i];
+ else
+ aIndices[EntityIndicesUsed++] = pTempArrayIndices[i] + numTempIndices;
+ }
+ for(int i = 0; i < numExtraIndices; i++)
+ if(extraIndices[i] != 0xFFFF){
+ assert(EntityIndicesUsed < NUMZONEINDICES);
+ if(extraIndices[i] < NUMUNCOMPRESSED)
+ aIndices[EntityIndicesUsed++] = extraIndices[i];
+ else
+ aIndices[EntityIndicesUsed++] = extraIndices[i] + numTempIndices;
+ }
+}
+
+
void
CCullZone::DoStuffLeavingZone(void)
@@ -403,13 +643,14 @@ CCullZone::DoStuffLeavingZone_OneBuilding(uint16 i)
int16 bb;
int j;
- if(i < 6000){
+
+ if(i < NUMUNCOMPRESSED){
CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = false;
bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false;
}else{
- i -= 6000;
+ i -= NUMUNCOMPRESSED;
for(j = 0; j < 3; j++)
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
}
@@ -421,14 +662,14 @@ CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i)
int16 bb;
int j;
- if(i < 6000){
+ if(i < NUMUNCOMPRESSED){
CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = false;
CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = false;
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false;
}else{
- i -= 6000;
+ i -= NUMUNCOMPRESSED;
for(j = 0; j < 3; j++)
DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[i+j]);
}
@@ -453,13 +694,13 @@ CCullZone::DoStuffEnteringZone_OneBuilding(uint16 i)
int16 bb;
int j;
- if(i < 6000){
+ if(i < NUMUNCOMPRESSED){
CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = true;
bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
}else{
- i -= 6000;
+ i -= NUMUNCOMPRESSED;
for(j = 0; j < 3; j++)
DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[i+j]);
}
@@ -471,14 +712,14 @@ CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i)
int16 bb;
int j;
- if(i < 6000){
+ if(i < NUMUNCOMPRESSED){
CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;
CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = true;
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
}else{
- i -= 6000;
+ i -= NUMUNCOMPRESSED;
for(j = 0; j < 3; j++)
DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[i+j]);
}
@@ -490,13 +731,13 @@ CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i)
int16 bb;
int j;
- if(i < 6000){
+ if(i < NUMUNCOMPRESSED){
CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
if(bb != -1)
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
}else{
- i -= 6000;
+ i -= NUMUNCOMPRESSED;
for(j = 0; j < 3; j++)
DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[i+j]);
}
@@ -519,6 +760,68 @@ CCullZone::CalcDistToCullZoneSquared(float x, float y)
}
bool
+CCullZone::TestLine(CVector vec1, CVector vec2)
+{
+ CColPoint colPoint;
+ CEntity *entity;
+
+ if (CWorld::ProcessLineOfSight(vec1, vec2, colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ if (CWorld::ProcessLineOfSight(CVector(vec1.x + 0.05f, vec1.y, vec1.z), CVector(vec2.x + 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ if (CWorld::ProcessLineOfSight(CVector(vec1.x - 0.05f, vec1.y, vec1.z), CVector(vec2.x - 0.05f, vec2.y, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y + 0.05f, vec1.z), CVector(vec2.x, vec2.y + 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y - 0.05f, vec1.z), CVector(vec2.x, vec2.y - 0.05f, vec2.z), colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ if (CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z + 0.05f), CVector(vec2.x, vec2.y, vec2.z + 0.05f), colPoint, entity, true, false, false, false, false, true, false))
+ return true;
+ return CWorld::ProcessLineOfSight(CVector(vec1.x, vec1.y, vec1.z - 0.05f), CVector(vec2.x, vec2.y, vec2.z - 0.05f), colPoint, entity, true, false, false, false, false, true, false);
+}
+
+bool
+CCullZone::DoThoroughLineTest(CVector start, CVector end, CEntity *testEntity)
+{
+ CColPoint colPoint;
+ CEntity *entity;
+
+ if(CWorld::ProcessLineOfSight(start, end, colPoint, entity, true, false, false, false, false, true, false) &&
+ testEntity != entity)
+ return false;
+
+ CVector side;
+#ifdef FIX_BUGS
+ if(start.x != end.x || start.y != end.y)
+#else
+ if(start.x != end.x && start.y != end.y)
+#endif
+ side = CVector(0.0f, 0.0f, 1.0f);
+ else
+ side = CVector(1.0f, 0.0f, 0.0f);
+ CVector up = CrossProduct(side, end - start);
+ side = CrossProduct(up, end - start);
+ side.Normalise();
+ up.Normalise();
+ side *= 0.1f;
+ up *= 0.1f;
+
+ if(CWorld::ProcessLineOfSight(start+side, end+side, colPoint, entity, true, false, false, false, false, true, false) &&
+ testEntity != entity)
+ return false;
+ if(CWorld::ProcessLineOfSight(start-side, end-side, colPoint, entity, true, false, false, false, false, true, false) &&
+ testEntity != entity)
+ return false;
+ if(CWorld::ProcessLineOfSight(start+up, end+up, colPoint, entity, true, false, false, false, false, true, false) &&
+ testEntity != entity)
+ return false;
+ if(CWorld::ProcessLineOfSight(start-up, end-up, colPoint, entity, true, false, false, false, false, true, false) &&
+ testEntity != entity)
+ return false;
+ return true;
+}
+
+bool
CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel)
{
const CVector &pos = entity->GetPosition();
@@ -526,10 +829,10 @@ CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel)
CSimpleModelInfo *minfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(entity->GetModelIndex());
float distToZone = CalcDistToCullZone(pos.x, pos.y);
float lodDist;
- if (minfo->m_isSubway)
- lodDist = minfo->GetLargestLodDistance() + 30.0f;
+ if (minfo->m_noFade)
+ lodDist = minfo->GetLargestLodDistance() + STREAM_DISTANCE;
else
- lodDist = minfo->GetLargestLodDistance() + 50.0f;
+ lodDist = minfo->GetLargestLodDistance() + STREAM_DISTANCE + FADE_DISTANCE;
if (lodDist > distToZone) return true;
if (!checkLevel) return false;
@@ -538,27 +841,749 @@ CCullZone::IsEntityCloseEnoughToZone(CEntity *entity, bool checkLevel)
}
bool
-CCullZones::DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set)
+CCullZone::PointFallsWithinZone(CVector pos, float radius)
{
- int32 curCount;
- int32 start;
- int32 size;
+ if(minx - radius > pos.x ||
+ maxx + radius < pos.x ||
+ miny - radius > pos.y ||
+ maxy + radius < pos.y ||
+ minz - radius > pos.z ||
+ maxz + radius < pos.z)
+ return false;
+ return true;
+}
- for (int i = 0; i < NumCullZones; i++) {
- curCount = 0;
- for (int group = 0; group < 3; group++) {
- aZones[i].GetGroupStartAndSize(group, start, size);
- int unk = 0; // TODO: figure out
- for (int j = 0; j < size; j++) {
- for (int k = 0; k < 3; k++) {
- if (set[k] == pTempArrayIndices[start+j])
- unk++;
+CVector ExtraFudgePointsCoors[] = {
+ CVector(978.0, -394.0, 18.0),
+ CVector(1189.7, -414.6, 27.0),
+ CVector(978.8, -391.0, 19.0),
+ CVector(1199.0, -502.3, 28.0),
+ CVector(1037.0, -391.9, 18.4),
+ CVector(1140.0, -608.7, 16.0),
+ CVector(1051.0, -26.0, 11.0),
+ CVector(951.5, -345.1, 12.0),
+ CVector(958.2, -394.6, 16.0),
+ CVector(1036.5, -390.0, 15.2),
+ CVector(960.6, -390.5, 20.9),
+ CVector(1061.0, -640.6, 16.3),
+ CVector(1034.5, -388.96, 14.78),
+ CVector(1038.4, -13.98, 12.2),
+ CVector(1047.2, -16.7, 10.6),
+ CVector(1257.9, -333.3, 40.0),
+ CVector(885.6, -424.9, 17.0),
+ CVector(1127.5, -795.8, 17.7),
+ CVector(1133.0, -716.0, 19.0),
+ CVector(1125.0, -694.0, 18.5),
+ CVector(1125.0, -670.0, 16.3),
+ CVector(1051.6, 36.3, 17.9),
+ CVector(1054.6, -11.4, 15.0),
+ CVector(1058.9, -278.0, 15.0),
+ CVector(1059.4, -261.0, 10.9),
+ CVector(1051.5, -638.5, 16.5),
+ CVector(1058.2, -643.4, 15.5),
+ CVector(1058.2, -643.4, 18.0),
+ CVector(826.0, -260.0, 7.0),
+ CVector(826.0, -260.0, 11.0),
+ CVector(833.0, -603.6, 16.4),
+ CVector(833.0, -603.6, 20.0),
+ CVector(1002.0, -318.5, 10.5),
+ CVector(998.0, -318.0, 9.8),
+ CVector(1127.0, -183.0, 18.1),
+ CVector(1123.0, -331.5, 23.8),
+ CVector(1123.8, -429.0, 24.0),
+ CVector(1197.0, -30.0, 13.7),
+ CVector(1117.5, -230.0, 17.3),
+ CVector(1117.5, -230.0, 20.0),
+ CVector(1120.0, -281.6, 21.5),
+ CVector(1120.0, -281.6, 24.0),
+ CVector(1084.5, -1022.7, 17.0),
+ CVector(1071.5, 5.4, 4.6),
+ CVector(1177.2, -215.7, 27.6),
+ CVector(841.6, -460.0, 19.7),
+ CVector(874.8, -456.6, 16.6),
+ CVector(918.3, -451.8, 17.8),
+ CVector(844.0, -495.7, 16.7),
+ CVector(842.0, -493.4, 21.0),
+ CVector(1433.5, -774.4, 16.9),
+ CVector(1051.0, -205.0, 7.5),
+ CVector(885.5, -425.6, 15.6),
+ CVector(182.6, -470.4, 27.8),
+ CVector(132.5, -930.2, 29.0),
+ CVector(124.7, -904.0, 28.0),
+ CVector(-50.0, -686.0, 22.0),
+ CVector(-49.1, -694.5, 22.5),
+ CVector(1063.8, -404.45, 16.2),
+ CVector(1062.2, -405.5, 17.0)
+};
+int32 NumTestPoints;
+int32 aTestPointsX[100];
+int32 aTestPointsY[100];
+int32 aTestPointsZ[100];
+CVector aTestPoints[100];
+int32 ElementsX, ElementsY, ElementsZ;
+float StepX, StepY, StepZ;
+int32 Memsize;
+uint8 *pMem;
+#define MEM(x, y, z) pMem[((x)*ElementsY + (y))*ElementsZ + (z)]
+#define FLAG_FREE 1
+#define FLAG_PROCESSED 2
+
+int32 MinValX, MaxValX;
+int32 MinValY, MaxValY;
+int32 MinValZ, MaxValZ;
+int32 Point1, Point2;
+int32 NewPointX, NewPointY, NewPointZ;
+
+
+void
+CCullZone::FindTestPoints()
+{
+ static int CZNumber;
+
+ NumTestPoints = 0;
+ ElementsX = (maxx-minx) < 1.0f ? 2 : (maxx-minx)+1.0f;
+ ElementsY = (maxy-miny) < 1.0f ? 2 : (maxy-miny)+1.0f;
+ ElementsZ = (maxz-minz) < 1.0f ? 2 : (maxz-minz)+1.0f;
+ if(ElementsX > 32) ElementsX = 32;
+ if(ElementsY > 32) ElementsY = 32;
+ if(ElementsZ > 32) ElementsZ = 32;
+ Memsize = ElementsX * ElementsY * ElementsZ;
+ StepX = (maxx-minx)/(ElementsX-1);
+ StepY = (maxy-miny)/(ElementsY-1);
+ StepZ = (maxz-minz)/(ElementsZ-1);
+
+ pMem = new uint8[Memsize];
+ memset(pMem, 0, Memsize);
+
+ // indices of center
+ int x = ElementsX * (position.x-minx)/(maxx-minx);
+ x = clamp(x, 0, ElementsX-1);
+ int y = ElementsY * (position.y-miny)/(maxy-miny);
+ y = clamp(y, 0, ElementsY-1);
+ int z = ElementsZ * (position.z-minz)/(maxz-minz);
+ z = clamp(z, 0, ElementsZ-1);
+
+ // Mark which test points inside the zone are not occupied by buildings.
+ // To do this, mark the start point as free and do a food fill.
+
+ // NB: we just assume the start position is free here!
+ MEM(x, y, z) |= FLAG_FREE;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ NumTestPoints++;
+
+ bool notDoneYet;
+ do{
+ notDoneYet = false;
+ for(x = 0; x < ElementsX; x++){
+ for(y = 0; y < ElementsY; y++){
+ for(z = 0; z < ElementsZ; z++){
+ if(!(MEM(x, y, z) & FLAG_FREE) || MEM(x, y, z) & FLAG_PROCESSED)
+ continue;
+
+ float pX = x*StepX + minx;
+ float pY = y*StepY + miny;
+ float pZ = z*StepZ + minz;
+
+ if(x > 0 && !(MEM(x-1, y, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX-StepX, pY, pZ)))
+ MEM(x-1, y, z) |= FLAG_FREE;
+ if(x < ElementsX-1 && !(MEM(x+1, y, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX+StepX, pY, pZ)))
+ MEM(x+1, y, z) |= FLAG_FREE;
+
+ if(y > 0 && !(MEM(x, y-1, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX, pY-StepY, pZ)))
+ MEM(x, y-1, z) |= FLAG_FREE;
+ if(y < ElementsY-1 && !(MEM(x, y+1, z) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX, pY+StepY, pZ)))
+ MEM(x, y+1, z) |= FLAG_FREE;
+
+ if(z > 0 && !(MEM(x, y, z-1) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX, pY, pZ-StepZ)))
+ MEM(x, y, z-1) |= FLAG_FREE;
+ if(z < ElementsZ-1 && !(MEM(x, y, z+1) & (FLAG_FREE | FLAG_PROCESSED)) &&
+ !TestLine(CVector(pX, pY, pZ), CVector(pX, pY, pZ+StepZ)))
+ MEM(x, y, z+1) |= FLAG_FREE;
+
+ notDoneYet = true;
+ MEM(x, y, z) |= FLAG_PROCESSED;
+ }
+ }
+ }
+ }while(notDoneYet);
+
+ bool done;
+
+ // Find bound planes of free space
+
+ // increase x, bounds in y and z
+ x = 0;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(y = 0; y < ElementsY; y++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(y + z < minA){
+ minA = y + z;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(y + z > maxA){
+ maxA = y + z;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(y - z < minB){
+ minB = y - z;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(y - z > maxB){
+ maxB = y - z;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
+ }
+ x++;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // decrease x, bounds in y and z
+ x = ElementsX-1;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(y = 0; y < ElementsY; y++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(y + z < minA){
+ minA = y + z;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(y + z > maxA){
+ maxA = y + z;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(y - z < minB){
+ minB = y - z;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(y - z > maxB){
+ maxB = y - z;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
+ }
+ x--;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // increase y, bounds in x and z
+ y = 0;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(x = 0; x < ElementsX; x++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(x + z < minA){
+ minA = x + z;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(x + z > maxA){
+ maxA = x + z;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(x - z < minB){
+ minB = x - z;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(x - z > maxB){
+ maxB = x - z;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
+ }
+ y++;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // decrease y, bounds in x and z
+ y = ElementsY-1;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(x = 0; x < ElementsX; x++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(x + z < minA){
+ minA = x + z;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(x + z > maxA){
+ maxA = x + z;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(x - z < minB){
+ minB = x - z;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(x - z > maxB){
+ maxB = x - z;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
}
+ y--;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // increase z, bounds in x and y
+ z = 0;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(x = 0; x < ElementsX; x++)
+ for(y = 0; y < ElementsY; y++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(x + y < minA){
+ minA = x + y;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(x + y > maxA){
+ maxA = x + y;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(x - y < minB){
+ minB = x - y;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(x - y > maxB){
+ maxB = x - y;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
+ }
+ z++;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // decrease z, bounds in x and y
+ z = ElementsZ-1;
+ do{
+ done = false;
+ int minA = 10000;
+ int minB = 10000;
+ int maxA = -10000;
+ int maxB = -10000;
+ for(x = 0; x < ElementsX; x++)
+ for(y = 0; y < ElementsY; y++)
+ if(MEM(x, y, z) & FLAG_FREE){
+ if(x + y < minA){
+ minA = x + y;
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ }
+ if(x + y > maxA){
+ maxA = x + y;
+ aTestPointsX[NumTestPoints+1] = x;
+ aTestPointsY[NumTestPoints+1] = y;
+ aTestPointsZ[NumTestPoints+1] = z;
+ }
+ if(x - y < minB){
+ minB = x - y;
+ aTestPointsX[NumTestPoints+2] = x;
+ aTestPointsY[NumTestPoints+2] = y;
+ aTestPointsZ[NumTestPoints+2] = z;
+ }
+ if(x - y > maxB){
+ maxB = x - y;
+ aTestPointsX[NumTestPoints+3] = x;
+ aTestPointsY[NumTestPoints+3] = y;
+ aTestPointsZ[NumTestPoints+3] = z;
+ }
+ done = true;
+ }
+ z--;
+ }while(!done);
+ NumTestPoints += 4;
+
+ // divide the axis aligned bounding planes into 4 and place some test points
+
+ // x = 0 plane
+ MinValY = 999999;
+ MinValZ = 999999;
+ MaxValY = 0;
+ MaxValZ = 0;
+ for(y = 0; y < ElementsY; y++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(0, y, z) & FLAG_FREE){
+ if(y < MinValY) MinValY = y;
+ if(z < MinValZ) MinValZ = z;
+ if(y > MaxValY) MaxValY = y;
+ if(z > MaxValZ) MaxValZ = z;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValY != 0 && MaxValZ != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointY = (Point1 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
+ NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
+ if(MEM(0, NewPointY, NewPointZ) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = 0;
+ aTestPointsY[NumTestPoints] = NewPointY;
+ aTestPointsZ[NumTestPoints] = NewPointZ;
+ NumTestPoints++;
+ }
+ }
+
+ // x = ElementsX-1 plane
+ MinValY = 999999;
+ MinValZ = 999999;
+ MaxValY = 0;
+ MaxValZ = 0;
+ for(y = 0; y < ElementsY; y++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(ElementsX-1, y, z) & FLAG_FREE){
+ if(y < MinValY) MinValY = y;
+ if(z < MinValZ) MinValZ = z;
+ if(y > MaxValY) MaxValY = y;
+ if(z > MaxValZ) MaxValZ = z;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValY != 0 && MaxValZ != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointY = (Point1 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
+ NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
+ if(MEM(ElementsX-1, NewPointY, NewPointZ) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = ElementsX-1;
+ aTestPointsY[NumTestPoints] = NewPointY;
+ aTestPointsZ[NumTestPoints] = NewPointZ;
+ NumTestPoints++;
+ }
+ }
+
+ // y = 0 plane
+ MinValX = 999999;
+ MinValZ = 999999;
+ MaxValX = 0;
+ MaxValZ = 0;
+ for(x = 0; x < ElementsX; x++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, 0, z) & FLAG_FREE){
+ if(x < MinValX) MinValX = x;
+ if(z < MinValZ) MinValZ = z;
+ if(x > MaxValX) MaxValX = x;
+ if(z > MaxValZ) MaxValZ = z;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValX != 0 && MaxValZ != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
+ NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
+ if(MEM(NewPointX, 0, NewPointZ) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = NewPointX;
+ aTestPointsY[NumTestPoints] = 0;
+ aTestPointsZ[NumTestPoints] = NewPointZ;
+ NumTestPoints++;
+ }
+ }
+
+ // y = ElementsY-1 plane
+ MinValX = 999999;
+ MinValZ = 999999;
+ MaxValX = 0;
+ MaxValZ = 0;
+ for(x = 0; x < ElementsX; x++)
+ for(z = 0; z < ElementsZ; z++)
+ if(MEM(x, ElementsY-1, z) & FLAG_FREE){
+ if(x < MinValX) MinValX = x;
+ if(z < MinValZ) MinValZ = z;
+ if(x > MaxValX) MaxValX = x;
+ if(z > MaxValZ) MaxValZ = z;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValX != 0 && MaxValZ != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
+ NewPointZ = (Point2 + 0.5f)*(MaxValZ - MinValZ)*0.5f + MinValZ;
+ if(MEM(NewPointX, ElementsY-1, NewPointZ) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = NewPointX;
+ aTestPointsY[NumTestPoints] = ElementsY-1;
+ aTestPointsZ[NumTestPoints] = NewPointZ;
+ NumTestPoints++;
+ }
+ }
+
+ // z = 0 plane
+ MinValX = 999999;
+ MinValY = 999999;
+ MaxValX = 0;
+ MaxValY = 0;
+ for(x = 0; x < ElementsX; x++)
+ for(y = 0; y < ElementsY; y++)
+ if(MEM(x, y, 0) & FLAG_FREE){
+ if(x < MinValX) MinValX = x;
+ if(y < MinValY) MinValY = y;
+ if(x > MaxValX) MaxValX = x;
+ if(y > MaxValY) MaxValY = y;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValX != 0 && MaxValY != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
+ NewPointY = (Point2 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
+ if(MEM(NewPointX, NewPointY, 0) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = NewPointX;
+ aTestPointsY[NumTestPoints] = NewPointY;
+ aTestPointsZ[NumTestPoints] = 0;
+ NumTestPoints++;
+ }
+ }
+
+ // z = ElementsZ-1 plane
+ MinValX = 999999;
+ MinValY = 999999;
+ MaxValX = 0;
+ MaxValY = 0;
+ for(x = 0; x < ElementsX; x++)
+ for(y = 0; y < ElementsY; y++)
+ if(MEM(x, y, ElementsZ-1) & FLAG_FREE){
+ if(x < MinValX) MinValX = x;
+ if(y < MinValY) MinValY = y;
+ if(x > MaxValX) MaxValX = x;
+ if(y > MaxValY) MaxValY = y;
+ }
+ // pick 4 points in the found bounds and add new test points
+ if(MaxValX != 0 && MaxValY != 0)
+ for(Point1 = 0; Point1 < 2; Point1++)
+ for(Point2 = 0; Point2 < 2; Point2++){
+ NewPointX = (Point1 + 0.5f)*(MaxValX - MinValX)*0.5f + MinValX;
+ NewPointY = (Point2 + 0.5f)*(MaxValY - MinValY)*0.5f + MinValY;
+ if(MEM(NewPointX, NewPointY, ElementsZ-1) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = NewPointX;
+ aTestPointsY[NumTestPoints] = NewPointY;
+ aTestPointsZ[NumTestPoints] = ElementsZ-1;
+ NumTestPoints++;
+ }
+ }
+
+ // add some hardcoded test points
+ for(int i = 0; i < ARRAY_SIZE(ExtraFudgePointsCoors); i++)
+ if(PointFallsWithinZone(ExtraFudgePointsCoors[i], 0.0f)){
+ x = ElementsX * (ExtraFudgePointsCoors[i].x-minx)/(maxx-minx);
+ y = ElementsY * (ExtraFudgePointsCoors[i].y-miny)/(maxy-miny);
+ z = ElementsZ * (ExtraFudgePointsCoors[i].z-minz)/(maxz-minz);
+ if(MEM(x, y, z) & FLAG_FREE){
+ aTestPointsX[NumTestPoints] = x;
+ aTestPointsY[NumTestPoints] = y;
+ aTestPointsZ[NumTestPoints] = z;
+ NumTestPoints++;
+ }
+ }
+
+ // remove duplicate points
+ for(int i = 0; i < NumTestPoints; i++)
+ for(int j = i+1; j < NumTestPoints; j++)
+ if(aTestPointsX[j] == aTestPointsX[i] &&
+ aTestPointsY[j] == aTestPointsY[i] &&
+ aTestPointsZ[j] == aTestPointsZ[i]){
+ // get rid of [j]
+ for(int k = j; k < NumTestPoints-1; k++){
+ aTestPointsX[k] = aTestPointsX[k+1];
+ aTestPointsY[k] = aTestPointsY[k+1];
+ aTestPointsZ[k] = aTestPointsZ[k+1];
+ }
+ NumTestPoints--;
+ }
+
+ // convert points to floating point
+ for(int i = 0; i < NumTestPoints; i++){
+ aTestPoints[i].x = aTestPointsX[i]*StepX + minx;
+ aTestPoints[i].y = aTestPointsY[i]*StepY + miny;
+ aTestPoints[i].z = aTestPointsZ[i]*StepZ + minz;
+ }
+
+ CZNumber++;
+
+ delete[] pMem;
+ pMem = nil;
+}
+
+bool
+CCullZone::TestEntityVisibilityFromCullZone(CEntity *entity, float extraDist, CEntity *LODentity)
+{
+ CColModel *colmodel = entity->GetColModel();
+ float boundMaxX = colmodel->boundingBox.max.x;
+ float boundMaxY = colmodel->boundingBox.max.y;
+ float boundMaxZ = colmodel->boundingBox.max.z;
+ float boundMinX = colmodel->boundingBox.min.x;
+ float boundMinY = colmodel->boundingBox.min.y;
+ float boundMinZ = colmodel->boundingBox.min.z;
+ if(LODentity){
+ colmodel = LODentity->GetColModel();
+ boundMaxX = Max(boundMaxX, colmodel->boundingBox.max.x);
+ boundMaxY = Max(boundMaxY, colmodel->boundingBox.max.y);
+ boundMaxZ = Max(boundMaxZ, colmodel->boundingBox.max.z);
+ boundMinX = Min(boundMinX, colmodel->boundingBox.min.x);
+ boundMinY = Min(boundMinY, colmodel->boundingBox.min.y);
+ boundMinZ = Min(boundMinZ, colmodel->boundingBox.min.z);
+ }
+
+ if(boundMaxZ-boundMinZ + extraDist < 0.5f)
+ boundMaxZ = boundMinZ + 0.5f;
+ else
+ boundMaxZ += extraDist;
+
+ CVector vecMin = entity->GetMatrix() * CVector(boundMinX, boundMinY, boundMinZ);
+ CVector vecMaxX = entity->GetMatrix() * CVector(boundMaxX, boundMinY, boundMinZ);
+ CVector vecMaxY = entity->GetMatrix() * CVector(boundMinX, boundMaxY, boundMinZ);
+ CVector vecMaxZ = entity->GetMatrix() * CVector(boundMinX, boundMinY, boundMaxZ);
+ CVector dirx = vecMaxX - vecMin;
+ CVector diry = vecMaxY - vecMin;
+ CVector dirz = vecMaxZ - vecMin;
+
+ // If building intersects zone at all, it's visible
+ int x, y, z;
+ for(x = 0; x < 9; x++){
+ CVector posX = vecMin + x/8.0f*dirx;
+ for(y = 0; y < 9; y++){
+ CVector posY = posX + y/8.0f*diry;
+ for(z = 0; z < 9; z++){
+ CVector posZ = posY + z/8.0f*dirz;
+ if(PointFallsWithinZone(posZ, 2.0f))
+ return true;
}
- if (unk == 3 && ++curCount >= count)
- return true;
}
}
+
+ float distToZone = CalcDistToCullZone(entity->GetPosition().x, entity->GetPosition().y)/15.0f;
+ distToZone = Max(distToZone, 7.0f);
+ int numX = (boundMaxX - boundMinX)/distToZone + 2.0f;
+ int numY = (boundMaxY - boundMinY)/distToZone + 2.0f;
+ int numZ = (boundMaxZ - boundMinZ)/distToZone + 2.0f;
+
+ float stepX = 1.0f/(numX-1);
+ float stepY = 1.0f/(numY-1);
+ float stepZ = 1.0f/(numZ-1);
+ float midX = (boundMaxX + boundMinX)/2.0f;
+ float midY = (boundMaxY + boundMinY)/2.0f;
+ float midZ = (boundMaxZ + boundMinZ)/2.0f;
+
+ // check both xy planes
+ for(int i = 0; i < NumTestPoints; i++){
+ CVector testPoint = aTestPoints[i];
+ CVector mid = entity->GetMatrix() * CVector(midX, midY, midZ);
+ mid.z += 0.1f;
+ if(DoThoroughLineTest(testPoint, mid, entity))
+ return true;
+
+ CVector ray = entity->GetPosition() - testPoint;
+
+ float dotX = DotProduct(ray, dirx);
+ float dotY = DotProduct(ray, diry);
+ float dotZ = DotProduct(ray, dirz);
+
+ for(x = 0; x < numX; x++){
+ CVector pMinZ = vecMin + x*stepX*dirx;
+ CVector pMaxZ = vecMin + x*stepX*dirx + dirz;
+ for(y = 0; y < numY; y++)
+ if(dotZ > 0.0f){
+ if(DoThoroughLineTest(testPoint, pMinZ + y*stepY*diry, entity))
+ return true;
+ }else{
+ if(DoThoroughLineTest(testPoint, pMaxZ + y*stepY*diry, entity))
+ return true;
+ }
+ }
+
+ for(x = 0; x < numX; x++){
+ CVector pMinY = vecMin + x*stepX*dirx;
+ CVector pMaxY = vecMin + x*stepX*dirx + diry;
+ for(z = 1; z < numZ-1; z++) // edge cases already handled
+ if(dotY > 0.0f){
+ if(DoThoroughLineTest(testPoint, pMinY + z*stepZ*dirz, entity))
+ return true;
+ }else{
+ if(DoThoroughLineTest(testPoint, pMaxY + z*stepZ*dirz, entity))
+ return true;
+ }
+ }
+
+ for(y = 1; y < numY-1; y++){ // edge cases already handled
+ CVector pMinX = vecMin + y*stepY*diry;
+ CVector pMaxX = vecMin + y*stepY*diry + dirx;
+ for(z = 1; z < numZ-1; z++) // edge cases already handled
+ if(dotX > 0.0f){
+ if(DoThoroughLineTest(testPoint, pMinX + z*stepZ*dirz, entity))
+ return true;
+ }else{
+ if(DoThoroughLineTest(testPoint, pMaxX + z*stepZ*dirz, entity))
+ return true;
+ }
+ }
+ }
+
return false;
}
diff --git a/src/core/ZoneCull.h b/src/core/ZoneCull.h
index 9bc07b8c..10742ffb 100644
--- a/src/core/ZoneCull.h
+++ b/src/core/ZoneCull.h
@@ -12,7 +12,7 @@ public:
float maxz;
int32 m_indexStart;
- int16 m_groupIndexCount[3];
+ int16 m_groupIndexCount[3]; // only useful during resolution stage
int16 m_numBuildings;
int16 m_numTreadablesPlus10m;
int16 m_numTreadables;
@@ -26,30 +26,35 @@ public:
static void DoStuffEnteringZone_OneTreadable(uint16 i);
- static bool TestLine(CVector a1, CVector a2);
+ static bool TestLine(CVector vec1, CVector vec2);
+ static bool DoThoroughLineTest(CVector vec1, CVector vec2, CEntity *testEntity);
float CalcDistToCullZoneSquared(float x, float y);
float CalcDistToCullZone(float x, float y) { return Sqrt(CalcDistToCullZoneSquared(x, y)); };
bool IsEntityCloseEnoughToZone(CEntity* entity, bool checkLevel);
+ bool PointFallsWithinZone(CVector pos, float radius);
+ bool TestEntityVisibilityFromCullZone(CEntity *entity, float extraDist, CEntity *LODentity);
+ void FindTestPoints();
void GetGroupStartAndSize(int32 groupid, int32 &start, int32 &size) {
switch (groupid) {
+ case 0:
+ default:
+ // buildings
+ start = m_indexStart;
+ size = m_groupIndexCount[0];
+ break;
case 1:
+ // treadables + 10m
start = m_groupIndexCount[0] + m_indexStart;
size = m_groupIndexCount[1];
break;
case 2:
+ // treadables
start = m_groupIndexCount[0] + m_groupIndexCount[1] + m_indexStart;
size = m_groupIndexCount[2];
break;
- default:
- start = m_indexStart;
- size = m_groupIndexCount[0];
- break;
}
}
-
- void FindTestPoints() {}; // todo
- bool TestEntityVisibilityFromCullZone(CEntity*, float, CEntity*) { return false; }; // todo
};
enum eZoneAttribs
@@ -121,5 +126,12 @@ public:
static void DoVisibilityTestCullZone(int zoneId, bool doIt);
static bool DoWeHaveMoreThanXOccurencesOfSet(int32 count, uint16 *set);
- static void CompressIndicesArray() {};// todo
+ static void CompressIndicesArray();
+ static bool PickRandomSetForGroup(int32 zone, int32 group, uint16 *set);
+ static void ReplaceSetForAllGroups(uint16 *set, uint16 setid);
+ static void TidyUpAndMergeLists(uint16 *extraIndices, int32 numExtraIndices);
+
+ // debug
+ static bool LoadTempFile(void);
+ static void SaveTempFile(void);
};
diff --git a/src/core/config.h b/src/core/config.h
index a87b1850..d64cca40 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -1,27 +1,27 @@
#pragma once
enum Config {
- NUMPLAYERS = 1,
+ NUMPLAYERS = 1, // 4 on PS2
NUMCDIMAGES = 12, // gta3.img duplicates (not used on PC)
MAX_CDIMAGES = 8, // additional cdimages
MAX_CDCHANNELS = 5,
- MODELINFOSIZE = 5500,
+ MODELINFOSIZE = 5500, // 3150 on PS2
// TXDSTORESIZE = 850,
TXDSTORESIZE = 1024, // for Xbox map
EXTRADIRSIZE = 128,
CUTSCENEDIRSIZE = 512,
- SIMPLEMODELSIZE = 5000,
+ SIMPLEMODELSIZE = 5000, // 2910 on PS2
MLOMODELSIZE = 1,
MLOINSTANCESIZE = 1,
TIMEMODELSIZE = 30,
CLUMPMODELSIZE = 5,
PEDMODELSIZE = 90,
- VEHICLEMODELSIZE = 120,
+ VEHICLEMODELSIZE = 120, // 70 on PS2
XTRACOMPSMODELSIZE = 2,
- TWODFXSIZE = 2000,
+ TWODFXSIZE = 2000, // 1210 on PS2
MAXVEHICLESLOADED = 50, // 70 on mobile
@@ -135,10 +135,6 @@ enum Config {
NUM_EXPLOSIONS = 48,
};
-// We'll use this once we're ready to become independent of the game
-// Use it to mark bugs in the code that will prevent the game from working then
-//#define STANDALONE
-
// We don't expect to compile for PS2 or Xbox
// but it might be interesting for documentation purposes
#define GTA_PC
@@ -156,30 +152,68 @@ enum Config {
// any debug stuff that is only left in mobile, is not in MASTER
//#define MASTER
+// once and for all:
+// pc: FINAL & MASTER
+// mobile: FINAL
+
+// MASTER builds must be FINAL
+#ifdef MASTER
+#define FINAL
+#endif
+
+// Version defines
+#define GTA3_PS2_140 300
+#define GTA3_PS2_160 301
+#define GTA3_PC_10 310
+#define GTA3_PC_11 311
+#define GTA3_PC_STEAM 312
+// TODO? maybe something for xbox or android?
+
+#define GTA_VERSION GTA3_PC_11
+
+// quality of life fixes that should also be in FINAL
+#define NASTY_GAME // nasty game for all languages
+#define NO_CDCHECK
+
+// those infamous texts
+#define DRAW_GAME_VERSION_TEXT
+#define DRAW_MENU_VERSION_TEXT
+
+// Memory allocation and compression
+// #define USE_CUSTOM_ALLOCATOR // use CMemoryHeap for allocation. use with care, not finished yet
+//#define COMPRESSED_COL_VECTORS // use compressed vectors for collision vertices
+//#define ANIM_COMPRESSION // only keep most recently used anims uncompressed
+
#if defined GTA_PS2
# define GTA_PS2_STUFF
# define RANDOMSPLASH
+# define USE_CUSTOM_ALLOCATOR
# define VU_COLLISION
+# define ANIM_COMPRESSION
#elif defined GTA_PC
-# define GTA3_1_1_PATCH
-//# define GTA3_STEAM_PATCH
# ifdef GTA_PS2_STUFF
# define USE_PS2_RAND
# define RANDOMSPLASH // use random splash as on PS2
# define PS2_MATFX
# endif
+# define GTA_REPLAY
+# define GTA_SCENE_EDIT
#elif defined GTA_XBOX
#endif
#ifdef VU_COLLISION
-#define COMPRESSED_COL_VECTORS // current need compressed vectors in this code
+#define COMPRESSED_COL_VECTORS // currently need compressed vectors in this code
#endif
#ifdef MASTER
// only in master builds
+ #undef DRAW_GAME_VERSION_TEXT
#else
// not in master builds
#define VALIDATE_SAVE_SIZE
+
+ #define NO_MOVIES // disable intro videos
+ #define DEBUGMENU
#endif
#ifdef FINAL
@@ -187,18 +221,19 @@ enum Config {
# define USE_MY_DOCUMENTS // use my documents directory for user files
#else
// not in any game
-# define NASTY_GAME // nasty game for all languages
-# define NO_MOVIES // disable intro videos
-# define NO_CDCHECK
# define CHATTYSPLASH // print what the game is loading
-# define DEBUGMENU
# define TIMEBARS // print debug timers
#endif
-#define FIX_BUGS // fixes bugs that we've came across during reversing, TODO: use this more
+#define FIX_BUGS // fixes bugs that we've came across during reversing
#define MORE_LANGUAGES // Add more translations to the game
#define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible
-#define LOAD_INI_SETTINGS
+#define LOAD_INI_SETTINGS // as the name suggests. fundamental for CUSTOM_FRONTEND_OPTIONS
+
+// Just debug menu entries
+#ifdef DEBUGMENU
+#define MISSION_SWITCHER // from debug menu
+#endif
// Rendering/display
//#define EXTRA_MODEL_FLAGS // from mobile to optimize rendering
@@ -209,17 +244,20 @@ enum Config {
#define USE_TXD_CDIMAGE // generate and load textures from txd.img
#define PS2_ALPHA_TEST // emulate ps2 alpha test
#define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number
-//#define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time
-#define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU
+#define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time
+#define DISABLE_VSYNC_ON_TEXTURE_CONVERSION // make texture conversion work faster by disabling vsync
//#define USE_TEXTURE_POOL
-#define CUTSCENE_BORDERS_SWITCH
+#ifdef LIBRW
//#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur)
//#define EXTENDED_PIPELINES // custom render pipelines (includes Neo)
-#define MULTISAMPLING // adds MSAA option
+//#define SCREEN_DROPLETS // neo water droplets
+#endif
-#ifdef LIBRW
-// these are not supported with librw yet
-# undef MULTISAMPLING
+#ifndef EXTENDED_COLOURFILTER
+#undef SCREEN_DROPLETS // we need the backbuffer for this effect
+#endif
+#ifndef EXTENDED_PIPELINES
+#undef SCREEN_DROPLETS // we need neo.txd
#endif
// Particle
@@ -239,12 +277,14 @@ enum Config {
#define ALT_DODO_CHEAT
#define REGISTER_START_BUTTON
//#define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls
+#define BUTTON_ICONS // use textures to show controller buttons
// Hud, frontend and radar
#define PS2_HUD
#define HUD_ENHANCEMENTS // Adjusts some aspects to make the HUD look/behave a little bit better.
// #define BETA_SLIDING_TEXT
#define TRIANGULAR_BLIPS // height indicating triangular radar blips, as in VC
+// #define XBOX_SUBTITLES // the infamous outlines
#define PC_MENU
#ifndef PC_MENU
@@ -258,7 +298,14 @@ enum Config {
//# define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc.
//# define PS2_SAVE_DIALOG // PS2 style save dialog with transparent black box
# define CUSTOM_FRONTEND_OPTIONS
-# define GRAPHICS_MENU_OPTIONS // otherwise Advanced Options menu will appear if Display is full
+
+# ifdef CUSTOM_FRONTEND_OPTIONS
+# define GRAPHICS_MENU_OPTIONS // otherwise Advanced Options menu will appear if Display is full
+# define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU
+# define CUTSCENE_BORDERS_SWITCH
+# define MULTISAMPLING // adds MSAA option
+# define INVERT_LOOK_FOR_PAD // add bInvertLook4Pad from VC
+# endif
#endif
// Script
@@ -270,7 +317,7 @@ enum Config {
#endif
//#define SIMPLIER_MISSIONS // apply simplifications from mobile
#define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
-#define SCRIPT_LOG_FILE_LEVEL 1 // 0 == no log, 1 == overwrite every frame, 2 == full log
+#define SCRIPT_LOG_FILE_LEVEL 0 // 0 == no log, 1 == overwrite every frame, 2 == full log
#ifndef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
#define USE_BASIC_SCRIPT_DEBUG_OUTPUT
@@ -307,6 +354,8 @@ enum Config {
#endif
//#define PS2_AUDIO // changes audio paths for cutscenes and radio to PS2 paths, needs vbdec to support VB with MSS
+// IMG
+#define BIG_IMG // allows to read larger img files
//#define SQUEEZE_PERFORMANCE
#ifdef SQUEEZE_PERFORMANCE
@@ -315,3 +364,7 @@ enum Config {
#define PC_PARTICLE
#define VC_PED_PORTS // To not process collisions always. But should be tested if that's really beneficial
#endif
+
+#ifdef LIBRW
+// these are not supported with librw yet
+#endif
diff --git a/src/core/main.cpp b/src/core/main.cpp
index 171d0a57..cc7f3259 100644
--- a/src/core/main.cpp
+++ b/src/core/main.cpp
@@ -63,7 +63,11 @@
#include "SceneEdit.h"
#include "debugmenu.h"
#include "Clock.h"
+#include "postfx.h"
#include "custompipes.h"
+#include "screendroplets.h"
+#include "frontendoption.h"
+#include "MemoryHeap.h"
GlobalScene Scene;
@@ -88,7 +92,11 @@ RwRGBA gColourTop;
bool gameAlreadyInitialised;
float NumberOfChunksLoaded;
+#ifdef GTA_PS2
+#define TOTALNUMCHUNKS 48.0f
+#else
#define TOTALNUMCHUNKS 73.0f
+#endif
bool g_SlowMode = false;
char version_name[64];
@@ -102,6 +110,18 @@ void TheGame(void);
void DebugMenuPopulate(void);
#endif
+#ifndef FINAL
+bool gbPrintMemoryUsage;
+#endif
+
+#ifdef PS2_MENU
+#define WANT_TO_LOAD TheMemoryCard.m_bWantToLoad
+#define FOUND_GAME_TO_LOAD TheMemoryCard.b_FoundRecentSavedGameWantToLoad
+#else
+#define WANT_TO_LOAD FrontEndMenuManager.m_bWantToLoad
+#define FOUND_GAME_TO_LOAD b_FoundRecentSavedGameWantToLoad
+#endif
+
void
ValidateVersion()
{
@@ -404,10 +424,20 @@ Initialise3D(void *param)
DebugMenuInit();
DebugMenuPopulate();
#endif // !DEBUGMENU
+#ifdef CUSTOM_FRONTEND_OPTIONS
+ // Apparently this func. can be run multiple times at the start.
+ if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0) {
+ // needs stored language and TheText to be loaded, and last TheText reload is at the start of here
+ CustomFrontendOptionsPopulate();
+ }
+#endif
bool ret = CGame::InitialiseRenderWare();
#ifdef EXTENDED_PIPELINES
CustomPipes::CustomPipeInit(); // need Scene.world for this
#endif
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::InitDraw();
+#endif
return ret;
}
@@ -417,6 +447,9 @@ Initialise3D(void *param)
static void
Terminate3D(void)
{
+#ifdef SCREEN_DROPLETS
+ ScreenDroplets::Shutdown();
+#endif
#ifdef EXTENDED_PIPELINES
CustomPipes::CustomPipeShutdown();
#endif
@@ -634,18 +667,18 @@ LoadingIslandScreen(const char *levelName)
CFont::SetColor(CRGBA(243, 237, 71, 255));
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f));
#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(20.0f), SCREEN_STRETCH_FROM_BOTTOM(110.0f), TheText.Get("WELCOME"));
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(110.0f), TheText.Get("WELCOME"));
#else
- CFont::PrintString(SCREEN_WIDTH - 20, SCREEN_STRETCH_FROM_BOTTOM(110.0f), TheText.Get("WELCOME"));
+ CFont::PrintString(SCREEN_WIDTH - 20, SCREEN_SCALE_FROM_BOTTOM(110.0f), TheText.Get("WELCOME"));
#endif
TextCopy(wstr, name);
TheText.UpperCase(wstr);
CFont::SetColor(CRGBA(243, 237, 71, 255));
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f));
#ifdef FIX_BUGS
- CFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(20.0f), SCREEN_STRETCH_FROM_BOTTOM(80.0f), wstr);
+ CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(80.0f), wstr);
#else
- CFont::PrintString(SCREEN_WIDTH-20, SCREEN_STRETCH_FROM_BOTTOM(80.0f), wstr);
+ CFont::PrintString(SCREEN_WIDTH-20, SCREEN_SCALE_FROM_BOTTOM(80.0f), wstr);
#endif
CFont::DrawFonts();
DoRWStuffEndOfFrame();
@@ -768,6 +801,170 @@ tZonePrint ZonePrint[] =
};
#ifndef MASTER
+
+void
+PrintMemoryUsage(void)
+{
+// little hack
+if(CPools::GetPtrNodePool() == nil)
+return;
+
+ // Style taken from LCS, modified for III
+// CFont::SetFontStyle(FONT_PAGER);
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::SetBackgroundOff();
+ CFont::SetWrapx(640.0f);
+// CFont::SetScale(0.5f, 0.75f);
+ CFont::SetScale(0.4f, 0.75f);
+ CFont::SetCentreOff();
+ CFont::SetCentreSize(640.0f);
+ CFont::SetJustifyOff();
+ CFont::SetPropOn();
+ CFont::SetColor(CRGBA(200, 200, 200, 200));
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetDropShadowPosition(0);
+
+ float y;
+
+#ifdef USE_CUSTOM_ALLOCATOR
+ y = 24.0f;
+ sprintf(gString, "Total: %d blocks, %d bytes", gMainHeap.m_totalBlocksUsed, gMainHeap.m_totalMemUsed);
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Game: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_GAME), gMainHeap.GetMemoryUsed(MEMID_GAME));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "World: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_WORLD), gMainHeap.GetMemoryUsed(MEMID_WORLD));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Render: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_RENDER), gMainHeap.GetMemoryUsed(MEMID_RENDER));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Render List: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_RENDERLIST), gMainHeap.GetMemoryUsed(MEMID_RENDERLIST));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Default Models: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_DEF_MODELS), gMainHeap.GetMemoryUsed(MEMID_DEF_MODELS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Textures: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_TEXTURES), gMainHeap.GetMemoryUsed(MEMID_TEXTURES));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Streaming: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM), gMainHeap.GetMemoryUsed(MEMID_STREAM));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Streamed Models: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_MODELS), gMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Streamed Textures: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_STREAM_TEXUTRES), gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Animation: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_ANIMATION), gMainHeap.GetMemoryUsed(MEMID_ANIMATION));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Pools: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_POOLS), gMainHeap.GetMemoryUsed(MEMID_POOLS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Collision: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_COLLISION), gMainHeap.GetMemoryUsed(MEMID_COLLISION));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Game Process: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_GAME_PROCESS), gMainHeap.GetMemoryUsed(MEMID_GAME_PROCESS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Script: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_SCRIPT), gMainHeap.GetMemoryUsed(MEMID_SCRIPT));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Cars: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_CARS), gMainHeap.GetMemoryUsed(MEMID_CARS));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Frontend: %d blocks, %d bytes", gMainHeap.GetBlocksUsed(MEMID_FRONTEND), gMainHeap.GetMemoryUsed(MEMID_FRONTEND));
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(24.0f, y, gUString);
+ y += 12.0f;
+#endif
+
+ y = 132.0f;
+ AsciiToUnicode("Pools usage:", gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "PtrNode: %d/%d", CPools::GetPtrNodePool()->GetNoOfUsedSpaces(), CPools::GetPtrNodePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "EntryInfoNode: %d/%d", CPools::GetEntryInfoNodePool()->GetNoOfUsedSpaces(), CPools::GetEntryInfoNodePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Ped: %d/%d", CPools::GetPedPool()->GetNoOfUsedSpaces(), CPools::GetPedPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Vehicle: %d/%d", CPools::GetVehiclePool()->GetNoOfUsedSpaces(), CPools::GetVehiclePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Building: %d/%d", CPools::GetBuildingPool()->GetNoOfUsedSpaces(), CPools::GetBuildingPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Treadable: %d/%d", CPools::GetTreadablePool()->GetNoOfUsedSpaces(), CPools::GetTreadablePool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Object: %d/%d", CPools::GetObjectPool()->GetNoOfUsedSpaces(), CPools::GetObjectPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "Dummy: %d/%d", CPools::GetDummyPool()->GetNoOfUsedSpaces(), CPools::GetDummyPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+
+ sprintf(gString, "AudioScriptObjects: %d/%d", CPools::GetAudioScriptObjectPool()->GetNoOfUsedSpaces(), CPools::GetAudioScriptObjectPool()->GetSize());
+ AsciiToUnicode(gString, gUString);
+ CFont::PrintString(400.0f, y, gUString);
+ y += 12.0f;
+}
+
void
DisplayGameDebugText()
{
@@ -779,11 +976,15 @@ DisplayGameDebugText()
TWEAKBOOL(bDisplayPosn);
TWEAKBOOL(bDisplayRate);
}
-#endif
+ if(gbPrintMemoryUsage)
+ PrintMemoryUsage();
+#endif
char str[200];
wchar ustr[200];
+
+#ifdef DRAW_GAME_VERSION_TEXT
wchar ver[200];
AsciiToUnicode(version_name, ver);
@@ -803,6 +1004,7 @@ DisplayGameDebugText()
#else
CFont::PrintString(10.0f, 10.0f, ver);
#endif
+#endif // #ifdef DRAW_GAME_VERSION_TEXT
FrameSamples++;
FramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f);
@@ -989,9 +1191,11 @@ Render2dStuff(void)
MusicManager.DisplayRadioStationName();
TheConsole.Display();
+#ifdef GTA_SCENE_EDIT
if(CSceneEdit::m_bEditOn)
CSceneEdit::Draw();
else
+#endif
CHud::Draw();
CUserDisplay::OnscnTimer.ProcessForDisplay();
CMessages::Display();
@@ -1010,13 +1214,9 @@ RenderMenus(void)
{
if (FrontEndMenuManager.m_bMenuActive)
{
-#ifdef PS2
- gMainHeap.PushMemId(_TODOCONST(17));
-#endif
+ PUSH_MEMID(MEMID_FRONTEND);
FrontEndMenuManager.DrawFrontEnd();
-#ifdef PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
}
}
@@ -1055,24 +1255,29 @@ Idle(void *arg)
CPad::UpdatePads();
FrontEndMenuManager.Process();
} else {
+ PUSH_MEMID(MEMID_GAME_PROCESS);
CPointLights::InitPerFrame();
tbStartTimer(0, "CGame::Process");
CGame::Process();
tbEndTimer("CGame::Process");
+ POP_MEMID();
+
tbStartTimer(0, "DMAudio.Service");
DMAudio.Service();
-
tbEndTimer("DMAudio.Service");
}
if (RsGlobal.quit)
return;
#else
+
+ PUSH_MEMID(MEMID_GAME_PROCESS);
CPointLights::InitPerFrame();
tbStartTimer(0, "CGame::Process");
CGame::Process();
tbEndTimer("CGame::Process");
+ POP_MEMID();
tbStartTimer(0, "DMAudio.Service");
DMAudio.Service();
@@ -1080,21 +1285,12 @@ Idle(void *arg)
#endif
if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){
-#ifdef PS2_MENU
- TheMemoryCard.m_bWantToLoad = false;
+ WANT_TO_LOAD = false;
FrontEndMenuManager.m_bWantToRestart = true;
-#else
- FrontEndMenuManager.m_bWantToRestart = true;
- FrontEndMenuManager.m_bWantToLoad = false;
-#endif
return;
}
-#ifdef PS2_MENU
- if ( FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad )
-#else
- if(FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
-#endif
+ if(FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)
{
return;
}
@@ -1104,18 +1300,22 @@ Idle(void *arg)
if(arg == nil)
return;
+ PUSH_MEMID(MEMID_RENDER);
+
if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu) &&
TheCamera.GetScreenFadeStatus() != FADE_2)
{
-#if defined(GTA_PC) && defined(FIX_BUGS)
+#if defined(GTA_PC) && !defined(RW_GL3) && defined(FIX_BUGS)
+ // This is from SA, but it's nice for windowed mode
if (!FrontEndMenuManager.m_bRenderGameInMenu) {
- // This is from SA, but it's nice for windowed mode
RwV2d pos;
pos.x = SCREEN_WIDTH / 2.0f;
pos.y = SCREEN_HEIGHT / 2.0f;
RsMouseSetPos(&pos);
}
#endif
+
+ PUSH_MEMID(MEMID_RENDERLIST);
tbStartTimer(0, "CnstrRenderList");
CRenderer::ConstructRenderList();
tbEndTimer("CnstrRenderList");
@@ -1123,6 +1323,7 @@ Idle(void *arg)
tbStartTimer(0, "PreRender");
CRenderer::PreRender();
tbEndTimer("PreRender");
+ POP_MEMID();
#ifdef FIX_BUGS
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); // TODO: temp? this fixes OpenGL render but there should be a better place for this
@@ -1133,12 +1334,12 @@ Idle(void *arg)
if(CWeather::LightningFlash && !CCullZones::CamNoRain()){
if(!DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255))
- return;
+ goto popret;
}else{
if(!DoRWStuffStartOfFrame_Horizon(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(),
CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),
255))
- return;
+ goto popret;
}
DefinedState();
@@ -1159,10 +1360,17 @@ Idle(void *arg)
RenderDebugShit();
RenderEffects();
- tbStartTimer(0, "RenderMotionBlur");
if((TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE) &&
TheCamera.m_ScreenReductionPercentage > 0.0f)
TheCamera.SetMotionBlurAlpha(150);
+
+#ifdef SCREEN_DROPLETS
+ CPostFX::GetBackBuffer(Scene.camera);
+ ScreenDroplets::Process();
+ ScreenDroplets::Render();
+#endif
+
+ tbStartTimer(0, "RenderMotionBlur");
TheCamera.RenderMotionBlur();
tbEndTimer("RenderMotionBlur");
@@ -1178,7 +1386,7 @@ Idle(void *arg)
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
if(!RsCameraBeginUpdate(Scene.camera))
- return;
+ goto popret;
}
#ifdef PS2_SAVE_DIALOG
@@ -1191,7 +1399,7 @@ Idle(void *arg)
#ifdef PS2_MENU
if ( TheMemoryCard.m_bWantToLoad )
- return;
+ goto popret;
#endif
tbStartTimer(0, "DoFade");
@@ -1210,8 +1418,13 @@ Idle(void *arg)
DoRWStuffEndOfFrame();
+ POP_MEMID(); // MEMID_RENDER
+
if(g_SlowMode)
ProcessSlowMode();
+ return;
+
+popret: POP_MEMID(); // MEMID_RENDER
}
void
@@ -1377,14 +1590,13 @@ TheModelViewer(void)
}
#endif
-#ifdef PS2
+
+#ifdef GTA_PS2
void TheGame(void)
{
printf("Into TheGame!!!\n");
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(1));
-#endif
+ PUSH_MEMID(MEMID_GAME); // NB: not popped
CTimer::Initialise();
@@ -1422,77 +1634,49 @@ void TheGame(void)
while (true)
{
-#ifdef PS2
- if (TheMemoryCard.m_bWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToLoad)
-#endif
+ if (WANT_TO_LOAD)
{
Const char *splash1 = GetLevelSplashScreen(CGame::currLevel);
LoadSplash(splash1);
}
-#ifdef PS2
- TheMemoryCard.m_bWantToLoad = false;
-#else
- FrontEndMenuManager.m_bWantToLoad = false;
-#endif
+ WANT_TO_LOAD = false;
CTimer::Update();
-#ifdef PS2
- while (!(FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad))
-#else
- while (!(FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad))
-#endif
+ while (!(FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD))
{
CSprite2d::InitPerFrame();
CFont::InitPerFrame();
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(12));
-#endif
- CPointLights::NumLights = 0;
+ PUSH_MEMID(MEMID_GAME_PROCESS)
+ CPointLights::InitPerFrame();
CGame::Process();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
DMAudio.Service();
if (CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing())
{
-#ifdef PS2
- TheMemoryCard.m_bWantToLoad = false;
-#else
- FrontEndMenuManager.m_bWantToLoad = false;
-#endif
+ WANT_TO_LOAD = false;
FrontEndMenuManager.m_bWantToRestart = true;
break;
}
-#ifdef PS2
- if (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
-#endif
+ if (FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)
break;
SetLightsWithTimeOfDayColour(Scene.world);
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(15));
-#endif
+
+ PUSH_MEMID(MEMID_RENDER);
if (!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu == true && TheCamera.GetScreenFadeStatus() != FADE_2 )
{
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(11));
-#endif
+
+ PUSH_MEMID(MEMID_RENDERLIST);
CRenderer::ConstructRenderList();
CRenderer::PreRender();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
if (CWeather::LightningFlash && !CCullZones::CamNoRain())
DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255);
@@ -1528,15 +1712,9 @@ void TheGame(void)
RenderMenus();
-#ifdef PS2
- if (TheMemoryCard.m_bWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToLoad)
-#endif
+ if (WANT_TO_LOAD)
{
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID(); // MEMID_RENDER
break;
}
@@ -1553,9 +1731,7 @@ void TheGame(void)
CTimer::Update();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID(): // MEMID_RENDER
if (g_SlowMode)
ProcessSlowMode();
@@ -1567,24 +1743,12 @@ void TheGame(void)
CGame::ShutDownForRestart();
CTimer::Stop();
-#ifdef PS2
- if (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
-#else
- if (FrontEndMenuManager.m_bWantToRestart || b_FoundRecentSavedGameWantToLoad)
-#endif
+ if (FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)
{
-#ifdef PS2
- if (TheMemoryCard.b_FoundRecentSavedGameWantToLoad)
-#else
- if (b_FoundRecentSavedGameWantToLoad)
-#endif
+ if (FOUND_GAME_TO_LOAD)
{
FrontEndMenuManager.m_bWantToRestart = true;
-#ifdef PS2
- TheMemoryCard.m_bWantToLoad = true;
-#else
- FrontEndMenuManager.m_bWantToLoad = true;
-#endif
+ WANT_TO_LOAD = true;
}
CGame::InitialiseWhenRestarting();
@@ -1607,7 +1771,7 @@ void SystemInit()
mwInit();
#endif
-#ifdef GTA_PS2
+#ifdef USE_CUSTOM_ALLOCATOR
InitMemoryMgr();
#endif
@@ -1637,7 +1801,7 @@ void SystemInit()
#ifdef GTA_PS2
CFileMgr::InitCd();
- Char modulepath[256];
+ char modulepath[256];
strcpy(modulepath, "cdrom0:\\");
strcat(modulepath, "SYSTEM\\");
@@ -1724,7 +1888,7 @@ void SystemInit()
//
#endif
-#ifdef PS2
+#ifdef GTA_PS2
TheMemoryCard.Init();
#endif
}
@@ -1753,7 +1917,7 @@ void GameInit()
#endif
CdStreamInit(MAX_CDCHANNELS);
-#ifdef PS2
+#ifdef GTA_PS2
Initialise3D(); //no params
#else
//TODO
@@ -1860,21 +2024,18 @@ void GameInit()
CreateDebugFont();
#ifdef GTA_PS2
- AddIntcHandler(_TODOCONST(2), VBlankCounter, 0);
+ AddIntcHandler(INTC_VBLANK_S, VBlankCounter, 0);
#endif
CameraSize(Scene.camera, NULL, DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
CSprite2d::SetRecipNearClip();
CTxdStore::Initialise();
-#ifdef GTA_PS2
- gMainHeap.PushMemId(_TODOCONST(9));
-#endif
+
+ PUSH_MEMID(MEMID_TEXTURES);
CFont::Initialise();
CHud::Initialise();
-#ifdef GTA_PS2
- gMainHeap.PopMemId();
-#endif
+ POP_MEMID();
ValidateVersion();
@@ -1902,11 +2063,10 @@ main(int argc, char *argv[])
SystemInit();
-#ifdef PS2
+#ifdef GTA_PS2
int32 r = TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE);
- if ( r == CMemoryCard::ERR_DIRNOENTRY || r == CMemoryCard::ERR_NOFORMAT
- && r != CMemoryCard::ERR_OPENNOENTRY && r != CMemoryCard::ERR_NONE )
+ if ( r == CMemoryCard::ERR_DIRNOENTRY || r == CMemoryCard::ERR_NOFORMAT )
{
GameInit();
@@ -1916,6 +2076,8 @@ main(int argc, char *argv[])
CFont::Initialise();
FrontEndMenuManager.DrawMemoryCardStartUpMenus();
+ }else if(r == CMemoryCard::ERR_OPENNOENTRY || r == CMemoryCard::ERR_NONE){
+ // eh?
}
#endif
@@ -1926,12 +2088,18 @@ main(int argc, char *argv[])
InitMPEGPlayer();
+#ifdef GTA_PAL
PlayMPEG("cdrom0:\\MOVIES\\DMAPAL.PSS;1", false);
if (CGame::frenchGame || CGame::germanGame)
PlayMPEG("cdrom0:\\MOVIES\\INTROPAF.PSS;1", true);
else
PlayMPEG("cdrom0:\\MOVIES\\INTROPAL.PSS;1", true);
+#else
+ PlayMPEG("cdrom0:\\MOVIES\\DMANTSC.PSS;1", false);
+
+ PlayMPEG("cdrom0:\\MOVIES\\INTRNTSC.PSS;1", true);
+#endif
ShutdownMPEGPlayer();
diff --git a/src/core/main.h b/src/core/main.h
index 13fff447..77fac46a 100644
--- a/src/core/main.h
+++ b/src/core/main.h
@@ -20,6 +20,10 @@ extern bool gbShowTimebars;
#define gbShowTimebars false
#endif
+#ifndef FINAL
+extern bool gbPrintMemoryUsage;
+#endif
+
class CSprite2d;
bool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);
diff --git a/src/core/re3.cpp b/src/core/re3.cpp
index a06762f5..5974175a 100644
--- a/src/core/re3.cpp
+++ b/src/core/re3.cpp
@@ -1,7 +1,6 @@
#include <csignal>
#define WITHWINDOWS
#include "common.h"
-#include "platform.h"
#include "crossplatform.h"
#include "Renderer.h"
#include "Credits.h"
@@ -16,7 +15,6 @@
#include "Boat.h"
#include "Heli.h"
#include "Automobile.h"
-#include "Ped.h"
#include "Console.h"
#include "Debug.h"
#include "Hud.h"
@@ -26,12 +24,12 @@
#include "Radar.h"
#include "debugmenu.h"
#include "Frontend.h"
-#include "Text.h"
#include "WaterLevel.h"
#include "main.h"
-#include "MBlur.h"
+#include "Script.h"
#include "postfx.h"
#include "custompipes.h"
+#include "MemoryHeap.h"
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
#include "FileMgr.h"
@@ -76,388 +74,61 @@ mysrand(unsigned int seed)
#ifdef CUSTOM_FRONTEND_OPTIONS
#include "frontendoption.h"
-#include "Font.h"
-void ReloadFrontendOptions(void)
+void
+CustomFrontendOptionsPopulate(void)
{
- CustomFrontendOptionsPopulate();
-}
-
-void RestoreDefGraphics(int8 action) {
- if (action != FEOPTION_ACTION_SELECT)
- return;
-
- #ifdef PS2_ALPHA_TEST
- gPS2alphaTest = false;
- #endif
- #ifdef MULTISAMPLING
- FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0;
- #endif
- #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those
- CMenuManager::m_PrefsFrameLimiter = true;
- CMenuManager::m_PrefsVsyncDisp = true;
- CMenuManager::m_PrefsVsync = true;
- CMenuManager::m_PrefsUseWideScreen = false;
- FrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode;
- #ifdef GTA3_1_1_PATCH
- if (_dwOperatingSystemVersion == OS_WIN98) {
- CMBlur::BlurOn = false;
- CMBlur::MotionBlurClose();
- } else {
- CMBlur::BlurOn = true;
- CMBlur::MotionBlurOpen(Scene.camera);
- }
- #else
- CMBlur::BlurOn = true;
- #endif
- FrontEndMenuManager.SaveSettings();
- #endif
-}
-
-void RestoreDefDisplay(int8 action) {
- if (action != FEOPTION_ACTION_SELECT)
- return;
-
- #ifdef CUTSCENE_BORDERS_SWITCH
- CMenuManager::m_PrefsCutsceneBorders = true;
- #endif
- #ifdef FREE_CAM
- TheCamera.bFreeCam = false;
- #endif
- #ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those
- CMenuManager::m_PrefsBrightness = 256;
- CMenuManager::m_PrefsLOD = 1.2f;
- CRenderer::ms_lodDistScale = 1.2f;
- CMenuManager::m_PrefsShowSubtitles = true;
- FrontEndMenuManager.SaveSettings();
- #endif
-}
-
-#ifdef MULTISAMPLING
-void MultiSamplingGoBack() {
- FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
-}
-
-void MultiSamplingButtonPress(int8 action) {
- if (action == FEOPTION_ACTION_SELECT) {
- if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
- FrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel;
- _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode);
- FrontEndMenuManager.SetHelperText(0);
- FrontEndMenuManager.SaveSettings();
- }
- } else if (action == FEOPTION_ACTION_LEFT || action == FEOPTION_ACTION_RIGHT) {
- if (FrontEndMenuManager.m_bGameNotLoaded) {
- FrontEndMenuManager.m_nDisplayMSAALevel += (action == FEOPTION_ACTION_RIGHT ? 1 : -1);
-
- int i = 0;
- int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels();
- while (maxAA != 1) {
- i++;
- maxAA >>= 1;
- }
-
- if (FrontEndMenuManager.m_nDisplayMSAALevel < 0)
- FrontEndMenuManager.m_nDisplayMSAALevel = i;
- else if (FrontEndMenuManager.m_nDisplayMSAALevel > i)
- FrontEndMenuManager.m_nDisplayMSAALevel = 0;
- }
- } else if (action == FEOPTION_ACTION_FOCUSLOSS) {
- if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
- FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
- FrontEndMenuManager.SetHelperText(3);
- }
- }
-}
-
-wchar* MultiSamplingDraw(bool *disabled, bool userHovering) {
- static wchar unicodeTemp[64];
- if (userHovering) {
- if (FrontEndMenuManager.m_nDisplayMSAALevel == FrontEndMenuManager.m_nPrefsMSAALevel) {
- if (FrontEndMenuManager.m_nHelperTextMsgId == 1) // Press enter to apply
- FrontEndMenuManager.ResetHelperText();
- } else {
- FrontEndMenuManager.SetHelperText(1);
- }
- } else {
- if (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {
- FrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;
- }
- }
-
- if (!FrontEndMenuManager.m_bGameNotLoaded)
- *disabled = true;
-
- switch (FrontEndMenuManager.m_nDisplayMSAALevel) {
- case 0:
- return TheText.Get("FEM_OFF");
- default:
- sprintf(gString, "%iX", 1 << (FrontEndMenuManager.m_nDisplayMSAALevel));
- AsciiToUnicode(gString, unicodeTemp);
- return unicodeTemp;
- }
+ // Moved to an array in MenuScreensCustom.cpp, but APIs are still available. see frontendoption.h
}
-const char* multisamplingKey = "MultiSampling";
#endif
-#ifdef MORE_LANGUAGES
-void LangPolSelect(int8 action)
-{
- if (action == FEOPTION_ACTION_SELECT) {
- FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_POLISH;
- FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
- FrontEndMenuManager.InitialiseChangedLanguageSettings();
- FrontEndMenuManager.SaveSettings();
- }
-}
-
-void LangRusSelect(int8 action)
-{
- if (action == FEOPTION_ACTION_SELECT) {
- FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_RUSSIAN;
- FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
- FrontEndMenuManager.InitialiseChangedLanguageSettings();
- FrontEndMenuManager.SaveSettings();
- }
-}
+#ifdef LOAD_INI_SETTINGS
+#include "ini_parser.hpp"
-void LangJapSelect(int8 action)
+linb::ini cfg;
+int CheckAndReadIniInt(const char *cat, const char *key, int original)
{
- if (action == FEOPTION_ACTION_SELECT) {
- FrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_JAPANESE;
- FrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;
- FrontEndMenuManager.InitialiseChangedLanguageSettings();
- FrontEndMenuManager.SaveSettings();
- }
-}
-#endif
+ std::string strval = cfg.get(cat, key, "");
+ const char *value = strval.c_str();
+ if (value && value[0] != '\0')
+ return atoi(value);
-#ifdef IMPROVED_VIDEOMODE
-void ScreenModeChange(int8 displayedValue)
-{
- if (displayedValue != FrontEndMenuManager.m_nPrefsWindowed) {
- FrontEndMenuManager.m_nPrefsWindowed = displayedValue;
- _psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); // apply same resolution
- FrontEndMenuManager.SetHelperText(0);
- FrontEndMenuManager.SaveSettings();
- }
+ return original;
}
-#endif
-#ifdef FREE_CAM
-void FreeCamChange(int8 displayedValue)
+float CheckAndReadIniFloat(const char *cat, const char *key, float original)
{
- TheCamera.bFreeCam = !!displayedValue;
- FrontEndMenuManager.SaveSettings();
-}
-const char* freeCamKey = "FreeCam";
-#endif
+ std::string strval = cfg.get(cat, key, "");
+ const char *value = strval.c_str();
+ if (value && value[0] != '\0')
+ return atof(value);
-#ifdef CUTSCENE_BORDERS_SWITCH
-void BorderModeChange(int8 displayedValue)
-{
- CMenuManager::m_PrefsCutsceneBorders = !!displayedValue;
- FrontEndMenuManager.SaveSettings();
+ return original;
}
-const char* cutsceneBordersKey = "CutsceneBorders";
-#endif
-#ifdef PS2_ALPHA_TEST
-void PS2AlphaTestChange(int8 displayedValue)
+void CheckAndSaveIniInt(const char *cat, const char *key, int val, bool &changed)
{
- gPS2alphaTest = !!displayedValue;
- FrontEndMenuManager.SaveSettings();
-}
-const char* ps2alphaKey = "PS2AlphaTest";
-#endif
-
-#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
-wchar selectedJoystickUnicode[128];
-
-wchar* DetectJoystickDraw(bool* disabled, bool userHovering) {
- int numButtons;
- int found = -1;
- const char *joyname;
- if (userHovering) {
- for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) {
- if ((joyname = glfwGetJoystickName(i))) {
- const uint8* buttons = glfwGetJoystickButtons(i, &numButtons);
- for (int j = 0; j < numButtons; j++) {
- if (buttons[j]) {
- found = i;
- break;
- }
- }
- if (found != -1)
- break;
- }
- }
-
- if (found != -1 && PSGLOBAL(joy1id) != found) {
- if (PSGLOBAL(joy1id) != -1 && PSGLOBAL(joy1id) != found)
- PSGLOBAL(joy2id) = PSGLOBAL(joy1id);
- else
- PSGLOBAL(joy2id) = -1;
-
- strcpy(gSelectedJoystickName, joyname);
- PSGLOBAL(joy1id) = found;
- }
+ char temp[10];
+ if (atoi(cfg.get(cat, key, "xxx").c_str()) != val) { // if .ini doesn't have our key, compare with xxx and forcefully add it
+ changed = true;
+ sprintf(temp, "%u", val);
+ cfg.set(cat, key, temp);
}
- if (PSGLOBAL(joy1id) == -1)
- AsciiToUnicode("Not found", selectedJoystickUnicode);
- else
- AsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode);
-
- return selectedJoystickUnicode;
}
-#endif
-// Important: Make sure to read the warnings/informations in frontendoption.h!!
-// If you will hardcode any text, please use AllocUnicode! wchar_t size differs between platforms
-void
-CustomFrontendOptionsPopulate(void)
+void CheckAndSaveIniFloat(const char *cat, const char *key, float val, bool &changed)
{
- RemoveCustomFrontendOptions(); // if exist
-
- // -- Graphics/display seperation preperation starts - don't add options in here!
-#ifdef GRAPHICS_MENU_OPTIONS
- int graphicsMenu = FrontendScreenAdd("FET_GRA", MENUSPRITE_MAINMENU, MENUPAGE_OPTIONS, 50, 0, 20,
- FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true);
-
- int newDisplayMenu = FrontendScreenAdd("FET_DIS", MENUSPRITE_MAINMENU, MENUPAGE_OPTIONS, 50, 0, 20,
- FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true);
-
- FrontendOptionSetCursor(MENUPAGE_OPTIONS, 2, true);
- FrontendOptionAddRedirect(TheText.Get("FET_DIS"), newDisplayMenu, 0);
- FrontendOptionSetCursor(MENUPAGE_OPTIONS, 3);
- FrontendOptionAddRedirect(TheText.Get("FET_GRA"), graphicsMenu, 0);
-
-#define SWITCH_TO_GRAPHICS_MENU FrontendOptionSetCursor(graphicsMenu, -1);
-#define SWITCH_TO_DISPLAY_MENU FrontendOptionSetCursor(newDisplayMenu, -1);
-#define CLONE_OPTION(a, b, c, d) FrontendOptionAddBuiltinAction(a, b, c, d);
-#define ADD_BACK FrontendOptionAddBackButton(TheText.Get("FEDS_TB"));
-#define ADD_RESTORE_DEFAULTS(a) FrontendOptionAddDynamic(TheText.Get("FET_DEF"), nil, nil, a, nil);
-#else
- int advancedDisplayMenu = FrontendScreenAdd("FET_ADV", MENUSPRITE_MAINMENU, MENUPAGE_DISPLAY_SETTINGS, 50, 0, 20,
- FONT_HEADING, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, true);
- bool movedToAdvMenu = false;
-
-#define SWITCH_TO_GRAPHICS_MENU \
- if (GetNumberOfMenuOptions(MENUPAGE_DISPLAY_SETTINGS) >= 12) { \
- FrontendOptionSetCursor(advancedDisplayMenu, -1); \
- movedToAdvMenu = true; \
- } else { \
- FrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3); \
- }
-
-#define SWITCH_TO_DISPLAY_MENU SWITCH_TO_GRAPHICS_MENU
-#define CLONE_OPTION(a, b, c, d)
-#define ADD_BACK
-#define ADD_RESTORE_DEFAULTS(a)
-#endif
- // -- Graphics/display seperation preperation end
-
- const wchar* off_on[] = { TheText.Get("FEM_OFF"), TheText.Get("FEM_ON") };
-
-#ifdef MORE_LANGUAGES
- FrontendOptionSetCursor(MENUPAGE_LANGUAGE_SETTINGS, -2);
- FrontendOptionAddDynamic(TheText.Get("FEL_POL"), nil, nil, LangPolSelect, nil);
- FrontendOptionAddDynamic(TheText.Get("FEL_RUS"), nil, nil, LangRusSelect, nil);
- FrontendOptionAddDynamic(TheText.Get("FEL_JAP"), nil, nil, LangJapSelect, nil);
-#endif
-
-#ifdef MENU_MAP
- FrontendOptionSetCursor(MENUPAGE_PAUSE_MENU, 2);
- FrontendOptionAddRedirect(TheText.Get("FEG_MAP"), MENUPAGE_MAP);
-#endif
-
- // -- Start of graphics menu - add options in display order!
-
- SWITCH_TO_GRAPHICS_MENU
- CLONE_OPTION(TheText.Get("FED_RES"), MENUACTION_SCREENRES, nil, nil);
- CLONE_OPTION(TheText.Get("FED_WIS"), MENUACTION_WIDESCREEN, nil, nil)
-
-#ifdef IMPROVED_VIDEOMODE
- const wchar* screenModes[] = { TheText.Get("FED_FLS"), TheText.Get("FED_WND") };
- // Storing isn't enabled because it's handled in Frontend
- FrontendOptionAddSelect(TheText.Get("FEM_SCF"), screenModes, 2, (int8*)&FrontEndMenuManager.m_nPrefsWindowed, true, ScreenModeChange, nil);
-#endif
-
- CLONE_OPTION(TheText.Get("FEM_VSC"), MENUACTION_FRAMESYNC, nil, nil);
- CLONE_OPTION(TheText.Get("FEM_FRM"), MENUACTION_FRAMELIMIT, nil, nil);
-
-#ifdef MULTISAMPLING
- SWITCH_TO_GRAPHICS_MENU
- FrontendOptionAddDynamic(TheText.Get("FED_AAS"), MultiSamplingDraw, (int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, MultiSamplingButtonPress, MultiSamplingGoBack, multisamplingKey);
-#endif
-
- CLONE_OPTION(TheText.Get("FED_TRA"), MENUACTION_TRAILS, nil, nil);
-
-#ifdef PS2_ALPHA_TEST
- SWITCH_TO_GRAPHICS_MENU
- FrontendOptionAddSelect(TheText.Get("FEM_2PR"), off_on, 2, (int8*)&gPS2alphaTest, false, PS2AlphaTestChange, nil, ps2alphaKey);
-#endif
-
- ADD_RESTORE_DEFAULTS(RestoreDefGraphics)
- ADD_BACK
-
- // ---- End of Graphics Menu ----
-
- // -- Start of Display menu - add options in display order!
-
- SWITCH_TO_DISPLAY_MENU
- CLONE_OPTION(TheText.Get("FED_BRI"), MENUACTION_BRIGHTNESS, nil, nil);
- CLONE_OPTION(TheText.Get("FEM_LOD"), MENUACTION_DRAWDIST, nil, nil);
-
-#ifdef CUTSCENE_BORDERS_SWITCH
- SWITCH_TO_DISPLAY_MENU
- FrontendOptionAddSelect(TheText.Get("FEM_CSB"), off_on, 2, (int8 *)&CMenuManager::m_PrefsCutsceneBorders, false, BorderModeChange, nil, cutsceneBordersKey);
-#endif
-
-#ifdef FREE_CAM
- SWITCH_TO_DISPLAY_MENU
- FrontendOptionAddSelect(TheText.Get("FEC_FRC"), off_on, 2, (int8*)&TheCamera.bFreeCam, false, FreeCamChange, nil, freeCamKey);
-#endif
-
- CLONE_OPTION(TheText.Get("FED_SUB"), MENUACTION_SUBTITLES, nil, nil);
-
- // Add link to advanced graphics menu if it's filled.
-#ifndef GRAPHICS_MENU_OPTIONS
- if (movedToAdvMenu) {
- FrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3);
- FrontendOptionAddRedirect(TheText.Get("FET_ADV"), advancedDisplayMenu, 0);
-
- FrontendOptionSetCursor(advancedDisplayMenu, -1);
- FrontendOptionAddBackButton(TheText.Get("FEDS_TB"));
+ char temp[10];
+ if (atof(cfg.get(cat, key, "xxx").c_str()) != val) { // if .ini doesn't have our key, compare with xxx and forcefully add it
+ changed = true;
+ sprintf(temp, "%f", val);
+ cfg.set(cat, key, temp);
}
-#endif
-
- ADD_RESTORE_DEFAULTS(RestoreDefDisplay)
- ADD_BACK
-
-#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
- int detectJoystickMenu = FrontendScreenAdd("FEC_JOD", MENUSPRITE_MAINMENU, MENUPAGE_CONTROLLER_PC, 40, 60, 20,
- FONT_BANK, MEDIUMTEXT_X_SCALE, MEDIUMTEXT_Y_SCALE, FESCREEN_LEFT_ALIGN, false);
-
- FrontendOptionSetCursor(detectJoystickMenu, 0);
-
- FrontendOptionAddBuiltinAction(TheText.Get("FEC_JPR"), MENUACTION_LABEL, nil, nil);
- FrontendOptionAddDynamic(TheText.Get("FEC_JDE"), DetectJoystickDraw, nil, nil, nil);
- FrontendOptionAddBackButton(TheText.Get("FEDS_TB"));
-
- FrontendOptionSetCursor(MENUPAGE_CONTROLLER_PC, 2);
- FrontendOptionAddRedirect(TheText.Get("FEC_JOD"), detectJoystickMenu, 1);
-#endif
}
-#endif
-#ifdef LOAD_INI_SETTINGS
-#include "ini_parser.hpp"
void LoadINISettings()
{
- linb::ini cfg;
cfg.load_file("re3.ini");
- char defaultStr[4];
#ifdef DONT_TRUST_RECOGNIZED_JOYSTICKS
// Written by assuming the codes below will run after _InputInitialiseJoys().
@@ -491,28 +162,38 @@ void LoadINISettings()
#endif
#ifdef CUSTOM_FRONTEND_OPTIONS
- for (int i = 0; i < numCustomFrontendOptions; i++) {
- FrontendOption& option = customFrontendOptions[i];
- if (option.save) {
- // CFO only supports saving uint8 right now
- sprintf(defaultStr, "%u", *option.value);
- option.lastSavedValue = option.displayedValue = *option.value = atoi(cfg.get("FrontendOptions", option.save, defaultStr).c_str());
+ for (int i = 0; i < MENUPAGES; i++) {
+ for (int j = 0; j < NUM_MENUROWS; j++) {
+ CMenuScreenCustom::CMenuEntry &option = aScreens[i].m_aEntries[j];
+ if (option.m_Action == MENUACTION_NOTHING)
+ break;
+
+ // CFO check
+ if (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) {
+ // CFO only supports saving uint8 right now
+ *option.m_CFO->value = CheckAndReadIniInt("FrontendOptions", option.m_CFO->save, *option.m_CFO->value);
+ if (option.m_Action == MENUACTION_CFO_SELECT) {
+ option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue = *option.m_CFO->value;
+ }
+ }
}
}
#endif
-#ifdef NO_ISLAND_LOADING
- sprintf(defaultStr, "%u", CMenuManager::m_PrefsIslandLoading);
- CMenuManager::m_PrefsIslandLoading = atoi(cfg.get("FrontendOptions", "NoIslandLoading", defaultStr).c_str());
- CMenuManager::m_DisplayIslandLoading = CMenuManager::m_PrefsIslandLoading;
+#ifdef EXTENDED_COLOURFILTER
+ CPostFX::Intensity = CheckAndReadIniFloat("CustomPipesValues", "PostFXIntensity", CPostFX::Intensity);
+#endif
+#ifdef EXTENDED_PIPELINES
+ CustomPipes::VehicleShininess = CheckAndReadIniFloat("CustomPipesValues", "NeoVehicleShininess", CustomPipes::VehicleShininess);
+ CustomPipes::VehicleSpecularity = CheckAndReadIniFloat("CustomPipesValues", "NeoVehicleSpecularity", CustomPipes::VehicleSpecularity);
+ CustomPipes::RimlightMult = CheckAndReadIniFloat("CustomPipesValues", "RimlightMult", CustomPipes::RimlightMult);
+ CustomPipes::LightmapMult = CheckAndReadIniFloat("CustomPipesValues", "LightmapMult", CustomPipes::LightmapMult);
+ CustomPipes::GlossMult = CheckAndReadIniFloat("CustomPipesValues", "GlossMult", CustomPipes::GlossMult);
#endif
-
}
void SaveINISettings()
{
- linb::ini cfg;
- cfg.load_file("re3.ini");
bool changed = false;
char temp[4];
@@ -523,23 +204,29 @@ void SaveINISettings()
}
#endif
#ifdef CUSTOM_FRONTEND_OPTIONS
- for (int i = 0; i < numCustomFrontendOptions; i++) {
- FrontendOption &option = customFrontendOptions[i];
- if (option.save) {
- if (atoi(cfg.get("FrontendOptions", option.save, "xxx").c_str()) != *option.value) { // if .ini doesn't have that key compare with xxx, so we can add it
- changed = true;
- sprintf(temp, "%u", *option.value);
- cfg.set("FrontendOptions", option.save, temp);
+ for (int i = 0; i < MENUPAGES; i++) {
+ for (int j = 0; j < NUM_MENUROWS; j++) {
+ CMenuScreenCustom::CMenuEntry &option = aScreens[i].m_aEntries[j];
+ if (option.m_Action == MENUACTION_NOTHING)
+ break;
+
+ if (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) {
+ // Beware: CFO only supports saving uint8 right now
+ CheckAndSaveIniInt("FrontendOptions", option.m_CFO->save, *option.m_CFO->value, changed);
}
}
}
#endif
-#ifdef NO_ISLAND_LOADING
- if (atoi(cfg.get("FrontendOptions", "NoIslandLoading", "xxx").c_str()) != CMenuManager::m_PrefsIslandLoading) {
- changed = true;
- sprintf(temp, "%u", CMenuManager::m_PrefsIslandLoading);
- cfg.set("FrontendOptions", "NoIslandLoading", temp);
- }
+
+#ifdef EXTENDED_COLOURFILTER
+ CheckAndSaveIniFloat("CustomPipesValues", "PostFXIntensity", CPostFX::Intensity, changed);
+#endif
+#ifdef EXTENDED_PIPELINES
+ CheckAndSaveIniFloat("CustomPipesValues", "NeoVehicleShininess", CustomPipes::VehicleShininess, changed);
+ CheckAndSaveIniFloat("CustomPipesValues", "NeoVehicleSpecularity", CustomPipes::VehicleSpecularity, changed);
+ CheckAndSaveIniFloat("CustomPipesValues", "RimlightMult", CustomPipes::RimlightMult, changed);
+ CheckAndSaveIniFloat("CustomPipesValues", "LightmapMult", CustomPipes::LightmapMult, changed);
+ CheckAndSaveIniFloat("CustomPipesValues", "GlossMult", CustomPipes::GlossMult, changed);
#endif
if (changed)
@@ -688,6 +375,19 @@ ResetCamStatics(void)
TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true;
}
+#ifdef MISSION_SWITCHER
+int8 nextMissionToSwitch = 0;
+static void
+SwitchToMission(void)
+{
+ CTheScripts::SwitchToMission(nextMissionToSwitch);
+}
+#endif
+
+#ifdef USE_CUSTOM_ALLOCATOR
+static void ParseHeap(void) { gMainHeap.ParseHeap(); }
+#endif
+
static const char *carnames[] = {
"landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "patriot", "firetruk", "trash", "stretch", "manana", "infernus", "blista", "pony",
"mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "kuruma", "bobcat", "mrwhoop", "bfinject", "corpse", "police", "enforcer",
@@ -870,8 +570,19 @@ DebugMenuPopulate(void)
DebugMenuAddVarBool8("Render", "Don't render Objects", &gbDontRenderObjects, nil);
DebugMenuAddVarBool8("Render", "Don't Render Water", &gbDontRenderWater, nil);
+#ifndef FINAL
+ DebugMenuAddVarBool8("Debug", "Print Memory Usage", &gbPrintMemoryUsage, nil);
+#ifdef USE_CUSTOM_ALLOCATOR
+ DebugMenuAddCmd("Debug", "Parse Heap", ParseHeap);
+#endif
+#endif
+ DebugMenuAddVarBool8("Debug", "Show cullzone debug stuff", &gbShowCullZoneDebugStuff, nil);
+ DebugMenuAddVarBool8("Debug", "Disable zone cull", &gbDisableZoneCull, nil);
+
DebugMenuAddVarBool8("Debug", "pad 1 -> pad 2", &CPad::m_bMapPadOneToPadTwo, nil);
+#ifdef GTA_SCENE_EDIT
DebugMenuAddVarBool8("Debug", "Edit on", &CSceneEdit::m_bEditOn, nil);
+#endif
#ifdef MENU_MAP
DebugMenuAddCmd("Debug", "Teleport to map waypoint", TeleportToWaypoint);
#endif
@@ -888,9 +599,6 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Debug", "Catalina Fly Away", CHeli::MakeCatalinaHeliFlyAway);
DebugMenuAddVarBool8("Debug", "Script Heli On", &CHeli::ScriptHeliOn, nil);
-#ifdef CUSTOM_FRONTEND_OPTIONS
- DebugMenuAddCmd("Debug", "Reload custom frontend options", ReloadFrontendOptions);
-#endif
DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", &CPed::bPopHeadsOnHeadshot, nil);
DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start);
DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop);
@@ -899,6 +607,29 @@ DebugMenuPopulate(void)
#ifdef TIMEBARS
DebugMenuAddVarBool8("Debug", "Show Timebars", &gbShowTimebars, nil);
#endif
+#ifdef MISSION_SWITCHER
+ DebugMenuEntry *missionEntry;
+ static const char* missions[] = {
+ "Intro Movie", "Hospital Info Scene", "Police Station Info Scene",
+ "RC Diablo Destruction", "RC Mafia Massacre", "RC Rumpo Rampage", "RC Casino Calamity",
+ "Patriot Playground", "A Ride In The Park", "Gripped!", "Multistorey Mayhem",
+ "Paramedic", "Firefighter", "Vigilante", "Taxi Driver",
+ "The Crook", "The Thieves", "The Wife", "Her Lover",
+ "Give Me Liberty and Luigi's Girls", "Don't Spank My Bitch Up", "Drive Misty For Me", "Pump-Action Pimp", "The Fuzz Ball",
+ "Mike Lips Last Lunch", "Farewell 'Chunky' Lee Chong", "Van Heist", "Cipriani's Chauffeur", "Dead Skunk In The Trunk", "The Getaway",
+ "Taking Out The Laundry", "The Pick-Up", "Salvatore's Called A Meeting", "Triads And Tribulations", "Blow Fish", "Chaperone", "Cutting The Grass",
+ "Bomb Da Base: Act I", "Bomb Da Base: Act II", "Last Requests", "Turismo", "I Scream, You Scream", "Trial By Fire", "Big'N'Veiny", "Sayonara Salvatore",
+ "Under Surveillance", "Paparazzi Purge", "Payday For Ray", "Two-Faced Tanner", "Kanbu Bust-Out", "Grand Theft Auto", "Deal Steal", "Shima", "Smack Down",
+ "Silence The Sneak", "Arms Shortage", "Evidence Dash", "Gone Fishing", "Plaster Blaster", "Marked Man",
+ "Liberator", "Waka-Gashira Wipeout!", "A Drop In The Ocean", "Bling-Bling Scramble", "Uzi Rider", "Gangcar Round-Up", "Kingdom Come",
+ "Grand Theft Aero", "Escort Service", "Decoy", "Love's Disappearance", "Bait", "Espresso-2-Go!", "S.A.M.",
+ "Uzi Money", "Toyminator", "Rigged To Blow", "Bullion Run", "Rumble", "The Exchange"
+ };
+
+ missionEntry = DebugMenuAddVar("Debug", "Select mission", &nextMissionToSwitch, nil, 1, 0, 79, missions);
+ DebugMenuEntrySetWrap(missionEntry, true);
+ DebugMenuAddCmd("Debug", "Start selected mission ", SwitchToMission);
+#endif
extern bool PrintDebugCode;
extern int16 DebugCamMode;
diff --git a/src/core/templates.h b/src/core/templates.h
index 4f7b8490..166f865c 100644
--- a/src/core/templates.h
+++ b/src/core/templates.h
@@ -46,8 +46,8 @@ class CPool
public:
CPool(int size){
// TODO: use new here
- m_entries = (U*)malloc(sizeof(U)*size);
- m_flags = (Flags*)malloc(sizeof(Flags)*size);
+ m_entries = (U*)new uint8[sizeof(U)*size];
+ m_flags = (Flags*)new uint8[sizeof(Flags)*size];
m_size = size;
m_allocPtr = 0;
for(int i = 0; i < size; i++){
@@ -61,8 +61,8 @@ public:
}
void Flush() {
if (m_size > 0) {
- free(m_entries);
- free(m_flags);
+ delete[] (uint8*)m_entries;
+ delete[] (uint8*)m_flags;
m_entries = nil;
m_flags = nil;
m_size = 0;
@@ -124,12 +124,18 @@ public:
(T*)&m_entries[handle >> 8] : nil;
}
int GetIndex(T *entry){
- int i = GetJustIndex(entry);
+ int i = GetJustIndex_NoFreeAssert(entry);
return m_flags[i].u + (i<<8);
}
int GetJustIndex(T *entry){
- // TODO: the cast is unsafe
- return (int)((U*)entry - m_entries);
+ int index = GetJustIndex_NoFreeAssert(entry);
+ assert(!IsFreeSlot(index));
+ return index;
+ }
+ int GetJustIndex_NoFreeAssert(T* entry){
+ int index = ((U*)entry - m_entries);
+ assert((U*)entry == (U*)&m_entries[index]); // cast is unsafe - check required
+ return index;
}
int GetNoOfUsedSpaces(void) const{
int i;
@@ -141,8 +147,8 @@ public:
}
bool IsFreeSlot(int i) { return !!m_flags[i].free; }
void ClearStorage(uint8 *&flags, U *&entries){
- free(flags);
- free(entries);
+ delete[] (uint8*)flags;
+ delete[] (uint8*)entries;
flags = nil;
entries = nil;
}
@@ -156,8 +162,8 @@ public:
debug("CopyBack:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */
}
void Store(uint8 *&flags, U *&entries){
- flags = (uint8*)malloc(sizeof(uint8)*m_size);
- entries = (U*)malloc(sizeof(U)*m_size);
+ flags = (uint8*)new uint8[sizeof(uint8)*m_size];
+ entries = (U*)new uint8[sizeof(U)*m_size];
memcpy(flags, m_flags, sizeof(uint8)*m_size);
memcpy(entries, m_entries, sizeof(U)*m_size);
debug("Stored:%d (/%d)\n", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */
diff --git a/src/core/vu0Collision.dsm b/src/core/vu0Collision.dsm
deleted file mode 100644
index 657c8b81..00000000
--- a/src/core/vu0Collision.dsm
+++ /dev/null
@@ -1,21 +0,0 @@
-.align 4
-.global Vu0CollisionDmaTag
-Vu0CollisionDmaTag:
-DMAcnt *
-MPG 0, *
-.vu
-.include "vu0Collision_1.s"
-.EndMPG
-.EndDmaData
-DMAend
-
-.global Vu0Collision2DmaTag
-Vu0Collision2DmaTag:
-DMAcnt *
-MPG 0, *
-.vu
-.include "vu0Collision_2.s"
-.EndMPG
-.EndDmaData
-DMAend
-.end
diff --git a/src/core/vu0Collision_1.s b/src/core/vu0Collision_1.s
deleted file mode 100644
index 055c8640..00000000
--- a/src/core/vu0Collision_1.s
+++ /dev/null
@@ -1,610 +0,0 @@
-QuitAndFail:
- NOP[E] IADDIU VI01, VI00, 0
- NOP NOP
-
-
-QuitAndSucceed:
- NOP[E] IADDIU VI01, VI00, 1
- NOP NOP
-
-
-; 20 -- unused
-; VF12, VF13 xyz: sphere centers
-; VF14, VF15 x: sphere radii
-; out:
-; VI01: set when collision
-; VF01: supposed to be intersection point?
-; VF02: normal (pointing towards s1, not normalized)
-.globl Vu0SphereToSphereCollision
-Vu0SphereToSphereCollision:
- SUB.xyz VF02, VF13, VF12 NOP ; dist of centers
- ADD.x VF04, VF14, VF15 NOP ; s = sum of radii
- MUL.xyzw VF03, VF02, VF02 NOP ;
- MUL.x VF04, VF04, VF04 DIV Q, VF14x, VF04x ; square s
- NOP NOP ;
- NOP NOP ;
- MULAx.w ACC, VF00, VF03 NOP ;
- MADDAy.w ACC, VF00, VF03 NOP ;
- MADDz.w VF03, VF00, VF03 NOP ; d = DistSq of centers
- NOP NOP ;
- MULAw.xyz ACC, VF12, VF00 NOP ;
- MADDq.xyz VF01, VF02, Q NOP ; intersection, but wrong
- CLIPw.xyz VF04, VF03 NOP ; compare s and d
- SUB.xyz VF02, VF00, VF02 NOP ; compute normal
- NOP NOP ;
- NOP NOP ;
- NOP FCAND VI01, 0x3 ; 0x2 cannot be set here
- NOP[E] NOP ;
- NOP NOP ;
-
-
-; B8 -- unused
-; VF12:
-; VF13: radius
-; VF14:
-; VF15: box dimensions (?)
-.globl Vu0SphereToAABBCollision
-Vu0SphereToAABBCollision:
- SUB.xyz VF03, VF12, VF14 LOI 0.5
- MULi.xyz VF15, VF15, I NOP
- MUL.x VF13, VF13, VF13 NOP
- SUB.xyz VF04, VF03, VF15 NOP
- ADD.xyz VF05, VF03, VF15 MR32.xyzw VF16, VF15
- CLIPw.xyz VF03, VF16 MR32.xyzw VF17, VF16
- MUL.xyz VF04, VF04, VF04 NOP
- MUL.xyz VF05, VF05, VF05 NOP
- CLIPw.xyz VF03, VF17 MR32.xyzw VF16, VF17
- NOP FCAND VI01, 0x1
- MINI.xyz VF04, VF04, VF05 MFIR.x VF09, VI01
- NOP NOP
- CLIPw.xyz VF03, VF16 FCAND VI01, 0x4
- NOP MFIR.y VF09, VI01
- NOP NOP
- MULAx.w ACC, VF00, VF00 NOP
- ADD.xyz VF01, VF00, VF03 FCAND VI01, 0x10
- NOP MFIR.z VF09, VI01
- NOP LOI 2
- NOP FCAND VI01, 0x30
- SUBAw.xyz ACC, VF00, VF00 IADD VI04, VI00, VI01
- ITOF0.xyz VF09, VF09 FCAND VI01, 0x300
- NOP IADD VI03, VI00, VI01
- NOP FCAND VI01, 0x3000
- NOP IADD VI02, VI00, VI01
- MADDi.xyzw VF09, VF09, I NOP
- NOP IBEQ VI04, VI00, IgnoreZValue
- NOP NOP
- MADDAz.w ACC, VF00, VF04 NOP
- MUL.z VF01, VF09, VF15 NOP
-IgnoreZValue:
- NOP IBEQ VI03, VI00, IgnoreYValue
- NOP NOP
- MADDAy.w ACC, VF00, VF04 NOP
- MUL.y VF01, VF09, VF15 NOP
-IgnoreYValue:
- NOP IBEQ VI02, VI00, IgnoreXValue
- NOP NOP
- MADDAx.w ACC, VF00, VF04 NOP
- MUL.x VF01, VF09, VF15 NOP
-IgnoreXValue:
- MADDx.w VF06, VF00, VF00 NOP
- SUB.xyz VF02, VF03, VF01 NOP
- ADD.xyz VF01, VF01, VF14 NOP
- MULx.w VF01, VF00, VF00 NOP
- CLIPw.xyz VF13, VF06 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0x1
-QuitMicrocode:
- NOP[E] NOP
- NOP NOP
-
-
-; 240
-.globl Vu0LineToSphereCollision
-Vu0LineToSphereCollision:
- SUB.xyzw VF01, VF13, VF12 NOP
- SUB.xyzw VF02, VF14, VF12 NOP
- MUL.xyz VF03, VF01, VF02 NOP
- MUL.xyz VF04, VF01, VF01 NOP
- MUL.x VF15, VF15, VF15 NOP
- MUL.xyz VF02, VF02, VF02 NOP
- MULAx.w ACC, VF00, VF03 NOP
- MADDAy.w ACC, VF00, VF03 NOP
- MADDz.w VF03, VF00, VF03 NOP
- MULAx.w ACC, VF00, VF04 NOP
- MADDAy.w ACC, VF00, VF04 NOP
- MADDz.w VF01, VF00, VF04 NOP
- MULAx.w ACC, VF00, VF02 NOP
- MADDAy.w ACC, VF00, VF02 NOP
- MADDz.w VF02, VF00, VF02 NOP
- MULA.w ACC, VF03, VF03 NOP
- MADDAx.w ACC, VF01, VF15 NOP
- MSUB.w VF05, VF01, VF02 NOP
- NOP NOP
- NOP NOP
- NOP IADDIU VI02, VI00, 0x10
- NOP FMAND VI01, VI02
- NOP IBNE VI01, VI00, QuitAndFail
- NOP NOP
- CLIPw.xyz VF15, VF02 SQRT Q, VF05w
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0x1
- NOP IBNE VI00, VI01, LineStartInsideSphere
- NOP NOP
- SUBq.w VF05, VF03, Q NOP
- SUB.w VF05, VF05, VF01 DIV Q, VF05w, VF01w
- NOP FMAND VI01, VI02
- NOP IBNE VI01, VI00, QuitAndFail
- NOP NOP
- NOP FMAND VI01, VI02
- NOP IBEQ VI01, VI00, QuitAndFail
- NOP NOP
- ADDA.xyz ACC, VF12, VF00 NOP
- MADDq.xyz VF01, VF01, Q NOP
- MULx.w VF01, VF00, VF00 NOP
- SUB.xyz VF02, VF01, VF14 NOP
- NOP[E] NOP
- NOP NOP
-LineStartInsideSphere:
- NOP MOVE.xyzw VF01, VF12
- NOP[E] IADDIU VI01, VI00, 0x1
- NOP NOP
-
-
-; 3C0
-.globl Vu0LineToAABBCollision
-Vu0LineToAABBCollision:
- SUB.xyzw VF08, VF13, VF12 LOI 0.5
- MULi.xyz VF15, VF15, I IADDIU VI08, VI00, 0x0
- SUB.xyzw VF12, VF12, VF14 NOP
- SUB.xyzw VF13, VF13, VF14 NOP
- NOP DIV Q, VF00w, VF08x
- NOP MR32.xyzw VF03, VF15
- SUB.xyz VF06, VF15, VF12 NOP
- ADD.xyz VF07, VF15, VF12 NOP
- NOP NOP
- CLIPw.xyz VF12, VF03 MR32.xyzw VF04, VF03
- NOP NOP
- ADDq.x VF09, VF00, Q DIV Q, VF00w, VF08y
- NOP NOP
- CLIPw.xyz VF12, VF04 MR32.xyzw VF05, VF04
- SUB.xyz VF07, VF00, VF07 IADDIU VI06, VI00, 0xCC
- NOP IADDIU VI07, VI00, 0x30
- NOP NOP
- CLIPw.xyz VF12, VF05 FCGET VI02
- NOP IAND VI02, VI02, VI06
- ADDq.y VF09, VF00, Q DIV Q, VF00w, VF08z
- SUB.xyz VF10, VF00, VF10 NOP
- CLIPw.xyz VF13, VF03 FCGET VI03
- CLIPw.xyz VF13, VF04 IAND VI03, VI03, VI07
- CLIPw.xyz VF13, VF05 FCAND VI01, 0x3330
- NOP IBEQ VI01, VI00, StartPointInsideAABB
- NOP NOP
- ADDq.z VF09, VF00, Q FCGET VI04
- NOP FCGET VI05
- NOP IAND VI04, VI04, VI06
- NOP IAND VI05, VI05, VI07
- MULx.xyz VF17, VF08, VF09 NOP
- MULy.xyz VF18, VF08, VF09 IADDIU VI07, VI00, 0x80
- MULz.xyz VF19, VF08, VF09 IAND VI06, VI02, VI07
- MUL.w VF10, VF00, VF00 IAND VI07, VI04, VI07
- NOP NOP
- NOP IBEQ VI06, VI07, CheckMaxXSide
- NOP NOP
- MULAx.xyz ACC, VF17, VF07 NOP
- MADDw.xyz VF16, VF12, VF00 NOP
- MUL.x VF10, VF07, VF09 NOP
- CLIPw.xyz VF16, VF04 NOP
- CLIPw.xyz VF16, VF05 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0x330
- NOP IBNE VI01, VI00, CheckMaxXSide
- NOP NOP
- MULx.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
- ADD.yz VF02, VF00, VF00 MOVE.xyzw VF01, VF16
- SUBw.x VF02, VF00, VF00 NOP
-CheckMaxXSide:
- MULAx.xyz ACC, VF17, VF06 IADDIU VI07, VI00, 0x40
- MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07
- MUL.x VF10, VF06, VF09 IAND VI07, VI04, VI07
- NOP NOP
- NOP IBEQ VI06, VI07, CheckMinYSide
- NOP NOP
- CLIPw.xyz VF16, VF04 NOP
- CLIPw.xyz VF16, VF05 NOP
- CLIPw.xyz VF10, VF10 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0xCC03
- NOP IBNE VI01, VI00, CheckMinYSide
- NOP NOP
- MULx.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
- ADD.yz VF02, VF00, VF00 MOVE.xyzw VF01, VF16
- ADDw.x VF02, VF00, VF00 NOP
-CheckMinYSide:
- MULAy.xyz ACC, VF18, VF07 IADDIU VI07, VI00, 0x8
- MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07
- MUL.y VF10, VF07, VF09 IAND VI07, VI04, VI07
- NOP NOP
- NOP IBEQ VI06, VI07, CheckMaxYSide
- NOP NOP
- CLIPw.xyz VF16, VF03 NOP
- CLIPw.xyz VF16, VF05 NOP
- CLIPw.xyz VF10, VF10 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0x3C0C
- NOP IBNE VI01, VI00, CheckMaxYSide
- NOP NOP
- MULy.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
- ADD.xz VF02, VF00, VF00 MOVE.xyzw VF01, VF16
- SUBw.y VF02, VF00, VF00 NOP
-CheckMaxYSide:
- MULAy.xyz ACC, VF18, VF06 IADDIU VI07, VI00, 0x4
- MADDw.xyz VF16, VF12, VF00 IAND VI06, VI02, VI07
- MUL.y VF10, VF06, VF09 IAND VI07, VI04, VI07
- NOP NOP
- NOP IBEQ VI06, VI07, CheckMinZSide
- NOP NOP
- CLIPw.xyz VF16, VF03 NOP
- CLIPw.xyz VF16, VF05 NOP
- CLIPw.xyz VF10, VF10 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0x3C0C
- NOP IBNE VI01, VI00, CheckMinZSide
- NOP NOP
- MULy.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
- ADD.xz VF02, VF00, VF00 MOVE.xyzw VF01, VF16
- ADDw.y VF02, VF00, VF00 NOP
-CheckMinZSide:
- MULAz.xyz ACC, VF19, VF07 IADDIU VI07, VI00, 0x20
- MADDw.xyz VF16, VF12, VF00 IAND VI06, VI03, VI07
- MUL.z VF10, VF07, VF09 IAND VI07, VI05, VI07
- NOP NOP
- NOP IBEQ VI06, VI07, CheckMaxZSide
- NOP NOP
- CLIPw.xyz VF16, VF03 NOP
- CLIPw.xyz VF16, VF04 NOP
- CLIPw.xyz VF10, VF10 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0x3330
- NOP IBNE VI01, VI00, CheckMaxZSide
- NOP NOP
- MULz.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
- ADD.xy VF02, VF00, VF00 MOVE.xyzw VF01, VF16
- SUBw.z VF02, VF00, VF00 NOP
-CheckMaxZSide:
- MULAz.xyz ACC, VF19, VF06 IADDIU VI07, VI00, 0x10
- MADDw.xyz VF16, VF12, VF00 IAND VI06, VI03, VI07
- MUL.z VF10, VF06, VF09 IAND VI07, VI05, VI07
- NOP NOP
- NOP IBEQ VI06, VI07, DoneAllChecks
- NOP NOP
- CLIPw.xyz VF16, VF03 NOP
- CLIPw.xyz VF16, VF04 NOP
- CLIPw.xyz VF10, VF10 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0x3330
- NOP IBNE VI01, VI00, DoneAllChecks
- NOP NOP
- MULz.w VF10, VF00, VF10 IADDIU VI08, VI00, 0x1
- ADD.xy VF02, VF00, VF00 MOVE.xyzw VF01, VF16
- ADDw.z VF02, VF00, VF00 NOP
-DoneAllChecks:
- ADD.xyz VF01, VF01, VF14 IADD VI01, VI00, VI08
- NOP[E] NOP
- NOP NOP
-StartPointInsideAABB:
- ADD.xyz VF01, VF12, VF14 WAITQ
- NOP IADDIU VI01, VI00, 0x1
- NOP[E] NOP
- NOP NOP
-
-
-; 860
-.globl Vu0LineToTriangleCollisionCompressedStart
-Vu0LineToTriangleCollisionCompressedStart:
- ITOF0.xyzw VF17, VF17 LOI 0.000244140625 ; 1.0/4096.0
- ITOF0.xyzw VF14, VF14 NOP
- ITOF0.xyzw VF15, VF15 NOP
- ITOF0.xyzw VF16, VF16 NOP
- MULi.xyz VF17, VF17, I LOI 0.0078125 ; 1.0/128.0
- MULi.w VF17, VF17, I NOP
- MULi.xyzw VF14, VF14, I NOP
- MULi.xyzw VF15, VF15, I NOP
- MULi.xyzw VF16, VF16, I NOP
-; fall through
-
-; 8A8
-; VF12: point0
-; VF13: point1
-; VF14-16: verts
-; VF17: plane
-; out:
-; VF01: intersection point
-; VF02: triangle normal
-; VF03 x: intersection parameter
-.globl Vu0LineToTriangleCollisionStart
-Vu0LineToTriangleCollisionStart:
- MUL.xyz VF10, VF17, VF12 LOI 0.5
- MUL.xyz VF11, VF17, VF13 NOP
- SUB.xyz VF02, VF13, VF12 NOP ; line dist
- ADD.xyz VF17, VF17, VF00 NOP
- MULi.w VF03, VF00, I NOP
- MULAx.w ACC, VF00, VF10 NOP
- MADDAy.w ACC, VF00, VF10 IADDIU VI06, VI00, 0xE0
- MADDz.w VF10, VF00, VF10 FMAND VI05, VI06 ; -- normal sign flags, unused
- MULAx.w ACC, VF00, VF11 NOP
- MADDAy.w ACC, VF00, VF11 NOP
- MADDz.w VF11, VF00, VF11 NOP
- SUB.w VF09, VF17, VF10 NOP ; plane-pos 0
- CLIPw.xyz VF17, VF03 NOP ; compare normal against 0.5 to figure out which in which dimension to compare
- NOP IADDIU VI02, VI00, 0x10 ; Sw flag
- SUBA.w ACC, VF17, VF11 NOP ; plane-pos 1
- SUB.w VF08, VF11, VF10 FMAND VI01, VI02
- NOP NOP
- NOP NOP
- NOP FMAND VI02, VI02
- NOP IBEQ VI01, VI02, QuitAndFail ; if on same side, no collision
- NOP NOP
- NOP DIV Q, VF09w, VF08w ; parameter of intersection
- NOP FCAND VI01, 0x3 ; check x direction
- NOP IADDIU VI02, VI01, 0x7F
- NOP IADDIU VI06, VI00, 0x80
- NOP IAND VI02, VI02, VI06 ; Sx flag
- NOP FCAND VI01, 0xC ; check y direction
- NOP IADDIU VI03, VI01, 0x3F
- MULAw.xyz ACC, VF12, VF00 IADDIU VI06, VI00, 0x40
- MADDq.xyz VF01, VF02, Q IAND VI03, VI03, VI06 ; point of intersection -- Sy flag
- MULx.w VF01, VF00, VF00 FCAND VI01, 0x30 ; -- check z direction
- ADDq.x VF03, VF00, Q IADDIU VI04, VI01, 0x1F ; output parameter
- SUB.xyz VF05, VF15, VF14 IADDIU VI06, VI00, 0x20 ; edge vectors
- SUB.xyz VF08, VF01, VF14 IAND VI04, VI04, VI06 ; edge vectors -- Sz flag
- SUB.xyz VF06, VF16, VF15 IADD VI06, VI02, VI03 ; edge vectors
- SUB.xyz VF09, VF01, VF15 IADD VI06, VI06, VI04 ; edge vectors -- combine flags
- SUB.xyz VF07, VF14, VF16 NOP ; edge vectors
- SUB.xyz VF10, VF01, VF16 NOP ; edge vectors
- OPMULA.xyz ACC, VF08, VF05 NOP
- OPMSUB.xyz VF18, VF05, VF08 NOP ; cross1
- OPMULA.xyz ACC, VF09, VF06 NOP
- OPMSUB.xyz VF19, VF06, VF09 NOP ; cross2
- OPMULA.xyz ACC, VF10, VF07 NOP
- OPMSUB.xyz VF20, VF07, VF10 FMAND VI02, VI06 ; cross3
- NOP NOP
- NOP FMAND VI03, VI06
- NOP NOP
- NOP FMAND VI04, VI06
- NOP NOP
- NOP IBNE VI03, VI02, QuitAndFail ; point has to lie on the same side of all edges (i.e. inside)
- NOP NOP
- NOP IBNE VI04, VI02, QuitAndFail
- NOP NOP
- MULw.xyz VF02, VF17, VF00 IADDIU VI01, VI00, 0x1 ; success
- NOP[E] NOP
- NOP NOP
-
-
-; A68
-; VF12: center
-; VF14: line origin
-; VF15: line vector to other point
-; out: VF16 xyz: nearest point on line; w: distance to that point
-DistanceBetweenSphereAndLine:
- SUB.xyz VF20, VF12, VF14 NOP
- MUL.xyz VF21, VF15, VF15 NOP
- ADDA.xyz ACC, VF14, VF15 NOP
- MSUBw.xyz VF25, VF12, VF00 NOP ; VF25 = VF12 - (VF14+VF15)
- MUL.xyz VF22, VF20, VF20 NOP
- MUL.xyz VF23, VF20, VF15 NOP
- MULAx.w ACC, VF00, VF21 NOP
- MADDAy.w ACC, VF00, VF21 NOP
- MADDz.w VF21, VF00, VF21 NOP ; MagSq VF15 (line length)
- MULAx.w ACC, VF00, VF23 NOP
- MADDAy.w ACC, VF00, VF23 NOP
- MADDz.w VF23, VF00, VF23 NOP ; dot(VF12-VF14, VF15)
- MULAx.w ACC, VF00, VF22 NOP
- MADDAy.w ACC, VF00, VF22 NOP
- MADDz.w VF22, VF00, VF22 IADDIU VI08, VI00, 0x10 ; MagSq VF12-VF14 -- Sw bit
- MUL.xyz VF25, VF25, VF25 FMAND VI08, VI08
- NOP DIV Q, VF23w, VF21w
- NOP IBNE VI00, VI08, NegativeRatio
- NOP NOP
- ADDA.xyz ACC, VF00, VF14 NOP
- MADDq.xyz VF16, VF15, Q WAITQ ; nearest point on infinte line
- ADDq.x VF24, VF00, Q NOP ; ratio
- NOP NOP
- NOP NOP
- SUB.xyz VF26, VF16, VF12 NOP
- CLIPw.xyz VF24, VF00 NOP ; compare ratio to 1.0
- NOP NOP
- NOP NOP
- MUL.xyz VF26, VF26, VF26 NOP
- NOP FCAND VI01, 0x1
- NOP IBNE VI00, VI01, RatioGreaterThanOne
- NOP NOP
- MULAx.w ACC, VF00, VF26 NOP
- MADDAy.w ACC, VF00, VF26 NOP
- MADDz.w VF16, VF00, VF26 NOP ; distance
- NOP JR VI15
- NOP NOP
-NegativeRatio:
- ADD.xyz VF16, VF00, VF14 NOP ; return line origin
- MUL.w VF16, VF00, VF22 NOP ; and DistSq to it
- NOP JR VI15
- NOP NOP
-RatioGreaterThanOne:
- MULAx.w ACC, VF00, VF25 NOP
- MADDAy.w ACC, VF00, VF25 NOP
- MADDz.w VF16, VF00, VF25 NOP
- ADD.xyz VF16, VF14, VF15 NOP ; return toerh line point
- NOP JR VI15
- NOP NOP
-
-
-; BE0
-.globl Vu0SphereToTriangleCollisionCompressedStart
-Vu0SphereToTriangleCollisionCompressedStart:
- ITOF0.xyzw VF17, VF17 LOI 0.000244140625 ; 1.0/4096.0
- ITOF0.xyzw VF14, VF14 NOP
- ITOF0.xyzw VF15, VF15 NOP
- ITOF0.xyzw VF16, VF16 NOP
- MULi.xyz VF17, VF17, I LOI 0.0078125 ; 1.0/128.0
- MULi.w VF17, VF17, I NOP
- MULi.xyzw VF14, VF14, I NOP
- MULi.xyzw VF15, VF15, I NOP
- MULi.xyzw VF16, VF16, I NOP
-; fall through
-
-; C28
-; VF12: sphere
-; VF14-16: verts
-; VF17: plane
-; out:
-; VF01: intersection point
-; VF02: triangle normal
-; VF03 x: intersection parameter
-.globl Vu0SphereToTriangleCollisionStart
-Vu0SphereToTriangleCollisionStart:
- MUL.xyz VF02, VF12, VF17 LOI 0.1
- ADD.xyz VF17, VF17, VF00 NOP
- ADDw.x VF13, VF00, VF12 NOP
- NOP NOP
- MULAx.w ACC, VF00, VF02 IADDIU VI06, VI00, 0xE0
- MADDAy.w ACC, VF00, VF02 FMAND VI05, VI06 ; normal sign flags
- MADDAz.w ACC, VF00, VF02 NOP
- MSUB.w VF02, VF00, VF17 NOP ; center plane pos
- MULi.w VF03, VF00, I MOVE.xyzw VF04, VF03
- NOP NOP
- NOP NOP
- CLIPw.xyz VF13, VF02 NOP ; compare dist and radius
- CLIPw.xyz VF17, VF03 NOP
- MULAw.xyz ACC, VF12, VF00 IADDIU VI07, VI00, 0x0 ; -- clear test case
- MSUBw.xyz VF01, VF17, VF02 NOP
- MULx.w VF01, VF00, VF00 FCAND VI01, 0x3 ; projected center on plane
- ABS.w VF02, VF02 IBEQ VI00, VI01, QuitAndFail ; no intersection
- NOP NOP
- NOP FCAND VI01, 0x3 ; -- check x direction
- SUB.xyz VF02, VF12, VF01 IADDIU VI02, VI01, 0x7F
- NOP IADDIU VI06, VI00, 0x80
- SUB.xyz VF05, VF15, VF14 IAND VI02, VI02, VI06
- SUB.xyz VF08, VF01, VF14 FCAND VI01, 0xC ; -- check y direction
- SUB.xyz VF06, VF16, VF15 IADDIU VI03, VI01, 0x3F
- SUB.xyz VF09, VF01, VF15 IADDIU VI06, VI00, 0x40
- SUB.xyz VF07, VF14, VF16 IAND VI03, VI03, VI06
- SUB.xyz VF10, VF01, VF16 FCAND VI01, 0x30 ; -- check z direction
- MUL.xyz VF03, VF02, VF02 IADDIU VI04, VI01, 0x1F
- OPMULA.xyz ACC, VF08, VF05 IADDIU VI06, VI00, 0x20
- OPMSUB.xyz VF18, VF05, VF08 IAND VI04, VI04, VI06
- OPMULA.xyz ACC, VF09, VF06 NOP
- OPMSUB.xyz VF19, VF06, VF09 IADD VI06, VI02, VI03
- OPMULA.xyz ACC, VF10, VF07 IADD VI06, VI06, VI04 ; -- combine flags
- OPMSUB.xyz VF20, VF07, VF10 FMAND VI02, VI06 ; -- cross 1 flags
- MULAx.w ACC, VF00, VF03 IAND VI05, VI05, VI06
- MADDAy.w ACC, VF00, VF03 FMAND VI03, VI06 ; -- cross 2 flags
- MADDz.w VF03, VF00, VF03 IADDIU VI08, VI00, 0x3
- NOP FMAND VI04, VI06 ; -- cross 3 flags
- NOP NOP
- NOP IBNE VI02, VI05, CheckSide2
- NOP RSQRT Q, VF00w, VF03w
- ADD.xyz VF04, VF00, VF16 IADDIU VI07, VI07, 0x1 ; inside side 1
-CheckSide2:
- NOP IBNE VI03, VI05, CheckSide3
- NOP NOP
- ADD.xyz VF04, VF00, VF14 IADDIU VI07, VI07, 0x1 ; inside side 2
-CheckSide3:
- NOP IBNE VI04, VI05, FinishCheckingSides
- NOP NOP
- ADD.xyz VF04, VF00, VF15 IADDIU VI07, VI07, 0x1 ; inside side 3
- NOP NOP
- NOP IBEQ VI07, VI08, TotallyInsideTriangle
- NOP NOP
-FinishCheckingSides:
- MUL.x VF13, VF13, VF13 IADDIU VI08, VI00, 0x2
- MULq.xyz VF02, VF02, Q WAITQ
- NOP IBNE VI07, VI08, IntersectionOutsideTwoSides
- NOP NOP
- NOP IBEQ VI02, VI05, CheckDistanceSide2
- NOP NOP
- NOP MOVE.xyzw VF15, VF05
- NOP BAL VI15, DistanceBetweenSphereAndLine
- NOP NOP
- NOP B ProcessLineResult
- NOP NOP
-CheckDistanceSide2:
- NOP IBEQ VI03, VI05, CheckDistanceSide3
- NOP NOP
- NOP MOVE.xyzw VF14, VF15
- NOP MOVE.xyzw VF15, VF06
- NOP BAL VI15, DistanceBetweenSphereAndLine
- NOP NOP
- NOP B ProcessLineResult
- NOP NOP
-CheckDistanceSide3:
- NOP MOVE.xyzw VF14, VF16
- NOP MOVE.xyzw VF15, VF07
- NOP BAL VI15, DistanceBetweenSphereAndLine
- NOP NOP
- NOP B ProcessLineResult
- NOP NOP
-IntersectionOutsideTwoSides:
- SUB.xyz VF05, VF04, VF12 NOP
- ADD.xyz VF01, VF00, VF04 NOP ; col point
- SUB.xyz VF02, VF12, VF04 NOP
- NOP NOP
- MUL.xyz VF05, VF05, VF05 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- MULAx.w ACC, VF00, VF05 NOP
- MADDAy.w ACC, VF00, VF05 NOP
- MADDz.w VF05, VF00, VF05 NOP ; distSq to vertex
- NOP NOP
- NOP NOP
- NOP NOP
- CLIPw.xyz VF13, VF05 SQRT Q, VF05w ; compare radiusSq and distSq
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0x1
- ADDq.x VF03, VF00, Q WAITQ ; dist to vertex
- NOP IBEQ VI00, VI01, QuitAndFail ; too far
- NOP NOP
- NOP NOP
- NOP DIV Q, VF00w, VF03x
- MULq.xyz VF02, VF02, Q WAITQ ; col normal
- NOP[E] NOP
- NOP NOP
-TotallyInsideTriangle:
- ADDw.x VF03, VF00, VF02 WAITQ
- MULq.xyz VF02, VF02, Q NOP
- NOP[E] IADDIU VI01, VI00, 0x1
- NOP NOP
-ProcessLineResult:
- CLIPw.xyz VF13, VF16 SQRT Q, VF16w
- ADD.xyz VF01, VF00, VF16 NOP
- SUB.xyz VF02, VF12, VF16 NOP
- NOP NOP
- NOP FCAND VI01, 0x1
- ADDq.x VF03, VF00, Q WAITQ
- NOP IBEQ VI00, VI01, QuitAndFail
- NOP NOP
- NOP NOP
- NOP DIV Q, VF00w, VF03x
- MULq.xyz VF02, VF02, Q WAITQ
- NOP[E] NOP
- NOP NOP
-
-EndOfMicrocode:
diff --git a/src/core/vu0Collision_2.s b/src/core/vu0Collision_2.s
deleted file mode 100644
index 716c29ac..00000000
--- a/src/core/vu0Collision_2.s
+++ /dev/null
@@ -1,191 +0,0 @@
-QuitAndFail2:
- NOP[E] IADDIU VI01, VI00, 0x0
- NOP NOP
-
-
-QuitAndSucceed2:
- NOP[E] IADDIU VI01, VI00, 0x1
- NOP NOP
-
-
-; 20
-GetBBVertices:
- MULw.xy VF02, VF01, VF00 NOP
- MUL.z VF02, VF01, VF11 NOP
- MULw.xz VF03, VF01, VF00 NOP
- MUL.y VF03, VF01, VF11 NOP
- MULw.x VF04, VF01, VF00 NOP
- MUL.yz VF04, VF01, VF11 NOP
- NOP JR VI15
- NOP NOP
-
-
-; 60
-Vu0OBBToOBBCollision:
- SUBw.xyz VF11, VF00, VF00 LOI 0.5
- MULi.xyz VF12, VF12, I NOP
- MULi.xyz VF13, VF13, I NOP
- NOP NOP
- NOP NOP
- NOP MOVE.xyz VF01, VF12
- NOP BAL VI15, GetBBVertices
- NOP NOP
- MULAx.xyz ACC, VF14, VF01 NOP
- MADDAy.xyz ACC, VF15, VF01 NOP
- MADDz.xyz VF01, VF16, VF01 NOP
- MULAx.xyz ACC, VF14, VF02 NOP
- MADDAy.xyz ACC, VF15, VF02 NOP
- MADDz.xyz VF02, VF16, VF02 NOP
- MULAx.xyz ACC, VF14, VF03 NOP
- MADDAy.xyz ACC, VF15, VF03 NOP
- MADDz.xyz VF03, VF16, VF03 NOP
- MULAx.xyz ACC, VF14, VF04 NOP
- MADDAy.xyz ACC, VF15, VF04 NOP
- MADDz.xyz VF04, VF16, VF04 NOP
- ABS.xyz VF05, VF01 NOP
- ABS.xyz VF06, VF02 NOP
- ABS.xyz VF07, VF03 NOP
- ABS.xyz VF08, VF04 NOP
- NOP NOP
- MAX.xyz VF05, VF05, VF06 NOP
- NOP NOP
- MAX.xyz VF07, VF07, VF08 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- MAX.xyz VF05, VF05, VF07 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- ADD.xyz VF09, VF05, VF13 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- MULx.w VF05, VF00, VF09 NOP
- MULy.w VF06, VF00, VF09 NOP
- MULz.w VF07, VF00, VF09 NOP
- CLIPw.xyz VF17, VF05 NOP
- CLIPw.xyz VF17, VF06 NOP
- CLIPw.xyz VF17, VF07 MOVE.xyz VF01, VF13
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0x3330
- NOP IBNE VI01, VI00, QuitAndFail2
- NOP NOP
- NOP BAL VI15, GetBBVertices
- NOP NOP
- MULAx.xyz ACC, VF18, VF01 NOP
- MADDAy.xyz ACC, VF19, VF01 NOP
- MADDz.xyz VF01, VF20, VF01 NOP
- MULAx.xyz ACC, VF18, VF02 NOP
- MADDAy.xyz ACC, VF19, VF02 NOP
- MADDz.xyz VF02, VF20, VF02 NOP
- MULAx.xyz ACC, VF18, VF03 NOP
- MADDAy.xyz ACC, VF19, VF03 NOP
- MADDz.xyz VF03, VF20, VF03 NOP
- MULAx.xyz ACC, VF18, VF04 NOP
- MADDAy.xyz ACC, VF19, VF04 NOP
- MADDz.xyz VF04, VF20, VF04 NOP
- ABS.xyz VF05, VF01 NOP
- ABS.xyz VF06, VF02 NOP
- ABS.xyz VF07, VF03 NOP
- ABS.xyz VF08, VF04 NOP
- NOP NOP
- MAX.xyz VF05, VF05, VF06 NOP
- NOP NOP
- MAX.xyz VF07, VF07, VF08 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- MAX.xyz VF05, VF05, VF07 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- ADD.xyz VF09, VF05, VF12 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- MULx.w VF05, VF00, VF09 NOP
- MULy.w VF06, VF00, VF09 NOP
- MULz.w VF07, VF00, VF09 NOP
- CLIPw.xyz VF21, VF05 NOP
- CLIPw.xyz VF21, VF06 NOP
- CLIPw.xyz VF21, VF07 NOP
- NOP NOP
- NOP NOP
- NOP NOP
- NOP FCAND VI01, 0x3330
- NOP IBNE VI01, VI00, QuitAndFail2
- NOP NOP
- SUB.xyz VF06, VF02, VF01 NOP
- SUB.xyz VF07, VF03, VF01 NOP
- ADD.xyz VF08, VF04, VF01 NOP
- ADD.x VF09, VF00, VF12 NOP
- ADD.yz VF09, VF00, VF00 NOP
- ADD.y VF10, VF00, VF12 NOP
- ADD.xz VF10, VF00, VF00 NOP
- ADD.z VF11, VF00, VF12 IADDI VI04, VI00, 0x0
- ADD.xy VF11, VF00, VF00 IADD VI02, VI00, VI00
- OPMULA.xyz ACC, VF06, VF09 NOP
- OPMSUB.xyz VF01, VF09, VF06 NOP
- OPMULA.xyz ACC, VF06, VF10 NOP
- OPMSUB.xyz VF02, VF10, VF06 NOP
- OPMULA.xyz ACC, VF06, VF11 NOP
- OPMSUB.xyz VF03, VF11, VF06 SQI.xyzw VF01, (VI02++)
- OPMULA.xyz ACC, VF07, VF09 NOP
- OPMSUB.xyz VF01, VF09, VF07 SQI.xyzw VF02, (VI02++)
- OPMULA.xyz ACC, VF07, VF10 NOP
- OPMSUB.xyz VF02, VF10, VF07 SQI.xyzw VF03, (VI02++)
- OPMULA.xyz ACC, VF07, VF11 NOP
- OPMSUB.xyz VF03, VF11, VF07 SQI.xyzw VF01, (VI02++)
- OPMULA.xyz ACC, VF08, VF09 NOP
- OPMSUB.xyz VF01, VF09, VF08 SQI.xyzw VF02, (VI02++)
- OPMULA.xyz ACC, VF08, VF10 NOP
- OPMSUB.xyz VF02, VF10, VF08 SQI.xyzw VF03, (VI02++)
- OPMULA.xyz ACC, VF08, VF11 LOI 0.5
- OPMSUB.xyz VF01, VF11, VF08 SQI.xyzw VF01, (VI02++)
- MULi.xyz VF06, VF06, I NOP
- MULi.xyz VF07, VF07, I SQI.xyzw VF02, (VI02++)
- MULi.xyz VF08, VF08, I NOP
- MUL.xyz VF02, VF21, VF01 NOP
- MUL.xyz VF03, VF12, VF01 NOP
- MUL.xyz VF09, VF06, VF01 NOP
- MUL.xyz VF10, VF07, VF01 NOP
- MUL.xyz VF11, VF08, VF01 NOP
- ABS.xyz VF03, VF03 NOP
- ADDy.x VF05, VF09, VF09 NOP
- ADDx.y VF05, VF10, VF10 NOP
- ADDx.z VF05, VF11, VF11 NOP
- NOP NOP
-EdgePairLoop:
- ADDz.x VF05, VF05, VF09 NOP
- ADDz.y VF05, VF05, VF10 NOP
- ADDy.z VF05, VF05, VF11 NOP
- MULAx.w ACC, VF00, VF02 IADD VI03, VI02, VI00
- MADDAy.w ACC, VF00, VF02 LQD.xyzw VF01, (--VI02)
- MADDz.w VF02, VF00, VF02 NOP
- ABS.xyz VF05, VF05 NOP
- MULAx.w ACC, VF00, VF03 NOP
- MADDAy.w ACC, VF00, VF03 NOP
- MADDAz.w ACC, VF00, VF03 NOP
- MADDAx.w ACC, VF00, VF05 NOP
- MADDAy.w ACC, VF00, VF05 NOP
- MADDz.w VF03, VF00, VF05 NOP
- ADDw.x VF04, VF00, VF02 NOP
- MUL.xyz VF02, VF21, VF01 NOP
- MUL.xyz VF03, VF12, VF01 NOP
- MUL.xyz VF09, VF06, VF01 NOP
- CLIPw.xyz VF04, VF03 NOP
- MUL.xyz VF10, VF07, VF01 NOP
- MUL.xyz VF11, VF08, VF01 NOP
- ABS.xyz VF03, VF03 NOP
- ADDy.x VF05, VF09, VF09 FCAND VI01, 0x3
- ADDx.y VF05, VF10, VF10 IBNE VI01, VI00, QuitAndFail2
- ADDx.z VF05, VF11, VF11 NOP
- NOP IBNE VI03, VI00, EdgePairLoop
- NOP NOP
- NOP[E] IADDIU VI01, VI00, 0x1
- NOP NOP
-
-EndOfMicrocode2: