このプロジェクトの主な焦点は、人々がグラフィックを行うことでアセンブリプログラミングを楽しい方法で学ぶことができることでした。このフレームワークは、Windows GUIとダイレクトXプログラミングの燃焼とすべてのボイラープレートのセットアップを削除し、まったく努力せずに画面にピクセルが設定されていることがわかるように、いくつかの指示があるため、走っています。さらに、1990年代のスタイルのグラフィックエフェクトとデモを書くのは楽しいです。
独自のデモシーンを作成するために使用できるテンプレートデモがあります。これを例として、コードを独自のDemosceneディレクトリにコピーすることで使用できます。 * demoscenes yourdemo*すべてのコードはAMD64ディレクトリに移動する必要があります。これは、x86-64アセンブリプロジェクトであるため、使用されるcやその他のランガージュは存在しないはずです。ソースファイルは、ターゲット名を変更するために変更する必要があります。 MakeFileがコピーされますが、Makeファイルを変更しません。プロジェクトを構築するには、 BCZコマンドを使用します。また、ルートディレクトリのBCZを使用してアプリケーションとライブラリを構築するために、 dirsファイルを更新する必要があります。
実装する3つの機能があり、エンジンがあなたを呼び戻すために使用する機能があります。
実装する3つの機能があり、エンジンがゲームのためにあなたを呼び戻すために使用する機能があります。
これらの関数はすべて、 master.incで定義されているmaster_demo_structである単一のパラメーターに渡されます。これには、画面のサイズとその他の情報とともに「デモ」のビデオバッファーが含まれます。
ストライドは、ビデオバッファーの各水平線のバイトの実際の長さであることに注意してください。それには、あなたが描くべきではない隠された部分が含まれています。したがって、幅を使用して描画の境界を計算しますが、ストライドを使用して、ビデオバッファの次の水平線に到達する方法を計算します。ただし、ダブルバッファライブラリを使用してグラフィックを実行し、ダブルバッファーAPIを使用して画面に更新することもできます。
X64揮発性および非揮発性レジスタがあります。 MSDN:https://msdn.microsoft.com/en-us/library/9z1stfyw.aspxでそれらを見ることができます。また、各関数呼び出しは、RSPに合わせて0xfffffffffffffffffffff8に並んで発生します。関数を呼び出すことを計画している場合は、一部の関数ではMOVAPSなどのAlignemntを必要とする命令を使用できると想定するため、スタックを0xffffffffffffffff0に並べる必要があります。スタックが整列されていない場合、いくつかの低機能呼び出しでクラッシュするリスクを実行します。
X86-64の関数呼び出しでは、スタックに4つのパラメーターの場所が予約されている必要があります。すべてのスタック予約は以前に行われます。エンデプログでは、スタックに予約されているスペースの量を追跡することでスタックウォークが機能します。最初の4つのパラメーターは、RCXまたはXMM0、RDXまたはXMM1、R8またはXMM2およびR9またはXMM3です。パラメーターが必要なパラメーターの数に関係なく、必要な4つのスタックの場所を渡すと、4を超える4を超えるパラメーターをスタックに渡す必要があります。また、最初の4つのパラメーターは、レジスタを使用してそれらのパラメーターを渡すため、入力されません。ただし、スペースは、パラメーターが不安定なレジスタにあるため、パラメーターを保存するか、必要なものを保存するためにスペースを使用するために呼び出される関数によって使用できます。
Parameter N (Not Required, must be populated with Nth parameter if exists)
...
Parameter 5 (Not Required, must be populated with 5th parameter if exists)
Parameter 4 (Required, but not populated use register)
Parameter 3 (Required, but not populated use register)
Parameter 2 (Required, but not populated use register)
Parameter 1 (Required, but not populated use register)
Return Address
Save registers
Locals
Parameter Frame for Function Calls in this function.
debug_public.incには2つのデバッグマクロがあります。1つ目はdebug_rsp_check_macroです。デバッグが構築されていない場合は何もしませんが、デバッグが構築された場合は、debugを直接挿入し、rspを確認します。
.ENDPROLOG
DEBUG_RSP_CHECK_MACRO
使用できる次のマクロは、コール命令を使用する代わりにdebug_function_callです。このマクロは、デバッグが有効になっていない場合に単純に呼び出されます。デバッグが有効になると、関数呼び出しの前に不揮発性のレジスタが保存されます。その後、functoinコールが正しいことが確認されます。その後、関数からデータを返すことができるため、RAX/XMM0を除き、ゴミで不揮発性のないすべてのレジスタをゴミを壊します。目標は、揮発性レジスタが保持された情報を想定している場合、これにより、これを行った場合、クラッシュまたはバグを引き起こすことを願っています。
;
; Generate new random color
;
DEBUG_FUNCTION_CALL Math_rand
以下は、ディレクトリ構造のレイアウトを説明しています。
フレームワークには、基本的なルーチン機能を提供することにより、デモビルディングを加速するために使用できるさまざまな機能が含まれています。
dbuffer_create
dbuffer_updatescreen
dbuffer_clearbuffer
dbuffer_free
debug_is_enabled
debug_function_call
debug_rsp_check_macro
Engine_Debug
frameloop_create
frameloop_performframe
frameloop_reset
frameloop_free
soft3d_init
soft3d_setcamerArotation
soft3d_setViewDistance
soft3d_setViewpoint
soft3d_setaspectratio
soft3d_convert3dto2d
soft3d_close
vpal_create
VPAL_SETCOLORINDEX
VPAL_GETCOLORINDEX
vpal_rotate
VPAL_ROTATERESET
vpal_free
prm_drawcircle
prm_drawline
GameEngine_init
gameEngine_printword
gameEngine_loadgif
gameengine_convertimagetosprite
gameEngine_displayfullscreenAnimatedimage
GameEngine_displaycenteredimage
GameEngine_free
inputx64_registerkeypress
inputx64_registerkeyrelease
gif_open
gif_close
gif_numberofimages
gif_getimagesize
GIF_GETIMAGEWIDTH
gif_getimageheight
gif_getimage32bpp
gif_getimage32bpprealtime
gif_getallimage32bpp
以下は、デモでライブラリとフレームワークの機能の一部を使用する方法のコーディング例です。
パレットの作成はシンプルです。色の数を供給し、パレットハンドルとして返品アドレスを保存するだけです。
MOV RCX, 256
DEBUG_FUNCTION_CALL VPal_Create
TEST RAX, RAX
JZ @Failure_Exit
MOV [VirtualPallete], RAX
その後、各色インデックスの色を生成できます。以下の例は、増加する白いパレットを作成します。ダブルバッファーAPIを使用している場合、パレットハンドルを使用して、ApproPraiteの色をビデオバッファーに入力できます。
@CreateWhitePalette:
MOV RAX, R12
MOV AH, AL
SHL RAX, 8
MOV AL, AH
MOV R8, RAX
MOV RDX, R12
MOV RCX, [VirtualPallete]
DEBUG_FUNCTION_CALL VPal_SetColorIndex
INC R12
CMP R12, 256
JB @CreateWhitePalette
ダブルバッファーの作成は、以下に定義するAPIを使用して簡単です。
MOV RDX, 1 ; 1 Byte Per pixels
MOV RCX, RSI ; MASTER_DEMO_STRUCT
DEBUG_FUNCTION_CALL DBuffer_Create
MOV [DoubleBufferPointer], RAX
TEST RAX, RAX
JZ @Failure_Exit
返されたポインターは、指定されたピクセルサイズに基づいて、画面の高さx幅として直接アクセスできます。
MOV RCX, [DoubleBufferPointer]
MOV BYTE PTR [RCX], 10h
画面は、単一の関数呼び出しによって更新できます。
;
; Update the screen with the buffer
;
MOV RCX, [DoubleBufferPointer]
MOV RDX, [VirtualPallete]
MOV R8, DB_FLAG_CLEAR_BUFFER
DEBUG_FUNCTION_CALL Dbuffer_UpdateScreen
ローカルスタックフレームをセットアップする高速かつ簡単な方法を提供するParamhelp_public.incによるDemoscene.incに含まれるマクロと構造が含まれています。覚えておくべきことの1つは、スタックスペースが最近無料であるため、この単純なデモフレームワークで必要としないスタックスペースを予約することで、各スタックを必要なスペースに合わせて調整するよりも時間を節約できます。ただし、実際に使用する予定のレジスタを保存するだけで、実行時間を制限できます。ヘッダーファイルには、レジスタを予約および保存するための構造とマクロを提供することにより、これを支援するマクロがあります。ローカル変数を使用する必要がある場合は、独自の追加構造を作成する必要があり、いくつかのレジスタのみを保存する必要がある場合は、マクロだけでなく手動で保存する必要があります。これまでのところ、すべてのレジスタまたはいくつかの特定のレジスタを保存します。
STD_FUNCTION_STACK_MINは、すべての不揮発性の汎用レジスタおよび関数呼び出しの8つのパラメーターとして定義されます。以下の例は、それを使用して、必要なGPレジスタをいくつか保存していることを示しています。
alloc_stack(SIZEOF STD_FUNCTION_STACK_MIN)
save_reg rdi, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRdi
save_reg rbx, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRbx
save_reg rsi, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRsi
save_reg r12, STD_FUNCTION_STACK_MIN.SaveRegs.SaveR12
.ENDPROLOG
DEBUG_RSP_CHECK_MACRO
... Function Code ...
MOV RSI, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRsi[RSP]
MOV RDI, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRdi[RSP]
MOV rbx, STD_FUNCTION_STACK_MIN.SaveRegs.SaveRbx[RSP]
MOV r12, STD_FUNCTION_STACK_MIN.SaveRegs.SaveR12[RSP]
ADD RSP, SIZE STD_FUNCTION_STACK_MIN
MOV EAX, 1
RET
ただし、すべてのGPレジスタを保存および復元できるマクロがあります。この例を以下に示します。
alloc_stack(SIZEOF STD_FUNCTION_STACK_MIN)
SAVE_ALL_STD_REGS STD_FUNCTION_STACK_MIN
.ENDPROLOG
DEBUG_RSP_CHECK_MACRO
... Function Code ...
RESTORE_ALL_STD_REGS STD_FUNCTION_STACK_MIN
ADD RSP, SIZE STD_FUNCTION_STACK_MIN
MOV EAX, 1
RET
以下は、最小値の定義を示しており、常に2つのバージョンがあります。 1つ目は、現在の関数のスタック割り当てであり、2番目の関数には、発信者から渡されたスタックパラメーターへのアクセスが含まれます。
STD_FUNCTION_STACK_MIN struct
Parameters LOCAL_PARAMETER_FRAME8 <?>
SaveRegs SAVE_REGISTERS_FRAME <?>
Padding dq ?
STD_FUNCTION_STACK_MIN ends
STD_FUNCTION_STACK_MIN_PARAMS struct
Parameters LOCAL_PARAMETER_FRAME8 <?>
SaveRegs SAVE_REGISTERS_FRAME <?>
Padding dq ?
FuncParams FUNCTION_PARAMETERS_FRAME <?>
STD_FUNCTION_STACK_MIN_PARAMS ends
XMMレジスタと、すべてのXMMレジスタを保存および復元するマクロを含むバージョンもあります。ただし、これらの標準構造にはローカル変数はありません。ただし、ローカル変数を定義する必要がある場合は、これらは開始するための優れた構造であり、ローカル変数を追加します。以下の例に示すように、「パディング」変数がパラメーターの場合、または[パラメーターと[保存]登録構造の間にローカル変数を追加します。ローカル変数を追加している場合は、パディング位置を使用できます。保持する必要はありません。アラインメントを維持することはそこにありますが、アライメントの問題を補うためにローカル変数をアレンジすることができます。XMMレジスタを保存するときにMOVAPSにトラップしないようにし、DEBUG_RSP_CHECK_MACROを使用してスタックアライメントが維持されるようにします。マクロテストの施行を行うには、Debug Equ Anabledを使用して実行する必要があります。
DEMO_FUNCTION_STACK_MIN_PARAMS struct
Parameters LOCAL_PARAMETER_FRAME8 <?>
; Local Variables Here
SaveRegs SAVE_REGISTERS_FRAME <?>
; Or Local Variables Here
FuncParams FUNCTION_PARAMETERS_FRAME <?>
DEMO_FUNCTION_STACK_MIN_PARAMS ends