Networking #1 - Lobby implemented (#335)

* Basic networking functions implemented to get the lobby functional

* Apply suggestions from code review

* PDNetObtainSystemUserName gets local system name

---------

Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com>
This commit is contained in:
Dethrace Engineering Department 2023-07-05 14:18:52 +12:00 committed by GitHub
parent 7d475fc117
commit 1c10b74141
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 4199 additions and 1176 deletions

View File

@ -1,3 +1,5 @@
$ErrorActionPreference = "Stop"
if ($($Env:PLATFORM_ARCH) -eq "x86") {
$sdl_path = "x86"
} else {
@ -18,7 +20,13 @@ Expand-Archive $Env:TEMP\SDL2-devel.zip -DestinationPath $Env:TEMP
# build
cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTS=ON "-DSDL2_ROOT_DIR=$($Env:TEMP)\SDL2-$sdl2_version" -B build
if ($LASTEXITCODE -ne 0) {
Exit $LASTEXITCODE
}
cmake --build build --config RelWithDebInfo
if ($LASTEXITCODE -ne 0) {
Exit $LASTEXITCODE
}
# copy SDL2.dll to build folder, so tests can run
cp $Env:TEMP\SDL2-$sdl2_version\lib\$sdl_path\SDL2.dll build

View File

@ -48,7 +48,10 @@ endfunction()
test_big_endian(IS_BIGENDIAN)
find_package(SDL2 REQUIRED)
find_package(SDL2 CONFIG)
if(NOT SDL2_FOUND)
find_package(SDL2 MODULE REQUIRED)
endif()
add_subdirectory(lib/libsmacker)
add_subdirectory(lib/glad)

View File

@ -10,6 +10,9 @@ target_include_directories(dethrace_obj
pd
)
# add_compile_options(-fsanitize=address)
# add_link_options(-fsanitize=address)
target_link_libraries(dethrace_obj PUBLIC SDL2::SDL2 smackw32 harness brender s3)
@ -35,6 +38,7 @@ else()
-Wstrict-prototypes
)
endif()
target_compile_definitions(dethrace_obj PRIVATE INSIDE_DETHRACE)
if(DETHRACE_FIX_BUGS)
target_compile_definitions(dethrace_obj PRIVATE DETHRACE_FIX_BUGS)
endif()
@ -154,14 +158,15 @@ target_sources(dethrace_obj PRIVATE
common/world.h
constants.h
dr_types.h
pc-dos/dosnet.c
pd/net.h
pc-dos/dossys.c
pd/sys.h
pc-win95/win95sys.c
pc-win95/dinput.h
pc-win95/ssdx.c
pc-win95/ssdx.h
pc-win95/win95net.c
pc-dos/dosnet.c
pc-dos/dossys.c
)
# Create our main game binary.
@ -184,7 +189,7 @@ if(NOT MSVC)
else()
target_link_libraries(dethrace PRIVATE dbghelp)
target_link_options(dethrace PRIVATE /subsystem:windows /ENTRY:mainCRTStartup)
target_compile_definitions(dethrace PRIVATE -D_CRT_SECURE_NO_WARNINGS -DSDL_MAIN_HANDLED)
target_compile_definitions(dethrace PRIVATE -D_CRT_SECURE_NO_WARNINGS -DSDL_MAIN_HANDLED -DWIN32_LEAN_AND_MEAN)
endif()
if(DETHRACE_IDE_ROOT_DIR)

View File

