Quantcast

Jump to content

» «
Photo

Opcodes. Variable number of arguments

14 replies to this topic
Lev_Landau
  • Lev_Landau

    Player Hater

  • Members
  • Joined: 11 Aug 2013

#1

Posted 07 March 2014 - 02:12 AM Edited by Lev_Landau, 24 April 2014 - 12:55 AM.

-


LINK/2012
  • LINK/2012

    LIVIN' IN CODE

  • Feroci Racing
  • Joined: 30 Jan 2011
  • Brazil

#2

Posted 07 March 2014 - 02:43 PM Edited by LINK/2012, 07 March 2014 - 03:12 PM.

You'll need to do that in somewhat a manual way.
 
First, you'll need a point of reference to how many extra parameters you'll have, in the case of those opcodes you have the "number of params" and the "number of formating".
Then you'll just need to collect the number of parameters needed using the respective SDK functions (CLEO_GetFloatOpcodeParam, CLEO_GetIntOpcodeParam, etc etc).
 
Now, how do you know what parameter type it is, a string, int, float...? Use CLEO_GetOperandType and check the result. The SDK should have a enum with the operand types but if it doesn't you can look here on the datatypes table.
 
Now, what if you don't have a number of parameters to collect but you still want to collect all extra parameters, just like 004F? Simple, the last operand type will be 0x0, it singalizes the end of the extra parameters list.
 
So, here we go with a example:

/* bla */ opcode_7FFF(/* bla bla bla */)
{
    int operand;
    // bla bla bla
 
    while(operand = CLEO_GetOperandType(thread)) // While not the end of the extra parameters
    {
        switch(operand)
        {
            // Check out the operand type and do your stuff
            // Put your cases here <>
        }
    }
}

Lev_Landau
  • Lev_Landau

    Player Hater

  • Members
  • Joined: 11 Aug 2013

#3

Posted 07 March 2014 - 10:29 PM Edited by Lev_Landau, 24 April 2014 - 12:55 AM.

-


LINK/2012
  • LINK/2012

    LIVIN' IN CODE

  • Feroci Racing
  • Joined: 30 Jan 2011
  • Brazil

#4

Posted 08 March 2014 - 12:36 AM Edited by LINK/2012, 08 March 2014 - 12:37 AM.

Most trivial options:

Option 1: Let the 'Log' function handle the parameters collection

Option 2: Store the parameters + parameter type on an array and send to the logging func.

 

I guess the option 1 is better, option 2 looks dirty.


Lev_Landau
  • Lev_Landau

    Player Hater

  • Members
  • Joined: 11 Aug 2013

#5

Posted 08 March 2014 - 02:42 PM Edited by Lev_Landau, 24 April 2014 - 12:55 AM.

-


LINK/2012
  • LINK/2012

    LIVIN' IN CODE

  • Feroci Racing
  • Joined: 30 Jan 2011
  • Brazil

#6

Posted 08 March 2014 - 04:04 PM Edited by LINK/2012, 08 March 2014 - 04:05 PM.

You could take the array parameter flags, check out here
But really, I don't think you should, the game itself don't care about what you're sending, it expects you to be sending what it wants.
For example, 0001 (WAIT), the game expects a integer, right? What if you send a float (e.g. WAIT 1.0)? Well, what will happen is that it will still collect a integer and then will WAIT 0x3F800000 (0x3F800000 is the binary representation of the floating point 1.0)
So really, just parse your formats, if you come up with an '%f' tell CLEO to collect a float, with a '%s', collect a string, and so on.
 
Here's a simple example:
void Log(const char* format, CScriptThread* thread)
{
    for(; *format; ++format)
    {
        if(*format == '%')
        {
            if(format[1] == 'f')
            {
                // Collect a float and sprintf into your buffer, or print it already, dunno
            }
            else if /* and so on */ {}
        }
        else { /**/ }
    }
}

/**/ opcode_7FFF(/**/)
{
    Log(CollectStringParameter(thread), thread);
    // Skip unused params if you want, CLEO has a SDK func to skip unused params.
}

Lev_Landau
  • Lev_Landau

    Player Hater

  • Members
  • Joined: 11 Aug 2013

#7

Posted 13 March 2014 - 01:28 AM Edited by Lev_Landau, 24 April 2014 - 12:55 AM.

-


_DK
  • _DK

    gta3 cleo

  • Feroci Racing
  • Joined: 12 Apr 2009
  • None

#8

Posted 13 March 2014 - 03:46 AM

CLEO SDK can't handle such opcodes. You need to do operations with CScriptThread data manually.

