home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff247.lzh
/
AnalogJoystick
/
JoyDemo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-09-15
|
15KB
|
427 lines
/*********************************************************/
/* */
/* ANALOG JOYSTICK DEMO */
/* */
/* Copyright (c) 1989, David Kinzer, All Rights Reserved */
/* */
/* Permission hereby granted to redistribute this */
/* program in unmodified form in a not for profit manner.*/
/* */
/* Permission hereby granted to use this software freely */
/* in programs, commercial or not. */
/* */
/*********************************************************/
/* */
/* JoyDemo.c */
/* */
/* This program demonstrates the use of an Analog */
/* Joystick input device on the Amiga (tm) Computer. */
/* This program also demonstrates the use of libraries, */
/* screens, and windows. */
/* */
/* */
/*********************************************************/
/* The following includes some header files which define
some types and structures used by this program. Note
that these include files will themselves include more
files so that everything they need is also included. */
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
/* Include our own defines for the Joystick portion of
the program. The use of quotes around the include
file name tells the compiler to look in the current
directory for the specified file. If not found, the
compiler will look in the default library. */
#include "ajoystick.h"
/* The following variables are required to use the
libraries. The libraries are loaded into ram so many
programs can use them at the same time. This
reduces duplication and therefore reduces the ammount
of ram needed for multitasking. These variables are
pointers to the base of the library entry point. They
must be global variables so the 'C' library routines
(which call the actual Amiga library routines) can
find them during the linking process. The 'C' library
routine adds an offset to this pointer and goes to the
subroutine located there. */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
/* The following will be used during the open library to
ask for a particular revision or greater in the
library. A value of Zero says open any revision.
This would be useful if you used one of the new version
1.2 routines which did not exist in V1.1. If you
were to call a non-existant routine, the system will
crash. */
#define INTUITION_REV 0L
#define GRAPHICS_REV 0L
/* Here we define the height of the title bar on a
window so our program will be able to skip over
that space, as well as the width of the window
boarders. */
#define TITLEHEIGHT 10L
#define BOTTOMWIDTH 1L
#define LEFTWIDTH 2L
#define RIGHTWIDTH 2L
/* Here is where we will define the font that we will
use for our display. It defines the font that will
be used by the text function for rendering in any
window on our screen. */
struct TextAttr MyFont =
{
(STRPTR)"topaz.font", /* Font Name */
TOPAZ_EIGHTY, /* Font Height */
FS_NORMAL, /* Style */
FPF_ROMFONT, /* Preferences */
};
/* Next we set up the data structure which opens the
screen. Notice we include the address of our font
structure in this structure. */
struct NewScreen OurScreen =
{
0, /* the left edge has to be zero */
0, /* top edge, start at top of screen */
640, /* Width, we want High Resolution */
200, /* Height, we want non-interlace */
2, /* Depth, Two Planes, 4 colors */
0,1, /* DetailPen and BlockPen specs */
HIRES, /* Let's go for High Res */
CUSTOMSCREEN, /* screen type, not the Workbench */
&MyFont, /* use the font we said to */
(STRPTR)"Joystick Screen",/* Screen name, in title bar*/
NULL, /* screen gadget */
NULL, /* No custom Bitmap */
};
/* OK, here comes the program. */
VOID main()
{
/* The following are used to open the screen and window. */
struct Screen *Screen_ptr;
struct NewWindow OurWindow;
struct Window *Window_ptr;
/* The following variables are used in the demo loop. */
struct AJoyData *JP;
long pcolor;
struct message *msgptr = NULL;
long old_x = -1;
long old_y = -1;
long old_color = 0;
/* Declare the return type of the functions used. */
APTR OpenLibrary(),OpenScreen(),OpenWindow();
APTR AllocMem(),GetMsg();
/* Declare our function to keep Lattice (tm) happy. */
VOID DrawBox();
/* Open the Intuition library. The result returned by
this call is a pointer to the jump table of the
Intuition library. This call will load the library
from disk if it is not already loaded. If this call
returns zero, something is wrong and Intuition is
not available to us. If this is true, attempting to
use the library will cause the machine to crash, so
we should exit the program. */
IntuitionBase = (struct IntuitionBase *) OpenLibrary(
(STRPTR)"intuition.library",INTUITION_REV);
if (IntuitionBase == NULL)
exit(FALSE);
/* Same with the Graphics Library */
GfxBase = (struct GfxBase *)OpenLibrary((STRPTR)
"graphics.library",GRAPHICS_REV);
if (GfxBase == NULL)
exit(FALSE);
/* Now it is time to get our screen. The OpenScreen call
does a bunch of neat stuff for us like getting chip
memory for the screen and RastPort structures. We
could do all this stuff for ourselves, but why? */
Screen_ptr = (struct Screen *)OpenScreen(&OurScreen);
if (Screen_ptr == NULL)
exit(FALSE);
/* We are going to fill out the window structure in order
so we can open a window on our new screen. Our window
will have a few gadgets for us to play with. Since
one of the IDCMP flags is set, this program will open
a message port which we will monitor to see when the
window should be closed. */
OurWindow.LeftEdge = 20;
OurWindow.TopEdge = 20;
OurWindow.Width = 512+LEFTWIDTH+RIGHTWIDTH;
OurWindow.Height = 128+TITLEHEIGHT+BOTTOMWIDTH;
OurWindow.DetailPen = 0;
OurWindow.BlockPen = 1;
OurWindow.Title = (STRPTR)"Joystick Drawing Window";
OurWindow.Flags = WINDOWCLOSE | SMART_REFRESH
| ACTIVATE | WINDOWDRAG
| WINDOWDEPTH | NOCAREREFRESH;
OurWindow.IDCMPFlags = CLOSEWINDOW;
OurWindow.Type = CUSTOMSCREEN;
OurWindow.FirstGadget = NULL;
OurWindow.CheckMark = NULL;
OurWindow.Screen = Screen_ptr;
OurWindow.BitMap = NULL;
OurWindow.MinWidth = 512+LEFTWIDTH+RIGHTWIDTH;
OurWindow.MinHeight = 128+TITLEHEIGHT+BOTTOMWIDTH;
OurWindow.MaxWidth = 512+LEFTWIDTH+RIGHTWIDTH;
OurWindow.MaxHeight = 128+TITLEHEIGHT+BOTTOMWIDTH;
/* Now open the window on our screen. */
Window_ptr = (struct Window *)OpenWindow(&OurWindow);
if (Window_ptr == NULL)
exit(FALSE);
/* Move the graphics pen (an imaginary thing) to where
we would like our text to be drawn. */
Move(Window_ptr->RPort,20L,20L);
/* Now let's send some text out to the screen */
Text(Window_ptr->RPort,(STRPTR)"Joystick Draw",13L);
/* Let's outline the text with a box, this is our own
function */
DrawBox(Window_ptr->RPort,1,12,22,16,128);
/* */
/* Now we get to the Analog Joystick part. */
/* */
/* Define some conversion functions that change the
0-255 input values into the coordinates for drawing
into our window. */
#define fx(x) (x / 128 + LEFTWIDTH)
#define fy(y) (y / 512 + TITLEHEIGHT)
/* Allocate some public memory for a data structure that
the ReadAJoystick will return the data to us in. It
is not necessary for this to be public for this
example program since we are linking the driver with
our program, but should this become a library, this
would be required. (It doesn't hurt to think ahead
some.) */
JP = (struct AJoyData *)AllocMem((long)sizeof
(struct AJoyData),MEMF_PUBLIC);
/* Continue only if the allocate worked. */
if (JP) {
/* Call the open routine of our driver. We are
requesting Unit 1 (the right mouse port), and we
want it to give us a single pressed indication for
each time button 2 is pressed. (This means button
1 [as well as 3 and 4 if your joystick is so
equipped] will report pressed as long as the user
holds it down.) */
if (OpenAJoystick(AJOYUNIT1 | U1B2SINGLE)) {
/* Set the graphics pen to color 1 (actual color
depends upon preferences) */
pcolor = 1;
SetAPen(Window_ptr->RPort,pcolor);
/* Loop until user clicks close box on the window. */
do {
/* Read settings of the Analog joystick and buttons. */
ReadAJoystick(AJOYUNIT1,JP);
/* Check button 2. Button 2 indicates the user wants
to change the color that he is drawing with. Note
that if we had not specified U1B2SINGLE on the open
call, the color would cycle as long as the user held
the button down. This would make it difficult for
him or her to select a color. If the button is
pressed, change the color variable and write the
new color on the display. */
if (JP->button2 != BUTTONUP) {
pcolor = (pcolor+1) % 4;
SetAPen(Window_ptr->RPort,pcolor);
WritePixel(Window_ptr->RPort,old_x,old_y);
WritePixel(Window_ptr->RPort,old_x+1,old_y);
}
/* If the joystick position has moved, we need to decide
if are to clean up the screen where we were drawing.
If the button is pressed, we leave the current color
on the screen. This is done in conjunction with the
statement below. If the old color matches the current
color, we just leave it. If it does not match, we
replace it with the color that used to be there. We
then move to the new position, save the color that
was there, and write out the new color. */
if ((fx(JP->x) != old_x) ||
(fy(JP->y) != old_y)) {
if (pcolor != old_color) {
SetAPen(Window_ptr->RPort,old_color);
WritePixel(Window_ptr->RPort,old_x,
old_y);
WritePixel(Window_ptr->RPort,old_x+1,
old_y);
SetAPen(Window_ptr->RPort,pcolor);
}
old_x = fx(JP->x);
old_y = fy(JP->y);
old_color = ReadPixel(Window_ptr->RPort,
old_x,old_y);
WritePixel(Window_ptr->RPort,old_x,old_y);
WritePixel(Window_ptr->RPort,old_x+1,old_y);
}
/* If button 1 is pressed, the user wants to draw in the
window. As long as the button is held, points will
change to the current color. We do this by changing
the saved color to the current color so when the
joystick is moved the color is retained. */
if (JP->button1 != BUTTONUP) {
old_color = pcolor;
}
/* Check for any messages coming in to our program. The
GetMsg routine returns a pointer to the first message
in the queue, if any. If there are no messages, it
returns a NULL. */
} while (!(msgptr = (struct message *)
GetMsg(Window_ptr->UserPort)));
/* We looped until a message arrived at the IDCMP port.
Since we only asked for one type of message, we are
assured that it is the close window message. If we
had asked for more types, we would have to decode it
to see what type of message it is. For our case, we
just reply the message, clean up, and we're done. */
ReplyMsg(msgptr);
/* Turn off the joystick routines. */
CloseAJoystick();
}
/* Free up the memory we allocated for our data
structure. */
FreeMem(JP,(long)sizeof(struct AJoyData));
}
/* Close up the window, and then the screen. Then we
are done. */
CloseWindow(Window_ptr);
CloseScreen(Screen_ptr);
exit(TRUE);
}
/* Here we have our own function which draws a box on
the screen. It calls an Amiga function called
PolyDraw which draws polygons on the display area.
We change the color of the pen to what is desired,
draw the box and set it back. We also preserve the
graphics pen location. */
VOID DrawBox(RP,PenColor,Top,Bottom,Left,Right)
struct RastPort *RP;
int PenColor,Top,Bottom,Left,Right;
{
int OldPenColor,x,y;
short points[4][2];
/* Fill in the points of our box polygon that will
be used by the DrawPoly function. The array must
be made up of 16 bit numbers. */
points [3][0] = Left;
points [3][1] = Top;
points [0][0] = Right;
points [0][1] = Top;
points [1][0] = Right;
points [1][1] = Bottom;
points [2][0] = Left;
points [2][1] = Bottom;
/* The Amiga routines should include ones to find out
the current color and location of the graphics pen,
but it was not to be. We will just go grab the
information from the RastPort structure. */
OldPenColor = RP->FgPen;
x = RP->cp_x;
y = RP->cp_y;
/* Set the pen to what we desire, and move the pen
to the top left corner of the Box. */
SetAPen(RP,(long)PenColor);
Move(RP,(long)Left,(long)Top);
/* Draw the Box. */
PolyDraw(RP,4L,points);
/* And set everything back again. */
SetAPen(RP,(long)OldPenColor);
Move(RP,(long)x,(long)y);
}
/* End: JoyDemo.c */