/***************************************************************************
 *                                                                         *
 * Module  : drvmodel.h (sky)                                              *
 *                                                                         *
 * Purpose : Driver model description (device specific vertices/polys)     *
 *                                                                         *
 **************************************************************************/

/* RWPUBLIC */
#ifndef SKY2_DRVMODEL_H
#define SKY2_DRVMODEL_H

/**
 * \defgroup driversky2 PS2
 * \ingroup rwcore
 *
 * PS2 drivers
 */

/**
 * \defgroup sky2unsupported Unsupported PS2 Functions
 * \ingroup driversky2
 *
 * Unsupported functions
 */

/* RWPUBLICEND */

/****************************************************************************
 Includes
 */

#include "batypes.h"
#include "bacolor.h"
#include "skygeneric.h"

/* Lets hope that gcc's constant folding works */

/* RWPUBLIC */
#ifndef _RW_EETYPES_H
#define _RW_EETYPES_H
#include <eetypes.h>
#endif /* _RW_EETYPES_H */

/****************************************************************************
 Defines
 */

/* Global size */
#define RWGLOBALSIZE (16*1024)

/* Cache Control */
 /* Normal adaptive LRU/MRU algorithm operation */
#define RWSKYCACHENORMAL    0  
/* Manual override, textures used while set are 
 * first candidates of purging (MRU) */
#define RWSKYCACHESTATIC    1   

/* Number of frames to average metrics over */
#define rwSKYMETRICSSAMPLES 8
/* log2 of number of frames per sample */
#define rwSKYMETRICSFRAMESPERSAMPLE 1

/* Metrowerks don't yet support this so guard */
#if (!defined(__MWERKS__))

#define RwFastRealToUInt32(valIn)               \
({                                              \
    float tmpFloat;                             \
    float floatIn = valIn;                      \
    RwUInt32 _result;                           \
                                                \
    __asm__  ("cvt.w.s %0, %2 \n                \
                       mfc1 %1, %0 \n           \
                  " : "=f" (tmpFloat),          \
                      "=r&" (_result)           \
                    : "f" (floatIn));           \
    _result;                                    \
})

#endif /* (!defined(__MWERKS__)) */

/* For now. Assumes inline does the right thing */
#if (defined(__MWERKS__)) && (!defined(RWDEBUG))

/* elided */

#endif /* (defined(__MWERKS__)) && (!defined(RWDEBUG)) */

#if (!defined(RwFastRealToUInt32))

#if (defined(__MWERKS__))
#if ( __MWERKS__ >= 0x2401)
/*
 * The following pragma is implemented in the MW 2.4 Compiler only:
 * - #pragma fast_fptosi on|off|reset
 * enabling this pragma will generate cvt.w.s instruction to
 * replace runtime function _fptosi.
 */
#pragma fast_fptosi on
#endif /* ( __MWERKS__ >= 0x2401)  */
#endif /* (defined(__MWERKS__)) */

#define RwFastRealToUInt32(valIn) ((RwUInt32)((RwReal)(valIn)))
#endif /* (!defined(RwFastRealToUInt32)) */

/* Set true depth information (for fogging, eg) */
/* I'm making this much like the Windows one, as we have to make RW4 apps */
/* less dependent of loads of fields set all over the place */

#define RwIm2DVertexSetCameraX(vert, camx)              \
     /* Nothing */
#define RwIm2DVertexSetCameraY(vert, camy)              \
     /* Nothing */
#define RwIm2DVertexSetCameraZ(vert, camz)              \
     ((vert)->u.els.camVertex_z = (camz))
#define RwIm2DVertexSetRecipCameraZ(vert, recipz)       \
    ((vert)->u.els.recipZ = (recipz))

#define RwIm2DVertexGetCameraX(vert)                    \
    (Bang!)
#define RwIm2DVertexGetCameraY(vert)                    \
    (Bang!)
#define RwIm2DVertexGetCameraZ(vert)                    \
    ((vert)->u.els.camVertex_z)
#define RwIm2DVertexGetRecipCameraZ(vert)               \
    ((vert)->u.els.recipZ)

/* Set screen space coordinates in a device vertex */
#define RwIm2DVertexSetScreenX(vert, scrnx)             \
    ((vert)->u.els.scrVertex.x = (scrnx))
