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