WIN32APIとC言語だけでここまでのものが作れるなんてってことで、今回はプログラムの紹介記事です。
なにかとここのプログラムでゲームプログラミングを勉強させていただいています。
WindowsでのめんどくさいVC++でのDLLの作成もしていますので、勉強になるかと思います。
クラスを使わずに構造体で関数ポインタを使っているところがちょっとびっくりしました。
ダウンロード
http://www13.plala.or.jp/kymats/program/program_game.html
のダウンロードのほうをクリックして
NGSE1_3(Programer'sEdition).exe
をダウンロード(最近あまり見ない自己解凍形式です)。
コンパイル
解凍するとこのような感じになっていると思います。
デバッグ用にはファイルが用意されていないので、Releaseのフォルダからファイルをコピーしてくる必要があります(後述)。
Visual Studio 2013での説明です。
ダウンロードしたファイルを解凍して
NovelGameScriptEngine.sln
があるので、クリックするとVisual Studioが立ち上がり、
下のような画面が出てくるので、OKを押してください。
コンバートが始まります。
終わると、なにやらたくさん警告が出てきますが、無視してOKです。
まず、コンパイルをします。
Visual Studio 2013で
ビルド > バッチビルド
すべて選択をしてからでリビルドを押すとコンパイル&リンクが始まります。
エラーが出ると思います。それらはすべて古い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に変えます。
デバッグ版で動かすために必要なファイルをコピー
NGSE1_3(Programer'sEdition)\release
フォルダから必要なファイルをコピーします。
作者様の説明がこのフォルダにあるのですが、
ちゃんと読んでいません
introduceフォルダ tokimekiフォルダ 文書フォルダ command.txt introduce.txt tokimeki.txt ロゴ.bmp setup.ini
をreleaseフォルダからDebugフォルダコピーすればOKでしょう。
setup.iniでおそらくテキストを切り替えるのでしょう。
あとはVisual Studioからデバッグ開始でもなんでもできます。
デバッグ実行画面はこんな感じ。