#define RwIm2DVertexSetScreenY(vert, scrny)             \
    ((vert)->u.els.scrVertex.y = (scrny))
#define RwIm2DVertexSetScreenZ(vert, scrnz)             \
    ((vert)->u.els.scrVertex.z = (scrnz))
#define RwIm2DVertexGetScreenX(vert)                    \
    ((vert)->u.els.scrVertex.x)
#define RwIm2DVertexGetScreenY(vert)                    \
    ((vert)->u.els.scrVertex.y)
#define RwIm2DVertexGetScreenZ(vert)                    \
    ((vert)->u.els.scrVertex.z)

/* Set texture coordinates in a device vertex */
#define RwIm2DVertexSetU(vert, texu, recipz)            \
    ((vert)->u.els.u = (texu))
#define RwIm2DVertexSetV(vert, texv, recipz)            \
    ((vert)->u.els.v = (texv))
#define RwIm2DVertexGetU(vert)                          \
    ((vert)->u.els.u)
#define RwIm2DVertexGetV(vert)                          \
    ((vert)->u.els.v)

/* Modify the luminance stuff */
#define RwIm2DVertexSetRealRGBA(vert, r, g, b, a)       \
MACRO_START                                             \
{                                                       \
    ((vert)->u.els.color.red = (r));                    \
    ((vert)->u.els.color.green = (g));                  \
    ((vert)->u.els.color.blue = (b));                   \
    ((vert)->u.els.color.alpha = (a));                  \
}                                                       \
MACRO_STOP

#define RwIm2DVertexSetIntRGBA(vert, r, g, b, a)        \
MACRO_START                                             \
{                                                       \
    ((vert)->u.els.color.red = (RwReal)(r));            \
    ((vert)->u.els.color.green = (RwReal)(g));          \
    ((vert)->u.els.color.blue = (RwReal)(b));           \
    ((vert)->u.els.color.alpha = (RwReal)(a));          \
}                                                       \
MACRO_STOP

#define RwIm2DVertexGetRed(vert)       \
    ((RwUInt32)((vert)->u.els.color.red))

#define RwIm2DVertexGetGreen(vert)     \
    ((RwUInt32)((vert)->u.els.color.green))

#define RwIm2DVertexGetBlue(vert)      \
    ((RwUInt32)((vert)->u.els.color.blue))

#define RwIm2DVertexGetAlpha(vert)     \
    ((RwUInt32)((vert)->u.els.color.alpha))

#define RwIm2DVertexCopyRGBA(dst, src) \
    ((dst)->u.els.color = (src)->u.els.color)

/* Clipper stuff */
/* We don't use the clipper here, so it does something really noddy */
/* Yeah, thanks for that. :-( -- Simon */

#define RwIm2DVertexClipRGBA(out, interp, near, far)                      \
MACRO_START                                                               \
{                                                                         \
    RwInt32 fixinterp =                                                   \
        (RwInt32) /* floor */ (((interp) * 65536.0f) + 0.5f); /* 16:0 */  \
                                                                          \
    ((out)->u.els.color.red   =                                           \
     (near)->u.els.color.red   +                                          \
     ((((RwInt32) ((far)->u.els.color.red  -(near)->u.els.color.red  )) * \
       fixinterp + 32768) >> 16));                                        \
                                                                          \
    ((out)->u.els.color.green =                                           \
     (near)->u.els.color.green +                                          \
     ((((RwInt32) ((far)->u.els.color.green-(near)->u.els.color.green)) * \
       fixinterp + 32768) >> 16));                                        \
                                                                          \
    ((out)->u.els.color.blue  =                                           \
     (near)->u.els.color.blue  +                                          \
     ((((RwInt32) ((far)->u.els.color.blue -(near)->u.els.color.blue )) * \
       fixinterp + 32768) >> 16));                                        \
                                                                          \
    ((out)->u.els.color.alpha =                                           \
     (near)->u.els.color.alpha +                                          \
     ((((RwInt32) ((far)->u.els.color.alpha-(near)->u.els.color.alpha)) * \
       fixinterp + 32768) >> 16));                                        \
}                                                                         \
MACRO_STOP

