controller.c 6.89 KB
/*
--------------------------------------------------------------------------------

	controller.c

	Martin Hollis 19/06/95		(c) Rare Ltd 1995

	Functions for initing and reading controllers

	Todo
		Change remapping so that different maps
		can be selected from the keypad? (by pressing all 6 keys
		at once)

--------------------------------------------------------------------------------
*/

#include <ultra64.h>				/* For CONT_* */

#define REMAP_VERSION	1		/* Affects remap solution */
					/* 0=no remap needed */
					/* 1=swap ABC and DEF */

#define MAX_MESGS	(MAXCONTROLLERS*10)
				/* NO LONGER NEEDED */
					/* Maximum number of messages */
					/* expected to accumulate between */
					/* two reads.  1 per controller per */
					/* frame, for 1/6th of a second */
					/* 6*10*4=240 bytes */








#if REMAP_VERSION == 1		/* REMAP 1 19/06/95 controllers */

#define REMAPS 6		/* 6 keys are wrong in this remap */
static int remaps[REMAPS][2]={	/* 'Change { A, to B },' */
  {	CONT_A,	CONT_B	},	/* Not done for efficiency, but for ease */
  {	CONT_B,	CONT_A	},
  {	CONT_C,	CONT_D	},
  {	CONT_D,	CONT_C	},
  {	CONT_E,	CONT_F	},
  {	CONT_F,	CONT_E	}
};

#else				/* REMAP 0 */

#define REMAPS 0		/* All OK in this remap */
static int remaps[1][2];		/* Just for compile's sake */

#endif

/*
--------------------------------------------------------------------------------
	remap
	Remaps the given controller input using the REMAP_VERSION
--------------------------------------------------------------------------------
*/

static void remap(OSContPad *pad) {
  OSContPad store;			/* u16 button; s8 stick_x,y; u8 errno; */
  int i;

  store=*pad;				/* Temporary store */
  for (i=0; i<REMAPS; i++)
    pad->button&=65535^remaps[i][0];	/* Remove bits that'll be changed */
  for (i=0; i<REMAPS; i++)		/* Remap keys: */
    if (store.button&remaps[i][0])	/* if old meaning set */
      pad->button|=remaps[i][1];		/* set new meaning */
}

/*
--------------------------------------------------------------------------------
	global variables
	For initcontrollers and readcontrollers
	pad[] lpad[] numof are externally visible for the client	  
--------------------------------------------------------------------------------
*/

int numof=0;				/* Number of controllers */
static u8 map[MAXCONTROLLERS]={0};	/* 0=absent n=use pad[n-1] */
static OSContStatus statusdata[MAXCONTROLLERS];
					/* u16|u8|u8 */
					/* type|status|errno */
OSContPad pad[MAXCONTROLLERS];		/* u16|s8|s8|u8|u8 6*6=36 bytes */
					/* u16 button; s8 stick_x,y; u8 errno; */
					/* [0]..[numof-1] are valid */
OSContPad lpad[MAXCONTROLLERS];		/* Last pad values */
static OSMesgQueue contMessageQ;
static OSMesg      contMessageBuf;

/*
--------------------------------------------------------------------------------
	initcontrollers
	Initialize all controllers
	Return the number of controllers found
--------------------------------------------------------------------------------
*/

static  u8 contpattern;		/* Could really be local to initcontrollers */
				/* Here for print */

int initcontrollers(void) {
  int i; int num=0;

  osCreateMesgQueue(&contMessageQ, &contMessageBuf, 1);
  osSetEventMesg(OS_EVENT_SI, &contMessageQ, (OSMesg)1);

  osContInit(&contMessageQ, &contpattern, &statusdata[0]);	/* Get pattern and status */
  osContStartReadData(&contMessageQ);
  for (i=0; i<MAXCONTROLLERS; i++)
    if ((contpattern & (1<<i)) &&
        !(statusdata[i].errno & CONT_NO_RESPONSE_ERROR))
      map[num++]=i+1;			/* Keep a map */

  numof=num;		/* Keep number */
  return num;		/* Number of controllers found */
}

/*
--------------------------------------------------------------------------------
	readcontrollers
	Read all controllers, updating pad[0..numof-1]
	This function does not block
--------------------------------------------------------------------------------
*/

