Implements depth effects (#95)

* implements depth effects
* fix missing skidmark textures
* implement sky color
* temporary fix for missing kerb materials
This commit is contained in:
Dethrace Engineering Department 2022-03-01 14:19:13 +13:00 committed by GitHub
parent 26fd105889
commit 92b67a9314
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 315 additions and 151 deletions

View File

@ -244,7 +244,7 @@ void BrPixelmapDirtyRectangleDoubleBuffer(br_pixelmap* dst, br_pixelmap* src, br
// IDA: void __cdecl BrPixelmapPixelSet(br_pixelmap *dst, br_int_32 x, br_int_32 y, br_uint_32 colour)
void BrPixelmapPixelSet(br_pixelmap* dst, br_int_32 x, br_int_32 y, br_uint_32 colour) {
br_point p;
//LOG_TRACE("(%p, %d, %d, %d)", dst, x, y, colour);
// LOG_TRACE("(%p, %d, %d, %d)", dst, x, y, colour);
br_uint_8* dst_pix = (br_uint_8*)dst->pixels;
dst_pix[(y * dst->row_bytes) + x] = (br_uint_8)colour;
}
@ -267,8 +267,8 @@ void BrPixelmapCopy(br_pixelmap* dst, br_pixelmap* src) {
// IDA: void __cdecl BrPixelmapLine(br_pixelmap *dst, br_int_32 x1, br_int_32 y1, br_int_32 x2, br_int_32 y2, br_uint_32 colour)
void BrPixelmapLine(br_pixelmap* dst, br_int_32 x1, br_int_32 y1, br_int_32 x2, br_int_32 y2, br_uint_32 colour) {
//br_point s;
//br_point e;
// br_point s;
// br_point e;
LOG_TRACE("(%p, %d, %d, %d, %d, %d)", dst, x1, y1, x2, y2, colour);
// Thanks Errol!

View File

@ -116,7 +116,7 @@ br_device_pixelmap* DevicePixelmapMemAllocate(br_uint_8 type, br_uint_16 w, br_u
tip = &pmTypeInfo[type];
pm = BrResAllocate(_pixelmap.res, sizeof(br_device_pixelmap), BR_MEMORY_PIXELMAP);
//pm->dispatch = &devicePixelmapDispatch;
// pm->dispatch = &devicePixelmapDispatch;
pm->pm_identifier = NULL;
pm->pm_map = NULL;
pm->pm_flags = BR_PMF_LINEAR;
@ -129,11 +129,11 @@ br_device_pixelmap* DevicePixelmapMemAllocate(br_uint_8 type, br_uint_16 w, br_u
pm->pm_type = type;
pm->pm_width = w;
pm->pm_height = h;
//8 bits, 1, 4 align, 1
// 8 bits, 1, 4 align, 1
//v11 = (tip->align + w - 1) / tip->align * tip->align * tip->bits;
//pm->pm_row_bytes = (v11 - (__CFSHL__(v11 >> 31, 3) + 8 * (v11 >> 31))) >> 3;
// TODO: calculate this differently
// v11 = (tip->align + w - 1) / tip->align * tip->align * tip->bits;
// 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;
@ -147,8 +147,8 @@ br_device_pixelmap* DevicePixelmapMemAllocate(br_uint_8 type, br_uint_16 w, br_u
pm->pm_pixels = BrResAllocate(pm, pm->pm_height * pm->pm_row_bytes, BR_MEMORY_PIXELS);
}
}
//TODO: not sure we need this
//pm->pm_pixels_qualifier = (unsigned __int16)_GetSysQual();
// TODO: not sure we need this
// pm->pm_pixels_qualifier = (unsigned __int16)_GetSysQual();
if (flags & BR_PMAF_INVERTED) {
pm->pm_pixels = (char*)pm->pm_pixels + (pm->pm_height - 1) * pm->pm_row_bytes;
pm->pm_row_bytes *= -1;
@ -183,7 +183,7 @@ br_error _M_br_device_pixelmap_mem_allocateSub(br_device_pixelmap* self, br_devi
pm->pm_stored = 0;
pm->dispatch = &devicePixelmapDispatch;
if (pm->pm_width != self->pm_width) {
pm->pm_flags &= 0xFDu; //unset BR_PMF_LINEAR
pm->pm_flags &= 0xFDu; // unset BR_PMF_LINEAR
}
*newpm = pm;
return 0;
@ -301,6 +301,9 @@ br_error _M_br_device_pixelmap_mem_match(br_device_pixelmap* self, br_device_pix
// }
if (mt.use == BRT_DEPTH) {
// TODO: hack this to make it work
mt.pixel_type = BR_PMT_DEPTH_16;
pm = DevicePixelmapMemAllocate(mt.pixel_type, mt.width, mt.height, NULL, (self->pm_row_bytes < 0) | BR_PMAF_NO_PIXELS);
r = abs(self->pm_row_bytes);
bytes = (signed int)pmTypeInfo[self->pm_type].bits >> 3;
@ -322,7 +325,7 @@ br_error _M_br_device_pixelmap_mem_match(br_device_pixelmap* self, br_device_pix
}
pm->pm_origin_x = self->pm_origin_x;
pm->pm_origin_y = self->pm_origin_y;
//self->dispatch = pm;
// self->dispatch = pm;
*newpm = pm;
return 0;

View File

@ -4,40 +4,40 @@
#include "harness/trace.h"
render_style_cbfn RenderStyleCalls[8] = {
renderFaces, /* BR_RSTYLE_DEFAULT */
nullRender, /* BR_RSTYLE_NONE */
renderPoints, /* BR_RSTYLE_POINTS */
renderEdges, /* BR_RSTYLE_EDGES */
renderFaces, /* BR_RSTYLE_FACES */
boundingBoxRenderPoints, /* BR_RSTYLE_BOUNDING_POINTS */
boundingBoxRenderEdges, /* BR_RSTYLE_BOUNDING_EDGES */
boundingBoxRenderFaces, /* BR_RSTYLE_BOUNDING_FACES */
renderFaces, /* BR_RSTYLE_DEFAULT */
nullRender, /* BR_RSTYLE_NONE */
renderPoints, /* BR_RSTYLE_POINTS */
renderEdges, /* BR_RSTYLE_EDGES */
renderFaces, /* BR_RSTYLE_FACES */
boundingBoxRenderPoints, /* BR_RSTYLE_BOUNDING_POINTS */
boundingBoxRenderEdges, /* BR_RSTYLE_BOUNDING_EDGES */
boundingBoxRenderFaces, /* BR_RSTYLE_BOUNDING_FACES */
};
v11face bounds_faces[12] = {
{ { 5, 6, 7 }, { 0, 13, 14}, { { 1.0f, 0.0f, 0.0f, 1.0f } } },
{ { 5, 4, 6 }, { 3, 4, 0}, { { 1.0f, 0.0f, 0.0f, 1.0f } } },
{ { 7, 6, 2 }, { 13, 6, 0}, { { 0.0f, 1.0f, 0.0f, 1.0f } } },
{ { 7, 2, 3 }, { 0, 5, 16}, { { 0.0f, 1.0f, 0.0f, 1.0f } } },
{ { 1, 5, 7 }, { 11, 14, 0}, { { 0.0f, 0.0f, 1.0f, 1.0f } } },
{ { 1, 7, 3 }, { 0, 16, 12}, { { 0.0f, 0.0f, 1.0f, 1.0f } } },
{ { 3, 0, 1 }, { 0, 8, 12}, { { -1.0f, 0.0f, 0.0f, 1.0f } } },
{ { 3, 2, 0 }, { 5, 1, 0}, { { -1.0f, 0.0f, 0.0f, 1.0f } } },
{ { 1, 0, 4 }, { 8, 9, 0}, { { 0.0f, -1.0f, 0.0f, 1.0f } } },
{ { 1, 4, 5 }, { 0, 3, 11}, { { 0.0f, -1.0f, 0.0f, 1.0f } } },
{ { 0, 6, 4 }, { 0, 4, 9}, { { 0.0f, 0.0f, -1.0f, 1.0f } } },
{ { 0, 2, 6 }, { 1, 6, 0}, { { 0.0f, 0.0f, -1.0f, 1.0f } } },
{ { 5, 6, 7 }, { 0, 13, 14 }, { { 1.0f, 0.0f, 0.0f, 1.0f } } },
{ { 5, 4, 6 }, { 3, 4, 0 }, { { 1.0f, 0.0f, 0.0f, 1.0f } } },
{ { 7, 6, 2 }, { 13, 6, 0 }, { { 0.0f, 1.0f, 0.0f, 1.0f } } },
{ { 7, 2, 3 }, { 0, 5, 16 }, { { 0.0f, 1.0f, 0.0f, 1.0f } } },
{ { 1, 5, 7 }, { 11, 14, 0 }, { { 0.0f, 0.0f, 1.0f, 1.0f } } },
{ { 1, 7, 3 }, { 0, 16, 12 }, { { 0.0f, 0.0f, 1.0f, 1.0f } } },
{ { 3, 0, 1 }, { 0, 8, 12 }, { { -1.0f, 0.0f, 0.0f, 1.0f } } },
{ { 3, 2, 0 }, { 5, 1, 0 }, { { -1.0f, 0.0f, 0.0f, 1.0f } } },
{ { 1, 0, 4 }, { 8, 9, 0 }, { { 0.0f, -1.0f, 0.0f, 1.0f } } },
{ { 1, 4, 5 }, { 0, 3, 11 }, { { 0.0f, -1.0f, 0.0f, 1.0f } } },
{ { 0, 6, 4 }, { 0, 4, 9 }, { { 0.0f, 0.0f, -1.0f, 1.0f } } },
{ { 0, 2, 6 }, { 1, 6, 0 }, { { 0.0f, 0.0f, -1.0f, 1.0f } } },
};
br_colour bounds_colours[12] = { 0 };
fmt_vertex bounds_vertices[8] = {
{ {{ -1.0f, -1.0f, -1.0f }}, {{ 0.0f, 0.0f }}, {{ -0.666f, -0.333f, -0.666f }} },
{ {{ -1.0f, -1.0f, 1.0f }}, {{ 0.0f, 0.0f }}, {{ -0.333f, -0.666f, 0.666f }} },
{ {{ -1.0f, 1.0f, -1.0f }}, {{ 0.0f, 1.0f }}, {{ -0.408f, 0.816f, -0.408f }} },
{ {{ -1.0f, 1.0f, 1.0f }}, {{ 0.0f, 1.0f }}, {{ -0.816f, 0.408f, 0.408f }} },
{ {{ 1.0f, -1.0f, -1.0f }}, {{ 1.0f, 0.0f }}, {{ 0.408f, -0.816f, -0.408f }} },
{ {{ 1.0f, -1.0f, 1.0f }}, {{ 1.0f, 0.0f }}, {{ 0.816f, -0.408f, 0.408f }} },
{ {{ 1.0f, 1.0f, -1.0f }}, {{ 1.0f, 1.0f }}, {{ 0.666f, 0.333f, -0.666f }} },
{ {{ 1.0f, 1.0f, 1.0f }}, {{ 1.0f, 1.0f }}, {{ 0.333f, 0.666f, 0.666f }} },
{ { { -1.0f, -1.0f, -1.0f } }, { { 0.0f, 0.0f } }, { { -0.666f, -0.333f, -0.666f } } },
{ { { -1.0f, -1.0f, 1.0f } }, { { 0.0f, 0.0f } }, { { -0.333f, -0.666f, 0.666f } } },
{ { { -1.0f, 1.0f, -1.0f } }, { { 0.0f, 1.0f } }, { { -0.408f, 0.816f, -0.408f } } },
{ { { -1.0f, 1.0f, 1.0f } }, { { 0.0f, 1.0f } }, { { -0.816f, 0.408f, 0.408f } } },
{ { { 1.0f, -1.0f, -1.0f } }, { { 1.0f, 0.0f } }, { { 0.408f, -0.816f, -0.408f } } },
{ { { 1.0f, -1.0f, 1.0f } }, { { 1.0f, 0.0f } }, { { 0.816f, -0.408f, 0.408f } } },
{ { { 1.0f, 1.0f, -1.0f } }, { { 1.0f, 1.0f } }, { { 0.666f, 0.333f, -0.666f } } },
{ { { 1.0f, 1.0f, 1.0f } }, { { 1.0f, 1.0f } }, { { 0.333f, 0.666f, 0.666f } } },
};
v11group bounds_face_groups[1] = {
{ NULL, bounds_faces, bounds_colours, NULL, bounds_vertices, bounds_colours, NULL, BR_ASIZE(bounds_faces), BR_ASIZE(bounds_vertices), 18 },
@ -64,7 +64,7 @@ br_model bounds_model = {
// IDA: void __usercall renderFaces(br_actor *actor@<EAX>, br_model *model@<EDX>, br_material *material@<EBX>, void *render_data@<ECX>, br_uint_8 style, int on_screen)
void renderFaces(br_actor* actor, br_model* model, br_material* material, void* render_data, br_uint_8 style, int on_screen) {
LOG_TRACE9("(%p, %p, %p, %p, %d, %d)", actor, model, material, render_data, style, on_screen);
Harness_Hook_renderFaces(model, material, BRT_TRIANGLE);
Harness_Hook_renderFaces(actor, model, material, BRT_TRIANGLE);
}
// IDA: void __usercall renderEdges(br_actor *actor@<EAX>, br_model *model@<EDX>, br_material *material@<EBX>, void *render_data@<ECX>, br_uint_8 style, int on_screen)
@ -123,11 +123,11 @@ br_model* makeMeshFromBounds(br_bounds* b) {
bounds_vertices[7].p.v[2] = b->max.v[2];
// 2. Modify d in the face equation (a*x+b*y+c*y+d=0)
for (i = 0; i < BR_ASIZE(bounds_faces)/4; i++) {
bounds_faces[2*i+0].eqn.v[3] = b->min.v[i];
bounds_faces[2*i+1].eqn.v[3] = b->min.v[i];
bounds_faces[2*i+6].eqn.v[3] = b->max.v[i];
bounds_faces[2*i+7].eqn.v[3] = b->max.v[i];
for (i = 0; i < BR_ASIZE(bounds_faces) / 4; i++) {
bounds_faces[2 * i + 0].eqn.v[3] = b->min.v[i];
bounds_faces[2 * i + 1].eqn.v[3] = b->min.v[i];
bounds_faces[2 * i + 6].eqn.v[3] = b->max.v[i];
bounds_faces[2 * i + 7].eqn.v[3] = b->max.v[i];
}
// 3. Copy bounds

View File

@ -5,6 +5,7 @@
#include "errors.h"
#include "globvars.h"
#include "globvrkm.h"
#include "harness/hooks.h"
#include "harness/trace.h"
#include "spark.h"
#include "utility.h"
@ -261,7 +262,66 @@ void DoDepthByShadeTable(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer
int depth_line_skip;
int render_line_skip;
LOG_TRACE("(%p, %p, %p, %d, %d, %d)", pRender_buffer, pDepth_buffer, pShade_table, pShade_table_power, pStart, pEnd);
NOT_IMPLEMENTED();
// Added to ensure we've copied the framebuffer+depthbuffer back into main memory
Harness_Hook_FlushRenderer();
too_near = 0xffff - (1 << pStart);
shade_table_pixels = pShade_table->pixels;
depth_shift_amount = pShade_table_power + 8 - pStart - pEnd;
render_ptr = (tU8*)pRender_buffer->pixels + pRender_buffer->base_x + pRender_buffer->base_y * pRender_buffer->row_bytes;
depth_ptr = pDepth_buffer->pixels;
render_line_skip = pRender_buffer->row_bytes - pRender_buffer->width;
depth_line_skip = pDepth_buffer->row_bytes / 2 - pRender_buffer->width;
if (depth_shift_amount <= 0) {
if (depth_shift_amount >= 0) {
for (y = 0; pRender_buffer->height > y; ++y) {
for (x = 0; pRender_buffer->width > x; ++x) {
if (*depth_ptr != 0xFFFF) {
depth_value = *depth_ptr - too_near;
if (depth_value < -(int16_t)too_near) {
*render_ptr = shade_table_pixels[(depth_value & 0xFF00) + *render_ptr];
}
}
++render_ptr;
++depth_ptr;
}
render_ptr += render_line_skip;
depth_ptr += depth_line_skip;
}
} else {
for (y = 0; pRender_buffer->height > y; ++y) {
for (x = 0; pRender_buffer->width > x; ++x) {
if (*depth_ptr != 0xFFFF) {
depth_value = *depth_ptr - too_near;
if (depth_value < -(int16_t)too_near) {
*render_ptr = shade_table_pixels[*render_ptr + ((depth_value >> (pEnd - (pShade_table_power + 8 - pStart))) & 0xFF00)];
}
}
++render_ptr;
++depth_ptr;
}
render_ptr += render_line_skip;
depth_ptr += depth_line_skip;
}
}
} else {
for (y = 0; pRender_buffer->height > y; ++y) {
for (x = 0; pRender_buffer->width > x; ++x) {
if (*depth_ptr != 0xFFFF) {
depth_value = *depth_ptr - too_near;
if (depth_value < -(int16_t)too_near) {
*render_ptr = shade_table_pixels[*render_ptr + ((depth_value << depth_shift_amount) & 0xFF00)];
}
}
++render_ptr;
++depth_ptr;
}
render_ptr += render_line_skip;
depth_ptr += depth_line_skip;
}
}
}
// IDA: void __usercall ExternalSky(br_pixelmap *pRender_buffer@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, br_matrix34 *pCamera_to_world@<ECX>)
@ -288,6 +348,8 @@ void ExternalSky(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_act
int repetitions;
br_pixelmap* col_map;
LOG_TRACE("(%p, %p, %p, %p)", pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world);
// TODO: Remove commented block in `ConditionallyFillWithSky` when we implement this properly
return;
dx = 0;
col_map = gHorizon_material->colour_map;
@ -369,31 +431,56 @@ void DoHorizon(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_actor
br_angle yaw;
br_actor* actor;
LOG_TRACE("(%p, %p, %p, %p)", pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world);
NOT_IMPLEMENTED();
STUB_ONCE();
}
// IDA: void __usercall DoDepthCue(br_pixelmap *pRender_buffer@<EAX>, br_pixelmap *pDepth_buffer@<EDX>)
void DoDepthCue(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer) {
LOG_TRACE("(%p, %p)", pRender_buffer, pDepth_buffer);
NOT_IMPLEMENTED();
DoDepthByShadeTable(
pRender_buffer,
pDepth_buffer,
gDepth_shade_table,
gDepth_shade_table_power,
gProgram_state.current_depth_effect.start,
gProgram_state.current_depth_effect.end);
}
// IDA: void __usercall DoFog(br_pixelmap *pRender_buffer@<EAX>, br_pixelmap *pDepth_buffer@<EDX>)
void DoFog(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer) {
LOG_TRACE("(%p, %p)", pRender_buffer, pDepth_buffer);
NOT_IMPLEMENTED();
DoDepthByShadeTable(
pRender_buffer,
pDepth_buffer,
gFog_shade_table,
gFog_shade_table_power,
gProgram_state.current_depth_effect.start,
gProgram_state.current_depth_effect.end);
}
// IDA: void __usercall DepthEffect(br_pixelmap *pRender_buffer@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, br_matrix34 *pCamera_to_world@<ECX>)
void DepthEffect(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_actor* pCamera, br_matrix34* pCamera_to_world) {
LOG_TRACE("(%p, %p, %p, %p)", pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world);
STUB_ONCE();
if (gProgram_state.current_depth_effect.type == eDepth_effect_darkness) {
DoDepthCue(pRender_buffer, pDepth_buffer);
}
if (gProgram_state.current_depth_effect.type == eDepth_effect_fog) {
DoFog(pRender_buffer, pDepth_buffer);
}
}
// IDA: void __usercall DepthEffectSky(br_pixelmap *pRender_buffer@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, br_matrix34 *pCamera_to_world@<ECX>)
void DepthEffectSky(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_actor* pCamera, br_matrix34* pCamera_to_world) {
LOG_TRACE("(%p, %p, %p, %p)", pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world);
STUB_ONCE();
if (gProgram_state.current_depth_effect.sky_texture
&& (!gLast_camera_special_volume || gLast_camera_special_volume->sky_col < 0)) {
DoHorizon(pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world);
}
}
// IDA: void __usercall DoWobbleCamera(br_actor *pCamera@<EAX>)
@ -584,8 +671,8 @@ void IncreaseAngle() {
for (i = 0; i < COUNT_OF(gCamera_list); i++) {
camera_ptr = gCamera_list[i]->type_data;
camera_ptr->field_of_view += 0x1c7; // 2.4993896484375 degrees
if (camera_ptr->field_of_view > 0x78e3) { // 169.9969482421875 degrees
camera_ptr->field_of_view += 0x1c7; // 2.4993896484375 degrees
if (camera_ptr->field_of_view > 0x78e3) { // 169.9969482421875 degrees
camera_ptr->field_of_view = 0x78e3;
}
#ifdef DETHRACE_FIX_BUGS
@ -606,8 +693,8 @@ void DecreaseAngle() {
for (i = 0; i < COUNT_OF(gCamera_list); i++) {
camera_ptr = gCamera_list[i]->type_data;
camera_ptr->field_of_view -= 0x1c7; // 2.4993896484375 degrees
if (camera_ptr->field_of_view < 0x71c) { // 9.99755859375 degrees
camera_ptr->field_of_view -= 0x1c7; // 2.4993896484375 degrees
if (camera_ptr->field_of_view < 0x71c) { // 9.99755859375 degrees
camera_ptr->field_of_view = 0x71c;
}
#ifdef DETHRACE_FIX_BUGS

View File

@ -1188,8 +1188,26 @@ int ConditionallyFillWithSky(br_pixelmap* pPixelmap) {
int bgnd_col;
LOG_TRACE("(%p)", pPixelmap);
STUB_ONCE();
return 0;
// TODO: Uncomment when ExternalSky is fully implemented
LOG_WARN_ONCE("Uncomment this block when ExternalSky is fully implemented");
// if (gProgram_state.current_depth_effect.sky_texture
// && (!gLast_camera_special_volume || gLast_camera_special_volume->sky_col < 0)) {
// return 0;
// }
if (gProgram_state.current_depth_effect.type == eDepth_effect_fog || gSwap_depth_effect_type == eDepth_effect_fog) {
bgnd_col = 255;
} else if (gProgram_state.current_depth_effect.type && gSwap_depth_effect_type) {
if (gLast_camera_special_volume && gLast_camera_special_volume->sky_col >= 0) {
bgnd_col = gLast_camera_special_volume->sky_col;
} else {
bgnd_col = 0;
}
} else {
bgnd_col = 0;
}
BrPixelmapFill(pPixelmap, bgnd_col);
return 1;
}
// IDA: void __usercall RenderAFrame(int pDepth_mask_on@<EAX>)
@ -2295,7 +2313,7 @@ void TellyOutImage(br_pixelmap* pImage, int pLeft, int pTop) {
// IDA: void __usercall SetShadowLevel(tShadow_level pLevel@<EAX>)
void SetShadowLevel(tShadow_level pLevel) {
LOG_TRACE("(%d)", pLevel);
gShadow_level = pLevel;
}

View File

@ -48,7 +48,8 @@ int ChoiceDisabled(int pChoice) {
// IDA: void __cdecl ResetInterfaceTimeout()
void ResetInterfaceTimeout() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gStart_time = PDGetTotalTime();
}
// IDA: void __usercall ChangeSelection(tInterface_spec *pSpec@<EAX>, int *pOld_selection@<EDX>, int *pNew_selection@<EBX>, int pMode@<ECX>, int pSkip_disabled)
@ -182,9 +183,6 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice)
void* palette_copy;
LOG_TRACE("(%p, %d, %d)", pSpec, pOptions, pCurrent_choice);
//added
int last_choice_2;
entry_status = gProgram_state.prog_status;
gTyping_slot = -1;
EdgeTriggerModeOn();
@ -368,7 +366,7 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice)
}
ProcessFlicQueue(gFrame_period);
if (DoMouseCursor() || EitherMouseButtonDown()) {
gStart_time = PDGetTotalTime();
ResetInterfaceTimeout();
}
PDScreenBufferSwap(0);
if (gMouse_in_use && !selection_changed) {
@ -496,13 +494,11 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice)
UnlockFlic(pSpec->pushed_flics[i].flic_index);
}
//v100 = gCurrent_choice;
if (gCurrent_choice == pSpec->escape_code) {
escaped = 1;
go_ahead = 0;
}
if (escaped) {
//v100 = pSpec->escape_code;
gCurrent_choice = pSpec->escape_code;
}
if (pSpec->done_proc) {

View File

@ -54,7 +54,7 @@ int CheckQuit() {
return 0;
}
//IDA: double __cdecl sqr(double pN)
// IDA: double __cdecl sqr(double pN)
double sqr(double pN) {
return pN * pN;
}
@ -289,13 +289,13 @@ char* GetALineWithNoPossibleService(FILE* pF, /*unsigned*/ char* pS) {
pS[i] -= 32;
}
}
//LOG_DEBUG("%s", result);
// LOG_DEBUG("%s", result);
return result;
}
// IDA: char* __usercall GetALineAndDontArgue@<EAX>(FILE *pF@<EAX>, char *pS@<EDX>)
char* GetALineAndDontArgue(FILE* pF, char* pS) {
//LOG_TRACE10("(%p, \"%s\")", pF, pS);
// LOG_TRACE10("(%p, \"%s\")", pF, pS);
PossibleService();
return GetALineWithNoPossibleService(pF, pS);
}
@ -659,7 +659,8 @@ void PrintScreenFile(FILE* pF) {
}
offset -= 2 * gBack_screen->row_bytes;
}
WriteU16L(pF, 0);;
WriteU16L(pF, 0);
;
}
// IDA: void __usercall PrintScreenFile16(FILE *pF@<EAX>)
@ -795,7 +796,7 @@ int FindBestMatch(tRGB_colour* pRGB_colour, br_pixelmap* pPalette) {
LOG_TRACE("(%p, %p)", pRGB_colour, pPalette);
near_c = 127;
min_d = 1.79769e+308; // max double
min_d = 1.79769e+308; // max double
dp = pPalette->pixels;
for (n = 0; n < 256; n++) {
trial_RGB.red = (dp[n] >> 16) & 0xff;
@ -893,9 +894,9 @@ br_pixelmap* GenerateDarkenedShadeTable(int pHeight, br_pixelmap* pPalette, int
ref_col.blue = pBlue_mix;
for (c = 0, tab_ptr = the_table->pixels; c < 256; c++, tab_ptr++) {
the_RGB.red = ((cp[i] >> 16) & 0xff) * pDarken;
the_RGB.green = ((cp[i] >> 8) & 0xff) * pDarken;
the_RGB.blue = ((cp[i] >> 0) & 0xff) * pDarken;
the_RGB.red = ((cp[c] >> 16) & 0xff) * pDarken;
the_RGB.green = ((cp[c] >> 8) & 0xff) * pDarken;
the_RGB.blue = ((cp[c] >> 0) & 0xff) * pDarken;
if (pHeight == 1) {
f_total_minus_1 = 1.;
@ -919,9 +920,9 @@ br_pixelmap* GenerateDarkenedShadeTable(int pHeight, br_pixelmap* pPalette, int
ratio2 = 1. - (1. - pThree_quarter) * (1. - ratio1) * 4.;
}
}
new_RGB.red = ref_col.red * ratio2 + the_RGB.red * (1. - ratio2);
new_RGB.red = ref_col.red * ratio2 + the_RGB.red * (1. - ratio2);
new_RGB.green = ref_col.green * ratio2 + the_RGB.green * (1. - ratio2);
new_RGB.blue = ref_col.blue * ratio2 + the_RGB.blue * (1. - ratio2);
new_RGB.blue = ref_col.blue * ratio2 + the_RGB.blue * (1. - ratio2);
*shade_ptr = FindBestMatch(&new_RGB, pPalette);
}
}
@ -1438,22 +1439,22 @@ int AlreadyBlended(br_material* pMaterial) {
// IDA: void __usercall BlendifyMaterialTablishly(br_material *pMaterial@<EAX>, int pPercent@<EDX>)
void BlendifyMaterialTablishly(br_material* pMaterial, int pPercent) {
char* s;
char* s = NULL;
LOG_TRACE("(%p, %d)", pMaterial, pPercent);
switch (pPercent) {
case 25:
s = "BLEND75.TAB";
break;
case 50:
s = "BLEND50.TAB";
break;
case 75:
s = "BLEND25.TAB";
break;
default:
PDFatalError("Invalid alpha");
break;
case 25:
s = "BLEND75.TAB";
break;
case 50:
s = "BLEND50.TAB";
break;
case 75:
s = "BLEND25.TAB";
break;
default:
PDFatalError("Invalid alpha");
break;
}
pMaterial->index_blend = BrTableFind(s);
if (pMaterial->index_blend == NULL) {
@ -1465,17 +1466,17 @@ void BlendifyMaterialTablishly(br_material* pMaterial, int pPercent) {
void BlendifyMaterialPrimitively(br_material* pMaterial, int pPercent) {
static br_token_value alpha25[3] = {
{ BRT_BLEND_B, { .b = 1 } },
{ BRT_OPACITY_X, { .x = 0x400000 }},
{ BRT_OPACITY_X, { .x = 0x400000 } },
{ 0 },
};
static br_token_value alpha50[3] = {
{ BRT_BLEND_B, { .b = 1 } },
{ BRT_OPACITY_X, { .x = 0x800000 }},
{ BRT_OPACITY_X, { .x = 0x800000 } },
{ 0 },
};
static br_token_value alpha75[3] = {
{ BRT_BLEND_B, { .b = 1 } },
{ BRT_OPACITY_X, { .x = 0xc00000 }},
{ BRT_OPACITY_X, { .x = 0xc00000 } },
{ 0 },
};
LOG_TRACE("(%p, %d)", pMaterial, pPercent);

View File

@ -84,8 +84,11 @@ void DebugCamera_Update() {
glm_normalize_to(direction, cam_front);
}
extern float gCamera_hither;
extern float gCamera_yon;
float* DebugCamera_Projection() {
glm_perspective(glm_rad(55.55), 320.0f / 200.0f /*4.0f / 3.0f*/, 0.1f, 10000.f, projection);
glm_perspective(glm_rad(55.55), 320.0f / 200.0f /*4.0f / 3.0f*/, gCamera_hither, gCamera_yon, projection);
return (float*)&projection;
}

View File

@ -19,7 +19,7 @@ harness_br_renderer* renderer_state;
br_pixelmap* last_dst = NULL;
br_pixelmap* last_src = NULL;
br_pixelmap* color_buffer = NULL;
br_pixelmap *last_colour_buffer, *last_depth_buffer;
unsigned int last_frame_time = 0;
@ -213,14 +213,16 @@ void Harness_Hook_MainGameLoop() {
// Begin 3d scene
void Harness_Hook_BrZbSceneRenderBegin(br_actor* world, br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer) {
last_colour_buffer = colour_buffer;
last_depth_buffer = depth_buffer;
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_renderFaces(br_actor* actor, br_model* model, br_material* material, br_token type) {
platform->RenderModel(actor, model, renderer_state->state.matrix.model_to_view);
}
void Harness_Hook_BrZbSceneRenderEnd() {
@ -231,6 +233,7 @@ void Harness_Hook_BrZbSceneRenderEnd() {
void Harness_Hook_BrPixelmapDoubleBuffer(br_pixelmap* dst, br_pixelmap* src) {
// draw the current colour_buffer (2d screen) contents
platform->FlushBuffers(last_colour_buffer, last_depth_buffer);
Harness_RenderScreen(dst, src);
platform->Swap();
@ -266,4 +269,8 @@ void Harness_Hook_S3Service(int unk1, int unk2) {
}
void Harness_Hook_S3StopAllOutletSounds() {
}
void Harness_Hook_FlushRenderer() {
platform->FlushBuffers(last_colour_buffer, last_depth_buffer);
}

View File

@ -14,10 +14,11 @@ typedef struct tPlatform {
void (*EndScene)();
void (*SetPalette)(uint8_t* palette);
void (*RenderFullScreenQuad)(uint8_t* src, int width, int height);
void (*RenderModel)(br_model* model, br_matrix34 model_matrix);
void (*RenderModel)(br_actor* actor, br_model* model, br_matrix34 model_matrix);
void (*Swap)();
void (*BufferTexture)(br_pixelmap* pm);
void (*BufferMaterial)(br_material* mat);
void (*FlushBuffers)(br_pixelmap* color_buffer, br_pixelmap* depth_buffer);
} tPlatform;

View File

@ -11,6 +11,7 @@ int Harness_Hook_KeyDown(unsigned char pScan_code);
void Harness_Hook_PDServiceSystem();
void Harness_Hook_PDSetKeyArray();
void Harness_Hook_MainGameLoop(); // limit FPS
void Harness_Hook_FlushRenderer(); // synchronize in-memory framebuffer and depthbuffer
// BRender hooks
void Harness_Hook_DOSGfxBegin();
@ -20,7 +21,7 @@ void Harness_Hook_BrPixelmapDoubleBuffer(br_pixelmap* dst, br_pixelmap* src);
void Harness_Hook_BrV1dbRendererBegin();
void Harness_Hook_BrZbSceneRenderBegin(br_actor* world, br_actor* camera, br_pixelmap* colour_buffer, br_pixelmap* depth_buffer);
void Harness_Hook_BrZbSceneRenderAdd(br_actor* tree);
void Harness_Hook_renderFaces(br_model* model, br_material* material, br_token type);
void Harness_Hook_renderFaces(br_actor* actor, br_model* model, br_material* material, br_token type);
void Harness_Hook_BrZbSceneRenderEnd();
void Harness_Hook_BrBufferUpdate(br_pixelmap* pm, br_token use, br_uint_16 flags);
void Harness_Hook_BrMaterialUpdate(br_material* mat, br_uint_16 flags);

View File

@ -9,11 +9,12 @@ void Null_BeginFrame(br_actor* camera, br_pixelmap* colour_buffer) {}
void Null_EndFrame() {}
void Null_SetPalette(uint8_t* palette) {}
void Null_RenderFullScreenQuad(uint8_t* src, int width, int height) {}
void Null_RenderModel(br_model* model, br_matrix34 model_matrix) {}
void Null_RenderModel(br_actor* actor, 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) {}
void Null_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer) {}
tPlatform null_platform = {
Null_Init,
@ -28,5 +29,6 @@ tPlatform null_platform = {
Null_RenderModel,
Null_Swap,
Null_BufferTexture,
Null_BufferMaterial
Null_BufferMaterial,
Null_FlushBuffers
};

View File

@ -18,7 +18,8 @@ tPlatform sdl_gl_platform = {
GLRenderer_RenderModel,
GLRenderer_Swap,
GLRenderer_BufferTexture,
GLRenderer_BufferMaterial
GLRenderer_BufferMaterial,
GLRenderer_FlushBuffers
};
#endif

View File

@ -15,7 +15,7 @@
SDL_Window* window;
SDL_GLContext context;
GLuint screen_buffer_vao, screen_buffer_ebo;
GLuint screen_texture, palette_texture;
GLuint screen_texture, palette_texture, depth_texture;
GLuint shader_program_2d;
GLuint shader_program_3d;
@ -23,11 +23,12 @@ GLuint framebuffer_id, framebuffer_texture = 0;
unsigned int rbo;
uint8_t gl_palette[4 * 256]; // RGBA
uint8_t* screen_buffer_flip_pixels;
uint16_t* depth_buffer_flip_pixels;
int window_width, window_height, render_width, render_height;
br_pixelmap* last_colour_buffer;
br_pixelmap* last_shade_table = NULL;
int dirty_buffers = 0;
struct {
GLuint pixels, shade_table;
@ -210,6 +211,7 @@ void InitializeOpenGLContext() {
glGenTextures(1, &screen_texture);
glGenTextures(1, &palette_texture);
glGenTextures(1, &framebuffer_texture);
glGenTextures(1, &depth_texture);
// setup framebuffer
glGenFramebuffers(1, &framebuffer_id);
@ -221,11 +223,12 @@ void InitializeOpenGLContext() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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, render_width, render_height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
glBindTexture(GL_TEXTURE_2D, depth_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, render_width, render_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_PANIC("Framebuffer is not complete!");
}
@ -268,6 +271,7 @@ void GLRenderer_CreateWindow(char* title, int width, int height, int pRender_wid
InitializeOpenGLContext();
screen_buffer_flip_pixels = malloc(sizeof(uint8_t) * render_width * render_height);
depth_buffer_flip_pixels = malloc(sizeof(uint16_t) * render_width * render_height);
}
void GLRenderer_SetPalette(uint8_t* rgba_colors) {
@ -317,7 +321,6 @@ void GLRenderer_SetShadeTable(br_pixelmap* table) {
extern br_v1db_state v1db;
void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer) {
last_colour_buffer = colour_buffer;
glViewport(colour_buffer->base_x, colour_buffer->base_y, colour_buffer->width, colour_buffer->height);
glEnable(GL_DEPTH_TEST);
@ -363,26 +366,13 @@ void GLRenderer_EndScene() {
// switch back to default fb
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// pull framebuffer into cpu memory to emulate BRender behavior
glBindTexture(GL_TEXTURE_2D, framebuffer_texture);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, screen_buffer_flip_pixels);
// flip texture to match the expected orientation
int dest_y = render_height;
uint8_t* pm_pixels = last_colour_buffer->pixels;
for (int y = 0; y < render_height; y++) {
dest_y--;
for (int x = 0; x < render_width; x++) {
pm_pixels[dest_y * render_width + x] = screen_buffer_flip_pixels[y * render_width + x];
}
}
CHECK_GL_ERROR("GLRenderer_RenderFullScreenQuad");
}
void GLRenderer_RenderFullScreenQuad(uint8_t* screen_buffer, int width, int height) {
glViewport(0, 0, window_width, window_height);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glUseProgram(shader_program_2d);
glBindTexture(GL_TEXTURE_2D, screen_texture);
@ -501,7 +491,30 @@ void build_model(br_model* model) {
CHECK_GL_ERROR("after build model");
}
void GLRenderer_RenderModel(br_model* model, br_matrix34 model_matrix) {
void setActiveMaterial(tStored_material* material) {
if (material) {
glUniform1i(uniforms_3d.palette_index_override, material->index_base);
if (material->shade_table) {
GLRenderer_SetShadeTable(material->shade_table);
}
if ((material->flags & BR_MATF_LIGHT) && material->shade_table) {
// TODO: light value shouldn't always be 0? Works for shadows, not sure about other things.
glUniform1i(uniforms_3d.light_value, 0);
} else {
glUniform1i(uniforms_3d.light_value, -1);
}
if (material->texture) {
tStored_pixelmap* stored_px = material->texture->stored;
if (stored_px) {
glBindTexture(GL_TEXTURE_2D, stored_px->id);
glUniform1i(uniforms_3d.palette_index_override, -1);
}
}
}
}
void GLRenderer_RenderModel(br_actor* actor, br_model* model, br_matrix34 model_matrix) {
tStored_model_context* ctx;
ctx = model->stored;
v11model* v11 = model->prepared;
@ -536,41 +549,27 @@ void GLRenderer_RenderModel(br_model* model, br_matrix34 model_matrix) {
int element_index = 0;
// br_actor can have a material too, which is applied to the faces if the face doesn't have a texture
if (actor->material) {
setActiveMaterial(actor->material->stored);
} else {
// TODO: set defaults for now. This fixes missing curb materials but probably isn't the right fix.
LOG_WARN_ONCE("set default palette override for missing actor material")
glUniform1i(uniforms_3d.palette_index_override, 227);
glUniform1i(uniforms_3d.light_value, -1);
}
v11group* group;
for (int g = 0; g < v11->ngroups; g++) {
group = &v11->groups[g];
tStored_material* material = group->stored;
if (material) {
glUniform1i(uniforms_3d.palette_index_override, material->index_base);
if (material->shade_table) {
GLRenderer_SetShadeTable(material->shade_table);
}
if ((material->flags & BR_MATF_LIGHT) && material->shade_table) {
// TODO: light value shouldn't always be 0? Works for shadows, not sure about other things.
glUniform1i(uniforms_3d.light_value, 0);
} else {
glUniform1i(uniforms_3d.light_value, -1);
}
if (material->texture) {
tStored_pixelmap* stored_px = material->texture->stored;
if (stored_px) {
glBindTexture(GL_TEXTURE_2D, stored_px->id);
glUniform1i(uniforms_3d.palette_index_override, -1);
}
}
} else {
// LOG_WARN("no material");
glUniform1i(uniforms_3d.palette_index_override, 0);
glUniform1i(uniforms_3d.light_value, -1);
}
setActiveMaterial(group->stored);
glDrawElements(GL_TRIANGLES, group->nfaces * 3, GL_UNSIGNED_INT, (void*)(element_index * sizeof(int)));
element_index += group->nfaces * 3;
}
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
dirty_buffers = 1;
CHECK_GL_ERROR("GLRenderer_RenderModel");
}
@ -616,6 +615,47 @@ void GLRenderer_BufferTexture(br_pixelmap* pm) {
CHECK_GL_ERROR("GLRenderer_BufferTexture");
}
void GLRenderer_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer) {
if (!dirty_buffers) {
return;
}
// pull framebuffer into cpu memory to emulate BRender behavior
glBindTexture(GL_TEXTURE_2D, framebuffer_texture);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, screen_buffer_flip_pixels);
// flip texture to match the expected orientation
int dest_y = render_height;
uint8_t* pm_pixels = color_buffer->pixels;
uint8_t new_pixel;
for (int y = 0; y < render_height; y++) {
dest_y--;
for (int x = 0; x < render_width; x++) {
new_pixel = screen_buffer_flip_pixels[y * render_width + x];
if (new_pixel != 0) {
pm_pixels[dest_y * render_width + x] = screen_buffer_flip_pixels[y * render_width + x];
}
}
}
// pull depthbuffer into cpu memory to emulate BRender behavior
glBindTexture(GL_TEXTURE_2D, depth_texture);
glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depth_buffer_flip_pixels);
dest_y = render_height;
uint16_t* depth_pixels = depth_buffer->pixels;
for (int y = 0; y < render_height; y++) {
dest_y--;
for (int x = 0; x < render_width; x++) {
depth_pixels[dest_y * render_width + x] = depth_buffer_flip_pixels[y * render_width + x];
}
}
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_id);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
dirty_buffers = 0;
}
void Harness_GLRenderer_RenderCube(float col, float x, float y, float z) {
// // Enable depth test

View File

@ -18,8 +18,9 @@ void GLRenderer_BeginScene(br_actor* camera, br_pixelmap* colour_buffer);
void GLRenderer_EndScene();
void GLRenderer_RenderFullScreenQuad(uint8_t* screen_buffer, int width, int height);
void GLRenderer_Swap();
void GLRenderer_RenderModel(br_model* model, br_matrix34 model_matrix);
void GLRenderer_RenderModel(br_actor* actor, br_model* model, br_matrix34 model_matrix);
void GLRenderer_BufferTexture(br_pixelmap* pm);
void GLRenderer_BufferMaterial(br_material* mat);
void GLRenderer_FlushBuffers(br_pixelmap* color_buffer, br_pixelmap* depth_buffer);
#endif

View File

@ -71,6 +71,9 @@ const char* fs_3d = "#version 330 core\n"
" } else {\n"
" palette_index = texelFetch(shade_table, ivec2(texel, light_value), 0).x;\n"
" }\n"
" if (palette_index == 0u) {\n"
" discard;\n"
" }\n"
" }\n"
" else {\n"
" palette_index = uint(palette_index_override);\n"