@ -494,36 +494,60 @@ void SetInitialPosition(tRace_info* pThe_race, int pCar_index, int pGrid_index)
car = pThe_race->opponent_list[pCar_index].car_spec;
BrMatrix34Identity(&car_actor->t.t.mat);
place_on_grid = 1;
if (gNet_mode && !gCurrent_net_game->options.grid_start && pThe_race->number_of_net_start_points) {
TELL_ME_IF_WE_PASS_THIS_WAY();
if (gNet_mode != eNet_mode_none && !gCurrent_net_game->options.grid_start && pThe_race->number_of_net_start_points != 0) {
start_i = i = IRandomBetween(0, pThe_race->number_of_net_start_points - 1);
do {
PossibleService();
for (j = 0; j < gNumber_of_net_players; j++) {
if (j != pCar_index) {
BrVector3Copy(&real_pos, &pThe_race->opponent_list[j].car_spec->car_master_actor->t.t.translate.t);
if (real_pos.v[0] > 500.f) {
real_pos.v[0] -= 1000.f;
real_pos.v[1] -= 1000.f;
real_pos.v[2] -= 1000.f;
}
BrVector3Sub(&dist, &real_pos, &pThe_race->net_starts[i].pos);
if (BrVector3LengthSquared(&dist) < 16.f) {
break;
}
}
}
if (j == gNumber_of_net_players) {
BrVector3Copy(&car_actor->t.t.translate.t, &pThe_race->net_starts[i].pos);
initial_yaw = BrDegreeToAngle(pThe_race->net_starts[i].yaw);
place_on_grid = 0;
}
i++;
if (i == pThe_race->number_of_net_start_points) {
i = 0;
}
} while (start_i != i);
}
if (place_on_grid) {
initial_yaw = (pThe_race->initial_yaw * 182.0444444444445);
initial_yaw = BrDegreeToAngle(pThe_race->initial_yaw);
BrMatrix34RotateY(&initial_yaw_matrix, initial_yaw);
grid_offset.v[0] = 0.0 - pGrid_index % 2;
grid_offset.v[1] = 0.0;
grid_offset.v[2] = (double)(pGrid_index / 2) * 2.0 + (double)(pGrid_index % 2) * 0.40000001;
grid_offset.v[0] = 0.0f - pGrid_index % 2;
grid_offset.v[1] = 0.0f;
grid_offset.v[2] = (br_scalar)(pGrid_index / 2) * 2.0f + (br_scalar)(pGrid_index % 2) * 0.4f;
BrMatrix34ApplyV(&car_actor->t.t.translate.t, &grid_offset, &initial_yaw_matrix);
BrVector3Accumulate(&car_actor->t.t.translate.t, &pThe_race->initial_position);
}
FindBestY(
&car_actor->t.t.translate.t,
gTrack_actor,
10.0,
10.0f,
&nearest_y_above,
&nearest_y_below,
&above_model,
&below_model,
&above_face_index,
&below_face_index);
if (nearest_y_above == 30000.0) {
if (nearest_y_below == -30000.0) {
car_actor->t.t.translate.t.v[1] = 0.0;
} else {
car_actor->t.t.translate.t.v[1] = nearest_y_below;
}
} else {
if (nearest_y_above != 30000.0f) {
car_actor->t.t.translate.t.v[1] = nearest_y_above;
} else if (nearest_y_below != -30000.0f) {
car_actor->t.t.translate.t.v[1] = nearest_y_below;
} else {
car_actor->t.t.translate.t.v[1] = 0.0f;
}
BrMatrix34PreRotateY(&car_actor->t.t.mat, initial_yaw);
if (gNet_mode) {
@ -531,7 +555,7 @@ void SetInitialPosition(tRace_info* pThe_race, int pCar_index, int pGrid_index)
&gNet_players[pThe_race->opponent_list[pCar_index].net_player_index].initial_position,
&car->car_master_actor->t.t.mat);
}
if (gNet_mode && car->disabled && car_actor->t.t.translate.t.v[0] < 500.0) {
if (gNet_mode != eNet_mode_none && car->disabled && car_actor->t.t.translate.t.v[0] < 500.0f) {
DisableCar(car);
}
// Enable to start all opponent cars upside down ;)

View File

@ -2500,7 +2500,34 @@ void InitAbuseomatic(void) {
int i;
int len;
LOG_TRACE("()");
NOT_IMPLEMENTED();
gString[20] = '\0';
PDBuildAppPath(path);
strcat(path, "ABUSE.TXT");
for (i = 0; i < COUNT_OF(gAbuse_text); i++) {
gAbuse_text[i] = NULL;
}
f = fopen(path, "rt");
if (f == NULL) {
return;
}
for (i = 0; i < COUNT_OF(gAbuse_text); i++) {
if (fgets(s, COUNT_OF(s) - 1, f) == NULL) {
break;
}
len = strlen(s);
if (len > 63) {
s[63] = '\0';
}
len = strlen(s);
while (len != 0 && s[len - 1] < ' ') {
s[len - 1] = '\0';
len--;
}
gAbuse_text[i] = BrMemAllocate(strlen(s) + 1, kMem_abuse_text);
strcpy(gAbuse_text[i], s);
}
fclose(f);
}
// IDA: void __cdecl DisposeAbuseomatic()

View File

@ -242,6 +242,10 @@ void dr_dprintf(char* fmt_string, ...) {
return;
}
if (gDiagnostic_file == NULL) {
return;
}
if (first_time == 0) {
first_time = GetTotalTime();
}
@ -254,6 +258,12 @@ void dr_dprintf(char* fmt_string, ...) {
va_end(args);
fputs("\n", gDiagnostic_file);
fflush(gDiagnostic_file);
// Added by dethrace for debugging
// va_start(args, fmt_string);
// vprintf(fmt_string, args);
// va_end(args);
// printf("\n");
}
// IDA: int __usercall DoErrorInterface@<EAX>(int pMisc_text_index@<EAX>)

View File

@ -425,7 +425,7 @@ void InitGame(int pStart_race) {
gWaiting_for_unpause = 1;
gWait_for_it = 1;
if (gNet_mode) {
if (gNet_mode != eNet_mode_none) {
gCredit_period = gCredit_period_network[gCurrent_net_game->type];
} else {
gCredit_period = gCredit_period_single[gProgram_state.skill_level];
@ -448,10 +448,10 @@ void InitGame(int pStart_race) {
gProgram_state.current_car.power_up_levels[i] = 0;
}
}
for (i = 0; gNumber_of_races > i; ++i) {
for (i = 0; i < gNumber_of_races; i++) {
gRace_list[i].been_there_done_that = 0;
}
for (i = 0; gNumber_of_racers > i; ++i) {
for (i = 0; i < gNumber_of_racers; i++) {
gOpponents[i].dead = 0;
}
gProgram_state.rank = gInitial_rank;
@ -470,7 +470,7 @@ void DisposeGameIfNecessary(void) {
int i;
LOG_TRACE("()");
if (gNet_mode) {
if (gNet_mode != eNet_mode_none) {
NetLeaveGame(gCurrent_net_game);
}
if (gGame_initialized) {

View File

@ -511,33 +511,29 @@ int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice)
} else {
result = gCurrent_choice;
}
if (!go_ahead) {
if (!escaped) {
if (pSpec->end_flic_otherwise > 0) {
DRS3StartSound(gEffects_outlet, 3007);
RunFlic(pSpec->end_flic_otherwise);
} else if (pSpec->end_flic_otherwise < 0) {
FadePaletteDown();
}
goto LABEL_230;
} else {
if (pSpec->end_flic_escaped > 0) {
DRS3StartSound(gEffects_outlet, 3007);
RunFlic(pSpec->end_flic_escaped);
} else if (pSpec->end_flic_escaped < 0) {
FadePaletteDown();
}
goto LABEL_230;
if (go_ahead) {
if (pSpec->end_flic_go_ahead > 0) {
DRS3StartSound(gIndexed_outlets[0], 3007);
RunFlic(pSpec->end_flic_go_ahead);
} else if (pSpec->end_flic_go_ahead < 0) {
FadePaletteDown();
}
} else if (escaped) {
if (pSpec->end_flic_escaped > 0) {
DRS3StartSound(gIndexed_outlets[0], 3007);
RunFlic(pSpec->end_flic_escaped);
} else if (pSpec->end_flic_escaped < 0) {
FadePaletteDown();
}
} else {
if (pSpec->end_flic_otherwise > 0) {
DRS3StartSound(gIndexed_outlets[0], 3007);
RunFlic(pSpec->end_flic_otherwise);
} else if (pSpec->end_flic_otherwise < 0) {
FadePaletteDown();
}
}
if (pSpec->end_flic_go_ahead > 0) {
DRS3StartSound(gEffects_outlet, 3007);
RunFlic(pSpec->end_flic_go_ahead);
} else if (pSpec->end_flic_go_ahead < 0) {
FadePaletteDown();
}
LABEL_230:
gProgram_state.dont_save_or_load = 0;
EndMouseCursor();
UnlockInterfaceStuff();

View File

@ -3411,7 +3411,12 @@ int OriginalCarmaCDinDrive(void) {
// IDA: int __cdecl CarmaCDinDriveOrFullGameInstalled()
int CarmaCDinDriveOrFullGameInstalled(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
if (gCD_fully_installed) {
return 1;
} else {
return OriginalCarmaCDinDrive();
}
}
// IDA: void __usercall ReadNetworkSettings(FILE *pF@<EAX>, tNet_game_options *pOptions@<EDX>)

View File

@ -323,10 +323,10 @@ int DoMainMenuInterface(tU32 pTime_out, int pContinue_allowed) {
if (pContinue_allowed) {
gMain_menu_spec = &interface_spec1;
result = DoInterfaceScreen(&interface_spec1, gFaded_palette | 2, 0);
if (result != 7 && result && result != 1 && result != 2) {
RunFlic(12);
} else {
if (result == 0 || result == 1 || result == 2 || result == 7) {
FadePaletteDown();
} else {
RunFlic(12);
}
switch (result) {
case 0:
@ -352,10 +352,10 @@ int DoMainMenuInterface(tU32 pTime_out, int pContinue_allowed) {
} else {
interface_spec2.time_out = pTime_out;
result = DoInterfaceScreen(&interface_spec2, gFaded_palette, 0);
if (result != 4 && result != -1) {
RunFlic(32);
} else {
if (result == -1 || result == 4) {
FadePaletteDown();
} else {
RunFlic(32);
}
switch (result) {
case 0:

View File

@ -1,11 +1,21 @@
#include "netgame.h"
#include "brender/brender.h"
#include "car.h"
#include "displays.h"
#include "errors.h"
#include "globvars.h"
#include "globvrpb.h"
#include "graphics.h"
#include "harness/trace.h"
#include "loading.h"
#include "network.h"
#include "newgame.h"
#include "opponent.h"
#include "pd/sys.h"
#include "pedestrn.h"
#include "powerup.h"
#include "racestrt.h"
#include "structur.h"
#include "utility.h"
#include <stdlib.h>
#include <string.h>
@ -74,7 +84,20 @@ void SendAllNonCarPositions(void) {
tNon_car_spec* non_car;
tNet_contents* contents;
LOG_TRACE("()");
NOT_IMPLEMENTED();
list = gProgram_state.track_spec.non_car_list;
for (i = 0; i < gProgram_state.track_spec.ampersand_digits; ++i) {
if (list[i]->type_data != NULL) {
non_car = (tNon_car_spec*)list[i]->type_data;
if (non_car->collision_info.driver == eDriver_non_car_unused_slot || non_car->collision_info.car_ID != i) {
contents = NetGetBroadcastContents(NETMSGID_NONCARPOSITION, 0);
BrMatrix34Copy(&contents->data.non_car_position.mat, &list[i]->t.t.mat);
contents->data.non_car_position.ID = i;
contents->data.non_car_position.flags = list[i]->identifier[3] == '!';
}
}
}
NetSendMessageStacks();
}
// IDA: void __usercall ReceivedNonCarPosition(tNet_contents *pContents@<EAX>)
@ -103,13 +126,60 @@ void SignalToStartRace2(int pIndex) {
int i;
int j;
LOG_TRACE("(%d)", pIndex);
NOT_IMPLEMENTED();
if (gCurrent_race.number_of_racers > 6) {
FadePaletteUp();
dr_dprintf("AAAARRRGGGHHH!!!! More than 6 racers!!!!");
PDFatalError("AAAARRRGGGHHH!!!! More than 6 racers!!!!");
}
gNeed_to_send_start_race = 0;
gStart_race_sent = 1;
the_message = NetBuildMessage(NETMSGID_STARTRACE, 0);
the_message->contents.data.start_race.racing = gProgram_state.racing;
if (pIndex >= 0) {
gNet_players[pIndex].last_waste_message = 0;
gNet_players[pIndex].wasteage_attributed = 0;
the_message->contents.data.start_race.car_count = -1;
the_message->contents.data.start_race.car_list[0].index = pIndex;
BrMatrix34Copy(&the_message->contents.data.start_race.car_list[0].mat,
&gCurrent_race.opponent_list[gNet_players[pIndex].opponent_list_index].car_spec->car_master_actor->t.t.mat);
} else {
the_message->contents.data.start_race.car_count = gCurrent_race.number_of_racers;
for (i = 0; i < gCurrent_race.number_of_racers; i++) {
BrMatrix34Copy(&the_message->contents.data.start_race.car_list[i].mat,
&gCurrent_race.opponent_list[i].car_spec->car_master_actor->t.t.mat);
for (j = 0; j < gNumber_of_net_players; j++) {
if (gCurrent_race.opponent_list[i].car_spec == gNet_players[j].car) {
the_message->contents.data.start_race.car_list[i].index = j;
break;
}
}
if (gCurrent_net_game->options.random_car_choice && (gCurrent_net_game->options.car_choice == eNet_car_all || gCurrent_net_game->options.car_choice == eNet_car_both)) {
if (gNet_players[the_message->contents.data.start_race.car_list[i].index].next_car_index < 0) {
gNet_players[the_message->contents.data.start_race.car_list[i].index].next_car_index = PickARandomCar();
gCar_details[gNet_players[the_message->contents.data.start_race.car_list[i].index].next_car_index].ownership = eCar_owner_someone;
}
the_message->contents.data.start_race.car_list[i].next_car_index = gNet_players[the_message->contents.data.start_race.car_list[i].index].next_car_index;
}
}
if (gPending_race < 0) {
gPending_race = PickNetRace(gProgram_state.current_race_index,
gCurrent_net_game->options.race_sequence_type);
}
the_message->contents.data.start_race.next_race = gPending_race;
}
NetGuaranteedSendMessageToAllPlayers(gCurrent_net_game, the_message, NULL);
if (gProgram_state.racing) {
SendCurrentPowerups();
}
}
// IDA: void __cdecl SignalToStartRace()
void SignalToStartRace(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gCurrent_net_game->no_races_yet = 0;
SignalToStartRace2(-1);
}
// IDA: void __cdecl SetUpNetCarPositions()
@ -120,7 +190,62 @@ void SetUpNetCarPositions(void) {
int grid_index;
int racer_count;
LOG_TRACE("()");
NOT_IMPLEMENTED();
DisableNetService();
if (!gInitialised_grid) {
for (i = 0; i < gNumber_of_net_players; i++) {
gNet_players[i].grid_position_set = 0;
gNet_players[i].last_waste_message = 0;
gNet_players[i].wasteage_attributed = 0;
}
}
for (i = 0; i < gNumber_of_net_players; i++) {
gCurrent_race.opponent_list[i].index = -1;
gCurrent_race.opponent_list[i].ranking = IRandomBetween(0, 99);
gCurrent_race.opponent_list[i].car_spec = gNet_players[i].car;
gCurrent_race.opponent_list[i].net_player_index = i;
gNet_players[i].opponent_list_index = i;
}
if (!gInitialised_grid && gCurrent_net_game->options.grid_start) {
qsort(gCurrent_race.opponent_list, gNumber_of_net_players, sizeof(tOpp_spec), SortGridFunction);
}
gCurrent_race.number_of_racers = 0;
for (i = 0; i < gNumber_of_net_players; i++) {
gNet_players[gCurrent_race.opponent_list[i].net_player_index].opponent_list_index = i;
}
for (i = 0; i < gNumber_of_net_players; i++) {
if ((gCurrent_race.opponent_list[i].car_spec->driver == eDriver_oppo && !gInitialised_grid)
|| (gCurrent_race.opponent_list[i].car_spec->driver >= eDriver_net_human && !gNet_players[gCurrent_race.opponent_list[i].net_player_index].grid_position_set)) {
grid_index = -1;
racer_count = 0;
while (racer_count < 6 && grid_index < 0) {
grid_index = racer_count;
for (k = 0; k < gNumber_of_net_players; k++) {
if (k != i
&& gNet_players[gCurrent_race.opponent_list[k].net_player_index].grid_position_set
&& gNet_players[gCurrent_race.opponent_list[k].net_player_index].grid_index == racer_count) {
grid_index = -1;
break;
}
}
racer_count++;
}
if (grid_index < 0) {
FatalError(kFatalError_NetworkCodeSelfCheck);
}
SetInitialPosition(&gCurrent_race, i, grid_index);
gNet_players[gCurrent_race.opponent_list[i].net_player_index].grid_index = grid_index;
if (gInitialised_grid) {
InitialiseCar2(gCurrent_race.opponent_list[i].car_spec, 0);
} else {
gCurrent_race.number_of_racers = i + 1;
}
gNet_players[gCurrent_race.opponent_list[i].net_player_index].grid_position_set = 1;
}
}
gCurrent_race.number_of_racers = gNumber_of_net_players;
gInitialised_grid = 1;
ReenableNetService();
}
// IDA: void __usercall ReinitialiseCar(tCar_spec *pCar@<EAX>)
@ -185,7 +310,56 @@ void DoNetworkHeadups(int pCredits) {
static tU32 last_flash;
static int flash_state;
LOG_TRACE("(%d)", pCredits);
STUB_ONCE();
if (gNot_shown_race_type_headup) {
gNot_shown_race_type_headup = 0;
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(59 + gCurrent_net_game->type));
}
if (gTime_for_punishment && gTime_for_punishment <= PDGetTotalTime()) {
gTime_for_punishment = 0;
switch (gCurrent_net_game->type) {
case eNet_game_type_carnage:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(219));
break;
case eNet_game_type_checkpoint:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(220));
break;
case eNet_game_type_sudden_death:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(221));
break;
case eNet_game_type_foxy:
NewTextHeadupSlot(4, 0, 2000, -4, GetMiscString(222));
break;
default:
break;
}
}
if (gNet_mode == eNet_mode_none || gNet_recovery_cost[gCurrent_net_game->type] <= gProgram_state.credits_earned - gProgram_state.credits_lost || Flash(200, &last_flash, &flash_state)) {
sprintf(s, "\xf8%d\xfa %s", pCredits, GetMiscString(94));
ChangeHeadupText(gNet_cash_headup, s);
} else {
ChangeHeadupText(gNet_cash_headup, "");
}
switch (gCurrent_net_game->type) {
case eNet_game_type_carnage:
sprintf(s, "%s \xf8%d\xfa", GetMiscString(180), gPed_target);
break;
case eNet_game_type_car_crusher:
sprintf(s, "%s \xf8%d\xfa", GetMiscString(181), gCurrent_net_game->options.race_end_target);
break;
case eNet_game_type_foxy:
TimerString(gCurrent_net_game->options.race_end_target, s2, 1, 1);
sprintf(s, "%s \xf8%s\xfa", GetMiscString(182), s2);
break;
case eNet_game_type_tag:
TimerString(gCurrent_net_game->options.race_end_target, s2, 1, 1);
sprintf(s, "%s \xf8%s\xfa", GetMiscString(183), s2);
break;
default:
s[0] = '\0';
break;
}
ChangeHeadupText(gNet_ped_headup, s);
}
// IDA: int __usercall SortNetHeadAscending@<EAX>(void *pFirst_one@<EAX>, void *pSecond_one@<EDX>)
@ -234,13 +408,29 @@ void DoNetScores(void) {
// IDA: void __cdecl InitNetHeadups()
void InitNetHeadups(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gIcons_pix = LoadPixelmap("CARICONS.PIX");
if (gIcons_pix != NULL) {
BrMapAdd(gIcons_pix);
}
gDigits_pix = LoadPixelmap("HDIGITS.PIX");
if (gDigits_pix != NULL) {
BrMapAdd(gDigits_pix);
}
}
// IDA: void __cdecl DisposeNetHeadups()
void DisposeNetHeadups(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
if (gIcons_pix != NULL) {
BrMapRemove(gIcons_pix);
BrPixelmapFree(gIcons_pix);
}
if (gDigits_pix != NULL) {
BrMapRemove(gDigits_pix);
BrPixelmapFree(gDigits_pix);
}
}
// IDA: void __cdecl EverybodysLost()
@ -323,13 +513,26 @@ void SendPlayerScores(void) {
tNet_contents* the_contents;
int i;
LOG_TRACE("()");
NOT_IMPLEMENTED();
the_contents = NetGetBroadcastContents(NETMSGID_SCORES, 0);
if (gCurrent_net_game->type == eNet_game_type_carnage) {
the_contents->data.scores.general_score = gPed_target;
} else if (gCurrent_net_game->type == eNet_game_type_tag || gCurrent_net_game->type == eNet_game_type_foxy) {
the_contents->data.scores.general_score = gNet_players[gIt_or_fox].ID;
}
for (i = 0; i < gNumber_of_net_players; i++) {
the_contents->data.scores.scores[i] = gNet_players[i].score;
}
}
// IDA: void __cdecl DoNetGameManagement()
void DoNetGameManagement(void) {
LOG_TRACE("()");
STUB_ONCE();
if (gNet_mode == eNet_mode_host) {
CalcPlayerScores();
SendPlayerScores();
}
}
// IDA: void __usercall InitialisePlayerScore(tNet_game_player_info *pPlayer@<EAX>)
@ -442,14 +645,24 @@ void UseGeneralScore(int pScore) {
// IDA: void __usercall NetSendEnvironmentChanges(tNet_game_player_info *pPlayer@<EAX>)
void NetSendEnvironmentChanges(tNet_game_player_info* pPlayer) {
LOG_TRACE("(%p)", pPlayer);
NOT_IMPLEMENTED();
SendAllPedestrianPositions(pPlayer->ID);
SendAllNonCarPositions();
}
// IDA: void __cdecl UpdateEnvironments()
void UpdateEnvironments(void) {
int i;
LOG_TRACE("()");
NOT_IMPLEMENTED();
for (i = 1; i < gNumber_of_net_players; i++) {
if (!gNet_players[i].race_stuff_initialised) {
NetSendEnvironmentChanges(&gNet_players[i]);
gNet_players[i].race_stuff_initialised = 1;
}
NetSendMessageStacks();
SendGameplay(gNet_players[i].ID, eNet_gameplay_go_for_it, 0, 0, 0, 0);
}
}
// IDA: void __usercall ReceivedGameplay(tNet_contents *pContents@<EAX>, tNet_message *pMessage@<EDX>, tU32 pReceive_time@<EBX>)
@ -467,7 +680,14 @@ void ReceivedGameplay(tNet_contents* pContents, tNet_message* pMessage, tU32 pRe
void SendGameplay(tPlayer_ID pPlayer, tNet_gameplay_mess pMess, int pParam_1, int pParam_2, int pParam_3, int pParam_4) {
tNet_message* the_message;
LOG_TRACE("(%d, %d, %d, %d, %d, %d)", pPlayer, pMess, pParam_1, pParam_2, pParam_3, pParam_4);
NOT_IMPLEMENTED();
the_message = NetBuildMessage(NETMSGID_GAMEPLAY, 0);
the_message->contents.data.gameplay.mess = pMess;
the_message->contents.data.gameplay.param_1 = pParam_1;
the_message->contents.data.gameplay.param_2 = pParam_2;
the_message->contents.data.gameplay.param_3 = pParam_3;
the_message->contents.data.gameplay.param_4 = pParam_4;
NetGuaranteedSendMessageToPlayer(gCurrent_net_game, the_message, pPlayer, 0);
}
// IDA: void __usercall SendGameplayToAllPlayers(tNet_gameplay_mess pMess@<EAX>, int pParam_1@<EDX>, int pParam_2@<EBX>, int pParam_3@<ECX>, int pParam_4)
@ -475,7 +695,13 @@ void SendGameplayToAllPlayers(tNet_gameplay_mess pMess, int pParam_1, int pParam
tNet_message* the_message;
LOG_TRACE("(%d, %d, %d, %d, %d)", pMess, pParam_1, pParam_2, pParam_3, pParam_4);
STUB_ONCE();
the_message = NetBuildMessage(NETMSGID_GAMEPLAY, 0);
the_message->contents.data.gameplay.mess = pMess;
the_message->contents.data.gameplay.param_1 = pParam_1;
the_message->contents.data.gameplay.param_2 = pParam_2;
the_message->contents.data.gameplay.param_3 = pParam_3;
the_message->contents.data.gameplay.param_4 = pParam_4;
NetGuaranteedSendMessageToAllPlayers(gCurrent_net_game, the_message, NULL);
}
// IDA: void __usercall SendGameplayToHost(tNet_gameplay_mess pMess@<EAX>, int pParam_1@<EDX>, int pParam_2@<EBX>, int pParam_3@<ECX>, int pParam_4)

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ extern tU32 gLast_flush_message;
extern int gRace_only_flags[33];
extern int gJoin_list_mode;
extern tNet_game_player_info gNew_net_players[6];
extern tGuaranteed_message gGuarantee_list[150];
extern tGuaranteed_message gGuarantee_list[100];
extern tMid_message* gMid_messages;
extern tU32 gLast_player_list_received;
extern tMin_message* gMin_messages;

File diff suppressed because it is too large Load Diff

View File

@ -1989,13 +1989,13 @@ void SendPedestrian(tPedestrian_data* pPedestrian, int pIndex) {
size_decider = 1;
}
the_message = NULL;
the_contents = NetGetBroadcastContents(0x19, size_decider);
the_contents = NetGetBroadcastContents(NETMSGID_PEDESTRIAN, size_decider);
} else {
size_decider = 2;
if (pPedestrian->current_frame == pPedestrian->sequences[pPedestrian->current_sequence].number_of_frames - 1) {
pPedestrian->sent_dead_message++;
}
the_message = NetBuildMessage(0x19, size_decider);
the_message = NetBuildMessage(NETMSGID_PEDESTRIAN, size_decider);
the_contents = &the_message->contents;
}
the_contents->data.pedestrian.index = pIndex;

View File

@ -294,6 +294,12 @@ void PratcamEvent(int pIndex) {
if (gInterface_within_race_mode) {
return;
}
#if defined(DETHRACE_FIX_BUGS)
// In low memory mode, `gPratcam_sequences`is not allocated and thus unsafe to access
if (gAusterity_mode) {
return;
}
#endif
if (gPratcam_sequences[pIndex].precedence <= gCurrent_pratcam_precedence) {
return;
}

View File

@ -14,9 +14,12 @@
#include "input.h"
#include "intrface.h"
#include "loading.h"
#include "netgame.h"
#include "network.h"
#include "newgame.h"
#include "opponent.h"
#include "pd/sys.h"
#include "racestrt.h"
#include "sound.h"
#include "structur.h"
#include "utility.h"
@ -37,7 +40,7 @@ tParts_category gPart_category;
tU32 gNet_synch_start;
tNet_game_details* gChoose_car_net_game;
int gPart_index;
int gChallenger_index__racestrt; // suffix added to avoid duplicate symbol
int gChallenger_index__racestrt; // suffix added to avoid duplicate symbol
tGrid_draw gDraw_grid_status;
tNet_sequence_type gNet_race_sequence__racestrt; // suffix added to avoid duplicate symbol
br_pixelmap* gTaken_image;
@ -2495,20 +2498,38 @@ void CheckPlayersAreResponding(void) {
tU32 time;
tNet_message* message;
LOG_TRACE("()");
NOT_IMPLEMENTED();
time = PDGetTotalTime();
for (i = 0; i < gNumber_of_net_players; i++) {
if (i != gThis_net_player_index && time - gNet_players[i].last_heard_from_him > 20000) {
gNet_players[i].player_status = ePlayer_status_not_responding;
}
}
if (gNet_mode == eNet_mode_client && gLast_host_query == 0) {
message = NetBuildMessage(NETMSGID_HOSTQUERY, 0);
NetGuaranteedSendMessageToHost(gCurrent_net_game, message, NULL);
gLast_host_query = time;
}
}
// IDA: void __cdecl NetSynchStartStart()
void NetSynchStartStart(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
CheckPlayersAreResponding();
}
// IDA: void __usercall DrawAnItem(int pX@<EAX>, int pY_index@<EDX>, int pFont_index@<EBX>, char *pText@<ECX>)
// Suffix added to avoid duplicate symbol
void DrawAnItem__racestrt(int pX, int pY_index, int pFont_index, char* pText) {
LOG_TRACE("(%d, %d, %d, \"%s\")", pX, pY_index, pFont_index, pText);
NOT_IMPLEMENTED();
TransBrPixelmapText(gBack_screen,
pX,
gCurrent_graf_data->start_synch_top + gCurrent_graf_data->start_synch_y_pitch * pY_index,
pFont_index,
gFont_7,
pText);
}
// IDA: void __usercall NetSynchStartDraw(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
@ -2517,51 +2538,272 @@ void NetSynchStartDraw(int pCurrent_choice, int pCurrent_mode) {
int number_ready;
char s[256];
LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
NOT_IMPLEMENTED();
number_ready = 0;
CheckPlayersAreResponding();
NetPlayerStatusChanged(ePlayer_status_ready);
for (i = 0; i < COUNT_OF(gNet_players); i++) {
BrPixelmapRectangleFill(gBack_screen,
gCurrent_graf_data->start_synch_x_0,
gCurrent_graf_data->start_synch_y_pitch * i + gCurrent_graf_data->start_synch_top,
gCurrent_graf_data->start_synch_x_r - gCurrent_graf_data->start_synch_x_1,
gFont_7->glyph_y,
0);
}
for (i = 0; i < gNumber_of_net_players; i++) {
strcpy(s, gNet_players[i].player_name);
if (gNet_players[i].host) {
strcat(s, " -");
strcat(s, GetMiscString(88));
strcat(s, "-");
}
TurnOffPaletteConversion();
DRPixelmapRectangleMaskedCopy(gBack_screen,
gCurrent_graf_data->start_synch_x_0,
gCurrent_graf_data->start_synch_top + 1 + gCurrent_graf_data->start_synch_y_pitch * i,
gIcons_pix,
0,
gNet_players[i].car_index * gCurrent_graf_data->net_head_icon_height,
gIcons_pix->width,
gCurrent_graf_data->net_head_icon_height);
TurnOnPaletteConversion();
DrawAnItem__racestrt(
gCurrent_graf_data->start_synch_x_1,
i,
(gNet_players[i].player_status == ePlayer_status_ready) ? 66 : 4,
s);
DrawAnItem__racestrt(gCurrent_graf_data->start_synch_x_2,
i,
(gNet_players[i].player_status == ePlayer_status_ready) ? 83 : ((gNet_players[i].player_status == ePlayer_status_not_responding) ? 247 : 4),
GetMiscString(77 + gNet_players[i].player_status));
if (gNet_players[i].player_status == ePlayer_status_ready) {
number_ready++;
}
}
if (gNet_mode == eNet_mode_host && gNumber_of_net_players == number_ready && gNumber_of_net_players > 1 && (!gNo_races_yet || gNumber_of_net_players == 6)) {
SignalToStartRace();
gSynch_race_start = 1;
}
}
// IDA: int __usercall NetSynchStartDone@<EAX>(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>, int pGo_ahead@<EBX>, int pEscaped@<ECX>, int pTimed_out)
int NetSynchStartDone(int pCurrent_choice, int pCurrent_mode, int pGo_ahead, int pEscaped, int pTimed_out) {
LOG_TRACE("(%d, %d, %d, %d, %d)", pCurrent_choice, pCurrent_mode, pGo_ahead, pEscaped, pTimed_out);
NOT_IMPLEMENTED();
if (pEscaped) {
pCurrent_choice = -1;
} else if (pCurrent_choice == 0) {
gProgram_state.prog_status = eProg_idling;
}
return pCurrent_choice;
}
// IDA: int __usercall NetSynchStartGoAhead@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
int NetSynchStartGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
NOT_IMPLEMENTED();
if (*pCurrent_choice == 0 || (gNet_mode == eNet_mode_host && *pCurrent_choice >= 0)) {
if (*pCurrent_choice == 0) {
gProgram_state.prog_status = eProg_idling;
return 1;
} else if (gNet_mode == eNet_mode_host && *pCurrent_choice == 1) {
if (gNumber_of_net_players <= 1) {
DRS3StartSound(gEffects_outlet, 3100);
return 0;
} else {
SignalToStartRace();
gSynch_race_start = 1;
gNo_races_yet = 0;
return 1;
}
} else {
return 1;
}
} else {
DRS3StartSound(gEffects_outlet, 3100);
return 0;
}
}
// IDA: int __usercall ExitWhenReady@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
int ExitWhenReady(int* pCurrent_choice, int* pCurrent_mode) {
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
NOT_IMPLEMENTED();
if (!gSynch_race_start && gProgram_state.prog_status != eProg_game_starting) {
if (gProgram_state.prog_status == eProg_idling) {
*pCurrent_choice = 0;
return 1;
} else {
return 0;
}
} else {
*pCurrent_choice = 1;
return 1;
}
}
// IDA: tSO_result __usercall NetSynchRaceStart2@<EAX>(tNet_synch_mode pMode@<EAX>)
tSO_result NetSynchRaceStart2(tNet_synch_mode pMode) {
static tFlicette flicker_on_hf[2];
static tFlicette flicker_off_hf[2];
static tFlicette push_hf[2];
static tMouse_area mouse_areas_hf[2];
static tInterface_spec interface_spec_hf;
static tFlicette flicker_on_hs[1];
static tFlicette flicker_off_hs[1];
static tFlicette push_hs[1];
static tMouse_area mouse_areas_hs[1];
static tInterface_spec interface_spec_hs;
static tFlicette flicker_on_c[1];
static tFlicette flicker_off_c[1];
static tFlicette push_c[1];
static tMouse_area mouse_areas_c[1];
static tInterface_spec interface_spec_c;
static tFlicette flicker_on_hf[2] = {
{ 321, { 219, 112 }, { 172, 362 } },
{ 321, { 39, 480 }, { 172, 379 } },
};
static tFlicette flicker_off_hf[2] = {
{ 322, { 219, 112 }, { 172, 362 } },
{ 322, { 39, 480 }, { 172, 379 } },
};
static tFlicette push_hf[2] = {
{ 206, { 219, 112 }, { 172, 362 } },
{ 205, { 39, 480 }, { 172, 379 } },
};
static tMouse_area mouse_areas_hf[2] = {
{ { 219, 480 }, { 172, 379 }, { 282, 182 }, { 192, 427 }, 0, 0, 0, NULL },
{ { 39, 112 }, { 172, 362 }, { 102, 182 }, { 192, 379 }, 1, 0, 0, NULL },
};
static tInterface_spec interface_spec_hf = {
0,
203,
0,
0,
0,
0,
8,
{ -1, 0 },
{ 1, 0 },
{ 0, 0 },
{ 1, 0 },
{ NULL, NULL },
{ -1, 0 },
{ 1, 0 },
{ 0, 0 },
{ 1, 0 },
{ NULL, NULL },
{ -1, 0 },
{ 1, 0 },
{ 0, 0 },
{ 1, 0 },
{ NULL, NULL },
{ -1, 0 },
{ 1, 0 },
{ 0, 0 },
{ 1, 0 },
{ NULL, NULL },
{ 1, 1 },
{ NetSynchStartGoAhead, NetSynchStartGoAhead },
{ 1, 1 },
{ NULL, NULL },
ExitWhenReady,
NetSynchStartDraw,
0,
NULL,
NetSynchStartStart,
NetSynchStartDone,
0,
{ 0, 0 },
NULL,
-1,
1,
COUNT_OF(flicker_on_hf),
flicker_on_hf,
flicker_off_hf,
push_hf,
COUNT_OF(mouse_areas_hf),
mouse_areas_hf,
0,
NULL,
};
static tFlicette flicker_on_hs[1] = {
{ 321, { 219, 112 }, { 172, 362 } },
};
static tFlicette flicker_off_hs[1] = {
{ 322, { 219, 112 }, { 172, 362 } },
};
static tFlicette push_hs[1] = {
{ 206, { 219, 112 }, { 172, 362 } },
};
static tMouse_area mouse_areas_hs[1] = {
{ { 219, 480 }, { 172, 379 }, { 282, 182 }, { 192, 427 }, 0, 0, 0, NULL },
};
static tInterface_spec interface_spec_hs = {
0, 209, 0, 0, 0, 0, 8,
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
{ 1, 1 }, { NetSynchStartGoAhead, NetSynchStartGoAhead }, { 1, 1 }, { NULL, NULL },
ExitWhenReady, NetSynchStartDraw, 0, NULL, NetSynchStartStart, NetSynchStartDone, 0, { 0, 0 },
NULL, -1, 1,
COUNT_OF(flicker_on_hs), flicker_on_hs, flicker_off_hs, push_hs,
COUNT_OF(mouse_areas_hs), mouse_areas_hs, 0, NULL
};
static tFlicette flicker_on_c[1] = {
{ 321, { 219, 112 }, { 172, 362 } },
};
static tFlicette flicker_off_c[1] = {
{ 322, { 219, 112 }, { 172, 362 } },
};
static tFlicette push_c[1] = {
{ 207, { 219, 112 }, { 172, 362 } },
};
static tMouse_area mouse_areas_c[1] = {
{ { 219, 112 }, { 172, 362 }, { 282, 182 }, { 192, 379 }, 0, 0, 0, NULL },
};
static tInterface_spec interface_spec_c = {
0, 204, 0, 0, 0, 0, 8,
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
{ 1, 1 }, { NetSynchStartGoAhead, NetSynchStartGoAhead }, { 1, 1 }, { NULL, NULL },
ExitWhenReady, NetSynchStartDraw, 0, NULL, NetSynchStartStart, NetSynchStartDone, 0, { 0, 0 },
NULL, -1, 1,
COUNT_OF(flicker_on_c), flicker_on_c, flicker_off_c, push_c,
COUNT_OF(mouse_areas_c), mouse_areas_c, 0, NULL
};
int result;
LOG_TRACE("(%d)", pMode);
NOT_IMPLEMENTED();
if (pMode != eNet_synch_client) {
if (gCurrent_net_game->status.stage == eNet_game_starting) {
gCurrent_net_game->status.stage = eNet_game_ready;
}
SetUpNetCarPositions();
// gNet_synch_start = PDGetTotalTime();
}
TurnOnPaletteConversion();
switch (pMode) {
case eNet_synch_host_first:
result = DoInterfaceScreen(&interface_spec_hf, 0, 1);
break;
case eNet_synch_host_subsequent:
result = DoInterfaceScreen(&interface_spec_hs, 0, -1);
break;
case eNet_synch_client:
result = DoInterfaceScreen(&interface_spec_c, 0, -1);
break;
default:
break;
}
TurnOffPaletteConversion();
FadePaletteDown();
if (result > -2 && result < 1) {
NetLeaveGame(gCurrent_net_game);
}
return eSO_continue;
}
// IDA: tSO_result __cdecl NetSynchRaceStart()
tSO_result NetSynchRaceStart(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
SuspendPendingFlic();
if (gNet_mode == eNet_mode_host) {
if (gNo_races_yet) {
return NetSynchRaceStart2(eNet_synch_host_first);
} else {
return NetSynchRaceStart2(eNet_synch_host_subsequent);
}
} else {
return NetSynchRaceStart2(eNet_synch_client);
}
}

View File

@ -395,7 +395,31 @@ int PickNetRace(int pCurrent_race, tNet_sequence_type pNet_race_sequence) {
int most_seldom_seen;
int races_to_pick_from[50];
LOG_TRACE("(%d, %d)", pCurrent_race, pNet_race_sequence);
NOT_IMPLEMENTED();
if (pNet_race_sequence == eNet_sequence_sequential) {
pCurrent_race++;
if (pCurrent_race >= gNumber_of_races) {
pCurrent_race = 0;
}
} else {
most_seldom_seen = 10000;
for (i = 0; i < gNumber_of_races; i++) {
if (gRace_list[i].been_there_done_that < most_seldom_seen) {
most_seldom_seen = gRace_list[i].been_there_done_that;
}
}
races_count = 0;
for (i = 0; i < gNumber_of_races; i++) {
if (gRace_list[i].been_there_done_that == most_seldom_seen && (i != pCurrent_race)) {
races_to_pick_from[races_count] = i;
races_count++;
}
}
new_index = IRandomBetween(0, races_count - 1);
pCurrent_race = races_to_pick_from[new_index];
gRace_list[pCurrent_race].been_there_done_that++;
}
return pCurrent_race;
}
// IDA: void __cdecl SwapNetCarsLoad()
@ -445,7 +469,7 @@ void DoGame(void) {
StartLoadingScreen();
gProgram_state.prog_status = eProg_game_ongoing;
second_select_race = 0;
if (gNet_mode_of_last_game == gNet_mode) {
if (gNet_mode == gNet_mode_of_last_game) {
PrintMemoryDump(0, "BEFORE START RACE SCREEN");
SelectOpponents(&gCurrent_race);
if (gNet_mode != eNet_mode_none) {

View File

@ -479,7 +479,6 @@ br_uint_32 DRPixelmapLoadMany(char* pFile_name, br_pixelmap** pPixelmaps, br_uin
int i;
br_uint_8 lobyte;
LOG_TRACE("(\"%s\", %p, %d)", pFile_name, pPixelmaps, pNum);
number_loaded = BrPixelmapLoadMany(pFile_name, pPixelmaps, pNum);
for (i = 0; i < number_loaded; i++) {
the_map = pPixelmaps[i];

View File

@ -453,6 +453,42 @@ enum {
kFatalError_RandomNumberOutOfRange_S = 116,
};
enum {
NETMSGID_SENDMEDETAILS = 0x00,
NETMSGID_DETAILS = 0x01,
NETMSGID_JOIN = 0x02,
NETMSGID_NEWPLAYERLIST = 0x03,
NETMSGID_GUARANTEEREPLY = 0x04,
NETMSGID_CARDETAILSREQ = 0x05,
NETMSGID_CARDETAILS = 0x06,
NETMSGID_LEAVE = 0x07,
NETMSGID_HOSTICIDE = 0x08,
NETMSGID_RACEOVER = 0x09,
NETMSGID_STATUSREPORT = 0x0a,
NETMSGID_STARTRACE = 0x0b,
NETMSGID_HEADUP = 0x0c,
NETMSGID_HOSTQUERY = 0x0d,
NETMSGID_HOSTREPLY = 0x0e,
NETMSGID_MECHANICS = 0x0f,
NETMSGID_NONCAR_INFO = 0x10,
NETMSGID_TIMESYNC = 0x11,
NETMSGID_CONFIRM = 0x12,
NETMSGID_DISABLECAR = 0x13,
NETMSGID_ENABLECAR = 0x14,
NETMSGID_POWERUP = 0x15,
NETMSGID_RECOVER = 0x16,
NETMSGID_SCORES = 0x17,
NETMSGID_WASTED = 0x18,
NETMSGID_PEDESTRIAN = 0x19,
NETMSGID_GAMEPLAY = 0x1a,
NETMSGID_NONCARPOSITION = 0x1b,
NETMSGID_COPINFO = 0x1c,
NETMSGID_GAMESCORES = 0x1d,
NETMSGID_OILSPILL = 0x1e,
NETMSGID_CRUSHPOINT = 0x1f,
NETMSGID_NONE = 0x20,
};
#define FONT_TYPEABLE 0
#define FONT_ORANGHED 1
#define FONT_BLUEHEAD 2

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,16 @@
#include "pd/net.h"
#include "errors.h"
#include "globvrpb.h"
#include "harness/hooks.h"
#include "harness/trace.h"
#include "network.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#ifdef __DOS__
tU32 gNetwork_init_flags;
tPD_net_game_info* gJoinable_games;
int gMatts_PC;
@ -26,9 +32,11 @@ tU8* gSend_packet_ptr;
W32 gSend_segment;
tU8* gListen_packet;
tU8* gListen_packet_ptr;
size_t gMsg_header_strlen;
int gNumber_of_networks;
int gNumber_of_hosts;
tRM_info RMI;
_IPX_HEADER gLast_received_IPX_header;
tU16 gSocket_number_network_order;
@ -42,7 +50,7 @@ tU16 gSend_selector;
/*static*/ int GetSocketNumberFromProfileFile(void);
/*static*/ tU32 EthernetAddressToU32(_IPX_LOCAL_TARGET* pAddr_ipx);
/*static*/ void NetNowIPXLocalTarget2String(char* pString, _IPX_LOCAL_TARGET* pSock_addr_ipx);
/*static*/ int GetMessageTypeFromMessage(char* pMessage_str) ;
/*static*/ int GetMessageTypeFromMessage(char* pMessage_str);
/*static*/ int SameEthernetAddress(_IPX_LOCAL_TARGET* pAddr_ipx1, _IPX_LOCAL_TARGET* pAddr_ipx2);
/*static*/ _IPX_LOCAL_TARGET* GetIPXAddrFromPlayerID(tPlayer_ID pPlayer_id);
/*static*/ void MakeMessageToSend(int pMessage_type);
@ -297,6 +305,7 @@ int PDNetInitialise(void) {
tU32 netnum;
char str[256];
int mess_num;
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
@ -326,7 +335,7 @@ int PDNetGetNextJoinGame(tNet_game_details* pGame, int pIndex) {
int j;
int number_of_hosts_has_changed;
char str[256];
LOG_TRACE("(%p, %d)", pGame, pIndex);
LOG_TRACE9("(%p, %d)", pGame, pIndex);
NOT_IMPLEMENTED();
}
@ -374,35 +383,7 @@ tPlayer_ID PDNetExtractPlayerID(tNet_game_details* pDetails) {
// IDA: void __usercall PDNetObtainSystemUserName(char *pName@<EAX>, int pMax_length@<EDX>)
void PDNetObtainSystemUserName(char* pName, int pMax_length) {
#ifdef _WIN32
uint32_t size;
char buffer[16];
int result;
#endif
dr_dprintf("PDNetObtainSystemUserName()\n");
// todo
#if 0
size = COUNT_OF(buffer);
result = GetComputerNameA(buffer, &size);
if (result == 0) {
LOG_WARN("GetComputerNameA failed with code=%u", GetLastError());
buffer[0] = '\0';
size = 0;
}
strncpy(pName, buffer, pMax_length - 1);
pName[pMax_length - 1] = '\0';
while (1) {
pName = strpbrk(pName, "_=(){}[]<>!$%^&*/:@~;'#,?\\|`\"");
if (pName == NULL || *pName == '\0') {
break;
}
*pName = '-';
}
#else
strcpy(pName, "Ron Turn");
#endif
}
// IDA: int __usercall PDNetSendMessageToPlayer@<EAX>(tNet_game_details *pDetails@<EAX>, tNet_message *pMessage@<EDX>, tPlayer_ID pPlayer@<EBX>)
@ -417,6 +398,7 @@ int PDNetSendMessageToPlayer(tNet_game_details* pDetails, tNet_message* pMessage
int PDNetSendMessageToAllPlayers(tNet_game_details* pDetails, tNet_message* pMessage) {
char str[256];
int i;
int r; // Added by dethrace
LOG_TRACE("(%p, %p)", pDetails, pMessage);
NOT_IMPLEMENTED();
}
@ -472,3 +454,5 @@ int PDNetGetHeaderSize(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
#endif

View File

@ -0,0 +1,193 @@
#include "dr_types.h"
#ifdef __DOS__
typedef struct _tagIPX_HEADER {
unsigned short wChecksum;
unsigned short wLength;
unsigned char bTransportControl;
unsigned char bPacketType;
unsigned char bDestNetworkNumber[4];
unsigned char bDestNetworkNode[6];
unsigned short wDestNetworkSocket;
unsigned char bSourceNetworkNumber[4];
unsigned char bSourceNetworkNode[6];
unsigned short wSourceNetworkSocket;
} _IPX_HEADER;
typedef struct _PACKET {
char* pData;
unsigned short wLength;
} _PACKET;
typedef struct _REAL_PACKET {
short wOffset;
short wSegment;
unsigned short wLength;
} _REAL_PACKET;
typedef struct _ECB_PACKET {
_PACKET sPacket;
_REAL_PACKET sRealPacket;
} _ECB_PACKET;
typedef struct _tagIPX_ECB {
char* pLinkAddress;
char* pESRRoutine;
unsigned char bInUse;
unsigned char bCompletionCode;
unsigned short wSocket;
unsigned short wConnectionID;
unsigned short wWorkSpace;
unsigned char bDriverWorkSpace[12];
unsigned char bImmediateAddress[6];
unsigned short wPacketCount;
_ECB_PACKET sPacket[2];
} _IPX_ECB;
typedef struct _tagIPX_INTERNET_ADDR {
unsigned char bNetwork[4];
unsigned char bNode[6];
} _IPX_INTERNET_ADDR;
typedef struct _tagIPX_NETWORK_ADDR {
_IPX_INTERNET_ADDR sInternetAddr;
unsigned char bSocket[2];
} _IPX_NETWORK_ADDR;
typedef struct _tagIPX_LOCAL_TARGET {
_IPX_INTERNET_ADDR sInternetAddr;
unsigned char bImmediate[6];
} _IPX_LOCAL_TARGET;
typedef struct _tagIPX_ELEMENT {
unsigned short wFlags;
unsigned short wOffset;
_IPX_HEADER sHeader;
_IPX_ECB sECB;
_IPX_ECB* pECB;
_IPX_HEADER* pIPXHeader;
char* pHeader;
unsigned short wHSize;
} _IPX_ELEMENT;
typedef struct _PROT_PTR {
char* pData;
} _PROT_PTR;
typedef struct _REAL_PTR {
short wOffset;
short wSegment;
} _REAL_PTR;
typedef struct _PTR {
_PROT_PTR sPointer;
_REAL_PTR sRealPtr;
} _PTR;
typedef struct _tag_NETBIOS_NCB {
unsigned char bCommand;
unsigned char bReturnCode;
unsigned char bLocalSession;
unsigned char bNetworkNameNumber;
_PTR sPtr;
unsigned short wLength;
unsigned char bCallName[16];
unsigned char bName[16];
unsigned char bReceiveTimeOut;
unsigned char bSendTimeOut;
char* pPostFunction;
unsigned char bAdapter;
unsigned char bCompletionCode;
unsigned char bReserve[14];
} _NETBIOS_NCB;
typedef struct _tagNETBIOS_ADAPTER_STATUS {
unsigned char bCardID[6];
unsigned char bReleaseLevel;
unsigned char bReserved1;
unsigned char bTypeOfAdapter;
unsigned char bOldOrNewParameters;
unsigned short wReportingPeriodMinutes;
unsigned short wFrameRejectReceivedCount;
unsigned short wFrameRejectSentCount;
unsigned short wReceivedDataFrameErrors;
unsigned short wUnsuccessfulTransmissions;
long dwGoodTransmissions;
long dwGoodReceptions;
unsigned short wRetransmissions;
unsigned short wExhaustedResourceCount;
unsigned short wT1TimerExpiredCount;
unsigned short wTITimerExpiredCount;
unsigned char bReserved2[4];
unsigned short wAvailableNCBS;
unsigned short wMaxNCBSConfigured;
unsigned short wMaxNCBSPossible;
unsigned short wBufferOrStationBusyCount;
unsigned short wMaxDatagramSize;
unsigned short wPendingSessions;
unsigned short wMaxSessionsConfigured;
unsigned short wMaxSessionsPossible;
unsigned short wMaxFrameSize;
unsigned short wNameCount;
struct {
unsigned char bName[16];
unsigned char bNameNumber;
unsigned char bNameStatus;
} sNameTable[20];
} _NETBIOS_ADAPTER_STATUS;
typedef struct _tagNETBIOS_ELEMENT {
unsigned short wFlags;
unsigned short wOffset;
_NETBIOS_NCB sNCB;
_NETBIOS_NCB* pNCB;
char* pHeader;
unsigned short wHSize;
} _NETBIOS_ELEMENT;
typedef struct _tagNETBIOS_LOCAL_TARGET {
unsigned char bNode[16];
} _NETBIOS_LOCAL_TARGET;
typedef struct _tagXFER_BLOCK_HEADER {
unsigned int wSequence;
unsigned int wType;
unsigned int wID;
unsigned int wLength;
unsigned int wNode;
unsigned int wUser1;
} _XFER_BLOCK_HEADER;
typedef struct _NETNOW_NODE_ADDR {
_IPX_LOCAL_TARGET sIPX;
_NETBIOS_LOCAL_TARGET sNETBIOS;
} _NETNOW_NODE_ADDR;
typedef struct _tagRMI_REGS _RMI_REGS;
typedef struct _tagBREGS _HMI_BREGS;
typedef struct _tagWREGS _HMI_WREGS;
typedef struct _tagDREGS _HMI_DREGS;
typedef struct _tagSREGS _HMI_SREGS;
typedef struct _tagIPX_HEADER _IPX_HEADER;
typedef struct _tagIPX_ECB _IPX_ECB;
typedef struct _tagIPX_INTERNET_ADDR _IPX_INTERNET_ADDR;
typedef struct _tagIPX_NETWORK_ADDR _IPX_NETWORK_ADDR;
typedef struct _tagIPX_LOCAL_TARGET _IPX_LOCAL_TARGET;
typedef struct _tagIPX_ELEMENT _IPX_ELEMENT;
typedef struct _tag_NETBIOS_NCB _NETBIOS_NCB;
typedef struct _tagNETBIOS_ADAPTER_STATUS _NETBIOS_ADAPTER_STATUS;
typedef struct _tagNETBIOS_ELEMENT _NETBIOS_ELEMENT;
typedef struct _tagNETBIOS_LOCAL_TARGET _NETBIOS_LOCAL_TARGET;
typedef struct _tagXFER_BLOCK_HEADER _XFER_BLOCK_HEADER;
typedef struct tPD_net_player_info {
_IPX_LOCAL_TARGET addr_ipx;
} tPD_net_player_info;
typedef struct tPD_net_game_info {
_IPX_LOCAL_TARGET addr_ipx;
tU32 last_response;
} tPD_net_game_info;
#endif

View File

@ -137,13 +137,16 @@ void PDInitialiseSystem(void) {
}
// IDA: void __cdecl PDShutdownSystem()
void PDShutdownSystem(void) {
void PDShutdownSystem() {
static int been_here = 0; // Added by dethrace
LOG_TRACE("()");
Harness_Hook_PDShutdownSystem();
CloseDiagnostics();
exit(0);
if (!been_here) {
Harness_Hook_PDShutdownSystem();
} else {
LOG_WARN("recursion detected => force exit");
exit(8);
}
}
// IDA: void __cdecl PDSaveOriginalPalette()

View File

@ -0,0 +1,668 @@
#include "pd/net.h"
#include "brender/brender.h"
#include "dr_types.h"
#include "errors.h"
#include "globvrpb.h"
#include "harness/config.h"
#include "harness/hooks.h"
#include "harness/trace.h"
#include "harness/winsock.h"
#include "network.h"
#include "pd/net.h"
#include "pd/sys.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
// dethrace: have switched out IPX implementation for IP
tU32 gNetwork_init_flags;
tPD_net_game_info* gJoinable_games;
int gMatts_PC;
tU16 gSocket_number_pd_format;
//_IPX_ELEMENT gListen_elements[16];
char gLocal_ipx_addr_string[32];
//_IPX_ELEMENT gSend_elements[16];
struct sockaddr_in* gLocal_addr_ipx;
char gReceive_buffer[512];
tPD_net_player_info gRemote_net_player_info;
struct sockaddr_in* gBroadcast_addr_ipx;
tPD_net_player_info gLocal_net_player_info;
char gSend_buffer[512];
tIPX_netnum gNetworks[16];
struct sockaddr_in* gRemote_addr_ipx;
tU8* gSend_packet;
// W32 gListen_segment;
tU8* gSend_packet_ptr;
// W32 gSend_segment;
tU8* gListen_packet;
tU8* gListen_packet_ptr;
size_t gMsg_header_strlen;
int gNumber_of_networks;
int gNumber_of_hosts;
//_IPX_HEADER gLast_received_IPX_header;
tU16 gSocket_number_network_order;
// unsigned short gECB_offset;
tU16 gListen_selector;
tU16 gSend_selector;
struct sockaddr_in gLocal_addr;
struct sockaddr_in gRemote_addr;
struct sockaddr_in gBroadcast_addr;
struct sockaddr_in gLast_received_addr;
int gSocket;
#define MESSAGE_HEADER_STR "CW95MSG"
#define JOINABLE_GAMES_CAPACITY 16
// IDA: void __cdecl ClearupPDNetworkStuff()
void ClearupPDNetworkStuff(void) {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
// IDA: void __usercall MATTMessageCheck(char *pFunction_name@<EAX>, tNet_message *pMessage@<EDX>, int pAlleged_size@<EBX>)
void MATTMessageCheck(char* pFunction_name, tNet_message* pMessage, int pAlleged_size) {
LOG_TRACE("(\"%s\", %p, %d)", pFunction_name, pMessage, pAlleged_size);
NOT_IMPLEMENTED();
}
// IDA: int __usercall GetProfileText@<EAX>(char *pDest@<EAX>, int pDest_len@<EDX>, char *pFname@<EBX>, char *pKeyname@<ECX>)
int GetProfileText(char* pDest, int pDest_len, char* pFname, char* pKeyname) {
FILE* fp;
char in_buf[256];
int i;
int j;
int len;
LOG_TRACE("(\"%s\", %d, \"%s\", \"%s\")", pDest, pDest_len, pFname, pKeyname);
NOT_IMPLEMENTED();
}
// IDA: int __cdecl GetSocketNumberFromProfileFile()
int GetSocketNumberFromProfileFile(void) {
char str[256];
int sscanf_res;
tU32 socknum;
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
// tU32 EthernetAddressToU32(SOCKADDR_IPX_* pAddr_ipx) {
// LOG_TRACE("(%p)", pAddr_ipx);
// NOT_IMPLEMENTED();
// }
void NetNowIPXLocalTarget2String(char* pString, struct sockaddr_in* pSock_addr_ipx) {
LOG_TRACE("(\"%s\", %p)", pString, pSock_addr_ipx);
char portbuf[10];
inet_ntop(AF_INET, &pSock_addr_ipx->sin_addr, pString, 32);
sprintf(portbuf, ":%d", ntohs(pSock_addr_ipx->sin_port));
strcat(pString, portbuf);
}
// IDA: int __usercall GetMessageTypeFromMessage@<EAX>(char *pMessage_str@<EAX>)
int GetMessageTypeFromMessage(char* pMessage_str) {
char* real_msg;
int msg_type_int;
LOG_TRACE("(\"%s\")", pMessage_str);
real_msg = &pMessage_str[4];
msg_type_int = 0;
// FIXME: "CW95MSG" value is used in and depends on platform
if (strncmp(real_msg, MESSAGE_HEADER_STR, gMsg_header_strlen) == 0) {
if (isdigit(real_msg[gMsg_header_strlen])) {
msg_type_int = real_msg[gMsg_header_strlen] - '0';
}
if (msg_type_int != 0 && msg_type_int < 3) {
return msg_type_int;
}
}
return 999;
}
int SameEthernetAddress(struct sockaddr_in* pAddr_ipx1, struct sockaddr_in* pAddr_ipx2) {
LOG_TRACE("(%p, %p)", pAddr_ipx1, pAddr_ipx2);
return memcmp(pAddr_ipx1, pAddr_ipx2, sizeof(struct sockaddr_in)) == 0;
}
/*SOCKADDR_IPX_* */ void* GetIPXAddrFromPlayerID(tPlayer_ID pPlayer_id) {
int i;
tU8* nodenum;
NOT_IMPLEMENTED();
}
// IDA: void __usercall MakeMessageToSend(int pMessage_type@<EAX>)
void MakeMessageToSend(int pMessage_type) {
LOG_TRACE("(%d)", pMessage_type);
#ifdef DETHRACE_FIX_BUGS
sprintf(gSend_buffer, "XXXX%s%1d", MESSAGE_HEADER_STR, pMessage_type);
#else
sprintf(gSend_buffer, "XXXX%s%0.1d", MESSAGE_HEADER_STR, pMessage_type);
#endif
}
// IDA: int __cdecl ReceiveHostResponses()
int ReceiveHostResponses(void) {
char str[256];
int i;
int already_registered;
LOG_TRACE("()");
char addr_string[32];
unsigned int sa_len;
int wsa_error;
sa_len = sizeof(gRemote_addr);
while (1) {
if (recvfrom(gSocket, gReceive_buffer, sizeof(gReceive_buffer), 0, (struct sockaddr*)&gRemote_addr, &sa_len) == -1) {
break;
}
NetNowIPXLocalTarget2String(addr_string, gRemote_addr_ipx);
dr_dprintf("ReceiveHostResponses(): Received string '%s' from %s", gReceive_buffer, addr_string);
if (SameEthernetAddress(gLocal_addr_ipx, gRemote_addr_ipx)) {
dr_dprintf("*** Discounting the above 'cos we sent it ***");
continue;
}
if (GetMessageTypeFromMessage(gReceive_buffer) != 2) {
dr_dprintf("*** Discounting the above 'cos it's not a host reply ***");
continue;
}
dr_dprintf("*** It's a host reply! ***");
already_registered = 0;
for (i = 0; i < gNumber_of_hosts; i++) {
if (SameEthernetAddress(&gJoinable_games[i].addr_in, gRemote_addr_ipx)) {
already_registered = 1;
break;
}
}
if (already_registered) {
dr_dprintf("That game already registered");
gJoinable_games[i].last_response = PDGetTotalTime();
} else {
dr_dprintf("Adding joinable game to slot #%d", gNumber_of_hosts);
gJoinable_games[gNumber_of_hosts].addr_in = *gRemote_addr_ipx;
gJoinable_games[gNumber_of_hosts].last_response = PDGetTotalTime();
gNumber_of_hosts++;
dr_dprintf("Number of games found so far: %d", gNumber_of_hosts);
}
if (gNumber_of_hosts) {
dr_dprintf("Currently registered net games:");
for (i = 0; i < gNumber_of_hosts; i++) {
NetNowIPXLocalTarget2String(str, &gJoinable_games[i].addr_in);
dr_dprintf("%d: Host addr %s", i, str);
}
}
}
wsa_error = WSAGetLastError() != WSAEWOULDBLOCK;
if (wsa_error == 0) {
return 1;
}
dr_dprintf("ReceiveHostResponses(): Error on recvfrom() - WSAGetLastError=%d", wsa_error);
return 0;
}
// IDA: int __cdecl BroadcastMessage()
int BroadcastMessage(void) {
int i;
int errors;
char broadcast_addr_string[32];
char* real_msg;
LOG_TRACE("()");
errors = 0;
for (i = 0; i < gNumber_of_networks; i++) {
//*(_DWORD*)gBroadcast_addr_ipx->sa_netnum = gNetworks[i];
NetNowIPXLocalTarget2String(broadcast_addr_string, gBroadcast_addr_ipx);
dr_dprintf("Broadcasting on address '%s'", broadcast_addr_string);
if (sendto(gSocket, gSend_buffer, strlen(gSend_buffer) + 1, 0, (struct sockaddr*)&gBroadcast_addr, sizeof(gBroadcast_addr)) == -1) {
dr_dprintf("BroadcastMessage(): Error on sendto() - WSAGetLastError=%d", WSAGetLastError());
errors = 1;
}
}
return errors == 0;
}
// IDA: int __cdecl PDNetInitialise()
int PDNetInitialise(void) {
tU32 timenow;
char profile_string[32];
char key_name[32];
int sscanf_res;
int i;
tU32 netnum;
char str[256];
int mess_num;
struct linger so_linger;
unsigned int sa_len;
WSADATA wsadata;
LOG_TRACE("()");
sa_len = sizeof(struct sockaddr_in);
dr_dprintf("PDNetInitialise()");
int ipx_socket_num = 12286;
// Dont bother to handle network.ini
// if (gWin32_should_load_network_ini) {
// if (GetPrivateProfileStringA(
// "Network",
// "IPXSocket",
// Default,
// (LPSTR)ReturnedString,
// 0x20u,
// gNetwork_profile_fname)) {
// v11 = sscanf(ReturnedString, "%x", &v9);
// if (v11) {
// if (v11 != -1) {
// dr_dprintf("New IPX socket %4.4x", v9);
// ipx_socket_num = sub_454930(v9);
// }
// }
// }
// }
gLocal_addr_ipx = &gLocal_addr;
gRemote_addr_ipx = &gRemote_addr;
gBroadcast_addr_ipx = &gBroadcast_addr;
memset(&gLocal_addr, 0, sizeof(struct sockaddr_in));
memset(&gRemote_addr, 0, sizeof(struct sockaddr_in));
memset(&gBroadcast_addr, 0, sizeof(struct sockaddr_in));
// gLocal_addr_ipx->sa_family = AF_IPX;
// gRemote_addr_ipx->sa_family = AF_IPX;
// gBroadcast_addr_ipx->sa_family = AF_IPX;
// gLocal_addr_ipx->sa_socket = ipx_socket_num;
// gRemote_addr_ipx->sa_socket = ipx_socket_num;
// gBroadcast_addr_ipx->sa_socket = ipx_socket_num;
// // IPX broadcast
// gBroadcast_addr_ipx->sa_nodenum[0] = -1;
// gBroadcast_addr_ipx->sa_nodenum[1] = -1;
// gBroadcast_addr_ipx->sa_nodenum[2] = -1;
// gBroadcast_addr_ipx->sa_nodenum[3] = -1;
// gBroadcast_addr_ipx->sa_nodenum[4] = -1;
// gBroadcast_addr_ipx->sa_nodenum[5] = -1;
gLocal_addr.sin_family = AF_INET;
gLocal_addr.sin_port = htons(12286);
gLocal_addr.sin_addr.s_addr = INADDR_ANY;
gRemote_addr.sin_family = AF_INET;
gRemote_addr.sin_port = htons(12286);
gBroadcast_addr.sin_family = AF_INET;
gBroadcast_addr.sin_port = htons(12286);
// original code was using MAKEWORD(1, 1)
if (WSAStartup(MAKEWORD(2, 2), &wsadata) == -1) {
dr_dprintf("PDNetInitialise(): WSAStartup() failed");
return -1;
}
// gSocket = socket(6, 2, 1000);
gSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (gSocket == -1) {
dr_dprintf("PDNetInitialise(): Failed to create socket - WSAGetLastError=%d", WSAGetLastError());
WSACleanup();
return -1;
}
int broadcast = 1;
setsockopt(gSocket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
so_linger.l_onoff = 1;
so_linger.l_linger = 0;
setsockopt(gSocket, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger));
unsigned long nobio = 1;
if (ioctlsocket(gSocket, FIONBIO, &nobio) == -1) {
dr_dprintf("Error on ioctlsocket() - WSAGetLastError=%d", WSAGetLastError());
closesocket(gSocket);
WSACleanup();
return -1;
}
if (harness_game_config.no_bind == 0) {
if (bind(gSocket, (struct sockaddr*)&gLocal_addr, sizeof(gLocal_addr)) == -1) {
dr_dprintf("Error on bind() - WSAGetLastError=%d", WSAGetLastError());
closesocket(gSocket);
WSACleanup();
return -1;
}
}
int res = getsockname(gSocket, (struct sockaddr*)&gLocal_addr, &sa_len);
NetNowIPXLocalTarget2String(gLocal_ipx_addr_string, gLocal_addr_ipx);
// gNetworks[0] = *(tIPX_netnum*)gLocal_addr_ipx->sa_netnum;
gNumber_of_networks = 1;
// if (gWin32_should_load_network_ini) {
// for (i = 1; i <= 15; ++i) {
// sprintf(KeyName, "%s%d", "Network", i);
// if (GetPrivateProfileStringA(
// "Network",
// KeyName,
// Default,
// (LPSTR)ReturnedString,
// 0x20u,
// gNetwork_profile_fname)) {
// v11 = sscanf(ReturnedString, "%x", &network_nbr);
// if (v11) {
// if (v11 != -1) {
// dr_dprintf("Found network number '%x' in INI file", network_nbr);
// gNetworks[gNumber_of_networks].bNetwork[0] = HIBYTE(network_nbr);
// gNetworks[gNumber_of_networks].bNetwork[1] = (network_nbr & 0xFF0000u) >> 16;
// gNetworks[gNumber_of_networks].bNetwork[2] = BYTE1(network_nbr);
// gNetworks[gNumber_of_networks].bNetwork[3] = network_nbr;
// if (gNetworks[gNumber_of_networks].bNetwork[0] != gLocal_addr_ipx->sa_netnum[0]
// || gNetworks[gNumber_of_networks].bNetwork[1] != gLocal_addr_ipx->sa_netnum[1]
// || gNetworks[gNumber_of_networks].bNetwork[2] != gLocal_addr_ipx->sa_netnum[2]
// || gNetworks[gNumber_of_networks].bNetwork[3] != gLocal_addr_ipx->sa_netnum[3]) {
// ++gNumber_of_networks;
// }
// }
// }
// }
// }
// dr_dprintf("Total networks = %d", gNumber_of_networks);
// }
// byte_536440 = *gLocal_addr_ipx;
dr_dprintf("Socket bound OK; local address is '%s'", gLocal_ipx_addr_string);
gMsg_header_strlen = 7;
if (strstr(gLocal_ipx_addr_string, "00a0240f9fac")) {
gMatts_PC = 1;
}
return 0;
}
// IDA: int __cdecl PDNetShutdown()
int PDNetShutdown(void) {
LOG_TRACE("()");
dr_dprintf("PDNetShutdown()");
if (gSocket != -1) {
closesocket(gSocket);
}
gSocket = -1;
return 0;
}
// IDA: void __cdecl PDNetStartProducingJoinList()
void PDNetStartProducingJoinList(void) {
LOG_TRACE("()");
dr_dprintf("PDNetStartProducingJoinList()");
gNumber_of_hosts = 0;
gJoinable_games = BrMemAllocate(sizeof(tPD_net_game_info) * JOINABLE_GAMES_CAPACITY, 0x80u);
if (gJoinable_games == NULL) {
PDFatalError("Can't allocate memory for joinable games");
}
}
// IDA: void __cdecl PDNetEndJoinList()
void PDNetEndJoinList(void) {
LOG_TRACE("()");
dr_dprintf("PDNetEndJoinList()");
if (gJoinable_games) {
BrMemFree(gJoinable_games);
}
gJoinable_games = NULL;
}
// IDA: int __usercall PDNetGetNextJoinGame@<EAX>(tNet_game_details *pGame@<EAX>, int pIndex@<EDX>)
int PDNetGetNextJoinGame(tNet_game_details* pGame, int pIndex) {
static tU32 next_broadcast_time = 0;
int i;
int j;
int number_of_hosts_has_changed;
char str[256];
LOG_TRACE9("(%p, %d)", pGame, pIndex);
dr_dprintf("PDNetGetNextJoinGame(): pIndex is %d", pIndex);
if (pIndex == 0) {
do {
number_of_hosts_has_changed = 0;
for (i = 0; i < gNumber_of_hosts; i++) {
if (gJoinable_games[i].last_response + 10000 < PDGetTotalTime()) {
number_of_hosts_has_changed = 1;
for (j = i; j < gNumber_of_hosts - 1; j++) {
memcpy(&gJoinable_games[j], &gJoinable_games[j + 1], sizeof(tPD_net_game_info));
}
}
}
if (number_of_hosts_has_changed) {
gNumber_of_hosts--;
}
} while (number_of_hosts_has_changed);
if (PDGetTotalTime() > next_broadcast_time) {
next_broadcast_time = PDGetTotalTime() + 3000;
MakeMessageToSend(1);
if (BroadcastMessage() == 0) {
dr_dprintf("PDNetGetNextJoinGame(): Error on BroadcastMessage()");
}
}
}
ReceiveHostResponses();
if (gNumber_of_hosts <= pIndex) {
return 0;
}
dr_dprintf("PDNetGetNextJoinGame(): Adding game.");
memcpy(&pGame->pd_net_info.addr_in, &gJoinable_games[pIndex].addr_in, sizeof(pGame->pd_net_info.addr_in));
return 1;
}
// IDA: void __usercall PDNetDisposeGameDetails(tNet_game_details *pDetails@<EAX>)
void PDNetDisposeGameDetails(tNet_game_details* pDetails) {
LOG_TRACE("(%p)", pDetails);
NOT_IMPLEMENTED();
}
// IDA: int __usercall PDNetHostGame@<EAX>(tNet_game_details *pDetails@<EAX>, char *pHost_name@<EDX>, void **pHost_address@<EBX>)
int PDNetHostGame(tNet_game_details* pDetails, char* pHost_name, void** pHost_address) {
LOG_TRACE("(%p, \"%s\", %p)", pDetails, pHost_name, pHost_address);
dr_dprintf("PDNetHostGame()");
*pHost_address = &gLocal_addr;
return 1;
}
// IDA: int __usercall PDNetJoinGame@<EAX>(tNet_game_details *pDetails@<EAX>, char *pPlayer_name@<EDX>)
int PDNetJoinGame(tNet_game_details* pDetails, char* pPlayer_name) {
LOG_TRACE("(%p, \"%s\")", pDetails, pPlayer_name);
dr_dprintf("PDNetJoinGame()");
return 0;
}
// IDA: void __usercall PDNetLeaveGame(tNet_game_details *pDetails@<EAX>)
void PDNetLeaveGame(tNet_game_details* pDetails) {
LOG_TRACE("(%p)", pDetails);
dr_dprintf("PDNetLeaveGame()");
}
// IDA: void __usercall PDNetHostFinishGame(tNet_game_details *pDetails@<EAX>)
void PDNetHostFinishGame(tNet_game_details* pDetails) {
LOG_TRACE("(%p)", pDetails);
dr_dprintf("PDNetHostFinishGame()");
}
// IDA: tU32 __usercall PDNetExtractGameID@<EAX>(tNet_game_details *pDetails@<EAX>)
tU32 PDNetExtractGameID(tNet_game_details* pDetails) {
LOG_TRACE("(%p)", pDetails);
dr_dprintf("PDNetExtractGameID()");
return ntohs(pDetails->pd_net_info.addr_in.sin_port); // PDGetTotalTime();
}
// IDA: tPlayer_ID __usercall PDNetExtractPlayerID@<EAX>(tNet_game_details *pDetails@<EAX>)
tPlayer_ID PDNetExtractPlayerID(tNet_game_details* pDetails) {
LOG_TRACE("(%p)", pDetails);
dr_dprintf("PDNetExtractPlayerID()");
return ntohs(gLocal_addr_ipx->sin_port);
}
// IDA: void __usercall PDNetObtainSystemUserName(char *pName@<EAX>, int pMax_length@<EDX>)
void PDNetObtainSystemUserName(char* pName, int pMax_length) {
int result;
char* found;
dr_dprintf("PDNetObtainSystemUserName()");
result = gethostname(pName, pMax_length);
if (result == 0) {
}
while (1) {
found = strpbrk(pName, "_=(){}[]<>!$%^&*/:@~;'#,?\\|`\"");
if (found == NULL) {
break;
}
*found = '-';
}
}
// IDA: int __usercall PDNetSendMessageToPlayer@<EAX>(tNet_game_details *pDetails@<EAX>, tNet_message *pMessage@<EDX>, tPlayer_ID pPlayer@<EBX>)
int PDNetSendMessageToPlayer(tNet_game_details* pDetails, tNet_message* pMessage, tPlayer_ID pPlayer) {
char str[256];
// SOCKADDR_IPX_* remote_addr_ipx;
LOG_TRACE("(%p, %p, %d)", pDetails, pMessage, pPlayer);
NOT_IMPLEMENTED();
}
// IDA: int __usercall PDNetSendMessageToAllPlayers@<EAX>(tNet_game_details *pDetails@<EAX>, tNet_message *pMessage@<EDX>)
int PDNetSendMessageToAllPlayers(tNet_game_details* pDetails, tNet_message* pMessage) {
char str[256];
int i;
LOG_TRACE("(%p, %p)", pDetails, pMessage);
for (i = 0; i < gNumber_of_net_players; ++i) {
if (i == gThis_net_player_index) {
continue;
}
if (sendto(gSocket, (const char*)pMessage, pMessage->overall_size, 0, (struct sockaddr*)&gNet_players[i].pd_net_info.addr_in, sizeof(gNet_players[i].pd_net_info.addr_in)) == -1) {
dr_dprintf("PDNetSendMessageToAllPlayers(): Error on sendto() - WSAGetLastError=%d", WSAGetLastError());
NetDisposeMessage(pDetails, pMessage);
return 1;
}
}
NetDisposeMessage(pDetails, pMessage);
return 0;
}
// IDA: tNet_message* __usercall PDNetGetNextMessage@<EAX>(tNet_game_details *pDetails@<EAX>, void **pSender_address@<EDX>)
tNet_message* PDNetGetNextMessage(tNet_game_details* pDetails, void** pSender_address) {
char* receive_buffer;
char str[256];
int msg_type;
LOG_TRACE("(%p, %p)", pDetails, pSender_address);
char addr_str[32];
unsigned int sa_len;
int res;
tNet_message* msg;
sa_len = sizeof(gRemote_addr);
msg = NetAllocateMessage(512);
receive_buffer = (char*)msg;
res = recvfrom(gSocket, receive_buffer, 512, 0, (struct sockaddr*)&gRemote_addr, &sa_len);
res = res != -1;
if (res == 0) {
res = WSAGetLastError() != WSAEWOULDBLOCK;
if (res) {
sprintf(str, "PDNetGetNextMessage(): Error on recvfrom() - WSAGetLastError=%d", res);
PDFatalError(str);
}
} else {
NetNowIPXLocalTarget2String(addr_str, gRemote_addr_ipx);
if (!SameEthernetAddress(gLocal_addr_ipx, gRemote_addr_ipx)) {
msg_type = GetMessageTypeFromMessage(receive_buffer);
switch (msg_type) {
case 1:
if (gNet_mode == eNet_mode_host) {
dr_dprintf("PDNetGetNextMessage(): Received '%s' from '%s', replying to joiner", receive_buffer, addr_str);
MakeMessageToSend(2);
if (sendto(gSocket, gSend_buffer, strlen(gSend_buffer) + 1, 0, (struct sockaddr*)&gRemote_addr, sizeof(gRemote_addr)) == -1) {
dr_dprintf("PDNetGetNextMessage(): Error on sendto() - WSAGetLastError=%d", WSAGetLastError());
}
}
break;
case 2:
// no-op
break;
default:
dr_dprintf("PDNetGetNextMessage(): res is %d, received message type %d from '%s', passing up", res, msg->contents.header.type, addr_str);
memcpy(&gLast_received_addr, gRemote_addr_ipx, sizeof(gLast_received_addr));
*pSender_address = &gLast_received_addr;
return msg;
}
}
}
msg->guarantee_number = 0;
NetDisposeMessage(pDetails, msg);
return 0;
}
// IDA: tNet_message* __usercall PDNetAllocateMessage@<EAX>(tU32 pSize@<EAX>, tS32 pSize_decider@<EDX>)
tNet_message* PDNetAllocateMessage(tU32 pSize, tS32 pSize_decider) {
LOG_TRACE("(%d, %d)", pSize, pSize_decider);
NOT_IMPLEMENTED();
}
// IDA: void __usercall PDNetDisposeMessage(tNet_game_details *pDetails@<EAX>, tNet_message *pMessage@<EDX>)
void PDNetDisposeMessage(tNet_game_details* pDetails, tNet_message* pMessage) {
LOG_TRACE("(%p, %p)", pDetails, pMessage);
NOT_IMPLEMENTED();
}
// IDA: void __usercall PDNetSetPlayerSystemInfo(tNet_game_player_info *pPlayer@<EAX>, void *pSender_address@<EDX>)
void PDNetSetPlayerSystemInfo(tNet_game_player_info* pPlayer, void* pSender_address) {
LOG_TRACE("(%p, %p)", pPlayer, pSender_address);
dr_dprintf("PDNetSetPlayerSystemInfo()");
memcpy(&pPlayer->pd_net_info, pSender_address, sizeof(pPlayer->pd_net_info));
}
// IDA: void __usercall PDNetDisposePlayer(tNet_game_player_info *pPlayer@<EAX>)
void PDNetDisposePlayer(tNet_game_player_info* pPlayer) {
LOG_TRACE("(%p)", pPlayer);
NOT_IMPLEMENTED();
}
// IDA: int __usercall PDNetSendMessageToAddress@<EAX>(tNet_game_details *pDetails@<EAX>, tNet_message *pMessage@<EDX>, void *pAddress@<EBX>)
int PDNetSendMessageToAddress(tNet_game_details* pDetails, tNet_message* pMessage, void* pAddress) {
char str[256];
LOG_TRACE("(%p, %p, %p)", pDetails, pMessage, pAddress);
NetNowIPXLocalTarget2String(str, (struct sockaddr_in*)pAddress);
if (pDetails->pd_net_info.addr_in.sin_port == 0) {
int i = 0;
}
if (sendto(gSocket, (const char*)pMessage, pMessage->overall_size, 0, (const struct sockaddr*)pAddress, sizeof(struct sockaddr)) == -1) {
dr_dprintf("PDNetSendMessageToAddress(): Error on sendto() - WSAGetLastError=%d", WSAGetLastError());
NetDisposeMessage(pDetails, pMessage);
return 1;
}
NetDisposeMessage(pDetails, pMessage);
return 0;
}
// IDA: int __usercall PDNetInitClient@<EAX>(tNet_game_details *pDetails@<EAX>)
int PDNetInitClient(tNet_game_details* pDetails) {
LOG_TRACE("(%p)", pDetails);
NOT_IMPLEMENTED();
}
// IDA: int __cdecl PDNetGetHeaderSize()
int PDNetGetHeaderSize(void) {
LOG_TRACE("()");
return 0;
}

View File

@ -0,0 +1,25 @@
#ifndef WIN95_NET_TYPES_H
#define WIN95_NET_TYPES_H
// #include "dr_types.h"
#include "harness/win95_polyfill.h"
#include "harness/winsock.h"
// dethrace: have switched out IPX implementation for IP
typedef struct tPD_net_player_info {
// struct sockaddr_ipx addr_ipx;
struct sockaddr_in addr_in;
} tPD_net_player_info;
typedef struct tPD_net_game_info {
// struct sockaddr_ipx addr_ipx;
struct sockaddr_in addr_in;
tU32 last_response;
} tPD_net_game_info;
// typedef struct tIPX_netnum {
// unsigned char bNetwork[4];
// } tIPX_netnum;
#endif

View File

@ -10,59 +10,17 @@
#include "brender/br_types.h"
#include "dr_types.h"
// void ClearupPDNetworkStuff(void);
void ClearupPDNetworkStuff(void);
// void MATTMessageCheck(char* pFunction_name, tNet_message* pMessage, int pAlleged_size);
void MATTMessageCheck(char* pFunction_name, tNet_message* pMessage, int pAlleged_size);
// int GetProfileText(char* pDest, int pDest_len, char* pFname, char* pKeyname);
int GetMessageTypeFromMessage(char* pMessage_str);
// int GetSocketNumberFromProfileFile(void);
void MakeMessageToSend(int pMessage_type);
// tU32 EthernetAddressToU32(_IPX_LOCAL_TARGET* pAddr_ipx);
int ReceiveHostResponses(void);
// void NetNowIPXLocalTarget2String(char* pString, _IPX_LOCAL_TARGET* pSock_addr_ipx);
// int GetMessageTypeFromMessage(char* pMessage_str);
// int SameEthernetAddress(_IPX_LOCAL_TARGET* pAddr_ipx1, _IPX_LOCAL_TARGET* pAddr_ipx2);
// _IPX_LOCAL_TARGET* GetIPXAddrFromPlayerID(tPlayer_ID pPlayer_id);
// void MakeMessageToSend(int pMessage_type);
// int ReceiveHostResponses(void);
// int BroadcastMessage(void);
// int hmiIPXCloseSocket(W32 wSocket);
// void hmiIPXListenForPacket(_IPX_ECB* pECB_ptr, tU32 pOffset);
// int hmiIPXPostListen(_IPX_ECB* pECB_ptr, tU32 pOffset);
// int hmiIPXGetData(PSTR pData, tU32 wDSize);
// void hmiIPXSendPacket(_IPX_ECB* sECB, _IPX_ECB** pPacket, PSTR pHeader, W32 wSize);
// int hmiIPXSendDataDirect(PSTR pHeader, W32 wHSize, PSTR pData, W32 wDSize, _NETNOW_NODE_ADDR* sNode);
// void hmiIPXGetInternetworkAddr(_IPX_INTERNET_ADDR* sInterworkAddr);
// void hmiIPXGetLocalTarget(_IPX_LOCAL_TARGET* sNetworkAddr);
// int AllocateRealMem(W32 wSize, PSTR* pPtr, W32* pSegment, tU16* pSelector);
// int FreeRealMem(tU16 pSelector);
// int hmiIPXInstalled(void);
// int hmiIPXOpenSocket(W32 wSocket);
// void GetLargestPacketSizeOoErBetterInsertLinfordChristieJokeHere(void);
// int hmiIPXInitSystem(W32 wSocket);
// void GetIPXToStickItsEarToTheGround(void);
int BroadcastMessage(void);
int PDNetInitialise(void);

187
src/S3/sos_dos_types.h Normal file
View File

@ -0,0 +1,187 @@
typedef unsigned int W32;
typedef struct _tag_sos_evds_struct _SOS_EVDS_STRUCT;
typedef struct _tag_sos_vds_struct _SOS_VDS_STRUCT;
typedef struct _tag_sos_sample _SOS_SAMPLE;
typedef _SOS_SAMPLE* PSOSSAMPLE;
typedef struct _tagCAPABILITIES _SOS_CAPABILITIES;
typedef _SOS_CAPABILITIES* PSOSCAPABILITIES;
typedef struct _SOS_HARDWARE* PSOSHARDWARE;
typedef struct _tag_sos_driver _SOS_DIGI_DRIVER;
typedef _SOS_DIGI_DRIVER* PSOSDIGIDRIVER;
typedef struct _SOS_DRV_FILEHEADER* PSOSDRVFILEHEADER;
typedef struct _SOS_DRV_DRIVERHEADER* PSOSDRVDRIVERHEADER;
typedef struct _tag_sos_system _SOS_SYSTEM;
typedef _SOS_SYSTEM* PSOSSYSTEM;
typedef struct _tag_sos_det_system _SOS_DET_SYSTEM;
typedef _SOS_DET_SYSTEM* PSOSDETSYSTEM;
typedef struct _tag_sos_timer_system _SOS_TIMER_SYSTEM;
typedef _SOS_TIMER_SYSTEM* PSOSTIMERSYSTEM;
typedef struct _tag_sos_evds_struct {
unsigned int region_size;
unsigned int offset;
unsigned int segment;
unsigned short number_available;
unsigned short number_used;
unsigned int page0;
} _SOS_EVDS_STRUCT;
typedef struct _tag_sos_vds_struct {
unsigned int region_size;
unsigned int offset;
unsigned short segment;
unsigned short ID;
unsigned int physical;
} _SOS_VDS_STRUCT;
typedef struct _tag_sos_sample {
char* pSample;
char* pSampleCurrent;
char* pSampleLoop;
unsigned long wLength;
unsigned long wLoopLength;
unsigned long wLoopEndLength;
unsigned long wLoopStage;
unsigned long wID;
unsigned long wFlags;
unsigned long wPriority;
unsigned long hSample;
unsigned long wVolume;
unsigned long wLoopCount;
unsigned long wRate;
unsigned long wBitsPerSample;
unsigned long wChannels;
unsigned long wFormat;
unsigned long wPanPosition;
unsigned long wPanSpeed;
unsigned long wPanStart;
unsigned long wPanEnd;
unsigned long wPanMode;
unsigned long wTotalBytesProcessed;
void (*pfnSampleProcessed)(PSOSSAMPLE*);
void (*pfnSampleDone)(PSOSSAMPLE*);
void (*pfnSampleLoop)(PSOSSAMPLE*);
unsigned long wSystem[16];
unsigned long wUser[16];
PSOSSAMPLE* pLink;
PSOSSAMPLE* pNext;
} _SOS_SAMPLE;
typedef struct _tagCAPABILITIES {
unsigned char szDeviceName[32];
W32 wDeviceVersion;
W32 wBitsPerSample;
W32 wChannels;
W32 wMinRate;
W32 wMaxRate;
W32 wMixerOnBoard;
W32 wMixerFlags;
W32 wFlags;
short* lpPortList;
short* lpDMAList;
short* lpIRQList;
short* lpRateList;
W32 fBackground;
W32 wID;
W32 wTimerID;
} _SOS_CAPABILITIES;
typedef struct _SOS_HARDWARE {
W32 wPort;
W32 wIRQ;
W32 wDMA;
W32 wParam;
} _SOS_HARDWARE;
typedef struct _tag_sos_driver {
W32 wFlags;
unsigned long wDriverRate;
unsigned long wDriverChannels;
unsigned long wDriverBitsPerSample;
unsigned long wDriverFormat;
unsigned long wMixerChannels;
unsigned long wDMACountRegister;
unsigned long wDMAPosition;
unsigned long wDMALastPosition;
unsigned long wDMADistance;
char* pXFERPosition;
unsigned long wXFERJumpAhead;
_SOS_SAMPLE* pSampleList;
void (*pfnPseudoDMAFunction)(void);
char* pDMABuffer;
char* pDMABufferEnd;
unsigned long wDMABufferSize;
char* pMixingBuffer;
char* pMixingBufferEnd;
unsigned long wMixingBufferSize;
unsigned long wActiveChannels;
_SOS_SAMPLE* pSamples;
_SOS_HARDWARE sHardware;
_SOS_CAPABILITIES sCaps;
char* lpDriverDS;
char* lpDriverCS;
W32 wSize;
unsigned long dwLinear;
unsigned long dwDMAPhysical;
char* lpDMABuffer;
W32 hMemory;
W32 wDMARealSeg;
W32 wID;
void (*pfnMixFunction)(void);
} _SOS_DIGI_DRIVER;
typedef struct _SOS_DRV_FILEHEADER {
unsigned char szName[32];
W32 wDrivers;
W32 lOffset;
W32 lFileSize;
} _SOS_DRV_FILEHEADER;
typedef struct _SOS_DRV_DRIVERHEADER {
unsigned char szName[32];
W32 lNextDriver;
W32 wSize;
W32 wDeviceID;
W32 wExtenderType;
} _SOS_DRV_DRIVERHEADER;
typedef struct _tag_sos_system {
W32 wFlags;
unsigned char szDriverPath[128];
unsigned char szTempDriverPath[128];
PSOSDIGIDRIVER pDriver[5];
_SOS_VDS_STRUCT sVDS;
_SOS_DRV_FILEHEADER sFileHeader;
_SOS_DRV_DRIVERHEADER sDriverHeader;
char* (*pMemAllocFunction)(unsigned long);
void (*pMemFreeFunction)(char*, W32);
} _SOS_SYSTEM;
typedef struct _tag_sos_det_system {
W32 wFlags;
unsigned char szDriverPath[128];
unsigned char szTempDriverPath[128];
_SOS_DRV_FILEHEADER sFileHeader;
_SOS_DRV_DRIVERHEADER sDriverHeader;
_SOS_CAPABILITIES sCaps;
PSOSCAPABILITIES pCaps;
char* lpBufferDS;
char* lpBufferCS;
W32 hFile;
unsigned long dwDriverIndex;
W32 wDriverIndexCur;
W32 hMemory;
unsigned long dwLinear;
} _SOS_DET_SYSTEM;
typedef struct _tag_sos_timer_system {
W32 wFlags;
W32 wChipDivisor;
void (*pfnEvent[16])(void);
W32 wEventRate[16];
unsigned long dwAdditiveFraction[16];
unsigned long dwCurrentSummation[16];
W32 wMIDIEventSongHandle[16];
W32 wMIDIActiveSongHandle;
} _SOS_TIMER_SYSTEM;

View File

@ -64,6 +64,7 @@ target_sources(harness PRIVATE
sound/sound.c
sound/sound.h
win95/polyfill.c
win95/winsock.c
platforms/null.c
platforms/null.h
@ -101,6 +102,7 @@ if(WIN32)
target_sources(harness PRIVATE
os/windows.c
)
target_link_libraries(harness PRIVATE ws2_32)
elseif(APPLE)
target_sources(harness PRIVATE
os/macos.c

View File

@ -161,6 +161,8 @@ void Harness_Init(int* argc, char* argv[]) {
harness_game_config.start_full_screen = 0;
// Emulate DOS behavior
harness_game_config.dos_mode = 0;
// Skip binding socket to allow local network testing
harness_game_config.no_bind = 0;
// install signal handler by default
harness_game_config.install_signalhandler = 1;
@ -249,6 +251,9 @@ int Harness_ProcessCommandLine(int* argc, char* argv[]) {
} else if (strcasecmp(argv[i], "--dos-mode") == 0) {
harness_game_config.dos_mode = 1;
handled = 1;
} else if (strcasecmp(argv[i], "--no-bind") == 0) {
harness_game_config.no_bind = 1;
handled = 1;
}
if (handled) {

View File

@ -42,6 +42,7 @@ typedef struct tHarness_game_config {
float volume_multiplier;
int start_full_screen;
int dos_mode;
int no_bind;
int install_signalhandler;
} tHarness_game_config;

View File

@ -0,0 +1,52 @@
/*
* Inspiration taken from https://github.com/TheAssemblyArmada/Vanilla-Conquer/blob/vanilla/common/sockets.h
*/
#ifndef HARNESS_WINSOCK_H
#define HARNESS_WINSOCK_H
#include <assert.h>
#ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#else /* Assume posix style sockets on non-windows */
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h> // for getaddrinfo() and freeaddrinfo()
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h> // for close()
#define closesocket(x) close(x)
#define WSAEISCONN EISCONN
#define WSAEINPROGRESS EINPROGRESS
#define WSAEALREADY EALREADY
#define WSAEADDRINUSE EADDRINUSE
#define WSAEADDRNOTAVAIL EADDRNOTAVAIL
#define WSAEBADF EBADF
#define WSAECONNREFUSED ECONNREFUSED
#define WSAEINTR EINTR
#define WSAENOTSOCK ENOTSOCK
#define WSAEWOULDBLOCK EWOULDBLOCK
#define WSAEINVAL EINVAL
#define WSAETIMEDOUT ETIMEDOUT
#define MAKEWORD(x, y) ((y) << 8 | (x))
typedef struct WSADATA {
} WSADATA;
int WSAStartup(int version, WSADATA* data);
int WSAGetLastError(void);
int WSACleanup(void);
int ioctlsocket(int handle, long cmd, unsigned long* argp);
#endif /* _WIN32 */
#endif

View File

@ -0,0 +1,27 @@
#include "harness/winsock.h"
#ifndef _WIN32
int WSAStartup(int version, WSADATA* data) {
// very minimal, we don't care about the arguments
return 0;
}
int WSAGetLastError(void) {
return errno;
}
int WSACleanup(void) {
return 0;
}
// Only implement non-blocking call for now
int ioctlsocket(int handle, long cmd, unsigned long* argp) {
assert(cmd == FIONBIO);
int flags = fcntl(handle, F_GETFL);
flags |= O_NONBLOCK;
return fcntl(handle, F_SETFL, flags);
}
#endif

View File

@ -28,7 +28,7 @@ if(NOT MSVC)
endif()
endif()
else()
target_compile_definitions(dethrace_test PRIVATE -D_CRT_SECURE_NO_WARNINGS -DSDL_MAIN_HANDLED)
target_compile_definitions(dethrace_test PRIVATE -D_CRT_SECURE_NO_WARNINGS -DSDL_MAIN_HANDLED -DWIN32_LEAN_AND_MEAN)
target_link_libraries(dethrace_test PRIVATE dbghelp)
endif()