(svn r14772) -Codechange: make the "dump log of game to reproduce" desync debug stuff a runtime configurable debug option instead of a compile time option.

This commit is contained in:
rubidium
2008-12-29 21:50:25 +00:00
parent 1892994ab2
commit f55995f1ef
11 changed files with 124 additions and 90 deletions

View File

@@ -583,7 +583,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallbac
return true;
}
#endif /* ENABLE_NETWORK */
DebugDumpCommands("ddc:cmd:%d;%d;%d;%d;%d;%d;%d;%s\n", _date, _date_fract, (int)_current_company, tile, p1, p2, cmd, text);
DEBUG(desync, 1, "cmd: %08x; %08x; %1x; %06x; %08x; %08x; %04x; %s\n", _date, _date_fract, (int)_current_company, tile, p1, p2, cmd & ~CMD_NETWORK_COMMAND, text);
/* update last build coordinate of company. */
if (tile != 0 && IsValidCompanyID(_current_company)) {

View File

@@ -15,9 +15,7 @@
#include "vehicle_base.h"
#include "debug.h"
#include "rail_gui.h"
#ifdef DEBUG_DUMP_COMMANDS
#include "saveload.h"
#endif
Year _cur_year;
Month _cur_month;
@@ -244,12 +242,12 @@ void IncreaseDate()
/* yes, call various monthly loops */
if (_game_mode != GM_MENU) {
#ifdef DEBUG_DUMP_COMMANDS
char name[MAX_PATH];
snprintf(name, lengthof(name), "dmp_cmds_%d.sav", _date);
SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR);
DebugDumpCommands("ddc:save:%s\n", name);
#endif /* DUMP_COMMANDS */
if (_debug_desync_level > 2) {
char name[MAX_PATH];
snprintf(name, lengthof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR);
}
if (_settings_client.gui.autosave != 0 && (_cur_month % _autosave_months[_settings_client.gui.autosave]) == 0) {
_do_autosave = true;
RedrawAutosave();

View File

@@ -10,6 +10,7 @@
#include "debug.h"
#include "string_func.h"
#include "network/core/core.h"
#include "fileio_func.h"
#if defined(ENABLE_NETWORK)
SOCKET _debug_socket = INVALID_SOCKET;
@@ -31,6 +32,7 @@ int _debug_freetype_level;
int _debug_sl_level;
int _debug_station_level;
int _debug_gamelog_level;
int _debug_desync_level;
struct DebugLevel {
@@ -56,6 +58,7 @@ struct DebugLevel {
DEBUG_LEVEL(sl),
DEBUG_LEVEL(station),
DEBUG_LEVEL(gamelog),
DEBUG_LEVEL(desync),
};
#undef DEBUG_LEVEL
@@ -71,7 +74,7 @@ static void debug_print(const char *dbg, const char *buf)
send(_debug_socket, buf2, (int)strlen(buf2), 0);
} else
#endif /* ENABLE_NETWORK */
{
if (strcmp(dbg, "desync") != 0) {
#if defined(WINCE)
/* We need to do OTTD2FS twice, but as it uses a static buffer, we need to store one temporary */
TCHAR tbuf[512];
@@ -81,6 +84,12 @@ static void debug_print(const char *dbg, const char *buf)
fprintf(stderr, "dbg: [%s] %s\n", dbg, buf);
#endif
IConsoleDebug(dbg, buf);
} else {
static FILE *f = FioFOpenFile("commands-out.log", "wb", AUTOSAVE_DIR);
if (f == NULL) return;
fprintf(f, "%s", buf);
fflush(f);
}
}
@@ -168,20 +177,3 @@ const char *GetDebugString()
return dbgstr;
}
#ifdef DEBUG_DUMP_COMMANDS
#include "fileio_func.h"
void CDECL DebugDumpCommands(const char *s, ...)
{
static FILE *f = FioFOpenFile("commands-out.log", "wb", AUTOSAVE_DIR);
if (f == NULL) return;
va_list va;
va_start(va, s);
vfprintf(f, s, va);
va_end(va);
fflush(f);
}
#endif /* DEBUG_DUMP_COMMANDS */

View File

@@ -48,6 +48,7 @@
extern int _debug_sl_level;
extern int _debug_station_level;
extern int _debug_gamelog_level;
extern int _debug_desync_level;
void CDECL debug(const char *dbg, ...);
#endif /* NO_DEBUG_MESSAGES */
@@ -101,16 +102,4 @@ const char *GetDebugString();
void ShowInfo(const char *str);
void CDECL ShowInfoF(const char *str, ...);
#ifdef DEBUG_DUMP_COMMANDS
void CDECL DebugDumpCommands(const char *s, ...);
#else /* DEBUG_DUMP_COMMANDS */
/* when defined as an empty function with variable argument list,
* it can't be inlined - so define it as an empty macro */
#if defined(__GNUC__) && (__GNUC__ < 3)
#define DebugDumpCommands(s, args...)
#else
#define DebugDumpCommands(s, ...)
#endif
#endif /* DEBUG_DUMP_COMMANDS */
#endif /* DEBUG_H */

View File

@@ -26,6 +26,7 @@
#include "newgrf_storage.h"
#include "water.h"
#include "tilehighlight_func.h"
#include "saveload.h"
#include "table/sprites.h"
@@ -163,8 +164,14 @@ static void _GenerateWorld(void *arg)
MarkWholeScreenDirty();
if (_network_dedicated) DEBUG(net, 0, "Map generated, starting game");
DEBUG(desync, 1, "new_map: %i\n", _settings_game.game_creation.generation_seed);
if (_settings_client.gui.pause_on_newgame && _game_mode == GM_NORMAL) DoCommandP(0, 1, 0, CMD_PAUSE);
if (_debug_desync_level > 0) {
char name[MAX_PATH];
snprintf(name, lengthof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR);
}
} catch (...) {
_generating_world = false;
throw;

View File

@@ -213,7 +213,7 @@ void NetworkTextMessage(NetworkAction action, ConsoleColour color, bool self_sen
SetDParam(2, data);
GetString(message, strid, lastof(message));
DebugDumpCommands("ddc:cmsg:%d;%d;%s\n", _date, _date_fract, message);
DEBUG(desync, 1, "msg: %d; %d; %s\n", _date, _date_fract, message);
IConsolePrintF(color, "%s", message);
NetworkAddChatMessage(color, duration, "%s", message);
}
@@ -964,7 +964,7 @@ static bool NetworkDoClientLoop()
if (_sync_seed_1 != _random.state[0]) {
#endif
NetworkError(STR_NETWORK_ERR_DESYNC);
DebugDumpCommands("ddc:serr:%d;%d\n", _date, _date_fract);
DEBUG(desync, 1, "sync_err: %d; %d\n", _date, _date_fract);
DEBUG(net, 0, "Sync error detected!");
NetworkClientError(NETWORK_RECV_STATUS_DESYNC, GetNetworkClientSocket(0));
return false;
@@ -1032,10 +1032,10 @@ void NetworkGameLoop()
char buff[4096];
if (fgets(buff, lengthof(buff), f) == NULL) break;
if (strncmp(buff, "ddc:cmd:", 8) != 0) continue;
if (strncmp(buff, "cmd: ", 8) != 0) continue;
cp = MallocT<CommandPacket>(1);
int company;
sscanf(&buff[8], "%d;%d;%d;%d;%d;%d;%d;%s", &next_date, &next_date_fract, &company, &cp->tile, &cp->p1, &cp->p2, &cp->cmd, cp->text);
sscanf(&buff[8], "%d; %d; %d; %d; %d; %d; %d; %s", &next_date, &next_date_fract, &company, &cp->tile, &cp->p1, &cp->p2, &cp->cmd, cp->text);
cp->company = (CompanyID)company;
}
#endif /* DEBUG_DUMP_COMMANDS */

View File

@@ -102,8 +102,6 @@ void NetworkExecuteCommand(CommandPacket *cp)
cp->callback = 0;
}
DebugDumpCommands("ddc:cmd:%d;%d;%d;%d;%d;%d;%d;%s\n", _date, _date_fract, (int)cp->company, cp->tile, cp->p1, cp->p2, cp->cmd, cp->text);
DoCommandP(cp->tile, cp->p1, cp->p2, cp->cmd | CMD_NETWORK_COMMAND, _callback_table[cp->callback], cp->text, cp->my_cmd);
}

