/**
 * Sky driver dma support
 * 
 * Copyright (c) Criterion Software Limited
 */

#ifndef _BADMA_H
#define _BADMA_H

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

#ifndef _RW_EEKERNEL_H
#define _RW_EEKERNEL_H
#include <eekernel.h>
#endif /* _RW_EEKERNEL_H */

#ifndef _RW_LIBDMA_H
#define _RW_LIBDMA_H
#include <libdma.h>
#endif /* _RW_LIBDMA_H */

#ifndef RWDEBUG
#define LOCAL_REG_SUPPORT
#endif /* RWDEBUG */

/* RWPUBLICEND */

#include "dmaalloc.h"
#include "drvmodel.h"

#include "devprofile.h"

/* Deliberately outside public scope */
/* Attempt to do promotion on AGIF packets */
#define SWEASYNC

#ifdef SWEASYNC
extern RwBool sweDontFlushRefs;
#endif /* SWEASYNC */

/* Deliberately outside public scope */
/* Attempt to gain more CPU time by moving spin lock */
#define MORECPU

#ifdef MORECPU

#ifdef    __cplusplus
extern "C"
{
#endif                          /* __cplusplus */
extern void _sweWaitQueue(void);
#ifdef    __cplusplus
}
#endif                          /* __cplusplus */
#endif /* MORECPU */

/* RWPUBLIC */
/* flags in top bits */
#define SWE_PKT_LOCAL       0x80000000
#define SWE_PKT_PROCESSED   0x40000000
#define SWE_PKT_NONCONTIG   0x20000000
#define SWE_PKT_SWAP        0x10000000
#define SWE_PKT_CIRCALLOC       0x08000000

#define SWE_PKT_TYPE_MASK   0xff
/* Real packets */
#define SWE_PKT_VU0     0x00
#define SWE_PKT_VU1     0x01
#define SWE_PKT_GIF     0x02

#define SWE_PKT_ASYNC       0x40
#define SWE_PKT_AGIF        (SWE_PKT_ASYNC | SWE_PKT_GIF)

/* Fake packets */
#define SWE_PKT_FLIP0       0x80
#define SWE_PKT_FLIP1       0x81
#define SWE_PKT_RASUREF         0x82
#define SWE_PKT_NULL            0x83
#define SWE_PKT_CALL            0x8f

#define SWE_PKT_IMM_MASK        0xffff00
#define SWE_PKT_IMM_SHIFT       8
#define SWE_PKT_IMM_MAX         (SWE_PKT_IMM_MASK>>SWE_PKT_IMM_SHIFT)

/* Sort of dma we want */
#define SWE_PKT_DMA_MODE_MASK       0x300
#define SWE_PKT_DMA_MODE_NORM       0x000
#define SWE_PKT_DMA_MODE_CHAIN      0x100
#define SWE_PKT_DMA_MODE_INTERL     0x200
#define SWE_PKT_DMA_MODE_CHAIN_TTE  0x500
/* Amount of shift to match mod field of Dn_CHCR reg */
#define SWE_DMA_MODE_SHIFT            6

/* Jump to new memory block */
#define SWE_PKT_GOTO        0xff

typedef RwBool (*sweDmaCallback)(RwBool inHandler);

#ifdef    __cplusplus
extern "C"
{
#endif                          /* __cplusplus */
extern RwBool sweOpenLocalPkt(int type, int size);
extern void sweCloseLocalPkt(void);
extern RwBool sweCallbackRestart(void);
#ifdef    __cplusplus
}
#endif                          /* __cplusplus */


#ifndef SWE_LPS_CONT
#define SWE_LPS_CONT 1
#endif /* SWE_LPS_CONT */

#ifndef SWE_LPS_PRIM
#define SWE_LPS_PRIM 2
#endif /* SWE_LPS_PRIM */

#ifndef SWE_LPS_NOFIXUP
#define SWE_LPS_NOFIXUP 0x80000000
#endif /* SWE_LPS_NOFIXUP */

/* Use this define to turn off excess EOP's in GIF tags */
#define LESSEOPSx

/* Use this define to use direct access */
#define USEDIRECTx

/* RWPUBLICEND */