void readcontrollers(void) {
  int i;
  static OSContPad *p = NULL;
  OSMesg dummyMessage;

  if (osRecvMesg(&contMessageQ, &dummyMessage, OS_MESG_NOBLOCK) == 0) {
    osContGetReadData(pad);		/* Now pad[0]..[MAXCONT] are valid */
#if 0
    {					/* Another type of copy */
      register u8 *a,*b,*c;
      a=(u8*)lpad; b=(u8*)pad; c=((u8*)pad)+sizeof(pad);
      do { *a=*b; a++; b++; } while (b!=c);
    }
#endif
    for (i=0; i<MAXCONTROLLERS; i++)	/* Copy old values */
      lpad[i]=pad[i];
    for (i=0; i<MAXCONTROLLERS; i++)	/* Find mapped ctrlers */
      if (map[i]) {			/* Here's one */
	pad[i]=pad[map[i]-1];		/* Pack values in lowest entries */
        remap(pad+i);			/* Remap the keys in this pad */
      }					/* Now pad[0]..[numof-1] are valid */

    osContStartReadData(&contMessageQ);	/* request latest controller information */
  }
}

/*
--------------------------------------------------------------------------------
	printcontrollers
	Prints info about each controller
	masks=
		0x0001	controller1
		0x0002	controller2
		0x0004	controller3
		0x0008	controller4
		0x0010	controller5
		0x0020	controller6
                0x0100  print general misc info
		0x0200	print status for specified controllers
		0x0400	print pad for specified controllers
--------------------------------------------------------------------------------
*/

void printcontrollers(u32 masks) {
  int i,j;

  if (masks&0x0100) {
    rmonPrintf("numof=%d    map=",numof);
    for (i=0; i<MAXCONTROLLERS; i++) rmonPrintf("%d",map[i]);
    rmonPrintf("\n\n");
  }

  for (i=0; i<MAXCONTROLLERS; i++) {
    if (masks&(1<<i)) {
      rmonPrintf("  controller[%d]\n",i);
      rmonPrintf("  --------------\n");
      rmonPrintf("\n");
      if (masks&0x0200) {
	rmonPrintf("  statusdata[%d].type   =0x%04x\n",i,statusdata[i].type);
	rmonPrintf("  statusdata[%d].status =%d\n",i,statusdata[i].status);
	rmonPrintf("  statusdata[%d].errno  =%d\n",i,statusdata[i].errno);
	rmonPrintf("\n");
      }
      if (masks&0x0400) {
	rmonPrintf("  pad[%d].button  =0x%04x\n",i,pad[i].button);
	rmonPrintf("  pad[%d].stick_x =%+d\n",i,pad[i].stick_x);
	rmonPrintf("  pad[%d].stick_y =%+d\n",i,pad[i].stick_y);
	rmonPrintf("  pad[%d].errno   =%d\n",i,pad[i].errno);
	rmonPrintf("\n");
      }
    }
  }

  if (masks&0x0100) {
    rmonPrintf("contpattern=0x%02x\n",contpattern);
    rmonPrintf("\n");
    rmonPrintf("contMessageQ.mtqueue   =0x%08x\n",contMessageQ.mtqueue);
    rmonPrintf("contMessageQ.fullqueue =0x%08x\n",contMessageQ.fullqueue);
    rmonPrintf("contMessageQ.validCount=%d\n",contMessageQ.validCount);
    rmonPrintf("contMessageQ.first     =%d\n",contMessageQ.first);
    rmonPrintf("contMessageQ.msgCount  =%d\n",contMessageQ.msgCount);
    rmonPrintf("contMessageQ.msg       =0x%08x\n",contMessageQ.msg);
    rmonPrintf("\n");
    rmonPrintf("contMessageBuf=0x%08x\n",contMessageBuf);
#if 0		/* For when contMessageBuf was an array */
    for (i=0; i<MAX_MESGS; i+=MAXCONTROLLERS) {
      rmonPrintf("  ");
      for (j=i; j<i+MAXCONTROLLERS; j++)
	if (j<MAX_MESGS) rmonPrintf("%08x, ",contMessageBuf[j]);
      rmonPrintf("\n");
    }
    rmonPrintf("};\n");
#endif
  }
}