mirror of
https://github.com/halpz/re3.git
synced 2025-11-21 15:47:00 +00:00
Merge branch 'master' of https://github.com/gtamodding/re3
This commit is contained in:
1310
src/core/Camera.cpp
Normal file
1310
src/core/Camera.cpp
Normal file
File diff suppressed because it is too large
Load Diff
477
src/core/Camera.h
Normal file
477
src/core/Camera.h
Normal file
@@ -0,0 +1,477 @@
|
||||
#pragma once
|
||||
#include "Placeable.h"
|
||||
|
||||
class CEntity;
|
||||
class CPed;
|
||||
class CAutomobile;
|
||||
|
||||
#define NUMBER_OF_VECTORS_FOR_AVERAGE 2
|
||||
|
||||
struct CCam
|
||||
{
|
||||
enum
|
||||
{
|
||||
MODE_TOPDOWN1 = 1,
|
||||
MODE_TOPDOWN2,
|
||||
MODE_BEHINDCAR,
|
||||
MODE_FOLLOWPED,
|
||||
MODE_AIMING,
|
||||
MODE_DEBUG,
|
||||
MODE_SNIPER,
|
||||
MODE_ROCKET,
|
||||
MODE_MODELVIEW,
|
||||
MODE_BILL,
|
||||
MODE_SYPHON,
|
||||
MODE_CIRCLE,
|
||||
MODE_CHEESYZOOM,
|
||||
MODE_WHEELCAM,
|
||||
MODE_FIXED,
|
||||
MODE_FIRSTPERSON,
|
||||
MODE_FLYBY,
|
||||
MODE_CAMONASTRING,
|
||||
MODE_REACTIONCAM,
|
||||
MODE_FOLLOWPEDWITHBINDING,
|
||||
MODE_CHRISWITHBINDINGPLUSROTATION,
|
||||
MODE_BEHINDBOAT,
|
||||
MODE_PLAYERFALLENWATER,
|
||||
MODE_CAMONTRAINROOF,
|
||||
MODE_CAMRUNNINGSIDETRAIN,
|
||||
MODE_BLOODONTHETRACKS,
|
||||
MODE_IMTHEPASSENGERWOOWOO,
|
||||
MODE_SYPHONCRIMINFRONT,
|
||||
MODE_PEDSDEADBABY,
|
||||
MODE_CUSHYPILLOWSARSE,
|
||||
MODE_LOOKATCARS,
|
||||
MODE_ARRESTCAMONE,
|
||||
MODE_ARRESTCAMTWO,
|
||||
MODE_M16FIRSTPERSON_34,
|
||||
MODE_SPECIALFIXEDFORSYPHON,
|
||||
MODE_FIGHT,
|
||||
MODE_TOPDOWNPED,
|
||||
MODE_SNIPER_RUN_AROUND,
|
||||
MODE_ROCKET_RUN_AROUND,
|
||||
MODE_FIRSTPERSONPEDONPC_40,
|
||||
MODE_FIRSTPERSONPEDONPC_41,
|
||||
MODE_FIRSTPERSONPEDONPC_42,
|
||||
MODE_EDITOR,
|
||||
MODE_M16FIRSTPERSON_44
|
||||
};
|
||||
|
||||
bool bBelowMinDist; //used for follow ped mode
|
||||
bool bBehindPlayerDesired; //used for follow ped mode
|
||||
bool m_bCamLookingAtVector;
|
||||
bool m_bCollisionChecksOn;
|
||||
bool m_bFixingBeta; //used for camera on a string
|
||||
bool m_bTheHeightFixerVehicleIsATrain;
|
||||
bool LookBehindCamWasInFront;
|
||||
bool LookingBehind;
|
||||
bool LookingLeft; // 32
|
||||
bool LookingRight;
|
||||
bool ResetStatics; //for interpolation type stuff to work
|
||||
bool Rotating;
|
||||
|
||||
int16 Mode; // CameraMode
|
||||
uint32 m_uiFinishTime; // 52
|
||||
|
||||
int m_iDoCollisionChecksOnFrameNum;
|
||||
int m_iDoCollisionCheckEveryNumOfFrames;
|
||||
int m_iFrameNumWereAt; // 64
|
||||
int m_iRunningVectorArrayPos;
|
||||
int m_iRunningVectorCounter;
|
||||
int DirectionWasLooking;
|
||||
|
||||
float f_max_role_angle; //=DEGTORAD(5.0f);
|
||||
float f_Roll; //used for adding a slight roll to the camera in the
|
||||
float f_rollSpeed;
|
||||
float m_fSyphonModeTargetZOffSet;
|
||||
float m_fUnknownZOffSet;
|
||||
float m_fAmountFractionObscured;
|
||||
float m_fAlphaSpeedOverOneFrame; // 100
|
||||
float m_fBetaSpeedOverOneFrame;
|
||||
float m_fBufferedTargetBeta;
|
||||
float m_fBufferedTargetOrientation;
|
||||
float m_fBufferedTargetOrientationSpeed;
|
||||
float m_fCamBufferedHeight;
|
||||
float m_fCamBufferedHeightSpeed;
|
||||
float m_fCloseInPedHeightOffset;
|
||||
float m_fCloseInPedHeightOffsetSpeed; // 132
|
||||
float m_fCloseInCarHeightOffset;
|
||||
float m_fCloseInCarHeightOffsetSpeed;
|
||||
float m_fDimensionOfHighestNearCar;
|
||||
float m_fDistanceBeforeChanges;
|
||||
float m_fFovSpeedOverOneFrame;
|
||||
float m_fMinDistAwayFromCamWhenInterPolating;
|
||||
float m_fPedBetweenCameraHeightOffset;
|
||||
float m_fPlayerInFrontSyphonAngleOffSet; // 164
|
||||
float m_fRadiusForDead;
|
||||
float m_fRealGroundDist; //used for follow ped mode
|
||||
float m_fTargetBeta;
|
||||
float m_fTimeElapsedFloat;
|
||||
|
||||
float m_fTransitionBeta;
|
||||
float m_fTrueBeta;
|
||||
float m_fTrueAlpha; // 200
|
||||
float m_fInitialPlayerOrientation; //used for first person
|
||||
|
||||
float Alpha;
|
||||
float AlphaSpeed;
|
||||
float FOV;
|
||||
float FOVSpeed;
|
||||
float Beta;
|
||||
float BetaSpeed;
|
||||
float Distance; // 232
|
||||
float DistanceSpeed;
|
||||
float CA_MIN_DISTANCE;
|
||||
float CA_MAX_DISTANCE;
|
||||
float SpeedVar;
|
||||
|
||||
// ped onfoot zoom distance
|
||||
float m_fTargetZoomGroundOne;
|
||||
float m_fTargetZoomGroundTwo; // 256
|
||||
float m_fTargetZoomGroundThree;
|
||||
// ped onfoot alpha angle offset
|
||||
float m_fTargetZoomOneZExtra;
|
||||
float m_fTargetZoomTwoZExtra;
|
||||
float m_fTargetZoomThreeZExtra;
|
||||
|
||||
float m_fTargetZoomZCloseIn;
|
||||
float m_fMinRealGroundDist;
|
||||
float m_fTargetCloseInDist;
|
||||
|
||||
CVector m_cvecTargetCoorsForFudgeInter; // 360
|
||||
CVector m_cvecCamFixedModeVector; // 372
|
||||
CVector m_cvecCamFixedModeSource; // 384
|
||||
CVector m_cvecCamFixedModeUpOffSet; // 396
|
||||
CVector m_vecLastAboveWaterCamPosition; //408 //helper for when the player has gone under the water
|
||||
CVector m_vecBufferedPlayerBodyOffset; // 420
|
||||
|
||||
// The three vectors that determine this camera for this frame
|
||||
CVector Front; // 432 // Direction of looking in
|
||||
CVector Source; // Coors in world space
|
||||
CVector SourceBeforeLookBehind;
|
||||
CVector Up; // Just that
|
||||
CVector m_arrPreviousVectors[NUMBER_OF_VECTORS_FOR_AVERAGE]; // used to average stuff
|
||||
CEntity *CamTargetEntity;
|
||||
|
||||
float m_fCameraDistance;
|
||||
float m_fIdealAlpha;
|
||||
float m_fPlayerVelocity;
|
||||
CAutomobile *m_pLastCarEntered; // So interpolation works
|
||||
CPed *m_pLastPedLookedAt;// So interpolation works
|
||||
bool m_bFirstPersonRunAboutActive;
|
||||
|
||||
|
||||
void GetVectorsReadyForRW(void);
|
||||
CVector DoAverageOnVector(const CVector &vec);
|
||||
float GetPedBetaAngleForClearView(const CVector &Target, float Dist, float BetaOffset, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies);
|
||||
void WorkOutCamHeightWeeCar(CVector &TargetCoors, float TargetOrientation);
|
||||
void WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, float TargetHeight);
|
||||
bool RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation);
|
||||
bool FixCamIfObscured(CVector &TargetCoors, float TargetHeight, float TargetOrientation);
|
||||
void Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist);
|
||||
void FixCamWhenObscuredByVehicle(const CVector &TargetCoors);
|
||||
bool Using3rdPersonMouseCam();
|
||||
bool GetWeaponFirstPersonOn();
|
||||
|
||||
void Process_Debug(float *vec, float a, float b, float c);
|
||||
void Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float);
|
||||
void Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, float, float);
|
||||
void Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float);
|
||||
};
|
||||
static_assert(sizeof(CCam) == 0x1A4, "CCam: wrong size");
|
||||
static_assert(offsetof(CCam, Alpha) == 0xA8, "CCam: error");
|
||||
static_assert(offsetof(CCam, Front) == 0x140, "CCam: error");
|
||||
|
||||
struct CCamPathSplines
|
||||
{
|
||||
float m_arr_PathData[800];
|
||||
};
|
||||
|
||||
struct CTrainCamNode
|
||||
{
|
||||
CVector m_cvecCamPosition;
|
||||
CVector m_cvecPointToLookAt;
|
||||
CVector m_cvecMinPointInRange;
|
||||
CVector m_cvecMaxPointInRange;
|
||||
float m_fDesiredFOV;
|
||||
float m_fNearClip;
|
||||
};
|
||||
|
||||
struct CQueuedMode
|
||||
{
|
||||
int16 Mode;
|
||||
float Duration;
|
||||
int16 MinZoom;
|
||||
int16 MaxZoom;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
LOOKING_BEHIND,
|
||||
LOOKING_LEFT,
|
||||
LOOKING_RIGHT,
|
||||
LOOKING_FORWARD,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
// TODO: figure out
|
||||
FADE_0,
|
||||
FADE_1, // mid fade
|
||||
FADE_2,
|
||||
|
||||
FADE_OUT = 0,
|
||||
FADE_IN,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MBLUR_NONE,
|
||||
MBLUR_SNIPER,
|
||||
MBLUR_NORMAL,
|
||||
MBLUR_INTRO1, // green camera
|
||||
MBLUR_INTRO2, // unused
|
||||
MBLUR_INTRO3, // bank scene
|
||||
MBLUR_INTRO4, // jail break scene
|
||||
MBLUR_INTRO5, // explosion
|
||||
MBLUR_INTRO6, // player shot
|
||||
MBLUR_UNUSED, // pinkish
|
||||
};
|
||||
|
||||
struct CCamera : public CPlaceable
|
||||
{
|
||||
bool m_bAboveGroundTrainNodesLoaded;
|
||||
bool m_bBelowGroundTrainNodesLoaded;
|
||||
bool m_bCamDirectlyBehind;
|
||||
bool m_bCamDirectlyInFront;
|
||||
bool m_bCameraJustRestored;
|
||||
bool m_bcutsceneFinished;
|
||||
bool m_bCullZoneChecksOn;
|
||||
bool m_bFirstPersonBeingUsed;
|
||||
bool m_bJustJumpedOutOf1stPersonBecauseOfTarget;
|
||||
bool m_bIdleOn;
|
||||
bool m_bInATunnelAndABigVehicle;
|
||||
bool m_bInitialNodeFound;
|
||||
bool m_bInitialNoNodeStaticsSet;
|
||||
bool m_bIgnoreFadingStuffForMusic;
|
||||
bool m_bPlayerIsInGarage;
|
||||
bool m_bJustCameOutOfGarage;
|
||||
bool m_bJustInitalised;
|
||||
bool m_bJust_Switched;
|
||||
bool m_bLookingAtPlayer;
|
||||
bool m_bLookingAtVector;
|
||||
bool m_bMoveCamToAvoidGeom;
|
||||
bool m_bObbeCinematicPedCamOn;
|
||||
bool m_bObbeCinematicCarCamOn;
|
||||
bool m_bRestoreByJumpCut;
|
||||
bool m_bUseNearClipScript;
|
||||
bool m_bStartInterScript;
|
||||
bool m_bStartingSpline;
|
||||
bool m_bTargetJustBeenOnTrain;
|
||||
bool m_bTargetJustCameOffTrain;
|
||||
bool m_bUseSpecialFovTrain;
|
||||
bool m_bUseTransitionBeta;
|
||||
bool m_bUseScriptZoomValuePed;
|
||||
bool m_bUseScriptZoomValueCar;
|
||||
bool m_bWaitForInterpolToFinish;
|
||||
bool m_bItsOkToLookJustAtThePlayer;
|
||||
bool m_bWantsToSwitchWidescreenOff;
|
||||
bool m_WideScreenOn;
|
||||
bool m_1rstPersonRunCloseToAWall;
|
||||
bool m_bHeadBob;
|
||||
bool m_bFailedCullZoneTestPreviously;
|
||||
|
||||
bool m_FadeTargetIsSplashScreen;
|
||||
|
||||
bool WorldViewerBeingUsed;
|
||||
uint8 ActiveCam;
|
||||
uint32 m_uiCamShakeStart;
|
||||
uint32 m_uiFirstPersonCamLastInputTime;
|
||||
// where are those?
|
||||
//bool m_bVehicleSuspenHigh;
|
||||
//bool m_bEnable1rstPersonCamCntrlsScript;
|
||||
//bool m_bAllow1rstPersonWeaponsCamera;
|
||||
|
||||
uint32 m_uiLongestTimeInMill;
|
||||
uint32 m_uiNumberOfTrainCamNodes;
|
||||
uint8 m_uiTransitionJUSTStarted;
|
||||
uint8 m_uiTransitionState; // 0:one mode 1:transition
|
||||
|
||||
uint32 m_uiTimeLastChange;
|
||||
uint32 m_uiTimeWeEnteredIdle;
|
||||
uint32 m_uiTimeTransitionStart;
|
||||
uint32 m_uiTransitionDuration;
|
||||
int m_BlurBlue;
|
||||
int m_BlurGreen;
|
||||
int m_BlurRed;
|
||||
int m_BlurType;
|
||||
|
||||
uint32 unknown;
|
||||
int m_iWorkOutSpeedThisNumFrames;
|
||||
int m_iNumFramesSoFar;
|
||||
|
||||
|
||||
int m_iCurrentTrainCamNode;
|
||||
int m_motionBlur;
|
||||
int m_imotionBlurAddAlpha;
|
||||
int m_iCheckCullZoneThisNumFrames;
|
||||
int m_iZoneCullFrameNumWereAt;
|
||||
int WhoIsInControlOfTheCamera;
|
||||
|
||||
float CamFrontXNorm;
|
||||
float CamFrontYNorm;
|
||||
float CarZoomIndicator;
|
||||
float CarZoomValue;
|
||||
float CarZoomValueSmooth;
|
||||
|
||||
float DistanceToWater;
|
||||
float FOVDuringInter;
|
||||
float LODDistMultiplier;
|
||||
float GenerationDistMultiplier;
|
||||
float m_fAlphaSpeedAtStartInter;
|
||||
float m_fAlphaWhenInterPol;
|
||||
float m_fAlphaDuringInterPol;
|
||||
float m_fBetaDuringInterPol;
|
||||
float m_fBetaSpeedAtStartInter;
|
||||
float m_fBetaWhenInterPol;
|
||||
float m_fFOVWhenInterPol;
|
||||
float m_fFOVSpeedAtStartInter;
|
||||
float m_fStartingBetaForInterPol;
|
||||
float m_fStartingAlphaForInterPol;
|
||||
float m_PedOrientForBehindOrInFront;
|
||||
float m_CameraAverageSpeed;
|
||||
float m_CameraSpeedSoFar;
|
||||
float m_fCamShakeForce;
|
||||
float m_fCarZoomValueScript;
|
||||
float m_fFovForTrain;
|
||||
float m_fFOV_Wide_Screen;
|
||||
float m_fNearClipScript;
|
||||
float m_fOldBetaDiff;
|
||||
float m_fPedZoomValue;
|
||||
|
||||
float m_fPedZoomValueScript;
|
||||
float m_fPedZoomValueSmooth;
|
||||
float m_fPositionAlongSpline;
|
||||
float m_ScreenReductionPercentage;
|
||||
float m_ScreenReductionSpeed;
|
||||
float m_AlphaForPlayerAnim1rstPerson;
|
||||
float Orientation;
|
||||
float PedZoomIndicator;
|
||||
float PlayerExhaustion;
|
||||
float SoundDistUp, SoundDistLeft, SoundDistRight;
|
||||
float SoundDistUpAsRead, SoundDistLeftAsRead, SoundDistRightAsRead;
|
||||
float SoundDistUpAsReadOld, SoundDistLeftAsReadOld, SoundDistRightAsReadOld;
|
||||
float m_fWideScreenReductionAmount;
|
||||
float m_fStartingFOVForInterPol;
|
||||
|
||||
// not static yet
|
||||
float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls
|
||||
float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls
|
||||
float m_f3rdPersonCHairMultX;
|
||||
float m_f3rdPersonCHairMultY;
|
||||
|
||||
|
||||
CCam Cams[3];
|
||||
void *pToGarageWeAreIn;
|
||||
void *pToGarageWeAreInForHackAvoidFirstPerson;
|
||||
CQueuedMode m_PlayerMode;
|
||||
CQueuedMode PlayerWeaponMode;
|
||||
CVector m_PreviousCameraPosition;
|
||||
CVector m_RealPreviousCameraPosition;
|
||||
CVector m_cvecAimingTargetCoors;
|
||||
CVector m_vecFixedModeVector;
|
||||
|
||||
// one of those has to go
|
||||
CVector m_vecFixedModeSource;
|
||||
CVector m_vecFixedModeUpOffSet;
|
||||
// CVector m_vecCutSceneOffset;
|
||||
CVector m_cvecStartingSourceForInterPol;
|
||||
CVector m_cvecStartingTargetForInterPol;
|
||||
CVector m_cvecStartingUpForInterPol;
|
||||
CVector m_cvecSourceSpeedAtStartInter;
|
||||
CVector m_cvecTargetSpeedAtStartInter;
|
||||
CVector m_cvecUpSpeedAtStartInter;
|
||||
CVector m_vecSourceWhenInterPol;
|
||||
CVector m_vecTargetWhenInterPol;
|
||||
CVector m_vecUpWhenInterPol;
|
||||
CVector m_vecClearGeometryVec;
|
||||
|
||||
CVector m_vecGameCamPos;
|
||||
CVector SourceDuringInter;
|
||||
CVector TargetDuringInter;
|
||||
CVector UpDuringInter;
|
||||
RwCamera *m_pRwCamera;
|
||||
CEntity *pTargetEntity;
|
||||
CCamPathSplines m_arrPathArray[4];
|
||||
CTrainCamNode m_arrTrainCamNode[800];
|
||||
CMatrix m_cameraMatrix;
|
||||
bool m_bGarageFixedCamPositionSet;
|
||||
bool m_vecDoingSpecialInterPolation;
|
||||
bool m_bScriptParametersSetForInterPol;
|
||||
bool m_bFading;
|
||||
bool m_bMusicFading;
|
||||
CMatrix m_viewMatrix;
|
||||
CVector m_vecFrustumNormals[4];
|
||||
CVector m_vecOldSourceForInter;
|
||||
CVector m_vecOldFrontForInter;
|
||||
CVector m_vecOldUpForInter;
|
||||
|
||||
float m_vecOldFOVForInter;
|
||||
float m_fFLOATingFade;
|
||||
float m_fFLOATingFadeMusic;
|
||||
float m_fTimeToFadeOut;
|
||||
float m_fTimeToFadeMusic;
|
||||
float m_fFractionInterToStopMovingTarget;
|
||||
float m_fFractionInterToStopCatchUpTarget;
|
||||
float m_fGaitSwayBuffer;
|
||||
float m_fScriptPercentageInterToStopMoving;
|
||||
float m_fScriptPercentageInterToCatchUp;
|
||||
|
||||
uint32 m_fScriptTimeForInterPolation;
|
||||
|
||||
|
||||
int16 m_iFadingDirection;
|
||||
int m_iModeObbeCamIsInForCar;
|
||||
int16 m_iModeToGoTo;
|
||||
int16 m_iMusicFadingDirection;
|
||||
int16 m_iTypeOfSwitch;
|
||||
|
||||
uint32 m_uiFadeTimeStarted;
|
||||
uint32 m_uiFadeTimeStartedMusic;
|
||||
|
||||
static bool &m_bUseMouse3rdPerson;
|
||||
|
||||
CMatrix &GetCameraMatrix(void) { return m_cameraMatrix; }
|
||||
CVector &GetGameCamPosition(void) { return m_vecGameCamPos; }
|
||||
bool IsPointVisible(const CVector ¢er, const CMatrix *mat);
|
||||
bool IsSphereVisible(const CVector ¢er, float radius, const CMatrix *mat);
|
||||
bool IsBoxVisible(RwV3d *box, const CMatrix *mat);
|
||||
int GetLookDirection(void);
|
||||
|
||||
void Fade(float timeout, int16 direction);
|
||||
int GetScreenFadeStatus(void);
|
||||
void ProcessFade(void);
|
||||
void ProcessMusicFade(void);
|
||||
void SetFadeColour(uint8 r, uint8 g, uint8 b);
|
||||
|
||||
void SetMotionBlur(int r, int g, int b, int a, int type);
|
||||
void SetMotionBlurAlpha(int a);
|
||||
void RenderMotionBlur(void);
|
||||
void ClearPlayerWeaponMode();
|
||||
void CalculateDerivedValues(void);
|
||||
|
||||
void DrawBordersForWideScreen(void);
|
||||
void Restore(void);
|
||||
void SetWidescreenOff(void);
|
||||
|
||||
void dtor(void) { this->CCamera::~CCamera(); }
|
||||
};
|
||||
static_assert(offsetof(CCamera, m_WideScreenOn) == 0x70, "CCamera: error");
|
||||
static_assert(offsetof(CCamera, WorldViewerBeingUsed) == 0x75, "CCamera: error");
|
||||
static_assert(offsetof(CCamera, m_uiNumberOfTrainCamNodes) == 0x84, "CCamera: error");
|
||||
static_assert(offsetof(CCamera, m_uiTransitionState) == 0x89, "CCamera: error");
|
||||
static_assert(offsetof(CCamera, m_uiTimeTransitionStart) == 0x94, "CCamera: error");
|
||||
static_assert(offsetof(CCamera, m_BlurBlue) == 0x9C, "CCamera: error");
|
||||
static_assert(offsetof(CCamera, Cams) == 0x1A4, "CCamera: error");
|
||||
static_assert(sizeof(CCamera) == 0xE9D8, "CCamera: wrong size");
|
||||
extern CCamera &TheCamera;
|
||||
529
src/core/CdStream.cpp
Normal file
529
src/core/CdStream.cpp
Normal file
@@ -0,0 +1,529 @@
|
||||
#include <windows.h>
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "CdStream.h"
|
||||
#include "rwcore.h"
|
||||
#include "RwHelper.h"
|
||||
|
||||
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", __VA_ARGS__)
|
||||
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", __VA_ARGS__)
|
||||
|
||||
struct CdReadInfo
|
||||
{
|
||||
uint32 nSectorOffset;
|
||||
uint32 nSectorsToRead;
|
||||
void *pBuffer;
|
||||
char field_C;
|
||||
bool bLocked;
|
||||
bool bInUse;
|
||||
char _pad0;
|
||||
int32 nStatus;
|
||||
HANDLE hSemaphore;
|
||||
HANDLE hFile;
|
||||
OVERLAPPED Overlapped;
|
||||
};
|
||||
VALIDATE_SIZE(CdReadInfo, 0x30);
|
||||
|
||||
char gCdImageNames[MAX_CDIMAGES+1][64];
|
||||
int32 gNumImages;
|
||||
int32 gNumChannels;
|
||||
|
||||
HANDLE gImgFiles[MAX_CDIMAGES];
|
||||
|
||||
HANDLE _gCdStreamThread;
|
||||
HANDLE gCdStreamSema;
|
||||
DWORD _gCdStreamThreadId;
|
||||
|
||||
CdReadInfo *gpReadInfo;
|
||||
Queue gChannelRequestQ;
|
||||
|
||||
int32 lastPosnRead;
|
||||
|
||||
BOOL _gbCdStreamOverlapped;
|
||||
BOOL _gbCdStreamAsync;
|
||||
DWORD _gdwCdStreamFlags;
|
||||
|
||||
|
||||
void
|
||||
CdStreamInitThread(void)
|
||||
{
|
||||
SetLastError(0);
|
||||
|
||||
if ( gNumChannels > 0 )
|
||||
{
|
||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
||||
{
|
||||
gpReadInfo[i].hSemaphore = CreateSemaphore(nil, 0, 2, nil);
|
||||
|
||||
if ( gpReadInfo[i].hSemaphore == nil )
|
||||
{
|
||||
CDTRACE("failed to create sync semaphore");
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gChannelRequestQ.items = (int32 *)LocalAlloc(LMEM_ZEROINIT, sizeof(int32) * (gNumChannels + 1));
|
||||
gChannelRequestQ.head = 0;
|
||||
gChannelRequestQ.tail = 0;
|
||||
gChannelRequestQ.size = gNumChannels + 1;
|
||||
ASSERT(gChannelRequestQ.items != nil );
|
||||
|
||||
gCdStreamSema = CreateSemaphore(nil, 0, 5, "CdStream");
|
||||
|
||||
if ( gCdStreamSema == nil )
|
||||
{
|
||||
CDTRACE("failed to create stream semaphore");
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
_gCdStreamThread = CreateThread(nil, 64*1024/*64KB*/, CdStreamThread, nil, CREATE_SUSPENDED, &_gCdStreamThreadId);
|
||||
|
||||
if ( _gCdStreamThread == nil )
|
||||
{
|
||||
CDTRACE("failed to create streaming thread");
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
SetThreadPriority(_gCdStreamThread, GetThreadPriority(GetCurrentThread()) - 1);
|
||||
|
||||
ResumeThread(_gCdStreamThread);
|
||||
}
|
||||
|
||||
void
|
||||
CdStreamInit(int32 numChannels)
|
||||
{
|
||||
DWORD SectorsPerCluster;
|
||||
DWORD BytesPerSector;
|
||||
DWORD NumberOfFreeClusters;
|
||||
DWORD TotalNumberOfClusters;
|
||||
|
||||
GetDiskFreeSpace(nil, &SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters);
|
||||
|
||||
_gdwCdStreamFlags = 0;
|
||||
|
||||
if ( BytesPerSector <= CDSTREAM_SECTOR_SIZE )
|
||||
{
|
||||
_gdwCdStreamFlags |= FILE_FLAG_NO_BUFFERING;
|
||||
debug("Using no buffered loading for streaming\n");
|
||||
}
|
||||
|
||||
_gbCdStreamOverlapped = TRUE;
|
||||
|
||||
_gdwCdStreamFlags |= FILE_FLAG_OVERLAPPED;
|
||||
|
||||
_gbCdStreamAsync = FALSE;
|
||||
|
||||
void *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, BytesPerSector);
|
||||
ASSERT( pBuffer != nil );
|
||||
|
||||
SetLastError(0);
|
||||
|
||||
gNumImages = 0;
|
||||
|
||||
gNumChannels = numChannels;
|
||||
|
||||
gpReadInfo = (CdReadInfo *)LocalAlloc(LMEM_ZEROINIT, sizeof(CdReadInfo) * numChannels);
|
||||
ASSERT( gpReadInfo != nil );
|
||||
|
||||
CDDEBUG("read info %p", gpReadInfo);
|
||||
|
||||
CdStreamAddImage("MODELS\\GTA3.IMG");
|
||||
|
||||
int32 nStatus = CdStreamRead(0, pBuffer, 0, 1);
|
||||
|
||||
CdStreamRemoveImages();
|
||||
|
||||
if ( nStatus == STREAM_SUCCESS )
|
||||
{
|
||||
_gbCdStreamAsync = TRUE;
|
||||
|
||||
debug("Using async loading for streaming\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
_gdwCdStreamFlags &= ~FILE_FLAG_OVERLAPPED;
|
||||
|
||||
_gbCdStreamOverlapped = FALSE;
|
||||
|
||||
_gbCdStreamAsync = TRUE;
|
||||
|
||||
debug("Using sync loading for streaming\n");
|
||||
}
|
||||
|
||||
CdStreamInitThread();
|
||||
|
||||
ASSERT( pBuffer != nil );
|
||||
RwFreeAlign(pBuffer);
|
||||
}
|
||||
|
||||
uint32
|
||||
GetGTA3ImgSize(void)
|
||||
{
|
||||
ASSERT( gImgFiles[0] != nil );
|
||||
return (uint32)GetFileSize(gImgFiles[0], nil);
|
||||
}
|
||||
|
||||
void
|
||||
CdStreamShutdown(void)
|
||||
{
|
||||
if ( _gbCdStreamAsync )
|
||||
{
|
||||
LocalFree(gChannelRequestQ.items);
|
||||
CloseHandle(gCdStreamSema);
|
||||
CloseHandle(_gCdStreamThread);
|
||||
|
||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
||||
CloseHandle(gpReadInfo[i].hSemaphore);
|
||||
}
|
||||
|
||||
LocalFree(gpReadInfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32
|
||||
CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)
|
||||
{
|
||||
ASSERT( channel < gNumChannels );
|
||||
ASSERT( buffer != nil );
|
||||
|
||||
lastPosnRead = size + offset;
|
||||
|
||||
ASSERT( _GET_INDEX(offset) < MAX_CDIMAGES );
|
||||
HANDLE hImage = gImgFiles[_GET_INDEX(offset)];
|
||||
ASSERT( hImage != nil );
|
||||
|
||||
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != nil );
|
||||
|
||||
pChannel->hFile = hImage;
|
||||
|
||||
SetLastError(0);
|
||||
|
||||
if ( _gbCdStreamAsync )
|
||||
{
|
||||
if ( pChannel->nSectorsToRead != 0 || pChannel->bInUse )
|
||||
return STREAM_NONE;
|
||||
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
pChannel->nSectorOffset = _GET_OFFSET(offset);
|
||||
pChannel->nSectorsToRead = size;
|
||||
pChannel->pBuffer = buffer;
|
||||
pChannel->bLocked = 0;
|
||||
|
||||
AddToQueue(&gChannelRequestQ, channel);
|
||||
|
||||
if ( !ReleaseSemaphore(gCdStreamSema, 1, nil) )
|
||||
printf("Signal Sema Error\n");
|
||||
|
||||
return STREAM_SUCCESS;
|
||||
}
|
||||
|
||||
if ( _gbCdStreamOverlapped )
|
||||
{
|
||||
ASSERT( channel < gNumChannels );
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != nil );
|
||||
|
||||
pChannel->Overlapped.Offset = _GET_OFFSET(offset) * CDSTREAM_SECTOR_SIZE;
|
||||
|
||||
if ( !ReadFile(hImage, buffer, size * CDSTREAM_SECTOR_SIZE, NULL, &pChannel->Overlapped)
|
||||
&& GetLastError() != ERROR_IO_PENDING )
|
||||
return STREAM_NONE;
|
||||
else
|
||||
return STREAM_SUCCESS;
|
||||
}
|
||||
|
||||
SetFilePointer(hImage, _GET_OFFSET(offset) * CDSTREAM_SECTOR_SIZE, nil, FILE_BEGIN);
|
||||
|
||||
DWORD NumberOfBytesRead;
|
||||
|
||||
if ( !ReadFile(hImage, buffer, size * CDSTREAM_SECTOR_SIZE, &NumberOfBytesRead, nil) )
|
||||
return STREAM_NONE;
|
||||
else
|
||||
return STREAM_SUCCESS;
|
||||
}
|
||||
|
||||
int32
|
||||
CdStreamGetStatus(int32 channel)
|
||||
{
|
||||
ASSERT( channel < gNumChannels );
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != nil );
|
||||
|
||||
if ( _gbCdStreamAsync )
|
||||
{
|
||||
if ( pChannel->bInUse )
|
||||
return STREAM_READING;
|
||||
|
||||
if ( pChannel->nSectorsToRead != 0 )
|
||||
return STREAM_WAITING;
|
||||
|
||||
if ( pChannel->nStatus != STREAM_NONE )
|
||||
{
|
||||
int32 status = pChannel->nStatus;
|
||||
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
return STREAM_NONE;
|
||||
}
|
||||
|
||||
if ( _gbCdStreamOverlapped )
|
||||
{
|
||||
ASSERT( pChannel->hFile != nil );
|
||||
if ( WaitForSingleObjectEx(pChannel->hFile, 0, TRUE) == WAIT_OBJECT_0 )
|
||||
return STREAM_NONE;
|
||||
else
|
||||
return STREAM_READING;
|
||||
}
|
||||
|
||||
return STREAM_NONE;
|
||||
}
|
||||
|
||||
int32
|
||||
CdStreamGetLastPosn(void)
|
||||
{
|
||||
return lastPosnRead;
|
||||
}
|
||||
|
||||
int32
|
||||
CdStreamSync(int32 channel)
|
||||
{
|
||||
ASSERT( channel < gNumChannels );
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != nil );
|
||||
|
||||
if ( _gbCdStreamAsync )
|
||||
{
|
||||
if ( pChannel->nSectorsToRead != 0 )
|
||||
{
|
||||
pChannel->bLocked = true;
|
||||
|
||||
ASSERT( pChannel->hSemaphore != nil );
|
||||
|
||||
WaitForSingleObject(pChannel->hSemaphore, INFINITE);
|
||||
}
|
||||
|
||||
pChannel->bInUse = false;
|
||||
|
||||
return pChannel->nStatus;
|
||||
}
|
||||
|
||||
DWORD NumberOfBytesTransferred;
|
||||
|
||||
if ( _gbCdStreamOverlapped && pChannel->hFile )
|
||||
{
|
||||
ASSERT(pChannel->hFile != nil );
|
||||
if ( GetOverlappedResult(pChannel->hFile, &pChannel->Overlapped, &NumberOfBytesTransferred, TRUE) )
|
||||
return STREAM_NONE;
|
||||
else
|
||||
return STREAM_ERROR;
|
||||
}
|
||||
|
||||
return STREAM_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
AddToQueue(Queue *queue, int32 item)
|
||||
{
|
||||
ASSERT( queue != nil );
|
||||
ASSERT( queue->items != nil );
|
||||
queue->items[queue->tail] = item;
|
||||
|
||||
queue->tail = (queue->tail + 1) % queue->size;
|
||||
|
||||
if ( queue->head == queue->tail )
|
||||
debug("Queue is full\n");
|
||||
}
|
||||
|
||||
int32
|
||||
GetFirstInQueue(Queue *queue)
|
||||
{
|
||||
ASSERT( queue != nil );
|
||||
if ( queue->head == queue->tail )
|
||||
return -1;
|
||||
|
||||
ASSERT( queue->items != nil );
|
||||
return queue->items[queue->head];
|
||||
}
|
||||
|
||||
void
|
||||
RemoveFirstInQueue(Queue *queue)
|
||||
{
|
||||
ASSERT( queue != nil );
|
||||
if ( queue->head == queue->tail )
|
||||
{
|
||||
debug("Queue is empty\n");
|
||||
return;
|
||||
}
|
||||
|
||||
queue->head = (queue->head + 1) % queue->size;
|
||||
}
|
||||
|
||||
DWORD
|
||||
WINAPI CdStreamThread(LPVOID lpThreadParameter)
|
||||
{
|
||||
debug("Created cdstream thread\n");
|
||||
|
||||
while ( true )
|
||||
{
|
||||
WaitForSingleObject(gCdStreamSema, INFINITE);
|
||||
|
||||
int32 channel = GetFirstInQueue(&gChannelRequestQ);
|
||||
ASSERT( channel < gNumChannels );
|
||||
|
||||
CdReadInfo *pChannel = &gpReadInfo[channel];
|
||||
ASSERT( pChannel != nil );
|
||||
|
||||
pChannel->bInUse = true;
|
||||
|
||||
if ( pChannel->nStatus == STREAM_NONE )
|
||||
{
|
||||
if ( _gbCdStreamOverlapped )
|
||||
{
|
||||
pChannel->Overlapped.Offset = pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE;
|
||||
|
||||
ASSERT(pChannel->hFile != nil );
|
||||
ASSERT(pChannel->pBuffer != nil );
|
||||
|
||||
DWORD NumberOfBytesTransferred;
|
||||
|
||||
if ( ReadFile(pChannel->hFile,
|
||||
pChannel->pBuffer,
|
||||
pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE,
|
||||
NULL,
|
||||
&pChannel->Overlapped) )
|
||||
{
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
}
|
||||
else if ( GetLastError() == ERROR_IO_PENDING
|
||||
&& GetOverlappedResult(pChannel->hFile, &pChannel->Overlapped, &NumberOfBytesTransferred, TRUE) )
|
||||
{
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pChannel->nStatus = STREAM_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(pChannel->hFile != nil );
|
||||
ASSERT(pChannel->pBuffer != nil );
|
||||
|
||||
SetFilePointer(pChannel->hFile, pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE, nil, FILE_BEGIN);
|
||||
|
||||
DWORD NumberOfBytesRead;
|
||||
if ( ReadFile(pChannel->hFile,
|
||||
pChannel->pBuffer,
|
||||
pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE,
|
||||
&NumberOfBytesRead,
|
||||
NULL) )
|
||||
{
|
||||
pChannel->nStatus = STREAM_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RemoveFirstInQueue(&gChannelRequestQ);
|
||||
|
||||
pChannel->nSectorsToRead = 0;
|
||||
|
||||
if ( pChannel->bLocked )
|
||||
{
|
||||
ASSERT( pChannel->hSemaphore != nil );
|
||||
ReleaseSemaphore(pChannel->hSemaphore, 1, NULL);
|
||||
}
|
||||
|
||||
pChannel->bInUse = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CdStreamAddImage(char const *path)
|
||||
{
|
||||
ASSERT(path != nil);
|
||||
ASSERT(gNumImages < MAX_CDIMAGES);
|
||||
|
||||
SetLastError(0);
|
||||
|
||||
gImgFiles[gNumImages] = CreateFile(path,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
nil,
|
||||
OPEN_EXISTING,
|
||||
_gdwCdStreamFlags | FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_READONLY,
|
||||
nil);
|
||||
|
||||
ASSERT( gImgFiles[gNumImages] != nil );
|
||||
if ( gImgFiles[gNumImages] == NULL )
|
||||
return false;
|
||||
|
||||
strcpy(gCdImageNames[gNumImages], path);
|
||||
|
||||
gNumImages++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char *
|
||||
CdStreamGetImageName(int32 cd)
|
||||
{
|
||||
ASSERT(cd < MAX_CDIMAGES);
|
||||
if ( gImgFiles[cd] != nil )
|
||||
return gCdImageNames[cd];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
CdStreamRemoveImages(void)
|
||||
{
|
||||
for ( int32 i = 0; i < gNumChannels; i++ )
|
||||
CdStreamSync(i);
|
||||
|
||||
for ( int32 i = 0; i < gNumImages; i++ )
|
||||
{
|
||||
SetLastError(0);
|
||||
|
||||
CloseHandle(gImgFiles[i]);
|
||||
gImgFiles[i] = nil;
|
||||
}
|
||||
|
||||
gNumImages = 0;
|
||||
}
|
||||
|
||||
int32
|
||||
CdStreamGetNumImages(void)
|
||||
{
|
||||
return gNumImages;
|
||||
}
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x405B50, CdStreamInitThread, PATCH_JUMP);
|
||||
InjectHook(0x405C80, CdStreamInit, PATCH_JUMP);
|
||||
//InjectHook(0x405DB0, debug, PATCH_JUMP);
|
||||
InjectHook(0x405DC0, GetGTA3ImgSize, PATCH_JUMP);
|
||||
InjectHook(0x405DD0, CdStreamShutdown, PATCH_JUMP);
|
||||
InjectHook(0x405E40, CdStreamRead, PATCH_JUMP);
|
||||
InjectHook(0x405F90, CdStreamGetStatus, PATCH_JUMP);
|
||||
InjectHook(0x406000, CdStreamGetLastPosn, PATCH_JUMP);
|
||||
InjectHook(0x406010, CdStreamSync, PATCH_JUMP);
|
||||
InjectHook(0x4060B0, AddToQueue, PATCH_JUMP);
|
||||
InjectHook(0x4060F0, GetFirstInQueue, PATCH_JUMP);
|
||||
InjectHook(0x406110, RemoveFirstInQueue, PATCH_JUMP);
|
||||
InjectHook(0x406140, CdStreamThread, PATCH_JUMP);
|
||||
InjectHook(0x406270, CdStreamAddImage, PATCH_JUMP);
|
||||
InjectHook(0x4062E0, CdStreamGetImageName, PATCH_JUMP);
|
||||
InjectHook(0x406300, CdStreamRemoveImages, PATCH_JUMP);
|
||||
InjectHook(0x406370, CdStreamGetNumImages, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
46
src/core/CdStream.h
Normal file
46
src/core/CdStream.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#define CDSTREAM_SECTOR_SIZE 2048
|
||||
|
||||
#define _GET_INDEX(a) (a >> 24)
|
||||
#define _GET_OFFSET(a) (a & 0xFFFFFF)
|
||||
|
||||
enum
|
||||
{
|
||||
STREAM_NONE = uint8( 0),
|
||||
STREAM_SUCCESS = uint8( 1),
|
||||
STREAM_READING = uint8(-1), // 0xFF,
|
||||
STREAM_ERROR = uint8(-2), // 0xFE,
|
||||
STREAM_ERROR_NOCD = uint8(-3), // 0xFD,
|
||||
STREAM_ERROR_WRONGCD = uint8(-4), // 0xFC,
|
||||
STREAM_ERROR_OPENCD = uint8(-5), // 0xFB,
|
||||
STREAM_WAITING = uint8(-6) // 0xFA,
|
||||
};
|
||||
|
||||
struct Queue
|
||||
{
|
||||
int32 *items;
|
||||
int32 head;
|
||||
int32 tail;
|
||||
int32 size;
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(Queue, 0x10);
|
||||
|
||||
|
||||
void CdStreamInitThread(void);
|
||||
void CdStreamInit(int32 numChannels);
|
||||
uint32 GetGTA3ImgSize(void);
|
||||
void CdStreamShutdown(void);
|
||||
int32 CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size);
|
||||
int32 CdStreamGetStatus(int32 channel);
|
||||
int32 CdStreamGetLastPosn(void);
|
||||
int32 CdStreamSync(int32 channel);
|
||||
void AddToQueue(Queue *queue, int32 item);
|
||||
int32 GetFirstInQueue(Queue *queue);
|
||||
void RemoveFirstInQueue(Queue *queue);
|
||||
DWORD WINAPI CdStreamThread(LPVOID lpThreadParameter);
|
||||
bool CdStreamAddImage(char const *path);
|
||||
char *CdStreamGetImageName(int32 cd);
|
||||
void CdStreamRemoveImages(void);
|
||||
int32 CdStreamGetNumImages(void);
|
||||
131
src/core/Clock.cpp
Normal file
131
src/core/Clock.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Timer.h"
|
||||
#include "Pad.h"
|
||||
#include "Clock.h"
|
||||
#include "Stats.h"
|
||||
|
||||
_TODO("gbFastTime");
|
||||
bool &gbFastTime = *(bool*)0x95CDBB;
|
||||
|
||||
uint8 &CClock::ms_nGameClockHours = *(uint8*)0x95CDA6;
|
||||
uint8 &CClock::ms_nGameClockMinutes = *(uint8*)0x95CDC8;
|
||||
uint16 &CClock::ms_nGameClockSeconds = *(uint16*)0x95CC7C;
|
||||
uint8 &CClock::ms_Stored_nGameClockHours = *(uint8*)0x95CD7B;
|
||||
uint8 &CClock::ms_Stored_nGameClockMinutes = *(uint8*)0x95CD9B;
|
||||
uint16 &CClock::ms_Stored_nGameClockSeconds = *(uint16*)0x95CC9C;
|
||||
uint32 &CClock::ms_nMillisecondsPerGameMinute = *(uint32*)0x8F2C64;
|
||||
int32 &CClock::ms_nLastClockTick = *(int32*)0x9430E4;
|
||||
bool &CClock::ms_bClockHasBeenStored = *(bool*)0x95CD82;
|
||||
|
||||
void
|
||||
CClock::Initialise(uint32 scale)
|
||||
{
|
||||
debug("Initialising CClock...\n");
|
||||
ms_nGameClockHours = 12;
|
||||
ms_nGameClockMinutes = 0;
|
||||
ms_nGameClockSeconds = 0;
|
||||
ms_nMillisecondsPerGameMinute = scale;
|
||||
ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
|
||||
ms_bClockHasBeenStored = false;
|
||||
debug("CClock ready\n");
|
||||
}
|
||||
|
||||
void
|
||||
CClock::Update(void)
|
||||
{
|
||||
if(CPad::GetPad(1)->GetRightShoulder1())
|
||||
{
|
||||
ms_nGameClockMinutes += 8;
|
||||
ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
|
||||
|
||||
if(ms_nGameClockMinutes >= 60)
|
||||
{
|
||||
ms_nGameClockHours++;
|
||||
ms_nGameClockMinutes = 0;
|
||||
if(ms_nGameClockHours >= 24)
|
||||
ms_nGameClockHours = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else if(CTimer::GetTimeInMilliseconds() - ms_nLastClockTick > ms_nMillisecondsPerGameMinute || gbFastTime)
|
||||
{
|
||||
ms_nGameClockMinutes++;
|
||||
ms_nLastClockTick += ms_nMillisecondsPerGameMinute;
|
||||
|
||||
if ( gbFastTime )
|
||||
ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
|
||||
|
||||
if(ms_nGameClockMinutes >= 60)
|
||||
{
|
||||
ms_nGameClockHours++;
|
||||
ms_nGameClockMinutes = 0;
|
||||
if(ms_nGameClockHours >= 24)
|
||||
{
|
||||
CStats::DaysPassed++;
|
||||
ms_nGameClockHours = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
ms_nGameClockSeconds +=
|
||||
60
|
||||
* (CTimer::GetTimeInMilliseconds() - ms_nLastClockTick)
|
||||
/ ms_nMillisecondsPerGameMinute;
|
||||
}
|
||||
|
||||
void
|
||||
CClock::SetGameClock(uint8 h, uint8 m)
|
||||
{
|
||||
ms_nGameClockHours = h;
|
||||
ms_nGameClockMinutes = m;
|
||||
ms_nGameClockSeconds = 0;
|
||||
ms_nLastClockTick = CTimer::GetTimeInMilliseconds();
|
||||
}
|
||||
|
||||
int32
|
||||
CClock::GetGameClockMinutesUntil(uint8 h, uint8 m)
|
||||
{
|
||||
int32 now, then;
|
||||
now = ms_nGameClockHours*60 + ms_nGameClockMinutes;
|
||||
then = h*60 + m;
|
||||
if(then < now)
|
||||
then += 24*60;
|
||||
return then-now;
|
||||
}
|
||||
|
||||
bool
|
||||
CClock::GetIsTimeInRange(uint8 h1, uint8 h2)
|
||||
{
|
||||
if(h1 > h2)
|
||||
return ms_nGameClockHours >= h1 || ms_nGameClockHours < h2;
|
||||
else
|
||||
return ms_nGameClockHours >= h1 && ms_nGameClockHours < h2;
|
||||
}
|
||||
|
||||
void
|
||||
CClock::StoreClock(void)
|
||||
{
|
||||
ms_Stored_nGameClockHours = ms_nGameClockHours;
|
||||
ms_Stored_nGameClockMinutes = ms_nGameClockMinutes;
|
||||
ms_Stored_nGameClockSeconds = ms_nGameClockSeconds;
|
||||
ms_bClockHasBeenStored = true;
|
||||
}
|
||||
|
||||
void
|
||||
CClock::RestoreClock(void)
|
||||
{
|
||||
ms_nGameClockHours = ms_Stored_nGameClockHours;
|
||||
ms_nGameClockMinutes = ms_Stored_nGameClockMinutes;
|
||||
ms_nGameClockSeconds = ms_Stored_nGameClockSeconds;
|
||||
}
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x473370, CClock::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x473460, CClock::Update, PATCH_JUMP);
|
||||
InjectHook(0x4733C0, CClock::SetGameClock, PATCH_JUMP);
|
||||
InjectHook(0x4733F0, CClock::GetGameClockMinutesUntil, PATCH_JUMP);
|
||||
InjectHook(0x473420, CClock::GetIsTimeInRange, PATCH_JUMP);
|
||||
InjectHook(0x473540, CClock::StoreClock, PATCH_JUMP);
|
||||
InjectHook(0x473570, CClock::RestoreClock, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
31
src/core/Clock.h
Normal file
31
src/core/Clock.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
class CClock
|
||||
{
|
||||
static uint8 &ms_nGameClockHours;
|
||||
static uint8 &ms_nGameClockMinutes;
|
||||
static uint16 &ms_nGameClockSeconds;
|
||||
static uint8 &ms_Stored_nGameClockHours;
|
||||
static uint8 &ms_Stored_nGameClockMinutes;
|
||||
static uint16 &ms_Stored_nGameClockSeconds;
|
||||
static uint32 &ms_nMillisecondsPerGameMinute;
|
||||
static int32 &ms_nLastClockTick;
|
||||
static bool &ms_bClockHasBeenStored;
|
||||
public:
|
||||
|
||||
static void Initialise(uint32 scale);
|
||||
static void Update(void);
|
||||
static void SetGameClock(uint8 h, uint8 m);
|
||||
static int32 GetGameClockMinutesUntil(uint8 h, uint8 m);
|
||||
static bool GetIsTimeInRange(uint8 h1, uint8 h2);
|
||||
static void StoreClock(void);
|
||||
static void RestoreClock(void);
|
||||
|
||||
static uint8 GetHours(void) { return ms_nGameClockHours; }
|
||||
static uint8 GetMinutes(void) { return ms_nGameClockMinutes; }
|
||||
static int16 GetSeconds(void) { return ms_nGameClockSeconds; }
|
||||
|
||||
|
||||
static uint8 &GetHoursRef(void) { return ms_nGameClockHours; }
|
||||
static uint8 &GetMinutesRef(void) { return ms_nGameClockMinutes; }
|
||||
};
|
||||
1887
src/core/Collision.cpp
Normal file
1887
src/core/Collision.cpp
Normal file
File diff suppressed because it is too large
Load Diff
157
src/core/Collision.h
Normal file
157
src/core/Collision.h
Normal file
@@ -0,0 +1,157 @@
|
||||
#pragma once
|
||||
|
||||
#include "templates.h"
|
||||
#include "Game.h" // for eLevelName
|
||||
|
||||
struct CColSphere
|
||||
{
|
||||
CVector center;
|
||||
float radius;
|
||||
uint8 surface;
|
||||
uint8 piece;
|
||||
|
||||
void Set(float radius, const CVector ¢er, uint8 surf, uint8 piece);
|
||||
void Set(float radius, const CVector ¢er) { 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
|
||||
{
|
||||
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);
|
||||
|
||||
CColLine *ctor(CVector *p0, CVector *p1) { return ::new (this) CColLine(*p0, *p1); }
|
||||
};
|
||||
|
||||
struct CColTriangle
|
||||
{
|
||||
uint16 a;
|
||||
uint16 b;
|
||||
uint16 c;
|
||||
uint8 surface;
|
||||
|
||||
void Set(const CVector *v, int a, int b, int c, uint8 surf, uint8 piece);
|
||||
};
|
||||
|
||||
struct CColTrianglePlane
|
||||
{
|
||||
CVector normal;
|
||||
float dist;
|
||||
uint8 dir;
|
||||
|
||||
void Set(const CVector *v, CColTriangle &tri);
|
||||
void GetNormal(CVector &n) const { n = normal; }
|
||||
float CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct CStoredCollPoly
|
||||
{
|
||||
CVector verts[3];
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct CColModel
|
||||
{
|
||||
CColSphere boundingSphere;
|
||||
CColBox boundingBox;
|
||||
short numSpheres;
|
||||
short numLines;
|
||||
short numBoxes;
|
||||
short numTriangles;
|
||||
int level;
|
||||
bool ownsCollisionVolumes;
|
||||
CColSphere *spheres;
|
||||
CColLine *lines;
|
||||
CColBox *boxes;
|
||||
CVector *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 *ctor(void) { return ::new (this) CColModel(); }
|
||||
void dtor(void) { this->CColModel::~CColModel(); }
|
||||
CColModel& operator=(const CColModel& other);
|
||||
};
|
||||
|
||||
class CCollision
|
||||
{
|
||||
public:
|
||||
static eLevelName &ms_collisionInMemory;
|
||||
static CLinkList<CColModel*> &ms_colModelCache;
|
||||
|
||||
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 CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);
|
||||
static bool TestLineSphere(const CColLine &line, const CColSphere &sph);
|
||||
static bool TestSphereTriangle(const CColSphere &sphere, const CVector *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 CVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly);
|
||||
static bool ProcessLineTriangle(const CColLine &line , const CVector *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 CVector *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 &matrix1, CColModel &model1, const CMatrix &matrix2, CColModel &model2, CColPoint *point1, CColPoint *point2, float *linedists);
|
||||
|
||||
// TODO:
|
||||
// CCollision::IsStoredPolyStillValidVerticalLine
|
||||
|
||||
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);
|
||||
};
|
||||
57
src/core/ControllerConfig.cpp
Normal file
57
src/core/ControllerConfig.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "ControllerConfig.h"
|
||||
#include "Pad.h"
|
||||
#include "FileMgr.h"
|
||||
|
||||
CControllerConfigManager &ControlsManager = *(CControllerConfigManager*)0x8F43A4;
|
||||
|
||||
WRAPPER void CControllerConfigManager::UpdateJoyButtonState(int padnumber) { EAXJMP(0x58F5B0); }
|
||||
WRAPPER void CControllerConfigManager::UpdateJoyInConfigMenus_ButtonDown(int button, int padnumber) { EAXJMP(0x58C5E0); }
|
||||
WRAPPER void CControllerConfigManager::AffectControllerStateOn_ButtonDown(int button, eControllerType type) { EAXJMP(0x58C730); }
|
||||
WRAPPER void CControllerConfigManager::UpdateJoyInConfigMenus_ButtonUp(int button, int padnumber) { EAXJMP(0x58CE80); }
|
||||
WRAPPER void CControllerConfigManager::AffectControllerStateOn_ButtonUp(int button, int padnumber) { EAXJMP(0x58CFD0); }
|
||||
WRAPPER void CControllerConfigManager::MakeControllerActionsBlank() { EAXJMP(0x58B7A0); }
|
||||
WRAPPER void CControllerConfigManager::InitDefaultControlConfiguration() { EAXJMP(0x58B930); }
|
||||
WRAPPER void CControllerConfigManager::InitDefaultControlConfigMouse(CMouseControllerState const &mousestate) { EAXJMP(0x58BD00); }
|
||||
WRAPPER int32 CControllerConfigManager::GetJoyButtonJustDown() { EAXJMP(0x58B7D0); }
|
||||
WRAPPER void CControllerConfigManager::InitDefaultControlConfigJoyPad(unsigned int buttons) { EAXJMP(0x58BD90); }
|
||||
WRAPPER void CControllerConfigManager::ClearSimButtonPressCheckers() { EAXJMP(0x58D220); }
|
||||
WRAPPER void CControllerConfigManager::AffectPadFromKeyBoard() { EAXJMP(0x58D0C0); }
|
||||
WRAPPER void CControllerConfigManager::AffectPadFromMouse() { EAXJMP(0x58D1A0); }
|
||||
|
||||
void CControllerConfigManager::LoadSettings(int32 file)
|
||||
{
|
||||
bool bValid = true;
|
||||
|
||||
if ( file )
|
||||
{
|
||||
char buff[29];
|
||||
CFileMgr::Read(file, buff, sizeof(buff));
|
||||
|
||||
if ( !strncmp(buff, "THIS FILE IS NOT VALID YET", sizeof(buff) - 3) )
|
||||
bValid = false;
|
||||
else
|
||||
CFileMgr::Seek(file, 0, 0);
|
||||
}
|
||||
|
||||
if ( bValid )
|
||||
{
|
||||
ControlsManager.MakeControllerActionsBlank();
|
||||
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
for ( int j = 0; j < 41; j++ )
|
||||
{
|
||||
CFileMgr::Read(file, (char *)&ControlsManager.m_aSettings[j][i], sizeof(tControllerConfigBind));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WRAPPER void CControllerConfigManager::SaveSettings(int32 file)
|
||||
{
|
||||
EAXJMP(0x58B800);
|
||||
}
|
||||
58
src/core/ControllerConfig.h
Normal file
58
src/core/ControllerConfig.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
// based on x-gtasa
|
||||
|
||||
enum eControllerType
|
||||
{
|
||||
KEYBOARD,
|
||||
OPTIONAL_EXTRA,
|
||||
MOUSE,
|
||||
JOYSTICK,
|
||||
};
|
||||
|
||||
class CMouseControllerState;
|
||||
|
||||
class CControllerConfigManager
|
||||
{
|
||||
public:
|
||||
struct tControllerConfigBind
|
||||
{
|
||||
RsKeyCodes m_Key;
|
||||
int32 m_ContSetOrder;
|
||||
};
|
||||
|
||||
bool field_0;
|
||||
char _pad0[3];
|
||||
DIJOYSTATE2 m_OldState;
|
||||
DIJOYSTATE2 m_NewState;
|
||||
wchar m_aActionNames[41][40];
|
||||
bool m_aButtonStates[17];
|
||||
char _pad1[3];
|
||||
tControllerConfigBind m_aSettings[41][4];
|
||||
uint8 m_aSimCheckers[4][4];
|
||||
bool m_bMouseAssociated;
|
||||
char _pad2[3];
|
||||
|
||||
void UpdateJoyButtonState(int padnumber);
|
||||
void UpdateJoyInConfigMenus_ButtonDown(int button, int padnumber);
|
||||
void AffectControllerStateOn_ButtonDown(int button, eControllerType type);
|
||||
void UpdateJoyInConfigMenus_ButtonUp(int button, int padnumber);
|
||||
void AffectControllerStateOn_ButtonUp(int button, int padnumber);
|
||||
|
||||
int32 GetJoyButtonJustDown();
|
||||
void LoadSettings(int32 file);
|
||||
void SaveSettings(int32 file);
|
||||
void MakeControllerActionsBlank();
|
||||
void InitDefaultControlConfiguration();
|
||||
void InitDefaultControlConfigMouse(CMouseControllerState const &mousestate);
|
||||
void InitDefaultControlConfigJoyPad(unsigned int buttons);
|
||||
void ClearSimButtonPressCheckers();
|
||||
void AffectPadFromKeyBoard();
|
||||
void AffectPadFromMouse();
|
||||
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(CControllerConfigManager, 0x143C);
|
||||
|
||||
extern CControllerConfigManager &ControlsManager;
|
||||
7
src/core/CutsceneMgr.cpp
Normal file
7
src/core/CutsceneMgr.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "CutsceneMgr.h"
|
||||
|
||||
bool &CCutsceneMgr::ms_running = *(bool*)0x95CCF5;
|
||||
bool &CCutsceneMgr::ms_cutsceneProcessing = *(bool*)0x95CD9F;
|
||||
CDirectory *&CCutsceneMgr::ms_pCutsceneDir = *(CDirectory**)0x8F5F88;
|
||||
15
src/core/CutsceneMgr.h
Normal file
15
src/core/CutsceneMgr.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
class CDirectory;
|
||||
|
||||
class CCutsceneMgr
|
||||
{
|
||||
static bool &ms_running;
|
||||
static bool &ms_cutsceneProcessing;
|
||||
|
||||
public:
|
||||
static CDirectory *&ms_pCutsceneDir;
|
||||
|
||||
static bool IsRunning(void) { return ms_running; }
|
||||
static bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; }
|
||||
};
|
||||
65
src/core/Directory.cpp
Normal file
65
src/core/Directory.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "FileMgr.h"
|
||||
#include "Directory.h"
|
||||
|
||||
CDirectory::CDirectory(int32 maxEntries)
|
||||
: numEntries(0), maxEntries(maxEntries)
|
||||
{
|
||||
entries = new DirectoryInfo[maxEntries];
|
||||
}
|
||||
|
||||
CDirectory::~CDirectory(void)
|
||||
{
|
||||
delete[] entries;
|
||||
}
|
||||
|
||||
void
|
||||
CDirectory::ReadDirFile(const char *filename)
|
||||
{
|
||||
int fd;
|
||||
DirectoryInfo dirinfo;
|
||||
|
||||
fd = CFileMgr::OpenFile(filename, "rb");
|
||||
while(CFileMgr::Read(fd, (char*)&dirinfo, sizeof(dirinfo)))
|
||||
AddItem(dirinfo);
|
||||
CFileMgr::CloseFile(fd);
|
||||
}
|
||||
|
||||
bool
|
||||
CDirectory::WriteDirFile(const char *filename)
|
||||
{
|
||||
int fd, n;
|
||||
fd = CFileMgr::OpenFileForWriting(filename);
|
||||
n = CFileMgr::Write(fd, (char*)entries, numEntries*sizeof(DirectoryInfo));
|
||||
CFileMgr::CloseFile(fd);
|
||||
return n == numEntries*sizeof(DirectoryInfo);
|
||||
}
|
||||
|
||||
void
|
||||
CDirectory::AddItem(const DirectoryInfo &dirinfo)
|
||||
{
|
||||
assert(numEntries < maxEntries);
|
||||
entries[numEntries++] = dirinfo;
|
||||
}
|
||||
|
||||
bool
|
||||
CDirectory::FindItem(const char *name, uint32 &offset, uint32 &size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < numEntries; i++)
|
||||
if(strcmpi(entries[i].name, name) == 0){
|
||||
offset = entries[i].offset;
|
||||
size = entries[i].size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x473630, &CDirectory::ReadDirFile, PATCH_JUMP);
|
||||
InjectHook(0x473690, &CDirectory::WriteDirFile, PATCH_JUMP);
|
||||
InjectHook(0x473600, &CDirectory::AddItem, PATCH_JUMP);
|
||||
InjectHook(0x4736E0, &CDirectory::FindItem, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
22
src/core/Directory.h
Normal file
22
src/core/Directory.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
class CDirectory
|
||||
{
|
||||
public:
|
||||
struct DirectoryInfo {
|
||||
uint32 offset;
|
||||
uint32 size;
|
||||
char name[24];
|
||||
};
|
||||
DirectoryInfo *entries;
|
||||
int32 maxEntries;
|
||||
int32 numEntries;
|
||||
|
||||
CDirectory(int32 maxEntries);
|
||||
~CDirectory(void);
|
||||
|
||||
void ReadDirFile(const char *filename);
|
||||
bool WriteDirFile(const char *filename);
|
||||
void AddItem(const DirectoryInfo &dirinfo);
|
||||
bool FindItem(const char *name, uint32 &offset, uint32 &size);
|
||||
};
|
||||
1182
src/core/FileLoader.cpp
Normal file
1182
src/core/FileLoader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
42
src/core/FileLoader.h
Normal file
42
src/core/FileLoader.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
class CFileLoader
|
||||
{
|
||||
static char ms_line[256];
|
||||
public:
|
||||
static void LoadLevel(const char *filename);
|
||||
static void LoadCollisionFromDatFile(int currlevel);
|
||||
static char *LoadLine(int fd);
|
||||
static RwTexDictionary *LoadTexDictionary(const char *filename);
|
||||
static void LoadCollisionFile(const char *filename);
|
||||
static void LoadCollisionModel(uint8 *buf, CColModel &model, char *name);
|
||||
static void LoadModelFile(const char *filename);
|
||||
static RpAtomic *FindRelatedModelInfoCB(RpAtomic *atomic, void *data);
|
||||
static void LoadClumpFile(const char *filename);
|
||||
static bool LoadClumpFile(RwStream *stream, uint32 id);
|
||||
static bool StartLoadClumpFile(RwStream *stream, uint32 id);
|
||||
static bool FinishLoadClumpFile(RwStream *stream, uint32 id);
|
||||
static bool LoadAtomicFile(RwStream *stream, uint32 id);
|
||||
static RpAtomic *SetRelatedModelInfoCB(RpAtomic *atomic, void *data);
|
||||
static RpClump *LoadAtomicFile2Return(const char *filename);
|
||||
static void AddTexDictionaries(RwTexDictionary *dst, RwTexDictionary *src);
|
||||
|
||||
static void LoadObjectTypes(const char *filename);
|
||||
static void LoadObject(const char *line);
|
||||
static void LoadTimeObject(const char *line);
|
||||
static void LoadClumpObject(const char *line);
|
||||
static void LoadVehicleObject(const char *line);
|
||||
static void LoadPedObject(const char *line);
|
||||
static int LoadPathHeader(const char *line, char *type);
|
||||
static void LoadPedPathNode(const char *line, int id, int node);
|
||||
static void LoadCarPathNode(const char *line, int id, int node);
|
||||
static void Load2dEffect(const char *line);
|
||||
|
||||
static void LoadScene(const char *filename);
|
||||
static void LoadObjectInstance(const char *line);
|
||||
static void LoadZone(const char *line);
|
||||
static void LoadCullZone(const char *line);
|
||||
static void LoadPickup(const char *line);
|
||||
|
||||
static void LoadMapZones(const char *filename);
|
||||
};
|
||||
300
src/core/FileMgr.cpp
Normal file
300
src/core/FileMgr.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <fcntl.h>
|
||||
#include <direct.h>
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "FileMgr.h"
|
||||
|
||||
const char *_psGetUserFilesFolder();
|
||||
|
||||
/*
|
||||
* Windows FILE is BROKEN for GTA.
|
||||
*
|
||||
* We need to support mapping between LF and CRLF for text files
|
||||
* but we do NOT want to end the file at the first sight of a SUB character.
|
||||
* So here is a simple implementation of a FILE interface that works like GTA expects.
|
||||
*/
|
||||
|
||||
struct myFILE
|
||||
{
|
||||
bool isText;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
#define NUMFILES 20
|
||||
static myFILE myfiles[NUMFILES];
|
||||
|
||||
/* Force file to open as binary but remember if it was text mode */
|
||||
static int
|
||||
myfopen(const char *filename, const char *mode)
|
||||
{
|
||||
int fd;
|
||||
char realmode[10], *p;
|
||||
|
||||
for(fd = 1; fd < NUMFILES; fd++)
|
||||
if(myfiles[fd].file == nil)
|
||||
goto found;
|
||||
return 0; // no free fd
|
||||
found:
|
||||
myfiles[fd].isText = strchr(mode, 'b') == nil;
|
||||
p = realmode;
|
||||
while(*mode)
|
||||
if(*mode != 't' && *mode != 'b')
|
||||
*p++ = *mode++;
|
||||
else
|
||||
mode++;
|
||||
*p++ = 'b';
|
||||
*p = '\0';
|
||||
myfiles[fd].file = fopen(filename, realmode);
|
||||
if(myfiles[fd].file == nil)
|
||||
return 0;
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int
|
||||
myfclose(int fd)
|
||||
{
|
||||
int ret;
|
||||
assert(fd < NUMFILES);
|
||||
if(myfiles[fd].file){
|
||||
ret = fclose(myfiles[fd].file);
|
||||
myfiles[fd].file = nil;
|
||||
return ret;
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
static int
|
||||
myfgetc(int fd)
|
||||
{
|
||||
int c;
|
||||
c = fgetc(myfiles[fd].file);
|
||||
if(myfiles[fd].isText && c == 015){
|
||||
/* translate CRLF to LF */
|
||||
c = fgetc(myfiles[fd].file);
|
||||
if(c == 012)
|
||||
return c;
|
||||
ungetc(c, myfiles[fd].file);
|
||||
return 015;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static int
|
||||
myfputc(int c, int fd)
|
||||
{
|
||||
/* translate LF to CRLF */
|
||||
if(myfiles[fd].isText && c == 012)
|
||||
fputc(015, myfiles[fd].file);
|
||||
return fputc(c, myfiles[fd].file);
|
||||
}
|
||||
|
||||
static char*
|
||||
myfgets(char *buf, int len, int fd)
|
||||
{
|
||||
int c;
|
||||
char *p;
|
||||
|
||||
p = buf;
|
||||
len--; // NUL byte
|
||||
while(len--){
|
||||
c = myfgetc(fd);
|
||||
if(c == EOF){
|
||||
if(p == buf)
|
||||
return nil;
|
||||
break;
|
||||
}
|
||||
*p++ = c;
|
||||
if(c == '\n')
|
||||
break;
|
||||
}
|
||||
*p = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int
|
||||
myfread(void *buf, size_t elt, size_t n, int fd)
|
||||
{
|
||||
if(myfiles[fd].isText){
|
||||
char *p;
|
||||
size_t i;
|
||||
int c;
|
||||
|
||||
n *= elt;
|
||||
p = (char*)buf;
|
||||
for(i = 0; i < n; i++){
|
||||
c = myfgetc(fd);
|
||||
if(c == EOF)
|
||||
break;
|
||||
*p++ = c;
|
||||
}
|
||||
return i / elt;
|
||||
}
|
||||
return fread(buf, elt, n, myfiles[fd].file);
|
||||
}
|
||||
|
||||
static int
|
||||
myfwrite(void *buf, size_t elt, size_t n, int fd)
|
||||
{
|
||||
if(myfiles[fd].isText){
|
||||
char *p;
|
||||
size_t i;
|
||||
int c;
|
||||
|
||||
n *= elt;
|
||||
p = (char*)buf;
|
||||
for(i = 0; i < n; i++){
|
||||
c = *p++;
|
||||
myfputc(c, fd);
|
||||
if(feof(myfiles[fd].file)) // is this right?
|
||||
break;
|
||||
}
|
||||
return i / elt;
|
||||
}
|
||||
return fwrite(buf, elt, n, myfiles[fd].file);
|
||||
}
|
||||
|
||||
static int
|
||||
myfseek(int fd, long offset, int whence)
|
||||
{
|
||||
return fseek(myfiles[fd].file, offset, whence);
|
||||
}
|
||||
|
||||
static int
|
||||
myfeof(int fd)
|
||||
{
|
||||
return feof(myfiles[fd].file);
|
||||
// return ferror(myfiles[fd].file);
|
||||
}
|
||||
|
||||
|
||||
char *CFileMgr::ms_rootDirName = (char*)0x5F18F8;
|
||||
char *CFileMgr::ms_dirName = (char*)0x713CA8;
|
||||
|
||||
void
|
||||
CFileMgr::Initialise(void)
|
||||
{
|
||||
_getcwd(ms_rootDirName, 128);
|
||||
strcat(ms_rootDirName, "\\");
|
||||
}
|
||||
|
||||
void
|
||||
CFileMgr::ChangeDir(const char *dir)
|
||||
{
|
||||
if(*dir == '\\'){
|
||||
strcpy(ms_dirName, ms_rootDirName);
|
||||
dir++;
|
||||
}
|
||||
if(*dir != '\0'){
|
||||
strcat(ms_dirName, dir);
|
||||
// BUG in the game it seems, it's off by one
|
||||
if(dir[strlen(dir)-1] != '\\')
|
||||
strcat(ms_dirName, "\\");
|
||||
}
|
||||
chdir(ms_dirName);
|
||||
}
|
||||
|
||||
void
|
||||
CFileMgr::SetDir(const char *dir)
|
||||
{
|
||||
strcpy(ms_dirName, ms_rootDirName);
|
||||
if(*dir != '\0'){
|
||||
strcat(ms_dirName, dir);
|
||||
// BUG in the game it seems, it's off by one
|
||||
if(dir[strlen(dir)-1] != '\\')
|
||||
strcat(ms_dirName, "\\");
|
||||
}
|
||||
chdir(ms_dirName);
|
||||
}
|
||||
|
||||
void
|
||||
CFileMgr::SetDirMyDocuments(void)
|
||||
{
|
||||
SetDir(""); // better start at the root if user directory is relative
|
||||
chdir(_psGetUserFilesFolder());
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::LoadFile(const char *file, uint8 *buf, int unused, const char *mode)
|
||||
{
|
||||
int fd;
|
||||
int n, len;
|
||||
|
||||
fd = myfopen(file, mode);
|
||||
if(fd == 0)
|
||||
return 0;
|
||||
len = 0;
|
||||
do{
|
||||
n = myfread(buf + len, 1, 0x4000, fd);
|
||||
if(n < 0)
|
||||
return -1;
|
||||
len += n;
|
||||
}while(n == 0x4000);
|
||||
buf[len] = 0;
|
||||
myfclose(fd);
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::OpenFile(const char *file, const char *mode)
|
||||
{
|
||||
return myfopen(file, mode);
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::OpenFileForWriting(const char *file)
|
||||
{
|
||||
return OpenFile(file, "wb");
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::Read(int fd, char *buf, int len)
|
||||
{
|
||||
return myfread(buf, 1, len, fd);
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::Write(int fd, char *buf, int len)
|
||||
{
|
||||
return myfwrite(buf, 1, len, fd);
|
||||
}
|
||||
|
||||
bool
|
||||
CFileMgr::Seek(int fd, int offset, int whence)
|
||||
{
|
||||
return !!myfseek(fd, offset, whence);
|
||||
}
|
||||
|
||||
bool
|
||||
CFileMgr::ReadLine(int fd, char *buf, int len)
|
||||
{
|
||||
return myfgets(buf, len, fd) != nil;
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::CloseFile(int fd)
|
||||
{
|
||||
return myfclose(fd);
|
||||
}
|
||||
|
||||
int
|
||||
CFileMgr::GetErrorReadWrite(int fd)
|
||||
{
|
||||
return myfeof(fd);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x478F80, CFileMgr::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x478FB0, CFileMgr::ChangeDir, PATCH_JUMP);
|
||||
InjectHook(0x479020, CFileMgr::SetDir, PATCH_JUMP);
|
||||
InjectHook(0x479080, CFileMgr::SetDirMyDocuments, PATCH_JUMP);
|
||||
InjectHook(0x479090, CFileMgr::LoadFile, PATCH_JUMP);
|
||||
InjectHook(0x479100, CFileMgr::OpenFile, PATCH_JUMP);
|
||||
InjectHook(0x479120, CFileMgr::OpenFileForWriting, PATCH_JUMP);
|
||||
InjectHook(0x479140, CFileMgr::Read, PATCH_JUMP);
|
||||
InjectHook(0x479160, CFileMgr::Write, PATCH_JUMP);
|
||||
InjectHook(0x479180, CFileMgr::Seek, PATCH_JUMP);
|
||||
InjectHook(0x4791D0, CFileMgr::ReadLine, PATCH_JUMP);
|
||||
InjectHook(0x479200, CFileMgr::CloseFile, PATCH_JUMP);
|
||||
InjectHook(0x479210, CFileMgr::GetErrorReadWrite, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
21
src/core/FileMgr.h
Normal file
21
src/core/FileMgr.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
class CFileMgr
|
||||
{
|
||||
static char *ms_rootDirName; //[128];
|
||||
static char *ms_dirName; //[128];
|
||||
public:
|
||||
static void Initialise(void);
|
||||
static void ChangeDir(const char *dir);
|
||||
static void SetDir(const char *dir);
|
||||
static void SetDirMyDocuments(void);
|
||||
static int LoadFile(const char *file, uint8 *buf, int unused, const char *mode);
|
||||
static int OpenFile(const char *file, const char *mode);
|
||||
static int OpenFileForWriting(const char *file);
|
||||
static int Read(int fd, char *buf, int len);
|
||||
static int Write(int fd, char *buf, int len);
|
||||
static bool Seek(int fd, int offset, int whence);
|
||||
static bool ReadLine(int fd, char *buf, int len);
|
||||
static int CloseFile(int fd);
|
||||
static int GetErrorReadWrite(int fd);
|
||||
};
|
||||
5
src/core/Fire.cpp
Normal file
5
src/core/Fire.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Fire.h"
|
||||
|
||||
WRAPPER void CFire::Extinguish(void) { EAXJMP(0x479D40); }
|
||||
23
src/core/Fire.h
Normal file
23
src/core/Fire.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include "Entity.h"
|
||||
|
||||
class CFire
|
||||
{
|
||||
char m_bIsOngoing;
|
||||
char m_bExists;
|
||||
char m_bPropogationFlag;
|
||||
char m_bAudioSet;
|
||||
CVector m_vecPos;
|
||||
CEntity *m_pEntity;
|
||||
CEntity *m_pSource;
|
||||
int m_nExtinguishTime;
|
||||
int m_nStartTime;
|
||||
int field_20;
|
||||
int field_24;
|
||||
int field_28;
|
||||
float field_2C;
|
||||
|
||||
public:
|
||||
void Extinguish(void);
|
||||
};
|
||||
2353
src/core/Frontend.cpp
Normal file
2353
src/core/Frontend.cpp
Normal file
File diff suppressed because it is too large
Load Diff
512
src/core/Frontend.h
Normal file
512
src/core/Frontend.h
Normal file
@@ -0,0 +1,512 @@
|
||||
#pragma
|
||||
|
||||
#include "Sprite2d.h"
|
||||
|
||||
#define MENUHEADER_POS_X 35.0f
|
||||
#define MENUHEADER_POS_Y 93.0f
|
||||
#define MENUHEADER_WIDTH 0.84f
|
||||
#define MENUHEADER_HEIGHT 1.6f
|
||||
|
||||
#define MENUACTION_POS_X 20.0f
|
||||
#define MENUACTION_POS_Y 37.5f
|
||||
#define MENUACTION_WIDTH 0.675f
|
||||
#define MENUACTION_HEIGHT 0.81f
|
||||
|
||||
#define MENUCOLUMN_POS_X MENUHEADER_POS_X + 16.0f
|
||||
#define MENUCOLUMN_MAX_Y 149.0f
|
||||
#define MENUCOLUMN_MID_Y 100.0f
|
||||
#define MENUCOLUMN_MIN_Y 110.0f
|
||||
#define MENUCOLUMN_PAUSE_Y 25.0f
|
||||
#define MENUCOLUMN_START_Y 9.0f
|
||||
#define MENUCOLUMN_FEDS 139.0f
|
||||
|
||||
#define MENUCOLUMN_SAVE_X 121.0f
|
||||
#define MENUCOLUMN_SAVE_Y 111.0f
|
||||
|
||||
#define MENUCOLUMN_SPACING_MAX 24.0f
|
||||
#define MENUCOLUMN_SPACING_MIN 20.0f
|
||||
|
||||
#define MENUSELECT_BOX_MAX 20.5f
|
||||
#define MENUSELECT_BOX_MIN 17.0f
|
||||
|
||||
#ifndef ASPECT_RATIO_SCALE
|
||||
#define MENURADIO_ICON_X 31.5f
|
||||
#else
|
||||
#define MENURADIO_ICON_X -262.0f
|
||||
#endif
|
||||
#define MENURADIO_ICON_Y 29.5f
|
||||
#define MENURADIO_ICON_W 60.0f
|
||||
#define MENURADIO_ICON_H 60.0f
|
||||
|
||||
#define MENUDROP_COLOR_A 150
|
||||
#define MENUDROP_COLOR_SIZE -1
|
||||
|
||||
#define MENUSLIDER_X 306.0f
|
||||
|
||||
#define buf(a) (char*)(a)
|
||||
|
||||
enum eLanguages
|
||||
{
|
||||
LANGUAGE_AMERICAN,
|
||||
LANGUAGE_FRENCH,
|
||||
LANGUAGE_GERMAN,
|
||||
LANGUAGE_ITALIAN,
|
||||
LANGUAGE_SPANISH,
|
||||
};
|
||||
|
||||
enum eFrontendSprites
|
||||
{
|
||||
FE2_MAINPANEL_UL,
|
||||
FE2_MAINPANEL_UR,
|
||||
FE2_MAINPANEL_DL,
|
||||
FE2_MAINPANEL_DR,
|
||||
FE2_MAINPANEL_DR2,
|
||||
FE2_TABACTIVE,
|
||||
FE_ICONBRIEF,
|
||||
FE_ICONSTATS,
|
||||
FE_ICONCONTROLS,
|
||||
FE_ICONSAVE,
|
||||
FE_ICONAUDIO,
|
||||
FE_ICONDISPLAY,
|
||||
FE_ICONLANGUAGE,
|
||||
FE_CONTROLLER,
|
||||
FE_CONTROLLERSH,
|
||||
FE_ARROWS1,
|
||||
FE_ARROWS2,
|
||||
FE_ARROWS3,
|
||||
FE_ARROWS4,
|
||||
FE_RADIO1,
|
||||
FE_RADIO2,
|
||||
FE_RADIO3,
|
||||
FE_RADIO4,
|
||||
FE_RADIO5,
|
||||
FE_RADIO6,
|
||||
FE_RADIO7,
|
||||
FE_RADIO8,
|
||||
FE_RADIO9,
|
||||
};
|
||||
|
||||
enum eMenuSprites
|
||||
{
|
||||
MENUSPRITE_CONNECTION,
|
||||
MENUSPRITE_FINDGAME,
|
||||
MENUSPRITE_HOSTGAME,
|
||||
MENUSPRITE_MAINMENU,
|
||||
MENUSPRITE_PLAYERSET,
|
||||
MENUSPRITE_SINGLEPLAYER,
|
||||
MENUSPRITE_MULTIPLAYER,
|
||||
MENUSPRITE_DMALOGO,
|
||||
MENUSPRITE_GTALOGO,
|
||||
MENUSPRITE_RSTARLOGO,
|
||||
MENUSPRITE_GAMESPY,
|
||||
MENUSPRITE_MOUSE,
|
||||
MENUSPRITE_MOUSET,
|
||||
MENUSPRITE_MP3LOGO,
|
||||
MENUSPRITE_DOWNOFF,
|
||||
MENUSPRITE_DOWNON,
|
||||
MENUSPRITE_UPOFF,
|
||||
MENUSPRITE_UPON,
|
||||
MENUSPRITE_GTA3LOGO,
|
||||
};
|
||||
|
||||
enum eSaveSlot
|
||||
{
|
||||
SAVESLOT_NONE,
|
||||
SAVESLOT_0,
|
||||
SAVESLOT_1,
|
||||
SAVESLOT_2,
|
||||
SAVESLOT_3,
|
||||
SAVESLOT_4,
|
||||
SAVESLOT_5,
|
||||
SAVESLOT_6,
|
||||
SAVESLOT_7,
|
||||
SAVESLOT_8,
|
||||
SAVESLOT_LABEL = 36
|
||||
};
|
||||
|
||||
enum eMenuScreen
|
||||
{
|
||||
MENUPAGE_DISABLED = -1,
|
||||
MENUPAGE_NONE = 0,
|
||||
MENUPAGE_STATS = 1,
|
||||
MENUPAGE_NEW_GAME = 2,
|
||||
MENUPAGE_BRIEFS = 3,
|
||||
MENUPAGE_CONTROLLER_SETTINGS = 4,
|
||||
MENUPAGE_SOUND_SETTINGS = 5,
|
||||
MENUPAGE_GRAPHICS_SETTINGS = 6,
|
||||
MENUPAGE_LANGUAGE_SETTINGS = 7,
|
||||
MENUPAGE_CHOOSE_LOAD_SLOT = 8,
|
||||
MENUPAGE_CHOOSE_DELETE_SLOT = 9,
|
||||
MENUPAGE_NEW_GAME_RELOAD = 10,
|
||||
MENUPAGE_LOAD_SLOT_CONFIRM = 11,
|
||||
MENUPAGE_DELETE_SLOT_CONFIRM = 12,
|
||||
MENUPAGE_13 = 13,
|
||||
MENUPAGE_LOADING_IN_PROGRESS = 14,
|
||||
MENUPAGE_DELETING_IN_PROGRESS = 15,
|
||||
MENUPAGE_16 = 16,
|
||||
MENUPAGE_DELETE_FAILED = 17,
|
||||
MENUPAGE_DEBUG_MENU = 18,
|
||||
MENUPAGE_MEMORY_CARD_1 = 19,
|
||||
MENUPAGE_MEMORY_CARD_2 = 20,
|
||||
MENUPAGE_MULTIPLAYER_MAIN = 21,
|
||||
MENUPAGE_SAVE_FAILED_1 = 22,
|
||||
MENUPAGE_SAVE_FAILED_2 = 23,
|
||||
MENUPAGE_SAVE = 24,
|
||||
MENUPAGE_NO_MEMORY_CARD = 25,
|
||||
MENUPAGE_CHOOSE_SAVE_SLOT = 26,
|
||||
MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27,
|
||||
MENUPAGE_MULTIPLAYER_MAP = 28,
|
||||
MENUPAGE_MULTIPLAYER_CONNECTION = 29,
|
||||
MENUPAGE_MULTIPLAYER_FIND_GAME = 30,
|
||||
MENUPAGE_MULTIPLAYER_MODE = 31,
|
||||
MENUPAGE_MULTIPLAYER_CREATE = 32,
|
||||
MENUPAGE_MULTIPLAYER_START = 33,
|
||||
MENUPAGE_SKIN_SELECT_OLD = 34,
|
||||
MENUPAGE_CONTROLLER_PC = 35,
|
||||
MENUPAGE_CONTROLLER_PC_OLD1 = 36,
|
||||
MENUPAGE_CONTROLLER_PC_OLD2 = 37,
|
||||
MENUPAGE_CONTROLLER_PC_OLD3 = 38,
|
||||
MENUPAGE_CONTROLLER_PC_OLD4 = 39,
|
||||
MENUPAGE_CONTROLLER_DEBUG = 40,
|
||||
MENUPAGE_OPTIONS = 41,
|
||||
MENUPAGE_EXIT = 42,
|
||||
MENUPAGE_SAVING_IN_PROGRESS = 43,
|
||||
MENUPAGE_SAVE_SUCCESSFUL = 44,
|
||||
MENUPAGE_DELETING = 45,
|
||||
MENUPAGE_DELETE_SUCCESS = 46,
|
||||
MENUPAGE_SAVE_FAILED = 47,
|
||||
MENUPAGE_LOAD_FAILED = 48,
|
||||
MENUPAGE_LOAD_FAILED_2 = 49,
|
||||
MENUPAGE_FILTER_GAME = 50,
|
||||
MENUPAGE_START_MENU = 51,
|
||||
MENUPAGE_PAUSE_MENU = 52,
|
||||
MENUPAGE_CHOOSE_MODE = 53,
|
||||
MENUPAGE_SKIN_SELECT = 54,
|
||||
MENUPAGE_KEYBOARD_CONTROLS = 55,
|
||||
MENUPAGE_MOUSE_CONTROLS = 56,
|
||||
MENUPAGE_57 = 57,
|
||||
MENUPAGE_58 = 58,
|
||||
MENUPAGES
|
||||
};
|
||||
|
||||
enum eMenuAction
|
||||
{
|
||||
MENUACTION_NOTHING,
|
||||
MENUACTION_LABEL,
|
||||
MENUACTION_CHANGEMENU,
|
||||
MENUACTION_CTRLVIBRATION,
|
||||
MENUACTION_CTRLCONFIG,
|
||||
MENUACTION_CTRLDISPLAY,
|
||||
MENUACTION_FRAMESYNC,
|
||||
MENUACTION_FRAMELIMIT,
|
||||
MENUACTION_TRAILS,
|
||||
MENUACTION_SUBTITLES,
|
||||
MENUACTION_WIDESCREEN,
|
||||
MENUACTION_BRIGHTNESS,
|
||||
MENUACTION_DRAWDIST,
|
||||
MENUACTION_MUSICVOLUME,
|
||||
MENUACTION_SFXVOLUME,
|
||||
MENUACTION_UNK15,
|
||||
MENUACTION_RADIO,
|
||||
MENUACTION_LANG_ENG,
|
||||
MENUACTION_LANG_FRE,
|
||||
MENUACTION_LANG_GER,
|
||||
MENUACTION_LANG_ITA,
|
||||
MENUACTION_LANG_SPA,
|
||||
MENUACTION_UPDATESAVE,
|
||||
MENUACTION_CHECKSAVE,
|
||||
MENUACTION_UNK24,
|
||||
MENUACTION_NEWGAME,
|
||||
MENUACTION_RELOADIDE,
|
||||
MENUACTION_RELOADIPL,
|
||||
MENUACTION_SETDBGFLAG,
|
||||
MENUACTION_SWITCHBIGWHITEDEBUGLIGHT,
|
||||
MENUACTION_PEDROADGROUPS,
|
||||
MENUACTION_CARROADGROUPS,
|
||||
MENUACTION_COLLISIONPOLYS,
|
||||
MENUACTION_REGMEMCARD1,
|
||||
MENUACTION_TESTFORMATMEMCARD1,
|
||||
MENUACTION_TESTUNFORMATMEMCARD1,
|
||||
MENUACTION_CREATEROOTDIR,
|
||||
MENUACTION_CREATELOADICONS,
|
||||
MENUACTION_FILLWITHGUFF,
|
||||
MENUACTION_SAVEONLYTHEGAME,
|
||||
MENUACTION_SAVEGAME,
|
||||
MENUACTION_SAVEGAMEUNDERGTA,
|
||||
MENUACTION_CREATECOPYPROTECTED,
|
||||
MENUACTION_TESTSAVE,
|
||||
MENUACTION_TESTLOAD,
|
||||
MENUACTION_TESTDELETE,
|
||||
MENUACTION_PARSEHEAP,
|
||||
MENUACTION_SHOWCULL,
|
||||
MENUACTION_MEMCARDSAVECONFIRM,
|
||||
MENUACTION_UPDATEMEMCARDSAVE,
|
||||
MENUACTION_UNK50,
|
||||
MENUACTION_DEBUGSTREAM,
|
||||
MENUACTION_MPMAP_LIBERTY,
|
||||
MENUACTION_MPMAP_REDLIGHT,
|
||||
MENUACTION_MPMAP_CHINATOWN,
|
||||
MENUACTION_MPMAP_TOWER,
|
||||
MENUACTION_MPMAP_SEWER,
|
||||
MENUACTION_MPMAP_INDUSTPARK,
|
||||
MENUACTION_MPMAP_DOCKS,
|
||||
MENUACTION_MPMAP_STAUNTON,
|
||||
MENUACTION_MPMAP_DEATHMATCH1,
|
||||
MENUACTION_MPMAP_DEATHMATCH2,
|
||||
MENUACTION_MPMAP_TEAMDEATH1,
|
||||
MENUACTION_MPMAP_TEAMDEATH2,
|
||||
MENUACTION_MPMAP_STASH,
|
||||
MENUACTION_MPMAP_CAPTURE,
|
||||
MENUACTION_MPMAP_RATRACE,
|
||||
MENUACTION_MPMAP_DOMINATION,
|
||||
MENUACTION_STARTMP,
|
||||
MENUACTION_UNK69,
|
||||
MENUACTION_UNK70,
|
||||
MENUACTION_FINDMP,
|
||||
MENUACTION_REDEFCTRL,
|
||||
MENUACTION_UNK73,
|
||||
MENUACTION_INITMP,
|
||||
MENUACTION_MP_PLAYERCOLOR,
|
||||
MENUACTION_MP_PLAYERNAME,
|
||||
MENUACTION_MP_GAMENAME,
|
||||
MENUACTION_GETKEY,
|
||||
MENUACTION_SHOWHEADBOB,
|
||||
MENUACTION_UNK80,
|
||||
MENUACTION_INVVERT,
|
||||
MENUACTION_CANCLEGAME,
|
||||
MENUACTION_MP_PLAYERNUMBER,
|
||||
MENUACTION_MOUSESENS,
|
||||
MENUACTION_CHECKMPGAMES,
|
||||
MENUACTION_CHECKMPPING,
|
||||
MENUACTION_MP_SERVER,
|
||||
MENUACTION_MP_MAP,
|
||||
MENUACTION_MP_GAMETYPE,
|
||||
MENUACTION_MP_LAN,
|
||||
MENUACTION_MP_INTERNET,
|
||||
MENUACTION_RESUME,
|
||||
MENUACTION_DONTCANCLE,
|
||||
MENUACTION_SCREENRES,
|
||||
MENUACTION_AUDIOHW,
|
||||
MENUACTION_SPEAKERCONF,
|
||||
MENUACTION_PLAYERSETUP,
|
||||
MENUACTION_RESTOREDEF,
|
||||
MENUACTION_CTRLMETHOD,
|
||||
MENUACTION_DYNAMICACOUSTIC,
|
||||
MENUACTION_LOADRADIO,
|
||||
MENUACTION_MOUSESTEER,
|
||||
MENUACTION_UNK103,
|
||||
MENUACTION_UNK104,
|
||||
MENUACTION_UNK105,
|
||||
MENUACTION_UNK106,
|
||||
MENUACTION_UNK107,
|
||||
MENUACTION_UNK108,
|
||||
MENUACTION_UNK109,
|
||||
MENUACTION_UNK110,
|
||||
};
|
||||
|
||||
enum eCheckHover
|
||||
{
|
||||
ACTIVATE_OPTION = 2,
|
||||
IGNORE_OPTION = 42,
|
||||
};
|
||||
|
||||
enum eMenuColumns
|
||||
{
|
||||
MENUCOLUMN_LEFT,
|
||||
MENUCOLUMN_CENTER,
|
||||
MENUCOLUMN_RIGHT,
|
||||
MENUCOLUMNS,
|
||||
};
|
||||
|
||||
enum eMenuRow
|
||||
{
|
||||
MENUROW_NONE = -1,
|
||||
MENUROW_0,
|
||||
MENUROW_1,
|
||||
MENUROW_2,
|
||||
MENUROW_3,
|
||||
MENUROW_4,
|
||||
MENUROW_5,
|
||||
MENUROW_6,
|
||||
MENUROW_7,
|
||||
MENUROW_8,
|
||||
MENUROW_9,
|
||||
MENUROW_10,
|
||||
MENUROW_11,
|
||||
MENUROW_12,
|
||||
MENUROW_13,
|
||||
MENUROW_14,
|
||||
MENUROW_15,
|
||||
MENUROW_16,
|
||||
MENUROW_17,
|
||||
MENUROWS,
|
||||
};
|
||||
|
||||
struct tSkinInfo
|
||||
{
|
||||
int field_0;
|
||||
char skinName[256];
|
||||
char currSkinName[256];
|
||||
char date[256];
|
||||
int field_304;
|
||||
};
|
||||
|
||||
struct CMenuScreen
|
||||
{
|
||||
char m_ScreenName[8];
|
||||
int32 unk;
|
||||
int32 m_PreviousPage[2]; // eMenuScreen
|
||||
int32 m_ParentEntry[2]; // eMenuRow
|
||||
|
||||
struct CMenuEntry
|
||||
{
|
||||
int32 m_Action; // eMenuAction
|
||||
char m_EntryName[8];
|
||||
int32 m_SaveSlot; // eSaveSlot
|
||||
int32 m_TargetMenu; // eMenuScreen
|
||||
} m_aEntries[MENUROWS];
|
||||
};
|
||||
|
||||
class CMenuManager
|
||||
{
|
||||
public:
|
||||
int32 m_nPrefsVideoMode;
|
||||
int32 m_nDisplayVideoMode;
|
||||
int8 m_nPrefsAudio3DProviderIndex;
|
||||
bool m_bKeyChangeNotProcessed;
|
||||
char m_aSkinName[256];
|
||||
int32 m_nHelperTextMsgId;
|
||||
bool m_bLanguageLoaded;
|
||||
bool m_bMenuActive;
|
||||
char field_112;
|
||||
char field_113;
|
||||
bool m_bStartGameLoading;
|
||||
bool m_bFirstTime;
|
||||
bool m_bGameNotLoaded;
|
||||
int32 m_nMousePosX;
|
||||
int32 m_nMousePosY;
|
||||
int32 m_nMouseTempPosX;
|
||||
int32 m_nMouseTempPosY;
|
||||
bool m_bShowMouse;
|
||||
tSkinInfo field_12C;
|
||||
tSkinInfo *m_pSelectedSkin;
|
||||
tSkinInfo *field_438;
|
||||
float field_43C;
|
||||
int field_440;
|
||||
int m_nSkinsTotal;
|
||||
char _unk0[4];
|
||||
int field_44C;
|
||||
bool m_bSkinsFound;
|
||||
bool m_bQuitGameNoCD;
|
||||
char field_452;
|
||||
bool m_bSaveMenuActive;
|
||||
bool m_bLoadingSavedGame;
|
||||
char field_455;
|
||||
char field_456;
|
||||
bool m_bSpritesLoaded;
|
||||
CSprite2d m_aFrontEndSprites[28];
|
||||
CSprite2d m_aMenuSprites[20];
|
||||
int field_518;
|
||||
int m_nMenuFadeAlpha;
|
||||
char field_520;
|
||||
char field_521;
|
||||
char field_522;
|
||||
char field_523;
|
||||
char field_524;
|
||||
int m_CurrCntrlAction;
|
||||
char _unk1[4];
|
||||
int field_530;
|
||||
char field_534;
|
||||
char field_535;
|
||||
int8 field_536;
|
||||
int m_nHelperTextAlpha;
|
||||
int m_nMouseOldPosX;
|
||||
int m_nMouseOldPosY;
|
||||
int m_nHoverOption;
|
||||
int m_nCurrScreen;
|
||||
int m_nCurrOption;
|
||||
int m_nPrevOption;
|
||||
int m_nPrevScreen;
|
||||
int field_558;
|
||||
int m_nCurrSaveSlot;
|
||||
int m_nScreenChangeDelayTimer;
|
||||
|
||||
static int32 &OS_Language;
|
||||
static int8 &m_PrefsUseVibration;
|
||||
static int8 &m_DisplayControllerOnFoot;
|
||||
static int8 &m_PrefsUseWideScreen;
|
||||
static int8 &m_PrefsRadioStation;
|
||||
static int8 &m_PrefsVsync;
|
||||
static int8 &m_PrefsVsyncDisp;
|
||||
static int8 &m_PrefsFrameLimiter;
|
||||
static int8 &m_PrefsShowSubtitles;
|
||||
static int8 &m_PrefsSpeakers;
|
||||
static int8 &m_ControlMethod;
|
||||
static int8 &m_PrefsDMA;
|
||||
static int8 &m_PrefsLanguage;
|
||||
static int8 &m_bDisableMouseSteering;
|
||||
static int32 &m_PrefsBrightness;
|
||||
static float &m_PrefsLOD;
|
||||
static int8 &m_bFrontEnd_ReloadObrTxtGxt;
|
||||
static int32 &m_PrefsMusicVolume;
|
||||
static int32 &m_PrefsSfxVolume;
|
||||
static uint8 *m_PrefsSkinFile;
|
||||
|
||||
static bool &m_bStartUpFrontEndRequested;
|
||||
static bool &m_bShutDownFrontEndRequested;
|
||||
static bool &m_PrefsAllowNastyGame;
|
||||
|
||||
public:
|
||||
void BuildStatLine(char *, void *, uint16, void *);
|
||||
static void CentreMousePointer();
|
||||
void CheckCodesForControls(int, int);
|
||||
bool CheckHover(int x1, int x2, int y1, int y2);
|
||||
void CheckSliderMovement(int);
|
||||
int CostructStatLine(int);
|
||||
void DisplayHelperText();
|
||||
float DisplaySlider(float, float, float, float, float, float);
|
||||
void DoSettingsBeforeStartingAGame();
|
||||
void Draw();
|
||||
void DrawControllerBound(int, int, int, uint8);
|
||||
void DrawControllerScreenExtraText(int, int, int);
|
||||
void DrawControllerSetupScreen();
|
||||
void DrawFrontEnd();
|
||||
void DrawFrontEndNormal();
|
||||
void DrawPlayerSetupScreen();
|
||||
int FadeIn(int alpha);
|
||||
void FilterOutColorMarkersFromString(uint16, CRGBA &);
|
||||
int GetStartOptionsCntrlConfigScreens();
|
||||
static void InitialiseChangedLanguageSettings();
|
||||
void LoadAllTextures();
|
||||
void LoadSettings();
|
||||
static void MessageScreen(char *);
|
||||
static void PickNewPlayerColour();
|
||||
void PrintBriefs();
|
||||
static void PrintErrorMessage();
|
||||
void PrintStats();
|
||||
void Process();
|
||||
void ProcessButtonPresses();
|
||||
void ProcessOnOffMenuOptions();
|
||||
static void RequestFrontEndShutdown();
|
||||
static void RequestFrontEndStartUp();
|
||||
void ResetHelperText();
|
||||
void SaveLoadFileError_SetUpErrorScreen();
|
||||
void SaveSettings();
|
||||
void SetHelperText(int text);
|
||||
void ShutdownJustMenu();
|
||||
static float StretchX(float);
|
||||
static float StretchY(float);
|
||||
void SwitchMenuOnAndOff();
|
||||
void UnloadTextures();
|
||||
void WaitForUserCD();
|
||||
|
||||
// New content:
|
||||
uint8 GetNumberOfMenuOptions();
|
||||
void SwitchToNewScreen(int8 screen);
|
||||
void SetDefaultPreferences(int8 screen);
|
||||
|
||||
};
|
||||
|
||||
static_assert(sizeof(CMenuManager) == 0x564, "CMenuManager: error");
|
||||
|
||||
extern CMenuManager &FrontEndMenuManager;
|
||||
23
src/core/Game.cpp
Normal file
23
src/core/Game.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Game.h"
|
||||
|
||||
eLevelName &CGame::currLevel = *(eLevelName*)0x941514;
|
||||
bool &CGame::bDemoMode = *(bool*)0x5F4DD0;
|
||||
bool &CGame::nastyGame = *(bool*)0x5F4DD4;
|
||||
bool &CGame::frenchGame = *(bool*)0x95CDCB;
|
||||
bool &CGame::germanGame = *(bool*)0x95CD1E;
|
||||
bool &CGame::noProstitutes = *(bool*)0x95CDCF;
|
||||
bool &CGame::playingIntro = *(bool*)0x95CDC2;
|
||||
char *CGame::aDatFile = (char*)0x773A48;
|
||||
|
||||
WRAPPER void CGame::Initialise(const char *datFile) { EAXJMP(0x48BED0); }
|
||||
WRAPPER void CGame::Process(void) { EAXJMP(0x48C850); }
|
||||
WRAPPER bool CGame::InitialiseOnceBeforeRW(void) { EAXJMP(0x48BB80); }
|
||||
WRAPPER bool CGame::InitialiseRenderWare(void) { EAXJMP(0x48BBA0); }
|
||||
WRAPPER void CGame::ShutdownRenderWare(void) { EAXJMP(0x48BCB0); }
|
||||
WRAPPER void CGame::FinalShutdown(void) { EAXJMP(0x48BEC0); }
|
||||
WRAPPER void CGame::ShutDown(void) { EAXJMP(0x48C3A0); }
|
||||
WRAPPER void CGame::ShutDownForRestart(void) { EAXJMP(0x48C6B0); }
|
||||
WRAPPER void CGame::InitialiseWhenRestarting(void) { EAXJMP(0x48C740); }
|
||||
WRAPPER bool CGame::InitialiseOnceAfterRW(void) { EAXJMP(0x48BD50); }
|
||||
37
src/core/Game.h
Normal file
37
src/core/Game.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
enum eLevelName
|
||||
{
|
||||
LEVEL_NONE = 0,
|
||||
LEVEL_INDUSTRIAL,
|
||||
LEVEL_COMMERCIAL,
|
||||
LEVEL_SUBURBAN
|
||||
};
|
||||
|
||||
class CGame
|
||||
{
|
||||
public:
|
||||
static eLevelName &currLevel;
|
||||
static bool &bDemoMode;
|
||||
static bool &nastyGame;
|
||||
static bool &frenchGame;
|
||||
static bool &germanGame;
|
||||
static bool &noProstitutes;
|
||||
static bool &playingIntro;
|
||||
static char *aDatFile; //[32];
|
||||
|
||||
static void Initialise(const char *datFile);
|
||||
static bool InitialiseOnceBeforeRW(void);
|
||||
static bool InitialiseRenderWare(void);
|
||||
static bool InitialiseOnceAfterRW(void);
|
||||
static void InitialiseWhenRestarting(void);
|
||||
static void ShutDown(void);
|
||||
static void ShutdownRenderWare(void);
|
||||
static void FinalShutdown(void);
|
||||
static void ShutDownForRestart(void);
|
||||
static void Process(void);
|
||||
|
||||
// NB: these do something on PS2
|
||||
static void TidyUpMemory(bool, bool) {}
|
||||
static void DrasticTidyUpMemory(void) {}
|
||||
};
|
||||
91
src/core/General.h
Normal file
91
src/core/General.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
class CGeneral
|
||||
{
|
||||
public:
|
||||
static float GetATanOfXY(float x, float y){
|
||||
if(x == 0.0f && y == 0.0f)
|
||||
return 0.0f;
|
||||
float xabs = fabs(x);
|
||||
float yabs = fabs(y);
|
||||
|
||||
if(xabs < yabs){
|
||||
if(y > 0.0f){
|
||||
if(x > 0.0f)
|
||||
return 0.5f*PI - atan2(x / y, 1.0f);
|
||||
else
|
||||
return 0.5f*PI + atan2(-x / y, 1.0f);
|
||||
}else{
|
||||
if(x > 0.0f)
|
||||
return 1.5f*PI + atan2(x / -y, 1.0f);
|
||||
else
|
||||
return 1.5f*PI - atan2(-x / -y, 1.0f);
|
||||
}
|
||||
}else{
|
||||
if(y > 0.0f){
|
||||
if(x > 0.0f)
|
||||
return atan2(y / x, 1.0f);
|
||||
else
|
||||
return PI - atan2(y / -x, 1.0f);
|
||||
}else{
|
||||
if(x > 0.0f)
|
||||
return 2.0f*PI - atan2(-y / x, 1.0f);
|
||||
else
|
||||
return PI + atan2(-y / -x, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static float LimitRadianAngle(float angle)
|
||||
{
|
||||
float result;
|
||||
|
||||
if (angle < -25.0f)
|
||||
result = -25.0f;
|
||||
else if (angle > 25.0f)
|
||||
result = 25.0f;
|
||||
else
|
||||
result = angle;
|
||||
|
||||
while (result >= PI) {
|
||||
result -= 2 * PI;
|
||||
}
|
||||
|
||||
while (result < -PI) {
|
||||
result += 2 * PI;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static float GetRadianAngleBetweenPoints(float x1, float y1, float x2, float y2)
|
||||
{
|
||||
float x = x2 - x1;
|
||||
float y = y2 - y1;
|
||||
|
||||
if (y == 0.0f)
|
||||
y = 0.0001f;
|
||||
|
||||
if (x > 0.0f) {
|
||||
if (y > 0.0f)
|
||||
return PI - atan2(x / y, 1.0f);
|
||||
else
|
||||
return -atan2(x / y, 1.0f);
|
||||
} else {
|
||||
if (y > 0.0f)
|
||||
return -(PI + atan2(x / y, 1.0f));
|
||||
else
|
||||
return -atan2(x / y, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// not too sure about all these...
|
||||
static uint16 GetRandomNumber(void)
|
||||
{ return myrand() & MYRAND_MAX; }
|
||||
// Probably don't want to ever reach high
|
||||
static float GetRandomNumberInRange(float low, float high)
|
||||
{ return low + (high - low)*(GetRandomNumber()/float(MYRAND_MAX + 1)); }
|
||||
|
||||
static int32 GetRandomNumberInRange(int32 low, int32 high)
|
||||
{ return low + (high - low)*(GetRandomNumber()/float(MYRAND_MAX + 1)); }
|
||||
};
|
||||
26
src/core/Lists.cpp
Normal file
26
src/core/Lists.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "common.h"
|
||||
#include "Pools.h"
|
||||
#include "Lists.h"
|
||||
|
||||
void*
|
||||
CPtrNode::operator new(size_t){
|
||||
CPtrNode *node = CPools::GetPtrNodePool()->New();
|
||||
assert(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
CPtrNode::operator delete(void *p, size_t){
|
||||
CPools::GetPtrNodePool()->Delete((CPtrNode*)p);
|
||||
}
|
||||
|
||||
void*
|
||||
CEntryInfoNode::operator new(size_t){
|
||||
CEntryInfoNode *node = CPools::GetEntryInfoNodePool()->New();
|
||||
assert(node);
|
||||
return node;
|
||||
}
|
||||
void
|
||||
CEntryInfoNode::operator delete(void *p, size_t){
|
||||
CPools::GetEntryInfoNodePool()->Delete((CEntryInfoNode*)p);
|
||||
}
|
||||
130
src/core/Lists.h
Normal file
130
src/core/Lists.h
Normal file
@@ -0,0 +1,130 @@
|
||||
#pragma once
|
||||
|
||||
class CPtrNode
|
||||
{
|
||||
public:
|
||||
void *item;
|
||||
CPtrNode *prev;
|
||||
CPtrNode *next;
|
||||
|
||||
void *operator new(size_t);
|
||||
void operator delete(void *p, size_t);
|
||||
};
|
||||
|
||||
class CPtrList
|
||||
{
|
||||
public:
|
||||
CPtrNode *first;
|
||||
|
||||
CPtrList(void) { first = nil; }
|
||||
~CPtrList(void) { Flush(); }
|
||||
CPtrNode *FindItem(void *item){
|
||||
CPtrNode *node;
|
||||
for(node = first; node; node = node->next)
|
||||
if(node->item == item)
|
||||
return node;
|
||||
return nil;
|
||||
}
|
||||
CPtrNode *InsertNode(CPtrNode *node){
|
||||
node->prev = nil;
|
||||
node->next = first;
|
||||
if(first)
|
||||
first->prev = node;
|
||||
first = node;
|
||||
return node;
|
||||
}
|
||||
CPtrNode *InsertItem(void *item){
|
||||
CPtrNode *node = new CPtrNode;
|
||||
node->item = item;
|
||||
InsertNode(node);
|
||||
return node;
|
||||
}
|
||||
void RemoveNode(CPtrNode *node){
|
||||
if(node == first)
|
||||
first = node->next;
|
||||
if(node->prev)
|
||||
node->prev->next = node->next;
|
||||
if(node->next)
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
void DeleteNode(CPtrNode *node){
|
||||
RemoveNode(node);
|
||||
delete node;
|
||||
}
|
||||
void RemoveItem(void *item){
|
||||
CPtrNode *node, *next;
|
||||
for(node = first; node; node = next){
|
||||
next = node->next;
|
||||
if(node->item == item)
|
||||
DeleteNode(node);
|
||||
}
|
||||
}
|
||||
void Flush(void){
|
||||
CPtrNode *node, *next;
|
||||
for(node = first; node; node = next){
|
||||
next = node->next;
|
||||
DeleteNode(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CSector;
|
||||
|
||||
// This records in which sector list a Physical is
|
||||
class CEntryInfoNode
|
||||
{
|
||||
public:
|
||||
CPtrList *list; // list in sector
|
||||
CPtrNode *listnode; // node in list
|
||||
CSector *sector;
|
||||
|
||||
CEntryInfoNode *prev;
|
||||
CEntryInfoNode *next;
|
||||
|
||||
void *operator new(size_t);
|
||||
void operator delete(void *p, size_t);
|
||||
};
|
||||
|
||||
class CEntryInfoList
|
||||
{
|
||||
public:
|
||||
CEntryInfoNode *first;
|
||||
|
||||
CEntryInfoList(void) { first = nil; }
|
||||
~CEntryInfoList(void) { Flush(); }
|
||||
CEntryInfoNode *InsertNode(CEntryInfoNode *node){
|
||||
node->prev = nil;
|
||||
node->next = first;
|
||||
if(first)
|
||||
first->prev = node;
|
||||
first = node;
|
||||
return node;
|
||||
}
|
||||
CEntryInfoNode *InsertItem(CPtrList *list, CPtrNode *listnode, CSector *sect){
|
||||
CEntryInfoNode *node = new CEntryInfoNode;
|
||||
node->list = list;
|
||||
node->listnode = listnode;
|
||||
node->sector = sect;
|
||||
InsertNode(node);
|
||||
return node;
|
||||
}
|
||||
void RemoveNode(CEntryInfoNode *node){
|
||||
if(node == first)
|
||||
first = node->next;
|
||||
if(node->prev)
|
||||
node->prev->next = node->next;
|
||||
if(node->next)
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
void DeleteNode(CEntryInfoNode *node){
|
||||
RemoveNode(node);
|
||||
delete node;
|
||||
}
|
||||
void Flush(void){
|
||||
CEntryInfoNode *node, *next;
|
||||
for(node = first; node; node = next){
|
||||
next = node->next;
|
||||
DeleteNode(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
380
src/core/MenuScreens.h
Normal file
380
src/core/MenuScreens.h
Normal file
@@ -0,0 +1,380 @@
|
||||
#pragma once
|
||||
|
||||
const CMenuScreen aScreens[] = {
|
||||
// MENUPAGE_NONE = 0
|
||||
{ "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0, },
|
||||
|
||||
// MENUPAGE_STATS = 1
|
||||
{ "FET_STA", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, MENUROW_5, MENUROW_2,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_NEW_GAME = 2
|
||||
{ "FET_SGA", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, MENUROW_0, MENUROW_1,
|
||||
MENUACTION_CHANGEMENU, "FES_SNG", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD,
|
||||
MENUACTION_CHANGEMENU, "GMLOAD", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT,
|
||||
MENUACTION_CHANGEMENU, "FES_DGA", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_BRIEFS = 3
|
||||
{ "FET_BRE", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, MENUROW_6, MENUROW_3,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENU_CONTROLLER_SETTINGS = 4
|
||||
{ "FET_CON", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_SOUND_SETTINGS = 5
|
||||
{ "FET_AUD", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_1, MENUROW_1,
|
||||
MENUACTION_MUSICVOLUME, "FEA_MUS", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
|
||||
MENUACTION_SFXVOLUME, "FEA_SFX", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
|
||||
MENUACTION_AUDIOHW, "FEA_3DH", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
|
||||
MENUACTION_SPEAKERCONF, "FEA_SPK", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
|
||||
MENUACTION_DYNAMICACOUSTIC, "FET_DAM", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
|
||||
MENUACTION_RADIO, "FEA_RSS", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
|
||||
MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
|
||||
},
|
||||
|
||||
// MENUPAGE_GRAPHICS_SETTINGS = 6
|
||||
{ "FET_DIS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_2, MENUROW_2,
|
||||
MENUACTION_BRIGHTNESS, "FED_BRI", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
|
||||
MENUACTION_DRAWDIST, "FEM_LOD", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
|
||||
//MENUACTION_FRAMESYNC, "FEM_VSC", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
|
||||
MENUACTION_FRAMELIMIT, "FEM_FRM", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
|
||||
MENUACTION_TRAILS, "FED_TRA", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
|
||||
MENUACTION_SUBTITLES, "FED_SUB", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
|
||||
MENUACTION_WIDESCREEN, "FED_WIS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
|
||||
MENUACTION_SCREENRES, "FED_RES", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
|
||||
MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_LANGUAGE_SETTINGS = 7
|
||||
{ "FET_LAN", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_3, MENUROW_3,
|
||||
MENUACTION_LANG_ENG, "FEL_ENG", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_LANG_FRE, "FEL_FRE", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_LANG_GER, "FEL_GER", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_LANG_ITA, "FEL_ITA", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_LANG_SPA, "FEL_SPA", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_CHOOSE_LOAD_SLOT = 8
|
||||
{ "FET_LG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUROW_1, MENUROW_1,
|
||||
MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1, MENUPAGE_LOAD_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2, MENUPAGE_LOAD_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL3", SAVESLOT_3, MENUPAGE_LOAD_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL4", SAVESLOT_4, MENUPAGE_LOAD_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL5", SAVESLOT_5, MENUPAGE_LOAD_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL6", SAVESLOT_6, MENUPAGE_LOAD_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL7", SAVESLOT_7, MENUPAGE_LOAD_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL8", SAVESLOT_8, MENUPAGE_LOAD_SLOT_CONFIRM,
|
||||
},
|
||||
|
||||
// MENUPAGE_CHOOSE_DELETE_SLOT = 9
|
||||
{ "FET_DG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUROW_2, MENUROW_2,
|
||||
MENUACTION_CHANGEMENU, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL1", SAVESLOT_1, MENUPAGE_DELETE_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL2", SAVESLOT_2, MENUPAGE_DELETE_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL3", SAVESLOT_3, MENUPAGE_DELETE_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL4", SAVESLOT_4, MENUPAGE_DELETE_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL5", SAVESLOT_5, MENUPAGE_DELETE_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL6", SAVESLOT_6, MENUPAGE_DELETE_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL7", SAVESLOT_7, MENUPAGE_DELETE_SLOT_CONFIRM,
|
||||
MENUACTION_CHECKSAVE, "FEM_SL8", SAVESLOT_8, MENUPAGE_DELETE_SLOT_CONFIRM,
|
||||
},
|
||||
|
||||
// MENUPAGE_NEW_GAME_RELOAD = 10
|
||||
{ "FET_NG", MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUPAGE_NEW_GAME, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FESZ_QR", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
|
||||
MENUACTION_NEWGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_LOAD_SLOT_CONFIRM = 11
|
||||
{ "FET_LG", MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, MENUPAGE_CHOOSE_LOAD_SLOT, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FESZ_QL", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT,
|
||||
MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_LOADING_IN_PROGRESS,
|
||||
},
|
||||
|
||||
// MENUPAGE_DELETE_SLOT_CONFIRM = 12
|
||||
{ "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FESZ_QD", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT,
|
||||
MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_DELETING,
|
||||
},
|
||||
|
||||
// MENUPAGE_13 = 13
|
||||
{ "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_LOADING_IN_PROGRESS = 14
|
||||
{ "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FED_LDW", SAVESLOT_NONE, MENUPAGE_LOAD_SLOT_CONFIRM,
|
||||
},
|
||||
|
||||
// MENUPAGE_DELETING_IN_PROGRESS = 15
|
||||
{ "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FEDL_WR", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_16 = 16
|
||||
{ "FET_LG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FES_LOE", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_DELETE_FAILED = 17
|
||||
{ "FET_DG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FES_DEE", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT,
|
||||
},
|
||||
|
||||
// MENUPAGE_DEBUG_MENU = 18
|
||||
{ "FED_DBG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_MEMORY_CARD_1 = 19
|
||||
{ "FEM_MCM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_MEMORY_CARD_2 = 20
|
||||
{ "FEM_MC2", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_MULTIPLAYER_MAIN = 21
|
||||
{ "FET_MP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_SAVE_FAILED_1 = 22
|
||||
{ "MCDNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_SAVE_FAILED_2 = 23
|
||||
{ "MCGNSP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_MEMCARDSAVECONFIRM, "JAILB_U", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_SAVE = 24
|
||||
{ "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FES_SCG", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_UPDATESAVE, "GMSAVE", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT,
|
||||
MENUACTION_UPDATEMEMCARDSAVE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_NO_MEMORY_CARD = 25
|
||||
{ "FES_NOC", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_CHOOSE_SAVE_SLOT = 26
|
||||
{ "FET_SG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_UPDATEMEMCARDSAVE, "FESZ_CA", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_UPDATESAVE, "FEM_SL1", SAVESLOT_1, MENUPAGE_SAVE_OVERWRITE_CONFIRM,
|
||||
MENUACTION_UPDATESAVE, "FEM_SL2", SAVESLOT_2, MENUPAGE_SAVE_OVERWRITE_CONFIRM,
|
||||
MENUACTION_UPDATESAVE, "FEM_SL3", SAVESLOT_3, MENUPAGE_SAVE_OVERWRITE_CONFIRM,
|
||||
MENUACTION_UPDATESAVE, "FEM_SL4", SAVESLOT_4, MENUPAGE_SAVE_OVERWRITE_CONFIRM,
|
||||
MENUACTION_UPDATESAVE, "FEM_SL5", SAVESLOT_5, MENUPAGE_SAVE_OVERWRITE_CONFIRM,
|
||||
MENUACTION_UPDATESAVE, "FEM_SL6", SAVESLOT_6, MENUPAGE_SAVE_OVERWRITE_CONFIRM,
|
||||
MENUACTION_UPDATESAVE, "FEM_SL7", SAVESLOT_7, MENUPAGE_SAVE_OVERWRITE_CONFIRM,
|
||||
MENUACTION_UPDATESAVE, "FEM_SL8", SAVESLOT_8, MENUPAGE_SAVE_OVERWRITE_CONFIRM,
|
||||
},
|
||||
|
||||
// MENUPAGE_SAVE_OVERWRITE_CONFIRM = 27
|
||||
{ "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FESZ_QO", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEM_YES", SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS,
|
||||
MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT,
|
||||
},
|
||||
|
||||
// MENUPAGE_MULTIPLAYER_MAP = 28
|
||||
{ "FET_MAP", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_MULTIPLAYER_CONNECTION = 29
|
||||
{ "FET_CON", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_MULTIPLAYER_FIND_GAME = 30
|
||||
{ "FET_FG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_MULTIPLAYER_MODE = 31
|
||||
{ "FET_GT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_MULTIPLAYER_CREATE = 32
|
||||
{ "FET_HG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_MULTIPLAYER_START = 33
|
||||
{ "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_SKIN_SELECT_OLD = 34
|
||||
{ "FET_PS", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_CONTROLLER_PC = 35
|
||||
{ "FET_CTL", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_CTRLMETHOD, "FET_CME", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC,
|
||||
MENUACTION_CHANGEMENU, "FET_RDK", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS,
|
||||
MENUACTION_CHANGEMENU, "FET_AMS", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS,
|
||||
MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_CONTROLLER_PC_OLD1 = 36
|
||||
{ "FET_CTL", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_CONTROLLER_PC_OLD2 = 37
|
||||
{ "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_CONTROLLER_PC_OLD3 = 38
|
||||
{ "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_CONTROLLER_PC_OLD4 = 39
|
||||
{ "FET_CTL", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_CONTROLLER_DEBUG = 40
|
||||
{ "FEC_DBG", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_OPTIONS = 41
|
||||
{ "FET_OPT", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, MENUROW_1, MENUROW_4,
|
||||
MENUACTION_CHANGEMENU, "FET_CTL", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC,
|
||||
MENUACTION_CHANGEMENU, "FET_AUD", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS,
|
||||
MENUACTION_CHANGEMENU, "FET_DIS", SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS,
|
||||
MENUACTION_CHANGEMENU, "FET_LAN", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS,
|
||||
//MENUACTION_CHANGEMENU, "FET_PSU", SAVESLOT_NONE, MENUPAGE_SKIN_SELECT,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_EXIT = 42
|
||||
{ "FET_QG", MENUPAGE_NONE, MENUPAGE_NONE, MENUPAGE_NONE, MENUROW_2, MENUROW_5,
|
||||
MENUACTION_LABEL, "FEQ_SRE", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEM_NO", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CANCLEGAME, "FEM_YES", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_SAVING_IN_PROGRESS = 43
|
||||
{ "", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FES_WAR", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_SAVE_SUCCESSFUL = 44
|
||||
{ "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FES_SSC", SAVESLOT_LABEL, MENUPAGE_NONE,
|
||||
MENUACTION_UPDATEMEMCARDSAVE, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT,
|
||||
},
|
||||
|
||||
// MENUPAGE_DELETING = 45
|
||||
{ "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FED_DLW", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_DELETE_SUCCESS = 46
|
||||
{ "FET_DG", MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUPAGE_CHOOSE_DELETE_SLOT, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "DEL_FNM", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT,
|
||||
},
|
||||
|
||||
// MENUPAGE_SAVE_FAILED = 47
|
||||
{ "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEC_OKK", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT,
|
||||
},
|
||||
|
||||
// MENUPAGE_LOAD_FAILED = 48
|
||||
{ "FET_SG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FEC_SVU", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_LOAD_FAILED_2 = 49
|
||||
{ "FET_LG", MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUPAGE_CHOOSE_SAVE_SLOT, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_LABEL, "FEC_LUN", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT,
|
||||
},
|
||||
|
||||
// MENUPAGE_FILTER_GAME = 50
|
||||
{ "FIL_FLT", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_START_MENU = 51
|
||||
{ "FEM_MM", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
|
||||
MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS,
|
||||
MENUACTION_CHANGEMENU, "FEM_QT", SAVESLOT_NONE, MENUPAGE_EXIT,
|
||||
},
|
||||
|
||||
// MENUPAGE_PAUSE_MENU = 52
|
||||
{ "FET_PAU", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
MENUACTION_RESUME, "FEM_RES", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
MENUACTION_CHANGEMENU, "FEN_STA", SAVESLOT_NONE, MENUPAGE_NEW_GAME,
|
||||
MENUACTION_CHANGEMENU, "FEP_STA", SAVESLOT_NONE, MENUPAGE_STATS,
|
||||
MENUACTION_CHANGEMENU, "FEP_BRI", SAVESLOT_NONE, MENUPAGE_BRIEFS,
|
||||
MENUACTION_CHANGEMENU, "FET_OPT", SAVESLOT_NONE, MENUPAGE_OPTIONS,
|
||||
MENUACTION_CHANGEMENU, "FEM_QT", SAVESLOT_NONE, MENUPAGE_EXIT,
|
||||
},
|
||||
|
||||
// MENUPAGE_CHOOSE_MODE = 53
|
||||
{ "FEN_STA", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_SKIN_SELECT = 54
|
||||
{ "FET_PSU", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, MENUROW_4, MENUROW_4,
|
||||
//MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_MULTIPLAYER_MAIN,
|
||||
},
|
||||
|
||||
// MENUPAGE_KEYBOARD_CONTROLS = 55
|
||||
{ "FET_STI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUROW_1, MENUROW_1,
|
||||
//MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC,
|
||||
},
|
||||
|
||||
// MENUPAGE_MOUSE_CONTROLS = 56
|
||||
{ "FET_MTI", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, MENUROW_2, MENUROW_2,
|
||||
MENUACTION_MOUSESENS, "FEC_MSH", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS,
|
||||
MENUACTION_INVVERT, "FEC_IVV", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS,
|
||||
MENUACTION_MOUSESTEER, "FET_MST", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
||||
// MENUPAGE_57 = 57
|
||||
{ "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
|
||||
// MENUPAGE_58 = 58
|
||||
{ "", MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUPAGE_DISABLED, MENUROW_0, MENUROW_0,
|
||||
|
||||
},
|
||||
};
|
||||
15
src/core/Messages.cpp
Normal file
15
src/core/Messages.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Messages.h"
|
||||
|
||||
WRAPPER void CMessages::Display(void) { EAXJMP(0x529800); }
|
||||
WRAPPER void CMessages::ClearAllMessagesDisplayedByGame(void) { EAXJMP(0x52B670); }
|
||||
WRAPPER int CMessages::WideStringCopy(wchar* dst, wchar* src, unsigned short size) { EAXJMP(0x5294B0); }
|
||||
WRAPPER char CMessages::WideStringCompare(wchar* str1, wchar* str2, unsigned short size) { EAXJMP(0x529510); }
|
||||
WRAPPER void CMessages::InsertNumberInString(wchar* src, int n1, int n2, int n3, int n4, int n5, int n6, wchar* dst) { EAXJMP(0x52A1A0); }
|
||||
WRAPPER void CMessages::InsertPlayerControlKeysInString(wchar* src) { EAXJMP(0x52A490); }
|
||||
WRAPPER int CMessages::GetWideStringLength(wchar* src) { EAXJMP(0x529490); }
|
||||
|
||||
tPreviousBrief *CMessages::PreviousBriefs = (tPreviousBrief *)0x713C08;
|
||||
tMessage *CMessages::BriefMessages = (tMessage *)0x8786E0;
|
||||
tBigMessage *CMessages::BIGMessages = (tBigMessage *)0x773628;
|
||||
44
src/core/Messages.h
Normal file
44
src/core/Messages.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
struct tMessage
|
||||
{
|
||||
wchar *m_pText;
|
||||
uint16 m_nFlag;
|
||||
private:
|
||||
int8 _pad6[2];
|
||||
public:
|
||||
uint32 m_nTime;
|
||||
uint32 m_nStartTime;
|
||||
int32 m_nNumber[6];
|
||||
wchar *m_pString;
|
||||
};
|
||||
|
||||
struct tBigMessage
|
||||
{
|
||||
tMessage m_Current;
|
||||
tMessage m_Stack[3];
|
||||
};
|
||||
|
||||
struct tPreviousBrief
|
||||
{
|
||||
wchar *m_pText;
|
||||
int32 m_nNumber[6];
|
||||
wchar *m_pString;
|
||||
};
|
||||
|
||||
class CMessages
|
||||
{
|
||||
public:
|
||||
static tPreviousBrief *PreviousBriefs;
|
||||
static tMessage *BriefMessages;
|
||||
static tBigMessage *BIGMessages;
|
||||
|
||||
public:
|
||||
static void Display(void);
|
||||
static void ClearAllMessagesDisplayedByGame(void);
|
||||
static int WideStringCopy(wchar* dst, wchar* src, unsigned short size);
|
||||
static char WideStringCompare(wchar* str1, wchar* str2, unsigned short size);
|
||||
static void InsertNumberInString(wchar* src, int n1, int n2, int n3, int n4, int n5, int n6, wchar* dst);
|
||||
static void InsertPlayerControlKeysInString(wchar* src);
|
||||
static int GetWideStringLength(wchar *src);
|
||||
};
|
||||
77
src/core/NodeName.cpp
Normal file
77
src/core/NodeName.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "NodeName.h"
|
||||
|
||||
static int32 &gPluginOffset = *(int32*)0x64C610;
|
||||
|
||||
enum
|
||||
{
|
||||
ID_NODENAME = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0xFE),
|
||||
};
|
||||
|
||||
#define NODENAMEEXT(o) (RWPLUGINOFFSET(char, o, gPluginOffset))
|
||||
|
||||
void*
|
||||
NodeNameConstructor(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)
|
||||
{
|
||||
if(gPluginOffset > 0)
|
||||
NODENAMEEXT(object)[0] = '\0';
|
||||
return object;
|
||||
}
|
||||
|
||||
void*
|
||||
NodeNameDestructor(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
void*
|
||||
NodeNameCopy(void *dstObject, const void *srcObject, RwInt32 offsetInObject, RwInt32 sizeInObject)
|
||||
{
|
||||
strncpy(NODENAMEEXT(dstObject), NODENAMEEXT(srcObject), 23);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RwStream*
|
||||
NodeNameStreamRead(RwStream *stream, RwInt32 binaryLength, void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)
|
||||
{
|
||||
RwStreamRead(stream, NODENAMEEXT(object), binaryLength);
|
||||
NODENAMEEXT(object)[binaryLength] = '\0';
|
||||
return stream;
|
||||
}
|
||||
|
||||
RwStream*
|
||||
NodeNameStreamWrite(RwStream *stream, RwInt32 binaryLength, const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)
|
||||
{
|
||||
RwStreamWrite(stream, NODENAMEEXT(object), binaryLength);
|
||||
return stream;
|
||||
}
|
||||
|
||||
RwInt32
|
||||
NodeNameStreamGetSize(const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)
|
||||
{
|
||||
// game checks for null pointer on node name extension but that really happen
|
||||
return rwstrlen(NODENAMEEXT(object));
|
||||
}
|
||||
|
||||
bool
|
||||
NodeNamePluginAttach(void)
|
||||
{
|
||||
gPluginOffset = RwFrameRegisterPlugin(24, ID_NODENAME,
|
||||
NodeNameConstructor,
|
||||
NodeNameDestructor,
|
||||
NodeNameCopy);
|
||||
RwFrameRegisterPluginStream(ID_NODENAME,
|
||||
NodeNameStreamRead,
|
||||
NodeNameStreamWrite,
|
||||
NodeNameStreamGetSize);
|
||||
return gPluginOffset != -1;
|
||||
}
|
||||
|
||||
char*
|
||||
GetFrameNodeName(RwFrame *frame)
|
||||
{
|
||||
if(gPluginOffset < 0)
|
||||
return nil;
|
||||
return NODENAMEEXT(frame);
|
||||
}
|
||||
4
src/core/NodeName.h
Normal file
4
src/core/NodeName.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
bool NodeNamePluginAttach(void);
|
||||
char *GetFrameNodeName(RwFrame *frame);
|
||||
20
src/core/PCSave.cpp
Normal file
20
src/core/PCSave.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Frontend.h"
|
||||
#include "PCSave.h"
|
||||
|
||||
WRAPPER void C_PcSave::SetSaveDirectory(const char *path) { EAXJMP(0x591EA0); }
|
||||
WRAPPER int8 C_PcSave::PopulateSlotInfo() { EAXJMP(0x592090); }
|
||||
WRAPPER int8 C_PcSave::DeleteSlot(int) { EAXJMP(0x5922F0); }
|
||||
WRAPPER int8 C_PcSave::SaveSlot(int) { EAXJMP(0x591EC0); }
|
||||
|
||||
WRAPPER int8 CheckSlotDataValid(int) { EAXJMP(0x591A40); }
|
||||
|
||||
WRAPPER wchar *GetNameOfSavedGame(int counter) { EAXJMP(0x591B60); }
|
||||
WRAPPER wchar *GetSavedGameDateAndTime(int counter) { EAXJMP(0x591B50); }
|
||||
|
||||
|
||||
C_PcSave PcSaveHelper = *(C_PcSave*)0x8E2C60;
|
||||
int *Slots = (int*)0x728040;
|
||||
int *SlotFileName = (int*)0x6F07C8;
|
||||
int *SlotSaveDate = (int*)0x72B858;
|
||||
21
src/core/PCSave.h
Normal file
21
src/core/PCSave.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
class C_PcSave
|
||||
{
|
||||
public:
|
||||
int32 m_nHelper;
|
||||
|
||||
static void SetSaveDirectory(const char *path);
|
||||
int8 PopulateSlotInfo();
|
||||
int8 DeleteSlot(int);
|
||||
int8 SaveSlot(int);
|
||||
};
|
||||
|
||||
extern int8 CheckSlotDataValid(int);
|
||||
extern wchar *GetNameOfSavedGame(int counter);
|
||||
extern wchar *GetSavedGameDateAndTime(int counter);
|
||||
|
||||
extern C_PcSave PcSaveHelper;
|
||||
extern int *Slots;
|
||||
extern int *SlotFileName;
|
||||
extern int *SlotSaveDate;
|
||||
2091
src/core/Pad.cpp
Normal file
2091
src/core/Pad.cpp
Normal file
File diff suppressed because it is too large
Load Diff
367
src/core/Pad.h
Normal file
367
src/core/Pad.h
Normal file
@@ -0,0 +1,367 @@
|
||||
#pragma once
|
||||
|
||||
// same as RW skeleton
|
||||
/*
|
||||
enum Key
|
||||
{
|
||||
// ascii...
|
||||
|
||||
KEY_ESC = 128,
|
||||
|
||||
KEY_F1 = 129,
|
||||
KEY_F2 = 130,
|
||||
KEY_F3 = 131,
|
||||
KEY_F4 = 132,
|
||||
KEY_F5 = 133,
|
||||
KEY_F6 = 134,
|
||||
KEY_F7 = 135,
|
||||
KEY_F8 = 136,
|
||||
KEY_F9 = 137,
|
||||
KEY_F10 = 138,
|
||||
KEY_F11 = 139,
|
||||
KEY_F12 = 140,
|
||||
|
||||
KEY_INS = 141,
|
||||
KEY_DEL = 142,
|
||||
KEY_HOME = 143,
|
||||
KEY_END = 144,
|
||||
KEY_PGUP = 145,
|
||||
KEY_PGDN = 146,
|
||||
|
||||
KEY_UP = 147,
|
||||
KEY_DOWN = 148,
|
||||
KEY_LEFT = 149,
|
||||
KEY_RIGHT = 150,
|
||||
|
||||
// some stuff ommitted
|
||||
|
||||
KEY_BACKSP = 168,
|
||||
KEY_TAB = 169,
|
||||
KEY_CAPSLK = 170,
|
||||
KEY_ENTER = 171,
|
||||
KEY_LSHIFT = 172,
|
||||
KEY_RSHIFT = 173,
|
||||
KEY_LCTRL = 174,
|
||||
KEY_RCTRL = 175,
|
||||
KEY_LALT = 176,
|
||||
KEY_RALT = 177,
|
||||
|
||||
KEY_NULL, // unused
|
||||
KEY_NUMKEYS
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
class CControllerState
|
||||
{
|
||||
public:
|
||||
int16 LeftStickX, LeftStickY;
|
||||
int16 RightStickX, RightStickY;
|
||||
int16 LeftShoulder1, LeftShoulder2;
|
||||
int16 RightShoulder1, RightShoulder2;
|
||||
int16 DPadUp, DPadDown, DPadLeft, DPadRight;
|
||||
int16 Start, Select;
|
||||
int16 Square, Triangle, Cross, Circle;
|
||||
int16 LeftShock, RightShock;
|
||||
int16 NetworkTalk;
|
||||
float GetLeftStickX(void) { return LeftStickX/32767.0f; };
|
||||
float GetLeftStickY(void) { return LeftStickY/32767.0f; };
|
||||
float GetRightStickX(void) { return RightStickX/32767.0f; };
|
||||
float GetRightStickY(void) { return RightStickY/32767.0f; };
|
||||
|
||||
void Clear(void);
|
||||
};
|
||||
VALIDATE_SIZE(CControllerState, 0x2A);
|
||||
|
||||
class CMouseControllerState
|
||||
{
|
||||
public:
|
||||
//uint32 btns; // bit 0-2 button 1-3
|
||||
|
||||
bool LMB;
|
||||
bool RMB;
|
||||
bool MMB;
|
||||
bool WHEELUP;
|
||||
bool WHEELDN;
|
||||
bool MXB1;
|
||||
bool MXB2;
|
||||
char _pad0;
|
||||
|
||||
float x, y;
|
||||
|
||||
CMouseControllerState();
|
||||
void Clear();
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(CMouseControllerState, 0x10);
|
||||
|
||||
class CMousePointerStateHelper
|
||||
{
|
||||
public:
|
||||
bool bInvertHorizontally;
|
||||
bool bInvertVertically;
|
||||
|
||||
CMouseControllerState GetMouseSetUp();
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(CMousePointerStateHelper, 0x2);
|
||||
|
||||
extern CMousePointerStateHelper &MousePointerStateHelper;
|
||||
|
||||
|
||||
class CKeyboardState
|
||||
{
|
||||
public:
|
||||
int16 F[12];
|
||||
int16 VK_KEYS[256];
|
||||
int16 ESC;
|
||||
int16 INS;
|
||||
int16 DEL;
|
||||
int16 HOME;
|
||||
int16 END;
|
||||
int16 PGUP;
|
||||
int16 PGDN;
|
||||
int16 UP;
|
||||
int16 DOWN;
|
||||
int16 LEFT;
|
||||
int16 RIGHT;
|
||||
int16 SCROLLLOCK;
|
||||
int16 PAUSE;
|
||||
int16 NUMLOCK;
|
||||
int16 DIV;
|
||||
int16 MUL;
|
||||
int16 SUB;
|
||||
int16 ADD;
|
||||
int16 ENTER;
|
||||
int16 DECIMAL;
|
||||
int16 NUM1;
|
||||
int16 NUM2;
|
||||
int16 NUM3;
|
||||
int16 NUM4;
|
||||
int16 NUM5;
|
||||
int16 NUM6;
|
||||
int16 NUM7;
|
||||
int16 NUM8;
|
||||
int16 NUM9;
|
||||
int16 NUM0;
|
||||
int16 BACKSP;
|
||||
int16 TAB;
|
||||
int16 CAPSLOCK;
|
||||
int16 EXTENTER;
|
||||
int16 LSHIFT;
|
||||
int16 RSHIFT;
|
||||
int16 SHIFT;
|
||||
int16 LCTRL;
|
||||
int16 RCTRL;
|
||||
int16 LALT;
|
||||
int16 RALT;
|
||||
int16 LWIN;
|
||||
int16 RWIN;
|
||||
int16 APPS;
|
||||
|
||||
void Clear();
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(CKeyboardState, 0x270);
|
||||
|
||||
enum
|
||||
{
|
||||
// taken from miss2
|
||||
PAD1 = 0,
|
||||
PAD2,
|
||||
|
||||
MAX_PADS
|
||||
};
|
||||
|
||||
class CPad
|
||||
{
|
||||
public:
|
||||
CControllerState NewState;
|
||||
CControllerState OldState;
|
||||
CControllerState PCTempKeyState;
|
||||
CControllerState PCTempJoyState;
|
||||
CControllerState PCTempMouseState;
|
||||
// straight out of my IDB
|
||||
int16 Phase;
|
||||
int16 Mode;
|
||||
int16 ShakeDur;
|
||||
uint8 ShakeFreq;
|
||||
int8 bHornHistory[5];
|
||||
uint8 iCurrHornHistory;
|
||||
bool DisablePlayerControls;
|
||||
int8 bApplyBrakes;
|
||||
char _unk[12]; //int32 unk[3];
|
||||
char _pad0[3];
|
||||
int32 LastTimeTouched;
|
||||
int32 AverageWeapon;
|
||||
int32 AverageEntries;
|
||||
|
||||
CPad() { }
|
||||
~CPad() { }
|
||||
|
||||
static bool &bDisplayNoControllerMessage;
|
||||
static bool &bObsoleteControllerMessage;
|
||||
static bool &m_bMapPadOneToPadTwo;
|
||||
|
||||
static CKeyboardState &OldKeyState;
|
||||
static CKeyboardState &NewKeyState;
|
||||
static CKeyboardState &TempKeyState;
|
||||
static char KeyBoardCheatString[18];
|
||||
static CMouseControllerState &OldMouseControllerState;
|
||||
static CMouseControllerState &NewMouseControllerState;
|
||||
static CMouseControllerState &PCTempMouseControllerState;
|
||||
|
||||
|
||||
|
||||
|
||||
void Clear(bool bResetPlayerControls);
|
||||
void ClearMouseHistory();
|
||||
void UpdateMouse();
|
||||
CControllerState ReconcileTwoControllersInput(CControllerState const &State1, CControllerState const &State2);
|
||||
void StartShake(int16 nDur, uint8 nFreq);
|
||||
void StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fz);
|
||||
void StartShake_Train(float fX, float fY);
|
||||
void AddToPCCheatString(char c);
|
||||
|
||||
static void UpdatePads(void);
|
||||
void ProcessPCSpecificStuff(void);
|
||||
void Update(int16 unk);
|
||||
|
||||
static void DoCheats(void);
|
||||
void DoCheats(int16 unk);
|
||||
|
||||
static void StopPadsShaking(void);
|
||||
void StopShaking(int16 unk);
|
||||
|
||||
static CPad *GetPad(int32 pad);
|
||||
|
||||
int16 GetSteeringLeftRight(void);
|
||||
int16 GetSteeringUpDown(void);
|
||||
int16 GetCarGunUpDown(void);
|
||||
int16 GetCarGunLeftRight(void);
|
||||
int16 GetPedWalkLeftRight(void);
|
||||
int16 GetPedWalkUpDown(void);
|
||||
int16 GetAnalogueUpDown(void);
|
||||
bool GetLookLeft(void);
|
||||
bool GetLookRight(void);
|
||||
bool GetLookBehindForCar(void);
|
||||
bool GetLookBehindForPed(void);
|
||||
bool GetHorn(void);
|
||||
bool HornJustDown(void);
|
||||
bool GetCarGunFired(void);
|
||||
bool CarGunJustDown(void);
|
||||
int16 GetHandBrake(void);
|
||||
int16 GetBrake(void);
|
||||
bool GetExitVehicle(void);
|
||||
bool ExitVehicleJustDown(void);
|
||||
int32 GetWeapon(void);
|
||||
bool WeaponJustDown(void);
|
||||
int16 GetAccelerate(void);
|
||||
bool CycleCameraModeUpJustDown(void);
|
||||
bool CycleCameraModeDownJustDown(void);
|
||||
bool ChangeStationJustDown(void);
|
||||
bool CycleWeaponLeftJustDown(void);
|
||||
bool CycleWeaponRightJustDown(void);
|
||||
bool GetTarget(void);
|
||||
bool TargetJustDown(void);
|
||||
bool JumpJustDown(void);
|
||||
bool GetSprint(void);
|
||||
bool ShiftTargetLeftJustDown(void);
|
||||
bool ShiftTargetRightJustDown(void);
|
||||
bool GetAnaloguePadUp(void);
|
||||
bool GetAnaloguePadDown(void);
|
||||
bool GetAnaloguePadLeft(void);
|
||||
bool GetAnaloguePadRight(void);
|
||||
bool GetAnaloguePadLeftJustUp(void);
|
||||
bool GetAnaloguePadRightJustUp(void);
|
||||
bool ForceCameraBehindPlayer(void);
|
||||
bool SniperZoomIn(void);
|
||||
bool SniperZoomOut(void);
|
||||
int16 SniperModeLookLeftRight(void);
|
||||
int16 SniperModeLookUpDown(void);
|
||||
int16 LookAroundLeftRight(void);
|
||||
int16 LookAroundUpDown(void);
|
||||
void ResetAverageWeapon(void);
|
||||
static void PrintErrorMessage(void);
|
||||
static void ResetCheats(void);
|
||||
static char *EditString(char *pStr, int32 nSize);
|
||||
static int32 *EditCodesForControls(int32 *pRsKeys, int32 nSize);
|
||||
|
||||
// mouse
|
||||
bool GetLeftMouseJustDown() { return !!(NewMouseControllerState.LMB && !OldMouseControllerState.LMB); }
|
||||
|
||||
// keyboard
|
||||
|
||||
bool GetCharJustDown(int32 c) { return !!(NewKeyState.VK_KEYS[c] && !OldKeyState.VK_KEYS[c]); }
|
||||
bool GetFJustDown(int32 n) { return !!(NewKeyState.F[n] && !OldKeyState.F[n]); }
|
||||
bool GetEscapeJustDown() { return !!(NewKeyState.ESC && !OldKeyState.ESC); }
|
||||
bool GetInsertJustDown() { return !!(NewKeyState.INS && !OldKeyState.INS); }
|
||||
bool GetDeleteJustDown() { return !!(NewKeyState.DEL && !OldKeyState.DEL); }
|
||||
bool GetHomeJustDown() { return !!(NewKeyState.HOME && !OldKeyState.HOME); }
|
||||
bool GetEndJustDown() { return !!(NewKeyState.END && !OldKeyState.END); }
|
||||
bool GetPageUpJustDown() { return !!(NewKeyState.PGUP && !OldKeyState.PGUP); }
|
||||
bool GetPageDownJustDown() { return !!(NewKeyState.PGDN && !OldKeyState.PGDN); }
|
||||
bool GetUpJustDown() { return !!(NewKeyState.UP && !OldKeyState.UP); }
|
||||
bool GetDownJustDown() { return !!(NewKeyState.DOWN && !OldKeyState.DOWN); }
|
||||
bool GetLeftJustDown() { return !!(NewKeyState.LEFT && !OldKeyState.LEFT); }
|
||||
bool GetRightJustDown() { return !!(NewKeyState.RIGHT && !OldKeyState.RIGHT); }
|
||||
bool GetScrollLockJustDown() { return !!(NewKeyState.SCROLLLOCK && !OldKeyState.SCROLLLOCK); }
|
||||
bool GetPauseJustDown() { return !!(NewKeyState.PAUSE && !OldKeyState.PAUSE); }
|
||||
bool GetNumLockJustDown() { return !!(NewKeyState.NUMLOCK && !OldKeyState.NUMLOCK); }
|
||||
bool GetDivideJustDown() { return !!(NewKeyState.DIV && !OldKeyState.DIV); }
|
||||
bool GetTimesJustDown() { return !!(NewKeyState.MUL && !OldKeyState.MUL); }
|
||||
bool GetMinusJustDown() { return !!(NewKeyState.SUB && !OldKeyState.SUB); }
|
||||
bool GetPlusJustDown() { return !!(NewKeyState.ADD && !OldKeyState.ADD); }
|
||||
bool GetPadEnterJustDown() { return !!(NewKeyState.ENTER && !OldKeyState.ENTER); } // GetEnterJustDown
|
||||
bool GetPadDelJustDown() { return !!(NewKeyState.DECIMAL && !OldKeyState.DECIMAL); }
|
||||
bool GetPad1JustDown() { return !!(NewKeyState.NUM1 && !OldKeyState.NUM1); }
|
||||
bool GetPad2JustDown() { return !!(NewKeyState.NUM2 && !OldKeyState.NUM2); }
|
||||
bool GetPad3JustDown() { return !!(NewKeyState.NUM3 && !OldKeyState.NUM3); }
|
||||
bool GetPad4JustDown() { return !!(NewKeyState.NUM4 && !OldKeyState.NUM4); }
|
||||
bool GetPad5JustDown() { return !!(NewKeyState.NUM5 && !OldKeyState.NUM5); }
|
||||
bool GetPad6JustDown() { return !!(NewKeyState.NUM6 && !OldKeyState.NUM6); }
|
||||
bool GetPad7JustDown() { return !!(NewKeyState.NUM7 && !OldKeyState.NUM7); }
|
||||
bool GetPad8JustDown() { return !!(NewKeyState.NUM8 && !OldKeyState.NUM8); }
|
||||
bool GetPad9JustDown() { return !!(NewKeyState.NUM9 && !OldKeyState.NUM9); }
|
||||
bool GetPad0JustDown() { return !!(NewKeyState.NUM0 && !OldKeyState.NUM0); }
|
||||
bool GetBackspaceJustDown() { return !!(NewKeyState.BACKSP && !OldKeyState.BACKSP); }
|
||||
bool GetTabJustDown() { return !!(NewKeyState.TAB && !OldKeyState.TAB); }
|
||||
bool GetCapsLockJustDown() { return !!(NewKeyState.CAPSLOCK && !OldKeyState.CAPSLOCK); }
|
||||
bool GetEnterJustDown() { return !!(NewKeyState.EXTENTER && !OldKeyState.EXTENTER); }
|
||||
bool GetLeftShiftJustDown() { return !!(NewKeyState.LSHIFT && !OldKeyState.LSHIFT); }
|
||||
bool GetShiftJustDown() { return !!(NewKeyState.SHIFT && !OldKeyState.SHIFT); }
|
||||
bool GetRightShiftJustDown() { return !!(NewKeyState.RSHIFT && !OldKeyState.RSHIFT); }
|
||||
bool GetLeftCtrlJustDown() { return !!(NewKeyState.LCTRL && !OldKeyState.LCTRL); }
|
||||
bool GetRightCtrlJustDown() { return !!(NewKeyState.RCTRL && !OldKeyState.RCTRL); }
|
||||
bool GetLeftAltJustDown() { return !!(NewKeyState.LALT && !OldKeyState.LALT); }
|
||||
bool GetRightAltJustDown() { return !!(NewKeyState.RALT && !OldKeyState.RALT); }
|
||||
bool GetLeftWinJustDown() { return !!(NewKeyState.LWIN && !OldKeyState.LWIN); }
|
||||
bool GetRightWinJustDown() { return !!(NewKeyState.RWIN && !OldKeyState.RWIN); }
|
||||
bool GetAppsJustDown() { return !!(NewKeyState.APPS && !OldKeyState.APPS); }
|
||||
|
||||
// pad
|
||||
|
||||
bool GetTriangleJustDown() { return !!(NewState.Triangle && !OldState.Triangle); }
|
||||
bool GetCircleJustDown() { return !!(NewState.Circle && !OldState.Circle); }
|
||||
bool GetCrossJustDown() { return !!(NewState.Cross && !OldState.Cross); }
|
||||
bool GetSquareJustDown() { return !!(NewState.Square && !OldState.Square); }
|
||||
bool GetDPadUpJustDown() { return !!(NewState.DPadUp && !OldState.DPadUp); }
|
||||
bool GetDPadDownJustDown() { return !!(NewState.DPadDown && !OldState.DPadDown); }
|
||||
bool GetDPadLeftJustDown() { return !!(NewState.DPadLeft && !OldState.DPadLeft); }
|
||||
bool GetDPadRightJustDown() { return !!(NewState.DPadRight && !OldState.DPadRight); }
|
||||
bool GetLeftShoulder1JustDown() { return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); }
|
||||
bool GetLeftShoulder2JustDown() { return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); }
|
||||
bool GetRightShoulder1JustDown() { return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); }
|
||||
bool GetRightShoulder2JustDown() { return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); }
|
||||
|
||||
int32 GetLeftShoulder1(void) { return NewState.LeftShoulder1; }
|
||||
int32 GetLeftShoulder2(void) { return NewState.LeftShoulder2; }
|
||||
int32 GetRightShoulder1(void) { return NewState.RightShoulder1; }
|
||||
int32 GetRightShoulder2(void) { return NewState.RightShoulder2; }
|
||||
};
|
||||
VALIDATE_SIZE(CPad, 0xFC);
|
||||
|
||||
#define IsButtonJustDown(pad, btn) \
|
||||
(!(pad)->OldState.btn && (pad)->NewState.btn)
|
||||
|
||||
void LittleTest(void);
|
||||
72
src/core/Placeable.cpp
Normal file
72
src/core/Placeable.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "common.h"
|
||||
#include "Placeable.h"
|
||||
#include "patcher.h"
|
||||
|
||||
CPlaceable::CPlaceable(void)
|
||||
{
|
||||
m_matrix.SetScale(1.0f);
|
||||
}
|
||||
|
||||
CPlaceable::~CPlaceable(void) { }
|
||||
|
||||
void
|
||||
CPlaceable::SetHeading(float angle)
|
||||
{
|
||||
CVector pos = GetPosition();
|
||||
m_matrix.SetRotateZ(angle);
|
||||
GetPosition() += pos;
|
||||
}
|
||||
|
||||
bool
|
||||
CPlaceable::IsWithinArea(float x1, float y1, float x2, float y2)
|
||||
{
|
||||
float tmp;
|
||||
|
||||
if(x1 > x2){
|
||||
tmp = x1;
|
||||
x1 = x2;
|
||||
x2 = tmp;
|
||||
}
|
||||
if(y1 > y2){
|
||||
tmp = y1;
|
||||
y1 = y2;
|
||||
y2 = tmp;
|
||||
}
|
||||
|
||||
return x1 <= GetPosition().x && GetPosition().x <= x2 &&
|
||||
y1 <= GetPosition().y && GetPosition().y <= y2;
|
||||
}
|
||||
|
||||
bool
|
||||
CPlaceable::IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2)
|
||||
{
|
||||
float tmp;
|
||||
|
||||
if(x1 > x2){
|
||||
tmp = x1;
|
||||
x1 = x2;
|
||||
x2 = tmp;
|
||||
}
|
||||
if(y1 > y2){
|
||||
tmp = y1;
|
||||
y1 = y2;
|
||||
y2 = tmp;
|
||||
}
|
||||
if(z1 > z2){
|
||||
tmp = z1;
|
||||
z1 = z2;
|
||||
z2 = tmp;
|
||||
}
|
||||
|
||||
return x1 <= GetPosition().x && GetPosition().x <= x2 &&
|
||||
y1 <= GetPosition().y && GetPosition().y <= y2 &&
|
||||
z1 <= GetPosition().z && GetPosition().z <= z2;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x49F9A0, &CPlaceable::ctor, PATCH_JUMP);
|
||||
InjectHook(0x49F9E0, &CPlaceable::dtor, PATCH_JUMP);
|
||||
InjectHook(0x49FA00, &CPlaceable::SetHeading, PATCH_JUMP);
|
||||
InjectHook(0x49FA50, (bool (CPlaceable::*)(float, float, float, float))&CPlaceable::IsWithinArea, PATCH_JUMP);
|
||||
InjectHook(0x49FAF0, (bool (CPlaceable::*)(float, float, float, float, float, float))&CPlaceable::IsWithinArea, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
26
src/core/Placeable.h
Normal file
26
src/core/Placeable.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
class CPlaceable
|
||||
{
|
||||
public:
|
||||
// disable allocation
|
||||
static void *operator new(size_t) = delete;
|
||||
|
||||
CMatrix m_matrix;
|
||||
|
||||
CPlaceable(void);
|
||||
virtual ~CPlaceable(void);
|
||||
CVector &GetPosition(void) { return *m_matrix.GetPosition(); }
|
||||
CVector &GetRight(void) { return *m_matrix.GetRight(); }
|
||||
CVector &GetForward(void) { return *m_matrix.GetForward(); }
|
||||
CVector &GetUp(void) { return *m_matrix.GetUp(); }
|
||||
CMatrix &GetMatrix(void) { return m_matrix; }
|
||||
void SetTransform(RwMatrix *m) { m_matrix = CMatrix(m, false); }
|
||||
void SetHeading(float angle);
|
||||
bool IsWithinArea(float x1, float y1, float x2, float y2);
|
||||
bool IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2);
|
||||
|
||||
CPlaceable *ctor(void) { return ::new (this) CPlaceable(); }
|
||||
void dtor(void) { this->CPlaceable::~CPlaceable(); }
|
||||
};
|
||||
static_assert(sizeof(CPlaceable) == 0x4C, "CPlaceable: error");
|
||||
5
src/core/PlayerInfo.cpp
Normal file
5
src/core/PlayerInfo.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "PlayerInfo.h"
|
||||
|
||||
WRAPPER void CPlayerInfo::MakePlayerSafe(bool) { EAXJMP(0x4A1400); }
|
||||
72
src/core/PlayerInfo.h
Normal file
72
src/core/PlayerInfo.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "Collision.h"
|
||||
|
||||
enum eWastedBustedState
|
||||
{
|
||||
WBSTATE_PLAYING,
|
||||
WBSTATE_WASTED,
|
||||
WBSTATE_BUSTED,
|
||||
WBSTATE_FAILED_CRITICAL_MISSION,
|
||||
};
|
||||
|
||||
class CVehicle;
|
||||
class CPlayerPed;
|
||||
class CCivilianPed;
|
||||
|
||||
class CPlayerInfo
|
||||
{
|
||||
public:
|
||||
CPlayerPed *m_pPed;
|
||||
CVehicle *m_pRemoteVehicle;
|
||||
CColModel m_ColModel;
|
||||
CVehicle *m_pVehicleEx;
|
||||
char m_aPlayerName[70];
|
||||
int32 m_nMoney;
|
||||
int32 m_nVisibleMoney;
|
||||
int32 m_nCollectedPackages;
|
||||
int32 m_nTotalPackages;
|
||||
int32 field_188;
|
||||
int32 m_nSwitchTaxiTime;
|
||||
bool m_bSwitchTaxi;
|
||||
int8 field_197;
|
||||
int8 field_198;
|
||||
int8 field_199;
|
||||
int32 m_nNextSexFrequencyUpdateTime;
|
||||
int32 m_nNextSexMoneyUpdateTime;
|
||||
int32 m_nSexFrequency;
|
||||
CCivilianPed *m_pHooker;
|
||||
int8 m_WBState; // eWastedBustedState
|
||||
int8 field_217;
|
||||
int8 field_218;
|
||||
int8 field_219;
|
||||
int32 m_nWBTime;
|
||||
bool m_bInRemoteMode;
|
||||
int8 field_225;
|
||||
int8 field_226;
|
||||
int8 field_227;
|
||||
int32 m_nTimeLostRemoteCar;
|
||||
int32 m_nTimeLastHealthLoss;
|
||||
int32 m_nTimeLastArmourLoss;
|
||||
int32 field_240;
|
||||
int32 m_nUpsideDownCounter;
|
||||
int32 field_248;
|
||||
int16 m_nTrafficMultiplier;
|
||||
int8 field_254;
|
||||
int8 field_255;
|
||||
float m_fRoadDensity;
|
||||
int32 m_nPreviousTimeRewardedForExplosion;
|
||||
int32 m_nExplosionsSinceLastReward;
|
||||
int32 field_268;
|
||||
int32 field_272;
|
||||
bool m_bInfiniteSprint;
|
||||
bool m_bFastReload;
|
||||
bool m_bGetOutOfJailFree;
|
||||
bool m_bGetOutOfHospitalFree;
|
||||
uint8 m_aSkinName[32];
|
||||
RwTexture *m_pSkinTexture;
|
||||
|
||||
void MakePlayerSafe(bool);
|
||||
};
|
||||
|
||||
static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerInfo: error");
|
||||
5
src/core/PlayerSkin.cpp
Normal file
5
src/core/PlayerSkin.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "PlayerSkin.h"
|
||||
|
||||
WRAPPER void CPlayerSkin::BeginFrontEndSkinEdit() { EAXJMP(0x59BC70); }
|
||||
7
src/core/PlayerSkin.h
Normal file
7
src/core/PlayerSkin.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
class CPlayerSkin
|
||||
{
|
||||
public:
|
||||
static void BeginFrontEndSkinEdit();
|
||||
};
|
||||
25
src/core/Pools.cpp
Normal file
25
src/core/Pools.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "common.h"
|
||||
#include "Pools.h"
|
||||
|
||||
CCPtrNodePool *&CPools::ms_pPtrNodePool = *(CCPtrNodePool**)0x943044;
|
||||
CEntryInfoNodePool *&CPools::ms_pEntryInfoNodePool = *(CEntryInfoNodePool**)0x941448;
|
||||
CPedPool *&CPools::ms_pPedPool = *(CPedPool**)0x8F2C60;
|
||||
CVehiclePool *&CPools::ms_pVehiclePool = *(CVehiclePool**)0x9430DC;
|
||||
CBuildingPool *&CPools::ms_pBuildingPool = *(CBuildingPool**)0x8F2C04;
|
||||
CTreadablePool *&CPools::ms_pTreadablePool = *(CTreadablePool**)0x8F2568;
|
||||
CObjectPool *&CPools::ms_pObjectPool = *(CObjectPool**)0x880E28;
|
||||
CDummyPool *&CPools::ms_pDummyPool = *(CDummyPool**)0x8F2C18;
|
||||
|
||||
void
|
||||
CPools::Initialise(void)
|
||||
{
|
||||
// TODO: unused right now
|
||||
ms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES);
|
||||
ms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS);
|
||||
ms_pPedPool = new CPedPool(NUMPEDS);
|
||||
ms_pVehiclePool = new CVehiclePool(NUMVEHICLES);
|
||||
ms_pBuildingPool = new CBuildingPool(NUMBUILDINGS);
|
||||
ms_pTreadablePool = new CTreadablePool(NUMTREADABLES);
|
||||
ms_pObjectPool = new CObjectPool(NUMOBJECTS);
|
||||
ms_pDummyPool = new CDummyPool(NUMDUMMIES);
|
||||
}
|
||||
43
src/core/Pools.h
Normal file
43
src/core/Pools.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "templates.h"
|
||||
#include "Lists.h"
|
||||
#include "Treadable.h"
|
||||
#include "Object.h"
|
||||
#include "CutsceneHead.h"
|
||||
#include "PlayerPed.h"
|
||||
#include "Automobile.h"
|
||||
#include "DummyPed.h"
|
||||
|
||||
typedef CPool<CPtrNode> CCPtrNodePool;
|
||||
typedef CPool<CEntryInfoNode> CEntryInfoNodePool;
|
||||
typedef CPool<CPed,CPlayerPed> CPedPool;
|
||||
typedef CPool<CVehicle,CAutomobile> CVehiclePool;
|
||||
typedef CPool<CBuilding> CBuildingPool;
|
||||
typedef CPool<CTreadable> CTreadablePool;
|
||||
typedef CPool<CObject, CCutsceneHead> CObjectPool;
|
||||
typedef CPool<CDummy, CDummyPed> CDummyPool;
|
||||
|
||||
class CPools
|
||||
{
|
||||
static CCPtrNodePool *&ms_pPtrNodePool;
|
||||
static CEntryInfoNodePool *&ms_pEntryInfoNodePool;
|
||||
static CPedPool *&ms_pPedPool;
|
||||
static CVehiclePool *&ms_pVehiclePool;
|
||||
static CBuildingPool *&ms_pBuildingPool;
|
||||
static CTreadablePool *&ms_pTreadablePool;
|
||||
static CObjectPool *&ms_pObjectPool;
|
||||
static CDummyPool *&ms_pDummyPool;
|
||||
// ms_pAudioScriptObjectPool
|
||||
public:
|
||||
static CCPtrNodePool *GetPtrNodePool(void) { return ms_pPtrNodePool; }
|
||||
static CEntryInfoNodePool *GetEntryInfoNodePool(void) { return ms_pEntryInfoNodePool; }
|
||||
static CPedPool *GetPedPool(void) { return ms_pPedPool; }
|
||||
static CVehiclePool *GetVehiclePool(void) { return ms_pVehiclePool; }
|
||||
static CBuildingPool *GetBuildingPool(void) { return ms_pBuildingPool; }
|
||||
static CTreadablePool *GetTreadablePool(void) { return ms_pTreadablePool; }
|
||||
static CObjectPool *GetObjectPool(void) { return ms_pObjectPool; }
|
||||
static CDummyPool *GetDummyPool(void) { return ms_pDummyPool; }
|
||||
|
||||
static void Initialise(void);
|
||||
};
|
||||
1117
src/core/Radar.cpp
Normal file
1117
src/core/Radar.cpp
Normal file
File diff suppressed because it is too large
Load Diff
146
src/core/Radar.h
Normal file
146
src/core/Radar.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#pragma once
|
||||
#include "Sprite2d.h"
|
||||
|
||||
enum eBlipType
|
||||
{
|
||||
BLIP_NONE,
|
||||
BLIP_CAR,
|
||||
BLIP_CHAR,
|
||||
BLIP_OBJECT,
|
||||
BLIP_COORD,
|
||||
BLIP_CONTACT_POINT
|
||||
};
|
||||
|
||||
enum eBlipDisplay
|
||||
{
|
||||
BLIP_DISPLAY_NEITHER = 0,
|
||||
BLIP_DISPLAY_MARKER_ONLY = 1,
|
||||
BLIP_DISPLAY_BLIP_ONLY = 2,
|
||||
BLIP_DISPLAY_BOTH = 3,
|
||||
};
|
||||
|
||||
enum eRadarSprite
|
||||
{
|
||||
RADAR_SPRITE_NONE = 0,
|
||||
RADAR_SPRITE_ASUKA = 1,
|
||||
RADAR_SPRITE_BOMB = 2,
|
||||
RADAR_SPRITE_CAT = 3,
|
||||
RADAR_SPRITE_CENTRE = 4,
|
||||
RADAR_SPRITE_COPCAR = 5,
|
||||
RADAR_SPRITE_DON = 6,
|
||||
RADAR_SPRITE_EIGHT = 7,
|
||||
RADAR_SPRITE_EL = 8,
|
||||
RADAR_SPRITE_ICE = 9,
|
||||
RADAR_SPRITE_JOEY = 10,
|
||||
RADAR_SPRITE_KENJI = 11,
|
||||
RADAR_SPRITE_LIZ = 12,
|
||||
RADAR_SPRITE_LUIGI = 13,
|
||||
RADAR_SPRITE_NORTH = 14,
|
||||
RADAR_SPRITE_RAY = 15,
|
||||
RADAR_SPRITE_SAL = 16,
|
||||
RADAR_SPRITE_SAVE = 17,
|
||||
RADAR_SPRITE_SPRAY = 18,
|
||||
RADAR_SPRITE_TONY = 19,
|
||||
RADAR_SPRITE_WEAPON = 20,
|
||||
RADAR_SPRITE_COUNT = 21,
|
||||
};
|
||||
|
||||
struct CBlip
|
||||
{
|
||||
int32 m_nColor;
|
||||
int16 m_eBlipType; // eBlipType
|
||||
int32 m_nEntityHandle;
|
||||
CVector2D m_vec2DPos;
|
||||
CVector m_vecPos;
|
||||
int16 m_BlipIndex;
|
||||
bool m_bDim;
|
||||
bool m_bInUse;
|
||||
float m_Radius;
|
||||
int16 m_wScale;
|
||||
int16 m_eBlipDisplay; // eBlipDisplay
|
||||
int16 m_IconID; // eRadarSprite
|
||||
};
|
||||
static_assert(sizeof(CBlip) == 0x30, "CBlip: error");
|
||||
|
||||
// Values for screen space
|
||||
#define RADAR_LEFT (40.0f)
|
||||
#define RADAR_BOTTOM (47.0f)
|
||||
#define RADAR_WIDTH (94.0f)
|
||||
#define RADAR_HEIGHT (76.0f)
|
||||
|
||||
class CRadar
|
||||
{
|
||||
public:
|
||||
static float &m_RadarRange;
|
||||
static CBlip *ms_RadarTrace; //[NUMRADARBLIPS]
|
||||
static CSprite2d *AsukaSprite;
|
||||
static CSprite2d *BombSprite;
|
||||
static CSprite2d *CatSprite;
|
||||
static CSprite2d *CentreSprite;
|
||||
static CSprite2d *CopcarSprite;
|
||||
static CSprite2d *DonSprite;
|
||||
static CSprite2d *EightSprite;
|
||||
static CSprite2d *ElSprite;
|
||||
static CSprite2d *IceSprite;
|
||||
static CSprite2d *JoeySprite;
|
||||
static CSprite2d *KenjiSprite;
|
||||
static CSprite2d *LizSprite;
|
||||
static CSprite2d *LuigiSprite;
|
||||
static CSprite2d *NorthSprite;
|
||||
static CSprite2d *RaySprite;
|
||||
static CSprite2d *SalSprite;
|
||||
static CSprite2d *SaveSprite;
|
||||
static CSprite2d *SpraySprite;
|
||||
static CSprite2d *TonySprite;
|
||||
static CSprite2d *WeaponSprite;
|
||||
static CSprite2d *RadarSprites[21];
|
||||
|
||||
public:
|
||||
static int CalculateBlipAlpha(float dist);
|
||||
static void ChangeBlipBrightness(int32 i, int32 bright);
|
||||
static void ChangeBlipColour(int32 i);
|
||||
static void ChangeBlipDisplay(int32 i, int16 flag);
|
||||
static void ChangeBlipScale(int32 i, int16 scale);
|
||||
static void ClearBlip(int32 i);
|
||||
static void ClearBlipForEntity(int16 type, int32 id);
|
||||
static int ClipRadarPoly(CVector2D *out, const CVector2D *in);
|
||||
static bool DisplayThisBlip(int32 i);
|
||||
static void Draw3dMarkers();
|
||||
static void DrawBlips();
|
||||
static void DrawMap();
|
||||
static void DrawRadarMap();
|
||||
static void DrawRadarMask();
|
||||
static void DrawRadarSection(int32 x, int32 y);
|
||||
static void DrawRadarSprite(int32 sprite, float x, float y, int32 alpha);
|
||||
static void DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha);
|
||||
static int32 GetActualBlipArray(int32 i);
|
||||
static int32 GetNewUniqueBlipIndex(int32 i);
|
||||
static int32 GetRadarTraceColour(int32 color, bool bright);
|
||||
static void Initialise();
|
||||
static float LimitRadarPoint(CVector2D &point);
|
||||
static void LoadAllRadarBlips(int32);
|
||||
static void LoadTextures();
|
||||
static void RemoveRadarSections();
|
||||
static void RemoveMapSection(int32 x, int32 y);
|
||||
static void RequestMapSection(int32 x, int32 y);
|
||||
static void SaveAllRadarBlips(int32);
|
||||
static void SetBlipSprite(int32 i, int32 icon);
|
||||
static int SetCoordBlip(int32 type, CVector pos, int32 flag);
|
||||
static int SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag);
|
||||
static void SetRadarMarkerState(int32 i, int32 flag);
|
||||
static void ShowRadarMarker(CVector pos, int16 color, float radius);
|
||||
static void ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha);
|
||||
static void Shutdown();
|
||||
static void StreamRadarSections(const CVector &posn);
|
||||
static void StreamRadarSections(int32 x, int32 y);
|
||||
static void TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y);
|
||||
static void TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in);
|
||||
static void TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in);
|
||||
static void TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in);
|
||||
|
||||
// no in CRadar in the game:
|
||||
static void GetTextureCorners(int32 x, int32 y, CVector2D *out);
|
||||
static void ClipRadarTileCoords(int32 &x, int32 &y);
|
||||
static bool IsPointInsideRadar(const CVector2D &);
|
||||
static int LineRadarBoxCollision(CVector2D &, const CVector2D &, const CVector2D &);
|
||||
};
|
||||
65
src/core/References.cpp
Normal file
65
src/core/References.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "World.h"
|
||||
#include "Vehicle.h"
|
||||
#include "PlayerPed.h"
|
||||
#include "Pools.h"
|
||||
#include "References.h"
|
||||
|
||||
CReference *CReferences::aRefs = (CReference*)0x70BBE0; //[NUMREFERENCES];
|
||||
CReference *&CReferences::pEmptyList = *(CReference**)0x8F1AF8;
|
||||
|
||||
void
|
||||
CReferences::Init(void)
|
||||
{
|
||||
int i;
|
||||
pEmptyList = &aRefs[0];
|
||||
for(i = 0; i < NUMREFERENCES; i++){
|
||||
aRefs[i].pentity = nil;
|
||||
aRefs[i].next = &aRefs[i+1];
|
||||
}
|
||||
aRefs[NUMREFERENCES-1].next = nil;
|
||||
}
|
||||
|
||||
void
|
||||
CReferences::RemoveReferencesToPlayer(void)
|
||||
{
|
||||
if(FindPlayerVehicle())
|
||||
FindPlayerVehicle()->ResolveReferences();
|
||||
if(FindPlayerPed())
|
||||
FindPlayerPed()->ResolveReferences();
|
||||
}
|
||||
|
||||
void
|
||||
CReferences::PruneAllReferencesInWorld(void)
|
||||
{
|
||||
int i;
|
||||
CEntity *e;
|
||||
|
||||
i = CPools::GetPedPool()->GetSize();
|
||||
while(--i >= 0){
|
||||
e = CPools::GetPedPool()->GetSlot(i);
|
||||
if(e)
|
||||
e->PruneReferences();
|
||||
}
|
||||
|
||||
i = CPools::GetVehiclePool()->GetSize();
|
||||
while(--i >= 0){
|
||||
e = CPools::GetVehiclePool()->GetSlot(i);
|
||||
if(e)
|
||||
e->PruneReferences();
|
||||
}
|
||||
|
||||
i = CPools::GetObjectPool()->GetSize();
|
||||
while(--i >= 0){
|
||||
e = CPools::GetObjectPool()->GetSlot(i);
|
||||
if(e)
|
||||
e->PruneReferences();
|
||||
}
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4A7350, CReferences::Init, PATCH_JUMP);
|
||||
InjectHook(0x4A7570, CReferences::RemoveReferencesToPlayer, PATCH_JUMP);
|
||||
InjectHook(0x4A75A0, CReferences::PruneAllReferencesInWorld, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
20
src/core/References.h
Normal file
20
src/core/References.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
class CEntity;
|
||||
|
||||
struct CReference
|
||||
{
|
||||
CReference *next;
|
||||
CEntity **pentity;
|
||||
};
|
||||
|
||||
class CReferences
|
||||
{
|
||||
public:
|
||||
static CReference *aRefs; //[NUMREFERENCES];
|
||||
static CReference *&pEmptyList;
|
||||
|
||||
static void Init(void);
|
||||
static void RemoveReferencesToPlayer(void);
|
||||
static void PruneAllReferencesInWorld(void);
|
||||
};
|
||||
230
src/core/RwClumpRead.cpp
Normal file
230
src/core/RwClumpRead.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
|
||||
struct rpGeometryList
|
||||
{
|
||||
RpGeometry **geometries;
|
||||
int32 numGeoms;
|
||||
};
|
||||
|
||||
struct rpAtomicBinary
|
||||
{
|
||||
RwInt32 frameIndex;
|
||||
RwInt32 geomIndex;
|
||||
RwInt32 flags;
|
||||
RwInt32 unused;
|
||||
};
|
||||
|
||||
static int32 numberGeometrys;
|
||||
static int32 streamPosition;
|
||||
static rpGeometryList gGeomList;
|
||||
static rwFrameList gFrameList;
|
||||
static RpClumpChunkInfo gClumpInfo;
|
||||
|
||||
rpGeometryList*
|
||||
GeometryListStreamRead1(RwStream *stream, rpGeometryList *geomlist)
|
||||
{
|
||||
int i;
|
||||
RwUInt32 size, version;
|
||||
RwInt32 numGeoms;
|
||||
|
||||
numberGeometrys = 0;
|
||||
if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))
|
||||
return nil;
|
||||
assert(size == 4);
|
||||
if(RwStreamRead(stream, &numGeoms, 4) != 4)
|
||||
return nil;
|
||||
|
||||
numberGeometrys = numGeoms/2;
|
||||
geomlist->numGeoms = numGeoms;
|
||||
if(geomlist->numGeoms > 0){
|
||||
geomlist->geometries = (RpGeometry**)RwMalloc(geomlist->numGeoms * sizeof(RpGeometry*));
|
||||
if(geomlist->geometries == nil)
|
||||
return nil;
|
||||
memset(geomlist->geometries, 0, geomlist->numGeoms * sizeof(RpGeometry*));
|
||||
}else
|
||||
geomlist->geometries = nil;
|
||||
|
||||
for(i = 0; i < numberGeometrys; i++){
|
||||
if(!RwStreamFindChunk(stream, rwID_GEOMETRY, nil, &version))
|
||||
return nil;
|
||||
geomlist->geometries[i] = RpGeometryStreamRead(stream);
|
||||
if(geomlist->geometries[i] == nil)
|
||||
return nil;
|
||||
}
|
||||
|
||||
return geomlist;
|
||||
}
|
||||
|
||||
rpGeometryList*
|
||||
GeometryListStreamRead2(RwStream *stream, rpGeometryList *geomlist)
|
||||
{
|
||||
int i;
|
||||
RwUInt32 version;
|
||||
|
||||
for(i = numberGeometrys; i < geomlist->numGeoms; i++){
|
||||
if(!RwStreamFindChunk(stream, rwID_GEOMETRY, nil, &version))
|
||||
return nil;
|
||||
geomlist->geometries[i] = RpGeometryStreamRead(stream);
|
||||
if(geomlist->geometries[i] == nil)
|
||||
return nil;
|
||||
}
|
||||
|
||||
return geomlist;
|
||||
}
|
||||
|
||||
void
|
||||
GeometryListDeinitialize(rpGeometryList *geomlist)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < geomlist->numGeoms; i++)
|
||||
if(geomlist->geometries[i])
|
||||
RpGeometryDestroy(geomlist->geometries[i]);
|
||||
|
||||
if(geomlist->numGeoms){
|
||||
RwFree(geomlist->geometries);
|
||||
geomlist->numGeoms = 0;
|
||||
}
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
ClumpAtomicStreamRead(RwStream *stream, rwFrameList *frmList, rpGeometryList *geomList)
|
||||
{
|
||||
RwUInt32 size, version;
|
||||
rpAtomicBinary a;
|
||||
RpAtomic *atomic;
|
||||
|
||||
numberGeometrys = 0;
|
||||
if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))
|
||||
return nil;
|
||||
assert(size <= sizeof(rpAtomicBinary));
|
||||
if(RwStreamRead(stream, &a, size) != size)
|
||||
return nil;
|
||||
|
||||
atomic = RpAtomicCreate();
|
||||
if(atomic == nil)
|
||||
return nil;
|
||||
|
||||
RpAtomicSetFlags(atomic, a.flags);
|
||||
|
||||
if(frmList->numFrames){
|
||||
assert(a.frameIndex < frmList->numFrames);
|
||||
RpAtomicSetFrame(atomic, frmList->frames[a.frameIndex]);
|
||||
}
|
||||
|
||||
if(geomList->numGeoms){
|
||||
assert(a.geomIndex < geomList->numGeoms);
|
||||
RpAtomicSetGeometry(atomic, geomList->geometries[a.geomIndex], 0);
|
||||
}else{
|
||||
RpGeometry *geom;
|
||||
if(!RwStreamFindChunk(stream, rwID_GEOMETRY, nil, &version)){
|
||||
RpAtomicDestroy(atomic);
|
||||
return nil;
|
||||
}
|
||||
geom = RpGeometryStreamRead(stream);
|
||||
if(geom == nil){
|
||||
RpAtomicDestroy(atomic);
|
||||
return nil;
|
||||
}
|
||||
RpAtomicSetGeometry(atomic, geom, 0);
|
||||
RpGeometryDestroy(geom);
|
||||
}
|
||||
|
||||
return atomic;
|
||||
}
|
||||
|
||||
bool
|
||||
RpClumpGtaStreamRead1(RwStream *stream)
|
||||
{
|
||||
RwUInt32 size, version;
|
||||
|
||||
if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))
|
||||
return false;
|
||||
if(version >= 0x33000){
|
||||
assert(size == 12);
|
||||
if(RwStreamRead(stream, &gClumpInfo, 12) != 12)
|
||||
return false;
|
||||
}else{
|
||||
assert(size == 4);
|
||||
if(RwStreamRead(stream, &gClumpInfo, 4) != 4)
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!RwStreamFindChunk(stream, rwID_FRAMELIST, nil, &version))
|
||||
return false;
|
||||
if(_rwFrameListStreamRead(stream, &gFrameList) == nil)
|
||||
return false;
|
||||
|
||||
if(!RwStreamFindChunk(stream, rwID_GEOMETRYLIST, nil, &version)){
|
||||
rwFrameListDeinitialize(&gFrameList);
|
||||
return false;
|
||||
}
|
||||
if(GeometryListStreamRead1(stream, &gGeomList) == nil){
|
||||
rwFrameListDeinitialize(&gFrameList);
|
||||
return false;
|
||||
}
|
||||
streamPosition = stream->Type.memory.position;
|
||||
return true;
|
||||
}
|
||||
|
||||
RpClump*
|
||||
RpClumpGtaStreamRead2(RwStream *stream)
|
||||
{
|
||||
int i;
|
||||
RwUInt32 version;
|
||||
RpAtomic *atomic;
|
||||
RpClump *clump;
|
||||
|
||||
clump = RpClumpCreate();
|
||||
if(clump == nil)
|
||||
return nil;
|
||||
|
||||
RwStreamSkip(stream, streamPosition - stream->Type.memory.position);
|
||||
|
||||
if(GeometryListStreamRead2(stream, &gGeomList) == nil){
|
||||
GeometryListDeinitialize(&gGeomList);
|
||||
rwFrameListDeinitialize(&gFrameList);
|
||||
RpClumpDestroy(clump);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RpClumpSetFrame(clump, gFrameList.frames[0]);
|
||||
|
||||
for(i = 0; i < gClumpInfo.numAtomics; i++){
|
||||
if(!RwStreamFindChunk(stream, rwID_ATOMIC, nil, &version)){
|
||||
GeometryListDeinitialize(&gGeomList);
|
||||
rwFrameListDeinitialize(&gFrameList);
|
||||
RpClumpDestroy(clump);
|
||||
return nil;
|
||||
}
|
||||
|
||||
atomic = ClumpAtomicStreamRead(stream, &gFrameList, &gGeomList);
|
||||
if(atomic == nil){
|
||||
GeometryListDeinitialize(&gGeomList);
|
||||
rwFrameListDeinitialize(&gFrameList);
|
||||
RpClumpDestroy(clump);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RpClumpAddAtomic(clump, atomic);
|
||||
}
|
||||
|
||||
GeometryListDeinitialize(&gGeomList);
|
||||
rwFrameListDeinitialize(&gFrameList);
|
||||
return clump;
|
||||
}
|
||||
|
||||
void
|
||||
RpClumpGtaCancelStream(void)
|
||||
{
|
||||
GeometryListDeinitialize(&gGeomList);
|
||||
rwFrameListDeinitialize(&gFrameList);
|
||||
gFrameList.numFrames = 0;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x526060, RpClumpGtaStreamRead1, PATCH_JUMP);
|
||||
InjectHook(0x526180, RpClumpGtaStreamRead2, PATCH_JUMP);
|
||||
InjectHook(0x5262D0, RpClumpGtaCancelStream, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
356
src/core/RwHelper.cpp
Normal file
356
src/core/RwHelper.cpp
Normal file
@@ -0,0 +1,356 @@
|
||||
#define WITHD3D
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Timecycle.h"
|
||||
#include "skeleton.h"
|
||||
|
||||
void *
|
||||
RwMallocAlign(RwUInt32 size, RwUInt32 align)
|
||||
{
|
||||
void *mem = (void *)malloc(size + align);
|
||||
|
||||
ASSERT(mem != nil);
|
||||
|
||||
void *addr = (void *)((((RwUInt32)mem) + align) & ~(align - 1));
|
||||
|
||||
ASSERT(addr != nil);
|
||||
|
||||
*(((void **)addr) - 1) = mem;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void
|
||||
RwFreeAlign(void *mem)
|
||||
{
|
||||
ASSERT(mem != nil);
|
||||
|
||||
void *addr = *(((void **)mem) - 1);
|
||||
|
||||
ASSERT(addr != nil);
|
||||
|
||||
free(addr);
|
||||
}
|
||||
|
||||
void
|
||||
DefinedState(void)
|
||||
{
|
||||
RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSWRAP);
|
||||
RwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)TRUE);
|
||||
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
|
||||
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
|
||||
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);
|
||||
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);
|
||||
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
|
||||
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
|
||||
RwRenderStateSet(rwRENDERSTATEALPHAPRIMITIVEBUFFER, (void*)FALSE);
|
||||
RwRenderStateSet(rwRENDERSTATEBORDERCOLOR, (void*)RWRGBALONG(0, 0, 0, 255));
|
||||
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
|
||||
RwRenderStateSet(rwRENDERSTATEFOGCOLOR,
|
||||
(void*)RWRGBALONG(CTimeCycle::GetFogRed(), CTimeCycle::GetFogGreen(), CTimeCycle::GetFogBlue(), 255));
|
||||
RwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)rwFOGTYPELINEAR);
|
||||
RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
|
||||
|
||||
// D3D stuff
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAREF, 2);
|
||||
}
|
||||
|
||||
RwFrame*
|
||||
GetFirstFrameCallback(RwFrame *child, void *data)
|
||||
{
|
||||
*(RwFrame**)data = child;
|
||||
return nil;
|
||||
}
|
||||
|
||||
RwFrame*
|
||||
GetFirstChild(RwFrame *frame)
|
||||
{
|
||||
RwFrame *child;
|
||||
|
||||
child = nil;
|
||||
RwFrameForAllChildren(frame, GetFirstFrameCallback, &child);
|
||||
return child;
|
||||
}
|
||||
|
||||
RwObject*
|
||||
GetFirstObjectCallback(RwObject *object, void *data)
|
||||
{
|
||||
*(RwObject**)data = object;
|
||||
return nil;
|
||||
}
|
||||
|
||||
RwObject*
|
||||
GetFirstObject(RwFrame *frame)
|
||||
{
|
||||
RwObject *obj;
|
||||
|
||||
obj = nil;
|
||||
RwFrameForAllObjects(frame, GetFirstObjectCallback, &obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
GetFirstAtomicCallback(RpAtomic *atm, void *data)
|
||||
{
|
||||
*(RpAtomic**)data = atm;
|
||||
return nil;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
GetFirstAtomic(RpClump *clump)
|
||||
{
|
||||
RpAtomic *atm;
|
||||
|
||||
atm = nil;
|
||||
RpClumpForAllAtomics(clump, GetFirstAtomicCallback, &atm);
|
||||
return atm;
|
||||
}
|
||||
|
||||
RwTexture*
|
||||
GetFirstTextureCallback(RwTexture *tex, void *data)
|
||||
{
|
||||
*(RwTexture**)data = tex;
|
||||
return nil;
|
||||
}
|
||||
|
||||
RwTexture*
|
||||
GetFirstTexture(RwTexDictionary *txd)
|
||||
{
|
||||
RwTexture *tex;
|
||||
|
||||
tex = nil;
|
||||
RwTexDictionaryForAllTextures(txd, GetFirstTextureCallback, &tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
void
|
||||
CameraSize(RwCamera * camera, RwRect * rect,
|
||||
RwReal viewWindow, RwReal aspectRatio)
|
||||
{
|
||||
if (camera)
|
||||
{
|
||||
RwVideoMode videoMode;
|
||||
RwRect r;
|
||||
RwRect origSize = { 0, 0, 0, 0 }; // FIX just to make the compier happy
|
||||
RwV2d vw;
|
||||
|
||||
RwEngineGetVideoModeInfo(&videoMode,
|
||||
RwEngineGetCurrentVideoMode());
|
||||
|
||||
origSize.w = RwRasterGetWidth(RwCameraGetRaster(camera));
|
||||
origSize.h = RwRasterGetHeight(RwCameraGetRaster(camera));
|
||||
|
||||
if (!rect)
|
||||
{
|
||||
if (videoMode.flags & rwVIDEOMODEEXCLUSIVE)
|
||||
{
|
||||
/* For full screen applications, resizing the camera just doesn't
|
||||
* make sense, use the video mode size.
|
||||
*/
|
||||
|
||||
r.x = r.y = 0;
|
||||
r.w = videoMode.width;
|
||||
r.h = videoMode.height;
|
||||
rect = &r;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
rect not specified - reuse current values
|
||||
*/
|
||||
r.w = RwRasterGetWidth(RwCameraGetRaster(camera));
|
||||
r.h = RwRasterGetHeight(RwCameraGetRaster(camera));
|
||||
r.x = r.y = 0;
|
||||
rect = &r;
|
||||
}
|
||||
}
|
||||
|
||||
if (( origSize.w != rect->w ) && ( origSize.h != rect->h ))
|
||||
{
|
||||
RwRaster *raster;
|
||||
RwRaster *zRaster;
|
||||
|
||||
/*
|
||||
* Destroy rasters...
|
||||
*/
|
||||
|
||||
raster = RwCameraGetRaster(camera);
|
||||
if( raster )
|
||||
{
|
||||
RwRasterDestroy(raster);
|
||||
}
|
||||
|
||||
zRaster = RwCameraGetZRaster(camera);
|
||||
if( zRaster )
|
||||
{
|
||||
RwRasterDestroy(zRaster);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create new rasters...
|
||||
*/
|
||||
|
||||
raster = RwRasterCreate(rect->w, rect->h, 0, rwRASTERTYPECAMERA);
|
||||
zRaster = RwRasterCreate(rect->w, rect->h, 0, rwRASTERTYPEZBUFFER);
|
||||
|
||||
if( raster && zRaster )
|
||||
{
|
||||
RwCameraSetRaster(camera, raster);
|
||||
RwCameraSetZRaster(camera, zRaster);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( raster )
|
||||
{
|
||||
RwRasterDestroy(raster);
|
||||
}
|
||||
|
||||
if( zRaster )
|
||||
{
|
||||
RwRasterDestroy(zRaster);
|
||||
}
|
||||
|
||||
rect->x = origSize.x;
|
||||
rect->y = origSize.y;
|
||||
rect->w = origSize.w;
|
||||
rect->h = origSize.h;
|
||||
|
||||
/*
|
||||
* Use default values...
|
||||
*/
|
||||
raster =
|
||||
RwRasterCreate(rect->w, rect->h, 0, rwRASTERTYPECAMERA);
|
||||
|
||||
zRaster =
|
||||
RwRasterCreate(rect->w, rect->h, 0, rwRASTERTYPEZBUFFER);
|
||||
|
||||
RwCameraSetRaster(camera, raster);
|
||||
RwCameraSetZRaster(camera, zRaster);
|
||||
}
|
||||
}
|
||||
|
||||
/* Figure out the view window */
|
||||
if (videoMode.flags & rwVIDEOMODEEXCLUSIVE)
|
||||
{
|
||||
/* derive ratio from aspect ratio */
|
||||
vw.x = viewWindow;
|
||||
vw.y = viewWindow / aspectRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* derive from pixel ratios */
|
||||
if (rect->w > rect->h)
|
||||
{
|
||||
vw.x = viewWindow;
|
||||
vw.y = (rect->h * viewWindow) / rect->w;
|
||||
}
|
||||
else
|
||||
{
|
||||
vw.x = (rect->w * viewWindow) / rect->h;
|
||||
vw.y = viewWindow;
|
||||
}
|
||||
}
|
||||
|
||||
RwCameraSetViewWindow(camera, &vw);
|
||||
|
||||
RsGlobal.width = rect->w;
|
||||
RsGlobal.height = rect->h;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
CameraDestroy(RwCamera *camera)
|
||||
{
|
||||
RwRaster *raster, *tmpRaster;
|
||||
RwFrame *frame;
|
||||
|
||||
if (camera)
|
||||
{
|
||||
frame = RwCameraGetFrame(camera);
|
||||
if (frame)
|
||||
{
|
||||
RwFrameDestroy(frame);
|
||||
}
|
||||
|
||||
raster = RwCameraGetRaster(camera);
|
||||
if (raster)
|
||||
{
|
||||
tmpRaster = RwRasterGetParent(raster);
|
||||
|
||||
RwRasterDestroy(raster);
|
||||
|
||||
if ((tmpRaster != nil) && (tmpRaster != raster))
|
||||
{
|
||||
RwRasterDestroy(tmpRaster);
|
||||
}
|
||||
}
|
||||
|
||||
raster = RwCameraGetZRaster(camera);
|
||||
if (raster)
|
||||
{
|
||||
tmpRaster = RwRasterGetParent(raster);
|
||||
|
||||
RwRasterDestroy(raster);
|
||||
|
||||
if ((tmpRaster != nil) && (tmpRaster != raster))
|
||||
{
|
||||
RwRasterDestroy(tmpRaster);
|
||||
}
|
||||
}
|
||||
|
||||
RwCameraDestroy(camera);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
RwCamera *
|
||||
CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer)
|
||||
{
|
||||
RwCamera *camera;
|
||||
|
||||
camera = RwCameraCreate();
|
||||
|
||||
if (camera)
|
||||
{
|
||||
RwCameraSetFrame(camera, RwFrameCreate());
|
||||
RwCameraSetRaster(camera,
|
||||
RwRasterCreate(0, 0, 0, rwRASTERTYPECAMERA));
|
||||
|
||||
if (zBuffer)
|
||||
{
|
||||
RwCameraSetZRaster(camera,
|
||||
RwRasterCreate(0, 0, 0,
|
||||
rwRASTERTYPEZBUFFER));
|
||||
}
|
||||
|
||||
/* now check that everything is valid */
|
||||
if (RwCameraGetFrame(camera) &&
|
||||
RwCameraGetRaster(camera) &&
|
||||
RwRasterGetParent(RwCameraGetRaster(camera)) &&
|
||||
(!zBuffer || (RwCameraGetZRaster(camera) &&
|
||||
RwRasterGetParent(RwCameraGetZRaster
|
||||
(camera)))))
|
||||
{
|
||||
/* everything OK */
|
||||
return (camera);
|
||||
}
|
||||
}
|
||||
|
||||
/* if we're here then an error must have occurred so clean up */
|
||||
|
||||
CameraDestroy(camera);
|
||||
return (nil);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
//InjectHook(0x526450, GetFirstObjectCallback, PATCH_JUMP);
|
||||
InjectHook(0x526460, GetFirstObject, PATCH_JUMP);
|
||||
InjectHook(0x527170, CameraSize, PATCH_JUMP);
|
||||
InjectHook(0x527340, CameraDestroy, PATCH_JUMP);
|
||||
InjectHook(0x5273B0, CameraCreate, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
27
src/core/RwHelper.h
Normal file
27
src/core/RwHelper.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
void *RwMallocAlign(RwUInt32 size, RwUInt32 align);
|
||||
void RwFreeAlign(void *mem);
|
||||
|
||||
void DefinedState(void);
|
||||
RwFrame *GetFirstChild(RwFrame *frame);
|
||||
RwObject *GetFirstObject(RwFrame *frame);
|
||||
RpAtomic *GetFirstAtomic(RpClump *clump);
|
||||
RwTexture *GetFirstTexture(RwTexDictionary *txd);
|
||||
|
||||
RwTexDictionary *RwTexDictionaryGtaStreamRead(RwStream *stream);
|
||||
RwTexDictionary *RwTexDictionaryGtaStreamRead1(RwStream *stream);
|
||||
RwTexDictionary *RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict);
|
||||
|
||||
bool RpClumpGtaStreamRead1(RwStream *stream);
|
||||
RpClump *RpClumpGtaStreamRead2(RwStream *stream);
|
||||
void RpClumpGtaCancelStream(void);
|
||||
|
||||
void CameraSize(RwCamera *camera,
|
||||
RwRect *rect,
|
||||
RwReal viewWindow,
|
||||
RwReal aspectRatio);
|
||||
void CameraDestroy(RwCamera *camera);
|
||||
RwCamera *CameraCreate(RwInt32 width,
|
||||
RwInt32 height,
|
||||
RwBool zBuffer);
|
||||
212
src/core/RwMatFX.cpp
Normal file
212
src/core/RwMatFX.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
#define WITHD3D
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
|
||||
struct MatFXNothing { int pad[5]; int effect; };
|
||||
|
||||
struct MatFXBump
|
||||
{
|
||||
RwFrame *bumpFrame;
|
||||
RwTexture *bumpedTex;
|
||||
RwTexture *bumpTex;
|
||||
float negBumpCoefficient;
|
||||
int pad;
|
||||
int effect;
|
||||
};
|
||||
|
||||
struct MatFXEnv
|
||||
{
|
||||
RwFrame *envFrame;
|
||||
RwTexture *envTex;
|
||||
float envCoeff;
|
||||
int envFBalpha;
|
||||
int pad;
|
||||
int effect;
|
||||
};
|
||||
|
||||
struct MatFXDual
|
||||
{
|
||||
RwTexture *dualTex;
|
||||
RwInt32 srcBlend;
|
||||
RwInt32 dstBlend;
|
||||
};
|
||||
|
||||
|
||||
struct MatFX
|
||||
{
|
||||
union {
|
||||
MatFXNothing n;
|
||||
MatFXBump b;
|
||||
MatFXEnv e;
|
||||
MatFXDual d;
|
||||
} fx[2];
|
||||
int effects;
|
||||
};
|
||||
|
||||
int &MatFXMaterialDataOffset = *(int*)0x66188C;
|
||||
int &MatFXAtomicDataOffset = *(int*)0x66189C;
|
||||
|
||||
#ifdef PS2_MATFX
|
||||
|
||||
void
|
||||
_rpMatFXD3D8AtomicMatFXDefaultRender(RxD3D8InstanceData *inst, int flags, RwTexture *texture)
|
||||
{
|
||||
if(flags & (rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2) && texture)
|
||||
RwD3D8SetTexture(texture, 0);
|
||||
else
|
||||
RwD3D8SetTexture(nil, 0);
|
||||
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(inst->vertexAlpha || inst->material->color.alpha != 0xFF));
|
||||
RwD3D8SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, inst->vertexAlpha != 0);
|
||||
RwD3D8SetPixelShader(0);
|
||||
RwD3D8SetVertexShader(inst->vertexShader);
|
||||
RwD3D8SetStreamSource(0, inst->vertexBuffer, inst->stride);
|
||||
|
||||
if(inst->indexBuffer){
|
||||
RwD3D8SetIndices(inst->indexBuffer, inst->baseIndex);
|
||||
RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);
|
||||
}else
|
||||
RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);
|
||||
}
|
||||
|
||||
// map [-1; -1] -> [0; 1], flip V
|
||||
static RwMatrix scalenormal = {
|
||||
{ 0.5f, 0.0f, 0.0f }, 0,
|
||||
{ 0.0f, -0.5f, 0.0f }, 0,
|
||||
{ 0.0f, 0.0f, 1.0f }, 0,
|
||||
{ 0.5f, 0.5f, 0.0f }, 0,
|
||||
|
||||
};
|
||||
|
||||
// flipped U for PS2
|
||||
static RwMatrix scalenormal_flipU = {
|
||||
{ -0.5f, 0.0f, 0.0f }, 0,
|
||||
{ 0.0f, -0.5f, 0.0f }, 0,
|
||||
{ 0.0f, 0.0f, 1.0f }, 0,
|
||||
{ 0.5f, 0.5f, 0.0f }, 0,
|
||||
|
||||
};
|
||||
|
||||
void
|
||||
ApplyEnvMapTextureMatrix(RwTexture *tex, int n, RwFrame *frame)
|
||||
{
|
||||
RwD3D8SetTexture(tex, n);
|
||||
RwD3D8SetTextureStageState(n, D3DRS_ALPHAREF, 2);
|
||||
RwD3D8SetTextureStageState(n, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL);
|
||||
if(frame){
|
||||
RwMatrix *envframemat = RwMatrixCreate();
|
||||
RwMatrix *tmpmat = RwMatrixCreate();
|
||||
RwMatrix *envmat = RwMatrixCreate();
|
||||
|
||||
RwMatrixInvert(envframemat, RwFrameGetLTM(frame));
|
||||
// PS2
|
||||
// can this be simplified?
|
||||
*tmpmat = *RwFrameGetLTM(RwCameraGetFrame((RwCamera*)RWSRCGLOBAL(curCamera)));
|
||||
RwV3dNegate(&tmpmat->right, &tmpmat->right);
|
||||
tmpmat->flags = 0;
|
||||
tmpmat->pos.x = 0.0f;
|
||||
tmpmat->pos.y = 0.0f;
|
||||
tmpmat->pos.z = 0.0f;
|
||||
RwMatrixMultiply(envmat, tmpmat, envframemat);
|
||||
*tmpmat = *envmat;
|
||||
// important because envframemat can have a translation that we don't like
|
||||
tmpmat->pos.x = 0.0f;
|
||||
tmpmat->pos.y = 0.0f;
|
||||
tmpmat->pos.z = 0.0f;
|
||||
// for some reason we flip in U as well
|
||||
RwMatrixMultiply(envmat, tmpmat, &scalenormal_flipU);
|
||||
|
||||
RwD3D8SetTransform(D3DTS_TEXTURE0+n, envmat);
|
||||
|
||||
RwMatrixDestroy(envmat);
|
||||
RwMatrixDestroy(tmpmat);
|
||||
RwMatrixDestroy(envframemat);
|
||||
}else
|
||||
RwD3D8SetTransform(D3DTS_TEXTURE0+n, &scalenormal);
|
||||
}
|
||||
|
||||
void
|
||||
_rpMatFXD3D8AtomicMatFXEnvRender_ps2(RxD3D8InstanceData *inst, int flags, int sel, RwTexture *texture, RwTexture *envMap)
|
||||
{
|
||||
MatFX *matfx = *RWPLUGINOFFSET(MatFX*, inst->material, MatFXMaterialDataOffset);
|
||||
MatFXEnv *env = &matfx->fx[sel].e;
|
||||
|
||||
uint8 intens = (uint8)(env->envCoeff*255.0f);
|
||||
|
||||
if(intens == 0 || envMap == nil){
|
||||
if(sel == 0)
|
||||
_rpMatFXD3D8AtomicMatFXDefaultRender(inst, flags, texture);
|
||||
return;
|
||||
}
|
||||
|
||||
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(inst->vertexAlpha || inst->material->color.alpha != 0xFF));
|
||||
if(flags & (rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2) && texture)
|
||||
RwD3D8SetTexture(texture, 0);
|
||||
else
|
||||
RwD3D8SetTexture(nil, 0);
|
||||
RwD3D8SetVertexShader(inst->vertexShader);
|
||||
RwD3D8SetStreamSource(0, inst->vertexBuffer, inst->stride);
|
||||
RwD3D8SetIndices(inst->indexBuffer, inst->baseIndex);
|
||||
if(inst->indexBuffer)
|
||||
RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);
|
||||
else
|
||||
RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);
|
||||
|
||||
// Effect pass
|
||||
|
||||
ApplyEnvMapTextureMatrix(envMap, 0, env->envFrame);
|
||||
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
|
||||
RwUInt32 src, dst, lighting, zwrite, fog, fogcol;
|
||||
RwRenderStateGet(rwRENDERSTATESRCBLEND, &src);
|
||||
RwRenderStateGet(rwRENDERSTATEDESTBLEND, &dst);
|
||||
|
||||
// This is of course not using framebuffer alpha,
|
||||
// but if the diffuse texture had no alpha, the result should actually be rather the same
|
||||
if(env->envFBalpha)
|
||||
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
|
||||
else
|
||||
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
|
||||
RwD3D8GetRenderState(D3DRS_LIGHTING, &lighting);
|
||||
RwD3D8GetRenderState(D3DRS_ZWRITEENABLE, &zwrite);
|
||||
RwD3D8GetRenderState(D3DRS_FOGENABLE, &fog);
|
||||
RwD3D8SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
if(fog){
|
||||
RwD3D8GetRenderState(D3DRS_FOGCOLOR, &fogcol);
|
||||
RwD3D8SetRenderState(D3DRS_FOGCOLOR, 0);
|
||||
}
|
||||
|
||||
D3DCOLOR texfactor = D3DCOLOR_RGBA(intens, intens, intens, intens);
|
||||
RwD3D8SetRenderState(D3DRS_TEXTUREFACTOR, texfactor);
|
||||
RwD3D8SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
RwD3D8SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
|
||||
RwD3D8SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TFACTOR);
|
||||
// alpha unused
|
||||
//RwD3D8SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
//RwD3D8SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
|
||||
//RwD3D8SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
|
||||
|
||||
if(inst->indexBuffer)
|
||||
RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);
|
||||
else
|
||||
RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);
|
||||
|
||||
// Reset states
|
||||
|
||||
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
|
||||
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)src);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)dst);
|
||||
RwD3D8SetRenderState(D3DRS_LIGHTING, lighting);
|
||||
RwD3D8SetRenderState(D3DRS_ZWRITEENABLE, zwrite);
|
||||
if(fog)
|
||||
RwD3D8SetRenderState(D3DRS_FOGCOLOR, fogcol);
|
||||
RwD3D8SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
RwD3D8SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, 0);
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x5CF6C0, _rpMatFXD3D8AtomicMatFXEnvRender_ps2, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
||||
#endif
|
||||
126
src/core/RwTexRead.cpp
Normal file
126
src/core/RwTexRead.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
|
||||
RwTexture*
|
||||
RwTextureGtaStreamRead(RwStream *stream)
|
||||
{
|
||||
RwUInt32 size, version;
|
||||
RwTexture *tex;
|
||||
|
||||
if(!RwStreamFindChunk(stream, rwID_TEXTURENATIVE, &size, &version))
|
||||
return nil;
|
||||
|
||||
// TODO: unused timing
|
||||
|
||||
if(!RWSRCGLOBAL(stdFunc[rwSTANDARDNATIVETEXTUREREAD](stream, &tex, size)))
|
||||
return nil;
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
RwTexture*
|
||||
destroyTexture(RwTexture *texture, void *data)
|
||||
{
|
||||
RwTextureDestroy(texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
RwTexDictionary*
|
||||
RwTexDictionaryGtaStreamRead(RwStream *stream)
|
||||
{
|
||||
RwUInt32 size, version;
|
||||
RwInt32 numTextures;
|
||||
RwTexDictionary *texDict;
|
||||
RwTexture *tex;
|
||||
|
||||
if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))
|
||||
return nil;
|
||||
assert(size == 4);
|
||||
if(RwStreamRead(stream, &numTextures, size) != size)
|
||||
return nil;
|
||||
|
||||
texDict = RwTexDictionaryCreate();
|
||||
if(texDict == nil)
|
||||
return nil;
|
||||
|
||||
while(numTextures--){
|
||||
tex = RwTextureGtaStreamRead(stream);
|
||||
if(tex == nil){
|
||||
RwTexDictionaryForAllTextures(texDict, destroyTexture, nil);
|
||||
RwTexDictionaryDestroy(texDict);
|
||||
return nil;
|
||||
}
|
||||
RwTexDictionaryAddTexture(texDict, tex);
|
||||
}
|
||||
|
||||
return texDict;
|
||||
}
|
||||
|
||||
static int32 numberTextures = -1;
|
||||
static int32 streamPosition;
|
||||
|
||||
RwTexDictionary*
|
||||
RwTexDictionaryGtaStreamRead1(RwStream *stream)
|
||||
{
|
||||
RwUInt32 size, version;
|
||||
RwInt32 numTextures;
|
||||
RwTexDictionary *texDict;
|
||||
RwTexture *tex;
|
||||
|
||||
numberTextures = 0;
|
||||
if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))
|
||||
return nil;
|
||||
assert(size == 4);
|
||||
if(RwStreamRead(stream, &numTextures, size) != size)
|
||||
return nil;
|
||||
|
||||
texDict = RwTexDictionaryCreate();
|
||||
if(texDict == nil)
|
||||
return nil;
|
||||
|
||||
numberTextures = numTextures/2;
|
||||
|
||||
while(numTextures > numberTextures){
|
||||
numTextures--;
|
||||
|
||||
tex = RwTextureGtaStreamRead(stream);
|
||||
if(tex == nil){
|
||||
RwTexDictionaryForAllTextures(texDict, destroyTexture, nil);
|
||||
RwTexDictionaryDestroy(texDict);
|
||||
return nil;
|
||||
}
|
||||
RwTexDictionaryAddTexture(texDict, tex);
|
||||
}
|
||||
|
||||
numberTextures = numTextures;
|
||||
streamPosition = stream->Type.memory.position;
|
||||
|
||||
return texDict;
|
||||
}
|
||||
|
||||
RwTexDictionary*
|
||||
RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict)
|
||||
{
|
||||
RwTexture *tex;
|
||||
|
||||
RwStreamSkip(stream, streamPosition - stream->Type.memory.position);
|
||||
|
||||
while(numberTextures--){
|
||||
tex = RwTextureGtaStreamRead(stream);
|
||||
if(tex == nil){
|
||||
RwTexDictionaryForAllTextures(texDict, destroyTexture, nil);
|
||||
RwTexDictionaryDestroy(texDict);
|
||||
return nil;
|
||||
}
|
||||
RwTexDictionaryAddTexture(texDict, tex);
|
||||
}
|
||||
|
||||
return texDict;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x592380, RwTextureGtaStreamRead, PATCH_JUMP);
|
||||
InjectHook(0x5924A0, RwTexDictionaryGtaStreamRead, PATCH_JUMP);
|
||||
InjectHook(0x592550, RwTexDictionaryGtaStreamRead1, PATCH_JUMP);
|
||||
InjectHook(0x592650, RwTexDictionaryGtaStreamRead2, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
13
src/core/Stats.cpp
Normal file
13
src/core/Stats.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "common.h"
|
||||
#include "Stats.h"
|
||||
|
||||
int32 &CStats::DaysPassed = *(int32*)0x8F2BB8;
|
||||
int32 &CStats::HeadShots = *(int32*)0x8F647C;
|
||||
bool& CStats::CommercialPassed = *(bool*)0x8F4334;
|
||||
int32 &CStats::NumberKillFrenziesPassed = *(int32*)0x8E287C;
|
||||
int32 &CStats::PeopleKilledByOthers = *(int32*)0x8E2C50;
|
||||
|
||||
void CStats::AnotherKillFrenzyPassed()
|
||||
{
|
||||
++NumberKillFrenziesPassed;
|
||||
}
|
||||
14
src/core/Stats.h
Normal file
14
src/core/Stats.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
class CStats
|
||||
{
|
||||
public:
|
||||
static int32 &DaysPassed;
|
||||
static int32 &HeadShots;
|
||||
static bool& CommercialPassed;
|
||||
static int32 &NumberKillFrenziesPassed;
|
||||
static int32 &PeopleKilledByOthers;
|
||||
|
||||
public:
|
||||
static void AnotherKillFrenzyPassed();
|
||||
};
|
||||
2509
src/core/Streaming.cpp
Normal file
2509
src/core/Streaming.cpp
Normal file
File diff suppressed because it is too large
Load Diff
188
src/core/Streaming.h
Normal file
188
src/core/Streaming.h
Normal file
@@ -0,0 +1,188 @@
|
||||
#pragma once
|
||||
|
||||
#include "Game.h"
|
||||
|
||||
enum {
|
||||
STREAM_OFFSET_MODEL = 0,
|
||||
STREAM_OFFSET_TXD = STREAM_OFFSET_MODEL+MODELINFOSIZE,
|
||||
NUMSTREAMINFO = STREAM_OFFSET_TXD+TXDSTORESIZE
|
||||
};
|
||||
|
||||
enum StreamFlags
|
||||
{
|
||||
STREAMFLAGS_DONT_REMOVE = 0x01,
|
||||
STREAMFLAGS_SCRIPTOWNED = 0x02,
|
||||
STREAMFLAGS_DEPENDENCY = 0x04, // Is this right?
|
||||
STREAMFLAGS_PRIORITY = 0x08,
|
||||
STREAMFLAGS_NOFADE = 0x10,
|
||||
|
||||
// TODO: this isn't named well, maybe CANT_REMOVE?
|
||||
STREAMFLAGS_NOT_IN_LIST = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED,
|
||||
STREAMFLAGS_KEEP_IN_MEMORY = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED|STREAMFLAGS_DEPENDENCY,
|
||||
};
|
||||
|
||||
enum StreamLoadState
|
||||
{
|
||||
STREAMSTATE_NOTLOADED = 0,
|
||||
STREAMSTATE_LOADED = 1,
|
||||
STREAMSTATE_INQUEUE = 2,
|
||||
STREAMSTATE_READING = 3, // channel is reading
|
||||
STREAMSTATE_STARTED = 4, // first part loaded
|
||||
};
|
||||
|
||||
enum ChannelState
|
||||
{
|
||||
CHANNELSTATE_IDLE = 0,
|
||||
CHANNELSTATE_READING = 1,
|
||||
CHANNELSTATE_STARTED = 2,
|
||||
CHANNELSTATE_ERROR = 3,
|
||||
};
|
||||
|
||||
class CStreamingInfo
|
||||
{
|
||||
public:
|
||||
CStreamingInfo *m_next;
|
||||
CStreamingInfo *m_prev;
|
||||
uint8 m_loadState;
|
||||
uint8 m_flags;
|
||||
|
||||
int16 m_nextID;
|
||||
uint32 m_position;
|
||||
uint32 m_size;
|
||||
|
||||
bool GetCdPosnAndSize(uint32 &posn, uint32 &size);
|
||||
void SetCdPosnAndSize(uint32 posn, uint32 size);
|
||||
void AddToList(CStreamingInfo *link);
|
||||
void RemoveFromList(void);
|
||||
uint32 GetCdSize(void) { return m_size; }
|
||||
bool IsPriority(void) { return !!(m_flags & STREAMFLAGS_PRIORITY); }
|
||||
};
|
||||
|
||||
struct CStreamingChannel
|
||||
{
|
||||
int32 streamIds[4];
|
||||
int32 offsets[4];
|
||||
int32 state;
|
||||
int32 field24;
|
||||
int32 position;
|
||||
int32 size;
|
||||
int32 numTries;
|
||||
int32 status; // from CdStream
|
||||
};
|
||||
|
||||
class CDirectory;
|
||||
enum eLevelName;
|
||||
class CPtrList;
|
||||
|
||||
class CStreaming
|
||||
{
|
||||
public:
|
||||
static bool &ms_disableStreaming;
|
||||
static bool &ms_bLoadingBigModel;
|
||||
static int32 &ms_numModelsRequested;
|
||||
static CStreamingInfo *ms_aInfoForModel; //[NUMSTREAMINFO]
|
||||
static CStreamingInfo &ms_startLoadedList;
|
||||
static CStreamingInfo &ms_endLoadedList;
|
||||
static CStreamingInfo &ms_startRequestedList;
|
||||
static CStreamingInfo &ms_endRequestedList;
|
||||
static int32 &ms_oldSectorX;
|
||||
static int32 &ms_oldSectorY;
|
||||
static int32 &ms_streamingBufferSize;
|
||||
static int8 **ms_pStreamingBuffer; //[2]
|
||||
static int32 &ms_memoryUsed;
|
||||
static CStreamingChannel *ms_channel; //[2]
|
||||
static int32 &ms_channelError;
|
||||
static int32 &ms_numVehiclesLoaded;
|
||||
static int32 *ms_vehiclesLoaded; //[MAXVEHICLESLOADED]
|
||||
static int32 &ms_lastVehicleDeleted;
|
||||
static CDirectory *&ms_pExtraObjectsDir;
|
||||
static int32 &ms_numPriorityRequests;
|
||||
static bool &ms_hasLoadedLODs;
|
||||
static int32 &ms_currentPedGrp;
|
||||
static int32 ms_lastCullZone;
|
||||
static uint16 &ms_loadedGangs;
|
||||
static uint16 &ms_loadedGangCars;
|
||||
static int32 ms_currentPedLoading;
|
||||
static int32 *ms_imageOffsets; //[NUMCDIMAGES]
|
||||
static int32 &ms_lastImageRead;
|
||||
static int32 &ms_imageSize;
|
||||
static uint32 &ms_memoryAvailable;
|
||||
|
||||
static void Init(void);
|
||||
static void Shutdown(void);
|
||||
static void Update(void);
|
||||
static void LoadCdDirectory(void);
|
||||
static void LoadCdDirectory(const char *dirname, int32 n);
|
||||
static bool ConvertBufferToObject(int8 *buf, int32 streamId);
|
||||
static bool FinishLoadingLargeFile(int8 *buf, int32 streamId);
|
||||
static bool HasModelLoaded(int32 id) { return ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED; }
|
||||
static void RequestModel(int32 model, int32 flags);
|
||||
static void ReRequestModel(int32 model) { RequestModel(model, ms_aInfoForModel[model].m_flags); }
|
||||
static void RequestTxd(int32 txd, int32 flags) { RequestModel(txd + STREAM_OFFSET_TXD, flags); }
|
||||
static void ReRequestTxd(int32 txd) { ReRequestModel(txd + STREAM_OFFSET_TXD); }
|
||||
static void RequestSubway(void);
|
||||
static void RequestBigBuildings(eLevelName level);
|
||||
static void RequestIslands(eLevelName level);
|
||||
static void RequestSpecialModel(int32 modelId, const char *modelName, int32 flags);
|
||||
static void RequestSpecialChar(int32 charId, const char *modelName, int32 flags);
|
||||
static bool HasSpecialCharLoaded(int32 id);
|
||||
static void SetMissionDoesntRequireSpecialChar(int32 id);
|
||||
static void DecrementRef(int32 id);
|
||||
static void RemoveModel(int32 id);
|
||||
static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); }
|
||||
static void RemoveUnusedBuildings(eLevelName level);
|
||||
static void RemoveBuildings(eLevelName level);
|
||||
static void RemoveUnusedBigBuildings(eLevelName level);
|
||||
static void RemoveIslandsNotUsed(eLevelName level);
|
||||
static void RemoveBigBuildings(eLevelName level);
|
||||
static bool RemoveLoadedVehicle(void);
|
||||
static bool RemoveLeastUsedModel(void);
|
||||
static void RemoveAllUnusedModels(void);
|
||||
static void RemoveUnusedModelsInLoadedList(void);
|
||||
static bool RemoveReferencedTxds(int32 mem);
|
||||
static int32 GetAvailableVehicleSlot(void);
|
||||
static bool IsTxdUsedByRequestedModels(int32 txdId);
|
||||
static bool AddToLoadedVehiclesList(int32 modelId);
|
||||
static bool IsObjectInCdImage(int32 id);
|
||||
static void HaveAllBigBuildingsLoaded(eLevelName level);
|
||||
static void SetModelIsDeletable(int32 id);
|
||||
static void SetModelTxdIsDeletable(int32 id);
|
||||
static void SetMissionDoesntRequireModel(int32 id);
|
||||
static void LoadInitialPeds(void);
|
||||
static void LoadInitialVehicles(void);
|
||||
static void StreamVehiclesAndPeds(void);
|
||||
static void StreamZoneModels(const CVector &pos);
|
||||
static void RemoveCurrentZonesModels(void);
|
||||
|
||||
static int32 GetCdImageOffset(int32 lastPosn);
|
||||
static int32 GetNextFileOnCd(int32 position, bool priority);
|
||||
static void RequestModelStream(int32 ch);
|
||||
static bool ProcessLoadingChannel(int32 ch);
|
||||
static void RetryLoadFile(int32 ch);
|
||||
static void LoadRequestedModels(void);
|
||||
static void LoadAllRequestedModels(bool priority);
|
||||
static void FlushChannels(void);
|
||||
static void FlushRequestList(void);
|
||||
|
||||
static void MakeSpaceFor(int32 size);
|
||||
static void ImGonnaUseStreamingMemory(void);
|
||||
static void IHaveUsedStreamingMemory(void);
|
||||
static void UpdateMemoryUsed(void);
|
||||
|
||||
static void AddModelsToRequestList(const CVector &pos);
|
||||
static void ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float xmin, float ymin, float xmax, float ymax);
|
||||
static void ProcessEntitiesInSectorList(CPtrList &list);
|
||||
static void DeleteFarAwayRwObjects(const CVector &pos);
|
||||
static void DeleteAllRwObjects(void);
|
||||
static void DeleteRwObjectsAfterDeath(const CVector &pos);
|
||||
static void DeleteRwObjectsBehindCamera(int32 mem);
|
||||
static void DeleteRwObjectsInSectorList(CPtrList &list);
|
||||
static void DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y);
|
||||
static bool DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, int32 mem);
|
||||
static bool DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, int32 mem);
|
||||
|
||||
static void LoadScene(const CVector &pos);
|
||||
|
||||
static void MemoryCardSave(uint8 *buffer, uint32 *length);
|
||||
static void MemoryCardLoad(uint8 *buffer, uint32 length);
|
||||
};
|
||||
150
src/core/SurfaceTable.cpp
Normal file
150
src/core/SurfaceTable.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "main.h"
|
||||
#include "FileMgr.h"
|
||||
#include "Weather.h"
|
||||
#include "Collision.h"
|
||||
#include "SurfaceTable.h"
|
||||
|
||||
float (*CSurfaceTable::ms_aAdhesiveLimitTable)[NUMADHESIVEGROUPS] = (float (*)[NUMADHESIVEGROUPS])0x8E29D4;
|
||||
|
||||
void
|
||||
CSurfaceTable::Initialise(char *filename)
|
||||
{
|
||||
int lineno, fieldno;
|
||||
char *line;
|
||||
char surfname[256];
|
||||
float adhesiveLimit;
|
||||
|
||||
CFileMgr::SetDir("");
|
||||
CFileMgr::LoadFile(filename, work_buff, sizeof(work_buff), "r");
|
||||
|
||||
line = (char*)work_buff;
|
||||
for(lineno = 0; lineno < NUMADHESIVEGROUPS; lineno++){
|
||||
// skip white space and comments
|
||||
while(*line == ' ' || *line == '\t' || *line == '\n' || *line == '\r' || *line == ';'){
|
||||
if(*line == ';'){
|
||||
while(*line != '\n' && *line != '\r')
|
||||
line++;
|
||||
}else
|
||||
line++;
|
||||
}
|
||||
|
||||
sscanf(line, "%s", surfname);
|
||||
// skip what we just read
|
||||
while(!(*line == ' ' || *line == '\t' || *line == ','))
|
||||
line++;
|
||||
|
||||
for(fieldno = 0; fieldno <= lineno; fieldno++){
|
||||
// skip white space
|
||||
while(*line == ' ' || *line == '\t' || *line == ',')
|
||||
line++;
|
||||
adhesiveLimit = 0.0f;
|
||||
if(*line != '-')
|
||||
sscanf(line, "%f", &adhesiveLimit);
|
||||
// skip what we just read
|
||||
while(!(*line == ' ' || *line == '\t' || *line == ',' || *line == '\n'))
|
||||
line++;
|
||||
|
||||
ms_aAdhesiveLimitTable[lineno][fieldno] = adhesiveLimit;
|
||||
ms_aAdhesiveLimitTable[fieldno][lineno] = adhesiveLimit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
CSurfaceTable::GetAdhesionGroup(uint8 surfaceType)
|
||||
{
|
||||
switch(surfaceType){
|
||||
case SURFACE_0: return ADHESIVE_ROAD;
|
||||
case SURFACE_1: return ADHESIVE_ROAD;
|
||||
case SURFACE_2: return ADHESIVE_LOOSE;
|
||||
case SURFACE_3: return ADHESIVE_LOOSE;
|
||||
case SURFACE_4: return ADHESIVE_HARD;
|
||||
case SURFACE_5: return ADHESIVE_ROAD;
|
||||
case SURFACE_6: return ADHESIVE_HARD;
|
||||
case SURFACE_7: return ADHESIVE_HARD;
|
||||
case SURFACE_8: return ADHESIVE_HARD;
|
||||
case SURFACE_9: return ADHESIVE_HARD;
|
||||
case SURFACE_10: return ADHESIVE_HARD;
|
||||
case SURFACE_11: return ADHESIVE_HARD;
|
||||
case SURFACE_12: return ADHESIVE_HARD;
|
||||
case SURFACE_13: return ADHESIVE_HARD;
|
||||
case SURFACE_14: return ADHESIVE_HARD;
|
||||
case SURFACE_15: return ADHESIVE_HARD;
|
||||
case SURFACE_16: return ADHESIVE_HARD;
|
||||
case SURFACE_17: return ADHESIVE_RUBBER;
|
||||
case SURFACE_18: return ADHESIVE_LOOSE;
|
||||
case SURFACE_19: return ADHESIVE_WET;
|
||||
case SURFACE_20: return ADHESIVE_ROAD;
|
||||
case SURFACE_21: return ADHESIVE_ROAD;
|
||||
case SURFACE_22: return ADHESIVE_ROAD;
|
||||
case SURFACE_23: return ADHESIVE_RUBBER;
|
||||
case SURFACE_24: return ADHESIVE_HARD;
|
||||
case SURFACE_25: return ADHESIVE_LOOSE;
|
||||
case SURFACE_26: return ADHESIVE_LOOSE;
|
||||
case SURFACE_27: return ADHESIVE_HARD;
|
||||
case SURFACE_28: return ADHESIVE_HARD;
|
||||
case SURFACE_29: return ADHESIVE_RUBBER;
|
||||
case SURFACE_30: return ADHESIVE_LOOSE;
|
||||
case SURFACE_31: return ADHESIVE_HARD;
|
||||
case SURFACE_32: return ADHESIVE_HARD;
|
||||
default: return ADHESIVE_ROAD;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
CSurfaceTable::GetWetMultiplier(uint8 surfaceType)
|
||||
{
|
||||
switch(surfaceType){
|
||||
case SURFACE_0:
|
||||
case SURFACE_1:
|
||||
case SURFACE_4:
|
||||
case SURFACE_5:
|
||||
case SURFACE_8:
|
||||
case SURFACE_20:
|
||||
case SURFACE_21:
|
||||
case SURFACE_22:
|
||||
case SURFACE_25:
|
||||
case SURFACE_30:
|
||||
case SURFACE_31:
|
||||
return 1.0f - CWeather::WetRoads*0.25f;
|
||||
|
||||
case SURFACE_2:
|
||||
case SURFACE_6:
|
||||
case SURFACE_7:
|
||||
case SURFACE_9:
|
||||
case SURFACE_10:
|
||||
case SURFACE_11:
|
||||
case SURFACE_12:
|
||||
case SURFACE_13:
|
||||
case SURFACE_14:
|
||||
case SURFACE_15:
|
||||
case SURFACE_16:
|
||||
case SURFACE_17:
|
||||
case SURFACE_23:
|
||||
case SURFACE_24:
|
||||
case SURFACE_26:
|
||||
case SURFACE_27:
|
||||
case SURFACE_28:
|
||||
case SURFACE_29:
|
||||
case SURFACE_32:
|
||||
return 1.0f - CWeather::WetRoads*0.4f;
|
||||
|
||||
default:
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
CSurfaceTable::GetAdhesiveLimit(CColPoint &colpoint)
|
||||
{
|
||||
return ms_aAdhesiveLimitTable[GetAdhesionGroup(colpoint.surfaceB)][GetAdhesionGroup(colpoint.surfaceA)];
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4AB8F0, CSurfaceTable::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x4ABA60, CSurfaceTable::GetAdhesionGroup, PATCH_JUMP);
|
||||
InjectHook(0x4ABAA0, CSurfaceTable::GetWetMultiplier, PATCH_JUMP);
|
||||
InjectHook(0x4ABA30, CSurfaceTable::GetAdhesiveLimit, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
106
src/core/SurfaceTable.h
Normal file
106
src/core/SurfaceTable.h
Normal file
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
SURFACE_0,
|
||||
SURFACE_1,
|
||||
SURFACE_2,
|
||||
SURFACE_3,
|
||||
SURFACE_4,
|
||||
SURFACE_5,
|
||||
SURFACE_6,
|
||||
SURFACE_7,
|
||||
SURFACE_8,
|
||||
SURFACE_9,
|
||||
SURFACE_10,
|
||||
SURFACE_11,
|
||||
SURFACE_12,
|
||||
SURFACE_13,
|
||||
SURFACE_14,
|
||||
SURFACE_15,
|
||||
SURFACE_16,
|
||||
SURFACE_17,
|
||||
SURFACE_18,
|
||||
SURFACE_19,
|
||||
SURFACE_20,
|
||||
SURFACE_21,
|
||||
SURFACE_22,
|
||||
SURFACE_23,
|
||||
SURFACE_24,
|
||||
SURFACE_25,
|
||||
SURFACE_26,
|
||||
SURFACE_27,
|
||||
SURFACE_28,
|
||||
SURFACE_29,
|
||||
SURFACE_30,
|
||||
SURFACE_31,
|
||||
SURFACE_32,
|
||||
|
||||
NUMSURFACETYPES
|
||||
};
|
||||
|
||||
// From nick
|
||||
// TODO: check and use this
|
||||
enum eSurfaceType
|
||||
{
|
||||
SURFACE_DEFAULT,
|
||||
SURFACE_TARMAC,
|
||||
SURFACE_GRASS,
|
||||
SURFACE_DIRT,
|
||||
SURFACE_DIRTTRACK,
|
||||
SURFACE_PAVEMENT,
|
||||
SURFACE_METAL6,
|
||||
SURFACE_GLASS,
|
||||
SURFACE_SCAFFOLD,
|
||||
SURFACE_METAL_DOOR, // garage door
|
||||
SURFACE_BILLBOARD,
|
||||
SURFACE_STEEL, //?
|
||||
SURFACE_METAL_POLE, // ?
|
||||
SURFACE_STREET_LIGHT,
|
||||
SURFACE_METAL14,
|
||||
SURFACE_METAL15,
|
||||
SURFACE_METAL_FENCE,
|
||||
SURFACE_FLESH,
|
||||
SURFACE_SAND,
|
||||
SURFACE_PUDDLE,
|
||||
SURFACE_WOOD,
|
||||
SURFACE_WOOD_BOX,
|
||||
SURFACE_WOOD_PLANK,
|
||||
SURFACE_TIRE,
|
||||
SURFACE_HARD24,
|
||||
SURFACE_HEDGE,
|
||||
SURFACE_STONE,
|
||||
SURFACE_METAL27,
|
||||
SURFACE_METAL28,
|
||||
SURFACE_RUBBER29,
|
||||
SURFACE_LOOSE30,
|
||||
SURFACE_BOLLARD,
|
||||
SURFACE_GATE,
|
||||
SURFACE_SAND33,
|
||||
SURFACE_ROAD34,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ADHESIVE_RUBBER,
|
||||
ADHESIVE_HARD,
|
||||
ADHESIVE_ROAD,
|
||||
ADHESIVE_LOOSE,
|
||||
ADHESIVE_WET,
|
||||
|
||||
NUMADHESIVEGROUPS
|
||||
};
|
||||
|
||||
struct CColPoint;
|
||||
|
||||
class CSurfaceTable
|
||||
{
|
||||
// static float ms_aAdhesiveLimitTable[NUMADHESIVEGROUPS][NUMADHESIVEGROUPS];
|
||||
static float (*ms_aAdhesiveLimitTable)[NUMADHESIVEGROUPS];
|
||||
public:
|
||||
static void Initialise(char *filename);
|
||||
static int GetAdhesionGroup(uint8 surfaceType);
|
||||
static float GetWetMultiplier(uint8 surfaceType);
|
||||
static float GetAdhesiveLimit(CColPoint &colpoint);
|
||||
};
|
||||
17
src/core/TempColModels.cpp
Normal file
17
src/core/TempColModels.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "TempColModels.h"
|
||||
|
||||
CColModel &CTempColModels::ms_colModelPed1 = *(CColModel*)0x726CB0;
|
||||
CColModel &CTempColModels::ms_colModelPed2 = *(CColModel*)0x726D08;
|
||||
CColModel &CTempColModels::ms_colModelBBox = *(CColModel*)0x727FE0;
|
||||
CColModel &CTempColModels::ms_colModelBumper1 = *(CColModel*)0x86BE88;
|
||||
CColModel &CTempColModels::ms_colModelWheel1 = *(CColModel*)0x878C40;
|
||||
CColModel &CTempColModels::ms_colModelPanel1 = *(CColModel*)0x87BDD8;
|
||||
CColModel &CTempColModels::ms_colModelBodyPart2 = *(CColModel*)0x87BE30;
|
||||
CColModel &CTempColModels::ms_colModelBodyPart1 = *(CColModel*)0x87BE88;
|
||||
CColModel &CTempColModels::ms_colModelCutObj = *(CColModel*)0x87C960;
|
||||
CColModel &CTempColModels::ms_colModelPedGroundHit = *(CColModel*)0x880480;
|
||||
CColModel &CTempColModels::ms_colModelBoot1 = *(CColModel*)0x880670;
|
||||
CColModel &CTempColModels::ms_colModelDoor1 = *(CColModel*)0x880850;
|
||||
CColModel &CTempColModels::ms_colModelBonnet1 = *(CColModel*)0x8808A8;
|
||||
21
src/core/TempColModels.h
Normal file
21
src/core/TempColModels.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#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;
|
||||
static CColModel &ms_colModelPedGroundHit;
|
||||
static CColModel &ms_colModelBoot1;
|
||||
static CColModel &ms_colModelDoor1;
|
||||
static CColModel &ms_colModelBonnet1;
|
||||
};
|
||||
232
src/core/Text.cpp
Normal file
232
src/core/Text.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "FileMgr.h"
|
||||
#include "Frontend.h"
|
||||
#include "Messages.h"
|
||||
#include "Text.h"
|
||||
|
||||
static wchar WideErrorString[25];
|
||||
|
||||
CText &TheText = *(CText*)0x941520;
|
||||
|
||||
CText::CText(void)
|
||||
{
|
||||
keyArray.entries = nil;
|
||||
keyArray.numEntries = 0;
|
||||
data.chars = nil;
|
||||
data.numChars = 0;
|
||||
encoding = 101;
|
||||
memset(WideErrorString, 0, sizeof(WideErrorString));
|
||||
}
|
||||
|
||||
CText::~CText(void)
|
||||
{
|
||||
data.Unload();
|
||||
keyArray.Unload();
|
||||
}
|
||||
|
||||
void
|
||||
CText::Load(void)
|
||||
{
|
||||
uint8 *filedata;
|
||||
char filename[32], type[4];
|
||||
int length;
|
||||
int offset, sectlen;
|
||||
|
||||
Unload();
|
||||
filedata = new uint8[0x40000];
|
||||
|
||||
CFileMgr::SetDir("TEXT");
|
||||
switch(CMenuManager::m_PrefsLanguage){
|
||||
case LANGUAGE_AMERICAN:
|
||||
sprintf(filename, "AMERICAN.GXT");
|
||||
break;
|
||||
case LANGUAGE_FRENCH:
|
||||
sprintf(filename, "FRENCH.GXT");
|
||||
break;
|
||||
case LANGUAGE_GERMAN:
|
||||
sprintf(filename, "GERMAN.GXT");
|
||||
break;
|
||||
case LANGUAGE_ITALIAN:
|
||||
sprintf(filename, "ITALIAN.GXT");
|
||||
break;
|
||||
case LANGUAGE_SPANISH:
|
||||
sprintf(filename, "SPANISH.GXT");
|
||||
break;
|
||||
}
|
||||
|
||||
length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");
|
||||
CFileMgr::SetDir("");
|
||||
|
||||
offset = 0;
|
||||
while(offset < length){
|
||||
type[0] = filedata[offset++];
|
||||
type[1] = filedata[offset++];
|
||||
type[2] = filedata[offset++];
|
||||
type[3] = filedata[offset++];
|
||||
sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 |
|
||||
(int)filedata[offset+1]<<8 | (int)filedata[offset+0];
|
||||
offset += 4;
|
||||
if(sectlen != 0){
|
||||
if(strncmp(type, "TKEY", 4) == 0)
|
||||
keyArray.Load(sectlen, filedata, &offset);
|
||||
else if(strncmp(type, "TDAT", 4) == 0)
|
||||
data.Load(sectlen, filedata, &offset);
|
||||
else
|
||||
offset += sectlen;
|
||||
}
|
||||
}
|
||||
|
||||
keyArray.Update(data.chars);
|
||||
|
||||
delete[] filedata;
|
||||
}
|
||||
|
||||
void
|
||||
CText::Unload(void)
|
||||
{
|
||||
CMessages::ClearAllMessagesDisplayedByGame();
|
||||
data.Unload();
|
||||
keyArray.Unload();
|
||||
}
|
||||
|
||||
wchar*
|
||||
CText::Get(const char *key)
|
||||
{
|
||||
return keyArray.Search(key);
|
||||
}
|
||||
|
||||
wchar
|
||||
CText::GetUpperCase(wchar c)
|
||||
{
|
||||
// TODO: do this depending on encoding
|
||||
if(islower(c))
|
||||
return toupper(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
CText::UpperCase(wchar *s)
|
||||
{
|
||||
while(*s){
|
||||
*s = GetUpperCase(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CKeyArray::Load(uint32 length, uint8 *data, int *offset)
|
||||
{
|
||||
uint32 i;
|
||||
uint8 *rawbytes;
|
||||
|
||||
numEntries = length / sizeof(CKeyEntry);
|
||||
entries = new CKeyEntry[numEntries];
|
||||
rawbytes = (uint8*)entries;
|
||||
|
||||
for(i = 0; i < length; i++)
|
||||
rawbytes[i] = data[(*offset)++];
|
||||
}
|
||||
|
||||
void
|
||||
CKeyArray::Unload(void)
|
||||
{
|
||||
delete[] entries;
|
||||
entries = nil;
|
||||
numEntries = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CKeyArray::Update(wchar *chars)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < numEntries; i++)
|
||||
entries[i].value = (wchar*)((uint8*)chars + (uintptr)entries[i].value);
|
||||
}
|
||||
|
||||
CKeyEntry*
|
||||
CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
|
||||
{
|
||||
int mid;
|
||||
int diff;
|
||||
|
||||
if(low > high)
|
||||
return nil;
|
||||
|
||||
mid = (low + high)/2;
|
||||
diff = strcmp(key, entries[mid].key);
|
||||
if(diff == 0)
|
||||
return &entries[mid];
|
||||
if(diff < 0)
|
||||
return BinarySearch(key, entries, low, mid-1);
|
||||
if(diff > 0)
|
||||
return BinarySearch(key, entries, mid+1, high);
|
||||
return nil;
|
||||
}
|
||||
|
||||
wchar*
|
||||
CKeyArray::Search(const char *key)
|
||||
{
|
||||
CKeyEntry *found;
|
||||
char errstr[25];
|
||||
int i;
|
||||
|
||||
found = BinarySearch(key, entries, 0, numEntries-1);
|
||||
if(found)
|
||||
return found->value;
|
||||
sprintf(errstr, "%s missing", key);
|
||||
for(i = 0; i < 25; i++)
|
||||
WideErrorString[i] = errstr[i];
|
||||
return WideErrorString;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CData::Load(uint32 length, uint8 *data, int *offset)
|
||||
{
|
||||
uint32 i;
|
||||
uint8 *rawbytes;
|
||||
|
||||
numChars = length / sizeof(wchar);
|
||||
chars = new wchar[numChars];
|
||||
rawbytes = (uint8*)chars;
|
||||
|
||||
for(i = 0; i < length; i++)
|
||||
rawbytes[i] = data[(*offset)++];
|
||||
}
|
||||
|
||||
void
|
||||
CData::Unload(void)
|
||||
{
|
||||
delete[] chars;
|
||||
chars = nil;
|
||||
numChars = 0;
|
||||
}
|
||||
|
||||
void
|
||||
AsciiToUnicode(const char *src, uint16 *dst)
|
||||
{
|
||||
while((*dst++ = *src++) != '\0');
|
||||
}
|
||||
|
||||
void
|
||||
TextCopy(wchar *dst, const wchar *src)
|
||||
{
|
||||
while((*dst++ = *src++) != '\0');
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP);
|
||||
InjectHook(0x52C580, &CText::Unload, PATCH_JUMP);
|
||||
InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP);
|
||||
InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP);
|
||||
InjectHook(0x52BF80, &CKeyArray::Update, PATCH_JUMP);
|
||||
InjectHook(0x52C060, &CKeyArray::BinarySearch, PATCH_JUMP);
|
||||
InjectHook(0x52BFB0, &CKeyArray::Search, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x52C120, &CData::Load, PATCH_JUMP);
|
||||
InjectHook(0x52C200, &CData::Unload, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
52
src/core/Text.h
Normal file
52
src/core/Text.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
void AsciiToUnicode(const char *src, wchar *dst);
|
||||
void TextCopy(wchar *dst, const wchar *src);
|
||||
|
||||
struct CKeyEntry
|
||||
{
|
||||
wchar *value;
|
||||
char key[8];
|
||||
};
|
||||
// If this fails, CKeyArray::Load will have to be fixed
|
||||
static_assert(sizeof(CKeyEntry) == 12, "CKeyEntry: error");
|
||||
|
||||
class CKeyArray
|
||||
{
|
||||
public:
|
||||
CKeyEntry *entries;
|
||||
int numEntries;
|
||||
|
||||
void Load(uint32 length, uint8 *data, int *offset);
|
||||
void Unload(void);
|
||||
void Update(wchar *chars);
|
||||
CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high);
|
||||
wchar *Search(const char *key);
|
||||
};
|
||||
|
||||
class CData
|
||||
{
|
||||
public:
|
||||
wchar *chars;
|
||||
int numChars;
|
||||
|
||||
void Load(uint32 length, uint8 *data, int *offset);
|
||||
void Unload(void);
|
||||
};
|
||||
|
||||
class CText
|
||||
{
|
||||
CKeyArray keyArray;
|
||||
CData data;
|
||||
int8 encoding;
|
||||
public:
|
||||
CText(void);
|
||||
~CText(void);
|
||||
void Load(void);
|
||||
void Unload(void);
|
||||
wchar *Get(const char *key);
|
||||
wchar GetUpperCase(wchar c);
|
||||
void UpperCase(wchar *s);
|
||||
};
|
||||
|
||||
extern CText &TheText;
|
||||
235
src/core/Timer.cpp
Normal file
235
src/core/Timer.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
#include <windows.h>
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "DMAudio.h"
|
||||
#include "Record.h"
|
||||
#include "Timer.h"
|
||||
|
||||
uint32 &CTimer::m_snTimeInMilliseconds = *(uint32*)0x885B48;
|
||||
uint32 &CTimer::m_snTimeInMillisecondsPauseMode = *(uint32*)0x5F7614;
|
||||
uint32 &CTimer::m_snTimeInMillisecondsNonClipped = *(uint32*)0x9412E8;
|
||||
uint32 &CTimer::m_snPreviousTimeInMilliseconds = *(uint32*)0x8F29E4;
|
||||
uint32 &CTimer::m_FrameCounter = *(uint32*)0x9412EC;
|
||||
float &CTimer::ms_fTimeScale = *(float*)0x8F2C20;
|
||||
float &CTimer::ms_fTimeStep = *(float*)0x8E2CB4;
|
||||
float &CTimer::ms_fTimeStepNonClipped = *(float*)0x8E2C4C;
|
||||
bool &CTimer::m_UserPause = *(bool*)0x95CD7C;
|
||||
bool &CTimer::m_CodePause = *(bool*)0x95CDB1;
|
||||
|
||||
//UInt32 oldPcTimer;
|
||||
uint32 &oldPcTimer = *(uint32*)0x9434F4;
|
||||
|
||||
//UInt32 suspendPcTimer;
|
||||
uint32 &suspendPcTimer = *(uint32*)0x62A308;
|
||||
|
||||
//UInt32 _nCyclesPerMS = 1;
|
||||
uint32 &_nCyclesPerMS = *(uint32*)0x5F7610;
|
||||
|
||||
//LARGE_INTEGER _oldPerfCounter;
|
||||
LARGE_INTEGER &_oldPerfCounter = *(LARGE_INTEGER*)0x62A310;
|
||||
|
||||
//LARGE_INTEGER perfSuspendCounter;
|
||||
LARGE_INTEGER &perfSuspendCounter = *(LARGE_INTEGER*)0x62A318;
|
||||
|
||||
//UInt32 suspendDepth;
|
||||
uint32 &suspendDepth = *(uint32*)0x62A320;
|
||||
|
||||
void CTimer::Initialise(void)
|
||||
{
|
||||
debug("Initialising CTimer...\n");
|
||||
|
||||
ms_fTimeScale = 1.0f;
|
||||
ms_fTimeStep = 1.0f;
|
||||
suspendDepth = 0;
|
||||
m_UserPause = false;
|
||||
m_CodePause = false;
|
||||
m_snTimeInMillisecondsNonClipped = 0;
|
||||
m_snPreviousTimeInMilliseconds = 0;
|
||||
m_snTimeInMilliseconds = 1;
|
||||
|
||||
LARGE_INTEGER perfFreq;
|
||||
if ( QueryPerformanceFrequency(&perfFreq) )
|
||||
{
|
||||
OutputDebugString("Performance counter available\n");
|
||||
_nCyclesPerMS = uint32(perfFreq.QuadPart / 1000);
|
||||
QueryPerformanceCounter(&_oldPerfCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputDebugString("Performance counter not available, using millesecond timer\n");
|
||||
_nCyclesPerMS = 0;
|
||||
oldPcTimer = RsTimer();
|
||||
}
|
||||
|
||||
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds;
|
||||
|
||||
m_FrameCounter = 0;
|
||||
|
||||
DMAudio.ResetTimers(m_snPreviousTimeInMilliseconds);
|
||||
|
||||
debug("CTimer ready\n");
|
||||
}
|
||||
|
||||
void CTimer::Shutdown(void)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
#if 1
|
||||
WRAPPER void CTimer::Update(void) { EAXJMP(0x4ACF70); }
|
||||
#else
|
||||
void CTimer::Update(void)
|
||||
{
|
||||
m_snPreviousTimeInMilliseconds = m_snTimeInMilliseconds;
|
||||
|
||||
if ( (double)_nCyclesPerMS != 0.0 )
|
||||
{
|
||||
LARGE_INTEGER pc;
|
||||
QueryPerformanceCounter(&pc);
|
||||
|
||||
int32 updInCycles = (pc.LowPart - _oldPerfCounter.LowPart) & 0x7FFFFFFF;
|
||||
|
||||
_oldPerfCounter = pc;
|
||||
|
||||
double updInCyclesScaled = (double)updInCycles * ms_fTimeScale;
|
||||
|
||||
double upd = updInCyclesScaled / (double)_nCyclesPerMS;
|
||||
|
||||
m_snTimeInMillisecondsPauseMode = (Int64)(m_snTimeInMillisecondsPauseMode + upd);
|
||||
|
||||
if ( GetIsPaused() )
|
||||
ms_fTimeStep = 0.0f;
|
||||
else
|
||||
{
|
||||
m_snTimeInMilliseconds = (Int64)(m_snTimeInMilliseconds + upd);
|
||||
m_snTimeInMillisecondsNonClipped = (Int64)(m_snTimeInMillisecondsNonClipped + upd);
|
||||
ms_fTimeStep = updInCyclesScaled / (double)_nCyclesPerMS / 20.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 timer = RsTimer();
|
||||
|
||||
uint32 updInMs = timer - oldPcTimer;
|
||||
|
||||
double upd = (double)updInMs * ms_fTimeScale;
|
||||
|
||||
oldPcTimer = timer;
|
||||
|
||||
m_snTimeInMillisecondsPauseMode = (Int64)(m_snTimeInMillisecondsPauseMode + upd);
|
||||
|
||||
if ( GetIsPaused() )
|
||||
ms_fTimeStep = 0.0f;
|
||||
else
|
||||
{
|
||||
m_snTimeInMilliseconds = (Int64)(m_snTimeInMilliseconds + upd);
|
||||
m_snTimeInMillisecondsNonClipped = (Int64)(m_snTimeInMillisecondsNonClipped + upd);
|
||||
ms_fTimeStep = upd / 1000.0f * 50.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ms_fTimeStep < 0.01f && !GetIsPaused() )
|
||||
ms_fTimeStep = 0.01f;
|
||||
|
||||
ms_fTimeStepNonClipped = ms_fTimeStep;
|
||||
|
||||
if ( CRecordDataForGame::RecordingState != RECORDSTATE_2 )
|
||||
{
|
||||
ms_fTimeStep = min(3.0f, ms_fTimeStep);
|
||||
|
||||
if ( (m_snTimeInMilliseconds - m_snPreviousTimeInMilliseconds) > 60 )
|
||||
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 60;
|
||||
}
|
||||
|
||||
if ( CRecordDataForChase::Status == RECORDSTATE_1 )
|
||||
{
|
||||
ms_fTimeStep = 1.0f;
|
||||
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 16;
|
||||
}
|
||||
|
||||
m_FrameCounter++;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CTimer::Suspend(void)
|
||||
{
|
||||
if ( ++suspendDepth > 1 )
|
||||
return;
|
||||
|
||||
if ( (double)_nCyclesPerMS != 0.0 )
|
||||
QueryPerformanceCounter(&perfSuspendCounter);
|
||||
else
|
||||
suspendPcTimer = RsTimer();
|
||||
}
|
||||
|
||||
void CTimer::Resume(void)
|
||||
{
|
||||
if ( --suspendDepth != 0 )
|
||||
return;
|
||||
|
||||
if ( (double)_nCyclesPerMS != 0.0 )
|
||||
{
|
||||
LARGE_INTEGER pc;
|
||||
QueryPerformanceCounter(&pc);
|
||||
|
||||
_oldPerfCounter.LowPart += pc.LowPart - perfSuspendCounter.LowPart;
|
||||
}
|
||||
else
|
||||
oldPcTimer += RsTimer() - suspendPcTimer;
|
||||
}
|
||||
|
||||
uint32 CTimer::GetCyclesPerMillisecond(void)
|
||||
{
|
||||
if (_nCyclesPerMS != 0)
|
||||
return _nCyclesPerMS;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32 CTimer::GetCurrentTimeInCycles(void)
|
||||
{
|
||||
if ( _nCyclesPerMS != 0 )
|
||||
{
|
||||
LARGE_INTEGER pc;
|
||||
QueryPerformanceCounter(&pc);
|
||||
return (pc.LowPart - _oldPerfCounter.LowPart) & 0x7FFFFFFF;
|
||||
}
|
||||
else
|
||||
return RsTimer() - oldPcTimer;
|
||||
}
|
||||
|
||||
bool CTimer::GetIsSlowMotionActive(void)
|
||||
{
|
||||
return ms_fTimeScale < 1.0f;
|
||||
}
|
||||
|
||||
void CTimer::Stop(void)
|
||||
{
|
||||
m_snPreviousTimeInMilliseconds = m_snTimeInMilliseconds;
|
||||
}
|
||||
|
||||
void CTimer::StartUserPause(void)
|
||||
{
|
||||
m_UserPause = true;
|
||||
}
|
||||
|
||||
void CTimer::EndUserPause(void)
|
||||
{
|
||||
m_UserPause = false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
STARTPATCHES
|
||||
InjectHook(0x4ACE60, CTimer::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x4ACF60, CTimer::Shutdown, PATCH_JUMP);
|
||||
InjectHook(0x4ACF70, CTimer::Update, PATCH_JUMP);
|
||||
InjectHook(0x4AD310, CTimer::Suspend, PATCH_JUMP);
|
||||
InjectHook(0x4AD370, CTimer::Resume, PATCH_JUMP);
|
||||
InjectHook(0x4AD3F0, CTimer::GetCyclesPerMillisecond, PATCH_JUMP);
|
||||
InjectHook(0x4AD410, CTimer::GetCurrentTimeInCycles, PATCH_JUMP);
|
||||
InjectHook(0x4AD450, CTimer::GetIsSlowMotionActive, PATCH_JUMP);
|
||||
InjectHook(0x4AD480, CTimer::Stop, PATCH_JUMP);
|
||||
InjectHook(0x4AD490, CTimer::StartUserPause, PATCH_JUMP);
|
||||
InjectHook(0x4AD4A0, CTimer::EndUserPause, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
#endif
|
||||
51
src/core/Timer.h
Normal file
51
src/core/Timer.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
class CTimer
|
||||
{
|
||||
static uint32 &m_snTimeInMilliseconds;
|
||||
static uint32 &m_snTimeInMillisecondsPauseMode;
|
||||
static uint32 &m_snTimeInMillisecondsNonClipped;
|
||||
static uint32 &m_snPreviousTimeInMilliseconds;
|
||||
static uint32 &m_FrameCounter;
|
||||
static float &ms_fTimeScale;
|
||||
static float &ms_fTimeStep;
|
||||
static float &ms_fTimeStepNonClipped;
|
||||
static bool &m_UserPause;
|
||||
static bool &m_CodePause;
|
||||
public:
|
||||
static float GetTimeStep(void) { return ms_fTimeStep; }
|
||||
static void SetTimeStep(float ts) { ms_fTimeStep = ts; }
|
||||
static float GetTimeStepInSeconds() { return ms_fTimeStep / 50.0f; }
|
||||
static float GetTimeStepInMilliseconds() { return ms_fTimeStep / 50.0f * 1000.0f; }
|
||||
static float GetTimeStepNonClipped(void) { return ms_fTimeStepNonClipped; }
|
||||
static float GetTimeStepNonClippedInSeconds(void) { return ms_fTimeStepNonClipped / 50.0f; }
|
||||
static void SetTimeStepNonClipped(float ts) { ms_fTimeStepNonClipped = ts; }
|
||||
static uint32 GetFrameCounter(void) { return m_FrameCounter; }
|
||||
static void SetFrameCounter(uint32 fc) { m_FrameCounter = fc; }
|
||||
static uint32 GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; }
|
||||
static void SetTimeInMilliseconds(uint32 t) { m_snTimeInMilliseconds = t; }
|
||||
static uint32 GetTimeInMillisecondsNonClipped(void) { return m_snTimeInMillisecondsNonClipped; }
|
||||
static void SetTimeInMillisecondsNonClipped(uint32 t) { m_snTimeInMillisecondsNonClipped = t; }
|
||||
static uint32 GetTimeInMillisecondsPauseMode(void) { return m_snTimeInMillisecondsPauseMode; }
|
||||
static void SetTimeInMillisecondsPauseMode(uint32 t) { m_snTimeInMillisecondsPauseMode = t; }
|
||||
static uint32 GetPreviousTimeInMilliseconds(void) { return m_snPreviousTimeInMilliseconds; }
|
||||
static void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; }
|
||||
static float GetTimeScale(void) { return ms_fTimeScale; }
|
||||
static void SetTimeScale(float ts) { ms_fTimeScale = ts; }
|
||||
|
||||
static bool GetIsPaused() { return m_UserPause || m_CodePause; }
|
||||
static bool GetIsUserPaused() { return m_UserPause; }
|
||||
static void SetCodePause(bool pause) { m_CodePause = pause; }
|
||||
|
||||
static void Initialise(void);
|
||||
static void Shutdown(void);
|
||||
static void Update(void);
|
||||
static void Suspend(void);
|
||||
static void Resume(void);
|
||||
static uint32 GetCyclesPerMillisecond(void);
|
||||
static uint32 GetCurrentTimeInCycles(void);
|
||||
static bool GetIsSlowMotionActive(void);
|
||||
static void Stop(void);
|
||||
static void StartUserPause(void);
|
||||
static void EndUserPause(void);
|
||||
};
|
||||
208
src/core/TxdStore.cpp
Normal file
208
src/core/TxdStore.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "templates.h"
|
||||
#include "Streaming.h"
|
||||
#include "RwHelper.h"
|
||||
#include "TxdStore.h"
|
||||
|
||||
CPool<TxdDef,TxdDef> *&CTxdStore::ms_pTxdPool = *(CPool<TxdDef,TxdDef>**)0x8F5FB8;
|
||||
RwTexDictionary *&CTxdStore::ms_pStoredTxd = *(RwTexDictionary**)0x9405BC;
|
||||
|
||||
void
|
||||
CTxdStore::Initialize(void)
|
||||
{
|
||||
if(ms_pTxdPool == nil)
|
||||
ms_pTxdPool = new CPool<TxdDef,TxdDef>(TXDSTORESIZE);
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::Shutdown(void)
|
||||
{
|
||||
if(ms_pTxdPool)
|
||||
delete ms_pTxdPool;
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::GameShutdown(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < TXDSTORESIZE; i++){
|
||||
TxdDef *def = GetSlot(i);
|
||||
if(def && GetNumRefs(i) == 0)
|
||||
RemoveTxdSlot(i);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
CTxdStore::AddTxdSlot(const char *name)
|
||||
{
|
||||
TxdDef *def = ms_pTxdPool->New();
|
||||
assert(def);
|
||||
def->texDict = nil;
|
||||
def->refCount = 0;
|
||||
strcpy(def->name, name);
|
||||
return ms_pTxdPool->GetJustIndex(def);
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::RemoveTxdSlot(int slot)
|
||||
{
|
||||
TxdDef *def = GetSlot(slot);
|
||||
if(def->texDict)
|
||||
RwTexDictionaryDestroy(def->texDict);
|
||||
ms_pTxdPool->Delete(def);
|
||||
}
|
||||
|
||||
int
|
||||
CTxdStore::FindTxdSlot(const char *name)
|
||||
{
|
||||
char *defname;
|
||||
int size = ms_pTxdPool->GetSize();
|
||||
for(int i = 0; i < size; i++){
|
||||
defname = GetTxdName(i);
|
||||
if(defname && _strcmpi(defname, name) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char*
|
||||
CTxdStore::GetTxdName(int slot)
|
||||
{
|
||||
TxdDef *def = GetSlot(slot);
|
||||
return def ? def->name : nil;
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::PushCurrentTxd(void)
|
||||
{
|
||||
ms_pStoredTxd = RwTexDictionaryGetCurrent();
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::PopCurrentTxd(void)
|
||||
{
|
||||
RwTexDictionarySetCurrent(ms_pStoredTxd);
|
||||
ms_pStoredTxd = nil;
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::SetCurrentTxd(int slot)
|
||||
{
|
||||
TxdDef *def = GetSlot(slot);
|
||||
if(def)
|
||||
RwTexDictionarySetCurrent(def->texDict);
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::Create(int slot)
|
||||
{
|
||||
GetSlot(slot)->texDict = RwTexDictionaryCreate();
|
||||
}
|
||||
|
||||
int
|
||||
CTxdStore::GetNumRefs(int slot)
|
||||
{
|
||||
return GetSlot(slot)->refCount;
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::AddRef(int slot)
|
||||
{
|
||||
GetSlot(slot)->refCount++;
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::RemoveRef(int slot)
|
||||
{
|
||||
if(--GetSlot(slot)->refCount <= 0)
|
||||
CStreaming::RemoveModel(slot + STREAM_OFFSET_TXD);
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::RemoveRefWithoutDelete(int slot)
|
||||
{
|
||||
GetSlot(slot)->refCount--;
|
||||
}
|
||||
|
||||
bool
|
||||
CTxdStore::LoadTxd(int slot, RwStream *stream)
|
||||
{
|
||||
TxdDef *def = GetSlot(slot);
|
||||
|
||||
if(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil)){
|
||||
def->texDict = RwTexDictionaryGtaStreamRead(stream);
|
||||
return def->texDict != nil;
|
||||
}
|
||||
printf("Failed to load TXD\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CTxdStore::LoadTxd(int slot, const char *filename)
|
||||
{
|
||||
RwStream *stream;
|
||||
bool ret;
|
||||
|
||||
ret = false;
|
||||
_rwD3D8TexDictionaryEnableRasterFormatConversion(true);
|
||||
do
|
||||
stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);
|
||||
while(stream == nil);
|
||||
ret = LoadTxd(slot, stream);
|
||||
RwStreamClose(stream, nil);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
CTxdStore::StartLoadTxd(int slot, RwStream *stream)
|
||||
{
|
||||
TxdDef *def = GetSlot(slot);
|
||||
if(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil)){
|
||||
def->texDict = RwTexDictionaryGtaStreamRead1(stream);
|
||||
return def->texDict != nil;
|
||||
}else{
|
||||
printf("Failed to load TXD\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CTxdStore::FinishLoadTxd(int slot, RwStream *stream)
|
||||
{
|
||||
TxdDef *def = GetSlot(slot);
|
||||
def->texDict = RwTexDictionaryGtaStreamRead2(stream, def->texDict);
|
||||
return def->texDict != nil;
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::RemoveTxd(int slot)
|
||||
{
|
||||
TxdDef *def = GetSlot(slot);
|
||||
if(def->texDict)
|
||||
RwTexDictionaryDestroy(def->texDict);
|
||||
def->texDict = nil;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x527440, CTxdStore::Initialize, PATCH_JUMP);
|
||||
InjectHook(0x527470, CTxdStore::Shutdown, PATCH_JUMP);
|
||||
InjectHook(0x527490, CTxdStore::GameShutdown, PATCH_JUMP);
|
||||
InjectHook(0x5274E0, CTxdStore::AddTxdSlot, PATCH_JUMP);
|
||||
InjectHook(0x5275D0, CTxdStore::FindTxdSlot, PATCH_JUMP);
|
||||
InjectHook(0x527590, CTxdStore::GetTxdName, PATCH_JUMP);
|
||||
InjectHook(0x527900, CTxdStore::PushCurrentTxd, PATCH_JUMP);
|
||||
InjectHook(0x527910, CTxdStore::PopCurrentTxd, PATCH_JUMP);
|
||||
InjectHook(0x5278C0, CTxdStore::SetCurrentTxd, PATCH_JUMP);
|
||||
InjectHook(0x527830, CTxdStore::Create, PATCH_JUMP);
|
||||
InjectHook(0x527A00, CTxdStore::GetNumRefs, PATCH_JUMP);
|
||||
InjectHook(0x527930, CTxdStore::AddRef, PATCH_JUMP);
|
||||
InjectHook(0x527970, CTxdStore::RemoveRef, PATCH_JUMP);
|
||||
InjectHook(0x5279C0, CTxdStore::RemoveRefWithoutDelete, PATCH_JUMP);
|
||||
InjectHook(0x527700, (bool (*)(int, RwStream*))CTxdStore::LoadTxd, PATCH_JUMP);
|
||||
InjectHook(0x5276B0, (bool (*)(int, const char*))CTxdStore::LoadTxd, PATCH_JUMP);
|
||||
InjectHook(0x527770, CTxdStore::StartLoadTxd, PATCH_JUMP);
|
||||
InjectHook(0x5277E0, CTxdStore::FinishLoadTxd, PATCH_JUMP);
|
||||
InjectHook(0x527870, CTxdStore::RemoveTxd, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
44
src/core/TxdStore.h
Normal file
44
src/core/TxdStore.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "templates.h"
|
||||
|
||||
struct TxdDef {
|
||||
RwTexDictionary *texDict;
|
||||
int refCount;
|
||||
char name[20];
|
||||
};
|
||||
|
||||
class CTxdStore
|
||||
{
|
||||
static CPool<TxdDef,TxdDef> *&ms_pTxdPool;
|
||||
static RwTexDictionary *&ms_pStoredTxd;
|
||||
public:
|
||||
static void Initialize(void);
|
||||
static void Shutdown(void);
|
||||
static void GameShutdown(void);
|
||||
static int AddTxdSlot(const char *name);
|
||||
static void RemoveTxdSlot(int slot);
|
||||
static int FindTxdSlot(const char *name);
|
||||
static char *GetTxdName(int slot);
|
||||
static void PushCurrentTxd(void);
|
||||
static void PopCurrentTxd(void);
|
||||
static void SetCurrentTxd(int slot);
|
||||
static void Create(int slot);
|
||||
static int GetNumRefs(int slot);
|
||||
static void AddRef(int slot);
|
||||
static void RemoveRef(int slot);
|
||||
static void RemoveRefWithoutDelete(int slot);
|
||||
static bool LoadTxd(int slot, RwStream *stream);
|
||||
static bool LoadTxd(int slot, const char *filename);
|
||||
static bool StartLoadTxd(int slot, RwStream *stream);
|
||||
static bool FinishLoadTxd(int slot, RwStream *stream);
|
||||
static void RemoveTxd(int slot);
|
||||
|
||||
static TxdDef *GetSlot(int slot) {
|
||||
assert(slot >= 0);
|
||||
assert(ms_pTxdPool);
|
||||
assert(slot < ms_pTxdPool->GetSize());
|
||||
return ms_pTxdPool->GetSlot(slot);
|
||||
}
|
||||
static bool isTxdLoaded(int slot);
|
||||
};
|
||||
176
src/core/User.cpp
Normal file
176
src/core/User.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
|
||||
#include "DMAudio.h"
|
||||
#include "Hud.h"
|
||||
#include "Replay.h"
|
||||
#include "Timer.h"
|
||||
#include "Script.h"
|
||||
#include "User.h"
|
||||
|
||||
CPlaceName& CUserDisplay::PlaceName = *(CPlaceName*)0x8F29BC;
|
||||
COnscreenTimer& CUserDisplay::OnscnTimer = *(COnscreenTimer*)0x862238;
|
||||
CPager& CUserDisplay::Pager = *(CPager*)0x8F2744;
|
||||
CCurrentVehicle& CUserDisplay::CurrentVehicle = *(CCurrentVehicle*)0x8F5FE8;
|
||||
|
||||
void COnscreenTimer::Init() {
|
||||
m_bDisabled = false;
|
||||
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
|
||||
m_sEntries[i].m_nTimerOffset = 0;
|
||||
m_sEntries[i].m_nCounterOffset = 0;
|
||||
|
||||
for(uint32 j = 0; j < 10; j++) {
|
||||
m_sEntries[i].m_aTimerText[j] = 0;
|
||||
m_sEntries[i].m_aCounterText[j] = 0;
|
||||
}
|
||||
|
||||
m_sEntries[i].m_nType = 0;
|
||||
m_sEntries[i].m_bTimerProcessed = 0;
|
||||
m_sEntries[i].m_bCounterProcessed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void COnscreenTimer::Process() {
|
||||
if(!CReplay::IsPlayingBack() && !m_bDisabled) {
|
||||
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
|
||||
m_sEntries[i].Process();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void COnscreenTimer::ProcessForDisplay() {
|
||||
if(CHud::m_Wants_To_Draw_Hud) {
|
||||
m_bProcessed = false;
|
||||
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
|
||||
if(m_sEntries[i].ProcessForDisplay()) {
|
||||
m_bProcessed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void COnscreenTimer::ClearCounter(uint32 offset) {
|
||||
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
|
||||
if(offset == m_sEntries[i].m_nCounterOffset) {
|
||||
m_sEntries[i].m_nCounterOffset = 0;
|
||||
m_sEntries[i].m_aCounterText[0] = 0;
|
||||
m_sEntries[i].m_nType = 0;
|
||||
m_sEntries[i].m_bCounterProcessed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void COnscreenTimer::ClearClock(uint32 offset) {
|
||||
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
|
||||
if(offset == m_sEntries[i].m_nTimerOffset) {
|
||||
m_sEntries[i].m_nTimerOffset = 0;
|
||||
m_sEntries[i].m_aTimerText[0] = 0;
|
||||
m_sEntries[i].m_bTimerProcessed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void COnscreenTimer::AddCounter(uint32 offset, uint16 type, char* text) {
|
||||
uint32 i = 0;
|
||||
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
|
||||
if(m_sEntries[i].m_nCounterOffset == 0) {
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
m_sEntries[i].m_nCounterOffset = offset;
|
||||
if(text) {
|
||||
strncpy(m_sEntries[i].m_aCounterText, text, 10);
|
||||
} else {
|
||||
m_sEntries[i].m_aCounterText[0] = 0;
|
||||
}
|
||||
|
||||
m_sEntries[i].m_nType = type;
|
||||
}
|
||||
|
||||
void COnscreenTimer::AddClock(uint32 offset, char* text) {
|
||||
uint32 i = 0;
|
||||
for(uint32 i = 0; i < NUMONSCREENTIMERENTRIES; i++) {
|
||||
if(m_sEntries[i].m_nTimerOffset == 0) {
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
m_sEntries[i].m_nTimerOffset = offset;
|
||||
if(text) {
|
||||
strncpy(m_sEntries[i].m_aTimerText, text, 10);
|
||||
} else {
|
||||
m_sEntries[i].m_aTimerText[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void COnscreenTimerEntry::Process() {
|
||||
if(m_nTimerOffset == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32* timerPtr = (uint32*)&CTheScripts::ScriptSpace[m_nTimerOffset];
|
||||
uint32 oldTime = *timerPtr;
|
||||
int32 newTime = int32(oldTime - uint32(20.0f * CTimer::GetTimeStep()));
|
||||
if(newTime < 0) {
|
||||
*timerPtr = 0;
|
||||
m_bTimerProcessed = 0;
|
||||
m_nTimerOffset = 0;
|
||||
m_aTimerText[0] = 0;
|
||||
} else {
|
||||
*timerPtr = (uint32)newTime;
|
||||
uint32 oldTimeSeconds = oldTime / 1000;
|
||||
if(oldTimeSeconds <= 11 && newTime / 1000 != oldTimeSeconds) {
|
||||
// TODO: use an enum here
|
||||
DMAudio.PlayFrontEndSound(0x93, newTime / 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool COnscreenTimerEntry::ProcessForDisplay() {
|
||||
m_bTimerProcessed = false;
|
||||
m_bCounterProcessed = false;
|
||||
|
||||
if(m_nTimerOffset == 0 && m_nCounterOffset == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_nTimerOffset != 0) {
|
||||
m_bTimerProcessed = true;
|
||||
ProcessForDisplayTimer();
|
||||
}
|
||||
|
||||
if(m_nCounterOffset != 0) {
|
||||
m_bCounterProcessed = true;
|
||||
ProcessForDisplayCounter();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int COnscreenTimerEntry::ProcessForDisplayTimer() {
|
||||
uint32 time = *(uint32*)&CTheScripts::ScriptSpace[m_nTimerOffset];
|
||||
return sprintf(m_bTimerBuffer, "%02d:%02d", time / 1000 / 60,
|
||||
time / 1000 % 60);
|
||||
}
|
||||
|
||||
int COnscreenTimerEntry::ProcessForDisplayCounter() {
|
||||
uint32 counter = *(uint32*)&CTheScripts::ScriptSpace[m_nCounterOffset];
|
||||
return sprintf(m_bCounterBuffer, "%d", counter);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x429160, &COnscreenTimerEntry::Process, PATCH_JUMP);
|
||||
InjectHook(0x429110, &COnscreenTimerEntry::ProcessForDisplay, PATCH_JUMP);
|
||||
InjectHook(0x429080, &COnscreenTimerEntry::ProcessForDisplayTimer, PATCH_JUMP);
|
||||
InjectHook(0x4290F0, &COnscreenTimerEntry::ProcessForDisplayCounter, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x429220, &COnscreenTimer::Init, PATCH_JUMP);
|
||||
InjectHook(0x429320, &COnscreenTimer::Process, PATCH_JUMP);
|
||||
InjectHook(0x4292E0, &COnscreenTimer::ProcessForDisplay, PATCH_JUMP);
|
||||
InjectHook(0x429450, &COnscreenTimer::ClearCounter, PATCH_JUMP);
|
||||
InjectHook(0x429410, &COnscreenTimer::ClearClock, PATCH_JUMP);
|
||||
InjectHook(0x4293B0, &COnscreenTimer::AddCounter, PATCH_JUMP);
|
||||
InjectHook(0x429350, &COnscreenTimer::AddClock, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
64
src/core/User.h
Normal file
64
src/core/User.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
class COnscreenTimerEntry
|
||||
{
|
||||
public:
|
||||
uint32 m_nTimerOffset;
|
||||
uint32 m_nCounterOffset;
|
||||
char m_aTimerText[10];
|
||||
char m_aCounterText[10];
|
||||
uint16 m_nType;
|
||||
char m_bCounterBuffer[42];
|
||||
char m_bTimerBuffer[42];
|
||||
bool m_bTimerProcessed;
|
||||
bool m_bCounterProcessed;
|
||||
|
||||
void Process();
|
||||
bool ProcessForDisplay();
|
||||
|
||||
int ProcessForDisplayTimer();
|
||||
int ProcessForDisplayCounter();
|
||||
};
|
||||
|
||||
static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");
|
||||
|
||||
class COnscreenTimer
|
||||
{
|
||||
public:
|
||||
COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
|
||||
bool m_bProcessed;
|
||||
bool m_bDisabled;
|
||||
|
||||
void Init();
|
||||
void Process();
|
||||
void ProcessForDisplay();
|
||||
|
||||
void ClearCounter(uint32 offset);
|
||||
void ClearClock(uint32 offset);
|
||||
|
||||
void AddCounter(uint32 offset, uint16 type, char* text);
|
||||
void AddClock(uint32 offset, char* text);
|
||||
};
|
||||
|
||||
static_assert(sizeof(COnscreenTimer) == 0x78, "COnscreenTimer: error");
|
||||
|
||||
class CPlaceName
|
||||
{
|
||||
};
|
||||
|
||||
class CCurrentVehicle
|
||||
{
|
||||
};
|
||||
|
||||
class CPager
|
||||
{
|
||||
};
|
||||
|
||||
class CUserDisplay
|
||||
{
|
||||
public:
|
||||
static CPlaceName &PlaceName;
|
||||
static COnscreenTimer &OnscnTimer;
|
||||
static CPager &Pager;
|
||||
static CCurrentVehicle &CurrentVehicle;
|
||||
};
|
||||
129
src/core/Wanted.cpp
Normal file
129
src/core/Wanted.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Wanted.h"
|
||||
|
||||
int32 &CWanted::MaximumWantedLevel = *(int32*)0x5F7714;
|
||||
|
||||
bool CWanted::AreSwatRequired()
|
||||
{
|
||||
return m_nWantedLevel >= 4;
|
||||
}
|
||||
|
||||
bool CWanted::AreFbiRequired()
|
||||
{
|
||||
return m_nWantedLevel >= 5;
|
||||
}
|
||||
|
||||
bool CWanted::AreArmyRequired()
|
||||
{
|
||||
return m_nWantedLevel >= 6;
|
||||
}
|
||||
|
||||
int CWanted::NumOfHelisRequired()
|
||||
{
|
||||
if (m_IsIgnoredByCops)
|
||||
return 0;
|
||||
|
||||
// Return value is number of helicopters, no need to name them.
|
||||
switch (m_nWantedLevel) {
|
||||
case WANTEDLEVEL_3:
|
||||
case WANTEDLEVEL_4:
|
||||
return 1;
|
||||
case WANTEDLEVEL_5:
|
||||
case WANTEDLEVEL_6:
|
||||
return 2;
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
void CWanted::SetWantedLevel(int32 level)
|
||||
{
|
||||
ClearQdCrimes();
|
||||
switch (level) {
|
||||
case NOTWANTED:
|
||||
m_nChaos = 0;
|
||||
break;
|
||||
case WANTEDLEVEL_1:
|
||||
m_nChaos = 60;
|
||||
break;
|
||||
case WANTEDLEVEL_2:
|
||||
m_nChaos = 220;
|
||||
break;
|
||||
case WANTEDLEVEL_3:
|
||||
m_nChaos = 420;
|
||||
break;
|
||||
case WANTEDLEVEL_4:
|
||||
m_nChaos = 820;
|
||||
break;
|
||||
case WANTEDLEVEL_5:
|
||||
m_nChaos = 1620;
|
||||
break;
|
||||
case WANTEDLEVEL_6:
|
||||
m_nChaos = 3220;
|
||||
break;
|
||||
default:
|
||||
if (level > MaximumWantedLevel)
|
||||
m_nChaos = MaximumWantedLevel;
|
||||
break;
|
||||
}
|
||||
UpdateWantedLevel();
|
||||
}
|
||||
|
||||
void CWanted::ClearQdCrimes()
|
||||
{
|
||||
for (int i = 0; i < 16; i++) {
|
||||
m_sCrimes[i].m_eCrimeType = CRIME_NONE;
|
||||
};
|
||||
}
|
||||
|
||||
void CWanted::UpdateWantedLevel()
|
||||
{
|
||||
int32 CurrWantedLevel = m_nWantedLevel;
|
||||
|
||||
if (m_nChaos >= 0 && m_nChaos < 40) {
|
||||
m_nWantedLevel = NOTWANTED;
|
||||
m_MaximumLawEnforcerVehicles = 0;
|
||||
m_MaxCops = 0;
|
||||
m_RoadblockDensity = 0;
|
||||
}
|
||||
else if (m_nChaos >= 40 && m_nChaos < 200) {
|
||||
m_nWantedLevel = WANTEDLEVEL_1;
|
||||
m_MaximumLawEnforcerVehicles = 1;
|
||||
m_MaxCops = 1;
|
||||
m_RoadblockDensity = 0;
|
||||
}
|
||||
else if (m_nChaos >= 200 && m_nChaos < 400) {
|
||||
m_nWantedLevel = WANTEDLEVEL_2;
|
||||
m_MaximumLawEnforcerVehicles = 2;
|
||||
m_MaxCops = 3;
|
||||
m_RoadblockDensity = 0;
|
||||
}
|
||||
else if (m_nChaos >= 400 && m_nChaos < 800) {
|
||||
m_nWantedLevel = WANTEDLEVEL_3;
|
||||
m_MaximumLawEnforcerVehicles = 2;
|
||||
m_MaxCops = 4;
|
||||
m_RoadblockDensity = 4;
|
||||
}
|
||||
else if (m_nChaos >= 800 && m_nChaos < 1600) {
|
||||
m_nWantedLevel = WANTEDLEVEL_4;
|
||||
m_MaximumLawEnforcerVehicles = 2;
|
||||
m_MaxCops = 6;
|
||||
m_RoadblockDensity = 8;
|
||||
}
|
||||
else if (m_nChaos >= 1600 && m_nChaos < 3200) {
|
||||
m_nWantedLevel = WANTEDLEVEL_5;
|
||||
m_MaximumLawEnforcerVehicles = 3;
|
||||
m_MaxCops = 8;
|
||||
m_RoadblockDensity = 10;
|
||||
}
|
||||
else if (m_nChaos >= 3200) {
|
||||
m_nWantedLevel = WANTEDLEVEL_6;
|
||||
m_MaximumLawEnforcerVehicles = 3;
|
||||
m_MaxCops = 10;
|
||||
m_RoadblockDensity = 12;
|
||||
}
|
||||
|
||||
if (CurrWantedLevel != m_nWantedLevel)
|
||||
m_nLastWantedLevelChange = CTimer::GetTimeInMilliseconds();
|
||||
}
|
||||
49
src/core/Wanted.h
Normal file
49
src/core/Wanted.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
#include "Entity.h"
|
||||
#include "math/Vector.h"
|
||||
#include "CopPed.h"
|
||||
|
||||
enum eWantedLevel {
|
||||
NOTWANTED,
|
||||
WANTEDLEVEL_1,
|
||||
WANTEDLEVEL_2,
|
||||
WANTEDLEVEL_3,
|
||||
WANTEDLEVEL_4,
|
||||
WANTEDLEVEL_5,
|
||||
WANTEDLEVEL_6,
|
||||
};
|
||||
|
||||
class CWanted
|
||||
{
|
||||
public:
|
||||
int32 m_nChaos;
|
||||
int32 m_nLastUpdateTime;
|
||||
int32 m_nLastWantedLevelChange;
|
||||
float m_fCrimeSensitivity;
|
||||
uint8 m_CurrentCops;
|
||||
uint8 m_MaxCops;
|
||||
uint8 m_MaximumLawEnforcerVehicles;
|
||||
int8 field_19;
|
||||
int16 m_RoadblockDensity;
|
||||
uint8 m_IsIgnoredByCops : 1;
|
||||
uint8 m_IsIgnoredByEveryOne : 1;
|
||||
uint8 m_IsSwatRequired : 1;
|
||||
uint8 m_IsFbiRequired : 1;
|
||||
uint8 m_IdArmyRequired : 1;
|
||||
int8 field_23;
|
||||
int32 m_nWantedLevel;
|
||||
CCrime m_sCrimes[16];
|
||||
CCopPed *m_pCops[10];
|
||||
static int32 &MaximumWantedLevel;
|
||||
|
||||
public:
|
||||
bool AreSwatRequired();
|
||||
bool AreFbiRequired();
|
||||
bool AreArmyRequired();
|
||||
int NumOfHelisRequired();
|
||||
void SetWantedLevel(int32);
|
||||
void ClearQdCrimes();
|
||||
void UpdateWantedLevel();
|
||||
};
|
||||
|
||||
static_assert(sizeof(CWanted) == 0x204, "CWanted: error");
|
||||
718
src/core/World.cpp
Normal file
718
src/core/World.cpp
Normal file
@@ -0,0 +1,718 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Entity.h"
|
||||
#include "Ped.h"
|
||||
#include "PlayerPed.h"
|
||||
#include "Vehicle.h"
|
||||
#include "Object.h"
|
||||
#include "Camera.h"
|
||||
#include "DMAudio.h"
|
||||
#include "CarCtrl.h"
|
||||
#include "Garages.h"
|
||||
#include "TempColModels.h"
|
||||
#include "World.h"
|
||||
|
||||
CPtrList *CWorld::ms_bigBuildingsList = (CPtrList*)0x6FAB60;
|
||||
CPtrList &CWorld::ms_listMovingEntityPtrs = *(CPtrList*)0x8F433C;
|
||||
CSector (*CWorld::ms_aSectors)[NUMSECTORS_X] = (CSector (*)[NUMSECTORS_Y])0x665608;
|
||||
uint16 &CWorld::ms_nCurrentScanCode = *(uint16*)0x95CC64;
|
||||
|
||||
uint8 &CWorld::PlayerInFocus = *(uint8 *)0x95CD61;
|
||||
CPlayerInfo *CWorld::Players = (CPlayerInfo *)0x9412F0;
|
||||
bool &CWorld::bNoMoreCollisionTorque = *(bool*)0x95CDCC;
|
||||
CEntity *&CWorld::pIgnoreEntity = *(CEntity**)0x8F6494;
|
||||
bool &CWorld::bIncludeDeadPeds = *(bool*)0x95CD8F;
|
||||
bool &CWorld::bSecondShift = *(bool*)0x95CD54;
|
||||
bool &CWorld::bForceProcessControl = *(bool*)0x95CD6C;
|
||||
bool &CWorld::bProcessCutsceneOnly = *(bool*)0x95CD8B;
|
||||
|
||||
void
|
||||
CWorld::Add(CEntity *ent)
|
||||
{
|
||||
if(ent->IsVehicle() || ent->IsPed())
|
||||
DMAudio.SetEntityStatus(((CPhysical*)ent)->m_audioEntityId, true);
|
||||
|
||||
if(ent->bIsBIGBuilding)
|
||||
ms_bigBuildingsList[ent->m_level].InsertItem(ent);
|
||||
else
|
||||
ent->Add();
|
||||
|
||||
if(ent->IsBuilding() || ent->IsDummy())
|
||||
return;
|
||||
|
||||
if(!ent->bIsStatic)
|
||||
((CPhysical*)ent)->AddToMovingList();
|
||||
}
|
||||
|
||||
void
|
||||
CWorld::Remove(CEntity *ent)
|
||||
{
|
||||
if(ent->IsVehicle() || ent->IsPed())
|
||||
DMAudio.SetEntityStatus(((CPhysical*)ent)->m_audioEntityId, false);
|
||||
|
||||
if(ent->bIsBIGBuilding)
|
||||
ms_bigBuildingsList[ent->m_level].RemoveItem(ent);
|
||||
else
|
||||
ent->Remove();
|
||||
|
||||
if(ent->IsBuilding() || ent->IsDummy())
|
||||
return;
|
||||
|
||||
if(!ent->bIsStatic)
|
||||
((CPhysical*)ent)->RemoveFromMovingList();
|
||||
}
|
||||
|
||||
void
|
||||
CWorld::ClearScanCodes(void)
|
||||
{
|
||||
CPtrNode *node;
|
||||
for(int i = 0; i < NUMSECTORS_Y; i++)
|
||||
for(int j = 0; j < NUMSECTORS_X; j++){
|
||||
CSector *s = &ms_aSectors[i][j];
|
||||
for(node = s->m_lists[ENTITYLIST_BUILDINGS].first; node; node = node->next)
|
||||
((CEntity*)node->item)->m_scanCode = 0;
|
||||
for(node = s->m_lists[ENTITYLIST_VEHICLES].first; node; node = node->next)
|
||||
((CEntity*)node->item)->m_scanCode = 0;
|
||||
for(node = s->m_lists[ENTITYLIST_PEDS].first; node; node = node->next)
|
||||
((CEntity*)node->item)->m_scanCode = 0;
|
||||
for(node = s->m_lists[ENTITYLIST_OBJECTS].first; node; node = node->next)
|
||||
((CEntity*)node->item)->m_scanCode = 0;
|
||||
for(node = s->m_lists[ENTITYLIST_DUMMIES].first; node; node = node->next)
|
||||
((CEntity*)node->item)->m_scanCode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CWorld::CameraToIgnoreThisObject(CEntity *ent)
|
||||
{
|
||||
if(CGarages::IsModelIndexADoor(ent->GetModelIndex()))
|
||||
return false;
|
||||
return ((CObject*)ent)->m_bCameraToAvoidThisObject != 1;
|
||||
}
|
||||
|
||||
bool
|
||||
CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
|
||||
{
|
||||
int x, xstart, xend;
|
||||
int y, ystart, yend;
|
||||
int y1, y2;
|
||||
float dist;
|
||||
|
||||
AdvanceCurrentScanCode();
|
||||
|
||||
entity = nil;
|
||||
dist = 1.0f;
|
||||
|
||||
xstart = GetSectorIndexX(point1.x);
|
||||
ystart = GetSectorIndexX(point1.y);
|
||||
xend = GetSectorIndexX(point2.x);
|
||||
yend = GetSectorIndexX(point2.y);
|
||||
|
||||
#define LOSARGS CColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects
|
||||
|
||||
if(xstart == xend && ystart == yend){
|
||||
// Only one sector
|
||||
return ProcessLineOfSightSector(*GetSector(xstart, ystart), LOSARGS);
|
||||
}else if(xstart == xend){
|
||||
// Only step in y
|
||||
if(ystart < yend)
|
||||
for(y = ystart; y <= yend; y++)
|
||||
ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
|
||||
else
|
||||
for(y = ystart; y >= yend; y--)
|
||||
ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
|
||||
return dist < 1.0f;
|
||||
}else if(ystart == yend){
|
||||
// Only step in x
|
||||
if(xstart < xend)
|
||||
for(x = xstart; x <= xend; x++)
|
||||
ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS);
|
||||
else
|
||||
for(x = xstart; x >= xend; x--)
|
||||
ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS);
|
||||
return dist < 1.0f;
|
||||
}else{
|
||||
if(point1.x < point2.x){
|
||||
// Step from left to right
|
||||
float m = (point2.y - point1.y) / (point2.x - point1.x);
|
||||
|
||||
y1 = ystart;
|
||||
y2 = GetSectorIndexY((GetWorldX(xstart+1) - point1.x)*m + point1.y);
|
||||
if(y1 < y2)
|
||||
for(y = y1; y <= y2; y++)
|
||||
ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
|
||||
else
|
||||
for(y = y1; y >= y2; y--)
|
||||
ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
|
||||
|
||||
for(x = xstart+1; x < xend; x++){
|
||||
y1 = y2;
|
||||
y2 = GetSectorIndexY((GetWorldX(x+1) - point1.x)*m + point1.y);
|
||||
if(y1 < y2)
|
||||
for(y = y1; y <= y2; y++)
|
||||
ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
|
||||
else
|
||||
for(y = y1; y >= y2; y--)
|
||||
ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
|
||||
}
|
||||
|
||||
y1 = y2;
|
||||
y2 = yend;
|
||||
if(y1 < y2)
|
||||
for(y = y1; y <= y2; y++)
|
||||
ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
|
||||
else
|
||||
for(y = y1; y >= y2; y--)
|
||||
ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
|
||||
}else{
|
||||
// Step from right to left
|
||||
float m = (point2.y - point1.y) / (point2.x - point1.x);
|
||||
|
||||
y1 = ystart;
|
||||
y2 = GetSectorIndexY((GetWorldX(xstart) - point1.x)*m + point1.y);
|
||||
if(y1 < y2)
|
||||
for(y = y1; y <= y2; y++)
|
||||
ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
|
||||
else
|
||||
for(y = y1; y >= y2; y--)
|
||||
ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
|
||||
|
||||
for(x = xstart-1; x > xend; x--){
|
||||
y1 = y2;
|
||||
y2 = GetSectorIndexY((GetWorldX(x) - point1.x)*m + point1.y);
|
||||
if(y1 < y2)
|
||||
for(y = y1; y <= y2; y++)
|
||||
ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
|
||||
else
|
||||
for(y = y1; y >= y2; y--)
|
||||
ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
|
||||
}
|
||||
|
||||
y1 = y2;
|
||||
y2 = yend;
|
||||
if(y1 < y2)
|
||||
for(y = y1; y <= y2; y++)
|
||||
ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
|
||||
else
|
||||
for(y = y1; y >= y2; y--)
|
||||
ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
|
||||
}
|
||||
return dist < 1.0f;
|
||||
}
|
||||
|
||||
#undef LOSARGS
|
||||
}
|
||||
|
||||
bool
|
||||
CWorld::ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
|
||||
{
|
||||
float mindist = dist;
|
||||
bool deadPeds = !!bIncludeDeadPeds;
|
||||
bIncludeDeadPeds = false;
|
||||
|
||||
if(checkBuildings){
|
||||
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity, ignoreSeeThrough);
|
||||
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough);
|
||||
}
|
||||
|
||||
if(checkVehicles){
|
||||
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity, ignoreSeeThrough);
|
||||
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity, ignoreSeeThrough);
|
||||
}
|
||||
|
||||
if(checkPeds){
|
||||
if(deadPeds)
|
||||
bIncludeDeadPeds = true;
|
||||
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity, ignoreSeeThrough);
|
||||
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough);
|
||||
bIncludeDeadPeds = false;
|
||||
}
|
||||
|
||||
if(checkObjects){
|
||||
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity, ignoreSeeThrough, ignoreSomeObjects);
|
||||
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, ignoreSomeObjects);
|
||||
}
|
||||
|
||||
if(checkDummies){
|
||||
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity, ignoreSeeThrough);
|
||||
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity, ignoreSeeThrough);
|
||||
}
|
||||
|
||||
bIncludeDeadPeds = deadPeds;
|
||||
|
||||
if(mindist < dist){
|
||||
dist = mindist;
|
||||
return true;
|
||||
}else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects)
|
||||
{
|
||||
bool deadPeds = false;
|
||||
float mindist = dist;
|
||||
CPtrNode *node;
|
||||
CEntity *e;
|
||||
CColModel *colmodel;
|
||||
|
||||
if(list.first && bIncludeDeadPeds && ((CEntity*)list.first->item)->IsPed())
|
||||
deadPeds = true;
|
||||
|
||||
for(node = list.first; node; node = node->next){
|
||||
e = (CEntity*)node->item;
|
||||
if(e->m_scanCode != GetCurrentScanCode() &&
|
||||
e != pIgnoreEntity &&
|
||||
(e->bUsesCollision || deadPeds) &&
|
||||
!(ignoreSomeObjects && CameraToIgnoreThisObject(e))){
|
||||
colmodel = nil;
|
||||
e->m_scanCode = GetCurrentScanCode();
|
||||
|
||||
if(e->IsPed()){
|
||||
if(e->bUsesCollision ||
|
||||
deadPeds && ((CPed*)e)->m_nPedState == PED_DEAD){
|
||||
if(((CPed*)e)->UseGroundColModel())
|
||||
colmodel = &CTempColModels::ms_colModelPedGroundHit;
|
||||
else
|
||||
colmodel = ((CPedModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()))->GetHitColModel();
|
||||
}else
|
||||
colmodel = nil;
|
||||
}else if(e->bUsesCollision)
|
||||
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
|
||||
|
||||
if(colmodel &&
|
||||
CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, dist, ignoreSeeThrough))
|
||||
entity = e;
|
||||
}
|
||||
}
|
||||
|
||||
if(mindist < dist){
|
||||
dist = mindist;
|
||||
return true;
|
||||
}else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CWorld::ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly)
|
||||
{
|
||||
AdvanceCurrentScanCode();
|
||||
CVector point2(point1.x, point1.y, z2);
|
||||
return CWorld::ProcessVerticalLineSector(*GetSector(GetSectorIndexX(point1.x), GetSectorIndexX(point1.y)),
|
||||
CColLine(point1, point2), point, entity,
|
||||
checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, poly);
|
||||
}
|
||||
|
||||
bool
|
||||
CWorld::ProcessVerticalLineSector(CSector §or, const CColLine &line, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly)
|
||||
{
|
||||
float mindist = 1.0f;
|
||||
|
||||
if(checkBuildings){
|
||||
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity, ignoreSeeThrough, poly);
|
||||
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, poly);
|
||||
}
|
||||
|
||||
if(checkVehicles){
|
||||
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity, ignoreSeeThrough, poly);
|
||||
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, poly);
|
||||
}
|
||||
|
||||
if(checkPeds){
|
||||
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity, ignoreSeeThrough, poly);
|
||||
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, poly);
|
||||
}
|
||||
|
||||
if(checkObjects){
|
||||
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity, ignoreSeeThrough, poly);
|
||||
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, poly);
|
||||
}
|
||||
|
||||
if(checkDummies){
|
||||
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity, ignoreSeeThrough, poly);
|
||||
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, poly);
|
||||
}
|
||||
|
||||
return mindist < 1.0f;
|
||||
}
|
||||
|
||||
bool
|
||||
CWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly)
|
||||
{
|
||||
float mindist = dist;
|
||||
CPtrNode *node;
|
||||
CEntity *e;
|
||||
CColModel *colmodel;
|
||||
|
||||
for(node = list.first; node; node = node->next){
|
||||
e = (CEntity*)node->item;
|
||||
if(e->m_scanCode != GetCurrentScanCode() &&
|
||||
e->bUsesCollision){
|
||||
e->m_scanCode = GetCurrentScanCode();
|
||||
|
||||
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
|
||||
if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, dist, ignoreSeeThrough, poly))
|
||||
entity = e;
|
||||
}
|
||||
}
|
||||
|
||||
if(mindist < dist){
|
||||
dist = mindist;
|
||||
return true;
|
||||
}else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
|
||||
{
|
||||
int x, xstart, xend;
|
||||
int y, ystart, yend;
|
||||
int y1, y2;
|
||||
|
||||
AdvanceCurrentScanCode();
|
||||
|
||||
xstart = GetSectorIndexX(point1.x);
|
||||
ystart = GetSectorIndexX(point1.y);
|
||||
xend = GetSectorIndexX(point2.x);
|
||||
yend = GetSectorIndexX(point2.y);
|
||||
|
||||
#define LOSARGS CColLine(point1, point2), checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects
|
||||
|
||||
if(xstart == xend && ystart == yend){
|
||||
// Only one sector
|
||||
return GetIsLineOfSightSectorClear(*GetSector(xstart, ystart), LOSARGS);
|
||||
}else if(xstart == xend){
|
||||
// Only step in y
|
||||
if(ystart < yend){
|
||||
for(y = ystart; y <= yend; y++)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
|
||||
return false;
|
||||
}else{
|
||||
for(y = ystart; y >= yend; y--)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
|
||||
return false;
|
||||
}
|
||||
}else if(ystart == yend){
|
||||
// Only step in x
|
||||
if(xstart < xend){
|
||||
for(x = xstart; x <= xend; x++)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS))
|
||||
return false;
|
||||
}else{
|
||||
for(x = xstart; x >= xend; x--)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS))
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if(point1.x < point2.x){
|
||||
// Step from left to right
|
||||
float m = (point2.y - point1.y) / (point2.x - point1.x);
|
||||
|
||||
y1 = ystart;
|
||||
y2 = GetSectorIndexY((GetWorldX(xstart+1) - point1.x)*m + point1.y);
|
||||
if(y1 < y2){
|
||||
for(y = y1; y <= y2; y++)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
|
||||
return false;
|
||||
}else{
|
||||
for(y = y1; y >= y2; y--)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
|
||||
return false;
|
||||
}
|
||||
|
||||
for(x = xstart+1; x < xend; x++){
|
||||
y1 = y2;
|
||||
y2 = GetSectorIndexY((GetWorldX(x+1) - point1.x)*m + point1.y);
|
||||
if(y1 < y2){
|
||||
for(y = y1; y <= y2; y++)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
|
||||
return false;
|
||||
}else{
|
||||
for(y = y1; y >= y2; y--)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
y1 = y2;
|
||||
y2 = yend;
|
||||
if(y1 < y2){
|
||||
for(y = y1; y <= y2; y++)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS))
|
||||
return false;
|
||||
}else{
|
||||
for(y = y1; y >= y2; y--)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS))
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
// Step from right to left
|
||||
float m = (point2.y - point1.y) / (point2.x - point1.x);
|
||||
|
||||
y1 = ystart;
|
||||
y2 = GetSectorIndexY((GetWorldX(xstart) - point1.x)*m + point1.y);
|
||||
if(y1 < y2){
|
||||
for(y = y1; y <= y2; y++)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
|
||||
return false;
|
||||
}else{
|
||||
for(y = y1; y >= y2; y--)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
|
||||
return false;
|
||||
}
|
||||
|
||||
for(x = xstart-1; x > xend; x--){
|
||||
y1 = y2;
|
||||
y2 = GetSectorIndexY((GetWorldX(x) - point1.x)*m + point1.y);
|
||||
if(y1 < y2){
|
||||
for(y = y1; y <= y2; y++)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
|
||||
return false;
|
||||
}else{
|
||||
for(y = y1; y >= y2; y--)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
y1 = y2;
|
||||
y2 = yend;
|
||||
if(y1 < y2){
|
||||
for(y = y1; y <= y2; y++)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS))
|
||||
return false;
|
||||
}else{
|
||||
for(y = y1; y >= y2; y--)
|
||||
if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
#undef LOSARGS
|
||||
}
|
||||
|
||||
bool
|
||||
CWorld::GetIsLineOfSightSectorClear(CSector §or, const CColLine &line, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
|
||||
{
|
||||
if(checkBuildings){
|
||||
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS], line, ignoreSeeThrough))
|
||||
return false;
|
||||
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, ignoreSeeThrough))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(checkVehicles){
|
||||
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES], line, ignoreSeeThrough))
|
||||
return false;
|
||||
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, ignoreSeeThrough))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(checkPeds){
|
||||
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_PEDS], line, ignoreSeeThrough))
|
||||
return false;
|
||||
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, ignoreSeeThrough))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(checkObjects){
|
||||
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS], line, ignoreSeeThrough, ignoreSomeObjects))
|
||||
return false;
|
||||
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, ignoreSeeThrough, ignoreSomeObjects))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(checkDummies){
|
||||
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_DUMMIES], line, ignoreSeeThrough))
|
||||
return false;
|
||||
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, ignoreSeeThrough))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough, bool ignoreSomeObjects)
|
||||
{
|
||||
CPtrNode *node;
|
||||
CEntity *e;
|
||||
CColModel *colmodel;
|
||||
|
||||
for(node = list.first; node; node = node->next){
|
||||
e = (CEntity*)node->item;
|
||||
if(e->m_scanCode != GetCurrentScanCode() &&
|
||||
e->bUsesCollision){
|
||||
|
||||
e->m_scanCode = GetCurrentScanCode();
|
||||
|
||||
if(e != pIgnoreEntity &&
|
||||
!(ignoreSomeObjects && CameraToIgnoreThisObject(e))){
|
||||
|
||||
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
|
||||
|
||||
if(CCollision::TestLineOfSight(line, e->GetMatrix(), *colmodel, ignoreSeeThrough))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float
|
||||
CWorld::FindGroundZForCoord(float x, float y)
|
||||
{
|
||||
CColPoint point;
|
||||
CEntity *ent;
|
||||
if(ProcessVerticalLine(CVector(x, y, 1000.0f), -1000.0f, point, ent, true, false, false, false, true, false, nil))
|
||||
return point.point.z;
|
||||
else
|
||||
return 20.0f;
|
||||
}
|
||||
|
||||
float
|
||||
CWorld::FindGroundZFor3DCoord(float x, float y, float z, bool *found)
|
||||
{
|
||||
CColPoint point;
|
||||
CEntity *ent;
|
||||
if(ProcessVerticalLine(CVector(x, y, z), -1000.0f, point, ent, true, false, false, false, false, false, nil)){
|
||||
if(found)
|
||||
*found = true;
|
||||
return point.point.z;
|
||||
}else{
|
||||
if(found)
|
||||
*found = false;
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
CWorld::FindRoofZFor3DCoord(float x, float y, float z, bool *found)
|
||||
{
|
||||
CColPoint point;
|
||||
CEntity *ent;
|
||||
if(ProcessVerticalLine(CVector(x, y, z), 1000.0f, point, ent, true, false, false, false, true, false, nil)){
|
||||
if(found)
|
||||
*found = true;
|
||||
return point.point.z;
|
||||
}else{
|
||||
if(found == nil)
|
||||
printf("THERE IS NO MAP BELOW THE FOLLOWING COORS:%f %f %f. (FindGroundZFor3DCoord)\n", x, y, z);
|
||||
if(found)
|
||||
*found = false;
|
||||
return 20.0f;
|
||||
}
|
||||
}
|
||||
|
||||
CPlayerPed*
|
||||
FindPlayerPed(void)
|
||||
{
|
||||
return CWorld::Players[CWorld::PlayerInFocus].m_pPed;
|
||||
}
|
||||
|
||||
CVehicle*
|
||||
FindPlayerVehicle(void)
|
||||
{
|
||||
CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
|
||||
if(ped->bInVehicle && ped->m_pMyVehicle)
|
||||
return ped->m_pMyVehicle;
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
CVehicle*
|
||||
FindPlayerTrain(void)
|
||||
{
|
||||
if(FindPlayerVehicle() && FindPlayerVehicle()->IsTrain())
|
||||
return FindPlayerVehicle();
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
CEntity*
|
||||
FindPlayerEntity(void)
|
||||
{
|
||||
CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
|
||||
if(ped->bInVehicle && ped->m_pMyVehicle)
|
||||
return ped->m_pMyVehicle;
|
||||
else
|
||||
return ped;
|
||||
}
|
||||
|
||||
CVector
|
||||
FindPlayerCoors(void)
|
||||
{
|
||||
CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
|
||||
if(ped->bInVehicle && ped->m_pMyVehicle)
|
||||
return ped->m_pMyVehicle->GetPosition();
|
||||
else
|
||||
return ped->GetPosition();
|
||||
}
|
||||
|
||||
CVector&
|
||||
FindPlayerSpeed(void)
|
||||
{
|
||||
CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
|
||||
if(ped->bInVehicle && ped->m_pMyVehicle)
|
||||
return ped->m_pMyVehicle->m_vecMoveSpeed;
|
||||
else
|
||||
return ped->m_vecMoveSpeed;
|
||||
}
|
||||
|
||||
CVector&
|
||||
FindPlayerCentreOfWorld(int32 player)
|
||||
{
|
||||
if(CCarCtrl::bCarsGeneratedAroundCamera)
|
||||
return TheCamera.GetPosition();
|
||||
if(CWorld::Players[player].m_pRemoteVehicle)
|
||||
return CWorld::Players[player].m_pRemoteVehicle->GetPosition();
|
||||
if(FindPlayerVehicle())
|
||||
return FindPlayerVehicle()->GetPosition();
|
||||
return CWorld::Players[player].m_pPed->GetPosition();
|
||||
}
|
||||
|
||||
CVector&
|
||||
FindPlayerCentreOfWorld_NoSniperShift(void)
|
||||
{
|
||||
if(CCarCtrl::bCarsGeneratedAroundCamera)
|
||||
return TheCamera.GetPosition();
|
||||
if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
|
||||
return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetPosition();
|
||||
if(FindPlayerVehicle())
|
||||
return FindPlayerVehicle()->GetPosition();
|
||||
return CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetPosition();
|
||||
}
|
||||
|
||||
float
|
||||
FindPlayerHeading(void)
|
||||
{
|
||||
if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
|
||||
return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetForward().Heading();
|
||||
if(FindPlayerVehicle())
|
||||
return FindPlayerVehicle()->GetForward().Heading();
|
||||
return CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetForward().Heading();
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4AE930, CWorld::Add, PATCH_JUMP);
|
||||
InjectHook(0x4AE9D0, CWorld::Remove, PATCH_JUMP);
|
||||
InjectHook(0x4B1F60, CWorld::ClearScanCodes, PATCH_JUMP);
|
||||
InjectHook(0x4AF970, CWorld::ProcessLineOfSight, PATCH_JUMP);
|
||||
InjectHook(0x4B0A80, CWorld::ProcessLineOfSightSector, PATCH_JUMP);
|
||||
InjectHook(0x4B0C70, CWorld::ProcessLineOfSightSectorList, PATCH_JUMP);
|
||||
InjectHook(0x4B0DE0, CWorld::ProcessVerticalLine, PATCH_JUMP);
|
||||
InjectHook(0x4B0EF0, CWorld::ProcessVerticalLineSector, PATCH_JUMP);
|
||||
InjectHook(0x4B1090, CWorld::ProcessVerticalLineSectorList, PATCH_JUMP);
|
||||
InjectHook(0x4AEAA0, CWorld::GetIsLineOfSightClear, PATCH_JUMP);
|
||||
InjectHook(0x4B2000, CWorld::GetIsLineOfSightSectorClear, PATCH_JUMP);
|
||||
InjectHook(0x4B2160, CWorld::GetIsLineOfSightSectorListClear, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x4B3A80, CWorld::FindGroundZForCoord, PATCH_JUMP);
|
||||
InjectHook(0x4B3AE0, CWorld::FindGroundZFor3DCoord, PATCH_JUMP);
|
||||
InjectHook(0x4B3B50, CWorld::FindRoofZFor3DCoord, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
119
src/core/World.h
Normal file
119
src/core/World.h
Normal file
@@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
|
||||
#include "Game.h"
|
||||
#include "Lists.h"
|
||||
#include "PlayerInfo.h"
|
||||
|
||||
/* Sectors span from -2000 to 2000 in x and y.
|
||||
* With 100x100 sectors, each is 40x40 units. */
|
||||
|
||||
#define SECTOR_SIZE_X (40.0f)
|
||||
#define SECTOR_SIZE_Y (40.0f)
|
||||
|
||||
#define NUMSECTORS_X (100)
|
||||
#define NUMSECTORS_Y (100)
|
||||
|
||||
#define WORLD_SIZE_X (NUMSECTORS_X * SECTOR_SIZE_X)
|
||||
#define WORLD_SIZE_Y (NUMSECTORS_Y * SECTOR_SIZE_Y)
|
||||
|
||||
#define WORLD_MIN_X (-2000.0f)
|
||||
#define WORLD_MIN_Y (-2000.0f)
|
||||
|
||||
#define WORLD_MAX_X (WORLD_MIN_X + WORLD_SIZE_X)
|
||||
#define WORLD_MAX_Y (WORLD_MIN_Y + WORLD_SIZE_Y)
|
||||
|
||||
enum
|
||||
{
|
||||
ENTITYLIST_BUILDINGS,
|
||||
ENTITYLIST_BUILDINGS_OVERLAP,
|
||||
ENTITYLIST_OBJECTS,
|
||||
ENTITYLIST_OBJECTS_OVERLAP,
|
||||
ENTITYLIST_VEHICLES,
|
||||
ENTITYLIST_VEHICLES_OVERLAP,
|
||||
ENTITYLIST_PEDS,
|
||||
ENTITYLIST_PEDS_OVERLAP,
|
||||
ENTITYLIST_DUMMIES,
|
||||
ENTITYLIST_DUMMIES_OVERLAP,
|
||||
|
||||
NUMSECTORENTITYLISTS
|
||||
};
|
||||
|
||||
class CSector
|
||||
{
|
||||
public:
|
||||
CPtrList m_lists[NUMSECTORENTITYLISTS];
|
||||
};
|
||||
static_assert(sizeof(CSector) == 0x28, "CSector: error");
|
||||
|
||||
class CEntity;
|
||||
struct CColPoint;
|
||||
struct CColLine;
|
||||
struct CStoredCollPoly;
|
||||
|
||||
class CWorld
|
||||
{
|
||||
static CPtrList *ms_bigBuildingsList; // [4];
|
||||
static CPtrList &ms_listMovingEntityPtrs;
|
||||
static CSector (*ms_aSectors)[NUMSECTORS_X]; // [NUMSECTORS_Y][NUMSECTORS_X];
|
||||
static uint16 &ms_nCurrentScanCode;
|
||||
|
||||
public:
|
||||
static uint8 &PlayerInFocus;
|
||||
static CPlayerInfo *Players;
|
||||
static CEntity *&pIgnoreEntity;
|
||||
static bool &bIncludeDeadPeds;
|
||||
static bool &bNoMoreCollisionTorque;
|
||||
static bool &bSecondShift;
|
||||
static bool &bForceProcessControl;
|
||||
static bool &bProcessCutsceneOnly;
|
||||
|
||||
static void Remove(CEntity *entity);
|
||||
static void Add(CEntity *entity);
|
||||
|
||||
static CSector *GetSector(int x, int y) { return &ms_aSectors[y][x]; }
|
||||
static CPtrList &GetBigBuildingList(eLevelName i) { return ms_bigBuildingsList[i]; }
|
||||
static CPtrList &GetMovingEntityList(void) { return ms_listMovingEntityPtrs; }
|
||||
static uint16 GetCurrentScanCode(void) { return ms_nCurrentScanCode; }
|
||||
static void AdvanceCurrentScanCode(void){
|
||||
if(++CWorld::ms_nCurrentScanCode == 0){
|
||||
CWorld::ClearScanCodes();
|
||||
CWorld::ms_nCurrentScanCode = 1;
|
||||
}
|
||||
}
|
||||
static void ClearScanCodes(void);
|
||||
|
||||
static bool CameraToIgnoreThisObject(CEntity *ent);
|
||||
|
||||
static bool ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
|
||||
static bool ProcessLineOfSightSector(CSector §or, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
|
||||
static bool ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
|
||||
static bool ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly);
|
||||
static bool ProcessVerticalLineSector(CSector §or, const CColLine &line, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly);
|
||||
static bool ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly);
|
||||
static bool GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
|
||||
static bool GetIsLineOfSightSectorClear(CSector §or, const CColLine &line, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
|
||||
static bool GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
|
||||
|
||||
static float FindGroundZForCoord(float x, float y);
|
||||
static float FindGroundZFor3DCoord(float x, float y, float z, bool *found);
|
||||
static float FindRoofZFor3DCoord(float x, float y, float z, bool *found);
|
||||
|
||||
static float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); }
|
||||
static float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); }
|
||||
static int GetSectorIndexX(float f) { return (int)GetSectorX(f); }
|
||||
static int GetSectorIndexY(float f) { return (int)GetSectorY(f); }
|
||||
static float GetWorldX(int x) { return x*SECTOR_SIZE_X + WORLD_MIN_X; }
|
||||
static float GetWorldY(int y) { return y*SECTOR_SIZE_Y + WORLD_MIN_Y; }
|
||||
};
|
||||
|
||||
class CPlayerPed;
|
||||
class CVehicle;
|
||||
CPlayerPed *FindPlayerPed(void);
|
||||
CVehicle *FindPlayerVehicle(void);
|
||||
CVehicle *FindPlayerTrain(void);
|
||||
CEntity *FindPlayerEntity(void);
|
||||
CVector FindPlayerCoors(void);
|
||||
CVector &FindPlayerSpeed(void);
|
||||
CVector &FindPlayerCentreOfWorld(int32 player);
|
||||
CVector &FindPlayerCentreOfWorld_NoSniperShift(void);
|
||||
float FindPlayerHeading(void);
|
||||
370
src/core/ZoneCull.cpp
Normal file
370
src/core/ZoneCull.cpp
Normal file
@@ -0,0 +1,370 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Building.h"
|
||||
#include "Treadable.h"
|
||||
#include "Train.h"
|
||||
#include "Pools.h"
|
||||
#include "Timer.h"
|
||||
#include "Camera.h"
|
||||
#include "World.h"
|
||||
#include "FileMgr.h"
|
||||
#include "ZoneCull.h"
|
||||
|
||||
int32 &CCullZones::NumCullZones = *(int*)0x8F2564;
|
||||
CCullZone *CCullZones::aZones = (CCullZone*)0x864750; // [NUMCULLZONES];
|
||||
int32 &CCullZones::NumAttributeZones = *(int*)0x8E29D0;
|
||||
CAttributeZone *CCullZones::aAttributeZones = (CAttributeZone*)0x709C60; // [NUMATTRIBZONES];
|
||||
uint16 *CCullZones::aIndices = (uint16*)0x847330; // [NUMZONEINDICES];
|
||||
int16 *CCullZones::aPointersToBigBuildingsForBuildings = (int16*)0x86C9D0; // [NUMBUILDINGS];
|
||||
int16 *CCullZones::aPointersToBigBuildingsForTreadables = (int16*)0x8F1B8C; // [NUMTREADABLES];
|
||||
|
||||
int32 &CCullZones::CurrentWantedLevelDrop_Player = *(int32*)0x880DA8;
|
||||
int32 &CCullZones::CurrentFlags_Camera = *(int32*)0x940718;
|
||||
int32 &CCullZones::CurrentFlags_Player = *(int32*)0x9415F0;
|
||||
int32 &CCullZones::OldCullZone = *(int32*)0x8E2C90;
|
||||
int32 &CCullZones::EntityIndicesUsed = *(int32*)0x8F2508;
|
||||
bool &CCullZones::bCurrentSubwayIsInvisible = *(bool*)0x95CDA5;
|
||||
bool &CCullZones::bCullZonesDisabled = *(bool*)0x95CD4A;
|
||||
|
||||
|
||||
void
|
||||
CCullZones::Init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
NumAttributeZones = 0;
|
||||
NumCullZones = 0;
|
||||
CurrentWantedLevelDrop_Player = 0;
|
||||
CurrentFlags_Camera = 0;
|
||||
CurrentFlags_Player = 0;
|
||||
OldCullZone = -1;
|
||||
EntityIndicesUsed = 0;
|
||||
bCurrentSubwayIsInvisible = false;
|
||||
|
||||
for(i = 0; i < NUMBUILDINGS; i++)
|
||||
aPointersToBigBuildingsForBuildings[i] = -1;
|
||||
for(i = 0; i < NUMTREADABLES; i++)
|
||||
aPointersToBigBuildingsForTreadables[i] = -1;
|
||||
}
|
||||
|
||||
void
|
||||
CCullZones::ResolveVisibilities(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
CFileMgr::SetDir("");
|
||||
fd = CFileMgr::OpenFile("DATA\\cullzone.dat", "rb");
|
||||
if(fd > 0){
|
||||
CFileMgr::Read(fd, (char*)&NumCullZones, 4);
|
||||
CFileMgr::Read(fd, (char*)aZones, NUMCULLZONES*sizeof(CCullZone));
|
||||
CFileMgr::Read(fd, (char*)&NumAttributeZones, 4);
|
||||
CFileMgr::Read(fd, (char*)aAttributeZones, NUMATTRIBZONES*sizeof(CAttributeZone));
|
||||
CFileMgr::Read(fd, (char*)aIndices, NUMZONEINDICES*2);
|
||||
CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForBuildings, NUMBUILDINGS*2);
|
||||
CFileMgr::Read(fd, (char*)aPointersToBigBuildingsForTreadables, NUMTREADABLES*2);
|
||||
CFileMgr::CloseFile(fd);
|
||||
}else{
|
||||
// TODO: implement code from mobile to generate data here
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CCullZones::Update(void)
|
||||
{
|
||||
bool invisible;
|
||||
|
||||
if(bCullZonesDisabled)
|
||||
return;
|
||||
|
||||
switch(CTimer::GetFrameCounter() & 7){
|
||||
case 0:
|
||||
case 4:
|
||||
/* Update Cull zone */
|
||||
ForceCullZoneCoors(TheCamera.GetGameCamPosition());
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* Update camera attributes */
|
||||
CurrentFlags_Camera = FindAttributesForCoors(TheCamera.GetGameCamPosition(), nil);
|
||||
invisible = (CurrentFlags_Camera & ATTRZONE_SUBWAYVISIBLE) == 0;
|
||||
if(invisible != bCurrentSubwayIsInvisible){
|
||||
MarkSubwayAsInvisible(!invisible);
|
||||
bCurrentSubwayIsInvisible = invisible;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
/* Update player attributes */
|
||||
CurrentFlags_Player = FindAttributesForCoors(FindPlayerCoors(),
|
||||
&CurrentWantedLevelDrop_Player);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CCullZones::ForceCullZoneCoors(CVector coors)
|
||||
{
|
||||
int32 z;
|
||||
z = FindCullZoneForCoors(coors);
|
||||
if(z != OldCullZone){
|
||||
if(OldCullZone >= 0)
|
||||
aZones[OldCullZone].DoStuffLeavingZone();
|
||||
if(z >= 0)
|
||||
aZones[z].DoStuffEnteringZone();
|
||||
OldCullZone = z;
|
||||
}
|
||||
}
|
||||
|
||||
int32
|
||||
CCullZones::FindCullZoneForCoors(CVector coors)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < NumCullZones; i++)
|
||||
if(coors.x >= aZones[i].minx && coors.x <= aZones[i].maxx &&
|
||||
coors.y >= aZones[i].miny && coors.y <= aZones[i].maxy &&
|
||||
coors.z >= aZones[i].minz && coors.z <= aZones[i].maxz)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32
|
||||
CCullZones::FindAttributesForCoors(CVector coors, int32 *wantedLevel)
|
||||
{
|
||||
int i;
|
||||
int32 attribs;
|
||||
|
||||
attribs = 0;
|
||||
for(i = 0; i < NumAttributeZones; i++)
|
||||
if(coors.x >= aAttributeZones[i].minx && coors.x <= aAttributeZones[i].maxx &&
|
||||
coors.y >= aAttributeZones[i].miny && coors.y <= aAttributeZones[i].maxy &&
|
||||
coors.z >= aAttributeZones[i].minz && coors.z <= aAttributeZones[i].maxz){
|
||||
attribs |= aAttributeZones[i].attributes;
|
||||
if(wantedLevel && *wantedLevel <= aAttributeZones[i].wantedLevel)
|
||||
*wantedLevel = aAttributeZones[i].wantedLevel;
|
||||
}
|
||||
return attribs;
|
||||
}
|
||||
|
||||
CAttributeZone*
|
||||
CCullZones::FindZoneWithStairsAttributeForPlayer(void)
|
||||
{
|
||||
int i;
|
||||
CVector coors;
|
||||
|
||||
coors = FindPlayerCoors();
|
||||
for(i = 0; i < NumAttributeZones; i++)
|
||||
if(aAttributeZones[i].attributes & ATTRZONE_STAIRS &&
|
||||
coors.x >= aAttributeZones[i].minx && coors.x <= aAttributeZones[i].maxx &&
|
||||
coors.y >= aAttributeZones[i].miny && coors.y <= aAttributeZones[i].maxy &&
|
||||
coors.z >= aAttributeZones[i].minz && coors.z <= aAttributeZones[i].maxz)
|
||||
return &aAttributeZones[i];
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
CCullZones::MarkSubwayAsInvisible(bool visible)
|
||||
{
|
||||
int i, n;
|
||||
CEntity *e;
|
||||
CVehicle *v;
|
||||
|
||||
n = CPools::GetBuildingPool()->GetSize();
|
||||
for(i = 0; i < n; i++){
|
||||
e = CPools::GetBuildingPool()->GetSlot(i);
|
||||
if(e && e->bIsSubway)
|
||||
e->bIsVisible = visible;
|
||||
}
|
||||
|
||||
n = CPools::GetTreadablePool()->GetSize();
|
||||
for(i = 0; i < n; i++){
|
||||
e = CPools::GetTreadablePool()->GetSlot(i);
|
||||
if(e && e->bIsSubway)
|
||||
e->bIsVisible = visible;
|
||||
}
|
||||
|
||||
n = CPools::GetVehiclePool()->GetSize();
|
||||
for(i = 0; i < n; i++){
|
||||
v = CPools::GetVehiclePool()->GetSlot(i);
|
||||
if(v && v->IsTrain() && ((CTrain*)v)->m_trackId != 0)
|
||||
v->bIsVisible = visible;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CCullZones::AddCullZone(CVector const &position,
|
||||
float minx, float maxx,
|
||||
float miny, float maxy,
|
||||
float minz, float maxz,
|
||||
uint16 flag, int16 wantedLevel)
|
||||
{
|
||||
CCullZone *cull;
|
||||
CAttributeZone *attrib;
|
||||
|
||||
CVector v;
|
||||
if((flag & ATTRZONE_NOTCULLZONE) == 0){
|
||||
cull = &aZones[NumCullZones++];
|
||||
v = position;
|
||||
// WTF is this?
|
||||
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)
|
||||
v = CVector(1061.4f, -506.0f, 18.5f);
|
||||
cull->position.x = clamp(v.x, minx, maxx);
|
||||
cull->position.y = clamp(v.y, miny, maxy);
|
||||
cull->position.z = clamp(v.z, minz, maxz);
|
||||
cull->minx = minx;
|
||||
cull->maxx = maxx;
|
||||
cull->miny = miny;
|
||||
cull->maxy = maxy;
|
||||
cull->minz = minz;
|
||||
cull->maxz = maxz;
|
||||
cull->unk2 = 0;
|
||||
cull->unk3 = 0;
|
||||
cull->unk4 = 0;
|
||||
cull->m_indexStart = 0;
|
||||
}
|
||||
if(flag & ~ATTRZONE_NOTCULLZONE){
|
||||
attrib = &aAttributeZones[NumAttributeZones++];
|
||||
attrib->minx = minx;
|
||||
attrib->maxx = maxx;
|
||||
attrib->miny = miny;
|
||||
attrib->maxy = maxy;
|
||||
attrib->minz = minz;
|
||||
attrib->maxz = maxz;
|
||||
attrib->attributes = flag;
|
||||
attrib->wantedLevel = wantedLevel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
CCullZone::DoStuffLeavingZone(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < m_numBuildings; i++)
|
||||
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[m_indexStart + i]);
|
||||
for(; i < m_numBuildings + m_numTreadablesPlus10m + m_numTreadables ; i++)
|
||||
DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[m_indexStart + i]);
|
||||
}
|
||||
|
||||
void
|
||||
CCullZone::DoStuffLeavingZone_OneBuilding(uint16 i)
|
||||
{
|
||||
int16 bb;
|
||||
int j;
|
||||
|
||||
if(i < 6000){
|
||||
CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = false;
|
||||
bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
|
||||
if(bb != -1)
|
||||
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false;
|
||||
}else{
|
||||
i -= 6000;
|
||||
for(j = 0; j < 3; j++)
|
||||
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i)
|
||||
{
|
||||
int16 bb;
|
||||
int j;
|
||||
|
||||
if(i < 6000){
|
||||
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;
|
||||
for(j = 0; j < 3; j++)
|
||||
DoStuffLeavingZone_OneTreadableBoth(CCullZones::aIndices[i+j]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CCullZone::DoStuffEnteringZone(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < m_numBuildings; i++)
|
||||
DoStuffEnteringZone_OneBuilding(CCullZones::aIndices[m_indexStart + i]);
|
||||
for(; i < m_numBuildings + m_numTreadablesPlus10m; i++)
|
||||
DoStuffEnteringZone_OneTreadablePlus10m(CCullZones::aIndices[m_indexStart + i]);
|
||||
for(; i < m_numBuildings + m_numTreadablesPlus10m + m_numTreadables; i++)
|
||||
DoStuffEnteringZone_OneTreadable(CCullZones::aIndices[m_indexStart + i]);
|
||||
}
|
||||
|
||||
void
|
||||
CCullZone::DoStuffEnteringZone_OneBuilding(uint16 i)
|
||||
{
|
||||
int16 bb;
|
||||
int j;
|
||||
|
||||
if(i < 6000){
|
||||
CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = true;
|
||||
bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
|
||||
if(bb != -1)
|
||||
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
|
||||
}else{
|
||||
i -= 6000;
|
||||
for(j = 0; j < 3; j++)
|
||||
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i)
|
||||
{
|
||||
int16 bb;
|
||||
int j;
|
||||
|
||||
if(i < 6000){
|
||||
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;
|
||||
for(j = 0; j < 3; j++)
|
||||
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i)
|
||||
{
|
||||
int16 bb;
|
||||
int j;
|
||||
|
||||
if(i < 6000){
|
||||
CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;;
|
||||
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
|
||||
if(bb != -1)
|
||||
CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
|
||||
}else{
|
||||
i -= 6000;
|
||||
for(j = 0; j < 3; j++)
|
||||
DoStuffLeavingZone_OneBuilding(CCullZones::aIndices[i+j]);
|
||||
}
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x524BC0, &CCullZones::Init, PATCH_JUMP);
|
||||
InjectHook(0x524EC0, &CCullZones::ResolveVisibilities, PATCH_JUMP);
|
||||
InjectHook(0x524F80, &CCullZones::Update, PATCH_JUMP);
|
||||
InjectHook(0x525370, &CCullZones::AddCullZone, PATCH_JUMP);
|
||||
InjectHook(0x5250D0, &CCullZones::ForceCullZoneCoors, PATCH_JUMP);
|
||||
InjectHook(0x525130, &CCullZones::FindCullZoneForCoors, PATCH_JUMP);
|
||||
InjectHook(0x5251C0, &CCullZones::FindAttributesForCoors, PATCH_JUMP);
|
||||
InjectHook(0x525290, &CCullZones::FindZoneWithStairsAttributeForPlayer, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x525610, &CCullZone::DoStuffLeavingZone, PATCH_JUMP);
|
||||
InjectHook(0x525810, &CCullZone::DoStuffEnteringZone, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
94
src/core/ZoneCull.h
Normal file
94
src/core/ZoneCull.h
Normal file
@@ -0,0 +1,94 @@
|
||||
class CCullZone
|
||||
{
|
||||
public:
|
||||
CVector position;
|
||||
float minx;
|
||||
float maxx;
|
||||
float miny;
|
||||
float maxy;
|
||||
float minz;
|
||||
float maxz;
|
||||
|
||||
// TODO: figure these out:
|
||||
int32 m_indexStart;
|
||||
int16 unk2;
|
||||
int16 unk3;
|
||||
int16 unk4;
|
||||
int16 m_numBuildings;
|
||||
int16 m_numTreadablesPlus10m;
|
||||
int16 m_numTreadables;
|
||||
|
||||
void DoStuffLeavingZone(void);
|
||||
static void DoStuffLeavingZone_OneBuilding(uint16 i);
|
||||
static void DoStuffLeavingZone_OneTreadableBoth(uint16 i);
|
||||
void DoStuffEnteringZone(void);
|
||||
static void DoStuffEnteringZone_OneBuilding(uint16 i);
|
||||
static void DoStuffEnteringZone_OneTreadablePlus10m(uint16 i);
|
||||
static void DoStuffEnteringZone_OneTreadable(uint16 i);
|
||||
};
|
||||
|
||||
enum eZoneAttribs
|
||||
{
|
||||
ATTRZONE_CAMCLOSEIN = 1,
|
||||
ATTRZONE_STAIRS = 2,
|
||||
ATTRZONE_1STPERSON = 4,
|
||||
ATTRZONE_NORAIN = 8,
|
||||
ATTRZONE_NOPOLICE = 0x10,
|
||||
ATTRZONE_NOTCULLZONE = 0x20,
|
||||
ATTRZONE_DOINEEDCOLLISION = 0x40,
|
||||
ATTRZONE_SUBWAYVISIBLE = 0x80,
|
||||
};
|
||||
|
||||
struct CAttributeZone
|
||||
{
|
||||
float minx;
|
||||
float maxx;
|
||||
float miny;
|
||||
float maxy;
|
||||
float minz;
|
||||
float maxz;
|
||||
int16 attributes;
|
||||
int16 wantedLevel;
|
||||
};
|
||||
|
||||
class CCullZones
|
||||
{
|
||||
public:
|
||||
static int32 &NumCullZones;
|
||||
static CCullZone *aZones; // [NUMCULLZONES];
|
||||
static int32 &NumAttributeZones;
|
||||
static CAttributeZone *aAttributeZones; // [NUMATTRIBZONES];
|
||||
static uint16 *aIndices; // [NUMZONEINDICES];
|
||||
static int16 *aPointersToBigBuildingsForBuildings; // [NUMBUILDINGS];
|
||||
static int16 *aPointersToBigBuildingsForTreadables; // [NUMTREADABLES];
|
||||
|
||||
static int32 &CurrentWantedLevelDrop_Player;
|
||||
static int32 &CurrentFlags_Camera;
|
||||
static int32 &CurrentFlags_Player;
|
||||
static int32 &OldCullZone;
|
||||
static int32 &EntityIndicesUsed;
|
||||
static bool &bCurrentSubwayIsInvisible;
|
||||
static bool &bCullZonesDisabled;
|
||||
|
||||
static void Init(void);
|
||||
static void ResolveVisibilities(void);
|
||||
static void Update(void);
|
||||
static void ForceCullZoneCoors(CVector coors);
|
||||
static int32 FindCullZoneForCoors(CVector coors);
|
||||
static int32 FindAttributesForCoors(CVector coors, int32 *wantedLevel);
|
||||
static CAttributeZone *FindZoneWithStairsAttributeForPlayer(void);
|
||||
static void MarkSubwayAsInvisible(bool visible);
|
||||
static void AddCullZone(CVector const &position,
|
||||
float minx, float maxx,
|
||||
float miny, float maxy,
|
||||
float minz, float maxz,
|
||||
uint16 flag, int16 wantedLevel);
|
||||
static bool CamCloseInForPlayer(void) { return (CurrentFlags_Player & ATTRZONE_CAMCLOSEIN) != 0; }
|
||||
static bool CamStairsForPlayer(void) { return (CurrentFlags_Player & ATTRZONE_STAIRS) != 0; }
|
||||
static bool Cam1stPersonForPlayer(void) { return (CurrentFlags_Player & ATTRZONE_1STPERSON) != 0; }
|
||||
static bool NoPolice(void) { return (CurrentFlags_Player & ATTRZONE_NOPOLICE) != 0; }
|
||||
static bool DoINeedToLoadCollision(void) { return (CurrentFlags_Player & ATTRZONE_DOINEEDCOLLISION) != 0; }
|
||||
static bool PlayerNoRain(void) { return (CurrentFlags_Player & ATTRZONE_NORAIN) != 0; }
|
||||
static bool CamNoRain(void) { return (CurrentFlags_Camera & ATTRZONE_NORAIN) != 0; }
|
||||
static int32 GetWantedLevelDrop(void) { return CurrentWantedLevelDrop_Player; }
|
||||
};
|
||||
874
src/core/Zones.cpp
Normal file
874
src/core/Zones.cpp
Normal file
@@ -0,0 +1,874 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
|
||||
#include "Zones.h"
|
||||
|
||||
#include "Clock.h"
|
||||
#include "Text.h"
|
||||
#include "World.h"
|
||||
|
||||
eLevelName &CTheZones::m_CurrLevel = *(eLevelName*)0x8F2BC8;
|
||||
CZone *&CTheZones::m_pPlayersZone = *(CZone**)0x8F254C;
|
||||
int16 &CTheZones::FindIndex = *(int16*)0x95CC40;
|
||||
|
||||
uint16 &CTheZones::NumberOfAudioZones = *(uint16*)0x95CC84;
|
||||
int16 *CTheZones::AudioZoneArray = (int16*)0x713BC0;
|
||||
uint16 &CTheZones::TotalNumberOfMapZones = *(uint16*)0x95CC74;
|
||||
uint16 &CTheZones::TotalNumberOfZones = *(uint16*)0x95CC36;
|
||||
CZone *CTheZones::ZoneArray = (CZone*)0x86BEE0;
|
||||
CZone *CTheZones::MapZoneArray = (CZone*)0x663EC0;
|
||||
uint16 &CTheZones::TotalNumberOfZoneInfos = *(uint16*)0x95CC3C;
|
||||
CZoneInfo *CTheZones::ZoneInfoArray = (CZoneInfo*)0x714400;
|
||||
|
||||
#define SWAPF(a, b) { float t; t = a; a = b; b = t; }
|
||||
|
||||
static void
|
||||
CheckZoneInfo(CZoneInfo *info)
|
||||
{
|
||||
assert(info->carThreshold[0] >= 0);
|
||||
assert(info->carThreshold[0] <= info->carThreshold[1]);
|
||||
assert(info->carThreshold[1] <= info->carThreshold[2]);
|
||||
assert(info->carThreshold[2] <= info->carThreshold[3]);
|
||||
assert(info->carThreshold[3] <= info->carThreshold[4]);
|
||||
assert(info->carThreshold[4] <= info->carThreshold[5]);
|
||||
assert(info->carThreshold[5] <= info->copThreshold);
|
||||
assert(info->copThreshold <= info->gangThreshold[0]);
|
||||
assert(info->gangThreshold[0] <= info->gangThreshold[1]);
|
||||
assert(info->gangThreshold[1] <= info->gangThreshold[2]);
|
||||
assert(info->gangThreshold[2] <= info->gangThreshold[3]);
|
||||
assert(info->gangThreshold[3] <= info->gangThreshold[4]);
|
||||
assert(info->gangThreshold[4] <= info->gangThreshold[5]);
|
||||
assert(info->gangThreshold[5] <= info->gangThreshold[6]);
|
||||
assert(info->gangThreshold[6] <= info->gangThreshold[7]);
|
||||
assert(info->gangThreshold[7] <= info->gangThreshold[8]);
|
||||
}
|
||||
|
||||
wchar*
|
||||
CZone::GetTranslatedName(void)
|
||||
{
|
||||
return TheText.Get(name);
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::Init(void)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < NUMAUDIOZONES; i++)
|
||||
AudioZoneArray[i] = -1;
|
||||
NumberOfAudioZones = 0;
|
||||
|
||||
CZoneInfo *zonei;
|
||||
int x = 1000/6;
|
||||
for(i = 0; i < 2*NUMZONES; i++){
|
||||
zonei = &ZoneInfoArray[i];
|
||||
zonei->carDensity = 10;
|
||||
zonei->carThreshold[0] = x;
|
||||
zonei->carThreshold[1] = zonei->carThreshold[0] + x;
|
||||
zonei->carThreshold[2] = zonei->carThreshold[1] + x;
|
||||
zonei->carThreshold[3] = zonei->carThreshold[2] + x;
|
||||
zonei->carThreshold[4] = zonei->carThreshold[3];
|
||||
zonei->carThreshold[5] = zonei->carThreshold[4];
|
||||
zonei->copThreshold = zonei->carThreshold[5] + x;
|
||||
zonei->gangThreshold[0] = zonei->copThreshold;
|
||||
zonei->gangThreshold[1] = zonei->gangThreshold[0];
|
||||
zonei->gangThreshold[2] = zonei->gangThreshold[1];
|
||||
zonei->gangThreshold[3] = zonei->gangThreshold[2];
|
||||
zonei->gangThreshold[4] = zonei->gangThreshold[3];
|
||||
zonei->gangThreshold[5] = zonei->gangThreshold[4];
|
||||
zonei->gangThreshold[6] = zonei->gangThreshold[5];
|
||||
zonei->gangThreshold[7] = zonei->gangThreshold[6];
|
||||
zonei->gangThreshold[8] = zonei->gangThreshold[7];
|
||||
CheckZoneInfo(zonei);
|
||||
}
|
||||
TotalNumberOfZoneInfos = 1; // why 1?
|
||||
|
||||
for(i = 0; i < NUMZONES; i++)
|
||||
memset(&ZoneArray[i], 0, sizeof(CZone));
|
||||
strcpy(ZoneArray[0].name, "CITYZON");
|
||||
ZoneArray[0].minx = -4000.0f;
|
||||
ZoneArray[0].miny = -4000.0f;
|
||||
ZoneArray[0].minz = -500.0f;
|
||||
ZoneArray[0].maxx = 4000.0f;
|
||||
ZoneArray[0].maxy = 4000.0f;
|
||||
ZoneArray[0].maxz = 500.0f;
|
||||
ZoneArray[0].level = LEVEL_NONE;
|
||||
TotalNumberOfZones = 1;
|
||||
|
||||
m_CurrLevel = LEVEL_NONE;
|
||||
m_pPlayersZone = &ZoneArray[0];
|
||||
|
||||
for(i = 0; i < NUMMAPZONES; i++){
|
||||
memset(&MapZoneArray[i], 0, sizeof(CZone));
|
||||
MapZoneArray[i].type = ZONE_MAPZONE;
|
||||
}
|
||||
strcpy(MapZoneArray[0].name, "THEMAP");
|
||||
MapZoneArray[0].minx = -4000.0f;
|
||||
MapZoneArray[0].miny = -4000.0f;
|
||||
MapZoneArray[0].minz = -500.0f;
|
||||
MapZoneArray[0].maxx = 4000.0f;
|
||||
MapZoneArray[0].maxy = 4000.0f;
|
||||
MapZoneArray[0].maxz = 500.0f;
|
||||
MapZoneArray[0].level = LEVEL_NONE;
|
||||
TotalNumberOfMapZones = 1;
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::Update(void)
|
||||
{
|
||||
CVector pos;
|
||||
pos = FindPlayerCoors();
|
||||
m_pPlayersZone = FindSmallestZonePosition(&pos);
|
||||
m_CurrLevel = GetLevelFromPosition(pos);
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::CreateZone(char *name, eZoneType type,
|
||||
float minx, float miny, float minz,
|
||||
float maxx, float maxy, float maxz,
|
||||
eLevelName level)
|
||||
{
|
||||
CZone *zone;
|
||||
char *p;
|
||||
|
||||
if(minx > maxx) SWAPF(minx, maxx);
|
||||
if(miny > maxy) SWAPF(miny, maxy);
|
||||
if(minz > maxz) SWAPF(minz, maxz);
|
||||
|
||||
// make upper case
|
||||
for(p = name; *p; p++) if(islower(*p)) *p = toupper(*p);
|
||||
|
||||
// add zone
|
||||
zone = &ZoneArray[TotalNumberOfZones++];
|
||||
strncpy(zone->name, name, 7);
|
||||
zone->name[7] = '\0';
|
||||
zone->type = type;
|
||||
zone->minx = minx;
|
||||
zone->miny = miny;
|
||||
zone->minz = minz;
|
||||
zone->maxx = maxx;
|
||||
zone->maxy = maxy;
|
||||
zone->maxz = maxz;
|
||||
zone->level = level;
|
||||
if(type == ZONE_AUDIO || type == ZONE_TYPE1 || type == ZONE_TYPE2){
|
||||
zone->zoneinfoDay = TotalNumberOfZoneInfos++;
|
||||
zone->zoneinfoNight = TotalNumberOfZoneInfos++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::CreateMapZone(char *name, eZoneType type,
|
||||
float minx, float miny, float minz,
|
||||
float maxx, float maxy, float maxz,
|
||||
eLevelName level)
|
||||
{
|
||||
CZone *zone;
|
||||
char *p;
|
||||
|
||||
if(minx > maxx) SWAPF(minx, maxx);
|
||||
if(miny > maxy) SWAPF(miny, maxy);
|
||||
if(minz > maxz) SWAPF(minz, maxz);
|
||||
|
||||
// make upper case
|
||||
for(p = name; *p; p++) if(islower(*p)) *p = toupper(*p);
|
||||
|
||||
// add zone
|
||||
zone = &MapZoneArray[TotalNumberOfMapZones++];
|
||||
strncpy(zone->name, name, 7);
|
||||
zone->name[7] = '\0';
|
||||
zone->type = type;
|
||||
zone->minx = minx;
|
||||
zone->miny = miny;
|
||||
zone->minz = minz;
|
||||
zone->maxx = maxx;
|
||||
zone->maxy = maxy;
|
||||
zone->maxz = maxz;
|
||||
zone->level = level;
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::PostZoneCreation(void)
|
||||
{
|
||||
int i;
|
||||
for(i = 1; i < TotalNumberOfZones; i++)
|
||||
InsertZoneIntoZoneHierarchy(&ZoneArray[i]);
|
||||
InitialiseAudioZoneArray();
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::InsertZoneIntoZoneHierarchy(CZone *zone)
|
||||
{
|
||||
zone->child = nil;
|
||||
zone->parent = nil;
|
||||
zone->next = nil;
|
||||
InsertZoneIntoZoneHierRecursive(zone, &ZoneArray[0]);
|
||||
}
|
||||
|
||||
bool
|
||||
CTheZones::InsertZoneIntoZoneHierRecursive(CZone *inner, CZone *outer)
|
||||
{
|
||||
int n;
|
||||
CZone *child, *next, *insert;
|
||||
|
||||
// return false if inner was not inserted into outer
|
||||
if(outer == nil ||
|
||||
!ZoneIsEntirelyContainedWithinOtherZone(inner, outer))
|
||||
return false;
|
||||
|
||||
// try to insert inner into children of outer
|
||||
for(child = outer->child; child; child = child->next)
|
||||
if(InsertZoneIntoZoneHierRecursive(inner, child))
|
||||
return true;
|
||||
|
||||
// insert inner as child of outer
|
||||
// count number of outer's children contained within inner
|
||||
n = 0;
|
||||
for(child = outer->child; child; child = child->next)
|
||||
if(ZoneIsEntirelyContainedWithinOtherZone(child, inner))
|
||||
n++;
|
||||
inner->next = outer->child;
|
||||
inner->parent = outer;
|
||||
outer->child = inner;
|
||||
// move children from outer to inner
|
||||
if(n){
|
||||
insert = inner;
|
||||
for(child = inner->next; child; child = next){
|
||||
next = child->next;
|
||||
if(ZoneIsEntirelyContainedWithinOtherZone(child,inner)){
|
||||
insert->next = child->next;
|
||||
child->parent = inner;
|
||||
child->next = inner->child;
|
||||
inner->child = child;
|
||||
}else
|
||||
insert = child;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CTheZones::ZoneIsEntirelyContainedWithinOtherZone(CZone *inner, CZone *outer)
|
||||
{
|
||||
char tmp[100];
|
||||
|
||||
if(inner->minx < outer->minx ||
|
||||
inner->maxx > outer->maxx ||
|
||||
inner->miny < outer->miny ||
|
||||
inner->maxy > outer->maxy ||
|
||||
inner->minz < outer->minz ||
|
||||
inner->maxz > outer->maxz){
|
||||
CVector vmin(inner->minx, inner->miny, inner->minz);
|
||||
if(PointLiesWithinZone(vmin, outer))
|
||||
sprintf(tmp, "Overlapping zones %s and %s\n",
|
||||
inner->name, outer->name);
|
||||
CVector vmax(inner->maxx, inner->maxy, inner->maxz);
|
||||
if(PointLiesWithinZone(vmax, outer))
|
||||
sprintf(tmp, "Overlapping zones %s and %s\n",
|
||||
inner->name, outer->name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CTheZones::PointLiesWithinZone(const CVector &v, CZone *zone)
|
||||
{
|
||||
return zone->minx <= v.x && v.x <= zone->maxx &&
|
||||
zone->miny <= v.y && v.y <= zone->maxy &&
|
||||
zone->minz <= v.z && v.z <= zone->maxz;
|
||||
}
|
||||
|
||||
eLevelName
|
||||
CTheZones::GetLevelFromPosition(CVector const &v)
|
||||
{
|
||||
int i;
|
||||
// char tmp[116];
|
||||
// if(!PointLiesWithinZone(v, &MapZoneArray[0]))
|
||||
// sprintf(tmp, "x = %.3f y= %.3f z = %.3f\n", v.x, v.y, v.z);
|
||||
for(i = 1; i < TotalNumberOfMapZones; i++)
|
||||
if(PointLiesWithinZone(v, &MapZoneArray[i]))
|
||||
return MapZoneArray[i].level;
|
||||
return MapZoneArray[0].level;
|
||||
}
|
||||
|
||||
CZone*
|
||||
CTheZones::FindSmallestZonePosition(const CVector *v)
|
||||
{
|
||||
CZone *best = &ZoneArray[0];
|
||||
// zone to test next
|
||||
CZone *zone = ZoneArray[0].child;
|
||||
while(zone)
|
||||
// if in zone, descent into children
|
||||
if(PointLiesWithinZone(*v, zone)){
|
||||
best = zone;
|
||||
zone = zone->child;
|
||||
// otherwise try next zone
|
||||
}else
|
||||
zone = zone->next;
|
||||
return best;
|
||||
}
|
||||
|
||||
CZone*
|
||||
CTheZones::FindSmallestZonePositionType(const CVector *v, eZoneType type)
|
||||
{
|
||||
CZone *best = nil;
|
||||
if(ZoneArray[0].type == type)
|
||||
best = &ZoneArray[0];
|
||||
// zone to test next
|
||||
CZone *zone = ZoneArray[0].child;
|
||||
while(zone)
|
||||
// if in zone, descent into children
|
||||
if(PointLiesWithinZone(*v, zone)){
|
||||
if(zone->type == type)
|
||||
best = zone;
|
||||
zone = zone->child;
|
||||
// otherwise try next zone
|
||||
}else
|
||||
zone = zone->next;
|
||||
return best;
|
||||
}
|
||||
|
||||
CZone*
|
||||
CTheZones::FindSmallestZonePositionILN(const CVector *v)
|
||||
{
|
||||
CZone *best = nil;
|
||||
if(ZoneArray[0].type == ZONE_AUDIO ||
|
||||
ZoneArray[0].type == ZONE_TYPE1 ||
|
||||
ZoneArray[0].type == ZONE_TYPE2)
|
||||
best = &ZoneArray[0];
|
||||
// zone to test next
|
||||
CZone *zone = ZoneArray[0].child;
|
||||
while(zone)
|
||||
// if in zone, descent into children
|
||||
if(PointLiesWithinZone(*v, zone)){
|
||||
if(zone->type == ZONE_AUDIO ||
|
||||
zone->type == ZONE_TYPE1 ||
|
||||
zone->type == ZONE_TYPE2)
|
||||
best = zone;
|
||||
zone = zone->child;
|
||||
// otherwise try next zone
|
||||
}else
|
||||
zone = zone->next;
|
||||
return best;
|
||||
}
|
||||
|
||||
int16
|
||||
CTheZones::FindZoneByLabelAndReturnIndex(char *name)
|
||||
{
|
||||
char str[8];
|
||||
memset(str, 0, 8);
|
||||
strncpy(str, name, 8);
|
||||
for(FindIndex = 0; FindIndex < TotalNumberOfZones; FindIndex++)
|
||||
if(strcmp(GetZone(FindIndex)->name, name) == 0)
|
||||
return FindIndex;
|
||||
return -1;
|
||||
}
|
||||
|
||||
CZoneInfo*
|
||||
CTheZones::GetZoneInfo(const CVector *v, uint8 day)
|
||||
{
|
||||
CZone *zone;
|
||||
zone = FindSmallestZonePositionILN(v);
|
||||
if(zone == nil)
|
||||
return &ZoneInfoArray[0];
|
||||
return &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info)
|
||||
{
|
||||
CZoneInfo *day, *night;
|
||||
float d, n;
|
||||
|
||||
day = GetZoneInfo(pos, 1);
|
||||
night = GetZoneInfo(pos, 0);
|
||||
|
||||
if(CClock::GetIsTimeInRange(8, 19))
|
||||
*info = *day;
|
||||
else if(CClock::GetIsTimeInRange(22, 5))
|
||||
*info = *night;
|
||||
else{
|
||||
if(CClock::GetIsTimeInRange(19, 22)){
|
||||
n = (CClock::GetHours() - 19) / 3.0f;
|
||||
assert(n >= 0.0f && n <= 1.0f);
|
||||
d = 1.0f - n;
|
||||
}else{
|
||||
d = (CClock::GetHours() - 5) / 3.0f;
|
||||
assert(d >= 0.0f && d <= 1.0f);
|
||||
n = 1.0f - d;
|
||||
}
|
||||
info->carDensity = day->carDensity * d + night->carDensity * n;
|
||||
info->carThreshold[0] = day->carThreshold[0] * d + night->carThreshold[0] * n;
|
||||
info->carThreshold[1] = day->carThreshold[1] * d + night->carThreshold[1] * n;
|
||||
info->carThreshold[2] = day->carThreshold[2] * d + night->carThreshold[2] * n;
|
||||
info->carThreshold[3] = day->carThreshold[3] * d + night->carThreshold[3] * n;
|
||||
info->carThreshold[4] = day->carThreshold[4] * d + night->carThreshold[4] * n;
|
||||
info->carThreshold[5] = day->carThreshold[5] * d + night->carThreshold[5] * n;
|
||||
info->copThreshold = day->copThreshold * d + night->copThreshold * n;
|
||||
info->gangThreshold[0] = day->gangThreshold[0] * d + night->gangThreshold[0] * n;
|
||||
info->gangThreshold[1] = day->gangThreshold[1] * d + night->gangThreshold[1] * n;
|
||||
info->gangThreshold[2] = day->gangThreshold[2] * d + night->gangThreshold[2] * n;
|
||||
info->gangThreshold[3] = day->gangThreshold[3] * d + night->gangThreshold[3] * n;
|
||||
info->gangThreshold[4] = day->gangThreshold[4] * d + night->gangThreshold[4] * n;
|
||||
info->gangThreshold[5] = day->gangThreshold[5] * d + night->gangThreshold[5] * n;
|
||||
info->gangThreshold[6] = day->gangThreshold[6] * d + night->gangThreshold[6] * n;
|
||||
info->gangThreshold[7] = day->gangThreshold[7] * d + night->gangThreshold[7] * n;
|
||||
info->gangThreshold[8] = day->gangThreshold[8] * d + night->gangThreshold[8] * n;
|
||||
|
||||
info->pedDensity = day->pedDensity * d + night->pedDensity * n;
|
||||
info->copDensity = day->copDensity * d + night->copDensity * n;
|
||||
info->gangDensity[0] = day->gangDensity[0] * d + night->gangDensity[0] * n;
|
||||
info->gangDensity[1] = day->gangDensity[1] * d + night->gangDensity[1] * n;
|
||||
info->gangDensity[2] = day->gangDensity[2] * d + night->gangDensity[2] * n;
|
||||
info->gangDensity[3] = day->gangDensity[3] * d + night->gangDensity[3] * n;
|
||||
info->gangDensity[4] = day->gangDensity[4] * d + night->gangDensity[4] * n;
|
||||
info->gangDensity[5] = day->gangDensity[5] * d + night->gangDensity[5] * n;
|
||||
info->gangDensity[6] = day->gangDensity[6] * d + night->gangDensity[6] * n;
|
||||
info->gangDensity[7] = day->gangDensity[7] * d + night->gangDensity[7] * n;
|
||||
info->gangDensity[8] = day->gangDensity[8] * d + night->gangDensity[8] * n;
|
||||
}
|
||||
if(CClock::GetIsTimeInRange(5, 19))
|
||||
info->pedGroup = day->pedGroup;
|
||||
else
|
||||
info->pedGroup = night->pedGroup;
|
||||
|
||||
CheckZoneInfo(info);
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::SetZoneCarInfo(uint16 zoneid, uint8 day, int16 carDensity,
|
||||
int16 gang0Num, int16 gang1Num, int16 gang2Num,
|
||||
int16 gang3Num, int16 gang4Num, int16 gang5Num,
|
||||
int16 gang6Num, int16 gang7Num, int16 gang8Num,
|
||||
int16 copNum,
|
||||
int16 car0Num, int16 car1Num, int16 car2Num,
|
||||
int16 car3Num, int16 car4Num, int16 car5Num)
|
||||
{
|
||||
CZone *zone;
|
||||
CZoneInfo *info;
|
||||
zone = GetZone(zoneid);
|
||||
info = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];
|
||||
|
||||
CheckZoneInfo(info);
|
||||
|
||||
if(carDensity != -1) info->carDensity = carDensity;
|
||||
int16 oldCar1Num = info->carThreshold[1] - info->carThreshold[0];
|
||||
int16 oldCar2Num = info->carThreshold[2] - info->carThreshold[1];
|
||||
int16 oldCar3Num = info->carThreshold[3] - info->carThreshold[2];
|
||||
int16 oldCar4Num = info->carThreshold[4] - info->carThreshold[3];
|
||||
int16 oldCar5Num = info->carThreshold[5] - info->carThreshold[4];
|
||||
int16 oldCopNum = info->copThreshold - info->carThreshold[5];
|
||||
int16 oldGang0Num = info->gangThreshold[0] - info->copThreshold;
|
||||
int16 oldGang1Num = info->gangThreshold[1] - info->gangThreshold[0];
|
||||
int16 oldGang2Num = info->gangThreshold[2] - info->gangThreshold[1];
|
||||
int16 oldGang3Num = info->gangThreshold[3] - info->gangThreshold[2];
|
||||
int16 oldGang4Num = info->gangThreshold[4] - info->gangThreshold[3];
|
||||
int16 oldGang5Num = info->gangThreshold[5] - info->gangThreshold[4];
|
||||
int16 oldGang6Num = info->gangThreshold[6] - info->gangThreshold[5];
|
||||
int16 oldGang7Num = info->gangThreshold[7] - info->gangThreshold[6];
|
||||
int16 oldGang8Num = info->gangThreshold[8] - info->gangThreshold[7];
|
||||
|
||||
if(car0Num != -1) info->carThreshold[0] = car0Num;
|
||||
if(car1Num != -1) info->carThreshold[1] = info->carThreshold[0] + car1Num;
|
||||
else info->carThreshold[1] = info->carThreshold[0] + oldCar1Num;
|
||||
if(car2Num != -1) info->carThreshold[2] = info->carThreshold[1] + car2Num;
|
||||
else info->carThreshold[2] = info->carThreshold[1] + oldCar2Num;
|
||||
if(car3Num != -1) info->carThreshold[3] = info->carThreshold[2] + car3Num;
|
||||
else info->carThreshold[3] = info->carThreshold[2] + oldCar3Num;
|
||||
if(car4Num != -1) info->carThreshold[4] = info->carThreshold[3] + car4Num;
|
||||
else info->carThreshold[4] = info->carThreshold[3] + oldCar4Num;
|
||||
if(car5Num != -1) info->carThreshold[5] = info->carThreshold[4] + car5Num;
|
||||
else info->carThreshold[5] = info->carThreshold[4] + oldCar5Num;
|
||||
if(copNum != -1) info->copThreshold = info->carThreshold[5] + copNum;
|
||||
else info->copThreshold = info->carThreshold[5] + oldCopNum;
|
||||
if(gang0Num != -1) info->gangThreshold[0] = info->copThreshold + gang0Num;
|
||||
else info->gangThreshold[0] = info->copThreshold + oldGang0Num;
|
||||
if(gang1Num != -1) info->gangThreshold[1] = info->gangThreshold[0] + gang1Num;
|
||||
else info->gangThreshold[1] = info->gangThreshold[0] + oldGang1Num;
|
||||
if(gang2Num != -1) info->gangThreshold[2] = info->gangThreshold[1] + gang2Num;
|
||||
else info->gangThreshold[2] = info->gangThreshold[1] + oldGang2Num;
|
||||
if(gang3Num != -1) info->gangThreshold[3] = info->gangThreshold[2] + gang3Num;
|
||||
else info->gangThreshold[3] = info->gangThreshold[2] + oldGang3Num;
|
||||
if(gang4Num != -1) info->gangThreshold[4] = info->gangThreshold[3] + gang4Num;
|
||||
else info->gangThreshold[4] = info->gangThreshold[3] + oldGang4Num;
|
||||
if(gang5Num != -1) info->gangThreshold[5] = info->gangThreshold[4] + gang5Num;
|
||||
else info->gangThreshold[5] = info->gangThreshold[4] + oldGang5Num;
|
||||
if(gang6Num != -1) info->gangThreshold[6] = info->gangThreshold[5] + gang6Num;
|
||||
else info->gangThreshold[6] = info->gangThreshold[5] + oldGang6Num;
|
||||
if(gang7Num != -1) info->gangThreshold[7] = info->gangThreshold[6] + gang7Num;
|
||||
else info->gangThreshold[7] = info->gangThreshold[6] + oldGang7Num;
|
||||
if(gang8Num != -1) info->gangThreshold[8] = info->gangThreshold[7] + gang8Num;
|
||||
else info->gangThreshold[8] = info->gangThreshold[7] + oldGang8Num;
|
||||
|
||||
CheckZoneInfo(info);
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::SetZonePedInfo(uint16 zoneid, uint8 day, int16 pedDensity,
|
||||
int16 gang0Density, int16 gang1Density, int16 gang2Density, int16 gang3Density,
|
||||
int16 gang4Density, int16 gang5Density, int16 gang6Density, int16 gang7Density,
|
||||
int16 gang8Density, int16 copDensity)
|
||||
{
|
||||
CZone *zone;
|
||||
CZoneInfo *info;
|
||||
zone = GetZone(zoneid);
|
||||
info = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];
|
||||
if(pedDensity != -1) info->pedDensity = pedDensity;
|
||||
if(copDensity != -1) info->copDensity = copDensity;
|
||||
if(gang0Density != -1) info->gangDensity[0] = gang0Density;
|
||||
if(gang1Density != -1) info->gangDensity[1] = gang1Density;
|
||||
if(gang2Density != -1) info->gangDensity[2] = gang2Density;
|
||||
if(gang3Density != -1) info->gangDensity[3] = gang3Density;
|
||||
if(gang4Density != -1) info->gangDensity[4] = gang4Density;
|
||||
if(gang5Density != -1) info->gangDensity[5] = gang5Density;
|
||||
if(gang6Density != -1) info->gangDensity[6] = gang6Density;
|
||||
if(gang7Density != -1) info->gangDensity[7] = gang7Density;
|
||||
if(gang8Density != -1) info->gangDensity[8] = gang8Density;
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::SetCarDensity(uint16 zoneid, uint8 day, uint16 cardensity)
|
||||
{
|
||||
CZone *zone;
|
||||
zone = GetZone(zoneid);
|
||||
if(zone->type == ZONE_AUDIO || zone->type == ZONE_TYPE1 || zone->type == ZONE_TYPE2)
|
||||
ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].carDensity = cardensity;
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::SetPedDensity(uint16 zoneid, uint8 day, uint16 peddensity)
|
||||
{
|
||||
CZone *zone;
|
||||
zone = GetZone(zoneid);
|
||||
if(zone->type == ZONE_AUDIO || zone->type == ZONE_TYPE1 || zone->type == ZONE_TYPE2)
|
||||
ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedDensity = peddensity;
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::SetPedGroup(uint16 zoneid, uint8 day, uint16 pedgroup)
|
||||
{
|
||||
CZone *zone;
|
||||
zone = GetZone(zoneid);
|
||||
if(zone->type == ZONE_AUDIO || zone->type == ZONE_TYPE1 || zone->type == ZONE_TYPE2)
|
||||
ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedGroup = pedgroup;
|
||||
}
|
||||
|
||||
int16
|
||||
CTheZones::FindAudioZone(CVector *pos)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < NumberOfAudioZones; i++)
|
||||
if(PointLiesWithinZone(*pos, GetZone(AudioZoneArray[i])))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
eLevelName
|
||||
CTheZones::FindZoneForPoint(const CVector &pos)
|
||||
{
|
||||
if(PointLiesWithinZone(pos, GetZone(FindZoneByLabelAndReturnIndex("IND_ZON"))))
|
||||
return LEVEL_INDUSTRIAL;
|
||||
if(PointLiesWithinZone(pos, GetZone(FindZoneByLabelAndReturnIndex("COM_ZON"))))
|
||||
return LEVEL_COMMERCIAL;
|
||||
if(PointLiesWithinZone(pos, GetZone(FindZoneByLabelAndReturnIndex("SUB_ZON"))))
|
||||
return LEVEL_SUBURBAN;
|
||||
return LEVEL_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::AddZoneToAudioZoneArray(CZone *zone)
|
||||
{
|
||||
int i, z;
|
||||
|
||||
if(zone->type != ZONE_AUDIO)
|
||||
return;
|
||||
|
||||
/* This is a bit stupid */
|
||||
z = -1;
|
||||
for(i = 0; i < NUMZONES; i++)
|
||||
if(&ZoneArray[i] == zone)
|
||||
z = i;
|
||||
AudioZoneArray[NumberOfAudioZones++] = z;
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::InitialiseAudioZoneArray(void)
|
||||
{
|
||||
bool gonext;
|
||||
CZone *zone;
|
||||
|
||||
gonext = false;
|
||||
zone = &ZoneArray[0];
|
||||
// Go deep first,
|
||||
// set gonext when backing up a level to visit the next child
|
||||
while(zone)
|
||||
if(gonext){
|
||||
AddZoneToAudioZoneArray(zone);
|
||||
if(zone->next){
|
||||
gonext = false;
|
||||
zone = zone->next;
|
||||
}else
|
||||
zone = zone->parent;
|
||||
}else if(zone->child)
|
||||
zone = zone->child;
|
||||
else{
|
||||
AddZoneToAudioZoneArray(zone);
|
||||
if(zone->next)
|
||||
zone = zone->next;
|
||||
else{
|
||||
gonext = true;
|
||||
zone = zone->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::SaveAllZones(uint8 *buffer, uint32 *length)
|
||||
{
|
||||
int i;
|
||||
|
||||
*length = 8 + 12 +
|
||||
NUMZONES*56 + 2*NUMZONES*58 + 4 +
|
||||
NUMMAPZONES*56 + NUMAUDIOZONES*2 + 4;
|
||||
|
||||
buffer[0] = 'Z';
|
||||
buffer[1] = 'N';
|
||||
buffer[2] = 'S';
|
||||
buffer[3] = '\0';
|
||||
*(uint32*)(buffer+4) = *length - 8;
|
||||
buffer += 8;
|
||||
|
||||
*(int32*)(buffer) = GetIndexForZonePointer(m_pPlayersZone);
|
||||
*(int32*)(buffer+4) = m_CurrLevel;
|
||||
*(int16*)(buffer+8) = FindIndex;
|
||||
*(int16*)(buffer+10) = 0;
|
||||
buffer += 12;
|
||||
|
||||
for(i = 0; i < NUMZONES; i++){
|
||||
memcpy(buffer, ZoneArray[i].name, 8);
|
||||
*(float*)(buffer+8) = ZoneArray[i].minx;
|
||||
*(float*)(buffer+12) = ZoneArray[i].miny;
|
||||
*(float*)(buffer+16) = ZoneArray[i].minz;
|
||||
*(float*)(buffer+20) = ZoneArray[i].maxx;
|
||||
*(float*)(buffer+24) = ZoneArray[i].maxy;
|
||||
*(float*)(buffer+28) = ZoneArray[i].maxz;
|
||||
*(int32*)(buffer+32) = ZoneArray[i].type;
|
||||
*(int32*)(buffer+36) = ZoneArray[i].level;
|
||||
*(int16*)(buffer+40) = ZoneArray[i].zoneinfoDay;
|
||||
*(int16*)(buffer+42) = ZoneArray[i].zoneinfoNight;
|
||||
*(int32*)(buffer+44) = GetIndexForZonePointer(ZoneArray[i].child);
|
||||
*(int32*)(buffer+48) = GetIndexForZonePointer(ZoneArray[i].parent);
|
||||
*(int32*)(buffer+52) = GetIndexForZonePointer(ZoneArray[i].next);
|
||||
buffer += 56;
|
||||
}
|
||||
|
||||
for(i = 0; i < 2*NUMZONES; i++){
|
||||
*(int16*)(buffer) = ZoneInfoArray[i].carDensity;
|
||||
*(int16*)(buffer+2) = ZoneInfoArray[i].carThreshold[0];
|
||||
*(int16*)(buffer+4) = ZoneInfoArray[i].carThreshold[1];
|
||||
*(int16*)(buffer+6) = ZoneInfoArray[i].carThreshold[2];
|
||||
*(int16*)(buffer+8) = ZoneInfoArray[i].carThreshold[3];
|
||||
*(int16*)(buffer+10) = ZoneInfoArray[i].carThreshold[4];
|
||||
*(int16*)(buffer+12) = ZoneInfoArray[i].carThreshold[5];
|
||||
*(int16*)(buffer+14) = ZoneInfoArray[i].copThreshold;
|
||||
*(int16*)(buffer+16) = ZoneInfoArray[i].gangThreshold[0];
|
||||
*(int16*)(buffer+18) = ZoneInfoArray[i].gangThreshold[1];
|
||||
*(int16*)(buffer+20) = ZoneInfoArray[i].gangThreshold[2];
|
||||
*(int16*)(buffer+22) = ZoneInfoArray[i].gangThreshold[3];
|
||||
*(int16*)(buffer+24) = ZoneInfoArray[i].gangThreshold[4];
|
||||
*(int16*)(buffer+26) = ZoneInfoArray[i].gangThreshold[5];
|
||||
*(int16*)(buffer+28) = ZoneInfoArray[i].gangThreshold[6];
|
||||
*(int16*)(buffer+30) = ZoneInfoArray[i].gangThreshold[7];
|
||||
*(int16*)(buffer+32) = ZoneInfoArray[i].gangThreshold[8];
|
||||
*(uint16*)(buffer+34) = ZoneInfoArray[i].pedDensity;
|
||||
*(uint16*)(buffer+36) = ZoneInfoArray[i].copDensity;
|
||||
*(uint16*)(buffer+38) = ZoneInfoArray[i].gangDensity[0];
|
||||
*(uint16*)(buffer+40) = ZoneInfoArray[i].gangDensity[1];
|
||||
*(uint16*)(buffer+42) = ZoneInfoArray[i].gangDensity[2];
|
||||
*(uint16*)(buffer+44) = ZoneInfoArray[i].gangDensity[3];
|
||||
*(uint16*)(buffer+46) = ZoneInfoArray[i].gangDensity[4];
|
||||
*(uint16*)(buffer+48) = ZoneInfoArray[i].gangDensity[5];
|
||||
*(uint16*)(buffer+50) = ZoneInfoArray[i].gangDensity[6];
|
||||
*(uint16*)(buffer+52) = ZoneInfoArray[i].gangDensity[7];
|
||||
*(uint16*)(buffer+54) = ZoneInfoArray[i].gangDensity[8];
|
||||
*(uint16*)(buffer+56) = ZoneInfoArray[i].pedGroup;
|
||||
buffer += 58;
|
||||
}
|
||||
|
||||
*(uint16*)(buffer) = TotalNumberOfZones;
|
||||
*(uint16*)(buffer+2) = TotalNumberOfZoneInfos;
|
||||
buffer += 4;
|
||||
|
||||
for(i = 0; i < NUMMAPZONES; i++){
|
||||
memcpy(buffer, MapZoneArray[i].name, 8);
|
||||
*(float*)(buffer+8) = MapZoneArray[i].minx;
|
||||
*(float*)(buffer+12) = MapZoneArray[i].miny;
|
||||
*(float*)(buffer+16) = MapZoneArray[i].minz;
|
||||
*(float*)(buffer+20) = MapZoneArray[i].maxx;
|
||||
*(float*)(buffer+24) = MapZoneArray[i].maxy;
|
||||
*(float*)(buffer+28) = MapZoneArray[i].maxz;
|
||||
*(int32*)(buffer+32) = MapZoneArray[i].type;
|
||||
*(int32*)(buffer+36) = MapZoneArray[i].level;
|
||||
*(int16*)(buffer+40) = MapZoneArray[i].zoneinfoDay;
|
||||
*(int16*)(buffer+42) = MapZoneArray[i].zoneinfoNight;
|
||||
#ifdef STANDALONE
|
||||
// BUG: GetIndexForZonePointer uses ZoneArray
|
||||
// so indices will be unpredictable with different memory layout
|
||||
assert(0);
|
||||
#endif
|
||||
*(int32*)(buffer+44) = GetIndexForZonePointer(MapZoneArray[i].child);
|
||||
*(int32*)(buffer+48) = GetIndexForZonePointer(MapZoneArray[i].parent);
|
||||
*(int32*)(buffer+52) = GetIndexForZonePointer(MapZoneArray[i].next);
|
||||
buffer += 56;
|
||||
}
|
||||
|
||||
for(i = 0; i < NUMAUDIOZONES; i++){
|
||||
*(int16*)buffer = AudioZoneArray[i];
|
||||
buffer += 2;
|
||||
}
|
||||
|
||||
*(uint16*)(buffer) = TotalNumberOfMapZones;
|
||||
*(uint16*)(buffer+2) = NumberOfAudioZones;
|
||||
}
|
||||
|
||||
void
|
||||
CTheZones::LoadAllZones(uint8 *buffer, uint32 length)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(length == 8 + 12 +
|
||||
NUMZONES*56 + 2*NUMZONES*58 + 4 +
|
||||
NUMMAPZONES*56 + NUMAUDIOZONES*2 + 4);
|
||||
assert(buffer[0] == 'Z');
|
||||
assert(buffer[1] == 'N');
|
||||
assert(buffer[2] == 'S');
|
||||
assert(buffer[3] == '\0');
|
||||
assert(*(uint32*)(buffer+4) == length - 8);
|
||||
buffer += 8;
|
||||
|
||||
m_pPlayersZone = GetPointerForZoneIndex(*(int32*)(buffer));
|
||||
m_CurrLevel = (eLevelName)*(int32*)(buffer+4);
|
||||
FindIndex = *(int16*)(buffer+8);
|
||||
assert(*(int16*)(buffer+10) == 0);
|
||||
buffer += 12;
|
||||
|
||||
for(i = 0; i < NUMZONES; i++){
|
||||
memcpy(ZoneArray[i].name, buffer, 8);
|
||||
ZoneArray[i].minx = *(float*)(buffer+8);
|
||||
ZoneArray[i].miny = *(float*)(buffer+12);
|
||||
ZoneArray[i].minz = *(float*)(buffer+16);
|
||||
ZoneArray[i].maxx = *(float*)(buffer+20);
|
||||
ZoneArray[i].maxy = *(float*)(buffer+24);
|
||||
ZoneArray[i].maxz = *(float*)(buffer+28);
|
||||
ZoneArray[i].type = (eZoneType)*(int32*)(buffer+32);
|
||||
ZoneArray[i].level = (eLevelName)*(int32*)(buffer+36);
|
||||
ZoneArray[i].zoneinfoDay = *(int16*)(buffer+40);
|
||||
ZoneArray[i].zoneinfoNight = *(int16*)(buffer+42);
|
||||
ZoneArray[i].child = GetPointerForZoneIndex(*(int32*)(buffer+44));
|
||||
ZoneArray[i].parent = GetPointerForZoneIndex(*(int32*)(buffer+48));
|
||||
ZoneArray[i].next = GetPointerForZoneIndex(*(int32*)(buffer+52));
|
||||
buffer += 56;
|
||||
}
|
||||
|
||||
for(i = 0; i < 2*NUMZONES; i++){
|
||||
ZoneInfoArray[i].carDensity = *(int16*)(buffer);
|
||||
ZoneInfoArray[i].carThreshold[0] = *(int16*)(buffer+2);
|
||||
ZoneInfoArray[i].carThreshold[1] = *(int16*)(buffer+4);
|
||||
ZoneInfoArray[i].carThreshold[2] = *(int16*)(buffer+6);
|
||||
ZoneInfoArray[i].carThreshold[3] = *(int16*)(buffer+8);
|
||||
ZoneInfoArray[i].carThreshold[4] = *(int16*)(buffer+10);
|
||||
ZoneInfoArray[i].carThreshold[5] = *(int16*)(buffer+12);
|
||||
ZoneInfoArray[i].copThreshold = *(int16*)(buffer+14);
|
||||
ZoneInfoArray[i].gangThreshold[0] = *(int16*)(buffer+16);
|
||||
ZoneInfoArray[i].gangThreshold[1] = *(int16*)(buffer+18);
|
||||
ZoneInfoArray[i].gangThreshold[2] = *(int16*)(buffer+20);
|
||||
ZoneInfoArray[i].gangThreshold[3] = *(int16*)(buffer+22);
|
||||
ZoneInfoArray[i].gangThreshold[4] = *(int16*)(buffer+24);
|
||||
ZoneInfoArray[i].gangThreshold[5] = *(int16*)(buffer+26);
|
||||
ZoneInfoArray[i].gangThreshold[6] = *(int16*)(buffer+28);
|
||||
ZoneInfoArray[i].gangThreshold[7] = *(int16*)(buffer+30);
|
||||
ZoneInfoArray[i].gangThreshold[8] = *(int16*)(buffer+32);
|
||||
ZoneInfoArray[i].pedDensity = *(uint16*)(buffer+34);
|
||||
ZoneInfoArray[i].copDensity = *(uint16*)(buffer+36);
|
||||
ZoneInfoArray[i].gangDensity[0] = *(uint16*)(buffer+38);
|
||||
ZoneInfoArray[i].gangDensity[1] = *(uint16*)(buffer+40);
|
||||
ZoneInfoArray[i].gangDensity[2] = *(uint16*)(buffer+42);
|
||||
ZoneInfoArray[i].gangDensity[3] = *(uint16*)(buffer+44);
|
||||
ZoneInfoArray[i].gangDensity[4] = *(uint16*)(buffer+46);
|
||||
ZoneInfoArray[i].gangDensity[5] = *(uint16*)(buffer+48);
|
||||
ZoneInfoArray[i].gangDensity[6] = *(uint16*)(buffer+50);
|
||||
ZoneInfoArray[i].gangDensity[7] = *(uint16*)(buffer+52);
|
||||
ZoneInfoArray[i].gangDensity[8] = *(uint16*)(buffer+54);
|
||||
ZoneInfoArray[i].pedGroup = *(uint16*)(buffer+56);
|
||||
buffer += 58;
|
||||
}
|
||||
|
||||
TotalNumberOfZones = *(uint16*)(buffer);
|
||||
TotalNumberOfZoneInfos = *(uint16*)(buffer+2);
|
||||
buffer += 4;
|
||||
|
||||
for(i = 0; i < NUMMAPZONES; i++){
|
||||
memcpy(MapZoneArray[i].name, buffer, 8);
|
||||
MapZoneArray[i].minx = *(float*)(buffer+8);
|
||||
MapZoneArray[i].miny = *(float*)(buffer+12);
|
||||
MapZoneArray[i].minz = *(float*)(buffer+16);
|
||||
MapZoneArray[i].maxx = *(float*)(buffer+20);
|
||||
MapZoneArray[i].maxy = *(float*)(buffer+24);
|
||||
MapZoneArray[i].maxz = *(float*)(buffer+28);
|
||||
MapZoneArray[i].type = (eZoneType)*(int32*)(buffer+32);
|
||||
MapZoneArray[i].level = (eLevelName)*(int32*)(buffer+36);
|
||||
MapZoneArray[i].zoneinfoDay = *(int16*)(buffer+40);
|
||||
MapZoneArray[i].zoneinfoNight = *(int16*)(buffer+42);
|
||||
#ifdef STANDALONE
|
||||
// BUG: GetPointerForZoneIndex uses ZoneArray
|
||||
// so pointers will be unpredictable with different memory layout
|
||||
assert(0);
|
||||
#endif
|
||||
MapZoneArray[i].child = GetPointerForZoneIndex(*(int32*)(buffer+44));
|
||||
MapZoneArray[i].parent = GetPointerForZoneIndex(*(int32*)(buffer+48));
|
||||
MapZoneArray[i].next = GetPointerForZoneIndex(*(int32*)(buffer+52));
|
||||
buffer += 56;
|
||||
}
|
||||
|
||||
for(i = 0; i < NUMAUDIOZONES; i++){
|
||||
AudioZoneArray[i] = *(int16*)buffer;
|
||||
buffer += 2;
|
||||
}
|
||||
|
||||
TotalNumberOfMapZones = *(uint16*)(buffer);
|
||||
NumberOfAudioZones = *(uint16*)(buffer+2);
|
||||
}
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4B5DD0, &CZone::GetTranslatedName, PATCH_JUMP);
|
||||
InjectHook(0x4B5DE0, CTheZones::Init, PATCH_JUMP);
|
||||
InjectHook(0x4B61D0, CTheZones::Update, PATCH_JUMP);
|
||||
InjectHook(0x4B6210, CTheZones::CreateZone, PATCH_JUMP);
|
||||
InjectHook(0x4B6380, CTheZones::CreateMapZone, PATCH_JUMP);
|
||||
InjectHook(0x4B64C0, CTheZones::PostZoneCreation, PATCH_JUMP);
|
||||
InjectHook(0x4B6500, CTheZones::InsertZoneIntoZoneHierarchy, PATCH_JUMP);
|
||||
InjectHook(0x4B6530, CTheZones::InsertZoneIntoZoneHierRecursive, PATCH_JUMP);
|
||||
InjectHook(0x4B65F0, CTheZones::ZoneIsEntirelyContainedWithinOtherZone, PATCH_JUMP);
|
||||
InjectHook(0x4B6710, CTheZones::PointLiesWithinZone, PATCH_JUMP);
|
||||
InjectHook(0x4B6910, CTheZones::GetLevelFromPosition, PATCH_JUMP);
|
||||
InjectHook(0x4B69B0, CTheZones::FindSmallestZonePosition, PATCH_JUMP);
|
||||
InjectHook(0x4B6790, CTheZones::FindSmallestZonePositionType, PATCH_JUMP);
|
||||
InjectHook(0x4B6890, CTheZones::FindSmallestZonePositionILN, PATCH_JUMP);
|
||||
InjectHook(0x4B6800, CTheZones::FindZoneByLabelAndReturnIndex, PATCH_JUMP);
|
||||
InjectHook(0x4B6FA0, CTheZones::GetZone, PATCH_JUMP);
|
||||
InjectHook(0x4B84F0, CTheZones::GetPointerForZoneIndex, PATCH_JUMP);
|
||||
InjectHook(0x4B6A10, CTheZones::GetZoneInfo, PATCH_JUMP);
|
||||
InjectHook(0x4B6FB0, CTheZones::GetZoneInfoForTimeOfDay, PATCH_JUMP);
|
||||
InjectHook(0x4B6A50, CTheZones::SetZoneCarInfo, PATCH_JUMP);
|
||||
InjectHook(0x4B6DC0, CTheZones::SetZonePedInfo, PATCH_JUMP);
|
||||
InjectHook(0x4B6EB0, CTheZones::SetCarDensity, PATCH_JUMP);
|
||||
InjectHook(0x4B6F00, CTheZones::SetPedDensity, PATCH_JUMP);
|
||||
InjectHook(0x4B6F50, CTheZones::SetPedGroup, PATCH_JUMP);
|
||||
InjectHook(0x4B83E0, CTheZones::FindAudioZone, PATCH_JUMP);
|
||||
InjectHook(0x4B8430, CTheZones::FindZoneForPoint, PATCH_JUMP);
|
||||
InjectHook(0x4B8340, CTheZones::AddZoneToAudioZoneArray, PATCH_JUMP);
|
||||
InjectHook(0x4B8510, CTheZones::SaveAllZones, PATCH_JUMP);
|
||||
InjectHook(0x4B8950, CTheZones::LoadAllZones, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
112
src/core/Zones.h
Normal file
112
src/core/Zones.h
Normal file
@@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
|
||||
#include "Game.h"
|
||||
|
||||
enum eZoneType
|
||||
{
|
||||
ZONE_AUDIO,
|
||||
ZONE_TYPE1, // this should be NAVIG
|
||||
ZONE_TYPE2, // this should be INFO...but all except MAPINFO get zoneinfo??
|
||||
ZONE_MAPZONE,
|
||||
};
|
||||
|
||||
class CZone
|
||||
{
|
||||
public:
|
||||
char name[8];
|
||||
float minx;
|
||||
float miny;
|
||||
float minz;
|
||||
float maxx;
|
||||
float maxy;
|
||||
float maxz;
|
||||
eZoneType type;
|
||||
eLevelName level;
|
||||
int16 zoneinfoDay;
|
||||
int16 zoneinfoNight;
|
||||
CZone *child;
|
||||
CZone *parent;
|
||||
CZone *next;
|
||||
|
||||
wchar *GetTranslatedName(void);
|
||||
};
|
||||
|
||||
class CZoneInfo
|
||||
{
|
||||
public:
|
||||
// Car data
|
||||
int16 carDensity;
|
||||
int16 carThreshold[6];
|
||||
int16 copThreshold;
|
||||
int16 gangThreshold[9];
|
||||
|
||||
// Ped data
|
||||
uint16 pedDensity;
|
||||
uint16 copDensity;
|
||||
uint16 gangDensity[9];
|
||||
uint16 pedGroup;
|
||||
};
|
||||
|
||||
|
||||
class CTheZones
|
||||
{
|
||||
public:
|
||||
static eLevelName &m_CurrLevel;
|
||||
static CZone *&m_pPlayersZone;
|
||||
static int16 &FindIndex;
|
||||
|
||||
static uint16 &NumberOfAudioZones;
|
||||
static int16 *AudioZoneArray; //[NUMAUDIOZONES];
|
||||
static uint16 &TotalNumberOfMapZones;
|
||||
static uint16 &TotalNumberOfZones;
|
||||
static CZone *ZoneArray; //[NUMZONES];
|
||||
static CZone *MapZoneArray; //[NUMMAPZONES];
|
||||
static uint16 &TotalNumberOfZoneInfos;
|
||||
static CZoneInfo *ZoneInfoArray; //[2*NUMZONES];
|
||||
|
||||
static void Init(void);
|
||||
static void Update(void);
|
||||
static void CreateZone(char *name, eZoneType type,
|
||||
float minx, float miny, float minz,
|
||||
float maxx, float maxy, float maxz,
|
||||
eLevelName level);
|
||||
static void CreateMapZone(char *name, eZoneType type,
|
||||
float minx, float miny, float minz,
|
||||
float maxx, float maxy, float maxz,
|
||||
eLevelName level);
|
||||
static CZone *GetZone(uint16 i) { return &ZoneArray[i]; }
|
||||
static void PostZoneCreation(void);
|
||||
static void InsertZoneIntoZoneHierarchy(CZone *zone);
|
||||
static bool InsertZoneIntoZoneHierRecursive(CZone *z1, CZone *z2);
|
||||
static bool ZoneIsEntirelyContainedWithinOtherZone(CZone *z1, CZone *z2);
|
||||
static bool PointLiesWithinZone(const CVector &v, CZone *zone);
|
||||
static eLevelName GetLevelFromPosition(CVector const &v);
|
||||
static CZone *FindSmallestZonePosition(const CVector *v);
|
||||
static CZone *FindSmallestZonePositionType(const CVector *v, eZoneType type);
|
||||
static CZone *FindSmallestZonePositionILN(const CVector *v);
|
||||
static int16 FindZoneByLabelAndReturnIndex(char *name);
|
||||
static CZoneInfo *GetZoneInfo(const CVector *v, uint8 day);
|
||||
static void GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info);
|
||||
static void SetZoneCarInfo(uint16 zoneid, uint8 day, int16 carDensity,
|
||||
int16 gang0Num, int16 gang1Num, int16 gang2Num,
|
||||
int16 gang3Num, int16 gang4Num, int16 gang5Num,
|
||||
int16 gang6Num, int16 gang7Num, int16 gang8Num,
|
||||
int16 copNum,
|
||||
int16 car0Num, int16 car1Num, int16 car2Num,
|
||||
int16 car3Num, int16 car4Num, int16 car5Num);
|
||||
static void SetZonePedInfo(uint16 zoneid, uint8 day, int16 pedDensity,
|
||||
int16 gang0Density, int16 gang1Density, int16 gang2Density, int16 gang3Density,
|
||||
int16 gang4Density, int16 gang5Density, int16 gang6Density, int16 gang7Density,
|
||||
int16 gang8Density, int16 copDensity);
|
||||
static void SetCarDensity(uint16 zoneid, uint8 day, uint16 cardensity);
|
||||
static void SetPedDensity(uint16 zoneid, uint8 day, uint16 peddensity);
|
||||
static void SetPedGroup(uint16 zoneid, uint8 day, uint16 pedgroup);
|
||||
static int16 FindAudioZone(CVector *pos);
|
||||
static eLevelName FindZoneForPoint(const CVector &pos);
|
||||
static CZone *GetPointerForZoneIndex(int32 i) { return i == -1 ? nil : &ZoneArray[i]; }
|
||||
static int32 GetIndexForZonePointer(CZone *zone) { return zone == nil ? -1 : zone - ZoneArray; }
|
||||
static void AddZoneToAudioZoneArray(CZone *zone);
|
||||
static void InitialiseAudioZoneArray(void);
|
||||
static void SaveAllZones(uint8 *buffer, uint32 *length);
|
||||
static void LoadAllZones(uint8 *buffer, uint32 length);
|
||||
};
|
||||
178
src/core/common.h
Normal file
178
src/core/common.h
Normal file
@@ -0,0 +1,178 @@
|
||||
#pragma once
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define _USE_MATH_DEFINES
|
||||
#pragma warning(disable: 4244) // int to float
|
||||
#pragma warning(disable: 4800) // int to bool
|
||||
#pragma warning(disable: 4305) // double to float
|
||||
#pragma warning(disable: 4838) // narrowing conversion
|
||||
#pragma warning(disable: 4996) // POSIX names
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
//#include <assert.h>
|
||||
#include <new>
|
||||
|
||||
#ifdef WITHD3D
|
||||
#include <windows.h>
|
||||
#include <d3d8types.h>
|
||||
#endif
|
||||
|
||||
#include <rwcore.h>
|
||||
#include <rpworld.h>
|
||||
|
||||
#define rwVENDORID_ROCKSTAR 0x0253F2
|
||||
|
||||
// Get rid of bullshit windows definitions, we're not running on an 8086
|
||||
#ifdef far
|
||||
#undef far
|
||||
#endif
|
||||
#ifdef near
|
||||
#undef near
|
||||
#endif
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef int8_t int8;
|
||||
typedef uint16_t uint16;
|
||||
typedef int16_t int16;
|
||||
typedef uint32_t uint32;
|
||||
typedef int32_t int32;
|
||||
typedef uintptr_t uintptr;
|
||||
typedef uint64_t uint64;
|
||||
typedef int64_t int64;
|
||||
// hardcode ucs-2
|
||||
typedef uint16_t wchar;
|
||||
|
||||
#define nil nullptr
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define ALIGNPTR(p) (void*)((((uintptr)(void*)p) + sizeof(void*)-1) & ~(sizeof(void*)-1))
|
||||
|
||||
// PDP-10 like byte functions
|
||||
#define MASK(p, s) (((1<<(s))-1) << (p))
|
||||
inline uint32 dpb(uint32 b, uint32 p, uint32 s, uint32 w)
|
||||
{
|
||||
uint32 m = MASK(p,s);
|
||||
return w & ~m | b<<p & m;
|
||||
}
|
||||
inline uint32 ldb(uint32 p, uint32 s, uint32 w)
|
||||
{
|
||||
return w>>p & (1<<s)-1;
|
||||
}
|
||||
|
||||
|
||||
// little hack
|
||||
extern void **rwengine;
|
||||
#define RwEngineInstance (*rwengine)
|
||||
|
||||
#include "skeleton.h"
|
||||
#include "Draw.h"
|
||||
|
||||
#define DEFAULT_SCREEN_WIDTH (640)
|
||||
#define DEFAULT_SCREEN_HEIGHT (448)
|
||||
#define DEFAULT_ASPECT_RATIO (4.0f/3.0f)
|
||||
|
||||
// game uses maximumWidth/Height, but this probably won't work
|
||||
// with RW windowed mode
|
||||
#define SCREEN_WIDTH ((float)RsGlobal.width)
|
||||
#define SCREEN_HEIGHT ((float)RsGlobal.height)
|
||||
#define SCREEN_ASPECT_RATIO (CDraw::GetAspectRatio())
|
||||
|
||||
// This scales from PS2 pixel coordinates to the real resolution
|
||||
#define SCREEN_STRETCH_X(a) ((a) * (float) SCREEN_WIDTH / DEFAULT_SCREEN_WIDTH)
|
||||
#define SCREEN_STRETCH_Y(a) ((a) * (float) SCREEN_HEIGHT / DEFAULT_SCREEN_HEIGHT)
|
||||
#define SCREEN_STRETCH_FROM_RIGHT(a) (SCREEN_WIDTH - SCREEN_STRETCH_X(a))
|
||||
#define SCREEN_STRETCH_FROM_BOTTOM(a) (SCREEN_HEIGHT - SCREEN_STRETCH_Y(a))
|
||||
|
||||
// This scales from PS2 pixel coordinates while optionally maintaining the aspect ratio
|
||||
#define SCREEN_SCALE_X(a) SCREEN_SCALE_AR(SCREEN_STRETCH_X(a))
|
||||
#define SCREEN_SCALE_Y(a) SCREEN_STRETCH_Y(a)
|
||||
#define SCREEN_SCALE_FROM_RIGHT(a) (SCREEN_WIDTH - SCREEN_SCALE_X(a))
|
||||
#define SCREEN_SCALE_FROM_BOTTOM(a) (SCREEN_HEIGHT - SCREEN_SCALE_Y(a))
|
||||
|
||||
#ifdef ASPECT_RATIO_SCALE
|
||||
#define SCREEN_SCALE_AR(a) ((a) * (4.0f / 3.0f) / SCREEN_ASPECT_RATIO)
|
||||
#else
|
||||
#define SCREEN_SCALE_AR(a) (a)
|
||||
#endif
|
||||
|
||||
#include "math/Vector.h"
|
||||
#include "math/Vector2D.h"
|
||||
#include "math/Matrix.h"
|
||||
#include "math/Rect.h"
|
||||
|
||||
class CRGBA
|
||||
{
|
||||
public:
|
||||
union
|
||||
{
|
||||
uint32 color32;
|
||||
struct { uint8 r, g, b, a; };
|
||||
struct { uint8 red, green, blue, alpha; };
|
||||
#ifdef RWCORE_H
|
||||
struct { RwRGBA rwRGBA; };
|
||||
#endif
|
||||
};
|
||||
|
||||
CRGBA(void) { }
|
||||
CRGBA(uint8 r, uint8 g, uint8 b, uint8 a) : r(r), g(g), b(b), a(a) { }
|
||||
#ifdef RWCORE_H
|
||||
operator RwRGBA &(void) {
|
||||
return rwRGBA;
|
||||
}
|
||||
|
||||
operator RwRGBA *(void) {
|
||||
return &rwRGBA;
|
||||
}
|
||||
|
||||
operator RwRGBA (void) const {
|
||||
return rwRGBA;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#define clamp(v, low, high) ((v)<(low) ? (low) : (v)>(high) ? (high) : (v))
|
||||
|
||||
inline float sq(float x) { return x*x; }
|
||||
#define SQR(x) ((x) * (x))
|
||||
|
||||
#define PI M_PI
|
||||
#define DEGTORAD(x) ((x) * PI / 180.0f)
|
||||
#define RADTODEG(x) ((x) * 180.0f / PI)
|
||||
|
||||
#ifdef USE_PS2_RAND
|
||||
#define MYRAND_MAX 65535
|
||||
#else
|
||||
#define MYRAND_MAX 32767
|
||||
#endif
|
||||
|
||||
int myrand(void);
|
||||
void mysrand(unsigned int seed);
|
||||
|
||||
void re3_debug(char *format, ...);
|
||||
void re3_trace(const char *filename, unsigned int lineno, const char *func, char *format, ...);
|
||||
void re3_assert(const char *expr, const char *filename, unsigned int lineno, const char *func);
|
||||
|
||||
#define DEBUGBREAK() __debugbreak();
|
||||
|
||||
#define debug(f, ...) re3_debug("[DBG]: " f, __VA_ARGS__)
|
||||
#define DEV(f, ...) re3_debug("[DEV]: " f, __VA_ARGS__)
|
||||
#define TRACE(f, ...) re3_trace(__FILE__, __LINE__, __FUNCTION__, f, __VA_ARGS__)
|
||||
#define Error(f, ...) re3_debug("[ERROR]: " f, __VA_ARGS__)
|
||||
|
||||
#define assert(_Expression) (void)( (!!(_Expression)) || (re3_assert(#_Expression, __FILE__, __LINE__, __FUNCTION__), 0) )
|
||||
#define ASSERT assert
|
||||
|
||||
#define _TODO(x)
|
||||
#define _TODOCONST(x) (x)
|
||||
|
||||
#define VALIDATE_SIZE(struc, size) static_assert(sizeof(struc) == size, "Invalid structure size of " #struc)
|
||||
#define VALIDATE_OFFSET(struc, member, offset) static_assert(offsetof(struc, member) == offset, "The offset of " #member " in " #struc " is not " #offset "...")
|
||||
|
||||
#define PERCENT(x, p) ((float(x) * (float(p) / 100.0f)))
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
#define BIT(num) (1<<(num))
|
||||
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
116
src/core/config.h
Normal file
116
src/core/config.h
Normal file
@@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
enum Config {
|
||||
NUMCDIMAGES = 12, // gta3.img duplicates (not used on PC)
|
||||
MAX_CDIMAGES = 8, // additional cdimages
|
||||
|
||||
MODELINFOSIZE = 5500,
|
||||
TXDSTORESIZE = 850,
|
||||
EXTRADIRSIZE = 128,
|
||||
|
||||
SIMPLEMODELSIZE = 5000,
|
||||
TIMEMODELSIZE = 30,
|
||||
CLUMPMODELSIZE = 5,
|
||||
PEDMODELSIZE = 90,
|
||||
VEHICLEMODELSIZE = 120,
|
||||
TWODFXSIZE = 2000,
|
||||
|
||||
MAXVEHICLESLOADED = 50, // 70 on mobile
|
||||
|
||||
NUMOBJECTINFO = 168, // object.dat
|
||||
|
||||
// Pool sizes
|
||||
NUMPTRNODES = 30000, // 26000 on PS2
|
||||
NUMENTRYINFOS = 5400, // 3200 on PS2
|
||||
NUMPEDS = 140, // 90 on PS2
|
||||
NUMVEHICLES = 110, // 70 on PS2
|
||||
NUMBUILDINGS = 5500, // 4915 on PS2
|
||||
NUMTREADABLES = 1214,
|
||||
NUMOBJECTS = 450,
|
||||
NUMDUMMIES = 2802, // 2368 on PS2
|
||||
NUMAUDIOSCRIPTOBJECTS = 256,
|
||||
|
||||
// Link list lengths
|
||||
// TODO: alpha list
|
||||
NUMCOLCACHELINKS = 200,
|
||||
NUMREFERENCES = 800,
|
||||
|
||||
// Zones
|
||||
NUMAUDIOZONES = 36,
|
||||
NUMZONES = 50,
|
||||
NUMMAPZONES = 25,
|
||||
|
||||
// Cull zones
|
||||
NUMCULLZONES = 512,
|
||||
NUMATTRIBZONES = 288,
|
||||
NUMZONEINDICES = 55000,
|
||||
|
||||
NUMHANDLINGS = 57,
|
||||
|
||||
PATHNODESIZE = 4500,
|
||||
|
||||
NUMWEATHERS = 4,
|
||||
NUMHOURS = 24,
|
||||
|
||||
NUMEXTRADIRECTIONALS = 4,
|
||||
NUMANTENNAS = 8,
|
||||
NUMCORONAS = 56,
|
||||
NUMPOINTLIGHTS = 32,
|
||||
|
||||
NUMONSCREENTIMERENTRIES = 1,
|
||||
NUMRADARBLIPS = 32,
|
||||
NUMPICKUPS = 336,
|
||||
};
|
||||
|
||||
// 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
|
||||
//#define GTA_PS2
|
||||
//#define GTA_XBOX
|
||||
|
||||
// This enables things from the PS2 version on PC
|
||||
#define GTA_PS2_STUFF
|
||||
|
||||
// This is enabled for all released games.
|
||||
// any debug stuff that isn't left in any game is not in FINAL
|
||||
//#define FINAL
|
||||
|
||||
// This is enabled for all released games except mobile
|
||||
// any debug stuff that is only left in mobile, is not in MASTER
|
||||
//#define MASTER
|
||||
|
||||
#if defined GTA_PS2
|
||||
# define RANDOMSPLASH
|
||||
#elif defined GTA_PC
|
||||
# define GTA3_1_1_PATCH
|
||||
# ifdef GTA_PS2_STUFF
|
||||
//# define USE_PS2_RAND // this is unsafe until we have the game reversed
|
||||
# define RANDOMSPLASH // use random splash as on PS2
|
||||
# define PS2_MATFX
|
||||
# endif
|
||||
#elif defined GTA_XBOX
|
||||
#endif
|
||||
|
||||
#ifdef MASTER
|
||||
// only in master builds
|
||||
#else
|
||||
// not in master builds
|
||||
#endif
|
||||
|
||||
#ifdef FINAL
|
||||
// in all games
|
||||
# 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 CHATTYSPLASH // print what the game is loading
|
||||
#endif
|
||||
|
||||
#define FIX_BUGS // fix bugs in the game, TODO: use this more
|
||||
#define KANGAROO_CHEAT
|
||||
#define ASPECT_RATIO_SCALE
|
||||
154
src/core/debugmenu_public.h
Normal file
154
src/core/debugmenu_public.h
Normal file
@@ -0,0 +1,154 @@
|
||||
|
||||
extern "C" {
|
||||
|
||||
typedef void (*TriggerFunc)(void);
|
||||
|
||||
struct DebugMenuEntry;
|
||||
|
||||
typedef DebugMenuEntry *(*DebugMenuAddInt8_TYPE)(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc, int8_t step, int8_t lowerBound, int8_t upperBound, const char **strings);
|
||||
typedef DebugMenuEntry *(*DebugMenuAddInt16_TYPE)(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc, int16_t step, int16_t lowerBound, int16_t upperBound, const char **strings);
|
||||
typedef DebugMenuEntry *(*DebugMenuAddInt32_TYPE)(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc, int32_t step, int32_t lowerBound, int32_t upperBound, const char **strings);
|
||||
typedef DebugMenuEntry *(*DebugMenuAddInt64_TYPE)(const char *path, const char *name, int64_t *ptr, TriggerFunc triggerFunc, int64_t step, int64_t lowerBound, int64_t upperBound, const char **strings);
|
||||
typedef DebugMenuEntry *(*DebugMenuAddUInt8_TYPE)(const char *path, const char *name, uint8_t *ptr, TriggerFunc triggerFunc, uint8_t step, uint8_t lowerBound, uint8_t upperBound, const char **strings);
|
||||
typedef DebugMenuEntry *(*DebugMenuAddUInt16_TYPE)(const char *path, const char *name, uint16_t *ptr, TriggerFunc triggerFunc, uint16_t step, uint16_t lowerBound, uint16_t upperBound, const char **strings);
|
||||
typedef DebugMenuEntry *(*DebugMenuAddUInt32_TYPE)(const char *path, const char *name, uint32_t *ptr, TriggerFunc triggerFunc, uint32_t step, uint32_t lowerBound, uint32_t upperBound, const char **strings);
|
||||
typedef DebugMenuEntry *(*DebugMenuAddUInt64_TYPE)(const char *path, const char *name, uint64_t *ptr, TriggerFunc triggerFunc, uint64_t step, uint64_t lowerBound, uint64_t upperBound, const char **strings);
|
||||
typedef DebugMenuEntry *(*DebugMenuAddFloat32_TYPE)(const char *path, const char *name, float *ptr, TriggerFunc triggerFunc, float step, float lowerBound, float upperBound);
|
||||
typedef DebugMenuEntry *(*DebugMenuAddFloat64_TYPE)(const char *path, const char *name, double *ptr, TriggerFunc triggerFunc, double step, double lowerBound, double upperBound);
|
||||
typedef DebugMenuEntry *(*DebugMenuAddCmd_TYPE)(const char *path, const char *name, TriggerFunc triggerFunc);
|
||||
typedef void (*DebugMenuEntrySetWrap_TYPE)(DebugMenuEntry *e, bool wrap);
|
||||
typedef void (*DebugMenuEntrySetStrings_TYPE)(DebugMenuEntry *e, const char **strings);
|
||||
typedef void (*DebugMenuEntrySetAddress_TYPE)(DebugMenuEntry *e, void *addr);
|
||||
|
||||
struct DebugMenuAPI
|
||||
{
|
||||
bool isLoaded;
|
||||
HMODULE module;
|
||||
DebugMenuAddInt8_TYPE addint8;
|
||||
DebugMenuAddInt16_TYPE addint16;
|
||||
DebugMenuAddInt32_TYPE addint32;
|
||||
DebugMenuAddInt64_TYPE addint64;
|
||||
DebugMenuAddUInt8_TYPE adduint8;
|
||||
DebugMenuAddUInt16_TYPE adduint16;
|
||||
DebugMenuAddUInt32_TYPE adduint32;
|
||||
DebugMenuAddUInt64_TYPE adduint64;
|
||||
DebugMenuAddFloat32_TYPE addfloat32;
|
||||
DebugMenuAddFloat64_TYPE addfloat64;
|
||||
DebugMenuAddCmd_TYPE addcmd;
|
||||
DebugMenuEntrySetWrap_TYPE setwrap;
|
||||
DebugMenuEntrySetStrings_TYPE setstrings;
|
||||
DebugMenuEntrySetAddress_TYPE setaddress;
|
||||
};
|
||||
extern DebugMenuAPI gDebugMenuAPI;
|
||||
|
||||
inline DebugMenuEntry *DebugMenuAddInt8(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc, int8_t step, int8_t lowerBound, int8_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.addint8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddInt16(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc, int16_t step, int16_t lowerBound, int16_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.addint16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddInt32(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc, int32_t step, int32_t lowerBound, int32_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.addint32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddInt64(const char *path, const char *name, int64_t *ptr, TriggerFunc triggerFunc, int64_t step, int64_t lowerBound, int64_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.addint64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddUInt8(const char *path, const char *name, uint8_t *ptr, TriggerFunc triggerFunc, uint8_t step, uint8_t lowerBound, uint8_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.adduint8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddUInt16(const char *path, const char *name, uint16_t *ptr, TriggerFunc triggerFunc, uint16_t step, uint16_t lowerBound, uint16_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.adduint16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddUInt32(const char *path, const char *name, uint32_t *ptr, TriggerFunc triggerFunc, uint32_t step, uint32_t lowerBound, uint32_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.adduint32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddUInt64(const char *path, const char *name, uint64_t *ptr, TriggerFunc triggerFunc, uint64_t step, uint64_t lowerBound, uint64_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.adduint64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddFloat32(const char *path, const char *name, float *ptr, TriggerFunc triggerFunc, float step, float lowerBound, float upperBound)
|
||||
{ return gDebugMenuAPI.addfloat32(path, name, ptr, triggerFunc, step, lowerBound, upperBound); }
|
||||
inline DebugMenuEntry *DebugMenuAddFloat64(const char *path, const char *name, double *ptr, TriggerFunc triggerFunc, double step, double lowerBound, double upperBound)
|
||||
{ return gDebugMenuAPI.addfloat64(path, name, ptr, triggerFunc, step, lowerBound, upperBound); }
|
||||
inline DebugMenuEntry *DebugMenuAddCmd(const char *path, const char *name, TriggerFunc triggerFunc)
|
||||
{ return gDebugMenuAPI.addcmd(path, name, triggerFunc); }
|
||||
inline void DebugMenuEntrySetWrap(DebugMenuEntry *e, bool wrap)
|
||||
{ gDebugMenuAPI.setwrap(e, wrap); }
|
||||
inline void DebugMenuEntrySetStrings(DebugMenuEntry *e, const char **strings)
|
||||
{ gDebugMenuAPI.setstrings(e, strings); }
|
||||
inline void DebugMenuEntrySetAddress(DebugMenuEntry *e, void *addr)
|
||||
{ gDebugMenuAPI.setaddress(e, addr); }
|
||||
|
||||
inline bool DebugMenuLoad(void)
|
||||
{
|
||||
if(gDebugMenuAPI.isLoaded)
|
||||
return true;
|
||||
HMODULE mod = LoadLibraryA("debugmenu");
|
||||
if(mod == nil){
|
||||
char modulePath[MAX_PATH];
|
||||
HMODULE dllModule;
|
||||
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)&gDebugMenuAPI, &dllModule);
|
||||
GetModuleFileNameA(dllModule, modulePath, MAX_PATH);
|
||||
char *p = strchr(modulePath, '\\');
|
||||
if(p) p[1] = '\0';
|
||||
strcat(modulePath, "debugmenu");
|
||||
mod = LoadLibraryA(modulePath);
|
||||
}
|
||||
if(mod == nil)
|
||||
return false;
|
||||
gDebugMenuAPI.addint8 = (DebugMenuAddInt8_TYPE)GetProcAddress(mod, "DebugMenuAddInt8");
|
||||
gDebugMenuAPI.addint16 = (DebugMenuAddInt16_TYPE)GetProcAddress(mod, "DebugMenuAddInt16");
|
||||
gDebugMenuAPI.addint32 = (DebugMenuAddInt32_TYPE)GetProcAddress(mod, "DebugMenuAddInt32");
|
||||
gDebugMenuAPI.addint64 = (DebugMenuAddInt64_TYPE)GetProcAddress(mod, "DebugMenuAddInt64");
|
||||
gDebugMenuAPI.adduint8 = (DebugMenuAddUInt8_TYPE)GetProcAddress(mod, "DebugMenuAddUInt8");
|
||||
gDebugMenuAPI.adduint16 = (DebugMenuAddUInt16_TYPE)GetProcAddress(mod, "DebugMenuAddUInt16");
|
||||
gDebugMenuAPI.adduint32 = (DebugMenuAddUInt32_TYPE)GetProcAddress(mod, "DebugMenuAddUInt32");
|
||||
gDebugMenuAPI.adduint64 = (DebugMenuAddUInt64_TYPE)GetProcAddress(mod, "DebugMenuAddUInt64");
|
||||
gDebugMenuAPI.addfloat32 = (DebugMenuAddFloat32_TYPE)GetProcAddress(mod, "DebugMenuAddFloat32");
|
||||
gDebugMenuAPI.addfloat64 = (DebugMenuAddFloat64_TYPE)GetProcAddress(mod, "DebugMenuAddFloat64");
|
||||
gDebugMenuAPI.addcmd = (DebugMenuAddCmd_TYPE)GetProcAddress(mod, "DebugMenuAddCmd");
|
||||
gDebugMenuAPI.setwrap = (DebugMenuEntrySetWrap_TYPE)GetProcAddress(mod, "DebugMenuEntrySetWrap");
|
||||
gDebugMenuAPI.setstrings = (DebugMenuEntrySetStrings_TYPE)GetProcAddress(mod, "DebugMenuEntrySetStrings");
|
||||
gDebugMenuAPI.setaddress = (DebugMenuEntrySetAddress_TYPE)GetProcAddress(mod, "DebugMenuEntrySetAddress");
|
||||
gDebugMenuAPI.isLoaded = true;
|
||||
gDebugMenuAPI.module = mod;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Also overload them for simplicity
|
||||
|
||||
inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc, int8_t step, int8_t lowerBound, int8_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.addint8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc, int16_t step, int16_t lowerBound, int16_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.addint16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc, int32_t step, int32_t lowerBound, int32_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.addint32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int64_t *ptr, TriggerFunc triggerFunc, int64_t step, int64_t lowerBound, int64_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.addint64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint8_t *ptr, TriggerFunc triggerFunc, uint8_t step, uint8_t lowerBound, uint8_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.adduint8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint16_t *ptr, TriggerFunc triggerFunc, uint16_t step, uint16_t lowerBound, uint16_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.adduint16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint32_t *ptr, TriggerFunc triggerFunc, uint32_t step, uint32_t lowerBound, uint32_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.adduint32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint64_t *ptr, TriggerFunc triggerFunc, uint64_t step, uint64_t lowerBound, uint64_t upperBound, const char **strings)
|
||||
{ return gDebugMenuAPI.adduint64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }
|
||||
inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, float *ptr, TriggerFunc triggerFunc, float step, float lowerBound, float upperBound)
|
||||
{ return gDebugMenuAPI.addfloat32(path, name, ptr, triggerFunc, step, lowerBound, upperBound); }
|
||||
inline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, double *ptr, TriggerFunc triggerFunc, double step, double lowerBound, double upperBound)
|
||||
{ return gDebugMenuAPI.addfloat64(path, name, ptr, triggerFunc, step, lowerBound, upperBound); }
|
||||
|
||||
inline DebugMenuEntry *DebugMenuAddVarBool32(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc)
|
||||
{
|
||||
static const char *boolstr[] = { "Off", "On" };
|
||||
DebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr);
|
||||
DebugMenuEntrySetWrap(e, true);
|
||||
return e;
|
||||
}
|
||||
inline DebugMenuEntry *DebugMenuAddVarBool16(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc)
|
||||
{
|
||||
static const char *boolstr[] = { "Off", "On" };
|
||||
DebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr);
|
||||
DebugMenuEntrySetWrap(e, true);
|
||||
return e;
|
||||
}
|
||||
inline DebugMenuEntry *DebugMenuAddVarBool8(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc)
|
||||
{
|
||||
static const char *boolstr[] = { "Off", "On" };
|
||||
DebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr);
|
||||
DebugMenuEntrySetWrap(e, true);
|
||||
return e;
|
||||
}
|
||||
891
src/core/main.cpp
Normal file
891
src/core/main.cpp
Normal file
@@ -0,0 +1,891 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "main.h"
|
||||
#include "General.h"
|
||||
#include "RwHelper.h"
|
||||
#include "Clouds.h"
|
||||
#include "Draw.h"
|
||||
#include "Sprite2d.h"
|
||||
#include "Renderer.h"
|
||||
#include "Coronas.h"
|
||||
#include "WaterLevel.h"
|
||||
#include "Weather.h"
|
||||
#include "Glass.h"
|
||||
#include "WaterCannon.h"
|
||||
#include "SpecialFX.h"
|
||||
#include "Shadows.h"
|
||||
#include "Skidmarks.h"
|
||||
#include "Antennas.h"
|
||||
#include "Rubbish.h"
|
||||
#include "Particle.h"
|
||||
#include "Pickups.h"
|
||||
#include "WeaponEffects.h"
|
||||
#include "PointLights.h"
|
||||
#include "Fluff.h"
|
||||
#include "Replay.h"
|
||||
#include "Camera.h"
|
||||
#include "World.h"
|
||||
#include "Ped.h"
|
||||
#include "Font.h"
|
||||
#include "Pad.h"
|
||||
#include "Hud.h"
|
||||
#include "User.h"
|
||||
#include "Messages.h"
|
||||
#include "Darkel.h"
|
||||
#include "Garages.h"
|
||||
#include "MusicManager.h"
|
||||
#include "VisibilityPlugins.h"
|
||||
#include "NodeName.h"
|
||||
#include "DMAudio.h"
|
||||
#include "CutsceneMgr.h"
|
||||
#include "Lights.h"
|
||||
#include "Credits.h"
|
||||
#include "ZoneCull.h"
|
||||
#include "Timecycle.h"
|
||||
#include "TxdStore.h"
|
||||
#include "FileMgr.h"
|
||||
#include "Text.h"
|
||||
#include "RpAnimBlend.h"
|
||||
#include "Frontend.h"
|
||||
|
||||
#define DEFAULT_VIEWWINDOW (tan(DEGTORAD(CDraw::GetFOV() * 0.5f)))
|
||||
|
||||
|
||||
GlobalScene &Scene = *(GlobalScene*)0x726768;
|
||||
|
||||
uint8 work_buff[55000];
|
||||
char gString[256];
|
||||
wchar *gUString = (wchar*)0x74B018;
|
||||
|
||||
bool &b_FoundRecentSavedGameWantToLoad = *(bool*)0x95CDA8;
|
||||
|
||||
|
||||
bool DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);
|
||||
void DoRWStuffEndOfFrame(void);
|
||||
|
||||
void RenderScene(void);
|
||||
void RenderDebugShit(void);
|
||||
void RenderEffects(void);
|
||||
void Render2dStuff(void);
|
||||
void RenderMenus(void);
|
||||
void DoFade(void);
|
||||
void Render2dStuffAfterFade(void);
|
||||
|
||||
CSprite2d *LoadSplash(const char *name);
|
||||
void DestroySplashScreen(void);
|
||||
|
||||
|
||||
extern void (*DebugMenuProcess)(void);
|
||||
extern void (*DebugMenuRender)(void);
|
||||
void DebugMenuInit(void);
|
||||
void DebugMenuPopulate(void);
|
||||
|
||||
void PrintGameVersion();
|
||||
|
||||
RwRGBA gColourTop;
|
||||
|
||||
void
|
||||
InitialiseGame(void)
|
||||
{
|
||||
LoadingScreen(nil, nil, "loadsc0");
|
||||
CGame::Initialise("DATA\\GTA3.DAT");
|
||||
}
|
||||
|
||||
void
|
||||
Idle(void *arg)
|
||||
{
|
||||
#ifdef ASPECT_RATIO_SCALE
|
||||
CDraw::SetAspectRatio(CDraw::FindAspectRatio());
|
||||
#endif
|
||||
|
||||
CTimer::Update();
|
||||
CSprite2d::InitPerFrame();
|
||||
CFont::InitPerFrame();
|
||||
CPointLights::InitPerFrame();
|
||||
CGame::Process();
|
||||
DMAudio.Service();
|
||||
|
||||
if(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){
|
||||
FrontEndMenuManager.m_bStartGameLoading = true;
|
||||
FrontEndMenuManager.m_bLoadingSavedGame = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if(FrontEndMenuManager.m_bStartGameLoading || b_FoundRecentSavedGameWantToLoad)
|
||||
return;
|
||||
|
||||
SetLightsWithTimeOfDayColour(Scene.world);
|
||||
|
||||
if(arg == nil)
|
||||
return;
|
||||
|
||||
if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.field_452 == 1) &&
|
||||
TheCamera.GetScreenFadeStatus() != FADE_2){
|
||||
#ifdef GTA_PC
|
||||
// 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
|
||||
CRenderer::ConstructRenderList();
|
||||
CRenderer::PreRender();
|
||||
|
||||
if(CWeather::LightningFlash && !CCullZones::CamNoRain()){
|
||||
if(!DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255))
|
||||
return;
|
||||
}else{
|
||||
if(!DoRWStuffStartOfFrame_Horizon(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(),
|
||||
CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),
|
||||
255))
|
||||
return;
|
||||
}
|
||||
|
||||
DefinedState();
|
||||
|
||||
// BUG. This has to be done BEFORE RwCameraBeginUpdate
|
||||
RwCameraSetFarClipPlane(Scene.camera, CTimeCycle::GetFarClip());
|
||||
RwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart());
|
||||
|
||||
RenderScene();
|
||||
RenderDebugShit();
|
||||
RenderEffects();
|
||||
|
||||
if((TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_NORMAL) &&
|
||||
TheCamera.m_ScreenReductionPercentage > 0.0)
|
||||
TheCamera.SetMotionBlurAlpha(150);
|
||||
TheCamera.RenderMotionBlur();
|
||||
|
||||
Render2dStuff();
|
||||
}else{
|
||||
float viewWindow = DEFAULT_VIEWWINDOW;
|
||||
CameraSize(Scene.camera, nil, viewWindow, DEFAULT_ASPECT_RATIO);
|
||||
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
|
||||
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
|
||||
if(!RsCameraBeginUpdate(Scene.camera))
|
||||
return;
|
||||
}
|
||||
|
||||
RenderMenus();
|
||||
#ifndef FINAL
|
||||
PrintGameVersion();
|
||||
#endif
|
||||
DoFade();
|
||||
Render2dStuffAfterFade();
|
||||
CCredits::Render();
|
||||
DoRWStuffEndOfFrame();
|
||||
|
||||
// if(g_SlowMode)
|
||||
// ProcessSlowMode();
|
||||
}
|
||||
|
||||
void
|
||||
FrontendIdle(void)
|
||||
{
|
||||
#ifdef ASPECT_RATIO_SCALE
|
||||
CDraw::SetAspectRatio(CDraw::FindAspectRatio());
|
||||
#endif
|
||||
|
||||
CTimer::Update();
|
||||
CSprite2d::SetRecipNearClip();
|
||||
CSprite2d::InitPerFrame();
|
||||
CFont::InitPerFrame();
|
||||
CPad::UpdatePads();
|
||||
FrontEndMenuManager.Process();
|
||||
|
||||
if(RsGlobal.quit)
|
||||
return;
|
||||
|
||||
float viewWindow = DEFAULT_VIEWWINDOW;
|
||||
CameraSize(Scene.camera, nil, viewWindow, DEFAULT_ASPECT_RATIO);
|
||||
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
|
||||
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
|
||||
if(!RsCameraBeginUpdate(Scene.camera))
|
||||
return;
|
||||
|
||||
DefinedState();
|
||||
RenderMenus();
|
||||
#ifndef FINAL
|
||||
PrintGameVersion();
|
||||
#endif
|
||||
DoFade();
|
||||
Render2dStuffAfterFade();
|
||||
CFont::DrawFonts();
|
||||
DoRWStuffEndOfFrame();
|
||||
}
|
||||
|
||||
bool
|
||||
DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha)
|
||||
{
|
||||
CRGBA TopColor(TopRed, TopGreen, TopBlue, Alpha);
|
||||
CRGBA BottomColor(BottomRed, BottomGreen, BottomBlue, Alpha);
|
||||
|
||||
CameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, SCREEN_ASPECT_RATIO);
|
||||
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
|
||||
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
|
||||
|
||||
if(!RsCameraBeginUpdate(Scene.camera))
|
||||
return false;
|
||||
|
||||
CSprite2d::InitPerFrame();
|
||||
|
||||
if(Alpha != 0)
|
||||
CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), BottomColor, BottomColor, TopColor, TopColor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha)
|
||||
{
|
||||
CameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, SCREEN_ASPECT_RATIO);
|
||||
CVisibilityPlugins::SetRenderWareCamera(Scene.camera);
|
||||
RwCameraClear(Scene.camera, &gColourTop, rwCAMERACLEARZ);
|
||||
|
||||
if(!RsCameraBeginUpdate(Scene.camera))
|
||||
return false;
|
||||
|
||||
TheCamera.m_viewMatrix.Update();
|
||||
CClouds::RenderBackground(TopRed, TopGreen, TopBlue, BottomRed, BottomGreen, BottomBlue, Alpha);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DoRWStuffEndOfFrame(void)
|
||||
{
|
||||
// CDebug::DebugDisplayTextBuffer();
|
||||
// FlushObrsPrintfs();
|
||||
RwCameraEndUpdate(Scene.camera);
|
||||
RsCameraShowRaster(Scene.camera);
|
||||
}
|
||||
|
||||
|
||||
// This is certainly a very useful function
|
||||
void
|
||||
DoRWRenderHorizon(void)
|
||||
{
|
||||
CClouds::RenderHorizon();
|
||||
}
|
||||
|
||||
void
|
||||
RenderScene(void)
|
||||
{
|
||||
CClouds::Render();
|
||||
DoRWRenderHorizon();
|
||||
CRenderer::RenderRoads();
|
||||
CCoronas::RenderReflections();
|
||||
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);
|
||||
CRenderer::RenderEverythingBarRoads();
|
||||
CRenderer::RenderBoats();
|
||||
DefinedState();
|
||||
CWaterLevel::RenderWater();
|
||||
CRenderer::RenderFadingInEntities();
|
||||
CRenderer::RenderVehiclesButNotBoats();
|
||||
CWeather::RenderRainStreaks();
|
||||
}
|
||||
|
||||
void
|
||||
RenderDebugShit(void)
|
||||
{
|
||||
// CTheScripts::RenderTheScriptDebugLines()
|
||||
}
|
||||
|
||||
void
|
||||
RenderEffects(void)
|
||||
{
|
||||
CGlass::Render();
|
||||
CWaterCannons::Render();
|
||||
CSpecialFX::Render();
|
||||
CShadows::RenderStaticShadows();
|
||||
CShadows::RenderStoredShadows();
|
||||
CSkidmarks::Render();
|
||||
CAntennas::Render();
|
||||
CRubbish::Render();
|
||||
CCoronas::Render();
|
||||
CParticle::Render();
|
||||
CPacManPickups::Render();
|
||||
CWeaponEffects::Render();
|
||||
CPointLights::RenderFogEffect();
|
||||
CMovingThings::Render();
|
||||
CRenderer::RenderFirstPersonVehicle();
|
||||
}
|
||||
|
||||
void
|
||||
Render2dStuff(void)
|
||||
{
|
||||
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
|
||||
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
|
||||
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
|
||||
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
|
||||
RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
|
||||
|
||||
CReplay::Display();
|
||||
CPickups::RenderPickUpText();
|
||||
|
||||
if(TheCamera.m_WideScreenOn)
|
||||
TheCamera.DrawBordersForWideScreen();
|
||||
|
||||
CPed *player = FindPlayerPed();
|
||||
int weaponType = 0;
|
||||
if(player)
|
||||
weaponType = player->GetWeapon()->m_eWeaponType;
|
||||
|
||||
bool firstPersonWeapon = false;
|
||||
int cammode = TheCamera.Cams[TheCamera.ActiveCam].Mode;
|
||||
if(cammode == CCam::MODE_SNIPER ||
|
||||
cammode == CCam::MODE_SNIPER_RUN_AROUND ||
|
||||
cammode == CCam::MODE_ROCKET ||
|
||||
cammode == CCam::MODE_ROCKET_RUN_AROUND)
|
||||
firstPersonWeapon = true;
|
||||
|
||||
// Draw black border for sniper and rocket launcher
|
||||
if((weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_ROCKETLAUNCHER) && firstPersonWeapon){
|
||||
CRGBA black(0, 0, 0, 255);
|
||||
|
||||
// top and bottom strips
|
||||
if (weaponType == WEAPONTYPE_ROCKETLAUNCHER) {
|
||||
CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(180)), black);
|
||||
CSprite2d::DrawRect(CRect(0.0f, SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(170), SCREEN_WIDTH, SCREEN_HEIGHT), black);
|
||||
}
|
||||
else {
|
||||
CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(210)), black);
|
||||
CSprite2d::DrawRect(CRect(0.0f, SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(210), SCREEN_WIDTH, SCREEN_HEIGHT), black);
|
||||
}
|
||||
CSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH / 2 - SCREEN_SCALE_X(210), SCREEN_HEIGHT), black);
|
||||
CSprite2d::DrawRect(CRect(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(210), 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), black);
|
||||
}
|
||||
|
||||
MusicManager.DisplayRadioStationName();
|
||||
// TheConsole.Display();
|
||||
/*
|
||||
if(CSceneEdit::m_bEditOn)
|
||||
CSceneEdit::Draw();
|
||||
else
|
||||
*/
|
||||
CHud::Draw();
|
||||
CUserDisplay::OnscnTimer.ProcessForDisplay();
|
||||
CMessages::Display();
|
||||
CDarkel::DrawMessages();
|
||||
CGarages::PrintMessages();
|
||||
CPad::PrintErrorMessage();
|
||||
CFont::DrawFonts();
|
||||
|
||||
DebugMenuRender();
|
||||
}
|
||||
|
||||
void
|
||||
RenderMenus(void)
|
||||
{
|
||||
if(FrontEndMenuManager.m_bMenuActive)
|
||||
FrontEndMenuManager.DrawFrontEnd();
|
||||
}
|
||||
|
||||
bool &JustLoadedDontFadeInYet = *(bool*)0x95CDB4;
|
||||
bool &StillToFadeOut = *(bool*)0x95CD99;
|
||||
uint32 &TimeStartedCountingForFade = *(uint32*)0x9430EC;
|
||||
uint32 &TimeToStayFadedBeforeFadeOut = *(uint32*)0x611564;
|
||||
|
||||
void
|
||||
DoFade(void)
|
||||
{
|
||||
if(CTimer::GetIsPaused())
|
||||
return;
|
||||
|
||||
if(JustLoadedDontFadeInYet){
|
||||
JustLoadedDontFadeInYet = false;
|
||||
TimeStartedCountingForFade = CTimer::GetTimeInMilliseconds();
|
||||
}
|
||||
|
||||
if(StillToFadeOut){
|
||||
if(CTimer::GetTimeInMilliseconds() - TimeStartedCountingForFade > TimeToStayFadedBeforeFadeOut){
|
||||
StillToFadeOut = false;
|
||||
TheCamera.Fade(3.0f, FADE_IN);
|
||||
TheCamera.ProcessFade();
|
||||
TheCamera.ProcessMusicFade();
|
||||
}else{
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(0.0f, FADE_OUT);
|
||||
TheCamera.ProcessFade();
|
||||
}
|
||||
}
|
||||
|
||||
if(CDraw::FadeValue != 0 || CMenuManager::m_PrefsBrightness < 256){
|
||||
CSprite2d *splash = LoadSplash(nil);
|
||||
|
||||
CRGBA fadeColor;
|
||||
CRect rect;
|
||||
int fadeValue = CDraw::FadeValue;
|
||||
float brightness = min(CMenuManager::m_PrefsBrightness, 256);
|
||||
if(brightness <= 50)
|
||||
brightness = 50;
|
||||
if(FrontEndMenuManager.m_bMenuActive)
|
||||
brightness = 256;
|
||||
|
||||
if(TheCamera.m_FadeTargetIsSplashScreen)
|
||||
fadeValue = 0;
|
||||
|
||||
float fade = fadeValue + 256 - brightness;
|
||||
if(fade == 0){
|
||||
fadeColor.r = 0;
|
||||
fadeColor.g = 0;
|
||||
fadeColor.b = 0;
|
||||
fadeColor.a = 0;
|
||||
}else{
|
||||
fadeColor.r = fadeValue * CDraw::FadeRed / fade;
|
||||
fadeColor.g = fadeValue * CDraw::FadeGreen / fade;
|
||||
fadeColor.b = fadeValue * CDraw::FadeBlue / fade;
|
||||
int alpha = 255 - brightness*(256 - fadeValue)/256;
|
||||
if(alpha < 0)
|
||||
alpha = 0;
|
||||
fadeColor.a = alpha;
|
||||
}
|
||||
|
||||
if(TheCamera.m_WideScreenOn){
|
||||
// what's this?
|
||||
float y = SCREEN_HEIGHT/2 * TheCamera.m_ScreenReductionPercentage/100.0f;
|
||||
rect.left = 0.0f;
|
||||
rect.right = SCREEN_WIDTH;
|
||||
rect.top = y - 8.0f;
|
||||
rect.bottom = SCREEN_HEIGHT - y - 8.0f;
|
||||
}else{
|
||||
rect.left = 0.0f;
|
||||
rect.right = SCREEN_WIDTH;
|
||||
rect.top = 0.0f;
|
||||
rect.bottom = SCREEN_HEIGHT;
|
||||
}
|
||||
CSprite2d::DrawRect(rect, fadeColor);
|
||||
|
||||
if(CDraw::FadeValue != 0 && TheCamera.m_FadeTargetIsSplashScreen){
|
||||
fadeColor.r = 255;
|
||||
fadeColor.g = 255;
|
||||
fadeColor.b = 255;
|
||||
fadeColor.a = CDraw::FadeValue;
|
||||
splash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), fadeColor, fadeColor, fadeColor, fadeColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Render2dStuffAfterFade(void)
|
||||
{
|
||||
CHud::DrawAfterFade();
|
||||
CFont::DrawFonts();
|
||||
}
|
||||
|
||||
CSprite2d splash;
|
||||
int splashTxdId = -1;
|
||||
|
||||
CSprite2d*
|
||||
LoadSplash(const char *name)
|
||||
{
|
||||
RwTexDictionary *txd;
|
||||
char filename[140];
|
||||
RwTexture *tex = nil;
|
||||
|
||||
if(name == nil)
|
||||
return &splash;
|
||||
if(splashTxdId == -1)
|
||||
splashTxdId = CTxdStore::AddTxdSlot("splash");
|
||||
|
||||
txd = CTxdStore::GetSlot(splashTxdId)->texDict;
|
||||
if(txd)
|
||||
tex = RwTexDictionaryFindNamedTexture(txd, name);
|
||||
// if texture is found, splash was already set up below
|
||||
|
||||
if(tex == nil){
|
||||
CFileMgr::SetDir("TXD\\");
|
||||
sprintf(filename, "%s.txd", name);
|
||||
if(splash.m_pTexture)
|
||||
splash.Delete();
|
||||
if(txd)
|
||||
CTxdStore::RemoveTxd(splashTxdId);
|
||||
CTxdStore::LoadTxd(splashTxdId, filename);
|
||||
CTxdStore::AddRef(splashTxdId);
|
||||
CTxdStore::PushCurrentTxd();
|
||||
CTxdStore::SetCurrentTxd(splashTxdId);
|
||||
splash.SetTexture(name);
|
||||
CTxdStore::PopCurrentTxd();
|
||||
CFileMgr::SetDir("");
|
||||
}
|
||||
|
||||
return &splash;
|
||||
}
|
||||
|
||||
void
|
||||
DestroySplashScreen(void)
|
||||
{
|
||||
splash.Delete();
|
||||
if(splashTxdId != -1)
|
||||
CTxdStore::RemoveTxdSlot(splashTxdId);
|
||||
splashTxdId = -1;
|
||||
}
|
||||
|
||||
float NumberOfChunksLoaded;
|
||||
#define TOTALNUMCHUNKS 73.0f
|
||||
|
||||
// TODO: compare with PS2
|
||||
void
|
||||
LoadingScreen(const char *str1, const char *str2, const char *splashscreen)
|
||||
{
|
||||
CSprite2d *splash;
|
||||
|
||||
#ifndef RANDOMSPLASH
|
||||
if(CGame::frenchGame || CGame::germanGame || !CGame::nastyGame)
|
||||
splashscreen = "mainsc2";
|
||||
else
|
||||
splashscreen = "mainsc1";
|
||||
#endif
|
||||
|
||||
splash = LoadSplash(splashscreen);
|
||||
|
||||
if(RsGlobal.quit)
|
||||
return;
|
||||
|
||||
if(DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255)){
|
||||
CSprite2d::SetRecipNearClip();
|
||||
CSprite2d::InitPerFrame();
|
||||
CFont::InitPerFrame();
|
||||
DefinedState();
|
||||
RwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);
|
||||
splash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));
|
||||
|
||||
if(str1){
|
||||
NumberOfChunksLoaded += 1;
|
||||
|
||||
float hpos = SCREEN_SCALE_X(40);
|
||||
float length = SCREEN_WIDTH - SCREEN_SCALE_X(100);
|
||||
float vpos = SCREEN_HEIGHT - SCREEN_SCALE_Y(13);
|
||||
float height = SCREEN_SCALE_Y(7);
|
||||
CSprite2d::DrawRect(CRect(hpos, vpos, hpos + length, vpos + height), CRGBA(40, 53, 68, 255));
|
||||
|
||||
length *= NumberOfChunksLoaded/TOTALNUMCHUNKS;
|
||||
CSprite2d::DrawRect(CRect(hpos, vpos, hpos + length, vpos + height), CRGBA(81, 106, 137, 255));
|
||||
|
||||
// this is done by the game but is unused
|
||||
CFont::SetScale(SCREEN_SCALE_X(2), SCREEN_SCALE_Y(2));
|
||||
CFont::SetPropOn();
|
||||
CFont::SetRightJustifyOn();
|
||||
CFont::SetFontStyle(FONT_HEADING);
|
||||
|
||||
#ifdef CHATTYSPLASH
|
||||
// my attempt
|
||||
static wchar tmpstr[80];
|
||||
float scale = SCREEN_SCALE_Y(0.8f);
|
||||
vpos -= 50*scale;
|
||||
CFont::SetScale(scale, scale);
|
||||
CFont::SetPropOn();
|
||||
CFont::SetRightJustifyOff();
|
||||
CFont::SetFontStyle(FONT_BANK);
|
||||
CFont::SetColor(CRGBA(255, 255, 255, 255));
|
||||
AsciiToUnicode(str1, tmpstr);
|
||||
CFont::PrintString(hpos, vpos, tmpstr);
|
||||
vpos += 25*scale;
|
||||
AsciiToUnicode(str2, tmpstr);
|
||||
CFont::PrintString(hpos, vpos, tmpstr);
|
||||
#endif
|
||||
}
|
||||
|
||||
CFont::DrawFonts();
|
||||
DoRWStuffEndOfFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ResetLoadingScreenBar(void)
|
||||
{
|
||||
NumberOfChunksLoaded = 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
LoadingIslandScreen(const char *levelName)
|
||||
{
|
||||
CSprite2d *splash;
|
||||
wchar *name;
|
||||
char str[100];
|
||||
wchar wstr[80];
|
||||
CRGBA col;
|
||||
|
||||
splash = LoadSplash(nil);
|
||||
name = TheText.Get(levelName);
|
||||
if(!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255))
|
||||
return;
|
||||
|
||||
CSprite2d::SetRecipNearClip();
|
||||
CSprite2d::InitPerFrame();
|
||||
CFont::InitPerFrame();
|
||||
DefinedState();
|
||||
col = CRGBA(255, 255, 255, 255);
|
||||
splash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), col, col, col, col);
|
||||
CFont::SetBackgroundOff();
|
||||
CFont::SetScale(1.5f, 1.5f);
|
||||
CFont::SetPropOn();
|
||||
CFont::SetRightJustifyOn();
|
||||
CFont::SetRightJustifyWrap(150.0f);
|
||||
CFont::SetFontStyle(FONT_HEADING);
|
||||
sprintf(str, "WELCOME TO");
|
||||
AsciiToUnicode(str, wstr);
|
||||
CFont::SetDropColor(CRGBA(0, 0, 0, 255));
|
||||
CFont::SetDropShadowPosition(3);
|
||||
CFont::SetColor(CRGBA(243, 237, 71, 255));
|
||||
CFont::SetScale(SCREEN_STRETCH_X(1.2f), SCREEN_STRETCH_Y(1.2f));
|
||||
CFont::PrintString(SCREEN_WIDTH - 20, SCREEN_STRETCH_FROM_BOTTOM(110.0f), TheText.Get("WELCOME"));
|
||||
TextCopy(wstr, name);
|
||||
TheText.UpperCase(wstr);
|
||||
CFont::SetColor(CRGBA(243, 237, 71, 255));
|
||||
CFont::SetScale(SCREEN_STRETCH_X(1.2f), SCREEN_STRETCH_Y(1.2f));
|
||||
CFont::PrintString(SCREEN_WIDTH-20, SCREEN_STRETCH_FROM_BOTTOM(80.0f), wstr);
|
||||
CFont::DrawFonts();
|
||||
DoRWStuffEndOfFrame();
|
||||
}
|
||||
|
||||
char*
|
||||
GetLevelSplashScreen(int level)
|
||||
{
|
||||
static char *splashScreens[4] = {
|
||||
nil,
|
||||
"splash1",
|
||||
"splash2",
|
||||
"splash3",
|
||||
};
|
||||
|
||||
return splashScreens[level];
|
||||
}
|
||||
|
||||
char*
|
||||
GetRandomSplashScreen(void)
|
||||
{
|
||||
int index;
|
||||
static int index2 = 0;
|
||||
static char splashName[128];
|
||||
static int splashIndex[24] = {
|
||||
25, 22, 4, 13,
|
||||
1, 21, 14, 16,
|
||||
10, 12, 5, 9,
|
||||
11, 18, 3, 2,
|
||||
19, 23, 7, 17,
|
||||
15, 6, 8, 20
|
||||
};
|
||||
|
||||
index = splashIndex[4*index2 + CGeneral::GetRandomNumberInRange(0, 3)];
|
||||
index2++;
|
||||
if(index2 == 6)
|
||||
index2 = 0;
|
||||
sprintf(splashName, "loadsc%d", index);
|
||||
return splashName;
|
||||
}
|
||||
|
||||
#include "rwcore.h"
|
||||
#include "rpworld.h"
|
||||
#include "rpmatfx.h"
|
||||
#include "rpskin.h"
|
||||
#include "rphanim.h"
|
||||
#include "rtbmp.h"
|
||||
|
||||
_TODO("temp, move this includes out of here")
|
||||
|
||||
static RwBool
|
||||
PluginAttach(void)
|
||||
{
|
||||
if( !RpWorldPluginAttach() )
|
||||
{
|
||||
printf("Couldn't attach world plugin\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( !RpSkinPluginAttach() )
|
||||
{
|
||||
printf("Couldn't attach RpSkin plugin\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( !RpHAnimPluginAttach() )
|
||||
{
|
||||
printf("Couldn't attach RpHAnim plugin\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( !NodeNamePluginAttach() )
|
||||
{
|
||||
printf("Couldn't attach node name plugin\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( !CVisibilityPlugins::PluginAttach() )
|
||||
{
|
||||
printf("Couldn't attach visibility plugins\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( !RpAnimBlendPluginAttach() )
|
||||
{
|
||||
printf("Couldn't attach RpAnimBlend plugin\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( !RpMatFXPluginAttach() )
|
||||
{
|
||||
printf("Couldn't attach RpMatFX plugin\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static RwBool
|
||||
Initialise3D(void *param)
|
||||
{
|
||||
if (RsRwInitialise(param))
|
||||
{
|
||||
//
|
||||
DebugMenuInit();
|
||||
DebugMenuPopulate();
|
||||
//
|
||||
|
||||
return CGame::InitialiseRenderWare();
|
||||
}
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Terminate3D(void)
|
||||
{
|
||||
CGame::ShutdownRenderWare();
|
||||
|
||||
RsRwTerminate();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
RsEventStatus
|
||||
AppEventHandler(RsEvent event, void *param)
|
||||
{
|
||||
switch( event )
|
||||
{
|
||||
case rsINITIALISE:
|
||||
{
|
||||
CGame::InitialiseOnceBeforeRW();
|
||||
return RsInitialise() ? rsEVENTPROCESSED : rsEVENTERROR;
|
||||
}
|
||||
|
||||
case rsCAMERASIZE:
|
||||
{
|
||||
|
||||
CameraSize(Scene.camera, (RwRect *)param,
|
||||
DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO);
|
||||
|
||||
return rsEVENTPROCESSED;
|
||||
}
|
||||
|
||||
case rsRWINITIALISE:
|
||||
{
|
||||
return Initialise3D(param) ? rsEVENTPROCESSED : rsEVENTERROR;
|
||||
}
|
||||
|
||||
case rsRWTERMINATE:
|
||||
{
|
||||
Terminate3D();
|
||||
|
||||
return rsEVENTPROCESSED;
|
||||
}
|
||||
|
||||
case rsTERMINATE:
|
||||
{
|
||||
CGame::FinalShutdown();
|
||||
|
||||
return rsEVENTPROCESSED;
|
||||
}
|
||||
|
||||
case rsPLUGINATTACH:
|
||||
{
|
||||
return PluginAttach() ? rsEVENTPROCESSED : rsEVENTERROR;
|
||||
}
|
||||
|
||||
case rsINPUTDEVICEATTACH:
|
||||
{
|
||||
AttachInputDevices();
|
||||
|
||||
return rsEVENTPROCESSED;
|
||||
}
|
||||
|
||||
case rsIDLE:
|
||||
{
|
||||
Idle(param);
|
||||
|
||||
return rsEVENTPROCESSED;
|
||||
}
|
||||
|
||||
case rsFRONTENDIDLE:
|
||||
{
|
||||
FrontendIdle();
|
||||
|
||||
return rsEVENTPROCESSED;
|
||||
}
|
||||
|
||||
case rsACTIVATE:
|
||||
{
|
||||
param ? DMAudio.ReacquireDigitalHandle() : DMAudio.ReleaseDigitalHandle();
|
||||
|
||||
return rsEVENTPROCESSED;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return rsEVENTNOTPROCESSED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintGameVersion()
|
||||
{
|
||||
CFont::SetPropOn();
|
||||
CFont::SetBackgroundOff();
|
||||
CFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(0.5f));
|
||||
CFont::SetCentreOff();
|
||||
CFont::SetRightJustifyOff();
|
||||
CFont::SetBackGroundOnlyTextOff();
|
||||
CFont::SetFontStyle(FONT_BANK);
|
||||
CFont::SetWrapx(SCREEN_WIDTH);
|
||||
CFont::SetDropShadowPosition(0);
|
||||
CFont::SetDropColor(CRGBA(0, 0, 0, 255));
|
||||
CFont::SetColor(CRGBA(235, 170, 50, 255));
|
||||
|
||||
strcpy(gString, "RE3");
|
||||
AsciiToUnicode(gString, gUString);
|
||||
CFont::PrintString(SCREEN_SCALE_X(10.5f), SCREEN_SCALE_Y(8.0f), gUString);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x48E480, Idle, PATCH_JUMP);
|
||||
InjectHook(0x48E700, FrontendIdle, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x48CF10, DoRWStuffStartOfFrame, PATCH_JUMP);
|
||||
InjectHook(0x48D040, DoRWStuffStartOfFrame_Horizon, PATCH_JUMP);
|
||||
InjectHook(0x48E030, RenderScene, PATCH_JUMP);
|
||||
InjectHook(0x48E080, RenderDebugShit, PATCH_JUMP);
|
||||
InjectHook(0x48E090, RenderEffects, PATCH_JUMP);
|
||||
InjectHook(0x48E0E0, Render2dStuff, PATCH_JUMP);
|
||||
InjectHook(0x48E450, RenderMenus, PATCH_JUMP);
|
||||
InjectHook(0x48D120, DoFade, PATCH_JUMP);
|
||||
InjectHook(0x48E470, Render2dStuffAfterFade, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x48D550, LoadSplash, PATCH_JUMP);
|
||||
InjectHook(0x48D670, DestroySplashScreen, PATCH_JUMP);
|
||||
InjectHook(0x48D770, LoadingScreen, PATCH_JUMP);
|
||||
InjectHook(0x48D760, ResetLoadingScreenBar, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x48D470, PluginAttach, PATCH_JUMP);
|
||||
InjectHook(0x48D520, Initialise3D, PATCH_JUMP);
|
||||
InjectHook(0x48D540, Terminate3D, PATCH_JUMP);
|
||||
InjectHook(0x48E800, AppEventHandler, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
22
src/core/main.h
Normal file
22
src/core/main.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
struct GlobalScene
|
||||
{
|
||||
RpWorld *world;
|
||||
RwCamera *camera;
|
||||
};
|
||||
extern GlobalScene &Scene;
|
||||
|
||||
extern uint8 work_buff[55000];
|
||||
extern char gString[256];
|
||||
extern wchar *gUString;
|
||||
extern bool &b_FoundRecentSavedGameWantToLoad;
|
||||
|
||||
class CSprite2d;
|
||||
|
||||
void InitialiseGame(void);
|
||||
void LoadingScreen(const char *str1, const char *str2, const char *splashscreen);
|
||||
void LoadingIslandScreen(const char *levelName);
|
||||
CSprite2d *LoadSplash(const char *name);
|
||||
char *GetLevelSplashScreen(int level);
|
||||
char *GetRandomSplashScreen(void);
|
||||
22
src/core/patcher.cpp
Normal file
22
src/core/patcher.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
|
||||
StaticPatcher *StaticPatcher::ms_head;
|
||||
|
||||
StaticPatcher::StaticPatcher(Patcher func)
|
||||
: m_func(func)
|
||||
{
|
||||
m_next = ms_head;
|
||||
ms_head = this;
|
||||
}
|
||||
|
||||
void
|
||||
StaticPatcher::Apply()
|
||||
{
|
||||
StaticPatcher *current = ms_head;
|
||||
while(current){
|
||||
current->Run();
|
||||
current = current->m_next;
|
||||
}
|
||||
ms_head = nil;
|
||||
}
|
||||
192
src/core/patcher.h
Normal file
192
src/core/patcher.h
Normal file
@@ -0,0 +1,192 @@
|
||||
#pragma once
|
||||
|
||||
#define WRAPPER __declspec(naked)
|
||||
#define DEPRECATED __declspec(deprecated)
|
||||
#define EAXJMP(a) { _asm mov eax, a _asm jmp eax }
|
||||
#define VARJMP(a) { _asm jmp a }
|
||||
#define WRAPARG(a) UNREFERENCED_PARAMETER(a)
|
||||
|
||||
#define NOVMT __declspec(novtable)
|
||||
#define SETVMT(a) *((DWORD_PTR*)this) = (DWORD_PTR)a
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PATCH_CALL,
|
||||
PATCH_JUMP,
|
||||
PATCH_NOTHING,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
III_10 = 1,
|
||||
III_11,
|
||||
III_STEAM,
|
||||
VC_10,
|
||||
VC_11,
|
||||
VC_STEAM
|
||||
};
|
||||
|
||||
extern int gtaversion;
|
||||
|
||||
class StaticPatcher
|
||||
{
|
||||
private:
|
||||
using Patcher = void(*)();
|
||||
|
||||
Patcher m_func;
|
||||
StaticPatcher *m_next;
|
||||
static StaticPatcher *ms_head;
|
||||
|
||||
void Run() { m_func(); }
|
||||
public:
|
||||
StaticPatcher(Patcher func);
|
||||
static void Apply();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline T AddressByVersion(uint32_t addressIII10, uint32_t addressIII11, uint32_t addressIIISteam, uint32_t addressvc10, uint32_t addressvc11, uint32_t addressvcSteam)
|
||||
{
|
||||
if(gtaversion == -1){
|
||||
if(*(uint32_t*)0x5C1E75 == 0xB85548EC) gtaversion = III_10;
|
||||
else if(*(uint32_t*)0x5C2135 == 0xB85548EC) gtaversion = III_11;
|
||||
else if(*(uint32_t*)0x5C6FD5 == 0xB85548EC) gtaversion = III_STEAM;
|
||||
else if(*(uint32_t*)0x667BF5 == 0xB85548EC) gtaversion = VC_10;
|
||||
else if(*(uint32_t*)0x667C45 == 0xB85548EC) gtaversion = VC_11;
|
||||
else if(*(uint32_t*)0x666BA5 == 0xB85548EC) gtaversion = VC_STEAM;
|
||||
else gtaversion = 0;
|
||||
}
|
||||
switch(gtaversion){
|
||||
case III_10:
|
||||
return (T)addressIII10;
|
||||
case III_11:
|
||||
return (T)addressIII11;
|
||||
case III_STEAM:
|
||||
return (T)addressIIISteam;
|
||||
case VC_10:
|
||||
return (T)addressvc10;
|
||||
case VC_11:
|
||||
return (T)addressvc11;
|
||||
case VC_STEAM:
|
||||
return (T)addressvcSteam;
|
||||
default:
|
||||
return (T)0;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
is10(void)
|
||||
{
|
||||
return gtaversion == III_10 || gtaversion == VC_10;
|
||||
}
|
||||
|
||||
inline bool
|
||||
isIII(void)
|
||||
{
|
||||
return gtaversion >= III_10 && gtaversion <= III_STEAM;
|
||||
}
|
||||
|
||||
inline bool
|
||||
isVC(void)
|
||||
{
|
||||
return gtaversion >= VC_10 && gtaversion <= VC_STEAM;
|
||||
}
|
||||
|
||||
#define PTRFROMCALL(addr) (uint32_t)(*(uint32_t*)((uint32_t)addr+1) + (uint32_t)addr + 5)
|
||||
#define INTERCEPT(saved, func, a) \
|
||||
{ \
|
||||
saved = PTRFROMCALL(a); \
|
||||
InjectHook(a, func); \
|
||||
}
|
||||
|
||||
template<typename T, typename AT> inline void
|
||||
Patch(AT address, T value)
|
||||
{
|
||||
DWORD dwProtect[2];
|
||||
VirtualProtect((void*)address, sizeof(T), PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
*(T*)address = value;
|
||||
VirtualProtect((void*)address, sizeof(T), dwProtect[0], &dwProtect[1]);
|
||||
}
|
||||
|
||||
template<typename AT> inline void
|
||||
Nop(AT address, unsigned int nCount)
|
||||
{
|
||||
DWORD dwProtect[2];
|
||||
VirtualProtect((void*)address, nCount, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
memset((void*)address, 0x90, nCount);
|
||||
VirtualProtect((void*)address, nCount, dwProtect[0], &dwProtect[1]);
|
||||
}
|
||||
|
||||
template<typename AT> inline void
|
||||
ClearCC(AT address, unsigned int nCount)
|
||||
{
|
||||
DWORD dwProtect[2];
|
||||
VirtualProtect((void*)address, nCount, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
memset((void*)address, 0xCC, nCount);
|
||||
VirtualProtect((void*)address, nCount, dwProtect[0], &dwProtect[1]);
|
||||
}
|
||||
|
||||
extern std::vector<int32> usedAddresses;
|
||||
|
||||
template<typename AT, typename HT> inline void
|
||||
InjectHook(AT address, HT hook, unsigned int nType=PATCH_NOTHING)
|
||||
{
|
||||
if(std::any_of(usedAddresses.begin(), usedAddresses.end(),
|
||||
[address](AT value) { return (int32)value == address; })) {
|
||||
debug("Used address %#06x twice when injecting hook\n", address);
|
||||
}
|
||||
|
||||
usedAddresses.push_back((int32)address);
|
||||
|
||||
DWORD dwProtect[2];
|
||||
switch ( nType )
|
||||
{
|
||||
case PATCH_JUMP:
|
||||
VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
*(BYTE*)address = 0xE9;
|
||||
break;
|
||||
case PATCH_CALL:
|
||||
VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
*(BYTE*)address = 0xE8;
|
||||
break;
|
||||
default:
|
||||
VirtualProtect((void*)((DWORD)address + 1), 4, PAGE_EXECUTE_READWRITE, &dwProtect[0]);
|
||||
break;
|
||||
}
|
||||
DWORD dwHook;
|
||||
_asm
|
||||
{
|
||||
mov eax, hook
|
||||
mov dwHook, eax
|
||||
}
|
||||
|
||||
*(ptrdiff_t*)((DWORD)address + 1) = (DWORD)dwHook - (DWORD)address - 5;
|
||||
if ( nType == PATCH_NOTHING )
|
||||
VirtualProtect((void*)((DWORD)address + 1), 4, dwProtect[0], &dwProtect[1]);
|
||||
else
|
||||
VirtualProtect((void*)address, 5, dwProtect[0], &dwProtect[1]);
|
||||
}
|
||||
|
||||
inline void ExtractCall(void *dst, uint32_t a)
|
||||
{
|
||||
*(uint32_t*)dst = (uint32_t)(*(uint32_t*)(a+1) + a + 5);
|
||||
}
|
||||
template<typename T>
|
||||
inline void InterceptCall(void *dst, T func, uint32_t a)
|
||||
{
|
||||
ExtractCall(dst, a);
|
||||
InjectHook(a, func);
|
||||
}
|
||||
template<typename T>
|
||||
inline void InterceptVmethod(void *dst, T func, uint32_t a)
|
||||
{
|
||||
*(uint32_t*)dst = *(uint32_t*)a;
|
||||
Patch(a, func);
|
||||
}
|
||||
|
||||
#define STARTPATCHES static StaticPatcher Patcher([](){
|
||||
#define ENDPATCHES });
|
||||
381
src/core/re3.cpp
Normal file
381
src/core/re3.cpp
Normal file
@@ -0,0 +1,381 @@
|
||||
#include <direct.h>
|
||||
#include <csignal>
|
||||
#include <windows.h>
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Renderer.h"
|
||||
#include "Credits.h"
|
||||
#include "Camera.h"
|
||||
#include "Weather.h"
|
||||
#include "Clock.h"
|
||||
#include "World.h"
|
||||
#include "Vehicle.h"
|
||||
#include "Streaming.h"
|
||||
#include "PathFind.h"
|
||||
#include "Boat.h"
|
||||
#include "Automobile.h"
|
||||
#include "debugmenu_public.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
std::vector<int32> usedAddresses;
|
||||
|
||||
void **rwengine = *(void***)0x5A10E1;
|
||||
|
||||
DebugMenuAPI gDebugMenuAPI;
|
||||
|
||||
WRAPPER void *gtanew(uint32 sz) { EAXJMP(0x5A0690); }
|
||||
WRAPPER void gtadelete(void *p) { EAXJMP(0x5A07E0); }
|
||||
|
||||
// overload our own new/delete with GTA's functions
|
||||
void *operator new(size_t sz) { return gtanew(sz); }
|
||||
void operator delete(void *ptr) noexcept { gtadelete(ptr); }
|
||||
|
||||
#ifdef USE_PS2_RAND
|
||||
unsigned __int64 myrand_seed = 1;
|
||||
#else
|
||||
unsigned long int myrand_seed = 1;
|
||||
#endif
|
||||
|
||||
int
|
||||
myrand(void)
|
||||
{
|
||||
#ifdef USE_PS2_RAND
|
||||
// Use our own implementation of rand, stolen from PS2
|
||||
myrand_seed = 0x5851F42D4C957F2D * myrand_seed + 1;
|
||||
return ((myrand_seed >> 32) & 0x7FFFFFFF);
|
||||
#else
|
||||
// or original codewarrior rand
|
||||
myrand_seed = myrand_seed * 1103515245 + 12345;
|
||||
return((myrand_seed >> 16) & 0x7FFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
mysrand(unsigned int seed)
|
||||
{
|
||||
myrand_seed = seed;
|
||||
}
|
||||
|
||||
int (*open_script_orig)(const char *path, const char *mode);
|
||||
int
|
||||
open_script(const char *path, const char *mode)
|
||||
{
|
||||
static int scriptToLoad = 1;
|
||||
|
||||
if(GetAsyncKeyState('G') & 0x8000)
|
||||
scriptToLoad = 0;
|
||||
if(GetAsyncKeyState('R') & 0x8000)
|
||||
scriptToLoad = 1;
|
||||
if(GetAsyncKeyState('D') & 0x8000)
|
||||
scriptToLoad = 2;
|
||||
|
||||
switch(scriptToLoad){
|
||||
case 0: return open_script_orig(path, mode);
|
||||
case 1: return open_script_orig("main_freeroam.scm", mode);
|
||||
case 2: return open_script_orig("main_d.scm", mode);
|
||||
}
|
||||
return open_script_orig(path, mode);
|
||||
}
|
||||
|
||||
int gDbgSurf;
|
||||
|
||||
void (*DebugMenuProcess)(void);
|
||||
void (*DebugMenuRender)(void);
|
||||
static void stub(void) { }
|
||||
|
||||
void
|
||||
DebugMenuInit(void)
|
||||
{
|
||||
if(DebugMenuLoad()){
|
||||
DebugMenuProcess = (void(*)(void))GetProcAddress(gDebugMenuAPI.module, "DebugMenuProcess");
|
||||
DebugMenuRender = (void(*)(void))GetProcAddress(gDebugMenuAPI.module, "DebugMenuRender");
|
||||
}
|
||||
if(DebugMenuProcess == nil || DebugMenuRender == nil){
|
||||
DebugMenuProcess = stub;
|
||||
DebugMenuRender = stub;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void WeaponCheat();
|
||||
void HealthCheat();
|
||||
void TankCheat();
|
||||
void BlowUpCarsCheat();
|
||||
void ChangePlayerCheat();
|
||||
void MayhemCheat();
|
||||
void EverybodyAttacksPlayerCheat();
|
||||
void WeaponsForAllCheat();
|
||||
void FastTimeCheat();
|
||||
void SlowTimeCheat();
|
||||
void MoneyCheat();
|
||||
void ArmourCheat();
|
||||
void WantedLevelUpCheat();
|
||||
void WantedLevelDownCheat();
|
||||
void SunnyWeatherCheat();
|
||||
void CloudyWeatherCheat();
|
||||
void RainyWeatherCheat();
|
||||
void FoggyWeatherCheat();
|
||||
void FastWeatherCheat();
|
||||
void OnlyRenderWheelsCheat();
|
||||
void ChittyChittyBangBangCheat();
|
||||
void StrongGripCheat();
|
||||
void NastyLimbsCheat();
|
||||
|
||||
// needs too much stuff for now
|
||||
#if 0
|
||||
void
|
||||
spawnCar(int id)
|
||||
{
|
||||
CVector playerpos;
|
||||
CStreaming::RequestModel(id, 0);
|
||||
CStreaming::LoadAllRequestedModels(false);
|
||||
if(CStreaming::HasModelLoaded(id)){
|
||||
FindPlayerCoors(playerpos);
|
||||
int node = ThePaths.FindNodeClosestToCoors(playerpos, 0, 100.0f, false, false);
|
||||
if(node < 0)
|
||||
return;
|
||||
|
||||
CVehicle *v;
|
||||
if(CModelInfo::IsBoatModel(id)){
|
||||
// CBoat* boat = (CBoat*)CVehicle__new(0x484);
|
||||
// boat = boat->ctor(id, 1);
|
||||
// v = (CVehicle*)(boat);
|
||||
}else{
|
||||
// CAutomobile *au = (CAutomobile*)CVehicle__new(0x5A8);
|
||||
// au = au->ctor(id, 1);
|
||||
// v = (CVehicle*)au;
|
||||
}
|
||||
/*
|
||||
// unlock doors
|
||||
FIELD(int, v, 0x224) = 1;
|
||||
// set player owned
|
||||
FIELD(uint8, v, 0x1F7) |= 4;
|
||||
|
||||
DebugMenuEntrySetAddress(carCol1, &FIELD(uchar, v, 0x19C));
|
||||
DebugMenuEntrySetAddress(carCol2, &FIELD(uchar, v, 0x19D));
|
||||
//if(id == MODELID_ESPERANTO)
|
||||
// FIELD(uchar, v, 0x19C) = 54;
|
||||
|
||||
v->matrix.matrix.pos.x = ThePaths.nodes[node].x;
|
||||
v->matrix.matrix.pos.y = ThePaths.nodes[node].y;
|
||||
v->matrix.matrix.pos.z = ThePaths.nodes[node].z + 4.0f;
|
||||
float x = v->matrix.matrix.pos.x;
|
||||
float y = v->matrix.matrix.pos.y;
|
||||
float z = v->matrix.matrix.pos.z;
|
||||
v->matrix.SetRotate(0.0f, 0.0f, 3.49f);
|
||||
v->matrix.matrix.pos.x += x;
|
||||
v->matrix.matrix.pos.y += y;
|
||||
v->matrix.matrix.pos.z += z;
|
||||
v->bfTypeStatus = v->bfTypeStatus & 7 | 0x20;
|
||||
FIELD(int, v, 0x224) = 1;
|
||||
*/
|
||||
CWorld::Add(v);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
DebugMenuPopulate(void)
|
||||
{
|
||||
if(DebugMenuLoad()){
|
||||
static const char *weathers[] = {
|
||||
"Sunny", "Cloudy", "Rainy", "Foggy"
|
||||
};
|
||||
DebugMenuEntry *e;
|
||||
e = DebugMenuAddVar("Time & Weather", "Current Hour", &CClock::GetHoursRef(), nil, 1, 0, 23, nil);
|
||||
DebugMenuEntrySetWrap(e, true);
|
||||
e = DebugMenuAddVar("Time & Weather", "Current Minute", &CClock::GetMinutesRef(),
|
||||
[](){ CWeather::InterpolationValue = CClock::GetMinutes()/60.0f; }, 1, 0, 59, nil);
|
||||
DebugMenuEntrySetWrap(e, true);
|
||||
e = DebugMenuAddVar("Time & Weather", "Old Weather", (int16*)&CWeather::OldWeatherType, nil, 1, 0, 3, weathers);
|
||||
DebugMenuEntrySetWrap(e, true);
|
||||
e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 3, weathers);
|
||||
DebugMenuEntrySetWrap(e, true);
|
||||
DebugMenuAddVar("Time & Weather", "Wind", (float*)&CWeather::Wind, nil, 0.1f, 0.0f, 1.0f);
|
||||
DebugMenuAddVar("Time & Weather", "Time scale", (float*)0x8F2C20, nil, 0.1f, 0.0f, 10.0f);
|
||||
|
||||
DebugMenuAddCmd("Cheats", "Weapons", WeaponCheat);
|
||||
DebugMenuAddCmd("Cheats", "Money", MoneyCheat);
|
||||
DebugMenuAddCmd("Cheats", "Health", HealthCheat);
|
||||
DebugMenuAddCmd("Cheats", "Wanted level up", WantedLevelUpCheat);
|
||||
DebugMenuAddCmd("Cheats", "Wanted level down", WantedLevelDownCheat);
|
||||
DebugMenuAddCmd("Cheats", "Tank", TankCheat);
|
||||
DebugMenuAddCmd("Cheats", "Blow up cars", BlowUpCarsCheat);
|
||||
DebugMenuAddCmd("Cheats", "Change player", ChangePlayerCheat);
|
||||
DebugMenuAddCmd("Cheats", "Mayhem", MayhemCheat);
|
||||
DebugMenuAddCmd("Cheats", "Everybody attacks player", EverybodyAttacksPlayerCheat);
|
||||
DebugMenuAddCmd("Cheats", "Weapons for all", WeaponsForAllCheat);
|
||||
DebugMenuAddCmd("Cheats", "Fast time", FastTimeCheat);
|
||||
DebugMenuAddCmd("Cheats", "Slow time", SlowTimeCheat);
|
||||
DebugMenuAddCmd("Cheats", "Armour", ArmourCheat);
|
||||
DebugMenuAddCmd("Cheats", "Sunny weather", SunnyWeatherCheat);
|
||||
DebugMenuAddCmd("Cheats", "Cloudy weather", CloudyWeatherCheat);
|
||||
DebugMenuAddCmd("Cheats", "Rainy weather", RainyWeatherCheat);
|
||||
DebugMenuAddCmd("Cheats", "Foggy weather", FoggyWeatherCheat);
|
||||
DebugMenuAddCmd("Cheats", "Fast weather", FastWeatherCheat);
|
||||
DebugMenuAddCmd("Cheats", "Only render wheels", OnlyRenderWheelsCheat);
|
||||
DebugMenuAddCmd("Cheats", "Chitty chitty bang bang", ChittyChittyBangBangCheat);
|
||||
DebugMenuAddCmd("Cheats", "Strong grip", StrongGripCheat);
|
||||
DebugMenuAddCmd("Cheats", "Nasty limbs", NastyLimbsCheat);
|
||||
|
||||
DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", (int8*)&gbShowPedRoadGroups, nil);
|
||||
DebugMenuAddVarBool8("Debug", "Show Car Road Groups", (int8*)&gbShowCarRoadGroups, nil);
|
||||
DebugMenuAddVarBool8("Debug", "Show Collision Polys", (int8*)&gbShowCollisionPolys, nil);
|
||||
DebugMenuAddVarBool8("Debug", "Don't render Buildings", (int8*)&gbDontRenderBuildings, nil);
|
||||
DebugMenuAddVarBool8("Debug", "Don't render Big Buildings", (int8*)&gbDontRenderBigBuildings, nil);
|
||||
DebugMenuAddVarBool8("Debug", "Don't render Peds", (int8*)&gbDontRenderPeds, nil);
|
||||
DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil);
|
||||
DebugMenuAddVar("Debug", "Dbg Surface", &gDbgSurf, nil, 1, 0, 34, nil);
|
||||
|
||||
DebugMenuAddCmd("Debug", "Start Credits", CCredits::Start);
|
||||
DebugMenuAddCmd("Debug", "Stop Credits", CCredits::Stop);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
int (*RsEventHandler_orig)(int a, int b);
|
||||
int
|
||||
delayedPatches10(int a, int b)
|
||||
{
|
||||
DebugMenuInit();
|
||||
DebugMenuPopulate();
|
||||
|
||||
return RsEventHandler_orig(a, b);
|
||||
}
|
||||
*/
|
||||
|
||||
void __declspec(naked) HeadlightsFix()
|
||||
{
|
||||
static const float fMinusOne = -1.0f;
|
||||
_asm
|
||||
{
|
||||
fld [esp+708h-690h]
|
||||
fcomp fMinusOne
|
||||
fnstsw ax
|
||||
and ah, 5
|
||||
cmp ah, 1
|
||||
jnz HeadlightsFix_DontLimit
|
||||
fld fMinusOne
|
||||
fstp [esp+708h-690h]
|
||||
|
||||
HeadlightsFix_DontLimit:
|
||||
fld [esp+708h-690h]
|
||||
fabs
|
||||
fld st
|
||||
push 0x5382F2
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
const int re3_buffsize = 1024;
|
||||
static char re3_buff[re3_buffsize];
|
||||
|
||||
void re3_assert(const char *expr, const char *filename, unsigned int lineno, const char *func)
|
||||
{
|
||||
int nCode;
|
||||
|
||||
strcpy_s(re3_buff, re3_buffsize, "Assertion failed!" );
|
||||
strcat_s(re3_buff, re3_buffsize, "\n" );
|
||||
|
||||
strcat_s(re3_buff, re3_buffsize, "File: ");
|
||||
strcat_s(re3_buff, re3_buffsize, filename );
|
||||
strcat_s(re3_buff, re3_buffsize, "\n" );
|
||||
|
||||
strcat_s(re3_buff, re3_buffsize, "Line: " );
|
||||
_itoa_s( lineno, re3_buff + strlen(re3_buff), re3_buffsize - strlen(re3_buff), 10 );
|
||||
strcat_s(re3_buff, re3_buffsize, "\n");
|
||||
|
||||
strcat_s(re3_buff, re3_buffsize, "Function: ");
|
||||
strcat_s(re3_buff, re3_buffsize, func );
|
||||
strcat_s(re3_buff, re3_buffsize, "\n" );
|
||||
|
||||
strcat_s(re3_buff, re3_buffsize, "Expression: ");
|
||||
strcat_s(re3_buff, re3_buffsize, expr);
|
||||
strcat_s(re3_buff, re3_buffsize, "\n");
|
||||
|
||||
strcat_s(re3_buff, re3_buffsize, "\n" );
|
||||
strcat_s(re3_buff, re3_buffsize, "(Press Retry to debug the application)");
|
||||
|
||||
|
||||
nCode = ::MessageBoxA(nil, re3_buff, "RE3 Assertion Failed!",
|
||||
MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
|
||||
|
||||
if (nCode == IDABORT)
|
||||
{
|
||||
raise(SIGABRT);
|
||||
_exit(3);
|
||||
}
|
||||
|
||||
if (nCode == IDRETRY)
|
||||
{
|
||||
__debugbreak();
|
||||
return;
|
||||
}
|
||||
|
||||
if (nCode == IDIGNORE)
|
||||
return;
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
void re3_debug(char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vsprintf_s(re3_buff, re3_buffsize, format, va);
|
||||
va_end(va);
|
||||
|
||||
printf("%s", re3_buff);
|
||||
}
|
||||
|
||||
void re3_trace(const char *filename, unsigned int lineno, const char *func, char *format, ...)
|
||||
{
|
||||
char buff[re3_buffsize *2];
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
vsprintf_s(re3_buff, re3_buffsize, format, va);
|
||||
va_end(va);
|
||||
|
||||
sprintf_s(buff, re3_buffsize * 2, "[%s.%s:%d]: %s", filename, func, lineno, re3_buff);
|
||||
|
||||
OutputDebugStringA(buff);
|
||||
}
|
||||
|
||||
void
|
||||
patch()
|
||||
{
|
||||
StaticPatcher::Apply();
|
||||
|
||||
// Patch<float>(0x46BC61+6, 1.0f); // car distance
|
||||
InjectHook(0x59E460, printf, PATCH_JUMP);
|
||||
InjectHook(0x475E00, printf, PATCH_JUMP); // _Error
|
||||
|
||||
|
||||
// stolen from silentpatch (sorry)
|
||||
Patch<WORD>(0x5382BF, 0x0EEB);
|
||||
InjectHook(0x5382EC, HeadlightsFix, PATCH_JUMP);
|
||||
|
||||
InterceptCall(&open_script_orig, open_script, 0x438869);
|
||||
|
||||
// InterceptCall(&RsEventHandler_orig, delayedPatches10, 0x58275E);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
DllMain(HINSTANCE hInst, DWORD reason, LPVOID)
|
||||
{
|
||||
if(reason == DLL_PROCESS_ATTACH){
|
||||
|
||||
AllocConsole();
|
||||
freopen("CONIN$", "r", stdin);
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
freopen("CONOUT$", "w", stderr);
|
||||
|
||||
if (*(DWORD*)0x5C1E75 == 0xB85548EC) // 1.0
|
||||
patch();
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
415
src/core/rw.cpp
Normal file
415
src/core/rw.cpp
Normal file
@@ -0,0 +1,415 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "rwcore.h"
|
||||
#include "rpworld.h"
|
||||
#include "rpmatfx.h"
|
||||
#include "rpskin.h"
|
||||
#include "rphanim.h"
|
||||
#include "rtbmp.h"
|
||||
|
||||
typedef RwV3d *(*rwVectorsMultFn) (RwV3d * pointsOut,
|
||||
const RwV3d * pointsIn,
|
||||
RwInt32 numPoints,
|
||||
const RwMatrix * matrix);
|
||||
|
||||
|
||||
WRAPPER void _rwObjectHasFrameSetFrame(void* object, RwFrame* frame) { EAXJMP(0x5BC950); }
|
||||
WRAPPER RpAtomic* AtomicDefaultRenderCallBack(RpAtomic* atomic) { EAXJMP(0x59E690); }
|
||||
WRAPPER void _rpAtomicResyncInterpolatedSphere(RpAtomic* atomic) { EAXJMP(0x59E6C0); }
|
||||
WRAPPER RwSphere const* RpAtomicGetWorldBoundingSphere(RpAtomic* atomic) { EAXJMP(0x59E800); }
|
||||
WRAPPER RwInt32 RpClumpGetNumAtomics(RpClump* clump) { EAXJMP(0x59ED50); }
|
||||
WRAPPER RpClump* RpClumpRender(RpClump* clump) { EAXJMP(0x59ED80); }
|
||||
WRAPPER RpClump* RpClumpForAllAtomics(RpClump* clump, RpAtomicCallBack callback, void* pData) { EAXJMP(0x59EDD0); }
|
||||
WRAPPER RpClump* RpClumpForAllCameras(RpClump* clump, RwCameraCallBack callback, void* pData) { EAXJMP(0x59EE10); }
|
||||
WRAPPER RpClump* RpClumpForAllLights(RpClump* clump, RpLightCallBack callback, void* pData) { EAXJMP(0x59EE60); }
|
||||
WRAPPER RpAtomic* RpAtomicCreate() { EAXJMP(0x59EEB0); }
|
||||
WRAPPER RpAtomic* RpAtomicSetGeometry(RpAtomic* atomic, RpGeometry* geometry, RwUInt32 flags) { EAXJMP(0x59EFA0); }
|
||||
WRAPPER RwBool RpAtomicDestroy(RpAtomic* atomic) { EAXJMP(0x59F020); }
|
||||
WRAPPER RpAtomic* RpAtomicClone(RpAtomic* atomic) { EAXJMP(0x59F0A0); }
|
||||
WRAPPER RpClump* RpClumpClone(RpClump* clump) { EAXJMP(0x59F1B0); }
|
||||
WRAPPER RpClump* RpClumpCreate() { EAXJMP(0x59F490); }
|
||||
WRAPPER RwBool RpClumpDestroy(RpClump* clump) { EAXJMP(0x59F500); }
|
||||
WRAPPER RpClump* RpClumpAddAtomic(RpClump* clump, RpAtomic* atomic) { EAXJMP(0x59F680); }
|
||||
WRAPPER RpClump* RpClumpRemoveAtomic(RpClump* clump, RpAtomic* atomic) { EAXJMP(0x59F6B0); }
|
||||
WRAPPER RpClump* RpClumpRemoveLight(RpClump* clump, RpLight* light) { EAXJMP(0x59F6E0); }
|
||||
WRAPPER RpClump* RpClumpStreamRead(RwStream* stream) { EAXJMP(0x59FC50); }
|
||||
WRAPPER RwInt32 RpAtomicRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5A0510); }
|
||||
WRAPPER RwInt32 RpClumpRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5A0540); }
|
||||
WRAPPER RwInt32 RpAtomicRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5A0570); }
|
||||
WRAPPER RwInt32 RpAtomicSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB) { EAXJMP(0x5A05A0); }
|
||||
WRAPPER RwInt32 RpAtomicSetStreamRightsCallBack(RwUInt32 pluginID, RwPluginDataChunkRightsCallBack rightsCB) { EAXJMP(0x5A05C0); }
|
||||
WRAPPER RwInt32 RpAtomicGetPluginOffset(RwUInt32 pluginID) { EAXJMP(0x5A05E0); }
|
||||
WRAPPER RpAtomic* RpAtomicSetFrame(RpAtomic* atomic, RwFrame* frame) { EAXJMP(0x5A0600); }
|
||||
WRAPPER RwInt32 RwEngineRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor initCB, RwPluginObjectDestructor termCB) { EAXJMP(0x5A0DC0); }
|
||||
WRAPPER RwInt32 RwEngineGetPluginOffset(RwUInt32 pluginID) { EAXJMP(0x5A0DF0); }
|
||||
WRAPPER RwInt32 RwEngineGetNumSubSystems() { EAXJMP(0x5A0E10); }
|
||||
WRAPPER RwSubSystemInfo* RwEngineGetSubSystemInfo(RwSubSystemInfo* subSystemInfo, RwInt32 subSystemIndex) { EAXJMP(0x5A0E40); }
|
||||
WRAPPER RwInt32 RwEngineGetCurrentSubSystem() { EAXJMP(0x5A0E70); }
|
||||
WRAPPER RwBool RwEngineSetSubSystem(RwInt32 subSystemIndex) { EAXJMP(0x5A0EA0); }
|
||||
WRAPPER RwInt32 RwEngineGetNumVideoModes() { EAXJMP(0x5A0ED0); }
|
||||
WRAPPER RwVideoMode* RwEngineGetVideoModeInfo(RwVideoMode* modeinfo, RwInt32 modeIndex) { EAXJMP(0x5A0F00); }
|
||||
WRAPPER RwInt32 RwEngineGetCurrentVideoMode() { EAXJMP(0x5A0F30); }
|
||||
WRAPPER RwBool RwEngineSetVideoMode(RwInt32 modeIndex) { EAXJMP(0x5A0F60); }
|
||||
WRAPPER RwBool RwEngineStop() { EAXJMP(0x5A0F90); }
|
||||
WRAPPER RwBool RwEngineStart() { EAXJMP(0x5A0FE0); }
|
||||
WRAPPER RwBool RwEngineClose() { EAXJMP(0x5A1070); }
|
||||
WRAPPER RwBool RwEngineOpen(RwEngineOpenParams* initParams) { EAXJMP(0x5A10E0); }
|
||||
WRAPPER RwBool RwEngineTerm() { EAXJMP(0x5A1290); }
|
||||
WRAPPER RwBool RwEngineInit(RwMemoryFunctions* memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) { EAXJMP(0x5A12D0); }
|
||||
WRAPPER void* _rwFrameOpen(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A15E0); }
|
||||
WRAPPER void* _rwFrameClose(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A1650); }
|
||||
WRAPPER RwFrame* _rwFrameCloneAndLinkClones(RwFrame* root) { EAXJMP(0x5A1690); }
|
||||
WRAPPER RwFrame* _rwFramePurgeClone(RwFrame* root) { EAXJMP(0x5A1880); }
|
||||
WRAPPER RwBool RwFrameDirty(RwFrame const* frame) { EAXJMP(0x5A1930); }
|
||||
WRAPPER void _rwFrameInit(RwFrame* frame) { EAXJMP(0x5A1950); }
|
||||
WRAPPER RwFrame* RwFrameCreate() { EAXJMP(0x5A1A00); }
|
||||
WRAPPER RwBool RwFrameDestroy(RwFrame* frame) { EAXJMP(0x5A1A30); }
|
||||
WRAPPER RwBool RwFrameDestroyHierarchy(RwFrame* frame) { EAXJMP(0x5A1BF0); }
|
||||
WRAPPER RwFrame* RwFrameUpdateObjects(RwFrame* frame) { EAXJMP(0x5A1C60); }
|
||||
WRAPPER RwMatrix* RwFrameGetLTM(RwFrame* frame) { EAXJMP(0x5A1CE0); }
|
||||
WRAPPER RwFrame* RwFrameAddChild(RwFrame* parent, RwFrame* child) { EAXJMP(0x5A1D00); }
|
||||
WRAPPER RwFrame* RwFrameRemoveChild(RwFrame* child) { EAXJMP(0x5A1ED0); }
|
||||
WRAPPER RwFrame* RwFrameForAllChildren(RwFrame* frame, RwFrameCallBack callBack, void* data) { EAXJMP(0x5A1FC0); }
|
||||
WRAPPER RwFrame* RwFrameTranslate(RwFrame* frame, RwV3d const* v, RwOpCombineType combine) { EAXJMP(0x5A2000); }
|
||||
WRAPPER RwFrame* RwFrameScale(RwFrame* frame, RwV3d const* v, RwOpCombineType combine) { EAXJMP(0x5A20A0); }
|
||||
WRAPPER RwFrame* RwFrameTransform(RwFrame* frame, RwMatrix const* m, RwOpCombineType combine) { EAXJMP(0x5A2140); }
|
||||
WRAPPER RwFrame* RwFrameRotate(RwFrame* frame, RwV3d const* axis, RwReal angle, RwOpCombineType combine) { EAXJMP(0x5A21E0); }
|
||||
WRAPPER RwFrame* RwFrameSetIdentity(RwFrame* frame) { EAXJMP(0x5A2280); }
|
||||
WRAPPER RwFrame* RwFrameForAllObjects(RwFrame* frame, RwObjectCallBack callBack, void* data) { EAXJMP(0x5A2340); }
|
||||
WRAPPER RwInt32 RwFrameRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5A2380); }
|
||||
WRAPPER RwBool _rwMatrixSetMultFn(rwMatrixMultFn multMat) { EAXJMP(0x5A23B0); }
|
||||
WRAPPER RwReal _rwMatrixDeterminant(RwMatrix const* matrix) { EAXJMP(0x5A2520); }
|
||||
WRAPPER RwReal _rwMatrixOrthogonalError(RwMatrix const* matrix) { EAXJMP(0x5A2570); }
|
||||
WRAPPER RwReal _rwMatrixNormalError(RwMatrix const* matrix) { EAXJMP(0x5A25D0); }
|
||||
WRAPPER RwReal _rwMatrixIdentityError(RwMatrix const* matrix) { EAXJMP(0x5A2660); }
|
||||
WRAPPER void* _rwMatrixClose(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A2730); }
|
||||
WRAPPER void* _rwMatrixOpen(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A2770); }
|
||||
WRAPPER RwMatrix* RwMatrixOptimize(RwMatrix* matrix, RwMatrixTolerance const* tolerance) { EAXJMP(0x5A2820); }
|
||||
WRAPPER RwMatrix* RwMatrixUpdate(RwMatrix* matrix) { EAXJMP(0x5A28E0); }
|
||||
WRAPPER RwMatrix* RwMatrixMultiply(RwMatrix* matrixOut, RwMatrix const* MatrixIn1, RwMatrix const* matrixIn2) { EAXJMP(0x5A28F0); }
|
||||
WRAPPER RwMatrix* RwMatrixRotateOneMinusCosineSine(RwMatrix* matrix, RwV3d const* unitAxis, RwReal oneMinusCosine, RwReal sine, RwOpCombineType combineOp) { EAXJMP(0x5A2960); }
|
||||
WRAPPER RwMatrix* RwMatrixRotate(RwMatrix* matrix, RwV3d const* axis, RwReal angle, RwOpCombineType combineOp) { EAXJMP(0x5A2BF0); }
|
||||
WRAPPER RwMatrix* RwMatrixInvert(RwMatrix* matrixOut, RwMatrix const* matrixIn) { EAXJMP(0x5A2C90); }
|
||||
WRAPPER RwMatrix* RwMatrixScale(RwMatrix* matrix, RwV3d const* scale, RwOpCombineType combineOp) { EAXJMP(0x5A2EE0); }
|
||||
WRAPPER RwMatrix* RwMatrixTranslate(RwMatrix* matrix, RwV3d const* translation, RwOpCombineType combineOp) { EAXJMP(0x5A3070); }
|
||||
WRAPPER RwMatrix* RwMatrixTransform(RwMatrix* matrix, RwMatrix const* transform, RwOpCombineType combineOp) { EAXJMP(0x5A31C0); }
|
||||
WRAPPER RwBool RwMatrixDestroy(RwMatrix* mpMat) { EAXJMP(0x5A3300); }
|
||||
WRAPPER RwMatrix* RwMatrixCreate() { EAXJMP(0x5A3330); }
|
||||
WRAPPER RwBool _rwVectorSetMultFn(rwVectorMultFn multPoint, rwVectorsMultFn multPoints, rwVectorMultFn multVector, rwVectorsMultFn multVectors) { EAXJMP(0x5A3450); }
|
||||
WRAPPER RwReal _rwV3dNormalize(RwV3d* out, RwV3d const* in) { EAXJMP(0x5A3600); }
|
||||
WRAPPER RwReal RwV3dLength(RwV3d const* in) { EAXJMP(0x5A36A0); }
|
||||
WRAPPER RwReal _rwSqrt(RwReal const num) { EAXJMP(0x5A3710); }
|
||||
WRAPPER RwReal _rwInvSqrt(RwReal const num) { EAXJMP(0x5A3770); }
|
||||
WRAPPER RwV3d* RwV3dTransformPoints(RwV3d* pointsOut, RwV3d const* pointsIn, RwInt32 numPoints, RwMatrix const* matrix) { EAXJMP(0x5A37D0); }
|
||||
WRAPPER RwV3d* RwV3dTransformVectors(RwV3d* vectorsOut, RwV3d const* vectorsIn, RwInt32 numPoints, RwMatrix const* matrix) { EAXJMP(0x5A37E0); }
|
||||
WRAPPER void* _rwVectorClose(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A37F0); }
|
||||
WRAPPER void* _rwVectorOpen(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5A3860); }
|
||||
WRAPPER RwUInt32 RwStreamRead(RwStream* stream, void* buffer, RwUInt32 length) { EAXJMP(0x5A3AD0); }
|
||||
WRAPPER RwStream* RwStreamWrite(RwStream* stream, void const* buffer, RwUInt32 length) { EAXJMP(0x5A3C30); }
|
||||
WRAPPER RwStream* RwStreamSkip(RwStream* stream, RwUInt32 offset) { EAXJMP(0x5A3DF0); }
|
||||
WRAPPER RwBool RwStreamClose(RwStream* stream, void* pData) { EAXJMP(0x5A3F10); }
|
||||
WRAPPER RwStream* RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, void const* pData) { EAXJMP(0x5A3FE0); }
|
||||
WRAPPER RwReal RwIm2DGetNearScreenZ() { EAXJMP(0x5A43A0); }
|
||||
WRAPPER RwReal RwIm2DGetFarScreenZ() { EAXJMP(0x5A43B0); }
|
||||
WRAPPER RwBool RwRenderStateSet(RwRenderState state, void* value) { EAXJMP(0x5A43C0); }
|
||||
WRAPPER RwBool RwRenderStateGet(RwRenderState state, void* value) { EAXJMP(0x5A4410); }
|
||||
WRAPPER RwBool RwIm2DRenderLine(RwIm2DVertex* vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2) { EAXJMP(0x5A4420); }
|
||||
WRAPPER RwBool RwIm2DRenderPrimitive(RwPrimitiveType primType, RwIm2DVertex* vertices, RwInt32 numVertices) { EAXJMP(0x5A4430); }
|
||||
WRAPPER RwBool RwIm2DRenderIndexedPrimitive(RwPrimitiveType primType, RwIm2DVertex* vertices, RwInt32 numVertices, RwImVertexIndex* indices, RwInt32 numIndices) { EAXJMP(0x5A4440); }
|
||||
WRAPPER RwCamera* RwCameraEndUpdate(RwCamera* camera) { EAXJMP(0x5A5020); }
|
||||
WRAPPER RwCamera* RwCameraBeginUpdate(RwCamera* camera) { EAXJMP(0x5A5030); }
|
||||
WRAPPER RwCamera* RwCameraSetViewOffset(RwCamera* camera, RwV2d const* offset) { EAXJMP(0x5A5040); }
|
||||
WRAPPER RwCamera* RwCameraSetNearClipPlane(RwCamera* camera, RwReal nearClip) { EAXJMP(0x5A5070); }
|
||||
WRAPPER RwCamera* RwCameraSetFarClipPlane(RwCamera* camera, RwReal farClip) { EAXJMP(0x5A5140); }
|
||||
WRAPPER RwFrustumTestResult RwCameraFrustumTestSphere(RwCamera const* camera, RwSphere const* sphere) { EAXJMP(0x5A5170); }
|
||||
WRAPPER RwCamera* RwCameraClear(RwCamera* camera, RwRGBA* colour, RwInt32 clearMode) { EAXJMP(0x5A51E0); }
|
||||
WRAPPER RwCamera* RwCameraShowRaster(RwCamera* camera, void* pDev, RwUInt32 flags) { EAXJMP(0x5A5210); }
|
||||
WRAPPER RwCamera* RwCameraSetProjection(RwCamera* camera, RwCameraProjection projection) { EAXJMP(0x5A5240); }
|
||||
WRAPPER RwCamera* RwCameraSetViewWindow(RwCamera* camera, RwV2d const* viewWindow) { EAXJMP(0x5A52B0); }
|
||||
WRAPPER RwInt32 RwCameraRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5A52F0); }
|
||||
WRAPPER RwBool RwCameraDestroy(RwCamera* camera) { EAXJMP(0x5A5320); }
|
||||
WRAPPER RwCamera* RwCameraCreate() { EAXJMP(0x5A5360); }
|
||||
WRAPPER RwBool RwTextureSetMipmapping(RwBool enable) { EAXJMP(0x5A7100); }
|
||||
WRAPPER RwBool RwTextureGetMipmapping() { EAXJMP(0x5A7120); }
|
||||
WRAPPER RwBool RwTextureSetAutoMipmapping(RwBool enable) { EAXJMP(0x5A7130); }
|
||||
WRAPPER RwBool RwTextureGetAutoMipmapping() { EAXJMP(0x5A7150); }
|
||||
WRAPPER RwTexDictionary* RwTexDictionaryCreate() { EAXJMP(0x5A7160); }
|
||||
WRAPPER RwBool RwTexDictionaryDestroy(RwTexDictionary* dict) { EAXJMP(0x5A7200); }
|
||||
WRAPPER RwTexDictionary const* RwTexDictionaryForAllTextures(RwTexDictionary const* dict, RwTextureCallBack fpCallBack, void* pData) { EAXJMP(0x5A7290); }
|
||||
WRAPPER RwTexture* RwTextureCreate(RwRaster* raster) { EAXJMP(0x5A72D0); }
|
||||
WRAPPER RwBool RwTextureDestroy(RwTexture* texture) { EAXJMP(0x5A7330); }
|
||||
WRAPPER RwTexture* RwTextureSetName(RwTexture* texture, RwChar const* name) { EAXJMP(0x5A73B0); }
|
||||
WRAPPER RwTexture* RwTextureSetMaskName(RwTexture* texture, RwChar const* maskName) { EAXJMP(0x5A7420); }
|
||||
WRAPPER RwTexture* RwTexDictionaryAddTexture(RwTexDictionary* dict, RwTexture* texture) { EAXJMP(0x5A7490); }
|
||||
WRAPPER RwTexture* RwTexDictionaryFindNamedTexture(RwTexDictionary* dict, RwChar const* name) { EAXJMP(0x5A74D0); }
|
||||
WRAPPER RwTexDictionary* RwTexDictionarySetCurrent(RwTexDictionary* dict) { EAXJMP(0x5A7550); }
|
||||
WRAPPER RwTexDictionary* RwTexDictionaryGetCurrent() { EAXJMP(0x5A7570); }
|
||||
WRAPPER RwTexture* RwTextureRead(RwChar const* name, RwChar const* maskName) { EAXJMP(0x5A7580); }
|
||||
WRAPPER RwBool RwTextureRasterGenerateMipmaps(RwRaster* raster, RwImage* image) { EAXJMP(0x5A7780); }
|
||||
WRAPPER RwImage* RwImageCreate(RwInt32 width, RwInt32 height, RwInt32 depth) { EAXJMP(0x5A9120); }
|
||||
WRAPPER RwBool RwImageDestroy(RwImage* image) { EAXJMP(0x5A9180); }
|
||||
WRAPPER RwImage* RwImageAllocatePixels(RwImage* image) { EAXJMP(0x5A91E0); }
|
||||
WRAPPER RwImage* RwImageFreePixels(RwImage* image) { EAXJMP(0x5A92A0); }
|
||||
WRAPPER RwImage* RwImageMakeMask(RwImage* image) { EAXJMP(0x5A92D0); }
|
||||
WRAPPER RwImage* RwImageApplyMask(RwImage* image, RwImage const* mask) { EAXJMP(0x5A93A0); }
|
||||
WRAPPER RwChar const* RwImageSetPath(RwChar const* path) { EAXJMP(0x5A9750); }
|
||||
WRAPPER RwImage* RwImageRead(RwChar const* imageName) { EAXJMP(0x5A9810); }
|
||||
WRAPPER RwChar const* RwImageFindFileType(RwChar const* imageName) { EAXJMP(0x5A9B40); }
|
||||
WRAPPER RwImage* RwImageReadMaskedImage(RwChar const* imageName, RwChar const* maskname) { EAXJMP(0x5A9C10); }
|
||||
WRAPPER RwImage* RwImageCopy(RwImage* destImage, RwImage const* sourceImage) { EAXJMP(0x5A9F50); }
|
||||
WRAPPER RwImage* RwImageGammaCorrect(RwImage* image) { EAXJMP(0x5AA130); }
|
||||
WRAPPER RwBool RwImageSetGamma(RwReal gammaValue) { EAXJMP(0x5AA2C0); }
|
||||
WRAPPER RwStream* _rwStreamWriteVersionedChunkHeader(RwStream* stream, RwInt32 type, RwInt32 size, RwUInt32 version, RwUInt32 buildNum) { EAXJMP(0x5AA4E0); }
|
||||
WRAPPER RwBool RwStreamFindChunk(RwStream* stream, RwUInt32 type, RwUInt32* lengthOut, RwUInt32* versionOut) { EAXJMP(0x5AA540); }
|
||||
WRAPPER void* RwMemLittleEndian32(void* mem, RwUInt32 size) { EAXJMP(0x5AA640); }
|
||||
WRAPPER void* RwMemNative32(void* mem, RwUInt32 size) { EAXJMP(0x5AA650); }
|
||||
WRAPPER void* RwMemFloat32ToReal(void* mem, RwUInt32 size) { EAXJMP(0x5AA660); }
|
||||
WRAPPER RwStream* RwStreamWriteReal(RwStream* stream, RwReal const* reals, RwUInt32 numBytes) { EAXJMP(0x5AA680); }
|
||||
WRAPPER RwStream* RwStreamWriteInt32(RwStream* stream, RwInt32 const* ints, RwUInt32 numBytes) { EAXJMP(0x5AA720); }
|
||||
WRAPPER RwStream* RwStreamReadReal(RwStream* stream, RwReal* reals, RwUInt32 numBytes) { EAXJMP(0x5AA740); }
|
||||
WRAPPER RwStream* RwStreamReadInt32(RwStream* stream, RwInt32* ints, RwUInt32 numBytes) { EAXJMP(0x5AA7B0); }
|
||||
WRAPPER RwUInt32 RwTextureStreamGetSize(RwTexture const* texture) { EAXJMP(0x5AA800); }
|
||||
WRAPPER RwTexture const* RwTextureStreamWrite(RwTexture const* texture, RwStream* stream) { EAXJMP(0x5AA870); }
|
||||
WRAPPER RwTexture* RwTextureStreamRead(RwStream* stream) { EAXJMP(0x5AAA40); }
|
||||
WRAPPER RwTexDictionary const* RwTexDictionaryStreamWrite(RwTexDictionary const* texDict, RwStream* stream) { EAXJMP(0x5AB020); }
|
||||
WRAPPER RpMorphTarget const* RpMorphTargetCalcBoundingSphere(RpMorphTarget const* morphTarget, RwSphere* boundingSphere) { EAXJMP(0x5AC890); }
|
||||
WRAPPER RwInt32 RpGeometryAddMorphTargets(RpGeometry* geometry, RwInt32 mtcount) { EAXJMP(0x5AC9A0); }
|
||||
WRAPPER RpGeometry const* RpGeometryTriangleSetVertexIndices(RpGeometry const* geometry, RpTriangle* triangle, RwUInt16 vert1, RwUInt16 vert2, RwUInt16 vert3) { EAXJMP(0x5ACB60); }
|
||||
WRAPPER RpGeometry* RpGeometryTriangleSetMaterial(RpGeometry* geometry, RpTriangle* triangle, RpMaterial* material) { EAXJMP(0x5ACB90); }
|
||||
WRAPPER RpGeometry* RpGeometryForAllMaterials(RpGeometry* geometry, RpMaterialCallBack fpCallBack, void* pData) { EAXJMP(0x5ACBF0); }
|
||||
WRAPPER RpGeometry* RpGeometryLock(RpGeometry* geometry, RwInt32 lockMode) { EAXJMP(0x5ACC30); }
|
||||
WRAPPER RpGeometry* RpGeometryUnlock(RpGeometry* geometry) { EAXJMP(0x5ACC60); }
|
||||
WRAPPER RpGeometry* RpGeometryCreate(RwInt32 numVert, RwInt32 numTriangles, RwUInt32 format) { EAXJMP(0x5ACD10); }
|
||||
WRAPPER RpGeometry* _rpGeometryAddRef(RpGeometry* geometry) { EAXJMP(0x5ACF40); }
|
||||
WRAPPER RwBool RpGeometryDestroy(RpGeometry* geometry) { EAXJMP(0x5ACF50); }
|
||||
WRAPPER RwInt32 RpGeometryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5ACFF0); }
|
||||
WRAPPER RwInt32 RpGeometryRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5AD020); }
|
||||
WRAPPER RpGeometry* RpGeometryStreamRead(RwStream* stream) { EAXJMP(0x5AD050); }
|
||||
WRAPPER RwRaster* RwRasterGetCurrentContext() { EAXJMP(0x5AD6D0); }
|
||||
WRAPPER RwRaster* RwRasterUnlock(RwRaster* raster) { EAXJMP(0x5AD6F0); }
|
||||
WRAPPER RwRaster* RwRasterRenderFast(RwRaster* raster, RwInt32 x, RwInt32 y) { EAXJMP(0x5AD710); }
|
||||
WRAPPER RwRaster* RwRasterUnlockPalette(RwRaster* raster) { EAXJMP(0x5AD750); }
|
||||
WRAPPER RwBool RwRasterDestroy(RwRaster* raster) { EAXJMP(0x5AD780); }
|
||||
WRAPPER RwRaster* RwRasterPushContext(RwRaster* raster) { EAXJMP(0x5AD7C0); }
|
||||
WRAPPER RwInt32 RwRasterRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5AD810); }
|
||||
WRAPPER RwUInt8* RwRasterLockPalette(RwRaster* raster, RwInt32 lockMode) { EAXJMP(0x5AD840); }
|
||||
WRAPPER RwRaster* RwRasterPopContext() { EAXJMP(0x5AD870); }
|
||||
WRAPPER RwInt32 RwRasterGetNumLevels(RwRaster* raster) { EAXJMP(0x5AD8C0); }
|
||||
WRAPPER RwRaster* RwRasterShowRaster(RwRaster* raster, void* dev, RwUInt32 flags) { EAXJMP(0x5AD900); }
|
||||
WRAPPER RwRaster* RwRasterCreate(RwInt32 width, RwInt32 height, RwInt32 depth, RwInt32 flags) { EAXJMP(0x5AD930); }
|
||||
WRAPPER RwUInt8* RwRasterLock(RwRaster* raster, RwUInt8 level, RwInt32 lockMode) { EAXJMP(0x5AD9D0); }
|
||||
WRAPPER RpMaterial* RpMaterialCreate() { EAXJMP(0x5ADC30); }
|
||||
WRAPPER RwBool RpMaterialDestroy(RpMaterial* material) { EAXJMP(0x5ADCB0); }
|
||||
WRAPPER RpMaterial* RpMaterialSetTexture(RpMaterial* material, RwTexture* texture) { EAXJMP(0x5ADD10); }
|
||||
WRAPPER RwInt32 RpMaterialRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5ADD40); }
|
||||
WRAPPER RwInt32 RpMaterialRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5ADD70); }
|
||||
WRAPPER RpMaterial* RpMaterialStreamRead(RwStream* stream) { EAXJMP(0x5ADDA0); }
|
||||
WRAPPER RpWorldSector* _rpSectorDefaultRenderCallBack(RpWorldSector* sector) { EAXJMP(0x5AE0B0); }
|
||||
WRAPPER RwBool _rpWorldForAllGlobalLights(RpLightCallBack callBack, void* pData) { EAXJMP(0x5AE100); }
|
||||
WRAPPER RpWorldSector* _rpWorldSectorForAllLocalLights(RpWorldSector* sector, RpLightCallBack callBack, void* pData) { EAXJMP(0x5AE150); }
|
||||
WRAPPER RpWorld* RpWorldUnlock(RpWorld* world) { EAXJMP(0x5AE190); }
|
||||
WRAPPER RpWorld* RpWorldSectorGetWorld(RpWorldSector const* sector) { EAXJMP(0x5AE2B0); }
|
||||
WRAPPER RwBool RpWorldDestroy(RpWorld* world) { EAXJMP(0x5AE340); }
|
||||
WRAPPER RpWorld* RpWorldCreate(RwBBox* boundingBox) { EAXJMP(0x5AE6A0); }
|
||||
WRAPPER RwInt32 RpWorldRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5AEA40); }
|
||||
WRAPPER RwInt32 RpWorldRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5AEA70); }
|
||||
WRAPPER RwBool RpWorldPluginAttach() { EAXJMP(0x5AEAA0); }
|
||||
WRAPPER RpWorld* RpWorldAddCamera(RpWorld* world, RwCamera* camera) { EAXJMP(0x5AFB80); }
|
||||
WRAPPER RpWorld* RpWorldRemoveCamera(RpWorld* world, RwCamera* camera) { EAXJMP(0x5AFBB0); }
|
||||
WRAPPER RpWorld* RpAtomicGetWorld(RpAtomic const* atomic) { EAXJMP(0x5AFC10); }
|
||||
WRAPPER RpWorld* RpWorldAddClump(RpWorld* world, RpClump* clump) { EAXJMP(0x5AFC20); }
|
||||
WRAPPER RpWorld* RpWorldAddLight(RpWorld* world, RpLight* light) { EAXJMP(0x5AFDA0); }
|
||||
WRAPPER RpWorld* RpWorldRemoveLight(RpWorld* world, RpLight* light) { EAXJMP(0x5AFDF0); }
|
||||
WRAPPER RwImage* RtBMPImageRead(RwChar const* imageName) { EAXJMP(0x5AFE70); }
|
||||
WRAPPER RwBool RpSkinPluginAttach() { EAXJMP(0x5B07D0); }
|
||||
WRAPPER RpAtomic* RpSkinAtomicSetHAnimHierarchy(RpAtomic* atomic, RpHAnimHierarchy* hierarchy) { EAXJMP(0x5B1050); }
|
||||
WRAPPER RpHAnimHierarchy* RpSkinAtomicGetHAnimHierarchy(RpAtomic const* atomic) { EAXJMP(0x5B1070); }
|
||||
WRAPPER RpSkin* RpSkinGeometryGetSkin(RpGeometry* geometry) { EAXJMP(0x5B1080); }
|
||||
WRAPPER RpGeometry* RpSkinGeometrySetSkin(RpGeometry* geometry, RpSkin* skin) { EAXJMP(0x5B1090); }
|
||||
WRAPPER RwMatrix const* RpSkinGetSkinToBoneMatrices(RpSkin* skin) { EAXJMP(0x5B10D0); }
|
||||
WRAPPER RpHAnimHierarchy* RpHAnimHierarchyCreate(RwInt32 numNodes, RwUInt32* nodeFlags, RwInt32* nodeIDs, RpHAnimHierarchyFlag flags, RwInt32 maxKeyFrameSize) { EAXJMP(0x5B10E0); }
|
||||
WRAPPER RpHAnimHierarchy* RpHAnimFrameGetHierarchy(RwFrame* frame) { EAXJMP(0x5B11F0); }
|
||||
WRAPPER RwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy* hierarchy, RpHAnimAnimation* anim) { EAXJMP(0x5B1200); }
|
||||
WRAPPER RwBool RpHAnimHierarchySubAnimTime(RpHAnimHierarchy* hierarchy, RwReal time) { EAXJMP(0x5B12B0); }
|
||||
WRAPPER RwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy* hierarchy, RwReal time) { EAXJMP(0x5B1480); }
|
||||
WRAPPER RwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy* hierarchy) { EAXJMP(0x5B1780); }
|
||||
WRAPPER RpHAnimAnimation* RpHAnimAnimationStreamRead(RwStream* stream) { EAXJMP(0x5B1C10); }
|
||||
WRAPPER RwBool RpHAnimPluginAttach() { EAXJMP(0x5B1D50); }
|
||||
WRAPPER RwBool RpMatFXPluginAttach() { EAXJMP(0x5B2640); }
|
||||
WRAPPER RpAtomic* RpMatFXAtomicEnableEffects(RpAtomic* atomic) { EAXJMP(0x5B3750); }
|
||||
WRAPPER RpMaterial* RpMatFXMaterialSetEffects(RpMaterial* material, RpMatFXMaterialFlags flags) { EAXJMP(0x5B3780); }
|
||||
WRAPPER RpMaterial* RpMatFXMaterialSetupEnvMap(RpMaterial* material, RwTexture* texture, RwFrame* frame, RwBool useFrameBufferAlpha, RwReal coef) { EAXJMP(0x5B38D0); }
|
||||
WRAPPER RpMaterial* RpMatFXMaterialSetBumpMapTexture(RpMaterial* material, RwTexture* texture) { EAXJMP(0x5B3A40); }
|
||||
WRAPPER RwBool RwD3D8SetRenderState(RwUInt32 state, RwUInt32 value) { EAXJMP(0x5B3CF0); }
|
||||
WRAPPER void RwD3D8GetRenderState(RwUInt32 state, void* value) { EAXJMP(0x5B3D40); }
|
||||
WRAPPER RwBool RwD3D8SetTextureStageState(RwUInt32 stage, RwUInt32 type, RwUInt32 value) { EAXJMP(0x5B3D60); }
|
||||
WRAPPER RwBool RwD3D8SetTexture(RwTexture* texture, RwUInt32 stage) { EAXJMP(0x5B53A0); }
|
||||
WRAPPER void* RwIm3DTransform(RwIm3DVertex* pVerts, RwUInt32 numVerts, RwMatrix* ltm, RwUInt32 flags) { EAXJMP(0x5B6720); }
|
||||
WRAPPER RwBool RwIm3DEnd() { EAXJMP(0x5B67F0); }
|
||||
WRAPPER RwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex* indices, RwInt32 numIndices) { EAXJMP(0x5B6820); }
|
||||
WRAPPER RwBool RwIm3DRenderLine(RwInt32 vert1, RwInt32 vert2) { EAXJMP(0x5B6980); }
|
||||
WRAPPER RxPipeline* RwIm3DSetTransformPipeline(RxPipeline* pipeline) { EAXJMP(0x5B6A50); }
|
||||
WRAPPER RxPipeline* RwIm3DSetRenderPipeline(RxPipeline* pipeline, RwPrimitiveType primType) { EAXJMP(0x5B6AC0); }
|
||||
WRAPPER void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate) { EAXJMP(0x5B95D0); }
|
||||
WRAPPER RwBool RwD3D8CameraAttachWindow(void* camera, void* hwnd) { EAXJMP(0x5B9640); }
|
||||
WRAPPER RwBool RwD3D8DeviceSupportsDXTTexture() { EAXJMP(0x5BAEB0); }
|
||||
WRAPPER RwBool RwD3D8SetVertexShader(RwUInt32 handle) { EAXJMP(0x5BAF90); }
|
||||
WRAPPER RwBool RwD3D8SetPixelShader(RwUInt32 handle) { EAXJMP(0x5BAFD0); }
|
||||
WRAPPER RwBool RwD3D8SetStreamSource(RwUInt32 streamNumber, void* streamData, RwUInt32 stride) { EAXJMP(0x5BB010); }
|
||||
WRAPPER RwBool RwD3D8SetIndices(void* indexData, RwUInt32 baseVertexIndex) { EAXJMP(0x5BB060); }
|
||||
WRAPPER RwBool RwD3D8DrawIndexedPrimitive(RwUInt32 primitiveType, RwUInt32 minIndex, RwUInt32 numVertices, RwUInt32 startIndex, RwUInt32 numIndices) { EAXJMP(0x5BB0B0); }
|
||||
WRAPPER RwBool RwD3D8DrawPrimitive(RwUInt32 primitiveType, RwUInt32 startVertex, RwUInt32 numVertices) { EAXJMP(0x5BB140); }
|
||||
WRAPPER RwBool RwD3D8SetTransform(RwUInt32 state, void const* matrix) { EAXJMP(0x5BB1D0); }
|
||||
WRAPPER void RwD3D8GetTransform(RwUInt32 state, void* matrix) { EAXJMP(0x5BB310); }
|
||||
WRAPPER RwBool RwD3D8SetTransformWorld(RwMatrix const* matrix) { EAXJMP(0x5BB340); }
|
||||
WRAPPER RwBool RwD3D8SetSurfaceProperties(RwRGBA const* color, RwSurfaceProperties const* surfaceProps, RwBool modulate) { EAXJMP(0x5BB490); }
|
||||
WRAPPER RwBool RwD3D8SetLight(RwInt32 index, void const* light) { EAXJMP(0x5BB7A0); }
|
||||
WRAPPER RwBool RwD3D8EnableLight(RwInt32 index, RwBool enable) { EAXJMP(0x5BB890); }
|
||||
WRAPPER RwBool RwD3D8DynamicVertexBufferCreate(RwUInt32 fvf, RwUInt32 size, void** vertexBuffer) { EAXJMP(0x5BB9F0); }
|
||||
WRAPPER void RwD3D8DynamicVertexBufferDestroy(void* vertexBuffer) { EAXJMP(0x5BBAE0); }
|
||||
WRAPPER RwBool RwD3D8IndexBufferCreate(RwUInt32 numIndices, void** indexBuffer) { EAXJMP(0x5BBB10); }
|
||||
WRAPPER RwBool RwD3D8CreatePixelShader(RwUInt32 const* function, RwUInt32* handle) { EAXJMP(0x5BBB40); }
|
||||
WRAPPER void RwD3D8DeletePixelShader(RwUInt32 handle) { EAXJMP(0x5BBB90); }
|
||||
WRAPPER RwBool RwD3D8SetPixelShaderConstant(RwUInt32 registerAddress, void const* antData, RwUInt32 antCount) { EAXJMP(0x5BBC00); }
|
||||
WRAPPER void const* RwD3D8GetCaps() { EAXJMP(0x5BBC30); }
|
||||
WRAPPER RwBool RwD3D8CameraIsSphereFullyInsideFrustum(void const* camera, void const* sphere) { EAXJMP(0x5BBC40); }
|
||||
WRAPPER RwBool RwD3D8CameraIsBBoxFullyInsideFrustum(void const* camera, void const* boundingBox) { EAXJMP(0x5BBCA0); }
|
||||
WRAPPER RwBool RwD3D8DynamicVertexBufferLock(RwUInt32 vertexSize, RwUInt32 numVertex, void** vertexBufferOut, void** vertexDataOut, RwUInt32* baseIndexOut) { EAXJMP(0x5BBD30); }
|
||||
WRAPPER RwBool RwD3D8DynamicVertexBufferUnlock(void* vertexBuffer) { EAXJMP(0x5BBEB0); }
|
||||
WRAPPER RwBool _rwIntelSSEsupported() { EAXJMP(0x5BBED0); }
|
||||
WRAPPER RwImage* RwImageSetFromRaster(RwImage* image, RwRaster* raster) { EAXJMP(0x5BBF10); }
|
||||
WRAPPER RwRaster* RwRasterSetFromImage(RwRaster* raster, RwImage* image) { EAXJMP(0x5BBF50); }
|
||||
WRAPPER RwImage* RwImageFindRasterFormat(RwImage* ipImage, RwInt32 nRasterType, RwInt32* npWidth, RwInt32* npHeight, RwInt32* npDepth, RwInt32* npFormat) { EAXJMP(0x5BBF80); }
|
||||
WRAPPER RwInt32 RwFrameRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5BBFF0); }
|
||||
WRAPPER rwFrameList* _rwFrameListDeinitialize(rwFrameList* frameList) { EAXJMP(0x5BC020); }
|
||||
WRAPPER rwFrameList* _rwFrameListStreamRead(RwStream* stream, rwFrameList* fl) { EAXJMP(0x5BC050); }
|
||||
WRAPPER RpLight* RpLightSetRadius(RpLight* light, RwReal radius) { EAXJMP(0x5BC300); }
|
||||
WRAPPER RpLight* RpLightSetColor(RpLight* light, RwRGBAReal const* color) { EAXJMP(0x5BC320); }
|
||||
WRAPPER RwReal RpLightGetConeAngle(RpLight const* light) { EAXJMP(0x5BC370); }
|
||||
WRAPPER RwInt32 RpLightRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5BC5B0); }
|
||||
WRAPPER RpLight* RpLightStreamRead(RwStream* stream) { EAXJMP(0x5BC5E0); }
|
||||
WRAPPER RwBool RpLightDestroy(RpLight* light) { EAXJMP(0x5BC780); }
|
||||
WRAPPER RpLight* RpLightCreate(RwInt32 type) { EAXJMP(0x5BC7C0); }
|
||||
WRAPPER void _rwD3D8TexDictionaryEnableRasterFormatConversion(RwBool enable) { EAXJMP(0x5BE280); }
|
||||
WRAPPER RwFileFunctions* RwOsGetFileInterface() { EAXJMP(0x5BF110); }
|
||||
WRAPPER RwBool RwFreeListDestroy(RwFreeList* freelist) { EAXJMP(0x5C1720); }
|
||||
WRAPPER RwFreeList* RwFreeListCreate(RwInt32 entrySize, RwInt32 entriesPerBlock, RwInt32 alignment) { EAXJMP(0x5C1790); }
|
||||
WRAPPER RwInt32 RwFreeListPurge(RwFreeList* freelist) { EAXJMP(0x5C19F0); }
|
||||
WRAPPER RwInt32 RwFreeListPurgeAllFreeLists() { EAXJMP(0x5C1B90); }
|
||||
WRAPPER RwFreeList* RwFreeListForAllUsed(RwFreeList* freelist, RwFreeListCallBack fpCallBack, void* pData) { EAXJMP(0x5C1D40); }
|
||||
WRAPPER RwBool _rxPipelineClose() { EAXJMP(0x5C2780); }
|
||||
WRAPPER RwBool _rxPipelineOpen() { EAXJMP(0x5C27E0); }
|
||||
WRAPPER RxHeap* RxHeapGetGlobalHeap() { EAXJMP(0x5C2AD0); }
|
||||
WRAPPER RxPacket* RxPacketCreate(RxPipelineNode* node) { EAXJMP(0x5C2AE0); }
|
||||
WRAPPER RxCluster* RxClusterSetExternalData(RxCluster* cluster, void* data, RwInt32 stride, RwInt32 numElements) { EAXJMP(0x5C2B10); }
|
||||
WRAPPER RxCluster* RxClusterSetData(RxCluster* cluster, void* data, RwInt32 stride, RwInt32 numElements) { EAXJMP(0x5C2B70); }
|
||||
WRAPPER RxCluster* RxClusterInitializeData(RxCluster* cluster, RwUInt32 numElements, RwUInt16 stride) { EAXJMP(0x5C2BD0); }
|
||||
WRAPPER RxCluster* RxClusterResizeData(RxCluster* CurrentCluster, RwUInt32 NumElements) { EAXJMP(0x5C2C40); }
|
||||
WRAPPER RxCluster* RxClusterLockWrite(RxPacket* packet, RwUInt32 clusterIndex, RxPipelineNode* node) { EAXJMP(0x5C2C90); }
|
||||
WRAPPER RxPipeline* RxPipelineExecute(RxPipeline* pipeline, void* data, RwBool heapReset) { EAXJMP(0x5C2D60); }
|
||||
WRAPPER RxPipeline* RxPipelineCreate() { EAXJMP(0x5C2E00); }
|
||||
WRAPPER void _rxPipelineDestroy(RxPipeline* Pipeline) { EAXJMP(0x5C2E70); }
|
||||
WRAPPER RwBool RwResourcesFreeResEntry(RwResEntry* entry) { EAXJMP(0x5C3080); }
|
||||
WRAPPER void _rwResourcesPurge() { EAXJMP(0x5C30F0); }
|
||||
WRAPPER RwResEntry* RwResourcesAllocateResEntry(void* owner, RwResEntry** ownerRef, RwInt32 size, RwResEntryDestroyNotify destroyNotify) { EAXJMP(0x5C3170); }
|
||||
WRAPPER RwBool RwResourcesEmptyArena() { EAXJMP(0x5C3360); }
|
||||
WRAPPER RwBool _rwPluginRegistryOpen() { EAXJMP(0x5C3450); }
|
||||
WRAPPER RwBool _rwPluginRegistryClose() { EAXJMP(0x5C3480); }
|
||||
WRAPPER RwInt32 _rwPluginRegistryGetPluginOffset(RwPluginRegistry const* reg, RwUInt32 pluginID) { EAXJMP(0x5C3590); }
|
||||
WRAPPER RwInt32 _rwPluginRegistryAddPlugin(RwPluginRegistry* reg, RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5C35C0); }
|
||||
WRAPPER RwPluginRegistry const* _rwPluginRegistryInitObject(RwPluginRegistry const* reg, void* object) { EAXJMP(0x5C37F0); }
|
||||
WRAPPER RwPluginRegistry const* _rwPluginRegistryDeInitObject(RwPluginRegistry const* reg, void* object) { EAXJMP(0x5C3850); }
|
||||
WRAPPER RwPluginRegistry const* _rwPluginRegistryCopyObject(RwPluginRegistry const* reg, void* dstObject, void const* srcObject) { EAXJMP(0x5C3880); }
|
||||
WRAPPER RwError* RwErrorSet(RwError* code) { EAXJMP(0x5C3910); }
|
||||
WRAPPER RwInt32 _rwerror(RwInt32 code, ...) { EAXJMP(0x5C3970); }
|
||||
WRAPPER RwInt32 _rwPluginRegistryAddPluginStream(RwPluginRegistry* reg, RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5C3980); }
|
||||
WRAPPER RwInt32 _rwPluginRegistryAddPlgnStrmlwysCB(RwPluginRegistry* reg, RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB) { EAXJMP(0x5C39C0); }
|
||||
WRAPPER RwInt32 _rwPluginRegistryAddPlgnStrmRightsCB(RwPluginRegistry* reg, RwUInt32 pluginID, RwPluginDataChunkRightsCallBack rightsCB) { EAXJMP(0x5C39F0); }
|
||||
WRAPPER RwPluginRegistry const* _rwPluginRegistryReadDataChunks(RwPluginRegistry const* reg, RwStream* stream, void* object) { EAXJMP(0x5C3A20); }
|
||||
WRAPPER RwPluginRegistry const* _rwPluginRegistryInvokeRights(RwPluginRegistry const* reg, RwUInt32 id, void* obj, RwUInt32 extraData) { EAXJMP(0x5C3B50); }
|
||||
WRAPPER RwInt32 _rwPluginRegistryGetSize(RwPluginRegistry const* reg, void const* object) { EAXJMP(0x5C3BA0); }
|
||||
WRAPPER RwPluginRegistry const* _rwPluginRegistryWriteDataChunks(RwPluginRegistry const* reg, RwStream* stream, void const* object) { EAXJMP(0x5C3BE0); }
|
||||
WRAPPER RwPluginRegistry const* _rwPluginRegistrySkipDataChunks(RwPluginRegistry const* reg, RwStream* stream) { EAXJMP(0x5C3CB0); }
|
||||
WRAPPER RwCamera* RwCameraStreamRead(RwStream* stream) { EAXJMP(0x5C3D30); }
|
||||
WRAPPER RwBBox* RwBBoxCalculate(RwBBox* boundBox, RwV3d const* verts, RwInt32 numVerts) { EAXJMP(0x5C5570); }
|
||||
WRAPPER RwImage* RwImageResample(RwImage* dstImage, RwImage const* srcImage) { EAXJMP(0x5C72B0); }
|
||||
WRAPPER RwImage* RwImageCreateResample(RwImage const* srcImage, RwInt32 width, RwInt32 height) { EAXJMP(0x5C7B30); }
|
||||
WRAPPER RxRenderStateVector* RxRenderStateVectorSetDefaultRenderStateVector(RxRenderStateVector* rsvp) { EAXJMP(0x5D9240); }
|
||||
WRAPPER RxRenderStateVector* RxRenderStateVectorCreate(RwBool current) { EAXJMP(0x5D9340); }
|
||||
WRAPPER void RxRenderStateVectorDestroy(RxRenderStateVector* rsvp) { EAXJMP(0x5D9410); }
|
||||
WRAPPER RxRenderStateVector* RxRenderStateVectorLoadDriverState(RxRenderStateVector* rsvp) { EAXJMP(0x5D9460); }
|
||||
WRAPPER void _rxEmbeddedPacketBetweenPipelines(RxPipeline* fromPipeline, RxPipeline* toPipeline) { EAXJMP(0x5D95D0); }
|
||||
WRAPPER RxPipelineNode* _rxEmbeddedPacketBetweenNodes(RxPipeline* pipeline, RxPipelineNode* nodeFrom, RwUInt32 whichOutput) { EAXJMP(0x5D9740); }
|
||||
WRAPPER void _rxPacketDestroy(RxPacket* Packet) { EAXJMP(0x5D9810); }
|
||||
WRAPPER RpMaterialList* _rpMaterialListDeinitialize(RpMaterialList* matList) { EAXJMP(0x5C8B10); }
|
||||
WRAPPER RpMaterialList* _rpMaterialListInitialize(RpMaterialList* matList) { EAXJMP(0x5C8B70); }
|
||||
WRAPPER RpMaterial* _rpMaterialListGetMaterial(RpMaterialList const* matList, RwInt32 matIndex) { EAXJMP(0x5C8B80); }
|
||||
WRAPPER RwInt32 _rpMaterialListAppendMaterial(RpMaterialList* matList, RpMaterial* material) { EAXJMP(0x5C8B90); }
|
||||
WRAPPER RwInt32 _rpMaterialListFindMaterialIndex(RpMaterialList const* matList, RpMaterial const* material) { EAXJMP(0x5C8C50); }
|
||||
WRAPPER RpMaterialList* _rpMaterialListStreamRead(RwStream* stream, RpMaterialList* matList) { EAXJMP(0x5C8C80); }
|
||||
WRAPPER RpMeshHeader* _rpMeshHeaderCreate(RwUInt32 size) { EAXJMP(0x5C8FE0); }
|
||||
WRAPPER void* _rpMeshClose(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5C8FF0); }
|
||||
WRAPPER void* _rpMeshOpen(void* instance, RwInt32 offset, RwInt32 size) { EAXJMP(0x5C9020); }
|
||||
WRAPPER RpBuildMesh* _rpBuildMeshCreate(RwUInt32 bufferSize) { EAXJMP(0x5C9140); }
|
||||
WRAPPER RwBool _rpBuildMeshDestroy(RpBuildMesh* mesh) { EAXJMP(0x5C9220); }
|
||||
WRAPPER RwBool _rpMeshDestroy(RpMeshHeader* mesh) { EAXJMP(0x5C9260); }
|
||||
WRAPPER RpBuildMesh* _rpBuildMeshAddTriangle(RpBuildMesh* mesh, RpMaterial* material, RwInt32 vert1, RwInt32 vert2, RwInt32 vert3) { EAXJMP(0x5C92A0); }
|
||||
WRAPPER RpMeshHeader* _rpMeshHeaderForAllMeshes(RpMeshHeader* meshHeader, RpMeshCallBack fpCallBack, void* pData) { EAXJMP(0x5C9380); }
|
||||
WRAPPER RwStream* _rpMeshWrite(RpMeshHeader const* meshHeader, void const* object, RwStream* stream, RpMaterialList const* matList) { EAXJMP(0x5C93C0); }
|
||||
WRAPPER RpMeshHeader* _rpMeshRead(RwStream* stream, void const* object, RpMaterialList const* matList) { EAXJMP(0x5C9510); }
|
||||
WRAPPER RwInt32 _rpMeshSize(RpMeshHeader const* meshHeader, void const* object) { EAXJMP(0x5C96E0); }
|
||||
WRAPPER RpMeshHeader* RpBuildMeshGenerateDefaultTriStrip(RpBuildMesh* buildmesh, void* data) { EAXJMP(0x5C9730); }
|
||||
WRAPPER RpMeshHeader* _rpTriListMeshGenerate(RpBuildMesh* buildMesh, void* data) { EAXJMP(0x5CAE10); }
|
||||
WRAPPER RpMeshHeader* _rpMeshOptimise(RpBuildMesh* buildmesh, RwUInt32 flags) { EAXJMP(0x5CB230); }
|
||||
WRAPPER RwInt32 RpWorldSectorRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor ructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB) { EAXJMP(0x5CB2B0); }
|
||||
WRAPPER RwInt32 RpWorldSectorRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB) { EAXJMP(0x5CB2E0); }
|
||||
WRAPPER RxPipeline* RpWorldSetDefaultSectorPipeline(RxPipeline* pipeline) { EAXJMP(0x5CB630); }
|
||||
WRAPPER RxPipeline* RpAtomicSetDefaultPipeline(RxPipeline* pipeline) { EAXJMP(0x5CB670); }
|
||||
WRAPPER void RpHAnimStdKeyFrameToMatrix(RwMatrix* matrix, void* voidIFrame) { EAXJMP(0x5CDEE0); }
|
||||
WRAPPER void RpHAnimStdKeyFrameInterpolate(void* voidOut, void* voidIn1, void* voidIn2, RwReal time) { EAXJMP(0x5CE000); }
|
||||
WRAPPER void RpHAnimStdKeyFrameBlend(void* voidOut, void* voidIn1, void* voidIn2, RwReal alpha) { EAXJMP(0x5CE420); }
|
||||
WRAPPER RpHAnimAnimation* RpHAnimStdKeyFrameStreamRead(RwStream* stream, RpHAnimAnimation* animation) { EAXJMP(0x5CE820); }
|
||||
WRAPPER RwBool RpHAnimStdKeyFrameStreamWrite(RpHAnimAnimation* animation, RwStream* stream) { EAXJMP(0x5CE8C0); }
|
||||
WRAPPER RwInt32 RpHAnimStdKeyFrameStreamGetSize(RpHAnimAnimation* animation) { EAXJMP(0x5CE930); }
|
||||
WRAPPER void RpHAnimStdKeyFrameMulRecip(void* voidFrame, void* voidStart) { EAXJMP(0x5CE950); }
|
||||
WRAPPER void RpHAnimStdKeyFrameAdd(void* voidOut, void* voidIn1, void* voidIn2) { EAXJMP(0x5CEAB0); }
|
||||
WRAPPER void RxHeapFree(RxHeap* heap, void* block) { EAXJMP(0x5D1070); }
|
||||
WRAPPER void* RxHeapAlloc(RxHeap* heap, RwUInt32 size) { EAXJMP(0x5D1260); }
|
||||
WRAPPER void* RxHeapRealloc(RxHeap* heap, void* block, RwUInt32 newSize, RwBool allowCopy) { EAXJMP(0x5D14D0); }
|
||||
WRAPPER RwBool _rxHeapReset(RxHeap* heap) { EAXJMP(0x5D1680); }
|
||||
WRAPPER void RxHeapDestroy(RxHeap* heap) { EAXJMP(0x5D16F0); }
|
||||
WRAPPER RxHeap* RxHeapCreate(RwUInt32 size) { EAXJMP(0x5D1750); }
|
||||
WRAPPER RxNodeOutput RxPipelineNodeFindOutputByName(RxPipelineNode* node, RwChar const* outputname) { EAXJMP(0x5D1EC0); }
|
||||
WRAPPER RxNodeInput RxPipelineNodeFindInput(RxPipelineNode* node) { EAXJMP(0x5D1F20); }
|
||||
WRAPPER RxPipeline* RxPipelineNodeRequestCluster(RxPipeline* pipeline, RxPipelineNode* node, RxClusterDefinition* clusterDef) { EAXJMP(0x5D1F30); }
|
||||
WRAPPER RxPipeline* RxLockedPipeUnlock(RxLockedPipe* pipeline) { EAXJMP(0x5D1FA0); }
|
||||
WRAPPER RxLockedPipe* RxPipelineLock(RxPipeline* pipeline) { EAXJMP(0x5D29F0); }
|
||||
WRAPPER RxPipelineNode* RxPipelineFindNodeByName(RxPipeline* pipeline, RwChar const* name, RxPipelineNode* start, RwInt32* nodeIndex) { EAXJMP(0x5D2B10); }
|
||||
WRAPPER RxLockedPipe* RxLockedPipeAddFragment(RxLockedPipe *pipeline, RwUInt32 *firstIndex, RxNodeDefinition *nodeDef0, ...) { EAXJMP(0x5D2BA0); }
|
||||
WRAPPER RxPipeline* RxLockedPipeAddPath(RxLockedPipe* pipeline, RxNodeOutput out, RxNodeInput in) { EAXJMP(0x5D2EE0); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetImmRenderSetup() { EAXJMP(0x5D31C0); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetImmMangleTriangleIndices() { EAXJMP(0x5D35C0); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetCullTriangle() { EAXJMP(0x5D3C60); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetClipTriangle() { EAXJMP(0x5D4F80); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetSubmitTriangle() { EAXJMP(0x5D51C0); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetImmInstance() { EAXJMP(0x5D5400); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetTransform() { EAXJMP(0x5D6000); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetImmStash() { EAXJMP(0x5D61C0); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetImmMangleLineIndices() { EAXJMP(0x5D6470); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetClipLine() { EAXJMP(0x5D7230); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetSubmitLine() { EAXJMP(0x5D74C0); }
|
||||
WRAPPER RwBool _rwD3D8LightsOpen() { EAXJMP(0x5D9C90); }
|
||||
WRAPPER void _rwD3D8LightsClose() { EAXJMP(0x5D9EF0); }
|
||||
WRAPPER RwBool _rwD3D8LightsGlobalEnable(RpLightFlag flags) { EAXJMP(0x5D9F80); }
|
||||
WRAPPER RwBool _rwD3D8LightLocalEnable(RpLight* light) { EAXJMP(0x5DA210); }
|
||||
WRAPPER void _rwD3D8LightsEnable(RwBool enable, RwUInt32 type) { EAXJMP(0x5DA450); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetD3D8WorldSectorAllInOne() { EAXJMP(0x5DAAC0); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetD3D8AtomicAllInOne() { EAXJMP(0x5DC500); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetWorldSectorInstance() { EAXJMP(0x5DCC50); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetWorldSectorEnumerateLights() { EAXJMP(0x5DCD80); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetAtomicInstance() { EAXJMP(0x5DD800); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetAtomicEnumerateLights() { EAXJMP(0x5DD9B0); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetMaterialScatter() { EAXJMP(0x5DDAA0); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetLight() { EAXJMP(0x5DF040); }
|
||||
WRAPPER RxNodeDefinition* RxNodeDefinitionGetPostLight() { EAXJMP(0x5DF560); }
|
||||
WRAPPER void RxD3D8AllInOneSetRenderCallBack(RxPipelineNode* node, RxD3D8AllInOneRenderCallBack callback) { EAXJMP(0x5DFC60); }
|
||||
205
src/core/templates.h
Normal file
205
src/core/templates.h
Normal file
@@ -0,0 +1,205 @@
|
||||
#pragma once
|
||||
|
||||
template<typename T, int n>
|
||||
class CStore
|
||||
{
|
||||
public:
|
||||
int allocPtr;
|
||||
T store[n];
|
||||
|
||||
T *alloc(void){
|
||||
if(this->allocPtr >= n){
|
||||
printf("Size of this thing:%d needs increasing\n", n);
|
||||
assert(0);
|
||||
}
|
||||
return &this->store[this->allocPtr++];
|
||||
}
|
||||
void clear(void){
|
||||
this->allocPtr = 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U = T>
|
||||
class CPool
|
||||
{
|
||||
U *m_entries;
|
||||
union Flags {
|
||||
struct {
|
||||
uint8 id : 7;
|
||||
uint8 free : 1;
|
||||
};
|
||||
uint8 u;
|
||||
} *m_flags;
|
||||
int m_size;
|
||||
int m_allocPtr;
|
||||
|
||||
public:
|
||||
CPool(int size){
|
||||
m_entries = (U*)malloc(sizeof(U)*size);
|
||||
m_flags = (Flags*)malloc(sizeof(Flags)*size);
|
||||
m_size = size;
|
||||
m_allocPtr = 0;
|
||||
for(int i = 0; i < size; i++){
|
||||
m_flags[i].id = 0;
|
||||
m_flags[i].free = 1;
|
||||
}
|
||||
}
|
||||
int GetSize(void) { return m_size; }
|
||||
T *New(void){
|
||||
bool wrapped = false;
|
||||
do
|
||||
if(++m_allocPtr == m_size){
|
||||
if(wrapped)
|
||||
return nil;
|
||||
wrapped = true;
|
||||
m_allocPtr = 0;
|
||||
}
|
||||
while(!m_flags[m_allocPtr].free);
|
||||
m_flags[m_allocPtr].free = 0;
|
||||
m_flags[m_allocPtr].id++;
|
||||
return (T*)&m_entries[m_allocPtr];
|
||||
}
|
||||
T *New(int handle){
|
||||
T *entry = (T*)&m_entries[handle>>8];
|
||||
SetNotFreeAt(handle);
|
||||
return entry;
|
||||
}
|
||||
void SetNotFreeAt(int handle){
|
||||
int idx = handle>>8;
|
||||
m_flags[idx].free = 0;
|
||||
m_flags[idx].id = handle & 0x7F;
|
||||
for(m_allocPtr = 0; m_allocPtr < m_size; m_allocPtr++)
|
||||
if(m_flags[m_allocPtr].free)
|
||||
return;
|
||||
}
|
||||
void Delete(T *entry){
|
||||
int i = GetJustIndex(entry);
|
||||
m_flags[i].free = 1;
|
||||
if(i < m_allocPtr)
|
||||
m_allocPtr = i;
|
||||
}
|
||||
T *GetSlot(int i){
|
||||
return m_flags[i].free ? nil : (T*)&m_entries[i];
|
||||
}
|
||||
T *GetAt(int handle){
|
||||
return m_flags[handle>>8].u == (handle & 0xFF) ?
|
||||
(T*)&m_entries[handle >> 8] : nil;
|
||||
}
|
||||
int GetIndex(T *entry){
|
||||
int i = GetJustIndex(entry);
|
||||
return m_flags[i].u + (i<<8);
|
||||
}
|
||||
int GetJustIndex(T *entry){
|
||||
// TODO: the cast is unsafe
|
||||
return (int)((U*)entry - m_entries);
|
||||
}
|
||||
int GetNoOfUsedSpaces(void){
|
||||
int i;
|
||||
int n = 0;
|
||||
for(i = 0; i < m_size; i++)
|
||||
if(!m_flags[i].free)
|
||||
n++;
|
||||
return n;
|
||||
}
|
||||
void ClearStorage(uint8 *&flags, U *&entries){
|
||||
free(flags);
|
||||
free(entries);
|
||||
flags = nil;
|
||||
entries = nil;
|
||||
}
|
||||
void CopyBack(uint8 *&flags, U *&entries){
|
||||
memcpy(m_flags, flags, sizeof(uint8)*m_size);
|
||||
memcpy(m_entries, entries, sizeof(U)*m_size);
|
||||
debug("Size copied:%d (%d)\n", sizeof(U)*m_size, sizeof(Flags)*m_size);
|
||||
m_allocPtr = 0;
|
||||
ClearStorage(flags, entries);
|
||||
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);
|
||||
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 */
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class CLink
|
||||
{
|
||||
public:
|
||||
T item;
|
||||
CLink<T> *prev;
|
||||
CLink<T> *next;
|
||||
|
||||
void Insert(CLink<T> *link){
|
||||
link->next = this->next;
|
||||
this->next->prev = link;
|
||||
link->prev = this;
|
||||
this->next = link;
|
||||
}
|
||||
void Remove(void){
|
||||
this->prev->next = this->next;
|
||||
this->next->prev = this->prev;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class CLinkList
|
||||
{
|
||||
public:
|
||||
CLink<T> head, tail;
|
||||
CLink<T> freeHead, freeTail;
|
||||
CLink<T> *links;
|
||||
|
||||
void Init(int n){
|
||||
links = new CLink<T>[n];
|
||||
head.next = &tail;
|
||||
tail.prev = &head;
|
||||
freeHead.next = &freeTail;
|
||||
freeTail.prev = &freeHead;
|
||||
while(n--)
|
||||
freeHead.Insert(&links[n]);
|
||||
}
|
||||
void Shutdown(void){
|
||||
delete[] links;
|
||||
links = nil;
|
||||
}
|
||||
void Clear(void){
|
||||
while(head.next != &tail)
|
||||
Remove(head.next);
|
||||
}
|
||||
CLink<T> *Insert(T const &item){
|
||||
CLink<T> *node = freeHead.next;
|
||||
if(node == &freeTail)
|
||||
return nil;
|
||||
node->item = item;
|
||||
node->Remove(); // remove from free list
|
||||
head.Insert(node);
|
||||
return node;
|
||||
}
|
||||
CLink<T> *InsertSorted(T const &item){
|
||||
CLink<T> *sort;
|
||||
for(sort = head.next; sort != &tail; sort = sort->next)
|
||||
if(sort->item.sort >= item.sort)
|
||||
break;
|
||||
CLink<T> *node = freeHead.next;
|
||||
if(node == &freeTail)
|
||||
return nil;
|
||||
node->item = item;
|
||||
node->Remove(); // remove from free list
|
||||
sort->prev->Insert(node);
|
||||
return node;
|
||||
}
|
||||
void Remove(CLink<T> *link){
|
||||
link->Remove(); // remove from list
|
||||
freeHead.Insert(link); // insert into free list
|
||||
}
|
||||
int Count(void){
|
||||
int n = 0;
|
||||
CLink<T> *lnk;
|
||||
for(lnk = head.next; lnk != &tail; lnk = lnk->next)
|
||||
n++;
|
||||
return n;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user