Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New opcode cleo return with #39

Merged
merged 10 commits into from
Nov 13, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
- **0DD5 ([get_game_platform](https://library.sannybuilder.com/#/sa/CLEO/0DD5))**
- **2000 ([resolve_filepath](https://library.sannybuilder.com/#/sa/CLEO/2000))**
- **2001 ([get_script_filename](https://library.sannybuilder.com/#/sa/CLEO/2001))**
- **2002 ([cleo_return_with](https://library.sannybuilder.com/#/sa/CLEO/2002))**
- **2003 ([cleo_return_false](https://library.sannybuilder.com/#/sa/CLEO/2003))**
- 'argument count' parameter of **0AB1 (cleo_call)** is now optional. `cleo_call @LABEL args 0` can be written as `cleo_call @LABEL`
- 'argument count' parameter of **0AB2 (cleo_return)** is now optional. `cleo_return 0` can be written as `cleo_return`
- opcodes **0AAB**, **0AE4**, **0AE5**, **0AE6**, **0AE7** and **0AE8** moved to the [FileSystemOperations](https://github.com/cleolibrary/CLEO5/tree/master/cleo_plugins/FileSystemOperations) plugin
Expand Down
47 changes: 47 additions & 0 deletions source/CCustomOpcodeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ namespace CLEO
OpcodeResult __stdcall opcode_0DD5(CRunningScript* thread); // get_platform
OpcodeResult __stdcall opcode_2000(CRunningScript* thread); // resolve_filepath
OpcodeResult __stdcall opcode_2001(CRunningScript* thread); // get_script_filename
OpcodeResult __stdcall opcode_2002(CRunningScript* thread); // cleo_return_with
OpcodeResult __stdcall opcode_2003(CRunningScript* thread); // cleo_return_false

typedef void(*FuncScriptDeleteDelegateT) (CRunningScript *script);
struct ScriptDeleteDelegate {
Expand Down Expand Up @@ -400,6 +402,8 @@ namespace CLEO
CLEO_RegisterOpcode(0x0DD5, opcode_0DD5); // get_platform
CLEO_RegisterOpcode(0x2000, opcode_2000); // resolve_filepath
CLEO_RegisterOpcode(0x2001, opcode_2001); // get_script_filename
CLEO_RegisterOpcode(0x2002, opcode_2002); // cleo_return_with
CLEO_RegisterOpcode(0x2002, opcode_2003); // cleo_return_false
}

void CCustomOpcodeSystem::Inject(CCodeInjector& inj)
Expand Down Expand Up @@ -3220,6 +3224,49 @@ namespace CLEO
SetScriptCondResult(thread, true);
return OR_CONTINUE;
}

//2002=-1, cleo_return_with ...
OpcodeResult __stdcall opcode_2002(CRunningScript* thread)
{
auto cs = reinterpret_cast<CCustomScript*>(thread);
DWORD returnParamCount = GetVarArgCount(cs);

if (returnParamCount) GetScriptParams(cs, returnParamCount);

ScmFunction* scmFunc = ScmFunction::Store[cs->GetScmFunction()];
scmFunc->Return(cs); // jump back to cleo_call, right after last input param. Return slot var args starts here
if (scmFunc->moduleExportRef != nullptr) GetInstance().ModuleSystem.ReleaseModuleRef((char*)scmFunc->moduleExportRef); // exiting export - release module
delete scmFunc;

DWORD returnSlotCount = GetVarArgCount(cs);
if(returnParamCount != returnSlotCount) // new CLEO5 opcode, strict error checks
{
SHOW_ERROR("Opcode [2002] returned %d params, while function caller expected %d in script %s\nScript suspended.", returnParamCount, returnSlotCount, cs->GetInfoStr().c_str());
return CCustomOpcodeSystem::ErrorSuspendScript(cs);
}

if (returnSlotCount) SetScriptParams(cs, returnSlotCount);
cs->IncPtr(); // skip var args

SetScriptCondResult(cs, true);
return OR_CONTINUE;
}

//2003=0, cleo_return_false
OpcodeResult __stdcall opcode_2003(CRunningScript* thread)
{
auto cs = reinterpret_cast<CCustomScript*>(thread);

ScmFunction* scmFunc = ScmFunction::Store[cs->GetScmFunction()];
scmFunc->Return(cs); // jump back to cleo_call, right after last input param. Return slot var args starts here
if (scmFunc->moduleExportRef != nullptr) GetInstance().ModuleSystem.ReleaseModuleRef((char*)scmFunc->moduleExportRef); // exiting export - release module
delete scmFunc;

SkipUnusedVarArgs(thread); // just exit without change of return params

SetScriptCondResult(cs, false);
return OR_CONTINUE;
}
}


Expand Down