From c179b2f783f49d20de1d90b2e9adf22d92b18464 Mon Sep 17 00:00:00 2001 From: Kp Date: Sun, 31 Dec 2017 21:11:25 +0000 Subject: [PATCH] Load robot customizations before use AlexanderBorisov reported[1] a broken demo that ultimately traced to incorrect reuse of stale data. The campaign[2] includes per-level robot definitions for level 3. Descent incorrectly accessed Robot_info before reloading it for the new level, so it used the level 3 data on level 4 robots during a warm start of level 4 for regular play, but used only the level 4 data for a cold start of level 4 for regular play and for playback of a demo recorded solely on level 4. The particular customizations applied on level 3 caused a level 4 demo recorded with level 3 robot customizations to use different record lengths than a level 4 demo recorded with level 4 robot customizations. Since demos do not record their record lengths, mismatched record lengths lead to effectively corrupt demos. In this case, it manifested as writing 8 anim_angles (per model_num 108, the model incorrectly inherited from level 3) instead of 1 anim_angles (per model_num 37, used only on cold starts). The extra anim_angles were then misinterpreted as a run of 42 ND_EVENT_EOF, because the extra angles were unused and the newdemo code defines the null byte as EOF (separate from receiving an actual EOF indicator from the file I/O library). That run of spurious EOF caused the demo playback code to refuse to play past the spurious EOF, resulting in a seemingly broken demo. As an unfortunate, but unavoidable, consequence, this change modifies the common path (warm playthrough of every level in the campaign) to work like the uncommon path (cold start of each level). Further, the affected robot triggers a trap in d2x::do_silly_animation[3] when using the correct model_num, because that polygon model has too few models for the joints used by the robot. When using the incorrect level 3 data, the robot animates without trapping. [1] https://forum.dxx-rebirth.com/showthread.php?tid=1023 [2] http://www.enspiar.com/dmdb/viewMission.php?id=212 ``` sha1sum ENTROPY.HOG ENTROPY.MN2 7bc7a12d00a1ddd3ae92ce90eb67d581ecab004a ENTROPY.HOG f2688a634f22b30a02c43d8fa1a049deb5a03f70 ENTROPY.MN2 stat -c '%s %Y %n' ENTROPY.HOG ENTROPY.MN2 2402638 875757712 ENTROPY.HOG 511 875757164 ENTROPY.MN2 ``` [3] ``` 799 if (jointnum >= Polygon_models[objp.rtype.pobj_info.model_num].n_models) { 800 Int3(); // Contact Mike: incompatible data, illegal jointnum, problem in pof file? 801 continue; 802 } ``` --- similar/main/gameseq.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/similar/main/gameseq.cpp b/similar/main/gameseq.cpp index 0d609b286..9c815a8de 100644 --- a/similar/main/gameseq.cpp +++ b/similar/main/gameseq.cpp @@ -771,6 +771,8 @@ void LoadLevel(int level_num,int page_in_textures) gr_set_default_canvas(); gr_clear_canvas(*grd_curcanv, BM_XRGB(0, 0, 0)); //so palette switching is less obvious + load_level_robots(level_num); + int load_ret = load_level(level_name); //actually load the data from disk! if (load_ret) @@ -798,8 +800,6 @@ void LoadLevel(int level_num,int page_in_textures) else load_bitmap_replacements(level_name); - load_level_robots(level_num); - if ( page_in_textures ) piggy_load_level_data(); #endif