You are not logged in.
Well a reinstall would be a good idea, then.
Assuming you still have the compact .exe installed, post the new crash report.
Mkay.. I realise now it's invisible when not logged in 
@John_Bryant
And did you read the topic of answered questions about this?
Don't use a downgrader, use the compact .exe.
Password is as it says on the post..
Read this topic. Read step 2. Same rules apply to CLEO 4.
Yes, CLEO three-quarters..
[large]Description[/large]
This mod adds extra optional settings to the stream.ini file, which already contains several settings for GTASA.
There are currently 11 extra settings. I'm working on finding some more to add.
[large]Features[/large]
* Frame Delay (increases FPS)
* Frame Limit
* Black Roads Fix
* License Plate Filtering
* Stencil Shadow Opacity
* Disable Motion Blur
* Disable Reflections (alt+tab bugfix)
* Disable Sound
* Disable Collision Particles
* Disable Flashes
* Disable Heat Haze
This mod works with both CLEO 4 and CLEO 3.
Visit the CLEO Website for the latest version of CLEO.
I'm working on adding new tweaks and bugfix options, so if you have any specific requests (and know how it can be done), feel free to ask here.
Thanks for that.
After finding out IDA has a "pseudocode" feature I noticed it uses strtok first. By the looks of the C++ Reference, this is something else I need (since it can automatically separate strings by spaces/tabs). I've often thought sscanf was the only way of doing something like this.
for ( i = CFileMgr_getConfigLine(v3); i; i = CFileMgr_getConfigLine(v2) )
{
if ( *(_BYTE *)i != '#' )
{
if ( *(_BYTE *)i )
{
v5 = strtok((char *)i, " ,\t");
v4 = strtok(0, " ,\t");
if ( stricmp(v5, "memory") || v1 )
{
if ( stricmp(v5, "devkit_memory") )
{
[...]
}
else
{
dword_8A5A80 = atoi(v4) << 10;
v1 = 1;
}
}
else
{
dword_8A5A80 = atoi(v4) << 10;
}
}
}
}It's much easier to keep track of the variables this way.
Working Code
{$CLEO}
wait 2
0A9A: 0@ = openfile "stream.ini" mode 0x72
else_jump @End
0AC6: 3@ = label @aFrameDelay offset
0AC7: 4@ = var 5@ offset
:ScanFile
while true
wait 0
0AA7: call_function 0x536F80 num_params 1 pop 1 0@ 1@
8039: not 1@ == 0
jf break
0A8D: 2@ = read_memory 1@ size 1 virtual_protect 0
8039: not 2@ == 0x23
jf break
0AA7: call_function 0x82244B num_params 2 pop 2 0x86A8C8 1@ 1@
0AA7: call_function 0x82244B num_params 2 pop 2 0x86A8C8 0 4@
0AA7: call_function 0x8229B6 num_params 2 pop 2 1@ 3@ 2@
0039: 2@ == 0
else_jump @ScanFile
0AA7: call_function 0x82258E num_params 1 pop 1 4@ 2@
0A8C: write_memory 0x53E94C size 1 value 2@ virtual_protect 1
break
end
0A9B: closefile 0@
:End
0A93: end_custom_thread
:aFrameDelay
hex
"framedelay" 00
endNow I'll work on adding all sorts of settings to this file. Probably to do with optimisation and graphics in order to keep the stream.ini's original purpose. Since I don't know of too many memory locations of this stuff yet, I better start digging... Thanks for the help.
I'm working on a script to add extra settings to the stream.ini file, which will support CLEO 3 and CLEO 4 (at the moment I'm using CLEO 4 for ease and debugging).
Pretty well-optimized script as it uses mostly functions. I'm not sure all of it works yet, but the first problem I've noticed is calling 0x8229B6 (strcmp)
{$CLEO}
wait 2
0A9A: 0@ = openfile "stream.ini" mode 0x72 // use CLEO 3 open mode
else_jump @End
0AC6: 2@ = label @aFrameDelay offset
:ScanFile
while true
wait 0
0AA7: call_function 0x536F80 num_params 1 pop 1 0@ 1@ // write the next line of stream.ini to 0xB71848
8039: not 1@ == 0 // above function returns "0xB71848" if it was successful
jf break
0AA7: call_function 0x8229B6 num_params 2 pop 2 0xB71848 2@ 1@ // thread memory used for CLEO 3 support, "framedelay" instead of 2@ produces same results
0ACE: show_formatted_text_box "%d" 1@
wait 2000
0039: 1@ == 2 // I'll set back to 1 later, this is for debugging
else_jump @ScanFile
0AA7: call_function 0x82258E num_params 1 pop 1 0xB71852 1@
0A8C: write_memory 0x53E94C size 1 value 1@ virtual_protect 1
break
end
0A9B: closefile 0@
:End
0A93: end_custom_thread
:aFrameDelay
hex
"framedelay" 00
endstream.ini
framedelay 5 memory 600000 devkit_memory 600000 vehicles 12 pe_lightchangerate 0.0008 pe_lightingbasecap 0.35 pe_lightingbasemult 0.4 pe_leftx 16 pe_topy 16 pe_rightx 16 pe_bottomy 16 pe_bRadiosity 1 dontbuildpaths
The problem is, the function returns -1 on the line which contains "framedelay". However, on the lines which contain "dontbuildpaths" and "devkit_memory" return 1. I see no reason why this is happening.
RewriteRule ^mypage/([A-Za-z]+)/([0-9]+).php$ page.php?act=$1&page=$2 [L,QSA]
Try taking a look at these, also: http://httpd.apache.org/docs/2.0/mod/mo … writeflags
Very interesting find. Is there a same effect without opcode 0ACE?
Yes, although I've just discovered that a large amount of other SA opcodes seem to crash, too. Some basic math opcodes work fine, yet others crash the game as part of trying to get the value from the variable.
Seems that SA changes its method of getting passed params for certain opcodes but I'm not sure why or what's wrong with the alternate method. It's part of "setNumberParams". Am I right in believing "setNumberParams" allows the SCM Parser to skip remaining parameters?
Global variables work fine as long as the array index is positive, which is why I decided to use them instead.
Maybe the array index is unsigned with various opcodes?
And I've finally got a simple, working example of that array crash:
Crashes
{$CLEO}
0006: 0@ = -1
0A8E: 2@(0@,1i) = 2 + 3
0ACE: show_formatted_text_box "%d" 1@
0A93: end_custom_threadSurvives
{$CLEO}
0006: 0@ = -1
0006: 2@(0@,1i) = 5
0ACE: show_formatted_text_box "%d" 1@
0A93: end_custom_threadCrash is at about 0x4644C7, as ever..
CLEO 4's installation should include the required .asi loader...
Best bet is to try installing CLEO 4 on a clean installation of SA.
Try installing CLEO 4 without the .asi loader installed.
Ah, in that case, the problem is with 0ADF and pointers on the input param:
{$CLEO}
0000:
wait 2000
0AC6: 0@ = label @TEMP offset
0AD3: 0@ = format "TEMP1"
0ADF: add_gxt 0@ text "Test string"
0ADE: 1@ = text_by_GXT_entry 0@
0ACE: show_formatted_text_box "%s %X" 1@ 1@ // shows " 1755BB0"
wait 5000
03E5: show_text_box "TEMP1" // does not display
0A93: end_custom_thread
:TEMP
hex
00 00 00 00 00 00 00
endBut why does it return 0x1755BB0 (cleo.asi+25BB0) when the GXT doesn't exist?
Hmm.. not sure if this was intentional, but I find the experience of using 0ADE very suprising.
0ADF: add_dynamic_GXT_entry "_TEST" text "Test string" 0AC8: 0@ = allocate_memory_size 260 0085: 1@ = 0@ 0ADE: 0@ = text_by_gxt_entry "_TEST" 0ACE: show_formatted_text_box "Before: %X~n~After: %X" 1@ 0@
The example given for 0ADE shows a normal variable being used, which I assumed meant that CLEO 4 would write the GXT text to the pointer. Instead, a pointer to the GXT entry address is given. This is okay if it's supposed to be this way, but the example is a bit misleading. I'll update the Opcode Database if this is the way the opcode works.
However, with this code:
0ADF: add_dynamic_GXT_entry "_TEST" text "Test string" 0AC8: 0@ = allocate_memory_size 260 0085: 1@ = 0@ 0ADE: 0@ = text_by_gxt_entry "EU38PLM" // random, inexistant GXT Entry 0ACE: show_formatted_text_box "Before: %X~n~After: %X" 1@ 0@
A memory address is still returned, which points to part of the loaded CLEO.asi itself. Here's the 32 bytes at the address returned:
00 00 00 00 45 72 72 6F 72 20 6C 6F 61 64 69 6E 67 20 70 6C 75 67 69 6E 20 25 73 00 72 62 00 00 ����Error loading plugin %s�rb��
I expected 0 or nothing to be returned, so it sent me down a lot of wrong paths. It'd be nice for some light to be shed on this opcode.
EDIT
And 0ADE doesn't seem to support pointers on the input parameter, which has left me completely stuck.
Opened CLEO 4 in IDA.
Apparently the problem is 0A8D.
0A9A: 32@ = openfile "cleo\missile.dat" mode 0x6272 // IF and SET
for 33@ = 0 to 29
0AA7: call_function 0x536F80 num_params 1 pop 1 32@ 11@
// reads the first line of the memory (from the file) to check it's not a line commented with ;
{0A8D: 12@ = read_memory 11@ size 1 virtual_protect 0
if
0039: 12@ == 0
then
break
end
if
0039: 12@ == 0x3B
then
000E: 33@ -= 1
continue
end
0AA5: call 3@(3@,1i) num_params 3 pop 3 11@ 13@ 14@
000A: 14@ += 0xA0}
end
0A9B: closefile 32@Works without crashing.
But this makes the mod completely inactive.
Yes, I know how the sub works, but what is the logic behind this...
A1D5865300 // mov eax, [0x005386D5] // Offset 0x008220ED 05D9865300 // add eax, 0x005386D9 // FFD0 // call eax 81C4A8000000 // add esp, 0x000000A8h C3 // ret
From Ryosukes source. 0x5386D5 contains an offset from one function to the sscanf function, then the add operation increases that value to get the exact address.
Which is why I assumed the exact value could not be copied.
Removed the waits and it crashes before the game even starts.
Replaced timers, added wait 3000 before the loop and wait 1000 in the loop. Game immediately crashes after 3 seconds.
And 3D Sound problems could be down to the dxdiag Sound Hardware settings?
0A9A: 32@ = openfile "cleo\missile.dat" mode 0x6272 // IF and SET
for 33@ = 0 to 29
0AA7: call_function 0x536F80 num_params 1 pop 1 32@ 11@
0A8D: 12@ = read_memory 11@ size 1 virtual_protect 0
if
0039: 12@ == 0
then
break
end
if
0039: 12@ == 0x3B
then
000E: 33@ -= 1
continue
end
0AA5: call 3@(3@,1i) num_params 3 pop 3 11@ 13@ 14@
000A: 14@ += 0xA0
wait 5000 // for debugging.
end
0A9B: closefile 32@In Ryosukes script first iteration works perfectly (returns to memory correctly) but crashes on 2nd iteration (cleo.asi+154C).
However, if there's a wait before the for loop (even with the wait 5000), it crashes on the first iteration (ntdll.dll+1B21A).
Thanks. I actually found a caller for "sscanf" in Ryosukes Missile mod.
He uses mov, then add to some up to halves of the address... I assumed because mov used a signed integer, making 0x8220AD go in the wrong direction?
Yes. I think the problem with calling these string functions directly might be down to how the data is passed.
Perhaps ASM would work if the bytes were passed one-by-one... But I still have troubles when it comes to handling registers.
while 0AB1: call_scm_func @GetConfigLine 1 0@ 1@
0AC6: 2@ = label @TempMemory offset
0AD3: 2@ = format "%d %s %s"
0AC6: 3@ = label @FUNC_sscanf offset
0AA7: call_function 3@ num_params 2 pop 2 1@ 2@ 4@ 5@ 6@
0ACE: show_formatted_text_box "%d %s %s" 4@ 5@ 6@
end
:FUNC_sscanf
8B4C2404 // mov ecx, [esp+0x04]
51 // push ecx
8B4C2408 // mov ecx, [esp+0x08] ?
51 // push ecx
8B4C240C // mov ecx, [esp+0x0C] ?
51 // push ecx
9AAD208200 // call 0x8220AD - 9A is the right one for a direct address?
// get return?
C3 // retI doubt this will even call right, since this is probably similar to what 0AA5 does... I think the bytes at the first address need to be read, and maybe the second.
Still, I don't understand the functions not working or why the opcode doesn't support aDMA.
I realise CLEO 4 file handles are different from CLEO 3 ones, but I've also figured out this is the causes compatibility issues with some CLEO 3 scripts, since this eliminates the ability to call San Andreas functions passing the file handle.
Ryosukes Missile script can be fixed by following these simple steps:
Find
0A9A: 32@ = openfile "cleo\missile.dat" mode 0x6272 // IF and SET
for 33@ = 0 to 29
0AA7: call_function 0x536F80 num_params 1 pop 1 32@ 11@
0A8D: 12@ = read_memory 11@ size 1 virtual_protect 0
if
0039: 12@ == 0
then
break
end
if
0039: 12@ == 0x3B
then
000E: 33@ -= 1
continue
end
0AA5: call 3@(3@,1i) num_params 3 pop 3 11@ 13@ 14@
000A: 14@ += 0xA0
end
0A9B: closefile 32@Replace With
0A9A: 32@ = openfile "cleo\missile.dat" mode "rt" // IF and SET
for 33@ = 0 to 29
//0AA7: call_function 0x536F80 num_params 1 pop 1 32@ 11@
0AB1: call_scm_func @GetConfigLine 1 32@ 11@
0A8D: 12@ = read_memory 11@ size 1 virtual_protect 0
if
0039: 12@ == 0
then
break
end
if
0039: 12@ == 0x3B
then
000E: 33@ -= 1
continue
end
0AA5: call 3@(3@,1i) num_params 3 pop 3 11@ 13@ 14@
000A: 14@ += 0xA0
end
0A9B: closefile 32@Find
:SSCANF_FORMAT hex "%d" 20 "%d" 20 "%d" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%d" 20 "%f" 20 "%f" 20 "%f" 20 "%d" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%d" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%d" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%f" 20 "%d" 20 "%f" 20 "%d" 20 "%x" 00 end
Add Above
:GetConfigLine
0A8C: write_memory 0xB71848 size 0x200 value 0 virtual_protect 0
while 0AD7: read_string_from_file 0@ to 0xB71848 size 0x200
0A8D: 2@ = read_memory 0xB71848 size 1 virtual_protect 0
if and
8039: not 2@ == 0xA
8039: not 2@ == 0xD
8039: not 2@ == 0x20
8039: not 2@ == 0x23
8039: not 2@ == 0x3B
then
0AA7: call_function 0x69DB50 num_params 1 pop 1 0xB71848 2@
000A: 2@ += 1
0A8E: 3@ = 0xB71848 + 2@
0A8C: write_memory 3@ size 1 value 0 virtual_protect 0
end
end
0AB2: ret 1 0xB71848Hopefully it will help people having troubles with the script. I know a few people who want this mod to work on CLEO 4.
But perhaps in any future update, CLEO could be made to check whether the script is using something like "mode 0x6272" and return the file handle using the old CLEO 3 method? It would good to have file operations compatible with SA's functions.
This seems to be an impossible task... I've tried just about everything to try and fix this, but nothing is working.
This is the code I have now, after long battles with previous code.
if
0A9A: TEMP_1 = openfile "file.dat" mode "r"
then
while 0AB1: call_scm_func @GetConfigLine 1 0@ TEMP_2
0AC6: TEMP_3 = label @TempMemory offset
0AD3: TEMP_3 = format "BF"
if
0AB1: call_scm_func @strpos 2 TEMP_3 TEMP_2 TEMP_4
then
0ACE: show_formatted_text_box "True! %s %d" TEMP_2 TEMP_4
else
0ACE: show_formatted_text_box "False! %s %d" TEMP_2 TEMP_4
end
wait 1000
end
endI'm trying to get data from a file similar to the GTA .dat files. :GetConfigLine returns the first valid .dat line it finds (non-commented and not blank). The line is stored in a part of SA's memory which was made for storing .dat lines.
Now I have to get each value of a line like this:
10,BFOST,Street
CLEO 4's opcode doesn't fit here because the scan_file/scan_string opcodes can't return to pointers. I've tried using aDMA, but that didn't work either, I get a "cleo.asi" error report. Also, with it a format like "%s,%s" doesn't work. It returns all the way to the newline.
SA's function seesm to allow "%s%s" to get two strings, which could be split by a comma and any amount of whitespaces.
I tried to use the sscanf function in SA but no matter how I use it there is a crash (in function "strcpy" or "strlen" apparently). I've even got a d3d9.dll error with this.
Finally I decided to make a sscanf function from scratch, which requires the use of other functions. I added "strpos" as from PHP. It finds the first occurance of a char sequence within a string and returns how far into the string it is.
Simple task.. except that the "strcmp" (string compare) function in SA is failing me now... I've tried all of them, I think.
:strpos
0AA7: call_function FUNC_strlen num_params 1 pop 1 0@ 3@
0AA7: call_function FUNC_strlen num_params 1 pop 1 1@ 4@
if and
8039: not 3@ == 0
8039: not 4@ == 0
then
000A: 3@ += 1
000A: 4@ += 1
0AC8: 7@ = allocate_memory_size 3@
for 5@ = 0 to 4@
0A8E: 6@ = 3@ + 5@
if 001D: 6@ > 4@
then break
end
0A8E: 8@ = 4@ + 1@
0AD3: 7@ = format "%s" 8@
0AA7: FUNC_strcmp 2 2 str1 7@ str2 0@ store_to 9@
wait 5000
if
0039: 9@ == 0
//0AD4: 9@ = scan_string "%*s" format 7@ 0@ // CLEO 4 probably doesn't support %* anyway.
//0AD4: 9@ = scan_string 7@ format 0@ // hmm.. doesn't work without specifiers?
then
0ACE: show_formatted_text_box "True! %d" 5@
0062: 5@ -= 2@
0AC9: free_allocated_memory 7@
0485: return_true
0AB2: ret 1 5@
end
end
0AC9: free_allocated_memory 7@
end
059A: return_false
0AB2: ret 1 0Calling the stcmp function gives me a crash. I've also tested with strings and it still doesn't work.
File: ntdll.dll Offset: 10E6
Maybe I need to pass an offset instead of an address? Offset from what?
So for some reason, any string related operation I try with SA's functions fail, except for the gtaStrlen one.
It'd be nice to be able to do it without creating my own C++ level function in SCM, but if that's not possible I guess it's the only option I have.
Ah, well I saw the post before the edit, so I fetched the alphas of the crosshair textures.
These allow you to have more control over what is visible, anyway... All dwords.
// Crosshair Textures (all weapons except camera and sniper rifle) 0x58E2EC // top right 0x58E3BF // top left? 0x58E420 // bottom right? 0x58E461 // bottom left? 0x58E287 // middle dot // Sniper Rifle and Camera 0x58E8F6 // top right 0x58E96C // top left? 0x58E9DC // bottom right? 0x58EA4B // bottom left?
0x726D2B - call createBulletTrail
0AC6: 0@ = label @CreateLaserParticle offset
0A8C: write_memory 0x726D2C size 4 value 0@ virtual_protect 1
:CreateLaserParticle
hex
{
06BC: create_M4_shoot_from 0@ 1@ 2@ target 3@ 4@ 5@ energy 6@
}
end:DisableCrosshair 0A8C: write_memory 0x58FBBF size 5 value 0x90 virtual_protect 1
I was goning to do this, but I don't have the required ASM skills. Planned to grab the parameters passed to :CreateLaserParticle and create either another thread (passing the params) or a corona, if possible.