/*************************************************************************
 ***                            pot.c                    (JJB TEMPLAR) ***
 *** Date begun: 6/8/89.                                               ***
 *** Last modified: 6/8/89.                                            ***
 *************************************************************************/
/*** An example of reading the pot inputs from joystick port 1.        ***
 *************************************************************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <hardware/intbits.h>
#include <intuition/intuition.h>
#include <resources/potgo.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/potgo.h>

#include <string.h>

#define NULL    0L

extern APTR     WBenchMsg;      /* A lie, to avoid extra wasted #include */

struct GfxBase          *GfxBase;
struct IntuitionBase    *IntuitionBase;
struct PotgoBase        *PotgoBase;

struct Window       *Window;
struct NewWindow    NewWindow = {
    20,20,150,75,3,2,CLOSEWINDOW,
    WINDOWDEPTH|WINDOWCLOSE|WINDOWDRAG|SMART_REFRESH|ACTIVATE,
    NULL,NULL,"Pot:",NULL,NULL,0,0,0,0,WBENCHSCREEN};

extern void VertBServer();
struct Interrupt    *VertBIntr;     /* Just like the manual! */

struct {
    volatile UWORD  potval;         /* Used by interrupt server */
    APTR            potbase;        /* So server can use WritePotgo() */
} server_data;

UBYTE   text[] = "00       00";     /* PotX = 0, PotY = 9 */
#define potbits     0x5001     /* DATRX,DATRY,START- 0101 0000 0000 0001 */

void    printf(char *);
void    dolibs();
void    dodisp();
void    plug(char *,UBYTE);
void    cleanup(int,char *);

void    printf(cp) /*====================================================*/
char    *cp;
{
    if (!WBenchMsg) Write(Output(),cp,strlen(cp));
}

void    dolibs() /*======================================================*/
{
    if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L)))
        cleanup(0,"ERROR: failed to open graphics.library!\n");
    if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L)))
        cleanup(1,"ERROR: failed to open intuition.library!\n");
    if (!(PotgoBase = (struct PotgoBase *)OpenResource("potgo.resource",0L)))
        cleanup(2,"ERROR: failed to open potgo.resource!\n");
    server_data.potbase = (APTR)PotgoBase;
}

void    dodisp() /*======================================================*/
{
register char   *cp;
register struct RastPort    *RP;
    if (!(Window = (struct Window *)OpenWindow(&NewWindow)))
        cleanup(3,"ERROR: failed to open window!\n");
    SetWindowTitles(Window,(char *)-1L,"Pot: an example by JJB TEMPLAR, 1st NZAUsG");
    RP = Window->RPort;
    SetAPen(RP,2);
    RectFill(RP,0,10,149,74);
    cp = "POTX     POTY";   SetDrMd(RP,JAM1);
    SetAPen(RP,0);          Move(RP,24,30);      Text(RP,cp,13);
    SetAPen(RP,1);          Move(RP,23,29);      Text(RP,cp,13);
    Move(RP,21,33);         Draw(RP,129,33);
    SetAPen(RP,0);
    Move(RP,22,34);         Draw(RP,130,34);
    SetDrMd(RP,JAM2);       SetBPen(RP,2);
}

void    plug(cp,val) /*==================================================*/
register char   *cp;
register UBYTE  val;
{
    *cp = (val >> 4) + '0';
    if (*cp > '9') *cp += 'a' - ('9' + 1);
    *cp++;
    *cp = (val & 0x0f) + '0';
    if (*cp > '9') *cp += 'a' - ('9' + 1);
}

void    main(argc,argv) /*===============================================*/
int     argc;
char    *argv[];
{
register struct RastPort        *RP;    /* Cache Window->RPort */
register struct IntuiMessage    *msg;
register int    loop;
UWORD   got;
    dolibs();
    dodisp();
    RP = Window->RPort;

    got = AllocPotBits(potbits);
    if ((got & potbits) != potbits) {
        FreePotBits(got);
        cleanup(4,"ERROR: failed to allocate pot bits!\n");
    }

    if (!(VertBIntr = (struct Interrupt *)AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC)))
        cleanup(5,"ERROR: failed to allocate memory for server!\n");

    VertBIntr->is_Node.ln_Type = NT_INTERRUPT;
    VertBIntr->is_Node.ln_Pri = -128;
    VertBIntr->is_Node.ln_Name = "Pot: JJB TEMPLAR";
    VertBIntr->is_Data = (APTR)&server_data;
    VertBIntr->is_Code = VertBServer;

    AddIntServer(INTB_VERTB,VertBIntr);

    loop = 1;
    while (loop) {
        if (msg = (struct IntuiMessage *)GetMsg(Window->UserPort)) {
            if (msg->Class == CLOSEWINDOW) loop = 0;
            ReplyMsg((struct Message *)msg);
        }

        plug(&text[0],(UBYTE)(server_data.potval & 0x00ff));
        plug(&text[9],(UBYTE)(server_data.potval >> 8));
        Move(RP,31,52);         Text(RP,text,11);
    }

    RemIntServer(INTB_VERTB,VertBIntr);
    cleanup(6,NULL);
}

void    cleanup(bra,cp) /*===============================================*/
int     bra;
char    *cp;
{
    if (cp) printf(cp);
    switch (bra) {
        case (6): FreeMem((BYTE *)VertBIntr,sizeof(struct Interrupt));
        case (5): FreePotBits(potbits);
        case (4): CloseWindow(Window);
        case (3):               /* No need to close resource */
        case (2): CloseLibrary(IntuitionBase);
        case (1): CloseLibrary(GfxBase);
        case (0): break;
    }
    XCEXIT(0);
}
