[Scummvm-tracker] [ScummVM :: Bugs] #14503: MM: XEEN: crash in carnage hand animation

ScummVM :: Bugs trac at scummvm.org
Sat Jun 10 10:38:39 UTC 2023


#14503: MM: XEEN: crash in carnage hand animation
--------------------+---------------------------------------------
Reporter:  yarolig  |       Owner:  (none)
    Type:  defect   |      Status:  new
Priority:  high     |   Component:  Engine: MM: Xeen
 Version:           |  Resolution:
Keywords:           |        Game:  Might and Magic: World of Xeen
--------------------+---------------------------------------------

Old description:

> Game crashes while showing carnage hand attack or hit animation.
>
> You can see this crash in mm4 endscene (say "showtime" to the mirror) or
> in the Darzog's Tower (save file attached).
>
> See also https://bugs.scummvm.org/ticket/14431#comment:2
>
> I have a dirty workaround:
> https://github.com/scummvm/scummvm/compare/master...yarolig:scummvm
> :carnage-hand-workaround
>
> The animation was ok in branch 2-7.
>
> Backtrace:
> {{{
> #0  __GI_raise (sig=sig at entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
> #1  0x00007ffff6a2d859 in __GI_abort () at abort.c:79
> #2  0x00007ffff6a2d729 in __assert_fail_base (fmt=0x7ffff6bc3588
> "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x55555653e408
> "_pos <= _size", file=0x55555653e365 "common/stream.cpp", line=132,
> function=<optimized out>)
>     at assert.c:92
> #3  0x00007ffff6a3efd6 in __GI___assert_fail (assertion=0x55555653e408
> "_pos <= _size", file=0x55555653e365 "common/stream.cpp", line=132,
> function=0x55555653e3d0 "virtual bool
> Common::MemoryReadStream::seek(int64, int)")
>     at assert.c:101
> #4  0x00005555561e2582 in Common::MemoryReadStream::seek(long, int)
> (this=0x7fffffffb400, offs=39457, whence=0) at common/stream.cpp:132
> #5  0x0000555555a1a5a0 in
> MM::Shared::Xeen::SpriteDrawer::draw(MM::Shared::Xeen::XSurface&,
> unsigned short, Common::Point const&, Common::Rect const&, unsigned int,
> int) (this=0x555557b2c750,
>     dest=..., offset=39457, pt=..., clipRect=..., flags=8192, scale=8) at
> engines/mm/shared/xeen/sprites.cpp:218
> #6  0x0000555555a19fde in
> MM::Shared::Xeen::SpriteResource::draw(MM::Shared::Xeen::XSurface&, int,
> Common::Point const&, Common::Rect const&, unsigned int, int) const
>     (this=0x555557b1eb08, dest=..., frame=3, destPos=..., bounds=...,
> flags=8192, scale=8) at engines/mm/shared/xeen/sprites.cpp:153
> #7  0x0000555555a0bd2b in
> MM::Xeen::SpriteResource::draw(MM::Xeen::Window&, int, Common::Point
> const&, unsigned int, int) (this=0x555557b1eb08, dest=..., frame=3,
> destPos=..., flags=8192, scale=8) at engines/mm/xeen/sprites.cpp:41
> #8  0x0000555555a0e7d1 in
> MM::Xeen::Window::drawList(MM::Xeen::DrawStruct*, int)
> (this=0x555557c63348, items=0x555557b8e928, count=170) at
> engines/mm/xeen/window.cpp:262
> #9  0x00005555559d831c in MM::Xeen::IndoorDrawList::draw()
> (this=0x555557b8d8a8) at engines/mm/xeen/interface_scene.cpp:389
> #10 0x00005555559e84ed in MM::Xeen::InterfaceScene::drawIndoors()
> (this=0x555557b8c680) at engines/mm/xeen/interface_scene.cpp:4406
> #11 0x00005555559da053 in MM::Xeen::InterfaceScene::drawIndoorsScene()
> (this=0x555557b8c680) at engines/mm/xeen/interface_scene.cpp:701
> #12 0x00005555559d86cc in MM::Xeen::InterfaceScene::drawScene()
> (this=0x555557b8c680) at engines/mm/xeen/interface_scene.cpp:449
> #13 0x00005555559ccb5e in MM::Xeen::Interface::draw3d(bool, bool)
> (this=0x555557b8c630, updateFlag=true, pauseFlag=true) at
> engines/mm/xeen/interface.cpp:1341
> #14 0x0000555555acdf57 in MM::Xeen::Combat::attack2(int,
> MM::Xeen::RangeType) (this=0x555557b5d230, damage=6,
> rangeType=MM::Xeen::RT_HIT) at engines/mm/xeen/combat.cpp:1482
> #15 0x0000555555acd562 in MM::Xeen::Combat::attack(MM::Xeen::Character&,
> MM::Xeen::RangeType) (this=0x555557b5d230, c=...,
> rangeType=MM::Xeen::RT_GROUP) at engines/mm/xeen/combat.cpp:1293
> #16 0x0000555555acfb15 in
> MM::Xeen::Combat::rangedAttack(MM::Xeen::PowType) (this=0x555557b5d230,
> powNum=MM::Xeen::POW_ARROW) at engines/mm/xeen/combat.cpp:1979
> #17 0x0000555555ad00f3 in MM::Xeen::Combat::shootRangedWeapon()
> (this=0x555557b5d230) at engines/mm/xeen/combat.cpp:2112
> #18 0x00005555559ca9a9 in MM::Xeen::Interface::perform()
> (this=0x555557b8c630) at engines/mm/xeen/interface.cpp:684
> #19 0x0000555555a10bd1 in MM::Xeen::XeenEngine::gameLoop()
> (this=0x555557b588a0) at engines/mm/xeen/xeen.cpp:285
> #20 0x0000555555a109fe in MM::Xeen::XeenEngine::play()
> (this=0x555557b588a0) at engines/mm/xeen/xeen.cpp:254
> #21 0x0000555555a10729 in MM::Xeen::XeenEngine::playGame()
> (this=0x555557b588a0) at engines/mm/xeen/xeen.cpp:210
> #22 0x0000555555a104c8 in MM::Xeen::XeenEngine::outerGameLoop()
> (this=0x555557b588a0) at engines/mm/xeen/xeen.cpp:165
> #23 0x0000555555a103ac in MM::Xeen::XeenEngine::run()
> (this=0x555557b588a0) at engines/mm/xeen/xeen.cpp:140
> #24 0x000055555595ca1f in runGame(Plugin const*, Plugin const*, OSystem&,
> Common::String const&) (plugin=0x555557033b20,
> enginePlugin=0x555556ef59d0, system=..., debugLevels=...) at
> base/main.cpp:318
> #25 0x000055555595ebbb in scummvm_main(int, char const* const*) (argc=1,
> argv=0x7fffffffdf08) at base/main.cpp:758
> #26 0x0000555555959aac in main(int, char**) (argc=1, argv=0x7fffffffdf08)
> at backends/platform/sdl/posix/posix-main.cpp:44
> }}}

