home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pleasure 76
/
OTACD76.bin
/
archive
/
game
/
PsrSDK16a
/
PsrSDK16a.lzh
/
Sample
/
PsrFF8
/
Plugin.c
< prev
Wrap
C/C++ Source or Header
|
2000-10-29
|
18KB
|
605 lines
/******************************************************************************/
/* */
/* [PSストリームアクセスプラグイン] */
/* */
/* FILE NAME : Plugin.c */
/* FUNCTION : FF8ムービー処理 */
/* */
/* FUNCTIONS | an outline */
/* --------------------------+-------------------------------------------- */
/* PsrQueryPlugin() | プラグイン情報の取得 */
/* PsrIsSupportCDBegin() | CDサポート判定 開始処理 */
/* PsrIsSupportCDEnd() | CDサポート判定 終了処理 */
/* PsrIsSupportCDSector() | CDサポート判定 セクタ通知 */
/* PsrIsSupportCDResult() | CDサポート判定 結果取得 */
/* PsrGetStrDataInfo() | ストリームデータ情報の取得 */
/* PsrOpenCD() | CDストリームのオープン */
/* PsrClose() | ストリームデータのクローズ */
/* PsrRead() | ストリームデータの読み取り */
/* PsrSeek() | 読み取り位置の設定 */
/* PsrDecodeAudio() | 音声データのデコード */
/* */
/* HISTORY | Comment | Name */
/* ------------------+---------------------------------------+------------ */
/* 2000.06.12 | 新規作成 | ふぃろ */
/* 2000.07.11 | PSRPLUGIN構造体の変更 1.10 | ふぃろ */
/* 2000.07.12 | CD解析中断用処理の追加 1.10 | ふぃろ */
/* 2000.08.08 | プラグイン仕様変更 1.20 | ふぃろ */
/* 2000.08.13 | 最終フレーム取得不能対策 1.21 | ふぃろ */
/* 2000.10.28 | プラグイン仕様変更 1.30 | ふぃろ */
/* */
/* (C) Copyright ふぃろ 2000. All rights reserved. */
/******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <Windows.h>
#include "CdAccess.h"
#include "PSRP.h"
typedef struct { // セクター構造 ----------------------------------------
BYTE acCdxa[24]; // CD-ROM XA
BYTE abHead[4]; // SM*\1
BYTE bSectNo; // セクタ番号 0~
BYTE bLastSectNo; // フレーム内最終セクタ番号
USHORT usFrameNo; // フレーム番号 0~
BYTE abData[2040]; // データ
BYTE abEdc[4]; // EDC
BYTE abPParity[172]; // Pパリティ
BYTE abQParity[104]; // Qパリティ
} _TSECTOR, *_PTSECTOR;
typedef struct { // ストリーム情報 --------------------------------------
WORD wTypeFlags; // データ種別フラグ PSR_STRTYPE_XXX
WORD wNumFrame; // フレーム数
WORD wUSector; // フレーム当りのセクタ数
DWORD dwBeginningPos; // データ開始セクタ番号
} _TSTREAM, *_PTSTREAM;
typedef struct { // ストリーム探索ハンドルの内容 ------------------------
BOOL fFindout; // 発見フラグ
INT iBuffer; // ストリームバッファ数
INT iNum; // ストリーム数
_PTSTREAM pstr; // ストリーム情報群
} _TFIND, *_PTFIND;
typedef struct { // ストリームハンドルの内容 ----------------------------
HANDLE hCdrom; // CD-ROMハンドル
DWORD nBeginning; // ストリーム開始位置
DWORD nNumSector; // 残りセクタ数
WORD wNumFrame; // フレーム数
WORD wSectPerFrame; // フレーム当りのセクタ数
_PTSECTOR psector; // 退避セクタ
} _THANDLE, *_PTHANDLE;
typedef struct { // WAVE要素 --------------------------------------------
SHORT sLeft;
SHORT sRight;
} _WAVEELM, *_PWAVEELM;
// ADPCM用係数 -----------------------------------------
static INT aiFILTER0[] = {0x0000, 0x00f0, 0x01cc, 0x0188, 0x01e8 };
static INT aiFILTER1[] = {0x0000, 0x0000, -0x00d0, -0x00dc, -0x00f0 };
#define _ROUND(val) (min(0x7fffL, max(-0x8000L, val)))
/******************************************************************************/
/* */
/* PsrQueryPlugin() : プラグイン情報の取得 */
/* */
/******************************************************************************/
CEXPORT VOID PsrQueryPlugin(
LPPSRPLUGIN lpPlugin) // プラグイン情報取得バッファアドレス
{
strcpy(lpPlugin->aName, "FF8 Stream");
strcpy(lpPlugin->aCopyright, "Copyright (c) Fyiro 2000.");
lpPlugin->usVersion = 130; // 1.10
lpPlugin->usIsSupportVersion = 0; // 1.10
lpPlugin->usSystemVersion = PSR_SYSTEMVERSION; // 1.10
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;
if(iNumToc != 1) return NULL;
if(!(lptoc[0].bAdr & 0x04)) return NULL; // CD-DA
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 fStream, fBegin;
if(!(pfind = hIsCD)) return FALSE;
if(!(psector = pvSector)) { // 1.10
if(pfind->fFindout) { // 1.10
pfind->fFindout = FALSE; // 1.10
pfind->iNum --; // 1.10
} // 1.10
return FALSE; // 1.10
} // 1.10
fStream = FALSE;// ストリームのセクタか? -------------------------------
if(memcmp(psector->abHead, "SM", 2) == 0) {
if(psector->abHead[3] == 1) {
if(psector->bLastSectNo) {
fStream = TRUE;
}
}
}
fBegin = FALSE; // 先頭セクタか? ---------------------------------------
if(fStream && !psector->bSectNo && !psector->usFrameNo) {
fBegin = TRUE;
}
if(!pfind->fFindout && !fBegin) fStream = FALSE;
// ストリームが発見されている場合 **********************************************
if(pfind->fFindout) {
pstr = &pfind->pstr[pfind->iNum - 1];
if(!fStream || fBegin) {
pfind->fFindout = FALSE; // 終わり!
if(!pstr->wNumFrame) pfind->iNum --;
}
else {
if(psector->bSectNo == psector->bLastSectNo) {
pstr->wNumFrame = psector->usFrameNo + 1;
}
if(psector->abHead[2] == 'J') {
pstr->wTypeFlags |= PSR_STRTYPE_MOVIE;
}
}
}
// ストリームが発見されていない場合 ********************************************
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->wTypeFlags = PSR_STRTYPE_AUDIO;
pstr->wNumFrame = 0; // 初期値
pstr->wUSector = psector->bLastSectNo + 1;
pstr->dwBeginningPos = nSector;
pfind->fFindout = TRUE;
pfind->iNum ++;
}
return TRUE;
}
/******************************************************************************/
/* */
/* PsrIsSupportCDResult() : CDサポート判定 結果取得 */
/* */
/******************************************************************************/
CEXPORT INT PsrIsSupportCDResult(
HANDLE hIsCD, // CDサポート判定ハンドル
INT iIndex, // ストリームインデックス
LPPSRSTREAMINFO lpStreamInfo) // ストリームデータ情報
{
_PTFIND pfind;
_PTSTREAM pstr;
if(!(pfind = hIsCD)) return 0;
if(pfind->iNum <= iIndex) return -1;
if(lpStreamInfo) {
pstr = &pfind->pstr[iIndex];
lpStreamInfo->wTypeFlags = pstr->wTypeFlags;
lpStreamInfo->wReserved = 0;
lpStreamInfo->nBeginSector = pstr->dwBeginningPos;
lpStreamInfo->nNumSector = (DWORD)pstr->wNumFrame *
(DWORD)pstr->wUSector;
lpStreamInfo->nNumFrame = (DWORD)pstr->wNumFrame;
lpStreamInfo->nPlayTime = ((DWORD)pstr->wNumFrame * 1000) / 15;
lpStreamInfo->szFrame.cx = 0x140;
lpStreamInfo->szFrame.cy = 0x0e0;
lpStreamInfo->wFrameRate = 150;
lpStreamInfo->wFormatTag = WAVE_FORMAT_PCM;
lpStreamInfo->wChannels = 2;
lpStreamInfo->wBitsPerSample = 16;
lpStreamInfo->nSamplesPerSec = 44100;
lpStreamInfo->nDataSize = lpStreamInfo->nNumSector * 2040; // 1.30
}
return pfind->iNum;
}
/******************************************************************************/
/* */
/* PsrGetStrDataInfo() : ストリームデータ情報の取得 */
/* */
/******************************************************************************/
CEXPORT BOOL PsrGetStrDataInfo(
INT iDriveNo, // ドライブ番号
DWORD dwBegin, // 開始セクタ番号
DWORD dwNumSector, // セクタ数
LPPSRSTREAMINFO lpStreamInfo) // ストリームデータ情報
{
HANDLE hCdrom;
_PTSECTOR psector;
INT iSectPerFrame;
WORD wTypeFlags;
// 先頭のセクタだけ読み取る ----------------------------
hCdrom = CdReadOpen(iDriveNo, NULL, dwBegin, 4, -1);
if(!hCdrom) return FALSE;
iSectPerFrame = 0;
wTypeFlags = 0;
while(psector = CdReadSector(hCdrom, NULL)) {
if(memcmp(psector->abHead, "SM", 2) == 0 &&
psector->abHead[3] == 1 && psector->bLastSectNo) {
iSectPerFrame = psector->bLastSectNo + 1;
if(psector->abHead[2] == 'N' ||
psector->abHead[2] == 'R')
wTypeFlags |= PSR_STRTYPE_AUDIO;
else if(psector->abHead[2] == 'J')
wTypeFlags |= PSR_STRTYPE_MOVIE;
}
CdUnlockReadBuffer(hCdrom, psector);
}
CdReadClose(hCdrom);
if(!iSectPerFrame || !wTypeFlags) return FALSE;
// ストリームデータ情報を作成する ----------------------
lpStreamInfo->wTypeFlags = wTypeFlags;
lpStreamInfo->wReserved = 0;
lpStreamInfo->nBeginSector = dwBegin;
lpStreamInfo->nNumSector = dwNumSector;
lpStreamInfo->nNumFrame = dwNumSector / iSectPerFrame;
lpStreamInfo->nPlayTime = (lpStreamInfo->nNumFrame * 1000) / 15;
if(wTypeFlags & PSR_STRTYPE_MOVIE) {
lpStreamInfo->szFrame.cx = 0x140;
lpStreamInfo->szFrame.cy = 0x0e0;
lpStreamInfo->wFrameRate = 150;
} else {
lpStreamInfo->szFrame.cx = 0;
lpStreamInfo->szFrame.cy = 0;
lpStreamInfo->wFrameRate = 0;
}
if(wTypeFlags & PSR_STRTYPE_AUDIO) {
lpStreamInfo->wFormatTag = WAVE_FORMAT_PCM;
lpStreamInfo->wChannels = 2;
lpStreamInfo->wBitsPerSample = 16;
lpStreamInfo->nSamplesPerSec = 44100;
} else {
lpStreamInfo->wFormatTag = 0;
lpStreamInfo->wChannels = 0;
lpStreamInfo->wBitsPerSample = 0;
lpStreamInfo->nSamplesPerSec = 0;
}
lpStreamInfo->nDataSize = lpStreamInfo->nNumSector * 2040;//1.30
return TRUE;
}
/******************************************************************************/
/* */
/* PsrOpenCD() : CDストリームのオープン */
/* */
/******************************************************************************/
CEXPORT HANDLE PsrOpenCD(
INT iDriveNo, // ドライブ番号
LPPSRSTREAMINFO lpStreamInfo) // ストリームデータ情報
{
_PTHANDLE phandle;
HANDLE hCdrom;
// CD-ROMのオープン ------------------------------------
hCdrom = CdReadOpen(iDriveNo, NULL,
lpStreamInfo->nBeginSector,
lpStreamInfo->nNumSector, -1);
if(!hCdrom) return NULL;
// ハンドルを作成 --------------------------------------
if(!(phandle = malloc(sizeof(_THANDLE)))) {
CdReadClose(hCdrom);
return NULL;
}
phandle->hCdrom = hCdrom;
phandle->nBeginning = lpStreamInfo->nBeginSector;
phandle->wSectPerFrame = (WORD)(lpStreamInfo->nNumSector /
lpStreamInfo->nNumFrame);
phandle->wNumFrame = (WORD)lpStreamInfo->nNumFrame;
phandle->psector = NULL;
PsrDecodeAudio(NULL, NULL, 0);
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;
INT iPos, iSize;
PBYTE pbBuff;
WORD wType, wNumSect;
phandle = hStream;
memset(lpBuffer, 0, sizeof(PSRREADBUFF) - PSR_FRAMEBUFFER);
pbBuff = lpBuffer->abData;
wType = 0;
wNumSect= 0;
// 退避バッファの内容を設定 ----------------------------
if(phandle->psector) {
psector = phandle->psector;
phandle->psector = NULL;
if(psector->abHead[2] == 'N') {
iPos = 0x168;
wType = PSR_STRTYPE_AUDIO;
} else if(psector->abHead[2] == 'J') {
iPos = 0;
wType = PSR_STRTYPE_MOVIE;
lpBuffer->nFrameNo = psector->usFrameNo + 1;
lpBuffer->szFrame.cx = 0x140;
lpBuffer->szFrame.cy = 0x0e0;
} else {
// ####
}
iSize = sizeof(psector->abData) - iPos;
memcpy(pbBuff, &psector->abData[iPos], iSize);
CdUnlockReadBuffer(phandle->hCdrom, psector);
pbBuff += iSize;
lpBuffer->nLength += iSize;
wNumSect = 1;
}
while(1) { // CDから読み込んで設定 --------------------------------
if(!(psector = CdReadSector(phandle->hCdrom, NULL))) break;
// 音声データ - - - - - - - - - - - - - - - - -
if(psector->abHead[2] == 'N' || psector->abHead[2] == 'R') {
if(wType & PSR_STRTYPE_MOVIE) {
phandle->psector = psector;
break;
}
iPos = 0x168;
wType = PSR_STRTYPE_AUDIO;
}
// 映像データ - - - - - - - - - - - - - - - - -
else if(psector->abHead[2] == 'J') {
if(wType & PSR_STRTYPE_AUDIO) {
phandle->psector = psector;
break;
}
iPos = 0;
wType = PSR_STRTYPE_MOVIE;
lpBuffer->nFrameNo = psector->usFrameNo + 1;
lpBuffer->szFrame.cx = 0x140;
lpBuffer->szFrame.cy = 0x0e0;
} else {
// ####
}
iSize = sizeof(psector->abData) - iPos;
memcpy(pbBuff, &psector->abData[iPos], iSize);
CdUnlockReadBuffer(phandle->hCdrom, psector);
pbBuff += iSize;
lpBuffer->nLength += iSize;
wNumSect ++;
if(wNumSect >= phandle->wSectPerFrame) break;
}
return (lpBuffer->nLength ? TRUE : FALSE);
}
/******************************************************************************/
/* */
/* PsrSeek() : 読み取り位置の設定 */
/* */
/******************************************************************************/
CEXPORT BOOL PsrSeek(
HANDLE hStream, // ストリームハンドル
DWORD dwPosition) // 読み取り位置 1/1000秒単位
{
_PTHANDLE phandle;
LONG lSector;
phandle = hStream;
lSector = ((dwPosition * 15) / 1000) * (LONG)phandle->wSectPerFrame;
if(phandle->psector) {
CdUnlockReadBuffer(phandle->hCdrom, phandle->psector);
phandle->psector = NULL;
}
if(CdSetReadPointer(phandle->hCdrom, lSector, FILE_BEGIN) == 0xffffffff) {
return FALSE;
}
PsrDecodeAudio(NULL, NULL, 0);
return TRUE;
}
/******************************************************************************/
/* */
/* PsrDecodeAudio() : 音声データのデコード */
/* */
/******************************************************************************/
CEXPORT DWORD PsrDecodeAudio(
LPPSRREADBUFF lpAudio, // 音声データ
PVOID pvBuffer, // デコード後の音声データ
DWORD nLength) // lpBufferのバイト数
{
static LONG alPRE_L[2], alPRE_R[2];
DWORD nSize;
INT i, j, k, iTmp;
INT iScaleL, iScaleR, iIndexL, iIndexR;
INT aiFilterL[2], aiFilterR[2];
INT aiValL[2], aiValR[2];
_PWAVEELM pwave;
PBYTE pbLeft, pbRight;
if(!lpAudio) {
alPRE_L[0] = alPRE_L[1] = 0;
alPRE_R[0] = alPRE_R[1] = 0;
return 0;
}
pwave = pvBuffer;
nSize = sizeof(_WAVEELM) * 0x69 * 14 * 2;
if(nLength < nSize) return nSize;
pbLeft = lpAudio->abData;
pbRight = lpAudio->abData + 0x690;
for(i=0; i<0x69; i++) {
iScaleL = 0x0c - (pbLeft[0] & 0x0f);
iIndexL = (pbLeft[0] >> 4);
aiFilterL[0] = aiFILTER0[iIndexL];
aiFilterL[1] = aiFILTER1[iIndexL];
iScaleR = 0x0c - (pbRight[0] & 0x0f);
iIndexR = (pbRight[0] >> 4);
aiFilterR[0] = aiFILTER0[iIndexR];
aiFilterR[1] = aiFILTER1[iIndexR];
pbLeft += 2;
pbRight += 2;
for(j=0; j<14; j++, pbLeft++, pbRight++) {
aiValL[0] = (pbLeft[0] & 0x0f);
aiValL[1] = (pbLeft[0] >> 4);
aiValR[0] = (pbRight[0] & 0x0f);
aiValR[1] = (pbRight[0] >> 4);
for(k=0; k<2; k++, pwave++) {
if(aiValL[k] >= 8) aiValL[k] -= 16;
iTmp = (aiValL[k] << iScaleL);
iTmp += ((alPRE_L[0] * aiFilterL[0] +
alPRE_L[1] * aiFilterL[1]) >> 8);
alPRE_L[1] = alPRE_L[0];
alPRE_L[0] = _ROUND(iTmp);
pwave[0].sLeft = (SHORT)alPRE_L[0];
if(aiValR[k] >= 8) aiValR[k] -= 16;
iTmp = (aiValR[k] << iScaleR);
iTmp += ((alPRE_R[0] * aiFilterR[0] +
alPRE_R[1] * aiFilterR[1]) >> 8);
alPRE_R[1] = alPRE_R[0];
alPRE_R[0] = _ROUND(iTmp);
pwave[0].sRight = (SHORT)alPRE_R[0];
}
}
}
return nSize;
}