[comp.sys.amiga.tech] Gameport Nightmare- Help!

ofer@bach.Berkeley.EDU (Jonathan Dubman) (08/15/89)

I am in the process of developing a spiffy arcade game which I plan to place in
the public domain so you can all enjoy it.  Any help is GREATLY appreciated!

It has both keyboard and joystick control; the joystick control is giving me
a nightmare.  I am at the end of my wits and I'm ready to look up the hardware
registers as soon as I get home.  I consider myself an experienced programmer
(12 years, 3 years on the Amiga) and I have ALL the Amiga documentation.
I'm a nice guy who's just spent 10 hours rebooting.

What I want to be able to do is read the current x, y, and fire values of the
joystick at any time.  I don't really care about queues- I read it fast enough.

I've poured over each of the manuals- Mortimore, Peck, RKM- and what is still
very vague is the EXACT SEMANTICS of the whole device interaction scheme.
  Will it start sending me messages as soon as I send it the READEVENT command?
  Will it then send me only one or many?
  If many, when will it stop?
  How do I instruct it to stop?
  What if there are pending messages and I close everything down?
  Do I bomb the system or just lose memory?
  When it sends me a message, am I expected to reply or acknowledge in any way?
  Where exactly does it put the returned data?  In the buffer, right?
  When does it put something in the buffer?
  What happens when the buffer fills up?
  What is the effect of trying quick I/O?
  What is the exact difference between absolute and relative modes?
  What is the effect of setting game trigger timeout to zero?
  What is the effect of setting it to a nonzero value?

Following this plea is a minimalistic joystick program that should report
movements and button presses for a while, then quit.

The first time I run it, it works, but generates some extra codes in the
opposite directions, and the second time I run it, it does nothing at all.

HEEEELP!  Post responses if of general interest, else respond to above account.
Thanks 2^20!

Jonathan Dubman

/*-----------------CUT HERE----------------------------------------------------*/

/* Joystick Test by Jonathan Dubman 8/12/89
 * compiles under MANX with 32-bit libraries (no typecasting necessary)
 */

#include <functions.h>
#include <exec/io.h>
#include <devices/inputevent.h>
#include <devices/gameport.h>

struct MsgPort *game_port;
struct IOStdReq *game_request;
char game_buffer[sizeof(struct InputEvent)];
struct InputEvent *gb;
struct GamePortTrigger game_trigger;

main()
{
	int i;

	/* I should check return codes, etc, but I'll keep it simple so
	 * we can see what's going on.
	 */

	game_port = CreatePort(0, 0);
	game_request = CreateStdIO(game_port);
	OpenDevice("gameport.device", 1, game_request, 0);

	gb = (struct InputEvent *)game_buffer;

	game_request->io_Command = GPD_SETCTYPE;
	*game_buffer = GPCT_ABSJOYSTICK;
	game_request->io_Data = (APTR)game_buffer;
	game_request->io_Length = 1;
	DoIO(game_request);

	game_request->io_Command = GPD_SETTRIGGER;
	game_request->io_Data = (APTR)&game_trigger;
	game_request->io_Length = sizeof(game_trigger);
	game_trigger.gpt_Keys = GPTF_UPKEYS | GPTF_DOWNKEYS;
	game_trigger.gpt_Timeout = 0;				/* ??? */
	game_trigger.gpt_XDelta = 1;
	game_trigger.gpt_YDelta = 1;
	DoIO(game_request);

	game_request->io_Command = GPD_READEVENT;
	game_request->io_Data = (APTR)game_buffer;
	game_request->io_Length = sizeof(struct InputEvent);
	game_request->io_Flags = IOF_QUICK;			/* ??? */
	SendIO(game_request);

	/* busy loop, yes, but this is only a test */
	/* most of the time there will be no message ready */

	for (i = 0; i < 100000; i++) {
		while (GetMsg(game_port)) {
			switch (gb->ie_X) {
				case -1: printf("Left\n");
				case 1: printf("Right\n");
			}
			switch (gb->ie_Y) {
				case -1: printf("Up\n");
				case 1: printf("Down\n");
			}
			if (gb->ie_Code == IECODE_LBUTTON)
				printf("Fire button down\n");
			if (gb->ie_Code == IECODE_LBUTTON + IECODE_UP_PREFIX)
				printf("Fire button up\n");
			SendIO(game_request);
		}
	}

	game_request->io_Command = GPD_SETCTYPE;	/* Do I need this? */
	*game_buffer = GPCT_NOCONTROLLER;
	game_request->io_Data = (APTR)game_buffer;
	game_request->io_Length = 1;
	DoIO(game_request);

	game_request->io_Command = CMD_CLEAR;		/* Do I need this? */
	DoIO(game_request);

	DeletePort(game_port);
	CloseDevice(game_request);			/* Forgot anything? */
}