New description:

 Game crashes while showing carnage hand attack or hit animation.

 You can see this crash in mm4 endscene (say "showtime" to the mirror) or
 in the Darzog's Tower (save file attached).

 See also https://bugs.scummvm.org/ticket/14431#comment:2

 I had a dirty workaround:
 {{{
 diff --git a/engines/mm/shared/xeen/sprites.cpp
 b/engines/mm/shared/xeen/sprites.cpp
 index 97fa01aa11b..ce5c377fc3c 100644
 --- a/engines/mm/shared/xeen/sprites.cpp
 +++ b/engines/mm/shared/xeen/sprites.cpp
 @@ -213,6 +213,12 @@ void SpriteDrawer::draw(XSurface &dest, uint16
 offset, const Common::Point &pt,
         _destBottom = (byte *)dest.getBasePtr(clipRect.right,
 clipRect.bottom - 1);
         _pitch = dest.pitch;

 +       // WORKAROUND for carnage hand
 +       if (_filesize == 5526) {
 +               if (offset > _filesize || offset == 86 || offset == 3584)
 +                       return;
 +       }
 +
         // Get cell header
         Common::MemoryReadStream f(_data, _filesize);
         f.seek(offset);
 }}}

 And now it less dirty:
 {{{
 diff --git a/engines/mm/shared/xeen/sprites.cpp
 b/engines/mm/shared/xeen/sprites.cpp
 index 97fa01aa11b..859818ddb66 100644
 --- a/engines/mm/shared/xeen/sprites.cpp
 +++ b/engines/mm/shared/xeen/sprites.cpp
 @@ -80,7 +80,7 @@ SpriteResource &SpriteResource::operator=(const
 SpriteResource &src) {
  void SpriteResource::load(const Common::String &filename) {
         _filename = filename;
         Common::File f;
 -       if (f.open(filename)) {
 +       if (g_engine->getGameID() == GType_MightAndMagic1 &&
 f.open(filename)) {
                 load(f);
         } else {
                 File f2(filename);
 }}}

 I'm posting a pull request if you are ok with that
 https://github.com/scummvm/scummvm/pull/5084

 The animation was ok in branch 2-7.

 Backtrace:
 {{{
 #0  __GI_raise (sig=sig at entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
 #1  0x00007ffff6a2d859 in __GI_abort () at abort.c:79
 #2  0x00007ffff6a2d729 in __assert_fail_base (fmt=0x7ffff6bc3588
 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x55555653e408
 "_pos <= _size", file=0x55555653e365 "common/stream.cpp", line=132,
 function=<optimized out>)
     at assert.c:92
 #3  0x00007ffff6a3efd6 in __GI___assert_fail (assertion=0x55555653e408
 "_pos <= _size", file=0x55555653e365 "common/stream.cpp", line=132,
 function=0x55555653e3d0 "virtual bool
 Common::MemoryReadStream::seek(int64, int)")
     at assert.c:101
 #4  0x00005555561e2582 in Common::MemoryReadStream::seek(long, int)
 (this=0x7fffffffb400, offs=39457, whence=0) at common/stream.cpp:132
 #5  0x0000555555a1a5a0 in
 MM::Shared::Xeen::SpriteDrawer::draw(MM::Shared::Xeen::XSurface&, unsigned
 short, Common::Point const&, Common::Rect const&, unsigned int, int)
 (this=0x555557b2c750,
     dest=..., offset=39457, pt=..., clipRect=..., flags=8192, scale=8) at
 engines/mm/shared/xeen/sprites.cpp:218
 #6  0x0000555555a19fde in
 MM::Shared::Xeen::SpriteResource::draw(MM::Shared::Xeen::XSurface&, int,
 Common::Point const&, Common::Rect const&, unsigned int, int) const
     (this=0x555557b1eb08, dest=..., frame=3, destPos=..., bounds=...,
 flags=8192, scale=8) at engines/mm/shared/xeen/sprites.cpp:153
 #7  0x0000555555a0bd2b in
 MM::Xeen::SpriteResource::draw(MM::Xeen::Window&, int, Common::Point
 const&, unsigned int, int) (this=0x555557b1eb08, dest=..., frame=3,
 destPos=..., flags=8192, scale=8) at engines/mm/xeen/sprites.cpp:41
 #8  0x0000555555a0e7d1 in
 MM::Xeen::Window::drawList(MM::Xeen::DrawStruct*, int)
 (this=0x555557c63348, items=0x555557b8e928, count=170) at
 engines/mm/xeen/window.cpp:262
 #9  0x00005555559d831c in MM::Xeen::IndoorDrawList::draw()
 (this=0x555557b8d8a8) at engines/mm/xeen/interface_scene.cpp:389
 #10 0x00005555559e84ed in MM::Xeen::InterfaceScene::drawIndoors()
 (this=0x555557b8c680) at engines/mm/xeen/interface_scene.cpp:4406
 #11 0x00005555559da053 in MM::Xeen::InterfaceScene::drawIndoorsScene()
 (this=0x555557b8c680) at engines/mm/xeen/interface_scene.cpp:701
 #12 0x00005555559d86cc in MM::Xeen::InterfaceScene::drawScene()
 (this=0x555557b8c680) at engines/mm/xeen/interface_scene.cpp:449
 #13 0x00005555559ccb5e in MM::Xeen::Interface::draw3d(bool, bool)
 (this=0x555557b8c630, updateFlag=true, pauseFlag=true) at
 engines/mm/xeen/interface.cpp:1341
 #14 0x0000555555acdf57 in MM::Xeen::Combat::attack2(int,
 MM::Xeen::RangeType) (this=0x555557b5d230, damage=6,
 rangeType=MM::Xeen::RT_HIT) at engines/mm/xeen/combat.cpp:1482
 #15 0x0000555555acd562 in MM::Xeen::Combat::attack(MM::Xeen::Character&,
 MM::Xeen::RangeType) (this=0x555557b5d230, c=...,
 rangeType=MM::Xeen::RT_GROUP) at engines/mm/xeen/combat.cpp:1293
 #16 0x0000555555acfb15 in
 MM::Xeen::Combat::rangedAttack(MM::Xeen::PowType) (this=0x555557b5d230,
 powNum=MM::Xeen::POW_ARROW) at engines/mm/xeen/combat.cpp:1979
 #17 0x0000555555ad00f3 in MM::Xeen::Combat::shootRangedWeapon()
 (this=0x555557b5d230) at engines/mm/xeen/combat.cpp:2112
 #18 0x00005555559ca9a9 in MM::Xeen::Interface::perform()
 (this=0x555557b8c630) at engines/mm/xeen/interface.cpp:684
 #19 0x0000555555a10bd1 in MM::Xeen::XeenEngine::gameLoop()
 (this=0x555557b588a0) at engines/mm/xeen/xeen.cpp:285
 #20 0x0000555555a109fe in MM::Xeen::XeenEngine::play()
 (this=0x555557b588a0) at engines/mm/xeen/xeen.cpp:254
 #21 0x0000555555a10729 in MM::Xeen::XeenEngine::playGame()
 (this=0x555557b588a0) at engines/mm/xeen/xeen.cpp:210
 #22 0x0000555555a104c8 in MM::Xeen::XeenEngine::outerGameLoop()
 (this=0x555557b588a0) at engines/mm/xeen/xeen.cpp:165
 #23 0x0000555555a103ac in MM::Xeen::XeenEngine::run()
 (this=0x555557b588a0) at engines/mm/xeen/xeen.cpp:140
 #24 0x000055555595ca1f in runGame(Plugin const*, Plugin const*, OSystem&,
 Common::String const&) (plugin=0x555557033b20,
 enginePlugin=0x555556ef59d0, system=..., debugLevels=...) at
 base/main.cpp:318
 #25 0x000055555595ebbb in scummvm_main(int, char const* const*) (argc=1,
 argv=0x7fffffffdf08) at base/main.cpp:758
 #26 0x0000555555959aac in main(int, char**) (argc=1, argv=0x7fffffffdf08)
 at backends/platform/sdl/posix/posix-main.cpp:44
 }}}

