Implement edit functions + functions around camera + ... (#146)

* Fix SEGFAULT due to reading out of bounds (we were using wrong index)

* Use floats instead of doubles

* Implement all flicplay.c functions

* Compare ptr against NULL

* Implement TotalRepair

* Implement some edit functions

* Implement actor/special volume related edit functions

* Implement MungeSpecialVolume

* Implement a few depth functions

* Fix location of spawned actors (when SHIFT was not pressed)

Co-authored-by: Dethrace Engineering Department <78985374+dethrace-labs@users.noreply.github.com>
This commit is contained in:
Anonymous Maarten 2022-09-28 09:40:53 +02:00 committed by GitHub
parent b5ccfe7dd2
commit db3d6ac91e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1215 additions and 194 deletions

View File

@ -12,6 +12,7 @@ extern struct br_font* BrFontProp7x9;
// BrActor
br_actor* BrActorLoad(char* filename);
br_uint_32 BrActorLoadMany(char* filename, br_actor** actors, br_uint_16 num);
br_uint_32 BrActorSave(char* filename, br_actor* ptr);
br_actor* BrActorAllocate(br_uint_8 type, void* type_data);
br_actor* BrActorAdd(br_actor* parent, br_actor* a);
void BrActorRelink(br_actor* parent, br_actor* a);
@ -77,6 +78,7 @@ void BrMatrix34Copy(br_matrix34* A, br_matrix34* B);
void BrMatrix34PreRotateY(br_matrix34* mat, br_angle ry);
void BrMatrix34RotateY(br_matrix34* mat, br_angle ry);
void BrMatrix34PostScale(br_matrix34* mat, br_scalar sx, br_scalar sy, br_scalar sz);
void BrMatrix34PreScale(br_matrix34* mat, br_scalar sx, br_scalar sy, br_scalar sz);
void BrMatrix34PreTransform(br_matrix34* mat, br_transform* xform);
void BrMatrix34PostTransform(br_matrix34* mat, br_transform* xform);
void BrMatrix34PreRotateX(br_matrix34* mat, br_angle rx);
@ -118,6 +120,7 @@ br_model* BrModelLoad(char* filename);
void BrModelFree(br_model* model);
void BrModelUpdate(br_model* model, br_uint_16 flags);
br_uint_32 BrModelLoadMany(char* filename, br_model** models, br_uint_16 num);
br_uint_32 BrModelSaveMany(char* filename, br_model** models, br_uint_16 num);
br_model_find_cbfn* BrModelFindHook(br_model_find_cbfn* hook);
// BrPixelmap

View File

@ -1206,7 +1206,26 @@ void MungeSpecialVolume(tCollision_info* pCar) {
tCar_spec* car;
LOG_TRACE("(%p)", pCar);
STUB_ONCE();
new_special_volume = FindSpecialVolume(&pCar->pos, pCar->last_special_volume);
if (pCar->auto_special_volume != NULL && (new_special_volume == NULL || new_special_volume->gravity_multiplier == 1.f)) {
if (pCar->water_d == 10000.f && pCar->water_depth_factor != 1.f) {
pCar->auto_special_volume = NULL;
} else {
new_special_volume = pCar->auto_special_volume;
}
}
if (pCar->last_special_volume != new_special_volume && pCar->driver == eDriver_local_human) {
if (pCar->last_special_volume != NULL && pCar->last_special_volume->exit_noise >= 0 && (new_special_volume == NULL || pCar->last_special_volume->exit_noise != new_special_volume->exit_noise)) {
DRS3StartSound(gCar_outlet, pCar->last_special_volume->exit_noise);
}
if (new_special_volume != NULL && new_special_volume->entry_noise >= 0 && (pCar->last_special_volume == NULL || pCar->last_special_volume->entry_noise != new_special_volume->entry_noise)) {
DRS3StartSound(gCar_outlet, new_special_volume->entry_noise);
}
}
pCar->last_special_volume = new_special_volume;
if (new_special_volume != NULL && pCar->num_smoke_columns != 0 && pCar->last_special_volume != NULL && pCar->last_special_volume->gravity_multiplier < 1.f) {
StopCarSmoking((tCar_spec*)pCar);
}
}
// IDA: void __usercall ResetCarSpecialVolume(tCollision_info *pCar@<EAX>)

View File

@ -1,6 +1,7 @@
#include "controls.h"
#include "brender/brender.h"
#include "brucetrk.h"
#include "car.h"
#include "constants.h"
#include "crush.h"
@ -826,7 +827,6 @@ void LookRight() {
// IDA: void __cdecl DamageTest()
void DamageTest() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
// IDA: void __cdecl TDamageEngine()
@ -920,7 +920,8 @@ void TDamageRRWheel() {
// IDA: void __cdecl MoveBonnetForward()
void MoveBonnetForward() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[2] -= .005f;
}
// IDA: void __cdecl SaveBonnet()
@ -928,109 +929,129 @@ void SaveBonnet() {
br_actor* bonny;
tPath_name the_path;
LOG_TRACE("()");
NOT_IMPLEMENTED();
bonny = gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor;
PathCat(the_path, gApplication_path, bonny->identifier);
BrActorSave(the_path, bonny);
}
// IDA: void __cdecl MoveBonnetBackward()
void MoveBonnetBackward() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[2] += .005f;
}
// IDA: void __cdecl MoveBonnetLeft()
void MoveBonnetLeft() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[0] -= .005f;
}
// IDA: void __cdecl ShrinkBonnetX()
void ShrinkBonnetX() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[0][0] *= .98f;
}
// IDA: void __cdecl SwellBonnetX()
void SwellBonnetX() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[0][0] *= 1.02f;
}
// IDA: void __cdecl ShrinkBonnetY()
void ShrinkBonnetY() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[1][1] *= .98f;
}
// IDA: void __cdecl SwellBonnetY()
void SwellBonnetY() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[1][1] *= 1.02f;
}
// IDA: void __cdecl ShrinkBonnetZ()
void ShrinkBonnetZ() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[2][2] *= .98f;
}
// IDA: void __cdecl SwellBonnetZ()
void SwellBonnetZ() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat.m[2][2] *= 1.02f;
}
// IDA: void __cdecl MoveBonnetDown()
void MoveBonnetDown() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[1] += .005f;
}
// IDA: void __cdecl MoveBonnetRight()
void MoveBonnetRight() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[0] += .005f;
}
// IDA: void __cdecl MoveBonnetUp()
void MoveBonnetUp() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.translate.t.v[1] -= .005f;
}
// IDA: void __cdecl TiltBonnetDownX()
void TiltBonnetDownX() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
BrMatrix34PreRotateX(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, BR_ANGLE_DEG(.5f));
}
// IDA: void __cdecl TiltBonnetUpX()
void TiltBonnetUpX() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
BrMatrix34PreRotateX(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, -BR_ANGLE_DEG(.5f));
}
// IDA: void __cdecl TiltBonnetDownY()
void TiltBonnetDownY() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
BrMatrix34PreRotateY(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, BR_ANGLE_DEG(.5f));
}
// IDA: void __cdecl TiltBonnetUpY()
void TiltBonnetUpY() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
BrMatrix34PreRotateY(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, -BR_ANGLE_DEG(.5f));
}
// IDA: void __cdecl TiltBonnetDownZ()
void TiltBonnetDownZ() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
BrMatrix34PreRotateZ(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, BR_ANGLE_DEG(.5f));
}
// IDA: void __cdecl TiltBonnetUpZ()
void TiltBonnetUpZ() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
BrMatrix34PreRotateZ(&gProgram_state.current_car.car_model_actors[gProgram_state.current_car.car_actor_count - 1].actor->t.t.mat, -BR_ANGLE_DEG(.5f));
}
// IDA: void __cdecl ToggleCockpit()
@ -1073,7 +1094,10 @@ void ToggleMirror() {
// IDA: void __cdecl ConcussMe()
void ConcussMe() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
SufferFromConcussion(1.f);
NewScreenWobble(IRandomPosNeg(15), IRandomPosNeg(10), IRandomBetween(10, 60));
PratcamEvent(3);
}
// IDA: void __cdecl CheckHelp()
@ -1370,7 +1394,19 @@ void ExplodeCar(tCar_spec* pCar) {
br_vector3 tv;
br_vector3 pos;
LOG_TRACE("(%p)", pCar);
NOT_IMPLEMENTED();
pCar->last_car_car_collision = 0;
pos.v[0] = .1449275f * pCar->cmpos.v[0];
pos.v[1] = .1449275f * pCar->cmpos.v[1];
pos.v[2] = pCar->bounds[0].min.v[2] + .3f * (pCar->bounds[0].max.v[2] - pCar->bounds[0].min.v[2]);
BrMatrix34ApplyP(&tv, &pos, &pCar->car_master_actor->t.t.mat);
CreatePuffOfSmoke(&tv, &pCar->v, 1.f, 1.f, 7, pCar);
pos.v[2] = pCar->bounds[0].min.v[2] + .7f * (pCar->bounds[0].max.v[2] - pCar->bounds[0].min.v[2]);
BrMatrix34ApplyP(&tv, &pos, &pCar->car_master_actor->t.t.mat);
CreatePuffOfSmoke(&tv, &pCar->v, 1.f, 1.f, 7, pCar);
DisableCar(pCar);
}
// IDA: void __usercall CheckRecoveryOfCars(tU32 pEndFrameTime@<EAX>)
@ -2168,21 +2204,60 @@ void ResetRecoveryVouchers() {
void CycleCarTexturingLevel() {
tCar_texturing_level new_level;
LOG_TRACE("()");
NOT_IMPLEMENTED();
new_level = (GetCarTexturingLevel() + 1) % eCTL_count;
SetCarTexturingLevel(new_level);
switch (new_level) {
case eCTL_none:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(50));
break;
case eCTL_transparent:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(51));
break;
case eCTL_full:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(52));
break;
case eCTL_count:
break;
}
}
// IDA: void __cdecl CycleWallTexturingLevel()
void CycleWallTexturingLevel() {
tWall_texturing_level new_level;
LOG_TRACE("()");
NOT_IMPLEMENTED();
new_level = (GetWallTexturingLevel() + 1) % eWTL_count;
ReallySetWallTexturingLevel(new_level);
SetWallTexturingLevel(new_level);
switch (new_level) {
case eWTL_none:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(55));
break;
case eWTL_linear:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(56));
break;
case eWTL_full:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(57));
break;
case eWTL_count:
break;
}
}
// IDA: void __cdecl CycleRoadTexturingLevel()
void CycleRoadTexturingLevel() {
tRoad_texturing_level new_level;
LOG_TRACE("()");
NOT_IMPLEMENTED();
new_level = (GetRoadTexturingLevel() + 1) % 3;
ReallySetRoadTexturingLevel(new_level);
SetRoadTexturingLevel(new_level);
if (new_level == eRTL_none) {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(53));
} else if (new_level == eRTL_full) {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(54));
}
}
// IDA: void __cdecl CycleYonFactor()
@ -2190,7 +2265,21 @@ void CycleYonFactor() {
br_scalar new_factor;
char factor_str[5];
LOG_TRACE("()");
NOT_IMPLEMENTED();
new_factor = GetYonFactor() / 2.f;
if (new_factor < .1f) {
new_factor = 1.f;
}
SetYonFactor(new_factor);
if (new_factor > .75f) {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(100));
} else if (new_factor > .375f) {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(101));
} else if (new_factor > .187f) {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(102));
} else {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(103));
}
}
// IDA: void __usercall SetSoundDetailLevel(int pLevel@<EAX>)
@ -2222,7 +2311,21 @@ int GetSoundDetailLevel() {
void CycleSoundDetailLevel() {
int new_level;
LOG_TRACE("()");
NOT_IMPLEMENTED();
new_level = (gSound_detail_level + 1) % 3;
ReallySetSoundDetailLevel(new_level);
SetSoundDetailLevel(new_level);
switch(new_level) {
case 0:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(116));
break;
case 1:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(117));
break;
case 2:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(118));
break;
}
}
// IDA: void __cdecl CycleCarSimplificationLevel()
@ -2230,21 +2333,46 @@ void CycleCarSimplificationLevel() {
char* src;
char* dst;
LOG_TRACE("()");
NOT_IMPLEMENTED();
gCar_simplification_level = (gCar_simplification_level + 1) % 5;
src = GetMiscString(119);
dst = BrMemAllocate(strlen(src), kMem_simp_level);
sprintf(dst, src, gCar_simplification_level);
NewTextHeadupSlot(4, 0, 2000, -4, dst);
BrMemFree(dst);
}
// IDA: void __cdecl ToggleAccessoryRendering()
void ToggleAccessoryRendering() {
int on;
LOG_TRACE("()");
NOT_IMPLEMENTED();
if (gNet_mode == eNet_mode_none) {
on = !GetAccessoryRendering();
SetAccessoryRendering(on);
if (on) {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(120));
} else {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(121));
}
} else {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(124));
}
}
// IDA: void __cdecl ToggleSmoke()
void ToggleSmoke() {
int on;
LOG_TRACE("()");
NOT_IMPLEMENTED();
on = !GetSmokeOn();
ReallySetSmokeOn(on);
SetSmokeOn(on);
if (on) {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(122));
} else {
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(123));
}
}
// IDA: void __usercall DrawSomeText2(tDR_font *pFont@<EAX>)

