From 7efbb049998793ad7da209ee72b685fb25f74592 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 23 Apr 2024 04:03:10 -0400 Subject: [PATCH 1/9] Implement/match LegoAnimPresenter::FUN_1006ab70 (#839) --- LEGO1/lego/legoomni/include/legoanimationmanager.h | 5 +++++ .../legoomni/src/common/legoanimationmanager.cpp | 12 ++++++++++++ LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp | 10 ++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index 2076c181..6341147d 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -8,6 +8,9 @@ #include "legotraninfolist.h" #include "mxcore.h" +class LegoAnimPresenter; +class LegoROIList; + // SIZE 0x18 struct Character { char* m_name; // 0x00 @@ -92,6 +95,8 @@ class LegoAnimationManager : public MxCore { void FUN_10062770(); void FUN_100627d0(MxBool); void FUN_100629b0(MxU32, MxBool); + void FUN_10063270(LegoROIList*, LegoAnimPresenter*); + void FUN_10063780(LegoROIList*); void FUN_10064670(MxBool); void FUN_10064740(MxBool); diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index 581f0f2c..fa3ce08b 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -621,6 +621,18 @@ void LegoAnimationManager::FUN_100629b0(MxU32, MxBool) // TODO } +// STUB: LEGO1 0x10063270 +void LegoAnimationManager::FUN_10063270(LegoROIList*, LegoAnimPresenter*) +{ + // TODO +} + +// STUB: LEGO1 0x10063780 +void LegoAnimationManager::FUN_10063780(LegoROIList*) +{ + // TODO +} + // STUB: LEGO1 0x10064670 void LegoAnimationManager::FUN_10064670(MxBool) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 1ace1292..61f93450 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -1,5 +1,6 @@ #include "legoanimpresenter.h" +#include "legoanimationmanager.h" #include "legoanimmmpresenter.h" #include "legocharactermanager.h" #include "legovideomanager.h" @@ -449,10 +450,15 @@ void LegoAnimPresenter::FUN_1006a4f0( } } -// STUB: LEGO1 0x1006ab70 +// FUNCTION: LEGO1 0x1006ab70 void LegoAnimPresenter::FUN_1006ab70() { - // TODO + if (m_unk0x96) { + AnimationManager()->FUN_10063270(m_unk0x74, this); + } + else { + AnimationManager()->FUN_10063780(m_unk0x74); + } } // FUNCTION: LEGO1 0x1006aba0 From 9025d5ed069f1128ea50e3c633c4312550d2f195 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 23 Apr 2024 04:33:38 -0400 Subject: [PATCH 2/9] Implement/match LegoWorld::FUN_1001fda0 (#840) --- LEGO1/lego/legoomni/include/legopathcontroller.h | 2 ++ LEGO1/lego/legoomni/src/entity/legoworld.cpp | 10 ++++++++-- LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp | 6 ++++++ LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp | 1 + 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h index 35bf5aa5..c9037091 100644 --- a/LEGO1/lego/legoomni/include/legopathcontroller.h +++ b/LEGO1/lego/legoomni/include/legopathcontroller.h @@ -5,6 +5,7 @@ #include "legopathactor.h" #include "mxcore.h" +class LegoAnimPresenter; class LegoPathBoundary; class LegoWorld; @@ -41,6 +42,7 @@ class LegoPathController : public MxCore { virtual void Destroy(); // vtable+0x18 undefined4 FUN_10046770(LegoPathActor* p_actor); + void FUN_100468f0(LegoAnimPresenter* p_presenter); MxResult FUN_10046b30(LegoPathBoundary** p_path, MxS32& p_value); void Enable(MxBool p_enable); void FUN_10046bb0(LegoWorld* p_world); diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index cc2ea8b3..cf42b0e3 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -299,10 +299,16 @@ void LegoWorld::FUN_1001fc80(IslePathActor* p_actor) } } -// STUB: LEGO1 0x1001fda0 +// FUNCTION: LEGO1 0x1001fda0 +// FUNCTION: BETA10 0x100da621 void LegoWorld::FUN_1001fda0(LegoAnimPresenter* p_presenter) { - // TODO + LegoPathControllerListCursor cursor(&m_list0x68); + LegoPathController* controller; + + while (cursor.Next(controller)) { + controller->FUN_100468f0(p_presenter); + } } // FUNCTION: LEGO1 0x1001ff80 diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp index e2e9056a..51c6e723 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp @@ -33,6 +33,12 @@ undefined4 LegoPathController::FUN_10046770(LegoPathActor* p_actor) return 0; } +// STUB: LEGO1 0x100468f0 +// FUNCTION: BETA10 0x100b72f7 +void LegoPathController::FUN_100468f0(LegoAnimPresenter* p_presenter) +{ +} + // STUB: LEGO1 0x10046b30 MxResult LegoPathController::FUN_10046b30(LegoPathBoundary** p_path, MxS32& p_value) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 61f93450..6a1583f2 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -814,6 +814,7 @@ void LegoAnimPresenter::EndAction() } // FUNCTION: LEGO1 0x1006c7d0 +// FUNCTION: BETA10 0x10051e07 void LegoAnimPresenter::VTable0x8c() { if (m_unk0x78) { From 41be78ed1c845e2d40c1559fdfa9d6b90f28c37c Mon Sep 17 00:00:00 2001 From: MS Date: Tue, 23 Apr 2024 17:06:43 -0400 Subject: [PATCH 3/9] Pointer substitution can use offset into variable (#841) --- .../isledecomp/compare/asm/parse.py | 10 +++-- tools/isledecomp/isledecomp/compare/core.py | 43 ++++++++++++++++--- tools/isledecomp/isledecomp/compare/db.py | 42 ++++++++++++++++-- tools/isledecomp/tests/test_sanitize.py | 12 +++--- tools/reccmp/reccmp.py | 3 ++ 5 files changed, 91 insertions(+), 19 deletions(-) diff --git a/tools/isledecomp/isledecomp/compare/asm/parse.py b/tools/isledecomp/isledecomp/compare/asm/parse.py index 93c28f03..a8ce153e 100644 --- a/tools/isledecomp/isledecomp/compare/asm/parse.py +++ b/tools/isledecomp/isledecomp/compare/asm/parse.py @@ -56,7 +56,7 @@ class ParseAsm: def __init__( self, relocate_lookup: Optional[Callable[[int], bool]] = None, - name_lookup: Optional[Callable[[int], str]] = None, + name_lookup: Optional[Callable[[int, bool], str]] = None, bin_lookup: Optional[Callable[[int, int], Optional[bytes]]] = None, ) -> None: self.relocate_lookup = relocate_lookup @@ -86,13 +86,15 @@ def float_replace(self, addr: int, data_size: int) -> Optional[str]: return None - def lookup(self, addr: int, use_cache: bool = True) -> Optional[str]: + def lookup( + self, addr: int, use_cache: bool = True, exact: bool = False + ) -> Optional[str]: """Return a replacement name for this address if we find one.""" if use_cache and (cached := self.replacements.get(addr, None)) is not None: return cached if callable(self.name_lookup): - if (name := self.name_lookup(addr)) is not None: + if (name := self.name_lookup(addr, exact)) is not None: if use_cache: self.replacements[addr] = name @@ -210,7 +212,7 @@ def sanitize(self, inst: DisasmLiteInst) -> Tuple[str, str]: # If we have a name for this address, use it. If not, # do not create a new placeholder. We will instead # fall through to generic jump handling below. - potential_name = self.lookup(op_str_address) + potential_name = self.lookup(op_str_address, exact=True) if potential_name is not None: return (inst.mnemonic, potential_name) diff --git a/tools/isledecomp/isledecomp/compare/core.py b/tools/isledecomp/isledecomp/compare/core.py index ce145dae..c66cee94 100644 --- a/tools/isledecomp/isledecomp/compare/core.py +++ b/tools/isledecomp/isledecomp/compare/core.py @@ -2,6 +2,7 @@ import logging import difflib import struct +import uuid from dataclasses import dataclass from typing import Callable, Iterable, List, Optional from isledecomp.bin import Bin as IsleBin, InvalidVirtualAddressError @@ -71,6 +72,9 @@ def __init__( self.recomp_bin = recomp_bin self.pdb_file = pdb_file self.code_dir = code_dir + # Controls whether we dump the asm output to a file + self.debug: bool = False + self.runid: str = uuid.uuid4().hex[:8] self._lines_db = LinesDb(code_dir) self._db = CompareDb() @@ -452,6 +456,16 @@ def _find_vtordisp(self): ) self._db.set_function_pair(orig_addr, recomp_addr) + def _dump_asm(self, orig_combined, recomp_combined): + """Append the provided assembly output to the debug files""" + with open(f"orig-{self.runid}.txt", "a", encoding="utf-8") as f: + for addr, line in orig_combined: + f.write(f"{addr}: {line}\n") + + with open(f"recomp-{self.runid}.txt", "a", encoding="utf-8") as f: + for addr, line in recomp_combined: + f.write(f"{addr}: {line}\n") + def _compare_function(self, match: MatchInfo) -> DiffReport: # Detect when the recomp function size would cause us to read # enough bytes from the original function that we cross into @@ -478,19 +492,33 @@ def _compare_function(self, match: MatchInfo) -> DiffReport: except IndexError: pass - def orig_lookup(addr: int) -> Optional[str]: - m = self._db.get_by_orig(addr) + def orig_lookup(addr: int, exact: bool) -> Optional[str]: + m = self._db.get_by_orig(addr, exact) if m is None: return None - return m.match_name() + if m.orig_addr == addr: + return m.match_name() - def recomp_lookup(addr: int) -> Optional[str]: - m = self._db.get_by_recomp(addr) + offset = addr - m.orig_addr + if m.compare_type != SymbolType.DATA or offset >= m.size: + return None + + return m.offset_name(offset) + + def recomp_lookup(addr: int, exact: bool) -> Optional[str]: + m = self._db.get_by_recomp(addr, exact) if m is None: return None - return m.match_name() + if m.recomp_addr == addr: + return m.match_name() + + offset = addr - m.recomp_addr + if m.compare_type != SymbolType.DATA or offset >= m.size: + return None + + return m.offset_name(offset) orig_should_replace = create_reloc_lookup(self.orig_bin) recomp_should_replace = create_reloc_lookup(self.recomp_bin) @@ -512,6 +540,9 @@ def recomp_lookup(addr: int) -> Optional[str]: orig_combined = orig_parse.parse_asm(orig_raw, match.orig_addr) recomp_combined = recomp_parse.parse_asm(recomp_raw, match.recomp_addr) + if self.debug: + self._dump_asm(orig_combined, recomp_combined) + # Detach addresses from asm lines for the text diff. orig_asm = [x[1] for x in orig_combined] recomp_asm = [x[1] for x in recomp_combined] diff --git a/tools/isledecomp/isledecomp/compare/db.py b/tools/isledecomp/isledecomp/compare/db.py index e912c8af..f055e8fd 100644 --- a/tools/isledecomp/isledecomp/compare/db.py +++ b/tools/isledecomp/isledecomp/compare/db.py @@ -53,7 +53,7 @@ def __init__( self.name = name self.size = size - def match_name(self) -> str: + def match_name(self) -> Optional[str]: """Combination of the name and compare type. Intended for name substitution in the diff. If there is a diff, it will be more obvious what this symbol indicates.""" @@ -64,6 +64,12 @@ def match_name(self) -> str: name = repr(self.name) if ctype == "STRING" else self.name return f"{name} ({ctype})" + def offset_name(self, ofs: int) -> Optional[str]: + if self.name is None: + return None + + return f"{self.name}+{ofs} (OFFSET)" + def matchinfo_factory(_, row): return MatchInfo(*row) @@ -135,7 +141,32 @@ def get_one_match(self, addr: int) -> Optional[MatchInfo]: cur.row_factory = matchinfo_factory return cur.fetchone() - def get_by_orig(self, addr: int) -> Optional[MatchInfo]: + def _get_closest_orig(self, addr: int) -> Optional[int]: + value = self._db.execute( + """SELECT max(orig_addr) FROM `symbols` + WHERE ? >= orig_addr + LIMIT 1 + """, + (addr,), + ).fetchone() + return value[0] if value is not None else None + + def _get_closest_recomp(self, addr: int) -> Optional[int]: + value = self._db.execute( + """SELECT max(recomp_addr) FROM `symbols` + WHERE ? >= recomp_addr + LIMIT 1 + """, + (addr,), + ).fetchone() + return value[0] if value is not None else None + + def get_by_orig(self, addr: int, exact: bool = True) -> Optional[MatchInfo]: + if not exact and not self._orig_used(addr): + addr = self._get_closest_orig(addr) + if addr is None: + return None + cur = self._db.execute( """SELECT * FROM `match_info` WHERE orig_addr = ? @@ -145,7 +176,12 @@ def get_by_orig(self, addr: int) -> Optional[MatchInfo]: cur.row_factory = matchinfo_factory return cur.fetchone() - def get_by_recomp(self, addr: int) -> Optional[MatchInfo]: + def get_by_recomp(self, addr: int, exact: bool = True) -> Optional[MatchInfo]: + if not exact and not self._recomp_used(addr): + addr = self._get_closest_recomp(addr) + if addr is None: + return None + cur = self._db.execute( """SELECT * FROM `match_info` WHERE recomp_addr = ? diff --git a/tools/isledecomp/tests/test_sanitize.py b/tools/isledecomp/tests/test_sanitize.py index 57097bf9..ca23c861 100644 --- a/tools/isledecomp/tests/test_sanitize.py +++ b/tools/isledecomp/tests/test_sanitize.py @@ -113,7 +113,7 @@ def relocate_lookup(addr: int) -> bool: def test_name_replace(start, end): """Make sure the name lookup function is called if present""" - def substitute(_: int) -> str: + def substitute(_: int, __: bool) -> str: return "_substitute_" p = ParseAsm(name_lookup=substitute) @@ -137,7 +137,7 @@ def test_replacement_numbering(): """If we can use the name lookup for the first address but not the second, the second replacement should be not .""" - def substitute_1234(addr: int) -> Optional[str]: + def substitute_1234(addr: int, _: bool) -> Optional[str]: return "_substitute_" if addr == 0x1234 else None p = ParseAsm(name_lookup=substitute_1234) @@ -171,7 +171,7 @@ def test_jump_to_function(): assume this is the case for all jumps. Only replace the jump with a name if we can find it using our lookup.""" - def substitute_1234(addr: int) -> Optional[str]: + def substitute_1234(addr: int, _: bool) -> Optional[str]: return "_substitute_" if addr == 0x1234 else None p = ParseAsm(name_lookup=substitute_1234) @@ -212,7 +212,7 @@ def test_float_variable(): """If there is a variable at the address referenced by a float instruction, use the name instead of calling into the float replacement handler.""" - def name_lookup(addr: int) -> Optional[str]: + def name_lookup(addr: int, _: bool) -> Optional[str]: return "g_myFloatVariable" if addr == 0x1234 else None p = ParseAsm(name_lookup=name_lookup) @@ -234,7 +234,7 @@ def relocate_lookup(addr: int) -> bool: return addr in (0x1234, 0x5555) # Only 0x5555 is a "known" address - def name_lookup(addr: int) -> Optional[str]: + def name_lookup(addr: int, _: bool) -> Optional[str]: return "hello" if addr == 0x5555 else None p = ParseAsm(relocate_lookup=relocate_lookup, name_lookup=name_lookup) @@ -263,7 +263,7 @@ def test_absolute_indirect(): we have it, but there are some circumstances where we want to replace with the pointer's name (i.e. an import function).""" - def name_lookup(addr: int) -> Optional[str]: + def name_lookup(addr: int, _: bool) -> Optional[str]: return { 0x1234: "Hello", 0x4321: "xyz", diff --git a/tools/reccmp/reccmp.py b/tools/reccmp/reccmp.py index 84266773..bcdb0899 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -241,6 +241,9 @@ def main(): isle_compare = IsleCompare(origfile, recompfile, args.pdb, args.decomp_dir) + if args.loglevel == logging.DEBUG: + isle_compare.debug = True + print() ### Compare one or none. From 67c9736953b1d686bfd9fea452844eb23d19acd1 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 24 Apr 2024 08:24:59 -0400 Subject: [PATCH 4/9] Implement/match LegoAnimPresenter::FUN_1006afc0 (#843) * Implement/match LegoAnimPresenter::FUN_1006afc0 * empty --- .../lego/legoomni/include/legoanimpresenter.h | 3 +- .../legoomni/src/video/legoanimpresenter.cpp | 34 +++++++++++++++++-- LEGO1/mxgeometry/mxmatrix.h | 3 +- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index aed665ae..0c2f3dcf 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -73,7 +73,7 @@ class LegoAnimPresenter : public MxVideoPresenter { virtual void VTable0xa0(Matrix4*); // vtable+0xa0 - MxResult FUN_1006afc0(MxMatrix*&, undefined4); + MxResult FUN_1006afc0(MxMatrix*& p_matrix, float p_und); MxResult FUN_1006b140(LegoROI* p_roi); void FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value); @@ -97,6 +97,7 @@ class LegoAnimPresenter : public MxVideoPresenter { LegoBool FUN_1006aba0(); MxBool FUN_1006abb0(LegoTreeNode* p_node, LegoROI* p_roi); void FUN_1006ac90(); + void FUN_1006b900(LegoAnim* p_anim, MxS32 p_und, MxMatrix* p_matrix); void FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix); void FUN_1006c8a0(MxBool p_bool); diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 6a1583f2..87cf6ae6 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -577,11 +577,32 @@ void LegoAnimPresenter::PutFrame() } } -// STUB: LEGO1 0x1006afc0 +// FUNCTION: LEGO1 0x1006afc0 // FUNCTION: BETA10 0x1005059a -MxResult LegoAnimPresenter::FUN_1006afc0(MxMatrix*&, undefined4) +MxResult LegoAnimPresenter::FUN_1006afc0(MxMatrix*& p_matrix, float p_und) { - // TODO + MxU32 length = m_roiMapSize + 1; + p_matrix = new MxMatrix[length]; + + MxS32 i; + for (i = 1; i < length; i++) { + if (m_roiMap[i] != NULL) { + p_matrix[i] = m_roiMap[i]->GetLocal2World(); + } + } + + FUN_1006b900(m_anim, p_und, m_unk0x78); + + for (i = 1; i < length; i++) { + MxMatrix mat; + + if (m_roiMap[i] != NULL) { + mat = p_matrix[i]; + p_matrix[i] = m_roiMap[i]->GetLocal2World(); + m_roiMap[i]->FUN_100a58f0(mat); + } + } + return SUCCESS; } @@ -720,6 +741,13 @@ const char* LegoAnimPresenter::GetActionObjectName() return m_action->GetObjectName(); } +// STUB: LEGO1 0x1006b900 +// FUNCTION: BETA10 0x100510d8 +void LegoAnimPresenter::FUN_1006b900(LegoAnim* p_anim, MxS32 p_und, MxMatrix* p_matrix) +{ + // TODO +} + // FUNCTION: LEGO1 0x1006b9a0 void LegoAnimPresenter::FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix) { diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h index abbc92f5..f6d0cece 100644 --- a/LEGO1/mxgeometry/mxmatrix.h +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -7,6 +7,7 @@ // SIZE 0x48 class MxMatrix : public Matrix4 { public: + // FUNCTION: LEGO1 0x1006b120 inline MxMatrix() : Matrix4(m_elements) {} // FUNCTION: LEGO1 0x10032770 @@ -26,7 +27,7 @@ class MxMatrix : public Matrix4 { virtual void operator=(const MxMatrix& p_matrix) { Equals(p_matrix); } // vtable+0x48 private: - float m_elements[4][4]; + float m_elements[4][4]; // 0x08 }; #endif // MXMATRIX_H From b789a15d0b764b9b65230412e5a01612fdd91233 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 24 Apr 2024 08:51:20 -0400 Subject: [PATCH 5/9] Implement/match LegoAnimPresenter::FUN_1006b900 (#844) --- .../lego/legoomni/include/legoanimpresenter.h | 2 +- .../legoomni/src/video/legoanimpresenter.cpp | 24 ++++++++++++++++--- LEGO1/lego/sources/roi/legoroi.cpp | 15 ++++++++---- LEGO1/lego/sources/roi/legoroi.h | 3 ++- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 0c2f3dcf..02a81b37 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -97,7 +97,7 @@ class LegoAnimPresenter : public MxVideoPresenter { LegoBool FUN_1006aba0(); MxBool FUN_1006abb0(LegoTreeNode* p_node, LegoROI* p_roi); void FUN_1006ac90(); - void FUN_1006b900(LegoAnim* p_anim, MxS32 p_und, MxMatrix* p_matrix); + void FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix); void FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix); void FUN_1006c8a0(MxBool p_bool); diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 87cf6ae6..892bc06f 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -741,11 +741,29 @@ const char* LegoAnimPresenter::GetActionObjectName() return m_action->GetObjectName(); } -// STUB: LEGO1 0x1006b900 +// FUNCTION: LEGO1 0x1006b900 // FUNCTION: BETA10 0x100510d8 -void LegoAnimPresenter::FUN_1006b900(LegoAnim* p_anim, MxS32 p_und, MxMatrix* p_matrix) +void LegoAnimPresenter::FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix) { - // TODO + LegoTreeNode* root = p_anim->GetRoot(); + MxMatrix mat; + LegoAnimNodeData* data = (LegoAnimNodeData*) root->GetData(); + + if (p_matrix != NULL) { + mat = *p_matrix; + } + else { + LegoROI* roi = m_roiMap[data->GetUnknown0x20()]; + + if (roi != NULL) { + mat = roi->GetLocal2World(); + } + else { + mat.SetIdentity(); + } + } + + LegoROI::FUN_100a8fd0(root, mat, p_time, m_roiMap); } // FUNCTION: LEGO1 0x1006b9a0 diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index c18b5de6..0bbed5da 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -405,14 +405,14 @@ LegoResult LegoROI::FUN_100a8da0(LegoTreeNode* p_node, const Matrix4& p_matrix, } // FUNCTION: LEGO1 0x100a8e80 -void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_rois) +void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap) { MxMatrix mat; LegoAnimNodeData* data = (LegoAnimNodeData*) p_node->GetData(); FUN_100a8cb0(data, p_time, mat); - LegoROI* roi = p_rois[data->GetUnknown0x20()]; + LegoROI* roi = p_roiMap[data->GetUnknown0x20()]; if (roi != NULL) { roi->m_local2world.Product(mat, p_matrix); roi->VTable0x1c(); @@ -421,7 +421,7 @@ void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_t roi->SetVisibility(und); for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { - FUN_100a8e80(p_node->GetChild(i), roi->m_local2world, p_time, p_rois); + FUN_100a8e80(p_node->GetChild(i), roi->m_local2world, p_time, p_roiMap); } } else { @@ -429,11 +429,18 @@ void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_t local2world.Product(mat, p_matrix); for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { - FUN_100a8e80(p_node->GetChild(i), local2world, p_time, p_rois); + FUN_100a8e80(p_node->GetChild(i), local2world, p_time, p_roiMap); } } } +// STUB: LEGO1 0x100a8fd0 +// FUNCTION: BETA10 0x1018ac81 +void LegoROI::FUN_100a8fd0(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap) +{ + // TODO +} + // FUNCTION: LEGO1 0x100a90f0 LegoResult LegoROI::SetFrame(LegoAnim* p_anim, LegoTime p_time) { diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index 34b5f809..64002d30 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -32,7 +32,8 @@ class LegoROI : public ViewROI { ); LegoROI* FindChildROI(const LegoChar* p_name, LegoROI* p_roi); LegoResult FUN_100a8da0(LegoTreeNode* p_node, const Matrix4& p_matrix, LegoTime p_time, LegoROI* p_roi); - static void FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_rois); + static void FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap); + static void FUN_100a8fd0(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap); LegoResult SetFrame(LegoAnim* p_anim, LegoTime p_time); LegoResult FUN_100a9170(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); LegoResult FUN_100a9210(LegoTextureInfo* p_textureInfo); From f898462d17352c1ed811d2bd75d4b634010cd781 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 24 Apr 2024 09:19:14 -0400 Subject: [PATCH 6/9] Implement/match LegoROI::FUN_100a8fd0 (#845) --- LEGO1/lego/sources/roi/legoroi.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index 0bbed5da..7bee2c40 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -434,11 +434,31 @@ void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_t } } -// STUB: LEGO1 0x100a8fd0 +// FUNCTION: LEGO1 0x100a8fd0 // FUNCTION: BETA10 0x1018ac81 void LegoROI::FUN_100a8fd0(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap) { - // TODO + MxMatrix mat; + + LegoAnimNodeData* data = (LegoAnimNodeData*) p_node->GetData(); + FUN_100a8cb0(data, p_time, mat); + + LegoROI* roi = p_roiMap[data->GetUnknown0x20()]; + if (roi != NULL) { + roi->m_local2world.Product(mat, p_matrix); + + for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { + FUN_100a8fd0(p_node->GetChild(i), roi->m_local2world, p_time, p_roiMap); + } + } + else { + MxMatrix local2world; + local2world.Product(mat, p_matrix); + + for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { + FUN_100a8fd0(p_node->GetChild(i), local2world, p_time, p_roiMap); + } + } } // FUNCTION: LEGO1 0x100a90f0 From 410824bd0f42a6d32e12da1abf65db892121c369 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 24 Apr 2024 09:51:28 -0400 Subject: [PATCH 7/9] Implement/match various small LegoAnimPresenter functions (#846) * Implement/match various small LegoAnimPresenter functions * Fix location of anim function * fix --- .../lego/legoomni/include/legoanimpresenter.h | 9 ++-- LEGO1/lego/legoomni/include/legoextraactor.h | 1 - .../include/legolocomotionanimpresenter.h | 2 + .../legoomni/include/legopathcontroller.h | 1 + LEGO1/lego/legoomni/include/legoworld.h | 1 + .../src/common/legoanimmmpresenter.cpp | 2 +- LEGO1/lego/legoomni/src/entity/legoworld.cpp | 12 ++++++ .../lego/legoomni/src/paths/legoanimactor.cpp | 5 ++- .../legoomni/src/paths/legoextraactor.cpp | 9 ++-- .../legoomni/src/paths/legopathcontroller.cpp | 6 +++ .../legoomni/src/video/legoanimpresenter.cpp | 43 +++++++++++++------ .../src/video/legolocomotionanimpresenter.cpp | 6 +++ 12 files changed, 71 insertions(+), 26 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 02a81b37..af6d58be 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -10,6 +10,7 @@ class LegoWorld; class LegoAnimClass; class LegoAnimActor; +class LegoPathBoundary; struct LegoAnimStructComparator { MxBool operator()(const char* const& p_a, const char* const& p_b) const { return strcmp(p_a, p_b) < 0; } @@ -62,7 +63,7 @@ class LegoAnimPresenter : public MxVideoPresenter { virtual void VTable0x8c(); // vtable+0x8c virtual void VTable0x90(); // vtable+0x90 virtual MxResult VTable0x94(Vector3&, Vector3&, float, float, Vector3&); // vtable+0x94 - virtual void VTable0x98(); // vtable+0x98 + virtual MxResult VTable0x98(LegoPathBoundary* p_boundary); // vtable+0x98 // FUNCTION: LEGO1 0x1000c990 virtual LegoROI** GetROIMap(MxU32& p_roiMapSize) @@ -71,16 +72,14 @@ class LegoAnimPresenter : public MxVideoPresenter { return m_roiMap; } // vtable+0x9c - virtual void VTable0xa0(Matrix4*); // vtable+0xa0 + virtual void VTable0xa0(Matrix4& p_matrix); // vtable+0xa0 MxResult FUN_1006afc0(MxMatrix*& p_matrix, float p_und); MxResult FUN_1006b140(LegoROI* p_roi); - void FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value); + const char* GetActionObjectName(); inline LegoAnim* GetAnimation() { return m_anim; } - const char* GetActionObjectName(); - protected: void Init(); void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/lego/legoomni/include/legoextraactor.h b/LEGO1/lego/legoomni/include/legoextraactor.h index c6ee0e61..696a3a50 100644 --- a/LEGO1/lego/legoomni/include/legoextraactor.h +++ b/LEGO1/lego/legoomni/include/legoextraactor.h @@ -2,7 +2,6 @@ #define LEGOEXTRAACTOR_H #include "legoanimactor.h" -#include "legoanimpresenter.h" // VTABLE: LEGO1 0x100d6c00 LegoAnimActor // VTABLE: LEGO1 0x100d6c10 LegoPathActor diff --git a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h index 55eda20b..b70841ea 100644 --- a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h @@ -35,6 +35,8 @@ class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { // SYNTHETIC: LEGO1 0x1006cfe0 // LegoLocomotionAnimPresenter::`scalar deleting destructor' + void FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value); + inline void DecrementUnknown0xd4() { if (m_unk0xd4) { diff --git a/LEGO1/lego/legoomni/include/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h index c9037091..5a55fa0e 100644 --- a/LEGO1/lego/legoomni/include/legopathcontroller.h +++ b/LEGO1/lego/legoomni/include/legopathcontroller.h @@ -43,6 +43,7 @@ class LegoPathController : public MxCore { undefined4 FUN_10046770(LegoPathActor* p_actor); void FUN_100468f0(LegoAnimPresenter* p_presenter); + void FUN_10046930(LegoAnimPresenter* p_presenter); MxResult FUN_10046b30(LegoPathBoundary** p_path, MxS32& p_value); void Enable(MxBool p_enable); void FUN_10046bb0(LegoWorld* p_world); diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index d1841669..f882b685 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -75,6 +75,7 @@ class LegoWorld : public LegoEntity { ); void FUN_1001fc80(IslePathActor* p_actor); void FUN_1001fda0(LegoAnimPresenter* p_presenter); + void FUN_1001fe90(LegoAnimPresenter* p_presenter); void AddPath(LegoPathController* p_controller); MxResult GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value); MxCore* Find(const char* p_class, const char* p_name); diff --git a/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp b/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp index 219502fe..17b47b46 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp @@ -149,7 +149,7 @@ void LegoAnimMMPresenter::ReadyTickle() } if (m_tranInfo != NULL && m_tranInfo->m_unk0x0c != NULL) { - m_presenter->VTable0xa0(m_tranInfo->m_unk0x0c); + m_presenter->VTable0xa0(*m_tranInfo->m_unk0x0c); } if (m_presenter != NULL) { diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index cf42b0e3..cfae9c2e 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -311,6 +311,18 @@ void LegoWorld::FUN_1001fda0(LegoAnimPresenter* p_presenter) } } +// FUNCTION: LEGO1 0x1001fe90 +// FUNCTION: BETA10 0x100da6b5 +void LegoWorld::FUN_1001fe90(LegoAnimPresenter* p_presenter) +{ + LegoPathControllerListCursor cursor(&m_list0x68); + LegoPathController* controller; + + while (cursor.Next(controller)) { + controller->FUN_10046930(p_presenter); + } +} + // FUNCTION: LEGO1 0x1001ff80 void LegoWorld::AddPath(LegoPathController* p_controller) { diff --git a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp index 1bac6592..832d05f9 100644 --- a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp @@ -1,7 +1,7 @@ #include "legoanimactor.h" #include "define.h" -#include "legoanimpresenter.h" +#include "legolocomotionanimpresenter.h" #include "legoworld.h" #include "misc.h" #include "mxutilities.h" @@ -200,7 +200,8 @@ void LegoAnimActor::ParseAction(char* p_extra) char* token = strtok(value, g_parseExtraTokens); while (token) { - LegoAnimPresenter* presenter = (LegoAnimPresenter*) world->Find("LegoAnimPresenter", token); + LegoLocomotionAnimPresenter* presenter = + (LegoLocomotionAnimPresenter*) world->Find("LegoAnimPresenter", token); if (presenter != NULL) { token = strtok(NULL, g_parseExtraTokens); diff --git a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp index 0ba019ce..066615ed 100644 --- a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp @@ -1,5 +1,6 @@ #include "legoextraactor.h" +#include "legolocomotionanimpresenter.h" #include "legosoundmanager.h" #include "misc.h" #include "mxmisc.h" @@ -11,10 +12,10 @@ DECOMP_SIZE_ASSERT(LegoExtraActor, 0x1dc) LegoWorld* g_unk0x100f31d0 = NULL; // GLOBAL: LEGO1 0x100f31d4 -LegoAnimPresenter* m_assAnimP = NULL; +LegoLocomotionAnimPresenter* m_assAnimP = NULL; // GLOBAL: LEGO1 0x100f31d8 -LegoAnimPresenter* m_disAnimP = NULL; +LegoLocomotionAnimPresenter* m_disAnimP = NULL; // GLOBAL: LEGO1 0x100f31dc MxS32 g_unk0x100f31dc = 0; @@ -156,8 +157,8 @@ inline void LegoExtraActor::FUN_1002ad8a() if (g_unk0x100f31d0 != w) { g_unk0x100f31d0 = w; - m_assAnimP = (LegoAnimPresenter*) w->Find("LegoAnimPresenter", "BNsAss01"); - m_disAnimP = (LegoAnimPresenter*) w->Find("LegoAnimPresenter", "BNsDis01"); + m_assAnimP = (LegoLocomotionAnimPresenter*) w->Find("LegoAnimPresenter", "BNsAss01"); + m_disAnimP = (LegoLocomotionAnimPresenter*) w->Find("LegoAnimPresenter", "BNsDis01"); } if (!m_assAnim) { diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp index 51c6e723..422b972f 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp @@ -39,6 +39,12 @@ void LegoPathController::FUN_100468f0(LegoAnimPresenter* p_presenter) { } +// STUB: LEGO1 0x10046930 +// FUNCTION: BETA10 0x100b737b +void LegoPathController::FUN_10046930(LegoAnimPresenter* p_presenter) +{ +} + // STUB: LEGO1 0x10046b30 MxResult LegoPathController::FUN_10046b30(LegoPathBoundary** p_path, MxS32& p_value) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 892bc06f..2d0c2297 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -805,10 +805,15 @@ void LegoAnimPresenter::ParseExtra() // TODO } -// STUB: LEGO1 0x1006c570 -void LegoAnimPresenter::VTable0xa0(Matrix4*) +// FUNCTION: LEGO1 0x1006c570 +// FUNCTION: BETA10 0x10051ab3 +void LegoAnimPresenter::VTable0xa0(Matrix4& p_matrix) { - // TODO + if (m_unk0x78 != NULL) { + delete m_unk0x78; + } + + m_unk0x78 = new MxMatrix(p_matrix); } // FUNCTION: LEGO1 0x1006c620 @@ -882,10 +887,19 @@ void LegoAnimPresenter::VTable0x8c() } } -// STUB: LEGO1 0x1006c860 +// FUNCTION: LEGO1 0x1006c860 +// FUNCTION: BETA10 0x10051f45 void LegoAnimPresenter::VTable0x90() { - // TODO + if (m_currentWorld != NULL) { + m_currentWorld->FUN_1001fe90(this); + + if (m_compositePresenter != NULL && m_compositePresenter->IsA("LegoAnimMMPresenter")) { + return; + } + + m_currentWorld->Remove(this); + } } // FUNCTION: LEGO1 0x1006c8a0 @@ -914,14 +928,17 @@ MxResult LegoAnimPresenter::VTable0x94(Vector3&, Vector3&, float, float, Vector3 return SUCCESS; } -// STUB: LEGO1 0x1006ca50 -void LegoAnimPresenter::VTable0x98() +// FUNCTION: LEGO1 0x1006ca50 +// FUNCTION: BETA10 0x100521d0 +MxResult LegoAnimPresenter::VTable0x98(LegoPathBoundary* p_boundary) { - // TODO -} + for (MxU32 i = 1; i <= m_roiMapSize; i++) { + LegoEntity* entity = m_roiMap[i]->GetEntity(); -// STUB: LEGO1 0x1006d680 -void LegoAnimPresenter::FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value) -{ - // TODO + if (entity != NULL) { + p_boundary->AddActor((LegoPathActor*) entity); + } + } + + return SUCCESS; } diff --git a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp index 9801c2bc..81a9b921 100644 --- a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp @@ -113,3 +113,9 @@ void LegoLocomotionAnimPresenter::EndAction() MxVideoPresenter::EndAction(); } } + +// STUB: LEGO1 0x1006d680 +void LegoLocomotionAnimPresenter::FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value) +{ + // TODO +} From 311b27b6971aa2eaf2c1beb71bbb96cff230aeed Mon Sep 17 00:00:00 2001 From: MS Date: Wed, 24 Apr 2024 12:10:51 -0400 Subject: [PATCH 8/9] Beta matching MxString (#842) * Beta matching MxString * Add /opt:ref for lego1. Reorder MxString header. * const fix * Remove lego1 Opt:ref --- LEGO1/lego/legoomni/include/legophonemelist.h | 2 + .../legoomni/src/common/legovariables.cpp | 3 +- LEGO1/omni/include/mxstring.h | 34 +++++--- LEGO1/omni/src/common/mxstring.cpp | 81 +++++++++++++++++-- 4 files changed, 103 insertions(+), 17 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legophonemelist.h b/LEGO1/lego/legoomni/include/legophonemelist.h index 10ade657..37e4b8b6 100644 --- a/LEGO1/lego/legoomni/include/legophonemelist.h +++ b/LEGO1/lego/legoomni/include/legophonemelist.h @@ -12,12 +12,14 @@ // class MxList // VTABLE: LEGO1 0x100d9d00 +// VTABLE: BETA10 0x101bef58 // SIZE 0x18 class LegoPhonemeList : public MxList { public: LegoPhonemeList() { SetDestroy(Destroy); } // FUNCTION: LEGO1 0x1007b210 + // FUNCTION: BETA10 0x100d8340 MxS8 Compare(LegoPhoneme* p_a, LegoPhoneme* p_b) override { MxString a(p_a->GetName()); diff --git a/LEGO1/lego/legoomni/src/common/legovariables.cpp b/LEGO1/lego/legoomni/src/common/legovariables.cpp index 83a17084..71e6e587 100644 --- a/LEGO1/lego/legoomni/src/common/legovariables.cpp +++ b/LEGO1/lego/legoomni/src/common/legovariables.cpp @@ -68,12 +68,13 @@ const char* g_nick = "Nick"; const char* g_laura = "Laura"; // FUNCTION: LEGO1 0x10037d00 +// FUNCTION: BETA10 0x100d5620 void VisibilityVariable::SetValue(const char* p_value) { MxVariable::SetValue(p_value); if (p_value) { - char* instruction = strtok(m_value.GetDataPtr(), g_delimiter2); + char* instruction = strtok(m_value.GetData(), g_delimiter2); char* name = strtok(NULL, g_delimiter2); MxBool show; diff --git a/LEGO1/omni/include/mxstring.h b/LEGO1/omni/include/mxstring.h index 231d2e2c..5d973e69 100644 --- a/LEGO1/omni/include/mxstring.h +++ b/LEGO1/omni/include/mxstring.h @@ -4,28 +4,42 @@ #include "mxcore.h" // VTABLE: LEGO1 0x100dc110 +// VTABLE: BETA10 0x101c1be0 // SIZE 0x10 class MxString : public MxCore { public: - MxString(const MxString& p_str); - ~MxString() override; - const MxString& operator=(const char* p_data); - MxString(); - MxString(const char*); + MxString(const MxString& p_str); + MxString(const char* p_str); + MxString(const char* p_str, MxU16 p_maxlen); + ~MxString() override; + + void Reverse(); void ToUpperCase(); void ToLowerCase(); + MxString& operator=(const MxString& p_str); - MxString operator+(const char* p_str); + const MxString& operator=(const char* p_str); + MxString operator+(const MxString& p_str) const; + MxString operator+(const char* p_str) const; MxString& operator+=(const char* p_str); - inline MxS8 Compare(const MxString& p_str) const { return strcmp(m_data, p_str.m_data); } - inline MxBool Equal(const MxString& p_str) const { return strcmp(m_data, p_str.m_data) == 0; } - inline const char* GetData() const { return m_data; } - inline char* GetDataPtr() const { return m_data; } + static void CharSwap(char* p_a, char* p_b); + + // FUNCTION: BETA10 0x10017c50 + inline char* GetData() const { return m_data; } + + // FUNCTION: BETA10 0x10067630 inline const MxU16 GetLength() const { return m_length; } + // FUNCTION: BETA10 0x100d8a30 + inline MxBool Equal(const MxString& p_str) const { return strcmp(m_data, p_str.m_data) == 0; } + + // FUNCTION: BETA10 0x1012a810 + inline MxS8 Compare(const MxString& p_str) const { return strcmp(m_data, p_str.m_data); } + // SYNTHETIC: LEGO1 0x100ae280 + // SYNTHETIC: BETA10 0x1012c9d0 // MxString::`scalar deleting destructor' private: diff --git a/LEGO1/omni/src/common/mxstring.cpp b/LEGO1/omni/src/common/mxstring.cpp index 09194eb7..b33a7f10 100644 --- a/LEGO1/omni/src/common/mxstring.cpp +++ b/LEGO1/omni/src/common/mxstring.cpp @@ -8,6 +8,7 @@ DECOMP_SIZE_ASSERT(MxString, 0x10) // FUNCTION: LEGO1 0x100ae200 +// FUNCTION: BETA10 0x1012c110 MxString::MxString() { // Set string to one char in length and set that char to null terminator @@ -17,6 +18,7 @@ MxString::MxString() } // FUNCTION: LEGO1 0x100ae2a0 +// FUNCTION: BETA10 0x1012c1a1 MxString::MxString(const MxString& p_str) { this->m_length = p_str.m_length; @@ -25,6 +27,7 @@ MxString::MxString(const MxString& p_str) } // FUNCTION: LEGO1 0x100ae350 +// FUNCTION: BETA10 0x1012c24f MxString::MxString(const char* p_str) { if (p_str) { @@ -39,25 +42,65 @@ MxString::MxString(const char* p_str) } } +// FUNCTION: BETA10 0x1012c330 +MxString::MxString(const char* p_str, MxU16 p_maxlen) +{ + if (p_str) { + if (strlen(p_str) <= p_maxlen) { + this->m_length = strlen(p_str); + } + else { + this->m_length = p_maxlen; + } + + // Basically strncpy + this->m_data = new char[this->m_length + 1]; + memcpy(this->m_data, p_str, this->m_length); + this->m_data[this->m_length] = '\0'; + } + else { + this->m_data = new char[1]; + this->m_data[0] = 0; + this->m_length = 0; + } +} + // FUNCTION: LEGO1 0x100ae420 +// FUNCTION: BETA10 0x1012c45b MxString::~MxString() { delete[] this->m_data; } +// FUNCTION: BETA10 0x1012c4de +void MxString::Reverse() +{ + char* start = this->m_data; + char* end = this->m_data + this->m_length - 1; + + while (start < end) { + CharSwap(start, end); + start++; + end--; + } +} + // FUNCTION: LEGO1 0x100ae490 +// FUNCTION: BETA10 0x1012c537 void MxString::ToUpperCase() { strupr(this->m_data); } // FUNCTION: LEGO1 0x100ae4a0 +// FUNCTION: BETA10 0x1012c55c void MxString::ToLowerCase() { strlwr(this->m_data); } // FUNCTION: LEGO1 0x100ae4b0 +// FUNCTION: BETA10 0x1012c581 MxString& MxString::operator=(const MxString& p_str) { if (this->m_data != p_str.m_data) { @@ -71,22 +114,39 @@ MxString& MxString::operator=(const MxString& p_str) } // FUNCTION: LEGO1 0x100ae510 -const MxString& MxString::operator=(const char* p_data) +// FUNCTION: BETA10 0x1012c606 +const MxString& MxString::operator=(const char* p_str) { - if (this->m_data != p_data) { + if (this->m_data != p_str) { delete[] this->m_data; - this->m_length = strlen(p_data); + this->m_length = strlen(p_str); this->m_data = new char[this->m_length + 1]; - strcpy(this->m_data, p_data); + strcpy(this->m_data, p_str); } return *this; } +// FUNCTION: BETA10 0x1012c68a +MxString MxString::operator+(const MxString& p_str) const +{ + MxString tmp; + delete[] tmp.m_data; + + tmp.m_length = p_str.m_length + this->m_length; + tmp.m_data = new char[tmp.m_length + 1]; + + strcpy(tmp.m_data, this->m_data); + strcpy(tmp.m_data + this->m_length, p_str.m_data); + + return MxString(tmp); +} + // Return type is intentionally just MxString, not MxString&. // This forces MSVC to add $ReturnUdt$ to the stack for 100% match. // FUNCTION: LEGO1 0x100ae580 -MxString MxString::operator+(const char* p_str) +// FUNCTION: BETA10 0x1012c78d +MxString MxString::operator+(const char* p_str) const { // MxString constructor allocates 1 byte for m_data, so free that first MxString tmp; @@ -102,6 +162,7 @@ MxString MxString::operator+(const char* p_str) } // FUNCTION: LEGO1 0x100ae690 +// FUNCTION: BETA10 0x1012c92f MxString& MxString::operator+=(const char* p_str) { int newlen = this->m_length + strlen(p_str); @@ -111,8 +172,16 @@ MxString& MxString::operator+=(const char* p_str) strcpy(tmp + this->m_length, p_str); delete[] this->m_data; - this->m_length = newlen; this->m_data = tmp; + this->m_length = newlen; return *this; } + +// FUNCTION: BETA10 0x1012ca10 +void MxString::CharSwap(char* p_a, char* p_b) +{ + char t = *p_a; + *p_a = *p_b; + *p_b = t; +} From 916c039e72b5b0ac2f65529f684e2ce6a8675c5f Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 25 Apr 2024 10:00:58 -0400 Subject: [PATCH 9/9] Implement/match LegoAnimPresenter::ParseExtra (#848) * Implement/match LegoAnimPresenter::ParseExtra * Fix --- LEGO1/define.cpp | 20 +++ LEGO1/define.h | 5 + .../lego/legoomni/include/legoanimpresenter.h | 81 ++++++++---- LEGO1/lego/legoomni/include/legopathactor.h | 2 +- .../legoomni/src/actors/islepathactor.cpp | 1 + .../src/common/legoanimmmpresenter.cpp | 1 + LEGO1/lego/legoomni/src/common/legoutils.cpp | 1 + .../lego/legoomni/src/paths/legoanimactor.cpp | 1 + .../legoomni/src/paths/legoextraactor.cpp | 1 + .../lego/legoomni/src/paths/legopathactor.cpp | 1 + .../legoomni/src/video/legoanimpresenter.cpp | 115 ++++++++++++++++-- LEGO1/modeldb/modeldb.cpp | 2 +- 12 files changed, 198 insertions(+), 33 deletions(-) diff --git a/LEGO1/define.cpp b/LEGO1/define.cpp index 1ff1f868..cdc2def9 100644 --- a/LEGO1/define.cpp +++ b/LEGO1/define.cpp @@ -12,10 +12,26 @@ const char* g_strANIMATION = "ANIMATION"; // STRING: LEGO1 0x10102024 const char* g_strATTACH_CAMERA = "ATTACH_CAMERA"; +// GLOBAL: LEGO1 0x10102080 +// STRING: LEGO1 0x100f4368 +const char* g_strFROM_PARENT = "FROM_PARENT"; + +// GLOBAL: LEGO1 0x10102084 +// STRING: LEGO1 0x10101fa4 +const char* g_strHIDE_ON_STOP = "HIDE_ON_STOP"; + +// GLOBAL: LEGO1 0x10102098 +// STRING: LEGO1 0x10101f60 +const char* g_strMUST_SUCCEED = "MUST_SUCCEED"; + // GLOBAL: LEGO1 0x1010209c // STRING: LEGO1 0x10101f58 const char* g_strOBJECT = "OBJECT"; +// GLOBAL: LEGO1 0x101020a8 +// STRING: LEGO1 0x10101f38 +const char* g_strPTATCAM = "PTATCAM"; + // GLOBAL: LEGO1 0x101020b0 // STRING: LEGO1 0x10101f20 const char* g_strSOUND = "SOUND"; @@ -28,6 +44,10 @@ const char* g_strMUTE = "MUTE"; // STRING: LEGO1 0x100f09cc const char* g_strSPEED = "SPEED"; +// GLOBAL: LEGO1 0x101020bc +// STRING: LEGO1 0x10101f10 +const char* g_strSUBST = "SUBST"; + // GLOBAL: LEGO1 0x101020cc // STRING: LEGO1 0x100f3808 const char* g_strVISIBILITY = "VISIBILITY"; diff --git a/LEGO1/define.h b/LEGO1/define.h index 086c4500..d975d1fb 100644 --- a/LEGO1/define.h +++ b/LEGO1/define.h @@ -14,5 +14,10 @@ extern const char* g_strSPEED; extern const char* g_strATTACH_CAMERA; extern const char* g_strMUTE; extern const char* g_strANIMMAN_ID; +extern const char* g_strFROM_PARENT; +extern const char* g_strHIDE_ON_STOP; +extern const char* g_strMUST_SUCCEED; +extern const char* g_strSUBST; +extern const char* g_strPTATCAM; #endif // DEFINE_H diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index af6d58be..30f858b0 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -16,6 +16,10 @@ struct LegoAnimStructComparator { MxBool operator()(const char* const& p_a, const char* const& p_b) const { return strcmp(p_a, p_b) < 0; } }; +struct LegoAnimSubstComparator { + MxBool operator()(const char* const& p_a, const char* const& p_b) const { return strcmp(p_a, p_b) < 0; } +}; + // SIZE 0x08 struct LegoAnimStruct { LegoROI* m_roi; // 0x00 @@ -23,14 +27,15 @@ struct LegoAnimStruct { }; typedef map LegoAnimPresenterMap; +typedef map LegoAnimSubstMap; // VTABLE: LEGO1 0x100d90c8 // SIZE 0xbc class LegoAnimPresenter : public MxVideoPresenter { public: enum { - c_bit1 = 0x01, - c_bit2 = 0x02 + c_hideOnStop = 0x01, + c_mustSucceed = 0x02 }; LegoAnimPresenter(); @@ -100,33 +105,48 @@ class LegoAnimPresenter : public MxVideoPresenter { void FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p_matrix); void FUN_1006c8a0(MxBool p_bool); - LegoAnim* m_anim; // 0x64 - LegoROI** m_roiMap; // 0x68 - MxU32 m_roiMapSize; // 0x6c - LegoROIList* m_unk0x70; // 0x70 - LegoROIList* m_unk0x74; // 0x74 - MxMatrix* m_unk0x78; // 0x78 - MxU32 m_flags; // 0x7c - LegoWorld* m_currentWorld; // 0x80 - MxAtomId m_animAtom; // 0x84 - undefined4 m_unk0x88; // 0x88 - LegoROI** m_unk0x8c; // 0x8c - const char** m_unk0x90; // 0x90 - MxU8 m_unk0x94; // 0x94 - undefined m_unk0x95; // 0x95 - MxBool m_unk0x96; // 0x96 - undefined m_unk0x97; // 0x97 - undefined4 m_unk0x98; // 0x98 - MxS16 m_unk0x9c; // 0x9c - undefined4 m_unk0xa0; // 0xa0 - undefined4 m_unk0xa4; // 0xa4 - Mx3DPointFloat m_unk0xa8; // 0xa8 + LegoAnim* m_anim; // 0x64 + LegoROI** m_roiMap; // 0x68 + MxU32 m_roiMapSize; // 0x6c + LegoROIList* m_unk0x70; // 0x70 + LegoROIList* m_unk0x74; // 0x74 + MxMatrix* m_unk0x78; // 0x78 + MxU32 m_flags; // 0x7c + LegoWorld* m_currentWorld; // 0x80 + MxAtomId m_worldAtom; // 0x84 + MxS32 m_worldId; // 0x88 + LegoROI** m_unk0x8c; // 0x8c + char** m_unk0x90; // 0x90 + MxU8 m_unk0x94; // 0x94 + undefined m_unk0x95; // 0x95 + MxBool m_unk0x96; // 0x96 + undefined m_unk0x97; // 0x97 + LegoAnimSubstMap* m_substMap; // 0x98 + MxS16 m_unk0x9c; // 0x9c + undefined4 m_unk0xa0; // 0xa0 + undefined4 m_unk0xa4; // 0xa4 + Mx3DPointFloat m_unk0xa8; // 0xa8 }; // clang-format off // SYNTHETIC: LEGO1 0x10068650 // LegoAnimPresenter::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x100689c0 +// map >::~map > + +// TEMPLATE: LEGO1 0x10068a10 +// _Tree,map >::_Kfn,LegoAnimSubstComparator,allocator >::~_Tree,map + +// TEMPLATE: LEGO1 0x10068ae0 +// _Tree,map >::_Kfn,LegoAnimSubstComparator,allocator >::iterator::_Inc + +// TEMPLATE: LEGO1 0x10068b20 +// _Tree,map >::_Kfn,LegoAnimSubstComparator,allocator >::erase + +// TEMPLATE: LEGO1 0x10068f70 +// _Tree,map >::_Kfn,LegoAnimSubstComparator,allocator >::_Erase + // TEMPLATE: LEGO1 0x10069d80 // _Tree,map >::_Kfn,LegoAnimStructComparator,allocator >::~_Tree,map >::_Kfn,LegoAnimStructComparator,allocator >::_Insert +// TEMPLATE: LEGO1 0x1006c1b0 +// _Tree,map >::_Kfn,LegoAnimSubstComparator,allocator >::iterator::_Dec + +// TEMPLATE: LEGO1 0x1006c200 +// _Tree,map >::_Kfn,LegoAnimSubstComparator,allocator >::_Insert + +// TEMPLATE: LEGO1 0x1006c4b0 +// list >::~list > + +// TEMPLATE: LEGO1 0x1006c520 +// List::~List + +// GLOBAL: LEGO1 0x100f7680 +// _Tree,map >::_Kfn,LegoAnimSubstComparator,allocator >::_Nil + // GLOBAL: LEGO1 0x100f7688 // _Tree,map >::_Kfn,LegoAnimStructComparator,allocator >::_Nil // clang-format on diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index d1bbd0ef..e9488e8e 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -3,11 +3,11 @@ #include "geom/legounkown100db7f4.h" #include "legoactor.h" -#include "legopathboundary.h" #include "misc/legounknown.h" #include "mxtypes.h" #include "realtime/matrix.h" +class LegoPathBoundary; class LegoPathController; // VTABLE: LEGO1 0x100d6e28 diff --git a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp index faf9709c..46dce944 100644 --- a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp +++ b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp @@ -2,6 +2,7 @@ #include "legoanimationmanager.h" #include "legonavcontroller.h" +#include "legopathboundary.h" #include "legoutils.h" #include "misc.h" #include "mxnotificationparam.h" diff --git a/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp b/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp index 17b47b46..e93e9a60 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp @@ -4,6 +4,7 @@ #include "define.h" #include "islepathactor.h" #include "legoanimationmanager.h" +#include "legoanimpresenter.h" #include "legotraninfo.h" #include "legovideomanager.h" #include "legoworld.h" diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index 613b01a8..3cf3e705 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -2,6 +2,7 @@ #include "act1state.h" #include "islepathactor.h" +#include "legoanimpresenter.h" #include "legogamestate.h" #include "legoinputmanager.h" #include "legonamedtexture.h" diff --git a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp index 832d05f9..c94b498d 100644 --- a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp @@ -2,6 +2,7 @@ #include "define.h" #include "legolocomotionanimpresenter.h" +#include "legopathboundary.h" #include "legoworld.h" #include "misc.h" #include "mxutilities.h" diff --git a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp index 066615ed..4402756d 100644 --- a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp @@ -1,6 +1,7 @@ #include "legoextraactor.h" #include "legolocomotionanimpresenter.h" +#include "legopathboundary.h" #include "legosoundmanager.h" #include "misc.h" #include "mxmisc.h" diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index 945e5f27..977624b5 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -1,6 +1,7 @@ #include "legopathactor.h" #include "legonavcontroller.h" +#include "legopathboundary.h" #include "legosoundmanager.h" #include "misc.h" #include "mxmisc.h" diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 2d0c2297..c3b8c107 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -1,8 +1,10 @@ #include "legoanimpresenter.h" +#include "define.h" #include "legoanimationmanager.h" #include "legoanimmmpresenter.h" #include "legocharactermanager.h" +#include "legopathboundary.h" #include "legovideomanager.h" #include "legoworld.h" #include "misc.h" @@ -13,6 +15,7 @@ #include "mxstreamchunk.h" #include "mxtimer.h" #include "mxtype18notificationparam.h" +#include "mxutilities.h" #include "mxvideomanager.h" #include "realtime/realtime.h" @@ -44,9 +47,9 @@ void LegoAnimPresenter::Init() m_unk0xa4 = 0; m_currentWorld = NULL; m_unk0x95 = 0; - m_unk0x88 = -1; - m_unk0x98 = 0; - m_animAtom.Clear(); + m_worldId = -1; + m_substMap = NULL; + m_worldAtom.Clear(); m_unk0x9c = 0; m_unk0x8c = NULL; m_unk0x90 = NULL; @@ -645,7 +648,7 @@ void LegoAnimPresenter::StartingTickle() FUN_100692b0(); FUN_100695c0(); - if (m_flags & c_bit2 && !FUN_1006aba0()) { + if (m_flags & c_mustSucceed && !FUN_1006aba0()) { goto done; } @@ -799,10 +802,106 @@ void LegoAnimPresenter::FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p LegoROI::FUN_100a8e80(root, mat, p_time, m_roiMap); } -// STUB: LEGO1 0x1006bac0 +// FUNCTION: LEGO1 0x1006bac0 +// FUNCTION: BETA10 0x100512e1 void LegoAnimPresenter::ParseExtra() { - // TODO + MxU16 extraLength; + char* extraData; + m_action->GetExtra(extraLength, extraData); + + if (extraLength & MAXWORD) { + char extraCopy[256]; + memcpy(extraCopy, extraData, extraLength & MAXWORD); + extraCopy[extraLength & MAXWORD] = '\0'; + + char output[256]; + if (KeyValueStringParse(NULL, g_strFROM_PARENT, extraCopy) && m_compositePresenter != NULL) { + m_compositePresenter->GetAction()->GetExtra(extraLength, extraData); + + if (extraLength & MAXWORD) { + memcpy(extraCopy, extraData, extraLength & MAXWORD); + extraCopy[extraLength & MAXWORD] = '\0'; + } + } + + if (KeyValueStringParse(output, g_strHIDE_ON_STOP, extraCopy)) { + m_flags |= c_hideOnStop; + } + + if (KeyValueStringParse(output, g_strMUST_SUCCEED, extraCopy)) { + m_flags |= c_mustSucceed; + } + + if (KeyValueStringParse(output, g_strSUBST, extraCopy)) { + m_substMap = new LegoAnimSubstMap(); + + char* substToken = output; + char *key, *value; + + while ((key = strtok(substToken, g_parseExtraTokens))) { + substToken = NULL; + + if ((value = strtok(NULL, g_parseExtraTokens))) { + char* keyCopy = new char[strlen(key) + 1]; + strcpy(keyCopy, key); + char* valueCopy = new char[strlen(value) + 1]; + strcpy(valueCopy, value); + (*m_substMap)[keyCopy] = valueCopy; + } + } + } + + if (KeyValueStringParse(output, g_strWORLD, extraCopy)) { + char* token = strtok(output, g_parseExtraTokens); + m_worldAtom = MxAtomId(token, e_lowerCase2); + + token = strtok(NULL, g_parseExtraTokens); + m_worldId = atoi(token); + } + + if (KeyValueStringParse(output, g_strPTATCAM, extraCopy)) { + list tmp; + + if (m_unk0x90 != NULL) { + for (MxS32 i = 0; i < m_unk0x94; i++) { + if (m_unk0x90[i] != NULL) { + // (modernization) critical bug: wrong free + delete[] m_unk0x90; + } + } + + delete[] m_unk0x90; + m_unk0x90 = NULL; + } + + if (m_unk0x8c != NULL) { + delete[] m_unk0x8c; + m_unk0x8c = NULL; + } + + char* token = strtok(output, g_parseExtraTokens); + while (token != NULL) { + char* valueCopy = new char[strlen(token) + 1]; + strcpy(valueCopy, token); + tmp.push_back(valueCopy); + token = strtok(NULL, g_parseExtraTokens); + } + + m_unk0x94 = tmp.size(); + if (m_unk0x94 != 0) { + m_unk0x8c = new LegoROI*[m_unk0x94]; + m_unk0x90 = new char*[m_unk0x94]; + memset(m_unk0x8c, 0, sizeof(*m_unk0x8c) * m_unk0x94); + memset(m_unk0x90, 0, sizeof(*m_unk0x90) * m_unk0x94); + + MxS32 i = 0; + for (list::iterator it = tmp.begin(); it != tmp.end(); it++, i++) { + m_unk0x90[i] = *it; + } + } + } + } } // FUNCTION: LEGO1 0x1006c570 @@ -845,7 +944,7 @@ void LegoAnimPresenter::EndAction() FUN_1006b9a0(m_anim, m_anim->GetDuration(), m_unk0x78); } - if (m_roiMapSize != 0 && m_roiMap != NULL && m_roiMap[1] != NULL && m_flags & c_bit1) { + if (m_roiMapSize != 0 && m_roiMap != NULL && m_roiMap[1] != NULL && m_flags & c_hideOnStop) { for (MxS16 i = 1; i <= m_roiMapSize; i++) { if (m_roiMap[i] != NULL) { m_roiMap[i]->SetVisibility(FALSE); @@ -876,7 +975,7 @@ void LegoAnimPresenter::VTable0x8c() } if (m_currentWorld == NULL) { - m_currentWorld = m_unk0x88 != -1 ? FindWorld(m_animAtom, m_unk0x88) : CurrentWorld(); + m_currentWorld = m_worldId != -1 ? FindWorld(m_worldAtom, m_worldId) : CurrentWorld(); } if (m_currentWorld) { diff --git a/LEGO1/modeldb/modeldb.cpp b/LEGO1/modeldb/modeldb.cpp index d7a8336f..b0489b8c 100644 --- a/LEGO1/modeldb/modeldb.cpp +++ b/LEGO1/modeldb/modeldb.cpp @@ -58,7 +58,7 @@ MxResult ModelDbPart::Read(FILE* p_file) return FAILURE; } - // Critical bug: buffer overrun + // (modernization) critical bug: buffer overrun if (fread(buff, len, 1, p_file) != 1) { return FAILURE; }