From 2f38659706ee4cf884c7b4d13449da4f3aaf9a61 Mon Sep 17 00:00:00 2001 From: sparky4 Date: Mon, 23 Nov 2015 16:22:28 -0600 Subject: [PATCH] wwww --- src/lib/modex/c_utils.asm | 456 +++++ src/lib/modex/c_utils.h | 117 ++ src/lib/modex/c_utils.lst | 597 +++++++ src/lib/modex/c_utils.sbr | Bin 0 -> 1731 bytes src/lib/modex/makefile | 30 + src/lib/modex/modex.asm | 2138 +++++++++++++----------- src/lib/modex/modex.h | 38 +- src/lib/modex/utls-asm.bat | 1 + src/lib/modex/w.sh | 3 + src/lib/modex/x.exe | Bin 0 -> 41090 bytes src/lib/modex/x_demo.c | 786 +++++++++ src/lib/modex/x_demo.dsk | Bin 0 -> 195 bytes x-demo.exe => src/lib/modex/x_demo.exe | Bin 58495 -> 58447 bytes src/lib/modex/x_demo.prj | Bin 0 -> 4936 bytes xdemo.smp => x-demo.smp | Bin x_demo.exe | Bin 0 -> 58447 bytes 16 files changed, 3183 insertions(+), 983 deletions(-) create mode 100755 src/lib/modex/c_utils.asm create mode 100755 src/lib/modex/c_utils.h create mode 100755 src/lib/modex/c_utils.lst create mode 100755 src/lib/modex/c_utils.sbr create mode 100755 src/lib/modex/makefile create mode 100755 src/lib/modex/utls-asm.bat create mode 100755 src/lib/modex/w.sh create mode 100755 src/lib/modex/x.exe create mode 100755 src/lib/modex/x_demo.c create mode 100755 src/lib/modex/x_demo.dsk rename x-demo.exe => src/lib/modex/x_demo.exe (86%) create mode 100755 src/lib/modex/x_demo.prj rename xdemo.smp => x-demo.smp (100%) create mode 100755 x_demo.exe 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 0000000000000000000000000000000000000000..0301171bdd90f778ed3f244b37130f9388df7f0a GIT binary patch literal 1731 zcmZ8hU1(fY5dQAuK&p#UAC#&fKJ+1i$i~{%wn9$2yN#Fb?%mvb6JlMtU9-E%CfnU~ zf101hwzk#OG>vU+Qxyc!2N9n{@L3cD5qwebS;PmQL{UWW!I`<6G!~ZSyEEr}b7tn7 zf#VpY4i`@p2M@?E>mDuUymV$_FuA{&&g8tHn1VAIbvw0s`>9g<6zE0t(XKMmUJw<0 zHy?s-iluVL5`exDQx!objKacF3Q)yL8lNHdY z(+7JBZZH}JozmniXxuTJN{Wv@-hiJ^M?s}hMq&mu*DsS$~{0n-MBnhI>?z>CnI#*j%$*se|?lw^L;Am0jr`8vA;!PtUtas20*?Hi0*+i(!2Hh%{}P54 z_G#P|n2N?_722Je1Nq{j!*c#C+FFi3V9shrA1PormzFJYr&ErZQ7#snRblNA+d*;C z6T-HvU7lI$73~$+6c;V1EivB_IdG1j_Y7zZ<{aoN{XZ!7^WX&1Qo0MOv0S&_QE5Hw zm^9=@G|V+G0ZTGHjWd zH094>s_NnCv^9gq`OFt0J}$u|(Chr?lQ$-gku%FnC7^3dP43Vsqdz2BReRUM4r z&SY>OS3z^Vxw#t8%}BEo)hj%!GcZ>rq*MyiYe!nkJm^fWUJyos>YWht>1?8)m$MPs3x4WckJ5rSNp>pVkJ&l@Pnu910PcFYZ} z=06a?@BBdlx8ySgOm|rU=eI`yb$hznh;_vxm~+eqXi%#~18?D2sosvCf#gltN!GXq zJMWlTO@sHZ<$b%oe<#F2_sDL&1>fD0z, ; 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 0000000000000000000000000000000000000000..7742d145c591d471d2e9b79e0fe99083a3d669f2 GIT binary patch literal 41090 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 JvY09JKLIz`z5M_H literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5573e71a90522ffd46c36a16b5c9ba8abd65ca3e GIT binary patch literal 195 zcmWG3ElSE)a8_{6&nro-C{b|B%t=*{VqoMI5@(cRVBq@7IGX`T8!-UE2HDAKJ5*pa z6Ho-Z3gyjI;~eAX Z@8{_2YG9z}91y_3NB}Z0{Qu9u001}XCCdN+ literal 0 HcmV?d00001 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 b4fee9143d4174b8284b8a72f43c7593c13fc714..75369abaeac5b4ea65201db3e49bc84a54e7aca8 100755 GIT binary patch delta 3470 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 L8ztrXEJFSVhBA8` diff --git a/src/lib/modex/x_demo.prj b/src/lib/modex/x_demo.prj new file mode 100755 index 0000000000000000000000000000000000000000..b3f307e5c005eb0b7ef8346090f3cdce82a31210 GIT binary patch literal 4936 zcmeI$`BNKZ7zgm@O#-A~Db}Nfw(zQ}_80=Bauknk*rZIHEXjm)%vh?^ge_7F!4T>l z@OE_UwDlkGZoTpR$>V2jsg6f4{|Q@fTN|J6hQZWn+>pdFF zGM12<3?&mgjCe|J8s2Hh1`>;xE))D#<)*OnGqRDO&sm~_W_-wW#%wuk`cVx&{n+#q z(@$AJUzwR-n|{OE=?J@#jXgMD=X4+Bn?8h^^o@5Cd^A2n?_t41qfs8UdpqfwsF4 zjU$>svH+T@$G?)Za;34oZc!Z%x5j_STNA(HtB&tt=r@=E| z57-O#foFlEj;R2Zpb9uav+(i`mR?+9ioD$eJ;89m)92L&{C!$rv)5Pp!1EZPXA;q- zg7_Js=gBMv2vu>#TxPH7%pCl%eN zuWoa9t&vJ!u>TfMNGhRlP!C0CK{vD*$ zV6l^&zn|iZ`uaTjg}vUNe<>xk&dhBgKTK@r=ZL%qA*IGRqom2s?fhTa!owL6P8;Ki ziDcZ6T4H1@|1O5LbGM+>no{loOI=Wr{lDP)*+HjvdQHlcJ?)+Zc)#6Z&hcCcu6&+Ce?(xLp9X6no_$}sdi8; j|AzcU&}^xtPP&3>Ff}z%Bdwy9w1SpXJvFd%1!v2jT`({0 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..75369abaeac5b4ea65201db3e49bc84a54e7aca8 GIT binary patch literal 58447 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 b<+f4w;SoHPfq$oq^=;Y`S;let_E_xSH)f$o literal 0 HcmV?d00001 -- 2.39.2