• 18 Avril 2025, 10:27:18


Auteur Sujet: SYSREQ ou pas ?  (Lu 3823 fois)

0 Membres et 1 Invité sur ce sujet

Hors ligne S4T3K

  • *
  • Nouveau
  • Messages: 20
    • Voir le profil
SYSREQ ou pas ?
« le: 14 Juin 2014, 16:57:51 »
Yop.

Je suis toujours en train de taffer sur mon fix pour les timers, permettant d'ajouter le spécifier "a" (ou s, je verrais) pour les tableaux, et actuellement, via la directive de pré-processeur #emit, j'ai récupéré dans "n" (avant de nettoyer le stack via ClearStack) les paramètres de la fonction (et donc Kilou, tu avais tord, c'est possible même si le nombre de paramètres est pas fixe, jtm), mais je suis censé lancer une requête système (via #emit SYSREQ.C nom_de_la_native).

Sauf que moi, je compte appeler une fonction "CallTimer(timerid)" qui appelera la fonction publique passée en paramètre via CallLocalFunction.

Donc je mets quoi en SYSREQ ? Et si je dois pas en mettre, je récupère tout les arguments où ?

Voilà mon code actuel :

Code: (pawn) [Sélectionner]

stock EFIX_SetTimerEx(const funcname[35], interval, bool:repeating, format[121], {Float, _}:...)
{

    for(fixi = 0; fixi < MAX_TIMERS; fixi++)
    {
        if(!InfoTimer[fixi][tRunning]) break;
    }

    static const num_args = 0;
    new n = (numargs() - num_args) * BYTES_PER_CELL;
    if(n == 3 * 4) SetTimer(funcname, interval, repeating);
    if(n)
    {
        new 
            arg_start,
            arg_end;

        #emit CONST.alt        8
        #emit LCTRL          5
        #emit ADD
        #emit STOR.S.pri        arg_start

        #emit LOAD.S.alt        n
        #emit ADD
        #emit STOR.S.pri        arg_end

        do
        {
            #emit LOAD.I
            #emit PUSH.pri
            arg_end -= BYTES_PER_CELL;
            #emit LOAD.S.pri      arg_end
        }
        while (arg_end > arg_start);

        #emit PUSH.S funcname
        #emit PUSH.S interval
        #emit PUSH.S repeating
        #emit PUSH.S format

        n += BYTES_PER_CELL * STATIC_ARGS;
        #emit PUSH.S          n
        #emit SYSREQ.C                 

        ClearStack(n);
    }
    return 1;
}

stock ClearStack(var)
{
    var += BYTES_PER_CELL;
    #emit LCTRL                        4
    #emit LOAD.S.alt                   n
    #emit ADD
    #emit SCTRL                        4



Voilà, merci d'avance.

PS : Je poste ici sur demande de Kilou. Il m'a dit qu'il y aurait plus de personnes aptes à m'aider ici que sur le forum samp français.
« Modifié: 04 Juillet 2014, 01:32:14 par S4T3K »

Hors ligne Ssk

  • *
  • Lulu's Stunt - Le serveur stunt de Lulu !
  • Messages: 8154
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #1 le: 15 Juin 2014, 23:37:27 »
Salut, pour jouer avec le P-CODE (ou l'assembleur amx, si on veut) il faut absolument lire la documentation.

Les 'SYSREQ' sont des opcodes qui permettent d'appeler des fonctions natives, c'est-à-dire des fonctions ajoutées par le logiciel qui utilise la machine virtuelle de l'AMX, dans notre cas le serveur SA-MP.

Pour appeler une fonction qui est situé dans l'amx (donc le script) il faut utiliser l'opcode 'CALL' en lui fournissant l'adresse relative de la fonction.

Si tu veux la documentation, elle se trouve ici : http://www.compuphase.com/pawn/Pawn_Implementer_Guide.pdf



Derrière tout programme se cache un programmeur, je considère le monde comme un programme.
Mon blog

Hors ligne S4T3K

  • *
  • Nouveau
  • Messages: 20
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #2 le: 16 Juin 2014, 12:42:44 »
Yop.

J'ai lu le tuto de Y_Less à propos de ça, mais le truc que j'ai pas compris c'est que :

Pour mon code, j'appelle la fonction CallTimer(timerid) via un SetTimerEx simple, le hic c'est que je sais pas où stocker "n", qui vaut pour le moment "tous mes paramètres" (enfin plutôt ceux à quoi ils correspondent dans le script).

1 : Je le stocke dans une variable normale "stockCorr[fixi] = n", mais dans ce cas là je prends pas en compte les flottants ni les tableaux, et ça va pas
2 : J'appelle le timer via SetTimerEx mais pour appeler la fonction du timer via CallLocalFunction, je mets quoi en dernier paramètre ? Puisque je pourrais pas récupérer ce que le codeur a rentré la première fois

Et c'est ça que j'arrive pas à comprendre.

Hors ligne Ssk

  • *
  • Lulu's Stunt - Le serveur stunt de Lulu !
  • Messages: 8154
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #3 le: 16 Juin 2014, 17:57:57 »
J'ai pas du tout saisi.

edit : En regardant de plus près ton code, je comprends vraiment pas ce que tu tente de faire.

Perso, pour récupérer les arguments d'une fonction je fais ça.

Code: (pawn) [Sélectionner]
args(a, b, c, d, e)
{
// 12 - premier argument de la fonction
new l_iArgsBytesCount = numargs() * 4;

new value;


while(l_iArgsBytesCount > 0)
{
#emit load.s.alt l_iArgsBytesCount
#emit addr.pri 12
#emit add
#emit load.i
#emit stor.s.pri value

printf("v -> %d", value);
l_iArgsBytesCount -= 4;
}
}
« Modifié: 16 Juin 2014, 18:29:01 par Ssk »



Derrière tout programme se cache un programmeur, je considère le monde comme un programme.
Mon blog

Hors ligne S4T3K

  • *
  • Nouveau
  • Messages: 20
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #4 le: 16 Juin 2014, 19:06:32 »
Bah je t'explique tout :

Mon code ci-dessus sert à fixer un défaut des timers simples (SetTimerEx) : on peut pas passer de tableaux en paramètres. Du coup, j'ai étudié un peu l'assembly et j'ai vu que c'était possible en utilisant le #emit.

J'ai donc suivi (plus ou moins en adaptant) le code de ZeeX pour SendClientMessageFormatted afin de récupérer un nombre non fixe d'arguments dans une adresse mémoire (une variable qui comporte cette adresse mémoire quoi) et cette adresse mémoire comporte la "pile" de tout ce à quoi correspondent les arguments dans la fonction. Kilou a eu le même problème de compréhension, donc pour illustrer je te donne un petit exemple

Code: (pawn) [Sélectionner]

new entier, Float:flottant, bool:boolean, tableau[10];

forward Fonction(entier, Float:flottant, bool:boolean, tableau[]);
public Fonction(entier, Float:flottant, bool:boolean, tableau[])
{
      // Faire des choses random ici
}

SetTimerEx("Fonction", 1000, false, /* Le "format" des paramètres */"ifba", /* Ce à quoi ils correspondent dans le code */ entier, flottant, boolean, tableau);

Donc actuellement, ma variable "n" en mémoire vaut, pour cet exemple, les adresses mémoires de "entier", "flottant", "boolean" et "tableau". Comme la native actuelle de samp "SetTimerEx" ne permet pas de passer des tableaux, j'aimerais rendre ça possible mais actuellement je suis bloqué à un endroit :

Je suis parti sur un système utilisant une fonction intermediaire "CallTimer(timerid)" et cette fonction devait à son tour appeler la fonction que le timer devait appeler à l'origine via CallLocalFunction, qui autorise le passage de "string" en paramètre.
Sauf que j'ai aucun moyen de récupérer "n" une fois que ma fonction "CallTimer" a été appelée.
Et c'est ça que j'aimerais savoir, comment la récupérer ?

Hors ligne Ssk

  • *
  • Lulu's Stunt - Le serveur stunt de Lulu !
  • Messages: 8154
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #5 le: 17 Juin 2014, 15:19:22 »
Salut, je crois que tu n'as pas compris le code donné.

'n' ne vaut pas les adresse en mémoire, mais la taille en octet des arguments passés dans ta fonction.

Je t'ai codé ça en espérant que tu comprennes, mais sinon je comprends toujours pas le rapport avec ton système de timer.

Code: (pawn) [Sélectionner]
#include <a_samp>


public OnFilterScriptInit()
{
printf("");
printf__("test %d", 5);
}

printf__({Float, _}:...)
{
new l_iArgsBytesCount;
new l_iArgsAddrStart;
new i;

/* Ici on récupère la taille en octets des arguments passé à la fonction*/
l_iArgsBytesCount = numargs() * 4;

/* Ici on récupère l'adresse en mémoire des arguments et on le stock dans 'l_iArgsAddrStart' */
#emit CONST.ALT 8
#emit LCTRL 5
#emit ADD
#emit STOR.S.PRI l_iArgsAddrStart


/* Ici on parcours tous les arguments passé en commençant par le dernier pour arriver au premier*/
for(i = l_iArgsBytesCount; i > 0; i -= 4)
{
/* On calcul l'adresse de l'argument */
#emit LOAD.S.ALT i
#emit LOAD.S.PRI l_iArgsAddrStart
#emit ADD
/* On charge la valeur stocké dans l'adresse précédemment calculé */
#emit LOAD.I
/* Et on le push dans la stack */
#emit PUSH.PRI
}

/* Comme c'est une fonction native, le premier argument doit être la taille en octet des arguments, du coup on push cette taille la */
#emit PUSH.S l_iArgsBytesCount
/* On appel la fonction native printf */
#emit SYSREQ.C printf


/* Et comme on a push des données dans la stack, il faut clear */
l_iArgsBytesCount += 4; // sans oublier qu'on a aussi push la taille des données, donc 4 octet en plus

#emit LCTRL 4
#emit LOAD.S.ALT l_iArgsBytesCount
#emit ADD
#emit SCTRL 4
}



Derrière tout programme se cache un programmeur, je considère le monde comme un programme.
Mon blog

Hors ligne S4T3K

  • *
  • Nouveau
  • Messages: 20
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #6 le: 17 Juin 2014, 16:34:04 »
Bah le système de timer fait en sorte de pouvoir simplement passer des tableaux en paramètres (via un spécificateur s ou a), chose actuellement impossible avec la fonction classique.

Pour faire ça, on a besoin de modifier la fonction SetTimerEx pour qu'on puisse stocker ce que valent les paramètres dans le script, et une fois qu'on a récupéré ce qu'ils valent, on stock ça quelque part, pour ensuite pouvoir s'en servir comme "correspondance" dans CallLocalFunction.

Je vais regarder ton code.

Hors ligne Ssk

  • *
  • Lulu's Stunt - Le serveur stunt de Lulu !
  • Messages: 8154
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #7 le: 17 Juin 2014, 18:17:45 »
D'accord, je comprends mieux.

Ce que tu souhaite faire c'est donc implémenter ton propre système de timer ?



Derrière tout programme se cache un programmeur, je considère le monde comme un programme.
Mon blog

Hors ligne Kiloutre

  • Nolife, nerd et geek passionné d'Ordinatique ! ^^
  • *
  • Grand Banditisme
  • Messages: 567
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #8 le: 17 Juin 2014, 19:52:31 »
C'est ça, il veut re-faire le système de timer parce que le système de base ne permet pas de passer de chaîne ni de tableau, et il aimerait remédier à cela

[/url]

Hors ligne Gzsume

  • *
  • Compétent dans l'inutile
  • Messages: 2236
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #9 le: 17 Juin 2014, 20:01:55 »
Il y a déjà des patchs pour ça, pourquoi vouloir le faire soi-même ?

Hors ligne Ssk

  • *
  • Lulu's Stunt - Le serveur stunt de Lulu !
  • Messages: 8154
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #10 le: 17 Juin 2014, 20:06:46 »
Ce sera assez limité comme système car tu pourra pas stocker autant de timer que les vrais.

Imagine un serveur avec une quinzaine de SetTimerEx, chacun avec plusieurs strings.

Comment va tu faire pour les sauver dans la mémoire ?



Derrière tout programme se cache un programmeur, je considère le monde comme un programme.
Mon blog

Hors ligne S4T3K

  • *
  • Nouveau
  • Messages: 20
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #11 le: 18 Juin 2014, 11:33:15 »
Ce fix était à l'origine pour être utilisé pour moi, j'ai seulement deux timers qui n'ont pas de paramètre "playerid" mais qui ont besoin de passer des tableaux, donc au niveau de l'opti ça reste raisonnable.

@Gzsume Si tu parles des y_timers, je trouve que Y_Less a trop compliqué son code pour rien, ce qui est dommage d'ailleurs car son système est pas mal. Si tu ne parles pas des y_timers, alors je ne connais (pour les timers) que le patch de Slice qui permet de rendre les délais plus précis.

Hors ligne Ssk

  • *
  • Lulu's Stunt - Le serveur stunt de Lulu !
  • Messages: 8154
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #12 le: 18 Juin 2014, 11:52:43 »
Pourquoi tu utilises pas des variables globales ?



Derrière tout programme se cache un programmeur, je considère le monde comme un programme.
Mon blog

Hors ligne S4T3K

  • *
  • Nouveau
  • Messages: 20
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #13 le: 18 Juin 2014, 17:37:50 »
Pourquoi pas, le problème reste le même en soi : comment je peux détecter, dans les arguments qu'aura passé le codeur, les tableaux ?

Le seul moyen que j'ai trouvé c'est l'assembly, et comme je trouve ça assez chaud, bah je continue d'apprendre.

Hors ligne Ssk

  • *
  • Lulu's Stunt - Le serveur stunt de Lulu !
  • Messages: 8154
    • Voir le profil
Re : SYSREQ ou pas ?
« Réponse #14 le: 18 Juin 2014, 21:26:37 »
Nan, je veux dire, faire un truc de ce genre :

Code: (pawn) [Sélectionner]
new g_szString[128];


public OnGameModeInit()
{
format(g_szString, sizeof(g_szString), "Ton texte ici");
SetTimer("tontimer", 1000, 0);
}

public tontimer()
{
print(g_szString);
}



Derrière tout programme se cache un programmeur, je considère le monde comme un programme.
Mon blog