siproc.c 7.96 KB
/*---------------------------------------------------------------------
        Copyright (C) 1998 Nintendo.
        
        File            siproc.c
        Coded    by     Koji Mitsunari. Apr 30, 1998.
        Modified by     Koji Mitsunari. May 18, 1998.
        Comments        SI Device Procedure
   
        $Id: 
   ---------------------------------------------------------------------*/
/**************************************************************************
 *
 *  $Revision: 1.1.1.2 $
 *  $Date: 2002/10/29 08:05:51 $
 *  $Source: 
 *
 **************************************************************************/

#include <ultra64.h>
#include "nu64sys.h"
#include "siproc.h"

extern s32	GbpakSramInit(OSPfs *);
extern s32	GbpakSramReadWrite(OSPfs *, u16, u32, u8 *, u32);

RetMsg		retMsg;
static OSMesg   retMsgBuf[RET_MSG_NUM];
OSMesgQueue     retMsgQ;

OSContPad	contdata[MAXCONTROLLERS];
OSContStatus	contstat[MAXCONTROLLERS];
Conts		conts[MAXCONTROLLERS];
OSPfs		pfs;

OSGbpakId	gbid;

/*---------------------------------------------------------------------
                  Initialize Controller
  ---------------------------------------------------------------------*/
static void
ContGetStatus(void)
{
  int	i;

  for (i = 0 ; i < MAXCONTROLLERS ; i ++) {
    conts[i].stat = contstat[i].status;
    if ( contstat[i].errno == 0 &&
	((contstat[i].type & CONT_TYPE_MASK) == CONT_TYPE_NORMAL)) {
      conts[i].flag |= 1;
    } else {
      conts[i].flag = 2;
    }
  }
}
/*---------------------------------------------------------------------
                  Read Controller
  ---------------------------------------------------------------------*/
static void
ReadCont(void)
{
  s32	i;

  osContGetReadData(contdata);
  for(i = 0 ; i < MAXCONTROLLERS ; i ++){
    if (!(contdata[i].errno & CONT_NO_RESPONSE_ERROR)) {
      conts[i].flag |= 1;
      conts[i].oldcon = conts[i].nowcon;
      conts[i].nowcon = (int)contdata[i].button;
      conts[i].nowtrg = conts[i].nowcon & (~conts[i].oldcon);
      conts[i].sx = contdata[i].stick_x;
      conts[i].sy = contdata[i].stick_y;
      
      conts[i].repeat = conts[i].nowcon & conts[i].oldcon;
      if (conts[i].repeat) {
	conts[i].repcnt ++;
	if (conts[i].repcnt < 32) {
	  conts[i].repeat = 0;
	} else if (conts[i].repcnt < 80) {
	  if (conts[i].repcnt & 3) {
	    conts[i].repeat = 0;
	  }
	}
      } else {
	conts[i].repcnt = 0;
      }
      conts[i].repeat |= conts[i].nowtrg;
    } else {
      conts[i].flag = 2;
    }
  }
}

/*---------------------------------------------------------------------
                  Read Data from 64GB-PAK
  ---------------------------------------------------------------------*/