View File

@ -5,8 +5,10 @@
#include "errors.h"
#include "globvars.h"
#include "globvrkm.h"
#include "globvrpb.h"
#include "harness/hooks.h"
#include "harness/trace.h"
#include "replay.h"
#include "spark.h"
#include "utility.h"
#include <math.h>
@ -80,7 +82,15 @@ br_scalar CalculateWrappingMultiplier(br_scalar pValue, br_scalar pYon) {
br_scalar trunc_k;
int int_k;
LOG_TRACE("(%f, %f)", pValue, pYon);
NOT_IMPLEMENTED();
k = pYon * 1.3f * TAU / pValue;
int_k = (int)k;
if (k - int_k <= .5f) {
trunc_k = int_k;
} else {
trunc_k = int_k + 1.f;
}
return trunc_k / TAU * pValue;
}
// IDA: br_scalar __usercall DepthCueingShiftToDistance@<ST0>(int pShift@<EAX>)
@ -128,6 +138,7 @@ void InstantDepthChange(tDepth_effect_type pType, br_pixelmap* pSky_texture, int
// IDA: br_scalar __cdecl Tan(br_scalar pAngle)
br_scalar Tan(br_scalar pAngle) {
LOG_TRACE("(%f)", pAngle);
return sinf(BrAngleToRadian(pAngle)) / cosf(BrAngleToRadian(pAngle));
}
@ -137,7 +148,11 @@ br_scalar EdgeU(br_angle pSky, br_angle pView, br_angle pPerfect) {
br_scalar b;
br_scalar c;
LOG_TRACE("(%d, %d, %d)", pSky, pView, pPerfect);
NOT_IMPLEMENTED();
a = cosf(BrAngleToRadian(pPerfect));
b = sinf(BrAngleToRadian(pView));
c = cosf(BrAngleToRadian(pView));
return b * a * a / (BrAngleToRadian(pSky) * (1.f + c));
}
// IDA: void __usercall MungeSkyModel(br_actor *pCamera@<EAX>, br_model *pModel@<EDX>)
@ -160,7 +175,71 @@ void MungeSkyModel(br_actor* pCamera, br_model* pModel) {
br_angle angle_range;
br_angle angle;
LOG_TRACE("(%p, %p)", pCamera, pModel);
NOT_IMPLEMENTED();
camera_data = pCamera->type_data;
tan_half_fov = Tan(camera_data->field_of_view / 2);
// BR_ANGLE_RAD(atan2f(tan_half_fov, camera_data->aspect / 2));
horizon_half_width = (camera_data->yon_z - 1.f) * tan_half_fov;
horizon_half_height = horizon_half_width * camera_data->aspect;
horizon_half_diag = BR_LENGTH2(horizon_half_width, horizon_half_height);
min_angle = BR_ANGLE_RAD(atan2f(horizon_half_diag, camera_data->yon_z - 1.f));
edge_u = EdgeU(gSky_image_width, 2 * min_angle, BR_ANGLE_DEG(10));
gSky_width = 2.f * horizon_half_width;
gSky_height = 2.f * horizon_half_height;
gSky_x_multiplier = CalculateWrappingMultiplier(gSky_width, camera_data->yon_z);
gSky_y_multiplier = CalculateWrappingMultiplier(gSky_height, camera_data->yon_z);
for (vertex = 0; vertex < 88; vertex += 4) {
pModel->vertices[vertex].map.v[0] = -edge_u;
}
for (vertex = 1; vertex < 88; vertex += 4) {
pModel->vertices[vertex].map.v[0] = -edge_u / 2.f;
}
for (vertex = 2; vertex < 88; vertex += 4) {
pModel->vertices[vertex].map.v[0] = edge_u / 2.f;
}
for (vertex = 3; vertex < 88; vertex += 4) {
pModel->vertices[vertex].map.v[0] = edge_u;
}
for (vertex = 0; vertex < 88; vertex += 4) {
pModel->vertices[vertex].p.v[0] = -horizon_half_diag;
}
for (vertex = 1; vertex < 88; vertex += 4) {
pModel->vertices[vertex].p.v[0] = -horizon_half_diag / 2.f;
}
for (vertex = 2; vertex < 88; vertex += 4) {
pModel->vertices[vertex].p.v[0] = horizon_half_diag / 2.f;
}
for (vertex = 3; vertex < 88; vertex += 4) {
pModel->vertices[vertex].p.v[0] = horizon_half_diag;
}
PossibleService();
angle_range = -(gSky_image_underground + (BR_ANGLE_DEG(90) - min_angle));
for (vertex = 0; vertex < 2; vertex++) {
angle = vertex * angle_range / 2 - (BR_ANGLE_DEG(90) + min_angle);
pModel->vertices[0 + 4 * vertex].p.v[1] = sinf(BrAngleToRadian(angle)) * (camera_data->yon_z - 1.f);
pModel->vertices[0 + 4 * vertex].p.v[2] = -cosf(BrAngleToRadian(angle)) * (camera_data->yon_z - 1.f);
}
for (vertex = 0; vertex < 18; vertex++) {
angle = vertex * gSky_image_height / 18 - gSky_image_height;
pModel->vertices[8 + 4 * vertex].p.v[1] = sinf(BrAngleToRadian(angle)) * (camera_data->yon_z - 1.f);
pModel->vertices[8 + 4 * vertex].p.v[2] = -cosf(BrAngleToRadian(angle)) * (camera_data->yon_z - 1.f);
}
for (vertex = 0; vertex < 2; vertex++) {
angle = vertex * (min_angle + BR_ANGLE_DEG(90) - (gSky_image_height - gSky_image_underground)) - (gSky_image_height - gSky_image_underground);
pModel->vertices[80 + 4 * vertex].p.v[1] = sinf(BrAngleToRadian(angle)) * (camera_data->yon_z - 1.f);
pModel->vertices[80 + 4 * vertex].p.v[2] = -cosf(BrAngleToRadian(angle)) * (camera_data->yon_z - 1.f);
}
PossibleService();
for (band = 0; band < 22; band++) {
for (vertex = 1; vertex < 4; vertex++) {
pModel->vertices[4 * band + vertex].p.v[1] = pModel->vertices[vertex].p.v[1];
pModel->vertices[4 * band + vertex].p.v[2] = pModel->vertices[vertex].p.v[2];
}
}
// FIXME: unknown model flag disabled
BrModelUpdate(pModel, BR_MODU_ALL & ~0x80);
}
// IDA: br_model* __usercall CreateHorizonModel@<EAX>(br_actor *pCamera@<EAX>)
@ -171,8 +250,36 @@ br_model* CreateHorizonModel(br_actor* pCamera) {
tU8 stripe;
br_model* model;
LOG_TRACE("(%p)", pCamera);
STUB();
return NULL;
model = BrModelAllocate(NULL, 88, 126);
model->flags |= BR_MODF_KEEP_ORIGINAL;
for (band = 0; band < 21; band++) {
for (stripe = 0; stripe < 3; stripe++) {
model->faces[6 * band + 2 * stripe].vertices[0] = stripe + 4 * band + 0;
model->faces[6 * band + 2 * stripe].vertices[1] = stripe + 4 * band + 1;
model->faces[6 * band + 2 * stripe].vertices[2] = stripe + 4 * band + 5;
model->faces[6 * band + 2 * stripe + 1].vertices[0] = stripe + 4 * band + 0;
model->faces[6 * band + 2 * stripe + 1].vertices[1] = stripe + 4 * band + 5;
model->faces[6 * band + 2 * stripe + 1].vertices[2] = stripe + 4 * band + 4;
model->faces[6 * band + 2 * stripe + 0].smoothing = 1;
model->faces[6 * band + 2 * stripe + 1].smoothing = 1;
model->faces[6 * band + 2 * stripe + 0].material = NULL;
model->faces[6 * band + 2 * stripe + 1].material = NULL;
}
}
for (vertex = 0; vertex < 12; vertex++) {
model->vertices[vertex].map.v[1] = 0.9999999f;
}
for (vertex = 80; vertex < 88; vertex++) {
model->vertices[vertex].map.v[1] = 0.f;
}
for (band = 1; band < 18; band++) {
model->vertices[4 * band + 8].map.v[1] = (float)(18 - band) / 18.f;
for (stripe = 1; stripe < 4; stripe++) {
model->vertices[4 * band + 8 + stripe].map.v[1] = model->vertices[4 * band + 8].map.v[1];
}
}
return model;
}
// IDA: void __usercall LoadDepthTable(char *pName@<EAX>, br_pixelmap **pTable@<EDX>, int *pPower@<EBX>)
@ -231,19 +338,18 @@ void InitDepthEffects() {
BrMaterialAdd(gHorizon_material);
gForward_sky_model = CreateHorizonModel(gCamera);
gRearview_sky_model = CreateHorizonModel(gRearview_camera);
LOG_WARN("InitDepthEffects not fully implemented. This will break cockpit views");
// BrModelAdd(gForward_sky_model);
// BrModelAdd(gRearview_sky_model);
// gForward_sky_actor = BrActorAllocate(BR_ACTOR_MODEL, 0);
// gForward_sky_actor->model = gForward_sky_model;
// gForward_sky_actor->material = gHorizon_material;
// gForward_sky_actor->render_style = BR_RSTYLE_NONE;
// BrActorAdd(gUniverse_actor, gForward_sky_actor);
// gRearview_sky_actor = BrActorAllocate(BR_ACTOR_MODEL, 0);
// gRearview_sky_actor->model = gRearview_sky_model;
// gRearview_sky_actor->material = gHorizon_material;
// gRearview_sky_actor->render_style = BR_RSTYLE_NONE;
// BrActorAdd(gUniverse_actor, gRearview_sky_actor);
BrModelAdd(gForward_sky_model);
BrModelAdd(gRearview_sky_model);
gForward_sky_actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
gForward_sky_actor->model = gForward_sky_model;
gForward_sky_actor->material = gHorizon_material;
gForward_sky_actor->render_style = BR_RSTYLE_NONE;
BrActorAdd(gUniverse_actor, gForward_sky_actor);
gRearview_sky_actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
gRearview_sky_actor->model = gRearview_sky_model;
gRearview_sky_actor->material = gHorizon_material;
gRearview_sky_actor->render_style = BR_RSTYLE_NONE;
BrActorAdd(gUniverse_actor, gRearview_sky_actor);
gLast_camera_special_volume = 0;
}
@ -397,13 +503,40 @@ void ExternalSky(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_act
}
}
#define ACTOR_CAMERA(ACTOR) ((br_camera*)((ACTOR)->type_data))
// IDA: void __usercall DoHorizon(br_pixelmap *pRender_buffer@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, br_matrix34 *pCamera_to_world@<ECX>)
void DoHorizon(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_actor* pCamera, br_matrix34* pCamera_to_world) {
br_angle yaw;
br_actor* actor;
LOG_TRACE("(%p, %p, %p, %p)", pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world);
STUB_ONCE();
yaw = BR_ANGLE_RAD(atan2f(pCamera_to_world->m[2][0], pCamera_to_world->m[2][2]));
if (!gProgram_state.cockpit_on && !(gAction_replay_mode && gAction_replay_camera_mode)) {
return;
}
if (gRendering_mirror) {
actor = gRearview_sky_actor;
} else {
actor = gForward_sky_actor;
if (ACTOR_CAMERA(gCamera)->field_of_view != gOld_fov || ACTOR_CAMERA(gCamera)->yon_z != gOld_yon) {
gOld_fov = ACTOR_CAMERA(gCamera)->field_of_view;
gOld_yon = ACTOR_CAMERA(gCamera)->yon_z;
MungeSkyModel(gCamera, gForward_sky_model);
}
}
BrMatrix34RotateY(&actor->t.t.mat, yaw);
BrVector3Copy(&actor->t.t.translate.t, (br_vector3*)pCamera_to_world->m[3]);
gHorizon_material->map_transform.m[0][0] = 1.f;
gHorizon_material->map_transform.m[0][1] = 0.f;
gHorizon_material->map_transform.m[1][0] = 0.f;
gHorizon_material->map_transform.m[1][1] = 1.f;
gHorizon_material->map_transform.m[2][0] = -BrFixedToFloat(yaw) / BrFixedToFloat(gSky_image_width);
gHorizon_material->map_transform.m[2][1] = 0.f;
BrMaterialUpdate(gHorizon_material, BR_MATU_ALL);
actor->render_style = BR_RSTYLE_FACES;
BrZbSceneRenderAdd(actor);
actor->render_style = BR_RSTYLE_NONE;
}
// IDA: void __usercall DoDepthCue(br_pixelmap *pRender_buffer@<EAX>, br_pixelmap *pDepth_buffer@<EDX>)

