Adds original 3dfx rendering path (#434)
* using dossys, virtual_fb driver * keyboard and hires working with dossys * adds explicit opengl mode, opengles support, use-after-free fix * remove compiler warnings * bump BRender dep to latest commit * adds mouse code from DOS version which correctly scales based on pixel size * more 3dfx fixes, adds game-completed arg
This commit is contained in:
parent
1ef129a7bf
commit
ca1ef76e7f
|
@ -16,7 +16,7 @@ jobs:
|
|||
matrix:
|
||||
platform:
|
||||
- { name: 'Linux', arch: 'x64', os: ubuntu-latest, werror: true }
|
||||
- { name: 'Linux', arch: 'arm64', os: ubuntu-latest, werror: true, cmake-toolchain-file: 'cmake/toolchains/linux-aarch64.cmake', apt-packages: 'gcc-aarch64-linux-gnu g++-aarch64-linux-gnu', cross: true }
|
||||
- { name: 'Linux', arch: 'arm64', os: ubuntu-24.04-arm, werror: true }
|
||||
- { name: 'MacOS', arch: 'arm64-x64', os: macos-latest, werror: true, cmake-args: '-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"' }
|
||||
- { name: 'Windows', arch: 'x86', os: windows-latest, msvc-arch: 'Win32' }
|
||||
- { name: 'Windows', arch: 'x64', os: windows-latest, msvc-arch: 'x64' }
|
||||
|
@ -45,12 +45,13 @@ jobs:
|
|||
- name: Set up SDL
|
||||
uses: libsdl-org/setup-sdl@main
|
||||
with:
|
||||
add-to-environment: true
|
||||
build-type: Release
|
||||
cmake-arguments: ${{ matrix.platform.cmake-args }}
|
||||
cmake-generator: Ninja
|
||||
cmake-toolchain-file: ${{ matrix.platform.cmake-toolchain-file }}
|
||||
discriminator: ${{ matrix.platform.arch }}
|
||||
version: 2-latest
|
||||
add-to-environment: true
|
||||
|
||||
- name: 'Prepare sources for release'
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
run: |
|
||||
|
|
|
@ -37,6 +37,7 @@ option(BUILD_TESTS "Build unit tests." OFF)
|
|||
option(DETHRACE_INSTALL "Add install target" OFF)
|
||||
option(DETHRACE_WERROR "Treat warnings as errors")
|
||||
option(DETHRACE_FIX_BUGS "Fix Dethrace bugs" ON)
|
||||
option(DETHRACE_3DFX_PATCH "Include changes from VOODOO2C.EXE" ON)
|
||||
|
||||
function(add_compile_flag_if_supported TARGET FLAG)
|
||||
cmake_parse_arguments(ARGS "" "" "LANGUAGES" ${ARGN})
|
||||
|
@ -47,6 +48,7 @@ function(add_compile_flag_if_supported TARGET FLAG)
|
|||
set(HAVE_FLAG_VARIABLE_NAME "HAVE_${FLAG_TO_IDENTIFIER}")
|
||||
check_c_compiler_flag("${FLAG}" "${HAVE_FLAG_VARIABLE_NAME}")
|
||||
if(${HAVE_FLAG_VARIABLE_NAME})
|
||||
string(REPLACE ";" "," ARGS_LANGUAGES "${ARGS_LANGUAGES}")
|
||||
target_compile_options("${TARGET}" PRIVATE "$<$<COMPILE_LANGUAGE:${ARGS_LANGUAGES}>:${FLAG}>")
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Dethrace
|
||||
# Dethrace
|
||||
|
||||
[](https://github.com/dethrace-labs/dethrace/actions/workflows/workflow.yml)
|
||||
[](https://twitter.com/dethrace_labs)
|
||||
|
@ -9,8 +9,8 @@ Dethrace is an attempt to learn how the 1997 driving/mayhem game [Carmageddon](h
|
|||
## Progress
|
||||
(Follow us on Discord or Twitter to get notified of updates!)
|
||||
|
||||
#### Last updated June 17 2024
|
||||
- 92% of functions implemented
|
||||
#### Last updated March 2025
|
||||
- 94% of functions implemented
|
||||
- Latest screenshot:
|
||||
|
||||
<img width="752" alt="Screenshot 2024-05-27 at 8 44 10 AM" src="https://github.com/dethrace-labs/dethrace/assets/1063652/10b3b579-1eb1-4242-8b56-ff062cfff810">
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 9c34086300f4f0bbb3a55206380f25b17dad6c12
|
||||
Subproject commit ee344356e359d9b9b310dda08e3be672da9b7f01
|
|
@ -40,6 +40,9 @@ target_compile_definitions(dethrace_obj PRIVATE INSIDE_DETHRACE)
|
|||
if(DETHRACE_FIX_BUGS)
|
||||
target_compile_definitions(dethrace_obj PRIVATE DETHRACE_FIX_BUGS)
|
||||
endif()
|
||||
if(DETHRACE_3DFX_PATCH)
|
||||
target_compile_definitions(dethrace_obj PRIVATE DETHRACE_3DFX_PATCH)
|
||||
endif()
|
||||
|
||||
if(IS_BIGENDIAN)
|
||||
target_compile_definitions(dethrace_obj PRIVATE BR_ENDIAN_BIG=1)
|
||||
|
|
|
@ -994,6 +994,7 @@ void FinishCars(tU32 pLast_frame_time, tU32 pTime) {
|
|||
BrVector3SetFloat(&minus_k, 0.f, 0.f, -1.f);
|
||||
}
|
||||
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) / harness_game_config.physics_step_time);
|
||||
|
@ -2591,7 +2592,7 @@ void CalcForce(tCar_spec* c, br_scalar dt) {
|
|||
ApplyTorque(c, &rightplane);
|
||||
BrVector3Scale(&rightplane, &b, dt / c->M);
|
||||
BrVector3Accumulate(&c->v, &rightplane);
|
||||
if (c->speed < 0.000099999997
|
||||
if (c->speed < 0.0001f
|
||||
&& ((!c->keys.acc && c->joystick.acc <= 0) || !c->gear)
|
||||
&& !c->keys.dec
|
||||
&& c->joystick.dec <= 0
|
||||
|
@ -5243,6 +5244,7 @@ void NormalPositionExternalCamera(tCar_spec* c, tU32 pTime) {
|
|||
manual_swing = gOld_yaw__car != gCamera_yaw || swoop;
|
||||
manual_zoom = (double)gOld_zoom != gCamera_zoom;
|
||||
BrVector3Copy(&old_camera_pos, &gCamera->t.t.translate.t);
|
||||
|
||||
if (!gProgram_state.cockpit_on) {
|
||||
if (swoop) {
|
||||
gCamera_yaw = 0;
|
||||
|
@ -7517,5 +7519,6 @@ int GetPrecalculatedFacesUnderCar(tCar_spec* pCar, tFace_ref** pFace_refs) {
|
|||
// IDA: br_material* __cdecl SomeNearbyMaterial()
|
||||
br_material* SomeNearbyMaterial(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
return gFace_list__car[gProgram_state.current_car.box_face_start].material;
|
||||
}
|
||||
|
|
|
@ -4,11 +4,14 @@
|
|||
#include "displays.h"
|
||||
#include "errors.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrkm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "harness/hooks.h"
|
||||
#include "harness/trace.h"
|
||||
#include "init.h"
|
||||
#include "pd/sys.h"
|
||||
#include "pedestrn.h"
|
||||
#include "replay.h"
|
||||
#include "spark.h"
|
||||
#include "trig.h"
|
||||
|
@ -99,7 +102,8 @@ br_scalar CalculateWrappingMultiplier(br_scalar pValue, br_scalar pYon) {
|
|||
// IDA: br_scalar __usercall DepthCueingShiftToDistance@<ST0>(int pShift@<EAX>)
|
||||
br_scalar DepthCueingShiftToDistance(int pShift) {
|
||||
LOG_TRACE("(%d)", pShift);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
return powf(10.0f, pShift * 0.1f) * gCamera_yon;
|
||||
}
|
||||
|
||||
// IDA: void __usercall FogAccordingToGPSCDE(br_material *pMaterial@<EAX>)
|
||||
|
@ -107,7 +111,29 @@ void FogAccordingToGPSCDE(br_material* pMaterial) {
|
|||
int start;
|
||||
int end;
|
||||
LOG_TRACE("(%p)", pMaterial);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
start = gProgram_state.current_depth_effect.start;
|
||||
end = gProgram_state.current_depth_effect.end;
|
||||
|
||||
switch (gProgram_state.current_depth_effect.type) {
|
||||
case eDepth_effect_darkness:
|
||||
pMaterial->fog_min = DepthCueingShiftToDistance(-start);
|
||||
pMaterial->fog_colour = BR_COLOUR_RGB(0, 0, 0);
|
||||
pMaterial->flags |= BR_MATF_FOG_LOCAL;
|
||||
pMaterial->fog_max = DepthCueingShiftToDistance(end);
|
||||
break;
|
||||
case eDepth_effect_fog:
|
||||
pMaterial->fog_min = DepthCueingShiftToDistance(-start);
|
||||
pMaterial->fog_colour = BR_COLOUR_RGB(248, 248, 248);
|
||||
pMaterial->flags |= BR_MATF_FOG_LOCAL;
|
||||
pMaterial->fog_max = DepthCueingShiftToDistance(end);
|
||||
break;
|
||||
case eDepth_effect_none:
|
||||
pMaterial->flags &= ~BR_MATF_FOG_LOCAL;
|
||||
break;
|
||||
}
|
||||
|
||||
BrMaterialUpdate(pMaterial, BR_MATU_ALL);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl FrobFog()
|
||||
|
@ -115,7 +141,27 @@ void FrobFog(void) {
|
|||
int i;
|
||||
br_material* mat;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gTrack_actor) {
|
||||
ProcessMaterials(gTrack_actor, (tPMFM2CB*)FogAccordingToGPSCDE);
|
||||
}
|
||||
if (gNon_track_actor) {
|
||||
ProcessMaterials(gNon_track_actor, (tPMFM2CB*)FogAccordingToGPSCDE);
|
||||
}
|
||||
for (i = 0; i < COUNT_OF(gMaterial); i++) {
|
||||
mat = gMaterial[i];
|
||||
FogAccordingToGPSCDE(mat);
|
||||
}
|
||||
for (i = 0; i < COUNT_OF(gCurrent_race.material_modifiers); i++) {
|
||||
mat = gCurrent_race.material_modifiers[i].skid_mark_material;
|
||||
if (mat) {
|
||||
FogAccordingToGPSCDE(mat);
|
||||
}
|
||||
}
|
||||
FogAccordingToGPSCDE(gDefault_track_material);
|
||||
if (gPed_material) {
|
||||
FogAccordingToGPSCDE(gPed_material);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall InstantDepthChange(tDepth_effect_type pType@<EAX>, br_pixelmap *pSky_texture@<EDX>, int pStart@<EBX>, int pEnd@<ECX>)
|
||||
|
@ -136,6 +182,12 @@ void InstantDepthChange(tDepth_effect_type pType, br_pixelmap* pSky_texture, int
|
|||
gProgram_state.default_depth_effect.type = pType;
|
||||
gProgram_state.default_depth_effect.start = pStart;
|
||||
gProgram_state.default_depth_effect.end = pEnd;
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gMaterial_fogging) {
|
||||
FrobFog();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: br_scalar __cdecl Tan(br_scalar pAngle)
|
||||
|
@ -338,14 +390,19 @@ void InitDepthEffects(void) {
|
|||
if (gHorizon_material == NULL) {
|
||||
FatalError(kFatalError_FindSkyMaterial_S, "HORIZON.MAT"); // 2nd argument added
|
||||
}
|
||||
gHorizon_material->index_blend = BrPixelmapAllocate(BR_PMT_INDEX_8, 256, 256, NULL, 0);
|
||||
BrTableAdd(gHorizon_material->index_blend);
|
||||
for (i = 0; i < 256; i++) {
|
||||
for (j = 0; j < 256; j++) {
|
||||
*((tU8*)gHorizon_material->index_blend->pixels + 256 * i + j) = j;
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gScreen->type == BR_PMT_INDEX_8 && !gMaterial_fogging)
|
||||
#endif
|
||||
{
|
||||
gHorizon_material->index_blend = BrPixelmapAllocate(BR_PMT_INDEX_8, 256, 256, NULL, 0);
|
||||
BrTableAdd(gHorizon_material->index_blend);
|
||||
for (i = 0; i < 256; i++) {
|
||||
for (j = 0; j < 256; j++) {
|
||||
*((tU8*)gHorizon_material->index_blend->pixels + 256 * i + j) = j;
|
||||
}
|
||||
}
|
||||
gHorizon_material->flags |= BR_MATF_PERSPECTIVE;
|
||||
}
|
||||
gHorizon_material->flags |= BR_MATF_PERSPECTIVE;
|
||||
BrMaterialAdd(gHorizon_material);
|
||||
gForward_sky_model = CreateHorizonModel(gCamera);
|
||||
gRearview_sky_model = CreateHorizonModel(gRearview_camera);
|
||||
|
@ -520,9 +577,15 @@ void DoHorizon(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_actor
|
|||
LOG_TRACE("(%p, %p, %p, %p)", pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world);
|
||||
|
||||
yaw = BrRadianToAngle(atan2f(pCamera_to_world->m[2][0], pCamera_to_world->m[2][2]));
|
||||
if (!gProgram_state.cockpit_on && !(gAction_replay_mode && gAction_replay_camera_mode)) {
|
||||
if (!gProgram_state.cockpit_on && !gAction_replay_mode && gAction_replay_camera_mode != eAction_replay_standard
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
&& !gBlitting_is_slow
|
||||
#endif
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gRendering_mirror) {
|
||||
actor = gRearview_sky_actor;
|
||||
} else {
|
||||
|
@ -577,6 +640,11 @@ void DoFog(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer) {
|
|||
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);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gMaterial_fogging) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (gProgram_state.current_depth_effect.type == eDepth_effect_darkness) {
|
||||
DoDepthCue(pRender_buffer, pDepth_buffer);
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
#include "constants.h"
|
||||
#include "controls.h"
|
||||
#include "depth.h"
|
||||
#include "errors.h"
|
||||
#include "flicplay.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrkm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "grafdata.h"
|
||||
|
@ -230,7 +232,25 @@ void DRPixelmapCleverText2(br_pixelmap* pPixelmap, int pX, int pY, tDR_font* pFo
|
|||
// IDA: void __usercall DeviouslyDimRectangle(br_pixelmap *pPixelmap@<EAX>, int pLeft@<EDX>, int pTop@<EBX>, int pRight@<ECX>, int pBottom, int pKnock_out_corners)
|
||||
void DeviouslyDimRectangle(br_pixelmap* pPixelmap, int pLeft, int pTop, int pRight, int pBottom, int pKnock_out_corners) {
|
||||
LOG_TRACE("(%p, %d, %d, %d, %d, %d)", pPixelmap, pLeft, pTop, pRight, pBottom, pKnock_out_corners);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pPixelmap != gBack_screen) {
|
||||
FatalError(124);
|
||||
}
|
||||
|
||||
gDim_model->vertices[1].p.v[0] = pLeft;
|
||||
gDim_model->vertices[0].p.v[0] = pLeft;
|
||||
gDim_model->vertices[3].p.v[0] = pRight;
|
||||
gDim_model->vertices[2].p.v[0] = pRight;
|
||||
gDim_model->vertices[3].p.v[1] = -pTop;
|
||||
gDim_model->vertices[0].p.v[1] = -pTop;
|
||||
gDim_model->vertices[2].p.v[1] = -pBottom;
|
||||
gDim_model->vertices[1].p.v[1] = -pBottom;
|
||||
BrModelUpdate(gDim_model, BR_MODU_VERTEX_POSITIONS);
|
||||
gDim_actor->render_style = BR_RSTYLE_FACES;
|
||||
PDUnlockRealBackScreen(1);
|
||||
BrZbSceneRender(g2d_camera, g2d_camera, gBack_screen, gDepth_buffer);
|
||||
PDLockRealBackScreen(1);
|
||||
gDim_actor->render_style = BR_RSTYLE_NONE;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl DimRectangle(br_pixelmap *pPixelmap, int pLeft, int pTop, int pRight, int pBottom, int pKnock_out_corners)
|
||||
|
@ -244,6 +264,11 @@ void DimRectangle(br_pixelmap* pPixelmap, int pLeft, int pTop, int pRight, int p
|
|||
int width;
|
||||
LOG_TRACE9("(%p, %d, %d, %d, %d, %d)", pPixelmap, pLeft, pTop, pRight, pBottom, pKnock_out_corners);
|
||||
|
||||
if (gDevious_2d) {
|
||||
DeviouslyDimRectangle(pPixelmap, pLeft, pTop, pRight, pBottom, pKnock_out_corners);
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = (tU8*)pPixelmap->pixels + pLeft + pPixelmap->row_bytes * pTop;
|
||||
line_skip = pPixelmap->row_bytes - pRight + pLeft;
|
||||
depth_table_ptr = gDepth_shade_table->pixels;
|
||||
|
@ -316,6 +341,12 @@ void DoPSPowerHeadup(int pY, int pLevel, char* pName, int pBar_colour) {
|
|||
int i;
|
||||
LOG_TRACE("(%d, %d, \"%s\", %d)", pY, pLevel, pName, pBar_colour);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gBack_screen->type == BR_PMT_RGB_565) {
|
||||
pBar_colour = PaletteEntry16Bit(gRender_palette, pBar_colour);
|
||||
}
|
||||
#endif
|
||||
|
||||
DimRectangle(gBack_screen, gCurrent_graf_data->ps_dim_left, pY, gCurrent_graf_data->ps_dim_right, gCurrent_graf_data->ps_dim_height + pY, 1);
|
||||
TransDRPixelmapText(gBack_screen, gCurrent_graf_data->ps_name_left, gCurrent_graf_data->ps_name_top_border + pY, gFonts + 6, pName, gBack_screen->width);
|
||||
|
||||
|
@ -1158,7 +1189,11 @@ void DoInstruments(tU32 pThe_time) {
|
|||
+ (double)the_wobble_y),
|
||||
gProgram_state.current_car.tacho_needle_colour[gProgram_state.cockpit_on]);
|
||||
} else if (tacho_image != NULL) {
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
DRPixelmapRectangleCopy(
|
||||
#else
|
||||
BrPixelmapRectangleCopy(
|
||||
#endif
|
||||
gBack_screen,
|
||||
the_wobble_x + gProgram_state.current_car.tacho_x[gProgram_state.cockpit_on],
|
||||
the_wobble_y + gProgram_state.current_car.tacho_y[gProgram_state.cockpit_on],
|
||||
|
|
|
@ -131,6 +131,18 @@ char* gError_messages[126] = {
|
|||
"Net contents too big %",
|
||||
"File % is corrupted",
|
||||
"Random number out of range (%)",
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
"Couldn't lock pixelmap %",
|
||||
"% should be locked but isn't",
|
||||
"Cannot purify pixelmap %",
|
||||
"File % must start with \"%\"",
|
||||
"Can't cope with version % for %",
|
||||
"Cannot tile pixelmap %",
|
||||
"Mysterious \"%\" in %",
|
||||
"Can only dim rectangles of gBack_screen",
|
||||
"Invalid material alpha"
|
||||
#endif
|
||||
};
|
||||
int gError_code;
|
||||
char* gPalette_copy__errors; // suffix added to avoid duplicate symbol
|
||||
|
|
|
@ -1838,7 +1838,16 @@ void InitialiseFlicPanel(int pIndex, int pLeft, int pTop, int pWidth, int pHeigh
|
|||
"Bruce bug at line %d, file ..\\..\\source\\common\\flicplay.c",
|
||||
68);
|
||||
}
|
||||
gPanel_buffer[pIndex] = DRPixelmapAllocate(gScreen->type, pWidth, pHeight, the_pixels, 0);
|
||||
gPanel_buffer[pIndex] = DRPixelmapAllocate(
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
gBack_screen->type,
|
||||
#else
|
||||
gScreen->type,
|
||||
#endif
|
||||
pWidth,
|
||||
pHeight,
|
||||
the_pixels,
|
||||
0);
|
||||
}
|
||||
|
||||
// IDA: void __usercall DisposeFlicPanel(int pIndex@<EAX>)
|
||||
|
|
|
@ -34,3 +34,6 @@ int gMax_texture_side;
|
|||
int gDevious_2d;
|
||||
int gMax_texture_aspect_ratio;
|
||||
int gMaterial_fogging;
|
||||
|
||||
// Added
|
||||
int gVoodoo_rush_mode;
|
||||
|
|
|
@ -37,4 +37,6 @@ extern int gDevious_2d;
|
|||
extern int gMax_texture_aspect_ratio;
|
||||
extern int gMaterial_fogging;
|
||||
|
||||
extern int gVoodoo_rush_mode;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "finteray.h"
|
||||
#include "flicplay.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "grafdata.h"
|
||||
#include "harness/hooks.h"
|
||||
|
@ -336,6 +337,11 @@ void DRDrawLine(br_pixelmap* pDestn, int pX1, int pY1, int pX2, int pY2, int pCo
|
|||
int the_diff;
|
||||
LOG_TRACE("(%p, %d, %d, %d, %d, %d)", pDestn, pX1, pY1, pX2, pY2, pColour);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gBack_screen->type == BR_PMT_RGB_565) {
|
||||
pColour = PaletteEntry16Bit(gRender_palette, pColour);
|
||||
}
|
||||
#endif
|
||||
BrPixelmapLine(pDestn, pX1, pY1, pX2, pY2, pColour);
|
||||
}
|
||||
|
||||
|
@ -425,7 +431,10 @@ void CopyWords(char* pDst, char* pSrc, int pN) {
|
|||
tU16* dst;
|
||||
tU16* src;
|
||||
LOG_TRACE("(\"%s\", \"%s\", %d)", pDst, pSrc, pN);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
dst = (tU16*)pDst;
|
||||
src = (tU16*)pSrc;
|
||||
BrMemCpy(dst, src, pN);
|
||||
}
|
||||
|
||||
// IDA: void __usercall Copy8BitStripImageTo16Bit(br_pixelmap *pDest@<EAX>, br_int_16 pDest_x@<EDX>, br_int_16 pOffset_x@<EBX>, br_int_16 pDest_y@<ECX>, br_int_16 pOffset_y, tS8 *pSource, br_int_16 pSource_x, br_int_16 pSource_y, br_uint_16 pWidth, br_uint_16 pHeight)
|
||||
|
@ -442,7 +451,66 @@ void Copy8BitStripImageTo16Bit(br_pixelmap* pDest, br_int_16 pDest_x, br_int_16
|
|||
char* destn_ptr;
|
||||
char* destn_ptr2;
|
||||
LOG_TRACE("(%p, %d, %d, %d, %d, %p, %d, %d, %d, %d)", pDest, pDest_x, pOffset_x, pDest_y, pOffset_y, pSource, pSource_x, pSource_y, pWidth, pHeight);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
height = *(uint16_t*)pSource;
|
||||
pSource = pSource + 2;
|
||||
if (pDest_y + pOffset_y >= 0) {
|
||||
destn_ptr = (char*)pDest->pixels + pDest->row_bytes * (pDest_y + pOffset_y);
|
||||
} else {
|
||||
pSource = SkipLines(pSource, -pDest_y - pOffset_y);
|
||||
destn_ptr = (char*)pDest->pixels;
|
||||
height += pDest_y + pOffset_y;
|
||||
pOffset_y = 0;
|
||||
pDest_y = 0;
|
||||
}
|
||||
|
||||
if (height + pDest_y + pOffset_y > pDest->height) {
|
||||
height = pDest->height - pDest_y - pOffset_y;
|
||||
}
|
||||
if (gBack_screen->type == BR_PMT_RGB_565) {
|
||||
pDest_x *= 2;
|
||||
pOffset_x *= 2;
|
||||
if (pDest_x + pOffset_x > 0) {
|
||||
destn_ptr += 2 * pDest_x + 2 * pOffset_x;
|
||||
}
|
||||
destn_width = 2 * pDest->width;
|
||||
}
|
||||
for (i = 0; i < height; i++) {
|
||||
number_of_chunks = *pSource;
|
||||
pSource++;
|
||||
destn_ptr2 = destn_ptr;
|
||||
|
||||
x_byte = pOffset_x + pDest_x;
|
||||
for (j = 0; j < number_of_chunks; j++) {
|
||||
chunk_length = *pSource;
|
||||
pSource++;
|
||||
if (chunk_length >= 0) {
|
||||
old_x_byte = x_byte;
|
||||
x_byte += chunk_length;
|
||||
if (old_x_byte >= 0) {
|
||||
destn_ptr2 += chunk_length;
|
||||
} else if (x_byte > 0) {
|
||||
destn_ptr2 += chunk_length + old_x_byte;
|
||||
}
|
||||
} else {
|
||||
old_x_byte = x_byte;
|
||||
x_byte += -chunk_length;
|
||||
if (old_x_byte >= 0) {
|
||||
if (destn_width >= x_byte) {
|
||||
CopyWords(destn_ptr2, (char*)pSource, -chunk_length);
|
||||
destn_ptr2 += -chunk_length;
|
||||
} else if (old_x_byte < destn_width) {
|
||||
CopyWords(destn_ptr2, (char*)pSource, destn_width - old_x_byte);
|
||||
}
|
||||
} else if (x_byte > 0) {
|
||||
CopyWords(destn_ptr2, (char*)&pSource[-old_x_byte], -chunk_length + old_x_byte);
|
||||
destn_ptr2 += -chunk_length + old_x_byte;
|
||||
}
|
||||
pSource += -chunk_length;
|
||||
}
|
||||
}
|
||||
destn_ptr += pDest->row_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall CopyStripImage(br_pixelmap *pDest@<EAX>, br_int_16 pDest_x@<EDX>, br_int_16 pOffset_x@<EBX>, br_int_16 pDest_y@<ECX>, br_int_16 pOffset_y, tS8 *pSource, br_int_16 pSource_x, br_int_16 pSource_y, br_uint_16 pWidth, br_uint_16 pHeight)
|
||||
|
@ -460,6 +528,21 @@ void CopyStripImage(br_pixelmap* pDest, br_int_16 pDest_x, br_int_16 pOffset_x,
|
|||
char* destn_ptr2;
|
||||
LOG_TRACE8("(%p, %d, %d, %d, %d, %p, %d, %d, %d, %d)", pDest, pDest_x, pOffset_x, pDest_y, pOffset_y, pSource, pSource_x, pSource_y, pWidth, pHeight);
|
||||
|
||||
if (gBack_screen->type == BR_PMT_RGB_565) {
|
||||
Copy8BitStripImageTo16Bit(
|
||||
pDest,
|
||||
pDest_x,
|
||||
pOffset_x,
|
||||
pDest_y,
|
||||
pOffset_y,
|
||||
pSource,
|
||||
pSource_x,
|
||||
pSource_y,
|
||||
pWidth,
|
||||
pHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
height = *(uint16_t*)pSource;
|
||||
pSource = pSource + 2;
|
||||
if (pDest_y + pOffset_y >= 0) {
|
||||
|
@ -549,6 +632,7 @@ void SetBRenderScreenAndBuffers(int pX_offset, int pY_offset, int pWidth, int pH
|
|||
if (gDepth_buffer == NULL) {
|
||||
FatalError(kFatalError_AllocateZBuffer);
|
||||
}
|
||||
|
||||
BrZbBegin(gRender_screen->type, gDepth_buffer->type);
|
||||
gBrZb_initialized = 1;
|
||||
}
|
||||
|
@ -563,7 +647,7 @@ void SetIntegerMapRenders(void) {
|
|||
gMap_render_height_i = ((int)gMap_render_height) & ~1;
|
||||
if (gReal_graf_data_index != 0) {
|
||||
gMap_render_x_i = 2 * gMap_render_x_i;
|
||||
gMap_render_y_i = 2 * gMap_render_y_i + 40;
|
||||
gMap_render_y_i = 2 * gMap_render_y_i + HIRES_Y_OFFSET;
|
||||
gMap_render_width_i = 2 * gMap_render_width_i;
|
||||
gMap_render_height_i = 2 * gMap_render_height_i;
|
||||
}
|
||||
|
@ -641,6 +725,9 @@ void DRSetPaletteEntries(br_pixelmap* pPalette, int pFirst_colour, int pCount) {
|
|||
((br_int_32*)pPalette->pixels)[0] = 0;
|
||||
}
|
||||
memcpy(gCurrent_palette_pixels + 4 * pFirst_colour, (char*)pPalette->pixels + 4 * pFirst_colour, 4 * pCount);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
g16bit_palette_valid = 0;
|
||||
#endif
|
||||
if (!gFaded_palette) {
|
||||
PDSetPaletteEntries(pPalette, pFirst_colour, pCount);
|
||||
}
|
||||
|
@ -653,6 +740,9 @@ void DRSetPalette3(br_pixelmap* pThe_palette, int pSet_current_palette) {
|
|||
|
||||
if (pSet_current_palette) {
|
||||
memcpy(gCurrent_palette_pixels, pThe_palette->pixels, 0x400u);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
g16bit_palette_valid = 0;
|
||||
#endif
|
||||
}
|
||||
if (!gFaded_palette) {
|
||||
PDSetPalette(pThe_palette);
|
||||
|
@ -667,6 +757,9 @@ void DRSetPalette2(br_pixelmap* pThe_palette, int pSet_current_palette) {
|
|||
((br_int_32*)pThe_palette->pixels)[0] = 0;
|
||||
if (pSet_current_palette) {
|
||||
memcpy(gCurrent_palette_pixels, pThe_palette->pixels, 0x400u);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
g16bit_palette_valid = 0;
|
||||
#endif
|
||||
}
|
||||
if (!gFaded_palette) {
|
||||
PDSetPalette(pThe_palette);
|
||||
|
@ -685,11 +778,18 @@ void DRSetPalette(br_pixelmap* pThe_palette) {
|
|||
void InitializePalettes(void) {
|
||||
int j;
|
||||
gCurrent_palette_pixels = BrMemAllocate(0x400u, kMem_cur_pal_pixels);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
g16bit_palette_valid = 0;
|
||||
#endif
|
||||
|
||||
gCurrent_palette = DRPixelmapAllocate(BR_PMT_RGBX_888, 1u, 256, gCurrent_palette_pixels, 0);
|
||||
gRender_palette = BrTableFind("DRRENDER.PAL");
|
||||
if (gRender_palette == NULL) {
|
||||
FatalError(kFatalError_RequiredPalette);
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
NobbleNonzeroBlacks(gRender_palette);
|
||||
#endif
|
||||
gOrig_render_palette = BrPixelmapAllocateSub(gRender_palette, 0, 0, gRender_palette->width, gRender_palette->height);
|
||||
gOrig_render_palette->pixels = BrMemAllocate(0x400u, kMem_render_pal_pixels);
|
||||
memcpy(gOrig_render_palette->pixels, gRender_palette->pixels, 0x400u);
|
||||
|
@ -954,7 +1054,7 @@ void DrawMapBlip(tCar_spec* pCar, tU32 pTime, br_matrix34* pTrans, br_vector3* p
|
|||
break;
|
||||
case 1:
|
||||
map_pos.v[0] = map_pos.v[0] * 2.f;
|
||||
map_pos.v[1] = map_pos.v[1] * 2.f + 40.f;
|
||||
map_pos.v[1] = map_pos.v[1] * 2.f + HIRES_Y_OFFSET;
|
||||
break;
|
||||
default:
|
||||
TELL_ME_IF_WE_PASS_THIS_WAY();
|
||||
|
@ -962,6 +1062,13 @@ void DrawMapBlip(tCar_spec* pCar, tU32 pTime, br_matrix34* pTrans, br_vector3* p
|
|||
period = 256; // Must be power of 2
|
||||
colours[0] = pColour;
|
||||
colours[1] = OppositeColour(pColour);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gBack_screen->type != BR_PMT_INDEX_8) {
|
||||
colours[0] = PaletteEntry16Bit(gRender_palette, colours[0]);
|
||||
colours[1] = PaletteEntry16Bit(gRender_palette, colours[1]);
|
||||
}
|
||||
#endif
|
||||
BrMatrix34Mul(&car_in_map_space, pTrans, &gCurrent_race.map_transformation);
|
||||
bearing = FastScalarArcTan2(car_in_map_space.m[2][0], car_in_map_space.m[2][1]);
|
||||
|
||||
|
@ -1029,10 +1136,20 @@ void DrawMapSmallBlip(tU32 pTime, br_vector3* pPos, int pColour) {
|
|||
BrMatrix34ApplyP(&map_pos, pPos, &gCurrent_race.map_transformation);
|
||||
if (gReal_graf_data_index != 0) {
|
||||
map_pos.v[0] = 2.f * map_pos.v[0];
|
||||
map_pos.v[1] = 2.f * map_pos.v[1] + 40.f;
|
||||
map_pos.v[1] = 2.f * map_pos.v[1] + HIRES_Y_OFFSET;
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gBack_screen->type == BR_PMT_RGB_565) {
|
||||
offset = ((int)map_pos.v[0] * 2) + gBack_screen->row_bytes * (int)map_pos.v[1];
|
||||
pColour = PaletteEntry16Bit(gRender_palette, pColour);
|
||||
br_uint_8* p1 = &(((br_uint_8*)gBack_screen->pixels)[offset]);
|
||||
*((br_uint_16*)(p1)) = pColour;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
offset = (int)map_pos.v[0] + gBack_screen->row_bytes * (int)map_pos.v[1];
|
||||
((br_uint_8*)gBack_screen->pixels)[offset] = pColour;
|
||||
}
|
||||
offset = (int)map_pos.v[0] + gBack_screen->row_bytes * (int)map_pos.v[1];
|
||||
((br_uint_8*)gBack_screen->pixels)[offset] = pColour;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1081,7 +1198,7 @@ void TryThisEdge(tCar_spec* pCar, br_vector3* pLight, int pIndex_1, br_scalar pS
|
|||
dot_2 = pSign_2 * pLight->v[pIndex_2];
|
||||
mult = dot_1 * dot_2;
|
||||
if (mult < 0 || (mult == 0 && (dot_1 > 0 || dot_2 > 0))) {
|
||||
if (gShadow_clip_plane_count < 6) {
|
||||
if (gShadow_clip_plane_count < BR_MAX_CLIP_PLANES) {
|
||||
MungeClipPlane(pLight, pCar, &gShadow_points[pPoint_index_1], &gShadow_points[pPoint_index_2], pY_offset);
|
||||
}
|
||||
}
|
||||
|
@ -1099,14 +1216,20 @@ br_scalar DistanceFromPlane(br_vector3* pPos, br_scalar pA, br_scalar pB, br_sca
|
|||
void DisableLights(void) {
|
||||
int i;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
for (i = 0; i < gNumber_of_lights; i++) {
|
||||
BrLightDisable(gLight_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl EnableLights()
|
||||
void EnableLights(void) {
|
||||
int i;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
for (i = 0; i < gNumber_of_lights; i++) {
|
||||
BrLightEnable(gLight_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ProcessShadow(tCar_spec *pCar@<EAX>, br_actor *pWorld@<EDX>, tTrack_spec *pTrack_spec@<EBX>, br_actor *pCamera@<ECX>, br_matrix34 *pCamera_to_world_transform, br_scalar pDistance_factor)
|
||||
|
@ -1214,7 +1337,7 @@ void ProcessShadow(tCar_spec* pCar, br_actor* pWorld, tTrack_spec* pTrack_spec,
|
|||
TryThisEdge(pCar, &light_ray_car, 0, -1.0, 2, 1.0, 3, 7, y_offset);
|
||||
TryThisEdge(pCar, &light_ray_car, 0, -1.0, 2, -1.0, 2, 6, y_offset);
|
||||
TryThisEdge(pCar, &light_ray_car, 0, 1.0, 2, -1.0, 5, 1, y_offset);
|
||||
for (i = 0; i < gShadow_clip_plane_count; ++i) {
|
||||
for (i = 0; i < gShadow_clip_plane_count; i++) {
|
||||
BrClipPlaneEnable(gShadow_clip_planes[i].clip);
|
||||
}
|
||||
face_count = GetPrecalculatedFacesUnderCar(pCar, &face_ref);
|
||||
|
@ -1307,9 +1430,17 @@ void ProcessShadow(tCar_spec* pCar, br_actor* pWorld, tTrack_spec* pTrack_spec,
|
|||
if (list_ptr->v[0].v[1] >= first_poly_below || list_ptr->v[1].v[1] >= first_poly_below || list_ptr->v[2].v[1] >= first_poly_below) {
|
||||
if (gFancy_shadow) {
|
||||
faces[f_num].material = list_ptr->material;
|
||||
if (list_ptr->material && list_ptr->material->colour_map && (list_ptr->material->flags & BR_MATF_LIGHT) == 0) {
|
||||
list_ptr->material->flags |= BR_MATF_SMOOTH | BR_MATF_LIGHT;
|
||||
BrMaterialUpdate(list_ptr->material, BR_MATU_RENDERING);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gShade_tables_do_not_work) {
|
||||
list_ptr->material->ka = 0.75f;
|
||||
BrMaterialUpdate(list_ptr->material, BR_MATU_LIGHTING);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (list_ptr->material && list_ptr->material->colour_map && (list_ptr->material->flags & BR_MATF_LIGHT) == 0) {
|
||||
list_ptr->material->flags |= BR_MATF_SMOOTH | BR_MATF_LIGHT;
|
||||
BrMaterialUpdate(list_ptr->material, BR_MATU_RENDERING);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
faces[f_num].material = gShadow_material;
|
||||
|
@ -1377,7 +1508,13 @@ void ProcessShadow(tCar_spec* pCar, br_actor* pWorld, tTrack_spec* pTrack_spec,
|
|||
camera_ptr->hither_z += camera_hither_fudge;
|
||||
}
|
||||
if (f_num) {
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
DisableLights();
|
||||
#endif
|
||||
BrZbSceneRenderBegin(gUniverse_actor, gCamera, gRender_screen, gDepth_buffer);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
EnableLights();
|
||||
#endif
|
||||
gShadow_model->vertices = verts;
|
||||
gShadow_model->faces = faces;
|
||||
gShadow_model->nfaces = f_num;
|
||||
|
@ -1405,6 +1542,13 @@ void ProcessShadow(tCar_spec* pCar, br_actor* pWorld, tTrack_spec* pTrack_spec,
|
|||
if (gFancy_shadow) {
|
||||
material = gShadow_model->faces[i].material;
|
||||
if (material) {
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gShade_tables_do_not_work) {
|
||||
material->ka = 1.0f;
|
||||
BrMaterialUpdate(material, BR_MATU_LIGHTING);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (material->colour_map && (material->flags & BR_MATF_LIGHT) != 0) {
|
||||
material->flags &= ~(BR_MATF_LIGHT | BR_MATF_PRELIT | BR_MATF_SMOOTH);
|
||||
BrMaterialUpdate(material, BR_MATU_RENDERING);
|
||||
|
@ -1495,9 +1639,9 @@ void FlashyMapCheckpoint(int pIndex, tU32 pTime) {
|
|||
case 1:
|
||||
DimRectangle(gBack_screen,
|
||||
2 * gCurrent_race.checkpoints[pIndex].map_left[0],
|
||||
2 * gCurrent_race.checkpoints[pIndex].map_top[0] + 40,
|
||||
2 * gCurrent_race.checkpoints[pIndex].map_top[0] + HIRES_Y_OFFSET,
|
||||
2 * gCurrent_race.checkpoints[pIndex].map_right[0],
|
||||
2 * gCurrent_race.checkpoints[pIndex].map_bottom[0] + 40,
|
||||
2 * gCurrent_race.checkpoints[pIndex].map_bottom[0] + HIRES_Y_OFFSET,
|
||||
0);
|
||||
break;
|
||||
default:
|
||||
|
@ -1527,7 +1671,18 @@ int ConditionallyFillWithSky(br_pixelmap* pPixelmap) {
|
|||
} else {
|
||||
bgnd_col = 0;
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (pPixelmap->type == BR_PMT_RGB_565) {
|
||||
bgnd_col = PaletteEntry16Bit(gRender_palette, bgnd_col);
|
||||
bgnd_col = (bgnd_col << 16) | bgnd_col;
|
||||
}
|
||||
#endif
|
||||
BrPixelmapFill(pPixelmap, bgnd_col);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
// Added by dethrace to ensure the pixel writes are flushed before 3d geometry
|
||||
BrPixelmapFlush(pPixelmap);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1557,7 +1712,12 @@ void RenderAFrame(int pDepth_mask_on) {
|
|||
tCar_spec* car;
|
||||
LOG_TRACE("(%d)", pDepth_mask_on);
|
||||
|
||||
gRender_screen->pixels = gBack_screen->pixels;
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gVoodoo_rush_mode >= 1) {
|
||||
gRender_screen->pixels = gBack_screen->pixels;
|
||||
}
|
||||
#endif
|
||||
|
||||
the_time = GetTotalTime();
|
||||
old_pixels = gRender_screen->pixels;
|
||||
cockpit_on = gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0 && !gMap_mode;
|
||||
|
@ -1575,6 +1735,7 @@ void RenderAFrame(int pDepth_mask_on) {
|
|||
if (gReal_graf_data_index) {
|
||||
BrPixelmapRectangleFill(gBack_screen, 0, 0, 640, 40, 0);
|
||||
BrPixelmapRectangleFill(gBack_screen, 0, 440, 640, 40, 0);
|
||||
|
||||
DRPixelmapDoubledCopy(
|
||||
gBack_screen,
|
||||
gCurrent_race.map_image,
|
||||
|
@ -1586,6 +1747,14 @@ void RenderAFrame(int pDepth_mask_on) {
|
|||
DRPixelmapCopy(gBack_screen, gCurrent_race.map_image);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
// Added by dethrace
|
||||
// 3d scene is drawn on top of the 2d map, so we must ensure that all the 2d pixel
|
||||
// writes have been flushed to the framebuffer first
|
||||
BrPixelmapFlush(gBack_screen);
|
||||
#endif
|
||||
|
||||
DimRectangle(
|
||||
gBack_screen,
|
||||
gMap_render_x_i - gCurrent_graf_data->map_render_x_marg,
|
||||
|
@ -1662,14 +1831,31 @@ void RenderAFrame(int pDepth_mask_on) {
|
|||
}
|
||||
gRendering_mirror = 0;
|
||||
DoSpecialCameraEffect(gCamera, &gCamera_to_world);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (!ConditionallyFillWithSky(gRender_screen->width == gBack_screen->width ? gBack_screen : gRender_screen)
|
||||
#else
|
||||
if (!ConditionallyFillWithSky(gRender_screen)
|
||||
#endif
|
||||
&& !gProgram_state.cockpit_on
|
||||
&& !(gAction_replay_camera_mode && gAction_replay_mode)) {
|
||||
ExternalSky(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (!gBlitting_is_slow)
|
||||
#endif
|
||||
{
|
||||
ExternalSky(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
PDUnlockRealBackScreen(1);
|
||||
#endif
|
||||
|
||||
#if !defined(DETHRACE_FIX_BUGS)
|
||||
// in map mode, the scene is rendered 3 times. We have no idea why.
|
||||
for (i = 0; i < (gMap_mode ? 3 : 1); i++)
|
||||
#elif defined(DETHRACE_3DFX_PATCH)
|
||||
for (i = 0; i < (gMap_mode && !gSmall_frames_are_slow ? 3 : 1); i++)
|
||||
#endif
|
||||
{
|
||||
RenderShadows(gUniverse_actor, &gProgram_state.track_spec, gCamera, &gCamera_to_world);
|
||||
|
@ -1689,12 +1875,50 @@ void RenderAFrame(int pDepth_mask_on) {
|
|||
RenderProximityRays(gRender_screen, gDepth_buffer, gCamera, &gCamera_to_world, gFrame_period);
|
||||
BrZbSceneRenderEnd();
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
PDLockRealBackScreen(1);
|
||||
#endif
|
||||
|
||||
BrMatrix34Copy(&gCamera->t.t.mat, &old_camera_matrix);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (cockpit_on) {
|
||||
PDUnlockRealBackScreen(1);
|
||||
PDLockRealBackScreen(1);
|
||||
CopyStripImage(
|
||||
gBack_screen,
|
||||
-gCurrent_graf_data->cock_margin_x,
|
||||
gScreen_wobble_x,
|
||||
-gCurrent_graf_data->cock_margin_y,
|
||||
gScreen_wobble_y,
|
||||
gProgram_state.current_car.cockpit_images[gProgram_state.cockpit_image_index],
|
||||
0,
|
||||
0,
|
||||
gCurrent_graf_data->total_cock_width,
|
||||
gCurrent_graf_data->total_cock_height);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gMirror_on__graphics) {
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gVoodoo_rush_mode >= 1) {
|
||||
gRearview_screen->pixels = gBack_screen->pixels;
|
||||
}
|
||||
gRearview_screen->base_x = gScreen_wobble_x + gProgram_state.current_car.mirror_left;
|
||||
gRearview_screen->base_y = gScreen_wobble_y + gProgram_state.current_car.mirror_top;
|
||||
#endif
|
||||
BrPixelmapFill(gRearview_depth_buffer, 0xFFFFFFFF);
|
||||
gRendering_mirror = 1;
|
||||
DoSpecialCameraEffect(gRearview_camera, &gRearview_camera_to_world);
|
||||
ConditionallyFillWithSky(gRearview_screen);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
PDUnlockRealBackScreen(1);
|
||||
|
||||
// Added by dethrace
|
||||
// Rearview mirror is drawn on top of the 2d cockpit, so we must ensure that all the 2d pixel
|
||||
// writes have been flushed to the framebuffer first
|
||||
BrPixelmapFlush(gBack_screen);
|
||||
// ---
|
||||
#endif
|
||||
BrZbSceneRenderBegin(gUniverse_actor, gRearview_camera, gRearview_screen, gRearview_depth_buffer);
|
||||
ProcessNonTrackActors(
|
||||
gRearview_screen,
|
||||
|
@ -1710,7 +1934,14 @@ void RenderAFrame(int pDepth_mask_on) {
|
|||
ProcessTrack(gUniverse_actor, &gProgram_state.track_spec, gRearview_camera, &gRearview_camera_to_world, 1);
|
||||
}
|
||||
RenderSplashes();
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
RenderSmoke(gRearview_screen, gRearview_depth_buffer, gRearview_camera, &gRearview_camera_to_world, gFrame_period);
|
||||
RenderSparks(gRearview_screen, gRearview_depth_buffer, gRearview_camera, &gRearview_camera_to_world, gFrame_period);
|
||||
#endif
|
||||
BrZbSceneRenderEnd();
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
PDLockRealBackScreen(1);
|
||||
#endif
|
||||
BrMatrix34Copy(&gRearview_camera->t.t.mat, &old_mirror_cam_matrix);
|
||||
gRendering_mirror = 0;
|
||||
}
|
||||
|
@ -1807,6 +2038,7 @@ void RenderAFrame(int pDepth_mask_on) {
|
|||
gBack_screen->base_x = real_base_x;
|
||||
gBack_screen->base_y = real_base_y;
|
||||
} else {
|
||||
#if !defined(DETHRACE_3DFX_PATCH)
|
||||
if (cockpit_on) {
|
||||
CopyStripImage(
|
||||
gBack_screen,
|
||||
|
@ -1831,9 +2063,14 @@ void RenderAFrame(int pDepth_mask_on) {
|
|||
gProgram_state.current_car.mirror_bottom - gProgram_state.current_car.mirror_top);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DimAFewBits();
|
||||
DoDamageScreen(the_time);
|
||||
if (!gAction_replay_mode || gAR_fudge_headups) {
|
||||
// Added by dethrace
|
||||
// Pratcam is drawn on top of the 2d cockpit, so we must ensure that all the 2d pixel
|
||||
// writes have been flushed to the framebuffer first
|
||||
BrPixelmapFlush(gBack_screen);
|
||||
DoPratcam(the_time);
|
||||
DoHeadups(the_time);
|
||||
}
|
||||
|
@ -2090,6 +2327,13 @@ void DRPixelmapRectangleMaskedCopy(br_pixelmap* pDest, br_int_16 pDest_x, br_int
|
|||
tU8* conv_table;
|
||||
LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d)", pDest, pDest_x, pDest_y, pSource, pSource_x, pSource_y, pWidth, pHeight);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (pDest->type == BR_PMT_RGB_565 && pSource->type == BR_PMT_INDEX_8) {
|
||||
Copy8BitTo16BitRectangleWithTransparency(pDest, pDest_x, pDest_y, pSource, pSource_x, pSource_y, pWidth, pHeight,
|
||||
gCurrent_conversion_table == NULL ? gCurrent_palette : gFlic_palette);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
source_ptr = (tU8*)pSource->pixels + (pSource->row_bytes * pSource_y + pSource_x);
|
||||
dest_ptr = (tU8*)pDest->pixels + (pDest->row_bytes * pDest_y + pDest_x);
|
||||
source_row_wrap = pSource->row_bytes - pWidth;
|
||||
|
@ -2129,7 +2373,7 @@ void DRPixelmapRectangleMaskedCopy(br_pixelmap* pDest, br_int_16 pDest_x, br_int
|
|||
dest_row_wrap += pDest_x + pWidth - pDest->width;
|
||||
pWidth = pDest->width - pDest_x;
|
||||
}
|
||||
// LOG_DEBUG("2 (src->width: %d, src->height: %d, pDest_x: %d, pDest_y: %d, pSource_x: %d, pSource_y: %d, pWidth: %d, pHeight: %d)", pSource->width, pSource->height, pDest_x, pDest_y, pSource_x, pSource_y, pWidth, pHeight);
|
||||
|
||||
if (gCurrent_conversion_table != NULL) {
|
||||
conv_table = gCurrent_conversion_table->pixels;
|
||||
for (y_count = 0; y_count < pHeight; y_count++) {
|
||||
|
@ -2185,7 +2429,14 @@ void DRPixelmapRectangleOnscreenCopy(br_pixelmap* pDest, br_int_16 pDest_x, br_i
|
|||
tU8* source_ptr;
|
||||
tU8* dest_ptr;
|
||||
tU8* conv_table;
|
||||
// LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d)", pDest, pDest_x, pDest_y, pSource, pSource_x, pSource_y, pWidth, pHeight);
|
||||
LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d)", pDest, pDest_x, pDest_y, pSource, pSource_x, pSource_y, pWidth, pHeight);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (pDest->type == BR_PMT_RGB_565 && pSource->type == BR_PMT_INDEX_8) {
|
||||
Copy8BitToOnscreen16BitRectangleWithTransparency(pDest, pDest_x, pDest_y, pSource, pSource_x, pSource_y, pWidth, pHeight, gCurrent_palette);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
source_row_wrap = pSource->row_bytes - pWidth;
|
||||
dest_row_wrap = pDest->row_bytes - pWidth;
|
||||
|
@ -2224,6 +2475,12 @@ void DRPixelmapRectangleShearedCopy(br_pixelmap* pDest, br_int_16 pDest_x, br_in
|
|||
tX1616 current_shear;
|
||||
LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d, %d)", pDest, pDest_x, pDest_y, pSource, pSource_x, pSource_y, pWidth, pHeight, pShear);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (pDest->type == BR_PMT_RGB_565 && pSource->type == BR_PMT_INDEX_8) {
|
||||
Copy8BitRectangleTo16BitRhombusWithTransparency(pDest, pDest_x, pDest_y, pSource, pSource_x, pSource_y, pWidth, pHeight, pShear, gCurrent_palette);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
current_shear = 0;
|
||||
last_shear_x = 0;
|
||||
source_ptr = (tU8*)pSource->pixels + pSource_x + pSource_y * pSource->row_bytes;
|
||||
|
@ -2366,7 +2623,11 @@ int AllocateTransientBitmap(int pWidth, int pHeight, int pUser_data) {
|
|||
|
||||
for (bm_index = 0; bm_index < COUNT_OF(gTransient_bitmaps); bm_index++) {
|
||||
if (gTransient_bitmaps[bm_index].pixmap == NULL) {
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
gTransient_bitmaps[bm_index].pixmap = DRPixelmapAllocate(gBack_screen->type, pWidth + 8, pHeight, NULL, 0);
|
||||
#else
|
||||
gTransient_bitmaps[bm_index].pixmap = DRPixelmapAllocate(BR_PMT_INDEX_8, pWidth + 8, pHeight, NULL, 0);
|
||||
#endif
|
||||
gTransient_bitmaps[bm_index].in_use = 0;
|
||||
gTransient_bitmaps[bm_index].user_data = pUser_data;
|
||||
return bm_index;
|
||||
|
@ -3031,7 +3292,7 @@ void InitShadow(void) {
|
|||
br_vector3 temp_v;
|
||||
LOG_TRACE("()");
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
for (i = 0; i < COUNT_OF(gShadow_clip_planes); i++) {
|
||||
gShadow_clip_planes[i].clip = BrActorAllocate(BR_ACTOR_CLIP_PLANE, NULL);
|
||||
BrActorAdd(gUniverse_actor, gShadow_clip_planes[i].clip);
|
||||
BrClipPlaneDisable(gShadow_clip_planes[i].clip);
|
||||
|
@ -3137,6 +3398,12 @@ void DRPixelmapDoubledCopy(br_pixelmap* pDestn, br_pixelmap* pSource, int pSourc
|
|||
int width_over_2;
|
||||
LOG_TRACE("(%p, %p, %d, %d, %d, %d)", pDestn, pSource, pSource_width, pSource_height, pX_offset, pY_offset);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (pDestn->type != pSource->type && pDestn->type == BR_PMT_RGB_565 && pSource->type == BR_PMT_INDEX_8) {
|
||||
CopyDoubled8BitTo16BitRectangle(pDestn, pSource, pSource_width, pSource_height, pX_offset, pY_offset, gCurrent_palette);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
dst_row_skip = 2 * pDestn->row_bytes - 2 * pSource_width;
|
||||
src_row_skip = (pSource->row_bytes - pSource_width) / 2;
|
||||
sptr = (tU16*)((tU8*)pSource->pixels - 2 * src_row_skip + 2 * (pSource->row_bytes * pSource_height / 2));
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "errors.h"
|
||||
#include "flicplay.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrkm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "grafdata.h"
|
||||
|
@ -166,6 +167,23 @@ void AllocateRearviewPixelmap(void) {
|
|||
char* rear_screen_pixels;
|
||||
LOG_TRACE("()");
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gRearview_screen != NULL) {
|
||||
BrPixelmapFree(gRearview_screen);
|
||||
gRearview_screen = NULL;
|
||||
}
|
||||
if (gProgram_state.mirror_on) {
|
||||
gRearview_screen = BrPixelmapAllocateSub(
|
||||
gBack_screen,
|
||||
gProgram_state.current_car.mirror_left,
|
||||
gProgram_state.current_car.mirror_top,
|
||||
gProgram_state.current_car.mirror_right - gProgram_state.current_car.mirror_left,
|
||||
gProgram_state.current_car.mirror_bottom - gProgram_state.current_car.mirror_top);
|
||||
gRearview_depth_buffer = gDepth_buffer;
|
||||
gRearview_screen->origin_x = gRearview_screen->width / 2;
|
||||
gRearview_screen->origin_y = gRearview_screen->height / 2;
|
||||
}
|
||||
#else
|
||||
if (gRearview_screen) {
|
||||
BrMemFree(gRearview_screen->pixels);
|
||||
BrPixelmapFree(gRearview_screen);
|
||||
|
@ -192,6 +210,7 @@ void AllocateRearviewPixelmap(void) {
|
|||
gRearview_screen->origin_y = gRearview_screen->height / 2;
|
||||
gRearview_depth_buffer = BrPixelmapMatch(gRearview_screen, BR_PMMATCH_DEPTH_16);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: void __cdecl ReinitialiseRearviewCamera()
|
||||
|
@ -221,6 +240,15 @@ void ReinitialiseRenderStuff(void) {
|
|||
gProgram_state.current_render_right = gProgram_state.current_car.render_right[gProgram_state.cockpit_image_index];
|
||||
gProgram_state.current_render_bottom = gProgram_state.current_car.render_bottom[gProgram_state.cockpit_image_index];
|
||||
} else {
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gSmall_frames_are_slow) {
|
||||
gProgram_state.current_render_top = 0;
|
||||
gProgram_state.current_render_right = gGraf_specs[gGraf_spec_index].total_width;
|
||||
gProgram_state.current_render_left = 0;
|
||||
gProgram_state.current_render_bottom = gGraf_specs[gGraf_spec_index].total_height;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
gProgram_state.current_render_top = (gGraf_specs[gGraf_spec_index].total_height / 18 & ~1) * gRender_indent;
|
||||
gProgram_state.current_render_left = (gGraf_specs[gGraf_spec_index].total_width / 18 & ~3) * gRender_indent;
|
||||
x_diff = gGraf_specs[gGraf_spec_index].total_width - gProgram_state.current_render_left;
|
||||
|
@ -320,26 +348,187 @@ void AustereWarning(void) {
|
|||
// IDA: void __cdecl InitLineStuff()
|
||||
void InitLineStuff(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
// HACK: originally 2 vertices
|
||||
gLine_model = BrModelAllocate("gLine_model", 3 /*2*/, 1);
|
||||
gLine_material = BrMaterialAllocate("gLine_material");
|
||||
gLine_actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
|
||||
if (!gLine_model || !gLine_material || !gLine_actor) {
|
||||
FatalError(94);
|
||||
}
|
||||
gLine_actor->identifier = "gLine_actor";
|
||||
gLine_actor->render_style = BR_RSTYLE_EDGES;
|
||||
gLine_actor->model = gLine_model;
|
||||
gLine_actor->material = gLine_material;
|
||||
gLine_model->flags = BR_MODF_QUICK_UPDATE | BR_MODF_KEEP_ORIGINAL;
|
||||
gLine_model->faces->vertices[0] = 0;
|
||||
gLine_model->faces->vertices[1] = 0;
|
||||
gLine_model->faces->vertices[2] = 1;
|
||||
|
||||
// HACK: override the 2 vertices + EDGES with 3 vertices + FACES
|
||||
gLine_model->faces->vertices[1] = 2;
|
||||
gLine_actor->render_style = BR_RSTYLE_FACES;
|
||||
// HACK end
|
||||
|
||||
gLine_material->flags = BR_MATF_TWO_SIDED | BR_MATF_SMOOTH | BR_MATF_PRELIT | BR_MATF_LIGHT;
|
||||
gLine_model->faces[0].flags = BR_FACEF_COPLANAR_0 | BR_FACEF_COPLANAR_2;
|
||||
BrModelAdd(gLine_model);
|
||||
BrMaterialAdd(gLine_material);
|
||||
BrActorAdd(gDont_render_actor, gLine_actor);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl InitSmokeStuff()
|
||||
void InitSmokeStuff(void) {
|
||||
static br_token_value fadealpha[3];
|
||||
static br_token_value fadealpha[3] = { { BRT_BLEND_B, { .u32 = 1 } }, { BRT_OPACITY_X, { .x = 0x4B0000 } }, { 0 } };
|
||||
tPath_name path;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
gBlend_model = BrModelAllocate("gBlend_model", 4, 2);
|
||||
gBlend_material = BrMaterialAllocate("gBlend_material");
|
||||
gBlend_actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
|
||||
if (!gBlend_model || !gBlend_material || !gBlend_actor) {
|
||||
FatalError(94);
|
||||
}
|
||||
gBlend_actor->identifier = "gBlend_actor";
|
||||
gBlend_actor->model = gBlend_model;
|
||||
gBlend_actor->material = gBlend_material;
|
||||
gBlend_model->faces[0].vertices[0] = 0;
|
||||
gBlend_model->faces[0].vertices[1] = 1;
|
||||
gBlend_model->faces[0].vertices[2] = 2;
|
||||
gBlend_model->faces[1].vertices[0] = 2;
|
||||
gBlend_model->faces[1].vertices[1] = 3;
|
||||
gBlend_model->faces[1].vertices[2] = 0;
|
||||
gBlend_model->vertices[0].p.v[0] = -1.0f;
|
||||
gBlend_model->vertices[0].p.v[1] = 1.0f;
|
||||
gBlend_model->vertices[0].p.v[2] = 0.0f;
|
||||
gBlend_model->vertices[1].p.v[0] = -1.0f;
|
||||
gBlend_model->vertices[1].p.v[1] = -1.0f;
|
||||
gBlend_model->vertices[1].p.v[2] = 0.0f;
|
||||
gBlend_model->vertices[2].p.v[0] = 1.0f;
|
||||
gBlend_model->vertices[2].p.v[1] = -1.0f;
|
||||
gBlend_model->vertices[2].p.v[2] = 0.0f;
|
||||
gBlend_model->vertices[3].p.v[0] = 1.0f;
|
||||
gBlend_model->vertices[3].p.v[1] = 1.0f;
|
||||
gBlend_model->vertices[3].p.v[2] = 0.0f;
|
||||
gBlend_material->flags = BR_MATF_PERSPECTIVE | BR_MATF_SMOOTH;
|
||||
gBlend_material->flags |= (BR_MATF_LIGHT | BR_MATF_PRELIT);
|
||||
gBlend_model->flags |= BR_MODF_KEEP_ORIGINAL;
|
||||
gBlend_material->extra_prim = fadealpha;
|
||||
PathCat(path, gApplication_path, "PIXELMAP");
|
||||
PathCat(path, path, "SMOKE.PIX");
|
||||
gBlend_material->colour_map = DRPixelmapLoad(path);
|
||||
if (!gBlend_material->colour_map) {
|
||||
FatalError(79, path);
|
||||
}
|
||||
gBlend_material->colour_map->map = gRender_palette;
|
||||
BrMapAdd(gBlend_material->colour_map);
|
||||
gBlend_model->vertices[0].map.v[0] = 0.0f;
|
||||
gBlend_model->vertices[0].map.v[1] = 1.0f - 1.0f / (float)gBlend_material->colour_map->height;
|
||||
gBlend_model->vertices[1].map.v[0] = 0.0f;
|
||||
gBlend_model->vertices[1].map.v[1] = 0.0f;
|
||||
gBlend_model->vertices[2].map.v[0] = 1.0f - 1.0f / (float)gBlend_material->colour_map->width;
|
||||
gBlend_model->vertices[2].map.v[1] = 0.0f;
|
||||
gBlend_model->vertices[3].map.v[0] = 1.0f - 1.0f / (float)gBlend_material->colour_map->width;
|
||||
gBlend_model->vertices[3].map.v[1] = 1.0f - 1.0f / (float)gBlend_material->colour_map->height;
|
||||
BrModelAdd(gBlend_model);
|
||||
BrMaterialAdd(gBlend_material);
|
||||
BrActorAdd(gDont_render_actor, gBlend_actor);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl Init2DStuff()
|
||||
void Init2DStuff(void) {
|
||||
br_camera* camera;
|
||||
static br_token_value fadealpha[3];
|
||||
static br_token_value fadealpha[3] = { { BRT_BLEND_B, { .u32 = 1u } }, { BRT_OPACITY_X, { .x = 0x800000 } }, { 0 } };
|
||||
tPath_name path;
|
||||
br_scalar prat_u;
|
||||
br_scalar prat_v;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
g2d_camera = BrActorAllocate(BR_ACTOR_CAMERA, NULL);
|
||||
gDim_model = BrModelAllocate("gDim_model", 4, 2);
|
||||
gDim_material = BrMaterialAllocate("gDim_material");
|
||||
gDim_actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
|
||||
gPrat_model = BrModelAllocate("gPrat_model", 4, 2);
|
||||
gPrat_material = BrMaterialAllocate("gPrat_material");
|
||||
gPrat_actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
|
||||
if (!gDim_model || !gDim_material || !gDim_actor || !gPrat_model || !gPrat_material || !gPrat_actor || !g2d_camera) {
|
||||
FatalError(94);
|
||||
}
|
||||
g2d_camera->identifier = "g2d_camera";
|
||||
camera = g2d_camera->type_data;
|
||||
camera->type = BR_CAMERA_PARALLEL;
|
||||
camera->hither_z = 1.0f;
|
||||
camera->yon_z = 3.0f;
|
||||
camera->width = gScreen->width;
|
||||
camera->height = gScreen->height;
|
||||
gDim_actor->identifier = "gDim_actor";
|
||||
gDim_actor->model = gDim_model;
|
||||
gDim_actor->material = gDim_material;
|
||||
|
||||
gDim_model->faces->vertices[0] = 0;
|
||||
gDim_model->faces->vertices[1] = 1;
|
||||
gDim_model->faces->vertices[2] = 2;
|
||||
gDim_model->faces[1].vertices[0] = 2;
|
||||
gDim_model->faces[1].vertices[1] = 3;
|
||||
gDim_model->faces[1].vertices[2] = 0;
|
||||
gDim_model->vertices->p.v[0] = 150.0f;
|
||||
gDim_model->vertices->p.v[1] = -20.0f;
|
||||
gDim_model->vertices->p.v[2] = -2.0f;
|
||||
gDim_model->vertices[1].p.v[0] = 150.0f;
|
||||
gDim_model->vertices[1].p.v[1] = -100.0f;
|
||||
gDim_model->vertices[1].p.v[2] = -2.0f;
|
||||
gDim_model->vertices[2].p.v[0] = 200.0f;
|
||||
gDim_model->vertices[2].p.v[1] = -100.0f;
|
||||
gDim_model->vertices[2].p.v[2] = -2.0f;
|
||||
gDim_model->vertices[3].p.v[0] = 200.0f;
|
||||
gDim_model->vertices[3].p.v[1] = -20.0f;
|
||||
gDim_model->vertices[3].p.v[2] = -2.0f;
|
||||
gDim_material->colour = 0;
|
||||
gDim_material->flags = BR_MATF_FORCE_FRONT;
|
||||
gDim_model->flags |= BR_MODF_KEEP_ORIGINAL;
|
||||
gDim_material->extra_prim = fadealpha;
|
||||
BrModelAdd(gDim_model);
|
||||
BrMaterialAdd(gDim_material);
|
||||
BrActorAdd(g2d_camera, gDim_actor);
|
||||
gDim_actor->render_style = BR_RSTYLE_NONE;
|
||||
gPrat_actor->identifier = "gPrat_actor";
|
||||
gPrat_actor->model = gPrat_model;
|
||||
gPrat_actor->material = gPrat_material;
|
||||
gPrat_model->faces->vertices[0] = 0;
|
||||
gPrat_model->faces->vertices[1] = 1;
|
||||
gPrat_model->faces->vertices[2] = 2;
|
||||
gPrat_model->faces[1].vertices[0] = 2;
|
||||
gPrat_model->faces[1].vertices[1] = 3;
|
||||
gPrat_model->faces[1].vertices[2] = 0;
|
||||
gPrat_model->vertices->p.v[0] = 150.0f;
|
||||
gPrat_model->vertices->p.v[1] = -20.0f;
|
||||
gPrat_model->vertices->p.v[2] = -2.0f;
|
||||
gPrat_model->vertices[1].p.v[0] = 150.0f;
|
||||
gPrat_model->vertices[1].p.v[1] = -100.0f;
|
||||
gPrat_model->vertices[1].p.v[2] = -2.0f;
|
||||
gPrat_model->vertices[2].p.v[0] = 200.0f;
|
||||
gPrat_model->vertices[2].p.v[1] = -100.0f;
|
||||
gPrat_model->vertices[2].p.v[2] = -2.0f;
|
||||
gPrat_model->vertices[3].p.v[0] = 200.0f;
|
||||
gPrat_model->vertices[3].p.v[1] = -20.0f;
|
||||
gPrat_model->vertices[3].p.v[2] = -2.0f;
|
||||
gPrat_material->colour = 0xFFFFFF;
|
||||
gPrat_material->flags = BR_MATF_FORCE_FRONT;
|
||||
gPrat_model->flags |= BR_MODF_KEEP_ORIGINAL;
|
||||
prat_u = 104.0f / (float)HighResPratBufferWidth();
|
||||
prat_v = 110.0f / (float)HighResPratBufferHeight();
|
||||
gPrat_model->vertices->map.v[0] = 0.0f;
|
||||
gPrat_model->vertices->map.v[1] = 0.0f;
|
||||
gPrat_model->vertices[1].map.v[0] = 0.0f;
|
||||
gPrat_model->vertices[1].map.v[1] = prat_v;
|
||||
gPrat_model->vertices[2].map.v[0] = prat_u;
|
||||
gPrat_model->vertices[2].map.v[1] = prat_v;
|
||||
gPrat_model->vertices[3].map.v[0] = prat_u;
|
||||
gPrat_model->vertices[3].map.v[1] = 0.0f;
|
||||
BrModelAdd(gPrat_model);
|
||||
BrMaterialAdd(gPrat_material);
|
||||
BrActorAdd(g2d_camera, gPrat_actor);
|
||||
gPrat_actor->render_style = BR_RSTYLE_NONE;
|
||||
}
|
||||
|
||||
// IDA: void __usercall InitialiseApplication(int pArgc@<EAX>, char **pArgv@<EDX>)
|
||||
|
@ -378,8 +567,22 @@ void InitialiseApplication(int pArgc, char** pArgv) {
|
|||
InitBRFonts();
|
||||
LoadMiscStrings();
|
||||
LoadInRegistees();
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
|
||||
// dethrace: if statement added to support all types of games
|
||||
if (harness_game_config.opengl_3dfx_mode) {
|
||||
InitLineStuff();
|
||||
InitSmokeStuff();
|
||||
Init2DStuff();
|
||||
}
|
||||
#endif
|
||||
|
||||
FinishLoadingGeneral();
|
||||
#ifndef DETHRACE_3DFX_PATCH
|
||||
// 3dfx patch calls this earlier
|
||||
InitializePalettes();
|
||||
#endif
|
||||
AustereWarning();
|
||||
LoadInterfaceStrings();
|
||||
InitializeActionReplay();
|
||||
|
@ -391,6 +594,14 @@ void InitialiseApplication(int pArgc, char** pArgv) {
|
|||
gDefault_track_material = BrMaterialAllocate("gDefault_track_material");
|
||||
gDefault_track_material->index_base = 227;
|
||||
gDefault_track_material->index_range = 1;
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
gDefault_track_material->ka = 1.0;
|
||||
gDefault_track_material->kd = 0.0;
|
||||
gDefault_track_material->ks = 0.0;
|
||||
gDefault_track_material->colour = ((br_colour*)gRender_palette->pixels)[227];
|
||||
#endif
|
||||
|
||||
BrMaterialAdd(gDefault_track_material);
|
||||
InitShadow();
|
||||
InitFlics();
|
||||
|
@ -423,9 +634,8 @@ void InitialiseApplication(int pArgc, char** pArgv) {
|
|||
// IDA: void __usercall InitialiseDeathRace(int pArgc@<EAX>, char **pArgv@<EDX>)
|
||||
void InitialiseDeathRace(int pArgc, char** pArgv) {
|
||||
PDInitialiseSystem();
|
||||
|
||||
InitialiseApplication(pArgc, pArgv);
|
||||
// dword_112DF8 = 1; // never checked by game
|
||||
gInitialisation_finished = 1;
|
||||
}
|
||||
|
||||
// IDA: void __usercall InitGame(int pStart_race@<EAX>)
|
||||
|
@ -473,6 +683,10 @@ void InitGame(int pStart_race) {
|
|||
gProgram_state.redo_race_index = -1;
|
||||
gWait_for_it = 0;
|
||||
SwitchToLoresMode();
|
||||
|
||||
// added by dethrace to support --game-completed arg
|
||||
gProgram_state.game_completed = harness_game_config.game_completed;
|
||||
// -
|
||||
}
|
||||
|
||||
// IDA: void __cdecl DisposeGameIfNecessary()
|
||||
|
@ -594,6 +808,23 @@ void InitRace(void) {
|
|||
}
|
||||
PrintMemoryDump(0, "DIRECTLY AFTER LOADING IN TRACK");
|
||||
LoadCopCars();
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
// In the 3dfx patch this code was moved from `LoadTrack` so that the pedestrian material would be
|
||||
// fogged correctly
|
||||
InstantDepthChange(
|
||||
gProgram_state.default_depth_effect.type,
|
||||
gProgram_state.default_depth_effect.sky_texture,
|
||||
gProgram_state.default_depth_effect.start,
|
||||
gProgram_state.default_depth_effect.end);
|
||||
gSwap_sky_texture = 0;
|
||||
if (!GetSkyTextureOn()) {
|
||||
ToggleSkyQuietly();
|
||||
}
|
||||
gSwap_depth_effect_type = -1;
|
||||
if (!GetDepthCueingOn()) {
|
||||
ToggleDepthCueingQuietly();
|
||||
}
|
||||
#endif
|
||||
PrintMemoryDump(0, "AFTER LOADING IN COPS");
|
||||
SaveShadeTables();
|
||||
gCountdown = 7;
|
||||
|
@ -669,6 +900,15 @@ void DisposeRace(void) {
|
|||
PossibleService();
|
||||
DisposePratcam();
|
||||
PossibleService();
|
||||
|
||||
#ifdef DETHRACE_FIX_BUGS
|
||||
// when exiting a race, skid mark materials are unloaded, but material_modifiers is not changed.
|
||||
// In 3dfx mode, `FrobFog` is called during loading the next track, which iterates over the material_modifiers
|
||||
// causing a use-after-free
|
||||
for (int i = 0; i < COUNT_OF(gCurrent_race.material_modifiers); i++) {
|
||||
gCurrent_race.material_modifiers[i].skid_mark_material = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: int __cdecl GetScreenSize()
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "flicplay.h"
|
||||
#include "formats.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrkm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "grafdata.h"
|
||||
|
@ -562,7 +563,13 @@ br_material* LoadMaterial(char* pName) {
|
|||
PossibleService();
|
||||
PathCat(the_path, gApplication_path, "MATERIAL");
|
||||
PathCat(the_path, the_path, pName);
|
||||
return BrMaterialLoad(the_path);
|
||||
result = BrMaterialLoad(the_path);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (result != NULL) {
|
||||
GlorifyMaterial(&result, 1);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
// IDA: br_model* __usercall LoadModel@<EAX>(char *pName@<EAX>)
|
||||
|
@ -574,7 +581,11 @@ br_model* LoadModel(char* pName) {
|
|||
PossibleService();
|
||||
PathCat(the_path, gApplication_path, "MODELS");
|
||||
PathCat(the_path, the_path, pName);
|
||||
return BrModelLoad(the_path);
|
||||
model = BrModelLoad(the_path);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
WhitenVertexRGB(&model, 1);
|
||||
#endif
|
||||
return model;
|
||||
}
|
||||
|
||||
// IDA: br_actor* __usercall LoadActor@<EAX>(char *pName@<EAX>)
|
||||
|
@ -637,6 +648,9 @@ void DRLoadMaterials(char* pPath_name) {
|
|||
|
||||
PossibleService();
|
||||
number_of_materials = BrMaterialLoadMany(pPath_name, material_array, COUNT_OF(material_array));
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
GlorifyMaterial(material_array, number_of_materials);
|
||||
#endif
|
||||
BrMaterialAddMany(material_array, number_of_materials);
|
||||
}
|
||||
|
||||
|
@ -648,6 +662,9 @@ void DRLoadModels(char* pPath_name) {
|
|||
|
||||
PossibleService();
|
||||
number_of_models = BrModelLoadMany(pPath_name, model_array, COUNT_OF(model_array));
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
WhitenVertexRGB(model_array, number_of_models);
|
||||
#endif
|
||||
BrModelAddMany(model_array, number_of_models);
|
||||
}
|
||||
|
||||
|
@ -698,6 +715,9 @@ void LoadInRegisteeDir(char* pThe_dir_path) {
|
|||
PathCat(reg_path, pThe_dir_path, "REG");
|
||||
LoadInFiles(reg_path, "PALETTES", DRLoadPalette);
|
||||
LoadInFiles(reg_path, "SHADETAB", DRLoadShadeTable);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
InitializePalettes();
|
||||
#endif
|
||||
LoadInFiles(reg_path, "PIXELMAP", DRLoadPixelmaps);
|
||||
LoadInFiles(reg_path, "MATERIAL", DRLoadMaterials);
|
||||
LoadInFiles(reg_path, "MODELS", DRLoadModels);
|
||||
|
@ -812,7 +832,60 @@ tS8* ConvertPixTo16BitStripMap(br_pixelmap* pBr_map) {
|
|||
tU8 byte;
|
||||
tU16* palette_entry;
|
||||
LOG_TRACE("(%p)", pBr_map);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
palette_entry = PaletteOf16Bits(gRender_palette)->pixels;
|
||||
max_line_bytes = 125 * ((pBr_map->width + 61) / 62) + 2;
|
||||
new_line = BrMemAllocate(max_line_bytes, kMem_strip_image);
|
||||
temp_strip_image = BrMemAllocate(max_line_bytes * pBr_map->height, kMem_strip_image);
|
||||
current_size = 2;
|
||||
i = 0;
|
||||
*(tU16*)temp_strip_image = pBr_map->height;
|
||||
for (i = 0; i < pBr_map->height; i++) {
|
||||
new_line_length = 2;
|
||||
counting_blanks = 0;
|
||||
next_byte = (tU8*)pBr_map->pixels + i * pBr_map->row_bytes;
|
||||
if (*next_byte == 0) {
|
||||
counting_blanks = 1;
|
||||
}
|
||||
counter = 0;
|
||||
chunk_counter = 0;
|
||||
j = 0;
|
||||
while (1) {
|
||||
while (counter < 62) {
|
||||
if (j == pBr_map->width)
|
||||
break;
|
||||
byte = *next_byte;
|
||||
if (counting_blanks != (*next_byte == 0))
|
||||
break;
|
||||
if (!counting_blanks) {
|
||||
*(tU16*)&new_line[new_line_length] = palette_entry[byte];
|
||||
new_line_length += 2;
|
||||
}
|
||||
next_byte++;
|
||||
counter++;
|
||||
j++;
|
||||
}
|
||||
if (counting_blanks) {
|
||||
new_line[new_line_length - 1] = 2 * counter;
|
||||
} else {
|
||||
new_line[new_line_length - 2 * counter - 1] = -2 * counter;
|
||||
}
|
||||
counting_blanks = byte == 0;
|
||||
++chunk_counter;
|
||||
counter = 0;
|
||||
if (j == pBr_map->width) {
|
||||
break;
|
||||
}
|
||||
new_line_length++;
|
||||
}
|
||||
*new_line = chunk_counter;
|
||||
memcpy(temp_strip_image + current_size, new_line, new_line_length);
|
||||
current_size += new_line_length;
|
||||
}
|
||||
strip_image = BrMemAllocate(current_size, kMem_strip_image_perm);
|
||||
memcpy(strip_image, temp_strip_image, current_size);
|
||||
BrMemFree(temp_strip_image);
|
||||
return (tS8*)strip_image;
|
||||
}
|
||||
|
||||
// IDA: tS8* __usercall ConvertPixToStripMap@<EAX>(br_pixelmap *pThe_br_map@<EAX>)
|
||||
|
@ -845,7 +918,7 @@ tS8* ConvertPixToStripMap(br_pixelmap* pThe_br_map) {
|
|||
temp_strip_image = BrMemAllocate(pThe_br_map->row_bytes * pThe_br_map->height, kMem_strip_image);
|
||||
current_size = 2;
|
||||
|
||||
*(br_uint_16*)temp_strip_image = pThe_br_map->height;
|
||||
*(tU16*)temp_strip_image = pThe_br_map->height;
|
||||
current_strip_pointer = temp_strip_image;
|
||||
|
||||
for (i = 0; i < pThe_br_map->height; i++) {
|
||||
|
@ -1703,14 +1776,19 @@ void SetModelFlags(br_model* pModel, int pOwner) {
|
|||
#else
|
||||
if (pOwner == OPPONENT_APC_IDX || gAusterity_mode) {
|
||||
#endif
|
||||
if ((pModel->flags & BR_MODF_UPDATEABLE) != 0) {
|
||||
pModel->flags &= ~(BR_MODF_KEEP_ORIGINAL | BR_MODF_UPDATEABLE);
|
||||
BrModelUpdate(pModel, BR_MODU_ALL);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (!gMaterial_fogging)
|
||||
#endif
|
||||
{
|
||||
if ((pModel->flags & BR_MODF_UPDATEABLE) != 0) {
|
||||
pModel->flags &= ~(BR_MODF_KEEP_ORIGINAL | BR_MODF_UPDATEABLE);
|
||||
BrModelUpdate(pModel, BR_MODU_ALL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
pModel->flags |= BR_MODF_DONT_WELD | BR_MODF_KEEP_ORIGINAL | BR_MODF_UPDATEABLE;
|
||||
BrModelUpdate(pModel, BR_MODU_ALL);
|
||||
}
|
||||
pModel->flags |= BR_MODF_DONT_WELD | BR_MODF_KEEP_ORIGINAL | BR_MODF_UPDATEABLE;
|
||||
BrModelUpdate(pModel, BR_MODU_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1834,9 +1912,17 @@ void LoadCar(char* pCar_name, tDriver pDriver, tCar_spec* pCar_spec, int pOwner,
|
|||
pCar_spec->cockpit_images[j] = NULL;
|
||||
} else {
|
||||
the_image = LoadPixelmap(str);
|
||||
if (the_image == NULL)
|
||||
if (the_image == NULL) {
|
||||
FatalError(kFatalError_LoadCockpitImage);
|
||||
pCar_spec->cockpit_images[j] = ConvertPixToStripMap(the_image);
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gBack_screen->type == BR_PMT_RGB_565) {
|
||||
pCar_spec->cockpit_images[j] = ConvertPixTo16BitStripMap(the_image);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
pCar_spec->cockpit_images[j] = ConvertPixToStripMap(the_image);
|
||||
}
|
||||
BrPixelmapFree(the_image);
|
||||
}
|
||||
GetALineAndDontArgue(g, s);
|
||||
|
|
|
@ -39,10 +39,30 @@ void QuitGame(void) {
|
|||
DRS3ShutDown();
|
||||
}
|
||||
if (gBr_initialized) {
|
||||
#ifdef DETHRACE_FIX_BUGS
|
||||
// In 3dfx mode, we need direct pixel access before calling `ClearEntireScreen`
|
||||
if (harness_game_config.opengl_3dfx_mode) {
|
||||
PDLockRealBackScreen(1);
|
||||
}
|
||||
#endif
|
||||
ClearEntireScreen();
|
||||
}
|
||||
PDRevertPalette();
|
||||
StopMusic();
|
||||
if (gBrZb_initialized) {
|
||||
BrZbEnd();
|
||||
}
|
||||
|
||||
if (gBr_initialized) {
|
||||
BrV1dbEndWrapper();
|
||||
}
|
||||
|
||||
#ifdef DETHRACE_FIX_BUGS
|
||||
// Hack: not sure if this is a bug in the original code or if its something caused by dethrace.
|
||||
// Avoids the device screen pixelmap being double-freed
|
||||
gDOSGfx_initialized = 0;
|
||||
#endif
|
||||
|
||||
PDShutdownSystem();
|
||||
CloseDiagnostics();
|
||||
exit(0);
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
#define _MAIN_H_
|
||||
|
||||
#include "dr_types.h"
|
||||
#include "harness/compiler.h"
|
||||
|
||||
void QuitGame(void);
|
||||
void HARNESS_NORETURN QuitGame(void);
|
||||
|
||||
tU32 TrackCount(br_actor* pActor, tU32* pCount);
|
||||
|
||||
|
|
|
@ -590,6 +590,14 @@ tRace_result MainGameLoop(void) {
|
|||
EnterUserMessage();
|
||||
SkidsPerFrame();
|
||||
if (!gWait_for_it) {
|
||||
#if defined(DETHRACE_3DFX_PATCH) && defined(DETHRACE_FIX_BUGS)
|
||||
// Fixes issue where returning to race mode from the UI shows 2d elements in the wrong colors for half a second.
|
||||
// In 3dfx mode, 2d elements are rendered using `Copy8BitTo16BitRectangleWithTransparency` which uses
|
||||
// `gCurrent_palette` to convert 8 bit to 16 bit pixels. `gCurrent_palette` is still set to the interface palette here
|
||||
// I couldn't confirm why this does not happen in the original 3dfx executable (or does it?)
|
||||
EnsureRenderPalette();
|
||||
EnsurePaletteUp();
|
||||
#endif
|
||||
RenderAFrame(1);
|
||||
}
|
||||
CheckReplayTurnOn();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "controls.h"
|
||||
#include "flicplay.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "grafdata.h"
|
||||
#include "graphics.h"
|
||||
|
@ -437,6 +438,7 @@ int QuitVerifyDone(int pCurrent_choice, int pCurrent_mode, int pGo_ahead, int pE
|
|||
if (pCurrent_choice) {
|
||||
memcpy(gBack_screen->pixels, gPixels_copy__mainmenu, gPixel_buffer_size__mainmenu);
|
||||
memcpy(gCurrent_palette_pixels, gPalette_copy__mainmenu, 0x400u);
|
||||
g16bit_palette_valid = 0;
|
||||
} else {
|
||||
ClearEntireScreen();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "displays.h"
|
||||
#include "errors.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "grafdata.h"
|
||||
#include "graphics.h"
|
||||
|
@ -1531,6 +1532,7 @@ void ReceivedGameplay(tNet_contents* pContents, tNet_message* pMessage, tU32 pRe
|
|||
FadePaletteDown();
|
||||
memcpy(gBack_screen->pixels, gPixels_copy, gPixel_buffer_size);
|
||||
memcpy(gCurrent_palette_pixels, gPalette_copy, 1024);
|
||||
g16bit_palette_valid = 0;
|
||||
BrMemFree(gPixels_copy);
|
||||
BrMemFree(gPalette_copy);
|
||||
PDScreenBufferSwap(0);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "displays.h"
|
||||
#include "errors.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "graphics.h"
|
||||
#include "harness/hooks.h"
|
||||
|
@ -1296,6 +1297,9 @@ void NetFullScreenMessage(int pStr_index, int pLeave_it_up_there) {
|
|||
if (restore_screen) {
|
||||
memcpy(gBack_screen->pixels, gPixels_copy_, gPixel_buffer_size_);
|
||||
memcpy(gCurrent_palette_pixels, gPalette_copy_, 0x400u);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
g16bit_palette_valid = 0;
|
||||
#endif
|
||||
BrMemFree(gPixels_copy_);
|
||||
BrMemFree(gPalette_copy_);
|
||||
PDScreenBufferSwap(0);
|
||||
|
@ -1577,13 +1581,11 @@ void ReceivedConfirm(tNet_contents* pContents) {
|
|||
// IDA: void __usercall ReceivedDisableCar(tNet_contents *pContents@<EAX>)
|
||||
void ReceivedDisableCar(tNet_contents* pContents) {
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedEnableCar(tNet_contents *pContents@<EAX>)
|
||||
void ReceivedEnableCar(tNet_contents* pContents) {
|
||||
LOG_TRACE("(%p)", pContents);
|
||||
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReceivedScores(tNet_contents *pContents@<EAX>)
|
||||
|
|
|
@ -45,6 +45,9 @@ void InitOilSpills(void) {
|
|||
the_material->colour_map = NULL;
|
||||
BrMatrix23Identity(&the_material->map_transform);
|
||||
the_material->index_shade = BrTableFind("IDENTITY.TAB");
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
GlorifyMaterial(&the_material, 1);
|
||||
#endif
|
||||
BrMaterialUpdate(the_material, BR_MATU_ALL);
|
||||
the_model = BrModelAllocate(NULL, 4, 2);
|
||||
the_model->flags |= BR_MODF_KEEP_ORIGINAL;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "errors.h"
|
||||
#include "flicplay.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "grafdata.h"
|
||||
#include "graphics.h"
|
||||
|
@ -313,14 +314,28 @@ void PratcamEvent(int pIndex) {
|
|||
int HighResPratBufferWidth(void) {
|
||||
int prat_width;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (!gDevious_2d || !gTextures_need_powers_of_2) {
|
||||
return 104;
|
||||
}
|
||||
for (prat_width = 1; prat_width < 104; prat_width *= 2) {
|
||||
;
|
||||
}
|
||||
return prat_width;
|
||||
}
|
||||
|
||||
// IDA: int __cdecl HighResPratBufferHeight()
|
||||
int HighResPratBufferHeight(void) {
|
||||
int prat_height;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (!gDevious_2d || !gTextures_need_powers_of_2) {
|
||||
return 110;
|
||||
}
|
||||
for (prat_height = 1; prat_height < 110; prat_height *= 2) {
|
||||
;
|
||||
}
|
||||
return prat_height;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl InitPratcam()
|
||||
|
@ -339,7 +354,11 @@ void InitPratcam(void) {
|
|||
the_pixels = BrMemAllocate(52 * 46, kMem_pratcam_pixelmap);
|
||||
break;
|
||||
case 1:
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
the_pixels = BrMemAllocate(HighResPratBufferWidth() * HighResPratBufferHeight(), kMem_pratcam_pixelmap);
|
||||
#else
|
||||
the_pixels = BrMemAllocate(104 * 110, kMem_pratcam_pixelmap);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
TELL_ME_IF_WE_PASS_THIS_WAY();
|
||||
|
@ -352,7 +371,11 @@ void InitPratcam(void) {
|
|||
gPrat_buffer = DRPixelmapAllocate(gScreen->type, 52, 46, the_pixels, 0);
|
||||
break;
|
||||
case 1:
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
gPrat_buffer = DRPixelmapAllocate(BR_PMT_INDEX_8, HighResPratBufferWidth(), HighResPratBufferHeight(), the_pixels, 0);
|
||||
#else
|
||||
gPrat_buffer = DRPixelmapAllocate(gScreen->type, 104, 110, the_pixels, 0);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
TELL_ME_IF_WE_PASS_THIS_WAY();
|
||||
|
@ -420,15 +443,15 @@ void DoPratcam(tU32 pThe_time) {
|
|||
tU32 time_diff;
|
||||
tU32 old_last_time;
|
||||
br_pixelmap* the_image;
|
||||
br_pixelmap* left_image;
|
||||
br_pixelmap* right_image;
|
||||
br_pixelmap* left_image;
|
||||
LOG_TRACE("(%d)", pThe_time);
|
||||
|
||||
if (gAusterity_mode) {
|
||||
return;
|
||||
}
|
||||
left_image = gProgram_state.current_car.prat_cam_right;
|
||||
right_image = gProgram_state.current_car.prat_cam_left;
|
||||
right_image = gProgram_state.current_car.prat_cam_right;
|
||||
left_image = gProgram_state.current_car.prat_cam_left;
|
||||
y_offset = (gNet_mode == eNet_mode_none) ? 0 : gCurrent_graf_data->net_head_box_bot + 1;
|
||||
|
||||
right_hand = gProgram_state.current_car.prat_left <= gBack_screen->width / 2;
|
||||
|
@ -461,6 +484,7 @@ void DoPratcam(tU32 pThe_time) {
|
|||
if (right_hand) {
|
||||
offset = -offset;
|
||||
}
|
||||
|
||||
DontLetFlicFuckWithPalettes();
|
||||
DisableTranslationText();
|
||||
for (i = 0; i < (old_last_time != 0 ? ((pThe_time - old_last_time) / gPrat_flic.frame_period) : 1); i++) {
|
||||
|
@ -472,12 +496,49 @@ void DoPratcam(tU32 pThe_time) {
|
|||
}
|
||||
EnableTranslationText();
|
||||
LetFlicFuckWithPalettes();
|
||||
BrPixelmapRectangleCopy(gBack_screen,
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
PDUnlockRealBackScreen(1);
|
||||
if (gDevious_2d) {
|
||||
gPrat_model->vertices[1].p.v[0] = gProgram_state.current_car.prat_left + offset;
|
||||
gPrat_model->vertices[0].p.v[0] = gProgram_state.current_car.prat_left + offset;
|
||||
gPrat_model->vertices[3].p.v[1] = -(y_offset + gProgram_state.current_car.prat_top);
|
||||
gPrat_model->vertices[0].p.v[1] = -(y_offset + gProgram_state.current_car.prat_top);
|
||||
|
||||
gPrat_model->vertices[3].p.v[0] = gPrat_model->vertices[1].p.v[0] + 104.0f;
|
||||
gPrat_model->vertices[2].p.v[0] = gPrat_model->vertices[1].p.v[0] + 104.0f;
|
||||
|
||||
gPrat_model->vertices[2].p.v[1] = gPrat_model->vertices[3].p.v[1] - 110.0f;
|
||||
gPrat_model->vertices[1].p.v[1] = gPrat_model->vertices[3].p.v[1] - 110.0f;
|
||||
BrModelUpdate(gPrat_model, BR_MODU_VERTEX_POSITIONS);
|
||||
gPrat_actor->render_style = BR_RSTYLE_FACES;
|
||||
gPrat_material->colour_map = gPrat_buffer;
|
||||
gPrat_buffer->map = gRender_palette;
|
||||
BrMapAdd(gPrat_buffer);
|
||||
BrMaterialUpdate(gPrat_material, BR_MATU_ALL);
|
||||
BrZbSceneRender(g2d_camera, g2d_camera, gBack_screen, gDepth_buffer);
|
||||
BrMapRemove(gPrat_buffer);
|
||||
gPrat_actor->render_style = BR_RSTYLE_NONE;
|
||||
} else {
|
||||
DRPixelmapRectangleCopy(
|
||||
gBack_screen,
|
||||
gProgram_state.current_car.prat_left + offset,
|
||||
gProgram_state.current_car.prat_top + y_offset,
|
||||
gPrat_buffer,
|
||||
0, 0,
|
||||
gPrat_buffer->width, gPrat_buffer->height);
|
||||
}
|
||||
PDLockRealBackScreen(1);
|
||||
#else
|
||||
BrPixelmapRectangleCopy(
|
||||
gBack_screen,
|
||||
gProgram_state.current_car.prat_left + offset,
|
||||
gProgram_state.current_car.prat_top + y_offset,
|
||||
gPrat_buffer,
|
||||
0, 0,
|
||||
gPrat_buffer->width, gPrat_buffer->height);
|
||||
#endif
|
||||
|
||||
if (gProgram_state.current_car.prat_cam_top != NULL) {
|
||||
top_border_height = gProgram_state.current_car.prat_cam_top->height;
|
||||
DRPixelmapRectangleMaskedCopy(
|
||||
|
@ -491,22 +552,22 @@ void DoPratcam(tU32 pThe_time) {
|
|||
} else {
|
||||
top_border_height = 0;
|
||||
}
|
||||
if (right_image != NULL) {
|
||||
DRPixelmapRectangleMaskedCopy(gBack_screen,
|
||||
gProgram_state.current_car.prat_left - right_image->width + offset,
|
||||
gProgram_state.current_car.prat_top - top_border_height + y_offset,
|
||||
right_image,
|
||||
0, 0,
|
||||
right_image->width, right_image->height);
|
||||
}
|
||||
if (left_image != NULL) {
|
||||
DRPixelmapRectangleMaskedCopy(gBack_screen,
|
||||
gProgram_state.current_car.prat_left - left_image->width + offset,
|
||||
gProgram_state.current_car.prat_top - top_border_height + y_offset,
|
||||
left_image,
|
||||
0, 0,
|
||||
left_image->width, left_image->height);
|
||||
}
|
||||
if (right_image != NULL) {
|
||||
DRPixelmapRectangleMaskedCopy(
|
||||
gBack_screen,
|
||||
gProgram_state.current_car.prat_right + offset - 1,
|
||||
gProgram_state.current_car.prat_top - top_border_height - 1 + y_offset,
|
||||
left_image,
|
||||
right_image,
|
||||
0, 0,
|
||||
left_image->width, left_image->height);
|
||||
right_image->width, right_image->height);
|
||||
}
|
||||
if (gProgram_state.current_car.prat_cam_bottom != NULL) {
|
||||
DRPixelmapRectangleMaskedCopy(
|
||||
|
|
|
@ -113,7 +113,12 @@ void DrawRaceList(int pOffset) {
|
|||
gBig_font,
|
||||
gRace_list[i].name);
|
||||
if (gRace_list[i].been_there_done_that && gBullet_image != NULL) {
|
||||
BrPixelmapRectangleCopy(gBack_screen,
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
DRPixelmapRectangleCopy(
|
||||
#else
|
||||
BrPixelmapRectangleCopy(
|
||||
#endif
|
||||
gBack_screen,
|
||||
gCurrent_graf_data->choose_race_bullet_left,
|
||||
y + (gBig_font->glyph_y - gBullet_image->height) / 2,
|
||||
gBullet_image,
|
||||
|
@ -2022,7 +2027,11 @@ void ChallengeStart(void) {
|
|||
BrFatal("C:\\Msdev\\Projects\\DethRace\\Racestrt.c", 2610, "Bruce bug at line %d, file C:\\Msdev\\Projects\\DethRace\\Racestrt.c", 50);
|
||||
}
|
||||
the_map = DRPixelmapAllocate(
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
BR_PMT_INDEX_8,
|
||||
#else
|
||||
gScreen->type,
|
||||
#endif
|
||||
gCurrent_graf_data->dare_mugshot_width,
|
||||
gCurrent_graf_data->dare_mugshot_height,
|
||||
0,
|
||||
|
@ -2032,7 +2041,16 @@ void ChallengeStart(void) {
|
|||
DisposeFlicPanel(0);
|
||||
TellyInImage(the_map, gCurrent_graf_data->dare_mugshot_left, gCurrent_graf_data->dare_mugshot_top);
|
||||
BrPixelmapFree(the_map);
|
||||
the_map = DRPixelmapAllocate(gScreen->type, gCurrent_graf_data->dare_text_width, gCurrent_graf_data->dare_mugshot_height, 0, 0);
|
||||
the_map = DRPixelmapAllocate(
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
BR_PMT_INDEX_8,
|
||||
#else
|
||||
gScreen->type,
|
||||
#endif
|
||||
gCurrent_graf_data->dare_text_width,
|
||||
gCurrent_graf_data->dare_mugshot_height,
|
||||
0,
|
||||
0);
|
||||
BrPixelmapFill(the_map, 0);
|
||||
TransBrPixelmapText(the_map, 0, 0, 1u, gBig_font, gOpponents[gChallenger_index__racestrt].abbrev_name);
|
||||
PathCat(the_path, gApplication_path, "DARES.TXT");
|
||||
|
|
|
@ -544,20 +544,42 @@ void BuildWrecks(void) {
|
|||
position += 1;
|
||||
}
|
||||
}
|
||||
gWreck_render_area = BrPixelmapAllocateSub(
|
||||
gBack_screen,
|
||||
gCurrent_graf_data->wreck_render_x,
|
||||
gCurrent_graf_data->wreck_render_y,
|
||||
gCurrent_graf_data->wreck_render_w,
|
||||
gCurrent_graf_data->wreck_render_h);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gScreen->type == BR_PMT_INDEX_8) {
|
||||
#endif
|
||||
gWreck_render_area = BrPixelmapAllocateSub(
|
||||
gBack_screen,
|
||||
gCurrent_graf_data->wreck_render_x,
|
||||
gCurrent_graf_data->wreck_render_y,
|
||||
gCurrent_graf_data->wreck_render_w,
|
||||
gCurrent_graf_data->wreck_render_h);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
} else {
|
||||
gWreck_render_area = BrPixelmapAllocateSub(
|
||||
gReal_back_screen,
|
||||
gCurrent_graf_data->wreck_render_x * 2,
|
||||
gCurrent_graf_data->wreck_render_y * 2 + HIRES_Y_OFFSET,
|
||||
gCurrent_graf_data->wreck_render_w * 2,
|
||||
gCurrent_graf_data->wreck_render_h * 2);
|
||||
}
|
||||
#endif
|
||||
gWreck_render_area->origin_x = gWreck_render_area->width / 2;
|
||||
gWreck_render_area->origin_y = gWreck_render_area->height / 2;
|
||||
gWreck_z_buffer = BrPixelmapAllocateSub(
|
||||
gDepth_buffer,
|
||||
gCurrent_graf_data->wreck_render_x,
|
||||
gCurrent_graf_data->wreck_render_y,
|
||||
gCurrent_graf_data->wreck_render_w,
|
||||
gCurrent_graf_data->wreck_render_h);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gScreen->type == BR_PMT_INDEX_8) {
|
||||
#endif
|
||||
gWreck_z_buffer = BrPixelmapAllocateSub(
|
||||
gDepth_buffer,
|
||||
gCurrent_graf_data->wreck_render_x,
|
||||
gCurrent_graf_data->wreck_render_y,
|
||||
gCurrent_graf_data->wreck_render_w,
|
||||
gCurrent_graf_data->wreck_render_h);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
} else {
|
||||
gWreck_z_buffer = gDepth_buffer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: void __cdecl DisposeWrecks()
|
||||
|
@ -595,9 +617,14 @@ void DisposeWrecks(void) {
|
|||
BrActorFree(gWreck_root);
|
||||
BrActorFree(gWreck_camera);
|
||||
gWreck_render_area->pixels = NULL;
|
||||
gWreck_z_buffer->pixels = NULL;
|
||||
BrPixelmapFree(gWreck_render_area);
|
||||
BrPixelmapFree(gWreck_z_buffer);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gScreen->type == BR_PMT_INDEX_8) {
|
||||
gWreck_z_buffer->pixels = NULL;
|
||||
BrPixelmapFree(gWreck_z_buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: int __usercall MatrixIsIdentity@<EAX>(br_matrix34 *pMat@<EAX>)
|
||||
|
@ -715,7 +742,7 @@ int CastSelectionRay(int* pCurrent_choice, int* pCurrent_mode) {
|
|||
GetMousePosition(&mouse_x, &mouse_y);
|
||||
if (gReal_graf_data_index != 0) {
|
||||
mouse_x = 2 * mouse_x;
|
||||
mouse_y = 2 * mouse_y + 40;
|
||||
mouse_y = 2 * mouse_y + HIRES_Y_OFFSET;
|
||||
}
|
||||
for (i = 0; i < gWreck_count; i++) {
|
||||
BrMatrix34PreScale(&gWreck_array[i].actor->t.t.mat, 2.f, 2.f, 2.f);
|
||||
|
@ -808,51 +835,115 @@ void DamageScrnDraw(int pCurrent_choice, int pCurrent_mode) {
|
|||
}
|
||||
EnsureRenderPalette();
|
||||
EnsurePaletteUp();
|
||||
BrPixelmapFill(gWreck_z_buffer, 0xffffffff);
|
||||
BrPixelmapFill(gWreck_render_area, BR_COLOUR_RGBA(0xb0, 0xb0, 0xb0, 0xb0));
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gScreen->type == BR_PMT_INDEX_8) {
|
||||
#endif
|
||||
BrPixelmapFill(gWreck_z_buffer, 0xffffffff);
|
||||
BrPixelmapFill(gWreck_render_area, BR_COLOUR_RGBA(0xb0, 0xb0, 0xb0, 0xb0));
|
||||
|
||||
rows = gWreck_render_area->height / 15.f;
|
||||
columns = gWreck_render_area->width / 15.f;
|
||||
for (v = 0; v <= rows; v++) {
|
||||
BrPixelmapLine(gWreck_render_area,
|
||||
-gWreck_render_area->origin_x,
|
||||
gWreck_render_area->height / 2.f - 15.f * (rows / 2.f - v) - gWreck_render_area->origin_y,
|
||||
gWreck_render_area->width - gWreck_render_area->origin_x,
|
||||
gWreck_render_area->height / 2.f - 15.f * (rows / 2.f - v) - gWreck_render_area->origin_y,
|
||||
8);
|
||||
}
|
||||
for (h = 0; h <= columns; h++) {
|
||||
BrPixelmapLine(gWreck_render_area,
|
||||
gWreck_render_area->width / 2.f - 15.f * (columns / 2.f - h) - gWreck_render_area->origin_x,
|
||||
-gWreck_render_area->origin_y,
|
||||
gWreck_render_area->width / 2.f - 15.f * (columns / 2.f - h) - gWreck_render_area->origin_x,
|
||||
gWreck_render_area->height - gWreck_render_area->origin_y,
|
||||
8);
|
||||
}
|
||||
BrZbSceneRenderBegin(gUniverse_actor, gWreck_camera, gWreck_render_area, gWreck_z_buffer);
|
||||
BrZbSceneRenderAdd(gWreck_root);
|
||||
BrZbSceneRenderEnd();
|
||||
if (sel_actor != NULL) {
|
||||
BrActorRemove(sel_actor);
|
||||
sel_actor->model = NULL;
|
||||
BrActorFree(sel_actor);
|
||||
}
|
||||
BrPixelmapRectangleFill(gBack_screen,
|
||||
gCurrent_graf_data->wreck_name_left,
|
||||
gCurrent_graf_data->wreck_name_top,
|
||||
gCurrent_graf_data->wreck_name_right - gCurrent_graf_data->wreck_name_left,
|
||||
gCurrent_graf_data->wreck_name_bottom - gCurrent_graf_data->wreck_name_top,
|
||||
0);
|
||||
if (gWreck_selected >= 0 && (gWreck_zoomed_in >= 0 || pCurrent_mode == 0)) {
|
||||
name = GetDriverName(gWreck_array[gWreck_selected].car_type,
|
||||
gWreck_array[gWreck_selected].car_index);
|
||||
TransBrPixelmapText(gBack_screen,
|
||||
(gCurrent_graf_data->wreck_name_left + gCurrent_graf_data->wreck_name_right - BrPixelmapTextWidth(gBack_screen, gFont_7, name)) / 2,
|
||||
gCurrent_graf_data->wreck_name_base_line,
|
||||
84,
|
||||
gFont_7,
|
||||
name);
|
||||
rows = gWreck_render_area->height / 15.f;
|
||||
columns = gWreck_render_area->width / 15.f;
|
||||
for (v = 0; v <= rows; v++) {
|
||||
BrPixelmapLine(gWreck_render_area,
|
||||
-gWreck_render_area->origin_x,
|
||||
gWreck_render_area->height / 2.f - 15.f * (rows / 2.f - v) - gWreck_render_area->origin_y,
|
||||
gWreck_render_area->width - gWreck_render_area->origin_x,
|
||||
gWreck_render_area->height / 2.f - 15.f * (rows / 2.f - v) - gWreck_render_area->origin_y,
|
||||
8);
|
||||
}
|
||||
for (h = 0; h <= columns; h++) {
|
||||
BrPixelmapLine(gWreck_render_area,
|
||||
gWreck_render_area->width / 2.f - 15.f * (columns / 2.f - h) - gWreck_render_area->origin_x,
|
||||
-gWreck_render_area->origin_y,
|
||||
gWreck_render_area->width / 2.f - 15.f * (columns / 2.f - h) - gWreck_render_area->origin_x,
|
||||
gWreck_render_area->height - gWreck_render_area->origin_y,
|
||||
8);
|
||||
}
|
||||
BrZbSceneRenderBegin(gUniverse_actor, gWreck_camera, gWreck_render_area, gWreck_z_buffer);
|
||||
BrZbSceneRenderAdd(gWreck_root);
|
||||
BrZbSceneRenderEnd();
|
||||
if (sel_actor != NULL) {
|
||||
BrActorRemove(sel_actor);
|
||||
sel_actor->model = NULL;
|
||||
BrActorFree(sel_actor);
|
||||
}
|
||||
BrPixelmapRectangleFill(gBack_screen,
|
||||
gCurrent_graf_data->wreck_name_left,
|
||||
gCurrent_graf_data->wreck_name_top,
|
||||
gCurrent_graf_data->wreck_name_right - gCurrent_graf_data->wreck_name_left,
|
||||
gCurrent_graf_data->wreck_name_bottom - gCurrent_graf_data->wreck_name_top,
|
||||
0);
|
||||
if (gWreck_selected >= 0 && (gWreck_zoomed_in >= 0 || pCurrent_mode == 0)) {
|
||||
name = GetDriverName(gWreck_array[gWreck_selected].car_type,
|
||||
gWreck_array[gWreck_selected].car_index);
|
||||
TransBrPixelmapText(gBack_screen,
|
||||
(gCurrent_graf_data->wreck_name_left + gCurrent_graf_data->wreck_name_right - BrPixelmapTextWidth(gBack_screen, gFont_7, name)) / 2,
|
||||
gCurrent_graf_data->wreck_name_base_line,
|
||||
84,
|
||||
gFont_7,
|
||||
name);
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
} else {
|
||||
rows = gCurrent_graf_data->wreck_render_h * 0.0666666f;
|
||||
columns = (double)gCurrent_graf_data->wreck_render_w * 0.0666666f;
|
||||
|
||||
BrPixelmapRectangleFill(gBack_screen, gCurrent_graf_data->wreck_render_x, gCurrent_graf_data->wreck_render_y, gCurrent_graf_data->wreck_render_w, gCurrent_graf_data->wreck_render_h, 0xB0B0B0B0);
|
||||
|
||||
for (v = 0; v <= rows; v++) {
|
||||
BrPixelmapLine(
|
||||
gBack_screen,
|
||||
gCurrent_graf_data->wreck_render_x,
|
||||
gCurrent_graf_data->wreck_render_h / 2.0f + gCurrent_graf_data->wreck_render_y - (rows / 2.0f - v) * 15.0f,
|
||||
gCurrent_graf_data->wreck_render_w + gCurrent_graf_data->wreck_render_x,
|
||||
gCurrent_graf_data->wreck_render_h / 2.0f + gCurrent_graf_data->wreck_render_y - (rows / 2.0f - v) * 15.0f,
|
||||
8);
|
||||
}
|
||||
for (h = 0; h <= columns; h++) {
|
||||
BrPixelmapLine(gBack_screen,
|
||||
gCurrent_graf_data->wreck_render_w / 2.0f + gCurrent_graf_data->wreck_render_x - (columns / 2.0f - h) * 15.0,
|
||||
gCurrent_graf_data->wreck_render_y,
|
||||
gCurrent_graf_data->wreck_render_w / 2.0f + gCurrent_graf_data->wreck_render_x - (columns / 2.0f - h) * 15.0,
|
||||
gCurrent_graf_data->wreck_render_h + gCurrent_graf_data->wreck_render_y,
|
||||
8);
|
||||
}
|
||||
if (sel_actor) {
|
||||
BrActorRemove(sel_actor);
|
||||
sel_actor->model = NULL;
|
||||
BrActorFree(sel_actor);
|
||||
}
|
||||
BrPixelmapRectangleFill(
|
||||
gBack_screen,
|
||||
gCurrent_graf_data->wreck_name_left,
|
||||
gCurrent_graf_data->wreck_name_top,
|
||||
gCurrent_graf_data->wreck_name_right - gCurrent_graf_data->wreck_name_left,
|
||||
gCurrent_graf_data->wreck_name_bottom - gCurrent_graf_data->wreck_name_top,
|
||||
0);
|
||||
if (gWreck_selected >= 0 && (gWreck_zoomed_in >= 0 || pCurrent_mode == 0)) {
|
||||
name = GetDriverName(gWreck_array[gWreck_selected].car_type, gWreck_array[gWreck_selected].car_index);
|
||||
TransBrPixelmapText(gBack_screen,
|
||||
(gCurrent_graf_data->wreck_name_left + gCurrent_graf_data->wreck_name_right - BrPixelmapTextWidth(gBack_screen, gFont_7, name)) / 2,
|
||||
gCurrent_graf_data->wreck_name_base_line,
|
||||
84,
|
||||
gFont_7,
|
||||
name);
|
||||
}
|
||||
CopyBackScreen(0);
|
||||
BrPixelmapFill(gWreck_z_buffer, 0xFFFFFFFF);
|
||||
PDUnlockRealBackScreen(1);
|
||||
|
||||
// Added by dethrace
|
||||
// 3d scene is drawn on top of the 2d hud, so we must ensure that all the 2d pixel
|
||||
// writes have been flushed to the framebuffer first
|
||||
BrPixelmapFlush(gReal_back_screen);
|
||||
// -
|
||||
|
||||
BrZbSceneRenderBegin(gUniverse_actor, gWreck_camera, gWreck_render_area, gWreck_z_buffer);
|
||||
BrZbSceneRenderAdd(gWreck_root);
|
||||
BrZbSceneRenderEnd();
|
||||
PDLockRealBackScreen(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: int __usercall DamageScrnLeft@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
||||
|
@ -1222,10 +1313,10 @@ void NetSumDraw(int pCurrent_choice, int pCurrent_mode) {
|
|||
DRPixelmapRectangleMaskedCopy(gBack_screen,
|
||||
gCurrent_graf_data->net_sum_x_1,
|
||||
gCurrent_graf_data->net_sum_headings_y + 1 + i * gCurrent_graf_data->net_sum_y_pitch,
|
||||
gIcons_pix_low_res, /* DOS version uses low res, Windows version uses normal res */
|
||||
gIcons_pix_low_res, /* DOS version uses low res, Windows version uses normal res */
|
||||
0,
|
||||
gCurrent_graf_data->net_head_icon_height * player->car_index,
|
||||
gIcons_pix_low_res->width, /* DOS version uses low res, Windows version uses normal res */
|
||||
gIcons_pix_low_res->width, /* DOS version uses low res, Windows version uses normal res */
|
||||
gCurrent_graf_data->net_head_icon_height);
|
||||
TurnOnPaletteConversion();
|
||||
DrawAnItem__racesumm(gCurrent_graf_data->net_sum_x_2, i, 83, s);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "loading.h"
|
||||
#include "oil.h"
|
||||
#include "piping.h"
|
||||
#include "utility.h"
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -139,12 +140,24 @@ void InitSkids(void) {
|
|||
BrMapAdd(LoadPixelmap(str));
|
||||
strcpy(str + sl, ".MAT");
|
||||
gMaterial[mat] = LoadMaterial(str);
|
||||
if (gMaterial[mat]) {
|
||||
BrMaterialAdd(gMaterial[mat]);
|
||||
} else {
|
||||
if (gMaterial[mat] == NULL) {
|
||||
BrFatal("..\\..\\source\\common\\skidmark.c", 207, "Couldn't find %s", gMaterial_names[mat]);
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
GlorifyMaterial(&gMaterial[mat], 1);
|
||||
#endif
|
||||
BrMaterialAdd(gMaterial[mat]);
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
else {
|
||||
|
||||
BrMapRemove(gMaterial[mat]->colour_map);
|
||||
gMaterial[mat]->colour_map = PurifiedPixelmap(gMaterial[mat]->colour_map);
|
||||
BrMapAdd(gMaterial[mat]->colour_map);
|
||||
GlorifyMaterial(&gMaterial[mat], 1);
|
||||
BrMaterialUpdate(gMaterial[mat], BR_MATU_ALL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (skid = 0; skid < COUNT_OF(gSkids); skid++) {
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#include "errors.h"
|
||||
#include "formats.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrkm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "graphics.h"
|
||||
#include "harness/hooks.h"
|
||||
#include "harness/trace.h"
|
||||
|
@ -93,7 +95,22 @@ void SetWorldToScreen(br_pixelmap* pScreen) {
|
|||
// IDA: void __usercall DrawLine3DThroughBRender(br_vector3 *pStart@<EAX>, br_vector3 *pEnd@<EDX>)
|
||||
void DrawLine3DThroughBRender(br_vector3* pStart, br_vector3* pEnd) {
|
||||
LOG_TRACE("(%p, %p)", pStart, pEnd);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
gLine_model->vertices[0].p = *pStart;
|
||||
gLine_model->vertices[1].p = *pEnd;
|
||||
|
||||
// HACK: third vertex added by dethrace to work around BR_RSTYLE_EDGES (see `InitLineStuff`)
|
||||
gLine_model->vertices[2].p = *pEnd;
|
||||
gLine_model->vertices[2].p.v[0] += 0.001f;
|
||||
gLine_model->vertices[2].p.v[1] += 0.001f;
|
||||
gLine_model->vertices[2].p.v[2] += 0.001f;
|
||||
gLine_model->vertices[2].red = gLine_model->vertices[1].red;
|
||||
gLine_model->vertices[2].grn = gLine_model->vertices[1].grn;
|
||||
gLine_model->vertices[2].blu = gLine_model->vertices[1].blu;
|
||||
// HACK end
|
||||
|
||||
BrModelUpdate(gLine_model, BR_MODU_VERTEX_POSITIONS);
|
||||
BrZbSceneRenderAdd(gLine_actor);
|
||||
}
|
||||
|
||||
// IDA: int __usercall DrawLine3D@<EAX>(br_vector3 *start@<EAX>, br_vector3 *end@<EDX>, br_pixelmap *pScreen@<EBX>, br_pixelmap *pDepth_buffer@<ECX>, br_pixelmap *shade_table)
|
||||
|
@ -106,6 +123,13 @@ int DrawLine3D(br_vector3* start, br_vector3* end, br_pixelmap* pScreen, br_pixe
|
|||
br_scalar ts;
|
||||
LOG_TRACE("(%p, %p, %p, %p, %p)", start, end, pScreen, pDepth_buffer, shade_table);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gNo_2d_effects) {
|
||||
DrawLine3DThroughBRender(start, end);
|
||||
return 999;
|
||||
}
|
||||
#endif
|
||||
|
||||
o = *start;
|
||||
p = *end;
|
||||
if (-gSpark_cam->hither_z < o.v[2] || -gSpark_cam->hither_z < p.v[2]) {
|
||||
|
@ -304,7 +328,23 @@ int DrawLine2D(br_vector3* o, br_vector3* p, br_pixelmap* pScreen, br_pixelmap*
|
|||
// IDA: void __usercall SetLineModelCols(tU8 pCol@<EAX>)
|
||||
void SetLineModelCols(tU8 pCol) {
|
||||
LOG_TRACE("(%d)", pCol);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pCol != 0) {
|
||||
gLine_model->vertices[0].red = 255;
|
||||
gLine_model->vertices[0].grn = 255;
|
||||
gLine_model->vertices[0].blu = 255;
|
||||
gLine_model->vertices[1].red = 255;
|
||||
gLine_model->vertices[1].grn = 255;
|
||||
gLine_model->vertices[1].blu = 255;
|
||||
} else {
|
||||
gLine_model->vertices[0].red = 255;
|
||||
gLine_model->vertices[0].grn = 0;
|
||||
gLine_model->vertices[0].blu = 0;
|
||||
gLine_model->vertices[1].red = 255;
|
||||
gLine_model->vertices[1].grn = 255;
|
||||
gLine_model->vertices[1].blu = 0;
|
||||
}
|
||||
BrModelUpdate(gLine_model, BR_MODU_ALL);
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReplaySparks(br_pixelmap *pRender_screen@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, tU32 pTime@<ECX>)
|
||||
|
@ -359,8 +399,21 @@ void RenderSparks(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_ac
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gNo_2d_effects) {
|
||||
BrActorRemove(gLine_actor);
|
||||
BrActorAdd(pCamera, gLine_actor);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gAction_replay_mode) {
|
||||
ReplaySparks(pRender_screen, pDepth_buffer, pCamera, pTime);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gNo_2d_effects) {
|
||||
BrActorRemove(gLine_actor);
|
||||
BrActorAdd(gDont_render_actor, gLine_actor);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
StartPipingSession(ePipe_chunk_spark);
|
||||
|
@ -419,6 +472,11 @@ void RenderSparks(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_ac
|
|||
ts = 0.1f;
|
||||
}
|
||||
BrVector3Scale(&gSparks[i].v, &gSparks[i].v, ts);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gNo_2d_effects) {
|
||||
SetLineModelCols(gSparks[i].colour);
|
||||
}
|
||||
#endif
|
||||
if (gSparks[i].colour) {
|
||||
DrawLine3D(&p, &new_pos, pRender_screen, pDepth_buffer, gFog_shade_table);
|
||||
} else {
|
||||
|
@ -426,6 +484,12 @@ void RenderSparks(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_ac
|
|||
}
|
||||
}
|
||||
EndPipingSession();
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gNo_2d_effects) {
|
||||
BrActorRemove(gLine_actor);
|
||||
BrActorAdd(gDont_render_actor, gLine_actor);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: void __usercall CreateSingleSpark(tCar_spec *pCar@<EAX>, br_vector3 *pPos@<EDX>, br_vector3 *pVel@<EBX>)
|
||||
|
@ -1074,11 +1138,20 @@ void SmokeCircle(br_vector3* o, br_scalar r, br_scalar extra_z, br_scalar streng
|
|||
}
|
||||
|
||||
// IDA: int __cdecl CmpSmokeZ(void *p1, void *p2)
|
||||
int CmpSmokeZ(void* p1, void* p2) {
|
||||
int CmpSmokeZ(const void* p1, const void* p2) {
|
||||
tBRender_smoke** a;
|
||||
tBRender_smoke** b;
|
||||
LOG_TRACE("(%p, %p)", p1, p2);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
a = (tBRender_smoke**)p1;
|
||||
b = (tBRender_smoke**)p2;
|
||||
if ((*a)->pos.v[2] == (*b)->pos.v[2]) {
|
||||
return 0;
|
||||
} else if ((*a)->pos.v[2] > (*b)->pos.v[2]) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl RenderRecordedSmokeCircles()
|
||||
|
@ -1089,7 +1162,35 @@ void RenderRecordedSmokeCircles(void) {
|
|||
tU8 grn;
|
||||
tU8 blu;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
BrQsort(gBR_smoke_pointers, gN_BR_smoke_structs, sizeof(void*), CmpSmokeZ);
|
||||
|
||||
for (i = 0; i < gN_BR_smoke_structs; i++) {
|
||||
smoke = gBR_smoke_pointers[i];
|
||||
BrVector3Copy(&gBlend_actor->t.t.translate.t, &smoke->pos);
|
||||
gBlend_actor->t.t.mat.m[0][0] = smoke->r;
|
||||
gBlend_actor->t.t.mat.m[1][1] = smoke->r / smoke->aspect;
|
||||
gBlend_material->extra_prim[1].v.x = BrFloatToFixed(smoke->strength * 150.0f);
|
||||
BrMaterialUpdate(gBlend_material, BR_MATU_EXTRA_PRIM);
|
||||
|
||||
red = BR_RED(smoke->col);
|
||||
grn = BR_GRN(smoke->col);
|
||||
blu = BR_BLU(smoke->col);
|
||||
gBlend_model->vertices[0].red = red;
|
||||
gBlend_model->vertices[0].grn = grn;
|
||||
gBlend_model->vertices[0].blu = blu;
|
||||
gBlend_model->vertices[1].red = red;
|
||||
gBlend_model->vertices[1].grn = grn;
|
||||
gBlend_model->vertices[1].blu = blu;
|
||||
gBlend_model->vertices[2].red = red;
|
||||
gBlend_model->vertices[2].grn = grn;
|
||||
gBlend_model->vertices[2].blu = blu;
|
||||
gBlend_model->vertices[3].red = red;
|
||||
gBlend_model->vertices[3].grn = grn;
|
||||
gBlend_model->vertices[3].blu = blu;
|
||||
BrModelUpdate(gBlend_model, BR_MODU_VERTEX_COLOURS);
|
||||
BrZbSceneRenderAdd(gBlend_actor);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall RecordSmokeCircle(br_vector3 *pCent@<EAX>, br_scalar pR, br_scalar pStrength, br_pixelmap *pShade, br_scalar pAspect)
|
||||
|
@ -1097,7 +1198,21 @@ void RecordSmokeCircle(br_vector3* pCent, br_scalar pR, br_scalar pStrength, br_
|
|||
tU8 shade_index;
|
||||
br_colour shade_rgb;
|
||||
LOG_TRACE("(%p, %f, %f, %p, %f)", pCent, pR, pStrength, pShade, pAspect);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gRendering_mirror) {
|
||||
DRMatrix34TApplyP(&gBR_smoke_structs[gN_BR_smoke_structs].pos, pCent, &gRearview_camera_to_world);
|
||||
} else {
|
||||
DRMatrix34TApplyP(&gBR_smoke_structs[gN_BR_smoke_structs].pos, pCent, &gCamera_to_world);
|
||||
}
|
||||
|
||||
gBR_smoke_structs[gN_BR_smoke_structs].r = pR;
|
||||
gBR_smoke_structs[gN_BR_smoke_structs].strength = pStrength;
|
||||
shade_index = ((tU8*)pShade->pixels)[pShade->row_bytes * (pShade->height - 1)];
|
||||
shade_rgb = ((br_colour*)gRender_palette->pixels)[shade_index];
|
||||
gBR_smoke_structs[gN_BR_smoke_structs].col = shade_rgb;
|
||||
gBR_smoke_structs[gN_BR_smoke_structs].aspect = pAspect;
|
||||
gBR_smoke_pointers[gN_BR_smoke_structs] = &gBR_smoke_structs[gN_BR_smoke_structs];
|
||||
gN_BR_smoke_structs++;
|
||||
}
|
||||
|
||||
// IDA: void __usercall SmokeCircle3D(br_vector3 *o@<EAX>, br_scalar r, br_scalar strength, br_scalar pAspect, br_pixelmap *pRender_screen, br_pixelmap *pDepth_buffer, br_pixelmap *pShade_table, br_actor *pCam)
|
||||
|
@ -1111,6 +1226,12 @@ void SmokeCircle3D(br_vector3* o, br_scalar r, br_scalar strength, br_scalar pAs
|
|||
LOG_TRACE("(%p, %f, %f, %f, %p, %p, %p, %p)", o, r, strength, pAspect, pRender_screen, pDepth_buffer, pShade_table, pCam);
|
||||
|
||||
cam = pCam->type_data;
|
||||
|
||||
if (gNo_2d_effects) {
|
||||
RecordSmokeCircle(o, r, strength, pShade_table, pAspect);
|
||||
return;
|
||||
}
|
||||
|
||||
srand(o->v[2] * 16777216.0f + o->v[1] * 65536.0f + o->v[0] * 256.0f + r);
|
||||
BrVector3Sub(&tv, o, (br_vector3*)gCamera_to_world.m[3]);
|
||||
BrMatrix34TApplyV(&p, &tv, &gCamera_to_world);
|
||||
|
@ -1229,85 +1350,115 @@ void RenderSmoke(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_act
|
|||
LOG_TRACE("(%p, %p, %p, %p, %d)", pRender_screen, pDepth_buffer, pCamera, pCamera_to_world, pTime);
|
||||
|
||||
not_lonely = 0;
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gNo_2d_effects) {
|
||||
gBlend_actor->render_style = BR_RSTYLE_FACES;
|
||||
BrActorRemove(gBlend_actor);
|
||||
BrActorAdd(pCamera, gBlend_actor);
|
||||
gN_BR_smoke_structs = 0;
|
||||
}
|
||||
#endif
|
||||
DrawTheGlow(pRender_screen, pDepth_buffer, pCamera);
|
||||
|
||||
if (gSmoke_flags != 0) {
|
||||
seed = rand();
|
||||
if (gAction_replay_mode) {
|
||||
ReplaySmoke(pRender_screen, pDepth_buffer, pCamera);
|
||||
srand(seed);
|
||||
} else {
|
||||
StartPipingSession(ePipe_chunk_smoke);
|
||||
for (i = 0; i < COUNT_OF(gSmoke); i++) {
|
||||
if ((gSmoke_flags & (1u << i)) != 0) {
|
||||
if (gSmoke[i].strength > 0.0) {
|
||||
if (gSmoke[i].time_sync) {
|
||||
BrVector3Scale(&tv, &gSmoke[i].v, gSmoke[i].time_sync / 1000.0);
|
||||
gSmoke[i].time_sync = 0;
|
||||
} else {
|
||||
BrVector3Scale(&tv, &gSmoke[i].v, pTime / 1000.0);
|
||||
}
|
||||
BrVector3Accumulate(&gSmoke[i].pos, &tv);
|
||||
} else {
|
||||
gSmoke_flags &= ~(1u << i);
|
||||
}
|
||||
if (gSmoke_flags == 0) {
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gNo_2d_effects) {
|
||||
BrActorRemove(gBlend_actor);
|
||||
BrActorAdd(gDont_render_actor, gBlend_actor);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
seed = rand();
|
||||
if (gAction_replay_mode) {
|
||||
ReplaySmoke(pRender_screen, pDepth_buffer, pCamera);
|
||||
srand(seed);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gNo_2d_effects) {
|
||||
RenderRecordedSmokeCircles();
|
||||
BrActorRemove(gBlend_actor);
|
||||
BrActorAdd(gDont_render_actor, gBlend_actor);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
StartPipingSession(ePipe_chunk_smoke);
|
||||
for (i = 0; i < COUNT_OF(gSmoke); i++) {
|
||||
if ((gSmoke_flags & (1u << i)) != 0) {
|
||||
if (gSmoke[i].strength > 0.0) {
|
||||
if (gSmoke[i].time_sync) {
|
||||
BrVector3Scale(&tv, &gSmoke[i].v, gSmoke[i].time_sync / 1000.0);
|
||||
gSmoke[i].time_sync = 0;
|
||||
} else {
|
||||
BrVector3Scale(&tv, &gSmoke[i].v, pTime / 1000.0);
|
||||
}
|
||||
BrVector3Accumulate(&gSmoke[i].pos, &tv);
|
||||
} else {
|
||||
gSmoke_flags &= ~(1u << i);
|
||||
}
|
||||
for (i = 0; i < COUNT_OF(gSmoke); i++) {
|
||||
if ((gSmoke_flags & (1u << i)) != 0) {
|
||||
if ((gSmoke[i].type & 0xf) == 7) {
|
||||
not_lonely |= 1u << i;
|
||||
} else if ((not_lonely & (1u << i)) == 0) {
|
||||
for (j = i + 1; j < COUNT_OF(gSmoke); j++) {
|
||||
if ((gSmoke_flags & (1u << j)) != 0) {
|
||||
BrVector3Sub(&tv, &gSmoke[i].pos, &gSmoke[i].pos);
|
||||
ts = BrVector3LengthSquared(&tv);
|
||||
if ((gSmoke[i].radius + gSmoke[j].radius) * (gSmoke[i].radius + gSmoke[j].radius) > ts) {
|
||||
not_lonely |= (1u << j) | (1u << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (((1u << i) & not_lonely) == 0) {
|
||||
gSmoke[i].strength = gSmoke[i].strength / 2.0;
|
||||
}
|
||||
aspect = (gSmoke[i].radius - 0.05f) / 0.25f * 0.5f + 1.0f;
|
||||
if ((gSmoke[i].type & 0x10) != 0) {
|
||||
SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius / aspect, gSmoke[i].strength, 1.0, pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xf], pCamera);
|
||||
} else {
|
||||
SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius, gSmoke[i].strength, aspect, pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xf], pCamera);
|
||||
}
|
||||
if (gSmoke[i].pipe_me) {
|
||||
AddSmokeToPipingSession(i, gSmoke[i].type, &gSmoke[i].pos, gSmoke[i].radius, gSmoke[i].strength);
|
||||
}
|
||||
gSmoke[i].radius = (double)pTime / 1000.0 * gSmoke[i].strength * 0.5 + gSmoke[i].radius;
|
||||
gSmoke[i].strength = gSmoke[i].strength - (double)pTime * gSmoke[i].decay_factor / 1000.0;
|
||||
if (gSmoke[i].radius > 0.3f) {
|
||||
gSmoke[i].radius = 0.3f;
|
||||
}
|
||||
if (gSmoke[i].strength > 0.0) {
|
||||
ts = 1.0f - (double)pTime * 0.002f;
|
||||
if (ts < 0.5f) {
|
||||
ts = 0.5f;
|
||||
}
|
||||
BrVector3Scale(&gSmoke[i].v, &gSmoke[i].v, ts);
|
||||
if (fabs(gSmoke[i].v.v[1]) < 0.43478259f && (gSmoke[i].type & 0xFu) < 7) {
|
||||
if (gSmoke[i].v.v[1] >= 0.0) {
|
||||
gSmoke[i].v.v[1] = 0.43478259f;
|
||||
} else {
|
||||
gSmoke[i].v.v[1] += 0.43478259f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gSmoke_flags &= ~(1u << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
EndPipingSession();
|
||||
srand(seed);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < COUNT_OF(gSmoke); i++) {
|
||||
if ((gSmoke_flags & (1u << i)) != 0) {
|
||||
if ((gSmoke[i].type & 0xf) == 7) {
|
||||
not_lonely |= 1u << i;
|
||||
} else if ((not_lonely & (1u << i)) == 0) {
|
||||
for (j = i + 1; j < COUNT_OF(gSmoke); j++) {
|
||||
if ((gSmoke_flags & (1u << j)) != 0) {
|
||||
BrVector3Sub(&tv, &gSmoke[i].pos, &gSmoke[i].pos);
|
||||
ts = BrVector3LengthSquared(&tv);
|
||||
if ((gSmoke[i].radius + gSmoke[j].radius) * (gSmoke[i].radius + gSmoke[j].radius) > ts) {
|
||||
not_lonely |= (1u << j) | (1u << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (((1u << i) & not_lonely) == 0) {
|
||||
gSmoke[i].strength = gSmoke[i].strength / 2.0;
|
||||
}
|
||||
aspect = (gSmoke[i].radius - 0.05f) / 0.25f * 0.5f + 1.0f;
|
||||
if ((gSmoke[i].type & 0x10) != 0) {
|
||||
SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius / aspect, gSmoke[i].strength, 1.0, pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xf], pCamera);
|
||||
} else {
|
||||
SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius, gSmoke[i].strength, aspect, pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xf], pCamera);
|
||||
}
|
||||
if (gSmoke[i].pipe_me) {
|
||||
AddSmokeToPipingSession(i, gSmoke[i].type, &gSmoke[i].pos, gSmoke[i].radius, gSmoke[i].strength);
|
||||
}
|
||||
gSmoke[i].radius = (double)pTime / 1000.0 * gSmoke[i].strength * 0.5 + gSmoke[i].radius;
|
||||
gSmoke[i].strength = gSmoke[i].strength - (double)pTime * gSmoke[i].decay_factor / 1000.0;
|
||||
if (gSmoke[i].radius > 0.3f) {
|
||||
gSmoke[i].radius = 0.3f;
|
||||
}
|
||||
if (gSmoke[i].strength > 0.0) {
|
||||
ts = 1.0f - (double)pTime * 0.002f;
|
||||
if (ts < 0.5f) {
|
||||
ts = 0.5f;
|
||||
}
|
||||
BrVector3Scale(&gSmoke[i].v, &gSmoke[i].v, ts);
|
||||
if (fabs(gSmoke[i].v.v[1]) < 0.43478259f && (gSmoke[i].type & 0xFu) < 7) {
|
||||
if (gSmoke[i].v.v[1] >= 0.0) {
|
||||
gSmoke[i].v.v[1] = 0.43478259f;
|
||||
} else {
|
||||
gSmoke[i].v.v[1] += 0.43478259f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gSmoke_flags &= ~(1u << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
EndPipingSession();
|
||||
srand(seed);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gNo_2d_effects) {
|
||||
RenderRecordedSmokeCircles();
|
||||
BrActorRemove(gBlend_actor);
|
||||
BrActorAdd(gDont_render_actor, gBlend_actor);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: void __usercall CreatePuffOfSmoke(br_vector3 *pos@<EAX>, br_vector3 *v@<EDX>, br_scalar strength, br_scalar pDecay_factor, int pType, tCar_spec *pC)
|
||||
|
|
|
@ -92,7 +92,7 @@ void SmokeLine(int l, int x, br_scalar zbuff, int r_squared, tU8* scr_ptr, tU16*
|
|||
|
||||
void SmokeCircle(br_vector3* o, br_scalar r, br_scalar extra_z, br_scalar strength, br_scalar pAspect, br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_pixelmap* pShade_table);
|
||||
|
||||
int CmpSmokeZ(void* p1, void* p2);
|
||||
int CmpSmokeZ(const void* p1, const void* p2);
|
||||
|
||||
void RenderRecordedSmokeCircles(void);
|
||||
|
||||
|
|
|
@ -659,7 +659,9 @@ void InitialiseProgramState(void) {
|
|||
gProgram_state.cockpit_on = gCockpit_on;
|
||||
gProgram_state.car_name[0] = 0;
|
||||
SetSoundVolumes();
|
||||
#if !defined(DETHRACE_3DFX_PATCH)
|
||||
AllocateRearviewPixelmap();
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: void __cdecl DoProgram()
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "constants.h"
|
||||
#include "errors.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "graphics.h"
|
||||
#include "harness/config.h"
|
||||
|
@ -416,7 +417,27 @@ void CopyDoubled8BitTo16BitRectangle(br_pixelmap* pDst, br_pixelmap* pSrc, int p
|
|||
tU16* dst_start1;
|
||||
tU16* palette_entry;
|
||||
LOG_TRACE("(%p, %p, %d, %d, %d, %d, %p)", pDst, pSrc, pSrc_width, pSrc_height, pDst_x, pDst_y, pPalette);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
palette_entry = PaletteOf16Bits(pPalette)->pixels;
|
||||
|
||||
for (y = 0; y < pSrc_height; y++) {
|
||||
src_start = ((tU8*)pSrc->pixels) + pSrc->row_bytes * y;
|
||||
dst_start0 = (tU16*)(((tU8*)pDst->pixels) + pDst->row_bytes * pDst_y);
|
||||
dst_start0 += pDst_x;
|
||||
dst_start1 = (tU16*)(((tU8*)pDst->pixels) + pDst->row_bytes * (pDst_y + 1));
|
||||
dst_start1 += pDst_x;
|
||||
|
||||
for (x = 0; x < pSrc_width; x++) {
|
||||
dst_start0[0] = palette_entry[*src_start];
|
||||
dst_start0[1] = palette_entry[*src_start];
|
||||
dst_start1[0] = palette_entry[*src_start];
|
||||
dst_start1[1] = palette_entry[*src_start];
|
||||
src_start++;
|
||||
dst_start0 += 2;
|
||||
dst_start1 += 2;
|
||||
}
|
||||
pDst_y += 2;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: br_pixelmap* __usercall Scale8BitPixelmap@<EAX>(br_pixelmap *pSrc@<EAX>, int pWidth@<EDX>, int pHeight@<EBX>)
|
||||
|
@ -447,7 +468,14 @@ br_pixelmap* Tile8BitPixelmap(br_pixelmap* pSrc, int pN) {
|
|||
// IDA: tException_list __usercall FindExceptionInList@<EAX>(char *pName@<EAX>, tException_list pList@<EDX>)
|
||||
tException_list FindExceptionInList(char* pName, tException_list pList) {
|
||||
LOG_TRACE("(\"%s\", %d)", pName, pList);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
while (pList) {
|
||||
if (DRStricmp(pName, pList->name) == 0) {
|
||||
return pList;
|
||||
}
|
||||
pList = pList->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// IDA: br_pixelmap* __usercall PurifiedPixelmap@<EAX>(br_pixelmap *pSrc@<EAX>)
|
||||
|
@ -458,7 +486,14 @@ br_pixelmap* PurifiedPixelmap(br_pixelmap* pSrc) {
|
|||
int new_height;
|
||||
tException_list e;
|
||||
LOG_TRACE("(%p)", pSrc);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
// dethrace: added conditional to allow both software and 3dfx modes
|
||||
if (!harness_game_config.opengl_3dfx_mode) {
|
||||
return pSrc;
|
||||
}
|
||||
|
||||
LOG_INFO("PurifiedPixelmap not implemented");
|
||||
return pSrc;
|
||||
}
|
||||
|
||||
// IDA: br_pixelmap* __usercall DRPixelmapLoad@<EAX>(char *pFile_name@<EAX>)
|
||||
|
@ -721,10 +756,18 @@ void PrintScreen(void) {
|
|||
LOG_TRACE("()");
|
||||
|
||||
f = OpenUniqueFileB("DUMP", "BMP");
|
||||
if (f != NULL) {
|
||||
PrintScreenFile(f);
|
||||
fclose(f);
|
||||
if (f == NULL) {
|
||||
return;
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (gBack_screen->type == BR_PMT_RGB_565) {
|
||||
PrintScreenFile16(f);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
PrintScreenFile(f);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
// IDA: tU32 __cdecl GetTotalTime()
|
||||
|
@ -1006,7 +1049,9 @@ tU16 PaletteEntry16Bit(br_pixelmap* pPal, int pEntry) {
|
|||
int green;
|
||||
int blue;
|
||||
LOG_TRACE("(%p, %d)", pPal, pEntry);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
src_entry = pPal->pixels;
|
||||
return ((tU8)src_entry[pEntry] >> 3) | (((src_entry[pEntry] >> 19) & 0x1F) << 11) | (32 * ((tU16)src_entry[pEntry] >> 10));
|
||||
}
|
||||
|
||||
// IDA: br_pixelmap* __usercall PaletteOf16Bits@<EAX>(br_pixelmap *pSrc@<EAX>)
|
||||
|
@ -1014,7 +1059,24 @@ br_pixelmap* PaletteOf16Bits(br_pixelmap* pSrc) {
|
|||
tU16* dst_entry;
|
||||
int value;
|
||||
LOG_TRACE("(%p)", pSrc);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (g16bit_palette == NULL) {
|
||||
g16bit_palette = BrPixelmapAllocate(BR_PMT_RGB_565, 1, 256, g16bit_palette, 0);
|
||||
if (g16bit_palette == NULL) {
|
||||
FatalError(94, "16-bit palette");
|
||||
}
|
||||
}
|
||||
if (!g16bit_palette_valid || pSrc != gSource_for_16bit_palette) {
|
||||
value = 0;
|
||||
dst_entry = g16bit_palette->pixels;
|
||||
for (value = 0; value < 256; value++) {
|
||||
*dst_entry = PaletteEntry16Bit(pSrc, value);
|
||||
dst_entry++;
|
||||
}
|
||||
gSource_for_16bit_palette = pSrc;
|
||||
g16bit_palette_valid = 1;
|
||||
}
|
||||
return g16bit_palette;
|
||||
}
|
||||
|
||||
// IDA: void __usercall Copy8BitTo16Bit(br_pixelmap *pDst@<EAX>, br_pixelmap *pSrc@<EDX>, br_pixelmap *pPalette@<EBX>)
|
||||
|
@ -1025,7 +1087,17 @@ void Copy8BitTo16Bit(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap* pPalette
|
|||
tU16* dst_start;
|
||||
tU16* palette_entry;
|
||||
LOG_TRACE("(%p, %p, %p)", pDst, pSrc, pPalette);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
palette_entry = PaletteOf16Bits(pPalette)->pixels;
|
||||
for (y = 0; y < pDst->height; y++) {
|
||||
src_start = (tU8*)pSrc->pixels + pSrc->row_bytes * y;
|
||||
dst_start = (tU16*)((tU8*)pDst->pixels + pDst->row_bytes * y);
|
||||
for (x = 0; x < pDst->width; x++) {
|
||||
*dst_start = palette_entry[*src_start];
|
||||
src_start++;
|
||||
dst_start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall Copy8BitTo16BitRectangle(br_pixelmap *pDst@<EAX>, tS16 pDst_x@<EDX>, tS16 pDst_y@<EBX>, br_pixelmap *pSrc@<ECX>, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, br_pixelmap *pPalette)
|
||||
|
@ -1036,7 +1108,57 @@ void Copy8BitTo16BitRectangle(br_pixelmap* pDst, tS16 pDst_x, tS16 pDst_y, br_pi
|
|||
tU16* dst_start;
|
||||
tU16* palette_entry;
|
||||
LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d, %p)", pDst, pDst_x, pDst_y, pSrc, pSrc_x, pSrc_y, pWidth, pHeight, pPalette);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pSrc_x < 0) {
|
||||
pWidth = pSrc_x + pWidth;
|
||||
pDst_x = pDst_x - pSrc_x;
|
||||
pSrc_x = 0;
|
||||
}
|
||||
if (pDst_x < 0) {
|
||||
pWidth += pDst_x;
|
||||
pSrc_x -= pDst_x;
|
||||
pDst_x = 0;
|
||||
}
|
||||
if (pSrc_y < 0) {
|
||||
pHeight = pSrc_y + pHeight;
|
||||
pDst_y = pDst_y - pSrc_y;
|
||||
pSrc_y = 0;
|
||||
}
|
||||
if (pDst_y < 0) {
|
||||
pHeight += pDst_y;
|
||||
pSrc_y -= pDst_y;
|
||||
pDst_y = 0;
|
||||
}
|
||||
|
||||
if (pSrc_x + pWidth > pSrc->width) {
|
||||
pWidth = pSrc->width - pSrc_x;
|
||||
}
|
||||
if (pSrc_y + pHeight > pSrc->height) {
|
||||
pHeight = pSrc->height - pSrc_y;
|
||||
}
|
||||
|
||||
if (pDst_x + pWidth > pDst->width) {
|
||||
pWidth = pDst->width - pDst_x;
|
||||
}
|
||||
if (pDst_y + pHeight > pDst->height) {
|
||||
pHeight = pDst->height - pDst_y;
|
||||
}
|
||||
|
||||
palette_entry = PaletteOf16Bits(pPalette)->pixels;
|
||||
for (y = 0; y < pHeight; y++) {
|
||||
src_start = (tU8*)pSrc->pixels + (pSrc->row_bytes * (pSrc_y + y));
|
||||
src_start += pSrc_x;
|
||||
dst_start = (tU16*)((tU8*)pDst->pixels + (pDst->row_bytes * (pDst_y + y)));
|
||||
dst_start += pDst_x;
|
||||
for (x = 0; x < pWidth; x++) {
|
||||
// even though we have a specific `WithTransparency` version of this function, this one also handles transparency!
|
||||
if (*src_start != 0) {
|
||||
*dst_start = palette_entry[*src_start];
|
||||
}
|
||||
src_start++;
|
||||
dst_start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall Copy8BitTo16BitRectangleWithTransparency(br_pixelmap *pDst@<EAX>, tS16 pDst_x@<EDX>, tS16 pDst_y@<EBX>, br_pixelmap *pSrc@<ECX>, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, br_pixelmap *pPalette)
|
||||
|
@ -1047,7 +1169,55 @@ void Copy8BitTo16BitRectangleWithTransparency(br_pixelmap* pDst, tS16 pDst_x, tS
|
|||
tU16* dst_start;
|
||||
tU16* palette_entry;
|
||||
LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d, %p)", pDst, pDst_x, pDst_y, pSrc, pSrc_x, pSrc_y, pWidth, pHeight, pPalette);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pSrc_x < 0) {
|
||||
pWidth = pSrc_x + pWidth;
|
||||
pDst_x = pDst_x - pSrc_x;
|
||||
pSrc_x = 0;
|
||||
}
|
||||
if (pDst_x < 0) {
|
||||
pWidth += pDst_x;
|
||||
pSrc_x -= pDst_x;
|
||||
pDst_x = 0;
|
||||
}
|
||||
if (pSrc_y < 0) {
|
||||
pHeight = pSrc_y + pHeight;
|
||||
pDst_y = pDst_y - pSrc_y;
|
||||
pSrc_y = 0;
|
||||
}
|
||||
if (pDst_y < 0) {
|
||||
pHeight += pDst_y;
|
||||
pSrc_y -= pDst_y;
|
||||
pDst_y = 0;
|
||||
}
|
||||
|
||||
if (pSrc_x + pWidth > pSrc->width) {
|
||||
pWidth = pSrc->width - pSrc_x;
|
||||
}
|
||||
if (pSrc_y + pHeight > pSrc->height) {
|
||||
pHeight = pSrc->height - pSrc_y;
|
||||
}
|
||||
|
||||
if (pDst_x + pWidth > pDst->width) {
|
||||
pWidth = pDst->width - pDst_x;
|
||||
}
|
||||
if (pDst_y + pHeight > pDst->height) {
|
||||
pHeight = pDst->height - pDst_y;
|
||||
}
|
||||
|
||||
palette_entry = PaletteOf16Bits(pPalette)->pixels;
|
||||
for (y = 0; y < pHeight; y++) {
|
||||
src_start = (tU8*)pSrc->pixels + (pSrc->row_bytes * (pSrc_y + y)) + pSrc_x;
|
||||
dst_start = (tU16*)((tU8*)pDst->pixels + (pDst->row_bytes * (pDst_y + y)));
|
||||
dst_start += pDst_x;
|
||||
for (x = 0; x < pWidth; x++) {
|
||||
if (*src_start != 0) {
|
||||
*dst_start = palette_entry[*src_start];
|
||||
}
|
||||
src_start++;
|
||||
dst_start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall Copy8BitToOnscreen16BitRectangleWithTransparency(br_pixelmap *pDst@<EAX>, tS16 pDst_x@<EDX>, tS16 pDst_y@<EBX>, br_pixelmap *pSrc@<ECX>, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, br_pixelmap *pPalette)
|
||||
|
@ -1058,7 +1228,20 @@ void Copy8BitToOnscreen16BitRectangleWithTransparency(br_pixelmap* pDst, tS16 pD
|
|||
tU16* dst_start;
|
||||
tU16* palette_entry;
|
||||
LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d, %p)", pDst, pDst_x, pDst_y, pSrc, pSrc_x, pSrc_y, pWidth, pHeight, pPalette);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
palette_entry = PaletteOf16Bits(pPalette)->pixels;
|
||||
for (y = 0; y < pHeight; y++) {
|
||||
src_start = (tU8*)pSrc->pixels + (pSrc->row_bytes * (pSrc_y + y)) + pSrc_x;
|
||||
dst_start = (tU16*)((tU8*)pDst->pixels + (pDst->row_bytes * (pDst_y + y)));
|
||||
dst_start += pDst_x;
|
||||
for (x = 0; x < pWidth; x++) {
|
||||
if (*src_start != 0) {
|
||||
*dst_start = palette_entry[*src_start];
|
||||
}
|
||||
src_start++;
|
||||
dst_start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall Copy8BitRectangleTo16BitRhombusWithTransparency(br_pixelmap *pDst@<EAX>, tS16 pDst_x@<EDX>, tS16 pDst_y@<EBX>, br_pixelmap *pSrc@<ECX>, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, tX1616 pShear, br_pixelmap *pPalette)
|
||||
|
@ -1073,21 +1256,95 @@ void Copy8BitRectangleTo16BitRhombusWithTransparency(br_pixelmap* pDst, tS16 pDs
|
|||
tS16 clipped_src_x;
|
||||
tS16 clipped_width;
|
||||
LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d, %d, %p)", pDst, pDst_x, pDst_y, pSrc, pSrc_x, pSrc_y, pWidth, pHeight, pShear, pPalette);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
palette_entry = PaletteOf16Bits(pPalette)->pixels;
|
||||
total_shear = 0;
|
||||
if (pSrc_y + pSrc->origin_y < 0) {
|
||||
pHeight += pSrc_y + pSrc->origin_y;
|
||||
pDst_y -= (pSrc_y + pSrc->origin_y);
|
||||
pSrc_y = 0;
|
||||
}
|
||||
if (pDst_y + pDst->origin_y < 0) {
|
||||
pHeight += pDst_y + pDst->origin_y;
|
||||
pSrc_y -= (pDst_y + pDst->origin_y);
|
||||
pDst_y = 0;
|
||||
}
|
||||
|
||||
if (pSrc_y + pSrc->origin_y + pHeight > pSrc->height) {
|
||||
pHeight = pSrc->height - (pSrc_y + pSrc->origin_y);
|
||||
}
|
||||
|
||||
if (pDst_y + pDst->origin_y + pHeight > pDst->height) {
|
||||
pHeight = pDst->height - pDst_y + pDst->origin_y;
|
||||
}
|
||||
if (pHeight > 0) {
|
||||
if (pSrc_x + pSrc->origin_x < 0) {
|
||||
pWidth += pSrc_x + pSrc->origin_x;
|
||||
pDst_x -= (pSrc_x + pSrc->origin_x);
|
||||
pSrc_x = 0;
|
||||
}
|
||||
|
||||
if (pSrc_x + pSrc->origin_x + pWidth > pSrc->width) {
|
||||
pWidth = pSrc->width - (pSrc_x + pSrc->origin_x);
|
||||
}
|
||||
for (y = 0; y < pHeight; y++) {
|
||||
clipped_src_x = pSrc_x + pSrc->origin_x;
|
||||
sheared_x = pDst_x + pDst->origin_x + (total_shear >> 16);
|
||||
clipped_width = pWidth;
|
||||
if ((sheared_x & 0x8000u) != 0) {
|
||||
clipped_width = pWidth + sheared_x;
|
||||
clipped_src_x = (pSrc_x + pSrc->origin_x) - sheared_x;
|
||||
sheared_x = 0;
|
||||
}
|
||||
|
||||
if (sheared_x + clipped_width > pDst->width) {
|
||||
clipped_width = pDst->width - sheared_x;
|
||||
}
|
||||
if (clipped_width > 0) {
|
||||
src_start = ((tU8*)pSrc->pixels) + (y + pSrc_y + pSrc->origin_y) * pSrc->row_bytes + clipped_src_x;
|
||||
dst_start = (tU16*)((tU8*)pDst->pixels + 2 * sheared_x + (y + pDst_y + pDst->origin_y) * pDst->row_bytes);
|
||||
|
||||
for (x = clipped_width; x > 0; x--) {
|
||||
if (*src_start) {
|
||||
*dst_start = palette_entry[*src_start];
|
||||
}
|
||||
src_start++;
|
||||
dst_start++;
|
||||
}
|
||||
}
|
||||
total_shear += pShear;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall DRPixelmapRectangleCopy(br_pixelmap *dst@<EAX>, br_int_16 dx@<EDX>, br_int_16 dy@<EBX>, br_pixelmap *src@<ECX>, br_int_16 sx, br_int_16 sy, br_uint_16 w, br_uint_16 h)
|
||||
void DRPixelmapRectangleCopy(br_pixelmap* dst, br_int_16 dx, br_int_16 dy, br_pixelmap* src, br_int_16 sx, br_int_16 sy, br_uint_16 w, br_uint_16 h) {
|
||||
LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d)", dst, dx, dy, src, sx, sy, w, h);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (dst->type == src->type) {
|
||||
BrPixelmapRectangleCopy(dst, dx, dy, src, sx, sy, w, h);
|
||||
} else if (dst->type == BR_PMT_RGB_565 && src->type == BR_PMT_INDEX_8) {
|
||||
Copy8BitTo16BitRectangle(dst, dx, dy, src, sx, sy, w, h, gCurrent_palette);
|
||||
}
|
||||
#else
|
||||
BrPixelmapRectangleCopy(dst, dx, dy, src, sx, sy, w, h);
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: void __usercall DRPixelmapCopy(br_pixelmap *dst@<EAX>, br_pixelmap *src@<EDX>)
|
||||
void DRPixelmapCopy(br_pixelmap* dst, br_pixelmap* src) {
|
||||
LOG_TRACE("(%p, %p)", dst, src);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (dst->type == src->type) {
|
||||
BrPixelmapCopy(dst, src);
|
||||
} else if (dst->type == BR_PMT_RGB_565 && src->type == BR_PMT_INDEX_8) {
|
||||
Copy8BitTo16Bit(dst, src, gCurrent_palette);
|
||||
}
|
||||
#else
|
||||
BrPixelmapCopy(dst, src);
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: void __usercall DRPixelmapRectangleFill(br_pixelmap *dst@<EAX>, br_int_16 x@<EDX>, br_int_16 y@<EBX>, br_uint_16 w@<ECX>, br_uint_16 h, br_uint_32 colour)
|
||||
|
@ -1163,7 +1420,7 @@ void SubsStringJob(char* pStr, ...) {
|
|||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
sub_str = va_arg(ap, char *);
|
||||
sub_str = va_arg(ap, char*);
|
||||
StripCR(sub_str);
|
||||
strcpy(temp_str, &sub_pt[1]);
|
||||
strcpy(sub_pt, sub_str);
|
||||
|
@ -1462,7 +1719,50 @@ void GlorifyMaterial(br_material** pArray, int pCount) {
|
|||
br_pixelmap* big_tile;
|
||||
tException_list e;
|
||||
LOG_TRACE("(%p, %d)", pArray, pCount);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
// Added by dethrace.
|
||||
// `GlorifyMaterial` is only present in the 3dfx patch.
|
||||
// If software mode, don't glorify, otherwise it puts the software renderer into lit mode
|
||||
// See `WhitenVertexRGB` for a similar check that is present in the original code
|
||||
if (!harness_game_config.opengl_3dfx_mode) {
|
||||
return;
|
||||
}
|
||||
// <<<
|
||||
|
||||
for (i = 0; i < pCount; i++) {
|
||||
if (pArray[i]->colour_map != NULL) {
|
||||
e = FindExceptionInList(pArray[i]->colour_map->identifier, gExceptions);
|
||||
|
||||
if (gInterpolate_textures) {
|
||||
// use linear texture filtering unless we have a "nobilinear" flag or the texture has transparent parts
|
||||
if ((e == NULL || (e->flags & ExceptionFlag_NoBilinear) == 0)
|
||||
&& !DRPixelmapHasZeros(pArray[i]->colour_map)) {
|
||||
pArray[i]->flags |= BR_MATF_MAP_INTERPOLATION;
|
||||
}
|
||||
}
|
||||
if (gUse_mip_maps) {
|
||||
pArray[i]->flags |= BR_MATF_MAP_ANTIALIASING;
|
||||
}
|
||||
if (gPerspective_is_fast) {
|
||||
pArray[i]->flags |= BR_MATF_PERSPECTIVE;
|
||||
}
|
||||
if (e && (e->flags & ExceptionFlag_Double)) {
|
||||
pArray[i]->map_transform.m[0][0] = 0.5f;
|
||||
pArray[i]->map_transform.m[1][1] = 0.5f;
|
||||
} else if (e && (e->flags & ExceptionFlag_Quadruple)) {
|
||||
pArray[i]->map_transform.m[0][0] = 0.25f;
|
||||
pArray[i]->map_transform.m[1][1] = 0.25f;
|
||||
}
|
||||
} else {
|
||||
c = pArray[i]->index_base + pArray[i]->index_range / 2;
|
||||
pArray[i]->colour = ((br_colour*)gRender_palette->pixels)[c];
|
||||
}
|
||||
pArray[i]->ka = 1.0f;
|
||||
pArray[i]->kd = 0.0f;
|
||||
pArray[i]->ks = 0.0f;
|
||||
pArray[i]->flags &= ~BR_MATF_PRELIT;
|
||||
pArray[i]->flags |= BR_MATF_LIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall WhitenVertexRGB(br_model **pArray@<EAX>, int pN@<EDX>)
|
||||
|
@ -1471,7 +1771,17 @@ void WhitenVertexRGB(br_model** pArray, int pN) {
|
|||
int v;
|
||||
br_vertex* vertex;
|
||||
LOG_TRACE("(%p, %d)", pArray, pN);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gScreen && gScreen->type != BR_PMT_INDEX_8 && pN > 0) {
|
||||
for (m = 0; m < pN; m++) {
|
||||
vertex = pArray[m]->vertices;
|
||||
for (v = 0; v < pArray[m]->nvertices; v++, vertex++) {
|
||||
vertex->red = 255;
|
||||
vertex->grn = 255;
|
||||
vertex->blu = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall NobbleNonzeroBlacks(br_pixelmap *pPalette@<EAX>)
|
||||
|
@ -1483,7 +1793,29 @@ void NobbleNonzeroBlacks(br_pixelmap* pPalette) {
|
|||
tU32* palette_entry;
|
||||
tU32 frobbed;
|
||||
LOG_TRACE("(%p)", pPalette);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
int i;
|
||||
|
||||
palette_entry = pPalette->pixels;
|
||||
frobbed = 0;
|
||||
if (*palette_entry != 0) {
|
||||
*palette_entry = 0;
|
||||
frobbed = 1;
|
||||
}
|
||||
palette_entry++;
|
||||
for (i = 1; i < 256; i++) {
|
||||
blue = (*palette_entry >> 16) & 0xff;
|
||||
green = (*palette_entry >> 8) & 0xff;
|
||||
red = (*palette_entry) & 0xff;
|
||||
if (blue == 0 && green == 0 && red == 0) {
|
||||
frobbed = 1;
|
||||
*palette_entry = 0x010101;
|
||||
}
|
||||
palette_entry++;
|
||||
}
|
||||
if (frobbed) {
|
||||
BrMapUpdate(pPalette, BR_MAPU_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: int __usercall PDCheckDriveExists@<EAX>(char *pThe_path@<EAX>)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "flicplay.h"
|
||||
#include "formats.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "globvrpb.h"
|
||||
#include "graphics.h"
|
||||
#include "harness/trace.h"
|
||||
|
@ -486,6 +487,9 @@ int LoadNMaterials(tBrender_storage* pStorage_space, FILE* pF, int pCount) {
|
|||
if (total == 0) {
|
||||
FatalError(kFatalError_LoadMaterialFile_S, str);
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
GlorifyMaterial(temp_array, total);
|
||||
#endif
|
||||
for (j = 0; j < total; j++) {
|
||||
if (temp_array[j]) {
|
||||
switch (AddMaterialToStorage(pStorage_space, temp_array[j])) {
|
||||
|
@ -527,6 +531,9 @@ int LoadNModels(tBrender_storage* pStorage_space, FILE* pF, int pCount) {
|
|||
PathCat(the_path, gApplication_path, "MODELS");
|
||||
PathCat(the_path, the_path, str);
|
||||
total = BrModelLoadMany(the_path, temp_array, 2000);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
WhitenVertexRGB(temp_array, total);
|
||||
#endif
|
||||
if (total == 0) {
|
||||
FatalError(kFatalError_LoadModelFile_S, str);
|
||||
}
|
||||
|
@ -662,7 +669,27 @@ void ProcessModelFaceMaterials2(br_model* pModel, tPMFM2CB pCallback) {
|
|||
tU16 group;
|
||||
br_material* old_mat;
|
||||
LOG_TRACE("(%p, %d)", pModel, pCallback);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pModel->faces) {
|
||||
for (f = 0; f < pModel->nfaces; f++) {
|
||||
if (pModel->faces[f].material) {
|
||||
pCallback(pModel->faces[f].material);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (pModel->prepared == NULL) {
|
||||
return;
|
||||
}
|
||||
for (group = 0; group < V11MODEL(pModel)->ngroups; group++) {
|
||||
for (f = 0; f < V11MODEL(pModel)->groups[group].nfaces; f++) {
|
||||
// old_mat = V11MODEL(pModel)->groups[group].face_colours[f];
|
||||
old_mat = V11MODEL(pModel)->groups[group].user;
|
||||
if (old_mat) {
|
||||
pCallback(old_mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall ProcessModelFaceMaterials(br_model *pModel@<EAX>, tPMFMCB pCallback@<EDX>)
|
||||
|
@ -711,6 +738,9 @@ int LoadNTrackModels(tBrender_storage* pStorage_space, FILE* pF, int pCount) {
|
|||
if (total == 0) {
|
||||
FatalError(kFatalError_LoadModelFile_S, str);
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
WhitenVertexRGB(temp_array, total);
|
||||
#endif
|
||||
for (j = 0; j < total; j++) {
|
||||
if (temp_array[j]) {
|
||||
switch (AddModelToStorage(pStorage_space, temp_array[j])) {
|
||||
|
@ -1050,7 +1080,20 @@ br_uint_32 AddProximities(br_actor* pActor, br_material* pMat, tFunkotronic_spec
|
|||
void Adjust2FloatsForExceptions(float* pVictim1, float* pVictim2, br_pixelmap* pCulprit) {
|
||||
tException_list e;
|
||||
LOG_TRACE("(%p, %p, %p)", pVictim1, pVictim2, pCulprit);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pCulprit && pCulprit->identifier != NULL) {
|
||||
e = FindExceptionInList(pCulprit->identifier, gExceptions);
|
||||
if (e) {
|
||||
if ((e->flags & ExceptionFlag_Double) != 0) {
|
||||
*pVictim1 = *pVictim1 * 2.0f;
|
||||
*pVictim2 = *pVictim2 * 2.0f;
|
||||
}
|
||||
if ((e->flags & ExceptionFlag_Quadruple) != 0) {
|
||||
*pVictim1 = *pVictim1 * 4.0f;
|
||||
*pVictim2 = *pVictim2 * 4.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall AddFunkotronics(FILE *pF@<EAX>, int pOwner@<EDX>, int pRef_offset@<EBX>)
|
||||
|
@ -1204,6 +1247,10 @@ void AddFunkotronics(FILE* pF, int pOwner, int pRef_offset) {
|
|||
the_funk->matrix_mod_data.roll_info.x_period = speed1 == 0.0f ? 0.0f : 1000.0f / speed1;
|
||||
the_funk->matrix_mod_data.roll_info.y_period = speed2 == 0.0f ? 0.0f : 1000.0f / speed2;
|
||||
}
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
Adjust2FloatsForExceptions(&the_funk->matrix_mod_data.roll_info.x_period, &the_funk->matrix_mod_data.roll_info.y_period, the_funk->material->colour_map);
|
||||
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1267,11 +1314,18 @@ void AddFunkotronics(FILE* pF, int pOwner, int pRef_offset) {
|
|||
193);
|
||||
}
|
||||
the_pixelmap = DRPixelmapAllocate(
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
BR_PMT_INDEX_8,
|
||||
#else
|
||||
gScreen->type,
|
||||
#endif
|
||||
the_funk->texture_animation_data.flic_info.flic_descriptor.width,
|
||||
the_funk->texture_animation_data.flic_info.flic_descriptor.height,
|
||||
the_pixels,
|
||||
0);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
the_pixelmap = PurifiedPixelmap(the_pixelmap);
|
||||
#endif
|
||||
AssertFlicPixelmap(&the_funk->texture_animation_data.flic_info.flic_descriptor, the_pixelmap);
|
||||
the_funk->material->colour_map = the_pixelmap;
|
||||
BrMaterialUpdate(the_funk->material, BR_MATU_ALL);
|
||||
|
@ -1826,7 +1880,15 @@ void SaveAdditionalStuff(void) {
|
|||
// IDA: br_uint_32 __cdecl ProcessMaterials(br_actor *pActor, tPMFM2CB pCallback)
|
||||
br_uint_32 ProcessMaterials(br_actor* pActor, tPMFM2CB pCallback) {
|
||||
LOG_TRACE("(%p, %d)", pActor, pCallback);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (pActor->material) {
|
||||
pCallback(pActor->material);
|
||||
}
|
||||
if (pActor->type == BR_ACTOR_MODEL && pActor->model != NULL) {
|
||||
ProcessModelFaceMaterials2(pActor->model, pCallback);
|
||||
}
|
||||
|
||||
return BrActorEnum(pActor, (br_actor_enum_cbfn*)ProcessMaterials, pCallback);
|
||||
}
|
||||
|
||||
// IDA: br_uint_32 __cdecl ProcessFaceMaterials2(br_actor *pActor, tPMFM2CB pCallback)
|
||||
|
@ -2340,7 +2402,9 @@ void ParseSpecialVolume(FILE* pF, tSpecial_volume* pSpec, char* pScreen_name_str
|
|||
// IDA: void __usercall AddExceptionToList(tException_list *pDst@<EAX>, tException_list pNew@<EDX>)
|
||||
void AddExceptionToList(tException_list* pDst, tException_list pNew) {
|
||||
LOG_TRACE("(%p, %d)", pDst, pNew);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
pNew->next = *pDst;
|
||||
*pDst = pNew;
|
||||
}
|
||||
|
||||
// IDA: void __usercall LoadExceptionsFile(char *pName@<EAX>)
|
||||
|
@ -2352,14 +2416,66 @@ void LoadExceptionsFile(char* pName) {
|
|||
tException_list e;
|
||||
char delimiters[4];
|
||||
LOG_TRACE("(\"%s\")", pName);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
strcpy(delimiters, "\t ,");
|
||||
f = DRfopen(pName, "rt");
|
||||
if (f) {
|
||||
GetALineAndDontArgue(f, line);
|
||||
tok = strtok(line, delimiters);
|
||||
if (DRStricmp(tok, "VERSION")) {
|
||||
FatalError(120, pName, "VERSION");
|
||||
}
|
||||
tok = strtok(NULL, delimiters);
|
||||
if (sscanf(tok, "%d", &file_version) == 0 || file_version != 1) {
|
||||
FatalError(121, tok, pName);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
GetALineAndDontArgue(f, line);
|
||||
tok = strtok(line, delimiters);
|
||||
if (DRStricmp(tok, "end") == 0) {
|
||||
break;
|
||||
}
|
||||
e = BrMemAllocate(sizeof(tException_list), kMem_misc);
|
||||
e->name = BrMemAllocate(strlen(tok) + 1, kMem_misc_string);
|
||||
strcpy(e->name, tok);
|
||||
e->flags = 0;
|
||||
while (1) {
|
||||
tok = strtok(NULL, delimiters);
|
||||
if (tok == NULL /*|| (IsTable[(unsigned __int8)(*v11 + 1)] & 0xE0) == 0*/) {
|
||||
break;
|
||||
}
|
||||
if (DRStricmp(tok, "mipmap") == 0) {
|
||||
e->flags |= ExceptionFlag_Mipmap;
|
||||
} else if (DRStricmp(tok, "nobilinear") == 0) {
|
||||
e->flags |= ExceptionFlag_NoBilinear;
|
||||
} else if (DRStricmp(tok, "double") == 0) {
|
||||
e->flags |= ExceptionFlag_Double;
|
||||
} else if (DRStricmp(tok, "quadruple") == 0) {
|
||||
e->flags |= ExceptionFlag_Quadruple;
|
||||
} else {
|
||||
FatalError(123, tok, pName);
|
||||
}
|
||||
}
|
||||
AddExceptionToList(&gExceptions, e);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall LoadExceptionsFileForTrack(char *pTrack_file_name@<EAX>)
|
||||
void LoadExceptionsFileForTrack(char* pTrack_file_name) {
|
||||
tPath_name exceptions_file_name;
|
||||
LOG_TRACE("(\"%s\")", pTrack_file_name);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
sprintf(
|
||||
exceptions_file_name,
|
||||
"%s%s%s%s",
|
||||
pTrack_file_name,
|
||||
gDir_separator,
|
||||
gExceptions_general_file,
|
||||
gExceptions_file_suffix);
|
||||
LoadExceptionsFile(exceptions_file_name);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl FreeExceptions()
|
||||
|
@ -2367,7 +2483,17 @@ void FreeExceptions(void) {
|
|||
tException_list list;
|
||||
tException_list next;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
list = gExceptions;
|
||||
if (list) {
|
||||
do {
|
||||
next = list->next;
|
||||
BrMemFree(list->name);
|
||||
BrMemFree(list);
|
||||
list = next;
|
||||
} while (next);
|
||||
}
|
||||
gExceptions = NULL;
|
||||
}
|
||||
|
||||
// IDA: void __usercall LoadTrack(char *pFile_name@<EAX>, tTrack_spec *pTrack_spec@<EDX>, tRace_info *pRace_info@<EBX>)
|
||||
|
@ -2418,6 +2544,9 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf
|
|||
killed_sky = 0;
|
||||
PathCat(the_path, gApplication_path, "RACES");
|
||||
PathCat(the_path, the_path, pFile_name);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
LoadExceptionsFileForTrack(the_path);
|
||||
#endif
|
||||
f = DRfopen(the_path, "rt");
|
||||
if (f == NULL) {
|
||||
FatalError(kFatalError_OpenRacesFile);
|
||||
|
@ -2524,15 +2653,20 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf
|
|||
LoadSomeMaterials(&gTrack_storage_space, f);
|
||||
SkipNLines(f);
|
||||
}
|
||||
for (i = 0; gTrack_storage_space.materials_count > i; ++i) {
|
||||
PossibleService();
|
||||
if (gTrack_storage_space.materials[i]->flags & (BR_MATF_LIGHT | BR_MATF_PRELIT | BR_MATF_SMOOTH)) {
|
||||
gTrack_storage_space.materials[i]->flags &= ~(BR_MATF_LIGHT | BR_MATF_PRELIT | BR_MATF_SMOOTH);
|
||||
if (gTrack_storage_space.materials[i]->flags & BR_MATF_TWO_SIDED) {
|
||||
gTrack_storage_space.materials[i]->user = DOUBLESIDED_USER_FLAG;
|
||||
gTrack_storage_space.materials[i]->flags &= ~BR_MATF_TWO_SIDED;
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (!gShade_tables_do_not_work)
|
||||
#endif
|
||||
{
|
||||
for (i = 0; i < gTrack_storage_space.materials_count; i++) {
|
||||
PossibleService();
|
||||
if (gTrack_storage_space.materials[i]->flags & (BR_MATF_LIGHT | BR_MATF_PRELIT | BR_MATF_SMOOTH)) {
|
||||
gTrack_storage_space.materials[i]->flags &= ~(BR_MATF_LIGHT | BR_MATF_PRELIT | BR_MATF_SMOOTH);
|
||||
if (gTrack_storage_space.materials[i]->flags & BR_MATF_TWO_SIDED) {
|
||||
gTrack_storage_space.materials[i]->user = DOUBLESIDED_USER_FLAG;
|
||||
gTrack_storage_space.materials[i]->flags &= ~BR_MATF_TWO_SIDED;
|
||||
}
|
||||
BrMaterialUpdate(gTrack_storage_space.materials[i], BR_MATU_RENDERING);
|
||||
}
|
||||
BrMaterialUpdate(gTrack_storage_space.materials[i], BR_MATU_RENDERING);
|
||||
}
|
||||
}
|
||||
if (gRace_file_version <= 5) {
|
||||
|
@ -2653,6 +2787,8 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf
|
|||
gProgram_state.default_depth_effect.start = 7;
|
||||
gProgram_state.default_depth_effect.end = 0;
|
||||
}
|
||||
#ifndef DETHRACE_3DFX_PATCH
|
||||
// In the 3dfx patch this code was moved into `InitRace`
|
||||
InstantDepthChange(
|
||||
gProgram_state.default_depth_effect.type,
|
||||
gProgram_state.default_depth_effect.sky_texture,
|
||||
|
@ -2666,6 +2802,7 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf
|
|||
if (!GetDepthCueingOn()) {
|
||||
ToggleDepthCueingQuietly();
|
||||
}
|
||||
#endif
|
||||
PossibleService();
|
||||
gDefault_engine_noise_index = GetAnInt(f);
|
||||
gDefault_water_spec_vol = &gDefault_default_water_spec_vol;
|
||||
|
@ -2810,6 +2947,13 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf
|
|||
strcat(str, ".MAT");
|
||||
material = LoadSingleMaterial(&gTrack_storage_space, str);
|
||||
pRace_info->material_modifiers[i].skid_mark_material = material;
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (material != NULL) {
|
||||
GlorifyMaterial(&material, 1);
|
||||
BrMaterialUpdate(material, BR_MATU_ALL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DETHRACE_FIX_BUGS)
|
||||
skid_mark_cnt++;
|
||||
#endif
|
||||
|
@ -2905,6 +3049,9 @@ void LoadTrack(char* pFile_name, tTrack_spec* pTrack_spec, tRace_info* pRace_inf
|
|||
FatalError(kFatalError_FileCorrupt_S, pFile_name);
|
||||
}
|
||||
fclose(f);
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
FreeExceptions();
|
||||
#endif
|
||||
}
|
||||
|
||||
// IDA: br_uint_32 __cdecl RemoveBounds(br_actor *pActor, void *pArg)
|
||||
|
@ -3000,46 +3147,46 @@ br_scalar NormaliseDegreeAngle(br_scalar pAngle) {
|
|||
|
||||
#define SAW(T, PERIOD) (fmodf((T), (PERIOD)) / (PERIOD))
|
||||
|
||||
#define MOVE_FUNK_PARAMETER(DEST, MODE, PERIOD, AMPLITUDE, FLASH_VALUE) \
|
||||
do { \
|
||||
switch (MODE) { \
|
||||
case eMove_continuous: \
|
||||
if ((PERIOD) == 0.f) { \
|
||||
DEST = 0.f; \
|
||||
} else { \
|
||||
DEST = (AMPLITUDE)*SAW(f_the_time, (PERIOD)); \
|
||||
} \
|
||||
break; \
|
||||
case eMove_controlled: \
|
||||
DEST = (PERIOD) * (AMPLITUDE); \
|
||||
break; \
|
||||
case eMove_absolute: \
|
||||
DEST = (PERIOD); \
|
||||
break; \
|
||||
case eMove_linear: \
|
||||
if ((PERIOD) == 0.f) { \
|
||||
DEST = 0.f; \
|
||||
} else { \
|
||||
DEST = (AMPLITUDE)*MapSawToTriangle(SAW(f_the_time, (PERIOD))); \
|
||||
} \
|
||||
break; \
|
||||
case eMove_flash: \
|
||||
if (2 * fmodf(f_the_time, (PERIOD)) > (PERIOD)) { \
|
||||
DEST = (FLASH_VALUE); \
|
||||
} else { \
|
||||
DEST = -(FLASH_VALUE); \
|
||||
} \
|
||||
break; \
|
||||
case eMove_harmonic: \
|
||||
if ((PERIOD) == 0.f) { \
|
||||
DEST = 0.f; \
|
||||
} else { \
|
||||
DEST = (AMPLITUDE)*BR_SIN(BR_ANGLE_DEG(SAW(f_the_time, (PERIOD)) * 360)); \
|
||||
} \
|
||||
break; \
|
||||
default: \
|
||||
TELL_ME_IF_WE_PASS_THIS_WAY(); \
|
||||
} \
|
||||
#define MOVE_FUNK_PARAMETER(DEST, MODE, PERIOD, AMPLITUDE, FLASH_VALUE) \
|
||||
do { \
|
||||
switch (MODE) { \
|
||||
case eMove_continuous: \
|
||||
if ((PERIOD) == 0.f) { \
|
||||
DEST = 0.f; \
|
||||
} else { \
|
||||
DEST = (AMPLITUDE) * SAW(f_the_time, (PERIOD)); \
|
||||
} \
|
||||
break; \
|
||||
case eMove_controlled: \
|
||||
DEST = (PERIOD) * (AMPLITUDE); \
|
||||
break; \
|
||||
case eMove_absolute: \
|
||||
DEST = (PERIOD); \
|
||||
break; \
|
||||
case eMove_linear: \
|
||||
if ((PERIOD) == 0.f) { \
|
||||
DEST = 0.f; \
|
||||
} else { \
|
||||
DEST = (AMPLITUDE) * MapSawToTriangle(SAW(f_the_time, (PERIOD))); \
|
||||
} \
|
||||
break; \
|
||||
case eMove_flash: \
|
||||
if (2 * fmodf(f_the_time, (PERIOD)) > (PERIOD)) { \
|
||||
DEST = (FLASH_VALUE); \
|
||||
} else { \
|
||||
DEST = -(FLASH_VALUE); \
|
||||
} \
|
||||
break; \
|
||||
case eMove_harmonic: \
|
||||
if ((PERIOD) == 0.f) { \
|
||||
DEST = 0.f; \
|
||||
} else { \
|
||||
DEST = (AMPLITUDE) * BR_SIN(BR_ANGLE_DEG(SAW(f_the_time, (PERIOD)) * 360)); \
|
||||
} \
|
||||
break; \
|
||||
default: \
|
||||
TELL_ME_IF_WE_PASS_THIS_WAY(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// IDA: void __cdecl FunkThoseTronics()
|
||||
|
|
|
@ -789,6 +789,14 @@ enum {
|
|||
NETMSGID_NONE = 0x20,
|
||||
};
|
||||
|
||||
// Introduced with 3DFX patch
|
||||
enum ExceptionFlags {
|
||||
ExceptionFlag_NoBilinear = 1,
|
||||
ExceptionFlag_Double = 2,
|
||||
ExceptionFlag_Quadruple = 4,
|
||||
ExceptionFlag_Mipmap = 4,
|
||||
};
|
||||
|
||||
#define FONT_TYPEABLE 0
|
||||
#define FONT_ORANGHED 1
|
||||
#define FONT_BLUEHEAD 2
|
||||
|
@ -838,4 +846,6 @@ enum {
|
|||
// average frame time in carm95
|
||||
#define MUNGE_ENGINE_INTERVAL 50
|
||||
|
||||
#define HIRES_Y_OFFSET 40
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,10 +15,13 @@ extern int original_main(int pArgc, char* pArgv[]);
|
|||
void BR_CALLBACK _BrBeginHook(void) {
|
||||
struct br_device* BR_EXPORT BrDrv1SoftPrimBegin(char* arguments);
|
||||
struct br_device* BR_EXPORT BrDrv1SoftRendBegin(char* arguments);
|
||||
struct br_device* BR_EXPORT BrDrv1VirtualFramebufferBegin(char* arguments);
|
||||
struct br_device* BR_EXPORT BrDrv1GLBegin(char* arguments);
|
||||
|
||||
BrDevAddStatic(NULL, BrDrv1SoftPrimBegin, NULL);
|
||||
BrDevAddStatic(NULL, BrDrv1SoftRendBegin, NULL);
|
||||
// BrDevAddStatic(NULL, BrDrv1SDL2Begin, NULL);
|
||||
BrDevAddStatic(NULL, BrDrv1VirtualFramebufferBegin, NULL);
|
||||
BrDevAddStatic(NULL, BrDrv1GLBegin, NULL);
|
||||
}
|
||||
|
||||
void BR_CALLBACK _BrEndHook(void) {
|
||||
|
|
|
@ -2,15 +2,18 @@
|
|||
#include "car.h"
|
||||
#include "errors.h"
|
||||
#include "globvars.h"
|
||||
#include "globvrbm.h"
|
||||
#include "grafdata.h"
|
||||
#include "graphics.h"
|
||||
#include "harness/config.h"
|
||||
#include "harness/hooks.h"
|
||||
#include "harness/os.h"
|
||||
#include "harness/trace.h"
|
||||
#include "init.h"
|
||||
#include "input.h"
|
||||
#include "loadsave.h"
|
||||
#include "main.h"
|
||||
#include "pc-dos/scancodes.h"
|
||||
#include "pd/sys.h"
|
||||
#include "sound.h"
|
||||
#include "utility.h"
|
||||
|
@ -21,17 +24,58 @@
|
|||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __DOS__
|
||||
#define GFX_INIT_STRING_32X20X8 "MCGA,W:320,H:200,B:8"
|
||||
#define GFX_INIT_STRING_64X48X8 "VESA,W:640,H:480,B:8"
|
||||
// This code comes from DOS, so small changes need to be made to run correctly on windowed systems.
|
||||
// Generally the pc-win95 does the same thing
|
||||
#define PLAY_NICE_WITH_GUI 1
|
||||
|
||||
#ifdef PLAY_NICE_WITH_GUI
|
||||
#define MOUSE_SPEED_MULTIPLIER 1
|
||||
#else
|
||||
#define MOUSE_SPEED_MULTIPLIER 0.25f
|
||||
#endif
|
||||
|
||||
int gDOSGfx_initialized;
|
||||
|
||||
int gExtra_mem;
|
||||
int gReplay_override;
|
||||
tGraf_spec gGraf_specs[2] = {
|
||||
{ 8, 1, 0, 320, 200, 0, 0, "32X20X8", "MCGA,W:320,H:200,B:8", 320, 320, 200, NULL },
|
||||
{ 8, 1, 0, 640, 480, 0, 0, "64X48X8", "VESA,W:640,H:480,B:8", 640, 640, 480, NULL }
|
||||
// { 8, 1, 0, 1920, 1080, 0, 0, "64X48X8", "VESA,W:640,H:480,B:8", 640, 1920, 1080, NULL }
|
||||
};
|
||||
int gASCII_table[128];
|
||||
tU32 gKeyboard_bits[8];
|
||||
int gASCII_shift_table[128];
|
||||
char gNetwork_profile_fname[256];
|
||||
tS32 gJoystick_min1y;
|
||||
tS32 gJoystick_min2y;
|
||||
tS32 gJoystick_min2x;
|
||||
tS32 gRaw_joystick2y;
|
||||
tS32 gRaw_joystick2x;
|
||||
tS32 gRaw_joystick1y;
|
||||
tS32 gRaw_joystick1x;
|
||||
tS32 gJoystick_range2y;
|
||||
tS32 gJoystick_range2x;
|
||||
tS32 gJoystick_range1y;
|
||||
tS32 gJoystick_range1x;
|
||||
int gNo_voodoo;
|
||||
int gSwitched_resolution;
|
||||
br_pixelmap* gReal_back_screen;
|
||||
tS32 gJoystick_min1x;
|
||||
br_pixelmap* gTemp_screen;
|
||||
tU32 gUpper_loop_limit;
|
||||
int gReal_back_screen_locked;
|
||||
void (*gPrev_keyboard_handler)();
|
||||
void (*gPrev_keyboard_handler)(void);
|
||||
tU8 gScan_code[123][2];
|
||||
|
||||
char* _unittest_last_fatal_error;
|
||||
// Added from retail executable
|
||||
int gForce_voodoo_rush_mode;
|
||||
int gForce_voodoo_mode;
|
||||
|
||||
br_device_gl_callback_procs gl_callbacks;
|
||||
br_device_virtualfb_callback_procs virtualfb_callbacks;
|
||||
|
||||
// forward declare for `PDInitialiseSystem`
|
||||
int InitJoysticks(void);
|
||||
|
||||
// IDA: void __cdecl KeyboardHandler()
|
||||
void KeyboardHandler(void) {
|
||||
|
@ -44,7 +88,7 @@ void KeyboardHandler(void) {
|
|||
|
||||
// IDA: int __usercall KeyDown@<EAX>(tU8 pScan_code@<EAX>)
|
||||
int KeyDown(tU8 pScan_code) {
|
||||
NOT_IMPLEMENTED();
|
||||
return (gKeyboard_bits[pScan_code >> 5] >> (pScan_code & 0x1F)) & 1;
|
||||
}
|
||||
|
||||
// IDA: void __usercall KeyTranslation(tU8 pKey_index@<EAX>, tU8 pScan_code_1@<EDX>, tU8 pScan_code_2@<EBX>)
|
||||
|
@ -55,19 +99,138 @@ void KeyTranslation(tU8 pKey_index, tU8 pScan_code_1, tU8 pScan_code_2) {
|
|||
|
||||
// IDA: void __cdecl KeyBegin()
|
||||
void KeyBegin(void) {
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
gScan_code[KEY_0][0] = SCANCODE_0;
|
||||
gScan_code[KEY_2][0] = SCANCODE_2;
|
||||
gScan_code[KEY_3][0] = SCANCODE_3;
|
||||
gScan_code[KEY_1][0] = SCANCODE_1;
|
||||
gScan_code[KEY_4][0] = SCANCODE_4;
|
||||
gScan_code[KEY_6][0] = SCANCODE_6;
|
||||
gScan_code[KEY_7][0] = SCANCODE_7;
|
||||
gScan_code[KEY_5][0] = SCANCODE_5;
|
||||
gScan_code[KEY_8][0] = SCANCODE_8;
|
||||
gScan_code[KEY_A][0] = SCANCODE_A;
|
||||
gScan_code[KEY_B][0] = SCANCODE_B;
|
||||
gScan_code[KEY_9][0] = SCANCODE_9;
|
||||
gScan_code[KEY_C][0] = SCANCODE_C;
|
||||
gScan_code[KEY_E][0] = SCANCODE_E;
|
||||
gScan_code[KEY_F][0] = SCANCODE_F;
|
||||
gScan_code[KEY_D][0] = SCANCODE_D;
|
||||
gScan_code[KEY_G][0] = SCANCODE_G;
|
||||
gScan_code[KEY_I][0] = SCANCODE_I;
|
||||
gScan_code[KEY_J][0] = SCANCODE_J;
|
||||
gScan_code[KEY_H][0] = SCANCODE_H;
|
||||
gScan_code[KEY_K][0] = SCANCODE_K;
|
||||
gScan_code[KEY_M][0] = SCANCODE_M;
|
||||
gScan_code[KEY_N][0] = SCANCODE_N;
|
||||
gScan_code[KEY_L][0] = SCANCODE_L;
|
||||
gScan_code[KEY_O][0] = SCANCODE_O;
|
||||
gScan_code[KEY_Q][0] = SCANCODE_Q;
|
||||
gScan_code[KEY_R][0] = SCANCODE_R;
|
||||
gScan_code[KEY_P][0] = SCANCODE_P;
|
||||
gScan_code[KEY_S][0] = SCANCODE_S;
|
||||
gScan_code[KEY_U][0] = SCANCODE_U;
|
||||
gScan_code[KEY_V][0] = SCANCODE_V;
|
||||
gScan_code[KEY_T][0] = SCANCODE_T;
|
||||
gScan_code[KEY_W][0] = SCANCODE_W;
|
||||
gScan_code[KEY_X][0] = SCANCODE_X;
|
||||
gScan_code[KEY_Y][0] = SCANCODE_Y;
|
||||
gScan_code[KEY_Z][0] = SCANCODE_Z;
|
||||
gScan_code[KEY_GRAVE][0] = SCANCODE_GRAVE;
|
||||
gScan_code[KEY_MINUS][0] = SCANCODE_MINUS;
|
||||
gScan_code[KEY_EQUALS][0] = SCANCODE_EQUALS;
|
||||
gScan_code[KEY_BACKSPACE][0] = SCANCODE_BACK;
|
||||
gScan_code[KEY_RETURN][0] = SCANCODE_RETURN;
|
||||
gScan_code[KEY_KP_ENTER][0] = SCANCODE_NUMPADENTER;
|
||||
|
||||
gScan_code[KEY_SHIFT_ANY][0] = SCANCODE_LSHIFT;
|
||||
gScan_code[KEY_SHIFT_ANY][1] = SCANCODE_RSHIFT;
|
||||
gScan_code[KEY_ALT_ANY][0] = SCANCODE_LALT;
|
||||
gScan_code[KEY_ALT_ANY][1] = SCANCODE_RALT;
|
||||
gScan_code[KEY_CTRL_ANY][0] = SCANCODE_LCONTROL;
|
||||
gScan_code[KEY_CTRL_ANY][1] = SCANCODE_RCONTROL;
|
||||
gScan_code[KEY_CTRL_ANY_2][0] = SCANCODE_LCONTROL;
|
||||
gScan_code[KEY_CTRL_ANY_2][1] = SCANCODE_RCONTROL;
|
||||
|
||||
gScan_code[KEY_CAPSLOCK][0] = SCANCODE_CAPITAL;
|
||||
gScan_code[KEY_UNKNOWN_55][0] = SCANCODE_OEM_102;
|
||||
gScan_code[KEY_SLASH][0] = SCANCODE_SLASH;
|
||||
gScan_code[KEY_SEMICOLON][0] = SCANCODE_SEMICOLON;
|
||||
gScan_code[KEY_COMMA][0] = SCANCODE_COMMA;
|
||||
gScan_code[KEY_TAB][0] = SCANCODE_TAB;
|
||||
gScan_code[KEY_PERIOD][0] = SCANCODE_PERIOD;
|
||||
gScan_code[KEY_LBRACKET][0] = SCANCODE_LBRACKET;
|
||||
gScan_code[KEY_ESCAPE][0] = SCANCODE_ESCAPE;
|
||||
gScan_code[KEY_APOSTROPHE][0] = SCANCODE_APOSTROPHE;
|
||||
gScan_code[KEY_BACKSLASH][0] = SCANCODE_BACKSLASH;
|
||||
gScan_code[KEY_INSERT][0] = SCANCODE_INSERT;
|
||||
gScan_code[KEY_END][0] = SCANCODE_END;
|
||||
gScan_code[KEY_RBRACKET][0] = SCANCODE_RBRACKET;
|
||||
gScan_code[KEY_HOME][0] = SCANCODE_HOME;
|
||||
gScan_code[KEY_PAGEUP][0] = SCANCODE_PGUP;
|
||||
gScan_code[KEY_RIGHT][0] = SCANCODE_RIGHT;
|
||||
gScan_code[KEY_DELETE][0] = SCANCODE_DELETE;
|
||||
gScan_code[KEY_LEFT][0] = SCANCODE_LEFT;
|
||||
gScan_code[KEY_UP][0] = SCANCODE_UP;
|
||||
gScan_code[KEY_PAGEDOWN][0] = SCANCODE_PGDN;
|
||||
gScan_code[KEY_KP_NUMLOCK][0] = SCANCODE_NUMLOCK;
|
||||
gScan_code[KEY_DOWN][0] = SCANCODE_DOWN;
|
||||
gScan_code[KEY_KP_DIVIDE][0] = SCANCODE_DIVIDE;
|
||||
gScan_code[KEY_KP_MULTIPLY][0] = SCANCODE_MULTIPLY;
|
||||
gScan_code[KEY_KP_PLUS][0] = SCANCODE_ADD;
|
||||
gScan_code[KEY_KP_MINUS][0] = SCANCODE_SUBTRACT;
|
||||
gScan_code[KEY_KP_EQUALS][0] = 0;
|
||||
gScan_code[KEY_KP_PERIOD][0] = SCANCODE_DECIMAL;
|
||||
gScan_code[KEY_KP_1][0] = SCANCODE_NUMPAD1;
|
||||
gScan_code[KEY_KP_3][0] = SCANCODE_NUMPAD3;
|
||||
gScan_code[KEY_KP_0][0] = SCANCODE_NUMPAD0;
|
||||
gScan_code[KEY_KP_2][0] = SCANCODE_NUMPAD2;
|
||||
gScan_code[KEY_KP_5][0] = SCANCODE_NUMPAD5;
|
||||
gScan_code[KEY_KP_7][0] = SCANCODE_NUMPAD7;
|
||||
gScan_code[KEY_KP_4][0] = SCANCODE_NUMPAD4;
|
||||
gScan_code[KEY_KP_6][0] = SCANCODE_NUMPAD6;
|
||||
gScan_code[KEY_KP_9][0] = SCANCODE_NUMPAD9;
|
||||
gScan_code[KEY_F2][0] = SCANCODE_F2;
|
||||
gScan_code[KEY_KP_8][0] = SCANCODE_NUMPAD8;
|
||||
gScan_code[KEY_F1][0] = SCANCODE_F1;
|
||||
gScan_code[KEY_F4][0] = SCANCODE_F4;
|
||||
gScan_code[KEY_F6][0] = SCANCODE_F6;
|
||||
gScan_code[KEY_F3][0] = SCANCODE_F3;
|
||||
gScan_code[KEY_F5][0] = SCANCODE_F5;
|
||||
gScan_code[KEY_F8][0] = SCANCODE_F8;
|
||||
gScan_code[KEY_F10][0] = SCANCODE_F10;
|
||||
gScan_code[KEY_F7][0] = SCANCODE_F7;
|
||||
gScan_code[KEY_F9][0] = SCANCODE_F9;
|
||||
gScan_code[KEY_F12][0] = SCANCODE_F12;
|
||||
gScan_code[KEY_SCRLK][0] = SCANCODE_SCROLL;
|
||||
gScan_code[KEY_F11][0] = SCANCODE_F11;
|
||||
gScan_code[KEY_PRTSCN][0] = 0;
|
||||
gScan_code[KEY_PAUSE][0] = 0;
|
||||
gScan_code[KEY_SPACE][0] = SCANCODE_SPACE;
|
||||
gScan_code[KEY_RSHIFT][0] = SCANCODE_RSHIFT;
|
||||
gScan_code[KEY_RALT][0] = SCANCODE_RALT;
|
||||
gScan_code[KEY_RCTRL][0] = SCANCODE_RCONTROL;
|
||||
gScan_code[KEY_LSHIFT][0] = SCANCODE_LSHIFT;
|
||||
gScan_code[KEY_LALT][0] = SCANCODE_LALT;
|
||||
gScan_code[KEY_LCTRL][0] = SCANCODE_LCONTROL;
|
||||
|
||||
// gPrev_keyboard_handler = dos_getvect(9);
|
||||
// dos_setvect(9, KeyboardHandler);
|
||||
}
|
||||
|
||||
// IDA: void __cdecl KeyEnd()
|
||||
void KeyEnd(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
// dos_setvect(9, gPrev_keyboard_handler);
|
||||
}
|
||||
|
||||
// IDA: int __usercall KeyDown22@<EAX>(int pKey_index@<EAX>)
|
||||
int KeyDown22(int pKey_index) {
|
||||
LOG_TRACE("(%d)", pKey_index);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
return KeyDown(gScan_code[pKey_index][0]) || KeyDown(gScan_code[pKey_index][1]);
|
||||
}
|
||||
|
||||
// IDA: void __usercall PDSetKeyArray(int *pKeys@<EAX>, int pMark@<EDX>)
|
||||
|
@ -76,6 +239,28 @@ void PDSetKeyArray(int* pKeys, int pMark) {
|
|||
tS32 joyX;
|
||||
tS32 joyY;
|
||||
LOG_TRACE10("(%p, %d)", pKeys, pMark);
|
||||
|
||||
#ifdef PLAY_NICE_WITH_GUI
|
||||
// Required in some cases like a tight loop waiting for a keypress
|
||||
gHarness_platform.ProcessWindowMessages(NULL);
|
||||
#endif
|
||||
|
||||
gKeys_pressed = 0;
|
||||
for (i = 0; i < COUNT_OF(gScan_code); i++) {
|
||||
if (KeyDown(gScan_code[i][0]) || KeyDown(gScan_code[i][1])) {
|
||||
gKeys_pressed = i + (gKeys_pressed << 8) + 1;
|
||||
pKeys[i] = pMark;
|
||||
} else if (pMark == pKeys[i]) {
|
||||
pKeys[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PDGetASCIIFromKey(int pKey) {
|
||||
if (PDKeyDown3(KEY_SHIFT_ANY))
|
||||
return gASCII_shift_table[pKey];
|
||||
else
|
||||
return gASCII_table[pKey];
|
||||
}
|
||||
|
||||
// IDA: void __usercall PDFatalError(char *pThe_str@<EAX>)
|
||||
|
@ -87,21 +272,37 @@ void PDFatalError(char* pThe_str) {
|
|||
exit(1);
|
||||
}
|
||||
been_here = 1;
|
||||
|
||||
dr_dprintf("FATAL ERROR: %s", pThe_str);
|
||||
|
||||
_unittest_last_fatal_error = pThe_str;
|
||||
fprintf(stderr, "FATAL ERROR: %s\n", pThe_str);
|
||||
|
||||
// wait for keypress
|
||||
|
||||
abort();
|
||||
if (gDOSGfx_initialized) {
|
||||
gDOSGfx_initialized = 0;
|
||||
BrDevEndOld();
|
||||
}
|
||||
printf("FATAL ERROR: %s\n", pThe_str);
|
||||
dr_dprintf("FATAL ERROR: %s\n", pThe_str);
|
||||
#ifdef PLAY_NICE_WITH_GUI
|
||||
gHarness_platform.ShowErrorMessage(NULL, "Carmageddon Fatal Error", pThe_str);
|
||||
#endif
|
||||
if (gBrZb_initialized) {
|
||||
gBrZb_initialized = 0;
|
||||
BrZbEnd();
|
||||
}
|
||||
if (gBr_initialized) {
|
||||
gBr_initialized = 0;
|
||||
}
|
||||
#ifndef PLAY_NICE_WITH_GUI
|
||||
// There is no window to receive keyboard events from
|
||||
while (PDAnyKeyDown() == -1) {
|
||||
}
|
||||
#endif
|
||||
QuitGame();
|
||||
}
|
||||
|
||||
// IDA: void __usercall PDNonFatalError(char *pThe_str@<EAX>)
|
||||
void PDNonFatalError(char* pThe_str) {
|
||||
LOG_TRACE("(\"%s\")", pThe_str);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
printf("ERROR: %s", pThe_str);
|
||||
while (PDAnyKeyDown() == -1) {
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl PDInitialiseSystem()
|
||||
|
@ -112,9 +313,8 @@ void PDInitialiseSystem(void) {
|
|||
|
||||
KeyBegin();
|
||||
|
||||
// v4 = DOSMouseBegin();
|
||||
gJoystick_deadzone = 8000;
|
||||
// gUpper_loop_limit = sub_A1940(v4, v5, v3, v6) / 2;
|
||||
// DOSMouseBegin();
|
||||
InitJoysticks();
|
||||
|
||||
// Demo's do not ship with KEYBOARD.COK file
|
||||
if (harness_game_info.defines.ascii_table == NULL) {
|
||||
|
@ -143,16 +343,15 @@ void PDInitialiseSystem(void) {
|
|||
}
|
||||
|
||||
// IDA: void __cdecl PDShutdownSystem()
|
||||
void PDShutdownSystem() {
|
||||
static int been_here = 0; // Added by dethrace
|
||||
void PDShutdownSystem(void) {
|
||||
LOG_TRACE("()");
|
||||
|
||||
if (!been_here) {
|
||||
Harness_Hook_PDShutdownSystem();
|
||||
} else {
|
||||
LOG_WARN("recursion detected => force exit");
|
||||
exit(8);
|
||||
// dos_setvect(9, gPrev_keyboard_handler);
|
||||
if (gDOSGfx_initialized) {
|
||||
BrDevEndOld();
|
||||
}
|
||||
// DOSMouseEnd();
|
||||
PDRevertPalette();
|
||||
}
|
||||
|
||||
// IDA: void __cdecl PDSaveOriginalPalette()
|
||||
|
@ -177,51 +376,121 @@ int PDInitScreenVars(int pArgc, char** pArgv) {
|
|||
|
||||
// IDA: void __cdecl PDInitScreen()
|
||||
void PDInitScreen(void) {
|
||||
LOG_TRACE("()");
|
||||
}
|
||||
|
||||
// IDA: void __cdecl sub_B4DB4()
|
||||
void sub_B4DB4(void) {
|
||||
// if (!gReal_back_screen->pixels_qualifier) {
|
||||
// gReal_back_screen->pixels_qualifier = (unsigned __int16)__DS__;
|
||||
// }
|
||||
}
|
||||
|
||||
// IDA: void __cdecl PDLockRealBackScreen()
|
||||
void PDLockRealBackScreen(void) {
|
||||
// In all retail 3dfx executables, it is void __usercall PDLockRealBackScreen(lock@<EAX>)
|
||||
void PDLockRealBackScreen(int lock) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (!gReal_back_screen_locked && !gReal_back_screen->pixels && lock <= gVoodoo_rush_mode) {
|
||||
sub_B4DB4();
|
||||
BrPixelmapDirectLock(gReal_back_screen, 1);
|
||||
if (!gReal_back_screen->pixels)
|
||||
FatalError(117, "gReal_back_screen");
|
||||
gReal_back_screen_locked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl PDUnlockRealBackScreen()
|
||||
void PDUnlockRealBackScreen(void) {
|
||||
// In all retail 3dfx executables, it is void __usercall PDUnlockRealBackScreen(lock@<EAX>)
|
||||
void PDUnlockRealBackScreen(int lock) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
if (gReal_back_screen_locked && gReal_back_screen->pixels && lock <= gVoodoo_rush_mode) {
|
||||
BrPixelmapDirectUnlock(gReal_back_screen);
|
||||
gReal_back_screen_locked = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __cdecl PDAllocateScreenAndBack()
|
||||
void PDAllocateScreenAndBack(void) {
|
||||
|
||||
dr_dprintf("PDAllocateScreenAndBack() - START...");
|
||||
BrMaterialFindHook(PDMissingMaterial);
|
||||
BrTableFindHook(PDMissingTable);
|
||||
BrModelFindHook(PDMissingModel);
|
||||
BrMapFindHook(PDMissingMap);
|
||||
gScreen = NULL;
|
||||
|
||||
// This is a bit of a mix between the original DOS code and windows code...
|
||||
// DOS:
|
||||
// gScreen = DOSGfxBegin(gGraf_specs[gGraf_spec_index].gfx_init_string);
|
||||
//
|
||||
// Windows:
|
||||
// SSDXInit(gGraf_specs[gGraf_spec_index].total_width, gGraf_specs[gGraf_spec_index].total_height)
|
||||
// gScreen = BrPixelmapAllocate(BR_PMT_INDEX_8, ...)
|
||||
//
|
||||
// added by dethrace. We default to software mode unless we explicitly ask for 3dfx opengl mode
|
||||
if (harness_game_config.opengl_3dfx_mode) {
|
||||
|
||||
Harness_Hook_GraphicsInit(gGraf_specs[gGraf_spec_index].total_width, gGraf_specs[gGraf_spec_index].total_height);
|
||||
gScreen = BrPixelmapAllocate(BR_PMT_INDEX_8, gGraf_specs[gGraf_spec_index].total_width, gGraf_specs[gGraf_spec_index].total_height, NULL, BR_PMAF_NORMAL);
|
||||
if (gGraf_spec_index != 0 && !gNo_voodoo) {
|
||||
|
||||
#ifdef PLAY_NICE_WITH_GUI
|
||||
gl_callbacks.get_proc_address = gHarness_platform.GL_GetProcAddress;
|
||||
gl_callbacks.swap_buffers = gHarness_platform.Swap;
|
||||
gl_callbacks.get_viewport = gHarness_platform.GetViewport;
|
||||
gHarness_platform.CreateWindow_("Carmageddon", gGraf_specs[gGraf_spec_index].phys_width, gGraf_specs[gGraf_spec_index].phys_height, eWindow_type_opengl);
|
||||
|
||||
BrDevBeginVar(&gScreen, "glrend",
|
||||
BRT_WIDTH_I32, gGraf_specs[gGraf_spec_index].phys_width,
|
||||
BRT_HEIGHT_I32, gGraf_specs[gGraf_spec_index].phys_height,
|
||||
BRT_OPENGL_CALLBACKS_P, &gl_callbacks,
|
||||
BRT_PIXEL_TYPE_U8, BR_PMT_RGB_565,
|
||||
BR_NULL_TOKEN);
|
||||
#else
|
||||
BrDevBegin(&gScreen, "3dfx_dos,w:640,h:480,b:16");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (gScreen != NULL) {
|
||||
if ((strcmp(gScreen->identifier, "Voodoo Graphics") == 0 && !gForce_voodoo_rush_mode) || gForce_voodoo_mode) {
|
||||
dr_dprintf("Voodoo Graphics mode");
|
||||
} else {
|
||||
dr_dprintf("Voodoo Rush mode");
|
||||
gVoodoo_rush_mode = 1;
|
||||
}
|
||||
gInterpolate_textures = 1;
|
||||
gUse_mip_maps = 1;
|
||||
gTextures_need_powers_of_2 = 1;
|
||||
gMax_texture_aspect_ratio = 8;
|
||||
gMax_texture_side = 256;
|
||||
gBlitting_is_slow = 1;
|
||||
gMaterial_fogging = 1;
|
||||
gExceptions_general_file = "VOODOO";
|
||||
gExceptions_file_suffix = ".TXT";
|
||||
gSmall_frames_are_slow = 1;
|
||||
gNo_2d_effects = 1;
|
||||
gPerspective_is_fast = 1;
|
||||
gNo_transients = 1;
|
||||
gDevious_2d = 1;
|
||||
gShade_tables_do_not_work = 1;
|
||||
} else {
|
||||
gExceptions_file_suffix = ".TXT";
|
||||
gInterpolate_textures = 1;
|
||||
gExceptions_general_file = "SOFTWARE";
|
||||
|
||||
#ifdef PLAY_NICE_WITH_GUI
|
||||
// Render framebuffer to memory and call hooks when swapping or palette changing
|
||||
virtualfb_callbacks.palette_changed = gHarness_platform.PaletteChanged;
|
||||
virtualfb_callbacks.swap_buffers = gHarness_platform.Swap;
|
||||
gHarness_platform.CreateWindow_("Carmageddon", gGraf_specs[gGraf_spec_index].phys_width, gGraf_specs[gGraf_spec_index].phys_height, eWindow_type_software);
|
||||
BrDevBeginVar(&gScreen, "virtualframebuffer",
|
||||
BRT_WIDTH_I32, gGraf_specs[gGraf_spec_index].phys_width,
|
||||
BRT_HEIGHT_I32, gGraf_specs[gGraf_spec_index].phys_height,
|
||||
BRT_VIRTUALFB_CALLBACKS_P, &virtualfb_callbacks,
|
||||
BR_NULL_TOKEN);
|
||||
#else
|
||||
gScreen = BrDevBeginOld(gGraf_specs[gGraf_spec_index].gfx_init_string);
|
||||
#endif
|
||||
gDOSGfx_initialized = 1;
|
||||
}
|
||||
gScreen->origin_x = 0;
|
||||
gDOSGfx_initialized = 1;
|
||||
gScreen->origin_y = 0;
|
||||
gBack_screen = BrPixelmapMatch(gScreen, BR_PMMATCH_OFFSCREEN);
|
||||
gReal_back_screen = gBack_screen;
|
||||
PDLockRealBackScreen(0);
|
||||
gBack_screen->origin_x = 0;
|
||||
gBack_screen->origin_y = 0;
|
||||
gTemp_screen = BrPixelmapMatch(gScreen, BR_PMMATCH_OFFSCREEN);
|
||||
gTemp_screen = BrPixelmapAllocate(BR_PMT_INDEX_8, gScreen->width, gScreen->height, 0, 0);
|
||||
gTemp_screen->origin_x = 0;
|
||||
gTemp_screen->origin_y = 0;
|
||||
dr_dprintf("PDAllocateScreenAndBack() - END.");
|
||||
}
|
||||
|
||||
// IDA: void __usercall Copy8BitTo16BitPixelmap(br_pixelmap *pDst@<EAX>, br_pixelmap *pSrc@<EDX>, br_pixelmap *pPalette@<EBX>)
|
||||
|
@ -236,7 +505,18 @@ void Copy8BitTo16BitPixelmap(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap*
|
|||
tU16* dst;
|
||||
tU16* palette_entry;
|
||||
LOG_TRACE("(%p, %p, %p)", pDst, pSrc, pPalette);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
palette_entry = PaletteOf16Bits(pPalette)->pixels;
|
||||
for (y = 0; pSrc->height > y; y++) {
|
||||
src = (tU8*)pSrc->pixels + pSrc->row_bytes * y;
|
||||
dst = (tU16*)((tU8*)pDst->pixels + pDst->row_bytes * y);
|
||||
for (x = 0; x < pSrc->width; x++) {
|
||||
value = *src;
|
||||
*dst = palette_entry[value];
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall Double8BitTo16BitPixelmap(br_pixelmap *pDst@<EAX>, br_pixelmap *pSrc@<EDX>, br_pixelmap *pPalette@<EBX>, tU16 pOff@<ECX>, tU16 pSrc_width, tU16 pSrc_height)
|
||||
|
@ -253,7 +533,36 @@ void Double8BitTo16BitPixelmap(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap
|
|||
tU16 sixteen;
|
||||
tU16* palette_entry;
|
||||
LOG_TRACE("(%p, %p, %p, %d, %d, %d)", pDst, pSrc, pPalette, pOff, pSrc_width, pSrc_height);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
// added by dethrace. Some local symbols seem to be missing
|
||||
int dst_y = 0;
|
||||
int line_buff_x = 0;
|
||||
static tU16 line_buff[640];
|
||||
|
||||
palette_entry = PaletteOf16Bits(pPalette)->pixels;
|
||||
if (pSrc_width > 640) {
|
||||
FatalError(94, "Double8BitTo16BitPixelmap");
|
||||
}
|
||||
dst_y = 0;
|
||||
for (y = 0; y < pSrc_height; y++) {
|
||||
src = (tU8*)pSrc->pixels + pSrc->row_bytes * y;
|
||||
dst0 = (tU16*)((tU8*)pDst->pixels + pDst->row_bytes * (dst_y + pOff));
|
||||
dst1 = (tU16*)((tU8*)pDst->pixels + pDst->row_bytes * (dst_y + pOff + 1));
|
||||
line_buff_x = 0;
|
||||
|
||||
for (x = 0; x < pSrc_width; x++) {
|
||||
sixteen = palette_entry[*src];
|
||||
line_buff[line_buff_x] = sixteen;
|
||||
line_buff[line_buff_x + 1] = sixteen;
|
||||
src++;
|
||||
line_buff_x += 2;
|
||||
}
|
||||
|
||||
// copy 2 full lines into destination
|
||||
memcpy(dst0, line_buff, pSrc_width * 2 * sizeof(tU16));
|
||||
memcpy(dst1, line_buff, pSrc_width * 2 * sizeof(tU16));
|
||||
dst_y += 2;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: br_pixelmap* __cdecl PDInterfacePixelmap()
|
||||
|
@ -265,33 +574,50 @@ br_pixelmap* PDInterfacePixelmap(void) {
|
|||
// IDA: void __cdecl SwapBackScreen()
|
||||
void SwapBackScreen(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
PDUnlockRealBackScreen(1);
|
||||
BrPixelmapDoubleBuffer(gScreen, gReal_back_screen);
|
||||
PDLockRealBackScreen(1);
|
||||
}
|
||||
|
||||
// IDA: void __usercall ReallyCopyBackScreen(int pRendering_area_only@<EAX>, int pClear_top_and_bottom@<EDX>)
|
||||
void ReallyCopyBackScreen(int pRendering_area_only, int pClear_top_and_bottom) {
|
||||
LOG_TRACE("(%d, %d)", pRendering_area_only, pClear_top_and_bottom);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
gAlready_copied = 1;
|
||||
if (pRendering_area_only) {
|
||||
BrPixelmapRectangleCopy(gScreen, gX_offset, gY_offset, gRender_screen, 0, 0, gWidth, gHeight);
|
||||
} else if (gReal_graf_data_index != gGraf_data_index) {
|
||||
BrPixelmapRectangleFill(gReal_back_screen, 0, 0, 640, 40, 0);
|
||||
BrPixelmapRectangleFill(gReal_back_screen, 0, 440, 640, 40, 0);
|
||||
if (gReal_back_screen->type == BR_PMT_RGB_565) {
|
||||
Double8BitTo16BitPixelmap(gReal_back_screen, gBack_screen, gCurrent_palette, 40, 320, 200);
|
||||
} else {
|
||||
DRPixelmapDoubledCopy(gReal_back_screen, gBack_screen, 320, 200, 0, 40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall CopyBackScreen(int pRendering_area_only@<EAX>)
|
||||
void CopyBackScreen(int pRendering_area_only) {
|
||||
LOG_TRACE("(%d)", pRendering_area_only);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
ReallyCopyBackScreen(pRendering_area_only, 1);
|
||||
}
|
||||
|
||||
// IDA: void __usercall PDScreenBufferSwap(int pRendering_area_only@<EAX>)
|
||||
void PDScreenBufferSwap(int pRendering_area_only) {
|
||||
LOG_TRACE10("(%d)", pRendering_area_only);
|
||||
if (pRendering_area_only) {
|
||||
BrPixelmapRectangleCopy(gScreen, gY_offset, gX_offset, gRender_screen, 0, 0, gWidth, gHeight);
|
||||
} else {
|
||||
if (gReal_graf_data_index == gGraf_data_index) {
|
||||
BrPixelmapDoubleBuffer(gScreen, gBack_screen);
|
||||
} else {
|
||||
DRPixelmapDoubledCopy(gTemp_screen, gBack_screen, 320, 200, 0, 40);
|
||||
BrPixelmapDoubleBuffer(gScreen, gTemp_screen);
|
||||
}
|
||||
|
||||
if (gSwitched_resolution) {
|
||||
BrPixelmapFill(gTemp_screen, 0);
|
||||
}
|
||||
if (!gAlready_copied) {
|
||||
ReallyCopyBackScreen(pRendering_area_only, 0);
|
||||
}
|
||||
gAlready_copied = 0;
|
||||
if (!pRendering_area_only) {
|
||||
SwapBackScreen();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,12 +647,9 @@ void PDInstallErrorHandlers(void) {
|
|||
|
||||
// IDA: void __cdecl PDSetFileVariables()
|
||||
void PDSetFileVariables(void) {
|
||||
gDir_separator[0] = '\\';
|
||||
|
||||
// Added >>
|
||||
// gDir_separator[0] = '\\';
|
||||
gDir_separator[0] = '/';
|
||||
gDir_separator[1] = '\0';
|
||||
// <<
|
||||
}
|
||||
|
||||
// IDA: void __usercall PDBuildAppPath(char *pThe_path@<EAX>)
|
||||
|
@ -334,7 +657,8 @@ void PDBuildAppPath(char* pThe_path) {
|
|||
int pos;
|
||||
|
||||
getcwd(pThe_path, 256);
|
||||
strcat(pThe_path, "/"); // original: pThe_path[pos] = '\\';
|
||||
// strcat(pThe_path, "\\");
|
||||
strcat(pThe_path, "/");
|
||||
strcpy(gNetwork_profile_fname, pThe_path);
|
||||
strcat(gNetwork_profile_fname, "NETWORK.INI");
|
||||
}
|
||||
|
@ -361,7 +685,9 @@ void PDSetPalette(br_pixelmap* pThe_palette) {
|
|||
void PDSetPaletteEntries(br_pixelmap* pPalette, int pFirst_colour, int pCount) {
|
||||
int i;
|
||||
tU8* p;
|
||||
p = (tU8*)pPalette->pixels + 4 * pFirst_colour;
|
||||
|
||||
p = pPalette->pixels;
|
||||
p += pFirst_colour * 4;
|
||||
for (i = pFirst_colour; i < pFirst_colour + pCount; i++) {
|
||||
#if BR_ENDIAN_BIG
|
||||
BrDevPaletteSetEntryOld(i, (p[1] << 16) | (p[2] << 8) | p[3]);
|
||||
|
@ -375,11 +701,17 @@ void PDSetPaletteEntries(br_pixelmap* pPalette, int pFirst_colour, int pCount) {
|
|||
// IDA: void __cdecl PDSwitchToRealResolution()
|
||||
void PDSwitchToRealResolution(void) {
|
||||
LOG_TRACE("()");
|
||||
|
||||
gBack_screen = gReal_back_screen;
|
||||
gSwitched_resolution = 1;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl PDSwitchToLoresMode()
|
||||
void PDSwitchToLoresMode(void) {
|
||||
LOG_TRACE("()");
|
||||
|
||||
gBack_screen = gTemp_screen;
|
||||
gSwitched_resolution = 0;
|
||||
}
|
||||
|
||||
// IDA: void __usercall PDMouseButtons(int *pButton_1@<EAX>, int *pButton_2@<EDX>)
|
||||
|
@ -389,7 +721,8 @@ void PDMouseButtons(int* pButton_1, int* pButton_2) {
|
|||
br_int_32 mouse_y;
|
||||
LOG_TRACE("(%p, %p)", pButton_1, pButton_2);
|
||||
|
||||
Harness_Hook_GetMouseButtons(pButton_1, pButton_2);
|
||||
// DOSMouseRead(...)
|
||||
gHarness_platform.GetMouseButtons(pButton_1, pButton_2);
|
||||
}
|
||||
|
||||
// IDA: void __usercall PDGetMousePosition(int *pX_coord@<EAX>, int *pY_coord@<EDX>)
|
||||
|
@ -403,23 +736,49 @@ void PDGetMousePosition(int* pX_coord, int* pY_coord) {
|
|||
static br_int_32 mouse_y;
|
||||
LOG_TRACE("(%p, %p)", pX_coord, pY_coord);
|
||||
|
||||
Harness_Hook_GetMousePosition(pX_coord, pY_coord);
|
||||
if (gReal_graf_data_index) {
|
||||
// DOSMouseRead(&mouse_x, &mouse_y, &mouse_buttons);
|
||||
gHarness_platform.GetMousePosition(&mouse_x, &mouse_y);
|
||||
|
||||
delta_x = gGraf_data[gGraf_data_index].width * mouse_x / gGraf_data[gReal_graf_data_index].width - gMouse_last_x_coord;
|
||||
delta_y = gGraf_data[gGraf_data_index].height * mouse_y / gGraf_data[gReal_graf_data_index].height - gMouse_last_y_coord;
|
||||
|
||||
mouse_x2 = (double)delta_x * MOUSE_SPEED_MULTIPLIER;
|
||||
mouse_y2 = (double)delta_y * MOUSE_SPEED_MULTIPLIER;
|
||||
|
||||
*pX_coord = gMouse_last_x_coord + mouse_x2;
|
||||
*pY_coord = gMouse_last_y_coord + mouse_y2;
|
||||
} else {
|
||||
mouse_x = gMouse_last_x_coord;
|
||||
mouse_y = gMouse_last_y_coord;
|
||||
// DOSMouseRead(&mouse_x, &mouse_y, &mouse_buttons);
|
||||
gHarness_platform.GetMousePosition(&mouse_x, &mouse_y);
|
||||
|
||||
delta_x = mouse_x - gMouse_last_x_coord;
|
||||
delta_y = mouse_y - gMouse_last_y_coord;
|
||||
*pX_coord = gMouse_last_x_coord + (MOUSE_SPEED_MULTIPLIER * delta_x);
|
||||
*pY_coord = gMouse_last_y_coord + (MOUSE_SPEED_MULTIPLIER * delta_y);
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: int __cdecl PDGetTotalTime()
|
||||
int PDGetTotalTime(void) {
|
||||
return OS_GetTime();
|
||||
return gHarness_platform.GetTicks();
|
||||
}
|
||||
|
||||
// IDA: int __usercall PDServiceSystem@<EAX>(tU32 pTime_since_last_call@<EAX>)
|
||||
int PDServiceSystem(tU32 pTime_since_last_call) {
|
||||
Harness_Hook_PDServiceSystem();
|
||||
|
||||
#ifdef PLAY_NICE_WITH_GUI
|
||||
// Added by dethrace. Win95 code does the same
|
||||
gHarness_platform.ProcessWindowMessages(NULL);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IDA: tU32 __cdecl LargestBlockAvail()
|
||||
tU32 LargestBlockAvail(void) {
|
||||
SREGS sregs;
|
||||
// SREGS sregs;
|
||||
tMem_info mem_info;
|
||||
size_t memmax;
|
||||
|
||||
|
@ -441,19 +800,60 @@ void PDAllocateActionReplayBuffer(char** pBuffer, tU32* pBuffer_size) {
|
|||
tU32 required;
|
||||
LOG_TRACE("(%p, %p)", pBuffer, pBuffer_size);
|
||||
|
||||
OS_AllocateActionReplayBuffer(pBuffer, pBuffer_size);
|
||||
lba = LargestBlockAvail();
|
||||
if (gReplay_override) {
|
||||
*pBuffer = 0;
|
||||
*pBuffer_size = 0;
|
||||
} else {
|
||||
if (gGraf_spec_index) {
|
||||
required = 600000;
|
||||
} else {
|
||||
required = 300000;
|
||||
}
|
||||
required += gExtra_mem;
|
||||
if (lba >= required + 65536) {
|
||||
required = lba - required;
|
||||
} else {
|
||||
required = 65536;
|
||||
}
|
||||
dr_dprintf("Allocated %u bytes to the action replay buffer for %s-res", required, gGraf_spec_index != 0 ? "high" : "low");
|
||||
*pBuffer = malloc(required);
|
||||
*pBuffer_size = required;
|
||||
}
|
||||
}
|
||||
|
||||
// IDA: void __usercall PDDisposeActionReplayBuffer(char *pBuffer@<EAX>)
|
||||
void PDDisposeActionReplayBuffer(char* pBuffer) {
|
||||
LOG_TRACE("(\"%s\")", pBuffer);
|
||||
|
||||
free(pBuffer);
|
||||
}
|
||||
|
||||
// IDA: void __usercall Usage(char *pProgpath@<EAX>)
|
||||
void Usage(char* pProgpath) {
|
||||
// char basename[9];
|
||||
char basename[256]; // fix: changed from 9 to avoid overflow on longer filenames
|
||||
char* basename; // changed to support longer names
|
||||
|
||||
basename = OS_Basename(pProgpath);
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
fprintf(stderr, "Usage: %s options\n", basename);
|
||||
fprintf(stderr, "E.G. %s %s 0.5 %s 0 %s 2 %s\n", basename, "-yon", "-simple", "-sound", "-spamfritter");
|
||||
fprintf(stderr, "Valid options are:\n");
|
||||
fprintf(stderr, "%s: force 640x480\n", "-hires");
|
||||
fprintf(stderr, "%s number: yon factor (between 0 and 1)\n", "-yon");
|
||||
fprintf(stderr, "%s number: car simplification level (integer between 0 and %d)\n", "-simple", 4);
|
||||
fprintf(stderr, "%s number: sound detail level (integer between 0 and 2)\n", "-sound");
|
||||
fprintf(stderr, "%s\n", "-robots");
|
||||
fprintf(stderr, "%s: force low memory mode\n", "-lomem");
|
||||
fprintf(stderr, "%s\n", "-nosound");
|
||||
fprintf(stderr, "%s: optimal spam frittering\n", "-spamfritter");
|
||||
fprintf(stderr, "%s\n", "-nocutscenes");
|
||||
fprintf(stderr, "%s\n", "-noreplay");
|
||||
fprintf(stderr, "%s\n", "-novoodoo");
|
||||
fprintf(stderr, "%s: force Voodoo Graphics mode\n", "-vgraphics");
|
||||
fprintf(stderr, "%s: force Voodoo Rush (or Voodoo 2) mode\n", "-vrush");
|
||||
#else
|
||||
fprintf(stderr,
|
||||
"Usage: %s [%s] [%s YonFactor] [%s CarSimplificationLevel] [%s SoundDetailLevel] [%s] [%s] [%s] [%s] [%s] [%s]\nWhere YonFactor is between 0 and 1,\nCarSimplificationLevel is a whole number between 0 and %d,\nand SoundDetailLevel is a whole number.\n",
|
||||
basename,
|
||||
|
@ -468,6 +868,7 @@ void Usage(char* pProgpath) {
|
|||
"-nocutscenes",
|
||||
"-noreplay",
|
||||
CAR_MAX_SIMPLIFICATION_LEVEL);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -477,6 +878,12 @@ int original_main(int pArgc, char** pArgv) {
|
|||
int i;
|
||||
float f;
|
||||
|
||||
// dethrace: added to default the software rendering mode
|
||||
if (!harness_game_config.opengl_3dfx_mode) {
|
||||
gNo_voodoo = 1;
|
||||
}
|
||||
//-
|
||||
|
||||
for (i = 1; i < pArgc; i++) {
|
||||
if (strcasecmp(pArgv[i], "-hires") == 0) {
|
||||
gGraf_spec_index = 1;
|
||||
|
@ -509,11 +916,25 @@ int original_main(int pArgc, char** pArgv) {
|
|||
gCut_scene_override = 1;
|
||||
} else if (strcasecmp(pArgv[i], "-noreplay") == 0) {
|
||||
gReplay_override = 1;
|
||||
} else if (strcasecmp(pArgv[i], "-novoodoo") == 0) {
|
||||
gNo_voodoo = 1;
|
||||
} else if (strcasecmp(pArgv[i], "-vrush") == 0) {
|
||||
gForce_voodoo_mode = 0;
|
||||
gForce_voodoo_rush_mode = 1;
|
||||
} else if (strcasecmp(pArgv[i], "-vgraphics") == 0) {
|
||||
gForce_voodoo_rush_mode = 0;
|
||||
gForce_voodoo_mode = 1;
|
||||
} else {
|
||||
Usage(pArgv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DETHRACE_3DFX_PATCH
|
||||
if (!gNo_voodoo) {
|
||||
gGraf_spec_index = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
GameMain(pArgc, pArgv);
|
||||
return 0;
|
||||
}
|
||||
|
@ -530,13 +951,7 @@ void PDEnterDebugger(char* pStr) {
|
|||
static unsigned char* save_it;
|
||||
LOG_TRACE("(\"%s\")", pStr);
|
||||
|
||||
// FIXME: uses __CrtDbgReport when using MSVC runtime
|
||||
STUB_ONCE();
|
||||
|
||||
dr_dprintf("PDEnterDebugger(): %s", pStr);
|
||||
// ShowCursor(1);
|
||||
abort();
|
||||
// ShowCursor(0);
|
||||
save_it = (unsigned char*)pStr;
|
||||
}
|
||||
|
||||
// IDA: void __cdecl PDEndItAllAndReRunTheBastard()
|
||||
|
@ -551,20 +966,40 @@ int LoopLimitTooLow(tU32 limit) {
|
|||
tU32 count;
|
||||
tU32 val;
|
||||
LOG_TRACE("(%d)", limit);
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
// v2 = j___clock(limit);
|
||||
// v3 = v2;
|
||||
// for (count = 0; count < limit; gRaw_joystick1x += v2) {
|
||||
// v5 = __inbyte(0x201u);
|
||||
// v2 = v5 & 1;
|
||||
// ++count;
|
||||
// }
|
||||
// return j___clock(v2) < (unsigned int)(v3 + 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IDA: tS32 __cdecl UpperLoopLimit()
|
||||
tS32 UpperLoopLimit(void) {
|
||||
tU32 limit;
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
for (limit = 1024; 2 * limit && LoopLimitTooLow(limit); limit *= 2)
|
||||
;
|
||||
while (2 * limit && LoopLimitTooLow(limit))
|
||||
limit *= 2;
|
||||
while (2 * limit && LoopLimitTooLow(limit))
|
||||
limit *= 2;
|
||||
return limit - 1;
|
||||
}
|
||||
|
||||
// IDA: int __cdecl InitJoysticks()
|
||||
int InitJoysticks(void) {
|
||||
LOG_TRACE("()");
|
||||
NOT_IMPLEMENTED();
|
||||
|
||||
gJoystick_deadzone = 8000;
|
||||
gUpper_loop_limit = UpperLoopLimit() / 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IDA: tU32 __usercall ReadJoystickAxis@<EAX>(int pBit@<EAX>)
|
||||
|
@ -670,6 +1105,7 @@ int PDFileUnlock(char* pThe_path) {
|
|||
}
|
||||
|
||||
// IDA: void __cdecl CriticalISR(INTPACK pRegs)
|
||||
typedef void* INTPACK;
|
||||
void CriticalISR(INTPACK pRegs) {
|
||||
LOG_TRACE("(%d)", pRegs);
|
||||
NOT_IMPLEMENTED();
|
||||
|
@ -678,7 +1114,7 @@ void CriticalISR(INTPACK pRegs) {
|
|||
// IDA: int __usercall PDCheckDriveExists2@<EAX>(char *pThe_path@<EAX>, char *pFile_name@<EDX>, tU32 pMin_size@<EBX>)
|
||||
int PDCheckDriveExists2(char* pThe_path, char* pFile_name, tU32 pMin_size) {
|
||||
struct stat buf;
|
||||
void (*old_critical_isr)();
|
||||
void (*old_critical_isr)(void);
|
||||
int stat_failed;
|
||||
char slasher[4];
|
||||
char the_path[256];
|
||||
|
@ -716,8 +1152,6 @@ int PDDoWeLeadAnAustereExistance(void) {
|
|||
return block < 15000000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int CheckGorePasswordFile(char* pPassword) {
|
||||
tPath_name path;
|
||||
FILE* f;
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
#ifndef SCANCODES_H
|
||||
#define SCANCODES_H
|
||||
|
||||
#define SCANCODE_ESCAPE 0x01
|
||||
#define SCANCODE_1 0x02
|
||||
#define SCANCODE_2 0x03
|
||||
#define SCANCODE_3 0x04
|
||||
#define SCANCODE_4 0x05
|
||||
#define SCANCODE_5 0x06
|
||||
#define SCANCODE_6 0x07
|
||||
#define SCANCODE_7 0x08
|
||||
#define SCANCODE_8 0x09
|
||||
#define SCANCODE_9 0x0A
|
||||
#define SCANCODE_0 0x0B
|
||||
#define SCANCODE_MINUS 0x0C /* - on main keyboard */
|
||||
#define SCANCODE_EQUALS 0x0D
|
||||
#define SCANCODE_BACK 0x0E /* backspace */
|
||||
#define SCANCODE_TAB 0x0F
|
||||
#define SCANCODE_Q 0x10
|
||||
#define SCANCODE_W 0x11
|
||||
#define SCANCODE_E 0x12
|
||||
#define SCANCODE_R 0x13
|
||||
#define SCANCODE_T 0x14
|
||||
#define SCANCODE_Y 0x15
|
||||
#define SCANCODE_U 0x16
|
||||
#define SCANCODE_I 0x17
|
||||
#define SCANCODE_O 0x18
|
||||
#define SCANCODE_P 0x19
|
||||
#define SCANCODE_LBRACKET 0x1A
|
||||
#define SCANCODE_RBRACKET 0x1B
|
||||
#define SCANCODE_RETURN 0x1C /* Enter on main keyboard */
|
||||
#define SCANCODE_LCONTROL 0x1D
|
||||
#define SCANCODE_A 0x1E
|
||||
#define SCANCODE_S 0x1F
|
||||
#define SCANCODE_D 0x20
|
||||
#define SCANCODE_F 0x21
|
||||
#define SCANCODE_G 0x22
|
||||
#define SCANCODE_H 0x23
|
||||
#define SCANCODE_J 0x24
|
||||
#define SCANCODE_K 0x25
|
||||
#define SCANCODE_L 0x26
|
||||
#define SCANCODE_SEMICOLON 0x27
|
||||
#define SCANCODE_APOSTROPHE 0x28
|
||||
#define SCANCODE_GRAVE 0x29
|
||||
#define SCANCODE_LSHIFT 0x2A
|
||||
#define SCANCODE_BACKSLASH 0x2B
|
||||
#define SCANCODE_Z 0x2C
|
||||
#define SCANCODE_X 0x2D
|
||||
#define SCANCODE_C 0x2E
|
||||
#define SCANCODE_V 0x2F
|
||||
#define SCANCODE_B 0x30
|
||||
#define SCANCODE_N 0x31
|
||||
#define SCANCODE_M 0x32
|
||||
#define SCANCODE_COMMA 0x33
|
||||
#define SCANCODE_PERIOD 0x34
|
||||
#define SCANCODE_SLASH 0x35
|
||||
#define SCANCODE_RSHIFT 0x36
|
||||
#define SCANCODE_MULTIPLY 0x37 /* * on numeric keypad */
|
||||
#define SCANCODE_LALT 0x38
|
||||
#define SCANCODE_SPACE 0x39
|
||||
#define SCANCODE_CAPITAL 0x3A
|
||||
#define SCANCODE_F1 0x3B
|
||||
#define SCANCODE_F2 0x3C
|
||||
#define SCANCODE_F3 0x3D
|
||||
#define SCANCODE_F4 0x3E
|
||||
#define SCANCODE_F5 0x3F
|
||||
#define SCANCODE_F6 0x40
|
||||
#define SCANCODE_F7 0x41
|
||||
#define SCANCODE_F8 0x42
|
||||
#define SCANCODE_F9 0x43
|
||||
#define SCANCODE_F10 0x44
|
||||
#define SCANCODE_NUMLOCK 0x45
|
||||
#define SCANCODE_SCROLL 0x46
|
||||
#define SCANCODE_NUMPAD7 0x47
|
||||
#define SCANCODE_NUMPAD8 0x48
|
||||
#define SCANCODE_NUMPAD9 0x49
|
||||
#define SCANCODE_SUBTRACT 0x4A /* - on numeric keypad */
|
||||
#define SCANCODE_NUMPAD4 0x4B
|
||||
#define SCANCODE_NUMPAD5 0x4C
|
||||
#define SCANCODE_NUMPAD6 0x4D
|
||||
#define SCANCODE_ADD 0x4E /* + on numeric keypad */
|
||||
#define SCANCODE_NUMPAD1 0x4F
|
||||
#define SCANCODE_NUMPAD2 0x50
|
||||
#define SCANCODE_NUMPAD3 0x51
|
||||
#define SCANCODE_NUMPAD0 0x52
|
||||
#define SCANCODE_DECIMAL 0x53 /* . on numeric keypad */
|
||||
#define SCANCODE_OEM_102 0x56 /* <> or \| on RT 102-key keyboard (Non-U.S.) */
|
||||
#define SCANCODE_F11 0x57
|
||||
#define SCANCODE_F12 0x58
|
||||
#define SCANCODE_NUMPADENTER 0x9C /* Enter on numeric keypad */
|
||||
#define SCANCODE_RCONTROL 0x9D
|
||||
#define SCANCODE_DIVIDE 0xB5 /* / on numeric keypad */
|
||||
#define SCANCODE_RALT 0xB8
|
||||
#define SCANCODE_PAUSE 0xC5
|
||||
#define SCANCODE_HOME 0xC7
|
||||
#define SCANCODE_UP 0xC8
|
||||
#define SCANCODE_PGUP 0xC9
|
||||
#define SCANCODE_LEFT 0xCB
|
||||
#define SCANCODE_RIGHT 0xCD
|
||||
#define SCANCODE_END 0xCF
|
||||
#define SCANCODE_DOWN 0xD0
|
||||
#define SCANCODE_PGDN 0xD1
|
||||
#define SCANCODE_INSERT 0xD2
|
||||
#define SCANCODE_DELETE 0xD3
|
||||
|
||||
#endif
|
|
@ -1,3 +1,4 @@
|
|||
#if 0
|
||||
#include "ssdx.h"
|
||||
#include "errors.h"
|
||||
#include "harness/hooks.h"
|
||||
|
@ -62,3 +63,5 @@ void SSDXHandleError(int error) {
|
|||
void SSDXSetPaleeteEntries(PALETTEENTRY_* palette, int pFirst_color, int pCount) {
|
||||
DirectDrawDevice_SetPaletteEntries(palette, pFirst_color, pCount);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#if 0
|
||||
#include "brender.h"
|
||||
#include "car.h"
|
||||
#include "dinput.h"
|
||||
|
@ -29,6 +30,34 @@
|
|||
|
||||
#define KEYDOWN(var, key) (var[key] & 0x80)
|
||||
|
||||
// int gExtra_mem;
|
||||
// int gReplay_override;
|
||||
// tGraf_spec gGraf_specs[2] int gASCII_table[128];
|
||||
// tU32 gKeyboard_bits[8];
|
||||
// int gASCII_shift_table[128];
|
||||
// char gNetwork_profile_fname[256];
|
||||
// tS32 gJoystick_min1y;
|
||||
// tS32 gJoystick_min2y;
|
||||
// tS32 gJoystick_min2x;
|
||||
// tS32 gRaw_joystick2y;
|
||||
// tS32 gRaw_joystick2x;
|
||||
// tS32 gRaw_joystick1y;
|
||||
// tS32 gRaw_joystick1x;
|
||||
// tS32 gJoystick_range2y;
|
||||
// tS32 gJoystick_range2x;
|
||||
// tS32 gJoystick_range1y;
|
||||
// tS32 gJoystick_range1x;
|
||||
// int gNo_voodoo;
|
||||
// int gSwitched_resolution;
|
||||
// br_pixelmap* gReal_back_screen;
|
||||
// tS32 gJoystick_min1x;
|
||||
// br_pixelmap* gTemp_screen;
|
||||
|
||||
// tU32 gUpper_loop_limit;
|
||||
// int gReal_back_screen_locked;
|
||||
// tU32 gScan_code[123]; // was tU8 [123][2] in symbol dump
|
||||
|
||||
int gDOSGfx_initialized;
|
||||
int gExtra_mem;
|
||||
int gReplay_override;
|
||||
tGraf_spec gGraf_specs[2] = {
|
||||
|
@ -55,9 +84,9 @@ int gSwitched_resolution;
|
|||
br_pixelmap* gReal_back_screen;
|
||||
tS32 gJoystick_min1x;
|
||||
br_pixelmap* gTemp_screen;
|
||||
int gGfx_initialized; // maybe renamed here
|
||||
tU32 gUpper_loop_limit;
|
||||
int gReal_back_screen_locked;
|
||||
void (*gPrev_keyboard_handler)(void);
|
||||
tU32 gScan_code[123]; // was tU8 [123][2] in symbol dump
|
||||
|
||||
// Added by dethrace. Windows-specific. Original variable names unknown.
|
||||
|
@ -68,6 +97,7 @@ int gWin32_action_replay_buffer_allocated;
|
|||
void* gWin32_action_replay_buffer;
|
||||
int gWin32_action_replay_buffer_size;
|
||||
void* gWin32_hwnd;
|
||||
int gWin32_gfx_initialized;
|
||||
int gWin32_lbutton_down;
|
||||
int gWin32_rbutton_down;
|
||||
PALETTEENTRY_ gWin32_palette[256];
|
||||
|
@ -520,7 +550,7 @@ void PDAllocateScreenAndBack(void) {
|
|||
gScreen = BrPixelmapAllocate(BR_PMT_INDEX_8, gGraf_specs[gGraf_spec_index].total_width, gGraf_specs[gGraf_spec_index].total_height, NULL, BR_PMAF_NORMAL);
|
||||
|
||||
gScreen->origin_x = 0;
|
||||
gGfx_initialized = 1;
|
||||
gWin32_gfx_initialized = 1;
|
||||
gScreen->origin_y = 0;
|
||||
gBack_screen = BrPixelmapMatch(gScreen, BR_PMMATCH_OFFSCREEN);
|
||||
gBack_screen->origin_x = 0;
|
||||
|
@ -1173,3 +1203,5 @@ void Win32BRenderFailureFunc(char* msg) {
|
|||
dr_dprintf("*******************************************************************************");
|
||||
Win32FatalError("BRender error detected:", msg);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,11 +16,15 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int gASCII_table[128];
|
||||
extern tU32 gKeyboard_bits[8];
|
||||
extern int gASCII_shift_table[128];
|
||||
extern int gDOSGfx_initialized;
|
||||
|
||||
// extern int gExtra_mem;
|
||||
// extern int gReplay_override;
|
||||
extern tGraf_spec gGraf_specs[2];
|
||||
extern char gNetwork_profile_fname[256];
|
||||
// extern int gASCII_table[128];
|
||||
// extern tU32 gKeyboard_bits[8];
|
||||
// extern int gASCII_shift_table[128];
|
||||
// extern char gNetwork_profile_fname[256];
|
||||
extern tS32 gJoystick_min1y;
|
||||
extern tS32 gJoystick_min2y;
|
||||
extern tS32 gJoystick_min2x;
|
||||
|
@ -32,22 +36,20 @@ extern tS32 gJoystick_range2y;
|
|||
extern tS32 gJoystick_range2x;
|
||||
extern tS32 gJoystick_range1y;
|
||||
extern tS32 gJoystick_range1x;
|
||||
extern int gNo_voodoo;
|
||||
extern int gSwitched_resolution;
|
||||
extern int gReplay_override;
|
||||
// extern int gNo_voodoo;
|
||||
// extern int gSwitched_resolution;
|
||||
extern br_pixelmap* gReal_back_screen;
|
||||
extern tS32 gJoystick_min1x;
|
||||
extern br_pixelmap* gTemp_screen;
|
||||
extern int gDOSGfx_initialized;
|
||||
extern tU32 gUpper_loop_limit;
|
||||
extern int gExtra_mem;
|
||||
extern int gReal_back_screen_locked;
|
||||
extern void (*gPrev_keyboard_handler)(void);
|
||||
// extern br_pixelmap* gTemp_screen;
|
||||
// extern tU32 gUpper_loop_limit;
|
||||
// extern int gReal_back_screen_locked;
|
||||
// extern void (*gPrev_keyboard_handler)(void);
|
||||
|
||||
// DOS
|
||||
// #ifdef __DOS__
|
||||
// extern tU8 gScan_code[123][2];
|
||||
// Windows
|
||||
extern tU32 gScan_code[123];
|
||||
// #else
|
||||
// extern tU32 gScan_code[123];
|
||||
// #endif
|
||||
|
||||
extern char* _unittest_last_fatal_error;
|
||||
|
||||
|
@ -73,7 +75,7 @@ void PDNonFatalError(char* pThe_str);
|
|||
|
||||
void PDInitialiseSystem(void);
|
||||
|
||||
HARNESS_NORETURN void PDShutdownSystem(void);
|
||||
void PDShutdownSystem(void);
|
||||
|
||||
void PDSaveOriginalPalette(void);
|
||||
|
||||
|
@ -83,9 +85,9 @@ int PDInitScreenVars(int pArgc, char** pArgv);
|
|||
|
||||
void PDInitScreen(void);
|
||||
|
||||
void PDLockRealBackScreen(void);
|
||||
void PDLockRealBackScreen(int lock);
|
||||
|
||||
void PDUnlockRealBackScreen(void);
|
||||
void PDUnlockRealBackScreen(int lock);
|
||||
|
||||
void PDAllocateScreenAndBack(void);
|
||||
|
||||
|
@ -99,7 +101,7 @@ br_pixelmap* PDInterfacePixelmap(void);
|
|||
|
||||
// void ReallyCopyBackScreen(int pRendering_area_only, int pClear_top_and_bottom);
|
||||
|
||||
// void CopyBackScreen(int pRendering_area_only);
|
||||
void CopyBackScreen(int pRendering_area_only);
|
||||
|
||||
void PDScreenBufferSwap(int pRendering_area_only);
|
||||
|
||||
|
|
|
@ -131,6 +131,11 @@ static void Harness_DetectGameMode(void) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 3dfx code paths require at least smoke.pix which is used instead of writing smoke directly to framebuffer
|
||||
if (access("DATA/PIXELMAP/SMOKE.PIX", F_OK) != -1) {
|
||||
harness_game_info.data_dir_has_3dfx_assets = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Harness_Init(int* argc, char* argv[]) {
|
||||
|
@ -144,8 +149,8 @@ void Harness_Init(int* argc, char* argv[]) {
|
|||
harness_game_config.enable_cd_check = 0;
|
||||
// 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;
|
||||
// limit to 60 fps by default
|
||||
harness_game_config.fps = 60;
|
||||
// do not freeze timer
|
||||
harness_game_config.freeze_timer = 0;
|
||||
// default demo time out is 240s
|
||||
|
@ -164,7 +169,6 @@ void Harness_Init(int* argc, char* argv[]) {
|
|||
harness_game_config.no_bind = 0;
|
||||
// Disable verbose logging
|
||||
harness_game_config.verbose = 0;
|
||||
|
||||
// install signal handler by default
|
||||
harness_game_config.install_signalhandler = 1;
|
||||
|
||||
|
@ -193,6 +197,11 @@ void Harness_Init(int* argc, char* argv[]) {
|
|||
Harness_DetectGameMode();
|
||||
}
|
||||
|
||||
if (harness_game_config.opengl_3dfx_mode && !harness_game_info.data_dir_has_3dfx_assets) {
|
||||
printf("Error: data directory does not contain 3dfx assets so opengl mode cannot be used\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (force_null_platform) {
|
||||
Null_Platform_Init(&gHarness_platform);
|
||||
} else {
|
||||
|
@ -267,9 +276,15 @@ int Harness_ProcessCommandLine(int* argc, char* argv[]) {
|
|||
} else if (strcasecmp(argv[i], "--no-bind") == 0) {
|
||||
harness_game_config.no_bind = 1;
|
||||
handled = 1;
|
||||
} else if (strcasecmp(argv[i], "--opengl") == 0) {
|
||||
harness_game_config.opengl_3dfx_mode = 1;
|
||||
handled = 1;
|
||||
} else if (strcasecmp(argv[i], "--no-music") == 0) {
|
||||
harness_game_config.no_music = 1;
|
||||
handled = 1;
|
||||
} else if (strcasecmp(argv[i], "--game-completed") == 0) {
|
||||
harness_game_config.game_completed = 1;
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
|
@ -291,8 +306,7 @@ FILE* Harness_Hook_fopen(const char* pathname, const char* mode) {
|
|||
}
|
||||
|
||||
// Localization
|
||||
int Harness_Hook_isalnum(int c)
|
||||
{
|
||||
int Harness_Hook_isalnum(int c) {
|
||||
if (harness_game_info.localization == eGameLocalization_polish) {
|
||||
// Polish diacritic letters in Windows-1250
|
||||
unsigned char letters[] = { 140, 143, 156, 159, 163, 165, 175, 179, 185, 191, 198, 202, 209, 211, 230, 234, 241, 243 };
|
||||
|
|
|
@ -31,6 +31,7 @@ typedef struct tHarness_game_info {
|
|||
// built-in shifted keyboard look-up table for certain localized Carmageddon releases
|
||||
int* ascii_shift_table;
|
||||
} defines;
|
||||
int data_dir_has_3dfx_assets;
|
||||
} tHarness_game_info;
|
||||
|
||||
typedef struct tHarness_game_config {
|
||||
|
@ -47,6 +48,8 @@ typedef struct tHarness_game_config {
|
|||
int no_bind;
|
||||
int no_music;
|
||||
int verbose;
|
||||
int opengl_3dfx_mode;
|
||||
int game_completed;
|
||||
|
||||
int install_signalhandler;
|
||||
} tHarness_game_config;
|
||||
|
|
|
@ -5,14 +5,17 @@
|
|||
#include "harness/win95_polyfill_defs.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef enum tHarness_window_type {
|
||||
eWindow_type_software = 0,
|
||||
eWindow_type_opengl = 1,
|
||||
} tHarness_window_type;
|
||||
|
||||
// Platform implementation functions
|
||||
typedef struct tHarness_platform {
|
||||
// Render a fullscreen quad using the specified pixel data
|
||||
void (*Renderer_Present)(br_pixelmap* src);
|
||||
// Set the 256 color palette to use (BGRA format)
|
||||
void (*Renderer_SetPalette)(PALETTEENTRY_* palette);
|
||||
// Create a window. Return a handle to the window
|
||||
void* (*CreateWindowAndRenderer)(char* title, int x, int y, int nWidth, int nHeight);
|
||||
// Get mouse button state
|
||||
int (*GetMouseButtons)(int* button_1, int* button_2);
|
||||
// Get mouse position
|
||||
|
@ -20,7 +23,7 @@ typedef struct tHarness_platform {
|
|||
// Close specified window
|
||||
void (*DestroyWindow)(void* window);
|
||||
// Process window messages, return any WM_QUIT message
|
||||
int (*ProcessWindowMessages)(MSG_* msg);
|
||||
void (*ProcessWindowMessages)(MSG_* msg);
|
||||
// Set position of a window
|
||||
int (*SetWindowPos)(void* hWnd, int x, int y, int nWidth, int nHeight);
|
||||
// Show/hide the cursor
|
||||
|
@ -34,6 +37,14 @@ typedef struct tHarness_platform {
|
|||
// Show error message
|
||||
int (*ShowErrorMessage)(void* window, char* text, char* caption);
|
||||
|
||||
// Create a window. Uses an underscore to avoid name collisions with windows.h `CreateWindow` macro
|
||||
void (*CreateWindow_)(char* title, int nWidth, int nHeight, tHarness_window_type window_type);
|
||||
void (*Swap)(br_pixelmap* back_buffer);
|
||||
void (*PaletteChanged)(br_colour entries[256]);
|
||||
// If this platform supports OpenGL
|
||||
void* (*GL_GetProcAddress)(const char* name);
|
||||
void (*GetViewport)(int* x, int* y, float* width_multiplier, float* height_multiplier);
|
||||
|
||||
} tHarness_platform;
|
||||
|
||||
extern tHarness_platform gHarness_platform;
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
// Optional: install a handler to print stack trace during a crash
|
||||
void OS_InstallSignalHandler(char* program_name);
|
||||
|
||||
char* OS_GetFirstFileInDirectory(char* path);
|
||||
|
||||
char* OS_GetNextFileInDirectory(void);
|
||||
|
||||
FILE* OS_fopen(const char* pathname, const char* mode);
|
||||
|
||||
size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen);
|
||||
|
|
|
@ -34,6 +34,7 @@ static char _program_name[1024];
|
|||
|
||||
static void* stack_traces[MAX_STACK_FRAMES];
|
||||
static char name_buf[4096];
|
||||
static DIR* directory_iterator;
|
||||
|
||||
struct dl_iterate_callback_data {
|
||||
int initialized;
|
||||
|
@ -236,6 +237,30 @@ void OS_InstallSignalHandler(char* program_name) {
|
|||
}
|
||||
}
|
||||
|
||||
char* OS_GetFirstFileInDirectory(char* path) {
|
||||
directory_iterator = opendir(path);
|
||||
if (directory_iterator == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return OS_GetNextFileInDirectory();
|
||||
}
|
||||
|
||||
char* OS_GetNextFileInDirectory(void) {
|
||||
struct dirent* entry;
|
||||
|
||||
if (directory_iterator == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
while ((entry = readdir(directory_iterator)) != NULL) {
|
||||
if (entry->d_type == DT_REG) {
|
||||
return entry->d_name;
|
||||
}
|
||||
}
|
||||
closedir(directory_iterator);
|
||||
directory_iterator = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE* OS_fopen(const char* pathname, const char* mode) {
|
||||
FILE* f = fopen(pathname, mode);
|
||||
if (f != NULL) {
|
||||
|
|
|
@ -29,6 +29,7 @@ static char _program_name[1024];
|
|||
#define MAX_STACK_FRAMES 64
|
||||
static void* stack_traces[MAX_STACK_FRAMES];
|
||||
static char name_buf[4096];
|
||||
static DIR* directory_iterator;
|
||||
|
||||
// Resolve symbol name and source location given the path to the executable and an address
|
||||
int addr2line(char const* const program_name, intptr_t slide, void const* const addr) {
|
||||
|
@ -220,6 +221,30 @@ void OS_InstallSignalHandler(char* program_name) {
|
|||
}
|
||||
}
|
||||
|
||||
char* OS_GetFirstFileInDirectory(char* path) {
|
||||
directory_iterator = opendir(path);
|
||||
if (directory_iterator == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return OS_GetNextFileInDirectory();
|
||||
}
|
||||
|
||||
char* OS_GetNextFileInDirectory(void) {
|
||||
struct dirent* entry;
|
||||
|
||||
if (directory_iterator == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
while ((entry = readdir(directory_iterator)) != NULL) {
|
||||
if (entry->d_type == DT_REG) {
|
||||
return entry->d_name;
|
||||
}
|
||||
}
|
||||
closedir(directory_iterator);
|
||||
directory_iterator = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE* OS_fopen(const char* pathname, const char* mode) {
|
||||
FILE* f;
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
// this has to be first
|
||||
#include <windows.h>
|
||||
//
|
||||
|
||||
#include <dbghelp.h>
|
||||
|
||||
#include "harness/config.h"
|
||||
|
@ -9,9 +11,9 @@
|
|||
#include "harness/trace.h"
|
||||
|
||||
#include <errno.h> /* errno, strerror */
|
||||
#include <io.h> /* _access_s, F_OK */
|
||||
#include <io.h> /* _access_s, F_OK */
|
||||
#include <stddef.h>
|
||||
#include <stdio.h> /* errno_t, FILE, fgets, fopen_s, fprintf*/
|
||||
#include <stdio.h> /* errno_t, FILE, fgets, fopen_s, fprintf*/
|
||||
#include <stdlib.h> /* _splitpath */
|
||||
#include <string.h> /* strcpy, strerror, strlen, strrchr */
|
||||
|
||||
|
@ -28,7 +30,10 @@ static char path_addr2line[1024];
|
|||
static char dirname_buf[_MAX_DIR];
|
||||
static char fname_buf[_MAX_FNAME];
|
||||
|
||||
#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) ||defined( __i386) || defined(_M_IX86)
|
||||
HANDLE directory_handle = NULL;
|
||||
char last_found_file[260];
|
||||
|
||||
#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__i386) || defined(_M_IX86)
|
||||
#define DETHRACE_CPU_X86 1
|
||||
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
|
||||
#define DETHRACE_CPU_X64 1
|
||||
|
@ -44,7 +49,7 @@ static char fname_buf[_MAX_FNAME];
|
|||
|
||||
static BOOL print_addr2line_address_location(HANDLE const hProcess, const DWORD64 address) {
|
||||
char addr2line_cmd[1024] = { 0 };
|
||||
const char *program_name = windows_program_name;
|
||||
const char* program_name = windows_program_name;
|
||||
IMAGEHLP_MODULE64 module_info;
|
||||
|
||||
if (path_addr2line[0] == '\0') {
|
||||
|
@ -63,7 +68,7 @@ static BOOL print_addr2line_address_location(HANDLE const hProcess, const DWORD6
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void printf_windows_message(const char *format, ...) {
|
||||
static void printf_windows_message(const char* format, ...) {
|
||||
va_list ap;
|
||||
char win_msg[512];
|
||||
FormatMessageA(
|
||||
|
@ -71,11 +76,11 @@ static void printf_windows_message(const char *format, ...) {
|
|||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
win_msg, sizeof(win_msg)/sizeof(*win_msg),
|
||||
win_msg, sizeof(win_msg) / sizeof(*win_msg),
|
||||
NULL);
|
||||
size_t win_msg_len = strlen(win_msg);
|
||||
while (win_msg[win_msg_len-1] == '\r' || win_msg[win_msg_len-1] == '\n' || win_msg[win_msg_len-1] == ' ') {
|
||||
win_msg[win_msg_len-1] = '\0';
|
||||
while (win_msg[win_msg_len - 1] == '\r' || win_msg[win_msg_len - 1] == '\n' || win_msg[win_msg_len - 1] == ' ') {
|
||||
win_msg[win_msg_len - 1] = '\0';
|
||||
win_msg_len--;
|
||||
}
|
||||
va_start(ap, format);
|
||||
|
@ -109,9 +114,9 @@ static BOOL print_dbghelp_address_location(HANDLE const hProcess, const DWORD64
|
|||
DWORD64 dwDisplacement;
|
||||
DWORD lineColumn = 0;
|
||||
IMAGEHLP_LINE64 line;
|
||||
const char *image_file_name;
|
||||
const char *symbol_name;
|
||||
const char *file_name;
|
||||
const char* image_file_name;
|
||||
const char* symbol_name;
|
||||
const char* file_name;
|
||||
char line_number[16];
|
||||
|
||||
memset(&module_info, 0, sizeof(module_info));
|
||||
|
@ -198,14 +203,14 @@ static void print_stacktrace(CONTEXT* context) {
|
|||
#endif
|
||||
|
||||
while (StackWalk(machine_type,
|
||||
GetCurrentProcess(),
|
||||
GetCurrentThread(),
|
||||
&frame,
|
||||
context,
|
||||
0,
|
||||
SymFunctionTableAccess,
|
||||
SymGetModuleBase,
|
||||
0)) {
|
||||
GetCurrentProcess(),
|
||||
GetCurrentThread(),
|
||||
&frame,
|
||||
context,
|
||||
0,
|
||||
SymFunctionTableAccess,
|
||||
SymGetModuleBase,
|
||||
0)) {
|
||||
|
||||
if (frame.AddrPC.Offset == frame.AddrReturn.Offset) {
|
||||
fprintf(stderr, "PC == Return Address => Possible endless callstack\n");
|
||||
|
@ -306,7 +311,7 @@ static LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS* ExceptionInfo)
|
|||
}
|
||||
|
||||
void OS_InstallSignalHandler(char* program_name) {
|
||||
const char *env_addr2line;
|
||||
const char* env_addr2line;
|
||||
|
||||
path_addr2line[0] = '\0';
|
||||
env_addr2line = getenv("ADDR2LINE");
|
||||
|
@ -322,6 +327,35 @@ void OS_InstallSignalHandler(char* program_name) {
|
|||
SetUnhandledExceptionFilter(windows_exception_handler);
|
||||
}
|
||||
|
||||
char* OS_GetFirstFileInDirectory(char* path) {
|
||||
char with_extension[256];
|
||||
WIN32_FIND_DATA find_data;
|
||||
|
||||
strcpy(with_extension, path);
|
||||
strcat(with_extension, "\\*.???");
|
||||
directory_handle = FindFirstFile(with_extension, &find_data);
|
||||
if (directory_handle == INVALID_HANDLE_VALUE) {
|
||||
return NULL;
|
||||
}
|
||||
strcpy(last_found_file, find_data.cFileName);
|
||||
return last_found_file;
|
||||
}
|
||||
|
||||
// Required: continue directory iteration. If no more files, return NULL
|
||||
char* OS_GetNextFileInDirectory(void) {
|
||||
WIN32_FIND_DATA find_data;
|
||||
if (directory_handle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (FindNextFile(directory_handle, &find_data)) {
|
||||
strcpy(last_found_file, find_data.cFileName);
|
||||
return last_found_file;
|
||||
}
|
||||
FindClose(directory_handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE* OS_fopen(const char* pathname, const char* mode) {
|
||||
FILE* f;
|
||||
errno_t err;
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
// todo: shouldnt depend on sdl...
|
||||
#include <SDL.h>
|
||||
|
||||
static void* null_create_window_and_renderer(char* title, int x, int y, int width, int height) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int null_set_window_pos(void* hWnd, int x, int y, int nWidth, int nHeight) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -18,8 +14,7 @@ static int null_show_error_message(void* window, char* text, char* caption) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int null_get_and_handle_message(MSG_* msg) {
|
||||
return 0;
|
||||
static void null_get_and_handle_message(MSG_* msg) {
|
||||
}
|
||||
|
||||
static void null_get_keyboard_state(unsigned int count, uint8_t* buffer) {
|
||||
|
@ -45,7 +40,6 @@ void Null_Platform_Init(tHarness_platform* platform) {
|
|||
// todo: shouldnt depend on sdl...
|
||||
platform->Sleep = SDL_Delay;
|
||||
platform->GetTicks = SDL_GetTicks;
|
||||
platform->CreateWindowAndRenderer = null_create_window_and_renderer;
|
||||
platform->ShowCursor = null_show_cursor;
|
||||
platform->SetWindowPos = null_set_window_pos;
|
||||
platform->DestroyWindow = null_destroy_window;
|
||||
|
|
|
@ -11,52 +11,46 @@ SDL_Renderer* renderer;
|
|||
SDL_Texture* screen_texture;
|
||||
uint32_t converted_palette[256];
|
||||
br_pixelmap* last_screen_src;
|
||||
|
||||
SDL_GLContext* gl_context;
|
||||
|
||||
int render_width, render_height;
|
||||
|
||||
Uint32 last_frame_time;
|
||||
|
||||
uint8_t directinput_key_state[SDL_NUM_SCANCODES];
|
||||
|
||||
static void* create_window_and_renderer(char* title, int x, int y, int width, int height) {
|
||||
render_width = width;
|
||||
render_height = height;
|
||||
struct {
|
||||
int x, y;
|
||||
float scale_x, scale_y;
|
||||
} viewport;
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||
LOG_PANIC("SDL_INIT_VIDEO error: %s", SDL_GetError());
|
||||
}
|
||||
// Callbacks back into original game code
|
||||
extern void QuitGame(void);
|
||||
extern uint32_t gKeyboard_bits[8];
|
||||
extern br_pixelmap* gBack_screen;
|
||||
|
||||
window = SDL_CreateWindow(title,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
width, height,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
static void calculate_viewport(int window_width, int window_height) {
|
||||
int vp_width, vp_height;
|
||||
float target_aspect_ratio;
|
||||
float aspect_ratio;
|
||||
|
||||
if (window == NULL) {
|
||||
LOG_PANIC("Failed to create window: %s", SDL_GetError());
|
||||
}
|
||||
aspect_ratio = (float)window_width / window_height;
|
||||
target_aspect_ratio = (float)gBack_screen->width / gBack_screen->height;
|
||||
|
||||
if (harness_game_config.start_full_screen) {
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
if (renderer == NULL) {
|
||||
LOG_PANIC("Failed to create renderer: %s", SDL_GetError());
|
||||
}
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_RenderSetLogicalSize(renderer, render_width, render_height);
|
||||
|
||||
screen_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
if (screen_texture == NULL) {
|
||||
SDL_RendererInfo info;
|
||||
SDL_GetRendererInfo(renderer, &info);
|
||||
for (Uint32 i = 0; i < info.num_texture_formats; i++) {
|
||||
LOG_INFO("%s\n", SDL_GetPixelFormatName(info.texture_formats[i]));
|
||||
vp_width = window_width;
|
||||
vp_height = window_height;
|
||||
if (aspect_ratio != target_aspect_ratio) {
|
||||
if (aspect_ratio > target_aspect_ratio) {
|
||||
vp_width = window_height * target_aspect_ratio + .5f;
|
||||
} else {
|
||||
vp_height = window_width / target_aspect_ratio + .5f;
|
||||
}
|
||||
LOG_PANIC("Failed to create screen_texture: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
return window;
|
||||
viewport.x = (window_width - vp_width) / 2;
|
||||
viewport.y = (window_height - vp_height) / 2;
|
||||
viewport.scale_x = (float)vp_width / gBack_screen->width;
|
||||
viewport.scale_y = (float)vp_height / gBack_screen->height;
|
||||
}
|
||||
|
||||
static int set_window_pos(void* hWnd, int x, int y, int nWidth, int nHeight) {
|
||||
|
@ -82,7 +76,7 @@ static int is_only_key_modifier(int modifier_flags, int flag_check) {
|
|||
return (modifier_flags & flag_check) && (modifier_flags & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI)) == (modifier_flags & flag_check);
|
||||
}
|
||||
|
||||
static int get_and_handle_message(MSG_* msg) {
|
||||
static void get_and_handle_message(MSG_* msg) {
|
||||
SDL_Event event;
|
||||
int dinput_key;
|
||||
|
||||
|
@ -97,7 +91,7 @@ static int get_and_handle_message(MSG_* msg) {
|
|||
if (event.key.type == SDL_KEYDOWN) {
|
||||
if ((event.key.keysym.mod & (KMOD_CTRL | KMOD_SHIFT | KMOD_ALT | KMOD_GUI))) {
|
||||
// Ignore keydown of RETURN when used together with some modifier
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
} else if (event.key.type == SDL_KEYUP) {
|
||||
if (is_only_key_modifier(event.key.keysym.mod, KMOD_ALT)) {
|
||||
|
@ -111,28 +105,28 @@ static int get_and_handle_message(MSG_* msg) {
|
|||
dinput_key = sdlScanCodeToDirectInputKeyNum[event.key.keysym.scancode];
|
||||
if (dinput_key == 0) {
|
||||
LOG_WARN("unexpected scan code %s (%d)", SDL_GetScancodeName(event.key.keysym.scancode), event.key.keysym.scancode);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
// DInput expects high bit to be set if key is down
|
||||
// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ee418261(v=vs.85)
|
||||
directinput_key_state[dinput_key] = (event.type == SDL_KEYDOWN ? 0x80 : 0);
|
||||
if (event.type == SDL_KEYDOWN) {
|
||||
gKeyboard_bits[dinput_key >> 5] |= (1 << (dinput_key & 0x1F));
|
||||
} else {
|
||||
gKeyboard_bits[dinput_key >> 5] &= ~(1 << (dinput_key & 0x1F));
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
if (event.window.event == SDL_WINDOWEVENT_CLOSE) {
|
||||
if (SDL_GetWindowID(window) == event.window.windowID) {
|
||||
msg->message = WM_QUIT;
|
||||
return 1;
|
||||
}
|
||||
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||
calculate_viewport(event.window.data1, event.window.data2);
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_QUIT:
|
||||
msg->message = WM_QUIT;
|
||||
return 1;
|
||||
QuitGame();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void get_keyboard_state(unsigned int count, uint8_t* buffer) {
|
||||
|
@ -152,21 +146,24 @@ static int get_mouse_buttons(int* pButton1, int* pButton2) {
|
|||
}
|
||||
|
||||
static int get_mouse_position(int* pX, int* pY) {
|
||||
int window_width, window_height;
|
||||
float lX, lY;
|
||||
|
||||
if (SDL_GetMouseFocus() != window) {
|
||||
return 0;
|
||||
}
|
||||
SDL_GetMouseState(pX, pY);
|
||||
SDL_RenderWindowToLogical(renderer, *pX, *pY, &lX, &lY);
|
||||
SDL_GetWindowSize(window, &window_width, &window_height);
|
||||
|
||||
#if defined(DETHRACE_FIX_BUGS)
|
||||
// In hires mode (640x480), the menus are still rendered at (320x240),
|
||||
// so prescale the cursor coordinates accordingly.
|
||||
lX *= 320;
|
||||
lX /= render_width;
|
||||
lY *= 200;
|
||||
lY /= render_height;
|
||||
#endif
|
||||
SDL_GetMouseState(pX, pY);
|
||||
if (renderer != NULL) {
|
||||
// software renderer
|
||||
SDL_RenderWindowToLogical(renderer, *pX, *pY, &lX, &lY);
|
||||
} else {
|
||||
// hardware renderer
|
||||
// handle case where window is stretched larger than the pixel size
|
||||
lX = *pX * (640.0f / window_width);
|
||||
lY = *pY * (480.0f / window_height);
|
||||
}
|
||||
*pX = (int)lX;
|
||||
*pY = (int)lY;
|
||||
return 0;
|
||||
|
@ -187,50 +184,148 @@ static void limit_fps(void) {
|
|||
last_frame_time = SDL_GetTicks();
|
||||
}
|
||||
|
||||
static void present_screen(br_pixelmap* src) {
|
||||
// fastest way to convert 8 bit indexed to 32 bit
|
||||
uint8_t* src_pixels = src->pixels;
|
||||
uint32_t* dest_pixels;
|
||||
int dest_pitch;
|
||||
|
||||
SDL_LockTexture(screen_texture, NULL, (void**)&dest_pixels, &dest_pitch);
|
||||
for (int i = 0; i < src->height * src->width; i++) {
|
||||
*dest_pixels = converted_palette[*src_pixels];
|
||||
dest_pixels++;
|
||||
src_pixels++;
|
||||
}
|
||||
SDL_UnlockTexture(screen_texture);
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
last_screen_src = src;
|
||||
|
||||
if (harness_game_config.fps != 0) {
|
||||
limit_fps();
|
||||
}
|
||||
}
|
||||
|
||||
static void set_palette(PALETTEENTRY_* pal) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
converted_palette[i] = (0xff << 24 | pal[i].peRed << 16 | pal[i].peGreen << 8 | pal[i].peBlue);
|
||||
}
|
||||
if (last_screen_src != NULL) {
|
||||
present_screen(last_screen_src);
|
||||
}
|
||||
}
|
||||
|
||||
int show_error_message(void* window, char* text, char* caption) {
|
||||
fprintf(stderr, "%s", text);
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, caption, text, window);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void create_window(char* title, int width, int height, tHarness_window_type window_type) {
|
||||
int window_width, window_height;
|
||||
|
||||
render_width = width;
|
||||
render_height = height;
|
||||
|
||||
window_width = width;
|
||||
window_height = height;
|
||||
|
||||
// special case lores and make a bigger window
|
||||
if (width == 320 && height == 200) {
|
||||
window_width = 640;
|
||||
window_height = 480;
|
||||
}
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||
LOG_PANIC("SDL_INIT_VIDEO error: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
if (window_type == eWindow_type_opengl) {
|
||||
|
||||
window = SDL_CreateWindow(title,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
window_width, window_height,
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||
|
||||
if (window == NULL) {
|
||||
LOG_PANIC("Failed to create window: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
gl_context = SDL_GL_CreateContext(window);
|
||||
|
||||
if (gl_context == NULL) {
|
||||
LOG_WARN("Failed to create OpenGL core profile: %s. Trying OpenGLES...", SDL_GetError());
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
gl_context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
if (gl_context == NULL) {
|
||||
LOG_PANIC("Failed to create OpenGL context: %s", SDL_GetError());
|
||||
}
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
|
||||
} else {
|
||||
window = SDL_CreateWindow(title,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
window_width, window_height,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
if (window == NULL) {
|
||||
LOG_PANIC("Failed to create window: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
if (renderer == NULL) {
|
||||
LOG_PANIC("Failed to create renderer: %s", SDL_GetError());
|
||||
}
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
||||
SDL_RenderSetLogicalSize(renderer, render_width, render_height);
|
||||
|
||||
screen_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
if (screen_texture == NULL) {
|
||||
SDL_RendererInfo info;
|
||||
SDL_GetRendererInfo(renderer, &info);
|
||||
for (Uint32 i = 0; i < info.num_texture_formats; i++) {
|
||||
LOG_INFO("%s\n", SDL_GetPixelFormatName(info.texture_formats[i]));
|
||||
}
|
||||
LOG_PANIC("Failed to create screen_texture: %s", SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
viewport.scale_x = 1;
|
||||
viewport.scale_y = 1;
|
||||
|
||||
if (harness_game_config.start_full_screen) {
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
}
|
||||
|
||||
static void swap(br_pixelmap* back_buffer) {
|
||||
uint8_t* src_pixels = back_buffer->pixels;
|
||||
uint32_t* dest_pixels;
|
||||
int dest_pitch;
|
||||
|
||||
get_and_handle_message(NULL);
|
||||
|
||||
if (gl_context != NULL) {
|
||||
SDL_GL_SwapWindow(window);
|
||||
} else {
|
||||
SDL_LockTexture(screen_texture, NULL, (void**)&dest_pixels, &dest_pitch);
|
||||
for (int i = 0; i < back_buffer->height * back_buffer->width; i++) {
|
||||
*dest_pixels = converted_palette[*src_pixels];
|
||||
dest_pixels++;
|
||||
src_pixels++;
|
||||
}
|
||||
SDL_UnlockTexture(screen_texture);
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
last_screen_src = back_buffer;
|
||||
}
|
||||
|
||||
if (harness_game_config.fps != 0) {
|
||||
limit_fps();
|
||||
}
|
||||
}
|
||||
|
||||
static void palette_changed(br_colour entries[256]) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
converted_palette[i] = (0xff << 24 | BR_RED(entries[i]) << 16 | BR_GRN(entries[i]) << 8 | BR_BLU(entries[i]));
|
||||
}
|
||||
if (last_screen_src != NULL) {
|
||||
swap(last_screen_src);
|
||||
}
|
||||
}
|
||||
|
||||
static void get_viewport(int* x, int* y, float* width_multipler, float* height_multiplier) {
|
||||
*x = viewport.x;
|
||||
*y = viewport.y;
|
||||
*width_multipler = viewport.scale_x;
|
||||
*height_multiplier = viewport.scale_y;
|
||||
}
|
||||
|
||||
void Harness_Platform_Init(tHarness_platform* platform) {
|
||||
platform->ProcessWindowMessages = get_and_handle_message;
|
||||
platform->Sleep = SDL_Delay;
|
||||
platform->GetTicks = SDL_GetTicks;
|
||||
platform->CreateWindowAndRenderer = create_window_and_renderer;
|
||||
platform->ShowCursor = SDL_ShowCursor;
|
||||
platform->SetWindowPos = set_window_pos;
|
||||
platform->DestroyWindow = destroy_window;
|
||||
|
@ -238,6 +333,10 @@ void Harness_Platform_Init(tHarness_platform* platform) {
|
|||
platform->GetMousePosition = get_mouse_position;
|
||||
platform->GetMouseButtons = get_mouse_buttons;
|
||||
platform->ShowErrorMessage = show_error_message;
|
||||
platform->Renderer_SetPalette = set_palette;
|
||||
platform->Renderer_Present = present_screen;
|
||||
|
||||
platform->CreateWindow_ = create_window;
|
||||
platform->Swap = swap;
|
||||
platform->PaletteChanged = palette_changed;
|
||||
platform->GL_GetProcAddress = SDL_GL_GetProcAddress;
|
||||
platform->GetViewport = get_viewport;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
#if 0
|
||||
#include "harness/hooks.h"
|
||||
#include "harness/os.h"
|
||||
#include "harness/win95_polyfill.h"
|
||||
|
@ -172,7 +172,8 @@ int FindClose_(HANDLE_ hFindFile) {
|
|||
}
|
||||
|
||||
void* CreateWindowExA_(uint32_t dwExStyle, char* lpClassName, char* lpWindowName, uint32_t dwStyle, int X, int Y, int nWidth, int nHeight, void* hWndParent, void* hMenu, void* hInstance, void* lpParam) {
|
||||
return gHarness_platform.CreateWindowAndRenderer(lpWindowName, X, Y, nWidth, nHeight);
|
||||
gHarness_platform.CreateWindow_(lpWindowName, nWidth, nHeight, eWindow_type_software);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int SetWindowPos_(void* hWnd, void* hWndInsertAfter, int X, int Y, int cx, int cy, unsigned int uFlags) {
|
||||
|
@ -249,3 +250,5 @@ int _CrtDbgReport_(int reportType, const char* filename, int linenumber, const c
|
|||
printf("_CrtDbgReport: (TODO)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
|
Loading…
Reference in New Issue