From 80f5fceff92e908d47a30567b0a34c26e8ce030c Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Fri, 25 Mar 2022 00:36:11 +0100 Subject: [PATCH] Start To Mouse (#109) * Detour fopen to an OS-specific implementation of fopen * Set opponent count to 5 * Implement switching opponents in 'View opponent' sub-panel --- src/BRSRC13/CORE/FW/file.c | 18 -- src/BRSRC13/CORE/STD/brstdfile.c | 5 +- src/DETHRACE/common/depth.c | 8 +- src/DETHRACE/common/flicplay.c | 48 ++-- src/DETHRACE/common/graphics.c | 374 +++++++++++++++++++++---- src/DETHRACE/common/intrface.c | 38 +-- src/DETHRACE/common/loading.c | 25 +- src/DETHRACE/common/mainmenu.c | 28 +- src/DETHRACE/common/options.c | 10 +- src/DETHRACE/common/racestrt.c | 92 +++++- src/DETHRACE/common/utility.c | 1 - src/DETHRACE/constants.h | 2 +- src/DETHRACE/pc-dos/dossys.c | 7 +- src/harness/harness.c | 19 +- src/harness/include/harness/hooks.h | 11 +- src/harness/include/harness/os.h | 3 + src/harness/io_platforms/io_platform.h | 4 +- src/harness/io_platforms/sdl_gl.c | 21 +- src/harness/os/linux.c | 26 +- src/harness/os/macos.c | 4 + src/harness/os/windows.c | 15 +- 21 files changed, 585 insertions(+), 174 deletions(-) diff --git a/src/BRSRC13/CORE/FW/file.c b/src/BRSRC13/CORE/FW/file.c index e9820ad7..6718dfc3 100644 --- a/src/BRSRC13/CORE/FW/file.c +++ b/src/BRSRC13/CORE/FW/file.c @@ -43,24 +43,6 @@ void* BrFileOpenRead(char* name, br_size_t n_magics, br_mode_test_cbfn* mode_tes raw_file = fw.fsys->open_read(name, n_magics, mode_test, &bin_mode); } -#ifdef BRENDER_FIX_BUGS - // Try all-uppercase filename for case sensitive file systems - if (raw_file == NULL) { - for (s = name + strlen(name); s != name;) { - s--; - if (*s == '\\' || *s == '/') { - break; - } - *s = toupper(*s); - } - if (mode_result != NULL) { - raw_file = fw.fsys->open_read(name, n_magics, mode_test, mode_result); - } else { - raw_file = fw.fsys->open_read(name, n_magics, mode_test, &bin_mode); - } - } -#endif - if (raw_file == NULL) { return NULL; } diff --git a/src/BRSRC13/CORE/STD/brstdfile.c b/src/BRSRC13/CORE/STD/brstdfile.c index 5c9d23a9..f7e8ee17 100644 --- a/src/BRSRC13/CORE/STD/brstdfile.c +++ b/src/BRSRC13/CORE/STD/brstdfile.c @@ -1,6 +1,7 @@ #include "brstdfile.h" #include "CORE/FW/diag.h" +#include "harness/hooks.h" #include "harness/trace.h" #include #include @@ -73,9 +74,9 @@ void* BrStdioOpenWrite(char* name, int mode) { FILE* fh; if (mode == BR_FS_MODE_TEXT) { - fh = fopen(name, "w"); + fh = Harness_Hook_fopen(name, "w"); } else { - fh = fopen(name, "wb"); + fh = Harness_Hook_fopen(name, "wb"); } return fh; diff --git a/src/DETHRACE/common/depth.c b/src/DETHRACE/common/depth.c index 1240b68e..0a065ae1 100644 --- a/src/DETHRACE/common/depth.c +++ b/src/DETHRACE/common/depth.c @@ -276,8 +276,8 @@ void DoDepthByShadeTable(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer if (depth_shift_amount <= 0) { if (depth_shift_amount >= 0) { - for (y = 0; pRender_buffer->height > y; ++y) { - for (x = 0; pRender_buffer->width > x; ++x) { + for (y = 0; y < pRender_buffer->height; ++y) { + for (x = 0; x < pRender_buffer->width; ++x) { if (*depth_ptr != 0xFFFF) { depth_value = *depth_ptr - too_near; if (depth_value < -(int16_t)too_near) { @@ -477,8 +477,8 @@ void DepthEffect(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_act void DepthEffectSky(br_pixelmap* pRender_buffer, br_pixelmap* pDepth_buffer, br_actor* pCamera, br_matrix34* pCamera_to_world) { LOG_TRACE("(%p, %p, %p, %p)", pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world); - if (gProgram_state.current_depth_effect.sky_texture - && (!gLast_camera_special_volume || gLast_camera_special_volume->sky_col < 0)) { + if (gProgram_state.current_depth_effect.sky_texture != NULL + && (gLast_camera_special_volume == NULL || gLast_camera_special_volume->sky_col < 0)) { DoHorizon(pRender_buffer, pDepth_buffer, pCamera, pCamera_to_world); } } diff --git a/src/DETHRACE/common/flicplay.c b/src/DETHRACE/common/flicplay.c index 3b9fcf02..81586bcd 100644 --- a/src/DETHRACE/common/flicplay.c +++ b/src/DETHRACE/common/flicplay.c @@ -673,7 +673,7 @@ int StartFlic(char* pFile_name, int pIndex, tFlic_descriptor_ptr pFlic_info, tU3 PathCat(the_path, the_path, pFile_name); pFlic_info->f = DRfopen(the_path, "rb"); - if (!pFlic_info->f) { + if (pFlic_info->f == NULL) { FatalError(13, pFile_name); } total_size = GetFileLength(pFlic_info->f); @@ -1408,7 +1408,7 @@ int LoadFlicData(char* pName, tU8** pData, tU32* pData_length) { PathCat(the_path, gApplication_path, "ANIM"); PathCat(the_path, the_path, pName); f = DRfopen(the_path, "rb"); - if (!f) { + if (f == NULL) { return 0; } *pData_length = GetFileLength(f); @@ -1490,12 +1490,9 @@ void PreloadBunchOfFlics(int pBunch_index) { // IDA: void __usercall UnlockBunchOfFlics(int pBunch_index@) void UnlockBunchOfFlics(int pBunch_index) { int i; + for (i = 0; i < gFlic_bunch[pBunch_index].count; i++) { - if (gFlic_bunch[pBunch_index].indexes[i] >= 0) { - if (gMain_flic_list[gFlic_bunch[pBunch_index].indexes[i]].data_ptr) { - MAMSUnlock((void**)&gMain_flic_list[gFlic_bunch[pBunch_index].indexes[i]].data_ptr); - } - } + UnlockFlic(gFlic_bunch[pBunch_index].indexes[i]); } } @@ -1503,7 +1500,10 @@ void UnlockBunchOfFlics(int pBunch_index) { void FlushAllFlics(int pBunch_index) { int i; LOG_TRACE("(%d)", pBunch_index); - NOT_IMPLEMENTED(); + + for (i = 0; i < COUNT_OF(gMain_flic_list); i++) { + FreeFlic(i); + } } // IDA: void __cdecl InitFlicQueue() @@ -1517,7 +1517,7 @@ int FlicQueueFinished() { LOG_TRACE("()"); the_flic = gFirst_flic; - while (the_flic) { + while (the_flic != NULL) { if (the_flic->must_finish) { return 0; } @@ -1540,7 +1540,7 @@ void ProcessFlicQueue(tU32 pInterval) { the_flic = gFirst_flic; last_flic = NULL; new_time = PDGetTotalTime(); - while (the_flic) { + while (the_flic != NULL) { if (new_time - the_flic->last_frame < the_flic->frame_period) { finished_playing = 0; } else { @@ -1549,7 +1549,7 @@ void ProcessFlicQueue(tU32 pInterval) { } if (finished_playing) { EndFlic(the_flic); - if (last_flic) { + if (last_flic != NULL) { last_flic->next = the_flic->next; } else { gFirst_flic = the_flic->next; @@ -1583,7 +1583,7 @@ void FlushFlicQueue() { PDScreenBufferSwap(0); } the_flic = gFirst_flic; - while (the_flic) { + while (the_flic != NULL) { old_flic = the_flic; EndFlic(the_flic); the_flic = the_flic->next; @@ -1601,7 +1601,7 @@ void AddToFlicQueue(int pIndex, int pX, int pY, int pMust_finish) { LOG_TRACE("(%d, %d, %d, %d)", pIndex, pX, pY, pMust_finish); the_flic = gFirst_flic; - while (the_flic) { + while (the_flic != NULL) { if (pX == the_flic->x_offset && pY == the_flic->y_offset) { doomed_flic = the_flic; break; @@ -1610,9 +1610,9 @@ void AddToFlicQueue(int pIndex, int pX, int pY, int pMust_finish) { the_flic = the_flic->next; } - if (doomed_flic) { + if (doomed_flic != NULL) { EndFlic(doomed_flic); - if (last_flic) { + if (last_flic != NULL) { last_flic->next = doomed_flic->next; } else { gFirst_flic = doomed_flic->next; @@ -1624,8 +1624,8 @@ void AddToFlicQueue(int pIndex, int pX, int pY, int pMust_finish) { new_flic = BrMemAllocate(sizeof(tFlic_descriptor), kMem_queued_flic); new_flic->next = NULL; the_flic = gFirst_flic; - if (gFirst_flic) { - while (the_flic->next) { + if (gFirst_flic != NULL) { + while (the_flic->next != NULL) { the_flic = the_flic->next; } the_flic->next = new_flic; @@ -1633,7 +1633,7 @@ void AddToFlicQueue(int pIndex, int pX, int pY, int pMust_finish) { gFirst_flic = new_flic; } new_flic->last_frame = 0; - new_flic->data_start = 0; + new_flic->data_start = NULL; new_flic->the_index = pIndex; new_flic->must_finish = pMust_finish; @@ -1657,7 +1657,7 @@ void InitialiseFlicPanel(int pIndex, int pLeft, int pTop, int pWidth, int pHeigh gPanel_flic[pIndex].data = NULL; gPanel_flic_left[pIndex] = pLeft; gPanel_flic_top[pIndex] = pTop; - the_pixels = BrMemAllocate(pHeight * ((pWidth + 3) & 0xFC), kFlic_panel_pixels); + the_pixels = BrMemAllocate(pHeight * ((pWidth + 3) & ~3), kFlic_panel_pixels); if (gScreen->row_bytes < 0) { BrFatal( "..\\..\\source\\common\\flicplay.c", @@ -1695,10 +1695,10 @@ void ServicePanelFlics(int pCopy_to_buffer) { DontLetFlicFuckWithPalettes(); TurnFlicTransparencyOn(); - for (i = 0; i < 2; i++) { + for (i = 0; i < COUNT_OF(gPanel_flic); i++) { old_last_time[i] = gLast_panel_frame_time[i]; - if (gPanel_buffer[i] && gPanel_flic[i].data) { - if (old_last_time[i]) { + if (gPanel_buffer[i] != NULL && gPanel_flic[i].data != NULL) { + if (old_last_time[i] != 0) { time_diff = the_time - old_last_time[i]; iteration_count = time_diff / gPanel_flic[i].frame_period; } else { @@ -1734,8 +1734,8 @@ void ServicePanelFlics(int pCopy_to_buffer) { } } } - gTransparency_on = 0; - gPalette_fuck_prevention = 0; + TurnFlicTransparencyOff(); + LetFlicFuckWithPalettes(); } // IDA: void __usercall ChangePanelFlic(int pIndex@, tU8 *pData@, tU32 pData_length@) diff --git a/src/DETHRACE/common/graphics.c b/src/DETHRACE/common/graphics.c index 7bd76cff..8782cc5d 100644 --- a/src/DETHRACE/common/graphics.c +++ b/src/DETHRACE/common/graphics.c @@ -12,9 +12,10 @@ #include "globvars.h" #include "globvrpb.h" #include "grafdata.h" -#include "harness/hooks.h" +#include "harness/os.h" #include "harness/trace.h" #include "init.h" +#include "input.h" #include "loading.h" #include "netgame.h" #include "network.h" @@ -38,15 +39,20 @@ int gPalette_munged; int gColourValues[1]; int gNext_transient; -int gCursor_x_offsets[8]; -int gCursor_y_offsets[8]; -int gCursor_gib_x_offsets[8]; -int gCursor_gib_y_offsets[8]; -int gCursor_giblet_sequence0[7]; -int gCursor_giblet_sequence1[5]; -int gCursor_giblet_sequence2[5]; -int gCursor_giblet_sequence3[5]; -int* gCursor_giblet_sequences[4]; +int gCursor_x_offsets[8] = { 6, 8, 16, 36, 6, 8, 16, 36, }; +int gCursor_y_offsets[8] = { 26, 19, 12, 5, 26, 19, 12, 5, }; +int gCursor_gib_x_offsets[8] = { 82, 72, 66, 36, 82, 72, 66, 36, }; +int gCursor_gib_y_offsets[8] = { 74, 86, 93, 106, 74, 86, 93, 106, }; +int gCursor_giblet_sequence0[7] = { 6, 0, 1, 2, 3, 4, 5, }; +int gCursor_giblet_sequence1[5] = { 4, 6, 7, 8, 9, }; +int gCursor_giblet_sequence2[5] = { 4, 10, 11, 12, 13, }; +int gCursor_giblet_sequence3[5] = { 4, 14, 15, 16, 17, }; +int* gCursor_giblet_sequences[4] = { + gCursor_giblet_sequence0, + gCursor_giblet_sequence1, + gCursor_giblet_sequence2, + gCursor_giblet_sequence3, +}; char* gFont_names[21] = { "TYPEABLE", "ORANGHED", @@ -1242,7 +1248,7 @@ void ProcessShadow(tCar_spec* pCar, br_actor* pWorld, tTrack_spec* pTrack_spec, material = gShadow_model->faces[i].material; if (material) { if (material->colour_map && (material->flags & BR_MATF_LIGHT) != 0) { - material->flags &= 0xFFFFFFF8; + material->flags &= ~(BR_MATF_LIGHT |BR_MATF_PRELIT | BR_MATF_SMOOTH); BrMaterialUpdate(material, BR_MATU_RENDERING); } } @@ -1950,43 +1956,57 @@ void DRPixelmapRectangleMaskedCopy(br_pixelmap* pDest, br_int_16 pDest_x, br_int dest_ptr -= pDest_y * pDest->row_bytes; pDest_y = 0; } - if (pDest->height > pDest_y) { - if (pDest_y + pHeight > pDest->height) { - pHeight = pDest->height - pDest_y; + if (pDest_y >= pDest->height) { + return; + } + if (pDest_y + pHeight > pDest->height) { + pHeight = pDest->height - pDest_y; + } + if (pDest_x < 0) { + pWidth += pDest_x; + if (pWidth <= 0) { + return; } - if (pDest_x < 0) { - pWidth += pDest_x; - if (pWidth <= 0) { - return; - } - source_ptr -= pDest_x; - dest_ptr -= pDest_x; - source_row_wrap -= pDest_x; - dest_row_wrap -= pDest_x; - pDest_x = 0; - } - if (pDest->width > pDest_x) { - if (pDest_x + pWidth > pDest->width) { - pWidth = pDest->width - pDest_x; - source_row_wrap += pDest_x + pWidth - pDest->width; - dest_row_wrap += pDest_x + pWidth - pDest->width; - } - if (gCurrent_conversion_table) { - TELL_ME_IF_WE_PASS_THIS_WAY(); - } else { - for (y_count = 0; y_count < pHeight; y_count++) { - for (x_count = 0; x_count < pWidth; x_count++) { - the_byte = *source_ptr; - if (the_byte) { - *dest_ptr = the_byte; - } - source_ptr++; - dest_ptr++; - } - source_ptr += source_row_wrap; - dest_ptr += dest_row_wrap; + source_ptr -= pDest_x; + dest_ptr -= pDest_x; + source_row_wrap -= pDest_x; + dest_row_wrap -= pDest_x; + pDest_x = 0; + } + if (pDest_x >= pDest->width) { + return; + } + if (pDest_x + pWidth > pDest->width) { + source_row_wrap += pDest_x + pWidth - pDest->width; + dest_row_wrap += pDest_x + pWidth - pDest->width; + pWidth = pDest->width - pDest_x; + } + if (gCurrent_conversion_table != NULL) { + conv_table = gCurrent_conversion_table->pixels; + for (y_count = 0; y_count < pHeight; y_count++) { + for (x_count = 0; x_count < pWidth; x_count++) { + the_byte = *source_ptr; + if (the_byte != 0) { + *dest_ptr = conv_table[the_byte]; } + source_ptr++; + dest_ptr++; } + source_ptr += source_row_wrap; + dest_ptr += dest_row_wrap; + } + } else { + for (y_count = 0; y_count < pHeight; y_count++) { + for (x_count = 0; x_count < pWidth; x_count++) { + the_byte = *source_ptr; + if (the_byte != 0) { + *dest_ptr = the_byte; + } + source_ptr++; + dest_ptr++; + } + source_ptr += source_row_wrap; + dest_ptr += dest_row_wrap; } } } @@ -2166,7 +2186,8 @@ void DRPixelmapRectangleVScaledCopy(br_pixelmap* pDest, br_int_16 pDest_x, br_in void InitTransientBitmaps() { int i; LOG_TRACE("()"); - for (i = 0; i < 50; i++) { + + for (i = 0; i < COUNT_OF(gTransient_bitmaps); i++) { gTransient_bitmaps[i].pixmap = NULL; gTransient_bitmaps[i].in_use = 0; } @@ -2176,40 +2197,100 @@ void InitTransientBitmaps() { int AllocateTransientBitmap(int pWidth, int pHeight, int pUser_data) { int bm_index; LOG_TRACE("(%d, %d, %d)", pWidth, pHeight, pUser_data); - NOT_IMPLEMENTED(); + + for (bm_index = 0; bm_index < COUNT_OF(gTransient_bitmaps); bm_index++) { + if (gTransient_bitmaps[bm_index].pixmap == NULL) { + gTransient_bitmaps[bm_index].pixmap = DRPixelmapAllocate(BR_PMT_INDEX_8, pWidth + 8, pHeight, NULL, 0); + gTransient_bitmaps[bm_index].in_use = 0; + gTransient_bitmaps[bm_index].user_data = pUser_data; + return bm_index; + } + } + FatalError(18); } // IDA: void __usercall DeallocateTransientBitmap(int pIndex@) void DeallocateTransientBitmap(int pIndex) { LOG_TRACE("(%d)", pIndex); - NOT_IMPLEMENTED(); + + if (gTransient_bitmaps[pIndex].pixmap != NULL) { + BrPixelmapFree(gTransient_bitmaps[pIndex].pixmap); + gTransient_bitmaps[pIndex].pixmap = NULL; + gTransient_bitmaps[pIndex].in_use = 0; + } } // IDA: void __cdecl DeallocateAllTransientBitmaps() void DeallocateAllTransientBitmaps() { int i; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + for (i = 0; i < COUNT_OF(gTransient_bitmaps); i++) { + DeallocateTransientBitmap(i); + } } // IDA: void __usercall RemoveTransientBitmaps(int pGraphically_remove_them@) void RemoveTransientBitmaps(int pGraphically_remove_them) { int i; int order_number; - STUB_ONCE(); + + if (pGraphically_remove_them) { + for (order_number = gNext_transient - 1; order_number >= 0; order_number--) { + for (i = 0; i < COUNT_OF(gTransient_bitmaps); i++) { + if (gTransient_bitmaps[i].pixmap != NULL && gTransient_bitmaps[i].order_number == order_number) { + if (gTransient_bitmaps[i].in_use) { + BrPixelmapRectangleCopy(gBack_screen, + gTransient_bitmaps[i].x_coord, + gTransient_bitmaps[i].y_coord, + gTransient_bitmaps[i].pixmap, + 0, + 0, + gTransient_bitmaps[i].pixmap->width, + gTransient_bitmaps[i].pixmap->height); + } + break; + } + } + } + } + gNext_transient = 0; } // IDA: void __usercall SaveTransient(int pIndex@, int pX_coord@, int pY_coord@) void SaveTransient(int pIndex, int pX_coord, int pY_coord) { LOG_TRACE("(%d, %d, %d)", pIndex, pX_coord, pY_coord); - NOT_IMPLEMENTED(); + + gTransient_bitmaps[pIndex].x_coord = pX_coord & ~3; + gTransient_bitmaps[pIndex].y_coord = pY_coord; + gTransient_bitmaps[pIndex].in_use = 1; + gTransient_bitmaps[pIndex].order_number = gNext_transient; + gNext_transient++; + BrPixelmapRectangleCopy(gTransient_bitmaps[pIndex].pixmap, + 0, + 0, + gBack_screen, + gTransient_bitmaps[pIndex].x_coord, + gTransient_bitmaps[pIndex].y_coord, + gTransient_bitmaps[pIndex].pixmap->width, + gTransient_bitmaps[pIndex].pixmap->height); } // IDA: void __usercall DrawCursorGiblet(tCursor_giblet *pGib@) void DrawCursorGiblet(tCursor_giblet* pGib) { br_pixelmap* the_image; LOG_TRACE("(%p)", pGib); - NOT_IMPLEMENTED(); + + SaveTransient(pGib->transient_index, pGib->x_coord, pGib->y_coord); + the_image = gCursor_giblet_images[gCursor_giblet_sequences[pGib->sequence_index][pGib->current_giblet]]; + DRPixelmapRectangleMaskedCopy(gBack_screen, + pGib->x_coord, + pGib->y_coord, + the_image, + 0, + 0, + the_image->width, + the_image->height); } // IDA: void __usercall ProcessCursorGiblets(int pPeriod@) @@ -2219,7 +2300,57 @@ void ProcessCursorGiblets(int pPeriod) { tU32 time_now; tCursor_giblet* gib; LOG_TRACE("(%d)", pPeriod); - NOT_IMPLEMENTED(); + + time_now = PDGetTotalTime(); + for (i = 0; i < COUNT_OF(gCursor_giblets); i++) { + gib = &gCursor_giblets[i]; + kill_the_giblet = 0; + if (gib->current_giblet == -1) { + continue; + } + if (!gib->landed && gib->e_t_a <= time_now) { + gib->landed = 1; + gib->the_speed = 0.f; + } + if (gib->landed) { + gib->giblet_change_period -= pPeriod / 2; + if (gib->giblet_change_period < 50) { + gib->giblet_change_period = 50; + } + if (gib->giblet_change_period <= time_now - gib->last_giblet_change) { + if (gCursor_giblet_sequences[gib->sequence_index][0] == gib->current_giblet) { + gib->current_giblet = 1; + } else { + gib->current_giblet++; + } + gib->last_giblet_change = time_now; + } + gib->y_coord += pPeriod * gib->the_speed / 1000.f; + if (gib->y_coord <= gGraf_data[gGraf_data_index].height) { + if (gib->the_speed < gGraf_specs[gGraf_spec_index].total_height * 160 / 480) { + gib->the_speed += pPeriod * gGraf_specs[gGraf_spec_index].total_height * 60 / 480 / 1000.f; + } + } else { + kill_the_giblet = 1; + } + } else { + if (gib->y_speed < gGraf_specs[gGraf_spec_index].total_height * 160 / 480) { + gib->y_speed += pPeriod * gGraf_specs[gGraf_spec_index].total_height * 60 / 480 / 1000.f * 2.f; + } + gib->x_coord += pPeriod * gib->x_speed / 1000.f; + gib->y_coord += pPeriod * gib->y_speed / 1000.f; + if (gib->x_coord < 0.f || gib->x_coord >= gGraf_data[gGraf_spec_index].width || gib->y_coord < 0.f || gib->y_coord >= gGraf_data[gGraf_spec_index].height) { + kill_the_giblet = 1; + } + } + if (kill_the_giblet) { + gib->current_giblet = -1; + DeallocateTransientBitmap(gib->transient_index); + } else { + DrawCursorGiblet(gib); + } + + } } // IDA: int __usercall NewCursorGiblet@(int pX_coord@, int pY_coord@, float pX_speed, float pY_speed, tU32 pDrop_time) @@ -2229,11 +2360,34 @@ int NewCursorGiblet(int pX_coord, int pY_coord, float pX_speed, float pY_speed, int the_height; int sequence_number; LOG_TRACE("(%d, %d, %f, %f, %d)", pX_coord, pY_coord, pX_speed, pY_speed, pDrop_time); - NOT_IMPLEMENTED(); + + sequence_number = IRandomBetween(0, COUNT_OF(gCursor_giblet_sequences) - 1); + if (pX_coord >= 0 && pX_coord < gGraf_data[gGraf_data_index].width && pY_coord >= 0 && pY_coord < gGraf_data[gGraf_data_index].height) { + for (i = 0; i < COUNT_OF(gCursor_giblets); i++) { + if (gCursor_giblets[i].current_giblet == -1) { + the_width = gCursor_giblet_images[gCursor_giblet_sequences[sequence_number][1]]->width; + the_height = gCursor_giblet_images[gCursor_giblet_sequences[sequence_number][1]]->height; + gCursor_giblets[i].transient_index = AllocateTransientBitmap(the_width, the_height, 1); + gCursor_giblets[i].current_giblet = 1; + gCursor_giblets[i].sequence_index = sequence_number; + gCursor_giblets[i].landed = 0; + gCursor_giblets[i].x_coord = sequence_number * gGraf_specs[gGraf_spec_index].total_width / 640 - the_width / 2 + pX_coord; + gCursor_giblets[i].y_coord = FRandomPosNeg(6.f) * gGraf_specs[gGraf_spec_index].total_height / 480 - the_height / 2 + pY_coord; + gCursor_giblets[i].x_speed = pX_speed; + gCursor_giblets[i].y_speed = pY_speed; + gCursor_giblets[i].last_giblet_change = 0; + gCursor_giblets[i].giblet_change_period = 1000; + gCursor_giblets[i].e_t_a = PDGetTotalTime() + pDrop_time; + return i; + } + } + } + return -1; } // IDA: int __cdecl DoMouseCursor() int DoMouseCursor() { + int x_coord; // Added by DethRace int y_coord; int mouse_moved; int new_required; @@ -2251,8 +2405,84 @@ int DoMouseCursor() { static int required_cursor; static int zero_count; static int button_was_down; - STUB_ONCE(); - return 0; + + period = 0; + this_call_time = PDGetTotalTime(); + if (last_call_time == 0) { + period = 1000; + } + while (period <= 20) { + // Sleep 1 ms to avoid 100% CPU usage + OS_Sleep(1); + this_call_time = PDGetTotalTime(); + period = this_call_time - last_call_time; + } + GetMousePosition(&x_coord, &y_coord); + mouse_moved = x_coord != gMouse_last_x_coord || y_coord != gMouse_last_y_coord; + button_is_down = EitherMouseButtonDown(); + cursor_offset = button_is_down ? 4 : 0; + if (gMouse_in_use || mouse_moved) { + gMouse_in_use = 1; + if (gMouse_last_x_coord == x_coord) { + if (zero_count >= 5) { + delta_x = 0; + } + zero_count++; + } else { + zero_count = 0; + delta_x = (x_coord - gMouse_last_x_coord) * 1000 / period; + } + if (delta_x < -10) { + new_required = 0; + } else if (delta_x < 11) { + new_required = 2; + } else { + new_required = 3; + } + if (new_required != required_cursor && this_call_time - last_required_change >= 200) { + last_required_change = this_call_time; + required_cursor = new_required; + } + if (gCurrent_cursor_index != required_cursor && PDGetTotalTime() - last_cursor_change >= 50) { + if (required_cursor < gCurrent_cursor_index) { + gCurrent_cursor_index--; + } else { + gCurrent_cursor_index++; + } + last_cursor_change = PDGetTotalTime(); + } + giblet_chance = Chance(1.f + 20.f * (abs(x_coord - gMouse_last_x_coord) + abs(y_coord - gMouse_last_y_coord)) / (float)period, period); + if (gProgram_state.sausage_eater_mode) { + giblet_count = 0; + } else { + giblet_count = 6 * BooleanTo1Or0(button_is_down && !button_was_down) + BooleanTo1Or0(giblet_chance); + } + for (; giblet_count != 0; giblet_count--) { + NewCursorGiblet( + x_coord + gCursor_gib_x_offsets[gCurrent_cursor_index + cursor_offset] * gGraf_specs[gGraf_spec_index].total_width / 640, + y_coord + gCursor_gib_y_offsets[gCurrent_cursor_index + cursor_offset] * gGraf_specs[gGraf_spec_index].total_height / 480, + ((float)(x_coord - gMouse_last_x_coord)) / period * 1000.f / 4.f, + ((float)(y_coord - gMouse_last_y_coord)) / period * 1000.f / 3.f, + (button_is_down && !button_was_down) ? 50 : 400); + } + ProcessCursorGiblets(period); + SaveTransient(gCursor_transient_index, + x_coord - gCursor_x_offsets[gCurrent_cursor_index + cursor_offset] * gGraf_specs[gGraf_spec_index].total_width / 640, + y_coord - gCursor_y_offsets[gCurrent_cursor_index + cursor_offset] * gGraf_specs[gGraf_spec_index].total_height / 480); + DRPixelmapRectangleMaskedCopy(gBack_screen, + x_coord - gCursor_x_offsets[gCurrent_cursor_index + cursor_offset] * gGraf_specs[gGraf_spec_index].total_width / 640, + y_coord - gCursor_y_offsets[gCurrent_cursor_index + cursor_offset] * gGraf_specs[gGraf_spec_index].total_height / 480, + gCursors[gCurrent_cursor_index + cursor_offset], + 0, + 0, + gCursors[gCurrent_cursor_index + cursor_offset]->width, + gCursors[gCurrent_cursor_index + cursor_offset]->height); + } + last_call_time = this_call_time; + button_was_down = button_is_down; + gMouse_last_x_coord = x_coord; + gMouse_last_y_coord = y_coord; + return mouse_moved; } // IDA: int __cdecl AllocateCursorTransient() @@ -2261,17 +2491,43 @@ int AllocateCursorTransient() { int largest_width; int largest_height; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + largest_width = 0; + largest_height = 0; + for (i = 0; i < COUNT_OF(gCursors); i++) { + if (largest_width < gCursors[i]->width) { + largest_width = gCursors[i]->width; + } + if (largest_height < gCursors[i]->height) { + largest_height = gCursors[i]->height; + } + } + return AllocateTransientBitmap(largest_width, largest_height, 0); } // IDA: void __cdecl StartMouseCursor() void StartMouseCursor() { - STUB(); + int i; + LOG_TRACE("()"); + + gNext_transient = 0; + gCursor_transient_index = AllocateCursorTransient(); + GetMousePosition(&gMouse_last_x_coord, &gMouse_last_y_coord); + gMouse_in_use = 0; + gCurrent_cursor_index = 2; + for (i = 0; i < COUNT_OF(gCursor_giblets); i++) { + gCursor_giblets[i].current_giblet = -1; + } + gMouse_started = 1; } // IDA: void __cdecl EndMouseCursor() void EndMouseCursor() { - STUB(); + LOG_TRACE("()"); + + RemoveTransientBitmaps(1); + DeallocateAllTransientBitmaps(); + gMouse_started = 0; } // IDA: void __usercall LoadFont(int pFont_ID@) diff --git a/src/DETHRACE/common/intrface.c b/src/DETHRACE/common/intrface.c index c6920d62..71064708 100644 --- a/src/DETHRACE/common/intrface.c +++ b/src/DETHRACE/common/intrface.c @@ -66,23 +66,23 @@ void ChangeSelection(tInterface_spec* pSpec, int* pOld_selection, int* pNew_sele } else if (*pOld_selection < *pNew_selection) { do { *pNew_selection = *pNew_selection + 1; - if (pSpec->move_up_min[pMode] != *pNew_selection && *pNew_selection <= pSpec->move_up_min[pMode]) { + if (*pNew_selection < pSpec->move_up_min[pMode]) { *pNew_selection = pSpec->move_up_max[pMode]; } - if (pSpec->move_up_max[pMode] < *pNew_selection) { + if (*pNew_selection > pSpec->move_up_max[pMode]) { *pNew_selection = pSpec->move_up_min[pMode]; } - } while (*pNew_selection != *pOld_selection && !ChoiceDisabled(*pNew_selection)); + } while (*pNew_selection != *pOld_selection && ChoiceDisabled(*pNew_selection)); } else { do { *pNew_selection = *pNew_selection - 1; - if (pSpec->move_up_min[pMode] != *pNew_selection && *pNew_selection <= pSpec->move_up_min[pMode]) { + if (*pNew_selection < pSpec->move_up_min[pMode]) { *pNew_selection = pSpec->move_up_max[pMode]; } - if (pSpec->move_up_max[pMode] < *pNew_selection) { + if (*pNew_selection > pSpec->move_up_max[pMode]) { *pNew_selection = pSpec->move_up_min[pMode]; } - } while (*pNew_selection != *pOld_selection && !ChoiceDisabled(*pNew_selection)); + } while (*pNew_selection != *pOld_selection && ChoiceDisabled(*pNew_selection)); } } @@ -157,7 +157,7 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice) tProg_status entry_status; // int x_coord; // int y_coord; // - int mouse_in_somewhere; + int mouse_in_somewhere = 0; int i; // int key2; int mouse_was_started; @@ -170,8 +170,8 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice) int the_key; // int the_max; int mouse_down; // - int new_mouse_down = 0; // - int last_mouse_down; + int new_mouse_down; // + int last_mouse_down = 0; int defeat_mode_change; // int selection_changed; // char the_str[256]; @@ -233,9 +233,9 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice) copy_areas = BrMemAllocate(sizeof(void*) * pSpec->number_of_recopy_areas, kMem_intf_copy_areas); for (i = 0; i < pSpec->number_of_recopy_areas; i++) { copy_areas[i] = BrPixelmapAllocate(BR_MEMORY_PIXELS, - ((pSpec->recopy_areas[i].right[gGraf_data_index] - pSpec->recopy_areas[i].left[gGraf_data_index]) + 3) & 0xFC, + ((pSpec->recopy_areas[i].right[gGraf_data_index] - pSpec->recopy_areas[i].left[gGraf_data_index]) + 3) & ~3, pSpec->recopy_areas[i].bottom[gGraf_data_index] - pSpec->recopy_areas[i].top[gGraf_data_index], - 0, 0); + NULL, 0); } } @@ -374,9 +374,11 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice) PDScreenBufferSwap(0); if (gMouse_in_use && !selection_changed) { GetMousePosition(&x_coord, &y_coord); - mouse_down = EitherMouseButtonDown(); - last_choice = 0; - new_mouse_down = mouse_down && !new_mouse_down; + new_mouse_down = EitherMouseButtonDown(); + mouse_down = new_mouse_down && !last_mouse_down; + last_mouse_down = new_mouse_down; + + mouse_in_somewhere = 0; for (i = 0; i < pSpec->number_of_mouse_areas; i++) { if (x_coord >= pSpec->mouse_areas[i].left[gGraf_data_index] && y_coord >= pSpec->mouse_areas[i].top[gGraf_data_index] @@ -393,10 +395,10 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice) } if (pSpec->mouse_areas[i].new_mode >= 0 || pSpec->mouse_areas[i].new_choice >= 0) { - last_choice = 1; + mouse_in_somewhere = 1; } if (mouse_down) { - if (pSpec->mouse_areas[i].mouse_click) { + if (pSpec->mouse_areas[i].mouse_click != NULL) { mouse_down = pSpec->mouse_areas[i].mouse_click(&gCurrent_choice, &gCurrent_mode, x_coord - pSpec->mouse_areas[i].left[gGraf_data_index], y_coord - pSpec->mouse_areas[i].top[gGraf_data_index]); @@ -407,7 +409,7 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice) } } - if (PDKeyDown(KEY_RETURN) || PDKeyDown(KEY_KP_ENTER) || (gTyping_slot < 0 && PDKeyDown(KEY_SPACE)) || (gMouse_in_use && last_choice && new_mouse_down)) { + if (PDKeyDown(KEY_RETURN) || PDKeyDown(KEY_KP_ENTER) || (gTyping_slot < 0 && PDKeyDown(KEY_SPACE)) || (gMouse_in_use && mouse_in_somewhere && mouse_down)) { DRS3StartSound(gIndexed_outlets[0], 3004); go_ahead = pSpec->go_ahead_allowed[gCurrent_mode]; if (pSpec->go_ahead_proc[gCurrent_mode]) { @@ -474,7 +476,7 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice) if (entry_status != eProg_idling && gProgram_state.prog_status == eProg_idling) { escaped = 1; } - } while ((!pSpec->exit_proc || !(pSpec->exit_proc)(&gCurrent_choice, &gCurrent_mode)) && !go_ahead && !timed_out && !escaped); + } while ((pSpec->exit_proc == NULL || !(pSpec->exit_proc)(&gCurrent_choice, &gCurrent_mode)) && !go_ahead && !timed_out && !escaped); LOG_WARN("OUT OF LOOP %d %d %d", go_ahead, timed_out, escaped); gTyping = 0; diff --git a/src/DETHRACE/common/loading.c b/src/DETHRACE/common/loading.c index 7180666f..5a8522fc 100644 --- a/src/DETHRACE/common/loading.c +++ b/src/DETHRACE/common/loading.c @@ -20,8 +20,6 @@ #include "globvrpb.h" #include "grafdata.h" #include "graphics.h" -#include "harness/config.h" -#include "harness/trace.h" #include "init.h" #include "input.h" #include "newgame.h" @@ -33,6 +31,9 @@ #include "spark.h" #include "utility.h" #include "world.h" +#include "harness/config.h" +#include "harness/hooks.h" +#include "harness/trace.h" #include #define HITHER_MULTIPLIER 2.0f @@ -550,7 +551,7 @@ void DRLoadPalette(char* pPath_name) { br_pixelmap* palette_array[100]; int number_of_palettes; - number_of_palettes = DRPixelmapLoadMany(pPath_name, palette_array, 100); + number_of_palettes = DRPixelmapLoadMany(pPath_name, palette_array, COUNT_OF(palette_array)); BrTableAddMany(palette_array, number_of_palettes); } @@ -559,7 +560,7 @@ void DRLoadShadeTable(char* pPath_name) { br_pixelmap* table_array[100]; int number_of_tables; - number_of_tables = DRPixelmapLoadMany(pPath_name, table_array, 100); + number_of_tables = DRPixelmapLoadMany(pPath_name, table_array, COUNT_OF(table_array)); BrTableAddMany(table_array, number_of_tables); } @@ -581,7 +582,7 @@ void DRLoadPixelmaps(char* pPath_name) { int i; PossibleService(); - number_of_pixelmaps = DRPixelmapLoadMany(pPath_name, pixelmap_array, 100); + number_of_pixelmaps = DRPixelmapLoadMany(pPath_name, pixelmap_array, COUNT_OF(pixelmap_array)); RezeroPixelmaps(pixelmap_array, number_of_pixelmaps); BrMapAddMany(pixelmap_array, number_of_pixelmaps); @@ -593,7 +594,7 @@ void DRLoadMaterials(char* pPath_name) { int number_of_materials; PossibleService(); - number_of_materials = BrMaterialLoadMany(pPath_name, material_array, 100); + number_of_materials = BrMaterialLoadMany(pPath_name, material_array, COUNT_OF(material_array)); BrMaterialAddMany(material_array, number_of_materials); } @@ -700,7 +701,7 @@ void LoadInterfaceStuff(int pWithin_race) { strcpy(path, "HANDX.PIX"); } PossibleService(); - if (!gCursors[0] && !LoadPixelmaps(path, gCursors, 4)) { + if (gCursors[0] == NULL && LoadPixelmaps(path, gCursors, 4) == 0) { FatalError(22); } if (gProgram_state.sausage_eater_mode) { @@ -709,11 +710,11 @@ void LoadInterfaceStuff(int pWithin_race) { strcpy(path, "HANDPX.PIX"); } PossibleService(); - if (!gCursors[4] && !LoadPixelmaps(path, &gCursors[4], 4)) { + if (gCursors[4] == NULL && LoadPixelmaps(path, &gCursors[4], 4) == 0) { FatalError(22); } PossibleService(); - if (!gCursor_giblet_images[0] && !LoadPixelmaps("CURSGIBX.PIX", gCursor_giblet_images, 18u)) { + if (gCursor_giblet_images[0] == NULL && LoadPixelmaps("CURSGIBX.PIX", gCursor_giblet_images, COUNT_OF(gCursor_giblet_images)) == 0) { FatalError(23); } } @@ -2633,7 +2634,7 @@ void LoadOpponents() { GetPairOfInts(f, &the_chunk->x_coord, &the_chunk->y_coord); GetPairOfInts(f, &the_chunk->frame_cue, &the_chunk->frame_end); the_chunk->line_count = GetAnInt(f); - while (the_chunk->line_count > 8) { + while (the_chunk->line_count > COUNT_OF(the_chunk->text)) { the_chunk->line_count--; GetALineAndDontArgue(f, s); } @@ -3070,9 +3071,9 @@ FILE* OldDRfopen(char* pFilename, char* pMode) { LOG_TRACE("(\"%s\", \"%s\")", pFilename, pMode); - fp = fopen(pFilename, pMode); + fp = Harness_Hook_fopen(pFilename, pMode); - if (fp) { + if (fp != NULL) { // Demo does not check gDecode_thing ("i am fiddling" in PROG.ACT) // If the text file starts with a '@' character, it will be decoded, otherwise used as-is. diff --git a/src/DETHRACE/common/mainmenu.c b/src/DETHRACE/common/mainmenu.c index ba191299..30cf13ae 100644 --- a/src/DETHRACE/common/mainmenu.c +++ b/src/DETHRACE/common/mainmenu.c @@ -168,22 +168,22 @@ int DoMainMenuInterface(tU32 pTime_out, int pContinue_allowed) { 0, // end_flic_escaped 0, // end_flic_otherwise 0, // flic_bunch_to_load - { 0x0FFFFFFFF, 0 }, // move_left_new_mode + { -1, 0 }, // move_left_new_mode { 0, 0 }, // move_left_delta { 0, 0 }, // move_left_min { 0, 0 }, // move_left_max { NULL, NULL }, // move_left_proc - { 0x0FFFFFFFF, 0 }, // move_right_new_mode + { -1, 0 }, // move_right_new_mode { 0, 0 }, // move_right_delta { 0, 0 }, // move_right_min { 0, 0 }, // move_right_max { NULL, NULL }, // move_right_proc - { 0x0FFFFFFFF, 0 }, // move_up_new_mode - { 0x0FFFFFFFF, 0 }, // move_up_delta + { -1, 0 }, // move_up_new_mode + { -1, 0 }, // move_up_delta { 0, 0 }, // move_up_min { 7, 0 }, // move_up_max { NULL, NULL }, // move_up_proc - { 0x0FFFFFFFF, 0 }, // move_down_new_mode + { -1, 0 }, // move_down_new_mode { 1, 0 }, // move_down_delta { 0, 0 }, // move_down_min { 7, 0 }, // move_down_max @@ -203,11 +203,11 @@ int DoMainMenuInterface(tU32 pTime_out, int pContinue_allowed) { NULL, // get_original_string 0, // escape_code 0, // dont_save_or_load - 8, // number_of_button_flics + COUNT_OF(flicker_on1), // number_of_button_flics flicker_on1, // flicker_on_flics flicker_off1, // flicker_off_flics push1, // pushed_flics - 8, // number_of_mouse_areas + COUNT_OF(mouse_areas1), // number_of_mouse_areas mouse_areas1, // mouse_areas 0, // number_of_recopy_areas NULL // recopy_areas @@ -249,22 +249,22 @@ int DoMainMenuInterface(tU32 pTime_out, int pContinue_allowed) { 0, // end_flic_escaped 0, // end_flic_otherwise 0, // flic_bunch_to_load - { 0x0FFFFFFFF, 0 }, // move_left_new_mode + { -1, 0 }, // move_left_new_mode { 0, 0 }, // move_left_delta { 0, 0 }, // move_left_min { 0, 0 }, // move_left_max { NULL, NULL }, // move_left_proc - { 0x0FFFFFFFF, 0 }, // move_right_new_mode + { -1, 0 }, // move_right_new_mode { 0, 0 }, // move_right_delta { 0, 0 }, // move_right_min { 0, 0 }, // move_right_max { NULL, NULL }, // move_right_proc - { 0x0FFFFFFFF, 0 }, // move_up_new_mode - { 0x0FFFFFFFF, 0 }, // move_up_delta + { -1, 0 }, // move_up_new_mode + { -1, 0 }, // move_up_delta { 0, 0 }, // move_up_min { 4, 0 }, // move_up_max { NULL, NULL }, // move_up_proc - { 0x0FFFFFFFF, 0 }, // move_down_new_mode + { -1, 0 }, // move_down_new_mode { 1, 0 }, // move_down_delta { 0, 0 }, // move_down_min { 4, 0 }, // move_down_max @@ -284,11 +284,11 @@ int DoMainMenuInterface(tU32 pTime_out, int pContinue_allowed) { NULL, // get_original_string 4, // escape_code 0, // dont_save_or_load - 5, // number_of_button_flics + COUNT_OF(flicker_on2), // number_of_button_flics flicker_on2, // flicker_on_flics flicker_off2, // flicker_off_flics push2, // pushed_flics - 5, // number_of_mouse_areas + COUNT_OF(mouse_areas2), // number_of_mouse_areas mouse_areas2, // mouse_areas 0, // number_of_recopy_areas NULL // recopy_areas diff --git a/src/DETHRACE/common/options.c b/src/DETHRACE/common/options.c index 61542ac5..cd5b3e29 100644 --- a/src/DETHRACE/common/options.c +++ b/src/DETHRACE/common/options.c @@ -431,7 +431,15 @@ int GraphOptDown(int* pCurrent_choice, int* pCurrent_mode) { int RadioClick(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) { int i; LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset); - NOT_IMPLEMENTED(); + + for (i = gRadio_bastards__options[*pCurrent_choice - 2].count - 1; i >= 0; i--) { + if (gThe_interface_spec__options->mouse_areas[2].left[gGraf_data_index] + pX_offset + 3 >= gRadio_bastards__options[*pCurrent_choice - 2].left[i]) { + DRS3StartSound(gIndexed_outlets[0], 3000); + RadioChanged(*pCurrent_choice - 2, i); + return 0; + } + } + return 0; } // IDA: int __usercall GraphOptGoAhead@(int *pCurrent_choice@, int *pCurrent_mode@) diff --git a/src/DETHRACE/common/racestrt.c b/src/DETHRACE/common/racestrt.c index cd1a06e2..8e100d87 100644 --- a/src/DETHRACE/common/racestrt.c +++ b/src/DETHRACE/common/racestrt.c @@ -777,7 +777,9 @@ tSO_result DoAutoPartsShop() { // IDA: void __cdecl SetOpponentFlic() void SetOpponentFlic() { LOG_TRACE("()"); - ChangePanelFlic(0, gOpponents[gCurrent_race.opponent_list[gOpponent_index].index].mug_shot_image_data, gOpponents[gCurrent_race.opponent_list[gOpponent_index].index].mug_shot_image_data_length); + ChangePanelFlic(0, + gOpponents[gCurrent_race.opponent_list[gOpponent_index].index].mug_shot_image_data, + gOpponents[gCurrent_race.opponent_list[gOpponent_index].index].mug_shot_image_data_length); } // IDA: void __cdecl DrawSceneyMappyInfoVieweyThing() @@ -858,25 +860,69 @@ int TryToMoveToArrows(int* pCurrent_choice, int* pCurrent_mode) { // IDA: int __usercall UpOpponent@(int *pCurrent_choice@, int *pCurrent_mode@) int UpOpponent(int* pCurrent_choice, int* pCurrent_mode) { LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + AddToFlicQueue(gStart_interface_spec->pushed_flics[5].flic_index, + gStart_interface_spec->pushed_flics[5].x[gGraf_data_index], + gStart_interface_spec->pushed_flics[5].y[gGraf_data_index], + 1); + DRS3StartSound(gIndexed_outlets[0], 3000); + DropOutImageThruBottom(GetPanelPixelmap(0), + gCurrent_graf_data->start_race_panel_left, + gCurrent_graf_data->start_race_panel_top, + gCurrent_graf_data->start_race_panel_top_clip, + gCurrent_graf_data->start_race_panel_bottom_clip); + if (gOpponent_index == 0) { + gOpponent_index = gCurrent_race.number_of_racers; + } + gOpponent_index--; + SetOpponentFlic(); + DropInImageFromTop(GetPanelPixelmap(0), + gCurrent_graf_data->start_race_panel_left, + gCurrent_graf_data->start_race_panel_top, + gCurrent_graf_data->start_race_panel_top_clip, + gCurrent_graf_data->start_race_panel_bottom_clip); } // IDA: int __usercall DownOpponent@(int *pCurrent_choice@, int *pCurrent_mode@) int DownOpponent(int* pCurrent_choice, int* pCurrent_mode) { LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + AddToFlicQueue(gStart_interface_spec->pushed_flics[6].flic_index, + gStart_interface_spec->pushed_flics[6].x[gGraf_data_index], + gStart_interface_spec->pushed_flics[6].y[gGraf_data_index], + 1); + DRS3StartSound(gIndexed_outlets[0], 3000); + DropOutImageThruTop(GetPanelPixelmap(0), + gCurrent_graf_data->start_race_panel_left, + gCurrent_graf_data->start_race_panel_top, + gCurrent_graf_data->start_race_panel_top_clip, + gCurrent_graf_data->start_race_panel_bottom_clip); + gOpponent_index++; + if (gOpponent_index == gCurrent_race.number_of_racers) { + gOpponent_index = 0; + } + SetOpponentFlic(); + DropInImageFromBottom(GetPanelPixelmap(0), + gCurrent_graf_data->start_race_panel_left, + gCurrent_graf_data->start_race_panel_top, + gCurrent_graf_data->start_race_panel_top_clip, + gCurrent_graf_data->start_race_panel_bottom_clip); } // IDA: int __usercall UpClickOpp@(int *pCurrent_choice@, int *pCurrent_mode@, int pX_offset@, int pY_offset@) int UpClickOpp(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) { LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset); - NOT_IMPLEMENTED(); + + UpOpponent(pCurrent_choice, pCurrent_mode); + return 0; } // IDA: int __usercall DownClickOpp@(int *pCurrent_choice@, int *pCurrent_mode@, int pX_offset@, int pY_offset@) int DownClickOpp(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) { LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset); - NOT_IMPLEMENTED(); + + DownOpponent(pCurrent_choice, pCurrent_mode); + return 0; } // IDA: void __cdecl SelectRaceStart() @@ -1757,7 +1803,21 @@ int GridClickCar(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY int base_pos; int x_coord; LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset); - NOT_IMPLEMENTED(); + + rel_pos = ((gCurrent_graf_data->grid_bottom_clip - gCurrent_graf_data->grid_top_clip) / 2) < pY_offset; + if (rel_pos) { + pX_offset -= gCurrent_graf_data->grid_x_stagger; + } + x_coord = pX_offset / gCurrent_graf_data->grid_x_pitch; + if (x_coord > 2) { + x_coord = 2; + } + new_pos = 2 * x_coord + rel_pos + (gOur_starting_position & ~1) - 2; + if (new_pos >= 0 && new_pos < gCurrent_race.number_of_racers && gProgram_state.rank < gCurrent_race.opponent_list[new_pos].ranking) { + DRS3StartSound(gIndexed_outlets[0], 3000); + DoGridTransition(gOur_starting_position, new_pos); + } + return 0; } // IDA: int __usercall GridClickNumbers@(int *pCurrent_choice@, int *pCurrent_mode@, int pX_offset@, int pY_offset@) @@ -1765,19 +1825,33 @@ int GridClickNumbers(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, in int new_pos; int i; LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset); - NOT_IMPLEMENTED(); + + new_pos = -1; + for (i = 0; i < gCurrent_race.number_of_racers; i++) { + if (gGrid_number_x_coords[i] <= pX_offset && (gCurrent_race.number_of_racers - 1 == i || pX_offset < gGrid_number_x_coords[i + 1])) { + new_pos = i; + break; + } + } + if (new_pos >= 0 && new_pos < gCurrent_race.number_of_racers && gProgram_state.rank <= gCurrent_race.opponent_list[new_pos].ranking) { + DRS3StartSound(gIndexed_outlets[0], 3000); + DoGridTransition(gOur_starting_position, new_pos); + } + return 0; } // IDA: int __usercall GridClickLeft@(int *pCurrent_choice@, int *pCurrent_mode@, int pX_offset@, int pY_offset@) int GridClickLeft(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) { LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset); - NOT_IMPLEMENTED(); + + GridMoveLeft(pCurrent_choice, pCurrent_mode); } // IDA: int __usercall GridClickRight@(int *pCurrent_choice@, int *pCurrent_mode@, int pX_offset@, int pY_offset@) int GridClickRight(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) { LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset); - NOT_IMPLEMENTED(); + + GridMoveRight(pCurrent_choice, pCurrent_mode); } // IDA: int __usercall CheckChallenge@(int *pCurrent_choice@, int *pCurrent_mode@) diff --git a/src/DETHRACE/common/utility.c b/src/DETHRACE/common/utility.c index 1309c3f7..856c3b8a 100644 --- a/src/DETHRACE/common/utility.c +++ b/src/DETHRACE/common/utility.c @@ -673,7 +673,6 @@ void PrintScreenFile(FILE* pF) { offset -= 2 * gBack_screen->row_bytes; } WriteU16L(pF, 0); - ; } // IDA: void __usercall PrintScreenFile16(FILE *pF@) diff --git a/src/DETHRACE/constants.h b/src/DETHRACE/constants.h index 7e43f0e0..384aed93 100644 --- a/src/DETHRACE/constants.h +++ b/src/DETHRACE/constants.h @@ -294,7 +294,7 @@ typedef enum keymapcodes { #define TIME_CONV_THING 0.00050000002 -#define OPPONENT_COUNT 0 +#define OPPONENT_COUNT 5 #define WORLD_SCALE 6.9f diff --git a/src/DETHRACE/pc-dos/dossys.c b/src/DETHRACE/pc-dos/dossys.c index a1e0a375..8b7a9300 100644 --- a/src/DETHRACE/pc-dos/dossys.c +++ b/src/DETHRACE/pc-dos/dossys.c @@ -532,9 +532,7 @@ void PDMouseButtons(int* pButton_1, int* pButton_2) { br_int_32 mouse_y; LOG_TRACE("(%p, %p)", pButton_1, pButton_2); - STUB_ONCE(); - *pButton_1 = 0; - *pButton_2 = 0; + Harness_Hook_GetMouseButtons(pButton_1, pButton_2); } // IDA: void __usercall PDGetMousePosition(int *pX_coord@, int *pY_coord@) @@ -547,7 +545,8 @@ void PDGetMousePosition(int* pX_coord, int* pY_coord) { static br_int_32 mouse_x; static br_int_32 mouse_y; LOG_TRACE("(%p, %p)", pX_coord, pY_coord); - NOT_IMPLEMENTED(); + + Harness_Hook_GetMousePosition(pX_coord, pY_coord); } // IDA: int __cdecl PDGetTotalTime() diff --git a/src/harness/harness.c b/src/harness/harness.c index 6db57fda..93f13f89 100644 --- a/src/harness/harness.c +++ b/src/harness/harness.c @@ -252,6 +252,10 @@ void Harness_Hook_PDSetKeyArray() { Window_PollEvents(); } +void Harness_Hook_FlushRenderer() { + renderer->FlushBuffers(last_colour_buffer, last_depth_buffer); +} + void Harness_Hook_BrMaterialUpdate(br_material* mat, br_uint_16 flags) { renderer->BufferMaterial(mat); } @@ -264,6 +268,16 @@ void Harness_Hook_BrBufferUpdate(br_pixelmap* pm, br_token use, br_uint_16 flags } } +// Input hooks +void Harness_Hook_GetMousePosition(int* pX, int* pY) { + Input_GetMousePosition(pX, pY); +} + +void Harness_Hook_GetMouseButtons(int* pButton1, int* pButton2) { + Input_GetMouseButtons(pButton1, pButton2); +} + +// Sound hooks void Harness_Hook_S3Service(int unk1, int unk2) { Sound_Service(); } @@ -271,6 +285,7 @@ void Harness_Hook_S3Service(int unk1, int unk2) { void Harness_Hook_S3StopAllOutletSounds() { } -void Harness_Hook_FlushRenderer() { - renderer->FlushBuffers(last_colour_buffer, last_depth_buffer); +// Filesystem hooks +FILE* Harness_Hook_fopen(const char* pathname, const char* mode) { + return OS_fopen(pathname, mode); } diff --git a/src/harness/include/harness/hooks.h b/src/harness/include/harness/hooks.h index 7eba5faf..795da1b8 100644 --- a/src/harness/include/harness/hooks.h +++ b/src/harness/include/harness/hooks.h @@ -3,6 +3,8 @@ #include "brender/br_types.h" +#include + void Harness_Init(int* argc, char* argv[]); // Hooks are called from original game code. @@ -27,8 +29,15 @@ void Harness_Hook_BrZbSceneRenderEnd(); void Harness_Hook_BrBufferUpdate(br_pixelmap* pm, br_token use, br_uint_16 flags); void Harness_Hook_BrMaterialUpdate(br_material* mat, br_uint_16 flags); +// Input hooks +void Harness_Hook_GetMousePosition(int* pX, int* pY); +void Harness_Hook_GetMouseButtons(int* pButton1, int* pButton2); + // Sound hooks void Harness_Hook_S3Service(int unk1, int unk2); void Harness_Hook_S3StopAllOutletSounds(); -#endif \ No newline at end of file +// Filesystem hooks +FILE* Harness_Hook_fopen(const char* pathname, const char* mode); + +#endif diff --git a/src/harness/include/harness/os.h b/src/harness/include/harness/os.h index 52ab9386..196032e9 100644 --- a/src/harness/include/harness/os.h +++ b/src/harness/include/harness/os.h @@ -2,6 +2,7 @@ #define HARNESS_OS_H #include +#include #if defined(_WIN32) || defined(_WIN64) #include @@ -43,4 +44,6 @@ int OS_IsDebuggerPresent(void); // Optional: install a handler to print stack trace during a crash void OS_InstallSignalHandler(char* program_name); +FILE* OS_fopen(const char* pathname, const char* mode); + #endif diff --git a/src/harness/io_platforms/io_platform.h b/src/harness/io_platforms/io_platform.h index e4ee4ea3..65fc72fb 100644 --- a/src/harness/io_platforms/io_platform.h +++ b/src/harness/io_platforms/io_platform.h @@ -8,5 +8,7 @@ void Window_PollEvents(void); void Window_Swap(int delay_ms_after_swap); int* Input_GetKeyMap(void); int Input_IsKeyDown(unsigned char scan_code); +void Input_GetMousePosition(int* pX, int* pY); +void Input_GetMouseButtons(int* pButton1, int* pButton2); -#endif \ No newline at end of file +#endif diff --git a/src/harness/io_platforms/sdl_gl.c b/src/harness/io_platforms/sdl_gl.c index 54e1b72d..84a4f0f9 100644 --- a/src/harness/io_platforms/sdl_gl.c +++ b/src/harness/io_platforms/sdl_gl.c @@ -122,6 +122,10 @@ int keymap[123] = { SDL_Window* window; SDL_GLContext context; uint8_t sdl_key_state[256]; +struct { + float x; + float y; +} sdl_window_scale; tRenderer gl_renderer = { GLRenderer_Init, @@ -155,7 +159,7 @@ tRenderer* Window_Create(char* title, int width, int height, int pRender_width, width, height, SDL_WINDOW_OPENGL); - if (!window) { + if (window == NULL) { LOG_PANIC("Failed to create window"); } @@ -164,6 +168,9 @@ tRenderer* Window_Create(char* title, int width, int height, int pRender_width, SDL_SetRelativeMouseMode(SDL_TRUE); } + sdl_window_scale.x = ((float)pRender_width) / width; + sdl_window_scale.y = ((float)pRender_height) / height; + // SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); context = SDL_GL_CreateContext(window); @@ -224,3 +231,15 @@ int* Input_GetKeyMap() { int Input_IsKeyDown(unsigned char scan_code) { return sdl_key_state[scan_code]; } + +void Input_GetMousePosition(int* pX, int* pY) { + SDL_GetMouseState(pX, pY); + *pX *= sdl_window_scale.x; + *pY *= sdl_window_scale.y; +} + +void Input_GetMouseButtons(int* pButton1, int* pButton2) { + int state = SDL_GetMouseState(NULL, NULL); + *pButton1 = state & SDL_BUTTON_LMASK; + *pButton2 = state & SDL_BUTTON_RMASK; +} diff --git a/src/harness/os/linux.c b/src/harness/os/linux.c index 80c0e526..53b3ba76 100644 --- a/src/harness/os/linux.c +++ b/src/harness/os/linux.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -285,3 +284,28 @@ void OS_InstallSignalHandler(char* program_name) { } } } + +FILE* OS_fopen(const char* pathname, const char* mode) { + FILE* f = fopen(pathname, mode); + if (f != NULL) { + return f; + } + char buffer[512]; + char buffer2[512]; + strcpy(buffer, pathname); + strcpy(buffer2, pathname); + char* pDirName = dirname(buffer); + char* pBaseName = basename(buffer2); + DIR* pDir = opendir(pDirName); + if (pDir == NULL) { + return NULL; + } + for (struct dirent* pDirent = readdir(pDir); pDirent != NULL; pDirent = readdir(pDir)) { + if (strcasecmp(pBaseName, pDirent->d_name) == 0) { + strcat(pDirName, "/"); + strcat(pDirName, pDirent->d_name); + return fopen(pDirName, mode); + } + } + return NULL; +} diff --git a/src/harness/os/macos.c b/src/harness/os/macos.c index b0f13249..c898be46 100644 --- a/src/harness/os/macos.c +++ b/src/harness/os/macos.c @@ -284,3 +284,7 @@ void OS_InstallSignalHandler(char* program_name) { } } } + +FILE* OS_fopen(const char* pathname, const char* mode) { + return fopen(pathname, mode); +} diff --git a/src/harness/os/windows.c b/src/harness/os/windows.c index 0b5e6f0e..148358df 100644 --- a/src/harness/os/windows.c +++ b/src/harness/os/windows.c @@ -203,4 +203,17 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS* ExceptionInfo) { void OS_InstallSignalHandler(char* program_name) { strcpy(_program_name, program_name); SetUnhandledExceptionFilter(windows_exception_handler); -} \ No newline at end of file +} + +FILE* OS_fopen(const char* pathname, const char* mode) { + FILE* f; + errno_t err; + + f = NULL; + err = fopen_s(&f, pathname, mode); + if (err != 0) { + fprintf(stderr, "Failed to open \"%s\"", pathname); + } + + return f; +}