/* LEGACY-SUPPORT macros */
#define RWIM2DVERTEXSetCameraX(_v, _cx)  RwIm2DVertexSetCameraX(_v, _cx)
#define RWIM2DVERTEXSetCameraY(_v, _cy)  RwIm2DVertexSetCameraY(_v, _cy)
#define RWIM2DVERTEXSetCameraZ(_v, _cz)  RwIm2DVertexSetCameraZ(_v, _cz)
#define RWIM2DVERTEXSetRecipCameraZ(_v, _rz) \
                                         RwIm2DVertexSetRecipCameraZ(_v, _rz)
#define RWIM2DVERTEXGetCameraX(_v)       RwIm2DVertexGetCameraX(_v)
#define RWIM2DVERTEXGetCameraY(_v)       RwIm2DVertexGetCameraY(_v)
#define RWIM2DVERTEXGetCameraZ(_v)       RwIm2DVertexGetCameraZ(_v)
#define RWIM2DVERTEXGetRecipCameraZ(_v)  RwIm2DVertexGetRecipCameraZ(_v)
#define RWIM2DVERTEXSetScreenX(_v, _sx)  RwIm2DVertexSetScreenX(_v, _sx)
#define RWIM2DVERTEXSetScreenY(_v, _sy)  RwIm2DVertexSetScreenY(_v, _sy)
#define RWIM2DVERTEXSetScreenZ(_v, _sz)  RwIm2DVertexSetScreenZ(_v, _sz)
#define RWIM2DVERTEXGetScreenX(_v)       RwIm2DVertexGetScreenX(_v)
#define RWIM2DVERTEXGetScreenY(_v)       RwIm2DVertexGetScreenY(_v)
#define RWIM2DVERTEXGetScreenZ(_v)       RwIm2DVertexGetScreenZ(_v)
#define RWIM2DVERTEXSetU(_v, u, _rz)     RwIm2DVertexSetU(_v, u, _rz)
#define RWIM2DVERTEXSetV(_v, v, _rz)     RwIm2DVertexSetV(_v, v, _rz)
#define RWIM2DVERTEXGetU(_v)             RwIm2DVertexGetU(_v)
#define RWIM2DVERTEXGetV(_v)             RwIm2DVertexGetV(_v)
#define RWIM2DVERTEXSetRealRGBA(_v, _r, _g, _b, _a) \
                                RwIm2DVertexSetRealRGBA(_v, _r, _g, _b, _a)
#define RWIM2DVERTEXSetIntRGBA(_v, _r, _g, _b, _a)  \
                                 RwIm2DVertexSetIntRGBA(_v, _r, _g, _b, _a)
#define RWIM2DVERTEXGetRed(_v)           RwIm2DVertexGetRed(_v)
#define RWIM2DVERTEXGetGreen(_v)         RwIm2DVertexGetGreen(_v)
#define RWIM2DVERTEXGetBlue(_v)          RwIm2DVertexGetBlue(_v)
#define RWIM2DVERTEXGetAlpha(_v)         RwIm2DVertexGetAlpha(_v)
#define RWIM2DVERTEXCopyRGBA(dst, src)   RwIm2DVertexCopyRGBA(dst, src)
#define RWIM2DVERTEXClipRGBA(o, i, n, f) RwIm2DVertexClipRGBA(o, i, n, f)

#undef rwInvSqrtOldMacro
#define rwInvSqrtOldMacro(_recip, _input)                                 \
MACRO_START                                                               \
{                                                                         \
    if ((_input) !=0)                                                     \
    {                                                                     \
        static const float _one = 1.0f;                                   \
        asm ("rsqrt.s %0, %1, %2" :                                       \
                      "=f" (_recip) : "f" (_one) , "f" (_input) : "cc");  \
    }                                                                     \
    else                                                                  \
    {                                                                     \
        (_recip) = (_input);                                              \
    }                                                                     \
}                                                                         \
MACRO_STOP

#undef rwSqrtMacro
#undef rwInvSqrtMacro
#undef rwSqrtInvSqrtMacro

#if (defined(__MWERKS__))

/*
 * mwccps2 doesn't like having a '.' in the name of an assembler
 * result variable, so go via "_result" to be on the safe side ..
 */

#define rwSqrtMacro(_root, _input)                                        \
MACRO_START                                                               \
{                                                                         \
    RwReal  _result = (RwReal)0;                                          \
    RwReal  _tmp = _input;                                                \
    asm ("sqrt.s %0, %1" : "=f" (_result) : "f" (_tmp) : "cc");           \
    _root = _result;                                                      \
}                                                                         \
MACRO_STOP

