Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 1 - 1 ;======================================================== ; MODEX.ASM - A Complete Mode X Library ; ; Version 1.04 Release, 3 May 1993, By Matt Pritchard ; With considerable input from Michael Abrash ; ; The following information is donated to the public domain in ; the hopes that save other programmers much frustration. ; ; If you do use this code in a product, it would be nice if ; you include a line like "Mode X routines by Matt Pritchard" ; in the credits. ; ; ========================================================= ; ; All of this code is designed to be assembled with MASM 5.10a ; but TASM 3.0 could be used as well. ; ; The routines contained are designed for use in a MEDIUM model ; program. All Routines are FAR, and is assumed that a DGROUP ; data segment exists and that DS will point to it on entry. ; ; For all routines, the AX, BX, CX, DX, ES and FLAGS registers ; will not be preserved, while the DS, BP, SI and DI registers ; will be preserved. ; ; Unless specifically noted, All Parameters are assumed to be ; "PASSED BY VALUE". That is, the actual value is placed on ; the stack. When a reference is passed it is assumed to be ; a near pointer to a variable in the DGROUP segment. ; ; Routines that return a single 16-Bit integer value will ; return that value in the AX register. ; ; This code will *NOT* run on an 8086/8088 because 80286+ ; specific instructions are used. If you have an 8088/86 ; and VGA, you can buy an 80386-40 motherboard for about ; $160 and move into the 90's. ; ; This code is reasonably optimized: Most drawing loops have ; been unrolled once and memory references are minimized by ; keeping stuff in registers when possible. ; ; Error Trapping varies by Routine. No Clipping is performed ; so the caller should verify that all coordinates are valid. ; ; Several Macros are used to simplify common 2 or 3 instruction ; sequences. Several Single letter Text Constants also ; simplify common assembler expressions like "WORD PTR". ; ; ------------------ Mode X Variations ------------------ ; ; Mode # Screen Size Max Pages Aspect Ratio (X:Y) ; ; 0 320 x 200 4 Pages 1.2:1 ; 1 320 x 400 2 Pages 2.4:1 ; 2 360 x 200 3 Pages 1.35:1 ; 3 360 x 400 1 Page 2.7:1 ; 4 320 x 240 3 Pages 1:1 ; 5 320 x 480 1 Page 2:1 ; 6 360 x 240 3 Pages 1.125:1 ; 7 360 x 480 1 Page 2.25:1 ; ; -------------------- The Legal Stuff ------------------ ; ; No warranty, either written or implied, is made as to ; the accuracy and usability of this code product. Use ; at your own risk. Batteries not included. Pepperoni ; and extra cheese available for an additional charge. ; ; ----------------------- The Author -------------------- ; ; Matt Pritchard is a paid programmer who'd rather be ; writing games. He can be reached at: P.O. Box 140264, ; Irving, TX 75014 USA. Michael Abrash is a living ; god, who now works for Bill Gates (Microsoft). ; ; -------------------- Revision History ----------------- ; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI ; SET_MODEX now saves SI ; 5-3-93: v1.04 - added LOAD_DAC_REGISTERS and ; READ_DAC_REGISTERS. Expanded CLR Macro ; to handle multiple registers ; PAGE 255, 132 .MODEL Medium .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 ENDIF IFDIFI , ; If AX not setup MOV AX, Value ; then Get Data 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 ENDIF IFDIFI , ; If AL not Setup MOV AL, Value ; then Get Data 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 ; 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 ; 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 ; ===== VGA Register Values ===== = A000 VGA_Segment EQU 0A000h ; Vga Memory Segment = 03C0 ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller = 03CE GC_Index EQU 03CEh ; VGA Graphics Controller = 03C4 SC_Index EQU 03C4h ; VGA Sequencer Controller = 03C5 SC_Data EQU 03C5h ; VGA Sequencer Data Port = 03D4 CRTC_Index EQU 03D4h ; VGA CRT Controller = 03D5 CRTC_Data EQU 03D5h ; VGA CRT Controller Data = 03C2 MISC_OUTPUT EQU 03C2h ; VGA Misc Register = 03DA INPUT_1 EQU 03DAh ; Input Status #1 Register = 03C8 DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register = 03C7 DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register = 03C9 PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W = 0033 PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg = 0002 MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg = 0004 READ_MAP EQU 004h ; GC Index: Read Map Register = 000C START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi = 000D START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo = 0102 MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1 = 1102 MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1 = 0F02 ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes = 0604 CHAIN4_OFF EQU 00604h ; Chain 4 mode Off = 0100 ASYNC_RESET EQU 00100h ; (A)synchronous Reset = 0300 SEQU_RESTART EQU 00300h ; Sequencer Restart = 0008 LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches = FF08 LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU = 0008 VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit = 0003 PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane # = 000F ALL_PLANES EQU 0Fh ; All Bit Planes Selected = 000F CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data = 1130 GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set = 0003 ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer = 0004 ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer ; Constants Specific for these routines = 0008 NUM_MODES EQU 8 ; # of Mode X Variations ; Specific Mode Data Table format... 000C Mode_Data_Table STRUC 0000 00 M_MiscR DB ? ; Value of MISC_OUTPUT register 0001 00 M_Pages DB ? ; Maximum Possible # of pages 0002 0000 M_XSize DW ? ; X Size Displayed on screen 0004 0000 M_YSize DW ? ; Y Size Displayed on screen 0006 0000 M_XMax DW ? ; Maximum Possible X Size 0008 0000 M_YMax DW ? ; Maximum Possible Y Size 000A 0000 M_CRTC DW ? ; Table of CRTC register values Mode_Data_Table ENDS ; ===== DGROUP STORAGE NEEDED (42 BYTES) ===== 0000 .DATA? 0000 0000 SCREEN_WIDTH DW 0 ; Width of a line in Bytes 0002 0000 SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels 0004 0000 LAST_PAGE DW 0 ; # of Display Pages 0006 0004 [ PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page 0000 ] 000E 0000 PAGE_SIZE DW 0 ; Size of Page in Addr Bytes 0010 0000 DISPLAY_PAGE DW 0 ; Page # currently displayed 0012 0000 ACTIVE_PAGE DW 0 ; Page # currently active 0014 0000 CURRENT_PAGE DW 0 ; Offset of current Page 0016 0000 CURRENT_SEGMENT DW 0 ; Segment of VGA memory 0018 0000 CURRENT_XOFFSET DW 0 ; Current Display X Offset 001A 0000 CURRENT_YOFFSET DW 0 ; Current Display Y Offset 001C 0000 CURRENT_MOFFSET DW 0 ; Current Start Offset 001E 0000 MAX_XOFFSET DW 0 ; Current Display X Offset 0020 0000 MAX_YOFFSET DW 0 ; Current Display Y Offset 0022 0000 0000 CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127 0026 0000 0000 CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255 0000 .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 0000 0F 0E 0C 08 Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H 0004 01 03 07 0F Right_Clip_Mask DB 01H, 03H, 07H, 0FH ; Bit Patterns for converting character fonts 0008 00 08 04 0C 02 0A Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH 06 0E 0010 01 09 05 0D 03 0B DB 01H,09H,05H,0DH,03H,0BH,07H,0FH 07 0F ; CRTC Register Values for Various Configurations 0018 MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes 0018 4009 DW 04009H ; Cell Height (1 Scan Line) 001A 0014 DW 00014H ; Dword Mode off 001C E317 DW 0E317H ; turn on Byte Mode 001E 0000 DW nil ; End of CRTC Data for 400/480 Line Mode 0020 MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes 0020 4109 DW 04109H ; Cell Height (2 Scan Lines) 0022 0014 DW 00014H ; Dword Mode off 0024 E317 DW 0E317H ; turn on Byte Mode 0026 0000 DW nil ; End of CRTC Data for 200/240 Line Mode 0028 MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels 0028 5F00 DW 05F00H ; Horz total 002A 4F01 DW 04F01H ; Horz Displayed 002C 5002 DW 05002H ; Start Horz Blanking 002E 8203 DW 08203H ; End Horz Blanking 0030 5404 DW 05404H ; Start H Sync 0032 8005 DW 08005H ; End H Sync 0034 0000 DW nil ; End of CRTC Data for 320 Horz pixels 0036 MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels 0036 6B00 DW 06B00H ; Horz total 0038 5901 DW 05901H ; Horz Displayed 003A 5A02 DW 05A02H ; Start Horz Blanking 003C 8E03 DW 08E03H ; End Horz Blanking 003E 5E04 DW 05E04H ; Start H Sync 0040 8A05 DW 08A05H ; End H Sync 0042 0000 DW nil ; End of CRTC Data for 360 Horz pixels 0044 MODE_200_Tall: 0044 MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes 0044 BF06 DW 0BF06H ; Vertical Total 0046 1F07 DW 01F07H ; Overflow 0048 9C10 DW 09C10H ; V Sync Start 004A 8E11 DW 08E11H ; V Sync End/Prot Cr0 Cr7 004C 8F12 DW 08F12H ; Vertical Displayed 004E 9615 DW 09615H ; V Blank Start 0050 B916 DW 0B916H ; V Blank End 0052 0000 DW nil ; End of CRTC Data for 200/400 Lines 0054 MODE_240_Tall: 0054 MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes 0054 0D06 DW 00D06H ; Vertical Total 0056 3E07 DW 03E07H ; Overflow 0058 EA10 DW 0EA10H ; V Sync Start 005A 8C11 DW 08C11H ; V Sync End/Prot Cr0 Cr7 005C DF12 DW 0DF12H ; Vertical Displayed 005E E715 DW 0E715H ; V Blank Start 0060 0616 DW 00616H ; V Blank End 0062 0000 DW nil ; End of CRTC Data for 240/480 Lines ; Table of Display Mode Tables 0064 MODE_TABLE: 0064 0074 R 0086 R DW o MODE_320x200, o MODE_320x400 0068 00E0 R 00F2 R DW o MODE_360x200, o MODE_360x400 006C 00BC R 00CE R DW o MODE_320x240, o MODE_320x480 Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 2 - 1 0070 0098 R 00AA R DW o MODE_360x240, o MODE_360x480 ; Table of Display Mode Components 0074 MODE_320x200: ; Data for 320 by 200 Pixels 0074 63 DB 063h ; 400 scan Lines & 25 Mhz Clock 0075 04 DB 4 ; Maximum of 4 Pages 0076 0140 00C8 DW 320, 200 ; Displayed Pixels (X,Y) 007A 0516 0330 DW 1302, 816 ; Max Possible X and Y Sizes 007E 0028 R 0044 R DW o MODE_320_Wide, o MODE_200_Tall 0082 0020 R 0000 DW o MODE_Double_Line, nil 0086 MODE_320x400: ; Data for 320 by 400 Pixels 0086 63 DB 063h ; 400 scan Lines & 25 Mhz Clock 0087 02 DB 2 ; Maximum of 2 Pages 0088 0140 0190 DW 320, 400 ; Displayed Pixels X,Y 008C 0288 0330 DW 648, 816 ; Max Possible X and Y Sizes 0090 0028 R 0044 R DW o MODE_320_Wide, o MODE_400_Tall 0094 0018 R 0000 DW o MODE_Single_Line, nil 0098 MODE_360x240: ; Data for 360 by 240 Pixels 0098 E7 DB 0E7h ; 480 scan Lines & 28 Mhz Clock 0099 03 DB 3 ; Maximum of 3 Pages 009A 0168 00F0 DW 360, 240 ; Displayed Pixels X,Y 009E 0444 02D8 DW 1092, 728 ; Max Possible X and Y Sizes 00A2 0036 R 0054 R DW o MODE_360_Wide, o MODE_240_Tall 00A6 0020 R 0000 DW o MODE_Double_Line , nil 00AA MODE_360x480: ; Data for 360 by 480 Pixels 00AA E7 DB 0E7h ; 480 scan Lines & 28 Mhz Clock 00AB 01 DB 1 ; Only 1 Page Possible 00AC 0168 01E0 DW 360, 480 ; Displayed Pixels X,Y 00B0 0220 02D8 DW 544, 728 ; Max Possible X and Y Sizes 00B4 0036 R 0054 R DW o MODE_360_Wide, o MODE_480_Tall 00B8 0018 R 0000 DW o MODE_Single_Line , nil 00BC MODE_320x240: ; Data for 320 by 240 Pixels 00BC E3 DB 0E3h ; 480 scan Lines & 25 Mhz Clock 00BD 03 DB 3 ; Maximum of 3 Pages 00BE 0140 00F0 DW 320, 240 ; Displayed Pixels X,Y 00C2 0440 0332 DW 1088, 818 ; Max Possible X and Y Sizes 00C6 0028 R 0054 R DW o MODE_320_Wide, o MODE_240_Tall 00CA 0020 R 0000 DW o MODE_Double_Line, nil 00CE MODE_320x480: ; Data for 320 by 480 Pixels 00CE E3 DB 0E3h ; 480 scan Lines & 25 Mhz Clock 00CF 01 DB 1 ; Only 1 Page Possible 00D0 0140 01E0 DW 320, 480 ; Displayed Pixels X,Y 00D4 021C 0332 DW 540, 818 ; Max Possible X and Y Sizes 00D8 0028 R 0054 R DW o MODE_320_WIDE, o MODE_480_Tall 00DC 0018 R 0000 DW o MODE_Single_Line, nil 00E0 MODE_360x200: ; Data for 360 by 200 Pixels 00E0 67 DB 067h ; 400 scan Lines & 28 Mhz Clock 00E1 03 DB 3 ; Maximum of 3 Pages 00E2 0168 00C8 DW 360, 200 ; Displayed Pixels (X,Y) 00E6 0516 02D8 DW 1302, 728 ; Max Possible X and Y Sizes 00EA 0036 R 0044 R DW o MODE_360_Wide, MODE_200_Tall 00EE 0020 R 0000 DW o MODE_Double_Line, nil 00F2 MODE_360x400: ; Data for 360 by 400 Pixels 00F2 67 DB 067h ; 400 scan Lines & 28 Mhz Clock 00F3 01 DB 1 ; Maximum of 1 Pages 00F4 0168 0190 DW 360, 400 ; Displayed Pixels X,Y 00F8 0288 0330 DW 648, 816 ; Max Possible X and Y Sizes 00FC 0036 R 0044 R DW o MODE_360_Wide, MODE_400_Tall 0100 0018 R 0000 DW o MODE_Single_Line, nil ; ===== MODE X SETUP ROUTINES ===== ;====================================================== ;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%) ;====================================================== ; ; Sets Up the specified version of Mode X. Allows for ; the setup of multiple video pages, and a virtual ; screen which can be larger than the displayed screen ; (which can then be scrolled a pixel at a time) ; ; ENTRY: ModeType = Desired Screen Resolution (0-7) ; ; 0 = 320 x 200, 4 Pages max, 1.2:1 Aspect Ratio ; 1 = 320 x 400, 2 Pages max, 2.4:1 Aspect Ratio ; 2 = 360 x 200, 3 Pages max, 1.35:1 Aspect Ratio ; 3 = 360 x 400, 1 Page max, 2.7:1 Aspect Ratio ; 4 = 320 x 240, 3 Pages max, 1:1 Aspect Ratio ; 5 = 320 x 480, 1 Page max, 2:1 Aspect Ratio ; 6 = 360 x 240, 3 Pages max, 1.125:1 Aspect Ratio ; 7 = 360 x 480, 1 Page max, 2.25:1 Aspect Ratio ; ; MaxXpos = The Desired Virtual Screen Width ; MaxYpos = The Desired Virtual Screen Height ; Pages = The Desired # of Video Pages ; ; EXIT: AX = Success Flag: 0 = Failure / -1= Success ; 0016 SVM_STACK STRUC 0000 0000 SVM_Table DW ? ; Offset of Mode Info Table 0002 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP 0000 000A 00000000 DD ? ; Caller 000E 0000 SVM_Pages DW ? ; # of Screen Pages desired 0010 0000 SVM_Ysize DW ? ; Vertical Screen Size Desired 0012 0000 SVM_Xsize DW ? ; Horizontal Screen Size Desired 0014 0000 SVM_Mode DW ? ; Display Resolution Desired SVM_STACK ENDS PUBLIC SET_VGA_MODEX 0104 SET_VGA_MODEX PROC FAR PUSHx BP, DS, SI, DI ; Preserve Important Registers 0104 55 1 PUSH BP ; Save R1 0105 1E 2 PUSH DS ; Save R1 0106 56 3 PUSH SI ; Save R1 0107 57 4 PUSH DI ; Save R1 0108 83 EC 02 SUB SP, 2 ; Allocate workspace 010B 8B EC MOV BP, SP ; Set up Stack Frame ; Check Legality of Mode Request.... 010D 8B 5E 14 MOV BX, [BP].SVM_Mode ; Get Requested Mode # 0110 83 FB 08 CMP BX, NUM_MODES ; Is it 0..7? 0113 73 47 JAE @SVM_BadModeSetup ; If Not, Error out 0115 D1 E3 SHL BX, 1 ; Scale BX 0117 2E: 8B B7 0064 R MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info 011C 89 76 00 MOV [BP].SVM_Table, SI ; Save ptr for later use ; Check # of Requested Display Pages 011F 8B 4E 0E MOV CX, [BP].SVM_Pages ; Get # of Requested Pages CLR CH ; Set Hi Word = 0! 0122 32 ED 1 XOR CH, CH ; Set Register = 0 0124 2E: 3A 4C 01 CMP CL, CS:[SI].M_Pages ; Check # Pages for mode 0128 77 32 JA @SVM_BadModeSetup ; Report Error if too Many Pages 012A E3 30 JCXZ @SVM_BadModeSetup ; Report Error if 0 Pages ; Check Validity of X Size 012C 83 66 12 F8 AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0 0130 8B 46 12 MOV AX, [BP].SVM_XSize ; Get Logical Screen Width 0133 2E: 3B 44 02 CMP AX, CS:[SI].M_XSize ; Check against Displayed X 0137 72 23 JB @SVM_BadModeSetup ; Report Error if too small 0139 2E: 3B 44 06 CMP AX, CS:[SI].M_XMax ; Check against Max X 013D 77 1D JA @SVM_BadModeSetup ; Report Error if too big ; Check Validity of Y Size 013F 8B 5E 10 MOV BX, [BP].SVM_YSize ; Get Logical Screen Height 0142 2E: 3B 5C 04 CMP BX, CS:[SI].M_YSize ; Check against Displayed Y 0146 72 14 JB @SVM_BadModeSetup ; Report Error if too small 0148 2E: 3B 5C 08 CMP BX, CS:[SI].M_YMax ; Check against Max Y 014C 77 0E JA @SVM_BadModeSetup ; Report Error if too big ; Enough memory to Fit it all? 014E C1 E8 02 SHR AX, 2 ; # of Bytes:Line = XSize/4 0151 F7 E1 MUL CX ; AX = Bytes/Line * Pages 0153 F7 E3 MUL BX ; DX:AX = Total VGA mem needed 0155 71 0A JNO @SVM_Continue ; Exit if Total Size > 256K 0157 4A DEC DX ; Was it Exactly 256K??? 0158 0B D0 OR DX, AX ; (DX = 1, AX = 0000) 015A 74 05 JZ @SVM_Continue ; if so, it's valid... 015C @SVM_BadModeSetup: CLR AX ; Return Value = False 015C 33 C0 1 XOR AX, AX ; Set Register = 0 015E E9 00E6 JMP @SVM_Exit ; Normal Exit 0161 @SVM_Continue: 0161 B8 0013 MOV AX, 13H ; Start with Mode 13H 0164 CD 10 INT 10H ; Let BIOS Set Mode OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode 0166 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register 0169 B8 0604 1 MOV AX, CHAIN4_OFF ; then Get Data Value 016C EF 1 OUT DX, AX ; Set I/O Register(s) OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset 016D BA 03C4 1 MOV DX, SC_INDEX ; then Select Register 0170 B8 0100 1 MOV AX, ASYNC_RESET ; then Get Data Value 0173 EF 1 OUT DX, AX ; Set I/O Register(s) OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size 0174 BA 03C2 1 MOV DX, MISC_OUTPUT ; then Select Register 0177 2E: 8A 04 1 MOV AL, CS:[SI].M_MiscR ; then Get Data Value 017A EE 1 OUT DX, AL ; Set I/O Register OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ... 017B BA 03C4 1 MOV DX, SC_INDEX ; then Select Register 017E B8 0300 1 MOV AX, SEQU_RESTART ; then Get Data Value 0181 EF 1 OUT DX, AX ; Set I/O Register(s) OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register 0182 BA 03D4 1 MOV DX, CRTC_INDEX ; then Select Register 0185 B0 11 1 MOV AL, 11H ; then Get Data Value 0187 EE 1 OUT DX, AL ; Set I/O Register 0188 42 INC DX ; Point to Data 0189 EC IN AL, DX ; Get Value, Bit 7 = Protect 018A 24 7F AND AL, 7FH ; Mask out Write Protect 018C EE OUT DX, AL ; And send it back 018D BA 03D4 MOV DX, CRTC_INDEX ; Vga Crtc Registers 0190 83 C6 0A ADD SI, M_CRTC ; SI -> CRTC Parameter Data ; Load Tables of CRTC Parameters from List of Tables 0193 @SVM_Setup_Table: 0193 2E: 8B 3C MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl 0196 83 C6 02 ADD SI, 2 ; Point to next Ptr Entry 0199 0B FF OR DI, DI ; A nil Ptr means that we have 019B 74 0D JZ @SVM_Set_Data ; finished CRTC programming 019D @SVM_Setup_CRTC: 019D 2E: 8B 05 MOV AX, CS:[DI] ; Get CRTC Data from Table 01A0 83 C7 02 ADD DI, 2 ; Advance Pointer 01A3 0B C0 OR AX, AX ; At End of Data Table? 01A5 74 EC JZ @SVM_Setup_Table ; If so, Exit & get next Table 01A7 EF OUT DX, AX ; Reprogram VGA CRTC reg 01A8 EB F3 JMP s @SVM_Setup_CRTC ; Process Next Table Entry ; Initialize Page & Scroll info, DI = 0 01AA @SVM_Set_Data: 01AA 89 3E 0010 R MOV DISPLAY_PAGE, DI ; Display Page = 0 01AE 89 3E 0012 R MOV ACTIVE_PAGE, DI ; Active Page = 0 01B2 89 3E 0014 R MOV CURRENT_PAGE, DI ; Current Page (Offset) = 0 01B6 89 3E 0018 R MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0 01BA 89 3E 001A R MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0 Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 3 - 1 01BE 89 3E 001C R MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0 01C2 B8 A000 MOV AX, VGA_SEGMENT ; Segment for VGA memory 01C5 A3 0016 R MOV CURRENT_SEGMENT, AX ; Save for Future LES's ; Set Logical Screen Width, X Scroll and Our Data 01C8 8B 76 00 MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info 01CB 8B 46 12 MOV AX, [BP].SVM_Xsize ; Get Display Width 01CE 8B C8 MOV CX, AX ; CX = Logical Width 01D0 2E: 2B 4C 02 SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value 01D4 89 0E 001E R MOV MAX_XOFFSET, CX ; Set Maximum X Scroll 01D8 C1 E8 02 SHR AX, 2 ; Bytes = Pixels / 4 01DB A3 0000 R MOV SCREEN_WIDTH, AX ; Save Width in Pixels 01DE D1 E8 SHR AX, 1 ; Offset Value = Bytes / 2 01E0 B4 13 MOV AH, 13h ; CRTC Offset Register Index 01E2 86 C4 XCHG AL, AH ; Switch format for OUT 01E4 EF OUT DX, AX ; Set VGA CRTC Offset Reg ; Setup Data table, Y Scroll, Misc for Other Routines 01E5 8B 46 10 MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height 01E8 8B C8 MOV CX, AX ; CX = Logical Height 01EA 2E: 2B 5C 04 SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value 01EE 89 0E 0020 R MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll 01F2 A3 0002 R MOV SCREEN_HEIGHT, AX ; Save Height in Pixels 01F5 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Page Size in Bytes, 01F9 A3 000E R MOV PAGE_SIZE, AX ; Save Page Size 01FC 8B 4E 0E MOV CX, [BP].SVM_Pages ; Get # of Pages 01FF 89 0E 0004 R MOV LAST_PAGE, CX ; Save # of Pages CLR BX ; Page # = 0 0203 33 DB 1 XOR BX, BX ; Set Register = 0 0205 8B D3 MOV DX, BX ; Page 0 Offset = 0 0207 @SVM_Set_Pages: 0207 89 97 0006 R MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset 020B 83 C3 02 ADD BX, 2 ; Page#++ 020E 03 D0 ADD DX, AX ; Compute Addr of Next Page LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set 0210 49 1 DEC CX ; Counter-- 0211 75 F4 1 JNZ @SVM_Set_Pages ; Jump if not 0 ; Clear VGA Memory OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes 0213 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register 0216 B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value 0219 EF 1 OUT DX, AX ; Set I/O Register(s) 021A C4 3E 0014 R LES DI, d CURRENT_PAGE ; -> Start of VGA memory CLR AX ; AX = 0 021E 33 C0 1 XOR AX, AX ; Set Register = 0 0220 FC CLD ; Block Xfer Forwards 0221 B9 8000 MOV CX, 8000H ; 32K * 4 * 2 = 256K 0224 F3/ AB REP STOSW ; Clear dat memory! ; Setup Font Pointers 0226 B7 03 MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127 0228 B8 1130 MOV AX, GET_CHAR_PTR ; Service to Get Pointer 022B CD 10 INT 10h ; Call VGA BIOS 022D 89 2E 0022 R MOV CHARSET_LOW, BP ; Save Char Set Offset 0231 8C 06 0024 R MOV CHARSET_LOW+2, ES ; Save Char Set Segment 0235 B7 04 MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255 0237 B8 1130 MOV AX, GET_CHAR_PTR ; Service to Get Pointer 023A CD 10 INT 10h ; Call VGA BIOS 023C 89 2E 0026 R MOV CHARSET_HI, BP ; Save Char Set Offset 0240 8C 06 0028 R MOV CHARSET_HI+2, ES ; Save Char Set Segment 0244 B8 FFFF MOV AX, True ; Return Success Code 0247 @SVM_EXIT: 0247 83 C4 02 ADD SP, 2 ; Deallocate workspace POPx DI, SI, DS, BP ; Restore Saved Registers 024A 5F 1 POP DI ; Restore R1 024B 5E 2 POP SI ; Restore R1 024C 1F 3 POP DS ; Restore R1 024D 5D 4 POP BP ; Restore R1 024E CA 0008 RET 8 ; Exit & Clean Up Stack 0251 SET_VGA_MODEX ENDP ;================== ;SET_MODEX% (Mode%) ;================== ; ; Quickie Mode Set - Sets Up Mode X to Default Configuration ; ; ENTRY: ModeType = Desired Screen Resolution (0-7) ; (See SET_VGA_MODEX for list) ; ; EXIT: AX = Success Flag: 0 = Failure / -1= Success ; 000A SM_STACK STRUC 0000 0000 0000 DW ?,? ; BP, SI 0004 00000000 DD ? ; Caller 0008 0000 SM_Mode DW ? ; Desired Screen Resolution SM_STACK ENDS PUBLIC SET_MODEX 0251 SET_MODEX PROC FAR PUSHx BP, SI ; Preserve Important registers 0251 55 1 PUSH BP ; Save R1 0252 56 2 PUSH SI ; Save R1 0253 8B EC MOV BP, SP ; Set up Stack Frame CLR AX ; Assume Failure 0255 33 C0 1 XOR AX, AX ; Set Register = 0 0257 8B 5E 08 MOV BX, [BP].SM_Mode ; Get Desired Mode # 025A 83 FB 08 CMP BX, NUM_MODES ; Is it a Valid Mode #? 025D 73 1C JAE @SMX_Exit ; If Not, don't Bother 025F 53 PUSH BX ; Push Mode Parameter 0260 D1 E3 SHL BX, 1 ; Scale BX to word Index 0262 2E: 8B B7 0064 R MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info 0267 2E: FF 74 02 PUSH CS:[SI].M_XSize ; Push Default X Size 026B 2E: FF 74 04 PUSH CS:[SI].M_Ysize ; Push Default Y size 026F 2E: 8A 44 01 MOV AL, CS:[SI].M_Pages ; Get Default # of Pages CLR AH ; Hi Byte = 0 0273 32 E4 1 XOR AH, AH ; Set Register = 0 0275 50 PUSH AX ; Push # Pages 0276 9A ---- 0104 R CALL f SET_VGA_MODEX ; Set up Mode X! 027B @SMX_Exit: POPx SI, BP ; Restore Registers 027B 5E 1 POP SI ; Restore R1 027C 5D 2 POP BP ; Restore R1 027D CA 0002 RET 2 ; Exit & Clean Up Stack 0280 SET_MODEX ENDP ; ===== BASIC GRAPHICS PRIMITIVES ===== ;============================ ;CLEAR_VGA_SCREEN (ColorNum%) ;============================ ; ; Clears the active display page ; ; ENTRY: ColorNum = Color Value to fill the page with ; ; EXIT: No meaningful values returned ; 000A CVS_STACK STRUC 0000 0000 0000 DW ?,? ; DI, BP 0004 00000000 DD ? ; Caller 0008 00 00 CVS_COLOR DB ?,? ; Color to Set Screen to CVS_STACK ENDS PUBLIC CLEAR_VGA_SCREEN 0280 CLEAR_VGA_SCREEN PROC FAR PUSHx BP, DI ; Preserve Important Registers 0280 55 1 PUSH BP ; Save R1 0281 57 2 PUSH DI ; Save R1 0282 8B EC MOV BP, SP ; Set up Stack Frame OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes 0284 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register 0287 B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value 028A EF 1 OUT DX, AX ; Set I/O Register(s) 028B C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 028F 8A 46 08 MOV AL, [BP].CVS_COLOR ; Get Color 0292 8A E0 MOV AH, AL ; Copy for Word Write 0294 FC CLD ; Block fill Forwards 0295 8B 0E 000E R MOV CX, PAGE_SIZE ; Get Size of Page 0299 D1 E9 SHR CX, 1 ; Divide by 2 for Words 029B F3/ AB REP STOSW ; Block Fill VGA memory POPx DI, BP ; Restore Saved Registers 029D 5F 1 POP DI ; Restore R1 029E 5D 2 POP BP ; Restore R1 029F CA 0002 RET 2 ; Exit & Clean Up Stack 02A2 CLEAR_VGA_SCREEN ENDP ;=================================== ;SET_POINT (Xpos%, Ypos%, ColorNum%) ;=================================== ; ; Plots a single Pixel on the active display page ; ; ENTRY: Xpos = X position to plot pixel at ; Ypos = Y position to plot pixel at ; ColorNum = Color to plot pixel with ; ; EXIT: No meaningful values returned ; 000E SP_STACK STRUC 0000 0000 0000 DW ?,? ; BP, DI 0004 00000000 DD ? ; Caller 0008 00 00 SETP_Color DB ?,? ; Color of Point to Plot 000A 0000 SETP_Ypos DW ? ; Y pos of Point to Plot 000C 0000 SETP_Xpos DW ? ; X pos of Point to Plot SP_STACK ENDS PUBLIC SET_POINT 02A2 SET_POINT PROC FAR PUSHx BP, DI ; Preserve Registers 02A2 55 1 PUSH BP ; Save R1 02A3 57 2 PUSH DI ; Save R1 02A4 8B EC MOV BP, SP ; Set up Stack Frame 02A6 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 02AA 8B 46 0A MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel 02AD F7 26 0000 R MUL SCREEN_WIDTH ; Get Offset to Start of Line 02B1 8B 5E 0C MOV BX, [BP].SETP_Xpos ; Get Xpos 02B4 8B CB MOV CX, BX ; Copy to extract Plane # from 02B6 C1 EB 02 SHR BX, 2 ; X offset (Bytes) = Xpos/4 02B9 03 D8 ADD BX, AX ; Offset = Width*Ypos + Xpos/4 02BB B8 0102 MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register 02BE 80 E1 03 AND CL, PLANE_BITS ; Get Plane Bits 02C1 D2 E4 SHL AH, CL ; Get Plane Select Value OUT_16 SC_Index, AX ; Select Plane 02C3 BA 03C4 1 MOV DX, SC_Index ; then Select Register 02C6 EF 1 OUT DX, AX ; Set I/O Register(s) 02C7 8A 46 08 MOV AL,[BP].SETP_Color ; Get Pixel Color 02CA 26: 88 01 MOV ES:[DI+BX], AL ; Draw Pixel POPx DI, BP ; Restore Saved Registers Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 4 - 1 02CD 5F 1 POP DI ; Restore R1 02CE 5D 2 POP BP ; Restore R1 02CF CA 0006 RET 6 ; Exit and Clean up Stack 02D2 SET_POINT ENDP ;========================== ;READ_POINT% (Xpos%, Ypos%) ;========================== ; ; Read the color of a pixel from the Active Display Page ; ; ENTRY: Xpos = X position of pixel to read ; Ypos = Y position of pixel to read ; ; EXIT: AX = Color of Pixel at (Xpos, Ypos) ; 000C RP_STACK STRUC 0000 0000 0000 DW ?,? ; BP, DI 0004 00000000 DD ? ; Caller 0008 0000 RP_Ypos DW ? ; Y pos of Point to Read 000A 0000 RP_Xpos DW ? ; X pos of Point to Read RP_STACK ENDS PUBLIC READ_POINT 02D2 READ_POINT PROC FAR PUSHx BP, DI ; Preserve Registers 02D2 55 1 PUSH BP ; Save R1 02D3 57 2 PUSH DI ; Save R1 02D4 8B EC MOV BP, SP ; Set up Stack Frame 02D6 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 02DA 8B 46 08 MOV AX, [BP].RP_Ypos ; Get Line # of Pixel 02DD F7 26 0000 R MUL SCREEN_WIDTH ; Get Offset to Start of Line 02E1 8B 5E 0A MOV BX, [BP].RP_Xpos ; Get Xpos 02E4 8B CB MOV CX, BX 02E6 C1 EB 02 SHR BX, 2 ; X offset (Bytes) = Xpos/4 02E9 03 D8 ADD BX, AX ; Offset = Width*Ypos + Xpos/4 02EB B0 04 MOV AL, READ_MAP ; GC Read Mask Register 02ED 8A E1 MOV AH, CL ; Get Xpos 02EF 80 E4 03 AND AH, PLANE_BITS ; & mask out Plane # OUT_16 GC_INDEX, AX ; Select Plane to read in 02F2 BA 03CE 1 MOV DX, GC_INDEX ; then Select Register 02F5 EF 1 OUT DX, AX ; Set I/O Register(s) CLR AH ; Clear Return Value Hi byte 02F6 32 E4 1 XOR AH, AH ; Set Register = 0 02F8 26: 8A 01 MOV AL, ES:[DI+BX] ; Get Color of Pixel POPx DI, BP ; Restore Saved Registers 02FB 5F 1 POP DI ; Restore R1 02FC 5D 2 POP BP ; Restore R1 02FD CA 0004 RET 4 ; Exit and Clean up Stack 0300 READ_POINT ENDP ;====================================================== ;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) ;====================================================== ; ; Fills a rectangular block on the active display Page ; ; ENTRY: Xpos1 = Left X position of area to fill ; Ypos1 = Top Y position of area to fill ; Xpos2 = Right X position of area to fill ; Ypos2 = Bottom Y position of area to fill ; ColorNum = Color to fill area with ; ; EXIT: No meaningful values returned ; 0016 FB_STACK STRUC 0000 0000 0000 0000 DW ?x4 ; DS, DI, SI, BP 0000 0008 00000000 DD ? ; Caller 000C 00 00 FB_Color DB ?,? ; Fill Color 000E 0000 FB_Ypos2 DW ? ; Y pos of Lower Right Pixel 0010 0000 FB_Xpos2 DW ? ; X pos of Lower Right Pixel 0012 0000 FB_Ypos1 DW ? ; Y pos of Upper Left Pixel 0014 0000 FB_Xpos1 DW ? ; X pos of Upper Left Pixel FB_STACK ENDS PUBLIC FILL_BLOCK 0300 FILL_BLOCK PROC FAR PUSHx BP, DS, SI, DI ; Preserve Important Registers 0300 55 1 PUSH BP ; Save R1 0301 1E 2 PUSH DS ; Save R1 0302 56 3 PUSH SI ; Save R1 0303 57 4 PUSH DI ; Save R1 0304 8B EC MOV BP, SP ; Set up Stack Frame 0306 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 030A FC CLD ; Direction Flag = Forward OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select 030B BA 03C4 1 MOV DX, SC_INDEX ; then Select Register 030E B0 02 1 MOV AL, MAP_MASK ; then Get Data Value 0310 EE 1 OUT DX, AL ; Set I/O Register ; Validate Pixel Coordinates ; If necessary, Swap so X1 <= X2, Y1 <= Y2 0311 8B 46 12 MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2? 0314 8B 5E 0E MOV BX, [BP].FB_Ypos2 ; BX = Y2 0317 3B C3 CMP AX, BX 0319 7E 04 JLE @FB_NOSWAP1 031B 89 5E 12 MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1 031E 93 XCHG AX, BX ; on stack for future use 031F @FB_NOSWAP1: 031F 2B D8 SUB BX, AX ; Get Y width 0321 43 INC BX ; Add 1 to avoid 0 value 0322 89 5E 0E MOV [BP].FB_Ypos2, BX ; Save in Ypos2 0325 F7 26 0000 R MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line 0329 03 F8 ADD DI, AX ; DI = Start of Line Y1 032B 8B 46 14 MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2 032E 8B 5E 10 MOV BX, [BP].FB_Xpos2 ; 0331 3B C3 CMP AX, BX 0333 7E 04 JLE @FB_NOSWAP2 ; Skip Ahead if Ok 0335 89 46 10 MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2 0338 93 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. 0339 @FB_NOSWAP2: 0339 8B D0 MOV DX, AX ; DX = X1 (Pixel Position) 033B C1 EA 02 SHR DX, 2 ; DX/4 = Bytes into Line 033E 03 FA ADD DI, DX ; DI = Addr of Upper-Left Corner 0340 8B CB MOV CX, BX ; CX = X2 (Pixel Position) 0342 C1 E9 02 SHR CX, 2 ; CX/4 = Bytes into Line 0345 3B D1 CMP DX, CX ; Start and end in same band? 0347 75 03 JNE @FB_NORMAL ; if not, check for l & r edges 0349 E9 0086 JMP @FB_ONE_BAND_ONLY ; if so, then special processing 034C @FB_NORMAL: 034C 2B CA SUB CX, DX ; CX = # bands -1 034E 8B F0 MOV SI, AX ; SI = PLANE#(X1) 0350 83 E6 03 AND SI, PLANE_BITS ; if Left edge is aligned then 0353 74 27 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 0355 BA 03C5 1 MOV DX, SC_Data ; then Select Register 0358 2E: 8A 84 0000 R 1 MOV AL, Left_Clip_Mask[SI] ; then Get Data Value 035D EE 1 OUT DX, AL ; Set I/O Register 035E 8B F7 MOV SI, DI ; SI = Copy of Start Addr (UL) 0360 8B 56 0E MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw 0363 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color 0366 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value 036A @FB_LEFT_LOOP: 036A 26: 88 04 MOV ES:[SI], AL ; Fill in Left Edge Pixels 036D 03 F3 ADD SI, BX ; Point to Next Line (Below) LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn 036F 4A 1 DEC DX ; Counter-- 0370 74 08 1 JZ @FB_LEFT_CONT ; Jump if 0 0372 26: 88 04 MOV ES:[SI], AL ; Fill in Left Edge Pixels 0375 03 F3 ADD SI, BX ; Point to Next Line (Below) LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn 0377 4A 1 DEC DX ; Counter-- 0378 75 F0 1 JNZ @FB_LEFT_LOOP ; Jump if not 0 037A @FB_LEFT_CONT: 037A 47 INC DI ; Point to Middle (or Right) Block 037B 49 DEC CX ; Reset CX instead of JMP @FB_RIGHT 037C @FB_L_PLANE_FLUSH: 037C 41 INC CX ; Add in Left band to middle block ; DI = Addr of 1st middle Pixel (band) to fill ; CX = # of Bands to fill -1 037D @FB_RIGHT: 037D 8B 76 10 MOV SI, [BP].FB_Xpos2 ; Get Xpos2 0380 83 E6 03 AND SI, PLANE_BITS ; Get Plane values 0383 83 FE 03 CMP SI, 0003 ; Plane = 3? 0386 74 2B 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 0388 BA 03C5 1 MOV DX, SC_Data ; then Select Register 038B 2E: 8A 84 0004 R 1 MOV AL, Right_Clip_Mask[SI] ; then Get Data Value 0390 EE 1 OUT DX, AL ; Set I/O Register 0391 8B F7 MOV SI, DI ; Get Addr of Left Edge 0393 03 F1 ADD SI, CX ; Add Width-1 (Bands) 0395 4E DEC SI ; To point to top of Right Edge 0396 8B 56 0E MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw 0399 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color 039C 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value 03A0 @FB_RIGHT_LOOP: 03A0 26: 88 04 MOV ES:[SI], AL ; Fill in Right Edge Pixels 03A3 03 F3 ADD SI, BX ; Point to Next Line (Below) LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn 03A5 4A 1 DEC DX ; Counter-- 03A6 74 08 1 JZ @FB_RIGHT_CONT ; Jump if 0 03A8 26: 88 04 MOV ES:[SI], AL ; Fill in Right Edge Pixels 03AB 03 F3 ADD SI, BX ; Point to Next Line (Below) LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn 03AD 4A 1 DEC DX ; Counter-- 03AE 75 F0 1 JNZ @FB_RIGHT_LOOP ; Jump if not 0 03B0 @FB_RIGHT_CONT: 03B0 49 DEC CX ; Minus 1 for Middle bands 03B1 74 51 JZ @FB_EXIT ; Uh.. no Middle bands... 03B3 @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 03B3 BA 03C5 1 MOV DX, SC_Data ; then Select Register 03B6 B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value 03B8 EE 1 OUT DX, AL ; Set I/O Register 03B9 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = DI Increment 03BD 2B D1 SUB DX, CX ; = Screen_Width-# Planes Filled 03BF 8B D9 MOV BX, CX ; BX = Quick Refill for CX 03C1 8B 76 0E MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill 03C4 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 5 - 1 03C7 @FB_MIDDLE_LOOP: 03C7 F3/ AA REP STOSB ; Fill in entire line 03C9 8B CB MOV CX, BX ; Recharge CX (Line Width) 03CB 03 FA ADD DI, DX ; Point to start of Next Line LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn 03CD 4E 1 DEC SI ; Counter-- 03CE 75 F7 1 JNZ @FB_MIDDLE_LOOP ; Jump if not 0 03D0 EB 32 JMP s @FB_EXIT ; Outa here 03D2 @FB_ONE_BAND_ONLY: 03D2 8B F0 MOV SI, AX ; Get Left Clip Mask, Save X1 03D4 83 E6 03 AND SI, PLANE_BITS ; Mask out Row # 03D7 2E: 8A 84 0000 R MOV AL, Left_Clip_Mask[SI] ; Get Left Edge Mask 03DC 8B F3 MOV SI, BX ; Get Right Clip Mask, Save X2 03DE 83 E6 03 AND SI, PLANE_BITS ; Mask out Row # 03E1 2E: 22 84 0004 R AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte OUT_8 SC_Data, AL ; Clip For Left & Right Masks 03E6 BA 03C5 1 MOV DX, SC_Data ; then Select Register 03E9 EE 1 OUT DX, AL ; Set I/O Register 03EA 8B 4E 0E MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw 03ED 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color 03F0 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value 03F4 @FB_ONE_LOOP: 03F4 26: 88 05 MOV ES:[DI], AL ; Fill in Pixels 03F7 03 FB ADD DI, BX ; Point to Next Line (Below) LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn 03F9 49 1 DEC CX ; Counter-- 03FA 74 08 1 JZ @FB_EXIT ; Jump if 0 03FC 26: 88 05 MOV ES:[DI], AL ; Fill in Pixels 03FF 03 FB ADD DI, BX ; Point to Next Line (Below) LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn 0401 49 1 DEC CX ; Counter-- 0402 75 F0 1 JNZ @FB_ONE_LOOP ; Jump if not 0 0404 @FB_EXIT: POPx DI, SI, DS, BP ; Restore Saved Registers 0404 5F 1 POP DI ; Restore R1 0405 5E 2 POP SI ; Restore R1 0406 1F 3 POP DS ; Restore R1 0407 5D 4 POP BP ; Restore R1 0408 CA 000A RET 10 ; Exit and Clean up Stack 040B FILL_BLOCK ENDP ;===================================================== ;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) ;===================================================== ; ; Draws a Line on the active display page ; ; ENTRY: Xpos1 = X position of first point on line ; Ypos1 = Y position of first point on line ; Xpos2 = X position of last point on line ; Ypos2 = Y position of last point on line ; ColorNum = Color to draw line with ; ; EXIT: No meaningful values returned ; 0014 DL_STACK STRUC 0000 0000 0000 0000 DW ?x3 ; DI, SI, BP 0006 00000000 DD ? ; Caller 000A 00 00 DL_ColorF DB ?,? ; Line Draw Color 000C 0000 DL_Ypos2 DW ? ; Y pos of last point 000E 0000 DL_Xpos2 DW ? ; X pos of last point 0010 0000 DL_Ypos1 DW ? ; Y pos of first point 0012 0000 DL_Xpos1 DW ? ; X pos of first point DL_STACK ENDS PUBLIC DRAW_LINE 040B DRAW_LINE PROC FAR PUSHx BP, SI, DI ; Preserve Important Registers 040B 55 1 PUSH BP ; Save R1 040C 56 2 PUSH SI ; Save R1 040D 57 3 PUSH DI ; Save R1 040E 8B EC MOV BP, SP ; Set up Stack Frame 0410 FC CLD ; Direction Flag = Forward OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select 0411 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register 0414 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value 0416 EE 1 OUT DX, AL ; Set I/O Register 0417 8A 6E 0A MOV CH, [BP].DL_ColorF ; Save Line Color in CH ; Check Line Type 041A 8B 76 12 MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2? 041D 8B 7E 0E MOV DI, [BP].DL_Xpos2 ; DX = X2 0420 3B F7 CMP SI, DI ; Is X1 < X2 0422 74 5D JE @DL_VLINE ; If X1=X2, Draw Vertical Line 0424 7C 02 JL @DL_NOSWAP1 ; If X1 < X2, don't swap 0426 87 F7 XCHG SI, DI ; X2 IS > X1, SO SWAP THEM 0428 @DL_NOSWAP1: ; SI = X1, DI = X2 0428 8B 46 10 MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2? 042B 3B 46 0C CMP AX, [BP].DL_Ypos2 ; Y1 = Y2? 042E 74 03 JE @DL_HORZ ; If so, Draw a Horizontal Line 0430 E9 0094 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 0433 @DL_HORZ: 0433 F7 26 0000 R MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width 0437 8B D0 MOV DX, AX ; CX = Line offset into Page 0439 8B C6 MOV AX, SI ; Get Left edge, Save X1 043B 83 E6 03 AND SI, PLANE_BITS ; Mask out Row # 043E 2E: 8A 9C 0000 R MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask 0443 8B CF MOV CX, DI ; Get Right edge, Save X2 0445 83 E7 03 AND DI, PLANE_BITS ; Mask out Row # 0448 2E: 8A BD 0004 R MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte 044D C1 E8 02 SHR AX, 2 ; Get X1 Byte # (=X1/4) 0450 C1 E9 02 SHR CX, 2 ; Get X2 Byte # (=X2/4) 0453 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 0457 03 FA ADD DI, DX ; Point to Start of Line 0459 03 F8 ADD DI, AX ; Point to Pixel X1 045B 2B C8 SUB CX, AX ; CX = # Of Bands (-1) to set 045D 75 02 JNZ @DL_LONGLN ; jump if longer than one segment 045F 22 DF AND BL, BH ; otherwise, merge clip masks 0461 @DL_LONGLN: OUT_8 SC_Data, BL ; Set the Left Clip Mask 0461 BA 03C5 1 MOV DX, SC_Data ; then Select Register 0464 8A C3 1 MOV AL, BL ; then Get Data Value 0466 EE 1 OUT DX, AL ; Set I/O Register 0467 8A 46 0A MOV AL, [BP].DL_ColorF ; Get Line Color 046A 8A D8 MOV BL, AL ; BL = Copy of Line Color 046C AA STOSB ; Set Left (1-4) Pixels 046D E3 55 JCXZ @DL_EXIT ; Done if only one Line Segment 046F 49 DEC CX ; CX = # of Middle Segments 0470 74 07 JZ @DL_XRSEG ; If no middle segments.... ; Draw Middle Segments OUT_8 DX, ALL_PLANES ; Write to ALL Planes 0472 B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value 0474 EE 1 OUT DX, AL ; Set I/O Register 0475 8A C3 MOV AL, BL ; Get Color from BL 0477 F3/ AA REP STOSB ; Draw Middle (4 Pixel) Segments 0479 @DL_XRSEG: OUT_8 DX, BH ; Select Planes for Right Clip Mask 0479 8A C7 1 MOV AL, BH ; then Get Data Value 047B EE 1 OUT DX, AL ; Set I/O Register 047C 8A C3 MOV AL, BL ; Get Color Value 047E AA STOSB ; Draw Right (1-4) Pixels 047F EB 43 JMP s @DL_EXIT ; We Are Done... ; This Code Draws A Vertical Line. On entry: ; CH = Line Color, SI & DI = X1 0481 @DL_VLINE: 0481 8B 46 10 MOV AX, [BP].DL_Ypos1 ; AX = Y1 0484 8B 76 0C MOV SI, [BP].DL_Ypos2 ; SI = Y2 0487 3B C6 CMP AX, SI ; Is Y1 < Y2? 0489 7E 01 JLE @DL_NOSWAP2 ; if so, Don't Swap them 048B 96 XCHG AX, SI ; Ok, NOW Y1 < Y2 048C @DL_NOSWAP2: 048C 2B F0 SUB SI, AX ; SI = Line Height (Y2-Y1+1) 048E 46 INC SI ; AX = Y1, DI = X1, Get offset into Page into AX 048F F7 26 0000 R MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width 0493 8B D7 MOV DX, DI ; Copy Xpos into DX 0495 C1 EF 02 SHR DI, 2 ; DI = Xpos/4 0498 03 C7 ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1 049A C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 049E 03 F8 ADD DI, AX ; Point to Pixel X1, Y1 ;Select Plane 04A0 8A CA MOV CL, DL ; CL = Save X1 04A2 80 E1 03 AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #) 04A5 B8 0102 MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1 04A8 D2 E4 SHL AH, CL ; Change to Correct Plane # OUT_16 SC_Index, AX ; Select Plane 04AA BA 03C4 1 MOV DX, SC_Index ; then Select Register 04AD EF 1 OUT DX, AX ; Set I/O Register(s) 04AE 8A C5 MOV AL, CH ; Get Saved Color 04B0 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By 04B4 @DL_VLoop: 04B4 26: 88 05 MOV ES:[DI], AL ; Draw Single Pixel 04B7 03 FB ADD DI, BX ; Point to Next Line LOOPjz SI, @DL_EXIT ; Lines--, Exit if done 04B9 4E 1 DEC SI ; Counter-- 04BA 74 08 1 JZ @DL_EXIT ; Jump if 0 04BC 26: 88 05 MOV ES:[DI], AL ; Draw Single Pixel 04BF 03 FB ADD DI, BX ; Point to Next Line LOOPx SI, @DL_VLoop ; Lines--, Loop until Done 04C1 4E 1 DEC SI ; Counter-- 04C2 75 F0 1 JNZ @DL_VLoop ; Jump if not 0 04C4 @DL_EXIT: 04C4 E9 0157 JMP @DL_EXIT2 ; Done! ; This code Draws a diagonal line in Mode X 04C7 @DL_BREZHAM: 04C7 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 04CB 8B 46 10 MOV AX, [BP].DL_Ypos1 ; get Y1 value 04CE 8B 5E 0C MOV BX, [BP].DL_Ypos2 ; get Y2 value 04D1 8B 4E 12 MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos 04D4 3B D8 CMP BX, AX ; Y2-Y1 is? 04D6 73 04 JNC @DL_DeltaYOK ; if Y2>=Y1 then goto... 04D8 93 XCHG BX, AX ; Swap em... 04D9 8B 4E 0E MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos 04DC @DL_DeltaYOK: 04DC F7 26 0000 R MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1 Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 6 - 1 04E0 03 F8 ADD DI, AX ; DI -> Start of Line Y1 on Page 04E2 8B C1 MOV AX, CX ; AX = Xpos (X1) 04E4 C1 E8 02 SHR AX, 2 ; /4 = Byte Offset into Line 04E7 03 F8 ADD DI, AX ; DI = Starting pos (X1,Y1) 04E9 B0 11 MOV AL, 11h ; Staring Mask 04EB 80 E1 03 AND CL, PLANE_BITS ; Get Plane # 04EE D2 E0 SHL AL, CL ; and shift into place 04F0 8A 66 0A MOV AH, [BP].DL_ColorF ; Color in Hi Bytes 04F3 50 PUSH AX ; Save Mask,Color... 04F4 8A E0 MOV AH, AL ; Plane # in AH 04F6 B0 02 MOV AL, MAP_MASK ; Select Plane Register OUT_16 SC_Index, AX ; Select initial plane 04F8 BA 03C4 1 MOV DX, SC_Index ; then Select Register 04FB EF 1 OUT DX, AX ; Set I/O Register(s) 04FC 8B 46 12 MOV AX, [BP].DL_Xpos1 ; get X1 value 04FF 8B 5E 10 MOV BX, [BP].DL_Ypos1 ; get Y1 value 0502 8B 4E 0E MOV CX, [BP].DL_Xpos2 ; get X2 value 0505 8B 56 0C MOV DX, [BP].DL_Ypos2 ; get Y2 value 0508 8B 2E 0000 R MOV BP, SCREEN_WIDTH ; Use BP for Line width to ; to avoid extra memory access 050C 2B D3 SUB DX, BX ; figure Delta_Y 050E 73 05 JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1 0510 03 DA ADD BX, DX ; put Y2 into Y1 0512 F7 DA NEG DX ; abs(Delta_Y) 0514 91 XCHG AX, CX ; and exchange X1 and X2 0515 @DL_DeltaYOK2: 0515 BB 8000 MOV BX, 08000H ; seed for fraction accumulator 0518 2B C8 SUB CX, AX ; figure Delta_X 051A 72 03 JC @DL_DrawLeft ; if negative, go left 051C E9 0084 JMP @DL_DrawRight ; Draw Line that slopes right 051F @DL_DrawLeft: 051F F7 D9 NEG CX ; abs(Delta_X) 0521 3B CA CMP CX, DX ; is Delta_X < Delta_Y? 0523 72 41 JB @DL_SteepLeft ; yes, so go do steep line ; (Delta_Y iterations) ; Draw a Shallow line to the left in Mode X 0525 @DL_ShallowLeft: CLR AX ; zero low word of Delta_Y * 10000h 0525 33 C0 1 XOR AX, AX ; Set Register = 0 0527 2B C2 SUB AX, DX ; DX:AX <- DX * 0FFFFh 0529 83 DA 00 SBB DX, 0 ; include carry 052C F7 F1 DIV CX ; divide by Delta_X 052E 8B F3 MOV SI, BX ; SI = Accumulator 0530 8B D8 MOV BX, AX ; BX = Add fraction 0532 58 POP AX ; Get Color, Bit mask 0533 BA 03C5 MOV DX, SC_Data ; Sequence controller data register 0536 41 INC CX ; Inc Delta_X so we can unroll loop ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down... 0537 @DL_SLLLoop: 0537 26: 88 25 MOV ES:[DI], AH ; set first pixel, plane data set up LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done 053A 49 1 DEC CX ; Counter-- 053B 74 26 1 JZ @DL_SLLExit ; Jump if 0 053D 03 F3 ADD SI, BX ; add numerator to accumulator 053F 73 02 JNC @DL_SLLL2nc ; move down on carry 0541 03 FD ADD DI, BP ; Move Down one line... 0543 @DL_SLLL2nc: 0543 4F DEC DI ; Left one addr 0544 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2 0546 3C 87 CMP AL, 87h ; wrap?, if AL <88 then Carry set 0548 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry 054B EE OUT DX, AL ; Set up New Bit Plane mask 054C 26: 88 25 MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done 054F 49 1 DEC CX ; Counter-- 0550 74 11 1 JZ @DL_SLLExit ; Jump if 0 0552 03 F3 ADD SI, BX ; add numerator to accumulator, 0554 73 02 JNC @DL_SLLL3nc ; move down on carry 0556 03 FD ADD DI, BP ; Move Down one line... 0558 @DL_SLLL3nc: ; Now move left a pixel... 0558 4F DEC DI ; Left one addr 0559 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2 055B 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set 055D 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry 0560 EE OUT DX, AL ; Set up New Bit Plane mask 0561 EB D4 JMP s @DL_SLLLoop ; loop until done 0563 @DL_SLLExit: 0563 E9 00B8 JMP @DL_EXIT2 ; and exit ; Draw a steep line to the left in Mode X 0566 @DL_SteepLeft: CLR AX ; zero low word of Delta_Y * 10000h 0566 33 C0 1 XOR AX, AX ; Set Register = 0 0568 87 D1 XCHG DX, CX ; Delta_Y switched with Delta_X 056A F7 F1 DIV CX ; divide by Delta_Y 056C 8B F3 MOV SI, BX ; SI = Accumulator 056E 8B D8 MOV BX, AX ; BX = Add Fraction 0570 58 POP AX ; Get Color, Bit mask 0571 BA 03C5 MOV DX, SC_Data ; Sequence controller data register 0574 41 INC CX ; Inc Delta_Y so we can unroll loop ; Loop (x2) to Draw Pixels, Move Down, and Maybe left 0575 @DL_STLLoop: 0575 26: 88 25 MOV ES:[DI], AH ; set first pixel LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done 0578 49 1 DEC CX ; Counter-- 0579 74 26 1 JZ @DL_STLExit ; Jump if 0 057B 03 F3 ADD SI, BX ; add numerator to accumulator 057D 73 09 JNC @DL_STLnc2 ; No carry, just move down! 057F 4F DEC DI ; Move Left one addr 0580 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2 0582 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set 0584 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry 0587 EE OUT DX, AL ; Set up New Bit Plane mask 0588 @DL_STLnc2: 0588 03 FD ADD DI, BP ; advance to next line. 058A 26: 88 25 MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done 058D 49 1 DEC CX ; Counter-- 058E 74 11 1 JZ @DL_STLExit ; Jump if 0 0590 03 F3 ADD SI, BX ; add numerator to accumulator 0592 73 09 JNC @DL_STLnc3 ; No carry, just move down! 0594 4F DEC DI ; Move Left one addr 0595 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2 0597 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set 0599 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry 059C EE OUT DX, AL ; Set up New Bit Plane mask 059D @DL_STLnc3: 059D 03 FD ADD DI, BP ; advance to next line. 059F EB D4 JMP s @DL_STLLoop ; Loop until done 05A1 @DL_STLExit: 05A1 EB 7B JMP @DL_EXIT2 ; and exit ; Draw a line that goes to the Right... 05A3 @DL_DrawRight: 05A3 3B CA CMP CX, DX ; is Delta_X < Delta_Y? 05A5 72 3E JB @DL_SteepRight ; yes, so go do steep line ; (Delta_Y iterations) ; Draw a Shallow line to the Right in Mode X 05A7 @DL_ShallowRight: CLR AX ; zero low word of Delta_Y * 10000h 05A7 33 C0 1 XOR AX, AX ; Set Register = 0 05A9 2B C2 SUB AX, DX ; DX:AX <- DX * 0FFFFh 05AB 83 DA 00 SBB DX, 0 ; include carry 05AE F7 F1 DIV CX ; divide by Delta_X 05B0 8B F3 MOV SI, BX ; SI = Accumulator 05B2 8B D8 MOV BX, AX ; BX = Add Fraction 05B4 58 POP AX ; Get Color, Bit mask 05B5 BA 03C5 MOV DX, SC_Data ; Sequence controller data register 05B8 41 INC CX ; Inc Delta_X so we can unroll loop ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down... 05B9 @DL_SLRLoop: 05B9 26: 88 25 MOV ES:[DI], AH ; set first pixel, mask is set up LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. 05BC 49 1 DEC CX ; Counter-- 05BD 74 24 1 JZ @DL_SLRExit ; Jump if 0 05BF 03 F3 ADD SI, BX ; add numerator to accumulator 05C1 73 02 JNC @DL_SLR2nc ; don't move down if carry not set 05C3 03 FD ADD DI, BP ; Move Down one line... 05C5 @DL_SLR2nc: ; Now move right a pixel... 05C5 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0 05C7 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set 05C9 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry 05CC EE OUT DX, AL ; Set up New Bit Plane mask 05CD 26: 88 25 MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done.. 05D0 49 1 DEC CX ; Counter-- 05D1 74 10 1 JZ @DL_SLRExit ; Jump if 0 05D3 03 F3 ADD SI, BX ; add numerator to accumulator 05D5 73 02 JNC @DL_SLR3nc ; don't move down if carry not set 05D7 03 FD ADD DI, BP ; Move Down one line... 05D9 @DL_SLR3nc: 05D9 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0 05DB 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set 05DD 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry 05E0 EE OUT DX, AL ; Set up New Bit Plane mask 05E1 EB D6 JMP s @DL_SLRLoop ; loop till done 05E3 @DL_SLRExit: 05E3 EB 39 JMP @DL_EXIT2 ; and exit ; Draw a Steep line to the Right in Mode X 05E5 @DL_SteepRight: CLR AX ; zero low word of Delta_Y * 10000h 05E5 33 C0 1 XOR AX, AX ; Set Register = 0 05E7 87 D1 XCHG DX, CX ; Delta_Y switched with Delta_X 05E9 F7 F1 DIV CX ; divide by Delta_Y 05EB 8B F3 MOV SI, BX ; SI = Accumulator 05ED 8B D8 MOV BX, AX ; BX = Add Fraction 05EF 58 POP AX ; Get Color, Bit mask 05F0 BA 03C5 MOV DX, SC_Data ; Sequence controller data register 05F3 41 INC CX ; Inc Delta_Y so we can unroll loop ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right 05F4 @STRLoop: 05F4 26: 88 25 MOV ES:[DI], AH ; set first pixel, mask is set up LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done 05F7 49 1 DEC CX ; Counter-- 05F8 74 24 1 JZ @DL_EXIT2 ; Jump if 0 05FA 03 F3 ADD SI, BX ; add numerator to accumulator 05FC 73 08 JNC @STRnc2 ; if no carry then just go down... 05FE D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0 0600 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set 0602 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry 0605 EE OUT DX, AL ; Set up New Bit Plane mask Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 7 - 1 0606 @STRnc2: 0606 03 FD ADD DI, BP ; advance to next line. 0608 26: 88 25 MOV ES:[DI], AH ; set pixel LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done 060B 49 1 DEC CX ; Counter-- 060C 74 10 1 JZ @DL_EXIT2 ; Jump if 0 060E 03 F3 ADD SI, BX ; add numerator to accumulator 0610 73 08 JNC @STRnc3 ; if no carry then just go down... 0612 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0 0614 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set 0616 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry 0619 EE OUT DX, AL ; Set up New Bit Plane mask 061A @STRnc3: 061A 03 FD ADD DI, BP ; advance to next line. 061C EB D6 JMP s @STRLoop ; loop till done 061E @DL_EXIT2: POPx DI, SI, BP ; Restore Saved Registers 061E 5F 1 POP DI ; Restore R1 061F 5E 2 POP SI ; Restore R1 0620 5D 3 POP BP ; Restore R1 0621 CA 000A RET 10 ; Exit and Clean up Stack 0624 DRAW_LINE ENDP ; ===== DAC COLOR REGISTER ROUTINES ===== ;================================================= ;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%) ;================================================= ; ; Sets a single (RGB) Vga Palette Register ; ; ENTRY: Register = The DAC # to modify (0-255) ; Red = The new Red Intensity (0-63) ; Green = The new Green Intensity (0-63) ; Blue = The new Blue Intensity (0-63) ; ; EXIT: No meaningful values returned ; 000E SDR_STACK STRUC 0000 0000 DW ? ; BP 0002 00000000 DD ? ; Caller 0006 00 00 SDR_Blue DB ?,? ; Blue Data Value 0008 00 00 SDR_Green DB ?,? ; Green Data Value 000A 00 00 SDR_Red DB ?,? ; Red Data Value 000C 00 00 SDR_Register DB ?,? ; Palette Register # SDR_STACK ENDS PUBLIC SET_DAC_REGISTER 0624 SET_DAC_REGISTER PROC FAR 0624 55 PUSH BP ; Save BP 0625 8B EC MOV BP, SP ; Set up Stack Frame ; Select which DAC Register to modify OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register 0627 BA 03C8 1 MOV DX, DAC_WRITE_ADDR ; then Select Register 062A 8A 46 0C 1 MOV AL, [BP].SDR_Register ; then Get Data Value 062D EE 1 OUT DX, AL ; Set I/O Register 062E BA 03C9 MOV DX, PEL_DATA_REG ; Dac Data Register OUT_8 DX, [BP].SDR_Red ; Set Red Intensity 0631 8A 46 0A 1 MOV AL, [BP].SDR_Red ; then Get Data Value 0634 EE 1 OUT DX, AL ; Set I/O Register OUT_8 DX, [BP].SDR_Green ; Set Green Intensity 0635 8A 46 08 1 MOV AL, [BP].SDR_Green ; then Get Data Value 0638 EE 1 OUT DX, AL ; Set I/O Register OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity 0639 8A 46 06 1 MOV AL, [BP].SDR_Blue ; then Get Data Value 063C EE 1 OUT DX, AL ; Set I/O Register 063D 5D POP BP ; Restore Registers 063E CA 0008 RET 8 ; Exit & Clean Up Stack 0641 SET_DAC_REGISTER ENDP ;==================================================== ;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%) ;==================================================== ; ; Reads the RGB Values of a single Vga Palette Register ; ; ENTRY: Register = The DAC # to read (0-255) ; Red = Offset to Red Variable in DS ; Green = Offset to Green Variable in DS ; Blue = Offset to Blue Variable in DS ; ; EXIT: The values of the integer variables Red, ; Green, and Blue are set to the values ; taken from the specified DAC register. ; 000E GDR_STACK STRUC 0000 0000 DW ? ; BP 0002 00000000 DD ? ; Caller 0006 0000 GDR_Blue DW ? ; Addr of Blue Data Value in DS 0008 0000 GDR_Green DW ? ; Addr of Green Data Value in DS 000A 0000 GDR_Red DW ? ; Addr of Red Data Value in DS 000C 00 00 GDR_Register DB ?,? ; Palette Register # GDR_STACK ENDS PUBLIC GET_DAC_REGISTER 0641 GET_DAC_REGISTER PROC FAR 0641 55 PUSH BP ; Save BP 0642 8B EC MOV BP, SP ; Set up Stack Frame ; Select which DAC Register to read in OUT_8 DAC_READ_ADDR, [BP].GDR_Register 0644 BA 03C7 1 MOV DX, DAC_READ_ADDR ; then Select Register 0647 8A 46 0C 1 MOV AL, [BP].GDR_Register ; then Get Data Value 064A EE 1 OUT DX, AL ; Set I/O Register 064B BA 03C9 MOV DX, PEL_DATA_REG ; Dac Data Register CLR AX ; Clear AX 064E 33 C0 1 XOR AX, AX ; Set Register = 0 0650 EC IN AL, DX ; Read Red Value 0651 8B 5E 0A MOV BX, [BP].GDR_Red ; Get Address of Red% 0654 89 07 MOV [BX], AX ; *Red% = AX 0656 EC IN AL, DX ; Read Green Value 0657 8B 5E 08 MOV BX, [BP].GDR_Green ; Get Address of Green% 065A 89 07 MOV [BX], AX ; *Green% = AX 065C EC IN AL, DX ; Read Blue Value 065D 8B 5E 06 MOV BX, [BP].GDR_Blue ; Get Address of Blue% 0660 89 07 MOV [BX], AX ; *Blue% = AX 0662 5D POP BP ; Restore Registers 0663 CA 0008 RET 8 ; Exit & Clean Up Stack 0666 GET_DAC_REGISTER ENDP ;=========================================================== ;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%) ;=========================================================== ; ; Sets a Block of Vga Palette Registers ; ; ENTRY: PalData = Far Pointer to Block of palette data ; StartReg = First Register # in range to set (0-255) ; EndReg = Last Register # in Range to set (0-255) ; Sync = Wait for Vertical Retrace Flag (Boolean) ; ; EXIT: No meaningful values returned ; ; NOTES: PalData is a linear array of 3 byte Palette values ; in the order: Red (0-63), Green (0-63), Blue (0-63) ; 0014 LDR_STACK STRUC 0000 0000 0000 0000 DW ?x3 ; BP, DS, SI 0006 00000000 DD ? ; Caller 000A 0000 LDR_Sync DW ? ; Vertical Sync Flag 000C 00 00 LDR_EndReg DB ?,? ; Last Register # 000E 00 00 LDR_StartReg DB ?,? ; First Register # 0010 00000000 LDR_PalData DD ? ; Far Ptr to Palette Data LDR_STACK ENDS PUBLIC LOAD_DAC_REGISTERS 0666 LOAD_DAC_REGISTERS PROC FAR PUSHx BP, DS, SI ; Save Registers 0666 55 1 PUSH BP ; Save R1 0667 1E 2 PUSH DS ; Save R1 0668 56 3 PUSH SI ; Save R1 0669 8B EC mov BP, SP ; Set up Stack Frame 066B 8B 46 0A mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag 066E 0B C0 or AX, AX ; is Sync Flag = 0? 0670 74 05 jz @LDR_Load ; if so, skip call 0672 9A ---- 0795 R call f SYNC_DISPLAY ; wait for vsync ; Determine register #'s, size to copy, etc 0677 @LDR_Load: 0677 C5 76 10 lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data 067A BA 03C8 mov DX, DAC_WRITE_ADDR ; DAC register # selector CLR AX, BX ; Clear for byte loads 067D 33 C0 1 XOR AX, AX ; Set Register = 0 067F 33 DB 2 XOR BX, BX ; Set Register = 0 0681 8A 46 0E mov AL, [BP].LDR_StartReg ; Get Start Register 0684 8A 5E 0C mov BL, [BP].LDR_EndReg ; Get End Register 0687 2B D8 sub BX, AX ; BX = # of DAC registers -1 0689 43 inc BX ; BX = # of DAC registers 068A 8B CB mov CX, BX ; CX = # of DAC registers 068C 03 CB add CX, BX ; CX = " " * 2 068E 03 CB add CX, BX ; CX = " " * 3 0690 FC cld ; Block OUTs forward 0691 EE out DX, AL ; set up correct register # ; Load a block of DAC Registers 0692 BA 03C9 mov DX, PEL_DATA_REG ; Dac Data Register 0695 F3/ 6E rep outsb ; block set DAC registers POPx SI, DS, BP ; Restore Registers 0697 5E 1 POP SI ; Restore R1 0698 1F 2 POP DS ; Restore R1 0699 5D 3 POP BP ; Restore R1 069A CA 000A ret 10 ; Exit & Clean Up Stack 069D LOAD_DAC_REGISTERS ENDP ;==================================================== ;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%) ;==================================================== ; ; Reads a Block of Vga Palette Registers ; ; ENTRY: PalData = Far Pointer to block to store palette data ; StartReg = First Register # in range to read (0-255) ; EndReg = Last Register # in Range to read (0-255) ; ; EXIT: No meaningful values returned ; ; NOTES: PalData is a linear array of 3 byte Palette values ; in the order: Red (0-63), Green (0-63), Blue (0-63) ; 0012 RDR_STACK STRUC 0000 0000 0000 0000 DW ?x3 ; BP, ES, DI 0006 00000000 DD ? ; Caller 000A 00 00 RDR_EndReg DB ?,? ; Last Register # 000C 00 00 RDR_StartReg DB ?,? ; First Register # 000E 00000000 RDR_PalData DD ? ; Far Ptr to Palette Data RDR_STACK ENDS PUBLIC READ_DAC_REGISTERS Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 8 - 1 069D READ_DAC_REGISTERS PROC FAR PUSHx BP, ES, DI ; Save Registers 069D 55 1 PUSH BP ; Save R1 069E 06 2 PUSH ES ; Save R1 069F 57 3 PUSH DI ; Save R1 06A0 8B EC mov BP, SP ; Set up Stack Frame ; Determine register #'s, size to copy, etc 06A2 C4 7E 0E les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer 06A5 BA 03C7 mov DX, DAC_READ_ADDR ; DAC register # selector CLR AX, BX ; Clear for byte loads 06A8 33 C0 1 XOR AX, AX ; Set Register = 0 06AA 33 DB 2 XOR BX, BX ; Set Register = 0 06AC 8A 46 0C mov AL, [BP].RDR_StartReg ; Get Start Register 06AF 8A 5E 0A mov BL, [BP].RDR_EndReg ; Get End Register 06B2 2B D8 sub BX, AX ; BX = # of DAC registers -1 06B4 43 inc BX ; BX = # of DAC registers 06B5 8B CB mov CX, BX ; CX = # of DAC registers 06B7 03 CB add CX, BX ; CX = " " * 2 06B9 03 CB add CX, BX ; CX = " " * 3 06BB FC cld ; Block INs forward ; Read a block of DAC Registers 06BC EE out DX, AL ; set up correct register # 06BD BA 03C9 mov DX, PEL_DATA_REG ; Dac Data Register 06C0 F3/ 6C rep insb ; block read DAC registers POPx DI, ES, BP ; Restore Registers 06C2 5F 1 POP DI ; Restore R1 06C3 07 2 POP ES ; Restore R1 06C4 5D 3 POP BP ; Restore R1 06C5 CA 0008 ret 8 ; Exit & Clean Up Stack 06C8 READ_DAC_REGISTERS ENDP ; ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== ;========================= ;SET_ACTIVE_PAGE (PageNo%) ;========================= ; ; Sets the active display Page to be used for future drawing ; ; ENTRY: PageNo = Display Page to make active ; (values: 0 to Number of Pages - 1) ; ; EXIT: No meaningful values returned ; 0008 SAP_STACK STRUC 0000 0000 DW ? ; BP 0002 00000000 DD ? ; Caller 0006 0000 SAP_Page DW ? ; Page # for Drawing SAP_STACK ENDS PUBLIC SET_ACTIVE_PAGE 06C8 SET_ACTIVE_PAGE PROC FAR 06C8 55 PUSH BP ; Preserve Registers 06C9 8B EC MOV BP, SP ; Set up Stack Frame 06CB 8B 5E 06 MOV BX, [BP].SAP_Page ; Get Desired Page # 06CE 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid? 06D2 73 0D JAE @SAP_Exit ; IF Not, Do Nothing 06D4 89 1E 0012 R MOV ACTIVE_PAGE, BX ; Set Active Page # 06D8 D1 E3 SHL BX, 1 ; Scale Page # to Word 06DA 8B 87 0006 R MOV AX, PAGE_ADDR[BX] ; Get offset to Page 06DE A3 0014 R MOV CURRENT_PAGE, AX ; And set for future LES's 06E1 @SAP_Exit: 06E1 5D POP BP ; Restore Registers 06E2 CA 0002 RET 2 ; Exit and Clean up Stack 06E5 SET_ACTIVE_PAGE ENDP ;================ ;GET_ACTIVE_PAGE% ;================ ; ; Returns the Video Page # currently used for Drawing ; ; ENTRY: No Parameters are passed ; ; EXIT: AX = Current Video Page used for Drawing ; PUBLIC GET_ACTIVE_PAGE 06E5 GET_ACTIVE_PAGE PROC FAR 06E5 A1 0012 R MOV AX, ACTIVE_PAGE ; Get Active Page # 06E8 CB RET ; Exit and Clean up Stack 06E9 GET_ACTIVE_PAGE ENDP ;=============================== ;SET_DISPLAY_PAGE (DisplayPage%) ;=============================== ; ; Sets the currently visible display page. ; When called this routine syncronizes the display ; to the vertical blank. ; ; ENTRY: PageNo = Display Page to show on the screen ; (values: 0 to Number of Pages - 1) ; ; EXIT: No meaningful values returned ; 0008 SDP_STACK STRUC 0000 0000 DW ? ; BP 0002 00000000 DD ? ; Caller 0006 0000 SDP_Page DW ? ; Page # to Display... SDP_STACK ENDS PUBLIC SET_DISPLAY_PAGE 06E9 SET_DISPLAY_PAGE PROC FAR 06E9 55 PUSH BP ; Preserve Registers 06EA 8B EC MOV BP, SP ; Set up Stack Frame 06EC 8B 5E 06 MOV BX, [BP].SDP_Page ; Get Desired Page # 06EF 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid? 06F3 73 2B JAE @SDP_Exit ; IF Not, Do Nothing 06F5 89 1E 0010 R MOV DISPLAY_PAGE, BX ; Set Display Page # 06F9 D1 E3 SHL BX, 1 ; Scale Page # to Word 06FB 8B 8F 0006 R MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page 06FF 03 0E 001C R ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling ; Wait if we are currently in a Vertical Retrace 0703 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register 0706 @DP_WAIT0: 0706 EC IN AL, DX ; Get VGA status 0707 24 08 AND AL, VERT_RETRACE ; In Display mode yet? 0709 75 FB JNZ @DP_WAIT0 ; If Not, wait for it ; Set the Start Display Address to the new page 070B BA 03D4 MOV DX, CRTC_Index ; We Change the VGA Sequencer 070E B0 0D MOV AL, START_DISP_LO ; Display Start Low Register 0710 8A E1 MOV AH, CL ; Low 8 Bits of Start Addr 0712 EF OUT DX, AX ; Set Display Addr Low 0713 B0 0C MOV AL, START_DISP_HI ; Display Start High Register 0715 8A E5 MOV AH, CH ; High 8 Bits of Start Addr 0717 EF OUT DX, AX ; Set Display Addr High ; Wait for a Vertical Retrace to smooth out things 0718 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register 071B @DP_WAIT1: 071B EC IN AL, DX ; Get VGA status 071C 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start? 071E 74 FB JZ @DP_WAIT1 ; If Not, wait for it ; Now Set Display Starting Address 0720 @SDP_Exit: 0720 5D POP BP ; Restore Registers 0721 CA 0002 RET 2 ; Exit and Clean up Stack 0724 SET_DISPLAY_PAGE ENDP ;================= ;GET_DISPLAY_PAGE% ;================= ; ; Returns the Video Page # currently displayed ; ; ENTRY: No Parameters are passed ; ; EXIT: AX = Current Video Page being displayed ; PUBLIC GET_DISPLAY_PAGE 0724 GET_DISPLAY_PAGE PROC FAR 0724 A1 0010 R MOV AX, DISPLAY_PAGE ; Get Display Page # 0727 CB RET ; Exit & Clean Up Stack 0728 GET_DISPLAY_PAGE ENDP ;======================================= ;SET_WINDOW (DisplayPage%, Xpos%, Ypos%) ;======================================= ; ; Since a Logical Screen can be larger than the Physical ; Screen, Scrolling is possible. This routine sets the ; Upper Left Corner of the Screen to the specified Pixel. ; Also Sets the Display page to simplify combined page ; flipping and scrolling. When called this routine ; syncronizes the display to the vertical blank. ; ; ENTRY: DisplayPage = Display Page to show on the screen ; Xpos = # of pixels to shift screen right ; Ypos = # of lines to shift screen down ; ; EXIT: No meaningful values returned ; 000C SW_STACK STRUC 0000 0000 DW ? ; BP 0002 00000000 DD ? ; Caller 0006 0000 SW_Ypos DW ? ; Y pos of UL Screen Corner 0008 0000 SW_Xpos DW ? ; X pos of UL Screen Corner 000A 0000 SW_Page DW ? ; (new) Display Page SW_STACK ENDS PUBLIC SET_WINDOW 0728 SET_WINDOW PROC FAR 0728 55 PUSH BP ; Preserve Registers 0729 8B EC MOV BP, SP ; Set up Stack Frame ; Check if our Scroll Offsets are Valid 072B 8B 5E 0A MOV BX, [BP].SW_Page ; Get Desired Page # 072E 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid? 0732 73 55 JAE @SW_Exit ; IF Not, Do Nothing 0734 8B 46 06 MOV AX, [BP].SW_Ypos ; Get Desired Y Offset 0737 3B 06 0020 R CMP AX, MAX_YOFFSET ; Is it Within Limits? 073B 77 4C JA @SW_Exit ; if not, exit 073D 8B 4E 08 MOV CX, [BP].SW_Xpos ; Get Desired X Offset 0740 3B 0E 001E R CMP CX, MAX_XOFFSET ; Is it Within Limits? Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 9 - 1 0744 77 43 JA @SW_Exit ; if not, exit ; Compute proper Display start address to use 0746 F7 26 0000 R MUL SCREEN_WIDTH ; AX = YOffset * Line Width 074A C1 E9 02 SHR CX, 2 ; CX / 4 = Bytes into Line 074D 03 C1 ADD AX, CX ; AX = Offset of Upper Left Pixel 074F A3 001C R MOV CURRENT_MOFFSET, AX ; Save Offset Info 0752 89 1E 0010 R MOV DISPLAY_PAGE, BX ; Set Current Page # 0756 D1 E3 SHL BX, 1 ; Scale Page # to Word 0758 03 87 0006 R ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page 075C 8B D8 MOV BX, AX ; BX = Desired Display Start 075E BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register ; Wait if we are currently in a Vertical Retrace 0761 @SW_WAIT0: 0761 EC IN AL, DX ; Get VGA status 0762 24 08 AND AL, VERT_RETRACE ; In Display mode yet? 0764 75 FB JNZ @SW_WAIT0 ; If Not, wait for it ; Set the Start Display Address to the new window 0766 BA 03D4 MOV DX, CRTC_Index ; We Change the VGA Sequencer 0769 B0 0D MOV AL, START_DISP_LO ; Display Start Low Register 076B 8A E3 MOV AH, BL ; Low 8 Bits of Start Addr 076D EF OUT DX, AX ; Set Display Addr Low 076E B0 0C MOV AL, START_DISP_HI ; Display Start High Register 0770 8A E7 MOV AH, BH ; High 8 Bits of Start Addr 0772 EF OUT DX, AX ; Set Display Addr High ; Wait for a Vertical Retrace to smooth out things 0773 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register 0776 @SW_WAIT1: 0776 EC IN AL, DX ; Get VGA status 0777 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start? 0779 74 FB 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 077B BA 03C0 1 MOV DX, ATTRIB_Ctrl ; then Select Register 077E B0 33 1 MOV AL, PIXEL_PAN_REG ; then Get Data Value 0780 EE 1 OUT DX, AL ; Set I/O Register 0781 8B 46 08 MOV AX, [BP].SW_Xpos ; Get Desired X Offset 0784 24 03 AND AL, 03 ; Get # of Pixels to Pan (0-3) 0786 D0 E0 SHL AL, 1 ; Shift for 256 Color Mode 0788 EE OUT DX, AL ; Fine tune the display! 0789 @SW_Exit: 0789 5D POP BP ; Restore Saved Registers 078A CA 0006 RET 6 ; Exit and Clean up Stack 078D SET_WINDOW ENDP ;============= ;GET_X_OFFSET% ;============= ; ; Returns the X coordinate of the Pixel currently display ; in the upper left corner of the display ; ; ENTRY: No Parameters are passed ; ; EXIT: AX = Current Horizontal Scroll Offset ; PUBLIC GET_X_OFFSET 078D GET_X_OFFSET PROC FAR 078D A1 0018 R MOV AX, CURRENT_XOFFSET ; Get current horz offset 0790 CB RET ; Exit & Clean Up Stack 0791 GET_X_OFFSET ENDP ;============= ;GET_Y_OFFSET% ;============= ; ; Returns the Y coordinate of the Pixel currently display ; in the upper left corner of the display ; ; ENTRY: No Parameters are passed ; ; EXIT: AX = Current Vertical Scroll Offset ; PUBLIC GET_Y_OFFSET 0791 GET_Y_OFFSET PROC FAR 0791 A1 001A R MOV AX, CURRENT_YOFFSET ; Get current vertical offset 0794 CB RET ; Exit & Clean Up Stack 0795 GET_Y_OFFSET ENDP ;============ ;SYNC_DISPLAY ;============ ; ; Pauses the computer until the next Vertical Retrace starts ; ; ENTRY: No Parameters are passed ; ; EXIT: No meaningful values returned ; PUBLIC SYNC_DISPLAY 0795 SYNC_DISPLAY PROC FAR 0795 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register ; Wait for any current retrace to end 0798 @SD_WAIT0: 0798 EC IN AL, DX ; Get VGA status 0799 24 08 AND AL, VERT_RETRACE ; In Display mode yet? 079B 75 FB JNZ @SD_WAIT0 ; If Not, wait for it ; Wait for the start of the next vertical retrace 079D @SD_WAIT1: 079D EC IN AL, DX ; Get VGA status 079E 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start? 07A0 74 FB JZ @SD_WAIT1 ; If Not, wait for it 07A2 CB RET ; Exit & Clean Up Stack 07A3 SYNC_DISPLAY ENDP ; ===== TEXT DISPLAY ROUTINES ===== ;================================================== ;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%) ;================================================== ; ; Draws an ASCII Text Character using the currently selected ; 8x8 font on the active display page. It would be a simple ; exercise to make this routine process variable height fonts. ; ; ENTRY: CharNum = ASCII character # to draw ; Xpos = X position to draw Character at ; Ypos = Y position of to draw Character at ; ColorF = Color to draw text character in ; ColorB = Color to set background to ; ; EXIT: No meaningful values returned ; 001E GPC_STACK STRUC 0000 0000 GPC_Width DW ? ; Screen Width-1 0002 00 00 GPC_Lines DB ?,? ; Scan lines to Decode 0004 0000 GPC_T_SETS DW ? ; Saved Charset Segment 0006 0000 GPC_T_SETO DW ? ; Saved Charset Offset 0008 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP 0000 0010 00000000 DD ? ; Caller 0014 00 00 GPC_ColorB DB ?,? ; Background Color 0016 00 00 GPC_ColorF DB ?,? ; Text Color 0018 0000 GPC_Ypos DW ? ; Y Position to Print at 001A 0000 GPC_Xpos DW ? ; X position to Print at 001C 00 00 GPC_Char DB ?,? ; Character to Print GPC_STACK ENDS PUBLIC GPRINTC 07A3 GPRINTC PROC FAR PUSHx BP, DS, SI, DI ; Preserve Important Registers 07A3 55 1 PUSH BP ; Save R1 07A4 1E 2 PUSH DS ; Save R1 07A5 56 3 PUSH SI ; Save R1 07A6 57 4 PUSH DI ; Save R1 07A7 83 EC 08 SUB SP, 8 ; Allocate WorkSpace on Stack 07AA 8B EC MOV BP, SP ; Set up Stack Frame 07AC C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 07B0 A1 0000 R MOV AX, SCREEN_WIDTH ; Get Logical Line Width 07B3 8B D8 MOV BX, AX ; BX = Screen Width 07B5 4B DEC BX ; = Screen Width-1 07B6 89 5E 00 MOV [BP].GPC_Width, BX ; Save for later use 07B9 F7 66 18 MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width 07BC 03 F8 ADD DI, AX ; DI -> Start of Line Ypos 07BE 8B 46 1A MOV AX, [BP].GPC_Xpos ; Get Xpos of Character 07C1 8B C8 MOV CX, AX ; Save Copy of Xpos 07C3 C1 E8 02 SHR AX, 2 ; Bytes into Line = Xpos/4 07C6 03 F8 ADD DI, AX ; DI -> (Xpos, Ypos) ;Get Source ADDR of Character Bit Map & Save 07C8 8A 46 1C MOV AL, [BP].GPC_Char ; Get Character # 07CB A8 80 TEST AL, 080h ; Is Hi Bit Set? 07CD 74 0C JZ @GPC_LowChar ; Nope, use low char set ptr 07CF 24 7F AND AL, 07Fh ; Mask Out Hi Bit 07D1 8B 1E 0026 R MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset 07D5 8B 16 0028 R MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment 07D9 EB 08 JMP s @GPC_Set_Char ; Go Setup Character Ptr 07DB @GPC_LowChar: 07DB 8B 1E 0022 R MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset 07DF 8B 16 0024 R MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment 07E3 @GPC_Set_Char: 07E3 89 56 04 MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack 07E6 B4 00 MOV AH, 0 ; Valid #'s are 0..127 07E8 C1 E0 03 SHL AX, 3 ; * 8 Bytes Per Bitmap 07EB 03 D8 ADD BX, AX ; BX = Offset of Selected char 07ED 89 5E 06 MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack 07F0 83 E1 03 AND CX, PLANE_BITS ; Get Plane # 07F3 B5 0F MOV CH, ALL_PLANES ; Get Initial Plane mask 07F5 D2 E5 SHL CH, CL ; And shift into position 07F7 80 E5 0F AND CH, ALL_PLANES ; And mask to lower nibble 07FA B0 04 MOV AL, 04 ; 4-Plane # = # of initial 07FC 2A C1 SUB AL, CL ; shifts to align bit mask 07FE 8A C8 MOV CL, AL ; Shift Count for SHL ;Get segment of character map OUT_8 SC_Index, MAP_MASK ; Setup Plane selections 0800 BA 03C4 1 MOV DX, SC_Index ; then Select Register 0803 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value 0805 EE 1 OUT DX, AL ; Set I/O Register 0806 42 INC DX ; DX -> SC_Data 0807 B0 08 MOV AL, 08 ; 8 Lines to Process 0809 88 46 02 MOV [BP].GPC_Lines, AL ; Save on Stack 080C 8E 5E 04 MOV DS, [BP].GPC_T_SETS ; Point to character set 080F @GPC_DECODE_CHAR_BYTE: Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 10 - 1 080F 8B 76 06 MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String 0812 8A 3C MOV BH, [SI] ; Get Bit Map 0814 46 INC SI ; Point to Next Line 0815 89 76 06 MOV [BP].GPC_T_SETO, SI ; And save new Pointer... CLR AX ; Clear AX 0818 33 C0 1 XOR AX, AX ; Set Register = 0 CLR BL ; Clear BL 081A 32 DB 1 XOR BL, BL ; Set Register = 0 081C D3 C3 ROL BX, CL ; BL holds left edge bits 081E 8B F3 MOV SI, BX ; Use as Table Index 0820 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits 0823 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL 0828 74 07 JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set 082A 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color 082D EE OUT DX, AL ; Set up Screen Mask 082E 26: 88 25 MOV ES:[DI], AH ; Write Foreground color 0831 @GPC_NO_LEFT1BITS: 0831 32 C5 XOR AL, CH ; Invert mask for Background 0833 74 07 JZ @GPC_NO_LEFT0BITS ; Hey, no need for this 0835 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color 0838 EE OUT DX, AL ; Set up Screen Mask 0839 26: 88 25 MOV ES:[DI], AH ; Write Foreground color ;Now Do Middle/Last Band 083C @GPC_NO_LEFT0BITS: 083C 47 INC DI ; Point to next Byte 083D C1 C3 04 ROL BX, 4 ; Shift 4 bits 0840 8B F3 MOV SI, BX ; Make Lookup Pointer 0842 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits 0845 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL 084A 74 07 JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set 084C 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color 084F EE OUT DX, AL ; Set up Screen Mask 0850 26: 88 25 MOV ES:[DI], AH ; Write Foreground color 0853 @GPC_NO_MIDDLE1BITS: 0853 34 0F XOR AL, ALL_PLANES ; Invert mask for Background 0855 74 07 JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this 0857 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color 085A EE OUT DX, AL ; Set up Screen Mask 085B 26: 88 25 MOV ES:[DI], AH ; Write Foreground color 085E @GPC_NO_MIDDLE0BITS: 085E 80 F5 0F XOR CH, ALL_PLANES ; Invert Clip Mask 0861 80 F9 04 CMP CL, 4 ; Aligned by 4? 0864 74 23 JZ @GPC_NEXT_LINE ; If so, Exit now.. 0866 47 INC DI ; Point to next Byte 0867 C1 C3 04 ROL BX, 4 ; Shift 4 bits 086A 8B F3 MOV SI, BX ; Make Lookup Pointer 086C 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits 086F 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL 0874 74 07 JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set 0876 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color 0879 EE OUT DX, AL ; Set up Screen Mask 087A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color 087D @GPC_NO_RIGHT1BITS: 087D 32 C5 XOR AL, CH ; Invert mask for Background 087F 74 07 JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this 0881 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color 0884 EE OUT DX, AL ; Set up Screen Mask 0885 26: 88 25 MOV ES:[DI], AH ; Write Foreground color 0888 @GPC_NO_RIGHT0BITS: 0888 4F DEC DI ; Adjust for Next Line Advance 0889 @GPC_NEXT_LINE: 0889 03 7E 00 ADD DI, [BP].GPC_Width ; Point to Next Line 088C 80 F5 0F XOR CH, CHAR_BITS ; Flip the Clip mask back 088F FE 4E 02 DEC [BP].GPC_Lines ; Count Down Lines 0892 74 03 JZ @GPC_EXIT ; Ok... Done! 0894 E9 FF78 JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey! 0897 @GPC_EXIT: 0897 83 C4 08 ADD SP, 08 ; Deallocate stack workspace POPx DI, SI, DS, BP ; Restore Saved Registers 089A 5F 1 POP DI ; Restore R1 089B 5E 2 POP SI ; Restore R1 089C 1F 3 POP DS ; Restore R1 089D 5D 4 POP BP ; Restore R1 089E CA 000A RET 10 ; Exit and Clean up Stack 08A1 GPRINTC ENDP ;========================================== ;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%) ;========================================== ; ; Transparently draws an ASCII Text Character using the ; currently selected 8x8 font on the active display page. ; ; ENTRY: CharNum = ASCII character # to draw ; Xpos = X position to draw Character at ; Ypos = Y position of to draw Character at ; ColorF = Color to draw text character in ; ; EXIT: No meaningful values returned ; 001C TGP_STACK STRUC 0000 0000 TGP_Width DW ? ; Screen Width-1 0002 00 00 TGP_Lines DB ?,? ; Scan lines to Decode 0004 0000 TGP_T_SETS DW ? ; Saved Charset Segment 0006 0000 TGP_T_SETO DW ? ; Saved Charset Offset 0008 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP 0000 0010 00000000 DD ? ; Caller 0014 00 00 TGP_ColorF DB ?,? ; Text Color 0016 0000 TGP_Ypos DW ? ; Y Position to Print at 0018 0000 TGP_Xpos DW ? ; X position to Print at 001A 00 00 TGP_Char DB ?,? ; Character to Print TGP_STACK ENDS PUBLIC TGPRINTC 08A1 TGPRINTC PROC FAR PUSHx BP, DS, SI, DI ; Preserve Important Registers 08A1 55 1 PUSH BP ; Save R1 08A2 1E 2 PUSH DS ; Save R1 08A3 56 3 PUSH SI ; Save R1 08A4 57 4 PUSH DI ; Save R1 08A5 83 EC 08 SUB SP, 8 ; Allocate WorkSpace on Stack 08A8 8B EC MOV BP, SP ; Set up Stack Frame 08AA C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 08AE A1 0000 R MOV AX, SCREEN_WIDTH ; Get Logical Line Width 08B1 8B D8 MOV BX, AX ; BX = Screen Width 08B3 4B DEC BX ; = Screen Width-1 08B4 89 5E 00 MOV [BP].TGP_Width, BX ; Save for later use 08B7 F7 66 16 MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width 08BA 03 F8 ADD DI, AX ; DI -> Start of Line Ypos 08BC 8B 46 18 MOV AX, [BP].TGP_Xpos ; Get Xpos of Character 08BF 8B C8 MOV CX, AX ; Save Copy of Xpos 08C1 C1 E8 02 SHR AX, 2 ; Bytes into Line = Xpos/4 08C4 03 F8 ADD DI, AX ; DI -> (Xpos, Ypos) ;Get Source ADDR of Character Bit Map & Save 08C6 8A 46 1A MOV AL, [BP].TGP_Char ; Get Character # 08C9 A8 80 TEST AL, 080h ; Is Hi Bit Set? 08CB 74 0C JZ @TGP_LowChar ; Nope, use low char set ptr 08CD 24 7F AND AL, 07Fh ; Mask Out Hi Bit 08CF 8B 1E 0026 R MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset 08D3 8B 16 0028 R MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment 08D7 EB 08 JMP s @TGP_Set_Char ; Go Setup Character Ptr 08D9 @TGP_LowChar: 08D9 8B 1E 0022 R MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset 08DD 8B 16 0024 R MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment 08E1 @TGP_Set_Char: 08E1 89 56 04 MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack 08E4 B4 00 MOV AH, 0 ; Valid #'s are 0..127 08E6 C1 E0 03 SHL AX, 3 ; * 8 Bytes Per Bitmap 08E9 03 D8 ADD BX, AX ; BX = Offset of Selected char 08EB 89 5E 06 MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack 08EE 83 E1 03 AND CX, PLANE_BITS ; Get Plane # 08F1 B5 0F MOV CH, ALL_PLANES ; Get Initial Plane mask 08F3 D2 E5 SHL CH, CL ; And shift into position 08F5 80 E5 0F AND CH, ALL_PLANES ; And mask to lower nibble 08F8 B0 04 MOV AL, 04 ; 4-Plane # = # of initial 08FA 2A C1 SUB AL, CL ; shifts to align bit mask 08FC 8A C8 MOV CL, AL ; Shift Count for SHL ;Get segment of character map OUT_8 SC_Index, MAP_MASK ; Setup Plane selections 08FE BA 03C4 1 MOV DX, SC_Index ; then Select Register 0901 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value 0903 EE 1 OUT DX, AL ; Set I/O Register 0904 42 INC DX ; DX -> SC_Data 0905 B0 08 MOV AL, 08 ; 8 Lines to Process 0907 88 46 02 MOV [BP].TGP_Lines, AL ; Save on Stack 090A 8E 5E 04 MOV DS, [BP].TGP_T_SETS ; Point to character set 090D @TGP_DECODE_CHAR_BYTE: 090D 8B 76 06 MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String 0910 8A 3C MOV BH, [SI] ; Get Bit Map 0912 46 INC SI ; Point to Next Line 0913 89 76 06 MOV [BP].TGP_T_SETO, SI ; And save new Pointer... 0916 8A 66 14 MOV AH, [BP].TGP_ColorF ; Get Foreground Color CLR BL ; Clear BL 0919 32 DB 1 XOR BL, BL ; Set Register = 0 091B D3 C3 ROL BX, CL ; BL holds left edge bits 091D 8B F3 MOV SI, BX ; Use as Table Index 091F 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits 0922 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL 0927 74 04 JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set 0929 EE OUT DX, AL ; Set up Screen Mask 092A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color ;Now Do Middle/Last Band 092D @TGP_NO_LEFT1BITS: 092D 47 INC DI ; Point to next Byte 092E C1 C3 04 ROL BX, 4 ; Shift 4 bits 0931 8B F3 MOV SI, BX ; Make Lookup Pointer 0933 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits 0936 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL 093B 74 04 JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set 093D EE OUT DX, AL ; Set up Screen Mask 093E 26: 88 25 MOV ES:[DI], AH ; Write Foreground color 0941 @TGP_NO_MIDDLE1BITS: 0941 80 F5 0F XOR CH, ALL_PLANES ; Invert Clip Mask 0944 80 F9 04 CMP CL, 4 ; Aligned by 4? 0947 74 15 JZ @TGP_NEXT_LINE ; If so, Exit now.. 0949 47 INC DI ; Point to next Byte 094A C1 C3 04 ROL BX, 4 ; Shift 4 bits 094D 8B F3 MOV SI, BX ; Make Lookup Pointer 094F 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 11 - 1 0952 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL 0957 74 04 JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set 0959 EE OUT DX, AL ; Set up Screen Mask 095A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color 095D @TGP_NO_RIGHT1BITS: 095D 4F DEC DI ; Adjust for Next Line Advance 095E @TGP_NEXT_LINE: 095E 03 7E 00 ADD DI, [BP].TGP_Width ; Point to Next Line 0961 80 F5 0F XOR CH, CHAR_BITS ; Flip the Clip mask back 0964 FE 4E 02 DEC [BP].TGP_Lines ; Count Down Lines 0967 74 02 JZ @TGP_EXIT ; Ok... Done! 0969 EB A2 JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey! 096B @TGP_EXIT: 096B 83 C4 08 ADD SP, 08 ; Deallocate stack workspace POPx DI, SI, DS, BP ; Restore Saved Registers 096E 5F 1 POP DI ; Restore R1 096F 5E 2 POP SI ; Restore R1 0970 1F 3 POP DS ; Restore R1 0971 5D 4 POP BP ; Restore R1 0972 CA 0008 RET 8 ; Exit and Clean up Stack 0975 TGPRINTC ENDP ;=============================================================== ;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) ;=============================================================== ; ; Routine to quickly Print a null terminated ASCII string on the ; active display page up to a maximum length. ; ; ENTRY: String = Far Pointer to ASCII string to print ; MaxLen = # of characters to print if no null found ; Xpos = X position to draw Text at ; Ypos = Y position of to draw Text at ; ColorF = Color to draw text in ; ColorB = Color to set background to ; ; EXIT: No meaningful values returned ; 001A PS_STACK STRUC 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP 0000 0008 00000000 DD ? ; Caller 000C 0000 PS_ColorB DW ? ; Background Color 000E 0000 PS_ColorF DW ? ; Text Color 0010 0000 PS_Ypos DW ? ; Y Position to Print at 0012 0000 PS_Xpos DW ? ; X position to Print at 0014 0000 PS_Len DW ? ; Maximum Length of string to print 0016 0000 0000 PS_Text DW ?,? ; Far Ptr to Text String PS_STACK ENDS PUBLIC PRINT_STR 0975 PRINT_STR PROC FAR PUSHx BP, DS, SI, DI ; Preserve Important Registers 0975 55 1 PUSH BP ; Save R1 0976 1E 2 PUSH DS ; Save R1 0977 56 3 PUSH SI ; Save R1 0978 57 4 PUSH DI ; Save R1 0979 8B EC MOV BP, SP ; Set up Stack Frame 097B @PS_Print_It: 097B 8B 4E 14 MOV CX, [BP].PS_Len ; Get Remaining text Length 097E E3 2F JCXZ @PS_Exit ; Exit when out of text 0980 C4 7E 16 LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text 0983 26: 8A 05 MOV AL, ES:[DI] ; AL = Text Character 0986 25 00FF AND AX, 00FFh ; Clear High Word 0989 74 24 JZ @PS_Exit ; Exit if null character 098B FF 4E 14 DEC [BP].PS_Len ; Remaining Text length-- 098E FF 46 16 INC [BP].PS_Text ; Point to Next text char ; Set up Call to GPRINTC 0991 50 PUSH AX ; Set Character Parameter 0992 8B 5E 12 MOV BX, [BP].PS_Xpos ; Get Xpos 0995 53 PUSH BX ; Set Xpos Parameter 0996 83 C3 08 ADD BX, 8 ; Advance 1 Char to Right 0999 89 5E 12 MOV [BP].PS_Xpos, BX ; Save for next time through 099C 8B 5E 10 MOV BX, [BP].PS_Ypos ; Get Ypos 099F 53 PUSH BX ; Set Ypos Parameter 09A0 8B 5E 0E MOV BX, [BP].PS_ColorF ; Get Text Color 09A3 53 PUSH BX ; Set ColorF Parameter 09A4 8B 5E 0C MOV BX, [BP].PS_ColorB ; Get Background Color 09A7 53 PUSH BX ; Set ColorB Parameter 09A8 9A ---- 07A3 R CALL f GPRINTC ; Print Character! 09AD EB CC JMP s @PS_Print_It ; Process next character 09AF @PS_Exit: POPx DI, SI, DS, BP ; Restore Saved Registers 09AF 5F 1 POP DI ; Restore R1 09B0 5E 2 POP SI ; Restore R1 09B1 1F 3 POP DS ; Restore R1 09B2 5D 4 POP BP ; Restore R1 09B3 CA 000E RET 14 ; Exit and Clean up Stack 09B6 PRINT_STR ENDP ;================================================================ ;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%) ;================================================================ ; ; Routine to quickly transparently Print a null terminated ASCII ; string on the active display page up to a maximum length. ; ; ENTRY: String = Far Pointer to ASCII string to print ; MaxLen = # of characters to print if no null found ; Xpos = X position to draw Text at ; Ypos = Y position of to draw Text at ; ColorF = Color to draw text in ; ; EXIT: No meaningful values returned ; 0018 TPS_STACK STRUC 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP 0000 0008 00000000 DD ? ; Caller 000C 0000 TPS_ColorF DW ? ; Text Color 000E 0000 TPS_Ypos DW ? ; Y Position to Print at 0010 0000 TPS_Xpos DW ? ; X position to Print at 0012 0000 TPS_Len DW ? ; Maximum Length of string to print 0014 0000 0000 TPS_Text DW ?,? ; Far Ptr to Text String TPS_STACK ENDS PUBLIC TPRINT_STR 09B6 TPRINT_STR PROC FAR PUSHx BP, DS, SI, DI ; Preserve Important Registers 09B6 55 1 PUSH BP ; Save R1 09B7 1E 2 PUSH DS ; Save R1 09B8 56 3 PUSH SI ; Save R1 09B9 57 4 PUSH DI ; Save R1 09BA 8B EC MOV BP, SP ; Set up Stack Frame 09BC @TPS_Print_It: 09BC 8B 4E 12 MOV CX, [BP].TPS_Len ; Get Remaining text Length 09BF E3 2B JCXZ @TPS_Exit ; Exit when out of text 09C1 C4 7E 14 LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text 09C4 26: 8A 05 MOV AL, ES:[DI] ; AL = Text Character 09C7 25 00FF AND AX, 00FFh ; Clear High Word 09CA 74 20 JZ @TPS_Exit ; Exit if null character 09CC FF 4E 12 DEC [BP].TPS_Len ; Remaining Text length-- 09CF FF 46 14 INC [BP].TPS_Text ; Point to Next text char ; Set up Call to TGPRINTC 09D2 50 PUSH AX ; Set Character Parameter 09D3 8B 5E 10 MOV BX, [BP].TPS_Xpos ; Get Xpos 09D6 53 PUSH BX ; Set Xpos Parameter 09D7 83 C3 08 ADD BX, 8 ; Advance 1 Char to Right 09DA 89 5E 10 MOV [BP].TPS_Xpos, BX ; Save for next time through 09DD 8B 5E 0E MOV BX, [BP].TPS_Ypos ; Get Ypos 09E0 53 PUSH BX ; Set Ypos Parameter 09E1 8B 5E 0C MOV BX, [BP].TPS_ColorF ; Get Text Color 09E4 53 PUSH BX ; Set ColorF Parameter 09E5 9A ---- 08A1 R CALL f TGPRINTC ; Print Character! 09EA EB D0 JMP s @TPS_Print_It ; Process next character 09EC @TPS_Exit: POPx DI, SI, DS, BP ; Restore Saved Registers 09EC 5F 1 POP DI ; Restore R1 09ED 5E 2 POP SI ; Restore R1 09EE 1F 3 POP DS ; Restore R1 09EF 5D 4 POP BP ; Restore R1 09F0 CA 000C RET 12 ; Exit and Clean up Stack 09F3 TPRINT_STR ENDP ;=========================================== ;SET_DISPLAY_FONT(SEG FontData, FontNumber%) ;=========================================== ; ; Allows the user to specify their own font data for ; wither the lower or upper 128 characters. ; ; ENTRY: FontData = Far Pointer to Font Bitmaps ; FontNumber = Which half of set this is ; = 0, Lower 128 characters ; = 1, Upper 128 characters ; ; EXIT: No meaningful values returned ; 000C SDF_STACK STRUC 0000 0000 DW ? ; BP 0002 00000000 DD ? ; Caller 0006 0000 SDF_Which DW ? ; Hi Table/Low Table Flag 0008 00000000 SDF_Font DD ? ; Far Ptr to Font Table SDF_STACK ENDS PUBLIC SET_DISPLAY_FONT 09F3 SET_DISPLAY_FONT PROC FAR 09F3 55 PUSH BP ; Preserve Registers 09F4 8B EC MOV BP, SP ; Set up Stack Frame 09F6 C4 7E 08 LES DI, [BP].SDF_Font ; Get Far Ptr to Font 09F9 BE 0022 R MOV SI, o CHARSET_LOW ; Assume Lower 128 chars 09FC F7 46 06 0001 TEST [BP].SDF_Which, 1 ; Font #1 selected? 0A01 74 03 JZ @SDF_Set_Font ; If not, skip ahead 0A03 BE 0026 R MOV SI, o CHARSET_HI ; Ah, really it's 128-255 0A06 @SDF_Set_Font: 0A06 89 3C MOV [SI], DI ; Set Font Pointer Offset 0A08 8C 44 02 MOV [SI+2], ES ; Set Font Pointer Segment 0A0B 5D POP BP ; Restore Registers 0A0C CA 0006 RET 6 ; We are Done.. Outa here 0A0F SET_DISPLAY_FONT ENDP ; ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== ;====================================================== ;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) ;====================================================== ; ; Draws a variable sized Graphics Bitmap such as a ; picture or an Icon on the current Display Page in ; Mode X. The Bitmap is stored in a linear byte array ; corresponding to (0,0) (1,0), (2,0) .. (Width, Height) Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 12 - 1 ; This is the same linear manner as mode 13h graphics. ; ; ENTRY: Image = Far Pointer to Bitmap Data ; Xpos = X position to Place Upper Left pixel at ; Ypos = Y position to Place Upper Left pixel at ; Width = Width of the Bitmap in Pixels ; Height = Height of the Bitmap in Pixels ; ; EXIT: No meaningful values returned ; 0022 DB_STACK STRUC 0000 0000 DB_LineO DW ? ; Offset to Next Line 0002 0000 DB_PixCount DW ? ; (Minimum) # of Pixels/Line 0004 0000 DB_Start DW ? ; Addr of Upper Left Pixel 0006 0000 DB_PixSkew DW ? ; # of bytes to Adjust EOL 0008 0000 DB_SkewFlag DW ? ; Extra Pix on Plane Flag 000A 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP 0000 0012 00000000 DD ? ; Caller 0016 0000 DB_Height DW ? ; Height of Bitmap in Pixels 0018 0000 DB_Width DW ? ; Width of Bitmap in Pixels 001A 0000 DB_Ypos DW ? ; Y position to Draw Bitmap at 001C 0000 DB_Xpos DW ? ; X position to Draw Bitmap at 001E 00000000 DB_Image DD ? ; Far Pointer to Graphics Bitmap DB_STACK ENDS PUBLIC DRAW_BITMAP 0A0F DRAW_BITMAP PROC FAR PUSHx BP, DS, SI, DI ; Preserve Important Registers 0A0F 55 1 PUSH BP ; Save R1 0A10 1E 2 PUSH DS ; Save R1 0A11 56 3 PUSH SI ; Save R1 0A12 57 4 PUSH DI ; Save R1 0A13 83 EC 0A SUB SP, 10 ; Allocate workspace 0A16 8B EC MOV BP, SP ; Set up Stack Frame 0A18 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 0A1C FC CLD ; Direction Flag = Forward 0A1D 8B 46 1A MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos 0A20 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Ypos 0A24 8B 5E 1C MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos 0A27 8A CB MOV CL, BL ; Save Plane # in CL 0A29 C1 EB 02 SHR BX, 2 ; Xpos/4 = Offset Into Line 0A2C 03 F8 ADD DI, AX ; ES:DI -> Start of Line 0A2E 03 FB ADD DI, BX ; ES:DI -> Upper Left Pixel 0A30 89 7E 04 MOV [BP].DB_Start, DI ; Save Starting Addr ; Compute line to line offset 0A33 8B 5E 18 MOV BX, [BP].DB_Width ; Get Width of Image 0A36 8B D3 MOV DX, BX ; Save Copy in DX 0A38 C1 EB 02 SHR BX, 2 ; /4 = width in bands 0A3B A1 0000 R MOV AX, SCREEN_WIDTH ; Get Screen Width 0A3E 2B C3 SUB AX, BX ; - (Bitmap Width/4) 0A40 89 46 00 MOV [BP].DB_LineO, AX ; Save Line Width offset 0A43 89 5E 02 MOV [BP].DB_PixCount, BX ; Minimum # pix to copy 0A46 83 E2 03 AND DX, PLANE_BITS ; Get "partial band" size (0-3) 0A49 89 56 06 MOV [BP].DB_PixSkew, DX ; Also End of Line Skew 0A4C 89 56 08 MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count 0A4F 83 E1 03 AND CX, PLANE_BITS ; CL = Starting Plane # 0A52 B8 1102 MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select 0A55 D2 E4 SHL AH, CL ; Select correct Plane OUT_16 SC_Index, AX ; Select Plane... 0A57 BA 03C4 1 MOV DX, SC_Index ; then Select Register 0A5A EF 1 OUT DX, AX ; Set I/O Register(s) 0A5B 8A FC MOV BH, AH ; BH = Saved Plane Mask 0A5D B3 04 MOV BL, 4 ; BL = Planes to Copy 0A5F @DB_COPY_PLANE: 0A5F C5 76 1E LDS SI, [BP].DB_Image ; DS:SI-> Source Image 0A62 8B 56 16 MOV DX, [BP].DB_Height ; # of Lines to Copy 0A65 8B 7E 04 MOV DI, [BP].DB_Start ; ES:DI-> Dest pos 0A68 @DB_COPY_LINE: 0A68 8B 4E 02 MOV CX, [BP].DB_PixCount ; Min # to copy 0A6B F6 C1 FC TEST CL, 0FCh ; 16+PixWide? 0A6E 74 18 JZ @DB_COPY_REMAINDER ; Nope... ; Pixel Copy loop has been unrolled to x4 0A70 @DB_COPY_LOOP: 0A70 A4 MOVSB ; Copy Bitmap Pixel 0A71 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane 0A74 A4 MOVSB ; Copy Bitmap Pixel 0A75 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane 0A78 A4 MOVSB ; Copy Bitmap Pixel 0A79 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane 0A7C A4 MOVSB ; Copy Bitmap Pixel 0A7D 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane 0A80 80 E9 04 SUB CL, 4 ; Pixels to Copy=-4 0A83 F6 C1 FC TEST CL, 0FCh ; 4+ Pixels Left? 0A86 75 E8 JNZ @DB_COPY_LOOP ; if so, do another block 0A88 @DB_COPY_REMAINDER: 0A88 E3 07 JCXZ @DB_NEXT_LINE ; Any Pixels left on line 0A8A @DB_COPY2: 0A8A A4 MOVSB ; Copy Bitmap Pixel 0A8B 83 C6 03 ADD SI,3 ; Skip to Next Byte in same plane LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done 0A8E 49 1 DEC CX ; Counter-- 0A8F 75 F9 1 JNZ @DB_COPY2 ; Jump if not 0 0A91 @DB_NEXT_LINE: ; any Partial Pixels? (some planes only) 0A91 0B 4E 08 OR CX, [BP].DB_SkewFlag ; Get Skew Count 0A94 74 03 JZ @DB_NEXT2 ; if no partial pixels 0A96 A4 MOVSB ; Copy Bitmap Pixel 0A97 4F DEC DI ; Back up to align 0A98 4E DEC SI ; Back up to align 0A99 @DB_NEXT2: 0A99 03 76 06 ADD SI, [BP].DB_PixSkew ; Adjust Skew 0A9C 03 7E 00 ADD DI, [BP].DB_LineO ; Set to Next Display Line LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more 0A9F 4A 1 DEC DX ; Counter-- 0AA0 75 C6 1 JNZ @DB_COPY_LINE ; Jump if not 0 ; Copy Next Plane.... 0AA2 FE CB DEC BL ; Planes to Go-- 0AA4 74 1B JZ @DB_Exit ; Hey! We are done 0AA6 D0 C7 ROL BH, 1 ; Next Plane in line... OUT_8 SC_Data, BH ; Select Plane 0AA8 BA 03C5 1 MOV DX, SC_Data ; then Select Register 0AAB 8A C7 1 MOV AL, BH ; then Get Data Value 0AAD EE 1 OUT DX, AL ; Set I/O Register 0AAE 3C 12 CMP AL, 12h ; Carry Set if AL=11h 0AB0 83 56 04 00 ADC [BP].DB_Start, 0 ; Screen Addr =+Carry 0AB4 FF 46 1E INC w [BP].DB_Image ; Start @ Next Byte 0AB7 83 6E 08 01 SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew 0ABB 83 56 08 00 ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1 0ABF EB 9E JMP s @DB_COPY_PLANE ; Go Copy the Next Plane 0AC1 @DB_Exit: 0AC1 83 C4 0A ADD SP, 10 ; Deallocate workspace POPx DI, SI, DS, BP ; Restore Saved Registers 0AC4 5F 1 POP DI ; Restore R1 0AC5 5E 2 POP SI ; Restore R1 0AC6 1F 3 POP DS ; Restore R1 0AC7 5D 4 POP BP ; Restore R1 0AC8 CA 000C RET 12 ; Exit and Clean up Stack 0ACB DRAW_BITMAP ENDP ;======================================================= ;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%) ;======================================================= ; ; Transparently Draws a variable sized Graphics Bitmap ; such as a picture or an Icon on the current Display Page ; in Mode X. Pixels with a value of 0 are not drawn, ; leaving the previous "background" contents intact. ; ; The Bitmap format is the same as for the DRAW_BITMAP function. ; ; ENTRY: Image = Far Pointer to Bitmap Data ; Xpos = X position to Place Upper Left pixel at ; Ypos = Y position to Place Upper Left pixel at ; Width = Width of the Bitmap in Pixels ; Height = Height of the Bitmap in Pixels ; ; EXIT: No meaningful values returned ; 0022 TB_STACK STRUC 0000 0000 TB_LineO DW ? ; Offset to Next Line 0002 0000 TB_PixCount DW ? ; (Minimum) # of Pixels/Line 0004 0000 TB_Start DW ? ; Addr of Upper Left Pixel 0006 0000 TB_PixSkew DW ? ; # of bytes to Adjust EOL 0008 0000 TB_SkewFlag DW ? ; Extra Pix on Plane Flag 000A 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP 0000 0012 00000000 DD ? ; Caller 0016 0000 TB_Height DW ? ; Height of Bitmap in Pixels 0018 0000 TB_Width DW ? ; Width of Bitmap in Pixels 001A 0000 TB_Ypos DW ? ; Y position to Draw Bitmap at 001C 0000 TB_Xpos DW ? ; X position to Draw Bitmap at 001E 00000000 TB_Image DD ? ; Far Pointer to Graphics Bitmap TB_STACK ENDS PUBLIC TDRAW_BITMAP 0ACB TDRAW_BITMAP PROC FAR PUSHx BP, DS, SI, DI ; Preserve Important Registers 0ACB 55 1 PUSH BP ; Save R1 0ACC 1E 2 PUSH DS ; Save R1 0ACD 56 3 PUSH SI ; Save R1 0ACE 57 4 PUSH DI ; Save R1 0ACF 83 EC 0A SUB SP, 10 ; Allocate workspace 0AD2 8B EC MOV BP, SP ; Set up Stack Frame 0AD4 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page 0AD8 FC CLD ; Direction Flag = Forward 0AD9 8B 46 1A MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos 0ADC F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Ypos 0AE0 8B 5E 1C MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos 0AE3 8A CB MOV CL, BL ; Save Plane # in CL 0AE5 C1 EB 02 SHR BX, 2 ; Xpos/4 = Offset Into Line 0AE8 03 F8 ADD DI, AX ; ES:DI -> Start of Line 0AEA 03 FB ADD DI, BX ; ES:DI -> Upper Left Pixel 0AEC 89 7E 04 MOV [BP].TB_Start, DI ; Save Starting Addr ; Compute line to line offset 0AEF 8B 5E 18 MOV BX, [BP].TB_Width ; Get Width of Image 0AF2 8B D3 MOV DX, BX ; Save Copy in DX 0AF4 C1 EB 02 SHR BX, 2 ; /4 = width in bands 0AF7 A1 0000 R MOV AX, SCREEN_WIDTH ; Get Screen Width 0AFA 2B C3 SUB AX, BX ; - (Bitmap Width/4) 0AFC 89 46 00 MOV [BP].TB_LineO, AX ; Save Line Width offset 0AFF 89 5E 02 MOV [BP].TB_PixCount, BX ; Minimum # pix to copy 0B02 83 E2 03 AND DX, PLANE_BITS ; Get "partial band" size (0-3) 0B05 89 56 06 MOV [BP].TB_PixSkew, DX ; Also End of Line Skew 0B08 89 56 08 MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count 0B0B 83 E1 03 AND CX, PLANE_BITS ; CL = Starting Plane # 0B0E B8 1102 MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select 0B11 D2 E4 SHL AH, CL ; Select correct Plane OUT_16 SC_Index, AX ; Select Plane... 0B13 BA 03C4 1 MOV DX, SC_Index ; then Select Register 0B16 EF 1 OUT DX, AX ; Set I/O Register(s) 0B17 8A FC MOV BH, AH ; BH = Saved Plane Mask 0B19 B3 04 MOV BL, 4 ; BL = Planes to Copy Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 13 - 1 0B1B @TB_COPY_PLANE: 0B1B C5 76 1E LDS SI, [BP].TB_Image ; DS:SI-> Source Image 0B1E 8B 56 16 MOV DX, [BP].TB_Height ; # of Lines to Copy 0B21 8B 7E 04 MOV DI, [BP].TB_Start ; ES:DI-> Dest pos ; Here AH is set with the value to be considered ; "Transparent". It can be changed! 0B24 B4 00 MOV AH, 0 ; Value to Detect 0 0B26 @TB_COPY_LINE: 0B26 8B 4E 02 MOV CX, [BP].TB_PixCount ; Min # to copy 0B29 F6 C1 FC TEST CL, 0FCh ; 16+PixWide? 0B2C 74 3A JZ @TB_COPY_REMAINDER ; Nope... ; Pixel Copy loop has been unrolled to x4 0B2E @TB_COPY_LOOP: 0B2E AC LODSB ; Get Pixel Value in AL 0B2F 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane 0B32 38 E0 CMP AL, AH ; It is "Transparent"? 0B34 74 03 JE @TB_SKIP_01 ; Skip ahead if so 0B36 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen 0B39 @TB_SKIP_01: 0B39 AC LODSB ; Get Pixel Value in AL 0B3A 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane 0B3D 38 E0 CMP AL, AH ; It is "Transparent"? 0B3F 74 04 JE @TB_SKIP_02 ; Skip ahead if so 0B41 26: 88 45 01 MOV ES:[DI+1], AL ; Copy Pixel to VGA screen 0B45 @TB_SKIP_02: 0B45 AC LODSB ; Get Pixel Value in AL 0B46 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane 0B49 38 E0 CMP AL, AH ; It is "Transparent"? 0B4B 74 04 JE @TB_SKIP_03 ; Skip ahead if so 0B4D 26: 88 45 02 MOV ES:[DI+2], AL ; Copy Pixel to VGA screen 0B51 @TB_SKIP_03: 0B51 AC LODSB ; Get Pixel Value in AL 0B52 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane 0B55 38 E0 CMP AL, AH ; It is "Transparent"? 0B57 74 04 JE @TB_SKIP_04 ; Skip ahead if so 0B59 26: 88 45 03 MOV ES:[DI+3], AL ; Copy Pixel to VGA screen 0B5D @TB_SKIP_04: 0B5D 83 C7 04 ADD DI, 4 ; Adjust Pixel Write Location 0B60 80 E9 04 SUB CL, 4 ; Pixels to Copy=-4 0B63 F6 C1 FC TEST CL, 0FCh ; 4+ Pixels Left? 0B66 75 C6 JNZ @TB_COPY_LOOP ; if so, do another block 0B68 @TB_COPY_REMAINDER: 0B68 E3 0F JCXZ @TB_NEXT_LINE ; Any Pixels left on line 0B6A @TB_COPY2: 0B6A AC LODSB ; Get Pixel Value in AL 0B6B 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane 0B6E 38 E0 CMP AL, AH ; It is "Transparent"? 0B70 74 03 JE @TB_SKIP_05 ; Skip ahead if so 0B72 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen 0B75 @TB_SKIP_05: 0B75 47 INC DI ; Advance Dest Addr LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done 0B76 49 1 DEC CX ; Counter-- 0B77 75 F1 1 JNZ @TB_COPY2 ; Jump if not 0 0B79 @TB_NEXT_LINE: ; any Partial Pixels? (some planes only) 0B79 0B 4E 08 OR CX, [BP].TB_SkewFlag ; Get Skew Count 0B7C 74 09 JZ @TB_NEXT2 ; if no partial pixels 0B7E AC LODSB ; Get Pixel Value in AL 0B7F 4E DEC SI ; Backup to Align 0B80 38 E0 CMP AL, AH ; It is "Transparent"? 0B82 74 03 JE @TB_NEXT2 ; Skip ahead if so 0B84 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen 0B87 @TB_NEXT2: 0B87 03 76 06 ADD SI, [BP].TB_PixSkew ; Adjust Skew 0B8A 03 7E 00 ADD DI, [BP].TB_LineO ; Set to Next Display Line LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More 0B8D 4A 1 DEC DX ; Counter-- 0B8E 75 96 1 JNZ @TB_COPY_LINE ; Jump if not 0 ;Copy Next Plane.... 0B90 FE CB DEC BL ; Planes to Go-- 0B92 74 1C JZ @TB_Exit ; Hey! We are done 0B94 D0 C7 ROL BH, 1 ; Next Plane in line... OUT_8 SC_Data, BH ; Select Plane 0B96 BA 03C5 1 MOV DX, SC_Data ; then Select Register 0B99 8A C7 1 MOV AL, BH ; then Get Data Value 0B9B EE 1 OUT DX, AL ; Set I/O Register 0B9C 3C 12 CMP AL, 12h ; Carry Set if AL=11h 0B9E 83 56 04 00 ADC [BP].TB_Start, 0 ; Screen Addr =+Carry 0BA2 FF 46 1E INC w [BP].TB_Image ; Start @ Next Byte 0BA5 83 6E 08 01 SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew 0BA9 83 56 08 00 ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1 0BAD E9 FF6B JMP @TB_COPY_PLANE ; Go Copy the next Plane 0BB0 @TB_Exit: 0BB0 83 C4 0A ADD SP, 10 ; Deallocate workspace POPx DI, SI, DS, BP ; Restore Saved Registers 0BB3 5F 1 POP DI ; Restore R1 0BB4 5E 2 POP SI ; Restore R1 0BB5 1F 3 POP DS ; Restore R1 0BB6 5D 4 POP BP ; Restore R1 0BB7 CA 000C RET 12 ; Exit and Clean up Stack 0BBA TDRAW_BITMAP ENDP ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== ;================================== ;COPY_PAGE (SourcePage%, DestPage%) ;================================== ; ; Duplicate on display page onto another ; ; ENTRY: SourcePage = Display Page # to Duplicate ; DestPage = Display Page # to hold copy ; ; EXIT: No meaningful values returned ; 0010 CP_STACK STRUC 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP 0000 0008 00000000 DD ? ; Caller 000C 0000 CP_DestP DW ? ; Page to hold copied image 000E 0000 CP_SourceP DW ? ; Page to Make copy from CP_STACK ENDS PUBLIC COPY_PAGE 0BBA COPY_PAGE PROC FAR PUSHx BP, DS, SI, DI ; Preserve Important Registers 0BBA 55 1 PUSH BP ; Save R1 0BBB 1E 2 PUSH DS ; Save R1 0BBC 56 3 PUSH SI ; Save R1 0BBD 57 4 PUSH DI ; Save R1 0BBE 8B EC MOV BP, SP ; Set up Stack Frame 0BC0 FC CLD ; Block Xfer Forwards ; Make sure Page #'s are valid 0BC1 8B 46 0E MOV AX, [BP].CP_SourceP ; Get Source Page # 0BC4 3B 06 0004 R CMP AX, LAST_PAGE ; is it > Max Page #? 0BC8 73 3D JAE @CP_Exit ; if so, abort 0BCA 8B 5E 0C MOV BX, [BP].CP_DestP ; Get Destination Page # 0BCD 3B 1E 0004 R CMP BX, LAST_PAGE ; is it > Max Page #? 0BD1 73 34 JAE @CP_Exit ; if so, abort 0BD3 3B C3 CMP AX, BX ; Pages #'s the same? 0BD5 74 30 JE @CP_Exit ; if so, abort ; Setup DS:SI and ES:DI to Video Pages 0BD7 D1 E3 SHL BX, 1 ; Scale index to Word 0BD9 8B BF 0006 R MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page 0BDD 8B D8 MOV BX, AX ; Index to Source page 0BDF D1 E3 SHL BX, 1 ; Scale index to Word 0BE1 8B B7 0006 R MOV SI, PAGE_ADDR[BX] ; Offset to Source Page 0BE5 8B 0E 000E R MOV CX, PAGE_SIZE ; Get size of Page 0BE9 A1 0016 R MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment 0BEC 8E C0 MOV ES, AX ; ES:DI -> Dest Page 0BEE 8E D8 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 0BF0 BA 03CE 1 MOV DX, GC_Index ; then Select Register 0BF3 B8 0008 1 MOV AX, LATCHES_ON ; then Get Data Value 0BF6 EF 1 OUT DX, AX ; Set I/O Register(s) OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes 0BF7 BA 03C4 1 MOV DX, SC_Index ; then Select Register 0BFA B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value 0BFD EF 1 OUT DX, AX ; Set I/O Register(s) ; Note.. Do *NOT* use MOVSW or MOVSD - they will ; Screw with the latches which are 8 bits x 4 0BFE F3/ A4 REP MOVSB ; Copy entire Page! ; Reset VGA for normal memory access OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off 0C00 BA 03CE 1 MOV DX, GC_Index ; then Select Register 0C03 B8 FF08 1 MOV AX, LATCHES_OFF ; then Get Data Value 0C06 EF 1 OUT DX, AX ; Set I/O Register(s) 0C07 @CP_Exit: POPx DI, SI, DS, BP ; Restore Saved Registers 0C07 5F 1 POP DI ; Restore R1 0C08 5E 2 POP SI ; Restore R1 0C09 1F 3 POP DS ; Restore R1 0C0A 5D 4 POP BP ; Restore R1 0C0B CA 0004 RET 4 ; Exit and Clean up Stack 0C0E COPY_PAGE ENDP ;========================================================================== ;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%) ;========================================================================== ; ; Copies a Bitmap Image from one Display Page to Another ; This Routine is Limited to copying Images with the same ; Plane Alignment. To Work: (X1 MOD 4) must = (DestX1 MOD 4) ; Copying an Image to the Same Page is supported, but results ; may be defined when the when the rectangular areas ; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) - ; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap... ; No Paramter checking to done to insure that ; X2 >= X1 and Y2 >= Y1. Be Careful... ; ; ENTRY: SourcePage = Display Page # with Source Image ; X1 = Upper Left Xpos of Source Image ; Y1 = Upper Left Ypos of Source Image ; X2 = Lower Right Xpos of Source Image ; Y2 = Lower Right Ypos of Source Image ; DestPage = Display Page # to copy Image to ; DestX1 = Xpos to Copy UL Corner of Image to ; DestY1 = Ypos to Copy UL Corner of Image to ; ; EXIT: AX = Success Flag: 0 = Failure / -1= Success ; 0020 CB_STACK STRUC 0000 0000 CB_Height DW ? ; Height of Image in Lines 0002 0000 CB_Width DW ? ; Width of Image in "bands" 0004 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP 0000 000C 00000000 DD ? ; Caller 0010 0000 CB_DestY1 DW ? ; Destination Ypos 0012 0000 CB_DestX1 DW ? ; Destination Xpos 0014 0000 CB_DestP DW ? ; Page to Copy Bitmap To Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 14 - 1 0016 0000 CB_Y2 DW ? ; LR Ypos of Image 0018 0000 CB_X2 DW ? ; LR Xpos of Image 001A 0000 CB_Y1 DW ? ; UL Ypos of Image 001C 0000 CB_X1 DW ? ; UL Xpos of Image 001E 0000 CB_SourceP DW ? ; Page containing Source Bitmap CB_STACK ENDS PUBLIC COPY_BITMAP 0C0E COPY_BITMAP PROC FAR PUSHx BP, DS, SI, DI ; Preserve Important Registers 0C0E 55 1 PUSH BP ; Save R1 0C0F 1E 2 PUSH DS ; Save R1 0C10 56 3 PUSH SI ; Save R1 0C11 57 4 PUSH DI ; Save R1 0C12 83 EC 04 SUB SP, 4 ; Allocate WorkSpace on Stack 0C15 8B EC MOV BP, SP ; Set up Stack Frame ; Prep Registers (and keep jumps short!) 0C17 8E 06 0016 R MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram 0C1B FC CLD ; Block Xfer Forwards ; Make sure Parameters are valid 0C1C 8B 5E 1E MOV BX, [BP].CB_SourceP ; Get Source Page # 0C1F 3B 1E 0004 R CMP BX, LAST_PAGE ; is it > Max Page #? 0C23 73 7D JAE @CB_Abort ; if so, abort 0C25 8B 4E 14 MOV CX, [BP].CB_DestP ; Get Destination Page # 0C28 3B 0E 0004 R CMP CX, LAST_PAGE ; is it > Max Page #? 0C2C 73 74 JAE @CB_Abort ; if so, abort 0C2E 8B 46 1C MOV AX, [BP].CB_X1 ; Get Source X1 0C31 33 46 12 XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1 0C34 83 E0 03 AND AX, PLANE_BITS ; Check Plane Bits 0C37 75 69 JNZ @CB_Abort ; They should cancel out ; Setup for Copy processing OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select 0C39 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register 0C3C B0 02 1 MOV AL, MAP_MASK ; then Get Data Value 0C3E EE 1 OUT DX, AL ; Set I/O Register OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on 0C3F BA 03CE 1 MOV DX, GC_Index ; then Select Register 0C42 B8 0008 1 MOV AX, LATCHES_ON ; then Get Data Value 0C45 EF 1 OUT DX, AX ; Set I/O Register(s) ; Compute Info About Images, Setup ES:SI & ES:DI 0C46 8B 46 16 MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines 0C49 2B 46 1A SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1 0C4C 40 INC AX ; (add 1 since were not 0 based) 0C4D 89 46 00 MOV [BP].CB_Height, AX ; Save on Stack for later use 0C50 8B 46 18 MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels 0C53 8B 56 1C MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1 0C56 C1 E8 02 SHR AX, 2 ; Get X2 Band (X2 / 4) 0C59 C1 EA 02 SHR DX, 2 ; Get X1 Band (X1 / 4) 0C5C 2B C2 SUB AX, DX ; AX = # of Bands - 1 0C5E 40 INC AX ; AX = # of Bands 0C5F 89 46 02 MOV [BP].CB_Width, AX ; Save on Stack for later use 0C62 D1 E3 SHL BX, 1 ; Scale Source Page to Word 0C64 8B B7 0006 R MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page 0C68 8B 46 1A MOV AX, [BP].CB_Y1 ; Get Source Y1 Line 0C6B F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Y1 0C6F 03 F0 ADD SI, AX ; SI = Offset to Line Y1 0C71 8B 46 1C MOV AX, [BP].CB_X1 ; Get Source X1 0C74 C1 E8 02 SHR AX, 2 ; X1 / 4 = Byte offset 0C77 03 F0 ADD SI, AX ; SI = Byte Offset to (X1,Y1) 0C79 8B D9 MOV BX, CX ; Dest Page Index to BX 0C7B D1 E3 SHL BX, 1 ; Scale Source Page to Word 0C7D 8B BF 0006 R MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page 0C81 8B 46 10 MOV AX, [BP].CB_DestY1 ; Get Dest Y1 Line 0C84 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Y1 0C88 03 F8 ADD DI, AX ; DI = Offset to Line Y1 0C8A 8B 46 12 MOV AX, [BP].CB_DestX1 ; Get Dest X1 0C8D C1 E8 02 SHR AX, 2 ; X1 / 4 = Byte offset 0C90 03 F8 ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1) 0C92 8B 4E 02 MOV CX, [BP].CB_Width ; CX = Width of Image (Bands) 0C95 49 DEC CX ; CX = 1? 0C96 74 0F JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band 0C98 8B 5E 1C MOV BX, [BP].CB_X1 ; Get Source X1 0C9B 83 E3 03 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?) 0C9E 74 70 JZ @CB_Check_Right ; if so, check right alignment 0CA0 75 41 JNZ @CB_Left_Band ; not aligned? well.. 0CA2 @CB_Abort: CLR AX ; Return False (Failure) 0CA2 33 C0 1 XOR AX, AX ; Set Register = 0 0CA4 E9 00D7 JMP @CB_Exit ; and Finish Up ; Copy when Left & Right Clip Masks overlap... 0CA7 @CB_Only_One_Band: 0CA7 8B 5E 1C MOV BX, [BP].CB_X1 ; Get Left Clip Mask 0CAA 83 E3 03 AND BX, PLANE_BITS ; Mask out Row # 0CAD 2E: 8A 87 0000 R MOV AL, Left_Clip_Mask[BX] ; Get Left Edge Mask 0CB2 8B 5E 18 MOV BX, [BP].CB_X2 ; Get Right Clip Mask 0CB5 83 E3 03 AND BX, PLANE_BITS ; Mask out Row # 0CB8 2E: 22 87 0004 R AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte OUT_8 SC_Data, AL ; Clip For Left & Right Masks 0CBD BA 03C5 1 MOV DX, SC_Data ; then Select Register 0CC0 EE 1 OUT DX, AL ; Set I/O Register 0CC1 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy 0CC4 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen CLR BX ; BX = Offset into Image 0CC8 33 DB 1 XOR BX, BX ; Set Register = 0 0CCA @CB_One_Loop: 0CCA 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches 0CCD 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches 0CD0 03 DA ADD BX, DX ; Advance Offset to Next Line LOOPjz CX, @CB_One_Done ; Exit Loop if Finished 0CD2 49 1 DEC CX ; Counter-- 0CD3 74 0B 1 JZ @CB_One_Done ; Jump if 0 0CD5 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches 0CD8 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches 0CDB 03 DA ADD BX, DX ; Advance Offset to Next Line LOOPx CX, @CB_One_Loop ; Loop until Finished 0CDD 49 1 DEC CX ; Counter-- 0CDE 75 EA 1 JNZ @CB_One_Loop ; Jump if not 0 0CE0 @CB_One_Done: 0CE0 E9 0094 JMP @CB_Finish ; Outa Here! ; Copy Left Edge of Bitmap 0CE3 @CB_Left_Band: OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask 0CE3 BA 03C5 1 MOV DX, SC_Data ; then Select Register 0CE6 2E: 8A 87 0000 R 1 MOV AL, Left_Clip_Mask[BX] ; then Get Data Value 0CEB EE 1 OUT DX, AL ; Set I/O Register 0CEC 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy 0CEF 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen CLR BX ; BX = Offset into Image 0CF3 33 DB 1 XOR BX, BX ; Set Register = 0 0CF5 @CB_Left_Loop: 0CF5 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches 0CF8 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches 0CFB 03 DA ADD BX, DX ; Advance Offset to Next Line LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished 0CFD 49 1 DEC CX ; Counter-- 0CFE 74 0B 1 JZ @CB_Left_Done ; Jump if 0 0D00 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches 0D03 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches 0D06 03 DA ADD BX, DX ; Advance Offset to Next Line LOOPx CX, @CB_Left_Loop ; Loop until Finished 0D08 49 1 DEC CX ; Counter-- 0D09 75 EA 1 JNZ @CB_Left_Loop ; Jump if not 0 0D0B @CB_Left_Done: 0D0B 47 INC DI ; Move Dest Over 1 band 0D0C 46 INC SI ; Move Source Over 1 band 0D0D FF 4E 02 DEC [BP].CB_Width ; Band Width-- ; Determine if Right Edge of Bitmap needs special copy 0D10 @CB_Check_Right: 0D10 8B 5E 18 MOV BX, [BP].CB_X2 ; Get Source X2 0D13 83 E3 03 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?) 0D16 80 FB 03 CMP BL, 03h ; Plane = 3? 0D19 74 2C JE @CB_Copy_Middle ; Copy the Middle then! ; Copy Right Edge of Bitmap 0D1B @CB_Right_Band: OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask 0D1B BA 03C5 1 MOV DX, SC_Data ; then Select Register 0D1E 2E: 8A 87 0004 R 1 MOV AL, Right_Clip_Mask[BX] ; then Get Data Value 0D23 EE 1 OUT DX, AL ; Set I/O Register 0D24 FF 4E 02 DEC [BP].CB_Width ; Band Width-- 0D27 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy 0D2A 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen 0D2E 8B 5E 02 MOV BX, [BP].CB_Width ; BX = Offset to Right Edge 0D31 @CB_Right_Loop: 0D31 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches 0D34 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches 0D37 03 DA ADD BX, DX ; Advance Offset to Next Line LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished 0D39 49 1 DEC CX ; Counter-- 0D3A 74 0B 1 JZ @CB_Right_Done ; Jump if 0 0D3C 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches 0D3F 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches 0D42 03 DA ADD BX, DX ; Advance Offset to Next Line LOOPx CX, @CB_Right_Loop ; Loop until Finished 0D44 49 1 DEC CX ; Counter-- 0D45 75 EA 1 JNZ @CB_Right_Loop ; Jump if not 0 0D47 @CB_Right_Done: ; Copy the Main Block of the Bitmap 0D47 @CB_Copy_Middle: 0D47 8B 4E 02 MOV CX, [BP].CB_Width ; Get Width Remaining 0D4A E3 2B JCXZ @CB_Finish ; Exit if Done OUT_8 SC_Data, ALL_PLANES ; Copy all Planes 0D4C BA 03C5 1 MOV DX, SC_Data ; then Select Register 0D4F B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value 0D51 EE 1 OUT DX, AL ; Set I/O Register 0D52 8B 16 0000 R MOV DX, SCREEN_WIDTH ; Get Width of Screen minus 0D56 2B D1 SUB DX, CX ; Image width (for Adjustment) 0D58 8B 46 00 MOV AX, [BP].CB_Height ; AX = # of Lines to Copy 0D5B 8B D9 MOV BX, CX ; BX = Quick REP reload count 0D5D 8C C1 MOV CX, ES ; Move VGA Segment 0D5F 8E D9 MOV DS, CX ; Into DS ; Actual Copy Loop. REP MOVSB does the work 0D61 @CB_Middle_Copy: 0D61 8B CB MOV CX, BX ; Recharge Rep Count 0D63 F3/ A4 REP MOVSB ; Move Bands LOOPjz AX, @CB_Finish ; Exit Loop if Finished 0D65 48 1 DEC AX ; Counter-- 0D66 74 0F 1 JZ @CB_Finish ; Jump if 0 0D68 03 F2 ADD SI, DX ; Adjust DS:SI to Next Line 0D6A 03 FA ADD DI, DX ; Adjust ES:DI to Next Line 0D6C 8B CB MOV CX, BX ; Recharge Rep Count 0D6E F3/ A4 REP MOVSB ; Move Bands 0D70 03 F2 ADD SI, DX ; Adjust DS:SI to Next Line 0D72 03 FA ADD DI, DX ; Adjust ES:DI to Next Line LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done 0D74 48 1 DEC AX ; Counter-- 0D75 75 EA 1 JNZ @CB_Middle_Copy ; Jump if not 0 0D77 @CB_Finish: OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on 0D77 BA 03CE 1 MOV DX, GC_Index ; then Select Register Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Page 15 - 1 0D7A B8 FF08 1 MOV AX, LATCHES_OFF ; then Get Data Value 0D7D EF 1 OUT DX, AX ; Set I/O Register(s) 0D7E @CB_Exit: 0D7E 83 C4 04 ADD SP, 04 ; Deallocate stack workspace POPx DI, SI, DS, BP ; Restore Saved Registers 0D81 5F 1 POP DI ; Restore R1 0D82 5E 2 POP SI ; Restore R1 0D83 1F 3 POP DS ; Restore R1 0D84 5D 4 POP BP ; Restore R1 0D85 CA 0010 RET 16 ; Exit and Clean up Stack 0D88 COPY_BITMAP ENDP END ; End of Code Segment Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Symbols 16 - 1 Macros: N a m e Type CLR . . . . . . . . . . . . . . Proc LOOPjz . . . . . . . . . . . . . Proc LOOPx . . . . . . . . . . . . . Proc OUT_16 . . . . . . . . . . . . . Proc OUT_8 . . . . . . . . . . . . . Proc POPx . . . . . . . . . . . . . . Proc PUSHx . . . . . . . . . . . . . Proc Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Symbols 17 - 1 Structures and Unions: N a m e Size Offset Type CB_STACK . . . . . . . . . . . . 0020 CB_Height . . . . . . . . . . 0000 Word CB_Width . . . . . . . . . . . 0002 Word CB_DestY1 . . . . . . . . . . 0010 Word CB_DestX1 . . . . . . . . . . 0012 Word CB_DestP . . . . . . . . . . . 0014 Word CB_Y2 . . . . . . . . . . . . 0016 Word CB_X2 . . . . . . . . . . . . 0018 Word CB_Y1 . . . . . . . . . . . . 001A Word CB_X1 . . . . . . . . . . . . 001C Word CB_SourceP . . . . . . . . . . 001E Word CP_STACK . . . . . . . . . . . . 0010 CP_DestP . . . . . . . . . . . 000C Word CP_SourceP . . . . . . . . . . 000E Word CVS_STACK . . . . . . . . . . . 000A CVS_COLOR . . . . . . . . . . 0008 Byte DB_STACK . . . . . . . . . . . . 0022 DB_LineO . . . . . . . . . . . 0000 Word DB_PixCount . . . . . . . . . 0002 Word DB_Start . . . . . . . . . . . 0004 Word DB_PixSkew . . . . . . . . . . 0006 Word DB_SkewFlag . . . . . . . . . 0008 Word DB_Height . . . . . . . . . . 0016 Word DB_Width . . . . . . . . . . . 0018 Word DB_Ypos . . . . . . . . . . . 001A Word DB_Xpos . . . . . . . . . . . 001C Word DB_Image . . . . . . . . . . . 001E DWord DL_STACK . . . . . . . . . . . . 0014 DL_ColorF . . . . . . . . . . 000A Byte DL_Ypos2 . . . . . . . . . . . 000C Word DL_Xpos2 . . . . . . . . . . . 000E Word DL_Ypos1 . . . . . . . . . . . 0010 Word DL_Xpos1 . . . . . . . . . . . 0012 Word FB_STACK . . . . . . . . . . . . 0016 FB_Color . . . . . . . . . . . 000C Byte FB_Ypos2 . . . . . . . . . . . 000E Word FB_Xpos2 . . . . . . . . . . . 0010 Word FB_Ypos1 . . . . . . . . . . . 0012 Word FB_Xpos1 . . . . . . . . . . . 0014 Word GDR_STACK . . . . . . . . . . . 000E GDR_Blue . . . . . . . . . . . 0006 Word GDR_Green . . . . . . . . . . 0008 Word GDR_Red . . . . . . . . . . . 000A Word GDR_Register . . . . . . . . . 000C Byte GPC_STACK . . . . . . . . . . . 001E GPC_Width . . . . . . . . . . 0000 Word GPC_Lines . . . . . . . . . . 0002 Byte GPC_T_SETS . . . . . . . . . . 0004 Word GPC_T_SETO . . . . . . . . . . 0006 Word GPC_ColorB . . . . . . . . . . 0014 Byte GPC_ColorF . . . . . . . . . . 0016 Byte GPC_Ypos . . . . . . . . . . . 0018 Word GPC_Xpos . . . . . . . . . . . 001A Word GPC_Char . . . . . . . . . . . 001C Byte LDR_STACK . . . . . . . . . . . 0014 LDR_Sync . . . . . . . . . . . 000A Word LDR_EndReg . . . . . . . . . . 000C Byte LDR_StartReg . . . . . . . . . 000E Byte LDR_PalData . . . . . . . . . 0010 DWord Mode_Data_Table . . . . . . . . 000C M_MiscR . . . . . . . . . . . 0000 Byte M_Pages . . . . . . . . . . . 0001 Byte M_XSize . . . . . . . . . . . 0002 Word M_YSize . . . . . . . . . . . 0004 Word M_XMax . . . . . . . . . . . . 0006 Word M_YMax . . . . . . . . . . . . 0008 Word M_CRTC . . . . . . . . . . . . 000A Word PS_STACK . . . . . . . . . . . . 001A PS_ColorB . . . . . . . . . . 000C Word PS_ColorF . . . . . . . . . . 000E Word PS_Ypos . . . . . . . . . . . 0010 Word PS_Xpos . . . . . . . . . . . 0012 Word PS_Len . . . . . . . . . . . . 0014 Word PS_Text . . . . . . . . . . . 0016 Word RDR_STACK . . . . . . . . . . . 0012 RDR_EndReg . . . . . . . . . . 000A Byte RDR_StartReg . . . . . . . . . 000C Byte RDR_PalData . . . . . . . . . 000E DWord RP_STACK . . . . . . . . . . . . 000C RP_Ypos . . . . . . . . . . . 0008 Word RP_Xpos . . . . . . . . . . . 000A Word SAP_STACK . . . . . . . . . . . 0008 SAP_Page . . . . . . . . . . . 0006 Word SDF_STACK . . . . . . . . . . . 000C SDF_Which . . . . . . . . . . 0006 Word SDF_Font . . . . . . . . . . . 0008 DWord SDP_STACK . . . . . . . . . . . 0008 SDP_Page . . . . . . . . . . . 0006 Word SDR_STACK . . . . . . . . . . . 000E SDR_Blue . . . . . . . . . . . 0006 Byte SDR_Green . . . . . . . . . . 0008 Byte SDR_Red . . . . . . . . . . . 000A Byte SDR_Register . . . . . . . . . 000C Byte SM_STACK . . . . . . . . . . . . 000A SM_Mode . . . . . . . . . . . 0008 Word SP_STACK . . . . . . . . . . . . 000E SETP_Color . . . . . . . . . . 0008 Byte SETP_Ypos . . . . . . . . . . 000A Word SETP_Xpos . . . . . . . . . . 000C Word SVM_STACK . . . . . . . . . . . 0016 SVM_Table . . . . . . . . . . 0000 Word SVM_Pages . . . . . . . . . . 000E Word SVM_Ysize . . . . . . . . . . 0010 Word SVM_Xsize . . . . . . . . . . 0012 Word SVM_Mode . . . . . . . . . . . 0014 Word SW_STACK . . . . . . . . . . . . 000C SW_Ypos . . . . . . . . . . . 0006 Word SW_Xpos . . . . . . . . . . . 0008 Word SW_Page . . . . . . . . . . . 000A Word TB_STACK . . . . . . . . . . . . 0022 TB_LineO . . . . . . . . . . . 0000 Word TB_PixCount . . . . . . . . . 0002 Word TB_Start . . . . . . . . . . . 0004 Word TB_PixSkew . . . . . . . . . . 0006 Word TB_SkewFlag . . . . . . . . . 0008 Word TB_Height . . . . . . . . . . 0016 Word TB_Width . . . . . . . . . . . 0018 Word TB_Ypos . . . . . . . . . . . 001A Word TB_Xpos . . . . . . . . . . . 001C Word TB_Image . . . . . . . . . . . 001E DWord TGP_STACK . . . . . . . . . . . 001C TGP_Width . . . . . . . . . . 0000 Word TGP_Lines . . . . . . . . . . 0002 Byte TGP_T_SETS . . . . . . . . . . 0004 Word TGP_T_SETO . . . . . . . . . . 0006 Word TGP_ColorF . . . . . . . . . . 0014 Byte TGP_Ypos . . . . . . . . . . . 0016 Word TGP_Xpos . . . . . . . . . . . 0018 Word TGP_Char . . . . . . . . . . . 001A Byte TPS_STACK . . . . . . . . . . . 0018 TPS_ColorF . . . . . . . . . . 000C Word TPS_Ypos . . . . . . . . . . . 000E Word TPS_Xpos . . . . . . . . . . . 0010 Word TPS_Len . . . . . . . . . . . 0012 Word TPS_Text . . . . . . . . . . . 0014 Word Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Symbols 18 - 1 Segments and Groups: N a m e Size Length Align Combine Class DGROUP . . . . . . . . . . . . . GROUP _DATA . . . . . . . . . . . . . 16 Bit 0000 Word Public 'DATA' _BSS . . . . . . . . . . . . . . 16 Bit 002A Word Public 'BSS' MODEX_TEXT . . . . . . . . . . . 16 Bit 0D88 Word Public 'CODE' Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Symbols 19 - 1 Procedures, parameters and locals: N a m e Type Value Attr CLEAR_VGA_SCREEN . . . . . . . . P Far 0280 MODEX_TEXT Length= 0022 Public COPY_BITMAP . . . . . . . . . . P Far 0C0E MODEX_TEXT Length= 017E Public COPY_PAGE . . . . . . . . . . . P Far 0BBA MODEX_TEXT Length= 0054 Public DRAW_BITMAP . . . . . . . . . . P Far 0A0F MODEX_TEXT Length= 00BC Public DRAW_LINE . . . . . . . . . . . P Far 040B MODEX_TEXT Length= 02A7 Public FILL_BLOCK . . . . . . . . . . . P Far 0300 MODEX_TEXT Length= 010B Public GET_ACTIVE_PAGE . . . . . . . . P Far 06E5 MODEX_TEXT Length= 0004 Public GET_DAC_REGISTER . . . . . . . . P Far 0641 MODEX_TEXT Length= 0025 Public GET_DISPLAY_PAGE . . . . . . . . P Far 0724 MODEX_TEXT Length= 0004 Public GET_X_OFFSET . . . . . . . . . . P Far 078D MODEX_TEXT Length= 0004 Public GET_Y_OFFSET . . . . . . . . . . P Far 0791 MODEX_TEXT Length= 0004 Public GPRINTC . . . . . . . . . . . . P Far 07A3 MODEX_TEXT Length= 00FE Public LOAD_DAC_REGISTERS . . . . . . . P Far 0666 MODEX_TEXT Length= 0037 Public PRINT_STR . . . . . . . . . . . P Far 0975 MODEX_TEXT Length= 0041 Public READ_DAC_REGISTERS . . . . . . . P Far 069D MODEX_TEXT Length= 002B Public READ_POINT . . . . . . . . . . . P Far 02D2 MODEX_TEXT Length= 002E Public SET_ACTIVE_PAGE . . . . . . . . P Far 06C8 MODEX_TEXT Length= 001D Public SET_DAC_REGISTER . . . . . . . . P Far 0624 MODEX_TEXT Length= 001D Public SET_DISPLAY_FONT . . . . . . . . P Far 09F3 MODEX_TEXT Length= 001C Public SET_DISPLAY_PAGE . . . . . . . . P Far 06E9 MODEX_TEXT Length= 003B Public SET_MODEX . . . . . . . . . . . P Far 0251 MODEX_TEXT Length= 002F Public SET_POINT . . . . . . . . . . . P Far 02A2 MODEX_TEXT Length= 0030 Public SET_VGA_MODEX . . . . . . . . . P Far 0104 MODEX_TEXT Length= 014D Public SET_WINDOW . . . . . . . . . . . P Far 0728 MODEX_TEXT Length= 0065 Public SYNC_DISPLAY . . . . . . . . . . P Far 0795 MODEX_TEXT Length= 000E Public TDRAW_BITMAP . . . . . . . . . . P Far 0ACB MODEX_TEXT Length= 00EF Public TGPRINTC . . . . . . . . . . . . P Far 08A1 MODEX_TEXT Length= 00D4 Public TPRINT_STR . . . . . . . . . . . P Far 09B6 MODEX_TEXT Length= 003D Public Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33 modex.asm Symbols 20 - 1 Symbols: N a m e Type Value Attr ?x3 . . . . . . . . . . . . . . Text ?,?,? ?x4 . . . . . . . . . . . . . . Text ?,?,?,? @CB_Abort . . . . . . . . . . . L Near 0CA2 MODEX_TEXT @CB_Check_Right . . . . . . . . L Near 0D10 MODEX_TEXT @CB_Copy_Middle . . . . . . . . L Near 0D47 MODEX_TEXT @CB_Exit . . . . . . . . . . . . L Near 0D7E MODEX_TEXT @CB_Finish . . . . . . . . . . . L Near 0D77 MODEX_TEXT @CB_Left_Band . . . . . . . . . L Near 0CE3 MODEX_TEXT @CB_Left_Done . . . . . . . . . L Near 0D0B MODEX_TEXT @CB_Left_Loop . . . . . . . . . L Near 0CF5 MODEX_TEXT @CB_Middle_Copy . . . . . . . . L Near 0D61 MODEX_TEXT @CB_One_Done . . . . . . . . . . L Near 0CE0 MODEX_TEXT @CB_One_Loop . . . . . . . . . . L Near 0CCA MODEX_TEXT @CB_Only_One_Band . . . . . . . L Near 0CA7 MODEX_TEXT @CB_Right_Band . . . . . . . . . L Near 0D1B MODEX_TEXT @CB_Right_Done . . . . . . . . . L Near 0D47 MODEX_TEXT @CB_Right_Loop . . . . . . . . . L Near 0D31 MODEX_TEXT @CP_Exit . . . . . . . . . . . . L Near 0C07 MODEX_TEXT @CodeSize . . . . . . . . . . . Number 0001h @DB_COPY2 . . . . . . . . . . . L Near 0A8A MODEX_TEXT @DB_COPY_LINE . . . . . . . . . L Near 0A68 MODEX_TEXT @DB_COPY_LOOP . . . . . . . . . L Near 0A70 MODEX_TEXT @DB_COPY_PLANE . . . . . . . . . L Near 0A5F MODEX_TEXT @DB_COPY_REMAINDER . . . . . . . L Near 0A88 MODEX_TEXT @DB_Exit . . . . . . . . . . . . L Near 0AC1 MODEX_TEXT @DB_NEXT2 . . . . . . . . . . . L Near 0A99 MODEX_TEXT @DB_NEXT_LINE . . . . . . . . . L Near 0A91 MODEX_TEXT @DL_BREZHAM . . . . . . . . . . L Near 04C7 MODEX_TEXT @DL_DeltaYOK2 . . . . . . . . . L Near 0515 MODEX_TEXT @DL_DeltaYOK . . . . . . . . . . L Near 04DC MODEX_TEXT @DL_DrawLeft . . . . . . . . . . L Near 051F MODEX_TEXT @DL_DrawRight . . . . . . . . . L Near 05A3 MODEX_TEXT @DL_EXIT2 . . . . . . . . . . . L Near 061E MODEX_TEXT @DL_EXIT . . . . . . . . . . . . L Near 04C4 MODEX_TEXT @DL_HORZ . . . . . . . . . . . . L Near 0433 MODEX_TEXT @DL_LONGLN . . . . . . . . . . . L Near 0461 MODEX_TEXT @DL_NOSWAP1 . . . . . . . . . . L Near 0428 MODEX_TEXT @DL_NOSWAP2 . . . . . . . . . . L Near 048C MODEX_TEXT @DL_SLLExit . . . . . . . . . . L Near 0563 MODEX_TEXT @DL_SLLL2nc . . . . . . . . . . L Near 0543 MODEX_TEXT @DL_SLLL3nc . . . . . . . . . . L Near 0558 MODEX_TEXT @DL_SLLLoop . . . . . . . . . . L Near 0537 MODEX_TEXT @DL_SLR2nc . . . . . . . . . . . L Near 05C5 MODEX_TEXT @DL_SLR3nc . . . . . . . . . . . L Near 05D9 MODEX_TEXT @DL_SLRExit . . . . . . . . . . L Near 05E3 MODEX_TEXT @DL_SLRLoop . . . . . . . . . . L Near 05B9 MODEX_TEXT @DL_STLExit . . . . . . . . . . L Near 05A1 MODEX_TEXT @DL_STLLoop . . . . . . . . . . L Near 0575 MODEX_TEXT @DL_STLnc2 . . . . . . . . . . . L Near 0588 MODEX_TEXT @DL_STLnc3 . . . . . . . . . . . L Near 059D MODEX_TEXT @DL_ShallowLeft . . . . . . . . L Near 0525 MODEX_TEXT @DL_ShallowRight . . . . . . . . L Near 05A7 MODEX_TEXT @DL_SteepLeft . . . . . . . . . L Near 0566 MODEX_TEXT @DL_SteepRight . . . . . . . . . L Near 05E5 MODEX_TEXT @DL_VLINE . . . . . . . . . . . L Near 0481 MODEX_TEXT @DL_VLoop . . . . . . . . . . . L Near 04B4 MODEX_TEXT @DL_XRSEG . . . . . . . . . . . L Near 0479 MODEX_TEXT @DP_WAIT0 . . . . . . . . . . . L Near 0706 MODEX_TEXT @DP_WAIT1 . . . . . . . . . . . L Near 071B MODEX_TEXT @DataSize . . . . . . . . . . . Number 0000h @FB_EXIT . . . . . . . . . . . . L Near 0404 MODEX_TEXT @FB_LEFT_CONT . . . . . . . . . L Near 037A MODEX_TEXT @FB_LEFT_LOOP . . . . . . . . . L Near 036A MODEX_TEXT @FB_L_PLANE_FLUSH . . . . . . . L Near 037C MODEX_TEXT @FB_MIDDLE_LOOP . . . . . . . . L Near 03C7 MODEX_TEXT @FB_NORMAL . . . . . . . . . . . L Near 034C MODEX_TEXT @FB_NOSWAP1 . . . . . . . . . . L Near 031F MODEX_TEXT @FB_NOSWAP2 . . . . . . . . . . L Near 0339 MODEX_TEXT @FB_ONE_BAND_ONLY . . . . . . . L Near 03D2 MODEX_TEXT @FB_ONE_LOOP . . . . . . . . . . L Near 03F4 MODEX_TEXT @FB_RIGHT_CONT . . . . . . . . . L Near 03B0 MODEX_TEXT @FB_RIGHT_LOOP . . . . . . . . . L Near 03A0 MODEX_TEXT @FB_RIGHT . . . . . . . . . . . L Near 037D MODEX_TEXT @FB_R_EDGE_FLUSH . . . . . . . . L Near 03B3 MODEX_TEXT @GPC_DECODE_CHAR_BYTE . . . . . L Near 080F MODEX_TEXT @GPC_EXIT . . . . . . . . . . . L Near 0897 MODEX_TEXT @GPC_LowChar . . . . . . . . . . L Near 07DB MODEX_TEXT @GPC_NEXT_LINE . . . . . . . . . L Near 0889 MODEX_TEXT @GPC_NO_LEFT0BITS . . . . . . . L Near 083C MODEX_TEXT @GPC_NO_LEFT1BITS . . . . . . . L Near 0831 MODEX_TEXT @GPC_NO_MIDDLE0BITS . . . . . . L Near 085E MODEX_TEXT @GPC_NO_MIDDLE1BITS . . . . . . L Near 0853 MODEX_TEXT @GPC_NO_RIGHT0BITS . . . . . . . L Near 0888 MODEX_TEXT @GPC_NO_RIGHT1BITS . . . . . . . L Near 087D MODEX_TEXT @GPC_Set_Char . . . . . . . . . L Near 07E3 MODEX_TEXT @Interface . . . . . . . . . . . Number 0000h @LDR_Load . . . . . . . . . . . L Near 0677 MODEX_TEXT @Model . . . . . . . . . . . . . Number 0004h @PS_Exit . . . . . . . . . . . . L Near 09AF MODEX_TEXT @PS_Print_It . . . . . . . . . . L Near 097B MODEX_TEXT @SAP_Exit . . . . . . . . . . . L Near 06E1 MODEX_TEXT @SDF_Set_Font . . . . . . . . . L Near 0A06 MODEX_TEXT @SDP_Exit . . . . . . . . . . . L Near 0720 MODEX_TEXT @SD_WAIT0 . . . . . . . . . . . L Near 0798 MODEX_TEXT @SD_WAIT1 . . . . . . . . . . . L Near 079D MODEX_TEXT @SMX_Exit . . . . . . . . . . . L Near 027B MODEX_TEXT @STRLoop . . . . . . . . . . . . L Near 05F4 MODEX_TEXT @STRnc2 . . . . . . . . . . . . L Near 0606 MODEX_TEXT @STRnc3 . . . . . . . . . . . . L Near 061A MODEX_TEXT @SVM_BadModeSetup . . . . . . . L Near 015C MODEX_TEXT @SVM_Continue . . . . . . . . . L Near 0161 MODEX_TEXT @SVM_EXIT . . . . . . . . . . . L Near 0247 MODEX_TEXT @SVM_Set_Data . . . . . . . . . L Near 01AA MODEX_TEXT @SVM_Set_Pages . . . . . . . . . L Near 0207 MODEX_TEXT @SVM_Setup_CRTC . . . . . . . . L Near 019D MODEX_TEXT @SVM_Setup_Table . . . . . . . . L Near 0193 MODEX_TEXT @SW_Exit . . . . . . . . . . . . L Near 0789 MODEX_TEXT @SW_WAIT0 . . . . . . . . . . . L Near 0761 MODEX_TEXT @SW_WAIT1 . . . . . . . . . . . L Near 0776 MODEX_TEXT @TB_COPY2 . . . . . . . . . . . L Near 0B6A MODEX_TEXT @TB_COPY_LINE . . . . . . . . . L Near 0B26 MODEX_TEXT @TB_COPY_LOOP . . . . . . . . . L Near 0B2E MODEX_TEXT @TB_COPY_PLANE . . . . . . . . . L Near 0B1B MODEX_TEXT @TB_COPY_REMAINDER . . . . . . . L Near 0B68 MODEX_TEXT @TB_Exit . . . . . . . . . . . . L Near 0BB0 MODEX_TEXT @TB_NEXT2 . . . . . . . . . . . L Near 0B87 MODEX_TEXT @TB_NEXT_LINE . . . . . . . . . L Near 0B79 MODEX_TEXT @TB_SKIP_01 . . . . . . . . . . L Near 0B39 MODEX_TEXT @TB_SKIP_02 . . . . . . . . . . L Near 0B45 MODEX_TEXT @TB_SKIP_03 . . . . . . . . . . L Near 0B51 MODEX_TEXT @TB_SKIP_04 . . . . . . . . . . L Near 0B5D MODEX_TEXT @TB_SKIP_05 . . . . . . . . . . L Near 0B75 MODEX_TEXT @TGP_DECODE_CHAR_BYTE . . . . . L Near 090D MODEX_TEXT @TGP_EXIT . . . . . . . . . . . L Near 096B MODEX_TEXT @TGP_LowChar . . . . . . . . . . L Near 08D9 MODEX_TEXT @TGP_NEXT_LINE . . . . . . . . . L Near 095E MODEX_TEXT @TGP_NO_LEFT1BITS . . . . . . . L Near 092D MODEX_TEXT @TGP_NO_MIDDLE1BITS . . . . . . L Near 0941 MODEX_TEXT @TGP_NO_RIGHT1BITS . . . . . . . L Near 095D MODEX_TEXT @TGP_Set_Char . . . . . . . . . L Near 08E1 MODEX_TEXT @TPS_Exit . . . . . . . . . . . L Near 09EC MODEX_TEXT @TPS_Print_It . . . . . . . . . L Near 09BC MODEX_TEXT @code . . . . . . . . . . . . . Text MODEX_TEXT @data . . . . . . . . . . . . . Text DGROUP @fardata? . . . . . . . . . . . Text FAR_BSS @fardata . . . . . . . . . . . . Text FAR_DATA @stack . . . . . . . . . . . . . Text DGROUP ACTIVE_PAGE . . . . . . . . . . Word 0012 _BSS ALL_PLANES_ON . . . . . . . . . Number 0F02h ALL_PLANES . . . . . . . . . . . Number 000Fh ASYNC_RESET . . . . . . . . . . Number 0100h ATTRIB_Ctrl . . . . . . . . . . Number 03C0h CHAIN4_OFF . . . . . . . . . . . Number 0604h CHARSET_HI . . . . . . . . . . . Word 0026 _BSS CHARSET_LOW . . . . . . . . . . Word 0022 _BSS CHAR_BITS . . . . . . . . . . . Number 000Fh CRTC_Data . . . . . . . . . . . Number 03D5h CRTC_Index . . . . . . . . . . . Number 03D4h CURRENT_MOFFSET . . . . . . . . Word 001C _BSS CURRENT_PAGE . . . . . . . . . . Word 0014 _BSS CURRENT_SEGMENT . . . . . . . . Word 0016 _BSS CURRENT_XOFFSET . . . . . . . . Word 0018 _BSS CURRENT_YOFFSET . . . . . . . . Word 001A _BSS Char_Plane_Data . . . . . . . . Byte 0008 MODEX_TEXT DAC_READ_ADDR . . . . . . . . . Number 03C7h DAC_WRITE_ADDR . . . . . . . . . Number 03C8h DISPLAY_PAGE . . . . . . . . . . Word 0010 _BSS False . . . . . . . . . . . . . Number 0000h GC_Index . . . . . . . . . . . . Number 03CEh GET_CHAR_PTR . . . . . . . . . . Number 1130h INPUT_1 . . . . . . . . . . . . Number 03DAh LAST_PAGE . . . . . . . . . . . Word 0004 _BSS LATCHES_OFF . . . . . . . . . . Number FF08h LATCHES_ON . . . . . . . . . . . Number 0008h Left_Clip_Mask . . . . . . . . . Byte 0000 MODEX_TEXT MAP_MASK_PLANE1 . . . . . . . . Number 0102h MAP_MASK_PLANE2 . . . . . . . . Number 1102h MAP_MASK . . . . . . . . . . . . Number 0002h MAX_XOFFSET . . . . . . . . . . Word 001E _BSS MAX_YOFFSET . . . . . . . . . . Word 0020 _BSS MISC_OUTPUT . . . . . . . . . . Number 03C2h MODE_200_Tall . . . . . . . . . L Near 0044 MODEX_TEXT MODE_240_Tall . . . . . . . . . L Near 0054 MODEX_TEXT MODE_320_Wide . . . . . . . . . L Near 0028 MODEX_TEXT MODE_320x200 . . . . . . . . . . L Near 0074 MODEX_TEXT MODE_320x240 . . . . . . . . . . L Near 00BC MODEX_TEXT MODE_320x400 . . . . . . . . . . L Near 0086 MODEX_TEXT MODE_320x480 . . . . . . . . . . L Near 00CE MODEX_TEXT MODE_360_Wide . . . . . . . . . L Near 0036 MODEX_TEXT MODE_360x200 . . . . . . . . . . L Near 00E0 MODEX_TEXT MODE_360x240 . . . . . . . . . . L Near 0098 MODEX_TEXT MODE_360x400 . . . . . . . . . . L Near 00F2 MODEX_TEXT MODE_360x480 . . . . . . . . . . L Near 00AA MODEX_TEXT MODE_400_Tall . . . . . . . . . L Near 0044 MODEX_TEXT MODE_480_Tall . . . . . . . . . L Near 0054 MODEX_TEXT MODE_Double_Line . . . . . . . . L Near 0020 MODEX_TEXT MODE_Single_Line . . . . . . . . L Near 0018 MODEX_TEXT MODE_TABLE . . . . . . . . . . . L Near 0064 MODEX_TEXT NUM_MODES . . . . . . . . . . . Number 0008h PAGE_ADDR . . . . . . . . . . . Word 0006 _BSS PAGE_SIZE . . . . . . . . . . . Word 000E _BSS PEL_DATA_REG . . . . . . . . . . Number 03C9h PIXEL_PAN_REG . . . . . . . . . Number 0033h PLANE_BITS . . . . . . . . . . . Number 0003h READ_MAP . . . . . . . . . . . . Number 0004h ROM_8x8_Hi . . . . . . . . . . . Number 0004h ROM_8x8_Lo . . . . . . . . . . . Number 0003h Right_Clip_Mask . . . . . . . . Byte 0004 MODEX_TEXT SCREEN_HEIGHT . . . . . . . . . Word 0002 _BSS SCREEN_WIDTH . . . . . . . . . . Word 0000 _BSS SC_Data . . . . . . . . . . . . Number 03C5h SC_Index . . . . . . . . . . . . Number 03C4h SEQU_RESTART . . . . . . . . . . Number 0300h START_DISP_HI . . . . . . . . . Number 000Ch START_DISP_LO . . . . . . . . . Number 000Dh True . . . . . . . . . . . . . . Number -0001h VERT_RETRACE . . . . . . . . . . Number 0008h VGA_Segment . . . . . . . . . . Number A000h 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