Files
CydandClaude Fable 5 12b31187f9 Move the build to VS2022 (v143) with runtime parity against VC9
Hand-converted the four .vcproj projects to .vcxproj (Win32, v143,
Windows 11 SDK + DXSDK June 2010 for d3dx9/dxerr only). WinTesla.sln now
builds the v143 projects; the legacy solution is kept as WinTesla_vc9.sln.

Kept: /Zp1 in Munga_L4+RP_L4, Unicode, x86, /DYNAMICBASE:NO,
/FORCE:MULTIPLE (header-defined globals still duplicated across TUs).
Changed: CRT unified to /MD(d); import libs linked by the exes instead of
merged into Munga_L4.lib; WINDOWS_IGNORE_PACKING_MISMATCH and
_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS defined;
legacy_stdio_definitions.lib for the June-2010 dxerr.lib.

Source fixes, all behavior-preserving: Time gains standard (non-volatile)
copy-ctor/assignment overloads (rvalues cannot bind to volatile& in
standard C++); operator==(SOCKADDR_IN&,...) made inline; L4DINPUT's
Enum*Callback pair renamed DIEnum* (collided with L4CTRL's under LTCG);
std::ios.in -> std::ios::in in CAMMGR.cpp.

Verified: VC9 baseline rebuilt from this tree first, then the v143 build
compared against it in a sandboxed game working copy - identical logs and
behavior through RIO init (against vRIO) and mission load, including the
same pre-existing AV in d3d_OBJECT::LoadTexture (L4D3D.cpp:262) that both
toolchains hit; documented in BUILD.md 4 as the next debugging target.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 12:22:31 -05:00

749 lines
17 KiB
C++

#include "munga.h"
#pragma hdrstop
#include "cammgr.h"
#include "mission.h"
#include "app.h"
#include "notation.h"
#include "namelist.h"
//##########################################################################
//##################### CameraInstanceManager #######################
//##########################################################################
//##########################################################################
// Construction and Destruction
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstanceManager::CameraInstanceManager() :
cameraList(NULL)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Initialize local member data
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
cameraIterator = new SChainIteratorOf<CameraInstance*>(cameraList);
Register_Object(cameraIterator);
InitializeCameraInstances();
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstanceManager::~CameraInstanceManager()
{
DeleteCameraList();
Unregister_Object(cameraIterator);
delete cameraIterator;
cameraIterator = NULL;
Check_Fpu();
}
//##########################################################################
// CameraInstance Creation and Deletion Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CameraInstanceManager::FindUniqueCameraID()
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Finds a cameraID that has been freed up or the next sequential number
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
SChainIteratorOf<CameraInstance*> iterator(cameraList);
CameraInstance *camera_instance;
int camera_ID = 0;
Logical ID_exists = False;
while(1)
{
//
//~~~~~~~~~~~~~~~~~~~~
// Reset the iterator
//~~~~~~~~~~~~~~~~~~~~
//
iterator.First();
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Iterate through the list of all cameraInstances for every ID Chosen
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
while ( (camera_instance = iterator.ReadAndNext()) != NULL)
{
if(camera_ID == camera_instance->GetCameraID())
{
ID_exists = True;
break;
}
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// If this cameraID not already used return the ID
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
if(!ID_exists)
{
break;
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Otherwise increment the ID and reset the boolean
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
++camera_ID;
ID_exists = False;
}
Check_Fpu();
return camera_ID;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstanceManager::SetCamera(
const Origin &new_origin,
CameraInstance *camera_instance
)
{
if(!camera_instance)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// No camera passed as an argument use cameraIterator
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
camera_instance = cameraIterator->GetCurrent();
if(!camera_instance)
{
CreateCameraInstance(new_origin);
}
else
{
camera_instance->SetLocalOrigin(new_origin);
}
}
else
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Camera passed in set its origin
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
camera_instance->SetLocalOrigin(new_origin);
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::CreateCameraInstance(const Origin &new_origin)
{
Check(this);
//
//~~~~~~~~~~~~~~~~~~~~~~~~
// Find a Unique CameraID
//~~~~~~~~~~~~~~~~~~~~~~~~
//
int camera_ID;
camera_ID = FindUniqueCameraID();
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create the new cameraInstance
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance *camera_instance =
new CameraInstance(
camera_ID,
new_origin
);
Register_Object(camera_instance);
AddCameraInstance(camera_instance);
Check_Fpu();
return camera_instance;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::AddCameraInstance(CameraInstance *camera_instance)
{
Check(this);
Check(cameraIterator);
Check(&cameraList);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Insert the new Camera Instance into the cameraList
// & Point the cameraIterator to it
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
if (!cameraIterator->GetCurrent())
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// If nothing in the cameraList create the first element
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
cameraList.Add(camera_instance);
cameraIterator->First();
Tell("Created the First Camera Instance \n");
}
else
{
cameraList.Add(camera_instance);
cameraIterator->Next();
Tell("Created a Camera Instance \n");
}
Check_Fpu();
return camera_instance;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::DeleteCameraInstance()
{
CameraInstance *camera_instance = cameraIterator->GetCurrent();
if(!camera_instance)
{
return NULL;
}
cameraIterator->Remove();
if(!cameraIterator->GetCurrent())
{
cameraIterator->First();
}
Unregister_Object(camera_instance);
delete camera_instance;
return GetCurrent();
}
//##########################################################################
// CameraList Manipulator Functions
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstanceManager::DeleteCameraList()
{
while (cameraIterator->GetCurrent() != NULL)
{
DeleteCameraInstance();
}
}
//##########################################################################
// CameraList Iterator Manipulator Functions
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::IncrementIterator()
{
Check(this);
if (cameraIterator->GetCurrent())
{
Check(cameraIterator);
cameraIterator->ReadAndNext();
if (!cameraIterator->GetCurrent())
{
cameraIterator->First();
}
}
Check_Fpu();
return GetCurrent();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::DecrementIterator()
{
Check(this);
if (cameraIterator->GetCurrent())
{
Check(cameraIterator);
cameraIterator->ReadAndPrevious();
if (!cameraIterator->GetCurrent())
{
cameraIterator->Last();
}
}
Check_Fpu();
return GetCurrent();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::AdvanceIterator(const CameraInstance &camera_instance)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Search for the camera_instance in the cameraList
// Iterator points to camera_instance upon return
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Check(&camera_instance);
Check(&cameraList);
Check(cameraIterator);
CameraInstance *current_instance;
cameraIterator->First();
while((current_instance = cameraIterator->GetCurrent()) != NULL)
{
if(current_instance == &camera_instance)
{
Check_Fpu();
return current_instance;
}
cameraIterator->Next();
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// camera_instance not found return NULL
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Check_Fpu();
return NULL;
}
//##########################################################################
// CameraList Searching and Query Functions
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::FindClosestCamera(const Point3D &point_3D)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Use a Simple distance formula to find closest camera
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Check(this);
CameraInstance *closest_camera = NULL;
Scalar dist_to_goal, min_dist=1e8f;
SChainIteratorOf<CameraInstance*> iterator(cameraList);
CameraInstance *camera_instance;
while ( (camera_instance = iterator.ReadAndNext()) != NULL)
{
Check(camera_instance);
if (camera_instance->CanCameraSee(point_3D))
{
Vector3D v;
v.Subtract(point_3D, camera_instance->GetPosition());
dist_to_goal = v.LengthSquared();
Check_Fpu();
if (dist_to_goal < min_dist)
{
min_dist = dist_to_goal;
closest_camera = camera_instance;
}
}
}
Check_Fpu();
return closest_camera;
}
//##########################################################################
// Test Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
CameraInstanceManager::TestInstance() const
{
return True;
}
//##########################################################################
// Tool Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstanceManager::InitializeCameraInstances()
{
Check(application);
ResourceDescription::ResourceID map_ID;
map_ID = application->GetCurrentMission()->GetMapID();
ResourceFile *res_file;
res_file = application->GetResourceFile();
Check(res_file);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create the camera filename from the map name
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ResourceDescription *res = res_file->FindResourceDescription(map_ID);
Check(res);
Str_Copy(
cameraFilename,
"cameras\\",
sizeof(cameraFilename)
);
//
// cam name matches map name
//
Str_Cat(
cameraFilename,
res->resourceName,
sizeof(cameraFilename)
);
//
// trunc cam name to DOS filename size
//
int name_length = strlen(cameraFilename);
if(name_length > 17)
{
cameraFilename[17] = '\0';
}
//
// Add the extension
//
Str_Cat(
cameraFilename,
".cam",
sizeof(cameraFilename)
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~
// See if the file exists
//~~~~~~~~~~~~~~~~~~~~~~~~
//
std::fstream cam_file;
//cam_file.open(cameraFilename, std::ios::nocreate | std::ios::in | std::ios::out);
// following alternate line created by Ryan Bunker on 1/6/07
cam_file.open(cameraFilename, std::ios::in);
if(cam_file) //NOTE: this appears broken (RB 1/6/07)
{
cam_file.close();
ReadNotationFile();
}
else
{
cam_file.close();
CreateStreamedCameraInstances(res_file, res->resourceName);
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstanceManager::ReadNotationFile()
{
Check(this);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create a Notation file out of the camera file
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NotationFile *cam_file = new NotationFile(cameraFilename);
Register_Object(cam_file);
NameList* camera_namelist = cam_file->MakePageList();
Register_Object(camera_namelist);
NameList::Entry *camera_entry = camera_namelist->GetFirstEntry();
char
camera_page_name[128];
while (camera_entry)
{
Str_Copy(
camera_page_name,
camera_entry->GetName(),
sizeof(camera_page_name)
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create a new camera Instance for this page
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance *camera_instance;
const char *camera_data_entry;
int cam_type;
if(
!cam_file->GetEntry(
camera_page_name,
"cameraType",
&camera_data_entry
)
)
{
cam_type = CameraInstance::DefaultCameraType;
}
else
{
Check_Pointer(camera_data_entry);
cam_type = CameraInstance::FindCameraType(camera_data_entry);
}
switch (cam_type)
{
case CameraInstance::DefaultCameraType:
camera_instance = new CameraInstance(cam_file, camera_page_name);
break;
case CameraInstance::AlwaysSeesCameraType:
camera_instance =
new AlwaysSeesCameraInstance(cam_file, camera_page_name);
break;
}
Register_Object(camera_instance);
AddCameraInstance(camera_instance);
camera_entry = camera_entry->GetNextEntry();
}
Unregister_Object(camera_namelist);
delete camera_namelist;
Unregister_Object(cam_file);
delete cam_file;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#define PAGE_NAME_SIZE 128
void
CameraInstanceManager::CreateStreamedCameraInstances(
ResourceFile *res_file,
const char *map_name
)
{
Check(this);
Check_Pointer(res_file);
Check_Pointer(map_name);
ResourceDescription *res =
res_file->FindResourceDescription(
map_name,
ResourceDescription::CameraStreamResourceType
);
if (!res)
{
Check_Fpu();
return;
}
res->Lock();
MemoryStream camera_stream(res->resourceAddress, res->resourceSize);
int camera_count = *(int*)camera_stream.GetPointer();
camera_stream.AdvancePointer(sizeof(camera_count));
//
//--------------------
// Read in each camera
//--------------------
//
while (camera_count--)
{
Check(&camera_stream);
CameraInstance::StreamedInstance *model =
(CameraInstance::StreamedInstance*)camera_stream.GetPointer();
Check_Pointer(model);
CameraInstance *camera_instance;
switch (model->cameraType)
{
case CameraInstance::DefaultCameraType:
camera_instance = new CameraInstance(model);
break;
case CameraInstance::AlwaysSeesCameraType:
camera_instance = new AlwaysSeesCameraInstance(model);
break;
}
Register_Object(camera_instance);
AddCameraInstance(camera_instance);
camera_stream.AdvancePointer(model->instanceSize);
}
res->Unlock();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstanceManager::WriteNotationFile()
{
Check(this);
Check(&cameraList);
NotationFile *camera_stream = new NotationFile();
Register_Object(camera_stream);
if(!camera_stream)
{
Fail("Error Opening Camera File\n");
}
SChainIteratorOf<CameraInstance*> iterator(cameraList);
CameraInstance *camera_instance;
iterator.First();
while ( (camera_instance = iterator.ReadAndNext()) != NULL)
{
camera_instance->WriteNotationPage(camera_stream);
}
camera_stream->WriteFile(cameraFilename);
Unregister_Object(camera_stream);
delete camera_stream;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#define PAGE_NAME_SIZE 128
ResourceDescription::ResourceID
CameraInstanceManager::CreateCameraInstancesStream(
ResourceFile *resource_file,
const char *camera_name,
const ResourceDirectories *directories
)
{
Check_Pointer(camera_name);
Check_Pointer(directories);
//
//-------------------
// Open the .cam file
//-------------------
//
int length = strlen(camera_name) + strlen(directories->mapDirectory)+ 1;
char *filename = new char[length];
Register_Pointer(filename);
Str_Copy(filename, directories->mapDirectory, length);
strncat(filename, camera_name, strlen(camera_name)-3);
Str_Cat(filename, "cam", length);
NotationFile *camera_notation = new NotationFile(filename);
Register_Object(camera_notation);
if (camera_notation->PageCount() == 0)
{
DEBUG_STREAM << "Missing .cam file" << std::endl << std::flush;
Dump_And_Die:
Unregister_Object(camera_notation);
delete camera_notation;
Unregister_Pointer(filename);
delete[] filename;
return ResourceDescription::NullResourceID;
}
int camera_count = 0;
NameList *pagelist = camera_notation->MakePageList();
Register_Object(pagelist);
NameList::Entry *entry = pagelist->GetFirstEntry();
char page_name[PAGE_NAME_SIZE];
while (entry)
{
++camera_count;
entry = entry->GetNextEntry();
}
size_t array_size =
sizeof(CameraInstance::StreamedInstance) * camera_count * 2;
long *camera_array = new long[(array_size+3) >> 2];
Register_Pointer(camera_array);
MemoryStream camera_stream(camera_array, array_size);
*(int*)camera_stream.GetPointer() = camera_count;
camera_stream.AdvancePointer(sizeof(camera_count));
entry = pagelist->GetFirstEntry();
while (entry)
{
Str_Copy(
page_name,
entry->GetName(),
sizeof(page_name)
);
if(strcmp(page_name, "CameraInfo") == 0)
{
entry = entry->GetNextEntry();
continue;
}
Check(&camera_stream);
CameraInstance::StreamedInstance *model =
(CameraInstance::StreamedInstance*)camera_stream.GetPointer();
Check_Pointer(model);
if (
!CameraInstance::CreateStreamedInstance(
model,
camera_notation,
page_name
)
)
{
Unregister_Pointer(camera_array);
delete[] camera_array;
Unregister_Object(pagelist);
delete pagelist;
goto Dump_And_Die;
}
camera_stream.AdvancePointer(model->instanceSize);
entry = entry->GetNextEntry();
}
//
//-------------------------------
// Write the stream out to disk.
//
Str_Copy(filename, camera_name, length);
filename[strlen(camera_name)-4] = '\0';
ResourceDescription *new_res =
resource_file->AddResource(
filename,
ResourceDescription::CameraStreamResourceType,
1,
ResourceDescription::LoadOnDemandFlag,
camera_array,
camera_stream.GetBytesUsed()
);
Check(new_res);
//-----------
// Free Mem
//
Unregister_Pointer(camera_array);
delete[] camera_array;
Unregister_Pointer(filename);
delete[] filename;
Unregister_Object(camera_notation);
delete camera_notation;
Unregister_Object(pagelist);
delete pagelist;
return new_res->resourceID;
}