#define rwInvSqrtMacro(_recip, _input)                                    \
MACRO_START                                                               \
{                                                                         \
    RwReal  _result = (RwReal)0;                                          \
    asm ("sqrt.s %0, %1" : "=f" (_result) : "f" (_input) : "cc");         \
    (_recip) = (_result > 0) ? ( ((RwReal)1)/(_result) ) : (_result);     \
}                                                                         \
MACRO_STOP

#define rwSqrtInvSqrtMacro(_root, _recip, _input)                         \
MACRO_START                                                               \
{                                                                         \
    RwReal  _result = (RwReal)0;                                          \
    asm ("sqrt.s %0, %1" : "=f" (_result) : "f" (_input) : "cc");         \
    _root = _result;                                                      \
    (_recip) = (_root > 0) ? ( ((RwReal)1)/(_root) ) : (_root);           \
}                                                                         \
MACRO_STOP

#endif /* (defined(__MWERKS__)) */

#if (!defined(rwSqrtMacro))
#define rwSqrtMacro(_root, _input)                                        \
MACRO_START                                                               \
{                                                                         \
    asm ("sqrt.s %0, %1" : "=f" (_root) : "f" (_input) : "cc");           \
}                                                                         \
MACRO_STOP
#endif /* (!defined(rwSqrtMacro)) */

#if (!defined(rwInvSqrtMacro))
#define rwInvSqrtMacro(_recip, _input)                                    \
MACRO_START                                                               \
{                                                                         \
    asm ("sqrt.s %0, %1" : "=f" (_recip) : "f" (_input) : "cc");          \
    (_recip) = (_recip > 0) ? ( ((RwReal)1)/(_recip) ) : (_recip);        \
}                                                                         \
MACRO_STOP
#endif /* (!defined(rwInvSqrtMacro)) */

#if (!defined(rwSqrtInvSqrtMacro))
#define rwSqrtInvSqrtMacro(_root, _recip, _input)                         \
MACRO_START                                                               \
{                                                                         \
    asm ("sqrt.s %0, %1" : "=f" (_root) : "f" (_input) : "cc");           \
    _root = _root;                                                        \
    (_recip) = (_root > 0) ? ( ((RwReal)1)/(_root) ) : (_root);           \
}                                                                         \
MACRO_STOP
#endif /* (!defined(rwSqrtInvSqrtMacro)) */

#if (!defined(USEINTVAR))
#if (defined(__MWERKS__))
/* Stop CW complaining about variables being unused if they are used, 
 * but only in inline asm */
#define USEINTVAR(_var) ((0)?((_var) = 0):(0))
#else /* (defined(__MWERKS__)) */
#define USEINTVAR(_var) /* No op */
#endif /* (defined(__MWERKS__)) */
#endif /* (!defined(USEINTVAR)) */

#define RwMatrixMultiplyVUMacro(_matrix, _matrixIn1, _matrixIn2)    \
MACRO_START                                                         \
{                                                                   \
    int __tmp1, __tmp2;                                             \
    USEINTVAR(__tmp1);                                              \
    USEINTVAR(__tmp2);                                              \
                                                                    \
    asm __volatile__ (".set noreorder                               \n\
        lqc2        vf1,  0x00(%2)                                  \n\
        lqc2        vf2,  0x10(%2)                                  \n\
        lqc2        vf3,  0x20(%2)                                  \n\
        lqc2        vf4,  0x30(%2)                                  \n\
        lwu         %0,   0x0C(%2)                                  \n\
        lqc2        vf5,  0x00(%3)                                  \n\
        lqc2        vf6,  0x10(%3)                                  \n\
        lqc2        vf7,  0x20(%3)                                  \n\
        lqc2        vf8,  0x30(%3)                                  \n\
        lwu         %1,   0x0C(%3)                                  \n\
        vmulax.xyz  ACC,  vf5, vf1                                  \n\
        vmadday.xyz ACC,  vf6, vf1                                  \n\
        vmaddz.xyz  vf9,  vf7, vf1                                  \n\
        vmulax.xyz  ACC,  vf5, vf2                                  \n\
        vmadday.xyz ACC,  vf6, vf2                                  \n\
        vmaddz.xyz  vf10, vf7, vf2                                  \n\
        vmulax.xyz  ACC,  vf5, vf3                                  \n\
        vmadday.xyz ACC,  vf6, vf3                                  \n\
        vmaddz.xyz  vf11, vf7, vf3                                  \n\
        vmulax.xyz  ACC,  vf5, vf4                                  \n\
        vmadday.xyz ACC,  vf6, vf4                                  \n\
        vmaddaz.xyz ACC,  vf7, vf4                                  \n\
        vmaddw.xyz  vf12, vf8, vf0                                  \n\
        and         %1, %1, %0                                      \n\
        sqc2        vf9,  0x00(%4)                              \n\
        sqc2        vf10, 0x10(%4)                              \n\
        sqc2        vf11, 0x20(%4)                              \n\
        sqc2        vf12, 0x30(%4)                              \n\
        sw          %1, 0x0C(%4)                                    \n\
        .set reorder "                                              \
         : "=r&" (__tmp1), "=r&" (__tmp2) : "r" (_matrixIn1),       \
           "r" (_matrixIn2), "r" (_matrix) : "cc",  "memory");      \
}                                                                   \
MACRO_STOP