#if (0 || defined(TRACE))
#define TRACEPRINTF(X)                  \
do                                      \
{                                       \
    RwUInt32            j, ze = 0;      \
    volatile RwUInt32  *vol = &ze;      \
    printf X ;                          \
    for (j = 0; j < 100000; j++)        \
    {                                   \
        if (*vol)                       \
        {                               \
            printf("Odd?\n");           \
        }                               \
    }                                   \
} while (0)

#else /* (defined(TRACE)) */
#define TRACEPRINTF(X)         /* Nothing */
#endif /* (defined(TRACE)) */

extern int                 sweLocalPacketState;
extern u_long128          *sweRealLocalPacketBase;
extern u_long128          *sweLocalPacketBase;
extern u_long128          *sweLocalPacketHigh;
extern u_long128          *sweLocalPacket;

/* RWPUBLIC */
/* Maximum number of queued flips - 1 */
extern int                 sweMaxFlips;
/* RWPUBLICEND */

#define SWE_LPS_INITIAL_SIZE 32

#define SCRATCHPAD ((u_long128*)0x70000000)

#if (!defined(VIF1RENDER))

#define TYPE_CHECK \
   (SWE_LPS_NOFIXUP | \
    SWE_PKT_CIRCALLOC | \
    SWE_PKT_DMA_MODE_CHAIN | \
    SWE_PKT_GIF)
#define PACKET_CHECK \
   (SWE_LPS_NOFIXUP | \
    SWE_PKT_CIRCALLOC | \
    SWE_PKT_DMA_MODE_CHAIN | \
    SWE_PKT_GIF)

#else /* (!defined(VIF1RENDER)) */

#define TYPE_CHECK \
   (SWE_PKT_VU1 | \
    SWE_PKT_CIRCALLOC | \
    SWE_PKT_DMA_MODE_CHAIN_TTE | \
    SWE_LPS_NOFIXUP)
#define PACKET_CHECK \
   (SWE_PKT_VU1 | \
    SWE_PKT_CIRCALLOC | \
    SWE_PKT_DMA_MODE_CHAIN_TTE | \
    SWE_LPS_NOFIXUP)

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

#ifdef LESSEOPS
#define LESSEOPS_TAGEND()                                       \
MACRO_START                                                     \
{                                                               \
    if (!sweLocalPacketGifQWC)                                  \
    {                                                           \
        /* gif end tag */                                       \
        *(long *) sweLocalPacket = 0x0000000000008000;          \
        *((long *) sweLocalPacket + 1) = 0x0000000000000000;    \
        sweLocalPacket++;                                       \
        numQuads++;                                             \
    }                                                           \
}                                                               \
MACRO_STOP
#endif /* LESSEOPS */

#if (!defined(LESSEOPS_TAGEND))
#define LESSEOPS_TAGEND() /* No op */
#endif /* (!defined(LESSEOPS_TAGEND)) */

#if defined(VIF1RENDER)
#define VIF1RENDER_MACRO()                                      \
MACRO_START                                                     \
{                                                               \
    if ((numQuads - 1) > 0)                                     \
    {                                                           \
        *((long *) sweLocalPacketBase + 1) =                    \
            ((0x50l << 24) |                                    \
             (long) (numQuads - 1)) <<  32;                     \
    }                                                           \
    else                                                        \
    {                                                           \
        *((long *) sweLocalPacketBase + 1) = 0;                 \
    }                                                           \
}                                                               \
MACRO_STOP
#endif /* defined(VIF1RENDER) */

#if (!defined(VIF1RENDER_MACRO))
#define VIF1RENDER_MACRO() /* No op */
#endif /* (!defined(VIF1RENDER_MACRO)) */

#ifndef USEDIRECT
#define COMPAREPACKET (SCRATCHPAD)
#else /* !USEDIRECT */
#define COMPAREPACKET \
   ((u_long128 *) ((RwUInt8 *) sweRealLocalPacketBase + DIRECTOFFSET) )
#endif /* !USEDIRECT */

#undef RWUSESWEFINALISEOPENLOCALPKTMACRO

