メインサイトへ戻る

;■■■PCゲーム改造初心者向け練習用プログラム No.1■■■
;正式名称:ののぴょん1号
;製作:うさぴょん
;協力:BlueAshさん 必殺!!猫まんま(はぐはぐ)さん 
;バージョン:1.05


;*************************************************************************************************
;アセンブルに関する基本設定
;*************************************************************************************************

.386                        ;アセンブルコードリストでは「;」以降がコメントとして無視される
.MODEL FLAT,STDCALL         
locals                      ;この5行はTASMでアセンブルする場合に必要
jumps                       
UNICODE=0


;*************************************************************************************************
;データセクション(初期化)
;*************************************************************************************************

.DATA                    
WINTITLE db "PCゲーム解析練習用プログラム No1 (CDチェック編+α) 〜うさぴょん〜",0   ;ダイアログのタイトル 
;WINTITLE db "ののぴょんは今日も元気! C#になんか負けないもん!",0 ;ダイアログのタイトル(予備) 

POINT  db "■■■ゲームの解析にあたり、先ず理解しておいて頂きたいポイント■■■",13,10
       db 13,10 
       db "・アセンブリ言語を用いたプログラミングの基礎",13,10
       db "・レジスタ、オペランド、ニーモニック、ポインタ、変数(初期化・未初期化)、各種命令等",13,10
       db "・アセンブリ言語の命令とWindowsAPIの関数・メッセージとの関連",13,10
       db "・APIの関数呼び出し時のパラメータ設定と返り値の扱い方",13,10
       db "・PEファイルヘッダで設定された各セクションの役割",13,10
       db "・ディスクイメージ上とメモリイメージ上での実行ファイルの違い",13,10
       db "・ファイル名とファイルハンドルの違い、検索ハンドル、ウィンドウハンドル",13,10
       db "・メニュー、ダイアログボックス、サブルーチン、構造体の定義とその仕組み",13,10
       db "・ダイアログボックスとメッセージボックスの違い",13,10
       db "・CDチェックやキー入力判断の動作原理と関連する関数",13,10
       db "・ファイル入出力の基本と関連関数の使い方(ゲーム改造ツール作成の初歩)",13,10
       db 13,10 
       db "<以下は理解しておいた方が望ましいこと>",13,10
       ;db "・ダイアログボックスのコントロールに入力された数字列と文字列の扱い方",13,10
       db "・CD−DAデバイスのオープンとCD再生、MCI関連関数の使い方",0



        ;■■CDチェック関連■■
        first     db 'これからゲームCDの認証を行います',0    ;「,0」は文字列の終わりを示す
        drive     db '%c:\',0                                  ;ドライブパス作成様式
        ask       db ' このCD−ROMドライブでよろしいですか?',0
        notice    db ' ご注意',0
        NoCD      db 'CD−ROMドライブが見つかりません。',13,10  ;文字列を改行させています
                  db '「キャンセル」で終了します。',0
        VolumeName db 'USAPYON',0                              ;ゲームCDのボリュームラベル
        IDfile    db 'usapyon.dat',0                           ;CD認証用ファイル名
        file      db '%s%s',0                                  ;CD認証用ファイルのパス作成様式
        information db ' お知らせ',0
        NoVolume    db 'CDが挿入されていません。',13,10    
                    db '次のCDドライブを探索します。',0
        VolumeWrong   db '別のCDが挿入されています。',13,10 
                      db '次のCDドライブを探索します。',0
        IDwrong   db 'CD認証用ファイルがありません。',13,10 
                  db '次のCDドライブを探索します。',0
        IDthrough db 'CD認証用ファイルがありました。',0
        SizeGood  db 'ゲームCDが認証されました。',13,10
                  db '',13,10
                  db '「OK」でCD再生を停止し、終了します。',0
        SizeWrong db 'このCD認証用ファイルは、',13,10
                  db '正規のものではありません。',13,10
                  db '次のCDドライブを探索します。',0
        ReadOnly  db 'CD認証用ファイルは、',13,10
                  db '読み取り専用属性です',13,10
                  db '次のCDドライブを探索します。',0

        ;■■CDチェックMCI処理関連■■
        DeviceName db 'cdaudio',0
        DeviceErr  db 'ゲームCDが認証されましたが、cdaudioデバイスがオープンできません。',13,10
                   db '他のアプリケーションがデバイスを使用している可能性があります。',13,10
                   db '或いはBGMにMIDIが選択されました。',13,10
                   db '',13,10
                   db 'そのため、CD-DAの代わりに"usapyon.mid"を再生します。',13,10
                   db '',13,10
                   db '「OK」でMIDI再生を停止し、CDチェックを終了します。',0
        WavPlay    db '効果音ファイル("usapyon.wav")のみ再生します。',0
        SetTrack     db 'set cdaudio time format tmsf',0  ;トラックベースの再生を指定
        PlayCDaudio  db 'play cdaudio from 2 to 3',0      ;再生トラックの指定
        CDstatus     db 'status cdaudio media present',0
        MediaErr     db 'ゲームCDは認証されましたが、',13,10
                     db 'ドライブにCDメディアが確認できません',13,10
                     db '',13,10
                     db '     終了します',0
        MediaSafe    db 'true',0
        SetMidi      db 'open usapyon.mid alias usausa',0  ;このファイルのデバイス名を「usausa」に
        ;実際には再生対象ファイル名をwsprintf関数で組み込むことになります。
        SetWAV       db 'open usapyon.wav alias usausa',0  ;WAVファイル再生用ストリングの例
        PlayMidi     db 'play usausa',0
        StopMidi     db 'stop usausa',0
        CloseMidi    db 'close usausa',0
        CloseAll     db 'close all',0
        
        ;■■ダイアログボックスプロシージャ関連■■
        NOTDrive      db 'エデットボックスにドライブパスを入力して下さい',0
        Drive_Unknown db 'ドライブタイプは、不明、リモートドライブ或いはRAMディスクです',0
        Drive_NON     db '指定のドライブは存在しません',0
        Drive_Hard    db '指定ドライブのドライブタイプはハードディスクです',0
        Drive_Fix     db '指定ドライブのドライブタイプはリムーバブルディスクです',0
        Drive_CD      db '指定ドライブのドライブタイプはコンパクトディスク(CD)です',0
        DriveExample  db 'C:\',0         ;ドライブパス入力例
        INTExample    db '99999999',0    ;符号付き整数値入力例
        atoi          db '入力された値は、16進数では %#X となります。',13,10
                      db 'この処理では、入力された文字列(数字)を内部で数値に変換して処理しています。',13,10
                      db 'アルファベットは無視されます。',0
        atoi16        db '入力された値は、10進数では %d となります。',13,10
                      db 'この処理では、入力された文字列(数字)を内部で数値に変換して処理しています。',0
        Menuname      db 'USAMENU',0
        IconName      db 'USA_ICON',0
        ;About         db 'バージョン情報について',0      ;メッセージボックス用
        AboutNotice   db 'PCゲーム改造初心者向け練習用プログラム No.1 Ver1.05',13,10
                      db '正式名称 ののぴょん1号',13,10
                      db '製作 うさぴょん',13,10
                      db '',13,10
                      db '詳細なバージョン情報等は、この実行ファイルのプロパティを参照して下さい。',0
        Dummy         db '',0
        CRCFormat     db 'このファイルのCRC32は%08Xです。ファイルサイズは%uバイトです。',0

        OpenMessage  db 'open cdaudio',0
        TrackMessage db 'play cdaudio from %u notify',0   ;MM_MCINOTIFYメッセージを返させる
        StopCD       db 'stop cdaudio',0
        CloseCD      db 'close cdaudio wait',0
        EjectCD      db 'set cdaudio door open',0
        InsertCD     db 'set cdaudio door closed',0
        CDTrackExample    db '2',0
        
        URL_1        db 'http://gamereverserz.cjb.net/',0
        URL_2        db 'http://scripterz.usaweb.nu/',0
        URL_3        db 'http://msdn.microsoft.com/default.asp',0
        URL_4        db 'http://www.microsoft.com/japan/developer/default.asp',0
        INIPath      db '\Usapyon.usa',0
        DefSection   db 'default',0
        DefKey       db 'TextFileEditor',0
        DefKeyM1     db 'Mediafile1',0
        DefKeyM2     db 'Mediafile2',0
        DefKeyM3     db 'Mediafile3',0
        DefKeyM4     db 'Mediafile4',0
        DefKeyM5     db 'Mediafile5',0
        DefKeyM6     db 'Mediafile6',0
        DefKeyM7     db 'Mediafile7',0
        DefKey3      db 'HexEditor',0
        DefKey4      db 'Calculater',0
        DefKey5      db 'Appli1',0   ;対象多数ならばwsprintf関数を使用
        DefKey6      db 'Appli2',0
        DefKey7      db 'Appli3',0
        DefKey8      db 'Appli4',0
        DefKey9      db 'Appli5',0
        DefKey10     db 'Appli6',0
        DefKey11     db 'Appli7',0

        AVIPlayMessage  db 'play %s ',0          ;ファイルパス指定だと"notify"設定不可
        AVIResumeMessage db 'resume %s',0
        AVIPauseMessage db 'pause %s',0
        AVIStopMessage  db 'stop %s',0
        AVICloseMessage db 'close %s',0
        SndVol          db '%s\SNDVOL32.EXE',0    ;C:\WINDOWSとは限らない
        
        ;■■改造処理関連■■
        Notepad         db '%s\NOTEPAD.EXE',0     ;C:\WINDOWSとは限らない
        SaveDataPos     db 'SaveData',0
        SaveWrong       db 'ファイルハンドル取得処理中にエラーが発生しました。',13,10
                        db '他のアプリケーションが対象ファイルを使用している可能性があります。',0
        MemWrong        db 'メモリブロック確保処理中にエラーが発生しました',0
        SerialWrong    db '連続書き換え型コードで指定された値のバイト数と、同書き換え範囲の',13,10
                       db 'バイト数に不整合がみられます。安全と推定される範囲内で書き替えます。',0
        ReplacePosInfo  db '置換型コードにより、オフセット %#X 以降を書き替えます。',0
        SearchWrong     db '置換型コードで指定したバイナリデータのファイル内探索を完了しました。',0
        SearchWrong2    db '置換型コードで指定したバイナリデータと、書き換え用データの',13,10
                        db 'サイズが異なります。書き替えを実行しますか?',0
        WriteError      db 'ファイルへの書き込みに失敗しました。',0
        WriteError2     db 'ファイルへの書き込みに失敗しました。「キャンセル」で次のコードに移ります。',0                
        CharaZero       db '置換対象或いは書き換え内容が0文字になっています。',13,10
                        db 'コード内に不必要な文字列が挿入されている可能性もあります。',0
        NGCode          db 'コードの様式に誤りがあります。',0
        HexIntFormat    db 'Offset:%#X [%02X %02X %02X %02X %02X %02X %02X %02X   %02X %02X %02X %02X %02X %02X %02X %02X]',0
        HexASCIIFormat  db 'Offset:%#X 「%s」 (値00:文字列終端)',0
        NOkey           db 'NoKey',0
        NOkey2          db '未選択',0
        NOMenuOfSelectGame   db '選択・改造されたゲームが特定できません。',0
        askupdate       db '選択中ゲーム及びエディットボックス内容の再確認を強くお奨めします',0
        CheatInfoUpdate db '現在のエディットボックスの内容で選択中ゲームの「GAME*」セクションを更新します',13,10
                        db '本当に更新してもよろしいですか?',0
        GameCount       db 'GameCount',0
        GameCodeCount   db 'CodeCount',0
        GameNameKey     db 'GameName',0
        GameSiteKey     db 'URL',0
        GameSectionFormat  db 'GAME%u',0
        SelectGameIs       db '現在選択・改造中のゲームは %s です。',0
        CodeNameFormat  db 'Code%u',0
        CheatDone       db '改造処理を終了しました。',13,10
                        db '',13,10
                        db '',0
        BackupName      db '%s.BAK',0
        BackupRewrite   db 'バックアップファイルが既に存在します。上書きしますか?',0
        TargetSection   db 'TargetGame',0
        TargetGameFormat db '改造対象%u',0
        FUIList db '16進−2進ビットパターン:',13,10
                db '00h=0000 01h=0001 02h=0010 03h=0011 04h=0100 05h=0101 06h=0110 07h=0111',13,10
                db '08h=1000 09h=1001 0Ah=1010 0Bh=1011 0Ch=1100 0Dh=1101 0Eh=1110 0Fh=1111',13,10
                db '',13,10
                db '10進−16進(リトルエンディアン):',13,10
               db '99=63h 999=E703h 9999=0F27h 99999=9F8601h 999999=3F420Fh 9999999=7F9698h',13,10
               db '99999999=FFE0F505h 255=FF000000h 65535=FFFF0000h 16777215=FFFFFFFFh ',13,10
               db '-100=9CFFFFFFh -1000=18FCFFFFh -10000=F0D8FFFFh ',13,10
               db '',13,10
               db 'その他',13,10
              db '"Debug"=4465627567h "DEBUG"=4445425547h "Test"=54657374h "TEST"=54455354h',13,10
              db '"警告"=8C788D90h "Error"=4572726F72h ',0

        ;■■その他■■
        Usatut1mutex    db 'UsaTut1x',0
        TrayText        db 'ののぴょん1号 [PCゲーム解析練習用プログラム No1 (CDチェック編)]',0
        TheEnd          db '終了(&E)',0
        ToTopTrack      db '最前面表示をトグル(&T)',0

        ;■■APIの関数呼び出し時の各パラメータを対応する値で設定■■
        ;パラメータ名は、WindowsAPIに準拠しています
                                        
        ;MessageBoxA関数用
        mb_ok          equ 30h            ;「OK」ボタン(0h)+アイコン付き(30h)のメッセージボックス
        mb_retrycancel equ 5              ;「再試行」「キャンセル」ボタンのあるメッセージボックス
        ;hWnd           equ 0             ;親ウィンドウハンドルが不要ならば0です
        mb_yesno       equ 4              ;「はい」「いいえ」のボタンがあるメッセージボックス
        mb_okcancel    equ 1              ;「はい」「キャンセル」のボタンがあるメッセージボックス
        idretry        equ 4              ;「再試行」ボタンを押した場合の返り値
        idno           equ 7              ;「いいえ」ボタンを押した場合の返り値
        idcancel       equ 2              ;「キャンセル」ボタンを押した場合の返り値

        ;GetVolumeInformationA関数用
        dwcVolumeNameSize        equ 100h   ;取得されたボリュームラベルの格納バッファバイト数
        lpVolumeSerialNumber     equ 0      ;ポインタだがボリュームシリアル番号が不要なら0でも可
        lpFileSystemNameBuffer   equ 0      ;ポインタだがファイルシステム名が不要なら0でも可
        nFileSystemNameSize      equ 0      ;ファイルシステム情報関連のパラメータで今回は不要です

        ;CreateFileA関数用
        generic_read equ 80000000h      ;読み取りアクセス
        generic_write equ 40000000h     ;書き込みアクセス
        file_share_read       equ 1     ;複数の読み取りアクセスが実行可能
        lpsecurity_attribute  equ 0     ;ファイルのセキュリティ属性(無効)
        open_existing         equ 3     ;ファイルをオープン
        file_attribute_normal equ 80h   ;ファイル属性(属性なし)
        handle                equ 0     ;ファイル作成時の拡張属性(不要)
        
        ;GetAsyncKeyState関数用
        vk_shift              equ 10h       ;シフトキーの仮想キーコード
        vk_control            equ 11h       ;Ctrlキーの仮想キーコード
        vk_Menu               equ 12h       ;Altキーの仮想キーコード

        ;mciSendCommandA関数用
        wDeviceIDOPEN         equ 0      ;デバイスのオープンには不要なので「wDeviceID」と区別
        MCI_OPEN              equ 803h
        MCI_OPEN_TYPE         equ 2000h
        MCI_NOTIFY            equ 1
        MCI_WAIT              equ 2
        MCI_CLOSE             equ 804h
        MCI_STOP              equ 808h

        ;mciSendStringA関数用
        MM_MCINOTIFY          equ 3B9h
        
        ;ReadFile,WriteFile関数用
        lpOverlapped          equ 0

        ;GlobalAlloc関数用
        GMEM_FIXED            equ 0    ;この指定で戻り値は確保メモリブロック先頭アドレスとなる

        ;GetLastError関数用
        ERROR_ALREADY_EXISTS  equ 0B7h
        ERROR_FILE_EXISTS     equ 50h

        ;GetMenu,GetMenuState,CheckMenuItem,RemoveMenu,EnableMenuItem関数用
        MF_BYPOSITION          equ 400h   ;メニューの識別に項目の相対的位置を使用
        MF_BYCOMMAND           equ 0      ;メニューの識別にIDを使用
        MF_ENABLED             equ 0      
        MF_GRAYED              equ 1
        MF_SEPARATOR           equ 800h
        MFS_CHECKED            equ 8h
        MFS_UNCHECKED          equ 0

        ;ShellExecuteA関数用
        SW_SHOWNORMAL           equ 1
        SW_MAXIMIZE             equ 3

        ;SetWindowPos関数用
        SWP_NOSIZE              equ 1
        SWP_NOMOVE              equ 2
        HWND_TOPMOST            equ -1     ;最前面の設定用
        HWND_TOP                equ 0
        HWND_BOTTOM             equ 1

        TrueSize              equ 270fh ;CD認証用ファイルのファイルサイズは9999バイト

        ;ダイアログプロシージャ用
        NULL                    equ 0
        WM_NULL                 equ 0       ;以下のウィンドウメッセージに注目して下さい
        WM_CREATE               equ 01h
        WM_CLOSE                equ 0010h
        WM_DESTROY              equ 0002h
        WM_SETICON              equ 0080h
        WM_INITDIALOG           equ 0110h
        WM_COMMAND              equ 0111h
        WM_TASKTRAY             equ 0506h
        WM_LBUTTONDOWN          equ 0201h
        WM_RBUTTONDOWN          equ 0204h
        WM_DROPFILES            equ 0233h
        WM_UNDO                 equ 304h
        WM_CLEAR                equ 303h
        WM_CUT                  equ 300h
        WM_COPY                 equ 301h
        WM_PASTE                equ 302h
        WM_SETTEXT              equ 0Ch
        WM_SETFONT              equ 30h
        WM_GETFONT              equ 31h
        WM_CTLCOLORDLG          equ 136h
        WM_CTLCOLORLISTBOX      equ 134h
        WM_CTLCOLOREDIT         equ 133h
        EM_REPLACESEL           equ 0C2h
        EM_LINESCROLLL          equ 0B6h
        EM_SETSEL               equ 0B1h
        LB_GETCURSEL            equ 188h
        LB_SETCURSEL            equ 186h
        LB_ADDSTRING            equ 180h
        LBN_SELCHANGE           equ 1       ;ウィンドウメッセージここまで
        ICON_SMALL              equ 0
        USA_ICON                equ 65h
        DLG_MAIN                equ 67h
        EDIT_TEXT_OUT           equ 03E9h
        EDIT_DRIVE              equ 03EBh
        EDIT_INT                equ 03F2h
        EDIT_CDTRACK            equ 138Bh
        EDIT_NOWSelected        equ 0DAEh
        LIST_GAME               equ 0DB1h
        BTN_CHECK               equ 03EFh
        BTN_EXIT                equ 03F0h
        BTN_GETDTYPE            equ 03ECh
        BTN_AtoI                equ 03F1h
        BTN_PlayTrack           equ 1388h
        BTN_Stop                equ 1389h
        BTN_Eject               equ 138Ah
        BTN_ChInfoUpdate        equ 0DB2h
        BTN_CheatNow            equ 0DB0h
        MenuCD                  equ 07D1h
        MenuTop                 equ 07FDh
        MenuEND                 equ 07D2h
        MenuTEXTPoint           equ 07D3h
        MenuTEXTALL             equ 0804h;Last#
        MenuTEXTALLClear        equ 07E1h
        MenuTEXTClear           equ 07D4h
        MenuTEXTUndo            equ 07E0h
        MenuCut                 equ 07F5h
        MenuCopy                equ 07F6h
        MenuPaste               equ 07F7h
        MenuChangeFont          equ 07F3h
        MenuUndoFont            equ 07F4h
        MenuMemo                equ 07DEh
        MenuHex                 equ 07E2h
        MenuCal                 equ 07E3h
        MenuAppli1              equ 07E6h
        MenuAppli2              equ 07E7h
        MenuAppli3              equ 07E8h
        MenuAppli4              equ 0800h
        MenuAppli5              equ 0801h
        MenuAppli6              equ 0802h
        MenuAppli7              equ 0803h
        MenuChInfo              equ 2710h
        MenuChInfoUpdate        equ 07FEh
        MenuDefINI              equ 07E9h
        MenuGameINI             equ 07DFh
        MenuCheat               equ 4E20h
        MenuCheatSelected       equ 07FAh
        MenuSelectGame          equ 07F8h
        MenuSelectGame2         equ 07F9h
        MenuINIOpen             equ 07F1h
        MenuFUI                 equ 07F2h
        MenuAbout               equ 07D5h
        MenuCDPlay              equ 07D8h
        MenuCDStop              equ 07D9h
        MenuCDEject             equ 07DAh
        MenuCDInsert            equ 07DBh
        MenuMulti1              equ 7531h
        MenuMulti2              equ 7532h
        MenuMulti3              equ 7533h
        MenuMulti4              equ 7534h
        MenuMulti5              equ 7535h
        MenuMulti6              equ 7536h
        MenuMulti7              equ 7537h
        MenuAVI2                equ 07E4h
        MenuAVI3                equ 07E5h
        MenuAVI4                equ 07FBh
        MenuVolume              equ 07F0h
        MenuTrackEnd            equ 9C42h
        MenuTrackTop            equ 9C41h
        CheckMidi               equ 0FA0h
        CheckWav                equ 0FA2h
        CDCheckSkip             equ 0FA1h
        CheckBackUp             equ 0DACh
        CheckNoWarning          equ 0DADh
        CheckUseHexEditor       equ 0DB3h
        Radio10                 equ 0BB9h
        Radio16                 equ 0BBAh
        SiteGame                equ 07FCh
        Site1                   equ 07D6h
        Site2                   equ 07D7h
        Site3                   equ 07DCh
        Site4                   equ 07DDh
        INIBufferSize           equ 7FFFh
        TargetBufferSize        equ 40h
        StartAppliBufSize       equ 104h
        WinPathCount            equ 105h

