]> 4ch.mooo.com Git - 16.git/blob - src/lib/modex/modex.lst
cleanup and consolidate some mode-X code modesetting.
[16.git] / src / lib / modex / modex.lst
1 Microsoft (R) Macro Assembler Version 6.11                  07/02/14 15:18:33\r
2 modex.asm                                                    Page 1 - 1\r
3 \r
4 \r
5                                 ;========================================================\r
6                                 ; MODEX.ASM - A Complete Mode X Library\r
7                                 ;\r
8                                 ; Version 1.04 Release, 3 May 1993, By Matt Pritchard\r
9                                 ; With considerable input from Michael Abrash\r
10                                 ;\r
11                                 ; The following information is donated to the public domain in\r
12                                 ; the hopes that save other programmers much frustration.\r
13                                 ;\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
16                                 ; in the credits.\r
17                                 ;\r
18                                 ; =========================================================\r
19                                 ;\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
22                                 ;\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
26                                 ;\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
30                                 ;\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
35                                 ;\r
36                                 ; Routines that return a single 16-Bit integer value will\r
37                                 ; return that value in the AX register.\r
38                                 ;\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
43                                 ;\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
47                                 ;\r
48                                 ; Error Trapping varies by Routine.  No Clipping is performed\r
49                                 ; so the caller should verify that all coordinates are valid.\r
50                                 ;\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
54                                 ;\r
55                                 ; ------------------ Mode X Variations ------------------\r
56                                 ;\r
57                                 ;  Mode #  Screen Size    Max Pages   Aspect Ratio (X:Y)\r
58                                 ;\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
67                                 ;\r
68                                 ; -------------------- The Legal Stuff ------------------\r
69                                 ;\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
74                                 ;\r
75                                 ; ----------------------- The Author --------------------\r
76                                 ;\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
81                                 ;\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
88                                 ;\r
89                                  \r
90                                     PAGE    255, 132\r
91                                  \r
92                                     .MODEL Medium\r
93                                     .286\r
94                                  \r
95                                     ; ===== MACROS =====\r
96                                  \r
97                                     ; Macro to OUT a 16 bit value to an I/O port\r
98                                  \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
102                                     ENDIF\r
103                                     IFDIFI <Value>, <AX>            ; If AX not setup\r
104                                         MOV     AX, Value           ; then Get Data Value\r
105                                     ENDIF\r
106                                         OUT     DX, AX              ; Set I/O Register(s)\r
107                                 ENDM\r
108                                  \r
109                                     ; Macro to OUT a 8 bit value to an I/O Port\r
110                                  \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
114                                     ENDIF\r
115                                     IFDIFI <Value>, <AL>            ; If AL not Setup\r
116                                         MOV     AL, Value           ; then Get Data Value\r
117                                     ENDIF\r
118                                         OUT     DX, AL              ; Set I/O Register\r
119                                 ENDM\r
120                                  \r
121                                     ; macros to PUSH and POP multiple registers\r
122                                  \r
123                                 PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
124                                     IFNB <R1>\r
125                                         PUSH    R1              ; Save R1\r
126                                         PUSHx   R2, R3, R4, R5, R6, R7, R8\r
127                                     ENDIF\r
128                                 ENDM\r
129                                  \r
130                                 POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
131                                     IFNB <R1>\r
132                                         POP     R1              ; Restore R1\r
133                                         POPx    R2, R3, R4, R5, R6, R7, R8\r
134                                     ENDIF\r
135                                 ENDM\r
136                                  \r
137                                     ; Macro to Clear Registers to 0\r
138                                  \r
139                                 CLR MACRO Register, R2, R3, R4, R5, R6\r
140                                     IFNB <Register>\r
141                                         XOR     Register, Register      ; Set Register = 0\r
142                                         CLR R2, R3, R4, R5, R6\r
143                                     ENDIF\r
144                                 ENDM\r
145                                  \r
146                                     ; Macros to Decrement Counter & Jump on Condition\r
147                                  \r
148                                 LOOPx MACRO Register, Destination\r
149                                     DEC     Register                ; Counter--\r
150                                     JNZ     Destination             ; Jump if not 0\r
151                                 ENDM\r
152                                  \r
153                                 LOOPjz MACRO Register, Destination\r
154                                     DEC     Register                ; Counter--\r
155                                     JZ      Destination             ; Jump if 0\r
156                                 ENDM\r
157                                  \r
158                                  \r
159                                     ; ===== General Constants =====\r
160                                  \r
161  = 0000                             False   EQU 0\r
162  =-0001                             True    EQU -1\r
163  = 0000                             nil     EQU 0\r
164                                  \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
173                                  \r
174                                     ; ===== VGA Register Values =====\r
175                                  \r
176  = A000                             VGA_Segment     EQU 0A000h  ; Vga Memory Segment\r
177                                  \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
186                                  \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
190                                  \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
196                                  \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
200                                  \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
204                                  \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
207                                  \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
212                                  \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
216                                  \r
217                                     ; Constants Specific for these routines\r
218                                  \r
219  = 0008                             NUM_MODES       EQU 8       ; # of Mode X Variations\r
220                                  \r
221                                     ; Specific Mode Data Table format...\r
222                                  \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
232                                  \r
233                                     ; ===== DGROUP STORAGE NEEDED (42 BYTES) =====\r
234                                  \r
235  0000                               .DATA?\r
236                                  \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
239                                  \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
242         0000\r
243        ]\r
244                                  \r
245  000E 0000                      PAGE_SIZE       DW  0       ; Size of Page in Addr Bytes\r
246                                  \r
247  0010 0000                      DISPLAY_PAGE    DW  0       ; Page # currently displayed\r
248  0012 0000                      ACTIVE_PAGE     DW  0       ; Page # currently active\r
249                                  \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
252                                  \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
255                                  \r
256  001C 0000                      CURRENT_MOFFSET DW  0       ; Current Start Offset\r
257                                  \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
260                                  \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
263                                  \r
264  0000                               .CODE\r
265                                  \r
266                                     ; ===== DATA TABLES =====\r
267                                  \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
271                                  \r
272                                     ; Bit Mask Tables for Left/Right/Character Masks\r
273                                  \r
274  0000 0F 0E 0C 08               Left_Clip_Mask      DB  0FH, 0EH, 0CH, 08H\r
275                                  \r
276  0004 01 03 07 0F               Right_Clip_Mask     DB  01H, 03H, 07H, 0FH\r
277                                  \r
278                                     ; Bit Patterns for converting character fonts\r
279                                  \r
280  0008 00 08 04 0C 02 0A         Char_Plane_Data     DB  00H,08H,04H,0CH,02H,0AH,06H,0EH\r
281        06 0E\r
282  0010  01 09 05 0D 03 0B                            DB  01H,09H,05H,0DH,03H,0BH,07H,0FH\r
283        07 0F\r
284                                  \r
285                                         ; CRTC Register Values for Various Configurations\r
286                                  \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
292                                  \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
298                                  \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
307                                  \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
316                                  \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
327                                  \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
338                                  \r
339                                         ; Table of Display Mode Tables\r
340                                  \r
341  0064                           MODE_TABLE:\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
347 \r
348 \r
349  0070  0098 R 00AA R                    DW  o MODE_360x240, o MODE_360x480\r
350                                  \r
351                                         ; Table of Display Mode Components\r
352                                  \r
353  0074                           MODE_320x200:           ; Data for 320 by 200 Pixels\r
354                                  \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
359                                  \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
362                                  \r
363  0086                           MODE_320x400:           ; Data for 320 by 400 Pixels\r
364                                  \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
369                                  \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
372                                  \r
373  0098                           MODE_360x240:           ; Data for 360 by 240 Pixels\r
374                                  \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
379                                  \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
382                                  \r
383  00AA                           MODE_360x480:           ; Data for 360 by 480 Pixels\r
384                                  \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
389                                  \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
392                                  \r
393  00BC                           MODE_320x240:           ; Data for 320 by 240 Pixels\r
394                                  \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
399                                  \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
402                                  \r
403  00CE                           MODE_320x480:           ; Data for 320 by 480 Pixels\r
404                                  \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
409                                  \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
412                                  \r
413  00E0                           MODE_360x200:           ; Data for 360 by 200 Pixels\r
414                                  \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
419                                  \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
422                                  \r
423  00F2                           MODE_360x400:           ; Data for 360 by 400 Pixels\r
424                                  \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
429                                  \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
432                                  \r
433                                  \r
434                                     ; ===== MODE X SETUP ROUTINES =====\r
435                                  \r
436                                 ;======================================================\r
437                                 ;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%)\r
438                                 ;======================================================\r
439                                 ;\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
444                                 ;\r
445                                 ; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
446                                 ;\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
455                                 ;\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
459                                 ;\r
460                                 ; EXIT:  AX = Success Flag:   0 = Failure / -1= Success\r
461                                 ;\r
462                                  \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
466        0000\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
472                                 SVM_STACK   ENDS\r
473                                  \r
474                                     PUBLIC  SET_VGA_MODEX\r
475                                  \r
476  0104                           SET_VGA_MODEX   PROC    FAR\r
477                                  \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
485                                  \r
486                                     ; Check Legality of Mode Request....\r
487                                  \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
491                                  \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
495                                  \r
496                                     ; Check # of Requested Display Pages\r
497                                  \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
504                                  \r
505                                     ; Check Validity of X Size\r
506                                  \r
507  012C  83 66 12 F8                  AND     [BP].SVM_XSize, 0FFF8h  ; X size Mod 8 Must = 0\r
508                                  \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
514                                  \r
515                                     ; Check Validity of Y Size\r
516                                  \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
522                                  \r
523                                     ; Enough memory to Fit it all?\r
524                                  \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
529                                  \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
533                                  \r
534  015C                           @SVM_BadModeSetup:\r
535                                  \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
539                                  \r
540  0161                           @SVM_Continue:\r
541                                  \r
542  0161  B8 0013                      MOV     AX, 13H             ; Start with Mode 13H\r
543  0164  CD 10                        INT     10H                 ; Let BIOS Set Mode\r
544                                  \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
561                                  \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
570                                  \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
573                                  \r
574                                     ; Load Tables of CRTC Parameters from List of Tables\r
575                                  \r
576  0193                           @SVM_Setup_Table:\r
577                                  \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
582                                  \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
588                                  \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
591                                  \r
592                                     ; Initialize Page & Scroll info, DI = 0\r
593                                  \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
602 \r
603 \r
604  01BE  89 3E 001C R                 MOV     CURRENT_MOFFSET, DI ; Memory Scroll Index = 0\r
605                                  \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
608                                  \r
609                                     ; Set Logical Screen Width, X Scroll and Our Data\r
610                                  \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
613                                  \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
617                                  \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
620                                  \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
625                                  \r
626                                     ; Setup Data table, Y Scroll, Misc for Other Routines\r
627                                  \r
628  01E5  8B 46 10                     MOV     AX, [BP].SVM_Ysize  ; Get Logical Screen Height\r
629                                  \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
633                                  \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
637                                  \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
640                                  \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
644                                  \r
645  0207                           @SVM_Set_Pages:\r
646                                  \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
653                                  \r
654                                     ; Clear VGA Memory\r
655                                  \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
661                                  \r
662                                     CLR     AX                  ; AX = 0\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
667                                  \r
668                                     ; Setup Font Pointers\r
669                                  \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
673                                  \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
676                                  \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
680                                  \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
683                                  \r
684  0244  B8 FFFF                      MOV     AX, True            ; Return Success Code\r
685                                  \r
686  0247                           @SVM_EXIT:\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
694                                  \r
695  0251                           SET_VGA_MODEX   ENDP\r
696                                  \r
697                                  \r
698                                 ;==================\r
699                                 ;SET_MODEX% (Mode%)\r
700                                 ;==================\r
701                                 ;\r
702                                 ; Quickie Mode Set - Sets Up Mode X to Default Configuration\r
703                                 ;\r
704                                 ; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
705                                 ;        (See SET_VGA_MODEX for list)\r
706                                 ;\r
707                                 ; EXIT:  AX = Success Flag:   0 = Failure / -1= Success\r
708                                 ;\r
709                                  \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
714                                 SM_STACK    ENDS\r
715                                  \r
716                                     PUBLIC  SET_MODEX\r
717                                  \r
718  0251                           SET_MODEX   PROC    FAR\r
719                                  \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
724                                  \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
730                                  \r
731  025F  53                           PUSH    BX                  ; Push Mode Parameter\r
732                                  \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
735                                  \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
742                                  \r
743  0276  9A ---- 0104 R               CALL    f SET_VGA_MODEX     ; Set up Mode X!\r
744                                  \r
745  027B                           @SMX_Exit:\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
750                                  \r
751  0280                           SET_MODEX   ENDP\r
752                                  \r
753                                  \r
754                                     ; ===== BASIC GRAPHICS PRIMITIVES =====\r
755                                  \r
756                                 ;============================\r
757                                 ;CLEAR_VGA_SCREEN (ColorNum%)\r
758                                 ;============================\r
759                                 ;\r
760                                 ; Clears the active display page\r
761                                 ;\r
762                                 ; ENTRY: ColorNum = Color Value to fill the page with\r
763                                 ;\r
764                                 ; EXIT:  No meaningful values returned\r
765                                 ;\r
766                                  \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
771                                 CVS_STACK   ENDS\r
772                                  \r
773                                     PUBLIC  CLEAR_VGA_SCREEN\r
774                                  \r
775  0280                           CLEAR_VGA_SCREEN    PROC    FAR\r
776                                  \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
781                                  \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
787                                  \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
791                                  \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
795                                  \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
800                                  \r
801  02A2                           CLEAR_VGA_SCREEN    ENDP\r
802                                  \r
803                                  \r
804                                 ;===================================\r
805                                 ;SET_POINT (Xpos%, Ypos%, ColorNum%)\r
806                                 ;===================================\r
807                                 ;\r
808                                 ; Plots a single Pixel on the active display page\r
809                                 ;\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
813                                 ;\r
814                                 ; EXIT:  No meaningful values returned\r
815                                 ;\r
816                                  \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
823                                 SP_STACK    ENDS\r
824                                  \r
825                                         PUBLIC SET_POINT\r
826                                  \r
827  02A2                           SET_POINT   PROC    FAR\r
828                                  \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
833                                  \r
834  02A6  C4 3E 0014 R                 LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
835                                  \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
838                                  \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
843                                  \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
850                                  \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
853                                  \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
857 \r
858 \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
862                                  \r
863  02D2                           SET_POINT        ENDP\r
864                                  \r
865                                  \r
866                                 ;==========================\r
867                                 ;READ_POINT% (Xpos%, Ypos%)\r
868                                 ;==========================\r
869                                 ;\r
870                                 ; Read the color of a pixel from the Active Display Page\r
871                                 ;\r
872                                 ; ENTRY: Xpos = X position of pixel to read\r
873                                 ;        Ypos = Y position of pixel to read\r
874                                 ;\r
875                                 ; EXIT:  AX   = Color of Pixel at (Xpos, Ypos)\r
876                                 ;\r
877                                  \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
883                                 RP_STACK    ENDS\r
884                                  \r
885                                         PUBLIC  READ_POINT\r
886                                  \r
887  02D2                           READ_POINT      PROC    FAR\r
888                                  \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
893                                  \r
894  02D6  C4 3E 0014 R                 LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
895                                  \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
898                                  \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
903                                  \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
910                                  \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
914                                  \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
919                                  \r
920  0300                           READ_POINT        ENDP\r
921                                  \r
922                                  \r
923                                 ;======================================================\r
924                                 ;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
925                                 ;======================================================\r
926                                 ;\r
927                                 ; Fills a rectangular block on the active display Page\r
928                                 ;\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
934                                 ;\r
935                                 ; EXIT:  No meaningful values returned\r
936                                 ;\r
937                                  \r
938  0016                           FB_STACK    STRUC\r
939  0000  0000 0000 0000                           DW  ?x4 ; DS, DI, SI, BP\r
940        0000\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
947                                 FB_STACK    ENDS\r
948                                  \r
949                                         PUBLIC    FILL_BLOCK\r
950                                  \r
951  0300                           FILL_BLOCK  PROC    FAR\r
952                                  \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
959                                  \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
962                                  \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
967                                  \r
968                                     ; Validate Pixel Coordinates\r
969                                     ; If necessary, Swap so X1 <= X2, Y1 <= Y2\r
970                                  \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
975                                  \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
978                                  \r
979  031F                           @FB_NOSWAP1:\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
983                                  \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
986                                  \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
991                                  \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
994                                  \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
999                                  \r
1000  0339                           @FB_NOSWAP2:\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
1004                                  \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
1007                                  \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
1011                                  \r
1012  034C                           @FB_NORMAL:\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
1017                                  \r
1018                                     ; Draw "Left Edge" vertical strip of 1-3 pixels...\r
1019                                  \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
1024                                  \r
1025  035E  8B F7                        MOV     SI, DI              ; SI = Copy of Start Addr (UL)\r
1026                                  \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
1030                                  \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
1037                                  \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
1043                                  \r
1044  037A                           @FB_LEFT_CONT:\r
1045                                  \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
1048                                  \r
1049  037C                           @FB_L_PLANE_FLUSH:\r
1050  037C  41                           INC     CX                  ; Add in Left band to middle block\r
1051                                  \r
1052                                     ; DI = Addr of 1st middle Pixel (band) to fill\r
1053                                     ; CX = # of Bands to fill -1\r
1054                                  \r
1055  037D                           @FB_RIGHT:\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
1060                                  \r
1061                                     ; Draw "Right Edge" vertical strip of 1-3 pixels...\r
1062                                  \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
1067                                  \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
1071                                  \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
1075                                  \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
1082                                  \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
1088                                  \r
1089  03B0                           @FB_RIGHT_CONT:\r
1090                                  \r
1091  03B0  49                           DEC     CX                  ; Minus 1 for Middle bands\r
1092  03B1  74 51                        JZ      @FB_EXIT            ; Uh.. no Middle bands...\r
1093                                  \r
1094  03B3                           @FB_R_EDGE_FLUSH:\r
1095                                  \r
1096                                     ; DI = Addr of Upper Left block to fill\r
1097                                     ; CX = # of Bands to fill in (width)\r
1098                                  \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
1103                                  \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
1106                                  \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
1112 \r
1113 \r
1114                                  \r
1115  03C7                           @FB_MIDDLE_LOOP:\r
1116  03C7  F3/ AA                       REP     STOSB               ; Fill in entire line\r
1117                                  \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
1123                                  \r
1124  03D0  EB 32                        JMP     s @FB_EXIT          ; Outa here\r
1125                                  \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
1133                                  \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
1137                                  \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
1141                                  \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
1148                                  \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
1154                                  \r
1155  0404                           @FB_EXIT:\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
1162                                  \r
1163  040B                           FILL_BLOCK   ENDP\r
1164                                  \r
1165                                  \r
1166                                 ;=====================================================\r
1167                                 ;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
1168                                 ;=====================================================\r
1169                                 ;\r
1170                                 ; Draws a Line on the active display page\r
1171                                 ;\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
1177                                 ;\r
1178                                 ; EXIT:  No meaningful values returned\r
1179                                 ;\r
1180                                  \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
1189                                 DL_STACK    ENDS\r
1190                                  \r
1191                                         PUBLIC DRAW_LINE\r
1192                                  \r
1193  040B                           DRAW_LINE   PROC    FAR\r
1194                                  \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
1201                                  \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
1207                                  \r
1208                                     ; Check Line Type\r
1209                                  \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
1215                                  \r
1216  0426  87 F7                        XCHG    SI, DI              ; X2 IS > X1, SO SWAP THEM\r
1217                                  \r
1218  0428                           @DL_NOSWAP1:\r
1219                                  \r
1220                                     ; SI = X1, DI = X2\r
1221                                  \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
1225                                  \r
1226  0430  E9 0094                      JMP     @DL_BREZHAM         ; Diagonal line... go do it...\r
1227                                  \r
1228                                     ; This Code draws a Horizontal Line in Mode X where:\r
1229                                     ; SI = X1, DI = X2, and AX = Y1/Y2\r
1230                                  \r
1231  0433                           @DL_HORZ:\r
1232                                  \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
1235                                  \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
1242                                  \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
1245                                  \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
1249                                  \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
1252                                  \r
1253  045F  22 DF                        AND     BL, BH              ; otherwise, merge clip masks\r
1254                                  \r
1255  0461                           @DL_LONGLN:\r
1256                                  \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
1261                                  \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
1265                                  \r
1266  046D  E3 55                        JCXZ    @DL_EXIT            ; Done if only one Line Segment\r
1267                                  \r
1268  046F  49                           DEC     CX                  ; CX = # of Middle Segments\r
1269  0470  74 07                        JZ      @DL_XRSEG           ; If no middle segments....\r
1270                                  \r
1271                                     ; Draw Middle Segments\r
1272                                  \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
1276                                  \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
1279                                  \r
1280  0479                           @DL_XRSEG:\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
1286                                  \r
1287  047F  EB 43                        JMP     s @DL_EXIT          ; We Are Done...\r
1288                                  \r
1289                                  \r
1290                                     ; This Code Draws A Vertical Line.  On entry:\r
1291                                     ; CH = Line Color, SI & DI = X1\r
1292                                  \r
1293  0481                           @DL_VLINE:\r
1294                                  \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
1299                                  \r
1300  048B  96                           XCHG    AX, SI              ; Ok, NOW Y1 < Y2\r
1301                                  \r
1302  048C                           @DL_NOSWAP2:\r
1303                                  \r
1304  048C  2B F0                        SUB     SI, AX              ; SI = Line Height (Y2-Y1+1)\r
1305  048E  46                           INC     SI\r
1306                                  \r
1307                                     ; AX = Y1, DI = X1, Get offset into Page into AX\r
1308                                  \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
1313                                  \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
1316                                  \r
1317                                     ;Select Plane\r
1318                                  \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
1326                                  \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
1329                                  \r
1330  04B4                           @DL_VLoop:\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
1336                                  \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
1342                                  \r
1343  04C4                           @DL_EXIT:\r
1344                                  \r
1345  04C4  E9 0157                      JMP     @DL_EXIT2           ; Done!\r
1346                                  \r
1347                                     ; This code Draws a diagonal line in Mode X\r
1348                                  \r
1349  04C7                           @DL_BREZHAM:\r
1350  04C7  C4 3E 0014 R                 LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
1351                                  \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
1355                                  \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
1358                                  \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
1361                                  \r
1362  04DC                           @DL_DeltaYOK:\r
1363  04DC  F7 26 0000 R                 MUL     SCREEN_WIDTH        ; Offset = SCREEN_WIDTH * Y1\r
1364                                  \r
1365 \fMicrosoft (R) Macro Assembler Version 6.11                 07/02/14 15:18:33\r
1366 modex.asm                                                    Page 6 - 1\r
1367 \r
1368 \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
1373                                  \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
1378                                  \r
1379  04F3  50                           PUSH    AX                  ; Save Mask,Color...\r
1380                                  \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
1386                                  \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
1391                                  \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
1394                                  \r
1395  050C  2B D3                        SUB     DX, BX              ; figure Delta_Y\r
1396  050E  73 05                        JNC     @DL_DeltaYOK2       ; jump if Y2 >= Y1\r
1397                                  \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
1401                                  \r
1402  0515                           @DL_DeltaYOK2:\r
1403  0515  BB 8000                      MOV     BX, 08000H          ; seed for fraction accumulator\r
1404                                  \r
1405  0518  2B C8                        SUB     CX, AX              ; figure Delta_X\r
1406  051A  72 03                        JC      @DL_DrawLeft        ; if negative, go left\r
1407                                  \r
1408  051C  E9 0084                      JMP     @DL_DrawRight       ; Draw Line that slopes right\r
1409                                  \r
1410  051F                           @DL_DrawLeft:\r
1411                                  \r
1412  051F  F7 D9                        NEG     CX                  ; abs(Delta_X)\r
1413                                  \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
1417                                  \r
1418                                     ; Draw a Shallow line to the left in Mode X\r
1419                                  \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
1426                                  \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
1432                                  \r
1433                                     ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...\r
1434                                  \r
1435  0537                           @DL_SLLLoop:\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
1440                                  \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
1443                                  \r
1444  0541  03 FD                        ADD     DI, BP              ; Move Down one line...\r
1445                                  \r
1446  0543                           @DL_SLLL2nc:\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
1452                                  \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
1457                                  \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
1460                                  \r
1461  0556  03 FD                        ADD     DI, BP              ; Move Down one line...\r
1462                                  \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
1470                                  \r
1471  0563                           @DL_SLLExit:\r
1472  0563  E9 00B8                      JMP     @DL_EXIT2           ; and exit\r
1473                                  \r
1474                                     ; Draw a steep line to the left in Mode X\r
1475                                  \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
1481                                  \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
1487                                  \r
1488                                     ; Loop (x2) to Draw Pixels, Move Down, and Maybe left\r
1489                                  \r
1490  0575                           @DL_STLLoop:\r
1491                                  \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
1496                                  \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
1499                                  \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
1505                                  \r
1506  0588                           @DL_STLnc2:\r
1507  0588  03 FD                        ADD     DI, BP              ; advance to next line.\r
1508                                  \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
1513                                  \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
1516                                  \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
1522                                  \r
1523  059D                           @DL_STLnc3:\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
1526                                  \r
1527  05A1                           @DL_STLExit:\r
1528  05A1  EB 7B                        JMP     @DL_EXIT2           ; and exit\r
1529                                  \r
1530                                     ; Draw a line that goes to the Right...\r
1531                                  \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
1536                                  \r
1537                                     ; Draw a Shallow line to the Right in Mode X\r
1538                                  \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
1545                                  \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
1551                                  \r
1552                                     ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...\r
1553                                  \r
1554  05B9                           @DL_SLRLoop:\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
1559                                  \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
1562                                  \r
1563  05C3  03 FD                        ADD     DI, BP              ; Move Down one line...\r
1564                                  \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
1570                                  \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
1575                                  \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
1578                                  \r
1579  05D7  03 FD                        ADD     DI, BP              ; Move Down one line...\r
1580                                  \r
1581  05D9                           @DL_SLR3nc:\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
1587                                  \r
1588  05E3                           @DL_SLRExit:\r
1589  05E3  EB 39                        JMP     @DL_EXIT2           ; and exit\r
1590                                  \r
1591                                     ; Draw a Steep line to the Right in Mode X\r
1592                                  \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
1598                                  \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
1604                                  \r
1605                                     ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right\r
1606                                  \r
1607  05F4                           @STRLoop:\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
1612                                  \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
1615                                  \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
1622 \r
1623 \r
1624                                  \r
1625  0606                           @STRnc2:\r
1626  0606  03 FD                        ADD     DI, BP              ; advance to next line.\r
1627                                  \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
1632                                  \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
1635                                  \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
1640                                  \r
1641  061A                           @STRnc3:\r
1642  061A  03 FD                        ADD     DI, BP              ; advance to next line.\r
1643  061C  EB D6                        JMP     s @STRLoop          ; loop till done\r
1644                                  \r
1645  061E                           @DL_EXIT2:\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
1651                                  \r
1652  0624                           DRAW_LINE        ENDP\r
1653                                  \r
1654                                  \r
1655                                     ; ===== DAC COLOR REGISTER ROUTINES =====\r
1656                                  \r
1657                                 ;=================================================\r
1658                                 ;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%)\r
1659                                 ;=================================================\r
1660                                 ;\r
1661                                 ; Sets a single (RGB) Vga Palette Register\r
1662                                 ;\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
1667                                 ;\r
1668                                 ; EXIT:  No meaningful values returned\r
1669                                 ;\r
1670                                  \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
1678                                 SDR_STACK   ENDS\r
1679                                  \r
1680                                     PUBLIC  SET_DAC_REGISTER\r
1681                                  \r
1682  0624                           SET_DAC_REGISTER    PROC    FAR\r
1683                                  \r
1684  0624  55                           PUSH    BP                  ; Save BP\r
1685  0625  8B EC                        MOV     BP, SP              ; Set up Stack Frame\r
1686                                  \r
1687                                     ; Select which DAC Register to modify\r
1688                                  \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
1693                                  \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
1704                                  \r
1705  063D  5D                           POP     BP                  ; Restore Registers\r
1706  063E  CA 0008                      RET     8                   ; Exit & Clean Up Stack\r
1707                                  \r
1708  0641                           SET_DAC_REGISTER    ENDP\r
1709                                  \r
1710                                 ;====================================================\r
1711                                 ;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%)\r
1712                                 ;====================================================\r
1713                                 ;\r
1714                                 ; Reads the RGB Values of a single Vga Palette Register\r
1715                                 ;\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
1720                                 ;\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
1724                                 ;\r
1725                                  \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
1733                                 GDR_STACK   ENDS\r
1734                                  \r
1735                                     PUBLIC  GET_DAC_REGISTER\r
1736                                  \r
1737  0641                           GET_DAC_REGISTER    PROC    FAR\r
1738                                  \r
1739  0641  55                           PUSH    BP                  ; Save BP\r
1740  0642  8B EC                        MOV     BP, SP              ; Set up Stack Frame\r
1741                                  \r
1742                                     ; Select which DAC Register to read in\r
1743                                  \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
1748                                  \r
1749  064B  BA 03C9                      MOV     DX, PEL_DATA_REG    ; Dac Data Register\r
1750                                     CLR     AX                  ; Clear AX\r
1751  064E  33 C0                 1          XOR     AX, AX      ; Set Register = 0\r
1752                                  \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
1756                                  \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
1760                                  \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
1764                                  \r
1765  0662  5D                           POP     BP                  ; Restore Registers\r
1766  0663  CA 0008                      RET     8                   ; Exit & Clean Up Stack\r
1767                                  \r
1768  0666                           GET_DAC_REGISTER    ENDP\r
1769                                  \r
1770                                  \r
1771                                 ;===========================================================\r
1772                                 ;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%)\r
1773                                 ;===========================================================\r
1774                                 ;\r
1775                                 ; Sets a Block of Vga Palette Registers\r
1776                                 ;\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
1781                                 ;\r
1782                                 ; EXIT:  No meaningful values returned\r
1783                                 ;\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
1786                                 ;\r
1787                                  \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
1795                                 LDR_STACK   ENDS\r
1796                                  \r
1797                                     PUBLIC  LOAD_DAC_REGISTERS\r
1798                                  \r
1799  0666                           LOAD_DAC_REGISTERS  PROC    FAR\r
1800                                  \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
1806                                  \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
1810                                  \r
1811  0672  9A ---- 0795 R               call    f SYNC_DISPLAY      ; wait for vsync\r
1812                                  \r
1813                                     ; Determine register #'s, size to copy, etc\r
1814                                  \r
1815  0677                           @LDR_Load:\r
1816                                  \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
1819                                  \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
1825                                  \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
1833                                  \r
1834                                     ; Load a block of DAC Registers\r
1835                                  \r
1836  0692  BA 03C9                      mov     DX, PEL_DATA_REG    ; Dac Data Register\r
1837                                  \r
1838  0695  F3/ 6E                       rep     outsb               ; block set DAC registers\r
1839                                  \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
1845                                  \r
1846  069D                           LOAD_DAC_REGISTERS  ENDP\r
1847                                  \r
1848                                  \r
1849                                 ;====================================================\r
1850                                 ;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%)\r
1851                                 ;====================================================\r
1852                                 ;\r
1853                                 ; Reads a Block of Vga Palette Registers\r
1854                                 ;\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
1858                                 ;\r
1859                                 ; EXIT:  No meaningful values returned\r
1860                                 ;\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
1863                                 ;\r
1864                                  \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
1871                                 RDR_STACK   ENDS\r
1872                                  \r
1873                                     PUBLIC  READ_DAC_REGISTERS\r
1874                                  \r
1875 \fMicrosoft (R) Macro Assembler Version 6.11                 07/02/14 15:18:33\r
1876 modex.asm                                                    Page 8 - 1\r
1877 \r
1878 \r
1879  069D                           READ_DAC_REGISTERS  PROC    FAR\r
1880                                  \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
1886                                  \r
1887                                     ; Determine register #'s, size to copy, etc\r
1888                                  \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
1891                                  \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
1897                                  \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
1904                                  \r
1905                                     ; Read a block of DAC Registers\r
1906                                  \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
1909                                  \r
1910  06C0  F3/ 6C                       rep     insb                ; block read DAC registers\r
1911                                  \r
1912                                     POPx    DI, ES, BP          ; Restore Registers\r
1913 \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
1918                                  \r
1919  06C8                           READ_DAC_REGISTERS  ENDP\r
1920                                  \r
1921                                  \r
1922                                     ; ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
1923                                  \r
1924                                 ;=========================\r
1925                                 ;SET_ACTIVE_PAGE (PageNo%)\r
1926                                 ;=========================\r
1927                                 ;\r
1928                                 ; Sets the active display Page to be used for future drawing\r
1929                                 ;\r
1930                                 ; ENTRY: PageNo = Display Page to make active\r
1931                                 ;        (values: 0 to Number of Pages - 1)\r
1932                                 ;\r
1933                                 ; EXIT:  No meaningful values returned\r
1934                                 ;\r
1935                                  \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
1940                                 SAP_STACK   ENDS\r
1941                                  \r
1942                                     PUBLIC  SET_ACTIVE_PAGE\r
1943                                  \r
1944  06C8                           SET_ACTIVE_PAGE PROC    FAR\r
1945                                  \r
1946  06C8  55                           PUSH    BP                  ; Preserve Registers\r
1947  06C9  8B EC                        MOV     BP, SP              ; Set up Stack Frame\r
1948                                  \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
1952                                  \r
1953  06D4  89 1E 0012 R                 MOV     ACTIVE_PAGE, BX     ; Set Active Page #\r
1954                                  \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
1957                                  \r
1958  06DE  A3 0014 R                    MOV     CURRENT_PAGE, AX    ; And set for future LES's\r
1959                                  \r
1960  06E1                           @SAP_Exit:\r
1961  06E1  5D                           POP     BP                  ; Restore Registers\r
1962  06E2  CA 0002                      RET     2                   ; Exit and Clean up Stack\r
1963                                  \r
1964  06E5                           SET_ACTIVE_PAGE ENDP\r
1965                                  \r
1966                                  \r
1967                                 ;================\r
1968                                 ;GET_ACTIVE_PAGE%\r
1969                                 ;================\r
1970                                 ;\r
1971                                 ; Returns the Video Page # currently used for Drawing\r
1972                                 ;\r
1973                                 ; ENTRY: No Parameters are passed\r
1974                                 ;\r
1975                                 ; EXIT:  AX = Current Video Page used for Drawing\r
1976                                 ;\r
1977                                  \r
1978                                     PUBLIC  GET_ACTIVE_PAGE\r
1979                                  \r
1980  06E5                           GET_ACTIVE_PAGE PROC    FAR\r
1981                                  \r
1982  06E5  A1 0012 R                    MOV     AX, ACTIVE_PAGE     ; Get Active Page #\r
1983  06E8  CB                           RET                         ; Exit and Clean up Stack\r
1984                                  \r
1985  06E9                           GET_ACTIVE_PAGE ENDP\r
1986                                  \r
1987                                  \r
1988                                 ;===============================\r
1989                                 ;SET_DISPLAY_PAGE (DisplayPage%)\r
1990                                 ;===============================\r
1991                                 ;\r
1992                                 ; Sets the currently visible display page.\r
1993                                 ; When called this routine syncronizes the display\r
1994                                 ; to the vertical blank.\r
1995                                 ;\r
1996                                 ; ENTRY: PageNo = Display Page to show on the screen\r
1997                                 ;        (values: 0 to Number of Pages - 1)\r
1998                                 ;\r
1999                                 ; EXIT:  No meaningful values returned\r
2000                                 ;\r
2001                                  \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
2006                                 SDP_STACK   ENDS\r
2007                                  \r
2008                                     PUBLIC  SET_DISPLAY_PAGE\r
2009                                  \r
2010  06E9                           SET_DISPLAY_PAGE    PROC    FAR\r
2011                                  \r
2012  06E9  55                           PUSH    BP                  ; Preserve Registers\r
2013  06EA  8B EC                        MOV     BP, SP              ; Set up Stack Frame\r
2014                                  \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
2018                                  \r
2019  06F5  89 1E 0010 R                 MOV     DISPLAY_PAGE, BX    ; Set Display Page #\r
2020                                  \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
2024                                  \r
2025                                     ; Wait if we are currently in a Vertical Retrace\r
2026                                  \r
2027  0703  BA 03DA                      MOV     DX, INPUT_1         ; Input Status #1 Register\r
2028                                  \r
2029  0706                           @DP_WAIT0:\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
2033                                  \r
2034                                     ; Set the Start Display Address to the new page\r
2035                                  \r
2036  070B  BA 03D4                      MOV     DX, CRTC_Index      ; We Change the VGA Sequencer\r
2037                                  \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
2041                                  \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
2045                                  \r
2046                                     ; Wait for a Vertical Retrace to smooth out things\r
2047                                  \r
2048  0718  BA 03DA                      MOV     DX, INPUT_1         ; Input Status #1 Register\r
2049                                  \r
2050  071B                           @DP_WAIT1:\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
2054                                  \r
2055                                     ; Now Set Display Starting Address\r
2056                                  \r
2057                                  \r
2058  0720                           @SDP_Exit:\r
2059  0720  5D                           POP     BP                  ; Restore Registers\r
2060  0721  CA 0002                      RET     2                   ; Exit and Clean up Stack\r
2061                                  \r
2062  0724                           SET_DISPLAY_PAGE    ENDP\r
2063                                  \r
2064                                  \r
2065                                 ;=================\r
2066                                 ;GET_DISPLAY_PAGE%\r
2067                                 ;=================\r
2068                                 ;\r
2069                                 ; Returns the Video Page # currently displayed\r
2070                                 ;\r
2071                                 ; ENTRY: No Parameters are passed\r
2072                                 ;\r
2073                                 ; EXIT:  AX = Current Video Page being displayed\r
2074                                 ;\r
2075                                  \r
2076                                     PUBLIC  GET_DISPLAY_PAGE\r
2077                                  \r
2078  0724                           GET_DISPLAY_PAGE    PROC    FAR\r
2079                                  \r
2080  0724  A1 0010 R                    MOV     AX, DISPLAY_PAGE    ; Get Display Page #\r
2081  0727  CB                           RET                         ; Exit & Clean Up Stack\r
2082                                  \r
2083  0728                           GET_DISPLAY_PAGE    ENDP\r
2084                                  \r
2085                                  \r
2086                                 ;=======================================\r
2087                                 ;SET_WINDOW (DisplayPage%, Xpos%, Ypos%)\r
2088                                 ;=======================================\r
2089                                 ;\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
2096                                 ;\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
2100                                 ;\r
2101                                 ; EXIT:  No meaningful values returned\r
2102                                 ;\r
2103                                  \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
2110                                 SW_STACK    ENDS\r
2111                                  \r
2112                                         PUBLIC SET_WINDOW\r
2113                                  \r
2114  0728                           SET_WINDOW  PROC    FAR\r
2115                                  \r
2116  0728  55                           PUSH    BP                  ; Preserve Registers\r
2117  0729  8B EC                        MOV     BP, SP              ; Set up Stack Frame\r
2118                                  \r
2119                                     ; Check if our Scroll Offsets are Valid\r
2120                                  \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
2124                                  \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
2128                                  \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
2133 \r
2134 \r
2135  0744  77 43                        JA      @SW_Exit            ; if not, exit\r
2136                                  \r
2137                                     ; Compute proper Display start address to use\r
2138                                  \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
2142                                  \r
2143  074F  A3 001C R                    MOV     CURRENT_MOFFSET, AX ; Save Offset Info\r
2144                                  \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
2149                                  \r
2150  075E  BA 03DA                      MOV     DX, INPUT_1         ; Input Status #1 Register\r
2151                                  \r
2152                                     ; Wait if we are currently in a Vertical Retrace\r
2153                                  \r
2154  0761                           @SW_WAIT0:\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
2158                                  \r
2159                                     ; Set the Start Display Address to the new window\r
2160                                  \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
2165                                  \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
2169                                  \r
2170                                     ; Wait for a Vertical Retrace to smooth out things\r
2171                                  \r
2172  0773  BA 03DA                      MOV     DX, INPUT_1         ; Input Status #1 Register\r
2173                                  \r
2174  0776                           @SW_WAIT1:\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
2178                                  \r
2179                                     ; Now Set the Horizontal Pixel Pan values\r
2180                                  \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
2185                                  \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
2190                                  \r
2191  0789                           @SW_Exit:\r
2192  0789  5D                           POP     BP                  ; Restore Saved Registers\r
2193  078A  CA 0006                      RET     6                   ; Exit and Clean up Stack\r
2194                                  \r
2195  078D                           SET_WINDOW        ENDP\r
2196                                  \r
2197                                  \r
2198                                 ;=============\r
2199                                 ;GET_X_OFFSET%\r
2200                                 ;=============\r
2201                                 ;\r
2202                                 ; Returns the X coordinate of the Pixel currently display\r
2203                                 ; in the upper left corner of the display\r
2204                                 ;\r
2205                                 ; ENTRY: No Parameters are passed\r
2206                                 ;\r
2207                                 ; EXIT:  AX = Current Horizontal Scroll Offset\r
2208                                 ;\r
2209                                  \r
2210                                     PUBLIC  GET_X_OFFSET\r
2211                                  \r
2212  078D                           GET_X_OFFSET    PROC    FAR\r
2213                                  \r
2214  078D  A1 0018 R                    MOV     AX, CURRENT_XOFFSET ; Get current horz offset\r
2215  0790  CB                           RET                         ; Exit & Clean Up Stack\r
2216                                  \r
2217  0791                           GET_X_OFFSET    ENDP\r
2218                                  \r
2219                                  \r
2220                                 ;=============\r
2221                                 ;GET_Y_OFFSET%\r
2222                                 ;=============\r
2223                                 ;\r
2224                                 ; Returns the Y coordinate of the Pixel currently display\r
2225                                 ; in the upper left corner of the display\r
2226                                 ;\r
2227                                 ; ENTRY: No Parameters are passed\r
2228                                 ;\r
2229                                 ; EXIT:  AX = Current Vertical Scroll Offset\r
2230                                 ;\r
2231                                  \r
2232                                     PUBLIC  GET_Y_OFFSET\r
2233                                  \r
2234  0791                           GET_Y_OFFSET    PROC    FAR\r
2235                                  \r
2236  0791  A1 001A R                    MOV     AX, CURRENT_YOFFSET ; Get current vertical offset\r
2237  0794  CB                           RET                         ; Exit & Clean Up Stack\r
2238                                  \r
2239  0795                           GET_Y_OFFSET    ENDP\r
2240                                  \r
2241                                  \r
2242                                 ;============\r
2243                                 ;SYNC_DISPLAY\r
2244                                 ;============\r
2245                                 ;\r
2246                                 ; Pauses the computer until the next Vertical Retrace starts\r
2247                                 ;\r
2248                                 ; ENTRY: No Parameters are passed\r
2249                                 ;\r
2250                                 ; EXIT:  No meaningful values returned\r
2251                                 ;\r
2252                                  \r
2253                                     PUBLIC  SYNC_DISPLAY\r
2254                                  \r
2255  0795                           SYNC_DISPLAY    PROC    FAR\r
2256                                  \r
2257  0795  BA 03DA                      MOV     DX, INPUT_1         ; Input Status #1 Register\r
2258                                  \r
2259                                     ; Wait for any current retrace to end\r
2260                                  \r
2261  0798                           @SD_WAIT0:\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
2265                                  \r
2266                                     ; Wait for the start of the next vertical retrace\r
2267                                  \r
2268  079D                           @SD_WAIT1:\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
2272                                  \r
2273  07A2  CB                           RET                         ; Exit & Clean Up Stack\r
2274                                  \r
2275  07A3                           SYNC_DISPLAY    ENDP\r
2276                                  \r
2277                                  \r
2278                                     ; ===== TEXT DISPLAY ROUTINES =====\r
2279                                  \r
2280                                 ;==================================================\r
2281                                 ;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%)\r
2282                                 ;==================================================\r
2283                                 ;\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
2287                                 ;\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
2293                                 ;\r
2294                                 ; EXIT:  No meaningful values returned\r
2295                                 ;\r
2296                                  \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
2303        0000\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
2310                                 GPC_STACK   ENDS\r
2311                                  \r
2312                                         PUBLIC GPRINTC\r
2313                                  \r
2314  07A3                           GPRINTC     PROC    FAR\r
2315                                  \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
2323                                  \r
2324  07AC  C4 3E 0014 R                 LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
2325                                  \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
2330                                  \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
2333                                  \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
2338                                  \r
2339                                     ;Get Source ADDR of Character Bit Map  & Save\r
2340                                  \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
2344                                  \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
2349                                  \r
2350  07DB                           @GPC_LowChar:\r
2351                                  \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
2354                                  \r
2355  07E3                           @GPC_Set_Char:\r
2356  07E3  89 56 04                     MOV     [BP].GPC_T_SETS, DX ; Save Segment on Stack\r
2357                                  \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
2362                                  \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
2367                                  \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
2371                                  \r
2372                                     ;Get segment of character map\r
2373                                  \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
2379                                  \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
2382                                  \r
2383  080C  8E 5E 04                     MOV     DS, [BP].GPC_T_SETS ; Point to character set\r
2384                                  \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
2388 \r
2389 \r
2390                                  \r
2391  080F  8B 76 06                     MOV     SI, [BP].GPC_T_SETO ; Get DS:SI = String\r
2392                                  \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
2396                                  \r
2397                                     CLR     AX                  ; Clear AX\r
2398  0818  33 C0                 1          XOR     AX, AX      ; Set Register = 0\r
2399                                  \r
2400                                     CLR     BL                      ; Clear BL\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
2407                                  \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
2411                                  \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
2415                                  \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
2419                                  \r
2420                                     ;Now Do Middle/Last Band\r
2421                                  \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
2425                                  \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
2430                                  \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
2434                                  \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
2438                                  \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
2442                                  \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
2447                                  \r
2448  0866  47                           INC     DI                  ; Point to next Byte\r
2449  0867  C1 C3 04                     ROL     BX, 4               ; Shift 4 bits\r
2450                                  \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
2455                                  \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
2459                                  \r
2460  087D                           @GPC_NO_RIGHT1BITS:\r
2461                                  \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
2464                                  \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
2468                                  \r
2469  0888                           @GPC_NO_RIGHT0BITS:\r
2470  0888  4F                           DEC     DI                  ; Adjust for Next Line Advance\r
2471                                  \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
2475                                  \r
2476  088F  FE 4E 02                     DEC     [BP].GPC_Lines      ; Count Down Lines\r
2477  0892  74 03                        JZ      @GPC_EXIT           ; Ok... Done!\r
2478                                  \r
2479  0894  E9 FF78                      JMP     @GPC_DECODE_CHAR_BYTE   ; Again! Hey!\r
2480                                  \r
2481  0897                           @GPC_EXIT:\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
2489                                  \r
2490  08A1                           GPRINTC  ENDP\r
2491                                  \r
2492                                  \r
2493                                 ;==========================================\r
2494                                 ;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%)\r
2495                                 ;==========================================\r
2496                                 ;\r
2497                                 ; Transparently draws an ASCII Text Character using the\r
2498                                 ; currently selected 8x8 font on the active display page.\r
2499                                 ;\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
2504                                 ;\r
2505                                 ; EXIT:  No meaningful values returned\r
2506                                 ;\r
2507                                  \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
2514        0000\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
2520                                 TGP_STACK   ENDS\r
2521                                  \r
2522                                         PUBLIC TGPRINTC\r
2523                                  \r
2524  08A1                           TGPRINTC    PROC    FAR\r
2525                                  \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
2533                                  \r
2534  08AA  C4 3E 0014 R                 LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page\r
2535                                  \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
2540                                  \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
2543                                  \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
2548                                  \r
2549                                     ;Get Source ADDR of Character Bit Map  & Save\r
2550                                  \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
2554                                  \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
2559                                  \r
2560  08D9                           @TGP_LowChar:\r
2561                                  \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
2564                                  \r
2565  08E1                           @TGP_Set_Char:\r
2566  08E1  89 56 04                     MOV     [BP].TGP_T_SETS, DX ; Save Segment on Stack\r
2567                                  \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
2572                                  \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
2577                                  \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
2581                                  \r
2582                                     ;Get segment of character map\r
2583                                  \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
2589                                  \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
2592                                  \r
2593  090A  8E 5E 04                     MOV     DS, [BP].TGP_T_SETS ; Point to character set\r
2594                                  \r
2595  090D                           @TGP_DECODE_CHAR_BYTE:\r
2596                                  \r
2597  090D  8B 76 06                     MOV     SI, [BP].TGP_T_SETO ; Get DS:SI = String\r
2598                                  \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
2602                                  \r
2603  0916  8A 66 14                     MOV     AH, [BP].TGP_ColorF ; Get Foreground Color\r
2604                                  \r
2605                                     CLR     BL                      ; Clear BL\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
2612                                  \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
2615                                  \r
2616                                     ;Now Do Middle/Last Band\r
2617                                  \r
2618  092D                           @TGP_NO_LEFT1BITS:\r
2619                                  \r
2620  092D  47                           INC     DI                  ; Point to next Byte\r
2621  092E  C1 C3 04                     ROL     BX, 4               ; Shift 4 bits\r
2622                                  \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
2627                                  \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
2630                                  \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
2635                                  \r
2636  0949  47                           INC     DI                  ; Point to next Byte\r
2637  094A  C1 C3 04                     ROL     BX, 4               ; Shift 4 bits\r
2638                                  \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
2643 \r
2644 \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
2647                                  \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
2650                                  \r
2651  095D                           @TGP_NO_RIGHT1BITS:\r
2652                                  \r
2653  095D  4F                           DEC     DI                  ; Adjust for Next Line Advance\r
2654                                  \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
2658                                  \r
2659  0964  FE 4E 02                     DEC     [BP].TGP_Lines      ; Count Down Lines\r
2660  0967  74 02                        JZ      @TGP_EXIT           ; Ok... Done!\r
2661                                  \r
2662  0969  EB A2                        JMP     @TGP_DECODE_CHAR_BYTE   ; Again! Hey!\r
2663                                  \r
2664  096B                           @TGP_EXIT:\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
2672                                  \r
2673  0975                           TGPRINTC    ENDP\r
2674                                  \r
2675                                  \r
2676                                 ;===============================================================\r
2677                                 ;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
2678                                 ;===============================================================\r
2679                                 ;\r
2680                                 ; Routine to quickly Print a null terminated ASCII string on the\r
2681                                 ; active display page up to a maximum length.\r
2682                                 ;\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
2689                                 ;\r
2690                                 ; EXIT:  No meaningful values returned\r
2691                                 ;\r
2692                                  \r
2693  001A                           PS_STACK    STRUC\r
2694  0000  0000 0000 0000                           DW  ?x4 ; DI, SI, DS, BP\r
2695        0000\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
2703                                 PS_STACK    ENDS\r
2704                                  \r
2705                                         PUBLIC  PRINT_STR\r
2706                                  \r
2707  0975                           PRINT_STR   PROC    FAR\r
2708                                  \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
2715                                  \r
2716  097B                           @PS_Print_It:\r
2717                                  \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
2720                                  \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
2725                                  \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
2728                                  \r
2729                                     ; Set up Call to GPRINTC\r
2730                                  \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
2736                                  \r
2737  099C  8B 5E 10                     MOV     BX, [BP].PS_Ypos    ; Get Ypos\r
2738  099F  53                           PUSH    BX                  ; Set Ypos Parameter\r
2739                                  \r
2740  09A0  8B 5E 0E                     MOV     BX, [BP].PS_ColorF  ; Get Text Color\r
2741  09A3  53                           PUSH    BX                  ; Set ColorF Parameter\r
2742                                  \r
2743  09A4  8B 5E 0C                     MOV     BX, [BP].PS_ColorB  ; Get Background Color\r
2744  09A7  53                           PUSH    BX                  ; Set ColorB Parameter\r
2745                                  \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
2748                                  \r
2749  09AF                           @PS_Exit:\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
2756                                  \r
2757  09B6                           PRINT_STR  ENDP\r
2758                                  \r
2759                                  \r
2760                                 ;================================================================\r
2761                                 ;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
2762                                 ;================================================================\r
2763                                 ;\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
2766                                 ;\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
2772                                 ;\r
2773                                 ; EXIT:  No meaningful values returned\r
2774                                 ;\r
2775                                  \r
2776  0018                           TPS_STACK   STRUC\r
2777  0000  0000 0000 0000                           DW  ?x4 ; DI, SI, DS, BP\r
2778        0000\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
2785                                 TPS_STACK   ENDS\r
2786                                  \r
2787                                         PUBLIC  TPRINT_STR\r
2788                                  \r
2789  09B6                           TPRINT_STR  PROC    FAR\r
2790                                  \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
2797                                  \r
2798  09BC                           @TPS_Print_It:\r
2799                                  \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
2802                                  \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
2807                                  \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
2810                                  \r
2811                                     ; Set up Call to TGPRINTC\r
2812                                  \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
2818                                  \r
2819  09DD  8B 5E 0E                     MOV     BX, [BP].TPS_Ypos   ; Get Ypos\r
2820  09E0  53                           PUSH    BX                  ; Set Ypos Parameter\r
2821                                  \r
2822  09E1  8B 5E 0C                     MOV     BX, [BP].TPS_ColorF ; Get Text Color\r
2823  09E4  53                           PUSH    BX                  ; Set ColorF Parameter\r
2824                                  \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
2827                                  \r
2828  09EC                           @TPS_Exit:\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
2835                                  \r
2836  09F3                           TPRINT_STR  ENDP\r
2837                                  \r
2838                                  \r
2839                                 ;===========================================\r
2840                                 ;SET_DISPLAY_FONT(SEG FontData, FontNumber%)\r
2841                                 ;===========================================\r
2842                                 ;\r
2843                                 ; Allows the user to specify their own font data for\r
2844                                 ; wither the lower or upper 128 characters.\r
2845                                 ;\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
2850                                 ;\r
2851                                 ; EXIT:  No meaningful values returned\r
2852                                 ;\r
2853                                  \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
2859                                 SDF_STACK   ENDS\r
2860                                  \r
2861                                     PUBLIC  SET_DISPLAY_FONT\r
2862                                  \r
2863  09F3                           SET_DISPLAY_FONT    PROC    FAR\r
2864                                  \r
2865  09F3  55                           PUSH    BP                  ; Preserve Registers\r
2866  09F4  8B EC                        MOV     BP, SP              ; Set up Stack Frame\r
2867                                  \r
2868  09F6  C4 7E 08                     LES     DI, [BP].SDF_Font   ; Get Far Ptr to Font\r
2869                                  \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
2873                                  \r
2874  0A03  BE 0026 R                    MOV     SI, o CHARSET_HI    ; Ah, really it's 128-255\r
2875                                  \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
2879                                  \r
2880  0A0B  5D                           POP     BP                  ; Restore Registers\r
2881  0A0C  CA 0006                      RET     6                   ; We are Done.. Outa here\r
2882                                  \r
2883  0A0F                           SET_DISPLAY_FONT    ENDP\r
2884                                  \r
2885                                  \r
2886                                     ; ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
2887                                  \r
2888                                 ;======================================================\r
2889                                 ;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
2890                                 ;======================================================\r
2891                                 ;\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
2898 \r
2899 \r
2900                                 ; This is the same linear manner as mode 13h graphics.\r
2901                                 ;\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
2907                                 ;\r
2908                                 ; EXIT:  No meaningful values returned\r
2909                                 ;\r
2910                                  \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
2918        0000\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
2925                                 DB_STACK    ENDS\r
2926                                  \r
2927                                         PUBLIC    DRAW_BITMAP\r
2928                                  \r
2929  0A0F                           DRAW_BITMAP PROC    FAR\r
2930                                  \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
2938                                  \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
2941                                  \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
2944                                  \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
2948                                  \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
2952                                  \r
2953                                     ; Compute line to line offset\r
2954                                  \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
2960                                  \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
2963                                  \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
2967                                  \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
2976                                  \r
2977  0A5F                           @DB_COPY_PLANE:\r
2978                                  \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
2982                                  \r
2983  0A68                           @DB_COPY_LINE:\r
2984  0A68  8B 4E 02                     MOV     CX, [BP].DB_PixCount    ; Min # to copy\r
2985                                  \r
2986  0A6B  F6 C1 FC                     TEST    CL, 0FCh            ; 16+PixWide?\r
2987  0A6E  74 18                        JZ      @DB_COPY_REMAINDER  ; Nope...\r
2988                                  \r
2989                                     ; Pixel Copy loop has been unrolled to x4\r
2990                                  \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
3000                                  \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
3004                                  \r
3005  0A88                           @DB_COPY_REMAINDER:\r
3006  0A88  E3 07                        JCXZ    @DB_NEXT_LINE       ; Any Pixels left on line\r
3007                                  \r
3008  0A8A                           @DB_COPY2:\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
3014                                  \r
3015  0A91                           @DB_NEXT_LINE:\r
3016                                  \r
3017                                     ; any Partial Pixels? (some planes only)\r
3018                                  \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
3021                                  \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
3025                                  \r
3026  0A99                           @DB_NEXT2:\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
3032                                  \r
3033                                     ; Copy Next Plane....\r
3034                                  \r
3035  0AA2  FE CB                        DEC     BL                  ; Planes to Go--\r
3036  0AA4  74 1B                        JZ      @DB_Exit            ; Hey! We are done\r
3037                                  \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
3043                                  \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
3047                                  \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
3050                                  \r
3051  0ABF  EB 9E                        JMP     s @DB_COPY_PLANE    ; Go Copy the Next Plane\r
3052                                  \r
3053  0AC1                           @DB_Exit:\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
3061                                  \r
3062  0ACB                           DRAW_BITMAP   ENDP\r
3063                                  \r
3064                                  \r
3065                                 ;=======================================================\r
3066                                 ;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
3067                                 ;=======================================================\r
3068                                 ;\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
3073                                 ;\r
3074                                 ; The Bitmap format is the same as for the DRAW_BITMAP function.\r
3075                                 ;\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
3081                                 ;\r
3082                                 ; EXIT:  No meaningful values returned\r
3083                                 ;\r
3084                                  \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
3092        0000\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
3099                                 TB_STACK    ENDS\r
3100                                  \r
3101                                         PUBLIC    TDRAW_BITMAP\r
3102                                  \r
3103  0ACB                           TDRAW_BITMAP    PROC    FAR\r
3104                                  \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
3112                                  \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
3115                                  \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
3118                                  \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
3122                                  \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
3126                                  \r
3127                                     ; Compute line to line offset\r
3128                                  \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
3134                                  \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
3137                                  \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
3141                                  \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
3150                                  \r
3151 \fMicrosoft (R) Macro Assembler Version 6.11                 07/02/14 15:18:33\r
3152 modex.asm                                                    Page 13 - 1\r
3153 \r
3154 \r
3155  0B1B                           @TB_COPY_PLANE:\r
3156                                  \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
3160                                  \r
3161                                     ; Here AH is set with the value to be considered\r
3162                                     ; "Transparent".  It can be changed!\r
3163                                  \r
3164  0B24  B4 00                        MOV     AH, 0               ; Value to Detect 0\r
3165                                  \r
3166  0B26                           @TB_COPY_LINE:\r
3167  0B26  8B 4E 02                     MOV     CX, [BP].TB_PixCount    ; Min # to copy\r
3168                                  \r
3169  0B29  F6 C1 FC                     TEST    CL, 0FCh            ; 16+PixWide?\r
3170  0B2C  74 3A                        JZ      @TB_COPY_REMAINDER  ; Nope...\r
3171                                  \r
3172                                     ; Pixel Copy loop has been unrolled to x4\r
3173                                  \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
3180                                  \r
3181  0B39                           @TB_SKIP_01:\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
3187                                  \r
3188  0B45                           @TB_SKIP_02:\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
3194                                  \r
3195  0B51                           @TB_SKIP_03:\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
3201                                  \r
3202  0B5D                           @TB_SKIP_04:\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
3207                                  \r
3208  0B68                           @TB_COPY_REMAINDER:\r
3209  0B68  E3 0F                        JCXZ    @TB_NEXT_LINE       ; Any Pixels left on line\r
3210                                  \r
3211  0B6A                           @TB_COPY2:\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
3217                                  \r
3218  0B75                           @TB_SKIP_05:\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
3223                                  \r
3224  0B79                           @TB_NEXT_LINE:\r
3225                                  \r
3226                                     ; any Partial Pixels? (some planes only)\r
3227                                  \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
3230                                  \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
3236                                  \r
3237  0B87                           @TB_NEXT2:\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
3243                                  \r
3244                                     ;Copy Next Plane....\r
3245                                  \r
3246  0B90  FE CB                        DEC     BL                  ; Planes to Go--\r
3247  0B92  74 1C                        JZ      @TB_Exit            ; Hey! We are done\r
3248                                  \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
3254                                  \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
3258                                  \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
3261                                  \r
3262  0BAD  E9 FF6B                      JMP     @TB_COPY_PLANE      ; Go Copy the next Plane\r
3263                                  \r
3264  0BB0                           @TB_Exit:\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
3272                                  \r
3273  0BBA                           TDRAW_BITMAP    ENDP\r
3274                                  \r
3275                                  \r
3276                                     ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
3277                                  \r
3278                                 ;==================================\r
3279                                 ;COPY_PAGE (SourcePage%, DestPage%)\r
3280                                 ;==================================\r
3281                                 ;\r
3282                                 ; Duplicate on display page onto another\r
3283                                 ;\r
3284                                 ; ENTRY: SourcePage = Display Page # to Duplicate\r
3285                                 ;        DestPage   = Display Page # to hold copy\r
3286                                 ;\r
3287                                 ; EXIT:  No meaningful values returned\r
3288                                 ;\r
3289                                  \r
3290  0010                           CP_STACK    STRUC\r
3291  0000  0000 0000 0000                           DW  ?x4 ; DI, SI, DS, BP\r
3292        0000\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
3296                                 CP_STACK    ENDS\r
3297                                  \r
3298                                         PUBLIC    COPY_PAGE\r
3299                                  \r
3300  0BBA                           COPY_PAGE   PROC    FAR\r
3301                                  \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
3309                                  \r
3310                                     ; Make sure Page #'s are valid\r
3311                                  \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
3315                                  \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
3319                                  \r
3320  0BD3  3B C3                        CMP     AX, BX              ; Pages #'s the same?\r
3321  0BD5  74 30                        JE      @CP_Exit            ; if so, abort\r
3322                                  \r
3323                                     ; Setup DS:SI and ES:DI to Video Pages\r
3324                                  \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
3327                                  \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
3331                                  \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
3336                                  \r
3337                                     ; Setup VGA registers for Mem to Mem copy\r
3338                                  \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
3347                                  \r
3348                                     ; Note.. Do *NOT* use MOVSW or MOVSD - they will\r
3349                                     ; Screw with the latches which are 8 bits x 4\r
3350                                  \r
3351  0BFE  F3/ A4                       REP     MOVSB               ; Copy entire Page!\r
3352                                  \r
3353                                     ; Reset VGA for normal memory access\r
3354                                  \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
3359                                  \r
3360  0C07                           @CP_Exit:\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
3367                                  \r
3368  0C0E                           COPY_PAGE   ENDP\r
3369                                  \r
3370                                  \r
3371                                 ;==========================================================================\r
3372                                 ;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%)\r
3373                                 ;==========================================================================\r
3374                                 ;\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
3384                                 ;\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
3393                                 ;\r
3394                                 ; EXIT:  AX = Success Flag:   0 = Failure / -1= Success\r
3395                                 ;\r
3396                                  \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
3401        0000\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
3408 \r
3409 \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
3415                                 CB_STACK    ENDS\r
3416                                  \r
3417                                         PUBLIC    COPY_BITMAP\r
3418                                  \r
3419  0C0E                           COPY_BITMAP PROC    FAR\r
3420                                  \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
3428                                  \r
3429                                     ; Prep Registers (and keep jumps short!)\r
3430                                  \r
3431  0C17  8E 06 0016 R                 MOV     ES, CURRENT_SEGMENT ; ES -> VGA Ram\r
3432  0C1B  FC                           CLD                         ; Block Xfer Forwards\r
3433                                  \r
3434                                     ; Make sure Parameters are valid\r
3435                                  \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
3439                                  \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
3443                                  \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
3448                                  \r
3449                                     ; Setup for Copy processing\r
3450                                  \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
3459                                  \r
3460                                     ; Compute Info About Images, Setup ES:SI & ES:DI\r
3461                                  \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
3466                                  \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
3474                                  \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
3483                                  \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
3493                                  \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
3497                                  \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
3502                                  \r
3503  0CA2                           @CB_Abort:\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
3507                                  \r
3508                                     ; Copy when Left & Right Clip Masks overlap...\r
3509                                  \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
3517                                  \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
3521                                  \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
3526                                  \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
3534                                  \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
3541                                  \r
3542  0CE0                           @CB_One_Done:\r
3543  0CE0  E9 0094                      JMP     @CB_Finish          ; Outa Here!\r
3544                                  \r
3545                                     ; Copy Left Edge of Bitmap\r
3546                                  \r
3547  0CE3                           @CB_Left_Band:\r
3548                                  \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
3553                                  \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
3558                                  \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
3566                                  \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
3573                                  \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
3578                                  \r
3579                                     ; Determine if Right Edge of Bitmap needs special copy\r
3580                                  \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
3586                                  \r
3587                                     ; Copy Right Edge of Bitmap\r
3588                                  \r
3589  0D1B                           @CB_Right_Band:\r
3590                                  \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
3595                                  \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
3600                                  \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
3608                                  \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
3615                                  \r
3616  0D47                           @CB_Right_Done:\r
3617                                  \r
3618                                     ; Copy the Main Block of the Bitmap\r
3619                                  \r
3620  0D47                           @CB_Copy_Middle:\r
3621                                  \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
3624                                  \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
3629                                  \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
3636                                  \r
3637                                     ; Actual Copy Loop.  REP MOVSB does the work\r
3638                                  \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
3645                                  \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
3648                                  \r
3649  0D6C  8B CB                        MOV     CX, BX              ; Recharge Rep Count\r
3650  0D6E  F3/ A4                       REP     MOVSB               ; Move Bands\r
3651                                  \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
3657                                  \r
3658  0D77                           @CB_Finish:\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
3663 \r
3664 \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
3667                                  \r
3668  0D7E                           @CB_Exit:\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
3676                                  \r
3677  0D88                           COPY_BITMAP ENDP\r
3678                                  \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
3682 \r
3683 \r
3684 \r
3685 \r
3686 Macros:\r
3687 \r
3688                 N a m e                 Type\r
3689 \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
3699 \r
3700 \r
3701 \r
3702 \r
3703 Structures and Unions:\r
3704 \r
3705                 N a m e                  Size\r
3706                                          Offset      Type\r
3707 \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
3845 \r
3846 \r
3847 \r
3848 \r
3849 Segments and Groups:\r
3850 \r
3851                 N a m e                 Size     Length   Align   Combine Class\r
3852 \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
3859 \r
3860 \r
3861 \r
3862 \r
3863 Procedures,  parameters and locals:\r
3864 \r
3865                 N a m e                 Type     Value    Attr\r
3866 \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
3897 \r
3898 \r
3899 \r
3900 \r
3901 Symbols:\r
3902 \r
3903                 N a m e                 Type     Value    Attr\r
3904 \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
4120 \r
4121            0 Warnings\r
4122            0 Errors\r