#define sweFinaliseOpenLocalPktMacro(_result, _type, _size)                \
MACRO_START                                                                \
{                                                                          \
    TRACEPRINTF(("%s(%d):%s - %x, %d\n",                                   \
                 __FILE__, __LINE__, __FUNCTION__, (_type), (_size)));     \
    TRACEPRINTF(("%s(%d):%s - sweLocalPacket %p, sweLocalPacketBase %p\n", \
                 __FILE__, __LINE__, __FUNCTION__, sweLocalPacket,         \
                 sweLocalPacketBase));                                     \
                                                                           \
    if ((sweLocalPacketState) &&                                           \
        (!(sweLocalPacketState & SWE_LPS_NOFIXUP)) &&                      \
        ((_type) & SWE_LPS_NOFIXUP))                                       \
    {                                                                      \
        if (TYPE_CHECK == (unsigned int) (_type))                          \
        {                                                                  \
            RwUInt32            numQuads =                                 \
                sweLocalPacket - sweLocalPacketBase;                       \
                                                                           \
            /* This is considered the most often called path */            \
                                                                           \
            LESSEOPS_TAGEND();                                             \
                                                                           \
                                                                           \
            TRACEPRINTF(("%s(%d):%s - numQuads %d sweLocalPacketBase %p\n",   \
                         __FILE__, __LINE__, __FUNCTION__, numQuads,       \
                         sweLocalPacketBase));                             \
            /* finalise dma tag at front of buffer */                      \
            /* Initially we have to write an end with interupt */          \
            *(long *) sweLocalPacketBase = (numQuads - 1) | (0x7l << 28)   \
                | (1l << 31);                                              \
                                                                           \
            VIF1RENDER_MACRO();                                            \
                                                                           \
            /* We now update the (_type) of the open pkt */                \
            sweLocalPacketState = (_type);                                 \
                                                                           \
            if ((_size) < 0)                                               \
                (_size) = -(_size);                                        \
            if (!(_size))                                                  \
                (_size) = SWE_LPS_INITIAL_SIZE;                            \
                                                                           \
            /* if we have a size hint we realloc here */                   \
            if (((_size))                                                  \
                && (sweLocalPacket + (_size) + 2 > sweLocalPacketHigh))    \
            {                                                              \
                RwBool              ret;                                   \
                                                                           \
                TRACEPRINTF(("%s(%d):%s - Calling sweOpenLocalPkt %x, %d\n",  \
                             __FILE__, __LINE__, __FUNCTION__,             \
                             (_type), (_size)));                           \
                ret = sweOpenLocalPkt((_type), (_size));                   \
                                                                           \
                /* We now check to see if the pkt changed due to the Open */  \
                /* If it didn't, we can safely change the end(i) to cnt */ \
                /* I'd prefer not to know about SCRATCHPAD, but I can see */  \
                /* no other way to check */                                \
                if ((ret) && (COMPAREPACKET != sweLocalPacket))            \
                {                                                          \
                    *(long *) sweLocalPacketBase =                         \
                        (numQuads - 1) | (0x1l << 28);                     \
                }                                                          \
                                                                           \
                TRACEPRINTF(("%s(%d):%s - sweLocalPacket %p, sweLocalPacketBase %p\n",  \
                             __FILE__, __LINE__, __FUNCTION__,             \
                             sweLocalPacket, sweLocalPacketBase));         \
                (_result) = (ret);                                         \
            }                                                              \
            else                                                           \
            {                                                              \
                /* We now overwrite the end with interupt, to be a count */   \
                *(long *) sweLocalPacketBase =                             \
                    (numQuads - 1) | (0x1l << 28);                         \
                                                                           \
                TRACEPRINTF(("%s(%d):%s - sweLocalPacket %p, sweLocalPacketBase %p\n",  \
                             __FILE__, __LINE__, __FUNCTION__,             \
                             sweLocalPacket, sweLocalPacketBase));         \
                (_result) = (TRUE);                                        \
            }                                                              \
        }                                                                  \
        else                                                               \
        {                                                                  \
            sweCloseLocalPkt();                                            \
            (_result) = (sweOpenLocalPkt((_type), (_size)));               \
        }                                                                  \
    }                                                                      \
    else if ((sweLocalPacketState)                                         \
             && (sweLocalPacketState & SWE_LPS_NOFIXUP)                    \
             && (!((_type) & SWE_LPS_NOFIXUP)))                            \
    {                                                                      \
        /* If you get here you must have appended a DMAend0 with interupt */  \
        if (PACKET_CHECK == (unsigned int) sweLocalPacketState)            \
        {                                                                  \
            if ((_size) < 0)                                               \
                (_size) = -(_size);                                        \
            if (!(_size))                                                  \
                (_size) = SWE_LPS_INITIAL_SIZE;                            \
                                                                           \
            /* if we have a size hint we realloc here */                   \
            if (((_size))                                                  \
                && (sweLocalPacket + (_size) + 2 > sweLocalPacketHigh))    \
            {                                                              \
                /* This case is more messy */                              \
                RwBool              ret;                                   \
                                                                           \
                /* We don't use the real new (_type) as this might damage the */     \
                /* old pkt. We open the old (_type), then set eh new (_type) and */  \
                /* perform the required adjustments */                     \
                TRACEPRINTF(("%s(%d):%s - Calling sweOpenLocalPkt %x, %d\n",  \
                             __FILE__, __LINE__, __FUNCTION__,             \
                             sweLocalPacketState, (_size)));               \
                ret = sweOpenLocalPkt(sweLocalPacketState, (_size));       \
                                                                           \
                /* We now check to see if the pkt changed due to the Open */  \
                /* I'd prefer not to know about SCRATCHPAD, but I can see */  \
                /* no other way to check */                                \
                if (ret)                                                   \
                {                                                          \
                    if (COMPAREPACKET != sweLocalPacket)                   \
                    {                                                      \
                        /* This means that we didn't open a new pkt */     \
                        TRACEPRINTF(("%s(%d):%s - using old pkt\n",        \
                                     __FILE__, __LINE__, __FUNCTION__));   \
                        sweLocalPacketBase = sweLocalPacket++;             \
                    }                                                      \
                    else                                                   \
                    {                                                      \
                        TRACEPRINTF(("%s(%d):%s - using new pkt\n",        \
                                     __FILE__, __LINE__, __FUNCTION__));   \
                        sweLocalPacket = sweLocalPacketBase + 1;           \
                    }                                                      \
                    sweLocalPacketState = (_type);                         \
                }                                                          \
                TRACEPRINTF(                                               \
                            ("%s(%d):%s - sweLocalPacket %p, sweLocalPacketBase %p\n",  \
                             __FILE__, __LINE__, __FUNCTION__,             \
                             sweLocalPacket, sweLocalPacketBase));         \
                                                                           \
                (_result) = (ret);                                         \
            }                                                              \
            else                                                           \
            {                                                              \
                /* We now update the (_type) of the open pkt */            \
                sweLocalPacketState = (_type);                             \
                                                                           \
                /* Set the new Beginning */                                \
                sweLocalPacketBase = sweLocalPacket - 1;                   \
                                                                           \
                TRACEPRINTF(                                               \
                            ("%s(%d):%s - sweLocalPacket %p, sweLocalPacketBase %p\n",  \
                             __FILE__, __LINE__, __FUNCTION__,             \
                             sweLocalPacket, sweLocalPacketBase));         \
                (_result) = (TRUE);                                        \
            }                                                              \
        }                                                                  \
        else                                                               \
        {                                                                  \
            sweCloseLocalPkt();                                            \
            (_result) = (sweOpenLocalPkt((_type), (_size)));               \
        }                                                                  \
    }                                                                      \
    else if (!(sweLocalPacketState)                                        \
             || ((sweLocalPacketState & SWE_LPS_NOFIXUP)                   \
                 && ((_type) & SWE_LPS_NOFIXUP)))                          \
    {                                                                      \
        /* rare path, so do the simple thing */                            \
        (_result) = (sweOpenLocalPkt((_type), (_size)));                   \
    }                                                                      \
    else                                                                   \
    {                                                                      \
        /* rare path, so do the simple thing */                            \
        sweCloseLocalPkt();                                                \
        (_result) = (sweOpenLocalPkt((_type), (_size)));                   \
    }                                                                      \
}                                                                          \
MACRO_STOP

