mirror of
https://gitlab.com/shinovon/re3-symbian.git
synced 2026-05-23 01:57:21 +03:00
Initial commit
This commit is contained in:
commit
77cdaaf97e
827 changed files with 418745 additions and 0 deletions
224
src/rw/ClumpRead.cpp
Normal file
224
src/rw/ClumpRead.cpp
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
#include "common.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 = STREAMPOS(stream);
|
||||
return true;
|
||||
}
|
||||
|
||||
RpClump*
|
||||
RpClumpGtaStreamRead2(RwStream *stream)
|
||||
{
|
||||
int i;
|
||||
RwUInt32 version;
|
||||
RpAtomic *atomic;
|
||||
RpClump *clump;
|
||||
|
||||
clump = RpClumpCreate();
|
||||
if(clump == nil)
|
||||
return nil;
|
||||
|
||||
RwStreamSkip(stream, streamPosition - STREAMPOS(stream));
|
||||
|
||||
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;
|
||||
}
|
||||
355
src/rw/Lights.cpp
Normal file
355
src/rw/Lights.cpp
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
#include "common.h"
|
||||
#include <rwcore.h>
|
||||
#include <rpworld.h>
|
||||
|
||||
#include "Lights.h"
|
||||
#include "Timer.h"
|
||||
#include "Timecycle.h"
|
||||
#include "Coronas.h"
|
||||
#include "Weather.h"
|
||||
#include "ZoneCull.h"
|
||||
#include "Frontend.h"
|
||||
|
||||
RpLight *pAmbient;
|
||||
RpLight *pDirect;
|
||||
RpLight *pExtraDirectionals[4] = { nil };
|
||||
int LightStrengths[4];
|
||||
int NumExtraDirLightsInWorld;
|
||||
|
||||
RwRGBAReal AmbientLightColourForFrame;
|
||||
RwRGBAReal AmbientLightColourForFrame_PedsCarsAndObjects;
|
||||
RwRGBAReal DirectionalLightColourForFrame;
|
||||
|
||||
RwRGBAReal AmbientLightColour;
|
||||
RwRGBAReal DirectionalLightColour;
|
||||
|
||||
void
|
||||
SetLightsWithTimeOfDayColour(RpWorld *)
|
||||
{
|
||||
CVector vec1, vec2, vecsun;
|
||||
RwMatrix mat;
|
||||
|
||||
if(pAmbient){
|
||||
AmbientLightColourForFrame.red = CTimeCycle::GetAmbientRed() * CCoronas::LightsMult;
|
||||
AmbientLightColourForFrame.green = CTimeCycle::GetAmbientGreen() * CCoronas::LightsMult;
|
||||
AmbientLightColourForFrame.blue = CTimeCycle::GetAmbientBlue() * CCoronas::LightsMult;
|
||||
if(CWeather::LightningFlash && !CCullZones::CamNoRain()){
|
||||
AmbientLightColourForFrame.red = 1.0f;
|
||||
AmbientLightColourForFrame.green = 1.0f;
|
||||
AmbientLightColourForFrame.blue = 1.0f;
|
||||
}
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.red = Min(1.0f, AmbientLightColourForFrame.red*1.3f);
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.green = Min(1.0f, AmbientLightColourForFrame.green*1.3f);
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.blue = Min(1.0f, AmbientLightColourForFrame.blue*1.3f);
|
||||
RpLightSetColor(pAmbient, &AmbientLightColourForFrame);
|
||||
}
|
||||
|
||||
if(pDirect){
|
||||
DirectionalLightColourForFrame.red = CTimeCycle::GetDirectionalRed() * CCoronas::LightsMult;
|
||||
DirectionalLightColourForFrame.green = CTimeCycle::GetDirectionalGreen() * CCoronas::LightsMult;
|
||||
DirectionalLightColourForFrame.blue = CTimeCycle::GetDirectionalBlue() * CCoronas::LightsMult;
|
||||
RpLightSetColor(pDirect, &DirectionalLightColourForFrame);
|
||||
|
||||
vecsun = CTimeCycle::m_VectorToSun[CTimeCycle::m_CurrentStoredValue];
|
||||
vec1 = CVector(0.0f, 0.0f, 1.0f);
|
||||
vec2 = CrossProduct(vec1, vecsun);
|
||||
vec2.Normalise();
|
||||
vec1 = CrossProduct(vec2, vecsun);
|
||||
mat.at.x = -vecsun.x;
|
||||
mat.at.y = -vecsun.y;
|
||||
mat.at.z = -vecsun.z;
|
||||
mat.right.x = vec1.x;
|
||||
mat.right.y = vec1.y;
|
||||
mat.right.z = vec1.z;
|
||||
mat.up.x = vec2.x;
|
||||
mat.up.y = vec2.y;
|
||||
mat.up.z = vec2.z;
|
||||
RwFrameTransform(RpLightGetFrame(pDirect), &mat, rwCOMBINEREPLACE);
|
||||
}
|
||||
|
||||
if(CMenuManager::m_PrefsBrightness > 256){
|
||||
float f1 = 2.0f * (CMenuManager::m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f;
|
||||
float f2 = 3.0f * (CMenuManager::m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f;
|
||||
|
||||
AmbientLightColourForFrame.red = Min(1.0f, AmbientLightColourForFrame.red * f2);
|
||||
AmbientLightColourForFrame.green = Min(1.0f, AmbientLightColourForFrame.green * f2);
|
||||
AmbientLightColourForFrame.blue = Min(1.0f, AmbientLightColourForFrame.blue * f2);
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.red = Min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.red * f1);
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.green = Min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.green * f1);
|
||||
AmbientLightColourForFrame_PedsCarsAndObjects.blue = Min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.blue * f1);
|
||||
#ifdef FIX_BUGS
|
||||
DirectionalLightColourForFrame.red = Min(1.0f, DirectionalLightColourForFrame.red * f1);
|
||||
DirectionalLightColourForFrame.green = Min(1.0f, DirectionalLightColourForFrame.green * f1);
|
||||
DirectionalLightColourForFrame.blue = Min(1.0f, DirectionalLightColourForFrame.blue * f1);
|
||||
#else
|
||||
DirectionalLightColourForFrame.red = Min(1.0f, AmbientLightColourForFrame.red * f1);
|
||||
DirectionalLightColourForFrame.green = Min(1.0f, AmbientLightColourForFrame.green * f1);
|
||||
DirectionalLightColourForFrame.blue = Min(1.0f, AmbientLightColourForFrame.blue * f1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
RpWorld*
|
||||
LightsCreate(RpWorld *world)
|
||||
{
|
||||
int i;
|
||||
RwRGBAReal color;
|
||||
RwFrame *frame;
|
||||
|
||||
if(world == nil)
|
||||
return nil;
|
||||
|
||||
pAmbient = RpLightCreate(rpLIGHTAMBIENT);
|
||||
RpLightSetFlags(pAmbient, rpLIGHTLIGHTATOMICS);
|
||||
color.red = 0.25f;
|
||||
color.green = 0.25f;
|
||||
color.blue = 0.2f;
|
||||
RpLightSetColor(pAmbient, &color);
|
||||
|
||||
pDirect = RpLightCreate(rpLIGHTDIRECTIONAL);
|
||||
RpLightSetFlags(pDirect, rpLIGHTLIGHTATOMICS);
|
||||
color.red = 1.0f;
|
||||
color.green = 0.85f;
|
||||
color.blue = 0.45f;
|
||||
RpLightSetColor(pDirect, &color);
|
||||
RpLightSetRadius(pDirect, 2.0f);
|
||||
frame = RwFrameCreate();
|
||||
RpLightSetFrame(pDirect, frame);
|
||||
RwV3d axis = { 1.0f, 1.0f, 0.0f };
|
||||
RwFrameRotate(frame, &axis, 160.0f, rwCOMBINEPRECONCAT);
|
||||
|
||||
RpWorldAddLight(world, pAmbient);
|
||||
RpWorldAddLight(world, pDirect);
|
||||
|
||||
for(i = 0; i < NUMEXTRADIRECTIONALS; i++){
|
||||
pExtraDirectionals[i] = RpLightCreate(rpLIGHTDIRECTIONAL);
|
||||
RpLightSetFlags(pExtraDirectionals[i], 0);
|
||||
color.red = 1.0f;
|
||||
color.green = 0.5f;
|
||||
color.blue = 0.0f;
|
||||
RpLightSetColor(pExtraDirectionals[i], &color);
|
||||
RpLightSetRadius(pExtraDirectionals[i], 2.0f);
|
||||
frame = RwFrameCreate();
|
||||
RpLightSetFrame(pExtraDirectionals[i], frame);
|
||||
RpWorldAddLight(world, pExtraDirectionals[i]);
|
||||
}
|
||||
|
||||
return world;
|
||||
}
|
||||
|
||||
void
|
||||
LightsDestroy(RpWorld *world)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(world == nil)
|
||||
return;
|
||||
|
||||
if(pAmbient){
|
||||
RpWorldRemoveLight(world, pAmbient);
|
||||
RpLightDestroy(pAmbient);
|
||||
pAmbient = nil;
|
||||
}
|
||||
|
||||
if(pDirect){
|
||||
RpWorldRemoveLight(world, pDirect);
|
||||
RwFrameDestroy(RpLightGetFrame(pDirect));
|
||||
RpLightDestroy(pDirect);
|
||||
pDirect = nil;
|
||||
}
|
||||
|
||||
for(i = 0; i < NUMEXTRADIRECTIONALS; i++)
|
||||
if(pExtraDirectionals[i]){
|
||||
RpWorldRemoveLight(world, pExtraDirectionals[i]);
|
||||
RwFrameDestroy(RpLightGetFrame(pExtraDirectionals[i]));
|
||||
RpLightDestroy(pExtraDirectionals[i]);
|
||||
pExtraDirectionals[i] = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorldReplaceNormalLightsWithScorched(RpWorld *world, float l)
|
||||
{
|
||||
RwRGBAReal color;
|
||||
color.red = l;
|
||||
color.green = l;
|
||||
color.blue = l;
|
||||
RpLightSetColor(pAmbient, &color);
|
||||
RpLightSetFlags(pDirect, 0);
|
||||
}
|
||||
|
||||
void
|
||||
WorldReplaceScorchedLightsWithNormal(RpWorld *world)
|
||||
{
|
||||
RpLightSetColor(pAmbient, &AmbientLightColourForFrame);
|
||||
RpLightSetFlags(pDirect, rpLIGHTLIGHTATOMICS);
|
||||
}
|
||||
|
||||
void
|
||||
AddAnExtraDirectionalLight(RpWorld *world, float dirx, float diry, float dirz, float red, float green, float blue)
|
||||
{
|
||||
float strength;
|
||||
int weakest;
|
||||
int i, n;
|
||||
RwRGBAReal color;
|
||||
RwV3d *dir;
|
||||
|
||||
strength = Max(Max(red, green), blue);
|
||||
n = -1;
|
||||
if(NumExtraDirLightsInWorld < NUMEXTRADIRECTIONALS)
|
||||
n = NumExtraDirLightsInWorld;
|
||||
else{
|
||||
weakest = strength;
|
||||
for(i = 0; i < NUMEXTRADIRECTIONALS; i++)
|
||||
if(LightStrengths[i] < weakest){
|
||||
weakest = LightStrengths[i];
|
||||
n = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(n < 0)
|
||||
return;
|
||||
|
||||
color.red = red;
|
||||
color.green = green;
|
||||
color.blue = blue;
|
||||
RpLightSetColor(pExtraDirectionals[n], &color);
|
||||
dir = RwMatrixGetAt(RwFrameGetMatrix(RpLightGetFrame(pExtraDirectionals[n])));
|
||||
dir->x = -dirx;
|
||||
dir->y = -diry;
|
||||
dir->z = -dirz;
|
||||
RwMatrixUpdate(RwFrameGetMatrix(RpLightGetFrame(pExtraDirectionals[n])));
|
||||
RwFrameUpdateObjects(RpLightGetFrame(pExtraDirectionals[n]));
|
||||
RpLightSetFlags(pExtraDirectionals[n], rpLIGHTLIGHTATOMICS);
|
||||
LightStrengths[n] = strength;
|
||||
NumExtraDirLightsInWorld = Min(NumExtraDirLightsInWorld+1, NUMEXTRADIRECTIONALS);
|
||||
}
|
||||
|
||||
void
|
||||
RemoveExtraDirectionalLights(RpWorld *world)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < NumExtraDirLightsInWorld; i++)
|
||||
RpLightSetFlags(pExtraDirectionals[i], 0);
|
||||
NumExtraDirLightsInWorld = 0;
|
||||
}
|
||||
|
||||
void
|
||||
SetAmbientAndDirectionalColours(float f)
|
||||
{
|
||||
AmbientLightColour.red = AmbientLightColourForFrame.red * f;
|
||||
AmbientLightColour.green = AmbientLightColourForFrame.green * f;
|
||||
AmbientLightColour.blue = AmbientLightColourForFrame.blue * f;
|
||||
|
||||
DirectionalLightColour.red = DirectionalLightColourForFrame.red * f;
|
||||
DirectionalLightColour.green = DirectionalLightColourForFrame.green * f;
|
||||
DirectionalLightColour.blue = DirectionalLightColourForFrame.blue * f;
|
||||
|
||||
RpLightSetColor(pAmbient, &AmbientLightColour);
|
||||
RpLightSetColor(pDirect, &DirectionalLightColour);
|
||||
}
|
||||
|
||||
// unused
|
||||
void
|
||||
SetFlashyColours(float f)
|
||||
{
|
||||
if(CTimer::GetTimeInMilliseconds() & 0x100){
|
||||
AmbientLightColour.red = 1.0f;
|
||||
AmbientLightColour.green = 1.0f;
|
||||
AmbientLightColour.blue = 1.0f;
|
||||
|
||||
DirectionalLightColour.red = DirectionalLightColourForFrame.red;
|
||||
DirectionalLightColour.green = DirectionalLightColourForFrame.green;
|
||||
DirectionalLightColour.blue = DirectionalLightColourForFrame.blue;
|
||||
|
||||
RpLightSetColor(pAmbient, &AmbientLightColour);
|
||||
RpLightSetColor(pDirect, &DirectionalLightColour);
|
||||
}else{
|
||||
SetAmbientAndDirectionalColours(f * 0.75f);
|
||||
}
|
||||
}
|
||||
|
||||
// unused
|
||||
void
|
||||
SetFlashyColours_Mild(float f)
|
||||
{
|
||||
if(CTimer::GetTimeInMilliseconds() & 0x100){
|
||||
AmbientLightColour.red = 0.65f;
|
||||
AmbientLightColour.green = 0.65f;
|
||||
AmbientLightColour.blue = 0.65f;
|
||||
|
||||
DirectionalLightColour.red = DirectionalLightColourForFrame.red;
|
||||
DirectionalLightColour.green = DirectionalLightColourForFrame.green;
|
||||
DirectionalLightColour.blue = DirectionalLightColourForFrame.blue;
|
||||
|
||||
RpLightSetColor(pAmbient, &AmbientLightColour);
|
||||
RpLightSetColor(pDirect, &DirectionalLightColour);
|
||||
}else{
|
||||
SetAmbientAndDirectionalColours(f * 0.9f);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SetBrightMarkerColours(float f)
|
||||
{
|
||||
AmbientLightColour.red = 0.6f;
|
||||
AmbientLightColour.green = 0.6f;
|
||||
AmbientLightColour.blue = 0.6f;
|
||||
|
||||
DirectionalLightColour.red = (1.0f - DirectionalLightColourForFrame.red) * 0.4f + DirectionalLightColourForFrame.red;
|
||||
DirectionalLightColour.green = (1.0f - DirectionalLightColourForFrame.green) * 0.4f + DirectionalLightColourForFrame.green;
|
||||
DirectionalLightColour.blue = (1.0f - DirectionalLightColourForFrame.blue) * 0.4f + DirectionalLightColourForFrame.blue;
|
||||
|
||||
RpLightSetColor(pAmbient, &AmbientLightColour);
|
||||
RpLightSetColor(pDirect, &DirectionalLightColour);
|
||||
}
|
||||
|
||||
void
|
||||
ReSetAmbientAndDirectionalColours(void)
|
||||
{
|
||||
RpLightSetColor(pAmbient, &AmbientLightColourForFrame);
|
||||
RpLightSetColor(pDirect, &DirectionalLightColourForFrame);
|
||||
}
|
||||
|
||||
void
|
||||
DeActivateDirectional(void)
|
||||
{
|
||||
RpLightSetFlags(pDirect, 0);
|
||||
}
|
||||
|
||||
void
|
||||
ActivateDirectional(void)
|
||||
{
|
||||
RpLightSetFlags(pDirect, rpLIGHTLIGHTATOMICS);
|
||||
}
|
||||
|
||||
void
|
||||
SetAmbientColours(void)
|
||||
{
|
||||
RpLightSetColor(pAmbient, &AmbientLightColourForFrame);
|
||||
}
|
||||
|
||||
void
|
||||
SetAmbientColoursForPedsCarsAndObjects(void)
|
||||
{
|
||||
RpLightSetColor(pAmbient, &AmbientLightColourForFrame_PedsCarsAndObjects);
|
||||
}
|
||||
|
||||
uint8 IndicateR[] = { 0, 255, 0, 0, 255, 255, 0 };
|
||||
uint8 IndicateG[] = { 0, 0, 255, 0, 255, 0, 255 };
|
||||
uint8 IndicateB[] = { 0, 0, 0, 255, 0, 255, 255 };
|
||||
|
||||
void
|
||||
SetAmbientColoursToIndicateRoadGroup(int i)
|
||||
{
|
||||
AmbientLightColour.red = IndicateR[i%7]/255.0f;
|
||||
AmbientLightColour.green = IndicateG[i%7]/255.0f;
|
||||
AmbientLightColour.blue = IndicateB[i%7]/255.0f;
|
||||
RpLightSetColor(pAmbient, &AmbientLightColour);
|
||||
}
|
||||
|
||||
void
|
||||
SetAmbientColours(RwRGBAReal *color)
|
||||
{
|
||||
RpLightSetColor(pAmbient, color);
|
||||
}
|
||||
26
src/rw/Lights.h
Normal file
26
src/rw/Lights.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
extern RpLight *pAmbient;
|
||||
extern RpLight *pDirect;
|
||||
extern RpLight *pExtraDirectionals[4];
|
||||
extern int LightStrengths[4];
|
||||
extern int NumExtraDirLightsInWorld;
|
||||
|
||||
void SetLightsWithTimeOfDayColour(RpWorld *);
|
||||
RpWorld *LightsCreate(RpWorld *world);
|
||||
void LightsDestroy(RpWorld *world);
|
||||
void WorldReplaceNormalLightsWithScorched(RpWorld *world, float l);
|
||||
void WorldReplaceScorchedLightsWithNormal(RpWorld *world);
|
||||
void AddAnExtraDirectionalLight(RpWorld *world, float dirx, float diry, float dirz, float red, float green, float blue);
|
||||
void RemoveExtraDirectionalLights(RpWorld *world);
|
||||
void SetAmbientAndDirectionalColours(float f);
|
||||
void SetFlashyColours(float f);
|
||||
void SetFlashyColours_Mild(float f);
|
||||
void SetBrightMarkerColours(float f);
|
||||
void ReSetAmbientAndDirectionalColours(void);
|
||||
void DeActivateDirectional(void);
|
||||
void ActivateDirectional(void);
|
||||
void SetAmbientColours(void);
|
||||
void SetAmbientColoursForPedsCarsAndObjects(void);
|
||||
void SetAmbientColoursToIndicateRoadGroup(int i);
|
||||
void SetAmbientColours(RwRGBAReal *color);
|
||||
497
src/rw/MemoryHeap.cpp
Normal file
497
src/rw/MemoryHeap.cpp
Normal file
|
|
@ -0,0 +1,497 @@
|
|||
#include "common.h"
|
||||
#include "main.h"
|
||||
#include "FileMgr.h"
|
||||
#include "Timer.h"
|
||||
#include "ModelInfo.h"
|
||||
#include "Streaming.h"
|
||||
#include "FileLoader.h"
|
||||
#include "MemoryHeap.h"
|
||||
|
||||
#ifdef USE_CUSTOM_ALLOCATOR
|
||||
|
||||
//#define MEMORYHEAP_ASSERT(cond) { if (!(cond)) { printf("ASSERT File:%s Line:%d\n", __FILE__, __LINE__); exit(1); } }
|
||||
//#define MEMORYHEAP_ASSERT_MESSAGE(cond, message) { if (!(cond)) { printf("ASSERT File:%s Line:%d:\n\t%s\n", __FILE__, __LINE__, message); exit(1); } }
|
||||
|
||||
#define MEMORYHEAP_ASSERT(cond) assert(cond)
|
||||
#define MEMORYHEAP_ASSERT_MESSAGE(cond, message) assert(cond)
|
||||
|
||||
// registered pointers that we keep track of
|
||||
void **gPtrList[4000];
|
||||
int32 numPtrs;
|
||||
int32 gPosnInList;
|
||||
// indices into the ptr list in here are free
|
||||
CStack<int32, 4000> m_ptrListIndexStack;
|
||||
// how much memory we've moved
|
||||
uint32 memMoved;
|
||||
|
||||
CMemoryHeap gMainHeap;
|
||||
|
||||
void
|
||||
CMemoryHeap::Init(uint32 total)
|
||||
{
|
||||
MEMORYHEAP_ASSERT((total != 0xF) != 0);
|
||||
|
||||
m_totalMemUsed = 0;
|
||||
m_memUsed = nil;
|
||||
m_currentMemID = MEMID_FREE;
|
||||
m_blocksUsed = nil;
|
||||
m_totalBlocksUsed = 0;
|
||||
m_unkMemId = -1;
|
||||
|
||||
uint8 *mem = (uint8*)malloc(total);
|
||||
assert(((uintptr)mem & 0xF) == 0);
|
||||
m_start = (HeapBlockDesc*)mem;
|
||||
m_end = (HeapBlockDesc*)(mem + total - sizeof(HeapBlockDesc));
|
||||
m_start->m_memId = MEMID_FREE;
|
||||
m_start->m_size = total - 2*sizeof(HeapBlockDesc);
|
||||
m_end->m_memId = MEMID_GAME;
|
||||
m_end->m_size = 0;
|
||||
|
||||
m_freeList.m_last.m_size = INT_MAX;
|
||||
m_freeList.Init();
|
||||
m_freeList.Insert(m_start);
|
||||
|
||||
// TODO: figure out what these are and use sizeof
|
||||
m_fixedSize[0].Init(0x10);
|
||||
m_fixedSize[1].Init(0x20);
|
||||
m_fixedSize[2].Init(0xE0);
|
||||
m_fixedSize[3].Init(0x60);
|
||||
m_fixedSize[4].Init(0x1C0);
|
||||
m_fixedSize[5].Init(0x50);
|
||||
|
||||
m_currentMemID = MEMID_FREE; // disable registration
|
||||
m_memUsed = (uint32*)Malloc(NUM_MEMIDS * sizeof(uint32));
|
||||
m_blocksUsed = (uint32*)Malloc(NUM_MEMIDS * sizeof(uint32));
|
||||
RegisterMalloc(GetDescFromHeapPointer(m_memUsed));
|
||||
RegisterMalloc(GetDescFromHeapPointer(m_blocksUsed));
|
||||
|
||||
m_currentMemID = MEMID_GAME;
|
||||
for(int i = 0; i < NUM_MEMIDS; i++){
|
||||
m_memUsed[i] = 0;
|
||||
m_blocksUsed[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CMemoryHeap::RegisterMalloc(HeapBlockDesc *block)
|
||||
{
|
||||
block->m_memId = m_currentMemID;
|
||||
if(m_currentMemID == MEMID_FREE)
|
||||
return;
|
||||
m_totalMemUsed += block->m_size + sizeof(HeapBlockDesc);
|
||||
m_memUsed[m_currentMemID] += block->m_size + sizeof(HeapBlockDesc);
|
||||
m_blocksUsed[m_currentMemID]++;
|
||||
m_totalBlocksUsed++;
|
||||
}
|
||||
|
||||
void
|
||||
CMemoryHeap::RegisterFree(HeapBlockDesc *block)
|
||||
{
|
||||
if(block->m_memId == MEMID_FREE)
|
||||
return;
|
||||
m_totalMemUsed -= block->m_size + sizeof(HeapBlockDesc);
|
||||
m_memUsed[block->m_memId] -= block->m_size + sizeof(HeapBlockDesc);
|
||||
m_blocksUsed[block->m_memId]--;
|
||||
m_totalBlocksUsed--;
|
||||
}
|
||||
|
||||
void*
|
||||
CMemoryHeap::Malloc(uint32 size)
|
||||
{
|
||||
static int recursion = 0;
|
||||
|
||||
// weird way to round up
|
||||
if((size & 0xF) != 0)
|
||||
size = (size&~0xF) + 0x10;
|
||||
|
||||
recursion++;
|
||||
|
||||
// See if we can allocate from one of the fixed-size lists
|
||||
for(int i = 0; i < NUM_FIXED_MEMBLOCKS; i++){
|
||||
CommonSize *list = &m_fixedSize[i];
|
||||
if(m_fixedSize[i].m_size == size){
|
||||
HeapBlockDesc *block = list->Malloc();
|
||||
if(block){
|
||||
RegisterMalloc(block);
|
||||
recursion--;
|
||||
return block->GetDataPointer();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// now try the normal free list
|
||||
HeapBlockDesc *next;
|
||||
for(HeapBlockDesc *block = m_freeList.m_first.m_next;
|
||||
block != &m_freeList.m_last;
|
||||
block = next){
|
||||
MEMORYHEAP_ASSERT(block->m_memId == MEMID_FREE);
|
||||
MEMORYHEAP_ASSERT_MESSAGE(block >= m_start && block <= m_end, "Block outside of memory");
|
||||
|
||||
// make sure block has maximum size
|
||||
uint32 initialsize = block->m_size;
|
||||
uint32 blocksize = CombineFreeBlocks(block);
|
||||
#ifdef FIX_BUGS
|
||||
// has to be done here because block can be moved
|
||||
next = block->m_next;
|
||||
#endif
|
||||
if(initialsize != blocksize){
|
||||
block->RemoveHeapFreeBlock();
|
||||
HeapBlockDesc *pos = block->m_prev->FindSmallestFreeBlock(block->m_size);
|
||||
block->InsertHeapFreeBlock(pos->m_prev);
|
||||
}
|
||||
if(block->m_size >= size){
|
||||
// got space to allocate from!
|
||||
block->RemoveHeapFreeBlock();
|
||||
FillInBlockData(block, block->GetNextConsecutive(), size);
|
||||
recursion--;
|
||||
return block->GetDataPointer();
|
||||
}
|
||||
#ifndef FIX_BUGS
|
||||
next = block->m_next;
|
||||
#endif
|
||||
}
|
||||
|
||||
// oh no, we're losing, try to free some stuff
|
||||
static bool removeCollision = false;
|
||||
static bool removeIslands = false;
|
||||
static bool removeBigBuildings = false;
|
||||
size_t initialMemoryUsed = CStreaming::ms_memoryUsed;
|
||||
CStreaming::MakeSpaceFor(0xCFE800 - CStreaming::ms_memoryUsed);
|
||||
if (recursion > 10)
|
||||
CGame::TidyUpMemory(true, false);
|
||||
else if (recursion > 6)
|
||||
CGame::TidyUpMemory(false, true);
|
||||
if (initialMemoryUsed == CStreaming::ms_memoryUsed && recursion > 11) {
|
||||
if (!removeCollision && !CGame::playingIntro) {
|
||||
CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC);
|
||||
removeCollision = true;
|
||||
}
|
||||
else if (!removeIslands && !CGame::playingIntro) {
|
||||
CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL);
|
||||
CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL);
|
||||
CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
|
||||
removeIslands = true;
|
||||
}
|
||||
else if (!removeBigBuildings) {
|
||||
CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);
|
||||
CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);
|
||||
CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);
|
||||
}
|
||||
else {
|
||||
LoadingScreen("NO MORE MEMORY", nil, nil);
|
||||
LoadingScreen("NO MORE MEMORY", nil, nil);
|
||||
}
|
||||
CGame::TidyUpMemory(true, false);
|
||||
}
|
||||
void *mem = Malloc(size);
|
||||
if (removeCollision) {
|
||||
CTimer::Stop();
|
||||
// TODO: different on PS2
|
||||
CFileLoader::LoadCollisionFromDatFile(CCollision::ms_collisionInMemory);
|
||||
removeCollision = false;
|
||||
CTimer::Update();
|
||||
}
|
||||
if (removeBigBuildings || removeIslands) {
|
||||
CTimer::Stop();
|
||||
if (!CGame::playingIntro)
|
||||
CStreaming::RequestBigBuildings(CGame::currLevel);
|
||||
CStreaming::LoadAllRequestedModels(true);
|
||||
removeBigBuildings = false;
|
||||
removeIslands = false;
|
||||
CTimer::Update();
|
||||
}
|
||||
recursion--;
|
||||
return mem;
|
||||
}
|
||||
|
||||
void*
|
||||
CMemoryHeap::Realloc(void *ptr, uint32 size)
|
||||
{
|
||||
if(ptr == nil)
|
||||
return Malloc(size);
|
||||
|
||||
// weird way to round up
|
||||
if((size & 0xF) != 0)
|
||||
size = (size&~0xF) + 0x10;
|
||||
|
||||
HeapBlockDesc *block = GetDescFromHeapPointer(ptr);
|
||||
|
||||
#ifdef FIX_BUGS
|
||||
// better handling of size < block->m_size
|
||||
if(size == 0){
|
||||
Free(ptr);
|
||||
return nil;
|
||||
}
|
||||
if(block->m_size >= size){
|
||||
// shrink allocated block
|
||||
RegisterFree(block);
|
||||
PushMemId(block->m_memId);
|
||||
FillInBlockData(block, block->GetNextConsecutive(), size);
|
||||
PopMemId();
|
||||
return ptr;
|
||||
}
|
||||
#else
|
||||
// not growing. just returning here is a bit cheap though
|
||||
if(block->m_size >= size)
|
||||
return ptr;
|
||||
#endif
|
||||
|
||||
// have to grow allocated block
|
||||
HeapBlockDesc *next = block->GetNextConsecutive();
|
||||
MEMORYHEAP_ASSERT_MESSAGE(next >= m_start && next <= m_end, "Block outside of memory");
|
||||
if(next->m_memId == MEMID_FREE){
|
||||
// try to grow the current block
|
||||
// make sure the next free block has maximum size
|
||||
uint32 freespace = CombineFreeBlocks(next);
|
||||
HeapBlockDesc *end = next->GetNextConsecutive();
|
||||
MEMORYHEAP_ASSERT_MESSAGE(end >= m_start && end <= m_end, "Block outside of memory");
|
||||
// why the sizeof here?
|
||||
if(block->m_size + next->m_size + sizeof(HeapBlockDesc) >= size){
|
||||
// enough space to grow
|
||||
next->RemoveHeapFreeBlock();
|
||||
RegisterFree(block);
|
||||
PushMemId(block->m_memId);
|
||||
FillInBlockData(block, next->GetNextConsecutive(), size);
|
||||
PopMemId();
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// can't grow the existing block, have to get a new one and copy
|
||||
PushMemId(block->m_memId);
|
||||
void *dst = Malloc(size);
|
||||
PopMemId();
|
||||
memcpy(dst, ptr, block->m_size);
|
||||
Free(ptr);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void
|
||||
CMemoryHeap::Free(void *ptr)
|
||||
{
|
||||
HeapBlockDesc *block = GetDescFromHeapPointer(ptr);
|
||||
MEMORYHEAP_ASSERT_MESSAGE(block->m_memId != MEMID_FREE, "MemoryHeap corrupt");
|
||||
MEMORYHEAP_ASSERT(m_unkMemId == -1 || m_unkMemId == block->m_memId);
|
||||
|
||||
RegisterFree(block);
|
||||
block->m_memId = MEMID_FREE;
|
||||
CombineFreeBlocks(block);
|
||||
FreeBlock(block);
|
||||
if(block->m_ptrListIndex != -1){
|
||||
int32 idx = block->m_ptrListIndex;
|
||||
gPtrList[idx] = nil;
|
||||
m_ptrListIndexStack.push(idx);
|
||||
}
|
||||
block->m_ptrListIndex = -1;
|
||||
}
|
||||
|
||||
// allocate 'size' bytes from 'block'
|
||||
void
|
||||
CMemoryHeap::FillInBlockData(HeapBlockDesc *block, HeapBlockDesc *end, uint32 size)
|
||||
{
|
||||
block->m_size = size;
|
||||
block->m_ptrListIndex = -1;
|
||||
HeapBlockDesc *remainder = block->GetNextConsecutive();
|
||||
MEMORYHEAP_ASSERT(remainder <= end);
|
||||
|
||||
if(remainder < end-1){
|
||||
RegisterMalloc(block);
|
||||
|
||||
// can fit another block in the remaining space
|
||||
remainder->m_size = GetSizeBetweenBlocks(remainder, end);
|
||||
remainder->m_memId = MEMID_FREE;
|
||||
MEMORYHEAP_ASSERT(remainder->m_size != 0);
|
||||
FreeBlock(remainder);
|
||||
}else{
|
||||
// fully allocate this one
|
||||
if(remainder < end)
|
||||
// no gaps allowed
|
||||
block->m_size = GetSizeBetweenBlocks(block, end);
|
||||
RegisterMalloc(block);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure free block has no other free blocks after it
|
||||
uint32
|
||||
CMemoryHeap::CombineFreeBlocks(HeapBlockDesc *block)
|
||||
{
|
||||
HeapBlockDesc *next = block->GetNextConsecutive();
|
||||
if(next->m_memId != MEMID_FREE)
|
||||
return block->m_size;
|
||||
// get rid of free blocks after this one and adjust size
|
||||
for(; next->m_memId == MEMID_FREE; next = next->GetNextConsecutive())
|
||||
next->RemoveHeapFreeBlock();
|
||||
block->m_size = GetSizeBetweenBlocks(block, next);
|
||||
return block->m_size;
|
||||
}
|
||||
|
||||
// Try to move all registered memory blocks into more optimal location
|
||||
void
|
||||
CMemoryHeap::TidyHeap(void)
|
||||
{
|
||||
for(int i = 0; i < numPtrs; i++){
|
||||
if(gPtrList[i] == nil || *gPtrList[i] == nil)
|
||||
continue;
|
||||
HeapBlockDesc *newblock = WhereShouldMemoryMove(*gPtrList[i]);
|
||||
if(newblock)
|
||||
*gPtrList[i] = MoveHeapBlock(newblock, GetDescFromHeapPointer(*gPtrList[i]));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void
|
||||
CMemoryHeap::RegisterMemPointer(void *ptr)
|
||||
{
|
||||
HeapBlockDesc *block = GetDescFromHeapPointer(*(void**)ptr);
|
||||
|
||||
if(block->m_ptrListIndex != -1)
|
||||
return; // already registered
|
||||
|
||||
int index;
|
||||
if(m_ptrListIndexStack.sp > 0){
|
||||
// re-use a previously free'd index
|
||||
index = m_ptrListIndexStack.pop();
|
||||
}else{
|
||||
// have to find a new index
|
||||
index = gPosnInList;
|
||||
|
||||
void **pp = gPtrList[index];
|
||||
// we're replacing an old pointer here??
|
||||
if(pp && *pp && *pp != (void*)0xDDDDDDDD)
|
||||
GetDescFromHeapPointer(*pp)->m_ptrListIndex = -1;
|
||||
|
||||
gPosnInList++;
|
||||
if(gPosnInList == 4000)
|
||||
gPosnInList = 0;
|
||||
if(numPtrs < 4000)
|
||||
numPtrs++;
|
||||
}
|
||||
gPtrList[index] = (void**)ptr;
|
||||
block->m_ptrListIndex = index;
|
||||
}
|
||||
|
||||
void*
|
||||
CMemoryHeap::MoveMemory(void *ptr)
|
||||
{
|
||||
HeapBlockDesc *newblock = WhereShouldMemoryMove(ptr);
|
||||
if(newblock)
|
||||
return MoveHeapBlock(newblock, GetDescFromHeapPointer(ptr));
|
||||
else
|
||||
return ptr;
|
||||
}
|
||||
|
||||
HeapBlockDesc*
|
||||
CMemoryHeap::WhereShouldMemoryMove(void *ptr)
|
||||
{
|
||||
HeapBlockDesc *block = GetDescFromHeapPointer(ptr);
|
||||
MEMORYHEAP_ASSERT(block->m_memId != MEMID_FREE);
|
||||
|
||||
HeapBlockDesc *next = block->GetNextConsecutive();
|
||||
if(next->m_memId != MEMID_FREE)
|
||||
return nil;
|
||||
|
||||
// we want to move the block into another block
|
||||
// such that the free space between this and the next block can be minimized
|
||||
HeapBlockDesc *newblock = m_freeList.m_first.FindSmallestFreeBlock(block->m_size);
|
||||
// size of free space wouldn't decrease, so return
|
||||
if(newblock->m_size >= block->m_size + next->m_size)
|
||||
return nil;
|
||||
// size of free space wouldn't decrease enough
|
||||
if(newblock->m_size >= 16 + 1.125f*block->m_size) // what are 16 and 1.125 here? sizeof(HeapBlockDesc)?
|
||||
return nil;
|
||||
return newblock;
|
||||
}
|
||||
|
||||
void*
|
||||
CMemoryHeap::MoveHeapBlock(HeapBlockDesc *dst, HeapBlockDesc *src)
|
||||
{
|
||||
PushMemId(src->m_memId);
|
||||
dst->RemoveHeapFreeBlock();
|
||||
FillInBlockData(dst, dst->GetNextConsecutive(), src->m_size);
|
||||
PopMemId();
|
||||
memcpy(dst->GetDataPointer(), src->GetDataPointer(), src->m_size);
|
||||
memMoved += src->m_size;
|
||||
dst->m_ptrListIndex = src->m_ptrListIndex;
|
||||
src->m_ptrListIndex = -1;
|
||||
Free(src->GetDataPointer());
|
||||
return dst->GetDataPointer();
|
||||
}
|
||||
|
||||
uint32
|
||||
CMemoryHeap::GetMemoryUsed(int32 id)
|
||||
{
|
||||
return m_memUsed[id];
|
||||
}
|
||||
|
||||
uint32
|
||||
CMemoryHeap::GetBlocksUsed(int32 id)
|
||||
{
|
||||
return m_blocksUsed[id];
|
||||
}
|
||||
|
||||
void
|
||||
CMemoryHeap::PopMemId(void)
|
||||
{
|
||||
assert(m_idStack.sp > 0);
|
||||
m_currentMemID = m_idStack.pop();
|
||||
assert(m_currentMemID != MEMID_FREE);
|
||||
}
|
||||
|
||||
void
|
||||
CMemoryHeap::PushMemId(int32 id)
|
||||
{
|
||||
MEMORYHEAP_ASSERT(id != MEMID_FREE);
|
||||
assert(m_idStack.sp < 16);
|
||||
m_idStack.push(m_currentMemID);
|
||||
m_currentMemID = id;
|
||||
}
|
||||
|
||||
void
|
||||
CMemoryHeap::ParseHeap(void)
|
||||
{
|
||||
char tmp[16];
|
||||
int fd = CFileMgr::OpenFileForWriting("heap.txt");
|
||||
CTimer::Stop();
|
||||
|
||||
// CMemoryHeap::IntegrityCheck();
|
||||
|
||||
uint32 addrQW = 0;
|
||||
for(HeapBlockDesc *block = m_start; block < m_end; block = block->GetNextConsecutive()){
|
||||
char chr = '*'; // free
|
||||
if(block->m_memId != MEMID_FREE)
|
||||
chr = block->m_memId-1 + 'A';
|
||||
int numQW = block->m_size>>4;
|
||||
|
||||
if((addrQW & 0x3F) == 0){
|
||||
sprintf(tmp, "\n%5dK:", addrQW>>6);
|
||||
CFileMgr::Write(fd, tmp, 8);
|
||||
}
|
||||
CFileMgr::Write(fd, "#", 1); // the descriptor, has to be 16 bytes!!!!
|
||||
addrQW++;
|
||||
|
||||
while(numQW--){
|
||||
if((addrQW & 0x3F) == 0){
|
||||
sprintf(tmp, "\n%5dK:", addrQW>>6);
|
||||
CFileMgr::Write(fd, tmp, 8);
|
||||
}
|
||||
CFileMgr::Write(fd, &chr, 1);
|
||||
addrQW++;
|
||||
}
|
||||
}
|
||||
|
||||
CTimer::Update();
|
||||
CFileMgr::CloseFile(fd);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CommonSize::Init(uint32 size)
|
||||
{
|
||||
m_freeList.Init();
|
||||
m_size = size;
|
||||
m_failed = 0;
|
||||
m_remaining = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
202
src/rw/MemoryHeap.h
Normal file
202
src/rw/MemoryHeap.h
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
#pragma once
|
||||
|
||||
// some windows shit
|
||||
#ifdef MoveMemory
|
||||
#undef MoveMemory
|
||||
#endif
|
||||
|
||||
#ifdef USE_CUSTOM_ALLOCATOR
|
||||
#define PUSH_MEMID(id) gMainHeap.PushMemId(id)
|
||||
#define POP_MEMID() gMainHeap.PopMemId()
|
||||
#define REGISTER_MEMPTR(ptr) gMainHeap.RegisterMemPointer(ptr)
|
||||
#else
|
||||
#define PUSH_MEMID(id)
|
||||
#define POP_MEMID()
|
||||
#define REGISTER_MEMPTR(ptr)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
MEMID_FREE,
|
||||
MEMID_GAME = 1, // "Game"
|
||||
MEMID_WORLD = 2, // "World"
|
||||
MEMID_ANIMATION = 3, // "Animation"
|
||||
MEMID_POOLS = 4, // "Pools"
|
||||
MEMID_DEF_MODELS = 5, // "Default Models"
|
||||
MEMID_STREAM = 6, // "Streaming"
|
||||
MEMID_STREAM_MODELS = 7, // "Streamed Models" (instance)
|
||||
MEMID_STREAM_TEXUTRES = 8, // "Streamed Textures"
|
||||
MEMID_TEXTURES = 9, // "Textures"
|
||||
MEMID_COLLISION = 10, // "Collision"
|
||||
MEMID_RENDERLIST = 11, // ?
|
||||
MEMID_GAME_PROCESS = 12, // "Game Process"
|
||||
MEMID_SCRIPT = 13, // "Script"
|
||||
MEMID_CARS = 14, // "Cars"
|
||||
MEMID_RENDER = 15, // "Render"
|
||||
MEMID_FRONTEND = 17, // ?
|
||||
|
||||
NUM_MEMIDS,
|
||||
|
||||
NUM_FIXED_MEMBLOCKS = 6
|
||||
};
|
||||
|
||||
template<typename T, uint32 N>
|
||||
class CStack
|
||||
{
|
||||
public:
|
||||
T values[N];
|
||||
uint32 sp;
|
||||
|
||||
CStack() : sp(0) {}
|
||||
void push(const T& val) { values[sp++] = val; }
|
||||
T& pop() { return values[--sp]; }
|
||||
};
|
||||
|
||||
|
||||
struct HeapBlockDesc
|
||||
{
|
||||
uint32 m_size;
|
||||
int16 m_memId;
|
||||
int16 m_ptrListIndex;
|
||||
HeapBlockDesc *m_next;
|
||||
HeapBlockDesc *m_prev;
|
||||
|
||||
HeapBlockDesc *GetNextConsecutive(void)
|
||||
{
|
||||
return (HeapBlockDesc*)((uintptr)this + sizeof(HeapBlockDesc) + m_size);
|
||||
}
|
||||
|
||||
void *GetDataPointer(void)
|
||||
{
|
||||
return (void*)((uintptr)this + sizeof(HeapBlockDesc));
|
||||
}
|
||||
|
||||
void RemoveHeapFreeBlock(void)
|
||||
{
|
||||
m_next->m_prev = m_prev;
|
||||
m_prev->m_next = m_next;
|
||||
}
|
||||
|
||||
// after node
|
||||
void InsertHeapFreeBlock(HeapBlockDesc *node)
|
||||
{
|
||||
m_next = node->m_next;
|
||||
node->m_next->m_prev = this;
|
||||
m_prev = node;
|
||||
node->m_next = this;
|
||||
}
|
||||
|
||||
HeapBlockDesc *FindSmallestFreeBlock(uint32 size)
|
||||
{
|
||||
HeapBlockDesc *b;
|
||||
for(b = m_next; b->m_size < size; b = b->m_next);
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef USE_CUSTOM_ALLOCATOR
|
||||
// TODO: figure something out for 64 bit pointers
|
||||
static_assert(sizeof(HeapBlockDesc) == 0x10, "HeapBlockDesc must have 0x10 size otherwise most of assumptions don't make sense");
|
||||
#endif
|
||||
|
||||
struct HeapBlockList
|
||||
{
|
||||
HeapBlockDesc m_first;
|
||||
HeapBlockDesc m_last;
|
||||
|
||||
void Init(void)
|
||||
{
|
||||
m_first.m_next = &m_last;
|
||||
m_last.m_prev = &m_first;
|
||||
}
|
||||
|
||||
void Insert(HeapBlockDesc *node)
|
||||
{
|
||||
node->InsertHeapFreeBlock(&m_first);
|
||||
}
|
||||
};
|
||||
|
||||
struct CommonSize
|
||||
{
|
||||
HeapBlockList m_freeList;
|
||||
uint32 m_size;
|
||||
uint32 m_failed;
|
||||
uint32 m_remaining;
|
||||
|
||||
void Init(uint32 size);
|
||||
void Free(HeapBlockDesc *node)
|
||||
{
|
||||
m_freeList.Insert(node);
|
||||
m_remaining++;
|
||||
}
|
||||
HeapBlockDesc *Malloc(void)
|
||||
{
|
||||
if(m_freeList.m_first.m_next == &m_freeList.m_last){
|
||||
m_failed++;
|
||||
return nil;
|
||||
}
|
||||
HeapBlockDesc *block = m_freeList.m_first.m_next;
|
||||
m_remaining--;
|
||||
block->RemoveHeapFreeBlock();
|
||||
block->m_ptrListIndex = -1;
|
||||
return block;
|
||||
}
|
||||
};
|
||||
|
||||
class CMemoryHeap
|
||||
{
|
||||
public:
|
||||
HeapBlockDesc *m_start;
|
||||
HeapBlockDesc *m_end;
|
||||
HeapBlockList m_freeList;
|
||||
CommonSize m_fixedSize[NUM_FIXED_MEMBLOCKS];
|
||||
uint32 m_totalMemUsed;
|
||||
CStack<int32, 16> m_idStack;
|
||||
uint32 m_currentMemID;
|
||||
uint32 *m_memUsed;
|
||||
uint32 m_totalBlocksUsed;
|
||||
uint32 *m_blocksUsed;
|
||||
uint32 m_unkMemId;
|
||||
|
||||
CMemoryHeap(void) : m_start(nil) {}
|
||||
void Init(uint32 total);
|
||||
void RegisterMalloc(HeapBlockDesc *block);
|
||||
void RegisterFree(HeapBlockDesc *block);
|
||||
void *Malloc(uint32 size);
|
||||
void *Realloc(void *ptr, uint32 size);
|
||||
void Free(void *ptr);
|
||||
void FillInBlockData(HeapBlockDesc *block, HeapBlockDesc *end, uint32 size);
|
||||
uint32 CombineFreeBlocks(HeapBlockDesc *block);
|
||||
void *MoveMemory(void *ptr);
|
||||
HeapBlockDesc *WhereShouldMemoryMove(void *ptr);
|
||||
void *MoveHeapBlock(HeapBlockDesc *dst, HeapBlockDesc *src);
|
||||
void PopMemId(void);
|
||||
void PushMemId(int32 id);
|
||||
void RegisterMemPointer(void *ptr);
|
||||
void TidyHeap(void);
|
||||
uint32 GetMemoryUsed(int32 id);
|
||||
uint32 GetBlocksUsed(int32 id);
|
||||
int32 GetLargestFreeBlock(void) { return m_freeList.m_last.m_prev->m_size; }
|
||||
|
||||
void ParseHeap(void);
|
||||
|
||||
HeapBlockDesc *GetDescFromHeapPointer(void *block)
|
||||
{
|
||||
return (HeapBlockDesc*)((uintptr)block - sizeof(HeapBlockDesc));
|
||||
}
|
||||
uint32 GetSizeBetweenBlocks(HeapBlockDesc *first, HeapBlockDesc *second)
|
||||
{
|
||||
return (uintptr)second - (uintptr)first - sizeof(HeapBlockDesc);
|
||||
}
|
||||
void FreeBlock(HeapBlockDesc *block){
|
||||
for(int i = 0; i < NUM_FIXED_MEMBLOCKS; i++){
|
||||
if(m_fixedSize[i].m_size == block->m_size){
|
||||
m_fixedSize[i].Free(block);
|
||||
return;
|
||||
}
|
||||
}
|
||||
HeapBlockDesc *b = m_freeList.m_first.FindSmallestFreeBlock(block->m_size);
|
||||
block->InsertHeapFreeBlock(b->m_prev);
|
||||
}
|
||||
};
|
||||
|
||||
extern CMemoryHeap gMainHeap;
|
||||
130
src/rw/MemoryMgr.cpp
Normal file
130
src/rw/MemoryMgr.cpp
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
#include "common.h"
|
||||
#include "MemoryHeap.h"
|
||||
#include "MemoryMgr.h"
|
||||
|
||||
|
||||
uint8 *pMemoryTop;
|
||||
|
||||
void
|
||||
InitMemoryMgr(void)
|
||||
{
|
||||
#ifdef USE_CUSTOM_ALLOCATOR
|
||||
#ifdef GTA_PS2
|
||||
#error "finish this"
|
||||
#else
|
||||
// randomly allocate 128mb
|
||||
gMainHeap.Init(128*1024*1024);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
RwMemoryFunctions memFuncs = {
|
||||
MemoryMgrMalloc,
|
||||
MemoryMgrFree,
|
||||
MemoryMgrRealloc,
|
||||
MemoryMgrCalloc
|
||||
};
|
||||
|
||||
#ifdef USE_CUSTOM_ALLOCATOR
|
||||
// game seems to be using heap directly here, but this is nicer
|
||||
void *operator new(size_t sz) throw() { return MemoryMgrMalloc(sz); }
|
||||
void *operator new[](size_t sz) throw() { return MemoryMgrMalloc(sz); }
|
||||
void operator delete(void *ptr) throw() { MemoryMgrFree(ptr); }
|
||||
void operator delete[](void *ptr) throw() { MemoryMgrFree(ptr); }
|
||||
#endif
|
||||
|
||||
void*
|
||||
MemoryMgrMalloc(size_t size)
|
||||
{
|
||||
#ifdef USE_CUSTOM_ALLOCATOR
|
||||
void *mem = gMainHeap.Malloc(size);
|
||||
#else
|
||||
void *mem = malloc(size);
|
||||
#endif
|
||||
if((uint8*)mem + size > pMemoryTop)
|
||||
pMemoryTop = (uint8*)mem + size ;
|
||||
return mem;
|
||||
}
|
||||
|
||||
void*
|
||||
MemoryMgrRealloc(void *ptr, size_t size)
|
||||
{
|
||||
#ifdef USE_CUSTOM_ALLOCATOR
|
||||
void *mem = gMainHeap.Realloc(ptr, size);
|
||||
#else
|
||||
void *mem = realloc(ptr, size);
|
||||
#endif
|
||||
if((uint8*)mem + size > pMemoryTop)
|
||||
pMemoryTop = (uint8*)mem + size ;
|
||||
return mem;
|
||||
}
|
||||
|
||||
void*
|
||||
MemoryMgrCalloc(size_t num, size_t size)
|
||||
{
|
||||
#ifdef USE_CUSTOM_ALLOCATOR
|
||||
void *mem = gMainHeap.Malloc(num*size);
|
||||
#else
|
||||
void *mem = calloc(num, size);
|
||||
#endif
|
||||
if((uint8*)mem + size > pMemoryTop)
|
||||
pMemoryTop = (uint8*)mem + size ;
|
||||
#ifdef FIX_BUGS
|
||||
memset(mem, 0, num*size);
|
||||
#endif
|
||||
return mem;
|
||||
}
|
||||
|
||||
void
|
||||
MemoryMgrFree(void *ptr)
|
||||
{
|
||||
#ifdef USE_CUSTOM_ALLOCATOR
|
||||
#ifdef FIX_BUGS
|
||||
// i don't suppose this is handled by RW?
|
||||
if(ptr == nil) return;
|
||||
#endif
|
||||
gMainHeap.Free(ptr);
|
||||
#else
|
||||
free(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *
|
||||
RwMallocAlign(RwUInt32 size, RwUInt32 align)
|
||||
{
|
||||
#if defined (FIX_BUGS) || defined(FIX_BUGS_64)
|
||||
uintptr ptralign = align-1;
|
||||
void *mem = (void *)MemoryMgrMalloc(size + sizeof(uintptr) + ptralign);
|
||||
|
||||
ASSERT(mem != nil);
|
||||
|
||||
void *addr = (void *)((((uintptr)mem) + sizeof(uintptr) + ptralign) & ~ptralign);
|
||||
|
||||
ASSERT(addr != nil);
|
||||
#else
|
||||
void *mem = (void *)MemoryMgrMalloc(size + align);
|
||||
|
||||
ASSERT(mem != nil);
|
||||
|
||||
void *addr = (void *)((((uintptr)mem) + align) & ~(align - 1));
|
||||
|
||||
ASSERT(addr != nil);
|
||||
#endif
|
||||
|
||||
*(((void **)addr) - 1) = mem;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void
|
||||
RwFreeAlign(void *mem)
|
||||
{
|
||||
ASSERT(mem != nil);
|
||||
|
||||
void *addr = *(((void **)mem) - 1);
|
||||
|
||||
ASSERT(addr != nil);
|
||||
|
||||
MemoryMgrFree(addr);
|
||||
}
|
||||
12
src/rw/MemoryMgr.h
Normal file
12
src/rw/MemoryMgr.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
extern RwMemoryFunctions memFuncs;
|
||||
void InitMemoryMgr(void);
|
||||
|
||||
void *MemoryMgrMalloc(size_t size);
|
||||
void *MemoryMgrRealloc(void *ptr, size_t size);
|
||||
void *MemoryMgrCalloc(size_t num, size_t size);
|
||||
void MemoryMgrFree(void *ptr);
|
||||
|
||||
void *RwMallocAlign(RwUInt32 size, RwUInt32 align);
|
||||
void RwFreeAlign(void *mem);
|
||||
77
src/rw/NodeName.cpp
Normal file
77
src/rw/NodeName.cpp
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
#include "common.h"
|
||||
|
||||
#include "NodeName.h"
|
||||
|
||||
static int32 gPluginOffset;
|
||||
|
||||
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)
|
||||
{
|
||||
char *name = NODENAMEEXT(object); // can't be nil
|
||||
return name ? (RwInt32)rwstrlen(name) : 0;
|
||||
}
|
||||
|
||||
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/rw/NodeName.h
Normal file
4
src/rw/NodeName.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
bool NodeNamePluginAttach(void);
|
||||
char *GetFrameNodeName(RwFrame *frame);
|
||||
735
src/rw/RwHelper.cpp
Normal file
735
src/rw/RwHelper.cpp
Normal file
|
|
@ -0,0 +1,735 @@
|
|||
#define WITHD3D
|
||||
#include "common.h"
|
||||
#include <rpskin.h>
|
||||
|
||||
#include "RwHelper.h"
|
||||
#include "Timecycle.h"
|
||||
#include "skeleton.h"
|
||||
#include "Debug.h"
|
||||
#include "MBlur.h"
|
||||
#if !defined(FINAL) || defined(DEBUGMENU)
|
||||
#include "rtcharse.h"
|
||||
#endif
|
||||
#ifndef FINAL
|
||||
RtCharset *debugCharset;
|
||||
bool bDebugRenderGroups;
|
||||
#endif
|
||||
|
||||
#ifdef PS2_ALPHA_TEST
|
||||
bool gPS2alphaTest = true;
|
||||
#else
|
||||
bool gPS2alphaTest = false;
|
||||
#endif
|
||||
bool gBackfaceCulling = true;
|
||||
|
||||
#if !defined(FINAL) || defined(DEBUGMENU)
|
||||
static bool charsetOpen;
|
||||
void OpenCharsetSafe()
|
||||
{
|
||||
if(!charsetOpen)
|
||||
RtCharsetOpen();
|
||||
charsetOpen = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CreateDebugFont()
|
||||
{
|
||||
#ifndef FINAL
|
||||
RwRGBA color = { 255, 255, 128, 255 };
|
||||
RwRGBA colorbg = { 0, 0, 0, 0 };
|
||||
OpenCharsetSafe();
|
||||
debugCharset = RtCharsetCreate(&color, &colorbg);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DestroyDebugFont()
|
||||
{
|
||||
#ifndef FINAL
|
||||
RtCharsetDestroy(debugCharset);
|
||||
RtCharsetClose();
|
||||
charsetOpen = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ObrsPrintfString(const char *str, short x, short y)
|
||||
{
|
||||
#ifndef FINAL
|
||||
RtCharsetPrintBuffered(debugCharset, str, x*8, y*16, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FlushObrsPrintfs()
|
||||
{
|
||||
#ifndef FINAL
|
||||
RtCharsetBufferFlush();
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#ifdef LIBRW
|
||||
rw::SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);
|
||||
|
||||
rw::SetRenderState(rw::GSALPHATEST, gPS2alphaTest);
|
||||
#else
|
||||
// D3D stuff
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
|
||||
#endif
|
||||
SetAlphaRef(2);
|
||||
}
|
||||
|
||||
void
|
||||
SetAlphaRef(int ref)
|
||||
{
|
||||
#ifdef LIBRW
|
||||
rw::SetRenderState(rw::ALPHATESTREF, ref+1);
|
||||
#else
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAREF, ref);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SetCullMode(uint32 mode)
|
||||
{
|
||||
if(gBackfaceCulling)
|
||||
RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)mode);
|
||||
else
|
||||
RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
|
||||
}
|
||||
|
||||
#ifndef FINAL
|
||||
void
|
||||
PushRendergroup(const char *name)
|
||||
{
|
||||
if(!bDebugRenderGroups)
|
||||
return;
|
||||
#if defined(RW_OPENGL)
|
||||
if(GLAD_GL_KHR_debug)
|
||||
glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, name);
|
||||
#elif defined(RW_D3D9)
|
||||
static WCHAR tmp[256];
|
||||
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, tmp, sizeof(tmp));
|
||||
D3DPERF_BeginEvent(0xFFFFFFFF, tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
PopRendergroup(void)
|
||||
{
|
||||
if(!bDebugRenderGroups)
|
||||
return;
|
||||
#if defined(RW_OPENGL)
|
||||
if(GLAD_GL_KHR_debug)
|
||||
glPopDebugGroup();
|
||||
#elif defined(RW_D3D9)
|
||||
D3DPERF_EndEvent();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef PED_SKIN
|
||||
static RpAtomic*
|
||||
isSkinnedCb(RpAtomic *atomic, void *data)
|
||||
{
|
||||
RpAtomic **pAtomic = (RpAtomic**)data;
|
||||
if(*pAtomic)
|
||||
return nil; // already found one
|
||||
if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)))
|
||||
*pAtomic = atomic; // we could just return nil here directly...
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
IsClumpSkinned(RpClump *clump)
|
||||
{
|
||||
RpAtomic *atomic = nil;
|
||||
RpClumpForAllAtomics(clump, isSkinnedCb, &atomic);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
static RpAtomic*
|
||||
GetAnimHierarchyCallback(RpAtomic *atomic, void *data)
|
||||
{
|
||||
*(RpHAnimHierarchy**)data = RpSkinAtomicGetHAnimHierarchy(atomic);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RpHAnimHierarchy*
|
||||
GetAnimHierarchyFromSkinClump(RpClump *clump)
|
||||
{
|
||||
RpHAnimHierarchy *hier = nil;
|
||||
RpClumpForAllAtomics(clump, GetAnimHierarchyCallback, &hier);
|
||||
return hier;
|
||||
}
|
||||
|
||||
static RwFrame*
|
||||
GetAnimHierarchyFromClumpCB(RwFrame *frame, void *data)
|
||||
{
|
||||
RpHAnimHierarchy *hier = RpHAnimFrameGetHierarchy(frame);
|
||||
if(hier){
|
||||
*(RpHAnimHierarchy**)data = hier;
|
||||
return nil;
|
||||
}
|
||||
RwFrameForAllChildren(frame, GetAnimHierarchyFromClumpCB, data);
|
||||
return frame;
|
||||
}
|
||||
|
||||
RpHAnimHierarchy*
|
||||
GetAnimHierarchyFromClump(RpClump *clump)
|
||||
{
|
||||
RpHAnimHierarchy *hier = nil;
|
||||
RwFrameForAllChildren(RpClumpGetFrame(clump), GetAnimHierarchyFromClumpCB, &hier);
|
||||
return hier;
|
||||
}
|
||||
|
||||
RwFrame*
|
||||
GetHierarchyFromChildNodesCB(RwFrame *frame, void *data)
|
||||
{
|
||||
RpHAnimHierarchy **pHier = (RpHAnimHierarchy**)data;
|
||||
RpHAnimHierarchy *hier = RpHAnimFrameGetHierarchy(frame);
|
||||
if(hier == nil)
|
||||
RwFrameForAllChildren(frame, GetHierarchyFromChildNodesCB, &hier);
|
||||
*pHier = hier;
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
SkinGetBonePositionsToTable(RpClump *clump, RwV3d *boneTable)
|
||||
{
|
||||
int i, parent;
|
||||
RpAtomic *atomic;
|
||||
RpSkin *skin;
|
||||
RpHAnimHierarchy *hier;
|
||||
int numBones;
|
||||
RwMatrix m, invmat;
|
||||
int stack[32];
|
||||
int sp;
|
||||
|
||||
if(boneTable == nil)
|
||||
return;
|
||||
|
||||
// atomic = GetFirstAtomic(clump); // mobile, also VC
|
||||
atomic = IsClumpSkinned(clump); // xbox, seems safer
|
||||
assert(atomic);
|
||||
skin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic));
|
||||
assert(skin);
|
||||
hier = GetAnimHierarchyFromSkinClump(clump);
|
||||
assert(hier);
|
||||
boneTable[0].x = 0.0f;
|
||||
boneTable[0].y = 0.0f;
|
||||
boneTable[0].z = 0.0f;
|
||||
numBones = RpSkinGetNumBones(skin);
|
||||
parent = 0;
|
||||
sp = 0;
|
||||
#ifdef FIX_BUGS
|
||||
stack[0] = 0; // i think this is ok
|
||||
#endif
|
||||
for(i = 1; i < numBones; i++){
|
||||
RwMatrixCopy(&m, &RpSkinGetSkinToBoneMatrices(skin)[i]);
|
||||
RwMatrixInvert(&invmat, &m);
|
||||
const RwMatrix *x = RpSkinGetSkinToBoneMatrices(skin);
|
||||
RwV3dTransformPoints(&boneTable[i], &invmat.pos, 1, &x[parent]);
|
||||
if(HIERNODEINFO(hier)[i].flags & rpHANIMPUSHPARENTMATRIX)
|
||||
stack[++sp] = parent;
|
||||
if(HIERNODEINFO(hier)[i].flags & rpHANIMPOPPARENTMATRIX)
|
||||
parent = stack[sp--];
|
||||
else
|
||||
parent = i;
|
||||
|
||||
//assert(parent >= 0 && parent < numBones);
|
||||
}
|
||||
}
|
||||
|
||||
RpHAnimAnimation*
|
||||
HAnimAnimationCreateForHierarchy(RpHAnimHierarchy *hier)
|
||||
{
|
||||
int i;
|
||||
#if defined FIX_BUGS || defined LIBRW
|
||||
int numNodes = hier->numNodes*2; // you're supposed to have at least two KFs per node
|
||||
#else
|
||||
int numNodes = hier->numNodes;
|
||||
#endif
|
||||
RpHAnimAnimation *anim = RpHAnimAnimationCreate(rpHANIMSTDKEYFRAMETYPEID, numNodes, 0, 0.0f);
|
||||
if(anim == nil)
|
||||
return nil;
|
||||
RpHAnimStdKeyFrame *frame;
|
||||
for(i = 0; i < numNodes; i++){
|
||||
frame = (RpHAnimStdKeyFrame*)HANIMFRAME(anim, i); // games uses struct size here, not safe
|
||||
frame->q.real = 1.0f;
|
||||
frame->q.imag.x = frame->q.imag.y = frame->q.imag.z = 0.0f;
|
||||
frame->t.x = frame->t.y = frame->t.z = 0.0f;
|
||||
#if defined FIX_BUGS || defined LIBRW
|
||||
// times are subtracted and divided giving NaNs
|
||||
// so they can't both be 0
|
||||
frame->time = i/hier->numNodes;
|
||||
#else
|
||||
frame->time = 0.0f;
|
||||
#endif
|
||||
frame->prevFrame = nil;
|
||||
}
|
||||
return anim;
|
||||
}
|
||||
|
||||
void
|
||||
RenderSkeleton(RpHAnimHierarchy *hier)
|
||||
{
|
||||
int i;
|
||||
int sp;
|
||||
int stack[32];
|
||||
int par;
|
||||
CVector p1, p2;
|
||||
int numNodes = hier->numNodes;
|
||||
RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);
|
||||
p1 = mats[0].pos;
|
||||
|
||||
par = 0;
|
||||
sp = 0;
|
||||
stack[sp++] = par;
|
||||
for(i = 1; i < numNodes; i++){
|
||||
p1 = mats[par].pos;
|
||||
p2 = mats[i].pos;
|
||||
CDebug::AddLine(p1, p2, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
if(HIERNODEINFO(hier)[i].flags & rpHANIMPUSHPARENTMATRIX)
|
||||
stack[sp++] = par;
|
||||
par = i;
|
||||
if(HIERNODEINFO(hier)[i].flags & rpHANIMPOPPARENTMATRIX)
|
||||
par = stack[--sp];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
// BUG: game just changes camera raster's sizes, but this is a hack
|
||||
#if defined FIX_BUGS || defined LIBRW
|
||||
/*
|
||||
* Destroy rasters...
|
||||
*/
|
||||
|
||||
raster = RwCameraGetRaster(camera);
|
||||
if( raster )
|
||||
{
|
||||
RwRasterDestroy(raster);
|
||||
camera->frameBuffer = nil;
|
||||
}
|
||||
|
||||
zRaster = RwCameraGetZRaster(camera);
|
||||
if( zRaster )
|
||||
{
|
||||
RwRasterDestroy(zRaster);
|
||||
camera->zBuffer = nil;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
#else
|
||||
raster = RwCameraGetRaster(camera);
|
||||
zRaster = RwCameraGetZRaster(camera);
|
||||
|
||||
raster->width = zRaster->width = rect->w;
|
||||
raster->height = zRaster->height = rect->h;
|
||||
#endif
|
||||
#ifdef FIX_BUGS
|
||||
if(CMBlur::BlurOn){
|
||||
CMBlur::MotionBlurClose();
|
||||
CMBlur::MotionBlurOpen(camera);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
#ifdef LIBRW
|
||||
#include <rpmatfx.h>
|
||||
#include "VehicleModelInfo.h"
|
||||
|
||||
int32
|
||||
findPlatform(rw::Atomic *a)
|
||||
{
|
||||
rw::Geometry *g = a->geometry;
|
||||
if(g->instData)
|
||||
return g->instData->platform;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// in CVehicleModelInfo in VC
|
||||
static RpMaterial*
|
||||
GetMatFXEffectMaterialCB(RpMaterial *material, void *data)
|
||||
{
|
||||
if(RpMatFXMaterialGetEffects(material) == rpMATFXEFFECTNULL)
|
||||
return material;
|
||||
*(int*)data = RpMatFXMaterialGetEffects(material);
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Game doesn't read atomic extensions so we never get any other than the default pipe,
|
||||
// but we need it for uninstancing
|
||||
void
|
||||
attachPipe(rw::Atomic *atomic)
|
||||
{
|
||||
if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)))
|
||||
atomic->pipeline = rw::skinGlobals.pipelines[rw::platform];
|
||||
else{
|
||||
int fx = rpMATFXEFFECTNULL;
|
||||
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), GetMatFXEffectMaterialCB, &fx);
|
||||
if(fx != rpMATFXEFFECTNULL)
|
||||
RpMatFXAtomicEnableEffects(atomic);
|
||||
}
|
||||
}
|
||||
|
||||
// Attach pipes for the platform we have native data for so we can uninstance
|
||||
void
|
||||
switchPipes(rw::Atomic *a, int32 platform)
|
||||
{
|
||||
if(a->pipeline && a->pipeline->platform != platform){
|
||||
uint32 plgid = a->pipeline->pluginID;
|
||||
switch(plgid){
|
||||
// assume default pipe won't be attached explicitly
|
||||
case rw::ID_SKIN:
|
||||
a->pipeline = rw::skinGlobals.pipelines[platform];
|
||||
break;
|
||||
case rw::ID_MATFX:
|
||||
a->pipeline = rw::matFXGlobals.pipelines[platform];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
ConvertPlatformAtomic(RpAtomic *atomic, void *data)
|
||||
{
|
||||
int32 driver = rw::platform;
|
||||
int32 platform = findPlatform(atomic);
|
||||
if(platform != 0 && platform != driver){
|
||||
attachPipe(atomic); // kludge
|
||||
rw::ObjPipeline *origPipe = atomic->pipeline;
|
||||
rw::platform = platform;
|
||||
switchPipes(atomic, rw::platform);
|
||||
if(atomic->geometry->flags & rw::Geometry::NATIVE)
|
||||
atomic->uninstance();
|
||||
// no ADC in this game
|
||||
//rw::ps2::unconvertADC(atomic->geometry);
|
||||
rw::platform = driver;
|
||||
atomic->pipeline = origPipe;
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FIX_BUGS) && defined(GTA_PC)
|
||||
RwUInt32 saved_alphafunc, saved_alpharef;
|
||||
|
||||
void
|
||||
SetAlphaTest(RwUInt32 alpharef)
|
||||
{
|
||||
#ifdef LIBRW
|
||||
saved_alphafunc = rw::GetRenderState(rw::ALPHATESTFUNC);
|
||||
saved_alpharef = rw::GetRenderState(rw::ALPHATESTREF);
|
||||
|
||||
rw::SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);
|
||||
rw::SetRenderState(rw::ALPHATESTREF, 0);
|
||||
#else
|
||||
RwD3D8GetRenderState(D3DRS_ALPHAFUNC, &saved_alphafunc);
|
||||
RwD3D8GetRenderState(D3DRS_ALPHAREF, &saved_alpharef);
|
||||
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAREF, alpharef);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
RestoreAlphaTest()
|
||||
{
|
||||
#ifdef LIBRW
|
||||
rw::SetRenderState(rw::ALPHATESTFUNC, saved_alphafunc);
|
||||
rw::SetRenderState(rw::ALPHATESTREF, saved_alpharef);
|
||||
#else
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAFUNC, saved_alphafunc);
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAREF, saved_alpharef);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
63
src/rw/RwHelper.h
Normal file
63
src/rw/RwHelper.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
|
||||
extern bool bDebugRenderGroups;
|
||||
extern bool gPS2alphaTest;
|
||||
|
||||
void OpenCharsetSafe();
|
||||
void CreateDebugFont();
|
||||
void DestroyDebugFont();
|
||||
void ObrsPrintfString(const char *str, short x, short y);
|
||||
void FlushObrsPrintfs();
|
||||
void DefinedState(void);
|
||||
void SetAlphaRef(int ref);
|
||||
void SetCullMode(uint32 mode);
|
||||
RwFrame *GetFirstChild(RwFrame *frame);
|
||||
RwObject *GetFirstObject(RwFrame *frame);
|
||||
RpAtomic *GetFirstAtomic(RpClump *clump);
|
||||
RwTexture *GetFirstTexture(RwTexDictionary *txd);
|
||||
|
||||
#ifdef PED_SKIN
|
||||
RpAtomic *IsClumpSkinned(RpClump *clump);
|
||||
RpHAnimHierarchy *GetAnimHierarchyFromSkinClump(RpClump *clump); // get from atomic
|
||||
RpHAnimHierarchy *GetAnimHierarchyFromClump(RpClump *clump); // get from frame
|
||||
RwFrame *GetHierarchyFromChildNodesCB(RwFrame *frame, void *data);
|
||||
void SkinGetBonePositionsToTable(RpClump *clump, RwV3d *boneTable);
|
||||
RpHAnimAnimation *HAnimAnimationCreateForHierarchy(RpHAnimHierarchy *hier);
|
||||
RpAtomic *AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data);
|
||||
void RenderSkeleton(RpHAnimHierarchy *hier);
|
||||
#endif
|
||||
|
||||
RwTexDictionary *RwTexDictionaryGtaStreamRead(RwStream *stream);
|
||||
RwTexDictionary *RwTexDictionaryGtaStreamRead1(RwStream *stream);
|
||||
RwTexDictionary *RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict);
|
||||
void ReadVideoCardCapsFile(uint32&, uint32&, uint32&, uint32&);
|
||||
bool CheckVideoCardCaps(void);
|
||||
void WriteVideoCardCapsFile(void);
|
||||
void ConvertingTexturesScreen(uint32, uint32, const char*);
|
||||
void DealWithTxdWriteError(uint32, uint32, const char*);
|
||||
bool CreateTxdImageForVideoCard();
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
RpAtomic *ConvertPlatformAtomic(RpAtomic *atomic, void *data);
|
||||
|
||||
#if defined(FIX_BUGS) && defined (GTA_PC)
|
||||
void SetAlphaTest(RwUInt32 alpharef);
|
||||
void RestoreAlphaTest();
|
||||
#else
|
||||
#define SetAlphaTest(a) (0)
|
||||
#define RestoreAlphaTest() (0)
|
||||
#endif
|
||||
312
src/rw/RwMatFX.cpp
Normal file
312
src/rw/RwMatFX.cpp
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
#ifndef LIBRW
|
||||
|
||||
#define WITHD3D
|
||||
#include "common.h"
|
||||
#include "rpmatfx.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;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
extern int MatFXMaterialDataOffset;
|
||||
extern int MatFXAtomicDataOffset;
|
||||
|
||||
void _rpMatFXD3D8AtomicMatFXEnvRender(RxD3D8InstanceData* inst, int flags, int sel, RwTexture* texture, RwTexture* envMap);
|
||||
void _rpMatFXD3D8AtomicMatFXRenderBlack(RxD3D8InstanceData *inst);
|
||||
void _rpMatFXD3D8AtomicMatFXBumpMapRender(RxD3D8InstanceData *inst, int flags, RwTexture *texture, RwTexture *bumpMap, RwTexture *envMap);
|
||||
void _rpMatFXD3D8AtomicMatFXDualPassRender(RxD3D8InstanceData *inst, int flags, RwTexture *texture, RwTexture *dualTexture);
|
||||
}
|
||||
|
||||
|
||||
#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);
|
||||
RwD3D8SetPixelShader(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);
|
||||
}
|
||||
|
||||
void
|
||||
_rwD3D8EnableClippingIfNeeded(void *object, RwUInt8 type)
|
||||
{
|
||||
int clip;
|
||||
if (type == rpATOMIC)
|
||||
clip = !RwD3D8CameraIsSphereFullyInsideFrustum(RwCameraGetCurrentCameraMacro(), RpAtomicGetWorldBoundingSphere((RpAtomic *)object));
|
||||
else
|
||||
clip = !RwD3D8CameraIsBBoxFullyInsideFrustum(RwCameraGetCurrentCameraMacro(), &((RpWorldSector *)object)->tightBoundingBox);
|
||||
RwD3D8SetRenderState(D3DRS_CLIPPING, clip);
|
||||
}
|
||||
|
||||
void
|
||||
_rwD3D8AtomicMatFXRenderCallback(RwResEntry *repEntry, void *object, RwUInt8 type, RwUInt32 flags)
|
||||
{
|
||||
RwBool lighting;
|
||||
RwBool forceBlack;
|
||||
RxD3D8ResEntryHeader *header;
|
||||
RxD3D8InstanceData *inst;
|
||||
RwInt32 i;
|
||||
|
||||
if (flags & rpGEOMETRYPRELIT) {
|
||||
RwD3D8SetRenderState(D3DRS_COLORVERTEX, 1);
|
||||
RwD3D8SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
|
||||
} else {
|
||||
RwD3D8SetRenderState(D3DRS_COLORVERTEX, 0);
|
||||
RwD3D8SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
|
||||
}
|
||||
|
||||
_rwD3D8EnableClippingIfNeeded(object, type);
|
||||
|
||||
RwD3D8GetRenderState(D3DRS_LIGHTING, &lighting);
|
||||
if (lighting || flags & rpGEOMETRYPRELIT) {
|
||||
forceBlack = FALSE;
|
||||
} else {
|
||||
forceBlack = TRUE;
|
||||
RwD3D8SetTexture(nil, 0);
|
||||
RwD3D8SetRenderState(D3DRS_TEXTUREFACTOR, D3DCOLOR_RGBA(0, 0, 0, 255));
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
|
||||
}
|
||||
|
||||
header = (RxD3D8ResEntryHeader *)(repEntry + 1);
|
||||
inst = (RxD3D8InstanceData *)(header + 1);
|
||||
for (i = 0; i < header->numMeshes; i++) {
|
||||
if (forceBlack)
|
||||
_rpMatFXD3D8AtomicMatFXRenderBlack(inst);
|
||||
else {
|
||||
if (lighting)
|
||||
RwD3D8SetSurfaceProperties(&inst->material->color, &inst->material->surfaceProps, flags & rpGEOMETRYMODULATEMATERIALCOLOR);
|
||||
MatFX *matfx = *RWPLUGINOFFSET(MatFX *, inst->material, MatFXMaterialDataOffset);
|
||||
int effect = matfx ? matfx->effects : rpMATFXEFFECTNULL;
|
||||
switch (effect) {
|
||||
case rpMATFXEFFECTNULL:
|
||||
default:
|
||||
_rpMatFXD3D8AtomicMatFXDefaultRender(inst, flags, inst->material->texture);
|
||||
break;
|
||||
case rpMATFXEFFECTBUMPMAP:
|
||||
_rpMatFXD3D8AtomicMatFXBumpMapRender(inst, flags, inst->material->texture, matfx->fx[0].b.bumpedTex, nil);
|
||||
break;
|
||||
case rpMATFXEFFECTENVMAP:
|
||||
{
|
||||
// TODO: matfx switch in the settings
|
||||
//_rpMatFXD3D8AtomicMatFXEnvRender(inst, flags, 0, inst->material->texture, matfx->fx[0].e.envTex);
|
||||
_rpMatFXD3D8AtomicMatFXEnvRender_ps2(inst, flags, 0, inst->material->texture, matfx->fx[0].e.envTex);
|
||||
break;
|
||||
}
|
||||
case rpMATFXEFFECTBUMPENVMAP:
|
||||
_rpMatFXD3D8AtomicMatFXBumpMapRender(inst, flags, inst->material->texture, matfx->fx[0].b.bumpedTex, matfx->fx[1].e.envTex);
|
||||
break;
|
||||
case rpMATFXEFFECTDUAL:
|
||||
_rpMatFXD3D8AtomicMatFXDualPassRender(inst, flags, inst->material->texture, matfx->fx[0].d.dualTex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
inst++;
|
||||
}
|
||||
|
||||
if (forceBlack) {
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReplaceMatFxCallback()
|
||||
{
|
||||
RxD3D8AllInOneSetRenderCallBack(
|
||||
RxPipelineFindNodeByName(RpMatFXGetD3D8Pipeline(rpMATFXD3D8ATOMICPIPELINE), RxNodeDefinitionGetD3D8AtomicAllInOne()->name, nil, nil),
|
||||
_rwD3D8AtomicMatFXRenderCallback);
|
||||
|
||||
}
|
||||
#endif // PS2_MATFX
|
||||
|
||||
#endif // !LIBRW
|
||||
247
src/rw/RwPS2AlphaTest.cpp
Normal file
247
src/rw/RwPS2AlphaTest.cpp
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
#ifndef LIBRW
|
||||
|
||||
#define WITHD3D
|
||||
#include "common.h"
|
||||
#ifdef PS2_ALPHA_TEST
|
||||
#include "rwcore.h"
|
||||
|
||||
extern "C" {
|
||||
RwBool _rwD3D8RenderStateIsVertexAlphaEnable(void);
|
||||
RwBool _rwD3D8RenderStateVertexAlphaEnable(RwBool enable);
|
||||
RwRaster *_rwD3D8RWGetRasterStage(RwUInt32 stage);
|
||||
}
|
||||
|
||||
extern bool gPS2alphaTest;
|
||||
|
||||
void
|
||||
_rxD3D8DualPassRenderCallback(RwResEntry *repEntry, void *object, RwUInt8 type, RwUInt32 flags)
|
||||
{
|
||||
RxD3D8ResEntryHeader *resEntryHeader;
|
||||
RxD3D8InstanceData *instancedData;
|
||||
RwInt32 numMeshes;
|
||||
RwBool lighting;
|
||||
RwBool vertexAlphaBlend;
|
||||
RwBool forceBlack;
|
||||
RwUInt32 ditherEnable;
|
||||
RwUInt32 shadeMode;
|
||||
void *lastVertexBuffer;
|
||||
|
||||
/* Get lighting state */
|
||||
RwD3D8GetRenderState(D3DRS_LIGHTING, &lighting);
|
||||
|
||||
forceBlack = FALSE;
|
||||
|
||||
if (lighting) {
|
||||
if (flags & rxGEOMETRY_PRELIT) {
|
||||
/* Emmisive color from the vertex colors */
|
||||
RwD3D8SetRenderState(D3DRS_COLORVERTEX, TRUE);
|
||||
RwD3D8SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
|
||||
} else {
|
||||
/* Emmisive color from material, set to black in the submit node */
|
||||
RwD3D8SetRenderState(D3DRS_COLORVERTEX, FALSE);
|
||||
RwD3D8SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
|
||||
}
|
||||
} else {
|
||||
if ((flags & rxGEOMETRY_PRELIT) == 0) {
|
||||
forceBlack = TRUE;
|
||||
|
||||
RwD3D8GetRenderState(D3DRS_DITHERENABLE, &ditherEnable);
|
||||
RwD3D8GetRenderState(D3DRS_SHADEMODE, &shadeMode);
|
||||
|
||||
RwD3D8SetRenderState(D3DRS_TEXTUREFACTOR, 0xff000000);
|
||||
RwD3D8SetRenderState(D3DRS_DITHERENABLE, FALSE);
|
||||
RwD3D8SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable clipping */
|
||||
if (type == rpATOMIC) {
|
||||
RpAtomic *atomic;
|
||||
RwCamera *cam;
|
||||
|
||||
atomic = (RpAtomic *)object;
|
||||
|
||||
cam = RwCameraGetCurrentCamera();
|
||||
// RWASSERT(cam);
|
||||
|
||||
if (RwD3D8CameraIsSphereFullyInsideFrustum(cam, RpAtomicGetWorldBoundingSphere(atomic))) {
|
||||
RwD3D8SetRenderState(D3DRS_CLIPPING, FALSE);
|
||||
} else {
|
||||
RwD3D8SetRenderState(D3DRS_CLIPPING, TRUE);
|
||||
}
|
||||
} else {
|
||||
RpWorldSector *worldSector;
|
||||
RwCamera *cam;
|
||||
|
||||
worldSector = (RpWorldSector *)object;
|
||||
|
||||
cam = RwCameraGetCurrentCamera();
|
||||
// RWASSERT(cam);
|
||||
|
||||
if (RwD3D8CameraIsBBoxFullyInsideFrustum(cam, RpWorldSectorGetTightBBox(worldSector))) {
|
||||
RwD3D8SetRenderState(D3DRS_CLIPPING, FALSE);
|
||||
} else {
|
||||
RwD3D8SetRenderState(D3DRS_CLIPPING, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set texture to NULL if hasn't any texture flags */
|
||||
if ((flags & (rxGEOMETRY_TEXTURED | rpGEOMETRYTEXTURED2)) == 0) {
|
||||
RwD3D8SetTexture(NULL, 0);
|
||||
|
||||
if (forceBlack) {
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
|
||||
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get vertex alpha Blend state */
|
||||
vertexAlphaBlend = _rwD3D8RenderStateIsVertexAlphaEnable();
|
||||
|
||||
/* Set Last vertex buffer to force the call */
|
||||
lastVertexBuffer = (void *)0xffffffff;
|
||||
|
||||
/* Get the instanced data */
|
||||
resEntryHeader = (RxD3D8ResEntryHeader *)(repEntry + 1);
|
||||
instancedData = (RxD3D8InstanceData *)(resEntryHeader + 1);
|
||||
|
||||
/*
|
||||
* Data shared between meshes
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the Default Pixel shader
|
||||
*/
|
||||
RwD3D8SetPixelShader(0);
|
||||
|
||||
/*
|
||||
* Vertex shader
|
||||
*/
|
||||
RwD3D8SetVertexShader(instancedData->vertexShader);
|
||||
|
||||
/* Get the number of meshes */
|
||||
numMeshes = resEntryHeader->numMeshes;
|
||||
while (numMeshes--) {
|
||||
// RWASSERT(instancedData->material != NULL);
|
||||
|
||||
if ((flags & (rxGEOMETRY_TEXTURED | rpGEOMETRYTEXTURED2))) {
|
||||
RwD3D8SetTexture(instancedData->material->texture, 0);
|
||||
|
||||
if (forceBlack) {
|
||||
/* Only change the colorop, we need to use the texture alpha channel */
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
|
||||
}
|
||||
}
|
||||
|
||||
if (instancedData->vertexAlpha || (0xFF != instancedData->material->color.alpha)) {
|
||||
if (!vertexAlphaBlend) {
|
||||
vertexAlphaBlend = TRUE;
|
||||
|
||||
_rwD3D8RenderStateVertexAlphaEnable(TRUE);
|
||||
}
|
||||
} else {
|
||||
if (vertexAlphaBlend) {
|
||||
vertexAlphaBlend = FALSE;
|
||||
|
||||
_rwD3D8RenderStateVertexAlphaEnable(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (lighting) {
|
||||
if (instancedData->vertexAlpha) {
|
||||
RwD3D8SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
|
||||
} else {
|
||||
RwD3D8SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
|
||||
}
|
||||
|
||||
RwD3D8SetSurfaceProperties(&instancedData->material->color, &instancedData->material->surfaceProps, (flags & rxGEOMETRY_MODULATE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Render
|
||||
*/
|
||||
|
||||
/* Set the stream source */
|
||||
if (lastVertexBuffer != instancedData->vertexBuffer) {
|
||||
RwD3D8SetStreamSource(0, instancedData->vertexBuffer, instancedData->stride);
|
||||
|
||||
lastVertexBuffer = instancedData->vertexBuffer;
|
||||
}
|
||||
if (!gPS2alphaTest) {
|
||||
/* Set the Index buffer */
|
||||
if (instancedData->indexBuffer != NULL) {
|
||||
RwD3D8SetIndices(instancedData->indexBuffer, instancedData->baseIndex);
|
||||
|
||||
/* Draw the indexed primitive */
|
||||
RwD3D8DrawIndexedPrimitive((D3DPRIMITIVETYPE)instancedData->primType, 0, instancedData->numVertices, 0, instancedData->numIndices);
|
||||
} else {
|
||||
RwD3D8DrawPrimitive((D3DPRIMITIVETYPE)instancedData->primType, instancedData->baseIndex, instancedData->numVertices);
|
||||
}
|
||||
} else {
|
||||
RwD3D8SetIndices(instancedData->indexBuffer, instancedData->baseIndex);
|
||||
|
||||
int hasAlpha, alphafunc, alpharef, zwrite;
|
||||
RwD3D8GetRenderState(D3DRS_ALPHABLENDENABLE, &hasAlpha);
|
||||
RwD3D8GetRenderState(D3DRS_ZWRITEENABLE, &zwrite);
|
||||
if (hasAlpha && zwrite) {
|
||||
RwD3D8GetRenderState(D3DRS_ALPHAFUNC, &alphafunc);
|
||||
RwD3D8GetRenderState(D3DRS_ALPHAREF, &alpharef);
|
||||
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAREF, 128);
|
||||
|
||||
if (instancedData->indexBuffer)
|
||||
RwD3D8DrawIndexedPrimitive(instancedData->primType, 0, instancedData->numVertices, 0, instancedData->numIndices);
|
||||
else
|
||||
RwD3D8DrawPrimitive(instancedData->primType, instancedData->baseIndex, instancedData->numVertices);
|
||||
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS);
|
||||
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
|
||||
|
||||
if (instancedData->indexBuffer)
|
||||
RwD3D8DrawIndexedPrimitive(instancedData->primType, 0, instancedData->numVertices, 0, instancedData->numIndices);
|
||||
else
|
||||
RwD3D8DrawPrimitive(instancedData->primType, instancedData->baseIndex, instancedData->numVertices);
|
||||
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAFUNC, alphafunc);
|
||||
RwD3D8SetRenderState(D3DRS_ALPHAREF, alpharef);
|
||||
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);
|
||||
} else {
|
||||
if (instancedData->indexBuffer)
|
||||
RwD3D8DrawIndexedPrimitive(instancedData->primType, 0, instancedData->numVertices, 0, instancedData->numIndices);
|
||||
else
|
||||
RwD3D8DrawPrimitive(instancedData->primType, instancedData->baseIndex, instancedData->numVertices);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move onto the next instancedData */
|
||||
instancedData++;
|
||||
}
|
||||
|
||||
if (forceBlack) {
|
||||
RwD3D8SetRenderState(D3DRS_DITHERENABLE, ditherEnable);
|
||||
RwD3D8SetRenderState(D3DRS_SHADEMODE, shadeMode);
|
||||
|
||||
if (_rwD3D8RWGetRasterStage(0)) {
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
} else {
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
|
||||
RwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReplaceAtomicPipeCallback()
|
||||
{
|
||||
RxD3D8AllInOneSetRenderCallBack(RxPipelineFindNodeByName(RXPIPELINEGLOBAL(platformAtomicPipeline), RxNodeDefinitionGetD3D8AtomicAllInOne()->name, nil, nil),
|
||||
_rxD3D8DualPassRenderCallback);
|
||||
}
|
||||
|
||||
#endif // PS2_ALPHA_TEST
|
||||
|
||||
#endif // !LIBRW
|
||||
459
src/rw/TexRead.cpp
Normal file
459
src/rw/TexRead.cpp
Normal file
|
|
@ -0,0 +1,459 @@
|
|||
#pragma warning( push )
|
||||
#pragma warning( disable : 4005)
|
||||
#pragma warning( pop )
|
||||
#define FORCE_PC_SCALING
|
||||
#include "common.h"
|
||||
#ifdef ANISOTROPIC_FILTERING
|
||||
#include "rpanisot.h"
|
||||
#endif
|
||||
#include "crossplatform.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include "Timer.h"
|
||||
#ifdef GTA_PC
|
||||
#include "FileMgr.h"
|
||||
#include "Pad.h"
|
||||
#include "main.h"
|
||||
#include "Directory.h"
|
||||
#include "Streaming.h"
|
||||
#include "TxdStore.h"
|
||||
#include "CdStream.h"
|
||||
#include "Font.h"
|
||||
#include "Sprite2d.h"
|
||||
#include "Text.h"
|
||||
#include "RwHelper.h"
|
||||
#include "Frontend.h"
|
||||
#endif //GTA_PC
|
||||
|
||||
float texLoadTime;
|
||||
int32 texNumLoaded;
|
||||
|
||||
#ifdef LIBRW
|
||||
#define READNATIVE(stream, tex, size) rwNativeTextureHackRead(stream, tex, size)
|
||||
#else
|
||||
#define READNATIVE(stream, tex, size) RWSRCGLOBAL(stdFunc[rwSTANDARDNATIVETEXTUREREAD](stream, tex, size))
|
||||
#endif
|
||||
|
||||
RwTexture*
|
||||
RwTextureGtaStreamRead(RwStream *stream)
|
||||
{
|
||||
RwUInt32 size, version;
|
||||
RwTexture *tex;
|
||||
|
||||
if(!RwStreamFindChunk(stream, rwID_TEXTURENATIVE, &size, &version))
|
||||
return nil;
|
||||
|
||||
float preloadTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond();
|
||||
|
||||
if(!READNATIVE(stream, &tex, size))
|
||||
return nil;
|
||||
|
||||
if (gGameState == GS_INIT_PLAYING_GAME) {
|
||||
texLoadTime = (texNumLoaded * texLoadTime + (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond() - preloadTime) / (float)(texNumLoaded+1);
|
||||
texNumLoaded++;
|
||||
}
|
||||
|
||||
#ifdef ANISOTROPIC_FILTERING
|
||||
if(tex && RpAnisotGetMaxSupportedMaxAnisotropy() > 1) // BUG? this was RpAnisotTextureGetMaxAnisotropy, but that doesn't make much sense
|
||||
RpAnisotTextureSetMaxAnisotropy(tex, RpAnisotGetMaxSupportedMaxAnisotropy());
|
||||
#endif
|
||||
|
||||
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;
|
||||
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 = STREAMPOS(stream);
|
||||
|
||||
return texDict;
|
||||
}
|
||||
|
||||
RwTexDictionary*
|
||||
RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict)
|
||||
{
|
||||
RwTexture *tex;
|
||||
|
||||
RwStreamSkip(stream, streamPosition - STREAMPOS(stream));
|
||||
|
||||
while(numberTextures--){
|
||||
tex = RwTextureGtaStreamRead(stream);
|
||||
if(tex == nil){
|
||||
RwTexDictionaryForAllTextures(texDict, destroyTexture, nil);
|
||||
RwTexDictionaryDestroy(texDict);
|
||||
return nil;
|
||||
}
|
||||
RwTexDictionaryAddTexture(texDict, tex);
|
||||
}
|
||||
|
||||
return texDict;
|
||||
}
|
||||
|
||||
#ifdef GTA_PC
|
||||
|
||||
#ifdef LIBRW
|
||||
|
||||
#define CAPSVERSION 0
|
||||
|
||||
struct GPUcaps
|
||||
{
|
||||
uint32 version; // so we can force regeneration easily
|
||||
uint32 platform;
|
||||
uint32 subplatform;
|
||||
uint32 dxtSupport;
|
||||
};
|
||||
|
||||
static void
|
||||
GetGPUcaps(GPUcaps *caps)
|
||||
{
|
||||
caps->version = CAPSVERSION;
|
||||
caps->platform = rw::platform;
|
||||
caps->subplatform = 0;
|
||||
caps->dxtSupport = 0;
|
||||
// TODO: more later
|
||||
#ifdef RW_GL3
|
||||
caps->subplatform = rw::gl3::gl3Caps.gles;
|
||||
caps->dxtSupport = rw::gl3::gl3Caps.dxtSupported;
|
||||
#endif
|
||||
#ifdef RW_D3D9
|
||||
caps->dxtSupport = 1; // TODO, probably
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ReadVideoCardCapsFile(GPUcaps *caps)
|
||||
{
|
||||
memset(caps, 0, sizeof(GPUcaps));
|
||||
|
||||
int32 file = CFileMgr::OpenFile("DATA\\CAPS.DAT", "rb");
|
||||
if (file != 0) {
|
||||
CFileMgr::Read(file, (char*)&caps->version, 4);
|
||||
CFileMgr::Read(file, (char*)&caps->platform, 4);
|
||||
CFileMgr::Read(file, (char*)&caps->subplatform, 4);
|
||||
CFileMgr::Read(file, (char*)&caps->dxtSupport, 4);
|
||||
CFileMgr::CloseFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CheckVideoCardCaps(void)
|
||||
{
|
||||
GPUcaps caps, fcaps;
|
||||
GetGPUcaps(&caps);
|
||||
ReadVideoCardCapsFile(&fcaps);
|
||||
return caps.version != fcaps.version ||
|
||||
caps.platform != fcaps.platform ||
|
||||
caps.subplatform != fcaps.subplatform ||
|
||||
caps.dxtSupport != fcaps.dxtSupport;
|
||||
}
|
||||
|
||||
void
|
||||
WriteVideoCardCapsFile(void)
|
||||
{
|
||||
GPUcaps caps;
|
||||
GetGPUcaps(&caps);
|
||||
int32 file = CFileMgr::OpenFile("DATA\\CAPS.DAT", "wb");
|
||||
if (file != 0) {
|
||||
CFileMgr::Write(file, (char*)&caps.version, 4);
|
||||
CFileMgr::Write(file, (char*)&caps.platform, 4);
|
||||
CFileMgr::Write(file, (char*)&caps.subplatform, 4);
|
||||
CFileMgr::Write(file, (char*)&caps.dxtSupport, 4);
|
||||
CFileMgr::CloseFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
extern "C" RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags);
|
||||
void
|
||||
ReadVideoCardCapsFile(uint32 &cap32, uint32 &cap24, uint32 &cap16, uint32 &cap8)
|
||||
{
|
||||
cap32 = UINT32_MAX;
|
||||
cap24 = UINT32_MAX;
|
||||
cap16 = UINT32_MAX;
|
||||
cap8 = UINT32_MAX;
|
||||
|
||||
int32 file = CFileMgr::OpenFile("DATA\\CAPS.DAT", "rb");
|
||||
if (file != 0) {
|
||||
CFileMgr::Read(file, (char*)&cap32, 4);
|
||||
CFileMgr::Read(file, (char*)&cap24, 4);
|
||||
CFileMgr::Read(file, (char*)&cap16, 4);
|
||||
CFileMgr::Read(file, (char*)&cap8, 4);
|
||||
CFileMgr::CloseFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CheckVideoCardCaps(void)
|
||||
{
|
||||
uint32 cap32 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT8888);
|
||||
uint32 cap24 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT888);
|
||||
uint32 cap16 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT1555);
|
||||
uint32 cap8 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMATPAL8 | rwRASTERFORMAT8888);
|
||||
uint32 fcap32, fcap24, fcap16, fcap8;
|
||||
ReadVideoCardCapsFile(fcap32, fcap24, fcap16, fcap8);
|
||||
return cap32 != fcap32 || cap24 != fcap24 || cap16 != fcap16 || cap8 != fcap8;
|
||||
}
|
||||
|
||||
void
|
||||
WriteVideoCardCapsFile(void)
|
||||
{
|
||||
uint32 cap32 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT8888);
|
||||
uint32 cap24 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT888);
|
||||
uint32 cap16 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT1555);
|
||||
uint32 cap8 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMATPAL8 | rwRASTERFORMAT8888);
|
||||
int32 file = CFileMgr::OpenFile("DATA\\CAPS.DAT", "wb");
|
||||
if (file != 0) {
|
||||
CFileMgr::Write(file, (char*)&cap32, 4);
|
||||
CFileMgr::Write(file, (char*)&cap24, 4);
|
||||
CFileMgr::Write(file, (char*)&cap16, 4);
|
||||
CFileMgr::Write(file, (char*)&cap8, 4);
|
||||
CFileMgr::CloseFile(file);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ConvertingTexturesScreen(uint32 num, uint32 count, const char *text)
|
||||
{
|
||||
HandleExit();
|
||||
|
||||
CSprite2d *splash = LoadSplash(nil);
|
||||
if (!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255))
|
||||
return;
|
||||
|
||||
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));
|
||||
|
||||
CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), SCREEN_SCALE_FROM_RIGHT(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(64, 64, 64, 255));
|
||||
CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), (SCREEN_SCALE_FROM_RIGHT(200.0f) - SCREEN_SCALE_X(200.0f)) * ((float)num / (float)count) + SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(255, 217, 106, 255));
|
||||
CSprite2d::DrawRect(CRect(SCREEN_SCALE_X(120.0f), SCREEN_SCALE_Y(150.0f), SCREEN_SCALE_FROM_RIGHT(120.0f), SCREEN_HEIGHT - SCREEN_SCALE_Y(220.0f)), CRGBA(50, 50, 50, 210));
|
||||
|
||||
CFont::SetBackgroundOff();
|
||||
CFont::SetPropOn();
|
||||
CFont::SetScale(SCREEN_SCALE_X(0.45f), SCREEN_SCALE_Y(0.7f));
|
||||
CFont::SetCentreOff();
|
||||
CFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(170.0f));
|
||||
CFont::SetJustifyOff();
|
||||
CFont::SetColor(CRGBA(255, 217, 106, 255));
|
||||
CFont::SetBackGroundOnlyTextOff();
|
||||
CFont::SetFontStyle(FONT_BANK);
|
||||
CFont::PrintString(SCREEN_SCALE_X(170.0f), SCREEN_SCALE_Y(160.0f), TheText.Get(text));
|
||||
CFont::DrawFonts();
|
||||
DoRWStuffEndOfFrame();
|
||||
}
|
||||
|
||||
void
|
||||
DealWithTxdWriteError(uint32 num, uint32 count, const char *text)
|
||||
{
|
||||
while (!RsGlobal.quit) {
|
||||
ConvertingTexturesScreen(num, count, text);
|
||||
CPad::UpdatePads();
|
||||
if (CPad::GetPad(0)->GetEscapeJustDown())
|
||||
break;
|
||||
}
|
||||
RsGlobal.quit = false;
|
||||
LoadingScreen(nil, nil, nil);
|
||||
RsGlobal.quit = true;
|
||||
}
|
||||
|
||||
#ifdef LIBRW
|
||||
#define STREAMTELL(str) str->tell()
|
||||
#else
|
||||
#define STREAMTELL(str) filesys->rwftell((str)->Type.file.fpFile)
|
||||
#endif
|
||||
|
||||
bool
|
||||
CreateTxdImageForVideoCard()
|
||||
{
|
||||
uint8 *buf = new uint8[CDSTREAM_SECTOR_SIZE];
|
||||
CDirectory *pDir = new CDirectory(TXDSTORESIZE);
|
||||
CDirectory::DirectoryInfo dirInfo;
|
||||
|
||||
CStreaming::FlushRequestList();
|
||||
|
||||
#ifndef LIBRW
|
||||
RwFileFunctions *filesys = RwOsGetFileInterface();
|
||||
#endif
|
||||
|
||||
RwStream *img = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, "models\\txd.img");
|
||||
if (img == nil) {
|
||||
// original code does otherwise and it leaks
|
||||
delete []buf;
|
||||
delete pDir;
|
||||
|
||||
if (_dwOperatingSystemVersion == OS_WINNT || _dwOperatingSystemVersion == OS_WIN2000 || _dwOperatingSystemVersion == OS_WINXP)
|
||||
DealWithTxdWriteError(0, TXDSTORESIZE, "CVT_CRT");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef RW_GL3
|
||||
// so we can read back DXT with GLES
|
||||
// only works for textures that are not yet loaded
|
||||
// so let's hope that is the case for all
|
||||
rw::gl3::needToReadBackTextures = true;
|
||||
#endif
|
||||
|
||||
#ifdef DISABLE_VSYNC_ON_TEXTURE_CONVERSION
|
||||
// let's disable vsync and frame limiter to speed up texture conversion
|
||||
// (actually we probably don't need to disable frame limiter in here, but let's do it just in case =P)
|
||||
int8 vsyncState = CMenuManager::m_PrefsVsync;
|
||||
int8 frameLimiterState = CMenuManager::m_PrefsFrameLimiter;
|
||||
CMenuManager::m_PrefsVsync = 0;
|
||||
CMenuManager::m_PrefsFrameLimiter = 0;
|
||||
#endif
|
||||
|
||||
int32 i;
|
||||
for (i = 0; i < TXDSTORESIZE; i++) {
|
||||
ConvertingTexturesScreen(i, TXDSTORESIZE, "CVT_MSG");
|
||||
|
||||
if (CTxdStore::GetSlot(i) != nil && CStreaming::IsObjectInCdImage(i + STREAM_OFFSET_TXD)) {
|
||||
#ifdef FIX_BUGS
|
||||
if(strcmp(CTxdStore::GetTxdName(i), "generic") == 0)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
CStreaming::RequestTxd(i, STREAMFLAGS_KEEP_IN_MEMORY);
|
||||
CStreaming::RequestModelStream(0);
|
||||
CStreaming::FlushChannels();
|
||||
|
||||
char filename[64];
|
||||
sprintf(filename, "%s.txd", CTxdStore::GetTxdName(i));
|
||||
|
||||
if (CTxdStore::GetSlot(i)->texDict) {
|
||||
|
||||
int32 pos = STREAMTELL(img);
|
||||
|
||||
if (RwTexDictionaryStreamWrite(CTxdStore::GetSlot(i)->texDict, img) == nil) {
|
||||
DealWithTxdWriteError(i, TXDSTORESIZE, "CVT_ERR");
|
||||
RwStreamClose(img, nil);
|
||||
delete []buf;
|
||||
delete pDir;
|
||||
CStreaming::RemoveTxd(i);
|
||||
#ifdef RW_GL3
|
||||
rw::gl3::needToReadBackTextures = false;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 size = STREAMTELL(img) - pos;
|
||||
int32 num = size % CDSTREAM_SECTOR_SIZE;
|
||||
|
||||
size /= CDSTREAM_SECTOR_SIZE;
|
||||
if (num != 0) {
|
||||
size++;
|
||||
num = CDSTREAM_SECTOR_SIZE - num;
|
||||
RwStreamWrite(img, buf, num);
|
||||
}
|
||||
|
||||
dirInfo.offset = pos / CDSTREAM_SECTOR_SIZE;
|
||||
dirInfo.size = size;
|
||||
strncpy(dirInfo.name, filename, sizeof(dirInfo.name));
|
||||
pDir->AddItem(dirInfo);
|
||||
CStreaming::RemoveTxd(i);
|
||||
}
|
||||
CStreaming::FlushRequestList();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DISABLE_VSYNC_ON_TEXTURE_CONVERSION
|
||||
// restore vsync and frame limiter states
|
||||
CMenuManager::m_PrefsVsync = vsyncState;
|
||||
CMenuManager::m_PrefsFrameLimiter = frameLimiterState;
|
||||
#endif
|
||||
|
||||
RwStreamClose(img, nil);
|
||||
delete []buf;
|
||||
|
||||
#ifdef RW_GL3
|
||||
rw::gl3::needToReadBackTextures = false;
|
||||
#endif
|
||||
|
||||
if (!pDir->WriteDirFile("models\\txd.dir")) {
|
||||
DealWithTxdWriteError(i, TXDSTORESIZE, "CVT_ERR");
|
||||
delete pDir;
|
||||
return false;
|
||||
}
|
||||
|
||||
delete pDir;
|
||||
|
||||
WriteVideoCardCapsFile();
|
||||
return true;
|
||||
}
|
||||
#endif // GTA_PC
|
||||
221
src/rw/TexturePools.cpp
Normal file
221
src/rw/TexturePools.cpp
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
#ifndef LIBRW
|
||||
|
||||
#include <d3d8.h>
|
||||
#define WITHD3D
|
||||
#include "common.h"
|
||||
#include "TexturePools.h"
|
||||
|
||||
// TODO: this needs to be integrated into RW
|
||||
|
||||
extern "C" LPDIRECT3DDEVICE8 _RwD3DDevice;
|
||||
|
||||
CTexturePool aTexturePools[12];
|
||||
CPaletteList PaletteList;
|
||||
int numTexturePools;
|
||||
int MaxPaletteIndex;
|
||||
bool bUsePaletteIndex = true;
|
||||
|
||||
|
||||
void
|
||||
CTexturePool::Create(D3DFORMAT _Format, int _size, uint32 mipmapLevels, int32 numTextures)
|
||||
{
|
||||
Format = _Format;
|
||||
size = _size;
|
||||
levels = mipmapLevels;
|
||||
pTextures = new IDirect3DTexture8 *[numTextures];
|
||||
texturesMax = numTextures;
|
||||
texturesNum = 0;
|
||||
texturesUsed = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CTexturePool::Release()
|
||||
{
|
||||
int i = 0;
|
||||
while (i < texturesNum) {
|
||||
pTextures[i]->Release();
|
||||
i++;
|
||||
}
|
||||
|
||||
delete[] pTextures;
|
||||
|
||||
pTextures = nil;
|
||||
texturesNum = 0;
|
||||
texturesUsed = 0;
|
||||
}
|
||||
|
||||
IDirect3DTexture8 *
|
||||
CTexturePool::FindTexture()
|
||||
{
|
||||
if (texturesNum == 0)
|
||||
return nil;
|
||||
texturesUsed--;
|
||||
return pTextures[--texturesNum];
|
||||
}
|
||||
|
||||
bool
|
||||
CTexturePool::AddTexture(IDirect3DTexture8 *texture)
|
||||
{
|
||||
++texturesUsed;
|
||||
if (texturesNum >= texturesMax)
|
||||
return false;
|
||||
pTextures[texturesNum] = texture;
|
||||
++texturesNum;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CTexturePool::Resize(int numTextures)
|
||||
{
|
||||
if (numTextures == texturesMax)
|
||||
return;
|
||||
|
||||
IDirect3DTexture8 **newTextures = new IDirect3DTexture8 *[numTextures];
|
||||
|
||||
for (int i = 0; i < texturesNum && i < numTextures; i++)
|
||||
newTextures[i] = pTextures[i];
|
||||
|
||||
if (numTextures < texturesNum) {
|
||||
for (int i = numTextures; i < texturesNum; i++)
|
||||
pTextures[i]->Release();
|
||||
}
|
||||
delete[] pTextures;
|
||||
pTextures = newTextures;
|
||||
texturesMax = numTextures;
|
||||
}
|
||||
|
||||
void
|
||||
CPaletteList::Alloc(int max)
|
||||
{
|
||||
Data = new int[max];
|
||||
Max = max;
|
||||
Num = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CPaletteList::Free()
|
||||
{
|
||||
delete[] Data;
|
||||
Data = nil;
|
||||
Num = 0;
|
||||
}
|
||||
|
||||
int
|
||||
CPaletteList::Find()
|
||||
{
|
||||
if (Num == 0)
|
||||
return -1;
|
||||
return Data[--Num];
|
||||
}
|
||||
|
||||
void
|
||||
CPaletteList::Add(int item)
|
||||
{
|
||||
if (Num < Max)
|
||||
Data[Num++] = item;
|
||||
else {
|
||||
Resize(2 * Max);
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPaletteList::Resize(int max)
|
||||
{
|
||||
if (max == Max)
|
||||
return;
|
||||
|
||||
int *newData = new int[4 * max];
|
||||
for (int i = 0; i < Num && i < max; i++)
|
||||
newData[i] = Data[i];
|
||||
delete[] Data;
|
||||
Data = newData;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CreateTexture(int width, int height, int levels, D3DFORMAT Format, IDirect3DTexture8 **texture)
|
||||
{
|
||||
if (width == height) {
|
||||
for (int i = 0; i < numTexturePools; i++) {
|
||||
if (width != aTexturePools[i].GetSize() && levels == aTexturePools[i].levels && Format == aTexturePools[i].Format)
|
||||
*texture = aTexturePools[i].FindTexture();
|
||||
}
|
||||
}
|
||||
if (*texture)
|
||||
return D3D_OK;
|
||||
else
|
||||
return _RwD3DDevice->CreateTexture(width, height, levels, 0, Format, D3DPOOL_MANAGED, texture);
|
||||
}
|
||||
|
||||
void
|
||||
ReleaseTexture(IDirect3DTexture8 *texture)
|
||||
{
|
||||
int levels = 1;
|
||||
if (texture->GetLevelCount() > 1)
|
||||
levels = 0;
|
||||
|
||||
D3DSURFACE_DESC SURFACE_DESC;
|
||||
|
||||
texture->GetLevelDesc(0, &SURFACE_DESC);
|
||||
|
||||
if (SURFACE_DESC.Width == SURFACE_DESC.Height) {
|
||||
for (int i = 0; i < numTexturePools; i++) {
|
||||
if (SURFACE_DESC.Width == aTexturePools[i].GetSize() && SURFACE_DESC.Format == aTexturePools[i].Format && levels == aTexturePools[i].levels) {
|
||||
if (!aTexturePools[i].AddTexture(texture)) {
|
||||
if (aTexturePools[i].texturesUsed > 3 * aTexturePools[i].texturesMax / 2) {
|
||||
aTexturePools[i].Resize(2 * aTexturePools[i].texturesMax);
|
||||
aTexturePools[i].texturesUsed--;
|
||||
aTexturePools[i].AddTexture(texture);
|
||||
} else {
|
||||
texture->Release();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numTexturePools < 12 && bUsePaletteIndex && levels != 0 && SURFACE_DESC.Width == SURFACE_DESC.Height &&
|
||||
(SURFACE_DESC.Width == 64 || SURFACE_DESC.Width == 128 || SURFACE_DESC.Width == 256)) {
|
||||
aTexturePools[numTexturePools].Create(SURFACE_DESC.Format, SURFACE_DESC.Width, 1, 16);
|
||||
aTexturePools[numTexturePools].AddTexture(texture);
|
||||
numTexturePools++;
|
||||
} else
|
||||
texture->Release();
|
||||
}
|
||||
|
||||
int
|
||||
FindAvailablePaletteIndex()
|
||||
{
|
||||
int index = PaletteList.Find();
|
||||
if (index == -1)
|
||||
index = MaxPaletteIndex++;
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
AddAvailablePaletteIndex(int index)
|
||||
{
|
||||
if (bUsePaletteIndex)
|
||||
PaletteList.Add(index);
|
||||
}
|
||||
|
||||
void
|
||||
_TexturePoolsInitialise()
|
||||
{
|
||||
PaletteList.Alloc(100);
|
||||
MaxPaletteIndex = 0;
|
||||
}
|
||||
|
||||
void
|
||||
_TexturePoolsShutdown()
|
||||
{
|
||||
for (int i = 0; i < numTexturePools; i++)
|
||||
aTexturePools[i].Release();
|
||||
|
||||
numTexturePools = 0;
|
||||
bUsePaletteIndex = false;
|
||||
PaletteList.Free();
|
||||
}
|
||||
|
||||
#endif // !LIBRW
|
||||
42
src/rw/TexturePools.h
Normal file
42
src/rw/TexturePools.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
class CTexturePool
|
||||
{
|
||||
public:
|
||||
D3DFORMAT Format;
|
||||
int size;
|
||||
uint32 levels;
|
||||
int32 texturesMax;
|
||||
int32 texturesUsed;
|
||||
int32 texturesNum;
|
||||
IDirect3DTexture8 **pTextures;
|
||||
|
||||
public:
|
||||
CTexturePool() {}
|
||||
void Create(D3DFORMAT _Format, int size, uint32 mipmapLevels, int32 numTextures);
|
||||
void Release();
|
||||
IDirect3DTexture8 *FindTexture();
|
||||
bool AddTexture(IDirect3DTexture8 *texture);
|
||||
void Resize(int numTextures);
|
||||
#ifdef FIX_BUGS
|
||||
int GetSize() { return size; }
|
||||
#else
|
||||
float GetSize() { return size; }
|
||||
#endif
|
||||
};
|
||||
|
||||
class CPaletteList
|
||||
{
|
||||
int Max;
|
||||
int Num;
|
||||
int *Data;
|
||||
public:
|
||||
void Alloc(int max);
|
||||
void Free();
|
||||
int Find();
|
||||
void Add(int item);
|
||||
void Resize(int max);
|
||||
};
|
||||
|
||||
void _TexturePoolsInitialise();
|
||||
void _TexturePoolsShutdown();
|
||||
183
src/rw/TxdStore.cpp
Normal file
183
src/rw/TxdStore.cpp
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
#include "common.h"
|
||||
|
||||
#include "templates.h"
|
||||
#include "General.h"
|
||||
#include "Streaming.h"
|
||||
#include "RwHelper.h"
|
||||
#include "TxdStore.h"
|
||||
|
||||
CPool<TxdDef,TxdDef> *CTxdStore::ms_pTxdPool;
|
||||
RwTexDictionary *CTxdStore::ms_pStoredTxd;
|
||||
|
||||
void
|
||||
CTxdStore::Initialise(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)
|
||||
{
|
||||
int size = ms_pTxdPool->GetSize();
|
||||
for(int i = 0; i < size; i++){
|
||||
TxdDef *def = GetSlot(i);
|
||||
if(def && !CGeneral::faststricmp(def->name, name))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char*
|
||||
CTxdStore::GetTxdName(int slot)
|
||||
{
|
||||
return GetSlot(slot)->name;
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::PushCurrentTxd(void)
|
||||
{
|
||||
ms_pStoredTxd = RwTexDictionaryGetCurrent();
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::PopCurrentTxd(void)
|
||||
{
|
||||
RwTexDictionarySetCurrent(ms_pStoredTxd);
|
||||
ms_pStoredTxd = nil;
|
||||
}
|
||||
|
||||
void
|
||||
CTxdStore::SetCurrentTxd(int slot)
|
||||
{
|
||||
RwTexDictionarySetCurrent(GetSlot(slot)->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::RemoveTxd(slot);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
44
src/rw/TxdStore.h
Normal file
44
src/rw/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 Initialise(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);
|
||||
};
|
||||
1059
src/rw/VisibilityPlugins.cpp
Normal file
1059
src/rw/VisibilityPlugins.cpp
Normal file
File diff suppressed because it is too large
Load diff
141
src/rw/VisibilityPlugins.h
Normal file
141
src/rw/VisibilityPlugins.h
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#pragma once
|
||||
|
||||
#include "templates.h"
|
||||
|
||||
class CEntity;
|
||||
class CSimpleModelInfo;
|
||||
class CClumpModelInfo;
|
||||
|
||||
typedef bool (*ClumpVisibilityCB)(RpClump*);
|
||||
|
||||
class CVisibilityPlugins
|
||||
{
|
||||
public:
|
||||
struct AlphaObjectInfo
|
||||
{
|
||||
union {
|
||||
CEntity *entity;
|
||||
RpAtomic *atomic;
|
||||
};
|
||||
float sort;
|
||||
};
|
||||
|
||||
static CLinkList<AlphaObjectInfo> m_alphaList;
|
||||
static CLinkList<AlphaObjectInfo> m_alphaEntityList;
|
||||
#ifdef NEW_RENDERER
|
||||
static CLinkList<AlphaObjectInfo> m_alphaBuildingList;
|
||||
#endif
|
||||
static RwCamera *ms_pCamera;
|
||||
static RwV3d *ms_pCameraPosn;
|
||||
static float ms_cullCompsDist;
|
||||
static float ms_vehicleLod0Dist;
|
||||
static float ms_vehicleLod1Dist;
|
||||
static float ms_vehicleFadeDist;
|
||||
static float ms_bigVehicleLod0Dist;
|
||||
static float ms_bigVehicleLod1Dist;
|
||||
static float ms_pedLod0Dist;
|
||||
static float ms_pedLod1Dist;
|
||||
static float ms_pedFadeDist;
|
||||
|
||||
static void Initialise(void);
|
||||
static void Shutdown(void);
|
||||
static void InitAlphaEntityList(void);
|
||||
static bool InsertEntityIntoSortedList(CEntity *e, float dist);
|
||||
static void InitAlphaAtomicList(void);
|
||||
static bool InsertAtomicIntoSortedList(RpAtomic *a, float dist);
|
||||
|
||||
static void SetRenderWareCamera(RwCamera *camera);
|
||||
|
||||
static RpAtomic *RenderWheelAtomicCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderObjNormalAtomic(RpAtomic *atomic);
|
||||
static RpAtomic *RenderAlphaAtomic(RpAtomic *atomic, int alpha);
|
||||
static RpAtomic *RenderFadingAtomic(RpAtomic *atm, float dist);
|
||||
|
||||
static RpAtomic *RenderVehicleHiDetailCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleHiDetailAlphaCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleHiDetailCB_Boat(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleReallyLowDetailCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic);
|
||||
static RpAtomic *RenderTrainHiDetailCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderTrainHiDetailAlphaCB(RpAtomic *atomic);
|
||||
|
||||
static RpAtomic *RenderPlayerCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderPedLowDetailCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderPedHiDetailCB(RpAtomic *atomic);
|
||||
static RpAtomic *RenderPedCB(RpAtomic *atomic); // for skinned models with only one clump
|
||||
|
||||
static void RenderAlphaAtomics(void);
|
||||
static void RenderFadingEntities(void);
|
||||
|
||||
// All actually unused
|
||||
static bool DefaultVisibilityCB(RpClump *clump);
|
||||
static bool FrustumSphereCB(RpClump *clump);
|
||||
static bool MloVisibilityCB(RpClump *clump);
|
||||
static bool VehicleVisibilityCB(RpClump *clump);
|
||||
static bool VehicleVisibilityCB_BigVehicle(RpClump *clump);
|
||||
|
||||
static float GetDistanceSquaredFromCamera(RwFrame *frame);
|
||||
static float GetDotProductWithCameraVector(RwMatrix *atomicMat, RwMatrix *clumpMat, uint32 flags);
|
||||
|
||||
//
|
||||
// RW Plugins
|
||||
//
|
||||
|
||||
union AtomicExt
|
||||
{
|
||||
CSimpleModelInfo *modelInfo; // used by SimpleModelInfo
|
||||
int flags; // used by ClumpModelInfo
|
||||
};
|
||||
static void SetAtomicModelInfo(RpAtomic*, CSimpleModelInfo*);
|
||||
static CSimpleModelInfo *GetAtomicModelInfo(RpAtomic *atomic);
|
||||
static void SetAtomicFlag(RpAtomic*, int);
|
||||
static void ClearAtomicFlag(RpAtomic*, int);
|
||||
static void SetAtomicId(RpAtomic *atomic, int);
|
||||
static int GetAtomicId(RpAtomic *atomic);
|
||||
static void SetAtomicRenderCallback(RpAtomic*, RpAtomicCallBackRender);
|
||||
|
||||
static void *AtomicConstructor(void *object, int32 offset, int32 len);
|
||||
static void *AtomicDestructor(void *object, int32 offset, int32 len);
|
||||
static void *AtomicCopyConstructor(void *dst, const void *src,
|
||||
int32 offset, int32 len);
|
||||
static int32 ms_atomicPluginOffset;
|
||||
|
||||
struct FrameExt
|
||||
{
|
||||
// BUG: this is abused to hold a pointer by SetClumpModelInfo
|
||||
intptr id;
|
||||
};
|
||||
static void SetFrameHierarchyId(RwFrame *frame, intptr id);
|
||||
static intptr GetFrameHierarchyId(RwFrame *frame);
|
||||
|
||||
static void *FrameConstructor(void *object, int32 offset, int32 len);
|
||||
static void *FrameDestructor(void *object, int32 offset, int32 len);
|
||||
static void *FrameCopyConstructor(void *dst, const void *src,
|
||||
int32 offset, int32 len);
|
||||
static int32 ms_framePluginOffset;
|
||||
|
||||
struct ClumpExt
|
||||
{
|
||||
ClumpVisibilityCB visibilityCB;
|
||||
int alpha;
|
||||
};
|
||||
static void SetClumpModelInfo(RpClump*, CClumpModelInfo*);
|
||||
static CClumpModelInfo *GetClumpModelInfo(RpClump*);
|
||||
static void SetClumpAlpha(RpClump*, int);
|
||||
static int GetClumpAlpha(RpClump*);
|
||||
static bool IsClumpVisible(RpClump*);
|
||||
|
||||
static void *ClumpConstructor(void *object, int32 offset, int32 len);
|
||||
static void *ClumpDestructor(void *object, int32 offset, int32 len);
|
||||
static void *ClumpCopyConstructor(void *dst, const void *src,
|
||||
int32 offset, int32 len);
|
||||
static int32 ms_clumpPluginOffset;
|
||||
|
||||
static bool PluginAttach(void);
|
||||
};
|
||||
|
||||
RpMaterial *SetAlphaCB(RpMaterial *material, void *data);
|
||||
Loading…
Add table
Add a link
Reference in a new issue