[DEV] New dynamic library system

Started by SplinterGU, September 08, 2007, 04:35:01 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

SplinterGU

Well, inagurating the forum, I want to show you some of advances of Bennu and show the first version of dynamic library system or BennuGD modules (BennuGD means, Bennu Game Development).

Features of the new system:
- Add language functions (DLLs, like until now)
- Add Globals Variables
- Add Locals variables
- Add Constants
- Ability to get access to any Global or Local variable of the system
- Now, it's not necessary to recompile .dcb file when comes a new dynamic library version that include new functions or new variables
(Except when it changes variable type, number of parameters or return type of a function).
- Functions to initialize and finalize the library.

Nothing better than an example to show how it's this.

bennudl.c (plugin)

[code language="c"]
#include <bgddl.h>

#include <stdlib.h>
#include <stdio.h>

/* ----------------------------------------------------------------- */
/* Samples functions prototypes                                      */

static int show_gvar (INSTANCE * my, int * params);
static int show_lvar (INSTANCE * my, int * params);

/* ----------------------------------------------------------------- */
/* Constants definitions (useful in compilation time)                */

DLCONSTANT  constants_def[] =
{
    { "FALSO",      TYPE_DWORD,      0 },
    { "VERDADERO",  TYPE_DWORD,     !0 },
    { NULL, 0, 0 }
} ;

/* ----------------------------------------------------------------- */
/* Globals Vars definitions (useful in compilation time)             */

char * globals_def = "int glob1;\n"
                     "int glob2;\n";

/* ----------------------------------------------------------------- */
/* Locals Vars definitions (useful in compilation time)              */

char * locals_def  = "int loc1;\n"
                     "int loc2;\n";

/* ----------------------------------------------------------------- */
/* This are the variables to you want get access.                    */
/* The interpreter fill this struct, if the variable exist.          */
/* (useful in runtime)                                               */

DLVARFIXUP  globals_fixup[] =   {
    /* Global Variable Name, pointer to data address, element size, elements in array */
                                { "timer[1]", NULL, -1, -1 },
                                { "fps", NULL, -1, -1 },
                                { "fileinfo.path", NULL, -1, -1 },
                                { "cdinfo.track", NULL, -1, -1 },
                                { "cdinfo.track[1].audio", NULL, -1, -1 },
                                { "os_id", NULL, -1, -1 },
                                { "glob1", NULL, -1, -1 },
                                { "glob2", NULL, -1, -1 },
                                { "a", NULL, -1, -1 },
                                { "b", NULL, -1, -1 },
                                { "c", NULL, -1, -1 },
                                { "d", NULL, -1, -1 },
                                { "e", NULL, -1, -1 },
                                { "e[0]", NULL, -1, -1 },
                                { "e[1]", NULL, -1, -1 },
                                { "e[2][1]", NULL, -1, -1 },
                                { NULL, NULL, -1, -1 }
                                };

/* ----------------------------------------------------------------- */
/* This are the variables to you want get access.                    */
/* The interpreter fill this struct, if the variable exist.          */
/* (useful in runtime)                                               */

DLVARFIXUP  locals_fixup[]  =   {
    /* Local Variable Name, offset to data, element size, elements in array */
                                { "x", -1, -1, -1 },
                                { "y", -1, -1, -1 },
                                { "graph", -1, -1, -1 },
                                { "loc1", -1, -1, -1 },
                                { "loc2", -1, -1, -1 },
                                { "reserved.status", -1, -1, -1 },
                                { NULL, -1, -1, -1 }
                                };

/* ----------------------------------------------------------------- */
/* Functions declarations                                            */

DLSYSFUNCS  functions_exports[] = {
                          { "SHOW_GVAR", "I", TYPE_INT, show_gvar },
                          { "SHOW_LVAR", "I", TYPE_INT, show_lvar },
                          { NULL, NULL, 0, NULL }
                          };

/* ----------------------------------------------------------------- */
/* Initialization functions of the module/plugin                     */

int module_initialize()
{
    return 0; // OK
}