#ifdef GSB
/******** WARNING! THIS MUST NOT BE CUSTOMER VISIBLE!*********************/
#define SWE_PKT_WAIT_DRAWNEXT   0x84
#define SWE_PKT_INC_TIME        0x85
/******** END WARNING! ***************************************************/
#endif /* GSB */

/* RWPUBLIC */

#if (defined(__MWERKS__))
/* MW version of /usr/local/sce/ee/include/eekernel.h:DI() */
/* MW specific overload removed. */
#endif /* (defined(__MWERKS__)) */

/* Critical section wrappers (for making access to variables modified
 * in interrupt handlers)
 */
#define START_CRITICAL_SECTION \
    DI()
#define END_CRITICAL_SECTION \
    EI()

typedef struct swe_pkt swe_pkt;
struct swe_pkt
{
    unsigned int type;   /**< Internal use */
    void *addr;          /**< Internal use */
};

typedef struct _rwSkyTwoCircuit _rwSkyTwoCircuit;
struct _rwSkyTwoCircuit
{
    RWALIGN(u_long128 dmaDisp1[4], 64); /**< Internal use */
    RWALIGN(u_long128 dmaDisp2[4], 64); /**< Internal use */
    tGS_DISPFB1     dispfb10;           /**< Internal use */
    tGS_DISPLAY1    display10;          /**< Internal use */ 
    tGS_DISPFB1     dispfb11;           /**< Internal use */
    tGS_DISPLAY1    display11;          /**< Internal use */
};

