/*                                                                        *
 * Joystick test program  V1.0 (09.02.1997)                               *
 *                                                                        *
 * Christian T. Steigies © 1997  (steigies@physik.uni-kiel.de)            *
 *                                                                        *
#define DEBUG
 *                                                                        */
/*+ "includes" */
#include <exec/types.h> /* must be included before any other Amiga Include */

#include <intuition/intuitionbase.h>
#include <intuition/gadgetclass.h>
#include <intuition/imageclass.h>

#include <graphics/gfxbase.h>

#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h> /* will #include <libraries/gadtools.h> */
#include <clib/dos_protos.h>
#include <clib/lowlevel_protos.h> /* will #include <libraries/lowlevel.h> */
#include <libraries/lowlevel.h>

#include <stdlib.h>
#include <stdio.h>

/*- */
/* ---------------------------------------------------------------------- */
/*+ "function prototypes" */
int     main(int argc, char *argv[]);
void    bail_out(int code);
BOOL    HandleMenuEvent(UWORD code);
BOOL    HandleJoyportEvent(ULONG joystick);
/*- */
/* ---------------------------------------------------------------------- */
/*+ "menu contents" */
/* Here we specify what we want our menus to contain: */

struct NewMenu mynewmenu[] =
{
        { NM_TITLE, "Project",    0 , 0, 0, 0,},
        {  NM_ITEM, "About",     "?", 0, 0, 0,},
        {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,},
        {  NM_ITEM, "Quit...",   "Q", 0, 0, 0,},

        { NM_TITLE, "Options",    0 , 0, 0, 0,},
        {  NM_ITEM, "Port 0",    "0", CHECKIT, ~1, 0,},
        {  NM_ITEM, "Port 1",    "1", CHECKIT|CHECKED, ~2, 0,},
/*        {  NM_ITEM, NM_BARLABEL,  0 , 0, 0, 0,}, */
        {  NM_ITEM, "Port 2",    "2", CHECKIT, ~4, 0,},
        {  NM_ITEM, "Port 3",    "3", CHECKIT, ~8, 0,},

        {   NM_END, 0,            0 , 0, 0, 0,},
};
/*- */
/* ---------------------------------------------------------------------- */
/*+ "images" */
static UWORD __chip emptyData[32] =
   {
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   0x000f, 0x0000,
   };
struct Image emptyImage = { 0,0, 34,17, 1, emptyData, 0x0,0x0, NULL };


static UWORD __chip arr_upData[] =
   {
   0x0001, 0x8000,    /* ...............##............... */
   0x0007, 0xe000,    /* .............######............. */
   0x001f, 0xf800,    /* ...........##########........... */
   0x007f, 0xfe00,    /* .........##############......... */
   0x01ff, 0xff80,    /* .......##################....... */
   0x07ff, 0xffe0,    /* .....######################..... */
   0x1fff, 0xfff8,    /* ...##########################... */
   0x7fff, 0xfffe,    /* .##############################. */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   };
struct Image arr_upImage = { 0,0, 31,15, 1, arr_upData, 0x1,0x0, NULL };


static UWORD __chip arr_downData[] =
   {
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x7fff, 0xfffe,    /* .##############################. */
   0x1fff, 0xfff8,    /* ...##########################... */
   0x07ff, 0xffe0,    /* .....######################..... */
   0x01ff, 0xff80,    /* .......##################....... */
   0x007f, 0xfe00,    /* .........##############......... */
   0x001f, 0xf800,    /* ...........##########........... */
   0x0007, 0xe000,    /* .............######............. */
   0x0001, 0x8000,    /* ...............##............... */
   };
struct Image arr_downImage = { 0,0, 31,15, 1, arr_downData, 0x1,0x0, NULL };

