#ifndef SMACKH
#define SMACKH

#define SMACKVERSION "3.2f"

#ifndef __RADRES__

#include "rad.h"

RADDEFSTART

typedef struct SmackTag {
  u32 Version;           // SMK2 only right now
  u32 Width;             // Width (1 based, 640 for example)
  u32 Height;            // Height (1 based, 480 for example)
  u32 Frames;            // Number of frames (1 based, 100 = 100 frames)
  u32 MSPerFrame;        // Frame Rate
  u32 SmackerType;       // bit 0 set=ring frame
  u32 LargestInTrack[7]; // Largest single size for each track
  u32 tablesize;         // Size of the init tables
  u32 codesize;          // Compression info   
  u32 absize;            // ditto
  u32 detailsize;        // ditto
  u32 typesize;          // ditto
  u32 TrackType[7];      // high byte=0x80-Comp,0x40-PCM data,0x20-16 bit,0x10-stereo
  u32 extra;             // extra value (should be zero)
  u32 NewPalette;        // set to one if the palette changed
  u8  Palette[772];      // palette data
  u32 PalType;           // type of palette
  u32 FrameNum;          // Frame Number to be displayed
  u32 FrameSize;         // The current frame's size in bytes
  u32 SndSize;           // The current frame sound tracks' size in bytes
  s32 LastRectx;         // Rect set in from SmackToBufferRect (X coord)
  s32 LastRecty;         // Rect set in from SmackToBufferRect (Y coord)
  s32 LastRectw;         // Rect set in from SmackToBufferRect (Width)
  s32 LastRecth;         // Rect set in from SmackToBufferRect (Height)
  u32 OpenFlags;         // flags used on open
  u32 LeftOfs;           // Left Offset used in SmackTo
  u32 TopOfs;            // Top Offset used in SmackTo
  u32 LargestFrameSize;  // Largest frame size
  u32 Highest1SecRate;   // Highest 1 sec data rate
  u32 Highest1SecFrame;  // Highest 1 sec data rate starting frame
  u32 ReadError;         // Set to non-zero if a read error has ocurred
  u32 addr32;            // translated address for 16 bit interface
} Smack;              

#define SmackHeaderSize(smk) ((((u8*)&((smk)->extra))-((u8*)(smk)))+4)

typedef struct SmackSumTag {
  u32 TotalTime;         // total time
  u32 MS100PerFrame;     // MS*100 per frame (100000/MS100PerFrame=Frames/Sec)
  u32 TotalOpenTime;     // Time to open and prepare for decompression
  u32 TotalFrames;       // Total Frames displayed
  u32 SkippedFrames;     // Total number of skipped frames
  u32 SoundSkips;        // Total number of sound skips
  u32 TotalBlitTime;     // Total time spent blitting
  u32 TotalReadTime;     // Total time spent reading 
  u32 TotalDecompTime;   // Total time spent decompressing
  u32 TotalBackReadTime; // Total time spent reading in background
  u32 TotalReadSpeed;    // Total io speed (bytes/second)
  u32 SlowestFrameTime;  // Slowest single frame time
  u32 Slowest2FrameTime; // Second slowest single frame time
  u32 SlowestFrameNum;   // Slowest single frame number
  u32 Slowest2FrameNum;  // Second slowest single frame number
  u32 AverageFrameSize;  // Average size of the frame
  u32 HighestMemAmount;  // Highest amount of memory allocated
  u32 TotalExtraMemory;  // Total extra memory allocated
  u32 HighestExtraUsed;  // Highest extra memory actually used
} SmackSum;


//=======================================================================
#define SMACKNEEDPAN    0x00020L // Will be setting the pan
#define SMACKNEEDVOLUME 0x00040L // Will be setting the volume
#define SMACKFRAMERATE  0x00080L // Override fr (call SmackFrameRate first)
#define SMACKLOADEXTRA  0x00100L // Load the extra buffer during SmackOpen
#define SMACKPRELOADALL 0x00200L // Preload the entire animation
#define SMACKNOSKIP     0x00400L // Don't skip frames if falling behind
#define SMACKSIMULATE   0x00800L // Simulate the speed (call SmackSim first)
#define SMACKFILEHANDLE 0x01000L // Use when passing in a file handle
#define SMACKTRACK1     0x02000L // Play audio track 1
#define SMACKTRACK2     0x04000L // Play audio track 2
#define SMACKTRACK3     0x08000L // Play audio track 3
#define SMACKTRACK4     0x10000L // Play audio track 4
#define SMACKTRACK5     0x20000L // Play audio track 5
#define SMACKTRACK6     0x40000L // Play audio track 6
#define SMACKTRACK7     0x80000L // Play audio track 7
#define SMACKTRACKS (SMACKTRACK1|SMACKTRACK2|SMACKTRACK3|SMACKTRACK4|SMACKTRACK5|SMACKTRACK6|SMACKTRACK7)

