จุดสนใจหลักของโครงการนี้คือเพื่อให้ผู้คนสามารถเรียนรู้การเขียนโปรแกรมแอสเซมบลีด้วยวิธีที่สนุกสนานด้วยการทำกราฟิก เฟรมเวิร์กจะลบเบอร์เดอร์ของการเรียนรู้ Windows GUI และการเขียนโปรแกรม Direct X และการตั้งค่าแผ่นหม้อไอน้ำทั้งหมดและเพียงแค่ตีพื้นทำงานเช่นเดียวกับคำแนะนำบางอย่างที่พวกเขาสามารถเห็นพิกเซลที่ตั้งอยู่บนหน้าจอโดยไม่ต้องใช้ความพยายามมากนัก นอกจากนี้ยังสนุกกับการเขียนเอฟเฟกต์กราฟิกสไตล์และการสาธิตในปี 1990
มีการสาธิตเทมเพลตที่คุณสามารถใช้เพื่อสร้างฉากสาธิตของคุณเอง คุณสามารถใช้สิ่งนี้เป็นตัวอย่างได้โดยการคัดลอกรหัสไปยังไดเรกทอรี demoscene ของคุณเอง * demoscenes yourdemo* รหัสทั้งหมดจะต้องเข้าไปในไดเรกทอรี AMD64 เนื่องจากนี่คือ โครงการแอสเซมบลี x86-64 ไม่ควรมี C หรือ langauges อื่น ๆ ที่ใช้ ไฟล์ แหล่งที่มา จะต้องมีการแก้ไขเพื่อเปลี่ยนชื่อเป้าหมาย MakeFile ถูกคัดลอก แต่คุณไม่ได้แก้ไขไฟล์ Make ในการสร้างโครงการที่คุณใช้คำสั่ง BCZ คุณจะต้องอัปเดตไฟล์ DIRS เพื่อให้แอปพลิเคชันและไลบรารีของคุณสร้างขึ้นโดยใช้ BCZ จากไดเรกทอรีรูท
มีสามฟังก์ชั่นที่จะใช้งานที่เอ็นจิ้นจะใช้เพื่อโทรกลับ
มีสามฟังก์ชั่นในการใช้งานเครื่องยนต์ที่จะใช้เพื่อโทรกลับสำหรับเกม
ฟังก์ชั่นทั้งหมดเหล่านี้จะผ่านพารามิเตอร์เดียวซึ่งเป็น master_demo_struct ตามที่กำหนดไว้ใน Master.inc ซึ่งรวมถึงบัฟเฟอร์วิดีโอสำหรับ "สาธิต" พร้อมกับขนาดของหน้าจอและข้อมูลอื่น ๆ
โปรดทราบว่าการก้าวย่างเป็นความยาวที่แท้จริงในไบต์ของแต่ละเส้นแนวนอนในบัฟเฟอร์วิดีโอ มันมีส่วนที่ซ่อนอยู่ที่คุณไม่ควรวาด ดังนั้นใช้ความกว้างเพื่อคำนวณขอบเขตของการวาด แต่ใช้การก้าวย่างเพื่อคำนวณวิธีการไปยังเส้นแนวนอนถัดไปในบัฟเฟอร์วิดีโอ อย่างไรก็ตามคุณยังสามารถใช้ไลบรารีบัฟเฟอร์คู่เพื่อดำเนินการกราฟิกของคุณและอัปเดตไปยังหน้าจอโดยใช้ Double Buffer API
มีการลงทะเบียน X64 ผันผวนและไม่ระเหย คุณสามารถดูได้ที่ MSDN: https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx นอกจากนี้การโทรแต่ละฟังก์ชั่นจะเกิดขึ้นกับ RSP ที่จัดเรียงเป็น 0xffffffffffffFFFF8 หากคุณวางแผนที่จะโทรหาฟังก์ชั่นใด ๆ คุณต้องจัดเรียงสแต็กเป็น 0xffffffffffffFFF0 เนื่องจากฟังก์ชั่นบางอย่างจะถือว่าพวกเขาสามารถใช้คำแนะนำที่ต้องมีการจัดตำแหน่งเช่น MOVAPS หากสแต็คไม่ได้จัดตำแหน่งคุณจะเสี่ยงต่อการล่มในการโทรฟังก์ชั่นที่ต่ำกว่า
การเรียกใช้ฟังก์ชันใน x86-64 ต้องการให้มี 4 ตำแหน่งพารามิเตอร์ที่สงวนไว้บนสแต็ก การจองสแต็กทั้งหมดจะทำก่อนหน้านี้เพื่อให้การเดินสแต็คสามารถทำงานได้โดยการติดตามปริมาณพื้นที่ที่สงวนไว้บนสแต็ก พารามิเตอร์สี่ตัวแรกคือ RCX หรือ XMM0, RDX หรือ XMM1, R8 หรือ XMM2 และ R9 หรือ XMM3 พารามิเตอร์ที่เกิน 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 แรกคือ debug_rsp_check_macro ซึ่งไม่ได้ทำอะไรเลยถ้าการดีบักไม่ได้ถูกสร้างขึ้น แต่เมื่อสร้างการดีบักคุณจะวางมันโดยตรงหลังจาก.
.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
จากนั้นคุณสามารถสร้างสีสำหรับดัชนีแต่ละสี ตัวอย่างด้านล่างสร้างจานสีขาวที่เพิ่มขึ้น หากคุณใช้ Double Buffer 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
มีมาโครและโครงสร้างที่รวมอยู่ใน demoscene.inc โดย paramhelp_public.inc ที่ให้วิธีที่ง่ายและง่ายดายในการตั้งค่าเฟรมสแต็กท้องถิ่น สิ่งหนึ่งที่ต้องจำไว้คือพื้นที่สแต็กนั้นฟรีในวันนี้ดังนั้นการจองพื้นที่สแต็กที่คุณไม่ต้องการในกรอบการสาธิตแบบง่าย ๆ นี้จะช่วยประหยัดเวลาได้มากกว่าการปรับแต่งแต่ละสแต็กโดยเฉพาะกับพื้นที่ที่คุณต้องการ อย่างไรก็ตามคุณสามารถ จำกัด เวลาการดำเนินการโดยบันทึกเฉพาะการลงทะเบียนที่คุณวางแผนจะใช้ มีมาโครในไฟล์ส่วนหัวเพื่อช่วยในการทำสิ่งนี้โดยการจัดหาโครงสร้างและมาโครเพื่อสำรองและบันทึกการลงทะเบียนของคุณ หากคุณต้องการใช้ตัวแปรท้องถิ่นคุณจะต้องสร้างโครงสร้างเพิ่มเติมของคุณเองและหากคุณต้องการบันทึกเพียงไม่กี่ครั้งที่คุณอาจต้องบันทึกด้วยตนเองและแมโครเท่านั้นที่จะไปไกลและบันทึกการลงทะเบียนทั้งหมดหรือการลงทะเบียนที่เฉพาะเจาะจง
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
ด้านล่างแสดงคำจำกัดความของขั้นต่ำและมีสองเวอร์ชันเสมอ ครั้งแรกคือการจัดสรรสแต็กสำหรับฟังก์ชั่นปัจจุบันและครั้งที่สองรวมถึงการเข้าถึงพารามิเตอร์สแต็กที่ส่งผ่านจากผู้โทร
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 ทั้งหมด อย่างไรก็ตามไม่มีโครงสร้างมาตรฐานเหล่านี้มีตัวแปรท้องถิ่น หากคุณต้องการกำหนดตัวแปรท้องถิ่นสิ่งเหล่านี้เป็นโครงสร้างที่ยอดเยี่ยมในการเริ่มต้นแล้วเพิ่มตัวแปรท้องถิ่นของคุณ ฉันจะเพิ่มตัวแปรในพื้นที่ของคุณไม่ว่าจะเป็นที่ที่ตัวแปร "padding" คือหรือระหว่างพารามิเตอร์และโครงสร้างการลงทะเบียนบันทึกดังแสดงในตัวอย่างด้านล่าง หากคุณกำลังเพิ่มตัวแปรท้องถิ่นคุณสามารถใช้ตำแหน่งการขยายที่ไม่จำเป็นต้องเก็บไว้ มันอยู่ในนั้นเพื่อรักษาการจัดตำแหน่ง แต่คุณสามารถจัดเรียงตัวแปรท้องถิ่นของคุณเพื่อชดเชยปัญหาการจัดตำแหน่งเพียงแค่ตรวจสอบให้แน่ใจว่าคุณไม่ได้ดักจับการเคลื่อนไหวเมื่อบันทึก XMM ลงทะเบียนและใช้ DEBUG_RSP_CHECK_MACRO เพื่อให้แน่ใจว่าการจัดตำแหน่งสแต็ก คุณจะต้องทำงานด้วยการเปิดใช้งาน Debug Equ เพื่อให้มีการบังคับใช้การทดสอบแมโคร
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