static UWORD __chip arr_leftData[] =
   {
   0x0006, 0x0000,    /* .............##................. */
   0x001e, 0x0000,    /* ...........####................. */
   0x007e, 0x0000,    /* .........######................. */
   0x01fe, 0x0000,    /* .......########................. */
   0x07ff, 0xfff8,    /* .....########################... */
   0x1fff, 0xfff8,    /* ...##########################... */
   0x7fff, 0xfff8,    /* .############################... */
   0x1fff, 0xfff8,    /* ...##########################... */
   0x07ff, 0xfff8,    /* .....########################... */
   0x01fe, 0x0000,    /* .......########................. */
   0x007e, 0x0000,    /* .........######................. */
   0x001e, 0x0000,    /* ...........####................. */
   0x0006, 0x0000,    /* .............##................. */
   };
struct Image arr_leftImage = { 0,0, 31,13, 1, arr_leftData, 0x1,0x0, NULL };


static UWORD __chip arr_rightData[] =
   {
   0x0003, 0x0000,    /* ..............##................ */
   0x0003, 0xc000,    /* ..............####.............. */
   0x0003, 0xf000,    /* ..............######............ */
   0x0003, 0xfc00,    /* ..............########.......... */
   0xffff, 0xff00,    /* ########################........ */
   0xffff, 0xffc0,    /* ##########################...... */
   0xffff, 0xfff0,    /* ############################.... */
   0xffff, 0xffc0,    /* ##########################...... */
   0xffff, 0xff00,    /* ########################........ */
   0x0003, 0xfc00,    /* ..............########.......... */
   0x0003, 0xf000,    /* ..............######............ */
   0x0003, 0xc000,    /* ..............####.............. */
   0x0003, 0x0000,    /* ..............##................ */
   };
struct Image arr_rightImage = { 0,0, 31,13, 1, arr_rightData, 0x1,0x0, NULL };


static UWORD __chip buttonData[] =
   {
   0x000f, 0xfe00, 0x0000,    /* ............###########......................... */
   0x00ff, 0xffe0, 0x0000,    /* ........###################..................... */
   0x03ff, 0xfff8, 0x0000,    /* ......#######################................... */
   0x0ffc, 0x07fe, 0x0000,    /* ....##########.......##########................. */
   0x1fe0, 0x00ff, 0x0000,    /* ...########.............########................ */
   0x3fc0, 0x007f, 0x8000,    /* ..########...............########............... */
   0x3f80, 0x003f, 0x8000,    /* ..#######.................#######............... */
   0x7f00, 0x001f, 0xc000,    /* .#######...................#######.............. */
   0x7f00, 0x001f, 0xc000,    /* .#######...................#######.............. */
   0x7f00, 0x001f, 0xc000,    /* .#######...................#######.............. */
   0x3f80, 0x003f, 0x8000,    /* ..#######.................#######............... */
   0x3fc0, 0x007f, 0x8000,    /* ..########...............########............... */
   0x1fe0, 0x00ff, 0x0000,    /* ...########.............########................ */
   0x0ffc, 0x07fe, 0x0000,    /* ....##########.......##########................. */
   0x03ff, 0xfff8, 0x0000,    /* ......#######################................... */
   0x00ff, 0xffe0, 0x0000,    /* ........###################..................... */
   0x000f, 0xfe00, 0x0000,    /* ............###########......................... */

   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0003, 0xf800, 0x0000,    /* ..............#######........................... */
   0x001f, 0xff00, 0x0000,    /* ...........#############........................ */
   0x003f, 0xff80, 0x0000,    /* ..........###############....................... */
   0x007f, 0xffc0, 0x0000,    /* .........#################...................... */
   0x00ff, 0xffe0, 0x0000,    /* ........###################..................... */
   0x00ff, 0xffe0, 0x0000,    /* ........###################..................... */
   0x00ff, 0xffe0, 0x0000,    /* ........###################..................... */
   0x007f, 0xffc0, 0x0000,    /* .........#################...................... */
   0x003f, 0xff80, 0x0000,    /* ..........###############....................... */
   0x001f, 0xff00, 0x0000,    /* ...........#############........................ */
   0x0003, 0xf800, 0x0000,    /* ..............#######........................... */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */

   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   0x0000, 0x0000, 0x0000,    /* ................................................ */
   };
struct Image buttonImage = { 0,0, 34,17, 3, buttonData, 0x7,0x0, NULL };