extern _rwSkyTwoCircuit tcaaDisp;

/*
 * MWERKS needs these to be declared
 * before they can be used further down in a #define
 */
#ifdef    __cplusplus
extern "C"
{
#endif                          /* __cplusplus */

extern long sweFrameRenderCount;
extern int sweUseHalfOffset;
extern volatile long sweCurrentHalfOffset;
extern volatile int sweNumFlipsInQueue;
extern volatile int sweFlipPending;
extern volatile int sweAutoFlip;

#ifdef    __cplusplus
}
#endif                          /* __cplusplus */

#if (defined(__MWERKS__))

#if (defined(RWVERBOSE))
#pragma message (__FILE__ "/" _SKY_EXPAND(__LINE__) ": __MWERKS__ == " _SKY_EXPAND(__MWERKS__))
#endif /* (defined(RWVERBOSE)) */

#define SWE_HALF_OFFSET_MACRO(_result)                  \
MACRO_START                                             \
{                                                       \
    if (sweUseHalfOffset)                               \
    {                                                   \
        DI();                                           \
        (_result) =                                     \
            (sweCurrentHalfOffset ^                     \
             (sweNumFlipsInQueue&1)^sweFlipPending);    \
        EI();                                           \
    }                                                   \
    else                                                \
    {                                                   \
        (_result) = (0l);                               \
    }                                                   \
}                                                       \
MACRO_STOP

static inline long
SWE_HALF_OFFSET(void)
{
    long result;
    SWE_HALF_OFFSET_MACRO(result);

    return result;
}

#else /* (defined(__MWERKS__)) */

/* This is complicated */
#define SWE_HALF_OFFSET()                        \
    (sweUseHalfOffset?                           \
    ({ long __res;                           \
      DI();                              \
      __res =                                                        \
              ( sweCurrentHalfOffset ^                                   \
               ( sweNumFlipsInQueue&1 ) ^                                \
               sweFlipPending );                                         \
      EI();                              \
      __res; })                          \
    :0l)

#define SWE_HALF_OFFSET_MACRO(_result)          \
MACRO_START                                     \
{                                               \
    (_result) = SWE_HALF_OFFSET();              \
}                                               \
MACRO_STOP

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

#define _sweAddVU0(A) _sweAddPkt(A, SWE_PKT_VU0)
#define _sweAddVU1(A) _sweAddPkt(A, SWE_PKT_VU1)
#define _sweAddGIF(A) _sweAddPkt(A, SWE_PKT_GIF)

/* we use this sometimes */