Lev_Landau
  • Lev_Landau

    Player Hater

  • Members
  • Joined: 11 Aug 2013

#9

Posted 13 March 2014 - 09:37 PM Edited by Lev_Landau, 24 April 2014 - 12:55 AM.


Deji
  • Deji

    Coding like a Rockstar!

  • Feroci Racing
  • Joined: 24 Dec 2007
  • None

#10

Posted 13 March 2014 - 11:47 PM

 

CLEO SDK can't handle such opcodes. You need to do operations with CScriptThread data manually.

What may handle them? There are native opcodes with variable number of parameters and I also found some custom opcodes, that accept variable number of parameters as well (namely SAMPFUNCS)

 

 

 

Simply check:

if( *thread->ip != NULL )

before trying to get a parameter.

 

However, the purpose of the 'null data type' is for the end of an argument list - not for the end of "variable number of arguments" - that is strictly a SB reference and it's common to confuse it's simplifications of what was once a more complex language. In the original engine it's never used for anything other than transmitting parameters to another script. CLEO actually never does any different - for most opcodes (CALL and RET) they are being used in pretty much the same way. All other times, the number of arguments and more importantly the types have to be known somehow. Pretty pointless trying to get everything when you know exactly what you need.

 

Anyway, CLEO 4 has already done this and the source code is available anyway, but here's the specific function of interest: https://pastebin.com/1nSRi0zi

 

As you can see, no need for getting a variable number of arguments, but you can call SkipOpcodeParams afterwards if you want to allow something that shouldn't happen.

 

The variant for sscanf-style operations might be of interest, too, but I'll just post it here:

int *result = (int *)GetScriptParamPointer(thread);
  SCRIPT_VAR *ExParams[35];
  // read extra params
  for(int i = 0; i<35; i++)
  {
   if(*thread->ip)
   {
    ExParams[i] = GetScriptParamPointer(thread);
    cExParams++;
   }
   else ExParams[i] = nullptr;
  }
  ++thread->ip;
  *result = sscanf(src, format,
   /* extra parameters (will be aligned automatically, but the limit of 35 elements maximum exists) */  
   ExParams[0], ExParams[1], ExParams[2], ExParams[3], ExParams[4], ExParams[5],
   ExParams[6], ExParams[7], ExParams[8], ExParams[9], ExParams[10], ExParams[11],
   ExParams[12], ExParams[13], ExParams[14], ExParams[15], ExParams[16], ExParams[17],
   ExParams[18], ExParams[19], ExParams[20], ExParams[21], ExParams[22], ExParams[23],
   ExParams[24], ExParams[25], ExParams[26], ExParams[27], ExParams[28], ExParams[29],
   ExParams[30], ExParams[31], ExParams[32], ExParams[33], ExParams[34]);

LINK/2012
  • LINK/2012

    LIVIN' IN CODE

  • Feroci Racing
  • Joined: 30 Jan 2011
  • Brazil

#11

Posted 14 March 2014 - 12:15 AM

How you need to do that manually? CLEO_GetOperandType returns the current byte (and thus the datatype) without moving PC.

Lev_Landau
  • Lev_Landau

    Player Hater

  • Members
  • Joined: 11 Aug 2013

#12

Posted 14 March 2014 - 09:56 PM Edited by Lev_Landau, 24 April 2014 - 12:55 AM.

-

Lev_Landau
  • Lev_Landau

    Player Hater

  • Members
  • Joined: 11 Aug 2013

#13

Posted 25 March 2014 - 11:21 PM Edited by Lev_Landau, 24 April 2014 - 12:54 AM.

-


Silent
  • Silent

    Moderating Cookie Monster

  • Feroci Racing
  • Joined: 01 Feb 2010
  • Poland
  • Most Helpful [GTA] 2013
    Most Helpful [Modding] 2013
    Most Talented [Modding] 2013
    Best Map 2013 "ViceCityStories PC Edition"
    Best Vehicle 2013 "III Aircraft"
    Most Helpful [Modding] 2012
    Modder of the Year 2012

#14

Posted 25 March 2014 - 11:31 PM Edited by Silent, 25 March 2014 - 11:32 PM.

Opcodes with an undefined amount of parameters 'terminate' the param list with 00, are you handling this in your code? If you don't, it'll next be executed as a part of opcode ID and therefore crash.

Lev_Landau
  • Lev_Landau

    Player Hater

  • Members
  • Joined: 11 Aug 2013

#15

Posted 27 March 2014 - 12:30 AM Edited by Lev_Landau, 24 April 2014 - 12:54 AM.

 





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users