指定アドレスから呼び出す方法
非常駐プログラムを実行するアドレスをあらかじめ記述しておき、非常駐プログラムを読み込んだ後、このアドレスから実行します。
<プログラムの記述例>
fid = GFS_NameToId((Sint8 *)fname); /* fnameは非常駐プログラム */ GFS_Load(fid, 0, 0x6080000, GFS_BUFSIZ_INF); /* 開始アドレスは非常駐プログラムのマップファイルから取得する */ ((volatile void (*)())(0x6081000))();
<プログラムのリンク時の宣言>
GCC -m2 -Xlinker -Tkernal.cof -Xlinker -e -Xlinker ___Start ....
この例の場合、非常駐プログラムの実行開始関数のアドレスが変わった場合、このプログラムの再コンパイルが必要になります。
外部宣言で関数を定義しておき、リンク時に-defsymオプションで外部宣言した関数に対してアドレスを設定します。関数の実行は、 非常駐プログラムを読み込んだ後、実行します。
<プログラムの記述例>
extern void SUB_main1( void ); #define SUB_ADDR 0x06080000 void main( void ) { : /* 非常駐プログラムのロード例 */ buf[0].type = CDBUF_COPY; buf[0].trans.copy.addr = (Uint32)SUB_ADDR; : slCdLoadFile(); /* 非常駐プログラムの実行 */ SUB_main1(); : }
<プログラムのリンク時の宣言>
GCC -m2 -Xlinker -defsym -Xlinker _SUB_main1=0x06081000 ¥ -Xlinker -Tkernal.cof -Xlinker -e -Xlinker ___Start ....
非常駐部の実行開始関数のアドレスが不定になりますので、一度仮に アドレスを設定して、非常駐プログラムを作成後、その非常駐部分の マップファイルから本当の実行開始アドレスを取得して再度アドレスを 設定し直してリンクする必要が場合があります。
オブジェクトファイル内に常駐部と同じ関数名で作成しないように注意してプログラミングします。(例えば、main関数などがぶつかる可能性があります。)
非常駐部のスタートアドレスを常駐部の読み込み開始アドレスと同じアドレスに設定してください。
非常駐部を作成するときにリンカの-Rオプションを指定して常駐部の実行ファイル(例としてKernal.COF)を指定します。
GCC -m2 -Xlinker -R -Xlinker kernal.cof .....
この指定により、常駐部のシンボルを抽出して非常駐プログラムに組み込みます。
使用するライブラリを常駐部と同様にリンクしても同じ関数が存在した場合は、-Rで指定したCOFFファイルの情報を優先します。
if ( CDC_GetHirqReq() & CDC_HIRQ_DCHG ) { SYS_EXECDMP(); /* マルチプレイヤを呼び出す */ }
この処理をしても問題ないのは、
だけです。これ以外の方法でトレイオープンチェックを行なった場合、動作を保証できません。
/* tracknoで指定したCDDAトラックの先頭フレームアドレスを取得する */ Sint32 GetCDStartFrame(Uint8 trackno) { CdcPos Pos; CdcStat stat; CDC_POS_PTYPE(&pos) = CDC_PTYPE_TNO; CDC_POS_TNO(&pos) = trackno; CDC_POS_IDX(&pos) = 1; CDC_CdSeek(&pos); while(1) { CDC_GetCurstat(&stat); if ( CDC_STAT_STATUS(&stat) == CDC_ST_PAUSE ) { break; } } return CDC_STAT_FAD(&stat); }
他の方法としてはディスクのTOC(Table Of Contents)を参照し、取得出来たテーブルから参照することも出来ます。
このテーブルにはトラック1からリードアウトの開始フレームアドレスまでが各トラック毎4バイト分ずつ格納されています。
TOCを取得する関数CDC_TgetToc関数については
『PROGRAMMER'S GUIDE CD通信インタフェースユーザズマニュアル(CDパート)』
8.2 関数詳細 No 1.5
取得したTOCの情報については
『PROGRAMMER'S GUIDE CD通信インタフェースユーザズマニュアル(CDパート)』
7.2 データ詳細 7.2.3 TOC情報/セッション情報 No 3.0
に記述があります。
GFSライブラリを用いている場合は、ファイルが既にオープンされているならば
GFS_Load()を繰り返せば目的は達成されます。
通常、数回のリトライ処理を行うようにすれば良いでしょう。リトライ処理は無限ループで回し続けることは避け、エラー表示は行わずマルチプレーヤへ処理を移してください。
これは、GFSライブラリのGFS_SetGmode関数で常駐モードを指定して、 1度CD-ROMからファイルを読み込んで常駐させておき、通常CD-ROMからと同 じようにGFS関数のGFS_Seek関数やGFS_Fread関数などを使用すると、再度 CD-ROMからアクセスせずにCDバッファから読み込むことができます。
GFSライブラリは、上記のGFS_SetGmode関数で指定するモードのデフォルト
値は破棄(GFS_GMODE_ERASE)になっており、常駐(GFS_GMODE_RESIDENT)にす
ることで、例えば常駐モードでCD-ROMからデータを読み込んだ後、CDDA再生
を実行させます。
その実行中にGFS関数を使用してCDバッファからデータを読
み込むことでデータバッファのような形で使用が可能です。
注意点として、200セクタを越えて移動(シーク)または読み込み(リード)させ
ると、CD-ROMにアクセスしてしまいますので、最大200セクタの範囲内で行っ
てください。
また、このような使用方法をしない場合は、必ずGFS_SetGmode関
数で破棄のモードに戻すようにしてください。
<例>CD
バッファにデータを常駐させて、CDDA再生中に読み込むサンプルプログラム
(但し、今回のプログラムは流れを説明するものなので、エラーチェックは行っていません。組み込み時には必ず加えてください。)
/* 常駐モードの設定*/ GFS_SetGmode(gfs, GFS_GMODE_RESIDENT); /* ファイルのCDバッファへの読み込み */ fid = GFS_NameToId( "sample.dat"); if ( fid >= 0 ) { GFS_Open( fid); GFS_NwCdRead( gfs, 200 ); } /* CDDA の再生 */ CDC_PLY_STYPE(&ply) = CDC_PTYPE_TNO; CDC_PLY_STNO(&ply) = 2; CDC_PLY_SIDX(&ply) = 0; CDC_PLY_ETYPE(&ply) = CDC_PTYPE_TNO; CDC_PLY_ETNO(&ply) = 3; CDC_PLY_EIDX(&ply) = 0; CDC_PLY_PMODE(&ply) = CDC_PM_DFL; ret = CDC_CdPlay(&ply); /* CDDA 再生中にCDバッファから読み込み */ GFS_Seek( gfs, GFS_SEEK_SET ); GFS_Fread( gfs, 10, buf, 10*2048 );
CDC I/Fライブラリを使用する。
CD-ROMアクセスが途中で入るため、CD-DA再生範囲とリピート回数を再度設定し直す。
元の位置にシークしてから再生再開するため、「ピックアップ位置を変更しない」設定にする。
また、プレイ、シーク等のドライブコマンドを実行する直前には、トレイの開閉 (DCHGフラグ)や<FATAL>状態をチェックすべきです。
<例>
CDDA再生とポーズ位置の取得方法を示した簡単なサンプルプログラム。
/* 初期化 */ Sint32 ret; Sint32 fad; CdcStat stat; CdcPly ply; CdcPos pos; // トラック番号5〜17を無限回演奏する CDC_PLY_STYPE(&ply)=CDC_PTYPE_TNO; CDC_PLY_STNO (&ply)=5; CDC_PLY_SIDX (&ply)=0; CDC_PLY_ETYPE(&ply)=CDC_PTYPE_TNO; CDC_PLY_ETNO (&ply)=17; CDC_PLY_EIDX (&ply)=0; CDC_PLY_PMODE(&ply)=0x0F; // 再生開始 CDC_CdPlay(&ply); while (1) { /* メインループ */ : : /* GFS ないし SGL による CD アクセスの発生 */ if (access==TRUE){ CDC_POS_TYPE(&pos)=CDC_PTYPE_NOCHG; /* CD-CA PAUSE */ CDC_CdSeek(&pos); /* PAUSE 実行 */ /* ポーズ位置のFADを取得する(数フレームの誤差あり) */ ret = CDC_GetCurStat(&stat); if (ret != CDC_ERR_OK) { return NG; } fad = CDC_STAT_FAD(&stat); : /* GFS ないし SGL による CD アクセス実行 */ : /* CD-DA 再生再開処理 */ CDC_POS_TYPE(&pos)=CDC_PTYPE_FAD; /* 再開位置指定 */ -> CDC_POS_FAD (&pos)=fad; /* FAD で指定 */ CDC_CdSeek(&pos); /* シーク実行 */ /* CD再生パラメータの設定 */ /* ・5〜17トラック */ /* ・無限回リピート */ /* ・ピックアップ位置を変更せず */ CDC_PLY_STYPE(&ply)=CDC_PTYPE_TNO; CDC_PLY_STNO (&ply)=5; CDC_PLY_SIDX (&ply)=0; CDC_PLY_ETYPE(&ply)=CDC_PTYPE_TNO; CDC_PLY_ETNO (&ply)=17; CDC_PLY_EIDX (&ply)=0; CDC_PLY_PMODE(&ply)=(CDC_PM_PIC_NOCHG | 0x0F); CDC_CdPlay(&ply); /* 再開実行 */ } : : : slSynch(); /* 等々 */ }