REDRIVER2/src_rebuild/Game/C/cell.c

190 lines
4.0 KiB
C

#include "driver2.h"
#include "cell.h"
#include "system.h"
#include "map.h"
#include "spool.h"
int cell_object_index = 0;
CELL_OBJECT cell_object_buffer[1024];
unsigned char cell_object_computed_values[2048];
extern u_char NumPlayers;
// [D] [T]
void ClearCopUsage(void)
{
ClearMem((char *)cell_object_computed_values, sizeof_cell_object_computed_values);
}
// [D] [T]
PACKED_CELL_OBJECT * GetFirstPackedCop(int cellx, int cellz, CELL_ITERATOR *pci, int use_computed, int level)
{
PACKED_CELL_OBJECT *ppco;
u_int value;
u_short index;
u_short num;
int cbr;
CELL_DATA* cell;
ushort ptr;
index = (cellx / MAP_REGION_SIZE & 1) + (cellz / MAP_REGION_SIZE & 1) * 2;
#ifdef PSX
if (NumPlayers == 2)
#endif // else do this check always
{
// [A] don't draw loading region
if (loading_region[index] != -1)
return NULL;
if (RoadMapRegions[index] != (cellx / MAP_REGION_SIZE) + (cellz / MAP_REGION_SIZE) * (cells_across / MAP_REGION_SIZE))
return NULL;
}
cbr = (cellz % MAP_REGION_SIZE) * MAP_REGION_SIZE + index * (MAP_REGION_SIZE*MAP_REGION_SIZE) + (cellx % MAP_REGION_SIZE);
ptr = cell_ptrs[cbr];
if (ptr == 0xffff)
return NULL;
cell = &cells[ptr];
if (level == -1)
{
if (cell->num & 0x4000)
return NULL;
}
else
{
/*
Data looks like this:
45,34,773,456 - default list of cell objects
0x4000 | 100 - list 1 header - type 100
70,378,4557 - objects of list 1
0x4000 | 14 - list 2 header - type 14
8767,555,445,223 - objects of list 2
0x8000 - end of cell objects
*/
while (cell->num != (level | 0x4000)) // skip until we reach the needed list header
{
cell++;
if (cell->num & 0x8000) // end of cell objects?
return NULL;
}
cell++;
}
pci->nearCell.x = (cellx - (cells_across / 2)) * MAP_CELL_SIZE;
pci->nearCell.z = (cellz - (cells_down / 2)) * MAP_CELL_SIZE;
pci->use_computed = use_computed;
pci->pcd = cell;
num = cell->num;
ppco = &cell_objects[num & 0x3fff];
if (ppco->value == 0xffff && (ppco->pos.vy & 1))
{
ppco = GetNextPackedCop(pci);
}
else if (use_computed)
{
value = 1 << (num & 7) & 0xffff;
if (cell_object_computed_values[(num & 0x3fff) >> 3] & value) // get cached value
{
ppco = GetNextPackedCop(pci);
pci->ppco = ppco;
return ppco;
}
cell_object_computed_values[(num & 0x3fff) >> 3] |= value;
}
pci->ppco = ppco;
return ppco;
}
// [D] [T]
PACKED_CELL_OBJECT* GetNextPackedCop(CELL_ITERATOR* pci)
{
ushort num;
u_int value;
PACKED_CELL_OBJECT* ppco;
CELL_DATA* celld;
celld = pci->pcd;
do {
do {
if (celld->num & 0x8000) // end of cell objects?
return NULL;
celld++;
num = celld->num;
if (num & 0x4000) // end of list?
return NULL;
ppco = &cell_objects[num & 0x3fff];
} while (ppco->value == 0xffff && (ppco->pos.vy & 1));
if (!pci->use_computed)
break;
value = 1 << (num & 7) & 0xffff;
if ((cell_object_computed_values[(num & 0x3fff) >> 3] & value) == 0)
{
cell_object_computed_values[(num & 0x3fff) >> 3] |= value;
break;
}
} while (true);
pci->pcd = celld;
pci->ppco = ppco;
return ppco;
}
// [D] [T]
CELL_OBJECT* UnpackCellObject(PACKED_CELL_OBJECT* ppco, XZPAIR* near)
{
CELL_OBJECT* pco;
if (ppco == NULL)
return NULL;
pco = &cell_object_buffer[cell_object_index];
cell_object_index = cell_object_index + 1 & 0x3ff;
pco->pos.vx = near->x + (((ppco->pos.vx - near->x) << 0x10) >> 0x10);
pco->pos.vz = near->z + (((ppco->pos.vz - near->z) << 0x10) >> 0x10);
pco->pos.vy = (ppco->pos.vy << 0x10) >> 0x11;
pco->yang = ppco->value & 0x3f;
pco->type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10);
return pco;
}
// [D] [T]
void QuickUnpackCellObject(PACKED_CELL_OBJECT* ppco, XZPAIR* near, CELL_OBJECT* pco)
{
pco->pos.vx = near->x + (((ppco->pos.vx - near->x) << 0x10) >> 0x10);
pco->pos.vz = near->z + (((ppco->pos.vz - near->z) << 0x10) >> 0x10);
pco->pos.vy = (ppco->pos.vy << 0x10) >> 0x11;
pco->yang = ppco->value & 0x3f;
pco->type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10);
}