#ifndef TBLIB_H
#define TBLIB_H 1

#ifndef SYS_CDEFS_H
    #include "CompilerSpecific.h"
#endif

#include <exec/types.h>
#include <exec/ports.h>
#include <devices/timer.h>
#include <stdarg.h>

/* useful functions for MsgPorts and Signals */
BOOL AllocPort( struct MsgPort *port );
void FreePort( struct MsgPort *port );
BYTE AllocSig( BYTE instead );
void FreeSig ( BYTE sig );

/* useful functions for timerequests */
void TimerDelay( struct timerequest *treq,
                 ULONG secs,
                 ULONG mics );
void StartTimer( struct timerequest *treq,
                 ULONG secs,
                 ULONG mics );
#define StopTimer(treq) GetMsg((treq)->tr_node.io_Message.mn_ReplyPort)
void AbortTimer( struct timerequest *treq );

/* little-endian <-> big-endian conversions */
UWORD i2m_word( UWORD d );
ULONG i2m_long( ULONG d );

/* 64bit math functions */
struct Integer64 {
    ULONG i64_Upper;
    ULONG i64_Lower;
};

#ifdef SYS_CDEFS_H
    /* dst += src */
    void ASM add64 ( REG(a0) struct Integer64 *dst,
                     REG(a1) struct Integer64 *src );

    /* dst -= src */
    void ASM sub64 ( REG(a0) struct Integer64 *dst,
                     REG(a1) struct Integer64 *src );

    /*
        dst < src       -1
        dst = src        0
        dst > src        1
    */
    int ASM cmp64 ( REG(a0) struct Integer64 *dst,
                    REG(a1) struct Integer64 *src );

#else
    /* dst += src */
    void ASM add64 ( REG(a0, struct Integer64 *dst),
                     REG(a1, struct Integer64 *src) );

    /* dst -= src */
    void ASM sub64 ( REG(a0, struct Integer64 *dst),
                     REG(a1, struct Integer64 *src) );

    /*
        dst < src       -1
        dst = src        0
        dst > src        1
    */
    int ASM cmp64 ( REG(a0, struct Integer64 *dst),
                    REG(a1, struct Integer64 *src) );
#endif

/* useful functions for strings */
void _vsprintf( UBYTE *buffer,
                UBYTE *fmt,
                va_list args );
void _sprintf( UBYTE *buffer,
               UBYTE *fmt,... );
BOOL _vsnprintf( UBYTE *buffer,
                 LONG maxlen,
                 UBYTE *fmt,
                 va_list args );
BOOL _snprintf( UBYTE *buffer,
                LONG maxlen,
                UBYTE *fmt,... );
UBYTE *_strdup( UBYTE *str );
UBYTE *_strdup_pool( UBYTE *str,
                     APTR pool );
void _strcat( UBYTE **str,
              UBYTE *cat );
void _strcatn( UBYTE *str,
               UBYTE *cat,
               ULONG maxlen );
void b2cstr( LONG bstr,
             UBYTE *cstr );
void b2cstrn( LONG bstr,
              UBYTE *cstr,
              ULONG maxlen );

void ErrorMsg( UBYTE *title,
               UBYTE *msg, ... );

/* function to check version of a library/device */
ULONG CheckLibVersion( struct Library *lib,
                       UWORD version,
                       UWORD revision );

#define     CLV_NOT_OPEN        0
#define     CLV_OLDER           1
#define     CLV_NEWER_OR_SAME   2

/* function to get/set environment variables */
LONG GetEnvVar( STRPTR name,
                STRPTR buffer,
                ULONG size,
                ULONG flags );
BOOL SetEnvVar( STRPTR name,
                STRPTR buffer,
                ULONG size,
                ULONG flags,
                BOOL save );
#define SetEnvVarSimple(name, buffer, save) SetEnvVar((name), (buffer), strlen((buffer)), GVF_GLOBAL_ONLY, (save))

/* function for pooled memory allocations */

#ifdef SYS_CDEFS_H
    void * ASM tbCreatePool( REG(d0) ULONG flags,
                             REG(d1) ULONG puddleSize,
                             REG(d2) ULONG threshSize );
    APTR ASM tbAllocPooled( REG(a0) APTR poolHeader,
                            REG(d0) ULONG memSize );
    APTR ASM tbAllocVecPooled( REG(a0) APTR poolHeader,
                               REG(d0) ULONG memSize );
    void ASM tbFreePooled( REG(a0) APTR poolHeader,
                           REG(a1) APTR memory,
                           REG(d0) ULONG memSize );
    void ASM tbFreeVecPooled( REG(a0) APTR poolHeader,
                              REG(a1) APTR memory );
    void ASM tbDeletePool( REG(a0) void *poolHeader );
#else
    void * ASM tbCreatePool( REG(d0, ULONG flags),
                             REG(d1, ULONG puddleSize),
                             REG(d2, ULONG threshSize) );
    APTR ASM tbAllocPooled( REG(a0, APTR poolHeader),
                            REG(d0, ULONG memSize) );
    APTR ASM tbAllocVecPooled( REG(a0, APTR poolHeader),
                               REG(d0, ULONG memSize) );
    void ASM tbFreePooled( REG(a0, APTR poolHeader),
                           REG(a1, APTR memory),
                           REG(d0, ULONG memSize) );
    void ASM tbFreeVecPooled( REG(a0, APTR poolHeader),
                              REG(a1, APTR memory) );
    void ASM tbDeletePool( REG(a0, void *poolHeader) );
#endif


ULONG __stdargs DoSuperNew( struct IClass *cl,
                            Object *obj,
                            Tag tag1, ... );
APTR MakeButton( UBYTE *txt );
APTR MakeCheckmark( UBYTE *txt );
#define MakeHook(hookname, funcname)    static struct Hook hookname = { {NULL, NULL}, (void *)funcname, NULL, NULL }

#endif