;*************************************************************************************************
;データセクション(未初期化)
;*************************************************************************************************
                                            ;未初期化変数の宣言
       ;FindFirstFileA関数用
       ;WIN32_FIND_DATA STRUC               ;WIN32_FIND_DATA構造体の定義(今回は不要)
                                            ;連続した一群のデータとなる点に注意
         dwFileAttributes    dd ?           ;ファイル属性
         ftCreationTime      dd ?
         ftLastAccessTime    dd ?
         ftLastWriteTime     dd ?
         nFileSizeHigh       dd ?
         nFileSizeLow        dd ?           ;ファイルのバイトサイズの下位ワード
         dwReserved0         dd ?
         dwReserved1         dd ?
         cFileName           db 104h DUP(?) ;「db 104h DUP(?)」でこの変数に260バイト確保しています
         cAlternateFileName  db 20h DUP(?)  ;本来の14hだとバイト確保に不具合が起きます
       ;WIN32_FIND_DATA ENDS

       ;mciSendCommandA関数用
       ;MCI_OPEN_PARMS STRUC                ;MCI_OPEN_PARMS構造体の定義(定義の必要が無い)
         dwCallback          dd ?           ;実際にはNULLになる
         wDeviceID           dd ?           ;デバイスID
         lpstrDeviceType     dd ?           ;ここにデバイス名(cdaudio)が入る
         lpstrElementName    dd ?
         lpstrAlias          dd ?
       ;MCI_OPEN_PARMS ENDS

       ;Shell_NotifyIconA関数用
       ;NOTIFYICONDATA STRUC
         iconDatacbSize      dd ?
         iconDatahWnd        dd ?
         iconDatauID         dd ?
         iconDatauFlags      dd ?
         iconDatauCallbackMessage   dd ?
         iconDatahIcon       dd ?
         iconDataszTip       db 64h DUP(?) 
       ;NOTIFYICONDATA ENDS

       ;GetCursorPos関数用
       ;POINT STRUC
         CursorX             dd ?
         CursorY             dd ?
       ;POINT ENDS

                                         ;以下の変数のサイズはddでも実際の処理上問題ありません
        DrivePath                dd ?    ;CDドライブのパス
        FindFileHandle           dd ?    ;CD認証用ファイルの検索ハンドル
        FileHandle               dd ?    ;CD認証用ファイルのファイルハンドル
        
        ;GetVolumeInformationA関数用
        lpMaximumComponentLength dd ?    ;ファイルシステム情報関連のパラメータで今回は不要です
                                         ;ポインタなので値0ではなく未初期化変数にしています
                                         ;この変数を値0に定義するとPass32でエラーがでます
        lpFileSystemFlags        dd ?    ;同上
        lpVolumeNameBuffer       db 104h DUP(?) ;取得されたボリュームラベルが格納されるポインタ
        
        ;CreateFileA関数用
        FilePath                 db 104h DUP(?) ;同ファイルパス
        
        ;mciSendStringA関数用                                 
        MediaPresent             db 20h DUP(?)  ;後で再定義される

        ;ReadFile,WriteFile関数用
        lpNumberOfBytesRead    dd ?             ;実際には使用しない
        lpNumberOfBytesWritten dd ?             ;同上

        ;GetFileTime,SetFileTime関数用(FileTime構造体を連続使用)
         LowDateTime1          dd ?
         HighDatetime1         dd ?
         LowDateTime2          dd ?
         HighDatetime2         dd ?
         LowDateTime3          dd ?
         HighDatetime3         dd ?

        ;ダイアログボックスプロシージャ用 他
        hEdit           dd ?
        hicon           dd ?
        hinst_          dd ?
        hDC             dd ?
        hDrop           dd ?
        hBrushDLG       dd ?
        hBrush          dd ?
        hBrush2         dd ?
        hHeap           dd ?
        MenuHandle      dd ?
        SubMenuHandle   dd ?
        SubMenuHandle1  dd ?
        SubMenuHandle2  dd ?
        SUbCheckBuf     db 120h DUP(?)
        SUbCheckBuf2    db 20h DUP(?)
        SUbCheckBuf3    db 90h DUP(?)
        MCIMessBuf      db 20h DUP(?)
        DummyStrage     db 150h DUP(?) 
        INIBuffer       dd ?           ;INIBufferSizeで再定義される 
        GameSectionNum  dd ?
        GameNum         dd ?
        GameNumID       dd ?
        GameTargetNum   db 16h DUP(?)
        SelectGameBuf   db 70h DUP(?)
        DirBuffer       db 104h DUP(?) ;INIファイルパス格納先
        DirBuffer2      db 104h DUP(?)
        KeyReturn       dd ?
        CodeCountBuf    dd ?
        ;CodeCountBuf2   dd ?            ;予備
        CodeNum         dd ?
        CodeName        db 10h DUP(?)
        CodeStart       db 16h DUP(?)
        CodeEnd         db 16h DUP(?)
        CodeFill        db 200h DUP(?)
        CodeFillBuf     dd ?
        CodeCountBuf2   dd ?
        ReplaceData     db 200h DUP(?)
        ReplaceData2    db 100h DUP(?)
        ReplaceFill     db 200h DUP(?)
        ReplaceFill2    db 100h DUP(?)    ;書き替え時に必要なデータ
        ReplacePos      dd ?
        ReplacePosString db 70h DUP(?)
        CharaFlag       dd ?              ;同上
        CharaFlag2      dd ?
        SerialMacro     dd ?              ;同上
        CodeStart2      db 8h DUP(?)      ;同上
        CodeEnd2        db 8h DUP(?)      ;同上
        CodeFill2       db 100h DUP(?)    ;同上
        PathBuffer      db 104h DUP(?)    ;同上
        PathBuffer2     db 104h DUP(?)    ;同上
        FileSize        dd ?
        MemPtr          dd ?
        TargetBuffer    db 40h DUP(?)     ;TargetBufferSizeで再定義される
        StartAppliBuf   db 104h DUP(?)    ;StartAppliBufSizeで再定義される
        CodeErrorMess   dd ?
        FontHandle      dd ?
        WinPath         db 105h DUP(?)    ;WinPathCountで再定義される
        WinAppliPath    db 105h DUP(?) 
        DragFileBuf     db 104h DUP(?) 
        XORBuf          dd ?
        GameCountBuf3   dd ?
        CRC32TextBuf    db 30h DUP(?) 
        CRC32Table      db 400h DUP(?)
        HexViewBuf      db 60h DUP(?) 
        HexViewBuf2     db 60h DUP(?) 
        HexViewStringBuf db 12h DUP(?)
        
;*************************************************************************************************
;コードセクション(関数インポートセクション部)
;*************************************************************************************************

.CODE
        extrn ExitProcess      : proc    ;「proc」はサブルーチンを定義する擬似命令

        extrn MessageBoxA      : proc    ;メッセージボックスの作成

        extrn CreateFileA      : proc    ;今回はファイルをオープンしています

        extrn GetDriveTypeA    : proc    ;ドライブの種類を取得

        extrn GetVolumeInformationA    : proc   ;ボリュームラベルの取得はこの関数以外でも可能です

        extrn FindFirstFileA   : proc  ;指定の検索ファイル名と名前が一致する最初のファイルを検索

        extrn FindClose        : proc    ;検索ハンドルを閉じる

        extrn lstrcmpA         : proc    ;文字列を比較します

        extrn CloseHandle      : proc    ;オープンしたファイルを閉じる

        extrn GetFileSize      : proc

        extrn GetAsyncKeyState : proc    ;特定のキーが押されたか調べる

        extrn MessageBeep      : proc

        extrn mciSendCommandA  : proc    ;特定のMCIデバイスにコマンドを送る

        extrn mciSendStringA   : proc    ;MCIデバイスにコマンドストリングを送る

        extrn _wsprintfA       : proc    ;TASMではこの関数名の前に「_」が必要になる
                                         ;指定のフォーマット様式で文字列をフォーマットして出力

        extrn GetModuleHandleA  : proc   ;特定のモジュールのハンドルを得る

        extrn WritePrivateProfileStringA : proc  ;INIファイルの指定セクションの特定キーに
                                                 ;文字列値を書き込み

        extrn DragAcceptFiles   : proc   ;ドラッグ・アンド・ドロップの許可

        extrn DragQueryFile     : proc   ;ドラッグ・アンド・ドロップされたファイルの情報を取得

        extrn DragFinish        : proc   ;同ファイル名転送用のメモリを開放

        extrn LoadIconA         : proc   ;リソースからアイコンをロード

        extrn DialogBoxParamA   : proc   ;ダイアログ作成用関数

        extrn EndDialog         : proc   ;モーダルダイアログボックスを破棄

        extrn SetWindowTextA    : proc   ;ウィンドウタイトルを設定

        extrn SetDlgItemTextA   : proc   ;コントロールのタイトルかテキストを設定

        extrn SendMessageA      : proc   ;メッセージを別ウィンドウに送って応答を待つ

        extrn IsDlgButtonChecked : proc  ;チェックボックスの選択状態を取得 

        extrn GetDlgItemTextA    : proc  ;ダイアログボックス内コントロール関連のタイトル
                                         ;またはテキストを取得

        extrn LoadMenuA          : proc  ;リソースで定義されたメニューのハンドルを取得

        extrn InsertMenuA        : proc  ;指定メニューの任意の位置にメニュー項目を追加

        extrn SetMenu            : proc  ;メニューをウィンドウに接続

        extrn GetMenu            : proc  ;ウィンドウハンドルからメニューハンドルを取得

        extrn GetMenuState       : proc  ;ポップアップメニュー内メニュー項目の状態等を取得

        extrn CheckMenuItem      : proc  ;メニュー項目にチェックを付ける(外す)
        
        extrn GetDlgItemInt      : proc  ;ダイアログボックス内のコントロールから10進数列を
                                         ;取得し整数値に変換

        extrn CheckRadioButton   : proc  ;ラジオボタングループの選択項目変更

        extrn Sleep              : proc  ;プロセスを指定したミリ秒数だけ停止

        extrn ShellExecuteA      : proc  ;指定したファイル等へ、指定した操作を実行する

        extrn GetPrivateProfileStringA   : proc  ;プライベートINIファイルの特定キーの文字列を取得

        extrn GetCurrentDirectoryA       : proc  ;プロセスのカレントフォルダを取得

        extrn lstrcatA                   : proc  ;文字列連結

        extrn lstrcpyA                   : proc 

        extrn GetPrivateProfileSectionA  : proc  ;プライベートINIファイルの特定セクションの
                                                 ;総てのキーと値を取得

        extrn GetPrivateProfileIntA      : proc  ;プライベートINIファイルの特定キーの整数値を取得

        extrn GetDlgItem                 : proc  ;コントロールIDからダイアログボックスコントロール
                                                 ;のウィンドウハンドルを取得

        extrn CheckDlgButton             : proc  ;ボタンコントロールのチェックを付加または削除


        extrn lstrlenA       : proc  ;文字列の長さを取得

        extrn CreateMutexA   : proc  ;プロセスの同期を取るためのミューテックスオブジェクトを作成

        extrn GetLastError   : proc  ;スレッドのローカル格納領域に設定された直前のエラーを取得
                                     
        extrn GlobalAlloc    : proc ;ヒープからメモリブロックを確保する

        extrn GlobalFree     : proc ;メモリブロックを開放する

        extrn SetFilePointer : proc ;オープンファイルのファイルポインタを移動する

        extrn ReadFile       : proc ;ファイルからデータを読みこむ

        extrn WriteFile      : proc ;データをファイルを書きこむ

        extrn SetFileAttributesA : proc  ;ファイルの属性を設定

        extrn CopyFileA      : proc 

        extrn ModifyMenuA    : proc ;メニュー項目のプロパティを変更する

        extrn SendDlgItemMessageA   : proc  ;ダイアログボックスコントロールへメッセージを送る

        extrn GetWindowsDirectoryA  : proc  ;ウィンドウフォルダのパスを取得

        extrn Shell_NotifyIconA      : proc  ;タスクトレイにアイコンを追加

        extrn TrackPopupMenu  : proc        ;画面の任意の位置にサブメニューを表示

        extrn GetSubMenu      : proc        ;ポップアップメニューのハンドルを取得

        extrn PostMessageA    : proc        ;メッセージキューにメッセージを入れて待たずに復帰

        extrn GetCursorPos    : proc

        extrn DestroyMenu     : proc        ;メモリからメニューを削除

        extrn AppendMenuA     : proc        ;メニューの最後に新しい項目を追加

        extrn CreatePopupMenu : proc        ;空のポップアップメニューを作成

        extrn GetSystemMenu   : proc        ;システムメニューのハンドルを取得

        extrn RemoveMenu      : proc        ;メニューからメニュー項目を削除

        extrn SetForegroundWindow : proc ;ウィンドウをフォアグラウンドに移行し入力フォーカスを得る

        extrn GetShortPathNameA : proc   ;長いパス名を短いパス名に変換

        extrn CreateSolidBrush   : proc  ;指定色のソリッド論理ブラシを作成

        extrn DeleteObject       : proc  ;作成した論理GDIオブジェクトを削除

        extrn GetFileTime        : proc   ;ファイルの作成日時・最終更新日時等を取得

        extrn SetFileTime        : proc   ;ファイルの作成日時・最終更新日時等を設定

        extrn SetWindowPos       : proc   ;ウィンドウ(子、ポップアップ、トップレベル)の
                                          ;サイズ、位置及び順序を変更

        extrn GetProcessHeap     : proc   ;プロセスのデフォルトヒープのハンドルを得る

        extrn HeapAlloc          : proc   ;ヒープからメモリブロックを確保する

        extrn HeapFree           : proc   ;ヒープからメモリブロックを開放する

        extrn WritePrivateProfileSectionA  : proc  ;プライベートINIファイルの特定のセクションの
                                                   ;総てのキーと値を書き換え

        extrn EnableWindow       : proc    ;ウィンドウを有効または無効にする

        extrn EnableMenuItem     : proc    ;メニュー項目を有効または無効(淡色表示)にする

        ;extrn IsDebuggerPresent  : proc   ;Win98で実装された関数