/* ----------------------------------------------------------------- */

int module_finalize()
{
    return 0; // OK
}

/* ----------------------------------------------------------------- */
/* Sample functions                                                  */

/* ----------------------------------------------------------------- */
/* Access to a global variable                                       */

static int show_gvar (INSTANCE * my, int * params)
{
    if (globals_fixup[params[0]].data_offset)
        printf("%s=%d\n", globals_fixup[params[0]].var, *(int *)(globals_fixup[params[0]].data_offset));

    return 0;
}

/* ----------------------------------------------------------------- */
/* Access to a local variable                                        */

static int show_lvar (INSTANCE * my, int * params)
{
    if (locals_fixup[params[0]].data_offset != (void *) -1)
        printf("%s=%d\n", locals_fixup[params[0]].var, *(int *)((char *)(my->locdata)+(int)(locals_fixup[params[0]].data_offset)));
    return 0;
}

/* ----------------------------------------------------------------- */
/* NOTE:                                                             */
/* The system include a fixup of variables and too of functions,     */
/* what one avoids that if the new dll add news functions            */
/* and/or news variables you must recompile the .dcb binary file.    */
/* ----------------------------------------------------------------- */
[/code]

bennudl.sym


globals_def
locals_def
constants_def
globals_fixup
locals_fixup
functions_exports
module_initialize
module_finalize


bgddl.h

[code language="c"]
/*
*  Copyright © 1999-2002 José Luis Cebrián Pagüe
*  Copyright © 2002-2006 Fenix Team
*  Copyright © 2006-2007 SplinterGU
*
*  This file is part of Bennu - Game Development
*
*  Bennu is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  Bennu is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
*
*/

#ifndef _BGDDL_H
    #define _BGDDL_H

    #include <typedef_st.h>
    #include <instance_st.h>

    typedef struct _dlvarfixup
    {
        char * var;
        void * data_offset;
        int size;
        int elements;
    }
    DLVARFIXUP;

    typedef struct _dlsysfuncs
    {
        char * name;
        char * paramtypes;
        int type;
        void * func;
    }
    DLSYSFUNCS;

    typedef struct _dlconstant
    {
        char * name;
        BASETYPE type;
        int code;
    } DLCONSTANT;

#endif [/code]

sample.prg

[code language="bennu"]
//----------------------------------------------------------------------------
program sample;

import "bennudl";


global
    a=0;
    b[2]=2,3;
    float c[2]=1.1, 2.2;

    d[2][3]=(1,2),3,(4,5);
    e[2][3]=1,2,3,4,5,6;

begin
    write_var(0,10,10,0,fps);
    while(!key(_ESC))

        x=mouse.x;
        y=mouse.y;

        SHOW_GVAR(0);
        SHOW_GVAR(1);
        SHOW_GVAR(2);

        SHOW_LVAR(0);
        SHOW_LVAR(1);

        frame;
    end;
end
[/code]

Thanks to izubiaurre for the translation
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

I post here one of the Bennu's module as a sample, for anybody that want development modules for bennu...
If anybody want the Bennu WIP only for development modules (no official modules), I can send this version...

[code language="bennu"]
/*
*  Copyright © 1999-2002 José Luis Cebrián Pagüe
*  Copyright © 2002-2006 Fenix Team
*  Copyright © 2006-2007 SplinterGU
*
*  This file is part of Bennu - Game Development
*
*  Bennu is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  Bennu is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef TARGET_MAC
#include <SDL/SDL.h>
#else
#include <SDL.h>
#endif

#include <SDL_keysym.h>
#include <SDL_thread.h>
#include <SDL_syswm.h>

#include "bgddl.h"

#include "bgdruntime.h"

#include "files.h"
#include "xstrings.h"

#include "dlvaracc.h"

static SDL_CD * sdl_cd = NULL;
static int      sdl_cdnum = -1;

/* ----------------------------------------------------------------- */

