gbpaksramreadwrite.c 7.5 KB
/*---------------------------------------------------------------------
        Copyright (C) 1998, Nintendo.
        
        File            gbpaksramreadwrite.c
        Coded    by     Koji Mitsunari. Oct  2, 1997.
        Modified by     Koji Mitsunari. Jul 28, 1998.
        Comments        64GB-PAK SRAM Read/Write for MBC1
   
        $Id: 
   ---------------------------------------------------------------------*/
/**************************************************************************
 *
 *  $Revision: 1.1.1.1 $
 *  $Date: 2002/05/02 03:27:32 $
 *  $Source: 
 *
 **************************************************************************/

#include <ultra64.h>

static	u8	srambank[MAXCONTROLLERS]; /* GB の SRAM のバンク */

/*------------------------------------------------------------------------*
 * 	64GBパック MBC1 SRAM アクセス用初期化関数 GbpakSramInit()
 *
 * [構文]
 *  #include <ultra64.h>
 *  extern s32	GbpakSramInit(OSPfs *);
 *
 *  s32 GbpakSramInit(OSPfs *pfs);
 *
 * [説明]
 *	関数 GbpakSramReadWrite()を呼ぶための、初期化関数です。
 *	MBC1 ゲームボーイ・カートリッジの SRAM のデータを読むための、レジス
 *	タのセットを行なっています。
 *	GbpakSramReadWrite()の前には、必ずこの関数を呼ぶ必要があります。
 *
 *	エラーが発生した場合、この関数が返すエラーコードには以下のものがあ
 *	ります。
 *
 *	PFS_ERR_NOPACK
 *		指定したコントローラに 64GBパックが挿し込まれていません。
 *	PFS_ERR_DEVICE
 *		64GBパックではないデバイスがコントローラに差し込まれてい
 *		ます。
 *	PFS_ERR_CONTRFAIL
 *		コントローラとのデータ転送の失敗です。
 *		コントローラが正しく接続されていないか、あるいは、64GBパッ
 *		クかコントローラコネクタに異常がある可能性があります。
 *	PFS_ERR_NO_GBCART
 *		64GBパックに GBカートリッジが差し込まれていません。
 *	PFS_ERR_NEW_GBCART
 *		GBカートリッジの抜き差しが行なわれました。
 *
 *------------------------------------------------------------------------*/
s32
GbpakSramInit(OSPfs *pfs)
{
  s32	i, ret;
  u8	status;
  u8	temp[32];
  
  /*--- GBカートリッジが抜き差しされていないか ---*/
  ret = osGbpakGetStatus(pfs, &status);
  if (ret != 0){
    return(ret);
  }

  /*--- MBC1 のレジスタ 3(0x6000)へのセット ---*/
  /*--- これにより、レジスタ 2(0x4000)が SRAM のバンク切り替えになる  ---*/
  for (i = 0 ; i < BLOCKSIZE ; temp[i++] = 1 );
  if ( (ret = osGbpakReadWrite(pfs, OS_WRITE,
			       0x6000, temp, BLOCKSIZE)) != 0 ) {
    return(ret);
  }

  /*--- MBC1 のレジスタ 0(0x0000)へのセット ---*/
  /*--- これにより、SRAM のアクセスが可能になる  ---*/
  for ( i = 0 ; i < BLOCKSIZE ; temp[i++] = 0 );
  temp[BLOCKSIZE-1] = 0x0a;
  
  if ( (ret = osGbpakReadWrite(pfs, OS_WRITE, 0x0000, temp, 32)) != 0 ) {
    return(ret);
  }

  /*--- 現在の SRAM のバンク。最初は不定なので、ダミーの値を入れておく ---*/
  srambank[pfs->channel] = 0xff;

  /*--- GBカートリッジが抜き差しされていないか ---*/
  ret = osGbpakGetStatus(pfs, &status);

  /*--- GBカートリッジへの電源が OFF になってしまっていないか ---*/
  /*--- (つまり、読み書き中にコントローラごと抜かれてないか) ---*/
  if (ret == 0){
    if (!(status & OS_GBPAK_POWER)) {
      ret = PFS_ERR_CONTRFAIL;
    }
  }

  return(ret);
} /* End of GbpakSramInit */

/*------------------------------------------------------------------------*
 * 	64GBパック MBC1 SRAM バンク切り替え関数 GbpakSramSetBank()
 *
 * [構文]
 *  #include <ultra64.h>
 *  s32 GbpakSramSetBank(OSPfs *pfs, u8 bank);
 *
 * [説明]
 *	関数 GbpakSramReadWrite()内で呼ばれる、SRAM のバンク切り替え関数で
 *	す。
 *
 *------------------------------------------------------------------------*/
