GEMlib
Work done on VDI bindings

VDI bindings in gemlib and mgemlib are quite similar (the main diff is the use of inline asm trap in gemlib). A big part of the work was to include local VDIPB structure in each binding, and make the (now local) vdi_intin, vdi_intout, vdi_ptsin and vdi_ptsout array size as small as possible. (AFAIK, AES userdefined object are drawn using VDI functions, and in such context, the stack used is the « system » stack, which is small on single-TOS).

The next major gemlib release is based on gemlib (for VDI bindings). The modifications are listed below:

Ok, enought words, here is an example: the binding of vsl_color().

vcl_color() binding from MGEMLIB 41

Extract form v_attrib.c
int vsl_color (int handle, int index)
{
    vdi_intin[0] = index;

    vdi_control[0] = 17;
    vdi_control[1] = vdi_control[5] = 0;
    vdi_control[3] = 1;
    vdi_control[6] = handle;

    vdi (&vdi_params);

    return ((int)vdi_intout[0]);
}

vsl_color() binding from GEMLIB 0.42.2

The file gem_vdiP.h
/*
 * gem_vdiP.h -- VDI trap interface
 *
 *    <AltF4@freemint.de>
 */

#ifndef _GEM_VDI_P_
# define _GEM_VDI_P_

# ifndef _GEMLIB_H_
#  include "gem.h"
# endif


#define vdi_control_ptr(n)   *((void**)(vdi_control +n))
#define vdi_intin_ptr(n)     *((void**)(vdi_intin   +n))
#define vdi_intout_long(n)   *((long*) (vdi_intout  +n))


#if defined(__GNUC_INLINE__) && (__GNUC__ > 2 ¦¦ __GNUC_MINOR__ > 5)

