+++ /dev/null
-;=======================================================\r
-;=== C_UTILS.ASM - Asm Utilities for C/C++ ===\r
-;=======================================================\r
-\r
- PAGE 255, 132\r
-\r
- .MODEL Huge\r
-; .286\r
-\r
- ; ==== MACROS ====\r
-\r
- ; macros to PUSH and POP multiple registers\r
-\r
-; PUSHx MACRO R1, R2, R3, R4;, R5, R6, R7, R8\r
-; IFNB <R1>\r
-; push R1 ; Save R1\r
-; PUSHx R2, R3, R4;, R5, R6, R7, R8\r
-; ENDIF\r
-; ENDM\r
-;\r
-; POPx MACRO R1, R2, R3, R4;, R5, R6, R7, R8\r
-; IFNB <R1>\r
-; pop R1 ; Restore R1\r
-; POPx R2, R3, R4;, R5, R6, R7, R8\r
-; ENDIF\r
-; ENDM\r
-\r
- ; Macro to Clear a Register to 0\r
-\r
-CLR MACRO Register\r
- xor Register, Register ; Set Register = 0\r
-ENDM\r
-\r
- ; Macros to Decrement Counter & Jump on Condition\r
-\r
-LOOPx MACRO Register, Destination\r
- dec Register ; Counter--\r
- jnz Destination ; Jump if not 0\r
-ENDM\r
-\r
-LOOPjz MACRO Register, Destination\r
- dec Register ; Counter--\r
- jz Destination ; Jump if 0\r
-ENDM\r
-\r
-\r
- ; ==== General Constants ====\r
-\r
- False EQU 0\r
- True EQU -1\r
- nil EQU 0\r
-\r
- b EQU BYTE PTR\r
- w EQU WORD PTR\r
- d EQU DWORD PTR\r
- o EQU OFFSET\r
- f EQU FAR PTR\r
- s EQU SHORT\r
- ?x4 EQU <?,?,?,?>\r
- ?x3 EQU <?,?,?>\r
- ?x2 EQU <?,?>\r
- ?x1 EQU <?>\r
-\r
-\r
- .Data\r
-\r
- EVEN\r
-\r
-RND_Seed DW 7397, 29447, 802\r
-RND_Mult DW 179, 183, 182\r
-RND_ModV DW 32771, 32779, 32783\r
-\r
-CR_LF DB 13, 10 ; the CRLF data\r
-\r
- .Code\r
-\r
-;===========================================\r
-;void far pascal dos_print (far char *Text)\r
-;===========================================\r
-;\r
-; - Print Text Directly to DOS console w/ CR/LF\r
-;\r
-\r
- PUBLIC DOS_PRINT\r
-\r
-DP_Stack STRUC\r
- DW ?x1 ; DI, SI, DS, BP\r
- DW ?x1 ; DI, SI, DS, BP\r
- DW ?x1 ; DI, SI, DS, BP\r
- DW ?x1 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- DP_Text DD ? ; Far Address of Text to print\r
-DP_Stack ENDS\r
-\r
-\r
-DOS_PRINT PROC FAR\r
-\r
- ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- push bp\r
- push ds\r
- push si\r
- push di\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
-\r
- ; Compute Length of string\r
-\r
- CLR CX ; Length = 0\r
- mov SI, DX ; DS:SI = String data\r
-\r
-@@DP_Scan_it:\r
-\r
- cmp b [SI], 0 ; Null Byte found?\r
- je @@DP_Got_Len ; exit loop if so\r
-\r
- inc CX ; Len++\r
- inc SI ; Point to next char\r
- jmp s @@DP_Scan_it ; check again...\r
-\r
-@@DP_Got_len:\r
-\r
- jcxz @No_Print ; Don't Print if empty\r
-\r
- mov BX, 1 ; 1= DOS Handle for Display\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
-@No_Print:\r
- mov AX, SEG DGROUP ; Restore DGroup\r
- mov DS, AX\r
-\r
- mov DX, o CR_LF ; Get Addr of CR/LF pair\r
- mov CX, 2 ; 2 Characters to Write\r
- mov BX, 1 ; 1= DOS Handle for Display\r
-\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
- cld ; Reset Direction Flag\r
- ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
- pop di\r
- pop si\r
- pop ds\r
- pop bp\r
- ret 4 ; Exit & Clean Up Stack\r
-\r
-DOS_PRINT ENDP\r
-\r
-\r
-;===========================================\r
-;void far pascal dos_prints (char far *Text)\r
-;===========================================\r
-;\r
-; Print Text Directly to DOS console\r
-; without a trailing CR/LF\r
-;\r
-\r
- PUBLIC DOS_PRINTS\r
-\r
-DOS_PRINTS PROC FAR\r
-\r
- ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- push bp\r
- push ds\r
- push si\r
- push di\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
-\r
- ; Compute Length of string\r
-\r
- CLR CX ; Length = 0\r
- mov SI, DX ; DS:SI = String data\r
-\r
-@@DPS_Scan_it:\r
-\r
- cmp b [SI], 0 ; Null Byte found?\r
- je @@DPS_Got_Len ; exit loop if so\r
-\r
- inc CX ; Len++\r
- inc SI ; Point to next char\r
- jmp s @@DPS_Scan_it ; check again...\r
-\r
-@@DPS_Got_len:\r
-\r
- jcxz @DPS_Exit ; Don't Print if empty\r
-\r
- mov BX, 1 ; 1= DOS Handle for Display\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
-@DPS_Exit:\r
- cld ; Reset Direction Flag\r
- ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
- pop di\r
- pop si\r
- pop ds\r
- pop bp\r
- ret 2 ; Exit & Clean Up Stack\r
-\r
-DOS_PRINTS ENDP\r
-\r
-\r
-;=========================================\r
-;void far pascal set_video_mode (int Mode)\r
-;=========================================\r
-;\r
-; Sets the Video Mode through the BIOS\r
-;\r
-\r
- PUBLIC SET_VIDEO_MODE\r
-\r
-SVM_Stack STRUC\r
- DW ?x1 ; DI, SI, DS, BP\r
- DW ?x1 ; DI, SI, DS, BP\r
- DW ?x1 ; DI, SI, DS, BP\r
- DW ?x1 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- SVM_Mode DB ?,? ; Desired Video Mode\r
-SVM_Stack ENDS\r
-\r
-\r
-SET_VIDEO_MODE PROC FAR\r
-\r
- ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- push bp\r
- push ds\r
- push si\r
- push di\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- CLR AH ; Function 0\r
- mov AL, [BP].SVM_Mode ; Get Mode #\r
-\r
- int 10H ; Change Video Modes\r
-\r
-@SVM_Exit:\r
- ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
- pop di\r
- pop si\r
- pop ds\r
- pop bp\r
- ret 2 ; Exit & Clean Up Stack\r
-\r
-SET_VIDEO_MODE ENDP\r
-\r
-\r
-;===================================\r
-;int far pascal scan_keyboard (void)\r
-;===================================\r
-;\r
-; Function to scan keyboard for a pressed key\r
-;\r
-\r
- PUBLIC SCAN_KEYBOARD\r
-\r
-SCAN_KEYBOARD PROC FAR\r
-\r
- ;PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- push bp\r
- push ds\r
- push si\r
- push di\r
-\r
- mov AH, 01H ; Function #1\r
- INT 16H ; Call Keyboard Driver\r
- JZ @SK_NO_KEY ; Exit if Zero flag set\r
-\r
- mov AH, 00H ; Remove Key from Buffer\r
- INT 16H ; Get Keycode in AX\r
-\r
- OR AL, AL ; Low Byte Set (Ascii?)\r
- JZ @SK_Exit ; if not, it's a F-Key\r
-\r
- CLR AH ; Clear ScanCode if Ascii\r
- JMP s @SK_Exit ; Return Key in AX\r
-\r
-@SK_NO_KEY:\r
- CLR AX ; Return Nil (no Keypress)\r
-\r
-@SK_Exit:\r
- cld ; Reset Direction Flag\r
- ;POPx DI, SI, DS, BP ; Restore Saved Registers\r
- pop di\r
- pop si\r
- pop ds\r
- pop bp\r
- ret ; Exit & Clean Up Stack\r
-\r
-SCAN_KEYBOARD ENDP\r
-\r
-\r
-;========================================\r
-;int far pascal random_int (int MaxValue)\r
-;========================================\r
-;\r
-; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
-;\r
-\r
-\r
- PUBLIC RANDOM_INT\r
-\r
-RI_Stack STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- RI_MaxVal DW ? ; Maximum Value to Return + 1\r
-RI_Stack ENDS\r
-\r
-\r
-RANDOM_INT PROC FAR\r
-\r
- push BP ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- CLR BX ; BX is the data index\r
- CLR CX ; CX is the accumulator\r
-\r
-REPT 3\r
- mov AX, RND_Seed[BX] ; load the initial seed\r
- mul RND_Mult[BX] ; multiply it\r
- div RND_ModV[BX] ; and obtain the Mod value\r
- mov RND_Seed[BX], DX ; save that for the next time\r
-\r
- add CX, DX ; add it into the accumulator\r
- inc BX\r
- inc BX ; point to the next set of values\r
-ENDM\r
-\r
- mov AX, CX ; AX = Random #\r
- CLR DX ; DX = 0\r
- div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder\r
-\r
- mov AX, DX\r
-\r
- pop BP ; Restore BP\r
- ret 2 ; back to BASIC with AX holding the result\r
-\r
-RANDOM_INT ENDP\r
-\r
-\r
-;==================================\r
-;void far pascal init_random (void)\r
-;==================================\r
-;\r
-; Scrambles the psuedo-random number sequence\r
-; (XOR's the seed value with the timer)\r
-;\r
-\r
- PUBLIC INIT_RANDOM\r
-\r
-INIT_RANDOM PROC FAR\r
-\r
- CLR AX ; Segment = 0000\r
- mov ES, AX\r
- mov AX, ES:[046Ch] ; Get Timer Lo Word\r
-\r
- xor RND_Seed, AX ; Scramble 1st Seed\r
-\r
- ret ; Exit & Clean Up Stack\r
-\r
-INIT_RANDOM ENDP\r
-\r
-;=========================================\r
-;int far pascal int_sqr (int X, int Round)\r
-;=========================================\r
-;\r
-; Returns the Integer Square Root of (X)\r
-; Round allows the return value to be rounded to the\r
-; nearest integer value by passing 0x80. Passing 0\r
-; return the Integer Portion only. The rounding amound is\r
-; a number from 0 to 1 multiplied by 256, thus\r
-; 0.5 * 0x100 = 0x80!\r
-;\r
-\r
-ISQ_Stack STRUC\r
- DW ?,? ; BP, DI\r
- DD ? ; Caller\r
- ISQ_Round DW ? ; Amount to Round Result * 256\r
- ISQ_X DW ? ; "X"\r
-ISQ_Stack ENDS\r
-\r
- PUBLIC INT_SQR\r
-\r
-INT_SQR PROC FAR\r
-\r
- ;PUSHx BP, DI ; Save BP\r
- push bp\r
- push di\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- xor AX, AX ; {xor eax,eax}\r
- xor DX, DX ; {xor edx,edx}\r
- mov DI, [BP].ISQ_X ; {mov edi,x}\r
-\r
- mov CX, 16 ; {mov cx, 32}\r
-\r
-@ISQ_L:\r
-\r
- shl DI, 1 ; {shl edi,1}\r
- rcl DX, 1 ; {rcl edx,1}\r
- shl DI, 1 ; {shl edi,1}\r
- rcl DX, 1 ; {rcl edx,1}\r
- shl AX, 1 ; {shl eax,1}\r
- mov BX, AX ; {mov ebx,eax}\r
- shl BX, 1 ; {shl ebx,1}\r
- inc BX ; {inc ebx}\r
- cmp DX, BX ; {cmp edx,ebx}\r
- jl @ISQ_S\r
-\r
- sub DX, BX ; {sub edx,ebx}\r
- inc AX ; {inc eax}\r
-\r
-@ISQ_S:\r
- loop @ISQ_L\r
-\r
- add ax, [BP].ISQ_Round ; {add eax,$00008000}\r
- ; {*round* result in hi word: ie. +0.5}\r
- shr ax, 1 ; {shr eax,16} {to ax (result)}\r
- shr ax, 1 ; {shr eax,16} {to ax (result)}\r
- shr ax, 1 ; {shr eax,16} {to ax (result)}\r
- shr ax, 1 ; {shr eax,16} {to ax (result)}\r
- shr ax, 1 ; {shr eax,16} {to ax (result)}\r
- shr ax, 1 ; {shr eax,16} {to ax (result)}\r
- shr ax, 1 ; {shr eax,16} {to ax (result)}\r
- shr ax, 1 ; {shr eax,16} {to ax (result)}\r
-\r
- ;POPx DI, BP ; Restore Registers\r
- pop di\r
- pop bp\r
- ret 4 ; Exit\r
-\r
-INT_SQR ENDP\r
-\r
-;=================================\r
-;int far pascal timer_count (void)\r
-;=================================\r
-;\r
-; Returns the current timer value as an integer/long integer\r
-;\r
-\r
- PUBLIC TIMER_COUNT\r
-\r
-TIMER_COUNT PROC FAR\r
-\r
- CLR AX ; Segment = 0000\r
- mov ES, AX\r
- mov AX, ES:[046Ch] ; Get Timer Lo Word\r
- mov DX, ES:[046Eh] ; Get Timer Hi Word\r
- ret ; Exit & Clean Up Stack\r
-\r
-TIMER_COUNT ENDP\r
-\r
-\r
- END\r