static s32
GbpakSramSetBank(OSPfs *pfs, u8 bank)
{
  s32	i , ret = 0;
  u8	temp[32];

  /*--- 書くのは 32 バイト単位なので、32 バイトすべてに ---*/
  /*--- 切り替えたい sram の bank の値をセットしておく ---*/
  for (i = 0 ; i < BLOCKSIZE ; temp[i++] = bank );

  /*--- MBC1 レジスタ 2 をセットして、SRAM のバンクを切り替える ---*/
  if ( (ret = osGbpakReadWrite(pfs, OS_WRITE,
			       0x4000, temp, BLOCKSIZE)) == 0 ) {
    /*--- バンク切り替えに成功したときは、そのバンクの値をおいておく ---*/
    srambank[pfs->channel] = bank;
  }
  return(ret);
} /* End of GbpakSramSetBank */

/*------------------------------------------------------------------------*
 * 	64GBパック MBC1 SRAM アクセス関数 GbpakSramReadWrite()
 *
 * [構文]
 *  #include <ultra64.h>
 *  extern s32	GbpakSramReadWrite(OSPfs *, u16, u32, u8 *, u32);
 *
 *  s32 GbpakSramReadWrite(OSPfs *pfs, u16 flag, u16 address, u8 *buffer,
 *                            u16 size);
 *
 * [説明]
 *	関数 GbpakSramReadWrite()は、ゲームボーイ・カートリッジの SRAM の
 *	データを読み書きするための関数です。MBC1にのみ対応しています。
 *	
 *	flagには、OS_READ または、OS_WRITE を指定します。
 *	OS_READのときはゲームボーイ・カートリッジからの読み込み、OS_WRITE
 *	のときはゲームボーイ・カートリッジへの書き込みを行ないます。
 *	address には、GBカセットの RAM アドレスの値(0x0000〜0x7fff)を
 *	指定します。
 *	sizeには読み書きするバイト数を指定します。
 *	address と size は32の倍数でなければなりません。
 *	bufferは、読み書きを行なう RDRAM上のバッファです。
 *	OSPfs構造体 pfsは 関数 osGbpakInit で初期化されたハンドルです。
 *
 *	エラーが発生した場合、この関数が返すエラーコードには以下のものがあ
 *	ります。
 *
 *	PFS_ERR_NOPACK
 *		指定したコントローラに 64GBパックが挿し込まれていません。
 *	PFS_ERR_DEVICE
 *		64GBパックではないデバイスがコントローラに差し込まれてい
 *		ます。
 *	PFS_ERR_CONTRFAIL
 *		コントローラとのデータ転送の失敗です。
 *		コントローラが正しく接続されていないか、あるいは、64GBパッ
 *		クかコントローラコネクタに異常がある可能性があります。
 *	PFS_ERR_NO_GBCART
 *		64GBパックに GBカートリッジが差し込まれていません。
 *	PFS_ERR_NEW_GBCART
 *		GBカートリッジの抜き差しが行なわれました。
 *
 *------------------------------------------------------------------------*/
s32
GbpakSramReadWrite(OSPfs *pfs, u16 flag, u32 address, u8 *buffer, u32 size)
{
  s32	ret, addr_end;
  u8	status;
  u8	bank;

  /*--- GBカートリッジが抜き差しされていないか ---*/
  ret = osGbpakGetStatus(pfs, &status);
  if (ret != 0){
    return(ret);
  }

  /*--- 開始アドレスの上位 3ビットから、SRAM バンクを決定 ---*/
  bank = (u8)(address >> 13);
  if ( bank != srambank[pfs->channel] ) { /* Check SRAM active bank  */
    if ((ret = GbpakSramSetBank(pfs, bank)) != 0 ) {
      return(ret);
    }
  }

  /* 実際にアクセスするのは 0xa000〜0xbfff までの 0x2000 の領域だから */
  address &= 0x1fff;
  addr_end = address + size;

  while (1) {
    if ( addr_end > 0x2000 ) {	/* 次のバンクにまたがってしまうとき */
      addr_end -= 0x2000;	/* 次のバンクの先頭からのアドレス */

      /*--- とりあえず、現在のバンクの最後(0xbfff)まで読み書き ---*/
      ret = osGbpakReadWrite(pfs, flag, (address+0xa000),
			     buffer, 0x2000-address);
      if (ret != 0 ) break;

      /*--- 読み書きしたぶんだけ、RDRAM 側のポインタを進めておく ---*/
      buffer += (0x2000-address);

      /*--- 次のバンクに切り替え ---*/
      if ( (ret = GbpakSramSetBank(pfs, ++bank)) != 0 ) break;
      size = addr_end;
      address = 0;
    } else {	      /*--- このバンクだけで済む場合 ---*/
      ret = osGbpakReadWrite(pfs, flag, (address+0xa000), buffer, size);
      break;
    }
  }

  if (ret == 0) {
    /*--- GBカートリッジが抜き差しされていないか ---*/
    ret = osGbpakGetStatus(pfs, &status);
  }

  if (ret == 0){
    /*--- GBカートリッジへの電源が OFF になってしまっていないか ---*/
    /*--- (つまり、読み書き中にコントローラごと抜かれてないか) ---*/
    if (!(status & OS_GBPAK_POWER)) {
      ret = PFS_ERR_CONTRFAIL;
    } else if (status & OS_GBPAK_RSTB_DETECTION) {
      ret = PFS_ERR_CONTRFAIL;
    }
  }

  return(ret);
} /* End of GbpakSramReadWrite */