```cpp ////// #define NB_ELEM 75 class SOOLStck; union SOOLFile { struct { /*00*/ char signature[4]; /*04*/ u32 size; /*08*/ u16 numSections; /*0A*/ u8 _pad[2]; /*0C u32 sectionOffsets[count]; */ } hdr; u8 bytes[]; }; union SOOLSctn { struct { /*00*/ u16 offsVars; /*02*/ u16 offsVarsEnd; /*04*/ u16 offsVirtualElements; /*06*/ u16 numVirtualElements; /*08*/ u16 unk08; /*0A*/ u16 numPublicMethods; // ? or could be an index of a particular method /*0C*/ u16 offsMethodsEnd; // offsMethodsEnd /*0E*/ u16 numMethods; // numMethods ? /*10 u16 methodOffsets[numMethods]; */ } hdr; u8 bytes[]; }; struct SOOLElem { /*00*/ u16 key; /*02*/ u16 value; }; class SOOLStck { private: /*0x00*/ s16 m_Array[NB_ELEM]; /*0x96*/ u8 _pad[2]; /*0x98*/ s32 m_Count; public: void Reset(void); // func_800628A0 bool IsFull(void); // func_800628A8 bool IsEmpty(void); // func_800628B8 bool Push(s16 value); // func_800628C4 s16 Pop(void); // func_80062924 void Trim(s32 n); // func_80062980 s16 Top(s32 i); // func_800629E0 void Reset2(void); // func_80062A40 void PrintValues(void); // func_80062A48 }; typedef void (*UnkC8Func)(void*); extern SOOLCtx *func_8005A820(void *unk, s16 ctxId); extern void io_print(const char*); // func_80057130 class SOOLCtx { private: /*00*/ u32 m_CtxId; /*04*/ void *m_unk04; // passed to unkC8 /*08*/ SOOLStck m_Stack; /*A4*/ u16 m_unkA4; // index of m_MethodOffsets /*A6*/ u16 m_unkA6; // set to m_Section->hdr.numPublicMethods; /*A8*/ s32 m_unkA8; /*AC*/ SOOLCtx *m_ExecCtx; /*B0*/ s16 m_Acc; // scratch value? // can be set to m_MethodOffsets[m_unkA4]; /*B2*/ s16 m_unkB2; /*B4*/ u8 m_Flags; // flags /*B5*/ u8 _pad[3]; // probably padding /*B8*/ SOOLSctn *m_Section; // pointer to variables/commands, has a header struct /*BC*/ u16 *m_MethodOffsets; // &m_Section->bytes[sizeof(SOOLSctn)], table of method offsets /*C0*/ s32 m_unkC0; /*C4*/ void *m_unkC4; /*C8*/ UnkC8Func m_unkC8; // a function pointer, receives m_unk04 public: SOOLCtx(/*a1*/u32 ctxId, /*a2*/struct SOOLFile *file, u32 sctnOffset, s32 sp10, void *sp14); // func_80061280 void func_800612E0(void); // func_800612E0 s32 Step(s16 *offs); // func_80061314 u16 GetElementValue(u16 key); // GetElementValue s8 GetFlags(void); // func_800625DC u16 GetA4(void); // func_800625F0 void SetA4(u16 value); // func_800625F8 u16 GetA6(void); // func_80062604 s32 GetA8(void); // func_8006260C s32 GetCtxId(void); // func_80062614 void func_8006261C(u16 a1); // func_8006261C void CheckMethod(u16 methodId); // func_80062680 s32 Get04(void); // func_80062718 void Set04(void *ptr); // func_8006272C void *GetC4(void); // func_80062734 void CheckVariable(s16 offset); // func_8006273C u8 *GetSectionData(u16 offset); // func_800627DC void SetC8(UnkC8Func ptr); // func_800627EC void SetFlags(u8 flags, bool bSet); // func_800627F4 void func_80062818(void); // func_80062818 void func_80062854(void) // func_80062854 void func_80062864(void) // func_80062864 void *GetAccPtr() // func_80062880 void *GetB2Ptr() // func_80062888 SOOLSctn *GetSection() // func_80062890 SOOLStck *GetStack(void) // func_80062898 }; /*****************************************************************/ SOOLCtx::SOOLCtx(/*a1*/u32 ctxId, /*a2*/struct SOOLFile *file, u32 stcnOffset, s32 sp10, void *sp14) // func_80061280 { m_CtxId = ctxId; m_unk04 = NULL; m_unkA4 = 0xFFFF; m_unkA6 = 0; m_unkA8 = 0; m_ExecCtx = this; m_Acc = 0; m_unkB2 = 0; m_Section = (SOOLSctn*) &file.bytes[stcnOffset]; // sctnOffset = an offset from the list after file header m_MethodOffsets = (m_Section->hdr.numMethods != 0) ? &m_Section->bytes[sizeof(SOOLSctn)] : NULL; m_unkC0 = sp10; m_unkC4 = sp14; m_unkC8 = NULL; } void SOOLCtx::func_800612E0(void) // func_800612E0 { if(m_Section != NULL) { m_Section = NULL; } if(m_unkC8 != NULL) { m_unkC8(m_unk04); } } s32 SOOLCtx::Step(s16 *offs) // func_80061314 { // j 80062518: a0->Push(a1); *offs++; return 1; // j 80062518: *offs++; return 1; // j 80062534: return 1; // j 80062538: return; // j 80061570: a0->Push(a1); *offs += 3; return 1; // j 80061578: *offs += 3; return 1; // s4 = this // s5 = offs (&this->unkB0) // huge switch with all the SOOL operations switch(m_Section->bytes[*offs]) // jump table at 800926D8 { case 0x00: // 80061370 SetFlags((1 << 1), true); return 1; case 0x01: // 80061388 return 0; case 0x02: // 80061390 // 02 // pop offset from the stack and branch to it. // pop value from stack and ? struct SOOLStck *stck = GetStack(); *offs = stck->Pop(); m_ExecCtx = func_8005A820(GetC4(), stck->Pop()); return 1; case 0x03: // 800613D0 // 03 [XX XX] // pop value from stack. if value is nonzero, branch to XXXX if((GetStack()->Pop() << 16) != 0) { //goto L80061578; *offs += 3; return 1; } // fallthrough case 0x04: // 800613EC // 04 [XX XX] // branch to XXXX u8 *mem = &m_ExecCtx->m_Section->bytes[*offs]; *offs = mem[1] | (mem[2] << 8); return 1; case 0x05: // 8006153C case 0x06: case 0x09: // 05 [XX XX] // 06 [XX XX] // 09 [XX XX] // byteswap XXXX and push to stack u8 *mem = &m_ExecCtx->m_Section->bytes[*offs]; GetStack()->Push((s16)(cmd[1] | (cmd[2] << 8))); *offs += 3; return 1; case 0x07: // 80061414 // 07 [XX XX] // load variable from offset XXXX, push variable to stack. u8 *cmd = m_ExecCtx->m_Section->bytes[*offs]; m_ExecCtx->CheckVariable(cmd[1] | (cmd[2] << 8)); // print error message if var is out of bounds cmd = m_ExecCtx->m_Section->bytes[*offs]; s16 *unk = m_ExecCtx->GetSectionData(cmd[1] | (cmd[2] << 8)); GetStack()->Push(unk[0]); *offs += 3; return 1; case 0x08: // 80061474 // 08 [XX XX] [YY YY] // XXXX=ctxId,YYYY=varOffset // load variable from offset YYYY in context specified by XXXX, push variable to stack u8 *cmd = &m_ExecCtx->m_Section.bytes[*offs]; SOOLCtx *ctx = func_8005A820(GetC4(), cmd[1] | (cmd[2] << 8)); cmd = &m_ExecCtx->m_Section.bytes[*offs]; ctx->CheckVariable(cmd[3] | (cmd[4] << 8)); cmd = &m_ExecCtx->m_Section.bytes[*offs]; ctx = func_8005A820(GetC4(), cmd[1] | (cmd[2] << 8)); cmd = &m_ExecCtx->m_Section.bytes[*offs]; u16 *var = ctx->GetSectionData(cmd[3] | (cmd[4] << 8)); GetStack()->Push(*var); *offs = *offs + 5; return 1; case 0x0A: // 80061588 // 0A [XX XX] [YY YY] // push two immediate values to the stack SOOLStck *stck = GetStack(); u8 *cmd = m_ExecCtx->m_Section.bytes[*offs]; stck->Push(cmd[1] | cmd[2] << 8); stck = GetStack(); cmd = m_ExecCtx.m_Section.bytes[*offs]; stck.Push(cmd[3] | cmd[4] << 8); *offs = *offs + 5; return 1; case 0x0B: // 800615E8 SOOLStck *stck = GetStack(); u16 key = stck->Pop(); u16 value = func_8005B410(GetC4(), stck->Pop(), key); // element value stck->Push(value); *offs = *offs + 1; return 1; case 0x0C: // 80061634 SOOLStck *stck = GetStack(); u16 key = stck->Pop(); // element key u16 value = func_8005B410(GetC4(), stck->Top(1), key) // element value stck->Push(value); *offs = *offs + 1; return 1; case 0x0D: // 80061684 SOOLStack *stck = GetStack() u16 key = stck->Pop(); // element key u16 ctxId = stck->Pop(); SOOLCtx *ctx = func_8005A820(GetC4(), ctxId); ctx->CheckVariable(func_8005B410(GetC4(), ctxId, key)); ctx = func_8005A820(GetC4(), ctxId); s16 *var = ctx->GetSectionData(func_8005B410(GetC4(), ctxId, key)) stck->Push(*var); *offs = *offs + 1; return 1; case 0x0E: // 80061734 // 0E [XXXX] [YYYY] u8 *cmd = &m_ExecCtx->m_Section.bytes[*offs]; if(m_unkA4 == cmd[1] | (cmd[2] << 8)) { *offs = (cmd[3] | cmd[4] << 8) return 1; } cmd = &m_ExecCtx->m_Section.bytes[*offs]; GetStack()->Push(cmd[2] << 8 | cmd[1]) *offs = *offs + 5; return 1; case 0x0F: // 800617C4 SOOLStck *stck = GetStack() if(stck->Pop() != 0) { this->func_8006261C(stck->Pop()); *offs = *offs + 1; return 1; } stck->Pop(); *offs = *offs + 1; return 1; case 0x10: // 80061810 SetFlags(1 << 2, true); *offs = *offs + 1; return 1; case 0x11: break; // 80061828 SetFlags(1 << 2, false); *offs = *offs + 1; return 1; case 0x12: // 80061840 SOOLStck *stck = GetStack() if(m_ExecCtx->GetA4() == s1->Pop()) { s1->Push(1); } else { s1->Push(0); } *offs = *offs + 1; return 1; case 0x13: // 80061880 SOOLStck *stck = GetStack() if(func_8005A820(GetC4(), s1->Pop())->GetA4() == s1->Pop()) { stck->Push(1); } else { stck->Push(0) } *offs = *offs + 1; return 1; case 0x14: // 800618E4 SOOLStck *stck = GetStack() stck->Push((s32)(stck->Pop() << 16) < 1); *offs = *offs + 1; return 1; case 0x15: // 80061908 // 15 // pop 2 values from the stack. push 1 if values are equal, else push 0. SOOLStck *stck = GetStack() stck->Push(((stck->Pop() ^ stck->Pop()) << 16) < 1); *offs = *offs + 1; return 1; case 0x16: break; // 8006193C // 16 // pop 2 values from the stack. push 1 if values are not equal, else push 0. SOOLStck *stck = GetStack(); stck->Push(0 < (stck->Pop() ^ stck-Pop()) << 16) *offs = *offs + 1; return 1; case 0x17: // 80061970 SOOLStck *stck = GetStack() if(stck->Pop() << 16 != 0) { if(stck->Pop() << 16 != 0) { stck->Push(1) *offs = *offs + 1; return 1; } else { stck->Push(0) *offs = *offs + 1; return 1; } } stck->Pop(); stck->Push(0); *offs = *offs + 1; return 1; case 0x18: break; // 800619C0 SOOLSTck *stck = GetStack() if(stck->Pop() << 16 != 0) { stck->Pop(); stck->Push(1); *offs = *offs + 1; return 1; } else { if(stck->Pop() << 16 != 0) { stck->Pop(); stck->Push(1); *offs = *offs + 1; return 1; } } stck->Pop(); stck->Push(0); *offs = *offs + 1; return 1; case 0x19: // 80061A18 // 19 // pop 2 values from the stack, subtract them, push result to stack SOOLStck *stck = GetStack(); stck->Push(stck->Pop() - stck->Pop()); *acc++; return 1; case 0x1A: // 80061A4C // 1A // pop 2 values from the stack, sum them, push result to stack SOOLStck *stck = GetStack(); stck->Push(stck->Pop() + stck->Pop()); *acc++; return 1; case 0x1B: // 80061A80 // 1B // pop 2 values from the stack, mod divide them, push result to stack SOOLStck *stck = GetStack(); s16 temp = stck->Pop(); if(stck->Top(1) << 16 == 0) { io_print("SOOL Engine: you have tried to divide an expression by zero."); } stck->Push(temp % stck->Pop()); *acc++; return 1; case 0x1C: // 80061B10 // 1C // pop 2 values from the stack, multiply them, push result to stack SOOLStck *stck = GetStack(); // s1 stck->Push(stck->Pop() * stck->Pop()); *acc++; return 1; case 0x1D: // 80061B4C // 1D // pop 2 values from the stack, divide them, push result to stack SOOLStck *stck = GetStack(); s16 temp = stck->Pop(); if(stck->Top(1) << 16 == 0) { io_print("SOOL Engine: you have tried to divide an expression by zero."); } stck->Push(temp / stck->Pop()); *acc++; return 1; case 0x1E: // 80061BDC // 1E // pop 2 values from the stack, push (val1 < val2) to the stack SOOLStck *stck = GetStack(); s16 val1 = stck->Pop(); s16 val2 = stck->Pop(); stck->Push(val1 < val2); *offs++; return 1; case 0x1F: // 80061C18 // 1F // pop 2 values from the stack, push (val2 < val1) to the stack SOOLStck *stck = GetStack(); s16 val1 = stck->Pop(); s16 val2 = stck->Pop(); stck->Push(val2 < val1); *offs++; return 1; case 0x20: // 80061C54 // 20 // pop 2 values from the stack, push !(val2 < val1) to the stack SOOLStck *stck = GetStack(); s16 val1 = stck->Pop(); s16 val2 = stck->Pop(); stck->Push(!(val2 < val1)); *offs++; return 1; case 0x21: // 80061C94 // 21 // pop 2 values from the stack, push !(val1 < val2) to the stack SOOLStck *stck = GetStack(); s16 val1 = stck->Pop(); s16 val2 = stck->Pop(); stck->Push(!(val1 < val2)); *offs++; return 1; case 0x22: // 80061CD4 // 22 // pop value from the stack, negate value, push result to stack SOOLStck *stck = GetStack(); stck->Push(-stck->Pop()); *offs++; return 1; case 0x23: // 80061CFC // 23 // pop 2 values from the stack, bitwise AND them, push result to stack SOOLStck *stck = GetStack(); stck->Push(stck->Pop() & stck->Pop()); *offs++; return 1; case 0x24: // 80061D30 // 24 // pop 2 values from the stack, bitwise OR them, push result to stack SOOLStck *stck = GetStack(); stck->Push(stck->Pop() | stck->Pop()); *offs++; return 1; case 0x25: // 80061D64 // 25 // pop 2 values from the stack, shift first value left by second value, push result to stack SOOLStck *stck = GetStack(); stck->Push(stck->Pop() << stck->Pop()); *offs++; return 1; case 0x26: // 80061DA0 // 26 // pop 2 values from the stack, shift first value right by second value, push result to stack SOOLStck *stck = GetStack(); stck->Push(stck->Pop() >> stck->Pop()); *offs++; return 1; case 0x28: // 80061DD4 // 28 // pop variable offset from the stack, copy value from stack top to variable (do not pop value) SOOLStck *stck = GetStack(); s16 varOffset = stck->Pop(); s16 value = stck->Top(1); m_ExecCtx->CheckVariable(s0); u16 *var = m_ExecCtx->GetSectionData(varOffset); *var = value; *offs++; return 1; case 0x29: // 80061E20 // 29 // pop variable offset, context id (? unchecked), from stack // copy value from top of stack to context's variable (do not pop value) SOOLStck *stck = GetStack(); s16 varOffset = stck->Pop(); s16 ctxId = stck->Pop(); // ????? s16 value = stck->Top(); func_8005A820(GetC4(), ctxId)->CheckVariable(varOffset); u16 *var = func_8005A820(GetC4(), ctxId)->GetSectionData(varOffset); *var = value; *offs++; return 1; case 0x2A: // 80061EA4 // 2A // pop variable offset, increment variable in memory by 1 u16 varOffset = GetStack()->Pop(); // the code fetches the var pointer twice for some reason. could indicate macro usage. u16 value = *m_ExecCtx->GetSectionData(varOffset); u16 *var = m_ExecCtx->GetSectionData(varOffset); *var = value + 1; *offs = *offs + 1; return 1; case 0x2B: // 80061EE0 // 2B // pop variable offset and context id. increment context's variable by 1 SOOLStck *stck = GetStack(); u16 varOffset = stck->Pop(); u16 ctxId = stck->Pop(); func_8005A820(GetC4(), ctxId)->CheckVariable(varOffset) u16 *var = func_8005A820(GetC4(), ctxId)->GetSectionData(varOffset); *var = *var + 1; *offs = *offs + 1; return 1; case 0x2C: // 80061F5C // 2C // pop variable offset, decrement variable by 1 u16 varOffset = GetStack()->Pop(); u16 value = *m_ExecCtx->GetSectionData(varOffset); u16 *var = m_ExecCtx->GetSectionData(varOffset); *var = value - 1; *offs = *offs + 1; return 1; case 0x2D: // 80061F98 // 2D // pop variable offset and context id from the stack, decrement context's variable by 1 SOOLStck *stck = GetStack(); u16 varOffset = stck->Pop(); u16 ctxId = stck->Pop(); func_8005A820(GetC4(), ctxId)->CheckVariable(varOffset); u16 *var = func_8005A820(GetC4(), ctxId)->GetSectionData(varOffset); *var = *var - 1; *offs++; return 1; case 0x2E: // 80062014 // 2E // pop 2 variable offsets from the stack, copy first variable to the second SOOLStck *stck = GetStack(); u16 *var1 = m_ExecCtx->GetSectionData(stck->Pop()); u16 *var2 = m_ExecCtx->GetSectionData(stck->Pop()); *var2 = *var1; *offs++; return 1; case 0x2F: // 8006205C // 2F // pop variable offset, context id, and value from stack. add value to context's variable SOOLStck *stck = GetStack(); u16 varOffset = stck->Pop(); u16 ctxId = stck->Pop(); func_8005A820(GetC4(), ctxId)->CheckVariable(varOffset); u16 *var = func_8005A820(GetC4(), ctxId)->GetSectionData(varOffset); *var = *var + stck->Pop(); *offs = *offs + 1; return 1; case 0x30: break; // 800620E4 // 30 // pop variable offset and value from the stack. Subtract value from variable. SOOLStck *stck = GetStack() u16 varOffset = stck->Pop(); u16 *var = m_ExecCtx->GetSectionData(varOffset); u16 value = *var; u16 newValue = value - stck->Pop(); var = m_ExecCtx->GetSectionData(varOffset); *var = newValue; *offs = *offs + 1; return 1; case 0x31: // 8006212C // 31 // pop variable offset, context id, and value from the stack. Subtract value from context's variable. SOOLStck *stck = GetStack(); u16 varOffset = stck->Pop(); u16 ctxId = stck->Pop(); func_8005A820(GetC4(), ctxId)->CheckVariable(); u16 *var = func_8005A820(GetC4(), ctxId)->GetSectionData(varOffset); *var = *var - stck->Pop(); *offs = *offs + 1; return 1; case 0x32: // 8006220C SetFlags(1 << 3, false); *offs = *offs + 1; return 1; case 0x34: // 80062224 // 34 // set flag 0, clear flag 3 m_ExecCtx->SetFlags(1 << 0, true); m_ExecCtx->SetFlags(1 << 3, false); *offs = *offs + 1; return 1; case 0x35: // 800621B4 // 35 // pop context id. clear flags 0 and 1 from context. SOOLCtx *ctx = func_8005A820(GetC4(), GetStack()->Pop()); ctx->SetFlags(1 << 0, false); ctx->SetFlags(1 << 0, false); *offs = *offs + 1; return 1; case 0x36: // 8006224C func_8005A820(GetC4, GetStack->Pop())->SetFlags(1, 1) *offs = *offs + 1; return 1; case 0x37: // 80062290 m_ExecCtx->func_8006261C(GetStack()->Pop()); if(m_ExecCtx->GetA8() != 0) { m_ExecCtx->SetFlags(1 << 3, false); } *offs = *offs + 1; return 1; case 0x38: break; // 800622D4 SOOLStck *stck = GetStack() SOOLCtx *ctx = func_8005A820(GetC4(), stck->Pop()) func_8006261C(ctx, stck->Pop()) if(ctx->GetA8() != 0) { ctx->SetFlags(1 << 3, false) } *offs = *offs + 1; return 1; case 0x39: // 80062340 SOOLStck *stck = GetStack(); u16 idx = stck->Pop(); m_ExecCtx->CheckMethod(idx); stck->Push(m_ExecCtx->GetCtxId()) *offs = *offs + 1; stck->Push(*offs); *offs = m_ExecCtx->unkBC[idx]; return 1; case 0x3A: break; // 800623A4 SOOLStck *stck = GetStack() u16 ctxId = stck->Pop() u16 methodId = stck->Pop() stck->Push(m_ExecCtx->GetCtxId()) *offs = *offs + 1; stck->Push(*offs); m_ExecCtx = func_8005A820(GetC4(), ctxId); m_ExecCtx->CheckMethod(methodId); *offs = m_ExecCtx->unkBC[methodId]; return 1; case 0x3B: // 80062440 // pop value from stack, do nothing with it SOOLStck *stck = GetStack(); stck->Pop(); *acc++; return 1; case 0x3C + 0: // 80062458 case 0x3C + 1: case 0x3C + 2: case 0x3C + 3: case 0x3C + 4: case 0x3C + 5: case 0x3C + 6: case 0x3C + 7: case 0x3C + 8: case 0x3C + 9: case 0x3C + 10: case 0x3C + 11: case 0x3C + 12: case 0x3C + 13: case 0x3C + 14: // call function with (cmdbyte-0x3B) args provided in the stack? s32 sp10 = 0; struct SOOLStck *stck = GetStack(); funcptr_8008C514(this, stck, &sp10); stck->Trim(m_ExecCtx->m_Section->bytes[*acc] + (sp10 + -0x3B)); *acc++; return 1; case 0x27: case 0x33: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F: // 80062528 io_print("SOOL Engine: Encountered an unknown operator code."); break; case 0x50 + 0: case 0x50 + 1: case 0x50 + 2: case 0x50 + 3: case 0x50 + 4: case 0x50 + 5: case 0x50 + 6: case 0x50 + 7: case 0x50 + 8: case 0x50 + 9: case 0x50 + 10: case 0x50 + 11: case 0x50 + 12: case 0x50 + 13: case 0x50 + 14: // 800624B0 // note func_8005B55C initializes funcptr_8008C510 = func_80057140 // call function with (cmdbyte-0x4F) args provided in the stack, push return value to stack? s32 sp14 = 0; struct SOOLStck *stck = GetStack(); s16 retval = funcptr_8008C510(this, stck, &sp14); // always 80057140? stck->Trim(m_ExecCtx->m_Section->bytes[*acc] + (sp14 - 0x4F)); stck->Push(retval); *acc++; return 1; } } u16 SOOLCtx::GetElementValue(u16 key) { s32 index; if(m_Section->hdr.numVirtualElements != 0) { struct SOOLElem *table = (struct SOOLElem *) &m_Section->bytes[m_Section->hdr.offsVirtualElements]; for(index = 0; index < m_Section->hdr.numVirtualElements; index++) { if(table[index].key == key) { break; } } if(index != m_Section->hdr.numVirtualElements) { return table[index].value; } } io_print("SOOL Engine: unable to find the virtual element in the concerned interactor."); return 0; } s8 SOOLCtx::GetFlags(void) // func_800625DC { return m_Flags; } u16 SOOLCtx::GetA4(void) // func_800625F0 { return m_unkA4; } void SOOLCtx::SetA4(u16 value) // func_800625F8 { m_unkA4 = value; m_unkA8 = 0; } u16 SOOLCtx::GetA6(void) // func_80062604 { return m_unkA6; } s32 SOOLCtx::GetA8(void) // func_8006260C { return 1; } s32 SOOLCtx::GetCtxId(void) // func_80062614 { return m_CtxId; } /* check if last command of a method is 0 * if true, set m_unkA6 to the method id * if the m_unkA6's value is new, set m_unkA8 to 1 */ void SOOLCtx::func_8006261C(u16 methodId) // func_8006261C { // methodId = m_unkAC if(methodId >= m_Section->hdr.numMethods) { return; } u8 lastCmdByte; if(methodId == m_Section->hdr.numMethods - 1), { lastCmdByte = m_Section->bytes[m_Section->hdr.offsMethodsEnd - 1]; } else { lastCmdByte = m_Section->bytes[m_MethodOffsets[methodId+1] - 1]; } if(lastCmdByte == 0x00) { if(methodId != m_unkA6) { m_unkA8 = 1; } m_unkA6 = methodId; } } void SOOLCtx::CheckMethod(u16 methodId) // func_80062680 { if(methodId >= m_Section->hdr.numMethods) { io_print("SOOL Engine: impossible to access a method cause of an incorrect method id."); } u8 *pos; if(methodId == (m_Section->hdr.numMethods - 1)) // last method { pos = &m_Section->bytes[m_Section->hdr.offsMethodsEnd]; } else { pos = &m_Section->bytes[m_MethodOffsets[methodId+1]]; } // check if last command of the method is 0x02 if(pos[-1] != 0x02) { io_print("SOOL Engine: impossible to access a method cause of an incorrect method id."); } } s32 SOOLCtx::Get04(void) // func_80062718 { if(this == NULL) { return NULL; } return m_unk04; } void SOOLCtx::Set04(void *ptr) // func_8006272C { m_unk04 = ptr; } void *SOOLCtx::GetC4(void) // func_80062734 { return m_unkC4; } void SOOLCtx::CheckVariable(s16 offset) // func_8006273C { if(m_Section->hdr.offsVars == 0xFFFF) { io_print("SOOL Engine: the interactor doesn't know the variable you want to read or write."); } if((offset & 0xFFFF) < m_Section->hdr.offsVars) { io_print("SOOL Engine: the interactor doesn't know the variable you want to read or write."); } if((m_Section->hdr.offsVarsEnd == 0xFFFF && offset >= m_Section->hdr.offsMethodsEnd) || offset >= m_Section->hdr.offsVarsEnd) { io_print("SOOL Engine: the interactor doesn't know the variable you want to read or write."); } } u8 *SOOLCtx::GetSectionData(u16 offset) // func_800627DC { return &m_Section->bytes[offset]; } void SOOLCtx::SetC8(UnkC8Func funcptr) // func_800627EC { m_unkC8 = funcptr; } void SOOLCtx::SetFlags(u8 flags, bool bSet) // func_800627F4 { if(bSet) // set bits { m_Flags |= flags; } else // clear bits { m_Flags &= ~flags; } } void SOOLCtx::func_80062818(void) // func_80062818 { m_unkA6 = m_Section->hdr.numPublicMethods; m_unkA8 = 1; if (m_unkA6 == 0xFFFF) { m_unkA8 = 0; m_Flags = m_Flags | (1 << 1); } } void SOOLCtx::func_80062854(void) // func_80062854 { m_unkB2 = m_Section->hdr.unk08; } void SOOLCtx::func_80062864(void) // func_80062864 { m_unkB0 = m_MethodOffsets[m_unkA4]; } void *SOOLCtx::GetAccPtr() // func_80062880 { return &m_Acc; } void *SOOLCtx::GetB2Ptr() // func_80062888 { return &m_unkB2; } void* SOOLCtx::GetSection() // func_80062890 { return m_Section; } SOOLStck *SOOLCtx::GetStack(void) // func_80062898 { return &m_Stack; } /*****************************************************************/ void SOOLStck::Reset(void) // func_800628A0 { // maybe this is the constructor? m_Count = 0; } bool SOOLStck::IsFull(void) // func_800628A8 { return (m_Count ^ NB_ELEM) < 1; } bool SOOLStck::IsEmpty(void) // func_800628B8 { return m_Count < 1; } bool SOOLStck::Push(s16 value) // func_800628C4 { if(m_Count == NB_ELEM) { io_print("SOOL Engine: Scenaric stack overflow.\n (if necessary, you can increase the defined value NB_ELEM in SOOLStck.h)"); } m_Array[m_Count++] = value; return 1; } s16 SOOLStck::Pop(void) // func_80062924 { if(m_Count <= 0) { io_print("SOOL Engine: Trying to Pop() an empty scenaric stack."); } return m_Array[--m_Count]; } void SOOLStck::Trim(int n) // func_80062980 { if(m_Count <= 0) { io_print("SOOL Engine: Trying to Pop() an empty scenaric stack."); } m_Count -= n; } s16 SOOLStck::Top(int i) // func_800629E0 { if(i <= 0 || (m_Count - i) < 0) { io_print("SOOL Engine: Invalid stack::Top(i) parameter on a scenaric stack."); } return m_Array[m_Count - i]; } void SOOLStck::Reset2(void) // func_80062A40 { m_Count = 0; } void SOOLStck::PrintValues(void) // func_80062A48 { // leftover debug function char str[unklength]; // sp10 for(int i = 0; i < m_Count; i++) { sprintf(&str, "SOOLStack[%d]=[%d]", i, m_Array[i]); func_80057138(&str); // empty stub } } //////////////////////////////////////////////////////// opcode 0x50+ handler s16 func_80057140(SOOLCtx *ctx, SOOLStck *stck, s32 *a2) { switch(stck->Top(1)) // jtbl 80092180 { case 0x00: return func_80057918(ctx, stck, a2); // 800571B0 case 0x01: return func_800579C8(ctx, stck, a2); // 800571C8 case 0x02: return func_80057A30(ctx, stck, a2); // 800571E0 case 0x03: return func_80057854(ctx, stck, a2); // 800571F8 case 0x04: return func_80057B00(ctx, stck, a2); // 80057210 case 0x05: return func_80057B68(ctx, stck, a2); // 80057228 case 0x06: return func_80057BD0(ctx, stck, a2); // 80057240 case 0x07: return func_80057D3C(ctx, stck, a2); // 800572A0 case 0x08: return func_80057C94(ctx, stck, a2); // 80057270 case 0x09: return func_80057854(ctx, stck, a2); // 80057288 case 0x0A: return func_80057DB8(ctx, stck, a2); // 800572B8 case 0x0B: return func_80058260(ctx, stck, a2); // 800572D0 case 0x0C: return func_8005891C(ctx, stck, a2); // 800572E8 case 0x0D: return func_80058A10(ctx, stck, a2); // 80057300 case 0x0E: return func_80057C38(ctx, stck, a2); // 80057258 case 0x0F: return func_80058A88(ctx, stck, a2); // 80057318 case 0x10: return func_80058B18(ctx, stck, a2); // 80057330 case 0x11: return func_80058C18(ctx, stck, a2); // 80057348 case 0x12: return func_80058C5C(ctx, stck, a2); // 80057360 case 0x13: return func_80058E74(ctx, stck, a2); // 80057378 case 0x14: return func_80058F44(ctx, stck, a2); // 80057390 case 0x15: return func_80058FC4(ctx, stck, a2); // 800573A8 case 0x16: return func_8005901C(ctx, stck, a2); // 800573C0 case 0x17: return func_800590DC(ctx, stck, a2); // 800573D8 case 0x18: return func_80059138(ctx, stck, a2); // 800573F0 case 0x19: return func_800591F8(ctx, stck, a2); // 80057408 case 0x1A: return func_800592E8(ctx, stck, a2); // 80057420 case 0x1B: return func_80057878(ctx, stck, a2); // 80057198 case 0x1C: return func_80059384(ctx, stck, a2); // 80057438 case 0x1D: return func_800593A4(ctx, stck, a2); // 80057450 case 0x1E: return func_80059404(ctx, stck, a2); // 80057468 case 0x1F: return func_80059458(ctx, stck, a2); // 80057480 case 0x20: return func_80059478(ctx, stck, a2); // 80057498 case 0x21: return func_80059560(ctx, stck, a2); // 800574B0 case 0x22: return func_800596B8(ctx, stck, a2); // 800574C8 case 0x23: return func_800596EC(ctx, stck, a2); // 800574E0 case 0x24: return func_80057898(ctx, stck, a2); // 800574F8 case 0x25: return func_800578B8(ctx, stck, a2); // 80057510 case 0x26: return func_80059770(ctx, stck, a2); // 80057528 case 0x27: return func_800598D8(ctx, stck, a2); // 80057540 case 0x28: return func_800578D8(ctx, stck, a2); // 80057558 case 0x29: return func_800578F8(ctx, stck, a2); // 80057570 case 0x2A: return func_8005990C(ctx, stck, a2); // 80057588 case 0x2B: return func_80059988(ctx, stck, a2); // 800575A0 case 0x2C: return func_800599A8(ctx, stck, a2); // 800575B8 case 0x2D: return func_80059A08(ctx, stck, a2); // 800575D0 case 0x2E: return func_80059A84(ctx, stck, a2); // 800575E8 case 0x2F: return func_80059AA4(ctx, stck, a2); // 80057600 case 0x30: return func_80058C3C(ctx, stck, a2); // 80057618 case 0x31: return func_80059AC8(ctx, stck, a2); // 80057630 case 0x32: return func_80059AEC(ctx, stck, a2); // 80057648 case 0x33: return func_80059B2C(ctx, stck, a2); // 80057660 case 0x34: return func_80059B80(ctx, stck, a2); // 80057678 case 0x35: return func_80059BF0(ctx, stck, a2); // 80057690 case 0x36: return func_80059C50(ctx, stck, a2); // 800576A8 case 0x37: return func_80059CAC(ctx, stck, a2); // 800576C0 case 0x38: return func_80059CCC(ctx, stck, a2); // 800576D8 case 0x39: return func_80059CF0(ctx, stck, a2); // 800576F0 case 0x3A: return func_80059D50(ctx, stck, a2); // 80057708 case 0x3B: return func_80059DB0(ctx, stck, a2); // 80057720 case 0x3C: return func_80059E10(ctx, stck, a2); // 80057738 case 0x3D: return func_80059E8C(ctx, stck, a2); // 80057750 case 0x3E: return func_80059EEC(ctx, stck, a2); // 80057768 case 0x3F: return func_80059F20(ctx, stck, a2); // 80057780 case 0x40: return func_80059198(ctx, stck, a2); // 80057798 case 0x41: return func_80059F80(ctx, stck, a2); // 800577B0 case 0x42: return func_8005A020(ctx, stck, a2); // 800577C8 case 0x43: return func_8005A074(ctx, stck, a2); // 800577E0 case 0x44: return func_8005A094(ctx, stck, a2); // 800577F8 case 0x45: return func_8005A0B4(ctx, stck, a2); // 80057810 case 0x46: return func_80058598(ctx, stck, a2); // 80057828 case 0x47: return func_8005A0D8(ctx, stck, a2); // 80057840 } } // 0x1B s16 func_80057878(SOOLCtx *ctx, SOOLStck *stck, s32 *a2) { return func_8003D0F4(); } // 0x24 s16 func_80057898(SOOLCtx *ctx, SOOLStck *stck, s32 *a2) { return func_8003C6FC(); } // 0x25 s16 func_800578B8(SOOLCtx *ctx, SOOLStck *stck, s32 *a2) { return func_8003C580(); } // 0x28 s16 func_800578D8(SOOLCtx *ctx, SOOLStck *stck, s32 *a2) { return func_8003C5D4(); } // 0x29 s16 func_800578F8(SOOLCtx *ctx, SOOLStck *stck, s32 *a2) { return func_8003C628(); } // 0x00 s16 func_80057918(SOOLCtx *ctx, SOOLStck *stck, s32 *a2) { // func_80082E90 = rand16 // Stack: [...] [max] [min] [code] s16 res = stck->Top(2) + func_80082E90() % ((stck->Top(3) - stck->Top(2)) + 1); if(res < 0) { res = -res; } return res; } /* 3C...4A: call_vnative 3C...4A Call a native function with n arguments provided on the stack where n = (command byte - 0x3C). The function to call is determined by a function ID at the top of the stack. Function IDs 0x00 through 0x98 are valid. Stack: [...] [argument(s)] [functionId] -> [...] 50...5E: call_native 50...5E Call a native function with n arguments provided on the stack where n = (command byte - 0x50), push the return value to the stack. The function to call is determined by a function ID at the top of the stack. Function IDs 0x00 through 0x47 are valid. Stack: [...] [argument(s)] [functionId] -> [...] [result] --------------- 00: rand(min, max) Return random number between min and max (inclusive). Stack: [...] [max] [min] [0x00] -> [...] [result] */ //////////////////////////////////////////////////////// SOOLCtx *func_8005A820(a0 /*unkc4*/, s32 ctxId) { s1 = a0 + 0x24 s32 index; for(index = 0; index < func_80056F14(s1); index++) { if(func_80056EEC(s1, index) == NULL) continue; if(func_80056EEC(s1, index)->GetCtxId() == ctxId) break; } if(index == func_80056F14(s1)) { func_80057130("SOOL Engine: impossible to access an interactor with an incorrect interactor number."); } return func_80056EEC(s1, index); } SOOLCtx *func_80056EEC(a0, index) { return a0->unk04[index]; } void func_80056F00(a0, index, a2) { a0->unk04[index] = a2; } func_80056F14(a0) { return a0->unk00; // array count } func_8005F1C(a0) { a0->unk00 = 0; a0->unk04 = NULL; } ...