/*

        RTG Library Usage Demo - Bouncing Truecolor ball

*/
//* "Includes"


/* Generic "Include Everything"-type file */
#include <stdlib.h>
#include <proto/utility.h>
#include <proto/exec.h>
#include <clib/rtgmaster_protos.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <pragmas/rtgmaster_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <exec/memory.h>
#include <utility/tagitem.h>
#include <rtgmaster/rtgmaster.h>
#include <rtgmaster/rtgsublibs.h>
#include <proto/rtgmaster.h>
#include <string.h>
#include <stdio.h>
#include <clib/dos_protos.h>


//*
//* "Globals"
struct RtgScreen *RtgScreen;
struct ScreenReq *sr;
struct RTGMasterBase *RTGMasterBase;
struct Library *UtilityBase, *IntuitionBase;
struct Library *GfxBase;
extern struct Library *DOSBase;
struct TagItem rtag[] = {
    smr_ChunkySupport,  -1,
    smr_PlanarSupport,  -1,
    smr_PrefsFileName,  (ULONG)"PingRtg.prefs",
    smr_Buffers,        2,
    TAG_DONE,           NULL
};

struct TagItem gtag[] = {
    grd_BytesPerRow,    0,
    grd_Width,          0,
    grd_Height,         0,
    grd_Depth,          0,
    grd_PixelLayout,    0,
    grd_ColorSpace,     0,
    grd_PlaneSize,      0,
    grd_BusSystem,      0,
    TAG_DONE,           0
};

struct TagItem tacks[] = {
    rtg_Buffers,    2,
    TAG_DONE,       0
};

BOOL Planar;
UBYTE *cbuf=NULL;
ULONG width;
UBYTE *sadr, *sadr2;
ULONG cmap[800];
#define CBUF 76800

/*
 * This is done using an ugly direct hardware hit
 * Should be an input handler or similar in future versions/real-life
 * applications!
 */
extern int MouseButton(void);
UBYTE *image;

