home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pleasure 76
/
OTACD76.bin
/
archive
/
game
/
PsrSDK16a
/
PsrSDK16a.lzh
/
Sample
/
PsrStr
/
Plugin.c
< prev
Wrap
C/C++ Source or Header
|
2000-12-02
|
15KB
|
455 lines
/******************************************************************************/
/* */
/* [PSストリームアクセスプラグイン] */
/* */
/* FILE NAME : Plugin.c */
/* FUNCTION : 標準STRアクセス (ファイル用) */
/* */
/* FUNCTIONS | an outline */
/* --------------------------+-------------------------------------------- */
/* PsrQueryPlugin() | プラグイン情報の取得 */
/* PsrIsSupportFile() | ストリームファイルのサポート判定 */
/* PsrGetStrFileInfo() | ストリームファイル情報の取得 */
/* PsrOpenFile() | ストリームファイルのオープン */
/* PsrClose() | ストリームデータのクローズ */
/* PsrRead() | ストリームデータの読み取り */
/* PsrSeek() | 読み取り位置の設定 */
/* */
/* HISTORY | Comment | Name */
/* ------------------+---------------------------------------+------------ */
/* 2000.01.21 | 新規作成 | ふぃろ */
/* 2000.05.09 | CDサポートのため全面修正 | ふぃろ */
/* 2000.07.06 | BSヘッダチェック (FF7対応) 1.01 | ふぃろ */
/* 2000.07.11 | PSRPLUGIN構造体の変更 1.10 | ふぃろ */
/* 2000.07.12 | サンプリングレートの判定 1.10 | ふぃろ */
/* 2000.07.15 | フレームレート誤認識 1.11 | ふぃろ */
/* 2000.07.16 | オーディオ判定 1.11 | ふぃろ */
/* 2000.07.19 | フレームレート判定を7.5おきに 1.12 | ふぃろ */
/* 2000.10.28 | プラグイン仕様変更 1.20 | ふぃろ */
/* 2000.12.03 | IKI形式のサポート 1.21 | ふぃろ */
/* */
/* (C) Copyright ふぃろ 2000. All rights reserved. */
/******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <Windows.h>
#include "PSRP.h"
#define _MaxSEARCH 24 // 1.01
typedef struct { // STRファイルのヘッダー構造 ---------------------------
CHAR achRiff[4]; // 'RIFF'
BYTE abDummy[0x28];
} _TSTRHEADER;
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;
typedef struct { // ストリームハンドルの内容 ----------------------------
HANDLE hFile; // ファイルハンドル
DWORD nAllSector; // セクタ数
DWORD nNumSector; // 残りセクタ数
DWORD nNumFrame; // フレーム数
DWORD nFrameRate; // フレームレート * 10
DWORD dwAudio; // オーディオ退避長
BYTE abAudio[0x900*2]; // オーディオ退避バッファ
} _THANDLE, *_PTHANDLE;
/******************************************************************************/
/* */
/* PsrQueryPlugin() : プラグイン情報の取得 */
/* */
/******************************************************************************/
CEXPORT VOID PsrQueryPlugin(
LPPSRPLUGIN lpPlugin) // プラグイン情報取得バッファアドレス
{
strcpy(lpPlugin->aName, "STR file");
strcpy(lpPlugin->aCopyright, "Copyright (c) Fyiro 2000.");
lpPlugin->usVersion = 121; // 1.10
lpPlugin->usIsSupportVersion = 0; // 1.10
lpPlugin->usSystemVersion = PSR_SYSTEMVERSION; // 1.10
strcpy(lpPlugin->aSiteName, "Fyiro's Garage"); // 1.20
strcpy(lpPlugin->aSiteUrl, "http://homepage2.nifty.com/~mkb/"); // 1.20
}
/******************************************************************************/
/* */
/* PsrIsSupportFile() : ストリームファイルのサポート判定 */
/* */
/******************************************************************************/
CEXPORT BOOL PsrIsSupportFile(
LPCTSTR lpFileName) // ファイル名
{
HANDLE hFile;
DWORD dwRead;
_TSTRHEADER strHeader;
_TSECTOR sector;
INT iPos; // 1.01
if(GetFileAttributes(lpFileName) & FILE_ATTRIBUTE_DIRECTORY) {
return FALSE;
}
// 指定されたファイルをオープンする --------------------
hFile = CreateFile(lpFileName, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if(hFile == INVALID_HANDLE_VALUE) return FALSE;
// 'RIFF'ヘッダーのチェック ----------------------------
ReadFile(hFile, &strHeader, sizeof(strHeader), &dwRead, 0);
if(memcmp(strHeader.achRiff, "RIFF", 4) != 0) {
CloseHandle(hFile);
return FALSE;
}
// 動画のチェック --------------------------------------
// ステータスコードが正しい ?
// データタイプがシステム定義フォーマット ?
// イメージのサイズが大きすぎない ?
// 先頭セクターが動画データ ?
if(!ReadFile(hFile, §or, sizeof(sector), &dwRead, 0)) {
CloseHandle(hFile);
return FALSE;
}
CloseHandle(hFile);
if(dwRead != sizeof(sector)) return FALSE;
if(sector.abSubHeader[2] == 0x64) return FALSE;
if(!sector.usStatus) return FALSE;
if(sector.usStatus & 0x00f0 != 0x0060) return FALSE;
if(!(sector.usDataType & 0x8000)) return FALSE;
if(sector.usNumSector > 24) return FALSE;
for(iPos=0; iPos<_MaxSEARCH; iPos++) { // 1.01
if(sector.ausMovie[iPos+1] == 0x3800) break; // 1.01
} // 1.01
if(sector.ausMovie[iPos+1] != 0x3800) return FALSE; // 1.01
if(sector.ausMovie[iPos+3] > 3) { // 1.21 ------->
if(sector.ausMovie[iPos+2] != sector.usWidth) return FALSE;
if(sector.ausMovie[iPos+3] != sector.usHeight) return FALSE;
} // <------- 1.21
return TRUE;
}
/******************************************************************************/
/* */
/* PsrGetStrFileInfo() : ストリームファイル情報の取得 */
/* */
/******************************************************************************/
CEXPORT BOOL PsrGetStrFileInfo(
LPCTSTR lpFileName, // ファイル名
LPPSRSTREAMINFO lpStreamInfo) // ストリームデータ情報
{
HANDLE hFile;
DWORD dwRead, dwSize, dwNumSector;
DWORD dwNumAudio, dwNumMovie, dwSecCount, dwLength;
DWORD dwNumMBlock, dwResolution, nAudioPct; // 1.10
DWORD nNumFrame, nTimeAudio; // 1.11
WORD wResolution, wLength, wRate; // 1.12
BYTE bAudioSubH; // 1.10
SIZE szFrame;
_TSECTOR sector;
// 指定されたファイルをオープンする --------------------
hFile = CreateFile(lpFileName, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if(hFile == INVALID_HANDLE_VALUE) return FALSE;
SetFilePointer(hFile, sizeof(_TSTRHEADER), NULL, FILE_BEGIN);
// セクター数を求める ----------------------------------
dwSize = GetFileSize(hFile, NULL) - sizeof(_TSTRHEADER);
dwNumSector = dwSize / sizeof(_TSECTOR);
// 先頭nフレーム分のセクターを読み取って必要な情報を収集
dwNumAudio = dwNumMovie = nAudioPct = nNumFrame = 0; // 1.11
while(1) {
if(!ReadFile(hFile, §or, sizeof(sector), &dwRead, 0)) break;
if(dwRead != sizeof(sector)) break;
if(sector.abSubHeader[2] == 0x64) {
dwNumAudio ++;
bAudioSubH = sector.abSubHeader[3]; // 1.10
if(!nAudioPct) { // 1.10
nAudioPct = dwNumAudio + dwNumMovie; // 1.10
} // 1.10
continue;
}
if(sector.usStatus && sector.ulFrameNo > 30) break;
dwNumMovie ++;
if(!sector.usStatus) continue;
if(sector.usSectorNo == 0 && sector.ulFrameNo) {
szFrame.cx = sector.usWidth;
szFrame.cy = sector.usHeight;
nNumFrame = sector.ulFrameNo; // 1.11
}
}
CloseHandle(hFile);
// 有効なセクターがない(エラー) ------------------------
if(!dwNumMovie) return FALSE;
// ストリームデータ情報を設定 --------------------------
dwNumMBlock = ((szFrame.cx + 15) / 16) * ((szFrame.cy + 15) / 16);
dwResolution= 90000 / dwNumMBlock;
if(dwResolution < 150) wResolution = 75;
else if(dwResolution < 300) wResolution = 150;
else if(dwResolution < 600) wResolution = 300;
else wResolution = 600;
dwLength = dwNumMovie * sizeof(sector.ausMovie) / nNumFrame; // 1.11
if(dwLength > 20 * 1024) wLength = 75;
else if(dwLength > 10 * 1024) wLength = 150;
else if(dwLength > 5 * 1024) wLength = 300;
else wLength = 600;
dwSecCount = dwNumAudio + dwNumMovie;
lpStreamInfo->wTypeFlags = PSR_STRTYPE_MOVIE;
lpStreamInfo->wReserved = 0;
lpStreamInfo->nBeginSector = 0;
lpStreamInfo->nNumSector = 0;
lpStreamInfo->nNumFrame = (dwNumSector * nNumFrame) / dwSecCount;
lpStreamInfo->szFrame = szFrame;
lpStreamInfo->wFrameRate = min(wResolution, wLength);
if(dwNumAudio) {
lpStreamInfo->wTypeFlags |= PSR_STRTYPE_AUDIO;
lpStreamInfo->wFormatTag = WAVE_FORMAT_PCM;
lpStreamInfo->wBitsPerSample = 16;
lpStreamInfo->wChannels = // 1.11
(bAudioSubH & 0x01) ? 2 : 1; // 1.11
lpStreamInfo->nSamplesPerSec = // 1.11
(bAudioSubH & 0x04) ? 18900:37800; // 1.11
}
else {
lpStreamInfo->wFormatTag = 0;
lpStreamInfo->wChannels = 0;
lpStreamInfo->nSamplesPerSec = 0;
lpStreamInfo->wBitsPerSample = 0;
}
if(dwNumAudio) {// フレームレート補正 ---------------------------- 1.12
nTimeAudio = (dwNumAudio * 40320) /
(lpStreamInfo->wChannels *
(lpStreamInfo->nSamplesPerSec / 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;
}
/******************************************************************************/
/* */
/* PsrOpenFile() : ストリームファイルのオープン */
/* */
/******************************************************************************/
CEXPORT HANDLE PsrOpenFile(
LPCTSTR lpFileName, // ファイル名
LPPSRSTREAMINFO lpStreamInfo) // ストリームデータ情報
{
_PTHANDLE phandle;
// ハンドルを作成 --------------------------------------
if(!(phandle = malloc(sizeof(_THANDLE)))) return NULL;
phandle->hFile = NULL;
phandle->nAllSector = 0;
phandle->nNumSector = 0;
phandle->nNumFrame = lpStreamInfo->nNumFrame;
phandle->nFrameRate = lpStreamInfo->wFrameRate;
phandle->dwAudio = 0;
// ファイルをオープンする ------------------------------
phandle->hFile = CreateFile(lpFileName, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if(phandle->hFile == INVALID_HANDLE_VALUE) {
free(phandle);
return NULL;
}
SetFilePointer(phandle->hFile, sizeof(_TSTRHEADER), NULL, FILE_BEGIN);
phandle->nAllSector = GetFileSize(phandle->hFile, NULL);
phandle->nAllSector -= sizeof(_TSTRHEADER);
phandle->nAllSector /= sizeof(_TSECTOR);
phandle->nNumSector = phandle->nAllSector;
return phandle;
}
/******************************************************************************/
/* */
/* PsrClose() : ストリームデータのクローズ */
/* */
/******************************************************************************/
CEXPORT BOOL PsrClose(
HANDLE hStream) // ストリームハンドル
{
_PTHANDLE phandle;
phandle = hStream;
CloseHandle(phandle->hFile);
free(phandle);
return TRUE;
}
/******************************************************************************/
/* */
/* PsrRead() : ストリームデータの読み取り */
/* */
/******************************************************************************/
CEXPORT BOOL PsrRead(
HANDLE hStream, // ストリームハンドル
LPPSRREADBUFF lpBuffer) // 読み取りバッファ
{
_PTHANDLE phandle;
_TSECTOR sector;
DWORD dwRead;
INT iSize, iLength, iPos; // 1.01
PBYTE pbBuffer;
phandle = hStream;
memset(lpBuffer, 0, sizeof(PSRREADBUFF) - PSR_FRAMEBUFFER);
// 退避オーディオバッファの内容を設定 ------------------
if(phandle->dwAudio) {
lpBuffer->nLength = phandle->dwAudio;
memcpy(lpBuffer->abData, phandle->abAudio, phandle->dwAudio);
phandle->dwAudio = 0;
return TRUE;
}
iLength = 0; // ファイルから読み込んで設定 --------------------------
while(phandle->nNumSector) {
if(!ReadFile(phandle->hFile, §or, sizeof(sector), &dwRead, 0)) break;
if(dwRead != sizeof(sector)) break;
phandle->nNumSector --;
// オーディオデータ - - - - - - - - - - - - - -
if(sector.abSubHeader[2] == 0x64) {
if(!lpBuffer->nFrameNo) {
lpBuffer->nLength = 0x900;
memcpy(lpBuffer->abData,
§or.usStatus, lpBuffer->nLength);
return TRUE;
} else {
if(phandle->dwAudio >= 0x900 * 2) continue;
memcpy(&phandle->abAudio[phandle->dwAudio],
§or.usStatus, 0x900);
phandle->dwAudio += 0x900;
continue;
}
}
// 動画データ - - - - - - - - - - - - - - - - -
if(!sector.usStatus) continue;
if(!sector.ulFrameNo) continue;
iPos = 0; // 先頭セクター - - - - - - - - - - - - - - - -
if(!sector.usSectorNo) {
lpBuffer->nFrameNo = sector.ulFrameNo;
lpBuffer->szFrame.cx = sector.usWidth;
lpBuffer->szFrame.cy = sector.usHeight;
iLength = (INT)sector.ulLength;
pbBuffer= lpBuffer->abData;
for(iPos=0; iPos<_MaxSEARCH; iPos++) { // 1.01 ------->
if(sector.ausMovie[iPos+1] == 0x3800) break;
} // <------- 1.01
}
if(iLength) { // イメージデータのコピー - - - - - - - - - - -
iSize = sizeof(sector.ausMovie) - // 1.01
(sizeof(USHORT) * iPos); // 1.01
iSize = min(iSize, iLength); // 1.01
memcpy(pbBuffer, §or.ausMovie[iPos], iSize);// 1.01
pbBuffer += iSize;
iLength -= iSize;
lpBuffer->nLength += iSize;
}
// 最終セクター - - - - - - - - - - - - - - - -
if(sector.usSectorNo == sector.usNumSector - 1) {
return TRUE;
}
}
return FALSE;
}
/******************************************************************************/
/* */
/* PsrSeek() : 読み取り位置の設定 */
/* */
/******************************************************************************/
CEXPORT BOOL PsrSeek(
HANDLE hStream, // ストリームハンドル
DWORD dwPosition) // 読み取り位置 1/1000秒単位
{
_PTHANDLE phandle;
LONG lFrame, lSector, lPos;
phandle = hStream;
lFrame = (dwPosition * phandle->nFrameRate) / 10000;
lSector = (lFrame * phandle->nAllSector) / phandle->nNumFrame;
lPos = lSector * sizeof(_TSECTOR) + sizeof(_TSTRHEADER);
if(SetFilePointer(phandle->hFile, lPos, NULL, FILE_BEGIN) == 0xffffffff) {
return FALSE;
}
phandle->dwAudio = 0;
phandle->nNumSector = phandle->nAllSector - lSector;
return TRUE;
}