2020-12-28 09:51:40 +01:00
|
|
|
#include "driver2.h"
|
|
|
|
#include "models.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "spool.h"
|
|
|
|
#include "mission.h"
|
|
|
|
#include "cars.h"
|
|
|
|
|
|
|
|
#include "STRINGS.H"
|
2020-04-09 17:53:52 +02:00
|
|
|
|
2020-05-18 14:11:07 +02:00
|
|
|
MODEL dummyModel = { 0 };
|
2020-04-10 01:29:12 +02:00
|
|
|
|
2020-04-05 15:53:08 +02:00
|
|
|
char* modelname_buffer = NULL;
|
|
|
|
char *car_models_lump = NULL;
|
2020-03-27 21:47:29 +01:00
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
MODEL* modelpointers[MAX_MODEL_SLOTS];
|
|
|
|
MODEL* pLodModels[MAX_MODEL_SLOTS];
|
|
|
|
|
2020-04-10 01:29:12 +02:00
|
|
|
int num_models_in_pack = 0;
|
|
|
|
|
|
|
|
unsigned short *Low2HighDetailTable = NULL;
|
|
|
|
unsigned short *Low2LowerDetailTable = NULL;
|
2020-11-07 18:37:23 +01:00
|
|
|
|
2020-11-12 17:51:44 +01:00
|
|
|
// [A]
|
2020-11-16 19:21:31 +01:00
|
|
|
int staticModelSlotBitfield[48];
|
|
|
|
|
|
|
|
// [A] returns freed slot count
|
|
|
|
int CleanSpooledModelSlots()
|
2020-11-12 17:51:44 +01:00
|
|
|
{
|
|
|
|
int i;
|
2020-11-16 19:21:31 +01:00
|
|
|
int num_freed;
|
|
|
|
|
|
|
|
num_freed = 0;
|
2020-11-12 17:51:44 +01:00
|
|
|
|
|
|
|
// assign model pointers
|
|
|
|
for (i = 0; i < MAX_MODEL_SLOTS; i++) // [A] bug fix. Init with dummyModel
|
|
|
|
{
|
2020-11-16 19:21:31 +01:00
|
|
|
// if bit does not indicate usage - reset to dummy model
|
|
|
|
if((staticModelSlotBitfield[i >> 5] & 1 << (i & 31)) == 0)
|
2020-11-12 17:51:44 +01:00
|
|
|
{
|
2020-11-16 19:21:31 +01:00
|
|
|
if(modelpointers[i] != &dummyModel)
|
|
|
|
{
|
|
|
|
modelpointers[i] = &dummyModel;
|
|
|
|
pLodModels[i] = &dummyModel;
|
|
|
|
|
|
|
|
num_freed++;
|
|
|
|
}
|
2020-11-12 17:51:44 +01:00
|
|
|
}
|
|
|
|
}
|
2020-11-16 19:21:31 +01:00
|
|
|
|
|
|
|
return num_freed;
|
2020-11-12 17:51:44 +01:00
|
|
|
}
|
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
// [D] [T]
|
2020-04-05 15:53:08 +02:00
|
|
|
void ProcessMDSLump(char *lump_file, int lump_size)
|
2020-03-27 21:47:29 +01:00
|
|
|
{
|
2020-11-07 18:37:23 +01:00
|
|
|
char* mdsfile;
|
2020-05-12 10:40:49 +02:00
|
|
|
MODEL *model;
|
2020-04-05 22:04:37 +02:00
|
|
|
MODEL *parentmodel;
|
|
|
|
int modelAmts;
|
2020-11-07 18:37:23 +01:00
|
|
|
int i, size;
|
2020-04-05 22:04:37 +02:00
|
|
|
|
|
|
|
modelAmts = *(int *)lump_file;
|
2020-11-07 18:37:23 +01:00
|
|
|
mdsfile = (lump_file + 4);
|
2020-04-05 22:04:37 +02:00
|
|
|
num_models_in_pack = modelAmts;
|
|
|
|
|
2020-11-16 19:21:31 +01:00
|
|
|
// [A] usage bits
|
|
|
|
ClearMem((char*)staticModelSlotBitfield, sizeof(staticModelSlotBitfield));
|
|
|
|
|
2020-04-05 22:04:37 +02:00
|
|
|
// assign model pointers
|
2020-11-07 18:37:23 +01:00
|
|
|
for (i = 0; i < MAX_MODEL_SLOTS; i++) // [A] bug fix. Init with dummyModel
|
2020-04-05 22:04:37 +02:00
|
|
|
{
|
2020-11-07 18:37:23 +01:00
|
|
|
modelpointers[i] = &dummyModel;
|
|
|
|
pLodModels[i] = &dummyModel;
|
|
|
|
}
|
2020-04-05 22:04:37 +02:00
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
for (i = 0; i < modelAmts; i++)
|
|
|
|
{
|
|
|
|
size = *(int*)mdsfile;
|
|
|
|
mdsfile += sizeof(int);
|
2020-04-05 22:04:37 +02:00
|
|
|
|
2020-11-12 17:51:44 +01:00
|
|
|
if (size)
|
|
|
|
{
|
2020-11-16 19:21:31 +01:00
|
|
|
// add the usage bit
|
|
|
|
staticModelSlotBitfield[i >> 5] |= 1 << (i & 31);
|
2020-11-12 17:51:44 +01:00
|
|
|
|
2020-11-16 19:21:31 +01:00
|
|
|
model = (MODEL*)mdsfile;
|
2020-11-12 17:51:44 +01:00
|
|
|
modelpointers[i] = model;
|
|
|
|
}
|
2020-05-12 10:40:49 +02:00
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
mdsfile += size;
|
2020-04-05 15:53:08 +02:00
|
|
|
}
|
2020-04-05 22:04:37 +02:00
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
// process parent instances
|
|
|
|
for (i = 0; i < modelAmts; i++)
|
2020-04-05 22:04:37 +02:00
|
|
|
{
|
2020-11-07 18:37:23 +01:00
|
|
|
model = modelpointers[i];
|
2020-04-05 22:04:37 +02:00
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
if (model->instance_number != -1)
|
|
|
|
{
|
|
|
|
parentmodel = modelpointers[model->instance_number];
|
2020-04-05 22:04:37 +02:00
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
if (parentmodel->collision_block != 0)
|
|
|
|
model->collision_block = (int)(char*)parentmodel + parentmodel->collision_block;
|
2020-04-05 22:04:37 +02:00
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
// convert to real offsets
|
|
|
|
model->vertices = (int)(char*)parentmodel + parentmodel->vertices;
|
|
|
|
model->normals = (int)(char*)parentmodel + parentmodel->normals;
|
|
|
|
model->point_normals = (int)(char*)parentmodel + parentmodel->point_normals;
|
|
|
|
}
|
2020-04-05 15:53:08 +02:00
|
|
|
}
|
2020-04-05 22:04:37 +02:00
|
|
|
|
|
|
|
// process models without parents
|
2020-11-07 18:37:23 +01:00
|
|
|
for (i = 0; i < modelAmts; i++)
|
2020-05-12 10:40:49 +02:00
|
|
|
{
|
2020-11-07 18:37:23 +01:00
|
|
|
model = modelpointers[i];
|
2020-05-12 10:40:49 +02:00
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
if (model->instance_number == -1)
|
|
|
|
{
|
|
|
|
if (model->collision_block != 0)
|
|
|
|
model->collision_block += (int)(char*)model;
|
2020-05-12 10:40:49 +02:00
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
model->vertices += (int)(char*)model;
|
|
|
|
model->normals += (int)(char*)model;
|
|
|
|
model->point_normals += (int)(char*)model;
|
|
|
|
}
|
2020-05-12 10:40:49 +02:00
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
model->poly_block += (int)(char*)model;
|
2020-04-05 15:53:08 +02:00
|
|
|
}
|
2020-03-27 21:47:29 +01:00
|
|
|
}
|
|
|
|
|
2020-11-07 18:37:23 +01:00
|
|
|
// [D] [T]
|
2020-04-05 15:53:08 +02:00
|
|
|
int ProcessCarModelLump(char *lump_ptr, int lump_size)
|
2020-03-27 21:47:29 +01:00
|
|
|
{
|
2020-05-14 13:11:37 +02:00
|
|
|
int size;
|
|
|
|
int *offsets;
|
|
|
|
char *models_offset;
|
|
|
|
|
|
|
|
|
|
|
|
MODEL *model;
|
|
|
|
int model_number;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
int specMemReq;
|
|
|
|
|
|
|
|
specMemReq = 0;
|
|
|
|
|
|
|
|
models_offset = lump_ptr + 4 + 160; // also skip model count
|
|
|
|
offsets = (int*)(lump_ptr + 100);
|
|
|
|
|
|
|
|
// compute special memory requirement for spooling
|
|
|
|
for (i = 8; i < 13; i++)
|
|
|
|
{
|
|
|
|
int cleanOfs = offsets[0];
|
|
|
|
int damOfs = offsets[1];
|
|
|
|
int lowOfs = offsets[2];
|
|
|
|
|
|
|
|
if (cleanOfs != -1)
|
2020-04-09 17:36:53 +02:00
|
|
|
{
|
2020-05-14 13:11:37 +02:00
|
|
|
size = ((MODEL*)(models_offset + cleanOfs))->poly_block;
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
if (damOfs != -1)
|
|
|
|
size += ((MODEL*)(models_offset + damOfs))->normals;
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
if (lowOfs != -1)
|
|
|
|
size += ((MODEL*)(models_offset + lowOfs))->poly_block;
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
size = (size + 2048) + 2048;
|
|
|
|
if (size > specMemReq)
|
|
|
|
specMemReq = size;
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
size = (damOfs - cleanOfs) + 2048;
|
|
|
|
if (size > specMemReq)
|
|
|
|
specMemReq = size;
|
|
|
|
|
|
|
|
size = (lowOfs - damOfs) + 2048;
|
|
|
|
if (size > specMemReq)
|
|
|
|
specMemReq = size;
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
if (i != 11) // what the fuck is this hack about?
|
2020-04-09 17:36:53 +02:00
|
|
|
{
|
2020-05-14 13:11:37 +02:00
|
|
|
// next model offset?
|
|
|
|
size = (offsets[3] - lowOfs) + 2048;
|
|
|
|
|
|
|
|
if(size > specMemReq)
|
|
|
|
specMemReq = size;
|
2020-04-05 15:53:08 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
offsets += 3;
|
|
|
|
}
|
2020-05-14 08:57:20 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
for (i = 0; i < 5; i++)
|
|
|
|
{
|
2020-05-16 12:07:52 +02:00
|
|
|
gCarCleanModelPtr[i] = NULL;
|
|
|
|
gCarDamModelPtr[i] = NULL;
|
|
|
|
gCarLowModelPtr[i] = NULL;
|
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
if (i == 4)
|
2021-04-04 11:24:16 +02:00
|
|
|
specmallocptr = (char*)mallocptr;
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
model_number = MissionHeader->residentModels[i];
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
if (model_number == 13)
|
2020-04-09 17:36:53 +02:00
|
|
|
{
|
2020-05-14 13:11:37 +02:00
|
|
|
model_number = 10 - (MissionHeader->residentModels[0] + MissionHeader->residentModels[1] + MissionHeader->residentModels[2]);
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
if (model_number < 1)
|
|
|
|
model_number = 1;
|
|
|
|
else if (model_number > 4)
|
|
|
|
model_number = 4;
|
2020-04-05 15:53:08 +02:00
|
|
|
}
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
if (model_number != -1)
|
2020-04-09 17:36:53 +02:00
|
|
|
{
|
2020-05-14 13:11:37 +02:00
|
|
|
offsets = (int *)(lump_ptr + 4 + model_number * sizeof(int)*3);
|
|
|
|
|
|
|
|
int cleanOfs = offsets[0];
|
|
|
|
int damOfs = offsets[1];
|
|
|
|
int lowOfs = offsets[2];
|
2021-04-25 00:30:34 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
if (cleanOfs != -1)
|
2020-05-13 11:57:51 +02:00
|
|
|
{
|
2021-03-27 11:05:39 +01:00
|
|
|
D_MALLOC_BEGIN();
|
2021-04-04 11:24:16 +02:00
|
|
|
model = GetCarModel(models_offset + cleanOfs, (char**)&mallocptr, 1, model_number, CAR_MODEL_CLEAN);
|
2020-05-14 13:11:37 +02:00
|
|
|
gCarCleanModelPtr[i] = model;
|
2021-03-27 11:05:39 +01:00
|
|
|
D_MALLOC_END();
|
2020-04-05 15:53:08 +02:00
|
|
|
}
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
if (damOfs != -1)
|
2020-05-13 11:57:51 +02:00
|
|
|
{
|
2021-03-27 11:05:39 +01:00
|
|
|
D_MALLOC_BEGIN();
|
2021-04-04 11:24:16 +02:00
|
|
|
model = GetCarModel(models_offset + damOfs, (char**)&mallocptr, 0, model_number, CAR_MODEL_DAMAGED);
|
2020-05-14 13:11:37 +02:00
|
|
|
gCarDamModelPtr[i] = model;
|
2021-03-27 11:05:39 +01:00
|
|
|
D_MALLOC_END();
|
2020-04-05 15:53:08 +02:00
|
|
|
}
|
2021-04-25 00:30:34 +02:00
|
|
|
|
2020-05-14 13:11:37 +02:00
|
|
|
if (lowOfs != -1)
|
2020-05-13 11:57:51 +02:00
|
|
|
{
|
2021-03-27 11:05:39 +01:00
|
|
|
D_MALLOC_BEGIN();
|
2021-04-04 11:24:16 +02:00
|
|
|
model = GetCarModel(models_offset + lowOfs, (char**)&mallocptr, 1, model_number, CAR_MODEL_LOWDETAIL);
|
2020-05-14 13:11:37 +02:00
|
|
|
gCarLowModelPtr[i] = model;
|
2021-03-27 11:05:39 +01:00
|
|
|
D_MALLOC_END();
|
2020-04-05 15:53:08 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-14 13:11:37 +02:00
|
|
|
}
|
2020-05-13 18:04:14 +02:00
|
|
|
|
2021-03-27 11:05:39 +01:00
|
|
|
D_MALLOC_BEGIN();
|
2020-05-14 13:11:37 +02:00
|
|
|
mallocptr = specmallocptr + specMemReq;
|
|
|
|
specLoadBuffer = specmallocptr + specMemReq - 2048;
|
2021-03-27 11:05:39 +01:00
|
|
|
D_MALLOC_END();
|
2020-04-09 17:36:53 +02:00
|
|
|
|
2020-04-05 15:53:08 +02:00
|
|
|
buildNewCars();
|
2020-04-09 17:42:17 +02:00
|
|
|
|
|
|
|
return 0;
|
2020-03-27 21:47:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-29 20:21:33 +01:00
|
|
|
char* CarModelTypeNames[] = {
|
|
|
|
"CLEAN",
|
|
|
|
"DAMAGED",
|
|
|
|
"LOW",
|
|
|
|
};
|
|
|
|
|
2020-11-29 23:22:00 +01:00
|
|
|
#ifndef PSX
|
|
|
|
// [A] loads car model from file
|
|
|
|
char* LoadCarModelFromFile(char* dest, int modelNumber, int type)
|
2020-03-27 21:47:29 +01:00
|
|
|
{
|
2020-11-29 20:21:33 +01:00
|
|
|
char* mem;
|
|
|
|
char filename[64];
|
2020-04-05 15:53:08 +02:00
|
|
|
|
2020-11-29 20:21:33 +01:00
|
|
|
sprintf(filename, "LEVELS\\%s\\CARMODEL_%d_%s.DMODEL", LevelNames[GameLevel], modelNumber, CarModelTypeNames[type-1]);
|
|
|
|
if(FileExists(filename))
|
|
|
|
{
|
2021-04-04 11:24:16 +02:00
|
|
|
mem = (char*)(dest ? dest : (_other_buffer + modelNumber * 0x10000 + (type-1) * 0x4000));
|
2020-11-29 23:22:00 +01:00
|
|
|
|
2020-11-29 20:21:33 +01:00
|
|
|
// get model from file
|
|
|
|
Loadfile(filename, mem);
|
2020-11-29 23:22:00 +01:00
|
|
|
return mem;
|
2020-11-29 20:21:33 +01:00
|
|
|
}
|
2020-11-29 23:22:00 +01:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-11-29 20:21:33 +01:00
|
|
|
#endif
|
2020-04-09 17:53:52 +02:00
|
|
|
|
2020-11-29 23:22:00 +01:00
|
|
|
// [D] [T]
|
|
|
|
MODEL* GetCarModel(char *src, char **dest, int KeepNormals, int modelNumber, int type)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
MODEL *model;
|
|
|
|
char* mem;
|
|
|
|
|
|
|
|
#ifndef PSX
|
|
|
|
mem = LoadCarModelFromFile(NULL, modelNumber, type);
|
|
|
|
|
|
|
|
if (!mem) // fallback to lump
|
|
|
|
mem = src;
|
|
|
|
#else
|
|
|
|
mem = src;
|
|
|
|
#endif
|
2020-11-29 20:21:33 +01:00
|
|
|
|
|
|
|
model = (MODEL *)*dest;
|
|
|
|
|
2020-05-13 20:10:01 +02:00
|
|
|
if (KeepNormals == 0)
|
2020-11-07 18:37:23 +01:00
|
|
|
size = ((MODEL*)mem)->normals;
|
2020-04-09 17:53:52 +02:00
|
|
|
else
|
2020-11-07 18:37:23 +01:00
|
|
|
size = ((MODEL*)mem)->poly_block;
|
2020-05-13 20:10:01 +02:00
|
|
|
|
2020-11-29 20:21:33 +01:00
|
|
|
// if loaded externally don't copy from source lump
|
2020-12-28 11:07:24 +01:00
|
|
|
memcpy((u_char*)*dest, (u_char*)mem, size);
|
2020-04-09 17:53:52 +02:00
|
|
|
|
2020-05-13 20:10:01 +02:00
|
|
|
if (KeepNormals == 0)
|
|
|
|
size = model->normals;
|
|
|
|
else
|
|
|
|
size = model->poly_block;
|
2021-04-25 00:30:34 +02:00
|
|
|
|
|
|
|
//*dest += size + 2;
|
|
|
|
*dest = (char*)((int)model + size + 3 & 0xfffffffc);
|
2020-04-09 17:53:52 +02:00
|
|
|
|
2020-05-13 20:10:01 +02:00
|
|
|
model->vertices += (int)model;
|
|
|
|
model->normals += (int)model;
|
2020-11-07 18:37:23 +01:00
|
|
|
model->poly_block = (int)mem + model->poly_block;
|
2020-04-09 17:53:52 +02:00
|
|
|
|
2020-05-13 20:10:01 +02:00
|
|
|
if (KeepNormals == 0)
|
2020-04-09 17:53:52 +02:00
|
|
|
model->point_normals = 0;
|
2020-05-13 20:10:01 +02:00
|
|
|
else
|
|
|
|
model->point_normals += (int)model;
|
2020-04-09 17:53:52 +02:00
|
|
|
|
|
|
|
return model;
|
2020-03-27 21:47:29 +01:00
|
|
|
}
|
|
|
|
|
2020-11-29 15:23:31 +01:00
|
|
|
// [D] [T]
|
|
|
|
MODEL* FindModelPtrWithName(char *name)
|
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
idx = FindModelIdxWithName(name);
|
|
|
|
|
|
|
|
return idx >= 0 ? modelpointers[idx] : NULL;
|
|
|
|
}
|
2020-03-27 21:47:29 +01:00
|
|
|
|
|
|
|
|
2020-11-29 15:23:31 +01:00
|
|
|
// [D] [T]
|
|
|
|
int FindModelIdxWithName(char *name)
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
str = modelname_buffer;
|
|
|
|
|
|
|
|
while (i < num_models_in_pack)
|
|
|
|
{
|
2021-04-18 21:52:27 +02:00
|
|
|
if (!strcmp(str, name))
|
2020-11-29 15:23:31 +01:00
|
|
|
return i;
|
|
|
|
|
|
|
|
while (*str++) {} // go to next string
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|