//*
//* "fail"
void fail(void) {
    if (RtgScreen) CloseRtgScreen(RtgScreen);
    if (RTGMasterBase) CloseLibrary((struct Library *)RTGMasterBase);
    if (UtilityBase) CloseLibrary(UtilityBase);
    if (cbuf) FreeVec(cbuf);
    exit(0L);
}
//*
//* "LoadImage"
BOOL LoadImage(void) {
    FILE *f;

    image=AllocVec(2976,MEMF_ANY);
    if (!image) return FALSE;

    f=fopen("Kugel.raw", "r");
    fread(image, 1,2976,f);
    fclose(f);

}
//*
//* "main"
void main(int argc, char **argv) {
   /*
    * Since this is a demo, I don't check anything at all
    * and simply assume that every open went ok... 8-)
    */
    int a,b;
    int img;
    struct TagItem *tag;
    UBYTE rr, rg, rb;
    ULONG size;
    LONG spx, spy;
    LONG sx,sy;
    LONG mx, my;


    RTGMasterBase = (struct RTGMasterBase *)OpenLibrary((STRPTR)"rtgmaster.library", 0);
    UtilityBase = OpenLibrary((STRPTR)"utility.library", 37L);
    IntuitionBase = OpenLibrary("intuition.library", 37L);
    GfxBase = OpenLibrary("graphics.library", 37L);

    sr = RtgScreenModeReq(rtag);

    if (sr==NULL) fail();

    RtgScreen = OpenRtgScreen(sr, tacks);

    GetRtgScreenData(RtgScreen, gtag);

    tag=FindTagItem(grd_BytesPerRow, gtag);
    size = tag->ti_Data;

    tag=FindTagItem(grd_Width, gtag);
    width = tag->ti_Data;

    tag=FindTagItem(grd_Depth, gtag);
    if (tag->ti_Data < 15) {
        printf("Screenmode not supported\n");
        fail();
    }

    tag=FindTagItem(grd_PixelLayout, gtag);
    printf("Screen pixel layout is ");
    switch(tag->ti_Data) {
        case grd_PLANAR:        printf("planar\n"); break;
        case grd_PLANATI:       printf("interleaved planar\n"); break;
        case grd_CHUNKY:        printf("8-Bit Z-Ordered (chunky)\n"); break;
        case grd_HICOL15:       printf("15-Bit Chunky (2 Byte/pixel)\n"); break;
        case grd_HICOL16:       printf("16-Bit Chunky (2 Byte/pixel)\n"); break;
        case grd_TRUECOL24:     printf("24-Bit Chunky (3 Byte/pixel)\n"); break;
        case grd_TRUECOL24P:    printf("24-Bit Chunky (3 Byteplanes/pixel)\n"); break;
        case grd_TRUECOL32:     printf("24-Bit Chunky (4 Bytes/pixel)\n"); break;
        case grd_GRAFFITI:      printf("Graffiti 8 bit\n"); break;
        case grd_TRUECOL32B:    printf("24-Bit Chunky (4 Bytes/pixel)\n"); break;
        default:                printf("unknown (%d)\n", tag->ti_Data); break;
    }

    tag=FindTagItem(grd_ColorSpace, gtag);
    if (tag->ti_Data) {
        printf("Color space is ");
        switch(tag->ti_Data) {
            case grd_Palette:   printf("CLUT-Based\n"); break;
            case grd_RGB:       printf("RGB (low-endian RGB)\n"); break;
            case grd_BGR:       printf("BGR (high-endian RGB)\n"); break;
            default:            printf("unknown (%d)\n", tag->ti_Data); break;
        }
    }

    tag=FindTagItem(grd_BusSystem, gtag);
    if (tag->ti_Data) {
        printf("Graphics card bus is ");
        switch(tag->ti_Data) {
            case grd_Z3:        printf("Zorro III\n"); break;
            case grd_Z2:        printf("Zorro II\n"); break;
            case grd_Custom:    printf("default custom chips\n"); break;
            case grd_RGBPort:   printf("conneted to the RGB Port\n"); break;
            case grd_GVP:       printf("GVP Special Bus (EGS110)\n"); break;
            case grd_DDirect:   printf("DracCoŽ Direct\n"); break;
            default:            printf("an unknown bus system\n"); break;
        }
    }

    if (tag->ti_Data == grd_PLANAR) Planar = TRUE;
    else Planar = FALSE;


    mx=FindTagItem(grd_Width,  gtag)->ti_Data - 34;
    my=FindTagItem(grd_Height, gtag)->ti_Data - 34;

    printf("Screen is %ld x %ld x %ld\n", gtag[1].ti_Data, gtag[2].ti_Data, gtag[3].ti_Data);
    printf("It has %ld bytes per row\n", size);


    if (Planar == TRUE) {
        cbuf = AllocVec(CBUF, MEMF_CLEAR|MEMF_FAST);
        if (cbuf==NULL) {
            cbuf=AllocVec(CBUF, MEMF_CLEAR);
            if (cbuf==NULL) {
                printf("Out of memory *SIGH*\n");
                fail();
            }
        }
    }

    LoadImage();

    if (RtgScreen) {
        LockRtgScreen(RtgScreen);
        sadr = (UBYTE *)GetBufAdr(RtgScreen,0);
        sadr2 = (UBYTE *)GetBufAdr(RtgScreen,1);

        //RtgBltClear(RtgScreen,0,0,0,gtag[1].ti_Data,gtag[2].ti_Data);
        //RtgBltClear(RtgScreen,1,0,0,gtag[1].ti_Data,gtag[2].ti_Data);


        FillRtgRectRGB(RtgScreen, sadr, 0x00000000,
            0,0, gtag[1].ti_Data, gtag[2].ti_Data);
        SwitchScreens(RtgScreen, 1);
        FillRtgRectRGB(RtgScreen, sadr2, 0x0000000,
            0,0, gtag[1].ti_Data, gtag[2].ti_Data);

        Delay(50L);

        img=0;
        for (a=0; a<31; a++) {
            for (b=0; b<32; b++) {
                rr=image[img];
                rg=image[img+1];
                rb=image[img+2]; img+=3;
                WriteRtgPixelRGB(RtgScreen, sadr2, 20+(ULONG)b,20+(ULONG)a,
                    rb|rg<<8|rr<<16);
            }
        }

        SwitchScreens(RtgScreen, 0);

        spx=2; spy=3;
        sx=18; sy=18;

        Forbid();
        while(MouseButton()==0) {
            sx+=spx; sy+=spy;
            if (sx>mx) {
                sx=mx;
                spx=-spx;
            } else if (sx<3) {
                sx=3;
                spx=-spx;
            }
            if (sy>my) {
                sy=my;
                spy=-spy;
            } else if (sy<3) {
                sy=3;
                spy=-spy;
            }
            RtgWaitTOF(RtgScreen);
            RtgBlit(RtgScreen, 1, 0,
                18,18,
                (ULONG)sx, (ULONG)sy,
                36, 36, 0xC0);
            WaitRtgBlit(RtgScreen);

        }
        Permit();
        UnlockRtgScreen(RtgScreen);
        CloseRtgScreen(RtgScreen);
    }

    FreeVec(image);

    CloseLibrary(GfxBase);
    CloseLibrary((struct Library *)RTGMasterBase);
    CloseLibrary(UtilityBase);
    CloseLibrary(IntuitionBase);
}
//*

