1 ; XTile Assembler routine lib
2 ;
3 ; COPYRIGHT (C) 1993 Erich P Gatejen 1993 All Rights Reserved
4 ;
5 ; File: XTILE.ASM
6 ;
7 ; Mode X graphics manager.
8
9 ; Ver 1.1 : Add sprites
10 ; Add 4-Pixel font
11 ; Add mouse interface
12 ; Add put pixel
13
14 ; Ver 2.0 : Major rewrite!
15 ; Add virtual size
16 ; Split-screen
17 ; More modes
18
19
20 IDEAL
21
22
23 INCLUDE "XTILE20!.USE"
24
25
26 DOSSEG
27
28 ; LARGE memory model.
29 MODEL LARGE
30
31 ; ------------------------------------------------------------------------
32 ; ----------------------------- Data Seg ---------------------------------
33 ; ------------------------------------------------------------------------
34 FARDATA
35
36 ; --- Mode set tables ----------------------------------------------------
37
38 ; - Tables for each mode
39 XMODE_320x200:
40 db 0e3h ; dot clock
41 db 02 ; # to change
42 dw 00014h ; turn off dword mode
43 dw 0e317h ; turn on byte mode
44 dw 320 ; X
45 dw 200 ; Y
46
47 XMODE_320x240:
48 db 0e3h ; dot clock
49 db 10 ; # to change
50 dw 00d06h ; v-total
51 dw 03e07h ; overflow (bit 8 of vertical counts)
52 dw 04109h ; cell height
53 dw 0ea10h ; v-start
54 dw 0ac11h ; v-end ( and protect bits 0-7 )
55 dw 0df12h ; vertical displayed
56 dw 00014h ; turn off dword mode
57 dw 0e715h ; v-blank start
58 dw 00616h ; v-blank end
59 dw 0e317h ; turn on byte mode
60 dw 320 ; X
61 dw 240 ; Y
62
63 XMODE_360x200:
64 db 0e7h ; dot clock
65 db 08 ; # to change
66 dw 06b00h ; h-total
67 dw 05901h ; horz displayed
68 dw 05a02h ; start horz blanking
69 dw 08e03h ; end horz blanking
70 dw 05e04h ; start h-sync
71 dw 08a05h ; end h-sync
72 dw 00014h ; turn off dword mode
73 dw 0e317h ; turn on byte mode
74 dw 360 ; X
75 dw 200 ; Y
76
77 XMODE_360x240:
78 db 0e7h ; dot clock
79 db 17 ; # to change
80 dw 06b00h ; h-total
81 dw 05901h ; horz displayed
82 dw 05a02h ; start horz blanking
83 dw 08e03h ; end horz blanking
84 dw 05e04h ; start h-sync
85 dw 08a05h ; end h-sync
86 dw 00d06h ; v-total
87 dw 03e07h ; overflow of vertical counts
88 dw 04109h ; cell height
89 dw 0ea10h ; v-start
90 dw 0ac11h ; v-end ( and protect bits 0-7 )
91 dw 0df12h ; vertical displayed
92 dw 02d13h ; offset
93 dw 00014h ; turn off dword mode
94 dw 0e715h ; v-blank start
95 dw 00616h ; v-blank end
96 dw 0e317h ; turn on byte mode
97 dw 360 ; X
98 dw 240 ; Y
99
100 XMODE_376x282:
101 db 067h ; dot clock
102 db 18 ; # to change
103 dw 06e00h ; h-total
104 dw 05d01h ; horz displayed
105 dw 05e02h ; start horz blanking
106 dw 09103h ; end horz blanking
107 dw 06204h ; start h-sync
108 dw 08f05h ; end h-sync
109 dw 06206h ; v-total
110 dw 0f007h ; overflow
111 dw 06109h ; cell height
112 dw 0310fh ; overflow
113 dw 03710h ; v-start
114 dw 08911h ; v-end
115 dw 03312h ; vertical displayed
116 dw 02f13h ; offset
117 dw 00014h ; turn off dword mode
118 dw 03c15h ; v-blank start
119 dw 05c16h ; v-blank end
120 dw 0e317h ; turn on byte mode
121 dw 376 ; X
122 dw 282 ; y
123
124
125 XMODE_320x400:
126 db 0e3h ; dot clock
127 db 03 ; # to change
128 dw 04009h ; cell height
129 dw 00014h ; turn off dword mode
130 dw 0e317h ; turn on byte mode
131 dw 320 ; X
132 dw 400 ; Y
133
134 XMODE_320x480:
135 db 0e3h ; dot clock
136 db 10 ; # to change
137 dw 00d06h ; v-total
138 dw 03e07h ; overflow
139 dw 04009h ; cell height
140 dw 0ea10h ; v-sync start
141 dw 0ac11h ; v-sync end
142 dw 0df12h ; vertical displayed
143 dw 00014h ; turn off dword mode
144 dw 0e715h ; v-blank start
145 dw 00616h ; v-blank end
146 dw 0e317h ; turn on byte mode
147 dw 320 ; X
148 dw 480 ; Y
149
150 XMODE_360x400:
151 db 0e7h ; dot clock
152 db 09 ; # to change
153 dw 06b00h ; h-total
154 dw 05901h ; horz displayed
155 dw 05a02h ; start horz blanking
156 dw 08e03h ; end horz blanking
157 dw 05e04h ; start h sync
158 dw 08a05h ; end h sync
159 dw 04009h ; cell height
160 dw 00014h ; turn off dword mode
161 dw 0e317h ; turn on byte mode
162 dw 360 ; X
163 dw 400 ; Y
164
165
166 XMODE_360x480:
167 db 0e7h ; dot clock
168 db 17 ; # to change
169 dw 06b00h ; h-total
170 dw 05901h ; horz displayed
171 dw 05a02h ; start horz blanking
172 dw 08e03h ; end horz blanking
173 dw 05e04h ; start h-sync
174 dw 08a05h ; end h-sync
175 dw 00d06h ; V-total
176 dw 03e07h ; overflow
177 dw 04009h ; cell height
178 dw 0ea10h ; v-sync start
179 dw 0ac11h ; v-sync end
180 dw 0df12h ; vertical displayed
181 dw 02d13h ; offset
182 dw 00014h ; turn off dword mode
183 dw 0e715h ; v-blank start
184 dw 00616h ; v-blank end
185 dw 0e317h ; turn on byte mode
186 dw 360 ; X
187 dw 480 ; Y
188
189 XMODE_360x360:
190 db 0e7h ; dot clock
191 db 15 ; # to change
192 dw 06b00h ; h-total
193 dw 05901h ; horz displayed
194 dw 05a02h ; start horz blanking
195 dw 08e03h ; end horz blanking
196 dw 05e04h ; start h sync
197 dw 08a05h ; end h sync
198 dw 04009h ; cell height
199 dw 08810h ; v-sync start
200 dw 08511h ; v-sync end
201 dw 06712h ; vertical displayed
202 dw 02d13h ; offset
203 dw 00014h ; turn off dword mode
204 dw 06d15h ; v-blank start
205 dw 0ba16h ; v-blank end
206 dw 0e317h ; turn on byte mode
207 dw 360 ; X
208 dw 360 ; Y
209
210
211 XMODE_376x308:
212 db 0e7h ; dot clock
213 db 18 ; # to change
214 dw 06e00h ; h-total
215 dw 05d01h ; horz displayed
216 dw 05e02h ; start horz blanking
217 dw 09103h ; end horz blanking
218 dw 06204h ; start h sync
219 dw 08f05h ; end h sync
220 dw 06206h ; v-total
221 dw 00f07h ; overflow
222 dw 04009h ; cell height
223 dw 0310fh ; overflow
224 dw 03710h ; v-sync start
225 dw 08911h ; v- sync end
226 dw 03312h ; vertical displayed
227 dw 02f13h ; offset
228 dw 00014h ; turn off dword mode
229 dw 03c15h ; v-blank start
230 dw 05c16h ; v-blank end
231 dw 0e317h ; turn on byte mode
232 dw 376 ; X
233 dw 308 ; Y
234
235 XMODE_376x564:
236 db 0e7h ; dot clock
237 db 18 ; # to change
238 dw 06e00h ; h-total
239 dw 05d01h ; horz displayed
240 dw 05e02h ; start horz blanking
241 dw 09103h ; end horz blanking
242 dw 06204h ; start h sync
243 dw 08f05h ; end h sync
244 dw 06206h ; v-total
245 dw 0f007h ; overflow
246 dw 06009h ; v-blank start
247 dw 0310fh ; overflow
248 dw 03710h ; v-sync start
249 dw 08911h ; v-sync end
250 dw 03312h ; vertical displayed
251 dw 02f13h ; offset
252 dw 00014h ; turn off dword mode
253 dw 03c15h ; v-blank start
254 dw 05c16h ; v- blank end
255 dw 0e317h ; turn on byte mode
256 dw 376
257 dw 564
258
259
260 ; - Table of available modes. Position relates to mode number D-SCAN
261 XMODE_TABLE:
262 dw OFFSET XMODE_320x240 ; Mode 0. 1:1 X
263 dw OFFSET XMODE_320x200 ; Mode 1. X
264 dw OFFSET XMODE_360x200 ; Mode 2. X
265 dw OFFSET XMODE_360x240 ; Mode 3. X
266 dw OFFSET XMODE_376x282 ; Mode 4. 1:1 DONT
267 dw OFFSET XMODE_360x360 ; Mode 5.
268 dw OFFSET XMODE_376x308 ; Mode 6.
269 dw OFFSET XMODE_320x400 ; Mode 7.
270 dw OFFSET XMODE_360x400 ; Mode 8.
271 dw OFFSET XMODE_320x480 ; Mode 9.
272 dw OFFSET XMODE_360x480 ; Mode 10.
273 dw OFFSET XMODE_376x564 ; Mode 11. DONT
274
275
276 ; --- Other Tables --------------------------------------------------------
277 ; Clip edge masks
278 Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H
279 Right_Clip_Mask DB 01H, 03H, 07H, 0FH
280
281
282 ; ---- Copyright notice --------------------------------------------------
283 Banner db 'COPYRIGHT (C) 1993 Erich P Gatejen' ; Do not remove
284 db ' All Rights Reserved ' ; Do not remove
285 ID db ' !!!!'
286
287
288 ; ---- XTile local data --------------------------------------------------
289
290 ; --- Define the current write page
291 Write_Page dw 0 ; Offset into current write page
292 WLine_Offset dw ? ; Line size in the current write page
293
294 ; --- Define the Alt write page
295 Alt_Page dw 0 ; Offset into the alternate write page
296 ALine_Offset dw ? ; Line size in the alternate page
297
298
299 ; --- Define the current display page
300 Display_Page dw ? ; Offset into display page
301 DLine_Offset dw ? ; Line size in current display page
302 DisplaySizeX dw ? ; Size of display page (X)
303 DisplaySizeY dw ? ; Size of display page (Y)
304 ViewXLoc dw ? ; Starting X of view
305 ViewYLoc dw ? ; Starting Y of view
306 MaxViewX dw ? ; Maximum View X
307 MaxViewY dw ? ; Max View Y
308 ScreenSizeX dw ? ; Actual screen size
309 ScreenSizeY dw ? ; Actual screen size (Minus split screen)
310
311 ; --- Split screen data
312 SplitY dw 500 ; Split line. If over screen size then no split
313 DScan dw ? ; Double scan flag
314 OriginalY dw ? ; The original Y screen size (Absolute size)
315
316 ; --- Font data
317 ; 8-pix font
318 UpLoaded8 dw 1 ; Is it uploaded? Assume not.
319 Font_SiteU8 dw ? ; Offset of registered uploaded font
320 LABEL Font_Addr8 DWORD ; For loading the address of an non-uploaded font
321 Font_SiteD8 dw ? ; Offset of registered not-uploaded font
322 FSS8 dw ? ; Segment. Don't change
323 Char_Base8 dw ? ; Base character for font
324 Font_Mask_S8 dw ? ; Seg with masks for font set
325 Font_Mask_O8 dw ? ; Offset
326
327 ; 4-pix font
328 UpLoaded4 dw 1 ; Is it uploaded? Assume not.
329 Font_SiteU4 dw ? ; Offset of registered uploaded font
330 LABEL Font_Addr4 DWORD ; For loading the address of an non-uploaded font
331 Font_SiteD4 dw ? ; Offset of registered not-uploaded font
332 FSS4 dw ? ; Segment. Don't change
333 Char_Base4 dw ? ; Base character for font
334 Font_Mask_S4 dw ? ; Seg with masks for font set
335 Font_Mask_O4 dw ? ; Offset
336
337 ; --- Mouse data
338 MousePage dw ? ; Address of the page the mouse is working on
339 MouseLines dw ? ; Number of lines in the mouses world
340 Mouse_Hndlr_O dd FAR ? ; Address of the user defined mouse handler
341 LABEL MPointerMask DWORD ; Address of the S:O for the next two
342 MPointerMask_O dw ? ; Location in user data of the mouse pntr mask
343 MPointerMask_S dw ? ; Segment ^
344 MUEventMask dw ? ; Events user wishes to be reported
345 MLastX dw ? ; Last known X location of the mouse
346 MLastY dw ? ; Last known Y location of the mouse
347 LockHandler dw 0 ; Block re-entry into mouse handler
348 SplitOffset dw ? ; Offset into display page in which starts the
349 ; scan line that may be in the split page
350
351 ; --- Clip Values
352 ClipSX dw ? ; Clip starting X
353 ClipSY dw ? ; Clip starting Y
354 ClipEX dw ? ; Clip ending X
355 ClipEY dw ? ; Clip ending Y
356
357 ENDS
358
359
360
361 ; ------------------------------------------------------------------------
362 ; ---------------------------- Code Seg ----------------------------------
363 ; ------------------------------------------------------------------------
364 SEGMENT CODE WORD PUBLIC 'CODE'
365
366
367 ASSUME cs:CODE
368
369 ; --------------------------- _XInit_Mode -------------------------------
370 ; - This will initialize Mode X.
371 ; -
372 public _XInit_Mode
373
374 PROC _XInit_Mode FAR
375
376 ARG Mode:WORD
377
378 push bp
379 mov bp, sp ; Save Stack frame
380 push si di ds ; Save calling frame
381
382 ASSUME ds: @fardata
383 mov ax, @fardata ; Set DS to segment w/ Table
384 mov ds, ax
385
386 cld
387
388 ; Get mode and decide if it is a double scan mode (one of first four )
389 mov ax, FALSE ; FALSE = 0, assume no double scan
390 mov cx, [Mode]
391 cmp cx, 3
392 jg @@NotDoubleScan
393 mov ax, TRUE ; It is double scan
394 @@NotDoubleScan:
395 mov [DScan], ax ; Set flag
396
397 ; -- Set the mode
398
399 ; Let BIOS set mode 13h
400 mov ax, 013h
401 int 010h
402
403 ; Disable Chain-4 and Synch reset
404 mov dx, SC_INDEX
405 mov ax, 0604h
406 out dx, ax
407 mov ax, 0100h
408 out dx, ax
409
410 ; Point to the mode table
411 mov bx, OFFSET XMODE_TABLE
412 shl cx, 1 ; Shift to word
413 add bx, cx ; Point to entry
414 mov si, [bx] ; Get address of specific mode table
415
416 ; Set the MISC register
417 lodsb ; Load dot clock
418 mov dx, MISC_OUTPUT
419 out dx, al ; Set the dot clock and H-Scanning
420
421 ; Undo the reset ( restart the sequencer )
422 mov dx, SC_INDEX
423 mov ax, 0300h
424 out dx, ax
425
426 ; -- Change the CRTC registers
427 mov dx, CRTC_INDEX
428
429 ; Unprotect the registers
430 mov al, 011h
431 out dx, al
432 inc dx
433 in al, dx
434 and al, 07fh
435 out dx, al
436
437 ; Find length of CRTC table entries
438 dec dx
439 xor cx,cx
440 lodsb ; Get number
441 mov cl,al ; Put in lower byte of CX
442
443 @@CRTCLoop:
444 lodsw ; Get output pair
445 out dx,ax
446 loop @@CRTCLoop
447
448 ; -- Set local data
449
450 ; - Set default page information
451
452 ; Use X size
453 lodsw ; Get X size
454 mov [DisplaySizeX], ax
455 mov [ScreenSizeX], ax
456
457 shr ax, 1
458 shr ax, 1
459 mov [WLine_Offset], ax ; Set line size in XBlocks
460 mov [DLine_Offset], ax ; Set line size in XBlocks
461
462 ; Use Y size
463 lodsw ; Get Y size
464 mov [DisplaySizeY], ax
465 mov [ScreenSizeY], ax
466 mov [OriginalY], ax
467
468 ; Zero the following
469 mov ax, 0
470 mov [Display_Page], ax ; Display offset 0000
471 mov [Write_Page], ax ; Write page offset 0000
472 mov [SplitY], ax ; No split screen
473 mov [ViewX], ax ; View at base
474 mov [ViewY], ax ; View at base
475 mov [MaxViewX], ax ; No room to move
476 mov [MaxViewY], ax
477
478 ; For split screen, suppress split panning
479 mov dx, IN_STATUS0
480 in al, dx ; Toggle to indexing mode
481
482 mov al, 010h+20h ; Index10 (bit5 set to maintain display)
483 mov dx, AC_INDEXR ; AC Index register
484 out dx, al
485 inc dx ; Point to Data register (read only)
486 in al, dx ; Get the current AC Mode Control
487 or al, 20h ; Enable suppress, bit 6
488 dec dx ; Point to Data reg (for write)
489 out dx, al ; Do it.
490
491 ; !!DONE!!
492 pop ds di si ; Return state
493 pop bp
494 ret
495
496
497 ENDP _XInit_Mode
498
499
500 ; --------------------------- _XSet_Write_Page ------------------------------
501 ; - This will set a write page. It will be the current write page for
502 ; - most write operations ( the ones that don't use this page will say
503 ; - so in thier discription )
504 ; -
505 public _XSet_Write_Page
506
507 PROC _XSet_Write_Page FAR
508
509 ARG Offst:WORD, XSize:WORD
510
511 push bp
512 mov bp, sp ; Save Stack frame
513 push ds
514
515 ; Set the DS to local data
516 ASSUME ds: @fardata
517 mov ax, @fardata
518 mov ds, ax
519
520 ; First, load the page offset
521 mov ax, [Offst] ; Get offset from pass
522 mov [Write_Page], ax ; Put it in var
523
524 ; Calculate the line offset
525 mov ax, [XSize] ; Get the total size
526 shr ax, 1 ; divided by 4 to make XBlocks
527 shr ax, 1
528 mov [WLine_Offset], ax ; Set line size in XBlocks
529
530 ; !!DONE!!
531 pop ds ; Return state
532 pop bp
533 ret
534
535 ENDP _XSet_Write_Page
536
537
538 ; --------------------------- _XSet_Display_Page -------------------------------
539 ; - This function set will set the display page. The view will also be set
540 ; -
541 public _XSet_Display_Page
542
543 PROC _XSet_Display_Page FAR
544
545 ARG Offst:WORD, XSize:WORD, YSize:WORD, ViewX:WORD, ViewY:WORD
546
547
548 push bp
549 mov bp, sp ; Set up stack frame
550 push ds
551
552
553 ; Set DS to local data
554 ASSUME ds: @fardata
555 mov ax, @fardata
556 mov ds, ax
557
558 ; Wait for retrace to end
559 mov dx, IN_STATUS1 ; Input Status #1 Register
560 @@Wait:
561 in al, dx
562 and al, 08h
563 jnz @@Wait
564
565 ; Set line offset. CRTC Offset register
566 ; Calculate the line offset
567 mov ax, [XSize] ; Get the total size
568 mov [DisplaySizeX], ax ; Save it
569 shr ax, 1 ; divide by 4 to make XBlocks
570 shr ax, 1
571 mov [DLine_Offset], ax ; Save XBlocks per line
572 shr ax, 1 ; divide by 2 to get register value
573
574 ; Set it
575 mov dx, CRTC_INDEX ; Set port
576 mov ah, 13h ; CRTC Offset Register Index
577 xchg al, ah ; Swap format
578 out dx, ax ; Send it
579
580 ; Set the Start Display Address to the new window
581 mov cx, [ViewX] ; Get X start for the view
582 mov [ViewXLoc], cx ; Save it for later
583 mov ax, [ViewY] ; Get Y start for the view
584 mov [ViewYLoc], ax ; Save it for later
585
586 ; Compute proper Display start address to use
587 mul [DLine_Offset] ; AX = Y size (AX) * XBlocks per line
588 shr cx, 1
589 shr cx, 1 ; Convert CX to XBlocks. Figure pan later
590 add cx, ax ; Find view upper left pixel
591 add cx, [Offst] ; Add page offset
592 ; NOTE: This will leave any 0-3 pan for later
593
594 ; Change CRTC
595 mov dx, CRTC_INDEX ; Set port
596 mov al, 0Dh ; Start display low.
597 mov ah, cl ; Load low 8 bits
598 out dx, ax
599 mov al, 0Ch ; Start display high
600 mov ah, ch ; Load high 8 Bits
601 out dx, ax
602
603 ; Wait for a Vertical Retrace
604 mov dx, IN_STATUS1
605 @@Wait2:
606 in al, dx
607 and al, 08h ; Vertical Retrace Start?
608 jz @@Wait2 ; If Not, loop until it is
609
610 ; Now Set the Horizontal Pixel Pan values
611 mov dx, 03C0h ; The Attribute controller
612 mov al, 033h ; Select Pixel Pan Register
613 out dx, al
614
615 ; Get the pan value and send it
616 mov ax, [ViewX] ; Get raw X View start
617 and al, 03 ; Peel off the significant bits
618 shl al, 1 ; Shift for 256 Color Mode
619 out dx, al ; Send it
620
621 ; Set some data values for this display page
622
623 ; Max View limits
624 mov ax, [XSize] ; Get the page size
625 sub ax, [ScreenSizeX] ; subtract the actual screen size
626 dec ax ; Adjust for count from 0
627 mov [MaxViewX], ax ; Save
628
629 mov ax, [YSize] ; Get the page size
630 mov [DisplaySizeY], ax ; Save this
631 sub ax, [ScreenSizeY] ; subtract the actual screen size
632 dec ax ; Adjust for count from 0
633 mov [MaxViewY], ax ; Save
634
635 ; Save page offset
636 mov ax, [Offst]
637 mov [Display_Page], ax
638
639 ; Calculate Split offset
640 mov ax, [ViewY] ; Get Y start
641 add ax, [SplitY] ; Add split line down in view
642 mul [DLine_Offset] ; Multiply times line size
643 add ax, [Display_Page] ; Add display page start
644 mov [SplitOffset], ax
645
646 ; DONE!!
647 @@Done:
648 pop ds ; Return state
649 pop bp
650 ret
651
652 ENDP _XSet_Display_Page
653
654 ; --------------------------- _XSet_Display_PageP -------------------------------
655 ; - This function set will set the display page. The view will also be set
656 ; - Anew palette will be loaded
657 public _XSet_Display_PageP
658
659 PROC _XSet_Display_PageP FAR
660
661 ARG Offst:WORD, XSize:WORD, YSize:WORD, ViewX:WORD, ViewY:WORD, START:WORD, NUMBER:WORD, PAL_O:DWORD
662
663 push bp
664 mov bp, sp ; Set up stack frame
665 push si di ds
666
667
668 ; Set DS to local data
669 ASSUME ds: @fardata
670 mov ax, @fardata
671 mov ds, ax
672
673 ; Wait for retrace to end
674 mov dx, IN_STATUS1 ; Input Status #1 Register
675 @@Wait:
676 in al, dx
677 and al, 08h
678 jnz @@Wait
679
680 ; Set line offset. CRTC Offset register
681 ; Calculate the line offset
682 mov ax, [XSize] ; Get the total size
683 mov [DisplaySizeX], ax ; Save it
684 shr ax, 1 ; divide by 4 to make XBlocks
685 shr ax, 1
686 mov [DLine_Offset], ax ; Save XBlocks per line
687 shr ax, 1 ; divide by 2 to get register value
688
689 ; Set it
690 mov dx, CRTC_INDEX ; Set port
691 mov ah, 13h ; CRTC Offset Register Index
692 xchg al, ah ; Swap format
693 out dx, ax ; Send it
694
695 ; Set the Start Display Address to the new window
696 mov cx, [ViewX] ; Get X start for the view
697 mov [ViewXLoc], cx ; Save it for later
698 mov ax, [ViewY] ; Get Y start for the view
699 mov [ViewYLoc], ax ; Save it for later
700
701 ; Compute proper Display start address to use
702 mul [DLine_Offset] ; AX = Y size (AX) * XBlocks per line
703 shr cx, 1
704 shr cx, 1 ; Convert CX to XBlocks. Figure pan later
705 add cx, ax ; Find view upper left pixel
706 add cx, [Offst] ; Add page offset
707 ; NOTE: This will leave any 0-3 pan for later
708
709 ; Change CRTC
710 mov dx, CRTC_INDEX ; Set port
711 mov al, 0Dh ; Start display low.
712 mov ah, cl ; Load low 8 bits
713 out dx, ax
714 mov al, 0Ch ; Start display high
715 mov ah, ch ; Load high 8 Bits
716 out dx, ax
717
718 ; --- Set palette
719
720 ; Set CX to number of colors and BX to current
721 mov cx, [NUMBER]
722 mov bx, [START]
723
724 ; Set ds:si to pal data
725 lds si, [PAL_O]
726
727 ; -- Wait retrace
728 mov dx, IN_STATUS1
729 @@WaitP:
730 in al, dx
731 and al, 08h ; Vertical Retrace Start?
732 jz @@WaitP ; If Not, loop until it is
733
734 ; ------- Main loop
735 @@Another:
736
737 ; Set color to change
738 mov dx, PAL_SET_COLOR
739 mov al, bl
740 out dx, al
741
742 ; Set RGB
743 mov dx, PAL_RGB_COLOR
744 lodsb ; Get byte
745 out dx, al ; Red
746 lodsb
747 out dx, al ; Green
748 lodsb
749 out dx, al ; Blue
750
751 ; Next values and loop if any left
752 inc bx
753 dec cx
754 jnz @@Another
755
756 ; --- Now Set the Horizontal Pixel Pan values
757 ; Set DS to local data
758 ASSUME ds: @fardata
759 mov ax, @fardata
760 mov ds, ax
761
762
763 mov dx, 03C0h ; The Attribute controller
764 mov al, 033h ; Select Pixel Pan Register
765 out dx, al
766
767 ; Get the pan value and send it
768 mov ax, [ViewX] ; Get raw X View start
769 and al, 03 ; Peel off the significant bits
770 shl al, 1 ; Shift for 256 Color Mode
771 out dx, al ; Send it
772
773 ; Set some data values for this display page
774
775 ; Max View limits
776 mov ax, [XSize] ; Get the page size
777 sub ax, [ScreenSizeX] ; subtract the actual screen size
778 dec ax ; Adjust for count from 0
779 mov [MaxViewX], ax ; Save
780
781 mov ax, [YSize] ; Get the page size
782 mov [DisplaySizeY], ax ; Save this
783 sub ax, [ScreenSizeY] ; subtract the actual screen size
784 dec ax ; Adjust for count from 0
785 mov [MaxViewY], ax ; Save
786
787 ; Save page offset
788 mov ax, [Offst]
789 mov [Display_Page], ax
790
791 ; Calculate Split offset
792 mov ax, [ViewY] ; Get Y start
793 add ax, [SplitY] ; Add split line down in view
794 mul [DLine_Offset] ; Multiply times line size
795 add ax, [Display_Page] ; Add display page start
796 mov [SplitOffset], ax
797
798 ; DONE!!
799 @@Done:
800 pop ds di si ; Return state
801 pop bp
802 ret
803
804 ENDP _XSet_Display_PageP
805
806
807 ; --------------------------- _XSet_AltPage --------------------------------
808 ; - This function sets the alternate page
809 public _XSet_AltPage
810
811 PROC _XSet_AltPage FAR
812
813 ARG XSize:WORD, Offst:WORD
814
815 push bp
816 mov bp, sp ; Set up stack frame
817 push ds
818
819
820 ; Set DS to local data
821 ASSUME ds: @fardata
822 mov ax, @fardata
823 mov ds, ax
824
825
826 ; Set line size
827 mov ax, [XSize]
828 shr ax, 1
829 shr ax, 1
830 mov [ALine_Offset], ax
831
832 ; Set page
833 mov ax, [Offst]
834 mov [Alt_Page], ax
835
836 ; DONE!!
837 @@Done:
838 pop ds ; Return state
839 pop bp
840 ret
841
842 ENDP _XSet_AltPage
843
844
845 ; --------------------------- _XSet_View ----------------------------------
846 ; - This function set will set the view port within the current page
847 ; - Return 0 if successful, else 1 (TRUE for C)
848 public _XSet_View
849
850 PROC _XSet_View FAR
851
852 ARG ViewX:WORD, ViewY:WORD
853
854
855 push bp
856 mov bp, sp ; Set up stack frame
857 push ds
858
859
860 ; Set DS to local data
861 ASSUME ds: @fardata
862 mov ax, @fardata
863 mov ds, ax
864
865 ; Wait for retrace to end
866 mov dx, IN_STATUS1 ; Input Status #1 Register
867 @@Wait:
868 in al, dx
869 and al, 08h
870 jnz @@Wait
871
872
873 ; Set the Start Display Address to the new window
874 mov cx, [ViewX] ; Get X start for the view
875 cmp cx, [MaxViewX] ; Is it within range
876 ja @@Error ; No, jump out.
877 mov [ViewXLoc], cx ; Save the view location
878
879 mov ax, [ViewY] ; Get Y start for the view
880 cmp ax, [MaxViewY] ; Is it within range
881 ja @@Error ; No, jump out.
882 mov [ViewYLoc], ax ; Save the view loc
883
884 ; Compute proper Display start address to use
885 mul [DLine_Offset] ; AX = Y size (AX) * XBlocks per line
886 shr cx, 1
887 shr cx, 1 ; Conver CX to XBlocks. Figure pan later
888 add cx, ax ; Find view upper left pixel
889 add cx, [Display_Page] ; Add page offset
890 ; NOTE: This will leave any 0-3 pan for later
891
892 ; Change CRTC
893 mov dx, CRTC_INDEX ; Set port
894 mov al, 0Dh ; Start display low.
895 mov ah, cl ; Load low 8 bits
896 out dx, ax
897 mov al, 0Ch ; Start display high
898 mov ah, ch ; Load high 8 Bits
899 out dx, ax
900
901 ; Wait for a Vertical Retrace
902 mov dx, IN_STATUS1
903 @@Wait2:
904 in al, dx
905 and al, 08h ; Vertical Retrace Start?
906 jz @@Wait2 ; If Not, loop until it is
907
908 ; Now Set the Horizontal Pixel Pan values
909 mov dx, 03C0h ; The Attribute controller
910 mov al, 033h ; Select Pixel Pan Register
911 out dx, al
912
913 ; Get the pan value and send it
914 mov ax, [ViewX] ; Get raw X View start
915 and al, 03 ; Peel off the significant bits
916 shl al, 1 ; Shift for 256 Color Mode
917 out dx, al ; Send it
918
919 ; Calculate Split offset
920 mov ax, [ViewY] ; Get Y start
921 add ax, [SplitY] ; Add split line down in view
922 mul [DLine_Offset] ; Multiply times line size
923 add ax, [Display_Page] ; Add display page start
924 mov [SplitOffset], ax
925
926 ; DONE!!
927 mov ax, 0 ; No Error, Get outta here
928 jmp @@Done
929
930 @@Error:
931 mov ax, 1 ; Error
932
933 @@Done:
934 pop ds ; Return state
935 pop bp
936 ret
937
938 ENDP _XSet_View
939
940
941 ; --------------------------- _XWait_Retrace -------------------------------
942 ; - Wait for vertical retrace
943 public _XWait_Retrace
944
945 PROC _XWait_Retrace FAR
946
947 ; Wait for a Vertical Retrace
948 mov dx, IN_STATUS1
949 @@Wait1:
950 in al, dx
951 and al, 08h ; Vertical Retrace Start?
952 jz @@Wait1 ; If Not, loop until it is
953
954 ret
955
956 ENDP _XWait_Retrace
957
958
959 ; --------------------------- _XSet_SplitScreen ---------------------------
960 ; - Set up the split screen. !XTotal is slave to Display total!
961 ; -
962 public _XSet_SplitScreen
963
964 PROC _XSet_SplitScreen FAR
965
966 ARG YSIZE:WORD
967
968 push bp
969 mov bp, sp ; Save Stack frame
970 push ds
971
972 ; Set DS to local data
973 ASSUME ds: @fardata
974 mov ax, @fardata
975 mov ds, ax
976
977
978 ; Get the split line and save it
979 mov bx, [OriginalY]
980 mov ax, [YSIZE]
981 sub bx, ax
982 dec bx ; Count from 0
983 mov [SplitY], bx ; Save it
984
985 ; Adjust the screen size for the display page
986 mov bx, [OriginalY] ; Get the ACTUAL screen size
987 sub bx, ax ; Subtract the split size
988 mov [ScreenSizeY], bx ; Save as the new screen size
989 ; NOTE: BX is now the starting line for the split
990
991 ; Change the MAX Y view
992 mov cx, [DisplaySizeY] ; Get the page size
993 sub cx, bx ; subtract the actual screen size
994 dec cx ; Adjust for count from 0
995 mov [MaxViewY], cx ; Save
996
997
998 ; See if the double scan effects how we set the registers
999 mov cx, [DScan]
1000 shl bx, cl ; Shift up if so
1001
1002 ; Wait for Vertical retrace to start
1003 mov dx, IN_STATUS1
1004 @@Wait:
1005 in al, dx
1006 and al, 08h ; Vertical Retrace Start?
1007 jz @@Wait ; If Not, loop until it is
1008
1009
1010 ; Set the registers
1011 cli ; Disallow interrupts
1012 mov dx, CRTC_INDEX
1013 mov ah, bl
1014 mov al, 018h ; Line compare register
1015 out dx, ax ; Do lower 8 bits of line compare
1016
1017 mov ah, bh
1018 and ah, 1
1019 mov cl, 4
1020 shl ah, cl ; Bit 4 for over flow
1021
1022 mov al, 07h ; Access overflow register
1023 out dx, al
1024 inc dx
1025 in al, dx ; Read the overflow register
1026
1027 and al, not 10h ; Or in our bit and send back
1028 or al, ah
1029 out dx, al
1030 dec dx
1031
1032 mov ah, bh
1033 and ah, 2
1034 ; optimize here!!!
1035 ror ah, 1 ; Second overflow bit to set
1036 ror ah, 1
1037 ror ah, 1
1038
1039 mov al, 09h ; Bit 6 of the Max Scan line register
1040 out dx, al
1041 inc dx
1042 in al, dx ; Read it
1043
1044 and al, not 40h ; Or in our bit and send it
1045 or al, ah
1046 out dx, al
1047
1048 sti ; Reallow interrupts
1049
1050 ; Calculate Split offset
1051 mov ax, [ViewYLoc] ; Get Y start
1052 add ax, [SplitY] ; Add split line down in view
1053 mul [DLine_Offset] ; Multiply times line size
1054 add ax, [Display_Page] ; Add display page start
1055 mov [SplitOffset], ax
1056
1057 ; - DONE!!
1058 pop ds ; Return state
1059 pop bp
1060 ret
1061
1062 ENDP _XSet_SplitScreen
1063
1064
1065
1066 ; --------------------------- _XSet_Box --------------------------------
1067 ; - This function will draw a box to the passed value. The X coord must
1068 ; - be MOD 4 aligned.
1069 ; -
1070 public _XSet_Box
1071
1072 PROC _XSet_Box FAR
1073
1074 ARG X_S:WORD, Y_S:WORD, X_D:WORD, Y_D:WORD, COLOR:BYTE
1075
1076 push bp
1077 mov bp, sp ; Save Stack frame
1078 push ds di si
1079
1080 ; Set DS to local data
1081 ASSUME ds: @fardata
1082 mov ax, @fardata
1083 mov ds, ax
1084
1085 cld
1086
1087 ; Set ES to display mem and DI to start of rectangle on screen
1088 mov ax, SCREEN_SEG
1089 mov es, ax
1090
1091 mov ax, [WLine_Offset] ; Get the line length for write page
1092 mov bx, ax ; Save in BX for later
1093 mul [Y_S] ; Find Y offset value. Place in AX
1094
1095 mov di, [X_S] ; Find X offset value. Place in DI
1096 shr di, 1
1097 shr di, 1 ; Adjust for planes
1098
1099 add di, ax ; Add X and Y offsets
1100 add di, [Write_Page] ; Add in page offset
1101
1102 ; Set all data from CPU and non from latches
1103 mov dx, GC_INDEX
1104 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
1105 out dx, ax
1106
1107 ; Insure Map Mask is set to all planes
1108 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
1109 mov dx, SC_INDEX
1110 out dx, ax
1111
1112 ; Insure X dist isn't 0 and put number of XBlocks in CX
1113 mov cx, [X_D]
1114 shr cx, 1 ; Div by 4 so we have
1115 shr cx, 1 ; the actual number addresses to fill
1116 ; per line
1117 cmp cx, 0
1118 jle @@Done ; Jump to stop if invalid
1119
1120
1121 ; SI will contain the number lines
1122 mov si, [Y_D]
1123
1124 ; Load color into al
1125 mov al, [COLOR]
1126
1127 ; Set BX to contain the distance from one scan line to next
1128 sub bx, cx ; BX was already loaded with line length
1129
1130 @@Rowloop:
1131 push cx ; Push cx so we can restore for each iteration
1132
1133 ; Do the actual line. REP STOSB.
1134 rep stosb
1135
1136 ; Adjust for next iteration
1137 pop cx ; Restore CX. ( [Pix/line]/4 )
1138 add di, bx ; Point DI to start of next line
1139
1140 ; End of Rowloop. Dec SI, if it is NOT 0 then do next line
1141 dec si
1142 jnz @@Rowloop
1143
1144 ; Else DONE!!
1145
1146 @@Done:
1147 pop si di ds
1148 pop bp
1149 ret
1150
1151 ENDP _XSet_Box
1152
1153
1154 ; --------------------------- _XClear -------------------------------
1155 ; - This will clear all memory on the video card to the passed value
1156 ; -
1157 public _XClear
1158
1159 PROC _XClear FAR
1160
1161 ARG COLOR:WORD
1162
1163 push bp
1164 mov bp, sp ; Save Stack frame
1165 push di
1166
1167 ; Set MAP MASK to all planes
1168 mov dx, SC_INDEX
1169 mov ax, 0F02h
1170 out dx, ax
1171
1172 ; Clear the screen
1173 mov ax, SCREEN_SEG
1174 mov es, ax
1175 sub di, di
1176 sub ax, ax
1177 mov ax, [COLOR]
1178 mov ah, al
1179 mov cx, 8000h
1180 rep stosw
1181
1182 ; DONE!
1183 pop di ; Return state
1184 pop bp
1185 ret
1186
1187 ENDP _XClear
1188
1189
1190 ; --------------------------- _XPut_Tile -------------------------------
1191 ; - This function will place a tile on the current write screen
1192 ; - It will be done a plane at a time and will expect the image data
1193 ; - to be laid out one plane at a time.
1194 ; - If there is an even number of XBlocks then a word write will be used
1195 ; -
1196 public _XPut_Tile
1197
1198 PROC _XPut_Tile FAR
1199
1200 ARG X_S:WORD, Y_S:WORD, X_D:WORD, Y_D:WORD, IMAGE_OFF:DWORD
1201
1202 push bp
1203 mov bp, sp ; Save Stack frame
1204 push ds di si
1205
1206 cld
1207
1208 ; Set all data from CPU and non from latches
1209 mov dx, GC_INDEX
1210 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
1211 out dx, ax
1212
1213 ; Get the Screen Seg and put it in es and load ds to fardata
1214 mov ax, SCREEN_SEG
1215 mov es, ax
1216
1217 ASSUME ds: @fardata
1218 mov ax, @fardata
1219 mov ds, ax ; Set DS to local fardata
1220
1221 ; Load CX with the number of XBlocks per image line
1222 mov cx, [X_D]
1223 shr cx, 1
1224 shr cx, 1 ; Divide by 4 to get
1225 mov [X_D], cx ; Save CX as new Delta
1226
1227 ; Load di with destination offset and save it in DEST
1228 mov ax, [WLine_Offset] ; Size of line in XBlocks
1229 mov bx, ax ; Save in DX
1230 mul [Y_S]
1231
1232 mov di, [X_S]
1233 shr di, 1
1234 shr di, 1
1235
1236 add di, [Write_Page]
1237 add di, ax ; Di is now loaded
1238
1239 mov [X_S], di ; Store it. Steal X start
1240
1241 ; Set [Y_S] to the distance from one scan line to next
1242 sub bx, cx ; minus number of XBlocks
1243 mov [Y_S], bx ; Move to store
1244
1245 ; Set BX to the number of scan lines
1246 mov bx, [Y_D]
1247
1248 ; Load ds:si with source
1249 lds si, [IMAGE_OFF]
1250
1251 ; Set up DX and AX for plane selection
1252 mov al, 02h ; Select Map Mask
1253 mov dx, SC_INDEX
1254 out dx, al
1255 inc dx
1256 mov al, 011h ; Set for plane selection
1257
1258 ; Save CX in AH
1259 mov ah, cl
1260
1261 ; This section is for the WRITES ------------------------------
1262
1263 @@PlanesW: ; Master plane loop.
1264
1265 out dx, al ; Set map mask
1266 mov dx, [Y_S] ; Steal DX to speed up add
1267
1268 @@RowloopW: ; Scan line loop
1269
1270 ; Do the actual line. REP MOVSW.
1271 shr cx, 1 ; Shift for word
1272 rep movsw
1273 adc cx, 0 ; Add 1(carry) to CX if dangling byte
1274 rep movsb ; Write dangle if there
1275
1276 ; Adjust for next iteration
1277 mov cl, ah ; Restore CX
1278 add di, dx ; Point DI to start of next line
1279
1280 ; !!End of Rowloop. Dec BX, if it is NOT 0 then do next line
1281 dec bx
1282 jnz @@RowloopW
1283
1284 ; Done with plane. Reset Destination pointers. Adjst plane
1285 mov di, [X_S] ; Restore destination
1286 mov bx, [Y_D] ; Restore scan line count
1287
1288 ; !!End of Plane loop.
1289 mov dx, (SC_INDEX+1) ; Restore DX for next plane
1290 shl al, 1 ; Shift up a plane.
1291 jnc @@PlanesW ; If carry set, drop out
1292
1293 ; !!!DONE
1294 pop si di ds ; Return state
1295 pop bp
1296 ret
1297
1298 ENDP _XPut_Tile
1299
1300
1301 ; --------------------------- _XPut_TileA -------------------------------
1302 ; - This function will place a tile on the current write screen
1303 ; - It will be done a plane at a time and will expect the image data
1304 ; - to be laid out one plane at a time.
1305 ; - If there is an even number of XBlocks then a word write will be used
1306 ; -
1307 ; - This will work for any X alignment
1308 public _XPut_TileA
1309
1310 PROC _XPut_TileA FAR
1311
1312 ARG X_S:WORD, Y_S:WORD, X_D:WORD, Y_D:WORD, IMAGE_OFF:DWORD
1313
1314 push bp
1315 mov bp, sp ; Save Stack frame
1316 push ds di si
1317
1318 cld
1319
1320 ; Set all data from CPU and non from latches
1321 mov dx, GC_INDEX
1322 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
1323 out dx, ax
1324
1325 ; Get the Screen Seg and put it in es and load ds to fardata
1326 mov ax, SCREEN_SEG
1327 mov es, ax
1328
1329 ASSUME ds: @fardata
1330 mov ax, @fardata
1331 mov ds, ax ; Set DS to local fardata
1332
1333 ; Determine the start plane and save on stack
1334 mov cx, [X_S]
1335 and cx, 3 ; Mask all but 2 LSB
1336 mov al, 11h
1337 shl al, cl ; Shift to first plane
1338 push ax
1339
1340 ; Load CX with the number of XBlocks per image line
1341 mov cx, [X_D]
1342 shr cx, 1
1343 shr cx, 1 ; Divide by 4 to get
1344
1345 ; Load di with destination offset and save it in DEST
1346 mov ax, [WLine_Offset] ; Size of line in XBlocks
1347 mov bx, ax ; Save in BX
1348 mul [Y_S]
1349
1350 mov di, [X_S]
1351 shr di, 1
1352 shr di, 1
1353
1354 add di, [Write_Page]
1355 add di, ax ; Di is now loaded
1356
1357 mov [X_S], di ; Store it. Steal X start
1358
1359 ; Set [Y_S] to the distance from one scan line to next
1360 sub bx, cx ; minus number of XBlocks
1361 mov [Y_S], bx ; Move to store
1362
1363 ; Set BX to the number of scan lines
1364 mov bx, [Y_D]
1365
1366 ; Load ds:si with source
1367 lds si, [IMAGE_OFF]
1368
1369 ; Set up DX and AX for plane selection
1370 mov al, 02h ; Select Map Mask
1371 mov dx, SC_INDEX
1372 out dx, al
1373 inc dx
1374 pop ax ; Pop off the plane selection
1375
1376 ; Save CX in AH
1377 mov ah, cl
1378
1379 mov [X_D], 4 ; Number of planes to do
1380
1381 ; This section is for the WRITES ------------------------------
1382
1383 @@PlanesW: ; Master plane loop.
1384
1385 out dx, al ; Set map mask
1386 mov dx, [Y_S] ; Steal DX to speed up add
1387
1388 @@RowloopW: ; Scan line loop
1389
1390 ; Do the actual line. REP MOVSW.
1391 shr cx, 1 ; Shift for word
1392 rep movsw
1393 adc cx, 0 ; Add 1(carry) to CX if dangling byte
1394 rep movsb ; Write dangle if there
1395
1396 ; Adjust for next iteration
1397 mov cl, ah ; Restore CX
1398 add di, dx ; Point DI to start of next line
1399
1400 ; !!End of Rowloop. Dec BX, if it is NOT 0 then do next line
1401 dec bx
1402 jnz @@RowloopW
1403
1404 ; Done with plane. Reset Destination pointers. Adjst plane
1405 mov di, [X_S] ; Restore destination
1406 mov bx, [Y_D] ; Restore scan line count
1407
1408 ; !!End of Plane loop.
1409 mov dx, (SC_INDEX+1) ; Restore DX for next plane
1410 rol al, 1 ; Shift up a plane.
1411 adc di, 0 ; Adjust to next XBlock if neccessary
1412 mov [X_S], di ; Save in case it moved
1413 dec [X_D] ; Decremet number of planes to do
1414 jnz @@PlanesW ; If no planes left drop out
1415
1416 ; !!!DONE
1417 pop si di ds ; Return state
1418 pop bp
1419 ret
1420
1421 ENDP _XPut_TileA
1422
1423
1424
1425 ; --------------------------- _XTile_Size -----------------------------------
1426 ; - This function will return the total number of bytes an image requires
1427 ; - Div by 4 will yield the number of XBlocks
1428 public _XTile_Size
1429
1430 PROC _XTile_Size FAR
1431
1432 ARG X_D:WORD, Y_D:WORD
1433
1434
1435 push bp
1436 mov bp, sp ; Save Stack frame
1437
1438 ; Load AX with the total number of bytes
1439 mov cx, [X_D]
1440 mov ax, [Y_D]
1441 mul cx ; Yield is total bytes
1442
1443 ; AX holds return
1444 pop bp
1445 ret
1446
1447 ENDP _XTile_Size
1448
1449
1450 ; --------------------------- _XUpload_Tile -------------------------------
1451 ; - This function will place a tile in the display memory
1452 ; - It will be done a plane at a time and will expect the image data
1453 ; - to be laid out one plane at a time.
1454 ; - The tile will be laid out in a linear manner and even though it may be
1455 ; - sent to the current screen it will not be correctly displayed
1456 ; -
1457 public _XUpload_Tile
1458 public _XUpload_Sprite
1459 LABEL _XUpload_Sprite FAR
1460
1461 PROC _XUpload_Tile FAR
1462
1463 ARG DEST:WORD, ISIZE:WORD, IMAGE_OFF:DWORD
1464
1465 push bp
1466 mov bp, sp ; Save Stack frame
1467 push ds di si
1468
1469 cld
1470
1471 ; Get the Screen Seg and put it in es
1472 mov ax, SCREEN_SEG
1473 mov es, ax
1474
1475
1476 ; Load di with destination offset and save it in DEST
1477 mov di, [DEST]
1478 mov bx, di ; Store it
1479
1480 ; Load ds:si with source
1481 lds si, [IMAGE_OFF]
1482
1483 ; Get number of XBlocks per plane.
1484 mov cx, [ISIZE]
1485 shr cx, 1
1486 shr cx, 1
1487 mov bp, cx ; Save size in BP
1488
1489 ; Set all data from CPU and non from latches
1490 mov dx, GC_INDEX
1491 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
1492 out dx, ax
1493
1494 ; Set up DX and AX for plane selection
1495 mov al, 02h ; Select the MAP MASK
1496 mov dx, SC_INDEX
1497 out dx, al
1498 inc dx
1499 mov al, 11h ; Plane 0
1500
1501 ; This section is for WRITES ------------------------------
1502 @@BeginWrite:
1503
1504 @@PlanesW: ; Master plane loop.
1505
1506 out dx, al ; Set the plane
1507
1508 ; Do the actual line. REP MOVSW.
1509 shr cx, 1 ; Set for word writes
1510 rep movsw
1511 adc cx, 0 ; Add 1(carry) to CX to see if dangle
1512 rep movsb ; Write the dangle if there.
1513
1514 ; Done with plane. Reset Destination pointers. Adjst plane
1515 mov di, bx ; Restore Destination
1516 mov cx, bp ; Restore CX.
1517
1518 ; !!End of Plane loop.
1519 shl al, 1 ; Shift plane selector
1520 jnc @@PlanesW ; If no carry, then more to do
1521
1522
1523 ; !!DONE!!
1524 pop si di ds ; Return state
1525 pop bp
1526 ret
1527
1528 ENDP _XUpload_Tile
1529
1530
1531 ; --------------------------- _XPaste_Tile -------------------------------
1532 ; - This function will place a tile from the display memory to current screen
1533 ; -
1534 public _XPaste_Tile
1535
1536 PROC _XPaste_Tile FAR
1537
1538
1539 ARG X_S:WORD, Y_S:WORD, X_D:WORD, Y_D:WORD, TILE:WORD
1540
1541 push bp
1542 mov bp, sp ; Save Stack frame
1543 push ds di si
1544
1545 cld
1546
1547 ; Load DS.
1548
1549 ASSUME ds: @fardata
1550 mov ax, @fardata
1551 mov ds, ax ; Set DS to segment XTile data
1552
1553 ; Set DI to start of rectangle on screen
1554 mov ax, [WLine_Offset]
1555 mul [Y_S] ; Find Y offset value. Place in AX
1556
1557 mov di, [X_S] ; Find X offset value. Place in DI
1558 shr di, 1
1559 shr di, 1
1560
1561 add di, ax ; Add X and Y offsets
1562 add di, [Write_Page] ; Add in page offset
1563
1564 ; Set all data from latches
1565 mov dx, GC_INDEX
1566 mov ax, 00000h + BIT_MASK ; Set all latch writes
1567 out dx, ax
1568
1569 ; Insure Map Mask is set to all planes
1570 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
1571 mov dx, SC_INDEX
1572 out dx, ax
1573
1574 ; Load CX with XBlocks per scan line
1575 mov cx, [X_D]
1576 shr cx, 1 ; Div by 4 so we have
1577 shr cx, 1 ; Xblock count
1578
1579 ; Set AX to the distance from one scan line to next
1580 mov ax, [WLine_Offset]
1581 sub ax, cx
1582
1583 ; Set SI to source
1584 mov si, [TILE]
1585
1586 ; Get the Screen Seg and put it in DS and ES
1587 mov dx, SCREEN_SEG
1588 mov ds, dx
1589 mov es, dx
1590
1591 ; Set DX to the number of scan lines
1592 mov dx, [Y_D]
1593
1594 ; Save the CX in BP
1595 mov bp, cx
1596
1597 ; This section is for WRITES ------------------------------
1598 @@Rowloop:
1599
1600 ; Do the actual line. REP MOVSB.
1601 rep movsb
1602
1603 ; Adjust for next iteration
1604 mov cx, bp ; Restore CX.
1605 add di, ax ; Point DI to start of next line
1606
1607 ; End of Rowloop. Dec DX, if it is NOT 0 then do next line
1608 dec dx
1609 jnz @@Rowloop
1610
1611 ; !!DONE!!
1612 pop si di ds ; Return state
1613 pop bp
1614 ret
1615
1616 ENDP _XPaste_Tile;
1617
1618
1619 ;-------------------------- _XPaste_Sprite ------------------------------
1620 ; - This function will place a sprite from the display memory to current screen
1621 ; - It will NOT do masking
1622 public _XPaste_Sprite
1623
1624 PROC _XPaste_Sprite FAR
1625
1626
1627 ARG X_S:WORD, Y_S:WORD, X_D:WORD, Y_D:WORD, TILE:WORD
1628
1629 push bp
1630 mov bp, sp ; Save Stack frame
1631 push ds di si
1632
1633 cld
1634
1635 ; Load DS.
1636
1637 ASSUME ds: @fardata
1638 mov ax, @fardata
1639 mov ds, ax ; Set DS to segment XTile data
1640
1641 ; Set DI to start of rectangle on screen
1642 mov ax, [WLine_Offset]
1643 mul [Y_S] ; Find Y offset value. Place in AX
1644
1645 mov di, [X_S] ; Find X offset value. Place in DI
1646 shr di, 1
1647 shr di, 1
1648
1649 add di, ax ; Add X and Y offsets
1650 add di, [Write_Page] ; Add in page offset
1651
1652 ; Set SI to source
1653 mov si, [TILE]
1654
1655 ; Find adjustment to source for alignment
1656 mov ax, [X_D]
1657 mov cx, [X_S]
1658
1659 shr ax, 1 ; Number of XBlocks a line
1660 shr ax, 1
1661 mul [Y_D] ; Find size of each sprite alignment
1662
1663 and cx, 3 ; Mask all but 2 LSBs
1664
1665 mul cx ; Find new offset
1666
1667 add si, ax ; Adjust SI
1668
1669 ; Get the Screen Seg and put it in DS and ES
1670 mov ax, SCREEN_SEG
1671 mov ds, ax
1672 mov es, ax
1673
1674 ; Set all data from latches
1675 mov dx, GC_INDEX
1676 mov ax, 00000h + BIT_MASK ; Set all latch writes
1677 out dx, ax
1678
1679 ; Insure Map Mask is set to all planes
1680 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
1681 mov dx, SC_INDEX
1682 out dx, ax
1683
1684 ; Load CX with XBlocks per scan line
1685 mov cx, [X_D]
1686 shr cx, 1 ; Div by 4 so we have
1687 shr cx, 1 ; Xblock count
1688
1689 ; Set AX to the distance from one scan line to next
1690 mov ax, [WLine_Offset]
1691 sub ax, cx
1692
1693 ; Set DX to the number of scan lines
1694 mov dx, [Y_D]
1695
1696 ; Save CX in BP
1697 mov bp, cx
1698
1699 ; This section is for WRITES ------------------------------
1700 @@Rowloop:
1701
1702 ; Do the actual line. REP MOVSB.
1703 rep movsb
1704
1705 ; Adjust for next iteration
1706 mov cx, bp ; Restore CX.
1707 add di, ax ; Point DI to start of next line
1708
1709 ; End of Rowloop. Dec DX, if it is NOT 0 then do next line
1710 dec dx
1711 jnz @@Rowloop
1712
1713 ; !!DONE!!
1714 pop si di ds ; Return state
1715 pop bp
1716 ret
1717
1718 ENDP _XPaste_Sprite
1719
1720
1721 ; --------------------------- _XPut_Tile_M -------------------------------
1722 ; - This function will place a tile on the current write screen
1723 ; - It will be done a plane at a time and will expect the image data
1724 ; - to be laid out one plane at a time.
1725 ; - All 0 pixels will leave the screen intact.
1726 ; -
1727 public _XPut_Tile_M
1728
1729 PROC _XPut_Tile_M FAR
1730
1731 ARG X_S:WORD, Y_S:WORD, X_D:WORD, Y_D:WORD, IMAGE_OFF:DWORD
1732
1733 push bp
1734 mov bp, sp ; Save Stack frame
1735 push ds di si
1736
1737 cld
1738
1739 ; Get the Screen Seg and put it in es
1740 mov ax, SCREEN_SEG
1741 mov es, ax
1742
1743
1744 ; Load CX with the number of XBlocks per scan line
1745 mov cx, [X_D]
1746 shr cx, 1
1747 shr cx, 1 ; Divide by 4 to get
1748
1749 ; Load DS.
1750 ASSUME ds: @fardata
1751 mov ax, @fardata
1752 mov ds, ax ; Set DS to fardata segment
1753
1754 ; Set [X_D] to the distance from one scan line to next
1755 mov ax, [WLine_Offset]
1756 sub ax, cx
1757 mov [X_D], ax
1758
1759 ; Save number of XBlocks a line in upper cx
1760 mov ch, cl
1761
1762 ; Set BL to the number of scan lines and save
1763 mov bx, [Y_D]
1764
1765 ; Load di with destination offset and save it in DEST
1766 mov ax, [WLine_Offset]
1767 mul [Y_S]
1768
1769 mov di, [X_S]
1770 shr di, 1
1771 shr di, 1 ; Adjust to number of XBlocks
1772
1773 add di, [Write_Page]
1774 add di, ax ; Di is now loaded
1775
1776 mov [X_S], di ; Store it
1777
1778 ; Load ds:si with source
1779 lds si, [IMAGE_OFF]
1780
1781 ; Set all data from CPU and non from latches
1782 mov dx, GC_INDEX
1783 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
1784 out dx, ax
1785
1786 ; Set up DX and AX for plane selection
1787 mov al, 02h ; Plane 0 selected
1788 mov dx, SC_INDEX
1789 inc dx
1790 mov ax, 1111h ; Set up AX
1791
1792 ; This section is for the WRITE ------------------------------
1793 @@PlanesB: ; Master plane loop.
1794
1795 out dx, al ; Set the plane
1796 mov dx, [X_D] ; Steal DX to speed up add
1797
1798 @@RowloopB: ; Scan line line
1799
1800 ; Do the actual line.
1801 @@PixelLoop:
1802 lodsb ; Get the pixel
1803 or al, al ; Is it zero
1804 jz @@NoDraw ; If zero, don't draw it
1805 mov [es:di], al ; Else, do draw it
1806
1807 @@NoDraw:
1808 inc di
1809 dec cl
1810 jnz @@PixelLoop
1811
1812 ; Adjust for next iteration
1813 mov cl, ch ; Restore CL. ( [Pix/line]/4 )
1814 add di, dx ; Point DI to start of next line
1815
1816 ; !!End of Rowloop. Dec SI, if it is NOT 0 then do next line
1817 dec bx
1818 jnz @@RowloopB
1819
1820 ; Done with plane. Reset Destination pointers. Adjst plane
1821 mov di, [X_S] ; Restore destination
1822 mov bx, [Y_D] ; Restore scan line count
1823 shl ah, 1 ; Adjust plane
1824 mov al, ah ; Save the
1825 mov dx, SC_INDEX+1 ; Restore SC ptr
1826 jnc @@PlanesB ; If no carry, then more planes
1827
1828 ; !!!DONE
1829 pop si di ds ; Return state
1830 pop bp
1831 ret
1832
1833 ENDP _XPut_Tile_M
1834
1835
1836 ; --------------------------- _XPut_TileA_M -------------------------------
1837 ; - This function will place a tile on the current write screen
1838 ; - It will be done a plane at a time and will expect the image data
1839 ; - to be laid out one plane at a time.
1840 ; - If there is an even number of XBlocks then a word write will be used
1841 ; -
1842 ; - This will work for any X alignment
1843 public _XPut_TileA_M
1844
1845 PROC _XPut_TileA_M FAR
1846
1847 ARG X_S:WORD, Y_S:WORD, X_D:WORD, Y_D:WORD, IMAGE_OFF:DWORD
1848
1849 push bp
1850 mov bp, sp ; Save Stack frame
1851 push ds di si
1852
1853 cld
1854
1855 ; Set all data from CPU and non from latches
1856 mov dx, GC_INDEX
1857 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
1858 out dx, ax
1859
1860 ; Get the Screen Seg and put it in es and load ds to fardata
1861 mov ax, SCREEN_SEG
1862 mov es, ax
1863
1864 ASSUME ds: @fardata
1865 mov ax, @fardata
1866 mov ds, ax ; Set DS to local fardata
1867
1868 ; Determine the start plane and save on stack
1869 mov cx, [X_S]
1870 and cx, 3 ; Mask all but 2 LSB
1871 mov ah, 11h
1872 shl ah, cl ; Shift to first plane
1873 push ax
1874
1875 ; Load CX with the number of XBlocks per image line
1876 mov cx, [X_D]
1877 shr cx, 1
1878 shr cx, 1 ; Divide by 4 to get
1879
1880 ; Load di with destination offset and save it in DEST
1881 mov ax, [WLine_Offset] ; Size of line in XBlocks
1882 mov bx, ax ; Save in BX
1883 mul [Y_S]
1884
1885 mov di, [X_S]
1886 shr di, 1
1887 shr di, 1
1888
1889 add di, [Write_Page]
1890 add di, ax ; Di is now loaded
1891
1892 mov [X_S], di ; Store it. Steal X start
1893
1894 ; Set [Y_S] to the distance from one scan line to next
1895 sub bx, cx ; minus number of XBlocks
1896 mov [Y_S], bx ; Move to store
1897
1898 ; Set BX to the number of scan lines
1899 mov bx, [Y_D]
1900
1901 ; Load ds:si with source
1902 lds si, [IMAGE_OFF]
1903
1904 ; Set up DX and AX for plane selection
1905 mov al, 02h ; Select Map Mask
1906 mov dx, SC_INDEX
1907 out dx, al
1908 inc dx
1909 pop ax ; Pop off the plane selection
1910
1911 ; Save CL in CH
1912 mov ch, cl
1913
1914 mov [X_D], 4 ; Number of planes to do
1915
1916 ; This section is for the WRITES ------------------------------
1917
1918 @@PlanesW: ; Master plane loop.
1919
1920 mov al, ah ; Prep ah
1921 out dx, al ; Set map mask
1922 mov dx, [Y_S] ; Steal DX to speed up add
1923
1924 @@RowloopW: ; Scan line loop
1925
1926 ; Do the actual line.
1927 @@PixelLoop:
1928 lodsb
1929 or al, al ; Is it zero
1930 jz @@NoDraw ; If zero, don't draw it
1931 mov [es:di], al ; Else, do draw it
1932
1933 @@NoDraw:
1934 inc di
1935 dec cl
1936 jnz @@RowloopW
1937
1938
1939 ; Adjust for next iteration
1940 mov cl, ch ; Restore CX
1941 add di, dx ; Point DI to start of next line
1942
1943 ; !!End of Rowloop. Dec BX, if it is NOT 0 then do next line
1944 dec bx
1945 jnz @@RowloopW
1946
1947 ; Done with plane. Reset Destination pointers. Adjst plane
1948 mov di, [X_S] ; Restore destination
1949 mov bx, [Y_D] ; Restore scan line count
1950
1951 ; !!End of Plane loop.
1952 mov dx, (SC_INDEX+1) ; Restore DX for next plane
1953 rol ah, 1 ; Shift up a plane.
1954 adc di, 0 ; Adjust to next XBlock if neccessary
1955 mov [X_S], di ; Save in case it moved
1956 dec [X_D] ; Decremet number of planes to do
1957 jnz @@PlanesW ; If no planes left drop out
1958
1959 ; !!!DONE
1960 pop si di ds ; Return state
1961 pop bp
1962 ret
1963
1964 ENDP _XPut_TileA_M
1965
1966
1967
1968 ; --------------------------- _XMove_Tile ----------------------------------
1969 ; - This function will move a tile about on the current write page
1970 ; - Coord, Size, and destination must be givin
1971 public _XMove_Tile
1972
1973 PROC _XMove_Tile FAR
1974
1975 ARG X_S:WORD, Y_S:WORD, X_E:WORD, Y_E:WORD, X_D:WORD, Y_D:WORD
1976
1977 push bp
1978 mov bp, sp ; Save Stack frame
1979 push ds si di
1980
1981 cld
1982
1983 ; Load DS.
1984 ASSUME ds: @fardata
1985 mov ax, @fardata
1986 mov ds, ax ; Set DS to fardata segment
1987
1988 mov cl, 2
1989
1990 ; Load si with source X in XBlocks
1991 mov si, [X_S]
1992 shr si, cl
1993
1994 ; Load di with destination X in XBlocks
1995 mov di, [X_D]
1996 shr di, cl
1997
1998 ; Convert [X_E] to width in XBlocks
1999 mov bx, [X_E]
2000 shr bx, cl
2001
2002 mov ax, bx ; Save in AX
2003 mov [X_E], bx ; Put back
2004
2005 ; Determine the X direction
2006 cmp si, di
2007 jge @@GoLeft
2008
2009 ; Going right. Copy right to left
2010 dec ax
2011 add si, ax ; Source starts at right edge
2012 add di, ax ; Same with destination
2013 neg bx ; Make negative
2014 std ; Move backwards on string instructions
2015
2016 ; Determine the Y direction
2017 @@GoLeft:
2018 mov cx, [WLine_Offset]
2019 mov ax, [Y_S] ; Get the Y source start
2020 mov dx, [Y_D] ; Get the Y destination
2021 cmp ax, dx ; Going up or down
2022 jge @@GoUp
2023
2024 ; Rectangle going down. Copy bottom to top
2025 mov ax, [Y_E] ; Get the bottom coord
2026 add dx, ax ; Add it to the destination, so
2027 ; it points to end of destination blk
2028 neg cx ; Make CX negative
2029 add ax, [Y_S] ; Point AX to end of source blk
2030 ; by adding size to start
2031
2032 ; Calcuate the offsets
2033 @@GoUp:
2034 push dx ; Save DX the torment of a multiply
2035 mul [WLine_Offset] ; Find Y adder for source
2036 add si, ax ; Add it
2037
2038 pop ax ; Pop off the destination Y into AX
2039 mul [WLine_Offset] ; Find Y adder for destination
2040 add di, ax ; Add it
2041
2042 sub cx, bx ; Find the scan line data
2043
2044 ; Add in the write page offset
2045 add si, [Write_Page]
2046 add di, [Write_Page]
2047
2048 ; Get the Screen Seg and put it in DS and ES
2049 mov ax, SCREEN_SEG
2050 mov ds, ax
2051 mov es, ax
2052
2053 ; Set all data from latches
2054 mov dx, GC_INDEX
2055 mov ax, 00000h + BIT_MASK ; Set all latch writes
2056 out dx, ax
2057
2058 ; Insure Map Mask is set to all planes
2059 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
2060 mov dx, SC_INDEX
2061 out dx, ax
2062
2063 ; Set AX to the Scan line lenghth
2064 mov ax, [X_E]
2065
2066 ; Set BX to the Y size
2067 mov bx, [Y_E]
2068
2069 ; Set DX to the Scan line differential
2070 mov dx, cx
2071
2072 ; Do the WRITES---------------------
2073 @@ScanLoop:
2074
2075 mov cx, ax ; Set cx to the Scan size
2076 rep movsb ; Do the line
2077
2078 ; Add the scan line differential to source and dest
2079 add si, dx
2080 add di, dx
2081
2082 ; See if done with all lines
2083 dec bx
2084 jnz @@ScanLoop ; No, then go and do another line
2085
2086 ; !!DONE!!
2087 pop di si ds
2088 pop bp ; Return state
2089 ret
2090
2091 ENDP _XMove_Tile
2092
2093
2094 ; --------------------------- _XMove_TileA --------------------------------
2095 ; - This function will move a tile to the alternate page
2096 ; - Coord, Size, and destination must be givin
2097 public _XMove_TileA
2098
2099 PROC _XMove_TileA FAR
2100
2101 ARG X_S:WORD, Y_S:WORD, X_E:WORD, Y_E:WORD, X_D:WORD, Y_D:WORD
2102
2103 push bp
2104 mov bp, sp ; Save Stack frame
2105 push ds si di
2106
2107 cld
2108
2109 ; Load DS.
2110 ASSUME ds: @fardata
2111 mov ax, @fardata
2112 mov ds, ax ; Set DS to fardata segment
2113
2114 ; Set all data from latches
2115 mov dx, GC_INDEX
2116 mov ax, 00000h + BIT_MASK ; Set all latch writes
2117 out dx, ax
2118
2119 ; Insure Map Mask is set to all planes
2120 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
2121 mov dx, SC_INDEX
2122 out dx, ax
2123
2124 ; Set SI to start of rectangle in write page
2125 mov ax, [WLine_Offset] ; Get line size
2126 mov cx, ax ; Save in CX
2127 mul [Y_S] ; Find Y offset
2128
2129 mov si, [X_S] ; Find X offset value. Place in DI
2130 shr si, 1
2131 shr si, 1
2132
2133 add si, ax ; Add X and Y offsets
2134 add si, [Write_Page] ; Add in page offset
2135
2136 ; Set DI to start of rectangle in write page
2137 mov ax, [ALine_Offset] ; Get line size
2138 mov bx, ax ; Save in BX
2139 mul [Y_D] ; Find Y offset
2140
2141 mov si, [X_D] ; Find X offset value. Place in DI
2142 shr si, 1
2143 shr si, 1
2144
2145 add si, ax ; Add X and Y offsets
2146 add si, [Alt_Page] ; Add in page offset
2147
2148
2149 ; Set AX to the Scan line lenghth in XBlocks
2150 mov ax, [X_E]
2151 shr ax, 1
2152 shr ax, 1
2153
2154 ; Make BX the scan line differntial for the alt page
2155 sub bx, ax
2156
2157 ; Make DX the scan line differntial for the write page
2158 sub cx, ax
2159 mov dx, cx
2160
2161 ; Set BP to the Y size
2162 mov bp, [Y_E]
2163
2164 ; Get the Screen Seg and put it in DS and ES
2165 mov cx, SCREEN_SEG
2166 mov ds, cx
2167 mov es, cx
2168
2169 ; Do the WRITES---------------------
2170 @@ScanLoop:
2171
2172 mov cx, ax ; Set cx to the Scan size
2173 rep movsb ; Do the line
2174
2175 ; Add the scan line differential to source and dest
2176 add si, dx
2177 add di, bx
2178
2179 ; See if done with all lines
2180 dec bp
2181 jnz @@ScanLoop ; No, then go and do another line
2182
2183 ; !!DONE!!
2184 pop di si ds
2185 pop bp ; Return state
2186 ret
2187
2188 ENDP _XMove_TileA
2189
2190
2191 ; --------------------------- _XRegister_Font8 ------------------------------
2192 ; - This function will register a 8-font.
2193 ; - The function will return in AX the actual number of bytes used.
2194 ; - The function expects each character to be laid out as for Upload_Tile,
2195 ; - one character at a time. Each character is 8x by 10y.
2196
2197 public _XRegister_Font8
2198
2199 PROC _XRegister_Font8 FAR
2200
2201 ARG DEST:WORD, NUMBER:WORD, BASE:WORD, UPLOAD:WORD, FONT_OFF:DWORD
2202
2203 push bp
2204 mov bp, sp ; Save Stack frame
2205 push ds di si
2206
2207 cld
2208
2209 ; Load DS.
2210 ASSUME ds: @fardata
2211 mov ax, @fardata
2212 mov ds, ax ; Set DS to fardata segment
2213
2214 ; Save the base char
2215 mov ax, [BASE]
2216 mov [Char_Base8], ax
2217
2218 ; Will we upload this font?
2219 mov cx, [UPLOAD]
2220 mov [UpLoaded8], cx ; Flag it ( 0 is uploaded )
2221 jcxz @@UploadFont ; Yes!, then jump to it
2222
2223 ; Don't upload this font. Just register and return.
2224 les si, [FONT_OFF]
2225 mov [Font_SiteD8], si
2226 mov ax, es
2227 mov [Font_SiteD8+2], ax
2228 jmp @@DONE
2229
2230 @@UploadFont:
2231 ; Check font size to insure no overrun
2232 mov dx, 20
2233 mov ax, [NUMBER]
2234 mul dx ; Mul number of chars by 20bytes
2235 add ax, [DEST] ; Add destination to get proposed end
2236 cmp ax, STORE ; Where is it in relation to begin
2237 ja @@CONT ; If above, no wrap of AX, OK
2238 mov ax, 0 ; Else leave 0 in AX, indicating ERR
2239 jmp @@DONE ; And jump out
2240
2241 @@CONT:
2242 ; Save the size and location
2243 mov ax, [DEST]
2244 mov [Font_SiteU8], ax
2245
2246 ; Load di with destination offset and save it in DX
2247 mov di, ax ; AX retains it from prev action
2248 mov dx, ax ; Store it
2249
2250 ; Load ds:si with source
2251 lds si, [FONT_OFF]
2252
2253 ; Load es with SCREEN SEG
2254 mov ax, SCREEN_SEG
2255 mov es, ax
2256
2257 ; This section iterates for each char----------------------------
2258 mov bx, [NUMBER] ; Set BL to number of characters
2259
2260 ; Set BP to destination, as was in DX
2261 mov bp, dx
2262
2263 ; Set all data from CPU and non from latches
2264 mov dx, GC_INDEX
2265 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
2266 out dx, ax
2267
2268 ; Set up DX plane selection
2269 mov dx, SC_INDEX
2270
2271 ; Set CX to number of scan lines in a char
2272 mov cx, 10 ; Set CX to 10 scan lines
2273
2274 @@BeginWrite:
2275
2276 ; Set AX up for plane selection
2277 mov ax, 1102h ; Plane 0 selected
2278
2279 ; This section loops through the planes for each char -----------
2280 @@PlanesW: ; Master plane loop.
2281
2282 out dx, ax ; Set the plane
2283
2284 ; Do the actual line. REP MOVSW. Move both XBlocks on each line
2285 rep movsw
2286
2287 ; Done with plane. Reset Destination pointers. Adjst plane
2288 mov di, bp
2289 shl ah, 1 ; Adjust plane. Carry set if done
2290 mov cx, 10 ; Restore CX.
2291
2292 ; !!End of Plane loop.
2293 jnc @@PlanesW ; If no carry, not done with char
2294
2295 ; !!End of Char loop.
2296
2297 add bp, 20 ; Adjust destination for next char
2298 mov di, bp ; Store it in DI
2299
2300 dec bx ; Another char done
2301 jnz @@BeginWrite ; If not zero, not done with font set
2302
2303 ; !!DONE!!
2304 @@DONE:
2305 pop si di ds ; Return state
2306 pop bp
2307 ret
2308
2309 ENDP _XRegister_Font8
2310
2311
2312 ; ----------------------------- _XChar8 ----------------------------------
2313 ; - This function will place a char from the current font to current screen
2314 ; - Uses the 8pix font
2315 public _XChar8
2316
2317 PROC _XChar8 FAR
2318
2319 ARG X_S:WORD, Y_S:WORD, CHAR:WORD
2320
2321 push bp
2322 mov bp, sp ; Save Stack frame
2323 push ds di si
2324
2325 cld
2326
2327 ; Load DS.
2328 ASSUME ds: @fardata
2329 mov ax, @fardata
2330 mov ds, ax ; Set DS to segment w/ Table
2331
2332 ; Set DI to start of character on screen
2333 mov ax, [WLine_Offset]
2334 mul [Y_S] ; Find Y offset value. Place in AX
2335
2336 mov di, [X_S] ; Find X offset value. Place in DI
2337 shr di, 1
2338 shr di, 1 ; Adjust to number of XBlocks
2339
2340 add di, ax ; Add X and Y offsets
2341 add di, [Write_Page] ; Add in page offset
2342
2343 ; Is the font uploaded or not
2344 mov ax, [UpLoaded8]
2345 cmp ax, UPLOADFONT
2346 je @@FontIsUploaded ; The font is uploaded
2347
2348 ; - Font is not uploaded
2349 ; Set CX to the scan line differential
2350 mov cx, [WLine_Offset]
2351 sub cx, 2 ; Subtract the XBlocks of a char
2352
2353 ; Figure character offset and add to load ds:si font site
2354 mov ax, 80 ; Put font size in ax
2355 xor bx, bx ; Clear bx
2356 mov bx, [CHAR] ; Put character place in BX
2357 sub bx, [Char_Base8] ; Subtract base char
2358 mul bx ; Mul size by place
2359 lds si, [Font_Addr8]
2360 add si, ax
2361
2362 ; Move the scan line differential from CX to BP
2363 mov bp, cx
2364
2365 ; Save the base destination in CX
2366 mov cx, di
2367
2368 ; Get the Screen Seg and put it in ES
2369 mov ax, SCREEN_SEG
2370 mov es, ax
2371
2372 ; Set all data from CPU and non from latches
2373 mov dx, GC_INDEX
2374 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
2375 out dx, ax
2376
2377 ; Set up DX and AX for plane selection
2378 mov ax, 1102h ; Plane 0 selected
2379 mov dx, SC_INDEX
2380
2381 ; This section is for WRITES ------------------------------
2382
2383 ; Set BH to number of lines to do
2384 mov bx, 10 ; 10 scan lines per 8-pix font
2385
2386 @@PlanesW: ; Master plane loop.
2387
2388 out dx, ax ; Set the plane
2389
2390 @@RowloopW: ; Scan line loop
2391
2392 ; Do the actual line. MOVSW.
2393 movsw
2394
2395 ; Adjust for next iteration
2396 add di, bp ; Point DI to start of next line
2397
2398 ; !!End of Rowloop. Dec BH, if it is NOT 0 then do next line
2399 dec bx
2400 jnz @@RowloopW
2401
2402 ; Done with plane. Reset Destination pointers. Adjst plane
2403 mov di, cx ; Restore the destination start
2404 mov bx, 10 ; Restore scan line count
2405 shl ah, 1 ; Adjust plane
2406
2407 ; !!End of Plane loop.
2408 jnc @@PlanesW ; If no carry, then more to do.
2409
2410
2411
2412 ; Done with this
2413 jmp @@DONE
2414
2415
2416 ; - Font is uploaded
2417 @@FontIsUploaded:
2418 ; Calc the source and put in SI
2419 mov si, [Font_SiteU8] ; Get base location
2420 mov ax, 20 ; Put font size in ax (in XBlock)
2421 mov bx, [CHAR] ; Put character place in BX
2422 sub bx, [Char_Base8] ; Subtract base char
2423 mul bx ; Mul size by place
2424 add si, ax ; Put in SI
2425
2426 ; Insure Map Mask is set to all planes
2427 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
2428 mov dx, SC_INDEX
2429 out dx, ax
2430
2431 ; Set all data from latches
2432 mov dx, GC_INDEX
2433 mov ax, 00000h + BIT_MASK ; Set all latch writes
2434 out dx, ax
2435
2436 ; Set AX to line dif.
2437 mov ax, [WLine_Offset] ; Page width
2438 sub ax, 2 ; minus XBlocks per char
2439
2440 ; Get the Screen Seg and put it in DS and ES
2441 mov dx, SCREEN_SEG
2442 mov ds, dx
2443 mov es, dx
2444
2445 ; Set CX to the number of scan lines
2446 mov cx, 10
2447
2448 ; This section is for WRITES ------------------------------
2449 @@Rowloop:
2450
2451 ; Do the actual line. MOVSB.
2452 movsb
2453 movsb
2454
2455 ; Adjust for next iteration
2456 add di, ax ; Point DI to start of next line
2457
2458 ; End of Rowloop.
2459 loop @@Rowloop
2460
2461 ; !!DONE!!
2462 @@DONE:
2463 pop si di ds ; Return state
2464 pop bp
2465 ret
2466
2467 ENDP _XChar8;
2468
2469
2470 ; ------------------------ _Register_Font_Masks8 ---------------------------
2471 ; - This function registers a font mask for the current 8pix font
2472 ; - This mask can be used for MFont character drawing
2473 public _Register_Font_Masks8
2474
2475 PROC _Register_Font_Masks8 FAR
2476
2477 ARG MASK_OFF:WORD, MASK_SEG:WORD
2478
2479 push bp
2480 mov bp, sp ; Save Stack frame
2481 push ds
2482
2483 ; Load DS.
2484 ASSUME ds: @fardata
2485 mov ax, @fardata
2486 mov ds, ax ; Set DS to fardata segment
2487
2488 ; Move location to local
2489 mov ax, [MASK_OFF]
2490 mov [Font_Mask_O8], ax
2491
2492 mov ax, [MASK_SEG]
2493 mov [Font_Mask_S8], ax
2494
2495 ; !!DONE!!
2496 pop ds
2497 pop bp ; Return state
2498 ret
2499
2500 ENDP _Register_Font_Masks8
2501
2502
2503 ; ----------------------------- _XChar8_M ----------------------------------
2504 ; - This function will place a char from the current font to current screen
2505 ; - This function requires a font mask set to be registered.
2506 ; - Uses the 8pix font
2507 public _XChar8_M
2508
2509 PROC _XChar8_M FAR
2510
2511 ARG X_S:WORD, Y_S:WORD, CHAR:WORD
2512
2513
2514 push bp
2515 mov bp, sp ; Save Stack frame
2516 push ds di si
2517
2518 cld
2519
2520 ; Load DS.
2521 ASSUME ds: @fardata
2522 mov ax, @fardata
2523 mov ds, ax ; Set DS to fardata segment
2524
2525 ; Set DI to start of rectangle on screen
2526 mov ax, [WLine_Offset]
2527 mov bx, ax ; Save in BX for later
2528 mul [Y_S] ; Find Y offset value. Place in AX
2529 mov di, [X_S] ; Find X offset value. Place in DI
2530 shr di, 1
2531 shr di, 1
2532
2533 add di, ax ; Add X and Y offsets
2534 add di, [Write_Page] ; Add in page offset
2535
2536 ; Is the font uploaded or not
2537 mov cx, [UpLoaded8] ; UPLOADED is 0!
2538 jcxz @@Uploaded ; The font is uploaded
2539
2540 ; - Font is not uploaded
2541
2542 ; Figure character offset and add to load ds:si font site
2543 mov ax, 80 ; Put font size in ax
2544 mov cx, [CHAR] ; Put character place in BX
2545 sub cx, [Char_Base8] ; Subtract base char
2546 mul cx ; Mul size by place
2547 lds si, [Font_Addr8]
2548 add si, ax
2549
2550 ; Set BX to the line differential
2551 dec bx ; BX was set above - first XBlock
2552
2553 ; Save the base destination in BP
2554 mov bp, di
2555
2556 ; Set all data from CPU and non from latches
2557 mov dx, GC_INDEX
2558 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
2559 out dx, ax
2560
2561 ; Get the Screen Seg and put it in ES
2562 mov ax, SCREEN_SEG
2563 mov es, ax
2564
2565 ; Set up DX and AX for plane selection
2566 mov ax, 0102h ; Plane 0 selected
2567 mov dx, SC_INDEX
2568
2569 ; This section is for WORD WRITES ------------------------------
2570
2571 ; Set CX to number of lines to do
2572 mov cx, 10 ; 10 scan lines per 8-pix font
2573
2574 @@PlanesW: ; Master plane loop.
2575
2576 out dx, ax ; Set the plane
2577
2578 @@RowloopW: ; Scan line loop
2579
2580 ; Do the actual DRAW. MOV.
2581 lodsb ; Get the pixel
2582 or al, al ; Is it zero
2583 jz @@NoDraw1 ; If zero, don't draw it
2584 mov [es:di], al ; Else, do draw it
2585
2586 @@NoDraw1:
2587 inc di
2588
2589 lodsb ; Get the pixel
2590 or al, al ; Is it zero
2591 jz @@NoDraw2 ; If zero, don't draw it
2592 mov [es:di], al ; Else, do draw it
2593
2594 @@NoDraw2:
2595 ; Adjust for next iteration
2596 add di, bx ; Point DI to start of next line
2597
2598 ; !!End of Rowloop. Dec CX, if it is NOT 0 then do next line
2599 loop @@RowloopW
2600
2601 ; Done with plane. Reset Destination pointers. Adjst plane
2602 mov di, bp ; Restore the destination start
2603 mov cx, 10 ; Restore scan line count
2604
2605 mov al, 02h ; Restore MAP MASK pointer
2606 shl ah, 1 ; Adjust plane
2607
2608 ; !!End of Plane loop. If carry not set, then not done
2609 jnc @@PlanesW
2610
2611 ; Done with this
2612 jmp @@DONE
2613
2614
2615 @@Uploaded:
2616 ; - Font is uploaded
2617
2618 ; Set SI to mask offset
2619 mov ax, 10 ; Put mask size in ax
2620 mov cx, [CHAR] ; Put character place in CX
2621 sub cx, [Char_Base8] ; Subtract base char
2622 mul cx ; Mul size by place
2623 add ax, [Font_Mask_O8] ; Find masks offset in mask set
2624 mov si, ax ; Save it
2625
2626 ; Calc the source and put in BX
2627 mov bx, [Font_SiteU8] ; Get base location
2628 mov ax, 20 ; Put font size in ax
2629 mov cx, [CHAR] ; Put character place in CX
2630 sub cx, [Char_Base8] ; Subtract base char
2631 mul cx ; Mul size by place
2632 add bx, ax ; Put in BX
2633
2634 ; Set BP to the scan line differential
2635 mov bp, [WLine_Offset]
2636 dec bp
2637
2638 ; Set DS to mask area
2639 mov ax, [Font_Mask_S8]
2640 mov ds, ax
2641
2642 ; Get the Screen Seg and put it in ES
2643 mov ax, SCREEN_SEG
2644 mov es, ax
2645
2646 ; Set all data from latches
2647 mov dx, GC_INDEX
2648 mov ax, 00000h + BIT_MASK ; Set all latch writes
2649 out dx, ax
2650
2651 ; Set up Map Mask
2652 mov al, 02h ; 02 is Map Mask
2653 mov dx, SC_INDEX
2654 out dx, al
2655 inc dx
2656
2657 ; Set CH to the number of scan lines
2658 mov ch, 10
2659
2660 ; Set CL to shift spaces
2661 mov cl, 4
2662
2663 ; This section is for WRITES ------------------------------
2664 @@Rowloop:
2665 ; This section prep the Map Mask
2666 lodsb ; Get mask byte
2667
2668 ; Set mask for first write
2669 out dx, al ; Set map mask
2670
2671 ; Write the first byte
2672 mov ah, [es:bx]
2673 mov [es:di], ah
2674
2675 ; Adjust di, bx
2676 inc di
2677 inc bx
2678
2679 ; Set mask for second write
2680 shr al, cl ; Move upper nibble down
2681 out dx, al ; Set map mask
2682
2683 ; Write the second byte
2684 mov ah, [es:bx]
2685 mov [es:di], ah
2686
2687 ; Adjust bx
2688 inc bx
2689
2690 ; Adjust for next iteration
2691 add di, bp ; Point DI to start of next line
2692
2693 ; End of Rowloop.
2694 dec ch
2695 jnz @@Rowloop
2696
2697 ; !!DONE!!
2698 @@DONE:
2699 pop si di ds ; Return state
2700 pop bp
2701 ret
2702
2703 ENDP _XChar8_M;
2704
2705 ; ----------------------------- _XChar8_C ----------------------------------
2706 ; - This function will place a char from the current font to current screen
2707 ; - This function requires a font mask set to be registered.
2708 ; - Uses only the mask set to place one color characters
2709 public _XChar8_C
2710
2711 PROC _XChar8_C FAR
2712
2713 ARG X_S:WORD, Y_S:WORD, CHAR:WORD, COLOR:WORD
2714
2715
2716 push bp
2717 mov bp, sp ; Save Stack frame
2718 push ds di si
2719
2720 cld
2721
2722 ; Load DS.
2723 ASSUME ds: @fardata
2724 mov ax, @fardata
2725 mov ds, ax ; Set DS to fardata segment
2726
2727 ; Set DI to start of rectangle on screen
2728 mov ax, [WLine_Offset]
2729 mov bx, ax ; Save in BX for later
2730 mul [Y_S] ; Find Y offset value. Place in AX
2731 mov di, [X_S] ; Find X offset value. Place in DI
2732 shr di, 1
2733 shr di, 1
2734
2735 add di, ax ; Add X and Y offsets
2736 add di, [Write_Page] ; Add in page offset
2737
2738 ; Set SI to mask offset
2739 mov ax, 10 ; Put mask size in ax
2740 mov cx, [CHAR] ; Put character place in CX
2741 sub cx, [Char_Base8] ; Subtract base char
2742 mul cx ; Mul size by place
2743 add ax, [Font_Mask_O8] ; Find masks offset in mask set
2744 mov si, ax ; Save it
2745
2746 ; Move the color into bx
2747 mov bx, [COLOR]
2748
2749 ; Set BP to the scan line differential
2750 mov bp, [WLine_Offset]
2751 dec bp
2752
2753 ; Set DS to mask area
2754 mov ax, [Font_Mask_S8]
2755 mov ds, ax
2756
2757 ; Get the Screen Seg and put it in ES
2758 mov ax, SCREEN_SEG
2759 mov es, ax
2760
2761 ; Set all data from CPU and non from latches
2762 mov dx, GC_INDEX
2763 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
2764 out dx, ax
2765
2766 ; Set up Map Mask
2767 mov al, 02h ; 02 is Map Mask
2768 mov dx, SC_INDEX
2769 out dx, al
2770 inc dx
2771
2772 ; Set CH to the number of scan lines
2773 mov ch, 10
2774
2775 ; Set CL to shift spaces
2776 mov cl, 4
2777
2778 ; This section is for WRITES ------------------------------
2779 @@Rowloop:
2780 ; This section prep the Map Mask
2781 lodsb ; Get mask byte
2782
2783 ; Set mask for first write
2784 out dx, al ; Set map mask
2785
2786 ; Write the first set
2787 mov [es:di], bl
2788
2789 ; Adjust di
2790 inc di
2791
2792 ; Set mask for second write
2793 shr al, cl ; Move upper nibble down
2794 out dx, al ; Set map mask
2795
2796 ; Write the second set
2797 mov [es:di], bl
2798
2799 ; Adjust for next iteration
2800 add di, bp ; Point DI to start of next line
2801
2802 ; End of Rowloop.
2803 dec ch
2804 jnz @@Rowloop
2805
2806 ; !!DONE!!
2807 @@DONE:
2808 pop si di ds ; Return state
2809 pop bp
2810 ret
2811
2812 ENDP _XChar8_C;
2813
2814
2815 ;----------------------------- _XString8 ----------------------------------
2816 ; - This function will place a char from the current font to current screen
2817 ; - It will use the masked font on mask flag set to not 0.
2818 public _XString8
2819
2820 PROC _XString8 FAR
2821
2822 ARG X_S:WORD, Y_S:WORD, MASKIT:WORD, STR_OFF:DWORD
2823
2824 push bp
2825 mov bp, sp ; Save Stack frame
2826 push ds di si
2827
2828 ; Load DS.
2829 ASSUME ds: @fardata
2830 mov ax, @fardata
2831 mov ds, ax ; Set DS to segment w/ Table
2832
2833 ; Move flag into CX
2834 mov cx, [MASKIT]
2835
2836 ; Load DS:SI
2837 lds si, [STR_OFF]
2838
2839 ; !!! This is the master string loop
2840 @@STRING:
2841 xor ax, ax
2842 mov al, [ds:si] ; Get the char
2843 cmp al, 0 ; Is it the EOS
2844 je @@DONE ; If so jump
2845
2846 ; Save cx
2847 push cx
2848
2849 ; Build stack frame
2850 push ax ; Push the char
2851 push [Y_S] ; Push the Y coor
2852 push [X_S] ; Push the X coor
2853 ; To mask or not to mask
2854 jcxz @@DontMask ; If Flag = 0, dont mask
2855 call _XChar8_M ; Put the masked char
2856 jmp @@Continue
2857
2858 @@DontMask:
2859 call _XChar8 ; Don't mask
2860
2861 @@Continue:
2862 add sp, 6 ; Adjust the stack
2863
2864 pop cx ; Restore cx
2865
2866 add [X_S], 8 ; Move the cursor
2867 inc si ; Point to next char
2868 jmp @@STRING ; Continue
2869
2870 ; !!DONE!!
2871 @@DONE:
2872 pop si di ds ; Return state
2873 pop bp
2874 ret
2875
2876 ENDP _XString8
2877
2878
2879 ;----------------------------- _XString8_C ----------------------------------
2880 ; - This function will place a char from the current font to current screen
2881 ; - It will use the single color mask.
2882 public _XString8_C
2883
2884 PROC _XString8_C FAR
2885
2886 ARG X_S:WORD, Y_S:WORD, COLOR:WORD, STR_OFF:DWORD
2887
2888 push bp
2889 mov bp, sp ; Save Stack frame
2890 push ds di si
2891
2892 ; Load DS.
2893 ASSUME ds: @fardata
2894 mov ax, @fardata
2895 mov ds, ax ; Set DS to segment w/ Table
2896
2897 ; Load DS:SI
2898 lds si, [STR_OFF]
2899
2900 ; !!! This is the master string loop
2901 @@STRING:
2902 xor ax, ax
2903 mov al, [ds:si] ; Get the char
2904 cmp al, 0 ; Is it the EOS
2905 je @@DONE ; If so jump
2906
2907 ; Save cx
2908 push cx
2909
2910 ; Build stack frame
2911 push [COLOR] ; Push the color
2912 push ax ; Push the char
2913 push [Y_S] ; Push the Y coor
2914 push [X_S] ; Push the X coor
2915
2916 ; Call the char routine
2917 call _XChar8_C ; Put the masked char
2918
2919 ; Recover from call
2920 add sp, 8 ; Adjust the stack
2921
2922 pop cx ; Restore cx
2923
2924 add [X_S], 8 ; Move the cursor
2925 inc si ; Point to next char
2926 jmp @@STRING ; Continue
2927
2928 ; !!DONE!!
2929 @@DONE:
2930 pop si di ds ; Return state
2931 pop bp
2932 ret
2933
2934 ENDP _XString8_C
2935
2936
2937 ; --------------------------- _XRegister_Font4 ------------------------------
2938 ; - This function will register a 4-font.
2939 ; - The function will return in AX the actual number of bytes used.
2940 ; - The function expects each character to be laid out as for Upload_Tile,
2941 ; - one character at a time. Each character is 4x by 6y.
2942
2943 public _XRegister_Font4
2944
2945 PROC _XRegister_Font4 FAR
2946
2947 ARG DEST:WORD, NUMBER:WORD, BASE:WORD, UPLOAD:WORD, FONT_OFF:DWORD
2948
2949 push bp
2950 mov bp, sp ; Save Stack frame
2951 push ds di si
2952
2953 cld
2954
2955 ; Load DS.
2956 ASSUME ds: @fardata
2957 mov ax, @fardata
2958 mov ds, ax ; Set DS to fardata segment
2959
2960 ; Save the base char
2961 mov ax, [BASE]
2962 mov [Char_Base4], ax
2963
2964 ; Will we upload this font?
2965 mov cx, [UPLOAD]
2966 mov [UpLoaded4], cx ; Flag it ( 0 is uploaded )
2967 jcxz @@UploadFont ; Yes!, then jump to it
2968
2969 ; Don't upload this font. Just register and return.
2970 les si, [FONT_OFF]
2971 mov [Font_SiteD4], si
2972 mov ax, es
2973 mov [Font_SiteD4+2], ax
2974 jmp @@DONE
2975
2976 @@UploadFont:
2977 ; Check font size to insure no overrun
2978 mov dx, 6
2979 mov ax, [NUMBER]
2980 mul dx ; Mul number of chars by 20bytes
2981 add ax, [DEST] ; Add destination to get proposed end
2982 cmp ax, STORE ; Where is it in relation to begin
2983 ja @@CONT ; If above, no wrap of AX, OK
2984 mov ax, 0 ; Else leave 0 in AX, indicating ERR
2985 jmp @@DONE ; And jump out
2986
2987 @@CONT:
2988 ; Save the size and location
2989 mov ax, [DEST]
2990 mov [Font_SiteU4], ax
2991
2992 ; Load di with destination offset and save it in DX
2993 mov di, ax ; AX retains it from prev action
2994 mov dx, di ; Store it
2995
2996 ; Load ds:si with source
2997 lds si, [FONT_OFF]
2998
2999 ; Load es with SCREEN SEG
3000 mov ax, SCREEN_SEG
3001 mov es, ax
3002
3003 ; This section iterates for each char----------------------------
3004 mov bx, [NUMBER] ; Set BX to number of characters
3005
3006 ; Set BP to destination
3007 mov bp, dx ; From above.
3008
3009 ; Set all data from CPU and non from latches
3010 mov dx, GC_INDEX
3011 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
3012 out dx, ax
3013
3014 ; Set up DX plane selection
3015 mov dx, SC_INDEX
3016
3017 @@BeginWrite:
3018
3019 ; Set AX up for plane selection
3020 mov ax, 1102h ; Plane 0 selected
3021
3022 ; This section loops through the planes for each char -----------
3023 @@PlanesB: ; Master plane loop.
3024
3025 out dx, ax ; Set the plane
3026
3027 ; Do the actual write. MOVSB. Move 6 single XBlocks on each line
3028 movsb ; 1
3029 movsb ; 2
3030 movsb ; 3
3031 movsb ; 4
3032 movsb ; 5
3033 movsb ; 6
3034
3035 @@EndPlane:
3036 ; Done with plane. Reset Destination pointers. Adjst plane
3037 mov di, bp
3038 shl ah, 1 ; Adjust plane. Carry set if done
3039
3040 ; !!End of Plane loop.
3041 jnc @@PlanesB ; If no carry, not done with char
3042
3043 ; !!End of Char loop.
3044
3045 add bp, 6 ; Adjust destination for next char
3046 mov di, bp ; Store it in DI
3047
3048 dec bx ; Another char done
3049 jnz @@BeginWrite ; If not zero, not done with font set
3050
3051 ; !!DONE!!
3052 @@DONE:
3053 pop si di ds ; Return state
3054 pop bp
3055 ret
3056
3057 ENDP _XRegister_Font4
3058
3059
3060 ; ----------------------------- _XChar4 ----------------------------------
3061 ; - This function will place a char from the current font to current screen
3062 ; - Uses the 8pix font
3063 public _XChar4
3064
3065 PROC _XChar4 FAR
3066
3067 ARG X_S:WORD, Y_S:WORD, CHAR:WORD
3068
3069 push bp
3070 mov bp, sp ; Save Stack frame
3071 push ds di si
3072
3073 cld
3074
3075 ; Load DS.
3076 ASSUME ds: @fardata
3077 mov ax, @fardata
3078 mov ds, ax ; Set DS to segment w/ Table
3079
3080 ; Set DI to start of character on screen
3081 mov ax, [WLine_Offset]
3082 mul [Y_S] ; Find Y offset value. Place in AX
3083
3084 mov di, [X_S] ; Find X offset value. Place in DI
3085 shr di, 1
3086 shr di, 1 ; Adjust to number of XBlocks
3087
3088 add di, ax ; Add X and Y offsets
3089 add di, [Write_Page] ; Add in page offset
3090
3091 ; Is the font uploaded or not
3092 mov ax, [UpLoaded4]
3093 cmp ax, UPLOADFONT
3094 je @@FontIsUploaded ; The font is uploaded
3095
3096 ; - Font is not uploaded
3097 ; Set CX to the scan line differential
3098 mov cx, [WLine_Offset]
3099 dec cx ; Subtract the XBlock of a char
3100
3101 ; Figure character offset and add to load ds:si font site
3102 mov ax, 24 ; Put font size in ax
3103 mov bx, [CHAR] ; Put character place in BX
3104 sub bx, [Char_Base4] ; Subtract base char
3105 mul bx ; Mul size by place
3106 lds si, [Font_Addr4]
3107 add si, ax
3108
3109 ; Save the base destination in BX
3110 mov bx, di
3111
3112 ; Get the Screen Seg and put it in ES
3113 mov ax, SCREEN_SEG
3114 mov es, ax
3115
3116 ; Set all data from CPU and non from latches
3117 mov dx, GC_INDEX
3118 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
3119 out dx, ax
3120
3121 ; Set up DX and AX for plane selection
3122 mov ax, 1102h ; Plane 0 selected
3123 mov dx, SC_INDEX
3124
3125 ; This section is for WRITES ------------------------------
3126
3127 @@PlanesW: ; Master plane loop.
3128
3129 out dx, ax ; Set the plane
3130
3131 ; Put a plane. Completely un-rolled
3132
3133 ; Do line # 1
3134 movsb
3135 add di, cx ; Point DI to start of next line
3136
3137 ; Do line # 2
3138 movsb
3139 add di, cx ; Point DI to start of next line
3140
3141 ; Do line # 3
3142 movsb
3143 add di, cx ; Point DI to start of next line
3144
3145 ; Do line # 4
3146 movsb
3147 add di, cx ; Point DI to start of next line
3148
3149 ; Do line # 5
3150 movsb
3151 add di, cx ; Point DI to start of next line
3152
3153 ; Do line # 6
3154 movsb
3155
3156
3157 ; Done with plane. Reset Destination pointers. Adjst plane
3158 mov di, bx ; Restore the destination start
3159 shl ah, 1 ; Adjust plane
3160
3161 ; !!End of Plane loop.
3162 jnc @@PlanesW ; If no carry, then more to do.
3163
3164
3165 ; Done with this
3166 jmp @@DONE
3167
3168
3169 ; - Font is uploaded
3170 @@FontIsUploaded:
3171 ; Calc the source and put in SI
3172 mov si, [Font_SiteU4] ; Get base location
3173 mov ax, 6 ; Put font size in ax
3174 xor bx, bx ; Clear bx
3175 mov bx, [CHAR] ; Put character place in BX
3176 sub bx, [Char_Base4] ; Subtract base char
3177 mul bx ; Mul size by place
3178 add si, ax ; Put in SI
3179
3180 ; Insure Map Mask is set to all planes
3181 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
3182 mov dx, SC_INDEX
3183 out dx, ax
3184
3185 ; Set all data from latches
3186 mov dx, GC_INDEX
3187 mov ax, 00000h + BIT_MASK ; Set all latch writes
3188 out dx, ax
3189
3190 ; Set AX to line dif.
3191 mov ax, [WLine_Offset] ; Page width
3192 dec ax ; minus XBlocks per char
3193
3194 ; Get the Screen Seg and put it in DS and ES
3195 mov dx, SCREEN_SEG
3196 mov ds, dx
3197 mov es, dx
3198
3199 ; This section is for WRITES ------------------------------
3200
3201 ; - Completely un-rolled
3202
3203 ; Scan line #1
3204 movsb
3205 add di, ax ; Point DI to start of next line
3206
3207 ; Scan line #2
3208 movsb
3209 add di, ax ; Point DI to start of next line
3210
3211 ; Scan line #3
3212 movsb
3213 add di, ax ; Point DI to start of next line
3214
3215 ; Scan line #4
3216 movsb
3217 add di, ax ; Point DI to start of next line
3218
3219 ; Scan line #5
3220 movsb
3221 add di, ax ; Point DI to start of next line
3222
3223 ; Scan line #6
3224 movsb
3225
3226
3227 ; !!DONE!!
3228 @@DONE:
3229 pop si di ds ; Return state
3230 pop bp
3231 ret
3232
3233 ENDP _XChar4;
3234
3235
3236 ; ------------------------ _Register_Font_Masks4 ---------------------------
3237 ; - This function registers a font mask for the current 4pix font
3238 ; - This mask can be used for MFont character drawing
3239 public _Register_Font_Masks4
3240
3241 PROC _Register_Font_Masks4 FAR
3242
3243 ARG MASK_OFF:WORD, MASK_SEG:WORD
3244
3245 push bp
3246 mov bp, sp ; Save Stack frame
3247 push ds
3248
3249 ; Load DS.
3250 ASSUME ds: @fardata
3251 mov ax, @fardata
3252 mov ds, ax ; Set DS to fardata segment
3253
3254 ; Move location to local
3255 mov ax, [MASK_OFF]
3256 mov [Font_Mask_O4], ax
3257
3258 mov ax, [MASK_SEG]
3259 mov [Font_Mask_S4], ax
3260
3261 ; !!DONE!!
3262 pop ds
3263 pop bp ; Return state
3264 ret
3265
3266 ENDP _Register_Font_Masks4
3267
3268
3269 ; ----------------------------- _XChar4_M ----------------------------------
3270 ; - This function will place a char from the current font to current screen
3271 ; - This function requires a font mask set to be registered.
3272 ; - Uses the 4pix font
3273 public _XChar4_M
3274
3275 PROC _XChar4_M FAR
3276
3277 ARG X_S:WORD, Y_S:WORD, CHAR:WORD
3278
3279 push bp
3280 mov bp, sp ; Save Stack frame
3281 push ds di si
3282
3283 cld
3284
3285 ; Load DS.
3286 ASSUME ds: @fardata
3287 mov ax, @fardata
3288 mov ds, ax ; Set DS to fardata segment
3289
3290 ; Set DI to start of rectangle on screen
3291 mov ax, [WLine_Offset]
3292 mov bx, ax ; Save in BX as S/L differential
3293 mul [Y_S] ; Find Y offset value. Place in AX
3294
3295 mov di, [X_S] ; Find X offset value. Place in DI
3296 shr di, 1
3297 shr di, 1
3298
3299 add di, ax ; Add X and Y offsets
3300 add di, [Write_Page] ; Add in page offset
3301
3302 ; Is the font uploaded or not
3303 mov cx, [UpLoaded4] ; UPLOADED is 0!
3304 jcxz @@Uploaded ; The font is uploaded
3305
3306 ; - Font is not uploaded
3307
3308 ; Figure character offset and add to load ds:si font site
3309 mov ax, 24 ; Put font size in ax
3310 mov cx, [CHAR] ; Put character place in BX
3311 sub cx, [Char_Base4] ; Subtract base char
3312 mul cx ; Mul size by place
3313 lds si, [Font_Addr4]
3314 add si, ax
3315
3316 ; Save the base destination in CX
3317 mov cx, di
3318
3319 ; Get the Screen Seg and put it in ES
3320 mov ax, SCREEN_SEG
3321 mov es, ax
3322
3323 ; Set all data from CPU and non from latches
3324 mov dx, GC_INDEX
3325 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
3326 out dx, ax
3327
3328 ; Set up DX and AX for plane selection
3329 mov ax, 0102h ; Plane 0 selected
3330 mov dx, SC_INDEX
3331
3332 ; This section is for WRITES ------------------------------
3333
3334 @@PlanesW: ; Master plane loop.
3335
3336 out dx, ax ; Set the plane
3337
3338
3339 ; Do the actual DRAW. MOV. Completely un-rolled!!
3340
3341 ; Scan line #1
3342 lodsb ; Get the pixel
3343 or al, al ; Is it zero
3344 jz @@NoDraw1 ; If zero, don't draw it
3345 mov [es:di], al ; Else, do draw it
3346
3347 @@NoDraw1:
3348 add di, bx ; Point DI to start of next line
3349
3350 ; Scan line #2
3351 lodsb ; Get the pixel
3352 or al, al ; Is it zero
3353 jz @@NoDraw2 ; If zero, don't draw it
3354 mov [es:di], al ; Else, do draw it
3355
3356 @@NoDraw2:
3357 add di, bx ; Point DI to start of next line
3358
3359 ; Scan line #3
3360 lodsb ; Get the pixel
3361 or al, al ; Is it zero
3362 jz @@NoDraw3 ; If zero, don't draw it
3363 mov [es:di], al ; Else, do draw it
3364
3365 @@NoDraw3:
3366 add di, bx ; Point DI to start of next line
3367
3368 ; Scan line #4
3369 lodsb ; Get the pixel
3370 or al, al ; Is it zero
3371 jz @@NoDraw4 ; If zero, don't draw it
3372 mov [es:di], al ; Else, do draw it
3373
3374 @@NoDraw4:
3375 add di, bx ; Point DI to start of next line
3376
3377 ; Scan line #5
3378 lodsb ; Get the pixel
3379 or al, al ; Is it zero
3380 jz @@NoDraw5 ; If zero, don't draw it
3381 mov [es:di], al ; Else, do draw it
3382
3383 @@NoDraw5:
3384 add di, bx ; Point DI to start of next line
3385
3386 ; Scan line #6
3387 lodsb ; Get the pixel
3388 or al, al ; Is it zero
3389 jz @@NoDraw6 ; If zero, don't draw it
3390 mov [es:di], al ; Else, do draw it
3391
3392 @@NoDraw6:
3393
3394
3395 ; Done with plane. Reset Destination pointers. Adjst plane
3396 mov di, cx ; Restore the destination start
3397
3398 mov al, 02h ; Restore MAP MASK pointer
3399 shl ah, 1 ; Adjust plane
3400
3401 ; !!End of Plane loop. If carry not set, then not done
3402 jnc @@PlanesW
3403
3404 ; Done with this
3405 jmp @@DONE
3406
3407
3408 @@Uploaded:
3409 ; - Font is uploaded
3410
3411 ; Set SI to mask offset
3412 mov ax, 3 ; Put mask size in ax
3413 mov cx, [CHAR] ; Put character place in CX
3414 sub cx, [Char_Base4] ; Subtract base char
3415 mul cx ; Mul size by place
3416 add ax, [Font_Mask_O4] ; Find masks offset in mask set
3417 mov si, ax ; Save it
3418
3419 ; Calc the source and put in BX
3420 mov bx, [Font_SiteU4] ; Get base location
3421 mov ax, 6 ; Put font size in ax
3422 mov cx, [CHAR] ; Put character place in BX
3423 sub cx, [Char_Base4] ; Subtract base char
3424 mul cx ; Mul size by place
3425 add bx, ax ; Put in SI
3426
3427 ; Set BP to the scan line differential
3428 mov bp, [WLine_Offset]
3429
3430 ; Set DS to mask area
3431 mov ax, [Font_Mask_S4]
3432 mov ds, ax
3433
3434 ; Get the Screen Seg and put it in ES
3435 mov ax, SCREEN_SEG
3436 mov es, ax
3437
3438 ; Set all data from latches
3439 mov dx, GC_INDEX
3440 mov ax, 00000h + BIT_MASK ; Set all latch writes
3441 out dx, ax
3442
3443 ; Set up Map Mask
3444 mov al, 02h ; 02 is Map Mask
3445 mov dx, SC_INDEX
3446 out dx, al
3447 inc dx
3448
3449 ; Set CL to shift spaces
3450 mov cl, 4
3451
3452 ; This section is for WRITES ------------------------------
3453
3454 ; -- Completely unrolled
3455
3456 ; Scan Line #1
3457 ; This section prep the Map Mask
3458 lodsb ; Get mask byte
3459
3460 ; Set mask for first write
3461 out dx, al ; Set map mask
3462
3463 ; Write the byte
3464 mov ah, [es:bx]
3465 mov [es:di], ah
3466
3467 ; Scan Line #2
3468 ; Set mask for next write
3469 shr al, cl ; Move upper nibble down
3470 out dx, al ; Set map mask
3471
3472 ; Adjust for next scan line
3473 add di, bp ; Point DI to start of next line
3474 inc bx
3475
3476 ; Write the second byte
3477 mov al, [es:bx]
3478 mov [es:di], al
3479
3480 ; Adjust for next scan line
3481 add di, bp ; Point DI to start of next line
3482 inc bx
3483
3484 ; Scan Line #3
3485 ; This section prep the Map Mask
3486 lodsb ; Get mask byte
3487
3488 ; Set mask for first write
3489 out dx, al ; Set map mask
3490
3491 ; Write the byte
3492 mov ah, [es:bx]
3493 mov [es:di], ah
3494
3495 ; Scan Line #4
3496 ; Set mask for next write
3497 shr al, cl ; Move upper nibble down
3498 out dx, al ; Set map mask
3499
3500 ; Adjust for next scan line
3501 add di, bp ; Point DI to start of next line
3502 inc bx
3503
3504 ; Write the second byte
3505 mov al, [es:bx]
3506 mov [es:di], al
3507
3508 ; Adjust for next scan line
3509 add di, bp ; Point DI to start of next line
3510 inc bx
3511
3512 ; Scan Line #5
3513 ; This section prep the Map Mask
3514 lodsb ; Get mask byte
3515
3516 ; Set mask for first write
3517 out dx, al ; Set map mask
3518
3519 ; Write the byte
3520 mov ah, [es:bx]
3521 mov [es:di], ah
3522
3523 ; Scan Line #6
3524 ; Set mask for next write
3525 shr al, cl ; Move upper nibble down
3526 out dx, al ; Set map mask
3527
3528 ; Adjust for next scan line
3529 add di, bp ; Point DI to start of next line
3530 inc bx
3531
3532 ; Write the second byte
3533 mov al, [es:bx]
3534 mov [es:di], al
3535
3536
3537 ; !!DONE!!
3538 @@DONE:
3539 pop si di ds ; Return state
3540 pop bp
3541 ret
3542
3543 ENDP _XChar4_M;
3544
3545
3546 ; ----------------------------- _XChar4_C ----------------------------------
3547 ; - This function will place a char from the current font to current screen
3548 ; - This function requires a font mask set to be registered.
3549 ; - Uses the 4pix font and the color specified.
3550 public _XChar4_C
3551
3552 PROC _XChar4_C FAR
3553
3554 ARG X_S:WORD, Y_S:WORD, CHAR:WORD, COLOR:WORD
3555
3556 push bp
3557 mov bp, sp ; Save Stack frame
3558 push ds di si
3559
3560 cld
3561
3562 ; Load DS.
3563 ASSUME ds: @fardata
3564 mov ax, @fardata
3565 mov ds, ax ; Set DS to fardata segment
3566
3567 ; Set DI to start of rectangle on screen
3568 mov ax, [WLine_Offset]
3569 mov bx, ax ; Save in BX as S/L differential
3570 mul [Y_S] ; Find Y offset value. Place in AX
3571
3572 mov di, [X_S] ; Find X offset value. Place in DI
3573 shr di, 1
3574 shr di, 1
3575
3576 add di, ax ; Add X and Y offsets
3577 add di, [Write_Page] ; Add in page offset
3578
3579 ; Set SI to mask offset
3580 mov ax, 3 ; Put mask size in ax
3581 mov cx, [CHAR] ; Put character place in CX
3582 sub cx, [Char_Base4] ; Subtract base char
3583 mul cx ; Mul size by place
3584 add ax, [Font_Mask_O4] ; Find masks offset in mask set
3585 mov si, ax ; Save it
3586
3587 ; Set BX to color
3588 mov bx, [COLOR]
3589
3590 ; Set BP to the scan line differential
3591 mov bp, [WLine_Offset]
3592
3593 ; Set DS to mask area
3594 mov ax, [Font_Mask_S4]
3595 mov ds, ax
3596
3597 ; Get the Screen Seg and put it in ES
3598 mov ax, SCREEN_SEG
3599 mov es, ax
3600
3601 ; Set all data from latches
3602 mov dx, GC_INDEX
3603 mov ax, 0FF00h + BIT_MASK ; Set all latch writes
3604 out dx, ax
3605
3606 ; Set up Map Mask
3607 mov al, 02h ; 02 is Map Mask
3608 mov dx, SC_INDEX
3609 out dx, al
3610 inc dx
3611
3612 ; Set CL to shift spaces
3613 mov cl, 4
3614
3615 ; This section is for WRITES ------------------------------
3616
3617 ; -- Completely unrolled
3618
3619 ; Scan Line #1
3620 ; This section prep the Map Mask
3621 lodsb ; Get mask byte
3622
3623 ; Set mask for first write
3624 out dx, al ; Set map mask
3625
3626 ; Write the byte
3627 mov [es:di], bl
3628
3629 ; Scan Line #2
3630 ; Set mask for next write
3631 shr al, cl ; Move upper nibble down
3632 out dx, al ; Set map mask
3633
3634 ; Adjust for next scan line
3635 add di, bp ; Point DI to start of next line
3636
3637 ; Write the second byte
3638 mov [es:di], bl
3639
3640 ; Adjust for next scan line
3641 add di, bp ; Point DI to start of next line
3642
3643 ; Scan Line #3
3644 ; This section prep the Map Mask
3645 lodsb ; Get mask byte
3646
3647 ; Set mask for first write
3648 out dx, al ; Set map mask
3649
3650 ; Write the byte
3651 mov [es:di], bl
3652
3653 ; Scan Line #4
3654 ; Set mask for next write
3655 shr al, cl ; Move upper nibble down
3656 out dx, al ; Set map mask
3657
3658 ; Adjust for next scan line
3659 add di, bp ; Point DI to start of next line
3660
3661 ; Write the second byte
3662 mov [es:di], bl
3663
3664 ; Adjust for next scan line
3665 add di, bp ; Point DI to start of next line
3666
3667 ; Scan Line #5
3668 ; This section prep the Map Mask
3669 lodsb ; Get mask byte
3670
3671 ; Set mask for first write
3672 out dx, al ; Set map mask
3673
3674 ; Write the byte
3675 mov [es:di], bl
3676
3677 ; Scan Line #6
3678 ; Set mask for next write
3679 shr al, cl ; Move upper nibble down
3680 out dx, al ; Set map mask
3681
3682 ; Adjust for next scan line
3683 add di, bp ; Point DI to start of next line
3684
3685 ; Write the second byte
3686 mov [es:di], bl
3687
3688
3689 ; !!DONE!!
3690 @@DONE:
3691 pop si di ds ; Return state
3692 pop bp
3693 ret
3694
3695 ENDP _XChar4_C
3696
3697 ;----------------------------- _XString4 ----------------------------------
3698 ; - This function will place a char from the current font to current screen
3699 ; - It will use the masked font on mask flag set to not 0.
3700 public _XString4
3701
3702 PROC _XString4 FAR
3703
3704 ARG X_S:WORD, Y_S:WORD, MASKIT:WORD, STR_OFF:DWORD
3705
3706 push bp
3707 mov bp, sp ; Save Stack frame
3708 push ds di si
3709
3710 ; Load DS.
3711 ASSUME ds: @fardata
3712 mov ax, @fardata
3713 mov ds, ax ; Set DS to segment w/ Table
3714
3715 ; Move flag into CX
3716 mov cx, [MASKIT]
3717
3718 ; Load DS:SI
3719 lds si, [STR_OFF]
3720
3721 ; !!! This is the master string loop
3722 @@STRING:
3723 xor ax, ax
3724 mov al, [ds:si] ; Get the char
3725 cmp al, 0 ; Is it the EOS
3726 je @@DONE ; If so jump
3727
3728 ; Save cx
3729 push cx
3730
3731 ; Build stack frame
3732 push ax ; Push the char
3733 push [Y_S] ; Push the Y coor
3734 push [X_S] ; Push the X coor
3735 ; To mask or not to mask
3736 jcxz @@DontMask ; If Flag = 0, dont mask
3737 call _XChar4_M ; Put the masked char
3738 jmp @@Continue
3739
3740 @@DontMask:
3741 call _XChar4 ; Don't mask
3742
3743 @@Continue:
3744 add sp, 6 ; Adjust the stack
3745
3746 pop cx ; Restore cx
3747
3748 add [X_S], 4 ; Move the cursor
3749 inc si ; Point to next char
3750 jmp @@STRING ; Continue
3751
3752 ; !!DONE!!
3753 @@DONE:
3754 pop si di ds ; Return state
3755 pop bp
3756 ret
3757
3758 ENDP _XString4
3759
3760
3761 ;----------------------------- _XString4_C ----------------------------------
3762 ; - This function will place a char from the current font to current screen
3763 ; - It will use the single color mask.
3764 public _XString4_C
3765
3766 PROC _XString4_C FAR
3767
3768 ARG X_S:WORD, Y_S:WORD, COLOR:WORD, STR_OFF:DWORD
3769
3770 push bp
3771 mov bp, sp ; Save Stack frame
3772 push ds di si
3773
3774 ; Load DS.
3775 ASSUME ds: @fardata
3776 mov ax, @fardata
3777 mov ds, ax ; Set DS to segment w/ Table
3778
3779 ; Load DS:SI
3780 lds si, [STR_OFF]
3781
3782 ; !!! This is the master string loop
3783 @@STRING:
3784 xor ax, ax
3785 mov al, [ds:si] ; Get the char
3786 cmp al, 0 ; Is it the EOS
3787 je @@DONE ; If so jump
3788
3789 ; Save cx
3790 push cx
3791
3792 ; Build stack frame
3793 push [COLOR] ; Push the color
3794 push ax ; Push the char
3795 push [Y_S] ; Push the Y coor
3796 push [X_S] ; Push the X coor
3797
3798 ; Call the char routine
3799 call _XChar4_C ; Put the masked char
3800
3801 ; Recover from call
3802 add sp, 8 ; Adjust the stack
3803
3804 pop cx ; Restore cx
3805
3806 add [X_S], 4 ; Move the cursor
3807 inc si ; Point to next char
3808 jmp @@STRING ; Continue
3809
3810 ; !!DONE!!
3811 @@DONE:
3812 pop si di ds ; Return state
3813 pop bp
3814 ret
3815
3816 ENDP _XString4_C
3817
3818
3819
3820 ; --------------------------- _XPaste_Tile_M -------------------------------
3821 ; - This function will place a tile from the display memory to current screen
3822 ; - It will use the mask passed to it to leave background transparent
3823 ; - Max Y size is 255
3824
3825 public _XPaste_Tile_M
3826
3827 PROC _XPaste_Tile_M FAR
3828
3829 ARG X_S:WORD, Y_S:WORD, X_D:WORD, Y_D:WORD, TILE:WORD, MASK_O:DWORD
3830
3831 push bp
3832 mov bp, sp ; Save Stack frame
3833 push ds di si
3834
3835 cld
3836
3837 ; Load DS.
3838 ASSUME ds: @fardata
3839 mov ax, @fardata
3840 mov ds, ax ; Set DS to fardata segment
3841
3842 ; Set DI to start of rectangle on screen
3843 mov ax, [WLine_Offset]
3844 mul [Y_S] ; Find Y offset value. Place in AX
3845
3846 mov di, [X_S] ; Find X offset value. Place in DI
3847 shr di, 1
3848 shr di, 1 ; Adjust to number of XBlocks
3849
3850 add di, ax ; Add X and Y offsets
3851 add di, [Write_Page] ; Add in page offset
3852
3853 ; Put in source in BX
3854 mov bx, [TILE]
3855
3856 ; Get the Screen Seg and put it in ES
3857 mov ax, SCREEN_SEG
3858 mov es, ax
3859
3860 ; Set all data from latches
3861 mov dx, GC_INDEX
3862 mov ax, 00000h + BIT_MASK ; Set all latch writes
3863 out dx, ax
3864
3865 ; Set CX to the number of XBlocks per line
3866 mov cx, [X_D]
3867 shr cx, 1
3868 shr cx, 1
3869
3870 ; Get distance from end of one line to start of other and save
3871 mov ax, [WLine_Offset] ; Get screen width
3872 sub ax, cx ; Del number of XBlocks
3873 mov dx, ax ; Save in DX
3874
3875 ; Save cl in ch.
3876 mov ch, cl ; Save in CH
3877
3878
3879 ; Set DS:SI to mask area
3880 lds si, [MASK_O]
3881
3882 ; Set AH to the rows to do
3883 mov ax, [Y_D] ; Puts number in AX
3884 mov ah, al ; Puts number in ah
3885
3886 ; Move scan line differential from dx to bp
3887 mov bp, dx
3888
3889 ; Set up Map Mask
3890 mov al, 02h ; 02 is Map Mask
3891 mov dx, SC_INDEX
3892 out dx, al
3893 inc dx
3894
3895 ; This section is for WRITES ------------------------------
3896 @@Rowloop:
3897
3898 @@ScanLine:
3899 ; This section prep the Map Mask
3900 lodsb ; Get mask byte
3901
3902 ; Set mask for write
3903 out dx, al ; Set map mask
3904
3905 ; Write the XBlock
3906 mov al, [es:bx]
3907 mov [es:di], al
3908
3909 ; Adjust bx and si
3910 inc bx
3911 inc di
3912
3913 ; End of ScanLine
3914 dec cl
3915 jnz @@ScanLine
3916
3917 ; Adjust for next iteration
3918 add di, bp ; Point DI to start of next line
3919
3920 ; Restore cl
3921 mov cl, ch
3922
3923 ; End of Rowloop.
3924 dec ah
3925 jnz @@Rowloop
3926
3927 ; !!DONE!!
3928 @@DONE:
3929 pop si di ds ; Return state
3930 pop bp
3931 ret
3932
3933 ENDP _XPaste_Tile_M;
3934
3935
3936 ; --------------------------- _XPaste_Sprite_M ----------------------------
3937 ; - This function will place a sprite from the display memory to current screen
3938 ; - It will use the mask passed to it to leave background transparent
3939 ; - Max Y size is 255
3940 public _XPaste_Sprite_M
3941
3942 PROC _XPaste_Sprite_M FAR
3943
3944 ARG X_S:WORD, Y_S:WORD, X_D:WORD, Y_D:WORD, TILE:WORD, MASK_O:DWORD
3945
3946 push bp
3947 mov bp, sp ; Save Stack frame
3948 push ds di si
3949
3950 cld
3951
3952 ; Load DS.
3953 ASSUME ds: @fardata
3954 mov ax, @fardata
3955 mov ds, ax ; Set DS to fardata segment
3956
3957 ; Set all data from latches
3958 mov dx, GC_INDEX
3959 mov ax, 00000h + BIT_MASK ; Set all latch writes
3960 out dx, ax
3961
3962 ; Set DI to start of rectangle on screen
3963 mov ax, [WLine_Offset] ; Scan line size
3964 mul [Y_S] ; Find Y offset value. Place in AX
3965
3966 mov di, [X_S] ; Find X offset value. Place in DI
3967 shr di, 1
3968 shr di, 1 ; Adjust to number of XBlocks
3969
3970 add di, ax ; Add X and Y offsets
3971 add di, [Write_Page] ; Add in page offset
3972
3973 ; Put source in BX
3974 mov bx, [TILE]
3975
3976 ; Find adjustment to source for alignment
3977 mov ax, [X_D]
3978 mov cx, [X_S]
3979
3980 shr ax, 1 ; Number of XBlocks a line
3981 shr ax, 1
3982 mul [Y_D] ; Find size of each sprite alignment
3983
3984 and cx, 3 ; Mask all but 2 LSBs
3985
3986 mul cx ; Find new offset
3987
3988 add bx, ax ; Adjust BX
3989
3990 ; Save adjustment for mask for alignment in DX
3991 mov dx, ax ; AX as calculated above
3992
3993 ; Set CX to the number of XBlocks
3994 mov cx, [X_D]
3995 shr cx, 1
3996 shr cx, 1
3997
3998 ; Get distance from end of one line to start of other and save
3999 mov ax, [WLine_Offset] ; Get screen width
4000 sub ax, cx ; Del number of XBlocks
4001
4002 ; Set DS:SI to mask area
4003 lds si, [MASK_O]
4004
4005 ; Add alignment adjust to si
4006 add si, dx
4007
4008 ; Set AH to the rows to do
4009 mov dx, [Y_D] ; Puts number in AX
4010 mov bp, ax ; Move diff into BP
4011 mov ah, dl ; Puts number in ah
4012
4013 ; Get the Screen Seg and put it in ES
4014 mov dx, SCREEN_SEG
4015 mov es, dx
4016
4017 ; Set up Map Mask
4018 mov al, 02h ; 02 is Map Mask
4019 mov dx, SC_INDEX
4020 out dx, al
4021 inc dx
4022
4023 ; Save scan length (CL) in CH
4024 mov ch, cl
4025
4026 ; This section is for WRITES ------------------------------
4027 @@Rowloop:
4028
4029 @@ScanLine:
4030 ; This section prep the Map Mask
4031 lodsb ; Get mask byte
4032
4033 ; Set mask for write
4034 out dx, al ; Set map mask
4035
4036 ; Write the XBlock
4037 mov al, [es:bx]
4038 mov [es:di], al
4039
4040 ; Adjust bx and si
4041 inc bx
4042 inc di
4043
4044 ; End of ScanLine
4045 dec cl
4046 jnz @@ScanLine
4047
4048
4049 ; Adjust for next iteration
4050 add di, bp ; Point DI to start of next line
4051
4052 ; Restore scan length
4053 mov cl, ch
4054
4055 ; End of Rowloop.
4056 dec ah
4057 jnz @@Rowloop
4058
4059 ; !!DONE!!
4060 @@DONE:
4061 pop si di ds ; Return state
4062 pop bp
4063 ret
4064
4065 ENDP _XPaste_Sprite_M;
4066
4067
4068 ; ------------------------ _XSet_Pal_Color ---------------------------
4069 ; - This function uses the bios to set a single color in the palette
4070 ; - Does !not! wait for retrace
4071 public _XSet_Pal_Color
4072
4073 PROC _XSet_Pal_Color FAR
4074
4075 ARG COLOR:WORD, RED:WORD, GREEN:WORD, BLUE:WORD
4076
4077 push bp
4078 mov bp, sp ; Save Stack frame
4079
4080 ; Set color to change
4081 mov ax, [COLOR] ; Load color number
4082 mov dx, PAL_SET_COLOR
4083 out dx, al
4084
4085 ; Set red
4086 mov dx, PAL_RGB_COLOR
4087 mov ax, [RED]
4088 out dx, al
4089
4090 ; Set green
4091 mov ax, [GREEN]
4092 out dx, al
4093
4094 ; Set blue
4095 mov ax, [BLUE]
4096 out dx, al
4097
4098 pop bp ; Return state
4099 ret
4100
4101 ENDP _XSet_Pal_Color
4102
4103 ; ------------------------ _XSet_Pal_Block ---------------------------
4104 ; - This function uses the bios to set a block of colors in the palette
4105 ; - !Does! wait for retrace
4106 public _XSet_Pal_Block
4107
4108 PROC _XSet_Pal_Block FAR
4109
4110 ARG START:WORD, NUMBER:WORD, PAL_O:DWORD
4111
4112 push bp
4113 mov bp, sp ; Save Stack frame
4114
4115 ; Save registers
4116 push ds si
4117
4118 ; Set CX to number of colors and BX to current
4119 mov cx, [NUMBER]
4120 mov bx, [START]
4121
4122 ; Set ds:si to pal data
4123 lds si, [PAL_O]
4124
4125 ; -- Wait retrace
4126 mov dx, IN_STATUS1
4127 @@WaitP:
4128 in al, dx
4129 and al, 08h ; Vertical Retrace Start?
4130 jz @@WaitP ; If Not, loop until it is
4131
4132 ; ------- Main loop
4133 @@Another:
4134
4135 ; Set color to change
4136 mov dx, PAL_SET_COLOR
4137 mov al, bl
4138 out dx, al
4139
4140 ; Set RGB
4141 mov dx, PAL_RGB_COLOR
4142 lodsb ; Get byte
4143 out dx, al ; Red
4144 lodsb
4145 out dx, al ; Green
4146 lodsb
4147 out dx, al ; Blue
4148
4149 ; Next values and loop if any left
4150 inc bx
4151 dec cx
4152 jnz @@Another
4153
4154 ; --- Done
4155 pop si ds
4156 pop bp ; Return state
4157 ret
4158
4159 ENDP _XSet_Pal_Block
4160
4161
4162 ; ------------------------ _XPut_Pixel ------------------------------------
4163 ; - Put a pixel to the screen.
4164 ; -
4165 public _XPut_Pixel
4166
4167 PROC _XPut_Pixel FAR
4168
4169 ARG X_LOC:WORD, Y_LOC:WORD, COLOR:WORD
4170
4171 push bp
4172 mov bp, sp ; Save Stack frame
4173
4174 push ds di
4175
4176
4177 ; Load DS.
4178 ASSUME ds: @fardata
4179 mov ax, @fardata
4180 mov ds, ax ; Set DS to fardata segment
4181
4182 ; Set DI to the XBlock
4183 mov ax, [WLine_Offset] ; Scan line size
4184 mul [Y_LOC] ; Find Y offset value. Place in AX
4185
4186 mov di, [X_LOC] ; Find X offset value. Place in DI
4187 mov cx, di ; For later to determine the mask
4188 shr di, 1
4189 shr di, 1 ; Adjust to number of XBlocks
4190
4191 add di, ax ; Add X and Y offsets
4192 add di, [Write_Page] ; Add in page offset
4193
4194
4195 ; Set ah to the mask
4196 and cx, 03h ; Get the lower 2 bits
4197 mov ax, 0102h ; MAP MASK
4198 shl ah, cl ; Shift to app. plane
4199
4200 ; Set up Map Mask
4201 mov dx, SC_INDEX
4202 out dx, ax
4203
4204 ; Set all data from CPU and non from latches
4205 mov dx, GC_INDEX
4206 mov ax, 0FF00h + BIT_MASK ; Set all CPU writes
4207 out dx, ax
4208
4209 ; Get the Screen Seg and put it in DS
4210 mov ax, SCREEN_SEG
4211 mov ds, ax
4212
4213 ; Get the color
4214 mov ax, [COLOR]
4215
4216 ; Put the Pixel
4217 mov [di], al
4218
4219 ; !!DONE!!
4220 pop di ds ; Return state
4221 pop bp
4222 ret
4223
4224 ENDP _XPut_Pixel
4225
4226
4227 ; ------------------------ _XPut_Line ------------------------------------
4228 ; - Put a line to the screen.
4229 ; -
4230 ; - Thanks to Matt Pritchard for some of this code
4231 public _XPut_Line
4232 PROC _XPut_Line FAR
4233
4234 ARG XSTART:WORD, YSTART:WORD, XEND:WORD, YEND:WORD, COLOR:WORD
4235
4236
4237 push bp
4238 mov bp, sp ; Save Stack frame
4239 push ds di si
4240
4241 ; Load DS.
4242 ASSUME ds: @fardata
4243 mov ax, @fardata
4244 mov ds, ax ; Set DS to fardata segment
4245
4246 cld
4247
4248 ; Set all data from CPU
4249 mov dx, GC_INDEX
4250 mov ax, 0FF00h + BIT_MASK
4251 out dx, ax
4252
4253 ; Set up ES
4254 mov ax, SCREEN_SEG
4255 mov es, ax
4256
4257 ; Set up Map Mask
4258 mov al, 02h ; 02 is Map Mask
4259 mov dx, SC_INDEX
4260 out dx, al
4261 inc dx
4262
4263 ; Check Line Type
4264
4265 mov si, [XSTART]
4266 mov di, [XEND]
4267 cmp si, di ; Is XSTART < XEND?
4268 je @@Vertical ; If X1=X2, it is a vertical line
4269 jl @@NoSwap ; If X1 < X2, no swap is needed
4270
4271 xchg si, di ; Swap so lower is in SI
4272
4273 @@NoSwap:
4274
4275 mov ax, [YSTART] ;
4276 cmp ax, [YEND] ; YSTART = YEND?
4277 je @@Horizontal ; If so, it is a horizontal line
4278
4279 jmp @@Brezhem ; Otherwise, use Brezhem's algorithm
4280
4281 ; Draw a horizontal line
4282 @@Horizontal:
4283 mul [WLine_Offset] ; Get Y offset into write page
4284 mov dx, ax ; Save in DX
4285
4286 mov ax, si
4287 and si, 3 ; Mask out plane bits
4288
4289 mov bl, [Left_Clip_Mask+si] ; Get Left Edge Mask
4290 mov cx, di ; Get Right edge, Save XSTART
4291 and di, 3 ; Mask out scan
4292 mov bh, [Right_Clip_Mask+di] ; Get Right Edge Mask byte
4293
4294 ; Convert AX and CX to XBlocks
4295 shr ax, 1
4296 shr ax, 1
4297 shr cx, 1
4298 shr cx, 1
4299
4300 ; Find start address
4301 mov di, [Write_Page]
4302 add di, dx ; Point to start of scan line
4303 add di, ax ; Point to start pixel
4304
4305 sub cx, ax ; Set CX to number of XBlocks - 1
4306 jnz @@Long ; Jump if more that one XBlock
4307
4308 and bl, bh ; Otherwise, merge clip masks
4309
4310 @@Long:
4311 mov dx, SC_INDEX+1 ; Point to SC data
4312
4313 ; Set left mask
4314 mov al, bl
4315 out dx, al
4316
4317 ; Get Color
4318 mov ax, [COLOR]
4319 mov bl, al ; Save color in bl
4320
4321 ; Set first XBlock
4322 stosb
4323
4324 jcxz @@DoneThis ; Done if only one XBlock
4325
4326 ; Dec cx and see if any middle XBlocks
4327 dec cx
4328 jz @@NoMiddleX
4329
4330 ; Draw middle XBlocks
4331
4332 ; Set map mask to all planes
4333 mov al, 0Fh
4334 out dx, al
4335
4336 ; Restore color and draw middle segments
4337 mov al, bl
4338 rep stosb
4339
4340 @@NoMiddleX:
4341 ; Do Left clip
4342 mov al, bh
4343 out dx, al
4344 stosb
4345
4346 @@DoneThis:
4347 jmp @@Done
4348
4349 ; Draw vertical line
4350 @@Vertical:
4351 mov ax, [YSTART]
4352 mov si, [YEND]
4353 cmp ax, si ; Is Y1 < Y2?
4354 jle @@NoSwap2 ; if so, Don't Swap
4355
4356 xchg ax, si ; Ok, swap lower into ax
4357
4358 @@NoSwap2:
4359 sub si, ax
4360 inc si
4361
4362 ; Get start address
4363 mul [WLine_Offset]
4364 mov dx, di ; Save XSTART in dx
4365 shr di, 1 ; Convert to XBlocks
4366 shr di, 1
4367
4368 add di, ax
4369 add di, [Write_Page]
4370
4371 ; Select Plane
4372 mov cl, dl ; Get lower of XSTART
4373 and cl, 3 ; Mask of plane selectoin bits
4374 mov ax, 0102h ; Map Mask register access
4375 shl ah, cl ; Shift to plane
4376 mov dx, SC_INDEX
4377 out dx, ax
4378
4379 ; Setup for writes
4380 mov ax, [COLOR] ; Get color
4381 mov bx, [WLine_Offset] ; Scan line differential
4382
4383 @@VertLoop:
4384 mov [es:di], al ; Write a pixel
4385 add di , bx ; Next scan line
4386 dec si
4387 jz @@EndLoop ; Done?
4388
4389 mov [es:di], al ; Write a pixel
4390 add di , bx ; Next scan line
4391 dec si
4392 jnz @@VertLoop ; More?
4393
4394 @@EndLoop:
4395 jmp @@Done
4396
4397 ; Brezhem's algorithm
4398 @@Brezhem:
4399
4400 ; Load write page into di
4401 mov di, [Write_Page]
4402
4403 ; Load starting values
4404 mov ax, [YSTART]
4405 mov bx, [YEND]
4406 mov cx, [XSTART]
4407
4408 cmp bx, ax ; Is Y2 >= Y1 is?
4409 jnc @@YOK ; If yes, OK!
4410
4411 xchg bx, ax ; Otherwise swap
4412 mov cx, [XEND] ; Get New Starting X
4413
4414 @@YOK:
4415 ; Find start address
4416 mul [WLine_Offset]
4417 add di, ax
4418 mov ax, cx
4419 shr ax, 1 ; Convert to XBlocks
4420 shr ax, 1
4421 add di, ax
4422
4423 ; Push color and start mask in same word
4424 mov ax, [COLOR]
4425 xchg ah, al
4426 mov al, 11h
4427 and cl, 3
4428 shl al, cl ; Find mask
4429 push ax
4430
4431 ; Prep map mask
4432 xchg ah, al
4433 mov al, 02h ; Map Mask register
4434 mov dx, SC_INDEX
4435 out dx, ax
4436
4437 ; Load position values
4438 mov ax, [XSTART]
4439 mov bx, [YSTART]
4440 mov cx, [XEND]
4441 mov dx, [YEND]
4442
4443 ; Load line size in BP
4444 mov bp, [WLine_Offset]
4445
4446 ; Check Y delta
4447 sub dx, bx ; Find delta
4448 jnc @@YDeltaOK ; Jump if Y2 >= Y1, delta ok
4449
4450 add bx, dx ; Otherwise fixup
4451 neg dx
4452 xchg ax, cx
4453
4454 @@YDeltaOK:
4455 mov bx, 08000H ; Seed for fraction AC
4456 sub cx, ax ; figure Delta_X
4457 jc @@DrawLeft ; if negative, go left
4458
4459 jmp @@DrawRight ; Draw Line that slopes right
4460
4461 @@DrawLeft:
4462 neg cx ; abs(Delta_X)
4463 cmp cx, dx ; is Delta_X < Delta_Y?
4464 jb @@SteepLeft ; yes, so go do steep line
4465 ; (Delta_Y iterations)
4466
4467 ; Draw a Shallow line to the left
4468 @@ShallowLeft:
4469 xor ax, ax ; zero low word of Delta_Y * 10000h
4470 sub ax, dx ; DX:AX <- DX * 0FFFFh
4471 sbb dx, 0 ; include carry
4472 div cx ; divide by Delta_X
4473
4474 mov si, bx ; SI = Accumulator
4475 mov bx, ax ; BX = Add fraction
4476 pop ax ; Get Color, Bit mask
4477 mov dx, SC_INDEX+1 ; Sequence controller data register
4478 inc cx ; Inc Delta_X so we can unroll loop
4479
4480 ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...
4481 @@SLLLoop:
4482 mov [es:di], ah
4483 dec cx
4484 jz @@SLLExit ; Delta_X--, Exit if done
4485
4486 add si, bx ; add numerator to accumulator
4487 jnc @@SLLL2nc ; move down on carry
4488
4489 add di, bp ; Move Down one line...
4490
4491 @@SLLL2nc:
4492 dec di ; Left one addr
4493 ror al, 1 ; Move Left one plane, back on 0 1 2
4494 cmp al, 87h ; wrap?, if AL <88 then Carry set
4495 adc di, 0 ; Adjust Address: DI = DI + Carry
4496 out dx, al ; Set up New Bit Plane mask
4497
4498 mov [es:di], al ; set pixel
4499 dec cx
4500 jz @@SLLExit ; Delta_X--, Exit if done
4501
4502 add si, bx ; add numerator to accumulator,
4503 jnc @@SLLL3nc ; move down on carry
4504
4505 add di, bp ; Move Down one line...
4506
4507 @@SLLL3nc: ; Now move left a pixel...
4508 dec di ; Left one addr
4509 ror al, 1 ; Move Left one plane, back on 0 1 2
4510 cmp al, 87h ; Wrap?, if AL <88 then Carry set
4511 adc di, 0 ; Adjust Address: DI = DI + Carry
4512 out dx, al ; Set up New Bit Plane mask
4513 jmp @@SLLLoop ; loop until done
4514
4515 @@SLLExit:
4516 jmp @@Done ; Done
4517
4518 ; Draw a steep line to the left
4519 @@SteepLeft:
4520 xor ax, ax ; zero low word of Delta_Y * 10000h
4521 xchg dx, cx ; Delta_Y switched with Delta_X
4522 div cx ; divide by Delta_Y
4523
4524 mov si, bx ; SI = Accumulator
4525 mov bx, ax ; BX = Add Fraction
4526 pop ax ; Get Color, Bit mask
4527 mov dx, SC_INDEX+1 ; Sequence controller data register
4528 inc cx ; Inc Delta_Y so we can unroll loop
4529
4530 ; Loop (x2) to Draw Pixels, Move Down, and Maybe left
4531 @@STLLoop:
4532
4533 mov [es:di], ah ; set first pixel
4534 dec cx
4535 jz @@STLExit ; Delta_Y--, Exit if done
4536
4537 add si, bx ; add numerator to accumulator
4538 jnc @@STLnc2 ; No carry, just move down!
4539
4540 dec di ; Move Left one addr
4541 ror al, 1 ; Move Left one plane, back on 0 1 2
4542 cmp al, 87h ; Wrap?, if AL <88 then Carry set
4543 adc di, 0 ; Adjust Address: DI = DI + Carry
4544 out dx, al ; Set up New Bit Plane mask
4545
4546 @@STLnc2:
4547 add di, bp ; advance to next line.
4548
4549 mov [es:di], ah ; set pixel
4550 dec cx
4551 jz @@STLExit ; Delta_Y--, Exit if done
4552
4553 add si, bx ; add numerator to accumulator
4554 jnc @@STLnc3 ; No carry, just move down!
4555
4556 dec di ; Move Left one addr
4557 ror al, 1 ; Move Left one plane, back on 0 1 2
4558 cmp al, 87h ; Wrap?, if AL <88 then Carry set
4559 adc di, 0 ; Adjust Address: DI = DI + Carry
4560 out dx, al ; Set up New Bit Plane mask
4561
4562 @@STLnc3:
4563 add di, bp ; advance to next line.
4564 jmp @@STLLoop ; Loop until done
4565
4566 @@STLExit:
4567 jmp @@Done ; Done!
4568
4569 ; Draw a line that goes to the Right...
4570 @@DrawRight:
4571 cmp cx, dx ; is Delta_X < Delta_Y?
4572 jb @@SteepRight ; yes, so go do steep line
4573 ; (Delta_Y iterations)
4574
4575 ; Draw a Shallow line to the Right in Mode X
4576 @@ShallowRight:
4577 xor ax, ax ; zero low word of Delta_Y * 10000h
4578 sub ax, dx ; DX:AX <- DX * 0FFFFh
4579 sbb dx, 0 ; include carry
4580 div cx ; divide by Delta_X
4581
4582 mov si, bx ; SI = Accumulator
4583 mov bx, ax ; BX = Add Fraction
4584 pop ax ; Get Color, Bit mask
4585 mov dx, SC_INDEX+1 ; Sequence controller data register
4586 inc cx ; Inc Delta_X so we can unroll loop
4587
4588 ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...
4589 @@SLRLoop:
4590 mov [es:di], ah ; set first pixel, mask is set up
4591 dec cx
4592 jz @@SLRExit ; Delta_X--, Exit if done..
4593
4594 add si, bx ; add numerator to accumulator
4595 jnc @@SLR2nc ; don't move down if carry not set
4596
4597 add di, bp ; Move Down one line...
4598
4599 @@SLR2nc: ; Now move right a pixel...
4600 rol al, 1 ; Move Right one addr if Plane = 0
4601 cmp al, 12h ; Wrap? if AL >12 then Carry not set
4602 adc di, 0 ; Adjust Address: DI = DI + Carry
4603 out dx, al ; Set up New Bit Plane mask
4604
4605 mov [es:di], ah ; set pixel
4606 dec cx
4607 jz @@SLRExit ; Delta_X--, Exit if done..
4608
4609 add si, bx ; add numerator to accumulator
4610 jnc @@SLR3nc ; don't move down if carry not set
4611
4612 add di, bp ; Move Down one line...
4613
4614 @@SLR3nc:
4615 rol al, 1 ; Move Right one addr if Plane = 0
4616 cmp al, 12h ; Wrap? if AL >12 then Carry not set
4617 adc di, 0 ; Adjust Address: DI = DI + Carry
4618 out dx, al ; Set up New Bit Plane mask
4619 jmp @@SLRLoop ; loop till done
4620
4621 @@SLRExit:
4622 jmp @@Done
4623
4624 ; Draw a Steep line to the Right in Mode X
4625
4626 @@SteepRight:
4627 xor ax, ax ; zero low word of Delta_Y * 10000h
4628 xchg dx, cx ; Delta_Y switched with Delta_X
4629 div cx ; divide by Delta_Y
4630
4631 mov si, bx ; SI = Accumulator
4632 mov bx, ax ; BX = Add Fraction
4633 pop ax ; Get Color, Bit mask
4634 mov dx, SC_INDEX+1 ; Sequence controller data register
4635 inc cx ; Inc Delta_Y so we can unroll loop
4636
4637 ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right
4638
4639 @@STRLoop:
4640 mov [es:di], ah ; set first pixel, mask is set up
4641 dec cx
4642 jz @@Done ; Delta_Y--, Exit if Done
4643
4644 add si, bx ; add numerator to accumulator
4645 jnc @@STRnc2 ; if no carry then just go down...
4646
4647 rol al, 1 ; Move Right one addr if Plane = 0
4648 cmp al, 12h ; Wrap? if AL >12 then Carry not set
4649 adc di, 0 ; Adjust Address: DI = DI + Carry
4650 out dx, al ; Set up New Bit Plane mask
4651
4652 @@STRnc2:
4653 add di, bp ; advance to next line.
4654
4655 mov [es:di], ah ; set pixel
4656 dec cx
4657 jz @@Done ; Delta_Y--, Exit if Done
4658
4659 add si, bx ; add numerator to accumulator
4660 jnc @@STRnc3 ; if no carry then just go down...
4661
4662 rol al, 1 ; Move Right one addr if Plane = 0
4663 cmp al, 12h ; Wrap? if AL >12 then Carry not set
4664 adc di, 0 ; Adjust Address: DI = DI + Carry
4665 out dx, al ; Set up New Bit Plane mask
4666
4667 @@STRnc3:
4668 add di, bp ; advance to next line.
4669 jmp @@STRLoop ; loop till done
4670
4671 ; !!DONE!!
4672 @@Done:
4673 pop si di ds ; Return state
4674 pop bp
4675 ret
4676
4677 ENDP _XPut_Line
4678
4679
4680 ; ------------------------ _MEvent_Handler ---------------------------
4681 ; - Xtile's mouse event handler
4682 ; - This one will NOT handle split screen
4683 ; -
4684 PROC _MEvent_Handler
4685
4686 ; Save thier DS
4687 push ds di si
4688
4689 ; This function is not callable from 'c' so we won't build a
4690 ; stack frame
4691
4692 ; Save the event masks
4693 push ax
4694
4695 ; Correct X pos
4696 shr cx, 1
4697
4698 ; Save dx in SI
4699 mov si, dx
4700
4701 ; Load DS.
4702 ASSUME ds: @fardata
4703 mov ax, @fardata
4704 mov ds, ax ; Set DS to fardata segment
4705
4706 ; Check for Lock
4707 cmp [LockHandler], NOTLOCKM ; Is it locked
4708 jz @@NotLocked
4709
4710 ; !!!Locked!!! Jump out
4711 pop ax ; Pull flags off stack
4712 jmp @@Done
4713
4714 @@NotLocked:
4715 ; Lock the handler
4716 mov ax, LOCKM
4717 mov [LockHandler], ax
4718
4719 ; Get and save the status of bit mask and map mask
4720 ; Get status of bit mask
4721 mov dx, GC_INDEX
4722 mov ax, 0808h ; 08 is bit mask
4723 out dx, al
4724 inc dx
4725 in al, dx ; Get the bit mask
4726 xchg al, ah
4727 push ax
4728
4729 ; Get Map Mask
4730 mov ax, 0202h ; 02 is Map Mask
4731 mov dx, SC_INDEX
4732 out dx, al
4733 inc dx
4734 in al, dx
4735 xchg al, ah
4736 push ax
4737
4738 ; -- Restore the the current background location ---
4739 ; This is a Save Site restore
4740 cld
4741
4742 ; Set DI to start of rectangle on screen
4743 mov ax, [DLine_Offset] ; Get line size
4744 mov bx, [MLastY] ; Get Y into view
4745 push bx ; Save on stack
4746 add bx, [ViewYLoc] ; Add start of view
4747 mul bx ; Find Y offset value. Place in AX
4748
4749 mov di, [MLastX] ; Find X offset value. Place in DI
4750 mov bp, di ; Save X in BP
4751 add di, [ViewXLoc] ; Get start of view and add it
4752 shr di, 1
4753 shr di, 1
4754
4755 add di, ax ; Add X and Y offsets
4756 add di, [MousePage] ; Add in page offset
4757
4758 ; Get DX back
4759 mov dx, si
4760
4761 ; Save the new location as the last known
4762 mov [MLastY], dx
4763 mov [MLastX], cx
4764
4765 ; See if we need to clip Second XBlock
4766 mov cx, 2 ; Assume 2 XBlocks to write
4767 mov dx, [ScreenSizeX] ; Get screen size
4768 sub dx, 4 ; Get 2nd to last XBlock
4769 cmp dx, bp
4770 jae @@Continue ; Both blocks on reload
4771 dec cx ; Only one block on reload
4772
4773 @@Continue:
4774 ; Set all data from latches
4775 mov dx, GC_INDEX
4776 mov ax, 00000h + BIT_MASK ; Set all latch writes
4777 out dx, ax
4778
4779 ; Insure Map Mask is set to all planes
4780 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
4781 mov dx, SC_INDEX
4782 out dx, ax
4783
4784 ; Set DX to number of lines to display
4785 mov dx, 8 ; Assume 8 scan lines
4786 pop bx ; Get Y last and put in BX
4787 mov ax, [MouseLines] ; Get Screen size Y and put in ax
4788 sub ax, 8 ; Subtract to make mimimum clip
4789
4790 cmp ax, bx ; Does it need clipping?
4791 ja @@ContinueC ; No, then go!
4792
4793 sub bx, ax ; Needs clipping! Find new DX
4794 sub dx, bx
4795
4796 @@ContinueC:
4797 ; Set BP to the distance from one scan line to next
4798 mov bp, [DLine_Offset]
4799 sub bp, cx ; # XBlocks per scan line
4800
4801 ; Get the Screen Seg and put it in DS and ES
4802 mov ax, SCREEN_SEG
4803 mov ds, ax
4804 mov es, ax
4805
4806 ; Set SI to source
4807 mov si, MSAVEOFFSET
4808
4809 ; Save number to move (CX) in BX
4810 mov bx, cx
4811
4812 ; This section is for WRITES ------------------------------
4813 ; The Reload will be clipped if appropriate
4814
4815 @@RowLoop:
4816 ; Put 1 or 2 XBlocks
4817 rep movsb
4818
4819 ; Ready next iteration
4820 add di, bp ; Point DI to start of next line
4821
4822 ; Reload CX
4823 mov cx, bx
4824
4825 ; Are we done?
4826 dec dx
4827 jnz @@RowLoop ; No, then go and do another line
4828
4829
4830 ; ------ Now save the new area --------
4831 ; -- Do the reload
4832
4833 ; Load DS.
4834 ASSUME ds: @fardata
4835 mov ax, @fardata
4836 mov ds, ax ; Set DS to fardata segment
4837
4838 ; Set SI to start of rectangle on screen
4839 mov ax, [DLine_Offset] ; Get line size
4840 mov bx, [MLastY] ; Get Y into view
4841 mov di, bx ; Save in DI
4842 add bx, [ViewYLoc] ; Add start of view
4843 mul bx ; Find Y offset value. Place in AX
4844
4845 mov si, [MLastX] ; Find X offset value. Place in DI
4846 mov bp, si ; Save in BP for later
4847 add si, [ViewXLoc] ; Get start of view and add it
4848 shr si, 1
4849 shr si, 1
4850
4851 add si, ax ; Add X and Y offsets
4852 add si, [MousePage] ; Add in page offset
4853
4854 push si ; Save what will later be DI
4855
4856 ; See if we need to clip Second XBlock
4857 mov cx, 2 ; Assume 2 XBlocks to write
4858 mov dx, [ScreenSizeX] ; Get screen size
4859 sub dx, 4 ; Get 2nd to last XBlock
4860 cmp dx, bp ; BP from above.
4861 jae @@Continue3 ; Both blocks on reload
4862 dec cx ; Only one block on reload
4863
4864 @@Continue3:
4865 ; Set DX to number of lines to reload
4866 mov dx, 8 ; Assume 8 scan lines
4867 mov bx, di ; Get Y last and put in BX (from SI)
4868 mov ax, [MouseLines] ; Get Screen size Y and put in ax
4869 sub ax, 8 ; Subtract to make mimimum clip
4870
4871 cmp ax, bx ; Does it need clipping?
4872 ja @@Continue4 ; No, then go!
4873
4874 sub bx, ax ; Needs clipping! Find new DX
4875 sub dx, bx
4876
4877 @@Continue4:
4878 ; Save DX ( as number of lines to do ) for later
4879 push dx
4880
4881 ; Set BP to scan line dif.
4882 mov bp, [DLine_Offset]
4883 sub bp, cx
4884
4885 ; Get the Screen Seg and put it in DS
4886 mov ax, SCREEN_SEG
4887 mov ds, ax
4888
4889 ; Set destination
4890 mov di, MSAVEOFFSET
4891
4892 ; Save SI so we dont have to calc later
4893 mov ax, si
4894
4895 ; Save CX in BX
4896 mov bx, cx
4897
4898 ; This section is for the MOVE ------------------------------
4899
4900 @@RowLoop2:
4901 ; Do line
4902 rep movsb ; One or two XBlocks
4903
4904 ; Prep for next line
4905 add si, bp ; Point SI to start of next line
4906 mov cx, bx ; Restore CX
4907
4908 ; Are we done?
4909 dec dx
4910 jnz @@RowLoop2 ; No, then go and do another
4911
4912
4913 ; -------- Put the pointer in the new position ---------
4914
4915 ; Load DS.
4916 ASSUME ds: @fardata
4917 mov ax, @fardata
4918 mov ds, ax ; Set DS to fardata segment
4919
4920
4921 ; Find adjustment to source for alignment
4922 mov bx, [MLastX] ; Put X loc into cx
4923 add bx, [ViewXLoc] ; Add view start
4924 mov ax, 16 ; Alignment size ( 2XBlocks*8Scan )
4925
4926 and bx, 3 ; Mask all but 2 LSBs
4927 mul bx ; Find offset into alignments (Put in AX)
4928
4929 ; Put source into BX and add the alignment adj
4930 mov bx, MOUSEOFFSET
4931 add bx, ax ; Adjust BX
4932
4933
4934 ; Set DS:SI to mask area
4935 lds si, [MPointerMask]
4936
4937 ; Add adjustment for mask for alignment
4938 add si, ax ; AX as calculated above
4939
4940 ; Set ah to rows to do
4941 pop ax ; Was DX in the reload
4942 mov ah, al ; Move to upper nibble
4943
4944 ; Increment BP to account for no last inc
4945 inc bp
4946
4947 ; Pop the destination, prev si, from the stack
4948 pop di
4949
4950 ; Set up Map Mask
4951 mov al, 02h ; 02 is Map Mask
4952 mov dx, SC_INDEX
4953 out dx, al
4954 inc dx
4955
4956 ; Shift CX down to see if we need to write 2nd XBlock
4957 shr cx, 1
4958
4959 ; This section is for WRITES ------------------------------
4960 @@Rowloop3:
4961
4962
4963 ; Set mask for first XBlock write
4964 lodsb ; Get mask byte
4965 out dx, al ; Set map mask
4966
4967 ; Write the 1st XBlock
4968 mov al, [es:bx]
4969 mov [es:di], al
4970
4971 ; Load the next mask
4972 lodsb
4973
4974 ; Increment source pointers
4975 inc bx
4976
4977 ; If CX is zero, pointer is clipped. Don't put next XBlock
4978 jcxz @@Clipped
4979
4980 ; - Do another write
4981 ; Set the mask
4982 out dx, al ; Set map mask
4983
4984 ; Increment destination pointers
4985 inc di
4986
4987 ; Write the 2nd XBlock
4988 mov al, [es:bx]
4989 mov [es:di], al
4990
4991 @@Clipped:
4992 ; Adjust for next iteration
4993 add di, bp ; Point to next scan line
4994 inc bx
4995
4996 ; End of Rowloop.
4997 dec ah
4998 jnz @@Rowloop3
4999
5000 ; -- Done with screen
5001
5002 ; Restore the state of the bit mask and map mask
5003 ; Get Map Mask
5004 mov dx, SC_INDEX
5005 pop ax
5006 out dx, ax
5007
5008 ; Do the BIT MASK
5009 mov dx, GC_INDEX
5010 pop ax
5011 out dx, ax
5012
5013 ; -- See if we have to call the user's handler
5014
5015 ; Make ES the local data
5016 ASSUME es: @fardata
5017 mov ax, @fardata
5018 mov es, ax ; Set ES to fardata segment
5019
5020 ; Restore event masks
5021 pop ax
5022
5023 ; AND the mask with users mask
5024 and ax, [es:MUEventMask]
5025
5026 ; If zero then don't call user's
5027 je @@Done
5028
5029 ; Otherwise set up stack and call users routine
5030 push ax ; Push the event mask
5031
5032 mov ax, @data ; Load users DGROUP
5033 mov ds, ax
5034
5035 push [es:MLastY] ; Push Y location
5036
5037 push [es:MLastX] ; Push X location
5038
5039 call [es:Mouse_Hndlr_O] ; User pointer to call user handler
5040
5041 ; Clean stack after call
5042 add sp, 6
5043
5044
5045 ; -- DONE!!
5046
5047 @@Done:
5048 ; Make DS the local data
5049 ASSUME ds: @fardata
5050 mov ax, @fardata
5051 mov ds, ax ; Set DS to fardata segment
5052
5053 ; Unlock the handler
5054 mov ax, NOTLOCKM
5055 mov [LockHandler], ax
5056
5057 pop si di ds ; Pop mouses DS
5058 ret
5059
5060 ENDP _MEvent_Handler
5061
5062
5063 ; ------------------------ _XRegister_Mouse ---------------------------
5064 ; - This function sets up the use of the mouse
5065 ; - It returns FALSE (0) if it cannot
5066 ; -
5067 public _XRegister_Mouse
5068
5069 PROC _XRegister_Mouse
5070
5071 ARG MPOINT:DWORD, MMASK:DWORD, HANDLER:DWORD
5072
5073 push bp
5074 mov bp, sp ; Save Stack frame
5075
5076 ; Save registers
5077 push ds si di
5078
5079 ; First see if mouse is available
5080 mov ax, 0
5081 int 33h
5082
5083 cmp ax, 0FFFFh ; If ax is FFFFh then mouse is present
5084 je @@Cont
5085
5086 mov ax, MOUSE_NOTPRES
5087 jmp @@Done ; Otherwise, done
5088
5089 ; Mouse is present so continue
5090 @@Cont:
5091
5092 ; ----------- Upload mouse pointer ------------
5093
5094 ; Prep the stack for call to upload sprite
5095 les si, [MPOINT] ; Get the image offset
5096 push es
5097 push si
5098
5099 mov si, (64*4) ; Mouse sprite size
5100 push si
5101
5102 mov si, MOUSEOFFSET ; Mouse pointer site
5103 push si
5104
5105 ; Call upload sprite
5106 call _XUpload_Sprite
5107
5108 ; Fix the stack after call
5109 add sp, 8
5110
5111 ; ---- Done uploading mouse pointer
5112
5113
5114 ; Load DS.
5115 ASSUME ds: @fardata
5116 mov ax, @fardata
5117 mov ds, ax ; Set DS to fardata segment
5118
5119 ; Get the pointer mask address
5120 les si, [MMASK]
5121 mov [MPointerMask_O], si
5122 mov ax, es
5123 mov [MPointerMask_S], ax
5124
5125 ; Set up user handler
5126 les si, [HANDLER]
5127 mov [OFFSET Mouse_Hndlr_O], si
5128 mov ax, es
5129 mov [OFFSET Mouse_Hndlr_O+2], ax
5130
5131 ; !!DONE!!
5132 mov ax, MOUSE_PRESENT ; Return the mouse is present
5133
5134
5135 ; Set the new mickey counts
5136 mov ax, 000Fh ; Mouse driver routine
5137 mov cx, 8 ; Double horizontal
5138 mov dx, 8 ; Default vertical
5139 int 033h ; Call routine
5140
5141 @@Done:
5142 pop di si ds
5143
5144 pop bp ; Return state
5145 ret
5146
5147 ENDP _XRegister_Mouse
5148
5149
5150 ; ------------------------ _Mouse_Active ---------------------------
5151 ; - Makes the mouse active and starts display of the pointer
5152 ; - It will not process for the split screen crossover, but can decided
5153 ; - between split page and normal page
5154
5155 public _XMouse_Active
5156
5157 PROC _XMouse_Active
5158
5159 ARG EMASK:WORD, STARTX:WORD, STARTY:WORD, SPLIT:WORD
5160
5161 push bp
5162 mov bp, sp ; Save Stack frame
5163
5164 ; Save regs
5165 push ds si di
5166
5167 ; Load DS.
5168 ASSUME ds: @fardata
5169 mov ax, @fardata
5170 mov ds, ax ; Set DS to fardata segment
5171
5172 cld
5173
5174 ; Save the users mask
5175 mov cx, [EMASK] ; Get user's mask
5176 push cx
5177
5178 ; Which page ?
5179 mov cx, [SPLIT]
5180 jcxz @@NORMALPAGE
5181
5182 ; - Split Page
5183 mov ax, 0
5184 mov [MousePage], ax ; Set page to 0, split page
5185
5186 mov ax, [OriginalY] ; Get absolute size
5187 sub ax, [SplitY] ; Subtract split Y size
5188 mov [MouseLines], ax ; Save it as the number of lines
5189
5190 jmp @@CONTINUE
5191
5192 ; - Normal Page
5193 @@NORMALPAGE:
5194 mov ax, [Display_Page]
5195 mov [MousePage], ax ; Set to display page
5196
5197 mov ax, [ScreenSizeY] ;
5198 mov [MouseLines], ax ; Save it as the number of lines
5199
5200 ; Set mouse reporting limits
5201 @@CONTINUE:
5202 mov ax, 0007h ; Set X limits function
5203 mov cx, 0000h ; X minimum
5204 mov dx, [ScreenSizeX] ; X maximum
5205 dec dx
5206 shl dx, 1 ; Comp for oddity
5207 int 033h
5208
5209 mov ax, 0008h ; Set Y limits function
5210 mov cx, 0000h ; Y minimum
5211 mov dx, [MouseLines] ; Y maximum
5212 dec dx ; Adjust for pointer size
5213 int 033h
5214
5215 ; -- Set up VGA Registers
5216 ; Set all data from latches
5217 mov dx, GC_INDEX
5218 mov ax, 00000h + BIT_MASK ; Set all latch writes
5219 out dx, ax
5220
5221 ; Insure Map Mask is set to all planes
5222 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
5223 mov dx, SC_INDEX
5224 out dx, ax
5225
5226
5227 ; -- Set the mouse's position and display the pointer
5228
5229 ; Let the driver know where the mouse pointer is
5230 mov ax, 0004h ; Set mouse pointer position func
5231
5232 mov cx, [STARTX] ; Set X coord
5233 mov dx, [STARTY] ; Set Y coord
5234
5235 mov [MLastX], cx ; Save as last location
5236 mov [MLastY], dx
5237
5238 shl cx, 1 ; Comp
5239
5240 int 033h ; Call function
5241
5242 ; Return CX to actual coord
5243 shr cx, 1
5244
5245
5246
5247 ; Reload background & fake a mouse event to put the pointer
5248 ; on the screen the first time
5249
5250 ; -- Do the reload ------------------------------
5251
5252 ; Set SI to start of rectangle on screen
5253 mov ax, [DLine_Offset] ; Get line size
5254 mov bx, [MLastY] ; Get Y into view
5255 mov di, bx ; Save in DI
5256 add bx, [ViewYLoc] ; Add start of view
5257 mul bx ; Find Y offset value. Place in AX
5258
5259 mov si, [MLastX] ; Find X offset value. Place in DI
5260 mov bp, si ; Save in BP for later
5261 add si, [ViewXLoc] ; Get start of view and add it
5262 shr si, 1
5263 shr si, 1
5264
5265 add si, ax ; Add X and Y offsets
5266 add si, [MousePage] ; Add in page offset
5267
5268 ; See if we need to clip Second XBlock
5269 mov cx, 2 ; Assume 2 XBlocks to write
5270 mov dx, [ScreenSizeX] ; Get screen size
5271 sub dx, 4 ; Get 2nd to last XBlock
5272 cmp dx, bp ; BP from above.
5273 jge @@Continue3 ; Both blocks on reload
5274 dec cx ; Only one block on reload
5275
5276 @@Continue3:
5277 ; Set DX to number of lines to reload
5278 mov dx, 8 ; Assume 8 scan lines
5279 mov bx, di ; Get Y last and put in BX (from SI)
5280 mov ax, [MouseLines] ; Get Screen size Y and put in ax
5281 sub ax, 8 ; Subtract to make mimimum clip
5282
5283 cmp ax, bx ; Does it need clipping?
5284 jg @@Continue4 ; No, then go!
5285
5286 sub bx, ax ; Needs clipping! Find new DX
5287 sub dx, bx
5288
5289 @@Continue4:
5290
5291 ; Set BP to scan line dif.
5292 mov bp, [DLine_Offset]
5293 sub bp, cx
5294
5295 ; Get the Screen Seg and put it in DS and ES
5296 mov ax, SCREEN_SEG
5297 mov ds, ax
5298 mov es, ax
5299
5300 ; Set destination
5301 mov di, MSAVEOFFSET
5302
5303 ; Save CX in BX
5304 mov bx, cx
5305
5306 ; This section is for the MOVE ------------------------------
5307
5308 @@RowLoop3:
5309 ; Do line
5310 rep movsb ; One or two XBlocks
5311
5312 ; Prep for next line
5313 add si, bp ; Point SI to start of next line
5314 mov cx, bx ; Restore CX
5315
5316 ; Are we done?
5317 dec dx
5318 jnz @@RowLoop3 ; No, then go and do another
5319
5320
5321 ; - Done with Reload ---------------------------------------
5322
5323 ; Load DS.
5324 ASSUME ds: @fardata
5325 mov ax, @fardata
5326 mov ds, ax ; Set DS to fardata segment
5327
5328 ; Ensure the mouse is not locked
5329 mov ax, NOTLOCKM
5330 mov [LockHandler], ax
5331
5332 ; Fake a mouse event and call handler
5333 mov ax, 0001h ; Indicate a move
5334 mov bx, 0000h ; No info
5335 mov cx, [MLastX] ; X coord
5336 shl cx, 1 ; Double, that's how it is expected
5337 mov dx, [MLastY] ; Y coord
5338
5339 call _MEvent_Handler
5340
5341 ; Get the users event mask, save, and build our mask in cx
5342 pop cx ; Get the Mask back
5343 mov [MUEventMask], cx ; Save it
5344 or cx, 0001h ; Build ours
5345 ; We must make sure all moves are reported
5346
5347 ; Define XTile's handler and register it with the mouse driver
5348 mov ax, 0000Ch ; Function number
5349 mov dx, cs ; Get XTile's handler address
5350 mov es, dx
5351 mov dx, OFFSET _MEvent_Handler
5352
5353 int 033h ; Call the mouse driver
5354 ; !!DONE!!
5355
5356 pop di si ds ; Restore regs
5357
5358 pop bp ; Return state
5359 ret
5360
5361 ENDP _XMouse_Active
5362
5363 ; ------------------------ _XMouse_InActive ---------------------------
5364 ; - Turns off the mouse. Restores background to last known mouse position.
5365 ; -
5366 public _XMouse_InActive
5367
5368 PROC _XMouse_InActive
5369
5370 push bp
5371 mov bp, sp ; Save Stack frame
5372
5373 ; Save regs
5374 push ds si di
5375
5376 ; Register with mouse driver that we don't want any more reports
5377 mov ax, 0000Ch ; Function number
5378 mov cx, 00000h ; Clear flag
5379 mov dx, 00000h ; Get XTile's handler address
5380 mov es, dx
5381 mov dx, 00000h
5382
5383 int 033h ; Call the mouse driver
5384
5385 ; Load DS with local segment
5386 ASSUME ds: @fardata
5387 mov ax, @fardata
5388 mov ds, ax ; Set DS to fardata segment
5389
5390 ; Ensure the mouse is locked
5391 mov ax, LOCKM
5392 mov [LockHandler], ax
5393
5394 ; Clear the users mask
5395 mov cx, 0000h ; Set to no events
5396 mov [MUEventMask], cx ; Save it
5397
5398 ; ---- This is the restore
5399 cld
5400
5401 ; Set DI to start of rectangle on screen
5402 mov ax, [DLine_Offset] ; Get line size
5403 mov bx, [MLastY] ; Get Y into view
5404 mov si, bx ; Save in SI
5405 add bx, [ViewYLoc] ; Add start of view
5406 mul bx ; Find Y offset value. Place in AX
5407
5408 mov di, [MLastX] ; Find X offset value. Place in DI
5409 mov bp, di ; Save X in BP
5410 add di, [ViewXLoc] ; Get start of view and add it
5411 shr di, 1
5412 shr di, 1
5413
5414 add di, ax ; Add X and Y offsets
5415 add di, [MousePage] ; Add in page offset
5416
5417
5418 ; See if we need to clip Second XBlock
5419 mov cx, 2 ; Assume 2 XBlocks to write
5420 mov dx, [ScreenSizeX] ; Get screen size
5421 sub dx, 4 ; Get 2nd to last XBlock
5422 cmp dx, bp
5423 ja @@Continue ; Both blocks on reload
5424 dec cx ; Only one block on reload
5425
5426 @@Continue:
5427 ; Set all data from latches
5428 mov dx, GC_INDEX
5429 mov ax, 00000h + BIT_MASK ; Set all latch writes
5430 out dx, ax
5431
5432 ; Insure Map Mask is set to all planes
5433 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
5434 mov dx, SC_INDEX
5435 out dx, ax
5436
5437 ; Set DX to number of lines to display
5438 mov dx, 8 ; Assume 8 scan lines
5439 mov ax, [MouseLines] ; Get Screen size Y and put in ax
5440 sub ax, 8 ; Subtract to make mimimum clip
5441
5442 cmp ax, si ; Does it need clipping? (SI = last Y)
5443 ja @@ContinueC ; No, then go!
5444
5445 sub si, ax ; Needs clipping! Find new DX
5446 sub dx, si
5447
5448 @@ContinueC:
5449 ; Set BP to the distance from one scan line to next
5450 mov bp, [DLine_Offset]
5451 sub bp, cx ; # XBlocks per scan line
5452
5453 ; Get the Screen Seg and put it in DS and ES
5454 mov ax, SCREEN_SEG
5455 mov ds, ax
5456 mov es, ax
5457
5458 ; Set SI to source
5459 mov si, MSAVEOFFSET
5460
5461 ; Save number to move (CX) in BX
5462 mov bx, cx
5463
5464 ; This section is for WRITES ------------------------------
5465 ; The Reload will be clipped if appropriate
5466
5467 @@RowLoop:
5468 ; Put 1 or 2 XBlocks
5469 rep movsb
5470
5471 ; Ready next iteration
5472 add di, bp ; Point DI to start of next line
5473
5474 ; Reload CX
5475 mov cx, bx
5476
5477 ; Are we done?
5478 dec dx
5479 jnz @@RowLoop ; No, then go and do another line
5480
5481
5482 ; -- DONE!!
5483
5484 pop di si ds ; Restore regs
5485 pop bp ; Return state
5486 ret
5487
5488 ENDP _XMouse_InActive
5489
5490
5491 ; ------------------------ _XWhere_Mouse ---------------------------
5492 ; - Lets the user know the last known mouse location
5493 public _XWhere_Mouse
5494
5495 PROC _XWhere_Mouse FAR
5496
5497 ARG X:DWORD, Y:DWORD
5498
5499 push bp
5500 mov bp, sp ; Save Stack frame
5501 push ds si
5502
5503 ; Load DS.
5504 ASSUME ds: @fardata
5505 mov ax, @fardata
5506 mov ds, ax ; Set DS to fardata segment
5507
5508 ; Load pointer to X
5509 les si, [X]
5510
5511 ; Get value and save
5512 mov ax, [MLastX]
5513 mov [es:si], ax
5514
5515 ; Load pointer to Y
5516 les si, [Y]
5517
5518 ; Get value and save
5519 mov ax, [MLastY]
5520 mov [es:si], ax
5521
5522 ; !!DONE!!
5523 pop si ds
5524 pop bp ; Return state
5525 ret
5526
5527 ENDP _XWhere_Mouse
5528
5529
5530 ; ------------------------ _XReload_TileW ---------------------------
5531 ; - This will "reload" a tile from the write page to display memory
5532 ; - storeage
5533 ; -
5534 public _XReload_TileW
5535
5536 PROC _XReload_TileW
5537
5538 ARG STARTX:WORD, STARTY:WORD, XDELTA:WORD, YDELTA:WORD, OFFST:WORD
5539
5540 push bp
5541 mov bp, sp ; Save Stack frame
5542
5543 ; Save regs
5544 push ds si di
5545
5546 ; Load DS.
5547 ASSUME ds: @fardata
5548 mov ax, @fardata
5549 mov ds, ax ; Set DS to fardata segment
5550
5551 ; -- Do the reload
5552
5553 ; Set SI to start of rectangle on screen
5554 mov ax, [WLine_Offset] ; Get line size
5555 mul [STARTY] ; Find Y offset
5556
5557 mov si, [STARTX] ; Find X offset value. Place in DI
5558 shr si, 1
5559 shr si, 1
5560
5561 add si, ax ; Add X and Y offsets
5562 add si, [Write_Page] ; Add in page offset
5563
5564 ; Set destination
5565 mov di, [OFFST]
5566
5567 ; Set all data from latches
5568 mov dx, GC_INDEX
5569 mov ax, 00000h + BIT_MASK ; Set all latch writes
5570 out dx, ax
5571
5572 ; Insure Map Mask is set to all planes
5573 mov ax, 0F02h ; 0F sets all planes. 02 is Map Mask
5574 mov dx, SC_INDEX
5575 out dx, ax
5576
5577 ; Set CX to the number of XBlocks to move per scan line
5578 mov cx, [XDELTA]
5579 shr cx, 1
5580 shr cx, 1
5581
5582 ; Set BX to the number of scan lines to do
5583 mov bx, [YDELTA]
5584
5585 ; Set AX to scan line dif.
5586 mov ax, [WLine_Offset]
5587 sub ax, cx ; Scan size minus tile size
5588
5589 ; Get the Screen Seg and put it in ES
5590 mov dx, SCREEN_SEG
5591 mov es, dx
5592 mov ds, dx
5593
5594 ; Save number of XBlocks (CX) in DX
5595 mov dx, cx
5596
5597 ; This section is for the MOVE ------------------------------
5598 @@Rowloop:
5599
5600 rep movsb
5601
5602 ; Adjust for next iteration
5603 add si, ax ; Point DI to start of next line
5604
5605 ; Re-load CX
5606 mov cx, dx
5607
5608 ; End of Rowloop.
5609 dec bx
5610 jnz @@Rowloop
5611
5612
5613 ; DONE!!!
5614 pop di si ds
5615
5616 pop bp ; Return state
5617 ret
5618
5619 ENDP _XReload_TileW
5620
5621
5622 ; ------------------------ _XDownload_TileS ---------------------------
5623 ; - This will "download" a tile from a store in video mem to system memory
5624 ; - This will not correctly download from an active screen!
5625 ; - WARNING!!! Only download one segments worth at a time!!!!
5626 ; -
5627 public _XDownload_TileS
5628
5629 PROC _XDownload_TileS
5630
5631 ARG STOREA:WORD, SIZEX:WORD, SIZEY:WORD, DEST:DWORD
5632
5633 push bp
5634 mov bp, sp ; Save Stack frame
5635
5636 ; Save regs
5637 push ds si di
5638
5639 ; Set SI to the store position
5640 mov si, [STOREA]
5641 mov bx, si ; Save in BX
5642
5643 ; Load destination
5644 les di, [DEST]
5645
5646 ; Calculate bytes per plane and store in CX
5647 mov ax, [SIZEX]
5648 mul [SIZEY] ; Total bytes
5649 shr ax, 1
5650 shr ax, 1 ; Total XBlocks
5651 mov cx, ax
5652 mov bp, ax ; Save in BP
5653
5654 ; Set up store segment
5655 mov ax, SCREEN_SEG
5656 mov ds, ax
5657
5658 ; Set up graphics controller for read page
5659 mov dx, GC_INDEX
5660 mov al, 04h ; Read map register
5661 out dx, al
5662 inc dx
5663
5664 ; Set AL to plane access
5665 mov al, 00h
5666
5667 ; Set AH to planes left
5668 mov ah, 4
5669
5670 ; This section is for the move ------------------------------
5671 @@PlaneLoop:
5672
5673 ; Set MAP MASK
5674 out dx, al
5675
5676 ; Do the move
5677 shr cx, 1 ; Shift for word
5678 rep movsw
5679 adc cx, 0 ; Add 1(carry) to CX if dangling byte
5680 rep movsb ; Write dangle if there
5681
5682 ; Restore CX and source
5683 mov cx, bp
5684 mov si, bx
5685
5686 ; !!End of Plane loop.
5687 inc al
5688 dec ah
5689 jnz @@PlaneLoop
5690
5691 ; DONE!!!
5692 pop di si ds
5693 pop bp ; Return state
5694 ret
5695
5696 ENDP _XDownload_TileS
5697
5698
5699 ; ------------------------ _XDownload_TileP ---------------------------
5700 ; - This will "download" a tile from the write page in video mem to system memory
5701 ; - WARNING!!! Only download one segments worth at a time!!!!
5702 ; -
5703 public _XDownload_TileP
5704
5705 PROC _XDownload_TileP
5706
5707 ARG STARTX:WORD, STARTY:WORD, SIZEX:WORD, SIZEY:WORD, DEST:DWORD
5708
5709 push bp
5710 mov bp, sp ; Save Stack frame
5711
5712 ; Save regs
5713 push ds si di
5714
5715 ; Load DS.
5716 ASSUME ds: @fardata
5717 mov ax, @fardata
5718 mov ds, ax ; Set DS to fardata segment
5719
5720 ; Set SI to start of rectangle on screen
5721 mov ax, [WLine_Offset] ; Get line size
5722 mul [STARTY] ; Find Y offset
5723
5724 mov si, [STARTX] ; Find X offset value. Place in DI
5725 push si ; Save it
5726 shr si, 1
5727 shr si, 1
5728
5729 add si, ax ; Add X and Y offsets
5730 add si, [Write_Page] ; Add in page offset
5731 mov [STARTX], si ; Save SI
5732
5733 ; Load destination
5734 les di, [DEST]
5735
5736 ; Calculate bytes per line and store in CX
5737 mov cx, [SIZEX]
5738 shr cx, 1
5739 shr cx, 1 ; Total XBlocks
5740
5741 ; Set [STARTY] to scan line dif.
5742 mov ax, [WLine_Offset]
5743 sub ax, cx ; Scan size minus tile size
5744 mov [STARTY], ax
5745
5746 ; Set up store segment
5747 mov ax, SCREEN_SEG
5748 mov ds, ax
5749
5750 ; Set up graphics controller for read page
5751 mov dx, GC_INDEX
5752 mov al, 04h ; Read map register
5753 out dx, al
5754 inc dx
5755
5756 ; Set AL to plane access
5757 pop ax
5758 and al, 03h ; Mask out plane selecting bits
5759
5760 ; Save XBlocks per line (CL) in AH
5761 mov ah, cl
5762
5763 ; Set BX to number of lines to do
5764 mov bx, [SIZEY]
5765
5766 ; Set number of planes to do
5767 mov [SIZEX], 4
5768
5769 ; This section is for the move ------------------------------
5770 @@PlaneLoop:
5771
5772 ; Set READ MASK
5773 out dx, al
5774
5775 ; Steal dx to speed up add
5776 mov dx, [STARTY]
5777
5778 @@LineLoop:
5779 ; Do the move
5780 shr cx, 1 ; Shift for word
5781 rep movsw
5782 adc cx, 0 ; Add 1(carry) to CX if dangling byte
5783 rep movsb ; Write dangle if there
5784
5785 ; Adjust for next line
5786 add si, dx ; Next line
5787 mov cl, ah ; Reset items per line
5788
5789 ; End of work for this plane?
5790 dec bx
5791 jnz @@LineLoop
5792
5793 ; Transition back to plane 0?
5794 inc al
5795 cmp al, 4 ; Plane 3 is last valid
5796 jne @@Continue
5797 mov al, 0 ; Put back to planer 0
5798 inc [STARTX] ; Move to next XBlock
5799
5800 @@Continue:
5801 ; Adjust for another plane
5802 mov si, [STARTX] ; Reset source
5803 mov bx, [SIZEY] ; Reset number of lines
5804
5805 ; Next plane?
5806 mov dx, GC_INDEX+1 ; Restore DX
5807 dec [SIZEX]
5808 jnz @@PlaneLoop
5809
5810 ; DONE!!!
5811 pop di si ds
5812 pop bp ; Return state
5813 ret
5814
5815 ENDP _XDownload_TileP
5816
5817
5818 ; ------------------------ _XSet_Clip ---------------------------
5819 ; - This will set the clip boundries
5820 ; -
5821 public _XSet_Clip
5822
5823 PROC _XSet_Clip
5824
5825 ARG STARTX:WORD, STARTY:WORD, ENDX:WORD, ENDY:WORD
5826
5827 push bp
5828 mov bp, sp ; Save Stack frame
5829
5830 ; Save regs
5831 push ds
5832
5833 ; Load DS.
5834 ASSUME ds: @fardata
5835 mov ax, @fardata
5836 mov ds, ax ; Set DS to fardata segment
5837
5838 ; -- Load the values
5839 mov ax, [STARTX]
5840 mov [ClipSX], ax
5841 mov ax, [STARTY]
5842 mov [ClipSY], ax
5843 mov ax, [ENDX]
5844 mov [ClipEX], ax
5845 mov ax, [ENDY]
5846 mov [ClipEY], ax
5847
5848 ; DONE!!!
5849 pop ds
5850
5851 pop bp ; Return state
5852 ret
5853
5854 ENDP _XSet_Clip
5855
5856
5857 ENDS
5858
5859 END
|