diff --git a/source/CCustomOpcodeSystem.cpp b/source/CCustomOpcodeSystem.cpp index e248fc48..43e4a7bf 100644 --- a/source/CCustomOpcodeSystem.cpp +++ b/source/CCustomOpcodeSystem.cpp @@ -21,6 +21,8 @@ namespace CLEO template inline CRunningScript& operator>>(CRunningScript& thread, memory_pointer& pval); + OpcodeResult __stdcall opcode_0051(CRunningScript * thread); // GOSUB return + OpcodeResult __stdcall opcode_0A92(CRunningScript *thread); OpcodeResult __stdcall opcode_0A93(CRunningScript *thread); OpcodeResult __stdcall opcode_0A94(CRunningScript *thread); @@ -225,6 +227,8 @@ namespace CLEO CCustomOpcodeSystem::CCustomOpcodeSystem() { TRACE("Initializing CLEO core opcodes..."); + + CLEO_RegisterOpcode(0x0051, opcode_0051); CLEO_RegisterOpcode(0x0A92, opcode_0A92); CLEO_RegisterOpcode(0x0A93, opcode_0A93); CLEO_RegisterOpcode(0x0A94, opcode_0A94); @@ -850,6 +854,23 @@ namespace CLEO /* Opcode definitions */ /************************************************************************/ + OpcodeResult __stdcall CCustomOpcodeSystem::opcode_0051(CRunningScript* thread) // GOSUB return + { + if (thread->SP == 0 && thread->IsCustom() && !IsLegacyScript(thread)) // CLEO5 - allow use of GOSUB `return` to exit cleo calls too + { + return GetInstance().OpcodeSystem.CleoReturnGeneric(0x0051, thread, false); // try CLEO's function return + } + + if (thread->SP == 0) + { + SHOW_ERROR("`return` used without preceding `gosub` call in script %s\nScript suspended.", ((CCustomScript*)thread)->GetInfoStr().c_str()); + return thread->Suspend(); + } + + size_t tableIdx = 0x0051 / 100; // 100 opcodes peer handler table + return originalOpcodeHandlers[tableIdx](thread, 0x0051); // call game's original + } + //0A92=-1,create_custom_thread %1d% OpcodeResult __stdcall opcode_0A92(CRunningScript *thread) { diff --git a/source/CCustomOpcodeSystem.h b/source/CCustomOpcodeSystem.h index 5dc984b7..bdf098e2 100644 --- a/source/CCustomOpcodeSystem.h +++ b/source/CCustomOpcodeSystem.h @@ -44,6 +44,8 @@ namespace CLEO static OpcodeResult CleoReturnGeneric(WORD opcode, CRunningScript* thread, bool returnArgs = false, DWORD returnArgCount = 0, bool strictArgCount = true); + static OpcodeResult __stdcall opcode_0051(CRunningScript* thread); // GOSUB's return + private: typedef OpcodeResult(__thiscall* _OpcodeHandler)(CRunningScript* thread, WORD opcode); diff --git a/tests/cleo_tests/.Compile_All.bat b/tests/cleo_tests/.Compile_All.bat index 31766810..de4ec11c 100644 --- a/tests/cleo_tests/.Compile_All.bat +++ b/tests/cleo_tests/.Compile_All.bat @@ -13,9 +13,11 @@ for /f "delims=" %%i in ('dir /b /s *.s') do ( @REM Compile all .txt files in the current directory and subdirectories for /f "delims=" %%i in ('dir /b /s *.txt') do ( - set p=%%i - echo Compiling !p:%__CD__%=!... - %SANNY% --compile "%%i" "%%~dpni.s" --no-splash --mode sa_sbl + if not "%%~nxi" == "cleo_tester.txt" ( + set p=%%i + echo Compiling !p:%__CD__%=!... + %SANNY% --compile "%%i" "%%~dpni.s" --no-splash --mode sa_sbl + ) ) echo Done. diff --git a/tests/cleo_tests/FilesystemOperations/0A9A.txt b/tests/cleo_tests/FilesystemOperations/0A9A.txt index 9e1c91f2..0518c8de 100644 --- a/tests/cleo_tests/FilesystemOperations/0A9A.txt +++ b/tests/cleo_tests/FilesystemOperations/0A9A.txt @@ -12,8 +12,7 @@ function tests it("should fail on a non-existing file", @test1) it("should open existing file", @test2) - - return true + return function test1 if diff --git a/tests/cleo_tests/MemoryOperations/0A8C.txt b/tests/cleo_tests/MemoryOperations/0A8C.txt index 3d78f687..eab94080 100644 --- a/tests/cleo_tests/MemoryOperations/0A8C.txt +++ b/tests/cleo_tests/MemoryOperations/0A8C.txt @@ -17,15 +17,14 @@ function tests it("should write 5 bytes", @test6) it("should write 7 bytes", @test7) it("should write float", @test8) - - return true + return :before get_var_pointer 2@ {store_to} 0@ 1@ = 0xcccccccc 2@ = 0xdddddddd 3@ = 0xeeeeeeee - 0051: return + return function test1 write_memory {address} 0@ {size} 0 {value} 0x11223344 {vp} false diff --git a/tests/cleo_tests/MemoryOperations/0A8D.txt b/tests/cleo_tests/MemoryOperations/0A8D.txt index 4bca250f..1bc929b5 100644 --- a/tests/cleo_tests/MemoryOperations/0A8D.txt +++ b/tests/cleo_tests/MemoryOperations/0A8D.txt @@ -15,14 +15,14 @@ function tests it("should read 4 bytes", @test5) it("should read float", @test6) - return true + return :prepare_tests 0@ = get_label_pointer @DATA 1@ = 0xcccccccc 2@ = 0xdddddddd 3@ = 0xeeeeeeee - 0051: return // sanny does not allow single `return` command in function context + return function test1 2@ = read_memory {address} 0@ {size} 0 {vp} false diff --git a/tests/cleo_tests/MemoryOperations/0A96.txt b/tests/cleo_tests/MemoryOperations/0A96.txt index 4fb436b1..dc5c20bb 100644 --- a/tests/cleo_tests/MemoryOperations/0A96.txt +++ b/tests/cleo_tests/MemoryOperations/0A96.txt @@ -8,8 +8,7 @@ terminate_this_custom_script function tests it("should return valid pointer", @test1) - - return true + return function test1 int handle = get_player_char 0 diff --git a/tests/cleo_tests/MemoryOperations/0A97.txt b/tests/cleo_tests/MemoryOperations/0A97.txt index 034ad422..1717e8d6 100644 --- a/tests/cleo_tests/MemoryOperations/0A97.txt +++ b/tests/cleo_tests/MemoryOperations/0A97.txt @@ -8,7 +8,7 @@ terminate_this_custom_script function tests it("should return a valid pointer", @test1) - return true + return function test1 request_model 400 diff --git a/tests/cleo_tests/MemoryOperations/0A98.txt b/tests/cleo_tests/MemoryOperations/0A98.txt index 3b6bf28f..60c2c264 100644 --- a/tests/cleo_tests/MemoryOperations/0A98.txt +++ b/tests/cleo_tests/MemoryOperations/0A98.txt @@ -8,7 +8,7 @@ terminate_this_custom_script function tests it("should return a valid pointer", @test1) - return true + return function test1 request_model 333 // golf club diff --git a/tests/cleo_tests/MemoryOperations/0AA4.txt b/tests/cleo_tests/MemoryOperations/0AA4.txt index 2192b551..ac496cd2 100644 --- a/tests/cleo_tests/MemoryOperations/0AA4.txt +++ b/tests/cleo_tests/MemoryOperations/0AA4.txt @@ -8,7 +8,7 @@ terminate_this_custom_script function tests it("should return address of Sleep function from kernel32.dll", @test1) - return true + return function test1 int load_library_addr = read_memory 0x858070 4 false diff --git a/tests/cleo_tests/MemoryOperations/0AC6.txt b/tests/cleo_tests/MemoryOperations/0AC6.txt index 3ae125fe..8df82524 100644 --- a/tests/cleo_tests/MemoryOperations/0AC6.txt +++ b/tests/cleo_tests/MemoryOperations/0AC6.txt @@ -8,7 +8,7 @@ terminate_this_custom_script function tests it("should return valid pointer", @test1) - return true + return function test1 int ptr = 0 diff --git a/tests/cleo_tests/MemoryOperations/0AC7.txt b/tests/cleo_tests/MemoryOperations/0AC7.txt index f202c8d6..1974662f 100644 --- a/tests/cleo_tests/MemoryOperations/0AC7.txt +++ b/tests/cleo_tests/MemoryOperations/0AC7.txt @@ -8,7 +8,7 @@ terminate_this_custom_script function tests it("should return valid pointer", @test1) - return true + return function test1 int val1 = 0x11223344 diff --git a/tests/cleo_tests/MemoryOperations/0AC8.txt b/tests/cleo_tests/MemoryOperations/0AC8.txt index 03d92f0a..057244f4 100644 --- a/tests/cleo_tests/MemoryOperations/0AC8.txt +++ b/tests/cleo_tests/MemoryOperations/0AC8.txt @@ -12,8 +12,7 @@ function tests it("should return valid pointer", @test1) it("should point to zero-filled mem in CLEO5", @test2) - - return true + return function test1 // 0@ is set in before_each callback @@ -30,11 +29,11 @@ function tests :allocate 0@ = 0x11223344 0@ = allocate_memory {size} 4 - 0051: return + return :free free_memory {address} 0@ - 0051: return + return end \ No newline at end of file diff --git a/tests/cleo_tests/MemoryOperations/0AC9.txt b/tests/cleo_tests/MemoryOperations/0AC9.txt index 120eb3f1..11c1eb33 100644 --- a/tests/cleo_tests/MemoryOperations/0AC9.txt +++ b/tests/cleo_tests/MemoryOperations/0AC9.txt @@ -8,7 +8,7 @@ terminate_this_custom_script function tests it("should free allocated memory", @test1) - return true + return function test1 int ptr = 0x11223344 diff --git a/tests/cleo_tests/MemoryOperations/0AE9.txt b/tests/cleo_tests/MemoryOperations/0AE9.txt index 6aa9ece7..6e76df78 100644 --- a/tests/cleo_tests/MemoryOperations/0AE9.txt +++ b/tests/cleo_tests/MemoryOperations/0AE9.txt @@ -8,7 +8,7 @@ terminate_this_custom_script function tests it("should pop float from stack", @test1) - return true + return function test1 diff --git a/tests/cleo_tests/MemoryOperations/0AEA.txt b/tests/cleo_tests/MemoryOperations/0AEA.txt index fc1b5de2..555bb926 100644 --- a/tests/cleo_tests/MemoryOperations/0AEA.txt +++ b/tests/cleo_tests/MemoryOperations/0AEA.txt @@ -7,7 +7,7 @@ terminate_this_custom_script function tests it("should return ped handle for pointer", @test1) - return true + return function test1 int handle = get_player_char 0 diff --git a/tests/cleo_tests/MemoryOperations/0AEB.txt b/tests/cleo_tests/MemoryOperations/0AEB.txt index 9647cada..de66d9bd 100644 --- a/tests/cleo_tests/MemoryOperations/0AEB.txt +++ b/tests/cleo_tests/MemoryOperations/0AEB.txt @@ -7,7 +7,7 @@ terminate_this_custom_script function tests it("should return vehicle handle for pointer", @test1) - return true + return function test1 request_model 400 diff --git a/tests/cleo_tests/MemoryOperations/0AEC.txt b/tests/cleo_tests/MemoryOperations/0AEC.txt index 57333051..e97d7521 100644 --- a/tests/cleo_tests/MemoryOperations/0AEC.txt +++ b/tests/cleo_tests/MemoryOperations/0AEC.txt @@ -7,7 +7,7 @@ terminate_this_custom_script function tests it("should return vehicle handle for pointer", @test1) - return true + return function test1 request_model 333 // golf club diff --git a/tests/cleo_tests/cleo_tester.txt b/tests/cleo_tests/cleo_tester.txt index 29be0a8e..27a8fd9b 100644 --- a/tests/cleo_tests/cleo_tester.txt +++ b/tests/cleo_tests/cleo_tester.txt @@ -58,7 +58,7 @@ function it(spec_name: integer, callback: int) index++ _cleo_tester_write_var(VAR_TEST_INDEX, index) - return true + return function run_spec // this function should use 0 local variables