mirror of
https://github.com/halpz/re3.git
synced 2025-07-26 00:42:45 +00:00
Merge branch 'master' of https://github.com/GTAmodding/re3
This commit is contained in:
@ -3,6 +3,7 @@
|
||||
#include <rpworld.h>
|
||||
|
||||
#include "Lights.h"
|
||||
#include "Timer.h"
|
||||
#include "Timecycle.h"
|
||||
#include "Coronas.h"
|
||||
#include "Weather.h"
|
||||
@ -248,6 +249,46 @@ SetAmbientAndDirectionalColours(float f)
|
||||
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)
|
||||
{
|
||||
|
@ -14,6 +14,8 @@ 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);
|
||||
|
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
|
225
src/rw/MemoryHeap.h
Normal file
225
src/rw/MemoryHeap.h
Normal file
@ -0,0 +1,225 @@
|
||||
#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,
|
||||
// IDs from LCS:
|
||||
/*
|
||||
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"
|
||||
MEMID_STREAM_LODS = 8, // "Streamed LODs"
|
||||
MEMID_STREAM_TEXUTRES = 9, // "Streamed Textures"
|
||||
MEMID_STREAM_COLLISION = 10, // "Streamed Collision"
|
||||
MEMID_STREAM_ANIMATION = 11, // "Streamed Animation"
|
||||
MEMID_TEXTURES = 12, // "Textures"
|
||||
MEMID_COLLISION = 13, // "Collision"
|
||||
MEMID_PRE_ALLOC = 14, // "PreAlloc"
|
||||
MEMID_GAME_PROCESS = 15, // "Game Process"
|
||||
MEMID_SCRIPT = 16, // "Script"
|
||||
MEMID_CARS = 17, // "Cars"
|
||||
MEMID_RENDER = 18, // "Render"
|
||||
MEMID_PED_ATTR = 19, // "Ped Attr"
|
||||
*/
|
||||
// III:
|
||||
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) { return MemoryMgrMalloc(sz); }
|
||||
void *operator new[](size_t sz) { return MemoryMgrMalloc(sz); }
|
||||
void operator delete(void *ptr) noexcept { MemoryMgrFree(ptr); }
|
||||
void operator delete[](void *ptr) noexcept { 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)
|
||||
{
|
||||
#ifdef FIX_BUGS
|
||||
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);
|
@ -7,8 +7,10 @@
|
||||
#include "Timecycle.h"
|
||||
#include "skeleton.h"
|
||||
#include "Debug.h"
|
||||
#ifndef FINAL
|
||||
#if !defined(FINAL) || defined(DEBUGMENU)
|
||||
#include "rtcharse.h"
|
||||
#endif
|
||||
#ifndef FINAL
|
||||
RtCharset *debugCharset;
|
||||
#endif
|
||||
|
||||
@ -19,7 +21,7 @@ bool gPS2alphaTest = false;
|
||||
#endif
|
||||
bool gBackfaceCulling = true;
|
||||
|
||||
#ifndef FINAL
|
||||
#if !defined(FINAL) || defined(DEBUGMENU)
|
||||
static bool charsetOpen;
|
||||
void OpenCharsetSafe()
|
||||
{
|
||||
@ -62,45 +64,6 @@ void FlushObrsPrintfs()
|
||||
#endif
|
||||
}
|
||||
|
||||
void *
|
||||
RwMallocAlign(RwUInt32 size, RwUInt32 align)
|
||||
{
|
||||
#ifdef FIX_BUGS
|
||||
uintptr ptralign = align-1;
|
||||
void *mem = (void *)malloc(size + sizeof(uintptr) + ptralign);
|
||||
|
||||
ASSERT(mem != nil);
|
||||
|
||||
void *addr = (void *)((((uintptr)mem) + sizeof(uintptr) + ptralign) & ~ptralign);
|
||||
|
||||
ASSERT(addr != nil);
|
||||
#else
|
||||
void *mem = (void *)malloc(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);
|
||||
|
||||
free(addr);
|
||||
}
|
||||
|
||||
void
|
||||
DefinedState(void)
|
||||
{
|
||||
@ -642,9 +605,81 @@ CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer)
|
||||
return (nil);
|
||||
}
|
||||
|
||||
#ifdef USE_TEXTURE_POOL
|
||||
WRAPPER void _TexturePoolsInitialise() { EAXJMP(0x598B10); }
|
||||
WRAPPER void _TexturePoolsShutdown() { EAXJMP(0x598B30); }
|
||||
#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)
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
extern bool gPS2alphaTest;
|
||||
|
||||
void *RwMallocAlign(RwUInt32 size, RwUInt32 align);
|
||||
void RwFreeAlign(void *mem);
|
||||
|
||||
void OpenCharsetSafe();
|
||||
void CreateDebugFont();
|
||||
void DestroyDebugFont();
|
||||
@ -53,8 +50,8 @@ RwCamera *CameraCreate(RwInt32 width,
|
||||
RwBool zBuffer);
|
||||
|
||||
|
||||
void _TexturePoolsInitialise();
|
||||
void _TexturePoolsShutdown();
|
||||
|
||||
RpAtomic *ConvertPlatformAtomic(RpAtomic *atomic, void *data);
|
||||
|
||||
#if defined(FIX_BUGS) && defined (GTA_PC)
|
||||
void SetAlphaTest(RwUInt32 alpharef);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "Sprite2d.h"
|
||||
#include "Text.h"
|
||||
#include "RwHelper.h"
|
||||
#include "Frontend.h"
|
||||
#endif //GTA_PC
|
||||
|
||||
float texLoadTime;
|
||||
@ -150,11 +151,80 @@ RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict)
|
||||
}
|
||||
|
||||
#ifdef GTA_PC
|
||||
#ifdef RWLIBS
|
||||
extern "C" RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags);
|
||||
#else
|
||||
RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags);
|
||||
|
||||
#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)
|
||||
{
|
||||
@ -201,6 +271,7 @@ WriteVideoCardCapsFile(void)
|
||||
CFileMgr::CloseFile(file);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ConvertingTexturesScreen(uint32 num, uint32 count, const char *text)
|
||||
@ -282,6 +353,22 @@ CreateTxdImageForVideoCard()
|
||||
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");
|
||||
@ -309,6 +396,9 @@ CreateTxdImageForVideoCard()
|
||||
delete []buf;
|
||||
delete pDir;
|
||||
CStreaming::RemoveTxd(i);
|
||||
#ifdef RW_GL3
|
||||
rw::gl3::needToReadBackTextures = false;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -332,9 +422,19 @@ CreateTxdImageForVideoCard()
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
|
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();
|
@ -10,8 +10,7 @@
|
||||
#include "VisibilityPlugins.h"
|
||||
#include "World.h"
|
||||
#include "custompipes.h"
|
||||
|
||||
#define FADE_DISTANCE 20.0f
|
||||
#include "MemoryHeap.h"
|
||||
|
||||
CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaList;
|
||||
CLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaEntityList;
|
||||
@ -32,6 +31,119 @@ float CVisibilityPlugins::ms_pedLod0Dist;
|
||||
float CVisibilityPlugins::ms_pedLod1Dist;
|
||||
float CVisibilityPlugins::ms_pedFadeDist;
|
||||
|
||||
#ifdef GTA_PS2 // maybe something else?
|
||||
// if wanted, delete the original geometry data after rendering
|
||||
// and only keep the instanced data
|
||||
bool
|
||||
rpDefaultGeometryInstance(RpGeometry *geo, void *atomic, int del)
|
||||
{
|
||||
#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31
|
||||
if(RpGeometryGetNumMorphTargets(geo) != 1)
|
||||
return false;
|
||||
|
||||
// this needs R*'s modification that geometry data is
|
||||
// allocated separately from the geometry itself
|
||||
geo->instanceFlags = rpGEOMETRYINSTANCE;
|
||||
AtomicDefaultRenderCallBack((RpAtomic*)atomic);
|
||||
|
||||
if(!del)
|
||||
return true;
|
||||
|
||||
// New mesh without indices
|
||||
RpMeshHeader *newheader = _rpMeshHeaderCreate(sizeof(RpMesh)*geo->mesh->numMeshes + sizeof(RpMeshHeader));
|
||||
newheader->numMeshes = geo->mesh->numMeshes;
|
||||
newheader->serialNum = 1;
|
||||
newheader->totalIndicesInMesh = 0;
|
||||
newheader->firstMeshOffset = 0;
|
||||
RpMesh *oldmesh = (RpMesh*)(geo->mesh+1);
|
||||
RpMesh *newmesh = (RpMesh*)(newheader+1);
|
||||
for(int i = 0; i < geo->mesh->numMeshes; i++){
|
||||
newmesh[i].indices = nil;
|
||||
newmesh[i].numIndices = 0;
|
||||
newmesh[i].material = oldmesh[i].material;
|
||||
}
|
||||
|
||||
geo->refCount++;
|
||||
RpGeometryLock(geo, rpGEOMETRYLOCKPOLYGONS | rpGEOMETRYLOCKVERTICES |
|
||||
rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT |
|
||||
rpGEOMETRYLOCKTEXCOORDS1 | rpGEOMETRYLOCKTEXCOORDS2);
|
||||
|
||||
// vertices and normals
|
||||
RpMorphTarget *mt = RpGeometryGetMorphTarget(geo, 0);
|
||||
if(mt->verts){
|
||||
RwFree(mt->verts);
|
||||
mt->verts = nil;
|
||||
mt->normals = nil;
|
||||
}
|
||||
geo->numVertices = 0;
|
||||
|
||||
// triangles
|
||||
for(int i = 0; i < RpGeometryGetNumTriangles(geo); i++){
|
||||
if(RpGeometryGetTriangles(geo)->matIndex == -1)
|
||||
continue;
|
||||
RpMaterialDestroy(_rpMaterialListGetMaterial(&geo->matList, RpGeometryGetTriangles(geo)->matIndex));
|
||||
}
|
||||
if(RpGeometryGetTriangles(geo)){
|
||||
RwFree(RpGeometryGetTriangles(geo));
|
||||
geo->triangles = nil;
|
||||
geo->numTriangles = 0;
|
||||
}
|
||||
|
||||
// tex coords
|
||||
if(RpGeometryGetVertexTexCoords(geo, 1)){
|
||||
RwFree(RpGeometryGetVertexTexCoords(geo, 1));
|
||||
geo->texCoords[1] = nil;
|
||||
}
|
||||
if(RpGeometryGetVertexTexCoords(geo, 0)){
|
||||
RwFree(RpGeometryGetVertexTexCoords(geo, 0));
|
||||
geo->texCoords[0] = nil;
|
||||
}
|
||||
|
||||
// vertex colors
|
||||
if(RpGeometryGetPreLightColors(geo)){
|
||||
RwFree(RpGeometryGetPreLightColors(geo));
|
||||
geo->preLitLum = nil;
|
||||
}
|
||||
|
||||
RpGeometryUnlock(geo);
|
||||
|
||||
geo->instanceFlags = rpGEOMETRYPERSISTENT;
|
||||
// BUG? don't we have to free the old mesh?
|
||||
geo->mesh = newheader;
|
||||
geo->refCount--;
|
||||
#else
|
||||
// We can do something for librw here actually, maybe later
|
||||
AtomicDefaultRenderCallBack((RpAtomic*)atomic);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
PreInstanceRenderCB(RpAtomic *atomic)
|
||||
{
|
||||
RpGeometry *geo = RpAtomicGetGeometry(atomic);
|
||||
if(RpGeometryGetTriangles(geo)){
|
||||
PUSH_MEMID(MEMID_STREAM_MODELS);
|
||||
rpDefaultGeometryInstance(geo, atomic, 1);
|
||||
POP_MEMID();
|
||||
}else
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
return atomic;
|
||||
}
|
||||
#define RENDERCALLBACK PreInstanceRenderCB
|
||||
#else
|
||||
RpAtomic*
|
||||
DefaultRenderCB_pushid(RpAtomic *atomic)
|
||||
{
|
||||
PUSH_MEMID(MEMID_STREAM_MODELS);
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
POP_MEMID();
|
||||
return atomic;
|
||||
}
|
||||
#define RENDERCALLBACK DefaultRenderCB_pushid
|
||||
#endif
|
||||
|
||||
void
|
||||
CVisibilityPlugins::Initialise(void)
|
||||
{
|
||||
@ -134,7 +246,7 @@ CVisibilityPlugins::RenderAlphaAtomics(void)
|
||||
for(node = m_alphaList.tail.prev;
|
||||
node != &m_alphaList.head;
|
||||
node = node->prev)
|
||||
AtomicDefaultRenderCallBack(node->item.atomic);
|
||||
RENDERCALLBACK(node->item.atomic);
|
||||
}
|
||||
|
||||
void
|
||||
@ -203,7 +315,7 @@ CVisibilityPlugins::RenderWheelAtomicCB(RpAtomic *atomic)
|
||||
if(lodatm){
|
||||
if(RpAtomicGetGeometry(lodatm) != RpAtomicGetGeometry(atomic))
|
||||
RpAtomicSetGeometry(atomic, RpAtomicGetGeometry(lodatm), rpATOMICSAMEBOUNDINGSPHERE);
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
@ -220,7 +332,7 @@ CVisibilityPlugins::RenderObjNormalAtomic(RpAtomic *atomic)
|
||||
len = RwV3dLength(&view);
|
||||
if(RwV3dDotProduct(&view, RwMatrixGetUp(m)) < -0.3f*len && len > 8.0f)
|
||||
return atomic;
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
@ -234,7 +346,7 @@ CVisibilityPlugins::RenderAlphaAtomic(RpAtomic *atomic, int alpha)
|
||||
flags = RpGeometryGetFlags(geo);
|
||||
RpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR);
|
||||
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);
|
||||
RpGeometrySetFlags(geo, flags);
|
||||
return atomic;
|
||||
@ -252,7 +364,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
|
||||
lodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE);
|
||||
if(mi->m_additive){
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
|
||||
}else{
|
||||
fadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE;
|
||||
@ -260,7 +372,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
|
||||
fadefactor = 1.0f;
|
||||
alpha = mi->m_alpha * fadefactor;
|
||||
if(alpha == 255)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
else{
|
||||
RpGeometry *geo = RpAtomicGetGeometry(lodatm);
|
||||
uint32 flags = RpGeometryGetFlags(geo);
|
||||
@ -268,7 +380,7 @@ CVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)
|
||||
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);
|
||||
if(geo != RpAtomicGetGeometry(atomic))
|
||||
RpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
RpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);
|
||||
RpGeometrySetFlags(geo, flags);
|
||||
}
|
||||
@ -295,7 +407,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB(RpAtomic *atomic)
|
||||
if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
|
||||
return atomic;
|
||||
}
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
@ -320,10 +432,10 @@ CVisibilityPlugins::RenderVehicleHiDetailAlphaCB(RpAtomic *atomic)
|
||||
if(flags & ATOMIC_FLAG_DRAWLAST){
|
||||
// sort before clump
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}else{
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}
|
||||
}
|
||||
return atomic;
|
||||
@ -346,7 +458,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic)
|
||||
if(dot > 0.0f)
|
||||
return atomic;
|
||||
}
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
@ -369,7 +481,7 @@ CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic)
|
||||
return atomic;
|
||||
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
@ -383,7 +495,7 @@ CVisibilityPlugins::RenderVehicleHiDetailCB_Boat(RpAtomic *atomic)
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq < ms_bigVehicleLod1Dist)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
@ -405,7 +517,7 @@ CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic)
|
||||
if(dot > 0.0f)
|
||||
return atomic;
|
||||
}
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
@ -429,7 +541,7 @@ CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic)
|
||||
return atomic;
|
||||
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
@ -446,7 +558,7 @@ CVisibilityPlugins::RenderVehicleReallyLowDetailCB(RpAtomic *atomic)
|
||||
if(dist >= ms_vehicleLod0Dist){
|
||||
alpha = GetClumpAlpha(clump);
|
||||
if(alpha == 255)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
else
|
||||
RenderAlphaAtomic(atomic, alpha);
|
||||
}
|
||||
@ -463,7 +575,7 @@ CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic)
|
||||
clumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));
|
||||
distsq = GetDistanceSquaredFromCamera(clumpframe);
|
||||
if(distsq >= ms_bigVehicleLod1Dist)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
@ -484,7 +596,7 @@ CVisibilityPlugins::RenderTrainHiDetailCB(RpAtomic *atomic)
|
||||
if(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*distsq < dot*dot))
|
||||
return atomic;
|
||||
}
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
@ -509,10 +621,10 @@ CVisibilityPlugins::RenderTrainHiDetailAlphaCB(RpAtomic *atomic)
|
||||
if(flags & ATOMIC_FLAG_DRAWLAST){
|
||||
// sort before clump
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq - 0.0001f))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}else{
|
||||
if(!InsertAtomicIntoSortedList(atomic, distsq + dot))
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
}
|
||||
}
|
||||
return atomic;
|
||||
@ -523,7 +635,7 @@ CVisibilityPlugins::RenderPlayerCB(RpAtomic *atomic)
|
||||
{
|
||||
if(CWorld::Players[0].m_pSkinTexture)
|
||||
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetTextureCB, CWorld::Players[0].m_pSkinTexture);
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
@ -539,7 +651,7 @@ CVisibilityPlugins::RenderPedLowDetailCB(RpAtomic *atomic)
|
||||
if(dist >= ms_pedLod0Dist){
|
||||
alpha = GetClumpAlpha(clump);
|
||||
if(alpha == 255)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
else
|
||||
RenderAlphaAtomic(atomic, alpha);
|
||||
}
|
||||
@ -558,7 +670,7 @@ CVisibilityPlugins::RenderPedHiDetailCB(RpAtomic *atomic)
|
||||
if(dist < ms_pedLod0Dist){
|
||||
alpha = GetClumpAlpha(clump);
|
||||
if(alpha == 255)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
else
|
||||
RenderAlphaAtomic(atomic, alpha);
|
||||
}
|
||||
@ -577,7 +689,7 @@ CVisibilityPlugins::RenderPedCB(RpAtomic *atomic)
|
||||
if(RwV3dDotProduct(&cam2atm, &cam2atm) < ms_pedLod1Dist){
|
||||
alpha = GetClumpAlpha(RpAtomicGetClump(atomic));
|
||||
if(alpha == 255)
|
||||
AtomicDefaultRenderCallBack(atomic);
|
||||
RENDERCALLBACK(atomic);
|
||||
else
|
||||
RenderAlphaAtomic(atomic, alpha);
|
||||
}
|
||||
@ -707,6 +819,11 @@ CVisibilityPlugins::PluginAttach(void)
|
||||
ms_clumpPluginOffset = RpClumpRegisterPlugin(sizeof(ClumpExt),
|
||||
ID_VISIBILITYCLUMP,
|
||||
ClumpConstructor, ClumpDestructor, ClumpCopyConstructor);
|
||||
|
||||
#if GTA_VERSION <= GTA3_PS2_160
|
||||
Initialise();
|
||||
#endif
|
||||
|
||||
return ms_atomicPluginOffset != -1 && ms_clumpPluginOffset != -1;
|
||||
}
|
||||
|
||||
@ -777,12 +894,11 @@ CVisibilityPlugins::GetAtomicId(RpAtomic *atomic)
|
||||
return ATOMICEXT(atomic)->flags;
|
||||
}
|
||||
|
||||
// This is rather useless, but whatever
|
||||
void
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(RpAtomic *atomic, RpAtomicCallBackRender cb)
|
||||
{
|
||||
if(cb == nil)
|
||||
cb = AtomicDefaultRenderCallBack; // not necessary
|
||||
cb = RENDERCALLBACK;
|
||||
RpAtomicSetRenderCallBack(atomic, cb);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user