;*************************************************************************************************
;コードセクション(コード本体)
;*************************************************************************************************

Start:  
        push    NULL               ;NULL設定にすればハンドルが戻り値
        call    GetModuleHandleA    
        test    eax, eax
        jne     GoodModule

NotStart:
        push    0
        call    ExitProcess

GoodModule:
        mov     hinst_, eax         ;インスタンスハンドルをストア
        push    offset Usatut1mutex ;二重起動を回避
        push    1                   ;TRUE
        push    NULL
        call    CreateMutexA
        call    GetLastError
        cmp     eax, ERROR_ALREADY_EXISTS
        je      NotStart
                                                            ;改造対策例(注:デバッガで対処可能)
        ;mov     eax, offset IsDebuggerPresent + 1          ;関数呼び出し偽装(この関数はWin95不可)
        ;dec     eax
        ;call    eax                                        ;対処法はDisTamper PROC参照
        ;test    eax,eax                                    ;デバッガから起動されている
        ;jnz     NotStart
        mov     esi,offset DummyStrage                      ;他の関数で使用する変数を流用
        mov     dword ptr [esi], 5C2E5C5Ch                  ;.dataセクション文字列検索不可
        mov     dword ptr [esi+4],45434953h                 ;"\\.\SICE"(VxD,パス解析オフ)
        call    DisTamper                                   ;解析ツール検出用サブルーチン
        ;dec    eax
        ;je     NotStart                                    ;終了処理へ向かわせる例
        mov     dword ptr [esi+4],53584244h                 ;"\\.\DBXSTAND"
        mov     dword ptr [esi+8],444E4154h                 ;BlueAshさんのCDチェックに関する
        call    DisTamper                                   ;チュートリアルを参考にしています
        ;dec    eax
        ;je     NotStart
        mov     dword ptr [esi+4],54535845h                 ;"\\.\EXSTAND"
        mov     dword ptr [esi+8],00444E41h                 ;同上
        call    DisTamper
        ;dec    eax
        ;je     NotStart
        and     dword ptr [esi], 0
        and     dword ptr [esi+4],0
        and     dword ptr [esi+8],0
        ;mov     dword ptr [hBrushDLG],0                    ;不要。GoodModule2参照
        jmp     GoodModule2

DisTamper PROC                                             ;普通はルーチン呼び出し箇所と離します
        mov     eax,offset CreateFileA + 1234h             ;関数呼び出しを偽装(逆アセンブラ対策)
        mov     hBrushDLG, eax                             ;他の関数で使用する変数を流用
        xor     eax,eax
        push    eax;handle
        push    file_attribute_normal
        push    open_existing
        push    eax;lpsecurity_attribute
        inc     eax
        push    eax;file_share_read
        push    generic_read + generic_write
        push    esi
        sub     dword ptr [hBrushDLG],1234h
        Call    dword ptr [hBrushDLG]                       ;OllyDbgならインポートセクション内の
                                                            ;関数対応アドレスにBPM(R)設定で、
                                                            ;本家なら「bpx createfilea」でブレーク
        inc     eax                                         ;0FFFFFFFFh:起動されていない
        je      AllClear                                    ;通常処理へ
        dec     eax                                         ;「cmp  eax,0FFFFFFFFh」は使用しない
        push    eax                                         ;解析の端緒になりかねないので、故意に
        call    CloseHandle                                 ;クローズしないケースもあります
        push    mb_ok
        call    MessageBeep                                 ;警告音を鳴らします
        mov     eax, 1                                      ;解析ツール検出フラグON

AllClear:
        ret

DisTamper ENDP

        
GoodModule2:
        push    0C0C0C0h
        call    CreateSolidBrush
        mov     hBrushDLG, eax
        push    0F5FFF5h
        call    CreateSolidBrush
        mov     hBrush, eax
        push    0FFFFF4h
        call    CreateSolidBrush
        mov     hBrush2, eax

        push    offset Menuname
        push    hinst_
        call    LoadMenuA
        mov     dword ptr [offset MenuHandle],eax
        
      push    offset DirBuffer          ;■■■以下でゲーム改造関連メニュー作成・追加■■■
      push    104h                      ;上バッファのサイズ
      call    GetCurrentDirectoryA
      push    104h                      ;ここではパス名のなので104hに再定義
      push    offset DirBuffer
      push    offset DirBuffer
      call    GetShortPathNameA
      push    offset INIPath
      push    offset DirBuffer
      call    lstrcatA                  ;INIファイル(usapyon.usa)のパスを作成しておく
      push    offset DirBuffer 
      push    0
      push    offset GameCount
      push    offset TargetSection
      call    GetPrivateProfileIntA
      mov     dword ptr [GameNum], eax
      mov     ebx, 0
      mov     dword ptr [GameNumID], MenuChInfo

AddMenu:
      inc     ebx
      push    ebx
      push    offset TargetGameFormat
      push    offset GameTargetNum
      call    _wsprintfA
      add     esp,0Ch
      push    offset GameTargetNum
      push    dword ptr [GameNumID]          ;新しく作成するメニューの識別子
      push    0
      push    2098                           ;MenuID=2098の上に新メニューを作成
      push    MenuHandle
      call    InsertMenuA
      push    offset GameTargetNum
      add     dword ptr [GameNumID],10000
      push    dword ptr [GameNumID]          ;新しく作成するメニューの識別子
      push    0
      push    2097                           ;MenuID=2097の上に新メニューを作成
      push    MenuHandle
      call    InsertMenuA
      sub     dword ptr [GameNumID],10000
      mov     edi, offset GameTargetNum    ;「改造対象#」で設定したゲーム名をメニュー項目名に設定
      mov     esi, dword ptr [GameNumID]
      call    GAMEMenu
      add     dword ptr [GameNumID],1
      cmp     ebx,dword ptr [GameNum]
      jb      AddMenu                        ;GameCount=Maxまでループ 
      call    GetProcessHeap                    ;INIBuffer用メモリブロック確保
      mov     hHeap, eax
      push    7FFFh
      push    8h
      push    hHeap
      call    HeapAlloc
      mov     INIBuffer, eax
        push    0                   ;WM_INITDIALOG処理関連パラメータだが今回は不要
        push    offset DlgProcedure ;ダイアログボックスプロシージャを指定
        push    0                   ;親ウィンドウのハンドルは不要
        push    DLG_MAIN            ;ダイアログを指定
        push    hinst_              ;インスタンスハンドルを指定
        call    DialogBoxParamA
        push    0
        call    ExitProcess

;*************************************************************************************************
;メインダイアログの定義
;*************************************************************************************************

PUBLIC DlgProcedure           ;■■■ダイアログボックスプロシージャ設定■■■
DlgProcedure    PROC STDCALL, hwnd_:DWORD, wmsg:DWORD, wparam_:DWORD, lparam_:DWORD
                USES ebx, edi, esi
         
        xor     eax, eax
        mov     ax, word ptr [wmsg]   ;■ウィンドウメッセージ判定■
        cmp     ax, WM_DESTROY        ;ウィンドウメッセージ
        je      WMdestroy
        cmp     ax, WM_CLOSE          ;ウィンドウメッセージ
        je      WMdestroy
        cmp     ax, WM_COMMAND        ;ウィンドウメッセージ
        je      WMcommand
        cmp     ax, WM_INITDIALOG     ;ウィンドウメッセージ
        je      InitDlg
        cmp     ax, WM_DROPFILES      ;ウィンドウメッセージ
        je      WMdropfiles
        cmp     ax, MM_MCINOTIFY     ;マルチメディアメッセージ
        je      CD_Stop              ;「Stop」ボタン押下ではなくCDトラック再生終了を検出するため
        cmp     ax, WM_TASKTRAY        ;ウィンドウメッセージ
        je      WMTasktray
        cmp     ax, WM_CTLCOLORDLG     ;ウィンドウメッセージ
        je      WMCtlcolordlg
        cmp     ax, WM_CTLCOLORLISTBOX ;ウィンドウメッセージ
        je      WMCtlcolorlistbox
        cmp     ax, WM_CTLCOLOREDIT    ;ウィンドウメッセージ
        je      WMCtlcoloredit
        xor     eax, eax
        RET

WMCtlcolordlg:
        mov     eax, hBrushDLG
        mov     dword ptr [wparam_], eax
        ret

WMCtlcolorlistbox:
        mov     eax, hBrush
        mov     dword ptr [wparam_], eax
        ret

WMCtlcoloredit:
        mov     eax, hBrush2
        mov     dword ptr [wparam_], eax
        ret

WMTasktray:                         ;■■■システムトレイ設定■■■
        push    offset CursorX
        call    GetCursorPos
        mov     eax, dword ptr [lparam_] 
        cmp     eax, WM_LBUTTONDOWN ;左クリック判定
        jnz     WMTasktray2
        push    5
        push    MenuHandle
        call    GetSubMenu
        mov     SubMenuHandle, eax
        push    hwnd_
        call    SetForegroundWindow
        push    0
        push    hwnd_
        push    0
        push    CursorY              ;以下でメニュー位置と様式を指定
        push    CursorX
        push    28h                  ;TPM_LEFTBUTTON + TPM_RIGHTALIGN + TPM_BOTTOMALIGN
        push    SubMenuHandle
        call    TrackPopupMenu       ;システムトレイ上にポップアップメニュー表示
                                     ;本来のメニューを接続しているので破棄できない
                                     ;ただし、メモリリークは起きない
        push    offset iconDatacbSize
        push    3                    ;NIM_SETFOCUS(要IE5だが、なくてもさして問題はない)
        call    Shell_NotifyIconA     ;タスクトレイにフォーカスを戻す
        push    0
        push    0
        push    WM_NULL
        push    hwnd_
        call    PostMessageA
        jmp     WMTasktray3

WMTasktray2:
        cmp     eax, WM_RBUTTONDOWN ;右クリック判定
        jnz     WMTasktray3
        call    CreatePopupMenu
        mov     SubMenuHandle1, eax
        push    offset ToTopTrack
        push    MenuTrackTop
        push    0
        push    SubMenuHandle1
        call    AppendMenuA
        push    offset Dummy
        push    2099
        push    MF_SEPARATOR
        push    SubMenuHandle1
        call    AppendMenuA
        push    offset TheEnd
        push    MenuTrackEnd
        push    0
        push    SubMenuHandle1
        call    AppendMenuA
        push    hwnd_
        call    SetForegroundWindow
        push    0
        push    hwnd_
        push    0
        push    CursorY              ;以下でメニュー位置と様式を指定
        push    CursorX
        push    2Ah                  ;TPM_RIGHTBUTTON + TPM_RIGHTALIGN + TPM_BOTTOMALIGN
        push    SubMenuHandle1
        call    TrackPopupMenu       ;システムトレイ上にポップアップメニュー表示
        push    offset iconDatacbSize
        push    3                    ;NIM_SETFOCUS(要IE5)
        call    Shell_NotifyIconA     ;タスクトレイにフォーカスを戻す
        push    SubMenuHandle1
        call    DestroyMenu          ;独自作成メニューなので破棄しないとメモリを占有したままに
        push    0
        push    0
        push    WM_NULL
        push    hwnd_
        call    PostMessageA

WMTasktray3:
        ret

WMdestroy:                             ;終了処理
        call    CD_END                 ;必ずCD再生を停止し、デバイスをクローズする
        push    0
        push    0
        push    0
        push    offset CloseAll
        call    mciSendStringA         ;必ずオープンした全マルチメディアのデバイスをクローズする
        push    offset iconDatacbSize
        push    2                      ;NIM_DELETE
        call    Shell_NotifyIconA      ;タスクトレイのアイコンを破棄
        push    hBrush
        call    DeleteObject
        push    hBrush2
        call    DeleteObject
        push    hBrushDLG
        call    DeleteObject
        push    INIBuffer
        push    40h
        push    hHeap
        call    HeapFree
        push    0
        push    hwnd_
        call    EndDialog
        push    0
        call    ExitProcess

WMcommand:                                ;■■■ダイアログの通常処理■■■
        mov     eax, dword ptr [wparam_]  ;■ダイアログ上の処理判定■
        cmp     ax, LIST_GAME
        je      ListSelect
        cmp     eax, BTN_CHECK            ;「CDチェック」ボタンが押されたか判定
        je      CheckMain
        cmp     eax, BTN_GETDTYPE
        je      CheckSub
        cmp     eax, BTN_EXIT
        je      WMdestroy
        cmp     eax, BTN_AtoI
        je      AtoIConv
        cmp     eax, BTN_PlayTrack
        je      CD_Play
        cmp     eax, BTN_Stop
        je      CD_Stop
        cmp     eax, BTN_Eject
        je      CD_Eject
        cmp     eax, BTN_ChInfoUpdate
        je      GameSectionUpdate
        cmp     eax, BTN_CheatNow
        je      GameCheatFromBTN

        cmp     eax, MenuCD               ;メニュー選択
        je      CheckMain
        cmp     eax, MenuTop
        je      FixTopWindow
        cmp     eax, MenuTrackTop
        je      FixTopWindow
        cmp     eax, MenuTrackEnd
        je      WMdestroy
        cmp     eax, MenuEND
        je      WMdestroy
        cmp     eax, MenuAbout
        je      AboutBox
        cmp     eax, MenuTEXTPoint
        je      TEXTpoint2
        cmp     eax, MenuTEXTClear
        je      EDIT_TEXT_OUT_Clear
        cmp     eax, MenuTEXTALL
        je      EDIT_TEXT_OUT_ALL
        cmp     eax, MenuTEXTALLClear
        je      EDIT_TEXT_OUT_ALLClear
        cmp     eax, MenuTEXTUndo
        je      EDIT_TEXT_OUT_UNDO
        cmp     eax, MenuCut
        je      EDIT_TEXT_OUT_Cut
        cmp     eax, MenuCopy
        je      EDIT_TEXT_OUT_Copy
        cmp     eax, MenuPaste
        je      EDIT_TEXT_OUT_Paste
        cmp     eax, MenuChangeFont
        je      ChangeFont
        cmp     eax, MenuUndoFont
        je      UndoFont
        cmp     eax, MenuCDPlay
        je      CD_Play
        cmp     eax, MenuCDStop
        je      CD_Stop
        cmp     eax, MenuCDEject
        je      CD_Eject
        cmp     eax, MenuCDInsert
        je      CD_Insert
        cmp     eax, MenuGameINI
        je      INIindicateGame
        cmp     eax, MenuFUI
        je      FUI
        cmp     eax, MenuSelectGame
        je      NowSelectGame
        cmp     eax, MenuSelectGame2
        je      NowSelectGame
        cmp     eax, MenuChInfoUpdate
        je      GameSectionUpdate
        cmp     eax, MenuCheatSelected
        je      CheatSelectedGame
        cmp     eax, MenuCheat
        jae     GameCheatPre
        jmp     WParamContinue

GameCheatPre:
        cmp     eax, MenuCheat+100          ;とりあえず100ゲームまで対応
        ja      WParamContinue
        jmp     GameCheat

WParamContinue:
        cmp     eax, MenuChInfo
        jae     INIindicatePre
        jmp     WParamContinue2

INIindicatePre:
        cmp     eax, MenuChInfo+100
        ja      WParamContinue2
        jmp     INIindicate

WParamContinue2:
        cmp     eax, MenuINIOpen
        je      INIOpen
        cmp     eax, Site1
        je      URL_DT
        cmp     eax, Site2
        je      URL_DT2
        cmp     eax, Site3
        je      URL_MSDN
        cmp     eax, Site4
        je      URL_MSDN2
        cmp     eax, SiteGame
        je      URL_GAME
        cmp     eax, MenuMemo
        je      MemoStart
        cmp     eax, MenuDefINI
        je      INIindicateDef
        cmp     eax, MenuMulti1
        je      AVIStart1
        cmp     eax, MenuMulti2
        je      AVIStart2
        cmp     eax, MenuMulti3
        je      AVIStart3
        cmp     eax, MenuMulti4
        je      AVIStart4
        cmp     eax, MenuMulti5
        je      AVIStart5
        cmp     eax, MenuMulti6
        je      AVIStart6
        cmp     eax, MenuMulti7
        je      AVIStart7
        cmp     eax, MenuAVI2
        je      AVIPause
        cmp     eax, MenuAVI3
        je      AVIStop
        cmp     eax, MenuAVI4
        je      AVIResume
        cmp     eax, MenuVolume
        je      SndVol32
        cmp     eax, MenuHex
        je      HexStart
        cmp     eax, MenuCal
        je      CalStart
        cmp     eax, MenuAppli1
        je      Appli1Start
        cmp     eax, MenuAppli2
        je      Appli2Start
        cmp     eax, MenuAppli3
        je      Appli3Start
        cmp     eax, MenuAppli4
        je      Appli4Start
        cmp     eax, MenuAppli5
        je      Appli5Start
        cmp     eax, MenuAppli6
        je      Appli6Start
        cmp     eax, MenuAppli7
        je      Appli7Start
        RET

