1 Microsoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
5 ;========================================================
\r
6 ; MODEX.ASM - A Complete Mode X Library
\r
8 ; Version 1.04 Release, 3 May 1993, By Matt Pritchard
\r
9 ; With considerable input from Michael Abrash
\r
11 ; The following information is donated to the public domain in
\r
12 ; the hopes that save other programmers much frustration.
\r
14 ; If you do use this code in a product, it would be nice if
\r
15 ; you include a line like "Mode X routines by Matt Pritchard"
\r
18 ; =========================================================
\r
20 ; All of this code is designed to be assembled with MASM 5.10a
\r
21 ; but TASM 3.0 could be used as well.
\r
23 ; The routines contained are designed for use in a MEDIUM model
\r
24 ; program. All Routines are FAR, and is assumed that a DGROUP
\r
25 ; data segment exists and that DS will point to it on entry.
\r
27 ; For all routines, the AX, BX, CX, DX, ES and FLAGS registers
\r
28 ; will not be preserved, while the DS, BP, SI and DI registers
\r
29 ; will be preserved.
\r
31 ; Unless specifically noted, All Parameters are assumed to be
\r
32 ; "PASSED BY VALUE". That is, the actual value is placed on
\r
33 ; the stack. When a reference is passed it is assumed to be
\r
34 ; a near pointer to a variable in the DGROUP segment.
\r
36 ; Routines that return a single 16-Bit integer value will
\r
37 ; return that value in the AX register.
\r
39 ; This code will *NOT* run on an 8086/8088 because 80286+
\r
40 ; specific instructions are used. If you have an 8088/86
\r
41 ; and VGA, you can buy an 80386-40 motherboard for about
\r
42 ; $160 and move into the 90's.
\r
44 ; This code is reasonably optimized: Most drawing loops have
\r
45 ; been unrolled once and memory references are minimized by
\r
46 ; keeping stuff in registers when possible.
\r
48 ; Error Trapping varies by Routine. No Clipping is performed
\r
49 ; so the caller should verify that all coordinates are valid.
\r
51 ; Several Macros are used to simplify common 2 or 3 instruction
\r
52 ; sequences. Several Single letter Text Constants also
\r
53 ; simplify common assembler expressions like "WORD PTR".
\r
55 ; ------------------ Mode X Variations ------------------
\r
57 ; Mode # Screen Size Max Pages Aspect Ratio (X:Y)
\r
59 ; 0 320 x 200 4 Pages 1.2:1
\r
60 ; 1 320 x 400 2 Pages 2.4:1
\r
61 ; 2 360 x 200 3 Pages 1.35:1
\r
62 ; 3 360 x 400 1 Page 2.7:1
\r
63 ; 4 320 x 240 3 Pages 1:1
\r
64 ; 5 320 x 480 1 Page 2:1
\r
65 ; 6 360 x 240 3 Pages 1.125:1
\r
66 ; 7 360 x 480 1 Page 2.25:1
\r
68 ; -------------------- The Legal Stuff ------------------
\r
70 ; No warranty, either written or implied, is made as to
\r
71 ; the accuracy and usability of this code product. Use
\r
72 ; at your own risk. Batteries not included. Pepperoni
\r
73 ; and extra cheese available for an additional charge.
\r
75 ; ----------------------- The Author --------------------
\r
77 ; Matt Pritchard is a paid programmer who'd rather be
\r
78 ; writing games. He can be reached at: P.O. Box 140264,
\r
79 ; Irving, TX 75014 USA. Michael Abrash is a living
\r
80 ; god, who now works for Bill Gates (Microsoft).
\r
82 ; -------------------- Revision History -----------------
\r
83 ; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI
\r
84 ; SET_MODEX now saves SI
\r
85 ; 5-3-93: v1.04 - added LOAD_DAC_REGISTERS and
\r
86 ; READ_DAC_REGISTERS. Expanded CLR Macro
\r
87 ; to handle multiple registers
\r
95 ; ===== MACROS =====
\r
97 ; Macro to OUT a 16 bit value to an I/O port
\r
99 OUT_16 MACRO Register, Value
\r
100 IFDIFI <Register>, <DX> ; If DX not setup
\r
101 MOV DX, Register ; then Select Register
\r
103 IFDIFI <Value>, <AX> ; If AX not setup
\r
104 MOV AX, Value ; then Get Data Value
\r
106 OUT DX, AX ; Set I/O Register(s)
\r
109 ; Macro to OUT a 8 bit value to an I/O Port
\r
111 OUT_8 MACRO Register, Value
\r
112 IFDIFI <Register>, <DX> ; If DX not setup
\r
113 MOV DX, Register ; then Select Register
\r
115 IFDIFI <Value>, <AL> ; If AL not Setup
\r
116 MOV AL, Value ; then Get Data Value
\r
118 OUT DX, AL ; Set I/O Register
\r
121 ; macros to PUSH and POP multiple registers
\r
123 PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8
\r
126 PUSHx R2, R3, R4, R5, R6, R7, R8
\r
130 POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8
\r
132 POP R1 ; Restore R1
\r
133 POPx R2, R3, R4, R5, R6, R7, R8
\r
137 ; Macro to Clear Registers to 0
\r
139 CLR MACRO Register, R2, R3, R4, R5, R6
\r
141 XOR Register, Register ; Set Register = 0
\r
142 CLR R2, R3, R4, R5, R6
\r
146 ; Macros to Decrement Counter & Jump on Condition
\r
148 LOOPx MACRO Register, Destination
\r
149 DEC Register ; Counter--
\r
150 JNZ Destination ; Jump if not 0
\r
153 LOOPjz MACRO Register, Destination
\r
154 DEC Register ; Counter--
\r
155 JZ Destination ; Jump if 0
\r
159 ; ===== General Constants =====
\r
165 = BYTE PTR b EQU BYTE PTR
\r
166 = WORD PTR w EQU WORD PTR
\r
167 = DWORD PTR d EQU DWORD PTR
\r
168 = OFFSET o EQU OFFSET
\r
169 = FAR PTR f EQU FAR PTR
\r
170 = SHORT s EQU SHORT
\r
171 = ?,?,?,? ?x4 EQU <?,?,?,?>
\r
172 = ?,?,? ?x3 EQU <?,?,?>
\r
174 ; ===== VGA Register Values =====
\r
176 = A000 VGA_Segment EQU 0A000h ; Vga Memory Segment
\r
178 = 03C0 ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller
\r
179 = 03CE GC_Index EQU 03CEh ; VGA Graphics Controller
\r
180 = 03C4 SC_Index EQU 03C4h ; VGA Sequencer Controller
\r
181 = 03C5 SC_Data EQU 03C5h ; VGA Sequencer Data Port
\r
182 = 03D4 CRTC_Index EQU 03D4h ; VGA CRT Controller
\r
183 = 03D5 CRTC_Data EQU 03D5h ; VGA CRT Controller Data
\r
184 = 03C2 MISC_OUTPUT EQU 03C2h ; VGA Misc Register
\r
185 = 03DA INPUT_1 EQU 03DAh ; Input Status #1 Register
\r
187 = 03C8 DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register
\r
188 = 03C7 DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register
\r
189 = 03C9 PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W
\r
191 = 0033 PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg
\r
192 = 0002 MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg
\r
193 = 0004 READ_MAP EQU 004h ; GC Index: Read Map Register
\r
194 = 000C START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi
\r
195 = 000D START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo
\r
197 = 0102 MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1
\r
198 = 1102 MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1
\r
199 = 0F02 ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes
\r
201 = 0604 CHAIN4_OFF EQU 00604h ; Chain 4 mode Off
\r
202 = 0100 ASYNC_RESET EQU 00100h ; (A)synchronous Reset
\r
203 = 0300 SEQU_RESTART EQU 00300h ; Sequencer Restart
\r
205 = 0008 LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches
\r
206 = FF08 LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU
\r
208 = 0008 VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit
\r
209 = 0003 PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane #
\r
210 = 000F ALL_PLANES EQU 0Fh ; All Bit Planes Selected
\r
211 = 000F CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data
\r
213 = 1130 GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set
\r
214 = 0003 ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer
\r
215 = 0004 ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer
\r
217 ; Constants Specific for these routines
\r
219 = 0008 NUM_MODES EQU 8 ; # of Mode X Variations
\r
221 ; Specific Mode Data Table format...
\r
223 000C Mode_Data_Table STRUC
\r
224 0000 00 M_MiscR DB ? ; Value of MISC_OUTPUT register
\r
225 0001 00 M_Pages DB ? ; Maximum Possible # of pages
\r
226 0002 0000 M_XSize DW ? ; X Size Displayed on screen
\r
227 0004 0000 M_YSize DW ? ; Y Size Displayed on screen
\r
228 0006 0000 M_XMax DW ? ; Maximum Possible X Size
\r
229 0008 0000 M_YMax DW ? ; Maximum Possible Y Size
\r
230 000A 0000 M_CRTC DW ? ; Table of CRTC register values
\r
231 Mode_Data_Table ENDS
\r
233 ; ===== DGROUP STORAGE NEEDED (42 BYTES) =====
\r
237 0000 0000 SCREEN_WIDTH DW 0 ; Width of a line in Bytes
\r
238 0002 0000 SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels
\r
240 0004 0000 LAST_PAGE DW 0 ; # of Display Pages
\r
241 0006 0004 [ PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page
\r
245 000E 0000 PAGE_SIZE DW 0 ; Size of Page in Addr Bytes
\r
247 0010 0000 DISPLAY_PAGE DW 0 ; Page # currently displayed
\r
248 0012 0000 ACTIVE_PAGE DW 0 ; Page # currently active
\r
250 0014 0000 CURRENT_PAGE DW 0 ; Offset of current Page
\r
251 0016 0000 CURRENT_SEGMENT DW 0 ; Segment of VGA memory
\r
253 0018 0000 CURRENT_XOFFSET DW 0 ; Current Display X Offset
\r
254 001A 0000 CURRENT_YOFFSET DW 0 ; Current Display Y Offset
\r
256 001C 0000 CURRENT_MOFFSET DW 0 ; Current Start Offset
\r
258 001E 0000 MAX_XOFFSET DW 0 ; Current Display X Offset
\r
259 0020 0000 MAX_YOFFSET DW 0 ; Current Display Y Offset
\r
261 0022 0000 0000 CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127
\r
262 0026 0000 0000 CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255
\r
266 ; ===== DATA TABLES =====
\r
268 ; Data Tables, Put in Code Segment for Easy Access
\r
269 ; (Like when all the other Segment Registers are in
\r
270 ; use!!) and reduced DGROUP requirements...
\r
272 ; Bit Mask Tables for Left/Right/Character Masks
\r
274 0000 0F 0E 0C 08 Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H
\r
276 0004 01 03 07 0F Right_Clip_Mask DB 01H, 03H, 07H, 0FH
\r
278 ; Bit Patterns for converting character fonts
\r
280 0008 00 08 04 0C 02 0A Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH
\r
282 0010 01 09 05 0D 03 0B DB 01H,09H,05H,0DH,03H,0BH,07H,0FH
\r
285 ; CRTC Register Values for Various Configurations
\r
287 0018 MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes
\r
288 0018 4009 DW 04009H ; Cell Height (1 Scan Line)
\r
289 001A 0014 DW 00014H ; Dword Mode off
\r
290 001C E317 DW 0E317H ; turn on Byte Mode
\r
291 001E 0000 DW nil ; End of CRTC Data for 400/480 Line Mode
\r
293 0020 MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes
\r
294 0020 4109 DW 04109H ; Cell Height (2 Scan Lines)
\r
295 0022 0014 DW 00014H ; Dword Mode off
\r
296 0024 E317 DW 0E317H ; turn on Byte Mode
\r
297 0026 0000 DW nil ; End of CRTC Data for 200/240 Line Mode
\r
299 0028 MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels
\r
300 0028 5F00 DW 05F00H ; Horz total
\r
301 002A 4F01 DW 04F01H ; Horz Displayed
\r
302 002C 5002 DW 05002H ; Start Horz Blanking
\r
303 002E 8203 DW 08203H ; End Horz Blanking
\r
304 0030 5404 DW 05404H ; Start H Sync
\r
305 0032 8005 DW 08005H ; End H Sync
\r
306 0034 0000 DW nil ; End of CRTC Data for 320 Horz pixels
\r
308 0036 MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels
\r
309 0036 6B00 DW 06B00H ; Horz total
\r
310 0038 5901 DW 05901H ; Horz Displayed
\r
311 003A 5A02 DW 05A02H ; Start Horz Blanking
\r
312 003C 8E03 DW 08E03H ; End Horz Blanking
\r
313 003E 5E04 DW 05E04H ; Start H Sync
\r
314 0040 8A05 DW 08A05H ; End H Sync
\r
315 0042 0000 DW nil ; End of CRTC Data for 360 Horz pixels
\r
317 0044 MODE_200_Tall:
\r
318 0044 MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes
\r
319 0044 BF06 DW 0BF06H ; Vertical Total
\r
320 0046 1F07 DW 01F07H ; Overflow
\r
321 0048 9C10 DW 09C10H ; V Sync Start
\r
322 004A 8E11 DW 08E11H ; V Sync End/Prot Cr0 Cr7
\r
323 004C 8F12 DW 08F12H ; Vertical Displayed
\r
324 004E 9615 DW 09615H ; V Blank Start
\r
325 0050 B916 DW 0B916H ; V Blank End
\r
326 0052 0000 DW nil ; End of CRTC Data for 200/400 Lines
\r
328 0054 MODE_240_Tall:
\r
329 0054 MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes
\r
330 0054 0D06 DW 00D06H ; Vertical Total
\r
331 0056 3E07 DW 03E07H ; Overflow
\r
332 0058 EA10 DW 0EA10H ; V Sync Start
\r
333 005A 8C11 DW 08C11H ; V Sync End/Prot Cr0 Cr7
\r
334 005C DF12 DW 0DF12H ; Vertical Displayed
\r
335 005E E715 DW 0E715H ; V Blank Start
\r
336 0060 0616 DW 00616H ; V Blank End
\r
337 0062 0000 DW nil ; End of CRTC Data for 240/480 Lines
\r
339 ; Table of Display Mode Tables
\r
342 0064 0074 R 0086 R DW o MODE_320x200, o MODE_320x400
\r
343 0068 00E0 R 00F2 R DW o MODE_360x200, o MODE_360x400
\r
344 006C 00BC R 00CE R DW o MODE_320x240, o MODE_320x480
\r
345 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
346 modex.asm Page 2 - 1
\r
349 0070 0098 R 00AA R DW o MODE_360x240, o MODE_360x480
\r
351 ; Table of Display Mode Components
\r
353 0074 MODE_320x200: ; Data for 320 by 200 Pixels
\r
355 0074 63 DB 063h ; 400 scan Lines & 25 Mhz Clock
\r
356 0075 04 DB 4 ; Maximum of 4 Pages
\r
357 0076 0140 00C8 DW 320, 200 ; Displayed Pixels (X,Y)
\r
358 007A 0516 0330 DW 1302, 816 ; Max Possible X and Y Sizes
\r
360 007E 0028 R 0044 R DW o MODE_320_Wide, o MODE_200_Tall
\r
361 0082 0020 R 0000 DW o MODE_Double_Line, nil
\r
363 0086 MODE_320x400: ; Data for 320 by 400 Pixels
\r
365 0086 63 DB 063h ; 400 scan Lines & 25 Mhz Clock
\r
366 0087 02 DB 2 ; Maximum of 2 Pages
\r
367 0088 0140 0190 DW 320, 400 ; Displayed Pixels X,Y
\r
368 008C 0288 0330 DW 648, 816 ; Max Possible X and Y Sizes
\r
370 0090 0028 R 0044 R DW o MODE_320_Wide, o MODE_400_Tall
\r
371 0094 0018 R 0000 DW o MODE_Single_Line, nil
\r
373 0098 MODE_360x240: ; Data for 360 by 240 Pixels
\r
375 0098 E7 DB 0E7h ; 480 scan Lines & 28 Mhz Clock
\r
376 0099 03 DB 3 ; Maximum of 3 Pages
\r
377 009A 0168 00F0 DW 360, 240 ; Displayed Pixels X,Y
\r
378 009E 0444 02D8 DW 1092, 728 ; Max Possible X and Y Sizes
\r
380 00A2 0036 R 0054 R DW o MODE_360_Wide, o MODE_240_Tall
\r
381 00A6 0020 R 0000 DW o MODE_Double_Line , nil
\r
383 00AA MODE_360x480: ; Data for 360 by 480 Pixels
\r
385 00AA E7 DB 0E7h ; 480 scan Lines & 28 Mhz Clock
\r
386 00AB 01 DB 1 ; Only 1 Page Possible
\r
387 00AC 0168 01E0 DW 360, 480 ; Displayed Pixels X,Y
\r
388 00B0 0220 02D8 DW 544, 728 ; Max Possible X and Y Sizes
\r
390 00B4 0036 R 0054 R DW o MODE_360_Wide, o MODE_480_Tall
\r
391 00B8 0018 R 0000 DW o MODE_Single_Line , nil
\r
393 00BC MODE_320x240: ; Data for 320 by 240 Pixels
\r
395 00BC E3 DB 0E3h ; 480 scan Lines & 25 Mhz Clock
\r
396 00BD 03 DB 3 ; Maximum of 3 Pages
\r
397 00BE 0140 00F0 DW 320, 240 ; Displayed Pixels X,Y
\r
398 00C2 0440 0332 DW 1088, 818 ; Max Possible X and Y Sizes
\r
400 00C6 0028 R 0054 R DW o MODE_320_Wide, o MODE_240_Tall
\r
401 00CA 0020 R 0000 DW o MODE_Double_Line, nil
\r
403 00CE MODE_320x480: ; Data for 320 by 480 Pixels
\r
405 00CE E3 DB 0E3h ; 480 scan Lines & 25 Mhz Clock
\r
406 00CF 01 DB 1 ; Only 1 Page Possible
\r
407 00D0 0140 01E0 DW 320, 480 ; Displayed Pixels X,Y
\r
408 00D4 021C 0332 DW 540, 818 ; Max Possible X and Y Sizes
\r
410 00D8 0028 R 0054 R DW o MODE_320_WIDE, o MODE_480_Tall
\r
411 00DC 0018 R 0000 DW o MODE_Single_Line, nil
\r
413 00E0 MODE_360x200: ; Data for 360 by 200 Pixels
\r
415 00E0 67 DB 067h ; 400 scan Lines & 28 Mhz Clock
\r
416 00E1 03 DB 3 ; Maximum of 3 Pages
\r
417 00E2 0168 00C8 DW 360, 200 ; Displayed Pixels (X,Y)
\r
418 00E6 0516 02D8 DW 1302, 728 ; Max Possible X and Y Sizes
\r
420 00EA 0036 R 0044 R DW o MODE_360_Wide, MODE_200_Tall
\r
421 00EE 0020 R 0000 DW o MODE_Double_Line, nil
\r
423 00F2 MODE_360x400: ; Data for 360 by 400 Pixels
\r
425 00F2 67 DB 067h ; 400 scan Lines & 28 Mhz Clock
\r
426 00F3 01 DB 1 ; Maximum of 1 Pages
\r
427 00F4 0168 0190 DW 360, 400 ; Displayed Pixels X,Y
\r
428 00F8 0288 0330 DW 648, 816 ; Max Possible X and Y Sizes
\r
430 00FC 0036 R 0044 R DW o MODE_360_Wide, MODE_400_Tall
\r
431 0100 0018 R 0000 DW o MODE_Single_Line, nil
\r
434 ; ===== MODE X SETUP ROUTINES =====
\r
436 ;======================================================
\r
437 ;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%)
\r
438 ;======================================================
\r
440 ; Sets Up the specified version of Mode X. Allows for
\r
441 ; the setup of multiple video pages, and a virtual
\r
442 ; screen which can be larger than the displayed screen
\r
443 ; (which can then be scrolled a pixel at a time)
\r
445 ; ENTRY: ModeType = Desired Screen Resolution (0-7)
\r
447 ; 0 = 320 x 200, 4 Pages max, 1.2:1 Aspect Ratio
\r
448 ; 1 = 320 x 400, 2 Pages max, 2.4:1 Aspect Ratio
\r
449 ; 2 = 360 x 200, 3 Pages max, 1.35:1 Aspect Ratio
\r
450 ; 3 = 360 x 400, 1 Page max, 2.7:1 Aspect Ratio
\r
451 ; 4 = 320 x 240, 3 Pages max, 1:1 Aspect Ratio
\r
452 ; 5 = 320 x 480, 1 Page max, 2:1 Aspect Ratio
\r
453 ; 6 = 360 x 240, 3 Pages max, 1.125:1 Aspect Ratio
\r
454 ; 7 = 360 x 480, 1 Page max, 2.25:1 Aspect Ratio
\r
456 ; MaxXpos = The Desired Virtual Screen Width
\r
457 ; MaxYpos = The Desired Virtual Screen Height
\r
458 ; Pages = The Desired # of Video Pages
\r
460 ; EXIT: AX = Success Flag: 0 = Failure / -1= Success
\r
463 0016 SVM_STACK STRUC
\r
464 0000 0000 SVM_Table DW ? ; Offset of Mode Info Table
\r
465 0002 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP
\r
467 000A 00000000 DD ? ; Caller
\r
468 000E 0000 SVM_Pages DW ? ; # of Screen Pages desired
\r
469 0010 0000 SVM_Ysize DW ? ; Vertical Screen Size Desired
\r
470 0012 0000 SVM_Xsize DW ? ; Horizontal Screen Size Desired
\r
471 0014 0000 SVM_Mode DW ? ; Display Resolution Desired
\r
474 PUBLIC SET_VGA_MODEX
\r
476 0104 SET_VGA_MODEX PROC FAR
\r
478 PUSHx BP, DS, SI, DI ; Preserve Important Registers
\r
479 0104 55 1 PUSH BP ; Save R1
\r
480 0105 1E 2 PUSH DS ; Save R1
\r
481 0106 56 3 PUSH SI ; Save R1
\r
482 0107 57 4 PUSH DI ; Save R1
\r
483 0108 83 EC 02 SUB SP, 2 ; Allocate workspace
\r
484 010B 8B EC MOV BP, SP ; Set up Stack Frame
\r
486 ; Check Legality of Mode Request....
\r
488 010D 8B 5E 14 MOV BX, [BP].SVM_Mode ; Get Requested Mode #
\r
489 0110 83 FB 08 CMP BX, NUM_MODES ; Is it 0..7?
\r
490 0113 73 47 JAE @SVM_BadModeSetup ; If Not, Error out
\r
492 0115 D1 E3 SHL BX, 1 ; Scale BX
\r
493 0117 2E: 8B B7 0064 R MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info
\r
494 011C 89 76 00 MOV [BP].SVM_Table, SI ; Save ptr for later use
\r
496 ; Check # of Requested Display Pages
\r
498 011F 8B 4E 0E MOV CX, [BP].SVM_Pages ; Get # of Requested Pages
\r
499 CLR CH ; Set Hi Word = 0!
\r
500 0122 32 ED 1 XOR CH, CH ; Set Register = 0
\r
501 0124 2E: 3A 4C 01 CMP CL, CS:[SI].M_Pages ; Check # Pages for mode
\r
502 0128 77 32 JA @SVM_BadModeSetup ; Report Error if too Many Pages
\r
503 012A E3 30 JCXZ @SVM_BadModeSetup ; Report Error if 0 Pages
\r
505 ; Check Validity of X Size
\r
507 012C 83 66 12 F8 AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0
\r
509 0130 8B 46 12 MOV AX, [BP].SVM_XSize ; Get Logical Screen Width
\r
510 0133 2E: 3B 44 02 CMP AX, CS:[SI].M_XSize ; Check against Displayed X
\r
511 0137 72 23 JB @SVM_BadModeSetup ; Report Error if too small
\r
512 0139 2E: 3B 44 06 CMP AX, CS:[SI].M_XMax ; Check against Max X
\r
513 013D 77 1D JA @SVM_BadModeSetup ; Report Error if too big
\r
515 ; Check Validity of Y Size
\r
517 013F 8B 5E 10 MOV BX, [BP].SVM_YSize ; Get Logical Screen Height
\r
518 0142 2E: 3B 5C 04 CMP BX, CS:[SI].M_YSize ; Check against Displayed Y
\r
519 0146 72 14 JB @SVM_BadModeSetup ; Report Error if too small
\r
520 0148 2E: 3B 5C 08 CMP BX, CS:[SI].M_YMax ; Check against Max Y
\r
521 014C 77 0E JA @SVM_BadModeSetup ; Report Error if too big
\r
523 ; Enough memory to Fit it all?
\r
525 014E C1 E8 02 SHR AX, 2 ; # of Bytes:Line = XSize/4
\r
526 0151 F7 E1 MUL CX ; AX = Bytes/Line * Pages
\r
527 0153 F7 E3 MUL BX ; DX:AX = Total VGA mem needed
\r
528 0155 71 0A JNO @SVM_Continue ; Exit if Total Size > 256K
\r
530 0157 4A DEC DX ; Was it Exactly 256K???
\r
531 0158 0B D0 OR DX, AX ; (DX = 1, AX = 0000)
\r
532 015A 74 05 JZ @SVM_Continue ; if so, it's valid...
\r
534 015C @SVM_BadModeSetup:
\r
536 CLR AX ; Return Value = False
\r
537 015C 33 C0 1 XOR AX, AX ; Set Register = 0
\r
538 015E E9 00E6 JMP @SVM_Exit ; Normal Exit
\r
540 0161 @SVM_Continue:
\r
542 0161 B8 0013 MOV AX, 13H ; Start with Mode 13H
\r
543 0164 CD 10 INT 10H ; Let BIOS Set Mode
\r
545 OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode
\r
546 0166 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register
\r
547 0169 B8 0604 1 MOV AX, CHAIN4_OFF ; then Get Data Value
\r
548 016C EF 1 OUT DX, AX ; Set I/O Register(s)
\r
549 OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset
\r
550 016D BA 03C4 1 MOV DX, SC_INDEX ; then Select Register
\r
551 0170 B8 0100 1 MOV AX, ASYNC_RESET ; then Get Data Value
\r
552 0173 EF 1 OUT DX, AX ; Set I/O Register(s)
\r
553 OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size
\r
554 0174 BA 03C2 1 MOV DX, MISC_OUTPUT ; then Select Register
\r
555 0177 2E: 8A 04 1 MOV AL, CS:[SI].M_MiscR ; then Get Data Value
\r
556 017A EE 1 OUT DX, AL ; Set I/O Register
\r
557 OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ...
\r
558 017B BA 03C4 1 MOV DX, SC_INDEX ; then Select Register
\r
559 017E B8 0300 1 MOV AX, SEQU_RESTART ; then Get Data Value
\r
560 0181 EF 1 OUT DX, AX ; Set I/O Register(s)
\r
562 OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register
\r
563 0182 BA 03D4 1 MOV DX, CRTC_INDEX ; then Select Register
\r
564 0185 B0 11 1 MOV AL, 11H ; then Get Data Value
\r
565 0187 EE 1 OUT DX, AL ; Set I/O Register
\r
566 0188 42 INC DX ; Point to Data
\r
567 0189 EC IN AL, DX ; Get Value, Bit 7 = Protect
\r
568 018A 24 7F AND AL, 7FH ; Mask out Write Protect
\r
569 018C EE OUT DX, AL ; And send it back
\r
571 018D BA 03D4 MOV DX, CRTC_INDEX ; Vga Crtc Registers
\r
572 0190 83 C6 0A ADD SI, M_CRTC ; SI -> CRTC Parameter Data
\r
574 ; Load Tables of CRTC Parameters from List of Tables
\r
576 0193 @SVM_Setup_Table:
\r
578 0193 2E: 8B 3C MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl
\r
579 0196 83 C6 02 ADD SI, 2 ; Point to next Ptr Entry
\r
580 0199 0B FF OR DI, DI ; A nil Ptr means that we have
\r
581 019B 74 0D JZ @SVM_Set_Data ; finished CRTC programming
\r
583 019D @SVM_Setup_CRTC:
\r
584 019D 2E: 8B 05 MOV AX, CS:[DI] ; Get CRTC Data from Table
\r
585 01A0 83 C7 02 ADD DI, 2 ; Advance Pointer
\r
586 01A3 0B C0 OR AX, AX ; At End of Data Table?
\r
587 01A5 74 EC JZ @SVM_Setup_Table ; If so, Exit & get next Table
\r
589 01A7 EF OUT DX, AX ; Reprogram VGA CRTC reg
\r
590 01A8 EB F3 JMP s @SVM_Setup_CRTC ; Process Next Table Entry
\r
592 ; Initialize Page & Scroll info, DI = 0
\r
594 01AA @SVM_Set_Data:
\r
595 01AA 89 3E 0010 R MOV DISPLAY_PAGE, DI ; Display Page = 0
\r
596 01AE 89 3E 0012 R MOV ACTIVE_PAGE, DI ; Active Page = 0
\r
597 01B2 89 3E 0014 R MOV CURRENT_PAGE, DI ; Current Page (Offset) = 0
\r
598 01B6 89 3E 0018 R MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0
\r
599 01BA 89 3E 001A R MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0
\r
600 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
601 modex.asm Page 3 - 1
\r
604 01BE 89 3E 001C R MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0
\r
606 01C2 B8 A000 MOV AX, VGA_SEGMENT ; Segment for VGA memory
\r
607 01C5 A3 0016 R MOV CURRENT_SEGMENT, AX ; Save for Future LES's
\r
609 ; Set Logical Screen Width, X Scroll and Our Data
\r
611 01C8 8B 76 00 MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info
\r
612 01CB 8B 46 12 MOV AX, [BP].SVM_Xsize ; Get Display Width
\r
614 01CE 8B C8 MOV CX, AX ; CX = Logical Width
\r
615 01D0 2E: 2B 4C 02 SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value
\r
616 01D4 89 0E 001E R MOV MAX_XOFFSET, CX ; Set Maximum X Scroll
\r
618 01D8 C1 E8 02 SHR AX, 2 ; Bytes = Pixels / 4
\r
619 01DB A3 0000 R MOV SCREEN_WIDTH, AX ; Save Width in Pixels
\r
621 01DE D1 E8 SHR AX, 1 ; Offset Value = Bytes / 2
\r
622 01E0 B4 13 MOV AH, 13h ; CRTC Offset Register Index
\r
623 01E2 86 C4 XCHG AL, AH ; Switch format for OUT
\r
624 01E4 EF OUT DX, AX ; Set VGA CRTC Offset Reg
\r
626 ; Setup Data table, Y Scroll, Misc for Other Routines
\r
628 01E5 8B 46 10 MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height
\r
630 01E8 8B C8 MOV CX, AX ; CX = Logical Height
\r
631 01EA 2E: 2B 5C 04 SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value
\r
632 01EE 89 0E 0020 R MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll
\r
634 01F2 A3 0002 R MOV SCREEN_HEIGHT, AX ; Save Height in Pixels
\r
635 01F5 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Page Size in Bytes,
\r
636 01F9 A3 000E R MOV PAGE_SIZE, AX ; Save Page Size
\r
638 01FC 8B 4E 0E MOV CX, [BP].SVM_Pages ; Get # of Pages
\r
639 01FF 89 0E 0004 R MOV LAST_PAGE, CX ; Save # of Pages
\r
641 CLR BX ; Page # = 0
\r
642 0203 33 DB 1 XOR BX, BX ; Set Register = 0
\r
643 0205 8B D3 MOV DX, BX ; Page 0 Offset = 0
\r
645 0207 @SVM_Set_Pages:
\r
647 0207 89 97 0006 R MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset
\r
648 020B 83 C3 02 ADD BX, 2 ; Page#++
\r
649 020E 03 D0 ADD DX, AX ; Compute Addr of Next Page
\r
650 LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set
\r
651 0210 49 1 DEC CX ; Counter--
\r
652 0211 75 F4 1 JNZ @SVM_Set_Pages ; Jump if not 0
\r
656 OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes
\r
657 0213 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register
\r
658 0216 B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value
\r
659 0219 EF 1 OUT DX, AX ; Set I/O Register(s)
\r
660 021A C4 3E 0014 R LES DI, d CURRENT_PAGE ; -> Start of VGA memory
\r
663 021E 33 C0 1 XOR AX, AX ; Set Register = 0
\r
664 0220 FC CLD ; Block Xfer Forwards
\r
665 0221 B9 8000 MOV CX, 8000H ; 32K * 4 * 2 = 256K
\r
666 0224 F3/ AB REP STOSW ; Clear dat memory!
\r
668 ; Setup Font Pointers
\r
670 0226 B7 03 MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127
\r
671 0228 B8 1130 MOV AX, GET_CHAR_PTR ; Service to Get Pointer
\r
672 022B CD 10 INT 10h ; Call VGA BIOS
\r
674 022D 89 2E 0022 R MOV CHARSET_LOW, BP ; Save Char Set Offset
\r
675 0231 8C 06 0024 R MOV CHARSET_LOW+2, ES ; Save Char Set Segment
\r
677 0235 B7 04 MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255
\r
678 0237 B8 1130 MOV AX, GET_CHAR_PTR ; Service to Get Pointer
\r
679 023A CD 10 INT 10h ; Call VGA BIOS
\r
681 023C 89 2E 0026 R MOV CHARSET_HI, BP ; Save Char Set Offset
\r
682 0240 8C 06 0028 R MOV CHARSET_HI+2, ES ; Save Char Set Segment
\r
684 0244 B8 FFFF MOV AX, True ; Return Success Code
\r
687 0247 83 C4 02 ADD SP, 2 ; Deallocate workspace
\r
688 POPx DI, SI, DS, BP ; Restore Saved Registers
\r
689 024A 5F 1 POP DI ; Restore R1
\r
690 024B 5E 2 POP SI ; Restore R1
\r
691 024C 1F 3 POP DS ; Restore R1
\r
692 024D 5D 4 POP BP ; Restore R1
\r
693 024E CA 0008 RET 8 ; Exit & Clean Up Stack
\r
695 0251 SET_VGA_MODEX ENDP
\r
698 ;==================
\r
699 ;SET_MODEX% (Mode%)
\r
700 ;==================
\r
702 ; Quickie Mode Set - Sets Up Mode X to Default Configuration
\r
704 ; ENTRY: ModeType = Desired Screen Resolution (0-7)
\r
705 ; (See SET_VGA_MODEX for list)
\r
707 ; EXIT: AX = Success Flag: 0 = Failure / -1= Success
\r
710 000A SM_STACK STRUC
\r
711 0000 0000 0000 DW ?,? ; BP, SI
\r
712 0004 00000000 DD ? ; Caller
\r
713 0008 0000 SM_Mode DW ? ; Desired Screen Resolution
\r
718 0251 SET_MODEX PROC FAR
\r
720 PUSHx BP, SI ; Preserve Important registers
\r
721 0251 55 1 PUSH BP ; Save R1
\r
722 0252 56 2 PUSH SI ; Save R1
\r
723 0253 8B EC MOV BP, SP ; Set up Stack Frame
\r
725 CLR AX ; Assume Failure
\r
726 0255 33 C0 1 XOR AX, AX ; Set Register = 0
\r
727 0257 8B 5E 08 MOV BX, [BP].SM_Mode ; Get Desired Mode #
\r
728 025A 83 FB 08 CMP BX, NUM_MODES ; Is it a Valid Mode #?
\r
729 025D 73 1C JAE @SMX_Exit ; If Not, don't Bother
\r
731 025F 53 PUSH BX ; Push Mode Parameter
\r
733 0260 D1 E3 SHL BX, 1 ; Scale BX to word Index
\r
734 0262 2E: 8B B7 0064 R MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info
\r
736 0267 2E: FF 74 02 PUSH CS:[SI].M_XSize ; Push Default X Size
\r
737 026B 2E: FF 74 04 PUSH CS:[SI].M_Ysize ; Push Default Y size
\r
738 026F 2E: 8A 44 01 MOV AL, CS:[SI].M_Pages ; Get Default # of Pages
\r
739 CLR AH ; Hi Byte = 0
\r
740 0273 32 E4 1 XOR AH, AH ; Set Register = 0
\r
741 0275 50 PUSH AX ; Push # Pages
\r
743 0276 9A ---- 0104 R CALL f SET_VGA_MODEX ; Set up Mode X!
\r
746 POPx SI, BP ; Restore Registers
\r
747 027B 5E 1 POP SI ; Restore R1
\r
748 027C 5D 2 POP BP ; Restore R1
\r
749 027D CA 0002 RET 2 ; Exit & Clean Up Stack
\r
751 0280 SET_MODEX ENDP
\r
754 ; ===== BASIC GRAPHICS PRIMITIVES =====
\r
756 ;============================
\r
757 ;CLEAR_VGA_SCREEN (ColorNum%)
\r
758 ;============================
\r
760 ; Clears the active display page
\r
762 ; ENTRY: ColorNum = Color Value to fill the page with
\r
764 ; EXIT: No meaningful values returned
\r
767 000A CVS_STACK STRUC
\r
768 0000 0000 0000 DW ?,? ; DI, BP
\r
769 0004 00000000 DD ? ; Caller
\r
770 0008 00 00 CVS_COLOR DB ?,? ; Color to Set Screen to
\r
773 PUBLIC CLEAR_VGA_SCREEN
\r
775 0280 CLEAR_VGA_SCREEN PROC FAR
\r
777 PUSHx BP, DI ; Preserve Important Registers
\r
778 0280 55 1 PUSH BP ; Save R1
\r
779 0281 57 2 PUSH DI ; Save R1
\r
780 0282 8B EC MOV BP, SP ; Set up Stack Frame
\r
782 OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes
\r
783 0284 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register
\r
784 0287 B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value
\r
785 028A EF 1 OUT DX, AX ; Set I/O Register(s)
\r
786 028B C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
788 028F 8A 46 08 MOV AL, [BP].CVS_COLOR ; Get Color
\r
789 0292 8A E0 MOV AH, AL ; Copy for Word Write
\r
790 0294 FC CLD ; Block fill Forwards
\r
792 0295 8B 0E 000E R MOV CX, PAGE_SIZE ; Get Size of Page
\r
793 0299 D1 E9 SHR CX, 1 ; Divide by 2 for Words
\r
794 029B F3/ AB REP STOSW ; Block Fill VGA memory
\r
796 POPx DI, BP ; Restore Saved Registers
\r
797 029D 5F 1 POP DI ; Restore R1
\r
798 029E 5D 2 POP BP ; Restore R1
\r
799 029F CA 0002 RET 2 ; Exit & Clean Up Stack
\r
801 02A2 CLEAR_VGA_SCREEN ENDP
\r
804 ;===================================
\r
805 ;SET_POINT (Xpos%, Ypos%, ColorNum%)
\r
806 ;===================================
\r
808 ; Plots a single Pixel on the active display page
\r
810 ; ENTRY: Xpos = X position to plot pixel at
\r
811 ; Ypos = Y position to plot pixel at
\r
812 ; ColorNum = Color to plot pixel with
\r
814 ; EXIT: No meaningful values returned
\r
817 000E SP_STACK STRUC
\r
818 0000 0000 0000 DW ?,? ; BP, DI
\r
819 0004 00000000 DD ? ; Caller
\r
820 0008 00 00 SETP_Color DB ?,? ; Color of Point to Plot
\r
821 000A 0000 SETP_Ypos DW ? ; Y pos of Point to Plot
\r
822 000C 0000 SETP_Xpos DW ? ; X pos of Point to Plot
\r
827 02A2 SET_POINT PROC FAR
\r
829 PUSHx BP, DI ; Preserve Registers
\r
830 02A2 55 1 PUSH BP ; Save R1
\r
831 02A3 57 2 PUSH DI ; Save R1
\r
832 02A4 8B EC MOV BP, SP ; Set up Stack Frame
\r
834 02A6 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
836 02AA 8B 46 0A MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel
\r
837 02AD F7 26 0000 R MUL SCREEN_WIDTH ; Get Offset to Start of Line
\r
839 02B1 8B 5E 0C MOV BX, [BP].SETP_Xpos ; Get Xpos
\r
840 02B4 8B CB MOV CX, BX ; Copy to extract Plane # from
\r
841 02B6 C1 EB 02 SHR BX, 2 ; X offset (Bytes) = Xpos/4
\r
842 02B9 03 D8 ADD BX, AX ; Offset = Width*Ypos + Xpos/4
\r
844 02BB B8 0102 MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register
\r
845 02BE 80 E1 03 AND CL, PLANE_BITS ; Get Plane Bits
\r
846 02C1 D2 E4 SHL AH, CL ; Get Plane Select Value
\r
847 OUT_16 SC_Index, AX ; Select Plane
\r
848 02C3 BA 03C4 1 MOV DX, SC_Index ; then Select Register
\r
849 02C6 EF 1 OUT DX, AX ; Set I/O Register(s)
\r
851 02C7 8A 46 08 MOV AL,[BP].SETP_Color ; Get Pixel Color
\r
852 02CA 26: 88 01 MOV ES:[DI+BX], AL ; Draw Pixel
\r
854 POPx DI, BP ; Restore Saved Registers
\r
855 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
856 modex.asm Page 4 - 1
\r
859 02CD 5F 1 POP DI ; Restore R1
\r
860 02CE 5D 2 POP BP ; Restore R1
\r
861 02CF CA 0006 RET 6 ; Exit and Clean up Stack
\r
863 02D2 SET_POINT ENDP
\r
866 ;==========================
\r
867 ;READ_POINT% (Xpos%, Ypos%)
\r
868 ;==========================
\r
870 ; Read the color of a pixel from the Active Display Page
\r
872 ; ENTRY: Xpos = X position of pixel to read
\r
873 ; Ypos = Y position of pixel to read
\r
875 ; EXIT: AX = Color of Pixel at (Xpos, Ypos)
\r
878 000C RP_STACK STRUC
\r
879 0000 0000 0000 DW ?,? ; BP, DI
\r
880 0004 00000000 DD ? ; Caller
\r
881 0008 0000 RP_Ypos DW ? ; Y pos of Point to Read
\r
882 000A 0000 RP_Xpos DW ? ; X pos of Point to Read
\r
887 02D2 READ_POINT PROC FAR
\r
889 PUSHx BP, DI ; Preserve Registers
\r
890 02D2 55 1 PUSH BP ; Save R1
\r
891 02D3 57 2 PUSH DI ; Save R1
\r
892 02D4 8B EC MOV BP, SP ; Set up Stack Frame
\r
894 02D6 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
896 02DA 8B 46 08 MOV AX, [BP].RP_Ypos ; Get Line # of Pixel
\r
897 02DD F7 26 0000 R MUL SCREEN_WIDTH ; Get Offset to Start of Line
\r
899 02E1 8B 5E 0A MOV BX, [BP].RP_Xpos ; Get Xpos
\r
900 02E4 8B CB MOV CX, BX
\r
901 02E6 C1 EB 02 SHR BX, 2 ; X offset (Bytes) = Xpos/4
\r
902 02E9 03 D8 ADD BX, AX ; Offset = Width*Ypos + Xpos/4
\r
904 02EB B0 04 MOV AL, READ_MAP ; GC Read Mask Register
\r
905 02ED 8A E1 MOV AH, CL ; Get Xpos
\r
906 02EF 80 E4 03 AND AH, PLANE_BITS ; & mask out Plane #
\r
907 OUT_16 GC_INDEX, AX ; Select Plane to read in
\r
908 02F2 BA 03CE 1 MOV DX, GC_INDEX ; then Select Register
\r
909 02F5 EF 1 OUT DX, AX ; Set I/O Register(s)
\r
911 CLR AH ; Clear Return Value Hi byte
\r
912 02F6 32 E4 1 XOR AH, AH ; Set Register = 0
\r
913 02F8 26: 8A 01 MOV AL, ES:[DI+BX] ; Get Color of Pixel
\r
915 POPx DI, BP ; Restore Saved Registers
\r
916 02FB 5F 1 POP DI ; Restore R1
\r
917 02FC 5D 2 POP BP ; Restore R1
\r
918 02FD CA 0004 RET 4 ; Exit and Clean up Stack
\r
920 0300 READ_POINT ENDP
\r
923 ;======================================================
\r
924 ;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)
\r
925 ;======================================================
\r
927 ; Fills a rectangular block on the active display Page
\r
929 ; ENTRY: Xpos1 = Left X position of area to fill
\r
930 ; Ypos1 = Top Y position of area to fill
\r
931 ; Xpos2 = Right X position of area to fill
\r
932 ; Ypos2 = Bottom Y position of area to fill
\r
933 ; ColorNum = Color to fill area with
\r
935 ; EXIT: No meaningful values returned
\r
938 0016 FB_STACK STRUC
\r
939 0000 0000 0000 0000 DW ?x4 ; DS, DI, SI, BP
\r
941 0008 00000000 DD ? ; Caller
\r
942 000C 00 00 FB_Color DB ?,? ; Fill Color
\r
943 000E 0000 FB_Ypos2 DW ? ; Y pos of Lower Right Pixel
\r
944 0010 0000 FB_Xpos2 DW ? ; X pos of Lower Right Pixel
\r
945 0012 0000 FB_Ypos1 DW ? ; Y pos of Upper Left Pixel
\r
946 0014 0000 FB_Xpos1 DW ? ; X pos of Upper Left Pixel
\r
951 0300 FILL_BLOCK PROC FAR
\r
953 PUSHx BP, DS, SI, DI ; Preserve Important Registers
\r
954 0300 55 1 PUSH BP ; Save R1
\r
955 0301 1E 2 PUSH DS ; Save R1
\r
956 0302 56 3 PUSH SI ; Save R1
\r
957 0303 57 4 PUSH DI ; Save R1
\r
958 0304 8B EC MOV BP, SP ; Set up Stack Frame
\r
960 0306 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
961 030A FC CLD ; Direction Flag = Forward
\r
963 OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select
\r
964 030B BA 03C4 1 MOV DX, SC_INDEX ; then Select Register
\r
965 030E B0 02 1 MOV AL, MAP_MASK ; then Get Data Value
\r
966 0310 EE 1 OUT DX, AL ; Set I/O Register
\r
968 ; Validate Pixel Coordinates
\r
969 ; If necessary, Swap so X1 <= X2, Y1 <= Y2
\r
971 0311 8B 46 12 MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2?
\r
972 0314 8B 5E 0E MOV BX, [BP].FB_Ypos2 ; BX = Y2
\r
973 0317 3B C3 CMP AX, BX
\r
974 0319 7E 04 JLE @FB_NOSWAP1
\r
976 031B 89 5E 12 MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1
\r
977 031E 93 XCHG AX, BX ; on stack for future use
\r
980 031F 2B D8 SUB BX, AX ; Get Y width
\r
981 0321 43 INC BX ; Add 1 to avoid 0 value
\r
982 0322 89 5E 0E MOV [BP].FB_Ypos2, BX ; Save in Ypos2
\r
984 0325 F7 26 0000 R MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line
\r
985 0329 03 F8 ADD DI, AX ; DI = Start of Line Y1
\r
987 032B 8B 46 14 MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2
\r
988 032E 8B 5E 10 MOV BX, [BP].FB_Xpos2 ;
\r
989 0331 3B C3 CMP AX, BX
\r
990 0333 7E 04 JLE @FB_NOSWAP2 ; Skip Ahead if Ok
\r
992 0335 89 46 10 MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2
\r
993 0338 93 XCHG AX, BX ; on stack for future use
\r
995 ; All our Input Values are in order, Now determine
\r
996 ; How many full "bands" 4 pixels wide (aligned) there
\r
997 ; are, and if there are partial bands (<4 pixels) on
\r
998 ; the left and right edges.
\r
1001 0339 8B D0 MOV DX, AX ; DX = X1 (Pixel Position)
\r
1002 033B C1 EA 02 SHR DX, 2 ; DX/4 = Bytes into Line
\r
1003 033E 03 FA ADD DI, DX ; DI = Addr of Upper-Left Corner
\r
1005 0340 8B CB MOV CX, BX ; CX = X2 (Pixel Position)
\r
1006 0342 C1 E9 02 SHR CX, 2 ; CX/4 = Bytes into Line
\r
1008 0345 3B D1 CMP DX, CX ; Start and end in same band?
\r
1009 0347 75 03 JNE @FB_NORMAL ; if not, check for l & r edges
\r
1010 0349 E9 0086 JMP @FB_ONE_BAND_ONLY ; if so, then special processing
\r
1013 034C 2B CA SUB CX, DX ; CX = # bands -1
\r
1014 034E 8B F0 MOV SI, AX ; SI = PLANE#(X1)
\r
1015 0350 83 E6 03 AND SI, PLANE_BITS ; if Left edge is aligned then
\r
1016 0353 74 27 JZ @FB_L_PLANE_FLUSH ; no special processing..
\r
1018 ; Draw "Left Edge" vertical strip of 1-3 pixels...
\r
1020 OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask
\r
1021 0355 BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
1022 0358 2E: 8A 84 0000 R 1 MOV AL, Left_Clip_Mask[SI] ; then Get Data Value
\r
1023 035D EE 1 OUT DX, AL ; Set I/O Register
\r
1025 035E 8B F7 MOV SI, DI ; SI = Copy of Start Addr (UL)
\r
1027 0360 8B 56 0E MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw
\r
1028 0363 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color
\r
1029 0366 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value
\r
1031 036A @FB_LEFT_LOOP:
\r
1032 036A 26: 88 04 MOV ES:[SI], AL ; Fill in Left Edge Pixels
\r
1033 036D 03 F3 ADD SI, BX ; Point to Next Line (Below)
\r
1034 LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn
\r
1035 036F 4A 1 DEC DX ; Counter--
\r
1036 0370 74 08 1 JZ @FB_LEFT_CONT ; Jump if 0
\r
1038 0372 26: 88 04 MOV ES:[SI], AL ; Fill in Left Edge Pixels
\r
1039 0375 03 F3 ADD SI, BX ; Point to Next Line (Below)
\r
1040 LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn
\r
1041 0377 4A 1 DEC DX ; Counter--
\r
1042 0378 75 F0 1 JNZ @FB_LEFT_LOOP ; Jump if not 0
\r
1044 037A @FB_LEFT_CONT:
\r
1046 037A 47 INC DI ; Point to Middle (or Right) Block
\r
1047 037B 49 DEC CX ; Reset CX instead of JMP @FB_RIGHT
\r
1049 037C @FB_L_PLANE_FLUSH:
\r
1050 037C 41 INC CX ; Add in Left band to middle block
\r
1052 ; DI = Addr of 1st middle Pixel (band) to fill
\r
1053 ; CX = # of Bands to fill -1
\r
1056 037D 8B 76 10 MOV SI, [BP].FB_Xpos2 ; Get Xpos2
\r
1057 0380 83 E6 03 AND SI, PLANE_BITS ; Get Plane values
\r
1058 0383 83 FE 03 CMP SI, 0003 ; Plane = 3?
\r
1059 0386 74 2B JE @FB_R_EDGE_FLUSH ; Hey, add to middle
\r
1061 ; Draw "Right Edge" vertical strip of 1-3 pixels...
\r
1063 OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask
\r
1064 0388 BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
1065 038B 2E: 8A 84 0004 R 1 MOV AL, Right_Clip_Mask[SI] ; then Get Data Value
\r
1066 0390 EE 1 OUT DX, AL ; Set I/O Register
\r
1068 0391 8B F7 MOV SI, DI ; Get Addr of Left Edge
\r
1069 0393 03 F1 ADD SI, CX ; Add Width-1 (Bands)
\r
1070 0395 4E DEC SI ; To point to top of Right Edge
\r
1072 0396 8B 56 0E MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw
\r
1073 0399 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color
\r
1074 039C 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value
\r
1076 03A0 @FB_RIGHT_LOOP:
\r
1077 03A0 26: 88 04 MOV ES:[SI], AL ; Fill in Right Edge Pixels
\r
1078 03A3 03 F3 ADD SI, BX ; Point to Next Line (Below)
\r
1079 LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn
\r
1080 03A5 4A 1 DEC DX ; Counter--
\r
1081 03A6 74 08 1 JZ @FB_RIGHT_CONT ; Jump if 0
\r
1083 03A8 26: 88 04 MOV ES:[SI], AL ; Fill in Right Edge Pixels
\r
1084 03AB 03 F3 ADD SI, BX ; Point to Next Line (Below)
\r
1085 LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn
\r
1086 03AD 4A 1 DEC DX ; Counter--
\r
1087 03AE 75 F0 1 JNZ @FB_RIGHT_LOOP ; Jump if not 0
\r
1089 03B0 @FB_RIGHT_CONT:
\r
1091 03B0 49 DEC CX ; Minus 1 for Middle bands
\r
1092 03B1 74 51 JZ @FB_EXIT ; Uh.. no Middle bands...
\r
1094 03B3 @FB_R_EDGE_FLUSH:
\r
1096 ; DI = Addr of Upper Left block to fill
\r
1097 ; CX = # of Bands to fill in (width)
\r
1099 OUT_8 SC_Data, ALL_PLANES ; Write to All Planes
\r
1100 03B3 BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
1101 03B6 B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value
\r
1102 03B8 EE 1 OUT DX, AL ; Set I/O Register
\r
1104 03B9 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = DI Increment
\r
1105 03BD 2B D1 SUB DX, CX ; = Screen_Width-# Planes Filled
\r
1107 03BF 8B D9 MOV BX, CX ; BX = Quick Refill for CX
\r
1108 03C1 8B 76 0E MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill
\r
1109 03C4 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color
\r
1110 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
1111 modex.asm Page 5 - 1
\r
1115 03C7 @FB_MIDDLE_LOOP:
\r
1116 03C7 F3/ AA REP STOSB ; Fill in entire line
\r
1118 03C9 8B CB MOV CX, BX ; Recharge CX (Line Width)
\r
1119 03CB 03 FA ADD DI, DX ; Point to start of Next Line
\r
1120 LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn
\r
1121 03CD 4E 1 DEC SI ; Counter--
\r
1122 03CE 75 F7 1 JNZ @FB_MIDDLE_LOOP ; Jump if not 0
\r
1124 03D0 EB 32 JMP s @FB_EXIT ; Outa here
\r
1126 03D2 @FB_ONE_BAND_ONLY:
\r
1127 03D2 8B F0 MOV SI, AX ; Get Left Clip Mask, Save X1
\r
1128 03D4 83 E6 03 AND SI, PLANE_BITS ; Mask out Row #
\r
1129 03D7 2E: 8A 84 0000 R MOV AL, Left_Clip_Mask[SI] ; Get Left Edge Mask
\r
1130 03DC 8B F3 MOV SI, BX ; Get Right Clip Mask, Save X2
\r
1131 03DE 83 E6 03 AND SI, PLANE_BITS ; Mask out Row #
\r
1132 03E1 2E: 22 84 0004 R AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte
\r
1134 OUT_8 SC_Data, AL ; Clip For Left & Right Masks
\r
1135 03E6 BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
1136 03E9 EE 1 OUT DX, AL ; Set I/O Register
\r
1138 03EA 8B 4E 0E MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw
\r
1139 03ED 8A 46 0C MOV AL, [BP].FB_Color ; Get Fill Color
\r
1140 03F0 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Vertical increment Value
\r
1142 03F4 @FB_ONE_LOOP:
\r
1143 03F4 26: 88 05 MOV ES:[DI], AL ; Fill in Pixels
\r
1144 03F7 03 FB ADD DI, BX ; Point to Next Line (Below)
\r
1145 LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn
\r
1146 03F9 49 1 DEC CX ; Counter--
\r
1147 03FA 74 08 1 JZ @FB_EXIT ; Jump if 0
\r
1149 03FC 26: 88 05 MOV ES:[DI], AL ; Fill in Pixels
\r
1150 03FF 03 FB ADD DI, BX ; Point to Next Line (Below)
\r
1151 LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn
\r
1152 0401 49 1 DEC CX ; Counter--
\r
1153 0402 75 F0 1 JNZ @FB_ONE_LOOP ; Jump if not 0
\r
1156 POPx DI, SI, DS, BP ; Restore Saved Registers
\r
1157 0404 5F 1 POP DI ; Restore R1
\r
1158 0405 5E 2 POP SI ; Restore R1
\r
1159 0406 1F 3 POP DS ; Restore R1
\r
1160 0407 5D 4 POP BP ; Restore R1
\r
1161 0408 CA 000A RET 10 ; Exit and Clean up Stack
\r
1163 040B FILL_BLOCK ENDP
\r
1166 ;=====================================================
\r
1167 ;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)
\r
1168 ;=====================================================
\r
1170 ; Draws a Line on the active display page
\r
1172 ; ENTRY: Xpos1 = X position of first point on line
\r
1173 ; Ypos1 = Y position of first point on line
\r
1174 ; Xpos2 = X position of last point on line
\r
1175 ; Ypos2 = Y position of last point on line
\r
1176 ; ColorNum = Color to draw line with
\r
1178 ; EXIT: No meaningful values returned
\r
1181 0014 DL_STACK STRUC
\r
1182 0000 0000 0000 0000 DW ?x3 ; DI, SI, BP
\r
1183 0006 00000000 DD ? ; Caller
\r
1184 000A 00 00 DL_ColorF DB ?,? ; Line Draw Color
\r
1185 000C 0000 DL_Ypos2 DW ? ; Y pos of last point
\r
1186 000E 0000 DL_Xpos2 DW ? ; X pos of last point
\r
1187 0010 0000 DL_Ypos1 DW ? ; Y pos of first point
\r
1188 0012 0000 DL_Xpos1 DW ? ; X pos of first point
\r
1193 040B DRAW_LINE PROC FAR
\r
1195 PUSHx BP, SI, DI ; Preserve Important Registers
\r
1196 040B 55 1 PUSH BP ; Save R1
\r
1197 040C 56 2 PUSH SI ; Save R1
\r
1198 040D 57 3 PUSH DI ; Save R1
\r
1199 040E 8B EC MOV BP, SP ; Set up Stack Frame
\r
1200 0410 FC CLD ; Direction Flag = Forward
\r
1202 OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select
\r
1203 0411 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register
\r
1204 0414 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value
\r
1205 0416 EE 1 OUT DX, AL ; Set I/O Register
\r
1206 0417 8A 6E 0A MOV CH, [BP].DL_ColorF ; Save Line Color in CH
\r
1210 041A 8B 76 12 MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2?
\r
1211 041D 8B 7E 0E MOV DI, [BP].DL_Xpos2 ; DX = X2
\r
1212 0420 3B F7 CMP SI, DI ; Is X1 < X2
\r
1213 0422 74 5D JE @DL_VLINE ; If X1=X2, Draw Vertical Line
\r
1214 0424 7C 02 JL @DL_NOSWAP1 ; If X1 < X2, don't swap
\r
1216 0426 87 F7 XCHG SI, DI ; X2 IS > X1, SO SWAP THEM
\r
1220 ; SI = X1, DI = X2
\r
1222 0428 8B 46 10 MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2?
\r
1223 042B 3B 46 0C CMP AX, [BP].DL_Ypos2 ; Y1 = Y2?
\r
1224 042E 74 03 JE @DL_HORZ ; If so, Draw a Horizontal Line
\r
1226 0430 E9 0094 JMP @DL_BREZHAM ; Diagonal line... go do it...
\r
1228 ; This Code draws a Horizontal Line in Mode X where:
\r
1229 ; SI = X1, DI = X2, and AX = Y1/Y2
\r
1233 0433 F7 26 0000 R MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width
\r
1234 0437 8B D0 MOV DX, AX ; CX = Line offset into Page
\r
1236 0439 8B C6 MOV AX, SI ; Get Left edge, Save X1
\r
1237 043B 83 E6 03 AND SI, PLANE_BITS ; Mask out Row #
\r
1238 043E 2E: 8A 9C 0000 R MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask
\r
1239 0443 8B CF MOV CX, DI ; Get Right edge, Save X2
\r
1240 0445 83 E7 03 AND DI, PLANE_BITS ; Mask out Row #
\r
1241 0448 2E: 8A BD 0004 R MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte
\r
1243 044D C1 E8 02 SHR AX, 2 ; Get X1 Byte # (=X1/4)
\r
1244 0450 C1 E9 02 SHR CX, 2 ; Get X2 Byte # (=X2/4)
\r
1246 0453 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
1247 0457 03 FA ADD DI, DX ; Point to Start of Line
\r
1248 0459 03 F8 ADD DI, AX ; Point to Pixel X1
\r
1250 045B 2B C8 SUB CX, AX ; CX = # Of Bands (-1) to set
\r
1251 045D 75 02 JNZ @DL_LONGLN ; jump if longer than one segment
\r
1253 045F 22 DF AND BL, BH ; otherwise, merge clip masks
\r
1257 OUT_8 SC_Data, BL ; Set the Left Clip Mask
\r
1258 0461 BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
1259 0464 8A C3 1 MOV AL, BL ; then Get Data Value
\r
1260 0466 EE 1 OUT DX, AL ; Set I/O Register
\r
1262 0467 8A 46 0A MOV AL, [BP].DL_ColorF ; Get Line Color
\r
1263 046A 8A D8 MOV BL, AL ; BL = Copy of Line Color
\r
1264 046C AA STOSB ; Set Left (1-4) Pixels
\r
1266 046D E3 55 JCXZ @DL_EXIT ; Done if only one Line Segment
\r
1268 046F 49 DEC CX ; CX = # of Middle Segments
\r
1269 0470 74 07 JZ @DL_XRSEG ; If no middle segments....
\r
1271 ; Draw Middle Segments
\r
1273 OUT_8 DX, ALL_PLANES ; Write to ALL Planes
\r
1274 0472 B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value
\r
1275 0474 EE 1 OUT DX, AL ; Set I/O Register
\r
1277 0475 8A C3 MOV AL, BL ; Get Color from BL
\r
1278 0477 F3/ AA REP STOSB ; Draw Middle (4 Pixel) Segments
\r
1281 OUT_8 DX, BH ; Select Planes for Right Clip Mask
\r
1282 0479 8A C7 1 MOV AL, BH ; then Get Data Value
\r
1283 047B EE 1 OUT DX, AL ; Set I/O Register
\r
1284 047C 8A C3 MOV AL, BL ; Get Color Value
\r
1285 047E AA STOSB ; Draw Right (1-4) Pixels
\r
1287 047F EB 43 JMP s @DL_EXIT ; We Are Done...
\r
1290 ; This Code Draws A Vertical Line. On entry:
\r
1291 ; CH = Line Color, SI & DI = X1
\r
1295 0481 8B 46 10 MOV AX, [BP].DL_Ypos1 ; AX = Y1
\r
1296 0484 8B 76 0C MOV SI, [BP].DL_Ypos2 ; SI = Y2
\r
1297 0487 3B C6 CMP AX, SI ; Is Y1 < Y2?
\r
1298 0489 7E 01 JLE @DL_NOSWAP2 ; if so, Don't Swap them
\r
1300 048B 96 XCHG AX, SI ; Ok, NOW Y1 < Y2
\r
1304 048C 2B F0 SUB SI, AX ; SI = Line Height (Y2-Y1+1)
\r
1307 ; AX = Y1, DI = X1, Get offset into Page into AX
\r
1309 048F F7 26 0000 R MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width
\r
1310 0493 8B D7 MOV DX, DI ; Copy Xpos into DX
\r
1311 0495 C1 EF 02 SHR DI, 2 ; DI = Xpos/4
\r
1312 0498 03 C7 ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1
\r
1314 049A C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
1315 049E 03 F8 ADD DI, AX ; Point to Pixel X1, Y1
\r
1319 04A0 8A CA MOV CL, DL ; CL = Save X1
\r
1320 04A2 80 E1 03 AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #)
\r
1321 04A5 B8 0102 MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1
\r
1322 04A8 D2 E4 SHL AH, CL ; Change to Correct Plane #
\r
1323 OUT_16 SC_Index, AX ; Select Plane
\r
1324 04AA BA 03C4 1 MOV DX, SC_Index ; then Select Register
\r
1325 04AD EF 1 OUT DX, AX ; Set I/O Register(s)
\r
1327 04AE 8A C5 MOV AL, CH ; Get Saved Color
\r
1328 04B0 8B 1E 0000 R MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By
\r
1331 04B4 26: 88 05 MOV ES:[DI], AL ; Draw Single Pixel
\r
1332 04B7 03 FB ADD DI, BX ; Point to Next Line
\r
1333 LOOPjz SI, @DL_EXIT ; Lines--, Exit if done
\r
1334 04B9 4E 1 DEC SI ; Counter--
\r
1335 04BA 74 08 1 JZ @DL_EXIT ; Jump if 0
\r
1337 04BC 26: 88 05 MOV ES:[DI], AL ; Draw Single Pixel
\r
1338 04BF 03 FB ADD DI, BX ; Point to Next Line
\r
1339 LOOPx SI, @DL_VLoop ; Lines--, Loop until Done
\r
1340 04C1 4E 1 DEC SI ; Counter--
\r
1341 04C2 75 F0 1 JNZ @DL_VLoop ; Jump if not 0
\r
1345 04C4 E9 0157 JMP @DL_EXIT2 ; Done!
\r
1347 ; This code Draws a diagonal line in Mode X
\r
1350 04C7 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
1352 04CB 8B 46 10 MOV AX, [BP].DL_Ypos1 ; get Y1 value
\r
1353 04CE 8B 5E 0C MOV BX, [BP].DL_Ypos2 ; get Y2 value
\r
1354 04D1 8B 4E 12 MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos
\r
1356 04D4 3B D8 CMP BX, AX ; Y2-Y1 is?
\r
1357 04D6 73 04 JNC @DL_DeltaYOK ; if Y2>=Y1 then goto...
\r
1359 04D8 93 XCHG BX, AX ; Swap em...
\r
1360 04D9 8B 4E 0E MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos
\r
1362 04DC @DL_DeltaYOK:
\r
1363 04DC F7 26 0000 R MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1
\r
1365 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
1366 modex.asm Page 6 - 1
\r
1369 04E0 03 F8 ADD DI, AX ; DI -> Start of Line Y1 on Page
\r
1370 04E2 8B C1 MOV AX, CX ; AX = Xpos (X1)
\r
1371 04E4 C1 E8 02 SHR AX, 2 ; /4 = Byte Offset into Line
\r
1372 04E7 03 F8 ADD DI, AX ; DI = Starting pos (X1,Y1)
\r
1374 04E9 B0 11 MOV AL, 11h ; Staring Mask
\r
1375 04EB 80 E1 03 AND CL, PLANE_BITS ; Get Plane #
\r
1376 04EE D2 E0 SHL AL, CL ; and shift into place
\r
1377 04F0 8A 66 0A MOV AH, [BP].DL_ColorF ; Color in Hi Bytes
\r
1379 04F3 50 PUSH AX ; Save Mask,Color...
\r
1381 04F4 8A E0 MOV AH, AL ; Plane # in AH
\r
1382 04F6 B0 02 MOV AL, MAP_MASK ; Select Plane Register
\r
1383 OUT_16 SC_Index, AX ; Select initial plane
\r
1384 04F8 BA 03C4 1 MOV DX, SC_Index ; then Select Register
\r
1385 04FB EF 1 OUT DX, AX ; Set I/O Register(s)
\r
1387 04FC 8B 46 12 MOV AX, [BP].DL_Xpos1 ; get X1 value
\r
1388 04FF 8B 5E 10 MOV BX, [BP].DL_Ypos1 ; get Y1 value
\r
1389 0502 8B 4E 0E MOV CX, [BP].DL_Xpos2 ; get X2 value
\r
1390 0505 8B 56 0C MOV DX, [BP].DL_Ypos2 ; get Y2 value
\r
1392 0508 8B 2E 0000 R MOV BP, SCREEN_WIDTH ; Use BP for Line width to
\r
1393 ; to avoid extra memory access
\r
1395 050C 2B D3 SUB DX, BX ; figure Delta_Y
\r
1396 050E 73 05 JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1
\r
1398 0510 03 DA ADD BX, DX ; put Y2 into Y1
\r
1399 0512 F7 DA NEG DX ; abs(Delta_Y)
\r
1400 0514 91 XCHG AX, CX ; and exchange X1 and X2
\r
1402 0515 @DL_DeltaYOK2:
\r
1403 0515 BB 8000 MOV BX, 08000H ; seed for fraction accumulator
\r
1405 0518 2B C8 SUB CX, AX ; figure Delta_X
\r
1406 051A 72 03 JC @DL_DrawLeft ; if negative, go left
\r
1408 051C E9 0084 JMP @DL_DrawRight ; Draw Line that slopes right
\r
1410 051F @DL_DrawLeft:
\r
1412 051F F7 D9 NEG CX ; abs(Delta_X)
\r
1414 0521 3B CA CMP CX, DX ; is Delta_X < Delta_Y?
\r
1415 0523 72 41 JB @DL_SteepLeft ; yes, so go do steep line
\r
1416 ; (Delta_Y iterations)
\r
1418 ; Draw a Shallow line to the left in Mode X
\r
1420 0525 @DL_ShallowLeft:
\r
1421 CLR AX ; zero low word of Delta_Y * 10000h
\r
1422 0525 33 C0 1 XOR AX, AX ; Set Register = 0
\r
1423 0527 2B C2 SUB AX, DX ; DX:AX <- DX * 0FFFFh
\r
1424 0529 83 DA 00 SBB DX, 0 ; include carry
\r
1425 052C F7 F1 DIV CX ; divide by Delta_X
\r
1427 052E 8B F3 MOV SI, BX ; SI = Accumulator
\r
1428 0530 8B D8 MOV BX, AX ; BX = Add fraction
\r
1429 0532 58 POP AX ; Get Color, Bit mask
\r
1430 0533 BA 03C5 MOV DX, SC_Data ; Sequence controller data register
\r
1431 0536 41 INC CX ; Inc Delta_X so we can unroll loop
\r
1433 ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...
\r
1436 0537 26: 88 25 MOV ES:[DI], AH ; set first pixel, plane data set up
\r
1437 LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done
\r
1438 053A 49 1 DEC CX ; Counter--
\r
1439 053B 74 26 1 JZ @DL_SLLExit ; Jump if 0
\r
1441 053D 03 F3 ADD SI, BX ; add numerator to accumulator
\r
1442 053F 73 02 JNC @DL_SLLL2nc ; move down on carry
\r
1444 0541 03 FD ADD DI, BP ; Move Down one line...
\r
1447 0543 4F DEC DI ; Left one addr
\r
1448 0544 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2
\r
1449 0546 3C 87 CMP AL, 87h ; wrap?, if AL <88 then Carry set
\r
1450 0548 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry
\r
1451 054B EE OUT DX, AL ; Set up New Bit Plane mask
\r
1453 054C 26: 88 25 MOV ES:[DI], AH ; set pixel
\r
1454 LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done
\r
1455 054F 49 1 DEC CX ; Counter--
\r
1456 0550 74 11 1 JZ @DL_SLLExit ; Jump if 0
\r
1458 0552 03 F3 ADD SI, BX ; add numerator to accumulator,
\r
1459 0554 73 02 JNC @DL_SLLL3nc ; move down on carry
\r
1461 0556 03 FD ADD DI, BP ; Move Down one line...
\r
1463 0558 @DL_SLLL3nc: ; Now move left a pixel...
\r
1464 0558 4F DEC DI ; Left one addr
\r
1465 0559 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2
\r
1466 055B 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set
\r
1467 055D 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry
\r
1468 0560 EE OUT DX, AL ; Set up New Bit Plane mask
\r
1469 0561 EB D4 JMP s @DL_SLLLoop ; loop until done
\r
1472 0563 E9 00B8 JMP @DL_EXIT2 ; and exit
\r
1474 ; Draw a steep line to the left in Mode X
\r
1476 0566 @DL_SteepLeft:
\r
1477 CLR AX ; zero low word of Delta_Y * 10000h
\r
1478 0566 33 C0 1 XOR AX, AX ; Set Register = 0
\r
1479 0568 87 D1 XCHG DX, CX ; Delta_Y switched with Delta_X
\r
1480 056A F7 F1 DIV CX ; divide by Delta_Y
\r
1482 056C 8B F3 MOV SI, BX ; SI = Accumulator
\r
1483 056E 8B D8 MOV BX, AX ; BX = Add Fraction
\r
1484 0570 58 POP AX ; Get Color, Bit mask
\r
1485 0571 BA 03C5 MOV DX, SC_Data ; Sequence controller data register
\r
1486 0574 41 INC CX ; Inc Delta_Y so we can unroll loop
\r
1488 ; Loop (x2) to Draw Pixels, Move Down, and Maybe left
\r
1492 0575 26: 88 25 MOV ES:[DI], AH ; set first pixel
\r
1493 LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done
\r
1494 0578 49 1 DEC CX ; Counter--
\r
1495 0579 74 26 1 JZ @DL_STLExit ; Jump if 0
\r
1497 057B 03 F3 ADD SI, BX ; add numerator to accumulator
\r
1498 057D 73 09 JNC @DL_STLnc2 ; No carry, just move down!
\r
1500 057F 4F DEC DI ; Move Left one addr
\r
1501 0580 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2
\r
1502 0582 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set
\r
1503 0584 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry
\r
1504 0587 EE OUT DX, AL ; Set up New Bit Plane mask
\r
1507 0588 03 FD ADD DI, BP ; advance to next line.
\r
1509 058A 26: 88 25 MOV ES:[DI], AH ; set pixel
\r
1510 LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done
\r
1511 058D 49 1 DEC CX ; Counter--
\r
1512 058E 74 11 1 JZ @DL_STLExit ; Jump if 0
\r
1514 0590 03 F3 ADD SI, BX ; add numerator to accumulator
\r
1515 0592 73 09 JNC @DL_STLnc3 ; No carry, just move down!
\r
1517 0594 4F DEC DI ; Move Left one addr
\r
1518 0595 D0 C8 ROR AL, 1 ; Move Left one plane, back on 0 1 2
\r
1519 0597 3C 87 CMP AL, 87h ; Wrap?, if AL <88 then Carry set
\r
1520 0599 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry
\r
1521 059C EE OUT DX, AL ; Set up New Bit Plane mask
\r
1524 059D 03 FD ADD DI, BP ; advance to next line.
\r
1525 059F EB D4 JMP s @DL_STLLoop ; Loop until done
\r
1528 05A1 EB 7B JMP @DL_EXIT2 ; and exit
\r
1530 ; Draw a line that goes to the Right...
\r
1532 05A3 @DL_DrawRight:
\r
1533 05A3 3B CA CMP CX, DX ; is Delta_X < Delta_Y?
\r
1534 05A5 72 3E JB @DL_SteepRight ; yes, so go do steep line
\r
1535 ; (Delta_Y iterations)
\r
1537 ; Draw a Shallow line to the Right in Mode X
\r
1539 05A7 @DL_ShallowRight:
\r
1540 CLR AX ; zero low word of Delta_Y * 10000h
\r
1541 05A7 33 C0 1 XOR AX, AX ; Set Register = 0
\r
1542 05A9 2B C2 SUB AX, DX ; DX:AX <- DX * 0FFFFh
\r
1543 05AB 83 DA 00 SBB DX, 0 ; include carry
\r
1544 05AE F7 F1 DIV CX ; divide by Delta_X
\r
1546 05B0 8B F3 MOV SI, BX ; SI = Accumulator
\r
1547 05B2 8B D8 MOV BX, AX ; BX = Add Fraction
\r
1548 05B4 58 POP AX ; Get Color, Bit mask
\r
1549 05B5 BA 03C5 MOV DX, SC_Data ; Sequence controller data register
\r
1550 05B8 41 INC CX ; Inc Delta_X so we can unroll loop
\r
1552 ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...
\r
1555 05B9 26: 88 25 MOV ES:[DI], AH ; set first pixel, mask is set up
\r
1556 LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..
\r
1557 05BC 49 1 DEC CX ; Counter--
\r
1558 05BD 74 24 1 JZ @DL_SLRExit ; Jump if 0
\r
1560 05BF 03 F3 ADD SI, BX ; add numerator to accumulator
\r
1561 05C1 73 02 JNC @DL_SLR2nc ; don't move down if carry not set
\r
1563 05C3 03 FD ADD DI, BP ; Move Down one line...
\r
1565 05C5 @DL_SLR2nc: ; Now move right a pixel...
\r
1566 05C5 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0
\r
1567 05C7 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set
\r
1568 05C9 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry
\r
1569 05CC EE OUT DX, AL ; Set up New Bit Plane mask
\r
1571 05CD 26: 88 25 MOV ES:[DI], AH ; set pixel
\r
1572 LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..
\r
1573 05D0 49 1 DEC CX ; Counter--
\r
1574 05D1 74 10 1 JZ @DL_SLRExit ; Jump if 0
\r
1576 05D3 03 F3 ADD SI, BX ; add numerator to accumulator
\r
1577 05D5 73 02 JNC @DL_SLR3nc ; don't move down if carry not set
\r
1579 05D7 03 FD ADD DI, BP ; Move Down one line...
\r
1582 05D9 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0
\r
1583 05DB 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set
\r
1584 05DD 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry
\r
1585 05E0 EE OUT DX, AL ; Set up New Bit Plane mask
\r
1586 05E1 EB D6 JMP s @DL_SLRLoop ; loop till done
\r
1589 05E3 EB 39 JMP @DL_EXIT2 ; and exit
\r
1591 ; Draw a Steep line to the Right in Mode X
\r
1593 05E5 @DL_SteepRight:
\r
1594 CLR AX ; zero low word of Delta_Y * 10000h
\r
1595 05E5 33 C0 1 XOR AX, AX ; Set Register = 0
\r
1596 05E7 87 D1 XCHG DX, CX ; Delta_Y switched with Delta_X
\r
1597 05E9 F7 F1 DIV CX ; divide by Delta_Y
\r
1599 05EB 8B F3 MOV SI, BX ; SI = Accumulator
\r
1600 05ED 8B D8 MOV BX, AX ; BX = Add Fraction
\r
1601 05EF 58 POP AX ; Get Color, Bit mask
\r
1602 05F0 BA 03C5 MOV DX, SC_Data ; Sequence controller data register
\r
1603 05F3 41 INC CX ; Inc Delta_Y so we can unroll loop
\r
1605 ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right
\r
1608 05F4 26: 88 25 MOV ES:[DI], AH ; set first pixel, mask is set up
\r
1609 LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done
\r
1610 05F7 49 1 DEC CX ; Counter--
\r
1611 05F8 74 24 1 JZ @DL_EXIT2 ; Jump if 0
\r
1613 05FA 03 F3 ADD SI, BX ; add numerator to accumulator
\r
1614 05FC 73 08 JNC @STRnc2 ; if no carry then just go down...
\r
1616 05FE D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0
\r
1617 0600 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set
\r
1618 0602 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry
\r
1619 0605 EE OUT DX, AL ; Set up New Bit Plane mask
\r
1620 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
1621 modex.asm Page 7 - 1
\r
1626 0606 03 FD ADD DI, BP ; advance to next line.
\r
1628 0608 26: 88 25 MOV ES:[DI], AH ; set pixel
\r
1629 LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done
\r
1630 060B 49 1 DEC CX ; Counter--
\r
1631 060C 74 10 1 JZ @DL_EXIT2 ; Jump if 0
\r
1633 060E 03 F3 ADD SI, BX ; add numerator to accumulator
\r
1634 0610 73 08 JNC @STRnc3 ; if no carry then just go down...
\r
1636 0612 D0 C0 ROL AL, 1 ; Move Right one addr if Plane = 0
\r
1637 0614 3C 12 CMP AL, 12h ; Wrap? if AL >12 then Carry not set
\r
1638 0616 83 D7 00 ADC DI, 0 ; Adjust Address: DI = DI + Carry
\r
1639 0619 EE OUT DX, AL ; Set up New Bit Plane mask
\r
1642 061A 03 FD ADD DI, BP ; advance to next line.
\r
1643 061C EB D6 JMP s @STRLoop ; loop till done
\r
1646 POPx DI, SI, BP ; Restore Saved Registers
\r
1647 061E 5F 1 POP DI ; Restore R1
\r
1648 061F 5E 2 POP SI ; Restore R1
\r
1649 0620 5D 3 POP BP ; Restore R1
\r
1650 0621 CA 000A RET 10 ; Exit and Clean up Stack
\r
1652 0624 DRAW_LINE ENDP
\r
1655 ; ===== DAC COLOR REGISTER ROUTINES =====
\r
1657 ;=================================================
\r
1658 ;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%)
\r
1659 ;=================================================
\r
1661 ; Sets a single (RGB) Vga Palette Register
\r
1663 ; ENTRY: Register = The DAC # to modify (0-255)
\r
1664 ; Red = The new Red Intensity (0-63)
\r
1665 ; Green = The new Green Intensity (0-63)
\r
1666 ; Blue = The new Blue Intensity (0-63)
\r
1668 ; EXIT: No meaningful values returned
\r
1671 000E SDR_STACK STRUC
\r
1672 0000 0000 DW ? ; BP
\r
1673 0002 00000000 DD ? ; Caller
\r
1674 0006 00 00 SDR_Blue DB ?,? ; Blue Data Value
\r
1675 0008 00 00 SDR_Green DB ?,? ; Green Data Value
\r
1676 000A 00 00 SDR_Red DB ?,? ; Red Data Value
\r
1677 000C 00 00 SDR_Register DB ?,? ; Palette Register #
\r
1680 PUBLIC SET_DAC_REGISTER
\r
1682 0624 SET_DAC_REGISTER PROC FAR
\r
1684 0624 55 PUSH BP ; Save BP
\r
1685 0625 8B EC MOV BP, SP ; Set up Stack Frame
\r
1687 ; Select which DAC Register to modify
\r
1689 OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register
\r
1690 0627 BA 03C8 1 MOV DX, DAC_WRITE_ADDR ; then Select Register
\r
1691 062A 8A 46 0C 1 MOV AL, [BP].SDR_Register ; then Get Data Value
\r
1692 062D EE 1 OUT DX, AL ; Set I/O Register
\r
1694 062E BA 03C9 MOV DX, PEL_DATA_REG ; Dac Data Register
\r
1695 OUT_8 DX, [BP].SDR_Red ; Set Red Intensity
\r
1696 0631 8A 46 0A 1 MOV AL, [BP].SDR_Red ; then Get Data Value
\r
1697 0634 EE 1 OUT DX, AL ; Set I/O Register
\r
1698 OUT_8 DX, [BP].SDR_Green ; Set Green Intensity
\r
1699 0635 8A 46 08 1 MOV AL, [BP].SDR_Green ; then Get Data Value
\r
1700 0638 EE 1 OUT DX, AL ; Set I/O Register
\r
1701 OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity
\r
1702 0639 8A 46 06 1 MOV AL, [BP].SDR_Blue ; then Get Data Value
\r
1703 063C EE 1 OUT DX, AL ; Set I/O Register
\r
1705 063D 5D POP BP ; Restore Registers
\r
1706 063E CA 0008 RET 8 ; Exit & Clean Up Stack
\r
1708 0641 SET_DAC_REGISTER ENDP
\r
1710 ;====================================================
\r
1711 ;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%)
\r
1712 ;====================================================
\r
1714 ; Reads the RGB Values of a single Vga Palette Register
\r
1716 ; ENTRY: Register = The DAC # to read (0-255)
\r
1717 ; Red = Offset to Red Variable in DS
\r
1718 ; Green = Offset to Green Variable in DS
\r
1719 ; Blue = Offset to Blue Variable in DS
\r
1721 ; EXIT: The values of the integer variables Red,
\r
1722 ; Green, and Blue are set to the values
\r
1723 ; taken from the specified DAC register.
\r
1726 000E GDR_STACK STRUC
\r
1727 0000 0000 DW ? ; BP
\r
1728 0002 00000000 DD ? ; Caller
\r
1729 0006 0000 GDR_Blue DW ? ; Addr of Blue Data Value in DS
\r
1730 0008 0000 GDR_Green DW ? ; Addr of Green Data Value in DS
\r
1731 000A 0000 GDR_Red DW ? ; Addr of Red Data Value in DS
\r
1732 000C 00 00 GDR_Register DB ?,? ; Palette Register #
\r
1735 PUBLIC GET_DAC_REGISTER
\r
1737 0641 GET_DAC_REGISTER PROC FAR
\r
1739 0641 55 PUSH BP ; Save BP
\r
1740 0642 8B EC MOV BP, SP ; Set up Stack Frame
\r
1742 ; Select which DAC Register to read in
\r
1744 OUT_8 DAC_READ_ADDR, [BP].GDR_Register
\r
1745 0644 BA 03C7 1 MOV DX, DAC_READ_ADDR ; then Select Register
\r
1746 0647 8A 46 0C 1 MOV AL, [BP].GDR_Register ; then Get Data Value
\r
1747 064A EE 1 OUT DX, AL ; Set I/O Register
\r
1749 064B BA 03C9 MOV DX, PEL_DATA_REG ; Dac Data Register
\r
1751 064E 33 C0 1 XOR AX, AX ; Set Register = 0
\r
1753 0650 EC IN AL, DX ; Read Red Value
\r
1754 0651 8B 5E 0A MOV BX, [BP].GDR_Red ; Get Address of Red%
\r
1755 0654 89 07 MOV [BX], AX ; *Red% = AX
\r
1757 0656 EC IN AL, DX ; Read Green Value
\r
1758 0657 8B 5E 08 MOV BX, [BP].GDR_Green ; Get Address of Green%
\r
1759 065A 89 07 MOV [BX], AX ; *Green% = AX
\r
1761 065C EC IN AL, DX ; Read Blue Value
\r
1762 065D 8B 5E 06 MOV BX, [BP].GDR_Blue ; Get Address of Blue%
\r
1763 0660 89 07 MOV [BX], AX ; *Blue% = AX
\r
1765 0662 5D POP BP ; Restore Registers
\r
1766 0663 CA 0008 RET 8 ; Exit & Clean Up Stack
\r
1768 0666 GET_DAC_REGISTER ENDP
\r
1771 ;===========================================================
\r
1772 ;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%)
\r
1773 ;===========================================================
\r
1775 ; Sets a Block of Vga Palette Registers
\r
1777 ; ENTRY: PalData = Far Pointer to Block of palette data
\r
1778 ; StartReg = First Register # in range to set (0-255)
\r
1779 ; EndReg = Last Register # in Range to set (0-255)
\r
1780 ; Sync = Wait for Vertical Retrace Flag (Boolean)
\r
1782 ; EXIT: No meaningful values returned
\r
1784 ; NOTES: PalData is a linear array of 3 byte Palette values
\r
1785 ; in the order: Red (0-63), Green (0-63), Blue (0-63)
\r
1788 0014 LDR_STACK STRUC
\r
1789 0000 0000 0000 0000 DW ?x3 ; BP, DS, SI
\r
1790 0006 00000000 DD ? ; Caller
\r
1791 000A 0000 LDR_Sync DW ? ; Vertical Sync Flag
\r
1792 000C 00 00 LDR_EndReg DB ?,? ; Last Register #
\r
1793 000E 00 00 LDR_StartReg DB ?,? ; First Register #
\r
1794 0010 00000000 LDR_PalData DD ? ; Far Ptr to Palette Data
\r
1797 PUBLIC LOAD_DAC_REGISTERS
\r
1799 0666 LOAD_DAC_REGISTERS PROC FAR
\r
1801 PUSHx BP, DS, SI ; Save Registers
\r
1802 0666 55 1 PUSH BP ; Save R1
\r
1803 0667 1E 2 PUSH DS ; Save R1
\r
1804 0668 56 3 PUSH SI ; Save R1
\r
1805 0669 8B EC mov BP, SP ; Set up Stack Frame
\r
1807 066B 8B 46 0A mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag
\r
1808 066E 0B C0 or AX, AX ; is Sync Flag = 0?
\r
1809 0670 74 05 jz @LDR_Load ; if so, skip call
\r
1811 0672 9A ---- 0795 R call f SYNC_DISPLAY ; wait for vsync
\r
1813 ; Determine register #'s, size to copy, etc
\r
1817 0677 C5 76 10 lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data
\r
1818 067A BA 03C8 mov DX, DAC_WRITE_ADDR ; DAC register # selector
\r
1820 CLR AX, BX ; Clear for byte loads
\r
1821 067D 33 C0 1 XOR AX, AX ; Set Register = 0
\r
1822 067F 33 DB 2 XOR BX, BX ; Set Register = 0
\r
1823 0681 8A 46 0E mov AL, [BP].LDR_StartReg ; Get Start Register
\r
1824 0684 8A 5E 0C mov BL, [BP].LDR_EndReg ; Get End Register
\r
1826 0687 2B D8 sub BX, AX ; BX = # of DAC registers -1
\r
1827 0689 43 inc BX ; BX = # of DAC registers
\r
1828 068A 8B CB mov CX, BX ; CX = # of DAC registers
\r
1829 068C 03 CB add CX, BX ; CX = " " * 2
\r
1830 068E 03 CB add CX, BX ; CX = " " * 3
\r
1831 0690 FC cld ; Block OUTs forward
\r
1832 0691 EE out DX, AL ; set up correct register #
\r
1834 ; Load a block of DAC Registers
\r
1836 0692 BA 03C9 mov DX, PEL_DATA_REG ; Dac Data Register
\r
1838 0695 F3/ 6E rep outsb ; block set DAC registers
\r
1840 POPx SI, DS, BP ; Restore Registers
\r
1841 0697 5E 1 POP SI ; Restore R1
\r
1842 0698 1F 2 POP DS ; Restore R1
\r
1843 0699 5D 3 POP BP ; Restore R1
\r
1844 069A CA 000A ret 10 ; Exit & Clean Up Stack
\r
1846 069D LOAD_DAC_REGISTERS ENDP
\r
1849 ;====================================================
\r
1850 ;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%)
\r
1851 ;====================================================
\r
1853 ; Reads a Block of Vga Palette Registers
\r
1855 ; ENTRY: PalData = Far Pointer to block to store palette data
\r
1856 ; StartReg = First Register # in range to read (0-255)
\r
1857 ; EndReg = Last Register # in Range to read (0-255)
\r
1859 ; EXIT: No meaningful values returned
\r
1861 ; NOTES: PalData is a linear array of 3 byte Palette values
\r
1862 ; in the order: Red (0-63), Green (0-63), Blue (0-63)
\r
1865 0012 RDR_STACK STRUC
\r
1866 0000 0000 0000 0000 DW ?x3 ; BP, ES, DI
\r
1867 0006 00000000 DD ? ; Caller
\r
1868 000A 00 00 RDR_EndReg DB ?,? ; Last Register #
\r
1869 000C 00 00 RDR_StartReg DB ?,? ; First Register #
\r
1870 000E 00000000 RDR_PalData DD ? ; Far Ptr to Palette Data
\r
1873 PUBLIC READ_DAC_REGISTERS
\r
1875 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
1876 modex.asm Page 8 - 1
\r
1879 069D READ_DAC_REGISTERS PROC FAR
\r
1881 PUSHx BP, ES, DI ; Save Registers
\r
1882 069D 55 1 PUSH BP ; Save R1
\r
1883 069E 06 2 PUSH ES ; Save R1
\r
1884 069F 57 3 PUSH DI ; Save R1
\r
1885 06A0 8B EC mov BP, SP ; Set up Stack Frame
\r
1887 ; Determine register #'s, size to copy, etc
\r
1889 06A2 C4 7E 0E les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer
\r
1890 06A5 BA 03C7 mov DX, DAC_READ_ADDR ; DAC register # selector
\r
1892 CLR AX, BX ; Clear for byte loads
\r
1893 06A8 33 C0 1 XOR AX, AX ; Set Register = 0
\r
1894 06AA 33 DB 2 XOR BX, BX ; Set Register = 0
\r
1895 06AC 8A 46 0C mov AL, [BP].RDR_StartReg ; Get Start Register
\r
1896 06AF 8A 5E 0A mov BL, [BP].RDR_EndReg ; Get End Register
\r
1898 06B2 2B D8 sub BX, AX ; BX = # of DAC registers -1
\r
1899 06B4 43 inc BX ; BX = # of DAC registers
\r
1900 06B5 8B CB mov CX, BX ; CX = # of DAC registers
\r
1901 06B7 03 CB add CX, BX ; CX = " " * 2
\r
1902 06B9 03 CB add CX, BX ; CX = " " * 3
\r
1903 06BB FC cld ; Block INs forward
\r
1905 ; Read a block of DAC Registers
\r
1907 06BC EE out DX, AL ; set up correct register #
\r
1908 06BD BA 03C9 mov DX, PEL_DATA_REG ; Dac Data Register
\r
1910 06C0 F3/ 6C rep insb ; block read DAC registers
\r
1912 POPx DI, ES, BP ; Restore Registers
\r
1914 06C2 5F 1 POP DI ; Restore R1
\r
1915 06C3 07 2 POP ES ; Restore R1
\r
1916 06C4 5D 3 POP BP ; Restore R1
\r
1917 06C5 CA 0008 ret 8 ; Exit & Clean Up Stack
\r
1919 06C8 READ_DAC_REGISTERS ENDP
\r
1922 ; ===== PAGE FLIPPING AND SCROLLING ROUTINES =====
\r
1924 ;=========================
\r
1925 ;SET_ACTIVE_PAGE (PageNo%)
\r
1926 ;=========================
\r
1928 ; Sets the active display Page to be used for future drawing
\r
1930 ; ENTRY: PageNo = Display Page to make active
\r
1931 ; (values: 0 to Number of Pages - 1)
\r
1933 ; EXIT: No meaningful values returned
\r
1936 0008 SAP_STACK STRUC
\r
1937 0000 0000 DW ? ; BP
\r
1938 0002 00000000 DD ? ; Caller
\r
1939 0006 0000 SAP_Page DW ? ; Page # for Drawing
\r
1942 PUBLIC SET_ACTIVE_PAGE
\r
1944 06C8 SET_ACTIVE_PAGE PROC FAR
\r
1946 06C8 55 PUSH BP ; Preserve Registers
\r
1947 06C9 8B EC MOV BP, SP ; Set up Stack Frame
\r
1949 06CB 8B 5E 06 MOV BX, [BP].SAP_Page ; Get Desired Page #
\r
1950 06CE 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid?
\r
1951 06D2 73 0D JAE @SAP_Exit ; IF Not, Do Nothing
\r
1953 06D4 89 1E 0012 R MOV ACTIVE_PAGE, BX ; Set Active Page #
\r
1955 06D8 D1 E3 SHL BX, 1 ; Scale Page # to Word
\r
1956 06DA 8B 87 0006 R MOV AX, PAGE_ADDR[BX] ; Get offset to Page
\r
1958 06DE A3 0014 R MOV CURRENT_PAGE, AX ; And set for future LES's
\r
1961 06E1 5D POP BP ; Restore Registers
\r
1962 06E2 CA 0002 RET 2 ; Exit and Clean up Stack
\r
1964 06E5 SET_ACTIVE_PAGE ENDP
\r
1971 ; Returns the Video Page # currently used for Drawing
\r
1973 ; ENTRY: No Parameters are passed
\r
1975 ; EXIT: AX = Current Video Page used for Drawing
\r
1978 PUBLIC GET_ACTIVE_PAGE
\r
1980 06E5 GET_ACTIVE_PAGE PROC FAR
\r
1982 06E5 A1 0012 R MOV AX, ACTIVE_PAGE ; Get Active Page #
\r
1983 06E8 CB RET ; Exit and Clean up Stack
\r
1985 06E9 GET_ACTIVE_PAGE ENDP
\r
1988 ;===============================
\r
1989 ;SET_DISPLAY_PAGE (DisplayPage%)
\r
1990 ;===============================
\r
1992 ; Sets the currently visible display page.
\r
1993 ; When called this routine syncronizes the display
\r
1994 ; to the vertical blank.
\r
1996 ; ENTRY: PageNo = Display Page to show on the screen
\r
1997 ; (values: 0 to Number of Pages - 1)
\r
1999 ; EXIT: No meaningful values returned
\r
2002 0008 SDP_STACK STRUC
\r
2003 0000 0000 DW ? ; BP
\r
2004 0002 00000000 DD ? ; Caller
\r
2005 0006 0000 SDP_Page DW ? ; Page # to Display...
\r
2008 PUBLIC SET_DISPLAY_PAGE
\r
2010 06E9 SET_DISPLAY_PAGE PROC FAR
\r
2012 06E9 55 PUSH BP ; Preserve Registers
\r
2013 06EA 8B EC MOV BP, SP ; Set up Stack Frame
\r
2015 06EC 8B 5E 06 MOV BX, [BP].SDP_Page ; Get Desired Page #
\r
2016 06EF 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid?
\r
2017 06F3 73 2B JAE @SDP_Exit ; IF Not, Do Nothing
\r
2019 06F5 89 1E 0010 R MOV DISPLAY_PAGE, BX ; Set Display Page #
\r
2021 06F9 D1 E3 SHL BX, 1 ; Scale Page # to Word
\r
2022 06FB 8B 8F 0006 R MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page
\r
2023 06FF 03 0E 001C R ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling
\r
2025 ; Wait if we are currently in a Vertical Retrace
\r
2027 0703 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register
\r
2030 0706 EC IN AL, DX ; Get VGA status
\r
2031 0707 24 08 AND AL, VERT_RETRACE ; In Display mode yet?
\r
2032 0709 75 FB JNZ @DP_WAIT0 ; If Not, wait for it
\r
2034 ; Set the Start Display Address to the new page
\r
2036 070B BA 03D4 MOV DX, CRTC_Index ; We Change the VGA Sequencer
\r
2038 070E B0 0D MOV AL, START_DISP_LO ; Display Start Low Register
\r
2039 0710 8A E1 MOV AH, CL ; Low 8 Bits of Start Addr
\r
2040 0712 EF OUT DX, AX ; Set Display Addr Low
\r
2042 0713 B0 0C MOV AL, START_DISP_HI ; Display Start High Register
\r
2043 0715 8A E5 MOV AH, CH ; High 8 Bits of Start Addr
\r
2044 0717 EF OUT DX, AX ; Set Display Addr High
\r
2046 ; Wait for a Vertical Retrace to smooth out things
\r
2048 0718 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register
\r
2051 071B EC IN AL, DX ; Get VGA status
\r
2052 071C 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start?
\r
2053 071E 74 FB JZ @DP_WAIT1 ; If Not, wait for it
\r
2055 ; Now Set Display Starting Address
\r
2059 0720 5D POP BP ; Restore Registers
\r
2060 0721 CA 0002 RET 2 ; Exit and Clean up Stack
\r
2062 0724 SET_DISPLAY_PAGE ENDP
\r
2065 ;=================
\r
2066 ;GET_DISPLAY_PAGE%
\r
2067 ;=================
\r
2069 ; Returns the Video Page # currently displayed
\r
2071 ; ENTRY: No Parameters are passed
\r
2073 ; EXIT: AX = Current Video Page being displayed
\r
2076 PUBLIC GET_DISPLAY_PAGE
\r
2078 0724 GET_DISPLAY_PAGE PROC FAR
\r
2080 0724 A1 0010 R MOV AX, DISPLAY_PAGE ; Get Display Page #
\r
2081 0727 CB RET ; Exit & Clean Up Stack
\r
2083 0728 GET_DISPLAY_PAGE ENDP
\r
2086 ;=======================================
\r
2087 ;SET_WINDOW (DisplayPage%, Xpos%, Ypos%)
\r
2088 ;=======================================
\r
2090 ; Since a Logical Screen can be larger than the Physical
\r
2091 ; Screen, Scrolling is possible. This routine sets the
\r
2092 ; Upper Left Corner of the Screen to the specified Pixel.
\r
2093 ; Also Sets the Display page to simplify combined page
\r
2094 ; flipping and scrolling. When called this routine
\r
2095 ; syncronizes the display to the vertical blank.
\r
2097 ; ENTRY: DisplayPage = Display Page to show on the screen
\r
2098 ; Xpos = # of pixels to shift screen right
\r
2099 ; Ypos = # of lines to shift screen down
\r
2101 ; EXIT: No meaningful values returned
\r
2104 000C SW_STACK STRUC
\r
2105 0000 0000 DW ? ; BP
\r
2106 0002 00000000 DD ? ; Caller
\r
2107 0006 0000 SW_Ypos DW ? ; Y pos of UL Screen Corner
\r
2108 0008 0000 SW_Xpos DW ? ; X pos of UL Screen Corner
\r
2109 000A 0000 SW_Page DW ? ; (new) Display Page
\r
2114 0728 SET_WINDOW PROC FAR
\r
2116 0728 55 PUSH BP ; Preserve Registers
\r
2117 0729 8B EC MOV BP, SP ; Set up Stack Frame
\r
2119 ; Check if our Scroll Offsets are Valid
\r
2121 072B 8B 5E 0A MOV BX, [BP].SW_Page ; Get Desired Page #
\r
2122 072E 3B 1E 0004 R CMP BX, LAST_PAGE ; Is Page # Valid?
\r
2123 0732 73 55 JAE @SW_Exit ; IF Not, Do Nothing
\r
2125 0734 8B 46 06 MOV AX, [BP].SW_Ypos ; Get Desired Y Offset
\r
2126 0737 3B 06 0020 R CMP AX, MAX_YOFFSET ; Is it Within Limits?
\r
2127 073B 77 4C JA @SW_Exit ; if not, exit
\r
2129 073D 8B 4E 08 MOV CX, [BP].SW_Xpos ; Get Desired X Offset
\r
2130 0740 3B 0E 001E R CMP CX, MAX_XOFFSET ; Is it Within Limits?
\r
2131 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
2132 modex.asm Page 9 - 1
\r
2135 0744 77 43 JA @SW_Exit ; if not, exit
\r
2137 ; Compute proper Display start address to use
\r
2139 0746 F7 26 0000 R MUL SCREEN_WIDTH ; AX = YOffset * Line Width
\r
2140 074A C1 E9 02 SHR CX, 2 ; CX / 4 = Bytes into Line
\r
2141 074D 03 C1 ADD AX, CX ; AX = Offset of Upper Left Pixel
\r
2143 074F A3 001C R MOV CURRENT_MOFFSET, AX ; Save Offset Info
\r
2145 0752 89 1E 0010 R MOV DISPLAY_PAGE, BX ; Set Current Page #
\r
2146 0756 D1 E3 SHL BX, 1 ; Scale Page # to Word
\r
2147 0758 03 87 0006 R ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page
\r
2148 075C 8B D8 MOV BX, AX ; BX = Desired Display Start
\r
2150 075E BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register
\r
2152 ; Wait if we are currently in a Vertical Retrace
\r
2155 0761 EC IN AL, DX ; Get VGA status
\r
2156 0762 24 08 AND AL, VERT_RETRACE ; In Display mode yet?
\r
2157 0764 75 FB JNZ @SW_WAIT0 ; If Not, wait for it
\r
2159 ; Set the Start Display Address to the new window
\r
2161 0766 BA 03D4 MOV DX, CRTC_Index ; We Change the VGA Sequencer
\r
2162 0769 B0 0D MOV AL, START_DISP_LO ; Display Start Low Register
\r
2163 076B 8A E3 MOV AH, BL ; Low 8 Bits of Start Addr
\r
2164 076D EF OUT DX, AX ; Set Display Addr Low
\r
2166 076E B0 0C MOV AL, START_DISP_HI ; Display Start High Register
\r
2167 0770 8A E7 MOV AH, BH ; High 8 Bits of Start Addr
\r
2168 0772 EF OUT DX, AX ; Set Display Addr High
\r
2170 ; Wait for a Vertical Retrace to smooth out things
\r
2172 0773 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register
\r
2175 0776 EC IN AL, DX ; Get VGA status
\r
2176 0777 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start?
\r
2177 0779 74 FB JZ @SW_WAIT1 ; If Not, wait for it
\r
2179 ; Now Set the Horizontal Pixel Pan values
\r
2181 OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register
\r
2182 077B BA 03C0 1 MOV DX, ATTRIB_Ctrl ; then Select Register
\r
2183 077E B0 33 1 MOV AL, PIXEL_PAN_REG ; then Get Data Value
\r
2184 0780 EE 1 OUT DX, AL ; Set I/O Register
\r
2186 0781 8B 46 08 MOV AX, [BP].SW_Xpos ; Get Desired X Offset
\r
2187 0784 24 03 AND AL, 03 ; Get # of Pixels to Pan (0-3)
\r
2188 0786 D0 E0 SHL AL, 1 ; Shift for 256 Color Mode
\r
2189 0788 EE OUT DX, AL ; Fine tune the display!
\r
2192 0789 5D POP BP ; Restore Saved Registers
\r
2193 078A CA 0006 RET 6 ; Exit and Clean up Stack
\r
2195 078D SET_WINDOW ENDP
\r
2202 ; Returns the X coordinate of the Pixel currently display
\r
2203 ; in the upper left corner of the display
\r
2205 ; ENTRY: No Parameters are passed
\r
2207 ; EXIT: AX = Current Horizontal Scroll Offset
\r
2210 PUBLIC GET_X_OFFSET
\r
2212 078D GET_X_OFFSET PROC FAR
\r
2214 078D A1 0018 R MOV AX, CURRENT_XOFFSET ; Get current horz offset
\r
2215 0790 CB RET ; Exit & Clean Up Stack
\r
2217 0791 GET_X_OFFSET ENDP
\r
2224 ; Returns the Y coordinate of the Pixel currently display
\r
2225 ; in the upper left corner of the display
\r
2227 ; ENTRY: No Parameters are passed
\r
2229 ; EXIT: AX = Current Vertical Scroll Offset
\r
2232 PUBLIC GET_Y_OFFSET
\r
2234 0791 GET_Y_OFFSET PROC FAR
\r
2236 0791 A1 001A R MOV AX, CURRENT_YOFFSET ; Get current vertical offset
\r
2237 0794 CB RET ; Exit & Clean Up Stack
\r
2239 0795 GET_Y_OFFSET ENDP
\r
2246 ; Pauses the computer until the next Vertical Retrace starts
\r
2248 ; ENTRY: No Parameters are passed
\r
2250 ; EXIT: No meaningful values returned
\r
2253 PUBLIC SYNC_DISPLAY
\r
2255 0795 SYNC_DISPLAY PROC FAR
\r
2257 0795 BA 03DA MOV DX, INPUT_1 ; Input Status #1 Register
\r
2259 ; Wait for any current retrace to end
\r
2262 0798 EC IN AL, DX ; Get VGA status
\r
2263 0799 24 08 AND AL, VERT_RETRACE ; In Display mode yet?
\r
2264 079B 75 FB JNZ @SD_WAIT0 ; If Not, wait for it
\r
2266 ; Wait for the start of the next vertical retrace
\r
2269 079D EC IN AL, DX ; Get VGA status
\r
2270 079E 24 08 AND AL, VERT_RETRACE ; Vertical Retrace Start?
\r
2271 07A0 74 FB JZ @SD_WAIT1 ; If Not, wait for it
\r
2273 07A2 CB RET ; Exit & Clean Up Stack
\r
2275 07A3 SYNC_DISPLAY ENDP
\r
2278 ; ===== TEXT DISPLAY ROUTINES =====
\r
2280 ;==================================================
\r
2281 ;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%)
\r
2282 ;==================================================
\r
2284 ; Draws an ASCII Text Character using the currently selected
\r
2285 ; 8x8 font on the active display page. It would be a simple
\r
2286 ; exercise to make this routine process variable height fonts.
\r
2288 ; ENTRY: CharNum = ASCII character # to draw
\r
2289 ; Xpos = X position to draw Character at
\r
2290 ; Ypos = Y position of to draw Character at
\r
2291 ; ColorF = Color to draw text character in
\r
2292 ; ColorB = Color to set background to
\r
2294 ; EXIT: No meaningful values returned
\r
2297 001E GPC_STACK STRUC
\r
2298 0000 0000 GPC_Width DW ? ; Screen Width-1
\r
2299 0002 00 00 GPC_Lines DB ?,? ; Scan lines to Decode
\r
2300 0004 0000 GPC_T_SETS DW ? ; Saved Charset Segment
\r
2301 0006 0000 GPC_T_SETO DW ? ; Saved Charset Offset
\r
2302 0008 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP
\r
2304 0010 00000000 DD ? ; Caller
\r
2305 0014 00 00 GPC_ColorB DB ?,? ; Background Color
\r
2306 0016 00 00 GPC_ColorF DB ?,? ; Text Color
\r
2307 0018 0000 GPC_Ypos DW ? ; Y Position to Print at
\r
2308 001A 0000 GPC_Xpos DW ? ; X position to Print at
\r
2309 001C 00 00 GPC_Char DB ?,? ; Character to Print
\r
2314 07A3 GPRINTC PROC FAR
\r
2316 PUSHx BP, DS, SI, DI ; Preserve Important Registers
\r
2317 07A3 55 1 PUSH BP ; Save R1
\r
2318 07A4 1E 2 PUSH DS ; Save R1
\r
2319 07A5 56 3 PUSH SI ; Save R1
\r
2320 07A6 57 4 PUSH DI ; Save R1
\r
2321 07A7 83 EC 08 SUB SP, 8 ; Allocate WorkSpace on Stack
\r
2322 07AA 8B EC MOV BP, SP ; Set up Stack Frame
\r
2324 07AC C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
2326 07B0 A1 0000 R MOV AX, SCREEN_WIDTH ; Get Logical Line Width
\r
2327 07B3 8B D8 MOV BX, AX ; BX = Screen Width
\r
2328 07B5 4B DEC BX ; = Screen Width-1
\r
2329 07B6 89 5E 00 MOV [BP].GPC_Width, BX ; Save for later use
\r
2331 07B9 F7 66 18 MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width
\r
2332 07BC 03 F8 ADD DI, AX ; DI -> Start of Line Ypos
\r
2334 07BE 8B 46 1A MOV AX, [BP].GPC_Xpos ; Get Xpos of Character
\r
2335 07C1 8B C8 MOV CX, AX ; Save Copy of Xpos
\r
2336 07C3 C1 E8 02 SHR AX, 2 ; Bytes into Line = Xpos/4
\r
2337 07C6 03 F8 ADD DI, AX ; DI -> (Xpos, Ypos)
\r
2339 ;Get Source ADDR of Character Bit Map & Save
\r
2341 07C8 8A 46 1C MOV AL, [BP].GPC_Char ; Get Character #
\r
2342 07CB A8 80 TEST AL, 080h ; Is Hi Bit Set?
\r
2343 07CD 74 0C JZ @GPC_LowChar ; Nope, use low char set ptr
\r
2345 07CF 24 7F AND AL, 07Fh ; Mask Out Hi Bit
\r
2346 07D1 8B 1E 0026 R MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset
\r
2347 07D5 8B 16 0028 R MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment
\r
2348 07D9 EB 08 JMP s @GPC_Set_Char ; Go Setup Character Ptr
\r
2350 07DB @GPC_LowChar:
\r
2352 07DB 8B 1E 0022 R MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset
\r
2353 07DF 8B 16 0024 R MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment
\r
2355 07E3 @GPC_Set_Char:
\r
2356 07E3 89 56 04 MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack
\r
2358 07E6 B4 00 MOV AH, 0 ; Valid #'s are 0..127
\r
2359 07E8 C1 E0 03 SHL AX, 3 ; * 8 Bytes Per Bitmap
\r
2360 07EB 03 D8 ADD BX, AX ; BX = Offset of Selected char
\r
2361 07ED 89 5E 06 MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack
\r
2363 07F0 83 E1 03 AND CX, PLANE_BITS ; Get Plane #
\r
2364 07F3 B5 0F MOV CH, ALL_PLANES ; Get Initial Plane mask
\r
2365 07F5 D2 E5 SHL CH, CL ; And shift into position
\r
2366 07F7 80 E5 0F AND CH, ALL_PLANES ; And mask to lower nibble
\r
2368 07FA B0 04 MOV AL, 04 ; 4-Plane # = # of initial
\r
2369 07FC 2A C1 SUB AL, CL ; shifts to align bit mask
\r
2370 07FE 8A C8 MOV CL, AL ; Shift Count for SHL
\r
2372 ;Get segment of character map
\r
2374 OUT_8 SC_Index, MAP_MASK ; Setup Plane selections
\r
2375 0800 BA 03C4 1 MOV DX, SC_Index ; then Select Register
\r
2376 0803 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value
\r
2377 0805 EE 1 OUT DX, AL ; Set I/O Register
\r
2378 0806 42 INC DX ; DX -> SC_Data
\r
2380 0807 B0 08 MOV AL, 08 ; 8 Lines to Process
\r
2381 0809 88 46 02 MOV [BP].GPC_Lines, AL ; Save on Stack
\r
2383 080C 8E 5E 04 MOV DS, [BP].GPC_T_SETS ; Point to character set
\r
2385 080F @GPC_DECODE_CHAR_BYTE:
\r
2386 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
2387 modex.asm Page 10 - 1
\r
2391 080F 8B 76 06 MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String
\r
2393 0812 8A 3C MOV BH, [SI] ; Get Bit Map
\r
2394 0814 46 INC SI ; Point to Next Line
\r
2395 0815 89 76 06 MOV [BP].GPC_T_SETO, SI ; And save new Pointer...
\r
2398 0818 33 C0 1 XOR AX, AX ; Set Register = 0
\r
2401 081A 32 DB 1 XOR BL, BL ; Set Register = 0
\r
2402 081C D3 C3 ROL BX, CL ; BL holds left edge bits
\r
2403 081E 8B F3 MOV SI, BX ; Use as Table Index
\r
2404 0820 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits
\r
2405 0823 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL
\r
2406 0828 74 07 JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set
\r
2408 082A 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color
\r
2409 082D EE OUT DX, AL ; Set up Screen Mask
\r
2410 082E 26: 88 25 MOV ES:[DI], AH ; Write Foreground color
\r
2412 0831 @GPC_NO_LEFT1BITS:
\r
2413 0831 32 C5 XOR AL, CH ; Invert mask for Background
\r
2414 0833 74 07 JZ @GPC_NO_LEFT0BITS ; Hey, no need for this
\r
2416 0835 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color
\r
2417 0838 EE OUT DX, AL ; Set up Screen Mask
\r
2418 0839 26: 88 25 MOV ES:[DI], AH ; Write Foreground color
\r
2420 ;Now Do Middle/Last Band
\r
2422 083C @GPC_NO_LEFT0BITS:
\r
2423 083C 47 INC DI ; Point to next Byte
\r
2424 083D C1 C3 04 ROL BX, 4 ; Shift 4 bits
\r
2426 0840 8B F3 MOV SI, BX ; Make Lookup Pointer
\r
2427 0842 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits
\r
2428 0845 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL
\r
2429 084A 74 07 JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set
\r
2431 084C 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color
\r
2432 084F EE OUT DX, AL ; Set up Screen Mask
\r
2433 0850 26: 88 25 MOV ES:[DI], AH ; Write Foreground color
\r
2435 0853 @GPC_NO_MIDDLE1BITS:
\r
2436 0853 34 0F XOR AL, ALL_PLANES ; Invert mask for Background
\r
2437 0855 74 07 JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this
\r
2439 0857 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color
\r
2440 085A EE OUT DX, AL ; Set up Screen Mask
\r
2441 085B 26: 88 25 MOV ES:[DI], AH ; Write Foreground color
\r
2443 085E @GPC_NO_MIDDLE0BITS:
\r
2444 085E 80 F5 0F XOR CH, ALL_PLANES ; Invert Clip Mask
\r
2445 0861 80 F9 04 CMP CL, 4 ; Aligned by 4?
\r
2446 0864 74 23 JZ @GPC_NEXT_LINE ; If so, Exit now..
\r
2448 0866 47 INC DI ; Point to next Byte
\r
2449 0867 C1 C3 04 ROL BX, 4 ; Shift 4 bits
\r
2451 086A 8B F3 MOV SI, BX ; Make Lookup Pointer
\r
2452 086C 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits
\r
2453 086F 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL
\r
2454 0874 74 07 JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set
\r
2456 0876 8A 66 16 MOV AH, [BP].GPC_ColorF ; Get Foreground Color
\r
2457 0879 EE OUT DX, AL ; Set up Screen Mask
\r
2458 087A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color
\r
2460 087D @GPC_NO_RIGHT1BITS:
\r
2462 087D 32 C5 XOR AL, CH ; Invert mask for Background
\r
2463 087F 74 07 JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this
\r
2465 0881 8A 66 14 MOV AH, [BP].GPC_ColorB ; Get background Color
\r
2466 0884 EE OUT DX, AL ; Set up Screen Mask
\r
2467 0885 26: 88 25 MOV ES:[DI], AH ; Write Foreground color
\r
2469 0888 @GPC_NO_RIGHT0BITS:
\r
2470 0888 4F DEC DI ; Adjust for Next Line Advance
\r
2472 0889 @GPC_NEXT_LINE:
\r
2473 0889 03 7E 00 ADD DI, [BP].GPC_Width ; Point to Next Line
\r
2474 088C 80 F5 0F XOR CH, CHAR_BITS ; Flip the Clip mask back
\r
2476 088F FE 4E 02 DEC [BP].GPC_Lines ; Count Down Lines
\r
2477 0892 74 03 JZ @GPC_EXIT ; Ok... Done!
\r
2479 0894 E9 FF78 JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey!
\r
2482 0897 83 C4 08 ADD SP, 08 ; Deallocate stack workspace
\r
2483 POPx DI, SI, DS, BP ; Restore Saved Registers
\r
2484 089A 5F 1 POP DI ; Restore R1
\r
2485 089B 5E 2 POP SI ; Restore R1
\r
2486 089C 1F 3 POP DS ; Restore R1
\r
2487 089D 5D 4 POP BP ; Restore R1
\r
2488 089E CA 000A RET 10 ; Exit and Clean up Stack
\r
2493 ;==========================================
\r
2494 ;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%)
\r
2495 ;==========================================
\r
2497 ; Transparently draws an ASCII Text Character using the
\r
2498 ; currently selected 8x8 font on the active display page.
\r
2500 ; ENTRY: CharNum = ASCII character # to draw
\r
2501 ; Xpos = X position to draw Character at
\r
2502 ; Ypos = Y position of to draw Character at
\r
2503 ; ColorF = Color to draw text character in
\r
2505 ; EXIT: No meaningful values returned
\r
2508 001C TGP_STACK STRUC
\r
2509 0000 0000 TGP_Width DW ? ; Screen Width-1
\r
2510 0002 00 00 TGP_Lines DB ?,? ; Scan lines to Decode
\r
2511 0004 0000 TGP_T_SETS DW ? ; Saved Charset Segment
\r
2512 0006 0000 TGP_T_SETO DW ? ; Saved Charset Offset
\r
2513 0008 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP
\r
2515 0010 00000000 DD ? ; Caller
\r
2516 0014 00 00 TGP_ColorF DB ?,? ; Text Color
\r
2517 0016 0000 TGP_Ypos DW ? ; Y Position to Print at
\r
2518 0018 0000 TGP_Xpos DW ? ; X position to Print at
\r
2519 001A 00 00 TGP_Char DB ?,? ; Character to Print
\r
2524 08A1 TGPRINTC PROC FAR
\r
2526 PUSHx BP, DS, SI, DI ; Preserve Important Registers
\r
2527 08A1 55 1 PUSH BP ; Save R1
\r
2528 08A2 1E 2 PUSH DS ; Save R1
\r
2529 08A3 56 3 PUSH SI ; Save R1
\r
2530 08A4 57 4 PUSH DI ; Save R1
\r
2531 08A5 83 EC 08 SUB SP, 8 ; Allocate WorkSpace on Stack
\r
2532 08A8 8B EC MOV BP, SP ; Set up Stack Frame
\r
2534 08AA C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
2536 08AE A1 0000 R MOV AX, SCREEN_WIDTH ; Get Logical Line Width
\r
2537 08B1 8B D8 MOV BX, AX ; BX = Screen Width
\r
2538 08B3 4B DEC BX ; = Screen Width-1
\r
2539 08B4 89 5E 00 MOV [BP].TGP_Width, BX ; Save for later use
\r
2541 08B7 F7 66 16 MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width
\r
2542 08BA 03 F8 ADD DI, AX ; DI -> Start of Line Ypos
\r
2544 08BC 8B 46 18 MOV AX, [BP].TGP_Xpos ; Get Xpos of Character
\r
2545 08BF 8B C8 MOV CX, AX ; Save Copy of Xpos
\r
2546 08C1 C1 E8 02 SHR AX, 2 ; Bytes into Line = Xpos/4
\r
2547 08C4 03 F8 ADD DI, AX ; DI -> (Xpos, Ypos)
\r
2549 ;Get Source ADDR of Character Bit Map & Save
\r
2551 08C6 8A 46 1A MOV AL, [BP].TGP_Char ; Get Character #
\r
2552 08C9 A8 80 TEST AL, 080h ; Is Hi Bit Set?
\r
2553 08CB 74 0C JZ @TGP_LowChar ; Nope, use low char set ptr
\r
2555 08CD 24 7F AND AL, 07Fh ; Mask Out Hi Bit
\r
2556 08CF 8B 1E 0026 R MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset
\r
2557 08D3 8B 16 0028 R MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment
\r
2558 08D7 EB 08 JMP s @TGP_Set_Char ; Go Setup Character Ptr
\r
2560 08D9 @TGP_LowChar:
\r
2562 08D9 8B 1E 0022 R MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset
\r
2563 08DD 8B 16 0024 R MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment
\r
2565 08E1 @TGP_Set_Char:
\r
2566 08E1 89 56 04 MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack
\r
2568 08E4 B4 00 MOV AH, 0 ; Valid #'s are 0..127
\r
2569 08E6 C1 E0 03 SHL AX, 3 ; * 8 Bytes Per Bitmap
\r
2570 08E9 03 D8 ADD BX, AX ; BX = Offset of Selected char
\r
2571 08EB 89 5E 06 MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack
\r
2573 08EE 83 E1 03 AND CX, PLANE_BITS ; Get Plane #
\r
2574 08F1 B5 0F MOV CH, ALL_PLANES ; Get Initial Plane mask
\r
2575 08F3 D2 E5 SHL CH, CL ; And shift into position
\r
2576 08F5 80 E5 0F AND CH, ALL_PLANES ; And mask to lower nibble
\r
2578 08F8 B0 04 MOV AL, 04 ; 4-Plane # = # of initial
\r
2579 08FA 2A C1 SUB AL, CL ; shifts to align bit mask
\r
2580 08FC 8A C8 MOV CL, AL ; Shift Count for SHL
\r
2582 ;Get segment of character map
\r
2584 OUT_8 SC_Index, MAP_MASK ; Setup Plane selections
\r
2585 08FE BA 03C4 1 MOV DX, SC_Index ; then Select Register
\r
2586 0901 B0 02 1 MOV AL, MAP_MASK ; then Get Data Value
\r
2587 0903 EE 1 OUT DX, AL ; Set I/O Register
\r
2588 0904 42 INC DX ; DX -> SC_Data
\r
2590 0905 B0 08 MOV AL, 08 ; 8 Lines to Process
\r
2591 0907 88 46 02 MOV [BP].TGP_Lines, AL ; Save on Stack
\r
2593 090A 8E 5E 04 MOV DS, [BP].TGP_T_SETS ; Point to character set
\r
2595 090D @TGP_DECODE_CHAR_BYTE:
\r
2597 090D 8B 76 06 MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String
\r
2599 0910 8A 3C MOV BH, [SI] ; Get Bit Map
\r
2600 0912 46 INC SI ; Point to Next Line
\r
2601 0913 89 76 06 MOV [BP].TGP_T_SETO, SI ; And save new Pointer...
\r
2603 0916 8A 66 14 MOV AH, [BP].TGP_ColorF ; Get Foreground Color
\r
2606 0919 32 DB 1 XOR BL, BL ; Set Register = 0
\r
2607 091B D3 C3 ROL BX, CL ; BL holds left edge bits
\r
2608 091D 8B F3 MOV SI, BX ; Use as Table Index
\r
2609 091F 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits
\r
2610 0922 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL
\r
2611 0927 74 04 JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set
\r
2613 0929 EE OUT DX, AL ; Set up Screen Mask
\r
2614 092A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color
\r
2616 ;Now Do Middle/Last Band
\r
2618 092D @TGP_NO_LEFT1BITS:
\r
2620 092D 47 INC DI ; Point to next Byte
\r
2621 092E C1 C3 04 ROL BX, 4 ; Shift 4 bits
\r
2623 0931 8B F3 MOV SI, BX ; Make Lookup Pointer
\r
2624 0933 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits
\r
2625 0936 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL
\r
2626 093B 74 04 JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set
\r
2628 093D EE OUT DX, AL ; Set up Screen Mask
\r
2629 093E 26: 88 25 MOV ES:[DI], AH ; Write Foreground color
\r
2631 0941 @TGP_NO_MIDDLE1BITS:
\r
2632 0941 80 F5 0F XOR CH, ALL_PLANES ; Invert Clip Mask
\r
2633 0944 80 F9 04 CMP CL, 4 ; Aligned by 4?
\r
2634 0947 74 15 JZ @TGP_NEXT_LINE ; If so, Exit now..
\r
2636 0949 47 INC DI ; Point to next Byte
\r
2637 094A C1 C3 04 ROL BX, 4 ; Shift 4 bits
\r
2639 094D 8B F3 MOV SI, BX ; Make Lookup Pointer
\r
2640 094F 83 E6 0F AND SI, CHAR_BITS ; Get Low Bits
\r
2641 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
2642 modex.asm Page 11 - 1
\r
2645 0952 2E: 8A 84 0008 R MOV AL, Char_Plane_Data[SI] ; Get Mask in AL
\r
2646 0957 74 04 JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set
\r
2648 0959 EE OUT DX, AL ; Set up Screen Mask
\r
2649 095A 26: 88 25 MOV ES:[DI], AH ; Write Foreground color
\r
2651 095D @TGP_NO_RIGHT1BITS:
\r
2653 095D 4F DEC DI ; Adjust for Next Line Advance
\r
2655 095E @TGP_NEXT_LINE:
\r
2656 095E 03 7E 00 ADD DI, [BP].TGP_Width ; Point to Next Line
\r
2657 0961 80 F5 0F XOR CH, CHAR_BITS ; Flip the Clip mask back
\r
2659 0964 FE 4E 02 DEC [BP].TGP_Lines ; Count Down Lines
\r
2660 0967 74 02 JZ @TGP_EXIT ; Ok... Done!
\r
2662 0969 EB A2 JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey!
\r
2665 096B 83 C4 08 ADD SP, 08 ; Deallocate stack workspace
\r
2666 POPx DI, SI, DS, BP ; Restore Saved Registers
\r
2667 096E 5F 1 POP DI ; Restore R1
\r
2668 096F 5E 2 POP SI ; Restore R1
\r
2669 0970 1F 3 POP DS ; Restore R1
\r
2670 0971 5D 4 POP BP ; Restore R1
\r
2671 0972 CA 0008 RET 8 ; Exit and Clean up Stack
\r
2673 0975 TGPRINTC ENDP
\r
2676 ;===============================================================
\r
2677 ;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)
\r
2678 ;===============================================================
\r
2680 ; Routine to quickly Print a null terminated ASCII string on the
\r
2681 ; active display page up to a maximum length.
\r
2683 ; ENTRY: String = Far Pointer to ASCII string to print
\r
2684 ; MaxLen = # of characters to print if no null found
\r
2685 ; Xpos = X position to draw Text at
\r
2686 ; Ypos = Y position of to draw Text at
\r
2687 ; ColorF = Color to draw text in
\r
2688 ; ColorB = Color to set background to
\r
2690 ; EXIT: No meaningful values returned
\r
2693 001A PS_STACK STRUC
\r
2694 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP
\r
2696 0008 00000000 DD ? ; Caller
\r
2697 000C 0000 PS_ColorB DW ? ; Background Color
\r
2698 000E 0000 PS_ColorF DW ? ; Text Color
\r
2699 0010 0000 PS_Ypos DW ? ; Y Position to Print at
\r
2700 0012 0000 PS_Xpos DW ? ; X position to Print at
\r
2701 0014 0000 PS_Len DW ? ; Maximum Length of string to print
\r
2702 0016 0000 0000 PS_Text DW ?,? ; Far Ptr to Text String
\r
2707 0975 PRINT_STR PROC FAR
\r
2709 PUSHx BP, DS, SI, DI ; Preserve Important Registers
\r
2710 0975 55 1 PUSH BP ; Save R1
\r
2711 0976 1E 2 PUSH DS ; Save R1
\r
2712 0977 56 3 PUSH SI ; Save R1
\r
2713 0978 57 4 PUSH DI ; Save R1
\r
2714 0979 8B EC MOV BP, SP ; Set up Stack Frame
\r
2716 097B @PS_Print_It:
\r
2718 097B 8B 4E 14 MOV CX, [BP].PS_Len ; Get Remaining text Length
\r
2719 097E E3 2F JCXZ @PS_Exit ; Exit when out of text
\r
2721 0980 C4 7E 16 LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text
\r
2722 0983 26: 8A 05 MOV AL, ES:[DI] ; AL = Text Character
\r
2723 0986 25 00FF AND AX, 00FFh ; Clear High Word
\r
2724 0989 74 24 JZ @PS_Exit ; Exit if null character
\r
2726 098B FF 4E 14 DEC [BP].PS_Len ; Remaining Text length--
\r
2727 098E FF 46 16 INC [BP].PS_Text ; Point to Next text char
\r
2729 ; Set up Call to GPRINTC
\r
2731 0991 50 PUSH AX ; Set Character Parameter
\r
2732 0992 8B 5E 12 MOV BX, [BP].PS_Xpos ; Get Xpos
\r
2733 0995 53 PUSH BX ; Set Xpos Parameter
\r
2734 0996 83 C3 08 ADD BX, 8 ; Advance 1 Char to Right
\r
2735 0999 89 5E 12 MOV [BP].PS_Xpos, BX ; Save for next time through
\r
2737 099C 8B 5E 10 MOV BX, [BP].PS_Ypos ; Get Ypos
\r
2738 099F 53 PUSH BX ; Set Ypos Parameter
\r
2740 09A0 8B 5E 0E MOV BX, [BP].PS_ColorF ; Get Text Color
\r
2741 09A3 53 PUSH BX ; Set ColorF Parameter
\r
2743 09A4 8B 5E 0C MOV BX, [BP].PS_ColorB ; Get Background Color
\r
2744 09A7 53 PUSH BX ; Set ColorB Parameter
\r
2746 09A8 9A ---- 07A3 R CALL f GPRINTC ; Print Character!
\r
2747 09AD EB CC JMP s @PS_Print_It ; Process next character
\r
2750 POPx DI, SI, DS, BP ; Restore Saved Registers
\r
2751 09AF 5F 1 POP DI ; Restore R1
\r
2752 09B0 5E 2 POP SI ; Restore R1
\r
2753 09B1 1F 3 POP DS ; Restore R1
\r
2754 09B2 5D 4 POP BP ; Restore R1
\r
2755 09B3 CA 000E RET 14 ; Exit and Clean up Stack
\r
2757 09B6 PRINT_STR ENDP
\r
2760 ;================================================================
\r
2761 ;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)
\r
2762 ;================================================================
\r
2764 ; Routine to quickly transparently Print a null terminated ASCII
\r
2765 ; string on the active display page up to a maximum length.
\r
2767 ; ENTRY: String = Far Pointer to ASCII string to print
\r
2768 ; MaxLen = # of characters to print if no null found
\r
2769 ; Xpos = X position to draw Text at
\r
2770 ; Ypos = Y position of to draw Text at
\r
2771 ; ColorF = Color to draw text in
\r
2773 ; EXIT: No meaningful values returned
\r
2776 0018 TPS_STACK STRUC
\r
2777 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP
\r
2779 0008 00000000 DD ? ; Caller
\r
2780 000C 0000 TPS_ColorF DW ? ; Text Color
\r
2781 000E 0000 TPS_Ypos DW ? ; Y Position to Print at
\r
2782 0010 0000 TPS_Xpos DW ? ; X position to Print at
\r
2783 0012 0000 TPS_Len DW ? ; Maximum Length of string to print
\r
2784 0014 0000 0000 TPS_Text DW ?,? ; Far Ptr to Text String
\r
2789 09B6 TPRINT_STR PROC FAR
\r
2791 PUSHx BP, DS, SI, DI ; Preserve Important Registers
\r
2792 09B6 55 1 PUSH BP ; Save R1
\r
2793 09B7 1E 2 PUSH DS ; Save R1
\r
2794 09B8 56 3 PUSH SI ; Save R1
\r
2795 09B9 57 4 PUSH DI ; Save R1
\r
2796 09BA 8B EC MOV BP, SP ; Set up Stack Frame
\r
2798 09BC @TPS_Print_It:
\r
2800 09BC 8B 4E 12 MOV CX, [BP].TPS_Len ; Get Remaining text Length
\r
2801 09BF E3 2B JCXZ @TPS_Exit ; Exit when out of text
\r
2803 09C1 C4 7E 14 LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text
\r
2804 09C4 26: 8A 05 MOV AL, ES:[DI] ; AL = Text Character
\r
2805 09C7 25 00FF AND AX, 00FFh ; Clear High Word
\r
2806 09CA 74 20 JZ @TPS_Exit ; Exit if null character
\r
2808 09CC FF 4E 12 DEC [BP].TPS_Len ; Remaining Text length--
\r
2809 09CF FF 46 14 INC [BP].TPS_Text ; Point to Next text char
\r
2811 ; Set up Call to TGPRINTC
\r
2813 09D2 50 PUSH AX ; Set Character Parameter
\r
2814 09D3 8B 5E 10 MOV BX, [BP].TPS_Xpos ; Get Xpos
\r
2815 09D6 53 PUSH BX ; Set Xpos Parameter
\r
2816 09D7 83 C3 08 ADD BX, 8 ; Advance 1 Char to Right
\r
2817 09DA 89 5E 10 MOV [BP].TPS_Xpos, BX ; Save for next time through
\r
2819 09DD 8B 5E 0E MOV BX, [BP].TPS_Ypos ; Get Ypos
\r
2820 09E0 53 PUSH BX ; Set Ypos Parameter
\r
2822 09E1 8B 5E 0C MOV BX, [BP].TPS_ColorF ; Get Text Color
\r
2823 09E4 53 PUSH BX ; Set ColorF Parameter
\r
2825 09E5 9A ---- 08A1 R CALL f TGPRINTC ; Print Character!
\r
2826 09EA EB D0 JMP s @TPS_Print_It ; Process next character
\r
2829 POPx DI, SI, DS, BP ; Restore Saved Registers
\r
2830 09EC 5F 1 POP DI ; Restore R1
\r
2831 09ED 5E 2 POP SI ; Restore R1
\r
2832 09EE 1F 3 POP DS ; Restore R1
\r
2833 09EF 5D 4 POP BP ; Restore R1
\r
2834 09F0 CA 000C RET 12 ; Exit and Clean up Stack
\r
2836 09F3 TPRINT_STR ENDP
\r
2839 ;===========================================
\r
2840 ;SET_DISPLAY_FONT(SEG FontData, FontNumber%)
\r
2841 ;===========================================
\r
2843 ; Allows the user to specify their own font data for
\r
2844 ; wither the lower or upper 128 characters.
\r
2846 ; ENTRY: FontData = Far Pointer to Font Bitmaps
\r
2847 ; FontNumber = Which half of set this is
\r
2848 ; = 0, Lower 128 characters
\r
2849 ; = 1, Upper 128 characters
\r
2851 ; EXIT: No meaningful values returned
\r
2854 000C SDF_STACK STRUC
\r
2855 0000 0000 DW ? ; BP
\r
2856 0002 00000000 DD ? ; Caller
\r
2857 0006 0000 SDF_Which DW ? ; Hi Table/Low Table Flag
\r
2858 0008 00000000 SDF_Font DD ? ; Far Ptr to Font Table
\r
2861 PUBLIC SET_DISPLAY_FONT
\r
2863 09F3 SET_DISPLAY_FONT PROC FAR
\r
2865 09F3 55 PUSH BP ; Preserve Registers
\r
2866 09F4 8B EC MOV BP, SP ; Set up Stack Frame
\r
2868 09F6 C4 7E 08 LES DI, [BP].SDF_Font ; Get Far Ptr to Font
\r
2870 09F9 BE 0022 R MOV SI, o CHARSET_LOW ; Assume Lower 128 chars
\r
2871 09FC F7 46 06 0001 TEST [BP].SDF_Which, 1 ; Font #1 selected?
\r
2872 0A01 74 03 JZ @SDF_Set_Font ; If not, skip ahead
\r
2874 0A03 BE 0026 R MOV SI, o CHARSET_HI ; Ah, really it's 128-255
\r
2876 0A06 @SDF_Set_Font:
\r
2877 0A06 89 3C MOV [SI], DI ; Set Font Pointer Offset
\r
2878 0A08 8C 44 02 MOV [SI+2], ES ; Set Font Pointer Segment
\r
2880 0A0B 5D POP BP ; Restore Registers
\r
2881 0A0C CA 0006 RET 6 ; We are Done.. Outa here
\r
2883 0A0F SET_DISPLAY_FONT ENDP
\r
2886 ; ===== BITMAP (SPRITE) DISPLAY ROUTINES =====
\r
2888 ;======================================================
\r
2889 ;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)
\r
2890 ;======================================================
\r
2892 ; Draws a variable sized Graphics Bitmap such as a
\r
2893 ; picture or an Icon on the current Display Page in
\r
2894 ; Mode X. The Bitmap is stored in a linear byte array
\r
2895 ; corresponding to (0,0) (1,0), (2,0) .. (Width, Height)
\r
2896 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
2897 modex.asm Page 12 - 1
\r
2900 ; This is the same linear manner as mode 13h graphics.
\r
2902 ; ENTRY: Image = Far Pointer to Bitmap Data
\r
2903 ; Xpos = X position to Place Upper Left pixel at
\r
2904 ; Ypos = Y position to Place Upper Left pixel at
\r
2905 ; Width = Width of the Bitmap in Pixels
\r
2906 ; Height = Height of the Bitmap in Pixels
\r
2908 ; EXIT: No meaningful values returned
\r
2911 0022 DB_STACK STRUC
\r
2912 0000 0000 DB_LineO DW ? ; Offset to Next Line
\r
2913 0002 0000 DB_PixCount DW ? ; (Minimum) # of Pixels/Line
\r
2914 0004 0000 DB_Start DW ? ; Addr of Upper Left Pixel
\r
2915 0006 0000 DB_PixSkew DW ? ; # of bytes to Adjust EOL
\r
2916 0008 0000 DB_SkewFlag DW ? ; Extra Pix on Plane Flag
\r
2917 000A 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP
\r
2919 0012 00000000 DD ? ; Caller
\r
2920 0016 0000 DB_Height DW ? ; Height of Bitmap in Pixels
\r
2921 0018 0000 DB_Width DW ? ; Width of Bitmap in Pixels
\r
2922 001A 0000 DB_Ypos DW ? ; Y position to Draw Bitmap at
\r
2923 001C 0000 DB_Xpos DW ? ; X position to Draw Bitmap at
\r
2924 001E 00000000 DB_Image DD ? ; Far Pointer to Graphics Bitmap
\r
2927 PUBLIC DRAW_BITMAP
\r
2929 0A0F DRAW_BITMAP PROC FAR
\r
2931 PUSHx BP, DS, SI, DI ; Preserve Important Registers
\r
2932 0A0F 55 1 PUSH BP ; Save R1
\r
2933 0A10 1E 2 PUSH DS ; Save R1
\r
2934 0A11 56 3 PUSH SI ; Save R1
\r
2935 0A12 57 4 PUSH DI ; Save R1
\r
2936 0A13 83 EC 0A SUB SP, 10 ; Allocate workspace
\r
2937 0A16 8B EC MOV BP, SP ; Set up Stack Frame
\r
2939 0A18 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
2940 0A1C FC CLD ; Direction Flag = Forward
\r
2942 0A1D 8B 46 1A MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos
\r
2943 0A20 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Ypos
\r
2945 0A24 8B 5E 1C MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos
\r
2946 0A27 8A CB MOV CL, BL ; Save Plane # in CL
\r
2947 0A29 C1 EB 02 SHR BX, 2 ; Xpos/4 = Offset Into Line
\r
2949 0A2C 03 F8 ADD DI, AX ; ES:DI -> Start of Line
\r
2950 0A2E 03 FB ADD DI, BX ; ES:DI -> Upper Left Pixel
\r
2951 0A30 89 7E 04 MOV [BP].DB_Start, DI ; Save Starting Addr
\r
2953 ; Compute line to line offset
\r
2955 0A33 8B 5E 18 MOV BX, [BP].DB_Width ; Get Width of Image
\r
2956 0A36 8B D3 MOV DX, BX ; Save Copy in DX
\r
2957 0A38 C1 EB 02 SHR BX, 2 ; /4 = width in bands
\r
2958 0A3B A1 0000 R MOV AX, SCREEN_WIDTH ; Get Screen Width
\r
2959 0A3E 2B C3 SUB AX, BX ; - (Bitmap Width/4)
\r
2961 0A40 89 46 00 MOV [BP].DB_LineO, AX ; Save Line Width offset
\r
2962 0A43 89 5E 02 MOV [BP].DB_PixCount, BX ; Minimum # pix to copy
\r
2964 0A46 83 E2 03 AND DX, PLANE_BITS ; Get "partial band" size (0-3)
\r
2965 0A49 89 56 06 MOV [BP].DB_PixSkew, DX ; Also End of Line Skew
\r
2966 0A4C 89 56 08 MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count
\r
2968 0A4F 83 E1 03 AND CX, PLANE_BITS ; CL = Starting Plane #
\r
2969 0A52 B8 1102 MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select
\r
2970 0A55 D2 E4 SHL AH, CL ; Select correct Plane
\r
2971 OUT_16 SC_Index, AX ; Select Plane...
\r
2972 0A57 BA 03C4 1 MOV DX, SC_Index ; then Select Register
\r
2973 0A5A EF 1 OUT DX, AX ; Set I/O Register(s)
\r
2974 0A5B 8A FC MOV BH, AH ; BH = Saved Plane Mask
\r
2975 0A5D B3 04 MOV BL, 4 ; BL = Planes to Copy
\r
2977 0A5F @DB_COPY_PLANE:
\r
2979 0A5F C5 76 1E LDS SI, [BP].DB_Image ; DS:SI-> Source Image
\r
2980 0A62 8B 56 16 MOV DX, [BP].DB_Height ; # of Lines to Copy
\r
2981 0A65 8B 7E 04 MOV DI, [BP].DB_Start ; ES:DI-> Dest pos
\r
2983 0A68 @DB_COPY_LINE:
\r
2984 0A68 8B 4E 02 MOV CX, [BP].DB_PixCount ; Min # to copy
\r
2986 0A6B F6 C1 FC TEST CL, 0FCh ; 16+PixWide?
\r
2987 0A6E 74 18 JZ @DB_COPY_REMAINDER ; Nope...
\r
2989 ; Pixel Copy loop has been unrolled to x4
\r
2991 0A70 @DB_COPY_LOOP:
\r
2992 0A70 A4 MOVSB ; Copy Bitmap Pixel
\r
2993 0A71 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane
\r
2994 0A74 A4 MOVSB ; Copy Bitmap Pixel
\r
2995 0A75 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane
\r
2996 0A78 A4 MOVSB ; Copy Bitmap Pixel
\r
2997 0A79 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane
\r
2998 0A7C A4 MOVSB ; Copy Bitmap Pixel
\r
2999 0A7D 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane
\r
3001 0A80 80 E9 04 SUB CL, 4 ; Pixels to Copy=-4
\r
3002 0A83 F6 C1 FC TEST CL, 0FCh ; 4+ Pixels Left?
\r
3003 0A86 75 E8 JNZ @DB_COPY_LOOP ; if so, do another block
\r
3005 0A88 @DB_COPY_REMAINDER:
\r
3006 0A88 E3 07 JCXZ @DB_NEXT_LINE ; Any Pixels left on line
\r
3009 0A8A A4 MOVSB ; Copy Bitmap Pixel
\r
3010 0A8B 83 C6 03 ADD SI,3 ; Skip to Next Byte in same plane
\r
3011 LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done
\r
3012 0A8E 49 1 DEC CX ; Counter--
\r
3013 0A8F 75 F9 1 JNZ @DB_COPY2 ; Jump if not 0
\r
3015 0A91 @DB_NEXT_LINE:
\r
3017 ; any Partial Pixels? (some planes only)
\r
3019 0A91 0B 4E 08 OR CX, [BP].DB_SkewFlag ; Get Skew Count
\r
3020 0A94 74 03 JZ @DB_NEXT2 ; if no partial pixels
\r
3022 0A96 A4 MOVSB ; Copy Bitmap Pixel
\r
3023 0A97 4F DEC DI ; Back up to align
\r
3024 0A98 4E DEC SI ; Back up to align
\r
3027 0A99 03 76 06 ADD SI, [BP].DB_PixSkew ; Adjust Skew
\r
3028 0A9C 03 7E 00 ADD DI, [BP].DB_LineO ; Set to Next Display Line
\r
3029 LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more
\r
3030 0A9F 4A 1 DEC DX ; Counter--
\r
3031 0AA0 75 C6 1 JNZ @DB_COPY_LINE ; Jump if not 0
\r
3033 ; Copy Next Plane....
\r
3035 0AA2 FE CB DEC BL ; Planes to Go--
\r
3036 0AA4 74 1B JZ @DB_Exit ; Hey! We are done
\r
3038 0AA6 D0 C7 ROL BH, 1 ; Next Plane in line...
\r
3039 OUT_8 SC_Data, BH ; Select Plane
\r
3040 0AA8 BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
3041 0AAB 8A C7 1 MOV AL, BH ; then Get Data Value
\r
3042 0AAD EE 1 OUT DX, AL ; Set I/O Register
\r
3044 0AAE 3C 12 CMP AL, 12h ; Carry Set if AL=11h
\r
3045 0AB0 83 56 04 00 ADC [BP].DB_Start, 0 ; Screen Addr =+Carry
\r
3046 0AB4 FF 46 1E INC w [BP].DB_Image ; Start @ Next Byte
\r
3048 0AB7 83 6E 08 01 SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew
\r
3049 0ABB 83 56 08 00 ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1
\r
3051 0ABF EB 9E JMP s @DB_COPY_PLANE ; Go Copy the Next Plane
\r
3054 0AC1 83 C4 0A ADD SP, 10 ; Deallocate workspace
\r
3055 POPx DI, SI, DS, BP ; Restore Saved Registers
\r
3056 0AC4 5F 1 POP DI ; Restore R1
\r
3057 0AC5 5E 2 POP SI ; Restore R1
\r
3058 0AC6 1F 3 POP DS ; Restore R1
\r
3059 0AC7 5D 4 POP BP ; Restore R1
\r
3060 0AC8 CA 000C RET 12 ; Exit and Clean up Stack
\r
3062 0ACB DRAW_BITMAP ENDP
\r
3065 ;=======================================================
\r
3066 ;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)
\r
3067 ;=======================================================
\r
3069 ; Transparently Draws a variable sized Graphics Bitmap
\r
3070 ; such as a picture or an Icon on the current Display Page
\r
3071 ; in Mode X. Pixels with a value of 0 are not drawn,
\r
3072 ; leaving the previous "background" contents intact.
\r
3074 ; The Bitmap format is the same as for the DRAW_BITMAP function.
\r
3076 ; ENTRY: Image = Far Pointer to Bitmap Data
\r
3077 ; Xpos = X position to Place Upper Left pixel at
\r
3078 ; Ypos = Y position to Place Upper Left pixel at
\r
3079 ; Width = Width of the Bitmap in Pixels
\r
3080 ; Height = Height of the Bitmap in Pixels
\r
3082 ; EXIT: No meaningful values returned
\r
3085 0022 TB_STACK STRUC
\r
3086 0000 0000 TB_LineO DW ? ; Offset to Next Line
\r
3087 0002 0000 TB_PixCount DW ? ; (Minimum) # of Pixels/Line
\r
3088 0004 0000 TB_Start DW ? ; Addr of Upper Left Pixel
\r
3089 0006 0000 TB_PixSkew DW ? ; # of bytes to Adjust EOL
\r
3090 0008 0000 TB_SkewFlag DW ? ; Extra Pix on Plane Flag
\r
3091 000A 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP
\r
3093 0012 00000000 DD ? ; Caller
\r
3094 0016 0000 TB_Height DW ? ; Height of Bitmap in Pixels
\r
3095 0018 0000 TB_Width DW ? ; Width of Bitmap in Pixels
\r
3096 001A 0000 TB_Ypos DW ? ; Y position to Draw Bitmap at
\r
3097 001C 0000 TB_Xpos DW ? ; X position to Draw Bitmap at
\r
3098 001E 00000000 TB_Image DD ? ; Far Pointer to Graphics Bitmap
\r
3101 PUBLIC TDRAW_BITMAP
\r
3103 0ACB TDRAW_BITMAP PROC FAR
\r
3105 PUSHx BP, DS, SI, DI ; Preserve Important Registers
\r
3106 0ACB 55 1 PUSH BP ; Save R1
\r
3107 0ACC 1E 2 PUSH DS ; Save R1
\r
3108 0ACD 56 3 PUSH SI ; Save R1
\r
3109 0ACE 57 4 PUSH DI ; Save R1
\r
3110 0ACF 83 EC 0A SUB SP, 10 ; Allocate workspace
\r
3111 0AD2 8B EC MOV BP, SP ; Set up Stack Frame
\r
3113 0AD4 C4 3E 0014 R LES DI, d CURRENT_PAGE ; Point to Active VGA Page
\r
3114 0AD8 FC CLD ; Direction Flag = Forward
\r
3116 0AD9 8B 46 1A MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos
\r
3117 0ADC F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Ypos
\r
3119 0AE0 8B 5E 1C MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos
\r
3120 0AE3 8A CB MOV CL, BL ; Save Plane # in CL
\r
3121 0AE5 C1 EB 02 SHR BX, 2 ; Xpos/4 = Offset Into Line
\r
3123 0AE8 03 F8 ADD DI, AX ; ES:DI -> Start of Line
\r
3124 0AEA 03 FB ADD DI, BX ; ES:DI -> Upper Left Pixel
\r
3125 0AEC 89 7E 04 MOV [BP].TB_Start, DI ; Save Starting Addr
\r
3127 ; Compute line to line offset
\r
3129 0AEF 8B 5E 18 MOV BX, [BP].TB_Width ; Get Width of Image
\r
3130 0AF2 8B D3 MOV DX, BX ; Save Copy in DX
\r
3131 0AF4 C1 EB 02 SHR BX, 2 ; /4 = width in bands
\r
3132 0AF7 A1 0000 R MOV AX, SCREEN_WIDTH ; Get Screen Width
\r
3133 0AFA 2B C3 SUB AX, BX ; - (Bitmap Width/4)
\r
3135 0AFC 89 46 00 MOV [BP].TB_LineO, AX ; Save Line Width offset
\r
3136 0AFF 89 5E 02 MOV [BP].TB_PixCount, BX ; Minimum # pix to copy
\r
3138 0B02 83 E2 03 AND DX, PLANE_BITS ; Get "partial band" size (0-3)
\r
3139 0B05 89 56 06 MOV [BP].TB_PixSkew, DX ; Also End of Line Skew
\r
3140 0B08 89 56 08 MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count
\r
3142 0B0B 83 E1 03 AND CX, PLANE_BITS ; CL = Starting Plane #
\r
3143 0B0E B8 1102 MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select
\r
3144 0B11 D2 E4 SHL AH, CL ; Select correct Plane
\r
3145 OUT_16 SC_Index, AX ; Select Plane...
\r
3146 0B13 BA 03C4 1 MOV DX, SC_Index ; then Select Register
\r
3147 0B16 EF 1 OUT DX, AX ; Set I/O Register(s)
\r
3148 0B17 8A FC MOV BH, AH ; BH = Saved Plane Mask
\r
3149 0B19 B3 04 MOV BL, 4 ; BL = Planes to Copy
\r
3151 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
3152 modex.asm Page 13 - 1
\r
3155 0B1B @TB_COPY_PLANE:
\r
3157 0B1B C5 76 1E LDS SI, [BP].TB_Image ; DS:SI-> Source Image
\r
3158 0B1E 8B 56 16 MOV DX, [BP].TB_Height ; # of Lines to Copy
\r
3159 0B21 8B 7E 04 MOV DI, [BP].TB_Start ; ES:DI-> Dest pos
\r
3161 ; Here AH is set with the value to be considered
\r
3162 ; "Transparent". It can be changed!
\r
3164 0B24 B4 00 MOV AH, 0 ; Value to Detect 0
\r
3166 0B26 @TB_COPY_LINE:
\r
3167 0B26 8B 4E 02 MOV CX, [BP].TB_PixCount ; Min # to copy
\r
3169 0B29 F6 C1 FC TEST CL, 0FCh ; 16+PixWide?
\r
3170 0B2C 74 3A JZ @TB_COPY_REMAINDER ; Nope...
\r
3172 ; Pixel Copy loop has been unrolled to x4
\r
3174 0B2E @TB_COPY_LOOP:
\r
3175 0B2E AC LODSB ; Get Pixel Value in AL
\r
3176 0B2F 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane
\r
3177 0B32 38 E0 CMP AL, AH ; It is "Transparent"?
\r
3178 0B34 74 03 JE @TB_SKIP_01 ; Skip ahead if so
\r
3179 0B36 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen
\r
3182 0B39 AC LODSB ; Get Pixel Value in AL
\r
3183 0B3A 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane
\r
3184 0B3D 38 E0 CMP AL, AH ; It is "Transparent"?
\r
3185 0B3F 74 04 JE @TB_SKIP_02 ; Skip ahead if so
\r
3186 0B41 26: 88 45 01 MOV ES:[DI+1], AL ; Copy Pixel to VGA screen
\r
3189 0B45 AC LODSB ; Get Pixel Value in AL
\r
3190 0B46 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane
\r
3191 0B49 38 E0 CMP AL, AH ; It is "Transparent"?
\r
3192 0B4B 74 04 JE @TB_SKIP_03 ; Skip ahead if so
\r
3193 0B4D 26: 88 45 02 MOV ES:[DI+2], AL ; Copy Pixel to VGA screen
\r
3196 0B51 AC LODSB ; Get Pixel Value in AL
\r
3197 0B52 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane
\r
3198 0B55 38 E0 CMP AL, AH ; It is "Transparent"?
\r
3199 0B57 74 04 JE @TB_SKIP_04 ; Skip ahead if so
\r
3200 0B59 26: 88 45 03 MOV ES:[DI+3], AL ; Copy Pixel to VGA screen
\r
3203 0B5D 83 C7 04 ADD DI, 4 ; Adjust Pixel Write Location
\r
3204 0B60 80 E9 04 SUB CL, 4 ; Pixels to Copy=-4
\r
3205 0B63 F6 C1 FC TEST CL, 0FCh ; 4+ Pixels Left?
\r
3206 0B66 75 C6 JNZ @TB_COPY_LOOP ; if so, do another block
\r
3208 0B68 @TB_COPY_REMAINDER:
\r
3209 0B68 E3 0F JCXZ @TB_NEXT_LINE ; Any Pixels left on line
\r
3212 0B6A AC LODSB ; Get Pixel Value in AL
\r
3213 0B6B 83 C6 03 ADD SI, 3 ; Skip to Next Byte in same plane
\r
3214 0B6E 38 E0 CMP AL, AH ; It is "Transparent"?
\r
3215 0B70 74 03 JE @TB_SKIP_05 ; Skip ahead if so
\r
3216 0B72 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen
\r
3219 0B75 47 INC DI ; Advance Dest Addr
\r
3220 LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done
\r
3221 0B76 49 1 DEC CX ; Counter--
\r
3222 0B77 75 F1 1 JNZ @TB_COPY2 ; Jump if not 0
\r
3224 0B79 @TB_NEXT_LINE:
\r
3226 ; any Partial Pixels? (some planes only)
\r
3228 0B79 0B 4E 08 OR CX, [BP].TB_SkewFlag ; Get Skew Count
\r
3229 0B7C 74 09 JZ @TB_NEXT2 ; if no partial pixels
\r
3231 0B7E AC LODSB ; Get Pixel Value in AL
\r
3232 0B7F 4E DEC SI ; Backup to Align
\r
3233 0B80 38 E0 CMP AL, AH ; It is "Transparent"?
\r
3234 0B82 74 03 JE @TB_NEXT2 ; Skip ahead if so
\r
3235 0B84 26: 88 05 MOV ES:[DI], AL ; Copy Pixel to VGA screen
\r
3238 0B87 03 76 06 ADD SI, [BP].TB_PixSkew ; Adjust Skew
\r
3239 0B8A 03 7E 00 ADD DI, [BP].TB_LineO ; Set to Next Display Line
\r
3240 LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More
\r
3241 0B8D 4A 1 DEC DX ; Counter--
\r
3242 0B8E 75 96 1 JNZ @TB_COPY_LINE ; Jump if not 0
\r
3244 ;Copy Next Plane....
\r
3246 0B90 FE CB DEC BL ; Planes to Go--
\r
3247 0B92 74 1C JZ @TB_Exit ; Hey! We are done
\r
3249 0B94 D0 C7 ROL BH, 1 ; Next Plane in line...
\r
3250 OUT_8 SC_Data, BH ; Select Plane
\r
3251 0B96 BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
3252 0B99 8A C7 1 MOV AL, BH ; then Get Data Value
\r
3253 0B9B EE 1 OUT DX, AL ; Set I/O Register
\r
3255 0B9C 3C 12 CMP AL, 12h ; Carry Set if AL=11h
\r
3256 0B9E 83 56 04 00 ADC [BP].TB_Start, 0 ; Screen Addr =+Carry
\r
3257 0BA2 FF 46 1E INC w [BP].TB_Image ; Start @ Next Byte
\r
3259 0BA5 83 6E 08 01 SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew
\r
3260 0BA9 83 56 08 00 ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1
\r
3262 0BAD E9 FF6B JMP @TB_COPY_PLANE ; Go Copy the next Plane
\r
3265 0BB0 83 C4 0A ADD SP, 10 ; Deallocate workspace
\r
3266 POPx DI, SI, DS, BP ; Restore Saved Registers
\r
3267 0BB3 5F 1 POP DI ; Restore R1
\r
3268 0BB4 5E 2 POP SI ; Restore R1
\r
3269 0BB5 1F 3 POP DS ; Restore R1
\r
3270 0BB6 5D 4 POP BP ; Restore R1
\r
3271 0BB7 CA 000C RET 12 ; Exit and Clean up Stack
\r
3273 0BBA TDRAW_BITMAP ENDP
\r
3276 ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====
\r
3278 ;==================================
\r
3279 ;COPY_PAGE (SourcePage%, DestPage%)
\r
3280 ;==================================
\r
3282 ; Duplicate on display page onto another
\r
3284 ; ENTRY: SourcePage = Display Page # to Duplicate
\r
3285 ; DestPage = Display Page # to hold copy
\r
3287 ; EXIT: No meaningful values returned
\r
3290 0010 CP_STACK STRUC
\r
3291 0000 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP
\r
3293 0008 00000000 DD ? ; Caller
\r
3294 000C 0000 CP_DestP DW ? ; Page to hold copied image
\r
3295 000E 0000 CP_SourceP DW ? ; Page to Make copy from
\r
3300 0BBA COPY_PAGE PROC FAR
\r
3302 PUSHx BP, DS, SI, DI ; Preserve Important Registers
\r
3303 0BBA 55 1 PUSH BP ; Save R1
\r
3304 0BBB 1E 2 PUSH DS ; Save R1
\r
3305 0BBC 56 3 PUSH SI ; Save R1
\r
3306 0BBD 57 4 PUSH DI ; Save R1
\r
3307 0BBE 8B EC MOV BP, SP ; Set up Stack Frame
\r
3308 0BC0 FC CLD ; Block Xfer Forwards
\r
3310 ; Make sure Page #'s are valid
\r
3312 0BC1 8B 46 0E MOV AX, [BP].CP_SourceP ; Get Source Page #
\r
3313 0BC4 3B 06 0004 R CMP AX, LAST_PAGE ; is it > Max Page #?
\r
3314 0BC8 73 3D JAE @CP_Exit ; if so, abort
\r
3316 0BCA 8B 5E 0C MOV BX, [BP].CP_DestP ; Get Destination Page #
\r
3317 0BCD 3B 1E 0004 R CMP BX, LAST_PAGE ; is it > Max Page #?
\r
3318 0BD1 73 34 JAE @CP_Exit ; if so, abort
\r
3320 0BD3 3B C3 CMP AX, BX ; Pages #'s the same?
\r
3321 0BD5 74 30 JE @CP_Exit ; if so, abort
\r
3323 ; Setup DS:SI and ES:DI to Video Pages
\r
3325 0BD7 D1 E3 SHL BX, 1 ; Scale index to Word
\r
3326 0BD9 8B BF 0006 R MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page
\r
3328 0BDD 8B D8 MOV BX, AX ; Index to Source page
\r
3329 0BDF D1 E3 SHL BX, 1 ; Scale index to Word
\r
3330 0BE1 8B B7 0006 R MOV SI, PAGE_ADDR[BX] ; Offset to Source Page
\r
3332 0BE5 8B 0E 000E R MOV CX, PAGE_SIZE ; Get size of Page
\r
3333 0BE9 A1 0016 R MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment
\r
3334 0BEC 8E C0 MOV ES, AX ; ES:DI -> Dest Page
\r
3335 0BEE 8E D8 MOV DS, AX ; DS:SI -> Source Page
\r
3337 ; Setup VGA registers for Mem to Mem copy
\r
3339 OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on
\r
3340 0BF0 BA 03CE 1 MOV DX, GC_Index ; then Select Register
\r
3341 0BF3 B8 0008 1 MOV AX, LATCHES_ON ; then Get Data Value
\r
3342 0BF6 EF 1 OUT DX, AX ; Set I/O Register(s)
\r
3343 OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes
\r
3344 0BF7 BA 03C4 1 MOV DX, SC_Index ; then Select Register
\r
3345 0BFA B8 0F02 1 MOV AX, ALL_PLANES_ON ; then Get Data Value
\r
3346 0BFD EF 1 OUT DX, AX ; Set I/O Register(s)
\r
3348 ; Note.. Do *NOT* use MOVSW or MOVSD - they will
\r
3349 ; Screw with the latches which are 8 bits x 4
\r
3351 0BFE F3/ A4 REP MOVSB ; Copy entire Page!
\r
3353 ; Reset VGA for normal memory access
\r
3355 OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off
\r
3356 0C00 BA 03CE 1 MOV DX, GC_Index ; then Select Register
\r
3357 0C03 B8 FF08 1 MOV AX, LATCHES_OFF ; then Get Data Value
\r
3358 0C06 EF 1 OUT DX, AX ; Set I/O Register(s)
\r
3361 POPx DI, SI, DS, BP ; Restore Saved Registers
\r
3362 0C07 5F 1 POP DI ; Restore R1
\r
3363 0C08 5E 2 POP SI ; Restore R1
\r
3364 0C09 1F 3 POP DS ; Restore R1
\r
3365 0C0A 5D 4 POP BP ; Restore R1
\r
3366 0C0B CA 0004 RET 4 ; Exit and Clean up Stack
\r
3368 0C0E COPY_PAGE ENDP
\r
3371 ;==========================================================================
\r
3372 ;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%)
\r
3373 ;==========================================================================
\r
3375 ; Copies a Bitmap Image from one Display Page to Another
\r
3376 ; This Routine is Limited to copying Images with the same
\r
3377 ; Plane Alignment. To Work: (X1 MOD 4) must = (DestX1 MOD 4)
\r
3378 ; Copying an Image to the Same Page is supported, but results
\r
3379 ; may be defined when the when the rectangular areas
\r
3380 ; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) -
\r
3381 ; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap...
\r
3382 ; No Paramter checking to done to insure that
\r
3383 ; X2 >= X1 and Y2 >= Y1. Be Careful...
\r
3385 ; ENTRY: SourcePage = Display Page # with Source Image
\r
3386 ; X1 = Upper Left Xpos of Source Image
\r
3387 ; Y1 = Upper Left Ypos of Source Image
\r
3388 ; X2 = Lower Right Xpos of Source Image
\r
3389 ; Y2 = Lower Right Ypos of Source Image
\r
3390 ; DestPage = Display Page # to copy Image to
\r
3391 ; DestX1 = Xpos to Copy UL Corner of Image to
\r
3392 ; DestY1 = Ypos to Copy UL Corner of Image to
\r
3394 ; EXIT: AX = Success Flag: 0 = Failure / -1= Success
\r
3397 0020 CB_STACK STRUC
\r
3398 0000 0000 CB_Height DW ? ; Height of Image in Lines
\r
3399 0002 0000 CB_Width DW ? ; Width of Image in "bands"
\r
3400 0004 0000 0000 0000 DW ?x4 ; DI, SI, DS, BP
\r
3402 000C 00000000 DD ? ; Caller
\r
3403 0010 0000 CB_DestY1 DW ? ; Destination Ypos
\r
3404 0012 0000 CB_DestX1 DW ? ; Destination Xpos
\r
3405 0014 0000 CB_DestP DW ? ; Page to Copy Bitmap To
\r
3406 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
3407 modex.asm Page 14 - 1
\r
3410 0016 0000 CB_Y2 DW ? ; LR Ypos of Image
\r
3411 0018 0000 CB_X2 DW ? ; LR Xpos of Image
\r
3412 001A 0000 CB_Y1 DW ? ; UL Ypos of Image
\r
3413 001C 0000 CB_X1 DW ? ; UL Xpos of Image
\r
3414 001E 0000 CB_SourceP DW ? ; Page containing Source Bitmap
\r
3417 PUBLIC COPY_BITMAP
\r
3419 0C0E COPY_BITMAP PROC FAR
\r
3421 PUSHx BP, DS, SI, DI ; Preserve Important Registers
\r
3422 0C0E 55 1 PUSH BP ; Save R1
\r
3423 0C0F 1E 2 PUSH DS ; Save R1
\r
3424 0C10 56 3 PUSH SI ; Save R1
\r
3425 0C11 57 4 PUSH DI ; Save R1
\r
3426 0C12 83 EC 04 SUB SP, 4 ; Allocate WorkSpace on Stack
\r
3427 0C15 8B EC MOV BP, SP ; Set up Stack Frame
\r
3429 ; Prep Registers (and keep jumps short!)
\r
3431 0C17 8E 06 0016 R MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram
\r
3432 0C1B FC CLD ; Block Xfer Forwards
\r
3434 ; Make sure Parameters are valid
\r
3436 0C1C 8B 5E 1E MOV BX, [BP].CB_SourceP ; Get Source Page #
\r
3437 0C1F 3B 1E 0004 R CMP BX, LAST_PAGE ; is it > Max Page #?
\r
3438 0C23 73 7D JAE @CB_Abort ; if so, abort
\r
3440 0C25 8B 4E 14 MOV CX, [BP].CB_DestP ; Get Destination Page #
\r
3441 0C28 3B 0E 0004 R CMP CX, LAST_PAGE ; is it > Max Page #?
\r
3442 0C2C 73 74 JAE @CB_Abort ; if so, abort
\r
3444 0C2E 8B 46 1C MOV AX, [BP].CB_X1 ; Get Source X1
\r
3445 0C31 33 46 12 XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1
\r
3446 0C34 83 E0 03 AND AX, PLANE_BITS ; Check Plane Bits
\r
3447 0C37 75 69 JNZ @CB_Abort ; They should cancel out
\r
3449 ; Setup for Copy processing
\r
3451 OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select
\r
3452 0C39 BA 03C4 1 MOV DX, SC_INDEX ; then Select Register
\r
3453 0C3C B0 02 1 MOV AL, MAP_MASK ; then Get Data Value
\r
3454 0C3E EE 1 OUT DX, AL ; Set I/O Register
\r
3455 OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on
\r
3456 0C3F BA 03CE 1 MOV DX, GC_Index ; then Select Register
\r
3457 0C42 B8 0008 1 MOV AX, LATCHES_ON ; then Get Data Value
\r
3458 0C45 EF 1 OUT DX, AX ; Set I/O Register(s)
\r
3460 ; Compute Info About Images, Setup ES:SI & ES:DI
\r
3462 0C46 8B 46 16 MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines
\r
3463 0C49 2B 46 1A SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1
\r
3464 0C4C 40 INC AX ; (add 1 since were not 0 based)
\r
3465 0C4D 89 46 00 MOV [BP].CB_Height, AX ; Save on Stack for later use
\r
3467 0C50 8B 46 18 MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels
\r
3468 0C53 8B 56 1C MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1
\r
3469 0C56 C1 E8 02 SHR AX, 2 ; Get X2 Band (X2 / 4)
\r
3470 0C59 C1 EA 02 SHR DX, 2 ; Get X1 Band (X1 / 4)
\r
3471 0C5C 2B C2 SUB AX, DX ; AX = # of Bands - 1
\r
3472 0C5E 40 INC AX ; AX = # of Bands
\r
3473 0C5F 89 46 02 MOV [BP].CB_Width, AX ; Save on Stack for later use
\r
3475 0C62 D1 E3 SHL BX, 1 ; Scale Source Page to Word
\r
3476 0C64 8B B7 0006 R MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page
\r
3477 0C68 8B 46 1A MOV AX, [BP].CB_Y1 ; Get Source Y1 Line
\r
3478 0C6B F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Y1
\r
3479 0C6F 03 F0 ADD SI, AX ; SI = Offset to Line Y1
\r
3480 0C71 8B 46 1C MOV AX, [BP].CB_X1 ; Get Source X1
\r
3481 0C74 C1 E8 02 SHR AX, 2 ; X1 / 4 = Byte offset
\r
3482 0C77 03 F0 ADD SI, AX ; SI = Byte Offset to (X1,Y1)
\r
3484 0C79 8B D9 MOV BX, CX ; Dest Page Index to BX
\r
3485 0C7B D1 E3 SHL BX, 1 ; Scale Source Page to Word
\r
3486 0C7D 8B BF 0006 R MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page
\r
3487 0C81 8B 46 10 MOV AX, [BP].CB_DestY1 ; Get Dest Y1 Line
\r
3488 0C84 F7 26 0000 R MUL SCREEN_WIDTH ; AX = Offset to Line Y1
\r
3489 0C88 03 F8 ADD DI, AX ; DI = Offset to Line Y1
\r
3490 0C8A 8B 46 12 MOV AX, [BP].CB_DestX1 ; Get Dest X1
\r
3491 0C8D C1 E8 02 SHR AX, 2 ; X1 / 4 = Byte offset
\r
3492 0C90 03 F8 ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1)
\r
3494 0C92 8B 4E 02 MOV CX, [BP].CB_Width ; CX = Width of Image (Bands)
\r
3495 0C95 49 DEC CX ; CX = 1?
\r
3496 0C96 74 0F JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band
\r
3498 0C98 8B 5E 1C MOV BX, [BP].CB_X1 ; Get Source X1
\r
3499 0C9B 83 E3 03 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?)
\r
3500 0C9E 74 70 JZ @CB_Check_Right ; if so, check right alignment
\r
3501 0CA0 75 41 JNZ @CB_Left_Band ; not aligned? well..
\r
3504 CLR AX ; Return False (Failure)
\r
3505 0CA2 33 C0 1 XOR AX, AX ; Set Register = 0
\r
3506 0CA4 E9 00D7 JMP @CB_Exit ; and Finish Up
\r
3508 ; Copy when Left & Right Clip Masks overlap...
\r
3510 0CA7 @CB_Only_One_Band:
\r
3511 0CA7 8B 5E 1C MOV BX, [BP].CB_X1 ; Get Left Clip Mask
\r
3512 0CAA 83 E3 03 AND BX, PLANE_BITS ; Mask out Row #
\r
3513 0CAD 2E: 8A 87 0000 R MOV AL, Left_Clip_Mask[BX] ; Get Left Edge Mask
\r
3514 0CB2 8B 5E 18 MOV BX, [BP].CB_X2 ; Get Right Clip Mask
\r
3515 0CB5 83 E3 03 AND BX, PLANE_BITS ; Mask out Row #
\r
3516 0CB8 2E: 22 87 0004 R AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte
\r
3518 OUT_8 SC_Data, AL ; Clip For Left & Right Masks
\r
3519 0CBD BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
3520 0CC0 EE 1 OUT DX, AL ; Set I/O Register
\r
3522 0CC1 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy
\r
3523 0CC4 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen
\r
3524 CLR BX ; BX = Offset into Image
\r
3525 0CC8 33 DB 1 XOR BX, BX ; Set Register = 0
\r
3527 0CCA @CB_One_Loop:
\r
3528 0CCA 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches
\r
3529 0CCD 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches
\r
3530 0CD0 03 DA ADD BX, DX ; Advance Offset to Next Line
\r
3531 LOOPjz CX, @CB_One_Done ; Exit Loop if Finished
\r
3532 0CD2 49 1 DEC CX ; Counter--
\r
3533 0CD3 74 0B 1 JZ @CB_One_Done ; Jump if 0
\r
3535 0CD5 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches
\r
3536 0CD8 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches
\r
3537 0CDB 03 DA ADD BX, DX ; Advance Offset to Next Line
\r
3538 LOOPx CX, @CB_One_Loop ; Loop until Finished
\r
3539 0CDD 49 1 DEC CX ; Counter--
\r
3540 0CDE 75 EA 1 JNZ @CB_One_Loop ; Jump if not 0
\r
3542 0CE0 @CB_One_Done:
\r
3543 0CE0 E9 0094 JMP @CB_Finish ; Outa Here!
\r
3545 ; Copy Left Edge of Bitmap
\r
3547 0CE3 @CB_Left_Band:
\r
3549 OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask
\r
3550 0CE3 BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
3551 0CE6 2E: 8A 87 0000 R 1 MOV AL, Left_Clip_Mask[BX] ; then Get Data Value
\r
3552 0CEB EE 1 OUT DX, AL ; Set I/O Register
\r
3554 0CEC 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy
\r
3555 0CEF 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen
\r
3556 CLR BX ; BX = Offset into Image
\r
3557 0CF3 33 DB 1 XOR BX, BX ; Set Register = 0
\r
3559 0CF5 @CB_Left_Loop:
\r
3560 0CF5 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches
\r
3561 0CF8 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches
\r
3562 0CFB 03 DA ADD BX, DX ; Advance Offset to Next Line
\r
3563 LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished
\r
3564 0CFD 49 1 DEC CX ; Counter--
\r
3565 0CFE 74 0B 1 JZ @CB_Left_Done ; Jump if 0
\r
3567 0D00 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches
\r
3568 0D03 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches
\r
3569 0D06 03 DA ADD BX, DX ; Advance Offset to Next Line
\r
3570 LOOPx CX, @CB_Left_Loop ; Loop until Finished
\r
3571 0D08 49 1 DEC CX ; Counter--
\r
3572 0D09 75 EA 1 JNZ @CB_Left_Loop ; Jump if not 0
\r
3574 0D0B @CB_Left_Done:
\r
3575 0D0B 47 INC DI ; Move Dest Over 1 band
\r
3576 0D0C 46 INC SI ; Move Source Over 1 band
\r
3577 0D0D FF 4E 02 DEC [BP].CB_Width ; Band Width--
\r
3579 ; Determine if Right Edge of Bitmap needs special copy
\r
3581 0D10 @CB_Check_Right:
\r
3582 0D10 8B 5E 18 MOV BX, [BP].CB_X2 ; Get Source X2
\r
3583 0D13 83 E3 03 AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?)
\r
3584 0D16 80 FB 03 CMP BL, 03h ; Plane = 3?
\r
3585 0D19 74 2C JE @CB_Copy_Middle ; Copy the Middle then!
\r
3587 ; Copy Right Edge of Bitmap
\r
3589 0D1B @CB_Right_Band:
\r
3591 OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask
\r
3592 0D1B BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
3593 0D1E 2E: 8A 87 0004 R 1 MOV AL, Right_Clip_Mask[BX] ; then Get Data Value
\r
3594 0D23 EE 1 OUT DX, AL ; Set I/O Register
\r
3596 0D24 FF 4E 02 DEC [BP].CB_Width ; Band Width--
\r
3597 0D27 8B 4E 00 MOV CX, [BP].CB_Height ; CX = # of Lines to Copy
\r
3598 0D2A 8B 16 0000 R MOV DX, SCREEN_WIDTH ; DX = Width of Screen
\r
3599 0D2E 8B 5E 02 MOV BX, [BP].CB_Width ; BX = Offset to Right Edge
\r
3601 0D31 @CB_Right_Loop:
\r
3602 0D31 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches
\r
3603 0D34 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches
\r
3604 0D37 03 DA ADD BX, DX ; Advance Offset to Next Line
\r
3605 LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished
\r
3606 0D39 49 1 DEC CX ; Counter--
\r
3607 0D3A 74 0B 1 JZ @CB_Right_Done ; Jump if 0
\r
3609 0D3C 26: 8A 00 MOV AL, ES:[SI+BX] ; Load Latches
\r
3610 0D3F 26: 88 01 MOV ES:[DI+BX], AL ; Unload Latches
\r
3611 0D42 03 DA ADD BX, DX ; Advance Offset to Next Line
\r
3612 LOOPx CX, @CB_Right_Loop ; Loop until Finished
\r
3613 0D44 49 1 DEC CX ; Counter--
\r
3614 0D45 75 EA 1 JNZ @CB_Right_Loop ; Jump if not 0
\r
3616 0D47 @CB_Right_Done:
\r
3618 ; Copy the Main Block of the Bitmap
\r
3620 0D47 @CB_Copy_Middle:
\r
3622 0D47 8B 4E 02 MOV CX, [BP].CB_Width ; Get Width Remaining
\r
3623 0D4A E3 2B JCXZ @CB_Finish ; Exit if Done
\r
3625 OUT_8 SC_Data, ALL_PLANES ; Copy all Planes
\r
3626 0D4C BA 03C5 1 MOV DX, SC_Data ; then Select Register
\r
3627 0D4F B0 0F 1 MOV AL, ALL_PLANES ; then Get Data Value
\r
3628 0D51 EE 1 OUT DX, AL ; Set I/O Register
\r
3630 0D52 8B 16 0000 R MOV DX, SCREEN_WIDTH ; Get Width of Screen minus
\r
3631 0D56 2B D1 SUB DX, CX ; Image width (for Adjustment)
\r
3632 0D58 8B 46 00 MOV AX, [BP].CB_Height ; AX = # of Lines to Copy
\r
3633 0D5B 8B D9 MOV BX, CX ; BX = Quick REP reload count
\r
3634 0D5D 8C C1 MOV CX, ES ; Move VGA Segment
\r
3635 0D5F 8E D9 MOV DS, CX ; Into DS
\r
3637 ; Actual Copy Loop. REP MOVSB does the work
\r
3639 0D61 @CB_Middle_Copy:
\r
3640 0D61 8B CB MOV CX, BX ; Recharge Rep Count
\r
3641 0D63 F3/ A4 REP MOVSB ; Move Bands
\r
3642 LOOPjz AX, @CB_Finish ; Exit Loop if Finished
\r
3643 0D65 48 1 DEC AX ; Counter--
\r
3644 0D66 74 0F 1 JZ @CB_Finish ; Jump if 0
\r
3646 0D68 03 F2 ADD SI, DX ; Adjust DS:SI to Next Line
\r
3647 0D6A 03 FA ADD DI, DX ; Adjust ES:DI to Next Line
\r
3649 0D6C 8B CB MOV CX, BX ; Recharge Rep Count
\r
3650 0D6E F3/ A4 REP MOVSB ; Move Bands
\r
3652 0D70 03 F2 ADD SI, DX ; Adjust DS:SI to Next Line
\r
3653 0D72 03 FA ADD DI, DX ; Adjust ES:DI to Next Line
\r
3654 LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done
\r
3655 0D74 48 1 DEC AX ; Counter--
\r
3656 0D75 75 EA 1 JNZ @CB_Middle_Copy ; Jump if not 0
\r
3659 OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on
\r
3660 0D77 BA 03CE 1 MOV DX, GC_Index ; then Select Register
\r
3661 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
3662 modex.asm Page 15 - 1
\r
3665 0D7A B8 FF08 1 MOV AX, LATCHES_OFF ; then Get Data Value
\r
3666 0D7D EF 1 OUT DX, AX ; Set I/O Register(s)
\r
3669 0D7E 83 C4 04 ADD SP, 04 ; Deallocate stack workspace
\r
3670 POPx DI, SI, DS, BP ; Restore Saved Registers
\r
3671 0D81 5F 1 POP DI ; Restore R1
\r
3672 0D82 5E 2 POP SI ; Restore R1
\r
3673 0D83 1F 3 POP DS ; Restore R1
\r
3674 0D84 5D 4 POP BP ; Restore R1
\r
3675 0D85 CA 0010 RET 16 ; Exit and Clean up Stack
\r
3677 0D88 COPY_BITMAP ENDP
\r
3679 END ; End of Code Segment
\r
3680 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
3681 modex.asm Symbols 16 - 1
\r
3690 CLR . . . . . . . . . . . . . . Proc
\r
3691 LOOPjz . . . . . . . . . . . . . Proc
\r
3692 LOOPx . . . . . . . . . . . . . Proc
\r
3693 OUT_16 . . . . . . . . . . . . . Proc
\r
3694 OUT_8 . . . . . . . . . . . . . Proc
\r
3695 POPx . . . . . . . . . . . . . . Proc
\r
3696 PUSHx . . . . . . . . . . . . . Proc
\r
3697 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
3698 modex.asm Symbols 17 - 1
\r
3703 Structures and Unions:
\r
3708 CB_STACK . . . . . . . . . . . . 0020
\r
3709 CB_Height . . . . . . . . . . 0000 Word
\r
3710 CB_Width . . . . . . . . . . . 0002 Word
\r
3711 CB_DestY1 . . . . . . . . . . 0010 Word
\r
3712 CB_DestX1 . . . . . . . . . . 0012 Word
\r
3713 CB_DestP . . . . . . . . . . . 0014 Word
\r
3714 CB_Y2 . . . . . . . . . . . . 0016 Word
\r
3715 CB_X2 . . . . . . . . . . . . 0018 Word
\r
3716 CB_Y1 . . . . . . . . . . . . 001A Word
\r
3717 CB_X1 . . . . . . . . . . . . 001C Word
\r
3718 CB_SourceP . . . . . . . . . . 001E Word
\r
3719 CP_STACK . . . . . . . . . . . . 0010
\r
3720 CP_DestP . . . . . . . . . . . 000C Word
\r
3721 CP_SourceP . . . . . . . . . . 000E Word
\r
3722 CVS_STACK . . . . . . . . . . . 000A
\r
3723 CVS_COLOR . . . . . . . . . . 0008 Byte
\r
3724 DB_STACK . . . . . . . . . . . . 0022
\r
3725 DB_LineO . . . . . . . . . . . 0000 Word
\r
3726 DB_PixCount . . . . . . . . . 0002 Word
\r
3727 DB_Start . . . . . . . . . . . 0004 Word
\r
3728 DB_PixSkew . . . . . . . . . . 0006 Word
\r
3729 DB_SkewFlag . . . . . . . . . 0008 Word
\r
3730 DB_Height . . . . . . . . . . 0016 Word
\r
3731 DB_Width . . . . . . . . . . . 0018 Word
\r
3732 DB_Ypos . . . . . . . . . . . 001A Word
\r
3733 DB_Xpos . . . . . . . . . . . 001C Word
\r
3734 DB_Image . . . . . . . . . . . 001E DWord
\r
3735 DL_STACK . . . . . . . . . . . . 0014
\r
3736 DL_ColorF . . . . . . . . . . 000A Byte
\r
3737 DL_Ypos2 . . . . . . . . . . . 000C Word
\r
3738 DL_Xpos2 . . . . . . . . . . . 000E Word
\r
3739 DL_Ypos1 . . . . . . . . . . . 0010 Word
\r
3740 DL_Xpos1 . . . . . . . . . . . 0012 Word
\r
3741 FB_STACK . . . . . . . . . . . . 0016
\r
3742 FB_Color . . . . . . . . . . . 000C Byte
\r
3743 FB_Ypos2 . . . . . . . . . . . 000E Word
\r
3744 FB_Xpos2 . . . . . . . . . . . 0010 Word
\r
3745 FB_Ypos1 . . . . . . . . . . . 0012 Word
\r
3746 FB_Xpos1 . . . . . . . . . . . 0014 Word
\r
3747 GDR_STACK . . . . . . . . . . . 000E
\r
3748 GDR_Blue . . . . . . . . . . . 0006 Word
\r
3749 GDR_Green . . . . . . . . . . 0008 Word
\r
3750 GDR_Red . . . . . . . . . . . 000A Word
\r
3751 GDR_Register . . . . . . . . . 000C Byte
\r
3752 GPC_STACK . . . . . . . . . . . 001E
\r
3753 GPC_Width . . . . . . . . . . 0000 Word
\r
3754 GPC_Lines . . . . . . . . . . 0002 Byte
\r
3755 GPC_T_SETS . . . . . . . . . . 0004 Word
\r
3756 GPC_T_SETO . . . . . . . . . . 0006 Word
\r
3757 GPC_ColorB . . . . . . . . . . 0014 Byte
\r
3758 GPC_ColorF . . . . . . . . . . 0016 Byte
\r
3759 GPC_Ypos . . . . . . . . . . . 0018 Word
\r
3760 GPC_Xpos . . . . . . . . . . . 001A Word
\r
3761 GPC_Char . . . . . . . . . . . 001C Byte
\r
3762 LDR_STACK . . . . . . . . . . . 0014
\r
3763 LDR_Sync . . . . . . . . . . . 000A Word
\r
3764 LDR_EndReg . . . . . . . . . . 000C Byte
\r
3765 LDR_StartReg . . . . . . . . . 000E Byte
\r
3766 LDR_PalData . . . . . . . . . 0010 DWord
\r
3767 Mode_Data_Table . . . . . . . . 000C
\r
3768 M_MiscR . . . . . . . . . . . 0000 Byte
\r
3769 M_Pages . . . . . . . . . . . 0001 Byte
\r
3770 M_XSize . . . . . . . . . . . 0002 Word
\r
3771 M_YSize . . . . . . . . . . . 0004 Word
\r
3772 M_XMax . . . . . . . . . . . . 0006 Word
\r
3773 M_YMax . . . . . . . . . . . . 0008 Word
\r
3774 M_CRTC . . . . . . . . . . . . 000A Word
\r
3775 PS_STACK . . . . . . . . . . . . 001A
\r
3776 PS_ColorB . . . . . . . . . . 000C Word
\r
3777 PS_ColorF . . . . . . . . . . 000E Word
\r
3778 PS_Ypos . . . . . . . . . . . 0010 Word
\r
3779 PS_Xpos . . . . . . . . . . . 0012 Word
\r
3780 PS_Len . . . . . . . . . . . . 0014 Word
\r
3781 PS_Text . . . . . . . . . . . 0016 Word
\r
3782 RDR_STACK . . . . . . . . . . . 0012
\r
3783 RDR_EndReg . . . . . . . . . . 000A Byte
\r
3784 RDR_StartReg . . . . . . . . . 000C Byte
\r
3785 RDR_PalData . . . . . . . . . 000E DWord
\r
3786 RP_STACK . . . . . . . . . . . . 000C
\r
3787 RP_Ypos . . . . . . . . . . . 0008 Word
\r
3788 RP_Xpos . . . . . . . . . . . 000A Word
\r
3789 SAP_STACK . . . . . . . . . . . 0008
\r
3790 SAP_Page . . . . . . . . . . . 0006 Word
\r
3791 SDF_STACK . . . . . . . . . . . 000C
\r
3792 SDF_Which . . . . . . . . . . 0006 Word
\r
3793 SDF_Font . . . . . . . . . . . 0008 DWord
\r
3794 SDP_STACK . . . . . . . . . . . 0008
\r
3795 SDP_Page . . . . . . . . . . . 0006 Word
\r
3796 SDR_STACK . . . . . . . . . . . 000E
\r
3797 SDR_Blue . . . . . . . . . . . 0006 Byte
\r
3798 SDR_Green . . . . . . . . . . 0008 Byte
\r
3799 SDR_Red . . . . . . . . . . . 000A Byte
\r
3800 SDR_Register . . . . . . . . . 000C Byte
\r
3801 SM_STACK . . . . . . . . . . . . 000A
\r
3802 SM_Mode . . . . . . . . . . . 0008 Word
\r
3803 SP_STACK . . . . . . . . . . . . 000E
\r
3804 SETP_Color . . . . . . . . . . 0008 Byte
\r
3805 SETP_Ypos . . . . . . . . . . 000A Word
\r
3806 SETP_Xpos . . . . . . . . . . 000C Word
\r
3807 SVM_STACK . . . . . . . . . . . 0016
\r
3808 SVM_Table . . . . . . . . . . 0000 Word
\r
3809 SVM_Pages . . . . . . . . . . 000E Word
\r
3810 SVM_Ysize . . . . . . . . . . 0010 Word
\r
3811 SVM_Xsize . . . . . . . . . . 0012 Word
\r
3812 SVM_Mode . . . . . . . . . . . 0014 Word
\r
3813 SW_STACK . . . . . . . . . . . . 000C
\r
3814 SW_Ypos . . . . . . . . . . . 0006 Word
\r
3815 SW_Xpos . . . . . . . . . . . 0008 Word
\r
3816 SW_Page . . . . . . . . . . . 000A Word
\r
3817 TB_STACK . . . . . . . . . . . . 0022
\r
3818 TB_LineO . . . . . . . . . . . 0000 Word
\r
3819 TB_PixCount . . . . . . . . . 0002 Word
\r
3820 TB_Start . . . . . . . . . . . 0004 Word
\r
3821 TB_PixSkew . . . . . . . . . . 0006 Word
\r
3822 TB_SkewFlag . . . . . . . . . 0008 Word
\r
3823 TB_Height . . . . . . . . . . 0016 Word
\r
3824 TB_Width . . . . . . . . . . . 0018 Word
\r
3825 TB_Ypos . . . . . . . . . . . 001A Word
\r
3826 TB_Xpos . . . . . . . . . . . 001C Word
\r
3827 TB_Image . . . . . . . . . . . 001E DWord
\r
3828 TGP_STACK . . . . . . . . . . . 001C
\r
3829 TGP_Width . . . . . . . . . . 0000 Word
\r
3830 TGP_Lines . . . . . . . . . . 0002 Byte
\r
3831 TGP_T_SETS . . . . . . . . . . 0004 Word
\r
3832 TGP_T_SETO . . . . . . . . . . 0006 Word
\r
3833 TGP_ColorF . . . . . . . . . . 0014 Byte
\r
3834 TGP_Ypos . . . . . . . . . . . 0016 Word
\r
3835 TGP_Xpos . . . . . . . . . . . 0018 Word
\r
3836 TGP_Char . . . . . . . . . . . 001A Byte
\r
3837 TPS_STACK . . . . . . . . . . . 0018
\r
3838 TPS_ColorF . . . . . . . . . . 000C Word
\r
3839 TPS_Ypos . . . . . . . . . . . 000E Word
\r
3840 TPS_Xpos . . . . . . . . . . . 0010 Word
\r
3841 TPS_Len . . . . . . . . . . . 0012 Word
\r
3842 TPS_Text . . . . . . . . . . . 0014 Word
\r
3843 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
3844 modex.asm Symbols 18 - 1
\r
3849 Segments and Groups:
\r
3851 N a m e Size Length Align Combine Class
\r
3853 DGROUP . . . . . . . . . . . . . GROUP
\r
3854 _DATA . . . . . . . . . . . . . 16 Bit 0000 Word Public 'DATA'
\r
3855 _BSS . . . . . . . . . . . . . . 16 Bit 002A Word Public 'BSS'
\r
3856 MODEX_TEXT . . . . . . . . . . . 16 Bit 0D88 Word Public 'CODE'
\r
3857 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
3858 modex.asm Symbols 19 - 1
\r
3863 Procedures, parameters and locals:
\r
3865 N a m e Type Value Attr
\r
3867 CLEAR_VGA_SCREEN . . . . . . . . P Far 0280 MODEX_TEXT Length= 0022 Public
\r
3868 COPY_BITMAP . . . . . . . . . . P Far 0C0E MODEX_TEXT Length= 017E Public
\r
3869 COPY_PAGE . . . . . . . . . . . P Far 0BBA MODEX_TEXT Length= 0054 Public
\r
3870 DRAW_BITMAP . . . . . . . . . . P Far 0A0F MODEX_TEXT Length= 00BC Public
\r
3871 DRAW_LINE . . . . . . . . . . . P Far 040B MODEX_TEXT Length= 02A7 Public
\r
3872 FILL_BLOCK . . . . . . . . . . . P Far 0300 MODEX_TEXT Length= 010B Public
\r
3873 GET_ACTIVE_PAGE . . . . . . . . P Far 06E5 MODEX_TEXT Length= 0004 Public
\r
3874 GET_DAC_REGISTER . . . . . . . . P Far 0641 MODEX_TEXT Length= 0025 Public
\r
3875 GET_DISPLAY_PAGE . . . . . . . . P Far 0724 MODEX_TEXT Length= 0004 Public
\r
3876 GET_X_OFFSET . . . . . . . . . . P Far 078D MODEX_TEXT Length= 0004 Public
\r
3877 GET_Y_OFFSET . . . . . . . . . . P Far 0791 MODEX_TEXT Length= 0004 Public
\r
3878 GPRINTC . . . . . . . . . . . . P Far 07A3 MODEX_TEXT Length= 00FE Public
\r
3879 LOAD_DAC_REGISTERS . . . . . . . P Far 0666 MODEX_TEXT Length= 0037 Public
\r
3880 PRINT_STR . . . . . . . . . . . P Far 0975 MODEX_TEXT Length= 0041 Public
\r
3881 READ_DAC_REGISTERS . . . . . . . P Far 069D MODEX_TEXT Length= 002B Public
\r
3882 READ_POINT . . . . . . . . . . . P Far 02D2 MODEX_TEXT Length= 002E Public
\r
3883 SET_ACTIVE_PAGE . . . . . . . . P Far 06C8 MODEX_TEXT Length= 001D Public
\r
3884 SET_DAC_REGISTER . . . . . . . . P Far 0624 MODEX_TEXT Length= 001D Public
\r
3885 SET_DISPLAY_FONT . . . . . . . . P Far 09F3 MODEX_TEXT Length= 001C Public
\r
3886 SET_DISPLAY_PAGE . . . . . . . . P Far 06E9 MODEX_TEXT Length= 003B Public
\r
3887 SET_MODEX . . . . . . . . . . . P Far 0251 MODEX_TEXT Length= 002F Public
\r
3888 SET_POINT . . . . . . . . . . . P Far 02A2 MODEX_TEXT Length= 0030 Public
\r
3889 SET_VGA_MODEX . . . . . . . . . P Far 0104 MODEX_TEXT Length= 014D Public
\r
3890 SET_WINDOW . . . . . . . . . . . P Far 0728 MODEX_TEXT Length= 0065 Public
\r
3891 SYNC_DISPLAY . . . . . . . . . . P Far 0795 MODEX_TEXT Length= 000E Public
\r
3892 TDRAW_BITMAP . . . . . . . . . . P Far 0ACB MODEX_TEXT Length= 00EF Public
\r
3893 TGPRINTC . . . . . . . . . . . . P Far 08A1 MODEX_TEXT Length= 00D4 Public
\r
3894 TPRINT_STR . . . . . . . . . . . P Far 09B6 MODEX_TEXT Length= 003D Public
\r
3895 \fMicrosoft (R) Macro Assembler Version 6.11 07/02/14 15:18:33
\r
3896 modex.asm Symbols 20 - 1
\r
3903 N a m e Type Value Attr
\r
3905 ?x3 . . . . . . . . . . . . . . Text ?,?,?
\r
3906 ?x4 . . . . . . . . . . . . . . Text ?,?,?,?
\r
3907 @CB_Abort . . . . . . . . . . . L Near 0CA2 MODEX_TEXT
\r
3908 @CB_Check_Right . . . . . . . . L Near 0D10 MODEX_TEXT
\r
3909 @CB_Copy_Middle . . . . . . . . L Near 0D47 MODEX_TEXT
\r
3910 @CB_Exit . . . . . . . . . . . . L Near 0D7E MODEX_TEXT
\r
3911 @CB_Finish . . . . . . . . . . . L Near 0D77 MODEX_TEXT
\r
3912 @CB_Left_Band . . . . . . . . . L Near 0CE3 MODEX_TEXT
\r
3913 @CB_Left_Done . . . . . . . . . L Near 0D0B MODEX_TEXT
\r
3914 @CB_Left_Loop . . . . . . . . . L Near 0CF5 MODEX_TEXT
\r
3915 @CB_Middle_Copy . . . . . . . . L Near 0D61 MODEX_TEXT
\r
3916 @CB_One_Done . . . . . . . . . . L Near 0CE0 MODEX_TEXT
\r
3917 @CB_One_Loop . . . . . . . . . . L Near 0CCA MODEX_TEXT
\r
3918 @CB_Only_One_Band . . . . . . . L Near 0CA7 MODEX_TEXT
\r
3919 @CB_Right_Band . . . . . . . . . L Near 0D1B MODEX_TEXT
\r
3920 @CB_Right_Done . . . . . . . . . L Near 0D47 MODEX_TEXT
\r
3921 @CB_Right_Loop . . . . . . . . . L Near 0D31 MODEX_TEXT
\r
3922 @CP_Exit . . . . . . . . . . . . L Near 0C07 MODEX_TEXT
\r
3923 @CodeSize . . . . . . . . . . . Number 0001h
\r
3924 @DB_COPY2 . . . . . . . . . . . L Near 0A8A MODEX_TEXT
\r
3925 @DB_COPY_LINE . . . . . . . . . L Near 0A68 MODEX_TEXT
\r
3926 @DB_COPY_LOOP . . . . . . . . . L Near 0A70 MODEX_TEXT
\r
3927 @DB_COPY_PLANE . . . . . . . . . L Near 0A5F MODEX_TEXT
\r
3928 @DB_COPY_REMAINDER . . . . . . . L Near 0A88 MODEX_TEXT
\r
3929 @DB_Exit . . . . . . . . . . . . L Near 0AC1 MODEX_TEXT
\r
3930 @DB_NEXT2 . . . . . . . . . . . L Near 0A99 MODEX_TEXT
\r
3931 @DB_NEXT_LINE . . . . . . . . . L Near 0A91 MODEX_TEXT
\r
3932 @DL_BREZHAM . . . . . . . . . . L Near 04C7 MODEX_TEXT
\r
3933 @DL_DeltaYOK2 . . . . . . . . . L Near 0515 MODEX_TEXT
\r
3934 @DL_DeltaYOK . . . . . . . . . . L Near 04DC MODEX_TEXT
\r
3935 @DL_DrawLeft . . . . . . . . . . L Near 051F MODEX_TEXT
\r
3936 @DL_DrawRight . . . . . . . . . L Near 05A3 MODEX_TEXT
\r
3937 @DL_EXIT2 . . . . . . . . . . . L Near 061E MODEX_TEXT
\r
3938 @DL_EXIT . . . . . . . . . . . . L Near 04C4 MODEX_TEXT
\r
3939 @DL_HORZ . . . . . . . . . . . . L Near 0433 MODEX_TEXT
\r
3940 @DL_LONGLN . . . . . . . . . . . L Near 0461 MODEX_TEXT
\r
3941 @DL_NOSWAP1 . . . . . . . . . . L Near 0428 MODEX_TEXT
\r
3942 @DL_NOSWAP2 . . . . . . . . . . L Near 048C MODEX_TEXT
\r
3943 @DL_SLLExit . . . . . . . . . . L Near 0563 MODEX_TEXT
\r
3944 @DL_SLLL2nc . . . . . . . . . . L Near 0543 MODEX_TEXT
\r
3945 @DL_SLLL3nc . . . . . . . . . . L Near 0558 MODEX_TEXT
\r
3946 @DL_SLLLoop . . . . . . . . . . L Near 0537 MODEX_TEXT
\r
3947 @DL_SLR2nc . . . . . . . . . . . L Near 05C5 MODEX_TEXT
\r
3948 @DL_SLR3nc . . . . . . . . . . . L Near 05D9 MODEX_TEXT
\r
3949 @DL_SLRExit . . . . . . . . . . L Near 05E3 MODEX_TEXT
\r
3950 @DL_SLRLoop . . . . . . . . . . L Near 05B9 MODEX_TEXT
\r
3951 @DL_STLExit . . . . . . . . . . L Near 05A1 MODEX_TEXT
\r
3952 @DL_STLLoop . . . . . . . . . . L Near 0575 MODEX_TEXT
\r
3953 @DL_STLnc2 . . . . . . . . . . . L Near 0588 MODEX_TEXT
\r
3954 @DL_STLnc3 . . . . . . . . . . . L Near 059D MODEX_TEXT
\r
3955 @DL_ShallowLeft . . . . . . . . L Near 0525 MODEX_TEXT
\r
3956 @DL_ShallowRight . . . . . . . . L Near 05A7 MODEX_TEXT
\r
3957 @DL_SteepLeft . . . . . . . . . L Near 0566 MODEX_TEXT
\r
3958 @DL_SteepRight . . . . . . . . . L Near 05E5 MODEX_TEXT
\r
3959 @DL_VLINE . . . . . . . . . . . L Near 0481 MODEX_TEXT
\r
3960 @DL_VLoop . . . . . . . . . . . L Near 04B4 MODEX_TEXT
\r
3961 @DL_XRSEG . . . . . . . . . . . L Near 0479 MODEX_TEXT
\r
3962 @DP_WAIT0 . . . . . . . . . . . L Near 0706 MODEX_TEXT
\r
3963 @DP_WAIT1 . . . . . . . . . . . L Near 071B MODEX_TEXT
\r
3964 @DataSize . . . . . . . . . . . Number 0000h
\r
3965 @FB_EXIT . . . . . . . . . . . . L Near 0404 MODEX_TEXT
\r
3966 @FB_LEFT_CONT . . . . . . . . . L Near 037A MODEX_TEXT
\r
3967 @FB_LEFT_LOOP . . . . . . . . . L Near 036A MODEX_TEXT
\r
3968 @FB_L_PLANE_FLUSH . . . . . . . L Near 037C MODEX_TEXT
\r
3969 @FB_MIDDLE_LOOP . . . . . . . . L Near 03C7 MODEX_TEXT
\r
3970 @FB_NORMAL . . . . . . . . . . . L Near 034C MODEX_TEXT
\r
3971 @FB_NOSWAP1 . . . . . . . . . . L Near 031F MODEX_TEXT
\r
3972 @FB_NOSWAP2 . . . . . . . . . . L Near 0339 MODEX_TEXT
\r
3973 @FB_ONE_BAND_ONLY . . . . . . . L Near 03D2 MODEX_TEXT
\r
3974 @FB_ONE_LOOP . . . . . . . . . . L Near 03F4 MODEX_TEXT
\r
3975 @FB_RIGHT_CONT . . . . . . . . . L Near 03B0 MODEX_TEXT
\r
3976 @FB_RIGHT_LOOP . . . . . . . . . L Near 03A0 MODEX_TEXT
\r
3977 @FB_RIGHT . . . . . . . . . . . L Near 037D MODEX_TEXT
\r
3978 @FB_R_EDGE_FLUSH . . . . . . . . L Near 03B3 MODEX_TEXT
\r
3979 @GPC_DECODE_CHAR_BYTE . . . . . L Near 080F MODEX_TEXT
\r
3980 @GPC_EXIT . . . . . . . . . . . L Near 0897 MODEX_TEXT
\r
3981 @GPC_LowChar . . . . . . . . . . L Near 07DB MODEX_TEXT
\r
3982 @GPC_NEXT_LINE . . . . . . . . . L Near 0889 MODEX_TEXT
\r
3983 @GPC_NO_LEFT0BITS . . . . . . . L Near 083C MODEX_TEXT
\r
3984 @GPC_NO_LEFT1BITS . . . . . . . L Near 0831 MODEX_TEXT
\r
3985 @GPC_NO_MIDDLE0BITS . . . . . . L Near 085E MODEX_TEXT
\r
3986 @GPC_NO_MIDDLE1BITS . . . . . . L Near 0853 MODEX_TEXT
\r
3987 @GPC_NO_RIGHT0BITS . . . . . . . L Near 0888 MODEX_TEXT
\r
3988 @GPC_NO_RIGHT1BITS . . . . . . . L Near 087D MODEX_TEXT
\r
3989 @GPC_Set_Char . . . . . . . . . L Near 07E3 MODEX_TEXT
\r
3990 @Interface . . . . . . . . . . . Number 0000h
\r
3991 @LDR_Load . . . . . . . . . . . L Near 0677 MODEX_TEXT
\r
3992 @Model . . . . . . . . . . . . . Number 0004h
\r
3993 @PS_Exit . . . . . . . . . . . . L Near 09AF MODEX_TEXT
\r
3994 @PS_Print_It . . . . . . . . . . L Near 097B MODEX_TEXT
\r
3995 @SAP_Exit . . . . . . . . . . . L Near 06E1 MODEX_TEXT
\r
3996 @SDF_Set_Font . . . . . . . . . L Near 0A06 MODEX_TEXT
\r
3997 @SDP_Exit . . . . . . . . . . . L Near 0720 MODEX_TEXT
\r
3998 @SD_WAIT0 . . . . . . . . . . . L Near 0798 MODEX_TEXT
\r
3999 @SD_WAIT1 . . . . . . . . . . . L Near 079D MODEX_TEXT
\r
4000 @SMX_Exit . . . . . . . . . . . L Near 027B MODEX_TEXT
\r
4001 @STRLoop . . . . . . . . . . . . L Near 05F4 MODEX_TEXT
\r
4002 @STRnc2 . . . . . . . . . . . . L Near 0606 MODEX_TEXT
\r
4003 @STRnc3 . . . . . . . . . . . . L Near 061A MODEX_TEXT
\r
4004 @SVM_BadModeSetup . . . . . . . L Near 015C MODEX_TEXT
\r
4005 @SVM_Continue . . . . . . . . . L Near 0161 MODEX_TEXT
\r
4006 @SVM_EXIT . . . . . . . . . . . L Near 0247 MODEX_TEXT
\r
4007 @SVM_Set_Data . . . . . . . . . L Near 01AA MODEX_TEXT
\r
4008 @SVM_Set_Pages . . . . . . . . . L Near 0207 MODEX_TEXT
\r
4009 @SVM_Setup_CRTC . . . . . . . . L Near 019D MODEX_TEXT
\r
4010 @SVM_Setup_Table . . . . . . . . L Near 0193 MODEX_TEXT
\r
4011 @SW_Exit . . . . . . . . . . . . L Near 0789 MODEX_TEXT
\r
4012 @SW_WAIT0 . . . . . . . . . . . L Near 0761 MODEX_TEXT
\r
4013 @SW_WAIT1 . . . . . . . . . . . L Near 0776 MODEX_TEXT
\r
4014 @TB_COPY2 . . . . . . . . . . . L Near 0B6A MODEX_TEXT
\r
4015 @TB_COPY_LINE . . . . . . . . . L Near 0B26 MODEX_TEXT
\r
4016 @TB_COPY_LOOP . . . . . . . . . L Near 0B2E MODEX_TEXT
\r
4017 @TB_COPY_PLANE . . . . . . . . . L Near 0B1B MODEX_TEXT
\r
4018 @TB_COPY_REMAINDER . . . . . . . L Near 0B68 MODEX_TEXT
\r
4019 @TB_Exit . . . . . . . . . . . . L Near 0BB0 MODEX_TEXT
\r
4020 @TB_NEXT2 . . . . . . . . . . . L Near 0B87 MODEX_TEXT
\r
4021 @TB_NEXT_LINE . . . . . . . . . L Near 0B79 MODEX_TEXT
\r
4022 @TB_SKIP_01 . . . . . . . . . . L Near 0B39 MODEX_TEXT
\r
4023 @TB_SKIP_02 . . . . . . . . . . L Near 0B45 MODEX_TEXT
\r
4024 @TB_SKIP_03 . . . . . . . . . . L Near 0B51 MODEX_TEXT
\r
4025 @TB_SKIP_04 . . . . . . . . . . L Near 0B5D MODEX_TEXT
\r
4026 @TB_SKIP_05 . . . . . . . . . . L Near 0B75 MODEX_TEXT
\r
4027 @TGP_DECODE_CHAR_BYTE . . . . . L Near 090D MODEX_TEXT
\r
4028 @TGP_EXIT . . . . . . . . . . . L Near 096B MODEX_TEXT
\r
4029 @TGP_LowChar . . . . . . . . . . L Near 08D9 MODEX_TEXT
\r
4030 @TGP_NEXT_LINE . . . . . . . . . L Near 095E MODEX_TEXT
\r
4031 @TGP_NO_LEFT1BITS . . . . . . . L Near 092D MODEX_TEXT
\r
4032 @TGP_NO_MIDDLE1BITS . . . . . . L Near 0941 MODEX_TEXT
\r
4033 @TGP_NO_RIGHT1BITS . . . . . . . L Near 095D MODEX_TEXT
\r
4034 @TGP_Set_Char . . . . . . . . . L Near 08E1 MODEX_TEXT
\r
4035 @TPS_Exit . . . . . . . . . . . L Near 09EC MODEX_TEXT
\r
4036 @TPS_Print_It . . . . . . . . . L Near 09BC MODEX_TEXT
\r
4037 @code . . . . . . . . . . . . . Text MODEX_TEXT
\r
4038 @data . . . . . . . . . . . . . Text DGROUP
\r
4039 @fardata? . . . . . . . . . . . Text FAR_BSS
\r
4040 @fardata . . . . . . . . . . . . Text FAR_DATA
\r
4041 @stack . . . . . . . . . . . . . Text DGROUP
\r
4042 ACTIVE_PAGE . . . . . . . . . . Word 0012 _BSS
\r
4043 ALL_PLANES_ON . . . . . . . . . Number 0F02h
\r
4044 ALL_PLANES . . . . . . . . . . . Number 000Fh
\r
4045 ASYNC_RESET . . . . . . . . . . Number 0100h
\r
4046 ATTRIB_Ctrl . . . . . . . . . . Number 03C0h
\r
4047 CHAIN4_OFF . . . . . . . . . . . Number 0604h
\r
4048 CHARSET_HI . . . . . . . . . . . Word 0026 _BSS
\r
4049 CHARSET_LOW . . . . . . . . . . Word 0022 _BSS
\r
4050 CHAR_BITS . . . . . . . . . . . Number 000Fh
\r
4051 CRTC_Data . . . . . . . . . . . Number 03D5h
\r
4052 CRTC_Index . . . . . . . . . . . Number 03D4h
\r
4053 CURRENT_MOFFSET . . . . . . . . Word 001C _BSS
\r
4054 CURRENT_PAGE . . . . . . . . . . Word 0014 _BSS
\r
4055 CURRENT_SEGMENT . . . . . . . . Word 0016 _BSS
\r
4056 CURRENT_XOFFSET . . . . . . . . Word 0018 _BSS
\r
4057 CURRENT_YOFFSET . . . . . . . . Word 001A _BSS
\r
4058 Char_Plane_Data . . . . . . . . Byte 0008 MODEX_TEXT
\r
4059 DAC_READ_ADDR . . . . . . . . . Number 03C7h
\r
4060 DAC_WRITE_ADDR . . . . . . . . . Number 03C8h
\r
4061 DISPLAY_PAGE . . . . . . . . . . Word 0010 _BSS
\r
4062 False . . . . . . . . . . . . . Number 0000h
\r
4063 GC_Index . . . . . . . . . . . . Number 03CEh
\r
4064 GET_CHAR_PTR . . . . . . . . . . Number 1130h
\r
4065 INPUT_1 . . . . . . . . . . . . Number 03DAh
\r
4066 LAST_PAGE . . . . . . . . . . . Word 0004 _BSS
\r
4067 LATCHES_OFF . . . . . . . . . . Number FF08h
\r
4068 LATCHES_ON . . . . . . . . . . . Number 0008h
\r
4069 Left_Clip_Mask . . . . . . . . . Byte 0000 MODEX_TEXT
\r
4070 MAP_MASK_PLANE1 . . . . . . . . Number 0102h
\r
4071 MAP_MASK_PLANE2 . . . . . . . . Number 1102h
\r
4072 MAP_MASK . . . . . . . . . . . . Number 0002h
\r
4073 MAX_XOFFSET . . . . . . . . . . Word 001E _BSS
\r
4074 MAX_YOFFSET . . . . . . . . . . Word 0020 _BSS
\r
4075 MISC_OUTPUT . . . . . . . . . . Number 03C2h
\r
4076 MODE_200_Tall . . . . . . . . . L Near 0044 MODEX_TEXT
\r
4077 MODE_240_Tall . . . . . . . . . L Near 0054 MODEX_TEXT
\r
4078 MODE_320_Wide . . . . . . . . . L Near 0028 MODEX_TEXT
\r
4079 MODE_320x200 . . . . . . . . . . L Near 0074 MODEX_TEXT
\r
4080 MODE_320x240 . . . . . . . . . . L Near 00BC MODEX_TEXT
\r
4081 MODE_320x400 . . . . . . . . . . L Near 0086 MODEX_TEXT
\r
4082 MODE_320x480 . . . . . . . . . . L Near 00CE MODEX_TEXT
\r
4083 MODE_360_Wide . . . . . . . . . L Near 0036 MODEX_TEXT
\r
4084 MODE_360x200 . . . . . . . . . . L Near 00E0 MODEX_TEXT
\r
4085 MODE_360x240 . . . . . . . . . . L Near 0098 MODEX_TEXT
\r
4086 MODE_360x400 . . . . . . . . . . L Near 00F2 MODEX_TEXT
\r
4087 MODE_360x480 . . . . . . . . . . L Near 00AA MODEX_TEXT
\r
4088 MODE_400_Tall . . . . . . . . . L Near 0044 MODEX_TEXT
\r
4089 MODE_480_Tall . . . . . . . . . L Near 0054 MODEX_TEXT
\r
4090 MODE_Double_Line . . . . . . . . L Near 0020 MODEX_TEXT
\r
4091 MODE_Single_Line . . . . . . . . L Near 0018 MODEX_TEXT
\r
4092 MODE_TABLE . . . . . . . . . . . L Near 0064 MODEX_TEXT
\r
4093 NUM_MODES . . . . . . . . . . . Number 0008h
\r
4094 PAGE_ADDR . . . . . . . . . . . Word 0006 _BSS
\r
4095 PAGE_SIZE . . . . . . . . . . . Word 000E _BSS
\r
4096 PEL_DATA_REG . . . . . . . . . . Number 03C9h
\r
4097 PIXEL_PAN_REG . . . . . . . . . Number 0033h
\r
4098 PLANE_BITS . . . . . . . . . . . Number 0003h
\r
4099 READ_MAP . . . . . . . . . . . . Number 0004h
\r
4100 ROM_8x8_Hi . . . . . . . . . . . Number 0004h
\r
4101 ROM_8x8_Lo . . . . . . . . . . . Number 0003h
\r
4102 Right_Clip_Mask . . . . . . . . Byte 0004 MODEX_TEXT
\r
4103 SCREEN_HEIGHT . . . . . . . . . Word 0002 _BSS
\r
4104 SCREEN_WIDTH . . . . . . . . . . Word 0000 _BSS
\r
4105 SC_Data . . . . . . . . . . . . Number 03C5h
\r
4106 SC_Index . . . . . . . . . . . . Number 03C4h
\r
4107 SEQU_RESTART . . . . . . . . . . Number 0300h
\r
4108 START_DISP_HI . . . . . . . . . Number 000Ch
\r
4109 START_DISP_LO . . . . . . . . . Number 000Dh
\r
4110 True . . . . . . . . . . . . . . Number -0001h
\r
4111 VERT_RETRACE . . . . . . . . . . Number 0008h
\r
4112 VGA_Segment . . . . . . . . . . Number A000h
\r
4113 b . . . . . . . . . . . . . . . Text BYTE PTR
\r
4114 d . . . . . . . . . . . . . . . Text DWORD PTR
\r
4115 f . . . . . . . . . . . . . . . Text FAR PTR
\r
4116 nil . . . . . . . . . . . . . . Number 0000h
\r
4117 o . . . . . . . . . . . . . . . Text OFFSET
\r
4118 s . . . . . . . . . . . . . . . Text SHORT
\r
4119 w . . . . . . . . . . . . . . . Text WORD PTR
\r