home *** CD-ROM | disk | FTP | other *** search
/ Pleasure 76 / OTACD76.bin / archive / game / PsrSDK16a / PsrSDK16a.lzh / Sample / PsrStr / Plugin.c < prev   
C/C++ Source or Header  |  2000-12-02  |  15KB  |  455 lines

  1. /******************************************************************************/
  2. /*                                          */
  3. /* [PSストリームアクセスプラグイン]                          */
  4. /*                                          */
  5. /*    FILE NAME    : Plugin.c                             */
  6. /*    FUNCTION    : 標準STRアクセス (ファイル用)                  */
  7. /*                                          */
  8. /*    FUNCTIONS        | an outline                      */
  9. /*    --------------------------+-------------------------------------------- */
  10. /*    PsrQueryPlugin()    | プラグイン情報の取得                  */
  11. /*    PsrIsSupportFile()    | ストリームファイルのサポート判定          */
  12. /*    PsrGetStrFileInfo()    | ストリームファイル情報の取得              */
  13. /*    PsrOpenFile()        | ストリームファイルのオープン              */
  14. /*    PsrClose()        | ストリームデータのクローズ              */
  15. /*    PsrRead()        | ストリームデータの読み取り              */
  16. /*    PsrSeek()        | 読み取り位置の設定                  */
  17. /*                                          */
  18. /*    HISTORY        | Comment                | Name          */
  19. /*    ------------------+---------------------------------------+------------ */
  20. /*    2000.01.21    | 新規作成                | ふぃろ      */
  21. /*    2000.05.09    | CDサポートのため全面修正        | ふぃろ      */
  22. /*    2000.07.06    | BSヘッダチェック (FF7対応)    1.01    | ふぃろ      */
  23. /*    2000.07.11    | PSRPLUGIN構造体の変更        1.10    | ふぃろ      */
  24. /*    2000.07.12    | サンプリングレートの判定    1.10    | ふぃろ      */
  25. /*    2000.07.15    | フレームレート誤認識        1.11    | ふぃろ      */
  26. /*    2000.07.16    | オーディオ判定        1.11    | ふぃろ      */
  27. /*    2000.07.19    | フレームレート判定を7.5おきに    1.12    | ふぃろ      */
  28. /*    2000.10.28    | プラグイン仕様変更        1.20    | ふぃろ      */
  29. /*    2000.12.03    | IKI形式のサポート        1.21    | ふぃろ      */
  30. /*                                          */
  31. /*            (C) Copyright ふぃろ 2000. All rights reserved.       */
  32. /******************************************************************************/
  33.  
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <malloc.h>
  37. #include <Windows.h>
  38.  
  39. #include "PSRP.h"
  40.  
  41.  
  42. #define _MaxSEARCH        24                    // 1.01
  43.  
  44.  
  45. typedef struct {    // STRファイルのヘッダー構造 ---------------------------
  46.     CHAR        achRiff[4];        // 'RIFF'
  47.     BYTE        abDummy[0x28];
  48. } _TSTRHEADER;
  49.  
  50.  
  51. typedef struct {    // セクター構造 ----------------------------------------
  52.     BYTE        abSync[12];        // CD-ROM XA 同期
  53.     BYTE        abHeader[4];        // CD-ROM XA ヘッダー
  54.     BYTE        abSubHeader[8];        // CD-ROM XA サブ・ヘッダー
  55.                         //  [01014280]x2 or [01016400]x2
  56.     USHORT        usStatus;        // 0110 xxxx xxxx VVVV  ex:6001
  57.                         //    x : Reserved for system
  58.                         //    V : Version
  59.     USHORT        usDataType;        // S--- ---- ---- ----    ex:8001
  60.                         //  S : 1=system-defained format
  61.                         //      0=user-defained format
  62.     USHORT        usSectorNo;        // セクター番号    0~
  63.     USHORT        usNumSector;        // セクター数 / フレーム
  64.     ULONG        ulFrameNo;        // フレーム番号    1~
  65.     ULONG        ulLength;        // フレーム当りのデータ長
  66.     USHORT        usWidth;        // イメージ幅
  67.     USHORT        usHeight;        // イメージ高さ
  68.     ULONG        ulMovieHeadM;        // Reserved for system
  69.     ULONG        ulMovieHeadV;        // Reserved for system
  70.     ULONG        ulReserved;        // 0000 fixed
  71.     USHORT        ausMovie[0x3F0];
  72.     BYTE        abEdc[4];        // CD-ROM XA EDC
  73.     BYTE        abEcc[276];        // CD-ROM XA ECC
  74. } _TSECTOR;
  75.  
  76.  
  77. typedef struct {    // ストリームハンドルの内容 ----------------------------
  78.     HANDLE        hFile;        // ファイルハンドル
  79.     DWORD        nAllSector;    // セクタ数
  80.     DWORD        nNumSector;    // 残りセクタ数
  81.     DWORD        nNumFrame;    // フレーム数
  82.     DWORD        nFrameRate;    // フレームレート    * 10
  83.     DWORD        dwAudio;    // オーディオ退避長
  84.     BYTE        abAudio[0x900*2]; // オーディオ退避バッファ
  85. } _THANDLE, *_PTHANDLE;
  86.  
  87. /******************************************************************************/
  88. /*                                          */
  89. /*    PsrQueryPlugin() : プラグイン情報の取得                      */
  90. /*                                          */
  91. /******************************************************************************/
  92.  
  93. CEXPORT    VOID    PsrQueryPlugin(
  94.     LPPSRPLUGIN    lpPlugin)    // プラグイン情報取得バッファアドレス
  95. {
  96.     strcpy(lpPlugin->aName,      "STR file");
  97.     strcpy(lpPlugin->aCopyright, "Copyright (c) Fyiro 2000.");
  98.     lpPlugin->usVersion         = 121;            // 1.10
  99.     lpPlugin->usIsSupportVersion = 0;            // 1.10
  100.     lpPlugin->usSystemVersion    = PSR_SYSTEMVERSION;    // 1.10
  101.     strcpy(lpPlugin->aSiteName, "Fyiro's Garage");        // 1.20
  102.     strcpy(lpPlugin->aSiteUrl, "http://homepage2.nifty.com/~mkb/");    // 1.20
  103. }
  104.  
  105.  
  106.  
  107. /******************************************************************************/
  108. /*                                          */
  109. /*    PsrIsSupportFile() : ストリームファイルのサポート判定              */
  110. /*                                          */
  111. /******************************************************************************/
  112.  
  113. CEXPORT BOOL    PsrIsSupportFile(
  114.     LPCTSTR        lpFileName)    // ファイル名
  115. {
  116.     HANDLE        hFile;
  117.     DWORD        dwRead;
  118.     _TSTRHEADER    strHeader;
  119.     _TSECTOR    sector;
  120.     INT        iPos;                        // 1.01
  121.  
  122.  
  123.     if(GetFileAttributes(lpFileName) & FILE_ATTRIBUTE_DIRECTORY) {
  124.         return FALSE;
  125.     }
  126.  
  127.             // 指定されたファイルをオープンする --------------------
  128.     hFile = CreateFile(lpFileName, GENERIC_READ,
  129.             FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
  130.     if(hFile == INVALID_HANDLE_VALUE)    return FALSE;
  131.  
  132.             // 'RIFF'ヘッダーのチェック ----------------------------
  133.     ReadFile(hFile, &strHeader, sizeof(strHeader), &dwRead, 0);
  134.     if(memcmp(strHeader.achRiff, "RIFF", 4) != 0) {
  135.         CloseHandle(hFile);
  136.         return FALSE;
  137.     }
  138.  
  139.             // 動画のチェック --------------------------------------
  140.             //    ステータスコードが正しい ?
  141.             //    データタイプがシステム定義フォーマット ?
  142.             //    イメージのサイズが大きすぎない ?
  143.             //    先頭セクターが動画データ ?
  144.     if(!ReadFile(hFile, §or, sizeof(sector), &dwRead, 0)) {
  145.         CloseHandle(hFile);
  146.         return FALSE;
  147.     }
  148.     CloseHandle(hFile);
  149.  
  150.     if(dwRead != sizeof(sector))        return FALSE;
  151.     if(sector.abSubHeader[2] == 0x64)    return FALSE;
  152.     if(!sector.usStatus)            return FALSE;
  153.  
  154.     if(sector.usStatus & 0x00f0 != 0x0060)    return FALSE;
  155.     if(!(sector.usDataType & 0x8000))    return FALSE;
  156.     if(sector.usNumSector > 24)        return FALSE;
  157.  
  158.     for(iPos=0; iPos<_MaxSEARCH; iPos++) {                // 1.01
  159.         if(sector.ausMovie[iPos+1] == 0x3800)    break;        // 1.01
  160.     }                                // 1.01
  161.     if(sector.ausMovie[iPos+1] != 0x3800)    return FALSE;        // 1.01
  162.     if(sector.ausMovie[iPos+3] > 3) {            // 1.21 ------->
  163.         if(sector.ausMovie[iPos+2] != sector.usWidth) return FALSE;
  164.         if(sector.ausMovie[iPos+3] != sector.usHeight) return FALSE;
  165.     }                            // <------- 1.21
  166.  
  167.     return TRUE;
  168. }
  169.  
  170. /******************************************************************************/
  171. /*                                          */
  172. /*    PsrGetStrFileInfo() : ストリームファイル情報の取得              */
  173. /*                                          */
  174. /******************************************************************************/
  175.  
  176. CEXPORT    BOOL    PsrGetStrFileInfo(
  177.     LPCTSTR        lpFileName,    // ファイル名
  178.     LPPSRSTREAMINFO    lpStreamInfo)    // ストリームデータ情報
  179. {
  180.     HANDLE        hFile;
  181.     DWORD        dwRead, dwSize, dwNumSector;
  182.     DWORD        dwNumAudio, dwNumMovie, dwSecCount, dwLength;
  183.     DWORD        dwNumMBlock, dwResolution, nAudioPct;        // 1.10
  184.     DWORD        nNumFrame, nTimeAudio;                // 1.11
  185.     WORD        wResolution, wLength, wRate;            // 1.12
  186.     BYTE        bAudioSubH;                    // 1.10
  187.     SIZE        szFrame;
  188.     _TSECTOR    sector;
  189.  
  190.  
  191.             // 指定されたファイルをオープンする --------------------
  192.     hFile = CreateFile(lpFileName, GENERIC_READ,
  193.             FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
  194.     if(hFile == INVALID_HANDLE_VALUE)    return FALSE;
  195.  
  196.     SetFilePointer(hFile, sizeof(_TSTRHEADER), NULL, FILE_BEGIN);
  197.  
  198.             // セクター数を求める ----------------------------------
  199.     dwSize = GetFileSize(hFile, NULL) - sizeof(_TSTRHEADER);
  200.     dwNumSector = dwSize / sizeof(_TSECTOR);
  201.  
  202.             // 先頭nフレーム分のセクターを読み取って必要な情報を収集
  203.     dwNumAudio = dwNumMovie = nAudioPct = nNumFrame = 0;        // 1.11
  204.     while(1) {
  205.         if(!ReadFile(hFile, §or, sizeof(sector), &dwRead, 0)) break;
  206.         if(dwRead != sizeof(sector))    break;
  207.  
  208.         if(sector.abSubHeader[2] == 0x64) {
  209.             dwNumAudio ++;
  210.             bAudioSubH = sector.abSubHeader[3];        // 1.10
  211.             if(!nAudioPct) {                // 1.10
  212.                 nAudioPct = dwNumAudio + dwNumMovie;    // 1.10
  213.             }                        // 1.10
  214.             continue;
  215.         }
  216.         if(sector.usStatus && sector.ulFrameNo > 30)    break;
  217.  
  218.         dwNumMovie ++;
  219.         if(!sector.usStatus)        continue;
  220.         if(sector.usSectorNo == 0 && sector.ulFrameNo) {
  221.             szFrame.cx = sector.usWidth;
  222.             szFrame.cy = sector.usHeight;
  223.             nNumFrame = sector.ulFrameNo;            // 1.11
  224.         }
  225.     }
  226.     CloseHandle(hFile);
  227.  
  228.             // 有効なセクターがない(エラー) ------------------------
  229.     if(!dwNumMovie)    return FALSE;
  230.  
  231.             // ストリームデータ情報を設定 --------------------------
  232.     dwNumMBlock = ((szFrame.cx + 15) / 16) * ((szFrame.cy + 15) / 16);
  233.     dwResolution= 90000 / dwNumMBlock;
  234.     if(dwResolution < 150)        wResolution = 75;
  235.     else if(dwResolution < 300)    wResolution = 150;
  236.     else if(dwResolution < 600)    wResolution = 300;
  237.     else                wResolution = 600;
  238.  
  239.     dwLength = dwNumMovie * sizeof(sector.ausMovie) / nNumFrame;    // 1.11
  240.     if(dwLength > 20 * 1024)        wLength = 75;
  241.     else if(dwLength > 10 * 1024)        wLength = 150;
  242.     else if(dwLength >  5 * 1024)        wLength = 300;
  243.     else                    wLength = 600;
  244.  
  245.     dwSecCount = dwNumAudio + dwNumMovie;
  246.     lpStreamInfo->wTypeFlags    = PSR_STRTYPE_MOVIE;
  247.     lpStreamInfo->wReserved        = 0;
  248.     lpStreamInfo->nBeginSector  = 0;
  249.     lpStreamInfo->nNumSector    = 0;
  250.     lpStreamInfo->nNumFrame        = (dwNumSector * nNumFrame) / dwSecCount;
  251.     lpStreamInfo->szFrame        = szFrame;
  252.     lpStreamInfo->wFrameRate    = min(wResolution, wLength);
  253.     if(dwNumAudio) {
  254.         lpStreamInfo->wTypeFlags    |= PSR_STRTYPE_AUDIO;
  255.         lpStreamInfo->wFormatTag    = WAVE_FORMAT_PCM;
  256.         lpStreamInfo->wBitsPerSample    = 16;
  257.         lpStreamInfo->wChannels        =            // 1.11
  258.                 (bAudioSubH & 0x01) ? 2 : 1;        // 1.11
  259.         lpStreamInfo->nSamplesPerSec    =            // 1.11
  260.                 (bAudioSubH & 0x04) ? 18900:37800;    // 1.11
  261.     }
  262.     else {
  263.         lpStreamInfo->wFormatTag    = 0;
  264.         lpStreamInfo->wChannels        = 0;
  265.         lpStreamInfo->nSamplesPerSec    = 0;
  266.         lpStreamInfo->wBitsPerSample    = 0;
  267.     }
  268.  
  269.     if(dwNumAudio) {// フレームレート補正 ---------------------------- 1.12
  270.         nTimeAudio = (dwNumAudio * 40320) /
  271.                 (lpStreamInfo->wChannels *
  272.                     (lpStreamInfo->nSamplesPerSec / 100));
  273.         wRate = (WORD)((nNumFrame * 10000) / nTimeAudio);
  274.         if(abs((INT)lpStreamInfo->wFrameRate - (INT)wRate) > 20){
  275.             lpStreamInfo->wFrameRate = ((wRate + 2) / 5) * 5;
  276.         }
  277.     }
  278.     lpStreamInfo->nPlayTime    = (lpStreamInfo->nNumFrame * 10000) /
  279.                     lpStreamInfo->wFrameRate;
  280.  
  281.     return TRUE;
  282. }
  283.  
  284. /******************************************************************************/
  285. /*                                          */
  286. /*    PsrOpenFile() : ストリームファイルのオープン                  */
  287. /*                                          */
  288. /******************************************************************************/
  289.  
  290. CEXPORT HANDLE    PsrOpenFile(
  291.     LPCTSTR        lpFileName,    // ファイル名
  292.     LPPSRSTREAMINFO    lpStreamInfo)    // ストリームデータ情報
  293. {
  294.     _PTHANDLE    phandle;
  295.  
  296.  
  297.             // ハンドルを作成 --------------------------------------
  298.     if(!(phandle = malloc(sizeof(_THANDLE))))    return NULL;
  299.     phandle->hFile        = NULL;
  300.     phandle->nAllSector    = 0;
  301.     phandle->nNumSector    = 0;
  302.     phandle->nNumFrame    = lpStreamInfo->nNumFrame;
  303.     phandle->nFrameRate    = lpStreamInfo->wFrameRate;
  304.     phandle->dwAudio    = 0;
  305.  
  306.             // ファイルをオープンする ------------------------------
  307.     phandle->hFile = CreateFile(lpFileName, GENERIC_READ,
  308.             FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
  309.     if(phandle->hFile == INVALID_HANDLE_VALUE) {
  310.         free(phandle);
  311.         return NULL;
  312.     }
  313.     SetFilePointer(phandle->hFile, sizeof(_TSTRHEADER), NULL, FILE_BEGIN);
  314.  
  315.     phandle->nAllSector = GetFileSize(phandle->hFile, NULL);
  316.      phandle->nAllSector -= sizeof(_TSTRHEADER);
  317.     phandle->nAllSector /= sizeof(_TSECTOR);
  318.     phandle->nNumSector = phandle->nAllSector;
  319.  
  320.     return phandle;
  321. }
  322.  
  323.  
  324.  
  325. /******************************************************************************/
  326. /*                                          */
  327. /*    PsrClose() : ストリームデータのクローズ                      */
  328. /*                                          */
  329. /******************************************************************************/
  330.  
  331. CEXPORT BOOL    PsrClose(
  332.     HANDLE        hStream)    // ストリームハンドル
  333. {
  334.     _PTHANDLE    phandle;
  335.  
  336.  
  337.     phandle = hStream;
  338.     CloseHandle(phandle->hFile);
  339.     free(phandle);
  340.     return TRUE;
  341. }
  342.  
  343. /******************************************************************************/
  344. /*                                          */
  345. /*    PsrRead() : ストリームデータの読み取り                      */
  346. /*                                          */
  347. /******************************************************************************/
  348.  
  349. CEXPORT BOOL    PsrRead(
  350.     HANDLE        hStream,    // ストリームハンドル
  351.     LPPSRREADBUFF    lpBuffer)    // 読み取りバッファ
  352. {
  353.     _PTHANDLE    phandle;
  354.     _TSECTOR    sector;
  355.     DWORD        dwRead;
  356.     INT        iSize, iLength, iPos;                // 1.01
  357.     PBYTE        pbBuffer;
  358.  
  359.  
  360.     phandle = hStream;
  361.     memset(lpBuffer, 0, sizeof(PSRREADBUFF) - PSR_FRAMEBUFFER);
  362.  
  363.             // 退避オーディオバッファの内容を設定 ------------------
  364.     if(phandle->dwAudio) {
  365.         lpBuffer->nLength = phandle->dwAudio;
  366.         memcpy(lpBuffer->abData, phandle->abAudio, phandle->dwAudio);
  367.         phandle->dwAudio = 0;
  368.         return TRUE;
  369.     }
  370.  
  371.     iLength = 0;    // ファイルから読み込んで設定 --------------------------
  372.     while(phandle->nNumSector) {
  373.         if(!ReadFile(phandle->hFile, §or, sizeof(sector), &dwRead, 0))    break;
  374.         if(dwRead != sizeof(sector))    break;
  375.  
  376.         phandle->nNumSector --;
  377.  
  378.                 // オーディオデータ - - - - - - - - - - - - - -
  379.         if(sector.abSubHeader[2] == 0x64) {
  380.             if(!lpBuffer->nFrameNo) {
  381.                 lpBuffer->nLength = 0x900;
  382.                 memcpy(lpBuffer->abData,
  383.                     §or.usStatus, lpBuffer->nLength);
  384.                 return TRUE;
  385.             } else {
  386.                 if(phandle->dwAudio >= 0x900 * 2) continue;
  387.                 memcpy(&phandle->abAudio[phandle->dwAudio],
  388.                     §or.usStatus, 0x900);
  389.                 phandle->dwAudio += 0x900;
  390.                 continue;
  391.             }
  392.         }
  393.  
  394.                 // 動画データ - - - - - - - - - - - - - - - - -
  395.         if(!sector.usStatus)    continue;
  396.         if(!sector.ulFrameNo)    continue;
  397.  
  398.         iPos = 0;    // 先頭セクター - - - - - - - - - - - - - - - -
  399.         if(!sector.usSectorNo) {
  400.             lpBuffer->nFrameNo    = sector.ulFrameNo;
  401.             lpBuffer->szFrame.cx    = sector.usWidth;
  402.             lpBuffer->szFrame.cy    = sector.usHeight;
  403.             iLength    = (INT)sector.ulLength;
  404.             pbBuffer= lpBuffer->abData;
  405.             for(iPos=0; iPos<_MaxSEARCH; iPos++) {    // 1.01 ------->
  406.                 if(sector.ausMovie[iPos+1] == 0x3800)    break;
  407.             }                    // <------- 1.01
  408.         }
  409.  
  410.         if(iLength) {    // イメージデータのコピー - - - - - - - - - - -
  411.             iSize = sizeof(sector.ausMovie) -        // 1.01
  412.                     (sizeof(USHORT) * iPos);    // 1.01
  413.             iSize = min(iSize, iLength);            // 1.01
  414.             memcpy(pbBuffer, §or.ausMovie[iPos], iSize);// 1.01
  415.             pbBuffer += iSize;
  416.             iLength    -= iSize;
  417.             lpBuffer->nLength += iSize;
  418.         }
  419.  
  420.                 // 最終セクター - - - - - - - - - - - - - - - -
  421.         if(sector.usSectorNo == sector.usNumSector - 1) {
  422.             return TRUE;
  423.         }
  424.     }
  425.     return FALSE;
  426. }
  427.  
  428. /******************************************************************************/
  429. /*                                          */
  430. /*    PsrSeek() : 読み取り位置の設定                          */
  431. /*                                          */
  432. /******************************************************************************/
  433.  
  434. CEXPORT BOOL    PsrSeek(
  435.     HANDLE        hStream,    // ストリームハンドル
  436.     DWORD        dwPosition)    // 読み取り位置        1/1000秒単位
  437. {
  438.     _PTHANDLE    phandle;
  439.     LONG        lFrame, lSector, lPos;
  440.  
  441.  
  442.     phandle    = hStream;
  443.     lFrame    = (dwPosition * phandle->nFrameRate) / 10000;
  444.     lSector    = (lFrame * phandle->nAllSector) / phandle->nNumFrame;
  445.     lPos    = lSector * sizeof(_TSECTOR) + sizeof(_TSTRHEADER);
  446.  
  447.     if(SetFilePointer(phandle->hFile, lPos, NULL, FILE_BEGIN) == 0xffffffff) {
  448.         return FALSE;
  449.     }
  450.  
  451.     phandle->dwAudio = 0;
  452.     phandle->nNumSector = phandle->nAllSector - lSector;
  453.     return TRUE;
  454. }
  455.