home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pleasure 76
/
OTACD76.bin
/
archive
/
game
/
PsrSDK16a
/
PsrSDK16a.lzh
/
Sample
/
PsrStrCd
/
Plugin.c
< prev
Wrap
C/C++ Source or Header
|
2000-12-02
|
26KB
|
805 lines
/******************************************************************************/
/* */
/* [PSストリームアクセスプラグイン] */
/* */
/* FILE NAME : Plugin.c */
/* FUNCTION : 標準STRアクセス (CD-ROM用) */
/* */
/* FUNCTIONS | an outline */
/* --------------------------+-------------------------------------------- */
/* PsrQueryPlugin() | プラグイン情報の取得 */
/* PsrIsSupportCDBegin() | CDサポート判定 開始処理 */
/* PsrIsSupportCDEnd() | CDサポート判定 終了処理 */
/* PsrIsSupportCDSector() | CDサポート判定 セクタ通知 */
/* PsrIsSupportCDResult() | CDサポート判定 結果取得 */
/* PsrGetStrDataInfo() | ストリームデータ情報の取得 */
/* PsrOpenCD() | CDストリームのオープン */
/* PsrClose() | ストリームデータのクローズ */
/* PsrRead() | ストリームデータの読み取り */
/* PsrSeek() | 読み取り位置の設定 */
/* */
/* HISTORY | Comment | Name */
/* ------------------+---------------------------------------+------------ */
/* 2000.06.16 | 新規作成 | ふぃろ */
/* 2000.06.27 | CD-DAトラックを含むCDにも対応 1.01 | ふぃろ */
/* 2000.06.27 | CD-DAトラックはスキップ 1.01 | ふぃろ */
/* 2000.06.27 | ダミーセクタの認識処理追加 1.01 | ふぃろ */
/* 2000.06.30 | 単位セクタ数の不良の対策 1.01 | ふぃろ */
/* 2000.07.03 | ダミーセクタ認識処理の強化 1.02 | ふぃろ */
/* 2000.07.06 | BSヘッダチェック (FF7対応) 1.03 | ふぃろ */
/* 2000.07.11 | PSRPLUGIN構造体の変更 1.10 | ふぃろ */
/* 2000.07.12 | CD解析中断用処理の追加 1.10 | ふぃろ */
/* 2000.07.12 | サンプリングレートの判定 1.10 | ふぃろ */
/* 2000.07.15 | フレームレート誤認識 1.11 | ふぃろ */
/* 2000.07.16 | オーディオ判定 1.11 | ふぃろ */
/* 2000.07.19 | フレームレート判定(0.5step) 1.12 | ふぃろ */
/* 2000.07.20 | STR終端判定強化 1.13 | ふぃろ */
/* 2000.07.23 | 0割り(暫定対策) 1.14 | ふぃろ */
/* 2000.08.03 | 可変フレームレート対策 1.20 | ふぃろ */
/* 2000.08.08 | 誤認識対策 1.21 | ふぃろ */
/* 2000.08.10 | 誤認識対策 (その2) 1.22 | ふぃろ */
/* 2000.08.26 | CD読み取り速度設定 1.23 | ふぃろ */
/* 2000.10.28 | プラグイン仕様変更 1.30 | ふぃろ */
/* 2000.11.25 | 複数同時格納形を除外する処理 1.31 | ふぃろ */
/* 2000.12.03 | IKI形式のサポート 1.31 | ふぃろ */
/* */
/* (C) Copyright ふぃろ 2000. All rights reserved. */
/******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <Windows.h>
#include "CdAccess.h"
#include "PSRP.h"
#define _NumAUDIOBUFF 8
#define _MaxSEARCH 24
//#define _SpinSPEED -1
#define _SpinSPEED 8
typedef struct { // セクター構造 ----------------------------------------
BYTE abSync[12]; // CD-ROM XA 同期
BYTE abHeader[4]; // CD-ROM XA ヘッダー
BYTE abSubHeader[8]; // CD-ROM XA サブ・ヘッダー
// [01014280]x2 or [01016400]x2
USHORT usStatus; // 0110 xxxx xxxx VVVV ex:6001
// x : Reserved for system
// V : Version
USHORT usDataType; // S--- ---- ---- ---- ex:8001
// S : 1=system-defained format
// 0=user-defained format
USHORT usSectorNo; // セクター番号 0~
USHORT usNumSector; // セクター数 / フレーム
ULONG ulFrameNo; // フレーム番号 1~
ULONG ulLength; // フレーム当りのデータ長
USHORT usWidth; // イメージ幅
USHORT usHeight; // イメージ高さ
ULONG ulMovieHeadM; // Reserved for system
ULONG ulMovieHeadV; // Reserved for system
ULONG ulReserved; // 0000 fixed
USHORT ausMovie[0x3F0];
BYTE abEdc[4]; // CD-ROM XA EDC
BYTE abEcc[276]; // CD-ROM XA ECC
} _TSECTOR, *_PTSECTOR;
typedef struct { // ストリーム情報 --------------------------------------
DWORD dwBeginNo; // データ開始セクタ番号
DWORD dwLastMovieNo; // 最後の動画セクタ番号
DWORD dwFastAudioNo; // 最初の音声セクタ番号
DWORD dwLastAudioNo; // 最後の音声セクタ番号
BYTE abAudioSH[4]; // 音声セクタのサブヘッダ
DWORD nStepAudio; // 音声セクタの間隔
DWORD nNumAudio; // 音声セクタ数
DWORD nNumFrame; // フレーム数
SIZE szFrame; // フレームサイズ
DWORD nSyncAudio; // 動画連動音声セクタ数
DWORD nSyncFrame; // 音声連動フレーム数
DWORD dwSize; // データサイズ 1.30
USHORT usDataType; // 動画のデータタイプ 1.31
WORD wMinFrame; // 最小フレームセクタ数
WORD wMaxFrame; // 最大フレームセクタ数
} _TSTREAM, *_PTSTREAM;
typedef struct { // ストリーム探索ハンドルの内容 ------------------------
BOOL fFindout; // 発見フラグ
DWORD dwPreBeginNo; // 直前のフレームの開始セクタ番号
DWORD nNumAudio; // dwPreBeginNoからのオーディオセクタ数
INT iBuffer; // ストリームバッファ数
INT iNum; // ストリーム数
_PTSTREAM pstr; // ストリーム情報群
} _TFIND, *_PTFIND;
typedef struct { // ストリームハンドルの内容 ----------------------------
HANDLE hCdrom; // CD-ROMハンドル
PSRSTREAMINFO str; // ストリームデータ情報
DWORD nStepAudio; // オーディオセクタ間隔
_PTSECTOR apaudio[_NumAUDIOBUFF]; // 退避オーディオセクタ
} _THANDLE, *_PTHANDLE;
enum { _TypeUNKNOW, _TypeDUMMY, _TypeAUDIO, _TypeMOVIE };
//****--------------------------------------------------------------------------
//**** _psrGetFrameRate() : フレームレートの取得
//****--------------------------------------------------------------------------
static WORD _strGetFrameRate(SIZE szFrame, DWORD nMinSect, DWORD nMaxSect) {
DWORD nMBlock, nReso, nLength;
WORD wReso, wLength;
nMBlock = ((szFrame.cx + 15) / 16) * ((szFrame.cy + 15) / 16);
nReso = 90000 / nMBlock;
if(nReso < 150) wReso = 75;
else if(nReso < 300) wReso = 150;
else if(nReso < 600) wReso = 300;
else wReso = 600;
nLength = (nMinSect + nMaxSect) * (0x7e0 / 2);
if(nLength > 20 * 1024) wLength = 75;
else if(nLength > 10 * 1024) wLength = 150;
else if(nLength > 5 * 1024) wLength = 300;
else wLength = 600;
return min(wReso, wLength);
}
/******************************************************************************/
/* */
/* PsrQueryPlugin() : プラグイン情報の取得 */
/* */
/******************************************************************************/
CEXPORT VOID PsrQueryPlugin(
LPPSRPLUGIN lpPlugin) // プラグイン情報取得バッファアドレス
{
strcpy(lpPlugin->aName, "STR CD-ROM");
strcpy(lpPlugin->aCopyright, "Copyright (c) Fyiro 2000.");
lpPlugin->usVersion = 131;
lpPlugin->usIsSupportVersion = 102;
lpPlugin->usSystemVersion = PSR_SYSTEMVERSION;
strcpy(lpPlugin->aSiteName, "Fyiro's Garage"); // 1.30
strcpy(lpPlugin->aSiteUrl, "http://homepage2.nifty.com/~mkb/"); // 1.30
}
/******************************************************************************/
/* */
/* PsrIsSupportCDBegin() : CDサポート判定 開始処理 */
/* */
/******************************************************************************/
CEXPORT HANDLE PsrIsSupportCDBegin(
INT iNumToc, // TOCの数
LPTOCENTRY lptoc) // TOC
{
_PTFIND pfind;
INT i;
// DAトラックのみのCDは処理対象外! ---------------------
for(i=0; i<iNumToc; i++) {
if(lptoc[i].bAdr & 0x04) break;
}
if(i == iNumToc) return NULL;
if(!(pfind = malloc(sizeof(_TFIND)))) return NULL;
// ハンドルの作成と初期設定 ----------------------------
pfind->fFindout = FALSE;
pfind->iBuffer = 10;
pfind->iNum = 0;
pfind->pstr = malloc(sizeof(_TSTREAM) * pfind->iBuffer);
if(!pfind->pstr) {
free(pfind);
return NULL;
}
return pfind;
}
/******************************************************************************/
/* */
/* PsrIsSupportCDEnd() : CDサポート判定 終了処理 */
/* */
/******************************************************************************/
CEXPORT VOID PsrIsSupportCDEnd(
HANDLE hIsCD) // CDサポート判定ハンドル
{
_PTFIND pfind;
if(!(pfind = hIsCD)) return;
free(pfind->pstr);
free(pfind);
}
/******************************************************************************/
/* */
/* PsrIsSupportCDSector() : CDサポート判定 セクタ通知 */
/* */
/******************************************************************************/
CEXPORT BOOL PsrIsSupportCDSector(
HANDLE hIsCD, // CDサポート判定ハンドル
TOCENTRY toc, // TOC
DWORD nSector, // セクタ番号
PVOID pvSector) // セクタ
{
_PTFIND pfind;
_PTSECTOR psector;
_PTSTREAM pstr;
BOOL fBegin;
INT iType, i;
WORD wNum;
DWORD dwLastSector;
if(!(pfind = hIsCD)) return FALSE;
if(!(toc.bAdr & 0x04)) return FALSE; // CD-DA
if(!(psector = pvSector)) {
if(pfind->fFindout) {
pfind->fFindout = FALSE;
pstr = &pfind->pstr[pfind->iNum - 1];
if((pstr->nNumFrame == 1) ||
(pstr->dwFastAudioNo && !pstr->nStepAudio)) {
pfind->iNum --;
}
}
return FALSE;
}
// ストリームのセクタか ? ------------------------------
iType = _TypeUNKNOW;
if((psector->abSubHeader[2] & 0x64) == 0x64) {
iType = _TypeAUDIO;
} else {
if((psector->usStatus & 0x00f0) == 0x0060 &&
(psector->usDataType & 0x8000) &&
psector->ulFrameNo &&
psector->usNumSector <= 20 &&
psector->usNumSector && !psector->ulReserved) {
iType = _TypeMOVIE;
}
}
fBegin = FALSE; // 先頭セクタか ? --------------------------------------
if(iType == _TypeMOVIE) {
if(!psector->usSectorNo && psector->ulFrameNo == 1) {
for(i=0; i<_MaxSEARCH; i++) {
if(psector->ausMovie[i+1] == 0x3800) break;
}
if(psector->ausMovie[i+1] == 0x3800 && // MAGIC
(psector->ausMovie[i+3] <= 3 || // FLC or VLC
(psector->ausMovie[i+2] == psector->usWidth &&
psector->ausMovie[i+3] == psector->usHeight)))
fBegin = TRUE;
else iType = _TypeUNKNOW;
}
}
if(!pfind->fFindout && !fBegin) iType = _TypeUNKNOW;
if(iType == _TypeAUDIO && pfind->fFindout) {
pstr = &pfind->pstr[pfind->iNum - 1];
if(pstr->nNumAudio &&
memcmp(pstr->abAudioSH, psector->abSubHeader, 4) != 0) {
iType = _TypeUNKNOW;
}
}
if(iType == _TypeUNKNOW) {
if(!psector->usStatus) iType = _TypeDUMMY;
}
if(iType == _TypeDUMMY) return TRUE;
// ストリームが発見されている場合 **********************************************
if(pfind->fFindout) {
pstr = &pfind->pstr[pfind->iNum - 1];
dwLastSector = max(pstr->dwLastMovieNo, pstr->dwLastAudioNo);
// データの終わり --------------------------------------
// 1. ストリームの開始セクタの場合 ----------------
// 2. すっごく離れた位置のセクタの場合 ------------
// 3. ストリームでないセクタの場合 ----------------
if(fBegin || nSector - dwLastSector > 32 || iType == _TypeUNKNOW) {
pfind->fFindout = FALSE;
if((pstr->nNumFrame == 1) ||
(pstr->dwFastAudioNo && !pstr->nStepAudio)) {
pfind->iNum --;
}
}
// 動画セクタ ------------------------------------------
else if(iType == _TypeMOVIE) {
if(pstr->usDataType != psector->usDataType) { // 1.31
pfind->fFindout = FALSE; // 1.31
pfind->iNum --; // 1.31
return TRUE; // 1.31
} // 1.31
pstr->dwLastMovieNo = nSector;
if(psector->usSectorNo == 0) {
pstr->nNumFrame = psector->ulFrameNo;
pstr->szFrame.cx = max(pstr->szFrame.cx,
psector->usWidth);
pstr->szFrame.cy = max(pstr->szFrame.cy,
psector->usHeight);
wNum = (WORD)(nSector - pfind->dwPreBeginNo);
wNum -= (WORD)pfind->nNumAudio;
pstr->wMinFrame = min(pstr->wMinFrame, wNum);
pstr->wMaxFrame = max(pstr->wMaxFrame, wNum);
pstr->dwSize += psector->ulLength; // 1.30
pfind->dwPreBeginNo = nSector;
pfind->nNumAudio = 0;
}
if(pstr->nNumAudio &&
nSector - pstr->dwLastAudioNo < pstr->nStepAudio) {
pstr->nSyncAudio = pstr->nNumAudio;
pstr->nSyncFrame = pstr->nNumFrame;
}
}
else { // 音声セクタ ------------------------------------------
if(!pstr->nNumAudio) {
pstr->dwFastAudioNo = nSector;
pstr->nStepAudio = nSector - pstr->dwBeginNo;
memcpy(pstr->abAudioSH, psector->abSubHeader, 4);
}
else if(pstr->nNumAudio == 1) {
pstr->nStepAudio = nSector - pstr->dwFastAudioNo;
}
pstr->dwLastAudioNo = nSector;
pstr->dwSize += 0x900; // 1.30
pstr->nNumAudio ++;
pfind->nNumAudio ++;
}
// データの終わり --------------------------------------
if(psector->abSubHeader[2] == 0x89) {
pstr = &pfind->pstr[pfind->iNum - 1];
pfind->fFindout = FALSE;
if((pstr->nNumFrame == 1) ||
(pstr->dwFastAudioNo && !pstr->nStepAudio)) {
pfind->iNum --;
}
}
}
// ストリームが発見されていない場合 ********************************************
// ストリームが見つかった! -----------------------------
if(!pfind->fFindout && fBegin) {
if(pfind->iBuffer == pfind->iNum) {
pfind->iBuffer += 10;
pstr = realloc(pfind->pstr,
sizeof(_TSTREAM) * pfind->iBuffer);
if(!pstr) {
pfind->iBuffer -= 10;
return TRUE; // とりあえず正常終了
}
pfind->pstr = pstr;
}
pstr = &pfind->pstr[pfind->iNum];
pstr->dwBeginNo = nSector;
pstr->dwLastMovieNo = nSector;
pstr->dwFastAudioNo = 0;
pstr->dwLastAudioNo = 0;
pstr->nStepAudio = 0;
pstr->nNumAudio = 0;
pstr->nNumFrame = 1;
pstr->szFrame.cx = psector->usWidth;
pstr->szFrame.cy = psector->usHeight;
pstr->nSyncAudio = 0;
pstr->nSyncFrame = 0;
pstr->dwSize = psector->ulLength; // 1.30
pstr->usDataType = psector->usDataType; // 1.31
pstr->wMinFrame = 0xffff;
pstr->wMaxFrame = 0;
pfind->fFindout = TRUE;
pfind->dwPreBeginNo = nSector;
pfind->nNumAudio = 0;
pfind->iNum ++;
}
return TRUE;
}
/******************************************************************************/
/* */
/* PsrIsSupportCDResult() : CDサポート判定 結果取得 */
/* */
/******************************************************************************/
CEXPORT INT PsrIsSupportCDResult(
HANDLE hIsCD, // CDサポート判定ハンドル
INT iIndex, // ストリームインデックス
LPPSRSTREAMINFO lpStreamInfo) // ストリームデータ情報
{
_PTFIND pfind;
_PTSTREAM pstr;
DWORD dwLast, nChannels, nSampleRate, nSample;
DWORD dwTime, dwAudio, dwMovie;
WORD wFps;
if(!(pfind = hIsCD)) return 0;
if(pfind->iNum <= iIndex) return -1;
if(!lpStreamInfo) return pfind->iNum;
pstr = &pfind->pstr[iIndex];
// ストリームデータ情報を暫定的に設定 ------------------
dwLast = max(pstr->dwLastMovieNo, pstr->dwLastAudioNo);
wFps = _strGetFrameRate(pstr->szFrame,
pstr->wMinFrame, pstr->wMaxFrame);
lpStreamInfo->wTypeFlags = PSR_STRTYPE_MOVIE;
lpStreamInfo->wReserved = 0;
lpStreamInfo->nBeginSector = pstr->dwBeginNo;
lpStreamInfo->nNumSector = (dwLast - pstr->dwBeginNo) + 1;
lpStreamInfo->nNumFrame = pstr->nNumFrame;
lpStreamInfo->szFrame = pstr->szFrame;
lpStreamInfo->wFrameRate = wFps;
lpStreamInfo->wFormatTag = 0;
lpStreamInfo->wChannels = 0;
lpStreamInfo->wBitsPerSample = 0;
lpStreamInfo->nSamplesPerSec = 0;
lpStreamInfo->nPlayTime = (pstr->nNumFrame * 10000) /
lpStreamInfo->wFrameRate;
lpStreamInfo->nDataSize = pstr->dwSize; // 1.30
// オーディオ情報を設定 --------------------------------
if(pstr->nNumAudio) {
nChannels = (pstr->abAudioSH[3] & 0x01) ? 2 : 1;
nSampleRate = (pstr->abAudioSH[3] & 0x04) ? 18900 : 37800;
lpStreamInfo->wTypeFlags |= PSR_STRTYPE_AUDIO;
lpStreamInfo->wFormatTag = WAVE_FORMAT_PCM;
lpStreamInfo->wBitsPerSample = 16;
lpStreamInfo->wChannels = (WORD)nChannels;
lpStreamInfo->nSamplesPerSec = nSampleRate;
// オーディオデータを元にフレームレートを計算 ----------
nSample = nChannels * (nSampleRate / 100);
dwTime = (pstr->nSyncAudio * 40320) / nSample;
if(dwTime) wFps = (WORD)((pstr->nSyncFrame * 10000) / dwTime);
// 可変フレームレートの場合… --------------------------
if(abs((INT)lpStreamInfo->wFrameRate - (INT)wFps) > 20){
if(pstr->wMaxFrame - pstr->wMinFrame > 3) {
lpStreamInfo->wTypeFlags |= PSR_STRTYPE_VFRATE;
lpStreamInfo->wFrameRate = _strGetFrameRate(
pstr->szFrame,
pstr->wMinFrame,
pstr->wMinFrame);
}
// 固定フレームレートの場合 ----------------------------
else {
lpStreamInfo->wFrameRate = ((wFps + 2) / 5) * 5;
}
}
lpStreamInfo->wFrameRate = max(lpStreamInfo->wFrameRate, 50);
// 再生時間の再計算 ------------------------------------
dwAudio = (pstr->nNumAudio * 40320) / nSample;
dwMovie = (pstr->nNumFrame * 10000) / lpStreamInfo->wFrameRate;
lpStreamInfo->nPlayTime = max(dwAudio, dwMovie);
}
return pfind->iNum;
}
/******************************************************************************/
/* */
/* PsrGetStrDataInfo() : ストリームデータ情報の取得 */
/* */
/******************************************************************************/
CEXPORT BOOL PsrGetStrDataInfo(
INT iDriveNo, // ドライブ番号
DWORD dwBegin, // 開始セクタ番号
DWORD dwNumSector, // セクタ数
LPPSRSTREAMINFO lpStreamInfo) // ストリームデータ情報
{
HANDLE hCdrom;
_PTSECTOR psector;
SIZE szFrame;
DWORD nNumAudio, nNumMovie, nNumFrame, nTimeAudio;
DWORD nSecCount, nMin, nMax, nChannels, nSampleRate;
WORD wRate;
BYTE bAudioSubH;
// 先頭nフレーム分のセクタを読み取って必要な情報を収集 -
hCdrom = CdReadOpen(iDriveNo, NULL, dwBegin, min(dwNumSector, 300), -1);
if(!hCdrom) return FALSE;
nNumAudio = nNumMovie = nNumFrame = 0;
while(psector = CdReadSector(hCdrom, NULL)) {
if(psector->abSubHeader[2] == 0x64) {
nNumAudio ++;
bAudioSubH = psector->abSubHeader[3];
}
else if(psector->usStatus && psector->ulFrameNo > 30) {
CdUnlockReadBuffer(hCdrom, psector);
break;
}
else {
nNumMovie ++;
if(psector->usStatus && psector->usSectorNo == 0) {
szFrame.cx = psector->usWidth;
szFrame.cy = psector->usHeight;
nNumFrame = psector->ulFrameNo;
}
}
CdUnlockReadBuffer(hCdrom, psector);
}
CdReadClose(hCdrom);
if(!nNumMovie) return FALSE;
// ストリームデータ情報を作成する ----------------------
nSecCount = nNumAudio + nNumMovie;
nMin = nNumMovie / nNumFrame;
nMax = (nNumMovie + nNumFrame - 1) / nNumFrame;
lpStreamInfo->wTypeFlags = PSR_STRTYPE_MOVIE;
lpStreamInfo->wReserved = 0;
lpStreamInfo->nBeginSector = dwBegin;
lpStreamInfo->nNumSector = dwNumSector;
lpStreamInfo->nNumFrame = (dwNumSector * nNumFrame) / nSecCount;
lpStreamInfo->szFrame = szFrame;
lpStreamInfo->wFrameRate = _strGetFrameRate(szFrame, nMin, nMax);
lpStreamInfo->wFormatTag = 0;
lpStreamInfo->wChannels = 0;
lpStreamInfo->wBitsPerSample = 0;
lpStreamInfo->nSamplesPerSec = 0;
if(nNumAudio) {
nChannels = (bAudioSubH & 0x01) ? 2 : 1;
nSampleRate = (bAudioSubH & 0x04) ? 18900 : 37800;
lpStreamInfo->wTypeFlags |= PSR_STRTYPE_AUDIO;
lpStreamInfo->wFormatTag = WAVE_FORMAT_PCM;
lpStreamInfo->wBitsPerSample = 16;
lpStreamInfo->wChannels = (WORD)nChannels;
lpStreamInfo->nSamplesPerSec = nSampleRate;
// フレームレート補正 ----------------------------------
nTimeAudio = (nNumAudio * 40320) /
(nChannels * (nSampleRate / 100));
wRate = (WORD)((nNumFrame * 10000) / nTimeAudio);
if(abs((INT)lpStreamInfo->wFrameRate - (INT)wRate) > 20){
lpStreamInfo->wFrameRate = ((wRate + 2) / 5) * 5;
}
}
lpStreamInfo->nPlayTime = (lpStreamInfo->nNumFrame * 10000) /
lpStreamInfo->wFrameRate;
return TRUE;
}
/******************************************************************************/
/* */
/* PsrOpenCD() : CDストリームのオープン */
/* */
/******************************************************************************/
CEXPORT HANDLE PsrOpenCD(
INT iDriveNo, // ドライブ番号
LPPSRSTREAMINFO lpStreamInfo) // ストリームデータ情報
{
_PTHANDLE phandle;
_PTSECTOR psector;
HANDLE hCdrom;
DWORD i, dwSec1, dwSec2;
// CD-ROMのオープン ------------------------------------
hCdrom = CdReadOpen(iDriveNo, NULL,
lpStreamInfo->nBeginSector,
lpStreamInfo->nNumSector, _SpinSPEED);
if(!hCdrom) return NULL;
// ハンドルを作成 --------------------------------------
if(!(phandle = malloc(sizeof(_THANDLE)))) {
CdReadClose(hCdrom);
return NULL;
}
phandle->hCdrom = hCdrom;
phandle->str = *lpStreamInfo;
for(i=0; i<_NumAUDIOBUFF; i++) phandle->apaudio[i] = NULL;
// オーディオセクタ間隔を求める ------------------------
dwSec1 = dwSec2 = 0;
if(lpStreamInfo->wTypeFlags & PSR_STRTYPE_AUDIO) {
for(i=1; !dwSec1 || !dwSec2; i++) {
if(!(psector = CdReadSector(hCdrom, NULL))) break;
if((psector->abSubHeader[2] & 0x64) == 0x64) {
if(!dwSec1) dwSec1 = i;
else dwSec2 = i;
}
CdUnlockReadBuffer(hCdrom, psector);
}
CdSetReadPointer(hCdrom, 0, FILE_BEGIN);
}
if(dwSec2) phandle->nStepAudio = dwSec2 - dwSec1;
else phandle->nStepAudio = dwSec1;
return phandle;
}
/******************************************************************************/
/* */
/* PsrClose() : ストリームデータのクローズ */
/* */
/******************************************************************************/
CEXPORT BOOL PsrClose(
HANDLE hStream) // ストリームハンドル
{
_PTHANDLE phandle;
phandle = hStream;
if(phandle->hCdrom) CdReadClose(phandle->hCdrom);
free(phandle);
return TRUE;
}
/******************************************************************************/
/* */
/* PsrRead() : ストリームデータの読み取り */
/* */
/******************************************************************************/
CEXPORT BOOL PsrRead(
HANDLE hStream, // ストリームハンドル
LPPSRREADBUFF lpBuffer) // 読み取りバッファ
{
_PTHANDLE phandle;
_PTSECTOR psector;
PBYTE pbBuff;
INT iLength, iSize, i, iPos;
BOOL fComp;
phandle = hStream;
memset(lpBuffer, 0, sizeof(PSRREADBUFF) - PSR_FRAMEBUFFER);
// 退避オーディオバッファの内容を設定 ------------------
pbBuff = lpBuffer->abData;
for(i=0; i<_NumAUDIOBUFF; i++) {
if(!phandle->apaudio[i]) break;
memcpy(pbBuff, &phandle->apaudio[i]->usStatus, 0x900);
CdUnlockReadBuffer(phandle->hCdrom, phandle->apaudio[i]);
phandle->apaudio[i] = NULL;
lpBuffer->nLength += 0x900;
pbBuff += 0x900;
}
if(lpBuffer->nLength) return TRUE;
iLength = 0; // CDから読み込んで設定 --------------------------------
fComp = FALSE;
while(!fComp) {
if(!(psector = CdReadSector(phandle->hCdrom, NULL))) break;
// 音声データ - - - - - - - - - - - - - - - - -
if((psector->abSubHeader[2] & 0x64) == 0x64) {
if(!lpBuffer->nFrameNo) {
lpBuffer->nLength = 0x900;
memcpy(lpBuffer->abData, &psector->usStatus, 0x900);
fComp = TRUE;
}
else {
for(i=0; i<_NumAUDIOBUFF; i++) {
if(!phandle->apaudio[i]) {
phandle->apaudio[i] = psector;
break;
}
}
if(i != _NumAUDIOBUFF) continue;
}
}
// 映像データ - - - - - - - - - - - - - - - - -
else if(psector->usStatus && psector->ulFrameNo) {
iPos = 0; // 先頭セクタ - - - - - - - - - - - - -
if(!psector->usSectorNo) {
lpBuffer->nFrameNo = psector->ulFrameNo;
lpBuffer->szFrame.cx = psector->usWidth;
lpBuffer->szFrame.cy = psector->usHeight;
iLength = (INT)psector->ulLength;
pbBuff = lpBuffer->abData;
for(iPos=0; iPos<_MaxSEARCH; iPos++) {
if(psector->ausMovie[iPos+1] == 0x3800) break;
}
}
if(iLength) { // イメージデータのコピー - - - - - - -
iSize = sizeof(psector->ausMovie) -
(sizeof(USHORT) * iPos);
iSize = min(iSize, iLength);
memcpy(pbBuff, &psector->ausMovie[iPos], iSize);
pbBuff += iSize;
iLength -= iSize;
lpBuffer->nLength += iSize;
}
// 最終セクタ - - - - - - - - - - - - -
if(psector->usSectorNo == psector->usNumSector - 1) {
if(lpBuffer->nFrameNo) {
fComp = TRUE;
if(phandle->str.wTypeFlags & PSR_STRTYPE_VFRATE) {
lpBuffer->wFrameRate =
_strGetFrameRate(
lpBuffer->szFrame,
psector->usNumSector-1,
psector->usNumSector);
}
}
}
}
CdUnlockReadBuffer(phandle->hCdrom, psector);
}
return fComp;
}
/******************************************************************************/
/* */
/* PsrSeek() : 読み取り位置の設定 */
/* */
/******************************************************************************/
CEXPORT BOOL PsrSeek(
HANDLE hStream, // ストリームハンドル
DWORD dwPosition) // 読み取り位置 1/1000秒単位
{
_PTHANDLE phandle;
DWORD nFrame, nSector;
INT i;
double dPos;
phandle = hStream;
for(i=0; i<_NumAUDIOBUFF; i++) {
if(phandle->apaudio[i]) {
CdUnlockReadBuffer(phandle->hCdrom, phandle->apaudio[i]);
phandle->apaudio[i] = NULL;
}
}
// 映像データからセクタ位置を算出 ----------------------
if(!(phandle->str.wTypeFlags & PSR_STRTYPE_AUDIO)) {
nFrame = (dwPosition * phandle->str.wFrameRate) / 10000;
nSector = (nFrame * phandle->str.nNumSector) / phandle->str.nNumFrame;
}
else { // 音声データからセクタ位置を算出 ----------------------
dPos = (double)(phandle->str.nSamplesPerSec / 100);
dPos *= (double)(dwPosition * phandle->nStepAudio);
dPos /= (double)(40320 / (DWORD)phandle->str.wChannels);
nSector = (DWORD)dPos;
}
nSector = min(nSector, phandle->str.nNumSector);
if(CdSetReadPointer(phandle->hCdrom, (LONG)nSector, FILE_BEGIN) == 0xffffffff) {
return FALSE;
}
return TRUE;
}