#if (!defined(_RW_MATMUL_CPU) && !defined(RwMatrixMultiplyMacro))
#define RwMatrixMultiplyMacro(_m, _m1, _m2) \
        RwMatrixMultiplyVUMacro(_m, _m1, _m2)
#endif /* (!defined(_RW_MATMUL_CPU) && !defined(RwMatrixMultiplyMacro)) */

#if ( (defined(RWMEMDEBUG)) && defined(RWDEBUG) )

/*
 * PS2 memdebug build requires linking with librtdbmalloc.a
 */

#include <rtdbmalloc.h>

#undef RwMalloc
#define RwMalloc(p_Size) \
    RtDBMalloc(__FILE__, __LINE__, (p_Size))

#undef RwCalloc
#define RwCalloc(p_Number, p_Size)    \
    RtDBCalloc(__FILE__, __LINE__, (p_Number), (p_Size))

#undef RwRealloc
#define RwRealloc(p_Name, p_Size) \
    RtDBRealloc(__FILE__, __LINE__, (p_Name), (p_Size))

#undef RwFree
#define RwFree(p_Name) \
    RtDBFree(__FILE__, __LINE__, (p_Name))

#undef RWPENTER
#define RWPENTER(_func)    RtDBStackEnter(_func,__FILE__,__LINE__)

#undef RWPEXIT
#define RWPEXIT(_func)     RtDBStackLeave(_func,__FILE__,__LINE__)

