【C++】【ゲーム開発】裏モードって聞いたらちょっとワクワクする

eye-catch Rockman Reanimated
eye-catch

ゲームを制作する際にデバッグ用の特殊コードを埋め込む事はよくするのだが、デバッグモードに入るトリガーが実は今までソースコードだったという話があって、これをなんとかexe起動する時に操作できないだろうかと探していたが、なんとなく実装できた。。

むしろデバッグモードで実行できる市販のゲームソフトなんて普通ないんですが、そもそも私が作成しているものは市販しない前提だし(´・ω・`)


えっと、その話の中で実はWindows APIの話が出てきます。
よく分からないと思うので、簡単に説明しますが、(実際私も詳しくは知らないので(;´・ω・))

まずWindowsプログラムをC言語とかで作成する際にこんな文を最初に書くはずです。

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) ... (省略  -- x86の場合です

これってあまり意識する必要ないのですが、実はmain関数です。

Consoleアプリケーションの場合だとint main(int argc, char *argv[]) … などとなっているやつですね。
これをGUI、いわゆるWindowsアプリケーションで実行しようとすると上記のようにWinMain関数を書かないといけないのです。
(正確にはリンカーが指定するエントリーポイントの名前です)

話の論点はそこではなくて、今回使用するのはこの引数です。

具体的に言うと、Windowsアプリ(.exe)を起動する時に引数を指定します。

アプリケーション実行時のコマンド

まぁ実際はコンソールからアプリを実行するような人は少数派でしょうから、そんな話よく分からないと思います。
(私も実際しないですし。じゃあなんで説明したんだって話になるんですが…( ^ω^)ふひひ知らね)

上記のように
> [アプリ名] [引数] [引数]…
みたいにしてやればWinMain関数の3番目の仮引数(LPSTR lpCmdLine)に値が渡されます。

このパラメータを読み取ってデバッグモードにするとかなんとか操作をすれば良いのです。

それでまあ、実際にはexeファイル実行する時にもマウスでカチカチってして起動するじゃないですか?
それはどうなの?という事で、

Drag & Dropをすれば、ドラッグ元のファイル名(のフルパス)が引数になります。

私が今回作成しているゲームのデバッグトリガーは”debug”がlpCmdLineに渡された時デバッグモードで起動できるようにしました。

// includes.
#include <string>
#include <regex>
#include <Windows.h>
#include "kernel.hpp"
#include "src/subroutine/kits/stringcontroller/substring_script.hpp"


namespace publish {

    auto systemModeSelect(LPSTR lpCmdLine) {
        auto mode_param = RunMode::GENERAL_MODE;
        if (!lstrcmpA("", lpCmdLine)) return mode_param;

        std::string str = lpCmdLine;
        if ('\"' == str.front() && '\"' == str.back()) {
            str = std::regex_replace(str, std::regex("\""), "");
        }
        str = subr::kits::stringcontroller::strRightTrim(str, 5);
        if (!lstrcmpA(str.c_str(), "debug")) {
            mode_param = RunMode::DEBUG_MODE;
            MessageBoxA(NULL, "Start in debug mode.", "Eris", MB_OK);
        }

        return mode_param;
    }

}  // namespace publish


// The entry point of application.
INT APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ INT nCmdShow) {
    auto mode = publish::systemModeSelect(lpCmdLine);
    /*
     * Note:
     * Normally, there no arguments to execute the system,
     * but by specifying a keyword reserved from the command line when boot-up this,
     * you're able to execute the system in debug mode.
     */
    if (!publish::Systems(mode)) {
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

今回もそのまんまソースコードぶっこみます。すみませんねー😜

実際にどうやって分岐するのかやってみましょう。

コメント

タイトルとURLをコピーしました