読者です 読者をやめる 読者になる 読者になる

Gobble up pudding

プログラミングの記事がメインのブログです。

MENU

WIN32APIだけでノベルゲームエンジン

スポンサードリンク

WIN32APIとC言語だけでここまでのものが作れるなんてってことで、今回はプログラムの紹介記事です。
なにかとここのプログラムでゲームプログラミングを勉強させていただいています。
WindowsでのめんどくさいVC++でのDLLの作成もしていますので、勉強になるかと思います。
クラスを使わずに構造体で関数ポインタを使っているところがちょっとびっくりしました。

ダウンロード

http://www13.plala.or.jp/kymats/program/program_game.html
のダウンロードのほうをクリックして
NGSE1_3(Programer'sEdition).exe
をダウンロード(最近あまり見ない自己解凍形式です)。

コンパイル

解凍するとこのような感じになっていると思います。
f:id:fa11enprince:20140618235318p:plain
デバッグ用にはファイルが用意されていないので、Releaseのフォルダからファイルをコピーしてくる必要があります(後述)。

Visual Studio 2013での説明です。
ダウンロードしたファイルを解凍して
NovelGameScriptEngine.sln
があるので、クリックするとVisual Studioが立ち上がり、
下のような画面が出てくるので、OKを押してください。
f:id:fa11enprince:20140618235450p:plain
コンバートが始まります。
終わると、なにやらたくさん警告が出てきますが、無視してOKです。
まず、コンパイルをします。
Visual Studio 2013で
ビルド > バッチビルド
すべて選択をしてからでリビルドを押すとコンパイル&リンクが始まります。
f:id:fa11enprince:20140618235701p:plain

エラーが出ると思います。それらはすべて古いVisual C++の仕様で
for (DWORD i = 0; i < ... )とか書かれているところです。
古い仕様ではこの局所変数が外部で使えるようになっているダメ仕様なので、
変数宣言が足りないところは補ってやります。

コード修正1

soundプロジェクト smfformat.cpp smfPlay::Close(void)

    //for(k=0;k<m_bufs;k++)
    for(BYTE k=0;k<m_bufs;k++)
    {
        if(m_pMidiHdr[k].lpData)
        {
            free(m_pMidiHdr[k].lpData);
            m_pMidiHdr[k].lpData=NULL;
        }
    }

コード修正2

soundプロジェクト smfformat.cpp SmfFormat::ConvertPhase1(BYTE *pData,DWORD *nSumEvent)

    //for(k=0;k<nTrack;k++)
    for(DWORD k=0;k<nTrack;k++)
    {
        MIDI *pMidi=midiList[k];
        offset+=8;          // チャンクタイプとデータサイズを読み飛ばす
        DWORD sumTime=0;    // 各トラックの絶対時間
        BYTE befSta=0;      // 各トラックの一つ前のイベント
        while(true)
        {

コード修正3

soundプロジェクト smfformat.cpp SmfFormat::ConvertPhase1(BYTE *pData,DWORD *nSumEvent)

    // 一番時間が遅い End of Track を最後のトラックに書き込む
    //for(MIDI *pMidi=midiList[nTrack-1]; pMidi->pNext!=NULL; pMidi=pMidi->pNext);      // トラックの最後を探す
    MIDI *pMidi;
    for(pMidi=midiList[nTrack-1]; pMidi->pNext!=NULL; pMidi=pMidi->pNext);      // トラックの最後を探す
    pMidi->pNext=(MIDI*)malloc(sizeof(MIDI)+2);
    pMidi=pMidi->pNext;
    pMidi->dwSumTime=lastEndTime;
    pMidi->dwEvent[0]=0xFF;
    pMidi->dwEvent[1]=0x2F;
    pMidi->dwEvent[2]=0x00;
    pMidi->pNext=NULL;      // 新しい(トラックの)最後

コード修正4

soundプロジェクト smfformat.cpp SmfFormat::ConvertPhase2(BYTE *pData,MIDI **midiList,DWORD nSumEvent)

    for(DWORD k=0;k<nSumEvent;k++)
    {
        //for(DWORD min=0; min<nTrack && list[min]==NULL; min++);       // 有効な一番時間が早いイベントを探す
        DWORD min;
        for(min=0; min<nTrack && list[min]==NULL; min++);       // 有効な一番時間が早いイベントを探す
        if(min==nTrack) continue;       // 全てのイベントを参照し終わった(k==nSumEvent)

        //for(n=min+1;n<nTrack;n++)
        for(DWORD n=min+1;n<nTrack;n++)
        {
            if(list[n]==NULL) continue;
            if(list[n]->dwSumTime < list[min]->dwSumTime) min=n;
        }

        midiArray[k]=list[min];
        list[min]=list[min]->pNext;     // 選択されたトラックの単方向リストを次に進める
    }

コード修正5

soundプロジェクト smfformat.cpp SmfFormat::Decode(BYTE *variable,DWORD *fixed)

    (*fixed)=0;
    //for(BYTE k=0;;k++)        // 最大4バイト
    BYTE k;
    for(k=0;;k++)       // 最大4バイト
    {
        if(k>=4) return 0;      // Error
        (*fixed)+=(variable[k] & 0x7F);
        if(!(variable[k] & 0x80)) break;
        (*fixed)<<=7;
    }
    return k+1;     // 可変長数値のバイト数

コード修正6

scripterプロジェクト eventlist.cpp DeleteLabelTag(IEventList eventList,DWORD deleteTagIndex)

    // 後ろを詰める
    //for(i=deleteTagIndex;i<eventList->codeCount;i++)
    for(DWORD i=deleteTagIndex;i<eventList->codeCount;i++)
    {
        eventList->codeList[i]=eventList->codeList[i+1];
    }

コード修正7

scripterプロジェクト eventlist.cpp DeleteEventList(IEventList eventList)

    //for(i=0;i<eventList->labelCount;i++) free(eventList->labelList[i]);
    for(DWORD i=0;i<eventList->labelCount;i++) free(eventList->labelList[i]);
    free(eventList->labelList);

もう一度同じ手順でリビルド(ビルド > バッチビルド)すると成功します。

========== すべてリビルド: 16 正常終了、0 失敗、0 スキップ ==========

ソリューションのスタートアッププロジェクトを設定

ソリューションの上で右クリックすると下記のような画面が出てきますので、
シングルスタートアッププロジェクトをmainに変えます。
f:id:fa11enprince:20140619002810p:plain

デバッグ版で動かすために必要なファイルをコピー

NGSE1_3(Programer'sEdition)\release
フォルダから必要なファイルをコピーします。
作者様の説明がこのフォルダにあるのですが、
ちゃんと読んでいません

introduceフォルダ
tokimekiフォルダ
文書フォルダ
command.txt
introduce.txt
tokimeki.txt
ロゴ.bmp
setup.ini

をreleaseフォルダからDebugフォルダコピーすればOKでしょう。
setup.iniでおそらくテキストを切り替えるのでしょう。

あとはVisual Studioからデバッグ開始でもなんでもできます。
デバッグ実行画面はこんな感じ。
f:id:fa11enprince:20140619003300p:plain

作者のホームページ

http://www13.plala.or.jp/kymats/