#define CD_TRACK        0
#define CD_FRAME        1
#define CD_TRACKS       2
#define CD_MINUTE       3
#define CD_SECOND       4
#define CD_SUBFRAME     5
#define CD_MINUTES      6
#define CD_SECONDS      7
#define CD_FRAMES       8
#define CD_TRACKINFO    9     /* 400 INTs */

/* ----------------------------------------------------------------- */
/* Definicion de constantes (usada en tiempo de compilacion)         */
DLCONSTANT  constants_def[] =
{
    { "CD_TRAYEMPTY", TYPE_INT, 0  },
    { "CD_STOPPED"  , TYPE_INT, 1  },
    { "CD_PLAYING"  , TYPE_INT, 2  },
    { "CD_PAUSED"   , TYPE_INT, 3  },
    { "CD_ERROR"    , TYPE_INT, -1 },
    { NULL          , 0       , 0  }
} ;

/* ----------------------------------------------------------------- */
/* Definicion de variables globales (usada en tiempo de compilacion) */
char * globals_def =
                    "   STRUCT cdinfo \n"
                    "       current_track; \n"
                    "       current_frame; \n"
                    "       tracks; \n"
                    "       minute; \n"
                    "       second; \n"
                    "       subframe; \n"
                    "       minutes; \n"
                    "       seconds; \n"
                    "       subframes; \n"
                    "       STRUCT track[99] \n"
                    "              audio; \n"
                    "              minutes; \n"
                    "              seconds; \n"
                    "              subframes; \n"
                    "       END; \n"
                    "   END; \n" ;

/* ----------------------------------------------------------------- */
/* Son las variables que se desea acceder.                           */
/* El interprete completa esta estructura, si la variable existe.    */
/* (usada en tiempo de ejecucion)                                    */
DLVARFIXUP  globals_fixup[] =   {
    /* Nombre de variable global, puntero al dato, tamaño del elemento, cantidad de elementos */
                                { "cdinfo.current_track", NULL, -1, -1 },
                                { "cdinfo.current_frame", NULL, -1, -1 },
                                { "cdinfo.tracks", NULL, -1, -1 },
                                { "cdinfo.minute", NULL, -1, -1 },
                                { "cdinfo.second", NULL, -1, -1 },
                                { "cdinfo.subframe", NULL, -1, -1 },
                                { "cdinfo.minutes", NULL, -1, -1 },
                                { "cdinfo.seconds", NULL, -1, -1 },
                                { "cdinfo.subframes", NULL, -1, -1 },
                                { "cdinfo.track", NULL, -1, -1 },
                                { NULL, NULL, -1, -1 }
                                };

/* ----------------------------------------------------------------- */
/**
   int CD_DRIVES()
   Returns the number of CD drives in the system
**/

static int modcd_drives (INSTANCE * my, int * params)
{
   return SDL_CDNumDrives();
}

/**
   int CD_STATUS (int CD)
   Returns the status of a CD (using SDL constants)
**/

static int modcd_status (INSTANCE * my, int * params)
{
   if (params[0] < 0 || params[0] >= SDL_CDNumDrives()) return 0;

   if (sdl_cd == NULL || sdl_cdnum != params[0])
   {
      if (sdl_cd) SDL_CDClose(sdl_cd);
      sdl_cd = SDL_CDOpen(params[0]);
      if (sdl_cd == NULL) return 0;
      sdl_cdnum = params[0];
   }

   return SDL_CDStatus(sdl_cd);

}

/**
   string CD_NAME (int CD)
   Returns a human-readable string with the name of a CD drive
**/

static int modcd_name (INSTANCE * my, int * params)
{
   int result;

   if (params[0] < 0 || params[0] >= SDL_CDNumDrives()) return 0;

   result = string_new(SDL_CDName(params[0]));
   string_use(result);
   return result;
}

/**
   CD_GETINFO(int CD)
   Fills the global structure CD with information about the current CD
   Returns 1 if there is a valid CD in the drive or 0 otherwise
**/