#define SMACKBUFFERREVERSED 0x00000001
#define SMACKBUFFER555      0x80000000
#define SMACKBUFFER565      0xc0000000
#define SMACKBUFFER16       (SMACKBUFFER555|SMACKBUFFER565)

#define SMACKYINTERLACE 0x100000L // Force interleaving Y scaling
#define SMACKYDOUBLE    0x200000L // Force doubling Y scaling
#define SMACKYNONE  (SMACKYINTERLACE|SMACKYDOUBLE) // Force normal Y scaling
#define SMACKFILEISSMK 0x2000000L // Internal flag for 16 to 32 bit thunking

#define SMACKAUTOEXTRA 0xffffffffL // NOT A FLAG! - Use as extrabuf param 
//=======================================================================

#define SMACKSURFACEFAST             0
#define SMACKSURFACESLOW             1
#define SMACKSURFACEDIRECT           2

RADEXPFUNC Smack PTR4* RADEXPLINK SmackOpen(const char PTR4* name,u32 flags,u32 extrabuf);

#ifdef __RADMAC__
  #include <files.h>

  RADEXPFUNC Smack PTR4* RADEXPLINK SmackMacOpen(FSSpec* fsp,u32 flags,u32 extrabuf);
#endif

RADEXPFUNC u32  RADEXPLINK SmackDoFrame(Smack PTR4* smk);
RADEXPFUNC void RADEXPLINK SmackNextFrame(Smack PTR4* smk);
RADEXPFUNC u32  RADEXPLINK SmackWait(Smack PTR4* smk);
RADEXPFUNC void RADEXPLINK SmackClose(Smack PTR4* smk);

RADEXPFUNC void RADEXPLINK SmackVolumePan(Smack PTR4* smk, u32 trackflag,u32 volume,u32 pan);

RADEXPFUNC void RADEXPLINK SmackSummary(Smack PTR4* smk,SmackSum PTR4* sum);

RADEXPFUNC u32  RADEXPLINK SmackSoundInTrack(Smack PTR4* smk,u32 trackflags);
RADEXPFUNC u32  RADEXPLINK SmackSoundOnOff(Smack PTR4* smk,u32 on);

#ifndef __RADMAC__
RADEXPFUNC void RADEXPLINK SmackToScreen(Smack PTR4* smk,u32 left,u32 top,u32 BytePS,const u16 PTR4* WinTbl,void* SetBank,u32 Flags);
#endif

RADEXPFUNC void RADEXPLINK SmackToBuffer(Smack PTR4* smk,u32 left,u32 top,u32 Pitch,u32 destheight,const void PTR4* buf,u32 Flags);
RADEXPFUNC u32  RADEXPLINK SmackToBufferRect(Smack PTR4* smk, u32 SmackSurface);

RADEXPFUNC void RADEXPLINK SmackGoto(Smack PTR4* smk,u32 frame);
RADEXPFUNC void RADEXPLINK SmackColorRemapWithTrans(Smack PTR4* smk,const void PTR4* remappal,u32 numcolors,u32 paltype,u32 transindex);
#define SmackColorRemap(smk,remappal,numcolors,paltype) SmackColorRemapWithTrans(smk,remappal,numcolors,paltype,1000)
RADEXPFUNC void RADEXPLINK SmackColorTrans(Smack PTR4* smk,const void PTR4* trans);
RADEXPFUNC void RADEXPLINK SmackFrameRate(u32 forcerate);
RADEXPFUNC void RADEXPLINK SmackSimulate(u32 sim);

RADEXPFUNC u32  RADEXPLINK SmackGetTrackData(Smack PTR4* smk,void PTR4* dest,u32 trackflag);

RADEXPFUNC void RADEXPLINK SmackSoundCheck(void);


//======================================================================

// the functions for the new SmackBlit API 

typedef struct _SMACKBLIT PTR4* HSMACKBLIT;

