```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;
}
...