static inline void
_vdi_trap_esc (VDIPB * vdipb,
               long cntrl_0_1, long cntrl_3, long cntrl_5, short handle)
{
       __asm__ volatile ("
              movea.l %0, a0;    ¦ &vdipb
              move.l  a0, d1;
              move.l  (a0), a0;  ¦ vdipb->control
              move.l  %1, (a0)+; ¦ cntrl_0, cntrl_1
              move.l  %2, (a0)+; ¦ cntrl_2, cntrl_3
              move.l  %3, (a0)+; ¦ cntrl_4, cntrl_5
              move.w  %4, (a0);  ¦ handle
              move.w  #115, d0;  ¦ 0x0073
              trap    #2;
              "
              :
              : "a"(vdipb), "g"(cntrl_0_1), "g"(cntrl_3), "g"(cntrl_5), "g"(handle)
              : "a0", "d0","d1"
       );
}
#define VDI_TRAP_ESC(vdipb, handle, opcode, subop, cntrl_1, cntrl_3) \
       _vdi_trap_esc (&vdipb, (opcode##uL<<16cntrl_1, cntrl_3, subop, handle)

static inline void
_vdi_trap_00 (VDIPB * vdipb, long cntrl_0_1, short handle)
{
       __asm__ volatile ("
              movea.l %0, a0;    ¦ &vdipb
              move.l  a0, d1;
              move.l  (a0), a0;  ¦ vdipb->control
              move.l  %1, (a0)+; ¦ cntrl_0, cntrl_1
              eor.l   d0, d0;
              move.l  d0, (a0)+; ¦ cntrl_2, cntrl_3
              move.l  d0, (a0)+; ¦ cntrl_4, cntrl_5
              move.w  %2, (a0);  ¦ handle
              move.w  #115, d0;  ¦ 0x0073
              trap    #2;
              "
              :
              : "a"(vdipb), "g"(cntrl_0_1), "g"(handle)
              : "a0", "d0","d1"
       );
}
#define VDI_TRAP_00(vdipb, handle, opcode) \
       _vdi_trap_00 (&vdipb, (opcode##uL<<16), handle)


#else /* no usage of gnu inlines, go the old way */

#define VDI_TRAP_ESC(vdipb, handle, opcode, subop, cntrl_1, cntrl_3) \
       vdi_control[0] = opcode;  \
       vdi_control[1] = cntrl_1; \
       vdi_control[3] = cntrl_3; \
       vdi_control[5] = subop;   \
       vdi_control[6] = handle;  \
       vdi (&vdipb);

#define VDI_TRAP_00(vdipb, handle, opcode) \
       VDI_TRAP_ESC (vdipb, handle, opcode, 0, 0, 0)
#endif


#define VDI_TRAP(vdipb, handle, opcode, cntrl_1, cntrl_3) \
       VDI_TRAP_ESC(vdipb, handle, opcode, 0, cntrl_1, cntrl_3)


# endif /* _GEM_VDI_P_ */

The file vsl_color.c
/*
 *   line attribute
 */

#include "gem_vdiP.h"


short
vsl_color (short handle, short index)
{
    vdi_intin[0] = index;

    VDI_TRAP (vdi_params, handle, 17, 0,1);

    return vdi_intout[0];
}

vsl_color() binding of the next GEMlib release

The file gem_vdiP.h
/*
 *  $Id: gem_vdiP.h,v 1.4.4.3 2003/02/16 20:57:41 a_bercegeay Exp $
 */

#ifndef _GEM_VDI_P_
# define _GEM_VDI_P_

# ifndef _GEMLIB_H_
#  include "mt_gem.h"
# endif


#define vdi_control_ptr(n)   *((void**)(vdi_control +n))
#define vdi_intin_ptr(n)     *((void**)(vdi_intin   +n))
#define vdi_intout_long(n)   *((long*) (vdi_intout  +n))

#define USE_LOCAL_VDIPB 1

#if defined(__GNUC_INLINE__) && (__GNUC__ > 2 ¦¦ __GNUC_MINOR__ > 5)

static inline void
_vdi_trap_esc (VDIPB * vdipb,
               long cntrl_0_1, long cntrl_3, long cntrl_5, short handle)
{
       __asm__ volatile ("
              movea.l %0, a0;    ¦ &vdipb
              move.l  a0, d1;
              move.l  (a0), a0;  ¦ vdipb->control
              move.l  %1, (a0)+; ¦ cntrl_0, cntrl_1
              move.l  %2, (a0)+; ¦ cntrl_2, cntrl_3
              move.l  %3, (a0)+; ¦ cntrl_4, cntrl_5
              move.w  %4, (a0);  ¦ handle
              move.w  #115, d0;  ¦ 0x0073
              trap    #2;
              "
              :
              : "a"(vdipb), "g"(cntrl_0_1), "g"(cntrl_3), "g"(cntrl_5), "g"(handle)
              : "a0", "d0","d1"
       );
}
#define VDI_TRAP_ESC(vdipb, handle, opcode, subop, cntrl_1, cntrl_3) \
       _vdi_trap_esc (&vdipb, (opcode##uL<<16cntrl_1, cntrl_3, subop, handle)

static inline void
_vdi_trap_00 (VDIPB * vdipb, long cntrl_0_1, short handle)
{
       __asm__ volatile ("
              movea.l %0, a0;    ¦ &vdipb
              move.l  a0, d1;
              move.l  (a0), a0;  ¦ vdipb->control
              move.l  %1, (a0)+; ¦ cntrl_0, cntrl_1
              eor.l   d0, d0;
              move.l  d0, (a0)+; ¦ cntrl_2, cntrl_3
              move.l  d0, (a0)+; ¦ cntrl_4, cntrl_5
              move.w  %2, (a0);  ¦ handle
              move.w  #115, d0;  ¦ 0x0073
              trap    #2;
              "
              :
              : "a"(vdipb), "g"(cntrl_0_1), "g"(handle)
              : "a0", "d0","d1"
       );
}
#define VDI_TRAP_00(vdipb, handle, opcode) \
       _vdi_trap_00 (&vdipb, (opcode##uL<<16), handle)


#else /* no usage of gnu inlines, go the old way */

#define VDI_TRAP_ESC(vdipb, handle, opcode, subop, cntrl_1, cntrl_3) \
       vdi_control[0] = opcode;  \
       vdi_control[1] = cntrl_1; \
       vdi_control[3] = cntrl_3; \
       vdi_control[5] = subop;   \
       vdi_control[6] = handle;  \
       vdi (&vdipb);

#define VDI_TRAP_00(vdipb, handle, opcode) \
       VDI_TRAP_ESC (vdipb, handle, opcode, 0, 0, 0)
#endif


#define VDI_TRAP(vdipb, handle, opcode, cntrl_1, cntrl_3) \
       VDI_TRAP_ESC(vdipb, handle, opcode, 0, cntrl_1, cntrl_3)

#define VDI_PARAMS(a,b,c,d,e) \
       VDIPB vdi_params;         \
       vdi_params.control = a;   \
       vdi_params.intin   = b;   \
       vdi_params.ptsin   = c;   \
       vdi_params.intout  = d;   \
       vdi_params.ptsout  = e;


# endif /* _GEM_VDI_P_ */

The file vsl_color.c
/*
 *  $Id: vsl_color.c,v 1.4.4.2 2003/02/16 20:19:07 a_bercegeay Exp $
 */

#include "gem_vdiP.h"

/** sets the color index for lines
 *
 *  @param handle Device handle
 *  @param index requested line color. If the index is invalid, color index 1
 *         will be selected.
 *
 *  @return realized line color
 *
 *  @since all VDI versions
 */

short
vsl_color (short handle, short index)
{
#if USE_LOCAL_VDIPB
    short vdi_control[VDI_CNTRLMAX]; 
    short vdi_intout[1]; 
    VDI_PARAMS(vdi_control, &index, 0L, vdi_intout, 0L );
#else
    vdi_intin[0] = index;
#endif

    VDI_TRAP (vdi_params, handle, 17, 0,1);

    return vdi_intout[0];
}