2019-05-15 16:52:37 +02:00
# include "common.h"
2020-04-17 15:31:11 +02:00
2019-10-30 00:12:58 +01:00
# include "General.h"
2019-06-26 21:33:58 +02:00
# include "Pad.h"
# include "Hud.h"
# include "Text.h"
2019-06-27 00:12:58 +02:00
# include "Clock.h"
# include "Renderer.h"
2019-06-20 14:49:16 +02:00
# include "ModelInfo.h"
# include "TxdStore.h"
2019-06-21 17:28:55 +02:00
# include "ModelIndices.h"
2019-06-20 14:49:16 +02:00
# include "Pools.h"
2020-03-28 15:47:52 +01:00
# include "Wanted.h"
2019-06-20 14:49:16 +02:00
# include "Directory.h"
# include "RwHelper.h"
2019-06-21 17:28:55 +02:00
# include "World.h"
2019-06-20 14:49:16 +02:00
# include "Entity.h"
# include "FileMgr.h"
2019-06-21 17:28:55 +02:00
# include "FileLoader.h"
2019-06-27 14:17:42 +02:00
# include "Zones.h"
# include "Radar.h"
# include "Camera.h"
2019-06-28 12:34:02 +02:00
# include "Record.h"
# include "CarCtrl.h"
# include "Population.h"
# include "Gangs.h"
# include "CutsceneMgr.h"
2019-06-20 14:49:16 +02:00
# include "CdStream.h"
2019-05-15 16:52:37 +02:00
# include "Streaming.h"
2020-04-18 22:50:37 +02:00
# include "Replay.h"
2019-08-15 16:51:39 +02:00
# include "main.h"
2020-05-05 17:04:43 +02:00
# include "ColStore.h"
# include "DMAudio.h"
2020-08-20 23:43:13 +02:00
# include "Script.h"
2020-12-18 14:19:03 +01:00
# include "MemoryMgr.h"
# include "MemoryHeap.h"
2020-12-19 01:21:04 +01:00
# include "Font.h"
2020-12-27 17:26:30 +01:00
# include "Frontend.h"
2021-01-02 10:38:54 +01:00
# include "VarConsole.h"
2020-08-20 23:43:13 +02:00
2020-04-17 07:54:14 +02:00
bool CStreaming : : ms_disableStreaming ;
bool CStreaming : : ms_bLoadingBigModel ;
int32 CStreaming : : ms_numModelsRequested ;
CStreamingInfo CStreaming : : ms_aInfoForModel [ NUMSTREAMINFO ] ;
CStreamingInfo CStreaming : : ms_startLoadedList ;
CStreamingInfo CStreaming : : ms_endLoadedList ;
CStreamingInfo CStreaming : : ms_startRequestedList ;
CStreamingInfo CStreaming : : ms_endRequestedList ;
int32 CStreaming : : ms_oldSectorX ;
int32 CStreaming : : ms_oldSectorY ;
int32 CStreaming : : ms_streamingBufferSize ;
2020-10-04 21:39:54 +02:00
# ifndef ONE_THREAD_PER_CHANNEL
2020-04-17 07:54:14 +02:00
int8 * CStreaming : : ms_pStreamingBuffer [ 2 ] ;
2020-10-04 21:39:54 +02:00
# else
int8 * CStreaming : : ms_pStreamingBuffer [ 4 ] ;
# endif
2020-07-22 13:56:28 +02:00
size_t CStreaming : : ms_memoryUsed ;
2020-04-17 07:54:14 +02:00
CStreamingChannel CStreaming : : ms_channel [ 2 ] ;
int32 CStreaming : : ms_channelError ;
int32 CStreaming : : ms_numVehiclesLoaded ;
2020-08-20 23:43:13 +02:00
int32 CStreaming : : ms_numPedsLoaded ;
2020-04-17 07:54:14 +02:00
int32 CStreaming : : ms_vehiclesLoaded [ MAXVEHICLESLOADED ] ;
int32 CStreaming : : ms_lastVehicleDeleted ;
2020-05-06 21:54:43 +02:00
bool CStreaming : : ms_bIsPedFromPedGroupLoaded [ NUMMODELSPERPEDGROUP ] ;
2020-04-17 07:54:14 +02:00
CDirectory * CStreaming : : ms_pExtraObjectsDir ;
int32 CStreaming : : ms_numPriorityRequests ;
int32 CStreaming : : ms_currentPedGrp ;
2019-06-20 14:49:16 +02:00
int32 CStreaming : : ms_currentPedLoading ;
int32 CStreaming : : ms_lastCullZone ;
2020-04-17 07:54:14 +02:00
uint16 CStreaming : : ms_loadedGangs ;
uint16 CStreaming : : ms_loadedGangCars ;
int32 CStreaming : : ms_imageOffsets [ NUMCDIMAGES ] ;
int32 CStreaming : : ms_lastImageRead ;
int32 CStreaming : : ms_imageSize ;
2020-07-22 13:56:28 +02:00
size_t CStreaming : : ms_memoryAvailable ;
2020-04-17 07:54:14 +02:00
int32 desiredNumVehiclesLoaded = 12 ;
2020-05-05 23:27:43 +02:00
CEntity * pIslandLODmainlandEntity ;
CEntity * pIslandLODbeachEntity ;
int32 islandLODmainland ;
int32 islandLODbeach ;
2019-06-20 14:49:16 +02:00
2021-01-02 10:38:54 +01:00
# ifndef MASTER
bool gbPrintStats ;
bool gbPrintVehiclesInMemory ; // TODO
bool gbPrintStreamingBuffer ; // TODO
# endif
2019-06-27 00:12:58 +02:00
bool
CStreamingInfo : : GetCdPosnAndSize ( uint32 & posn , uint32 & size )
{
if ( m_size = = 0 )
return false ;
posn = m_position ;
size = m_size ;
return true ;
}
void
CStreamingInfo : : SetCdPosnAndSize ( uint32 posn , uint32 size )
{
m_position = posn ;
m_size = size ;
}
void
CStreamingInfo : : AddToList ( CStreamingInfo * link )
{
// Insert this after link
m_next = link - > m_next ;
m_prev = link ;
link - > m_next = this ;
m_next - > m_prev = this ;
}
void
CStreamingInfo : : RemoveFromList ( void )
{
m_next - > m_prev = m_prev ;
m_prev - > m_next = m_next ;
m_next = nil ;
m_prev = nil ;
}
2019-06-12 20:07:37 +02:00
2019-06-20 14:49:16 +02:00
void
2020-05-05 13:02:42 +02:00
CStreaming : : Init2 ( void )
2019-06-20 14:49:16 +02:00
{
int i ;
for ( i = 0 ; i < NUMSTREAMINFO ; i + + ) {
ms_aInfoForModel [ i ] . m_loadState = STREAMSTATE_NOTLOADED ;
ms_aInfoForModel [ i ] . m_next = nil ;
ms_aInfoForModel [ i ] . m_prev = nil ;
ms_aInfoForModel [ i ] . m_nextID = - 1 ;
ms_aInfoForModel [ i ] . m_size = 0 ;
ms_aInfoForModel [ i ] . m_position = 0 ;
}
2019-06-26 21:33:58 +02:00
ms_channelError = - 1 ;
2019-06-20 14:49:16 +02:00
// init lists
ms_startLoadedList . m_next = & ms_endLoadedList ;
ms_startLoadedList . m_prev = nil ;
ms_endLoadedList . m_prev = & ms_startLoadedList ;
ms_endLoadedList . m_next = nil ;
ms_startRequestedList . m_next = & ms_endRequestedList ;
ms_startRequestedList . m_prev = nil ;
ms_endRequestedList . m_prev = & ms_startRequestedList ;
ms_endRequestedList . m_next = nil ;
// init misc
ms_oldSectorX = 0 ;
ms_oldSectorY = 0 ;
ms_streamingBufferSize = 0 ;
ms_disableStreaming = false ;
ms_memoryUsed = 0 ;
ms_bLoadingBigModel = false ;
// init channels
2019-06-24 18:44:23 +02:00
ms_channel [ 0 ] . state = CHANNELSTATE_IDLE ;
ms_channel [ 1 ] . state = CHANNELSTATE_IDLE ;
2019-06-20 14:49:16 +02:00
for ( i = 0 ; i < 4 ; i + + ) {
2019-06-24 18:44:23 +02:00
ms_channel [ 0 ] . streamIds [ i ] = - 1 ;
2019-06-20 14:49:16 +02:00
ms_channel [ 0 ] . offsets [ i ] = - 1 ;
2019-06-24 18:44:23 +02:00
ms_channel [ 1 ] . streamIds [ i ] = - 1 ;
2019-06-20 14:49:16 +02:00
ms_channel [ 1 ] . offsets [ i ] = - 1 ;
}
// init stream info, mark things that are already loaded
for ( i = 0 ; i < MODELINFOSIZE ; i + + ) {
CBaseModelInfo * mi = CModelInfo : : GetModelInfo ( i ) ;
if ( mi & & mi - > GetRwObject ( ) ) {
2019-06-24 18:44:23 +02:00
ms_aInfoForModel [ i ] . m_loadState = STREAMSTATE_LOADED ;
ms_aInfoForModel [ i ] . m_flags = STREAMFLAGS_DONT_REMOVE ;
2019-06-20 14:49:16 +02:00
if ( mi - > IsSimple ( ) )
( ( CSimpleModelInfo * ) mi ) - > m_alpha = 255 ;
}
}
for ( i = 0 ; i < TXDSTORESIZE ; i + + )
if ( CTxdStore : : GetSlot ( i ) & & CTxdStore : : GetSlot ( i ) - > texDict )
ms_aInfoForModel [ i + STREAM_OFFSET_TXD ] . m_loadState = STREAMSTATE_LOADED ;
for ( i = 0 ; i < MAXVEHICLESLOADED ; i + + )
ms_vehiclesLoaded [ i ] = - 1 ;
ms_numVehiclesLoaded = 0 ;
2020-08-20 23:43:13 +02:00
ms_numPedsLoaded = 8 ;
2019-06-20 14:49:16 +02:00
2020-05-06 21:54:43 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( ms_bIsPedFromPedGroupLoaded ) ; i + + )
ms_bIsPedFromPedGroupLoaded [ i ] = false ;
2019-06-20 14:49:16 +02:00
ms_pExtraObjectsDir = new CDirectory ( EXTRADIRSIZE ) ;
ms_numPriorityRequests = 0 ;
ms_currentPedGrp = - 1 ;
ms_lastCullZone = - 1 ; // unused because RemoveModelsNotVisibleFromCullzone is gone
ms_loadedGangs = 0 ;
2020-05-06 21:54:43 +02:00
ms_currentPedLoading = NUMMODELSPERPEDGROUP ; // unused, whatever it is
2019-06-20 14:49:16 +02:00
LoadCdDirectory ( ) ;
// allocate streaming buffers
if ( ms_streamingBufferSize & 1 ) ms_streamingBufferSize + + ;
2021-01-27 16:26:08 +01:00
# ifndef ONE_THREAD_PER_CHANNEL
2019-06-24 18:44:23 +02:00
ms_pStreamingBuffer [ 0 ] = ( int8 * ) RwMallocAlign ( ms_streamingBufferSize * CDSTREAM_SECTOR_SIZE , CDSTREAM_SECTOR_SIZE ) ;
2019-06-20 14:49:16 +02:00
ms_streamingBufferSize / = 2 ;
ms_pStreamingBuffer [ 1 ] = ms_pStreamingBuffer [ 0 ] + ms_streamingBufferSize * CDSTREAM_SECTOR_SIZE ;
2021-01-27 16:26:08 +01:00
# else
ms_pStreamingBuffer [ 0 ] = ( int8 * ) RwMallocAlign ( ms_streamingBufferSize * 2 * CDSTREAM_SECTOR_SIZE , CDSTREAM_SECTOR_SIZE ) ;
ms_streamingBufferSize / = 2 ;
ms_pStreamingBuffer [ 1 ] = ms_pStreamingBuffer [ 0 ] + ms_streamingBufferSize * CDSTREAM_SECTOR_SIZE ;
ms_pStreamingBuffer [ 2 ] = ms_pStreamingBuffer [ 1 ] + ms_streamingBufferSize * CDSTREAM_SECTOR_SIZE ;
2020-10-04 21:39:54 +02:00
ms_pStreamingBuffer [ 3 ] = ms_pStreamingBuffer [ 2 ] + ms_streamingBufferSize * CDSTREAM_SECTOR_SIZE ;
# endif
2019-06-20 14:49:16 +02:00
debug ( " Streaming buffer size is %d sectors " , ms_streamingBufferSize ) ;
2020-08-19 14:58:43 +02:00
// PC only, figure out how much memory we got
# ifdef GTA_PC
2019-06-20 14:49:16 +02:00
# define MB (1024*1024)
2020-08-19 14:58:43 +02:00
# ifdef FIX_BUGS
// do what gta3 does
extern size_t _dwMemAvailPhys ;
ms_memoryAvailable = ( _dwMemAvailPhys - 10 * MB ) / 2 ;
if ( ms_memoryAvailable < 65 * MB )
ms_memoryAvailable = 65 * MB ;
desiredNumVehiclesLoaded = ( int32 ) ( ( ms_memoryAvailable / MB - 65 ) / 3 + 12 ) ;
if ( desiredNumVehiclesLoaded > MAXVEHICLESLOADED )
desiredNumVehiclesLoaded = MAXVEHICLESLOADED ;
# else
2020-07-22 13:56:28 +02:00
ms_memoryAvailable = 65 * MB ;
2020-05-06 21:54:43 +02:00
desiredNumVehiclesLoaded = 25 ;
2020-08-19 14:58:43 +02:00
debug ( " Memory allocated to Streaming is %zuMB " , ms_memoryAvailable / MB ) ; // original modifier was %d
# endif
2019-06-20 14:49:16 +02:00
# undef MB
2020-08-19 14:58:43 +02:00
# endif
2019-06-20 14:49:16 +02:00
// find island LODs
2020-05-05 23:27:43 +02:00
pIslandLODmainlandEntity = nil ;
pIslandLODbeachEntity = nil ;
islandLODmainland = - 1 ;
islandLODbeach = - 1 ;
2021-01-02 10:38:54 +01:00
CModelInfo : : GetModelInfo ( " IslandLODmainland " , & islandLODmainland ) ;
CModelInfo : : GetModelInfo ( " IslandLODbeach " , & islandLODbeach ) ;
# ifndef MASTER
VarConsole . Add ( " Streaming Debug " , & gbPrintStats , true ) ;
VarConsole . Add ( " Streaming Vehicle Debug " , & gbPrintVehiclesInMemory , true ) ;
VarConsole . Add ( " Printf Streaming Buffer contents " , & gbPrintStreamingBuffer , true ) ;
# endif
2020-05-05 13:02:42 +02:00
}
void
CStreaming : : Init ( void )
{
# ifdef USE_TXD_CDIMAGE
2020-08-20 23:43:13 +02:00
if ( ! CanVideoCardDoDXT ( ) ) {
int txdHandle = CFileMgr : : OpenFile ( " MODELS \\ TXD.IMG " , " r " ) ;
if ( txdHandle )
CFileMgr : : CloseFile ( txdHandle ) ;
if ( ! CheckVideoCardCaps ( ) & & txdHandle ) {
2020-05-05 13:02:42 +02:00
CdStreamAddImage ( " MODELS \\ TXD.IMG " ) ;
CStreaming : : Init2 ( ) ;
2020-08-20 23:43:13 +02:00
} else {
CStreaming : : Init2 ( ) ;
if ( CreateTxdImageForVideoCard ( ) ) {
CStreaming : : Shutdown ( ) ;
CdStreamAddImage ( " MODELS \\ TXD.IMG " ) ;
CStreaming : : Init2 ( ) ;
}
2020-05-05 13:02:42 +02:00
}
2020-08-20 23:43:13 +02:00
} else
CStreaming : : Init2 ( ) ;
2020-05-05 13:02:42 +02:00
# else
2020-05-11 17:03:32 +02:00
CStreaming : : Init2 ( ) ;
2020-05-05 13:02:42 +02:00
# endif
2019-06-20 14:49:16 +02:00
}
2020-08-20 23:43:13 +02:00
void
CStreaming : : ReInit ( void )
{
int i ;
CStreaming : : FlushRequestList ( ) ;
CStreaming : : DeleteAllRwObjects ( ) ;
CStreaming : : RemoveAllUnusedModels ( ) ;
for ( i = 0 ; i < MODELINFOSIZE ; i + + )
if ( CModelInfo : : GetModelInfo ( i ) & & ms_aInfoForModel [ i ] . m_flags & STREAMFLAGS_SCRIPTOWNED )
SetMissionDoesntRequireModel ( i ) ;
CStreaming : : ms_disableStreaming = false ;
}
2019-06-20 14:49:16 +02:00
void
CStreaming : : Shutdown ( void )
{
RwFreeAlign ( ms_pStreamingBuffer [ 0 ] ) ;
ms_streamingBufferSize = 0 ;
2020-08-20 23:43:13 +02:00
if ( ms_pExtraObjectsDir ) {
2019-06-20 14:49:16 +02:00
delete ms_pExtraObjectsDir ;
2020-08-20 23:43:13 +02:00
# ifdef FIX_BUGS
ms_pExtraObjectsDir = nil ;
# endif
}
2019-06-20 14:49:16 +02:00
}
2020-11-26 17:11:55 +01:00
# ifndef MASTER
uint64 timeProcessingTXD ;
uint64 timeProcessingDFF ;
# endif
2019-06-28 12:34:02 +02:00
void
CStreaming : : Update ( void )
{
CStreamingInfo * si , * prev ;
bool requestedSubway = false ;
2020-11-26 17:11:55 +01:00
# ifndef MASTER
timeProcessingTXD = 0 ;
timeProcessingDFF = 0 ;
# endif
2019-06-28 12:34:02 +02:00
UpdateMemoryUsed ( ) ;
if ( ms_channelError ! = - 1 ) {
RetryLoadFile ( ms_channelError ) ;
return ;
}
if ( CTimer : : GetIsPaused ( ) )
return ;
2020-05-05 17:04:43 +02:00
LoadBigBuildingsWhenNeeded ( ) ;
if ( ! ms_disableStreaming & & TheCamera . GetPosition ( ) . z < 55.0f )
2020-08-20 23:43:13 +02:00
AddModelsToRequestList ( TheCamera . GetPosition ( ) , 0 ) ;
2019-06-28 12:34:02 +02:00
DeleteFarAwayRwObjects ( TheCamera . GetPosition ( ) ) ;
if ( ! ms_disableStreaming & &
2020-05-05 17:04:43 +02:00
! CCutsceneMgr : : IsCutsceneProcessing ( ) & &
2019-06-28 12:34:02 +02:00
ms_numModelsRequested < 5 & &
2020-05-05 18:06:38 +02:00
! CRenderer : : m_loadingPriority & &
2020-05-06 21:54:43 +02:00
CGame : : currArea = = AREA_MAIN_MAP & &
2020-05-05 18:06:38 +02:00
! CReplay : : IsPlayingBack ( ) ) {
2019-06-28 12:34:02 +02:00
StreamVehiclesAndPeds ( ) ;
2019-06-29 11:09:33 +02:00
StreamZoneModels ( FindPlayerCoors ( ) ) ;
2019-06-28 12:34:02 +02:00
}
LoadRequestedModels ( ) ;
2020-05-05 17:04:43 +02:00
if ( CWorld : : Players [ 0 ] . m_pRemoteVehicle ) {
CColStore : : AddCollisionNeededAtPosn ( FindPlayerCoors ( ) ) ;
CColStore : : LoadCollision ( CWorld : : Players [ 0 ] . m_pRemoteVehicle - > GetPosition ( ) ) ;
CColStore : : EnsureCollisionIsInMemory ( CWorld : : Players [ 0 ] . m_pRemoteVehicle - > GetPosition ( ) ) ;
} else {
CColStore : : LoadCollision ( FindPlayerCoors ( ) ) ;
CColStore : : EnsureCollisionIsInMemory ( FindPlayerCoors ( ) ) ;
}
2020-05-05 13:02:42 +02:00
2020-11-26 17:11:55 +01:00
// TODO: PrintRequestList
//if (CPad::GetPad(1)->GetLeftShoulder2JustDown() && CPad::GetPad(1)->GetRightShoulder1() && CPad::GetPad(1)->GetRightShoulder2())
// PrintRequestList();
2020-05-05 13:02:42 +02:00
2019-06-28 12:34:02 +02:00
for ( si = ms_endRequestedList . m_prev ; si ! = & ms_startRequestedList ; si = prev ) {
prev = si - > m_prev ;
if ( ( si - > m_flags & ( STREAMFLAGS_KEEP_IN_MEMORY | STREAMFLAGS_PRIORITY ) ) = = 0 )
RemoveModel ( si - ms_aInfoForModel ) ;
}
}
2019-06-20 14:49:16 +02:00
void
CStreaming : : LoadCdDirectory ( void )
{
char dirname [ 132 ] ;
int i ;
2019-06-27 10:58:51 +02:00
# ifdef GTA_PC
2019-06-20 14:49:16 +02:00
ms_imageOffsets [ 0 ] = 0 ;
2019-06-27 10:58:51 +02:00
ms_imageOffsets [ 1 ] = - 1 ;
ms_imageOffsets [ 2 ] = - 1 ;
ms_imageOffsets [ 3 ] = - 1 ;
ms_imageOffsets [ 4 ] = - 1 ;
ms_imageOffsets [ 5 ] = - 1 ;
2019-06-20 14:49:16 +02:00
ms_imageSize = GetGTA3ImgSize ( ) ;
2019-06-24 18:44:23 +02:00
// PS2 uses CFileMgr::GetCdFile on all IMG files to fill the array
2019-06-27 10:58:51 +02:00
# endif
2019-06-24 18:44:23 +02:00
2019-06-20 14:49:16 +02:00
i = CdStreamGetNumImages ( ) ;
while ( i - - > = 1 ) {
strcpy ( dirname , CdStreamGetImageName ( i ) ) ;
strncpy ( strrchr ( dirname , ' . ' ) + 1 , " DIR " , 3 ) ;
LoadCdDirectory ( dirname , i ) ;
}
ms_lastImageRead = 0 ;
ms_imageSize / = CDSTREAM_SECTOR_SIZE ;
}
void
CStreaming : : LoadCdDirectory ( const char * dirname , int n )
{
int fd , lastID , imgSelector ;
2020-05-05 18:06:38 +02:00
int modelId ;
2019-06-20 14:49:16 +02:00
CDirectory : : DirectoryInfo direntry ;
char * dot ;
lastID = - 1 ;
fd = CFileMgr : : OpenFile ( dirname , " rb " ) ;
assert ( fd > 0 ) ;
imgSelector = n < < 24 ;
assert ( sizeof ( direntry ) = = 32 ) ;
while ( CFileMgr : : Read ( fd , ( char * ) & direntry , sizeof ( direntry ) ) ) {
2020-05-05 17:04:43 +02:00
bool bAddToStreaming = false ;
if ( direntry . size > ( uint32 ) ms_streamingBufferSize )
ms_streamingBufferSize = direntry . size ;
direntry . name [ 23 ] = ' \0 ' ;
dot = strchr ( direntry . name , ' . ' ) ;
if ( dot = = nil | | dot - direntry . name > 20 ) {
debug ( " %s is too long \n " , direntry . name ) ;
lastID = - 1 ;
continue ;
}
* dot = ' \0 ' ;
2020-05-08 15:59:57 +02:00
if ( strncasecmp ( dot + 1 , " DFF " , 3 ) = = 0 ) {
2020-05-05 17:04:43 +02:00
if ( CModelInfo : : GetModelInfo ( direntry . name , & modelId ) ) {
bAddToStreaming = true ;
} else {
# ifdef FIX_BUGS
// remember which cdimage this came from
ms_pExtraObjectsDir - > AddItem ( direntry , n ) ;
# else
ms_pExtraObjectsDir - > AddItem ( direntry ) ;
# endif
lastID = - 1 ;
}
2020-05-08 15:59:57 +02:00
} else if ( strncasecmp ( dot + 1 , " TXD " , 3 ) = = 0 ) {
2020-05-05 17:04:43 +02:00
modelId = CTxdStore : : FindTxdSlot ( direntry . name ) ;
if ( modelId = = - 1 )
modelId = CTxdStore : : AddTxdSlot ( direntry . name ) ;
modelId + = STREAM_OFFSET_TXD ;
bAddToStreaming = true ;
2020-05-08 15:59:57 +02:00
} else if ( strncasecmp ( dot + 1 , " COL " , 3 ) = = 0 ) {
2020-05-05 17:04:43 +02:00
modelId = CColStore : : FindColSlot ( direntry . name ) ;
if ( modelId = = - 1 )
modelId = CColStore : : AddColSlot ( direntry . name ) ;
modelId + = STREAM_OFFSET_COL ;
bAddToStreaming = true ;
2020-05-08 20:56:42 +02:00
} else if ( strncasecmp ( dot + 1 , " IFP " , 3 ) = = 0 ) {
modelId = CAnimManager : : RegisterAnimBlock ( direntry . name ) ;
modelId + = STREAM_OFFSET_ANIM ;
bAddToStreaming = true ;
2020-05-05 17:04:43 +02:00
} else {
* dot = ' . ' ;
lastID = - 1 ;
}
if ( bAddToStreaming ) {
if ( ms_aInfoForModel [ modelId ] . GetCdSize ( ) ) {
debug ( " %s.%s appears more than once in %s \n " , direntry . name , dot + 1 , dirname ) ;
lastID = - 1 ;
} else {
direntry . offset | = imgSelector ;
ms_aInfoForModel [ modelId ] . SetCdPosnAndSize ( direntry . offset , direntry . size ) ;
if ( lastID ! = - 1 )
ms_aInfoForModel [ lastID ] . m_nextID = modelId ;
lastID = modelId ;
}
}
2019-06-20 14:49:16 +02:00
}
CFileMgr : : CloseFile ( fd ) ;
}
2020-05-06 21:54:43 +02:00
static char *
GetObjectName ( int streamId )
{
static char objname [ 32 ] ;
if ( streamId < STREAM_OFFSET_TXD )
2021-01-08 20:53:11 +01:00
sprintf ( objname , " %s.dff " , CModelInfo : : GetModelInfo ( streamId ) - > GetModelName ( ) ) ;
2020-05-06 21:54:43 +02:00
else if ( streamId > = STREAM_OFFSET_TXD & & streamId < STREAM_OFFSET_COL )
sprintf ( objname , " %s.txd " , CTxdStore : : GetTxdName ( streamId - STREAM_OFFSET_TXD ) ) ;
2020-05-08 15:59:57 +02:00
else if ( streamId > = STREAM_OFFSET_COL & & streamId < STREAM_OFFSET_ANIM )
2020-05-06 21:54:43 +02:00
sprintf ( objname , " %s.col " , CColStore : : GetColName ( streamId - STREAM_OFFSET_COL ) ) ;
2020-05-08 20:56:42 +02:00
else {
assert ( streamId < NUMSTREAMINFO ) ;
sprintf ( objname , " %s.ifp " , CAnimManager : : GetAnimationBlock ( streamId - STREAM_OFFSET_ANIM ) - > name ) ;
}
2020-05-06 21:54:43 +02:00
return objname ;
}
2020-12-21 12:34:29 +01:00
# ifdef USE_CUSTOM_ALLOCATOR
RpAtomic *
RegisterAtomicMemPtrsCB ( RpAtomic * atomic , void * data )
{
// empty because we expect models to be pre-instanced
return atomic ;
}
# endif
2020-05-06 21:54:43 +02:00
2019-06-21 17:28:55 +02:00
bool
CStreaming : : ConvertBufferToObject ( int8 * buf , int32 streamId )
{
RwMemory mem ;
RwStream * stream ;
int cdsize ;
uint32 startTime , endTime , timeDiff ;
CBaseModelInfo * mi ;
bool success ;
startTime = CTimer : : GetCurrentTimeInCycles ( ) / CTimer : : GetCyclesPerMillisecond ( ) ;
cdsize = ms_aInfoForModel [ streamId ] . GetCdSize ( ) ;
mem . start = ( uint8 * ) buf ;
mem . length = cdsize * CDSTREAM_SECTOR_SIZE ;
stream = RwStreamOpen ( rwSTREAMMEMORY , rwSTREAMREAD , & mem ) ;
if ( streamId < STREAM_OFFSET_TXD ) {
// Model
2019-06-24 18:44:23 +02:00
mi = CModelInfo : : GetModelInfo ( streamId ) ;
2019-06-21 17:28:55 +02:00
2020-05-08 20:56:42 +02:00
// Txd and anim have to be loaded
int animId = mi - > GetAnimFileIndex ( ) ;
2021-01-08 13:51:42 +01:00
# ifdef FIX_BUGS
if ( ! HasTxdLoaded ( mi - > GetTxdSlot ( ) ) | |
# else
// texDict will exist even if only first part has loaded
2020-05-08 20:56:42 +02:00
if ( CTxdStore : : GetSlot ( mi - > GetTxdSlot ( ) ) - > texDict = = nil | |
2021-01-08 13:51:42 +01:00
# endif
2020-05-08 20:56:42 +02:00
animId ! = - 1 & & ! CAnimManager : : GetAnimationBlock ( animId ) - > isLoaded ) {
2019-06-21 17:28:55 +02:00
RemoveModel ( streamId ) ;
2019-06-24 18:44:23 +02:00
ReRequestModel ( streamId ) ;
2019-06-21 17:28:55 +02:00
RwStreamClose ( stream , & mem ) ;
return false ;
}
2020-05-08 20:56:42 +02:00
// Set Txd and anims to use
2019-06-21 17:28:55 +02:00
CTxdStore : : AddRef ( mi - > GetTxdSlot ( ) ) ;
2020-12-21 12:34:29 +01:00
# if GTA_VERSION > GTAVC_PS2
2020-05-08 20:56:42 +02:00
if ( animId ! = - 1 )
CAnimManager : : AddAnimBlockRef ( animId ) ;
2020-12-21 12:34:29 +01:00
# endif
2019-06-21 17:28:55 +02:00
2020-11-26 16:47:19 +01:00
PUSH_MEMID ( MEMID_STREAM_MODELS ) ;
CTxdStore : : SetCurrentTxd ( mi - > GetTxdSlot ( ) ) ;
2019-06-21 17:28:55 +02:00
if ( mi - > IsSimple ( ) ) {
2019-06-24 18:44:23 +02:00
success = CFileLoader : : LoadAtomicFile ( stream , streamId ) ;
2020-05-06 21:54:43 +02:00
// TODO(MIAMI)? complain if file is not pre-instanced. we hardly are interested in that
2020-05-05 14:06:55 +02:00
} else if ( mi - > GetModelType ( ) = = MITYPE_VEHICLE ) {
2019-06-21 17:28:55 +02:00
// load vehicles in two parts
2019-06-24 18:44:23 +02:00
CModelInfo : : GetModelInfo ( streamId ) - > AddRef ( ) ;
success = CFileLoader : : StartLoadClumpFile ( stream , streamId ) ;
2019-06-21 17:28:55 +02:00
if ( success )
ms_aInfoForModel [ streamId ] . m_loadState = STREAMSTATE_STARTED ;
} else {
2019-06-24 18:44:23 +02:00
success = CFileLoader : : LoadClumpFile ( stream , streamId ) ;
2020-11-30 23:44:58 +01:00
# ifdef USE_CUSTOM_ALLOCATOR
if ( success )
RpClumpForAllAtomics ( ( RpClump * ) mi - > GetRwObject ( ) , RegisterAtomicMemPtrsCB , nil ) ;
# endif
2019-06-21 17:28:55 +02:00
}
2020-11-26 16:47:19 +01:00
POP_MEMID ( ) ;
2019-06-21 17:28:55 +02:00
UpdateMemoryUsed ( ) ;
2020-05-08 20:56:42 +02:00
// Txd and anims no longer needed unless we only read part of the file
if ( ms_aInfoForModel [ streamId ] . m_loadState ! = STREAMSTATE_STARTED ) {
2019-06-21 17:28:55 +02:00
CTxdStore : : RemoveRefWithoutDelete ( mi - > GetTxdSlot ( ) ) ;
2020-12-21 12:34:29 +01:00
# if GTA_VERSION > GTAVC_PS2
2020-05-08 20:56:42 +02:00
if ( animId ! = - 1 )
CAnimManager : : RemoveAnimBlockRefWithoutDelete ( animId ) ;
2020-12-21 12:34:29 +01:00
# endif
2020-05-08 20:56:42 +02:00
}
2019-06-21 17:28:55 +02:00
if ( ! success ) {
2021-01-08 20:53:11 +01:00
debug ( " Failed to load %s \n " , CModelInfo : : GetModelInfo ( streamId ) - > GetModelName ( ) ) ;
2019-06-21 17:28:55 +02:00
RemoveModel ( streamId ) ;
2019-06-24 18:44:23 +02:00
ReRequestModel ( streamId ) ;
2019-06-21 17:28:55 +02:00
RwStreamClose ( stream , & mem ) ;
return false ;
}
2020-05-05 17:04:43 +02:00
} else if ( streamId > = STREAM_OFFSET_TXD & & streamId < STREAM_OFFSET_COL ) {
2019-06-21 17:28:55 +02:00
// Txd
if ( ( ms_aInfoForModel [ streamId ] . m_flags & STREAMFLAGS_KEEP_IN_MEMORY ) = = 0 & &
! IsTxdUsedByRequestedModels ( streamId - STREAM_OFFSET_TXD ) ) {
RemoveModel ( streamId ) ;
RwStreamClose ( stream , & mem ) ;
return false ;
}
2020-11-26 16:47:19 +01:00
PUSH_MEMID ( MEMID_STREAM_TEXUTRES ) ;
2019-06-21 17:28:55 +02:00
if ( ms_bLoadingBigModel | | cdsize > 200 ) {
success = CTxdStore : : StartLoadTxd ( streamId - STREAM_OFFSET_TXD , stream ) ;
if ( success )
ms_aInfoForModel [ streamId ] . m_loadState = STREAMSTATE_STARTED ;
} else
success = CTxdStore : : LoadTxd ( streamId - STREAM_OFFSET_TXD , stream ) ;
2020-11-26 16:47:19 +01:00
POP_MEMID ( ) ;
2019-06-21 17:28:55 +02:00
UpdateMemoryUsed ( ) ;
if ( ! success ) {
debug ( " Failed to load %s.txd \n " , CTxdStore : : GetTxdName ( streamId - STREAM_OFFSET_TXD ) ) ;
RemoveModel ( streamId ) ;
2019-06-24 18:44:23 +02:00
ReRequestModel ( streamId ) ;
2019-06-21 17:28:55 +02:00
RwStreamClose ( stream , & mem ) ;
return false ;
}
2020-05-08 15:59:57 +02:00
} else if ( streamId > = STREAM_OFFSET_COL & & streamId < STREAM_OFFSET_ANIM ) {
2020-12-21 12:34:29 +01:00
PUSH_MEMID ( MEMID_STREAM_COLLISION ) ;
bool success = CColStore : : LoadCol ( streamId - STREAM_OFFSET_COL , mem . start , mem . length ) ;
POP_MEMID ( ) ;
if ( ! success ) {
2020-05-05 17:04:43 +02:00
debug ( " Failed to load %s.col \n " , CColStore : : GetColName ( streamId - STREAM_OFFSET_COL ) ) ;
RemoveModel ( streamId ) ;
ReRequestModel ( streamId ) ;
RwStreamClose ( stream , & mem ) ;
return false ;
}
2020-05-08 15:59:57 +02:00
} else if ( streamId > = STREAM_OFFSET_ANIM ) {
assert ( streamId < NUMSTREAMINFO ) ;
2020-05-08 20:56:42 +02:00
if ( ( ms_aInfoForModel [ streamId ] . m_flags & STREAMFLAGS_KEEP_IN_MEMORY ) = = 0 & &
! AreAnimsUsedByRequestedModels ( streamId - STREAM_OFFSET_ANIM ) ) {
RemoveModel ( streamId ) ;
RwStreamClose ( stream , & mem ) ;
return false ;
}
2020-12-21 12:34:29 +01:00
PUSH_MEMID ( MEMID_STREAM_ANIMATION ) ;
2020-05-08 20:56:42 +02:00
CAnimManager : : LoadAnimFile ( stream , true , nil ) ;
CAnimManager : : CreateAnimAssocGroups ( ) ;
2020-12-21 12:34:29 +01:00
POP_MEMID ( ) ;
2019-06-21 17:28:55 +02:00
}
RwStreamClose ( stream , & mem ) ;
if ( streamId < STREAM_OFFSET_TXD ) {
// Model
// Vehicles and Peds not in loaded list
2020-05-05 14:06:55 +02:00
if ( mi - > GetModelType ( ) ! = MITYPE_VEHICLE & & mi - > GetModelType ( ) ! = MITYPE_PED ) {
2019-06-21 17:28:55 +02:00
CSimpleModelInfo * smi = ( CSimpleModelInfo * ) mi ;
// Set fading for some objects
if ( mi - > IsSimple ( ) & & ! smi - > m_isBigBuilding ) {
if ( ms_aInfoForModel [ streamId ] . m_flags & STREAMFLAGS_NOFADE )
smi - > m_alpha = 255 ;
else
smi - > m_alpha = 0 ;
}
2020-05-06 21:54:43 +02:00
if ( CanRemoveModel ( streamId ) )
2019-06-21 17:28:55 +02:00
ms_aInfoForModel [ streamId ] . AddToList ( & ms_startLoadedList ) ;
}
2020-05-08 20:56:42 +02:00
} else if ( streamId > = STREAM_OFFSET_TXD & & streamId < STREAM_OFFSET_COL | |
streamId > = STREAM_OFFSET_ANIM ) {
assert ( streamId < NUMSTREAMINFO ) ;
// Txd and anims
2020-05-06 21:54:43 +02:00
if ( CanRemoveModel ( streamId ) )
2019-06-21 17:28:55 +02:00
ms_aInfoForModel [ streamId ] . AddToList ( & ms_startLoadedList ) ;
}
// Mark objects as loaded
if ( ms_aInfoForModel [ streamId ] . m_loadState ! = STREAMSTATE_STARTED ) {
ms_aInfoForModel [ streamId ] . m_loadState = STREAMSTATE_LOADED ;
2020-11-26 16:47:19 +01:00
# ifndef USE_CUSTOM_ALLOCATOR
2019-06-21 17:28:55 +02:00
ms_memoryUsed + = ms_aInfoForModel [ streamId ] . GetCdSize ( ) * CDSTREAM_SECTOR_SIZE ;
2020-11-26 16:47:19 +01:00
# endif
2019-06-21 17:28:55 +02:00
}
endTime = CTimer : : GetCurrentTimeInCycles ( ) / CTimer : : GetCyclesPerMillisecond ( ) ;
timeDiff = endTime - startTime ;
2020-05-06 21:54:43 +02:00
if ( timeDiff > 5 )
debug ( " %s took %d ms \n " , GetObjectName ( streamId ) , timeDiff ) ;
2019-06-21 17:28:55 +02:00
return true ;
}
bool
CStreaming : : FinishLoadingLargeFile ( int8 * buf , int32 streamId )
{
RwMemory mem ;
RwStream * stream ;
uint32 startTime , endTime , timeDiff ;
CBaseModelInfo * mi ;
bool success ;
startTime = CTimer : : GetCurrentTimeInCycles ( ) / CTimer : : GetCyclesPerMillisecond ( ) ;
if ( ms_aInfoForModel [ streamId ] . m_loadState ! = STREAMSTATE_STARTED ) {
if ( streamId < STREAM_OFFSET_TXD )
2019-06-24 18:44:23 +02:00
CModelInfo : : GetModelInfo ( streamId ) - > RemoveRef ( ) ;
2019-06-21 17:28:55 +02:00
return false ;
}
mem . start = ( uint8 * ) buf ;
mem . length = ms_aInfoForModel [ streamId ] . GetCdSize ( ) * CDSTREAM_SECTOR_SIZE ;
stream = RwStreamOpen ( rwSTREAMMEMORY , rwSTREAMREAD , & mem ) ;
if ( streamId < STREAM_OFFSET_TXD ) {
// Model
2019-06-24 18:44:23 +02:00
mi = CModelInfo : : GetModelInfo ( streamId ) ;
2020-11-26 16:47:19 +01:00
PUSH_MEMID ( MEMID_STREAM_MODELS ) ;
2019-06-21 17:28:55 +02:00
CTxdStore : : SetCurrentTxd ( mi - > GetTxdSlot ( ) ) ;
success = CFileLoader : : FinishLoadClumpFile ( stream , streamId ) ;
2020-11-30 23:44:58 +01:00
if ( success ) {
# ifdef USE_CUSTOM_ALLOCATOR
RpClumpForAllAtomics ( ( RpClump * ) mi - > GetRwObject ( ) , RegisterAtomicMemPtrsCB , nil ) ;
# endif
2019-06-21 17:28:55 +02:00
success = AddToLoadedVehiclesList ( streamId ) ;
2020-11-30 23:44:58 +01:00
}
2020-11-26 16:47:19 +01:00
POP_MEMID ( ) ;
2019-06-21 17:28:55 +02:00
mi - > RemoveRef ( ) ;
CTxdStore : : RemoveRefWithoutDelete ( mi - > GetTxdSlot ( ) ) ;
2020-12-21 12:34:29 +01:00
# if GTA_VERSION > GTAVC_PS2
2020-05-08 20:56:42 +02:00
if ( mi - > GetAnimFileIndex ( ) ! = - 1 )
CAnimManager : : RemoveAnimBlockRefWithoutDelete ( mi - > GetAnimFileIndex ( ) ) ;
2020-12-21 12:34:29 +01:00
# endif
2020-05-06 21:54:43 +02:00
} else if ( streamId > = STREAM_OFFSET_TXD & & streamId < STREAM_OFFSET_COL ) {
2019-06-21 17:28:55 +02:00
// Txd
CTxdStore : : AddRef ( streamId - STREAM_OFFSET_TXD ) ;
2020-11-26 16:47:19 +01:00
PUSH_MEMID ( MEMID_STREAM_TEXUTRES ) ;
2019-06-21 17:28:55 +02:00
success = CTxdStore : : FinishLoadTxd ( streamId - STREAM_OFFSET_TXD , stream ) ;
2020-11-26 16:47:19 +01:00
POP_MEMID ( ) ;
2019-06-21 17:28:55 +02:00
CTxdStore : : RemoveRefWithoutDelete ( streamId - STREAM_OFFSET_TXD ) ;
2020-05-08 20:56:42 +02:00
} else {
assert ( 0 & & " invalid streamId " ) ;
2019-06-21 17:28:55 +02:00
}
RwStreamClose ( stream , & mem ) ;
2020-11-26 16:47:19 +01:00
2020-12-21 12:34:29 +01:00
ms_aInfoForModel [ streamId ] . m_loadState = STREAMSTATE_LOADED ;
2020-11-26 16:47:19 +01:00
# ifndef USE_CUSTOM_ALLOCATOR
2019-06-21 17:28:55 +02:00
ms_memoryUsed + = ms_aInfoForModel [ streamId ] . GetCdSize ( ) * CDSTREAM_SECTOR_SIZE ;
2020-11-26 16:47:19 +01:00
# endif
2019-06-21 17:28:55 +02:00
if ( ! success ) {
RemoveModel ( streamId ) ;
2019-06-24 18:44:23 +02:00
ReRequestModel ( streamId ) ;
2020-12-21 12:34:29 +01:00
UpdateMemoryUsed ( ) ;
2019-06-21 17:28:55 +02:00
return false ;
}
2020-12-21 12:34:29 +01:00
UpdateMemoryUsed ( ) ;
2019-06-21 17:28:55 +02:00
endTime = CTimer : : GetCurrentTimeInCycles ( ) / CTimer : : GetCyclesPerMillisecond ( ) ;
timeDiff = endTime - startTime ;
2020-05-06 21:54:43 +02:00
if ( timeDiff > 5 )
debug ( " %s took %d ms \n " , GetObjectName ( streamId ) , timeDiff ) ;
2019-06-21 17:28:55 +02:00
return true ;
}
void
CStreaming : : RequestModel ( int32 id , int32 flags )
{
CSimpleModelInfo * mi ;
if ( ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_INQUEUE ) {
// updgrade to priority
2019-06-26 16:49:32 +02:00
if ( flags & STREAMFLAGS_PRIORITY & & ! ms_aInfoForModel [ id ] . IsPriority ( ) ) {
2019-06-21 17:28:55 +02:00
ms_numPriorityRequests + + ;
ms_aInfoForModel [ id ] . m_flags | = STREAMFLAGS_PRIORITY ;
}
} else if ( ms_aInfoForModel [ id ] . m_loadState ! = STREAMSTATE_NOTLOADED ) {
flags & = ~ STREAMFLAGS_PRIORITY ;
}
ms_aInfoForModel [ id ] . m_flags | = flags ;
if ( ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_LOADED ) {
// Already loaded, only check changed flags
if ( ms_aInfoForModel [ id ] . m_flags & STREAMFLAGS_NOFADE & & id < STREAM_OFFSET_TXD ) {
2019-06-24 18:44:23 +02:00
mi = ( CSimpleModelInfo * ) CModelInfo : : GetModelInfo ( id ) ;
2019-06-21 17:28:55 +02:00
if ( mi - > IsSimple ( ) )
mi - > m_alpha = 255 ;
}
// reinsert into list
if ( ms_aInfoForModel [ id ] . m_next ) {
ms_aInfoForModel [ id ] . RemoveFromList ( ) ;
2020-05-06 21:54:43 +02:00
if ( CanRemoveModel ( id ) )
2019-06-21 17:28:55 +02:00
ms_aInfoForModel [ id ] . AddToList ( & ms_startLoadedList ) ;
}
} else if ( ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_NOTLOADED | |
ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_LOADED ) { // how can this be true again?
if ( ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_NOTLOADED ) {
2020-05-08 20:56:42 +02:00
if ( id < STREAM_OFFSET_TXD ) {
mi = ( CSimpleModelInfo * ) CModelInfo : : GetModelInfo ( id ) ;
RequestTxd ( mi - > GetTxdSlot ( ) , flags ) ;
int anim = mi - > GetAnimFileIndex ( ) ;
if ( anim ! = - 1 )
RequestAnim ( anim , STREAMFLAGS_DEPENDENCY ) ;
}
2019-06-21 17:28:55 +02:00
ms_aInfoForModel [ id ] . AddToList ( & ms_startRequestedList ) ;
ms_numModelsRequested + + ;
if ( flags & STREAMFLAGS_PRIORITY )
ms_numPriorityRequests + + ;
}
ms_aInfoForModel [ id ] . m_loadState = STREAMSTATE_INQUEUE ;
ms_aInfoForModel [ id ] . m_flags = flags ;
}
}
2020-05-05 17:04:43 +02:00
# define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE
2020-05-05 13:02:42 +02:00
2019-06-21 17:28:55 +02:00
void
CStreaming : : RequestBigBuildings ( eLevelName level )
{
int i , n ;
CBuilding * b ;
2019-10-16 23:53:25 +02:00
n = CPools : : GetBuildingPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
2019-06-21 17:28:55 +02:00
b = CPools : : GetBuildingPool ( ) - > GetSlot ( i ) ;
2020-12-27 17:26:30 +01:00
if ( b & & b - > bIsBIGBuilding
# ifdef NO_ISLAND_LOADING
& & ( ( ( FrontEndMenuManager . m_PrefsIslandLoading ! = CMenuManager : : ISLAND_LOADING_LOW ) & & ( b ! = pIslandLODmainlandEntity ) & &
( b ! = pIslandLODbeachEntity ) ) | |
( b - > m_level = = level ) )
# else
& & b - > m_level = = level
# endif
)
2020-05-05 17:04:43 +02:00
if ( ! b - > bStreamBIGBuilding )
2020-05-05 18:06:38 +02:00
RequestModel ( b - > GetModelIndex ( ) , BIGBUILDINGFLAGS ) ;
2019-06-21 17:28:55 +02:00
}
RequestIslands ( level ) ;
}
2020-05-05 17:04:43 +02:00
void
CStreaming : : RequestBigBuildings ( eLevelName level , const CVector & pos )
{
int i , n ;
CBuilding * b ;
n = CPools : : GetBuildingPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
b = CPools : : GetBuildingPool ( ) - > GetSlot ( i ) ;
2020-07-09 18:18:42 +02:00
if ( b & & b - > bIsBIGBuilding
2020-12-27 17:26:30 +01:00
# ifdef NO_ISLAND_LOADING
& & ( ( ( FrontEndMenuManager . m_PrefsIslandLoading ! = CMenuManager : : ISLAND_LOADING_LOW ) & & ( b ! = pIslandLODmainlandEntity ) & & ( b ! = pIslandLODbeachEntity )
) | | ( b - > m_level = = level ) )
# else
& & b - > m_level = = level
2020-07-09 18:18:42 +02:00
# endif
)
2020-05-05 17:04:43 +02:00
if ( b - > bStreamBIGBuilding ) {
2020-05-11 17:03:32 +02:00
if ( CRenderer : : ShouldModelBeStreamed ( b , pos ) )
2020-05-05 17:04:43 +02:00
RequestModel ( b - > GetModelIndex ( ) , 0 ) ;
} else
RequestModel ( b - > GetModelIndex ( ) , BIGBUILDINGFLAGS ) ;
}
RequestIslands ( level ) ;
}
void
CStreaming : : InstanceBigBuildings ( eLevelName level , const CVector & pos )
{
int i , n ;
CBuilding * b ;
n = CPools : : GetBuildingPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
b = CPools : : GetBuildingPool ( ) - > GetSlot ( i ) ;
if ( b & & b - > bIsBIGBuilding & & b - > m_level = = level & &
b - > bStreamBIGBuilding & & b - > m_rwObject = = nil )
2020-05-11 17:03:32 +02:00
if ( CRenderer : : ShouldModelBeStreamed ( b , pos ) )
2020-05-05 17:04:43 +02:00
b - > CreateRwObject ( ) ;
}
}
2020-05-08 20:56:42 +02:00
void
CStreaming : : InstanceLoadedModelsInSectorList ( CPtrList & list )
{
CPtrNode * node ;
CEntity * e ;
for ( node = list . first ; node ; node = node - > next ) {
e = ( CEntity * ) node - > item ;
if ( IsAreaVisible ( e - > m_area ) & & e - > m_rwObject = = nil )
e - > CreateRwObject ( ) ;
}
}
void
CStreaming : : InstanceLoadedModels ( const CVector & pos )
{
int minX = CWorld : : GetSectorIndexX ( pos . x - 80.0f ) ;
if ( minX < = 0 ) minX = 0 ;
int minY = CWorld : : GetSectorIndexY ( pos . y - 80.0f ) ;
if ( minY < = 0 ) minY = 0 ;
int maxX = CWorld : : GetSectorIndexX ( pos . x + 80.0f ) ;
if ( maxX > = NUMSECTORS_X ) maxX = NUMSECTORS_X - 1 ;
int maxY = CWorld : : GetSectorIndexY ( pos . y + 80.0f ) ;
if ( maxY > = NUMSECTORS_Y ) maxY = NUMSECTORS_Y - 1 ;
int x , y ;
for ( y = minY ; y < = maxY ; y + + ) {
for ( x = minX ; x < = maxX ; x + + ) {
CSector * sector = CWorld : : GetSector ( x , y ) ;
InstanceLoadedModelsInSectorList ( sector - > m_lists [ ENTITYLIST_BUILDINGS ] ) ;
InstanceLoadedModelsInSectorList ( sector - > m_lists [ ENTITYLIST_BUILDINGS_OVERLAP ] ) ;
InstanceLoadedModelsInSectorList ( sector - > m_lists [ ENTITYLIST_OBJECTS ] ) ;
InstanceLoadedModelsInSectorList ( sector - > m_lists [ ENTITYLIST_DUMMIES ] ) ;
}
}
}
2020-05-06 21:54:43 +02:00
2019-06-21 17:28:55 +02:00
void
CStreaming : : RequestIslands ( eLevelName level )
{
2020-12-27 17:26:30 +01:00
ISLAND_LOADING_ISNT ( HIGH )
2019-06-21 17:28:55 +02:00
switch ( level ) {
2020-05-05 23:27:43 +02:00
case LEVEL_MAINLAND :
if ( islandLODbeach ! = - 1 )
RequestModel ( islandLODbeach , BIGBUILDINGFLAGS ) ;
2019-06-21 17:28:55 +02:00
break ;
2020-05-05 23:27:43 +02:00
case LEVEL_BEACH :
if ( islandLODmainland ! = - 1 )
RequestModel ( islandLODmainland , BIGBUILDINGFLAGS ) ;
2019-06-21 17:28:55 +02:00
break ;
2020-05-12 01:24:57 +02:00
default : break ;
2019-06-21 17:28:55 +02:00
}
}
2020-08-20 23:43:13 +02:00
static char * IGnames [ ] = {
" player " ,
" player2 " ,
" player3 " ,
" player4 " ,
" player5 " ,
" player6 " ,
" player7 " ,
" player8 " ,
" player9 " ,
" play10 " ,
" play11 " ,
" igken " ,
" igcandy " ,
" igsonny " ,
" igbuddy " ,
" igjezz " ,
" ighlary " ,
" igphil " ,
" igmerc " ,
" igdick " ,
" igdiaz " ,
" "
} ;
static char * CSnames [ ] = {
" csplay " ,
" csplay2 " ,
" csplay3 " ,
" csplay4 " ,
" csplay5 " ,
" csplay6 " ,
" csplay7 " ,
" csplay8 " ,
" csplay9 " ,
" csplay10 " ,
" csplay11 " ,
" csken " ,
" cscandy " ,
" cssonny " ,
" csbuddy " ,
" csjezz " ,
" cshlary " ,
" csphil " ,
" csmerc " ,
" csdick " ,
" csdiaz " ,
" "
} ;
2019-06-21 17:28:55 +02:00
void
CStreaming : : RequestSpecialModel ( int32 modelId , const char * modelName , int32 flags )
{
CBaseModelInfo * mi ;
int txdId ;
char oldName [ 48 ] ;
uint32 pos , size ;
2020-08-20 23:43:13 +02:00
int i , n ;
2019-06-21 17:28:55 +02:00
mi = CModelInfo : : GetModelInfo ( modelId ) ;
2020-10-17 17:26:48 +02:00
if ( strncasecmp ( " CSPlay " , modelName , 6 ) = = 0 ) {
2021-01-08 20:53:11 +01:00
char * curname = CModelInfo : : GetModelInfo ( MI_PLAYER ) - > GetModelName ( ) ;
2020-08-20 23:43:13 +02:00
for ( int i = 0 ; CSnames [ i ] [ 0 ] ; i + + ) {
if ( strcasecmp ( curname , IGnames [ i ] ) = = 0 ) {
modelName = CSnames [ i ] ;
break ;
}
}
}
2021-01-08 20:53:11 +01:00
if ( ! CGeneral : : faststrcmp ( mi - > GetModelName ( ) , modelName ) ) {
2019-06-21 17:28:55 +02:00
// Already have the correct name, just request it
RequestModel ( modelId , flags ) ;
return ;
}
2020-08-20 23:43:13 +02:00
if ( mi - > GetNumRefs ( ) > 0 ) {
n = CPools : : GetPedPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 & & mi - > GetNumRefs ( ) > 0 ; i - - ) {
CPed * ped = CPools : : GetPedPool ( ) - > GetSlot ( i ) ;
if ( ped & & ped - > GetModelIndex ( ) = = modelId & &
! ped - > IsPlayer ( ) & & ped - > CanBeDeletedEvenInVehicle ( ) )
CTheScripts : : RemoveThisPed ( ped ) ;
}
n = CPools : : GetObjectPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 & & mi - > GetNumRefs ( ) > 0 ; i - - ) {
CObject * obj = CPools : : GetObjectPool ( ) - > GetSlot ( i ) ;
if ( obj & & obj - > GetModelIndex ( ) = = modelId & & obj - > CanBeDeleted ( ) ) {
CWorld : : Remove ( obj ) ;
CWorld : : RemoveReferencesToDeletedObject ( obj ) ;
delete obj ;
}
}
}
2021-01-08 20:53:11 +01:00
strcpy ( oldName , mi - > GetModelName ( ) ) ;
mi - > SetModelName ( modelName ) ;
2019-06-21 17:28:55 +02:00
// What exactly is going on here?
if ( CModelInfo : : GetModelInfo ( oldName , nil ) ) {
txdId = CTxdStore : : FindTxdSlot ( oldName ) ;
if ( txdId ! = - 1 & & CTxdStore : : GetSlot ( txdId ) - > texDict ) {
CTxdStore : : AddRef ( txdId ) ;
RemoveModel ( modelId ) ;
CTxdStore : : RemoveRefWithoutDelete ( txdId ) ;
} else
RemoveModel ( modelId ) ;
} else
RemoveModel ( modelId ) ;
2020-04-25 00:40:14 +02:00
bool found = ms_pExtraObjectsDir - > FindItem ( modelName , pos , size ) ;
assert ( found ) ;
2019-06-21 17:28:55 +02:00
mi - > ClearTexDictionary ( ) ;
if ( CTxdStore : : FindTxdSlot ( modelName ) = = - 1 )
mi - > SetTexDictionary ( " generic " ) ;
else
mi - > SetTexDictionary ( modelName ) ;
ms_aInfoForModel [ modelId ] . SetCdPosnAndSize ( pos , size ) ;
RequestModel ( modelId , flags ) ;
}
void
CStreaming : : RequestSpecialChar ( int32 charId , const char * modelName , int32 flags )
{
RequestSpecialModel ( charId + MI_SPECIAL01 , modelName , flags ) ;
}
2019-06-28 12:34:02 +02:00
bool
CStreaming : : HasSpecialCharLoaded ( int32 id )
{
return HasModelLoaded ( id + MI_SPECIAL01 ) ;
}
void
CStreaming : : SetMissionDoesntRequireSpecialChar ( int32 id )
{
return SetMissionDoesntRequireModel ( id + MI_SPECIAL01 ) ;
}
2019-06-26 16:49:32 +02:00
void
CStreaming : : DecrementRef ( int32 id )
{
ms_numModelsRequested - - ;
if ( ms_aInfoForModel [ id ] . IsPriority ( ) ) {
ms_aInfoForModel [ id ] . m_flags & = ~ STREAMFLAGS_PRIORITY ;
ms_numPriorityRequests - - ;
}
}
2019-06-21 17:28:55 +02:00
void
CStreaming : : RemoveModel ( int32 id )
{
int i ;
if ( ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_NOTLOADED )
return ;
if ( ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_LOADED ) {
2020-05-05 17:04:43 +02:00
if ( id < STREAM_OFFSET_TXD )
CModelInfo : : GetModelInfo ( id ) - > DeleteRwObject ( ) ;
else if ( id > = STREAM_OFFSET_TXD & & id < STREAM_OFFSET_COL )
CTxdStore : : RemoveTxd ( id - STREAM_OFFSET_TXD ) ;
2020-05-08 15:59:57 +02:00
else if ( id > = STREAM_OFFSET_COL & & id < STREAM_OFFSET_ANIM )
2020-05-05 17:04:43 +02:00
CColStore : : RemoveCol ( id - STREAM_OFFSET_COL ) ;
2020-05-08 20:56:42 +02:00
else if ( id > = STREAM_OFFSET_ANIM ) {
assert ( id < NUMSTREAMINFO ) ;
CAnimManager : : RemoveAnimBlock ( id - STREAM_OFFSET_ANIM ) ;
}
2019-06-21 17:28:55 +02:00
ms_memoryUsed - = ms_aInfoForModel [ id ] . GetCdSize ( ) * CDSTREAM_SECTOR_SIZE ;
}
if ( ms_aInfoForModel [ id ] . m_next ) {
// Remove from list, model is neither loaded nor requested
2019-06-26 16:49:32 +02:00
if ( ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_INQUEUE )
DecrementRef ( id ) ;
2019-06-21 17:28:55 +02:00
ms_aInfoForModel [ id ] . RemoveFromList ( ) ;
} else if ( ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_READING ) {
for ( i = 0 ; i < 4 ; i + + ) {
2019-06-24 18:44:23 +02:00
if ( ms_channel [ 0 ] . streamIds [ i ] = = id )
ms_channel [ 0 ] . streamIds [ i ] = - 1 ;
if ( ms_channel [ 1 ] . streamIds [ i ] = = id )
ms_channel [ 1 ] . streamIds [ i ] = - 1 ;
2019-06-21 17:28:55 +02:00
}
}
if ( ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_STARTED ) {
2020-05-05 17:04:43 +02:00
if ( id < STREAM_OFFSET_TXD )
RpClumpGtaCancelStream ( ) ;
else if ( id > = STREAM_OFFSET_TXD & & id < STREAM_OFFSET_COL )
CTxdStore : : RemoveTxd ( id - STREAM_OFFSET_TXD ) ;
2020-05-08 15:59:57 +02:00
else if ( id > = STREAM_OFFSET_COL & & id < STREAM_OFFSET_ANIM )
2020-05-05 17:04:43 +02:00
CColStore : : RemoveCol ( id - STREAM_OFFSET_COL ) ;
2020-05-08 20:56:42 +02:00
else if ( id > = STREAM_OFFSET_ANIM ) {
assert ( id < NUMSTREAMINFO ) ;
CAnimManager : : RemoveAnimBlock ( id - STREAM_OFFSET_ANIM ) ;
}
2019-06-21 17:28:55 +02:00
}
ms_aInfoForModel [ id ] . m_loadState = STREAMSTATE_NOTLOADED ;
}
2019-06-24 18:44:23 +02:00
void
CStreaming : : RemoveUnusedBuildings ( eLevelName level )
{
2020-05-05 23:27:43 +02:00
if ( level ! = LEVEL_BEACH )
RemoveBuildings ( LEVEL_BEACH ) ;
if ( level ! = LEVEL_MAINLAND )
RemoveBuildings ( LEVEL_MAINLAND ) ;
2019-06-24 18:44:23 +02:00
}
void
CStreaming : : RemoveBuildings ( eLevelName level )
{
int i , n ;
CEntity * e ;
CBaseModelInfo * mi ;
2019-10-16 23:53:25 +02:00
n = CPools : : GetBuildingPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
2019-06-24 18:44:23 +02:00
e = CPools : : GetBuildingPool ( ) - > GetSlot ( i ) ;
if ( e & & e - > m_level = = level ) {
mi = CModelInfo : : GetModelInfo ( e - > GetModelIndex ( ) ) ;
if ( ! e - > bImBeingRendered ) {
e - > DeleteRwObject ( ) ;
2020-05-05 14:06:55 +02:00
if ( mi - > GetNumRefs ( ) = = 0 )
2019-06-24 18:44:23 +02:00
RemoveModel ( e - > GetModelIndex ( ) ) ;
}
}
}
2019-10-16 23:53:25 +02:00
n = CPools : : GetTreadablePool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
2019-06-24 18:44:23 +02:00
e = CPools : : GetTreadablePool ( ) - > GetSlot ( i ) ;
if ( e & & e - > m_level = = level ) {
mi = CModelInfo : : GetModelInfo ( e - > GetModelIndex ( ) ) ;
if ( ! e - > bImBeingRendered ) {
e - > DeleteRwObject ( ) ;
2020-05-05 14:06:55 +02:00
if ( mi - > GetNumRefs ( ) = = 0 )
2019-06-24 18:44:23 +02:00
RemoveModel ( e - > GetModelIndex ( ) ) ;
}
}
}
2019-10-16 23:53:25 +02:00
n = CPools : : GetObjectPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
2019-06-24 18:44:23 +02:00
e = CPools : : GetObjectPool ( ) - > GetSlot ( i ) ;
if ( e & & e - > m_level = = level ) {
mi = CModelInfo : : GetModelInfo ( e - > GetModelIndex ( ) ) ;
if ( ! e - > bImBeingRendered & & ( ( CObject * ) e ) - > ObjectCreatedBy = = GAME_OBJECT ) {
e - > DeleteRwObject ( ) ;
2020-05-05 14:06:55 +02:00
if ( mi - > GetNumRefs ( ) = = 0 )
2019-06-24 18:44:23 +02:00
RemoveModel ( e - > GetModelIndex ( ) ) ;
}
}
}
2019-10-16 23:53:25 +02:00
n = CPools : : GetDummyPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
2019-06-24 18:44:23 +02:00
e = CPools : : GetDummyPool ( ) - > GetSlot ( i ) ;
if ( e & & e - > m_level = = level ) {
mi = CModelInfo : : GetModelInfo ( e - > GetModelIndex ( ) ) ;
if ( ! e - > bImBeingRendered ) {
e - > DeleteRwObject ( ) ;
2020-05-05 14:06:55 +02:00
if ( mi - > GetNumRefs ( ) = = 0 )
2019-06-24 18:44:23 +02:00
RemoveModel ( e - > GetModelIndex ( ) ) ;
}
}
}
}
2020-08-20 23:43:13 +02:00
void
CStreaming : : RemoveBuildingsNotInArea ( int32 area )
{
int i , n ;
CEntity * e ;
n = CPools : : GetBuildingPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
e = CPools : : GetBuildingPool ( ) - > GetSlot ( i ) ;
if ( e & & e - > m_rwObject & & ! IsAreaVisible ( area ) & &
( ! e - > bIsBIGBuilding | | e - > bStreamBIGBuilding ) ) {
if ( e - > bIsBIGBuilding )
RequestModel ( e - > GetModelIndex ( ) , 0 ) ;
if ( ! e - > bImBeingRendered )
e - > DeleteRwObject ( ) ;
}
}
n = CPools : : GetTreadablePool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
e = CPools : : GetTreadablePool ( ) - > GetSlot ( i ) ;
if ( e & & e - > m_rwObject & & ! IsAreaVisible ( area ) & &
( ! e - > bIsBIGBuilding | | e - > bStreamBIGBuilding ) ) {
if ( e - > bIsBIGBuilding )
RequestModel ( e - > GetModelIndex ( ) , 0 ) ;
if ( ! e - > bImBeingRendered )
e - > DeleteRwObject ( ) ;
}
}
n = CPools : : GetObjectPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
e = CPools : : GetObjectPool ( ) - > GetSlot ( i ) ;
if ( e & & e - > m_rwObject & & ! IsAreaVisible ( area ) & &
( ! e - > bIsBIGBuilding | | e - > bStreamBIGBuilding ) ) {
if ( e - > bIsBIGBuilding )
RequestModel ( e - > GetModelIndex ( ) , 0 ) ;
if ( ! e - > bImBeingRendered )
e - > DeleteRwObject ( ) ;
}
}
n = CPools : : GetDummyPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
e = CPools : : GetDummyPool ( ) - > GetSlot ( i ) ;
if ( e & & e - > m_rwObject & & ! IsAreaVisible ( area ) & &
( ! e - > bIsBIGBuilding | | e - > bStreamBIGBuilding ) ) {
if ( e - > bIsBIGBuilding )
RequestModel ( e - > GetModelIndex ( ) , 0 ) ;
if ( ! e - > bImBeingRendered )
e - > DeleteRwObject ( ) ;
}
}
}
2019-06-24 18:44:23 +02:00
void
CStreaming : : RemoveUnusedBigBuildings ( eLevelName level )
{
2020-12-27 17:26:30 +01:00
ISLAND_LOADING_IS ( LOW )
{
2020-05-05 23:27:43 +02:00
if ( level ! = LEVEL_BEACH )
RemoveBigBuildings ( LEVEL_BEACH ) ;
if ( level ! = LEVEL_MAINLAND )
RemoveBigBuildings ( LEVEL_MAINLAND ) ;
2020-12-27 17:26:30 +01:00
}
2019-06-24 18:44:23 +02:00
RemoveIslandsNotUsed ( level ) ;
}
void
DeleteIsland ( CEntity * island )
{
if ( island = = nil )
return ;
if ( island - > bImBeingRendered )
debug ( " Didn't delete island because it was being rendered \n " ) ;
else {
island - > DeleteRwObject ( ) ;
CStreaming : : RemoveModel ( island - > GetModelIndex ( ) ) ;
}
}
void
CStreaming : : RemoveIslandsNotUsed ( eLevelName level )
{
2020-05-05 17:04:43 +02:00
int i ;
2020-05-05 23:27:43 +02:00
if ( pIslandLODmainlandEntity = = nil )
2020-05-05 17:04:43 +02:00
for ( i = CPools : : GetBuildingPool ( ) - > GetSize ( ) - 1 ; i > = 0 ; i - - ) {
CBuilding * building = CPools : : GetBuildingPool ( ) - > GetSlot ( i ) ;
if ( building = = nil )
continue ;
2020-05-05 23:27:43 +02:00
if ( building - > GetModelIndex ( ) = = islandLODmainland )
pIslandLODmainlandEntity = building ;
if ( building - > GetModelIndex ( ) = = islandLODbeach )
pIslandLODbeachEntity = building ;
2020-05-05 17:04:43 +02:00
}
2020-12-27 17:26:30 +01:00
# ifdef NO_ISLAND_LOADING
if ( FrontEndMenuManager . m_PrefsIslandLoading = = CMenuManager : : ISLAND_LOADING_HIGH ) {
DeleteIsland ( pIslandLODmainlandEntity ) ;
DeleteIsland ( pIslandLODbeachEntity ) ;
} else
# endif
2019-06-24 18:44:23 +02:00
switch ( level ) {
2020-05-05 23:27:43 +02:00
case LEVEL_MAINLAND :
DeleteIsland ( pIslandLODmainlandEntity ) ;
2019-06-24 18:44:23 +02:00
break ;
2020-05-05 23:27:43 +02:00
case LEVEL_BEACH :
DeleteIsland ( pIslandLODbeachEntity ) ;
2020-07-13 17:10:17 +02:00
2019-06-24 18:44:23 +02:00
break ;
}
}
void
CStreaming : : RemoveBigBuildings ( eLevelName level )
{
int i , n ;
CEntity * e ;
CBaseModelInfo * mi ;
2019-10-16 23:53:25 +02:00
n = CPools : : GetBuildingPool ( ) - > GetSize ( ) - 1 ;
for ( i = n ; i > = 0 ; i - - ) {
2019-06-24 18:44:23 +02:00
e = CPools : : GetBuildingPool ( ) - > GetSlot ( i ) ;
if ( e & & e - > bIsBIGBuilding & & e - > m_level = = level ) {
mi = CModelInfo : : GetModelInfo ( e - > GetModelIndex ( ) ) ;
if ( ! e - > bImBeingRendered ) {
e - > DeleteRwObject ( ) ;
2020-05-05 14:06:55 +02:00
if ( mi - > GetNumRefs ( ) = = 0 )
2019-06-24 18:44:23 +02:00
RemoveModel ( e - > GetModelIndex ( ) ) ;
}
}
}
}
bool
CStreaming : : RemoveLoadedVehicle ( void )
{
int i , id ;
for ( i = 0 ; i < MAXVEHICLESLOADED ; i + + ) {
ms_lastVehicleDeleted + + ;
if ( ms_lastVehicleDeleted = = MAXVEHICLESLOADED )
ms_lastVehicleDeleted = 0 ;
id = ms_vehiclesLoaded [ ms_lastVehicleDeleted ] ;
2020-05-06 21:54:43 +02:00
if ( id ! = - 1 & & CanRemoveModel ( id ) & & CModelInfo : : GetModelInfo ( id ) - > GetNumRefs ( ) = = 0 & &
2019-06-24 18:44:23 +02:00
ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_LOADED )
goto found ;
}
return false ;
found :
RemoveModel ( ms_vehiclesLoaded [ ms_lastVehicleDeleted ] ) ;
ms_numVehiclesLoaded - - ;
ms_vehiclesLoaded [ ms_lastVehicleDeleted ] = - 1 ;
2020-05-08 10:11:09 +02:00
CVehicleModelInfo * pVehicleInfo = ( CVehicleModelInfo * ) CModelInfo : : GetModelInfo ( id ) ;
if ( pVehicleInfo - > m_vehicleClass ! = - 1 )
CCarCtrl : : RemoveFromLoadedVehicleArray ( id , pVehicleInfo - > m_vehicleClass ) ;
2019-06-24 18:44:23 +02:00
return true ;
}
bool
2020-05-06 21:54:43 +02:00
CStreaming : : RemoveLeastUsedModel ( uint32 excludeMask )
2019-06-24 18:44:23 +02:00
{
CStreamingInfo * si ;
int streamId ;
for ( si = ms_endLoadedList . m_prev ; si ! = & ms_startLoadedList ; si = si - > m_prev ) {
2020-05-06 21:54:43 +02:00
if ( si - > m_flags & excludeMask )
continue ;
2019-06-24 18:44:23 +02:00
streamId = si - ms_aInfoForModel ;
if ( streamId < STREAM_OFFSET_TXD ) {
2020-05-05 14:06:55 +02:00
if ( CModelInfo : : GetModelInfo ( streamId ) - > GetNumRefs ( ) = = 0 ) {
2019-06-24 18:44:23 +02:00
RemoveModel ( streamId ) ;
return true ;
}
2020-05-06 21:54:43 +02:00
} else if ( streamId > = STREAM_OFFSET_TXD & & streamId < STREAM_OFFSET_COL ) {
2019-06-26 21:33:58 +02:00
if ( CTxdStore : : GetNumRefs ( streamId - STREAM_OFFSET_TXD ) = = 0 & &
! IsTxdUsedByRequestedModels ( streamId - STREAM_OFFSET_TXD ) ) {
2019-06-24 18:44:23 +02:00
RemoveModel ( streamId ) ;
return true ;
}
2020-05-08 20:56:42 +02:00
} else if ( streamId > = STREAM_OFFSET_ANIM ) {
assert ( streamId < NUMSTREAMINFO ) ;
if ( CAnimManager : : GetNumRefsToAnimBlock ( streamId - STREAM_OFFSET_ANIM ) = = 0 & &
! AreAnimsUsedByRequestedModels ( streamId - STREAM_OFFSET_ANIM ) ) {
RemoveModel ( streamId ) ;
return true ;
}
2019-06-24 18:44:23 +02:00
}
}
2020-05-06 21:54:43 +02:00
return ( ms_numVehiclesLoaded > 7 | | CGame : : currArea ! = AREA_MAIN_MAP & & ms_numVehiclesLoaded > 4 ) & & RemoveLoadedVehicle ( ) ;
2019-06-24 18:44:23 +02:00
}
void
CStreaming : : RemoveAllUnusedModels ( void )
{
int i ;
for ( i = 0 ; i < MAXVEHICLESLOADED ; i + + )
RemoveLoadedVehicle ( ) ;
2019-10-06 23:39:25 +02:00
for ( i = NUM_DEFAULT_MODELS ; i < MODELINFOSIZE ; i + + ) {
2019-06-24 18:44:23 +02:00
if ( ms_aInfoForModel [ i ] . m_loadState = = STREAMSTATE_LOADED & &
2020-05-05 14:06:55 +02:00
CModelInfo : : GetModelInfo ( i ) - > GetNumRefs ( ) = = 0 ) {
2019-06-24 18:44:23 +02:00
RemoveModel ( i ) ;
ms_aInfoForModel [ i ] . m_loadState = STREAMSTATE_NOTLOADED ;
}
}
}
void
CStreaming : : RemoveUnusedModelsInLoadedList ( void )
{
// empty
}
2020-08-20 23:43:13 +02:00
bool
CStreaming : : RemoveLoadedZoneModel ( void )
{
int i ;
if ( ms_currentPedGrp = = - 1 )
return false ;
for ( i = 0 ; i < NUMMODELSPERPEDGROUP ; i + + ) {
int mi = CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ i ] ;
if ( mi ! = - 1 & & ms_bIsPedFromPedGroupLoaded [ i ] & &
HasModelLoaded ( mi ) & & CanRemoveModel ( mi ) & &
CModelInfo : : GetModelInfo ( mi ) - > GetNumRefs ( ) = = 0 ) {
RemoveModel ( CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ i ] ) ;
ms_numPedsLoaded - - ;
ms_bIsPedFromPedGroupLoaded [ i ] = false ;
return true ;
}
}
return false ;
}
2019-06-24 18:44:23 +02:00
bool
CStreaming : : IsTxdUsedByRequestedModels ( int32 txdId )
{
CStreamingInfo * si ;
int streamId ;
int i ;
2019-06-26 21:46:55 +02:00
for ( si = ms_startRequestedList . m_next ; si ! = & ms_endRequestedList ; si = si - > m_next ) {
2019-06-24 18:44:23 +02:00
streamId = si - ms_aInfoForModel ;
if ( streamId < STREAM_OFFSET_TXD & &
CModelInfo : : GetModelInfo ( streamId ) - > GetTxdSlot ( ) = = txdId )
return true ;
}
for ( i = 0 ; i < 4 ; i + + ) {
streamId = ms_channel [ 0 ] . streamIds [ i ] ;
if ( streamId ! = - 1 & & streamId < STREAM_OFFSET_TXD & &
CModelInfo : : GetModelInfo ( streamId ) - > GetTxdSlot ( ) = = txdId )
return true ;
streamId = ms_channel [ 1 ] . streamIds [ i ] ;
if ( streamId ! = - 1 & & streamId < STREAM_OFFSET_TXD & &
CModelInfo : : GetModelInfo ( streamId ) - > GetTxdSlot ( ) = = txdId )
return true ;
}
return false ;
}
2020-05-08 20:56:42 +02:00
bool
CStreaming : : AreAnimsUsedByRequestedModels ( int32 animId )
{
CStreamingInfo * si ;
int streamId ;
int i ;
for ( si = ms_startRequestedList . m_next ; si ! = & ms_endRequestedList ; si = si - > m_next ) {
streamId = si - ms_aInfoForModel ;
if ( streamId < STREAM_OFFSET_TXD & &
CModelInfo : : GetModelInfo ( streamId ) - > GetAnimFileIndex ( ) = = animId )
return true ;
}
for ( i = 0 ; i < 4 ; i + + ) {
streamId = ms_channel [ 0 ] . streamIds [ i ] ;
if ( streamId ! = - 1 & & streamId < STREAM_OFFSET_TXD & &
CModelInfo : : GetModelInfo ( streamId ) - > GetAnimFileIndex ( ) = = animId )
return true ;
streamId = ms_channel [ 1 ] . streamIds [ i ] ;
if ( streamId ! = - 1 & & streamId < STREAM_OFFSET_TXD & &
CModelInfo : : GetModelInfo ( streamId ) - > GetAnimFileIndex ( ) = = animId )
return true ;
}
return false ;
}
2019-06-24 18:44:23 +02:00
int32
CStreaming : : GetAvailableVehicleSlot ( void )
{
int i ;
for ( i = 0 ; i < MAXVEHICLESLOADED ; i + + )
if ( ms_vehiclesLoaded [ i ] = = - 1 )
return i ;
return - 1 ;
}
bool
CStreaming : : AddToLoadedVehiclesList ( int32 modelId )
{
int i ;
int id ;
if ( ms_numVehiclesLoaded < desiredNumVehiclesLoaded ) {
// still room for vehicles
for ( i = 0 ; i < MAXVEHICLESLOADED ; i + + ) {
if ( ms_vehiclesLoaded [ ms_lastVehicleDeleted ] = = - 1 )
break ;
ms_lastVehicleDeleted + + ;
if ( ms_lastVehicleDeleted = = MAXVEHICLESLOADED )
ms_lastVehicleDeleted = 0 ;
}
assert ( ms_vehiclesLoaded [ ms_lastVehicleDeleted ] = = - 1 ) ;
ms_numVehiclesLoaded + + ;
} else {
// find vehicle we can remove
for ( i = 0 ; i < MAXVEHICLESLOADED ; i + + ) {
id = ms_vehiclesLoaded [ ms_lastVehicleDeleted ] ;
2020-05-06 21:54:43 +02:00
if ( id ! = - 1 & & CanRemoveModel ( id ) & &
CModelInfo : : GetModelInfo ( id ) - > GetNumRefs ( ) = = 0 )
2019-06-24 18:44:23 +02:00
goto found ;
ms_lastVehicleDeleted + + ;
if ( ms_lastVehicleDeleted = = MAXVEHICLESLOADED )
ms_lastVehicleDeleted = 0 ;
}
id = - 1 ;
found :
if ( id = = - 1 ) {
// didn't find anything, try a free slot
id = GetAvailableVehicleSlot ( ) ;
if ( id = = - 1 )
return false ; // still no luck
ms_lastVehicleDeleted = id ;
2020-08-20 23:43:13 +02:00
// this is more than we wanted actually
2019-06-24 18:44:23 +02:00
ms_numVehiclesLoaded + + ;
2020-05-08 10:11:09 +02:00
}
else {
2019-06-24 18:44:23 +02:00
RemoveModel ( id ) ;
2020-05-08 16:05:54 +02:00
CVehicleModelInfo * pVehicleInfo = ( CVehicleModelInfo * ) CModelInfo : : GetModelInfo ( id ) ;
2020-05-08 10:11:09 +02:00
if ( pVehicleInfo - > m_vehicleClass ! = - 1 )
2020-05-08 16:05:54 +02:00
CCarCtrl : : RemoveFromLoadedVehicleArray ( id , pVehicleInfo - > m_vehicleClass ) ;
2020-05-08 10:11:09 +02:00
}
2019-06-24 18:44:23 +02:00
}
ms_vehiclesLoaded [ ms_lastVehicleDeleted + + ] = modelId ;
if ( ms_lastVehicleDeleted = = MAXVEHICLESLOADED )
ms_lastVehicleDeleted = 0 ;
2020-05-08 10:11:09 +02:00
CVehicleModelInfo * pVehicleInfo = ( CVehicleModelInfo * ) CModelInfo : : GetModelInfo ( modelId ) ;
if ( pVehicleInfo - > m_vehicleClass ! = - 1 )
CCarCtrl : : AddToLoadedVehicleArray ( modelId , pVehicleInfo - > m_vehicleClass , pVehicleInfo - > m_frequency ) ;
2019-06-24 18:44:23 +02:00
return true ;
}
bool
CStreaming : : IsObjectInCdImage ( int32 id )
{
uint32 posn , size ;
return ms_aInfoForModel [ id ] . GetCdPosnAndSize ( posn , size ) ;
}
void
CStreaming : : SetModelIsDeletable ( int32 id )
{
ms_aInfoForModel [ id ] . m_flags & = ~ STREAMFLAGS_DONT_REMOVE ;
2020-08-20 23:43:13 +02:00
if ( ( id > = STREAM_OFFSET_TXD & & id < STREAM_OFFSET_COL | | CModelInfo : : GetModelInfo ( id ) - > GetModelType ( ) ! = MITYPE_VEHICLE ) & &
2019-06-26 21:33:58 +02:00
( ms_aInfoForModel [ id ] . m_flags & STREAMFLAGS_SCRIPTOWNED ) = = 0 ) {
2019-06-24 18:44:23 +02:00
if ( ms_aInfoForModel [ id ] . m_loadState ! = STREAMSTATE_LOADED )
RemoveModel ( id ) ;
else if ( ms_aInfoForModel [ id ] . m_next = = nil )
ms_aInfoForModel [ id ] . AddToList ( & ms_startLoadedList ) ;
}
}
void
CStreaming : : SetModelTxdIsDeletable ( int32 id )
{
SetModelIsDeletable ( CModelInfo : : GetModelInfo ( id ) - > GetTxdSlot ( ) + STREAM_OFFSET_TXD ) ;
}
void
CStreaming : : SetMissionDoesntRequireModel ( int32 id )
{
ms_aInfoForModel [ id ] . m_flags & = ~ STREAMFLAGS_SCRIPTOWNED ;
2020-05-05 14:06:55 +02:00
if ( ( id > = STREAM_OFFSET_TXD | | CModelInfo : : GetModelInfo ( id ) - > GetModelType ( ) ! = MITYPE_VEHICLE ) & &
2019-06-26 21:33:58 +02:00
( ms_aInfoForModel [ id ] . m_flags & STREAMFLAGS_DONT_REMOVE ) = = 0 ) {
2019-06-24 18:44:23 +02:00
if ( ms_aInfoForModel [ id ] . m_loadState ! = STREAMSTATE_LOADED )
RemoveModel ( id ) ;
else if ( ms_aInfoForModel [ id ] . m_next = = nil )
ms_aInfoForModel [ id ] . AddToList ( & ms_startLoadedList ) ;
}
}
void
CStreaming : : LoadInitialPeds ( void )
{
RequestModel ( MI_COP , STREAMFLAGS_DONT_REMOVE ) ;
RequestModel ( MI_MALE01 , STREAMFLAGS_DONT_REMOVE ) ;
RequestModel ( MI_TAXI_D , STREAMFLAGS_DONT_REMOVE ) ;
2020-05-15 16:30:25 +02:00
}
2020-05-10 19:09:49 +02:00
2020-05-15 16:30:25 +02:00
void
CStreaming : : LoadInitialWeapons ( void )
{
2020-05-19 16:39:19 +02:00
CStreaming : : RequestModel ( MI_NIGHTSTICK , STREAMFLAGS_DONT_REMOVE ) ;
2020-05-15 16:30:25 +02:00
CStreaming : : RequestModel ( MI_MISSILE , STREAMFLAGS_DONT_REMOVE ) ;
2019-06-24 18:44:23 +02:00
}
void
CStreaming : : LoadInitialVehicles ( void )
{
ms_numVehiclesLoaded = 0 ;
ms_lastVehicleDeleted = 0 ;
2020-08-20 23:43:13 +02:00
RequestModel ( MI_POLICE , STREAMFLAGS_DONT_REMOVE ) ;
2019-06-24 18:44:23 +02:00
}
2019-06-28 12:34:02 +02:00
void
CStreaming : : StreamVehiclesAndPeds ( void )
{
int i , model ;
static int timeBeforeNextLoad = 0 ;
static int modelQualityClass = 0 ;
2020-04-10 10:03:38 +02:00
if ( CRecordDataForGame : : IsRecording ( ) | |
2020-04-18 22:50:37 +02:00
CRecordDataForGame : : IsPlayingBack ( )
# ifdef FIX_BUGS
| | CReplay : : IsPlayingBack ( )
# endif
)
2019-06-28 12:34:02 +02:00
return ;
if ( FindPlayerPed ( ) - > m_pWanted - > AreSwatRequired ( ) ) {
RequestModel ( MI_ENFORCER , STREAMFLAGS_DONT_REMOVE ) ;
RequestModel ( MI_SWAT , STREAMFLAGS_DONT_REMOVE ) ;
} else {
SetModelIsDeletable ( MI_ENFORCER ) ;
if ( ! HasModelLoaded ( MI_ENFORCER ) )
SetModelIsDeletable ( MI_SWAT ) ;
}
if ( FindPlayerPed ( ) - > m_pWanted - > AreFbiRequired ( ) ) {
2020-07-08 16:26:23 +02:00
RequestModel ( MI_FBIRANCH , STREAMFLAGS_DONT_REMOVE ) ;
2019-06-28 12:34:02 +02:00
RequestModel ( MI_FBI , STREAMFLAGS_DONT_REMOVE ) ;
} else {
2020-07-08 16:26:23 +02:00
SetModelIsDeletable ( MI_FBIRANCH ) ;
if ( ! HasModelLoaded ( MI_FBIRANCH ) )
2019-06-28 12:34:02 +02:00
SetModelIsDeletable ( MI_FBI ) ;
}
if ( FindPlayerPed ( ) - > m_pWanted - > AreArmyRequired ( ) ) {
RequestModel ( MI_RHINO , STREAMFLAGS_DONT_REMOVE ) ;
RequestModel ( MI_BARRACKS , STREAMFLAGS_DONT_REMOVE ) ;
RequestModel ( MI_ARMY , STREAMFLAGS_DONT_REMOVE ) ;
} else {
SetModelIsDeletable ( MI_RHINO ) ;
SetModelIsDeletable ( MI_BARRACKS ) ;
if ( ! HasModelLoaded ( MI_RHINO ) & & ! HasModelLoaded ( MI_BARRACKS ) )
SetModelIsDeletable ( MI_ARMY ) ;
}
if ( FindPlayerPed ( ) - > m_pWanted - > NumOfHelisRequired ( ) > 0 )
RequestModel ( MI_CHOPPER , STREAMFLAGS_DONT_REMOVE ) ;
else
SetModelIsDeletable ( MI_CHOPPER ) ;
2020-05-08 22:29:43 +02:00
if ( FindPlayerPed ( ) - > m_pWanted - > AreMiamiViceRequired ( ) ) {
2020-05-10 11:25:30 +02:00
SetModelIsDeletable ( MI_VICE1 ) ;
SetModelIsDeletable ( MI_VICE2 ) ;
SetModelIsDeletable ( MI_VICE3 ) ;
SetModelIsDeletable ( MI_VICE4 ) ;
SetModelIsDeletable ( MI_VICE5 ) ;
SetModelIsDeletable ( MI_VICE6 ) ;
SetModelIsDeletable ( MI_VICE7 ) ;
SetModelIsDeletable ( MI_VICE8 ) ;
2020-05-08 22:29:43 +02:00
RequestModel ( MI_VICECHEE , STREAMFLAGS_DONT_REMOVE ) ;
2020-08-20 23:43:13 +02:00
if ( CPopulation : : NumMiamiViceCops = = 0 )
switch ( CCarCtrl : : MiamiViceCycle ) {
case 0 :
RequestModel ( MI_VICE1 , STREAMFLAGS_DONT_REMOVE ) ;
RequestModel ( MI_VICE2 , STREAMFLAGS_DONT_REMOVE ) ;
break ;
case 1 :
RequestModel ( MI_VICE3 , STREAMFLAGS_DONT_REMOVE ) ;
RequestModel ( MI_VICE4 , STREAMFLAGS_DONT_REMOVE ) ;
break ;
case 2 :
RequestModel ( MI_VICE5 , STREAMFLAGS_DONT_REMOVE ) ;
RequestModel ( MI_VICE6 , STREAMFLAGS_DONT_REMOVE ) ;
break ;
case 3 :
RequestModel ( MI_VICE7 , STREAMFLAGS_DONT_REMOVE ) ;
RequestModel ( MI_VICE8 , STREAMFLAGS_DONT_REMOVE ) ;
break ;
}
2020-05-08 22:29:43 +02:00
}
else {
SetModelIsDeletable ( MI_VICECHEE ) ;
2020-05-10 11:25:30 +02:00
SetModelIsDeletable ( MI_VICE1 ) ;
SetModelIsDeletable ( MI_VICE2 ) ;
SetModelIsDeletable ( MI_VICE3 ) ;
SetModelIsDeletable ( MI_VICE4 ) ;
SetModelIsDeletable ( MI_VICE5 ) ;
SetModelIsDeletable ( MI_VICE6 ) ;
SetModelIsDeletable ( MI_VICE7 ) ;
SetModelIsDeletable ( MI_VICE8 ) ;
2020-05-08 22:29:43 +02:00
}
2019-06-28 12:34:02 +02:00
if ( timeBeforeNextLoad > = 0 )
timeBeforeNextLoad - - ;
else if ( ms_numVehiclesLoaded < = desiredNumVehiclesLoaded ) {
2020-05-08 10:11:09 +02:00
CZoneInfo zone ;
2020-05-24 17:27:12 +02:00
CVector coors = FindPlayerCoors ( ) ;
CTheZones : : GetZoneInfoForTimeOfDay ( & coors , & zone ) ;
2020-05-08 10:11:09 +02:00
int32 maxReq = - 1 ;
int32 mostRequestedRating = 0 ;
for ( i = 0 ; i < CCarCtrl : : TOTAL_CUSTOM_CLASSES ; i + + ) {
if ( CCarCtrl : : NumRequestsOfCarRating [ i ] > maxReq & &
2020-05-08 15:16:46 +02:00
( ( i = = 0 & & zone . carThreshold [ 0 ] ! = 0 ) | |
2021-02-28 13:50:51 +01:00
# ifdef FIX_BUGS
( i < CCarCtrl : : NUM_CAR_CLASSES & & zone . carThreshold [ i ] ! = zone . carThreshold [ i - 1 ] ) | |
( i = = CCarCtrl : : NUM_CAR_CLASSES & & zone . boatThreshold [ i - CCarCtrl : : NUM_CAR_CLASSES ] ! = 0 ) | |
( i > CCarCtrl : : NUM_CAR_CLASSES & & i < CCarCtrl : : TOTAL_CUSTOM_CLASSES & & zone . boatThreshold [ i - CCarCtrl : : NUM_CAR_CLASSES ] ! = zone . boatThreshold [ i - CCarCtrl : : NUM_CAR_CLASSES - 1 ] ) ) ) {
# else
2020-05-08 15:16:46 +02:00
( i ! = 0 & & zone . carThreshold [ i ] ! = zone . carThreshold [ i - 1 ] ) ) ) {
2021-02-28 13:50:51 +01:00
# endif
2020-05-08 10:11:09 +02:00
maxReq = CCarCtrl : : NumRequestsOfCarRating [ i ] ;
mostRequestedRating = i ;
}
2019-06-28 12:34:02 +02:00
}
2020-05-08 10:11:09 +02:00
model = CCarCtrl : : ChooseCarModelToLoad ( mostRequestedRating ) ;
if ( ! HasModelLoaded ( model ) ) {
2019-06-28 12:34:02 +02:00
RequestModel ( model , STREAMFLAGS_DEPENDENCY ) ;
2020-05-08 10:11:09 +02:00
timeBeforeNextLoad = 350 ;
2019-06-28 12:34:02 +02:00
}
2020-05-08 10:11:09 +02:00
CCarCtrl : : NumRequestsOfCarRating [ mostRequestedRating ] = 0 ;
2019-06-28 12:34:02 +02:00
}
}
void
CStreaming : : StreamZoneModels ( const CVector & pos )
{
2020-08-20 23:43:13 +02:00
int i , j ;
2019-06-28 12:34:02 +02:00
uint16 gangsToLoad , gangCarsToLoad , bit ;
CZoneInfo info ;
2020-08-20 23:43:13 +02:00
static int timeBeforeNextLoad = 0 ;
2019-06-28 12:34:02 +02:00
CTheZones : : GetZoneInfoForTimeOfDay ( & pos , & info ) ;
if ( info . pedGroup ! = ms_currentPedGrp ) {
// unload pevious group
if ( ms_currentPedGrp ! = - 1 )
2020-05-07 17:53:38 +02:00
for ( i = 0 ; i < NUMMODELSPERPEDGROUP ; i + + ) {
2020-08-20 23:43:13 +02:00
ms_bIsPedFromPedGroupLoaded [ i ] = false ;
if ( CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ i ] ! = - 1 ) {
SetModelIsDeletable ( CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ i ] ) ;
SetModelTxdIsDeletable ( CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ i ] ) ;
}
2019-06-28 12:34:02 +02:00
}
ms_currentPedGrp = info . pedGroup ;
2020-08-20 23:43:13 +02:00
for ( i = 0 ; i < MAXZONEPEDSLOADED ; i + + ) {
do
j = CGeneral : : GetRandomNumberInRange ( 0 , NUMMODELSPERPEDGROUP ) ;
while ( ms_bIsPedFromPedGroupLoaded [ j ] ) ;
ms_bIsPedFromPedGroupLoaded [ j ] = true ;
if ( CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ j ] ! = - 1 )
2020-08-24 20:52:16 +02:00
RequestModel ( CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ j ] , STREAMFLAGS_DEPENDENCY ) ;
2019-06-28 12:34:02 +02:00
}
2020-08-20 23:43:13 +02:00
ms_numPedsLoaded = MAXZONEPEDSLOADED ;
timeBeforeNextLoad = 300 ;
2019-06-28 12:34:02 +02:00
}
2020-08-20 23:43:13 +02:00
if ( timeBeforeNextLoad > = 0 )
timeBeforeNextLoad - - ;
else {
// Switch a ped
int oldMI ;
// Find a ped to unload
for ( i = 0 ; i < NUMMODELSPERPEDGROUP ; i + + )
if ( ms_bIsPedFromPedGroupLoaded [ i ] ) {
oldMI = CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ i ] ;
if ( oldMI ! = - 1 & & CModelInfo : : GetModelInfo ( oldMI ) - > GetNumRefs ( ) = = 0 )
break ;
}
// And load a new one
if ( i ! = NUMMODELSPERPEDGROUP | | ms_numPedsLoaded < MAXZONEPEDSLOADED ) {
do
j = CGeneral : : GetRandomNumberInRange ( 0 , NUMMODELSPERPEDGROUP ) ;
while ( ms_bIsPedFromPedGroupLoaded [ j ] ) ;
if ( ms_numPedsLoaded = = MAXZONEPEDSLOADED )
2020-08-24 20:52:16 +02:00
ms_bIsPedFromPedGroupLoaded [ i ] = false ;
2020-08-20 23:43:13 +02:00
ms_bIsPedFromPedGroupLoaded [ j ] = true ;
int newMI = CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ j ] ;
if ( newMI ! = oldMI ) {
RequestModel ( newMI , STREAMFLAGS_DEPENDENCY ) ;
2021-01-08 20:53:11 +01:00
debug ( " Request Ped %s \n " , CModelInfo : : GetModelInfo ( newMI ) - > GetModelName ( ) ) ;
2020-08-20 23:43:13 +02:00
if ( ms_numPedsLoaded = = MAXZONEPEDSLOADED ) {
SetModelIsDeletable ( oldMI ) ;
SetModelTxdIsDeletable ( oldMI ) ;
2021-01-08 20:53:11 +01:00
debug ( " Remove Ped %s \n " , CModelInfo : : GetModelInfo ( oldMI ) - > GetModelName ( ) ) ;
2020-08-20 23:43:13 +02:00
} else
ms_numPedsLoaded + + ;
timeBeforeNextLoad = 300 ;
}
}
}
2019-06-28 12:34:02 +02:00
RequestModel ( MI_MALE01 , STREAMFLAGS_DONT_REMOVE ) ;
2020-08-20 23:43:13 +02:00
RequestModel ( MI_TAXI_D , STREAMFLAGS_DONT_REMOVE ) ;
2019-06-28 12:34:02 +02:00
gangsToLoad = 0 ;
gangCarsToLoad = 0 ;
2020-05-07 17:53:38 +02:00
if ( info . gangPedThreshold [ 0 ] ! = info . copPedThreshold )
gangsToLoad = 1 ;
for ( i = 1 ; i < NUM_GANGS ; i + + )
if ( info . gangPedThreshold [ i ] ! = info . gangPedThreshold [ i - 1 ] )
gangsToLoad | = 1 < < i ;
if ( info . gangThreshold [ 0 ] ! = info . copThreshold )
gangCarsToLoad = 1 ;
for ( i = 1 ; i < NUM_GANGS ; i + + )
if ( info . gangThreshold [ i ] ! = info . gangThreshold [ i - 1 ] )
gangCarsToLoad | = 1 < < i ;
2019-06-28 12:34:02 +02:00
if ( gangsToLoad = = ms_loadedGangs & & gangCarsToLoad = = ms_loadedGangCars )
return ;
2020-08-20 23:43:13 +02:00
int gangModelsToload = gangsToLoad | gangCarsToLoad ;
if ( gangsToLoad ! = ms_loadedGangs | | gangCarsToLoad ! = ms_loadedGangCars ) {
for ( i = 0 ; i < NUM_GANGS ; i + + ) {
bit = 1 < < i ;
if ( gangModelsToload & bit & & ( ms_loadedGangs & bit ) = = 0 ) {
RequestModel ( CGangs : : GetGangPedModel1 ( i ) , STREAMFLAGS_DEPENDENCY ) ;
RequestModel ( CGangs : : GetGangPedModel2 ( i ) , STREAMFLAGS_DEPENDENCY ) ;
ms_loadedGangs | = bit ;
} else if ( ( gangModelsToload & bit ) = = 0 & & ms_loadedGangs & bit ) {
SetModelIsDeletable ( CGangs : : GetGangPedModel1 ( i ) ) ;
SetModelIsDeletable ( CGangs : : GetGangPedModel2 ( i ) ) ;
SetModelTxdIsDeletable ( CGangs : : GetGangPedModel1 ( i ) ) ;
SetModelTxdIsDeletable ( CGangs : : GetGangPedModel2 ( i ) ) ;
ms_loadedGangs & = ~ bit ;
}
2020-05-07 11:33:20 +02:00
2020-08-20 23:43:13 +02:00
if ( CGangs : : GetGangVehicleModel ( i ) ! = - 1 ) {
if ( ( gangCarsToLoad & bit ) & & ( ms_loadedGangCars & bit ) = = 0 ) {
RequestModel ( CGangs : : GetGangVehicleModel ( i ) , STREAMFLAGS_DEPENDENCY ) ;
} else if ( ( gangCarsToLoad & bit ) = = 0 & & ms_loadedGangCars & bit ) {
SetModelIsDeletable ( CGangs : : GetGangVehicleModel ( i ) ) ;
SetModelTxdIsDeletable ( CGangs : : GetGangVehicleModel ( i ) ) ;
}
}
2019-06-28 12:34:02 +02:00
}
2020-08-20 23:43:13 +02:00
ms_loadedGangCars = gangCarsToLoad ;
2019-06-28 12:34:02 +02:00
}
}
void
CStreaming : : RemoveCurrentZonesModels ( void )
{
int i ;
2020-06-14 14:57:27 +02:00
if ( ms_currentPedGrp ! = - 1 )
for ( i = 0 ; i < NUMMODELSPERPEDGROUP ; i + + ) {
2020-08-24 20:52:16 +02:00
ms_bIsPedFromPedGroupLoaded [ i ] = false ;
2021-03-06 17:28:59 +01:00
if ( CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ i ] ! = - 1 ) {
2019-06-28 12:34:02 +02:00
SetModelIsDeletable ( CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ i ] ) ;
2020-06-14 14:57:27 +02:00
SetModelTxdIsDeletable ( CPopulation : : ms_pPedGroups [ ms_currentPedGrp ] . models [ i ] ) ;
}
2019-06-28 12:34:02 +02:00
}
2020-06-14 14:57:27 +02:00
CStreaming : : RequestModel ( MI_MALE01 , STREAMFLAGS_DONT_REMOVE ) ;
CStreaming : : RequestModel ( MI_TAXI_D , STREAMFLAGS_DONT_REMOVE ) ;
for ( i = 0 ; i < NUM_GANGS ; i + + ) {
if ( CGangs : : GetGangPedModel1 ( i ) ! = - 1 ) {
SetModelIsDeletable ( CGangs : : GetGangPedModel1 ( i ) ) ;
SetModelTxdIsDeletable ( CGangs : : GetGangPedModel1 ( i ) ) ;
}
if ( CGangs : : GetGangPedModel2 ( i ) ! = - 1 ) {
SetModelIsDeletable ( CGangs : : GetGangPedModel2 ( i ) ) ;
SetModelTxdIsDeletable ( CGangs : : GetGangPedModel2 ( i ) ) ;
}
if ( CGangs : : GetGangVehicleModel ( i ) ! = - 1 ) {
2020-05-16 16:00:40 +02:00
SetModelIsDeletable ( CGangs : : GetGangVehicleModel ( i ) ) ;
2020-06-14 14:57:27 +02:00
SetModelTxdIsDeletable ( CGangs : : GetGangVehicleModel ( i ) ) ;
}
2019-06-28 12:34:02 +02:00
}
ms_currentPedGrp = - 1 ;
ms_loadedGangs = 0 ;
ms_loadedGangCars = 0 ;
}
2020-05-05 17:04:43 +02:00
void
CStreaming : : LoadBigBuildingsWhenNeeded ( void )
{
// Very much like CCollision::Update and CCollision::LoadCollisionWhenINeedIt
if ( CCutsceneMgr : : IsCutsceneProcessing ( ) )
return ;
2020-07-13 17:10:17 +02:00
if ( CTheZones : : m_CurrLevel = = LEVEL_GENERIC | |
2020-05-05 17:04:43 +02:00
CTheZones : : m_CurrLevel = = CGame : : currLevel )
return ;
CTimer : : Suspend ( ) ;
CGame : : currLevel = CTheZones : : m_CurrLevel ;
2020-12-27 17:26:30 +01:00
ISLAND_LOADING_IS ( LOW )
{
DMAudio . SetEffectsFadeVol ( 0 ) ;
CPad : : StopPadsShaking ( ) ;
CCollision : : LoadCollisionScreen ( CGame : : currLevel ) ;
DMAudio . Service ( ) ;
RemoveUnusedBigBuildings ( CGame : : currLevel ) ;
RemoveUnusedBuildings ( CGame : : currLevel ) ;
RemoveUnusedModelsInLoadedList ( ) ;
CGame : : TidyUpMemory ( true , true ) ;
}
2020-05-05 17:04:43 +02:00
CReplay : : EmptyReplayBuffer ( ) ;
2020-07-13 17:10:17 +02:00
if ( CGame : : currLevel ! = LEVEL_GENERIC )
2020-05-05 17:04:43 +02:00
LoadSplash ( GetLevelSplashScreen ( CGame : : currLevel ) ) ;
2020-12-27 17:26:30 +01:00
ISLAND_LOADING_IS ( LOW )
CStreaming : : RequestBigBuildings ( CGame : : currLevel , TheCamera . GetPosition ( ) ) ;
2021-01-04 20:55:41 +01:00
# ifdef NO_ISLAND_LOADING
2020-12-27 17:26:30 +01:00
else if ( FrontEndMenuManager . m_PrefsIslandLoading = = CMenuManager : : ISLAND_LOADING_MEDIUM ) {
RemoveIslandsNotUsed ( CGame : : currLevel ) ;
CStreaming : : RequestIslands ( CGame : : currLevel ) ;
}
2021-01-04 20:55:41 +01:00
# endif
2020-12-27 17:26:30 +01:00
2020-08-21 12:09:45 +02:00
CStreaming : : LoadAllRequestedModels ( false ) ;
2020-05-05 17:04:43 +02:00
CGame : : TidyUpMemory ( true , true ) ;
CTimer : : Resume ( ) ;
2020-12-27 17:26:30 +01:00
ISLAND_LOADING_IS ( LOW )
DMAudio . SetEffectsFadeVol ( 127 ) ;
2020-05-05 17:04:43 +02:00
}
2019-06-24 18:44:23 +02:00
2019-06-26 16:49:32 +02:00
// Find starting offset of the cdimage we next want to read
// Not useful at all on PC...
int32
CStreaming : : GetCdImageOffset ( int32 lastPosn )
{
int offset , off ;
int i , img ;
int dist , mindist ;
img = - 1 ;
2020-05-11 04:55:57 +02:00
mindist = INT32_MAX ;
2019-06-26 16:49:32 +02:00
offset = ms_imageOffsets [ ms_lastImageRead ] ;
if ( lastPosn < = offset | | lastPosn > offset + ms_imageSize ) {
// last read position is not in last image
for ( i = 0 ; i < NUMCDIMAGES ; i + + ) {
off = ms_imageOffsets [ i ] ;
if ( off = = - 1 ) continue ;
if ( ( uint32 ) lastPosn > ( uint32 ) off )
// after start of image, get distance from end
// negative if before end!
dist = lastPosn - ( off + ms_imageSize ) ;
else
// before image, get offset to start
// this will never be negative
dist = off - lastPosn ;
if ( dist < mindist ) {
img = i ;
mindist = dist ;
}
}
assert ( img > = 0 ) ;
offset = ms_imageOffsets [ img ] ;
ms_lastImageRead = img ;
}
return offset ;
}
inline bool
2020-05-08 20:56:42 +02:00
ModelNotLoaded ( int32 modelId )
2019-06-26 16:49:32 +02:00
{
2020-05-08 20:56:42 +02:00
CStreamingInfo * si = & CStreaming : : ms_aInfoForModel [ modelId ] ;
return si - > m_loadState ! = STREAMSTATE_LOADED & & si - > m_loadState ! = STREAMSTATE_READING ;
2019-06-26 16:49:32 +02:00
}
2020-05-08 20:56:42 +02:00
inline bool TxdNotLoaded ( int32 txdId ) { return ModelNotLoaded ( txdId + STREAM_OFFSET_TXD ) ; }
inline bool AnimNotLoaded ( int32 animId ) { return animId ! = - 1 & & ModelNotLoaded ( animId + STREAM_OFFSET_ANIM ) ; }
2019-06-26 16:49:32 +02:00
// Find stream id of next requested file in cdimage
int32
CStreaming : : GetNextFileOnCd ( int32 lastPosn , bool priority )
{
CStreamingInfo * si , * next ;
int streamId ;
uint32 posn , size ;
int streamIdFirst , streamIdNext ;
uint32 posnFirst , posnNext ;
streamIdFirst = - 1 ;
streamIdNext = - 1 ;
2020-05-11 04:55:57 +02:00
posnFirst = UINT32_MAX ;
posnNext = UINT32_MAX ;
2019-06-26 16:49:32 +02:00
for ( si = ms_startRequestedList . m_next ; si ! = & ms_endRequestedList ; si = next ) {
next = si - > m_next ;
streamId = si - ms_aInfoForModel ;
// only priority requests if there are any
if ( priority & & ms_numPriorityRequests ! = 0 & & ! si - > IsPriority ( ) )
continue ;
2020-05-08 20:56:42 +02:00
// request Txds or anims if necessary
if ( streamId < STREAM_OFFSET_TXD ) {
int txdId = CModelInfo : : GetModelInfo ( streamId ) - > GetTxdSlot ( ) ;
if ( TxdNotLoaded ( txdId ) ) {
ReRequestTxd ( txdId ) ;
continue ;
}
int animId = CModelInfo : : GetModelInfo ( streamId ) - > GetAnimFileIndex ( ) ;
if ( AnimNotLoaded ( animId ) ) {
ReRequestAnim ( animId ) ;
continue ;
}
} else if ( streamId > = STREAM_OFFSET_ANIM & & CCutsceneMgr : : IsCutsceneProcessing ( ) )
continue ;
if ( ms_aInfoForModel [ streamId ] . GetCdPosnAndSize ( posn , size ) ) {
2019-06-26 16:49:32 +02:00
if ( posn < posnFirst ) {
// find first requested file in image
streamIdFirst = streamId ;
posnFirst = posn ;
}
if ( posn < posnNext & & posn > = ( uint32 ) lastPosn ) {
// find first requested file after last read position
streamIdNext = streamId ;
posnNext = posn ;
}
} else {
// empty file
DecrementRef ( streamId ) ;
si - > RemoveFromList ( ) ;
si - > m_loadState = STREAMSTATE_LOADED ;
}
}
// wrap around
if ( streamIdNext = = - 1 )
streamIdNext = streamIdFirst ;
if ( streamIdNext = = - 1 & & ms_numPriorityRequests ! = 0 ) {
// try non-priority files
ms_numPriorityRequests = 0 ;
streamIdNext = GetNextFileOnCd ( lastPosn , false ) ;
}
return streamIdNext ;
}
/*
* Streaming buffer size is half of the largest file .
* Files larger than the buffer size can only be loaded by channel 0 ,
* which then uses both buffers , while channel 1 is idle .
* ms_bLoadingBigModel is set to true to indicate this state .
*/
// Make channel read from disc
void
CStreaming : : RequestModelStream ( int32 ch )
{
int lastPosn , imgOffset , streamId ;
int totalSize ;
uint32 posn , size , unused ;
int i ;
int haveBigFile , havePed ;
lastPosn = CdStreamGetLastPosn ( ) ;
imgOffset = GetCdImageOffset ( lastPosn ) ;
streamId = GetNextFileOnCd ( lastPosn - imgOffset , true ) ;
2020-05-06 21:54:43 +02:00
// remove Txds and Anims that aren't requested anymore
while ( streamId ! = - 1 ) {
if ( ms_aInfoForModel [ streamId ] . m_flags & STREAMFLAGS_KEEP_IN_MEMORY )
break ;
if ( streamId > = STREAM_OFFSET_TXD & & streamId < STREAM_OFFSET_COL ) {
if ( IsTxdUsedByRequestedModels ( streamId - STREAM_OFFSET_TXD ) )
break ;
2020-05-08 20:56:42 +02:00
} else if ( streamId > = STREAM_OFFSET_ANIM ) {
assert ( streamId < NUMSTREAMINFO ) ;
if ( AreAnimsUsedByRequestedModels ( streamId - STREAM_OFFSET_ANIM ) )
break ;
2020-05-06 21:54:43 +02:00
} else
2019-06-26 16:49:32 +02:00
break ;
RemoveModel ( streamId ) ;
// so try next file
ms_aInfoForModel [ streamId ] . GetCdPosnAndSize ( posn , size ) ;
streamId = GetNextFileOnCd ( posn + size , true ) ;
}
if ( streamId = = - 1 )
return ;
ms_aInfoForModel [ streamId ] . GetCdPosnAndSize ( posn , size ) ;
if ( size > ( uint32 ) ms_streamingBufferSize ) {
// Can only load big models on channel 0, and 1 has to be idle
if ( ch = = 1 | | ms_channel [ 1 ] . state ! = CHANNELSTATE_IDLE )
return ;
ms_bLoadingBigModel = true ;
}
// Load up to 4 adjacent files
haveBigFile = 0 ;
havePed = 0 ;
totalSize = 0 ;
for ( i = 0 ; i < 4 ; i + + ) {
// no more files we can read
if ( streamId = = - 1 | | ms_aInfoForModel [ streamId ] . m_loadState ! = STREAMSTATE_INQUEUE )
break ;
// also stop at non-priority files
ms_aInfoForModel [ streamId ] . GetCdPosnAndSize ( unused , size ) ;
if ( ms_numPriorityRequests ! = 0 & & ! ms_aInfoForModel [ streamId ] . IsPriority ( ) )
break ;
// Can't load certain combinations of files together
if ( streamId < STREAM_OFFSET_TXD ) {
2020-05-05 14:06:55 +02:00
if ( havePed & & CModelInfo : : GetModelInfo ( streamId ) - > GetModelType ( ) = = MITYPE_PED | |
haveBigFile & & CModelInfo : : GetModelInfo ( streamId ) - > GetModelType ( ) = = MITYPE_VEHICLE | |
2020-05-08 20:56:42 +02:00
TxdNotLoaded ( CModelInfo : : GetModelInfo ( streamId ) - > GetTxdSlot ( ) ) | |
AnimNotLoaded ( CModelInfo : : GetModelInfo ( streamId ) - > GetAnimFileIndex ( ) ) )
2019-06-26 16:49:32 +02:00
break ;
} else {
if ( haveBigFile & & size > 200 )
break ;
}
// Now add the file
ms_channel [ ch ] . streamIds [ i ] = streamId ;
ms_channel [ ch ] . offsets [ i ] = totalSize ;
totalSize + = size ;
// To big for buffer, remove again
if ( totalSize > ms_streamingBufferSize & & i > 0 ) {
totalSize - = size ;
break ;
}
if ( streamId < STREAM_OFFSET_TXD ) {
2020-05-05 14:06:55 +02:00
if ( CModelInfo : : GetModelInfo ( streamId ) - > GetModelType ( ) = = MITYPE_PED )
2019-06-26 16:49:32 +02:00
havePed = 1 ;
2020-05-05 14:06:55 +02:00
if ( CModelInfo : : GetModelInfo ( streamId ) - > GetModelType ( ) = = MITYPE_VEHICLE )
2019-06-26 16:49:32 +02:00
haveBigFile = 1 ;
} else {
if ( size > 200 )
haveBigFile = 1 ;
}
ms_aInfoForModel [ streamId ] . m_loadState = STREAMSTATE_READING ;
ms_aInfoForModel [ streamId ] . RemoveFromList ( ) ;
DecrementRef ( streamId ) ;
streamId = ms_aInfoForModel [ streamId ] . m_nextID ;
}
// clear remaining slots
for ( ; i < 4 ; i + + )
ms_channel [ ch ] . streamIds [ i ] = - 1 ;
// Now read the data
assert ( ! ( ms_bLoadingBigModel & & ch = = 1 ) ) ; // this would clobber the buffer
if ( CdStreamRead ( ch , ms_pStreamingBuffer [ ch ] , imgOffset + posn , totalSize ) = = STREAM_NONE )
debug ( " FUCKFUCKFUCK \n " ) ;
ms_channel [ ch ] . state = CHANNELSTATE_READING ;
ms_channel [ ch ] . field24 = 0 ;
ms_channel [ ch ] . size = totalSize ;
ms_channel [ ch ] . position = imgOffset + posn ;
ms_channel [ ch ] . numTries = 0 ;
}
2019-06-24 18:44:23 +02:00
2019-06-26 16:49:32 +02:00
// Load data previously read from disc
2019-06-24 18:44:23 +02:00
bool
CStreaming : : ProcessLoadingChannel ( int32 ch )
{
int status ;
int i , id , cdsize ;
status = CdStreamGetStatus ( ch ) ;
if ( status ! = STREAM_NONE ) {
// busy
if ( status ! = STREAM_READING & & status ! = STREAM_WAITING ) {
ms_channelError = ch ;
ms_channel [ ch ] . state = CHANNELSTATE_ERROR ;
ms_channel [ ch ] . status = status ;
}
return false ;
}
if ( ms_channel [ ch ] . state = = CHANNELSTATE_STARTED ) {
ms_channel [ ch ] . state = CHANNELSTATE_IDLE ;
FinishLoadingLargeFile ( & ms_pStreamingBuffer [ ch ] [ ms_channel [ ch ] . offsets [ 0 ] * CDSTREAM_SECTOR_SIZE ] ,
ms_channel [ ch ] . streamIds [ 0 ] ) ;
ms_channel [ ch ] . streamIds [ 0 ] = - 1 ;
} else {
ms_channel [ ch ] . state = CHANNELSTATE_IDLE ;
for ( i = 0 ; i < 4 ; i + + ) {
id = ms_channel [ ch ] . streamIds [ i ] ;
if ( id = = - 1 )
continue ;
cdsize = ms_aInfoForModel [ id ] . GetCdSize ( ) ;
2020-05-05 14:06:55 +02:00
if ( id < STREAM_OFFSET_TXD & & CModelInfo : : GetModelInfo ( id ) - > GetModelType ( ) = = MITYPE_VEHICLE & &
2019-06-24 18:44:23 +02:00
ms_numVehiclesLoaded > = desiredNumVehiclesLoaded & &
2019-06-26 21:33:58 +02:00
! RemoveLoadedVehicle ( ) & &
2020-05-06 21:54:43 +02:00
( CanRemoveModel ( id ) | | GetAvailableVehicleSlot ( ) = = - 1 ) ) {
2019-06-24 18:44:23 +02:00
// can't load vehicle
RemoveModel ( id ) ;
2020-05-06 21:54:43 +02:00
if ( ! CanRemoveModel ( id ) )
2019-06-24 18:44:23 +02:00
ReRequestModel ( id ) ;
else if ( CTxdStore : : GetNumRefs ( CModelInfo : : GetModelInfo ( id ) - > GetTxdSlot ( ) ) = = 0 )
RemoveTxd ( CModelInfo : : GetModelInfo ( id ) - > GetTxdSlot ( ) ) ;
} else {
MakeSpaceFor ( cdsize * CDSTREAM_SECTOR_SIZE ) ;
ConvertBufferToObject ( & ms_pStreamingBuffer [ ch ] [ ms_channel [ ch ] . offsets [ i ] * CDSTREAM_SECTOR_SIZE ] ,
id ) ;
if ( ms_aInfoForModel [ id ] . m_loadState = = STREAMSTATE_STARTED ) {
// queue for second part
ms_channel [ ch ] . state = CHANNELSTATE_STARTED ;
ms_channel [ ch ] . offsets [ 0 ] = ms_channel [ ch ] . offsets [ i ] ;
ms_channel [ ch ] . streamIds [ 0 ] = id ;
if ( i ! = 0 )
ms_channel [ ch ] . streamIds [ i ] = - 1 ;
} else
ms_channel [ ch ] . streamIds [ i ] = - 1 ;
}
}
}
if ( ms_bLoadingBigModel & & ms_channel [ ch ] . state ! = CHANNELSTATE_STARTED ) {
ms_bLoadingBigModel = false ;
// reset channel 1 after loading a big model
2019-06-26 21:33:58 +02:00
for ( i = 0 ; i < 4 ; i + + )
2019-06-24 18:44:23 +02:00
ms_channel [ 1 ] . streamIds [ i ] = - 1 ;
ms_channel [ 1 ] . state = CHANNELSTATE_IDLE ;
}
return true ;
}
2019-06-26 21:33:58 +02:00
void
CStreaming : : RetryLoadFile ( int32 ch )
{
2020-05-12 01:24:57 +02:00
Const char * key ;
2019-06-26 21:33:58 +02:00
CPad : : StopPadsShaking ( ) ;
if ( ms_channel [ ch ] . numTries > = 3 ) {
switch ( ms_channel [ ch ] . status ) {
case STREAM_ERROR_NOCD : key = " NOCD " ; break ;
case STREAM_ERROR_OPENCD : key = " OPENCD " ; break ;
case STREAM_ERROR_WRONGCD : key = " WRONGCD " ; break ;
default : key = " CDERROR " ; break ;
}
CHud : : SetMessage ( TheText . Get ( key ) ) ;
CTimer : : SetCodePause ( true ) ;
}
switch ( ms_channel [ ch ] . state ) {
2019-10-06 01:41:35 +02:00
case CHANNELSTATE_ERROR :
ms_channel [ ch ] . numTries + + ;
if ( CdStreamGetStatus ( ch ) = = STREAM_READING | | CdStreamGetStatus ( ch ) = = STREAM_WAITING ) break ;
2019-06-26 21:33:58 +02:00
case CHANNELSTATE_IDLE :
CdStreamRead ( ch , ms_pStreamingBuffer [ ch ] , ms_channel [ ch ] . position , ms_channel [ ch ] . size ) ;
ms_channel [ ch ] . state = CHANNELSTATE_READING ;
ms_channel [ ch ] . field24 = - 600 ;
break ;
case CHANNELSTATE_READING :
if ( ProcessLoadingChannel ( ch ) ) {
ms_channelError = - 1 ;
CTimer : : SetCodePause ( false ) ;
}
break ;
}
}
2019-06-26 16:49:32 +02:00
void
CStreaming : : LoadRequestedModels ( void )
2019-06-24 18:44:23 +02:00
{
2019-06-26 16:49:32 +02:00
static int currentChannel = 0 ;
// We can't read with channel 1 while channel 0 is using its buffer
if ( ms_bLoadingBigModel )
currentChannel = 0 ;
// We have data, load
if ( ms_channel [ currentChannel ] . state = = CHANNELSTATE_READING | |
ms_channel [ currentChannel ] . state = = CHANNELSTATE_STARTED )
ProcessLoadingChannel ( currentChannel ) ;
if ( ms_channelError = = - 1 ) {
// Channel is idle, read more data
if ( ms_channel [ currentChannel ] . state = = CHANNELSTATE_IDLE )
RequestModelStream ( currentChannel ) ;
// Switch channel
if ( ms_channel [ currentChannel ] . state ! = CHANNELSTATE_STARTED )
currentChannel = 1 - currentChannel ;
}
2019-06-24 18:44:23 +02:00
}
2020-10-04 21:39:54 +02:00
2021-01-27 16:26:08 +01:00
// Let's load models in 4 threads; when one of them becomes idle, process the file, and fill thread with another file. Unfortunately processing models are still single-threaded.
2020-10-04 21:39:54 +02:00
// Currently only supported on POSIX streamer.
2021-01-27 16:26:08 +01:00
// WIP - some files are loaded swapped (CdStreamPosix problem?)
#if 0 //def ONE_THREAD_PER_CHANNEL
2020-10-04 21:39:54 +02:00
void
CStreaming : : LoadAllRequestedModels ( bool priority )
{
static bool bInsideLoadAll = false ;
int imgOffset , streamId , status ;
int i ;
uint32 posn , size ;
if ( bInsideLoadAll )
return ;
bInsideLoadAll = true ;
FlushChannels ( ) ;
imgOffset = GetCdImageOffset ( CdStreamGetLastPosn ( ) ) ;
int streamIds [ ARRAY_SIZE ( ms_pStreamingBuffer ) ] ;
int streamSizes [ ARRAY_SIZE ( ms_pStreamingBuffer ) ] ;
int streamPoses [ ARRAY_SIZE ( ms_pStreamingBuffer ) ] ;
2021-01-27 16:26:08 +01:00
int readOrder [ 4 ] = { - 1 } ; // Channel IDs ordered by read time
int readI = 0 ;
2020-10-04 21:39:54 +02:00
int processI = 0 ;
2021-01-27 16:26:08 +01:00
bool first = true ;
// All those "first" checks are because of variables aren't initialized in first pass.
2020-10-04 21:39:54 +02:00
while ( true ) {
for ( int i = 0 ; i < ARRAY_SIZE ( ms_pStreamingBuffer ) ; i + + ) {
2021-01-27 16:26:08 +01:00
// Channel has file to load
2020-10-04 21:39:54 +02:00
if ( ! first & & streamIds [ i ] ! = - 1 ) {
continue ;
}
if ( ms_endRequestedList . m_prev ! = & ms_startRequestedList ) {
streamId = GetNextFileOnCd ( 0 , priority ) ;
if ( streamId = = - 1 ) {
streamIds [ i ] = - 1 ;
break ;
}
if ( ms_aInfoForModel [ streamId ] . GetCdPosnAndSize ( posn , size ) ) {
streamIds [ i ] = - 1 ;
2021-01-27 16:26:08 +01:00
// Big file, needs 2 buffer
2020-10-04 21:39:54 +02:00
if ( size > ( uint32 ) ms_streamingBufferSize ) {
if ( i + 1 = = ARRAY_SIZE ( ms_pStreamingBuffer ) )
2021-01-27 16:26:08 +01:00
break ;
2020-10-04 21:39:54 +02:00
else if ( ! first & & streamIds [ i + 1 ] ! = - 1 )
continue ;
2021-01-27 16:26:08 +01:00
2020-10-04 21:39:54 +02:00
} else {
2021-01-27 16:26:08 +01:00
// Buffer of current channel is part of a "big file", pass
2020-10-04 21:39:54 +02:00
if ( i ! = 0 & & streamIds [ i - 1 ] ! = - 1 & & streamSizes [ i - 1 ] > ( uint32 ) ms_streamingBufferSize )
continue ;
}
ms_aInfoForModel [ streamId ] . RemoveFromList ( ) ;
DecrementRef ( streamId ) ;
streamIds [ i ] = streamId ;
streamSizes [ i ] = size ;
streamPoses [ i ] = posn ;
2021-01-27 16:26:08 +01:00
if ( ! first )
assert ( readOrder [ readI ] = = - 1 ) ;
//printf("read: order %d, ch %d, id %d, size %d\n", readI, i, streamId, size);
2020-10-04 21:39:54 +02:00
CdStreamRead ( i , ms_pStreamingBuffer [ i ] , imgOffset + posn , size ) ;
2021-01-27 16:26:08 +01:00
readOrder [ readI ] = i ;
if ( first & & readI + 1 ! = ARRAY_SIZE ( readOrder ) )
readOrder [ readI + 1 ] = - 1 ;
readI = ( readI + 1 ) % ARRAY_SIZE ( readOrder ) ;
2020-10-04 21:39:54 +02:00
} else {
ms_aInfoForModel [ streamId ] . RemoveFromList ( ) ;
DecrementRef ( streamId ) ;
ms_aInfoForModel [ streamId ] . m_loadState = STREAMSTATE_LOADED ;
streamIds [ i ] = - 1 ;
}
2021-01-27 16:26:08 +01:00
} else {
2020-10-04 21:39:54 +02:00
streamIds [ i ] = - 1 ;
2021-01-27 16:26:08 +01:00
break ;
}
2020-10-04 21:39:54 +02:00
}
first = false ;
2021-01-27 16:26:08 +01:00
int nextChannel = readOrder [ processI ] ;
2020-10-04 21:39:54 +02:00
2021-01-27 16:26:08 +01:00
// Now start processing
if ( nextChannel = = - 1 | | streamIds [ nextChannel ] = = - 1 )
2020-10-04 21:39:54 +02:00
break ;
2021-01-27 16:26:08 +01:00
//printf("process: order %d, ch %d, id %d\n", processI, nextChannel, streamIds[nextChannel]);
2020-10-04 21:39:54 +02:00
// Try again on error
2021-01-27 16:26:08 +01:00
while ( CdStreamSync ( nextChannel ) ! = STREAM_NONE ) {
CdStreamRead ( nextChannel , ms_pStreamingBuffer [ nextChannel ] , imgOffset + streamPoses [ nextChannel ] , streamSizes [ nextChannel ] ) ;
2020-10-04 21:39:54 +02:00
}
2021-01-27 16:26:08 +01:00
ms_aInfoForModel [ streamIds [ nextChannel ] ] . m_loadState = STREAMSTATE_READING ;
MakeSpaceFor ( streamSizes [ nextChannel ] * CDSTREAM_SECTOR_SIZE ) ;
ConvertBufferToObject ( ms_pStreamingBuffer [ nextChannel ] , streamIds [ nextChannel ] ) ;
if ( ms_aInfoForModel [ streamIds [ nextChannel ] ] . m_loadState = = STREAMSTATE_STARTED )
FinishLoadingLargeFile ( ms_pStreamingBuffer [ nextChannel ] , streamIds [ nextChannel ] ) ;
2020-10-04 21:39:54 +02:00
2021-01-27 16:26:08 +01:00
if ( streamIds [ nextChannel ] < STREAM_OFFSET_TXD ) {
CSimpleModelInfo * mi = ( CSimpleModelInfo * ) CModelInfo : : GetModelInfo ( streamIds [ nextChannel ] ) ;
2020-10-04 21:39:54 +02:00
if ( mi - > IsSimple ( ) )
mi - > m_alpha = 255 ;
}
2021-01-27 16:26:08 +01:00
streamIds [ nextChannel ] = - 1 ;
readOrder [ processI ] = - 1 ;
processI = ( processI + 1 ) % ARRAY_SIZE ( readOrder ) ;
2020-10-04 21:39:54 +02:00
}
ms_bLoadingBigModel = false ;
for ( i = 0 ; i < 4 ; i + + ) {
ms_channel [ 1 ] . streamIds [ i ] = - 1 ;
ms_channel [ 1 ] . offsets [ i ] = - 1 ;
}
ms_channel [ 1 ] . state = CHANNELSTATE_IDLE ;
bInsideLoadAll = false ;
}
# else
2019-06-26 16:49:32 +02:00
void
CStreaming : : LoadAllRequestedModels ( bool priority )
2019-06-24 18:44:23 +02:00
{
2019-06-26 16:49:32 +02:00
static bool bInsideLoadAll = false ;
int imgOffset , streamId , status ;
int i ;
2019-06-24 18:44:23 +02:00
uint32 posn , size ;
2020-08-20 23:43:13 +02:00
int numRequests = 4 * ms_numModelsRequested ;
2019-06-26 16:49:32 +02:00
if ( bInsideLoadAll )
return ;
2020-08-20 23:43:13 +02:00
bInsideLoadAll = true ;
if ( priority )
numRequests = ms_numPriorityRequests ;
2019-06-24 18:44:23 +02:00
2019-06-26 16:49:32 +02:00
FlushChannels ( ) ;
imgOffset = GetCdImageOffset ( CdStreamGetLastPosn ( ) ) ;
2020-08-20 23:43:13 +02:00
while ( ms_endRequestedList . m_prev ! = & ms_startRequestedList & & numRequests > 0 ) {
numRequests - - ;
2019-06-26 16:49:32 +02:00
streamId = GetNextFileOnCd ( 0 , priority ) ;
if ( streamId = = - 1 )
break ;
ms_aInfoForModel [ streamId ] . RemoveFromList ( ) ;
2020-08-20 23:43:13 +02:00
ms_channel [ 0 ] . streamIds [ 0 ] = streamId ;
2019-06-26 16:49:32 +02:00
DecrementRef ( streamId ) ;
if ( ms_aInfoForModel [ streamId ] . GetCdPosnAndSize ( posn , size ) ) {
do
status = CdStreamRead ( 0 , ms_pStreamingBuffer [ 0 ] , imgOffset + posn , size ) ;
while ( CdStreamSync ( 0 ) | | status = = STREAM_NONE ) ;
ms_aInfoForModel [ streamId ] . m_loadState = STREAMSTATE_READING ;
2021-01-27 16:26:08 +01:00
2019-06-26 16:49:32 +02:00
MakeSpaceFor ( size * CDSTREAM_SECTOR_SIZE ) ;
ConvertBufferToObject ( ms_pStreamingBuffer [ 0 ] , streamId ) ;
if ( ms_aInfoForModel [ streamId ] . m_loadState = = STREAMSTATE_STARTED )
FinishLoadingLargeFile ( ms_pStreamingBuffer [ 0 ] , streamId ) ;
if ( streamId < STREAM_OFFSET_TXD ) {
CSimpleModelInfo * mi = ( CSimpleModelInfo * ) CModelInfo : : GetModelInfo ( streamId ) ;
if ( mi - > IsSimple ( ) )
mi - > m_alpha = 255 ;
2019-06-24 18:44:23 +02:00
}
} else {
2019-06-26 16:49:32 +02:00
// empty
ms_aInfoForModel [ streamId ] . m_loadState = STREAMSTATE_LOADED ;
2019-06-24 18:44:23 +02:00
}
}
2019-06-26 16:49:32 +02:00
ms_bLoadingBigModel = false ;
for ( i = 0 ; i < 4 ; i + + ) {
ms_channel [ 1 ] . streamIds [ i ] = - 1 ;
ms_channel [ 1 ] . offsets [ i ] = - 1 ;
2019-06-24 18:44:23 +02:00
}
2019-06-26 16:49:32 +02:00
ms_channel [ 1 ] . state = CHANNELSTATE_IDLE ;
bInsideLoadAll = false ;
2019-06-24 18:44:23 +02:00
}
2020-10-04 21:39:54 +02:00
# endif
2019-06-24 18:44:23 +02:00
void
CStreaming : : FlushChannels ( void )
{
if ( ms_channel [ 1 ] . state = = CHANNELSTATE_STARTED )
ProcessLoadingChannel ( 1 ) ;
2019-06-26 16:49:32 +02:00
if ( ms_channel [ 0 ] . state = = CHANNELSTATE_READING ) {
2019-06-24 18:44:23 +02:00
CdStreamSync ( 0 ) ;
ProcessLoadingChannel ( 0 ) ;
}
if ( ms_channel [ 0 ] . state = = CHANNELSTATE_STARTED )
ProcessLoadingChannel ( 0 ) ;
2019-06-26 16:49:32 +02:00
if ( ms_channel [ 1 ] . state = = CHANNELSTATE_READING ) {
2019-06-24 18:44:23 +02:00
CdStreamSync ( 1 ) ;
ProcessLoadingChannel ( 1 ) ;
}
if ( ms_channel [ 1 ] . state = = CHANNELSTATE_STARTED )
ProcessLoadingChannel ( 1 ) ;
}
void
CStreaming : : FlushRequestList ( void )
{
CStreamingInfo * si , * next ;
for ( si = ms_startRequestedList . m_next ; si ! = & ms_endRequestedList ; si = next ) {
next = si - > m_next ;
RemoveModel ( si - ms_aInfoForModel ) ;
}
2021-01-27 16:26:08 +01:00
# ifdef FLUSHABLE_STREAMING
2020-10-04 21:39:54 +02:00
if ( ms_channel [ 0 ] . state = = CHANNELSTATE_READING ) {
flushStream [ 0 ] = 1 ;
}
if ( ms_channel [ 1 ] . state = = CHANNELSTATE_READING ) {
flushStream [ 1 ] = 1 ;
}
# endif
2019-06-24 18:44:23 +02:00
FlushChannels ( ) ;
}
2019-06-21 17:28:55 +02:00
2019-06-12 20:07:37 +02:00
void
CStreaming : : ImGonnaUseStreamingMemory ( void )
{
2020-11-26 16:47:19 +01:00
PUSH_MEMID ( MEMID_STREAM ) ;
2019-06-12 20:07:37 +02:00
}
void
CStreaming : : IHaveUsedStreamingMemory ( void )
{
2020-11-26 16:47:19 +01:00
POP_MEMID ( ) ;
2019-06-12 20:07:37 +02:00
UpdateMemoryUsed ( ) ;
}
void
CStreaming : : UpdateMemoryUsed ( void )
{
2020-11-26 16:47:19 +01:00
# ifdef USE_CUSTOM_ALLOCATOR
ms_memoryUsed =
gMainHeap . GetMemoryUsed ( MEMID_STREAM ) +
gMainHeap . GetMemoryUsed ( MEMID_STREAM_MODELS ) +
2020-12-21 12:34:29 +01:00
gMainHeap . GetMemoryUsed ( MEMID_STREAM_TEXUTRES ) +
gMainHeap . GetMemoryUsed ( MEMID_STREAM_COLLISION ) +
gMainHeap . GetMemoryUsed ( MEMID_STREAM_ANIMATION ) ;
2020-11-26 16:47:19 +01:00
# endif
2019-06-12 20:07:37 +02:00
}
2019-06-20 14:49:16 +02:00
2020-08-20 23:43:13 +02:00
# define STREAM_DIST 80.0f
2019-06-20 14:49:16 +02:00
2019-06-27 00:12:58 +02:00
void
2020-08-20 23:43:13 +02:00
CStreaming : : AddModelsToRequestList ( const CVector & pos , int32 flags )
2019-06-20 14:49:16 +02:00
{
2019-06-27 00:12:58 +02:00
float xmin , xmax , ymin , ymax ;
int ixmin , ixmax , iymin , iymax ;
int ix , iy ;
int dx , dy , d ;
CSector * sect ;
xmin = pos . x - STREAM_DIST ;
ymin = pos . y - STREAM_DIST ;
xmax = pos . x + STREAM_DIST ;
ymax = pos . y + STREAM_DIST ;
ixmin = CWorld : : GetSectorIndexX ( xmin ) ;
if ( ixmin < 0 ) ixmin = 0 ;
ixmax = CWorld : : GetSectorIndexX ( xmax ) ;
if ( ixmax > = NUMSECTORS_X ) ixmax = NUMSECTORS_X - 1 ;
iymin = CWorld : : GetSectorIndexY ( ymin ) ;
if ( iymin < 0 ) iymin = 0 ;
iymax = CWorld : : GetSectorIndexY ( ymax ) ;
if ( iymax > = NUMSECTORS_Y ) iymax = NUMSECTORS_Y - 1 ;
CWorld : : AdvanceCurrentScanCode ( ) ;
2020-03-07 20:22:43 +01:00
for ( iy = iymin ; iy < = iymax ; iy + + ) {
2019-06-27 00:12:58 +02:00
dy = iy - CWorld : : GetSectorIndexY ( pos . y ) ;
2020-03-07 20:22:43 +01:00
for ( ix = ixmin ; ix < = ixmax ; ix + + ) {
2019-06-27 00:12:58 +02:00
if ( CRenderer : : m_loadingPriority & & ms_numModelsRequested > 5 )
return ;
dx = ix - CWorld : : GetSectorIndexX ( pos . x ) ;
d = dx * dx + dy * dy ;
sect = CWorld : : GetSector ( ix , iy ) ;
2020-08-20 23:43:13 +02:00
if ( d < = 0 ) {
ProcessEntitiesInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] , flags ) ;
ProcessEntitiesInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS_OVERLAP ] , flags ) ;
ProcessEntitiesInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] , flags ) ;
ProcessEntitiesInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] , flags ) ;
} else if ( d < = 3 * 3 ) {
ProcessEntitiesInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] , pos . x , pos . y , xmin , ymin , xmax , ymax , flags ) ;
ProcessEntitiesInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS_OVERLAP ] , pos . x , pos . y , xmin , ymin , xmax , ymax , flags ) ;
ProcessEntitiesInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] , pos . x , pos . y , xmin , ymin , xmax , ymax , flags ) ;
ProcessEntitiesInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] , pos . x , pos . y , xmin , ymin , xmax , ymax , flags ) ;
2019-06-27 00:12:58 +02:00
}
}
}
2019-06-20 14:49:16 +02:00
}
void
2020-08-20 23:43:13 +02:00
CStreaming : : ProcessEntitiesInSectorList ( CPtrList & list , float x , float y , float xmin , float ymin , float xmax , float ymax , int32 flags )
2019-06-20 14:49:16 +02:00
{
2019-06-27 00:12:58 +02:00
CPtrNode * node ;
CEntity * e ;
float lodDistSq ;
CVector2D pos ;
for ( node = list . first ; node ; node = node - > next ) {
e = ( CEntity * ) node - > item ;
if ( e - > m_scanCode = = CWorld : : GetCurrentScanCode ( ) )
continue ;
e - > m_scanCode = CWorld : : GetCurrentScanCode ( ) ;
2020-08-20 23:43:13 +02:00
if ( ! e - > bStreamingDontDelete & & IsAreaVisible ( e - > m_area ) & & ! e - > bDontStream & & e - > bIsVisible ) {
2019-06-27 00:12:58 +02:00
CTimeModelInfo * mi = ( CTimeModelInfo * ) CModelInfo : : GetModelInfo ( e - > GetModelIndex ( ) ) ;
2020-05-05 14:06:55 +02:00
if ( mi - > GetModelType ( ) ! = MITYPE_TIME | | CClock : : GetIsTimeInRange ( mi - > GetTimeOn ( ) , mi - > GetTimeOff ( ) ) ) {
2019-06-27 00:12:58 +02:00
lodDistSq = sq ( mi - > GetLargestLodDistance ( ) ) ;
2020-04-19 18:34:08 +02:00
lodDistSq = Min ( lodDistSq , sq ( STREAM_DIST ) ) ;
2019-06-27 00:12:58 +02:00
pos = CVector2D ( e - > GetPosition ( ) ) ;
if ( xmin < pos . x & & pos . x < xmax & &
ymin < pos . y & & pos . y < ymax & &
( CVector2D ( x , y ) - pos ) . MagnitudeSqr ( ) < lodDistSq )
2020-08-20 23:43:13 +02:00
RequestModel ( e - > GetModelIndex ( ) , flags ) ;
2019-06-27 00:12:58 +02:00
}
}
}
2019-06-20 14:49:16 +02:00
}
void
2020-08-20 23:43:13 +02:00
CStreaming : : ProcessEntitiesInSectorList ( CPtrList & list , int32 flags )
2019-06-20 14:49:16 +02:00
{
2019-06-27 00:12:58 +02:00
CPtrNode * node ;
CEntity * e ;
for ( node = list . first ; node ; node = node - > next ) {
e = ( CEntity * ) node - > item ;
if ( e - > m_scanCode = = CWorld : : GetCurrentScanCode ( ) )
continue ;
e - > m_scanCode = CWorld : : GetCurrentScanCode ( ) ;
2020-08-20 23:43:13 +02:00
if ( ! e - > bStreamingDontDelete & & IsAreaVisible ( e - > m_area ) & & ! e - > bDontStream & & e - > bIsVisible ) {
2019-06-27 00:12:58 +02:00
CTimeModelInfo * mi = ( CTimeModelInfo * ) CModelInfo : : GetModelInfo ( e - > GetModelIndex ( ) ) ;
2020-05-05 14:06:55 +02:00
if ( mi - > GetModelType ( ) ! = MITYPE_TIME | | CClock : : GetIsTimeInRange ( mi - > GetTimeOn ( ) , mi - > GetTimeOff ( ) ) )
2020-08-20 23:43:13 +02:00
RequestModel ( e - > GetModelIndex ( ) , flags ) ;
2019-06-27 00:12:58 +02:00
}
}
2019-06-20 14:49:16 +02:00
}
void
2019-06-27 00:12:58 +02:00
CStreaming : : DeleteFarAwayRwObjects ( const CVector & pos )
2019-06-20 14:49:16 +02:00
{
2019-06-27 14:17:42 +02:00
int posx , posy ;
int x , y ;
int r , i ;
CSector * sect ;
posx = CWorld : : GetSectorIndexX ( pos . x ) ;
posy = CWorld : : GetSectorIndexY ( pos . y ) ;
// Move oldSectorX/Y to new sector and delete RW objects in its "wake" for every step:
// O is the old sector, <- is the direction in which we move it,
// X are the sectors we delete RW objects from (except we go up to 10)
// X
// X X
// X X X
// X X X
// <- O X X X
// X X X
// X X X
// X X
// X
while ( posx ! = ms_oldSectorX ) {
if ( posx < ms_oldSectorX ) {
for ( r = 2 ; r < = 10 ; r + + ) {
x = ms_oldSectorX + r ;
if ( x < 0 )
continue ;
if ( x > = NUMSECTORS_X )
break ;
for ( i = - r ; i < = r ; i + + ) {
y = ms_oldSectorY + i ;
if ( y < 0 )
continue ;
if ( y > = NUMSECTORS_Y )
break ;
sect = CWorld : : GetSector ( x , y ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] ) ;
DeleteRwObjectsInOverlapSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS_OVERLAP ] , ms_oldSectorX , ms_oldSectorY ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] ) ;
}
}
ms_oldSectorX - - ;
} else {
for ( r = 2 ; r < = 10 ; r + + ) {
x = ms_oldSectorX - r ;
if ( x < 0 )
break ;
if ( x > = NUMSECTORS_X )
continue ;
for ( i = - r ; i < = r ; i + + ) {
y = ms_oldSectorY + i ;
if ( y < 0 )
continue ;
if ( y > = NUMSECTORS_Y )
break ;
sect = CWorld : : GetSector ( x , y ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] ) ;
DeleteRwObjectsInOverlapSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS_OVERLAP ] , ms_oldSectorX , ms_oldSectorY ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] ) ;
}
}
ms_oldSectorX + + ;
}
}
while ( posy ! = ms_oldSectorY ) {
if ( posy < ms_oldSectorY ) {
for ( r = 2 ; r < = 10 ; r + + ) {
y = ms_oldSectorY + r ;
if ( y < 0 )
continue ;
if ( y > = NUMSECTORS_Y )
break ;
for ( i = - r ; i < = r ; i + + ) {
x = ms_oldSectorX + i ;
if ( x < 0 )
continue ;
if ( x > = NUMSECTORS_X )
break ;
sect = CWorld : : GetSector ( x , y ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] ) ;
DeleteRwObjectsInOverlapSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS_OVERLAP ] , ms_oldSectorX , ms_oldSectorY ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] ) ;
}
}
ms_oldSectorY - - ;
} else {
for ( r = 2 ; r < = 10 ; r + + ) {
y = ms_oldSectorY - r ;
if ( y < 0 )
break ;
if ( y > = NUMSECTORS_Y )
continue ;
for ( i = - r ; i < = r ; i + + ) {
x = ms_oldSectorX + i ;
if ( x < 0 )
continue ;
if ( x > = NUMSECTORS_X )
break ;
sect = CWorld : : GetSector ( x , y ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] ) ;
DeleteRwObjectsInOverlapSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS_OVERLAP ] , ms_oldSectorX , ms_oldSectorY ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] ) ;
}
}
ms_oldSectorY + + ;
}
}
2019-06-27 00:12:58 +02:00
}
void
CStreaming : : DeleteAllRwObjects ( void )
{
int x , y ;
CSector * sect ;
for ( x = 0 ; x < NUMSECTORS_X ; x + + )
for ( y = 0 ; y < NUMSECTORS_Y ; y + + ) {
sect = CWorld : : GetSector ( x , y ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS_OVERLAP ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS_OVERLAP ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES_OVERLAP ] ) ;
}
}
void
CStreaming : : DeleteRwObjectsAfterDeath ( const CVector & pos )
{
int ix , iy ;
int x , y ;
CSector * sect ;
ix = CWorld : : GetSectorIndexX ( pos . x ) ;
2020-03-07 20:22:43 +01:00
iy = CWorld : : GetSectorIndexY ( pos . y ) ;
2019-06-27 00:12:58 +02:00
for ( x = 0 ; x < NUMSECTORS_X ; x + + )
for ( y = 0 ; y < NUMSECTORS_Y ; y + + )
2019-07-10 17:18:26 +02:00
if ( Abs ( ix - x ) > 3.0f & &
Abs ( iy - y ) > 3.0f ) {
2019-06-27 00:12:58 +02:00
sect = CWorld : : GetSector ( x , y ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS_OVERLAP ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS_OVERLAP ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] ) ;
DeleteRwObjectsInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES_OVERLAP ] ) ;
}
}
2019-06-27 14:17:42 +02:00
void
2020-07-22 13:56:28 +02:00
CStreaming : : DeleteRwObjectsBehindCamera ( size_t mem )
2019-06-27 14:17:42 +02:00
{
int ix , iy ;
int x , y ;
int xmin , xmax , ymin , ymax ;
int inc ;
CSector * sect ;
if ( ms_memoryUsed < mem )
return ;
ix = CWorld : : GetSectorIndexX ( TheCamera . GetPosition ( ) . x ) ;
2020-03-07 20:22:43 +01:00
iy = CWorld : : GetSectorIndexY ( TheCamera . GetPosition ( ) . y ) ;
2019-06-27 14:17:42 +02:00
2019-07-10 17:18:26 +02:00
if ( Abs ( TheCamera . GetForward ( ) . x ) > Abs ( TheCamera . GetForward ( ) . y ) ) {
2019-06-27 14:17:42 +02:00
// looking west/east
2020-04-19 18:34:08 +02:00
ymin = Max ( iy - 10 , 0 ) ;
ymax = Min ( iy + 10 , NUMSECTORS_Y - 1 ) ;
2019-06-27 14:17:42 +02:00
assert ( ymin < = ymax ) ;
// Delete a block of sectors that we know is behind the camera
2020-08-20 23:43:13 +02:00
if ( TheCamera . GetForward ( ) . x > 0.0f ) {
2019-06-27 14:17:42 +02:00
// looking east
2020-04-19 18:34:08 +02:00
xmax = Max ( ix - 2 , 0 ) ;
xmin = Max ( ix - 10 , 0 ) ;
2019-06-27 14:17:42 +02:00
inc = 1 ;
} else {
// looking west
2020-04-19 18:34:08 +02:00
xmax = Min ( ix + 2 , NUMSECTORS_X - 1 ) ;
xmin = Min ( ix + 10 , NUMSECTORS_X - 1 ) ;
2019-06-27 14:17:42 +02:00
inc = - 1 ;
}
for ( y = ymin ; y < = ymax ; y + + ) {
for ( x = xmin ; x ! = xmax ; x + = inc ) {
sect = CWorld : : GetSector ( x , y ) ;
if ( DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] , mem ) | |
DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] , mem ) | |
DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] , mem ) )
return ;
}
}
2020-08-20 23:43:13 +02:00
while ( RemoveLoadedZoneModel ( ) )
if ( ms_memoryUsed < mem )
return ;
2019-06-27 14:17:42 +02:00
// Now a block that intersects with the camera's frustum
2020-08-20 23:43:13 +02:00
if ( TheCamera . GetForward ( ) . x > 0.0f ) {
2019-06-27 14:17:42 +02:00
// looking east
2020-04-19 18:34:08 +02:00
xmax = Max ( ix + 10 , 0 ) ;
xmin = Max ( ix - 2 , 0 ) ;
2019-06-27 14:17:42 +02:00
inc = 1 ;
} else {
// looking west
2020-04-19 18:34:08 +02:00
xmax = Min ( ix - 10 , NUMSECTORS_X - 1 ) ;
xmin = Min ( ix + 2 , NUMSECTORS_X - 1 ) ;
2019-06-27 14:17:42 +02:00
inc = - 1 ;
}
for ( y = ymin ; y < = ymax ; y + + ) {
for ( x = xmin ; x ! = xmax ; x + = inc ) {
sect = CWorld : : GetSector ( x , y ) ;
if ( DeleteRwObjectsNotInFrustumInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] , mem ) | |
DeleteRwObjectsNotInFrustumInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] , mem ) | |
DeleteRwObjectsNotInFrustumInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] , mem ) )
return ;
}
}
// As last resort, delete objects from the last step more aggressively
for ( y = ymin ; y < = ymax ; y + + ) {
for ( x = xmax ; x ! = xmin ; x - = inc ) {
sect = CWorld : : GetSector ( x , y ) ;
if ( DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] , mem ) | |
DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] , mem ) | |
DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] , mem ) )
return ;
}
}
} else {
// looking north/south
2020-04-19 18:34:08 +02:00
xmin = Max ( ix - 10 , 0 ) ;
xmax = Min ( ix + 10 , NUMSECTORS_X - 1 ) ;
2019-06-27 14:17:42 +02:00
assert ( xmin < = xmax ) ;
// Delete a block of sectors that we know is behind the camera
2020-08-20 23:43:13 +02:00
if ( TheCamera . GetForward ( ) . y > 0.0f ) {
2019-06-27 14:17:42 +02:00
// looking north
2020-04-19 18:34:08 +02:00
ymax = Max ( iy - 2 , 0 ) ;
ymin = Max ( iy - 10 , 0 ) ;
2019-06-27 14:17:42 +02:00
inc = 1 ;
} else {
// looking south
2020-04-19 18:34:08 +02:00
ymax = Min ( iy + 2 , NUMSECTORS_Y - 1 ) ;
ymin = Min ( iy + 10 , NUMSECTORS_Y - 1 ) ;
2019-06-27 14:17:42 +02:00
inc = - 1 ;
}
for ( x = xmin ; x < = xmax ; x + + ) {
for ( y = ymin ; y ! = ymax ; y + = inc ) {
sect = CWorld : : GetSector ( x , y ) ;
if ( DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] , mem ) | |
DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] , mem ) | |
DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] , mem ) )
return ;
}
}
2020-08-20 23:43:13 +02:00
while ( RemoveLoadedZoneModel ( ) )
if ( ms_memoryUsed < mem )
return ;
2019-06-27 14:17:42 +02:00
// Now a block that intersects with the camera's frustum
2020-08-20 23:43:13 +02:00
if ( TheCamera . GetForward ( ) . y > 0.0f ) {
2019-06-27 14:17:42 +02:00
// looking north
2020-04-19 18:34:08 +02:00
ymax = Max ( iy + 10 , 0 ) ;
ymin = Max ( iy - 2 , 0 ) ;
2019-06-27 14:17:42 +02:00
inc = 1 ;
} else {
// looking south
2020-04-19 18:34:08 +02:00
ymax = Min ( iy - 10 , NUMSECTORS_Y - 1 ) ;
ymin = Min ( iy + 2 , NUMSECTORS_Y - 1 ) ;
2019-06-27 14:17:42 +02:00
inc = - 1 ;
}
for ( x = xmin ; x < = xmax ; x + + ) {
for ( y = ymin ; y ! = ymax ; y + = inc ) {
sect = CWorld : : GetSector ( x , y ) ;
if ( DeleteRwObjectsNotInFrustumInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] , mem ) | |
DeleteRwObjectsNotInFrustumInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] , mem ) | |
DeleteRwObjectsNotInFrustumInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] , mem ) )
return ;
}
}
2020-08-20 23:43:13 +02:00
// this is gone in mobile together with RemoveReferencedTxds
// if(RemoveReferencedTxds(mem))
// return;
2019-06-27 14:17:42 +02:00
// As last resort, delete objects from the last step more aggressively
for ( x = xmin ; x < = xmax ; x + + ) {
for ( y = ymax ; y ! = ymin ; y - = inc ) {
sect = CWorld : : GetSector ( x , y ) ;
if ( DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_BUILDINGS ] , mem ) | |
DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_DUMMIES ] , mem ) | |
DeleteRwObjectsBehindCameraInSectorList ( sect - > m_lists [ ENTITYLIST_OBJECTS ] , mem ) )
return ;
}
}
}
2020-08-20 23:43:13 +02:00
while ( ms_memoryUsed > = mem & & RemoveLeastUsedModel ( 0 ) ) ;
2019-06-27 14:17:42 +02:00
}
2019-06-27 00:12:58 +02:00
void
CStreaming : : DeleteRwObjectsInSectorList ( CPtrList & list )
{
CPtrNode * node ;
CEntity * e ;
for ( node = list . first ; node ; node = node - > next ) {
e = ( CEntity * ) node - > item ;
2019-06-27 14:17:42 +02:00
if ( ! e - > bStreamingDontDelete & & ! e - > bImBeingRendered )
2019-06-27 00:12:58 +02:00
e - > DeleteRwObject ( ) ;
}
}
void
CStreaming : : DeleteRwObjectsInOverlapSectorList ( CPtrList & list , int32 x , int32 y )
{
CPtrNode * node ;
CEntity * e ;
for ( node = list . first ; node ; node = node - > next ) {
e = ( CEntity * ) node - > item ;
2019-06-27 14:17:42 +02:00
if ( e - > m_rwObject & & ! e - > bStreamingDontDelete & & ! e - > bImBeingRendered ) {
2019-06-27 00:12:58 +02:00
// Now this is pretty weird...
2020-08-20 23:43:13 +02:00
if ( Abs ( CWorld : : GetSectorIndexX ( e - > GetPosition ( ) . x ) - x ) > = 1.6f )
2019-06-27 00:12:58 +02:00
// {
e - > DeleteRwObject ( ) ;
// return; // BUG?
// }
else // FIX?
2020-08-20 23:43:13 +02:00
if ( Abs ( CWorld : : GetSectorIndexY ( e - > GetPosition ( ) . y ) - y ) > = 1.6f )
2019-06-27 00:12:58 +02:00
e - > DeleteRwObject ( ) ;
}
}
2019-06-20 14:49:16 +02:00
}
2019-06-27 14:17:42 +02:00
bool
2020-07-22 13:56:28 +02:00
CStreaming : : DeleteRwObjectsBehindCameraInSectorList ( CPtrList & list , size_t mem )
2019-06-27 14:17:42 +02:00
{
CPtrNode * node ;
CEntity * e ;
for ( node = list . first ; node ; node = node - > next ) {
e = ( CEntity * ) node - > item ;
if ( ! e - > bStreamingDontDelete & & ! e - > bImBeingRendered & &
2020-08-20 23:43:13 +02:00
e - > m_rwObject & & ms_aInfoForModel [ e - > GetModelIndex ( ) ] . m_next & &
FindPlayerPed ( ) - > m_pCurSurface ! = e ) {
2019-06-27 14:17:42 +02:00
e - > DeleteRwObject ( ) ;
2020-05-05 14:06:55 +02:00
if ( CModelInfo : : GetModelInfo ( e - > GetModelIndex ( ) ) - > GetNumRefs ( ) = = 0 ) {
2019-06-27 14:17:42 +02:00
RemoveModel ( e - > GetModelIndex ( ) ) ;
if ( ms_memoryUsed < mem )
return true ;
}
}
}
return false ;
}
bool
2020-07-22 13:56:28 +02:00
CStreaming : : DeleteRwObjectsNotInFrustumInSectorList ( CPtrList & list , size_t mem )
2019-06-27 14:17:42 +02:00
{
CPtrNode * node ;
CEntity * e ;
for ( node = list . first ; node ; node = node - > next ) {
e = ( CEntity * ) node - > item ;
if ( ! e - > bStreamingDontDelete & & ! e - > bImBeingRendered & &
2020-08-20 23:43:13 +02:00
e - > m_rwObject & & ( ! e - > IsVisible ( ) | | e - > bOffscreen ) & & ms_aInfoForModel [ e - > GetModelIndex ( ) ] . m_next ) {
2019-06-27 14:17:42 +02:00
e - > DeleteRwObject ( ) ;
2020-05-05 14:06:55 +02:00
if ( CModelInfo : : GetModelInfo ( e - > GetModelIndex ( ) ) - > GetNumRefs ( ) = = 0 ) {
2019-06-27 14:17:42 +02:00
RemoveModel ( e - > GetModelIndex ( ) ) ;
if ( ms_memoryUsed < mem )
return true ;
}
}
}
return false ;
}
void
CStreaming : : MakeSpaceFor ( int32 size )
{
2020-10-03 16:17:24 +02:00
# ifdef FIX_BUGS
# define MB (1024 * 1024)
if ( ms_memoryAvailable = = 0 ) {
extern size_t _dwMemAvailPhys ;
ms_memoryAvailable = ( _dwMemAvailPhys - 10 * MB ) / 2 ;
if ( ms_memoryAvailable < 65 * MB ) ms_memoryAvailable = 65 * MB ;
}
# undef MB
# endif
2020-07-22 13:56:28 +02:00
while ( ms_memoryUsed > = ms_memoryAvailable - size )
2020-05-06 21:54:43 +02:00
if ( ! RemoveLeastUsedModel ( STREAMFLAGS_20 ) ) {
2019-06-27 14:17:42 +02:00
DeleteRwObjectsBehindCamera ( ms_memoryAvailable - size ) ;
return ;
}
}
void
CStreaming : : LoadScene ( const CVector & pos )
{
CStreamingInfo * si , * prev ;
eLevelName level ;
2020-05-06 12:23:57 +02:00
level = CTheZones : : GetLevelFromPosition ( & pos ) ;
2019-06-27 14:17:42 +02:00
debug ( " Start load scene \n " ) ;
for ( si = ms_endRequestedList . m_prev ; si ! = & ms_startRequestedList ; si = prev ) {
prev = si - > m_prev ;
if ( ( si - > m_flags & ( STREAMFLAGS_KEEP_IN_MEMORY | STREAMFLAGS_PRIORITY ) ) = = 0 )
RemoveModel ( si - ms_aInfoForModel ) ;
}
CRenderer : : m_loadingPriority = false ;
DeleteAllRwObjects ( ) ;
2020-07-13 17:10:17 +02:00
if ( level = = LEVEL_GENERIC )
2020-05-05 17:04:43 +02:00
level = CGame : : currLevel ;
CGame : : currLevel = level ;
RemoveUnusedBigBuildings ( level ) ;
RequestBigBuildings ( level , pos ) ;
2020-07-13 17:10:17 +02:00
RequestBigBuildings ( LEVEL_GENERIC , pos ) ;
2020-05-05 17:04:43 +02:00
RemoveIslandsNotUsed ( level ) ;
LoadAllRequestedModels ( false ) ;
InstanceBigBuildings ( level , pos ) ;
2020-07-13 17:10:17 +02:00
InstanceBigBuildings ( LEVEL_GENERIC , pos ) ;
2020-08-20 23:43:13 +02:00
AddModelsToRequestList ( pos , STREAMFLAGS_20 ) ;
2020-05-05 17:04:43 +02:00
CRadar : : StreamRadarSections ( pos ) ;
2020-05-08 10:11:09 +02:00
if ( ! CGame : : IsInInterior ( ) ) {
for ( int i = 0 ; i < 5 ; i + + ) {
CZoneInfo zone ;
CTheZones : : GetZoneInfoForTimeOfDay ( & pos , & zone ) ;
int32 model = CCarCtrl : : ChooseCarModelToLoad ( CCarCtrl : : ChooseCarRating ( & zone ) ) ;
CStreaming : : RequestModel ( model , STREAMFLAGS_DEPENDENCY ) ;
}
}
2020-05-05 17:04:43 +02:00
LoadAllRequestedModels ( false ) ;
2020-05-08 20:56:42 +02:00
InstanceLoadedModels ( pos ) ;
2020-05-05 17:04:43 +02:00
for ( int i = 0 ; i < NUMSTREAMINFO ; i + + )
ms_aInfoForModel [ i ] . m_flags & = ~ STREAMFLAGS_20 ;
2019-06-27 14:17:42 +02:00
debug ( " End load scene \n " ) ;
}
2020-05-08 20:56:42 +02:00
void
CStreaming : : LoadSceneCollision ( const CVector & pos )
{
CColStore : : LoadCollision ( pos ) ;
CStreaming : : LoadAllRequestedModels ( false ) ;
}
2019-06-28 12:34:02 +02:00
void
2019-10-08 22:07:11 +02:00
CStreaming : : MemoryCardSave ( uint8 * buf , uint32 * size )
2019-06-28 12:34:02 +02:00
{
int i ;
2019-10-08 22:07:11 +02:00
* size = NUM_DEFAULT_MODELS ;
2019-10-06 23:39:25 +02:00
for ( i = 0 ; i < NUM_DEFAULT_MODELS ; i + + )
2019-06-28 12:34:02 +02:00
if ( ms_aInfoForModel [ i ] . m_loadState = = STREAMSTATE_LOADED )
2019-10-08 22:07:11 +02:00
buf [ i ] = ms_aInfoForModel [ i ] . m_flags ;
2019-06-28 12:34:02 +02:00
else
2019-10-08 22:07:11 +02:00
buf [ i ] = 0xFF ;
2019-06-28 12:34:02 +02:00
}
void
2019-10-08 22:07:11 +02:00
CStreaming : : MemoryCardLoad ( uint8 * buf , uint32 size )
2019-06-28 12:34:02 +02:00
{
uint32 i ;
2019-10-08 22:07:11 +02:00
assert ( size = = NUM_DEFAULT_MODELS ) ;
for ( i = 0 ; i < size ; i + + )
2019-06-28 12:34:02 +02:00
if ( ms_aInfoForModel [ i ] . m_loadState = = STREAMSTATE_LOADED )
2019-10-08 22:07:11 +02:00
if ( buf [ i ] ! = 0xFF )
ms_aInfoForModel [ i ] . m_flags = buf [ i ] ;
2019-06-28 12:34:02 +02:00
}
2019-08-15 16:51:39 +02:00
void
CStreaming : : UpdateForAnimViewer ( void )
{
if ( CStreaming : : ms_channelError = = - 1 ) {
2020-08-20 23:43:13 +02:00
CStreaming : : AddModelsToRequestList ( CVector ( 0.0f , 0.0f , 0.0f ) , 0 ) ;
2019-08-15 16:51:39 +02:00
CStreaming : : LoadRequestedModels ( ) ;
2020-07-22 13:56:28 +02:00
// original modifier was %d
sprintf ( gString , " Requested %d, memory size %zuK \n " , CStreaming : : ms_numModelsRequested , 2 * CStreaming : : ms_memoryUsed ) ;
2019-08-15 16:51:39 +02:00
}
else {
CStreaming : : RetryLoadFile ( CStreaming : : ms_channelError ) ;
}
}
2020-11-26 17:11:55 +01:00
void
CStreaming : : PrintStreamingBufferState ( )
{
char str [ 128 ] ;
wchar wstr [ 128 ] ;
uint32 offset , size ;
CTimer : : Stop ( ) ;
int i = 0 ;
while ( i < NUMSTREAMINFO ) {
while ( true ) {
int j = 0 ;
DoRWStuffStartOfFrame ( 50 , 50 , 50 , 0 , 0 , 0 , 255 ) ;
CPad : : UpdatePads ( ) ;
CSprite2d : : InitPerFrame ( ) ;
CFont : : InitPerFrame ( ) ;
DefinedState ( ) ;
CRect unusedRect ( 0 , 0 , RsGlobal . maximumWidth , RsGlobal . maximumHeight ) ;
CRGBA unusedColor ( 255 , 255 , 255 , 255 ) ;
CFont : : SetFontStyle ( FONT_BANK ) ;
CFont : : SetBackgroundOff ( ) ;
CFont : : SetWrapx ( DEFAULT_SCREEN_WIDTH ) ;
CFont : : SetScale ( 0.5f , 0.75f ) ;
CFont : : SetCentreOff ( ) ;
CFont : : SetCentreSize ( DEFAULT_SCREEN_WIDTH ) ;
CFont : : SetJustifyOff ( ) ;
CFont : : SetColor ( CRGBA ( 200 , 200 , 200 , 200 ) ) ;
CFont : : SetBackGroundOnlyTextOff ( ) ;
int modelIndex = i ;
if ( modelIndex < NUMSTREAMINFO ) {
int y = 24 ;
for ( ; j < 34 & & modelIndex < NUMSTREAMINFO ; modelIndex + + ) {
CStreamingInfo * streamingInfo = & ms_aInfoForModel [ modelIndex ] ;
CBaseModelInfo * modelInfo = CModelInfo : : GetModelInfo ( modelIndex ) ;
if ( streamingInfo - > m_loadState ! = STREAMSTATE_LOADED | | ! streamingInfo - > GetCdPosnAndSize ( offset , size ) )
continue ;
if ( modelIndex > = STREAM_OFFSET_TXD )
sprintf ( str , " txd %s, refs %d, size %dK, flags 0x%x " , CTxdStore : : GetTxdName ( modelIndex - STREAM_OFFSET_TXD ) ,
CTxdStore : : GetNumRefs ( modelIndex - STREAM_OFFSET_TXD ) , 2 * size , streamingInfo - > m_flags ) ;
else
2021-01-08 20:53:11 +01:00
sprintf ( str , " model %d,%s, refs%d, size%dK, flags%x " , modelIndex , modelInfo - > GetModelName ( ) , modelInfo - > GetNumRefs ( ) , 2 * size ,
2020-11-26 17:11:55 +01:00
streamingInfo - > m_flags ) ;
AsciiToUnicode ( str , wstr ) ;
CFont : : PrintString ( 24.0f , y , wstr ) ;
y + = 12 ;
j + + ;
}
}
if ( CPad : : GetPad ( 1 ) - > GetCrossJustDown ( ) )
i = modelIndex ;
if ( ! CPad : : GetPad ( 1 ) - > GetTriangleJustDown ( ) )
break ;
i = 0 ;
CFont : : DrawFonts ( ) ;
DoRWStuffEndOfFrame ( ) ;
}
CFont : : DrawFonts ( ) ;
DoRWStuffEndOfFrame ( ) ;
}
CTimer : : Update ( ) ;
2021-01-27 16:26:08 +01:00
}