Bad.boy! Posted April 28, 2012 Share Posted April 28, 2012 Does anyone know where I can find info about the structure of a cleo file. I want to know what globals and locals compiles in. And what jumps, gosubs, thread names etc. compile in to. Is there also some sort of documentation of opcode's hex values. I need to know this, for making a high end compiler that doesn't make double jumps and compiles better. Link to comment Share on other sites More sharing options...
Silent Posted April 28, 2012 Share Posted April 28, 2012 Sanny compiles perfectly if your script is good enough. Link to comment Share on other sites More sharing options...
Bad.boy! Posted April 28, 2012 Author Share Posted April 28, 2012 Can't find the file that had double jumps, anyway I still want to make my own compiler. So can someone share their knowledge about this. And more specific: If I compile "0000: NOP" where does it compile into (hex values)? Link to comment Share on other sites More sharing options...
fastman92 Posted April 28, 2012 Share Posted April 28, 2012 (edited) Some things are covered here: http://www.mediafire.com/?xrq6v1z1l5zwr8b What are labels: there are no registered labels in structure of SCM file. They are just negative INT offsets relative to beginning of script. A jump to offset 800 would be jump to -800 as INT value, usually 4-byte number, but not limited to. Bad.boy!, you need to have a strong knowledge of C++ or any other programming language, in other case you're not gonna success. Edited April 28, 2012 by fastman92 Link to comment Share on other sites More sharing options...
Bad.boy! Posted April 28, 2012 Author Share Posted April 28, 2012 (edited) Some things are covered here:http://www.mediafire.com/?xrq6v1z1l5zwr8b What are labels: there are no registered labels in structure of SCM file. They are just negative INT offsets relative to beginning of script. A jump to offset 800 would be jump to -800 as INT value, usually 4-byte number, but not limited to. Bad.boy!, you need to have a strong knowledge of C++ or any other programming language, in other case you're not gonna success. I know I probably won't succeed in making a full compiler. But I'll start small, I try to add ±10 opcodes and a simple struct. Then the most difficult part converting text into something that GTA can read. About the labels, how does Sanny Builder know what number of a label should be. It has to be a higher number each time or does it need to have more then just a higher number. What are the requirements for a label? EDIT: I've been quiet stupid about the opcodes, they are hex already (0A93 = 93 0A). Edited April 28, 2012 by Bad.boy! Link to comment Share on other sites More sharing options...
fastman92 Posted April 28, 2012 Share Posted April 28, 2012 (edited) Sanny Builder creates a binary code at first. It uses array to store references to labels. Tha means, during compilation whole binary code is created at first, but labels are missing. It saves in array, for example that there is reference to @mylabel on 55. It has array to store label position of compiled file too. For example :mylabel is compiled on 30 It will put on 55 position, offset -30 (negative numbers are used). Opcode numbers are WORD values (16 bits = 2 bytes) whereas oldest bit states whether conditional result from opcode should be negated and last 15 bits is number of opcode. There are possibily 0x7FFF + 1 opcodes equal to 8192. Edited April 28, 2012 by fastman92 Link to comment Share on other sites More sharing options...
Bad.boy! Posted April 28, 2012 Author Share Posted April 28, 2012 (edited) I have a question about the check if $PLAYER_CHAR ($2) is defined. 56 02 + Player (02 08 00?) Why is $2 "02 08 00". 08 = $2 I guess but why? Nevermind I found out that I have to divide the variable by 4. 56 02 + 02 (GLOBAL) + X (VARIABLE) For example $2 = 2*2 = 04 00 and $4 = 4*4 = 10 00 56 02 + 03 (LOCAL) + X (VARIABLE) For example [email protected] = 02 00 and [email protected] = 06 00 Edited April 28, 2012 by Bad.boy! Link to comment Share on other sites More sharing options...
fastman92 Posted April 28, 2012 Share Posted April 28, 2012 (edited) http://www.mediafire.com/?xrq6v1z1l5zwr8b Read it about SCM opcode parameter types. Global variables use number of byte, for example $2 = 08 00, $3 = 0C 00. 0xC in hex is equal to 12. Local variables use a variable number, for example [email protected] = 04 00, [email protected] = 07 00, [email protected] = 0E 10 270 = 0x10E Edited April 28, 2012 by fastman92 Link to comment Share on other sites More sharing options...
Wesser Posted April 28, 2012 Share Posted April 28, 2012 What are labels: there are no registered labels in structure of SCM file. They are just negative INT offsets relative to beginning of script.A jump to offset 800 would be jump to -800 as INT value, usually 4-byte number, but not limited to. That's not exactly. Jump offsets are relative to the each thread base address and those of the MAIN thread aren't negative at all. Why don't you link some articles of the forum wiki (such as this and this)? They provides a lot more information. However, I stopped working on my own HL decompiler because of VB.NET inefficiency and now I'm moving the code to C++. Be patient. 012 345 678 9A BCD EFG HIJK LMN OPQR STUV WX YZ Link to comment Share on other sites More sharing options...
Bad.boy! Posted April 28, 2012 Author Share Posted April 28, 2012 Thanks wesser. I'm making my compiler in c# and I don't make a decompiler because that will take to much time. About the jumps I came up with this: 0002 GOTO 02 00 + 01 + Place in file? + FF FF FF004D JUMP_IF_FALSE 4D 00 + 01 + Place in file? + FF FF FF Is the place in file the 200th binary number for example? I can make some progress if I know that, because now I can't go further than this (which is atleast something): Source:SCRIPT_NAME "TEST"Decompiled:{$CLEO .cs}//-------------MAIN---------------thread "TEST" I'm trying to make this: SCRIPT_NAME "TEST":TESTWHILE NOT IS_PLAYER_PLAYING playerWAIT 0ENDWHILEEND_CUSTOM_THREAD Link to comment Share on other sites More sharing options...
fastman92 Posted April 28, 2012 Share Posted April 28, 2012 Place in file? + FF FF FF What? Read docx 01 4 Static number: (Long) Integer – 32 bits It's negative integer value that takes 4 bytes. Do you know that numbers may be longer than one byte? Link to comment Share on other sites More sharing options...
Link2012 Posted April 28, 2012 Share Posted April 28, 2012 0002 GOTO 02 00 + 01 + Place in file? + FF FF FF004D JUMP_IF_FALSE 4D 00 + 01 + Place in file? + FF FF FF Those FF's is part of the place in file... But for example, a CLEO Script has local offsets, so the offset is negative, so for example, the offset 2 should be compiled as -2, Main.scm Missions and Externals too. -1 in hex is 0xFFFFFFFF -2 is 0xFFFFFFFE and so on. So 0000: // This prevent a jump 0 adding 2 bytes at the header, because 0 has no negative value, so if you do a jump 0 you're jumping to main.scm:Labeljump @Label Compiled is 00 00{Here is offset 2}02 00 // Opcode 000201 // Datatype Int32FFFFFE // -2, jump to offset 2 relative to this thread base. Link to comment Share on other sites More sharing options...
Wesser Posted April 28, 2012 Share Posted April 28, 2012 Thanks Wesser. I'm making my compiler in C# and I don't make a decompiler because that will take to much time. It's useless. I have good plannings for the future compiling process like including functions, implement classes such as all OOP languages have and give support for ASM code pieces. Everything is done theorically, I still need some more time to write the main code. 012 345 678 9A BCD EFG HIJK LMN OPQR STUV WX YZ Link to comment Share on other sites More sharing options...
Bad.boy! Posted April 29, 2012 Author Share Posted April 29, 2012 I'm having problems with the immediate 32 bit float. 1.25 = 00 00 A0 3F How to calculate it, or how did you do it Wesser? 06 4 Float IEEE 754 – 32 bits Link to comment Share on other sites More sharing options...
fastman92 Posted April 29, 2012 Share Posted April 29, 2012 (edited) There's no reason for you to write another coprocessor In programming language when for example if you are using scanf function and came with "1.25" string as input string with format "%f", then you'll easily get "1.25" converted to 4-byte floating point (float). To display float you can use something like this: // C++ code/* scanf example */#include <stdio.h>int main (){ float f = 1.25; printf ("Your float: %.3f", f); return 0;} Edited April 29, 2012 by fastman92 Link to comment Share on other sites More sharing options...
Bad.boy! Posted April 29, 2012 Author Share Posted April 29, 2012 I need to do it the other way around. How to get from 1.25 to 00 00 A0 3F? Link to comment Share on other sites More sharing options...
fastman92 Posted April 29, 2012 Share Posted April 29, 2012 I need to do it the other way around.How to get from 1.25 to 00 00 A0 3F? Man, "1.25" will be automatically converted to 00 00 A0 3F using any C++ that lets you perform this task. Look for C++ functions to convert in Google: C++ string to float Link to comment Share on other sites More sharing options...
Bad.boy! Posted April 29, 2012 Author Share Posted April 29, 2012 I'm making my compiler in C# not C++. Anyway I just found out that it didn't work. Because the value was inverted, I got (3FA00000). Link to comment Share on other sites More sharing options...
fastman92 Posted April 29, 2012 Share Posted April 29, 2012 00 00 A0 3F is 0x3FA00000 when read as 4-byte DWORD. It's 1.25 when read as float. Link to comment Share on other sites More sharing options...
Bad.boy! Posted April 29, 2012 Author Share Posted April 29, 2012 (edited) Does anyone know why the compiler ignores a "0" on purpose? public static string Bit32Float(double Value) // 06 { float Waarde = (float)Value; byte[] bytes = System.BitConverter.GetBytes(Waarde); int i = System.BitConverter.ToInt32(bytes, 0); string Hex = i.ToString("X8"); Debug.Print(Hex); string[] Waardes = Regex.Split(Hex, ""); string[] Paar = new string[5]; int Getal = 0; foreach (string nummer in Waardes) { Getal++; switch (Getal) { case 1: Paar[1] = nummer; break; case 2: Paar[1] += nummer; break; case 3: Paar[2] = nummer; break; case 4: Paar[2] += nummer; break; case 5: Paar[3] = nummer; break; case 6: Paar[3] += nummer; break; case 7: Paar[4] = nummer; break; case 8: Paar[4] += nummer; break; } } Hex = Paar[4] + Paar[3] + Paar[2] + Paar[1]; Debug.Print(Hex); return Hex; }DEBUG:3FA000000000FA3 Edited April 29, 2012 by Bad.boy! Link to comment Share on other sites More sharing options...
fastman92 Posted April 29, 2012 Share Posted April 29, 2012 3F A0 00 00 You put value being read as 0x0000A03F = 0xA03F when integer. 00 00 A0 3F isn't equal to 3F A0 00 00. Link to comment Share on other sites More sharing options...
Wesser Posted April 29, 2012 Share Posted April 29, 2012 Seriously, leave it. You're asking help for basic things. 012 345 678 9A BCD EFG HIJK LMN OPQR STUV WX YZ Link to comment Share on other sites More sharing options...
Bad.boy! Posted April 30, 2012 Author Share Posted April 30, 2012 I am quiet stubborn*, and continue working on this compiler. Does anyone know how high a number must be to use 8bit, 16bit or 32bit ints? What is the highest value 8, 16 and 32bit can handle? *Google translate, don't know if it's the word I mean Link to comment Share on other sites More sharing options...
fastman92 Posted April 30, 2012 Share Posted April 30, 2012 I am quiet stubborn*, and continue working on this compiler. Does anyone know how high a number must be to use 8bit, 16bit or 32bit ints? What is the highest value 8, 16 and 32bit can handle? *Google translate, don't know if it's the word I mean Calculate it yourself 2^8 - 1 = ? 2^16 -1 = ? 2^32 -1 = ? ^ is power sign. For example 2 ^ 3 = 2*2*2 = 8 Look in Google what is binary system 10101011111010101010110100101 Seriously, leave it. Link to comment Share on other sites More sharing options...
Deji Posted April 30, 2012 Share Posted April 30, 2012 Well, personally I like to encourage all attempts to gain a greater understanding of something through practical work. Bad.boy could just do with learning to do more of his own research. But in fairness, this stuff should be pretty well documented by now, but it isn't. As Wesser said, though, this article has enough information to get you well on your way (though parts are pretty badly written and demonstrated, but I guess most of it was written years ago). Link to comment Share on other sites More sharing options...
Bad.boy! Posted May 1, 2012 Author Share Posted May 1, 2012 (edited) I continued working on the compiler (with no decompiling functions). And I made some progress. From this: EDIT: This didn't really work Ohh and I aint that bad in C# (not good either), it's just that I never done anything with hex and binary's. Edited May 2, 2012 by Bad.boy! Link to comment Share on other sites More sharing options...
Wesser Posted May 2, 2012 Share Posted May 2, 2012 You must analyze the source code first. You cannot create any scripts without a theorical face. For example, R* didn't implement a REPEAT-UNTIL statement, which is what you've done now (they probably found either some conflicts with FOR loop composition or its futility). My decompiler (which follows R*'s standards) won't decompile your code correctly then. 012 345 678 9A BCD EFG HIJK LMN OPQR STUV WX YZ Link to comment Share on other sites More sharing options...
Bad.boy! Posted May 2, 2012 Author Share Posted May 2, 2012 (edited) They made a repeat until loop, but R* code jumps to an other label and jumps back (I think): WHILE NOT HAS_MODEL_LOADED counter_create_car WAIT 0 PRINT_NOW LOADCAR 100 1 //"Loading vehicle, press pad2 leftshoulder1 to cancel" IF IS_BUTTON_PRESSED PAD2 LEFTSHOULDER1 //++ counter_create_car GOTO next_carzzz ENDIF ENDWHILE So I should make an other label and then jump back? EDIT: New Code public static void OpcodeWhile(string lijn, int index, bool flag) { if (flag == false) { Main.index--; index--; int index5 = 0; for (int i = index; i > 0; i--) { if (Main.Script[i] != null) { int Temp = Main.Script[i].Length; Temp /= 2; index5 += Temp; } } index5 *= -1; string Hex3 = "4D00" + Variables.Signed32BitInt(index5); bool isNot = false; int index2 = 0; string Opcode = ""; string[] opcode = lijn.Split(new Char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (!lijn.Contains("NOT")) { foreach (string woord in opcode) { index2++; if (index2 == 2) { Opcode += woord; } if (index2 == 3) { Opcode += " " + woord; } } } else { isNot = true; foreach (string woord in opcode) { index2++; if (index2 == 3) { Opcode += woord; } if (index2 == 4) { Opcode += " " + woord; } } } int index4 = 0; foreach (string ding in Main.While) { if (ding != null) { if (ding.Length > 1) { index4++; } } } Main.FindOpcode(Opcode, index, true); string Hex = ""; if (isNot == true) { int index3 = 0; string[] Tempvar = Regex.Split(Main.While[index4], ""); foreach (string nummer in Tempvar) { index3++; if (index3 == 4) { Hex += "8"; } else { Hex += nummer; } } } else { Hex = Main.While[index4]; } Main.While[index4] = Hex + Hex3; Main.CurrentWhile[index4] = "Huidige"; } else { Main.Error = true; } } public static void OpcodeEndWhile(string lijn, int index, bool flag) { if (flag == false) { int i = -1; foreach (string line in Main.CurrentWhile) { if (line != null) { if (line == "Huidige") { i++; } } } string Hex = Main.While[i]; Main.CurrentWhile[i] = null; Main.Script[index] = Hex; Main.index++; } else { Main.Error = true; } } Edited May 3, 2012 by Bad.boy! Link to comment Share on other sites More sharing options...
Wesser Posted May 2, 2012 Share Posted May 2, 2012 Listen, I have good knowledges about the source code, so it'd be useless for you to understand by yourself what another user already knows. Wait some time till my documentation will come up. 012 345 678 9A BCD EFG HIJK LMN OPQR STUV WX YZ Link to comment Share on other sites More sharing options...
Bad.boy! Posted May 5, 2012 Author Share Posted May 5, 2012 If anyone is interested: I've finished the while loop, and added an if loop. THREAD "HIGH" // <-- BugIF IS_PLAYER_PLAYING PLAYER IF IS_PLAYER_PLAYING PLAYER2<155> WAIT 100 ELSE WAIT 200 // <-- Bug ENDIF WAIT 300ENDIFEND_CUSTOM_THREAD {$CLEO .cs}//-------------MAIN---------------if Player.Defined($PLAYER_CHAR)else_jump @NONAME_52 if Player.Defined($SECOND_PLAYER)else_jump @NONAME_43 wait 100 jump @NONAME_47 :NONAME_43wait -56 // Bug:NONAME_47wait 300 :NONAME_520A93: end_custom_thread The if with while doesn't seem to compile good, but I'm sure that it is fixable. This is a generated code, it's not programmed to compile only that combination Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now