WMdropfiles:                       ;■■■ドラッグ・アンド・ドロップされたファイルの処理■■■
        mov     ebx, dword ptr [wparam_]
        mov     hDrop,ebx
        push    104h
        push    offset DragFileBuf
        push    0                  ;一度に1つのファイルのみ受け付けるように制限(安全策)
        push    hDrop
        call    DragQueryFile
        mov     edi, offset GetAsyncKeyState
        Push    vk_control         ;Ctrlキー
        Call    edi                ;キーが押されたかチェックしてEAXレジスタに値を返す
        cmp     ah,80h             ;キーが現在押されていればah=80h
        jz      WMdropfiles2       ;押されていれば指定したテキストファイルエディタで開く
        Push    vk_Menu            ;Altキー
        Call    edi
        cmp     ah,80h
        jz      WMdropfiles3       ;押されていれば指定したヘキサエディタで開く
        Push    41h                ;Aキー
        Call    edi
        cmp     ah,80h
        jz      WMdropfiles4       ;押されていれば登録したアプリケーション1で開く
        Push    5Ah                ;Zキー
        Call    edi
        cmp     ah,80h
        jz      WMdropfiles5       ;押されていれば登録したアプリケーション2で開く
        Push    58h                ;Xキー
        Call    edi
        cmp     ah,80h
        jz      WMdropfiles6       ;押されていれば登録したアプリケーション3で開く
        Push    53h                ;Sキー 選択中ゲームのセーブデータのパスを変更
        Call    edi
        cmp     ah,80h
        jz      SaveDataNameCh
        Push    54h                ;Tキー 基本設定のテキストファイルエディタを変更
        Call    edi
        cmp     ah,80h
        jz      TextFileEditorCH
        Push    48h                ;Hキー 基本設定のヘキサエディタを変更
        Call    edi
        cmp     ah,80h
        jz      HexEditorCH
        Push    51h                ;Qキー 基本設定のアプリケーション1を変更
        Call    edi
        cmp     ah,80h
        jz      Appli1CH
        Push    57h                ;Wキー
        Call    edi
        cmp     ah,80h
        jz      Appli2CH
        Push    45h                ;Eキー
        Call    edi
        cmp     ah,80h
        jz      Appli3CH
        Push    52h                ;Rキー
        Call    edi
        cmp     ah,80h
        jz      Appli4CH
        Push    47h                ;Gキー
        Call    edi
        cmp     ah,80h
        jz      Appli5CH
        Push    59h                ;Yキー
        Call    edi
        cmp     ah,80h
        jz      Appli6CH
        Push    55h                ;Uキー
        Call    edi
        cmp     ah,80h
        jz      Appli7CH
        
        
        Push    43h                ;Cキー ドラッグ・アンド・ドロップされたファイルのCRCを取得
        Call    edi
        cmp     ah,80h
        jz      GetCRC
        Push    31h                ;1キー 基本設定のマルチメディアファイル1を変更
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH1
        Push    32h                ;2キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH2
        Push    33h                ;3キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH3
        Push    34h                ;4キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH4
        Push    35h                ;5キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH5
        Push    36h                ;6キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH6
        Push    37h                ;7キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH7
        Push    61h                ;1キー(テンキー) 基本設定のマルチメディアファイルを変更
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH1
        Push    62h                ;2キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH2
        Push    63h                ;3キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH3
        Push    64h                ;4キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH4
        Push    65h                ;5キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH5
        Push    66h                ;6キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH6
        Push    67h                ;7キー
        Call    edi
        cmp     ah,80h
        jz      AVIFileCH7
        jmp     WMdropfilesMain2   ;簡易テキスト表示 

WMdropfiles2:
        mov     esi,offset DefKey
        jmp     WMdropfilesMain

WMdropfiles3:
        mov     esi,offset DefKey3
        jmp     WMdropfilesMain

WMdropfiles4:
        mov     esi,offset DefKey5
        jmp     WMdropfilesMain

WMdropfiles5:
        mov     esi,offset DefKey6
        jmp     WMdropfilesMain

WMdropfiles6:
        mov     esi,offset DefKey7
        
WMdropfilesMain:
        push    104h                          ;ここではパス名のなので104hに再定義
        push    offset DragFileBuf
        push    offset DragFileBuf
        call    GetShortPathNameA
        push    offset DirBuffer
        push    INIBufferSize
        push    INIBuffer
        push    offset NOkey
        push    esi
        push    offset DefSection
        call    GetPrivateProfileStringA
        push    104h                           ;ここではパス名のなので104hに再定義
        push    INIBuffer
        push    INIBuffer
        call    GetShortPathNameA
        push    SW_SHOWNORMAL
        push    0
        push    offset DragFileBuf
        push    INIBuffer
        push    0
        push    hwnd_
        call    ShellExecuteA
        push    hDrop
        call    DragFinish                 ;ドラッグ・アンド・ドロップ処理終了
        ret

WMdropfilesMain2: 
        push    104h               ;ここではパス名のなので104hに再定義
        push    offset DragFileBuf
        push    offset DragFileBuf
        call    GetShortPathNameA
        push    handle
        push    file_attribute_normal
        push    open_existing
        push    lpsecurity_attribute
        push    file_share_read
        push    generic_read        ; + generic_write
        push    offset DragFileBuf
        Call    CreateFileA 
        mov     FileHandle,eax      ;返り値のファイルハンドルを退避
        push    0                   ;ファイルサイズがFFFFFFFFhバイト以上の場合は必要
        push    FileHandle
        Call    GetFileSize
        mov     FileSize,eax 
        push    FileSize
        push    GMEM_FIXED
        Call    GlobalAlloc         
        mov     MemPtr,eax           ;確保したメモリブロックのポインタを退避
        cmp     eax,0
        jnz     WMdropfilesMain3
        Push    mb_ok
        Call    MessageBeep
        push    mb_ok
        push    offset notice
        push    offset MemWrong
        push    hwnd_
        Call    MessageBoxA
        jmp     WMdropfilesMain4

WMdropfilesMain3:
        cmp     FileSize, 7800h          ;エディットコントロールへのテキスト表示サイズを限定
        jb      WMdropfilesMain3a        ;SET_LIMITTEXTでも可
        mov     FileSize, 7800h

WMdropfilesMain3a:
        push    0
        push    0
        push    0
        push    FileHandle
        call    SetFilePointer
        push    lpOverlapped
        push    offset lpNumberOfBytesRead
        push    FileSize
        push    MemPtr
        push    FileHandle
        Call    ReadFile
        push    MemPtr
        push    EDIT_TEXT_OUT
        push    hwnd_
        call    SetDlgItemTextA      ;他に良い方法がありますが、特に問題が無いのでこの関数を使用
        push    MemPtr
        call    GlobalFree

WMdropfilesMain4:
        push    FileHandle
        call    CloseHandle
        push    hDrop
        call    DragFinish           ;ドラッグ・アンド・ドロップ処理終了
        ret

GetCRC:                            ;■■■CRC取得処理■■■
        push    104h               ;ここではパス名のなので104hに再定義
        push    offset DragFileBuf
        push    offset DragFileBuf
        call    GetShortPathNameA
        push    handle
        push    file_attribute_normal
        push    open_existing
        push    lpsecurity_attribute
        push    file_share_read
        push    generic_read        ; + generic_write
        push    offset DragFileBuf
        Call    CreateFileA 
        mov     FileHandle,eax      ;返り値のファイルハンドルを退避
        push    0                   ;ファイルサイズがFFFFFFFFhバイト以上の場合は必要
        push    FileHandle
        Call    GetFileSize
        mov     FileSize,eax 
        push    FileSize
        push    GMEM_FIXED
        Call    GlobalAlloc         
        mov     MemPtr,eax           ;確保したメモリブロックのポインタを退避
        cmp     eax,0
        jnz     WMdropfilesMain3b
        Push    mb_ok
        Call    MessageBeep
        push    mb_ok
        push    offset notice
        push    offset MemWrong
        push    hwnd_
        Call    MessageBoxA
        jmp     WMdropfilesMain4a

WMdropfilesMain3b:
        push    0
        push    0
        push    0
        push    FileHandle
        call    SetFilePointer
        push    lpOverlapped
        push    offset lpNumberOfBytesRead
        push    FileSize
        push    MemPtr
        push    FileHandle
        Call    ReadFile

CRCTableMake1:
        xor     ecx,ecx

CRCTableMake2:
        mov     eax,ecx
        xor     edx,edx

CRCTableMake4:
        test    al,1
        je      CRCTableMake6
        shr     eax,1
        xor     eax,0EDB88320h           ;Polynomial
        jmp     CRCTableMake7

CRCTableMake6:
        shr     eax,1

CRCTableMake7:
        inc     edx
        cmp     edx,8
        jb      CRCTableMake4
        mov     dword ptr [CRC32Table+4*ecx],eax
        inc     ecx
        cmp     ecx,255
        jbe     CRCTableMake2
        mov     edx,MemPtr
        mov     ecx,FileSize
        or      eax,-1                    ;initial value = 0xFFFFFFFF
        jmp     CRC3

CRC2:
        mov     ebx,eax
        xor     bl,byte ptr [edx]
        and     ebx,255
        mov     ebx,dword ptr [CRC32Table+4*ebx]
        shr     eax,8
        xor     ebx,eax
        mov     eax,ebx
        inc     edx
CRC3:             
        dec     ecx
        jns     CRC2
        xor     eax, 0FFFFFFFFh
        push    FileSize
        push    eax
        push    offset CRCFormat
        push    offset CRC32TextBuf
        call    _wsprintfA
        add     esp,10h
        push    offset CRC32TextBuf
        push    EDIT_TEXT_OUT
        push    hwnd_
        call    SetDlgItemTextA 
        push    MemPtr
        call    GlobalFree

WMdropfilesMain4a:
        push    FileHandle
        call    CloseHandle
        push    hDrop
        call    DragFinish               ;ドラッグ・アンド・ドロップ処理終了
        ret

        
SaveDataNameCh:                          ;書き換え対象セーブデータのパスを変更
        mov     esi, offset GameTargetNum
        mov     eax, offset SaveDataPos
        jmp     KeyValueChMain

TextFileEditorCH:
        mov     esi, offset DefSection
        mov     eax, offset DefKey
        jmp     KeyValueChMain

HexEditorCH:
        mov     esi, offset DefSection
        mov     eax, offset DefKey3
        jmp     KeyValueChMain

Appli1CH:
        mov     esi, offset DefSection
        mov     eax, offset DefKey5
        jmp     KeyValueChMain

Appli2CH:
        mov     esi, offset DefSection
        mov     eax, offset DefKey6
        jmp     KeyValueChMain

Appli3CH:
        mov     esi, offset DefSection
        mov     eax, offset DefKey7
        jmp     KeyValueChMain

Appli4CH:
        mov     esi, offset DefSection
        mov     eax, offset DefKey8
        jmp     KeyValueChMain

Appli5CH:
        mov     esi, offset DefSection
        mov     eax, offset DefKey9
        jmp     KeyValueChMain

Appli6CH:
        mov     esi, offset DefSection
        mov     eax, offset DefKey10
        jmp     KeyValueChMain

Appli7CH:
        mov     esi, offset DefSection
        mov     eax, offset DefKey11
        jmp     KeyValueChMain

AVIFileCH1:
        mov     esi, offset DefSection
        mov     eax, offset DefKeyM1
        jmp     KeyValueChMain

AVIFileCH2:
        mov     esi, offset DefSection
        mov     eax, offset DefKeyM2
        jmp     KeyValueChMain

AVIFileCH3:
        mov     esi, offset DefSection
        mov     eax, offset DefKeyM3
        jmp     KeyValueChMain

AVIFileCH4:
        mov     esi, offset DefSection
        mov     eax, offset DefKeyM4
        jmp     KeyValueChMain

AVIFileCH5:
        mov     esi, offset DefSection
        mov     eax, offset DefKeyM5
        jmp     KeyValueChMain

AVIFileCH6:
        mov     esi, offset DefSection
        mov     eax, offset DefKeyM6
        jmp     KeyValueChMain

AVIFileCH7:
        mov     esi, offset DefSection
        mov     eax, offset DefKeyM7
        
KeyValueChMain:
        push    offset DirBuffer
        push    offset DragFileBuf
        push    eax
        push    esi
        call    WritePrivateProfileStringA     ;INIファイルに書き込み
        push    hDrop
        call    DragFinish                ;ドラッグ・アンド・ドロップ処理終了
        call    MediaMenuChange
        ret

InitDlg:                                  ;■■■ダイアログの初期処理■■■
        push    1
        push    hwnd_
        call    DragAcceptFiles           ;ドラッグ・アンド・ドロップの許可
        push    offset IconName
        push    hinst_
        call    LoadIconA
        test    eax, eax
        je      TEXTpoint                 ;アイコンのロードに失敗
        mov     hicon, eax
        push    hicon
        push    ICON_SMALL
        push    WM_SETICON                ;ウィンドウメッセージ
        push    hwnd_
        call    SendMessageA
        mov     dword ptr [offset iconDatacbSize],7Ch    ;NOTIFYICONDATA構造体の設定
        mov     eax, hwnd_
        mov     dword ptr [offset iconDatahwnd],eax
        mov     dword ptr [offset iconDatauID],1
        mov     dword ptr [offset iconDatauFlags],7       ;NIF_ICON +NIF_MESSAGE + NIF_TIP
        mov     dword ptr [offset iconDatauCallbackMessage],WM_TASKTRAY
        mov     eax, hicon
        mov     dword ptr [offset iconDatahIcon],eax
        push    offset TrayText
        push    offset iconDataszTip
        call    lstrcpyA
        push    offset iconDatacbSize
        push    0                                          ;NIM_ADD
        call    Shell_NotifyIconA                           ;タスクトレイにアイコン追加
        push    0
        push    hwnd_
        call    GetSystemMenu                              ;不要なシステムメニューを削除
        mov     SubMenuHandle2, eax
        push    MF_BYPOSITION
        push    0                                          ;不要なシステムメニューの位置
        push    SubMenuHandle2
        call    RemoveMenu
        push    MF_BYPOSITION
        push    1
        push    SubMenuHandle2
        call    RemoveMenu
        push    MF_BYPOSITION
        push    2
        push    SubMenuHandle2
        call    RemoveMenu
                
TEXTpoint:
        push    EDIT_TEXT_OUT
        push    hwnd_
        call    GetDlgItem
        mov     dword ptr [offset hEdit],eax   ;エディットコントロールのハンドルを取得・退避
        push    offset WINTITLE
        push    hwnd_                      
        call    SetWindowTextA             ;ウィンドウタイトルを設定
        test    eax, eax
        je      WMdestroy
        push    offset DriveExample
        push    EDIT_DRIVE
        push    hwnd_
        call    SetDlgItemTextA            ;ドライブ入力例を表示
        push    offset INTExample
        push    EDIT_INT
        push    hwnd_
        call    SetDlgItemTextA            ;CDトラック番号入力例を表示
        push    offset CDTrackExample
        push    EDIT_CDTRACK
        push    hwnd_
        call    SetDlgItemTextA
        push    0BB9h                      ;ラジオボタンの初期状態を設定
        push    0BBAh
        push    0BB9h
        push    hwnd_
        call    CheckRadioButton
        push    1                          ;チェックを付加
        push    CheckBackUp
        push    hwnd_
        call    CheckDlgButton             ;チェックボタンの状態を設定
        push    1
        push    CheckNoWarning
        push    hwnd_
        call    CheckDlgButton
        push    dword ptr [offset MenuHandle]
        push    hwnd_
        call    SetMenu
        call    MediaMenuChange

        push    0
        push    0
        push    WM_GETFONT
        push    hwnd_
        call    SendMessageA
        mov     dword ptr [FontHandle], eax
        push    WinPathCount
        push    offset WinPath
        Call    GetWindowsDirectoryA
        mov     ebx, 0
      
AddListBox:
        inc     ebx
        push    ebx
        push    offset TargetGameFormat
        push    offset GameTargetNum
        call    _wsprintfA
        add     esp,0Ch
        mov     edi, offset GameTargetNum
        push    offset DirBuffer
        push    TargetBufferSize
        push    offset TargetBuffer
        push    offset NOkey
        push    edi
        push    offset TargetSection
        call    GetPrivateProfileStringA 
        push    offset TargetBuffer
        push    ebx
        push    LB_ADDSTRING
        push    LIST_GAME                     ;ListBoxのID
        push    hwnd_
        call    SendDlgItemMessageA           ;「改造対象#」で設定したゲーム名をリスト項目名に設定
        cmp     ebx,dword ptr [GameNum]
        jb      AddListBox                    ;GameCount=登録数までループ 
        push    BTN_ChInfoUpdate
        push    hwnd_
        call    GetDlgItem                     ;改造関連ボタンの無効化 
        push    0                              ;FALSE
        push    eax
        call    EnableWindow
        push    BTN_CheatNow
        push    hwnd_
        call    GetDlgItem
        push    0                              ;FALSE
        push    eax
        call    EnableWindow
        push    MF_BYCOMMAND + MF_GRAYED
        push    MenuChInfoUpdate
        push    MenuHandle
        call    EnableMenuItem
        push    MF_BYCOMMAND + MF_GRAYED
        push    MenuCheatSelected
        push    MenuHandle
        call    EnableMenuItem
        push    MF_BYCOMMAND + MF_GRAYED
        push    SiteGame
        push    MenuHandle
        call    EnableMenuItem
        push    0
        push    8
        push    0C5h;EM_LIMITTEXT
        push    EDIT_INT
        push    hwnd_
        call    SendDlgItemMessageA


TEXTpoint2:
        push    offset POINT
        push    EDIT_TEXT_OUT
        push    hwnd_
        call    SetDlgItemTextA            ;「今回のポイント」を表示
        
BacktoDLG:                                ;CDチェックルーチン他からここに戻る
        RET                               ;戻ってからRET命令に繋ぐ方が簡単