typedef struct _SMACKBLIT {
  u32 Flags;
  u8 PTR4* Palette;
  u32 PalType;
  u16 PTR4* SmoothTable;
  u16 PTR4* Conv8to16Table;
  u32 whichmode;
  u32 palindex;
  u32 t16index;
  u32 smoothindex;
  u32 smoothtype;
  u32 firstpalette;
} SMACKBLIT;

#define SMACKBLIT1X                1
#define SMACKBLIT2X                2
#define SMACKBLIT2XSMOOTHING       4
#define SMACKBLIT2XINTERLACE       8

RADEXPFUNC HSMACKBLIT RADEXPLINK SmackBlitOpen(u32 flags);
RADEXPFUNC void RADEXPLINK SmackBlitSetPalette(HSMACKBLIT sblit, void PTR4* Palette,u32 PalType);
RADEXPFUNC u32 RADEXPLINK SmackBlitSetFlags(HSMACKBLIT sblit,u32 flags);
RADEXPFUNC void RADEXPLINK SmackBlit(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch);
RADEXPFUNC void RADEXPLINK SmackBlitClear(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, u32 destw, u32 desth, s32 color);
RADEXPFUNC void RADEXPLINK SmackBlitClose(HSMACKBLIT sblit);
RADEXPFUNC void RADEXPLINK SmackBlitTrans(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch, u32 trans);
RADEXPFUNC void RADEXPLINK SmackBlitMask(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch, u32 trans,void PTR4* mask);
RADEXPFUNC void RADEXPLINK SmackBlitMerge(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch, u32 trans,void PTR4* back);
RADEXPFUNC char PTR4* RADEXPLINK SmackBlitString(HSMACKBLIT sblit,char PTR4* dest);

#ifndef __RADMAC__
RADEXPFUNC u32 RADEXPLINK SmackUseMMX(u32 flag); //0=off, 1=on, 2=query current
#endif

//======================================================================
#ifdef __RADDOS__

  #define SMACKSOUNDNONE -1

  extern void* SmackTimerSetupAddr;
  extern void* SmackTimerReadAddr;
  extern void* SmackTimerDoneAddr;

  typedef void RADEXPLINK (*SmackTimerSetupType)(void);
  typedef u32 RADEXPLINK (*SmackTimerReadType)(void);
  typedef void RADEXPLINK (*SmackTimerDoneType)(void);

  #define SmackTimerSetup() ((SmackTimerSetupType)(SmackTimerSetupAddr))()
  #define SmackTimerRead() ((SmackTimerReadType)(SmackTimerReadAddr))()
  #define SmackTimerDone() ((SmackTimerDoneType)(SmackTimerDoneAddr))()

  RADEXPFUNC u8 RADEXPLINK SmackSoundUseMSS(void* DigDriver);

  #ifndef AIL_startup
    #ifdef __SW_3R
      extern s32 cdecl AIL_startup_reg(void);
      #define AIL_startup AIL_startup_reg
    #else
      extern s32 cdecl AIL_startup_stack(void);
      #define AIL_startup AIL_startup_stack
    #endif
  #endif
  #define SmackSoundMSSLiteInit() SmackSoundMSSLiteInitWithStart(&AIL_startup);
  RADEXPFUNC void RADEXPLINK SmackSoundMSSLiteInitWithStart(void* start);
  RADEXPFUNC void RADEXPLINK SmackSoundMSSLiteDone(void);

  RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS3r(u32 SOSDriver,u32 MaxTimerSpeed);
  RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS3s(u32 SOSDriver,u32 MaxTimerSpeed);
  RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS4r(u32 SOSDriver,u32 MaxTimerSpeed);
  RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS4s(u32 SOSDriver,u32 MaxTimerSpeed);

  #ifdef __SW_3R
    #define SmackSoundUseSOS3 SmackSoundUseSOS3r
    #define SmackSoundUseSOS4 SmackSoundUseSOS4r
  #else
    #define SmackSoundUseSOS3 SmackSoundUseSOS3s
    #define SmackSoundUseSOS4 SmackSoundUseSOS4s
  #endif