/*- */
/* ---------------------------------------------------------------------- */
/*+ "structs & global variables" */
struct  GfxBase *GfxBase = NULL;
struct  IntuitionBase *IntuitionBase = NULL;
struct  Library *GadToolsBase = NULL;
struct  Library *LowLevelBase = NULL;
struct  Screen *mysc = NULL;
struct  Menu *menu = NULL;
struct  Window *mywin = NULL;
void    *vi = NULL;
struct  DrawInfo *dri = NULL;

BOOL    shell;
BOOL    terminated;
ULONG   joyport;
/*- */
/* ---------------------------------------------------------------------- */
/*+ "int main(int argc, char *argv[])" */
int
main(int argc, char *argv[])
{
        struct  IntuiMessage *imsg;
        ULONG   imsgClass;
        UWORD   imsgCode;
        ULONG   joystick;
        ULONG   o_joy;
/*        struct  TagItem tags[1]; */
/* no more need for tags, using SetJoyPortAttrs instead of SetJoyPortAttrsA */

        shell = TRUE;
/*        shell = FALSE; */
        terminated = FALSE;
        joyport = 1;
        joystick = 0;
        o_joy = 0;
/* ---------------------------------------------------------------------- */
        if (shell) puts("Do NOT run me from the ZSHell !!!");
/*+ "args" */
        if (argc == 2)
        {
                printf("Usage:\n\tJoystick <options>\nwhat options???\n");
                bail_out(0);
        }
/*- */
/*+ "Open all libraries" */
        if (!(GfxBase = (struct GfxBase *) OpenLibrary((UBYTE *)"graphics.library", 39L)))
                bail_out(20);

        if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary((UBYTE *)"intuition.library", 39L)))
                bail_out(20);

        if (!(GadToolsBase = OpenLibrary((UBYTE *)"gadtools.library", 39L)))
                bail_out(20);

        if (!(LowLevelBase = OpenLibrary((UBYTE *)"lowlevel.library", 40L)))
                bail_out(20);

        if (!(mysc = LockPubScreen(NULL)))
                bail_out(20);

        if (!(vi = GetVisualInfo(mysc,
            TAG_DONE)))
                bail_out(20);

        if (!(dri = GetScreenDrawInfo(mysc)))
                bail_out(20);
#ifdef DEBUG
        if (shell) puts("libraries opened!");
#endif
/*- */
/*+ "create menu and open window" */
        if (!(menu = CreateMenus(mynewmenu,
                TAG_DONE)))
        {
                bail_out(20);
        }

        if (!LayoutMenus(menu, vi,
/*        GTMN_TextAttr, tattr, */
                GTMN_NewLookMenus, TRUE,
                TAG_DONE))
                bail_out(20);

        if (!(mywin = OpenWindowTags(NULL,
                WA_InnerWidth, 150,
                WA_InnerHeight, 100,
                WA_Top, 50,
                WA_Left, 50,

                WA_Activate, TRUE,
                WA_DragBar, TRUE,
                WA_DepthGadget, TRUE,
                WA_CloseGadget, TRUE,
/*                WA_SizeGadget, TRUE, */
                WA_SmartRefresh, TRUE,

/* NOTE: NOCAREREFRESH is not allowed if you use GadTools Gadgets! */
                WA_NoCareRefresh, TRUE,

                WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_MENUPICK,

                WA_MaxWidth,  150,
                WA_MaxHeight, 100,
                WA_MinWidth,  150,
                WA_MinHeight, 100,
                WA_Title, "Joystick",
                WA_ScreenTitle, "Joystick Tester ©1997 Christian T. Steigies",
                WA_NewLookMenus, TRUE,
                TAG_DONE)))
                bail_out(20);

        SetMenuStrip(mywin, menu);
#ifdef DEBUG
        if (shell) puts("window opened!");
#endif