static int modcd_getinfo (INSTANCE * my, int * params)
{
   int i, pos, total = 0;
   char * trackinfo;

   if (params[0] < 0 || params[0] >= SDL_CDNumDrives()) return 0;

   if (sdl_cd == NULL || sdl_cdnum != params[0])
   {
      if (sdl_cd) SDL_CDClose(sdl_cd);
      sdl_cd = SDL_CDOpen(params[0]);
      if (sdl_cd == NULL) return 0;
      sdl_cdnum = params[0];
   }

   GLODWORD(CD_TRACKS) = sdl_cd->numtracks;
   GLODWORD(CD_TRACK)  = sdl_cd->cur_track;
   FRAMES_TO_MSF (sdl_cd->cur_frame, &GLODWORD(CD_MINUTE), &GLODWORD(CD_SECOND), &GLODWORD(CD_SUBFRAME));

   trackinfo = &GLODWORD(CD_TRACKINFO);

   for (i = 0; i < sdl_cd->numtracks ; i++, trackinfo += 16)
   {
      total += sdl_cd->track.length;
      *(Uint32 *) trackinfo = (sdl_cd->track.type == SDL_AUDIO_TRACK);
      FRAMES_TO_MSF (sdl_cd->track.length, trackinfo+4, trackinfo+8, trackinfo+12);
   }
   FRAMES_TO_MSF (total, &GLODWORD(CD_MINUTES), &GLODWORD(CD_SECONDS), &GLODWORD(CD_FRAMES));
   return 1;
}

/**
   CD_PLAY (int CD, int TRACK)
   Starts playing a track of the given CD
**/

static int modcd_play (INSTANCE * my, int * params)
{
   if (params[0] < 0 || params[0] >= SDL_CDNumDrives()) return 0;

   if (sdl_cd == NULL || sdl_cdnum != params[0])
   {
      if (sdl_cd) SDL_CDClose(sdl_cd);
      sdl_cd = SDL_CDOpen(params[0]);
      if (sdl_cd == NULL) return 0;
      sdl_cdnum = params[0];
   }

   if (CD_INDRIVE(SDL_CDStatus(sdl_cd)))
      return !SDL_CDPlayTracks(sdl_cd, params[1], 0, 1, 0);

   return 0;
}

/**
   CD_PLAY (int CD, int TRACK, int NUMTRACKS)
   Plays a series of tracks of the CD
**/

static int modcd_playtracks (INSTANCE * my, int * params)
{
   if (params[0] < 0 || params[0] >= SDL_CDNumDrives()) return 0;

   if (sdl_cd == NULL || sdl_cdnum != params[0])
   {
      if (sdl_cd) SDL_CDClose(sdl_cd);
      sdl_cd = SDL_CDOpen(params[0]);
      if (sdl_cd == NULL) return 0;
      sdl_cdnum = params[0];
   }

   if (CD_INDRIVE(SDL_CDStatus(sdl_cd)))
      return !SDL_CDPlayTracks(sdl_cd, params[1], 0, params[2], 0);

   return 0;
}

/**
   CD_EJECT (int CD)
   Ejects a CD
**/

static int modcd_eject (INSTANCE * my, int * params)
{
   if (params[0] < 0 || params[0] >= SDL_CDNumDrives()) return 0;

   if (sdl_cd == NULL || sdl_cdnum != params[0])
   {
      if (sdl_cd) SDL_CDClose(sdl_cd);
      sdl_cd = SDL_CDOpen(params[0]);
      if (sdl_cd == NULL) return 0;
      sdl_cdnum = params[0];
   }

   return !SDL_CDEject(sdl_cd);
}

/**
   CD_PAUSE (int CD)
   Pauses the CD playing
**/

static int modcd_pause (INSTANCE * my, int * params)
{
   if (params[0] < 0 || params[0] >= SDL_CDNumDrives()) return 0;

   if (sdl_cd == NULL || sdl_cdnum != params[0])
   {
      if (sdl_cd) SDL_CDClose(sdl_cd);
      sdl_cd = SDL_CDOpen(params[0]);
      if (sdl_cd == NULL) return 0;
      sdl_cdnum = params[0];
   }

   return !SDL_CDPause(sdl_cd);
}