#else

  #define SMACKRESRESET    0
  #define SMACKRES640X400  1
  #define SMACKRES640X480  2
  #define SMACKRES800X600  3
  #define SMACKRES1024X768 4

  RADEXPFUNC u32 RADEXPLINK SmackSetSystemRes(u32 mode);  // use SMACKRES* values

  #define SMACKNOCUSTOMBLIT        128
  #define SMACKSMOOTHBLIT          256
  #define SMACKINTERLACEBLIT       512

  #ifdef __RADMAC__

    #include <windows.h>
    #include <palettes.h>
    #include <qdoffscreen.h>

    #define SmackTimerSetup()
    #define SmackTimerDone()
    RADEXPFUNC u32 RADEXPLINK SmackTimerRead(void);

    RADEXPFUNC s32 RADEXPLINK SmackGDSurfaceType( GDHandle gd );

    #define SMACKAUTOBLIT          0
    #define SMACKDIRECTBLIT        1
    #define SMACKGWORLDBLIT        2

    typedef struct SmackBufTag {
      u32 Reversed;
      u32 SurfaceType;    // SMACKSURFACExxxxxx
      u32 BlitType;       // SMACKxxxxxBLIT
      u32 Width;
      u32 Height;
      u32 Pitch;
      u32 Zoomed;
      u32 ZWidth;
      u32 ZHeight;
      u32 DispColors;     // colors on screen
      u32 MaxPalColors;
      u32 PalColorsInUse;
      u32 StartPalColor;
      u32 EndPalColor;
      void* Buffer;
      void* Palette;
      u32 PalType;
      u32 SoftwareCursor;

      WindowPtr wp;
      GWorldPtr gwp;
      CTabHandle cth;
      PaletteHandle palh;

      GDHandle gd;
      u32 gdSurfaceType;
      HSMACKBLIT sblit;
      void * ScreenAddr;
      u32 ScreenPitch;
      
      s32 manyblits;
      s32 PTR4* blitrects;
      s32 PTR4* rectsptr;
      s32 maxrects;
      s32 numrects;

    } SmackBuf;

  #else

    #ifdef __RADWIN__

      #define INCLUDE_MMSYSTEM_H
      #include "windows.h"
      #include "windowsx.h"

      #ifdef __RADNT__          // to combat WIN32_LEAN_AND_MEAN

        #include "mmsystem.h"

        RADEXPFUNC s32 RADEXPLINK SmackDDSurfaceType(void* lpDDS);

      #endif

      #define SMACKAUTOBLIT              0
      #define SMACKFULL320X240BLIT       1
      #define SMACKFULL320X200BLIT       2
      #define SMACKFULL320X200DIRECTBLIT 3
      #define SMACKSTANDARDBLIT          4
      #define SMACKWINGBLIT              5
      #define SMACKDIBSECTIONBLIT        5

      #define WM_SMACKACTIVATE WM_USER+0x5678

      typedef struct SmackBufTag {
        u32 Reversed;             // 1 if the buffer is upside down
        u32 SurfaceType;          // SMACKSURFACExxxx defines
        u32 BlitType;             // SMACKxxxxBLIT defines
        u32 FullScreen;           // 1 if full-screen
        u32 Width;
        u32 Height;
        u32 Pitch;
        u32 Zoomed;
        u32 ZWidth;
        u32 ZHeight;
        u32 DispColors;           // colors on the screen
        u32 MaxPalColors;         // total possible colors in palette (usually 256)
        u32 PalColorsInUse;       // Used colors in palette (usually 236)
        u32 StartPalColor;        // first usable color index (usually 10)
        u32 EndPalColor;          // last usable color index (usually 246)
        RGBQUAD Palette[256];
        u32 PalType;
        u32 forceredraw;  // force a complete redraw on next blit (for >8bit)
        u32 didapalette;  // force an invalidate on the next palette change

        void PTR4* Buffer;
        void PTR4* DIBRestore;
        u32 OurBitmap;
        u32 OrigBitmap;
        u32 OurPalette;
        u32 WinGDC;
        u32 FullFocused;
        u32 ParentHwnd;
        u32 OldParWndProc;
        u32 OldDispWndProc;
        u32 DispHwnd;
        u32 WinGBufHandle;
        void PTR4* lpDD;
        void PTR4* lpDDSP;
        u32 DDSurfaceType;
        HSMACKBLIT DDblit;
        s32 ddSoftwarecur;
        s32 didaddblit;
        s32 lastwasdd;
        RECT ddscreen;
        s32 manyblits;
        s32 PTR4* blitrects;
        s32 PTR4* rectsptr;
        s32 maxrects;
        s32 numrects;
        HDC lastdc;
      } SmackBuf;

      RADEXPFUNC void RADEXPLINK SmackGet(Smack PTR4* smk,void PTR4* dest);
      RADEXPFUNC void RADEXPLINK SmackBufferGet( SmackBuf PTR4* sbuf, void PTR4* dest);
      
      RADEXPFUNC u8 RADEXPLINK SmackSoundUseMSS(void PTR4* dd);
      RADEXPFUNC u8 RADEXPLINK SmackSoundUseDirectSound(void PTR4* dd); // NULL=Create
      RADEXPFUNC void RADEXPLINK SmackSoundSetDirectSoundHWND(HWND hw);
      RADEXPFUNC u8 RADEXPLINK SmackSoundUseDW(u32 openfreq, u32 openbits, u32 openchans);

      #define SmackTimerSetup()
      #define SmackTimerDone()
      #define SmackTimerRead timeGetTime

    #endif

  #endif

  #ifdef __RADMAC__
    RADEXPFUNC SmackBuf PTR4* RADEXPLINK SmackBufferOpen( WindowPtr wp, u32 BlitType, u32 width, u32 height, u32 ZoomW, u32 ZoomH );
    RADEXPFUNC u32  RADEXPLINK SmackBufferBlit( SmackBuf PTR4* sbuf, s32 hwndx, s32 hwndy, s32 subx, s32 suby, s32 subw, s32 subh );
    RADEXPFUNC void RADEXPLINK SmackBufferFromScreen( SmackBuf PTR4* destbuf, s32 x, s32 y);

    RADEXPFUNC s32 RADEXPLINK SmackIsSoftwareCursor(GDHandle gd);
    RADEXPFUNC s32 RADEXPLINK SmackCheckCursor(WindowPtr wp,s32 x,s32 y,s32 w,s32 h);
    RADEXPFUNC void RADEXPLINK SmackRestoreCursor(s32 checkcount);
  #else
    RADEXPFUNC SmackBuf PTR4* RADEXPLINK SmackBufferOpen( HWND wnd, u32 BlitType, u32 width, u32 height, u32 ZoomW, u32 ZoomH );
    RADEXPFUNC u32  RADEXPLINK SmackBufferBlit( SmackBuf PTR4* sbuf, HDC dc, s32 hwndx, s32 hwndy, s32 subx, s32 suby, s32 subw, s32 subh );
    RADEXPFUNC void RADEXPLINK SmackBufferFromScreen( SmackBuf PTR4* destbuf, HWND hw, s32 x, s32 y);

    RADEXPFUNC s32 RADEXPLINK SmackIsSoftwareCursor(void* lpDDSP,HCURSOR cur);
    RADEXPFUNC s32 RADEXPLINK SmackCheckCursor(HWND wnd,s32 x,s32 y,s32 w,s32 h);
    RADEXPFUNC void RADEXPLINK SmackRestoreCursor(s32 checkcount);
  #endif

  RADEXPFUNC void RADEXPLINK SmackBufferStartMultipleBlits( SmackBuf PTR4* sbuf );
  RADEXPFUNC void RADEXPLINK SmackBufferEndMultipleBlits( SmackBuf PTR4* sbuf );

  RADEXPFUNC char PTR4* RADEXPLINK SmackBufferString(SmackBuf PTR4* sb,char PTR4* dest);

  RADEXPFUNC void RADEXPLINK SmackBufferNewPalette( SmackBuf PTR4* sbuf, const void PTR4* pal, u32 paltype );
  RADEXPFUNC u32  RADEXPLINK SmackBufferSetPalette( SmackBuf PTR4* sbuf );
  RADEXPFUNC void RADEXPLINK SmackBufferClose( SmackBuf PTR4* sbuf );
 
  RADEXPFUNC void RADEXPLINK SmackBufferClear( SmackBuf PTR4* destbuf, u32 color);

  RADEXPFUNC void RADEXPLINK SmackBufferToBuffer( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh);
  RADEXPFUNC void RADEXPLINK SmackBufferToBufferTrans( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh,u32 TransColor);
  RADEXPFUNC void RADEXPLINK SmackBufferToBufferMask( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh,u32 TransColor,const SmackBuf PTR4* maskbuf);
  RADEXPFUNC void RADEXPLINK SmackBufferToBufferMerge( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh,u32 TransColor,const SmackBuf PTR4* mergebuf);
  RADEXPFUNC void RADEXPLINK SmackBufferCopyPalette( SmackBuf PTR4* destbuf, SmackBuf PTR4* sourcebuf, u32 remap);

  RADEXPFUNC u32  RADEXPLINK SmackBufferFocused( SmackBuf PTR4* sbuf);

#endif

RADDEFEND

#endif

#endif
