X-Git-Url: http://4ch.mooo.com/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fmodex%2Fmodex.asm;h=f2b1b5124db8b7d4f6132f68af8e718700e30f6d;hb=34abe02e0e49c2b73912babf54fc63b5cdc56284;hp=2985fd80def58c8de0feac946d8035da15985a9c;hpb=19d97c4277378f20c6c756981f4123cdc6cbb32b;p=16.git diff --git a/src/lib/modex/modex.asm b/src/lib/modex/modex.asm index 2985fd80..f2b1b512 100755 --- a/src/lib/modex/modex.asm +++ b/src/lib/modex/modex.asm @@ -82,16 +82,16 @@ ; READ_DAC_REGISTERS. Expanded CLR Macro ; to handle multiple registers ; - + PAGE 255, 132 - - .MODEL Medium - .286 - + + .MODEL Huge + ;.286 + ; ===== MACROS ===== - + ; Macro to OUT a 16 bit value to an I/O port - + OUT_16 MACRO Register, Value IFDIFI , ; If DX not setup MOV DX, Register ; then Select Register @@ -101,9 +101,9 @@ OUT_16 MACRO Register, Value ENDIF OUT DX, AX ; Set I/O Register(s) ENDM - + ; Macro to OUT a 8 bit value to an I/O Port - + OUT_8 MACRO Register, Value IFDIFI , ; If DX not setup MOV DX, Register ; then Select Register @@ -113,64 +113,63 @@ OUT_8 MACRO Register, Value ENDIF OUT DX, AL ; Set I/O Register ENDM - + ; macros to PUSH and POP multiple registers - -PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 - IFNB - PUSH R1 ; Save R1 - PUSHx R2, R3, R4, R5, R6, R7, R8 - ENDIF -ENDM - -POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 - IFNB - POP R1 ; Restore R1 - POPx R2, R3, R4, R5, R6, R7, R8 - ENDIF -ENDM - + +; PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8 +; IFNB +; PUSH R1 ; Save R1 +; PUSHx R2, R3, R4, R5, R6, R7, R8 +; ENDIF +; ENDM +; +; POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8 +; IFNB +; POP R1 ; Restore R1 +; POPx R2, R3, R4, R5, R6, R7, R8 +; ENDIF +; ENDM + ; Macro to Clear Registers to 0 - -CLR MACRO Register, R2, R3, R4, R5, R6 - IFNB - XOR Register, Register ; Set Register = 0 - CLR R2, R3, R4, R5, R6 - ENDIF -ENDM - + +; CLR MACRO Register, R2, R3, R4;, R5, R6 +; IFNB +; XOR Register, Register ; Set Register = 0 +; CLR R2, R3, R4;, R5, R6 +; ENDIF +; ENDM + ; Macros to Decrement Counter & Jump on Condition - + LOOPx MACRO Register, Destination DEC Register ; Counter-- JNZ Destination ; Jump if not 0 ENDM - + LOOPjz MACRO Register, Destination DEC Register ; Counter-- JZ Destination ; Jump if 0 ENDM - - + + ; ===== General Constants ===== - + False EQU 0 True EQU -1 nil EQU 0 - + b EQU BYTE PTR w EQU WORD PTR d EQU DWORD PTR o EQU OFFSET f EQU FAR PTR s EQU SHORT - ?x4 EQU - ?x3 EQU - + ?x1 EQU + ; ===== VGA Register Values ===== - + VGA_Segment EQU 0A000h ; Vga Memory Segment - + ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller GC_Index EQU 03CEh ; VGA Graphics Controller SC_Index EQU 03C4h ; VGA Sequencer Controller @@ -179,43 +178,43 @@ ENDM CRTC_Data EQU 03D5h ; VGA CRT Controller Data MISC_OUTPUT EQU 03C2h ; VGA Misc Register INPUT_1 EQU 03DAh ; Input Status #1 Register - + DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W - + PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg READ_MAP EQU 004h ; GC Index: Read Map Register START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo - + MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1 MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1 ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes - + CHAIN4_OFF EQU 00604h ; Chain 4 mode Off ASYNC_RESET EQU 00100h ; (A)synchronous Reset SEQU_RESTART EQU 00300h ; Sequencer Restart - + LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU - + VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane # ALL_PLANES EQU 0Fh ; All Bit Planes Selected CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data - + GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer - + ; Constants Specific for these routines - + NUM_MODES EQU 8 ; # of Mode X Variations - + ; Specific Mode Data Table format... - + Mode_Data_Table STRUC M_MiscR DB ? ; Value of MISC_OUTPUT register M_Pages DB ? ; Maximum Possible # of pages @@ -225,69 +224,69 @@ Mode_Data_Table STRUC M_YMax DW ? ; Maximum Possible Y Size M_CRTC DW ? ; Table of CRTC register values Mode_Data_Table ENDS - + ; ===== DGROUP STORAGE NEEDED (42 BYTES) ===== - + .DATA? - + SCREEN_WIDTH DW 0 ; Width of a line in Bytes SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels - + LAST_PAGE DW 0 ; # of Display Pages PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page - + PAGE_SIZE DW 0 ; Size of Page in Addr Bytes - + DISPLAY_PAGE DW 0 ; Page # currently displayed ACTIVE_PAGE DW 0 ; Page # currently active - + CURRENT_PAGE DW 0 ; Offset of current Page CURRENT_SEGMENT DW 0 ; Segment of VGA memory - + CURRENT_XOFFSET DW 0 ; Current Display X Offset CURRENT_YOFFSET DW 0 ; Current Display Y Offset - + CURRENT_MOFFSET DW 0 ; Current Start Offset - + MAX_XOFFSET DW 0 ; Current Display X Offset MAX_YOFFSET DW 0 ; Current Display Y Offset - + CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127 CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255 - + .CODE - + ; ===== DATA TABLES ===== - + ; Data Tables, Put in Code Segment for Easy Access ; (Like when all the other Segment Registers are in ; use!!) and reduced DGROUP requirements... - + ; Bit Mask Tables for Left/Right/Character Masks - + Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H - + Right_Clip_Mask DB 01H, 03H, 07H, 0FH - + ; Bit Patterns for converting character fonts - + Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH DB 01H,09H,05H,0DH,03H,0BH,07H,0FH - + ; CRTC Register Values for Various Configurations - + MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes DW 04009H ; Cell Height (1 Scan Line) DW 00014H ; Dword Mode off DW 0E317H ; turn on Byte Mode DW nil ; End of CRTC Data for 400/480 Line Mode - + MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes DW 04109H ; Cell Height (2 Scan Lines) DW 00014H ; Dword Mode off DW 0E317H ; turn on Byte Mode DW nil ; End of CRTC Data for 200/240 Line Mode - + MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels DW 05F00H ; Horz total DW 04F01H ; Horz Displayed @@ -296,7 +295,7 @@ MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels DW 05404H ; Start H Sync DW 08005H ; End H Sync DW nil ; End of CRTC Data for 320 Horz pixels - + MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels DW 06B00H ; Horz total DW 05901H ; Horz Displayed @@ -305,7 +304,7 @@ MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels DW 05E04H ; Start H Sync DW 08A05H ; End H Sync DW nil ; End of CRTC Data for 360 Horz pixels - + MODE_200_Tall: MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes DW 0BF06H ; Vertical Total @@ -316,7 +315,7 @@ MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes DW 09615H ; V Blank Start DW 0B916H ; V Blank End DW nil ; End of CRTC Data for 200/400 Lines - + MODE_240_Tall: MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes DW 00D06H ; Vertical Total @@ -327,100 +326,100 @@ MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes DW 0E715H ; V Blank Start DW 00616H ; V Blank End DW nil ; End of CRTC Data for 240/480 Lines - + ; Table of Display Mode Tables - + MODE_TABLE: DW o MODE_320x200, o MODE_320x400 DW o MODE_360x200, o MODE_360x400 DW o MODE_320x240, o MODE_320x480 DW o MODE_360x240, o MODE_360x480 - + ; Table of Display Mode Components - + MODE_320x200: ; Data for 320 by 200 Pixels - + DB 063h ; 400 scan Lines & 25 Mhz Clock DB 4 ; Maximum of 4 Pages DW 320, 200 ; Displayed Pixels (X,Y) DW 1302, 816 ; Max Possible X and Y Sizes - + DW o MODE_320_Wide, o MODE_200_Tall DW o MODE_Double_Line, nil - + MODE_320x400: ; Data for 320 by 400 Pixels - + DB 063h ; 400 scan Lines & 25 Mhz Clock DB 2 ; Maximum of 2 Pages DW 320, 400 ; Displayed Pixels X,Y DW 648, 816 ; Max Possible X and Y Sizes - + DW o MODE_320_Wide, o MODE_400_Tall DW o MODE_Single_Line, nil - + MODE_360x240: ; Data for 360 by 240 Pixels - + DB 0E7h ; 480 scan Lines & 28 Mhz Clock DB 3 ; Maximum of 3 Pages DW 360, 240 ; Displayed Pixels X,Y DW 1092, 728 ; Max Possible X and Y Sizes - + DW o MODE_360_Wide, o MODE_240_Tall DW o MODE_Double_Line , nil - + MODE_360x480: ; Data for 360 by 480 Pixels - + DB 0E7h ; 480 scan Lines & 28 Mhz Clock DB 1 ; Only 1 Page Possible DW 360, 480 ; Displayed Pixels X,Y DW 544, 728 ; Max Possible X and Y Sizes - + DW o MODE_360_Wide, o MODE_480_Tall DW o MODE_Single_Line , nil - + MODE_320x240: ; Data for 320 by 240 Pixels - + DB 0E3h ; 480 scan Lines & 25 Mhz Clock DB 3 ; Maximum of 3 Pages DW 320, 240 ; Displayed Pixels X,Y DW 1088, 818 ; Max Possible X and Y Sizes - + DW o MODE_320_Wide, o MODE_240_Tall DW o MODE_Double_Line, nil - + MODE_320x480: ; Data for 320 by 480 Pixels - + DB 0E3h ; 480 scan Lines & 25 Mhz Clock DB 1 ; Only 1 Page Possible DW 320, 480 ; Displayed Pixels X,Y DW 540, 818 ; Max Possible X and Y Sizes - + DW o MODE_320_WIDE, o MODE_480_Tall DW o MODE_Single_Line, nil - + MODE_360x200: ; Data for 360 by 200 Pixels - + DB 067h ; 400 scan Lines & 28 Mhz Clock DB 3 ; Maximum of 3 Pages DW 360, 200 ; Displayed Pixels (X,Y) DW 1302, 728 ; Max Possible X and Y Sizes - + DW o MODE_360_Wide, MODE_200_Tall DW o MODE_Double_Line, nil - + MODE_360x400: ; Data for 360 by 400 Pixels - + DB 067h ; 400 scan Lines & 28 Mhz Clock DB 1 ; Maximum of 1 Pages DW 360, 400 ; Displayed Pixels X,Y DW 648, 816 ; Max Possible X and Y Sizes - + DW o MODE_360_Wide, MODE_400_Tall DW o MODE_Single_Line, nil - - + + ; ===== MODE X SETUP ROUTINES ===== - + ;====================================================== ;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%) ;====================================================== @@ -445,118 +444,149 @@ MODE_360x400: ; Data for 360 by 400 Pixels ; MaxYpos = The Desired Virtual Screen Height ; Pages = The Desired # of Video Pages ; -; EXIT: AX = Success Flag: 0 = Failure / -1= Success +; EXIT: AX = Success Flag: >0 = Failure / 0 = Success ; - + SVM_STACK STRUC SVM_Table DW ? ; Offset of Mode Info Table - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP DD ? ; Caller SVM_Pages DW ? ; # of Screen Pages desired SVM_Ysize DW ? ; Vertical Screen Size Desired SVM_Xsize DW ? ; Horizontal Screen Size Desired SVM_Mode DW ? ; Display Resolution Desired SVM_STACK ENDS - + PUBLIC SET_VGA_MODEX - + SET_VGA_MODEX PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 2 ; Allocate workspace MOV BP, SP ; Set up Stack Frame - + ; Check Legality of Mode Request.... - + MOV BX, [BP].SVM_Mode ; Get Requested Mode # CMP BX, NUM_MODES ; Is it 0..7? - JAE @SVM_BadModeSetup ; If Not, Error out - + JAE @SVM_BadModeSetup1 ; If Not, Error out + SHL BX, 1 ; Scale BX MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info MOV [BP].SVM_Table, SI ; Save ptr for later use - + ; Check # of Requested Display Pages - + MOV CX, [BP].SVM_Pages ; Get # of Requested Pages - CLR CH ; Set Hi Word = 0! + ;CLR CH ; Set Hi Word = 0! + mov ch,0 ; Set Hi Word = 0! CMP CL, CS:[SI].M_Pages ; Check # Pages for mode - JA @SVM_BadModeSetup ; Report Error if too Many Pages - JCXZ @SVM_BadModeSetup ; Report Error if 0 Pages - + JA @SVM_BadModeSetup2 ; Report Error if too Many Pages + JCXZ @SVM_BadModeSetup3 ; Report Error if 0 Pages + ; Check Validity of X Size - + AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0 - + MOV AX, [BP].SVM_XSize ; Get Logical Screen Width CMP AX, CS:[SI].M_XSize ; Check against Displayed X - JB @SVM_BadModeSetup ; Report Error if too small + JB @SVM_BadModeSetup4 ; Report Error if too small CMP AX, CS:[SI].M_XMax ; Check against Max X - JA @SVM_BadModeSetup ; Report Error if too big - + JA @SVM_BadModeSetup5 ; Report Error if too big + ; Check Validity of Y Size - + MOV BX, [BP].SVM_YSize ; Get Logical Screen Height CMP BX, CS:[SI].M_YSize ; Check against Displayed Y - JB @SVM_BadModeSetup ; Report Error if too small + JB @SVM_BadModeSetup6 ; Report Error if too small CMP BX, CS:[SI].M_YMax ; Check against Max Y - JA @SVM_BadModeSetup ; Report Error if too big - + JA @SVM_BadModeSetup7 ; Report Error if too big + ; Enough memory to Fit it all? - - SHR AX, 2 ; # of Bytes:Line = XSize/4 + + SHR AX, 1 ; # of Bytes:Line = XSize/4 + SHR AX, 1 ; # of Bytes:Line = XSize/4 MUL CX ; AX = Bytes/Line * Pages MUL BX ; DX:AX = Total VGA mem needed JNO @SVM_Continue ; Exit if Total Size > 256K - + DEC DX ; Was it Exactly 256K??? OR DX, AX ; (DX = 1, AX = 0000) JZ @SVM_Continue ; if so, it's valid... - + + jmp @SVM_Continue;0000 + @SVM_BadModeSetup: - - CLR AX ; Return Value = False + mov ax,8 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup1: + mov ax,1 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup2: + mov ax,2 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup3: + mov ax,3 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup4: + mov ax,4 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup5: + mov ax,5 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup6: + mov ax,6 ; Return Value = False + JMP @SVM_Exit ; Normal Exit +@SVM_BadModeSetup7: + mov ax,7 ; Return Value = False JMP @SVM_Exit ; Normal Exit - + @SVM_Continue: - + MOV AX, 13H ; Start with Mode 13H INT 10H ; Let BIOS Set Mode - + OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ... - + OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register INC DX ; Point to Data IN AL, DX ; Get Value, Bit 7 = Protect AND AL, 7FH ; Mask out Write Protect OUT DX, AL ; And send it back - + MOV DX, CRTC_INDEX ; Vga Crtc Registers ADD SI, M_CRTC ; SI -> CRTC Parameter Data - + ; Load Tables of CRTC Parameters from List of Tables - + @SVM_Setup_Table: - + MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl ADD SI, 2 ; Point to next Ptr Entry OR DI, DI ; A nil Ptr means that we have JZ @SVM_Set_Data ; finished CRTC programming - + @SVM_Setup_CRTC: MOV AX, CS:[DI] ; Get CRTC Data from Table ADD DI, 2 ; Advance Pointer OR AX, AX ; At End of Data Table? JZ @SVM_Setup_Table ; If so, Exit & get next Table - + OUT DX, AX ; Reprogram VGA CRTC reg JMP s @SVM_Setup_CRTC ; Process Next Table Entry - + ; Initialize Page & Scroll info, DI = 0 - + @SVM_Set_Data: MOV DISPLAY_PAGE, DI ; Display Page = 0 MOV ACTIVE_PAGE, DI ; Active Page = 0 @@ -564,88 +594,93 @@ SET_VGA_MODEX PROC FAR MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0 MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0 MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0 - + MOV AX, VGA_SEGMENT ; Segment for VGA memory MOV CURRENT_SEGMENT, AX ; Save for Future LES's - + ; Set Logical Screen Width, X Scroll and Our Data - + MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info MOV AX, [BP].SVM_Xsize ; Get Display Width - + MOV CX, AX ; CX = Logical Width SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value MOV MAX_XOFFSET, CX ; Set Maximum X Scroll - - SHR AX, 2 ; Bytes = Pixels / 4 + + SHR AX, 1 ; Bytes = Pixels / 4 + SHR AX, 1 ; Bytes = Pixels / 4 MOV SCREEN_WIDTH, AX ; Save Width in Pixels - + SHR AX, 1 ; Offset Value = Bytes / 2 MOV AH, 13h ; CRTC Offset Register Index XCHG AL, AH ; Switch format for OUT OUT DX, AX ; Set VGA CRTC Offset Reg - + ; Setup Data table, Y Scroll, Misc for Other Routines - + MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height - + MOV CX, AX ; CX = Logical Height SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll - + MOV SCREEN_HEIGHT, AX ; Save Height in Pixels MUL SCREEN_WIDTH ; AX = Page Size in Bytes, MOV PAGE_SIZE, AX ; Save Page Size - + MOV CX, [BP].SVM_Pages ; Get # of Pages MOV LAST_PAGE, CX ; Save # of Pages - - CLR BX ; Page # = 0 + + mov bx,0 ; Page # = 0 MOV DX, BX ; Page 0 Offset = 0 - + @SVM_Set_Pages: - + MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset ADD BX, 2 ; Page#++ ADD DX, AX ; Compute Addr of Next Page LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set - + ; Clear VGA Memory - + OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes LES DI, d CURRENT_PAGE ; -> Start of VGA memory - - CLR AX ; AX = 0 + + mov ax,0 ; AX = 0 CLD ; Block Xfer Forwards MOV CX, 8000H ; 32K * 4 * 2 = 256K REP STOSW ; Clear dat memory! - + ; Setup Font Pointers - + MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127 MOV AX, GET_CHAR_PTR ; Service to Get Pointer INT 10h ; Call VGA BIOS - + MOV CHARSET_LOW, BP ; Save Char Set Offset MOV CHARSET_LOW+2, ES ; Save Char Set Segment - + MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255 MOV AX, GET_CHAR_PTR ; Service to Get Pointer INT 10h ; Call VGA BIOS - + MOV CHARSET_HI, BP ; Save Char Set Offset MOV CHARSET_HI+2, ES ; Save Char Set Segment - + MOV AX, True ; Return Success Code - + @SVM_EXIT: ADD SP, 2 ; Deallocate workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 8 ; Exit & Clean Up Stack - + SET_VGA_MODEX ENDP - - + + ;================== ;SET_MODEX% (Mode%) ;================== @@ -657,47 +692,51 @@ SET_VGA_MODEX ENDP ; ; EXIT: AX = Success Flag: 0 = Failure / -1= Success ; - + SM_STACK STRUC DW ?,? ; BP, SI DD ? ; Caller SM_Mode DW ? ; Desired Screen Resolution SM_STACK ENDS - + PUBLIC SET_MODEX - + SET_MODEX PROC FAR - - PUSHx BP, SI ; Preserve Important registers + + ;PUSHx BP, SI ; Preserve Important registers + push bp + push si MOV BP, SP ; Set up Stack Frame - - CLR AX ; Assume Failure + + mov ax,0 ; Assume Failure MOV BX, [BP].SM_Mode ; Get Desired Mode # CMP BX, NUM_MODES ; Is it a Valid Mode #? JAE @SMX_Exit ; If Not, don't Bother - + PUSH BX ; Push Mode Parameter - + SHL BX, 1 ; Scale BX to word Index MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info - + PUSH CS:[SI].M_XSize ; Push Default X Size PUSH CS:[SI].M_Ysize ; Push Default Y size MOV AL, CS:[SI].M_Pages ; Get Default # of Pages - CLR AH ; Hi Byte = 0 + mov ah,0 ; Hi Byte = 0 PUSH AX ; Push # Pages - + CALL f SET_VGA_MODEX ; Set up Mode X! - + @SMX_Exit: - POPx SI, BP ; Restore Registers + ;POPx SI, BP ; Restore Registers + pop si + pop bp RET 2 ; Exit & Clean Up Stack - + SET_MODEX ENDP - - + + ; ===== BASIC GRAPHICS PRIMITIVES ===== - + ;============================ ;CLEAR_VGA_SCREEN (ColorNum%) ;============================ @@ -708,37 +747,41 @@ SET_MODEX ENDP ; ; EXIT: No meaningful values returned ; - + CVS_STACK STRUC DW ?,? ; DI, BP DD ? ; Caller CVS_COLOR DB ?,? ; Color to Set Screen to CVS_STACK ENDS - + PUBLIC CLEAR_VGA_SCREEN - + CLEAR_VGA_SCREEN PROC FAR - - PUSHx BP, DI ; Preserve Important Registers + + ;PUSHx BP, DI ; Preserve Important Registers + push bp + push di MOV BP, SP ; Set up Stack Frame - + OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AL, [BP].CVS_COLOR ; Get Color MOV AH, AL ; Copy for Word Write CLD ; Block fill Forwards - + MOV CX, PAGE_SIZE ; Get Size of Page SHR CX, 1 ; Divide by 2 for Words REP STOSW ; Block Fill VGA memory - - POPx DI, BP ; Restore Saved Registers + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp RET 2 ; Exit & Clean Up Stack - + CLEAR_VGA_SCREEN ENDP - - + + ;=================================== ;SET_POINT (Xpos%, Ypos%, ColorNum%) ;=================================== @@ -751,7 +794,7 @@ CLEAR_VGA_SCREEN ENDP ; ; EXIT: No meaningful values returned ; - + SP_STACK STRUC DW ?,? ; BP, DI DD ? ; Caller @@ -759,38 +802,43 @@ SP_STACK STRUC SETP_Ypos DW ? ; Y pos of Point to Plot SETP_Xpos DW ? ; X pos of Point to Plot SP_STACK ENDS - + PUBLIC SET_POINT - + SET_POINT PROC FAR - - PUSHx BP, DI ; Preserve Registers + + ;PUSHx BP, DI ; Preserve Registers + push bp + push di MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel MUL SCREEN_WIDTH ; Get Offset to Start of Line - + MOV BX, [BP].SETP_Xpos ; Get Xpos MOV CX, BX ; Copy to extract Plane # from - SHR BX, 2 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 ADD BX, AX ; Offset = Width*Ypos + Xpos/4 - + MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register AND CL, PLANE_BITS ; Get Plane Bits SHL AH, CL ; Get Plane Select Value OUT_16 SC_Index, AX ; Select Plane - + MOV AL,[BP].SETP_Color ; Get Pixel Color MOV ES:[DI+BX], AL ; Draw Pixel - - POPx DI, BP ; Restore Saved Registers + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp RET 6 ; Exit and Clean up Stack - + SET_POINT ENDP - - + + ;========================== ;READ_POINT% (Xpos%, Ypos%) ;========================== @@ -802,45 +850,50 @@ SET_POINT ENDP ; ; EXIT: AX = Color of Pixel at (Xpos, Ypos) ; - + RP_STACK STRUC DW ?,? ; BP, DI DD ? ; Caller RP_Ypos DW ? ; Y pos of Point to Read RP_Xpos DW ? ; X pos of Point to Read RP_STACK ENDS - + PUBLIC READ_POINT - + READ_POINT PROC FAR - - PUSHx BP, DI ; Preserve Registers + + ;PUSHx BP, DI ; Preserve Registers + push bp + push di MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AX, [BP].RP_Ypos ; Get Line # of Pixel MUL SCREEN_WIDTH ; Get Offset to Start of Line - + MOV BX, [BP].RP_Xpos ; Get Xpos MOV CX, BX - SHR BX, 2 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 + SHR BX, 1 ; X offset (Bytes) = Xpos/4 ADD BX, AX ; Offset = Width*Ypos + Xpos/4 - + MOV AL, READ_MAP ; GC Read Mask Register MOV AH, CL ; Get Xpos AND AH, PLANE_BITS ; & mask out Plane # OUT_16 GC_INDEX, AX ; Select Plane to read in - - CLR AH ; Clear Return Value Hi byte + + mov ah,0 ; Clear Return Value Hi byte MOV AL, ES:[DI+BX] ; Get Color of Pixel - - POPx DI, BP ; Restore Saved Registers + + ;POPx DI, BP ; Restore Saved Registers + pop di + pop bp RET 4 ; Exit and Clean up Stack - + READ_POINT ENDP - - + + ;====================================================== ;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) ;====================================================== @@ -855,9 +908,12 @@ READ_POINT ENDP ; ; EXIT: No meaningful values returned ; - + FB_STACK STRUC - DW ?x4 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller FB_Color DB ?,? ; Fill Color FB_Ypos2 DW ? ; Y pos of Lower Right Pixel @@ -865,154 +921,160 @@ FB_STACK STRUC FB_Ypos1 DW ? ; Y pos of Upper Left Pixel FB_Xpos1 DW ? ; X pos of Upper Left Pixel FB_STACK ENDS - + PUBLIC FILL_BLOCK - + FILL_BLOCK PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page CLD ; Direction Flag = Forward - + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select - + ; Validate Pixel Coordinates ; If necessary, Swap so X1 <= X2, Y1 <= Y2 - + MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2? MOV BX, [BP].FB_Ypos2 ; BX = Y2 CMP AX, BX JLE @FB_NOSWAP1 - + MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1 XCHG AX, BX ; on stack for future use - + @FB_NOSWAP1: SUB BX, AX ; Get Y width INC BX ; Add 1 to avoid 0 value MOV [BP].FB_Ypos2, BX ; Save in Ypos2 - + MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line ADD DI, AX ; DI = Start of Line Y1 - + MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2 MOV BX, [BP].FB_Xpos2 ; CMP AX, BX JLE @FB_NOSWAP2 ; Skip Ahead if Ok - + MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2 XCHG AX, BX ; on stack for future use - + ; All our Input Values are in order, Now determine ; How many full "bands" 4 pixels wide (aligned) there ; are, and if there are partial bands (<4 pixels) on ; the left and right edges. - + @FB_NOSWAP2: MOV DX, AX ; DX = X1 (Pixel Position) - SHR DX, 2 ; DX/4 = Bytes into Line + SHR DX, 1 ; DX/4 = Bytes into Line + SHR DX, 1 ; DX/4 = Bytes into Line ADD DI, DX ; DI = Addr of Upper-Left Corner - + MOV CX, BX ; CX = X2 (Pixel Position) - SHR CX, 2 ; CX/4 = Bytes into Line - + SHR CX, 1 ; CX/4 = Bytes into Line + SHR CX, 1 ; CX/4 = Bytes into Line + CMP DX, CX ; Start and end in same band? JNE @FB_NORMAL ; if not, check for l & r edges JMP @FB_ONE_BAND_ONLY ; if so, then special processing - + @FB_NORMAL: SUB CX, DX ; CX = # bands -1 MOV SI, AX ; SI = PLANE#(X1) AND SI, PLANE_BITS ; if Left edge is aligned then JZ @FB_L_PLANE_FLUSH ; no special processing.. - + ; Draw "Left Edge" vertical strip of 1-3 pixels... - + OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask - + MOV SI, DI ; SI = Copy of Start Addr (UL) - + MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw MOV AL, [BP].FB_Color ; Get Fill Color MOV BX, SCREEN_WIDTH ; Get Vertical increment Value - + @FB_LEFT_LOOP: MOV ES:[SI], AL ; Fill in Left Edge Pixels ADD SI, BX ; Point to Next Line (Below) LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn - + MOV ES:[SI], AL ; Fill in Left Edge Pixels ADD SI, BX ; Point to Next Line (Below) LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn - + @FB_LEFT_CONT: - + INC DI ; Point to Middle (or Right) Block DEC CX ; Reset CX instead of JMP @FB_RIGHT - + @FB_L_PLANE_FLUSH: INC CX ; Add in Left band to middle block - + ; DI = Addr of 1st middle Pixel (band) to fill ; CX = # of Bands to fill -1 - + @FB_RIGHT: MOV SI, [BP].FB_Xpos2 ; Get Xpos2 AND SI, PLANE_BITS ; Get Plane values CMP SI, 0003 ; Plane = 3? JE @FB_R_EDGE_FLUSH ; Hey, add to middle - + ; Draw "Right Edge" vertical strip of 1-3 pixels... - + OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask - + MOV SI, DI ; Get Addr of Left Edge ADD SI, CX ; Add Width-1 (Bands) DEC SI ; To point to top of Right Edge - + MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw MOV AL, [BP].FB_Color ; Get Fill Color MOV BX, SCREEN_WIDTH ; Get Vertical increment Value - + @FB_RIGHT_LOOP: MOV ES:[SI], AL ; Fill in Right Edge Pixels ADD SI, BX ; Point to Next Line (Below) LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn - + MOV ES:[SI], AL ; Fill in Right Edge Pixels ADD SI, BX ; Point to Next Line (Below) LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn - + @FB_RIGHT_CONT: - + DEC CX ; Minus 1 for Middle bands JZ @FB_EXIT ; Uh.. no Middle bands... - + @FB_R_EDGE_FLUSH: - + ; DI = Addr of Upper Left block to fill ; CX = # of Bands to fill in (width) - + OUT_8 SC_Data, ALL_PLANES ; Write to All Planes - + MOV DX, SCREEN_WIDTH ; DX = DI Increment SUB DX, CX ; = Screen_Width-# Planes Filled - + MOV BX, CX ; BX = Quick Refill for CX MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill MOV AL, [BP].FB_Color ; Get Fill Color - + @FB_MIDDLE_LOOP: REP STOSB ; Fill in entire line - + MOV CX, BX ; Recharge CX (Line Width) ADD DI, DX ; Point to start of Next Line LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn - + JMP s @FB_EXIT ; Outa here - + @FB_ONE_BAND_ONLY: MOV SI, AX ; Get Left Clip Mask, Save X1 AND SI, PLANE_BITS ; Mask out Row # @@ -1020,29 +1082,33 @@ FILL_BLOCK PROC FAR MOV SI, BX ; Get Right Clip Mask, Save X2 AND SI, PLANE_BITS ; Mask out Row # AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte - + OUT_8 SC_Data, AL ; Clip For Left & Right Masks - + MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw MOV AL, [BP].FB_Color ; Get Fill Color MOV BX, SCREEN_WIDTH ; Get Vertical increment Value - + @FB_ONE_LOOP: MOV ES:[DI], AL ; Fill in Pixels ADD DI, BX ; Point to Next Line (Below) LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn - + MOV ES:[DI], AL ; Fill in Pixels ADD DI, BX ; Point to Next Line (Below) LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn - + @FB_EXIT: - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 10 ; Exit and Clean up Stack - + FILL_BLOCK ENDP - - + + ;===================================================== ;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) ;===================================================== @@ -1057,9 +1123,11 @@ FILL_BLOCK ENDP ; ; EXIT: No meaningful values returned ; - + DL_STACK STRUC - DW ?x3 ; DI, SI, BP + DW ?x1 ; DI, SI, BP + DW ?x1 ; DI, SI, BP + DW ?x1 ; DI, SI, BP DD ? ; Caller DL_ColorF DB ?,? ; Line Draw Color DL_Ypos2 DW ? ; Y pos of last point @@ -1067,249 +1135,256 @@ DL_STACK STRUC DL_Ypos1 DW ? ; Y pos of first point DL_Xpos1 DW ? ; X pos of first point DL_STACK ENDS - + PUBLIC DRAW_LINE - + DRAW_LINE PROC FAR - - PUSHx BP, SI, DI ; Preserve Important Registers + + ;PUSHx BP, SI, DI ; Preserve Important Registers + push bp + push si + push di MOV BP, SP ; Set up Stack Frame CLD ; Direction Flag = Forward - + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select MOV CH, [BP].DL_ColorF ; Save Line Color in CH - + ; Check Line Type - + MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2? MOV DI, [BP].DL_Xpos2 ; DX = X2 CMP SI, DI ; Is X1 < X2 JE @DL_VLINE ; If X1=X2, Draw Vertical Line JL @DL_NOSWAP1 ; If X1 < X2, don't swap - + XCHG SI, DI ; X2 IS > X1, SO SWAP THEM - + @DL_NOSWAP1: - + ; SI = X1, DI = X2 - + MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2? CMP AX, [BP].DL_Ypos2 ; Y1 = Y2? JE @DL_HORZ ; If so, Draw a Horizontal Line - + JMP @DL_BREZHAM ; Diagonal line... go do it... - + ; This Code draws a Horizontal Line in Mode X where: ; SI = X1, DI = X2, and AX = Y1/Y2 - + @DL_HORZ: - + MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width MOV DX, AX ; CX = Line offset into Page - + MOV AX, SI ; Get Left edge, Save X1 AND SI, PLANE_BITS ; Mask out Row # MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask MOV CX, DI ; Get Right edge, Save X2 AND DI, PLANE_BITS ; Mask out Row # MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte - - SHR AX, 2 ; Get X1 Byte # (=X1/4) - SHR CX, 2 ; Get X2 Byte # (=X2/4) - + + SHR AX, 1 ; Get X1 Byte # (=X1/4) + SHR CX, 1 ; Get X2 Byte # (=X2/4) + SHR AX, 1 ; Get X1 Byte # (=X1/4) + SHR CX, 1 ; Get X2 Byte # (=X2/4) + LES DI, d CURRENT_PAGE ; Point to Active VGA Page ADD DI, DX ; Point to Start of Line ADD DI, AX ; Point to Pixel X1 - + SUB CX, AX ; CX = # Of Bands (-1) to set JNZ @DL_LONGLN ; jump if longer than one segment - + AND BL, BH ; otherwise, merge clip masks - + @DL_LONGLN: - + OUT_8 SC_Data, BL ; Set the Left Clip Mask - + MOV AL, [BP].DL_ColorF ; Get Line Color MOV BL, AL ; BL = Copy of Line Color STOSB ; Set Left (1-4) Pixels - + JCXZ @DL_EXIT ; Done if only one Line Segment - + DEC CX ; CX = # of Middle Segments JZ @DL_XRSEG ; If no middle segments.... - + ; Draw Middle Segments - + OUT_8 DX, ALL_PLANES ; Write to ALL Planes - + MOV AL, BL ; Get Color from BL REP STOSB ; Draw Middle (4 Pixel) Segments - + @DL_XRSEG: OUT_8 DX, BH ; Select Planes for Right Clip Mask MOV AL, BL ; Get Color Value STOSB ; Draw Right (1-4) Pixels - + JMP s @DL_EXIT ; We Are Done... - - + + ; This Code Draws A Vertical Line. On entry: ; CH = Line Color, SI & DI = X1 - + @DL_VLINE: - + MOV AX, [BP].DL_Ypos1 ; AX = Y1 MOV SI, [BP].DL_Ypos2 ; SI = Y2 CMP AX, SI ; Is Y1 < Y2? JLE @DL_NOSWAP2 ; if so, Don't Swap them - + XCHG AX, SI ; Ok, NOW Y1 < Y2 - + @DL_NOSWAP2: - + SUB SI, AX ; SI = Line Height (Y2-Y1+1) INC SI - + ; AX = Y1, DI = X1, Get offset into Page into AX - + MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width MOV DX, DI ; Copy Xpos into DX - SHR DI, 2 ; DI = Xpos/4 + SHR DI, 1 ; DI = Xpos/4 + SHR DI, 1 ; DI = Xpos/4 ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1 - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page ADD DI, AX ; Point to Pixel X1, Y1 - + ;Select Plane - + MOV CL, DL ; CL = Save X1 AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #) MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1 SHL AH, CL ; Change to Correct Plane # OUT_16 SC_Index, AX ; Select Plane - + MOV AL, CH ; Get Saved Color MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By - + @DL_VLoop: MOV ES:[DI], AL ; Draw Single Pixel ADD DI, BX ; Point to Next Line LOOPjz SI, @DL_EXIT ; Lines--, Exit if done - + MOV ES:[DI], AL ; Draw Single Pixel ADD DI, BX ; Point to Next Line LOOPx SI, @DL_VLoop ; Lines--, Loop until Done - + @DL_EXIT: - + JMP @DL_EXIT2 ; Done! - + ; This code Draws a diagonal line in Mode X - + @DL_BREZHAM: LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AX, [BP].DL_Ypos1 ; get Y1 value MOV BX, [BP].DL_Ypos2 ; get Y2 value MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos - + CMP BX, AX ; Y2-Y1 is? JNC @DL_DeltaYOK ; if Y2>=Y1 then goto... - + XCHG BX, AX ; Swap em... MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos - + @DL_DeltaYOK: MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1 - + ADD DI, AX ; DI -> Start of Line Y1 on Page MOV AX, CX ; AX = Xpos (X1) - SHR AX, 2 ; /4 = Byte Offset into Line + SHR AX, 1 ; /4 = Byte Offset into Line + SHR AX, 1 ; /4 = Byte Offset into Line ADD DI, AX ; DI = Starting pos (X1,Y1) - + MOV AL, 11h ; Staring Mask AND CL, PLANE_BITS ; Get Plane # SHL AL, CL ; and shift into place MOV AH, [BP].DL_ColorF ; Color in Hi Bytes - + PUSH AX ; Save Mask,Color... - + MOV AH, AL ; Plane # in AH MOV AL, MAP_MASK ; Select Plane Register OUT_16 SC_Index, AX ; Select initial plane - + MOV AX, [BP].DL_Xpos1 ; get X1 value MOV BX, [BP].DL_Ypos1 ; get Y1 value MOV CX, [BP].DL_Xpos2 ; get X2 value MOV DX, [BP].DL_Ypos2 ; get Y2 value - + MOV BP, SCREEN_WIDTH ; Use BP for Line width to ; to avoid extra memory access - + SUB DX, BX ; figure Delta_Y JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1 - + ADD BX, DX ; put Y2 into Y1 NEG DX ; abs(Delta_Y) XCHG AX, CX ; and exchange X1 and X2 - + @DL_DeltaYOK2: MOV BX, 08000H ; seed for fraction accumulator - + SUB CX, AX ; figure Delta_X JC @DL_DrawLeft ; if negative, go left - + JMP @DL_DrawRight ; Draw Line that slopes right - + @DL_DrawLeft: - + NEG CX ; abs(Delta_X) - + CMP CX, DX ; is Delta_X < Delta_Y? JB @DL_SteepLeft ; yes, so go do steep line ; (Delta_Y iterations) - + ; Draw a Shallow line to the left in Mode X - + @DL_ShallowLeft: - CLR AX ; zero low word of Delta_Y * 10000h + mov ax,0 ; zero low word of Delta_Y * 10000h SUB AX, DX ; DX:AX <- DX * 0FFFFh SBB DX, 0 ; include carry DIV CX ; divide by Delta_X - + MOV SI, BX ; SI = Accumulator MOV BX, AX ; BX = Add fraction POP AX ; Get Color, Bit mask MOV DX, SC_Data ; Sequence controller data register INC CX ; Inc Delta_X so we can unroll loop - + ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down... - + @DL_SLLLoop: MOV ES:[DI], AH ; set first pixel, plane data set up LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done - + ADD SI, BX ; add numerator to accumulator JNC @DL_SLLL2nc ; move down on carry - + ADD DI, BP ; Move Down one line... - + @DL_SLLL2nc: DEC DI ; Left one addr ROR AL, 1 ; Move Left one plane, back on 0 1 2 CMP AL, 87h ; wrap?, if AL <88 then Carry set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done - + ADD SI, BX ; add numerator to accumulator, JNC @DL_SLLL3nc ; move down on carry - + ADD DI, BP ; Move Down one line... - + @DL_SLLL3nc: ; Now move left a pixel... DEC DI ; Left one addr ROR AL, 1 ; Move Left one plane, back on 0 1 2 @@ -1317,171 +1392,174 @@ DRAW_LINE PROC FAR ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask JMP s @DL_SLLLoop ; loop until done - + @DL_SLLExit: JMP @DL_EXIT2 ; and exit - + ; Draw a steep line to the left in Mode X - + @DL_SteepLeft: - CLR AX ; zero low word of Delta_Y * 10000h + mov ax,0 ; zero low word of Delta_Y * 10000h XCHG DX, CX ; Delta_Y switched with Delta_X DIV CX ; divide by Delta_Y - + MOV SI, BX ; SI = Accumulator MOV BX, AX ; BX = Add Fraction POP AX ; Get Color, Bit mask MOV DX, SC_Data ; Sequence controller data register INC CX ; Inc Delta_Y so we can unroll loop - + ; Loop (x2) to Draw Pixels, Move Down, and Maybe left - + @DL_STLLoop: - + MOV ES:[DI], AH ; set first pixel LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done - + ADD SI, BX ; add numerator to accumulator JNC @DL_STLnc2 ; No carry, just move down! - + DEC DI ; Move Left one addr ROR AL, 1 ; Move Left one plane, back on 0 1 2 CMP AL, 87h ; Wrap?, if AL <88 then Carry set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + @DL_STLnc2: ADD DI, BP ; advance to next line. - + MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done - + ADD SI, BX ; add numerator to accumulator JNC @DL_STLnc3 ; No carry, just move down! - + DEC DI ; Move Left one addr ROR AL, 1 ; Move Left one plane, back on 0 1 2 CMP AL, 87h ; Wrap?, if AL <88 then Carry set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + @DL_STLnc3: ADD DI, BP ; advance to next line. JMP s @DL_STLLoop ; Loop until done - + @DL_STLExit: JMP @DL_EXIT2 ; and exit - + ; Draw a line that goes to the Right... - + @DL_DrawRight: CMP CX, DX ; is Delta_X < Delta_Y? JB @DL_SteepRight ; yes, so go do steep line ; (Delta_Y iterations) - + ; Draw a Shallow line to the Right in Mode X - + @DL_ShallowRight: - CLR AX ; zero low word of Delta_Y * 10000h + mov ax,0 ; zero low word of Delta_Y * 10000h SUB AX, DX ; DX:AX <- DX * 0FFFFh SBB DX, 0 ; include carry DIV CX ; divide by Delta_X - + MOV SI, BX ; SI = Accumulator MOV BX, AX ; BX = Add Fraction POP AX ; Get Color, Bit mask MOV DX, SC_Data ; Sequence controller data register INC CX ; Inc Delta_X so we can unroll loop - + ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down... - + @DL_SLRLoop: MOV ES:[DI], AH ; set first pixel, mask is set up LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. - + ADD SI, BX ; add numerator to accumulator JNC @DL_SLR2nc ; don't move down if carry not set - + ADD DI, BP ; Move Down one line... - + @DL_SLR2nc: ; Now move right a pixel... ROL AL, 1 ; Move Right one addr if Plane = 0 CMP AL, 12h ; Wrap? if AL >12 then Carry not set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. - + ADD SI, BX ; add numerator to accumulator JNC @DL_SLR3nc ; don't move down if carry not set - + ADD DI, BP ; Move Down one line... - + @DL_SLR3nc: ROL AL, 1 ; Move Right one addr if Plane = 0 CMP AL, 12h ; Wrap? if AL >12 then Carry not set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask JMP s @DL_SLRLoop ; loop till done - + @DL_SLRExit: JMP @DL_EXIT2 ; and exit - + ; Draw a Steep line to the Right in Mode X - + @DL_SteepRight: - CLR AX ; zero low word of Delta_Y * 10000h + mov ax,0 ; zero low word of Delta_Y * 10000h XCHG DX, CX ; Delta_Y switched with Delta_X DIV CX ; divide by Delta_Y - + MOV SI, BX ; SI = Accumulator MOV BX, AX ; BX = Add Fraction POP AX ; Get Color, Bit mask MOV DX, SC_Data ; Sequence controller data register INC CX ; Inc Delta_Y so we can unroll loop - + ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right - + @STRLoop: MOV ES:[DI], AH ; set first pixel, mask is set up LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done - + ADD SI, BX ; add numerator to accumulator JNC @STRnc2 ; if no carry then just go down... - + ROL AL, 1 ; Move Right one addr if Plane = 0 CMP AL, 12h ; Wrap? if AL >12 then Carry not set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + @STRnc2: ADD DI, BP ; advance to next line. - + MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done - + ADD SI, BX ; add numerator to accumulator JNC @STRnc3 ; if no carry then just go down... - + ROL AL, 1 ; Move Right one addr if Plane = 0 CMP AL, 12h ; Wrap? if AL >12 then Carry not set ADC DI, 0 ; Adjust Address: DI = DI + Carry OUT DX, AL ; Set up New Bit Plane mask - + @STRnc3: ADD DI, BP ; advance to next line. JMP s @STRLoop ; loop till done - + @DL_EXIT2: - POPx DI, SI, BP ; Restore Saved Registers + ;POPx DI, SI, BP ; Restore Saved Registers + pop di + pop si + pop bp RET 10 ; Exit and Clean up Stack - + DRAW_LINE ENDP - - + + ; ===== DAC COLOR REGISTER ROUTINES ===== - + ;================================================= ;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%) ;================================================= @@ -1495,7 +1573,7 @@ DRAW_LINE ENDP ; ; EXIT: No meaningful values returned ; - + SDR_STACK STRUC DW ? ; BP DD ? ; Caller @@ -1504,28 +1582,28 @@ SDR_STACK STRUC SDR_Red DB ?,? ; Red Data Value SDR_Register DB ?,? ; Palette Register # SDR_STACK ENDS - + PUBLIC SET_DAC_REGISTER - + SET_DAC_REGISTER PROC FAR - + PUSH BP ; Save BP MOV BP, SP ; Set up Stack Frame - + ; Select which DAC Register to modify - + OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register - + MOV DX, PEL_DATA_REG ; Dac Data Register OUT_8 DX, [BP].SDR_Red ; Set Red Intensity OUT_8 DX, [BP].SDR_Green ; Set Green Intensity OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity - + POP BP ; Restore Registers RET 8 ; Exit & Clean Up Stack - + SET_DAC_REGISTER ENDP - + ;==================================================== ;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%) ;==================================================== @@ -1541,7 +1619,7 @@ SET_DAC_REGISTER ENDP ; Green, and Blue are set to the values ; taken from the specified DAC register. ; - + GDR_STACK STRUC DW ? ; BP DD ? ; Caller @@ -1550,39 +1628,39 @@ GDR_STACK STRUC GDR_Red DW ? ; Addr of Red Data Value in DS GDR_Register DB ?,? ; Palette Register # GDR_STACK ENDS - + PUBLIC GET_DAC_REGISTER - + GET_DAC_REGISTER PROC FAR - + PUSH BP ; Save BP MOV BP, SP ; Set up Stack Frame - + ; Select which DAC Register to read in - + OUT_8 DAC_READ_ADDR, [BP].GDR_Register - + MOV DX, PEL_DATA_REG ; Dac Data Register - CLR AX ; Clear AX - + mov ax,0 ; Clear AX + IN AL, DX ; Read Red Value MOV BX, [BP].GDR_Red ; Get Address of Red% MOV [BX], AX ; *Red% = AX - + IN AL, DX ; Read Green Value MOV BX, [BP].GDR_Green ; Get Address of Green% MOV [BX], AX ; *Green% = AX - + IN AL, DX ; Read Blue Value MOV BX, [BP].GDR_Blue ; Get Address of Blue% MOV [BX], AX ; *Blue% = AX - + POP BP ; Restore Registers RET 8 ; Exit & Clean Up Stack - + GET_DAC_REGISTER ENDP - - + + ;=========================================================== ;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%) ;=========================================================== @@ -1599,40 +1677,45 @@ GET_DAC_REGISTER ENDP ; NOTES: PalData is a linear array of 3 byte Palette values ; in the order: Red (0-63), Green (0-63), Blue (0-63) ; - + LDR_STACK STRUC - DW ?x3 ; BP, DS, SI + DW ?x1 ; BP, DS, SI + DW ?x1 ; BP, DS, SI + DW ?x1 ; BP, DS, SI DD ? ; Caller LDR_Sync DW ? ; Vertical Sync Flag LDR_EndReg DB ?,? ; Last Register # LDR_StartReg DB ?,? ; First Register # LDR_PalData DD ? ; Far Ptr to Palette Data LDR_STACK ENDS - + PUBLIC LOAD_DAC_REGISTERS - + LOAD_DAC_REGISTERS PROC FAR - - PUSHx BP, DS, SI ; Save Registers + + ;PUSHx BP, DS, SI ; Save Registers + push bp + push ds + push si mov BP, SP ; Set up Stack Frame - + mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag or AX, AX ; is Sync Flag = 0? jz @LDR_Load ; if so, skip call - + call f SYNC_DISPLAY ; wait for vsync - + ; Determine register #'s, size to copy, etc - + @LDR_Load: - + lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data mov DX, DAC_WRITE_ADDR ; DAC register # selector - - CLR AX, BX ; Clear for byte loads + + mov ax,0, BX ; Clear for byte loads mov AL, [BP].LDR_StartReg ; Get Start Register mov BL, [BP].LDR_EndReg ; Get End Register - + sub BX, AX ; BX = # of DAC registers -1 inc BX ; BX = # of DAC registers mov CX, BX ; CX = # of DAC registers @@ -1640,19 +1723,22 @@ LOAD_DAC_REGISTERS PROC FAR add CX, BX ; CX = " " * 3 cld ; Block OUTs forward out DX, AL ; set up correct register # - + ; Load a block of DAC Registers - + mov DX, PEL_DATA_REG ; Dac Data Register - - rep outsb ; block set DAC registers - - POPx SI, DS, BP ; Restore Registers + + ;rep outsb ; block set DAC registers + + ;POPx SI, DS, BP ; Restore Registers + pop si + pop ds + pop bp ret 10 ; Exit & Clean Up Stack - + LOAD_DAC_REGISTERS ENDP - - + + ;==================================================== ;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%) ;==================================================== @@ -1668,53 +1754,61 @@ LOAD_DAC_REGISTERS ENDP ; NOTES: PalData is a linear array of 3 byte Palette values ; in the order: Red (0-63), Green (0-63), Blue (0-63) ; - + RDR_STACK STRUC - DW ?x3 ; BP, ES, DI + DW ?x1 ; BP, ES, DI + DW ?x1 ; BP, ES, DI + DW ?x1 ; BP, ES, DI DD ? ; Caller RDR_EndReg DB ?,? ; Last Register # RDR_StartReg DB ?,? ; First Register # RDR_PalData DD ? ; Far Ptr to Palette Data RDR_STACK ENDS - + PUBLIC READ_DAC_REGISTERS - + READ_DAC_REGISTERS PROC FAR - - PUSHx BP, ES, DI ; Save Registers + + ;PUSHx BP, ES, DI ; Save Registers + push bp + push es + push di mov BP, SP ; Set up Stack Frame - + ; Determine register #'s, size to copy, etc - + les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer mov DX, DAC_READ_ADDR ; DAC register # selector - - CLR AX, BX ; Clear for byte loads + + mov ax,0, BX ; Clear for byte loads mov AL, [BP].RDR_StartReg ; Get Start Register mov BL, [BP].RDR_EndReg ; Get End Register - + sub BX, AX ; BX = # of DAC registers -1 inc BX ; BX = # of DAC registers mov CX, BX ; CX = # of DAC registers add CX, BX ; CX = " " * 2 add CX, BX ; CX = " " * 3 cld ; Block INs forward - + ; Read a block of DAC Registers - + out DX, AL ; set up correct register # mov DX, PEL_DATA_REG ; Dac Data Register - - rep insb ; block read DAC registers - - POPx DI, ES, BP ; Restore Registers + + ;rep insb ; block read DAC registers + + ;POPx DI, ES, BP ; Restore Registers + pop di + pop es + pop bp ret 8 ; Exit & Clean Up Stack - + READ_DAC_REGISTERS ENDP - - + + ; ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== - + ;========================= ;SET_ACTIVE_PAGE (PageNo%) ;========================= @@ -1726,38 +1820,38 @@ READ_DAC_REGISTERS ENDP ; ; EXIT: No meaningful values returned ; - + SAP_STACK STRUC DW ? ; BP DD ? ; Caller SAP_Page DW ? ; Page # for Drawing SAP_STACK ENDS - + PUBLIC SET_ACTIVE_PAGE - + SET_ACTIVE_PAGE PROC FAR - + PUSH BP ; Preserve Registers MOV BP, SP ; Set up Stack Frame - + MOV BX, [BP].SAP_Page ; Get Desired Page # CMP BX, LAST_PAGE ; Is Page # Valid? JAE @SAP_Exit ; IF Not, Do Nothing - + MOV ACTIVE_PAGE, BX ; Set Active Page # - + SHL BX, 1 ; Scale Page # to Word MOV AX, PAGE_ADDR[BX] ; Get offset to Page - + MOV CURRENT_PAGE, AX ; And set for future LES's - + @SAP_Exit: POP BP ; Restore Registers RET 2 ; Exit and Clean up Stack - + SET_ACTIVE_PAGE ENDP - - + + ;================ ;GET_ACTIVE_PAGE% ;================ @@ -1768,17 +1862,17 @@ SET_ACTIVE_PAGE ENDP ; ; EXIT: AX = Current Video Page used for Drawing ; - + PUBLIC GET_ACTIVE_PAGE - + GET_ACTIVE_PAGE PROC FAR - + MOV AX, ACTIVE_PAGE ; Get Active Page # RET ; Exit and Clean up Stack - + GET_ACTIVE_PAGE ENDP - - + + ;=============================== ;SET_DISPLAY_PAGE (DisplayPage%) ;=============================== @@ -1792,70 +1886,70 @@ GET_ACTIVE_PAGE ENDP ; ; EXIT: No meaningful values returned ; - + SDP_STACK STRUC DW ? ; BP DD ? ; Caller SDP_Page DW ? ; Page # to Display... SDP_STACK ENDS - + PUBLIC SET_DISPLAY_PAGE - + SET_DISPLAY_PAGE PROC FAR - + PUSH BP ; Preserve Registers MOV BP, SP ; Set up Stack Frame - + MOV BX, [BP].SDP_Page ; Get Desired Page # CMP BX, LAST_PAGE ; Is Page # Valid? JAE @SDP_Exit ; IF Not, Do Nothing - + MOV DISPLAY_PAGE, BX ; Set Display Page # - + SHL BX, 1 ; Scale Page # to Word MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling - + ; Wait if we are currently in a Vertical Retrace - + MOV DX, INPUT_1 ; Input Status #1 Register - + @DP_WAIT0: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; In Display mode yet? JNZ @DP_WAIT0 ; If Not, wait for it - + ; Set the Start Display Address to the new page - + MOV DX, CRTC_Index ; We Change the VGA Sequencer - + MOV AL, START_DISP_LO ; Display Start Low Register MOV AH, CL ; Low 8 Bits of Start Addr OUT DX, AX ; Set Display Addr Low - + MOV AL, START_DISP_HI ; Display Start High Register MOV AH, CH ; High 8 Bits of Start Addr OUT DX, AX ; Set Display Addr High - + ; Wait for a Vertical Retrace to smooth out things - + MOV DX, INPUT_1 ; Input Status #1 Register - + @DP_WAIT1: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; Vertical Retrace Start? JZ @DP_WAIT1 ; If Not, wait for it - + ; Now Set Display Starting Address - - + + @SDP_Exit: POP BP ; Restore Registers RET 2 ; Exit and Clean up Stack - + SET_DISPLAY_PAGE ENDP - - + + ;================= ;GET_DISPLAY_PAGE% ;================= @@ -1866,17 +1960,17 @@ SET_DISPLAY_PAGE ENDP ; ; EXIT: AX = Current Video Page being displayed ; - + PUBLIC GET_DISPLAY_PAGE - + GET_DISPLAY_PAGE PROC FAR - + MOV AX, DISPLAY_PAGE ; Get Display Page # RET ; Exit & Clean Up Stack - + GET_DISPLAY_PAGE ENDP - - + + ;======================================= ;SET_WINDOW (DisplayPage%, Xpos%, Ypos%) ;======================================= @@ -1894,7 +1988,7 @@ GET_DISPLAY_PAGE ENDP ; ; EXIT: No meaningful values returned ; - + SW_STACK STRUC DW ? ; BP DD ? ; Caller @@ -1902,86 +1996,87 @@ SW_STACK STRUC SW_Xpos DW ? ; X pos of UL Screen Corner SW_Page DW ? ; (new) Display Page SW_STACK ENDS - + PUBLIC SET_WINDOW - + SET_WINDOW PROC FAR - + PUSH BP ; Preserve Registers MOV BP, SP ; Set up Stack Frame - + ; Check if our Scroll Offsets are Valid - + MOV BX, [BP].SW_Page ; Get Desired Page # CMP BX, LAST_PAGE ; Is Page # Valid? JAE @SW_Exit ; IF Not, Do Nothing - + MOV AX, [BP].SW_Ypos ; Get Desired Y Offset CMP AX, MAX_YOFFSET ; Is it Within Limits? JA @SW_Exit ; if not, exit - + MOV CX, [BP].SW_Xpos ; Get Desired X Offset CMP CX, MAX_XOFFSET ; Is it Within Limits? JA @SW_Exit ; if not, exit - + ; Compute proper Display start address to use - + MUL SCREEN_WIDTH ; AX = YOffset * Line Width - SHR CX, 2 ; CX / 4 = Bytes into Line + SHR CX, 1 ; CX / 4 = Bytes into Line + SHR CX, 1 ; CX / 4 = Bytes into Line ADD AX, CX ; AX = Offset of Upper Left Pixel - + MOV CURRENT_MOFFSET, AX ; Save Offset Info - + MOV DISPLAY_PAGE, BX ; Set Current Page # SHL BX, 1 ; Scale Page # to Word ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page MOV BX, AX ; BX = Desired Display Start - + MOV DX, INPUT_1 ; Input Status #1 Register - + ; Wait if we are currently in a Vertical Retrace - + @SW_WAIT0: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; In Display mode yet? JNZ @SW_WAIT0 ; If Not, wait for it - + ; Set the Start Display Address to the new window - + MOV DX, CRTC_Index ; We Change the VGA Sequencer MOV AL, START_DISP_LO ; Display Start Low Register MOV AH, BL ; Low 8 Bits of Start Addr OUT DX, AX ; Set Display Addr Low - + MOV AL, START_DISP_HI ; Display Start High Register MOV AH, BH ; High 8 Bits of Start Addr OUT DX, AX ; Set Display Addr High - + ; Wait for a Vertical Retrace to smooth out things - + MOV DX, INPUT_1 ; Input Status #1 Register - + @SW_WAIT1: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; Vertical Retrace Start? JZ @SW_WAIT1 ; If Not, wait for it - + ; Now Set the Horizontal Pixel Pan values - + OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register - + MOV AX, [BP].SW_Xpos ; Get Desired X Offset AND AL, 03 ; Get # of Pixels to Pan (0-3) SHL AL, 1 ; Shift for 256 Color Mode OUT DX, AL ; Fine tune the display! - + @SW_Exit: POP BP ; Restore Saved Registers RET 6 ; Exit and Clean up Stack - + SET_WINDOW ENDP - - + + ;============= ;GET_X_OFFSET% ;============= @@ -1993,17 +2088,17 @@ SET_WINDOW ENDP ; ; EXIT: AX = Current Horizontal Scroll Offset ; - + PUBLIC GET_X_OFFSET - + GET_X_OFFSET PROC FAR - + MOV AX, CURRENT_XOFFSET ; Get current horz offset RET ; Exit & Clean Up Stack - + GET_X_OFFSET ENDP - - + + ;============= ;GET_Y_OFFSET% ;============= @@ -2015,17 +2110,17 @@ GET_X_OFFSET ENDP ; ; EXIT: AX = Current Vertical Scroll Offset ; - + PUBLIC GET_Y_OFFSET - + GET_Y_OFFSET PROC FAR - + MOV AX, CURRENT_YOFFSET ; Get current vertical offset RET ; Exit & Clean Up Stack - + GET_Y_OFFSET ENDP - - + + ;============ ;SYNC_DISPLAY ;============ @@ -2036,34 +2131,34 @@ GET_Y_OFFSET ENDP ; ; EXIT: No meaningful values returned ; - + PUBLIC SYNC_DISPLAY - + SYNC_DISPLAY PROC FAR - + MOV DX, INPUT_1 ; Input Status #1 Register - + ; Wait for any current retrace to end - + @SD_WAIT0: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; In Display mode yet? JNZ @SD_WAIT0 ; If Not, wait for it - + ; Wait for the start of the next vertical retrace - + @SD_WAIT1: IN AL, DX ; Get VGA status AND AL, VERT_RETRACE ; Vertical Retrace Start? JZ @SD_WAIT1 ; If Not, wait for it - + RET ; Exit & Clean Up Stack - + SYNC_DISPLAY ENDP - - + + ; ===== TEXT DISPLAY ROUTINES ===== - + ;================================================== ;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%) ;================================================== @@ -2080,13 +2175,16 @@ SYNC_DISPLAY ENDP ; ; EXIT: No meaningful values returned ; - + GPC_STACK STRUC GPC_Width DW ? ; Screen Width-1 GPC_Lines DB ?,? ; Scan lines to Decode GPC_T_SETS DW ? ; Saved Charset Segment GPC_T_SETO DW ? ; Saved Charset Offset - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller GPC_ColorB DB ?,? ; Background Color GPC_ColorF DB ?,? ; Text Color @@ -2094,171 +2192,189 @@ GPC_STACK STRUC GPC_Xpos DW ? ; X position to Print at GPC_Char DB ?,? ; Character to Print GPC_STACK ENDS - + PUBLIC GPRINTC - + GPRINTC PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 8 ; Allocate WorkSpace on Stack MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AX, SCREEN_WIDTH ; Get Logical Line Width MOV BX, AX ; BX = Screen Width DEC BX ; = Screen Width-1 MOV [BP].GPC_Width, BX ; Save for later use - + MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width ADD DI, AX ; DI -> Start of Line Ypos - + MOV AX, [BP].GPC_Xpos ; Get Xpos of Character MOV CX, AX ; Save Copy of Xpos - SHR AX, 2 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 ADD DI, AX ; DI -> (Xpos, Ypos) - + ;Get Source ADDR of Character Bit Map & Save - + MOV AL, [BP].GPC_Char ; Get Character # TEST AL, 080h ; Is Hi Bit Set? JZ @GPC_LowChar ; Nope, use low char set ptr - + AND AL, 07Fh ; Mask Out Hi Bit MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment JMP s @GPC_Set_Char ; Go Setup Character Ptr - + @GPC_LowChar: - + MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment - + @GPC_Set_Char: MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack - + MOV AH, 0 ; Valid #'s are 0..127 - SHL AX, 3 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap ADD BX, AX ; BX = Offset of Selected char MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack - + AND CX, PLANE_BITS ; Get Plane # MOV CH, ALL_PLANES ; Get Initial Plane mask SHL CH, CL ; And shift into position AND CH, ALL_PLANES ; And mask to lower nibble - + MOV AL, 04 ; 4-Plane # = # of initial SUB AL, CL ; shifts to align bit mask MOV CL, AL ; Shift Count for SHL - + ;Get segment of character map - + OUT_8 SC_Index, MAP_MASK ; Setup Plane selections INC DX ; DX -> SC_Data - + MOV AL, 08 ; 8 Lines to Process MOV [BP].GPC_Lines, AL ; Save on Stack - + MOV DS, [BP].GPC_T_SETS ; Point to character set - + @GPC_DECODE_CHAR_BYTE: - + MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String - + MOV BH, [SI] ; Get Bit Map INC SI ; Point to Next Line MOV [BP].GPC_T_SETO, SI ; And save new Pointer... - - CLR AX ; Clear AX - - CLR BL ; Clear BL + + mov ax,0 ; Clear AX + + ;mov bl,0 ; Clear BL + mov bl,0 ROL BX, CL ; BL holds left edge bits MOV SI, BX ; Use as Table Index AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set - + MOV AH, [BP].GPC_ColorF ; Get Foreground Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @GPC_NO_LEFT1BITS: XOR AL, CH ; Invert mask for Background JZ @GPC_NO_LEFT0BITS ; Hey, no need for this - + MOV AH, [BP].GPC_ColorB ; Get background Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + ;Now Do Middle/Last Band - + @GPC_NO_LEFT0BITS: INC DI ; Point to next Byte - ROL BX, 4 ; Shift 4 bits - + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + MOV SI, BX ; Make Lookup Pointer AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set - + MOV AH, [BP].GPC_ColorF ; Get Foreground Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @GPC_NO_MIDDLE1BITS: XOR AL, ALL_PLANES ; Invert mask for Background JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this - + MOV AH, [BP].GPC_ColorB ; Get background Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @GPC_NO_MIDDLE0BITS: XOR CH, ALL_PLANES ; Invert Clip Mask CMP CL, 4 ; Aligned by 4? JZ @GPC_NEXT_LINE ; If so, Exit now.. - + INC DI ; Point to next Byte - ROL BX, 4 ; Shift 4 bits - + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + MOV SI, BX ; Make Lookup Pointer AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set - + MOV AH, [BP].GPC_ColorF ; Get Foreground Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @GPC_NO_RIGHT1BITS: - + XOR AL, CH ; Invert mask for Background JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this - + MOV AH, [BP].GPC_ColorB ; Get background Color OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @GPC_NO_RIGHT0BITS: DEC DI ; Adjust for Next Line Advance - + @GPC_NEXT_LINE: ADD DI, [BP].GPC_Width ; Point to Next Line XOR CH, CHAR_BITS ; Flip the Clip mask back - + DEC [BP].GPC_Lines ; Count Down Lines JZ @GPC_EXIT ; Ok... Done! - + JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey! - + @GPC_EXIT: ADD SP, 08 ; Deallocate stack workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 10 ; Exit and Clean up Stack - + GPRINTC ENDP - - + + ;========================================== ;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%) ;========================================== @@ -2273,158 +2389,178 @@ GPRINTC ENDP ; ; EXIT: No meaningful values returned ; - + TGP_STACK STRUC TGP_Width DW ? ; Screen Width-1 TGP_Lines DB ?,? ; Scan lines to Decode TGP_T_SETS DW ? ; Saved Charset Segment TGP_T_SETO DW ? ; Saved Charset Offset - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller TGP_ColorF DB ?,? ; Text Color TGP_Ypos DW ? ; Y Position to Print at TGP_Xpos DW ? ; X position to Print at TGP_Char DB ?,? ; Character to Print TGP_STACK ENDS - + PUBLIC TGPRINTC - + TGPRINTC PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 8 ; Allocate WorkSpace on Stack MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page - + MOV AX, SCREEN_WIDTH ; Get Logical Line Width MOV BX, AX ; BX = Screen Width DEC BX ; = Screen Width-1 MOV [BP].TGP_Width, BX ; Save for later use - + MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width ADD DI, AX ; DI -> Start of Line Ypos - + MOV AX, [BP].TGP_Xpos ; Get Xpos of Character MOV CX, AX ; Save Copy of Xpos - SHR AX, 2 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 + SHR AX, 1 ; Bytes into Line = Xpos/4 ADD DI, AX ; DI -> (Xpos, Ypos) - + ;Get Source ADDR of Character Bit Map & Save - + MOV AL, [BP].TGP_Char ; Get Character # TEST AL, 080h ; Is Hi Bit Set? JZ @TGP_LowChar ; Nope, use low char set ptr - + AND AL, 07Fh ; Mask Out Hi Bit MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment JMP s @TGP_Set_Char ; Go Setup Character Ptr - + @TGP_LowChar: - + MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment - + @TGP_Set_Char: MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack - + MOV AH, 0 ; Valid #'s are 0..127 - SHL AX, 3 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap + SHL AX, 1 ; * 8 Bytes Per Bitmap ADD BX, AX ; BX = Offset of Selected char MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack - + AND CX, PLANE_BITS ; Get Plane # MOV CH, ALL_PLANES ; Get Initial Plane mask SHL CH, CL ; And shift into position AND CH, ALL_PLANES ; And mask to lower nibble - + MOV AL, 04 ; 4-Plane # = # of initial SUB AL, CL ; shifts to align bit mask MOV CL, AL ; Shift Count for SHL - + ;Get segment of character map - + OUT_8 SC_Index, MAP_MASK ; Setup Plane selections INC DX ; DX -> SC_Data - + MOV AL, 08 ; 8 Lines to Process MOV [BP].TGP_Lines, AL ; Save on Stack - + MOV DS, [BP].TGP_T_SETS ; Point to character set - + @TGP_DECODE_CHAR_BYTE: - + MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String - + MOV BH, [SI] ; Get Bit Map INC SI ; Point to Next Line MOV [BP].TGP_T_SETO, SI ; And save new Pointer... - + MOV AH, [BP].TGP_ColorF ; Get Foreground Color - - CLR BL ; Clear BL + + mov bl,0 ; Clear BL ROL BX, CL ; BL holds left edge bits MOV SI, BX ; Use as Table Index AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set - + OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + ;Now Do Middle/Last Band - + @TGP_NO_LEFT1BITS: - + INC DI ; Point to next Byte - ROL BX, 4 ; Shift 4 bits - + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + MOV SI, BX ; Make Lookup Pointer AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set - + OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @TGP_NO_MIDDLE1BITS: XOR CH, ALL_PLANES ; Invert Clip Mask CMP CL, 4 ; Aligned by 4? JZ @TGP_NEXT_LINE ; If so, Exit now.. - + INC DI ; Point to next Byte - ROL BX, 4 ; Shift 4 bits - + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + ROL BX, 1 ; Shift 4 bits + MOV SI, BX ; Make Lookup Pointer AND SI, CHAR_BITS ; Get Low Bits MOV AL, Char_Plane_Data[SI] ; Get Mask in AL JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set - + OUT DX, AL ; Set up Screen Mask MOV ES:[DI], AH ; Write Foreground color - + @TGP_NO_RIGHT1BITS: - + DEC DI ; Adjust for Next Line Advance - + @TGP_NEXT_LINE: ADD DI, [BP].TGP_Width ; Point to Next Line XOR CH, CHAR_BITS ; Flip the Clip mask back - + DEC [BP].TGP_Lines ; Count Down Lines JZ @TGP_EXIT ; Ok... Done! - + JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey! - + @TGP_EXIT: ADD SP, 08 ; Deallocate stack workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 8 ; Exit and Clean up Stack - + TGPRINTC ENDP - - + + ;=============================================================== ;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) ;=============================================================== @@ -2441,9 +2577,12 @@ TGPRINTC ENDP ; ; EXIT: No meaningful values returned ; - + PS_STACK STRUC - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller PS_ColorB DW ? ; Background Color PS_ColorF DW ? ; Text Color @@ -2452,54 +2591,62 @@ PS_STACK STRUC PS_Len DW ? ; Maximum Length of string to print PS_Text DW ?,? ; Far Ptr to Text String PS_STACK ENDS - + PUBLIC PRINT_STR - + PRINT_STR PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di MOV BP, SP ; Set up Stack Frame - + @PS_Print_It: - + MOV CX, [BP].PS_Len ; Get Remaining text Length JCXZ @PS_Exit ; Exit when out of text - + LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text MOV AL, ES:[DI] ; AL = Text Character AND AX, 00FFh ; Clear High Word JZ @PS_Exit ; Exit if null character - + DEC [BP].PS_Len ; Remaining Text length-- INC [BP].PS_Text ; Point to Next text char - + ; Set up Call to GPRINTC - + PUSH AX ; Set Character Parameter MOV BX, [BP].PS_Xpos ; Get Xpos PUSH BX ; Set Xpos Parameter ADD BX, 8 ; Advance 1 Char to Right MOV [BP].PS_Xpos, BX ; Save for next time through - + MOV BX, [BP].PS_Ypos ; Get Ypos PUSH BX ; Set Ypos Parameter - + MOV BX, [BP].PS_ColorF ; Get Text Color PUSH BX ; Set ColorF Parameter - + MOV BX, [BP].PS_ColorB ; Get Background Color PUSH BX ; Set ColorB Parameter - + CALL f GPRINTC ; Print Character! JMP s @PS_Print_It ; Process next character - + @PS_Exit: - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 14 ; Exit and Clean up Stack - + PRINT_STR ENDP - - + + ;================================================================ ;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) ;================================================================ @@ -2515,9 +2662,12 @@ PRINT_STR ENDP ; ; EXIT: No meaningful values returned ; - + TPS_STACK STRUC - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller TPS_ColorF DW ? ; Text Color TPS_Ypos DW ? ; Y Position to Print at @@ -2525,51 +2675,59 @@ TPS_STACK STRUC TPS_Len DW ? ; Maximum Length of string to print TPS_Text DW ?,? ; Far Ptr to Text String TPS_STACK ENDS - + PUBLIC TPRINT_STR - + TPRINT_STR PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di MOV BP, SP ; Set up Stack Frame - + @TPS_Print_It: - + MOV CX, [BP].TPS_Len ; Get Remaining text Length JCXZ @TPS_Exit ; Exit when out of text - + LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text MOV AL, ES:[DI] ; AL = Text Character AND AX, 00FFh ; Clear High Word JZ @TPS_Exit ; Exit if null character - + DEC [BP].TPS_Len ; Remaining Text length-- INC [BP].TPS_Text ; Point to Next text char - + ; Set up Call to TGPRINTC - + PUSH AX ; Set Character Parameter MOV BX, [BP].TPS_Xpos ; Get Xpos PUSH BX ; Set Xpos Parameter ADD BX, 8 ; Advance 1 Char to Right MOV [BP].TPS_Xpos, BX ; Save for next time through - + MOV BX, [BP].TPS_Ypos ; Get Ypos PUSH BX ; Set Ypos Parameter - + MOV BX, [BP].TPS_ColorF ; Get Text Color PUSH BX ; Set ColorF Parameter - + CALL f TGPRINTC ; Print Character! JMP s @TPS_Print_It ; Process next character - + @TPS_Exit: - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 12 ; Exit and Clean up Stack - + TPRINT_STR ENDP - - + + ;=========================================== ;SET_DISPLAY_FONT(SEG FontData, FontNumber%) ;=========================================== @@ -2584,41 +2742,41 @@ TPRINT_STR ENDP ; ; EXIT: No meaningful values returned ; - + SDF_STACK STRUC DW ? ; BP DD ? ; Caller SDF_Which DW ? ; Hi Table/Low Table Flag SDF_Font DD ? ; Far Ptr to Font Table SDF_STACK ENDS - + PUBLIC SET_DISPLAY_FONT - + SET_DISPLAY_FONT PROC FAR - + PUSH BP ; Preserve Registers MOV BP, SP ; Set up Stack Frame - + LES DI, [BP].SDF_Font ; Get Far Ptr to Font - + MOV SI, o CHARSET_LOW ; Assume Lower 128 chars TEST [BP].SDF_Which, 1 ; Font #1 selected? JZ @SDF_Set_Font ; If not, skip ahead - + MOV SI, o CHARSET_HI ; Ah, really it's 128-255 - + @SDF_Set_Font: MOV [SI], DI ; Set Font Pointer Offset MOV [SI+2], ES ; Set Font Pointer Segment - + POP BP ; Restore Registers RET 6 ; We are Done.. Outa here - + SET_DISPLAY_FONT ENDP - - + + ; ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== - + ;====================================================== ;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) ;====================================================== @@ -2637,14 +2795,17 @@ SET_DISPLAY_FONT ENDP ; ; EXIT: No meaningful values returned ; - + DB_STACK STRUC DB_LineO DW ? ; Offset to Next Line DB_PixCount DW ? ; (Minimum) # of Pixels/Line DB_Start DW ? ; Addr of Upper Left Pixel DB_PixSkew DW ? ; # of bytes to Adjust EOL DB_SkewFlag DW ? ; Extra Pix on Plane Flag - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller DB_Height DW ? ; Height of Bitmap in Pixels DB_Width DW ? ; Width of Bitmap in Pixels @@ -2652,65 +2813,71 @@ DB_STACK STRUC DB_Xpos DW ? ; X position to Draw Bitmap at DB_Image DD ? ; Far Pointer to Graphics Bitmap DB_STACK ENDS - + PUBLIC DRAW_BITMAP - + DRAW_BITMAP PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 10 ; Allocate workspace MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page CLD ; Direction Flag = Forward - + MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos MUL SCREEN_WIDTH ; AX = Offset to Line Ypos - + MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos MOV CL, BL ; Save Plane # in CL - SHR BX, 2 ; Xpos/4 = Offset Into Line - + SHR BX, 1 ; Xpos/4 = Offset Into Line + SHR BX, 1 ; Xpos/4 = Offset Into Line + ADD DI, AX ; ES:DI -> Start of Line ADD DI, BX ; ES:DI -> Upper Left Pixel MOV [BP].DB_Start, DI ; Save Starting Addr - + ; Compute line to line offset - + MOV BX, [BP].DB_Width ; Get Width of Image MOV DX, BX ; Save Copy in DX - SHR BX, 2 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands MOV AX, SCREEN_WIDTH ; Get Screen Width SUB AX, BX ; - (Bitmap Width/4) - + MOV [BP].DB_LineO, AX ; Save Line Width offset MOV [BP].DB_PixCount, BX ; Minimum # pix to copy - + AND DX, PLANE_BITS ; Get "partial band" size (0-3) MOV [BP].DB_PixSkew, DX ; Also End of Line Skew MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count - + AND CX, PLANE_BITS ; CL = Starting Plane # MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select SHL AH, CL ; Select correct Plane OUT_16 SC_Index, AX ; Select Plane... MOV BH, AH ; BH = Saved Plane Mask MOV BL, 4 ; BL = Planes to Copy - + @DB_COPY_PLANE: - + LDS SI, [BP].DB_Image ; DS:SI-> Source Image MOV DX, [BP].DB_Height ; # of Lines to Copy MOV DI, [BP].DB_Start ; ES:DI-> Dest pos - + @DB_COPY_LINE: MOV CX, [BP].DB_PixCount ; Min # to copy - + TEST CL, 0FCh ; 16+PixWide? JZ @DB_COPY_REMAINDER ; Nope... - + ; Pixel Copy loop has been unrolled to x4 - + @DB_COPY_LOOP: MOVSB ; Copy Bitmap Pixel ADD SI, 3 ; Skip to Next Byte in same plane @@ -2720,60 +2887,64 @@ DRAW_BITMAP PROC FAR ADD SI, 3 ; Skip to Next Byte in same plane MOVSB ; Copy Bitmap Pixel ADD SI, 3 ; Skip to Next Byte in same plane - + SUB CL, 4 ; Pixels to Copy=-4 TEST CL, 0FCh ; 4+ Pixels Left? JNZ @DB_COPY_LOOP ; if so, do another block - + @DB_COPY_REMAINDER: JCXZ @DB_NEXT_LINE ; Any Pixels left on line - + @DB_COPY2: MOVSB ; Copy Bitmap Pixel ADD SI,3 ; Skip to Next Byte in same plane LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done - + @DB_NEXT_LINE: - + ; any Partial Pixels? (some planes only) - + OR CX, [BP].DB_SkewFlag ; Get Skew Count JZ @DB_NEXT2 ; if no partial pixels - + MOVSB ; Copy Bitmap Pixel DEC DI ; Back up to align DEC SI ; Back up to align - + @DB_NEXT2: ADD SI, [BP].DB_PixSkew ; Adjust Skew ADD DI, [BP].DB_LineO ; Set to Next Display Line LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more - + ; Copy Next Plane.... - + DEC BL ; Planes to Go-- JZ @DB_Exit ; Hey! We are done - + ROL BH, 1 ; Next Plane in line... OUT_8 SC_Data, BH ; Select Plane - + CMP AL, 12h ; Carry Set if AL=11h ADC [BP].DB_Start, 0 ; Screen Addr =+Carry INC w [BP].DB_Image ; Start @ Next Byte - + SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1 - + JMP s @DB_COPY_PLANE ; Go Copy the Next Plane - + @DB_Exit: ADD SP, 10 ; Deallocate workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 12 ; Exit and Clean up Stack - + DRAW_BITMAP ENDP - - + + ;======================================================= ;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) ;======================================================= @@ -2793,14 +2964,17 @@ DRAW_BITMAP ENDP ; ; EXIT: No meaningful values returned ; - + TB_STACK STRUC TB_LineO DW ? ; Offset to Next Line TB_PixCount DW ? ; (Minimum) # of Pixels/Line TB_Start DW ? ; Addr of Upper Left Pixel TB_PixSkew DW ? ; # of bytes to Adjust EOL TB_SkewFlag DW ? ; Extra Pix on Plane Flag - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller TB_Height DW ? ; Height of Bitmap in Pixels TB_Width DW ? ; Width of Bitmap in Pixels @@ -2808,163 +2982,173 @@ TB_STACK STRUC TB_Xpos DW ? ; X position to Draw Bitmap at TB_Image DD ? ; Far Pointer to Graphics Bitmap TB_STACK ENDS - + PUBLIC TDRAW_BITMAP - + TDRAW_BITMAP PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 10 ; Allocate workspace MOV BP, SP ; Set up Stack Frame - + LES DI, d CURRENT_PAGE ; Point to Active VGA Page CLD ; Direction Flag = Forward - + MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos MUL SCREEN_WIDTH ; AX = Offset to Line Ypos - + MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos MOV CL, BL ; Save Plane # in CL - SHR BX, 2 ; Xpos/4 = Offset Into Line - + SHR BX, 1 ; Xpos/4 = Offset Into Line + SHR BX, 1 ; Xpos/4 = Offset Into Line + ADD DI, AX ; ES:DI -> Start of Line ADD DI, BX ; ES:DI -> Upper Left Pixel MOV [BP].TB_Start, DI ; Save Starting Addr - + ; Compute line to line offset - + MOV BX, [BP].TB_Width ; Get Width of Image MOV DX, BX ; Save Copy in DX - SHR BX, 2 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands + SHR BX, 1 ; /4 = width in bands MOV AX, SCREEN_WIDTH ; Get Screen Width SUB AX, BX ; - (Bitmap Width/4) - + MOV [BP].TB_LineO, AX ; Save Line Width offset MOV [BP].TB_PixCount, BX ; Minimum # pix to copy - + AND DX, PLANE_BITS ; Get "partial band" size (0-3) MOV [BP].TB_PixSkew, DX ; Also End of Line Skew MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count - + AND CX, PLANE_BITS ; CL = Starting Plane # MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select SHL AH, CL ; Select correct Plane OUT_16 SC_Index, AX ; Select Plane... MOV BH, AH ; BH = Saved Plane Mask MOV BL, 4 ; BL = Planes to Copy - + @TB_COPY_PLANE: - + LDS SI, [BP].TB_Image ; DS:SI-> Source Image MOV DX, [BP].TB_Height ; # of Lines to Copy MOV DI, [BP].TB_Start ; ES:DI-> Dest pos - + ; Here AH is set with the value to be considered ; "Transparent". It can be changed! - + MOV AH, 0 ; Value to Detect 0 - + @TB_COPY_LINE: MOV CX, [BP].TB_PixCount ; Min # to copy - + TEST CL, 0FCh ; 16+PixWide? JZ @TB_COPY_REMAINDER ; Nope... - + ; Pixel Copy loop has been unrolled to x4 - + @TB_COPY_LOOP: LODSB ; Get Pixel Value in AL ADD SI, 3 ; Skip to Next Byte in same plane CMP AL, AH ; It is "Transparent"? JE @TB_SKIP_01 ; Skip ahead if so MOV ES:[DI], AL ; Copy Pixel to VGA screen - + @TB_SKIP_01: LODSB ; Get Pixel Value in AL ADD SI, 3 ; Skip to Next Byte in same plane CMP AL, AH ; It is "Transparent"? JE @TB_SKIP_02 ; Skip ahead if so MOV ES:[DI+1], AL ; Copy Pixel to VGA screen - + @TB_SKIP_02: LODSB ; Get Pixel Value in AL ADD SI, 3 ; Skip to Next Byte in same plane CMP AL, AH ; It is "Transparent"? JE @TB_SKIP_03 ; Skip ahead if so MOV ES:[DI+2], AL ; Copy Pixel to VGA screen - + @TB_SKIP_03: LODSB ; Get Pixel Value in AL ADD SI, 3 ; Skip to Next Byte in same plane CMP AL, AH ; It is "Transparent"? JE @TB_SKIP_04 ; Skip ahead if so MOV ES:[DI+3], AL ; Copy Pixel to VGA screen - + @TB_SKIP_04: ADD DI, 4 ; Adjust Pixel Write Location SUB CL, 4 ; Pixels to Copy=-4 TEST CL, 0FCh ; 4+ Pixels Left? JNZ @TB_COPY_LOOP ; if so, do another block - + @TB_COPY_REMAINDER: JCXZ @TB_NEXT_LINE ; Any Pixels left on line - + @TB_COPY2: LODSB ; Get Pixel Value in AL ADD SI, 3 ; Skip to Next Byte in same plane CMP AL, AH ; It is "Transparent"? JE @TB_SKIP_05 ; Skip ahead if so MOV ES:[DI], AL ; Copy Pixel to VGA screen - + @TB_SKIP_05: INC DI ; Advance Dest Addr LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done - + @TB_NEXT_LINE: - + ; any Partial Pixels? (some planes only) - + OR CX, [BP].TB_SkewFlag ; Get Skew Count JZ @TB_NEXT2 ; if no partial pixels - + LODSB ; Get Pixel Value in AL DEC SI ; Backup to Align CMP AL, AH ; It is "Transparent"? JE @TB_NEXT2 ; Skip ahead if so MOV ES:[DI], AL ; Copy Pixel to VGA screen - + @TB_NEXT2: ADD SI, [BP].TB_PixSkew ; Adjust Skew ADD DI, [BP].TB_LineO ; Set to Next Display Line LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More - + ;Copy Next Plane.... - + DEC BL ; Planes to Go-- JZ @TB_Exit ; Hey! We are done - + ROL BH, 1 ; Next Plane in line... OUT_8 SC_Data, BH ; Select Plane - + CMP AL, 12h ; Carry Set if AL=11h ADC [BP].TB_Start, 0 ; Screen Addr =+Carry INC w [BP].TB_Image ; Start @ Next Byte - + SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1 - + JMP @TB_COPY_PLANE ; Go Copy the next Plane - + @TB_Exit: ADD SP, 10 ; Deallocate workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 12 ; Exit and Clean up Stack - + TDRAW_BITMAP ENDP - - + + ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== - + ;================================== ;COPY_PAGE (SourcePage%, DestPage%) ;================================== @@ -2976,70 +3160,81 @@ TDRAW_BITMAP ENDP ; ; EXIT: No meaningful values returned ; - + CP_STACK STRUC - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller CP_DestP DW ? ; Page to hold copied image CP_SourceP DW ? ; Page to Make copy from CP_STACK ENDS - + PUBLIC COPY_PAGE - + COPY_PAGE PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di MOV BP, SP ; Set up Stack Frame CLD ; Block Xfer Forwards - + ; Make sure Page #'s are valid - + MOV AX, [BP].CP_SourceP ; Get Source Page # CMP AX, LAST_PAGE ; is it > Max Page #? JAE @CP_Exit ; if so, abort - + MOV BX, [BP].CP_DestP ; Get Destination Page # CMP BX, LAST_PAGE ; is it > Max Page #? JAE @CP_Exit ; if so, abort - + CMP AX, BX ; Pages #'s the same? JE @CP_Exit ; if so, abort - + ; Setup DS:SI and ES:DI to Video Pages - + SHL BX, 1 ; Scale index to Word MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page - + MOV BX, AX ; Index to Source page SHL BX, 1 ; Scale index to Word MOV SI, PAGE_ADDR[BX] ; Offset to Source Page - + MOV CX, PAGE_SIZE ; Get size of Page MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment MOV ES, AX ; ES:DI -> Dest Page MOV DS, AX ; DS:SI -> Source Page - + ; Setup VGA registers for Mem to Mem copy - + OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes - + ; Note.. Do *NOT* use MOVSW or MOVSD - they will ; Screw with the latches which are 8 bits x 4 - + REP MOVSB ; Copy entire Page! - + ; Reset VGA for normal memory access - + OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off - + @CP_Exit: - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 4 ; Exit and Clean up Stack - + COPY_PAGE ENDP - - + + ;========================================================================== ;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%) ;========================================================================== @@ -3065,11 +3260,14 @@ COPY_PAGE ENDP ; ; EXIT: AX = Success Flag: 0 = Failure / -1= Success ; - + CB_STACK STRUC CB_Height DW ? ; Height of Image in Lines CB_Width DW ? ; Width of Image in "bands" - DW ?x4 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DI, SI, DS, BP + DW ?x1 ; DS, DI, SI, BP + DW ?x1 ; DS, DI, SI, BP DD ? ; Caller CB_DestY1 DW ? ; Destination Ypos CB_DestX1 DW ? ; Destination Xpos @@ -3080,64 +3278,71 @@ CB_STACK STRUC CB_X1 DW ? ; UL Xpos of Image CB_SourceP DW ? ; Page containing Source Bitmap CB_STACK ENDS - + PUBLIC COPY_BITMAP - + COPY_BITMAP PROC FAR - - PUSHx BP, DS, SI, DI ; Preserve Important Registers + + ;PUSHx BP, DS, SI, DI ; Preserve Important Registers + push bp + push ds + push si + push di SUB SP, 4 ; Allocate WorkSpace on Stack MOV BP, SP ; Set up Stack Frame - + ; Prep Registers (and keep jumps short!) - + MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram CLD ; Block Xfer Forwards - + ; Make sure Parameters are valid - + MOV BX, [BP].CB_SourceP ; Get Source Page # CMP BX, LAST_PAGE ; is it > Max Page #? JAE @CB_Abort ; if so, abort - + MOV CX, [BP].CB_DestP ; Get Destination Page # CMP CX, LAST_PAGE ; is it > Max Page #? JAE @CB_Abort ; if so, abort - + MOV AX, [BP].CB_X1 ; Get Source X1 XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1 AND AX, PLANE_BITS ; Check Plane Bits JNZ @CB_Abort ; They should cancel out - + ; Setup for Copy processing - + OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on - + ; Compute Info About Images, Setup ES:SI & ES:DI - + MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1 INC AX ; (add 1 since were not 0 based) MOV [BP].CB_Height, AX ; Save on Stack for later use - + MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1 - SHR AX, 2 ; Get X2 Band (X2 / 4) - SHR DX, 2 ; Get X1 Band (X1 / 4) + SHR AX, 1 ; Get X2 Band (X2 / 4) + SHR DX, 1 ; Get X1 Band (X1 / 4) + SHR AX, 1 ; Get X2 Band (X2 / 4) + SHR DX, 1 ; Get X1 Band (X1 / 4) SUB AX, DX ; AX = # of Bands - 1 INC AX ; AX = # of Bands MOV [BP].CB_Width, AX ; Save on Stack for later use - + SHL BX, 1 ; Scale Source Page to Word MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page MOV AX, [BP].CB_Y1 ; Get Source Y1 Line MUL SCREEN_WIDTH ; AX = Offset to Line Y1 ADD SI, AX ; SI = Offset to Line Y1 MOV AX, [BP].CB_X1 ; Get Source X1 - SHR AX, 2 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset ADD SI, AX ; SI = Byte Offset to (X1,Y1) - + MOV BX, CX ; Dest Page Index to BX SHL BX, 1 ; Scale Source Page to Word MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page @@ -3145,24 +3350,25 @@ COPY_BITMAP PROC FAR MUL SCREEN_WIDTH ; AX = Offset to Line Y1 ADD DI, AX ; DI = Offset to Line Y1 MOV AX, [BP].CB_DestX1 ; Get Dest X1 - SHR AX, 2 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset + SHR AX, 1 ; X1 / 4 = Byte offset ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1) - + MOV CX, [BP].CB_Width ; CX = Width of Image (Bands) DEC CX ; CX = 1? JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band - + MOV BX, [BP].CB_X1 ; Get Source X1 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?) JZ @CB_Check_Right ; if so, check right alignment JNZ @CB_Left_Band ; not aligned? well.. - + @CB_Abort: - CLR AX ; Return False (Failure) + mov ax,0 ; Return False (Failure) JMP @CB_Exit ; and Finish Up - + ; Copy when Left & Right Clip Masks overlap... - + @CB_Only_One_Band: MOV BX, [BP].CB_X1 ; Get Left Clip Mask AND BX, PLANE_BITS ; Mask out Row # @@ -3170,126 +3376,130 @@ COPY_BITMAP PROC FAR MOV BX, [BP].CB_X2 ; Get Right Clip Mask AND BX, PLANE_BITS ; Mask out Row # AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte - + OUT_8 SC_Data, AL ; Clip For Left & Right Masks - + MOV CX, [BP].CB_Height ; CX = # of Lines to Copy MOV DX, SCREEN_WIDTH ; DX = Width of Screen - CLR BX ; BX = Offset into Image - + mov bx,0 ; BX = Offset into Image + @CB_One_Loop: MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPjz CX, @CB_One_Done ; Exit Loop if Finished - + MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPx CX, @CB_One_Loop ; Loop until Finished - + @CB_One_Done: JMP @CB_Finish ; Outa Here! - + ; Copy Left Edge of Bitmap - + @CB_Left_Band: - + OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask - + MOV CX, [BP].CB_Height ; CX = # of Lines to Copy MOV DX, SCREEN_WIDTH ; DX = Width of Screen - CLR BX ; BX = Offset into Image - + mov bx,0 ; BX = Offset into Image + @CB_Left_Loop: MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished - + MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPx CX, @CB_Left_Loop ; Loop until Finished - + @CB_Left_Done: INC DI ; Move Dest Over 1 band INC SI ; Move Source Over 1 band DEC [BP].CB_Width ; Band Width-- - + ; Determine if Right Edge of Bitmap needs special copy - + @CB_Check_Right: MOV BX, [BP].CB_X2 ; Get Source X2 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?) CMP BL, 03h ; Plane = 3? JE @CB_Copy_Middle ; Copy the Middle then! - + ; Copy Right Edge of Bitmap - + @CB_Right_Band: - + OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask - + DEC [BP].CB_Width ; Band Width-- MOV CX, [BP].CB_Height ; CX = # of Lines to Copy MOV DX, SCREEN_WIDTH ; DX = Width of Screen MOV BX, [BP].CB_Width ; BX = Offset to Right Edge - + @CB_Right_Loop: MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished - + MOV AL, ES:[SI+BX] ; Load Latches MOV ES:[DI+BX], AL ; Unload Latches ADD BX, DX ; Advance Offset to Next Line LOOPx CX, @CB_Right_Loop ; Loop until Finished - + @CB_Right_Done: - + ; Copy the Main Block of the Bitmap - + @CB_Copy_Middle: - + MOV CX, [BP].CB_Width ; Get Width Remaining JCXZ @CB_Finish ; Exit if Done - + OUT_8 SC_Data, ALL_PLANES ; Copy all Planes - + MOV DX, SCREEN_WIDTH ; Get Width of Screen minus SUB DX, CX ; Image width (for Adjustment) MOV AX, [BP].CB_Height ; AX = # of Lines to Copy MOV BX, CX ; BX = Quick REP reload count MOV CX, ES ; Move VGA Segment MOV DS, CX ; Into DS - + ; Actual Copy Loop. REP MOVSB does the work - + @CB_Middle_Copy: MOV CX, BX ; Recharge Rep Count REP MOVSB ; Move Bands LOOPjz AX, @CB_Finish ; Exit Loop if Finished - + ADD SI, DX ; Adjust DS:SI to Next Line ADD DI, DX ; Adjust ES:DI to Next Line - + MOV CX, BX ; Recharge Rep Count REP MOVSB ; Move Bands - + ADD SI, DX ; Adjust DS:SI to Next Line ADD DI, DX ; Adjust ES:DI to Next Line LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done - + @CB_Finish: OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on - + @CB_Exit: ADD SP, 04 ; Deallocate stack workspace - POPx DI, SI, DS, BP ; Restore Saved Registers + ;POPx DI, SI, DS, BP ; Restore Saved Registers + pop di + pop si + pop ds + pop bp RET 16 ; Exit and Clean up Stack - + COPY_BITMAP ENDP - + END ; End of Code Segment