View File

@@ -1029,53 +1029,53 @@ void StateGameLoop()
CallWindowTickEvent();
NewsLoop();
} else {
#ifdef DEBUG_DUMP_COMMANDS
Vehicle *v;
FOR_ALL_VEHICLES(v) {
if (v != v->First()) continue;
if (_debug_desync_level > 1) {
Vehicle *v;
FOR_ALL_VEHICLES(v) {
if (v != v->First()) continue;
switch (v->type) {
case VEH_ROAD: {
extern byte GetRoadVehLength(const Vehicle *v);
if (GetRoadVehLength(v) != v->u.road.cached_veh_length) {
printf("cache mismatch: vehicle %i, company %i, unit number %i\n", v->index, (int)v->owner, v->unitnumber);
}
} break;
case VEH_TRAIN: {
uint length = 0;
for (Vehicle *u = v; u != NULL; u = u->Next()) length++;
VehicleRail *wagons = MallocT<VehicleRail>(length);
length = 0;
for (Vehicle *u = v; u != NULL; u = u->Next()) wagons[length++] = u->u.rail;
TrainConsistChanged(v, true);
length = 0;
for (Vehicle *u = v; u != NULL; u = u->Next()) {
if (memcmp(&wagons[length], &u->u.rail, sizeof(VehicleRail)) != 0) {
printf("cache mismatch: vehicle %i, company %i, unit number %i, wagon %i\n", v->index, (int)v->owner, v->unitnumber, length);
switch (v->type) {
case VEH_ROAD: {
extern byte GetRoadVehLength(const Vehicle *v);
if (GetRoadVehLength(v) != v->u.road.cached_veh_length) {
DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i\n", v->index, (int)v->owner, v->unitnumber);
}
length++;
}
} break;
free(wagons);
} break;
case VEH_TRAIN: {
uint length = 0;
for (Vehicle *u = v; u != NULL; u = u->Next()) length++;
case VEH_AIRCRAFT: {
uint speed = v->u.air.cached_max_speed;
UpdateAircraftCache(v);
if (speed != v->u.air.cached_max_speed) {
printf("cache mismatch: vehicle %i, company %i, unit number %i\n", v->index, (int)v->owner, v->unitnumber);
}
} break;
VehicleRail *wagons = MallocT<VehicleRail>(length);
length = 0;
for (Vehicle *u = v; u != NULL; u = u->Next()) wagons[length++] = u->u.rail;
default:
break;
TrainConsistChanged(v, true);
length = 0;
for (Vehicle *u = v; u != NULL; u = u->Next()) {
if (memcmp(&wagons[length], &u->u.rail, sizeof(VehicleRail)) != 0) {
DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i, wagon %i\n", v->index, (int)v->owner, v->unitnumber, length);
}
length++;
}
free(wagons);
} break;
case VEH_AIRCRAFT: {
uint speed = v->u.air.cached_max_speed;
UpdateAircraftCache(v);
if (speed != v->u.air.cached_max_speed) {
DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i\n", v->index, (int)v->owner, v->unitnumber);
}
} break;
default:
break;
}
}
}
#endif
/* All these actions has to be done from OWNER_NONE
* for multiplayer compatibility */

View File

@@ -1687,6 +1687,7 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb)
/* General tactic is to first save the game to memory, then use an available writer
* to write it to file, either in threaded mode if possible, or single-threaded */
if (mode == SL_SAVE) { /* SAVE game */
DEBUG(desync, 1, "save: %s\n", filename);
fmt = GetSavegameFormat("memory"); // write to memory
_sl.write_bytes = fmt->writer;
@@ -1714,7 +1715,7 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb)
}
} else { /* LOAD game */
assert(mode == SL_LOAD);
DebugDumpCommands("ddc:load:%s\n", filename);
DEBUG(desync, 1, "load: %s\n", filename);
if (fread(hdr, sizeof(hdr), 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE);