gamelog.cpp

Go to the documentation of this file.
00001 /* $Id: gamelog.cpp 20957 2010-10-17 12:12:13Z frosch $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "openttd.h"
00014 #include "saveload/saveload.h"
00015 #include "string_func.h"
00016 #include "settings_type.h"
00017 #include "gamelog_internal.h"
00018 #include "console_func.h"
00019 #include "debug.h"
00020 #include "date_func.h"
00021 #include "rev.h"
00022 
00023 #include <stdarg.h>
00024 
00025 extern const uint16 SAVEGAME_VERSION;  
00026 
00027 extern SavegameType _savegame_type; 
00028 
00029 extern uint32 _ttdp_version;     
00030 extern uint16 _sl_version;       
00031 extern byte   _sl_minor_version; 
00032 
00033 
00034 static GamelogActionType _gamelog_action_type = GLAT_NONE; 
00035 
00036 LoggedAction *_gamelog_action = NULL;        
00037 uint _gamelog_actions         = 0;           
00038 static LoggedAction *_current_action = NULL; 
00039 
00040 
00046 void GamelogStartAction(GamelogActionType at)
00047 {
00048   assert(_gamelog_action_type == GLAT_NONE); // do not allow starting new action without stopping the previous first
00049   _gamelog_action_type = at;
00050 }
00051 
00055 void GamelogStopAction()
00056 {
00057   assert(_gamelog_action_type != GLAT_NONE); // nobody should try to stop if there is no action in progress
00058 
00059   bool print = _current_action != NULL;
00060 
00061   _current_action = NULL;
00062   _gamelog_action_type = GLAT_NONE;
00063 
00064   if (print) GamelogPrintDebug(5);
00065 }
00066 
00070 void GamelogReset()
00071 {
00072   assert(_gamelog_action_type == GLAT_NONE);
00073 
00074   for (uint i = 0; i < _gamelog_actions; i++) {
00075     const LoggedAction *la = &_gamelog_action[i];
00076     for (uint j = 0; j < la->changes; j++) {
00077       const LoggedChange *lc = &la->change[j];
00078       if (lc->ct == GLCT_SETTING) free(lc->setting.name);
00079     }
00080     free(la->change);
00081   }
00082 
00083   free(_gamelog_action);
00084 
00085   _gamelog_action  = NULL;
00086   _gamelog_actions = 0;
00087   _current_action  = NULL;
00088 }
00089 
00090 static const uint GAMELOG_BUF_LEN = 1024; 
00091 
00092 static uint _dbgofs = 0; 
00093 
00094 static void AddDebugText(char *buf, const char *s, ...) WARN_FORMAT(2, 3);
00095 
00096 static void AddDebugText(char *buf, const char *s, ...)
00097 {
00098   if (GAMELOG_BUF_LEN <= _dbgofs) return;
00099 
00100   va_list va;
00101 
00102   va_start(va, s);
00103   _dbgofs += vsnprintf(buf + _dbgofs, GAMELOG_BUF_LEN - _dbgofs, s, va);
00104   va_end(va);
00105 }
00106 
00107 
00115 static void PrintGrfInfo(char *buf, uint grfid, const uint8 *md5sum, const GRFConfig *gc)
00116 {
00117   char txt[40];
00118 
00119   if (md5sum != NULL) {
00120     md5sumToString(txt, lastof(txt), md5sum);
00121     AddDebugText(buf, "GRF ID %08X, checksum %s", BSWAP32(grfid), txt);
00122   } else {
00123     AddDebugText(buf, "GRF ID %08X", BSWAP32(grfid));
00124   }
00125 
00126   if (gc != NULL) {
00127     AddDebugText(buf, ", filename: %s (md5sum matches)", gc->filename);
00128   } else {
00129     gc = FindGRFConfig(grfid, FGCM_ANY);
00130     if (gc != NULL) {
00131       AddDebugText(buf, ", filename: %s (matches GRFID only)", gc->filename);
00132     } else {
00133       AddDebugText(buf, ", unknown GRF");
00134     }
00135   }
00136   return;
00137 }
00138 
00139 
00141 static const char * const la_text[] = {
00142   "new game started",
00143   "game loaded",
00144   "GRF config changed",
00145   "cheat was used",
00146   "settings changed",
00147   "GRF bug triggered",
00148   "emergency savegame",
00149 };
00150 
00151 assert_compile(lengthof(la_text) == GLAT_END);
00152 
00160 struct GRFPresence{
00161   const GRFConfig *gc;  
00162   bool was_missing;     
00163 
00164   GRFPresence(const GRFConfig *gc) : gc(gc), was_missing(false) {}
00165 };
00166 typedef SmallMap<uint32, GRFPresence> GrfIDMapping;
00167 
00172 void GamelogPrint(GamelogPrintProc *proc)
00173 {
00174   char buf[GAMELOG_BUF_LEN];
00175   GrfIDMapping grf_names;
00176 
00177   proc("---- gamelog start ----");
00178 
00179   const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
00180 
00181   for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
00182     assert((uint)la->at < GLAT_END);
00183 
00184     snprintf(buf, GAMELOG_BUF_LEN, "Tick %u: %s", (uint)la->tick, la_text[(uint)la->at]);
00185     proc(buf);
00186 
00187     const LoggedChange *lcend = &la->change[la->changes];
00188 
00189     for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
00190       _dbgofs = 0;
00191       AddDebugText(buf, "     ");
00192 
00193       switch (lc->ct) {
00194         default: NOT_REACHED();
00195         case GLCT_MODE:
00196           AddDebugText(buf, "New game mode: %u landscape: %u",
00197             (uint)lc->mode.mode, (uint)lc->mode.landscape);
00198           break;
00199 
00200         case GLCT_REVISION:
00201           AddDebugText(buf, "Revision text changed to %s, savegame version %u, ",
00202             lc->revision.text, lc->revision.slver);
00203 
00204           switch (lc->revision.modified) {
00205             case 0: AddDebugText(buf, "not "); break;
00206             case 1: AddDebugText(buf, "maybe "); break;
00207             default: break;
00208           }
00209 
00210           AddDebugText(buf, "modified, _openttd_newgrf_version = 0x%08x", lc->revision.newgrf);
00211           break;
00212 
00213         case GLCT_OLDVER:
00214           AddDebugText(buf, "Conversion from ");
00215           switch (lc->oldver.type) {
00216             default: NOT_REACHED();
00217             case SGT_OTTD:
00218               AddDebugText(buf, "OTTD savegame without gamelog: version %u, %u",
00219                 GB(lc->oldver.version, 8, 16), GB(lc->oldver.version, 0, 8));
00220               break;
00221 
00222             case SGT_TTO:
00223               AddDebugText(buf, "TTO savegame");
00224               break;
00225 
00226             case SGT_TTD:
00227               AddDebugText(buf, "TTD savegame");
00228               break;
00229 
00230             case SGT_TTDP1:
00231             case SGT_TTDP2:
00232               AddDebugText(buf, "TTDP savegame, %s format",
00233                 lc->oldver.type == SGT_TTDP1 ? "old" : "new");
00234               if (lc->oldver.version != 0) {
00235                 AddDebugText(buf, ", TTDP version %u.%u.%u.%u",
00236                   GB(lc->oldver.version, 24, 8), GB(lc->oldver.version, 20, 4),
00237                   GB(lc->oldver.version, 16, 4), GB(lc->oldver.version, 0, 16));
00238               }
00239               break;
00240           }
00241           break;
00242 
00243         case GLCT_SETTING:
00244           AddDebugText(buf, "Setting changed: %s : %d -> %d", lc->setting.name, lc->setting.oldval, lc->setting.newval);
00245           break;
00246 
00247         case GLCT_GRFADD: {
00248           const GRFConfig *gc = FindGRFConfig(lc->grfadd.grfid, FGCM_EXACT, lc->grfadd.md5sum);
00249           AddDebugText(buf, "Added NewGRF: ");
00250           PrintGrfInfo(buf, lc->grfadd.grfid, lc->grfadd.md5sum, gc);
00251           GrfIDMapping::Pair *gm = grf_names.Find(lc->grfrem.grfid);
00252           if (gm != grf_names.End() && !gm->second.was_missing) AddDebugText(buf, ". Gamelog inconsistency: GrfID was already added!");
00253           grf_names[lc->grfadd.grfid] = gc;
00254           break;
00255         }
00256 
00257         case GLCT_GRFREM: {
00258           GrfIDMapping::Pair *gm = grf_names.Find(lc->grfrem.grfid);
00259           AddDebugText(buf, la->at == GLAT_LOAD ? "Missing NewGRF: " : "Removed NewGRF: ");
00260           PrintGrfInfo(buf, lc->grfrem.grfid, NULL, gm != grf_names.End() ? gm->second.gc : NULL);
00261           if (gm == grf_names.End()) {
00262             AddDebugText(buf, ". Gamelog inconsistency: GrfID was never added!");
00263           } else {
00264             if (la->at == GLAT_LOAD) {
00265               /* Missing grfs on load are not removed from the configuration */
00266               gm->second.was_missing = true;
00267             } else {
00268               grf_names.Erase(gm);
00269             }
00270           }
00271           break;
00272         }
00273 
00274         case GLCT_GRFCOMPAT: {
00275           const GRFConfig *gc = FindGRFConfig(lc->grfadd.grfid, FGCM_EXACT, lc->grfadd.md5sum);
00276           AddDebugText(buf, "Compatible NewGRF loaded: ");
00277           PrintGrfInfo(buf, lc->grfcompat.grfid, lc->grfcompat.md5sum, gc);
00278           if (!grf_names.Contains(lc->grfcompat.grfid)) AddDebugText(buf, ". Gamelog inconsistency: GrfID was never added!");
00279           grf_names[lc->grfcompat.grfid] = gc;
00280           break;
00281         }
00282 
00283         case GLCT_GRFPARAM: {
00284           GrfIDMapping::Pair *gm = grf_names.Find(lc->grfrem.grfid);
00285           AddDebugText(buf, "GRF parameter changed: ");
00286           PrintGrfInfo(buf, lc->grfparam.grfid, NULL, gm != grf_names.End() ? gm->second.gc : NULL);
00287           if (gm == grf_names.End()) AddDebugText(buf, ". Gamelog inconsistency: GrfID was never added!");
00288           break;
00289         }
00290 
00291         case GLCT_GRFMOVE: {
00292           GrfIDMapping::Pair *gm = grf_names.Find(lc->grfrem.grfid);
00293           AddDebugText(buf, "GRF order changed: %08X moved %d places %s",
00294             BSWAP32(lc->grfmove.grfid), abs(lc->grfmove.offset), lc->grfmove.offset >= 0 ? "down" : "up" );
00295           PrintGrfInfo(buf, lc->grfmove.grfid, NULL, gm != grf_names.End() ? gm->second.gc : NULL);
00296           if (gm == grf_names.End()) AddDebugText(buf, ". Gamelog inconsistency: GrfID was never added!");
00297           break;
00298         }
00299 
00300         case GLCT_GRFBUG: {
00301           GrfIDMapping::Pair *gm = grf_names.Find(lc->grfrem.grfid);
00302           switch (lc->grfbug.bug) {
00303             default: NOT_REACHED();
00304             case GBUG_VEH_LENGTH:
00305               AddDebugText(buf, "Rail vehicle changes length outside a depot: GRF ID %08X, internal ID 0x%X", BSWAP32(lc->grfbug.grfid), (uint)lc->grfbug.data);
00306               break;
00307           }
00308           PrintGrfInfo(buf, lc->grfbug.grfid, NULL, gm != grf_names.End() ? gm->second.gc : NULL);
00309           if (gm == grf_names.End()) AddDebugText(buf, ". Gamelog inconsistency: GrfID was never added!");
00310           break;
00311         }
00312 
00313         case GLCT_EMERGENCY:
00314           break;
00315       }
00316 
00317       proc(buf);
00318     }
00319   }
00320 
00321   proc("---- gamelog end ----");
00322 }
00323 
00324 
00325 static void GamelogPrintConsoleProc(const char *s)
00326 {
00327   IConsolePrint(CC_WARNING, s);
00328 }
00329 
00330 void GamelogPrintConsole()
00331 {
00332   GamelogPrint(&GamelogPrintConsoleProc);
00333 }
00334 
00335 static int _gamelog_print_level = 0; 
00336 
00337 static void GamelogPrintDebugProc(const char *s)
00338 {
00339   DEBUG(gamelog, _gamelog_print_level, "%s", s);
00340 }
00341 
00342 
00349 void GamelogPrintDebug(int level)
00350 {
00351   _gamelog_print_level = level;
00352   GamelogPrint(&GamelogPrintDebugProc);
00353 }
00354 
00355 
00362 static LoggedChange *GamelogChange(GamelogChangeType ct)
00363 {
00364   if (_current_action == NULL) {
00365     if (_gamelog_action_type == GLAT_NONE) return NULL;
00366 
00367     _gamelog_action  = ReallocT(_gamelog_action, _gamelog_actions + 1);
00368     _current_action  = &_gamelog_action[_gamelog_actions++];
00369 
00370     _current_action->at      = _gamelog_action_type;
00371     _current_action->tick    = _tick_counter;
00372     _current_action->change  = NULL;
00373     _current_action->changes = 0;
00374   }
00375 
00376   _current_action->change = ReallocT(_current_action->change, _current_action->changes + 1);
00377 
00378   LoggedChange *lc = &_current_action->change[_current_action->changes++];
00379   lc->ct = ct;
00380 
00381   return lc;
00382 }
00383 
00384 
00388 void GamelogEmergency()
00389 {
00390   /* Terminate any active action */
00391   if (_gamelog_action_type != GLAT_NONE) GamelogStopAction();
00392   GamelogStartAction(GLAT_EMERGENCY);
00393   GamelogChange(GLCT_EMERGENCY);
00394   GamelogStopAction();
00395 }
00396 
00400 bool GamelogTestEmergency()
00401 {
00402   const LoggedChange *emergency = NULL;
00403 
00404   const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
00405   for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
00406     const LoggedChange *lcend = &la->change[la->changes];
00407     for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
00408       if (lc->ct == GLCT_EMERGENCY) emergency = lc;
00409     }
00410   }
00411 
00412   return (emergency != NULL);
00413 }
00414 
00418 void GamelogRevision()
00419 {
00420   assert(_gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_LOAD);
00421 
00422   LoggedChange *lc = GamelogChange(GLCT_REVISION);
00423   if (lc == NULL) return;
00424 
00425   memset(lc->revision.text, 0, sizeof(lc->revision.text));
00426   strecpy(lc->revision.text, _openttd_revision, lastof(lc->revision.text));
00427   lc->revision.slver = SAVEGAME_VERSION;
00428   lc->revision.modified = _openttd_revision_modified;
00429   lc->revision.newgrf = _openttd_newgrf_version;
00430 }
00431 
00435 void GamelogMode()
00436 {
00437   assert(_gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_LOAD || _gamelog_action_type == GLAT_CHEAT);
00438 
00439   LoggedChange *lc = GamelogChange(GLCT_MODE);
00440   if (lc == NULL) return;
00441 
00442   lc->mode.mode      = _game_mode;
00443   lc->mode.landscape = _settings_game.game_creation.landscape;
00444 }
00445 
00449 void GamelogOldver()
00450 {
00451   assert(_gamelog_action_type == GLAT_LOAD);
00452 
00453   LoggedChange *lc = GamelogChange(GLCT_OLDVER);
00454   if (lc == NULL) return;
00455 
00456   lc->oldver.type = _savegame_type;
00457   lc->oldver.version = (_savegame_type == SGT_OTTD ? ((uint32)_sl_version << 8 | _sl_minor_version) : _ttdp_version);
00458 }
00459 
00466 void GamelogSetting(const char *name, int32 oldval, int32 newval)
00467 {
00468   assert(_gamelog_action_type == GLAT_SETTING);
00469 
00470   LoggedChange *lc = GamelogChange(GLCT_SETTING);
00471   if (lc == NULL) return;
00472 
00473   lc->setting.name = strdup(name);
00474   lc->setting.oldval = oldval;
00475   lc->setting.newval = newval;
00476 }
00477 
00478 
00483 void GamelogTestRevision()
00484 {
00485   const LoggedChange *rev = NULL;
00486 
00487   const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
00488   for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
00489     const LoggedChange *lcend = &la->change[la->changes];
00490     for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
00491       if (lc->ct == GLCT_REVISION) rev = lc;
00492     }
00493   }
00494 
00495   if (rev == NULL || strcmp(rev->revision.text, _openttd_revision) != 0 ||
00496       rev->revision.modified != _openttd_revision_modified ||
00497       rev->revision.newgrf != _openttd_newgrf_version) {
00498     GamelogRevision();
00499   }
00500 }
00501 
00506 void GamelogTestMode()
00507 {
00508   const LoggedChange *mode = NULL;
00509 
00510   const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
00511   for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
00512     const LoggedChange *lcend = &la->change[la->changes];
00513     for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
00514       if (lc->ct == GLCT_MODE) mode = lc;
00515     }
00516   }
00517 
00518   if (mode == NULL || mode->mode.mode != _game_mode || mode->mode.landscape != _settings_game.game_creation.landscape) GamelogMode();
00519 }
00520 
00521 
00528 static void GamelogGRFBug(uint32 grfid, byte bug, uint64 data)
00529 {
00530   assert(_gamelog_action_type == GLAT_GRFBUG);
00531 
00532   LoggedChange *lc = GamelogChange(GLCT_GRFBUG);
00533   if (lc == NULL) return;
00534 
00535   lc->grfbug.data  = data;
00536   lc->grfbug.grfid = grfid;
00537   lc->grfbug.bug   = bug;
00538 }
00539 
00549 bool GamelogGRFBugReverse(uint32 grfid, uint16 internal_id)
00550 {
00551   const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
00552   for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
00553     const LoggedChange *lcend = &la->change[la->changes];
00554     for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
00555       if (lc->ct == GLCT_GRFBUG && lc->grfbug.grfid == grfid &&
00556           lc->grfbug.bug == GBUG_VEH_LENGTH && lc->grfbug.data == internal_id) {
00557         return false;
00558       }
00559     }
00560   }
00561 
00562   GamelogStartAction(GLAT_GRFBUG);
00563   GamelogGRFBug(grfid, GBUG_VEH_LENGTH, internal_id);
00564   GamelogStopAction();
00565 
00566   return true;
00567 }
00568 
00569 
00575 static inline bool IsLoggableGrfConfig(const GRFConfig *g)
00576 {
00577   return !HasBit(g->flags, GCF_STATIC) && g->status != GCS_NOT_FOUND;
00578 }
00579 
00584 void GamelogGRFRemove(uint32 grfid)
00585 {
00586   assert(_gamelog_action_type == GLAT_LOAD || _gamelog_action_type == GLAT_GRF);
00587 
00588   LoggedChange *lc = GamelogChange(GLCT_GRFREM);
00589   if (lc == NULL) return;
00590 
00591   lc->grfrem.grfid = grfid;
00592 }
00593 
00598 void GamelogGRFAdd(const GRFConfig *newg)
00599 {
00600   assert(_gamelog_action_type == GLAT_LOAD || _gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_GRF);
00601 
00602   if (!IsLoggableGrfConfig(newg)) return;
00603 
00604   LoggedChange *lc = GamelogChange(GLCT_GRFADD);
00605   if (lc == NULL) return;
00606 
00607   lc->grfadd = newg->ident;
00608 }
00609 
00615 void GamelogGRFCompatible(const GRFIdentifier *newg)
00616 {
00617   assert(_gamelog_action_type == GLAT_LOAD || _gamelog_action_type == GLAT_GRF);
00618 
00619   LoggedChange *lc = GamelogChange(GLCT_GRFCOMPAT);
00620   if (lc == NULL) return;
00621 
00622   lc->grfcompat = *newg;
00623 }
00624 
00630 static void GamelogGRFMove(uint32 grfid, int32 offset)
00631 {
00632   assert(_gamelog_action_type == GLAT_GRF);
00633 
00634   LoggedChange *lc = GamelogChange(GLCT_GRFMOVE);
00635   if (lc == NULL) return;
00636 
00637   lc->grfmove.grfid  = grfid;
00638   lc->grfmove.offset = offset;
00639 }
00640 
00646 static void GamelogGRFParameters(uint32 grfid)
00647 {
00648   assert(_gamelog_action_type == GLAT_GRF);
00649 
00650   LoggedChange *lc = GamelogChange(GLCT_GRFPARAM);
00651   if (lc == NULL) return;
00652 
00653   lc->grfparam.grfid = grfid;
00654 }
00655 
00661 void GamelogGRFAddList(const GRFConfig *newg)
00662 {
00663   assert(_gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_LOAD);
00664 
00665   for (; newg != NULL; newg = newg->next) {
00666     GamelogGRFAdd(newg);
00667   }
00668 }
00669 
00671 struct GRFList {
00672   uint n;
00673   const GRFConfig *grf[];
00674 };
00675 
00680 static GRFList *GenerateGRFList(const GRFConfig *grfc)
00681 {
00682   uint n = 0;
00683   for (const GRFConfig *g = grfc; g != NULL; g = g->next) {
00684     if (IsLoggableGrfConfig(g)) n++;
00685   }
00686 
00687   GRFList *list = (GRFList*)MallocT<byte>(sizeof(GRFList) + n * sizeof(GRFConfig*));
00688 
00689   list->n = 0;
00690   for (const GRFConfig *g = grfc; g != NULL; g = g->next) {
00691     if (IsLoggableGrfConfig(g)) list->grf[list->n++] = g;
00692   }
00693 
00694   return list;
00695 }
00696 
00702 void GamelogGRFUpdate(const GRFConfig *oldc, const GRFConfig *newc)
00703 {
00704   GRFList *ol = GenerateGRFList(oldc);
00705   GRFList *nl = GenerateGRFList(newc);
00706 
00707   uint o = 0, n = 0;
00708 
00709   while (o < ol->n && n < nl->n) {
00710     const GRFConfig *og = ol->grf[o];
00711     const GRFConfig *ng = nl->grf[n];
00712 
00713     if (og->ident.grfid != ng->ident.grfid) {
00714       uint oi, ni;
00715       for (oi = 0; oi < ol->n; oi++) {
00716         if (ol->grf[oi]->ident.grfid == nl->grf[n]->ident.grfid) break;
00717       }
00718       if (oi < o) {
00719         /* GRF was moved, this change has been logged already */
00720         n++;
00721         continue;
00722       }
00723       if (oi == ol->n) {
00724         /* GRF couldn't be found in the OLD list, GRF was ADDED */
00725         GamelogGRFAdd(nl->grf[n++]);
00726         continue;
00727       }
00728       for (ni = 0; ni < nl->n; ni++) {
00729         if (nl->grf[ni]->ident.grfid == ol->grf[o]->ident.grfid) break;
00730       }
00731       if (ni < n) {
00732         /* GRF was moved, this change has been logged already */
00733         o++;
00734         continue;
00735       }
00736       if (ni == nl->n) {
00737         /* GRF couldn't be found in the NEW list, GRF was REMOVED */
00738         GamelogGRFRemove(ol->grf[o++]->ident.grfid);
00739         continue;
00740       }
00741 
00742       /* o < oi < ol->n
00743        * n < ni < nl->n */
00744       assert(ni > n && ni < nl->n);
00745       assert(oi > o && oi < ol->n);
00746 
00747       ni -= n; // number of GRFs it was moved downwards
00748       oi -= o; // number of GRFs it was moved upwards
00749 
00750       if (ni >= oi) { // prefer the one that is moved further
00751         /* GRF was moved down */
00752         GamelogGRFMove(ol->grf[o++]->ident.grfid, ni);
00753       } else {
00754         GamelogGRFMove(nl->grf[n++]->ident.grfid, -(int)oi);
00755       }
00756     } else {
00757       if (memcmp(og->ident.md5sum, ng->ident.md5sum, sizeof(og->ident.md5sum)) != 0) {
00758         /* md5sum changed, probably loading 'compatible' GRF */
00759         GamelogGRFCompatible(&nl->grf[n]->ident);
00760       }
00761 
00762       if (og->num_params != ng->num_params || memcmp(og->param, ng->param, og->num_params * sizeof(og->param[0])) != 0) {
00763         GamelogGRFParameters(ol->grf[o]->ident.grfid);
00764       }
00765 
00766       o++;
00767       n++;
00768     }
00769   }
00770 
00771   while (o < ol->n) GamelogGRFRemove(ol->grf[o++]->ident.grfid); // remaining GRFs were removed ...
00772   while (n < nl->n) GamelogGRFAdd   (nl->grf[n++]);              // ... or added
00773 
00774   free(ol);
00775   free(nl);
00776 }

Generated on Sun Jan 9 16:01:54 2011 for OpenTTD by  doxygen 1.6.1