/* * Absolute_Joystick.c * * Gameport device absolute joystick example * * Compile with SAS 5.10 lc -b1 -cfistq -v -y -L * * Run from CLI only */ #include <exec/types.h> #include <exec/io.h> #include <exec/memory.h> #include <intuition/intuition.h> #include <exec/exec.h> #include <dos/dos.h> #include <devices/gameport.h> #include <devices/inputevent.h> #include <clib/exec_protos.h> #include <clib/alib_protos.h> #include <clib/dos_protos.h> #include <clib/intuition_protos.h> #include <stdio.h> #ifdef LATTICE int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ int chkabort(void) { return(0); } /* really */ #endif #define JOY_X_DELTA (1) #define JOY_Y_DELTA (1) #define TIMEOUT_SECONDS (10) extern struct ExecBase *SysBase; /*----------------------------------------------------------------------- ** Routine to print out some information for the user. */ VOID printInstructions(VOID) { printf("\n >>> gameport.device Absolute Joystick Demo <<<\n\n"); if (SysBase->VBlankFrequency==60) printf(" Running on NTSC system (60 Hz).\n"); else if (SysBase->VBlankFrequency==50) printf(" Running on PAL system (50 Hz).\n"); printf(" Attach joystick to rear connector (A3000) and (A1000).\n" " Attach joystick to right connector (A2000).\n" " Attach joystick to left connector (A500).\n" " Then move joystick and click its button(s).\n\n" " To exit program press and release fire button 3 times in a row.\n" " The program also exits if no activity occurs for 1 minute.\n\n"); } /*----------------------------------------------------------------------- ** print out information on the event received. */ BOOL check_move(struct InputEvent *game_event) { WORD xmove, ymove; BOOL timeout=FALSE; xmove = game_event->ie_X; ymove = game_event->ie_Y; if (xmove == 1) { if (ymove == 1) printf("RIGHT DOWN\n"); else if (ymove == 0) printf("RIGHT\n"); else if (ymove ==-1) printf("RIGHT UP\n"); else printf("UNKNOWN Y\n"); } else if (xmove ==-1) { if (ymove == 1) printf("LEFT DOWN\n"); else if (ymove == 0) printf("LEFT\n"); else if (ymove ==-1) printf("LEFT UP\n"); else printf("UNKNOWN Y\n"); } else if (xmove == 0) { if (ymove == 1) printf("DOWN\n"); /* note that 0,0 can be a timeout, or a direction release. */ else if (ymove == 0) { if (game_event->ie_TimeStamp.tv_secs >= (UWORD)(SysBase->VBlankFrequency)*TIMEOUT_SECONDS) { printf("TIMEOUT\n"); timeout=TRUE; } else printf("RELEASE\n"); } else if (ymove ==-1) printf("UP\n"); else printf("UNKNOWN Y\n"); } else { printf("UNKNOWN X "); if (ymove == 1) printf("unknown action\n"); else if (ymove == 0) printf("unknown action\n"); else if (ymove ==-1) printf("unknown action\n"); else printf("UNKNOWN Y\n"); } return(timeout); } /*----------------------------------------------------------------------- ** send a request to the gameport to read an event. */ VOID send_read_request( struct InputEvent *game_event, struct IOStdReq *game_io_msg) { game_io_msg->io_Command = GPD_READEVENT; game_io_msg->io_Flags = 0; game_io_msg->io_Data = (APTR)game_event; game_io_msg->io_Length = sizeof(struct InputEvent); SendIO(game_io_msg); /* Asynchronous - message will return later */ } /*----------------------------------------------------------------------- ** simple loop to process gameport events. */ VOID processEvents( struct IOStdReq *game_io_msg, struct MsgPort *game_msg_port) { BOOL timeout; SHORT timeouts; SHORT button_count; BOOL not_finished; struct InputEvent game_event; /* where input event will be stored */ /* From now on, just read input events into the event buffer, ** one at a time. READEVENT waits for the preset conditions. */ timeouts = 0; button_count = 0; not_finished = TRUE; while ((timeouts < 6) && (not_finished)) { /* Send the read request */ send_read_request(&game_event,game_io_msg); /* Wait for joystick action */ Wait(1L << game_msg_port->mp_SigBit); while (NULL != GetMsg(game_msg_port)) { timeout=FALSE; switch(game_event.ie_Code) { case IECODE_LBUTTON: printf(" FIRE BUTTON PRESSED \n"); break; case (IECODE_LBUTTON | IECODE_UP_PREFIX): printf(" FIRE BUTTON RELEASED \n"); if (3 == ++button_count) not_finished = FALSE; break; case IECODE_RBUTTON: printf(" ALT BUTTON PRESSED \n"); button_count = 0; break; case (IECODE_RBUTTON | IECODE_UP_PREFIX): printf(" ALT BUTTON RELEASED \n"); button_count = 0; break; case IECODE_NOBUTTON: /* Check for change in position */ timeout = check_move(&game_event); button_count = 0; break; default: break; } if (timeout) timeouts++; else timeouts=0; } } } /*----------------------------------------------------------------------- ** allocate the controller if it is available. ** you allocate the controller by setting its type to something ** other than GPCT_NOCONTROLLER. Before you allocate the thing ** you need to check if anyone else is using it (it is free if ** it is set to GPCT_NOCONTROLLER). */ BOOL set_controller_type(BYTE type, struct IOStdReq *game_io_msg) { BOOL success = FALSE; BYTE controller_type = 0; /* begin critical section ** we need to be sure that between the time we check that the controller ** is available and the time we allocate it, no one else steals it. */ Forbid(); game_io_msg->io_Command = GPD_ASKCTYPE; /* inquire current status */ game_io_msg->io_Flags = IOF_QUICK; game_io_msg->io_Data = (APTR)&controller_type; /* put answer in here */ game_io_msg->io_Length = 1; DoIO(game_io_msg); /* No one is using this device unit, let's claim it */ if (controller_type == GPCT_NOCONTROLLER) { game_io_msg->io_Command = GPD_SETCTYPE; game_io_msg->io_Flags = IOF_QUICK; game_io_msg->io_Data = (APTR)&type; game_io_msg->io_Length = 1; DoIO( game_io_msg); success = TRUE; } Permit(); /* critical section end */ return(success); } /*----------------------------------------------------------------------- ** tell the gameport when to trigger. */ VOID set_trigger_conditions(struct GamePortTrigger *gpt, struct IOStdReq *game_io_msg) { /* trigger on all joystick key transitions */ gpt->gpt_Keys = GPTF_UPKEYS | GPTF_DOWNKEYS; gpt->gpt_XDelta = JOY_X_DELTA; gpt->gpt_YDelta = JOY_Y_DELTA; /* timeout trigger every TIMEOUT_SECONDS second(s) */ gpt->gpt_Timeout = (UWORD)(SysBase->VBlankFrequency) * TIMEOUT_SECONDS; game_io_msg->io_Command = GPD_SETTRIGGER; game_io_msg->io_Flags = IOF_QUICK; game_io_msg->io_Data = (APTR)gpt; game_io_msg->io_Length = (LONG)sizeof(struct GamePortTrigger); DoIO(game_io_msg); } /*----------------------------------------------------------------------- ** clear the buffer. do this before you begin to be sure you ** start in a known state. */ VOID flush_buffer(struct IOStdReq *game_io_msg) { game_io_msg->io_Command = CMD_CLEAR; game_io_msg->io_Flags = IOF_QUICK; game_io_msg->io_Data = NULL; game_io_msg->io_Length = 0; DoIO(game_io_msg); } /*----------------------------------------------------------------------- ** free the unit by setting its type back to GPCT_NOCONTROLLER. */ VOID free_gp_unit(struct IOStdReq *game_io_msg) { BYTE type = GPCT_NOCONTROLLER; game_io_msg->io_Command = GPD_SETCTYPE; game_io_msg->io_Flags = IOF_QUICK; game_io_msg->io_Data = (APTR)&type; game_io_msg->io_Length = 1; DoIO(game_io_msg); } /*----------------------------------------------------------------------- ** allocate everything and go. On failure, free any resources that ** have been allocated. this program fails quietly-no error messages. */ VOID main(int argc,char **argv) { struct GamePortTrigger joytrigger; struct IOStdReq *game_io_msg; struct MsgPort *game_msg_port; /* Create port for gameport device communications */ if (game_msg_port = CreatePort("RKM_game_port",0)) { /* Create message block for device IO */ if (game_io_msg = (struct IOStdReq *) CreateExtIO(game_msg_port,sizeof(*game_io_msg))) { game_io_msg->io_Message.mn_Node.ln_Type = NT_UNKNOWN; /* Open the right/back (unit 1, number 2) gameport.device unit */ if (!OpenDevice("gameport.device",1,game_io_msg,0)) { /* Set controller type to joystick */ if (set_controller_type(GPCT_ABSJOYSTICK,game_io_msg)) { /* Specify the trigger conditions */ set_trigger_conditions(&joytrigger,game_io_msg); printInstructions(); /* Clear device buffer to start from a known state. ** There might still be events left */ flush_buffer(game_io_msg); processEvents(game_io_msg,game_msg_port); /* Free gameport unit so other applications can use it ! */ free_gp_unit(game_io_msg); } CloseDevice(game_io_msg); } DeleteExtIO(game_io_msg); } DeletePort(game_msg_port); } }