home *** CD-ROM | disk | FTP | other *** search
/ Pleasure 76 / OTACD76.bin / archive / game / PsrSDK16a / PsrSDK16a.lzh / Sample / PsrXaCd / Plugin.c < prev   
C/C++ Source or Header  |  2000-11-20  |  18KB  |  574 lines

  1. /******************************************************************************/
  2. /*                                          */
  3. /* [PS XAプラグイン]                                  */
  4. /*                                          */
  5. /*    FILE NAME    : Plugin.c                             */
  6. /*    FUNCTION    : 標準XAアクセス (CD-ROM用)                  */
  7. /*                                          */
  8. /*    FUNCTIONS        | an outline                      */
  9. /*    --------------------------+-------------------------------------------- */
  10. /*    PsrQueryPlugin()    | プラグイン情報の取得                  */
  11. /*    PsrIsSupportCDBegin()    | CDサポート判定 開始処理              */
  12. /*    PsrIsSupportCDEnd()    | CDサポート判定 終了処理              */
  13. /*    PsrIsSupportCDSector()    | CDサポート判定 セクタ通知              */
  14. /*    PsrIsSupportCDResult()    | CDサポート判定 結果取得              */
  15. /*    PsrGetStrDataInfo()    | ストリームデータ情報の取得              */
  16. /*    PsrOpenCD()        | CDストリームのオープン              */
  17. /*    PsrClose()        | ストリームデータのクローズ              */
  18. /*    PsrRead()        | ストリームデータの読み取り              */
  19. /*    PsrSeek()        | 読み取り位置の設定                  */
  20. /*                                          */
  21. /*    HISTORY        | Comment                | Name          */
  22. /*    ------------------+---------------------------------------+------------ */
  23. /*    2000.07.16    | 新規作成                | ふぃろ      */
  24. /*    2000.07.19    | STRの最後のXA部を拾っちゃう件    1.01    | ふぃろ      */
  25. /*    2000.07.20    | STRの終端判定を強化        1.02    | ふぃろ      */
  26. /*    2000.07.21    | セクタ数不良を修正        1.03    | ふぃろ      */
  27. /*    2000.08.08    | STRのXA部を拾っちゃう件2    1.04    | ふぃろ      */
  28. /*    2000.08.10    | チャンネル番号判定修正    1.05    | ふぃろ      */
  29. /*    2000.10.28    | プラグイン仕様変更        1.10    | ふぃろ      */
  30. /*    2000.11.14    | 誤認識対策            1.11    | ふぃろ      */
  31. /*                                          */
  32. /*            (C) Copyright ふぃろ 2000. All rights reserved.       */
  33. /******************************************************************************/
  34.  
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <malloc.h>
  38. #include <Windows.h>
  39.  
  40. #include "CdAccess.h"
  41. #include "PSRP.h"
  42.  
  43. static LONG    alZERO[] = {0, 0, 0, 0, 0, 0, 0, 0};
  44.  
  45.  
  46. typedef struct {    // サブヘッダー ----------------------------------------
  47.     USHORT        usChaNo;        // チャンネル番号
  48.     BYTE        bfType;            // タイプ
  49.     BYTE        bfFlags;        // フラグ
  50. } _TSUBHEADER, *_PTSUBHEADER;
  51.  
  52.  
  53. typedef struct {    // セクター構造 ----------------------------------------
  54.     BYTE        abSync[12];        // CD-ROM XA 同期
  55.     BYTE        abHeader[4];        // CD-ROM XA ヘッダー
  56.     _TSUBHEADER    asubH[2];        // CD-ROM XA サブヘッダー 1.05
  57.     BYTE        abAudio[0x900];        // XA AUDIO
  58.     BYTE        abEdc[4];        // CD-ROM XA EDC
  59. } _TSECTOR, *_PTSECTOR;
  60.  
  61.  
  62. typedef struct {    // ストリーム情報 --------------------------------------
  63.     DWORD        dwBegin;    // データ開始セクタ番号
  64.     DWORD        nLength;    // データセクタ数
  65.     USHORT        usChannels;    // チャンネル数            1.05
  66.     USHORT        usChaNo;    // チャンネル番号        1.05
  67.     BYTE        bFlags;        // フラグ
  68.     BYTE        bEnded;        // 完了フラグ
  69.     DWORD        nLast;        // 最終セクタ            1.11
  70.     DWORD        nLastGood;    // 最終有効セクタ        1.11
  71. } _TSTREAM, *_PTSTREAM;
  72.  
  73.  
  74. typedef struct {    // ストリーム探索ハンドルの内容 ------------------------
  75.     INT        iBuffer;    // ストリームバッファ数
  76.     INT        iNum;        // ストリーム数
  77.     INT        iNumChannels;    // XAチャンネル数
  78.     _PTSTREAM    pstr;        // ストリーム情報群
  79. } _TFIND, *_PTFIND;
  80.  
  81.  
  82. typedef struct {    // ストリームハンドルの内容 ----------------------------
  83.     HANDLE        hCdrom;        // CD-ROMハンドル
  84.     DWORD        nBegin;        // ストリーム開始セクタ
  85.     DWORD        nAllSector;    // セクタ数
  86.     DWORD        nSamplingRate;    // サンプリングレート
  87.     WORD        wChannels;    // チャンネル数
  88.     WORD        wStep;        // セクタ間隔
  89.     _TSUBHEADER    subH;        // サブヘッダ
  90.     _PTSECTOR    apSector[2];    // 退避セクタ
  91. } _THANDLE, *_PTHANDLE;
  92.  
  93. /******************************************************************************/
  94. /*                                          */
  95. /*    PsrQueryPlugin() : プラグイン情報の取得                      */
  96. /*                                          */
  97. /******************************************************************************/
  98.  
  99. CEXPORT    VOID    PsrQueryPlugin(
  100.     LPPSRPLUGIN    lpPlugin)    // プラグイン情報取得バッファアドレス
  101. {
  102.     strcpy(lpPlugin->aName,      "XA CD-ROM");
  103.     strcpy(lpPlugin->aCopyright, "Copyright (c) Fyiro 2000.");
  104.     lpPlugin->usVersion         = 111;
  105.     lpPlugin->usIsSupportVersion = 0;
  106.     lpPlugin->usSystemVersion    = PSR_SYSTEMVERSION;
  107.     strcpy(lpPlugin->aSiteName, "Fyiro's Garage");        // 1.10
  108.     strcpy(lpPlugin->aSiteUrl, "http://homepage2.nifty.com/~mkb/");    // 1.10
  109. }
  110.  
  111.  
  112.  
  113. /******************************************************************************/
  114. /*                                          */
  115. /*    PsrIsSupportCDBegin() : CDサポート判定 開始処理                  */
  116. /*                                          */
  117. /******************************************************************************/
  118.  
  119. CEXPORT HANDLE    PsrIsSupportCDBegin(
  120.     INT        iNumToc,    // TOCの数
  121.     LPTOCENTRY    lptoc)        // TOC
  122. {
  123.     _PTFIND        pfind;
  124.     INT        i;
  125.  
  126.  
  127.     for(i=0; i<iNumToc; i++) {
  128.         if(lptoc[i].bAdr & 0x04)    break;
  129.     }
  130.     if(i == iNumToc)    return NULL;
  131.  
  132.     if(!(pfind = malloc(sizeof(_TFIND))))    return NULL;
  133.  
  134.             // ハンドルの作成と初期設定 ----------------------------
  135.     pfind->iBuffer    = 64;
  136.     pfind->iNum    = 0;
  137.     pfind->iNumChannels = 0;
  138.     pfind->pstr    = malloc(sizeof(_TSTREAM) * pfind->iBuffer);
  139.     if(!pfind->pstr) {
  140.         free(pfind);
  141.         return NULL;
  142.     }
  143.     return pfind;
  144. }
  145.  
  146.  
  147.  
  148. /******************************************************************************/
  149. /*                                          */
  150. /*    PsrIsSupportCDEnd() : CDサポート判定 終了処理                  */
  151. /*                                          */
  152. /******************************************************************************/
  153.  
  154. CEXPORT    VOID    PsrIsSupportCDEnd(
  155.     HANDLE        hIsCD)        // CDサポート判定ハンドル
  156. {
  157.     _PTFIND        pfind;
  158.  
  159.  
  160.     if(!(pfind = hIsCD))    return;
  161.     free(pfind->pstr);
  162.     free(pfind);
  163. }
  164.  
  165. /******************************************************************************/
  166. /*                                          */
  167. /*    PsrIsSupportCDSector() : CDサポート判定 セクタ通知              */
  168. /*                                          */
  169. /******************************************************************************/
  170.  
  171. typedef struct {
  172.     ULONG        aulCode[4];
  173.     BYTE        abData[112];
  174. } _ADPCM, *_PADPCM;
  175.  
  176. static BOOL    _psrIsGoodAudio(_PADPCM padpcm);
  177.  
  178. CEXPORT    BOOL    PsrIsSupportCDSector(
  179.     HANDLE        hIsCD,        // CDサポート判定ハンドル
  180.     TOCENTRY    toc,        // TOC
  181.     DWORD        nSector,    // セクタ番号
  182.     PVOID        pvSector)    // セクタ
  183. {
  184.     _PTFIND        pfind;
  185.     _PTSECTOR    psector;
  186.     _PTSTREAM    pstr;
  187.     INT        i;
  188.     USHORT        usNum;
  189.  
  190.  
  191.     if(!(pfind = hIsCD))    return FALSE;
  192.     if(!(toc.bAdr & 0x04))    return FALSE;        // CD-DA
  193.     if(!(psector = pvSector)) {
  194.         for(i=pfind->iNum-1; i>=0; i--) {
  195.             if(!pfind->pstr[i].bEnded) {
  196.                 pfind->pstr[i] = pfind->pstr[pfind->iNum-1];
  197.                 pfind->iNum --;
  198.             }
  199.         }
  200.         pfind->iNumChannels = 0;
  201.         return FALSE;
  202.     }
  203.  
  204.             // XAのセクタではない ----------------------------------
  205.     if(memcmp(psector->abAudio, alZERO, sizeof(alZERO)) == 0 ||
  206.        (psector->asubH[0].bfType == 0 && psector->asubH[0].bfFlags == 0)) {
  207.         return TRUE;    // ダミー
  208.     }
  209.     if((psector->asubH[0].bfType & 0x7f) != 0x64) {        // 1.11 ------->
  210.         pstr = pfind->pstr;
  211.         for(i=0; i<pfind->iNum; i++) {
  212.             if(!pstr[i].bEnded && pstr[i].nLength != 1) {
  213.                 usNum = (USHORT)(nSector - pstr[i].nLast);
  214.                 if(usNum >= pstr[i].usChannels) {
  215.                     pstr[i].bEnded = 1;
  216.                     if(!pstr[i].nLastGood) {
  217.                         pstr[i] = pstr[pfind->iNum-1];
  218.                         pfind->iNum --;
  219.                         i --;
  220.                     }
  221.                     pfind->iNumChannels --;
  222.                 }
  223.             }
  224.         }
  225.         return TRUE;
  226.     }                            // <------- 1.11
  227.  
  228.             // ストリーム情報の探索 --------------------------------
  229.     for(pstr=NULL, i=0; i<pfind->iNum; i++) {
  230.         if(!pfind->pstr[i].bEnded &&
  231.             pfind->pstr[i].usChaNo == psector->asubH[0].usChaNo) {
  232.             pstr = &pfind->pstr[i];
  233.             break;
  234.         }
  235.     }
  236.  
  237.     if(!pstr) {    // ストリーム追加 --------------------------------------
  238.         if(pfind->iBuffer == pfind->iNum) {
  239.             pfind->iBuffer += 16;
  240.             pstr = realloc(pfind->pstr,
  241.                     sizeof(_TSTREAM) * pfind->iBuffer);
  242.             if(!pstr) {
  243.                 pfind->iBuffer -= 16;
  244.                 return TRUE;    // とりあえず正常終了
  245.             }
  246.             pfind->pstr = pstr;
  247.         }
  248.  
  249.         pstr = &pfind->pstr[pfind->iNum];
  250.         pstr->dwBegin    = nSector;
  251.         pstr->nLength    = 0;
  252.         pstr->usChannels= 1;                    // 1.03
  253.         pstr->usChaNo    = psector->asubH[0].usChaNo;
  254.         pstr->bFlags    = psector->asubH[0].bfFlags;
  255.         pstr->bEnded    = 0;
  256.         pstr->nLast    = 0;                    // 1.11
  257.         pstr->nLastGood    = 0;                    // 1.11
  258.         pfind->iNum ++;
  259.         pfind->iNumChannels ++;
  260.     }
  261.     if(pstr->nLength == 1) {
  262.         pstr->usChannels = (USHORT)(nSector - pstr->dwBegin);
  263.     }
  264.     pstr->nLast    = nSector;                    // 1.11
  265.  
  266.             // 音声データが有効なセクタであるか判定 ----------- 1.11
  267.     if(_psrIsGoodAudio((_PADPCM)psector->abAudio)) {
  268.         pstr->nLastGood    = nSector;
  269.     }
  270.  
  271.     pstr->nLength ++;
  272.  
  273.             // XAストリームの終了コード ----------------------------
  274.     if(psector->asubH[0].bfType & 0x80) {
  275.         pstr->bEnded = 1;
  276.         if(!pstr->nLastGood) {
  277.             *pstr = pfind->pstr[pfind->iNum-1];
  278.             pfind->iNum --;
  279.         }
  280.         pfind->iNumChannels --;
  281.         return TRUE;
  282.     }
  283.  
  284.     return TRUE;
  285. }
  286.  
  287.  
  288. //****--------------------------------------------------------------------------
  289. //****    _psrIsGoodAudio() : 音声データが有効か判定
  290. //****--------------------------------------------------------------------------
  291.  
  292. static BOOL    _psrIsGoodAudio(_PADPCM padpcm) {
  293.     INT        i, j;
  294.  
  295.     for(i=0; i<18; i++) {
  296.         if((padpcm->aulCode[0] && padpcm->aulCode[0] != 0x0c0c0c0c) ||
  297.            (padpcm->aulCode[1] && padpcm->aulCode[1] != 0x0c0c0c0c) ||
  298.            (padpcm->aulCode[2] && padpcm->aulCode[2] != 0x0c0c0c0c) ||
  299.            (padpcm->aulCode[3] && padpcm->aulCode[3] != 0x0c0c0c0c)) {
  300.             return TRUE;
  301.         }
  302.         for(j=0; j<112; j++) {
  303.             if(padpcm->abData[j])    return TRUE;
  304.         }
  305.         padpcm ++;
  306.     }
  307.  
  308.     return FALSE;
  309. }
  310.  
  311. /******************************************************************************/
  312. /*                                          */
  313. /*    PsrIsSupportCDResult() : CDサポート判定 結果取得              */
  314. /*                                          */
  315. /******************************************************************************/
  316.  
  317. CEXPORT    INT    PsrIsSupportCDResult(
  318.     HANDLE        hIsCD,        // CDサポート判定ハンドル
  319.     INT        iIndex,        // ストリームインデックス
  320.     LPPSRSTREAMINFO    lpStreamInfo)    // ストリームデータ情報
  321. {
  322.     _PTFIND        pfind;
  323.     _PTSTREAM    pstr;
  324.  
  325.  
  326.     if(!(pfind = hIsCD))        return 0;
  327.     if(pfind->iNum <= iIndex)    return -1;
  328.  
  329.     if(lpStreamInfo) {
  330.         pstr = &pfind->pstr[iIndex];
  331.         memset(lpStreamInfo, 0, sizeof(PSRSTREAMINFO));
  332.         lpStreamInfo->wTypeFlags    = PSR_STRTYPE_AUDIO;
  333.         lpStreamInfo->wFormatTag    = WAVE_FORMAT_PCM;
  334.         lpStreamInfo->wBitsPerSample    = 16;
  335.         lpStreamInfo->nBeginSector    = pstr->dwBegin;
  336.         lpStreamInfo->nNumSector    =
  337.             (DWORD)pstr->usChannels * (pstr->nLength - 1) + 1;// 1.03
  338.         lpStreamInfo->wChannels        = (pstr->bFlags & 0x01) ? 2 : 1;
  339.         lpStreamInfo->nSamplesPerSec    = (pstr->bFlags & 0x04) ? 18900:37800;
  340.         lpStreamInfo->nPlayTime = (40320 * pstr->nLength) /
  341.                 (lpStreamInfo->wChannels *
  342.                     (lpStreamInfo->nSamplesPerSec / 100));
  343.         lpStreamInfo->nDataSize = pstr->nLength * 0x900;    //1.30
  344.     }
  345.     return pfind->iNum;
  346. }
  347.  
  348. /******************************************************************************/
  349. /*                                          */
  350. /*    PsrGetStrDataInfo() : ストリームデータ情報の取得              */
  351. /*                                          */
  352. /******************************************************************************/
  353.  
  354. CEXPORT    BOOL    PsrGetStrDataInfo(
  355.     INT        iDriveNo,    // ドライブ番号
  356.     DWORD        dwBegin,    // 開始セクタ番号
  357.     DWORD        dwNumSector,    // セクタ数
  358.     LPPSRSTREAMINFO    lpStreamInfo)    // ストリームデータ情報
  359. {
  360.     HANDLE        hCdrom;
  361.     _PTSECTOR    psector;
  362.     _TSUBHEADER    subH;
  363.     DWORD        nStep;
  364.  
  365.  
  366.             // CD-ROMのオープン ------------------------------------
  367.     hCdrom = CdReadOpen(iDriveNo, NULL, dwBegin, min(256, dwNumSector), -1);
  368.     if(!hCdrom)    return FALSE;
  369.  
  370.             // 最初のセクタを読み込む ------------------------------
  371.     if(!(psector = CdReadSector(hCdrom, NULL))) {
  372.         CdReadClose(hCdrom);
  373.         return FALSE;
  374.     }
  375.     subH = psector->asubH[0];
  376.     subH.bfType &= 0x7f;
  377.     CdUnlockReadBuffer(hCdrom, psector);
  378.  
  379.     nStep = 1;    // セクタ間隔を求める ----------------------------- 1.03
  380.     if(dwNumSector <= 1) {
  381.         while(1) {
  382.             if(!(psector = CdReadSector(hCdrom, NULL))) {
  383.                 CdReadClose(hCdrom);
  384.                 return FALSE;
  385.             }
  386.             if(subH.usChaNo == psector->asubH[0].usChaNo &&
  387.                subH.bfType == (psector->asubH[0].bfType & 0x7f) &&
  388.                subH.bfFlags == psector->asubH[0].bfFlags) {
  389.                 break;
  390.             }
  391.             nStep ++;
  392.             CdUnlockReadBuffer(hCdrom, psector);
  393.         }
  394.     }
  395.     CdReadClose(hCdrom);
  396.  
  397.             // ストリーム情報を設定する ----------------------------
  398.     memset(lpStreamInfo, 0, sizeof(PSRSTREAMINFO));
  399.     lpStreamInfo->wTypeFlags    = PSR_STRTYPE_AUDIO;
  400.     lpStreamInfo->wFormatTag    = WAVE_FORMAT_PCM;
  401.     lpStreamInfo->wBitsPerSample    = 16;
  402.     lpStreamInfo->nBeginSector    = dwBegin;
  403.     lpStreamInfo->nNumSector    = dwNumSector;
  404.     lpStreamInfo->wChannels        = (subH.bfFlags & 0x01) ? 2 : 1;
  405.     lpStreamInfo->nSamplesPerSec    = (subH.bfFlags & 0x04) ? 18900 : 37800;
  406.     dwNumSector = (dwNumSector + (nStep - 1)) / nStep;
  407.     lpStreamInfo->nPlayTime = (40320 * dwNumSector) /
  408.                 ((DWORD)lpStreamInfo->wChannels *
  409.                     (lpStreamInfo->nSamplesPerSec / 100));
  410.     return TRUE;
  411. }
  412.  
  413. /******************************************************************************/
  414. /*                                          */
  415. /*    PsrOpenCD() : CDストリームのオープン                      */
  416. /*                                          */
  417. /******************************************************************************/
  418.  
  419. CEXPORT HANDLE    PsrOpenCD(
  420.     INT        iDriveNo,    // ドライブ番号
  421.     LPPSRSTREAMINFO    lpStreamInfo)    // ストリームデータ情報
  422. {
  423.     _PTHANDLE    phandle;
  424.     HANDLE        hCdrom;
  425.     _PTSECTOR    psector;
  426.  
  427.  
  428.             // CD-ROMのオープン ------------------------------------
  429.     hCdrom = CdReadOpen(iDriveNo, NULL,
  430.                 lpStreamInfo->nBeginSector,
  431.                 lpStreamInfo->nNumSector, -1);
  432.     if(!hCdrom)    return NULL;
  433.  
  434.             // ハンドルを作成 --------------------------------------
  435.     if(!(phandle = malloc(sizeof(_THANDLE)))) {
  436.         CdReadClose(hCdrom);
  437.         return NULL;
  438.     }
  439.     phandle->hCdrom        = hCdrom;
  440.     phandle->nBegin        = lpStreamInfo->nBeginSector;
  441.     phandle->nAllSector    = lpStreamInfo->nNumSector;
  442.     phandle->nSamplingRate    = lpStreamInfo->nSamplesPerSec;
  443.     phandle->wChannels    = lpStreamInfo->wChannels;
  444.     phandle->wStep        = 1;                    // 1.03
  445.     phandle->apSector[0]    = NULL;                    // 1.03
  446.     phandle->apSector[1]    = NULL;                    // 1.03
  447.  
  448.             // セクタの間隔を求める --------------------------------
  449.     if(!(phandle->apSector[0] = CdReadSector(hCdrom, NULL))) {
  450.         free(phandle);
  451.         CdReadClose(hCdrom);
  452.         return NULL;
  453.     }
  454.     phandle->subH = phandle->apSector[0]->asubH[0];
  455.     phandle->subH.bfType &= 0x7f;
  456.     while(lpStreamInfo->nNumSector > 1) {                // 1.03
  457.         if(!(psector = CdReadSector(hCdrom, NULL))) {
  458.             free(phandle);
  459.             CdReadClose(hCdrom);
  460.             return NULL;
  461.         }
  462.         if(phandle->subH.usChaNo == psector->asubH[0].usChaNo &&
  463.            phandle->subH.bfType == (psector->asubH[0].bfType & 0x7f) &&
  464.            phandle->subH.bfFlags == psector->asubH[0].bfFlags) {
  465.             phandle->apSector[1] = psector;
  466.             break;
  467.         }
  468.         phandle->wStep ++;                    // 1.03
  469.     }
  470.  
  471.     return phandle;
  472. }
  473.  
  474. /******************************************************************************/
  475. /*                                          */
  476. /*    PsrClose() : ストリームデータのクローズ                      */
  477. /*                                          */
  478. /******************************************************************************/
  479.  
  480. CEXPORT BOOL    PsrClose(
  481.     HANDLE        hStream)    // ストリームハンドル
  482. {
  483.     _PTHANDLE    phandle;
  484.  
  485.  
  486.     phandle = hStream;
  487.     if(phandle->hCdrom)    CdReadClose(phandle->hCdrom);
  488.     free(phandle);
  489.     return TRUE;
  490. }
  491.  
  492. /******************************************************************************/
  493. /*                                          */
  494. /*    PsrRead() : ストリームデータの読み取り                      */
  495. /*                                          */
  496. /******************************************************************************/
  497.  
  498. CEXPORT BOOL    PsrRead(
  499.     HANDLE        hStream,    // ストリームハンドル
  500.     LPPSRREADBUFF    lpBuffer)    // 読み取りバッファ
  501. {
  502.     _PTHANDLE    phandle;
  503.     _PTSECTOR    psector;
  504.  
  505.  
  506.     phandle = hStream;
  507.     memset(lpBuffer, 0, sizeof(PSRREADBUFF) - PSR_FRAMEBUFFER);
  508.  
  509.     if(phandle->apSector[0]) {
  510.         psector = phandle->apSector[0];
  511.         phandle->apSector[0] = NULL;
  512.     } else if(phandle->apSector[1]) {
  513.         psector = phandle->apSector[1];
  514.         phandle->apSector[1] = NULL;
  515.     } else {
  516.         psector = NULL;
  517.     }
  518.     if(psector) {
  519.         lpBuffer->nLength = 0x900;
  520.         memcpy(lpBuffer->abData, psector->abAudio, 0x900);
  521.         CdUnlockReadBuffer(phandle->hCdrom, psector);
  522.         return TRUE;
  523.     }
  524.  
  525.     while(1) {
  526.         psector = CdReadSector(phandle->hCdrom, NULL);
  527.         if(!psector)    return FALSE;
  528.  
  529.         if(phandle->subH.usChaNo == psector->asubH[0].usChaNo &&
  530.            phandle->subH.bfType == (psector->asubH[0].bfType & 0x7f) &&
  531.            phandle->subH.bfFlags == psector->asubH[0].bfFlags) {
  532.             lpBuffer->nLength    = 0x900;
  533.             memcpy(lpBuffer->abData, psector->abAudio, 0x900);
  534.         }
  535.         CdUnlockReadBuffer(phandle->hCdrom, psector);
  536.         if(lpBuffer->nLength)    break;
  537.     }
  538.     return TRUE;
  539. }
  540.  
  541. /******************************************************************************/
  542. /*                                          */
  543. /*    PsrSeek() : 読み取り位置の設定                          */
  544. /*                                          */
  545. /******************************************************************************/
  546.  
  547. CEXPORT BOOL    PsrSeek(
  548.     HANDLE        hStream,    // ストリームハンドル
  549.     DWORD        dwPosition)    // 読み取り位置        1/1000秒単位
  550. {
  551.     _PTHANDLE    phandle;
  552.     DWORD        dwSector;
  553.  
  554.  
  555.     phandle = hStream;
  556.     if(phandle->apSector[0]) {
  557.         CdUnlockReadBuffer(phandle->hCdrom, phandle->apSector[0]);
  558.         phandle->apSector[0] = NULL;
  559.     }
  560.     if(phandle->apSector[1]) {
  561.         CdUnlockReadBuffer(phandle->hCdrom, phandle->apSector[1]);
  562.         phandle->apSector[1] = NULL;
  563.     }
  564.  
  565.     dwSector = (phandle->nSamplingRate / 100) * (dwPosition / 10);
  566.     dwSector /= (4032 / (DWORD)phandle->wChannels);
  567.     dwSector *= (DWORD)phandle->wStep;
  568.     dwSector = min(dwSector, phandle->nAllSector);
  569.     if(CdSetReadPointer(phandle->hCdrom, (LONG)dwSector, FILE_BEGIN) == 0xffffffff) {
  570.         return FALSE;
  571.     }
  572.     return TRUE;
  573. }
  574.