static void
GbpakRamAccess(SiMsg *msg, RetMsg *rmsg, u16 flag)
{
  static s32	step = 0;

  switch(step) {
  case 0:			/*--- 64GBパックの初期化 ---*/
    rmsg->ret = osGbpakInit(&n_siMessageQ, &pfs, CONTNO);
    switch(rmsg->ret) {
    case 0:
      step ++;
      rmsg->errmes = NULL ;
      break;
    case PFS_ERR_NOPACK:
      rmsg->errmes = GBPAK_ERR_MES_NOPACK ;
      break;
    case PFS_ERR_DEVICE:
      rmsg->errmes = GBPAK_ERR_MES_ERR_DEVICE ;
      break;
    case PFS_ERR_CONTRFAIL:
      rmsg->errmes = GBPAK_ERR_MES_FAIL ;
      break;
    }
    if (rmsg->ret != 0) {
      break;
    }
  case 1:			/*--- ROM の登録エリアの読み込み ---*/
    rmsg->ret = osGbpakReadId(&pfs, &gbid, &(rmsg->status));
    if (rmsg->ret == 0) {
      rmsg->ret = osGbpakCheckConnector(&pfs, &(rmsg->status));
    }
    switch(rmsg->ret){
    case 0:		/*--- 登録エリアの読み込みに成功 ---*/
#if	COMPANY_CODE == 0
      /*--- ゲームタイトルが登録されていない場合 ---*/
      step ++;
      rmsg->errmes = NULL ;
#else
      /*--- ゲームタイトルとメーカーコードをチェックして ---*/
      /*--- 対応のゲームが差さっているかどうかチェック ---*/
      if ( (bcmp(gbid.game_title, (u8 *)GAME_TITLE, 16) == 0 ) &&
	  (gbid.company_code == COMPANY_CODE) ) {
	step ++;
	rmsg->errmes = NULL ;
      } else {
	rmsg->errmes = GBPAK_ERR_MES_ANOTHER_GAME ;
	step = 1;
	rmsg->ret = GBPAK_ERR_ANOTHER_GAME;
      }
#endif
      break;
    case PFS_ERR_NOPACK:	/*--- 何も差さっていない ---*/
      rmsg->errmes = GBPAK_ERR_MES_NOPACK ;
      step = 0;			/* osGbpakInit()からやり直し */
      break;
    case PFS_ERR_DEVICE:	/*--- 64GBパック以外のパック ---*/
      rmsg->errmes = GBPAK_ERR_MES_ERR_DEVICE ;
      step = 0;			/* osGbpakInit()からやり直し */
      break;
    case PFS_ERR_CONTRFAIL:	/*--- 読み書き失敗 ---*/
      rmsg->errmes = GBPAK_ERR_MES_FAIL_IN_READ_ID;
      step = 0;			/* osGbpakInit()からやり直し */
      break;
    case PFS_ERR_NEW_GBCART:	/*--- GBカートリッジが差し替えられた ---*/
      rmsg->errmes = NULL;
      break;
    case PFS_ERR_NO_GBCART:	/*--- GBカートリッジが差し込まれてない ---*/
      rmsg->errmes = GBPAK_ERR_MES_NOCART ;
      break;
    }
    if (rmsg->ret != 0) {
      break;
    }
  case 2:			/* RAMからデータを読む */
    /*--- MBC1 SRAMアクセス用初期化関数 ---*/
    /* レジスタ 0(RAMアクセス可)、レジスタ 3(ROM/RAMチェンジ)のセット等 */
    rmsg->ret = GbpakSramInit(&pfs);
    if (rmsg->ret == 0) {
      /*--- 「アクセス中」というメッセージを画面に表示 ---*/
      rmsg->errmes = GBPAK_ERR_MES_NOW_LOADING ;
      osSendMesg(&retMsgQ, (OSMesg *)&retMsg, OS_MESG_BLOCK);
      /*--- MBC1 SRAMアクセス関数 (gbpaksramreadwrite.cを参照) ---*/
      rmsg->ret = GbpakSramReadWrite(&pfs, flag, msg->address, msg->buffer,
				    msg->size);
      if (rmsg->ret == 0) {
	/*--- アクセスが終了したので、電源を OFF にしておく ---*/
	rmsg->ret = osGbpakPower(&pfs, OS_GBPAK_POWER_OFF);
      }
    }
    switch(rmsg->ret){
    case 0:			/*--- 読み書き成功 ---*/
      rmsg->errmes = NULL ;
      break;
    case PFS_ERR_NOPACK:	/*--- 何も差さっていない ---*/
      rmsg->errmes = GBPAK_ERR_MES_NOPACK ;
      step = 0;			/* osGbpakInit()からやり直し */
      break;
    case PFS_ERR_DEVICE:	/*--- 64GBパック以外のパック ---*/
      rmsg->errmes = GBPAK_ERR_MES_ERR_DEVICE ;
      step = 0;			/* osGbpakInit()からやり直し */
      break;
    case PFS_ERR_CONTRFAIL:	/*--- 読み書き失敗 ---*/
      rmsg->errmes = GBPAK_ERR_MES_FAIL;
      step = 0;			/* osGbpakInit()からやり直し */
      break;
    case PFS_ERR_NEW_GBCART:	/*--- GBカートリッジが差し替えられた ---*/
      rmsg->errmes = NULL;
      step = 1;
      break;
    case PFS_ERR_NO_GBCART:	/*--- GBカートリッジが差し込まれてない ---*/
      rmsg->errmes = GBPAK_ERR_MES_NOCART ;
      step = 1;
      break;
    }
  }
}

/*---------------------------------------------------------------------
                  Serial Interface Procedure
  ---------------------------------------------------------------------*/
void
siproc(void)
{
  s32		i;
  static	queryflag = 0;
  SiMsg 	*msg = NULL;
  u8		pattern;

  osCreateMesgQueue(&retMsgQ, retMsgBuf, RET_MSG_NUM);

  osContInit(&n_siMessageQ, &pattern, contstat);
  for (i = 0 ; i < MAXCONTROLLERS ; i++ ) {
    conts[i].flag = 0;
    conts[i].nowcon = 0;
  }
  ContGetStatus();

  while (1){
    osRecvMesg(&siMsgQ, (OSMesg *)&msg, OS_MESG_BLOCK);

    switch(msg->cmd) {
    case SI_CONT_READ:		/* コントローラからのデータ読み込み */
      osContStartReadData(&n_siMessageQ);
      osRecvMesg(&n_siMessageQ, NULL, OS_MESG_BLOCK);
      ReadCont();

      /*--- 1回おき程度にコントローラの状態を調べにいく ---*/
      if (queryflag == 0 ) {
	osContStartQuery(&n_siMessageQ);
	osRecvMesg(&n_siMessageQ, NULL, OS_MESG_BLOCK);
	osContGetQuery(contstat);
	ContGetStatus();
      }
      queryflag ^= 1;

      /* 読み込みの終了を通知する */
      retMsg.proc_status = 0;
      osSendMesg(&retMsgQ, (OSMesg *)&retMsg, OS_MESG_BLOCK);
      break;

    case SI_GBPAK_READ:		/* RAM から読み込む場合 */
      retMsg.proc_status = 1;
      GbpakRamAccess(msg, &retMsg, OS_READ);
      retMsg.proc_status = 0;
      osSendMesg(&retMsgQ, (OSMesg *)&retMsg, OS_MESG_BLOCK);
      break;

    case SI_GBPAK_WRITE:	/* RAM に書き込む場合(未使用) */
      retMsg.proc_status = 1;
      GbpakRamAccess(msg, &retMsg, OS_WRITE);
      retMsg.proc_status = 0;
      osSendMesg(&retMsgQ, (OSMesg *)&retMsg, OS_MESG_BLOCK);
      break;
    }
  }
}