Feature/loadcar (#42)

* LoadCar
This commit is contained in:
Jeff Harris 2021-01-26 21:49:35 +13:00 committed by GitHub
parent 62d000b861
commit 6bc804710e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 4295 additions and 1745 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,109 +1,111 @@
#include "brqsort.h"
#include <stdlib.h>
// Global variables
char rscid[49];
// IDA: void __cdecl BrQsort(void *basep, unsigned int nelems, unsigned int size, br_qsort_cbfn *comp)
void BrQsort(void* basep, unsigned int nelems, unsigned int size, br_qsort_cbfn comp) {
char* stack[40];
char** sp;
char* i;
char* j;
char* limit;
unsigned int thresh;
char* base;
unsigned int width;
void (*swap_func)(char*, char*, unsigned int);
qsort(basep, nelems, size, comp);
// char* stack[40];
// char** sp;
// char* i;
// char* j;
// char* limit;
// unsigned int thresh;
// char* base;
// unsigned int width;
// void (*swap_func)(char*, char*, unsigned int);
width = size;
swap_func = swap_chars;
// width = size;
// swap_func = swap_chars;
if (size == 4) { // Do we have exactly 1 32bit in worth of data at a time?
swap_func = swap_int_1;
} else if (!(size & 3)) { // Is our data divisible by 4 so can be swapped 32bit at a time?
width >>= 2;
swap_func = swap_ints;
}
// if (size == 4) { // Do we have exactly 1 32bit in worth of data at a time?
// swap_func = swap_int_1;
// } else if (!(size & 3)) { // Is our data divisible by 4 so can be swapped 32bit at a time?
// width >>= 2;
// swap_func = swap_ints;
// }
base = (char*)basep;
thresh = 7 * size;
sp = stack;
// base = (char*)basep;
// thresh = 7 * size;
// sp = stack;
for (limit = (char*)basep + size * nelems;; limit = sp[1]) {
while (limit - base > thresh) {
swap_func(
&base[size * ((limit - base) / size >> 1)],
base,
width);
i = &base[size];
j = &limit[-size];
// for (limit = (char*)basep + size * nelems;; limit = sp[1]) {
// while (limit - base > thresh) {
// swap_func(
// &base[size * ((limit - base) / size >> 1)],
// base,
// width);
// i = &base[size];
// j = &limit[-size];
if (comp(&base[size], &limit[-size]) > 0) {
swap_func(i, j, width);
}
// if (comp(&base[size], &limit[-size]) > 0) {
// swap_func(i, j, width);
// }
if (comp(base, j) > 0) {
swap_func(base, j, width);
}
// if (comp(base, j) > 0) {
// swap_func(base, j, width);
// }
if (comp(i, base) > 0) {
swap_func(i, base, width);
}
// if (comp(i, base) > 0) {
// swap_func(i, base, width);
// }
while (1) {
do {
i += size;
} while (comp(i, base) < 0);
// while (1) {
// do {
// i += size;
// } while (comp(i, base) < 0);
do {
j -= size;
} while (comp(j, base) > 0);
// do {
// j -= size;
// } while (comp(j, base) > 0);
if (i > j) {
break;
}
// if (i > j) {
// break;
// }
swap_func(i, j, width);
}
// swap_func(i, j, width);
// }
swap_func(base, j, width);
// swap_func(base, j, width);
if (j - base <= limit - i) {
*sp = i;
sp[1] = limit;
limit = j;
} else {
*sp = base;
sp[1] = j;
base = i;
}
// if (j - base <= limit - i) {
// *sp = i;
// sp[1] = limit;
// limit = j;
// } else {
// *sp = base;
// sp[1] = j;
// base = i;
// }
sp += 2;
}
// sp += 2;
// }
j = base;
// j = base;
for (i = &base[size]; i < limit; i += size) {
while (comp(j, &j[size]) > 0) {
swap_func(j, &j[size], width);
// for (i = &base[size]; i < limit; i += size) {
// while (comp(j, &j[size]) > 0) {
// swap_func(j, &j[size], width);
if (j == base) {
break;
}
// if (j == base) {
// break;
// }
j -= size;
}
// j -= size;
// }
j = i;
}
// j = i;
// }
if (stack == sp) {
break;
}
// if (stack == sp) {
// break;
// }
sp -= 2;
base = *sp;
}
// sp -= 2;
// base = *sp;
// }
}
// IDA: void __usercall swap_chars(char *a@<EAX>, char *b@<EDX>, unsigned int nbytes@<EBX>)

View File

@ -38,13 +38,20 @@ void* BrSwapBlock(void* block, int count, int size) {
br_uint_8* cp;
int i;
int k;
LOG_TRACE9("(%p, %d, %d)", block, count, size);
LOG_TRACE("(%p, %d, %d)", block, count, size);
cp = (br_uint_8*)block;
switch (size) {
case 1:
return block;
break;
case 2:
for (i = 0; i < count; i++) {
k = cp[1];
cp[1] = cp[0];
cp[0] = k;
cp += 2;
}
break;
case 4:
for (i = 0; i < count; i++) {
k = cp[0];
@ -60,4 +67,5 @@ void* BrSwapBlock(void* block, int count, int size) {
default:
LOG_PANIC("size not implemented");
}
return block;
}

View File

@ -406,13 +406,13 @@ br_uint_32 DfStructReadBinary(br_datafile* df, br_file_struct* str, void* base)
n = 4;
break;
}
for (i = 0; i < n; i++) {
conv.b[3] = BrFileGetChar(df->h);
conv.b[2] = BrFileGetChar(df->h);
conv.b[1] = BrFileGetChar(df->h);
conv.b[0] = BrFileGetChar(df->h);
*mp = conv.f;
mp += 4;
((br_fvector4_f*)mp)->v[i] = conv.f;
}
LABEL_33:
@ -510,7 +510,7 @@ br_uint_32 DfStructWriteArray(br_datafile* df, br_file_struct* str, void* base,
br_uint_32 DfStructReadArray(br_datafile* df, br_file_struct* str, void* base, int n) {
char* cp;
int i;
LOG_TRACE("(%p, %p, %p, %d)", df, str, base, n);
LOG_TRACE9("(%p, %p, %p, %d)", df, str, base, n);
cp = (char*)base;
for (i = 0; i < n; i++) {
@ -593,7 +593,7 @@ void DfCountWriteBinary(br_datafile* df, br_uint_32 count) {
// IDA: br_uint_32 __usercall DfCountReadBinary@<EAX>(br_datafile *df@<EAX>)
br_uint_32 DfCountReadBinary(br_datafile* df) {
br_uint_32 l;
LOG_TRACE("(%p)", df);
LOG_TRACE9("(%p)", df);
BrFileRead(&l, 4, 1, df->h);
return BrSwap32(l);
}
@ -714,7 +714,7 @@ int DfNameSizeText(br_datafile* df, char* name) {
char* DfNameReadBinary(br_datafile* df, char* name) {
int c;
int i;
LOG_TRACE("(%p, \"%s\")", df, name);
LOG_TRACE9("(%p, \"%s\")", df, name);
for (i = 0; i < 255; i++) {
c = BrFileGetChar(df->h);

View File

@ -33,12 +33,14 @@ void* BrResAllocate(void* vparent, br_size_t size, br_uint_8 res_class) {
br_int_32 calign;
br_int_32 pad;
br_int_32 actual_pad;
LOG_TRACE10("(%p, %d, %d)", vparent, size, res_class);
LOG_TRACE9("(%p, %d, %d)", vparent, size, res_class);
char* tmp;
malign = BrMemAlign(res_class) - 1;
calign = fw.resource_class_index[res_class]->alignment;
if (calign <= 0) {
calign = 4;
}
@ -48,11 +50,10 @@ void* BrResAllocate(void* vparent, br_size_t size, br_uint_8 res_class) {
pad = (~malign & calign) + 3;
actual_pad = (sizeof(resource_header) + pad) & 0xFFFC;
// JeffH ignore calculated padding for simplicity. We dont care too much about
// Jeff ignore calculated padding for simplicity. We dont care too much about
// optimizing data alignment at this point ;)
pad = 0;
actual_pad = sizeof(resource_header) + pad;
res = (resource_header*)BrMemAllocate(size + actual_pad, res_class);
res->class = res_class;

View File

@ -1,5 +1,8 @@
#include "scratch.h"
#include "diag.h"
#include "fwsetup.h"
#include "harness.h"
#include "resource.h"
char scratchString[512];
char rscid[49];
@ -7,13 +10,28 @@ char rscid[49];
// IDA: void* __cdecl BrScratchAllocate(br_size_t size)
void* BrScratchAllocate(br_size_t size) {
LOG_TRACE("(%d)", size);
NOT_IMPLEMENTED();
if (fw.scratch_inuse)
BrFailure("Scratchpad not available");
fw.scratch_last = size;
if (size > fw.scratch_size) {
if (fw.scratch_ptr)
BrResFree(fw.scratch_ptr);
fw.scratch_ptr = BrResAllocate(fw.res, size, BR_MEMORY_SCRATCH);
fw.scratch_size = size;
}
fw.scratch_inuse = 1;
return fw.scratch_ptr;
}
// IDA: void __cdecl BrScratchFree(void *scratch)
void BrScratchFree(void* scratch) {
LOG_TRACE("(%p)", scratch);
NOT_IMPLEMENTED();
fw.scratch_inuse = 0;
}
// IDA: void __cdecl BrScratchFlush()

View File

@ -2,6 +2,12 @@
#define _ANGLES_H_
#include "br_types.h"
#include <math.h>
#define BrAngleToRadian(a) ((br_scalar)((a) * (M_PI / 32768.0)))
#define BrRadianToAngle(r) ((br_angle)(long)((r) * (32768.0 / M_PI)))
#define BR_COS(a) ((br_scalar)cos(BrAngleToRadian(a)))
br_matrix34* BrEulerToMatrix34(br_matrix34* mat, br_euler* euler);

View File

@ -119,8 +119,11 @@ void BrVector3Add(br_vector3* v1, br_vector3* v2, br_vector3* v3) {
// IDA: void __cdecl BrVector3Accumulate(br_vector3 *v1, br_vector3 *v2)
void BrVector3Accumulate(br_vector3* v1, br_vector3* v2) {
LOG_TRACE("(%p, %p)", v1, v2);
NOT_IMPLEMENTED();
LOG_TRACE10("(%p, %p)", v1, v2);
v1->v[0] += v2->v[0];
v1->v[1] += v2->v[1];
v1->v[2] += v2->v[2];
}
// IDA: void __cdecl BrVector3Sub(br_vector3 *v1, br_vector3 *v2, br_vector3 *v3)
@ -168,8 +171,20 @@ br_scalar BrVector3LengthSquared(br_vector3* v1) {
// IDA: void __cdecl BrVector3Normalise(br_vector3 *v1, br_vector3 *v2)
void BrVector3Normalise(br_vector3* v1, br_vector3* v2) {
br_scalar scale;
LOG_TRACE("(%p, %p)", v1, v2);
NOT_IMPLEMENTED();
LOG_TRACE10("(%p, %p)", v1, v2);
scale = BR_LENGTH3(v2->v[0], v2->v[1], v2->v[2]);
if (scale > BR_SCALAR_EPSILON * 2) {
v1->v[0] = v2->v[0] / scale;
v1->v[1] = v2->v[1] / scale;
v1->v[2] = v2->v[2] / scale;
} else {
v1->v[0] = BR_SCALAR(1.0);
v1->v[1] = BR_SCALAR(0.0);
v1->v[2] = BR_SCALAR(0.0);
}
}
// IDA: void __cdecl BrVector3NormaliseLP(br_vector3 *v1, br_vector3 *v2)

View File

@ -98,7 +98,7 @@ br_pixelmap* BrPixelmapClone(br_pixelmap* src) {
// IDA: void __cdecl BrPixelmapFill(br_pixelmap *dst, br_uint_32 colour)
void BrPixelmapFill(br_pixelmap* dst, br_uint_32 colour) {
br_uint_8 linear_wholepixels; //added JeffH
br_uint_8 linear_wholepixels; //added Jeff
LOG_TRACE("(%p, %d)", dst, colour);
linear_wholepixels = BR_PMF_LINEAR | BR_PMF_ROW_WHOLEPIXELS;

View File

@ -26,5 +26,5 @@ br_material* BrMaterialAllocate(char* name) {
// IDA: void __cdecl BrMaterialFree(br_material *m)
void BrMaterialFree(br_material* m) {
LOG_TRACE("(%p)", m);
NOT_IMPLEMENTED();
BrResFree(m);
}

View File

@ -1,8 +1,15 @@
#include "prepmesh.h"
#include "CORE/FW/brqsort.h"
#include "CORE/FW/diag.h"
#include "CORE/FW/resource.h"
#include "CORE/FW/scratch.h"
#include "CORE/MATH/plane.h"
#include "CORE/MATH/vector.h"
#include "CORE/STD/brmath.h"
#include "CORE/STD/brstdlib.h"
#include "angles.h"
#include "harness.h"
#include <assert.h>
br_model* compareModel;
char* pm_edge_scratch;
@ -11,6 +18,8 @@ int num_edges;
pm_temp_edge* pm_edge_table;
char rscid[51];
#define PREP_ALIGN(f) (f)
// IDA: int __usercall addEdge@<EAX>(br_uint_16 first@<EAX>, br_uint_16 last@<EDX>)
int addEdge(br_uint_16 first, br_uint_16 last) {
pm_temp_edge* tep;
@ -40,8 +49,18 @@ void BrPrepareEdges(br_model* model) {
int FacesCompare(void* p1, void* p2) {
br_face* f1;
br_face* f2;
LOG_TRACE("(%p, %p)", p1, p2);
NOT_IMPLEMENTED();
LOG_TRACE9("(%p, %p)", p1, p2);
f1 = *(br_face**)p1;
f2 = *(br_face**)p2;
if (f1->material > f2->material) {
return 1;
}
if (f1->material < f2->material) {
return -1;
}
return 0;
}
// IDA: int __cdecl TVCompare_XYZ(void *p1, void *p2)
@ -51,8 +70,27 @@ int TVCompare_XYZ(void* p1, void* p2) {
br_vertex* v1;
br_vertex* v2;
int i;
LOG_TRACE("(%p, %p)", p1, p2);
NOT_IMPLEMENTED();
LOG_TRACE9("(%p, %p)", p1, p2);
tv1 = *(prep_vertex**)p1;
tv2 = *(prep_vertex**)p2;
assert(compareModel != NULL);
if (tv1->v == tv2->v)
return 0;
v1 = compareModel->vertices + tv1->v;
v2 = compareModel->vertices + tv2->v;
for (i = 0; i < 3; i++) {
if (v1->p.v[i] > v2->p.v[i])
return 1;
if (v1->p.v[i] < v2->p.v[i])
return -1;
}
return 0;
}
// IDA: int __cdecl TVCompare_MXYZUVN(void *p1, void *p2)
@ -63,7 +101,44 @@ int TVCompare_MXYZUVN(void* p1, void* p2) {
br_vertex* v2;
int i;
LOG_TRACE("(%p, %p)", p1, p2);
NOT_IMPLEMENTED();
tv1 = *(struct prep_vertex**)p1;
tv2 = *(struct prep_vertex**)p2;
assert(compareModel != NULL);
if (compareModel->faces[tv1->f].material > compareModel->faces[tv2->f].material)
return 1;
if (compareModel->faces[tv1->f].material < compareModel->faces[tv2->f].material)
return -1;
if (tv1->v != tv2->v) {
v1 = compareModel->vertices + tv1->v;
v2 = compareModel->vertices + tv2->v;
for (i = 0; i < 3; i++) {
if (v1->p.v[i] > v2->p.v[i])
return 1;
if (v1->p.v[i] < v2->p.v[i])
return -1;
}
for (i = 0; i < 2; i++) {
if (v1->map.v[i] > v2->map.v[i])
return 1;
if (v1->map.v[i] < v2->map.v[i])
return -1;
}
}
for (i = 0; i < 3; i++) {
if (tv1->n.v[i] > tv2->n.v[i])
return 1;
if (tv1->n.v[i] < tv2->n.v[i])
return -1;
}
return 0;
}
// IDA: int __cdecl TVCompare_MVN(void *p1, void *p2)
@ -71,8 +146,34 @@ int TVCompare_MVN(void* p1, void* p2) {
prep_vertex* tv1;
prep_vertex* tv2;
int i;
LOG_TRACE("(%p, %p)", p1, p2);
NOT_IMPLEMENTED();
LOG_TRACE9("(%p, %p)", p1, p2);
tv1 = *(prep_vertex**)p1;
tv2 = *(prep_vertex**)p2;
// if (compareModel->faces[tv1->f].material != NULL) {
// LOG_DEBUG("%s, %s", compareModel->faces[tv1->f].material->identifier, compareModel->faces[tv2->f].material->identifier);
// }
if (compareModel->faces[tv1->f].material > compareModel->faces[tv2->f].material)
return 1;
if (compareModel->faces[tv1->f].material < compareModel->faces[tv2->f].material)
return -1;
if (tv1->v > tv2->v)
return 1;
if (tv1->v < tv2->v)
return -1;
/*
* Compare Normal
*/
for (i = 0; i < 3; i++) {
if (tv1->n.v[i] > tv2->n.v[i])
return 1;
if (tv1->n.v[i] < tv2->n.v[i])
return -1;
}
return 0;
}
// IDA: br_fraction __cdecl BrScalarToFractionClamp(br_scalar s)
@ -107,8 +208,15 @@ void PrepareFaceNormals(br_model* model) {
void Smoothing(br_model* model, br_scalar crease_limit, prep_vertex** start, prep_vertex** end) {
prep_vertex** outer;
prep_vertex** inner;
LOG_TRACE("(%p, %f, %p, %p)", model, crease_limit, start, end);
NOT_IMPLEMENTED();
LOG_TRACE9("(%p, %f, %p, %p)", model, crease_limit, start, end);
for (outer = start; outer < end; outer++) {
for (inner = start; inner < end; inner++) {
if ((inner == outer) || (model->faces[(*outer)->f].smoothing & model->faces[(*inner)->f].smoothing)) {
BrVector3Accumulate(&(*outer)->n, &model->faces[(*inner)->f].n);
}
}
}
}
// IDA: void __usercall SmoothingCreased(br_model *model@<EAX>, br_scalar crease_limit, prep_vertex **start, prep_vertex **end)
@ -124,14 +232,36 @@ void SmoothingCreased(br_model* model, br_scalar crease_limit, prep_vertex** sta
void CopyVertex(v11group* group, int v, prep_vertex* src, br_model* model) {
br_vertex* srcv;
br_vector3 n;
LOG_TRACE("(%p, %d, %p, %p)", group, v, src, model);
NOT_IMPLEMENTED();
LOG_TRACE9("(%p, %d, %p, %p)", group, v, src, model);
srcv = model->vertices + src->v;
br_vector3 temp;
group->vertices[v].p.v[0] = srcv->p.v[0] - model->pivot.v[0];
group->vertices[v].p.v[1] = srcv->p.v[1] - model->pivot.v[1];
group->vertices[v].p.v[2] = srcv->p.v[2] - model->pivot.v[2];
group->vertices[v].map = srcv->map;
BrVector3Normalise(&group->vertices[v].n, &src->n);
group->vertex_colours[v] = BR_COLOUR_RGBA(srcv->red, srcv->grn, srcv->blu, srcv->index);
group->vertex_user[v] = src->v;
}
// IDA: void __usercall CopyFace(v11group *group@<EAX>, int f@<EDX>, br_face *src@<EBX>, br_model *model@<ECX>)
void CopyFace(v11group* group, int f, br_face* src, br_model* model) {
LOG_TRACE("(%p, %d, %p, %p)", group, f, src, model);
NOT_IMPLEMENTED();
LOG_TRACE9("(%p, %d, %p, %p)", group, f, src, model);
group->faces[f].vertices[0] = src->vertices[0];
group->faces[f].vertices[1] = src->vertices[1];
group->faces[f].vertices[2] = src->vertices[2];
group->face_colours[f] = BR_COLOUR_RGBA(src->red, src->grn, src->blu, src->index);
group->faces[f].eqn.v[0] = src->n.v[0];
group->faces[f].eqn.v[1] = src->n.v[1];
group->faces[f].eqn.v[2] = src->n.v[2];
group->faces[f].eqn.v[3] = src->d;
group->face_user[f] = src - model->faces;
}
// IDA: void __usercall PrepareGroups(br_model *model@<EAX>)
@ -167,9 +297,192 @@ void PrepareGroups(br_model* model) {
br_face** sorted_faces;
char* cp;
LOG_WARN("Ignoring this one for now");
if (model->flags & BR_MODF_DONT_WELD) {
vertex_compare_smoothing = TVCompare_XYZ;
vertex_compare_groups = TVCompare_MVN;
} else {
vertex_compare_smoothing = TVCompare_XYZ;
vertex_compare_groups = TVCompare_MXYZUVN;
}
return;
if (model->flags & BR_MODF_CREASE) {
crease_limit = BR_COS(model->crease_angle);
smoothing_fn = SmoothingCreased;
} else {
crease_limit = BR_SCALAR(0.0);
smoothing_fn = Smoothing;
}
compareModel = model;
ntemps = model->nfaces * 3;
block_size = ntemps * (sizeof(*temp_verts) + sizeof(*sorted_vertices)) + model->nfaces * sizeof(sorted_faces);
temp_verts = BrScratchAllocate(block_size);
BrMemSet(temp_verts, 0, block_size);
sorted_vertices = (struct prep_vertex**)(temp_verts + ntemps);
sorted_faces = (struct br_face**)(sorted_vertices + ntemps);
gtvp = temp_verts;
for (i = 0, f = 0, fp = model->faces; f < model->nfaces; f++, fp++) {
sorted_faces[f] = fp;
for (v = 0; v < 3; v++, i++, gtvp++) {
if (model->flags & BR_MODF_CUSTOM_NORMALS) {
TELL_ME_IF_WE_PASS_THIS_WAY();
// gtvp->n.v[0] = model->vertices[fp->vertices[v]].n.v[0];
// gtvp->n.v[1] = model->vertices[fp->vertices[v]].n.v[1];
// gtvp->n.v[2] = model->vertices[fp->vertices[v]].n.v[2];
}
gtvp->v = fp->vertices[v];
gtvp->f = f;
sorted_vertices[i] = gtvp;
}
if (fp->smoothing == 0)
fp->smoothing = (br_uint_16)~0;
}
BrQsort(sorted_faces, model->nfaces, sizeof(*sorted_faces), FacesCompare);
if (!(model->flags & BR_MODF_CUSTOM_NORMALS)) {
BrQsort(sorted_vertices, ntemps, sizeof(*sorted_vertices), vertex_compare_smoothing);
for (v = 0, i = 0; v < ntemps - 1; v++) {
if (vertex_compare_smoothing(sorted_vertices + v, sorted_vertices + v + 1)) {
smoothing_fn(model, crease_limit, sorted_vertices + i, sorted_vertices + v + 1);
i = v + 1;
}
}
smoothing_fn(model, crease_limit, sorted_vertices + i, sorted_vertices + ntemps);
}
BrQsort(sorted_vertices, ntemps, sizeof(*sorted_vertices), vertex_compare_groups);
for (v = 0, nv = 1; v < ntemps - 1; v++)
if (vertex_compare_groups(sorted_vertices + v, sorted_vertices + v + 1))
nv++;
for (f = 1, ng = 1; f < model->nfaces; f++) {
if (sorted_faces[f]->material != sorted_faces[f - 1]->material) {
ng++;
}
}
nf = model->nfaces;
block_size = PREP_ALIGN(sizeof(struct v11model)) + PREP_ALIGN(ng * sizeof(struct v11group)) +
PREP_ALIGN(nf * sizeof(*v11g->faces)) +
PREP_ALIGN(nv * sizeof(*v11g->vertices)) +
PREP_ALIGN(nf * sizeof(br_colour)) + PREP_ALIGN(nv * sizeof(br_colour)) + nv * sizeof(br_int_16) + nf * sizeof(br_int_16);
if (model->prepared && block_size > ((struct v11model*)(model->prepared))->size) {
BrResFree(model->prepared);
model->prepared = NULL;
}
if (model->prepared == NULL) {
model->prepared = BrResAllocate(model, block_size, BR_MEMORY_PREPARED_MODEL);
((struct v11model*)(model->prepared))->size = block_size;
}
cp = model->prepared;
v11m = (void*)cp;
cp += PREP_ALIGN(sizeof(struct v11model));
v11g = (void*)cp;
cp += PREP_ALIGN(ng * sizeof(struct v11group));
v11f = (void*)cp;
cp += PREP_ALIGN(nf * sizeof(struct v11face));
v11v = (void*)cp;
cp += PREP_ALIGN(nv * sizeof(struct fmt_vertex));
v11vcolours = (void*)cp;
cp += PREP_ALIGN(nv * sizeof(br_colour));
v11fcolours = (void*)cp;
cp += PREP_ALIGN(nf * sizeof(br_colour));
v11vuser = (void*)cp;
cp += nv * sizeof(br_uint_16);
v11fuser = (void*)cp;
cp += nf * sizeof(br_uint_16);
v11m->groups = v11g;
v11m->ngroups = ng;
v11g[0].faces = v11f;
v11g[0].face_colours = v11fcolours;
v11g[0].face_user = v11fuser;
v11g[0].stored = sorted_faces[0]->material ? sorted_faces[0]->material->stored : NULL;
v11g[0].nfaces = 0;
for (f = 0, g = 0; f < model->nfaces - 1; f++) {
CopyFace(v11g + g, v11g[g].nfaces, sorted_faces[f], model);
v11g[g].nfaces++;
if (sorted_faces[f]->material != sorted_faces[f + 1]->material) {
g++;
v11g[g].faces = v11f + f + 1;
v11g[g].face_colours = v11fcolours + f + 1;
v11g[g].face_user = v11fuser + f + 1;
v11g[g].stored = sorted_faces[f + 1]->material ? sorted_faces[f + 1]->material->stored : NULL;
v11g[g].nfaces = 0;
}
}
CopyFace(v11g + g, v11g[g].nfaces, sorted_faces[f], model);
v11g[g].nfaces++;
v11g[0].vertices = v11v;
v11g[0].vertex_colours = v11vcolours;
v11g[0].vertex_user = v11vuser;
v11g[0].nvertices = 1;
CopyVertex(v11g, 0, sorted_vertices[0], model);
for (v = 0, g = 0, count = 0; v < ntemps - 1; v++) {
if (model->faces[sorted_vertices[v]->f].material != model->faces[sorted_vertices[v + 1]->f].material) {
g++;
v11g[g].vertices = v11v + count + 1;
v11g[g].vertex_colours = v11vcolours + count + 1;
v11g[g].vertex_user = v11vuser + count + 1;
v11g[g].nvertices = 0;
}
old_count = count;
if (vertex_compare_groups(sorted_vertices + v, sorted_vertices + v + 1)) {
count++;
sorted_vertices[v]->v = count;
CopyVertex(v11g + g, v11g[g].nvertices, sorted_vertices[v + 1], model);
v11g[g].nvertices++;
}
sorted_vertices[v]->v = old_count;
}
sorted_vertices[v]->v = count;
for (g = 0; g < ng; g++) {
for (f = 0; f < v11g[g].nfaces; f++) {
v = v11g[g].face_user[f] * 3;
v11g[g].faces[f].vertices[0] = temp_verts[v + 0].v;
v11g[g].faces[f].vertices[1] = temp_verts[v + 1].v;
v11g[g].faces[f].vertices[2] = temp_verts[v + 2].v;
}
}
BrScratchFree(temp_verts);
}
// IDA: void __usercall PrepareBoundingRadius(br_model *model@<EAX>)
@ -288,7 +601,7 @@ void BrModelUpdate(br_model* model, br_uint_16 flags) {
v11m = (v11model*)model->prepared;
if (v11m) {
for (g = 0; g < v11m->ngroups; g++) {
prepareEdges(&v11m->groups[g], model);
//prepareEdges(&v11m->groups[g], model);
}
}
} else {
@ -366,21 +679,18 @@ void BrModelUpdate(br_model* model, br_uint_16 flags) {
// }
}
// We arent generating optimized model or storing at this point, so
// we do not want to free the faces/verts
// if (model->flags >= 0) {
// if (model->faces) {
// BrResFree(model->faces);
// }
// if (model->vertices) {
// BrResFree(model->vertices);
// }
// model->vertices = 0;
// model->nfaces = 0;
// model->nvertices = 0;
// model->faces = 0;
// }
if (model->flags >= 0) {
if (model->faces) {
BrResFree(model->faces);
}
if (model->vertices) {
BrResFree(model->vertices);
}
model->vertices = 0;
model->nfaces = 0;
model->nvertices = 0;
model->faces = 0;
}
}
}

View File

@ -1,8 +1,10 @@
#include "v1dbfile.h"
#include "CORE/FW/datafile.h"
#include "CORE/FW/diag.h"
#include "CORE/FW/genfile.h"
#include "CORE/FW/resource.h"
#include "CORE/FW/scratch.h"
#include "CORE/V1DB/actsupt.h"
#include "CORE/V1DB/dbsetup.h"
#include "CORE/V1DB/matsupt.h"
@ -39,7 +41,6 @@ br_file_struct br_plane_F;
br_file_struct_member br_bounds3_FM[2];
br_file_struct br_bounds3_F;
br_file_struct_member br_plane_FM[1];
transform_type TransformTypes[7];
br_file_struct br_transform_translation_F;
br_file_struct_member br_transform_translation_FM[1];
br_file_enum angle_order_F;
@ -50,8 +51,25 @@ br_file_struct br_transform_euler_F;
br_file_struct br_transform_quat_F;
br_file_struct_member br_transform_quat_FM[5];
br_file_enum_member angle_order_FM[24];
br_file_struct br_transform_matrix34_F;
br_file_struct_member br_transform_matrix34_FM[4];
br_file_struct_member br_transform_matrix34_FM[] = {
{ 20u, offsetof(br_transform, t.mat.m[0]), "t.mat.m[0]", NULL },
{ 20u, offsetof(br_transform, t.mat.m[1]), "t.mat.m[1]", NULL },
{ 20u, offsetof(br_transform, t.mat.m[2]), "t.mat.m[2]", NULL },
{ 20u, offsetof(br_transform, t.mat.m[3]), "t.mat.m[3]", NULL }
};
br_file_struct br_transform_matrix34_F = { "br_transform_matrix34", 4u, br_transform_matrix34_FM, sizeof(br_transform) };
transform_type TransformTypes[] = {
{ 43u, &br_transform_matrix34_F },
{ 44u, &br_transform_matrix34_F },
{ 45u, &br_transform_quat_F },
{ 46u, &br_transform_euler_F },
{ 47u, &br_transform_look_up_F },
{ 48u, &br_transform_translation_F },
{ 49u, NULL }
};
br_file_enum_member render_style_FM[8];
br_file_enum_member actor_type_FM[8] = {
@ -114,8 +132,8 @@ br_file_struct br_old_face_1_F;
br_file_struct_member br_face_FM[5] = {
{ 3u, offsetof(br_face, vertices), "vertices[0]", NULL },
{ 3u, offsetof(br_face, vertices) + 2, "vertices[1]", NULL },
{ 3u, offsetof(br_face, vertices) + 4, "vertices[2]", NULL },
{ 3u, offsetof(br_face, vertices[1]), "vertices[1]", NULL },
{ 3u, offsetof(br_face, vertices[2]), "vertices[2]", NULL },
{ 3u, offsetof(br_face, smoothing), "smoothing", NULL },
{ 1u, offsetof(br_face, flags), "flags", NULL }
};
@ -124,17 +142,20 @@ br_file_struct br_face_F = { "br_face", 5u, br_face_FM, sizeof(br_face) };
br_file_struct_member br_old_vertex_uv_FM[5];
br_file_struct br_old_vertex_uv_F;
br_file_struct_member br_vertex_uv_FM[2];
br_file_struct br_vertex_uv_F;
br_file_struct_member br_vertex_uv_FM[] = {
{ 10, offsetof(br_vertex, map.v[0]), "map.v[0]", NULL },
{ 10u, offsetof(br_vertex, map.v[1]), "map.v[1]", NULL }
};
br_file_struct br_vertex_uv_F = { "br_vertex_uv", 2, br_vertex_uv_FM, sizeof(br_vertex) };
br_file_struct_member br_vertex_FM[3] = {
{ 10, offsetof(br_vertex, p) + 0, "p.v[x]", NULL },
{ 10, offsetof(br_vertex, p) + 4, "p.v[y]", NULL },
{ 10, offsetof(br_vertex, p) + 8, "p.v[z]", NULL }
{ 10, offsetof(br_vertex, p.v[0]), "p.v[x]", NULL },
{ 10, offsetof(br_vertex, p.v[1]), "p.v[y]", NULL },
{ 10, offsetof(br_vertex, p.v[2]), "p.v[z]", NULL }
};
br_file_struct br_vertex_F = { "br_vertex", 3, br_vertex_FM, sizeof(br_vertex) };
br_chunks_table_entry ModelLoadEntries[15] = {
br_chunks_table_entry ModelLoadEntries[] = {
{ 0u, 0u, &FopRead_END },
{ 9u, 0u, &FopRead_OLD_MATERIAL_INDEX },
{ 10u, 0u, &FopRead_OLD_VERTICES },
@ -189,9 +210,10 @@ struct {
{ 32u, offsetof(br_material, screendoor), 1 }
};
// Added by JeffH.
// Added by Jeff.
#define DF_MATERIAL 3
#define DF_ACTOR 4
#define DF_MATERIAL_INDEX 5
#define DF_MODEL 8
#define DF_TRANSFORM 16
@ -207,7 +229,7 @@ int FopWrite_VERTICES(br_datafile* df, br_vertex* vertices, int nvertices) {
int FopRead_VERTICES(br_datafile* df, br_uint_32 id, br_uint_32 length, br_uint_32 count) {
br_model* mp;
int i;
LOG_TRACE("(%p, %d, %d, %d)", df, id, length, count);
LOG_TRACE9("(%p, %d, %d, %d)", df, id, length, count);
mp = DfTop(DF_MODEL, NULL);
mp->vertices = BrResAllocate(mp, sizeof(br_vertex) * count, BR_MEMORY_VERTICES);
@ -232,8 +254,14 @@ int FopWrite_VERTEX_UV(br_datafile* df, br_vertex* vertices, int nvertices) {
// IDA: int __usercall FopRead_VERTEX_UV@<EAX>(br_datafile *df@<EAX>, br_uint_32 id@<EDX>, br_uint_32 length@<EBX>, br_uint_32 count@<ECX>)
int FopRead_VERTEX_UV(br_datafile* df, br_uint_32 id, br_uint_32 length, br_uint_32 count) {
br_model* mp;
LOG_TRACE("(%p, %d, %d, %d)", df, id, length, count);
NOT_IMPLEMENTED();
LOG_TRACE9("(%p, %d, %d, %d)", df, id, length, count);
mp = DfTop(DF_MODEL, NULL);
if (count > mp->nvertices) {
BrFailure("Vertex UV: too many entries");
}
DfStructReadArray(df, &br_vertex_uv_F, mp->vertices, count);
return 0;
}
// IDA: int __usercall FopRead_OLD_VERTICES_UV@<EAX>(br_datafile *df@<EAX>, br_uint_32 id@<EDX>, br_uint_32 length@<EBX>, br_uint_32 count@<ECX>)
@ -248,8 +276,16 @@ int FopRead_MATERIAL_INDEX(br_datafile* df, br_uint_32 id, br_uint_32 length, br
char name[256];
br_material** mip;
br_uint_32 i;
LOG_TRACE("(%p, %d, %d, %d)", df, id, length, count);
NOT_IMPLEMENTED();
LOG_TRACE9("(%p, %d, %d, %d)", df, id, length, count);
mip = (br_material**)BrResAllocate(v1db.res, sizeof(intptr_t) * (count + 1), BR_MEMORY_MATERIAL_INDEX);
mip[0] = NULL;
for (i = 1; i < count + 1; i++) {
df->prims->name_read(df, name);
mip[i] = BrMaterialFind(name);
}
DfPush(DF_MATERIAL_INDEX, mip, count + 1);
return 0;
}
// IDA: int __usercall FopWrite_MATERIAL_INDEX@<EAX>(br_datafile *df@<EAX>, br_material **materials@<EDX>, int nmaterials@<EBX>)
@ -275,7 +311,7 @@ int FopRead_OLD_MATERIAL_INDEX(br_datafile* df, br_uint_32 id, br_uint_32 length
int FopRead_FACES(br_datafile* df, br_uint_32 id, br_uint_32 length, br_uint_32 count) {
br_model* mp;
int i;
LOG_TRACE("(%p, %d, %d, %d)", df, id, length, count);
LOG_TRACE9("(%p, %d, %d, %d)", df, id, length, count);
mp = DfTop(DF_MODEL, 0);
mp->faces = (br_face*)BrResAllocate(mp, sizeof(br_face) * count, BR_MEMORY_FACES);
mp->nfaces = count;
@ -284,6 +320,7 @@ int FopRead_FACES(br_datafile* df, br_uint_32 id, br_uint_32 length, br_uint_32
if (!mp->faces[i].smoothing) {
mp->faces[i].smoothing = -1;
}
mp->faces[i].index = i;
}
return 0;
@ -335,8 +372,29 @@ int FopRead_FACE_MATERIAL(br_datafile* df, br_uint_32 id, br_uint_32 length, br_
br_uint_16* ip;
int block_count;
int i;
LOG_TRACE("(%p, %d, %d, %d)", df, id, length, count);
NOT_IMPLEMENTED();
LOG_TRACE9("(%p, %d, %d, %d)", df, id, length, count);
mindex = DfPop(DF_MATERIAL_INDEX, &nmaterials);
mp = DfTop(DF_MODEL, 0);
block = BrScratchAllocate(length);
block_count = mp->nfaces;
block = df->prims->block_read(df, block, &block_count, sizeof(br_uint_16), 0);
if (block_count > mp->nfaces)
BrFailure("Face Materials: too many entries");
fp = mp->faces;
ip = block;
for (i = 0; i < block_count; i++) {
fp->material = (*ip < nmaterials) ? mindex[*ip] : NULL;
fp++;
ip++;
}
BrScratchFree(block);
BrResFree(mindex);
return 0;
}
// IDA: int __usercall FopRead_MODEL@<EAX>(br_datafile *df@<EAX>, br_uint_32 id@<EDX>, br_uint_32 length@<EBX>, br_uint_32 count@<ECX>)
@ -491,6 +549,7 @@ int FopRead_ACTOR_MATERIAL(br_datafile* df, br_uint_32 id, br_uint_32 length, br
a = DfTop(DF_ACTOR, NULL);
df->prims->name_read(df, name);
a->material = BrMaterialFind(name);
return 0;
}
// IDA: int __usercall FopWrite_ACTOR_TRANSFORM@<EAX>(br_datafile *df@<EAX>)
@ -579,7 +638,12 @@ int FopRead_ACTOR_ADD_CHILD(br_datafile* df, br_uint_32 id, br_uint_32 length, b
br_actor* a;
br_actor* p;
LOG_TRACE("(%p, %d, %d, %d)", df, id, length, count);
NOT_IMPLEMENTED();
a = DfPop(DF_ACTOR, 0);
p = DfTop(DF_ACTOR, 0);
BrActorAdd(p, a);
return 0;
}
// IDA: int __usercall FopWrite_TRANSFORM@<EAX>(br_datafile *df@<EAX>, br_transform *t@<EDX>)
@ -595,11 +659,14 @@ int FopRead_TRANSFORM(br_datafile* df, br_uint_32 id, br_uint_32 length, br_uint
br_transform* tp;
LOG_TRACE9("(%p, %d, %d, %d)", df, id, length, count);
for (t = 0; t < 7; t++) {
for (t = 0; t < COUNT_OF(TransformTypes); t++) {
if (id == TransformTypes[t].id) {
break;
}
}
if (t == 7) {
LOG_PANIC("transform type not found!")
}
tp = (br_transform*)BrResAllocate(v1db.res, sizeof(br_transform), BR_MEMORY_TRANSFORM);
tp->type = t;
df->res = tp;
@ -831,10 +898,13 @@ br_uint_32 BrMaterialSave(char* filename, br_material* ptr) {
// IDA: br_actor* __cdecl BrActorLoad(char *filename)
br_actor* BrActorLoad(char* filename) {
LOG_TRACE("(\"%s\")", filename);
br_actor* ptr;
if (BrActorLoadMany(filename, &ptr, 1u) == 1) {
return ptr;
}
LOG_DEBUG("loadmany fail");
return NULL;
}

View File

@ -683,7 +683,7 @@ typedef br_pixelmap* br_map_find_cbfn(char*);
typedef br_uint_32 br_map_enum_cbfn(br_pixelmap*, void*);
typedef br_pixelmap* br_table_find_cbfn(char*);
typedef br_uint_32 br_table_enum_cbfn(br_pixelmap*, void*);
typedef br_uint_32 br_actor_enum_cbfn(br_actor*, void*);
typedef intptr_t br_actor_enum_cbfn(br_actor*, void*);
typedef struct br_vector3 br_vector3;
typedef int br_pick2d_cbfn(br_actor*, br_model*, br_material*, br_vector3*, br_vector3*, br_scalar, br_scalar, void*);
typedef struct br_matrix34 br_matrix34;
@ -2947,10 +2947,8 @@ enum {
BR_MATF_ALWAYS_VISIBLE = 0x00000800,
BR_MATF_TWO_SIDED = 0x00001000,
BR_MATF_FORCE_Z_0 = 0x00002000,
BR_MATF_DITHER = 0x00004000
#if 0
BR_MATF_CUSTOM = 0x00008000
#endif
BR_MATF_DITHER = 0x00004000,
BR_MATF_CUSTOM = 0x00008000
};
/*
@ -2963,7 +2961,7 @@ enum {
BR_MODU_GROUPS = 0x0008,
BR_MODU_BOUNDING_BOX = 0x0010,
BR_MODU_MATERIALS = 0x0020,
BR_MODU_UNKNOWN = 0x0100, /* Added by JeffH. Referred to in code */
BR_MODU_UNKNOWN = 0x0100, /* Added by Jeff. Referred to in code */
BR_MODU_ALL = 0x7fff
};
@ -3003,7 +3001,12 @@ enum {
BR_MODF_CUSTOM = 0x0020, /* Invoke custom callback for this model */
BR_MODF_PREPREPARED = 0x0040, /* Model structure is pre-prepared - update performs no work */
BR_MODF_UPDATEABLE = 0x0080 /* Added by JeffH from Errols code */
BR_MODF_CREASE = 0x0100, /* Create creases in smoothing along edges if face<->face angle is g.t model->crease */
BR_MODF_CUSTOM_NORMALS = 0x0200, /* Uses vertex normals from br_vertex structure */
BR_MODF_CUSTOM_BOUNDS = 0x0400, /* Bounding box is already set up */
//BR_MODF_FACES_ONLY = 0x0800, /* Model will only be used to render faces (not edges or points) */
BR_MODF_UPDATEABLE = 0x0080 /* Added by Jeff from Errols code */
};
#define BR_COLOUR_RGB(r, g, b) \
@ -3014,4 +3017,10 @@ enum {
#define BR_SCALAR(x) ((br_scalar)(x))
#define BR_COLOUR_RGBA(r, g, b, a) \
((((unsigned int)(a)) << 24) | (((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b)))
#define BR_LENGTH3(a, b, c) ((br_scalar)sqrt((a) * (a) + (b) * (b) + (c) * (c)))
#define BR_SCALAR_EPSILON 1.192092896e-7f
#endif /* BR_TYPES_H */

View File

@ -42,4 +42,7 @@ br_pixelmap* BrTableFind(char* pattern);
void BrFatal(const char* name, int line, const char* s, ...);
void BrModelFree(br_model* model);
void BrModelUpdate(br_model* model, br_uint_16 flags);
#endif

View File

@ -18,7 +18,7 @@ DEPS := $(OBJS:.o=.d)
INC_DIRS := $(shell find $(SRC_DIR) -type d) $(BR_SRC_DIR) $(HARNESS_SRC_DIR) $(LIB_SRC_DIR)
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
CFLAGS ?= $(INC_FLAGS) -g -Wno-return-type -Wno-missing-declarations -Werror=implicit-function-declaration
CFLAGS ?= $(INC_FLAGS) -g -Wno-return-type -Wno-missing-declarations -Werror=implicit-function-declaration -Werror=format -Werror=int-to-pointer-cast
SDL_LDFLAGS = `sdl2-config --libs`

View File

@ -169,7 +169,15 @@ void ChangeYCoordinate(br_scalar pNew_y, tU32 pTime_taken, br_model* pThe_model,
void SwitchCarActor(tCar_spec* pCar_spec, int pModel_index) {
int i;
LOG_TRACE("(%p, %d)", pCar_spec, pModel_index);
NOT_IMPLEMENTED();
for (i = 0; i < pCar_spec->car_actor_count; i++) {
if (i == pModel_index) {
pCar_spec->car_model_actors[i].actor->render_style = BR_RSTYLE_FACES;
} else {
pCar_spec->car_model_actors[i].actor->render_style = BR_RSTYLE_NONE;
}
}
pCar_spec->current_car_actor = pModel_index;
}
// IDA: void __usercall InitialiseCar2(tCar_spec *pCar@<EAX>, int pClear_disabled_flag@<EDX>)
@ -1763,7 +1771,33 @@ void SetCarSuspGiveAndHeight(tCar_spec* pCar, br_scalar pFront_give_factor, br_s
br_scalar ratio;
int i;
LOG_TRACE("(%p, %f, %f, %f, %f, %f)", pCar, pFront_give_factor, pRear_give_factor, pDamping_factor, pExtra_front_height, pExtra_rear_height);
NOT_IMPLEMENTED();
front_give = pCar->susp_give[1] * pFront_give_factor * 6.9000001;
rear_give = pCar->susp_give[0] * pRear_give_factor * 6.9000001;
damping = pCar->damping * pDamping_factor;
ratio = fabs((pCar->wpos[0].v[2] - pCar->cmpos.v[2]) / (pCar->wpos[2].v[2] - pCar->cmpos.v[2]));
pCar->sk[0] = pCar->M / (ratio + 1.0) * 5.0 / rear_give;
pCar->sb[0] = pCar->M / (ratio + 1.0) * sqrt(5.0) / sqrt(rear_give);
ratio = 1.0 / ratio;
pCar->sk[1] = pCar->M / (ratio + 1.0) * 5.0 / front_give;
pCar->sb[1] = pCar->M / (ratio + 1.0) * sqrt(5.0) / sqrt(front_give);
pCar->sb[0] = pCar->sb[0] * damping;
pCar->sb[1] = pCar->sb[1] * damping;
pCar->susp_height[0] = pCar->ride_height + rear_give + pExtra_rear_height;
pCar->susp_height[1] = pCar->ride_height + front_give + pExtra_front_height;
if (rear_give >= front_give) {
i = -rear_give;
} else {
i = -front_give;
}
if (pExtra_rear_height >= pExtra_front_height) {
i -= pExtra_rear_height;
} else {
i -= pExtra_front_height;
}
pCar->bounds[0].min.v[1] = i;
pCar->bounds[0].min.v[1] = pCar->bounds[0].min.v[1] / 6.9000001;
}
// IDA: int __usercall TestForCarInSensiblePlace@<EAX>(tCar_spec *car@<EAX>)

View File

@ -1,4 +1,6 @@
#include "crush.h"
#include "brender.h"
#include "loading.h"
#include <stdlib.h>
float gWobble_spam_y[8];
@ -17,7 +19,36 @@ int ReadCrushData(FILE* pF, tCrush_data* pCrush_data) {
tCrush_point_spec* the_spec;
tCrush_neighbour* the_neighbour;
LOG_TRACE("(%p, %p)", pF, pCrush_data);
NOT_IMPLEMENTED();
pCrush_data->softness_factor = GetAFloat(pF);
GetPairOfFloats(pF, &pCrush_data->min_fold_factor, &pCrush_data->max_fold_factor);
pCrush_data->wibble_factor = GetAFloat(pF);
pCrush_data->limit_deviant = GetAFloat(pF);
pCrush_data->split_chance = GetAFloat(pF);
pCrush_data->min_y_fold_down = GetAFloat(pF);
pCrush_data->number_of_crush_points = GetAnInt(pF);
pCrush_data->crush_points = (tCrush_point_spec*)BrMemAllocate(sizeof(tCrush_point_spec) * pCrush_data->number_of_crush_points, kMem_crush_data);
the_spec = pCrush_data->crush_points;
for (i = 0; i < pCrush_data->number_of_crush_points; i++) {
the_spec->vertex_index = GetAnInt(pF);
GetThreeFloats(pF, &the_spec->limits_neg.v[0], &the_spec->limits_neg.v[1], &the_spec->limits_neg.v[2]);
GetThreeFloats(pF, &the_spec->limits_pos.v[0], &the_spec->limits_pos.v[1], &the_spec->limits_pos.v[2]);
GetThreeFloats(pF, &the_spec->softness_neg.v[0], &the_spec->softness_neg.v[1], &the_spec->softness_neg.v[2]);
GetThreeFloats(pF, &the_spec->softness_pos.v[0], &the_spec->softness_pos.v[1], &the_spec->softness_pos.v[2]);
the_spec->number_of_neighbours = GetAnInt(pF);
the_spec->neighbours = BrMemAllocate(sizeof(tCrush_neighbour) * the_spec->number_of_neighbours, kMem_crush_neighbours);
the_neighbour = the_spec->neighbours;
for (j = 0; j < the_spec->number_of_neighbours; j++) {
the_neighbour->vertex_index = GetAnInt(pF);
the_neighbour->factor = GetAnInt(pF);
the_neighbour++;
}
the_spec++;
}
LOG_DEBUG("exit");
return 0;
}
// IDA: float __usercall SkipCrushData@<ST0>(FILE *pF@<EAX>)

View File

@ -313,7 +313,12 @@ void AssertYons() {
br_camera* camera_ptr;
int i;
LOG_TRACE("()");
NOT_IMPLEMENTED();
for ( i = 0; i < 2; ++i )
{
camera_ptr = gCamera_list[i]->type_data;
camera_ptr->yon_z = gYon_multiplier * gCamera_yon;
}
}
// IDA: void __cdecl IncreaseYon()

View File

@ -4,7 +4,33 @@
#include "br_types.h"
#include "dr_types.h"
extern br_font* gBR_fonts[4];
extern tQueued_headup gQueued_headups[4];
extern int gOld_times[10];
extern int gLast_fancy_headup;
extern tU32 gLast_time_earn_time;
extern tU32 gLast_centre_headup;
extern tU32 gLast_fancy_time;
extern int gQueued_headup_count;
extern tU32 gLast_earn_time;
extern tU32 gLast_time_credit_amount;
extern int gLast_credit_amount;
extern tDR_font* gCached_font;
extern int gLast_time_credit_headup;
extern int gLast_fancy_index;
extern int gLast_credit_headup;
extern tHeadup gHeadups[15];
extern int gLaps_headup;
extern int gCar_kill_count_headup;
extern int gTimer_headup;
extern int gTime_awarded_headup;
extern int gPed_kill_count_headup;
extern int gDim_amount;
extern br_pixelmap* gHeadup_images[31];
extern int gNet_cash_headup;
extern int gNet_ped_headup;
extern int gCredits_lost_headup;
extern int gCredits_won_headup;
void GetTimerString(char* pStr, int pFudge_colon);

View File

@ -20,7 +20,7 @@ br_filesystem gFilesystem = {
NULL
};
// Added by JeffH
// Added by Jeff
#define DR_MEMORY_FILESYSTEM 140
// IDA: void* __cdecl DRStdioOpenRead(char *name, br_size_t n_magics, br_mode_test_cbfn *identify, int *mode_result)

View File

@ -141,6 +141,7 @@ void FatalError(int pStr_index, ...) {
char* sub_pt;
va_list ap;
int i = 0;
LOG_TRACE("(%d)", pStr_index);
va_start(ap, pStr_index);

View File

@ -1434,7 +1434,7 @@ void FlushFlicQueue() {
tFlic_descriptor* old_flic;
LOG_TRACE("()");
// JeffH: loop through pending flics until we reach the end or we find one that is `must_finish`.
// Jeff: loop through pending flics until we reach the end or we find one that is `must_finish`.
// If `must_finish`, we process the queue then check again.
// If there are no `must_finish` in the list,
while (gFirst_flic) {

View File

@ -258,7 +258,72 @@ void CopyStripImage(br_pixelmap* pDest, br_int_16 pDest_x, br_int_16 pOffset_x,
char* destn_ptr;
char* destn_ptr2;
LOG_TRACE("(%p, %d, %d, %d, %d, %p, %d, %d, %d, %d)", pDest, pDest_x, pOffset_x, pDest_y, pOffset_y, pSource, pSource_x, pSource_y, pWidth, pHeight);
NOT_IMPLEMENTED();
height = *(uint16_t*)pSource;
pSource = pSource + 2;
if (pDest_y + pOffset_y >= 0) {
destn_ptr = (char*)pDest->pixels + pDest->row_bytes * (pDest_y + pOffset_y);
} else {
LOG_PANIC("path not implemented");
// Copy8BitStripImageTo16Bit(
// pSource,
// -pDest_y - pOffset_y,
// v12,
// v13,
// v14,
// (tS8*)height,
// v16,
// v18,
// v20,
// v22);
// pSourcea = v10;
// destn_ptr = (char*)pDest->pixels;
// height = pDest_y + pOffset_y + v11;
// pOffset_y = 0;
// pDest_y = 0;
}
if (height + pDest_y + pOffset_y > pDest->height) {
height = pDest->height - pDest_y - pOffset_y;
}
off_the_left = pDest_x + pOffset_x;
if (off_the_left > 0) {
destn_ptr += off_the_left;
}
for (i = 0; i < height; i++) {
destn_ptr2 = destn_ptr;
number_of_chunks = *pSource;
pSource++;
x_byte = off_the_left;
for (j = 0; j < number_of_chunks; j++) {
chunk_length = *pSource++;
if (chunk_length >= 0) {
old_x_byte = x_byte;
x_byte += chunk_length;
if (old_x_byte >= 0) {
destn_ptr2 += chunk_length;
} else if (x_byte > 0) {
destn_ptr2 += chunk_length + old_x_byte;
}
} else {
old_x_byte = x_byte;
x_byte += -chunk_length;
if (old_x_byte >= 0) {
if (pDest->width >= x_byte) {
memcpy(destn_ptr2, pSource, -chunk_length);
destn_ptr2 += -chunk_length;
} else if (old_x_byte < pDest->width) {
memcpy(destn_ptr2, pSource, pDest->width - old_x_byte);
}
} else if (x_byte > 0) {
memcpy(destn_ptr2, &pSource[-old_x_byte], -chunk_length + old_x_byte);
destn_ptr2 += -chunk_length + old_x_byte;
}
pSource += -chunk_length;
}
}
destn_ptr += pDest->row_bytes;
}
}
// IDA: void __usercall SetBRenderScreenAndBuffers(int pX_offset@<EAX>, int pY_offset@<EDX>, int pWidth@<EBX>, int pHeight@<ECX>)
@ -308,7 +373,33 @@ void SetIntegerMapRenders() {
void AdjustRenderScreenSize() {
int switched_res;
LOG_TRACE("()");
NOT_IMPLEMENTED();
switched_res = SwitchToRealResolution();
ReinitialiseRenderStuff();
if (gMap_mode) {
gRender_screen->base_x = gMap_render_x_i;
gRender_screen->base_y = gMap_render_y_i;
gRender_screen->width = gMap_render_width_i;
gRender_screen->height = gMap_render_height_i;
} else {
gRender_screen->base_x = gProgram_state.current_render_left;
gRender_screen->base_y = gProgram_state.current_render_top;
gRender_screen->height = gProgram_state.current_render_bottom - gProgram_state.current_render_top;
gRender_screen->width = gProgram_state.current_render_right - gProgram_state.current_render_left;
}
if (gRender_screen->row_bytes == gRender_screen->width) {
gRender_screen->flags |= BR_PMF_ROW_WHOLEPIXELS;
} else {
//v0 = gRender_screen->flags & 0xFB;
}
gRender_screen->origin_x = gRender_screen->width / 2;
gRender_screen->origin_y = gRender_screen->height / 2;
gWidth = gRender_screen->width;
gHeight = gRender_screen->height;
ReinitialiseForwardCamera();
if (switched_res) {
SwitchToLoresMode();
}
}
// IDA: void __cdecl ScreenSmaller()
@ -738,7 +829,7 @@ void Darken(tU8* pPtr, unsigned int pDarken_amount) {
void SetFadedPalette(int pDegree) {
int j;
br_pixelmap* the_palette;
unsigned char* the_pixels; //JeffH added unsigned
unsigned char* the_pixels; //Jeff added unsigned
LOG_TRACE10("(%d)", pDegree);
memcpy(gScratch_pixels, gCurrent_palette->pixels, 0x400u);

View File

@ -104,7 +104,8 @@ void ReinitialiseForwardCamera() {
float d;
float w;
LOG_TRACE("()");
NOT_IMPLEMENTED();
STUB();
}
// IDA: void __cdecl AllocateRearviewPixelmap()
@ -144,7 +145,7 @@ void AllocateRearviewPixelmap() {
void ReinitialiseRearviewCamera() {
br_camera* camera_ptr;
LOG_TRACE("()");
NOT_IMPLEMENTED();
STUB();
}
// IDA: void __cdecl ReinitialiseRenderStuff()
@ -152,7 +153,20 @@ void ReinitialiseRenderStuff() {
int x_diff;
int y_diff;
LOG_TRACE("()");
NOT_IMPLEMENTED();
if (gProgram_state.cockpit_on) {
gProgram_state.current_render_left = gProgram_state.current_car.render_left[gProgram_state.cockpit_image_index];
gProgram_state.current_render_top = gProgram_state.current_car.render_top[gProgram_state.cockpit_image_index];
gProgram_state.current_render_right = gProgram_state.current_car.render_right[gProgram_state.cockpit_image_index];
gProgram_state.current_render_bottom = gProgram_state.current_car.render_bottom[gProgram_state.cockpit_image_index];
} else {
y_diff = (gGraf_specs[gGraf_spec_index].total_height / 18 & 0xFFFFFFFE) * gRender_indent;
x_diff = (gGraf_specs[gGraf_spec_index].total_width / 18 & 0xFFFFFFFC) * gRender_indent;
gProgram_state.current_render_left = x_diff;
gProgram_state.current_render_top = y_diff;
gProgram_state.current_render_right = gGraf_specs[gGraf_spec_index].total_width - x_diff;
gProgram_state.current_render_bottom = gGraf_specs[gGraf_spec_index].total_height - y_diff;
}
}
// IDA: void __cdecl InstallFindFailedHooks()
@ -346,7 +360,41 @@ void InitialiseDeathRace(int pArgc, char** pArgv) {
void InitGame(int pStart_race) {
int i;
LOG_TRACE("(%d)", pStart_race);
NOT_IMPLEMENTED();
gWaiting_for_unpause = 1;
gWait_for_it = 1;
if (gNet_mode) {
gCredit_period = gCredit_period_network[gCurrent_net_game->type];
} else {
gCredit_period = gCredit_period_single[gProgram_state.skill_level];
}
SwitchToRealResolution();
gGame_to_load = -1;
gCurrent_race.number_of_racers = 0;
LoadHeadupImages();
gGame_initialized = 1;
gNet_mode_of_last_game = gNet_mode;
gNo_races_yet = 1;
NetPlayerStatusChanged(ePlayer_status_loading);
gProgram_state.current_race_index = pStart_race;
for (i = 0; i < COUNT_OF(gProgram_state.current_car.power_up_levels); i++) {
gProgram_state.current_car.power_up_levels[i] = 0;
}
for (i = 0; gNumber_of_races > i; ++i) {
gRace_list[i].been_there_done_that = 0;
}
for (i = 0; gNumber_of_racers > i; ++i) {
gOpponents[i].dead = 0;
}
gProgram_state.rank = gInitial_rank;
gProgram_state.credits = gInitial_credits[gProgram_state.skill_level];
gProgram_state.credits_per_rank = gCredits_per_rank[gProgram_state.skill_level];
gProgram_state.number_of_cars = 1;
gProgram_state.cars_available[0] = gProgram_state.frank_or_anniness;
gProgram_state.game_completed = 0;
gProgram_state.redo_race_index = -1;
gWait_for_it = 0;
return SwitchToLoresMode();
}
// IDA: void __cdecl DisposeGameIfNecessary()

View File

@ -291,7 +291,7 @@ int KeyIsDown(int pKey_index) {
void WaitForNoKeys() {
LOG_TRACE("()");
int key_result = 0; //JeffH added
int key_result = 0; //Jeff added
while (1) {
CheckQuit();

File diff suppressed because it is too large Load Diff

View File

@ -120,7 +120,7 @@ void AddRefOffset(int* pRef_holder);
void GetDamageProgram(FILE* pF, tCar_spec* pCar_spec, tImpact_location pImpact_location);
br_uint_32 LinkModel(br_actor* pActor, tModel_pool* pModel_pool);
intptr_t LinkModel(br_actor* pActor, tModel_pool* pModel_pool);
void FreeUpBonnetModels(br_model** pModel_array, int pModel_count);

View File

@ -461,7 +461,7 @@ void ReceivedLeave(tNet_contents* pContents, tNet_message* pMessage) {
void NetFullScreenMessage(int pStr_index, int pLeave_it_up_there) {
tU32 start_time;
char* s;
// JeffH: added underscore suffix to avoid collisions with samed-named globals
// Jeff: added underscore suffix to avoid collisions with samed-named globals
int gPixel_buffer_size_;
char* gPixels_copy_;
char* gPalette_copy_;

View File

@ -4,6 +4,45 @@
#include "br_types.h"
#include "dr_types.h"
extern br_pixelmap* gFlame_map[20];
extern tBRender_smoke* gBR_smoke_pointers[30];
extern tSplash gSplash[32];
extern br_material* gSplash_material[20];
extern tBRender_smoke gBR_smoke_structs[30];
extern tSmoke_column gSmoke_column[25];
extern br_matrix4 gCameraToScreen;
extern tSpark gSparks[32];
extern br_model* gShrapnel_model[2];
extern br_pixelmap* gShade_list[16];
extern int gN_BR_smoke_structs;
extern br_pixelmap** gDust_table;
extern tSmoke gSmoke[25];
extern tU32 gSplash_flags;
extern int gSmoke_num;
extern int gNext_column;
extern int gColumn_flags;
extern tU32 gNext_splash;
extern int gOffset;
extern int gIt_type;
extern br_pixelmap* gBlack_smoke_shade_table;
extern br_pixelmap* gGrey_smoke_shade_table;
extern br_model* gLollipop_model;
extern int gNum_splash_types;
extern int gNum_dust_tables;
extern int gSmoke_on;
extern int gSmoke_flags;
extern br_model* gSplash_model;
extern int gDust_rotate;
extern br_pixelmap* gIt_shade_table;
extern br_pixelmap* gDark_smoke_shade_table;
extern int gShrapnel_flags;
extern int gSpark_flags;
extern int gNext_shrapnel;
extern br_camera* gSpark_cam;
extern int gNext_spark;
extern br_material* gBlack_material;
extern tShrapnel gShrapnel[15];
void DrawDot(br_scalar z, tU8* scr_ptr, tU16* depth_ptr, tU8* shade_ptr);
void SetWorldToScreen(br_pixelmap* pScreen);

View File

@ -99,7 +99,9 @@ void DoLogos() {
// IDA: void __cdecl DoProgOpeningAnimation()
void DoProgOpeningAnimation() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.prog_status = eProg_idling;
DRS3StopOutletSound(gIndexed_outlets[0]);
}
// IDA: void __cdecl DoProgramDemo()
@ -195,56 +197,32 @@ void InitialiseProgramState() {
// IDA: void __cdecl DoProgram()
void DoProgram() {
InitialiseProgramState();
while (1) {
while (gProgram_state.prog_status != eProg_quit) {
switch (gProgram_state.prog_status) {
case eProg_intro:
DisposeGameIfNecessary();
ClearEntireScreen();
DoSCILogo();
DoOpeningAnimation();
DoSCILogo();
gProgram_state.prog_status = eProg_opening;
continue;
DoLogos();
break;
case eProg_opening:
DisposeGameIfNecessary();
gProgram_state.prog_status = eProg_idling;
DRS3StopOutletSound(gIndexed_outlets[0]);
if (gProgram_state.prog_status == eProg_quit) {
return;
}
continue;
DoProgOpeningAnimation();
break;
case eProg_idling:
DisposeGameIfNecessary();
if (gGame_to_load >= 0) {
DoLoadGame(0);
if (gProgram_state.prog_status == eProg_quit) {
return;
}
continue;
if (gGame_to_load < 0) {
DoMainMenuScreen(30000u, 0, 0);
} else {
DoLoadGame();
}
DoMainMenuScreen(30000, 0, 0);
if (gProgram_state.prog_status != eProg_quit) {
continue;
}
return;
break;
case eProg_demo:
DoLogos();
gProgram_state.prog_status = eProg_idling;
DRS3StopOutletSound(gIndexed_outlets[0]);
if (gProgram_state.prog_status == eProg_quit) {
return;
}
continue;
DoProgramDemo();
break;
case eProg_game_starting:
DoGame();
if (gProgram_state.prog_status == eProg_quit) {
return;
}
continue;
case eProg_game_ongoing:
case eProg_quit:
// JeffH added to avoid compiler warnings about missing case handling
LOG_PANIC("We do not expect to get here");
break;
default:
break;
}
}
}

View File

@ -59,27 +59,26 @@ void EncodeLine(char* pS) {
char* key;
unsigned char c;
FILE* test;
tPath_name test_path;
char temp[256];
tPath_name the_path;
char s[256];
len = strlen(pS);
key = (char*)gLong_key;
if (!gEncryption_method) {
strcpy(test_path, gApplication_path);
strcat(test_path, gDir_separator);
strcat(test_path, "GENERAL.TXT");
strcpy(the_path, gApplication_path);
strcat(the_path, gDir_separator);
strcat(the_path, "GENERAL.TXT");
test = fopen(test_path, "rt");
test = fopen(the_path, "rt");
if (test) {
fgets(temp, 256, test);
if (temp[0] != '@') {
fgets(s, 256, test);
if (s[0] != '@') {
gEncryption_method = 2;
} else {
gEncryption_method = 1;
EncodeLine(&temp[1]);
temp[7] = '\0';
if (strcmp(&temp[1], "0.01\t\t") != 0) {
EncodeLine(&s[1]);
s[7] = '\0';
if (strcmp(&s[1], "0.01\t\t") != 0) {
gEncryption_method = 2;
}
}
@ -181,7 +180,7 @@ br_scalar SRandomPosNeg(br_scalar pN) {
// IDA: char* __usercall GetALineWithNoPossibleService@<EAX>(FILE *pF@<EAX>, unsigned char *pS@<EDX>)
char* GetALineWithNoPossibleService(FILE* pF, /*unsigned*/ char* pS) {
// JeffH removed "signed' to avoid compiler warnings..
// Jeff removed "signed' to avoid compiler warnings..
/*signed*/ char* result;
/*signed*/ char s[256];
int ch;
@ -241,6 +240,7 @@ char* GetALineWithNoPossibleService(FILE* pF, /*unsigned*/ char* pS) {
pS[i] -= 32;
}
}
//LOG_DEBUG("%s", result);
return result;
}
@ -421,8 +421,8 @@ void WaitFor(tU32 pDelay) {
}
// IDA: br_uint_32 __usercall DRActorEnumRecurse@<EAX>(br_actor *pActor@<EAX>, br_actor_enum_cbfn *callback@<EDX>, void *arg@<EBX>)
br_uint_32 DRActorEnumRecurse(br_actor* pActor, br_actor_enum_cbfn* callback, void* arg) {
br_uint_32 result;
intptr_t DRActorEnumRecurse(br_actor* pActor, br_actor_enum_cbfn* callback, void* arg) {
intptr_t result;
result = callback(pActor, arg);
if (result == 0) {
@ -444,15 +444,20 @@ br_uint_32 DRActorEnumRecurse(br_actor* pActor, br_actor_enum_cbfn* callback, vo
}
// IDA: br_uint_32 __cdecl CompareActorID(br_actor *pActor, void *pArg)
br_uint_32 CompareActorID(br_actor* pActor, void* pArg) {
intptr_t CompareActorID(br_actor* pActor, void* pArg) {
LOG_TRACE("(%p, %p)", pActor, pArg);
NOT_IMPLEMENTED();
if (pActor->identifier && !strcmp(pActor->identifier, (const char*)pArg)) {
return (intptr_t)pActor;
} else {
return 0;
}
}
// IDA: br_actor* __usercall DRActorFindRecurse@<EAX>(br_actor *pSearch_root@<EAX>, char *pName@<EDX>)
br_actor* DRActorFindRecurse(br_actor* pSearch_root, char* pName) {
LOG_TRACE("(%p, \"%s\")", pSearch_root, pName);
NOT_IMPLEMENTED();
return (br_actor*)DRActorEnumRecurse(pSearch_root, CompareActorID, pName);
}
// IDA: br_uint_32 __usercall DRActorEnumRecurseWithMat@<EAX>(br_actor *pActor@<EAX>, br_material *pMat@<EDX>, br_uint_32 (*pCall_back)(br_actor*, br_material*, void*)@<EBX>, void *pArg@<ECX>)
@ -771,9 +776,28 @@ int NormalSideOfPlane(br_vector3* pPoint, br_vector3* pNormal, br_scalar pD) {
br_material* DRMaterialClone(br_material* pMaterial) {
br_material* the_material;
char s[256];
static int name_suffix;
static int name_suffix = 0;
LOG_TRACE("(%p)", pMaterial);
NOT_IMPLEMENTED();
the_material = BrMaterialAllocate(NULL);
the_material->flags = pMaterial->flags;
the_material->ka = pMaterial->ka;
the_material->kd = pMaterial->kd;
the_material->ks = pMaterial->ks;
the_material->power = pMaterial->power;
the_material->colour = pMaterial->colour;
the_material->index_base = pMaterial->index_base;
the_material->index_range = pMaterial->index_range;
the_material->index_shade = pMaterial->index_shade;
the_material->index_blend = pMaterial->index_blend;
the_material->colour_map = pMaterial->colour_map;
memcpy(&the_material->map_transform, &pMaterial->map_transform, sizeof(the_material->map_transform));
sprintf(s, "%s(%d)", pMaterial->identifier, name_suffix);
name_suffix++;
the_material->identifier = (char*)BrResAllocate(the_material, strlen(s) + 1, BR_MEMORY_STRING);
strcpy(the_material->identifier, s);
BrMaterialAdd(the_material);
return the_material;
}
// IDA: void __usercall StripCR(char *s@<EAX>)
@ -1043,7 +1067,11 @@ void SkipNLines(FILE* pF) {
int count;
char s[256];
LOG_TRACE("(%p)", pF);
NOT_IMPLEMENTED();
count = GetAnInt(pF);
for (i = 0; i < count; i++) {
GetALineAndDontArgue(pF, s);
}
}
// IDA: int __usercall DRStricmp@<EAX>(char *p1@<EAX>, char *p2@<EDX>)

View File

@ -61,9 +61,9 @@ br_uint_32 DRPixelmapLoadMany(char* pFile_name, br_pixelmap** pPixelmaps, br_uin
void WaitFor(tU32 pDelay);
br_uint_32 DRActorEnumRecurse(br_actor* pActor, br_actor_enum_cbfn* callback, void* arg);
intptr_t DRActorEnumRecurse(br_actor* pActor, br_actor_enum_cbfn* callback, void* arg);
br_uint_32 CompareActorID(br_actor* pActor, void* pArg);
intptr_t CompareActorID(br_actor* pActor, void* pArg);
br_actor* DRActorFindRecurse(br_actor* pSearch_root, char* pName);

View File

@ -3,8 +3,11 @@
#include "brender.h"
#include "car.h"
#include "errors.h"
#include "flicplay.h"
#include "globvars.h"
#include "loading.h"
#include "pc-dos/dossys.h"
#include "utility.h"
#include <string.h>
@ -15,15 +18,15 @@ br_actor* gDelete_list[500];
br_actor* gLight_array[50];
br_model* gAdditional_models[1000];
br_actor* gSpec_vol_actors[100];
char* gDepth_effect_names[2] = { "dark", "fog" };
char* gFunk_nature_names[4];
char* gGroove_object_names[4];
char* gGroove_path_names[2];
char* gGroove_nature_names[2];
char* gFunk_anim_names[2];
char* gFunk_move_names[6];
char* gDepth_effect_names[] = { "dark", "fog" };
char* gFunk_nature_names[] = { "constant", "distance", "lastlap", "otherlaps" };
char* gGroove_object_names[] = { "spin", "rock", "throb", "shear" };
char* gGroove_path_names[] = { "straight", "circular" };
char* gGroove_nature_names[] = { "constant", "distance" };
char* gFunk_anim_names[] = { "frames", "flic" };
char* gFunk_move_names[] = { "linear", "harmonic", "flash", "controlled", "absolute", "continuous" };
tPath_name gAdditional_actor_path;
char* gTime_mode_names[2];
char* gTime_mode_names[] = { "approximate", "accurate" };
tPath_name gAdditional_model_path;
tU32 gPrevious_groove_times[2];
int gRace_file_version;
@ -31,7 +34,7 @@ br_vector3 gActor_centre;
tWall_texturing_level gWall_texturing_level = eWTL_full;
int gNumber_of_additional_models;
int gNumber_of_actors;
float gTemp;
float x_0;
br_actor* gLast_actor;
br_actor* gKnown_actor;
br_actor* gAdditional_actors;
@ -47,12 +50,12 @@ br_actor* gStandard_lamp;
tRotate_mode gCurrent_rotate_mode = eRotate_mode_y;
tCar_texturing_level gCar_texturing_level = eCTL_full;
br_scalar gSight_distance_squared;
char* gLollipop_names[3];
char* gAxis_names[3];
char* gLollipop_names[] = { "xlollipop", "ylollipop", "zlollipop" };
char* gAxis_names[] = { "x", "y", "z" };
int gGroovidelics_array_size;
tGroovidelic_spec* gGroovidelics_array;
int gSpec_vol_mode;
char* gFunk_type_names[5];
char* gFunk_type_names[] = { "spin", "rock", "throb", "slither", "roll" };
tFunkotronic_spec* gFunkotronics_array;
int gFunkotronics_array_size;
@ -101,11 +104,11 @@ void InitialiseStorageSpace(tBrender_storage* pStorage_space, int pMax_pixelmaps
pStorage_space->max_shade_tables = pMax_shade_tables;
pStorage_space->max_materials = pMax_materials;
pStorage_space->max_models = pMax_models;
pStorage_space->pixelmaps = BrMemCalloc(pMax_pixelmaps, 4, 0xD7u);
pStorage_space->shade_tables = BrMemCalloc(pMax_shade_tables, 4, 0xD8u);
pStorage_space->materials = BrMemCalloc(pMax_materials, 4, 0xD9u);
pStorage_space->models = BrMemCalloc(pMax_models, 4, 0xDAu);
pStorage_space->saved_colour_maps = BrMemCalloc(pMax_materials, 4, 0xDBu);
pStorage_space->pixelmaps = BrMemCalloc(pMax_pixelmaps, 4, kMem_stor_space_pix);
pStorage_space->shade_tables = BrMemCalloc(pMax_shade_tables, 4, kMem_stor_space_tab);
pStorage_space->materials = BrMemCalloc(pMax_materials, 4, kMem_stor_space_mat);
pStorage_space->models = BrMemCalloc(pMax_models, 4, kMem_stor_space_mod);
pStorage_space->saved_colour_maps = BrMemCalloc(pMax_materials, 4, kMem_stor_space_save);
}
// IDA: void __usercall DisposeStorageSpace(tBrender_storage *pStorage_space@<EAX>)
@ -128,7 +131,20 @@ void ClearOutStorageSpace(tBrender_storage* pStorage_space) {
tAdd_to_storage_result AddPixelmapToStorage(tBrender_storage* pStorage_space, br_pixelmap** pThe_pm) {
int i;
LOG_TRACE("(%p, %p)", pStorage_space, pThe_pm);
NOT_IMPLEMENTED();
if (pStorage_space->pixelmaps_count >= pStorage_space->max_pixelmaps) {
return eStorage_not_enough_room;
}
for (i = 0; i < pStorage_space->pixelmaps_count; i++) {
if (pStorage_space->pixelmaps[i]->identifier
&& pThe_pm[1]
&& !strcmp(pStorage_space->pixelmaps[i]->identifier, (const char*)pThe_pm[1])) {
return eStorage_duplicate;
}
}
pStorage_space->pixelmaps[pStorage_space->pixelmaps_count++] = (br_pixelmap*)pThe_pm;
return eStorage_allocated;
}
// IDA: tAdd_to_storage_result __usercall AddShadeTableToStorage@<EAX>(tBrender_storage *pStorage_space@<EAX>, br_pixelmap *pThe_st@<EDX>)
@ -142,14 +158,39 @@ tAdd_to_storage_result AddShadeTableToStorage(tBrender_storage* pStorage_space,
tAdd_to_storage_result AddMaterialToStorage(tBrender_storage* pStorage_space, br_material* pThe_mat) {
int i;
LOG_TRACE("(%p, %p)", pStorage_space, pThe_mat);
NOT_IMPLEMENTED();
if (pStorage_space->materials_count >= pStorage_space->max_materials) {
return eStorage_not_enough_room;
}
for (i = 0; i < pStorage_space->materials_count; i++) {
if (pStorage_space->materials[i]->identifier
&& pThe_mat->identifier
&& !strcmp(pStorage_space->materials[i]->identifier, pThe_mat->identifier)) {
return eStorage_duplicate;
}
}
pStorage_space->saved_colour_maps[pStorage_space->materials_count] = 0;
pStorage_space->materials[pStorage_space->materials_count++] = pThe_mat;
return eStorage_allocated;
}
// IDA: tAdd_to_storage_result __usercall AddModelToStorage@<EAX>(tBrender_storage *pStorage_space@<EAX>, br_model *pThe_mod@<EDX>)
tAdd_to_storage_result AddModelToStorage(tBrender_storage* pStorage_space, br_model* pThe_mod) {
int i;
LOG_TRACE("(%p, %p)", pStorage_space, pThe_mod);
NOT_IMPLEMENTED();
if (pStorage_space->materials_count >= pStorage_space->max_models) {
return eStorage_not_enough_room;
}
for (i = 0; i < pStorage_space->models_count; i++) {
if (pStorage_space->models[i]->identifier
&& pThe_mod->identifier
&& !strcmp(pStorage_space->models[i]->identifier, pThe_mod->identifier)) {
return eStorage_duplicate;
}
}
pStorage_space->models[pStorage_space->models_count++] = pThe_mod;
return eStorage_allocated;
}
// IDA: int __usercall LoadNPixelmaps@<EAX>(tBrender_storage *pStorage_space@<EAX>, FILE *pF@<EDX>, int pCount@<EBX>)
@ -163,7 +204,43 @@ int LoadNPixelmaps(tBrender_storage* pStorage_space, FILE* pF, int pCount) {
char* str;
br_pixelmap* temp_array[200];
LOG_TRACE("(%p, %p, %d)", pStorage_space, pF, pCount);
NOT_IMPLEMENTED();
new_ones = 0;
for (i = 0; pCount > i; ++i) {
PossibleService();
GetALineAndDontArgue(pF, s);
str = strtok(s, "\t ,/");
PathCat(the_path, gApplication_path, gGraf_specs[gGraf_spec_index].data_dir_name);
PathCat(the_path, the_path, "PIXELMAP");
PathCat(the_path, the_path, str);
AllowOpenToFail();
total = DRPixelmapLoadMany(the_path, temp_array, 200);
if (!total) {
PathCat(the_path, gApplication_path, "PIXELMAP");
PathCat(the_path, the_path, str);
total = DRPixelmapLoadMany(the_path, temp_array, 200);
if (!total) {
FatalError(79);
}
}
for (j = 0; j < total; j++) {
if (temp_array[j]) {
switch (AddPixelmapToStorage(pStorage_space, (br_pixelmap**)temp_array[j])) {
case eStorage_not_enough_room:
FatalError(67);
break;
case eStorage_duplicate:
BrPixelmapFree(temp_array[j]);
break;
case eStorage_allocated:
BrMapAdd(temp_array[j]);
++new_ones;
break;
}
}
}
}
return new_ones;
}
// IDA: br_pixelmap* __usercall LoadSinglePixelmap@<EAX>(tBrender_storage *pStorage_space@<EAX>, char *pName@<EDX>)
@ -191,7 +268,37 @@ int LoadNShadeTables(tBrender_storage* pStorage_space, FILE* pF, int pCount) {
char* str;
br_pixelmap* temp_array[50];
LOG_TRACE("(%p, %p, %d)", pStorage_space, pF, pCount);
NOT_IMPLEMENTED();
new_ones = 0;
for (i = 0; i < pCount; i++) {
PossibleService();
GetALineAndDontArgue(pF, s);
str = strtok(s, "\t ,/");
PathCat(the_path, gApplication_path, "SHADETAB");
PathCat(the_path, the_path, str);
total = DRPixelmapLoadMany(the_path, temp_array, 50);
if (!total) {
FatalError(80);
}
for (j = 0; j < total; j++) {
if (temp_array[j]) {
switch (AddShadeTableToStorage(pStorage_space, temp_array[j])) {
case eStorage_not_enough_room:
FatalError(68);
break;
case eStorage_duplicate:
BrPixelmapFree(temp_array[j]);
break;
case eStorage_allocated:
BrTableAdd(temp_array[j]);
++new_ones;
break;
}
}
}
}
return new_ones;
}
// IDA: br_pixelmap* __usercall LoadSingleShadeTable@<EAX>(tBrender_storage *pStorage_space@<EAX>, char *pName@<EDX>)
@ -212,7 +319,35 @@ int LoadNMaterials(tBrender_storage* pStorage_space, FILE* pF, int pCount) {
char* str;
br_material* temp_array[200];
LOG_TRACE("(%p, %p, %d)", pStorage_space, pF, pCount);
NOT_IMPLEMENTED();
new_ones = 0;
for (i = 0; i < pCount; ++i) {
PossibleService();
GetALineAndDontArgue(pF, s);
str = strtok(s, "\t ,/");
PathCat(the_path, gApplication_path, "MATERIAL");
PathCat(the_path, the_path, str);
total = BrMaterialLoadMany(the_path, temp_array, 200);
if (!total) {
FatalError(81);
}
for (j = 0; j < total; j++) {
if (temp_array[j]) {
switch (AddMaterialToStorage(pStorage_space, temp_array[j])) {
case eStorage_not_enough_room:
FatalError(69);
break;
case eStorage_duplicate:
BrMaterialFree(temp_array[j]);
break;
case eStorage_allocated:
BrMaterialAdd(temp_array[j]);
new_ones++;
}
}
}
}
return new_ones;
}
// IDA: int __usercall LoadNModels@<EAX>(tBrender_storage *pStorage_space@<EAX>, FILE *pF@<EDX>, int pCount@<EBX>)
@ -228,7 +363,40 @@ int LoadNModels(tBrender_storage* pStorage_space, FILE* pF, int pCount) {
v11model* prepared;
int group;
LOG_TRACE("(%p, %p, %d)", pStorage_space, pF, pCount);
NOT_IMPLEMENTED();
new_ones = 0;
for (i = 0; i < pCount; i++) {
PossibleService();
GetALineAndDontArgue(pF, s);
str = strtok(s, "\t ,/");
PathCat(the_path, gApplication_path, "MODELS");
PathCat(the_path, the_path, str);
total = BrModelLoadMany(the_path, temp_array, 2000);
if (!total) {
FatalError(82);
}
for (j = 0; j < total; j++) {
if (temp_array[j]) {
switch (AddModelToStorage(pStorage_space, temp_array[j])) {
case eStorage_not_enough_room:
LOG_DEBUG("going to");
FatalError(70);
break;
case eStorage_duplicate:
BrModelFree(temp_array[j]);
break;
case eStorage_allocated:
temp_array[j]->flags |= 0x80u;
RemoveDoubleSided(temp_array[j]);
BrModelAdd(temp_array[j]);
++new_ones;
break;
}
}
}
}
return new_ones;
}
// IDA: void __usercall DodgyModelUpdate(br_model *pM@<EAX>)
@ -323,7 +491,11 @@ void LoadSomePixelmaps(tBrender_storage* pStorage_space, FILE* pF) {
char* str;
br_pixelmap* temp_array[200];
LOG_TRACE("(%p, %p)", pStorage_space, pF);
NOT_IMPLEMENTED();
GetALineAndDontArgue(pF, s);
str = strtok(s, "\t ,/");
sscanf(str, "%d", &count);
LoadNPixelmaps(pStorage_space, pF, count);
}
// IDA: void __usercall LoadSomeShadeTables(tBrender_storage *pStorage_space@<EAX>, FILE *pF@<EDX>)
@ -337,7 +509,11 @@ void LoadSomeShadeTables(tBrender_storage* pStorage_space, FILE* pF) {
char* str;
br_pixelmap* temp_array[50];
LOG_TRACE("(%p, %p)", pStorage_space, pF);
NOT_IMPLEMENTED();
GetALineAndDontArgue(pF, s);
str = strtok(s, "\t ,/");
sscanf(str, "%d", &count);
LoadNShadeTables(pStorage_space, pF, count);
}
// IDA: void __usercall LoadSomeMaterials(tBrender_storage *pStorage_space@<EAX>, FILE *pF@<EDX>)
@ -351,7 +527,11 @@ void LoadSomeMaterials(tBrender_storage* pStorage_space, FILE* pF) {
char* str;
br_material* temp_array[200];
LOG_TRACE("(%p, %p)", pStorage_space, pF);
NOT_IMPLEMENTED();
GetALineAndDontArgue(pF, s);
str = strtok(s, "\t ,/");
sscanf(str, "%d", &count);
LoadNMaterials(pStorage_space, pF, count);
}
// IDA: void __usercall LoadSomeModels(tBrender_storage *pStorage_space@<EAX>, FILE *pF@<EDX>)
@ -365,7 +545,11 @@ void LoadSomeModels(tBrender_storage* pStorage_space, FILE* pF) {
char* str;
br_model* temp_array[2000];
LOG_TRACE("(%p, %p)", pStorage_space, pF);
NOT_IMPLEMENTED();
GetALineAndDontArgue(pF, s);
str = strtok(s, "\t ,/");
sscanf(str, "%d", &count);
LoadNModels(pStorage_space, pF, count);
}
// IDA: void __usercall LoadSomeTrackModels(tBrender_storage *pStorage_space@<EAX>, FILE *pF@<EDX>)
@ -385,7 +569,12 @@ void LoadSomeTrackModels(tBrender_storage* pStorage_space, FILE* pF) {
// IDA: void __usercall AddFunkGrooveBinding(int pSlot_number@<EAX>, float *pPeriod_address@<EDX>)
void AddFunkGrooveBinding(int pSlot_number, float* pPeriod_address) {
LOG_TRACE("(%d, %p)", pSlot_number, pPeriod_address);
NOT_IMPLEMENTED();
if (pSlot_number < 0 || pSlot_number >= COUNT_OF(gGroove_funk_bindings)) {
FatalError(72);
}
gGroove_funk_bindings[pSlot_number] = pPeriod_address;
*pPeriod_address = 0.0;
}
// IDA: void __usercall ControlBoundFunkGroove(int pSlot_number@<EAX>, float pValue)
@ -404,7 +593,13 @@ float ControlBoundFunkGroovePlus(int pSlot_number, float pValue) {
void ShiftBoundGrooveFunks(char* pStart, char* pEnd, int pDelta) {
int i;
LOG_TRACE("(\"%s\", \"%s\", %d)", pStart, pEnd, pDelta);
NOT_IMPLEMENTED();
for (i = 0; i < COUNT_OF(gGroove_funk_bindings); i++) {
if ((signed int)gGroove_funk_bindings[i] >= (signed int)pStart
&& (signed int)gGroove_funk_bindings[i] < (signed int)pEnd) {
gGroove_funk_bindings[i] = (float*)((char*)gGroove_funk_bindings[i] + (pDelta & 0xFFFFFFFC));
}
}
}
// IDA: tFunkotronic_spec* __cdecl AddNewFunkotronic()
@ -412,7 +607,28 @@ tFunkotronic_spec* AddNewFunkotronic() {
void* new_array;
int i;
LOG_TRACE("()");
NOT_IMPLEMENTED();
for (i = 0; i < gFunkotronics_array_size; i++) {
if (gFunkotronics_array[i].owner == -999) {
memset(&gFunkotronics_array[i], 0, sizeof(tFunkotronic_spec));
return &gFunkotronics_array[i];
}
}
gFunkotronics_array_size += 16;
new_array = BrMemCalloc(gFunkotronics_array_size, sizeof(tFunkotronic_spec), kMem_funk_spec);
if (gFunkotronics_array) {
memcpy(new_array, gFunkotronics_array, sizeof(tFunkotronic_spec) * (gFunkotronics_array_size - 16));
ShiftBoundGrooveFunks(
(char*)gFunkotronics_array,
(char*)&gFunkotronics_array[gFunkotronics_array_size - 16],
(char*)new_array - (char*)gFunkotronics_array);
BrMemFree(gFunkotronics_array);
}
gFunkotronics_array = new_array;
for (i = 0; i < 16; i++) {
gFunkotronics_array[gFunkotronics_array_size - i].owner = -999;
}
return &gFunkotronics_array[gFunkotronics_array_size - 16];
}
// IDA: void __usercall DisposeFunkotronics(int pOwner@<EAX>)
@ -477,8 +693,265 @@ void AddFunkotronics(FILE* pF, int pOwner, int pRef_offset) {
float s_max;
void* the_pixels;
br_pixelmap* the_pixelmap;
float x_0;
float x_1;
int d_0;
int d_1;
LOG_TRACE("(%p, %d, %d)", pF, pOwner, pRef_offset);
NOT_IMPLEMENTED();
first_time = 1;
while (!feof(pF)) {
PossibleService();
GetALineAndDontArgue(pF, s);
if (strcmp(s, "END OF FUNK") == 0) {
break;
}
if (!first_time) {
if (strcmp(s, "NEXT FUNK") != 0) {
FatalError(62);
}
GetALineAndDontArgue(pF, s);
}
first_time = 0;
the_funk = AddNewFunkotronic();
the_funk->owner = pOwner;
str = strtok(s, "\t ,/");
the_funk->material = BrMaterialFind(str);
if (!the_funk->material) {
FatalError(64);
}
the_funk->mode = GetALineAndInterpretCommand(pF, gFunk_nature_names, COUNT_OF(gFunk_nature_names));
the_funk->matrix_mod_type = GetALineAndInterpretCommand(pF, gFunk_type_names, COUNT_OF(gFunk_type_names));
if (the_funk->matrix_mod_type != -1) {
the_funk->matrix_mode = GetALineAndInterpretCommand(pF, gFunk_move_names, COUNT_OF(gFunk_move_names));
}
switch (the_funk->matrix_mod_type) {
case eMatrix_mod_spin:
if (the_funk->matrix_mode != eMove_controlled && the_funk->matrix_mode != eMove_absolute) {
x_0 = GetAFloat(pF);
the_funk->matrix_mod_data.spin_info.period = x_0 == -1 ? 0.0 : 1000.0 / x_0;
} else {
i = GetAnInt(pF);
AddFunkGrooveBinding(i + pRef_offset, &the_funk->matrix_mod_data.spin_info.period);
}
break;
case eMatrix_mod_rock: // rock
if (the_funk->matrix_mode != eMove_controlled && the_funk->matrix_mode != eMove_absolute) {
x_0 = GetAFloat(pF);
the_funk->matrix_mod_data.rock_info.period = x_0 == -1 ? 0.0 : 1000.0 / x_0;
} else {
d_0 = GetAnInt(pF);
AddFunkGrooveBinding(d_0 + pRef_offset, &the_funk->matrix_mod_data.rock_info.period);
}
the_funk->matrix_mod_data.rock_info.rock_angle = GetAFloat(pF);
GetPairOfFloats(pF, &x_0, &x_1);
the_funk->matrix_mod_data.rock_info.x_centre = x_0 / 100.0;
the_funk->matrix_mod_data.rock_info.y_centre = x_1 / 100.0;
break;
case eMatrix_mod_throb: // throb
if (the_funk->matrix_mode != eMove_controlled && the_funk->matrix_mode != eMove_absolute) {
GetPairOfFloats(pF, &speed1, &speed2);
the_funk->matrix_mod_data.throb_info.x_period = speed1 == 0.0f ? 0.0f : 1000.0f / speed1;
the_funk->matrix_mod_data.throb_info.y_period = speed2 == 0.0f ? 0.0f : 1000.0f / speed2;
} else {
GetPairOfInts(pF, &d_0, &d_1);
if (d_0 >= 0) {
AddFunkGrooveBinding(d_0 + pRef_offset, &the_funk->matrix_mod_data.throb_info.x_period);
}
if (d_1 >= 0) {
AddFunkGrooveBinding(d_1 + pRef_offset, &the_funk->matrix_mod_data.throb_info.y_period);
}
}
GetPairOfFloatPercents(
pF,
&the_funk->matrix_mod_data.throb_info.x_magnitude,
&the_funk->matrix_mod_data.throb_info.y_magnitude);
GetPairOfFloats(pF, &x_0, &x_1);
the_funk->matrix_mod_data.throb_info.x_centre = x_0 / 100.0;
the_funk->matrix_mod_data.throb_info.y_centre = x_1 / 100.0;
if (the_funk->matrix_mode != eMove_controlled) {
if (the_funk->matrix_mod_data.throb_info.x_period == 0.0) {
the_funk->matrix_mod_data.throb_info.x_period = 1.0;
the_funk->matrix_mod_data.throb_info.x_magnitude = 0.0;
}
if (the_funk->matrix_mod_data.throb_info.y_period == 0.0) {
the_funk->matrix_mod_data.throb_info.y_period = 1.0;
the_funk->matrix_mod_data.throb_info.y_magnitude = 0.0;
}
}
break;
case eMatrix_mod_slither: // slither
if (the_funk->matrix_mode != eMove_controlled && the_funk->matrix_mode != eMove_absolute) {
GetPairOfFloats(pF, &speed1, &speed2);
the_funk->matrix_mod_data.slither_info.x_period = speed1 == 0.0f ? 0.0f : 1000.0f / speed1;
the_funk->matrix_mod_data.slither_info.y_period = speed2 == 0.0f ? 0.0f : 1000.0f / speed2;
} else {
GetPairOfInts(pF, &d_0, &d_1);
if (d_0 >= 0) {
AddFunkGrooveBinding(d_0 + pRef_offset, &the_funk->matrix_mod_data.slither_info.x_period);
}
if (d_1 >= 0) {
AddFunkGrooveBinding(d_1 + pRef_offset, &the_funk->matrix_mod_data.slither_info.y_period);
}
}
GetPairOfFloatPercents(
pF,
&the_funk->matrix_mod_data.slither_info.x_magnitude,
&the_funk->matrix_mod_data.slither_info.y_magnitude);
if (the_funk->matrix_mode != eMove_controlled) {
if (the_funk->matrix_mod_data.slither_info.x_period == 0.0) {
the_funk->matrix_mod_data.slither_info.x_period = 1.0;
the_funk->matrix_mod_data.slither_info.x_magnitude = 0.0;
}
if (the_funk->matrix_mod_data.slither_info.y_period == 0.0) {
the_funk->matrix_mod_data.slither_info.y_period = 1.0;
the_funk->matrix_mod_data.slither_info.y_magnitude = 0.0;
}
}
break;
case eMatrix_mod_roll: // roll
if (the_funk->matrix_mode != eMove_controlled && the_funk->matrix_mode != eMove_absolute) {
GetPairOfFloats(pF, &speed1, &speed2);
the_funk->matrix_mod_data.roll_info.x_period = speed1 == 0.0f ? 0.0f : 1000.0f / speed1;
the_funk->matrix_mod_data.roll_info.y_period = speed2 == 0.0f ? 0.0f : 1000.0f / speed2;
} else {
GetPairOfInts(pF, &d_0, &d_1);
if (d_0 >= 0) {
AddFunkGrooveBinding(d_0 + pRef_offset, &the_funk->matrix_mod_data.roll_info.x_period);
}
if (d_1 >= 0) {
AddFunkGrooveBinding(d_1 + pRef_offset, &the_funk->matrix_mod_data.roll_info.y_period);
}
}
break;
default:
break;
}
the_funk->lighting_animation_type = GetALineAndInterpretCommand(pF, gFunk_move_names, COUNT_OF(gFunk_move_names));
if (the_funk->lighting_animation_type != -1) {
if (the_funk->lighting_animation_type != eMove_controlled && the_funk->lighting_animation_type != eMove_absolute) {
x_0 = GetAFloat(pF);
the_funk->lighting_animation_period = x_0 == 0.0f ? 0.0f : 1000.0 / x_0;
} else {
d_0 = GetAnInt(pF);
AddFunkGrooveBinding(d_0 + pRef_offset, &the_funk->lighting_animation_period);
}
GetThreeFloatPercents(pF, &a_min, &d_min, &s_min);
GetThreeFloatPercents(pF, &a_max, &d_max, &s_max);
the_funk->ambient_base = (a_min + a_max) / 2.0;
the_funk->direct_base = (d_min + d_max) / 2.0;
the_funk->specular_base = (s_min + s_max) / 2.0;
the_funk->ambient_delta = (a_max - a_min) / 2.0;
the_funk->direct_delta = (d_max - d_min) / 2.0;
the_funk->specular_delta = (s_max - s_min) / 2.0;
}
the_funk->texture_animation_type = GetALineAndInterpretCommand(pF, gFunk_anim_names, COUNT_OF(gFunk_anim_names));
if (the_funk->texture_animation_type != -1) {
the_funk->time_mode = GetALineAndInterpretCommand(pF, gTime_mode_names, COUNT_OF(gTime_mode_names));
}
if (the_funk->texture_animation_type == eTexture_animation_flic && gAusterity_mode) {
the_funk->texture_animation_type = -1;
GetALineAndDontArgue(pF, s);
}
the_funk->last_frame = 0.0;
if (the_funk->texture_animation_type == eTexture_animation_flic) {
GetAString(pF, s);
the_funk->texture_animation_data.flic_info.flic_data = 0;
if (LoadFlicData(
s,
&the_funk->texture_animation_data.flic_info.flic_data,
&the_funk->texture_animation_data.flic_info.flic_data_length)) {
the_funk->texture_animation_data.flic_info.flic_descriptor.data_start = NULL;
StartFlic(
s,
-1,
&the_funk->texture_animation_data.flic_info.flic_descriptor,
the_funk->texture_animation_data.flic_info.flic_data_length,
(tS8*)the_funk->texture_animation_data.flic_info.flic_data,
0,
0,
0,
0);
the_funk->last_frame = 0.0;
the_pixels = BrMemAllocate(
the_funk->texture_animation_data.flic_info.flic_descriptor.height
* ((the_funk->texture_animation_data.flic_info.flic_descriptor.width + 3) & 0xFFFFFFFC),
kMem_video_pixels);
if (gScreen->row_bytes < 0) {
BrFatal(
"C:\\Msdev\\Projects\\DethRace\\World.c",
1729,
"Bruce bug at line %d, file C:\\Msdev\\Projects\\DethRace\\World.c",
193);
}
the_pixelmap = DRPixelmapAllocate(
gScreen->type,
the_funk->texture_animation_data.flic_info.flic_descriptor.width,
the_funk->texture_animation_data.flic_info.flic_descriptor.height,
the_pixels,
0);
AssertFlicPixelmap(&the_funk->texture_animation_data.flic_info.flic_descriptor, the_pixelmap);
the_funk->material->colour_map = the_pixelmap;
BrMaterialUpdate(the_funk->material, 0x7FFFu);
} else {
the_funk->texture_animation_type = -1;
}
} else if (the_funk->texture_animation_type == eTexture_animation_frames) {
i = GetALineAndInterpretCommand(pF, gFunk_move_names, COUNT_OF(gFunk_move_names));
the_funk->texture_animation_data.frames_info.mode = i;
if (the_funk->texture_animation_data.frames_info.mode != eMove_controlled
&& the_funk->texture_animation_data.frames_info.mode != eMove_absolute) {
x_0 = GetAFloat(pF);
the_funk->texture_animation_data.frames_info.period = x_0 == 0.0f ? 0.0f : 1000.0 / x_0;
} else {
d_0 = GetAnInt(pF);
AddFunkGrooveBinding(d_0 + pRef_offset, &the_funk->texture_animation_data.frames_info.period);
}
the_funk->texture_animation_data.frames_info.texture_count = (int)GetAFloat(pF);
for (i = 0; i < the_funk->texture_animation_data.frames_info.texture_count; i++) {
GetAString(pF, s);
the_funk->texture_animation_data.frames_info.textures[i] = BrMapFind(s);
if (!the_funk->texture_animation_data.frames_info.textures[i]) {
FatalError(66);
}
}
}
the_funk->proximity_count = 0;
the_funk->proximity_array = 0;
if (the_funk->mode == eFunk_mode_distance) {
DRActorEnumRecurseWithMat(
gUniverse_actor,
0,
CalcProximities,
the_funk);
the_funk->proximity_array = BrMemAllocate(sizeof(br_vector3) * the_funk->proximity_count, kMem_funk_prox_array);
the_funk->proximity_count = 0;
DRActorEnumRecurseWithMat(
gUniverse_actor,
0,
AddProximities,
the_funk);
for (i = 0; i < the_funk->proximity_count; i++) {
for (j = i + 1; the_funk->proximity_count > j; ++j) {
if (the_funk->proximity_array[j].v[0] == the_funk->proximity_array[i].v[0]
&& the_funk->proximity_array[j].v[1] == the_funk->proximity_array[i].v[1]
&& the_funk->proximity_array[j].v[2] == the_funk->proximity_array[i].v[2]) {
memcpy(
&the_funk->proximity_array[j],
&the_funk->proximity_array[j + 1],
4 * (3 * (the_funk->proximity_count - j) - 3));
--j;
--the_funk->proximity_count;
}
}
}
}
}
}
// IDA: void __usercall DisposeGroovidelics(int pOwner@<EAX>)
@ -494,7 +967,28 @@ tGroovidelic_spec* AddNewGroovidelic() {
void* new_array;
int i;
LOG_TRACE("()");
NOT_IMPLEMENTED();
for (i = 0; i < gGroovidelics_array_size; i++) {
if (gGroovidelics_array[i].owner == -999) {
memset(&gGroovidelics_array[i], 0, sizeof(tGroovidelic_spec));
return &gGroovidelics_array[i];
}
}
gGroovidelics_array_size += 16;
new_array = (tGroovidelic_spec*)BrMemCalloc(gGroovidelics_array_size, 128, 221);
if (gGroovidelics_array) {
memcpy(new_array, gGroovidelics_array, (gGroovidelics_array_size - 16) * sizeof(tGroovidelic_spec));
ShiftBoundGrooveFunks(
(char*)gGroovidelics_array,
(char*)&gGroovidelics_array[gGroovidelics_array_size - 16],
(char*)new_array - (char*)gGroovidelics_array);
BrMemFree(gGroovidelics_array);
}
gGroovidelics_array = new_array;
for (i = 0; i < 16; i++) {
gGroovidelics_array[i + gGroovidelics_array_size - 16].owner = -999;
}
return &gGroovidelics_array[gGroovidelics_array_size - 16];
}
// IDA: void __usercall AddGroovidelics(FILE *pF@<EAX>, int pOwner@<EDX>, br_actor *pParent_actor@<EBX>, int pRef_offset@<ECX>, int pAllowed_to_be_absent)
@ -505,8 +999,214 @@ void AddGroovidelics(FILE* pF, int pOwner, br_actor* pParent_actor, int pRef_off
int i;
int j;
tGroovidelic_spec* the_groove;
float x_0;
float x_1;
float x_2;
int d_0;
int d_1;
int d_2;
LOG_TRACE("(%p, %d, %p, %d, %d)", pF, pOwner, pParent_actor, pRef_offset, pAllowed_to_be_absent);
NOT_IMPLEMENTED();
first_time = 1;
while (!(feof(pF))) {
PossibleService();
GetALineAndDontArgue(pF, s);
if (strcmp(s, "END OF GROOVE") == 0) {
break;
}
if (!first_time) {
if (strcmp(s, "NEXT GROOVE") != 0) {
FatalError(63);
}
GetALineAndDontArgue(pF, s);
}
first_time = 0;
str = strtok(s, "\t ,/");
the_groove = AddNewGroovidelic();
the_groove->owner = pOwner;
the_groove->actor = DRActorFindRecurse(pParent_actor, str);
if (!the_groove->actor) {
if (!pAllowed_to_be_absent && !gAusterity_mode) {
FatalError(65, str);
}
if (!gGroove_by_proxy_actor) {
gGroove_by_proxy_actor = BrActorAllocate(BR_ACTOR_MODEL, 0);
gGroove_by_proxy_actor->model = LoadModel("PROXY.DAT");
BrModelAdd(gGroove_by_proxy_actor->model);
BrActorAdd(gDont_render_actor, gGroove_by_proxy_actor);
}
the_groove->actor = gGroove_by_proxy_actor;
}
the_groove->lollipop_mode = GetALineAndInterpretCommand(pF, gLollipop_names, COUNT_OF(gLollipop_names));
the_groove->mode = GetALineAndInterpretCommand(pF, gGroove_nature_names, COUNT_OF(gGroove_nature_names));
;
the_groove->path_type = GetALineAndInterpretCommand(pF, gGroove_path_names, COUNT_OF(gGroove_path_names));
the_groove->path_interrupt_status = 0;
the_groove->object_interrupt_status = 0;
if (the_groove->path_type != -1) {
the_groove->path_mode = GetALineAndInterpretCommand(pF, gFunk_move_names, COUNT_OF(gFunk_move_names));
}
if (the_groove->path_type == eGroove_path_circular) {
TELL_ME_IF_WE_PASS_THIS_WAY();
// GetThreeFloats(pF, &v90, &v89, &v88);
// the_groove->path_data.circular_info.centre.v[0] = v90;
// the_groove->path_data.circular_info.centre.v[1] = v89;
// the_groove->path_data.circular_info.centre.v[2] = v88;
// if (the_groove->path_data.circular_info.centre.v[2] == 0.0
// && *(float*)&the_groove->path_data.circular_info.axis == 0.0
// && *((float*)&the_groove->path_data.circular_info + 6) == 0.0) {
// v25 = (_DWORD*)the_groove->actor->t.t.translate.t.v;
// v26 = (_DWORD*)&the_groove->path_data.circular_info.centre.v[2];
// *v26 = *v25;
// v26[1] = v25[1];
// v26[2] = v25[2];
// }
// if (the_groove->path_mode != 3 && the_groove->path_mode != 4) {
// v29 = GetAFloat(pF);
// x_0 = v29;
// if (v31) {
// v62 = 0.0;
// } else {
// v62 = 1000.0 / x_0;
// }
// the_groove->path_data.circular_info.period = v62;
// } else {
// v27 = &the_groove->path_data.circular_info.period;
// v28 = GetAnInt(pF);
// AddFunkGrooveBinding(v28 + pRef_offset, v27);
// }
// v32 = GetAFloat(pF);
// the_groove->path_data.circular_info.radius = v32;
// v33 = GetALineAndInterpretCommand(pF, gAxis_names, 3);
// the_groove->path_data.circular_info.axis = v33;
} else if (the_groove->path_type == eGroove_path_straight) {
GetThreeFloats(pF,
&the_groove->path_data.straight_info.centre.v[0],
&the_groove->path_data.straight_info.centre.v[1],
&the_groove->path_data.straight_info.centre.v[2]);
if (the_groove->path_data.straight_info.centre.v[0] == 0.0
&& the_groove->path_data.straight_info.centre.v[1] == 0.0
&& the_groove->path_data.straight_info.centre.v[2] == 0.0) {
the_groove->path_data.straight_info.centre.v[0] = the_groove->actor->t.t.translate.t.v[0];
the_groove->path_data.straight_info.centre.v[1] = the_groove->actor->t.t.translate.t.v[1];
the_groove->path_data.straight_info.centre.v[2] = the_groove->actor->t.t.translate.t.v[2];
}
if (the_groove->path_mode != eMove_controlled && the_groove->path_mode != eMove_absolute) {
x_0 = GetAFloat(pF);
the_groove->path_data.straight_info.period = x_0 == 0.0f ? 0.0f : 1000.0 / x_0;
} else {
i = GetAnInt(pF);
AddFunkGrooveBinding(i + pRef_offset, &the_groove->path_data.straight_info.period);
}
GetThreeFloats(
pF,
&the_groove->path_data.straight_info.x_delta,
&the_groove->path_data.straight_info.y_delta,
&the_groove->path_data.straight_info.z_delta);
}
the_groove->object_type = GetALineAndInterpretCommand(pF, gGroove_object_names, COUNT_OF(gGroove_object_names));
the_groove->object_position = the_groove->actor->t.t.translate.t;
if (the_groove->object_type != -1) {
the_groove->object_mode = GetALineAndInterpretCommand(pF, gFunk_move_names, COUNT_OF(gFunk_move_names));
}
switch (the_groove->object_type) {
case eGroove_object_spin:
if (the_groove->object_mode != eMove_controlled && the_groove->object_mode != eMove_absolute) {
x_0 = GetAFloat(pF);
the_groove->object_data.spin_info.period = x_0 == 0.0f ? 0.0f : 1000.0 / x_0;
} else {
d_0 = GetAnInt(pF);
AddFunkGrooveBinding(d_0 + pRef_offset, &the_groove->object_data.spin_info.period);
}
GetThreeFloats(pF,
&the_groove->object_centre.v[0],
&the_groove->object_centre.v[1],
&the_groove->object_centre.v[2]);
the_groove->object_data.spin_info.axis = GetALineAndInterpretCommand(pF, gAxis_names, COUNT_OF(gAxis_names));
break;
case eGroove_object_rock:
if (the_groove->object_mode != eMove_controlled && the_groove->object_mode != eMove_absolute) {
x_0 = GetAFloat(pF);
the_groove->object_data.rock_info.period = x_0 == 0.0f ? 0.0f : 1000.0 / x_0;
} else {
d_0 = GetAnInt(pF);
AddFunkGrooveBinding(d_0 + pRef_offset, &the_groove->object_data.rock_info.period);
}
GetThreeFloats(pF,
&the_groove->object_centre.v[0],
&the_groove->object_centre.v[1],
&the_groove->object_centre.v[2]);
the_groove->object_data.rock_info.axis = GetALineAndInterpretCommand(pF, gAxis_names, COUNT_OF(gAxis_names));
the_groove->object_data.rock_info.max_angle = GetAFloat(pF);
break;
case eGroove_object_throb:
if (the_groove->object_mode != eMove_controlled && the_groove->object_mode != eMove_absolute) {
GetThreeFloats(pF, &x_0, &x_1, &x_2);
the_groove->object_data.throb_info.x_period = x_0 == 0.0f ? 0.0f : 1000.0 / x_0;
the_groove->object_data.throb_info.y_period = x_1 == 0.0f ? 0.0f : 1000.0 / x_1;
the_groove->object_data.throb_info.z_period = x_2 == 0.0f ? 0.0f : 1000.0 / x_2;
} else {
GetThreeInts(pF, &d_0, &d_1, &d_2);
if (d_0 >= 0) {
AddFunkGrooveBinding(d_0 + pRef_offset, &the_groove->object_data.throb_info.x_period);
}
if (d_1 >= 0) {
AddFunkGrooveBinding(d_1 + pRef_offset, &the_groove->object_data.throb_info.y_period);
}
if (d_2 >= 0) {
AddFunkGrooveBinding(d_2 + pRef_offset, &the_groove->object_data.throb_info.z_period);
}
}
GetThreeFloats(pF,
&the_groove->object_centre.v[0],
&the_groove->object_centre.v[1],
&the_groove->object_centre.v[2]);
GetThreeFloatPercents(
pF,
&the_groove->object_data.throb_info.x_magnitude,
&the_groove->object_data.throb_info.y_magnitude,
&the_groove->object_data.throb_info.z_magnitude);
break;
case eGroove_object_shear:
if (the_groove->object_mode != eMove_controlled && the_groove->object_mode != eMove_absolute) {
GetThreeFloats(pF, &x_0, &x_1, &x_2);
the_groove->object_data.shear_info.x_period = x_0 == 0.0f ? 0.0f : 1000.0 / x_0;
the_groove->object_data.shear_info.y_period = x_1 == 0.0f ? 0.0f : 1000.0 / x_1;
the_groove->object_data.shear_info.z_period = x_2 == 0.0f ? 0.0f : 1000.0 / x_2;
} else {
GetThreeInts(pF, &d_0, &d_1, &d_2);
if (d_0 >= 0) {
AddFunkGrooveBinding(d_0 + pRef_offset, &the_groove->object_data.shear_info.x_period);
}
if (d_1 >= 0) {
AddFunkGrooveBinding(d_1 + pRef_offset, &the_groove->object_data.shear_info.y_period);
}
if (d_2 >= 0) {
AddFunkGrooveBinding(d_2 + pRef_offset, &the_groove->object_data.shear_info.z_period);
}
}
GetThreeFloats(pF,
&the_groove->object_centre.v[0],
&the_groove->object_centre.v[1],
&the_groove->object_centre.v[2]);
GetThreeFloatPercents(
pF,
&the_groove->object_data.shear_info.x_magnitude,
&the_groove->object_data.shear_info.y_magnitude,
&the_groove->object_data.shear_info.z_magnitude);
break;
default:
break;
}
}
}
// IDA: void __usercall KillGroovadelic(int pOwner@<EAX>)
@ -743,13 +1443,34 @@ void RevealStoredTextures(tBrender_storage* pStorage) {
// IDA: void __usercall SetCarStorageTexturingLevel(tBrender_storage *pStorage@<EAX>, tCar_texturing_level pNew@<EDX>, tCar_texturing_level pOld@<EBX>)
void SetCarStorageTexturingLevel(tBrender_storage* pStorage, tCar_texturing_level pNew, tCar_texturing_level pOld) {
LOG_TRACE("(%p, %d, %d)", pStorage, pNew, pOld);
NOT_IMPLEMENTED();
switch (pNew) {
case eCTL_none:
HideStoredTextures(pStorage);
break;
case eCTL_transparent:
if (pOld) {
if (pOld == 2) {
HideStoredOpaqueTextures(pStorage);
}
} else {
RevealStoredTransparentTextures(pStorage);
}
break;
case eCTL_full:
RevealStoredTextures(pStorage);
break;
default:
LOG_PANIC("not handled");
}
}
// IDA: tCar_texturing_level __cdecl GetCarTexturingLevel()
tCar_texturing_level GetCarTexturingLevel() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
return gCar_texturing_level;
}
// IDA: void __usercall SetCarTexturingLevel(tCar_texturing_level pLevel@<EAX>)
@ -916,7 +1637,7 @@ void DisposeTexturingMaterials() {
// IDA: br_uint_32 __cdecl SetAccessoryRenderingCB(br_actor *pActor, void *pFlag)
br_uint_32 SetAccessoryRenderingCB(br_actor* pActor, void* pFlag) {
if (pActor->identifier && *pActor->identifier == 38) {
if (pActor->identifier && *pActor->identifier == '&') {
pActor->render_style = *(br_uint_8*)pFlag;
}
return 0;
@ -930,9 +1651,9 @@ void SetAccessoryRendering(int pOn) {
if (gTrack_actor) {
if (pOn) {
style = 4;
style = BR_RSTYLE_FACES;
} else {
style = 1;
style = BR_RSTYLE_NONE;
}
DRActorEnumRecurse(gTrack_actor, (br_actor_enum_cbfn*)SetAccessoryRenderingCB, &style);
}

View File

@ -1,7 +1,9 @@
#ifndef CONSTANTS_H
#define CONSTANTS_H
// JeffH: These names are not part of the symbol dump, so the names in this file are not original, except as noted.
#define V11MODEL(model) (((v11model*)model->prepared))
// Jeff: These names are not part of the symbol dump, so the names in this file are not original, except as noted.
// Names from `gMem_names`. See also: `CreateStainlessClasses`
typedef enum dr_memory_classes {
@ -269,4 +271,6 @@ typedef enum keymapcodes {
#define PLAYER_NAME_MAX_LENGTH 13
#define DAMAGE_UNIT_PERIODS 5
#endif

View File

@ -932,283 +932,286 @@ typedef struct tPursuee_trail {
tU8 nodes_shifted_this_frame;
} tPursuee_trail;
typedef struct tCar_spec_struct {
int index;
int disabled;
tDriver driver;
br_actor* car_master_actor;
br_scalar min_torque_squared;
br_scalar break_off_radians_squared;
br_vector3 v;
br_vector3 old_v;
br_vector3 velocity_car_space;
br_matrix34 oldmat;
br_matrix34 old_frame_mat;
br_vector3 pos;
br_vector3 omega;
br_vector3 oldomega;
br_scalar M;
int infinite_mass;
br_vector3 I;
br_vector3 cmpos;
int extra_point_num;
br_bounds bounds[3];
br_bounds max_bounds[2];
br_vector3 extra_points[6];
br_scalar original_extra_points_z[6];
br_vector3 old_point;
br_vector3 old_norm;
int box_face_start;
int box_face_end;
int box_face_ref;
br_matrix34 last_box_inv_mat;
br_bounds last_box;
int doing_nothing_flag;
tSpecial_volume* last_special_volume;
tSpecial_volume* auto_special_volume;
int frame_collision_flag;
int collision_flag;
int max_shrapnel_material;
br_vector3 direction;
float speed;
tU16 car_ID;
br_material* shrapnel_material[3];
br_bounds bounds_world_space;
tBounds_type bounds_ws_type;
tU16 fire_vertex[12];
tU16 num_smoke_columns;
br_vector3 water_normal;
br_scalar water_d;
br_scalar water_depth_factor;
tNet_message_mechanics_info message;
tU32 last_car_car_collision;
br_scalar dt;
struct tCar_spec_struct* who_last_hit_me;
char name[32];
char driver_name[32];
char grid_icon_names[3][14];
tS8* cockpit_images[3];
br_pixelmap* prat_cam_left;
br_pixelmap* prat_cam_top;
br_pixelmap* prat_cam_right;
br_pixelmap* prat_cam_bottom;
br_pixelmap* prat_cam_dummy;
br_pixelmap* speedo_image[2];
br_pixelmap* tacho_image[2];
br_pixelmap* damage_background;
br_pixelmap* lhands_images[7];
br_pixelmap* rhands_images[7];
br_pixelmap* grid_icon_image;
br_pixelmap* gears_image;
int fg_index;
int underwater_ability;
int invulnerable;
int wall_climber_mode;
int can_be_stolen;
int has_been_stolen;
int active;
int knackered;
int pre_car_col_knackered;
int render_left[3];
int render_top[3];
int render_right[3];
int render_bottom[3];
int mirror_left;
int mirror_top;
int mirror_right;
int mirror_bottom;
int prat_left;
int prat_top;
int prat_right;
int prat_bottom;
int speedo_x[2];
int speedo_y[2];
int speedo_centre_x[2];
int speedo_centre_y[2];
int speedo_x_pitch[2];
int speedo_y_pitch[2];
int speedo_radius_1[2];
int speedo_radius_2[2];
int speedo_start_angle[2];
int speedo_end_angle[2];
int speedo_needle_colour[2];
int tacho_x[2];
int tacho_y[2];
int tacho_centre_x[2];
int tacho_centre_y[2];
int tacho_x_pitch[2];
int tacho_y_pitch[2];
int tacho_radius_1[2];
int tacho_radius_2[2];
int tacho_start_angle[2];
int tacho_end_angle[2];
int tacho_needle_colour[2];
int gear_x[2];
int gear_y[2];
int red_line;
int lhands_x[7];
int lhands_y[7];
int rhands_x[7];
int rhands_y[7];
int number_of_hands_images;
int max_speed;
int damage_x_offset;
int damage_y_offset;
int damage_background_x;
int damage_background_y;
int dim_count[2];
int dim_left[2][4];
int dim_top[2][4];
int dim_right[2][4];
int dim_bottom[2][4];
int car_actor_count;
int current_car_actor;
int principal_car_actor;
int car_model_variable;
int number_of_steerable_wheels;
int steering_ref[6];
int lf_sus_ref[4];
int rf_sus_ref[4];
int lr_sus_ref[2];
int rr_sus_ref[2];
int driven_wheels_spin_ref_1;
int driven_wheels_spin_ref_2;
int driven_wheels_spin_ref_3;
int driven_wheels_spin_ref_4;
int non_driven_wheels_spin_ref_1;
int non_driven_wheels_spin_ref_2;
int non_driven_wheels_spin_ref_3;
int non_driven_wheels_spin_ref_4;
int engine_noises[3];
float driver_x_offset;
float driver_y_offset;
float driver_z_offset;
float mirror_x_offset;
float mirror_y_offset;
float mirror_z_offset;
float rearview_camera_angle;
float head_left_angle;
float head_right_angle;
float steering_angle;
float speedo_speed;
float lf_sus_position;
float rf_sus_position;
float lr_sus_position;
float rr_sus_position;
float driven_wheels_circum;
float non_driven_wheels_circum;
float bounce_rate;
float bounce_amount;
float collision_mass_multiplier;
float damage_multiplier;
float grip_multiplier;
float engine_power_multiplier;
tDamage_unit damage_units[12];
tU8 frame_start_damage[12];
tImpact_location last_impact_location;
tDamage_program damage_programs[6];
tHeadup_slot headup_slots[2][20];
tParts_spec power_ups[3];
int car_actor_pipe_ref;
tCar_actor car_model_actors[5];
br_material* screen_material;
br_material* screen_material_source;
br_matrix34 last_safe_positions[5];
int wheel_slip;
br_scalar damping;
br_scalar sk[2];
br_scalar sb[2];
br_scalar susp_give[2];
br_scalar susp_height[2];
br_scalar ride_height;
br_vector3 wpos[4];
br_scalar curvature;
br_scalar maxcurve;
br_scalar turn_speed;
br_scalar oldd[4];
int material_index[4];
int dust_time[4];
br_scalar mu[3];
br_scalar friction_elipticity;
br_scalar down_force_speed;
int down_force_flag;
br_scalar initial_brake;
br_scalar brake_increase;
br_scalar freduction;
br_scalar acc_force;
br_scalar torque;
br_scalar brake_force;
int traction_control;
br_scalar rolling_r_front;
br_scalar rolling_r_back;
tCar_controls keys;
tJoystick joystick;
int pedals_xy;
int number_of_wheels_on_ground;
br_actor* wheel_actors[6];
float wheel_rot_pos[4];
br_scalar wheel_dam_offset[4];
br_scalar damage_magnitude_accumulator;
br_scalar revs;
br_scalar target_revs;
br_vector3 road_normal;
br_scalar max_force_front;
br_scalar max_force_rear;
int gear;
int just_changed_gear;
int max_gear;
br_scalar speed_revs_ratio;
br_scalar force_torque_ratio;
tS3_sound_source_ptr sound_source;
br_matrix34 pre_car_col_mat;
br_scalar pre_car_col_speed;
br_vector3 pre_car_col_direction;
br_vector3 pre_car_col_velocity;
br_vector3 pre_car_col_velocity_car_space;
br_vector3 velocity_bu_per_sec;
float last_col_prop_x;
float last_col_prop_y;
float last_col_prop_z;
tU32 time_last_hit;
tU32 time_last_victim;
struct tCar_spec_struct* last_hit_by;
struct tCar_spec_struct* last_culprit;
int no_of_processes_recording_my_trail;
tPursuee_trail my_trail;
unsigned int grudge_raised_recently;
unsigned int big_bang;
unsigned int scary_bang;
tU32 last_collision_time;
tU32 last_time_we_touched_a_player;
tU32 end_steering_damage_effect;
tU32 end_trans_damage_effect;
int false_key_left;
int false_key_right;
struct tCar_spec_struct* last_person_to_hit_us;
struct tCar_spec_struct* last_person_we_hit;
br_vector3 engine_pos;
br_model* last_wheel_models[4];
int last_wheel_faces[4];
tU32 shadow_intersection_flags;
tU32 last_bounce;
unsigned int new_skidding;
unsigned int old_skidding;
tU16 old_skid[4];
br_vector3 prev_skid_pos[4];
br_vector3 skid_line_start[4];
br_vector3 skid_line_end[4];
br_vector3 nor[4];
br_vector3 prev_nor[4];
br_vector3 special_start[4];
br_scalar oil_remaining[4];
br_scalar blood_remaining[4];
br_scalar total_length[4];
float proxy_ray_distance;
tS32 powerups[64];
tU32 time_to_recover;
tU32 repair_time;
int power_up_levels[3];
tS3_sound_tag horn_sound_tag;
typedef struct tCar_spec_struct { // size: 0x1a9c
int index; // @0x0
int disabled; // @0x4
tDriver driver; // @0x8
br_actor* car_master_actor; // @0xc
br_scalar min_torque_squared; // @0x10
br_scalar break_off_radians_squared; // @0x14
br_vector3 v; // @0x18
br_vector3 old_v; // @0x24
br_vector3 velocity_car_space; // @0x30
br_matrix34 oldmat; // @0x3c
br_matrix34 old_frame_mat; // @0x6c
br_vector3 pos; // @0x9c
br_vector3 omega; // @0xa8
br_vector3 oldomega; // @0xb4
br_scalar M; // @0xc0
int infinite_mass; // @0xc4
br_vector3 I; // @0xc8
br_vector3 cmpos; // @0xd4
int extra_point_num; // @0xe0
br_bounds bounds[3]; // @0xe4
br_bounds max_bounds[2]; // @0x12c
br_vector3 extra_points[6]; // @0x15c
br_scalar original_extra_points_z[6]; // @0x1a4
br_vector3 old_point; // @0x1bc
br_vector3 old_norm; // @0x1c8
int box_face_start; // @0x1d4
int box_face_end; // @0x1d8
int box_face_ref; // @0x1dc
br_matrix34 last_box_inv_mat; // @0x1e0
br_bounds last_box; // @0x210
int doing_nothing_flag; // @0x228
tSpecial_volume* last_special_volume; // @0x22c
tSpecial_volume* auto_special_volume; // @0x230
int frame_collision_flag; // @0x234
int collision_flag; // @0x238
int max_shrapnel_material; // @0x23c
br_vector3 direction; // @0x240
float speed; // @0x24c
tU16 car_ID; // @0x250
br_material* shrapnel_material[3]; // @0x254
br_bounds bounds_world_space; // @0x260
tBounds_type bounds_ws_type; // @0x278
tU16 fire_vertex[12]; // @0x27c
tU16 num_smoke_columns; // @0x294
br_vector3 water_normal; // @0x298
br_scalar water_d; // @0x2a4
br_scalar water_depth_factor; // @0x2a8
tNet_message_mechanics_info message; // @0x2ac
tU32 last_car_car_collision; // @0x330
br_scalar dt; // @0x334
tCar_spec* who_last_hit_me; // @0x338
char name[32]; // @0x33c
char driver_name[32]; // @0x35c
char grid_icon_names[3][14]; // @0x37c
tS8* cockpit_images[3]; // @0x3a8
br_pixelmap* prat_cam_left; // @0x3b4
br_pixelmap* prat_cam_top; // @0x3b8
br_pixelmap* prat_cam_right; // @0x3bc
br_pixelmap* prat_cam_bottom; // @0x3c0
br_pixelmap* prat_cam_dummy; // @0x3c4
br_pixelmap* speedo_image[2]; // @0x3c8
br_pixelmap* tacho_image[2]; // @0x3d0
br_pixelmap* damage_background; // @0x3d8
br_pixelmap* lhands_images[7]; // @0x3dc
br_pixelmap* rhands_images[7]; // @0x3f8
br_pixelmap* grid_icon_image; // @0x414
br_pixelmap* gears_image; // @0x418
int fg_index; // @0x41c
int underwater_ability; // @0x420
int invulnerable; // @0x424
int wall_climber_mode; // @0x428
int can_be_stolen; // @0x42c
int has_been_stolen; // @0x430
int active; // @0x434
int knackered; // @0x438
int pre_car_col_knackered; // @0x43c
int render_left[3]; // @0x440
int render_top[3]; // @0x44c
int render_right[3]; // @0x458
int render_bottom[3]; // @0x464
int mirror_left; // @0x470
int mirror_top; // @0x474
int mirror_right; // @0x478
int mirror_bottom; // @0x47c
int prat_left; // @0x480
int prat_top; // @0x484
int prat_right; // @0x488
int prat_bottom; // @0x48c
int speedo_x[2]; // @0x490
int speedo_y[2]; // @0x498
int speedo_centre_x[2]; // @0x4a0
int speedo_centre_y[2]; // @0x4a8
int speedo_x_pitch[2]; // @0x4b0
int speedo_y_pitch[2]; // @0x4b8
int speedo_radius_1[2]; // @0x4c0
int speedo_radius_2[2]; // @0x4c8
int speedo_start_angle[2]; // @0x4d0
int speedo_end_angle[2]; // @0x4d8
int speedo_needle_colour[2]; // @0x4e0
int tacho_x[2]; // @0x4e8
int tacho_y[2]; // @0x4f0
int tacho_centre_x[2]; // @0x4f8
int tacho_centre_y[2]; // @0x500
int tacho_x_pitch[2]; // @0x508
int tacho_y_pitch[2]; // @0x510
int tacho_radius_1[2]; // @0x518
int tacho_radius_2[2]; // @0x520
int tacho_start_angle[2]; // @0x528
int tacho_end_angle[2]; // @0x530
int tacho_needle_colour[2]; // @0x538
int gear_x[2]; // @0x540
int gear_y[2]; // @0x548
int red_line; // @0x550
int lhands_x[7]; // @0x554
int lhands_y[7]; // @0x570
int rhands_x[7]; // @0x58c
int rhands_y[7]; // @0x5a8
int number_of_hands_images; // @0x5c4
int max_speed; // @0x5c8
int damage_x_offset; // @0x5cc
int damage_y_offset; // @0x5d0
int damage_background_x; // @0x5d4
int damage_background_y; // @0x5d8
int dim_count[2]; // @0x5dc
int dim_left[2][4]; // @0x5e4
int dim_top[2][4]; // @0x604
int dim_right[2][4]; // @0x624
int dim_bottom[2][4]; // @0x644
int car_actor_count; // @0x664
int current_car_actor; // @0x668
int principal_car_actor; // @0x66c
int car_model_variable; // @0x670
int number_of_steerable_wheels; // @0x674
int steering_ref[6]; // @0x678
int lf_sus_ref[4]; // @0x690
int rf_sus_ref[4]; // @0x6a0
int lr_sus_ref[2]; // @0x6b0
int rr_sus_ref[2]; // @0x6b8
int driven_wheels_spin_ref_1; // @0x6c0
int driven_wheels_spin_ref_2; // @0x6c4
int driven_wheels_spin_ref_3; // @0x6c8
int driven_wheels_spin_ref_4; // @0x6cc
int non_driven_wheels_spin_ref_1; // @0x6d0
int non_driven_wheels_spin_ref_2; // @0x6d4
int non_driven_wheels_spin_ref_3; // @0x6d8
int non_driven_wheels_spin_ref_4; // @0x6dc
int engine_noises[3]; // @0x6e0
float driver_x_offset; // @0x6ec
float driver_y_offset; // @0x6f0
float driver_z_offset; // @0x6f4
float mirror_x_offset; // @0x6f8
float mirror_y_offset; // @0x6fc
float mirror_z_offset; // @0x700
float rearview_camera_angle; // @0x704
float head_left_angle; // @0x708
float head_right_angle; // @0x70c
float steering_angle; // @0x710
float speedo_speed; // @0x714
float lf_sus_position; // @0x718
float rf_sus_position; // @0x71c
float lr_sus_position; // @0x720
float rr_sus_position; // @0x724
float driven_wheels_circum; // @0x728
float non_driven_wheels_circum; // @0x72c
float bounce_rate; // @0x730
float bounce_amount; // @0x734
float collision_mass_multiplier; // @0x738
float damage_multiplier; // @0x73c
float grip_multiplier; // @0x740
float engine_power_multiplier; // @0x744
tDamage_unit damage_units[12]; // @0x748
tU8 frame_start_damage[12]; // @0x958
tImpact_location last_impact_location; // @0x964
tDamage_program damage_programs[6]; // @0x968
tHeadup_slot headup_slots[2][20]; // @0x998
tParts_spec power_ups[3]; // @0xfd8
int car_actor_pipe_ref; // @0x12b4
tCar_actor car_model_actors[5]; // @0x12b8
br_material* screen_material; // @0x13a8
br_material* screen_material_source; // @0x13ac
br_matrix34 last_safe_positions[5]; // @0x13b0
int wheel_slip; // @0x14a0
br_scalar damping; // @0x14a4
br_scalar sk[2]; // @0x14a8
br_scalar sb[2]; // @0x14b0
br_scalar susp_give[2]; // @0x14b8
br_scalar susp_height[2]; // @0x14c0
br_scalar ride_height; // @0x14c8
br_vector3 wpos[4]; // @0x14cc
br_scalar curvature; // @0x14fc
br_scalar maxcurve; // @0x1500
br_scalar turn_speed; // @0x1504
br_scalar oldd[4]; // @0x1508
int material_index[4]; // @0x1518
int dust_time[4]; // @0x1528
br_scalar mu[3]; // @0x1538
br_scalar friction_elipticity; // @0x1544
br_scalar down_force_speed; // @0x1548
int down_force_flag; // @0x154c
br_scalar initial_brake; // @0x1550
br_scalar brake_increase; // @0x1554
br_scalar freduction; // @0x1558
br_scalar acc_force; // @0x155c
br_scalar torque; // @0x1560
br_scalar brake_force; // @0x1564
int traction_control; // @0x1568
br_scalar rolling_r_front; // @0x156c
br_scalar rolling_r_back; // @0x1570
tCar_controls keys; // @0x1574
tJoystick joystick; // @0x1578
int pedals_xy; // @0x1588
int number_of_wheels_on_ground; // @0x158c
br_actor* wheel_actors[6]; // @0x1590
float wheel_rot_pos[4]; // @0x15a8
br_scalar wheel_dam_offset[4]; // @0x15b8
br_scalar damage_magnitude_accumulator; // @0x15c8
br_scalar revs; // @0x15cc
br_scalar target_revs; // @0x15d0
br_vector3 road_normal; // @0x15d4
br_scalar max_force_front; // @0x15e0
br_scalar max_force_rear; // @0x15e4
int gear; // @0x15e8
int just_changed_gear; // @0x15ec
int max_gear; // @0x15f0
br_scalar speed_revs_ratio; // @0x15f4
br_scalar force_torque_ratio; // @0x15f8
tS3_sound_source_ptr sound_source; // @0x15fc
br_matrix34 pre_car_col_mat; // @0x1600
br_scalar pre_car_col_speed; // @0x1630
br_vector3 pre_car_col_direction; // @0x1634
br_vector3 pre_car_col_velocity; // @0x1640
br_vector3 pre_car_col_velocity_car_space; // @0x164c
br_vector3 velocity_bu_per_sec; // @0x1658
float last_col_prop_x; // @0x1664
float last_col_prop_y; // @0x1668
float last_col_prop_z; // @0x166c
tU32 time_last_hit; // @0x1670
tU32 time_last_victim; // @0x1674
struct tCar_spec_struct* last_hit_by; // @0x1678
struct tCar_spec_struct* last_culprit; // @0x167c
int no_of_processes_recording_my_trail; // @0x1680
tPursuee_trail my_trail; // @0x1684
// unsigned int grudge_raised_recently : 0; // @0x17c8
// unsigned int big_bang : 1; // @0x17c8
// unsigned int scary_bang : 2; // @0x17c8
unsigned int grudge_bang_scary_bang; // TODO: should use the above bit fields...
tU32 last_collision_time; // @0x17cc
tU32 last_time_we_touched_a_player; // @0x17d0
tU32 end_steering_damage_effect; // @0x17d4
tU32 end_trans_damage_effect; // @0x17d8
int false_key_left; // @0x17dc
int false_key_right; // @0x17e0
tCar_spec* last_person_to_hit_us; // @0x17e4
tCar_spec* last_person_we_hit; // @0x17e8
br_vector3 engine_pos; // @0x17ec
br_model* last_wheel_models[4]; // @0x17f8
int last_wheel_faces[4]; // @0x1808
tU32 shadow_intersection_flags; // @0x1818
tU32 last_bounce; // @0x181c
unsigned int new_skidding; // @0x1820
unsigned int old_skidding; // @0x1824
tU16 old_skid[4]; // @0x1828
br_vector3 prev_skid_pos[4]; // @0x1830
br_vector3 skid_line_start[4]; // @0x1860
br_vector3 skid_line_end[4]; // @0x1890
br_vector3 nor[4]; // @0x18c0
br_vector3 prev_nor[4]; // @0x18f0
br_vector3 special_start[4]; // @0x1920
br_scalar oil_remaining[4]; // @0x1950
br_scalar blood_remaining[4]; // @0x1960
br_scalar total_length[4]; // @0x1970
float proxy_ray_distance; // @0x1980
tS32 powerups[64]; // @0x1984
tU32 time_to_recover; // @0x1a84
tU32 repair_time; // @0x1a88
int power_up_levels[3]; // @0x1a8c
tS3_sound_tag horn_sound_tag; // @0x1a98
} tCar_spec;
typedef struct tOppo_psyche {

View File

@ -7,17 +7,6 @@
extern int original_main(int pArgc, char* pArgv[]);
int main(int argc, char* argv[]) {
int result;
char* root_dir = getenv("DETHRACE_ROOT_DIR");
if (!root_dir) {
LOG_PANIC("DETHRACE_ROOT_DIR is not set");
}
printf("DETHRACE_ROOT_DIR: %s\n", root_dir);
result = chdir(root_dir);
if (result != 0) {
LOG_PANIC("Failed to chdir. Returned %d", result);
}
Harness_Init(argv[0], &OpenGLRenderer);

View File

@ -258,6 +258,8 @@ void PDFatalError(char* pThe_str) {
// wait for keypress
Harness_Debug_PrintStack();
DoSaveGame(1);
if (!_unittest_do_not_exit) {
exit(1);
@ -845,7 +847,7 @@ int PDCheckDriveExists2(char* pThe_path, char* pFile_name, tU32 pMin_size) {
strcpy(the_path, pThe_path);
}
// JeffH: force unix dir separator >>
// Jeff: force unix dir separator >>
char* rep = the_path;
while ((rep = strchr(rep, '\\')) != NULL) {
*rep++ = '/';

View File

@ -5,21 +5,20 @@
#include <unistd.h>
#define BLUE
#define LOG_LEVEL 3
#define LOG_TRACE(...) debug_printf("[TRACE] %s", __FUNCTION__, __VA_ARGS__)
#define LOG_TRACE10(...) \
if (LOG_LEVEL >= 10) { \
if (harness_debug_level >= 10) { \
debug_printf("[TRACE] %s", __FUNCTION__, __VA_ARGS__); \
}
#define LOG_TRACE9(...) \
if (LOG_LEVEL >= 9) { \
if (harness_debug_level >= 9) { \
debug_printf("[TRACE] %s", __FUNCTION__, __VA_ARGS__); \
}
#define LOG_TRACE8(...) \
if (LOG_LEVEL >= 8) { \
if (harness_debug_level >= 8) { \
debug_printf("[TRACE] %s", __FUNCTION__, __VA_ARGS__); \
}
@ -35,6 +34,10 @@
sleep(2); \
exit(1);
#define TELL_ME_IF_WE_PASS_THIS_WAY() \
debug_printf("\033[0;31m[PANIC] %s ", __FUNCTION__, "%s", "code path not expected"); \
exit(1);
#define STUB() \
debug_printf("\033[0;31m[WARN] %s ", __FUNCTION__, "%s", "stubbed");

View File

@ -6,15 +6,17 @@
#include <sys/stat.h>
SDL_Window* window;
renderer* current_renderer;
tRenderer* current_renderer;
br_pixelmap* palette;
uint32_t* screen_buffer;
br_pixelmap* last_dst = NULL;
br_pixelmap* last_src = NULL;
// if not 0, enable the original CD check code, otherwise just skip
int harness_enable_cd_check;
// if true, disable the original CD check code
int harness_disable_cd_check = 1;
int harness_debug_level = 7;
// SplatPack or Carmageddon. This is where we represent the code differences between the two. For example, the intro smack file.
tHarness_GameMode harness_game_mode;
@ -30,7 +32,9 @@ void Harness_DetectGameMode() {
LOG_INFO("\"%s\"", harness_game_mode.name);
}
void Harness_Init(char* name, renderer* renderer) {
void Harness_Init(char* name, tRenderer* renderer) {
int result;
install_signal_handler(name);
current_renderer = renderer;
screen_buffer = NULL;
@ -39,9 +43,26 @@ void Harness_Init(char* name, renderer* renderer) {
LOG_PANIC("SDL_INIT_TIMER error: %s", SDL_GetError());
}
char* root_dir = getenv("DETHRACE_ROOT_DIR");
if (!root_dir) {
LOG_INFO("DETHRACE_ROOT_DIR is not set, assuming '.'");
} else {
printf("DETHRACE_ROOT_DIR: %s\n", root_dir);
result = chdir(root_dir);
if (result != 0) {
LOG_PANIC("Failed to chdir. Returned %d", result);
}
}
Harness_DetectGameMode();
}
void Harness_Debug_PrintStack() {
#ifndef _WIN32
posix_print_stack_trace();
#endif
}
void Harness_PumpEvents() {
SDL_Event event;
@ -62,7 +83,12 @@ void Harness_PumpEvents() {
int Harness_Hook_HandleCommandLineArg(char* arg) {
if (strcasecmp(arg, "-cdcheck") == 0) {
harness_enable_cd_check = 1;
harness_disable_cd_check = 0;
return 1;
} else if (strstr(arg, "-debug=") != NULL) {
char* s = strstr(arg, "=");
harness_debug_level = atoi(s + 1);
LOG_INFO("debug level set to %d", harness_debug_level);
return 1;
}
return 0;

View File

@ -5,11 +5,13 @@
#include "debug.h"
#include <SDL2/SDL.h>
typedef struct renderer {
#define COUNT_OF(array) (sizeof((array)) / sizeof((array)[0]))
typedef struct tRenderer {
int (*get_window_flags)();
void (*init)(SDL_Window* window);
void (*doubleBuffer)(uint32_t* src, SDL_Window* window);
} renderer;
} tRenderer;
typedef struct tHarness_GameMode {
char* name;
@ -17,9 +19,12 @@ typedef struct tHarness_GameMode {
} tHarness_GameMode;
extern tHarness_GameMode harness_game_mode;
extern int harness_enable_cd_check;
extern int harness_disable_cd_check;
extern int harness_debug_level;
void Harness_Init(char* name, renderer* renderer);
void Harness_Init(char* name, tRenderer* renderer);
void Harness_Debug_PrintStack();
// Hooks are called from original game code.
int Harness_Hook_HandleCommandLineArg(char* arg);

View File

@ -12,7 +12,7 @@
#endif
#include <SDL2/SDL_opengl.h>
renderer OpenGLRenderer = {
tRenderer OpenGLRenderer = {
Harness_GLRenderer_GetWindowFlags,
Harness_GLRenderer_Init,
Harness_GLRenderer_DoubleBuffer,

View File

@ -4,7 +4,7 @@
#include "harness.h"
#include <SDL2/SDL.h>
extern renderer OpenGLRenderer;
extern tRenderer OpenGLRenderer;
int Harness_GLRenderer_GetWindowFlags();
void Harness_GLRenderer_Init(SDL_Window* window);

View File

@ -7,7 +7,7 @@ void Harness_NullRenderer_Init(SDL_Window* window) {}
void Harness_NullRenderer_Activate(SDL_Window* window) {}
void Harness_NullRenderer_DoubleBuffer(uint32_t* src, SDL_Window* window) {}
renderer NullRenderer = {
tRenderer NullRenderer = {
Harness_NullRenderer_GetWindowFlags,
Harness_NullRenderer_Init,
Harness_NullRenderer_DoubleBuffer

View File

@ -3,6 +3,6 @@
#include "harness.h"
extern renderer NullRenderer;
extern tRenderer NullRenderer;
#endif

View File

@ -282,6 +282,7 @@ void resolve_full_path(char* path, const char* argv0) {
void install_signal_handler(char* program_name) {
resolve_full_path(_program_name, program_name);
printf("fill path %s\n", _program_name);
/* setup alternate stack */
{

View File

@ -3,6 +3,7 @@
#include "CORE/PIXELMAP/pmfile.h"
#include "CORE/V1DB/actsupt.h"
#include "CORE/V1DB/modsupt.h"
#include "CORE/V1DB/prepmesh.h"
#include "CORE/V1DB/regsupt.h"
#include "CORE/V1DB/v1dbfile.h"

View File

@ -5,7 +5,6 @@
#include <string.h>
void test_errors_FatalError() {
_unittest_do_not_exit = 1;
FatalError(0x6b, "test_errors", "FATAL");
TEST_ASSERT_EQUAL_STRING("Can't open 'test_errors'", _unittest_last_fatal_error);
}

View File

@ -1,12 +1,9 @@
#include "tests.h"
#include "CORE/V1DB/actsupt.h"
#include "common/globvars.h"
#include "common/init.h"
void test_init_AllocateCamera() {
gSelf = BrActorAllocate(BR_ACTOR_NONE, NULL);
gUniverse_actor = BrActorAllocate(BR_ACTOR_NONE, NULL);
AllocateCamera();
TEST_ASSERT_NOT_NULL(gRearview_camera);
}

View File

@ -3,10 +3,14 @@
#include <string.h>
#include <unistd.h>
#include "CORE/PIXELMAP/pixelmap.h"
#include "common/globvars.h"
#include "common/graphics.h"
#include "common/init.h"
#include "common/loading.h"
#include "common/newgame.h"
#include "common/utility.h"
#include "common/world.h"
void test_loading_GetCDPathFromPathsTxtFile() {
REQUIRES_DATA_DIRECTORY();
@ -37,7 +41,7 @@ void test_loading_LoadGeneralParameters() {
TEST_ASSERT_EQUAL_INT(7500, gInitial_credits[0]);
TEST_ASSERT_EQUAL_INT(5000, gInitial_credits[1]);
TEST_ASSERT_EQUAL_INT(3000, gInitial_credits[2]);
TEST_ASSERT_EQUAL_STRING("BLKEAGLE.TXT", gBasic_car_names[0]);
TEST_ASSERT_EQUAL_STRING("NEWEAGLE.TXT", gBasic_car_names[0]);
TEST_ASSERT_EQUAL_FLOAT(0.2f, gDefault_default_water_spec_vol.gravity_multiplier);
TEST_ASSERT_EQUAL_FLOAT(50.0f, gDefault_default_water_spec_vol.viscosity_multiplier);
@ -65,14 +69,14 @@ void test_loading_opponents() {
LoadOpponents();
TEST_ASSERT_EQUAL_INT(40, gNumber_of_racers);
o = &gOpponents[2];
TEST_ASSERT_EQUAL_STRING("Agent Orange", o->name);
TEST_ASSERT_EQUAL_STRING("Orange", o->abbrev_name);
TEST_ASSERT_EQUAL_INT(12, o->car_number);
TEST_ASSERT_EQUAL_STRING("Sinthea", o->name);
TEST_ASSERT_EQUAL_STRING("Sinthea", o->abbrev_name);
TEST_ASSERT_EQUAL_INT(73, o->car_number);
TEST_ASSERT_EQUAL_INT(4, o->strength_rating);
TEST_ASSERT_EQUAL_INT(eNet_avail_never, o->network_availability);
TEST_ASSERT_EQUAL_STRING("LEADPUMP.FLI", o->mug_shot_name);
TEST_ASSERT_EQUAL_STRING("AGENTO.TXT", o->car_file_name);
TEST_ASSERT_EQUAL_STRING("AGENTO.FLI", o->stolen_car_flic_name);
TEST_ASSERT_EQUAL_STRING("SINTHMUG.FLI", o->mug_shot_name);
TEST_ASSERT_EQUAL_STRING("SLED.TXT", o->car_file_name);
TEST_ASSERT_EQUAL_STRING("SLED.FLI", o->stolen_car_flic_name);
TEST_ASSERT_EQUAL_INT(2, o->text_chunk_count);
TEST_ASSERT_EQUAL_INT(5, o->text_chunks[0].x_coord);
TEST_ASSERT_EQUAL_INT(3, o->text_chunks[0].y_coord);
@ -111,6 +115,109 @@ void test_loading_memread() {
TEST_ASSERT_EQUAL_INT(-4, MemReadS8(&data));
}
void test_loading_ConvertPixToStripMap() {
REQUIRES_DATA_DIRECTORY();
br_pixelmap* pm;
tS8* strip_data;
br_pixelmap* pm_unstripped;
int x;
int y;
br_uint_8* src_pix;
br_uint_8* dst_pix;
pm = DRPixelmapLoad("DATA/32x20x8/PIXELMAP/FRANKF.PIX");
TEST_ASSERT_NOT_NULL(pm);
strip_data = ConvertPixToStripMap(pm);
TEST_ASSERT_NOT_NULL(strip_data);
pm_unstripped = BrPixelmapAllocate(BR_MEMORY_PIXELS, pm->width, pm->height, NULL, BR_PMAF_NORMAL);
CopyStripImage(pm_unstripped, 0, 0, 0, 0, strip_data, 0, 0, pm->width, pm->height);
src_pix = (br_uint_8*)pm->pixels;
dst_pix = (br_uint_8*)pm_unstripped->pixels;
for (y = 0; y < pm->height; y++) {
for (x = 0; x < pm->width; x++) {
if (src_pix[y * pm->row_bytes + x] != dst_pix[y * pm_unstripped->row_bytes + x]) {
printf("Original and unstripped images do not match at (%d %d)\n", x, y);
TEST_FAIL();
}
}
}
}
void test_loading_LoadCar() {
REQUIRES_DATA_DIRECTORY();
tCar_spec car_spec;
tBrender_storage storage;
InitialiseStorageSpace(&storage, 50, 50, 50, 50);
LoadCar("NEWEAGLE.TXT", eDriver_local_human, &car_spec, eFrankie, "playerName", &storage);
TEST_ASSERT_TRUE(car_spec.active);
TEST_ASSERT_FALSE(car_spec.disabled);
br_model* model = car_spec.car_model_actors[car_spec.principal_car_actor].actor->model;
TEST_ASSERT_EQUAL_STRING("NEWEAGLE.DAT", model->identifier);
TEST_ASSERT_EQUAL_FLOAT(1.0, car_spec.M);
float e_cmpos[] = { 0, 0.345, 0 };
TEST_ASSERT_EQUAL_FLOAT_ARRAY(e_cmpos, car_spec.cmpos.v, 3);
TEST_ASSERT_EQUAL_INT(2, car_spec.number_of_steerable_wheels);
TEST_ASSERT_EQUAL_INT(7, car_spec.steering_ref[0]);
TEST_ASSERT_EQUAL_INT(8, car_spec.steering_ref[1]);
TEST_ASSERT_EQUAL_INT(-1, car_spec.driven_wheels_spin_ref_1);
TEST_ASSERT_EQUAL_INT(-1, car_spec.driven_wheels_spin_ref_2);
TEST_ASSERT_EQUAL_INT(2, car_spec.driven_wheels_spin_ref_3);
TEST_ASSERT_EQUAL_INT(1, car_spec.driven_wheels_spin_ref_4);
TEST_ASSERT_EQUAL_FLOAT(36.231884, car_spec.sk[0]);
TEST_ASSERT_EQUAL_FLOAT(36.231884, car_spec.sk[1]);
TEST_ASSERT_EQUAL_FLOAT(4.2562828, car_spec.sb[0]);
TEST_ASSERT_EQUAL_FLOAT(4.2562828, car_spec.sb[1]);
TEST_ASSERT_EQUAL_FLOAT(0.41400003, car_spec.ride_height);
TEST_ASSERT_EQUAL_FLOAT(2.1244245, car_spec.mu[0]);
TEST_ASSERT_EQUAL_FLOAT(2.2325289, car_spec.mu[1]);
TEST_ASSERT_EQUAL_FLOAT(2.3518364, car_spec.mu[2]);
TEST_ASSERT_NOT_NULL(car_spec.car_model_actors[0].actor->model);
// Test prepared mesh creation
TEST_ASSERT_EQUAL_INT(17, V11MODEL(model)->ngroups);
int found_test_prep_group = 0;
for (int i = 0; i < V11MODEL(model)->ngroups; i++) {
if (V11MODEL(model)->groups[i].nfaces == 47) {
found_test_prep_group = 1;
TEST_ASSERT_EQUAL_INT(99, V11MODEL(model)->groups[i].nvertices);
TEST_ASSERT_EQUAL_FLOAT(-0.0844900012, V11MODEL(model)->groups[i].vertices[0].p.v[0]);
TEST_ASSERT_EQUAL_FLOAT(0.0440330058, V11MODEL(model)->groups[i].vertices[0].p.v[1]);
TEST_ASSERT_EQUAL_FLOAT(0.1230980009, V11MODEL(model)->groups[i].vertices[0].p.v[2]);
TEST_ASSERT_EQUAL_FLOAT(1.0, V11MODEL(model)->groups[i].vertices[0].map.v[0]);
TEST_ASSERT_EQUAL_FLOAT(0.664765000, V11MODEL(model)->groups[i].vertices[0].map.v[1]);
TEST_ASSERT_EQUAL_FLOAT(-0.0071384655, V11MODEL(model)->groups[i].vertices[0].n.v[0]);
TEST_ASSERT_EQUAL_FLOAT(0.9597771764, V11MODEL(model)->groups[i].vertices[0].n.v[1]);
TEST_ASSERT_EQUAL_FLOAT(-0.2806721628, V11MODEL(model)->groups[i].vertices[0].n.v[2]);
break;
}
}
if (!found_test_prep_group) {
TEST_FAIL_MESSAGE("expected prep group not found");
}
// for (int i = 0; i < V11MODEL(model)->ngroups; i++) {
// printf("group %d, nfaces=%d, verts=%d\n", i, V11MODEL(model)->groups[i].nfaces, V11MODEL(model)->groups[i].nvertices);
// for (int j = 0; j < V11MODEL(model)->groups[i].nvertices; j++) {
// printf("(%.10f %.10f %.10f), (%.9f %.9f), (%.10f %.10f %.10f)\n",
// V11MODEL(model)->groups[i].vertices[j].p.v[j], V11MODEL(model)->groups[i].vertices[j].p.v[1], V11MODEL(model)->groups[i].vertices[j].p.v[2],
// V11MODEL(model)->groups[i].vertices[j].map.v[j], V11MODEL(model)->groups[i].vertices[j].map.v[1],
// V11MODEL(model)->groups[i].vertices[j].n.v[j], V11MODEL(model)->groups[i].vertices[j].n.v[1], V11MODEL(model)->groups[i].vertices[j].n.v[2]);
// }
// }
// for (int j = 0; j < V11MODEL(model)->groups[i].nfaces; j++) {
// printf("(%d %d %d)\n", V11MODEL(model)->groups[i].faces[j].vertices[0], V11MODEL(model)->groups[i].faces[j].vertices[1], V11MODEL(model)->groups[i].faces[j].vertices[2]);
// }
}
void test_loading_suite() {
RUN_TEST(test_loading_GetCDPathFromPathsTxtFile);
RUN_TEST(test_loading_OldDRfopen);
@ -118,4 +225,6 @@ void test_loading_suite() {
RUN_TEST(test_loading_brfont);
RUN_TEST(test_loading_opponents);
RUN_TEST(test_loading_memread);
RUN_TEST(test_loading_ConvertPixToStripMap);
RUN_TEST(test_loading_LoadCar);
}

View File

@ -10,7 +10,7 @@ void test_loading_powerups() {
REQUIRES_DATA_DIRECTORY();
LoadPowerups();
TEST_ASSERT_EQUAL_INT(46, gNumber_of_powerups);
TEST_ASSERT_EQUAL_INT(51, gNumber_of_powerups);
}
void test_powerup_suite() {

View File

@ -9,10 +9,15 @@
#include "framework/unity.h"
#include "CORE/PIXELMAP/pixelmap.h"
#include "CORE/V1DB/actsupt.h"
#include "CORE/V1DB/dbsetup.h"
#include "common/newgame.h"
#include "common/utility.h"
#include "common/drmem.h"
#include "common/globvars.h"
#include "common/grafdata.h"
#include "harness.h"
#include "renderers/null_renderer.h"
@ -20,6 +25,8 @@
#define debug(format_, ...) fprintf(stderr, format_, __VA_ARGS__)
extern int _unittest_do_not_exit;
extern void test_utility_suite();
extern void test_loading_suite();
extern void test_controls_suite();
@ -64,6 +71,22 @@ void setup_global_vars() {
printf("WARN: DETHRACE_ROOT_DIR is not defined. Skipping tests which require it\n");
strcpy(gApplication_path, ".");
}
BrV1dbBeginWrapper_Float();
CreateStainlessClasses();
gCurrent_graf_data = &gGraf_data[0];
gGraf_data_index = 0;
gGraf_spec_index = 0;
gRender_screen = BrPixelmapAllocate(BR_PMT_INDEX_8, 320, 200, NULL, 0);
gSelf = BrActorAllocate(BR_ACTOR_NONE, NULL);
gUniverse_actor = BrActorAllocate(BR_ACTOR_NONE, NULL);
strcpy(gBasic_car_names[0], "BLKEAGLE.TXT");
_unittest_do_not_exit = 1;
harness_debug_level = 7;
}
int has_data_directory() {
@ -78,12 +101,10 @@ int main(int argc, char** argv) {
exit(1);
}
Harness_Init("tests", &NullRenderer);
Harness_Init(argv[0], &NullRenderer);
setup_global_vars();
BrV1dbBeginWrapper_Float();
printf("Completed setup\n");
// BRSRC13

View File

@ -45,6 +45,9 @@ STATE_MODULE = 1
STATE_LOCALS = 2
STATE_TYPES = 3
LOCALVAR_SCOPE_FUNCTION = 0
LOCALVAR_SCOPE_BLOCK = 1
INDENT_SPACES = 4
modules = []
@ -58,6 +61,8 @@ eof = 0
generated_type_names = {}
indent = 0
localvar_scope = LOCALVAR_SCOPE_FUNCTION
dr_types_file = {}
br_types_file = {}
@ -84,6 +89,8 @@ def unread_line():
def read_file():
state = STATE_NONE
current_module = None
# list of blocks each containing a list of vars scoped to that block. Always local to a function.
block_scopes = []
while eof == 0:
line = read_line()
@ -130,17 +137,20 @@ def read_file():
elif local_type == 'NEAR_RTN_386' or local_type == 'FAR_RTN_386':
fn = process_function(current_module)
fn['block_scopes'] = block_scopes.copy()
last_fn = fn
current_module['functions'].append(fn)
localvar_scope = LOCALVAR_SCOPE_FUNCTION
block_scopes = []
elif local_type == 'LOCAL':
if last_fn is not None:
if localvar_scope == LOCALVAR_SCOPE_FUNCTION:
local_var = process_function_var()
last_fn['local_vars'].append(local_var)
else:
# TODO: ignore block_386 scoped local variables for now
# Maybe indicates asm { ... } usage?
local_var = process_function_var()
elif localvar_scope == LOCALVAR_SCOPE_BLOCK:
block_var = process_function_var()
block_scopes[-1].append(block_var)
#print('block_scope', block_var)
elif local_type == 'SET_BASE_386':
last_local_type = local_type
@ -149,7 +159,8 @@ def read_file():
elif local_type == 'BLOCK_386':
read_line()
last_fn = None
localvar_scope = LOCALVAR_SCOPE_BLOCK
block_scopes.append([])
else:
print('Line ', line_number, 'Unknown local type', local_type)
@ -337,13 +348,9 @@ def resolve_type_str(module, type_idx, var_name, decl=True):
t = module['types'][t['base_type']]
if t['type'] == 'NEAR386 PROC' or t['type'] == 'FAR386 PROC':
print (var_name, 'IS PROC')
return_type = resolve_type_str(module, t['return_type'], '')
#print 'rt', return_type
a = describe_args(module, t, False)
print(var_name, 'a', a)
# print 'i', indirections
# print 'b', bounds
s = return_type + ' (' + indirections + var_name + bounds + ')(' + a + ')'
return s
if decl == True and t['type'] == 'FIELD_LIST':
@ -497,12 +504,10 @@ def get_struct_name(module, t):
for i in module['types']:
t2 = module['types'][i]
if 'type_idx' in t2 and t2['type_idx'] == target_id:
print ('t2', t2)
if t2['scope_idx'] == '0':
return t2['value']
found_id = t2['id']
found_name = t2['value']
print ('found1', t2['value'])
if found_id is None:
print ('ERROR1: not found', t)
return None
@ -640,8 +645,8 @@ def generate_c_file(module):
# global variables
for gv in module['global_vars']:
# print('gv:', gv)
str = resolve_type_str(module, gv['type'], gv['name'])
c_file.write(str)
s = resolve_type_str(module, gv['type'], gv['name'])
c_file.write(s)
c_file.write(';\n')
c_file.write('\n')
@ -662,6 +667,17 @@ def generate_c_file(module):
c_file.write(resolve_type_str(module, v['type'], v['name']))
c_file.write(';\n')
b_num = 0
for b in fn['block_scopes']:
for v in b:
c_file.write(' ' * INDENT_SPACES)
if 'CONST' in v['addr_type']:
c_file.write('static ')
name = '__block' + str(b_num) + '__' + v['name']
c_file.write(resolve_type_str(module, v['type'], name))
c_file.write(';\n')
b_num = b_num + 1
c_file.write(' ' * INDENT_SPACES)
c_file.write('LOG_TRACE("(')
@ -699,6 +715,7 @@ def generate_c_file(module):
do_comma = True
c_file.write(');\n')
c_file.write(' ' * INDENT_SPACES)
c_file.write('NOT_IMPLEMENTED();\n')
c_file.write('}\n\n')