MediaMenuChange PROC
        mov edi, offset DefKey5           ;「Appli#」で設定したアプリパスをメニュー項目名に設定
        mov esi, MenuAppli1
        call StartAppliMenu
        mov edi, offset DefKey6
        mov esi, MenuAppli2
        call StartAppliMenu
        mov edi, offset DefKey7
        mov esi, MenuAppli3
        call StartAppliMenu
        mov edi, offset DefKey8
        mov esi, MenuAppli4
        call StartAppliMenu
        mov edi, offset DefKey9
        mov esi, MenuAppli5
        call StartAppliMenu
        mov edi, offset DefKey10
        mov esi, MenuAppli6
        call StartAppliMenu
        mov edi, offset DefKey11
        mov esi, MenuAppli7
        call StartAppliMenu
        mov edi, offset DefKeyM1         ;「Mediafile#」で設定したファイルパスをメニュー項目名に設定
        mov esi, MenuMulti1
        call StartAppliMenu
        mov edi, offset DefKeyM2
        mov esi, MenuMulti2
        call StartAppliMenu
        mov edi, offset DefKeyM3
        mov esi, MenuMulti3
        call StartAppliMenu
        mov edi, offset DefKeyM4
        mov esi, MenuMulti4
        call StartAppliMenu
        mov edi, offset DefKeyM5
        mov esi, MenuMulti5
        call StartAppliMenu
        mov edi, offset DefKeyM6
        mov esi, MenuMulti6
        call StartAppliMenu
        mov edi, offset DefKeyM7
        mov esi, MenuMulti7
        call StartAppliMenu
        ret
MediaMenuChange ENDP

GAMEMenu PROC
        push offset DirBuffer
        push TargetBufferSize
        push offset TargetBuffer
        push offset NOkey
        push edi
        push offset TargetSection
        call GetPrivateProfileStringA            ;”改造対象#”キー読み込み
        push  hwnd_
        call GetMenu
        push offset TargetBuffer
        push esi                                 ;「改造情報詳細」直下のメニュー項目
        push 0
        push esi
        push MenuHandle
        call ModifyMenuA                         ;メニュー項目をゲーム名に変更
        add esi, 10000                           ;メニューID参照
        push  hwnd_
        call GetMenu
        push offset TargetBuffer
        push esi                                 ;「改造直実行」直下のメニュー項目
        push 0
        push esi
        push MenuHandle
        call ModifyMenuA
        ret
GAMEMenu ENDP   

StartAppliMenu PROC
        push offset DirBuffer
        push StartAppliBufSize
        push offset StartAppliBuf
        push offset NOkey
        push edi
        push offset DefSection
        call GetPrivateProfileStringA            ;”Appli#”キー読み込み
        push  hwnd_
        call GetMenu
        push offset StartAppliBuf
        push esi                                 ;「指定アプリの起動」直下のメニュー項目
        push 0
        push esi
        push eax
        call ModifyMenuA                         ;メニュー項目をパスに変更
        ret
StartAppliMenu ENDP

MenuOfSelectGame PROC
        push offset DirBuffer
        push TargetBufferSize
        push offset TargetBuffer
        push offset NOMenuOfSelectGame
        push offset GameNameKey
        push offset GameTargetNum
        call GetPrivateProfileStringA            ;"GameName"キー読み込み
        push offset TargetBuffer
        push 2040                                ;「改造対象一覧を表示」直下のメニュー項目
        push 0
        push 2040
        push MenuHandle
        call ModifyMenuA                         ;メニュー項目をゲーム名に変更
        push MFS_CHECKED + MF_BYCOMMAND
        push 2040
        push MenuHandle
        call CheckMenuItem
        push offset DirBuffer
        push TargetBufferSize
        push offset TargetBuffer
        push offset NOMenuOfSelectGame
        push offset GameNameKey
        push offset GameTargetNum
        call GetPrivateProfileStringA            ;"GameName"キー読み込み
        push offset TargetBuffer
        push 2041                                ;「改造直実行」直下のメニュー項目
        push 0
        push 2041
        push MenuHandle
        call ModifyMenuA                         ;メニュー項目をゲーム名に変更
        push MFS_CHECKED + MF_BYCOMMAND
        push 2041
        push MenuHandle
        call CheckMenuItem
        push offset TargetBuffer
        push 3502
        push hwnd_
        call SetDlgItemTextA
        mov eax, GameCountBuf3
        dec eax
        push 0
        push eax
        push LB_SETCURSEL
        push 3505                                 ;ListBoxのID
        push hwnd_
        call SendDlgItemMessageA                  ;リストボックスの選択項目変更
        ret
MenuOfSelectGame ENDP

DlgProcedure ENDP

;*************************************************************************************************
;CDチェックメインルーチン
;*************************************************************************************************

CheckMain:                 
  push CDCheckSkip         ;CDチェックのスキップが選択されているかチェック
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jz Goal

  push mb_ok - 30h       ;アイコンを付けるパラメータを除去
  push offset information
  push offset first      ;開始メッセージ
  push hwnd_
  Call MessageBoxA

Retry:
  mov ebx, 41h           ;41は"A"のASCII値なので「mov ebx ,'A'」でも可
  jmp Check

Increment:
  mov eax, ebx           ;ドライブ文字を表す値を別のレジスタに転送
  add eax, 01            ;インクリメントして(inc eaxでも可)
  mov ebx, eax           ;次のドライブ文字を表す値に変更
  
Check:                   ;CDドライブチェック
  mov ecx, ebx
  cmp ecx, 5Ah           ;5Aは"Z"のASCII値
  jg Error               ;Zドライブ以降はジャンプ
                         ;jaでも動作上は問題ありません 
  mov edx, ebx
  push edx               ;ドライブ文字を表す値
  push offset drive      
  push offset DrivePath  ;作成される文字列の格納先
  Call _wsprintfA        ;ドライブパス作成
  add esp,0Ch
  push offset DrivePath
  Call GetDriveTypeA     ;返り値についてはBlueAshさんのチュートリアル参照
  cmp eax, 5             ;EAXレジスタに格納された返り値を元にCDドライブかの判断
  jne Increment          ;CDドライブ以外は次のドライブへ
  je Nomal
 
Error:
  push mb_ok              ;一般の警告音
  Call MessageBeep
  push mb_retrycancel + 10h  ;アイコンを付けるパラメータを追加
  push offset notice
  push offset NoCD        ;警告メッセージ
  push hwnd_
  Call MessageBoxA
  cmp eax ,idretry
  je Retry                ;再試行へ
                          ;以下「キャンセル」が押された場合の処理
Backdoor:                 ;CDチェック回避のバックドアを、過去の実例から再現しました
  Push vk_shift           ;シフトキー
  Call GetAsyncKeyState   ;キーが押されたかチェックしてEAXレジスタに値を返す
  test ah,80h             ;キーが現在押されていればah=80hで演算結果(論理積)は80h
  jz Close                ;押されていなければ終了処理へ
  jmp Goal                ;押されていればCDチェックをスキップ

Nomal:
  Push 20h                ;メッセージ(問い合わせ)のサウンド
  Call MessageBeep
  push mb_yesno + 20h     ;アイコンを付けるパラメータを追加
  push offset ask
  push offset DrivePath   ;ドライブパスを表示
  push hwnd_
  Call MessageBoxA
  cmp eax,idno            ;「いいえ」を押したか?
  je Increment            ;次のCDドライブを探す
  
CDidentify:                           ;CD認証をはじめます
  push nFileSystemNameSize             ;不要なので0をPUSHしている
  push lpFileSystemNameBuffer          ;同上
  push offset lpFileSystemFlags        ;実際にはこのポインタは不要です
  push offset lpMaximumComponentLength ;同上
  push lpVolumeSerialNumber
  push dwcVolumeNameSize              ;文字単位で100h(256)にしましたが104hでも構いません
  push offset lpVolumeNameBuffer      ;取得するボリュームラベル格納先 
  push offset DrivePath
  Call GetVolumeInformationA          ;CDドライブのボリュームラベルを取得
  test eax ,eax                       ;返り値をチェック
  jnz VolNameCheck                    ;ボリュームラベル名チェックへ
  
  push mb_ok
  Call MessageBeep
  push mb_ok
  push offset notice
  push offset NoVolume     ;ボリュームラベルが取得できないのはCDドライブにCDが無いから 
  push hwnd_
  Call MessageBoxA
  jmp Increment            ;次のドライブへ  

VolNameCheck:              ;ボリュームラベルチェック
  push offset lpVolumeNameBuffer
  push offset VolumeName   ;「USAPYON」
  Call lstrcmpA            ;2つの文字列を比較
  test eax ,eax
  jz IDCheck               ;CD認証用ファイルチェックへ

  push mb_ok
  Call MessageBeep
  push mb_ok
  push offset notice
  push offset VolumeWrong  ;CDドライブのボリュームラベルが「USAPYON」ではない
  push hwnd_
  Call MessageBoxA
  jmp Increment            ;次のドライブへ  

IDCheck:                   
  push offset IDfile
  push offset DrivePath
  push offset file
  push offset FilePath
  Call _wsprintfA         ;CD認証用ファイル「usapyon.dat」のパスを作成
  add esp,10h

FileExistence:            ;CD認証ファイルの存在チェック
  push offset dwFileAttributes  ;WIN32_FIND_DATA構造体へのポインタ
  push offset FilePath
  Call FindFirstFileA     ;CDドライブのルートに「usapyon.dat」があるか?
  cmp eax,0FFFFFFFFh      ;ファイル「usapyon.dat」が存在しない(エラーが返された)
  je NoIDfile
  mov FindFileHandle ,eax ;返り値の検索ハンドルを退避

  push handle             ;以下でファイルハンドルを取得します
  push file_attribute_normal
  push open_existing
  push lpsecurity_attribute
  push file_share_read
  push generic_read
  push offset FilePath
  Call CreateFileA        ;この関数はファイルの存在チェックにも使用可能です
  mov FileHandle,eax      ;返り値のファイルハンドルを退避
  jmp IDsafe

NoIDfile:
  Push mb_ok
  Call MessageBeep
  push mb_ok
  push offset notice
  push offset IDwrong     ;CD認証失敗 
  push hwnd_
  Call MessageBoxA
  jmp Increment           ;次のドライブへ  

IDsafe:
  Push 40h                ;メッセージ(情報)のサウンド
  Call MessageBeep
  push mb_ok - 30h + 40h  ;アイコンを付けるパラメータを変更
  push offset information
  push offset IDthrough
  push hwnd_
  Call MessageBoxA
                           ;以下ファイルサイズチェック
;FileSize:                 ;コードを分かりやすくするためのラベルで実際には使用しない 
  push 0                   ;ファイルサイズがFFFFFFFFhバイト以上の場合は必要
  push FileHandle
  Call GetFileSize
  cmp eax,TrueSize         ;ファイルサイズは9999バイトか比較
  je Sizesafe
  
Sizeout:
  Push mb_ok
  Call MessageBeep
  push mb_ok
  push offset notice
  push offset SizeWrong    ;CD認証ファイルのサイズが適合しない 
  push hwnd_
  Call MessageBoxA
  jmp Increment            ;次のドライブへ

Sizesafe:
  mov eax ,dwFileAttributes
  and al ,01               ;CD認証ファイルは読み取り専用属性かチェック
  jnz Goal

  push mb_ok
  push offset notice
  push offset ReadOnly     ;読み取り専用属性でない
  push hwnd_
  Call MessageBoxA
  jmp Increment            ;次のドライブへ

;*************************************************************************************************
;CDチェックMCI関連処理部分ルーチン
;*************************************************************************************************

Goal:
  push CheckWav            ;WAV再生が選択されているかチェック
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jz NOCDDevice

  push CheckMidi           ;MidiのBGMが選択されているかチェック
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jz NOCDDevice

  push offset dwCallback   ;MCI_OPEN_PARMS構造体のポインタ
  push MCI_OPEN_TYPE       ;コマンド処理用フラグ
  push MCI_OPEN            ;デバイスをオープン
  push wDeviceIDOPEN       ;デバイスをオープンする際は不要(NULL)
  mov dword ptr [lpstrDeviceType], offset DeviceName ;デバイス名格納アドレスを転送
  call mciSendCommandA
  test eax, eax            ;デバイスのオープンに成功したら戻り値は0
  jne NOCDDevice

  push 0                   ;以下CDメディアの存在をチェック
  push 8h                  ;変数MediaPresentのサイズを再指定
  push offset MediaPresent
  push offset CDstatus
  call mciSendStringA
  push offset MediaPresent ;CDメディアが存在すれば文字列"true"が返される
  push offset MediaSafe
  Call lstrcmpA
  test eax ,eax
  jne NoMedia

  push 0                   ;以下トラックベースでの再生を設定(mciSendCommandA関数でも可)
  push 0                   ;トラックベースでなければ分ベースになる
  push 0
  push offset SetTrack
  call mciSendStringA
                           ;以下でCD再生開始
  push 0                   ;NULL
  push 0                   ;ゼロサイズ
  push 0                   ;ポインタだがNULL可
  push offset PlayCDaudio
  call mciSendStringA
  
  push mb_ok - 30h
  push offset information
  push offset SizeGood     ;「ゲームCDが認証されました」
  push hwnd_
  Call MessageBoxA
  jmp CDStop

NOCDDevice:                
  call MidiStart           ;MIDI再生用サブルーチンの呼び出し
  jmp Close

NoMedia:
  Push 40h
  Call MessageBeep
  push mb_ok - 30h + 40h
  push offset information
  push offset MediaErr     ;ゲームCD認証兼CDメディア確認エラーのメッセージ
  push hwnd_
  Call MessageBoxA
  jmp CDClose

CDStop:
  push offset dwCallback
  push MCI_WAIT
  push MCI_STOP
  push wDeviceID
  call mciSendCommandA      ;CD再生を停止

CDClose:
  push offset dwCallback
  push MCI_NOTIFY
  push MCI_CLOSE
  push wDeviceID
  call mciSendCommandA     ;cdaudioデバイスをクローズ

Close:
  push FindFileHandle
  Call FindClose           ;ファイル検索ハンドルをクローズ

  push FileHandle
  Call CloseHandle         ;ファイルハンドルをクローズ

Last:
  jmp BacktoDLG             ;ダイアログに戻る
  ;push 0                                    ;親プロセスに返す終了コード(無意味)
  ;.invoke .win32 'KERNEL32.ExitProcess'     ;APIを直接呼び出す例
  ;Call ExitProcess                          ;ダイアログに処理を戻すため使わない

MidiStart PROC             ;■■■MIDI・WAV再生用サブルーチン■■■
  push CheckWav            ;WAV再生が選択されているかチェック
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jnz SelectMidi
  mov ebx, offset SetWAV     ;こちらを使えば「usapyon.wav」を再生します。
  mov esi, offset WavPlay    ;WAV再生メッセージ
  jmp Midi_Wav_Play

SelectMidi:
  mov ebx, offset SetMidi
  mov esi, offset DeviceErr  ;デバイスエラー兼MIDI再生メッセージ

Midi_Wav_Play:
  mov edi, offset mciSendStringA  ;汎用レジスタにロードして複数回利用する例
  push 0                   ;以下MIDI・WAファイルの再生を設定(mciSendCommandA関数でも可)
  push 0
  push 0
  push ebx                 ;MIDI・WAVを指定
  call edi                 ;mciSendStringA
  
  push 0                   ;以下でMIDI・WAVファイルの再生開始
  push 0
  push 0
  push offset PlayMidi
  call edi                 ;mciSendStringA
  
  push mb_ok - 30h         ;アイコンを除去しないとウィンドウズのイベントサウンドが再生される
  push offset information
  push esi                 ;メッセージ格納先ポインタを指定
  push hwnd_
  Call MessageBoxA

  ;push 0BB8h              ;WAVファイルの再生時に上のメッセージボックスを使わない場合は、
  ;call Sleep              ;再生時間を取得してその分プロセスを停止し、WAVを終わりまで再生させる

  push 0                   ;以下MIDI・WAVファイルの再生を停止
  push 0
  push 0
  push offset StopMidi
  call edi                 ;mciSendStringA
  
  push 0                   ;以下でMIDI・WAVファイルのデバイスをクローズ
  push 0
  push 0
  push offset CloseMidi
  call edi                 ;mciSendStringA
  ret
MidiStart ENDP 

;*************************************************************************************************
;CDチェック以外の付属機能
;*************************************************************************************************

FixTopWindow:               ;■■■最前面表示処理■■■
  push MF_BYCOMMAND
  push MenuTop
  push MenuHandle
  call GetMenuState
  cmp al,MFS_CHECKED
  je BringToBehind
  push MF_BYCOMMAND + MFS_CHECKED
  push MenuTop
  push MenuHandle
  call CheckMenuItem
  push SWP_NOSIZE + SWP_NOMOVE
  push 0
  push 0
  push 0
  push 0
  push HWND_TOPMOST
  push hwnd_
  call SetWindowPos
  jmp BacktoDLG

BringToBehind:
  push MF_BYCOMMAND + MFS_UNCHECKED
  push MenuTop
  push MenuHandle
  call CheckMenuItem
  push SWP_NOSIZE + SWP_NOMOVE
  push 0
  push 0
  push 0
  push 0
  push HWND_BOTTOM
  push hwnd_
  call SetWindowPos
  push SWP_NOSIZE + SWP_NOMOVE
  push 0
  push 0
  push 0
  push 0
  push HWND_TOP
  push hwnd_
  call SetWindowPos
  jmp BacktoDLG

AtoIConv:                   ;■■■10進数列−16進数値変換処理■■■
  push Radio16              ;「16」が選択されているかチェック
  push hwnd_
  call IsDlgButtonChecked   ;チェックボタンの状態を取得
  dec eax
  jz AtoIConv16
  push 1                    ;符号付き整数を指定
  push offset DummyStrage   ;Bool変数のポインタ
  push EDIT_INT             ;コントロールID
  push hwnd_                ;ダイアログボックスのハンドル
  call GetDlgItemInt        ;符号付き整数以外の入力は総て値0と認識します
  push eax                  ;16進数値に変換された入力文字列
  push offset atoi
  push offset SUbCheckBuf   ;作成される文字列の格納先
  Call _wsprintfA           ;数値を文字列のコメントに変換
  add  esp,0Ch
  push offset SUbCheckBuf
  push EDIT_TEXT_OUT
  push hwnd_
  call SetDlgItemTextA      ;コメントを表示
  jmp BacktoDLG