--
Comment (by yarolig):

 looks like a Common::File calls
 CCArchive::createReadStreamForMember("049.att."), which calls
 BaseCCArchive::getHeaderEntry which tries to convert file name to resource
 id.

 In case of file name "049.att." it is converted to existing resource with
 id=55679 and file size 5526.

 The dot "." was added in Common:: File::Open
 {{{
         if ((stream = archive.createReadStreamForMember(filename))) {
                 debug(8, "Opening hashed: %s",
 filename.toString().c_str());
         } else if ((stream =
 archive.createReadStreamForMember(filename.append(".")))) {
                 // WORKAROUND: Bug #2548: "SIMON1: Game Detection fails"
                 // sometimes instead of "GAMEPC" we get "GAMEPC." (note
 trailing dot)
                 debug(8, "Opening hashed: %s.",
 filename.toString().c_str());
         }
 }}}

 I guess that resource loading by ID is a MM1 thing, so my best workaround
 now is:
 {{{
 void SpriteResource::load(const Common::String &filename) {
         _filename = filename;
         Common::File f;

         if (g_engine->getGameID() == GType_MightAndMagic1 &&
 f.open(filename)) {
                 load(f);
         } else {
                 File f2(filename);
                 load(f2);
         }
 }

 }}}
-- 
Ticket URL: <https://bugs.scummvm.org/ticket/14503#comment:7>
ScummVM :: Bugs <https://bugs.scummvm.org>
ScummVM


More information about the Scummvm-tracker mailing list