From c5acce4cfbd872443802d02cc3f06b931c79045b Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 20 May 2024 00:22:59 +0200
Subject: Extend the available arithmetic operations on vmpa2t Python objects.

---
 plugins/pychrysalide/arch/vmpa.c | 125 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 122 insertions(+), 3 deletions(-)

diff --git a/plugins/pychrysalide/arch/vmpa.c b/plugins/pychrysalide/arch/vmpa.c
index 605b04d..20784cd 100644
--- a/plugins/pychrysalide/arch/vmpa.c
+++ b/plugins/pychrysalide/arch/vmpa.c
@@ -76,6 +76,12 @@ static bool convert_pyobj_to_vmpa(PyObject *, vmpa2t *);
 /* Effectue une opération de type 'add' avec le type 'vmpa'. */
 static PyObject *py_vmpa_nb_add(PyObject *, PyObject *);
 
+/* Effectue une opération de type 'sub' avec le type 'vmpa'. */
+static PyObject *py_vmpa_nb_subtract(PyObject *, PyObject *);
+
+/* Effectue une opération de type 'add' sur une instance 'vmpa'. */
+static PyObject *py_vmpa_nb_inplace_add(PyObject *, PyObject *);
+
 
 
 /* ------------------------ DEFINITION D'UNE ZONE EN MEMOIRE ------------------------ */
@@ -499,6 +505,8 @@ static PyObject *py_vmpa_nb_add(PyObject *o1, PyObject *o2)
     vmpa2t addr1;                           /* Première adresse à traiter  */
     vmpa2t addr2;                           /* Seconde adresse à traiter   */
     PyTypeObject *py_vmpa_type;             /* Type Python pour 'vmpa'     */
+    phys_t new_phys;                        /* Nouvelle position           */
+    virt_t new_virt;                        /* Nouvelle adresse            */
 
     if (!convert_pyobj_to_vmpa(o1, &addr1))
         return NULL;
@@ -510,9 +518,117 @@ static PyObject *py_vmpa_nb_add(PyObject *o1, PyObject *o2)
 
     result = PyObject_CallObject((PyObject *)py_vmpa_type, NULL);
 
-    init_vmpa(&((py_vmpa_t *)result)->addr,
-              addr1.physical + addr2.physical,
-              addr1.virtual + addr2.virtual);
+    if (addr1.physical != NO_PHYSICAL && addr2.physical != NO_PHYSICAL)
+        new_phys = addr1.physical + addr2.physical;
+    else
+        new_phys = NO_PHYSICAL;
+
+    if (addr1.virtual != NO_VIRTUAL && addr2.virtual != NO_VIRTUAL)
+        new_virt = addr1.virtual + addr2.virtual;
+    else
+        new_virt = NO_VIRTUAL;
+
+    init_vmpa(&((py_vmpa_t *)result)->addr, new_phys, new_virt);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : o1 = premier élément concerné par l'opération.               *
+*                o2 = second élément concerné par l'opération.                *
+*                                                                             *
+*  Description : Effectue une opération de type 'sub' avec le type 'vmpa'.    *
+*                                                                             *
+*  Retour      : Résultat de l'opération.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_vmpa_nb_subtract(PyObject *o1, PyObject *o2)
+{
+    PyObject *result;                       /* Résultat à retourner        */
+    vmpa2t addr1;                           /* Première adresse à traiter  */
+    vmpa2t addr2;                           /* Seconde adresse à traiter   */
+    PyTypeObject *py_vmpa_type;             /* Type Python pour 'vmpa'     */
+    phys_t new_phys;                        /* Nouvelle position           */
+    virt_t new_virt;                        /* Nouvelle adresse            */
+
+    if (!convert_pyobj_to_vmpa(o1, &addr1))
+        return NULL;
+
+    if (!convert_pyobj_to_vmpa(o2, &addr2))
+        return NULL;
+
+    py_vmpa_type = get_python_vmpa_type();
+
+    result = PyObject_CallObject((PyObject *)py_vmpa_type, NULL);
+
+    if (addr1.physical != NO_PHYSICAL && addr2.physical != NO_PHYSICAL)
+        new_phys = addr1.physical - addr2.physical;
+    else
+        new_phys = NO_PHYSICAL;
+
+    if (addr1.virtual != NO_VIRTUAL && addr2.virtual != NO_VIRTUAL)
+        new_virt = addr1.virtual - addr2.virtual;
+    else
+        new_virt = NO_VIRTUAL;
+
+    init_vmpa(&((py_vmpa_t *)result)->addr, new_phys, new_virt);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : o1 = premier élément concerné par l'opération.               *
+*                o2 = second élément concerné par l'opération.                *
+*                                                                             *
+*  Description : Effectue une opération de type 'add' sur une instance 'vmpa'.*
+*                                                                             *
+*  Retour      : Résultat de l'opération.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_vmpa_nb_inplace_add(PyObject *o1, PyObject *o2)
+{
+    PyObject *result;                       /* Résultat à retourner        */
+    vmpa2t addr1;                           /* Première adresse à traiter  */
+    vmpa2t addr2;                           /* Seconde adresse à traiter   */
+    phys_t new_phys;                        /* Nouvelle position           */
+    virt_t new_virt;                        /* Nouvelle adresse            */
+    vmpa2t *inplace;                        /* Données à modifier          */
+
+    if (!convert_pyobj_to_vmpa(o1, &addr1))
+        return NULL;
+
+    if (!convert_pyobj_to_vmpa(o2, &addr2))
+        return NULL;
+
+    if (addr1.physical != NO_PHYSICAL && addr2.physical != NO_PHYSICAL)
+        new_phys = addr1.physical + addr2.physical;
+    else
+        new_phys = NO_PHYSICAL;
+
+    if (addr1.virtual != NO_VIRTUAL && addr2.virtual != NO_VIRTUAL)
+        new_virt = addr1.virtual + addr2.virtual;
+    else
+        new_virt = NO_VIRTUAL;
+
+    inplace = get_internal_vmpa(o1);
+
+    inplace->physical = new_phys;
+    inplace->virtual = new_virt;
+
+    result = o1;
+    Py_INCREF(result);
 
     return result;
 
@@ -536,6 +652,9 @@ PyTypeObject *get_python_vmpa_type(void)
     static PyNumberMethods py_vmpa_nb_proto = {
 
         .nb_add = py_vmpa_nb_add,
+        .nb_subtract = py_vmpa_nb_subtract,
+
+        .nb_inplace_add = py_vmpa_nb_inplace_add,
 
         /*
      binaryfunc nb_add;
-- 
cgit v0.11.2-87-g4458