AtoIConv16:                 ;■■■16進数列−10進数値変換処理■■■
  push 20h                  ;バッファ最大文字数
  push offset SUbCheckBuf3  ;文字列格納バッファのポインタ
  push EDIT_INT             ;コントロールID
  push hwnd_                ;ダイアログボックスのハンドル
  call GetDlgItemTextA
  mov  eax,offset SUbCheckBuf3
  call HexAtoHexI
  push eax                                ;16進数値に変換された入力文字列
  push offset atoi16
  push offset SUbCheckBuf3                ;作成される文字列の格納先
  Call _wsprintfA                         ;数値を文字列のコメントに変換
  add esp,0Ch
  push offset SUbCheckBuf3
  push EDIT_TEXT_OUT
  push hwnd_
  call SetDlgItemTextA                    ;コメントを表示
  jmp BacktoDLG

HexAtoHexI PROC                           ;変換処理サブルーチン(コード未整理)
      push edx                            ;atoi関数、itoa関数についても参照して下さい
      push ebx
      push ecx

HAtoHI1:
      jmp HAtoHI3

HAtoHI2:
      inc eax

HAtoHI3:
      cmp byte ptr [eax],32
      je  HAtoHI2
      cmp byte ptr [eax],9
      je  HAtoHI2 
      cmp byte ptr [eax],43
      jne HAtoHI4
      inc eax
      jmp HAtoHI5

HAtoHI4:
      cmp byte ptr [eax],45
      jne HAtoHI6
      or ecx,-1
      inc eax

HAtoHI6:
HAtoHI5:
      xor edx,edx
      jmp HAtoHI8

HAtoHI7:
      shl edx,4
      cmp byte ptr [eax],48
      jl HAtoHI9
      cmp byte ptr [eax],57
      jg HAtoHI9
      movsx ebx,byte ptr [eax]
      add ebx,-48
      add edx,ebx
      jmp HAtoHI10

HAtoHI9:
      cmp byte ptr [eax],65
      jl HAtoHI11
      cmp byte ptr [eax],70
      jg HAtoHI11
      movsx ebx,byte ptr [eax]
      add ebx,-55
      add edx,ebx
      jmp HAtoHI10

HAtoHI11:
      movsx ebx,byte ptr [eax]
      add ebx,-87
      add edx,ebx

HAtoHI10:
      inc eax

HAtoHI8:
      cmp byte ptr [eax],48
      jl  HAtoHI12
      cmp byte ptr [eax],57
      jle HAtoHI7

HAtoHI12:
      cmp byte ptr [eax],65
      jl  HAtoHI13
      cmp byte ptr [eax],70
      jle HAtoHI7

HAtoHI13:
      cmp byte ptr [eax],97
      jl  HAtoHI14
      cmp byte ptr [eax],102
      jle HAtoHI7

HAtoHI14:
      dec ecx
      jne HAtoHI15
      mov eax,edx
      jmp HAtoHI17

HAtoHI15:
      mov eax,edx

HAtoHI18:
HAtoHI17:    
      pop ecx
      pop ebx
      pop edx
      ret
HexAtoHexI ENDP


CheckSub:                                 ;■■■ドライブタイプ判定処理■■■
  push 20h                                ;バッファ最大文字数
  push offset SUbCheckBuf2                ;文字列格納バッファのポインタ
  push EDIT_DRIVE                         ;コントロールID
  push hwnd_                              ;ダイアログボックスのハンドル
  call GetDlgItemTextA
  cmp eax, 3                              ;戻り値は入力された文字数
  ja NotDriveletter
  mov eax, dword ptr [offset SUbCheckBuf2]
  cmp al, 41h                             ;41h="A"
  jb NotDriveletter
  cmp al, 7Ah                             ;7Ah="z"
  ja NotDriveletter
  cmp al, 5Bh                             ;"["
  je NotDriveletter                         
  cmp al, 5Ch                             ;"\"
  je NotDriveletter                       
  cmp al, 5Dh                             ;"]"
  je NotDriveletter                       
  cmp al, 5Eh                             ;"^"
  je NotDriveletter                       
  cmp al, 5Fh                             ;"_"
  je NotDriveletter                       
  cmp ah, 3Ah                             ;":"
  jne NotDriveletter                      
  shr eax, 10h                            
  cmp al, 0h                              ;未入力
  je CDCheck2nd                           
  cmp al, 5Ch                             ;"\"
  je CDCheck2nd

NotDriveletter:              ;wsprintf関数で入力されたドライブパス文字列をコメントに追加可能
  ;Push 40h
  ;Call MessageBeep
  push mb_ok - 30h + 40h
  push offset information
  push offset NOTDrive
  push hwnd_
  Call MessageBoxA
  jmp BacktoDLG

CDCheck2nd:                 
  push offset SUbCheckBuf2
  Call GetDriveTypeA
  cmp eax, 1
  je DriveReturn1
  cmp eax, 3
  je DriveReturn3
  cmp eax, 2
  je DriveReturn2
  cmp eax, 5
  je DriveReturn5
  push offset Drive_Unknown

DriveReturn1:
  push offset Drive_NON
  jmp CheckResult

DriveReturn3:
  push offset Drive_Hard
  jmp CheckResult

DriveReturn2:
  push offset Drive_Fix
  jmp CheckResult

DriveReturn5:
  push offset Drive_CD
  
CheckResult:
  push EDIT_TEXT_OUT
  push hwnd_
  call SetDlgItemTextA  
  jmp BacktoDLG           ;ダイアログに戻る


AboutBox:                  ;■■■バージョン情報についての表示■■■
  push offset AboutNotice
  push EDIT_TEXT_OUT
  push hwnd_
  call SetDlgItemTextA
  jmp BacktoDLG
 
EDIT_TEXT_OUT_Clear:      ;■■■メインエディットボックス選択領域をクリア■■■
  mov eax, WM_CLEAR
  jmp EDIT_TEXT_OUT_MAIN

EDIT_TEXT_OUT_UNDO:       ;■■■メインエディットボックスでUNDO■■■
  mov eax, WM_UNDO
  jmp EDIT_TEXT_OUT_MAIN

EDIT_TEXT_OUT_Cut:        ;■■■メインエディットボックスでCUT■■■
  mov eax, WM_CUT
  jmp EDIT_TEXT_OUT_MAIN

EDIT_TEXT_OUT_Copy:       ;■■■メインエディットボックスでCOPY■■■
  mov eax, WM_COPY
  jmp EDIT_TEXT_OUT_MAIN

EDIT_TEXT_OUT_Paste:      ;■■■メインエディットボックスでPASTE■■■
  mov eax, WM_PASTE
  
EDIT_TEXT_OUT_MAIN:
  push 0
  push 0
  push eax
  push hEdit
  call SendMessageA
  jmp BacktoDLG

EDIT_TEXT_OUT_ALL:         ;■■■エディットコントロール内全テキストを選択■■■
  call SelectALLtext
  jmp BacktoDLG

SelectALLtext PROC
  push -1
  push 0
  push EM_SETSEL
  push hEdit
  call SendMessageA
  ret 
SelectALLtext ENDP
  
EDIT_TEXT_OUT_ALLClear:     ;■■■エディットコントロール内全テキストをクリア■■■
  call SelectALLtext
  jmp EDIT_TEXT_OUT_Clear
  
;*************************************************************************************************
;CD−DA及び各種メディアファイルの操作ルーチン
;*************************************************************************************************

CD_Play:                   ;■■■トラック指定によるCD再生■■■
  push 0                   ;符号なし整数を指定
  push offset DummyStrage  ;Bool変数のポインタ
  push EDIT_CDTRACK        ;コントロールID
  push hwnd_               ;ダイアログボックスのハンドル
  call GetDlgItemInt       ;符号なし整数以外の入力は総て値0と認識します
  push eax                 ;数値に変換された入力文字列
  push offset TrackMessage
  push offset MCIMessBuf   ;作成される文字列の格納先
  Call _wsprintfA          ;数値を文字列のコメントに変換
  add  esp,0Ch

  push 0                   ;NULL
  push 0                   ;ゼロサイズ
  push 0                   ;ポインタだがNULL可
  push offset OpenMessage
  call mciSendStringA
  
  push 0                   ;以下トラックベースでの再生を設定(mciSendCommandA関数でも可)
  push 0                   ;トラックベースでなければ分ベースになる
  push 0
  push offset SetTrack
  call mciSendStringA

  push 01F4h               ;再生開始までにバッファを置いて、再生エラーが起きる可能性に対処
  call Sleep

  push hwnd_               ;MM_MCINOTIFYメッセージを返すウィンドウハンドル
  push 0
  push 0
  push offset MCIMessBuf
  call mciSendStringA
  jmp BacktoDLG

CD_Stop:                   ;■■■CD停止処理■■■
  call CD_END        ;「Stop」ボタン押下時とアプリ終了時にCD再生停止とデバイスのクローズを行う
  jmp BacktoDLG

CD_END PROC
  push 0
  push 0
  push 0
  push offset StopCD
  call mciSendStringA
  
  push 0
  push 0
  push 0
  push offset CloseCD
  call mciSendStringA
  ret
CD_END ENDP

CD_Eject:                   ;■■■CD取り出し処理■■■
  call CD_END               ;CD停止処理
  push 0
  push 0
  push 0
  push offset EjectCD
  call mciSendStringA
  jmp BacktoDLG

CD_Insert:                  ;■■■CD挿入処理■■■
  push 0
  push 0
  push 0
  push offset InsertCD
  call mciSendStringA
  jmp BacktoDLG

AVIStart1:                 ;■■■マルチメディアファイル再生処理■■■
  mov edi, offset DefKeyM1
  mov esi, offset AVIPlayMessage
  jmp AVIStartMain

AVIStart2:
  mov edi, offset DefKeyM2
  mov esi, offset AVIPlayMessage
  jmp AVIStartMain

AVIStart3:
  mov edi, offset DefKeyM3
  mov esi, offset AVIPlayMessage
  jmp AVIStartMain

AVIStart4:
  mov edi, offset DefKeyM4
  mov esi, offset AVIPlayMessage
  jmp AVIStartMain

AVIStart5:
  mov edi, offset DefKeyM5
  mov esi, offset AVIPlayMessage
  jmp AVIStartMain

AVIStart6:
  mov edi, offset DefKeyM6
  mov esi, offset AVIPlayMessage
  jmp AVIStartMain

AVIStart7:
  mov edi, offset DefKeyM7
  mov esi, offset AVIPlayMessage
  jmp AVIStartMain

AVIResume:                       ;■■■マルチメディアファイル再開処理■■■
  mov esi, offset AVIResumeMessage
  jmp AVIStartMain2

AVIPause:                        ;■■■マルチメディアファイル一時停止処理■■■
  mov esi, offset AVIPauseMessage
  jmp AVIStartMain2

AVIStop:                         ;■■■マルチメディアファイル停止処理■■■
  push INIBuffer                 ;AVIStartMain2重複処理:サブルーチン化で不具合有り
  push offset AVIStopMessage
  push offset DirBuffer2
  call _wsprintfA
  add  esp,0Ch
  push 0
  push 0
  push 0
  push offset DirBuffer2
  call mciSendStringA
  mov esi,offset AVICloseMessage ;■■■デバイスクローズ処理■■■
  jmp AVIStartMain2

AVIStartMain:
  push offset DirBuffer
  push INIBufferSize
  push INIBuffer
  push offset NOkey
  push offset edi
  push offset DefSection
  call GetPrivateProfileStringA

AVIStartMain2:
  push 104h                       ;ここではパス名のなので104hに再定義
  push INIBuffer
  push INIBuffer
  call GetShortPathNameA

  push INIBuffer
  push esi
  push offset DirBuffer2
  call _wsprintfA
  add  esp,0Ch
  push 0
  push 0
  push 0
  push offset DirBuffer2
  call mciSendStringA
  jmp BacktoDLG

SndVol32:                        ;■■■Sndvol32.exe起動処理■■■
  push 104h                      ;ここではパス名のなので104hに再定義
  push offset WinPath
  push offset WinPath
  call GetShortPathNameA
  push offset WinPath
  push offset SndVol
  push offset WinAppliPath
  call _wsprintfA
  add  esp,0Ch
  push SW_SHOWNORMAL
  push 0
  push 0
  push offset WinAppliPath
  push 0
  push hwnd_
  call ShellExecuteA
  jmp BacktoDLG

;*************************************************************************************************
;URL展開・アプリ起動処理
;*************************************************************************************************

URL_DT:               ;■■■URL展開処理■■■
  mov esi, offset URL_1
  jmp URL_MAIN

URL_DT2:
  mov esi, offset URL_2
  jmp URL_MAIN

URL_MSDN:
  mov esi, offset URL_3
  jmp URL_MAIN

URL_MSDN2:
  mov esi,  offset URL_4
  jmp URL_MAIN

URL_GAME:
  push offset DirBuffer
  push INIBufferSize
  push INIBuffer
  push offset NOkey
  push offset GameSiteKey
  push offset GameTargetNum
  call GetPrivateProfileStringA
  mov esi,  INIBuffer

URL_MAIN:
  push SW_MAXIMIZE
  push 0
  push 0
  push esi
  push 0
  push hwnd_
  call ShellExecuteA
  jmp BacktoDLG

INIOpen:                  ;■■■INIファイルオープン処理■■■
  push 104h               ;ここではパス名のなので104hに再定義
  push offset WinPath
  push offset WinPath
  call GetShortPathNameA
  push offset WinPath
  push offset Notepad
  push offset WinAppliPath
  call _wsprintfA
  add  esp,0Ch
  push SW_MAXIMIZE
  push 0
  push offset DirBuffer
  push offset WinAppliPath
  push 0
  push hwnd_
  call ShellExecuteA
  jmp BacktoDLG

ChangeFont:               ;■■■フォント変更処理■■■
  push 1
  push 0
  push WM_SETFONT
  push EDIT_TEXT_OUT
  push hwnd_
  call SendDlgItemMessageA
  jmp BacktoDLG

UndoFont:                 ;■■■フォント変更処理2■■■
  push 1
  push dword ptr [FontHandle]
  push WM_SETFONT
  push EDIT_TEXT_OUT
  push hwnd_
  call SendDlgItemMessageA
  jmp BacktoDLG

MemoStart:                ;■■■テキストエディタ起動処理■■■
  mov esi,offset DefKey
  jmp StartMain

HexStart:                 ;■■■ヘキサエディタ起動処理■■■
  mov esi,offset DefKey3
  jmp StartMain

CalStart:                 ;■■■16進電卓起動処理■■■
  mov esi,offset DefKey4
  jmp StartMain

Appli1Start:              ;■■■登録アプリ1起動処理■■■
  mov esi,offset DefKey5
  jmp StartMain

Appli2Start:              ;■■■登録アプリ2起動処理■■■
  mov esi,offset DefKey6
  jmp StartMain

Appli3Start:              ;■■■登録アプリ3起動処理■■■
  mov esi,offset DefKey7
  jmp StartMain

Appli4Start:              ;■■■登録アプリ4起動処理■■■
  mov esi,offset DefKey8
  jmp StartMain

Appli5Start:              ;■■■登録アプリ5起動処理■■■
  mov esi,offset DefKey9
  jmp StartMain

Appli6Start:              ;■■■登録アプリ6起動処理■■■
  mov esi,offset DefKey10
  jmp StartMain

Appli7Start:              ;■■■登録アプリ7起動処理■■■
  mov esi,offset DefKey11

StartMain: 
  push offset DirBuffer
  push INIBufferSize
  push INIBuffer
  push offset NOkey
  push esi
  push offset DefSection
  call GetPrivateProfileStringA
  push 104h                           ;ここではパス名のなので104hに再定義
  push INIBuffer
  push INIBuffer
  call GetShortPathNameA
  push SW_SHOWNORMAL
  push 0
  push 0
  push INIBuffer
  push 0
  push hwnd_
  call ShellExecuteA
  jmp BacktoDLG

;*************************************************************************************************
;ゲーム改造関連ルーチン
;*************************************************************************************************

CheatEnable PROC
  push BTN_ChInfoUpdate
  push hwnd_
  call GetDlgItem                     ;改造関連ボタンの有効化 
  push 1                              ;True
  push eax
  call EnableWindow
  push BTN_CheatNow
  push hwnd_
  call GetDlgItem
  push 1                              ;True
  push eax
  call EnableWindow
  push MF_BYCOMMAND + MF_ENABLED      ;改造関連メニューの有効化 
  push MenuChInfoUpdate
  push MenuHandle
  call EnableMenuItem
  push MF_BYCOMMAND + MF_ENABLED      ;改造関連メニューの有効化
  push MenuCheatSelected
  push MenuHandle
  call EnableMenuItem
  push MF_BYCOMMAND + MF_ENABLED      ;改造関連メニューの有効化
  push SiteGame
  push MenuHandle
  call EnableMenuItem
  ret 
CheatEnable ENDP

ListSelect:                       ;■■■選択ゲームの変更認識処理■■■
  shr eax,10h 
  cmp eax,LBN_SELCHANGE
  jne BacktoDLG
  call CheatEnable
  jmp SelectGameFromList

FUI:
  push offset FUIList
  push EDIT_TEXT_OUT
  push hwnd_
  call SetDlgItemTextA
  jmp BacktoDLG

GameSectionUpdate:                 ;■■■選択中ゲームのGAMEセクション更新処理■■■
  push vk_shift                    ;バックドア
  call GetAsyncKeyState
  cmp ah,80h
  jz GameSectionUpdate2
  push mb_yesno + 20h              ;アイコンを付けるパラメータを追加
  push offset askupdate
  push offset CheatInfoUpdate
  push hwnd_
  Call MessageBoxA
  cmp eax,idno                     ;「いいえ」を押したか?
  je BacktoDLG

GameSectionUpdate2:
  mov ecx, 1FFFh
  mov ebx, INIBuffer

INIBufferClear:
  mov dword ptr [ebx],0
  add ebx, 4
  loop INIBufferClear
  push 7FFFh
  push INIBuffer
  push EDIT_TEXT_OUT
  push hwnd_
  call GetDlgItemTextA
  push offset DirBuffer
  push INIBuffer
  push offset GameTargetNum
  call WritePrivateProfileSectionA
  mov esi, offset GameTargetNum
  jmp INIindicateMain
  jmp BacktoDLG