/**
   CD_RESUME (int CD)
   Resumes a CD in pause
**/

static int modcd_resume (INSTANCE * my, int * params)
{
   if (params[0] < 0 || params[0] >= SDL_CDNumDrives()) return 0;

   if (sdl_cd == NULL || sdl_cdnum != params[0])
   {
      if (sdl_cd) SDL_CDClose(sdl_cd);
      sdl_cd = SDL_CDOpen(params[0]);
      if (sdl_cd == NULL) return 0;
      sdl_cdnum = params[0];
   }

   return !SDL_CDResume(sdl_cd);
}

/**
   CD_STOP (int CD)
   Stops the CD
**/

static int modcd_stop (INSTANCE * my, int * params)
{
   if (params[0] < 0 || params[0] >= SDL_CDNumDrives()) return 0;

   if (sdl_cd == NULL || sdl_cdnum != params[0])
   {
      if (sdl_cd) SDL_CDClose(sdl_cd);
      sdl_cd = SDL_CDOpen(params[0]);
      if (sdl_cd == NULL) return 0;
      sdl_cdnum = params[0];
   }

   return !SDL_CDStop(sdl_cd);
}

/* ---------------------------------------------------------------------- */

DLSYSFUNCS  functions_exports[] = {
    /* Funciones de manejo de CD */
    { "CD_DRIVES"   , ""      , TYPE_INT    , modcd_drives     },
    { "CD_STATUS"   , "I"     , TYPE_INT    , modcd_status     },
    { "CD_NAME"     , "I"     , TYPE_STRING , modcd_name       },
    { "CD_GETINFO"  , "I"     , TYPE_INT    , modcd_getinfo    },
    { "CD_PLAY"     , "II"    , TYPE_INT    , modcd_play       },
    { "CD_PLAY"     , "III"   , TYPE_INT    , modcd_playtracks },
    { "CD_STOP"     , "I"     , TYPE_INT    , modcd_stop       },
    { "CD_PAUSE"    , "I"     , TYPE_INT    , modcd_pause      },
    { "CD_RESUME"   , "I"     , TYPE_INT    , modcd_resume     },
    { "CD_EJECT"    , "I"     , TYPE_INT    , modcd_eject      },
    { 0             , 0       , 0           , 0                }
};

/* ----------------------------------------------------------------- */
/* Funciones de inicializacion del modulo/plugin                     */

int module_initialize()
{
    if (!SDL_WasInit(SDL_INIT_CDROM))
        SDL_InitSubSystem (SDL_INIT_CDROM);
    return 0; // OK
}

/* ----------------------------------------------------------------- */

int module_finalize()
{
    return 0; // OK
}
[/code]

dlvaracc.h

[code language="c"]
#ifndef _DLVARACC_H
    #define _DLVARACC_H

    #undef LOCDWORD
    #undef LOCWORD
    #undef LOCBYTE

    #undef GLODWORD
    #undef GLOWORD
    #undef GLOBYTE

    /* Macros para acceder a datos locales de una instancia */
    #define LOCDWORD(a,b) (*(Sint32 *)((Uint8 *)(a->locdata) + (Uint32)locals_fixup.data_offset))
    #define LOCWORD(a,b)  (*(Uint16 *)((Uint8 *)(a->locdata) + (Uint32)locals_fixup.data_offset))
    #define LOCBYTE(a,b)  (*(Uint8  *)((Uint8 *)(a->locdata) + (Uint32)locals_fixup.data_offset))

    /* Macros para acceder a datos globales */
    #define GLODWORD(b)   (*(Sint32 *)(globals_fixup.data_offset))
    #define GLOWORD(b)    (*(Uint16 *)(globals_fixup.data_offset))
    #define GLOBYTE(b)    (*(Uint8  *)(globals_fixup.data_offset))

#endif
[/code]
Download Lastest BennuGD Release: http://www.bennugd.org/node/2