gbpakcheckconnector.c 3.96 KB
/*---------------------------------------------------------------------
        Copyright (C) 1998, Nintendo.
        
        File            gbpakcheckconnector.c
        Coded    by     Koji Mitsunari. May 18, 1998.
        Modified by	Koji Mitsunari. Sep 21, 1998.
        Comments        Check connector between GB cartridge and 64GB PAK
   
        $Id: 
   ---------------------------------------------------------------------*/

/**************************************************************************
 *
 *  $Revision: 1.1.1.1 $
 *  $Date: 2002/05/02 03:28:44 $
 *  $Source: 
 *
 **************************************************************************/

#include "osint.h"
#include "controller.h"

#define	BUF_CNT		4
#define	MIN_ADDR	0x80
#define	MAX_ADDR	0x4000
#define	RAM_ADDR	0xa000
#define	ROM_ADDR	0x2000

s32
osGbpakCheckConnector(OSPfs *pfs, u8 *status)
{
  s32	ret;
  s32	bufn = 1, oldbufn = 0;
  u16	address = 0, oldaddr = 0;
  u16	daddr = 0;
  u16	num;
  u8	buf[3][BUF_CNT][BLOCKSIZE];
  u8	buf_status[3][BUF_CNT];

  ret = osGbpakGetStatus(pfs, status);
  if (ret == PFS_ERR_NEW_GBCART) {	/*--- 挿し直しされてたら ---*/
    ret = osGbpakGetStatus(pfs, status);
  }
  if (ret == PFS_ERR_NEW_GBCART) {
    return(PFS_ERR_CONTRFAIL);
  } else if (ret == 0) {
    if (!(*status & OS_GBPAK_POWER)) { /*--- 電源が入っていなかったら ---*/
      if ((ret = osGbpakPower(pfs, OS_GBPAK_POWER_ON))!= 0) {
	return(ret);
      }
    }

    bzero(buf_status, sizeof(buf_status));

    /* Read Gameboy cartridge ROM area */
    for ( address = MIN_ADDR ; address <= MAX_ADDR ; address <<= 1) {
      /*--- 隣り合うアドレス同士のチェック ---*/
      num = 0;
      daddr = 0;
      do {
	ret = osGbpakReadWrite(pfs, OS_READ, address+daddr, 
			       buf[bufn][num], BLOCKSIZE);
	if (ret != 0 ) return(ret);
	buf_status[bufn][num] = 1;

	if (buf_status[oldbufn][num] == 0) {
	  ret = osGbpakReadWrite(pfs, OS_READ, oldaddr+daddr,
				 buf[oldbufn][num], BLOCKSIZE);
	  if (ret != 0 ) {
	    return(ret);
	  } else {
	    buf_status[oldbufn][num] = 1;
	  }
	}
	if (bcmp(buf[bufn][num], buf[oldbufn][num], BLOCKSIZE) != 0 ) {
	  num = 0;
	  break;		/* OK! because data are different */
	}
	daddr += BLOCKSIZE;
      } while (num++ < BUF_CNT-1);
      
      if (num != 0) {
	return(PFS_ERR_CONTRFAIL);
      }
      /*--- 0番地と各アドレスのチェック ---*/
      if (oldbufn != 0) {
	num = 0 ;
	daddr = 0;
	do {
	  if (buf_status[bufn][num] == 0) {
	    ret = osGbpakReadWrite(pfs, OS_READ, address+daddr, 
				   buf[bufn][num], BLOCKSIZE);
	    if (ret != 0 ) return(ret);
	    buf_status[bufn][num] = 1;
	  }

	  if (buf_status[0][num] == 0) {
	    ret = osGbpakReadWrite(pfs, OS_READ, daddr,
				   buf[0][num], BLOCKSIZE);
	    if (ret != 0 ) {
	      return(ret);
	    } else {
	      buf_status[0][num] = 1;
	    }
	  }
	  if (bcmp(buf[bufn][num], buf[0][num], BLOCKSIZE) != 0 ) {
	    num = 0;
	    break;		/* OK! because data are different */
	  }
	  daddr += BLOCKSIZE;
	} while (num++ < BUF_CNT-1);
      }
      if (num != 0) {
	return(PFS_ERR_CONTRFAIL);
      }
      if (oldbufn != 0) {
	bzero(buf_status[oldbufn], BUF_CNT);
      }
      oldaddr = address;
      oldbufn = bufn;
      bufn ^= 3;
    }

    /*--- RAM エリアのチェック --*/
    if ((pfs->dir_size > 1) || (pfs->version == 2)) {
      num = 0 ;
      daddr = 0;
      do {
	ret = osGbpakReadWrite(pfs, OS_READ, RAM_ADDR+daddr, 
			       buf[bufn][num], BLOCKSIZE);
	if (ret != 0 ) return(ret);

	ret = osGbpakReadWrite(pfs, OS_READ, ROM_ADDR+daddr,
			       buf[oldbufn][num], BLOCKSIZE);
	if (ret != 0 ) {
	  return(ret);
	}
	if (bcmp(buf[bufn][num], buf[oldbufn][num], BLOCKSIZE) != 0 ) {
	  num = 0;
	  break;		/* OK! because data are different */
	}
	daddr += BLOCKSIZE;
      } while (num++ < BUF_CNT-1);
      if ( num != 0 ) {
	return(PFS_ERR_CONTRFAIL);
      }
    }

    /* Confirm if data have been read correctly */
    ret = osGbpakGetStatus(pfs, status);
    if (ret == PFS_ERR_NEW_GBCART) {
      ret = PFS_ERR_CONTRFAIL;
    }
  }
  return(ret);
}