SelectGameFromList:                  ;■■■改造情報表示処理■■■
   push 0
   push 0
   push LB_GETCURSEL
   push 3505                          ;ListBoxのID
   push hwnd_
   call SendDlgItemMessageA
   mov GameCountBuf3, eax
   inc  eax
   push eax
   push offset TargetGameFormat
   push offset GameTargetNum
   call _wsprintfA
   add  esp,0Ch
   mov  edi, offset GameTargetNum    ;「改造対象#」で設定したゲーム名        
   push offset DirBuffer
   push TargetBufferSize
   push offset TargetBuffer
   push offset NOkey
   push edi
   push offset TargetSection
   call GetPrivateProfileStringA 
   push offset TargetBuffer
   push 3502
   push hwnd_
   call SetDlgItemTextA
   inc  GameCountBuf3
   push GameCountBuf3
   push offset GameSectionFormat
   push offset GameTargetNum
   call _wsprintfA
   add  esp,0Ch
   mov esi, offset GameTargetNum
   call MenuOfSelectGame
   jmp INIindicateMain

NowSelectGame:                ;■■■現在選択・改造中のゲーム表示処理■■■
  push offset DirBuffer
  push INIBufferSize
  push INIBuffer
  push offset NOkey2
  push offset GameNameKey
  push offset GameTargetNum
  call GetPrivateProfileStringA
  push INIBuffer
  push offset SelectGameIs
  push offset SelectGameBuf
  call _wsprintfA
  add  esp,0Ch
  push offset SelectGameBuf
  push EDIT_TEXT_OUT
  push hwnd_
  call SetDlgItemTextA
  jmp BacktoDLG

INIindicate:                    ;■■■INIファイルの基本設定・改造コード表示処理■■■
  sub eax, MenuChInfo
  inc eax 
  mov GameCountBuf3, eax
  push eax 
  push offset GameSectionFormat
  push offset GameTargetNum
  call _wsprintfA
  add esp,0Ch
  mov esi, offset GameTargetNum
  call MenuOfSelectGame
  call CheatEnable
  jmp INIindicateMain

INIindicateGame:
  mov esi, offset TargetSection
  jmp INIindicateMain

INIindicateDef:
  mov esi, offset DefSection

INIindicateMain:
  mov edi, INIBuffer      
  push offset DirBuffer           ;INIファイルのパス
  push INIBufferSize              ;取得セクション内容格納バッファのサイズ
  push INIBuffer                  ;同ポインタ
  push esi                        ;目的のセクション名
  call GetPrivateProfileSectionA;指定セクションの内容を総て取得
  push offset Dummy             ;エディットコントロールをダミーデータでクリア
  push EDIT_TEXT_OUT
  push hwnd_
  call SetDlgItemTextA          ;エディットコントロールに文字を送る別の方法 
  mov dword ptr [KeyReturn],00000A0Dh    ;強制改行の準備(\r\n不可)

NextLine:
  push edi                      ;INIBuffer
  call lstrlenA
  mov esi,eax
  push edi                      ;INIBuffer
  push 0
  push EM_REPLACESEL
  push hEdit
  call SendMessageA
  push offset KeyReturn
  push 0
  push EM_REPLACESEL
  push hEdit
  call SendMessageA             ;強制改行
  add edi,esi
  inc edi
  cmp byte ptr [edi], 0         ;これ以降文字が無いか
  je LineEnd 
  mov eax, dword ptr [INIBuffer]
  add eax, INIBufferSize          
  cmp edi, eax
  jb  NextLine

LineEnd:    
  push -104h                    ;縦方向スクロール行数
  push 0
  push EM_LINESCROLLL
  push hEdit
  call SendMessageA             ;エディットコントロールの最初の行まで戻す
  jmp BacktoDLG                 ;ダイアログに戻る

GameCheatFromBTN:
  push GameCountBuf3
  push offset GameSectionFormat
  push offset GameTargetNum
  call _wsprintfA
  add  esp,0Ch
  jmp CheatSelectedGame

GameCheat:                      ;■■■ゲーム改造実行処理の準備(対象ファイルのオープン)■■■
  sub eax, MenuCheat
  inc eax 
  mov GameCountBuf3, eax
  push eax 
  push offset GameSectionFormat
  push offset GameTargetNum
  call _wsprintfA
  add  esp,0Ch
  call CheatEnable

CheatSelectedGame:
  mov esi,offset GameTargetNum
  mov dword ptr [GameSectionNum],esi        ;ゲームセクションの特定
  call MenuOfSelectGame
  jmp GameCheatMain

GameCheatMain:
  mov dword ptr [offset CodeCountBuf2], 1    ;コード番号を1にセット

;PreCheat:
  push offset DirBuffer
  push 104h                                ;INIBufferSizeでは不整合が生じてエラー
  push offset PathBuffer                   ;PathBuffer=104h
  push offset NOkey
  push offset SaveDataPos
  push dword ptr [GameSectionNum]
  call GetPrivateProfileStringA            ;”SaveData”キー読み込み
  push 104h                                ;ここではパス名のなので104hに再定義
  push offset PathBuffer
  push offset PathBuffer
  call GetShortPathNameA
  push file_attribute_normal
  push offset PathBuffer
  call SetFileAttributesA                  ;読み取り専用属性を外してファイル属性をノーマルに
  push handle
  push file_attribute_normal
  push open_existing
  push lpsecurity_attribute
  push file_share_read
  push generic_read + generic_write
  push offset PathBuffer
  Call CreateFileA 
  mov FileHandle,eax                        ;返り値のファイルハンドルを退避
  cmp  eax,0FFFFFFFFh                       ;セクション名の間違いもここでフォロー
  jnz SaveExist

SaveError:                                  ;ファイルハンドル取得失敗 
  mov dword ptr [CodeErrorMess], offset SaveWrong
  call CodeError
  push CheckNoWarning
  push hwnd_
  call IsDlgButtonChecked            ;チェックボタンの状態を取得
  dec eax
  jz CheatFinish2
  Push mb_ok
  Call MessageBeep
  push mb_ok
  push offset notice
  push offset SaveWrong
  push hwnd_
  Call MessageBoxA
  jmp  CheatFinish2

SaveExist:               ;■■■対象ファイルのバックアップ作成処理■■■
  push offset PathBuffer 
  push offset BackupName
  push offset PathBuffer2
  call _wsprintfA
  add  esp,0Ch
  push CheckBackUp
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jnz SaveExist2
  push 1                   ;True
  push offset PathBuffer2
  push offset PathBuffer
  call CopyFileA
  call GetLastError
  cmp  eax, ERROR_FILE_EXISTS
  jnz SaveExist2
  Push 20h                ;メッセージ(問い合わせ)のサウンド
  Call MessageBeep
  push mb_yesno + 20h     ;アイコンを付けるパラメータを追加
  push offset information
  push offset BackupRewrite
  push hwnd_
  Call MessageBoxA
  cmp eax,idno            ;「いいえ」を押したか?
  je SaveExist2
  push 0                  ;False
  push offset PathBuffer2
  push offset PathBuffer
  call CopyFileA

SaveExist2:                ;■■■メモリブロック確保と対象ファイルの読み込み■■■
  push offset LowDateTime1
  push offset LowDateTime2
  push offset LowDateTime3
  push FileHandle
  call GetFileTime
  push 0                   ;ファイルサイズがFFFFFFFFhバイト以上の場合は必要
  push FileHandle
  Call GetFileSize
  mov FileSize,eax 
  push FileSize
  push GMEM_FIXED
  Call GlobalAlloc         
  mov MemPtr,eax           ;確保したメモリブロックのポインタを退避
  cmp eax,0
  jnz MemorySafe
  mov dword ptr [CodeErrorMess], offset MemWrong
  call CodeError
  push CheckNoWarning
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jz CheatFinish
  Push mb_ok
  Call MessageBeep
  push mb_ok
  push offset notice
  push offset MemWrong
  push hwnd_
  Call MessageBoxA
  jmp  CheatFinish

MemorySafe:
  push lpOverlapped
  push offset lpNumberOfBytesRead
  push FileSize
  push MemPtr
  push FileHandle
  Call ReadFile

GetCode:                       ;■■■ゲーム改造コードの読み込みと型判定■■■
  push dword ptr [offset CodeCountBuf2]
  push offset CodeNameFormat
  push offset CodeName
  call _wsprintfA                          ;”Code#”文字列作成
  add  esp,0Ch
  push offset DirBuffer
  push INIBufferSize
  push INIBuffer
  push offset NOkey
  push offset CodeName
  push dword ptr [GameSectionNum]
  call GetPrivateProfileStringA            ;”Code#”読み込み
  mov ecx, INIBuffer
  mov edx, offset CodeStart
  cmp byte ptr [ecx], 25h     ;"%"         ;置換型コードの判定
  je CodeReplacePre
  cmp byte ptr [ecx], 48h     ;"H"
  je HexView

Code1st:
  mov bl,byte ptr [ecx]
  mov byte ptr [edx], bl
  inc edx
  inc ecx
  cmp byte ptr [ecx], 3Eh     ;">"         ;コード制御記号認識
  je Code2nd
  cmp byte ptr [ecx], 2Dh     ;"-"
  je Code3rdPre
  cmp byte ptr [ecx], 24h     ;"$"         ;文字列型コードの判定
  je Code3rdString1
  jmp Code1st

Code2nd:
  mov byte ptr [offset SerialMacro], 1      ;">"を用いた連続処理のフラグを成立させる
  mov eax, offset CodeStart
  call HexAtoHexI
  mov dword ptr [offset CodeStart2], eax    ;書き換え開始オフセットを変数「CodeStart2」として格納
  mov edx, offset CodeEnd
  inc ecx
  
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je ZeroCharaError
  cmp byte ptr [ecx], 20h     ;" "
  je ZeroCharaError
  cmp byte ptr [ecx], 3Bh     ;";"
  je ZeroCharaError
  cmp byte ptr [ecx], 81h     ;全角スペースの可能性
  je ZeroCharaError
  cmp byte ptr [ecx], 2Fh     
  jbe CodeFormatError
  
Code2ndmain:
  mov bl,byte ptr [ecx]
  mov byte ptr [edx],bl
  inc edx
  inc ecx
  cmp byte ptr [ecx], 2Dh     ;"-"         ;コード制御記号認識
  je Code3rd
  cmp byte ptr [ecx], 24h     ;"$"         ;エラー回避用(通常文字列連続処理は使用しない)
  je Code3rdString2
  cmp byte ptr [ecx], 26h     ;"&"         ;コード制御記号認識(XOR処理)
  je CodeXOR
  cmp byte ptr [ecx], 23h     ;"#"         ;コード制御記号認識(リバースエンディアン処理)
  je CodeReverse
  jmp Code2ndmain

CodeReverse:                                ;■■■格納データリバース処理■■■
  mov eax, offset CodeEnd
  call HexAtoHexI
  mov dword ptr [offset CodeEnd2], eax      ;書き換え終了オフセットを変数「CodeEnd2」として格納
  mov ecx,dword ptr [offset CodeEnd2]
  sub ecx,dword ptr [offset CodeStart2]
  inc ecx
  mov dword ptr [offset CharaFlag],ecx 
  mov esi, MemPtr
  add esi, dword ptr [offset CodeEnd2]
  mov edx, offset CodeFill2
 
ReverseFill:
  mov bl, byte ptr [esi]
  mov byte ptr [edx], bl 
  dec esi
  inc edx
  loop ReverseFill
  jmp CheatMain

CodeXOR:                                    ;■■■連続型XOR書き換え処理■■■
  mov eax, offset CodeEnd
  call HexAtoHexI
  mov dword ptr [offset CodeEnd2], eax      ;書き換え終了オフセットを変数「CodeEnd2」として格納
  inc ecx
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je ZeroCharaError
  cmp byte ptr [ecx], 20h     ;" "
  je ZeroCharaError
  cmp byte ptr [ecx], 3Bh     ;";"
  je ZeroCharaError
  cmp byte ptr [ecx], 81h     ;全角スペースの可能性
  je ZeroCharaError
  mov edi, offset CodeFillBuf
  mov esi, offset CodeFill2
  mov dx, word ptr [ecx]
  mov word ptr [edi],dx
  mov eax, edi
  call HexAtoHexI
  mov byte ptr [XORBuf], al
  ;xor ebx,ebx

XorMain2:                         
  mov ebx, MemPtr
  add ebx, dword ptr [CodeStart2]
  mov al, byte ptr [XORBuf]
  xor byte ptr [ebx],al
  mov edi, dword ptr [CodeStart2]
  cmp edi, dword ptr [CodeEnd2]
  ja SerialError                  ;範囲指定ミスなので書き換えしない
  push 0
  push 0
  push dword ptr [CodeStart2]
  push FileHandle
  call SetFilePointer
  push lpOverlapped
  push offset lpNumberOfBytesWritten
  push 1h
  push ebx
  push FileHandle
  Call WriteFile
  cmp eax,0
  jnz XORMain3
  mov dword ptr [CodeErrorMess], offset WriteError2
  call CodeError
  push CheckNoWarning
  push hwnd_
  call IsDlgButtonChecked            ;チェックボタンの状態を取得
  dec eax
  jz BufClearPre
  push mb_okcancel + 30h             ;アイコンを付けるパラメータを追加
  push offset CodeName
  push offset WriteError2
  push hwnd_
  Call MessageBoxA
  cmp eax,idcancel
  je BufClearPre

XORMain3:
  add dword ptr [CodeStart2], 1
  cmp edi, dword ptr [CodeEnd2]
  je BufClearPre
  jmp XORMain2

HexView:                                    ;■■■16進表示型コードの処理■■■
  inc ecx
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je ZeroCharaError
  cmp byte ptr [ecx], 20h     ;" "
  je ZeroCharaError
  cmp byte ptr [ecx], 3Bh     ;";"
  je ZeroCharaError
  cmp byte ptr [ecx], 81h     ;全角スペースの可能性
  je ZeroCharaError
  
HexView2:
  mov bl,byte ptr [ecx]
  mov byte ptr [edx], bl
  inc edx
  inc ecx
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je HexView3
  cmp byte ptr [ecx], 20h     ;" "
  je HexView3
  cmp byte ptr [ecx], 3Bh     ;";"
  je HexView3
  cmp byte ptr [ecx], 81h     ;全角スペースの可能性
  jmp HexView2

HexView3:
  mov eax, offset CodeStart
  call HexAtoHexI
  mov dword ptr [offset CodeStart2], eax
  mov eax,MemPtr
  add eax, dword ptr [CodeStart2]
  mov ecx,10h
  
HexViewLoop:
  movsx edx, byte ptr [eax + 0Fh]
  and edx, 0FFh
  push edx
  dec eax
  loop HexViewLoop
  push dword ptr [offset CodeStart2]
  push offset HexIntFormat
  push offset HexViewBuf
  call _wsprintfA
  add  esp,4Ch
  mov dword ptr [CodeErrorMess],offset HexViewBuf
  call CodeError

  mov eax,MemPtr
  add eax, dword ptr [CodeStart2]
  mov esi,offset HexViewStringBuf
  mov ecx,10h
  
HexViewLoop2:
  mov bl, byte ptr [eax]
  mov byte ptr [esi],bl
  inc esi

  inc eax
  loop HexViewLoop2
  push offset HexViewStringBuf
  push dword ptr [offset CodeStart2]
  push offset HexASCIIFormat
  push offset HexViewBuf2
  call _wsprintfA
  add  esp,10h
  mov dword ptr [CodeErrorMess],offset HexViewBuf2
  call CodeError
  jmp BufClearPre

CodeReplacePre:                            ;■■■置換型ゲーム改造コードの処理■■■
  inc ecx
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je ZeroCharaError
  cmp byte ptr [ecx], 20h     ;" "
  je ZeroCharaError
  cmp byte ptr [ecx], 3Bh     ;";"
  je ZeroCharaError
  cmp byte ptr [ecx], 81h     ;全角スペースの可能性
  je ZeroCharaError
  mov edx, offset ReplaceData

CodeReplace1:
  mov bl,byte ptr [ecx]
  mov byte ptr [edx], bl
  inc edx
  inc ecx
  cmp byte ptr [ecx], 2Dh     ;"-"
  je  CodeReplace2
  cmp byte ptr [ecx], 3Eh     ;">"
  je  CodeFormatError
  jmp CodeReplace1

CodeReplace2:
  push ecx                             ;取得文字列バッファのアドレスを退避
  push offset ReplaceData
  call lstrlenA
  mov dword ptr [offset CharaFlag], eax  ;入力文字数を退避させておき、書き換え時に参照
  shr dword ptr [offset CharaFlag], 1  ;(AtoIで字数半減)入力16進数字列の字数が奇数になることはない
  cmp dword ptr [offset CharaFlag],0
  je ZeroCharaError
  mov ecx, eax                         ;ループカウンタ
  mov esi, offset ReplaceData
  mov edi, offset CodeFillBuf
  mov ebx, offset ReplaceData2
  
CodeReplace3:
  mov dx, word ptr [esi]
  mov word ptr [edi],dx
  mov eax, edi
  call HexAtoHexI
  mov byte ptr [ebx], al   ;置換対象内容の16進値を変数「ReplaceData2」として格納
  inc ebx
  inc esi
  inc esi
  loop CodeReplace3        ;必要回数の倍ループすることになる(問題がないので対処不要)
  pop ecx                  ;取得文字列バッファのアドレスを退避
  inc ecx                  ;"-"の次
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je ZeroCharaError
  cmp byte ptr [ecx], 20h     ;" "
  je ZeroCharaError
  cmp byte ptr [ecx], 3Bh     ;";"
  je ZeroCharaError
  cmp byte ptr [ecx], 81h     ;全角スペースの可能性
  je ZeroCharaError
  mov edx, offset ReplaceFill

