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:
add an /* $Id$ */ comment in front of each file
add a documentation of the function using doxygen syntax
add local VDIPB definition, optimised for each binding. The local VDIPB is used only if USE_LOCAL_VDIPB is set to 1 (see gem_vdiP.h)
Notice diffs between gemlib and mgemlib binding, to track remaining bugs. Sometimes, both gemlib and mgemlib were wrong... so the bug have to be fixed.
write down diffs noticed in the file « gemlib.todo »
Ok, enought words, here is an example: the binding of vsl_color.
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]); } |
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<<16)|cntrl_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]; } |
The file gem_vdiP.h
/* * $Id: gem_vdiP.h,v 1.4.4.1 2002/12/28 18:58:33 a_bercegeay Exp $ */ #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)) #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<<16)|cntrl_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
/* * $Id: vsl_color.c,v 1.4.4.1 2002/12/28 18:48:46 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]; VDIPB vdi_params = { &vdi_control[0], /* vdi_control */ &index, /* vdi_intin */ 0L, /* vdi_ptsin */ &vdi_intout[0], /* vdi_intout */ 0L /* vdi_ptsout */ }; #else vdi_intin[0] = index; #endif VDI_TRAP (vdi_params, handle, 17, 0,1); return vdi_intout[0]; } |