home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / CD32 / CD32_Support / examples / SA_Examples / lowlevel / GameControl / GameControl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-31  |  14.8 KB  |  537 lines

  1. /* GameControl.c
  2.  * 
  3.  * CLI usage:
  4.  *     [run] gamecontrol [screen <PubScreenName>]
  5.  * Workbench usage:
  6.  *     double-click on the icon
  7.  *
  8.  * The purpose of this beastie is to test the mechanical contacts on the game
  9.  * controller to see if there are any spurious directions.  It's quite
  10.  * visual.  To test, simply run this from CLI or Workbench, and have a game
  11.  * controller plugged into Port 0.  Press the directional keypad in such
  12.  * a way as to go along a straight line in one direction.  If you don't,
  13.  * there's a problem with the controller.
  14.  *
  15.  * It also happens to be yet another test of lowlevel.library's
  16.  * SystemControl(SCON_AddCreateKeys) function, which is why it lives
  17.  * where it lives on the server.
  18.  *
  19.  * $VER: GameControl_c 1.1 (18.05.93) by J.W. Lockhart
  20.  *
  21.  */
  22.  
  23. /* Includes --------------------------------------------- */
  24. #include <exec/types.h>
  25. #include <exec/libraries.h>
  26. #include <exec/memory.h>
  27. #include <dos/dos.h>
  28. #include <dos/rdargs.h>
  29. #include <graphics/gfx.h>
  30. #include <graphics/display.h>
  31. #include <graphics/rastport.h>
  32. #include <graphics/regions.h>
  33. #include <graphics/text.h>
  34. #include <graphics/view.h>
  35. #include <graphics/rpattr.h>
  36. #include <intuition/intuition.h>
  37. #include <intuition/screens.h>
  38. #include <libraries/lowlevel.h>
  39. #include <clib/exec_protos.h>
  40. #include <clib/dos_protos.h>
  41. #include <clib/graphics_protos.h>
  42. #include <clib/lowlevel_protos.h>
  43. #include <clib/intuition_protos.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46.  
  47. #include <pragmas/lowlevel_pragmas.h>
  48.  
  49. #include "gamecontrol_protos.h"
  50.  
  51. /* Defines ------------------------------------------ */
  52. #ifndef PROGNAME
  53.     /* conditional so that we can redefine it for the Wrap version */
  54. #define PROGNAME "GameControl"
  55. #endif
  56. #define ERRMSG_LIBNOOPEN "Couldn't open %s V%ld (or better)!\n"
  57. #define TEMPLATE "SCREEN"
  58. #define MAX_XGRID 31       /* 31 horizontal boxes           */
  59. #define MAX_YGRID  9       /* 9 vertical boxes              */
  60. #define GRIDSIZE  20       /* 20 pixels by 20 pixels        */
  61. #define PEN_FG    1        /* foreground/text pen           */
  62. #define PEN_BG    0        /* background/transparent pen    */
  63. #define PEN_HI    3        /* highlight pen                 */
  64. #define PEN_FLASH 4        /* flash pen (shine)             */
  65.  
  66.  
  67. /* Structs ------------------------------ */
  68. struct Opts {
  69.     STRPTR screen;
  70. };
  71.  
  72. /* Protos ------------------------------------------ */
  73. static VOID GoodBye(int);
  74. static LONG doInit(VOID);
  75. extern VOID KPrintF(STRPTR,...);
  76.  
  77. /* Globals --------------------------------------- */
  78. struct Opts     opts;
  79. struct RDArgs  *rdargs;
  80. struct Library *IntuitionBase;
  81. struct Library *GfxBase;
  82. struct Library *LowLevelBase;
  83. struct Library *KeymapBase;
  84. struct Window  *win;
  85. struct RastPort *rp;
  86. struct EasyStruct easyStruct, *ez;
  87. UBYTE  ezBuf[100];
  88. BOOL   cliStart, keysOn;
  89. struct Rectangle grid[MAX_XGRID][MAX_YGRID];
  90. int    curX, curY;              /* actually, current grid[][] numbers */
  91.  
  92. VOID main(int argc, UBYTE *argv[]) {
  93.     struct Screen *scr;
  94.     UWORD code, qual;
  95.     ULONG class;
  96.     struct IntuiMessage *msg;
  97.  
  98.     cliStart = (argc != 0);
  99.     ez = &easyStruct;
  100.     ez->es_StructSize = sizeof(struct EasyStruct);
  101.     ez->es_Flags = NULL;
  102.     ez->es_GadgetFormat = "OK";
  103.     ez->es_Title = PROGNAME;
  104.  
  105.     if (!doInit()) {
  106.         GoodBye(RETURN_FAIL);
  107.     }
  108.  
  109.     if (!turnOnLLKeys(TRUE)) {
  110.         ezReq("SystemControl() failed!\nCannot read controller!", NULL);
  111.         GoodBye(RETURN_FAIL);
  112.     }
  113.     keysOn = TRUE;
  114.  
  115.     if (scr = LockPubScreen(opts.screen)) {  /* null opts.screen == Workbench */
  116.         win = OpenWindowTags(NULL, 
  117.                              WA_Title, PROGNAME,
  118.                              WA_PubScreen, scr,
  119.                              WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_REFRESHWINDOW|IDCMP_NEWSIZE,
  120.                              WA_RMBTrap, TRUE,
  121.                              WA_InnerWidth, 620,
  122.                              WA_InnerHeight, 180,
  123.                              WA_DragBar, TRUE,
  124.                              WA_CloseGadget, TRUE,
  125.                              WA_DepthGadget, TRUE,
  126.                              WA_SizeGadget, FALSE,
  127.                              WA_Activate, TRUE,
  128.                              WA_SimpleRefresh, TRUE,
  129.                              TAG_DONE);
  130.         UnlockPubScreen(NULL,scr);
  131.     }
  132.     else {
  133.         ezReq("Can't lock screen to open window!\n", NULL);
  134.         GoodBye(RETURN_FAIL);
  135.     }
  136.  
  137.     if (!win) {
  138.         ezReq("Can't open window!\n", NULL);
  139.         GoodBye(RETURN_FAIL);
  140.     }
  141.  
  142.     rp = win->RPort;
  143.     initGrid();
  144.     drawGrid();
  145.  
  146.     curX = MAX_XGRID / 2 ;
  147.     curY = MAX_YGRID / 2 ;
  148.     liteBox(curX, curY);
  149.  
  150.     while (1) {
  151.         WaitPort(win->UserPort);
  152.         while (msg = (struct IntuiMessage *)GetMsg(win->UserPort)) {
  153.             class = msg->Class;
  154.             code  = msg->Code;
  155.             qual  = msg->Qualifier;
  156.             switch (class) {
  157.                 case IDCMP_CLOSEWINDOW:
  158.                     ReplyMsg((struct Message *)msg);
  159.                     GoodBye(RETURN_OK);
  160.                     break;
  161.                 case IDCMP_MOUSEMOVE:
  162.                 case IDCMP_MOUSEBUTTONS:
  163.                 case IDCMP_RAWKEY:
  164.                     /* we look for PORT(anything) in case we ever need to... */
  165.                     switch (code) {
  166.                         case RAWKEY_PORT0_BUTTON_PLAY:
  167.                             break;
  168.                         case RAWKEY_PORT0_JOY_UP:
  169.                         case RAWKEY_PORT1_JOY_UP:
  170.                         case RAWKEY_PORT2_JOY_UP:
  171.                         case RAWKEY_PORT3_JOY_UP:
  172.                             changeBox(curX, curY, curX, curY-1);
  173.                             break;
  174.                         case RAWKEY_PORT0_JOY_DOWN:
  175.                         case RAWKEY_PORT1_JOY_DOWN:
  176.                         case RAWKEY_PORT2_JOY_DOWN:
  177.                         case RAWKEY_PORT3_JOY_DOWN:
  178.                             changeBox(curX, curY, curX, curY+1);
  179.                             break;
  180.                         case RAWKEY_PORT0_JOY_LEFT:
  181.                         case RAWKEY_PORT1_JOY_LEFT:
  182.                         case RAWKEY_PORT2_JOY_LEFT:
  183.                         case RAWKEY_PORT3_JOY_LEFT:
  184.                             changeBox(curX, curY, curX-1, curY);
  185.                             break;
  186.                         case RAWKEY_PORT0_JOY_RIGHT:
  187.                         case RAWKEY_PORT1_JOY_RIGHT:
  188.                         case RAWKEY_PORT2_JOY_RIGHT:
  189.                         case RAWKEY_PORT3_JOY_RIGHT:
  190.                             changeBox(curX, curY, curX+1, curY);
  191.                             break;
  192.                         default:
  193.                             break;
  194.                     }
  195.                     break;
  196.                 case IDCMP_VANILLAKEY:
  197.                     /* shouldn't get it */
  198.                     break;
  199.                 case IDCMP_NEWSIZE:
  200.                 case IDCMP_REFRESHWINDOW:
  201.                     drawGrid();
  202.                     liteBox(curX, curY);
  203.                     break;
  204.                 
  205.                 default:
  206.                     break;
  207.             }
  208.             ReplyMsg((struct Message *)msg);
  209.         }
  210.     }
  211.  
  212.     GoodBye(RETURN_OK);
  213. }
  214.  
  215. /* turnOnLLKeys ===============================================================
  216.    use lowlevel.library/SystemControl() to turn on the flow of RawKey
  217.    game controller events to our task (TRUE), or to turn them off (FALSE).
  218.    Returns TRUE for success, FALSE otherwise.
  219.  */
  220. BOOL turnOnLLKeys(BOOL on) {
  221.     ULONG retVal;
  222.  
  223.     if (on) {
  224.         retVal = SystemControl(SCON_AddCreateKeys, 1UL, TAG_DONE);
  225.     }
  226.     else {
  227.         retVal = SystemControl(SCON_RemCreateKeys, 1UL, TAG_DONE);
  228.     }
  229.  
  230.     return((BOOL)(retVal == 0UL));
  231. }
  232.  
  233. #ifdef DEBUG
  234. /* dumpBox =====================================================
  235.    debugging tool, tells grid number and Rectangle coordinates
  236.  */
  237. VOID dumpBox(STRPTR desc, int boxX, int boxY) {
  238.     KPrintF("%s: [%ld][%ld] = %ld, %ld, %ld, %ld\n",
  239.              desc,
  240.              (LONG)boxX,
  241.              (LONG)boxY,
  242.              (LONG)grid[boxX][boxY].MinX,
  243.              (LONG)grid[boxX][boxY].MinY,
  244.              (LONG)grid[boxX][boxY].MaxX,
  245.              (LONG)grid[boxX][boxY].MaxY);
  246. }
  247. #endif
  248.  
  249.  
  250. /* changeBox ============================================
  251.    If valid new box, re-grid the old one and highlight
  252.    the new one.  change global curX and curY.
  253.  
  254.    Else if invalid new box, just flash the old one
  255.    and don't change anything.
  256.  
  257.    Inputs are xy coords for grid[][]
  258.       (grid[x][y])
  259. */
  260. VOID changeBox(int oldX, int oldY, int newX, int newY) {
  261.  
  262.     /* only 1 coordinate will be changing,
  263.        but it can't change beyond our array limits
  264.      */
  265.  
  266. #ifdef WRAP
  267.     if (newX >= MAX_XGRID) {
  268.         newX = 0;
  269.     }
  270.     if (newX < 0) {
  271.         newX = MAX_XGRID-1;
  272.     }
  273.     if (newY >= MAX_YGRID) {
  274.         newY = 0;
  275.     }
  276.     if (newY < 0) {
  277.         newY = MAX_YGRID-1;
  278.     }
  279. #else
  280.     if ((newX >= MAX_XGRID) || (newX < 0)) {
  281.         flashBox(oldX, oldY);
  282.         return;
  283.     }
  284.     if ((newY >= MAX_YGRID) || (newY < 0)) {
  285.         flashBox(oldX, oldY);
  286.         return;
  287.     }
  288. #endif
  289.  
  290. /*
  291.     dumpBox("Old", oldX, oldY);
  292.     dumpBox("New", newX, newY);
  293. */
  294.  
  295.     gridBox(oldX, oldY);
  296.     liteBox(newX, newY);
  297.     curX = newX;
  298.     curY = newY;
  299.  
  300.     return;
  301. }
  302.  
  303. /* flashBox ==================================================
  304.  */
  305. VOID flashBox(int x, int y) {
  306.     WORD miX, miY, maX, maY;
  307.  
  308.     miX = grid[x][y].MinX + 2;
  309.     miY = grid[x][y].MinY + 2;
  310.     maX = grid[x][y].MaxX - 2;
  311.     maY = grid[x][y].MaxY - 2;
  312.  
  313.     SetAPen(rp, PEN_FLASH);
  314.     RectFill(rp, miX, miY, maX, maY);
  315.  
  316.     Delay(2L);
  317.  
  318.     SetAPen(rp, PEN_HI);
  319.     RectFill(rp, miX, miY, maX, maY);
  320.  
  321.     return;
  322. }
  323.  
  324. /* gridBox ===================================================
  325.    Draw a grid around a box.  That is, fill the box with black,
  326.    allow for borders, then fill the smaller box with grey.
  327.    Inputs are valid x and y such that "grid[x][y]" is a valid
  328.    reference.
  329.  */
  330. VOID gridBox(int x, int y) {
  331.     WORD miX, miY, maX, maY;
  332.  
  333.     miX = grid[x][y].MinX;
  334.     miY = grid[x][y].MinY;
  335.     maX = grid[x][y].MaxX;
  336.     maY = grid[x][y].MaxY;
  337.  
  338.     SetAPen(rp, PEN_FG);
  339.     RectFill(rp, miX, miY, maX, maY);
  340.  
  341.     miX += 2;
  342.     miY += 2;
  343.     maX -= 2;
  344.     maY -= 2;
  345.  
  346.     SetAPen(rp, PEN_BG);
  347.     RectFill(rp, miX, miY, maX, maY);
  348.  
  349.     return;
  350. }
  351.  
  352. /* liteBox ===================================================
  353.     Highlight a box, leaving the borders ("grid") intact.
  354.  */
  355. VOID liteBox(int x, int y) {
  356.     WORD miX, miY, maX, maY;
  357.  
  358.     miX = grid[x][y].MinX + 2;
  359.     miY = grid[x][y].MinY + 2;
  360.     maX = grid[x][y].MaxX - 2;
  361.     maY = grid[x][y].MaxY - 2;
  362.  
  363.     SetAPen(rp, PEN_HI);
  364.     RectFill(rp, miX, miY, maX, maY);
  365.  
  366.     return;
  367. }
  368.  
  369.  
  370. /* drawGrid =========================================
  371.     actually, does a bunch of rectfills :-)
  372.     Easier to adjust the grid thickness that way.
  373.  */
  374. VOID drawGrid(VOID) {
  375.     int i, j;
  376.     SHORT mix, miy, maX, maY, minVal, maxVal;
  377.  
  378.  
  379.     SetAPen(rp,PEN_FG);
  380.     SetDrMd(rp,JAM1);
  381.  
  382.     minVal = grid[0][0].MinY;
  383.     maxVal = grid[0][MAX_YGRID-1].MaxY;
  384.     for (i = 1; i < MAX_XGRID; i++) {
  385.         mix = grid[i][MAX_YGRID-1].MinX - 1;
  386.         maX = grid[i][MAX_YGRID-1].MinX + 1;
  387.         RectFill(rp, mix, minVal, maX, maxVal);
  388.     }
  389.  
  390.     minVal = grid[0][0].MinX;
  391.     maxVal = grid[MAX_XGRID-1][0].MaxX;
  392.     for (j = 1; j < MAX_YGRID; j++) {
  393.         miy = grid[MAX_XGRID-1][j].MinY - 1;
  394.         maY = grid[MAX_XGRID-1][j].MinY + 1;
  395.         RectFill(rp, minVal, miy, maxVal, maY);
  396.     }
  397.  
  398.     /* now the special case, the outer borders...should also look snazzy. */
  399.  
  400.     /* top */
  401.     RectFill(rp,grid[0][0].MinX, grid[0][0].MinY, grid[MAX_XGRID-1][0].MaxX, grid[0][0].MinY+1);
  402.  
  403.     /* right */
  404.     RectFill(rp,grid[MAX_XGRID-1][0].MaxX-1,grid[MAX_XGRID-1][0].MinY,grid[MAX_XGRID-1][0].MaxX,grid[MAX_XGRID-1][MAX_YGRID-1].MaxY);
  405.  
  406.     /* bottom */
  407.     RectFill(rp,grid[0][MAX_YGRID-1].MinX,grid[0][MAX_YGRID-1].MaxY-1,grid[MAX_XGRID-1][0].MaxX,grid[0][MAX_YGRID-1].MaxY);
  408.  
  409.     /* left */
  410.     RectFill(rp,grid[0][0].MinX, grid[0][0].MinY,grid[0][0].MinX+1,grid[0][MAX_YGRID-1].MaxY);
  411.  
  412.     return;
  413. }
  414.  
  415. /* initGrid =======================================
  416.    fill in values for grid
  417.  */
  418. VOID initGrid(VOID) {
  419.     int i, j, row, col, winBottom, winRight, rowAdj, colAdj;
  420.  
  421.     row = win->BorderLeft;
  422.     winBottom = win->Height - win->BorderBottom - 1;
  423.     winRight =  win->Width - (win->BorderLeft + win->BorderRight - 1);
  424.     rowAdj = GRIDSIZE;
  425.  
  426.     for (i = 0; i < MAX_XGRID; i++) {
  427.         /* move across */
  428.         col = win->BorderTop;
  429.         colAdj = GRIDSIZE;
  430.         for (j = 0; j < MAX_YGRID; j++) {
  431.             /* then move down each column */
  432.             grid[i][j].MinX = row;
  433.             grid[i][j].MinY = col;
  434.             grid[i][j].MaxX = row + rowAdj;
  435.             grid[i][j].MaxY = col + colAdj;
  436.             col += GRIDSIZE;
  437.             if ((col+colAdj) > winBottom) {
  438.                 colAdj = winBottom - col;
  439.             }
  440.         }
  441.         row += GRIDSIZE;
  442.         if ((row+rowAdj) >= winRight) {
  443.             rowAdj = winRight - row;
  444.         }
  445.     }
  446.     return;
  447. }
  448.  
  449. /* ezReq ================================================================
  450.    Pop up an EasyRequester to tell the user something.  Since we
  451.    only offer "OK" to click upon, we don't return anything.
  452.  */
  453. VOID ezReq(STRPTR str, APTR arg1, ...) {
  454.  
  455.     ez->es_TextFormat = str;
  456.     EasyRequestArgs(win, ez, NULL, &arg1);
  457.  
  458.     return;
  459. }
  460.  
  461. /* GoodBye ===============================================
  462.    Clean-exit routine.
  463.  */
  464. static VOID GoodBye(int rc) {
  465.  
  466.     if (win) {
  467.         CloseWindow(win);
  468.     }
  469.  
  470.     if (keysOn) {
  471.         turnOnLLKeys(FALSE);
  472.     }
  473.  
  474.     if (KeymapBase) {
  475.         CloseLibrary(KeymapBase);
  476.     }
  477.  
  478.     if (LowLevelBase) {
  479.         CloseLibrary(LowLevelBase);
  480.     }
  481.  
  482.     if (GfxBase) {
  483.         CloseLibrary(GfxBase);
  484.     }
  485.  
  486.     if (IntuitionBase) {
  487.         CloseLibrary(IntuitionBase);
  488.     }
  489.  
  490.     if (rdargs) {
  491.         FreeArgs(rdargs);
  492.     }
  493.  
  494.     exit(rc);
  495. }
  496.  
  497. /* doInit =============================================
  498.  * Open libraries, call ReadArgs() if necessary.
  499.  * Returns TRUE for success, FALSE otherwise.
  500.  */
  501. static LONG doInit(VOID) {
  502.     if (cliStart) {
  503.         rdargs = ReadArgs(TEMPLATE, (LONG *)&opts, NULL);
  504.         if (!rdargs) {
  505.             PrintFault(IoErr(), PROGNAME);
  506.             return(FALSE);
  507.         }
  508.     }
  509.  
  510.     IntuitionBase = OpenLibrary("intuition.library", 37L);
  511.     if (!IntuitionBase) {
  512.         Printf(ERRMSG_LIBNOOPEN, "intuition.library", 37L);
  513.         return(FALSE);
  514.     }
  515.  
  516.     GfxBase = OpenLibrary("graphics.library", 37L);
  517.     if (!GfxBase) {
  518.         ezReq(ERRMSG_LIBNOOPEN, "graphics.library", 37L);
  519.         return(FALSE);
  520.     }
  521.  
  522.     LowLevelBase = OpenLibrary("lowlevel.library", 40L);
  523.     if (!LowLevelBase) {
  524.         ezReq(ERRMSG_LIBNOOPEN, "lowlevel.library", 40L);
  525.         return(FALSE);
  526.     }
  527.  
  528.     /* in case we ever use keyboard events such as cursor_up, etc. */
  529.     KeymapBase = OpenLibrary("keymap.library", 0L);
  530.     if (!KeymapBase) {
  531.         ezReq(ERRMSG_LIBNOOPEN, "keymap.library", 0L);
  532.         return(FALSE);
  533.     }
  534.     return(TRUE);
  535. }
  536.  
  537.