CodeReplace4:
  mov bl,byte ptr [ecx]
  mov byte ptr [edx], bl
  inc edx
  inc ecx
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je CodeReplace5
  cmp byte ptr [ecx], 20h     ;" "
  je CodeReplace5
  cmp byte ptr [ecx], 3Bh     ;";"
  je CodeReplace5
  cmp byte ptr [ecx], 81h     ;全角スペースの可能性
  je CodeReplace5
  jmp CodeReplace4

CodeReplace5:
  push offset ReplaceFill
  call lstrlenA
  mov dword ptr [offset CharaFlag2], eax  ;入力文字数を退避させておき、書き換え時に参照
  shr dword ptr [offset CharaFlag2], 1 ;(AtoIで字数半減)入力16進数字列の字数が奇数になることはない
  cmp dword ptr [offset CharaFlag2],0
  je ZeroCharaError
  mov ecx, eax                         ;ループカウンタ(ReplaceDataサイズ/2)
  mov esi, offset ReplaceFill
  mov edi, offset CodeFillBuf
  mov ebx, offset ReplaceFill2
  
CodeReplace6:
  mov dx, word ptr [esi]
  mov word ptr [edi],dx
  mov eax, edi
  call HexAtoHexI
  mov byte ptr [ebx], al   ;書き換え内容の16進値を変数「ReplaceFill2」として格納
  inc ebx
  inc esi
  inc esi
  loop CodeReplace6        ;必要回数の倍ループすることになる(問題がないので対処不要)

CodeReplaceMain:
  push offset ReplaceFill2
  call lstrlenA
  cmp eax, dword ptr [offset CharaFlag]
  jnz CodeReplaceMain2
  jmp CodeReplaceMain3

CodeError PROC
  mov dword ptr [KeyReturn],0A0D0A0Dh
  push offset CodeName
  push 0
  push EM_REPLACESEL
  push hEdit
  call SendMessageA
  push dword ptr [CodeErrorMess]
  push 0
  push EM_REPLACESEL
  push hEdit
  call SendMessageA
  push offset KeyReturn
  push 0
  push EM_REPLACESEL
  push hEdit
  call SendMessageA  ;強制改行
  ret
CodeError ENDP

CodeReplaceMain2:
  mov dword ptr [CodeErrorMess], offset SearchWrong2
  call CodeError
  push CheckNoWarning
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jz CodeReplaceMain3
  push mb_yesno + 20h     ;アイコンを付けるパラメータを追加
  push offset CodeName
  push offset SearchWrong2 
  push hwnd_
  Call MessageBoxA
  cmp eax,idno            ;「いいえ」を押したか?
  je BufClearPre

CodeReplaceMain3:
  mov  edi,MemPtr
  mov  ecx,FileSize
  mov  esi,offset ReplaceData2
  mov  al, byte ptr [esi] 
  jmp SearchLoop

SearchLoopReturn:
  dec ReplacePos 
  mov ecx, FileSize
  sub ecx, ReplacePos
  sub ecx, dword ptr [offset CharaFlag2]
  dec ecx
  mov edi, ReplacePos
  inc edi
  add edi, dword ptr [offset CharaFlag2]
  cmp FileSize,edi
  jbe BufClearPre
  add edi, MemPtr
  mov  esi,offset ReplaceData2
  mov  al, byte ptr [esi] 

SearchLoop:
  repnz scasb                ;置換元データとの一致箇所を探索
  cmp  ecx,0
  jz   SearchError
  push ecx                   ;ファイルサイズ−置換元データと同一箇所の先頭オフセット−1を退避
  push edi
  push esi
  dec  edi
  mov  ecx, dword ptr [offset CharaFlag]
  inc ecx                    ;比較精度を高める安全策(エラー回避に必須)
  repz cmpsb                 ;置換元データとの完全一致を確認
  cmp  ecx,0
  jz   ReplaceDo
  pop  esi
  pop  edi
  pop  ecx
  jmp SearchLoop

SearchError:
  mov dword ptr [CodeErrorMess], offset SearchWrong
  call CodeError
  jmp  CodeError2
 
ReplaceDo:
  pop  esi
  pop  edi
  pop ecx                     ;オフセット復帰       
  dec  edi
  inc  ecx
  mov  eax,FileSize
  sub  eax,ecx
  mov ReplacePos, eax
  push eax
  push offset ReplacePosInfo
  push offset ReplacePosString
  Call _wsprintfA
  add esp,0Ch
  mov dword ptr [CodeErrorMess], offset ReplacePosString
  call CodeError
  push CheckNoWarning
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jz ReplaceDo2            ;CodeError2へのジャンプ不可
  push mb_ok
  push offset CodeName
  push offset ReplacePosString
  push hwnd_
  Call MessageBoxA

ReplaceDo2:  
  push 0
  push 0
  push ReplacePos             ;置換元データと同一箇所のオフセット
  push FileHandle
  call SetFilePointer
  push lpOverlapped
  push offset lpNumberOfBytesWritten
  push dword ptr [offset CharaFlag2]
  push offset ReplaceFill2
  push FileHandle
  Call WriteFile
  cmp eax,0
  jnz SearchLoopReturn
  mov dword ptr [CodeErrorMess], offset WriteError
  call CodeError
  jmp  CodeError2
                                            ;■■■通常のゲーム改造コードの処理■■■
Code3rdPre:
  mov byte ptr [offset SerialMacro], 0      ;">"を用いた連続処理のフラグをクリア
  mov eax, offset CodeStart
  call HexAtoHexI
  mov dword ptr [offset CodeStart2], eax    ;書き換え開始オフセットを変数「CodeStart2」として格納
  mov edx, offset CodeFill
  inc ecx
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je ZeroCharaError
  cmp byte ptr [ecx], 20h     ;" "
  je ZeroCharaError
  cmp byte ptr [ecx], 3Bh     ;";"
  je ZeroCharaError
  cmp byte ptr [ecx], 81h     ;全角スペースの可能性
  je ZeroCharaError
  cmp byte ptr [ecx], 26h     ;"&"         ;コード制御記号認識(XOR処理)
  je CodeFormatError
  cmp byte ptr [ecx], 23h     ;"#"         ;コード制御記号認識(リバースエンディアン処理)
  je CodeFormatError
  jmp Code3rdmain

Code3rd:
  mov eax, offset CodeEnd
  call HexAtoHexI
  mov dword ptr [offset CodeEnd2], eax      ;書き換え終了オフセットを変数「CodeEnd2」として格納
  mov edx, offset CodeFill
  inc ecx
  
Code3rdmain:
  mov bl, byte ptr [ecx]
  mov byte ptr [edx], bl
  inc edx
  inc ecx
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je Code3rdFinish
  cmp byte ptr [ecx], 20h     ;" "
  je Code3rdFinish
  cmp byte ptr [ecx], 3Bh     ;";"
  je Code3rdFinish
  cmp byte ptr [ecx], 81h     ;全角スペースの可能性
  je Code3rdFinish
  cmp byte ptr [ecx], 2Bh     ;"+"
  je AddInt
  jmp Code3rdmain

AddInt:                      ;■■■加算型ゲーム改造コードの処理■■■
  cmp SerialMacro, 1
  je CodeFormatError
  push offset CodeFill
  call lstrlenA
  mov dword ptr [offset CharaFlag], eax  ;入力文字数を退避させておき、書き換え時に参照
  shr dword ptr [offset CharaFlag], 1  ;(AtoIで字数半減)入力16進数字列の字数が奇数になることはない
  cmp dword ptr [offset CharaFlag],0
  je ZeroCharaError
  mov ecx, eax
  mov esi, offset CodeFill
  mov edi, offset CodeFillBuf
  mov ebx, offset CodeFill2
  dec ebx                   ;格納方式を逆にする場合

AddInt2:
  mov eax, esi              ;格納方式を逆にする場合
  add eax, ecx              ;格納方式を逆にする場合
  mov dx, word ptr [eax]    ;格納方式を逆にする場合
  mov word ptr [edi],dx
  mov eax, edi
  call HexAtoHexI
  mov byte ptr [ebx], al    ;書き換え内容の16進値を変数「CodeFill2」として格納
  inc ebx
  dec esi                   ;格納方式を逆にする場合
  loop AddInt2              ;必要回数の倍ループすることになる(問題がないので対処不要)
  mov eax,dword ptr [offset CodeStart2]
  add eax, MemPtr
  mov ecx, dword ptr [eax]
  add dword ptr [offset CodeFill2],ecx
  jmp CheatMain
                                            
Code3rdString1:                             ;■■■文字列型ゲーム改造コードの処理■■■
  mov eax, offset CodeStart
  call HexAtoHexI
  mov dword ptr [offset CodeStart2], eax    ;書き換え開始オフセットを変数「CodeStart2」として格納
  mov edx, offset CodeFill2
  inc ecx
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je ZeroCharaError
  cmp byte ptr [ecx], 3Bh     ;";"
  je ZeroCharaError
  jmp Code3rdStringmain

Code3rdString2:  
  mov eax, offset CodeEnd
  call HexAtoHexI
  mov dword ptr [offset CodeEnd2], eax      ;書き換え終了オフセットを変数「CodeEnd2」として格納
  mov edx, offset CodeFill2
  inc ecx
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je ZeroCharaError
  cmp byte ptr [ecx], 3Bh     ;";"
  je ZeroCharaError

Code3rdStringmain:
  mov bl, byte ptr [ecx]
  mov byte ptr [edx], bl                    ;書き換え内容を変数「CodeFill2」として格納
  inc edx
  inc ecx
  cmp byte ptr [ecx], 00h     ;NULL         ;文字列終了或いはコード制御記号認識
  je Code3rdStringChara
  ;cmp byte ptr [ecx], 20h    ;" "          ;文字列に半角スペースが使われる可能性に対処
  ;je Code3rdStringChara
  cmp byte ptr [ecx], 3Bh    ;";"
  je Code3rdStringChara
  jmp Code3rdStringmain

Code3rdStringChara:
  push offset CodeFill2
  call lstrlenA
  mov dword ptr [offset CharaFlag], eax  ;入力文字数を退避させておき、書き換え時に参照
  cmp dword ptr [offset CharaFlag],0
  je ZeroCharaError
  jmp CheatMain

Code3rdFinish:                ;■■■ファイル書き換え用データを処理■■■
  push offset CodeFill
  call lstrlenA
  mov dword ptr [offset CharaFlag], eax  ;入力文字数を退避させておき、書き換え時に参照
  shr dword ptr [offset CharaFlag], 1  ;(AtoIで字数半減)入力16進数字列の字数が奇数になることはない
  cmp dword ptr [offset CharaFlag],0
  je ZeroCharaError
  mov ecx, eax
  mov esi, offset CodeFill
  mov edi, offset CodeFillBuf
  mov ebx, offset CodeFill2
  ;dec ebx                   ;格納方式を逆にする場合

Code3rdFinish2:
  ;mov eax, esi              ;格納方式を逆にする場合
  ;add eax, ecx              ;格納方式を逆にする場合
  ;mov dx, word ptr [eax]    ;格納方式を逆にする場合
mov dx, word ptr [esi]       ;格納方式を逆にする場合不要
  mov word ptr [edi],dx
  mov eax, edi
  call HexAtoHexI
  mov byte ptr [ebx], al     ;書き換え内容の16進値を変数「CodeFill2」として格納
  inc ebx
  ;dec esi                   ;格納方式を逆にする場合
inc esi                      ;格納方式を逆にする場合不要
inc esi                      ;格納方式を逆にする場合不要
  loop Code3rdFinish2        ;必要回数の倍ループすることになる(問題がないので対処不要)

CheatMain:                   ;■■■ファイル書き換え処理■■■
  cmp SerialMacro, 1
  jz CheatMain2
  push 0
  push 0
  push dword ptr [CodeStart2]
  push FileHandle
  call SetFilePointer
  push lpOverlapped
  push offset lpNumberOfBytesWritten
  push CharaFlag
  push offset CodeFill2
  push FileHandle
  Call WriteFile
  cmp eax,0
  jnz BufClearPre
  mov dword ptr [CodeErrorMess], offset WriteError
  call CodeError
  jmp  CodeError2
 
CheatMain2:                 ;■■■連続型コードのファイル書き換え処理■■■
  mov edi, dword ptr [CodeStart2]
  add edi, dword ptr [offset CharaFlag]
  dec edi
  cmp edi, dword ptr [CodeEnd2]
  ja SerialError
  push 0
  push 0
  push dword ptr [CodeStart2]
  push FileHandle
  call SetFilePointer
  push lpOverlapped
  push offset lpNumberOfBytesWritten
  push CharaFlag
  push offset CodeFill2
  push FileHandle
  Call WriteFile
  cmp eax,0
  jnz CheatMain3
  mov dword ptr [CodeErrorMess], offset WriteError2
  call CodeError
  push CheckNoWarning
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jz BufClearPre
  push mb_okcancel + 30h             ;アイコンを付けるパラメータを追加
  push offset CodeName
  push offset WriteError2
  push hwnd_
  Call MessageBoxA
  cmp eax,idcancel
  je BufClearPre

CheatMain3:
  movsx esi, byte ptr [offset CharaFlag]
  add dword ptr [CodeStart2], esi
  cmp edi, dword ptr [CodeEnd2]
  je BufClearPre
  jmp CheatMain2

CodeFormatError:
  mov dword ptr [CodeErrorMess], offset NGCode
  call CodeError
  
CodeError2: 
  push CheckNoWarning
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jz BufClearPre
  Push mb_ok
  Call MessageBeep
  push mb_ok
  push offset CodeName
  push dword ptr [CodeErrorMess]    ;offset NGCode
  push hwnd_
  Call MessageBoxA
  jmp BufClearPre

ZeroCharaError:
  mov dword ptr [CodeErrorMess], offset CharaZero
  call CodeError
  jmp  CodeError2

SerialError:
  mov dword ptr [CodeErrorMess], offset SerialWrong
  call CodeError
  jmp CodeError2
  
BufClearPre:                                ;■■■書き換え後の後処理■■■
  mov ecx, 40h
  mov ebx, offset CodeFill

BufClear:
  mov dword ptr [ebx],0                     ;変数「CodeFill1」初期化(最適化としてはand命令が適切)
  add ebx, 4
  loop BufClear
  mov ecx, 40h
  mov ebx, offset CodeFill2

BufClear2:
  mov dword ptr [ebx],0                     ;変数「CodeFill2」初期化
  add ebx, 4
  loop BufClear2
  mov ecx, 40h
  mov ebx, offset ReplaceFill

BufClear3:
  mov dword ptr [ebx],0                     ;変数「ReplaceFill」初期化
  add ebx, 4
  loop BufClear3
  mov ecx, 40h
  mov ebx, offset ReplaceFill2

BufClear4:
  mov dword ptr [ebx],0                     ;変数「ReplaceFill2」初期化
  add ebx, 4
  loop BufClear4
  mov ecx, 40h
  mov ebx, offset ReplaceData

BufClear5:
  mov dword ptr [ebx],0                     ;変数「ReplaceData」初期化
  add ebx, 4
  loop BufClear5
  mov ecx, 40h
  mov ebx, offset ReplaceData2

BufClear6:
  mov dword ptr [ebx],0                     ;変数「ReplaceData2」初期化
  add ebx, 4
  loop BufClear6
  
  mov dword ptr [offset CodeStart], 0       ;変数「CodeStart」初期化
  mov dword ptr [offset CodeEnd], 0         ;変数「CodeEnd」初期化
  mov dword ptr [offset CodeStart2], 0      ;変数「CodeStart2」初期化
  mov dword ptr [offset CodeEnd2], 0        ;コード終了オフセット指定なしのケースにも対処
                                              ;8バイトクリアしないと無限書き込みのエラーを招く
  mov dword ptr [offset CodeStart+4], 0       ;変数「CodeStart」初期化
  mov dword ptr [offset CodeEnd+4], 0         ;変数「CodeEnd」初期化
  mov dword ptr [offset CodeStart2+4], 0      ;変数「CodeStart2」初期化
  mov dword ptr [offset CodeEnd2+4], 0        ;コード終了オフセット指定なしのケースにも対処
  mov dword ptr [offset CodeFillBuf], 0
  mov byte ptr [offset SerialMacro], 0
  push offset DirBuffer 
  push 0
  push offset GameCodeCount
  push dword ptr [GameSectionNum]
  call GetPrivateProfileIntA
  mov esi, eax
  inc dword ptr [offset CodeCountBuf2]
  cmp esi, dword ptr [offset CodeCountBuf2]
  jb CheatFinish
  jmp GetCode                               ;次のコードへ

CheatFinish:                                ;■■■全コード処理終了後の処理■■■
  push offset LowDateTime1
  push offset LowDateTime2
  push offset LowDateTime3
  push FileHandle
  call SetFileTime
  push MemPtr
  call GlobalFree
  push FileHandle
  call CloseHandle

CheatFinish2:
  mov dword ptr [CodeErrorMess], offset CheatDone
  call CodeError
  push CheckUseHexEditor   
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jnz CheatFinish2a
  push offset DirBuffer
  push INIBufferSize
  push INIBuffer
  push offset NOkey
  push offset DefKey3
  push offset DefSection
  call GetPrivateProfileStringA
  push 104h                           ;ここではパス名のなので104hに再定義
  push INIBuffer
  push INIBuffer
  call GetShortPathNameA
  push SW_SHOWNORMAL
  push 0
  push offset PathBuffer
  push INIBuffer
  push 0
  push hwnd_
  call ShellExecuteA                   ;ヘキサエディタでファイルを展開

CheatFinish2a:
  push CheckNoWarning
  push hwnd_
  call IsDlgButtonChecked  ;チェックボタンの状態を取得
  dec eax
  jz BacktoDLG
  Push mb_ok
  Call MessageBeep
  push mb_ok - 30h + 40h
  push offset information
  push offset CheatDone                     ;改造完了のメッセージ
  push hwnd_
  Call MessageBoxA
  jmp BacktoDLG

ends                                         ;■■■コード終了■■■
end Start                                    ;■■■コード開始は「Start」から■■■



;このソースが、あなたのゲーム解析スキルアップに役立てば幸いです。