/*- */
/* ---------------------------------------------------------------------- */
/*+ "main loop" */
    if (!SetJoyPortAttrs( joyport, SJA_TYPE_JOYSTK )) {
            if (shell) puts("Failure!");
    }
    while (!terminated)
    {
/*        if (!SetJoyPortAttrs( joyport, SJA_TYPE_JOYSTK )) {
                if (shell) puts("Failure!");
        } */
        joystick = ReadJoyPort(joyport); /* & (JP_DIRECTION_MASK | JP_BUTTON_MASK); */
        HandleJoyportEvent(joystick);

        if (imsg = (struct IntuiMessage *)GetMsg(mywin->UserPort))
        {
            if (shell) printf("current joyport is: %d\n",joyport);
            imsgClass = imsg->Class;
            imsgCode = imsg->Code;
            ReplyMsg((struct Message *)imsg);
            switch (imsgClass) {
                case IDCMP_MENUPICK:
                    terminated = HandleMenuEvent(imsgCode);
                    break;

                case IDCMP_CLOSEWINDOW:
                    if (shell) printf("CLOSEWINDOW.\n");
                    terminated = TRUE;
                    break;
            } /* switch */
        } /* if */
        Delay(1);
    } /* while */
/*- */
/* ---------------------------------------------------------------------- */
        bail_out(0);
}
/*- */
/* ---------------------------------------------------------------------- */
/*+ "void bail_out(int code)" */
/*
 * Function to close down or free any opened or allocated stuff, and then
 * exit.
 *
 */
void
bail_out(int code)
{
        int     i;


        if (LowLevelBase)
        {
                for (i = 0; i++; i <= 3) {
                        SetJoyPortAttrs(i, SJA_Reinitialize);
                } /* for */

                CloseLibrary(LowLevelBase);
        }

        if (mywin)
        {
                ClearMenuStrip(mywin);
                CloseWindow(mywin);
        }

    /* None of these two calls mind a NULL parameter, so it's not
     * necessary to check for non-NULL before calling.  If we do that,
     * we must be certain that the OpenLibrary() of GadTools succeeded,
     * or else we would be jumping into outer space:
     */
        if (GadToolsBase)
        {
                FreeMenus(menu);
                FreeVisualInfo(vi);
                CloseLibrary(GadToolsBase);
        }

        if (dri)
        {
                FreeScreenDrawInfo( mysc, dri );
        }

        if (mysc)
        {
                UnlockPubScreen(NULL, mysc);
        }

        if (IntuitionBase)
        {
                CloseLibrary( (struct Library *) IntuitionBase );
        }

        if (GfxBase)
        {
                CloseLibrary( (struct Library *) GfxBase );
        }

        exit(code);
}

/*- */
/* ---------------------------------------------------------------------- */
/*+ "BOOL HandleMenuEvent(UWORD code)" */
/*
 * This function handles IntuiMessage events of type MENUPICK.
 *
 */