View File

@ -865,7 +865,35 @@ void DoDifferenceX(tFlic_descriptor* pFlic_info, tU32 chunk_length) {
tU8 the_byte;
tU32 the_row_bytes;
LOG_TRACE("(%p, %d)", pFlic_info, chunk_length);
NOT_IMPLEMENTED();
first_line = MemReadU16(&pFlic_info->data);
line_count = MemReadU16(&pFlic_info->data);
the_row_bytes = pFlic_info->the_pixelmap->row_bytes;
line_pixel_ptr = pFlic_info->first_pixel + first_line * the_row_bytes;
for (i = 0; i < line_count; i++) {
pixel_ptr = line_pixel_ptr;
number_of_packets = MemReadU8(&pFlic_info->data);
for (j = 0; j < number_of_packets; j++) {
skip_count = MemReadU8(&pFlic_info->data);
size_count = MemReadS8(&pFlic_info->data);
pixel_ptr += skip_count;
if (size_count >= 0) {
for (k = 0; k < size_count; k++) {
*pixel_ptr = *pFlic_info->data;
pFlic_info->data++;
pixel_ptr++;
}
} else {
the_byte = *pFlic_info->data;
pFlic_info->data++;
for (k = 0; k < -size_count; k++) {
*pixel_ptr = the_byte;
pixel_ptr++;
}
}
}
line_pixel_ptr += the_row_bytes;
}
}
// IDA: void __usercall DoDifferenceTrans(tFlic_descriptor *pFlic_info@<EAX>, tU32 chunk_length@<EDX>)
@ -883,7 +911,42 @@ void DoDifferenceTrans(tFlic_descriptor* pFlic_info, tU32 chunk_length) {
tU8 the_byte;
tU32 the_row_bytes;
LOG_TRACE("(%p, %d)", pFlic_info, chunk_length);
NOT_IMPLEMENTED();
first_line = MemReadU16(&pFlic_info->data);
line_count = MemReadU16(&pFlic_info->data);
the_row_bytes = pFlic_info->the_pixelmap->row_bytes;
line_pixel_ptr = pFlic_info->first_pixel + first_line * the_row_bytes;
for (i = 0; i < line_count; i++) {
pixel_ptr = line_pixel_ptr;
number_of_packets = MemReadU8(&pFlic_info->data);
for (j = 0; j < number_of_packets; j++) {
skip_count = MemReadU8(&pFlic_info->data);
size_count = MemReadS8(&pFlic_info->data);
pixel_ptr += skip_count;
if (size_count >= 0) {
for (k = 0; k < size_count; k++) {
the_byte = *pFlic_info->data;
pFlic_info->data++;
if (the_byte != '\0') {
*pixel_ptr = the_byte;
}
pixel_ptr++;
}
} else {
the_byte = *pFlic_info->data;
pFlic_info->data++;
if (the_byte == '\0') {
pixel_ptr += size_count;
} else {
for (k = 0; k < -size_count; k++) {
*pixel_ptr = the_byte;
pixel_ptr++;
}
}
}
}
line_pixel_ptr += the_row_bytes;
}
}
// IDA: void __usercall DoColour256(tFlic_descriptor *pFlic_info@<EAX>, tU32 chunk_length@<EDX>)
@ -1068,7 +1131,18 @@ void DoBlack(tFlic_descriptor* pFlic_info, tU32 chunk_length) {
tU32 the_row_bytes;
tU32* line_pixel_ptr;
LOG_TRACE("(%p, %d)", pFlic_info, chunk_length);
NOT_IMPLEMENTED();
pixel_ptr = pFlic_info->first_pixel;
the_row_bytes = pFlic_info->the_pixelmap->row_bytes;
the_width = pFlic_info->width;
for (i = 0; i < pFlic_info->height; i++) {
line_pixel_ptr = (tU32*)pixel_ptr;
for (j = 0; j < the_width / sizeof(tU32); j++) {
*line_pixel_ptr = 0;
line_pixel_ptr++;
}
pixel_ptr += the_row_bytes;
}
}
// IDA: void __usercall DoRunLengthX(tFlic_descriptor *pFlic_info@<EAX>, tU32 chunk_length@<EDX>)
@ -1163,7 +1237,18 @@ void DoUncompressed(tFlic_descriptor* pFlic_info, tU32 chunk_length) {
tU32 the_row_bytes;
tU32* line_pixel_ptr;
LOG_TRACE("(%p, %d)", pFlic_info, chunk_length);
NOT_IMPLEMENTED();
pixel_ptr = pFlic_info->first_pixel;
the_row_bytes = pFlic_info->the_pixelmap->row_bytes;
the_width = pFlic_info->width;
for (i = 0; i < pFlic_info->height; i++) {
line_pixel_ptr = (tU32*)pixel_ptr;
for (j = 0; j < the_width / 4; j++) {
*line_pixel_ptr = MemReadU32(&pFlic_info->data);
line_pixel_ptr++;
}
pixel_ptr += the_row_bytes;
}
}
// IDA: void __usercall DoUncompressedTrans(tFlic_descriptor *pFlic_info@<EAX>, tU32 chunk_length@<EDX>)
@ -1176,7 +1261,25 @@ void DoUncompressedTrans(tFlic_descriptor* pFlic_info, tU32 chunk_length) {
tU8 the_byte;
tU32 the_row_bytes;
LOG_TRACE("(%p, %d)", pFlic_info, chunk_length);
NOT_IMPLEMENTED();
pixel_ptr = pFlic_info->first_pixel;
the_row_bytes = pFlic_info->the_pixelmap->row_bytes;
the_width = pFlic_info->width;
for (i = 0; i < pFlic_info->height; i++) {
line_pixel_ptr = pixel_ptr;
for (j = 0; j < the_width; j++) {
#if defined (DETHRACE_FIX_BUGS)
the_byte = MemReadU8(&pFlic_info->data);
#else
the_byte = MemReadU32(&pFlic_info->data);
#endif
if (the_byte != '\0') {
*line_pixel_ptr = the_byte;
}
line_pixel_ptr++;
}
pixel_ptr += the_row_bytes;
}
}
// IDA: void __usercall DoMini(tFlic_descriptor *pFlic_info@<EAX>, tU32 chunk_length@<EDX>)

