Recovery and Race Completed logic (#74)
* implements race completed, recovery logic * fps limiter, better framebuffer handling
This commit is contained in:
parent
ee032df264
commit
94167e09c8
|
@ -0,0 +1,28 @@
|
|||
# Code layout
|
||||
|
||||
### DETHRACE
|
||||
Game logic. According to the symbol dump, these files were originally stored in `C:\DETHRACE\src`.
|
||||
|
||||
`DETHRACE/common` - all common logic
|
||||
`DETHRACE/pc-dos` - all platform-specific functions (DOS, in this case)
|
||||
`DETHRACE/pd` - platform-dependent generic headers.
|
||||
|
||||
_All code here is kept as similar to how we think the original code might have been. Any changes required are implemented as hooks in the `harness`._
|
||||
|
||||
### BRSRC13
|
||||
|
||||
[BRender](https://en.wikipedia.org/wiki/Argonaut_Games#BRender), originally stored in `C:\BRSRC13`. A graphics rendering library.
|
||||
|
||||
Apparently Stainless Software used their own build of BRender with unknown modifications.
|
||||
|
||||
_All code here is kept as similar to how we think the original code might have been. Any changes required are implemented as hooks in the `harness`._
|
||||
|
||||
### S3
|
||||
|
||||
Audio library. No other information.
|
||||
|
||||
_All code here is kept as similar to how we think the original code might have been. Any changes required are implemented as hooks in the `harness`._
|
||||
|
||||
### harness
|
||||
|
||||
- Provides hooks into the game logic to implement modern cross-platform support.
|
|
@ -0,0 +1,59 @@
|
|||
# Rendering pipeline
|
||||
|
||||
The original game renders both 2d and 3d elements to the same memory buffer, called `gBack_screen`.
|
||||
|
||||
Another variable, `gRender_screen`, points into that memory buffer and is where the 3d scene is drawn on top of any existing 2d pixels.
|
||||
|
||||
Rendering is done in a (standard for the time) 8 bit paletted mode.
|
||||
|
||||
```
|
||||
+-----------------------------------------+
|
||||
|gBack_screen |
|
||||
| +------------------------+ |
|
||||
| | gRender_screen | |
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
| +------------------------+ |
|
||||
| |
|
||||
+-----------------------------------------+
|
||||
```
|
||||
|
||||
The `RenderAFrame` function does the following:
|
||||
|
||||
1. Render 2d background content (horizon, map, etc) to `gBack_screen`
|
||||
2. Start 3d scene rendering
|
||||
3. Render 3d environment to `gRender_screen`
|
||||
4. End 3d scene rendering
|
||||
5. Render 2d foreground content into `gBack_screen` (HUD, messages, etc)
|
||||
6. Swap buffers
|
||||
|
||||
If the rearview mirror is rendered, steps 3-4 are repeated, this time rendering into `gRearview_screen`
|
||||
|
||||
## Palette manipulation
|
||||
|
||||
The game palette is updated frequently:
|
||||
1. Fade screen to black
|
||||
2. Fade screen back up to normal brightness
|
||||
3. Different palettes for the menu interface and for game play
|
||||
4. The "On drugs" powerup
|
||||
|
||||
Palette animations run in a tight loop, assuming they are writing to the system color palette, so do not re-render the 3d scene etc. We handle this by hooking the palette functions and reusing the last-rendered scene from our framebuffer.
|
||||
|
||||
## OpenGL implementation
|
||||
|
||||
### Start 3d rendering hook
|
||||
- Capture the current `gBack_screen` and convert it to a 32 bit OpenGL texture, and render it as a full-screen quad.
|
||||
- Configure OpenGL framebuffer to do render-to-texture
|
||||
- Clear `gBack_screen`
|
||||
|
||||
### Render model hook
|
||||
- Render the model as an OpenGL VBO, convert referenced materials to OpenGL textures.
|
||||
|
||||
### End 3d rendering hook
|
||||
Render the framebuffer from above as a full-screen quad.
|
||||
|
||||
### Swap buffers hook
|
||||
- Again capture `gBack_screen` to pick up HUD elements rendered after the 3d scene, convert it to 32 bit, and render it as a full-screen quad.
|
||||
- Generate a palette-manipulation image which is blended over the top of everything as a full-screen quad to handle palette animations.
|
|
@ -8,5 +8,5 @@ br_pixelmap* DOSGfxBegin(char* setup_string) {
|
|||
LOG_TRACE("(\"%s\")", setup_string);
|
||||
|
||||
Harness_Hook_DOSGfxBegin();
|
||||
return BrPixelmapAllocate(BR_PMT_INDEX_8, 320, 240, NULL, BR_PMAF_NORMAL);
|
||||
return BrPixelmapAllocate(BR_PMT_INDEX_8, 320, 200, NULL, BR_PMAF_NORMAL);
|
||||
}
|
||||
|
|
|
@ -135,6 +135,8 @@ br_device_pixelmap* DevicePixelmapMemAllocate(br_uint_8 type, br_uint_16 w, br_u
|
|||
//pm->pm_row_bytes = (v11 - (__CFSHL__(v11 >> 31, 3) + 8 * (v11 >> 31))) >> 3;
|
||||
// TODO: calculate this differently
|
||||
pm->pm_row_bytes = w;
|
||||
pm->pm_row_bytes = tip->bits * tip->align * ((w + tip->align - 1) / tip->align) / 8;
|
||||
|
||||
if ((8 * pm->pm_row_bytes % tip->bits) == 0) {
|
||||
pm->pm_flags |= BR_PMF_ROW_WHOLEPIXELS;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "globvrkm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "graphics.h"
|
||||
#include "harness/config.h"
|
||||
#include "harness/trace.h"
|
||||
#include "netgame.h"
|
||||
#include "oil.h"
|
||||
|
@ -280,13 +281,13 @@ void InitialiseCar2(tCar_spec* pCar, int pClear_disabled_flag) {
|
|||
}
|
||||
BrMatrix34Copy(&pCar->old_frame_mat, &safe_position);
|
||||
BrMatrix34Copy(&pCar->oldmat, &safe_position);
|
||||
pCar->oldmat.m[3][0] *= 6.9000001;
|
||||
pCar->oldmat.m[3][1] *= 6.9000001;
|
||||
pCar->oldmat.m[3][2] *= 6.9000001;
|
||||
pCar->oldmat.m[3][0] *= WORLD_SCALE;
|
||||
pCar->oldmat.m[3][1] *= WORLD_SCALE;
|
||||
pCar->oldmat.m[3][2] *= WORLD_SCALE;
|
||||
BrMatrix34ApplyP(&pCar->pos, &pCar->cmpos, &pCar->oldmat);
|
||||
pCar->pos.v[0] /= 6.9000001;
|
||||
pCar->pos.v[1] /= 6.9000001;
|
||||
pCar->pos.v[2] /= 6.9000001;
|
||||
pCar->pos.v[0] /= WORLD_SCALE;
|
||||
pCar->pos.v[1] /= WORLD_SCALE;
|
||||
pCar->pos.v[2] /= WORLD_SCALE;
|
||||
for (j = 0; j < COUNT_OF(pCar->oldd); j++) {
|
||||
pCar->oldd[j] = pCar->ride_height;
|
||||
}
|
||||
|
@ -662,7 +663,41 @@ void RememberSafePosition(tCar_spec* car, tU32 pTime) {
|
|||
br_scalar ts;
|
||||
LOG_TRACE("(%p, %d)", car, pTime);
|
||||
|
||||
STUB_ONCE();
|
||||
if (car->disabled) {
|
||||
return;
|
||||
}
|
||||
time_count += pTime;
|
||||
if (time_count < 5000) {
|
||||
return;
|
||||
}
|
||||
time_count = 4000;
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (car->susp_height[j >> 1] <= car->oldd[j]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((!car->last_special_volume || car->last_special_volume->gravity_multiplier == 1.0)
|
||||
&& gCurrent_race.material_modifiers[car->material_index[0]].tyre_road_friction >= 0.1
|
||||
&& gCurrent_race.material_modifiers[car->material_index[1]].tyre_road_friction >= 0.1
|
||||
&& gCurrent_race.material_modifiers[car->material_index[2]].tyre_road_friction >= 0.1
|
||||
&& gCurrent_race.material_modifiers[car->material_index[3]].tyre_road_friction >= 0.1
|
||||
&& car->car_master_actor->t.t.mat.m[1][1] >= 0.80000001) {
|
||||
|
||||
for (j = 0; j < 5; j++) {
|
||||
r.v[0] = car->car_master_actor->t.t.mat.m[3][0] - car->last_safe_positions[j].m[3][0];
|
||||
r.v[1] = car->car_master_actor->t.t.mat.m[3][1] - car->last_safe_positions[j].m[3][1];
|
||||
r.v[2] = car->car_master_actor->t.t.mat.m[3][2] - car->last_safe_positions[j].m[3][2];
|
||||
|
||||
if (BrVector3LengthSquared(&r) < 8.4015961) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (j = 3; j > 0; j--) {
|
||||
BrMatrix34Copy(&car->last_safe_positions[j], &car->last_safe_positions[j - 1]);
|
||||
}
|
||||
BrMatrix34Copy(&car->last_safe_positions[0], &car->car_master_actor->t.t.mat);
|
||||
time_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ControlOurCar(tU32 pTime_difference@<EAX>)
|
||||
|
@ -680,14 +715,14 @@ void ControlOurCar(tU32 pTime_difference) {
|
|||
if (gNet_mode) {
|
||||
gCar_flying = 0;
|
||||
} else {
|
||||
car->car_master_actor->t.t.mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] * 6.9000001;
|
||||
car->car_master_actor->t.t.mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] * 6.9000001;
|
||||
car->car_master_actor->t.t.mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] * 6.9000001;
|
||||
car->car_master_actor->t.t.mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] * WORLD_SCALE;
|
||||
car->car_master_actor->t.t.mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] * WORLD_SCALE;
|
||||
car->car_master_actor->t.t.mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] * WORLD_SCALE;
|
||||
ts = (double)pTime_difference / 1000.0;
|
||||
FlyCar(car, ts);
|
||||
car->car_master_actor->t.t.mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] / 6.9000001;
|
||||
car->car_master_actor->t.t.mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] / 6.9000001;
|
||||
car->car_master_actor->t.t.mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] / 6.9000001;
|
||||
car->car_master_actor->t.t.mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] / WORLD_SCALE;
|
||||
car->car_master_actor->t.t.mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] / WORLD_SCALE;
|
||||
car->car_master_actor->t.t.mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] / WORLD_SCALE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -905,7 +940,7 @@ void FinishCars(tU32 pLast_frame_time, tU32 pTime) {
|
|||
BrMatrix34ApplyV(&car->direction, &minus_k, &car->car_master_actor->t.t.mat);
|
||||
} else if (gLast_mechanics_time > pLast_frame_time && gCar_to_view == car) {
|
||||
BrVector3Sub(&car->old_v, &car->old_v, &car->v);
|
||||
BrVector3Scale(&car->old_v, &car->old_v, (gLast_mechanics_time - pLast_frame_time) / (float)PHYSICS_STEP_TIME);
|
||||
BrVector3Scale(&car->old_v, &car->old_v, (gLast_mechanics_time - pLast_frame_time) / harness_game_config.physics_step_time);
|
||||
BrVector3Accumulate(&car->old_v, &car->v);
|
||||
BrVector3Normalise(&car->direction, &car->old_v);
|
||||
} else {
|
||||
|
@ -1021,7 +1056,7 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) {
|
|||
ForceRebuildActiveCarList();
|
||||
}
|
||||
if (gLast_mechanics_time < last_frame_time) {
|
||||
gLast_mechanics_time = PHYSICS_STEP_TIME * (last_frame_time / PHYSICS_STEP_TIME);
|
||||
gLast_mechanics_time = harness_game_config.physics_step_time * (last_frame_time / harness_game_config.physics_step_time);
|
||||
}
|
||||
GetNonCars();
|
||||
if (frame_end_time <= gLast_mechanics_time) {
|
||||
|
@ -1033,7 +1068,7 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) {
|
|||
|
||||
gDoing_physics = 1;
|
||||
PrepareCars(last_frame_time);
|
||||
gDt = PHYSICS_STEP_TIME / 1000.0; // 0.039999999;
|
||||
gDt = harness_game_config.physics_step_time / 1000.0; // 0.039999999;
|
||||
gMechanics_time_sync = pTime_difference - (gLast_mechanics_time - last_frame_time);
|
||||
while (gLast_mechanics_time < frame_end_time && step_number < 5) {
|
||||
step_number++;
|
||||
|
@ -1047,8 +1082,8 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) {
|
|||
for (i = 0; gNum_active_cars > i; ++i) {
|
||||
car = gActive_car_list[i];
|
||||
car->dt = -1.0;
|
||||
if (car->message.type == 15 && car->message.time >= gLast_mechanics_time && gLast_mechanics_time + PHYSICS_STEP_TIME >= car->message.time) {
|
||||
car->dt = (double)(gLast_mechanics_time + PHYSICS_STEP_TIME - car->message.time) / 1000.0;
|
||||
if (car->message.type == 15 && car->message.time >= gLast_mechanics_time && gLast_mechanics_time + harness_game_config.physics_step_time >= car->message.time) {
|
||||
car->dt = (double)(gLast_mechanics_time + harness_game_config.physics_step_time - car->message.time) / 1000.0;
|
||||
if (gDt - 0.0001 <= car->dt) {
|
||||
GetNetPos(car);
|
||||
} else if (gNet_mode == eNet_mode_host) {
|
||||
|
@ -1066,7 +1101,7 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) {
|
|||
}
|
||||
}
|
||||
if (!car->disabled
|
||||
&& (!car->doing_nothing_flag || (car->driver >= eDriver_net_human && (!gRecover_timer || car->driver != eDriver_local_human)))) {
|
||||
&& (!car->doing_nothing_flag || (car->driver >= eDriver_net_human && (!gPalette_fade_time || car->driver != eDriver_local_human)))) {
|
||||
if (car->box_face_ref != gFace_num__car
|
||||
&& (car->box_face_ref != gFace_num__car - 1 || car->box_face_start <= gFace_count)) {
|
||||
car_info = (tCollision_info*)car;
|
||||
|
@ -1081,8 +1116,8 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) {
|
|||
non_car = gActive_non_car_list[i];
|
||||
if (!non_car->collision_info.doing_nothing_flag) {
|
||||
non_car->collision_info.dt = -1.0;
|
||||
if (non_car->collision_info.message.type == 16 && non_car->collision_info.message.time >= gLast_mechanics_time && gLast_mechanics_time + PHYSICS_STEP_TIME >= non_car->collision_info.message.time) {
|
||||
non_car->collision_info.dt = (double)(gLast_mechanics_time + PHYSICS_STEP_TIME - non_car->collision_info.message.time) / 1000.0;
|
||||
if (non_car->collision_info.message.type == 16 && non_car->collision_info.message.time >= gLast_mechanics_time && gLast_mechanics_time + harness_game_config.physics_step_time >= non_car->collision_info.message.time) {
|
||||
non_car->collision_info.dt = (double)(gLast_mechanics_time + harness_game_config.physics_step_time - non_car->collision_info.message.time) / 1000.0;
|
||||
GetNetPos((tCar_spec*)non_car);
|
||||
}
|
||||
if (non_car->collision_info.box_face_ref != gFace_num__car
|
||||
|
@ -1099,8 +1134,8 @@ void ApplyPhysicsToCars(tU32 last_frame_time, tU32 pTime_difference) {
|
|||
old_num_cars = gNum_cars_and_non_cars;
|
||||
CrashCarsTogether(gDt);
|
||||
} while (old_num_cars < gNum_cars_and_non_cars);
|
||||
gMechanics_time_sync -= PHYSICS_STEP_TIME;
|
||||
gLast_mechanics_time += PHYSICS_STEP_TIME;
|
||||
gMechanics_time_sync -= harness_game_config.physics_step_time;
|
||||
gLast_mechanics_time += harness_game_config.physics_step_time;
|
||||
}
|
||||
gMechanics_time_sync = 1;
|
||||
SendCarData(gLast_mechanics_time);
|
||||
|
@ -1180,9 +1215,9 @@ void MoveAndCollideCar(tCar_spec* car, br_scalar dt) {
|
|||
TranslateCar(car_info, dt);
|
||||
CollideCarWithWall(car_info, dt);
|
||||
BrMatrix34ApplyP(&car->pos, &car->cmpos, &car->car_master_actor->t.t.mat);
|
||||
car->pos.v[0] = car->pos.v[0] / 6.9000001;
|
||||
car->pos.v[1] = car->pos.v[1] / 6.9000001;
|
||||
car->pos.v[2] = car->pos.v[2] / 6.9000001;
|
||||
car->pos.v[0] = car->pos.v[0] / WORLD_SCALE;
|
||||
car->pos.v[1] = car->pos.v[1] / WORLD_SCALE;
|
||||
car->pos.v[2] = car->pos.v[2] / WORLD_SCALE;
|
||||
for (wheel = 0; wheel < 4; wheel++) {
|
||||
SkidMark(car, wheel);
|
||||
}
|
||||
|
@ -2318,7 +2353,6 @@ int CollCheck(tCollision_info* c, br_scalar dt) {
|
|||
// v35 = 0;
|
||||
// v36 = 0x3F800000;
|
||||
// v48 = 0x3F800347;
|
||||
|
||||
car_spec = (tCar_spec*)c;
|
||||
mat = &c->car_master_actor->t.t.mat;
|
||||
oldmat = &c->oldmat;
|
||||
|
@ -2349,7 +2383,6 @@ int CollCheck(tCollision_info* c, br_scalar dt) {
|
|||
a1.v[0] = mat->m[3][0] / WORLD_SCALE;
|
||||
a1.v[1] = mat->m[3][1] / WORLD_SCALE;
|
||||
a1.v[2] = mat->m[3][2] / WORLD_SCALE;
|
||||
|
||||
BrMatrix34ApplyV(&aa, &bnds.min, mat);
|
||||
BrVector3Accumulate(&aa, &a1);
|
||||
for (j = 0; j < 3; ++j) {
|
||||
|
@ -2357,9 +2390,7 @@ int CollCheck(tCollision_info* c, br_scalar dt) {
|
|||
edges[j].v[1] = (bnds.max.v[j] - bnds.min.v[j]) * mat->m[j][1];
|
||||
edges[j].v[2] = (bnds.max.v[j] - bnds.min.v[j]) * mat->m[j][2];
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
f_ref = &gFace_list__car[c->box_face_start];
|
||||
while (c->box_face_end - c->box_face_start > i && i < 50) {
|
||||
BrVector3Sub(&bb, &aa, &f_ref->v[0]);
|
||||
|
@ -2489,7 +2520,6 @@ int CollCheck(tCollision_info* c, br_scalar dt) {
|
|||
M.m[i][j] = BrVector3Dot(&n[i], &normal_force);
|
||||
}
|
||||
}
|
||||
|
||||
switch (k) {
|
||||
case 1:
|
||||
ts = SinglePointColl(f, &M, d);
|
||||
|
@ -3015,14 +3045,14 @@ void MultiFindFloorInBoxM(int pNum_rays, br_vector3* a, br_vector3* b, br_vector
|
|||
LOG_TRACE("(%d, %p, %p, %p, %p, %p, %p)", pNum_rays, a, b, nor, d, c, mat_ref);
|
||||
|
||||
for (i = 0; i < pNum_rays; i++) {
|
||||
aa[i].v[0] = a[i].v[0] / 6.9000001;
|
||||
aa[i].v[1] = a[i].v[1] / 6.9000001;
|
||||
aa[i].v[2] = a[i].v[2] / 6.9000001;
|
||||
aa[i].v[0] = a[i].v[0] / WORLD_SCALE;
|
||||
aa[i].v[1] = a[i].v[1] / WORLD_SCALE;
|
||||
aa[i].v[2] = a[i].v[2] / WORLD_SCALE;
|
||||
d[i] = 2.0;
|
||||
}
|
||||
bb.v[0] = b->v[0] / 6.9000001;
|
||||
bb.v[1] = b->v[1] / 6.9000001;
|
||||
bb.v[2] = b->v[2] / 6.9000001;
|
||||
bb.v[0] = b->v[0] / WORLD_SCALE;
|
||||
bb.v[1] = b->v[1] / WORLD_SCALE;
|
||||
bb.v[2] = b->v[2] / WORLD_SCALE;
|
||||
MultiFindFloorInBoxBU(pNum_rays, aa, &bb, nor, d, c, mat_ref);
|
||||
}
|
||||
|
||||
|
@ -3061,12 +3091,12 @@ void findfloor(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d) {
|
|||
br_vector3 bb;
|
||||
LOG_TRACE("(%p, %p, %p, %p)", a, b, nor, d);
|
||||
|
||||
aa.v[0] = a->v[0] / 6.9000001;
|
||||
aa.v[1] = a->v[1] / 6.9000001;
|
||||
aa.v[2] = a->v[2] / 6.9000001;
|
||||
bb.v[0] = b->v[0] / 6.9000001;
|
||||
bb.v[1] = b->v[1] / 6.9000001;
|
||||
bb.v[2] = b->v[2] / 6.9000001;
|
||||
aa.v[0] = a->v[0] / WORLD_SCALE;
|
||||
aa.v[1] = a->v[1] / WORLD_SCALE;
|
||||
aa.v[2] = a->v[2] / WORLD_SCALE;
|
||||
bb.v[0] = b->v[0] / WORLD_SCALE;
|
||||
bb.v[1] = b->v[1] / WORLD_SCALE;
|
||||
bb.v[2] = b->v[2] / WORLD_SCALE;
|
||||
FindFace(&aa, &bb, nor, d, &material);
|
||||
}
|
||||
|
||||
|
@ -3076,12 +3106,12 @@ int FindFloorInBoxM(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d,
|
|||
br_vector3 bb;
|
||||
LOG_TRACE("(%p, %p, %p, %p, %p)", a, b, nor, d, c);
|
||||
|
||||
aa.v[0] = a->v[0] / 6.9000001;
|
||||
aa.v[1] = a->v[1] / 6.9000001;
|
||||
aa.v[2] = a->v[2] / 6.9000001;
|
||||
bb.v[0] = b->v[0] / 6.9000001;
|
||||
bb.v[1] = b->v[1] / 6.9000001;
|
||||
bb.v[2] = b->v[2] / 6.9000001;
|
||||
aa.v[0] = a->v[0] / WORLD_SCALE;
|
||||
aa.v[1] = a->v[1] / WORLD_SCALE;
|
||||
aa.v[2] = a->v[2] / WORLD_SCALE;
|
||||
bb.v[0] = b->v[0] / WORLD_SCALE;
|
||||
bb.v[1] = b->v[1] / WORLD_SCALE;
|
||||
bb.v[2] = b->v[2] / WORLD_SCALE;
|
||||
return FindFloorInBoxBU(&aa, &bb, nor, d, c);
|
||||
}
|
||||
|
||||
|
@ -3170,12 +3200,12 @@ int FindFloorInBoxM2(br_vector3* a, br_vector3* b, br_vector3* nor, br_scalar* d
|
|||
br_vector3 bb;
|
||||
LOG_TRACE("(%p, %p, %p, %p, %p)", a, b, nor, d, c);
|
||||
|
||||
aa.v[0] = a->v[0] / 6.9000001;
|
||||
aa.v[1] = a->v[1] / 6.9000001;
|
||||
aa.v[2] = a->v[2] / 6.9000001;
|
||||
bb.v[0] = b->v[0] / 6.9000001;
|
||||
bb.v[1] = b->v[1] / 6.9000001;
|
||||
bb.v[2] = b->v[2] / 6.9000001;
|
||||
aa.v[0] = a->v[0] / WORLD_SCALE;
|
||||
aa.v[1] = a->v[1] / WORLD_SCALE;
|
||||
aa.v[2] = a->v[2] / WORLD_SCALE;
|
||||
bb.v[0] = b->v[0] / WORLD_SCALE;
|
||||
bb.v[1] = b->v[1] / WORLD_SCALE;
|
||||
bb.v[2] = b->v[2] / WORLD_SCALE;
|
||||
return FindFloorInBoxBU2(&aa, &bb, nor, d, c);
|
||||
}
|
||||
|
||||
|
@ -3241,9 +3271,9 @@ int BoxFaceIntersect(br_bounds* pB, br_matrix34* pM, br_matrix34* pMold, br_vect
|
|||
}
|
||||
}
|
||||
while (n > j) {
|
||||
pPoint_list[j].v[0] = pPoint_list[j].v[0] * 6.9000001;
|
||||
pPoint_list[j].v[1] = pPoint_list[j].v[1] * 6.9000001;
|
||||
pPoint_list[j].v[2] = pPoint_list[j].v[2] * 6.9000001;
|
||||
pPoint_list[j].v[0] = pPoint_list[j].v[0] * WORLD_SCALE;
|
||||
pPoint_list[j].v[1] = pPoint_list[j].v[1] * WORLD_SCALE;
|
||||
pPoint_list[j].v[2] = pPoint_list[j].v[2] * WORLD_SCALE;
|
||||
pPoint_list[j].v[0] = pPoint_list[j].v[0] - c->cmpos.v[0];
|
||||
pPoint_list[j].v[1] = pPoint_list[j].v[1] - c->cmpos.v[1];
|
||||
pPoint_list[j].v[2] = pPoint_list[j].v[2] - c->cmpos.v[2];
|
||||
|
@ -3276,9 +3306,9 @@ int BoxFaceIntersect(br_bounds* pB, br_matrix34* pM, br_matrix34* pMold, br_vect
|
|||
pPoint_list[m].v[2] = pPoint_list[n - 1].v[2];
|
||||
n = m + 1;
|
||||
}
|
||||
pMold->m[3][0] = pMold->m[3][0] * 6.9000001;
|
||||
pMold->m[3][1] = pMold->m[3][1] * 6.9000001;
|
||||
pMold->m[3][2] = pMold->m[3][2] * 6.9000001;
|
||||
pMold->m[3][0] = pMold->m[3][0] * WORLD_SCALE;
|
||||
pMold->m[3][1] = pMold->m[3][1] * WORLD_SCALE;
|
||||
pMold->m[3][2] = pMold->m[3][2] * WORLD_SCALE;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -3605,7 +3635,12 @@ void ToggleCollisionDetection() {
|
|||
// IDA: void __cdecl CancelPendingCunningStunt()
|
||||
void CancelPendingCunningStunt() {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
gQuite_wild_end = 0;
|
||||
gQuite_wild_start = 0;
|
||||
gOn_me_wheels_start = 0;
|
||||
gWoz_upside_down_at_all = 0;
|
||||
gWild_start = 0;
|
||||
}
|
||||
|
||||
// IDA: float __cdecl frac(float pN)
|
||||
|
@ -3703,7 +3738,7 @@ void MungeCarGraphics(tU32 pFrame_period) {
|
|||
for (i = 0; i < oily_count; i++) {
|
||||
GetOilSpillDetails(i, &oily_actor, &oily_size);
|
||||
if (oily_actor) {
|
||||
car_radius = the_car->bounds[1].max.v[2] / 6.9000001 * 1.5;
|
||||
car_radius = the_car->bounds[1].max.v[2] / WORLD_SCALE * 1.5;
|
||||
if (oily_actor->t.t.mat.m[3][0] - oily_size < car_x + car_radius
|
||||
&& oily_actor->t.t.mat.m[3][0] + oily_size > car_x - car_radius
|
||||
&& oily_actor->t.t.mat.m[3][2] - oily_size < car_z + car_radius
|
||||
|
@ -4164,7 +4199,12 @@ void SetUpPanningCamera(tCar_spec* c) {
|
|||
// IDA: void __usercall SaveCameraPosition(int i@<EAX>)
|
||||
void SaveCameraPosition(int i) {
|
||||
LOG_TRACE("(%d)", i);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gSave_camera[i].saved != 1) {
|
||||
gSave_camera[i].zoom = gCamera_zoom;
|
||||
gSave_camera[i].yaw = gCamera_yaw;
|
||||
gSave_camera[i].saved = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall RestoreCameraPosition(int i@<EAX>)
|
||||
|
@ -5171,8 +5211,8 @@ void SetCarSuspGiveAndHeight(tCar_spec* pCar, br_scalar pFront_give_factor, br_s
|
|||
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);
|
||||
|
||||
front_give = pCar->susp_give[1] * pFront_give_factor * 6.9000001;
|
||||
rear_give = pCar->susp_give[0] * pRear_give_factor * 6.9000001;
|
||||
front_give = pCar->susp_give[1] * pFront_give_factor * WORLD_SCALE;
|
||||
rear_give = pCar->susp_give[0] * pRear_give_factor * WORLD_SCALE;
|
||||
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;
|
||||
|
@ -5196,7 +5236,7 @@ void SetCarSuspGiveAndHeight(tCar_spec* pCar, br_scalar pFront_give_factor, br_s
|
|||
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;
|
||||
pCar->bounds[0].min.v[1] = pCar->bounds[0].min.v[1] / WORLD_SCALE;
|
||||
}
|
||||
|
||||
// IDA: int __usercall TestForCarInSensiblePlace@<EAX>(tCar_spec *car@<EAX>)
|
||||
|
@ -5214,7 +5254,70 @@ int TestForCarInSensiblePlace(tCar_spec* car) {
|
|||
br_vector3 tv;
|
||||
br_vector3 tv2;
|
||||
LOG_TRACE("(%p)", car);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
car_info = (tCollision_info*)car;
|
||||
if (!gProgram_state.racing) {
|
||||
return 1;
|
||||
}
|
||||
mat1 = &car_info->car_master_actor->t.t.mat;
|
||||
if (!gDoing_physics) {
|
||||
mat1->m[3][0] = mat1->m[3][0] * WORLD_SCALE;
|
||||
mat1->m[3][1] = mat1->m[3][1] * WORLD_SCALE;
|
||||
mat1->m[3][2] = mat1->m[3][2] * WORLD_SCALE;
|
||||
}
|
||||
GetFacesInBox(car_info);
|
||||
BrMatrix34ApplyP(&car_info->pos, &car_info->cmpos, &car_info->car_master_actor->t.t.mat);
|
||||
car_info->pos.v[0] = car_info->pos.v[0] / WORLD_SCALE;
|
||||
car_info->pos.v[1] = car_info->pos.v[1] / WORLD_SCALE;
|
||||
car_info->pos.v[2] = car_info->pos.v[2] / WORLD_SCALE;
|
||||
k = CollCheck(car_info, -2.0);
|
||||
if (!k) {
|
||||
if (gNum_active_non_cars + gNum_active_cars != gNum_cars_and_non_cars) {
|
||||
GetNonCars();
|
||||
}
|
||||
for (i = 0; i < gNum_cars_and_non_cars; i++) {
|
||||
c2 = (tCollision_info*)gActive_car_list[i];
|
||||
if (car_info != c2) {
|
||||
mat2 = &c2->car_master_actor->t.t.mat;
|
||||
mat2->m[3][0] = mat2->m[3][0] * WORLD_SCALE;
|
||||
mat2->m[3][1] = mat2->m[3][1] * WORLD_SCALE;
|
||||
mat2->m[3][2] = mat2->m[3][2] * WORLD_SCALE;
|
||||
sep.v[0] = mat1->m[3][0] - mat2->m[3][0];
|
||||
sep.v[1] = mat1->m[3][1] - mat2->m[3][1];
|
||||
sep.v[2] = mat1->m[3][2] - mat2->m[3][2];
|
||||
if (BrVector3LengthSquared(&sep) <= 100.0) {
|
||||
k += TestOldMats(car_info, c2, 0);
|
||||
k += TestOldMats(c2, car_info, 0);
|
||||
}
|
||||
if (k) {
|
||||
BrMatrix34ApplyP(&tv, &car_info->cmpos, mat1);
|
||||
BrMatrix34ApplyP(&tv2, &c2->cmpos, mat2);
|
||||
tv.v[0] = tv2.v[0] - tv.v[0];
|
||||
tv.v[1] = tv2.v[1] - tv.v[1];
|
||||
tv.v[2] = tv2.v[2] - tv.v[2];
|
||||
BrMatrix34TApplyV(&car_info->old_point, &tv, &car_info->car_master_actor->t.t.mat);
|
||||
BrVector3Normalise(&car_info->old_norm, &car_info->old_point);
|
||||
BrVector3Negate(&car_info->old_norm, &car_info->old_norm);
|
||||
}
|
||||
mat2->m[3][0] = mat2->m[3][0] / WORLD_SCALE;
|
||||
mat2->m[3][1] = mat2->m[3][1] / WORLD_SCALE;
|
||||
mat2->m[3][2] = mat2->m[3][2] / WORLD_SCALE;
|
||||
if (k) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gDoing_physics) {
|
||||
mat1->m[3][0] = mat1->m[3][0] / WORLD_SCALE;
|
||||
mat1->m[3][1] = mat1->m[3][1] / WORLD_SCALE;
|
||||
mat1->m[3][2] = mat1->m[3][2] / WORLD_SCALE;
|
||||
}
|
||||
if (k) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: int __usercall TestOldMats@<EAX>(tCollision_info *c1@<EAX>, tCollision_info *c2@<EDX>, int newmats@<EBX>)
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
#include "brender/brender.h"
|
||||
#include "car.h"
|
||||
#include "constants.h"
|
||||
#include "crush.h"
|
||||
#include "displays.h"
|
||||
#include "finteray.h"
|
||||
#include "flicplay.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrkm.h"
|
||||
|
@ -15,11 +17,15 @@
|
|||
#include "mainloop.h"
|
||||
#include "netgame.h"
|
||||
#include "network.h"
|
||||
#include "opponent.h"
|
||||
#include "pd/sys.h"
|
||||
#include "pedestrn.h"
|
||||
#include "piping.h"
|
||||
#include "pratcam.h"
|
||||
#include "replay.h"
|
||||
#include "s3/s3sound.h"
|
||||
#include "sound.h"
|
||||
#include "spark.h"
|
||||
#include "structur.h"
|
||||
#include "utility.h"
|
||||
#include "world.h"
|
||||
|
@ -73,7 +79,7 @@ tToggle_element gToggle_array[] = {
|
|||
int gRepair_last_time;
|
||||
int gHad_auto_recover;
|
||||
tU32 gLast_repair_time;
|
||||
tEdit_mode gWhich_edit_mode;
|
||||
tEdit_mode gWhich_edit_mode = eEdit_mode_options;
|
||||
char* gEdit_mode_names[10];
|
||||
tEdit_func* gEdit_funcs[10][18][8];
|
||||
tCheat gKev_keys[44] = {
|
||||
|
@ -123,7 +129,7 @@ tCheat gKev_keys[44] = {
|
|||
};
|
||||
int gAllow_car_flying;
|
||||
int gEntering_message;
|
||||
tU32 gPalette_fade_time;
|
||||
tU32 gPalette_fade_time; // was gRecover_timer
|
||||
char* gAbuse_text[10];
|
||||
char gString[84];
|
||||
int gToo_late;
|
||||
|
@ -618,13 +624,16 @@ int CarWorldOffFallenCheckThingy(tCar_spec* pCar, int pCheck_around) {
|
|||
br_vector3 offset_w;
|
||||
int result;
|
||||
LOG_TRACE("(%p, %d)", pCar, pCheck_around);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB_ONCE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IDA: int __usercall HasCarFallenOffWorld@<EAX>(tCar_spec *pCar@<EAX>)
|
||||
int HasCarFallenOffWorld(tCar_spec* pCar) {
|
||||
LOG_TRACE("(%p)", pCar);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
return CarWorldOffFallenCheckThingy(pCar, 1);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl CheckForBeingOutOfThisWorld()
|
||||
|
@ -633,38 +642,124 @@ void CheckForBeingOutOfThisWorld() {
|
|||
static tU32 sLast_check;
|
||||
int time_step;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
the_time = PDGetTotalTime();
|
||||
|
||||
if (!gRecover_timer || ((gProgram_state.current_car.frame_collision_flag || gProgram_state.current_car.number_of_wheels_on_ground) && !IsCarInTheSea())) {
|
||||
gRecover_timer = 0;
|
||||
if ((the_time - sLast_check) > 200) {
|
||||
sLast_check = the_time;
|
||||
if (HasCarFallenOffWorld(&gProgram_state.current_car)) {
|
||||
gRecover_timer = 3000;
|
||||
}
|
||||
}
|
||||
if (IsCarInTheSea()) {
|
||||
if (!gRecover_timer) {
|
||||
gRecover_timer = 3000;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
gRecover_timer -= gFrame_period;
|
||||
if (gRecover_timer <= 0 || IsCarInTheSea() == 2) {
|
||||
gRecover_timer = 0;
|
||||
RecoverCar();
|
||||
gHad_auto_recover = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall CheckHornLocal(tCar_spec *pCar@<EAX>)
|
||||
void CheckHornLocal(tCar_spec* pCar) {
|
||||
LOG_TRACE("(%p)", pCar);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB_ONCE();
|
||||
}
|
||||
|
||||
// IDA: void __usercall CheckHorn3D(tCar_spec *pCar@<EAX>)
|
||||
void CheckHorn3D(tCar_spec* pCar) {
|
||||
LOG_TRACE("(%p)", pCar);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB_ONCE();
|
||||
}
|
||||
|
||||
// IDA: void __cdecl CheckHorns()
|
||||
void CheckHorns() {
|
||||
int i;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gNet_mode) {
|
||||
for (i = 0; i < gNumber_of_net_players; ++i) {
|
||||
CheckHorn3D(gNet_players[i].car);
|
||||
}
|
||||
} else {
|
||||
CheckHornLocal(&gProgram_state.current_car);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl SetRecovery()
|
||||
void SetRecovery() {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gRace_finished
|
||||
|| gProgram_state.current_car.knackered
|
||||
|| gWait_for_it
|
||||
|| gHad_auto_recover
|
||||
|| gPalette_fade_time) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gNet_mode == eNet_mode_none) {
|
||||
gRecover_car = 1;
|
||||
gRecover_timer = 0;
|
||||
return;
|
||||
}
|
||||
if (gProgram_state.current_car.time_to_recover) {
|
||||
if (GetRaceTime() + 600 >= gProgram_state.current_car.time_to_recover) {
|
||||
NewTextHeadupSlot2(4, 0, 2000, -4, GetMiscString(242), 1);
|
||||
gToo_late = 1;
|
||||
} else {
|
||||
gProgram_state.current_car.time_to_recover = 0;
|
||||
NewTextHeadupSlot2(4, 0, 2000, -4, GetMiscString(125), 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!CheckRecoverCost()) {
|
||||
return;
|
||||
}
|
||||
if (gCurrent_net_game->type == eNet_game_type_foxy) {
|
||||
if (gThis_net_player_index == gIt_or_fox) {
|
||||
gProgram_state.current_car.time_to_recover = GetRaceTime() + 5000;
|
||||
gRecover_timer = 0;
|
||||
gToo_late = 0;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (gCurrent_net_game->type != eNet_game_type_tag) {
|
||||
gProgram_state.current_car.time_to_recover = GetRaceTime() + 3000;
|
||||
gRecover_timer = 0;
|
||||
gToo_late = 0;
|
||||
return;
|
||||
}
|
||||
if (gThis_net_player_index != gIt_or_fox) {
|
||||
gProgram_state.current_car.time_to_recover = GetRaceTime() + 5000;
|
||||
gRecover_timer = 0;
|
||||
gToo_late = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
gProgram_state.current_car.time_to_recover = GetRaceTime() + 1000;
|
||||
gRecover_timer = 0;
|
||||
gToo_late = 0;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl RecoverCar()
|
||||
void RecoverCar() {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gNet_mode == eNet_mode_none || !gPalette_fade_time) {
|
||||
gRecover_car = 1;
|
||||
}
|
||||
gProgram_state.current_car.time_to_recover = 0;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl CheckMapRenderMove()
|
||||
|
@ -674,7 +769,8 @@ void CheckMapRenderMove() {
|
|||
float old_x;
|
||||
float old_y;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB_ONCE();
|
||||
}
|
||||
|
||||
// IDA: void __usercall ExplodeCar(tCar_spec *pCar@<EAX>)
|
||||
|
@ -691,14 +787,47 @@ void CheckRecoveryOfCars(tU32 pEndFrameTime) {
|
|||
int time;
|
||||
char s[256];
|
||||
LOG_TRACE("(%d)", pEndFrameTime);
|
||||
STUB_ONCE();
|
||||
|
||||
if (gProgram_state.current_car.time_to_recover) {
|
||||
if (gProgram_state.current_car.knackered) {
|
||||
gProgram_state.current_car.time_to_recover = 0;
|
||||
} else {
|
||||
time = (gProgram_state.current_car.time_to_recover - pEndFrameTime + 1000) / 1000;
|
||||
sprintf(s, "%s %d %s", GetMiscString(97), time, time > 1 ? GetMiscString(99) : GetMiscString(98));
|
||||
if (!gToo_late) {
|
||||
NewTextHeadupSlot2(4, 0, 2000, -4, s, 0);
|
||||
}
|
||||
if (gProgram_state.current_car.time_to_recover <= pEndFrameTime) {
|
||||
RecoverCar();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gNet_mode) {
|
||||
for (i = 0; i < gNumber_of_net_players; i++) {
|
||||
if (gThis_net_player_index != i && gNet_players[i].car->time_to_recover && gNet_players[i].car->time_to_recover <= pEndFrameTime) {
|
||||
gNet_players[i].player_status = ePlayer_status_recovering;
|
||||
gNet_players[i].car->message.type = 32;
|
||||
gNet_players[i].car->message.time = pEndFrameTime;
|
||||
ExplodeCar(gNet_players[i].car);
|
||||
gNet_players[i].car->time_to_recover = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall LoseSomePSPowerups(int pNumber@<EAX>)
|
||||
void LoseSomePSPowerups(int pNumber) {
|
||||
int index;
|
||||
LOG_TRACE("(%d)", pNumber);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gNet_mode && pNumber > 0) {
|
||||
while (pNumber--) {
|
||||
index = IRandomBetween(0, 2);
|
||||
if (gProgram_state.current_car.power_up_levels[index]) {
|
||||
gProgram_state.current_car.power_up_levels[index]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl CheckOtherRacingKeys()
|
||||
|
@ -722,13 +851,158 @@ void CheckOtherRacingKeys() {
|
|||
static int stopped_repairing;
|
||||
LOG_TRACE("()");
|
||||
|
||||
STUB_ONCE();
|
||||
car = GetCarSpec(eVehicle_self, 0);
|
||||
CheckMapRenderMove();
|
||||
CheckHorns();
|
||||
CheckForBeingOutOfThisWorld();
|
||||
if (gPalette_fade_time) {
|
||||
SortOutRecover(car);
|
||||
} else if (gNet_mode && NetGetPlayerStatus() == ePlayer_status_recovering) {
|
||||
NetPlayerStatusChanged(ePlayer_status_racing);
|
||||
}
|
||||
if ((!gAuto_repair && !KeyIsDown(44))
|
||||
|| gRace_finished
|
||||
|| gProgram_state.current_car.knackered
|
||||
|| gWait_for_it
|
||||
|| gEntering_message) {
|
||||
gRepair_last_time = 0;
|
||||
stopped_repairing = 0;
|
||||
total_repair_cost = 0;
|
||||
total_difference = 0;
|
||||
if (sound_tag) {
|
||||
for (i = 0; i < 10 && S3SoundStillPlaying(sound_tag); ++i) {
|
||||
DRS3StopSound(sound_tag);
|
||||
}
|
||||
sound_tag = 0;
|
||||
}
|
||||
} else {
|
||||
if (!gAuto_repair && !gRepair_last_time && GetTotalTime() - gLast_repair_time < 1200) {
|
||||
gAuto_repair = 1;
|
||||
}
|
||||
gLast_repair_time = GetTotalTime();
|
||||
gRepair_last_time = 1;
|
||||
if (!NeedToExpandBoundingBox) {
|
||||
if (gFree_repairs
|
||||
|| gNet_mode == eNet_mode_none
|
||||
|| gProgram_state.credits_earned - gProgram_state.credits_lost >= 1) {
|
||||
bodywork_repair_amount = RepairCar(gProgram_state.current_car.car_ID, gFrame_period, &amount);
|
||||
NeedToExpandBoundingBox = bodywork_repair_amount > 0;
|
||||
cost = 0;
|
||||
for (j = 0; j < COUNT_OF(gProgram_state.current_car.damage_units); j++) {
|
||||
old_level = gProgram_state.current_car.damage_units[j].damage_level;
|
||||
if (amount == 0.0) {
|
||||
new_level = 0;
|
||||
} else {
|
||||
new_level = ((double)gProgram_state.current_car.damage_units[j].damage_level
|
||||
- floor(bodywork_repair_amount / amount * (double)gProgram_state.current_car.damage_units[j].damage_level));
|
||||
}
|
||||
if (new_level >= 0) {
|
||||
if (new_level < 100) {
|
||||
gProgram_state.current_car.damage_units[j].damage_level = new_level;
|
||||
} else {
|
||||
gProgram_state.current_car.damage_units[j].damage_level = 99;
|
||||
}
|
||||
} else {
|
||||
gProgram_state.current_car.damage_units[j].damage_level = 0;
|
||||
}
|
||||
gProgram_state.current_car.damage_units[j].smoke_last_level = gProgram_state.current_car.damage_units[j].damage_level;
|
||||
if (gNet_mode) {
|
||||
ts = gNet_repair_cost[gCurrent_net_game->type];
|
||||
} else {
|
||||
ts = gRepair_cost[gProgram_state.skill_level];
|
||||
}
|
||||
cost = (old_level - gProgram_state.current_car.damage_units[j].damage_level) * ts + cost;
|
||||
total_difference += old_level - new_level;
|
||||
}
|
||||
if (!gFree_repairs) {
|
||||
LoseSomePSPowerups(total_difference / 100);
|
||||
}
|
||||
total_difference %= 100;
|
||||
cost = 10 * (cost / 10);
|
||||
if (((!total_repair_cost && cost) || bodywork_repair_amount != 0.0) && !sound_tag) {
|
||||
sound_tag = DRS3StartSound(gIndexed_outlets[1], 5200);
|
||||
}
|
||||
if (gProgram_state.current_car.num_smoke_columns) {
|
||||
StopCarSmoking(&gProgram_state.current_car);
|
||||
}
|
||||
if (!cost && bodywork_repair_amount == 0.0) {
|
||||
gAuto_repair = 0;
|
||||
}
|
||||
if (!gFree_repairs) {
|
||||
cost += SpendCredits(cost);
|
||||
}
|
||||
total_repair_cost += cost;
|
||||
if (total_repair_cost) {
|
||||
if (gFree_repairs) {
|
||||
NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(4));
|
||||
} else {
|
||||
sprintf(s, "%s %d", GetMiscString(5), total_repair_cost);
|
||||
NewTextHeadupSlot(4, 0, 1000, -4, s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!stopped_repairing) {
|
||||
NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(95));
|
||||
}
|
||||
gAuto_repair = 0;
|
||||
stopped_repairing = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NeedToExpandBoundingBox) {
|
||||
NeedToExpandBoundingBox = ExpandBoundingBox(&gProgram_state.current_car) == 0;
|
||||
}
|
||||
if (!gRecover_car || gProgram_state.current_car.knackered) {
|
||||
gHad_auto_recover = 0;
|
||||
} else if (CheckRecoverCost()) {
|
||||
gRecover_timer = 0;
|
||||
SetFlipUpCar(car);
|
||||
if (gNet_mode) {
|
||||
NewTextHeadupSlot(4, 0, 1500, -4, " ");
|
||||
}
|
||||
if (gRecovery_voucher_count) {
|
||||
gRecovery_voucher_count--;
|
||||
sprintf(s, "%s", GetMiscString(48));
|
||||
NewTextHeadupSlot(4, 0, 1500, -4, s);
|
||||
} else {
|
||||
if (gNet_mode) {
|
||||
cost = gNet_recovery_cost[gCurrent_net_game->type];
|
||||
} else {
|
||||
cost = gRecovery_cost[gProgram_state.skill_level];
|
||||
}
|
||||
SpendCredits(cost);
|
||||
if (gNet_mode) {
|
||||
cost = gNet_recovery_cost[gCurrent_net_game->type];
|
||||
} else {
|
||||
cost = gRecovery_cost[gProgram_state.skill_level];
|
||||
}
|
||||
sprintf(s, "%s %d", GetMiscString(7), cost);
|
||||
NewTextHeadupSlot(4, 0, 1500, -4, s);
|
||||
LoseSomePSPowerups(2);
|
||||
}
|
||||
CancelPendingCunningStunt();
|
||||
PipeSingleSpecial(ePipe_special_fade);
|
||||
}
|
||||
gRecover_car = 0;
|
||||
}
|
||||
|
||||
// IDA: int __cdecl CheckRecoverCost()
|
||||
int CheckRecoverCost() {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gProgram_state.current_car.knackered
|
||||
|| gNet_mode == eNet_mode_none
|
||||
|| (gProgram_state.credits_earned - gProgram_state.credits_lost) >= gNet_recovery_cost[gCurrent_net_game->type]
|
||||
|| gRecovery_voucher_count) {
|
||||
return 1;
|
||||
}
|
||||
gProgram_state.credits_earned = 0;
|
||||
gProgram_state.credits_lost = 0;
|
||||
NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(96));
|
||||
DoFancyHeadup(18);
|
||||
KnackerThisCar(&gProgram_state.current_car);
|
||||
SendGameplayToHost(eNet_gameplay_suicide, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IDA: void __usercall SortOutRecover(tCar_spec *pCar@<EAX>)
|
||||
|
@ -743,7 +1017,14 @@ void SortOutRecover(tCar_spec* pCar) {
|
|||
// IDA: void __usercall SetFlipUpCar(tCar_spec *pCar@<EAX>)
|
||||
void SetFlipUpCar(tCar_spec* pCar) {
|
||||
LOG_TRACE("(%p)", pCar);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gNet_mode && pCar->driver == eDriver_local_human) {
|
||||
DisableCar(pCar);
|
||||
gPalette_fade_time = GetRaceTime();
|
||||
NetPlayerStatusChanged(ePlayer_status_recovering);
|
||||
} else {
|
||||
FlipUpCar(pCar);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall FlipUpCar(tCar_spec *car@<EAX>)
|
||||
|
@ -759,7 +1040,97 @@ void FlipUpCar(tCar_spec* car) {
|
|||
br_material* material;
|
||||
br_scalar t;
|
||||
LOG_TRACE("(%p)", car);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
count = 0;
|
||||
if (car->driver == eDriver_local_human && gNet_mode == eNet_mode_none) {
|
||||
FadePaletteDown();
|
||||
while (KeyIsDown(44)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
car->doing_nothing_flag = 0;
|
||||
EnableCar(car);
|
||||
new_pos = 1;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (car->susp_height[i >> 1] <= car->oldd[i]) {
|
||||
new_pos = 0;
|
||||
}
|
||||
}
|
||||
do {
|
||||
tv.v[0] = car->car_master_actor->t.t.mat.m[3][0] - car->last_safe_positions[0].m[3][0];
|
||||
tv.v[1] = car->car_master_actor->t.t.mat.m[3][1] - car->last_safe_positions[0].m[3][1];
|
||||
tv.v[2] = car->car_master_actor->t.t.mat.m[3][2] - car->last_safe_positions[0].m[3][2];
|
||||
if (BrVector3LengthSquared(&tv) > 8.3015966) {
|
||||
new_pos = 0;
|
||||
}
|
||||
BrMatrix34Copy(&car->car_master_actor->t.t.mat, &car->last_safe_positions[new_pos]);
|
||||
BrMatrix34Copy(&car->oldmat, &car->last_safe_positions[new_pos]);
|
||||
BrMatrix34Copy(&car->old_frame_mat, &car->oldmat);
|
||||
car->oldmat.m[3][0] = car->oldmat.m[3][0] * WORLD_SCALE;
|
||||
car->oldmat.m[3][1] = car->oldmat.m[3][1] * WORLD_SCALE;
|
||||
car->oldmat.m[3][2] = car->oldmat.m[3][2] * WORLD_SCALE;
|
||||
dir.v[0] = 0.0;
|
||||
dir.v[1] = 0.28985506;
|
||||
dir.v[2] = 0.0;
|
||||
FindFace(&car->car_master_actor->t.t.euler.t, &dir, &tv, &t, &material);
|
||||
if (t > 1.0) {
|
||||
car->car_master_actor->t.t.mat.m[3][0] += dir.v[0];
|
||||
car->car_master_actor->t.t.mat.m[3][1] += dir.v[1];
|
||||
car->car_master_actor->t.t.mat.m[3][2] += dir.v[2];
|
||||
car->oldmat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] * WORLD_SCALE;
|
||||
car->oldmat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] * WORLD_SCALE;
|
||||
car->oldmat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] * WORLD_SCALE;
|
||||
car->old_frame_mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0];
|
||||
car->old_frame_mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1];
|
||||
car->old_frame_mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2];
|
||||
}
|
||||
tv.v[0] = 0.0;
|
||||
tv.v[1] = 0.0;
|
||||
tv.v[2] = -0.001;
|
||||
BrMatrix34ApplyV(&car->v, &tv, &car->car_master_actor->t.t.mat);
|
||||
car->omega.v[0] = 0.0;
|
||||
car->omega.v[1] = 0.0;
|
||||
car->omega.v[2] = 0.0;
|
||||
car->direction.v[0] = -car->oldmat.m[2][0];
|
||||
car->direction.v[1] = -car->oldmat.m[2][1];
|
||||
car->direction.v[2] = -car->oldmat.m[2][2];
|
||||
for (i = 0; i <= new_pos; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
BrMatrix34Copy(&car->last_safe_positions[j], &car->last_safe_positions[j + 1]);
|
||||
}
|
||||
}
|
||||
for (l = 0; l < 10; l++) {
|
||||
BrVector3Scale(&car->old_norm, &car->old_norm, 0.072463766);
|
||||
BrMatrix34ApplyV(&tv, &car->old_norm, &car->car_master_actor->t.t.mat);
|
||||
car->car_master_actor->t.t.mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] + tv.v[0];
|
||||
car->car_master_actor->t.t.mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] + tv.v[1];
|
||||
car->car_master_actor->t.t.mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] + tv.v[2];
|
||||
car->oldmat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] * WORLD_SCALE;
|
||||
car->oldmat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] * WORLD_SCALE;
|
||||
car->oldmat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] * WORLD_SCALE;
|
||||
car->old_frame_mat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0];
|
||||
car->old_frame_mat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1];
|
||||
car->old_frame_mat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2];
|
||||
if (TestForCarInSensiblePlace(car)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
} while (l == 10 && count < 3);
|
||||
car->oldmat.m[3][0] = car->car_master_actor->t.t.mat.m[3][0] * WORLD_SCALE;
|
||||
car->oldmat.m[3][1] = car->car_master_actor->t.t.mat.m[3][1] * WORLD_SCALE;
|
||||
car->oldmat.m[3][2] = car->car_master_actor->t.t.mat.m[3][2] * WORLD_SCALE;
|
||||
car->curvature = 0.0;
|
||||
for (j = 0; j < 4; ++j) {
|
||||
car->oldd[j] = car->ride_height;
|
||||
}
|
||||
car->revs = 0.0;
|
||||
car->gear = 0;
|
||||
car->auto_special_volume = 0;
|
||||
if (car->driver == eDriver_local_human) {
|
||||
InitialiseExternalCamera();
|
||||
PositionExternalCamera(car, 100u);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall GetPowerup(int pNum@<EAX>)
|
||||
|
@ -1068,6 +1439,8 @@ void ToggleArrow() {
|
|||
static br_actor* old_actor;
|
||||
LOG_TRACE("()");
|
||||
|
||||
return;
|
||||
|
||||
if (gArrow_mode) {
|
||||
gProgram_state.current_car.car_model_actors[gProgram_state.current_car.principal_car_actor].actor = old_actor;
|
||||
BrActorRemove(gArrow_actor);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "crush.h"
|
||||
#include "brender/brender.h"
|
||||
#include "globvars.h"
|
||||
#include "harness/trace.h"
|
||||
#include "loading.h"
|
||||
#include "utility.h"
|
||||
|
@ -215,7 +216,10 @@ void TotallyRepairACar(tCar_spec* pCar) {
|
|||
// IDA: void __cdecl TotallyRepairCar()
|
||||
void TotallyRepairCar() {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (!gArrow_mode) {
|
||||
TotallyRepairACar(&gProgram_state.current_car);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl CheckLastCar()
|
||||
|
|
|
@ -165,7 +165,24 @@ void DoEndRaceAnimation() {
|
|||
int made_a_profit;
|
||||
int went_up_a_rank;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
made_a_profit = gProgram_state.credits_earned > gProgram_state.credits_lost;
|
||||
went_up_a_rank = gProgram_state.credits_earned > gProgram_state.credits_per_rank;
|
||||
|
||||
FadePaletteDown();
|
||||
|
||||
if (gAusterity_mode || gNet_mode) {
|
||||
return;
|
||||
}
|
||||
if (gProgram_state.credits + gProgram_state.credits_earned - gProgram_state.credits_lost >= 0) {
|
||||
if (!made_a_profit && !went_up_a_rank) {
|
||||
PlaySmackerFile("UNSUCSES.SMK");
|
||||
} else if (!made_a_profit || !went_up_a_rank) {
|
||||
PlaySmackerFile("MUNDANE.SMK");
|
||||
} else {
|
||||
PlaySmackerFile("SUCCESS.SMK");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl DoGameOverAnimation()
|
||||
|
|
|
@ -1176,7 +1176,19 @@ void EarnCredits(int pAmount) {
|
|||
int SpendCredits(int pAmount) {
|
||||
int amount;
|
||||
LOG_TRACE("(%d)", pAmount);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
LOG_DEBUG("spending");
|
||||
|
||||
gProgram_state.credits_lost += pAmount;
|
||||
if (gNet_mode == eNet_mode_none) {
|
||||
return 0;
|
||||
}
|
||||
amount = gProgram_state.credits_earned - gProgram_state.credits_lost;
|
||||
if (gProgram_state.credits_earned - gProgram_state.credits_lost >= 0) {
|
||||
return 0;
|
||||
}
|
||||
gProgram_state.credits_lost = gProgram_state.credits_earned;
|
||||
return amount;
|
||||
}
|
||||
|
||||
// IDA: void __usercall AwardTime(tU32 pTime@<EAX>)
|
||||
|
|
|
@ -584,6 +584,7 @@ void PlayFlicsInDarkness() {
|
|||
void ReilluminateFlics() {
|
||||
LOG_TRACE("()");
|
||||
gDark_mode = 0;
|
||||
FadePaletteUp();
|
||||
}
|
||||
|
||||
// IDA: void __cdecl TurnFlicTransparencyOn()
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "globvars.h"
|
||||
#include "globvrpb.h"
|
||||
#include "grafdata.h"
|
||||
#include "harness/hooks.h"
|
||||
#include "harness/trace.h"
|
||||
#include "init.h"
|
||||
#include "loading.h"
|
||||
|
@ -882,7 +883,6 @@ void RenderAFrame(int pDepth_mask_on) {
|
|||
static int frame_counter;
|
||||
|
||||
frame_counter++;
|
||||
//LOG_DEBUG("%d", frame_counter);
|
||||
|
||||
gRender_screen->pixels = gBack_screen->pixels;
|
||||
the_time = GetTotalTime();
|
||||
|
@ -1184,7 +1184,7 @@ void RenderAFrame(int pDepth_mask_on) {
|
|||
PipeFrameFinish();
|
||||
}
|
||||
gRender_screen->pixels = old_pixels;
|
||||
if (!gRecover_timer || GetRaceTime() > gRecover_timer + 500) {
|
||||
if (!gPalette_fade_time || GetRaceTime() > gPalette_fade_time + 500) {
|
||||
PDScreenBufferSwap(0);
|
||||
}
|
||||
if (gAction_replay_mode) {
|
||||
|
@ -1238,7 +1238,7 @@ void ResetPalette() {
|
|||
// IDA: void __usercall Darken(tU8 *pPtr@<EAX>, unsigned int pDarken_amount@<EDX>)
|
||||
void Darken(tU8* pPtr, unsigned int pDarken_amount) {
|
||||
unsigned int value;
|
||||
//LOG_TRACE("(%p, %d)", pPtr, pDarken_amount);
|
||||
LOG_TRACE10("(%p, %d)", pPtr, pDarken_amount);
|
||||
|
||||
*pPtr = (pDarken_amount * *pPtr) / 256;
|
||||
}
|
||||
|
@ -1247,9 +1247,11 @@ void Darken(tU8* pPtr, unsigned int pDarken_amount) {
|
|||
void SetFadedPalette(int pDegree) {
|
||||
int j;
|
||||
br_pixelmap* the_palette;
|
||||
unsigned char* the_pixels; //Jeff added unsigned
|
||||
char* the_pixels;
|
||||
LOG_TRACE10("(%d)", pDegree);
|
||||
|
||||
Harness_Hook_SetFadedPalette(pDegree);
|
||||
|
||||
memcpy(gScratch_pixels, gCurrent_palette->pixels, 0x400u);
|
||||
for (j = 0; j < 256; j++) {
|
||||
Darken((tU8*)&gScratch_pixels[4 * j], pDegree);
|
||||
|
@ -1265,6 +1267,7 @@ void FadePaletteDown() {
|
|||
int i;
|
||||
int start_time;
|
||||
int the_time;
|
||||
LOG_TRACE("()");
|
||||
|
||||
if (!gFaded_palette) {
|
||||
gFaded_palette = 1;
|
||||
|
@ -1289,6 +1292,7 @@ void FadePaletteUp() {
|
|||
int i;
|
||||
int start_time;
|
||||
int the_time;
|
||||
LOG_TRACE("()");
|
||||
|
||||
if (gFaded_palette) {
|
||||
gFaded_palette = 0;
|
||||
|
@ -2019,7 +2023,8 @@ void SaveShadeTables() {
|
|||
void DisposeSavedShadeTables() {
|
||||
int i;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
// IDA: void __cdecl ShadowMode()
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "opponent.h"
|
||||
#include "pd/sys.h"
|
||||
#include "pedestrn.h"
|
||||
#include "piping.h"
|
||||
#include "powerup.h"
|
||||
#include "pratcam.h"
|
||||
#include "raycast.h"
|
||||
|
@ -483,7 +484,8 @@ void LoadInTrack() {
|
|||
// IDA: void __cdecl DisposeTrack()
|
||||
void DisposeTrack() {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
FreeTrack(&gProgram_state.track_spec);
|
||||
}
|
||||
|
||||
// IDA: void __usercall CopyMaterialColourFromIndex(br_material *pMaterial@<EAX>)
|
||||
|
@ -614,7 +616,33 @@ void InitRace() {
|
|||
// IDA: void __cdecl DisposeRace()
|
||||
void DisposeRace() {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
PossibleService();
|
||||
DisposePiping();
|
||||
PossibleService();
|
||||
CloseDownPowerUps();
|
||||
PossibleService();
|
||||
if (!TranslationMode()) {
|
||||
DisposeFont(1);
|
||||
DisposeFont(2);
|
||||
DisposeFont(3);
|
||||
}
|
||||
PossibleService();
|
||||
DisposeFont(6);
|
||||
DisposeFont(7);
|
||||
DisposeFont(8);
|
||||
DisposeFont(4);
|
||||
DisposeFont(5);
|
||||
PossibleService();
|
||||
DisposeSavedShadeTables();
|
||||
PossibleService();
|
||||
DisposeSoundSources();
|
||||
PossibleService();
|
||||
DisposeOpponents();
|
||||
PossibleService();
|
||||
DisposePedestrians();
|
||||
PossibleService();
|
||||
DisposePratcam();
|
||||
PossibleService();
|
||||
}
|
||||
|
||||
// IDA: int __cdecl GetScreenSize()
|
||||
|
|
|
@ -1103,7 +1103,6 @@ void ReadMechanicsData(FILE* pF, tCar_spec* c) {
|
|||
LOG_TRACE("(%p, %p)", pF, c);
|
||||
|
||||
GetALineAndDontArgue(pF, s);
|
||||
LOG_DEBUG("s %s", s);
|
||||
for (i = strlen(s) - 1; s[i] == ' '; --i) {
|
||||
;
|
||||
}
|
||||
|
@ -1185,7 +1184,6 @@ void ReadMechanicsData(FILE* pF, tCar_spec* c) {
|
|||
c->mu[1] *= sqrt((c->wpos[0].v[2] - c->cmpos.v[2]) / (c->wpos[0].v[2] - c->wpos[2].v[2]) * (c->M * 5.0));
|
||||
c->mu[2] *= sqrt((c->wpos[2].v[2] - c->cmpos.v[2]) / (c->wpos[2].v[2] - c->wpos[0].v[2]) * (c->M * 5.0));
|
||||
|
||||
LOG_DEBUG("%f %f %f", c->mu[0], c->mu[1], c->mu[2]);
|
||||
for (i = 0; i < 4; ++i) {
|
||||
c->wpos[i].v[1] = c->ride_height;
|
||||
}
|
||||
|
@ -2094,7 +2092,7 @@ void LoadHeadupImages() {
|
|||
tPath_name the_path;
|
||||
LOG_TRACE("()");
|
||||
|
||||
for (i = 0; i < 31; ++i) {
|
||||
for (i = 0; i < COUNT_OF(gHeadup_image_info); i++) {
|
||||
PossibleService();
|
||||
if (gHeadup_image_info[i].avail && (gHeadup_image_info[i].avail != eNot_net || gNet_mode) && (gHeadup_image_info[i].avail != eNet_only || !gNet_mode)) {
|
||||
gHeadup_images[i] = NULL;
|
||||
|
@ -2829,7 +2827,17 @@ void LoadOpponentsCars(tRace_info* pRace_info) {
|
|||
void DisposeOpponentsCars(tRace_info* pRace_info) {
|
||||
int i;
|
||||
LOG_TRACE("(%p)", pRace_info);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
for (i = 0; i < pRace_info->number_of_racers; i++) {
|
||||
PossibleService();
|
||||
if (pRace_info->opponent_list[i].index >= 0) {
|
||||
if (pRace_info->opponent_list[i].car_spec) {
|
||||
DisposeCar(pRace_info->opponent_list[i].car_spec, pRace_info->opponent_list[i].index);
|
||||
BrMemFree(pRace_info->opponent_list[i].car_spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
ClearOutStorageSpace(&gTheir_cars_storage_space);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl LoadMiscStrings()
|
||||
|
@ -3045,7 +3053,7 @@ int TestForOriginalCarmaCDinDrive() {
|
|||
int paths_txt_first_char;
|
||||
|
||||
// Jeff: Added to optionally bypass this check
|
||||
if (harness_disable_cd_check) {
|
||||
if (harness_game_config.disable_cd_check) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "globvrpb.h"
|
||||
#include "graphics.h"
|
||||
#include "harness/config.h"
|
||||
#include "harness/hooks.h"
|
||||
#include "harness/trace.h"
|
||||
#include "input.h"
|
||||
#include "main.h"
|
||||
|
@ -389,9 +390,6 @@ void UpdateFramePeriod(tU32* pCamera_period) {
|
|||
} else {
|
||||
*pCamera_period = 10;
|
||||
}
|
||||
|
||||
// todo: FPS limiter
|
||||
//usleep(40 * 1000);
|
||||
}
|
||||
|
||||
// IDA: tU32 __cdecl GetLastTickCount()
|
||||
|
@ -506,8 +504,6 @@ tRace_result MainGameLoop() {
|
|||
ForceRebuildActiveCarList();
|
||||
PrintMemoryDump(0, "ABOUT TO ENTER MAINLOOP");
|
||||
|
||||
double last_time = GetTotalTime() / 1000.0;
|
||||
|
||||
do {
|
||||
frame_start_time = GetTotalTime();
|
||||
CyclePollKeys();
|
||||
|
@ -582,15 +578,16 @@ tRace_result MainGameLoop() {
|
|||
CheckReplayTurnOn();
|
||||
if (!gRecover_car
|
||||
&& gProgram_state.prog_status == eProg_game_ongoing
|
||||
&& !gRecover_timer
|
||||
&& !gPalette_fade_time
|
||||
&& (gNet_mode == eNet_mode_none
|
||||
|| !gAction_replay_mode
|
||||
|| gProgram_state.current_car.car_master_actor->t.t.mat.m[3][0] < 500.0)) {
|
||||
|
||||
EnsureRenderPalette();
|
||||
EnsurePaletteUp();
|
||||
}
|
||||
DoNetGameManagement();
|
||||
if (KeyIsDown(0) && !gEntering_message) {
|
||||
if (KeyIsDown(KEYMAP_ESCAPE) && !gEntering_message) {
|
||||
WaitForNoKeys();
|
||||
if (gAction_replay_mode) {
|
||||
ToggleReplay();
|
||||
|
@ -625,15 +622,7 @@ tRace_result MainGameLoop() {
|
|||
gAbandon_game = 0;
|
||||
}
|
||||
|
||||
// Added to lock framerate to 30fps. Seems to help physics be less twitchy...
|
||||
double secs = GetTotalTime();
|
||||
//LOG_DEBUG("timediff %f", secs - (last_time + (1.0 / 30.0)));
|
||||
// while (secs < last_time + (1.0 / 30.0) * 1000) {
|
||||
// //LOG_DEBUG("skipping time...");
|
||||
// secs = GetTotalTime();
|
||||
// }
|
||||
//usleep(50 * 1000);
|
||||
//last_time += (1.0 / 30.0) * 1000;
|
||||
Harness_Hook_MainGameLoop();
|
||||
|
||||
} while (gProgram_state.prog_status == eProg_game_ongoing
|
||||
&& !MungeRaceFinished()
|
||||
|
|
|
@ -538,44 +538,43 @@ int DoVerifyQuit(int pReplace_background) {
|
|||
// IDA: tMM_result __usercall DoMainMenu@<EAX>(tU32 pTime_out@<EAX>, int pSave_allowed@<EDX>, int pContinue_allowed@<EBX>)
|
||||
tMM_result DoMainMenu(tU32 pTime_out, int pSave_allowed, int pContinue_allowed) {
|
||||
tMM_result the_result;
|
||||
LOG_TRACE("(%d, %d, %d)", pTime_out, pSave_allowed, pContinue_allowed);
|
||||
|
||||
if (gProgram_state.racing) {
|
||||
FadePaletteDown(pTime_out);
|
||||
FadePaletteDown();
|
||||
}
|
||||
the_result = GetMainMenuOption(pTime_out, pContinue_allowed);
|
||||
switch (the_result) {
|
||||
case eMM_end_game:
|
||||
if (!gNet_mode) {
|
||||
break;
|
||||
if (gNet_mode) {
|
||||
gProgram_state.prog_status = eProg_idling;
|
||||
}
|
||||
gProgram_state.prog_status = eProg_idling;
|
||||
break;
|
||||
case eMM_1_start:
|
||||
if (pContinue_allowed || gAusterity_mode) {
|
||||
PlayFlicsFromMemory();
|
||||
}
|
||||
if (!DoOnePlayerStart()) {
|
||||
the_result = 0;
|
||||
the_result = eMM_none;
|
||||
}
|
||||
if (!pContinue_allowed && !gAusterity_mode) {
|
||||
break;
|
||||
if (pContinue_allowed || gAusterity_mode) {
|
||||
PlayFlicsFromDisk();
|
||||
}
|
||||
PlayFlicsFromDisk();
|
||||
break;
|
||||
case eMM_n_start:
|
||||
if (DoMultiPlayerStart()) {
|
||||
break;
|
||||
if (!DoMultiPlayerStart()) {
|
||||
LoadRaces(gRace_list, &gNumber_of_races, -1);
|
||||
the_result = eMM_none;
|
||||
}
|
||||
LoadRaces(gRace_list, &gNumber_of_races, -1);
|
||||
the_result = 0;
|
||||
break;
|
||||
case eMM_loaded:
|
||||
if (!DoLoadGame(the_result)) {
|
||||
the_result = 0;
|
||||
if (!DoLoadGame()) {
|
||||
the_result = eMM_none;
|
||||
}
|
||||
break;
|
||||
case eMM_save:
|
||||
DoSaveGame(pSave_allowed);
|
||||
the_result = 0;
|
||||
the_result = eMM_none;
|
||||
break;
|
||||
case eMM_options:
|
||||
LoadSoundOptionsData();
|
||||
|
@ -583,10 +582,9 @@ tMM_result DoMainMenu(tU32 pTime_out, int pSave_allowed, int pContinue_allowed)
|
|||
FreeSoundOptionsData();
|
||||
break;
|
||||
case eMM_quit:
|
||||
if (DoVerifyQuit(0)) {
|
||||
break;
|
||||
if (!DoVerifyQuit(0)) {
|
||||
the_result = eMM_none;
|
||||
}
|
||||
the_result = 0;
|
||||
break;
|
||||
case eMM_recover:
|
||||
SetRecovery();
|
||||
|
@ -595,7 +593,7 @@ tMM_result DoMainMenu(tU32 pTime_out, int pSave_allowed, int pContinue_allowed)
|
|||
gAbandon_game = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return the_result;
|
||||
}
|
||||
return the_result;
|
||||
}
|
||||
|
@ -603,6 +601,7 @@ tMM_result DoMainMenu(tU32 pTime_out, int pSave_allowed, int pContinue_allowed)
|
|||
// IDA: void __usercall DoMainMenuScreen(tU32 pTime_out@<EAX>, int pSave_allowed@<EDX>, int pContinue_allowed@<EBX>)
|
||||
void DoMainMenuScreen(tU32 pTime_out, int pSave_allowed, int pContinue_allowed) {
|
||||
tPlayer_status old_status;
|
||||
LOG_TRACE("(%d, %d, %d)", pTime_out, pSave_allowed, pContinue_allowed);
|
||||
|
||||
if (pContinue_allowed || gAusterity_mode) {
|
||||
PlayFlicsFromDisk();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "globvrpb.h"
|
||||
#include "harness/trace.h"
|
||||
#include "network.h"
|
||||
#include "opponent.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
int gPowerup_cost[4];
|
||||
|
@ -142,7 +143,21 @@ void DisableCar(tCar_spec* pCar) {
|
|||
// IDA: void __usercall EnableCar(tCar_spec *pCar@<EAX>)
|
||||
void EnableCar(tCar_spec* pCar) {
|
||||
LOG_TRACE("(%p)", pCar);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pCar->driver_name[0]) {
|
||||
if (pCar->disabled) {
|
||||
pCar->disabled = 0;
|
||||
ForceRebuildActiveCarList();
|
||||
}
|
||||
if (pCar->car_master_actor->t.t.mat.m[3][0] > 500.0) {
|
||||
pCar->car_master_actor->t.t.mat.m[3][0] = pCar->car_master_actor->t.t.mat.m[3][0] - 1000.0f;
|
||||
pCar->car_master_actor->t.t.mat.m[3][1] = pCar->car_master_actor->t.t.mat.m[3][1] - 1000.0f;
|
||||
pCar->car_master_actor->t.t.mat.m[3][2] = pCar->car_master_actor->t.t.mat.m[3][2] - 1000.0f;
|
||||
pCar->old_frame_mat.m[3][0] = pCar->car_master_actor->t.t.mat.m[3][0];
|
||||
pCar->old_frame_mat.m[3][1] = pCar->car_master_actor->t.t.mat.m[3][1];
|
||||
pCar->old_frame_mat.m[3][2] = pCar->car_master_actor->t.t.mat.m[3][2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall DoNetworkHeadups(int pCredits@<EAX>)
|
||||
|
|
|
@ -944,7 +944,8 @@ void InitOpponents(tRace_info* pRace_info) {
|
|||
void DisposeOpponents() {
|
||||
int i;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
// IDA: void __usercall WakeUpOpponentsToTheFactThatTheStartHasBeenJumped(int pWhat_the_countdown_was@<EAX>)
|
||||
|
|
|
@ -1546,7 +1546,8 @@ void DisposePedestrians() {
|
|||
int j;
|
||||
tPedestrian_data* the_pedestrian;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
// IDA: void __cdecl DoPedReport()
|
||||
|
|
|
@ -338,7 +338,8 @@ void PipeSingleDamage(int pCar_ID, tS8* pDifferences) {
|
|||
// IDA: void __usercall PipeSingleSpecial(tSpecial_type pType@<EAX>)
|
||||
void PipeSingleSpecial(tSpecial_type pType) {
|
||||
LOG_TRACE("(%d)", pType);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
// IDA: void __usercall PipeSinglePedGib(int pIndex@<EAX>, br_matrix34 *pTrans@<EDX>, int pSize@<EBX>, int pGib_index@<ECX>, int pPed_index)
|
||||
|
@ -411,7 +412,8 @@ void InitialisePiping() {
|
|||
// IDA: void __cdecl DisposePiping()
|
||||
void DisposePiping() {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
// IDA: void __cdecl InitLastDamageArrayEtc()
|
||||
|
|
|
@ -151,7 +151,8 @@ void CloseDownPowerUps() {
|
|||
int i;
|
||||
tPowerup* the_powerup;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
// IDA: void __usercall DrawPowerups(tU32 pTime@<EAX>)
|
||||
|
|
|
@ -91,7 +91,8 @@ void ChangeAmbientPratcamNow(int pIndex, int pStart_chunk) {
|
|||
// IDA: void __usercall ChangeAmbientPratcam(int pIndex@<EAX>)
|
||||
void ChangeAmbientPratcam(int pIndex) {
|
||||
LOG_TRACE("(%d)", pIndex);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
// IDA: void __usercall PratcamEventNow(int pIndex@<EAX>)
|
||||
|
@ -135,7 +136,8 @@ void DisposePratcam() {
|
|||
int k;
|
||||
int l;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
// IDA: void __usercall DoPratcam(tU32 pThe_time@<EAX>)
|
||||
|
|
|
@ -350,5 +350,7 @@ void DoNetRaceSummary() {
|
|||
tSO_result DoEndRaceSummary(int* pFirst_summary_done, tRace_result pRace_result) {
|
||||
tSO_result result;
|
||||
LOG_TRACE("(%p, %d)", pFirst_summary_done, pRace_result);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
return eSO_main_menu_invoked;
|
||||
}
|
||||
|
|
|
@ -126,7 +126,12 @@ int DRS3ChangePitchSpeed(tS3_sound_tag pTag, tS3_pitch pNew_pitch) {
|
|||
// IDA: int __usercall DRS3StopSound@<EAX>(tS3_sound_tag pSound_tag@<EAX>)
|
||||
int DRS3StopSound(tS3_sound_tag pSound_tag) {
|
||||
LOG_TRACE("(%d)", pSound_tag);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gSound_enabled) {
|
||||
return S3StopSound(pSound_tag);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: int __usercall DRS3LoadSound@<EAX>(tS3_sound_id pThe_sound@<EAX>)
|
||||
|
@ -222,7 +227,8 @@ void DisposeSoundSources() {
|
|||
int toggle;
|
||||
tCar_spec* the_car;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
// IDA: tS3_sound_tag __usercall DRS3StartSound3D@<EAX>(tS3_outlet_ptr pOutlet@<EAX>, tS3_sound_id pSound@<EDX>, br_vector3 *pInitial_position@<EBX>, br_vector3 *pInitial_velocity@<ECX>, tS3_repeats pRepeats, tS3_volume pVolume, tS3_pitch pPitch, tS3_speed pSpeed)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "structur.h"
|
||||
#include "car.h"
|
||||
#include "controls.h"
|
||||
#include "crush.h"
|
||||
#include "cutscene.h"
|
||||
#include "displays.h"
|
||||
|
@ -17,8 +18,10 @@
|
|||
#include "mainloop.h"
|
||||
#include "mainmenu.h"
|
||||
#include "netgame.h"
|
||||
#include "network.h"
|
||||
#include "opponent.h"
|
||||
#include "piping.h"
|
||||
#include "pratcam.h"
|
||||
#include "racestrt.h"
|
||||
#include "racesumm.h"
|
||||
#include "sound.h"
|
||||
|
@ -66,7 +69,60 @@ int NumberOfOpponentsLeft() {
|
|||
// IDA: void __usercall RaceCompleted(tRace_over_reason pReason@<EAX>)
|
||||
void RaceCompleted(tRace_over_reason pReason) {
|
||||
LOG_TRACE("(%d)", pReason);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (!gRace_finished) {
|
||||
if (gNet_mode == eNet_mode_host && pReason < eRace_over_network_victory) {
|
||||
NetFinishRace(gCurrent_net_game, pReason);
|
||||
}
|
||||
if (pReason == eRace_over_out_of_time || pReason == eRace_over_demo) {
|
||||
ChangeAmbientPratcam(35);
|
||||
} else if (pReason < eRace_over_abandoned) {
|
||||
ChangeAmbientPratcam(34);
|
||||
}
|
||||
gRace_over_reason = pReason;
|
||||
if (gMap_mode) {
|
||||
ToggleMap();
|
||||
}
|
||||
switch (gRace_over_reason) {
|
||||
case eRace_over_laps:
|
||||
case eRace_over_peds:
|
||||
case eRace_over_opponents:
|
||||
ChangeAmbientPratcam(34);
|
||||
DoFancyHeadup(14);
|
||||
DRS3StartSound(gIndexed_outlets[4], 8011);
|
||||
break;
|
||||
case eRace_over_abandoned:
|
||||
if (gNet_mode == eNet_mode_client) {
|
||||
gHost_abandon_game = 1;
|
||||
NetFullScreenMessage(87, 0);
|
||||
}
|
||||
break;
|
||||
case eRace_over_out_of_time:
|
||||
ChangeAmbientPratcam(35);
|
||||
DoFancyHeadup(13);
|
||||
DRS3StartSound(gIndexed_outlets[4], 8010);
|
||||
break;
|
||||
case eRace_over_demo:
|
||||
ChangeAmbientPratcam(35);
|
||||
DoFancyHeadup(21);
|
||||
break;
|
||||
case eRace_over_network_victory:
|
||||
ChangeAmbientPratcam(34);
|
||||
DoFancyHeadup(20);
|
||||
break;
|
||||
case eRace_over_network_loss:
|
||||
ChangeAmbientPratcam(36);
|
||||
DoFancyHeadup(17);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (gNet_mode) {
|
||||
gRace_finished = 8000;
|
||||
} else {
|
||||
gRace_finished = 4000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall Checkpoint(int pCheckpoint_index@<EAX>, int pDo_sound@<EDX>)
|
||||
|
|
|
@ -426,11 +426,7 @@ br_pixelmap* DRPixelmapLoad(char* pFile_name) {
|
|||
if (the_map) {
|
||||
the_map->origin_x = 0;
|
||||
the_map->origin_y = 0;
|
||||
|
||||
lobyte = the_map->row_bytes & 0xff;
|
||||
lobyte += 3;
|
||||
lobyte &= 0xfc;
|
||||
the_map->row_bytes = (the_map->row_bytes & 0xff00) | lobyte;
|
||||
the_map->row_bytes = (the_map->row_bytes + 3) & 0xFFFC;
|
||||
}
|
||||
return the_map;
|
||||
}
|
||||
|
@ -446,10 +442,7 @@ br_uint_32 DRPixelmapLoadMany(char* pFile_name, br_pixelmap** pPixelmaps, br_uin
|
|||
number_loaded = BrPixelmapLoadMany(pFile_name, pPixelmaps, pNum);
|
||||
for (i = 0; i < number_loaded; i++) {
|
||||
the_map = pPixelmaps[i];
|
||||
lobyte = the_map->row_bytes & 0xff;
|
||||
lobyte += 3;
|
||||
lobyte &= 0xfc;
|
||||
the_map->row_bytes = (the_map->row_bytes & 0xff00) | lobyte;
|
||||
the_map->row_bytes = (the_map->row_bytes + 3) & 0xFFFC;
|
||||
the_map->base_x = 0;
|
||||
the_map->base_y = 0;
|
||||
}
|
||||
|
|
|
@ -2524,7 +2524,8 @@ void FreeTrack(tTrack_spec* pTrack_spec) {
|
|||
int i;
|
||||
tNon_car_spec* non_car;
|
||||
LOG_TRACE("(%p)", pTrack_spec);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
// IDA: void __usercall ProcessTrack(br_actor *pWorld@<EAX>, tTrack_spec *pTrack_spec@<EDX>, br_actor *pCamera@<EBX>, br_matrix34 *pCamera_to_world_transform@<ECX>, int pRender_blends)
|
||||
|
|
|
@ -237,6 +237,7 @@ typedef enum keycodes {
|
|||
} keycodes;
|
||||
|
||||
typedef enum keymapcodes {
|
||||
KEYMAP_ESCAPE = 0,
|
||||
KEYMAP_Q = 1,
|
||||
KEYMAP_S = 2,
|
||||
KEYMAP_L = 3,
|
||||
|
@ -288,8 +289,6 @@ typedef enum keymapcodes {
|
|||
|
||||
#define d180_OVER_PI 57.29577951308232 // (180 / PI)
|
||||
|
||||
#define PHYSICS_STEP_TIME 40.0
|
||||
|
||||
#define DR_PI 3.141592653589793
|
||||
|
||||
#define TIME_CONV_THING 0.00050000002
|
||||
|
|
|
@ -6,5 +6,7 @@
|
|||
void S3Service(int inside_cockpit, int unk1);
|
||||
tS3_sound_tag S3StartSound(tS3_outlet_ptr pOutlet, tS3_sound_id pSound);
|
||||
void S3StopAllOutletSounds();
|
||||
int S3SoundStillPlaying(tS3_sound_tag pSound);
|
||||
int S3StopSound(tS3_sound_tag pSound_tag);
|
||||
|
||||
#endif
|
|
@ -14,4 +14,12 @@ void S3StopAllOutletSounds() {
|
|||
|
||||
tS3_sound_tag S3StartSound(tS3_outlet_ptr pOutlet, tS3_sound_id pSound) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int S3SoundStillPlaying(tS3_sound_tag pSound) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int S3StopSound(tS3_sound_tag pSound_tag) {
|
||||
return 0;
|
||||
}
|
|
@ -19,17 +19,24 @@ harness_br_renderer* renderer_state;
|
|||
br_pixelmap* last_dst = NULL;
|
||||
br_pixelmap* last_src = NULL;
|
||||
|
||||
// if true, disable the original CD check code
|
||||
int harness_disable_cd_check = 1;
|
||||
// value between 0 and 1 - 0 is no fade, 1 is full black
|
||||
float palette_fade_to_black_alpha = 0;
|
||||
|
||||
int back_screen_is_transparent = 0;
|
||||
int rendered_scenes_this_frame = 0;
|
||||
int rendered_scenes_last_frame = 0;
|
||||
|
||||
unsigned int last_frame_time = 0;
|
||||
|
||||
extern void BrPixelmapFill(br_pixelmap* dst, br_uint_32 colour);
|
||||
extern unsigned int GetTotalTime();
|
||||
extern uint8_t gScan_code[123][2];
|
||||
|
||||
// SplatPack or Carmageddon. This is where we represent the code differences between the two. For example, the intro smack file.
|
||||
tHarness_game_info harness_game_info;
|
||||
|
||||
// Configuration options
|
||||
tHarness_game_config harness_game_config;
|
||||
|
||||
int Harness_ProcessCommandLine(int* argc, char* argv[]);
|
||||
|
||||
void Harness_DetectGameMode() {
|
||||
|
@ -54,6 +61,13 @@ void Harness_DetectGameMode() {
|
|||
void Harness_Init(int* argc, char* argv[]) {
|
||||
int result;
|
||||
|
||||
// disable the original CD check code
|
||||
harness_game_config.disable_cd_check = 1;
|
||||
// original physics time step. Lower values seem to work better at 30+ fps
|
||||
harness_game_config.physics_step_time = 40;
|
||||
// do not limit fps by default
|
||||
harness_game_config.fps = 0;
|
||||
|
||||
Harness_ProcessCommandLine(argc, argv);
|
||||
|
||||
install_signal_handler(argv[0]);
|
||||
|
@ -94,18 +108,28 @@ int Harness_ProcessCommandLine(int* argc, char* argv[]) {
|
|||
for (int i = 1; i < *argc; i++) {
|
||||
int handled = 0;
|
||||
|
||||
if (strcasecmp(argv[i], "-cdcheck") == 0) {
|
||||
harness_disable_cd_check = 0;
|
||||
if (strcasecmp(argv[i], "--cdcheck") == 0) {
|
||||
harness_game_config.disable_cd_check = 0;
|
||||
handled = 1;
|
||||
} else if (strstr(argv[i], "-debug") != NULL) {
|
||||
char* s = strstr(argv[i], "=");
|
||||
} else if (strstr(argv[i], "--debug ") != NULL) {
|
||||
char* s = strstr(argv[i], " ");
|
||||
harness_debug_level = atoi(s + 1);
|
||||
LOG_INFO("debug level set to %d", harness_debug_level);
|
||||
handled = 1;
|
||||
} else if (strstr(argv[i], "-platform") != NULL) {
|
||||
platform_name = strstr(argv[i], "=") + 1;
|
||||
} else if (strstr(argv[i], "--platform ") != NULL) {
|
||||
platform_name = strstr(argv[i], " ") + 1;
|
||||
LOG_INFO("Platform set to: %s", platform_name);
|
||||
handled = 1;
|
||||
} else if (strstr(argv[i], "--physics-step-time ") != NULL) {
|
||||
char* s = strstr(argv[i], " ");
|
||||
harness_game_config.physics_step_time = atof(s + 1);
|
||||
LOG_INFO("Physics step time set to %f", harness_game_config.physics_step_time);
|
||||
handled = 1;
|
||||
} else if (strstr(argv[i], "--fps ") != NULL) {
|
||||
char* s = strstr(argv[i], " ");
|
||||
harness_game_config.fps = atoi(s + 1);
|
||||
LOG_INFO("FPS limiter set to %f", harness_game_config.fps);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
|
@ -135,12 +159,13 @@ void Harness_Hook_DOSGfxBegin() {
|
|||
platform->NewWindow("Dethrace", 640, 400);
|
||||
}
|
||||
|
||||
void Harness_ConvertPalettedPixelmapTo32Bit(uint32_t** dst, br_pixelmap* src) {
|
||||
void Harness_ConvertPalettedPixelmapTo32Bit(uint32_t** dst, br_pixelmap* src, int vflip) {
|
||||
uint8_t palette_index = 0;
|
||||
uint8_t* data = src->pixels;
|
||||
uint32_t* colors;
|
||||
int x;
|
||||
int y;
|
||||
int dest_y;
|
||||
|
||||
if (!palette) {
|
||||
return;
|
||||
|
@ -151,34 +176,36 @@ void Harness_ConvertPalettedPixelmapTo32Bit(uint32_t** dst, br_pixelmap* src) {
|
|||
}
|
||||
|
||||
// generate 32 bit texture from src + palette
|
||||
for (y = 0; y < src->height; y++) {
|
||||
for (x = 0; x < src->width; x++) {
|
||||
palette_index = (data[y * src->row_bytes + x]);
|
||||
(*dst)[y * src->width + x] = colors[palette_index];
|
||||
if (vflip) {
|
||||
dest_y = src->height - 1;
|
||||
for (y = 0; y < src->height; y++) {
|
||||
for (x = 0; x < src->width; x++) {
|
||||
palette_index = (data[y * src->row_bytes + x]);
|
||||
(*dst)[dest_y * src->width + x] = colors[palette_index];
|
||||
}
|
||||
dest_y--;
|
||||
}
|
||||
} else {
|
||||
for (y = 0; y < src->height; y++) {
|
||||
for (x = 0; x < src->width; x++) {
|
||||
palette_index = (data[y * src->row_bytes + x]);
|
||||
(*dst)[y * src->width + x] = colors[palette_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render 2d back buffer
|
||||
void Harness_RenderScreen(br_pixelmap* dst, br_pixelmap* src) {
|
||||
Harness_ConvertPalettedPixelmapTo32Bit(&screen_buffer, src);
|
||||
platform->RenderFullScreenQuad(screen_buffer, back_screen_is_transparent);
|
||||
platform->PollEvents();
|
||||
Harness_ConvertPalettedPixelmapTo32Bit(&screen_buffer, src, 1);
|
||||
platform->RenderFullScreenQuad(screen_buffer, 320, 200);
|
||||
|
||||
last_dst = dst;
|
||||
last_src = src;
|
||||
}
|
||||
|
||||
void Harness_Hook_BrPixelmapDoubleBuffer(br_pixelmap* dst, br_pixelmap* src) {
|
||||
Harness_RenderScreen(dst, src);
|
||||
platform->Swap();
|
||||
back_screen_is_transparent = 0;
|
||||
}
|
||||
void Harness_Hook_BrDevPaletteSetOld(br_pixelmap* pm) {
|
||||
palette = pm;
|
||||
if (last_src) {
|
||||
Harness_RenderScreen(last_dst, last_src);
|
||||
platform->Swap();
|
||||
}
|
||||
}
|
||||
|
||||
void Harness_Hook_BrDevPaletteSetEntryOld(int i, br_colour colour) {
|
||||
|
@ -193,29 +220,76 @@ void Harness_Hook_BrV1dbRendererBegin(br_v1db_state* v1db) {
|
|||
v1db->renderer = (br_renderer*)renderer_state;
|
||||
}
|
||||
|
||||
int col = 128;
|
||||
|
||||
void Harness_Hook_renderFaces(br_model* model, br_material* material, br_token type) {
|
||||
platform->RenderModel(model, renderer_state->state.matrix.model_to_view);
|
||||
}
|
||||
|
||||
// Begin 3d scene
|
||||
void Harness_Hook_BrZbSceneRenderBegin(br_actor* world, br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer) {
|
||||
// splat current back_screen to framebuffer
|
||||
Harness_RenderScreen(NULL, colour_buffer);
|
||||
// clear to transparent ready for the game to render foreground bits
|
||||
BrPixelmapFill(colour_buffer, 0);
|
||||
back_screen_is_transparent = 1;
|
||||
rendered_scenes_this_frame++;
|
||||
|
||||
//current_renderer->setViewport(colour_buffer->base_x * 2, colour_buffer->base_y * 2, colour_buffer->width * 2, colour_buffer->height * 2);
|
||||
platform->BeginFrame(camera, colour_buffer);
|
||||
col = 0;
|
||||
// if this is the first 3d scene this frame, draw the current colour_buffer (2d screen) contents to framebuffer
|
||||
if (rendered_scenes_this_frame == 0) {
|
||||
Harness_RenderScreen(NULL, colour_buffer);
|
||||
}
|
||||
// clear to transparent ready for the game to render foreground elements which we will capture later in `Harness_Hook_BrPixelmapDoubleBuffer`
|
||||
BrPixelmapFill(colour_buffer, 0);
|
||||
|
||||
platform->BeginScene(camera, colour_buffer);
|
||||
}
|
||||
|
||||
void Harness_Hook_BrZbSceneRenderAdd(br_actor* tree) {
|
||||
}
|
||||
|
||||
void Harness_Hook_renderFaces(br_model* model, br_material* material, br_token type) {
|
||||
platform->RenderModel(model, renderer_state->state.matrix.model_to_view);
|
||||
}
|
||||
|
||||
void Harness_Hook_BrZbSceneRenderEnd() {
|
||||
platform->EndFrame();
|
||||
platform->EndScene();
|
||||
}
|
||||
|
||||
void Harness_Hook_MainGameLoop() {
|
||||
if (harness_game_config.fps == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (last_frame_time) {
|
||||
unsigned int frame_time = GetTotalTime() - last_frame_time;
|
||||
|
||||
if (frame_time < 100) {
|
||||
|
||||
int sleep_time = (1000 / harness_game_config.fps) - frame_time;
|
||||
if (sleep_time > 5) {
|
||||
SDL_Delay(sleep_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last_frame_time = GetTotalTime();
|
||||
}
|
||||
|
||||
// Called by game to swap buffers at end of frame rendering
|
||||
void Harness_Hook_BrPixelmapDoubleBuffer(br_pixelmap* dst, br_pixelmap* src) {
|
||||
|
||||
// should we switch to fb 0 here ?
|
||||
|
||||
// draw the current colour_buffer (2d screen) contents
|
||||
Harness_RenderScreen(dst, src);
|
||||
|
||||
// draw the current 3d frame buffer
|
||||
if (rendered_scenes_this_frame) {
|
||||
platform->RenderFrameBuffer();
|
||||
}
|
||||
|
||||
// if the game has faded the palette, we should respect that.
|
||||
// fixes screen flash during race start or recovery
|
||||
if (palette_fade_to_black_alpha != 0) {
|
||||
platform->RenderColorBlend(0, 0, 0, palette_fade_to_black_alpha);
|
||||
}
|
||||
|
||||
platform->Swap();
|
||||
platform->PollEvents();
|
||||
|
||||
// reset 3d render count
|
||||
rendered_scenes_last_frame = rendered_scenes_this_frame;
|
||||
rendered_scenes_this_frame = 0;
|
||||
}
|
||||
|
||||
int Harness_Hook_KeyDown(unsigned char pScan_code) {
|
||||
|
@ -245,4 +319,18 @@ void Harness_Hook_S3Service(int unk1, int unk2) {
|
|||
}
|
||||
|
||||
void Harness_Hook_S3StopAllOutletSounds() {
|
||||
}
|
||||
|
||||
void Harness_Hook_SetFadedPalette(int pDegree) {
|
||||
|
||||
// pDegree is 0-255 where 0 is full black and 255 is full original color.
|
||||
// we convert this to an alpha blend value
|
||||
palette_fade_to_black_alpha = (256 - pDegree) / 256.f;
|
||||
|
||||
if (rendered_scenes_last_frame > 0) {
|
||||
platform->RenderFrameBuffer();
|
||||
}
|
||||
Harness_RenderScreen(last_dst, last_src);
|
||||
platform->RenderColorBlend(0, 0, 0, palette_fade_to_black_alpha);
|
||||
platform->Swap();
|
||||
}
|
|
@ -10,10 +10,12 @@ typedef struct tPlatform {
|
|||
void (*PollEvents)();
|
||||
int* (*GetKeyMap)();
|
||||
int (*IsKeyDown)(unsigned char pScan_code);
|
||||
void (*BeginFrame)(br_actor* camera, br_pixelmap* colour_buffer);
|
||||
void (*EndFrame)();
|
||||
void (*RenderFullScreenQuad)(uint32_t* src, int transparent);
|
||||
void (*BeginScene)(br_actor* camera, br_pixelmap* colour_buffer);
|
||||
void (*EndScene)();
|
||||
void (*RenderFullScreenQuad)(uint32_t* src, int width, int height);
|
||||
void (*RenderColorBlend)(float r, float g, float b, float a);
|
||||
void (*RenderModel)(br_model* model, br_matrix34 model_matrix);
|
||||
void (*RenderFrameBuffer)();
|
||||
void (*Swap)();
|
||||
void (*BufferTexture)(br_pixelmap* pm);
|
||||
void (*BufferMaterial)(br_material* mat);
|
||||
|
@ -27,6 +29,6 @@ typedef struct tCamera {
|
|||
void (*setPosition)();
|
||||
} tCamera;
|
||||
|
||||
void Harness_ConvertPalettedPixelmapTo32Bit(uint32_t** dst, br_pixelmap* src);
|
||||
void Harness_ConvertPalettedPixelmapTo32Bit(uint32_t** dst, br_pixelmap* src, int vflip);
|
||||
|
||||
#endif
|
|
@ -11,12 +11,20 @@ typedef enum tHarness_game_type {
|
|||
typedef struct tHarness_game_info {
|
||||
tHarness_game_type mode;
|
||||
struct {
|
||||
char* INTRO_SMK_FILE; // different between carmageddon and splatpack
|
||||
char* GERMAN_LOADSCRN; // different between demo and full game
|
||||
// different between carmageddon and splatpack
|
||||
char* INTRO_SMK_FILE;
|
||||
// different between demo and full game
|
||||
char* GERMAN_LOADSCRN;
|
||||
} defines;
|
||||
} tHarness_game_info;
|
||||
|
||||
typedef struct tHarness_game_config {
|
||||
int disable_cd_check;
|
||||
float physics_step_time;
|
||||
float fps;
|
||||
} tHarness_game_config;
|
||||
|
||||
extern tHarness_game_info harness_game_info;
|
||||
extern int harness_disable_cd_check;
|
||||
extern tHarness_game_config harness_game_config;
|
||||
|
||||
#endif
|
|
@ -10,6 +10,8 @@ void Harness_Init(int* argc, char* argv[]);
|
|||
int Harness_Hook_KeyDown(unsigned char pScan_code);
|
||||
void Harness_Hook_PDServiceSystem();
|
||||
void Harness_Hook_PDSetKeyArray();
|
||||
void Harness_Hook_SetFadedPalette(int pDegree);
|
||||
void Harness_Hook_MainGameLoop(); // limit FPS
|
||||
|
||||
// BRender hooks
|
||||
void Harness_Hook_DOSGfxBegin();
|
||||
|
|
|
@ -7,8 +7,10 @@ int* Null_GetKeyMap() { return NULL; }
|
|||
int Null_IsKeyDown(unsigned char pScan_code) { return 0; }
|
||||
void Null_BeginFrame(br_actor* camera, br_pixelmap* colour_buffer) {}
|
||||
void Null_EndFrame() {}
|
||||
void Null_RenderFullScreenQuad(uint32_t* src, int transparent) {}
|
||||
void Null_RenderFullScreenQuad(uint32_t* src, int width, int height) {}
|
||||
void Null_RenderColorBlend(float r, float g, float b, float a) {}
|
||||
void Null_RenderModel(br_model* model, br_matrix34 model_matrix) {}
|
||||
void Null_RenderFrameBuffer() {}
|
||||
void Null_Swap() {}
|
||||
void Null_BufferTexture(br_pixelmap* pm) {}
|
||||
void Null_BufferMaterial(br_material* mat) {}
|
||||
|
@ -22,7 +24,9 @@ tPlatform null_platform = {
|
|||
Null_BeginFrame,
|
||||
Null_EndFrame,
|
||||
Null_RenderFullScreenQuad,
|
||||
Null_RenderColorBlend,
|
||||
Null_RenderModel,
|
||||
Null_RenderFrameBuffer,
|
||||
Null_Swap,
|
||||
Null_BufferTexture,
|
||||
Null_BufferMaterial
|
||||
|
|
|
@ -11,10 +11,12 @@ tPlatform sdl_gl_platform = {
|
|||
SDLPlatform_PollEvents,
|
||||
SDLPlatform_GetKeyMap,
|
||||
SDLPlatform_IsKeyDown,
|
||||
GLRenderer_BeginFrame,
|
||||
GLRenderer_EndFrame,
|
||||
GLRenderer_BeginScene,
|
||||
GLRenderer_EndScene,
|
||||
GLRenderer_RenderFullScreenQuad,
|
||||
GLRenderer_RenderColorBlend,
|
||||
GLRenderer_RenderModel,
|
||||
GLRenderer_RenderFramebuffer,
|
||||
GLRenderer_Swap,
|
||||
GLRenderer_BufferTexture,
|
||||
GLRenderer_BufferMaterial
|
||||
|
|
|
@ -29,7 +29,10 @@ GLuint screen_buffer_vao, screen_buffer_ebo;
|
|||
GLuint screen_texture;
|
||||
GLuint shader_program_2d;
|
||||
GLuint shader_program_2d_trans;
|
||||
GLuint shader_program_2d_pp;
|
||||
GLuint shader_program_3d;
|
||||
GLuint framebuffer_id, framebuffer_texture = 0;
|
||||
unsigned int rbo;
|
||||
|
||||
int window_width, window_height;
|
||||
|
||||
|
@ -57,17 +60,26 @@ void LoadShaders() {
|
|||
glAttachShader(shader_program_2d, vs);
|
||||
glAttachShader(shader_program_2d, fs);
|
||||
glLinkProgram(shader_program_2d);
|
||||
|
||||
glDeleteShader(fs);
|
||||
|
||||
fs = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
CompileShader(fs, fs_2d_trans);
|
||||
shader_program_2d_trans = glCreateProgram();
|
||||
glAttachShader(shader_program_2d_trans, vs);
|
||||
glAttachShader(shader_program_2d_trans, fs);
|
||||
glLinkProgram(shader_program_2d_trans);
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
|
||||
fs = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
CompileShader(fs, fs_postprocess);
|
||||
shader_program_2d_pp = glCreateProgram();
|
||||
glAttachShader(shader_program_2d_pp, vs);
|
||||
glAttachShader(shader_program_2d_pp, fs);
|
||||
glLinkProgram(shader_program_2d_pp);
|
||||
glDeleteShader(fs);
|
||||
|
||||
glDeleteShader(vs);
|
||||
|
||||
vs = glCreateShader(GL_VERTEX_SHADER);
|
||||
fs = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
CompileShader(fs, fs_3d);
|
||||
|
@ -123,10 +135,10 @@ void GLRenderer_CreateWindow(char* title, int width, int height) {
|
|||
|
||||
float vertices[] = {
|
||||
// positions // colors // texture coords
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
|
||||
1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
|
||||
-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top right
|
||||
1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // bottom right
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // bottom left
|
||||
-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f // top left
|
||||
};
|
||||
unsigned int indices[] = {
|
||||
0, 1, 3, // first triangle
|
||||
|
@ -163,13 +175,40 @@ void GLRenderer_CreateWindow(char* title, int width, int height) {
|
|||
|
||||
glGenTextures(1, &screen_texture);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Accept fragment if it closer to the camera than the former one
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
glGenFramebuffers(1, &framebuffer_id);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id);
|
||||
glClearColor(0, 0, 0, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glGenTextures(1, &framebuffer_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, framebuffer_texture);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebuffer_texture, 0);
|
||||
|
||||
glGenRenderbuffers(1, &rbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
LOG_PANIC("ERROR::FRAMEBUFFER:: Framebuffer is not complete!");
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void GLRenderer_BeginFrame(br_actor* camera, br_pixelmap* colour_buffer) {
|
||||
void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer) {
|
||||
|
||||
glViewport(colour_buffer->base_x * 2, colour_buffer->base_y * 2, colour_buffer->width * 2, colour_buffer->height * 2);
|
||||
|
||||
|
@ -211,28 +250,58 @@ void GLRenderer_BeginFrame(br_actor* camera, br_pixelmap* colour_buffer) {
|
|||
glUniformMatrix4fv(projection_u, 1, GL_FALSE, proj);
|
||||
|
||||
DebugCamera_Update();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void GLRenderer_EndFrame() {
|
||||
void GLRenderer_EndScene() {
|
||||
}
|
||||
|
||||
void GLRenderer_RenderFramebuffer() {
|
||||
|
||||
glViewport(0, 0, window_width, window_height);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBindTexture(GL_TEXTURE_2D, framebuffer_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glUseProgram(shader_program_2d_trans);
|
||||
|
||||
glBindVertexArray(screen_buffer_vao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, screen_buffer_ebo);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void GLRenderer_RenderFullScreenQuad(uint32_t* screen_buffer, int transparent) {
|
||||
void GLRenderer_RenderFullScreenQuad(uint32_t* screen_buffer, int width, int height) {
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
// TODO: remove fixed 320x200
|
||||
glBindTexture(GL_TEXTURE_2D, screen_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 320, 200, 0, GL_BGRA, GL_UNSIGNED_BYTE, screen_buffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, screen_buffer);
|
||||
|
||||
glUseProgram(shader_program_2d_trans);
|
||||
|
||||
glBindVertexArray(screen_buffer_vao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, screen_buffer_ebo);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// GLRenderer_RenderColorBlend renders a fullscreen quad with the desired color
|
||||
void GLRenderer_RenderColorBlend(float r, float g, float b, float a) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glUseProgram(shader_program_2d_pp);
|
||||
GLuint model_u = glGetUniformLocation(shader_program_2d_pp, "color");
|
||||
glUniform4f(model_u, r, g, b, a);
|
||||
|
||||
if (transparent) {
|
||||
glUseProgram(shader_program_2d_trans);
|
||||
} else {
|
||||
glUseProgram(shader_program_2d);
|
||||
}
|
||||
glBindVertexArray(screen_buffer_vao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, screen_buffer_ebo);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
|
@ -241,7 +310,6 @@ void GLRenderer_RenderFullScreenQuad(uint32_t* screen_buffer, int transparent) {
|
|||
|
||||
void GLRenderer_Swap() {
|
||||
SDL_GL_SwapWindow(window);
|
||||
// glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
|
@ -414,7 +482,7 @@ void GLRenderer_BufferMaterial(br_material* mat) {
|
|||
void GLRenderer_BufferTexture(br_pixelmap* pm) {
|
||||
if (!pm->stored) {
|
||||
uint32_t* full_color_texture = NULL;
|
||||
Harness_ConvertPalettedPixelmapTo32Bit(&full_color_texture, pm);
|
||||
Harness_ConvertPalettedPixelmapTo32Bit(&full_color_texture, pm, 0);
|
||||
if (full_color_texture == NULL) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
#include <SDL.h>
|
||||
|
||||
void GLRenderer_CreateWindow(char* title, int width, int height);
|
||||
void GLRenderer_BeginFrame(br_actor* camera, br_pixelmap* colour_buffer);
|
||||
void GLRenderer_EndFrame();
|
||||
void GLRenderer_RenderFullScreenQuad(uint32_t* screen_buffer, int transparent);
|
||||
void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer);
|
||||
void GLRenderer_EndScene();
|
||||
void GLRenderer_RenderFullScreenQuad(uint32_t* screen_buffer, int width, int height);
|
||||
void GLRenderer_RenderColorBlend(float r, float g, float b, float a);
|
||||
void GLRenderer_RenderFramebuffer();
|
||||
void GLRenderer_Swap();
|
||||
void GLRenderer_RenderModel(br_model* model, br_matrix34 model_matrix);
|
||||
void GLRenderer_BufferTexture(br_pixelmap* pm);
|
||||
|
|
|
@ -34,6 +34,16 @@ const char* fs_2d_trans = "#version 330 core\n"
|
|||
" }\n"
|
||||
"}\n\0";
|
||||
|
||||
const char* fs_postprocess = "#version 330 core\n"
|
||||
"in vec2 TexCoord;\n"
|
||||
"uniform vec4 color;\n"
|
||||
"layout (location = 0) out vec4 FragColor;\n"
|
||||
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" FragColor = color;\n"
|
||||
"}\n\0";
|
||||
|
||||
// const char* vs_3d = "#version 330 core\n"
|
||||
// "layout (location = 0) in vec3 aPos;\n"
|
||||
// "layout (location = 1) in vec3 aNormal;\n"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
extern const char* vs_2d;
|
||||
extern const char* fs_2d;
|
||||
extern const char* fs_2d_trans;
|
||||
extern const char* fs_postprocess;
|
||||
|
||||
extern const char* fs_3d;
|
||||
extern const char* vs_3d;
|
||||
|
|
Loading…
Reference in New Issue