BOOL
HandleMenuEvent(UWORD code)
{
    /* Your code goes here */
#ifdef DEBUG
        if (shell) {
                printf( "imsgCode: %i\t",code );
                printf( "Menu Nr.: %i\t",( MENUNUM(code) ) );
                printf( "Item Nr.: %i\t",( ITEMNUM(code) ) );
                printf( "Sub  Nr.: %i\n",( SUBNUM(code) ) );
        }
#endif
        switch (MENUNUM(code)) {
                case 0: /* Project */
                        switch (ITEMNUM(code))
                        {
                                case 0: /* About */
                                        if (shell) puts("About!");
                                        break;
                                case 2: /* Quit */
                                        if (shell) puts("Terminated by Menu :-(");
                                        return TRUE;
                                        break;
                        }
                       break;
                case 1: /* Options */
                        switch (ITEMNUM(code))
                        {
                                case 0: /* Port 0 */
                                        if (shell) puts("Joystick in Port 0 selected");
                                        if (!SetJoyPortAttrs(0 , SJA_TYPE_JOYSTK)) {
                                                if (shell) puts("Failure!");
                                        }
                                        joyport = 0;
                                        break;
                                case 1: /* Port 1 */
                                        if (shell) puts("Joystick in Port 1 selected");
                                        if (!SetJoyPortAttrs(1 , SJA_TYPE_JOYSTK)) {
                                                if (shell) puts("Failure!");
                                        }
                                        joyport = 1;
                                        break;
                                case 2: /* Port 2 */
                                        if (shell) puts("Joystick in Port 2 selected (4-player adapter)");
                                        if (!SetJoyPortAttrs(2 , SJA_TYPE_JOYSTK)) {
                                                if (shell) puts("Failure!");
                                        }
                                        joyport = 2;
                                        break;
                                case 3: /* Port 3 */
                                        if (shell) puts("Joystick in Port 3 selected (4-player adapter)");
                                        if (!SetJoyPortAttrs(3 , SJA_TYPE_JOYSTK)) {
                                                if (shell) puts("Failure!");
                                        }
                                        joyport = 3;
                                        break;
                        }
                        break;
        }
        return(FALSE);
}
/*- */
/* ---------------------------------------------------------------------- */
/*+ "BOOL HandleJoyportEvent(ULONG joystick)" */
BOOL
HandleJoyportEvent(ULONG joystick)
{
/* SystemControlA() ?*/
#ifdef DEBUG
        BOOL    newline;

        newline = FALSE;
        if (joystick & JP_TYPE_JOYSTK) {
            if (shell) puts("Joystick");
        }
        if (joystick & JP_TYPE_MOUSE) {
            if (shell) puts("Mouse");
        }
        if (joystick & JP_TYPE_NOTAVAIL) {
            if (shell) puts("Notavail");
        }
        if (joystick & JP_TYPE_GAMECTLR) {
            if (shell) puts("Game");
        }
        if (joystick & JP_TYPE_UNKNOWN) {
            if (shell) puts("Unknown");
        }
#endif

        if (joystick & JPF_BUTTON_RED) {
            DrawImage(mywin->RPort, &buttonImage, 20-3, 20);
#ifdef DEBUG
            if (shell) printf("LEFT FIRE BUTTON ");
            newline = TRUE;
#endif
        } else {
            DrawImage(mywin->RPort, &emptyImage, 20-3, 20);
        }

        if (joystick & JPF_BUTTON_BLUE) {
            DrawImage(mywin->RPort, &buttonImage, 100-3, 20);
#ifdef DEBUG
            if (shell) printf("RIGHT FIRE BUTTON ");
            newline = TRUE;
#endif
        } else {
            DrawImage(mywin->RPort, &emptyImage, 100-3, 20);
        }

        if (joystick & JPF_BUTTON_PLAY) {
            DrawImage(mywin->RPort, &buttonImage, 60-3, 20);
#ifdef DEBUG
            if (shell) printf("MIDDLE FIRE BUTTON ");
            newline = TRUE;
#endif
        } else {
            DrawImage(mywin->RPort, &emptyImage, 60-3, 20);
        }

        if (joystick & JPF_JOY_UP) {
            DrawImage(mywin->RPort, &arr_upImage, 60, 40);
#ifdef DEBUG
            if (shell) printf("UP ");
            newline = TRUE;
#endif
        } else {
            DrawImage(mywin->RPort, &emptyImage, 60, 40);
        }

        if (joystick & JPF_JOY_DOWN) {
            DrawImage(mywin->RPort, &arr_downImage, 60, 80);
#ifdef DEBUG
            if (shell) printf("DOWN ");
            newline = TRUE;
#endif
        } else {
            DrawImage(mywin->RPort, &emptyImage, 60, 80);
        }

        if (joystick & JPF_JOY_LEFT) {
            DrawImage(mywin->RPort, &arr_leftImage, 20, 60);
#ifdef DEBUG
            if (shell) printf("LEFT ");
            newline = TRUE;
#endif
        } else {
            DrawImage(mywin->RPort, &emptyImage, 20, 60);
        }

        if (joystick & JPF_JOY_RIGHT) {
            DrawImage(mywin->RPort, &arr_rightImage, 100, 60);
#ifdef DEBUG
            if (shell) printf("RIGHT ");
            newline = TRUE;
#endif
        } else {
            DrawImage(mywin->RPort, &emptyImage, 100, 60);
        }

#ifdef DEBUG
        if (newline) {
            if (shell) printf("\n");
            newline = FALSE;
        }
#endif
        return(TRUE);
}
/*- */
/* ---------------------------------------------------------------------- */

