Portal-Zone Gothic-Zone Gothic II-Zone Gothic 3-Zone Gothic 4-Zone Modifikationen-Zone Download-Zone Foren-Zone RPG-Zone Almanach-Zone Spirit of Gothic

 

Seite 9 von 9 « Erste ... 256789
Ergebnis 161 bis 174 von 174
  1. Beiträge anzeigen #161 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Dass es bei C_Info Instanzen zu einer Exception kommt ist interessant, weil andere Klassen scheinbar einfach ignoriert werden. Wie auch immer:
    Zitat Zitat von Milky-Way Beitrag anzeigen
    Wie gehe ich mit dieser Information weiter vor?
    So wie hier vorgeschlagen.

    Das kann so aussehen:
    Code:
    func void B_ValidateOther() {
        // Original
        if (Hlp_IsValidNpc(other)) {
            Npc_GetTarget(self);
            self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
            self.aivar[AIV_LOADGAME] = FALSE;
            return;
        };
    
        // Else: !Hlp_IsValidNpc(other)
    
        var int symbPtr; symbPtr = MEM_GetSymbolByIndex(self.aivar[AIV_LASTTARGET]);
        if (symbPtr) {
            var zCPar_Symbol symb; symb = _^(symbPtr);
            if ((symb.bitfield & zCPar_Symbol_bitfield_type) == zPAR_TYPE_INSTANCE) {
                symb = _PM_ToClass(self.aivar[AIV_LASTTARGET]);
                if (Hlp_StrCmp(symb.name, "C_NPC")) {
                    // Original
                    other = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]);
                    Npc_SetTarget(self, other);
                    self.aivar[AIV_LOADGAME] = TRUE;
                    return;
                };
            };
        };
    
        // Else
        // Npc_SetTarget(self, NULL); // ?
        self.aivar[AIV_LOADGAME] = TRUE;
    };
    Da weiß ich aber nicht, was man am besten als Target von Self speichert, wenn etwas in der AI Variable ein ungültiger NPC gespeichert war (vor letzte Zeile). Müsste man mal austesten. Vielleicht etwas wie:
    Code:
    other = MEM_NullToInst();
    Npc_SetTarget(self, other);

  2. Beiträge anzeigen #162 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.191
     
    Milky-Way ist offline
    Habe jetzt erst den edit zu deinem früheren Post gesehen. Mit der PemMem-Funktion scheine ich es halbwegs hinbekommen zu haben.

    Ich habe zunächst am Ende des Hooks angefügt
    Code:
                var zCPar_Symbol symbClass; symbClass = _PM_ToClass(id);
                msg = ConcatStrings("  B_ValidateOther: symbClass=", symbClass.name);
                MEM_SendToSpy(zERR_TYPE_WARN, msg); // Warning is easier to spot
    und da wurde mir dann auch noch C_INFO angezeigt.

    Wenn ich statt id nach PC_Hero frage, dann ist symbClass.name == C_NPC.

    Also noch in den Hook eingebaut:
    Code:
                if !Hlp_StrCmp(symbClass.name, "C_NPC")
                {
                    Npc_GetTarget (self);
                    self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID (other);
                    self.aivar[AIV_LOADGAME] = FALSE;
                    return;
                };
    Damit stürzt das Spiel immerhin nicht mehr ab. Ich weiß nicht genau, was das Spiel macht, wenn Npc_GetTarget (self); kein brauchbares target findet?

    Gibt es Bedenken, dass obiger Code zu umständlich, nicht performant genug sein könnte? Ich weiß nicht, wie aufwändig _PM_ToClass bzw. _^(MEM_ReadIntArray(currSymbolTableAddress, id)); sind, sowie Hlp_StrCmp.

  3. Beiträge anzeigen #163 Zitieren
    Dea
    Registriert seit
    Jul 2007
    Beiträge
    10.446
     
    Lehona ist offline
    Also ReadIntArray(...) ist super billig. Da Hlp_StrCmp() eine External ist, wird die vermutlich auch nicht allzu teuer sein. _PM_ToClass() verfolgt bloß ein paar Pointer, das kannst du denke ich auch bedenkenlos verwenden. Insgesamt: Wenn es euren Bug/Crash behebt, würde ich es einfach so lassen.

  4. Beiträge anzeigen #164 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.191
     
    Milky-Way ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Dass es bei C_Info Instanzen zu einer Exception kommt ist interessant, weil andere Klassen scheinbar einfach ignoriert werden. Wie auch immer:

    So wie hier vorgeschlagen.

    Das kann so aussehen:
    Code:
    func void B_ValidateOther() {
        // Original
        if (Hlp_IsValidNpc(other)) {
            Npc_GetTarget(self);
            self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
            self.aivar[AIV_LOADGAME] = FALSE;
            return;
        };
    
        // Else: !Hlp_IsValidNpc(other)
    
        var int symbPtr; symbPtr = MEM_GetSymbolByIndex(self.aivar[AIV_LASTTARGET]);
        if (symbPtr) {
            var zCPar_Symbol symb; symb = _^(symbPtr);
            if ((symb.bitfield & zCPar_Symbol_bitfield_type) == zPAR_TYPE_INSTANCE) {
                symb = _PM_ToClass(self.aivar[AIV_LASTTARGET]);
                if (Hlp_StrCmp(symb.name, "C_NPC")) {
                    // Original
                    other = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]);
                    Npc_SetTarget(self, other);
                    self.aivar[AIV_LOADGAME] = TRUE;
                    return;
                };
            };
        };
    
        // Else
        // Npc_SetTarget(self, NULL); // ?
        self.aivar[AIV_LOADGAME] = TRUE;
    };
    Da weiß ich aber nicht, was man am besten als Target von Self speichert, wenn etwas in der AI Variable ein ungültiger NPC gespeichert war (vor letzte Zeile). Müsste man mal austesten. Vielleicht etwas wie:
    Code:
    other = MEM_NullToInst();
    Npc_SetTarget(self, other);
    Danke, damit stürzt es nun nicht mehr ab. Ob ein null target stört, weiß ich nicht. Da dieses Problem ja aber auch nur nach einem Patch auftritt, ist es mir auch nicht so wichtig, solange das Spiel nicht abstürzt.

    Zitat Zitat von Lehona Beitrag anzeigen
    Also ReadIntArray(...) ist super billig. Da Hlp_StrCmp() eine External ist, wird die vermutlich auch nicht allzu teuer sein. _PM_ToClass() verfolgt bloß ein paar Pointer, das kannst du denke ich auch bedenkenlos verwenden. Insgesamt: Wenn es euren Bug/Crash behebt, würde ich es einfach so lassen.
    Super, danke!

  5. Beiträge anzeigen #165 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Zitat Zitat von Milky-Way Beitrag anzeigen
    Danke, damit stürzt es nun nicht mehr ab.
    Mir ist dazu noch ein Problem zu dem Code aufgefallen. Kurz nach Starten von Gothic kann es sein, dass das Hilfssymbol yInstance_Help, das den Index null trägt, noch nie befüllt war. Wenn nun ein NPC in der AI-Variable null stehen hat (weil er z.B. noch nie einen Gegner hatte), wird das Parent (also Klasse oder Prototyp) vom Hilfssymbol nachgeschlagen, welches aber null ist, weil es noch nie gesetzt wurde. In dem Fall würde der Aufruf von _PM_ToClass einen Crash verursachen.

    Abhilfe sollte stattdessen dieser Code schaffen (ungetestet):

    Code:
    func void B_ValidateOther() {
        // Original
        if (Hlp_IsValidNpc(other)) {
            Npc_GetTarget(self);
            self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
            self.aivar[AIV_LOADGAME] = FALSE;
            return;
        };
    
        // Else: !Hlp_IsValidNpc(other)
    
        var int symbPtr; symbPtr = MEM_GetSymbolByIndex(self.aivar[AIV_LASTTARGET]);
        if (symbPtr) {
            var zCPar_Symbol symb; symb = _^(symbPtr);
            if ((symb.bitfield & zCPar_Symbol_bitfield_type) == zPAR_TYPE_INSTANCE) {
                symb = _PM_ToClass(self.aivar[AIV_LASTTARGET]);
                if (Hlp_StrCmp(symb.name, "C_NPC")) {
                if (Hlp_Is_oCNpc(symb.offset)) {
                    // Original
                    other = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]);
                    Npc_SetTarget(self, other);
                    self.aivar[AIV_LOADGAME] = TRUE;
                    return;
                };
            };
        };
    
        // Else
        Npc_SetTarget(self, NULL);
        self.aivar[AIV_LOADGAME] = TRUE;
    };

  6. Beiträge anzeigen #166 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.191
     
    Milky-Way ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Mir ist dazu noch ein Problem zu dem Code aufgefallen. Kurz nach Starten von Gothic kann es sein, dass das Hilfssymbol yInstance_Help, das den Index null trägt, noch nie befüllt war. Wenn nun ein NPC in der AI-Variable null stehen hat (weil er z.B. noch nie einen Gegner hatte), wird das Parent (also Klasse oder Prototyp) vom Hilfssymbol nachgeschlagen, welches aber null ist, weil es noch nie gesetzt wurde. In dem Fall würde der Aufruf von _PM_ToClass einen Crash verursachen.

    Abhilfe sollte stattdessen dieser Code schaffen (ungetestet):

    Code:
    func void B_ValidateOther() {
        // Original
        if (Hlp_IsValidNpc(other)) {
            Npc_GetTarget(self);
            self.aivar[AIV_LASTTARGET] = Hlp_GetInstanceID(other);
            self.aivar[AIV_LOADGAME] = FALSE;
            return;
        };
    
        // Else: !Hlp_IsValidNpc(other)
    
        var int symbPtr; symbPtr = MEM_GetSymbolByIndex(self.aivar[AIV_LASTTARGET]);
        if (symbPtr) {
            var zCPar_Symbol symb; symb = _^(symbPtr);
            if ((symb.bitfield & zCPar_Symbol_bitfield_type) == zPAR_TYPE_INSTANCE) {
                symb = _PM_ToClass(self.aivar[AIV_LASTTARGET]);
                if (Hlp_StrCmp(symb.name, "C_NPC")) {
                if (Hlp_Is_oCNpc(symb.offset)) {
                    // Original
                    other = Hlp_GetNpc(self.aivar[AIV_LASTTARGET]);
                    Npc_SetTarget(self, other);
                    self.aivar[AIV_LOADGAME] = TRUE;
                    return;
                };
            };
        };
    
        // Else
        Npc_SetTarget(self, NULL);
        self.aivar[AIV_LOADGAME] = TRUE;
    };
    Auch mit dieser Version stürzt das Spiel nicht mehr ab beim Laden. Das von dir beschriebene Problem der vorherigen Version trat bei mir (noch) nicht auf, daher kann ich nicht testen, ob es in der Situation nun besser funktionieren würde. Aber danke, für deine Arbeit, ich nehme gerne die aktualisierte Version!

  7. Beiträge anzeigen #167 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.191
     
    Milky-Way ist offline
    Einer unserer Tester hat momentan oefter mal Access Violations beim Laden eines Spielstands (aus dem Spiel heraus).

    Die Fehlermeldungen, die dabei produziert wurden, sagen mir erst mal gar nichts (siehe unten) -- gibt es da einen Ansatz, dem Problem auf die Schliche zu kommen?

    Es scheint so, als gaebe es zwei unterschiedliche Fehlermeldungen -- ob beide letztlich auf das selbe Problem hinweisen, weiss ich natuerlich noch nicht.

    Ueber jegliche Ideen, woran es liegen koennte, wuerde ich mich sehr freuen. Wir verwenden Ikarus + LeGo jeweils auf dem aktuellsten Stand, inklusive noch nicht "veroeffentlichten" Aenderungen, die bereits auf Github zu finden sind. (die erschienen mir alle tatsaechliche Bugfixes zu sein, die mehr Problem beheben als ausloesen sollten)

    Falls ich vom Spieler noch andere Infos erfragen sollte, lasst es mich einfach wissen

    Variante 1: Gothic2.exe

    Spoiler:(zum lesen bitte Text markieren)

    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=3FABBFFD  EBX=00000000  ECX=00AB4118  EDX=25550A26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F400  EIP=0079249D  FLG=00010202
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x233FF024 0xFFFFFFFF) Gothic2.exe
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=31032FFD  EBX=00000000  ECX=00AB4118  EDX=25552A26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F3A8  EIP=0079249D  FLG=00010202
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x233F0024 0xFFFFFFFF) Gothic2.exe
    //=====================================================

    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=2E62BFFD  EBX=00000000  ECX=00AB4118  EDX=25551A26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F400  EIP=0079249D  FLG=00010206
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x233FB024 0xFFFFFFFF) Gothic2.exe
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=3A82BFFD  EBX=00000000  ECX=00AB4118  EDX=27547A26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F400  EIP=0079249D  FLG=00010202
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x233F0024 0xFFFFFFFF) Gothic2.exe
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=3AB7BFFD  EBX=00000000  ECX=00AB4118  EDX=2754DA26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F3A8  EIP=0079249D  FLG=00010202
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x233F2024 0xFFFFFFFF) Gothic2.exe
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=37D74FFD  EBX=00000000  ECX=00AB4118  EDX=23842A26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F400  EIP=0079249D  FLG=00010206
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x20830024 0xFFFFFFFF) Gothic2.exe
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=39426FFD  EBX=00000000  ECX=00AB4118  EDX=26582A26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F3A8  EIP=0079249D  FLG=00010202
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x2242D024 0xFFFFFFFF) Gothic2.exe
    //=====================================================

    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=3237FFFD  EBX=00000000  ECX=00AB4118  EDX=24582A26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F400  EIP=0079249D  FLG=00010202
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x22426024 0xFFFFFFFF) Gothic2.exe
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=3AA44FFD  EBX=00000000  ECX=00AB4118  EDX=25548A26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F400  EIP=0079249D  FLG=00010206
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x233F5024 0xFFFFFFFF) Gothic2.exe
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=3DE8FFFD  EBX=00000000  ECX=00AB4118  EDX=2554BA26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F400  EIP=0079249D  FLG=00010202
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x233F3024 0xFFFFFFFF) Gothic2.exe
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=34458FFD  EBX=00000000  ECX=00AB4118  EDX=2754BA26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F3A8  EIP=0079249D  FLG=00010202
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x233F6024 0xFFFFFFFF) Gothic2.exe
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=3B4C7FFD  EBX=00000000  ECX=00AB4118  EDX=25552A26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F400  EIP=0079249D  FLG=00010202
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x233F7024 0xFFFFFFFF) Gothic2.exe
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module Gothic2.exe at 0023:0079249D
    EAX=31179FFD  EBX=00000000  ECX=00AB4118  EDX=27555A26  ESI=00AB4118
    EDI=00AB4108  EBP=00AB40C0  ESP=0135F3A8  EIP=0079249D  FLG=00010202
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:0079249D (0x00000051 0x00000042 0x233F5024 0xFFFFFFFF) Gothic2.exe
    //=====================================================



    Variante 2: ntdll.dll

    Spoiler:(zum lesen bitte Text markieren)

    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module ntdll.dll at 0023:77DDE634, RtlGetCurrentServiceSessionId()+2532 byte(s)
    EAX=0171FE98  EBX=016A00C0  ECX=FFFFFC19  EDX=3091D368  ESI=0171FE90
    EDI=016A0000  EBP=0135F888  ESP=0135F7C0  EIP=77DDE634  FLG=00010246
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:77DDE634 (0x0171FE90 0x0171FE98 0x0171FE98 0x016A0000) ntdll.dll, RtlGetCurrentServiceSessionId()+2532 byte(s)
    0023:77E26CEB (0x00000000 0x00000000 0x00000000 0x00000000) ntdll.dll, LdrCallEnclave()+1931 byte(s)
    0023:77DDDC16 (0x016A0000 0x00000000 0x0171FE98 0x00000000) ntdll.dll, RtlFreeHeap()+70 byte(s)
    0023:71CE7A51 (0x0171FE98 0x0171FE98 0x00AB1168 0x33042650) SHW32.DLL
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module ntdll.dll at 0023:7745E6D4, RtlGetCurrentServiceSessionId()+2532 byte(s)
    EAX=017613C0  EBX=016E00C0  ECX=FFFFFC19  EDX=308974D0  ESI=017613B8
    EDI=016E0000  EBP=0135F750  ESP=0135F688  EIP=7745E6D4  FLG=00010246
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:7745E6D4 (0x017613B8 0x017613C0 0x017613C0 0x016E0000) ntdll.dll, RtlGetCurrentServiceSessionId()+2532 byte(s)
    0023:774A6DAB (0x00000000 0x00000000 0x00000000 0x24A67B00) ntdll.dll, LdrCallEnclave()+1931 byte(s)
    0023:7745DCB6 (0x016E0000 0x00000000 0x017613C0 0x00000000) ntdll.dll, RtlFreeHeap()+70 byte(s)
    0023:735D7A51 (0x017613C0 0x017613C0 0x00AB1168 0x2FAC3300) SHW32.DLL
    //=====================================================

    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module ntdll.dll at 0023:7745E6D4, RtlGetCurrentServiceSessionId()+2532 byte(s)
    EAX=2D08E378  EBX=013C00C0  ECX=FFFFFC19  EDX=2D089D40  ESI=2D08E370
    EDI=013C0000  EBP=0135F750  ESP=0135F688  EIP=7745E6D4  FLG=00010246
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:7745E6D4 (0x2D08E370 0x2D08E378 0x2D08E378 0x013C0000) ntdll.dll, RtlGetCurrentServiceSessionId()+2532 byte(s)
    0023:774A6DAB (0x00000000 0x00000000 0x00000000 0x3D2CB57C) ntdll.dll, LdrCallEnclave()+1931 byte(s)
    0023:7745DCB6 (0x013C0000 0x00000000 0x2D08E378 0x00000000) ntdll.dll, RtlFreeHeap()+70 byte(s)
    0023:71A77A51 (0x2D08E378 0x2D08E378 0x00AB1168 0x2F3D3EB0) SHW32.DLL
    //=====================================================
    Code:
    //======================UNHANDLED EXCEPTION======================
    //======================UNHANDLED EXCEPTION======================
    Gothic2.exe caused a EXCEPTION_ACCESS_VIOLATION in module ntdll.dll at 0023:7745E6D4, RtlGetCurrentServiceSessionId()+2532 byte(s)
    EAX=2E253618  EBX=016700C0  ECX=00000000  EDX=36A55408  ESI=2E253610
    EDI=01670000  EBP=0135F7D0  ESP=0135F708  EIP=7745E6D4  FLG=00010246
    CS=0023   DS=002B  SS=002B  ES=002B   FS=0053  GS=002B
    //=====================  INFOS =========================
    Gothic II - 2.6 (fix), Parser Version: 50
    User:  ...,  CPUType: 586,  Mem: 2048 MB total, 2048 MB free
    //====================== CALLSTACK ========================
    0023:7745E6D4 (0x2E253610 0x2E253618 0x2E253618 0x01670000) ntdll.dll, RtlGetCurrentServiceSessionId()+2532 byte(s)
    0023:774A6DAB (0x00000000 0x00000000 0x00000000 0x00000001) ntdll.dll, LdrCallEnclave()+1931 byte(s)
    0023:7745DCB6 (0x01670000 0x00000000 0x2E253618 0x00000000) ntdll.dll, RtlFreeHeap()+70 byte(s)
    0023:71A77A51 (0x2E253618 0x2E253618 0x00AB18B0 0x2E253618) SHW32.DLL
    //=====================================================

  8. Beiträge anzeigen #168 Zitieren
    Veteran Avatar von N1kX
    Registriert seit
    Aug 2018
    Ort
    Serov
    Beiträge
    640
     
    N1kX ist gerade online
    Zitat Zitat von Milky-Way Beitrag anzeigen
    Einer unserer Tester hat momentan oefter mal Access Violations beim Laden eines Spielstands (aus dem Spiel heraus).

    Die Fehlermeldungen, die dabei produziert wurden, sagen mir erst mal gar nichts (siehe unten) -- gibt es da einen Ansatz, dem Problem auf die Schliche zu kommen?

    Es scheint so, als gaebe es zwei unterschiedliche Fehlermeldungen -- ob beide letztlich auf das selbe Problem hinweisen, weiss ich natuerlich noch nicht.

    Ueber jegliche Ideen, woran es liegen koennte, wuerde ich mich sehr freuen. Wir verwenden Ikarus + LeGo jeweils auf dem aktuellsten Stand, inklusive noch nicht "veroeffentlichten" Aenderungen, die bereits auf Github zu finden sind. (die erschienen mir alle tatsaechliche Bugfixes zu sein, die mehr Problem beheben als ausloesen sollten)

    Falls ich vom Spieler noch andere Infos erfragen sollte, lasst es mich einfach wissen
    Hello. It looks like an error using forbidden memory. Let the tester try to disable DEP in the OS and see if it helps.


    General recommendation for mods with Ikarus + Lego is to disable DEP, SP does not do this, Union always turns it off when installing.

  9. Beiträge anzeigen #169 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Auch wenn der Stacktrace ähnlich aussieht, wie wenn DEP nicht ausgeschaltet ist, glaube ich nicht dass das die Ursache ist. Sonst sollte der Absturz schon viel früher passieren.



    Zitat Zitat von Milky-Way Beitrag anzeigen
    gibt es da einen Ansatz, dem Problem auf die Schliche zu kommen?
    Ja, hier ein paar (dabei beziehe ich mich nur auf das ersten AC):
    1. Nachschlagen der Adresse in IDA, an der die AC auftritt
      Das ist hier 0079249D (oberste Zeile der AC nach dem "0023:"). Unter normalen Umständen wird neben "Gothic2.exe" noch das Debugsymbol aufgeführt aus dem die Exception geworfen wird. Merkwürdig, dass sie hier nicht steht. Das deutet eigentlich darauf hin, dass es sich nicht um die Reportversion handelt.
      Angenommen es ist die Reportversion, dann ist die Adresse 0x79249D in zCParser::DoStack. Das macht es noch seltsamer, denn in dem Fall würde ich einen aussagekräftigeren Stacktrace erwarten (mehr Zeilen mit Ursprung in Daedalus, usw.).
      An der Adresse wird die Variable nach einem "zPAR_OP_UN_PLUS" verarbeitet, also +var. Das Poppen der Variable scheitert, der Stack scheint korrupt.
      Ob diese Diagnose so korrekt ist, bezweifele ich aber, denn der Stack zu dem Zeitpunkt sieht auch komisch aus, d.h. erster Wert (0x00000051) entspräche einem Codeoffset (vgl. hier) innerhalb von mem_checkversion, in dem kein "zPAR_OP_UN_PLUS" Token vorkommt (angenommen es handelt sich um die Content-Skripte und nicht Menu-Skripte o.Ä. oder der Stack hat sich in zCParser::DoStack schon geändert)

    2. Systematisches Ausklammern von benutzten Patchen/Plugins
      Das SystemPack, Ninja, aber vor allem Union(-Plugins) biegen viel in der Engine um. Ich kann mir vorstellen, dass der untypisch unvollständige Stacktrace damit zusammenhängt. Ninja kann ich an der bestimmten Adresse ausschließen und das SystemPack ändert m.W. nach auch nichts im Parser. Wilde Spekulationen, die von Spielern häufig als Absolut genommen werden, will ich hier aber vermeiden und warte desshalb mal auf eine Liste der tatsächlich verwendeten Patchtes/Plugins.

    3. Untersuchen des Logs vom zSpy
      Ninja erlaubt das loggen vom zSpy ohne Mod-Starter o.Ä. Voraussetzung dafür ist, dass der zSpy vor Spielstart gestartet ist und Ninja verwendet wird. Nötige Informationen finden sich dazu hier. Da der Absturz scheinbar häufiger vorkommt, ließe er sich evtl. noch einmal mit zSpy vom Tester reproduzieren.

    4. Überprüfen, ob Speicherstand einer älteren Mod-Version
      Es kann natürlich immer sein, dass etwas in einem Speicherstand nicht mehr mit der aktuellen Version der Mod übereinstimmt. Es wäre interessant zu wissen, ob der Speicherstand von einer früheren Version der Mod stammt oder mit der selben begonnen wurde.
    Das wäre so meine Herangehensweise, bzw. Ansätze.

  10. Beiträge anzeigen #170 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.191
     
    Milky-Way ist offline
    Vielen Dank fuer die Anregungen -- bezueglich Patches etc. habe ich den Tester mal gefragt.

    Ich habe auch mal nach dem genauen Zeitpunkt des Absturzes gefragt -- wuerde es eher auf die Menu.dat hinweisen, wenn der Absturz direkt beim Klick auf den zu ladenen Spielstand kommt?


    Es sollte sich definitiv um einen Spielstand handeln, der mit derselben Version erstellt wurde.


    Mir faellt gerade noch ein, dass wir folgenden Hook drin haben, weil es Probleme gab beim Laden von Spielstaenden, dass Gothic sich ueber korrupte Items beschwert hat. Die Funktion initSavegameWatcher(); wird einmalig pro Session aufgerufen zum Zeitpunkt zu dem wir auch alle unsere anderen Hooks eintragen. Falls es zu unuebersichtlich ist, kann ich auch den Code etwas mehr sortieren, bzw. rausloeschen, was gar nicht aufgerufen wird. Ich habe erst mal alles drin gelassen, damit ggf. Gedankengaenge ersichtlich werden / was / wieso hier im Code probiert wird.

    Code:
    //========================================
    // [intern] Hook controller
    //========================================
    func int _HookWithOptionalSkip(var int funcID, // ESP-36
                    var int _edi,     // ESP-32 // Function parameters in order of popad (reverse order of pushad)
                    var int _esi,     // ESP-28
                    var int _ebp,     // ESP-24
                    var int _esp,     // ESP-20
                    var int _ebx,     // ESP-16
                    var int _edx,     // ESP-12
                    var int _ecx,     // ESP-8
                    var int _eax) {   // ESP-4
    
        // Backup use-instance before anything else. Temporary variable for now, because it's done before locals()
        var int _instBak_temp; _instBak_temp = MEM_GetUseInstance();
    
        // Local backup for recursive hooks
        locals();
        
        var int result;
    
        // Secure register variables locally for recursive hooks
        var int eaxBak; eaxBak = EAX;
        var int ecxBak; ecxBak = ECX;
        var int edxBak; edxBak = EDX;
        var int ebxBak; ebxBak = EBX;
        var int espBak; espBak = ESP;
        var int ebpBak; ebpBak = EBP;
        var int esiBak; esiBak = ESI;
        var int ediBak; ediBak = EDI;
    
        // Get address of yINSTANCE_HELP by symbol index 0
        const int instHlpAddr = 0;
        if (!instHlpAddr) {
            instHlpAddr = MEM_GetSymbolByIndex(0)+zCParSymbol_offset_offset;
        };
    
        // Also secure global instances
        var int selfBak;  selfBak  = _@(self);
        var int otherBak; otherBak = _@(other);
        var int itemBak;  itemBak  = _@(item);
        var int iHlpBak;  iHlpBak  = MEM_ReadInt(instHlpAddr);
        var int instBak;  instBak  = _instBak_temp;
    
        // Update register variables
        EAX = _eax;
        ECX = _ecx;
        EDX = _edx;
        EBX = _ebx;
        ESP = _esp;
        EBP = _ebp;
        ESI = _esi;
        EDI = _edi;
    
        // Check whether Ikarus is initialized for hooks that happen during level change
        if (!_@(MEM_Parser)) {
            MEM_InitLabels();
            MEM_InitGlobalInst();
        };
    
        // Do not overwrite the global instances by default
        HookOverwriteInstances = FALSE;
    
    
            // Clear data stack in-between function calls
            MEM_Parser.datastack_sptr = 0;
    
            // Call the function
            MEM_CallByID(funcID);
            result = MEMINT_StackPopInt();
    
            // Restore global instances in between function calls
            if (!HookOverwriteInstances) {
                MEM_AssignInstSuppressNullWarning = TRUE;
                self  = _^(selfBak);
                other = _^(otherBak);
                item  = _^(itemBak);
                MEM_AssignInstSuppressNullWarning = FALSE;
            };
            MEM_WriteInt(instHlpAddr, iHlpBak);
            MEM_SetUseInstance(instBak);
    
            // Stack registers should be kept read-only in between function calls
            ESP = _esp; // Stack pointer is read-only
            EBP = _ebp; // Base pointer is read-only
    
        // Update modifiable registers on stack (ESP points to the position before pushad)
        MEM_WriteInt(ESP-32, EDI);
        MEM_WriteInt(ESP-28, ESI);
        MEM_WriteInt(ESP-16, EBX);
        MEM_WriteInt(ESP-12, EDX);
        MEM_WriteInt(ESP-8,  ECX);
        MEM_WriteInt(ESP-4,  EAX);
    
        // Restore register variables for recursive hooks
        EDI = ediBak;
        ESI = esiBak;
        EBP = ebpBak;
        ESP = espBak;
        EBX = ebxBak;
        EDX = edxBak;
        ECX = ecxBak;
        EAX = eaxBak;
    
        // Just to be safe: restore again at the very end of the function
        MEM_SetUseInstance(instBak);
        
        return result;
    };
    
    
    
    func void HookWithOptionalSkip_I(var int address, var int oldInstr, var int function) {
        var int SymbID;         // Symbol index of 'function'
        var int ptr;            // Pointer to temporary memory of the old instruction
        var int relAdr;         // Relative address from 'address' to new assembly code
        
        // ----- Safety checks -----
        if (oldInstr < 5) {
            PrintDebug("HookWithOptionalSkip_I: oldInstr is too small. The minimum required length is 5 bytes.");
            return;
        };
        
        SymbID = function;
        if (SymbID == -1) {
            PrintDebug("HookWithOptionalSkip_I: The provided deadalus function was not found.");
            return;
        };
        
        // ----- Backup old instruction -----
        ptr = MEM_Alloc(oldInstr);
        MEM_CopyBytes(address, ptr, oldInstr);
        
        // ----- Allocate new stream for assembly code -----
        ASM_Open(100 + oldInstr + 6 + 1); // Asm code + oldInstr + retn + 1   49 
    
        // ----- Treat possibly protected memory -----
        MemoryProtectionOverride(address, oldInstr+3);
        
        // ----- Add jump from engine function to new code -----
        relAdr = ASMINT_CurrRun-address-5;
        MEM_WriteByte(address + 0, ASMINT_OP_jmp);
        MEM_WriteInt (address + 1, relAdr);
        
        
        // ----- Write new assembly code -----
    
        // Call daedalus hook function
        ASM_1(ASMINT_OP_pusha); // ESP -= 32 (8*4)
    
        ASM_1(ASMINT_OP_pushIm);
        ASM_4(SymbID);
        
        ASM_1(ASMINT_OP_pushIm);
        ASM_4(MEM_GetFuncID(_HookWithOptionalSkip));
        
        ASM_1(ASMINT_OP_pushIm);
        ASM_4(parser);
    
        ASM_1(ASMINT_OP_call);
        ASM_4(zParser__CallFunc-ASM_Here()-4);
        
        ASM_2(ASMINT_OP_addImToESP);
        ASM_1(12); // 3*4: parser, _HookWithOptionalSkip, SymbID
        
        //const int zCParser__GetParameterI = 7997280;//.text:007A0760 ?GetParameter@zCParser@@QAEXAAH@Z proc near
        const int zCParser__PopDataValue = 7936176; //.text:007918B0 ; int __thiscall 
        
        // parser has to be in ecx
        const int MOV_ECX_BASE = 185;// //0xb9   
        
        
        // mov eax, [eax]
        const int GET_RETURN_VALUE = 139; //mov eax, [eax] // 8b 00  -> 008b
        ASM_2(GET_RETURN_VALUE);
        
        //ASM_1(ASMINT_OP_pushIm);
        //ASM_4(parser);
        //ASM_1(ASMINT_OP_call);
        //ASM_4(zCParser__PopDataValue-ASM_Here()-4);
        
        const int TEST_EAX_ZERO = 49285;//test eax, eax //85 C0 => 0xC085 (important: reversed order!)
        ASM_2(TEST_EAX_ZERO);
        
        // skip hooked code if eax is true
        const int SKIP_OPCODE = 1908;// 7 bytes to jump: jz 07 // 74 05 => 0x0774 (important: reversed order!)
        ASM_2(SKIP_OPCODE);
        //ASM_1(oldInstr + 7); // ASMINT_OP_popa, oldInstr, ASMINT_OP_pushIm, address+oldInstr, ASMINT_OP_retn
        
        
        // if (eax != 0)
            ASM_1(ASMINT_OP_popa); // Pop altered registers
            // Return to engine function
            ASM_1(ASMINT_OP_pushIm);
            ASM_4(address + oldInstr);
            ASM_1(ASMINT_OP_retn);
        
        
        
        // else 
            ASM_1(ASMINT_OP_popa); // Pop altered registers
            // Append original instruction
            MEM_CopyBytes(ptr, ASMINT_Cursor, oldInstr);
            MEM_Free(ptr);
            ASMINT_Cursor += oldInstr;
            // Return to engine function
            ASM_1(ASMINT_OP_pushIm);
            ASM_4(address + oldInstr);
            ASM_1(ASMINT_OP_retn);
        
    
        var int i; i = ASM_Close();
    };
    
    
    func void HookWithOptionalSkip_F(var int address, var int oldInstr, var func function) {
        HookWithOptionalSkip_I(address, oldInstr, MEM_GetFuncID(function));
    };
    
    class SimpleStack {
    	var int list;
    	var int numElements;
    };
    
    instance SimpleStack@(SimpleStack) {};
    
    func int SimpleStack_isEmpty(var int stackPtr) {
    	var SimpleStack stack; stack = _^(stackPtr);
    	return stack.numElements == 0;
    };
    
    func void SimpleStack_Clear(var int stackPtr) {
    	if (SimpleStack_isEmpty(stackPtr)) {return;};
    	
    	var SimpleStack stack; stack = _^(stackPtr);
    	
    	List_Destroy(stack.list);
    	stack.list = 0;
    	stack.numElements = 0;
    };
    
    func int SimpleStack_Create() {
        var int ptr; ptr = create(SimpleStack@);
        var SimpleStack stack; stack = _^(ptr);
        stack.list = 0;
        stack.numElements = 0;
    	
        return ptr;
    };
    
    func void SimpleStack_Destroy(var int stackPtr) {
    	SimpleStack_Clear(stackPtr);
    	MEM_Free(stackPtr);
    };
    
    func void SimpleStack_Push(var int stackPtr, var int data) {
    	var SimpleStack stack; stack = _^(stackPtr);
    	
    	if (SimpleStack_isEmpty(stackPtr)) {
    		stack.list = List_Create(data);
    	} else {
    		List_AddFront(stack.list, data);
    	};
    	
    	stack.numElements += 1;
    };
    
    func int SimpleStack_Pop(var int stackPtr) {
    	if (SimpleStack_isEmpty(stackPtr)) {return 0; };
    	var SimpleStack stack; stack = _^(stackPtr);
    	
    	var zCList current; current = _^(stack.list);
    	
    	var int result; result = current.data;
    	var int next; next = current.next;
    	MEM_Free(_@(current));
    	stack.list = next;
    	stack.numElements -= 1;
    	if (SimpleStack_isEmpty(stackPtr)) {
    		stack.list = 0;
    	};
    	
    	return result;
    };
    
    
    
    func void SavegameWatcher__printVTable(var int vTable) {
    
    	const int zCVob_vtbl = 8624508; //.rdata:0083997C ; const zCVob::`vftable'
        const int zCObject_vtbl = 8579228; //.rdata:0082E89C ; const zCObject::`vftable'
    	
    	var string msg;
    	msg = "SavegameWatcher__printVTable: vTable = ";
    	
    	
    	if (vTable == oCItem_vtbl) {
    		msg = ConcatStrings(msg, "oCItem_vtbl"); 
    	} else if (vTable == oCNpc_vtbl) {
    		msg = ConcatStrings(msg, "oCNpc_vtbl"); 
    	} else if (vTable == zCVob_vtbl) {
    		msg = ConcatStrings(msg, "zCVob_vtbl"); 
        } else if (vTable == zCObject_vtbl) {
            msg = ConcatStrings(msg, "zCObject_vtbl"); 
    	} else {
    		msg = ConcatStrings(msg, "other/unknown"); 
    	};
    	
    	MEM_Info(msg); 
    	
    	msg = "SavegameWatcher__printVTable: vtable address = ";
    	msg = ConcatStrings(msg, IntToString(vTable));
    	MEM_Info(msg); 
    };
    
    func void SavegameWatcher__logInstanceName(var int instanceID) {
    
    	MEM_Info("SavegameWatcher__logInstanceName");
    
    	var string msg; msg = "SavegameWatcher__logInstanceName:: log instance id: ";
    	
    	var string instanceName; 
    	
    	if (instanceID < 0 || instanceID >= MEM_Parser.symtab_table_numInArray) {
    		MEM_Info("SavegameWatcher__logInstanceName:: INVALID");
    		instanceName = "INVALID INSTANCE";
    	} else {
    		MEM_Info("Before sym");
    		//var int i; i = MEM_ReadIntArray(currSymbolTableAddress, instanceID);
    		var zCPar_Symbol sym; sym = MEM_PtrToInst(MEM_ReadIntArray(currSymbolTableAddress, instanceID));
    		instanceName = sym.name;
    		MEM_Info("After sym");
    	};
    	
    	msg = ConcatStrings(msg, instanceName);
    	MEM_Info(msg);
    };
    
    
    func void SavegameWatcher__logVob(var int vobPtr) {
    	
    	if (vobPtr == 0) {
    		MEM_Warn("SavegameWatcher__logVob:: vob is null");
    		return;
    	};
    	
    	var zCVob vob; vob = _^(vobPtr);
    	
    	if (vob._vtbl == oCItem_vtbl) {
    		var oCItem itm; itm = _^(vobPtr);
    		MEM_Info("SavegameWatcher__logVob:: Log item");
    		SavegameWatcher__logInstanceName(itm.instanz);
    		MEM_Info("SavegameWatcher__logVob:: Finished logging item");
    	
    	} else if (vob._vtbl == oCNpc_vtbl) {
    		var oCNpc onpc; onpc = _^(vobPtr);
    		MEM_Info("SavegameWatcher__logVob:: Log npc");
    		SavegameWatcher__logInstanceName(onpc.instanz);
    		MEM_Info("SavegameWatcher__logVob:: Finished logging npc");
    		
    	};
    	
    	var string msg; msg = "SavegameWatcher__logVob:: ref-Ctr =  ";
    	var string refCtr; refCtr = IntToString(vob._zCObject_refCtr);
    	msg = ConcatStrings(msg, refCtr);
    	MEM_Info(msg);
    	
    	msg = "SavegameWatcher__logVob:: address (decimal): ";
    	var string address; address = IntToString(vobPtr);
    	msg = ConcatStrings(msg, address);
    	MEM_Info(msg);
    	
    	SavegameWatcher__printVTable(vob._vtbl);
    };
    
    /**
     * Checks a zCVob if it is valid for the world-vob-list.
     * Note: Although zCWorld manages a list of zCVobs, it only stores oCItems and oCNpcs.
     * Thus, other zCVobs are treated as invalid.
     */
    func int SavegameWatcher__isValidVob(var int vobPtr, var int ignoreHighRefs) {
    	
    	var zCVob vob; vob = _^(vobPtr);
    	var int isValid; isValid = 1;
    	
    	//if (vob._vtbl == oCItem_vtbl
    	//|| vob._vtbl == oCNpc_vtbl) {
    	//	isValid = 1;
    	//};
    	
    	if (vob._zCObject_refCtr < 0) {
    		isValid = 0;
    	};
    	
    	if (vob._zCObject_refCtr >= 900 && !ignoreHighRefs) {
    		isValid = 0;
    	};
    	
    	return isValid;
    };
    
    
    func void SavegameWatcher__voblistOnDestruct() {
    	
    	if (EDI == 0) {
    		MEM_Warn("SavegameWatcher__voblistOnDestruct:: A null-pointer is supposed to be deleted!");
    		return;
    	};
    
        var zCObject vob; vob = _^(EDI);
    	
    	if (vob.refCtr < 0) {
    	
    		MEM_Warn("SavegameWatcher__voblistOnDestruct:: Detected corrupted vob!");
    		SavegameWatcher__printVTable(vob._vtbl);
    	};
    };
    func void SavegameWatcher__voblistOnCheckRef() {
    	
    	if (EDI == 0) {
    		MEM_Warn("SavegameWatcher__voblistOnCheckRef:: A null-pointer is supposed to be checked for ref counting!");
    		return;
    	};
    	
        if (ECX < 0) {
    	
    		var zCObject vob; vob = _^(EDI);
    		var string msg;
    		msg = "SavegameWatcher__voblistOnCheckRef:: refCtr = ";
    		msg = ConcatStrings(msg, IntToString(ECX)); // Decreased(!) reference count
    		msg = ConcatStrings(msg, " :: ");
    		msg = ConcatStrings(msg, vob.objectName);
    	
            // Reference counter <= 0: Display message as warning
            MEM_Warn(msg);
        };
    };
    
    func int checkAndCleanup(var int vobList) {
    	var int vobPtr; vobPtr = 0;
    	var int listPtr; listPtr = vobList;
    	//var int corruptedVobsPtr; corruptedVobsPtr = SimpleStack_Create();
    	
    	var int prevPtr; prevPtr = listPtr;
    	
    		
    	while(listPtr != 0);
    		vobPtr = MEM_ReadInt(listPtr + 4);
    		
    		if (vobPtr != 0) {
    			if (!SavegameWatcher__isValidVob(vobPtr, true)) {
    				
    				// log vob to file
    				SavegameWatcher__logVob(vobPtr);
    				
    				var zCListSort list;
    				var zCListSort prev;
    				
    				// skip data-elem
    				if (listPtr == vobList) {
    					list = _^(vobList);
    					//list.data = 0; // Note: Can produce nullptr read
    					if (list.next != 0) {
    						vobList = list.next;
    					};
    					
    				} else {
    					list = _^(listPtr);
    					prev = _^(prevPtr);
    					prev.next = list.next;
    					//list.data = 0; // Note: Can produce nullptr read
    				};
    				
    				
    			};
    		};
    		
    		
    		prevPtr = listPtr;
    		listPtr = MEM_ReadInt(listPtr + 8);
    	end;
    	
    	return vobList;
    };
    
    func void SavegameWatcher__checkVobList() {
    
    	MEM_Info("SavegameWatcher__checkVobList:: Check voblist");
    	
    	MEM_World.voblist = checkAndCleanup(MEM_World.voblist);
    	MEM_World.voblist_items = checkAndCleanup(MEM_World.voblist_items);
    	MEM_World.voblist_npcs = checkAndCleanup(MEM_World.voblist_npcs);
    	
    	MEM_Info("SavegameWatcher__checkVobList:: Finished");
    };
    
    
    //.text:00781480 ; public: void __thiscall zCListSort<class zCVob>::InsertSort(class zCVob *)
    func void SavegameWatcher__zCListZCVobInsertSortHook() {
    
    	var int vobPtr; vobPtr = MEM_ReadInt(ESP + 4);
    	if (!SavegameWatcher__isValidVob(vobPtr, true)) {
    		//AI_PrintScreen ("Detected corrupted vob to be inserted!", -1, YPOS_Global+20, FONT_Screen, 15);
    		MEM_Warn("SavegameWatcher__zCListZCVobInsertSortHook:: Detected corrupted vob to be inserted!");
    		SavegameWatcher__logVob(vobPtr);
    	};
    };
    
    /**
     * @return true if the replaced code for the jump instruction should be skipped; 
     * false otherwise
     */
    func int oCWorldDisposeVobsIterVobListDestructReplaceHook() {
        
        
        // edi contains the vob to be destructed
        if (EDI == 0) {
    		MEM_Warn("SavegameWatcher__voblistOnDestruct:: A null-pointer is supposed to be deleted!");
    		return true;
    	};
    
        var zCObject vob; vob = _^(EDI);
    	
    	if (vob.refCtr < 0) {
    	
    		MEM_Warn("SavegameWatcher__voblistOnDestruct:: Detected corrupted vob!");
            SavegameWatcher__printVTable(vob._vtbl);
            MEM_AssignInstNull(vob);
            return true;
    	};
        
        return false;
    };
    
    func void initSavegameWatcher() {
        //MEM_InitAll();
    
        const int oCWorld__DisposeVobs_iterVoblist_checkRef = 7867681; //0x780D21
        const int oCWorld__DisposeVobs_iterVoblist_destruct = 7867688; //0x780D28
    	const int oCWorld__DisposeVobs = 7867344; //.text:00780BD0 ?DisposeVobs@oCWorld@@UAEXXZ proc near  ; CODE XREF: oCWorld::~oCWorld(void)+35↑p
        const int zCListSort__InsertSort = 7869568; //.text:00781480 ; public: void __thiscall zCListSort<class zCVob>::InsertSort(class zCVob *)
    	//HookEngineF(oCWorld__DisposeVobs_iterVoblist_checkRef, 5, SavegameWatcher__voblistOnCheckRef);
        //HookEngineF(oCWorld__DisposeVobs_iterVoblist_destruct, 6, SavegameWatcher__voblistOnDestruct);
    	//HookEngineF(oCWorld__DisposeVobs, 10, SavegameWatcher__checkVobList);
    	//HookEngineF(zCListSort__InsertSort, 5, SavegameWatcher__zCListZCVobInsertSortHook);
        
        const int oCWorld__DisposeVobs_iterVoblist_destruct_replace = 7867688; //00780D28
        HookWithOptionalSkip_F(oCWorld__DisposeVobs_iterVoblist_destruct_replace, 9, oCWorldDisposeVobsIterVobListDestructReplaceHook);
    };

  11. Beiträge anzeigen #171 Zitieren
    Ehrengarde Avatar von mud-freak
    Registriert seit
    Dec 2005
    Beiträge
    2.199
     
    mud-freak ist offline
    Danke für den Code. Ein zSpy Log wäre tatsächlich im Moment notwendig, um mehr zum Ursprung sagen zu können. Da der Absturz, wenn ich das richtig verstehe, unmittelbar zu Beginn des Ladevorgangs auftritt, ist ein Zusammenhang mit dem oCWorld::DisposeVobs-Hook nicht unwahrscheinlich. Aus dem Skript heraus konnte ich da aber so ohne Weiteres nicht erkennen, wo es zu einem Problem kommen könnte, weil das doch recht sehr verkapselt ist.

    Beiläufig könntet ihr mit dieser etwas "leichteren" (und performanteren) Lösung etwas aufräumen, wenn ihr auf die Debugausgaben verzichten könnt. Vielleicht behebt es das Problem schon. Mit dem Skript unten (nur mäßig getestet) fällt im Grunde der gesamte gepostete Code weg. Anstatt den Referenzzähler zu überprüfen, wird hier ein Check eingeschoben der prüft, ob die Adresse der virtuellen Tabelle sich in einem sinnvollen Bereich befindet, um zu bestimmen ob es sich um einen gültigen zCVob-Pointer handelt. Andere, besserdefinierte Ansätze (z.B. über __RTDynamicCast, um Objektklassen/-vererbungen festzustellen) verkraften ungültige Pointer nicht.
    Spoiler:(zum lesen bitte Text markieren)
    Code:
    func void hookDisposeVobs() {
        // In assembly for faster execution
        const int oCWorld__DisposeVobs_destroyVob = 7867690; //0x780D2A
    
        // Only write it once
        if (MEM_ReadByte(oCWorld__DisposeVobs_destroyVob) == /*6A*/106) {
    
            // Overwrite old code (modified from LeGo_HookEngine)
            ASM_Open(/*new*/14 + /*old*/7 + /*ret*/6);
            var int relAdr; relAdr = ASMINT_CurrRun-oCWorld__DisposeVobs_destroyVob-5;
            MemoryProtectionOverride(oCWorld__DisposeVobs_destroyVob, 5);
            MEM_WriteByte(oCWorld__DisposeVobs_destroyVob+0, ASMINT_OP_jmp);
            MEM_WriteInt( oCWorld__DisposeVobs_destroyVob+1, relAdr);
    
            // Check if address lies between smallest and largest known vtbl addresses
            ASM_1(/*3D*/ 61); ASM_4(/*0x82E6F0*/8578800);               //cmp  eax, zSTRING__vftable
            ASM_1(/*7C*/124); ASM_1(14);                                //jl   .done
            ASM_1(/*3D*/ 61); ASM_4(/*0x843DB4*/8666548);               //cmp  eax, exception__vftable
            ASM_1(/*7F*/127); ASM_1(7);                                 //jg   .done
            // Rewrite what has been overwritten
            ASM_1(/*6A*/106); ASM_1(/*01*/  1);                         //push 0x1
            ASM_1(/*8B*/139); ASM_1(/*CF*/207);                         //mov  ecx, edi
            ASM_1(/*FF*/255); ASM_1(/*50*/ 80); ASM_1(/*0C*/ 12);       //call DWORD PTR [eax+0xC]
            // .done:
            ASM_1(/*68*/104); ASM_4(oCWorld__DisposeVobs_destroyVob+7); //push address
            var int i; i = ASM_Close();                                 //ret
        };
    };

    Ist das Überprüfen der Vobliste aktuell denn noch notwending? Wenn ja, wäre es anstatt dessen vielleicht mal an der Zeit dem tatsächlichen Ursprung der ungültigen Vobs in der Vobliste auf die Schliche zu kommen als nur Symptome zu bekämpfen (die, wie möglicherweise hier, noch mehr Probleme erzeugen).


    Bevor wir hier irgendetwas überstürzen wäre der zSpy log sinnvoll, gerade weil der Stacktrace der AV so unvollständig ist.

  12. Beiträge anzeigen #172 Zitieren
    Knight Commander Avatar von Neconspictor
    Registriert seit
    Jan 2009
    Beiträge
    2.749
     
    Neconspictor ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Ist das Überprüfen der Vobliste aktuell denn noch notwending? Wenn ja, wäre es anstatt dessen vielleicht mal an der Zeit dem tatsächlichen Ursprung der ungültigen Vobs in der Vobliste auf die Schliche zu kommen als nur Symptome zu bekämpfen (die, wie möglicherweise hier, noch mehr Probleme erzeugen).
    Diese unschöne Lösung haben wir eingesetzt, weil wir dem eigentlichen Problem nicht auf die Schliche gekommen sind. Müsste man also durch reines Testen ausprobieren, ob's jetzt auch ohne geht. Problem ist, dass damals die Abstürze sehr unregelmäßig und manchmal erst nach Stunden aufgetreten sind. Da ist es extrem schwer, das eigentliche Problem zu lokalisieren.

  13. Beiträge anzeigen #173 Zitieren
    now also in your universe  Avatar von Milky-Way
    Registriert seit
    Jun 2007
    Beiträge
    15.191
     
    Milky-Way ist offline
    Zitat Zitat von mud-freak Beitrag anzeigen
    Danke für den Code. Ein zSpy Log wäre tatsächlich im Moment notwendig, um mehr zum Ursprung sagen zu können. Da der Absturz, wenn ich das richtig verstehe, unmittelbar zu Beginn des Ladevorgangs auftritt, ist ein Zusammenhang mit dem oCWorld::DisposeVobs-Hook nicht unwahrscheinlich. Aus dem Skript heraus konnte ich da aber so ohne Weiteres nicht erkennen, wo es zu einem Problem kommen könnte, weil das doch recht sehr verkapselt ist.
    Aktuell tritt der Fehler (leider?) nicht mehr auf beim Spieler, daher kann es noch etwas dauern, bis wir da mal ein zSpy-log zu bekommen. Eventuell deutet das daraufhin, dass der Fehler mit etwas zusammenhängt, was es vor allem zu Beginn der Mod gibt, aber das ist letztlich nur wilde Spekulation.

    Die Funktion hookDisposeVobs würde ich im nächsten Durchlauf ausprobieren lassen.

  14. Beiträge anzeigen #174 Zitieren
    Veteran Avatar von N1kX
    Registriert seit
    Aug 2018
    Ort
    Serov
    Beiträge
    640
     
    N1kX ist gerade online
    Hello. Nobody figured out why a dat file sometimes cannot be unpacked via DecDat? It displays an error like this

    Spoiler:(zum lesen bitte Text markieren)
    [23:08:39] Inf: export symbol dia_cassia_magicbook_justint(:69009)[23:08:39] Inf: export symbol dia_cassia_magicbook_kill(:69010)
    [23:08:39] Inf: export symbol dia_cassia_magicbook_stolen(:69011)
    [23:08:39] Inf: export symbol dia_cassia_magicbook_rumors(:69012)
    [23:08:39] Inf: export symbol dia_cassia_richstones(:69013)
    [23:08:39] Inf: export symbol dia_cassia_richstones_condition(:69014)
    [23:08:39] ERR: unhandled exception occured: java.lang.ArrayIndexOutOfBoundsException: -1
    java.lang.ArrayIndexOutOfBoundsException: -1
    at de.lego.gottfried.decdat.decompiler.Function.decompileParameter(Function.java:71 )
    at de.lego.gottfried.decdat.decompiler.Function.decompileOperation(Function.java:14 1)
    at de.lego.gottfried.decdat.decompiler.Function.decompile(Function.java:239)
    at de.lego.gottfried.decdat.decompiler.Function.<init>(Function.java:261)
    at de.lego.gottfried.decdat.decompiler.Decompiler.addBytecode(Decompiler.java:105)
    at de.lego.gottfried.decdat.decompiler.DecompilerFunction.toString(DecompilerFuncti on.java:38)
    at de.lego.gottfried.decdat.exporter.Exporter.toFile(Exporter.java:25)
    at de.lego.gottfried.decdat.exporter.Exporter.ToFile(Exporter.java:125)
    at de.lego.gottfried.decdat.MainForm.actionPerformed(MainForm.java:264)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.AbstractButton.doClick(Unknown Source)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Un known Source)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Un known Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Un known Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)


    It looks like DecDat has any bugs because it mangles functions.
    For example
    Code:
    func void dia_cassia_magicbook_stolen() {    b_giveplayerxp(150);
        ai_output(other, self, я140801);
        ai_output(self, other, я140802);
        ai_output(other, self, я140803);
        ai_output(self, other, я140804);
        self;
        other;
        я140805;
    };
    And this is how DecDat should show the same function.

    Code:
    func void dia_cassia_magicbook_stolen() {
        B_GivePlayerXP(150);
        AI_Output(other, self, я140801); 
        AI_Output(self, other, я140802;
        AI_Output(other, self, я140803); 
        AI_Output(self, other, я140804); 
        AI_Output(self, other, я140805); 
        B_LogEntry(TOPIC_VATRASMAGICBOOK, я140806);
        magicbookfindtrade = TRUE;
        Info_ClearChoices(69006);
    };

Seite 9 von 9 « Erste ... 256789

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
Impressum | Link Us | intern
World of Gothic © by World of Gothic Team
Gothic, Gothic 2 & Gothic 3 are © by Piranha Bytes & Egmont Interactive & JoWooD Productions AG, all rights reserved worldwide