#ifdef    __cplusplus
extern "C"
{
#endif                          /* __cplusplus */

extern RwBool _sweHook(void);
extern RwBool _sweOpen(void);
extern void _sweUnhook(void);
extern void _sweClose(void);
extern void _sweFlush(void);
extern void _sweReqFlip(void *addr, int id, unsigned int flags);
extern void _sweWaitFlip(void);
extern void _sweGarbageCollectChain(void);
extern RwBool _sweAddPkt(void* addr, int ch);
extern RwBool _sweAppendToChain(void *addr, void *link);
extern void _sweProcrastinatedAddURef(unsigned int *ptr);

/* Stealth functions */
extern void sweFlushPURef(void);

extern RwBool _swePreAlloc(int memory, int chain, RwBool limit);

extern void sweDmaSend(sceDmaChan *d, void *tag, unsigned int extra);

extern RwBool sweFinaliseOpenLocalPkt(int type, int size);

/* We define the max size and check for inconsistency */
#ifndef SWE_LPS_MAX_PACKET_SIZE
#define SWE_LPS_MAX_PACKET_SIZE 1022
#else /* !SWE_LPS_MAX_PACKET_SIZE */
#if (SWE_LPS_MAX_PACKET_SIZE != 1022)
#error "Definitions of SWE_LPS_MAX_PACKET_SIZE in badma.{c,h} conflict"
#endif
#endif /* !SWE_LPS_MAX_PACKET_SIZE */

/* We define a max qword count for image ops */
#define SWE_LPS_MAX_IMG_QWC \
        (SWE_LPS_MAX_PACKET_SIZE-17>32750?32750:SWE_LPS_MAX_PACKET_SIZE-17)

#ifdef LESSEOPS
/* GIF tag to qword data count */
#define SWEGIFTOSIZE(A) \
({                  \
    u_long128 input = (A);      \
    unsigned int tmp;           \
    unsigned int tmp2;          \
    unsigned int result;        \
    __asm__ ("  andi    %0, %3, 0x7fff  \n\
        dsrl32  %2, %3, 0x1c    \n\
        dsrl32  %1, %3, 0x1a    \n\
        andi    %2, %2, 0xf \n\
        andi    %1, %1, 0x3 \n\
        addiu   %2, %2, 1   \n\
        multu   %0, %2      \n\
.set noreorder              \n\
.set nomacro                \n\
        beq %1, $0, 0f  \n\
        addiu   %1, %1, -1  \n\
        beq %1, $0, 1f  \n\
        nop         \n\
        beq $0, $0, 2f  \n\
        nop         \n\
.set macro              \n\
.set reorder                \n\
0:                  \n\
.set noreorder              \n\
.set nomacro                \n\
        beq $0, $0, 2f  \n\
1:      mflo    %0      \n\
.set macro              \n\
.set reorder                \n\
        addui   %0, %0, 1   \n\
        dsrl    %0, %0, 1   \n\
2:                  \n\
             " : "=r&" (result),    \
             "=r&" (tmp)        \
             "=r&" (tmp2)       \
               : "r" (input));      \
    result;             \
})
#endif /* LESSEOPS */

/* These shouldn't be functions, they need to be much lighter weight...  */

extern void _sweAddCont(u_long128 arg);
extern void _sweAddPrim(u_long128 arg);

/* ... so we wrap them as follows: */
/* These can only be used if a packet of the correct type is known to be open */
extern u_long128 *sweLocalPacket;
extern u_long128 *sweLocalPacketHigh;

#ifdef LESSEOPS
extern unsigned int sweLocalPacketGifQWC;
#endif /* LESSEOPS */

#ifdef LESSEOPS
#define SWEADDCONT(A)               \
sweLocalPacketGifQWC--;             \
if (sweLocalPacket < sweLocalPacketHigh)    \
{                       \
    *sweLocalPacket++ = (A);            \
}                       \
else                        \
{                       \
    _sweAddCont(A);             \
}
#else /* LESSEOPS */
#define SWEADDCONT(A)               \
if (sweLocalPacket < sweLocalPacketHigh)    \
{                       \
    *sweLocalPacket++ = (A);            \
}                       \
else                        \
{                       \
    _sweAddCont(A);             \
}
#endif /* LESSEOPS */

#ifdef LESSEOPS
#define SWEADDCONTGIF(A)            \
if (sweLocalPacket < sweLocalPacketHigh)    \
{                       \
    *sweLocalPacket++ = (A);            \
}                       \
else                        \
{                       \
    _sweAddCont(A);             \
}                       \
sweLocalPacketGifQWC = SWEGIFTOSIZE(A)
#else /* LESSEOPS */
#define SWEADDCONTGIF(A)            \
if (sweLocalPacket < sweLocalPacketHigh)    \
{                       \
    *sweLocalPacket++ = (A);            \
}                       \
else                        \
{                       \
    _sweAddCont(A);             \
}
#endif /* LESSEOPS */

#ifdef LESSEOPS
#define SWEADDPRIM(A)               \
sweLocalPacketGifQWC--;             \
if (sweLocalPacket < sweLocalPacketHigh)    \
{                       \
    *sweLocalPacket++ = (A);            \
}                       \
else                        \
{                       \
    _sweAddPrim(A);             \
}
#else /* LESSEOPS */
#define SWEADDPRIM(A)               \
if (sweLocalPacket < sweLocalPacketHigh)    \
{                       \
    *sweLocalPacket++ = (A);            \
}                       \
else                        \
{                       \
    _sweAddPrim(A);             \
}
#endif /* LESSEOPS */

#ifdef LESSEOPS
#define SWEADDPRIMGIF(A)            \
if (sweLocalPacket < sweLocalPacketHigh)    \
{                       \
    *sweLocalPacket++ = (A);            \
}                       \
else                        \
{                       \
    _sweAddPrim(A);             \
}                       \
sweLocalPacketGifQWC = SWEGIFTOSIZE(A)
#else /* LESSEOPS */
#define SWEADDPRIMGIF(A)            \
if (sweLocalPacket < sweLocalPacketHigh)    \
{                       \
    *sweLocalPacket++ = (A);            \
}                       \
else                        \
{                       \
    _sweAddPrim(A);             \
}
#endif /* LESSEOPS */

/* These can only be used if a packet of the correct type is known to be open
   and contains sufficient space */

#ifdef LESSEOPS
#define SWEADDCONTFAST(A)               \
    sweLocalPacketGifQWC--;             \
    *sweLocalPacket++ = (A)
#define SWEADDPRIMFAST(A)               \
    sweLocalPacketGifQWC--;             \
    *sweLocalPacket++ = (A)

#define SWEADDCONTGIFFAST(A, C)             \
    sweLocalPacketGifQWC = (C);             \
    *sweLocalPacket++ = (A)
#define SWEADDPRIMGIFFAST(A, C)             \
    sweLocalPacketGifQWC = (C);             \
    *sweLocalPacket++ = (A)
#else /* LESSEOPS */
/**
 * \ingroup sky2unsupported
 * \ref SWEADDCONTFAST
 * The macro \ref SWEADDCONTFAST adds a
 * quadword to the currently open local packet. It does no error checking.
 * For this library build, this is functionally equivalent to
 * \ref SWEADDPRIMFAST, \ref SWEADDCONTGIFFAST or \ref SWEADDPRIMGIFFAST
 *
 * \param  A   the quadword to be added.
 */
#define SWEADDCONTFAST(A)               \
    *sweLocalPacket++ = (A)
/**
 * \ingroup sky2unsupported
 * \ref SWEADDPRIMFAST 
 * The macro \ref SWEADDPRIMFAST adds a
 * quadword to the currently open local packet. It does no error checking.
 * For this library build, this is functionally equivalent to
 * \ref SWEADDCONTFAST, \ref SWEADDCONTGIFFAST or \ref SWEADDPRIMGIFFAST
 *
 * \param  A   the quadword to be added.
 */
#define SWEADDPRIMFAST(A)               \
    *sweLocalPacket++ = (A)

/**
 * \ingroup sky2unsupported
 * \ref SWEADDCONTGIFFAST 
 * The macro \ref SWEADDCONTGIFFAST
 * adds a quadword to the currently open local packet. It does no error
 * checking. For this library build, this is functionally equivalent to
 * \ref SWEADDCONTFAST, \ref SWEADDPRIMFAST or \ref SWEADDPRIMGIFFAST
 *
 * \param  A   the quadword to be added.
 * \param  C   The GIF tag NLOOP field (ignored)
 */
#define SWEADDCONTGIFFAST(A, C)             \
    *sweLocalPacket++ = (A)
/**
 * \ingroup sky2unsupported
 * \ref SWEADDPRIMGIFFAST
 * The macro \ref SWEADDPRIMGIFFAST
 * adds a quadword to the currently open local packet. It does no error
 * checking. For this library build, this is functionally equivalent to
 * \ref SWEADDCONTFAST, \ref SWEADDPRIMFAST or \ref SWEADDCONTGIFFAST
 *
 * \param  A   the quadword to be added.
 * \param  C   The GIF tag NLOOP field (ignored)
 */
#define SWEADDPRIMGIFFAST(A, C)             \
    *sweLocalPacket++ = (A)

#ifdef LOCAL_REG_SUPPORT
/* This is a solution to the non-optimal code generated due to sweLocalPacket
   being global. It relies on the fact that at -03, the const and if boils
   off, leaving the appropriate code only */

static const int sweInLocalBlock = 0;

extern u_long128 *__localLocalPacketPointer;

#define SWE_LOCAL_BLOCK_BEGIN()                            \
do                                                         \
{                                                          \
    const int sweInLocalBlock = 1;                         \
    u_long128 *__localLocalPacketPointer = sweLocalPacket

#define SWE_LOCAL_BLOCK_END()                              \
    sweLocalPacket = __localLocalPacketPointer;            \
} while (0)

#undef SWEADDCONTFAST
#undef SWEADDPRIMFAST
#undef SWEADDCONTGIFFAST
#undef SWEADDPRIMGIFFAST

#define SWEADDCONTFAST(A)                   \
do                                          \
{                                           \
    if (sweInLocalBlock)                    \
        *__localLocalPacketPointer++ = (A); \
    else                                    \
        *sweLocalPacket++ = (A);            \
}                                           \
while (0)

#define SWEADDPRIMFAST(A)               \
    SWEADDCONTFAST(A)

#define SWEADDCONTGIFFAST(A, C)             \
    SWEADDCONTFAST(A)

#define SWEADDPRIMGIFFAST(A, C)             \
    SWEADDCONTFAST(A)

#else /* LOCAL_REG_SUPPORT */

#define SWE_LOCAL_BLOCK_BEGIN()
#define SWE_LOCAL_BLOCK_END()

#endif /* LOCAL_REG_SUPPORT */

#endif /* LESSEOPS */

#ifdef    __cplusplus
}
#endif                          /* __cplusplus */

