From: sparky4 Date: Mon, 23 Nov 2015 22:22:28 +0000 (-0600) Subject: wwww X-Git-Url: http://4ch.mooo.com/gitweb/?a=commitdiff_plain;h=2f38659706ee4cf884c7b4d13449da4f3aaf9a61;hp=ef4d6d862e0ba6315fb942645a044651a2dbdd8a;p=16.git wwww --- diff --git a/src/lib/modex/c_utils.asm b/src/lib/modex/c_utils.asm new file mode 100755 index 00000000..01182013 --- /dev/null +++ b/src/lib/modex/c_utils.asm @@ -0,0 +1,456 @@ +;======================================================= +;=== C_UTILS.ASM - Asm Utilities for C/C++ === +;======================================================= + + PAGE 255, 132 + + .MODEL Huge +; .286 + + ; ==== MACROS ==== + + ; macros to PUSH and POP multiple registers + +; PUSHx MACRO R1, R2, R3, R4;, R5, R6, R7, R8 +; IFNB +; push R1 ; Save R1 +; PUSHx R2, R3, R4;, R5, R6, R7, R8 +; ENDIF +; ENDM +; +; POPx MACRO R1, R2, R3, R4;, R5, R6, R7, R8 +; IFNB +; pop R1 ; Restore R1 +; POPx R2, R3, R4;, R5, R6, R7, R8 +; ENDIF +; ENDM + + ; Macro to Clear a Register to 0 + +CLR MACRO Register + xor Register, Register ; Set Register = 0 +ENDM + + ; Macros to Decrement Counter & Jump on Condition + +LOOPx MACRO Register, Destination + dec Register ; Counter-- + jnz Destination ; Jump if not 0 +ENDM + +LOOPjz MACRO Register, Destination + dec Register ; Counter-- + jz Destination ; Jump if 0 +ENDM + + + ; ==== General Constants ==== + + False EQU 0 + True EQU -1 + nil EQU 0 + + b EQU BYTE PTR + w EQU WORD PTR + d EQU DWORD PTR + o EQU OFFSET + f EQU FAR PTR + s EQU SHORT + ?x4 EQU + ?x3 EQU + ?x2 EQU + ?x1 EQU + + + .Data + + EVEN + +RND_Seed DW 7397, 29447, 802 +RND_Mult DW 179, 183, 182 +RND_ModV DW 32771, 32779, 32783 + +CR_LF DB 13, 10 ; the CRLF data + + .Code + +;=========================================== +;void far pascal dos_print (far char *Text) +;=========================================== +; +; - Print Text Directly to DOS console w/ CR/LF +; + + PUBLIC DOS_PRINT + +DP_Stack STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DD ? ; Caller + DP_Text DD ? ; Far Address of Text to print +DP_Stack ENDS + + +DOS_PRINT PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + mov BP, SP ; Set up Stack Frame + + lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + mov SI, DX ; DS:SI = String data + +@@DP_Scan_it: + + cmp b [SI], 0 ; Null Byte found? + je @@DP_Got_Len ; exit loop if so + + inc CX ; Len++ + inc SI ; Point to next char + jmp s @@DP_Scan_it ; check again... + +@@DP_Got_len: + + jcxz @No_Print ; Don't Print if empty + + mov BX, 1 ; 1= DOS Handle for Display + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + +@No_Print: + mov AX, SEG DGROUP ; Restore DGroup + mov DS, AX + + mov DX, o CR_LF ; Get Addr of CR/LF pair + mov CX, 2 ; 2 Characters to Write + mov BX, 1 ; 1= DOS Handle for Display + + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + + cld ; Reset Direction Flag + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret 4 ; Exit & Clean Up Stack + +DOS_PRINT ENDP + + +;=========================================== +;void far pascal dos_prints (char far *Text) +;=========================================== +; +; Print Text Directly to DOS console +; without a trailing CR/LF +; + + PUBLIC DOS_PRINTS + +DOS_PRINTS PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + mov BP, SP ; Set up Stack Frame + + lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + mov SI, DX ; DS:SI = String data + +@@DPS_Scan_it: + + cmp b [SI], 0 ; Null Byte found? + je @@DPS_Got_Len ; exit loop if so + + inc CX ; Len++ + inc SI ; Point to next char + jmp s @@DPS_Scan_it ; check again... + +@@DPS_Got_len: + + jcxz @DPS_Exit ; Don't Print if empty + + mov BX, 1 ; 1= DOS Handle for Display + mov AH, 40h ; Write Text Function + int 21h ; Call DOS to do it + +@DPS_Exit: + cld ; Reset Direction Flag + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret 2 ; Exit & Clean Up Stack + +DOS_PRINTS ENDP + + +;========================================= +;void far pascal set_video_mode (int Mode) +;========================================= +; +; Sets the Video Mode through the BIOS +; + + PUBLIC SET_VIDEO_MODE + +SVM_Stack STRUC + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DD ? ; Caller + SVM_Mode DB ?,? ; Desired Video Mode +SVM_Stack ENDS + + +SET_VIDEO_MODE PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + mov BP, SP ; Set up Stack Frame + + CLR AH ; Function 0 + mov AL, [BP].SVM_Mode ; Get Mode # + + int 10H ; Change Video Modes + +@SVM_Exit: + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret 2 ; Exit & Clean Up Stack + +SET_VIDEO_MODE ENDP + + +;=================================== +;int far pascal scan_keyboard (void) +;=================================== +; +; Function to scan keyboard for a pressed key +; + + PUBLIC SCAN_KEYBOARD + +SCAN_KEYBOARD PROC FAR + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di + + mov AH, 01H ; Function #1 + INT 16H ; Call Keyboard Driver + JZ @SK_NO_KEY ; Exit if Zero flag set + + mov AH, 00H ; Remove Key from Buffer + INT 16H ; Get Keycode in AX + + OR AL, AL ; Low Byte Set (Ascii?) + JZ @SK_Exit ; if not, it's a F-Key + + CLR AH ; Clear ScanCode if Ascii + JMP s @SK_Exit ; Return Key in AX + +@SK_NO_KEY: + CLR AX ; Return Nil (no Keypress) + +@SK_Exit: + cld ; Reset Direction Flag + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp + ret ; Exit & Clean Up Stack + +SCAN_KEYBOARD ENDP + + +;======================================== +;int far pascal random_int (int MaxValue) +;======================================== +; +; Returns a pseudo-random number in the range of (0.. MaxInt-1) +; + + + PUBLIC RANDOM_INT + +RI_Stack STRUC + DW ? ; BP + DD ? ; Caller + RI_MaxVal DW ? ; Maximum Value to Return + 1 +RI_Stack ENDS + + +RANDOM_INT PROC FAR + + push BP ; Preserve Important Registers + mov BP, SP ; Set up Stack Frame + + CLR BX ; BX is the data index + CLR CX ; CX is the accumulator + +REPT 3 + mov AX, RND_Seed[BX] ; load the initial seed + mul RND_Mult[BX] ; multiply it + div RND_ModV[BX] ; and obtain the Mod value + mov RND_Seed[BX], DX ; save that for the next time + + add CX, DX ; add it into the accumulator + inc BX + inc BX ; point to the next set of values +ENDM + + mov AX, CX ; AX = Random # + CLR DX ; DX = 0 + div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder + + mov AX, DX + + pop BP ; Restore BP + ret 2 ; back to BASIC with AX holding the result + +RANDOM_INT ENDP + + +;================================== +;void far pascal init_random (void) +;================================== +; +; Scrambles the psuedo-random number sequence +; (XOR's the seed value with the timer) +; + + PUBLIC INIT_RANDOM + +INIT_RANDOM PROC FAR + + CLR AX ; Segment = 0000 + mov ES, AX + mov AX, ES:[046Ch] ; Get Timer Lo Word + + xor RND_Seed, AX ; Scramble 1st Seed + + ret ; Exit & Clean Up Stack + +INIT_RANDOM ENDP + +;========================================= +;int far pascal int_sqr (int X, int Round) +;========================================= +; +; Returns the Integer Square Root of (X) +; Round allows the return value to be rounded to the +; nearest integer value by passing 0x80. Passing 0 +; return the Integer Portion only. The rounding amound is +; a number from 0 to 1 multiplied by 256, thus +; 0.5 * 0x100 = 0x80! +; + +ISQ_Stack STRUC + DW ?,? ; BP, DI + DD ? ; Caller + ISQ_Round DW ? ; Amount to Round Result * 256 + ISQ_X DW ? ; "X" +ISQ_Stack ENDS + + PUBLIC INT_SQR + +INT_SQR PROC FAR + + ;PUSHx BP, DI ; Save BP + push bp + push di + mov BP, SP ; Set up Stack Frame + + xor AX, AX ; {xor eax,eax} + xor DX, DX ; {xor edx,edx} + mov DI, [BP].ISQ_X ; {mov edi,x} + + mov CX, 16 ; {mov cx, 32} + +@ISQ_L: + + shl DI, 1 ; {shl edi,1} + rcl DX, 1 ; {rcl edx,1} + shl DI, 1 ; {shl edi,1} + rcl DX, 1 ; {rcl edx,1} + shl AX, 1 ; {shl eax,1} + mov BX, AX ; {mov ebx,eax} + shl BX, 1 ; {shl ebx,1} + inc BX ; {inc ebx} + cmp DX, BX ; {cmp edx,ebx} + jl @ISQ_S + + sub DX, BX ; {sub edx,ebx} + inc AX ; {inc eax} + +@ISQ_S: + loop @ISQ_L + + add ax, [BP].ISQ_Round ; {add eax,$00008000} + ; {*round* result in hi word: ie. +0.5} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + shr ax, 1 ; {shr eax,16} {to ax (result)} + + ;POPx DI, BP ; Restore Registers + pop di + pop bp + ret 4 ; Exit + +INT_SQR ENDP + +;================================= +;int far pascal timer_count (void) +;================================= +; +; Returns the current timer value as an integer/long integer +; + + PUBLIC TIMER_COUNT + +TIMER_COUNT PROC FAR + + CLR AX ; Segment = 0000 + mov ES, AX + mov AX, ES:[046Ch] ; Get Timer Lo Word + mov DX, ES:[046Eh] ; Get Timer Hi Word + ret ; Exit & Clean Up Stack + +TIMER_COUNT ENDP + + + END diff --git a/src/lib/modex/c_utils.h b/src/lib/modex/c_utils.h new file mode 100755 index 00000000..9be6ba2d --- /dev/null +++ b/src/lib/modex/c_utils.h @@ -0,0 +1,117 @@ + +#ifndef __C_UTILS_H +#define __C_UTILS_H + + + /* Misc Constants */ + +#define True -1 +#define False 0 +#define nil 0 + + /* Color Constants */ + +#define c_BLACK 0 +#define c_BLUE 1 +#define c_GREEN 2 +#define c_CYAN 3 +#define c_RED 4 +#define c_PURPLE 5 +#define c_BROWN 6 +#define c_WHITE 7 +#define c_GREY 8 +#define c_bBLUE 9 +#define c_bGREEN 10 +#define c_bCYAN 11 +#define c_bRED 12 +#define c_bPURPLE 13 +#define c_YELLOW 14 +#define c_bWHITE 15 +#define c_BRIGHT 16 + + +#define Ky_F1 0x3B00 +#define Ky_F2 0x3C00 +#define Ky_F3 0x3D00 +#define Ky_F4 0x3E00 +#define Ky_F5 0x3F00 +#define Ky_F6 0x4000 +#define Ky_F7 0x4100 +#define Ky_F8 0x4200 +#define Ky_F9 0x4300 +#define Ky_F10 0x4400 + +#define Ky_Up 0x4800 +#define Ky_Left 0x4B00 +#define Ky_Right 0x4D00 +#define Ky_Down 0x5000 +#define Ky_SUp 0xC800 +#define Ky_SLeft 0xCB00 +#define Ky_SRight 0xCD00 +#define Ky_SDown 0xD000 + +#define Ky_Home 0x4700 +#define Ky_End 0x4F00 +#define Ky_PgUp 0x4900 +#define Ky_PgDn 0x5100 +#define Ky_SHome 0xC700 +#define Ky_SEnd 0xCF00 +#define Ky_SPgUp 0xC900 +#define Ky_SPgDn 0xD100 + +#define Ky_Ins 0x5200 +#define Ky_Del 0x5300 +#define Ky_SIns 0xC200 +#define Ky_SDel 0xC300 + +#define Ky_Tab 0x0009 +#define Ky_RvsTab 0x8F00 +#define Ky_STab 0x8F00 + +#define Ky_BS 0x0008 +#define Ky_CR 0x000D +#define Ky_ESC 0x001B +#define Ky_Clr 0x007F + +#define Ky_Plus 0x002D +#define Ky_Minus 0x002B + +#define Ky_AltA 0x1E00 +#define Ky_AltB 0x3000 +#define Ky_AltC 0x2E00 +#define Ky_AltD 0x2000 +#define Ky_AltE 0x1200 +#define Ky_AltF 0x2100 +#define Ky_AltG 0x2200 +#define Ky_AltH 0x2300 +#define Ky_AltI 0x1700 +#define Ky_AltJ 0x2400 +#define Ky_AltK 0x2500 +#define Ky_AltL 0x2600 +#define Ky_AltM 0x3200 +#define Ky_AltN 0x3100 +#define Ky_AltO 0x1800 +#define Ky_AltP 0x1900 +#define Ky_AltQ 0x1000 +#define Ky_AltR 0x1300 +#define Ky_AltS 0x1F00 +#define Ky_AltT 0x1400 +#define Ky_AltU 0x1600 +#define Ky_AltV 0x2F00 +#define Ky_AltW 0x1100 +#define Ky_AltX 0x2D00 +#define Ky_AltY 0x1500 +#define Ky_AltZ 0x2C00 + + /* .ASM Functions From C_UTILS.ASM */ + +void far pascal dos_print (char far *Text); +void far pascal dos_prints (char far *Text); +void far pascal set_video_mode (int Mode); +int far pascal scan_keyboard (void); +int far pascal random_int (int MaxValue); +void far pascal init_random (void); +int far pascal int_sqr (int X, int Round); +int far pascal timer_count (void); + +#endif diff --git a/src/lib/modex/c_utils.lst b/src/lib/modex/c_utils.lst new file mode 100755 index 00000000..f9664ba0 --- /dev/null +++ b/src/lib/modex/c_utils.lst @@ -0,0 +1,597 @@ +Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Page 1 - 1 + + + ;======================================================= + ;=== C_UTILS.ASM - Asm Utilities for C/C++ === + ;======================================================= + + PAGE 255, 132 + + .MODEL Medium + .286 + + ; ==== MACROS ==== + + ; macros to PUSH and POP multiple registers + + PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + push R1 ; Save R1 + PUSHx R2, R3, R4, R5, R6, R7, R8 + ENDIF + ENDM + + POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 + IFNB + pop R1 ; Restore R1 + POPx R2, R3, R4, R5, R6, R7, R8 + ENDIF + ENDM + + ; Macro to Clear a Register to 0 + + CLR MACRO Register + xor Register, Register ; Set Register = 0 + ENDM + + ; Macros to Decrement Counter & Jump on Condition + + LOOPx MACRO Register, Destination + dec Register ; Counter-- + jnz Destination ; Jump if not 0 + ENDM + + LOOPjz MACRO Register, Destination + dec Register ; Counter-- + jz Destination ; Jump if 0 + ENDM + + + ; ==== General Constants ==== + + = 0000 False EQU 0 + =-0001 True EQU -1 + = 0000 nil EQU 0 + + = BYTE PTR b EQU BYTE PTR + = WORD PTR w EQU WORD PTR + = DWORD PTR d EQU DWORD PTR + = OFFSET o EQU OFFSET + = FAR PTR f EQU FAR PTR + = SHORT s EQU SHORT + = ?,?,?,? ?x4 EQU + = ?,?,? ?x3 EQU + + + 0000 .Data + + EVEN + + 0000 1CE5 7307 0322 RND_Seed DW 7397, 29447, 802 + 0006 00B3 00B7 00B6 RND_Mult DW 179, 183, 182 + 000C 8003 800B 800F RND_ModV DW 32771, 32779, 32783 + + 0012 0D 0A CR_LF DB 13, 10 ; the CRLF data + + 0000 .Code + + ;=========================================== + ;void far pascal dos_print (far char *Text) + ;=========================================== + ; + ; - Print Text Directly to DOS console w/ CR/LF + ; + + PUBLIC DOS_PRINT + + 0010 DP_Stack STRUC + 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0008 00000000 DD ? ; Caller + 000C 00000000 DP_Text DD ? ; Far Address of Text to print + DP_Stack ENDS + + + 0000 DOS_PRINT PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0000 55 1 push BP ; Save R1 + 0001 1E 2 push DS ; Save R1 + 0002 56 3 push SI ; Save R1 + 0003 57 4 push DI ; Save R1 + 0004 8B EC mov BP, SP ; Set up Stack Frame + + 0006 C5 56 0C lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + 0009 33 C9 1 xor CX, CX ; Set Register = 0 + 000B 8B F2 mov SI, DX ; DS:SI = String data + + 000D @@DP_Scan_it: + + 000D 80 3C 00 cmp b [SI], 0 ; Null Byte found? + 0010 74 04 je @@DP_Got_Len ; exit loop if so + + 0012 41 inc CX ; Len++ + 0013 46 inc SI ; Point to next char + 0014 EB F7 jmp s @@DP_Scan_it ; check again... + + 0016 @@DP_Got_len: + + 0016 E3 07 jcxz @No_Print ; Don't Print if empty + + 0018 BB 0001 mov BX, 1 ; 1= DOS Handle for Display + 001B B4 40 mov AH, 40h ; Write Text Function + 001D CD 21 int 21h ; Call DOS to do it + + 001F @No_Print: + 001F B8 ---- R mov AX, SEG DGROUP ; Restore DGroup + 0022 8E D8 mov DS, AX + + 0024 BA 0012 R mov DX, o CR_LF ; Get Addr of CR/LF pair + 0027 B9 0002 mov CX, 2 ; 2 Characters to Write + 002A BB 0001 mov BX, 1 ; 1= DOS Handle for Display + + 002D B4 40 mov AH, 40h ; Write Text Function + 002F CD 21 int 21h ; Call DOS to do it + + 0031 FC cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + 0032 5F 1 pop DI ; Restore R1 + 0033 5E 2 pop SI ; Restore R1 + 0034 1F 3 pop DS ; Restore R1 + 0035 5D 4 pop BP ; Restore R1 + 0036 CA 0004 ret 4 ; Exit & Clean Up Stack + + 0039 DOS_PRINT ENDP + + + ;=========================================== + ;void far pascal dos_prints (char far *Text) + ;=========================================== + ; + ; Print Text Directly to DOS console + ; without a trailing CR/LF + ; + + PUBLIC DOS_PRINTS + + 0039 DOS_PRINTS PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0039 55 1 push BP ; Save R1 + 003A 1E 2 push DS ; Save R1 + 003B 56 3 push SI ; Save R1 + 003C 57 4 push DI ; Save R1 + 003D 8B EC mov BP, SP ; Set up Stack Frame + + 003F C5 56 0C lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor + + ; Compute Length of string + + CLR CX ; Length = 0 + 0042 33 C9 1 xor CX, CX ; Set Register = 0 + 0044 8B F2 mov SI, DX ; DS:SI = String data + + 0046 @@DPS_Scan_it: + + 0046 80 3C 00 cmp b [SI], 0 ; Null Byte found? + 0049 74 04 je @@DPS_Got_Len ; exit loop if so + + 004B 41 inc CX ; Len++ + 004C 46 inc SI ; Point to next char + 004D EB F7 jmp s @@DPS_Scan_it ; check again... + + 004F @@DPS_Got_len: + + 004F E3 07 jcxz @DPS_Exit ; Don't Print if empty + + 0051 BB 0001 mov BX, 1 ; 1= DOS Handle for Display + 0054 B4 40 mov AH, 40h ; Write Text Function + 0056 CD 21 int 21h ; Call DOS to do it + + 0058 @DPS_Exit: + 0058 FC cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + 0059 5F 1 pop DI ; Restore R1 + 005A 5E 2 pop SI ; Restore R1 + 005B 1F 3 pop DS ; Restore R1 + 005C 5D 4 pop BP ; Restore R1 + 005D CA 0002 ret 2 ; Exit & Clean Up Stack + + 0060 DOS_PRINTS ENDP + + + ;========================================= + ;void far pascal set_video_mode (int Mode) + ;========================================= + ; + ; Sets the Video Mode through the BIOS + ; + + PUBLIC SET_VIDEO_MODE + + 000E SVM_Stack STRUC + 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP + 0000 + 0008 00000000 DD ? ; Caller + 000C 00 00 SVM_Mode DB ?,? ; Desired Video Mode + SVM_Stack ENDS + + + 0060 SET_VIDEO_MODE PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0060 55 1 push BP ; Save R1 + 0061 1E 2 push DS ; Save R1 + 0062 56 3 push SI ; Save R1 + 0063 57 4 push DI ; Save R1 + 0064 8B EC mov BP, SP ; Set up Stack Frame + + CLR AH ; Function 0 + 0066 32 E4 1 xor AH, AH ; Set Register = 0 + 0068 8A 46 0C mov AL, [BP].SVM_Mode ; Get Mode # + + 006B CD 10 int 10H ; Change Video Modes + + 006D @SVM_Exit: + POPx DI, SI, DS, BP ; Restore Saved Registers + 006D 5F 1 pop DI ; Restore R1 + 006E 5E 2 pop SI ; Restore R1 + 006F 1F 3 pop DS ; Restore R1 + 0070 5D 4 pop BP ; Restore R1 + 0071 CA 0002 ret 2 ; Exit & Clean Up Stack + + 0074 SET_VIDEO_MODE ENDP + + + ;=================================== + ;int far pascal scan_keyboard (void) + ;=================================== + ; + ; Function to scan keyboard for a pressed key + ; + + PUBLIC SCAN_KEYBOARD + + 0074 SCAN_KEYBOARD PROC FAR + + PUSHx BP, DS, SI, DI ; Preserve Important Registers + 0074 55 1 push BP ; Save R1 + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Page 2 - 1 + + + 0075 1E 2 push DS ; Save R1 + 0076 56 3 push SI ; Save R1 + 0077 57 4 push DI ; Save R1 + + 0078 B4 01 mov AH, 01H ; Function #1 + 007A CD 16 INT 16H ; Call Keyboard Driver + 007C 74 0C JZ @SK_NO_KEY ; Exit if Zero flag set + + 007E B4 00 mov AH, 00H ; Remove Key from Buffer + 0080 CD 16 INT 16H ; Get Keycode in AX + + 0082 0A C0 OR AL, AL ; Low Byte Set (Ascii?) + 0084 74 06 JZ @SK_Exit ; if not, it's a F-Key + + CLR AH ; Clear ScanCode if Ascii + 0086 32 E4 1 xor AH, AH ; Set Register = 0 + 0088 EB 02 JMP s @SK_Exit ; Return Key in AX + + 008A @SK_NO_KEY: + CLR AX ; Return Nil (no Keypress) + 008A 33 C0 1 xor AX, AX ; Set Register = 0 + + 008C @SK_Exit: + 008C FC cld ; Reset Direction Flag + POPx DI, SI, DS, BP ; Restore Saved Registers + 008D 5F 1 pop DI ; Restore R1 + 008E 5E 2 pop SI ; Restore R1 + 008F 1F 3 pop DS ; Restore R1 + 0090 5D 4 pop BP ; Restore R1 + 0091 CB ret ; Exit & Clean Up Stack + + 0092 SCAN_KEYBOARD ENDP + + + ;======================================== + ;int far pascal random_int (int MaxValue) + ;======================================== + ; + ; Returns a pseudo-random number in the range of (0.. MaxInt-1) + ; + + + PUBLIC RANDOM_INT + + 0008 RI_Stack STRUC + 0000 0000 DW ? ; BP + 0002 00000000 DD ? ; Caller + 0006 0000 RI_MaxVal DW ? ; Maximum Value to Return + 1 + RI_Stack ENDS + + + 0092 RANDOM_INT PROC FAR + + 0092 55 push BP ; Preserve Important Registers + 0093 8B EC mov BP, SP ; Set up Stack Frame + + CLR BX ; BX is the data index + 0095 33 DB 1 xor BX, BX ; Set Register = 0 + CLR CX ; CX is the accumulator + 0097 33 C9 1 xor CX, CX ; Set Register = 0 + + REPT 3 + mov AX, RND_Seed[BX] ; load the initial seed + mul RND_Mult[BX] ; multiply it + div RND_ModV[BX] ; and obtain the Mod value + mov RND_Seed[BX], DX ; save that for the next time + + add CX, DX ; add it into the accumulator + inc BX + inc BX ; point to the next set of values + ENDM + 0099 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed + 009D F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it + 00A1 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value + 00A5 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time + 00A9 03 CA 1 add CX, DX ; add it into the accumulator + 00AB 43 1 inc BX + 00AC 43 1 inc BX ; point to the next set of values + 00AD 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed + 00B1 F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it + 00B5 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value + 00B9 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time + 00BD 03 CA 1 add CX, DX ; add it into the accumulator + 00BF 43 1 inc BX + 00C0 43 1 inc BX ; point to the next set of values + 00C1 8B 87 0000 R 1 mov AX, RND_Seed[BX] ; load the initial seed + 00C5 F7 A7 0006 R 1 mul RND_Mult[BX] ; multiply it + 00C9 F7 B7 000C R 1 div RND_ModV[BX] ; and obtain the Mod value + 00CD 89 97 0000 R 1 mov RND_Seed[BX], DX ; save that for the next time + 00D1 03 CA 1 add CX, DX ; add it into the accumulator + 00D3 43 1 inc BX + 00D4 43 1 inc BX ; point to the next set of values + + 00D5 8B C1 mov AX, CX ; AX = Random # + CLR DX ; DX = 0 + 00D7 33 D2 1 xor DX, DX ; Set Register = 0 + 00D9 F7 76 06 div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder + + 00DC 8B C2 mov AX, DX + + 00DE 5D pop BP ; Restore BP + 00DF CA 0002 ret 2 ; back to BASIC with AX holding the result + + 00E2 RANDOM_INT ENDP + + + ;================================== + ;void far pascal init_random (void) + ;================================== + ; + ; Scrambles the psuedo-random number sequence + ; (XOR's the seed value with the timer) + ; + + PUBLIC INIT_RANDOM + + 00E2 INIT_RANDOM PROC FAR + + CLR AX ; Segment = 0000 + 00E2 33 C0 1 xor AX, AX ; Set Register = 0 + 00E4 8E C0 mov ES, AX + 00E6 26: A1 046C mov AX, ES:[046Ch] ; Get Timer Lo Word + + 00EA 31 06 0000 R xor RND_Seed, AX ; Scramble 1st Seed + + 00EE CB ret ; Exit & Clean Up Stack + + 00EF INIT_RANDOM ENDP + + ;========================================= + ;int far pascal int_sqr (int X, int Round) + ;========================================= + ; + ; Returns the Integer Square Root of (X) + ; Round allows the return value to be rounded to the + ; nearest integer value by passing 0x80. Passing 0 + ; return the Integer Portion only. The rounding amound is + ; a number from 0 to 1 multiplied by 256, thus + ; 0.5 * 0x100 = 0x80! + ; + + 000C ISQ_Stack STRUC + 0000 0000 0000 DW ?,? ; BP, DI + 0004 00000000 DD ? ; Caller + 0008 0000 ISQ_Round DW ? ; Amount to Round Result * 256 + 000A 0000 ISQ_X DW ? ; "X" + ISQ_Stack ENDS + + PUBLIC INT_SQR + + 00EF INT_SQR PROC FAR + + PUSHx BP, DI ; Save BP + 00EF 55 1 push BP ; Save R1 + 00F0 57 2 push DI ; Save R1 + 00F1 8B EC mov BP, SP ; Set up Stack Frame + + 00F3 33 C0 xor AX, AX ; {xor eax,eax} + 00F5 33 D2 xor DX, DX ; {xor edx,edx} + 00F7 8B 7E 0A mov DI, [BP].ISQ_X ; {mov edi,x} + + 00FA B9 0010 mov CX, 16 ; {mov cx, 32} + + 00FD @ISQ_L: + + 00FD D1 E7 shl DI, 1 ; {shl edi,1} + 00FF D1 D2 rcl DX, 1 ; {rcl edx,1} + 0101 D1 E7 shl DI, 1 ; {shl edi,1} + 0103 D1 D2 rcl DX, 1 ; {rcl edx,1} + 0105 D1 E0 shl AX, 1 ; {shl eax,1} + 0107 8B D8 mov BX, AX ; {mov ebx,eax} + 0109 D1 E3 shl BX, 1 ; {shl ebx,1} + 010B 43 inc BX ; {inc ebx} + 010C 3B D3 cmp DX, BX ; {cmp edx,ebx} + 010E 7C 03 jl @ISQ_S + + 0110 2B D3 sub DX, BX ; {sub edx,ebx} + 0112 40 inc AX ; {inc eax} + + 0113 @ISQ_S: + 0113 E2 E8 loop @ISQ_L + + 0115 03 46 08 add ax, [BP].ISQ_Round ; {add eax,$00008000} + ; {*round* result in hi word: ie. +0 + .5} + 0118 C1 E8 08 shr ax, 8 ; {shr eax,16} {to ax (result)} + + POPx DI, BP ; Restore Registers + 011B 5F 1 pop DI ; Restore R1 + 011C 5D 2 pop BP ; Restore R1 + 011D CA 0004 ret 4 ; Exit + + 0120 INT_SQR ENDP + + ;================================= + ;int far pascal timer_count (void) + ;================================= + ; + ; Returns the current timer value as an integer/long integer + ; + + PUBLIC TIMER_COUNT + + 0120 TIMER_COUNT PROC FAR + + CLR AX ; Segment = 0000 + 0120 33 C0 1 xor AX, AX ; Set Register = 0 + 0122 8E C0 mov ES, AX + 0124 26: A1 046C mov AX, ES:[046Ch] ; Get Timer Lo Word + 0128 26: 8B 16 046E mov DX, ES:[046Eh] ; Get Timer Hi Word + 012D CB ret ; Exit & Clean Up Stack + + 012E TIMER_COUNT ENDP + + + END + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 3 - 1 + + + + +Macros: + + N a m e Type + +CLR . . . . . . . . . . . . . . Proc +LOOPjz . . . . . . . . . . . . . Proc +LOOPx . . . . . . . . . . . . . Proc +POPx . . . . . . . . . . . . . . Proc +PUSHx . . . . . . . . . . . . . Proc + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 4 - 1 + + + + +Structures and Unions: + + N a m e Size + Offset Type + +DP_Stack . . . . . . . . . . . . 0010 + DP_Text . . . . . . . . . . . 000C DWord +ISQ_Stack . . . . . . . . . . . 000C + ISQ_Round . . . . . . . . . . 0008 Word + ISQ_X . . . . . . . . . . . . 000A Word +RI_Stack . . . . . . . . . . . . 0008 + RI_MaxVal . . . . . . . . . . 0006 Word +SVM_Stack . . . . . . . . . . . 000E + SVM_Mode . . . . . . . . . . . 000C Byte + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 5 - 1 + + + + +Segments and Groups: + + N a m e Size Length Align Combine Class + +C_UTILS_TEXT . . . . . . . . . . 16 Bit 012E Word Public 'CODE' +DGROUP . . . . . . . . . . . . . GROUP +_DATA . . . . . . . . . . . . . 16 Bit 0014 Word Public 'DATA' + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 6 - 1 + + + + +Procedures, parameters and locals: + + N a m e Type Value Attr + +DOS_PRINTS . . . . . . . . . . . P Far 0039 C_UTILS_TEXT Length= 0027 Public +DOS_PRINT . . . . . . . . . . . P Far 0000 C_UTILS_TEXT Length= 0039 Public +INIT_RANDOM . . . . . . . . . . P Far 00E2 C_UTILS_TEXT Length= 000D Public +INT_SQR . . . . . . . . . . . . P Far 00EF C_UTILS_TEXT Length= 0031 Public +RANDOM_INT . . . . . . . . . . . P Far 0092 C_UTILS_TEXT Length= 0050 Public +SCAN_KEYBOARD . . . . . . . . . P Far 0074 C_UTILS_TEXT Length= 001E Public +SET_VIDEO_MODE . . . . . . . . . P Far 0060 C_UTILS_TEXT Length= 0014 Public +TIMER_COUNT . . . . . . . . . . P Far 0120 C_UTILS_TEXT Length= 000E Public + Microsoft (R) Macro Assembler Version 6.11 07/03/14 12:38:18 +c_utils.asm Symbols 7 - 1 + + + + +Symbols: + + N a m e Type Value Attr + +?x3 . . . . . . . . . . . . . . Text ?,?,? +?x4 . . . . . . . . . . . . . . Text ?,?,?,? +@@DPS_Got_len . . . . . . . . . L Near 004F C_UTILS_TEXT +@@DPS_Scan_it . . . . . . . . . L Near 0046 C_UTILS_TEXT +@@DP_Got_len . . . . . . . . . . L Near 0016 C_UTILS_TEXT +@@DP_Scan_it . . . . . . . . . . L Near 000D C_UTILS_TEXT +@CodeSize . . . . . . . . . . . Number 0001h +@DPS_Exit . . . . . . . . . . . L Near 0058 C_UTILS_TEXT +@DataSize . . . . . . . . . . . Number 0000h +@ISQ_L . . . . . . . . . . . . . L Near 00FD C_UTILS_TEXT +@ISQ_S . . . . . . . . . . . . . L Near 0113 C_UTILS_TEXT +@Interface . . . . . . . . . . . Number 0000h +@Model . . . . . . . . . . . . . Number 0004h +@No_Print . . . . . . . . . . . L Near 001F C_UTILS_TEXT +@SK_Exit . . . . . . . . . . . . L Near 008C C_UTILS_TEXT +@SK_NO_KEY . . . . . . . . . . . L Near 008A C_UTILS_TEXT +@SVM_Exit . . . . . . . . . . . L Near 006D C_UTILS_TEXT +@code . . . . . . . . . . . . . Text C_UTILS_TEXT +@data . . . . . . . . . . . . . Text DGROUP +@fardata? . . . . . . . . . . . Text FAR_BSS +@fardata . . . . . . . . . . . . Text FAR_DATA +@stack . . . . . . . . . . . . . Text DGROUP +CR_LF . . . . . . . . . . . . . Byte 0012 _DATA +False . . . . . . . . . . . . . Number 0000h +RND_ModV . . . . . . . . . . . . Word 000C _DATA +RND_Mult . . . . . . . . . . . . Word 0006 _DATA +RND_Seed . . . . . . . . . . . . Word 0000 _DATA +True . . . . . . . . . . . . . . Number -0001h +b . . . . . . . . . . . . . . . Text BYTE PTR +d . . . . . . . . . . . . . . . Text DWORD PTR +f . . . . . . . . . . . . . . . Text FAR PTR +nil . . . . . . . . . . . . . . Number 0000h +o . . . . . . . . . . . . . . . Text OFFSET +s . . . . . . . . . . . . . . . Text SHORT +w . . . . . . . . . . . . . . . Text WORD PTR + + 0 Warnings + 0 Errors diff --git a/src/lib/modex/c_utils.sbr b/src/lib/modex/c_utils.sbr new file mode 100755 index 00000000..0301171b Binary files /dev/null and b/src/lib/modex/c_utils.sbr differ diff --git a/src/lib/modex/makefile b/src/lib/modex/makefile new file mode 100755 index 00000000..fdf9d91c --- /dev/null +++ b/src/lib/modex/makefile @@ -0,0 +1,30 @@ +!ifdef __LINUX__ +REMOVECOMMAND=rm -f +COPYCOMMAND=cp -f +DIRSEP=/ +OBJ=o +!else +REMOVECOMMAND=del +COPYCOMMAND=copy /y +DIRSEP=\ +OBJ=obj +!endif + +CFLAGS=-d2 -0 -mc + +all: x_demo.exe + +x_demo.exe: x_demo.$(OBJ) modex.$(OBJ) c_utils.$(OBJ) + wcl $(CFLAGS) x_demo.$(OBJ) modex.$(OBJ) c_utils.$(OBJ) +x_demo.$(OBJ): x_demo.c + wcl -c $(CFLAGS) x_demo.c + +c_utils.$(OBJ): c_utils.asm + wcl -c $(CFLAGS) c_utils.asm +modex.$(OBJ): modex.asm + wcl -c $(CFLAGS) modex.asm + +clean: .symbolic + @$(REMOVECOMMAND) x-demo.exe + @$(REMOVECOMMAND) *.$(OBJ) + @$(REMOVECOMMAND) *.err diff --git a/src/lib/modex/modex.asm b/src/lib/modex/modex.asm index 2985fd80..f2b1b512 100755 --- a/src/lib/modex/modex.asm +++ b/src/lib/modex/modex.asm @@ -82,16 +82,16 @@ ; READ_DAC_REGISTERS. Expanded CLR Macro ; to handle multiple registers ; - + PAGE 255, 132 - - .MODEL Medium - .286 - + + .MODEL Huge + ;.286 + ; ===== MACROS ===== - + ; Macro to OUT a 16 bit value to an I/O port - + OUT_16 MACRO Register, Value IFDIFI , ; If DX not setup MOV DX, Register ; then Select Register @@ -101,9 +101,9 @@ OUT_16 MACRO Register, Value ENDIF OUT DX, AX ; Set I/O Register(s) ENDM - + ; Macro to OUT a 8 bit value to an I/O Port - + OUT_8 MACRO Register, Value IFDIFI , ; If DX not setup MOV DX, Register ; then Select Register @@ -113,64 +113,63 @@ OUT_8 MACRO Register, Value ENDIF OUT DX, AL ; Set I/O Register ENDM - + ; macros to PUSH and POP multiple registers - -PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 - IFNB - PUSH R1 ; Save R1 - PUSHx R2, R3, R4, R5, R6, R7, R8 - ENDIF -ENDM - -POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 - IFNB - POP R1 ; Restore R1 - POPx R2, R3, R4, R5, R6, R7, R8 - ENDIF -ENDM - + +; PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 +; IFNB +; PUSH R1 ; Save R1 +; PUSHx R2, R3, R4, R5, R6, R7, R8 +; ENDIF +; ENDM +; +; POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 +; IFNB +; POP R1 ; Restore R1 +; POPx R2, R3, R4, R5, R6, R7, R8 +; ENDIF +; ENDM + ; Macro to Clear Registers to 0 - -CLR MACRO Register, R2, R3, R4, R5, R6 - IFNB - XOR Register, Register ; Set Register = 0 - CLR R2, R3, R4, R5, R6 - ENDIF -ENDM - + +; CLR MACRO Register, R2, R3, R4;, R5, R6 +; IFNB +; XOR Register, Register ; Set Register = 0 +; CLR R2, R3, R4;, R5, R6 +; ENDIF +; ENDM + ; Macros to Decrement Counter & Jump on Condition - + LOOPx MACRO Register, Destination DEC Register ; Counter-- JNZ Destination ; Jump if not 0 ENDM - + LOOPjz MACRO Register, Destination DEC Register ; Counter-- JZ Destination ; Jump if 0 ENDM - - + + ; ===== General Constants ===== - + False EQU 0 True EQU -1 nil EQU 0 - + b EQU BYTE PTR w EQU WORD PTR d EQU DWORD PTR o EQU OFFSET f EQU FAR PTR s EQU SHORT - ?x4 EQU - ?x3 EQU - + ?x1 EQU + ; ===== VGA Register Values ===== - + VGA_Segment EQU 0A000h ; Vga Memory Segment - + ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller GC_Index EQU 03CEh ; VGA Graphics Controller SC_Index EQU 03C4h ; VGA Sequencer Controller @@ -179,43 +178,43 @@ ENDM CRTC_Data EQU 03D5h ; VGA CRT Controller Data MISC_OUTPUT EQU 03C2h ; VGA Misc Register INPUT_1 EQU 03DAh ; Input Status #1 Register - + DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W - + PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg READ_MAP EQU 004h ; GC Index: Read Map Register START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo - + MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1 MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1 ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes - + CHAIN4_OFF EQU 00604h ; Chain 4 mode Off ASYNC_RESET EQU 00100h ; (A)synchronous Reset SEQU_RESTART EQU 00300h ; Sequencer Restart - + LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU - + VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane # ALL_PLANES EQU 0Fh ; All Bit Planes Selected CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data - + GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer - + ; Constants Specific for these routines - + NUM_MODES EQU 8 ; # of Mode X Variations - + ; Specific Mode Data Table format... - + Mode_Data_Table STRUC M_MiscR DB ? ; Value of MISC_OUTPUT register M_Pages DB ? ; Maximum Possible # of pages @@ -225,69 +224,69 @@ Mode_Data_Table STRUC M_YMax DW ? ; Maximum Possible Y Size M_CRTC DW ? ; Table of CRTC register values Mode_Data_Table ENDS - + ; ===== DGROUP STORAGE NEEDED (42 BYTES) ===== - + .DATA? - + SCREEN_WIDTH DW 0 ; Width of a line in Bytes SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels - + LAST_PAGE DW 0 ; # of Display Pages PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page - + PAGE_SIZE DW 0 ; Size of Page in Addr Bytes - + DISPLAY_PAGE DW 0 ; Page # currently displayed ACTIVE_PAGE DW 0 ; Page # currently active - + CURRENT_PAGE DW 0 ; Offset of current Page CURRENT_SEGMENT DW 0 ; Segment of VGA memory - + CURRENT_XOFFSET DW 0 ; Current Display X Offset CURRENT_YOFFSET DW 0 ; Current Display Y Offset - + CURRENT_MOFFSET DW 0 ; Current Start Offset - + MAX_XOFFSET DW 0 ; Current Display X Offset MAX_YOFFSET DW 0 ; Current Display Y Offset - + CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127 CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255 - + .CODE - + ; ===== DATA TABLES ===== - + ; Data Tables, Put in Code Segment for Easy Access ; (Like when all the other Segment Registers are in ; use!!) and reduced DGROUP requirements... - + ; Bit Mask Tables for Left/Right/Character Masks - + Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H - + Right_Clip_Mask DB 01H, 03H, 07H, 0FH - + ; Bit Patterns for converting character fonts - + Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH DB 01H,09H,05H,0DH,03H,0BH,07H,0FH - + ; CRTC Register Values for Various Configurations - + MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes DW 04009H ; Cell Height (1 Scan Line) DW 00014H ; Dword Mode off DW 0E317H ; turn on Byte Mode DW nil ; End of CRTC Data for 400/480 Line Mode - + MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes DW 04109H ; Cell Height (2 Scan Lines) DW 00014H ; Dword Mode off DW 0E317H ; turn on Byte Mode DW nil ; End of CRTC Data for 200/240 Line Mode - + MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels DW 05F00H ; Horz total DW 04F01H ; Horz Displayed @@ -296,7 +295,7 @@ MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels DW 05404H ; Start H Sync DW 08005H ; End H Sync DW nil ; End of CRTC Data for 320 Horz pixels - + MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels DW 06B00H ; Horz total DW 05901H ; Horz Displayed @@ -305,7 +304,7 @@ MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels DW 05E04H ; Start H Sync DW 08A05H ; End H Sync DW nil ; End of CRTC Data for 360 Horz pixels - + MODE_200_Tall: MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes DW 0BF06H ; Vertical Total @@ -316,7 +315,7 @@ MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes DW 09615H ; V Blank Start DW 0B916H ; V Blank End DW nil ; End of CRTC Data for 200/400 Lines - + MODE_240_Tall: MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes DW 00D06H ; Vertical Total @@ -327,100 +326,100 @@ MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes DW 0E715H ; V Blank Start DW 00616H ; V Blank End DW nil ; End of CRTC Data for 240/480 Lines - + ; Table of Display Mode Tables - + MODE_TABLE: DW o MODE_320x200, o MODE_320x400 DW o MODE_360x200, o MODE_360x400 DW o MODE_320x240, o MODE_320x480 DW o MODE_360x240, o MODE_360x480 - + ; Table of Display Mode Components - + MODE_320x200: ; Data for 320 by 200 Pixels - + DB 063h ; 400 scan Lines & 25 Mhz Clock DB 4 ; Maximum of 4 Pages DW 320, 200 ; Displayed Pixels (X,Y) DW 1302, 816 ; Max Possible X and Y Sizes - + DW o MODE_320_Wide, o MODE_200_Tall DW o MODE_Double_Line, nil - + MODE_320x400: ; Data for 320 by 400 Pixels - + DB 063h ; 400 scan Lines & 25 Mhz Clock DB 2 ; Maximum of 2 Pages DW 320, 400 ; Displayed Pixels X,Y DW 648, 816 ; Max Possible X and Y Sizes - + DW o MODE_320_Wide, o MODE_400_Tall DW o MODE_Single_Line, nil - + MODE_360x240: ; Data for 360 by 240 Pixels - + DB 0E7h ; 480 scan Lines & 28 Mhz Clock DB 3 ; Maximum of 3 Pages DW 360, 240 ; Displayed Pixels X,Y DW 1092, 728 ; Max Possible X and Y Sizes - + DW o MODE_360_Wide, o MODE_240_Tall DW o MODE_Double_Line , nil - + MODE_360x480: ; Data for 360 by 480 Pixels - + DB 0E7h ; 480 scan Lines & 28 Mhz Clock DB 1 ; Only 1 Page Possible DW 360, 480 ; Displayed Pixels X,Y DW 544, 728 ; Max Possible X and Y Sizes - + DW o MODE_360_Wide, o MODE_480_Tall DW o MODE_Single_Line , nil - + MODE_320x240: ; Data for 320 by 240 Pixels - + DB 0E3h ; 480 scan Lines & 25 Mhz Clock DB 3 ; Maximum of 3 Pages DW 320, 240 ; Displayed Pixels X,Y DW 1088, 818 ; Max Possible X and Y Sizes - + DW o MODE_320_Wide, o MODE_240_Tall DW o MODE_Double_Line, nil - + MODE_320x480: ; Data for 320 by 480 Pixels - + DB 0E3h ; 480 scan Lines & 25 Mhz Clock DB 1 ; Only 1 Page Possible DW 320, 480 ; Displayed Pixels X,Y DW 540, 818 ; Max Possible X and Y Sizes - + DW o MODE_320_WIDE, o MODE_480_Tall DW o MODE_Single_Line, nil - + MODE_360x200: ; Data for 360 by 200 Pixels - + DB 067h ; 400 scan Lines & 28 Mhz Clock DB 3 ; Maximum of 3 Pages DW 360, 200 ; Displayed Pixels (X,Y) DW 1302, 728 ; Max Possible X and Y Sizes - + DW o MODE_360_Wide, MODE_200_Tall DW o MODE_Double_Line, nil - + MODE_360x400: ; Data for 360 by 400 Pixels - + DB 067h ; 400 scan Lines & 28 Mhz Clock DB 1 ; Maximum of 1 Pages DW 360, 400 ; Displayed Pixels X,Y DW 648, 816 ; Max Possible X and Y Sizes - + DW o MODE_360_Wide, MODE_400_Tall DW o MODE_Single_Line, nil - - + + ; ===== MODE X SETUP ROUTINES ===== - + ;====================================================== ;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%) ;====================================================== @@ -445,118 +444,149 @@ MODE_360x400: ; Data for 360 by 400 Pixels ; MaxYpos = The Desired Virtual Screen Height ; Pages = The Desired # of Video Pages ; -; EXIT: AX = Success Flag: 0 = Failure / -1= Success +; EXIT: AX = Success Flag: >0 = Failure / 0 = Success ; - + SVM_STACK STRUC SVM_Table DW ? ; Offset of Mode Info Table - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP DD ? ; Caller SVM_Pages DW ? ; # of Screen Pages desired SVM_Ysize DW ? ; Vertical Screen Size Desired SVM_Xsize DW ? ; Horizontal Screen Size Desired SVM_Mode DW ? ; Display Resolution Desired SVM_STACK ENDS - + PUBLIC SET_VGA_MODEX - + SET_VGA_MODEX PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 2 ; Allocate workspace MOV BP, SP ; Set up Stack Frame - + ; Check Legality of Mode Request.... - + MOV BX, [BP].SVM_Mode ; Get Requested Mode # CMP BX, NUM_MODES ; Is it 0..7? - JAE @SVM_BadModeSetup ; If Not, Error out - + JAE @SVM_BadModeSetup1 ; If Not, Error out + SHL BX, 1 ; Scale BX MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info MOV [BP].SVM_Table, SI ; Save ptr for later use - + ; Check # of Requested Display Pages - + MOV CX, [BP].SVM_Pages ; Get # of Requested Pages - CLR CH ; Set Hi Word = 0! + ;CLR CH ; Set Hi Word = 0! + mov ch,0 ; Set Hi Word = 0! CMP CL, CS:[SI].M_Pages ; Check # Pages for mode - JA @SVM_BadModeSetup ; Report Error if too Many Pages - JCXZ @SVM_BadModeSetup ; Report Error if 0 Pages - + JA @SVM_BadModeSetup2 ; Report Error if too Many Pages + JCXZ @SVM_BadModeSetup3 ; Report Error if 0 Pages + ; Check Validity of X Size - + AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0 - + MOV AX, [BP].SVM_XSize ; Get Logical Screen Width CMP AX, CS:[SI].M_XSize ; Check against Displayed X - JB @SVM_BadModeSetup ; Report Error if too small + JB @SVM_BadModeSetup4 ; Report Error if too small CMP AX, CS:[SI].M_XMax ; Check against Max X - JA @SVM_BadModeSetup ; Report Error if too big - + JA @SVM_BadModeSetup5 ; Report Error if too big + ; Check Validity of Y Size - + MOV BX, [BP].SVM_YSize ; Get Logical Screen Height CMP BX, CS:[SI].M_YSize ; Check against Displayed Y - JB @SVM_BadModeSetup ; Report Error if too small + JB @SVM_BadModeSetup6 ; Report Error if too small CMP BX, CS:[SI].M_YMax ; Check against Max Y - JA @SVM_BadModeSetup ; Report Error if too big - + JA @SVM_BadModeSetup7 ; Report Error if too big + ; Enough memory to Fit it all? - - SHR AX, 2 ; # of Bytes:Line = XSize/4 + + SHR AX, 1 ; # of Bytes:Line = XSize/4 + SHR AX, 1 ; # of Bytes:Line = XSize/4 MUL CX ; AX = Bytes/Line * Pages MUL BX ; DX:AX = Total VGA mem needed JNO @SVM_Continue ; Exit if Total Size > 256K - + DEC DX ; Was it Exactly 256K??? OR DX, AX ; (DX = 1, AX = 0000) JZ @SVM_Continue ; if so, it's valid... - + + jmp @SVM_Continue;0000 + @SVM_BadModeSetup: - - CLR AX ; Return Value = False + mov ax,8 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup1: + mov ax,1 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup2: + mov ax,2 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup3: + mov ax,3 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup4: + mov ax,4 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup5: + mov ax,5 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup6: + mov ax,6 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup7: + mov ax,7 ; Return Value = False JMP @SVM_Exit ; Normal Exit - + @SVM_Continue: - + MOV AX, 13H ; Start with Mode 13H INT 10H ; Let BIOS Set Mode - + OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ... - + OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register INC DX ; Point to Data IN AL, DX ; Get Value, Bit 7 = Protect AND AL, 7FH ; Mask out Write Protect OUT DX, AL ; And send it back - + MOV DX, CRTC_INDEX ; Vga Crtc Registers ADD SI, M_CRTC ; SI -> CRTC Parameter Data - + ; Load Tables of CRTC Parameters from List of Tables - + @SVM_Setup_Table: - + MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl ADD SI, 2 ; Point to next Ptr Entry OR DI, DI ; A nil Ptr means that we have JZ @SVM_Set_Data ; finished CRTC programming - + @SVM_Setup_CRTC: MOV AX, CS:[DI] ; Get CRTC Data from Table ADD DI, 2 ; Advance Pointer OR AX, AX ; At End of Data Table? JZ @SVM_Setup_Table ; If so, Exit & get next Table - + OUT DX, AX ; Reprogram VGA CRTC reg JMP s @SVM_Setup_CRTC ; Process Next Table Entry - + ; Initialize Page & Scroll info, DI = 0 - + @SVM_Set_Data: MOV DISPLAY_PAGE, DI ; Display Page = 0 MOV ACTIVE_PAGE, DI ; Active Page = 0 @@ -564,88 +594,93 @@ SET_VGA_MODEX PROC FAR MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0 MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0 MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0 - + MOV AX, VGA_SEGMENT ; Segment for VGA memory MOV CURRENT_SEGMENT, AX ; Save for Future LES's - + ; Set Logical Screen Width, X Scroll and Our Data - + MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info MOV AX, [BP].SVM_Xsize ; Get Display Width - + MOV CX, AX ; CX = Logical Width SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value MOV MAX_XOFFSET, CX ; Set Maximum X Scroll - - SHR AX, 2 ; Bytes = Pixels / 4 + + SHR AX, 1 ; Bytes = Pixels / 4 + SHR AX, 1 ; Bytes = Pixels / 4 MOV SCREEN_WIDTH, AX ; Save Width in Pixels - + SHR AX, 1 ; Offset Value = Bytes / 2 MOV AH, 13h ; CRTC Offset Register Index XCHG AL, AH ; Switch format for OUT OUT DX, AX ; Set VGA CRTC Offset Reg - + ; Setup Data table, Y Scroll, Misc for Other Routines - + MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height - + MOV CX, AX ; CX = Logical Height SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll - + MOV SCREEN_HEIGHT, AX ; Save Height in Pixels MUL SCREEN_WIDTH ; AX = Page Size in Bytes, MOV PAGE_SIZE, AX ; Save Page Size - + MOV CX, [BP].SVM_Pages ; Get # of Pages MOV LAST_PAGE, CX ; Save # of Pages - - CLR BX ; Page # = 0 + + mov bx,0 ; Page # = 0 MOV DX, BX ; Page 0 Offset = 0 - + @SVM_Set_Pages: - + MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset ADD BX, 2 ; Page#++ ADD DX, AX ; Compute Addr of Next Page LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set - + ; Clear VGA Memory - + OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes LES DI, d CURRENT_PAGE ; -> Start of VGA memory - - CLR AX ; AX = 0 + + mov ax,0 ; AX = 0 CLD ; Block Xfer Forwards MOV CX, 8000H ; 32K * 4 * 2 = 256K REP STOSW ; Clear dat memory! - + ; Setup Font Pointers - + MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127 MOV AX, GET_CHAR_PTR ; Service to Get Pointer INT 10h ; Call VGA BIOS - + MOV CHARSET_LOW, BP ; Save Char Set Offset MOV CHARSET_LOW+2, ES ; Save Char Set Segment - + MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255 MOV AX, GET_CHAR_PTR ; Service to Get Pointer INT 10h ; Call VGA BIOS - + MOV CHARSET_HI, BP ; Save Char Set Offset MOV CHARSET_HI+2, ES ; Save Char Set Segment - + MOV AX, True ; Return Success Code - + @SVM_EXIT: ADD SP, 2 ; Deallocate workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 8 ; Exit & Clean Up Stack - + SET_VGA_MODEX ENDP - - + + ;================== ;SET_MODEX% (Mode%) ;================== @@ -657,47 +692,51 @@ SET_VGA_MODEX ENDP ; ; EXIT: AX = Success Flag: 0 = Failure / -1= Success ; - + SM_STACK STRUC DW ?,? ; BP, SI DD ? ; Caller SM_Mode DW ? ; Desired Screen Resolution SM_STACK ENDS - + PUBLIC SET_MODEX - + SET_MODEX PROC FAR - - PUSHx BP, SI ; Preserve Important registers + + ;PUSHx BP, SI ; Preserve Important registers + push bp + push si MOV BP, SP ; Set up Stack Frame - - CLR AX ; Assume Failure + + mov ax,0 ; Assume Failure MOV BX, [BP].SM_Mode ; Get Desired Mode # CMP BX, NUM_MODES ; Is it a Valid Mode #? JAE @SMX_Exit ; If Not, don't Bother - + PUSH BX ; Push Mode Parameter - + SHL BX, 1 ; Scale BX to word Index MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info - + PUSH CS:[SI].M_XSize ; Push Default X Size PUSH CS:[SI].M_Ysize ; Push Default Y size MOV AL, CS:[SI].M_Pages ; Get Default # of Pages - CLR AH ; Hi Byte = 0 + mov ah,0 ; Hi Byte = 0 PUSH AX ; Push # Pages - + CALL f SET_VGA_MODEX ; Set up Mode X! - + @SMX_Exit: - POPx SI, BP ; Restore Registers + ;POPx SI, BP ; Restore Registers + pop si + pop bp RET 2 ; Exit & Clean Up Stack - + SET_MODEX ENDP - - + + ; ===== BASIC GRAPHICS PRIMITIVES ===== - + ;============================ ;CLEAR_VGA_SCREEN (ColorNum%) ;============================ @@ -708,37 +747,41 @@ SET_MODEX ENDP ; ; EXIT: No meaningful values returned ; - + CVS_STACK STRUC DW ?,? ; DI, BP DD ? ; Caller CVS_COLOR DB ?,? ; Color to Set Screen to CVS_STACK ENDS - + PUBLIC CLEAR_VGA_SCREEN - + CLEAR_VGA_SCREEN PROC FAR - - PUSHx BP, DI ; Preserve Important Registers + + ;PUSHx BP, DI ; Preserve Important Registers + push bp + push di MOV BP, SP ; Set up Stack Frame - + OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AL, [BP].CVS_COLOR ; Get Color MOV AH, AL ; Copy for Word Write CLD ; Block fill Forwards - + MOV CX, PAGE_SIZE ; Get Size of Page SHR CX, 1 ; Divide by 2 for Words REP STOSW ; Block Fill VGA memory - - POPx DI, BP ; Restore Saved Registers + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp RET 2 ; Exit & Clean Up Stack - + CLEAR_VGA_SCREEN ENDP - - + + ;=================================== ;SET_POINT (Xpos%, Ypos%, ColorNum%) ;=================================== @@ -751,7 +794,7 @@ CLEAR_VGA_SCREEN ENDP ; ; EXIT: No meaningful values returned ; - + SP_STACK STRUC DW ?,? ; BP, DI DD ? ; Caller @@ -759,38 +802,43 @@ SP_STACK STRUC SETP_Ypos DW ? ; Y pos of Point to Plot SETP_Xpos DW ? ; X pos of Point to Plot SP_STACK ENDS - + PUBLIC SET_POINT - + SET_POINT PROC FAR - - PUSHx BP, DI ; Preserve Registers + + ;PUSHx BP, DI ; Preserve Registers + push bp + push di MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel MUL SCREEN_WIDTH ; Get Offset to Start of Line - + MOV BX, [BP].SETP_Xpos ; Get Xpos MOV CX, BX ; Copy to extract Plane # from - SHR BX, 2 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 ADD BX, AX ; Offset = Width*Ypos + Xpos/4 - + MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register AND CL, PLANE_BITS ; Get Plane Bits SHL AH, CL ; Get Plane Select Value OUT_16 SC_Index, AX ; Select Plane - + MOV AL,[BP].SETP_Color ; Get Pixel Color MOV ES:[DI+BX], AL ; Draw Pixel - - POPx DI, BP ; Restore Saved Registers + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp RET 6 ; Exit and Clean up Stack - + SET_POINT ENDP - - + + ;========================== ;READ_POINT% (Xpos%, Ypos%) ;========================== @@ -802,45 +850,50 @@ SET_POINT ENDP ; ; EXIT: AX = Color of Pixel at (Xpos, Ypos) ; - + RP_STACK STRUC DW ?,? ; BP, DI DD ? ; Caller RP_Ypos DW ? ; Y pos of Point to Read RP_Xpos DW ? ; X pos of Point to Read RP_STACK ENDS - + PUBLIC READ_POINT - + READ_POINT PROC FAR - - PUSHx BP, DI ; Preserve Registers + + ;PUSHx BP, DI ; Preserve Registers + push bp + push di MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AX, [BP].RP_Ypos ; Get Line # of Pixel MUL SCREEN_WIDTH ; Get Offset to Start of Line - + MOV BX, [BP].RP_Xpos ; Get Xpos MOV CX, BX - SHR BX, 2 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 ADD BX, AX ; Offset = Width*Ypos + Xpos/4 - + MOV AL, READ_MAP ; GC Read Mask Register MOV AH, CL ; Get Xpos AND AH, PLANE_BITS ; & mask out Plane # OUT_16 GC_INDEX, AX ; Select Plane to read in - - CLR AH ; Clear Return Value Hi byte + + mov ah,0 ; Clear Return Value Hi byte MOV AL, ES:[DI+BX] ; Get Color of Pixel - - POPx DI, BP ; Restore Saved Registers + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp RET 4 ; Exit and Clean up Stack - + READ_POINT ENDP - - + + ;====================================================== ;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) ;====================================================== @@ -855,9 +908,12 @@ READ_POINT ENDP ; ; EXIT: No meaningful values returned ; - + FB_STACK STRUC - DW ?x4 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller FB_Color DB ?,? ; Fill Color FB_Ypos2 DW ? ; Y pos of Lower Right Pixel @@ -865,154 +921,160 @@ FB_STACK STRUC FB_Ypos1 DW ? ; Y pos of Upper Left Pixel FB_Xpos1 DW ? ; X pos of Upper Left Pixel FB_STACK ENDS - + PUBLIC FILL_BLOCK - + FILL_BLOCK PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page CLD ; Direction Flag = Forward - + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select - + ; Validate Pixel Coordinates ; If necessary, Swap so X1 <= X2, Y1 <= Y2 - + MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2? MOV BX, [BP].FB_Ypos2 ; BX = Y2 CMP AX, BX JLE @FB_NOSWAP1 - + MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1 XCHG AX, BX ; on stack for future use - + @FB_NOSWAP1: SUB BX, AX ; Get Y width INC BX ; Add 1 to avoid 0 value MOV [BP].FB_Ypos2, BX ; Save in Ypos2 - + MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line ADD DI, AX ; DI = Start of Line Y1 - + MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2 MOV BX, [BP].FB_Xpos2 ; CMP AX, BX JLE @FB_NOSWAP2 ; Skip Ahead if Ok - + MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2 XCHG AX, BX ; on stack for future use - + ; All our Input Values are in order, Now determine ; How many full "bands" 4 pixels wide (aligned) there ; are, and if there are partial bands (<4 pixels) on ; the left and right edges. - + @FB_NOSWAP2: MOV DX, AX ; DX = X1 (Pixel Position) - SHR DX, 2 ; DX/4 = Bytes into Line + SHR DX, 1 ; DX/4 = Bytes into Line + SHR DX, 1 ; DX/4 = Bytes into Line ADD DI, DX ; DI = Addr of Upper-Left Corner - + MOV CX, BX ; CX = X2 (Pixel Position) - SHR CX, 2 ; CX/4 = Bytes into Line - + SHR CX, 1 ; CX/4 = Bytes into Line + SHR CX, 1 ; CX/4 = Bytes into Line + CMP DX, CX ; Start and end in same band? JNE @FB_NORMAL ; if not, check for l & r edges JMP @FB_ONE_BAND_ONLY ; if so, then special processing - + @FB_NORMAL: SUB CX, DX ; CX = # bands -1 MOV SI, AX ; SI = PLANE#(X1) AND SI, PLANE_BITS ; if Left edge is aligned then JZ @FB_L_PLANE_FLUSH ; no special processing.. - + ; Draw "Left Edge" vertical strip of 1-3 pixels... - + OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask - + MOV SI, DI ; SI = Copy of Start Addr (UL) - + MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw MOV AL, [BP].FB_Color ; Get Fill Color MOV BX, SCREEN_WIDTH ; Get Vertical increment Value - + @FB_LEFT_LOOP: MOV ES:[SI], AL ; Fill in Left Edge Pixels ADD SI, BX ; Point to Next Line (Below) LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn - + MOV ES:[SI], AL ; Fill in Left Edge Pixels ADD SI, BX ; Point to Next Line (Below) LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn - + @FB_LEFT_CONT: - + INC DI ; Point to Middle (or Right) Block DEC CX ; Reset CX instead of JMP @FB_RIGHT - + @FB_L_PLANE_FLUSH: INC CX ; Add in Left band to middle block - + ; DI = Addr of 1st middle Pixel (band) to fill ; CX = # of Bands to fill -1 - + @FB_RIGHT: MOV SI, [BP].FB_Xpos2 ; Get Xpos2 AND SI, PLANE_BITS ; Get Plane values CMP SI, 0003 ; Plane = 3? JE @FB_R_EDGE_FLUSH ; Hey, add to middle - + ; Draw "Right Edge" vertical strip of 1-3 pixels... - + OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask - + MOV SI, DI ; Get Addr of Left Edge ADD SI, CX ; Add Width-1 (Bands) DEC SI ; To point to top of Right Edge - + MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw MOV AL, [BP].FB_Color ; Get Fill Color MOV BX, SCREEN_WIDTH ; Get Vertical increment Value - + @FB_RIGHT_LOOP: MOV ES:[SI], AL ; Fill in Right Edge Pixels ADD SI, BX ; Point to Next Line (Below) LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn - + MOV ES:[SI], AL ; Fill in Right Edge Pixels ADD SI, BX ; Point to Next Line (Below) LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn - + @FB_RIGHT_CONT: - + DEC CX ; Minus 1 for Middle bands JZ @FB_EXIT ; Uh.. no Middle bands... - + @FB_R_EDGE_FLUSH: - + ; DI = Addr of Upper Left block to fill ; CX = # of Bands to fill in (width) - + OUT_8 SC_Data, ALL_PLANES ; Write to All Planes - + MOV DX, SCREEN_WIDTH ; DX = DI Increment SUB DX, CX ; = Screen_Width-# Planes Filled - + MOV BX, CX ; BX = Quick Refill for CX MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill MOV AL, [BP].FB_Color ; Get Fill Color - + @FB_MIDDLE_LOOP: REP STOSB ; Fill in entire line - + MOV CX, BX ; Recharge CX (Line Width) ADD DI, DX ; Point to start of Next Line LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn - + JMP s @FB_EXIT ; Outa here - + @FB_ONE_BAND_ONLY: MOV SI, AX ; Get Left Clip Mask, Save X1 AND SI, PLANE_BITS ; Mask out Row # @@ -1020,29 +1082,33 @@ FILL_BLOCK PROC FAR MOV SI, BX ; Get Right Clip Mask, Save X2 AND SI, PLANE_BITS ; Mask out Row # AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte - + OUT_8 SC_Data, AL ; Clip For Left & Right Masks - + MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw MOV AL, [BP].FB_Color ; Get Fill Color MOV BX, SCREEN_WIDTH ; Get Vertical increment Value - + @FB_ONE_LOOP: MOV ES:[DI], AL ; Fill in Pixels ADD DI, BX ; Point to Next Line (Below) LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn - + MOV ES:[DI], AL ; Fill in Pixels ADD DI, BX ; Point to Next Line (Below) LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn - + @FB_EXIT: - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 10 ; Exit and Clean up Stack - + FILL_BLOCK ENDP - - + + ;===================================================== ;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) ;===================================================== @@ -1057,9 +1123,11 @@ FILL_BLOCK ENDP ; ; EXIT: No meaningful values returned ; - + DL_STACK STRUC - DW ?x3 ; DI, SI, BP + DW ?x1 ; DI, SI, BP + DW ?x1 ; DI, SI, BP + DW ?x1 ; DI, SI, BP DD ? ; Caller DL_ColorF DB ?,? ; Line Draw Color DL_Ypos2 DW ? ; Y pos of last point @@ -1067,249 +1135,256 @@ DL_STACK STRUC DL_Ypos1 DW ? ; Y pos of first point DL_Xpos1 DW ? ; X pos of first point DL_STACK ENDS - + PUBLIC DRAW_LINE - + DRAW_LINE PROC FAR - - PUSHx BP, SI, DI ; Preserve Important Registers + + ;PUSHx BP, SI, DI ; Preserve Important Registers + push bp + push si + push di MOV BP, SP ; Set up Stack Frame CLD ; Direction Flag = Forward - + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select MOV CH, [BP].DL_ColorF ; Save Line Color in CH - + ; Check Line Type - + MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2? MOV DI, [BP].DL_Xpos2 ; DX = X2 CMP SI, DI ; Is X1 < X2 JE @DL_VLINE ; If X1=X2, Draw Vertical Line JL @DL_NOSWAP1 ; If X1 < X2, don't swap - + XCHG SI, DI ; X2 IS > X1, SO SWAP THEM - + @DL_NOSWAP1: - + ; SI = X1, DI = X2 - + MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2? CMP AX, [BP].DL_Ypos2 ; Y1 = Y2? JE @DL_HORZ ; If so, Draw a Horizontal Line - + JMP @DL_BREZHAM ; Diagonal line... go do it... - + ; This Code draws a Horizontal Line in Mode X where: ; SI = X1, DI = X2, and AX = Y1/Y2 - + @DL_HORZ: - + MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width MOV DX, AX ; CX = Line offset into Page - + MOV AX, SI ; Get Left edge, Save X1 AND SI, PLANE_BITS ; Mask out Row # MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask MOV CX, DI ; Get Right edge, Save X2 AND DI, PLANE_BITS ; Mask out Row # MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte - - SHR AX, 2 ; Get X1 Byte # (=X1/4) - SHR CX, 2 ; Get X2 Byte # (=X2/4) - + + SHR AX, 1 ; Get X1 Byte # (=X1/4) + SHR CX, 1 ; Get X2 Byte # (=X2/4) + SHR AX, 1 ; Get X1 Byte # (=X1/4) + SHR CX, 1 ; Get X2 Byte # (=X2/4) + LES DI, d CURRENT_PAGE ; Point to Active VGA Page ADD DI, DX ; Point to Start of Line ADD DI, AX ; Point to Pixel X1 - + SUB CX, AX ; CX = # Of Bands (-1) to set JNZ @DL_LONGLN ; jump if longer than one segment - + AND BL, BH ; otherwise, merge clip masks - + @DL_LONGLN: - + OUT_8 SC_Data, BL ; Set the Left Clip Mask - + MOV AL, [BP].DL_ColorF ; Get Line Color MOV BL, AL ; BL = Copy of Line Color STOSB ; Set Left (1-4) Pixels - + JCXZ @DL_EXIT ; Done if only one Line Segment - + DEC CX ; CX = # of Middle Segments JZ @DL_XRSEG ; If no middle segments.... - + ; Draw Middle Segments - + OUT_8 DX, ALL_PLANES ; Write to ALL Planes - + MOV AL, BL ; Get Color from BL REP STOSB ; Draw Middle (4 Pixel) Segments - + @DL_XRSEG: OUT_8 DX, BH ; Select Planes for Right Clip Mask MOV AL, BL ; Get Color Value STOSB ; Draw Right (1-4) Pixels - + JMP s @DL_EXIT ; We Are Done... - - + + ; This Code Draws A Vertical Line. On entry: ; CH = Line Color, SI & DI = X1 - + @DL_VLINE: - + MOV AX, [BP].DL_Ypos1 ; AX = Y1 MOV SI, [BP].DL_Ypos2 ; SI = Y2 CMP AX, SI ; Is Y1 < Y2? JLE @DL_NOSWAP2 ; if so, Don't Swap them - + XCHG AX, SI ; Ok, NOW Y1 < Y2 - + @DL_NOSWAP2: - + SUB SI, AX ; SI = Line Height (Y2-Y1+1) INC SI - + ; AX = Y1, DI = X1, Get offset into Page into AX - + MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width MOV DX, DI ; Copy Xpos into DX - SHR DI, 2 ; DI = Xpos/4 + SHR DI, 1 ; DI = Xpos/4 + SHR DI, 1 ; DI = Xpos/4 ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1 - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page ADD DI, AX ; Point to Pixel X1, Y1 - + ;Select Plane - + MOV CL, DL ; CL = Save X1 AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #) MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1 SHL AH, CL ; Change to Correct Plane # OUT_16 SC_Index, AX ; Select Plane - + MOV AL, CH ; Get Saved Color MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By - + @DL_VLoop: MOV ES:[DI], AL ; Draw Single Pixel ADD DI, BX ; Point to Next Line LOOPjz SI, @DL_EXIT ; Lines--, Exit if done - + MOV ES:[DI], AL ; Draw Single Pixel ADD DI, BX ; Point to Next Line LOOPx SI, @DL_VLoop ; Lines--, Loop until Done - + @DL_EXIT: - + JMP @DL_EXIT2 ; Done! - + ; This code Draws a diagonal line in Mode X - + @DL_BREZHAM: LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AX, [BP].DL_Ypos1 ; get Y1 value MOV BX, [BP].DL_Ypos2 ; get Y2 value MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos - + CMP BX, AX ; Y2-Y1 is? JNC @DL_DeltaYOK ; if Y2>=Y1 then goto... - + XCHG BX, AX ; Swap em... MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos - + @DL_DeltaYOK: MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1 - + ADD DI, AX ; DI -> Start of Line Y1 on Page MOV AX, CX ; AX = Xpos (X1) - SHR AX, 2 ; /4 = Byte Offset into Line + SHR AX, 1 ; /4 = Byte Offset into Line + SHR AX, 1 ; /4 = Byte Offset into Line ADD DI, AX ; DI = Starting pos (X1,Y1) - + MOV AL, 11h ; Staring Mask AND CL, PLANE_BITS ; Get Plane # SHL AL, CL ; and shift into place MOV AH, [BP].DL_ColorF ; Color in Hi Bytes - + PUSH AX ; Save Mask,Color... - + MOV AH, AL ; Plane # in AH MOV AL, MAP_MASK ; Select Plane Register OUT_16 SC_Index, AX ; Select initial plane - + MOV AX, [BP].DL_Xpos1 ; get X1 value MOV BX, [BP].DL_Ypos1 ; get Y1 value MOV CX, [BP].DL_Xpos2 ; get X2 value MOV DX, [BP].DL_Ypos2 ; get Y2 value - + MOV BP, SCREEN_WIDTH ; Use BP for Line width to ; to avoid extra memory access - + SUB DX, BX ; figure Delta_Y JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1 - + ADD BX, DX ; put Y2 into Y1 NEG DX ; abs(Delta_Y) XCHG AX, CX ; and exchange X1 and X2 - + @DL_DeltaYOK2: MOV BX, 08000H ; seed for fraction accumulator - + SUB CX, AX ; figure Delta_X JC @DL_DrawLeft ; if negative, go left - + JMP @DL_DrawRight ; Draw Line that slopes right - + @DL_DrawLeft: - + NEG CX ; abs(Delta_X) - + CMP CX, DX ; is Delta_X < Delta_Y? JB @DL_SteepLeft ; yes, so go do steep line ; (Delta_Y iterations) - + ; Draw a Shallow line to the left in Mode X - + @DL_ShallowLeft: - CLR AX ; zero low word of Delta_Y * 10000h + mov ax,0 ; zero low word of Delta_Y * 10000h SUB AX, DX ; DX:AX <- DX * 0FFFFh SBB DX, 0 ; include carry DIV CX ; divide by Delta_X - + MOV SI, BX ; SI = Accumulator MOV BX, AX ; BX = Add fraction POP AX ; Get Color, Bit mask MOV DX, SC_Data ; Sequence controller data register INC CX ; Inc Delta_X so we can unroll loop - + ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down... - + @DL_SLLLoop: MOV ES:[DI], AH ; set first pixel, plane data set up LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done - + ADD SI, BX ; add numerator to accumulator JNC @DL_SLLL2nc ; move down on carry - + ADD DI, BP ; Move Down one line... - + @DL_SLLL2nc: DEC DI ; Left one addr ROR AL, 1 ; Move Left one plane, back on 0 1 2 CMP AL, 87h ; wrap?, if AL <88 then Carry set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done - + ADD SI, BX ; add numerator to accumulator, JNC @DL_SLLL3nc ; move down on carry - + ADD DI, BP ; Move Down one line... - + @DL_SLLL3nc: ; Now move left a pixel... DEC DI ; Left one addr ROR AL, 1 ; Move Left one plane, back on 0 1 2 @@ -1317,171 +1392,174 @@ DRAW_LINE PROC FAR ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask JMP s @DL_SLLLoop ; loop until done - + @DL_SLLExit: JMP @DL_EXIT2 ; and exit - + ; Draw a steep line to the left in Mode X - + @DL_SteepLeft: - CLR AX ; zero low word of Delta_Y * 10000h + mov ax,0 ; zero low word of Delta_Y * 10000h XCHG DX, CX ; Delta_Y switched with Delta_X DIV CX ; divide by Delta_Y - + MOV SI, BX ; SI = Accumulator MOV BX, AX ; BX = Add Fraction POP AX ; Get Color, Bit mask MOV DX, SC_Data ; Sequence controller data register INC CX ; Inc Delta_Y so we can unroll loop - + ; Loop (x2) to Draw Pixels, Move Down, and Maybe left - + @DL_STLLoop: - + MOV ES:[DI], AH ; set first pixel LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done - + ADD SI, BX ; add numerator to accumulator JNC @DL_STLnc2 ; No carry, just move down! - + DEC DI ; Move Left one addr ROR AL, 1 ; Move Left one plane, back on 0 1 2 CMP AL, 87h ; Wrap?, if AL <88 then Carry set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + @DL_STLnc2: ADD DI, BP ; advance to next line. - + MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done - + ADD SI, BX ; add numerator to accumulator JNC @DL_STLnc3 ; No carry, just move down! - + DEC DI ; Move Left one addr ROR AL, 1 ; Move Left one plane, back on 0 1 2 CMP AL, 87h ; Wrap?, if AL <88 then Carry set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + @DL_STLnc3: ADD DI, BP ; advance to next line. JMP s @DL_STLLoop ; Loop until done - + @DL_STLExit: JMP @DL_EXIT2 ; and exit - + ; Draw a line that goes to the Right... - + @DL_DrawRight: CMP CX, DX ; is Delta_X < Delta_Y? JB @DL_SteepRight ; yes, so go do steep line ; (Delta_Y iterations) - + ; Draw a Shallow line to the Right in Mode X - + @DL_ShallowRight: - CLR AX ; zero low word of Delta_Y * 10000h + mov ax,0 ; zero low word of Delta_Y * 10000h SUB AX, DX ; DX:AX <- DX * 0FFFFh SBB DX, 0 ; include carry DIV CX ; divide by Delta_X - + MOV SI, BX ; SI = Accumulator MOV BX, AX ; BX = Add Fraction POP AX ; Get Color, Bit mask MOV DX, SC_Data ; Sequence controller data register INC CX ; Inc Delta_X so we can unroll loop - + ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down... - + @DL_SLRLoop: MOV ES:[DI], AH ; set first pixel, mask is set up LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. - + ADD SI, BX ; add numerator to accumulator JNC @DL_SLR2nc ; don't move down if carry not set - + ADD DI, BP ; Move Down one line... - + @DL_SLR2nc: ; Now move right a pixel... ROL AL, 1 ; Move Right one addr if Plane = 0 CMP AL, 12h ; Wrap? if AL >12 then Carry not set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. - + ADD SI, BX ; add numerator to accumulator JNC @DL_SLR3nc ; don't move down if carry not set - + ADD DI, BP ; Move Down one line... - + @DL_SLR3nc: ROL AL, 1 ; Move Right one addr if Plane = 0 CMP AL, 12h ; Wrap? if AL >12 then Carry not set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask JMP s @DL_SLRLoop ; loop till done - + @DL_SLRExit: JMP @DL_EXIT2 ; and exit - + ; Draw a Steep line to the Right in Mode X - + @DL_SteepRight: - CLR AX ; zero low word of Delta_Y * 10000h + mov ax,0 ; zero low word of Delta_Y * 10000h XCHG DX, CX ; Delta_Y switched with Delta_X DIV CX ; divide by Delta_Y - + MOV SI, BX ; SI = Accumulator MOV BX, AX ; BX = Add Fraction POP AX ; Get Color, Bit mask MOV DX, SC_Data ; Sequence controller data register INC CX ; Inc Delta_Y so we can unroll loop - + ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right - + @STRLoop: MOV ES:[DI], AH ; set first pixel, mask is set up LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done - + ADD SI, BX ; add numerator to accumulator JNC @STRnc2 ; if no carry then just go down... - + ROL AL, 1 ; Move Right one addr if Plane = 0 CMP AL, 12h ; Wrap? if AL >12 then Carry not set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + @STRnc2: ADD DI, BP ; advance to next line. - + MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done - + ADD SI, BX ; add numerator to accumulator JNC @STRnc3 ; if no carry then just go down... - + ROL AL, 1 ; Move Right one addr if Plane = 0 CMP AL, 12h ; Wrap? if AL >12 then Carry not set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + @STRnc3: ADD DI, BP ; advance to next line. JMP s @STRLoop ; loop till done - + @DL_EXIT2: - POPx DI, SI, BP ; Restore Saved Registers + ;POPx DI, SI, BP ; Restore Saved Registers + pop di + pop si + pop bp RET 10 ; Exit and Clean up Stack - + DRAW_LINE ENDP - - + + ; ===== DAC COLOR REGISTER ROUTINES ===== - + ;================================================= ;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%) ;================================================= @@ -1495,7 +1573,7 @@ DRAW_LINE ENDP ; ; EXIT: No meaningful values returned ; - + SDR_STACK STRUC DW ? ; BP DD ? ; Caller @@ -1504,28 +1582,28 @@ SDR_STACK STRUC SDR_Red DB ?,? ; Red Data Value SDR_Register DB ?,? ; Palette Register # SDR_STACK ENDS - + PUBLIC SET_DAC_REGISTER - + SET_DAC_REGISTER PROC FAR - + PUSH BP ; Save BP MOV BP, SP ; Set up Stack Frame - + ; Select which DAC Register to modify - + OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register - + MOV DX, PEL_DATA_REG ; Dac Data Register OUT_8 DX, [BP].SDR_Red ; Set Red Intensity OUT_8 DX, [BP].SDR_Green ; Set Green Intensity OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity - + POP BP ; Restore Registers RET 8 ; Exit & Clean Up Stack - + SET_DAC_REGISTER ENDP - + ;==================================================== ;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%) ;==================================================== @@ -1541,7 +1619,7 @@ SET_DAC_REGISTER ENDP ; Green, and Blue are set to the values ; taken from the specified DAC register. ; - + GDR_STACK STRUC DW ? ; BP DD ? ; Caller @@ -1550,39 +1628,39 @@ GDR_STACK STRUC GDR_Red DW ? ; Addr of Red Data Value in DS GDR_Register DB ?,? ; Palette Register # GDR_STACK ENDS - + PUBLIC GET_DAC_REGISTER - + GET_DAC_REGISTER PROC FAR - + PUSH BP ; Save BP MOV BP, SP ; Set up Stack Frame - + ; Select which DAC Register to read in - + OUT_8 DAC_READ_ADDR, [BP].GDR_Register - + MOV DX, PEL_DATA_REG ; Dac Data Register - CLR AX ; Clear AX - + mov ax,0 ; Clear AX + IN AL, DX ; Read Red Value MOV BX, [BP].GDR_Red ; Get Address of Red% MOV [BX], AX ; *Red% = AX - + IN AL, DX ; Read Green Value MOV BX, [BP].GDR_Green ; Get Address of Green% MOV [BX], AX ; *Green% = AX - + IN AL, DX ; Read Blue Value MOV BX, [BP].GDR_Blue ; Get Address of Blue% MOV [BX], AX ; *Blue% = AX - + POP BP ; Restore Registers RET 8 ; Exit & Clean Up Stack - + GET_DAC_REGISTER ENDP - - + + ;=========================================================== ;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%) ;=========================================================== @@ -1599,40 +1677,45 @@ GET_DAC_REGISTER ENDP ; NOTES: PalData is a linear array of 3 byte Palette values ; in the order: Red (0-63), Green (0-63), Blue (0-63) ; - + LDR_STACK STRUC - DW ?x3 ; BP, DS, SI + DW ?x1 ; BP, DS, SI + DW ?x1 ; BP, DS, SI + DW ?x1 ; BP, DS, SI DD ? ; Caller LDR_Sync DW ? ; Vertical Sync Flag LDR_EndReg DB ?,? ; Last Register # LDR_StartReg DB ?,? ; First Register # LDR_PalData DD ? ; Far Ptr to Palette Data LDR_STACK ENDS - + PUBLIC LOAD_DAC_REGISTERS - + LOAD_DAC_REGISTERS PROC FAR - - PUSHx BP, DS, SI ; Save Registers + + ;PUSHx BP, DS, SI ; Save Registers + push bp + push ds + push si mov BP, SP ; Set up Stack Frame - + mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag or AX, AX ; is Sync Flag = 0? jz @LDR_Load ; if so, skip call - + call f SYNC_DISPLAY ; wait for vsync - + ; Determine register #'s, size to copy, etc - + @LDR_Load: - + lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data mov DX, DAC_WRITE_ADDR ; DAC register # selector - - CLR AX, BX ; Clear for byte loads + + mov ax,0, BX ; Clear for byte loads mov AL, [BP].LDR_StartReg ; Get Start Register mov BL, [BP].LDR_EndReg ; Get End Register - + sub BX, AX ; BX = # of DAC registers -1 inc BX ; BX = # of DAC registers mov CX, BX ; CX = # of DAC registers @@ -1640,19 +1723,22 @@ LOAD_DAC_REGISTERS PROC FAR add CX, BX ; CX = " " * 3 cld ; Block OUTs forward out DX, AL ; set up correct register # - + ; Load a block of DAC Registers - + mov DX, PEL_DATA_REG ; Dac Data Register - - rep outsb ; block set DAC registers - - POPx SI, DS, BP ; Restore Registers + + ;rep outsb ; block set DAC registers + + ;POPx SI, DS, BP ; Restore Registers + pop si + pop ds + pop bp ret 10 ; Exit & Clean Up Stack - + LOAD_DAC_REGISTERS ENDP - - + + ;==================================================== ;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%) ;==================================================== @@ -1668,53 +1754,61 @@ LOAD_DAC_REGISTERS ENDP ; NOTES: PalData is a linear array of 3 byte Palette values ; in the order: Red (0-63), Green (0-63), Blue (0-63) ; - + RDR_STACK STRUC - DW ?x3 ; BP, ES, DI + DW ?x1 ; BP, ES, DI + DW ?x1 ; BP, ES, DI + DW ?x1 ; BP, ES, DI DD ? ; Caller RDR_EndReg DB ?,? ; Last Register # RDR_StartReg DB ?,? ; First Register # RDR_PalData DD ? ; Far Ptr to Palette Data RDR_STACK ENDS - + PUBLIC READ_DAC_REGISTERS - + READ_DAC_REGISTERS PROC FAR - - PUSHx BP, ES, DI ; Save Registers + + ;PUSHx BP, ES, DI ; Save Registers + push bp + push es + push di mov BP, SP ; Set up Stack Frame - + ; Determine register #'s, size to copy, etc - + les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer mov DX, DAC_READ_ADDR ; DAC register # selector - - CLR AX, BX ; Clear for byte loads + + mov ax,0, BX ; Clear for byte loads mov AL, [BP].RDR_StartReg ; Get Start Register mov BL, [BP].RDR_EndReg ; Get End Register - + sub BX, AX ; BX = # of DAC registers -1 inc BX ; BX = # of DAC registers mov CX, BX ; CX = # of DAC registers add CX, BX ; CX = " " * 2 add CX, BX ; CX = " " * 3 cld ; Block INs forward - + ; Read a block of DAC Registers - + out DX, AL ; set up correct register # mov DX, PEL_DATA_REG ; Dac Data Register - - rep insb ; block read DAC registers - - POPx DI, ES, BP ; Restore Registers + + ;rep insb ; block read DAC registers + + ;POPx DI, ES, BP ; Restore Registers + pop di + pop es + pop bp ret 8 ; Exit & Clean Up Stack - + READ_DAC_REGISTERS ENDP - - + + ; ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== - + ;========================= ;SET_ACTIVE_PAGE (PageNo%) ;========================= @@ -1726,38 +1820,38 @@ READ_DAC_REGISTERS ENDP ; ; EXIT: No meaningful values returned ; - + SAP_STACK STRUC DW ? ; BP DD ? ; Caller SAP_Page DW ? ; Page # for Drawing SAP_STACK ENDS - + PUBLIC SET_ACTIVE_PAGE - + SET_ACTIVE_PAGE PROC FAR - + PUSH BP ; Preserve Registers MOV BP, SP ; Set up Stack Frame - + MOV BX, [BP].SAP_Page ; Get Desired Page # CMP BX, LAST_PAGE ; Is Page # Valid? JAE @SAP_Exit ; IF Not, Do Nothing - + MOV ACTIVE_PAGE, BX ; Set Active Page # - + SHL BX, 1 ; Scale Page # to Word MOV AX, PAGE_ADDR[BX] ; Get offset to Page - + MOV CURRENT_PAGE, AX ; And set for future LES's - + @SAP_Exit: POP BP ; Restore Registers RET 2 ; Exit and Clean up Stack - + SET_ACTIVE_PAGE ENDP - - + + ;================ ;GET_ACTIVE_PAGE% ;================ @@ -1768,17 +1862,17 @@ SET_ACTIVE_PAGE ENDP ; ; EXIT: AX = Current Video Page used for Drawing ; - + PUBLIC GET_ACTIVE_PAGE - + GET_ACTIVE_PAGE PROC FAR - + MOV AX, ACTIVE_PAGE ; Get Active Page # RET ; Exit and Clean up Stack - + GET_ACTIVE_PAGE ENDP - - + + ;=============================== ;SET_DISPLAY_PAGE (DisplayPage%) ;=============================== @@ -1792,70 +1886,70 @@ GET_ACTIVE_PAGE ENDP ; ; EXIT: No meaningful values returned ; - + SDP_STACK STRUC DW ? ; BP DD ? ; Caller SDP_Page DW ? ; Page # to Display... SDP_STACK ENDS - + PUBLIC SET_DISPLAY_PAGE - + SET_DISPLAY_PAGE PROC FAR - + PUSH BP ; Preserve Registers MOV BP, SP ; Set up Stack Frame - + MOV BX, [BP].SDP_Page ; Get Desired Page # CMP BX, LAST_PAGE ; Is Page # Valid? JAE @SDP_Exit ; IF Not, Do Nothing - + MOV DISPLAY_PAGE, BX ; Set Display Page # - + SHL BX, 1 ; Scale Page # to Word MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling - + ; Wait if we are currently in a Vertical Retrace - + MOV DX, INPUT_1 ; Input Status #1 Register - + @DP_WAIT0: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; In Display mode yet? JNZ @DP_WAIT0 ; If Not, wait for it - + ; Set the Start Display Address to the new page - + MOV DX, CRTC_Index ; We Change the VGA Sequencer - + MOV AL, START_DISP_LO ; Display Start Low Register MOV AH, CL ; Low 8 Bits of Start Addr OUT DX, AX ; Set Display Addr Low - + MOV AL, START_DISP_HI ; Display Start High Register MOV AH, CH ; High 8 Bits of Start Addr OUT DX, AX ; Set Display Addr High - + ; Wait for a Vertical Retrace to smooth out things - + MOV DX, INPUT_1 ; Input Status #1 Register - + @DP_WAIT1: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; Vertical Retrace Start? JZ @DP_WAIT1 ; If Not, wait for it - + ; Now Set Display Starting Address - - + + @SDP_Exit: POP BP ; Restore Registers RET 2 ; Exit and Clean up Stack - + SET_DISPLAY_PAGE ENDP - - + + ;================= ;GET_DISPLAY_PAGE% ;================= @@ -1866,17 +1960,17 @@ SET_DISPLAY_PAGE ENDP ; ; EXIT: AX = Current Video Page being displayed ; - + PUBLIC GET_DISPLAY_PAGE - + GET_DISPLAY_PAGE PROC FAR - + MOV AX, DISPLAY_PAGE ; Get Display Page # RET ; Exit & Clean Up Stack - + GET_DISPLAY_PAGE ENDP - - + + ;======================================= ;SET_WINDOW (DisplayPage%, Xpos%, Ypos%) ;======================================= @@ -1894,7 +1988,7 @@ GET_DISPLAY_PAGE ENDP ; ; EXIT: No meaningful values returned ; - + SW_STACK STRUC DW ? ; BP DD ? ; Caller @@ -1902,86 +1996,87 @@ SW_STACK STRUC SW_Xpos DW ? ; X pos of UL Screen Corner SW_Page DW ? ; (new) Display Page SW_STACK ENDS - + PUBLIC SET_WINDOW - + SET_WINDOW PROC FAR - + PUSH BP ; Preserve Registers MOV BP, SP ; Set up Stack Frame - + ; Check if our Scroll Offsets are Valid - + MOV BX, [BP].SW_Page ; Get Desired Page # CMP BX, LAST_PAGE ; Is Page # Valid? JAE @SW_Exit ; IF Not, Do Nothing - + MOV AX, [BP].SW_Ypos ; Get Desired Y Offset CMP AX, MAX_YOFFSET ; Is it Within Limits? JA @SW_Exit ; if not, exit - + MOV CX, [BP].SW_Xpos ; Get Desired X Offset CMP CX, MAX_XOFFSET ; Is it Within Limits? JA @SW_Exit ; if not, exit - + ; Compute proper Display start address to use - + MUL SCREEN_WIDTH ; AX = YOffset * Line Width - SHR CX, 2 ; CX / 4 = Bytes into Line + SHR CX, 1 ; CX / 4 = Bytes into Line + SHR CX, 1 ; CX / 4 = Bytes into Line ADD AX, CX ; AX = Offset of Upper Left Pixel - + MOV CURRENT_MOFFSET, AX ; Save Offset Info - + MOV DISPLAY_PAGE, BX ; Set Current Page # SHL BX, 1 ; Scale Page # to Word ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page MOV BX, AX ; BX = Desired Display Start - + MOV DX, INPUT_1 ; Input Status #1 Register - + ; Wait if we are currently in a Vertical Retrace - + @SW_WAIT0: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; In Display mode yet? JNZ @SW_WAIT0 ; If Not, wait for it - + ; Set the Start Display Address to the new window - + MOV DX, CRTC_Index ; We Change the VGA Sequencer MOV AL, START_DISP_LO ; Display Start Low Register MOV AH, BL ; Low 8 Bits of Start Addr OUT DX, AX ; Set Display Addr Low - + MOV AL, START_DISP_HI ; Display Start High Register MOV AH, BH ; High 8 Bits of Start Addr OUT DX, AX ; Set Display Addr High - + ; Wait for a Vertical Retrace to smooth out things - + MOV DX, INPUT_1 ; Input Status #1 Register - + @SW_WAIT1: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; Vertical Retrace Start? JZ @SW_WAIT1 ; If Not, wait for it - + ; Now Set the Horizontal Pixel Pan values - + OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register - + MOV AX, [BP].SW_Xpos ; Get Desired X Offset AND AL, 03 ; Get # of Pixels to Pan (0-3) SHL AL, 1 ; Shift for 256 Color Mode OUT DX, AL ; Fine tune the display! - + @SW_Exit: POP BP ; Restore Saved Registers RET 6 ; Exit and Clean up Stack - + SET_WINDOW ENDP - - + + ;============= ;GET_X_OFFSET% ;============= @@ -1993,17 +2088,17 @@ SET_WINDOW ENDP ; ; EXIT: AX = Current Horizontal Scroll Offset ; - + PUBLIC GET_X_OFFSET - + GET_X_OFFSET PROC FAR - + MOV AX, CURRENT_XOFFSET ; Get current horz offset RET ; Exit & Clean Up Stack - + GET_X_OFFSET ENDP - - + + ;============= ;GET_Y_OFFSET% ;============= @@ -2015,17 +2110,17 @@ GET_X_OFFSET ENDP ; ; EXIT: AX = Current Vertical Scroll Offset ; - + PUBLIC GET_Y_OFFSET - + GET_Y_OFFSET PROC FAR - + MOV AX, CURRENT_YOFFSET ; Get current vertical offset RET ; Exit & Clean Up Stack - + GET_Y_OFFSET ENDP - - + + ;============ ;SYNC_DISPLAY ;============ @@ -2036,34 +2131,34 @@ GET_Y_OFFSET ENDP ; ; EXIT: No meaningful values returned ; - + PUBLIC SYNC_DISPLAY - + SYNC_DISPLAY PROC FAR - + MOV DX, INPUT_1 ; Input Status #1 Register - + ; Wait for any current retrace to end - + @SD_WAIT0: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; In Display mode yet? JNZ @SD_WAIT0 ; If Not, wait for it - + ; Wait for the start of the next vertical retrace - + @SD_WAIT1: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; Vertical Retrace Start? JZ @SD_WAIT1 ; If Not, wait for it - + RET ; Exit & Clean Up Stack - + SYNC_DISPLAY ENDP - - + + ; ===== TEXT DISPLAY ROUTINES ===== - + ;================================================== ;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%) ;================================================== @@ -2080,13 +2175,16 @@ SYNC_DISPLAY ENDP ; ; EXIT: No meaningful values returned ; - + GPC_STACK STRUC GPC_Width DW ? ; Screen Width-1 GPC_Lines DB ?,? ; Scan lines to Decode GPC_T_SETS DW ? ; Saved Charset Segment GPC_T_SETO DW ? ; Saved Charset Offset - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller GPC_ColorB DB ?,? ; Background Color GPC_ColorF DB ?,? ; Text Color @@ -2094,171 +2192,189 @@ GPC_STACK STRUC GPC_Xpos DW ? ; X position to Print at GPC_Char DB ?,? ; Character to Print GPC_STACK ENDS - + PUBLIC GPRINTC - + GPRINTC PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 8 ; Allocate WorkSpace on Stack MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AX, SCREEN_WIDTH ; Get Logical Line Width MOV BX, AX ; BX = Screen Width DEC BX ; = Screen Width-1 MOV [BP].GPC_Width, BX ; Save for later use - + MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width ADD DI, AX ; DI -> Start of Line Ypos - + MOV AX, [BP].GPC_Xpos ; Get Xpos of Character MOV CX, AX ; Save Copy of Xpos - SHR AX, 2 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 ADD DI, AX ; DI -> (Xpos, Ypos) - + ;Get Source ADDR of Character Bit Map & Save - + MOV AL, [BP].GPC_Char ; Get Character # TEST AL, 080h ; Is Hi Bit Set? JZ @GPC_LowChar ; Nope, use low char set ptr - + AND AL, 07Fh ; Mask Out Hi Bit MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment JMP s @GPC_Set_Char ; Go Setup Character Ptr - + @GPC_LowChar: - + MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment - + @GPC_Set_Char: MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack - + MOV AH, 0 ; Valid #'s are 0..127 - SHL AX, 3 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap ADD BX, AX ; BX = Offset of Selected char MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack - + AND CX, PLANE_BITS ; Get Plane # MOV CH, ALL_PLANES ; Get Initial Plane mask SHL CH, CL ; And shift into position AND CH, ALL_PLANES ; And mask to lower nibble - + MOV AL, 04 ; 4-Plane # = # of initial SUB AL, CL ; shifts to align bit mask MOV CL, AL ; Shift Count for SHL - + ;Get segment of character map - + OUT_8 SC_Index, MAP_MASK ; Setup Plane selections INC DX ; DX -> SC_Data - + MOV AL, 08 ; 8 Lines to Process MOV [BP].GPC_Lines, AL ; Save on Stack - + MOV DS, [BP].GPC_T_SETS ; Point to character set - + @GPC_DECODE_CHAR_BYTE: - + MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String - + MOV BH, [SI] ; Get Bit Map INC SI ; Point to Next Line MOV [BP].GPC_T_SETO, SI ; And save new Pointer... - - CLR AX ; Clear AX - - CLR BL ; Clear BL + + mov ax,0 ; Clear AX + + ;mov bl,0 ; Clear BL + mov bl,0 ROL BX, CL ; BL holds left edge bits MOV SI, BX ; Use as Table Index AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set - + MOV AH, [BP].GPC_ColorF ; Get Foreground Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @GPC_NO_LEFT1BITS: XOR AL, CH ; Invert mask for Background JZ @GPC_NO_LEFT0BITS ; Hey, no need for this - + MOV AH, [BP].GPC_ColorB ; Get background Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + ;Now Do Middle/Last Band - + @GPC_NO_LEFT0BITS: INC DI ; Point to next Byte - ROL BX, 4 ; Shift 4 bits - + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + MOV SI, BX ; Make Lookup Pointer AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set - + MOV AH, [BP].GPC_ColorF ; Get Foreground Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @GPC_NO_MIDDLE1BITS: XOR AL, ALL_PLANES ; Invert mask for Background JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this - + MOV AH, [BP].GPC_ColorB ; Get background Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @GPC_NO_MIDDLE0BITS: XOR CH, ALL_PLANES ; Invert Clip Mask CMP CL, 4 ; Aligned by 4? JZ @GPC_NEXT_LINE ; If so, Exit now.. - + INC DI ; Point to next Byte - ROL BX, 4 ; Shift 4 bits - + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + MOV SI, BX ; Make Lookup Pointer AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set - + MOV AH, [BP].GPC_ColorF ; Get Foreground Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @GPC_NO_RIGHT1BITS: - + XOR AL, CH ; Invert mask for Background JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this - + MOV AH, [BP].GPC_ColorB ; Get background Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @GPC_NO_RIGHT0BITS: DEC DI ; Adjust for Next Line Advance - + @GPC_NEXT_LINE: ADD DI, [BP].GPC_Width ; Point to Next Line XOR CH, CHAR_BITS ; Flip the Clip mask back - + DEC [BP].GPC_Lines ; Count Down Lines JZ @GPC_EXIT ; Ok... Done! - + JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey! - + @GPC_EXIT: ADD SP, 08 ; Deallocate stack workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 10 ; Exit and Clean up Stack - + GPRINTC ENDP - - + + ;========================================== ;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%) ;========================================== @@ -2273,158 +2389,178 @@ GPRINTC ENDP ; ; EXIT: No meaningful values returned ; - + TGP_STACK STRUC TGP_Width DW ? ; Screen Width-1 TGP_Lines DB ?,? ; Scan lines to Decode TGP_T_SETS DW ? ; Saved Charset Segment TGP_T_SETO DW ? ; Saved Charset Offset - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller TGP_ColorF DB ?,? ; Text Color TGP_Ypos DW ? ; Y Position to Print at TGP_Xpos DW ? ; X position to Print at TGP_Char DB ?,? ; Character to Print TGP_STACK ENDS - + PUBLIC TGPRINTC - + TGPRINTC PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 8 ; Allocate WorkSpace on Stack MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AX, SCREEN_WIDTH ; Get Logical Line Width MOV BX, AX ; BX = Screen Width DEC BX ; = Screen Width-1 MOV [BP].TGP_Width, BX ; Save for later use - + MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width ADD DI, AX ; DI -> Start of Line Ypos - + MOV AX, [BP].TGP_Xpos ; Get Xpos of Character MOV CX, AX ; Save Copy of Xpos - SHR AX, 2 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 ADD DI, AX ; DI -> (Xpos, Ypos) - + ;Get Source ADDR of Character Bit Map & Save - + MOV AL, [BP].TGP_Char ; Get Character # TEST AL, 080h ; Is Hi Bit Set? JZ @TGP_LowChar ; Nope, use low char set ptr - + AND AL, 07Fh ; Mask Out Hi Bit MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment JMP s @TGP_Set_Char ; Go Setup Character Ptr - + @TGP_LowChar: - + MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment - + @TGP_Set_Char: MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack - + MOV AH, 0 ; Valid #'s are 0..127 - SHL AX, 3 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap ADD BX, AX ; BX = Offset of Selected char MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack - + AND CX, PLANE_BITS ; Get Plane # MOV CH, ALL_PLANES ; Get Initial Plane mask SHL CH, CL ; And shift into position AND CH, ALL_PLANES ; And mask to lower nibble - + MOV AL, 04 ; 4-Plane # = # of initial SUB AL, CL ; shifts to align bit mask MOV CL, AL ; Shift Count for SHL - + ;Get segment of character map - + OUT_8 SC_Index, MAP_MASK ; Setup Plane selections INC DX ; DX -> SC_Data - + MOV AL, 08 ; 8 Lines to Process MOV [BP].TGP_Lines, AL ; Save on Stack - + MOV DS, [BP].TGP_T_SETS ; Point to character set - + @TGP_DECODE_CHAR_BYTE: - + MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String - + MOV BH, [SI] ; Get Bit Map INC SI ; Point to Next Line MOV [BP].TGP_T_SETO, SI ; And save new Pointer... - + MOV AH, [BP].TGP_ColorF ; Get Foreground Color - - CLR BL ; Clear BL + + mov bl,0 ; Clear BL ROL BX, CL ; BL holds left edge bits MOV SI, BX ; Use as Table Index AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set - + OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + ;Now Do Middle/Last Band - + @TGP_NO_LEFT1BITS: - + INC DI ; Point to next Byte - ROL BX, 4 ; Shift 4 bits - + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + MOV SI, BX ; Make Lookup Pointer AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set - + OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @TGP_NO_MIDDLE1BITS: XOR CH, ALL_PLANES ; Invert Clip Mask CMP CL, 4 ; Aligned by 4? JZ @TGP_NEXT_LINE ; If so, Exit now.. - + INC DI ; Point to next Byte - ROL BX, 4 ; Shift 4 bits - + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + MOV SI, BX ; Make Lookup Pointer AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set - + OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @TGP_NO_RIGHT1BITS: - + DEC DI ; Adjust for Next Line Advance - + @TGP_NEXT_LINE: ADD DI, [BP].TGP_Width ; Point to Next Line XOR CH, CHAR_BITS ; Flip the Clip mask back - + DEC [BP].TGP_Lines ; Count Down Lines JZ @TGP_EXIT ; Ok... Done! - + JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey! - + @TGP_EXIT: ADD SP, 08 ; Deallocate stack workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 8 ; Exit and Clean up Stack - + TGPRINTC ENDP - - + + ;=============================================================== ;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) ;=============================================================== @@ -2441,9 +2577,12 @@ TGPRINTC ENDP ; ; EXIT: No meaningful values returned ; - + PS_STACK STRUC - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller PS_ColorB DW ? ; Background Color PS_ColorF DW ? ; Text Color @@ -2452,54 +2591,62 @@ PS_STACK STRUC PS_Len DW ? ; Maximum Length of string to print PS_Text DW ?,? ; Far Ptr to Text String PS_STACK ENDS - + PUBLIC PRINT_STR - + PRINT_STR PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di MOV BP, SP ; Set up Stack Frame - + @PS_Print_It: - + MOV CX, [BP].PS_Len ; Get Remaining text Length JCXZ @PS_Exit ; Exit when out of text - + LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text MOV AL, ES:[DI] ; AL = Text Character AND AX, 00FFh ; Clear High Word JZ @PS_Exit ; Exit if null character - + DEC [BP].PS_Len ; Remaining Text length-- INC [BP].PS_Text ; Point to Next text char - + ; Set up Call to GPRINTC - + PUSH AX ; Set Character Parameter MOV BX, [BP].PS_Xpos ; Get Xpos PUSH BX ; Set Xpos Parameter ADD BX, 8 ; Advance 1 Char to Right MOV [BP].PS_Xpos, BX ; Save for next time through - + MOV BX, [BP].PS_Ypos ; Get Ypos PUSH BX ; Set Ypos Parameter - + MOV BX, [BP].PS_ColorF ; Get Text Color PUSH BX ; Set ColorF Parameter - + MOV BX, [BP].PS_ColorB ; Get Background Color PUSH BX ; Set ColorB Parameter - + CALL f GPRINTC ; Print Character! JMP s @PS_Print_It ; Process next character - + @PS_Exit: - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 14 ; Exit and Clean up Stack - + PRINT_STR ENDP - - + + ;================================================================ ;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) ;================================================================ @@ -2515,9 +2662,12 @@ PRINT_STR ENDP ; ; EXIT: No meaningful values returned ; - + TPS_STACK STRUC - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller TPS_ColorF DW ? ; Text Color TPS_Ypos DW ? ; Y Position to Print at @@ -2525,51 +2675,59 @@ TPS_STACK STRUC TPS_Len DW ? ; Maximum Length of string to print TPS_Text DW ?,? ; Far Ptr to Text String TPS_STACK ENDS - + PUBLIC TPRINT_STR - + TPRINT_STR PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di MOV BP, SP ; Set up Stack Frame - + @TPS_Print_It: - + MOV CX, [BP].TPS_Len ; Get Remaining text Length JCXZ @TPS_Exit ; Exit when out of text - + LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text MOV AL, ES:[DI] ; AL = Text Character AND AX, 00FFh ; Clear High Word JZ @TPS_Exit ; Exit if null character - + DEC [BP].TPS_Len ; Remaining Text length-- INC [BP].TPS_Text ; Point to Next text char - + ; Set up Call to TGPRINTC - + PUSH AX ; Set Character Parameter MOV BX, [BP].TPS_Xpos ; Get Xpos PUSH BX ; Set Xpos Parameter ADD BX, 8 ; Advance 1 Char to Right MOV [BP].TPS_Xpos, BX ; Save for next time through - + MOV BX, [BP].TPS_Ypos ; Get Ypos PUSH BX ; Set Ypos Parameter - + MOV BX, [BP].TPS_ColorF ; Get Text Color PUSH BX ; Set ColorF Parameter - + CALL f TGPRINTC ; Print Character! JMP s @TPS_Print_It ; Process next character - + @TPS_Exit: - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 12 ; Exit and Clean up Stack - + TPRINT_STR ENDP - - + + ;=========================================== ;SET_DISPLAY_FONT(SEG FontData, FontNumber%) ;=========================================== @@ -2584,41 +2742,41 @@ TPRINT_STR ENDP ; ; EXIT: No meaningful values returned ; - + SDF_STACK STRUC DW ? ; BP DD ? ; Caller SDF_Which DW ? ; Hi Table/Low Table Flag SDF_Font DD ? ; Far Ptr to Font Table SDF_STACK ENDS - + PUBLIC SET_DISPLAY_FONT - + SET_DISPLAY_FONT PROC FAR - + PUSH BP ; Preserve Registers MOV BP, SP ; Set up Stack Frame - + LES DI, [BP].SDF_Font ; Get Far Ptr to Font - + MOV SI, o CHARSET_LOW ; Assume Lower 128 chars TEST [BP].SDF_Which, 1 ; Font #1 selected? JZ @SDF_Set_Font ; If not, skip ahead - + MOV SI, o CHARSET_HI ; Ah, really it's 128-255 - + @SDF_Set_Font: MOV [SI], DI ; Set Font Pointer Offset MOV [SI+2], ES ; Set Font Pointer Segment - + POP BP ; Restore Registers RET 6 ; We are Done.. Outa here - + SET_DISPLAY_FONT ENDP - - + + ; ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== - + ;====================================================== ;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) ;====================================================== @@ -2637,14 +2795,17 @@ SET_DISPLAY_FONT ENDP ; ; EXIT: No meaningful values returned ; - + DB_STACK STRUC DB_LineO DW ? ; Offset to Next Line DB_PixCount DW ? ; (Minimum) # of Pixels/Line DB_Start DW ? ; Addr of Upper Left Pixel DB_PixSkew DW ? ; # of bytes to Adjust EOL DB_SkewFlag DW ? ; Extra Pix on Plane Flag - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller DB_Height DW ? ; Height of Bitmap in Pixels DB_Width DW ? ; Width of Bitmap in Pixels @@ -2652,65 +2813,71 @@ DB_STACK STRUC DB_Xpos DW ? ; X position to Draw Bitmap at DB_Image DD ? ; Far Pointer to Graphics Bitmap DB_STACK ENDS - + PUBLIC DRAW_BITMAP - + DRAW_BITMAP PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 10 ; Allocate workspace MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page CLD ; Direction Flag = Forward - + MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos MUL SCREEN_WIDTH ; AX = Offset to Line Ypos - + MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos MOV CL, BL ; Save Plane # in CL - SHR BX, 2 ; Xpos/4 = Offset Into Line - + SHR BX, 1 ; Xpos/4 = Offset Into Line + SHR BX, 1 ; Xpos/4 = Offset Into Line + ADD DI, AX ; ES:DI -> Start of Line ADD DI, BX ; ES:DI -> Upper Left Pixel MOV [BP].DB_Start, DI ; Save Starting Addr - + ; Compute line to line offset - + MOV BX, [BP].DB_Width ; Get Width of Image MOV DX, BX ; Save Copy in DX - SHR BX, 2 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands MOV AX, SCREEN_WIDTH ; Get Screen Width SUB AX, BX ; - (Bitmap Width/4) - + MOV [BP].DB_LineO, AX ; Save Line Width offset MOV [BP].DB_PixCount, BX ; Minimum # pix to copy - + AND DX, PLANE_BITS ; Get "partial band" size (0-3) MOV [BP].DB_PixSkew, DX ; Also End of Line Skew MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count - + AND CX, PLANE_BITS ; CL = Starting Plane # MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select SHL AH, CL ; Select correct Plane OUT_16 SC_Index, AX ; Select Plane... MOV BH, AH ; BH = Saved Plane Mask MOV BL, 4 ; BL = Planes to Copy - + @DB_COPY_PLANE: - + LDS SI, [BP].DB_Image ; DS:SI-> Source Image MOV DX, [BP].DB_Height ; # of Lines to Copy MOV DI, [BP].DB_Start ; ES:DI-> Dest pos - + @DB_COPY_LINE: MOV CX, [BP].DB_PixCount ; Min # to copy - + TEST CL, 0FCh ; 16+PixWide? JZ @DB_COPY_REMAINDER ; Nope... - + ; Pixel Copy loop has been unrolled to x4 - + @DB_COPY_LOOP: MOVSB ; Copy Bitmap Pixel ADD SI, 3 ; Skip to Next Byte in same plane @@ -2720,60 +2887,64 @@ DRAW_BITMAP PROC FAR ADD SI, 3 ; Skip to Next Byte in same plane MOVSB ; Copy Bitmap Pixel ADD SI, 3 ; Skip to Next Byte in same plane - + SUB CL, 4 ; Pixels to Copy=-4 TEST CL, 0FCh ; 4+ Pixels Left? JNZ @DB_COPY_LOOP ; if so, do another block - + @DB_COPY_REMAINDER: JCXZ @DB_NEXT_LINE ; Any Pixels left on line - + @DB_COPY2: MOVSB ; Copy Bitmap Pixel ADD SI,3 ; Skip to Next Byte in same plane LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done - + @DB_NEXT_LINE: - + ; any Partial Pixels? (some planes only) - + OR CX, [BP].DB_SkewFlag ; Get Skew Count JZ @DB_NEXT2 ; if no partial pixels - + MOVSB ; Copy Bitmap Pixel DEC DI ; Back up to align DEC SI ; Back up to align - + @DB_NEXT2: ADD SI, [BP].DB_PixSkew ; Adjust Skew ADD DI, [BP].DB_LineO ; Set to Next Display Line LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more - + ; Copy Next Plane.... - + DEC BL ; Planes to Go-- JZ @DB_Exit ; Hey! We are done - + ROL BH, 1 ; Next Plane in line... OUT_8 SC_Data, BH ; Select Plane - + CMP AL, 12h ; Carry Set if AL=11h ADC [BP].DB_Start, 0 ; Screen Addr =+Carry INC w [BP].DB_Image ; Start @ Next Byte - + SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1 - + JMP s @DB_COPY_PLANE ; Go Copy the Next Plane - + @DB_Exit: ADD SP, 10 ; Deallocate workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 12 ; Exit and Clean up Stack - + DRAW_BITMAP ENDP - - + + ;======================================================= ;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) ;======================================================= @@ -2793,14 +2964,17 @@ DRAW_BITMAP ENDP ; ; EXIT: No meaningful values returned ; - + TB_STACK STRUC TB_LineO DW ? ; Offset to Next Line TB_PixCount DW ? ; (Minimum) # of Pixels/Line TB_Start DW ? ; Addr of Upper Left Pixel TB_PixSkew DW ? ; # of bytes to Adjust EOL TB_SkewFlag DW ? ; Extra Pix on Plane Flag - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller TB_Height DW ? ; Height of Bitmap in Pixels TB_Width DW ? ; Width of Bitmap in Pixels @@ -2808,163 +2982,173 @@ TB_STACK STRUC TB_Xpos DW ? ; X position to Draw Bitmap at TB_Image DD ? ; Far Pointer to Graphics Bitmap TB_STACK ENDS - + PUBLIC TDRAW_BITMAP - + TDRAW_BITMAP PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 10 ; Allocate workspace MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page CLD ; Direction Flag = Forward - + MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos MUL SCREEN_WIDTH ; AX = Offset to Line Ypos - + MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos MOV CL, BL ; Save Plane # in CL - SHR BX, 2 ; Xpos/4 = Offset Into Line - + SHR BX, 1 ; Xpos/4 = Offset Into Line + SHR BX, 1 ; Xpos/4 = Offset Into Line + ADD DI, AX ; ES:DI -> Start of Line ADD DI, BX ; ES:DI -> Upper Left Pixel MOV [BP].TB_Start, DI ; Save Starting Addr - + ; Compute line to line offset - + MOV BX, [BP].TB_Width ; Get Width of Image MOV DX, BX ; Save Copy in DX - SHR BX, 2 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands MOV AX, SCREEN_WIDTH ; Get Screen Width SUB AX, BX ; - (Bitmap Width/4) - + MOV [BP].TB_LineO, AX ; Save Line Width offset MOV [BP].TB_PixCount, BX ; Minimum # pix to copy - + AND DX, PLANE_BITS ; Get "partial band" size (0-3) MOV [BP].TB_PixSkew, DX ; Also End of Line Skew MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count - + AND CX, PLANE_BITS ; CL = Starting Plane # MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select SHL AH, CL ; Select correct Plane OUT_16 SC_Index, AX ; Select Plane... MOV BH, AH ; BH = Saved Plane Mask MOV BL, 4 ; BL = Planes to Copy - + @TB_COPY_PLANE: - + LDS SI, [BP].TB_Image ; DS:SI-> Source Image MOV DX, [BP].TB_Height ; # of Lines to Copy MOV DI, [BP].TB_Start ; ES:DI-> Dest pos - + ; Here AH is set with the value to be considered ; "Transparent". It can be changed! - + MOV AH, 0 ; Value to Detect 0 - + @TB_COPY_LINE: MOV CX, [BP].TB_PixCount ; Min # to copy - + TEST CL, 0FCh ; 16+PixWide? JZ @TB_COPY_REMAINDER ; Nope... - + ; Pixel Copy loop has been unrolled to x4 - + @TB_COPY_LOOP: LODSB ; Get Pixel Value in AL ADD SI, 3 ; Skip to Next Byte in same plane CMP AL, AH ; It is "Transparent"? JE @TB_SKIP_01 ; Skip ahead if so MOV ES:[DI], AL ; Copy Pixel to VGA screen - + @TB_SKIP_01: LODSB ; Get Pixel Value in AL ADD SI, 3 ; Skip to Next Byte in same plane CMP AL, AH ; It is "Transparent"? JE @TB_SKIP_02 ; Skip ahead if so MOV ES:[DI+1], AL ; Copy Pixel to VGA screen - + @TB_SKIP_02: LODSB ; Get Pixel Value in AL ADD SI, 3 ; Skip to Next Byte in same plane CMP AL, AH ; It is "Transparent"? JE @TB_SKIP_03 ; Skip ahead if so MOV ES:[DI+2], AL ; Copy Pixel to VGA screen - + @TB_SKIP_03: LODSB ; Get Pixel Value in AL ADD SI, 3 ; Skip to Next Byte in same plane CMP AL, AH ; It is "Transparent"? JE @TB_SKIP_04 ; Skip ahead if so MOV ES:[DI+3], AL ; Copy Pixel to VGA screen - + @TB_SKIP_04: ADD DI, 4 ; Adjust Pixel Write Location SUB CL, 4 ; Pixels to Copy=-4 TEST CL, 0FCh ; 4+ Pixels Left? JNZ @TB_COPY_LOOP ; if so, do another block - + @TB_COPY_REMAINDER: JCXZ @TB_NEXT_LINE ; Any Pixels left on line - + @TB_COPY2: LODSB ; Get Pixel Value in AL ADD SI, 3 ; Skip to Next Byte in same plane CMP AL, AH ; It is "Transparent"? JE @TB_SKIP_05 ; Skip ahead if so MOV ES:[DI], AL ; Copy Pixel to VGA screen - + @TB_SKIP_05: INC DI ; Advance Dest Addr LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done - + @TB_NEXT_LINE: - + ; any Partial Pixels? (some planes only) - + OR CX, [BP].TB_SkewFlag ; Get Skew Count JZ @TB_NEXT2 ; if no partial pixels - + LODSB ; Get Pixel Value in AL DEC SI ; Backup to Align CMP AL, AH ; It is "Transparent"? JE @TB_NEXT2 ; Skip ahead if so MOV ES:[DI], AL ; Copy Pixel to VGA screen - + @TB_NEXT2: ADD SI, [BP].TB_PixSkew ; Adjust Skew ADD DI, [BP].TB_LineO ; Set to Next Display Line LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More - + ;Copy Next Plane.... - + DEC BL ; Planes to Go-- JZ @TB_Exit ; Hey! We are done - + ROL BH, 1 ; Next Plane in line... OUT_8 SC_Data, BH ; Select Plane - + CMP AL, 12h ; Carry Set if AL=11h ADC [BP].TB_Start, 0 ; Screen Addr =+Carry INC w [BP].TB_Image ; Start @ Next Byte - + SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1 - + JMP @TB_COPY_PLANE ; Go Copy the next Plane - + @TB_Exit: ADD SP, 10 ; Deallocate workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 12 ; Exit and Clean up Stack - + TDRAW_BITMAP ENDP - - + + ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== - + ;================================== ;COPY_PAGE (SourcePage%, DestPage%) ;================================== @@ -2976,70 +3160,81 @@ TDRAW_BITMAP ENDP ; ; EXIT: No meaningful values returned ; - + CP_STACK STRUC - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller CP_DestP DW ? ; Page to hold copied image CP_SourceP DW ? ; Page to Make copy from CP_STACK ENDS - + PUBLIC COPY_PAGE - + COPY_PAGE PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di MOV BP, SP ; Set up Stack Frame CLD ; Block Xfer Forwards - + ; Make sure Page #'s are valid - + MOV AX, [BP].CP_SourceP ; Get Source Page # CMP AX, LAST_PAGE ; is it > Max Page #? JAE @CP_Exit ; if so, abort - + MOV BX, [BP].CP_DestP ; Get Destination Page # CMP BX, LAST_PAGE ; is it > Max Page #? JAE @CP_Exit ; if so, abort - + CMP AX, BX ; Pages #'s the same? JE @CP_Exit ; if so, abort - + ; Setup DS:SI and ES:DI to Video Pages - + SHL BX, 1 ; Scale index to Word MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page - + MOV BX, AX ; Index to Source page SHL BX, 1 ; Scale index to Word MOV SI, PAGE_ADDR[BX] ; Offset to Source Page - + MOV CX, PAGE_SIZE ; Get size of Page MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment MOV ES, AX ; ES:DI -> Dest Page MOV DS, AX ; DS:SI -> Source Page - + ; Setup VGA registers for Mem to Mem copy - + OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes - + ; Note.. Do *NOT* use MOVSW or MOVSD - they will ; Screw with the latches which are 8 bits x 4 - + REP MOVSB ; Copy entire Page! - + ; Reset VGA for normal memory access - + OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off - + @CP_Exit: - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 4 ; Exit and Clean up Stack - + COPY_PAGE ENDP - - + + ;========================================================================== ;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%) ;========================================================================== @@ -3065,11 +3260,14 @@ COPY_PAGE ENDP ; ; EXIT: AX = Success Flag: 0 = Failure / -1= Success ; - + CB_STACK STRUC CB_Height DW ? ; Height of Image in Lines CB_Width DW ? ; Width of Image in "bands" - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller CB_DestY1 DW ? ; Destination Ypos CB_DestX1 DW ? ; Destination Xpos @@ -3080,64 +3278,71 @@ CB_STACK STRUC CB_X1 DW ? ; UL Xpos of Image CB_SourceP DW ? ; Page containing Source Bitmap CB_STACK ENDS - + PUBLIC COPY_BITMAP - + COPY_BITMAP PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 4 ; Allocate WorkSpace on Stack MOV BP, SP ; Set up Stack Frame - + ; Prep Registers (and keep jumps short!) - + MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram CLD ; Block Xfer Forwards - + ; Make sure Parameters are valid - + MOV BX, [BP].CB_SourceP ; Get Source Page # CMP BX, LAST_PAGE ; is it > Max Page #? JAE @CB_Abort ; if so, abort - + MOV CX, [BP].CB_DestP ; Get Destination Page # CMP CX, LAST_PAGE ; is it > Max Page #? JAE @CB_Abort ; if so, abort - + MOV AX, [BP].CB_X1 ; Get Source X1 XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1 AND AX, PLANE_BITS ; Check Plane Bits JNZ @CB_Abort ; They should cancel out - + ; Setup for Copy processing - + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on - + ; Compute Info About Images, Setup ES:SI & ES:DI - + MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1 INC AX ; (add 1 since were not 0 based) MOV [BP].CB_Height, AX ; Save on Stack for later use - + MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1 - SHR AX, 2 ; Get X2 Band (X2 / 4) - SHR DX, 2 ; Get X1 Band (X1 / 4) + SHR AX, 1 ; Get X2 Band (X2 / 4) + SHR DX, 1 ; Get X1 Band (X1 / 4) + SHR AX, 1 ; Get X2 Band (X2 / 4) + SHR DX, 1 ; Get X1 Band (X1 / 4) SUB AX, DX ; AX = # of Bands - 1 INC AX ; AX = # of Bands MOV [BP].CB_Width, AX ; Save on Stack for later use - + SHL BX, 1 ; Scale Source Page to Word MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page MOV AX, [BP].CB_Y1 ; Get Source Y1 Line MUL SCREEN_WIDTH ; AX = Offset to Line Y1 ADD SI, AX ; SI = Offset to Line Y1 MOV AX, [BP].CB_X1 ; Get Source X1 - SHR AX, 2 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset ADD SI, AX ; SI = Byte Offset to (X1,Y1) - + MOV BX, CX ; Dest Page Index to BX SHL BX, 1 ; Scale Source Page to Word MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page @@ -3145,24 +3350,25 @@ COPY_BITMAP PROC FAR MUL SCREEN_WIDTH ; AX = Offset to Line Y1 ADD DI, AX ; DI = Offset to Line Y1 MOV AX, [BP].CB_DestX1 ; Get Dest X1 - SHR AX, 2 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1) - + MOV CX, [BP].CB_Width ; CX = Width of Image (Bands) DEC CX ; CX = 1? JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band - + MOV BX, [BP].CB_X1 ; Get Source X1 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?) JZ @CB_Check_Right ; if so, check right alignment JNZ @CB_Left_Band ; not aligned? well.. - + @CB_Abort: - CLR AX ; Return False (Failure) + mov ax,0 ; Return False (Failure) JMP @CB_Exit ; and Finish Up - + ; Copy when Left & Right Clip Masks overlap... - + @CB_Only_One_Band: MOV BX, [BP].CB_X1 ; Get Left Clip Mask AND BX, PLANE_BITS ; Mask out Row # @@ -3170,126 +3376,130 @@ COPY_BITMAP PROC FAR MOV BX, [BP].CB_X2 ; Get Right Clip Mask AND BX, PLANE_BITS ; Mask out Row # AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte - + OUT_8 SC_Data, AL ; Clip For Left & Right Masks - + MOV CX, [BP].CB_Height ; CX = # of Lines to Copy MOV DX, SCREEN_WIDTH ; DX = Width of Screen - CLR BX ; BX = Offset into Image - + mov bx,0 ; BX = Offset into Image + @CB_One_Loop: MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPjz CX, @CB_One_Done ; Exit Loop if Finished - + MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPx CX, @CB_One_Loop ; Loop until Finished - + @CB_One_Done: JMP @CB_Finish ; Outa Here! - + ; Copy Left Edge of Bitmap - + @CB_Left_Band: - + OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask - + MOV CX, [BP].CB_Height ; CX = # of Lines to Copy MOV DX, SCREEN_WIDTH ; DX = Width of Screen - CLR BX ; BX = Offset into Image - + mov bx,0 ; BX = Offset into Image + @CB_Left_Loop: MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished - + MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPx CX, @CB_Left_Loop ; Loop until Finished - + @CB_Left_Done: INC DI ; Move Dest Over 1 band INC SI ; Move Source Over 1 band DEC [BP].CB_Width ; Band Width-- - + ; Determine if Right Edge of Bitmap needs special copy - + @CB_Check_Right: MOV BX, [BP].CB_X2 ; Get Source X2 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?) CMP BL, 03h ; Plane = 3? JE @CB_Copy_Middle ; Copy the Middle then! - + ; Copy Right Edge of Bitmap - + @CB_Right_Band: - + OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask - + DEC [BP].CB_Width ; Band Width-- MOV CX, [BP].CB_Height ; CX = # of Lines to Copy MOV DX, SCREEN_WIDTH ; DX = Width of Screen MOV BX, [BP].CB_Width ; BX = Offset to Right Edge - + @CB_Right_Loop: MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished - + MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPx CX, @CB_Right_Loop ; Loop until Finished - + @CB_Right_Done: - + ; Copy the Main Block of the Bitmap - + @CB_Copy_Middle: - + MOV CX, [BP].CB_Width ; Get Width Remaining JCXZ @CB_Finish ; Exit if Done - + OUT_8 SC_Data, ALL_PLANES ; Copy all Planes - + MOV DX, SCREEN_WIDTH ; Get Width of Screen minus SUB DX, CX ; Image width (for Adjustment) MOV AX, [BP].CB_Height ; AX = # of Lines to Copy MOV BX, CX ; BX = Quick REP reload count MOV CX, ES ; Move VGA Segment MOV DS, CX ; Into DS - + ; Actual Copy Loop. REP MOVSB does the work - + @CB_Middle_Copy: MOV CX, BX ; Recharge Rep Count REP MOVSB ; Move Bands LOOPjz AX, @CB_Finish ; Exit Loop if Finished - + ADD SI, DX ; Adjust DS:SI to Next Line ADD DI, DX ; Adjust ES:DI to Next Line - + MOV CX, BX ; Recharge Rep Count REP MOVSB ; Move Bands - + ADD SI, DX ; Adjust DS:SI to Next Line ADD DI, DX ; Adjust ES:DI to Next Line LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done - + @CB_Finish: OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on - + @CB_Exit: ADD SP, 04 ; Deallocate stack workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 16 ; Exit and Clean up Stack - + COPY_BITMAP ENDP - + END ; End of Code Segment diff --git a/src/lib/modex/modex.h b/src/lib/modex/modex.h index 7de25a63..1381abb6 100755 --- a/src/lib/modex/modex.h +++ b/src/lib/modex/modex.h @@ -1,9 +1,9 @@ - + #ifndef __MODEX_H #define __MODEX_H - + /* ===== SCREEN RESOLUTIONS ===== */ - + #define Mode_320x200 0 #define Mode_320x400 1 #define Mode_360x200 2 @@ -12,14 +12,14 @@ #define Mode_320x480 5 #define Mode_360x240 6 #define Mode_360x480 7 - + /* ===== MODE X SETUP ROUTINES ===== */ - + int far pascal set_vga_modex (int Mode, int MaxXpos, int MaxYpos, int Pages); int far pascal set_modex (int Mode); - + /* ===== BASIC GRAPHICS PRIMITIVES ===== */ - + void far pascal clear_vga_screen (int Color); void far pascal set_point (int Xpos, int Ypos, int Color); int far pascal read_point (int Xpos, int Ypos); @@ -27,18 +27,18 @@ void far pascal fill_block (int Xpos1, int Ypos1, int Xpos2, int Ypos2, int Color); void far pascal draw_line (int Xpos1, int Ypos1, int Xpos2, int Ypos2, int Color); - + /* ===== DAC COLOR REGISTER ROUTINES ===== */ - + void far pascal set_dac_register (int RegNo, int Red, int Green, int Blue); void far pascal get_dac_register (int RegNo, int* Red, int* Green, int* Blue); void far pascal load_dac_registers (char far *PalData, int StartReg, int EndReg, int VSync); void far pascal readd_dac_registers (char far *PalData, int StartReg, int EndReg); - + /* ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== */ - + void far pascal set_active_page (int PageNo); int far pascal get_active_page (void); void far pascal set_display_page (int PageNo); @@ -47,9 +47,9 @@ void far pascal set_window (int DisplayPage, int XOffset, int YOffset); int far pascal get_x_offset (void); int far pascal get_y_offset (void); void far pascal sync_display (void); - + /* ===== TEXT DISPLAY ROUTINES ===== */ - + void far pascal gprintc (int CharNum, int Xpos, int Ypos, int ColorF, int ColorB); void far pascal tgprintc (int CharNum, int Xpos, int Ypos, int ColorF); @@ -58,19 +58,19 @@ void far pascal print_str (char far *Text, int MaxLen, int Xpos, int Ypos, void far pascal tprint_str (char far *Text, int MaxLen, int Xpos, int Ypos, int ColorF); void far pascal set_display_font (char far *FontData, int FontNumber); - + /* ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== */ - + void far pascal draw_bitmap (char far *Image, int Xpos, int Ypos, int Width, int Height); void far pascal tdraw_bitmap (char far *Image, int Xpos, int Ypos, int Width, int Height); - + /* ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== */ - + void far pascal copy_page (int SourcePage, int DestPage); void far pascal copy_bitmap (int SourcePage, int X1, int Y1, int X2, int Y2, int DestPage, int DestX1, int DestY1); - - + + #endif diff --git a/src/lib/modex/utls-asm.bat b/src/lib/modex/utls-asm.bat new file mode 100755 index 00000000..d996978f --- /dev/null +++ b/src/lib/modex/utls-asm.bat @@ -0,0 +1 @@ +MASM c_utils, c_utils, c_utils, nul; \ No newline at end of file diff --git a/src/lib/modex/w.sh b/src/lib/modex/w.sh new file mode 100755 index 00000000..4483916f --- /dev/null +++ b/src/lib/modex/w.sh @@ -0,0 +1,3 @@ +#! /bin/bash +wmake clean;wmake +cp x_demo.exe ../../../ diff --git a/src/lib/modex/x.exe b/src/lib/modex/x.exe new file mode 100755 index 00000000..7742d145 Binary files /dev/null and b/src/lib/modex/x.exe differ diff --git a/src/lib/modex/x_demo.c b/src/lib/modex/x_demo.c new file mode 100755 index 00000000..dfe9a3e0 --- /dev/null +++ b/src/lib/modex/x_demo.c @@ -0,0 +1,786 @@ +/* X-DEMO.C - a Mode "X" Demo */ +/* By Matt Pritchard, 14 Apr, 1993 */ + +#include +#include + +#include "modex.h" +#include "c_utils.h" + +#define MAX_SHAPES 32 +#define MAX_SPRITES 64 + + /* routines in this file */ + +void demo_res (int, int, int); +int get_key (void); +void error_out (char*); +void load_shapes (void); +int int_sqrt (int, int); +void page_demo (void); + + /* Structures for Sprites */ + +struct Shape +{ + unsigned char Image[512]; + int X_Width; + int Y_Width; +} Img [MAX_SHAPES]; + +struct Sprite +{ + int X_pos; + int Y_pos; + int X_Dir; + int Y_Dir; + int Shape; + int Last_X [2]; + int Last_Y [2]; +} Obj [MAX_SPRITES]; + + + /* MAIN */ + + +int main(int argc, char *argv[]) +{ + + /* if (argc > 0) + { + while (argc > 0) + { + dos_print ("Unknown Argument: "); + dos_print (makefp argv[argc]); + argc--; + } + return (0); + + } + */ + + init_random (); + + load_shapes (); + + demo_res ( Mode_320x200, 320, 200 ); + demo_res ( Mode_320x400, 320, 400 ); + + demo_res ( Mode_360x200, 360, 200 ); + demo_res ( Mode_360x400, 360, 400 ); + + demo_res ( Mode_320x240, 320, 240 ); + demo_res ( Mode_320x480, 320, 480 ); + + demo_res ( Mode_360x240, 360, 240 ); + demo_res ( Mode_360x480, 360, 480 ); + + page_demo (); + + set_video_mode (3); + dos_print ("This Mode X Demo is Finished"); + return (0); + +} + + + /* Demonstrate a given resolution */ + + +void demo_res (int Screen_Mode, int X_max, int Y_max) +{ + +char *Error1 = "Failure while calling SET_MODEX"; +char *Error2 = "Failure during READ_PIXEL test"; + +char *Abort_Msg = "Demo aborted by User"; + +char *Demo_Msg = " This is a MODE X demo "; +char *Scrn_Msg = "Screen Resolution is by "; +char *Cont_Msg = "Press to Continue"; + +char *Line_Msg = "LINE TEST"; +char *Fill_Msg = "FILL TEST"; +char *Pixel_Msg = "PIXEL TEST"; + +char Text[10]; + +int x1, y1, x2, y2 = 0; +int x, y, z = 0; +int X_Center, gap = 0; + + + if (set_modex (Screen_Mode) == 0) + { + error_out (Error1); + } + + X_Center = X_max / 2; + + x1 = 10; + y1 = 10; + x2 = X_max - 1; + y2 = Y_max - 1; + + for (z = 0; z <= 3; z++) + { + y = 31 - z -z; + draw_line (x1+z, y1+z, x2-z, y1+z, y); + draw_line (x1+z, y1+z, x1+z, y2-z, y); + draw_line (x1+z, y2-z, x2-z, y2-z, y); + draw_line (x2-z, y1+z, x2-z, y2-z, y); + } + + for (x = 0; x < (X_max / 10); x++) + { + tgprintc (48 + ((x+1) % 10), x*10+1, 1, 9 + ((x/8) % 7) ); + draw_line (x*10+9, 0, x*10+9, 3, c_bWHITE); + } + + for (y = 0; y < (Y_max / 10); y++) + { + tgprintc (48 + ((y+1) % 10), 1, y*10+1, 9 + ((y/10) % 7) ); + draw_line (0, y*10+9, 3, y*10+9, c_bWHITE); + } + + for (x = 0; x <= 63; x++) + { + z = 15 + (x * 3 / 4); + set_dac_register (64+x, z, z, z); + set_dac_register (128+x, 0, z, z); + + draw_line (103-x, 60, 40+x, 123, 64+x); + draw_line (40, 60+x, 103, 123-x, 128+x); + + } + + tprint_str (Line_Msg, 9, 37, 130, c_BLUE); + + y = 60; + gap = 0; + for (x = 0; x <= 9; x++) + { + fill_block (120, y, 120+x, y+gap, 64+x); + fill_block (140 - (15-x), y, 150+x, y+gap, 230+x); + fill_block (170 - (15-x), y, 170, y+gap, 128+x); + y = y + gap + 2; + gap++; + } + + tprint_str (Fill_Msg, 9, 110, 46, c_GREEN); + + for (x = 190; x <= 250; x+=2) + { + for (y = 60; y <= 122; y+=2) + { + z = (x+x+y+y) & 0xff; + set_point (x, y, z); + } + } + + tprint_str (Pixel_Msg, 10, 182, 130, c_RED); + + for (x = 190; x <= 250; x+=2) + { + for (y = 60; y <= 122; y+=2) + { + z = (x+x+y+y) & 0xff; + if (read_point(x, y) != z) + { + error_out (Error2); + } + } + } + + print_str (Demo_Msg, 23, X_Center - 92, 20, c_bRED, c_BLUE); + + x = X_Center - 124; + print_str (Scrn_Msg, 28, x, 30, c_bGREEN, c_BLACK); + + sprintf (Text, "%3d", X_max); + print_str (Text, 3, x+168, 30, c_bPURPLE, c_BLACK); + + sprintf (Text, "%3d", Y_max); + print_str (Text, 3, x + 224, 30, c_bWHITE, c_BLACK); + + for (x = 0; x <= 15; x++) + { + set_dac_register (230+x, 63-x*4, 0, 15+x*3); + draw_line (30+x, Y_max-6-x, X_max-20-x, Y_max-6-x, 230+x); + } + + tprint_str (Cont_Msg, 27, X_Center - 103, Y_max-18, c_YELLOW); + + if (get_key () == Ky_ESC) + { + error_out (Abort_Msg); + } + + return ; + +} + + + /* Wait for a Keystroke */ + + +int get_key(void) +{ + +int c = 0; + + while (c == 0) + { + c = scan_keyboard (); + } + + return (c); + +} + + + /* Error Handling Routine */ + + +void error_out (char * text) +{ + + set_video_mode (3); + dos_print (text); + exit (EXIT_SUCCESS); + +} + + + /* Routine to generate random sprites */ + + +void load_shapes () +{ + +unsigned char Grid[33][33]; + +char *Error1 = "Bad Shape Selected Error"; + +int Shape; +int x, y, z; +int Style, Color; +int X_Width, Y_Width, Center, S_Width; +int Hollow_X, Hollow_Y; + + for (Shape = 0; Shape < MAX_SHAPES; Shape++) + { + for (y = 0; y <= 32; y++) + { + for (x = 0; x <= 32; x++) + { + Grid[x][y] = c_BLACK; + } + } + + Style = random_int (6); + Color = 1 + random_int (15); + + switch (Style) + + { + /* SOLID BOXES */ + + case 0: + + { + do + { + X_Width = 3 + random_int(30); + Y_Width = 3 + random_int(30); + + } while ( (X_Width * Y_Width) >= 512); + + for (x = 1; x <= X_Width; x++) + { + for (y = 1; y <= Y_Width; y++) + { + Grid[x][y] = Color; + } + } + + break; + + } + /* HOLLOW BOXES */ + + case 1: + + { + do { + X_Width = 6 + random_int(27); + Y_Width = 6 + random_int(27); + } while ( (X_Width * Y_Width) >= 512); + + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + Grid[x][y] = Color; + } + } + + Hollow_X = 1 + random_int ((X_Width / 2) -1); + Hollow_Y = 1 + random_int ((Y_Width / 2) -1); + + for (y = Hollow_Y+1; y <= Y_Width-Hollow_Y; y++) + { + for (x = Hollow_X+1; x <= X_Width-Hollow_X; x++) + { + Grid[x][y] = c_BLACK; + } + } + + break; + + } + + /* SOLID DIAMOND */ + + case 2: + + { + + X_Width = 3 + 2 * random_int(10); + Y_Width = X_Width; + Center = X_Width / 2; + + for (y = 0; y <= Center; y++) + { + for (x = 0; x <= y; x++) + { + Grid [Center-x+1][y+1] = Color; + Grid [Center+x+1][y+1] = Color; + Grid [Center-x+1][Y_Width-y] = Color; + Grid [Center+x+1][Y_Width-y] = Color; + } + } + + break; + + } + + /* HOLLOW DIAMOND */ + + case 3: + + { + + X_Width = 3 + 2 * random_int(10); + Y_Width = X_Width; + Center = X_Width / 2; + S_Width = random_int (Center); + + for (y = 0; y <= Center; y++) + { + for (x = 0; x <= y; x++) + { + if ( x+(Center-y) >= S_Width ) + { + Grid [Center-x+1][y+1] = Color; + Grid [Center+x+1][y+1] = Color; + Grid [Center-x+1][Y_Width-y] = Color; + Grid [Center+x+1][Y_Width-y] = Color; + } + } + } + + break; + + } + + /* BALL */ + + case 4: + + { + + X_Width = 7 + 2 * random_int (8); + Y_Width = X_Width; + Center = 1 + X_Width / 2; + + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + z = int_sqrt(Center-x, Center-y); + if (z < Center) + { + Grid[x][y] = 150 + Color * 2 + z * 3; + } + } + } + + break; + } + + /* HOLLOW BALLS */ + + case 5: + + { + X_Width = 7 + 2 * random_int (8); + Y_Width = X_Width; + Center = 1 + X_Width / 2; + S_Width = random_int (X_Width); + + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + z = int_sqrt(Center-x, Center-y); + if ( (z < Center) && (z >= S_Width) ) + { + Grid[x][y] = 150 + Color * 2 + z * 3; + } + } + } + + + break; + } + + default: + + { + error_out (Error1); + break; + + } + + } + + z = 0; + for (y = 1; y <= Y_Width; y++) + { + for (x = 1; x <= X_Width; x++) + { + Img[Shape].Image[z] = Grid[x][y]; + z++; + } + } + + Img[Shape].X_Width = X_Width; + Img[Shape].Y_Width = Y_Width; + + } + + return; +} + + + /* Quickie Psuedo Integer Square Root Routine */ + + +int int_sqrt ( int x, int y ) +{ + +int Sqr_Table[12] = {1, 4, 9, 6, 25, 36, 49, 64, 81, 100, 121, 144}; + +int r, d; + + d = (x * x) + (y * y); + r = 0; + + while ( d >= Sqr_Table[r] ) + { + r++; + } + + return (r); + +} + + + /* The Bit Sprite Demo */ + + +void page_demo () +{ + +char *Error1 = "Failure during SET_VGA_MODEX (0, 320, 200, 2) call"; + +int Last_Objects[2], Visible_Objects; + +int Screen_X = 384; +int Screen_Y = 224; + +int x, y, z; +int c, dc; +int x1, y1, x2, y2; + +int Sprite_X, Sprite_Y; +int Current_Page; +int New_X, New_Y; + +int View_X, View_Y, View_Max, View_Cnt, View_XD, View_YD; +int Set_Color, Prev_Color, S_Dir, P_Dir; + +int Demo_Running = True; +int redo, code; + +int pee; +pee = set_vga_modex(Mode_320x200, Screen_X, Screen_Y, 3); + if ( pee > 0) + { + set_video_mode (3); + dos_print (Error1); + fprintf(stdout, "return value is %d\n", pee); + //error_out (Error1); + exit (EXIT_SUCCESS); + } + + set_active_page (0); + clear_vga_screen (c_BLACK); + + print_str ("This is a Test of the Following Functions:", 99, 10, 9, c_bWHITE, c_BLACK); + + draw_line (10, 18, 350, 18, c_YELLOW); + print_str ("SET_ACTIVE_PAGE", 99, 10, 20, c_bBLUE, c_BLACK); + print_str ("SET_DISPLAY_PAGE", 99, 10, 30, c_GREEN, c_BLACK); + print_str ("SET_DAC_REGISTER", 99, 10, 40, c_RED, c_BLACK); + print_str ("CLEAR_VGA_SCREEN", 99, 10, 50, c_CYAN, c_BLACK); + + print_str ("TDRAW_BITMAP", 99, 10, 60, c_PURPLE, c_BLACK); + print_str ("COPY_PAGE", 99, 10, 70, c_GREEN, c_BLACK); + print_str ("COPY_BITMAP", 99, 10, 80, c_CYAN, c_BLACK); + + print_str ("GPRINTC", 99, 10, 90, c_BLUE, c_BLACK); + print_str ("TGPRINTC", 99, 10, 100, c_GREEN, c_BLACK); + print_str ("SET_WINDOW", 99, 10, 110, c_RED, c_BLACK); + + print_str ("VIRTUAL SCREEN SIZES", 20, 190, 20, c_bBLUE, c_BLACK); + print_str (" SMOOTH SCROLLING", 20, 190, 30, c_GREEN, c_BLACK); + print_str (" SPRITE ANIMATION", 20, 190, 40, c_CYAN, c_BLACK); + print_str (" PAGE FLIPPING", 20, 190, 50, c_RED, c_BLACK); + print_str (" COLOR CYCLING", 20, 190, 60, c_PURPLE, c_BLACK); + + for (x = 0; x <=60; x++) + { + set_dac_register (50 + x, 3 + x, 0, 60 - x); + set_dac_register (150 + x, 3 + x, 0, 60 - x); + } + + c = 0; + dc = 1; + for (x = 0; x <= (Screen_X / 2); x++) + { + draw_line (Screen_X / 2 - 1, Screen_Y / 4, x, Screen_Y - 1, c + 50); + draw_line (Screen_X / 2, Screen_Y / 4, Screen_X - x - 1, Screen_Y - 1, c + 50); + c+= dc; + if ((c == 0) || (c == 60) ) { dc = -dc;} + } + + tprint_str ("Press to Continue", 99, 72, 190, c_bWHITE); + tprint_str ("< > = Faster < > = Slower", 99, 72, 204, c_bGREEN); + tprint_str ("< > = Fewer Shapes < > = More Shapes", 99, 32, 218, c_bCYAN); + + tgprintc (43, 80, 204, c_YELLOW); + tgprintc (45, 200, 204, c_YELLOW); + + tgprintc (25, 40, 218, c_YELLOW); + tgprintc (24, 200, 218, c_YELLOW); + + copy_page (0, 1); + copy_page (0, 2); + + for (x = 0; x < MAX_SPRITES; x++) + { + do { + Obj[x].X_Dir = random_int(7) - 3; + Obj[x].Y_Dir = random_int(7) - 3; + } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) ); + + Obj[x].Shape = x % MAX_SHAPES; + + Sprite_X = Img[Obj[x].Shape].X_Width; + Sprite_Y = Img[Obj[x].Shape].Y_Width; + + Obj[x].X_pos = 1 + random_int(Screen_X - Sprite_X - 2); + Obj[x].Y_pos = 1 + random_int(Screen_Y - Sprite_Y - 2); + + Obj[x].Last_X[0] = Obj[x].X_pos; + Obj[x].Last_X[1] = Obj[x].X_pos; + Obj[x].Last_Y[0] = Obj[x].Y_pos; + Obj[x].Last_Y[1] = Obj[x].Y_pos; + + } + + Current_Page = 0; + + View_X = 0; + View_Y = 0; + View_Max = 3; + View_Cnt = 0; + View_XD = 1; + View_YD = 1; + + Set_Color = 3; + S_Dir = 1; + Prev_Color = 0; + P_Dir = 1; + + Visible_Objects = MAX_SPRITES / 2; + Last_Objects[0] = 0; + Last_Objects[1] = 0; + + while (Demo_Running) + { + + set_active_page (Current_Page); + + /* Erase Old Images */ + + for (x = 0; x <= Last_Objects[Current_Page]; x++) + { + z = 2; + y = Obj[x].Shape; + x1 = Obj[x].Last_X[Current_Page]; + y1 = Obj[x].Last_Y[Current_Page]; + x2 = x1 + Img[y].X_Width -1; + y2 = y1 + Img[y].Y_Width -1; + + x1 = x1 & 0xfffc; + x2 = x2 | 0x0003; + + copy_bitmap (z, x1, y1, x2, y2, Current_Page, x1, y1); + } + + /* Draw new images */ + + for (x = 0; x <= Visible_Objects; x++) + { + Sprite_X = Img[Obj[x].Shape].X_Width; + Sprite_Y = Img[Obj[x].Shape].Y_Width; + + /* Move Sprite */ + + do + { + redo = False; + New_X = Obj[x].X_pos + Obj[x].X_Dir; + + if (( New_X < 0 ) || (New_X + Sprite_X > Screen_X) ) + { + Obj[x].X_Dir = -Obj[x].X_Dir; + if (random_int(20) == 1) + { + do + { + Obj[x].X_Dir = random_int(7) - 3; + Obj[x].Y_Dir = random_int(7) - 3; + } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) ); + redo = True; + } + } + } while (redo); + Obj[x].X_pos = Obj[x].X_pos + Obj[x].X_Dir; + + + do + { + redo = False; + New_Y = Obj[x].Y_pos + Obj[x].Y_Dir; + + if ( (New_Y < 0) || (New_Y + Sprite_Y > Screen_Y) ) + { + Obj[x].Y_Dir = -Obj[x].Y_Dir; + if (random_int(20) == 1) + { + do + { + Obj[x].X_Dir = random_int(7) - 3; + Obj[x].Y_Dir = random_int(7) - 3; + } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) ); + redo = True; + } + } + } while (redo); + + Obj[x].Y_pos = Obj[x].Y_pos + Obj[x].Y_Dir; + + /* Draw Sprite */ + + tdraw_bitmap ((char far*) &Img[Obj[x].Shape], Obj[x].X_pos, Obj[x].Y_pos, Sprite_X, Sprite_Y); + + Obj[x].Last_X[Current_Page] = Obj[x].X_pos; + Obj[x].Last_Y[Current_Page] = Obj[x].Y_pos; + + } + + Last_Objects[Current_Page] = Visible_Objects; + + + /* Pan Screen Back & Forth */ + + View_Cnt++; + if (View_Cnt >= View_Max) + { + View_X+= View_XD; + if ( (View_X == 0) || (View_X == 39) ) {View_XD = -View_XD;} + if (View_XD < 0) + { + View_Y+= View_YD; + if ( (View_Y == 0) || (View_Y == 39) ) {View_YD = -View_YD;} + } + + set_window (Current_Page, View_X, View_Y); + + View_Cnt = 0; + } + else + { + set_display_page (Current_Page); + } + + /* Cycle Colors */ + + set_dac_register (50 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color); + set_dac_register (50 + Set_Color, Set_Color, 10, 63 - Set_Color); + + set_dac_register (150 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color); + set_dac_register (150 + Set_Color, 63, 63, Set_Color); + + Set_Color+= S_Dir; + if ( (Set_Color == 60) || (Set_Color == 0) ) {S_Dir = -S_Dir;} + + Prev_Color+= P_Dir; + if ( (Prev_Color == 60) || (Prev_Color == 0) ) {P_Dir = -P_Dir;} + + /* Check for Keystroke */ + + Current_Page = Current_Page ^ 0x01; + + code = scan_keyboard (); + + if (code == Ky_ESC) {Demo_Running = False;} + + if (code == Ky_Plus) + { + if (View_Max < 12) {View_Max++;} + } + + if (code == Ky_Minus) + { + if (View_Max > 1) {View_Max--;} + if (View_Cnt >= View_Max) {View_Cnt = 0;} + } + + if (code == Ky_Up) + { + if (Visible_Objects < MAX_SPRITES-1) {Visible_Objects++;} + } + + if (code == Ky_Down) + { + if (Visible_Objects > 0) {Visible_Objects--;} + } + + } + +} diff --git a/src/lib/modex/x_demo.dsk b/src/lib/modex/x_demo.dsk new file mode 100755 index 00000000..5573e71a Binary files /dev/null and b/src/lib/modex/x_demo.dsk differ diff --git a/x-demo.exe b/src/lib/modex/x_demo.exe similarity index 86% rename from x-demo.exe rename to src/lib/modex/x_demo.exe index b4fee914..75369aba 100755 Binary files a/x-demo.exe and b/src/lib/modex/x_demo.exe differ diff --git a/src/lib/modex/x_demo.prj b/src/lib/modex/x_demo.prj new file mode 100755 index 00000000..b3f307e5 Binary files /dev/null and b/src/lib/modex/x_demo.prj differ diff --git a/xdemo.smp b/x-demo.smp similarity index 100% rename from xdemo.smp rename to x-demo.smp diff --git a/x_demo.exe b/x_demo.exe new file mode 100755 index 00000000..75369aba Binary files /dev/null and b/x_demo.exe differ