#undef RWASSERTE
#define RWASSERTE(_condition)                                              \
MACRO_START                                                                \
{                                                                          \
    if (!(_condition))                                                     \
    {                                                                      \
        printf("%s(%d): assertion failure [%s]\n",                         \
               __FILE__, __LINE__, #_condition);                           \
        RtDBStackDump("RW stack on failure of [" ## #_condition ## "]:\n", \
                      RtDBStackCurrent());                                 \
    }                                                                      \
}                                                                          \
MACRO_STOP

#undef RWCRTCHECKMEMORY
#define RWCRTCHECKMEMORY()                                              \
    do                                                                  \
    {                                                                   \
        int             invalid_heap;                                   \
                                                                        \
        invalid_heap = RtDBMallocChainCheck(__FILE__, __LINE__, TRUE);  \
        RWASSERTE(!invalid_heap);                                       \
    }   while(0)

#endif /* ( (defined(RWMEMDEBUG)) && defined(RWDEBUG) ) */

/****************************************************************************
 Global Types
 */

/**
 * $ingroup driversky2
 * $typedef RwSky2DVertexFields
 */
typedef struct RwSky2DVertexFields RwSky2DVertexFields;
/**
 * \ingroup driversky2
 * \struct RwSky2DVertexFields
 * Structure for 2D vertex fields
 */
struct RwSky2DVertexFields
{
    RwV3d          scrVertex;              /**< Object space vertex */
    RwReal         camVertex_z;            /**< Camera space z (for fog table) */
    RwReal         u;                      /**< Texture coordinate */
    RwReal         v;                      /**< Texture coordinate */
    RwReal         recipZ;                 /**< Recipz */
    RwReal         pad1;                   /**< Padding (fog table) */
    RwRGBAReal     color;                  /**< Color */
    RwV3d          objNormal;              /**< We allocate this, even though
                                            * we don't use it - we may want
                                            * to later.
                                            */
    RwReal         pad2;                   /**< Alignment padding */
};

/**
 * $ingroup driversky2
 * $typedef RwSky2DVertexAlignmentOverlay
 */
typedef union RwSky2DVertexAlignmentOverlay RwSky2DVertexAlignmentOverlay;
/**
 * \ingroup driversky2
 * \union RwSky2DVertexAlignmentOverlay
 * Union allowing access to \ref RwSky2DVertexFields as a 4 quad words
 */
union RwSky2DVertexAlignmentOverlay
{
    RwSky2DVertexFields els;                            /**< Internal use */
    u_long128 qWords[4];                                /**< Internal use */
};

/**
 * $ingroup driversky2
 * $typedef RwSky2DVertex
 */
typedef struct RwSky2DVertex RwSky2DVertex;
/**
 * \ingroup driversky2
 * \struct RwSky2DVertex
 * Structure for 2D vertex
 */
struct RwSky2DVertex
{
    RwSky2DVertexAlignmentOverlay u;                    /**< Internal use */
};

/* Define types used */
/**
 * \ingroup driversky2
 * \typedef RwIm2DVertex
 * Typedef for a RenderWare Graphics Immediate Mode 2D Vertex
 */
typedef RwSky2DVertex   RwIm2DVertex;
/* LEGACY-SUPPORT macro */

/**
 * \ingroup driversky2
 * \def RWIM2DVERTEX
 * RWIM2DVERTEX is a legacy macro for RwIm2DVertex
 */

#define RWIM2DVERTEX    RwIm2DVertex

/**
 * \ingroup driversky2
 * \typedef RxVertexIndex
 * Typedef for a RenderWare Graphics PowerPipe Immediate Mode Vertex
 */
typedef RwUInt16        RxVertexIndex;

/**
 * \ingroup driversky2
 * \typedef RwImVertexIndex
 * Typedef for a RenderWare Graphics Immediate Mode Vertex
 */
typedef RxVertexIndex   RwImVertexIndex;

/* LEGACY-SUPPORT macro */
/**
 * \ingroup driversky2
 * \def RWIMVERTEXINDEX
 * RWIMVERTEXINDEX is a legacy macro for RwImVertexIndex
 */
#define RWIMVERTEXINDEX RwImVertexIndex


/**
 * $ingroup driversky2
 * $typedef RwSkyMetrics
 */
typedef struct RwSkyMetrics RwSkyMetrics;
/**
 * \ingroup driversky2
 * \struct RwSkyMetrics
 * Structure containing metrics counters
 */
struct RwSkyMetrics
{
    RwUInt32 profTotal;                                 /**< Internal use */
    RwUInt32 vu1Running;                                /**< Internal use */
    RwUInt32 dma1Running;                               /**< Internal use */
    RwUInt32 dma2Running;                               /**< Internal use */
    /* Internal1 is the time over which dma1 is stalled on vu and no GIF
     * transfer is taking place. */
    RwUInt32 internal1;                                 /**< Internal use */
    RwUInt32 vSyncsSinceLastFlip;                       /**< Internal use */
    RwUInt64 flipPktTime;                               /**< Internal use */
    RwUInt32 totalVSyncsOverPeriod;                     /**< Internal use */

    RwUInt32 curFrame;                                  /**< Internal use */
    RwUInt32 frameProfTotal[rwSKYMETRICSSAMPLES];       /**< Internal use */
    RwUInt32 frameVu1Running[rwSKYMETRICSSAMPLES];      /**< Internal use */
    RwUInt32 frameDma1Running[rwSKYMETRICSSAMPLES];     /**< Internal use */
    RwUInt32 frameDma2Running[rwSKYMETRICSSAMPLES];     /**< Internal use */
    RwUInt32 frameinternal1[rwSKYMETRICSSAMPLES];       /**< Internal use */
    RwUInt32 frameVSyncsOverPeriod[rwSKYMETRICSSAMPLES]; /**< Internal use */
    RwUInt32 lastFrameVSyncCount;                       /**< Internal use */
    RwUInt64 flipPktToFlipTime;                         /**< Internal use */
};

#endif /* SKY2_DRVMODEL_H */

/* RWPUBLICEND */