/* RWPUBLICEND */

#ifdef    __cplusplus
extern "C"
{
#endif                          /* __cplusplus */

#if (defined(DMATIME))
extern unsigned long       sweDmaRunTime;
#endif /* (defined(DMATIME)) */

/* RWPUBLIC */
/* For external PL2 that wants to use dma allocator */
extern circularAllocator *circAllocator;
/* RWPUBLICEND */

/* Only available if TIMER was defined in badma.c */
extern unsigned long _sweReadTimer(void);

/* Temp externs so we can wait elsewhere on destroy */
extern swe_pkt *sweCurrentBase;
extern swe_pkt *sweChainEnd;

/* RWPUBLIC */
/* Debugging VIF Mark generation */
#define DEBUGWITHMARK

#ifdef DEBUGWITHMARK
extern unsigned int sweDebugMark;

#define DEBUGMARK() \
    ((7l<<24) | (unsigned long)(sweDebugMark++ & 0xffff))

#else /* DEBUGWITHMARK */

#define DEBUGMARK() (0l)

#endif /* DEBUGWITHMARK */
/* RWPUBLICEND */

#ifdef PG

extern void _sweProfileReset(void);
extern void _sweProfileDump(void);

#endif /* PG */

#ifdef RWMETRICS
extern void _sweMetricsReset(void);
extern RwSkyMetrics *_sweMetricsGet(void);
#endif /* RWMETRICS */

#ifdef    __cplusplus
}
#endif                          /* __cplusplus */

extern void         _mcount(void);
extern void         _mcountend(void);

#ifdef PROCRAS
extern void                _sweFlushHid();
#endif /* PROCRAS */

#endif /* _BADMA_H */