View File

@ -1229,7 +1229,7 @@ void ProcessGetNearPlayer(tOpponent_spec* pOpponent_spec, tProcess_objective_com
return;
}
if (pCommand == ePOC_run) {
if ((pOpponent_spec->car_spec->car_ID & 0xFF00) == 768 && pOpponent_spec->distance_from_home > 75.0) {
if ((pOpponent_spec->car_spec->car_ID & 0xff00) == 768 && pOpponent_spec->distance_from_home > 75.0) {
dr_dprintf("%s: Completing get_near objective because I'm out of my precinct", pOpponent_spec->car_spec->driver_name);
NewObjective(pOpponent_spec, eOOT_return_to_start);
return;

View File

@ -624,7 +624,7 @@ void SetSoundVolumes() {
if (!gSound_enabled) {
return;
}
if (gEffects_outlet) {
if (gEffects_outlet != NULL) {
DRS3SetOutletVolume(gEffects_outlet, 42 * gProgram_state.effects_volume);
}
DRS3SetOutletVolume(gCar_outlet, 42 * gProgram_state.effects_volume);

View File

@ -82,7 +82,7 @@ void SetWorldToScreen(br_pixelmap* pScreen) {
LOG_TRACE("(%p)", pScreen);
BrMatrix4Perspective(&mat, gSpark_cam->field_of_view, gSpark_cam->aspect, -gSpark_cam->hither_z, -gSpark_cam->yon_z);
BrMatrix4Scale(&mat2, pScreen->width / 2, pScreen->height / 2, 1.0);
BrMatrix4Scale(&mat2, pScreen->width / 2, pScreen->height / 2, 1.0f);
BrMatrix4Mul(&gCameraToScreen, &mat, &mat2);
}

View File

@ -296,7 +296,9 @@ void CheckCheckpoints() {
// IDA: void __cdecl TotalRepair()
void TotalRepair() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
TotallyRepairCar();
NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(41));
}
// IDA: void __cdecl DoLogos()

File diff suppressed because it is too large Load Diff